summaryrefslogtreecommitdiff
path: root/libcons
diff options
context:
space:
mode:
Diffstat (limited to 'libcons')
-rw-r--r--libcons/ChangeLog15
-rw-r--r--libcons/Makefile2
-rw-r--r--libcons/cons-switch.c58
-rw-r--r--libcons/cons.h13
-rw-r--r--libcons/file-changed.c116
-rw-r--r--libcons/vcons-open.c4
-rw-r--r--libcons/vcons-scrollback.c122
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;
+}