Hi, Here is a little patch so smcup and rmcup are supported in the console server. I know this patch is far from perfect, perhaps I'm not even doing the right thing.
A later version will support 3 options: --rmcup=on --rmcup=off --rmcup=to-scrollback-buffer I know that these argument names suck and I'd like to hear a good alternative name. :) Some short technical descriptions of these options: rmcup=on Works more or less the same as on xterm. Xterm really switches to an alternative screen, this patch doesn't work that way. It just backups the visible screen and cleans it. Because of this the scrollback buffer still works. There is one problem with this mode. Because I just backup the visible screen and don't put any other restrictions on the screen (is this possible and do we want this?). The "smcup application" can destroy the scrollback buffer a bit as I have noticed. less does this for example. (It can clear one screen of the scrollback buffer). Perhaps I don't understand the console good enough to see why this exactly happens. I know this can be prevented by backing up the whole buffer instead of just the visible screen. rmcup=off Old behavior rmcup=to-scrollback-buffer This nice feature was a really good idea of Marcus. It does the same as rmcup, but puts the alternate screen in the scrollback buffer instead of overwriting it. This has one advantage. When you use C-z a lot with emacs it fills up you scrollbackbuffer really fast. :) I hope someone will have a look at this patch and will comment on it. I didn't put it on savannah yet because it is far from perfect. You can also help me by testing this patch for me! :) Thanks, Marco 2003-08-03 Marco Gerards <[EMAIL PROTECTED]> * display.c (struct display): New member ALT_CURSOR and ALT_SCREEN. (screen_to_alternate): New function. (screen_from_alternate): Likewise. (handle_esc_bracket_right_angle_hl): Implement smcup and rmcup. * hurd.ti: Add capabilities smcup and rmcup. Only in console: #display.# Only in console: .#display. Common subdirectories: /home/marco/src/hurdcvs/hurd/console/CVS and console/CVS diff -up /home/marco/src/hurdcvs/hurd/console/display.c console/display.c --- /home/marco/src/hurdcvs/hurd/console/display.c 2003-06-03 23:19:00.000000000 +0200 +++ console/display.c 2003-08-05 19:32:33.000000000 +0200 @@ -184,6 +184,22 @@ struct display struct cons_display *user; + /* The backup of the screen and cursor position used for switching + to the alternate screen. Notice there is no real alternate + screen, the alternate screen created by backing up the current + screen and clearing it. */ + struct cursor alt_cursor; + struct + { + /* Width of screen matrix. */ + uint32_t width; + /* Number of lines in visible area following + (and including) CUR_LINE. */ + uint32_t height; + /* Is NULL when the alternate screen is not active. */ + conchar_t *_matrixp; + } alt_screen; + /* The pager for the USER member. */ struct user_pager user_pager; @@ -1075,6 +1091,115 @@ void limit_cursor (display_t display) /* XXX Flag cursor change. */ } +/* Switch the screen on DISPLAY to the "alternate screen". */ +static void +screen_to_alternate (display_t display) +{ + struct cons_display *user = display->user; + + off_t start = ((user->screen.cur_line % user->screen.lines)) + * user->screen.width; + off_t end = (((user->screen.cur_line % user->screen.lines) + + user->screen.height - 1) + * user->screen.width + user->screen.width - 1); + off_t size = (user->screen.width * user->screen.lines); + + if (start >= size && end >= size) + { + start -= size; + end -= size; + } + + /* Save the cursor position. XXX: Should the visibility be saved? */ + display->alt_cursor.saved_x = user->cursor.col; + display->alt_cursor.saved_y = user->cursor.row; + + /* Save the screen, including its dimensions. */ + display->alt_screen.width = user->screen.width; + display->alt_screen.height = user->screen.height; + + /* XXX: Only save the visible screen. Perhaps we should save the + complete buffer because the alternative screen can affect the + scrollback buffer. */ + display->alt_screen._matrixp + = malloc (user->screen.width * user->screen.height * sizeof (conchar_t)); + + if (end < size) + memcpy (display->alt_screen._matrixp, + user->_matrix + start, (end - start + 1) * sizeof (conchar_t)); + else + { + memcpy (display->alt_screen._matrixp, + user->_matrix + start, (size - start) * sizeof (conchar_t)); + memcpy (display->alt_screen._matrixp + size - start, + user->_matrix, (end - size) * sizeof (conchar_t)); + } + + /* Clear the "alternate screen". */ + screen_fill (display, 0, 0, + user->screen.width - 1, user->screen.height - 1, + L' ', display->attr.current); +} + +/* The screen on DISPLAY is showing the alternate screen, switch back + to the regular screen. */ +static void +screen_from_alternate (display_t display) +{ + struct cons_display *user = display->user; + + /* Keep the alternate screen in the scrollback buffer. XXX: This + should be made optional. */ + user->screen.cur_line += user->screen.height; + + off_t start = ((user->screen.cur_line % user->screen.lines)) + * user->screen.width; + + off_t end = (((user->screen.cur_line % user->screen.lines) + + user->screen.height - 1) + * user->screen.width + user->screen.width - 1); + off_t size = (user->screen.width * user->screen.lines); + + if (start >= size && end >= size) + { + start -= size; + end -= size; + } + + /* The screen has been resized while the alternate screen was + active, don't restore the old screen. */ + if (user->screen.width != display.alt_screen.width + || user->screen.height != display.alt_screen.height) + { + free (display->alt_screen._matrixp); + display->alt_screen._matrixp = 0; + return 0; + } + + if (end < size) + { + memcpy (user->_matrix + start, display->alt_screen._matrixp, + (end - start + 1) * sizeof (conchar_t)); + + display_record_filechange (display, start, end); + } + else + { + memcpy (user->_matrix + start, display->alt_screen._matrixp, + (size - start) * sizeof (conchar_t)); + memcpy (user->_matrix, display->alt_screen._matrixp + size - start, + (end - size) * sizeof (conchar_t)); + display_record_filechange (display, start, end - size); + } + + free (display->alt_screen._matrixp); + display->alt_screen._matrixp = 0; + + user->cursor.col = display->alt_cursor.saved_x; + user->cursor.row = display->alt_cursor.saved_y; + /* In case the screen was larger before: */ + limit_cursor (display); +} static void linefeed (display_t display) @@ -1434,6 +1559,21 @@ handle_esc_bracket_right_angle_hl (displ else display->attr.current.bold = 0; break; + case 2: + /* <smcup>, <rmcup>. Use this to safe and restore the screen. */ + if (flag) /* smcup. */ + { + /* Backup the screen. */ + if (display->alt_screen._matrixp == NULL) + screen_to_alternate (display); + } + else /* rmcup. */ + { + /* Restore the screen. */ + if (display->alt_screen._matrixp != NULL) + screen_from_alternate (display); + } + break; } } diff -up /home/marco/src/hurdcvs/hurd/console/hurd.ti console/hurd.ti --- /home/marco/src/hurdcvs/hurd/console/hurd.ti 2002-10-10 14:26:04.000000000 +0200 +++ console/hurd.ti 2003-08-05 19:30:03.000000000 +0200 @@ -64,6 +64,8 @@ hurd|The GNU Hurd console server, ed=\E[J, # Clear to end (beginning) of line. el=\E[K, el1=\E[1K, +# Switch to (from) alternate screen. + smcup=\E[>2h, rmcup=\E[>2l, # Insert one character (P1 characters). # <ich1> not included because we have insert mode. _______________________________________________ Bug-hurd mailing list [EMAIL PROTECTED] http://mail.gnu.org/mailman/listinfo/bug-hurd