jcs
/subtext
/amendments
/37
console: More ANSI support like line insert and delete
jcs made amendment 37 over 2 years ago
--- console.c Wed Dec 15 15:21:23 2021
+++ console.c Thu Dec 23 20:47:51 2021
@@ -31,24 +31,24 @@
#define CONSOLE_PADDING 6
+void console_setup(struct session *session);
+void console_redraw(struct console *console, short force);
+short console_bound(struct console *console);
+void console_parse_csi(struct console *console);
+
struct node_funcs console_node_funcs = {
- NULL,
+ console_setup,
console_input,
console_output,
console_close
};
-void console_redraw(struct console *console, short force);
-short console_bound(struct console *console);
-void console_parse_csi(struct console *console);
-
struct console *
console_init(struct console **cur_console)
{
- char title[64] = { 0 };
+ char title[64];
struct console *console;
- Rect bounds = { 0 };
- Rect data_bounds = { 0, 0, 0, 1 }; /* tlbr */
+ Rect bounds;
short width, height;
console = xmalloczero(sizeof(struct console));
@@ -64,12 +64,12 @@ console_init(struct console **cur_console)
bounds.left = (screenBits.bounds.right - width) / 2;
bounds.right = bounds.left + width;
- bounds.top = ((screenBits.bounds.bottom - height) / 2) +
- (GetMBarHeight());
+ bounds.top = (GetMBarHeight()) +
+ ((screenBits.bounds.bottom - height) / 2);
bounds.bottom = bounds.top + height;
- if (sprintf(title, "%s: console", PROGRAM_NAME) > sizeof(title))
- panic("sprintf overflow!");
+ snprintf(title, sizeof(title), "%s: %s: console", PROGRAM_NAME,
+ db->config.hostname);
CtoPstr(title);
console->win = NewWindow(0L, &bounds, title, false, noGrowDocProc,
@@ -83,7 +83,7 @@ console_init(struct console **cur_console)
console->session = session_create("console", "console",
&console_node_funcs);
console->session->cookie = (void *)console;
- console->session->ansi = 1;
+ console->session->vt100 = 1;
console->session->cp437 = 1;
console->session->tspeed = 19200;
strlcpy(console->session->autologin_username, "sysop",
@@ -98,6 +98,14 @@ console_init(struct console **cur_console)
}
void
+console_setup(struct session *session)
+{
+ struct console *console = (struct console *)session->cookie;
+ session->terminal_cols = console->ncolumns;
+ session->terminal_rows = console->nlines;
+}
+
+void
console_close(struct session *session)
{
struct console *console = (struct console *)session->cookie;
@@ -259,7 +267,7 @@ console_bound(struct console *console)
short n;
#endif
- while (console->cursor_column >= console->ncolumns) {
+ while (console->cursor_column > console->ncolumns) {
console->cursor_line++;
console->cursor_column -= console->ncolumns;
}
@@ -344,20 +352,22 @@ console_redraw(struct console *console, short force)
cursor.right = cursor.left + FONT_WIDTH;
cursor.bottom = cursor.top + FONT_HEIGHT;
FillRect(&cursor, white);
-
- MoveTo(cursor.left, cursor.top + FONT_HEIGHT - 2);
- if (cbold != (console->attrs[cell] & ATTR_BOLD)) {
- if (console->attrs[cell] & ATTR_BOLD)
- TextFace(thePort->txFace | bold);
- else
- TextFace(thePort->txFace & ~bold);
-
- cbold = console->attrs[cell] & ATTR_BOLD;
+ if (console->chars[cell] != ' ') {
+ MoveTo(cursor.left, cursor.top + FONT_HEIGHT - 2);
+
+ if (cbold != (console->attrs[cell] & ATTR_BOLD)) {
+ if (console->attrs[cell] & ATTR_BOLD)
+ TextFace(thePort->txFace | bold);
+ else
+ TextFace(thePort->txFace & ~bold);
+
+ cbold = console->attrs[cell] & ATTR_BOLD;
+ }
+
+ DrawChar(console->chars[cell]);
}
- DrawChar(console->chars[cell]);
-
if (console->attrs[cell] & ATTR_REVERSE)
InvertRect(&cursor);
if (console->attrs[cell] & ATTR_CURSOR)
@@ -379,6 +389,7 @@ console_parse_csi(struct console *console)
short serviced = 0;
short param1 = -1, param2 = -1;
short parambuflen;
+ short start, count;
char parambuf[4];
unsigned char c;
@@ -398,8 +409,11 @@ console_parse_csi(struct console *console)
case 'E':
case 'F':
case 'G':
+ case 'I':
case 'J':
case 'K':
+ case 'L':
+ case 'M':
case 'S':
case 'T':
case 'd':
@@ -468,38 +482,30 @@ console_parse_csi(struct console *console)
switch (c) {
case 'A': /* CUU - cursor up, stop at top of screen */
- for (x = 0; x < param1 && console->cursor_line > 0; x++)
- console->cursor_line--;
+ console->cursor_line = MAX(0, console->cursor_line - param1);
break;
case 'B': /* CUD - cursor down, stop at bottom of screen */
- for (x = 0; x < param1 &&
- console->cursor_line < console->nlines - 1; x++)
- console->cursor_line++;
+ console->cursor_line = MIN(console->nlines - 1,
+ console->cursor_line + param1);
break;
case 'C': /* CUF - cursor forward, stop at screen edge */
- for (x = 0; x < param1 &&
- console->cursor_column < console->ncolumns - 1; x++)
- console->cursor_column++;
+ console->cursor_column = MIN(console->ncolumns - 1,
+ console->cursor_column + param1);
break;
case 'D': /* CUB - cursor back, stop at left edge of screen */
- for (x = 0; x < param1 && console->cursor_column > 0; x++)
- console->cursor_column--;
+ console->cursor_column = MAX(0, console->cursor_column - param1);
break;
case 'E': /* CNL - cursor next line */
console->cursor_column = 0;
- for (x = 0; x < param1 &&
- console->cursor_line < console->nlines - 1; x++)
- console->cursor_line++;
+ console->cursor_line = MAX(console->nlines - 1,
+ console->cursor_line + param1);
break;
case 'F': /* CPL - cursor previous line */
console->cursor_column = 0;
- for (x = 0; x < param1 && console->cursor_line > 0; x++)
- console->cursor_line--;
+ console->cursor_line = MAX(0, console->cursor_line - param1);
break;
case 'G': /* CHA - cursor horizontal absolute */
- if (param1 > console->ncolumns)
- param1 = console->ncolumns;
- console->cursor_column = param1;
+ console->cursor_column = BOUND(param1, 0, console->ncolumns - 1);
break;
case 'H': /* CUP - cursor absolute position */
case 'f': /* HVP - horizontal vertical position */
@@ -520,47 +526,30 @@ console_parse_csi(struct console *console)
case 'J': /* ED - erase in display */
switch (param1) {
case 0:
- /* clear from cursor to end of screen */
- for (y = console->cursor_line; y < console->nlines; y++) {
- for (x = 0; x < console->ncolumns; x++) {
- if (y == console->cursor_line &&
- x < console->cursor_column)
- continue;
-
- cursor = (y * console->ncolumns) + x;
- console->chars[cursor] = ' ';
- console->attrs[cursor] = console->cur_attr | ATTR_DIRTY;
- }
- }
+ /* clear from cursor (inclusive) to end of screen */
+ start = (console->cursor_line * console->ncolumns) +
+ console->cursor_column;
+ count = (console->ncolumns * console->nlines) - start;
+ memset(console->chars + start, ' ', count);
+ memset(console->attrs + start, console->cur_attr | ATTR_DIRTY,
+ count);
break;
case 1:
/* clear from cursor to beginning of the screen */
- for (y = console->cursor_line; y >= 0; y--) {
- for (x = console->ncolumns; x >= 0; x--) {
- if (y == console->cursor_line &&
- x > console->cursor_column)
- continue;
-
- cursor = (y * console->ncolumns) + x;
- console->chars[cursor] = ' ';
- console->attrs[cursor] = console->cur_attr | ATTR_DIRTY;
- }
- }
+ count = (console->cursor_line * console->ncolumns) +
+ console->cursor_column;
+ memset(console->chars, ' ', count);
+ memset(console->attrs, console->cur_attr | ATTR_DIRTY, count);
break;
case 2:
/* clear entire screen, mark everything clean */
- cursor = 0;
- for (y = 0; y < console->nlines; y++) {
- for (x = 0; x < console->ncolumns; x++) {
- console->chars[cursor] = ' ';
- console->attrs[cursor] = console->cur_attr;
- cursor++;
- }
- }
-
+ count = console->ncolumns * console->nlines;
+ memset(console->chars, ' ', count);
+ memset(console->attrs, console->cur_attr | ATTR_DIRTY, count);
+
/* and then quickly clear the screen */
- console_bound(console);
- console_redraw(console, CONSOLE_CLEAR_SCREEN);
+ //console_bound(console);
+ //console_redraw(console, CONSOLE_CLEAR_SCREEN);
break;
}
break;
@@ -568,34 +557,84 @@ console_parse_csi(struct console *console)
switch (param1) {
case 0:
/* clear from cursor to end of line */
- if (console->cursor_column >= console->ncolumns)
- break;
- for (x = console->cursor_column; x < console->ncolumns; x++) {
- cursor = (console->cursor_line * console->ncolumns) + x;
- console->chars[cursor] = ' ';
- console->attrs[cursor] = console->cur_attr | ATTR_DIRTY;
- }
+ start = (console->cursor_line * console->ncolumns) +
+ console->cursor_column;
+ count = console->ncolumns - console->cursor_column;
+ memset(console->chars + start, ' ', count);
+ memset(console->attrs + start, console->cur_attr | ATTR_DIRTY,
+ count);
break;
case 1:
/* clear from cursor to beginning of line */
- if (console->cursor_column == 0)
- break;
- for (x = console->cursor_column; x >= 0; x--) {
- cursor = (console->cursor_line * console->ncolumns) + x;
- console->chars[cursor] = ' ';
- console->attrs[cursor] = console->cur_attr | ATTR_DIRTY;
- }
+ start = (console->cursor_line * console->ncolumns);
+ count = console->ncolumns - console->cursor_column;
+ memset(console->chars + start, ' ', count);
+ memset(console->attrs + start, console->cur_attr | ATTR_DIRTY,
+ count);
break;
case 2:
/* clear entire line */
- for (x = 0; x < console->ncolumns - 1; x++) {
- cursor = (console->cursor_line * console->ncolumns) + x;
- console->chars[cursor] = ' ';
- console->attrs[cursor] = console->cur_attr | ATTR_DIRTY;
- }
+ start = (console->cursor_line * console->ncolumns);
+ count = console->ncolumns;
+ memset(console->chars + start, ' ', count);
+ memset(console->attrs + start, console->cur_attr | ATTR_DIRTY,
+ count);
break;
}
break;
+ case 'L': /* IL - insert line */
+ param1 = BOUND(param1, 0, console->nlines - console->cursor_line);
+ if (param1 == 0)
+ break;
+ if (console->cursor_line != console->nlines - 1) {
+ /* move remaining lines down */
+ count = console->ncolumns *
+ (console->nlines - console->cursor_line - param1);
+ memmove(console->chars +
+ ((console->cursor_line + param1) * console->ncolumns),
+ console->chars +
+ (console->cursor_line * console->ncolumns),
+ count);
+ memmove(console->attrs +
+ ((console->cursor_line + param1) * console->ncolumns),
+ console->attrs +
+ (console->cursor_line * console->ncolumns),
+ count);
+ }
+ /* clear new lines at cursor line */
+ start = console->ncolumns * console->cursor_line;
+ count = console->ncolumns * param1;
+ memset(console->chars + start, ' ', count);
+ memset(console->attrs + start, console->cur_attr, count);
+ /* mark all of that dirty */
+ count = start + (console->ncolumns *
+ (console->nlines - console->cursor_line));
+ for (x = start; x < count; x++)
+ console->attrs[x] |= ATTR_DIRTY;
+ break;
+ case 'M': /* DL - delete line */
+ param1 = BOUND(param1, 0, console->nlines - console->cursor_line);
+ if (param1 == 0)
+ break;
+ start = console->cursor_line * console->ncolumns;
+ count = console->ncolumns *
+ (console->nlines - console->cursor_line - param1);
+ memmove(console->chars + start, console->chars + start +
+ console->ncolumns, count);
+ memmove(console->attrs + start, console->attrs + start +
+ console->ncolumns, count);
+ /* fill in new blank lines at the end */
+ start += count;
+ count = param1 * console->ncolumns;
+ memset(console->chars + start, ' ', count);
+ memset(console->attrs + start, console->cur_attr, count);
+ /* mark all of that dirty */
+ start = console->cursor_line * console->ncolumns;
+ count = start + (console->ncolumns *
+ (console->nlines - console->cursor_line));
+ for (x = start; x < count; x++)
+ console->attrs[x] |= ATTR_DIRTY;
+ break;
case 'S': /* SU - scroll up */
/* TODO */
break;
@@ -702,13 +741,11 @@ console_parse_csi(struct console *console)
break;
}
break;
- case '7': /* DECSC - save cursor */
- case 's': /* from ANSI.SYS */
+ case 's': /* SCO - save cursor position */
console->saved_cursor_column = console->cursor_column;
console->saved_cursor_line = console->cursor_line;
break;
- case '8': /* DECRC - restore cursor */
- case 'u': /* from ANSI.SYS */
+ case 'u': /* SCO - restore saved cursor position */
console->cursor_column = console->saved_cursor_column;
console->cursor_line = console->saved_cursor_line;
break;