summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--console-client/ChangeLog51
-rw-r--r--console-client/console.c19
-rw-r--r--console-client/display.h9
-rw-r--r--console-client/ncursesw.c185
-rw-r--r--console-client/vga.c144
5 files changed, 365 insertions, 43 deletions
diff --git a/console-client/ChangeLog b/console-client/ChangeLog
index 94131588..10a5c8af 100644
--- a/console-client/ChangeLog
+++ b/console-client/ChangeLog
@@ -1,3 +1,54 @@
+2003-08-11 Marco Gerards <metgerards@student.han.nl>
+
+ * console.c (cons_vcons_set_dimension): New function.
+ * display.h (display_ops): New interface set_dimension.
+ * ncursesw.c (ncursesw_set_dimension): New function.
+ (ncursesw_displ): Add ncursesw_set_dimension.
+ (ncurses_lock): Make variable static.
+ (current_width): New variable.
+ (current_height): Likewise.
+ (cursor_state): Likewise.
+ (cursor_hidden): Likewise.
+ (driver_ncursesw_ops): Added ncursesw_set_dimension.
+ * vga.c (current_width): New variable.
+ (current_height): Likewise.
+ (vga_display_set_cursor_status): If the cursor is outside the
+ screen, don't change the visibility.
+ (vga_display_set_cursor_pos): Don't set the cursor outside the
+ physical screen. Update cursor_hidden and hide/unhide
+ to match cursor_hidden. Function moved to above
+ vga_display_set_cursor_status.
+ (vga_display_scroll): Report an error when scrolling is not
+ possible.
+ (vga_display_clear): Recalculate cols, rows and length.
+ (vga_display_write): Make it wrap around the edge.
+ (vga_set_dimension): New function.
+ (vga_disp_ops): Added vga_set_dimension.
+
+ * ncursesw.c (conspad): New variable.
+ (padx): Likewise.
+ (pady): Likewise.
+ (autoscroll): Likewise.
+ (refresh_screen): new function.
+ (input_loop): Use conspad instead of (the default) stdscr.
+ Call console_exit instead of exiting here. Add keybindings
+ 'j, 'k', 'l' and 'i' to scroll the console, add keybinding 'a'
+ to switch autoscroll.
+ (mvwputsn): Use conspad instead of (the default) stdscr.
+ (ncursesw_scroll): Likewise.
+ (ncursesw_write): Likewise.
+ (ncursesw_driver_start): Likewise. Initialize conspad.
+ (ncursesw_update): Call refresh_screen to refresh the console.
+ (ncursesw_set_cursor_pos): Use conspad instead of (the default)
+ stdscr. Make the console autoscroll.
+
+ * ncursesw.c (ncursesw_driver_start): Remove endwin call at
+ the end of the function.
+
+ * ncursesw.c (ncursesw_set_cursor_status): If the status can
+ not be set, use another status that can sanely be used instead
+ of the unavailable status.
+
2003-07-14 Marco Gerards <metgerards@student.han.nl>
* vga.c: New global variable vga_display_max_glyphs.
diff --git a/console-client/console.c b/console-client/console.c
index 34573580..0fb3aa97 100644
--- a/console-client/console.c
+++ b/console-client/console.c
@@ -1,5 +1,5 @@
/* console.c -- A pluggable console client.
- Copyright (C) 2002 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003 Free Software Foundation, Inc.
Written by Marcus Brinkmann.
This program is free software; you can redistribute it and/or
@@ -354,6 +354,23 @@ cons_vcons_set_scroll_lock (vcons_t vcons, int onoff)
mutex_unlock (&global_lock);
}
+
+/* The user must define this function. Clear the existing screen
+ matrix and set the size of the screen matrix to the dimension COL x
+ ROW. This call will be immediately followed by a call to
+ cons_vcons_write that covers the whole new screen matrix. */
+error_t
+cons_vcons_set_dimension (vcons_t vcons, uint32_t col, uint32_t row)
+{
+ mutex_lock (&global_lock);
+ if (vcons == active_vcons)
+ display_iterate
+ if (display->ops->set_dimension)
+ display->ops->set_dimension (display->handle, col, row);
+ mutex_unlock (&global_lock);
+ return 0;
+}
+
/* Console-specific options. */
static const struct argp_option
diff --git a/console-client/display.h b/console-client/display.h
index 44e62773..3dc97fde 100644
--- a/console-client/display.h
+++ b/console-client/display.h
@@ -1,5 +1,5 @@
/* display.h - The interface to and for a display driver.
- Copyright (C) 2002 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003 Free Software Foundation, Inc.
Written by Marcus Brinkmann.
This file is part of the GNU Hurd.
@@ -133,6 +133,13 @@ struct display_ops
/* Do not use, do not remove. */
void (*deprecated) (void *handle, int key);
+
+ /* Change the dimension of the physical screen to one that can
+ display the vcons with the size of WIDTH * HEIGHT and clear the
+ old screen. If the physical screen already has the right
+ resolution do nothing. This function is always followed by a
+ write that covers the whole new screen. */
+ error_t (*set_dimension) (void *handle, int width, int height);
};
#endif /* _DISPLAY_H_ */
diff --git a/console-client/ncursesw.c b/console-client/ncursesw.c
index 215fc9b8..e14abd7c 100644
--- a/console-client/ncursesw.c
+++ b/console-client/ncursesw.c
@@ -1,5 +1,5 @@
/* ncursesw.c - The ncursesw console driver.
- Copyright (C) 2002 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003 Free Software Foundation, Inc.
Written by Marcus Brinkmann.
This program is free software; you can redistribute it and/or
@@ -34,7 +34,22 @@
/* ncurses is not thread-safe. This lock protects all calls into the
ncurses library. */
-struct mutex ncurses_lock;
+static struct mutex ncurses_lock;
+
+/* The current width and height the ncursesw driver is using. */
+static int current_width;
+static int current_height;
+
+/* The window on which the console is shown. */
+static WINDOW *conspad;
+
+/* The upper left corner shown in the pad. */
+static int padx;
+static int pady;
+
+/* Autoscroll is on or off. Autoscroll makes scrolling dependant on
+ the cursor position. */
+static int autoscroll;
/* Forward declaration. */
static struct display_ops ncursesw_display_ops;
@@ -258,6 +273,17 @@ ucs4_to_altchar (wchar_t chr, chtype *achr)
return 1;
}
+static error_t
+refresh_screen (void)
+{
+ /* It is possible */
+ if (!current_width && !current_height)
+ return 0;
+ return prefresh (conspad, pady, padx, 0, 0,
+ (current_height <= LINES ? current_height : LINES) - 1,
+ (current_width <= COLS ? current_width : COLS) - 1);
+}
+
static any_t
input_loop (any_t unused)
{
@@ -282,7 +308,7 @@ input_loop (any_t unused)
size_t size = 0;
mutex_lock (&ncurses_lock);
- while ((ret = getch ()) != ERR)
+ while ((ret = wgetch (conspad)) != ERR)
{
int i;
int found;
@@ -292,8 +318,8 @@ input_loop (any_t unused)
switch (ret)
{
case 'x':
- endwin ();
- exit (0);
+ mutex_unlock (&ncurses_lock);
+ console_exit ();
break;
case 23: /* ^W */
assert (size < 100);
@@ -313,6 +339,42 @@ input_loop (any_t unused)
console_switch (1 + (ret - '1'), 0);
mutex_lock (&ncurses_lock);
break;
+ case 'j':
+ /* Scroll pad to left. */
+ if (padx > 0)
+ {
+ padx--;
+ refresh_screen ();
+ }
+ break;
+ case 'k':
+ /* Scroll pad down. */
+ if (pady < current_height - LINES)
+ {
+ pady++;
+ refresh_screen ();
+ }
+ break;
+ case 'l':
+ /* Scroll pad to right. */
+ if (padx < current_width - COLS)
+ {
+ padx++;
+ ncurses_refresh ();
+ }
+ break;
+ case 'i':
+ /* Scroll pad up. */
+ if (pady > 0)
+ {
+ pady--;
+ refresh_screen ();
+ }
+ break;
+ case 'a':
+ /* Switch autoscroll on/off. */
+ autoscroll = !autoscroll;
+ break;
default:
break;
}
@@ -326,13 +388,15 @@ input_loop (any_t unused)
break;
default:
found = 0;
- for (i =0; i < sizeof(keycodes) / sizeof(keycodes[0]); i++)
+ for (i = 0; i < sizeof (keycodes) / sizeof (keycodes[0]);
+ i++)
{
if (keycodes[i].curses == ret)
{
if (keycodes[i].cons)
{
- assert (size < 101 - strlen(keycodes[i].cons));
+ assert (size
+ < 101 - strlen (keycodes[i].cons));
strcpy (&buf[size], keycodes[i].cons);
size += strlen (keycodes[i].cons);
}
@@ -382,7 +446,7 @@ mvwputsn (conchar_t *str, size_t len, off_t x, off_t y)
attr_t attr = conchar_attr_to_attr (str->attr);
short color_pair = conchar_attr_to_color_pair (str->attr);
- move (y, x);
+ wmove (conspad, y, x);
while (len)
{
int ret;
@@ -396,7 +460,7 @@ mvwputsn (conchar_t *str, size_t len, off_t x, off_t y)
}
if (ucs4_to_altchar (str->chr, &ac))
- addch (ac | attr | color_pair);
+ waddch (conspad, ac | attr | color_pair);
else
{
wch[0] = str->chr;
@@ -409,7 +473,7 @@ mvwputsn (conchar_t *str, size_t len, off_t x, off_t y)
assert (!"Do something if setcchar fails.");
}
#endif
- ret = add_wch (&chr);
+ ret = wadd_wch (conspad, &chr);
#if 0
if (ret == ERR)
{
@@ -429,7 +493,7 @@ static error_t
ncursesw_update (void *handle)
{
mutex_lock (&ncurses_lock);
- refresh ();
+ refresh_screen ();
mutex_unlock (&ncurses_lock);
return 0;
}
@@ -439,7 +503,45 @@ static error_t
ncursesw_set_cursor_pos (void *handle, uint32_t col, uint32_t row)
{
mutex_lock (&ncurses_lock);
- move (row, col);
+ assert (current_width && current_height);
+ if (autoscroll)
+ {
+ /* Autoscroll to the right. */
+ if (col > COLS + padx)
+ {
+ padx += COLS / 2;
+ if (padx > COLS + current_width)
+ padx = current_width - COLS;
+ ncurses_refresh ();
+ }
+ /* Autoscroll to the left. */
+ else if (col < padx)
+ {
+ padx -= COLS / 2;
+ if (padx < 0)
+ padx = 0;
+ ncurses_refresh ();
+ }
+ /* Autoscroll down. */
+ if (row > LINES + pady)
+ {
+ pady += LINES / 2;
+ if (pady > LINES + current_height)
+ pady = current_height - LINES;
+ ncurses_refresh ();
+ }
+ /* Autoscroll up. */
+ else if (row < pady)
+ {
+ pady -= LINES / 2;
+ if (pady < 0)
+ pady = 0;
+ ncurses_refresh ();
+ }
+ }
+
+ wmove (conspad, row, col);
+
mutex_unlock (&ncurses_lock);
return 0;
}
@@ -449,7 +551,13 @@ static error_t
ncursesw_set_cursor_status (void *handle, uint32_t status)
{
mutex_lock (&ncurses_lock);
- curs_set (status ? (status == 1 ? 1 : 2) : 0);
+
+ /* If the cursor is invisible and switching to one visible state is
+ impossible, switch to the other visible state or else the cursor
+ will not be shown at all. */
+ if (curs_set (status) == -1 && status)
+ curs_set (status == 1 ? 2 : 1);
+
mutex_unlock (&ncurses_lock);
return 0;
}
@@ -462,11 +570,11 @@ ncursesw_scroll (void *handle, int delta)
assert (delta >= 0);
mutex_lock (&ncurses_lock);
- idlok (stdscr, TRUE);
- scrollok (stdscr, TRUE);
- scrl (delta);
- idlok (stdscr, FALSE);
- scrollok (stdscr, FALSE);
+ idlok (conspad, TRUE);
+ scrollok (conspad, TRUE);
+ wscrl (conspad, delta);
+ idlok (conspad, FALSE);
+ scrollok (conspad, FALSE);
mutex_unlock (&ncurses_lock);
return 0;
}
@@ -480,9 +588,9 @@ ncursesw_write (void *handle, conchar_t *str, size_t length,
int y;
mutex_lock (&ncurses_lock);
- getyx (stdscr, y, x);
+ getyx (conspad, y, x);
mvwputsn (str, length, col, row);
- wmove (stdscr, y, x);
+ wmove (conspad, y, x);
mutex_unlock (&ncurses_lock);
return 0;
}
@@ -531,10 +639,17 @@ ncursesw_driver_start (void *handle)
raw ();
noecho ();
nonl ();
- intrflush (stdscr, FALSE);
- nodelay (stdscr, TRUE);
- timeout (1);
- keypad (stdscr, TRUE);
+
+ /* Create a new pad with the size minimal size. This pad will be
+ resized by ncursesw_set_dimension. */
+ conspad = newpad (1, 1);
+ if (!conspad)
+ return errno;
+
+ intrflush (conspad, FALSE);
+ nodelay (conspad, TRUE);
+ wtimeout (conspad, 1);
+ keypad (conspad, TRUE);
err = driver_add_display (&ncursesw_display_ops, NULL);
if (err)
@@ -559,9 +674,8 @@ ncursesw_driver_start (void *handle)
}
cthread_detach (cthread_fork (input_loop, NULL));
- endwin ();
- return err;
+ return 0;
}
/* Destroy the display HANDLE. */
@@ -579,6 +693,22 @@ ncursesw_driver_fini (void *handle, int force)
return 0;
}
+static error_t
+ncursesw_set_dimension (void *handle, int width, int height)
+{
+ mutex_lock (&ncurses_lock);
+ if (width != current_width || height != current_height)
+ {
+ wresize (conspad, height, width);
+ padx = 0;
+ pady = 0;
+ }
+ current_width = width;
+ current_height = height;
+ mutex_unlock(&ncurses_lock);
+ return 0;
+}
+
struct driver_ops driver_ncursesw_ops =
{
@@ -596,7 +726,8 @@ static struct display_ops ncursesw_display_ops =
ncursesw_write,
ncursesw_update,
ncursesw_flash,
- NULL
+ NULL,
+ ncursesw_set_dimension
};
static struct input_ops ncursesw_input_ops =
diff --git a/console-client/vga.c b/console-client/vga.c
index d1d73e39..7f666494 100644
--- a/console-client/vga.c
+++ b/console-client/vga.c
@@ -74,6 +74,16 @@ static struct mutex vga_display_lock;
/* Forward declaration. */
static struct display_ops vga_display_ops;
+/* The current width and height the ncursesw driver is using. */
+static int current_width;
+static int current_height;
+
+/* The cursor state to restore the state to. */
+static int cursor_state;
+
+/* Is set to 1 if the cursor moved out of the physical screen and the
+ cursor state should be hidden. */
+static int cursor_hidden;
struct refchr
{
@@ -318,29 +328,54 @@ vga_display_fini (void *handle, int force)
}
-/* Set the cursor's position on display HANDLE to column COL and row
- ROW. */
+/* Set the cursor's state to STATE on display HANDLE. */
static error_t
-vga_display_set_cursor_pos (void *handle, uint32_t col, uint32_t row)
+vga_display_set_cursor_status (void *handle, uint32_t state)
{
struct vga_display *disp = handle;
- unsigned int pos = row * disp->width + col;
- vga_set_cursor_pos (pos);
+ /* Don't display the cursor if its location is not within the
+ physical screen. */
+ if (!cursor_hidden)
+ {
+ if (state != CONS_CURSOR_INVISIBLE)
+ dynafont_set_cursor (disp->df, state == CONS_CURSOR_VERY_VISIBLE ? 1 : 0);
+
+ vga_display_cursor (state == CONS_CURSOR_INVISIBLE ? 0 : 1);
+ }
+
+ cursor_state = state;
return 0;
}
-/* Set the cursor's state to STATE on display HANDLE. */
+/* Set the cursor's position on display HANDLE to column COL and row
+ ROW. */
static error_t
-vga_display_set_cursor_status (void *handle, uint32_t state)
+vga_display_set_cursor_pos (void *handle, uint32_t col, uint32_t row)
{
struct vga_display *disp = handle;
+ unsigned int pos = row * disp->width + col;
- if (state != CONS_CURSOR_INVISIBLE)
- dynafont_set_cursor (disp->df, state == CONS_CURSOR_VERY_VISIBLE ? 1 : 0);
- vga_display_cursor (state == CONS_CURSOR_INVISIBLE ? 0 : 1);
+ /* Make sure the cursor can only be moved to a position on te
+ physical screen. */
+ if (col < disp->width && row < disp->height)
+ {
+ vga_set_cursor_pos (pos);
+ if (cursor_hidden)
+ {
+ /* Restore the cursor. */
+ cursor_hidden = 0;
+ vga_display_set_cursor_status (handle, cursor_state);
+ }
+ }
+ else if (!cursor_hidden)
+ {
+ /* Hide the cursor. */
+ cursor_hidden = 1;
+ vga_display_cursor (CONS_CURSOR_INVISIBLE);
+ }
return 0;
}
@@ -355,7 +390,12 @@ vga_display_scroll (void *handle, int delta)
int count = abs(delta) * disp->width;
int i;
struct refchr *refpos;
-
+
+ /* XXX: If the virtual console is bigger than the physical console it is
+ impossible to scroll because the data to scroll is not in memory. */
+ if (current_height > disp->height)
+ return ENOTSUP;
+
if (delta > 0)
{
memmove (vga_videomem, vga_videomem + 2 * count,
@@ -485,8 +525,31 @@ static error_t
vga_display_clear (void *handle, size_t length, uint32_t col, uint32_t row)
{
struct vga_display *disp = handle;
- struct refchr *refpos = &disp->refmatrix[row][col];
+ struct refchr *refpos = &disp->refmatrix[row][0];
+ int cols;
+ /* The column can be outside the physical screen, in that case
+ adjust the position. */
+ if (col >= disp->width)
+ {
+ col = disp->width - col;
+ row++;
+ }
+ refpos += col;
+
+ /* The first row is not in the physical screen, nothing has to be
+ done. */
+ if (row >= disp->height)
+ return 0;
+
+ /* The length cannot be used. Recalculate it to wrap the lines. */
+ cols = length / current_width;
+ length = (length % current_width) + cols * disp->width ;
+
+ /* Make sure the end of length is still in the physical screen. */
+ if (length > (disp->width * disp->height - (row * disp->width + col)) - col)
+ length = disp->width * disp->height - (row * disp->width + col) - col;
+
while (length > 0)
{
if (refpos->used)
@@ -511,9 +574,21 @@ vga_display_write (void *handle, conchar_t *str, size_t length,
uint32_t col, uint32_t row)
{
struct vga_display *disp = handle;
- char *pos = vga_videomem + 2 * (row * disp->width + col);
+ char *pos;
struct refchr *refpos = &disp->refmatrix[row][col];
+ /* The starting column is outside the physical screen. */
+ if (disp->width < current_width && col >= disp->width)
+ {
+ size_t skip = current_width - disp->width;
+ str += skip;
+ length -= skip;
+ col = 0;
+ row++;
+ }
+
+ pos = vga_videomem + 2 * (row * disp->width + col);
+
/* Although all references to the current fgcol or bgcol could have
been released here, for example due to a scroll operation, we
know that the color slots have not been reused yet, as no routine
@@ -524,6 +599,31 @@ vga_display_write (void *handle, conchar_t *str, size_t length,
while (length--)
{
int charval = dynafont_lookup (disp->df, str);
+ col++;
+
+ /* The virtual console is smaller than the physical screen. */
+ if (col > current_width)
+ {
+ size_t skip = disp->width - current_width;
+ pos += skip * 2;
+ refpos += skip;
+ col = 1;
+ row++;
+ }
+ /* The virtual console is bigger than the physical console. */
+ else if (disp->width < current_width && col == disp->width)
+ {
+ size_t skip = current_width - disp->width;
+ str += skip;
+ length -= skip;
+ col = 1;
+ row++;
+ }
+
+ /* The screen is filled until the bottom of the screen. */
+ if (row >= disp->height)
+ return 0;
+
if (!disp->cur_conchar_attr_init
|| *(uint32_t *) &disp->cur_conchar_attr != *(uint32_t *) &str->attr)
{
@@ -566,6 +666,21 @@ vga_display_write (void *handle, conchar_t *str, size_t length,
return 0;
}
+static error_t
+vga_set_dimension (void *handle, int width, int height)
+{
+ if (current_width && current_height)
+ vga_display_clear (handle, current_width * current_height, 0, 0);
+
+ current_width = width;
+ current_height = height;
+
+ /* FIXME: Should support greater dimensions by changing the video
+ mode. */
+
+ return 0;
+}
+
struct driver_ops driver_vga_ops =
{
@@ -583,5 +698,6 @@ static struct display_ops vga_display_ops =
vga_display_write,
NULL,
vga_display_flash,
- NULL
+ NULL,
+ vga_set_dimension
};