diff options
Diffstat (limited to 'libcons')
-rw-r--r-- | libcons/ChangeLog | 15 | ||||
-rw-r--r-- | libcons/Makefile | 2 | ||||
-rw-r--r-- | libcons/cons-switch.c | 58 | ||||
-rw-r--r-- | libcons/cons.h | 13 | ||||
-rw-r--r-- | libcons/file-changed.c | 116 | ||||
-rw-r--r-- | libcons/vcons-open.c | 4 | ||||
-rw-r--r-- | libcons/vcons-scrollback.c | 122 |
7 files changed, 267 insertions, 63 deletions
diff --git a/libcons/ChangeLog b/libcons/ChangeLog index ee8a9ec6..bae85db0 100644 --- a/libcons/ChangeLog +++ b/libcons/ChangeLog @@ -1,5 +1,20 @@ 2002-09-09 Marcus Brinkmann <marcus@gnu.org> + * Makefile (SRCS): Add vcons-scrollback.c. + * vcons-scrollback.c: New file. + * cons.h (struct vcons): Add SCROLLING member. + * file-changed.c: Include <assert.h>. + (cons_S_file_changed): Be careful to take VCONS->scrolling into + account when doing clipping and scrolling. + + * cons-switch.c: Roll back to earlier version with vcons -> + vcons_entry adjustments. The user is now expected to hold a + reference to the VCONS. + * cons.h: Fix prototype, too. + + * vcons-open.c (cons_vcons_open): Initialize VCONS->lock, + VCONS->input and VCONS->display. + * vcons-remove.c: New file. * Makefile (SRCS): Add vcons-destroy.c. * cons.h: New type vcons_list_t. diff --git a/libcons/Makefile b/libcons/Makefile index a7fe6bf8..2a677e7d 100644 --- a/libcons/Makefile +++ b/libcons/Makefile @@ -22,7 +22,7 @@ libname = libcons SRCS= demuxer.c init-init.c init-loop.c opts-version.c extra-version.c \ dir-changed.c file-changed.c opts-std-startup.c cons-lookup.c \ cons-switch.c vcons-remove.c vcons-add.c vcons-open.c \ - vcons-close.c vcons-destroy.c vcons-refresh.c + vcons-close.c vcons-destroy.c vcons-refresh.c vcons-scrollback.c LCLHDRS = priv.h mutations.h installhdrs = cons.h diff --git a/libcons/cons-switch.c b/libcons/cons-switch.c index d9aa64af..c39e83da 100644 --- a/libcons/cons-switch.c +++ b/libcons/cons-switch.c @@ -23,44 +23,47 @@ #include "cons.h" -/* Open the virtual console ID or the ACTIVE_ID plus DELTA one in CONS - and return it in R_VCONS, which will be locked. */ +/* Open the virtual console ID or the virtual console DELTA steps away + from VCONS in the linked list and return it in R_VCONS, which will + be locked. */ error_t -cons_switch (cons_t cons, int active_id, int id, int delta, vcons_t *r_vcons) +cons_switch (vcons_t vcons, int id, int delta, vcons_t *r_vcons) { error_t err = 0; + cons_t cons = vcons->cons; vcons_list_t vcons_entry = NULL; if (!id && !delta) return 0; mutex_lock (&cons->lock); - vcons_entry = cons->vcons_list; - while (vcons_entry && vcons_entry->id != (id ?: active_id)) - vcons_entry = vcons_entry->next; - - if (!id && vcons_entry) + if (id) + { + vcons_entry = cons->vcons_list; + while (vcons_entry && vcons_entry->id != id) + vcons_entry = vcons_entry->next; + } + else if (delta > 0) + { + vcons_entry = vcons->vcons_entry; + while (delta-- > 0) + { + vcons_entry = vcons_entry->next; + if (!vcons_entry) + vcons_entry = cons->vcons_list; + } + } + else { - if (delta > 0) - { - while (delta-- > 0) - { - vcons_entry = vcons_entry->next; - if (!vcons_entry) - vcons_entry = cons->vcons_list; - } - } - else - { - assert (delta < 0); - while (delta++ < 0) - { - vcons_entry = vcons_entry->prev; - if (!vcons_entry) - vcons_entry = cons->vcons_last; - } - } + assert (delta < 0); + while (delta++ < 0) + { + vcons_entry = vcons_entry->prev; + if (!vcons_entry) + vcons_entry = cons->vcons_last; + } } + if (!vcons_entry) { mutex_unlock (&cons->lock); @@ -78,6 +81,7 @@ cons_switch (cons_t cons, int active_id, int id, int delta, vcons_t *r_vcons) if (!err) vcons_entry->vcons = *r_vcons; } + mutex_unlock (&cons->lock); return err; } diff --git a/libcons/cons.h b/libcons/cons.h index e7484db5..6b2fca49 100644 --- a/libcons/cons.h +++ b/libcons/cons.h @@ -103,6 +103,8 @@ struct vcons cons_change_t *buffer; } changes; } state; + + uint32_t scrolling; }; struct cons @@ -206,10 +208,13 @@ void cons_vcons_add (cons_t cons, vcons_list_t vcons_entry); virtual console entry is removed. CONS is locked. */ void cons_vcons_remove (cons_t cons, vcons_list_t vcons_entry); -/* Open the virtual console ID or the ACTIVE_ID plus DELTA one in CONS - and return it in R_VCONS. */ -error_t cons_switch (cons_t cons, int active_id, int id, int delta, - vcons_t *r_vcons); +/* Open the virtual console ID or the virtual console DELTA steps away + from VCONS in the linked list and return it in R_VCONS, which will + be locked. */ +error_t cons_switch (vcons_t vcons, int id, int delta, vcons_t *r_vcons); + +/* Scroll back into the history of VCONS by DELTA lines. */ +int cons_vcons_scrollback (vcons_t vcons, int delta); extern const struct argp cons_startup_argp; diff --git a/libcons/file-changed.c b/libcons/file-changed.c index 9d7a066b..b4372ed9 100644 --- a/libcons/file-changed.c +++ b/libcons/file-changed.c @@ -18,8 +18,10 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ -#include <mach.h> #include <errno.h> +#include <assert.h> + +#include <mach.h> #include "cons.h" #include "fs_notify_S.h" @@ -70,10 +72,27 @@ cons_S_file_changed (cons_notify_t notify, natural_t tickno, { if (change.what.cursor_pos) { + uint32_t old_row = vcons->state.cursor.row; + uint32_t height = vcons->state.screen.height; + uint32_t row; + vcons->state.cursor.col = vcons->display->cursor.col; - vcons->state.cursor.row = vcons->display->cursor.row; - cons_vcons_set_cursor_pos (vcons, vcons->state.cursor.col, - vcons->state.cursor.row); + row = vcons->state.cursor.row = vcons->display->cursor.row; + + if (row + vcons->scrolling < height) + { + cons_vcons_set_cursor_pos (vcons, + vcons->state.cursor.col, + row + vcons->scrolling); + if (old_row + vcons->scrolling >= height) + /* The cursor was invisible before. */ + cons_vcons_set_cursor_status (vcons, + vcons->state.cursor.status); + } + else if (old_row + vcons->scrolling < height) + /* The cursor was visible before. */ + cons_vcons_set_cursor_status (vcons, CONS_CURSOR_INVISIBLE); + cons_vcons_update (vcons); } if (change.what.cursor_status) @@ -86,8 +105,9 @@ cons_S_file_changed (cons_notify_t notify, natural_t tickno, if (change.what.screen_cur_line) { uint32_t new_cur_line; - + new_cur_line = vcons->display->screen.cur_line; + if (new_cur_line != vcons->state.screen.cur_line) { off_t size = vcons->state.screen.width @@ -103,30 +123,57 @@ cons_S_file_changed (cons_notify_t notify, natural_t tickno, else scrolling = UINT32_MAX - vcons->state.screen.cur_line + 1 + new_cur_line; - if (scrolling > vcons->state.screen.height) - scrolling = vcons->state.screen.height; - if (scrolling < vcons->state.screen.height) - cons_vcons_scroll (vcons, scrolling); - vis_start = vcons->state.screen.width - * (new_cur_line % vcons->state.screen.lines); - start = (((new_cur_line % vcons->state.screen.lines) - + vcons->state.screen.height - scrolling) - * vcons->state.screen.width) % size; - end = start + scrolling * vcons->state.screen.width - 1; - cons_vcons_write (vcons, - vcons->state.screen.matrix + start, - end < size - ? end - start + 1 - : size - start, - 0, vcons->state.screen.height - - scrolling); - if (end >= size) - cons_vcons_write (vcons, - vcons->state.screen.matrix, - end - size + 1, - 0, (size - vis_start) - / vcons->state.screen.width); - cons_vcons_update (vcons); + + /* If we are scrollbacking, defer scrolling + until absolutely necessary. */ + if (vcons->scrolling) + { + if (vcons->scrolling + scrolling <= vcons->state.screen.scr_lines) + { + vcons->scrolling += scrolling; + scrolling = 0; + } + else + { + scrolling -= vcons->state.screen.scr_lines - vcons->scrolling; + vcons->scrolling = vcons->state.screen.scr_lines; + } + } + + if (scrolling) + { + uint32_t cur_disp_line; + + if (new_cur_line >= vcons->scrolling) + cur_disp_line = new_cur_line - vcons->scrolling; + else + cur_disp_line = (UINT32_MAX - (vcons->scrolling - new_cur_line)) + 1; + + if (scrolling > vcons->state.screen.height) + scrolling = vcons->state.screen.height; + if (scrolling < vcons->state.screen.height) + cons_vcons_scroll (vcons, scrolling); + vis_start = vcons->state.screen.width + * (cur_disp_line % vcons->state.screen.lines); + start = (((cur_disp_line % vcons->state.screen.lines) + + vcons->state.screen.height - scrolling) + * vcons->state.screen.width) % size; + end = start + scrolling * vcons->state.screen.width - 1; + cons_vcons_write (vcons, + vcons->state.screen.matrix + start, + end < size + ? end - start + 1 + : size - start, + 0, vcons->state.screen.height + - scrolling); + if (end >= size) + cons_vcons_write (vcons, + vcons->state.screen.matrix, + end - size + 1, + 0, (size - vis_start) + / vcons->state.screen.width); + cons_vcons_update (vcons); + } vcons->state.screen.cur_line = new_cur_line; } } @@ -134,6 +181,8 @@ cons_S_file_changed (cons_notify_t notify, natural_t tickno, { vcons->state.screen.scr_lines = vcons->display->screen.scr_lines; + if (vcons->state.screen.scr_lines < vcons->scrolling) + assert (!"Implement shrinking scrollback buffer! XXX"); } if (change.what.bell_audible) { @@ -158,8 +207,7 @@ cons_S_file_changed (cons_notify_t notify, natural_t tickno, { /* For clipping. */ off_t size = vcons->state.screen.width*vcons->state.screen.lines; - off_t rotate = vcons->state.screen.width - * (vcons->state.screen.cur_line % vcons->state.screen.lines); + off_t rotate; off_t vis_end = vcons->state.screen.height * vcons->state.screen.width - 1; off_t end2 = -1; @@ -167,6 +215,12 @@ cons_S_file_changed (cons_notify_t notify, natural_t tickno, off_t start = change.matrix.start; off_t end = change.matrix.end; + if (vcons->state.screen.cur_line >= vcons->scrolling) + rotate = vcons->state.screen.cur_line - vcons->scrolling; + else + rotate = (UINT32_MAX - (vcons->scrolling - vcons->state.screen.cur_line)) + 1; + rotate = vcons->state.screen.width * (rotate % vcons->state.screen.lines); + /* Rotate the buffer. */ start -= rotate; if (start < 0) diff --git a/libcons/vcons-open.c b/libcons/vcons-open.c index 0d826b63..8841b938 100644 --- a/libcons/vcons-open.c +++ b/libcons/vcons-open.c @@ -55,6 +55,10 @@ cons_vcons_open (cons_t cons, vcons_list_t vcons_entry, vcons_t *r_vcons) vcons->cons = cons; vcons->vcons_entry = vcons_entry; vcons->id = vcons_entry->id; + mutex_init (&vcons->lock); + vcons->input = -1; + vcons->display = MAP_FAILED; + vcons->scrolling = 0; /* Open the directory port of the virtual console. */ vconsp = file_name_lookup_under (cons->dirport, name, diff --git a/libcons/vcons-scrollback.c b/libcons/vcons-scrollback.c new file mode 100644 index 00000000..cfc94458 --- /dev/null +++ b/libcons/vcons-scrollback.c @@ -0,0 +1,122 @@ +/* vcons-scrollback.c - Move forward and backward in the scrollback buffer. + Copyright (C) 2002 Free Software Foundation, Inc. + Written by Marcus Brinkmann. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#include <stdint.h> + +#include <cthreads.h> + +#include "cons.h" + +/* Scroll back into the history of VCONS by DELTA lines. */ +int +cons_vcons_scrollback (vcons_t vcons, int delta) +{ + int scrolling; + uint32_t new_scr; + + mutex_lock (&vcons->lock); + if (delta > 0 || vcons->scrolling > (uint32_t) (-delta)) + { + new_scr = vcons->scrolling + delta; + if (new_scr > vcons->state.screen.scr_lines) + new_scr = vcons->state.screen.scr_lines; + } + else + new_scr = 0; + + if (new_scr == vcons->scrolling) + { + mutex_unlock (&vcons->lock); + return 0; + } + + scrolling = vcons->scrolling - new_scr; + { + uint32_t new_cur_line; + off_t size = vcons->state.screen.width + * vcons->state.screen.lines; + off_t vis_start; + off_t start; + off_t end; + + if (vcons->state.screen.cur_line >= new_scr) + new_cur_line = vcons->state.screen.cur_line - new_scr; + else + new_cur_line = (UINT32_MAX - (new_scr - vcons->state.screen.cur_line)) + 1; + + if (scrolling > 0 && (uint32_t) scrolling > vcons->state.screen.height) + scrolling = vcons->state.screen.height; + else if (scrolling < 0 + && (uint32_t) (-scrolling) > vcons->state.screen.height) + scrolling = -vcons->state.screen.height; + if ((scrolling > 0 && scrolling < vcons->state.screen.height) + || (scrolling < 0 + && (uint32_t) (-scrolling) < vcons->state.screen.height)) + cons_vcons_scroll (vcons, scrolling); + + vis_start = vcons->state.screen.width + * (new_cur_line % vcons->state.screen.lines); + if (scrolling > 0) + start = (((new_cur_line % vcons->state.screen.lines) + + vcons->state.screen.height - scrolling) + * vcons->state.screen.width) % size; + else + start = vis_start; + end = start + abs (scrolling) * vcons->state.screen.width - 1; + + cons_vcons_write (vcons, + vcons->state.screen.matrix + start, + end < size + ? end - start + 1 + : size - start, + 0, (scrolling > 0) + ? vcons->state.screen.height - scrolling : 0); + if (end >= size) + cons_vcons_write (vcons, + vcons->state.screen.matrix, + end - size + 1, + 0, (size - vis_start) + / vcons->state.screen.width); + } + + /* Set the new cursor position. */ + { + uint32_t row = vcons->state.cursor.row; + uint32_t height = vcons->state.screen.height; + + if (row + new_scr < height) + { + cons_vcons_set_cursor_pos (vcons, vcons->state.cursor.col, + row + new_scr); + if (row + vcons->scrolling >= height) + /* The cursor was invisible before. */ + cons_vcons_set_cursor_status (vcons, vcons->state.cursor.status); + } + else if (row + vcons->scrolling < height) + /* The cursor was visible before. */ + cons_vcons_set_cursor_status (vcons, CONS_CURSOR_INVISIBLE); + } + + cons_vcons_update (vcons); + vcons->scrolling -= scrolling; + mutex_unlock (&vcons->lock); + + return -scrolling; +} |