jcs
/subtext
/amendments
/29
console: Implement scrolling, speed up redrawing
No need to pass hints anymore, just do less math in the loop scanning
for dirty cells
jcs made amendment 29 over 2 years ago
--- console.c Mon Dec 13 09:14:36 2021
+++ console.c Mon Dec 13 21:42:20 2021
@@ -33,7 +33,8 @@ struct node_funcs console_node_funcs = {
console_close
};
-void console_redraw(struct console *console, short numhints, short *hints);
+void console_redraw(struct console *console, short force);
+short console_bound(struct console *console);
void console_parse_csi(struct console *console);
struct console *
@@ -50,9 +51,8 @@ console_init(struct console **cur_console)
memset(console->chars, ' ', sizeof(console->chars));
console->ncolumns = 80;
console->nlines = 24;
- console->attrs[0] |= (ATTR_CURSOR | ATTR_DIRTY);
- width = FONT_WIDTH * (console->ncolumns + 2);
+ width = (FONT_WIDTH * console->ncolumns) + (FONT_WIDTH * 2);
height = (FONT_HEIGHT * console->nlines) + (FONT_WIDTH * 2);
bounds.left = (screenBits.bounds.right - width) / 2;
@@ -110,27 +110,21 @@ console_idle(struct console *console)
{
struct session *session = console->session;
short n, len, cursor, iac = 0;
- short hints[100];
- short nhints = 0;
if (session->obuflen == 0)
return;
+ /* uncursor */
cursor = (console->cursor_line * console->ncolumns) +
console->cursor_column;
- console->attrs[cursor] |= ATTR_DIRTY;
+ if (cursor >= sizeof(console->attrs))
+ panic("console_idle: cursor out of bounds!");
console->attrs[cursor] &= ~ATTR_CURSOR;
- hints[nhints++] = cursor;
+ console->attrs[cursor] |= ATTR_DIRTY;
for (n = 0; n < session->obuflen; n++) {
- if (console->cursor_column >= console->ncolumns &&
- session->obuf[n] != '\n') {
- console->cursor_column = 0;
- console->cursor_line++;
- }
-
if (console->in_csi) {
- if (session->obuf[n] == '\e' ||
+ if (session->obuf[n] == '\33' ||
console->csilen >= nitems(console->csi) - 1) {
console_parse_csi(console);
console->in_csi = 0;
@@ -151,6 +145,8 @@ console_idle(struct console *console)
break;
case '\n':
console->cursor_line++;
+ console->cursor_column = 0; /* \r should do this, but JIC */
+ console_bound(console);
break;
case '\33': /* \e */
if (session->obuflen <= n + 1) {
@@ -166,15 +162,12 @@ console_idle(struct console *console)
}
/* escape but not CSI, fall through */
default:
+ console_bound(console);
cursor = (console->cursor_line * console->ncolumns) +
console->cursor_column;
console->chars[cursor] = session->obuf[n];
console->attrs[cursor] = console->cur_attr | ATTR_DIRTY;
console->cursor_column++;
- if (nhints != -1 && nhints < nitems(hints) - 1)
- hints[nhints++] = cursor;
- else
- nhints = -1;
break;
}
}
@@ -183,14 +176,8 @@ console_idle(struct console *console)
session->obuflen = 0;
output_done:
- cursor = (console->cursor_line * console->ncolumns) +
- console->cursor_column;
- console->attrs[cursor] |= (ATTR_DIRTY | ATTR_CURSOR);
- if (nhints != -1 && nhints < nitems(hints) - 1)
- hints[nhints++] = cursor;
- else if (nhints == -1)
- nhints = 0;
- console_redraw(console, nhints, hints);
+ console_bound(console);
+ console_redraw(console, 0);
}
void
@@ -215,7 +202,7 @@ console_update(struct console *console, EventRecord *e
switch (what) {
case -1:
case updateEvt:
- console_redraw(console, -1, NULL);
+ console_redraw(console, 1);
//browser_update_menu(browser);
UpdtControl(console->win, console->win->visRgn);
@@ -261,66 +248,115 @@ console_input(struct session *session)
return 0;
}
-void
-console_redraw(struct console *console, short nhints, short *hints)
+short
+console_bound(struct console *console)
{
- Rect cursor;
- short n, nsize, cell, line = 0, column = 0;
+ unsigned short shift_lines, shift_cols, chars_left, pxout;
+ RgnHandle rgn;
+ Rect r;
+ short ret = 0;
+#ifdef SMOOTH_SCROLLING
+ Rect r2;
+ short n;
+#endif
- if (nhints > 0)
- nsize = nhints;
- else {
- nsize = nitems(console->chars);
- SetCursor(*(GetCursor(watchCursor)));
+ while (console->cursor_column >= console->ncolumns) {
+ console->cursor_line++;
+ console->cursor_column -= console->ncolumns;
}
- for (n = 0; n < nsize; n++) {
- if (nhints > 0) {
- cell = hints[n];
- } else {
- if (nhints == 0 && !(console->attrs[n] & ATTR_DIRTY))
- continue;
-
- /*
- * speed hack: if doing a whole-window update, no need to
- * redraw blank space
- */
- if (nhints == -1 && console->chars[n] == ' ' &&
- !(console->attrs[n] & ATTR_CURSOR))
- continue;
+ if (console->cursor_line >= console->nlines) {
+ shift_lines = console->cursor_line - console->nlines + 1;
+ shift_cols = shift_lines * console->ncolumns;
+ chars_left = (console->nlines * console->ncolumns) - shift_cols;
+ pxout = shift_lines * FONT_HEIGHT;
- cell = n;
+ rgn = NewRgn();
+ r.left = console->win->portRect.left + FONT_WIDTH;
+ r.top = console->win->portRect.top + FONT_WIDTH;
+ r.right = r.left + (console->ncolumns * FONT_WIDTH);
+ r.bottom = r.top + ((console->nlines) * FONT_HEIGHT);
+#ifdef SMOOTH_SCROLLING
+ for (n = 0; n < pxout; n++) {
+ ScrollRect(&r, 0, -1, rgn);
+ r2 = r;
+ r2.top = r.bottom - 1;
+ r2.bottom = r.top + 1;
+ FillRect(&r2, white);
}
+#else
+ ScrollRect(&r, 0, -pxout, rgn);
+ r.top = r.bottom - 1;
+ r.bottom = r.top + pxout;
+ FillRect(&r, white);
+#endif
+ DisposeRgn(rgn);
+
+ BlockMove(console->chars + shift_cols, console->chars, chars_left);
+ BlockMove(console->attrs + shift_cols, console->attrs, chars_left);
+ memset(console->chars + chars_left, ' ', shift_cols);
+ memset(console->attrs + chars_left, console->cur_attr, shift_cols);
- line = cell / console->ncolumns;
- column = cell - (line * console->ncolumns);
+ console->cursor_line = console->nlines - 1;
+ ret = 1;
+ }
+
+ return ret;
+}
- cursor.left = FONT_WIDTH + ((console->win->portRect.left +
- column) * FONT_WIDTH);
- cursor.top = FONT_WIDTH + ((console->win->portRect.top + line) *
- FONT_HEIGHT);
+void
+console_redraw(struct console *console, short force)
+{
+ Rect cursor;
+ short n, nsize, cell, cbold = -1;
+
+ /* recursor */
+ console->attrs[(console->cursor_line * console->ncolumns) +
+ console->cursor_column] |= (ATTR_CURSOR | ATTR_DIRTY);
+
+ nsize = console->ncolumns * console->nlines;
+ SetCursor(*(GetCursor(watchCursor)));
+
+ cursor.left = console->win->portRect.left + FONT_WIDTH;
+ cursor.top = console->win->portRect.top + FONT_WIDTH;
+ for (cell = 0; cell < nsize; cell++) {
+ if (cell) {
+ if (cell % console->ncolumns == 0) {
+ cursor.left = console->win->portRect.left + FONT_WIDTH;
+ cursor.top += FONT_HEIGHT;
+ } else {
+ cursor.left += FONT_WIDTH;
+ }
+ }
+
+ if (!force && !(console->attrs[cell] & ATTR_DIRTY))
+ continue;
+
cursor.right = cursor.left + FONT_WIDTH;
cursor.bottom = cursor.top + FONT_HEIGHT;
-
FillRect(&cursor, white);
-
- MoveTo(cursor.left, cursor.top + FONT_HEIGHT - 2);
- if (console->attrs[cell] & ATTR_BOLD)
- TextFace(thePort->txFace | bold);
- else
- TextFace(thePort->txFace & ~bold);
+ 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]);
- console->attrs[n] &= ~ATTR_DIRTY;
+ console->attrs[cell] &= ~ATTR_DIRTY;
if (console->attrs[cell] & ATTR_CURSOR)
InvertRect(&cursor);
}
-
+
ValidRect(&console->win->portRect);
- if (nhints <= 0)
- SetCursor(&arrow);
+ SetCursor(&arrow);
}
void
@@ -672,11 +708,9 @@ console_parse_csi(struct console *console)
}
if (serviced) {
- cursor = (console->cursor_line * console->ncolumns) +
- console->cursor_column;
- console->attrs[cursor] |= (ATTR_CURSOR | ATTR_DIRTY);
console->csilen = 0;
console->csi[0] = '\0';
console->in_csi = 0;
+ console_bound(console);
}
}
--- console.h Mon Dec 6 17:32:18 2021
+++ console.h Mon Dec 13 13:43:42 2021
@@ -24,6 +24,8 @@ struct console {
struct console **cur_console;
WindowPtr win;
ControlHandle scroller;
+ short nlines;
+ short ncolumns;
char chars[80 * 24];
char attrs[80 * 24];
char cur_attr;
@@ -32,8 +34,6 @@ struct console {
#define ATTR_UNDERLINE (1 << 2)
#define ATTR_CURSOR (1 << 6)
#define ATTR_DIRTY (1 << 7)
- short nlines;
- short ncolumns;
short cursor_line;
short cursor_column;
short in_csi;