aboutsummaryrefslogtreecommitdiff
path: root/sys/cmd/dvtm
diff options
context:
space:
mode:
Diffstat (limited to 'sys/cmd/dvtm')
-rw-r--r--sys/cmd/dvtm/LICENSE23
-rw-r--r--sys/cmd/dvtm/config.h208
-rw-r--r--sys/cmd/dvtm/dvtm-editor.c183
-rw-r--r--sys/cmd/dvtm/dvtm.c1810
-rw-r--r--sys/cmd/dvtm/dvtm.h233
-rw-r--r--sys/cmd/dvtm/dvtm.info136
-rw-r--r--sys/cmd/dvtm/hook.c346
-rw-r--r--sys/cmd/dvtm/rules.mk33
-rw-r--r--sys/cmd/dvtm/vt.c2112
-rw-r--r--sys/cmd/dvtm/vt.h48
10 files changed, 0 insertions, 5132 deletions
diff --git a/sys/cmd/dvtm/LICENSE b/sys/cmd/dvtm/LICENSE
deleted file mode 100644
index 8afe5bf..0000000
--- a/sys/cmd/dvtm/LICENSE
+++ /dev/null
@@ -1,23 +0,0 @@
-MIT/X Consortium License
-
- (c) 2006-2007 Anselm R. Garbe <garbeam at gmail dot com>
- (c) 2007-2016 Marc André Tanner <mat at brain-dump dot org>
- (c) 2020-???? Nicholas Noll <nbnoll at eml dot cc>
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
diff --git a/sys/cmd/dvtm/config.h b/sys/cmd/dvtm/config.h
deleted file mode 100644
index ec70596..0000000
--- a/sys/cmd/dvtm/config.h
+++ /dev/null
@@ -1,208 +0,0 @@
-#define VERSION "1.0"
-
-/* valid curses attributes are listed below they can be ORed
- *
- * A_NORMAL Normal display (no highlight)
- * A_STANDOUT Best highlighting mode of the terminal.
- * A_UNDERLINE Underlining
- * A_REVERSE Reverse video
- * A_BLINK Blinking
- * A_DIM Half bright
- * A_BOLD Extra bright or bold
- * A_PROTECT Protected mode
- * A_INVIS Invisible or blank mode
- */
-
-enum {
- DEFAULT,
- BLUE,
- GREEN,
-};
-
-static Color colors[] = {
- [DEFAULT] = { .fg = -1, .bg = -1, .fg256 = -1, .bg256 = -1, },
- [BLUE] = { .fg = COLOR_BLUE, .bg = -1, .fg256 = 68, .bg256 = -1, },
- [GREEN] = { .fg = COLOR_GREEN, .bg = -1, .fg256 = 65, .bg256 = -1, },
-};
-
-#define COLOR(c) COLOR_PAIR(colors[c].pair)
-/* curses attributes for the currently focused window */
-#define SELECTED_ATTR (COLOR(GREEN) | A_NORMAL)
-/* curses attributes for normal (not selected) windows */
-#define NORMAL_ATTR (COLOR(DEFAULT) | A_NORMAL)
-/* curses attributes for a window with pending urgent flag */
-#define URGENT_ATTR NORMAL_ATTR
-/* curses attributes for the status bar */
-#define BAR_ATTR (COLOR(GREEN) | A_NORMAL)
-/* characters for beginning and end of status bar message */
-#define BAR_BEGIN '['
-#define BAR_END ']'
-/* status bar (command line option -s) position */
-#define BAR_POS BAR_TOP /* BAR_BOTTOM, BAR_OFF */
-/* whether status bar should be hidden if only one client exists */
-#define BAR_AUTOHIDE false
-/* master width factor [0.1 .. 0.9] */
-#define MFACT 0.5
-/* number of clients in master area */
-#define NMASTER 1
-/* scroll back buffer size in lines */
-#define SCROLL_HISTORY 500
-/* printf format string for the tag in the status bar */
-#define TAG_SYMBOL "[%s]"
-/* curses attributes for the currently selected tags */
-#define TAG_SEL (COLOR(GREEN) | A_BOLD)
-/* curses attributes for not selected tags which contain no windows */
-#define TAG_NORMAL (COLOR(DEFAULT) | A_NORMAL)
-/* curses attributes for not selected tags which contain windows */
-#define TAG_OCCUPIED (COLOR(GREEN) | A_NORMAL)
-/* curses attributes for not selected tags which with urgent windows */
-#define TAG_URGENT (COLOR(GREEN) | A_NORMAL | A_BLINK)
-
-static const char tags[][8] = { "1", "2", "3", "4", "5" };
-
-/* by default the first layout entry is used */
-static Layout layouts[] = {
- { "[]=", tile },
- { "+++", grid },
- { "TTT", bstack },
- { "[ ]", fullscreen },
-};
-
-#define MOD ('`')
-#define TAGKEYS(KEY,TAG) \
- { { MOD, 'v', KEY, }, { view, { tags[TAG] } } }, \
- { { MOD, 't', KEY, }, { tag, { tags[TAG] } } }, \
- { { MOD, 'V', KEY, }, { toggleview, { tags[TAG] } } }, \
- { { MOD, 'T', KEY, }, { toggletag, { tags[TAG] } } },
-
-/* you can specifiy at most 3 arguments */
-static KeyBinding bindings[] = {
- { { MOD, 'c', }, { create, { NULL } } },
- { { MOD, 'C', }, { create, { NULL, NULL, "$CWD" } } },
- { { MOD, 'x', 'x', }, { killclient, { NULL } } },
- { { MOD, 'j', }, { focusnext, { NULL } } },
- { { MOD, 'J', }, { focusdown, { NULL } } },
- { { MOD, 'K', }, { focusup, { NULL } } },
- { { MOD, 'H', }, { focusleft, { NULL } } },
- { { MOD, 'L', }, { focusright, { NULL } } },
- { { MOD, 'k', }, { focusprev, { NULL } } },
- { { MOD, 'f', }, { setlayout, { "[]=" } } },
- { { MOD, 'g', }, { setlayout, { "+++" } } },
- { { MOD, 'b', }, { setlayout, { "TTT" } } },
- { { MOD, 'm', }, { setlayout, { "[ ]" } } },
- { { MOD, ' ', }, { setlayout, { NULL } } },
- { { MOD, 'i', }, { incnmaster, { "+1" } } },
- { { MOD, 'd', }, { incnmaster, { "-1" } } },
- { { MOD, 'h', }, { setmfact, { "-0.05" } } },
- { { MOD, 'l', }, { setmfact, { "+0.05" } } },
- { { MOD, '.', }, { toggleminimize, { NULL } } },
- { { MOD, 's', }, { togglebar, { NULL } } },
- { { MOD, 'S', }, { togglebarpos, { NULL } } },
- { { MOD, 'M', }, { togglemouse, { NULL } } },
- { { MOD, '\n', }, { zoom , { NULL } } },
- { { MOD, '\r', }, { zoom , { NULL } } },
- { { MOD, '1', }, { focusn, { "1" } } },
- { { MOD, '2', }, { focusn, { "2" } } },
- { { MOD, '3', }, { focusn, { "3" } } },
- { { MOD, '4', }, { focusn, { "4" } } },
- { { MOD, '5', }, { focusn, { "5" } } },
- { { MOD, '6', }, { focusn, { "6" } } },
- { { MOD, '7', }, { focusn, { "7" } } },
- { { MOD, '8', }, { focusn, { "8" } } },
- { { MOD, '9', }, { focusn, { "9" } } },
- { { MOD, '\t', }, { focuslast, { NULL } } },
- { { MOD, 'q', 'q', }, { quit, { NULL } } },
- { { MOD, 'a', }, { togglerunall, { NULL } } },
- { { MOD, CTRL('L'), }, { redraw, { NULL } } },
- { { MOD, 'r', }, { redraw, { NULL } } },
- { { MOD, 'e', }, { copymode, { "dvtm-editor" } } },
- { { MOD, 'E', }, { copymode, { "dvtm-pager" } } },
- { { MOD, '/', }, { copymode, { "dvtm-pager", "/" } } },
- { { MOD, 'p', }, { paste, { NULL } } },
- { { MOD, KEY_PPAGE, }, { scrollback, { "-1" } } },
- { { MOD, KEY_NPAGE, }, { scrollback, { "1" } } },
- { { MOD, '?', }, { create, { "man dvtm", "dvtm help" } } },
- { { MOD, MOD, }, { send, { (const char []){MOD, 0} } } },
- { { KEY_SPREVIOUS, }, { scrollback, { "-1" } } },
- { { KEY_SNEXT, }, { scrollback, { "1" } } },
- { { MOD, '0', }, { view, { NULL } } },
- { { MOD, KEY_F(1), }, { view, { tags[0] } } },
- { { MOD, KEY_F(2), }, { view, { tags[1] } } },
- { { MOD, KEY_F(3), }, { view, { tags[2] } } },
- { { MOD, KEY_F(4), }, { view, { tags[3] } } },
- { { MOD, KEY_F(5), }, { view, { tags[4] } } },
- { { MOD, 'v', '0' }, { view, { NULL } } },
- { { MOD, 'v', '\t', }, { viewprevtag, { NULL } } },
- { { MOD, 't', '0' }, { tag, { NULL } } },
- TAGKEYS( '1', 0)
- TAGKEYS( '2', 1)
- TAGKEYS( '3', 2)
- TAGKEYS( '4', 3)
- TAGKEYS( '5', 4)
-};
-
-static const ColorRule colorrules[] = {
- { "", A_NORMAL, &colors[DEFAULT] }, /* default */
-};
-
-/* possible values for the mouse buttons are listed below:
- *
- * BUTTON1_PRESSED mouse button 1 down
- * BUTTON1_RELEASED mouse button 1 up
- * BUTTON1_CLICKED mouse button 1 clicked
- * BUTTON1_DOUBLE_CLICKED mouse button 1 double clicked
- * BUTTON1_TRIPLE_CLICKED mouse button 1 triple clicked
- * BUTTON2_PRESSED mouse button 2 down
- * BUTTON2_RELEASED mouse button 2 up
- * BUTTON2_CLICKED mouse button 2 clicked
- * BUTTON2_DOUBLE_CLICKED mouse button 2 double clicked
- * BUTTON2_TRIPLE_CLICKED mouse button 2 triple clicked
- * BUTTON3_PRESSED mouse button 3 down
- * BUTTON3_RELEASED mouse button 3 up
- * BUTTON3_CLICKED mouse button 3 clicked
- * BUTTON3_DOUBLE_CLICKED mouse button 3 double clicked
- * BUTTON3_TRIPLE_CLICKED mouse button 3 triple clicked
- * BUTTON4_PRESSED mouse button 4 down
- * BUTTON4_RELEASED mouse button 4 up
- * BUTTON4_CLICKED mouse button 4 clicked
- * BUTTON4_DOUBLE_CLICKED mouse button 4 double clicked
- * BUTTON4_TRIPLE_CLICKED mouse button 4 triple clicked
- * BUTTON_SHIFT shift was down during button state change
- * BUTTON_CTRL control was down during button state change
- * BUTTON_ALT alt was down during button state change
- * ALL_MOUSE_EVENTS report all button state changes
- * REPORT_MOUSE_POSITION report mouse movement
- */
-
-#ifdef NCURSES_MOUSE_VERSION
-# define CONFIG_MOUSE /* compile in mouse support if we build against ncurses */
-#endif
-
-#define ENABLE_MOUSE true /* whether to enable mouse events by default */
-
-#ifdef CONFIG_MOUSE
-static Button buttons[] = {
- { BUTTON1_CLICKED, { mouse_focus, { NULL } } },
- { BUTTON1_DOUBLE_CLICKED, { mouse_fullscreen, { "[ ]" } } },
- { BUTTON2_CLICKED, { mouse_zoom, { NULL } } },
- { BUTTON3_CLICKED, { mouse_minimize, { NULL } } },
-};
-#endif /* CONFIG_MOUSE */
-
-static Cmd commands[] = {
- /* create [cmd]: create a new window, run `cmd` in the shell if specified */
- { "create", { create, { NULL } } },
- /* focus <win_id>: focus the window whose `DVTM_WINDOW_ID` is `win_id` */
- { "focus", { focusid, { NULL } } },
- /* tag <win_id> <tag> [tag ...]: add +tag, remove -tag or set tag of the window with the given identifier */
- { "tag", { tagid, { NULL } } },
-};
-
-/* gets executed when dvtm is started */
-static Action actions[] = {
- { create, { NULL } },
-};
-
-static char const * const keytable[] = {
- /* add your custom key escape sequences */
-};
diff --git a/sys/cmd/dvtm/dvtm-editor.c b/sys/cmd/dvtm/dvtm-editor.c
deleted file mode 100644
index e8685e9..0000000
--- a/sys/cmd/dvtm/dvtm-editor.c
+++ /dev/null
@@ -1,183 +0,0 @@
-/* Invoke $EDITOR as a filter.
- *
- * Copyright (c) 2016 Dmitry Bogatov <KAction@gnu.org>
- * Copyright (c) 2017 Marc André Tanner <mat@brain-dump.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-static
-void
-error(const char *msg, ...) {
- va_list ap;
- va_start(ap, msg);
- vfprintf(stderr, msg, ap);
- va_end(ap);
- if (errno)
- fprintf(stderr, ": %s", strerror(errno));
- fprintf(stderr, "\n");
-}
-
-int
-main(int argc, char *argv[])
-{
- int exit_status = EXIT_FAILURE, tmp_write = -1;
-
- const char *editor = getenv("DVTM_EDITOR");
- if (!editor)
- editor = getenv("VISUAL");
- if (!editor)
- editor = getenv("EDITOR");
- if (!editor)
- editor = "vi";
-
- char tempname[] = "/tmp/dvtm-editor.XXXXXX";
- if ((tmp_write = mkstemp(tempname)) == -1) {
- error("failed to open temporary file `%s'", tempname);
- goto err;
- }
-
- /* POSIX does not mandates modes of temporary file. */
- if (fchmod(tmp_write, 0600) == -1) {
- error("failed to change mode of temporary file `%s'", tempname);
- goto err;
- }
-
- char buffer[2048];
- ssize_t bytes;
- while ((bytes = read(STDIN_FILENO, buffer, sizeof(buffer))) > 0) {
- do {
- ssize_t written = write(tmp_write, buffer, bytes);
- if (written == -1) {
- error("failed to write data to temporary file `%s'",
- tempname);
- goto err;
- }
- bytes -= written;
- } while (bytes > 0);
- }
-
- if (fsync(tmp_write) == -1) {
- error("failed to fsync temporary file `%s'", tempname);
- goto err;
- }
-
- struct stat stat_before;
- if (fstat(tmp_write, &stat_before) == -1) {
- error("failed to stat newly created temporary file `%s'", tempname);
- goto err;
- }
-
- if (close(tmp_write) == -1) {
- error("failed to close temporary file `%s'", tempname);
- goto err;
- }
-
- pid_t pid = fork();
- if (pid == -1) {
- error("failed to fork editor process");
- goto err;
- } else if (pid == 0) {
- int tty = open("/dev/tty", O_RDWR);
- if (tty == -1) {
- error("failed to open /dev/tty");
- _exit(1);
- }
-
- if (dup2(tty, STDIN_FILENO) == -1) {
- error("failed to set tty as stdin");
- _exit(1);
- }
-
- if (dup2(tty, STDOUT_FILENO) == -1) {
- error("failed to set tty as stdout");
- _exit(1);
- }
-
- if (dup2(tty, STDERR_FILENO) == -1) {
- error("failed to set tty as stderr");
- _exit(1);
- }
-
- close(tty);
-
- const char *editor_argv[argc+2];
- editor_argv[0] = editor;
- for (int i = 1; i < argc; i++)
- editor_argv[i] = argv[i];
- editor_argv[argc] = tempname;
- editor_argv[argc+1] = NULL;
-
- execvp(editor, (char* const*)editor_argv);
- error("failed to exec editor process `%s'", editor);
- _exit(127);
- }
-
- int status;
- if (waitpid(pid, &status, 0) == -1) {
- error("waitpid failed");
- goto err;
- }
- if (!WIFEXITED(status)) {
- error("editor invocation failed");
- goto err;
- }
- if ((status = WEXITSTATUS(status)) != 0) {
- error("editor terminated with exit status: %d", status);
- goto err;
- }
-
- int tmp_read = open(tempname, O_RDONLY);
- if (tmp_read == -1) {
- error("failed to open for reading of edited temporary file `%s'",
- tempname);
- goto err;
- }
-
- struct stat stat_after;
- if (fstat(tmp_read, &stat_after) == -1) {
- error("failed to stat edited temporary file `%s'", tempname);
- goto err;
- }
-
- if (stat_before.st_mtime == stat_after.st_mtime)
- goto ok; /* no modifications */
-
- while ((bytes = read(tmp_read, buffer, sizeof(buffer))) > 0) {
- do {
- ssize_t written = write(STDOUT_FILENO, buffer, bytes);
- if (written == -1) {
- error("failed to write data to stdout");
- goto err;
- }
- bytes -= written;
- } while (bytes > 0);
- }
-
-ok:
- exit_status = EXIT_SUCCESS;
-err:
- if (tmp_write != -1)
- unlink(tempname);
- return exit_status;
-}
diff --git a/sys/cmd/dvtm/dvtm.c b/sys/cmd/dvtm/dvtm.c
deleted file mode 100644
index 3c0f52b..0000000
--- a/sys/cmd/dvtm/dvtm.c
+++ /dev/null
@@ -1,1810 +0,0 @@
-#include "dvtm.h"
-
-/* global variables */
-uint waw, wah, wax, way;
-Client *clients = nil;
-char *title;
-const char *dvtm_name = "dvtm";
-Screen screen = { .mfact = MFACT, .nmaster = NMASTER, .history = SCROLL_HISTORY };
-static Client *stack = nil;
-static Client *sel = nil;
-static Client *lastsel = nil;
-static Client *msel = nil;
-
-static uint seltags;
-static uint tagset[2] = { 1, 1 };
-static bool mouse_events_enabled = ENABLE_MOUSE;
-static Layout *layout = layouts;
-
-static StatusBar bar = { .fd = -1, .lastpos = BAR_POS, .pos = BAR_POS, .autohide = BAR_AUTOHIDE, .h = 1 };
-static CmdFifo cmdfifo = { .fd = -1 };
-static const char *shell;
-static Register copyreg;
-static volatile sig_atomic_t running = true;
-static bool runinall = false;
-
-/* function implementations */
-
-static
-void
-eprint(const char *errstr, ...)
-{
- va_list ap;
- va_start(ap, errstr);
- vfprintf(stderr, errstr, ap);
- va_end(ap);
-}
-
-static
-void
-fatal(const char *errstr, ...)
-{
- va_list ap;
- va_start(ap, errstr);
- vfprintf(stderr, errstr, ap);
- va_end(ap);
- exit(EXIT_FAILURE);
-}
-
-static
-bool
-isarrange(void (*func)())
-{
- return func == layout->arrange;
-}
-
-static
-bool
-isvisible(Client *c)
-{
- return c->tags & tagset[seltags];
-}
-
-static
-bool
-is_content_visible(Client *c)
-{
- if (!c)
- return false;
- if (isarrange(fullscreen))
- return sel == c;
- return isvisible(c) && !c->minimized;
-}
-
-Client*
-nextvisible(Client *c)
-{
- for (; c && !isvisible(c); c = c->next);
- return c;
-}
-
-static
-void
-updatebarpos(void)
-{
- bar.y = 0;
- wax = 0;
- way = 0;
- wah = screen.h;
- waw = screen.w;
- if (bar.pos == BAR_TOP) {
- wah -= bar.h;
- way += bar.h;
- } else if (bar.pos == BAR_BOTTOM) {
- wah -= bar.h;
- bar.y = wah;
- }
-}
-
-static
-void
-hidebar(void)
-{
- if (bar.pos != BAR_OFF) {
- bar.lastpos = bar.pos;
- bar.pos = BAR_OFF;
- }
-}
-
-static
-void
-showbar(void)
-{
- if (bar.pos == BAR_OFF)
- bar.pos = bar.lastpos;
-}
-
-static
-void
-drawbar(void)
-{
- int sx, sy, x, y, width;
- uint occupied = 0, urgent = 0;
- if (bar.pos == BAR_OFF)
- return;
-
- for (Client *c = clients; c; c = c->next) {
- occupied |= c->tags;
- if (c->urgent)
- urgent |= c->tags;
- }
-
- getyx(stdscr, sy, sx);
- attrset(BAR_ATTR);
- move(bar.y, 0);
-
- for (uint i = 0; i < arrlen(tags); i++){
- if (tagset[seltags] & (1 << i))
- attrset(TAG_SEL);
- else if (urgent & (1 << i))
- attrset(TAG_URGENT);
- else if (occupied & (1 << i))
- attrset(TAG_OCCUPIED);
- else
- attrset(TAG_NORMAL);
- printw(TAG_SYMBOL, tags[i]);
- }
-
- attrset(runinall ? TAG_SEL : TAG_NORMAL);
- addstr(layout->symbol);
- attrset(TAG_NORMAL);
-
- getyx(stdscr, y, x);
- (void)y;
- int maxwidth = screen.w - x - 2;
-
- addch(BAR_BEGIN);
- attrset(BAR_ATTR);
-
- wchar_t wbuf[sizeof bar.text];
- size_t numchars = mbstowcs(wbuf, bar.text, sizeof bar.text);
-
- if (numchars != (size_t)-1 && (width = wcswidth(wbuf, maxwidth)) != -1) {
- int pos;
- for (pos = 0; pos + width < maxwidth; pos++)
- addch(' ');
-
- for (size_t i = 0; i < numchars; i++) {
- pos += wcwidth(wbuf[i]);
- if (pos > maxwidth)
- break;
- addnwstr(wbuf+i, 1);
- }
-
- clrtoeol();
- }
-
- attrset(TAG_NORMAL);
- mvaddch(bar.y, screen.w - 1, BAR_END);
- attrset(NORMAL_ATTR);
- move(sy, sx);
- wnoutrefresh(stdscr);
-}
-
-static
-int
-show_border(void) {
- return (bar.pos != BAR_OFF) || (clients && clients->next);
-}
-
-static void
-draw_border(Client *c) {
- char t = '\0';
- int x, y, maxlen, attrs = NORMAL_ATTR;
-
- if (!show_border())
- return;
- if (sel != c && c->urgent)
- attrs = URGENT_ATTR;
- if (sel == c || (runinall && !c->minimized))
- attrs = SELECTED_ATTR;
-
- wattrset(c->window, attrs);
- getyx(c->window, y, x);
- mvwhline(c->window, 0, 0, ACS_HLINE, c->w);
- maxlen = c->w - 10;
- if (maxlen < 0)
- maxlen = 0;
- if ((size_t)maxlen < sizeof(c->title)) {
- t = c->title[maxlen];
- c->title[maxlen] = '\0';
- }
-
- mvwprintw(c->window, 0, 2, "[%s%s#%d]",
- *c->title ? c->title : "",
- *c->title ? " | " : "",
- c->order);
- if (t)
- c->title[maxlen] = t;
- wmove(c->window, y, x);
-}
-
-static void
-draw_content(Client *c) {
- vt_draw(c->term, c->window, c->has_title_line, 0);
-}
-
-static void
-draw(Client *c) {
- if (is_content_visible(c)) {
- redrawwin(c->window);
- draw_content(c);
- }
- if (!isarrange(fullscreen) || sel == c)
- draw_border(c);
- wnoutrefresh(c->window);
-}
-
-static void
-draw_all(void) {
- if (!nextvisible(clients)) {
- sel = nil;
- curs_set(0);
- erase();
- drawbar();
- doupdate();
- return;
- }
-
- if (!isarrange(fullscreen)) {
- for (Client *c = nextvisible(clients); c; c = nextvisible(c->next)) {
- if (c != sel)
- draw(c);
- }
- }
- /* as a last step the selected window is redrawn,
- * this has the effect that the cursor position is
- * accurate
- */
- if (sel)
- draw(sel);
-}
-
-static void
-arrange(void) {
- uint m = 0, n = 0;
- for (Client *c = nextvisible(clients); c; c = nextvisible(c->next)) {
- c->order = ++n;
- if (c->minimized)
- m++;
- }
- erase();
- attrset(NORMAL_ATTR);
- if (bar.fd == -1 && bar.autohide) {
- if ((!clients || !clients->next) && n == 1)
- hidebar();
- else
- showbar();
- updatebarpos();
- }
- if (m && !isarrange(fullscreen))
- wah--;
- layout->arrange();
- if (m && !isarrange(fullscreen)) {
- uint i = 0, nw = waw / m, nx = wax;
- for (Client *c = nextvisible(clients); c; c = nextvisible(c->next)) {
- if (c->minimized) {
- resize(c, nx, way+wah, ++i == m ? waw - nx : nw, 1);
- nx += nw;
- }
- }
- wah++;
- }
- focus(nil);
- wnoutrefresh(stdscr);
- drawbar();
- draw_all();
-}
-
-static void
-attach(Client *c) {
- if (clients)
- clients->prev = c;
- c->next = clients;
- c->prev = nil;
- clients = c;
- for (int o = 1; c; c = nextvisible(c->next), o++)
- c->order = o;
-}
-
-static void
-attachafter(Client *c, Client *a) { /* attach c after a */
- if (c == a)
- return;
- if (!a)
- for (a = clients; a && a->next; a = a->next);
-
- if (a) {
- if (a->next)
- a->next->prev = c;
- c->next = a->next;
- c->prev = a;
- a->next = c;
- for (int o = a->order; c; c = nextvisible(c->next))
- c->order = ++o;
- }
-}
-
-static void
-attachstack(Client *c) {
- c->snext = stack;
- stack = c;
-}
-
-static void
-detach(Client *c) {
- Client *d;
- if (c->prev)
- c->prev->next = c->next;
- if (c->next) {
- c->next->prev = c->prev;
- for (d = nextvisible(c->next); d; d = nextvisible(d->next))
- --d->order;
- }
- if (c == clients)
- clients = c->next;
- c->next = c->prev = nil;
-}
-
-static void
-settitle(Client *c) {
- char *term, *t = title;
- if (!t && sel == c && *c->title)
- t = c->title;
- if (t && (term = getenv("TERM")) && !strstr(term, "linux")) {
- printf("\033]0;%s\007", t);
- fflush(stdout);
- }
-}
-
-static void
-detachstack(Client *c) {
- Client **tc;
- for (tc = &stack; *tc && *tc != c; tc = &(*tc)->snext);
- *tc = c->snext;
-}
-
-void
-focus(Client *c) {
- if (!c)
- for (c = stack; c && !isvisible(c); c = c->snext);
- if (sel == c)
- return;
- lastsel = sel;
- sel = c;
- if (lastsel) {
- lastsel->urgent = false;
- if (!isarrange(fullscreen)) {
- draw_border(lastsel);
- wnoutrefresh(lastsel->window);
- }
- }
-
- if (c) {
- detachstack(c);
- attachstack(c);
- settitle(c);
- c->urgent = false;
- if (isarrange(fullscreen)) {
- draw(c);
- } else {
- draw_border(c);
- wnoutrefresh(c->window);
- }
- }
- curs_set(c && !c->minimized && vt_cursor_visible(c->term));
-}
-
-static
-void
-applycolorrules(Client *c)
-{
- const ColorRule *r = colorrules;
- int fg = r->color->fg, bg = r->color->bg;
- attr_t attrs = r->attrs;
-
- for (uint i = 1; i < arrlen(colorrules); i++) {
- r = &colorrules[i];
- if (strstr(c->title, r->title)) {
- attrs = r->attrs;
- fg = r->color->fg;
- bg = r->color->bg;
- break;
- }
- }
-
- vt_default_colors_set(c->term, attrs, fg, bg);
-}
-
-static
-void
-term_title_handler(Vt *term, const char *title) {
- Client *c = (Client *)vt_data_get(term);
- if (title)
- strncpy(c->title, title, sizeof(c->title) - 1);
- c->title[title ? sizeof(c->title) - 1 : 0] = '\0';
- settitle(c);
- if (!isarrange(fullscreen) || sel == c)
- draw_border(c);
- applycolorrules(c);
-}
-
-static
-void
-term_urgent_handler(Vt *term) {
- Client *c = (Client *)vt_data_get(term);
- c->urgent = true;
- printf("\a");
- fflush(stdout);
- drawbar();
- if (!isarrange(fullscreen) && sel != c && isvisible(c))
- draw_border(c);
-}
-
-static
-void
-move_client(Client *c, int x, int y)
-{
- if (c->x == x && c->y == y)
- return;
- debug("moving, x: %d y: %d\n", x, y);
- if (mvwin(c->window, y, x) == ERR) {
- eprint("error moving, x: %d y: %d\n", x, y);
- } else {
- c->x = x;
- c->y = y;
- }
-}
-
-static
-void
-resize_client(Client *c, int w, int h)
-{
- bool has_title_line = show_border();
- bool resize_window = c->w != w || c->h != h;
- if (resize_window) {
- debug("resizing, w: %d h: %d\n", w, h);
- if (wresize(c->window, h, w) == ERR) {
- eprint("error resizing, w: %d h: %d\n", w, h);
- } else {
- c->w = w;
- c->h = h;
- }
- }
- if (resize_window || c->has_title_line != has_title_line) {
- c->has_title_line = has_title_line;
- vt_resize(c->app, h - has_title_line, w);
- if (c->editor)
- vt_resize(c->editor, h - has_title_line, w);
- }
-}
-
-void
-resize(Client *c, int x, int y, int w, int h)
-{
- resize_client(c, w, h);
- move_client(c, x, y);
-}
-
-static
-Client*
-get_client_by_coord(uint x, unsigned int y) {
- if (y < way || y >= way+wah)
- return nil;
- if (isarrange(fullscreen))
- return sel;
- for (Client *c = nextvisible(clients); c; c = nextvisible(c->next)) {
- if (x >= c->x && x < c->x + c->w && y >= c->y && y < c->y + c->h) {
- debug("mouse event, x: %d y: %d client: %d\n", x, y, c->order);
- return c;
- }
- }
- return nil;
-}
-
-static
-void
-sigchld_handler(int sig) {
- int errsv = errno;
- int status;
- pid_t pid;
-
- while ((pid = waitpid(-1, &status, WNOHANG)) != 0) {
- if (pid == -1) {
- if (errno == ECHILD) {
- /* no more child processes */
- break;
- }
- eprint("waitpid: %s\n", strerror(errno));
- break;
- }
-
- debug("child with pid %d died\n", pid);
-
- for (Client *c = clients; c; c = c->next) {
- if (c->pid == pid) {
- c->died = true;
- break;
- }
- if (c->editor && vt_pid_get(c->editor) == pid) {
- c->editor_died = true;
- break;
- }
- }
- }
-
- errno = errsv;
-}
-
-static
-void
-sigwinch_handler(int sig) {
- screen.need_resize = true;
-}
-
-static
-void
-sigterm_handler(int sig) {
- running = false;
-}
-
-static
-void
-resize_screen(void)
-{
- struct winsize ws;
-
- if (ioctl(0, TIOCGWINSZ, &ws) == -1) {
- getmaxyx(stdscr, screen.h, screen.w);
- } else {
- screen.w = ws.ws_col;
- screen.h = ws.ws_row;
- }
-
- debug("resize_screen(), w: %d h: %d\n", screen.w, screen.h);
-
- resizeterm(screen.h, screen.w);
- wresize(stdscr, screen.h, screen.w);
- updatebarpos();
- clear();
- arrange();
-}
-
-static
-KeyBinding*
-keybinding(KeyCombo keys, uint keycount)
-{
- for (uint b = 0; b < arrlen(bindings); b++) {
- for (uint k = 0; k < keycount; k++) {
- if (keys[k] != bindings[b].keys[k])
- break;
- if (k == keycount - 1)
- return &bindings[b];
- }
- }
- return nil;
-}
-
-static
-uint
-bitoftag(const char *tag)
-{
- uint i;
- if (!tag)
- return ~0;
- for (i = 0; (i < arrlen(tags)) && strcmp(tags[i], tag); i++);
- return (i < arrlen(tags)) ? (1 << i) : 0;
-}
-
-static void
-tagschanged() {
- bool allminimized = true;
- for (Client *c = nextvisible(clients); c; c = nextvisible(c->next)) {
- if (!c->minimized) {
- allminimized = false;
- break;
- }
- }
- if (allminimized && nextvisible(clients)) {
- focus(nil);
- toggleminimize(nil);
- }
- arrange();
-}
-
-void
-tag(const char *args[])
-{
- if (!sel)
- return;
- sel->tags = bitoftag(args[0]) & TAGMASK;
- tagschanged();
-}
-
-void
-tagid(const char *args[])
-{
- if (!args[0] || !args[1])
- return;
-
- const int win_id = atoi(args[0]);
- for (Client *c = clients; c; c = c->next) {
- if (c->id == win_id) {
- uint ntags = c->tags;
- for (uint i = 1; i < MAX_ARGS && args[i]; i++) {
- if (args[i][0] == '+')
- ntags |= bitoftag(args[i]+1);
- else if (args[i][0] == '-')
- ntags &= ~bitoftag(args[i]+1);
- else
- ntags = bitoftag(args[i]);
- }
- ntags &= TAGMASK;
- if (ntags) {
- c->tags = ntags;
- tagschanged();
- }
- return;
- }
- }
-}
-
-void
-toggletag(const char *args[])
-{
- if (!sel)
- return;
- uint newtags = sel->tags ^ (bitoftag(args[0]) & TAGMASK);
- if (newtags) {
- sel->tags = newtags;
- tagschanged();
- }
-}
-
-void
-toggleview(const char *args[])
-{
- uint newtagset = tagset[seltags] ^ (bitoftag(args[0]) & TAGMASK);
- if (newtagset) {
- tagset[seltags] = newtagset;
- tagschanged();
- }
-}
-
-void
-view(const char *args[])
-{
- uint newtagset = bitoftag(args[0]) & TAGMASK;
- if (tagset[seltags] != newtagset && newtagset) {
- seltags ^= 1; /* toggle sel tagset */
- tagset[seltags] = newtagset;
- tagschanged();
- }
-}
-
-void
-viewprevtag(const char *args[])
-{
- seltags ^= 1;
- tagschanged();
-}
-
-static
-void
-keypress(int code)
-{
- int key = -1;
- uint len = 1;
- char buf[8] = { '\e' };
-
- if (code == '\e') {
- /* pass characters following escape to the underlying app */
- nodelay(stdscr, TRUE);
- for (int t; len < sizeof(buf) && (t = getch()) != ERR; len++) {
- if (t > 255) {
- key = t;
- break;
- }
- buf[len] = t;
- }
- nodelay(stdscr, FALSE);
- }
-
- for (Client *c = runinall ? nextvisible(clients) : sel; c; c = nextvisible(c->next)) {
- if (is_content_visible(c)) {
- c->urgent = false;
- if (code == '\e')
- vt_write(c->term, buf, len);
- else
- vt_keypress(c->term, code);
-
- if (key != -1)
- vt_keypress(c->term, key);
- }
- if (!runinall)
- break;
- }
-}
-
-static
-void
-mouse_setup(void)
-{
-#ifdef CONFIG_MOUSE
- mmask_t mask = 0;
-
- if (mouse_events_enabled) {
- mask = BUTTON1_CLICKED | BUTTON2_CLICKED;
- for (uint i = 0; i < arrlen(buttons); i++)
- mask |= buttons[i].mask;
- }
- mousemask(mask, nil);
-#endif /* CONFIG_MOUSE */
-}
-
-static bool
-checkshell(const char *shell) {
- if (shell == nil || *shell == '\0' || *shell != '/')
- return false;
- if (!strcmp(strrchr(shell, '/')+1, dvtm_name))
- return false;
- if (access(shell, X_OK))
- return false;
- return true;
-}
-
-static const char *
-getshell(void) {
- const char *shell = getenv("SHELL");
- struct passwd *pw;
-
- if (checkshell(shell))
- return shell;
- if ((pw = getpwuid(getuid())) && checkshell(pw->pw_shell))
- return pw->pw_shell;
- return "/bin/sh";
-}
-
-static
-void
-setup(void)
-{
- shell = getshell();
- setlocale(LC_CTYPE, "");
- initscr();
- start_color();
- noecho();
- nonl();
- keypad(stdscr, TRUE);
- mouse_setup();
- raw();
- vt_init();
- vt_keytable_set(keytable, arrlen(keytable));
- for (uint i = 0; i < arrlen(colors); i++) {
- if (COLORS == 256) {
- if (colors[i].fg256)
- colors[i].fg = colors[i].fg256;
- if (colors[i].bg256)
- colors[i].bg = colors[i].bg256;
- }
- colors[i].pair = vt_color_reserve(colors[i].fg, colors[i].bg);
- }
- resize_screen();
-
- struct sigaction sa;
- memset(&sa, 0, sizeof sa);
- sa.sa_flags = 0;
- sigemptyset(&sa.sa_mask);
- sa.sa_handler = sigwinch_handler;
- sigaction(SIGWINCH, &sa, nil);
- sa.sa_handler = sigchld_handler;
- sigaction(SIGCHLD, &sa, nil);
- sa.sa_handler = sigterm_handler;
- sigaction(SIGTERM, &sa, nil);
- sa.sa_handler = SIG_IGN;
- sigaction(SIGPIPE, &sa, nil);
-}
-
-static
-void
-destroy(Client *c) {
- if (sel == c)
- focusnextnm(nil);
- detach(c);
- detachstack(c);
- if (sel == c) {
- Client *next = nextvisible(clients);
- if (next) {
- focus(next);
- toggleminimize(nil);
- } else {
- sel = nil;
- }
- }
- if (lastsel == c)
- lastsel = nil;
- werase(c->window);
- wnoutrefresh(c->window);
- vt_destroy(c->term);
- delwin(c->window);
- if (!clients && arrlen(actions)) {
- if (!strcmp(c->cmd, shell))
- quit(nil);
- else
- create(nil);
- }
- free(c);
- arrange();
-}
-
-static
-void
-cleanup(void) {
- while (clients)
- destroy(clients);
- vt_shutdown();
- endwin();
- free(copyreg.data);
- if (bar.fd > 0)
- close(bar.fd);
- if (bar.file)
- unlink(bar.file);
- if (cmdfifo.fd > 0)
- close(cmdfifo.fd);
- if (cmdfifo.file)
- unlink(cmdfifo.file);
-}
-
-static
-char *getcwd_by_pid(Client *c) {
- if (!c)
- return nil;
- char buf[32];
- snprintf(buf, sizeof buf, "/proc/%d/cwd", c->pid);
- return realpath(buf, nil);
-}
-
-void
-create(const char *args[])
-{
- const char *pargs[4] = { shell, nil };
- char buf[8], *cwd = nil;
- const char *env[] = {
- "DVTM_WINDOW_ID", buf,
- nil
- };
-
- if (args && args[0]) {
- pargs[1] = "-c";
- pargs[2] = args[0];
- pargs[3] = nil;
- }
- Client *c = calloc(1, sizeof(Client));
- if (!c)
- return;
- c->tags = tagset[seltags];
- c->id = ++cmdfifo.id;
- snprintf(buf, sizeof buf, "%d", c->id);
-
- if (!(c->window = newwin(wah, waw, way, wax))) {
- free(c);
- return;
- }
-
- c->term = c->app = vt_create(screen.h, screen.w, screen.history);
- if (!c->term) {
- delwin(c->window);
- free(c);
- return;
- }
-
- if (args && args[0]) {
- c->cmd = args[0];
- char name[PATH_MAX];
- strncpy(name, args[0], sizeof(name));
- name[sizeof(name)-1] = '\0';
- strncpy(c->title, basename(name), sizeof(c->title));
- } else {
- c->cmd = shell;
- }
-
- if (args && args[1])
- strncpy(c->title, args[1], sizeof(c->title));
- c->title[sizeof(c->title)-1] = '\0';
-
- if (args && args[2])
- cwd = !strcmp(args[2], "$CWD") ? getcwd_by_pid(sel) : (char*)args[2];
- c->pid = vt_forkpty(c->term, shell, pargs, cwd, env, nil, nil);
- if (args && args[2] && !strcmp(args[2], "$CWD"))
- free(cwd);
- vt_data_set(c->term, c);
- vt_title_handler_set(c->term, term_title_handler);
- vt_urgent_handler_set(c->term, term_urgent_handler);
- applycolorrules(c);
- c->x = wax;
- c->y = way;
- debug("client with pid %d forked\n", c->pid);
- attach(c);
- focus(c);
- arrange();
-}
-
-void
-copymode(const char *args[])
-{
- if (!args || !args[0] || !sel || sel->editor)
- return;
-
- bool colored = strstr(args[0], "pager") != nil;
-
- if (!(sel->editor = vt_create(sel->h - sel->has_title_line, sel->w, 0)))
- return;
-
- int *to = &sel->editor_fds[0];
- int *from = strstr(args[0], "editor") ? &sel->editor_fds[1] : nil;
- sel->editor_fds[0] = sel->editor_fds[1] = -1;
-
- const char *argv[3] = { args[0], nil, nil };
- char argline[32];
- int line = vt_content_start(sel->app);
- snprintf(argline, sizeof(argline), "+%d", line);
- argv[1] = argline;
-
- if (vt_forkpty(sel->editor, args[0], argv, nil, nil, to, from) < 0) {
- vt_destroy(sel->editor);
- sel->editor = nil;
- return;
- }
-
- sel->term = sel->editor;
-
- if (sel->editor_fds[0] != -1) {
- char *buf = nil;
- size_t len = vt_content_get(sel->app, &buf, colored);
- char *cur = buf;
- while (len > 0) {
- ssize_t res = write(sel->editor_fds[0], cur, len);
- if (res < 0) {
- if (errno == EAGAIN || errno == EINTR)
- continue;
- break;
- }
- cur += res;
- len -= res;
- }
- free(buf);
- close(sel->editor_fds[0]);
- sel->editor_fds[0] = -1;
- }
-
- if (args[1])
- vt_write(sel->editor, args[1], strlen(args[1]));
-}
-
-void
-focusn(const char *args[])
-{
- for (Client *c = nextvisible(clients); c; c = nextvisible(c->next)) {
- if (c->order == atoi(args[0])) {
- focus(c);
- if (c->minimized)
- toggleminimize(nil);
- return;
- }
- }
-}
-
-void
-focusid(const char *args[])
-{
- if (!args[0])
- return;
-
- const int win_id = atoi(args[0]);
- for (Client *c = clients; c; c = c->next) {
- if (c->id == win_id) {
- focus(c);
- if (c->minimized)
- toggleminimize(nil);
- if (!isvisible(c)) {
- c->tags |= tagset[seltags];
- tagschanged();
- }
- return;
- }
- }
-}
-
-void
-focusnext(const char *args[])
-{
- Client *c;
- if (!sel)
- return;
- for (c = sel->next; c && !isvisible(c); c = c->next);
- if (!c)
- for (c = clients; c && !isvisible(c); c = c->next);
- if (c)
- focus(c);
-}
-
-void
-focusnextnm(const char *args[])
-{
- if (!sel)
- return;
- Client *c = sel;
- do {
- c = nextvisible(c->next);
- if (!c)
- c = nextvisible(clients);
- } while (c->minimized && c != sel);
- focus(c);
-}
-
-void
-focusprev(const char *args[])
-{
- Client *c;
- if (!sel)
- return;
- for (c = sel->prev; c && !isvisible(c); c = c->prev);
- if (!c) {
- for (c = clients; c && c->next; c = c->next);
- for (; c && !isvisible(c); c = c->prev);
- }
- if (c)
- focus(c);
-}
-
-void
-focusprevnm(const char *args[])
-{
- if (!sel)
- return;
- Client *c = sel;
- do {
- for (c = c->prev; c && !isvisible(c); c = c->prev);
- if (!c) {
- for (c = clients; c && c->next; c = c->next);
- for (; c && !isvisible(c); c = c->prev);
- }
- } while (c && c != sel && c->minimized);
- focus(c);
-}
-
-void
-focuslast(const char *args[])
-{
- if (lastsel)
- focus(lastsel);
-}
-
-void
-focusup(const char *args[])
-{
- if (!sel)
- return;
- /* avoid vertical separator, hence +1 in x direction */
- Client *c = get_client_by_coord(sel->x + 1, sel->y - 1);
- if (c)
- focus(c);
- else
- focusprev(args);
-}
-
-void
-focusdown(const char *args[])
-{
- if (!sel)
- return;
- Client *c = get_client_by_coord(sel->x, sel->y + sel->h);
- if (c)
- focus(c);
- else
- focusnext(args);
-}
-
-void
-focusleft(const char *args[])
-{
- if (!sel)
- return;
- Client *c = get_client_by_coord(sel->x - 2, sel->y);
- if (c)
- focus(c);
- else
- focusprev(args);
-}
-
-void
-focusright(const char *args[])
-{
- if (!sel)
- return;
- Client *c = get_client_by_coord(sel->x + sel->w + 1, sel->y);
- if (c)
- focus(c);
- else
- focusnext(args);
-}
-
-void
-killclient(const char *args[])
-{
- if (!sel)
- return;
- debug("killing client with pid: %d\n", sel->pid);
- kill(-sel->pid, SIGKILL);
-}
-
-void
-paste(const char *args[])
-{
- if (sel && copyreg.data)
- vt_write(sel->term, copyreg.data, copyreg.len);
-}
-
-void
-quit(const char *args[])
-{
- cleanup();
- exit(EXIT_SUCCESS);
-}
-
-void
-redraw(const char *args[])
-{
- for (Client *c = clients; c; c = c->next) {
- if (!c->minimized) {
- vt_dirty(c->term);
- wclear(c->window);
- wnoutrefresh(c->window);
- }
- }
- resize_screen();
-}
-
-void
-scrollback(const char *args[])
-{
- if (!is_content_visible(sel))
- return;
-
- if (!args[0] || atoi(args[0]) < 0)
- vt_scroll(sel->term, -sel->h/2);
- else
- vt_scroll(sel->term, sel->h/2);
-
- draw(sel);
- curs_set(vt_cursor_visible(sel->term));
-}
-
-void
-send(const char *args[])
-{
- if (sel && args && args[0])
- vt_write(sel->term, args[0], strlen(args[0]));
-}
-
-void
-setlayout(const char *args[])
-{
- uint i;
-
- if (!args || !args[0]) {
- if (++layout == &layouts[arrlen(layouts)])
- layout = &layouts[0];
- } else {
- for (i = 0; i < arrlen(layouts); i++)
- if (!strcmp(args[0], layouts[i].symbol))
- break;
- if (i == arrlen(layouts))
- return;
- layout = &layouts[i];
- }
- arrange();
-}
-
-void
-incnmaster(const char *args[])
-{
- int delta;
-
- if (isarrange(fullscreen) || isarrange(grid))
- return;
- /* arg handling, manipulate nmaster */
- if (args[0] == nil) {
- screen.nmaster = NMASTER;
- } else if (sscanf(args[0], "%d", &delta) == 1) {
- if (args[0][0] == '+' || args[0][0] == '-')
- screen.nmaster += delta;
- else
- screen.nmaster = delta;
- if (screen.nmaster < 1)
- screen.nmaster = 1;
- }
- arrange();
-}
-
-void
-setmfact(const char *args[])
-{
- float delta;
-
- if (isarrange(fullscreen) || isarrange(grid))
- return;
- /* arg handling, manipulate mfact */
- if (args[0] == nil) {
- screen.mfact = MFACT;
- } else if (sscanf(args[0], "%f", &delta) == 1) {
- if (args[0][0] == '+' || args[0][0] == '-')
- screen.mfact += delta;
- else
- screen.mfact = delta;
- if (screen.mfact < 0.1)
- screen.mfact = 0.1;
- else if (screen.mfact > 0.9)
- screen.mfact = 0.9;
- }
- arrange();
-}
-
-void
-startup(const char *args[])
-{
- for (uint i = 0; i < arrlen(actions); i++)
- actions[i].cmd(actions[i].args);
-}
-
-void
-togglebar(const char *args[])
-{
- if (bar.pos == BAR_OFF)
- showbar();
- else
- hidebar();
- bar.autohide = false;
- updatebarpos();
- redraw(nil);
-}
-
-void
-togglebarpos(const char *args[])
-{
- switch (bar.pos == BAR_OFF ? bar.lastpos : bar.pos) {
- case BAR_TOP:
- bar.pos = BAR_BOTTOM;
- break;
- case BAR_BOTTOM:
- bar.pos = BAR_TOP;
- break;
- }
- updatebarpos();
- redraw(nil);
-}
-
-void
-toggleminimize(const char *args[])
-{
- Client *c, *m, *t;
- uint n;
- if (!sel)
- return;
- /* the last window can't be minimized */
- if (!sel->minimized) {
- for (n = 0, c = nextvisible(clients); c; c = nextvisible(c->next))
- if (!c->minimized)
- n++;
- if (n == 1)
- return;
- }
- sel->minimized = !sel->minimized;
- m = sel;
- /* check whether the master client was minimized */
- if (sel == nextvisible(clients) && sel->minimized) {
- c = nextvisible(sel->next);
- detach(c);
- attach(c);
- focus(c);
- detach(m);
- for (; c && (t = nextvisible(c->next)) && !t->minimized; c = t);
- attachafter(m, c);
- } else if (m->minimized) {
- /* non master window got minimized move it above all other
- * minimized ones */
- focusnextnm(nil);
- detach(m);
- for (c = nextvisible(clients); c && (t = nextvisible(c->next)) && !t->minimized; c = t);
- attachafter(m, c);
- } else { /* window is no longer minimized, move it to the master area */
- vt_dirty(m->term);
- detach(m);
- attach(m);
- }
- arrange();
-}
-
-void
-togglemouse(const char *args[])
-{
- mouse_events_enabled = !mouse_events_enabled;
- mouse_setup();
-}
-
-void
-togglerunall(const char *args[])
-{
- runinall = !runinall;
- drawbar();
- draw_all();
-}
-
-void
-zoom(const char *args[])
-{
- Client *c;
-
- if (!sel)
- return;
- if (args && args[0])
- focusn(args);
- if ((c = sel) == nextvisible(clients))
- if (!(c = nextvisible(c->next)))
- return;
- detach(c);
- attach(c);
- focus(c);
- if (c->minimized)
- toggleminimize(nil);
- arrange();
-}
-
-/* commands for use by mouse bindings */
-void
-mouse_focus(const char *args[])
-{
- focus(msel);
- if (msel->minimized)
- toggleminimize(nil);
-}
-
-void
-mouse_fullscreen(const char *args[])
-{
- mouse_focus(nil);
- setlayout(isarrange(fullscreen) ? nil : args);
-}
-
-void
-mouse_minimize(const char *args[])
-{
- focus(msel);
- toggleminimize(nil);
-}
-
-void
-mouse_zoom(const char *args[])
-{
- focus(msel);
- zoom(nil);
-}
-
-static
-Cmd *
-get_cmd_by_name(const char *name) {
- for (uint i = 0; i < arrlen(commands); i++) {
- if (!strcmp(name, commands[i].name))
- return &commands[i];
- }
- return nil;
-}
-
-static
-void
-handle_cmdfifo(void) {
- int r;
- char *p, *s, cmdbuf[512], c;
- Cmd *cmd;
-
- r = read(cmdfifo.fd, cmdbuf, sizeof cmdbuf - 1);
- if (r <= 0) {
- cmdfifo.fd = -1;
- return;
- }
-
- cmdbuf[r] = '\0';
- p = cmdbuf;
- while (*p) {
- /* find the command name */
- for (; *p == ' ' || *p == '\n'; p++);
- for (s = p; *p && *p != ' ' && *p != '\n'; p++);
- if ((c = *p))
- *p++ = '\0';
- if (*s && (cmd = get_cmd_by_name(s)) != nil) {
- bool quote = false;
- int argc = 0;
- const char *args[MAX_ARGS], *arg;
- memset(args, 0, sizeof(args));
- /* if arguments were specified in config.h ignore the one given via
- * the named pipe and thus skip everything until we find a new line
- */
- if (cmd->action.args[0] || c == '\n') {
- debug("execute %s", s);
- cmd->action.cmd(cmd->action.args);
- while (*p && *p != '\n')
- p++;
- continue;
- }
- /* no arguments were given in config.h so we parse the command line */
- while (*p == ' ')
- p++;
- arg = p;
- for (; (c = *p); p++) {
- switch (*p) {
- case '\\':
- /* remove the escape character '\\' move every
- * following character to the left by one position
- */
- switch (p[1]) {
- case '\\':
- case '\'':
- case '\"': {
- char *t = p+1;
- do {
- t[-1] = *t;
- } while (*t++);
- }
- }
- break;
- case '\'':
- case '\"':
- quote = !quote;
- break;
- case ' ':
- if (!quote) {
- case '\n':
- /* remove trailing quote if there is one */
- if (*(p - 1) == '\'' || *(p - 1) == '\"')
- *(p - 1) = '\0';
- *p++ = '\0';
- /* remove leading quote if there is one */
- if (*arg == '\'' || *arg == '\"')
- arg++;
- if (argc < MAX_ARGS)
- args[argc++] = arg;
-
- while (*p == ' ')
- ++p;
- arg = p--;
- }
- break;
- }
-
- if (c == '\n' || *p == '\n') {
- if (!*p)
- p++;
- debug("execute %s", s);
- for(int i = 0; i < argc; i++)
- debug(" %s", args[i]);
- debug("\n");
- cmd->action.cmd(args);
- break;
- }
- }
- }
- }
-}
-
-static void
-handle_mouse(void) {
-#ifdef CONFIG_MOUSE
- MEVENT event;
- uint i;
- if (getmouse(&event) != OK)
- return;
- msel = get_client_by_coord(event.x, event.y);
-
- if (!msel)
- return;
-
- debug("mouse x:%d y:%d cx:%d cy:%d mask:%d\n", event.x, event.y, event.x - msel->x, event.y - msel->y, event.bstate);
-
- vt_mouse(msel->term, event.x - msel->x, event.y - msel->y, event.bstate);
-
- for (i = 0; i < arrlen(buttons); i++) {
- if (event.bstate & buttons[i].mask)
- buttons[i].action.cmd(buttons[i].action.args);
- }
-
- msel = nil;
-#endif /* CONFIG_MOUSE */
-}
-
-static void
-handle_statusbar(void) {
- char *p;
- int r;
- switch (r = read(bar.fd, bar.text, sizeof bar.text - 1)) {
- case -1:
- strncpy(bar.text, strerror(errno), sizeof bar.text - 1);
- bar.text[sizeof bar.text - 1] = '\0';
- bar.fd = -1;
- break;
- case 0:
- bar.fd = -1;
- break;
- default:
- bar.text[r] = '\0';
- p = bar.text + r - 1;
- for (; p >= bar.text && *p == '\n'; *p-- = '\0');
- for (; p >= bar.text && *p != '\n'; --p);
- if (p >= bar.text)
- memmove(bar.text, p + 1, strlen(p));
- drawbar();
- }
-}
-
-static void
-handle_editor(Client *c) {
- if (!copyreg.data && (copyreg.data = malloc(screen.history)))
- copyreg.size = screen.history;
- copyreg.len = 0;
- while (c->editor_fds[1] != -1 && copyreg.len < copyreg.size) {
- ssize_t len = read(c->editor_fds[1], copyreg.data + copyreg.len, copyreg.size - copyreg.len);
- if (len == -1) {
- if (errno == EINTR)
- continue;
- break;
- }
- if (len == 0)
- break;
- copyreg.len += len;
- if (copyreg.len == copyreg.size) {
- copyreg.size *= 2;
- if (!(copyreg.data = realloc(copyreg.data, copyreg.size))) {
- copyreg.size = 0;
- copyreg.len = 0;
- }
- }
- }
- c->editor_died = false;
- c->editor_fds[1] = -1;
- vt_destroy(c->editor);
- c->editor = nil;
- c->term = c->app;
- vt_dirty(c->term);
- draw_content(c);
- wnoutrefresh(c->window);
-}
-
-static int
-open_or_create_fifo(const char *name, const char **name_created) {
- struct stat info;
- int fd;
-
- do {
- if ((fd = open(name, O_RDWR|O_NONBLOCK)) == -1) {
- if (errno == ENOENT && !mkfifo(name, S_IRUSR|S_IWUSR)) {
- *name_created = name;
- continue;
- }
- fatal("%s\n", strerror(errno));
- }
- } while (fd == -1);
-
- if (fstat(fd, &info) == -1)
- fatal("%s\n", strerror(errno));
- if (!S_ISFIFO(info.st_mode))
- fatal("%s is not a named pipe\n", name);
- return fd;
-}
-
-static
-void
-usage(void) {
- cleanup();
- eprint("usage: dvtm [-v] [-M] [-m mod] [-d delay] [-h lines] [-t title] "
- "[-s status-fifo] [-c cmd-fifo] [cmd...]\n");
- exit(EXIT_FAILURE);
-}
-
-static
-bool
-parse_args(int argc, char *argv[]) {
- bool init = false;
- const char *name = argv[0];
-
- if (name && (name = strrchr(name, '/')))
- dvtm_name = name + 1;
- if (!getenv("ESCDELAY"))
- set_escdelay(100);
- for (int arg = 1; arg < argc; arg++) {
- if (argv[arg][0] != '-') {
- const char *args[] = { argv[arg], nil, nil };
- if (!init) {
- setup();
- init = true;
- }
- create(args);
- continue;
- }
- if (argv[arg][1] != 'v' && argv[arg][1] != 'M' && (arg + 1) >= argc)
- usage();
- switch (argv[arg][1]) {
- case 'v':
- puts("dvtm-"VERSION);
- exit(EXIT_SUCCESS);
- case 'M':
- mouse_events_enabled = !mouse_events_enabled;
- break;
- case 'm': {
- char *mod = argv[++arg];
- if (mod[0] == '^' && mod[1])
- *mod = CTRL(mod[1]);
- for (uint b = 0; b < arrlen(bindings); b++)
- if (bindings[b].keys[0] == MOD)
- bindings[b].keys[0] = *mod;
- break;
- }
- case 'd':
- set_escdelay(atoi(argv[++arg]));
- if (ESCDELAY < 50)
- set_escdelay(50);
- else if (ESCDELAY > 1000)
- set_escdelay(1000);
- break;
- case 'h':
- screen.history = atoi(argv[++arg]);
- break;
- case 't':
- title = argv[++arg];
- break;
- case 's':
- bar.fd = open_or_create_fifo(argv[++arg], &bar.file);
- updatebarpos();
- break;
- case 'c': {
- const char *fifo;
- cmdfifo.fd = open_or_create_fifo(argv[++arg], &cmdfifo.file);
- if (!(fifo = realpath(argv[arg], nil)))
- fatal("%s\n", strerror(errno));
- setenv("DVTM_CMD_FIFO", fifo, 1);
- break;
- }
- default:
- usage();
- }
- }
- return init;
-}
-
-int
-main(int argc, char *argv[])
-{
- KeyCombo keys;
- uint key_index = 0;
- memset(keys, 0, sizeof(keys));
- sigset_t emptyset, blockset;
-
- setenv("DVTM", VERSION, 1);
- if (!parse_args(argc, argv)) {
- setup();
- startup(nil);
- }
-
- sigemptyset(&emptyset);
- sigemptyset(&blockset);
- sigaddset(&blockset, SIGWINCH);
- sigaddset(&blockset, SIGCHLD);
- sigprocmask(SIG_BLOCK, &blockset, nil);
-
- while (running) {
- int r, nfds = 0;
- fd_set rd;
-
- if (screen.need_resize) {
- resize_screen();
- screen.need_resize = false;
- }
-
- FD_ZERO(&rd);
- FD_SET(STDIN_FILENO, &rd);
-
- if (cmdfifo.fd != -1) {
- FD_SET(cmdfifo.fd, &rd);
- nfds = cmdfifo.fd;
- }
-
- if (bar.fd != -1) {
- FD_SET(bar.fd, &rd);
- nfds = MAX(nfds, bar.fd);
- }
-
- for (Client *c = clients; c;) {
- if (c->editor && c->editor_died)
- handle_editor(c);
- if (!c->editor && c->died) {
- Client *t = c->next;
- destroy(c);
- c = t;
- continue;
- }
- int pty = c->editor ? vt_pty_get(c->editor) : vt_pty_get(c->app);
- FD_SET(pty, &rd);
- nfds = MAX(nfds, pty);
- c = c->next;
- }
-
- doupdate();
- r = pselect(nfds + 1, &rd, nil, nil, nil, &emptyset);
-
- if (r < 0) {
- if (errno == EINTR)
- continue;
- perror("select()");
- exit(EXIT_FAILURE);
- }
-
- if (FD_ISSET(STDIN_FILENO, &rd)) {
- /* NOTE: this is the input handling step */
- int code = getch();
- if (code >= 0) {
- keys[key_index++] = code;
- KeyBinding *binding = nil;
-
- if (code == KEY_MOUSE) {
- key_index = 0;
- handle_mouse();
- } else if ((binding = keybinding(keys, key_index))) {
- uint key_length = MAX_KEYS;
- while (key_length > 1 && !binding->keys[key_length-1])
- key_length--;
- if (key_index == key_length) {
- binding->action.cmd(binding->action.args);
- key_index = 0;
- memset(keys, 0, sizeof(keys));
- }
- } else {
- key_index = 0;
- memset(keys, 0, sizeof(keys));
- keypress(code);
- }
- }
- if (r == 1) /* no data available on pty's */
- continue;
- }
-
- if (cmdfifo.fd != -1 && FD_ISSET(cmdfifo.fd, &rd))
- handle_cmdfifo();
-
- if (bar.fd != -1 && FD_ISSET(bar.fd, &rd))
- handle_statusbar();
-
- for (Client *c = clients; c; c = c->next) {
- if (FD_ISSET(vt_pty_get(c->term), &rd)) {
- if (vt_process(c->term) < 0 && errno == EIO) {
- if (c->editor)
- c->editor_died = true;
- else
- c->died = true;
- continue;
- }
- }
-
- if (c != sel && is_content_visible(c)) {
- draw_content(c);
- wnoutrefresh(c->window);
- }
- }
-
- if (is_content_visible(sel)) {
- draw_content(sel);
- curs_set(vt_cursor_visible(sel->term));
- wnoutrefresh(sel->window);
- }
- }
-
- cleanup();
- return 0;
-}
diff --git a/sys/cmd/dvtm/dvtm.h b/sys/cmd/dvtm/dvtm.h
deleted file mode 100644
index a777e18..0000000
--- a/sys/cmd/dvtm/dvtm.h
+++ /dev/null
@@ -1,233 +0,0 @@
- /* See LICENSE for details. */
-#pragma once
-#include <u.h>
-#include <libn.h>
-
-#include <locale.h>
-#include <libgen.h>
-
-#include <sys/select.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <sys/wait.h>
-#include <sys/time.h>
-#include <sys/types.h>
-
-// #include <vendor/curses.h>
-#include <termios.h>
-
-#include "vt.h"
-
-/* types */
-typedef struct Layout Layout;
-typedef struct Client Client;
-typedef struct Screen Screen;
-
-typedef struct Cmd Cmd;
-typedef struct CmdFifo CmdFifo;
-typedef struct Register Register;
-typedef struct Editor Editor;
-
-typedef struct Button Button;
-typedef struct KeyBinding KeyBinding;
-typedef struct StatusBar StatusBar;
-
-struct Screen
-{
- float mfact;
- uint nmaster;
- int history;
- int w, h;
- volatile sig_atomic_t need_resize;
-};
-
-struct Layout
-{
- const char *symbol;
- void (*arrange)(void);
-} ;
-
-struct Client
-{
- WINDOW *window;
- Vt *term;
- Vt *editor, *app;
- /* meta data */
- int editor_fds[2];
- volatile sig_atomic_t editor_died;
- const char *cmd;
- char title[255];
- int order;
- pid_t pid;
- ushort id;
- ushort x, y, w, h;
- bool has_title_line;
- bool minimized;
- bool urgent;
- volatile sig_atomic_t died;
- Client *next, *prev, *snext;
- uint tags;
-};
-
-typedef struct {
- int fg;
- int bg;
- int fg256;
- int bg256;
- int pair;
-} Color;
-
-typedef struct {
- const char *title;
- attr_t attrs;
- Color *color;
-} ColorRule;
-
-#define ALT(k) ((k) + (161 - 'a'))
-
-#if defined CTRL && defined _AIX
-#undef CTRL
-#endif
-
-#ifndef CTRL
-#define CTRL(k) ((k) & 0x1F)
-#endif
-#define CTRL_ALT(k) ((k) + (129 - 'a'))
-
-#define MAX_ARGS 8
-
-typedef struct
-{
- void (*cmd)(const char *args[]);
- const char *args[3];
-} Action;
-
-#define MAX_KEYS 3
-
-typedef uint KeyCombo[MAX_KEYS];
-
-struct KeyBinding
-{
- KeyCombo keys;
- Action action;
-};
-
-struct Button
-{
- mmask_t mask;
- Action action;
-};
-
-struct Cmd
-{
- const char *name;
- Action action;
-} ;
-
-enum { BAR_TOP, BAR_BOTTOM, BAR_OFF };
-
-struct StatusBar
-{
- int fd;
- int pos, lastpos;
- bool autohide;
- ushort h;
- ushort y;
- char text[512];
- const char *file;
-};
-
-struct CmdFifo
-{
- int fd;
- const char *file;
- ushort id;
-};
-
-struct Register
-{
- char *data;
- size_t len;
- size_t size;
-};
-
-struct Editor
-{
- char *name;
- const char *argv[4];
- bool filter;
- bool color;
-};
-
-#define TAGMASK ((1 << arrlen(tags)) - 1)
-
-#ifdef NDEBUG
- #define debug(format, args...)
-#else
- #define debug eprint
-#endif
-
-/* commands for use by keybindings */
-void create(const char *args[]);
-void copymode(const char *args[]);
-void focusn(const char *args[]);
-void focusid(const char *args[]);
-void focusnext(const char *args[]);
-void focusnextnm(const char *args[]);
-void focusprev(const char *args[]);
-void focusprevnm(const char *args[]);
-void focuslast(const char *args[]);
-void focusup(const char *args[]);
-void focusdown(const char *args[]);
-void focusleft(const char *args[]);
-void focusright(const char *args[]);
-void killclient(const char *args[]);
-void paste(const char *args[]);
-void quit(const char *args[]);
-void redraw(const char *args[]);
-void scrollback(const char *args[]);
-void send(const char *args[]);
-void setlayout(const char *args[]);
-void incnmaster(const char *args[]);
-void setmfact(const char *args[]);
-void startup(const char *args[]);
-void tag(const char *args[]);
-void tagid(const char *args[]);
-void togglebar(const char *args[]);
-void togglebarpos(const char *args[]);
-void toggleminimize(const char *args[]);
-void togglemouse(const char *args[]);
-void togglerunall(const char *args[]);
-void toggletag(const char *args[]);
-void toggleview(const char *args[]);
-void viewprevtag(const char *args[]);
-void view(const char *args[]);
-void zoom(const char *args[]);
-
-/* commands for use by mouse bindings */
-void mouse_focus(const char *args[]);
-void mouse_fullscreen(const char *args[]);
-void mouse_minimize(const char *args[]);
-void mouse_zoom(const char *args[]);
-
-/* functions and variables available to layouts via config.h */
-Client* nextvisible(Client *c);
-void focus(Client *c);
-void resize(Client *c, int x, int y, int w, int h);
-
-extern Screen screen;
-extern uint waw, wah, wax, way;
-extern Client *clients;
-extern char *title;
-
-void fibonacci(int s);
-void spiral(void);
-void dwindle(void);
-void fullscreen(void);
-void grid(void);
-void tile(void);
-void tstack(void);
-void bstack(void);
-void vstack(void);
-
-#include "config.h"
diff --git a/sys/cmd/dvtm/dvtm.info b/sys/cmd/dvtm/dvtm.info
deleted file mode 100644
index cafc0fe..0000000
--- a/sys/cmd/dvtm/dvtm.info
+++ /dev/null
@@ -1,136 +0,0 @@
-dvtm|dynamic virtual terminal manager,
- am,
- eo,
- mir,
- msgr,
- xenl,
- colors#8,
- cols#80,
- it#8,
- lines#24,
- ncv@,
- pairs#64,
- acsc=``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~,
- bel=^G,
- blink=\E[5m,
- bold=\E[1m,
- civis=\E[?25l,
- clear=\E[H\E[2J,
- cnorm=\E[?25h,
- cr=^M,
- csr=\E[%i%p1%d;%p2%dr,
- cub=\E[%p1%dD,
- cub1=^H,
- cud=\E[%p1%dB,
- cud1=^J,
- cuf=\E[%p1%dC,
- cuf1=\E[C,
- cup=\E[%i%p1%d;%p2%dH,
- cuu=\E[%p1%dA,
- cuu1=\E[A,
- dl=\E[%p1%dM,
- dl1=\E[M,
- ed=\E[J,
- el=\E[K,
- el1=\E[1K,
- enacs=\E(B\E)0,
- home=\E[H,
- hpa=\E[%i%p1%dG,
- ht=^I,
- hts=\EH,
- ich=\E[%p1%d@,
- ich1=\E[@,
- il=\E[%p1%dL,
- il1=\E[L,
- ind=^J,
- is1=\E[?47l\E=\E[?1l,
- is2=\E[r\E[m\E[2J\E[H\E[?7h\E[?1;3;4;6l\E[4l,
- kDC=\E[3$,
- kEND=\E[8$,
- kHOM=\E[7$,
- kIC=\E[2$,
- kLFT=\E[d,
- kNXT=\E[6$,
- kPRV=\E[5$,
- kRIT=\E[c,
- ka1=\EOw,
- ka3=\EOy,
- kb2=\EOu,
- kbs=\177,
- kc1=\EOq,
- kc3=\EOs,
- kcbt=\E[Z,
- kcub1=\E[D,
- kcud1=\E[B,
- kcuf1=\E[C,
- kcuu1=\E[A,
- kdch1=\E[3~,
- kel=\E[8\^,
- kend=\E[8~,
- kent=\EOM,
- kf0=\E[21~,
- kf1=\E[11~,
- kf2=\E[12~,
- kf3=\E[13~,
- kf4=\E[14~,
- kf5=\E[15~,
- kf6=\E[17~,
- kf7=\E[18~,
- kf8=\E[19~,
- kf9=\E[20~,
- kf10=\E[21~,
- kf11=\E[23~,
- kf12=\E[24~,
- kf13=\E[25~,
- kf14=\E[26~,
- kf15=\E[28~,
- kf16=\E[29~,
- kf17=\E[31~,
- kf18=\E[32~,
- kf19=\E[33~,
- kf20=\E[34~,
- kf21=\E[23$,
- kf22=\E[24$
- kfnd=\E[1~,
- khome=\E[7~,
- kich1=\E[2~,
- kind=\E[a,
- kmous=\E[M,
- knp=\E[6~,
- kpp=\E[5~,
- kri=\E[b,
- kslt=\E[4~,
- op=\E[39;49m,
- rc=\E8,
- rev=\E[7m,
- ri=\EM,
- ritm=\E[23m,
- rmacs=^O,
- rmcup=\E[2J\E[?47l\E8,
- rmir=\E[4l,
- rmso=\E[27m,
- rmul=\E[24m,
- rs1=\E>\E[?1;3;4;5;6l\E[?7h\E[m\E[r\E[2J\E[H,
- rs2=\E[r\E[m\E[2J\E[H\E[?7h\E[?1;3;4;6l\E[4l\E>\E[?1000l\E[?25h,
- s0ds=\E(B,
- s1ds=\E(0,
- sc=\E7,
- setab=\E[4%p1%dm,
- setaf=\E[3%p1%dm,
- sgr=\E[0%?%p6%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;m%?%p9%t\016%e\017%;,
- sgr0=\E[m\017,
- sitm=\E[3m,
- smacs=^N,
- smcup=\E7\E[?47h,
- smir=\E[4h,
- smso=\E[7m,
- smul=\E[4m,
- tbc=\E[3g,
- vpa=\E[%i%p1%dd,
-
-dvtm-256color|dynamic virtual terminal manager with 256 colors,
- use=dvtm,
- colors#256,
- pairs#32767,
- setab=\E[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m,
- setaf=\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m,
diff --git a/sys/cmd/dvtm/hook.c b/sys/cmd/dvtm/hook.c
deleted file mode 100644
index 6865f87..0000000
--- a/sys/cmd/dvtm/hook.c
+++ /dev/null
@@ -1,346 +0,0 @@
-#include "dvtm.h"
-
-void
-fibonacci(int s)
-{
- unsigned int nx, ny, nw, nnw, nh, nnh, i, n, mod;
- Client *c;
-
- for (n = 0, c = nextvisible(clients); c; c = nextvisible(c->next))
- if (!c->minimized)
- n++;
-
- /* initial position and dimensions */
- nx = wax;
- ny = way;
- nw = (n == 1) ? waw : screen.mfact * waw;
- /* don't waste space dviding by 2 doesn't work for odd numbers
- * plus we need space for the border too. therefore set up these
- * variables for the next new width/height
- */
- nnw = waw - nw - 1;
- nnh = nh = wah;
-
- /* set the mod factor, 2 for dwindle, 4 for spiral */
- mod = s ? 4 : 2;
-
- for (i = 0, c = nextvisible(clients); c; c = nextvisible(c->next)) {
- if (c->minimized)
- continue;
- /* dwindle: even case, spiral: case 0 */
- if (i % mod == 0) {
- if (i) {
- if (s) {
- nh = nnh;
- ny -= nh;
- } else {
- ny += nh;
- nh = nnh;
- }
- /* don't adjust the width for the last client */
- if (i < n - 1) {
- nw /= 2;
- nnw -= nw + 1;
- }
- mvaddch(ny, nx - 1, ACS_LTEE);
- }
- } else if (i % mod == 1) { /* dwindle: odd case, spiral: case 1 */
- nx += nw;
- mvvline(ny, nx, ACS_VLINE, nh);
- mvaddch(ny, nx, ACS_TTEE);
- ++nx;
- nw = nnw;
- /* don't adjust the height for the last client */
- if (i < n - 1) {
- nh /= 2;
- nnh -= nh;
- }
- } else if (i % mod == 2 && s) { /* spiral: case 2 */
- ny += nh;
- nh = nnh;
- /* don't adjust the width for the last client */
- if (i < n - 1) {
- nw /= 2;
- nnw -= nw + 1;
- nx += nnw;
- mvvline(ny, nx, ACS_VLINE, nh);
- mvaddch(ny, nx, ACS_TTEE);
- ++nx;
- } else {
- mvaddch(ny, nx - 1, ACS_LTEE);
- }
- } else if (s) { /* spiral: case 3 */
- nw = nnw;
- nx -= nw + 1; /* border */
- /* don't adjust the height for the last client */
- if (i < n - 1) {
- nh /= 2;
- nnh -= nh;
- ny += nnh;
- }
- mvaddch(ny, nx - 1, ACS_LTEE);
- }
-
- resize(c, nx, ny, nw, nh);
- i++;
- }
-}
-
-
-void
-spiral(void)
-{
- fibonacci(1);
-}
-
-void
-dwindle(void)
-{
- fibonacci(0);
-}
-
-void
-fullscreen(void)
-{
- for (Client *c = nextvisible(clients); c; c = nextvisible(c->next))
- resize(c, wax, way, waw, wah);
-}
-
-void
-grid(void)
-{
- unsigned int i, n, nx, ny, nw, nh, aw, ah, cols, rows;
- Client *c;
-
- for (n = 0, c = nextvisible(clients); c; c = nextvisible(c->next))
- if (!c->minimized)
- n++;
- /* grid dimensions */
- for (cols = 0; cols <= n / 2; cols++)
- if (cols * cols >= n)
- break;
- rows = (cols && (cols - 1) * cols >= n) ? cols - 1 : cols;
- /* window geoms (cell height/width) */
- nh = wah / (rows ? rows : 1);
- nw = waw / (cols ? cols : 1);
- for (i = 0, c = nextvisible(clients); c; c = nextvisible(c->next)) {
- if (c->minimized)
- continue;
- /* if there are less clients in the last row than normal adjust the
- * split rate to fill the empty space */
- if (rows > 1 && i == (rows * cols) - cols && (n - i) <= (n % cols))
- nw = waw / (n - i);
- nx = (i % cols) * nw + wax;
- ny = (i / cols) * nh + way;
- /* adjust height/width of last row/column's windows */
- ah = (i >= cols * (rows - 1)) ? wah - nh * rows : 0;
- /* special case if there are less clients in the last row */
- if (rows > 1 && i == n - 1 && (n - i) < (n % cols))
- /* (n % cols) == number of clients in the last row */
- aw = waw - nw * (n % cols);
- else
- aw = ((i + 1) % cols == 0) ? waw - nw * cols : 0;
- if (i % cols) {
- mvvline(ny, nx, ACS_VLINE, nh + ah);
- /* if we are on the first row, or on the last one and there are fewer clients
- * than normal whose border does not match the line above, print a top tree char
- * otherwise a plus sign. */
- if (i <= cols
- || (i >= rows * cols - cols && n % cols
- && (cols - (n % cols)) % 2))
- mvaddch(ny, nx, ACS_TTEE);
- else
- mvaddch(ny, nx, ACS_PLUS);
- nx++, aw--;
- }
- resize(c, nx, ny, nw + aw, nh + ah);
- i++;
- }
-}
-
-void
-tile(void)
-{
- unsigned int i, n, nx, ny, nw, nh, m, mw, mh, th;
- Client *c;
-
- for (n = 0, c = nextvisible(clients); c; c = nextvisible(c->next))
- if (!c->minimized)
- n++;
-
- m = MAX(1, MIN(n, screen.nmaster));
- mw = n == m ? waw : screen.mfact * waw;
- mh = wah / m;
- th = n == m ? 0 : wah / (n - m);
- nx = wax;
- ny = way;
-
- for (i = 0, c = nextvisible(clients); c; c = nextvisible(c->next)) {
- if (c->minimized)
- continue;
- if (i < m) { /* master */
- nw = mw;
- nh = (i < m - 1) ? mh : (way + wah) - ny;
- } else { /* tile window */
- if (i == m) {
- ny = way;
- nx += mw;
- mvvline(ny, nx, ACS_VLINE, wah);
- mvaddch(ny, nx, ACS_TTEE);
- nx++;
- nw = waw - mw -1;
- }
- nh = (i < n - 1) ? th : (way + wah) - ny;
- if (i > m)
- mvaddch(ny, nx - 1, ACS_LTEE);
- }
- resize(c, nx, ny, nw, nh);
- ny += nh;
- i++;
- }
-
- /* Fill in nmaster intersections */
- if (n > m) {
- ny = way + mh;
- for (i = 1; i < m; i++) {
- mvaddch(ny, nx - 1, ((ny - 1) % th ? ACS_RTEE : ACS_PLUS));
- ny += mh;
- }
- }
-}
-
-void
-tstack(void)
-{
- unsigned int i, n, nx, ny, nw, nh, m, mw, mh, tw;
- Client *c;
-
- for (n = 0, c = nextvisible(clients); c; c = nextvisible(c->next))
- if (!c->minimized)
- n++;
-
- m = MAX(1, MIN(n, screen.nmaster));
- mh = n == m ? wah : screen.mfact * wah;
- mw = waw / m;
- tw = n == m ? 0 : waw / (n - m);
- nx = wax;
- ny = way + wah - mh;
-
- for (i = 0, c = nextvisible(clients); c; c = nextvisible(c->next)) {
- if (c->minimized)
- continue;
- if (i < m) { /* master */
- if (i > 0) {
- mvvline(ny, nx, ACS_VLINE, nh);
- mvaddch(ny, nx, ACS_TTEE);
- nx++;
- }
- nh = mh;
- nw = (i < m - 1) ? mw : (wax + waw) - nx;
- } else { /* tile window */
- if (i == m) {
- nx = wax;
- ny = way;
- nh = (way + wah) - ny - mh;
- }
- if (i > m) {
- mvvline(ny, nx, ACS_VLINE, nh);
- mvaddch(ny, nx, ACS_TTEE);
- nx++;
- }
- nw = (i < n - 1) ? tw : (wax + waw) - nx;
- }
- resize(c, nx, ny, nw, nh);
- nx += nw;
- i++;
- }
-}
-
-void
-bstack(void)
-{
- unsigned int i, n, nx, ny, nw, nh, m, mw, mh, tw;
- Client *c;
-
- for (n = 0, c = nextvisible(clients); c; c = nextvisible(c->next))
- if (!c->minimized)
- n++;
-
- m = MAX(1, MIN(n, screen.nmaster));
- mh = n == m ? wah : screen.mfact * wah;
- mw = waw / m;
- tw = n == m ? 0 : waw / (n - m);
- nx = wax;
- ny = way;
-
- for (i = 0, c = nextvisible(clients); c; c = nextvisible(c->next)) {
- if (c->minimized)
- continue;
- if (i < m) { /* master */
- if (i > 0) {
- mvvline(ny, nx, ACS_VLINE, nh);
- mvaddch(ny, nx, ACS_TTEE);
- nx++;
- }
- nh = mh;
- nw = (i < m - 1) ? mw : (wax + waw) - nx;
- } else { /* tile window */
- if (i == m) {
- nx = wax;
- ny += mh;
- nh = (way + wah) - ny;
- }
- if (i > m) {
- mvvline(ny, nx, ACS_VLINE, nh);
- mvaddch(ny, nx, ACS_TTEE);
- nx++;
- }
- nw = (i < n - 1) ? tw : (wax + waw) - nx;
- }
- resize(c, nx, ny, nw, nh);
- nx += nw;
- i++;
- }
-
- /* Fill in nmaster intersections */
- if (n > m) {
- nx = wax;
- for (i = 0; i < m; i++) {
- if (i > 0) {
- mvaddch(ny, nx, ACS_PLUS);
- nx++;
- }
- nw = (i < m - 1) ? mw : (wax + waw) - nx;
- nx += nw;
- }
- }
-}
-
-/* a vertical stack layout, all windows have the full screen width. */
-void
-vstack(void)
-{
- unsigned int i, n, ny, nh, m, mh, th;
- Client *c;
-
- for (n = 0, c = nextvisible(clients); c; c = nextvisible(c->next))
- if (!c->minimized)
- n++;
-
- m = MAX(1, MIN(n, screen.nmaster));
- mh = (n == m ? wah : screen.mfact * wah);
- th = n == m ? 0 : (wah - mh) / (n - m);
- ny = way;
-
- for (i = 0, c = nextvisible(clients); c; c = nextvisible(c->next)) {
- if (c->minimized)
- continue;
- if (i < m) /* master */
- nh = (i < m - 1) ? mh / m : (way + mh) - ny;
- else /* tile window */
- nh = (i < n - 1) ? th : (way + wah) - ny;
- resize(c, wax, ny, waw, nh);
- ny += nh;
- i++;
- }
-}
diff --git a/sys/cmd/dvtm/rules.mk b/sys/cmd/dvtm/rules.mk
deleted file mode 100644
index f12aa17..0000000
--- a/sys/cmd/dvtm/rules.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-include share/push.mk
-
-# Local sources
-SRCS_$(d) := \
-$(d)/hook.c \
-$(d)/vt.c \
-$(d)/dvtm.c
-
-# needed for additional editor target
-AUX := $(d)/dvtm-editor.o
-AUX := $(patsubst $(SRC_DIR)/%, $(OBJ_DIR)/%, $(AUX))
-
-DVTM := $(d)/dvtm
-DVTM-ED := $(d)/dvtm-editor
-
-DVTM := $(patsubst $(SRC_DIR)/%, $(OBJ_DIR)/%, $(DVTM))
-DVTM-ED := $(patsubst $(SRC_DIR)/%, $(OBJ_DIR)/%, $(DVTM-ED))
-
-BINS_$(d) := $(DVTM) $(DVTM-ED)
-
-include share/paths.mk
-
-$(DVTM): TCFLAGS = -D_XOPEN_SOURCE=700 -D_XOPEN_SOURCE_EXTENDED -DNDEBUG
-$(DVTM): TCLIBS = -lncursesw $(OBJ_DIR)/libn/libn.a
-$(DVTM): $(OBJS_$(d))
- $(COMPLINK)
-
-$(DVTM-ED): TCFLAGS = -D_XOPEN_SOURCE=700 -D_XOPEN_SOURCE_EXTENDED
-$(DVTM-ED): TCLIBS = -lncursesw -lutil -lc
-$(DVTM-ED): $(AUX)
- $(COMPLINK)
-
-include share/pop.mk
diff --git a/sys/cmd/dvtm/vt.c b/sys/cmd/dvtm/vt.c
deleted file mode 100644
index aff4ab0..0000000
--- a/sys/cmd/dvtm/vt.c
+++ /dev/null
@@ -1,2112 +0,0 @@
-/* See license for details */
-#include <u.h>
-#include <libn.h>
-
-#include <langinfo.h>
-#include <signal.h>
-#include <termios.h>
-
-#include <sys/ioctl.h>
-#include <sys/types.h>
-
-#if defined(__linux__) || defined(__CYGWIN__)
-# include <pty.h>
-#elif defined(__FreeBSD__) || defined(__DragonFly__)
-# include <libutil.h>
-#elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__)
-# include <util.h>
-#endif
-
-#include "vt.h"
-
-#ifndef NCURSES_ATTR_SHIFT
-# define NCURSES_ATTR_SHIFT 8
-#endif
-
-#ifndef NCURSES_ACS
-# ifdef PDCURSES
-# define NCURSES_ACS(c) (acs_map[(uchar)(c)])
-# else /* BSD curses */
-# define NCURSES_ACS(c) (_acs_map[(uchar)(c)])
-# endif
-#endif
-
-#ifdef NCURSES_VERSION
-
-#ifndef NCURSES_EXT_COLORS
-# define NCURSES_EXT_COLORS 0
-#endif
-
-#if !NCURSES_EXT_COLORS
-# define MAX_COLOR_PAIRS MIN(COLOR_PAIRS, 256)
-#endif
-
-#endif
-
-#ifndef MAX_COLOR_PAIRS
-# define MAX_COLOR_PAIRS COLOR_PAIRS
-#endif
-
-#if defined _AIX && defined CTRL
-# undef CTRL
-#endif
-#ifndef CTRL
-# define CTRL(k) ((k) & 0x1F)
-#endif
-
-#define IS_CONTROL(ch) !((ch) & 0xffffff60UL)
-
-static bool is_utf8, has_default_colors;
-static int color_pairs_reserved, color_pairs_max, color_pair_current;
-static short *color2palette, default_fg, default_bg;
-static char vt_term[32];
-
-typedef struct {
- wchar_t text;
- attr_t attr;
- union {
- struct {
- short fg;
- short bg;
- };
- struct {
- uint8 r;
- uint8 g;
- uint8 b;
- };
- };
-} Cell;
-
-typedef struct {
- Cell *cells;
- uint dirty:1;
-} Row;
-
-/* Buffer holding the current terminal window content (as an array) as well
- * as the scroll back buffer content (as a circular/ring buffer).
- *
- * If new content is added to terminal the view port slides down and the
- * previously top most line is moved into the scroll back buffer at postion
- * scroll_index. This index will eventually wrap around and thus overwrite
- * the oldest lines.
- *
- * In the scenerio below a scroll up has been performed. That is 'scroll_above'
- * lines still lie above the current view port. Further scrolling up will show
- * them. Similarly 'scroll_below' is the amount of lines below the current
- * viewport.
- *
- * The function buffer_boundary sets the row pointers to the start/end range
- * of the section delimiting the region before/after the viewport. The functions
- * buffer_row_{first,last} return the first/last logical row. And
- * buffer_row_{next,prev} allows to iterate over the logical lines in either
- * direction.
- *
- * scroll back buffer
- *
- * scroll_buf->+----------------+-----+
- * | | | ^ \
- * | before | | | |
- * current terminal content | viewport | | | |
- * | | | |
- * +----------------+-----+\ | | | s > scroll_above
- * ^ | | i | \ | | i | c |
- * | | | n | \ | | n | r |
- * | | v | \ | | v | o |
- * r | | i | \ | | i | l /
- * o | viewport | s | >|<- scroll_index | s | l \
- * w | | i | / | | i | |
- * s | | b | / | after | b | s > scroll_below
- * | | l | / | viewport | l | i |
- * v | | e | / | | e | z /
- * +----------------+-----+/ | unused | | e
- * <- maxcols -> | scroll back | |
- * <- cols -> | buffer | | |
- * | | | |
- * | | | v
- * scroll_buf + scroll_size->+----------------+-----+
- * <- maxcols ->
- * <- cols ->
- */
-typedef struct {
- Row *lines; /* array of Row pointers of size 'rows' */
- Row *curs_row; /* row on which the cursor currently resides */
- Row *scroll_buf; /* a ring buffer holding the scroll back content */
- Row *scroll_top; /* row in lines where scrolling region starts */
- Row *scroll_bot; /* row in lines where scrolling region ends */
- bool *tabs; /* a boolean flag for each column whether it is a tab */
- int scroll_size; /* maximal capacity of scroll back buffer (in lines) */
- int scroll_index; /* current index into the ring buffer */
- int scroll_above; /* number of lines above current viewport */
- int scroll_below; /* number of lines below current viewport */
- int rows, cols; /* current dimension of buffer */
- int maxcols; /* allocated cells (maximal cols over time) */
- attr_t curattrs, savattrs; /* current and saved attributes for cells */
- int curs_col; /* current cursor column (zero based) */
- int curs_srow, curs_scol; /* saved cursor row/colmn (zero based) */
- short curfg, curbg; /* current fore and background colors */
- short savfg, savbg; /* saved colors */
-} Buffer;
-
-struct Vt {
- Buffer buffer_normal; /* normal screen buffer */
- Buffer buffer_alternate; /* alternate screen buffer */
- Buffer *buffer; /* currently active buffer (one of the above) */
- attr_t defattrs; /* attributes to use for normal/empty cells */
- int deffg, defbg; /* colors to use for back normal/empty cells (white/black) */
- int pty; /* master side pty file descriptor */
- pid_t pid; /* process id of the process running in this vt */
- /* flags */
- uint seen_input:1;
- uint insert:1;
- uint escaped:1;
- uint curshid:1;
- uint curskeymode:1;
- uint bell:1;
- uint relposmode:1;
- uint mousetrack:1;
- uint graphmode:1;
- uint savgraphmode:1;
- bool charsets[2];
- /* buffers and parsing state */
- char rbuf[BUFSIZ];
- char ebuf[BUFSIZ];
- uint rlen, elen;
- int srow, scol; /* last known offset to display start row, start column */
- char title[256]; /* xterm style window title */
- vt_title_handler_t title_handler; /* hook which is called when title changes */
- vt_urgent_handler_t urgent_handler; /* hook which is called upon bell */
- void *data; /* user supplied data */
-};
-
-static const char *keytable[KEY_MAX+1] = {
- [KEY_ENTER] = "\r",
- ['\n'] = "\n",
- /* for the arrow keys the CSI / SS3 sequences are not stored here
- * because they depend on the current cursor terminal mode
- */
- [KEY_UP] = "A",
- [KEY_DOWN] = "B",
- [KEY_RIGHT] = "C",
- [KEY_LEFT] = "D",
-#ifdef KEY_SUP
- [KEY_SUP] = "\e[1;2A",
-#endif
-#ifdef KEY_SDOWN
- [KEY_SDOWN] = "\e[1;2B",
-#endif
- [KEY_SRIGHT] = "\e[1;2C",
- [KEY_SLEFT] = "\e[1;2D",
- [KEY_BACKSPACE] = "\177",
- [KEY_IC] = "\e[2~",
- [KEY_DC] = "\e[3~",
- [KEY_PPAGE] = "\e[5~",
- [KEY_NPAGE] = "\e[6~",
- [KEY_HOME] = "\e[7~",
- [KEY_END] = "\e[8~",
- [KEY_BTAB] = "\e[Z",
- [KEY_SUSPEND] = "\x1A", /* Ctrl+Z gets mapped to this */
- [KEY_F(1)] = "\e[11~",
- [KEY_F(2)] = "\e[12~",
- [KEY_F(3)] = "\e[13~",
- [KEY_F(4)] = "\e[14~",
- [KEY_F(5)] = "\e[15~",
- [KEY_F(6)] = "\e[17~",
- [KEY_F(7)] = "\e[18~",
- [KEY_F(8)] = "\e[19~",
- [KEY_F(9)] = "\e[20~",
- [KEY_F(10)] = "\e[21~",
- [KEY_F(11)] = "\e[23~",
- [KEY_F(12)] = "\e[24~",
- [KEY_F(13)] = "\e[23~",
- [KEY_F(14)] = "\e[24~",
- [KEY_F(15)] = "\e[25~",
- [KEY_F(16)] = "\e[26~",
- [KEY_F(17)] = "\e[28~",
- [KEY_F(18)] = "\e[29~",
- [KEY_F(19)] = "\e[31~",
- [KEY_F(20)] = "\e[32~",
- [KEY_F(21)] = "\e[33~",
- [KEY_F(22)] = "\e[34~",
- [KEY_RESIZE] = "",
-#ifdef KEY_EVENT
- [KEY_EVENT] = "",
-#endif
-};
-
-static void puttab(Vt *t, int count);
-static void process_nonprinting(Vt *t, wchar_t wc);
-static void send_curs(Vt *t);
-
-const static
-attr_t
-build_attrs(attr_t curattrs)
-{
- return ((curattrs & ~A_COLOR) | COLOR_PAIR(curattrs & 0xff)) >> NCURSES_ATTR_SHIFT;
-}
-
-static
-void
-row_set(Row *row, int start, int len, Buffer *t)
-{
- Cell cell = {
- .text = L'\0',
- .attr = t ? build_attrs(t->curattrs) : 0,
- .fg = t ? t->curfg : -1,
- .bg = t ? t->curbg : -1,
- };
-
- for (int i = start; i < len + start; i++)
- row->cells[i] = cell;
- row->dirty = true;
-}
-
-static
-void
-row_roll(Row *start, Row *end, int count)
-{
- int n = end - start;
-
- count %= n;
- if (count < 0)
- count += n;
-
- if (count) {
- char buf[count * sizeof(Row)];
- memcpy(buf, start, count * sizeof(Row));
- memmove(start, start + count, (n - count) * sizeof(Row));
- memcpy(end - count, buf, count * sizeof(Row));
- for (Row *row = start; row < end; row++)
- row->dirty = true;
- }
-}
-
-static
-void
-buffer_clear(Buffer *b)
-{
- Cell cell = {
- .text = L'\0',
- .attr = A_NORMAL,
- .fg = -1,
- .bg = -1,
- };
-
- for (int i = 0; i < b->rows; i++) {
- Row *row = b->lines + i;
- for (int j = 0; j < b->cols; j++) {
- row->cells[j] = cell;
- row->dirty = true;
- }
- }
-}
-
-static
-void
-buffer_free(Buffer *b)
-{
- for (int i = 0; i < b->rows; i++)
- free(b->lines[i].cells);
- free(b->lines);
- for (int i = 0; i < b->scroll_size; i++)
- free(b->scroll_buf[i].cells);
- free(b->scroll_buf);
- free(b->tabs);
-}
-
-static
-void
-buffer_scroll(Buffer *b, int s)
-{
- /* work in screenfuls */
- int ssz = b->scroll_bot - b->scroll_top;
- if (s > ssz) {
- buffer_scroll(b, ssz);
- buffer_scroll(b, s - ssz);
- return;
- }
- if (s < -ssz) {
- buffer_scroll(b, -ssz);
- buffer_scroll(b, s + ssz);
- return;
- }
-
- b->scroll_above += s;
- if (b->scroll_above >= b->scroll_size)
- b->scroll_above = b->scroll_size;
-
- if (s > 0 && b->scroll_size) {
- for (int i = 0; i < s; i++) {
- Row tmp = b->scroll_top[i];
- b->scroll_top[i] = b->scroll_buf[b->scroll_index];
- b->scroll_buf[b->scroll_index] = tmp;
-
- b->scroll_index++;
- if (b->scroll_index == b->scroll_size)
- b->scroll_index = 0;
- }
- }
- row_roll(b->scroll_top, b->scroll_bot, s);
- if (s < 0 && b->scroll_size) {
- for (int i = (-s) - 1; i >= 0; i--) {
- b->scroll_index--;
- if (b->scroll_index == -1)
- b->scroll_index = b->scroll_size - 1;
-
- Row tmp = b->scroll_top[i];
- b->scroll_top[i] = b->scroll_buf[b->scroll_index];
- b->scroll_buf[b->scroll_index] = tmp;
- b->scroll_top[i].dirty = true;
- }
- }
-}
-
-static
-void
-buffer_resize(Buffer *b, int rows, int cols)
-{
- Row *lines = b->lines;
-
- if (b->rows != rows) {
- if (b->curs_row >= lines + rows) {
- /* scroll up instead of simply chopping off bottom */
- buffer_scroll(b, (b->curs_row - b->lines) - rows + 1);
- }
- while (b->rows > rows) {
- free(lines[b->rows - 1].cells);
- b->rows--;
- }
-
- lines = realloc(lines, sizeof(Row) * rows);
- }
-
- if (b->maxcols < cols) {
- for (int row = 0; row < b->rows; row++) {
- lines[row].cells = realloc(lines[row].cells, sizeof(Cell) * cols);
- if (b->cols < cols)
- row_set(lines + row, b->cols, cols - b->cols, nil);
- lines[row].dirty = true;
- }
- Row *sbuf = b->scroll_buf;
- for (int row = 0; row < b->scroll_size; row++) {
- sbuf[row].cells = realloc(sbuf[row].cells, sizeof(Cell) * cols);
- if (b->cols < cols)
- row_set(sbuf + row, b->cols, cols - b->cols, nil);
- }
- b->tabs = realloc(b->tabs, sizeof(*b->tabs) * cols);
- for (int col = b->cols; col < cols; col++)
- b->tabs[col] = !(col & 7);
- b->maxcols = cols;
- b->cols = cols;
- } else if (b->cols != cols) {
- for (int row = 0; row < b->rows; row++)
- lines[row].dirty = true;
- b->cols = cols;
- }
-
- int deltarows = 0;
- if (b->rows < rows) {
- while (b->rows < rows) {
- lines[b->rows].cells = calloc(b->maxcols, sizeof(Cell));
- row_set(lines + b->rows, 0, b->maxcols, b);
- b->rows++;
- }
-
- /* prepare for backfill */
- if (b->curs_row >= b->scroll_bot - 1) {
- deltarows = b->lines + rows - b->curs_row - 1;
- if (deltarows > b->scroll_above)
- deltarows = b->scroll_above;
- }
- }
-
- b->curs_row += lines - b->lines;
- b->scroll_top = lines;
- b->scroll_bot = lines + rows;
- b->lines = lines;
-
- /* perform backfill */
- if (deltarows > 0) {
- buffer_scroll(b, -deltarows);
- b->curs_row += deltarows;
- }
-}
-
-static
-bool
-buffer_init(Buffer *b, int rows, int cols, int scroll_size)
-{
- b->curattrs = A_NORMAL; /* white text over black background */
- b->curfg = b->curbg = -1;
- if (scroll_size < 0)
- scroll_size = 0;
- if (scroll_size && !(b->scroll_buf = calloc(scroll_size, sizeof(Row))))
- return false;
- b->scroll_size = scroll_size;
- buffer_resize(b, rows, cols);
- return true;
-}
-
-static
-void
-buffer_boundry(Buffer *b, Row **bs, Row **be, Row **as, Row **ae)
-{
- if (bs)
- *bs = nil;
- if (be)
- *be = nil;
- if (as)
- *as = nil;
- if (ae)
- *ae = nil;
- if (!b->scroll_size)
- return;
-
- if (b->scroll_above) {
- if (bs)
- *bs = &b->scroll_buf[(b->scroll_index - b->scroll_above + b->scroll_size) % b->scroll_size];
- if (be)
- *be = &b->scroll_buf[(b->scroll_index-1 + b->scroll_size) % b->scroll_size];
- }
- if (b->scroll_below) {
- if (as)
- *as = &b->scroll_buf[b->scroll_index];
- if (ae)
- *ae = &b->scroll_buf[(b->scroll_index + b->scroll_below-1) % b->scroll_size];
- }
-}
-
-static
-Row *
-buffer_row_first(Buffer *b) {
- Row *bstart;
- if (!b->scroll_size || !b->scroll_above)
- return b->lines;
- buffer_boundry(b, &bstart, nil, nil, nil);
- return bstart;
-}
-
-static
-Row *
-buffer_row_last(Buffer *b) {
- Row *aend;
- if (!b->scroll_size || !b->scroll_below)
- return b->lines + b->rows - 1;
- buffer_boundry(b, nil, nil, nil, &aend);
- return aend;
-}
-
-static
-Row *
-buffer_row_next(Buffer *b, Row *row)
-{
- Row *before_start, *before_end, *after_start, *after_end;
- Row *first = b->lines, *last = b->lines + b->rows - 1;
-
- if (!row)
- return nil;
-
- buffer_boundry(b, &before_start, &before_end, &after_start, &after_end);
-
- if (row >= first && row < last)
- return ++row;
- if (row == last)
- return after_start;
- if (row == before_end)
- return first;
- if (row == after_end)
- return nil;
- if (row == &b->scroll_buf[b->scroll_size - 1])
- return b->scroll_buf;
- return ++row;
-}
-
-static
-Row *
-buffer_row_prev(Buffer *b, Row *row)
-{
- Row *before_start, *before_end, *after_start, *after_end;
- Row *first = b->lines, *last = b->lines + b->rows - 1;
-
- if (!row)
- return nil;
-
- buffer_boundry(b, &before_start, &before_end, &after_start, &after_end);
-
- if (row > first && row <= last)
- return --row;
- if (row == first)
- return before_end;
- if (row == before_start)
- return nil;
- if (row == after_start)
- return last;
- if (row == b->scroll_buf)
- return &b->scroll_buf[b->scroll_size - 1];
- return --row;
-}
-
-static
-void
-cursor_clamp(Vt *t)
-{
- Buffer *b = t->buffer;
- Row *lines = t->relposmode ? b->scroll_top : b->lines;
- int rows = t->relposmode ? b->scroll_bot - b->scroll_top : b->rows;
-
- if (b->curs_row < lines)
- b->curs_row = lines;
- if (b->curs_row >= lines + rows)
- b->curs_row = lines + rows - 1;
- if (b->curs_col < 0)
- b->curs_col = 0;
- if (b->curs_col >= b->cols)
- b->curs_col = b->cols - 1;
-}
-
-static
-void
-cursor_line_down(Vt *t)
-{
- Buffer *b = t->buffer;
- row_set(b->curs_row, b->cols, b->maxcols - b->cols, nil);
- b->curs_row++;
- if (b->curs_row < b->scroll_bot)
- return;
-
- vt_noscroll(t);
-
- b->curs_row = b->scroll_bot - 1;
- buffer_scroll(b, 1);
- row_set(b->curs_row, 0, b->cols, b);
-}
-
-static
-void
-cursor_save(Vt *t)
-{
- Buffer *b = t->buffer;
- b->curs_srow = b->curs_row - b->lines;
- b->curs_scol = b->curs_col;
-}
-
-static
-void
-cursor_restore(Vt *t)
-{
- Buffer *b = t->buffer;
- b->curs_row = b->lines + b->curs_srow;
- b->curs_col = b->curs_scol;
- cursor_clamp(t);
-}
-
-static
-void
-attributes_save(Vt *t)
-{
- Buffer *b = t->buffer;
- b->savattrs = b->curattrs;
- b->savfg = b->curfg;
- b->savbg = b->curbg;
- t->savgraphmode = t->graphmode;
-}
-
-static
-void
-attributes_restore(Vt *t)
-{
- Buffer *b = t->buffer;
- b->curattrs = b->savattrs;
- b->curfg = b->savfg;
- b->curbg = b->savbg;
- t->graphmode = t->savgraphmode;
-}
-
-static
-void
-new_escape_sequence(Vt *t)
-{
- t->escaped = true;
- t->elen = 0;
- t->ebuf[0] = '\0';
-}
-
-static
-void
-cancel_escape_sequence(Vt *t)
-{
- t->escaped = false;
- t->elen = 0;
- t->ebuf[0] = '\0';
-}
-
-static
-bool
-is_valid_csi_ender(int c)
-{
- return (c >= 'a' && c <= 'z')
- || (c >= 'A' && c <= 'Z')
- || (c == '@' || c == '`');
-}
-
-/* interprets a 'set attribute' (SGR) CSI escape sequence */
-static
-void
-interpret_csi_sgr(Vt *t, int param[], int pcount)
-{
- Buffer *b = t->buffer;
- if (pcount == 0) {
- /* special case: reset attributes */
- b->curattrs = A_NORMAL;
- b->curfg = b->curbg = -1;
- return;
- }
-
- for (int i = 0; i < pcount; i++) {
- switch (param[i]) {
- case 0:
- b->curattrs = A_NORMAL;
- b->curfg = b->curbg = -1;
- break;
- case 1:
- b->curattrs |= A_BOLD;
- break;
- case 2:
- b->curattrs |= A_DIM;
- break;
-#ifdef A_ITALIC
- case 3:
- b->curattrs |= A_ITALIC;
- break;
-#endif
- case 4:
- b->curattrs |= A_UNDERLINE;
- break;
- case 5:
- b->curattrs |= A_BLINK;
- break;
- case 7:
- b->curattrs |= A_REVERSE;
- break;
- case 8:
- b->curattrs |= A_INVIS;
- break;
- case 22:
- b->curattrs &= ~(A_BOLD | A_DIM);
- break;
-#ifdef A_ITALIC
- case 23:
- b->curattrs &= ~A_ITALIC;
- break;
-#endif
- case 24:
- b->curattrs &= ~A_UNDERLINE;
- break;
- case 25:
- b->curattrs &= ~A_BLINK;
- break;
- case 27:
- b->curattrs &= ~A_REVERSE;
- break;
- case 28:
- b->curattrs &= ~A_INVIS;
- break;
- case 30 ... 37: /* fg */
- b->curfg = param[i] - 30;
- break;
- case 38:
- if ((i + 2) < pcount && param[i + 1] == 5) {
- b->curfg = param[i + 2];
- i += 2;
- }
- break;
- case 39:
- b->curfg = -1;
- break;
- case 40 ... 47: /* bg */
- b->curbg = param[i] - 40;
- break;
- case 48:
- if ((i + 2) < pcount && param[i + 1] == 5) {
- b->curbg = param[i + 2];
- i += 2;
- }
- break;
- case 49:
- b->curbg = -1;
- break;
- case 90 ... 97: /* hi fg */
- b->curfg = param[i] - 82;
- break;
- case 100 ... 107: /* hi bg */
- b->curbg = param[i] - 92;
- break;
- default:
- break;
- }
- }
-}
-
-/* interprets an 'erase display' (ED) escape sequence */
-static
-void
-interpret_csi_ed(Vt *t, int param[], int pcount)
-{
- Row *row, *start, *end;
- Buffer *b = t->buffer;
-
- attributes_save(t);
- b->curattrs = A_NORMAL;
- b->curfg = b->curbg = -1;
-
- if (pcount && param[0] == 2) {
- start = b->lines;
- end = b->lines + b->rows;
- } else if (pcount && param[0] == 1) {
- start = b->lines;
- end = b->curs_row;
- row_set(b->curs_row, 0, b->curs_col + 1, b);
- } else {
- row_set(b->curs_row, b->curs_col, b->cols - b->curs_col, b);
- start = b->curs_row + 1;
- end = b->lines + b->rows;
- }
-
- for (row = start; row < end; row++)
- row_set(row, 0, b->cols, b);
-
- attributes_restore(t);
-}
-
-/* interprets a 'move cursor' (CUP) escape sequence */
-static
-void
-interpret_csi_cup(Vt *t, int param[], int pcount)
-{
- Buffer *b = t->buffer;
- Row *lines = t->relposmode ? b->scroll_top : b->lines;
-
- if (pcount == 0) {
- b->curs_row = lines;
- b->curs_col = 0;
- } else if (pcount == 1) {
- b->curs_row = lines + param[0] - 1;
- b->curs_col = 0;
- } else {
- b->curs_row = lines + param[0] - 1;
- b->curs_col = param[1] - 1;
- }
-
- cursor_clamp(t);
-}
-
-/* Interpret the 'relative mode' sequences: CUU, CUD, CUF, CUB, CNL,
- * CPL, CHA, HPR, VPA, VPR, HPA */
-static
-void
-interpret_csi_c(Vt *t, char verb, int param[], int pcount)
-{
- Buffer *b = t->buffer;
- int n = (pcount && param[0] > 0) ? param[0] : 1;
-
- switch (verb) {
- case 'A':
- b->curs_row -= n;
- break;
- case 'B':
- case 'e':
- b->curs_row += n;
- break;
- case 'C':
- case 'a':
- b->curs_col += n;
- break;
- case 'D':
- b->curs_col -= n;
- break;
- case 'E':
- b->curs_row += n;
- b->curs_col = 0;
- break;
- case 'F':
- b->curs_row -= n;
- b->curs_col = 0;
- break;
- case 'G':
- case '`':
- b->curs_col = n - 1;
- break;
- case 'd':
- b->curs_row = b->lines + n - 1;
- break;
- }
-
- cursor_clamp(t);
-}
-
-/* Interpret the 'erase line' escape sequence */
-static
-void
-interpret_csi_el(Vt *t, int param[], int pcount)
-{
- Buffer *b = t->buffer;
- switch (pcount ? param[0] : 0) {
- case 1:
- row_set(b->curs_row, 0, b->curs_col + 1, b);
- break;
- case 2:
- row_set(b->curs_row, 0, b->cols, b);
- break;
- default:
- row_set(b->curs_row, b->curs_col, b->cols - b->curs_col, b);
- break;
- }
-}
-
-/* Interpret the 'insert blanks' sequence (ICH) */
-static
-void
-interpret_csi_ich(Vt *t, int param[], int pcount)
-{
- Buffer *b = t->buffer;
- Row *row = b->curs_row;
- int n = (pcount && param[0] > 0) ? param[0] : 1;
-
- if (b->curs_col + n > b->cols)
- n = b->cols - b->curs_col;
-
- for (int i = b->cols - 1; i >= b->curs_col + n; i--)
- row->cells[i] = row->cells[i - n];
-
- row_set(row, b->curs_col, n, b);
-}
-
-/* Interpret the 'delete chars' sequence (DCH) */
-static
-void
-interpret_csi_dch(Vt *t, int param[], int pcount)
-{
- Buffer *b = t->buffer;
- Row *row = b->curs_row;
- int n = (pcount && param[0] > 0) ? param[0] : 1;
-
- if (b->curs_col + n > b->cols)
- n = b->cols - b->curs_col;
-
- for (int i = b->curs_col; i < b->cols - n; i++)
- row->cells[i] = row->cells[i + n];
-
- row_set(row, b->cols - n, n, b);
-}
-
-/* Interpret an 'insert line' sequence (IL) */
-static
-void
-interpret_csi_il(Vt *t, int param[], int pcount)
-{
- Buffer *b = t->buffer;
- int n = (pcount && param[0] > 0) ? param[0] : 1;
-
- if (b->curs_row + n >= b->scroll_bot) {
- for (Row *row = b->curs_row; row < b->scroll_bot; row++)
- row_set(row, 0, b->cols, b);
- } else {
- row_roll(b->curs_row, b->scroll_bot, -n);
- for (Row *row = b->curs_row; row < b->curs_row + n; row++)
- row_set(row, 0, b->cols, b);
- }
-}
-
-/* Interpret a 'delete line' sequence (DL) */
-static
-void
-interpret_csi_dl(Vt *t, int param[], int pcount)
-{
- Buffer *b = t->buffer;
- int n = (pcount && param[0] > 0) ? param[0] : 1;
-
- if (b->curs_row + n >= b->scroll_bot) {
- for (Row *row = b->curs_row; row < b->scroll_bot; row++)
- row_set(row, 0, b->cols, b);
- } else {
- row_roll(b->curs_row, b->scroll_bot, n);
- for (Row *row = b->scroll_bot - n; row < b->scroll_bot; row++)
- row_set(row, 0, b->cols, b);
- }
-}
-
-/* Interpret an 'erase characters' (ECH) sequence */
-static
-void
-interpret_csi_ech(Vt *t, int param[], int pcount)
-{
- Buffer *b = t->buffer;
- int n = (pcount && param[0] > 0) ? param[0] : 1;
-
- if (b->curs_col + n > b->cols)
- n = b->cols - b->curs_col;
-
- row_set(b->curs_row, b->curs_col, n, b);
-}
-
-/* Interpret a 'set scrolling region' (DECSTBM) sequence */
-static
-void
-interpret_csi_decstbm(Vt *t, int param[], int pcount)
-{
- Buffer *b = t->buffer;
- int new_top, new_bot;
-
- switch (pcount) {
- case 0:
- b->scroll_top = b->lines;
- b->scroll_bot = b->lines + b->rows;
- break;
- case 2:
- new_top = param[0] - 1;
- new_bot = param[1];
-
- /* clamp to bounds */
- if (new_top < 0)
- new_top = 0;
- if (new_top >= b->rows)
- new_top = b->rows - 1;
- if (new_bot < 0)
- new_bot = 0;
- if (new_bot >= b->rows)
- new_bot = b->rows;
-
- /* check for range validity */
- if (new_top < new_bot) {
- b->scroll_top = b->lines + new_top;
- b->scroll_bot = b->lines + new_bot;
- }
- break;
- default:
- return; /* malformed */
- }
- b->curs_row = b->scroll_top;
- b->curs_col = 0;
-}
-
-static
-void
-interpret_csi_mode(Vt *t, int param[], int pcount, bool set)
-{
- for (int i = 0; i < pcount; i++) {
- switch (param[i]) {
- case 4: /* insert/replace mode */
- t->insert = set;
- break;
- }
- }
-}
-
-static
-void
-interpret_csi_priv_mode(Vt *t, int param[], int pcount, bool set)
-{
- for (int i = 0; i < pcount; i++) {
- switch (param[i]) {
- case 1: /* set application/normal cursor key mode (DECCKM) */
- t->curskeymode = set;
- break;
- case 6: /* set origin to relative/absolute (DECOM) */
- t->relposmode = set;
- break;
- case 25: /* make cursor visible/invisible (DECCM) */
- t->curshid = !set;
- break;
- case 1049: /* combine 1047 + 1048 */
- case 47: /* use alternate/normal screen buffer */
- case 1047:
- if (!set)
- buffer_clear(&t->buffer_alternate);
- t->buffer = set ? &t->buffer_alternate : &t->buffer_normal;
- vt_dirty(t);
- if (param[i] != 1049)
- break;
- /* fall through */
- case 1048: /* save/restore cursor */
- if (set)
- cursor_save(t);
- else
- cursor_restore(t);
- break;
- case 1000: /* enable/disable normal mouse tracking */
- t->mousetrack = set;
- break;
- }
- }
-}
-
-static
-void
-interpret_csi(Vt *t)
-{
- Buffer *b = t->buffer;
- int csiparam[16];
- uint param_count = 0;
- const char *p = t->ebuf + 1;
- char verb = t->ebuf[t->elen - 1];
-
- /* parse numeric parameters */
- for (p += (t->ebuf[1] == '?'); *p; p++) {
- if (IS_CONTROL(*p)) {
- process_nonprinting(t, *p);
- } else if (*p == ';') {
- if (param_count >= arrlen(csiparam))
- return; /* too long! */
- csiparam[param_count++] = 0;
- } else if (isdigit((uchar)*p)) {
- if (param_count == 0)
- csiparam[param_count++] = 0;
- csiparam[param_count - 1] *= 10;
- csiparam[param_count - 1] += *p - '0';
- }
- }
-
- if (t->ebuf[1] == '?') {
- switch (verb) {
- case 'h':
- case 'l': /* private set/reset mode */
- interpret_csi_priv_mode(t, csiparam, param_count, verb == 'h');
- break;
- }
- return;
- }
-
- /* delegate handling depending on command character (verb) */
- switch (verb) {
- case 'h':
- case 'l': /* set/reset mode */
- interpret_csi_mode(t, csiparam, param_count, verb == 'h');
- break;
- case 'm': /* set attribute */
- interpret_csi_sgr(t, csiparam, param_count);
- break;
- case 'J': /* erase display */
- interpret_csi_ed(t, csiparam, param_count);
- break;
- case 'H':
- case 'f': /* move cursor */
- interpret_csi_cup(t, csiparam, param_count);
- break;
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'e':
- case 'a':
- case 'd':
- case '`': /* relative move */
- interpret_csi_c(t, verb, csiparam, param_count);
- break;
- case 'K': /* erase line */
- interpret_csi_el(t, csiparam, param_count);
- break;
- case '@': /* insert characters */
- interpret_csi_ich(t, csiparam, param_count);
- break;
- case 'P': /* delete characters */
- interpret_csi_dch(t, csiparam, param_count);
- break;
- case 'L': /* insert lines */
- interpret_csi_il(t, csiparam, param_count);
- break;
- case 'M': /* delete lines */
- interpret_csi_dl(t, csiparam, param_count);
- break;
- case 'X': /* erase chars */
- interpret_csi_ech(t, csiparam, param_count);
- break;
- case 'S': /* SU: scroll up */
- vt_scroll(t, param_count ? -csiparam[0] : -1);
- break;
- case 'T': /* SD: scroll down */
- vt_scroll(t, param_count ? csiparam[0] : 1);
- break;
- case 'Z': /* CBT: cursor backward tabulation */
- puttab(t, param_count ? -csiparam[0] : -1);
- break;
- case 'g': /* TBC: tabulation clear */
- switch (param_count ? csiparam[0] : 0) {
- case 0:
- b->tabs[b->curs_col] = false;
- break;
- case 3:
- memset(b->tabs, 0, sizeof(*b->tabs) * b->maxcols);
- break;
- }
- break;
- case 'r': /* set scrolling region */
- interpret_csi_decstbm(t, csiparam, param_count);
- break;
- case 's': /* save cursor location */
- cursor_save(t);
- break;
- case 'u': /* restore cursor location */
- cursor_restore(t);
- break;
- case 'n': /* query cursor location */
- if (param_count == 1 && csiparam[0] == 6)
- send_curs(t);
- break;
- default:
- break;
- }
-}
-
-/* Interpret an 'index' (IND) sequence */
-static
-void
-interpret_csi_ind(Vt *t)
-{
- Buffer *b = t->buffer;
- if (b->curs_row < b->lines + b->rows - 1)
- b->curs_row++;
-}
-
-/* Interpret a 'reverse index' (RI) sequence */
-static
-void
-interpret_csi_ri(Vt *t)
-{
- Buffer *b = t->buffer;
- if (b->curs_row > b->scroll_top)
- b->curs_row--;
- else {
- row_roll(b->scroll_top, b->scroll_bot, -1);
- row_set(b->scroll_top, 0, b->cols, b);
- }
-}
-
-/* Interpret a 'next line' (NEL) sequence */
-static
-void
-interpret_csi_nel(Vt *t)
-{
- Buffer *b = t->buffer;
- if (b->curs_row < b->lines + b->rows - 1) {
- b->curs_row++;
- b->curs_col = 0;
- }
-}
-
-/* Interpret a 'select character set' (SCS) sequence */
-static
-void
-interpret_csi_scs(Vt *t)
-{
- /* ESC ( sets G0, ESC ) sets G1 */
- t->charsets[!!(t->ebuf[0] == ')')] = (t->ebuf[1] == '0');
- t->graphmode = t->charsets[0];
-}
-
-/* Interpret an 'operating system command' (OSC) sequence */
-static
-void
-interpret_osc(Vt *t)
-{
- /* ESC ] command ; data BEL
- * ESC ] command ; data ESC \\
- * Note that BEL or ESC \\ have already been replaced with NUL.
- */
- char *data = nil;
- int command = strtoul(t->ebuf + 1, &data, 10);
- if (data && *data == ';') {
- switch (command) {
- case 0: /* icon name and window title */
- case 2: /* window title */
- if (t->title_handler)
- t->title_handler(t, data+1);
- break;
- case 1: /* icon name */
- break;
- default:
-#ifndef NDEBUG
- fprintf(stderr, "unknown OSC command: %d\n", command);
-#endif
- break;
- }
- }
-}
-
-static
-void
-try_interpret_escape_seq(Vt *t)
-{
- char lastchar = t->ebuf[t->elen - 1];
-
- if (!*t->ebuf)
- return;
-
- switch (*t->ebuf) {
- case '#': /* ignore DECDHL, DECSWL, DECDWL, DECHCP, DECFPP */
- if (t->elen == 2) {
- if (lastchar == '8') { /* DECALN */
- interpret_csi_ed(t, (int []){ 2 }, 1);
- goto handled;
- }
- goto cancel;
- }
- break;
- case '(':
- case ')':
- if (t->elen == 2) {
- interpret_csi_scs(t);
- goto handled;
- }
- break;
- case ']': /* OSC - operating system command */
- if (lastchar == '\a' ||
- (lastchar == '\\' && t->elen >= 2 && t->ebuf[t->elen - 2] == '\e')) {
- t->elen -= lastchar == '\a' ? 1 : 2;
- t->ebuf[t->elen] = '\0';
- interpret_osc(t);
- goto handled;
- }
- break;
- case '[': /* CSI - control sequence introducer */
- if (is_valid_csi_ender(lastchar)) {
- interpret_csi(t);
- goto handled;
- }
- break;
- case '7': /* DECSC: save cursor and attributes */
- attributes_save(t);
- cursor_save(t);
- goto handled;
- case '8': /* DECRC: restore cursor and attributes */
- attributes_restore(t);
- cursor_restore(t);
- goto handled;
- case 'D': /* IND: index */
- interpret_csi_ind(t);
- goto handled;
- case 'M': /* RI: reverse index */
- interpret_csi_ri(t);
- goto handled;
- case 'E': /* NEL: next line */
- interpret_csi_nel(t);
- goto handled;
- case 'H': /* HTS: horizontal tab set */
- t->buffer->tabs[t->buffer->curs_col] = true;
- goto handled;
- default:
- goto cancel;
- }
-
- if (t->elen + 1 >= sizeof(t->ebuf)) {
-cancel:
-#ifndef NDEBUG
- fprintf(stderr, "cancelled: \\033");
- for (uint i = 0; i < t->elen; i++) {
- if (isprint(t->ebuf[i])) {
- fputc(t->ebuf[i], stderr);
- } else {
- fprintf(stderr, "\\%03o", t->ebuf[i]);
- }
- }
- fputc('\n', stderr);
-#endif
-handled:
- cancel_escape_sequence(t);
- }
-}
-
-static
-void
-puttab(Vt *t, int count)
-{
- Buffer *b = t->buffer;
- int direction = count >= 0 ? 1 : -1;
- for (int col = b->curs_col + direction; count; col += direction) {
- if (col < 0) {
- b->curs_col = 0;
- break;
- }
- if (col >= b->cols) {
- b->curs_col = b->cols - 1;
- break;
- }
- if (b->tabs[col]) {
- b->curs_col = col;
- count -= direction;
- }
- }
-}
-
-static
-void
-process_nonprinting(Vt *t, wchar_t wc)
-{
- Buffer *b = t->buffer;
- switch (wc) {
- case '\e': /* ESC */
- new_escape_sequence(t);
- break;
- case '\a': /* BEL */
- if (t->urgent_handler)
- t->urgent_handler(t);
- break;
- case '\b': /* BS */
- if (b->curs_col > 0)
- b->curs_col--;
- break;
- case '\t': /* HT */
- puttab(t, 1);
- break;
- case '\r': /* CR */
- b->curs_col = 0;
- break;
- case '\v': /* VT */
- case '\f': /* FF */
- case '\n': /* LF */
- cursor_line_down(t);
- break;
- case '\016': /* SO: shift out, invoke the G1 character set */
- t->graphmode = t->charsets[1];
- break;
- case '\017': /* SI: shift in, invoke the G0 character set */
- t->graphmode = t->charsets[0];
- break;
- }
-}
-
-static
-void
-is_utf8_locale(void)
-{
- const char *cset = nl_langinfo(CODESET);
- if (!cset)
- cset = "ANSI_X3.4-1968";
- is_utf8 = !strcmp(cset, "UTF-8");
-}
-
-static
-wchar_t
-get_vt100_graphic(char c)
-{
- static char vt100_acs[] = "`afgjklmnopqrstuvwxyz{|}~";
-
- /*
- * 5f-7e standard vt100
- * 40-5e rxvt extension for extra curses acs chars
- */
- static uint16_t const vt100_utf8[62] = {
- 0x2191, 0x2193, 0x2192, 0x2190, 0x2588, 0x259a, 0x2603, // 41-47
- 0, 0, 0, 0, 0, 0, 0, 0, // 48-4f
- 0, 0, 0, 0, 0, 0, 0, 0, // 50-57
- 0, 0, 0, 0, 0, 0, 0, 0x0020, // 58-5f
- 0x25c6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0, 0x00b1, // 60-67
- 0x2424, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, 0x23ba, // 68-6f
- 0x23bb, 0x2500, 0x23bc, 0x23bd, 0x251c, 0x2524, 0x2534, 0x252c, // 70-77
- 0x2502, 0x2264, 0x2265, 0x03c0, 0x2260, 0x00a3, 0x00b7, // 78-7e
- };
-
- if (is_utf8)
- return vt100_utf8[c - 0x41];
- else if (strchr(vt100_acs, c))
- return NCURSES_ACS(c);
- return '\0';
-}
-
-static
-void
-put_wc(Vt *t, wchar_t wc)
-{
- int width = 0;
-
- if (!t->seen_input) {
- t->seen_input = 1;
- kill(-t->pid, SIGWINCH);
- }
-
- if (t->escaped) {
- if (t->elen + 1 < sizeof(t->ebuf)) {
- t->ebuf[t->elen] = wc;
- t->ebuf[++t->elen] = '\0';
- try_interpret_escape_seq(t);
- } else {
- cancel_escape_sequence(t);
- }
- } else if (IS_CONTROL(wc)) {
- process_nonprinting(t, wc);
- } else {
- if (t->graphmode) {
- if (wc >= 0x41 && wc <= 0x7e) {
- wchar_t gc = get_vt100_graphic(wc);
- if (gc)
- wc = gc;
- }
- width = 1;
- } else if ((width = wcwidth(wc)) < 1) {
- width = 1;
- }
- Buffer *b = t->buffer;
- Cell blank_cell = { L'\0', build_attrs(b->curattrs), b->curfg, b->curbg };
- if (width == 2 && b->curs_col == b->cols - 1) {
- b->curs_row->cells[b->curs_col++] = blank_cell;
- b->curs_row->dirty = true;
- }
-
- if (b->curs_col >= b->cols) {
- b->curs_col = 0;
- cursor_line_down(t);
- }
-
- if (t->insert) {
- Cell *src = b->curs_row->cells + b->curs_col;
- Cell *dest = src + width;
- size_t len = b->cols - b->curs_col - width;
- memmove(dest, src, len * sizeof *dest);
- }
-
- b->curs_row->cells[b->curs_col] = blank_cell;
- b->curs_row->cells[b->curs_col++].text = wc;
- b->curs_row->dirty = true;
- if (width == 2)
- b->curs_row->cells[b->curs_col++] = blank_cell;
- }
-}
-
-int
-vt_process(Vt *t)
-{
- int res;
- uint pos = 0;
- mbstate_t ps;
- memset(&ps, 0, sizeof(ps));
-
- if (t->pty < 0) {
- errno = EINVAL;
- return -1;
- }
-
- /* read from the pty */
- res = read(t->pty, t->rbuf + t->rlen, sizeof(t->rbuf) - t->rlen);
- if (res < 0)
- return -1;
-
- /* process the bytes you read */
- t->rlen += res;
- while (pos < t->rlen) {
- wchar_t wc;
- ssize_t len;
-
- len = (ssize_t)mbrtowc(&wc, t->rbuf + pos, t->rlen - pos, &ps);
- if (len == -2) {
- t->rlen -= pos;
- memmove(t->rbuf, t->rbuf + pos, t->rlen);
- return 0;
- }
-
- if (len == -1) {
- len = 1;
- wc = t->rbuf[pos];
- }
-
- pos += len ? len : 1;
- put_wc(t, wc);
- }
-
- t->rlen -= pos;
- memmove(t->rbuf, t->rbuf + pos, t->rlen);
- return 0;
-}
-
-void
-vt_default_colors_set(Vt *t, attr_t attrs, short fg, short bg)
-{
- t->defattrs = attrs;
- t->deffg = fg;
- t->defbg = bg;
-}
-
-Vt *
-vt_create(int rows, int cols, int scroll_size)
-{
- if (rows <= 0 || cols <= 0)
- return nil;
-
- Vt *t = calloc(1, sizeof(Vt));
- if (!t)
- return nil;
-
- t->pty = -1;
- t->deffg = t->defbg = -1;
- t->buffer = &t->buffer_normal;
-
- if (!buffer_init(&t->buffer_normal, rows, cols, scroll_size) ||
- !buffer_init(&t->buffer_alternate, rows, cols, 0)) {
- free(t);
- return nil;
- }
-
- return t;
-}
-
-void
-vt_resize(Vt *t, int rows, int cols)
-{
- struct winsize ws = { .ws_row = rows, .ws_col = cols };
-
- if (rows <= 0 || cols <= 0)
- return;
-
- vt_noscroll(t);
- buffer_resize(&t->buffer_normal, rows, cols);
- buffer_resize(&t->buffer_alternate, rows, cols);
- cursor_clamp(t);
- ioctl(t->pty, TIOCSWINSZ, &ws);
- kill(-t->pid, SIGWINCH);
-}
-
-void
-vt_destroy(Vt *t)
-{
- if (!t)
- return;
- buffer_free(&t->buffer_normal);
- buffer_free(&t->buffer_alternate);
- close(t->pty);
- free(t);
-}
-
-void
-vt_dirty(Vt *t)
-{
- Buffer *b = t->buffer;
- for (Row *row = b->lines, *end = row + b->rows; row < end; row++)
- row->dirty = true;
-}
-
-void
-vt_draw(Vt *t, WINDOW *win, int srow, int scol)
-{
- Buffer *b = t->buffer;
-
- if (srow != t->srow || scol != t->scol) {
- vt_dirty(t);
- t->srow = srow;
- t->scol = scol;
- }
-
- for (int i = 0; i < b->rows; i++) {
- Row *row = b->lines + i;
-
- if (!row->dirty)
- continue;
-
- wmove(win, srow + i, scol);
- Cell *cell = nil;
- for (int j = 0; j < b->cols; j++) {
- Cell *prev_cell = cell;
- cell = row->cells + j;
- if (!prev_cell || cell->attr != prev_cell->attr
- || cell->fg != prev_cell->fg
- || cell->bg != prev_cell->bg) {
- if (cell->attr == A_NORMAL)
- cell->attr = t->defattrs;
- if (cell->fg == -1)
- cell->fg = t->deffg;
- if (cell->bg == -1)
- cell->bg = t->defbg;
- wattrset(win, cell->attr << NCURSES_ATTR_SHIFT);
- wcolor_set(win, vt_color_get(t, cell->fg, cell->bg), nil);
- }
-
- if (is_utf8 && cell->text >= 128) {
- char buf[MB_CUR_MAX + 1];
- size_t len = wcrtomb(buf, cell->text, nil);
- if (len > 0) {
- waddnstr(win, buf, len);
- if (wcwidth(cell->text) > 1)
- j++;
- }
- } else {
- waddch(win, cell->text > ' ' ? cell->text : ' ');
- }
- }
-
- int x, y;
- getyx(win, y, x);
- (void)y;
- if (x && x < b->cols - 1)
- whline(win, ' ', b->cols - x);
-
- row->dirty = false;
- }
-
- wmove(win, srow + b->curs_row - b->lines, scol + b->curs_col);
-}
-
-void
-vt_scroll(Vt *t, int rows)
-{
- Buffer *b = t->buffer;
- if (!b->scroll_size)
- return;
- if (rows < 0) { /* scroll back */
- if (rows < -b->scroll_above)
- rows = -b->scroll_above;
- } else { /* scroll forward */
- if (rows > b->scroll_below)
- rows = b->scroll_below;
- }
- buffer_scroll(b, rows);
- b->scroll_below -= rows;
-}
-
-void
-vt_noscroll(Vt *t)
-{
- int scroll_below = t->buffer->scroll_below;
- if (scroll_below)
- vt_scroll(t, scroll_below);
-}
-
-pid_t
-vt_forkpty(Vt *t, const char *p, const char *argv[], const char *cwd, const char *env[], int *to, int *from)
-{
- int vt2ed[2], ed2vt[2];
- struct winsize ws;
- ws.ws_row = t->buffer->rows;
- ws.ws_col = t->buffer->cols;
- ws.ws_xpixel = ws.ws_ypixel = 0;
-
- if (to && pipe(vt2ed)) {
- *to = -1;
- to = nil;
- }
- if (from && pipe(ed2vt)) {
- *from = -1;
- from = nil;
- }
-
- pid_t pid = forkpty(&t->pty, nil, nil, &ws);
- if (pid < 0)
- return -1;
-
- if (pid == 0) {
- setsid();
-
- sigset_t emptyset;
- sigemptyset(&emptyset);
- sigprocmask(SIG_SETMASK, &emptyset, nil);
-
- if (to) {
- close(vt2ed[1]);
- dup2(vt2ed[0], STDIN_FILENO);
- close(vt2ed[0]);
- }
-
- if (from) {
- close(ed2vt[0]);
- dup2(ed2vt[1], STDOUT_FILENO);
- close(ed2vt[1]);
- }
-
- int maxfd = sysconf(_SC_OPEN_MAX);
- for (int fd = 3; fd < maxfd; fd++)
- if (close(fd) == -1 && errno == EBADF)
- break;
-
- for (const char **envp = env; envp && envp[0]; envp += 2)
- setenv(envp[0], envp[1], 1);
- setenv("TERM", vt_term, 1);
-
- if (cwd)
- chdir(cwd);
-
- execvp(p, (char *const *)argv);
- fprintf(stderr, "\nexecv() failed.\nCommand: '%s'\n", argv[0]);
- exit(1);
- }
-
- if (to) {
- close(vt2ed[0]);
- *to = vt2ed[1];
- }
-
- if (from) {
- close(ed2vt[1]);
- *from = ed2vt[0];
- }
-
- return t->pid = pid;
-}
-
-int
-vt_pty_get(Vt *t)
-{
- return t->pty;
-}
-
-ssize_t
-vt_write(Vt *t, const char *buf, size_t len)
-{
- ssize_t ret = len;
-
- while (len > 0) {
- ssize_t res = write(t->pty, buf, len);
- if (res < 0) {
- if (errno != EAGAIN && errno != EINTR)
- return -1;
- continue;
- }
- buf += res;
- len -= res;
- }
-
- return ret;
-}
-
-static
-void
-send_curs(Vt *t)
-{
- Buffer *b = t->buffer;
- char keyseq[16];
- snprintf(keyseq, sizeof keyseq, "\e[%d;%dR", (int)(b->curs_row - b->lines), b->curs_col);
- vt_write(t, keyseq, strlen(keyseq));
-}
-
-void
-vt_keypress(Vt *t, int keycode)
-{
- vt_noscroll(t);
-
- if (keycode >= 0 && keycode <= KEY_MAX && keytable[keycode]) {
- switch (keycode) {
- case KEY_UP:
- case KEY_DOWN:
- case KEY_RIGHT:
- case KEY_LEFT: {
- char keyseq[3] = { '\e', (t->curskeymode ? 'O' : '['), keytable[keycode][0] };
- vt_write(t, keyseq, sizeof keyseq);
- break;
- }
- default:
- vt_write(t, keytable[keycode], strlen(keytable[keycode]));
- }
- } else if (keycode <= UCHAR_MAX) {
- char c = keycode;
- vt_write(t, &c, 1);
- } else {
-#ifndef NDEBUG
- fprintf(stderr, "unhandled key %#o\n", keycode);
-#endif
- }
-}
-
-void
-vt_mouse(Vt *t, int x, int y, mmask_t mask)
-{
-#ifdef NCURSES_MOUSE_VERSION
- char seq[6] = { '\e', '[', 'M' }, state = 0, button = 0;
-
- if (!t->mousetrack)
- return;
-
- if (mask & (BUTTON1_PRESSED | BUTTON1_CLICKED))
- button = 0;
- else if (mask & (BUTTON2_PRESSED | BUTTON2_CLICKED))
- button = 1;
- else if (mask & (BUTTON3_PRESSED | BUTTON3_CLICKED))
- button = 2;
- else if (mask & (BUTTON1_RELEASED | BUTTON2_RELEASED | BUTTON3_RELEASED))
- button = 3;
-
- if (mask & BUTTON_SHIFT)
- state |= 4;
- if (mask & BUTTON_ALT)
- state |= 8;
- if (mask & BUTTON_CTRL)
- state |= 16;
-
- seq[3] = 32 + button + state;
- seq[4] = 32 + x;
- seq[5] = 32 + y;
-
- vt_write(t, seq, sizeof seq);
-
- if (mask & (BUTTON1_CLICKED | BUTTON2_CLICKED | BUTTON3_CLICKED)) {
- /* send a button release event */
- button = 3;
- seq[3] = 32 + button + state;
- vt_write(t, seq, sizeof seq);
- }
-#endif /* NCURSES_MOUSE_VERSION */
-}
-
-static
-uint
-color_hash(short fg, short bg)
-{
- if (fg == -1)
- fg = COLORS;
- if (bg == -1)
- bg = COLORS + 1;
- return fg * (COLORS + 2) + bg;
-}
-
-int
-vt_rgb_get(Vt *t, uint8 r, uint8 g, uint8 b)
-{
- return 0;
-}
-
-
-int
-vt_color_get(Vt *t, short fg, short bg)
-{
- if (fg >= COLORS)
- fg = (t ? t->deffg : default_fg);
- if (bg >= COLORS)
- bg = (t ? t->defbg : default_bg);
-
- if (!has_default_colors) {
- if (fg == -1)
- fg = (t && t->deffg != -1 ? t->deffg : default_fg);
- if (bg == -1)
- bg = (t && t->defbg != -1 ? t->defbg : default_bg);
- }
-
- if (!color2palette || (fg == -1 && bg == -1))
- return 0;
- uint index = color_hash(fg, bg);
- if (color2palette[index] == 0) {
- short oldfg, oldbg;
- for (;;) {
- if (++color_pair_current >= color_pairs_max)
- color_pair_current = color_pairs_reserved + 1;
- pair_content(color_pair_current, &oldfg, &oldbg);
- uint old_index = color_hash(oldfg, oldbg);
- if (color2palette[old_index] >= 0) {
- if (init_pair(color_pair_current, fg, bg) == OK) {
- color2palette[old_index] = 0;
- color2palette[index] = color_pair_current;
- }
- break;
- }
- }
- }
-
- int color_pair = color2palette[index];
- return color_pair >= 0 ? color_pair : -color_pair;
-}
-
-int
-vt_color_reserve(short fg, short bg)
-{
- if (!color2palette || fg >= COLORS || bg >= COLORS)
- return 0;
-
- if (!has_default_colors && fg == -1)
- fg = default_fg;
- if (!has_default_colors && bg == -1)
- bg = default_bg;
- if (fg == -1 && bg == -1)
- return 0;
-
- uint index = color_hash(fg, bg);
- if (color2palette[index] >= 0) {
- if (init_pair(color_pairs_reserved + 1, fg, bg) == OK)
- color2palette[index] = -(++color_pairs_reserved);
- }
- int color_pair = color2palette[index];
- return color_pair >= 0 ? color_pair : -color_pair;
-}
-
-int
-vt_rgb_reserve(short fg, short bg)
-{
- if (!color2palette || fg >= COLORS || bg >= COLORS)
- return 0;
-
- if (!has_default_colors && fg == -1)
- fg = default_fg;
- if (!has_default_colors && bg == -1)
- bg = default_bg;
- if (fg == -1 && bg == -1)
- return 0;
-
- uint index = color_hash(fg, bg);
- if (color2palette[index] >= 0) {
- if (init_pair(color_pairs_reserved + 1, fg, bg) == OK)
- color2palette[index] = -(++color_pairs_reserved);
- }
- int color_pair = color2palette[index];
- return color_pair >= 0 ? color_pair : -color_pair;
-}
-
-static
-void
-init_colors(void)
-{
- pair_content(0, &default_fg, &default_bg);
- if (default_fg == -1)
- default_fg = COLOR_WHITE;
- if (default_bg == -1)
- default_bg = COLOR_BLACK;
- has_default_colors = (use_default_colors() == OK);
- color_pairs_max = MIN(MAX_COLOR_PAIRS, SHRT_MAX);
-
- if (COLORS)
- color2palette = calloc((COLORS + 2) * (COLORS + 2), sizeof(int));
- /*
- * XXX: On undefined color-pairs NetBSD curses pair_content() set fg
- * and bg to default colors while ncurses set them respectively to
- * 0 and 0. Initialize all color-pairs in order to have consistent
- * behaviour despite the implementation used.
- */
- for (short i = 1; i < color_pairs_max; i++)
- init_extended_pair(i, 0, 0);
-
- vt_color_reserve(COLOR_WHITE, COLOR_BLACK);
-}
-
-void
-vt_init(void)
-{
- init_colors();
- is_utf8_locale();
- char *term = getenv("DVTM_TERM");
- if (!term)
- term = "dvtm";
-
- snprintf(vt_term, sizeof vt_term, "%s%s", term, COLORS >= 256 ? "-256color" : "");
-}
-
-void
-vt_keytable_set(const char * const keytable_overlay[], int count)
-{
- for (int k = 0; k < count && k < KEY_MAX; k++) {
- const char *keyseq = keytable_overlay[k];
- if (keyseq)
- keytable[k] = keyseq;
- }
-}
-
-void
-vt_shutdown(void)
-{
- free(color2palette);
-}
-
-void
-vt_title_handler_set(Vt *t, vt_title_handler_t handler)
-{
- t->title_handler = handler;
-}
-
-void
-vt_urgent_handler_set(Vt *t, vt_urgent_handler_t handler)
-{
- t->urgent_handler = handler;
-}
-
-void
-vt_data_set(Vt *t, void *data)
-{
- t->data = data;
-}
-
-void *
-vt_data_get(Vt *t)
-{
- return t->data;
-}
-
-bool
-vt_cursor_visible(Vt *t)
-{
- return t->buffer->scroll_below ? false : !t->curshid;
-}
-
-pid_t
-vt_pid_get(Vt *t)
-{
- return t->pid;
-}
-
-size_t
-vt_content_get(Vt *t, char **buf, bool colored)
-{
- Buffer *b = t->buffer;
- int lines = b->scroll_above + b->scroll_below + b->rows + 1;
- size_t size = lines * ((b->cols + 1) * ((colored ? 64 : 0) + MB_CUR_MAX));
- mbstate_t ps;
- memset(&ps, 0, sizeof(ps));
-
- if (!(*buf = malloc(size)))
- return 0;
-
- char *s = *buf;
- Cell *prev_cell = nil;
-
- for (Row *row = buffer_row_first(b); row; row = buffer_row_next(b, row)) {
- size_t len = 0;
- char *last_non_space = s;
- for (int col = 0; col < b->cols; col++) {
- Cell *cell = row->cells + col;
- if (colored) {
- int esclen = 0;
- if (!prev_cell || cell->attr != prev_cell->attr) {
- attr_t attr = cell->attr << NCURSES_ATTR_SHIFT;
- esclen = sprintf(s, "\033[0%s%s%s%s%s%sm",
- attr & A_BOLD ? ";1" : "",
- attr & A_DIM ? ";2" : "",
- attr & A_UNDERLINE ? ";4" : "",
- attr & A_BLINK ? ";5" : "",
- attr & A_REVERSE ? ";7" : "",
- attr & A_INVIS ? ";8" : "");
- if (esclen > 0)
- s += esclen;
- }
- if (!prev_cell || cell->fg != prev_cell->fg || cell->attr != prev_cell->attr) {
- if (cell->fg == -1)
- esclen = sprintf(s, "\033[39m");
- else
- esclen = sprintf(s, "\033[38;5;%dm", cell->fg);
- if (esclen > 0)
- s += esclen;
- }
- if (!prev_cell || cell->bg != prev_cell->bg || cell->attr != prev_cell->attr) {
- if (cell->bg == -1)
- esclen = sprintf(s, "\033[49m");
- else
- esclen = sprintf(s, "\033[48;5;%dm", cell->bg);
- if (esclen > 0)
- s += esclen;
- }
- prev_cell = cell;
- }
- if (cell->text) {
- len = wcrtomb(s, cell->text, &ps);
- if (len > 0)
- s += len;
- last_non_space = s;
- } else if (len) {
- len = 0;
- } else {
- *s++ = ' ';
- }
- }
-
- s = last_non_space;
- *s++ = '\n';
- }
-
- return s - *buf;
-}
-
-int
-vt_content_start(Vt *t)
-{
- return t->buffer->scroll_above;
-}
diff --git a/sys/cmd/dvtm/vt.h b/sys/cmd/dvtm/vt.h
deleted file mode 100644
index dfc94b3..0000000
--- a/sys/cmd/dvtm/vt.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* see LICENSE for details */
-#pragma once
-#include <u.h>
-
-#include <vendor/curses.h>
-#include <stdbool.h>
-#include <sys/types.h>
-
-#ifndef NCURSES_MOUSE_VERSION
-#define mmask_t ulong
-#endif
-
-typedef struct Vt Vt;
-typedef void (*vt_title_handler_t)(Vt*, const char *title);
-typedef void (*vt_urgent_handler_t)(Vt*);
-
-void vt_init(void);
-void vt_shutdown(void);
-
-void vt_keytable_set(char const * const keytable_overlay[], int count);
-void vt_default_colors_set(Vt*, attr_t attrs, short fg, short bg);
-void vt_title_handler_set(Vt*, vt_title_handler_t);
-void vt_urgent_handler_set(Vt*, vt_urgent_handler_t);
-void vt_data_set(Vt*, void *);
-void *vt_data_get(Vt*);
-
-Vt *vt_create(int rows, int cols, int scroll_buf_sz);
-void vt_resize(Vt*, int rows, int cols);
-void vt_destroy(Vt*);
-pid_t vt_forkpty(Vt*, const char *p, const char *argv[], const char *cwd, const char *env[], int *to, int *from);
-int vt_pty_get(Vt*);
-bool vt_cursor_visible(Vt*);
-
-int vt_process(Vt *);
-void vt_keypress(Vt *, int keycode);
-ssize_t vt_write(Vt*, const char *buf, size_t len);
-void vt_mouse(Vt*, int x, int y, mmask_t mask);
-void vt_dirty(Vt*);
-void vt_draw(Vt*, WINDOW *win, int startrow, int startcol);
-int vt_color_get(Vt*, short fg, short bg);
-int vt_color_reserve(short fg, short bg);
-
-void vt_scroll(Vt*, int rows);
-void vt_noscroll(Vt*);
-
-pid_t vt_pid_get(Vt*);
-size_t vt_content_get(Vt*, char **s, bool colored);
-int vt_content_start(Vt*);