diff options
Diffstat (limited to 'libcons')
-rw-r--r-- | libcons/Makefile | 38 | ||||
-rw-r--r-- | libcons/cons-lookup.c | 107 | ||||
-rw-r--r-- | libcons/cons-switch.c | 88 | ||||
-rw-r--r-- | libcons/cons.h | 331 | ||||
-rw-r--r-- | libcons/demuxer.c | 30 | ||||
-rw-r--r-- | libcons/dir-changed.c | 129 | ||||
-rw-r--r-- | libcons/extra-version.c | 24 | ||||
-rw-r--r-- | libcons/file-changed.c | 366 | ||||
-rw-r--r-- | libcons/init-init.c | 97 | ||||
-rw-r--r-- | libcons/init-loop.c | 32 | ||||
-rw-r--r-- | libcons/mutations.h | 27 | ||||
-rw-r--r-- | libcons/opts-std-startup.c | 229 | ||||
-rw-r--r-- | libcons/opts-version.c | 44 | ||||
-rw-r--r-- | libcons/priv.h | 93 | ||||
-rw-r--r-- | libcons/vcons-add.c | 30 | ||||
-rw-r--r-- | libcons/vcons-close.c | 45 | ||||
-rw-r--r-- | libcons/vcons-destroy.c | 52 | ||||
-rw-r--r-- | libcons/vcons-event.c | 31 | ||||
-rw-r--r-- | libcons/vcons-input.c | 64 | ||||
-rw-r--r-- | libcons/vcons-move-mouse.c | 103 | ||||
-rw-r--r-- | libcons/vcons-open.c | 175 | ||||
-rw-r--r-- | libcons/vcons-refresh.c | 76 | ||||
-rw-r--r-- | libcons/vcons-remove.c | 31 | ||||
-rw-r--r-- | libcons/vcons-scrollback.c | 164 |
24 files changed, 2406 insertions, 0 deletions
diff --git a/libcons/Makefile b/libcons/Makefile new file mode 100644 index 00000000..38ca74a7 --- /dev/null +++ b/libcons/Makefile @@ -0,0 +1,38 @@ +# +# Copyright (C) 1994,95,96,97,98,99,2000,01,02,2005,2010 Free Software Foundation, Inc. +# +# This program 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. +# +# This program 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +dir := libcons +makemode := library + +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-scrollback.c \ + vcons-input.c vcons-move-mouse.c vcons-event.c +LCLHDRS = priv.h mutations.h $(installhdrs) +installhdrs = cons.h + +fs_notify-MIGSFLAGS = -imacros $(srcdir)/mutations.h +MIGSTUBS = fs_notifyServer.o +OBJS = $(sort $(SRCS:.c=.o) $(MIGSTUBS)) + +HURDLIBS = threads ports + +MIGCOMSFLAGS = -prefix cons_ + +include ../Makeconf diff --git a/libcons/cons-lookup.c b/libcons/cons-lookup.c new file mode 100644 index 00000000..d91cc3ce --- /dev/null +++ b/libcons/cons-lookup.c @@ -0,0 +1,107 @@ +/* cons-lookup.c - Looking up virtual consoles. + 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 <errno.h> +#include <malloc.h> +#include <sys/mman.h> + +#include "cons.h" + +/* Lookup the virtual console entry with number ID in the console + CONS, and return it in R_VCONS_ENTRY. If CREATE is true, the + virtual console entry will be created if it doesn't exist yet. If + CREATE is true, and ID 0, the first free virtual console id is + used. CONS must be locked. */ +error_t +cons_lookup (cons_t cons, int id, int create, vcons_list_t *r_vcons_entry) +{ + vcons_list_t previous_vcons_entry = 0; + vcons_list_t vcons_entry; + + if (!id && !create) + return EINVAL; + + if (id) + { + if (cons->vcons_list && cons->vcons_list->id <= id) + { + previous_vcons_entry = cons->vcons_list; + while (previous_vcons_entry->next + && previous_vcons_entry->next->id <= id) + previous_vcons_entry = previous_vcons_entry->next; + if (previous_vcons_entry->id == id) + { + *r_vcons_entry = previous_vcons_entry; + return 0; + } + } + else if (!create) + return ESRCH; + } + else + { + id = 1; + if (cons->vcons_list && cons->vcons_list->id == 1) + { + previous_vcons_entry = cons->vcons_list; + while (previous_vcons_entry && previous_vcons_entry->id == id) + { + id++; + previous_vcons_entry = previous_vcons_entry->next; + } + } + } + + vcons_entry = calloc (1, sizeof (struct vcons_list)); + if (!vcons_entry) + return ENOMEM; + + vcons_entry->id = id; + vcons_entry->vcons = NULL; + + /* Insert the virtual console into the doubly linked list. */ + if (previous_vcons_entry) + { + vcons_entry->prev = previous_vcons_entry; + if (previous_vcons_entry->next) + { + previous_vcons_entry->next->prev = vcons_entry; + vcons_entry->next = previous_vcons_entry->next; + } + else + cons->vcons_last = vcons_entry; + previous_vcons_entry->next = vcons_entry; + } + else + { + if (cons->vcons_list) + { + cons->vcons_list->prev = vcons_entry; + vcons_entry->next = cons->vcons_list; + } + else + cons->vcons_last = vcons_entry; + cons->vcons_list = vcons_entry; + } + + cons_vcons_add (cons, vcons_entry); + *r_vcons_entry = vcons_entry; + return 0; +} diff --git a/libcons/cons-switch.c b/libcons/cons-switch.c new file mode 100644 index 00000000..752af97e --- /dev/null +++ b/libcons/cons-switch.c @@ -0,0 +1,88 @@ +/* cons-switch.c - Switch to another virtual console. + 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 <errno.h> +#include <assert.h> + +#include "cons.h" + +/* 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) +{ + error_t err = 0; + cons_t cons = vcons->cons; + vcons_list_t vcons_entry = NULL; + + if (!id && !delta) + return 0; + + mutex_lock (&cons->lock); + 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 + { + assert (delta < 0); + vcons_entry = vcons->vcons_entry; + while (delta++ < 0) + { + vcons_entry = vcons_entry->prev; + if (!vcons_entry) + vcons_entry = cons->vcons_last; + } + } + + if (!vcons_entry) + { + mutex_unlock (&cons->lock); + return ESRCH; + } + + if (vcons_entry->vcons) + { + *r_vcons = vcons_entry->vcons; + mutex_lock (&vcons_entry->vcons->lock); + } + else + { + err = cons_vcons_open (cons, vcons_entry, 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 new file mode 100644 index 00000000..e9d01a8c --- /dev/null +++ b/libcons/cons.h @@ -0,0 +1,331 @@ +/* cons.h - Definitions for cons helper and callback functions. + Copyright (C) 2002, 2003, 2005 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. */ + +#ifndef _HURD_CONS_H +#define _HURD_CONS_H + +#include <dirent.h> + +#include <hurd/ports.h> +#include <mach.h> + +#include <hurd/console.h> + +typedef struct cons *cons_t; +typedef struct vcons_list *vcons_list_t; +typedef struct vcons *vcons_t; +typedef struct cons_notify *cons_notify_t; + +struct vcons_list +{ + cons_t cons; + vcons_list_t next; + vcons_list_t prev; + + /* The ID of the virtual console entry in the list. */ + int id; + + /* The opened vcons port on which we receive notifications. */ + vcons_t vcons; +}; + +struct cons_notify +{ + struct port_info pi; + + /* This is set for the dir notification port. */ + cons_t cons; +}; + +struct vcons +{ + /* This must come first for the port info structure. */ + struct cons_notify notify; + + /* These elements are static from creation time. */ + cons_t cons; + vcons_list_t vcons_entry; + int id; + + /* The lock that protects all other members. */ + struct mutex lock; + + /* The FD of the input node. */ + int input; + + /* The shared memory of the display. */ + struct cons_display *display; + size_t display_size; + + struct + { + uint32_t flags; + struct + { + uint32_t col; + uint32_t row; + uint32_t status; + } cursor; + struct + { + uint32_t width; + uint32_t height; + uint32_t lines; + uint32_t cur_line; + uint32_t scr_lines; + conchar_t *matrix; + } screen; + struct + { + uint32_t audible; + uint32_t visible; + } bell; + struct + { + uint32_t written; + uint32_t length; + cons_change_t *buffer; + } changes; + } state; + + uint32_t scrolling; +}; + +struct cons +{ + /* Protects the cons structure and the linked list in + VCONS_LIST. */ + struct mutex lock; + vcons_list_t vcons_list; + vcons_list_t vcons_last; + + struct port_class *port_class; + struct port_bucket *port_bucket; + DIR *dir; + io_t dirport; + int slack; +}; + +/* Determines if the mouse moves relatively, to an absolute location + or to an absolute location expressed by a percentage. */ +enum mouse_movement + { + CONS_VCONS_MOUSE_MOVE_REL, + CONS_VCONS_MOUSE_MOVE_ABS, + CONS_VCONS_MOUSE_MOVE_ABS_PERCENT + }; + +/* The status of a mouse button. */ +enum mouse_button + { + CONS_VCONS_MOUSE_BUTTON_NO_OP, + CONS_VCONS_MOUSE_BUTTON_PRESSED, + CONS_VCONS_MOUSE_BUTTON_RELEASED + }; + +/* An event produced by mouse movement an button presses. */ +typedef struct mouse_event +{ + enum mouse_movement mouse_movement; + float x; + float y; + + enum mouse_button mouse_button; + int button; +} *mouse_event_t; + + +/* The user must define this variable. Set this to the name of the + console client. */ +extern const char *cons_client_name; + +/* The user must define this variable. Set this to be the client + version number. */ +extern const char *cons_client_version; + +/* The user may define this variable. Set this to be any additional + version specification that should be printed for --version. */ +extern char *cons_extra_version; + +/* The user must define this function. Deallocate the scarce + resources (like font glyph slots, colors etc) in the LENGTH entries + of the screen matrix starting from position COL and ROW. This call + is immediately followed by calls to cons_vcons_write that cover the + same area. If there are no scarce resources, the caller might do + nothing. */ +void cons_vcons_clear (vcons_t vcons, size_t length, + uint32_t col, uint32_t row); + +/* The user must define this function. Write LENGTH characters + starting from STR on the virtual console VCONS, which is locked, + starting from position COL and ROW. */ +void cons_vcons_write (vcons_t vcons, conchar_t *str, size_t length, + uint32_t col, uint32_t row); + +/* The user must define this function. Set the cursor on virtual + console VCONS, which is locked, to position COL and ROW. */ +void cons_vcons_set_cursor_pos (vcons_t vcons, uint32_t col, uint32_t row); + +/* The user must define this function. Set the cursor status of + virtual console VCONS, which is locked, to STATUS. */ +void cons_vcons_set_cursor_status (vcons_t vcons, uint32_t status); + +/* The user must define this function. Scroll the content of virtual + console VCONS, which is locked, up by DELTA if DELTA is positive or + down by -DELTA if DELTA is negative. DELTA will never be zero, and + the absolute value if DELTA will be smaller than or equal to the + height of the screen matrix. + + This call will be immediately followed by corresponding + cons_vcons_write calls to fill the resulting gap on the screen, and + VCONS will be looked throughout the whole time. The purpose of the + function is two-fold: It is called with an absolute value of DELTA + smaller than the screen height to perform scrolling. It is called + with an absolute value of DELTA equal to the screen height to + prepare a full refresh of the screen. In the latter case the user + should not really perform any scrolling. Instead it might + deallocate limited resources (like display glyph slots and palette + colors) if that helps to perform the subsequent write, just like + cons_vcons_clear. It goes without saying that the same + deallocation, if any, should be performed on the area that will be + filled with the scrolled in content. + + XXX Possibly need a function to invalidate scrollback buffer, or in + general to signal a switch of the console so state can be reset. + Only do this if we make guarantees about validity of scrollback + buffer, of course. + + The driver is allowed to delay the effect of this operation until + the UPDATE function is called. */ +void cons_vcons_scroll (vcons_t vcons, int delta); + +/* The user may define this function. Make the changes from + cons_vcons_write, cons_vcons_set_cursor_pos, + cons_vcons_set_cursor_status and cons_vcons_scroll active. VCONS + is locked and will have been continuously locked from the first + change since the last update on. This is the latest possible point + the user must make the changes visible from. The user can always + make the changes visible at a more convenient, earlier time. */ +void cons_vcons_update (vcons_t vcons); + +/* The user must define this function. Make the virtual console + VCONS, which is locked, beep audibly. */ +void cons_vcons_beep (vcons_t vcons); + +/* The user must define this function. Make the virtual console + VCONS, which is locked, flash visibly. */ +void cons_vcons_flash (vcons_t vcons); + +/* The user must define this function. Notice the current status of + the scroll lock flag. */ +void cons_vcons_set_scroll_lock (vcons_t vcons, int onoff); + +/* The user must define this function. It is called whenever a + virtual console is selected to be the active one. It is the user's + responsibility to close the console at some later time. */ +error_t cons_vcons_activate (vcons_t vcons); + +/* The user may define this function. It is called after a + virtual console entry was added. CONS is locked. */ +void cons_vcons_add (cons_t cons, vcons_list_t vcons_entry); + +/* The user may define this function. It is called just before a + 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 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); + +/* Enter SIZE bytes from the buffer BUF into the virtual console + VCONS. */ +error_t cons_vcons_input (vcons_t vcons, char *buf, size_t size); + +/* 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); + +typedef enum + { + CONS_SCROLL_DELTA_LINES, CONS_SCROLL_DELTA_SCREENS, + CONS_SCROLL_ABSOLUTE_LINE, CONS_SCROLL_ABSOLUTE_PERCENTAGE + } cons_scroll_t; + +/* Scroll back into the history of VCONS. If TYPE is + CONS_SCROLL_DELTA_LINES, scroll up or down by VALUE lines. If TYPE + is CONS_SCROLL_DELTA_SCREENS, scroll up or down by VALUE multiples + of a screen height. If TYPE is CONS_SCROLL_ABSOLUTE_LINE, scroll to + line VALUE (where 0 is the lowest line). If TYPE is + CONS_SCROLL_ABSOLUTE_PERCENTAGE, scroll to the position determined + by VALUE, where 0 is the bottom and 1 is the top. + + The function returns the number of lines actually scrolled up or + down. */ +int cons_vcons_scrollback (vcons_t vcons, cons_scroll_t type, float value); + +/* Set the mouse cursor position to X, Y. VCONS is locked. */ +error_t cons_vcons_set_mousecursor_pos (vcons_t vcons, float x, float y); + +/* If STATUS is set to 0, hide the mouse cursor, otherwise show + it. VCONS is locked. */ +error_t cons_vcons_set_mousecursor_status (vcons_t vcons, int status); + + + +extern const struct argp cons_startup_argp; + +extern struct port_bucket *cons_port_bucket; +extern struct port_class *cons_port_class; + +/* The filename of the console server. */ +extern char *cons_file; + +error_t cons_init (void); +void cons_server_loop (void); +int cons_demuxer (mach_msg_header_t *inp, mach_msg_header_t *outp); + +/* Lookup the virtual console with number ID in the console CONS, + acquire a reference for it, and return its list entry in R_VCONS. + If CREATE is true, the virtual console will be created if it + doesn't exist yet. If CREATE is true, and ID 0, the first free + virtual console id is used. CONS must be locked. */ +error_t cons_lookup (cons_t cons, int id, int create, vcons_list_t *r_vcons); + +/* Open the virtual console for VCONS_ENTRY. CONS is locked. */ +error_t cons_vcons_open (cons_t cons, vcons_list_t vcons_entry, + vcons_t *r_vcons); + +/* Close the virtual console VCONS. VCONS->cons is locked. */ +void cons_vcons_close (vcons_t vcons); + +/* Destroy the virtual console VCONS. */ +void cons_vcons_destroy (void *port); + +/* Redraw the virtual console VCONS, which is locked. */ +void cons_vcons_refresh (vcons_t vcons); + +/* Handle the event EV on the virtual console VCONS. */ +error_t cons_vcons_move_mouse (vcons_t vcons, mouse_event_t ev); + +#endif /* hurd/cons.h */ diff --git a/libcons/demuxer.c b/libcons/demuxer.c new file mode 100644 index 00000000..8982bfa9 --- /dev/null +++ b/libcons/demuxer.c @@ -0,0 +1,30 @@ +/* demuxer.c - Message demuxer for console client library. + 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 "cons.h" + +int +cons_demuxer (mach_msg_header_t *inp, mach_msg_header_t *outp) +{ + int cons_fs_notify_server (mach_msg_header_t *inp, mach_msg_header_t *outp); + + return (cons_fs_notify_server (inp, outp)); +} + diff --git a/libcons/dir-changed.c b/libcons/dir-changed.c new file mode 100644 index 00000000..e1997d0f --- /dev/null +++ b/libcons/dir-changed.c @@ -0,0 +1,129 @@ +/* dir-changed.c - Handling dir changed notifications. + 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 <errno.h> +#include <dirent.h> +#include <assert.h> +#include <mach.h> +#include <cthreads.h> + +#include "cons.h" +#include "fs_notify_S.h" + + +static error_t +add_one (cons_t cons, char *name) +{ + unsigned long int nr; + char *tail; + + errno = 0; + nr = strtoul (name, &tail, 10); + if (!errno && *tail == '\0' && nr > 0) + { + vcons_list_t vcons_entry; + return cons_lookup (cons, nr, 1, &vcons_entry); + } + return 0; +} + +static error_t +lookup_one (cons_t cons, char *name, vcons_list_t *vcons_entry) +{ + unsigned long int nr; + char *tail; + + errno = 0; + nr = strtoul (name, &tail, 10); + if (!errno && *tail == '\0' && nr > 0) + return cons_lookup (cons, nr, 0, vcons_entry); + return 0; +} + + +kern_return_t +cons_S_dir_changed (cons_notify_t notify, natural_t tickno, + dir_changed_type_t change, string_t name) +{ + error_t err; + cons_t cons; + + if (!notify || !notify->cons) + return EOPNOTSUPP; + cons = notify->cons; + + mutex_lock (&cons->lock); + + switch (change) + { + case DIR_CHANGED_NULL: + { + DIR *dir = cons->dir; + struct dirent *dent; + do + { + errno = 0; + dent = readdir (dir); + if (!dent && errno) + err = errno; + else if (dent) + err = add_one (cons, dent->d_name); + } + while (dent && !err); + if (err) + assert ("Unexpected error"); /* XXX */ + } + break; + case DIR_CHANGED_NEW: + { + err = add_one (cons, name); + if (err) + assert ("Unexpected error"); /* XXX */ + } + break; + case DIR_CHANGED_UNLINK: + { + vcons_list_t vcons_entry; + err = lookup_one (cons, name, &vcons_entry); + if (!err) + { + cons_vcons_remove (cons, vcons_entry); + if (vcons_entry->prev) + vcons_entry->prev->next = vcons_entry->next; + else + cons->vcons_list = vcons_entry->next; + if (vcons_entry->next) + vcons_entry->next->prev = vcons_entry->prev; + else + cons->vcons_last = vcons_entry->prev; + + free (vcons_entry); + } + } + break; + case DIR_CHANGED_RENUMBER: + default: + assert ("Unexpected dir-changed type."); + mutex_unlock (&cons->lock); + return EINVAL; + } + mutex_unlock (&cons->lock); + return 0; +} diff --git a/libcons/extra-version.c b/libcons/extra-version.c new file mode 100644 index 00000000..4ff54d85 --- /dev/null +++ b/libcons/extra-version.c @@ -0,0 +1,24 @@ +/* Default value for cons_extra_version + 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 "priv.h" + +char *cons_extra_version = ""; diff --git a/libcons/file-changed.c b/libcons/file-changed.c new file mode 100644 index 00000000..b12a6f10 --- /dev/null +++ b/libcons/file-changed.c @@ -0,0 +1,366 @@ +/* file-changed.c - Handling file changed notifications. + Copyright (C) 2002, 2003, 2004, 2005 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 <errno.h> +#include <assert.h> + +#include <mach.h> + +#include "cons.h" +#include "fs_notify_S.h" + +kern_return_t +cons_S_file_changed (cons_notify_t notify, natural_t tickno, + file_changed_type_t change, + off_t start, off_t end) +{ + error_t err = 0; + vcons_t vcons = (vcons_t) notify; + + if (!notify || notify->cons) + return EOPNOTSUPP; + + mutex_lock (&vcons->lock); + switch (change) + { + case FILE_CHANGED_NULL: + /* Always sent first for sync. */ + cons_vcons_refresh (vcons); + break; + case FILE_CHANGED_WRITE: + /* File data has been written. */ + while (vcons->state.changes.written < vcons->display->changes.written) + { + cons_change_t change; + + if (vcons->display->changes.written - vcons->state.changes.written + > vcons->cons->slack) + { + cons_vcons_refresh (vcons); + continue; + } + change = vcons->state.changes.buffer[vcons->state.changes.written + % vcons->state.changes.length]; + if (vcons->display->changes.written - vcons->state.changes.written + > vcons->state.changes.length - 1) + { + /* While we were reading the entry, the server might + have overwritten it. */ + cons_vcons_refresh (vcons); + continue; + } + vcons->state.changes.written++; + + if (change.what.not_matrix) + { + 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; + 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_console_event (vcons, CONS_EVT_OUTPUT); + cons_vcons_update (vcons); + } + if (change.what.cursor_status) + { + vcons->state.cursor.status = vcons->display->cursor.status; + cons_vcons_set_cursor_status (vcons, + vcons->state.cursor.status); + cons_vcons_update (vcons); + } + 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 + * vcons->state.screen.lines; + off_t vis_start; + uint32_t scrolling; + off_t start; + off_t end; + + if (new_cur_line > vcons->state.screen.cur_line) + scrolling = new_cur_line + - vcons->state.screen.cur_line; + else + scrolling = UINT32_MAX - vcons->state.screen.cur_line + + 1 + new_cur_line; + + /* If we are scrolling back, defer scrolling + until absolutely necessary. */ + if (vcons->scrolling) + { + if (_cons_jump_down_on_output) + _cons_vcons_scrollback + (vcons, CONS_SCROLL_ABSOLUTE_LINE, 0); + else + { + 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); + else + cons_vcons_clear (vcons, vcons->state.screen.width + * vcons->state.screen.height, + 0, 0); + 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_console_event (vcons, CONS_EVT_OUTPUT); + cons_vcons_update (vcons); + } + vcons->state.screen.cur_line = new_cur_line; + } + } + if (change.what.screen_scr_lines) + { + 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) + { + while (vcons->state.bell.audible + < vcons->display->bell.audible) + { + if (_cons_audible_bell == BELL_AUDIBLE) + cons_vcons_beep (vcons); + else if (_cons_audible_bell == BELL_VISUAL) + cons_vcons_flash (vcons); + vcons->state.bell.audible++; + } + } + if (change.what.bell_visible) + { + while (vcons->state.bell.visible + < vcons->display->bell.visible) + { + if (_cons_visual_bell == BELL_VISUAL) + cons_vcons_flash (vcons); + else if (_cons_visual_bell == BELL_AUDIBLE) + cons_vcons_beep (vcons); + vcons->state.bell.visible++; + } + } + if (change.what.flags) + { + uint32_t flags = vcons->display->flags; + + if ((flags & CONS_FLAGS_SCROLL_LOCK) + != (vcons->state.flags & CONS_FLAGS_SCROLL_LOCK)) + cons_vcons_set_scroll_lock (vcons, flags + & CONS_FLAGS_SCROLL_LOCK); + vcons->state.flags = flags; + } + } + else + { + /* For clipping. */ + off_t size = vcons->state.screen.width*vcons->state.screen.lines; + off_t rotate; + off_t vis_end = vcons->state.screen.height + * vcons->state.screen.width - 1; + off_t end2 = -1; + off_t start_rel = 0; /* start relative to visible start. */ + off_t start = change.matrix.start; + off_t end = change.matrix.end; + + if (vcons->scrolling && _cons_jump_down_on_output) + _cons_vcons_scrollback (vcons, CONS_SCROLL_ABSOLUTE_LINE, 0); + + 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) + start += size; + end -= rotate; + if (end < 0) + end += size; + + /* Find the intersection. */ + if (start > vis_end) + { + if (end < start) + { + start = 0; + if (vis_end < end) + end = vis_end; + } + else + start = -1; + } + else + { + if (end >= start) + { + if (end > vis_end) + end = vis_end; + } + else + { + end2 = end; + end = vis_end; + } + } + /* We now have three cases: No intersection if start == + -1, one intersection [start;end] if end2 == -1, and + two intersections [start;end] and [0;end2] if end2 != + -1. However, we still have to undo the buffer + rotation. */ + if (start != -1) + { + start_rel = start; + start += rotate; + if (start >= size) + start -= size; + end += rotate; + if (end >= size) + end -= size; + if (start > end) + end += size; + } + if (end2 != -1) + /* The interval should be [vis_start:end2]. */ + end2 += rotate; + + if (start != -1) + { + cons_vcons_clear (vcons, end - start + 1, + start_rel % vcons->state.screen.width, + start_rel / vcons->state.screen.width); + cons_vcons_write (vcons, vcons->state.screen.matrix + start, + end < size + ? end - start + 1 + : size - start, + start_rel % vcons->state.screen.width, + start_rel / vcons->state.screen.width); + if (end >= size) + cons_vcons_write (vcons, vcons->state.screen.matrix, + end - size + 1, + (size - rotate) + % vcons->state.screen.width, + (size - rotate) + / vcons->state.screen.width); + if (end2 != -1) + { + cons_vcons_clear (vcons, end2 - rotate + 1, 0, 0); + cons_vcons_write (vcons, + vcons->state.screen.matrix + rotate, + end2 < size + ? end2 - rotate + 1 + : size - rotate, + 0, 0); + if (end2 >= size) + cons_vcons_write (vcons, vcons->state.screen.matrix, + end2 - size + 1, + (size - rotate) + % vcons->state.screen.width, + (size - rotate) + / vcons->state.screen.width); + } + _cons_vcons_console_event (vcons, CONS_EVT_OUTPUT); + cons_vcons_update (vcons); + } + } + } + break; + case FILE_CHANGED_EXTEND: + /* File has grown. */ + case FILE_CHANGED_TRUNCATE: + /* File has been truncated. */ + case FILE_CHANGED_META: + /* Stat information has changed, and none of the previous three + apply. Not sent for changes in node times. */ + default: + err = EINVAL; + }; + + mutex_unlock (&vcons->lock); + return err; +} diff --git a/libcons/init-init.c b/libcons/init-init.c new file mode 100644 index 00000000..eda292f5 --- /dev/null +++ b/libcons/init-init.c @@ -0,0 +1,97 @@ +/* init-init.c - Initialize the console library. + Copyright (C) 1995, 1996, 2002 Free Software Foundation, Inc. + Written by Michael I. Bushnell, p/BSG and 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 <errno.h> +#include <malloc.h> + +#include <hurd.h> +#include <hurd/ports.h> + +#include <mach.h> + +#include "cons.h" +#include "priv.h" + +struct port_bucket *cons_port_bucket; +struct port_class *cons_port_class; + + +error_t +cons_init (void) +{ + error_t err; + cons_t cons; + cons_notify_t dir_notify_port; + mach_port_t dir_notify; + + cons_port_bucket = ports_create_bucket (); + if (!cons_port_bucket) + return errno; + + cons_port_class = ports_create_class (cons_vcons_destroy, NULL); + if (!cons_port_class) + return errno; + + /* Create the console structure. */ + cons = malloc (sizeof (*cons)); + if (!cons) + return errno; + mutex_init (&cons->lock); + cons->vcons_list = NULL; + cons->vcons_last = NULL; + cons->dir = opendir (cons_file); + cons->slack = _cons_slack; + if (!cons->dir) + { + free (cons); + return errno; + } + cons->dirport = getdport (dirfd (cons->dir)); + if (cons->dirport == MACH_PORT_NULL) + { + closedir (cons->dir); + free (cons); + return errno; + } + + /* Request directory notifications. */ + err = ports_create_port (cons_port_class, cons_port_bucket, + sizeof (*dir_notify_port), &dir_notify_port); + if (err) + { + mach_port_deallocate (mach_task_self (), cons->dirport); + closedir (cons->dir); + free (cons); + return err; + } + dir_notify_port->cons = cons; + + dir_notify = ports_get_right (dir_notify_port); + err = dir_notice_changes (cons->dirport, dir_notify, + MACH_MSG_TYPE_MAKE_SEND); + if (err) + { + mach_port_deallocate (mach_task_self (), cons->dirport); + closedir (cons->dir); + free (cons); + return err; + } + return 0; +} diff --git a/libcons/init-loop.c b/libcons/init-loop.c new file mode 100644 index 00000000..18576cb0 --- /dev/null +++ b/libcons/init-loop.c @@ -0,0 +1,32 @@ +/* init-loop.c - Server loop for console client library. + 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 <hurd/ports.h> + +#include "cons.h" + +void +cons_server_loop (void) +{ + ports_manage_port_operations_one_thread (cons_port_bucket, + cons_demuxer, 0); + /* Not reached. */ +} + diff --git a/libcons/mutations.h b/libcons/mutations.h new file mode 100644 index 00000000..af5ab2d0 --- /dev/null +++ b/libcons/mutations.h @@ -0,0 +1,27 @@ +/* mutations.h - MIG mutations for the console client library. + 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. */ + +/* Only CPP macro definitions should go in this file. */ + +#define FS_NOTIFY_INTRAN cons_notify_t begin_using_notify_port (fs_notify_t) +#define FS_NOTIFY_DESTRUCTOR end_using_notify_port (cons_notify_t) + +#define FS_NOTIFY_IMPORTS import "priv.h"; + diff --git a/libcons/opts-std-startup.c b/libcons/opts-std-startup.c new file mode 100644 index 00000000..23bd9971 --- /dev/null +++ b/libcons/opts-std-startup.c @@ -0,0 +1,229 @@ +/* opts-std-startup.c - Standard startup-time command line parser. + Copyright (C) 1995,96,97,98,99,2001,02,2003,2004,2005 Free Software Foundation, Inc. + Written by Miles Bader <miles@gnu.org> and 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include <stdio.h> +#include <argp.h> +#include <string.h> + +#include "priv.h" + + +/* Option keys for long-only options in argp_option. */ +#define OPT_SLACK 600 /* --slack */ +#define OPT_JUMP_DOWN_ON_INPUT 601 /* --jump-down-on-input */ +#define OPT_NO_JUMP_DOWN_ON_INPUT 602 /* --no-jump-down-on-input */ +#define OPT_JUMP_DOWN_ON_OUTPUT 603 /* --jump-down-on-output */ +#define OPT_NO_JUMP_DOWN_ON_OUTPUT 604 /* --no-jump-down-on-output */ +#define OPT_VISUAL_BELL 605 /* --visual-bell */ +#define OPT_AUDIBLE_BELL 606 /* --audible-bell */ +#define OPT_MOUSE_SHOW 607 /* --mouse-show-on */ +#define OPT_MOUSE_HIDE 608 /* --mouse-hide-on */ +#define OPT_MOUSE_SENS 609 /* --mouse-sensitivity */ + +/* The number of records the client is allowed to lag behind the server. */ +#define DEFAULT_SLACK 100 +#define DEFAULT_SLACK_STRING STRINGIFY(DEFAULT_SLACK) +#define STRINGIFY(x) STRINGIFY_1(x) +#define STRINGIFY_1(x) #x + +/* The mouse sensitivity. */ +#define DEFAULT_MOUSE_SENS 3.0 +#define DEFAULT_MOUSE_SENS_STRING STRINGIFY(DEFAULT_MOUSE_SENS) + +/* Number of records the client is allowed to lag behind the + server. */ +int _cons_slack = DEFAULT_SLACK; + +/* If we jump down on input. */ +int _cons_jump_down_on_input = 1; + +/* If we jump down on output. */ +int _cons_jump_down_on_output; + +/* The filename of the console server. */ +char *cons_file; + +/* The type of bell used for the visual bell. */ +bell_type_t _cons_visual_bell = BELL_VISUAL; + +/* The type of bell used for the audible bell. */ +bell_type_t _cons_audible_bell = BELL_AUDIBLE; + +/* The type of events that will make the mouse cursor visible. */ +int _cons_show_mouse = CONS_EVT_MOUSE_MOVE; + +/* The type of events that will hide the mouse cursor. */ +int _cons_hide_mouse = CONS_EVT_KEYPRESS; + +/* The mouse sensitivity. */ +float _cons_mouse_sens = DEFAULT_MOUSE_SENS; + +static const struct argp_option +startup_options[] = +{ + { "slack", OPT_SLACK, "RECORDS", 0, "Max number of records the client is" + " allowed to lag behind the server (default " DEFAULT_SLACK_STRING ")" }, + { "jump-down-on-input", OPT_JUMP_DOWN_ON_INPUT, NULL, 0, + "End scrollback when something is entered (default)" }, + { "no-jump-down-on-input", OPT_NO_JUMP_DOWN_ON_INPUT, NULL, 0, + "End scrollback when something is entered" }, + { "jump-down-on-output", OPT_JUMP_DOWN_ON_OUTPUT, NULL, 0, + "End scrollback when something is printed" }, + { "no-jump-down-on-output", OPT_NO_JUMP_DOWN_ON_OUTPUT, NULL, 0, + "End scrollback when something is printed (default)" }, + { "visual-bell", OPT_VISUAL_BELL, "BELL", 0, "Visual bell: on (default), " + "off, visual, audible" }, + { "audible-bell", OPT_AUDIBLE_BELL, "BELL", 0, "Audible bell: on (default), " + "off, visual, audible" }, + { "mouse-show-on", OPT_MOUSE_SHOW, "EVENTS", 0, "One or more of the events" + " mousemove, mousebutton, keypress, output (default is mousemove), if one" + " of these events occur the mouse cursor will be made visible" }, + { "mouse-hide-on", OPT_MOUSE_HIDE, "EVENTS", 0, "One or more of the events" + " mousemove, mousebutton, keypress, output (default is keypress), if one" + " of these events occur the mouse cursor will be hidden " }, + { "mouse-sensitivity", OPT_MOUSE_SENS, "SENSITIVITY", 0, "The mouse" + " sensitivity (default " DEFAULT_MOUSE_SENS_STRING "). A lower value" + " means more sensitive" }, + { 0, 0 } +}; + +static const char args_doc[] = "CONSOLE"; +static const char doc[] = "A console client."; + + +static error_t +parse_startup_opt (int opt, char *arg, struct argp_state *state) +{ + int parse_events (char *events) + { + char *evtstr = strdupa (events); + char *tok = strtok (evtstr, ","); + int evmask = 0; + + while (tok) + { + if (!strcasecmp ("mousemove", tok)) + evmask |= CONS_EVT_MOUSE_MOVE; + else if (!strcasecmp ("mousebutton", tok)) + evmask |= CONS_EVT_MOUSE_BUTTON; + else if (!strcasecmp ("keypress", tok)) + evmask |= CONS_EVT_KEYPRESS; + else if (!strcasecmp ("output", tok)) + evmask |= CONS_EVT_OUTPUT; + else + argp_error (state, "The event can be one of: MOUSEMOVE," + " MOUSEBUTTON, KEYPRESS or OUTPUT"); + tok = strtok (NULL, ","); + } + return evmask; + } + + switch (opt) + { + case OPT_SLACK: + _cons_slack = atoi (arg); + break; + + case OPT_JUMP_DOWN_ON_INPUT: + _cons_jump_down_on_input = 1; + break; + + case OPT_NO_JUMP_DOWN_ON_INPUT: + _cons_jump_down_on_input = 0; + break; + + case OPT_JUMP_DOWN_ON_OUTPUT: + _cons_jump_down_on_output = 1; + break; + + case OPT_NO_JUMP_DOWN_ON_OUTPUT: + _cons_jump_down_on_output = 0; + break; + + case OPT_AUDIBLE_BELL: + if (!strcasecmp ("on", arg) || !strcasecmp ("audible", arg)) + _cons_audible_bell = BELL_AUDIBLE; + else if (!strcasecmp ("off", arg)) + _cons_audible_bell = BELL_OFF; + else if (!strcasecmp ("visual", arg)) + _cons_audible_bell = BELL_VISUAL; + else + argp_error (state, "The audible bell can be one of: on, off, visual, " + "audible"); + break; + + case OPT_VISUAL_BELL: + if (!strcasecmp ("on", arg) || !strcasecmp ("visual", arg)) + _cons_visual_bell = BELL_VISUAL; + else if (!strcasecmp ("off", arg)) + _cons_visual_bell = BELL_OFF; + else if (!strcasecmp ("audible", arg)) + _cons_visual_bell = BELL_AUDIBLE; + else + argp_error (state, "The visual bell can be one of: on, off, visual, " + "audible"); + break; + + case OPT_MOUSE_SHOW: + _cons_show_mouse = parse_events (arg); + break; + + case OPT_MOUSE_HIDE: + _cons_hide_mouse = parse_events (arg); + break; + + case OPT_MOUSE_SENS: + { + char *tail; + + errno = 0; + _cons_mouse_sens = strtod (arg, &tail); + if (tail == NULL || tail == arg || *tail != '\0') + argp_error (state, "SENSITIVITY is not a number: %s", arg); + if (errno) + argp_error (state, "Overflow in argument SENSITIVITY %s", arg); + break; + } + + case ARGP_KEY_ARG: + if (state->arg_num > 0) + /* Too many arguments. */ + argp_error (state, "Too many non option arguments"); + cons_file = arg; + break; + + case ARGP_KEY_NO_ARGS: + argp_error (state, "Filename of console server missing"); + break; + + default: + return ARGP_ERR_UNKNOWN; + } + + return 0; +} + +/* An argp structure for the standard console client command line + arguments. */ +const struct argp +cons_startup_argp = +{ + startup_options, parse_startup_opt, args_doc, doc +}; diff --git a/libcons/opts-version.c b/libcons/opts-version.c new file mode 100644 index 00000000..f8751490 --- /dev/null +++ b/libcons/opts-version.c @@ -0,0 +1,44 @@ +/* opts-version.c - Default hook for argp --version handling + Copyright (C) 1996, 2002 Free Software Foundation, Inc. + Written by Miles Bader <miles@gnu.ai.mit.edu> and 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include <stdio.h> +#include <argp.h> +#include <version.h> + +#include "priv.h" + +static void +_print_version (FILE *stream, struct argp_state *state) +{ + if (argp_program_version) + /* If this is non-zero, then the program's probably defined it, so let + that take precedence over the default. */ + fputs (argp_program_version, stream); + else if (cons_extra_version && *cons_extra_version) + fprintf (stream, "%s (%s) %s\n", + cons_client_name, cons_extra_version, cons_client_version); + else + fprintf (stream, "%s %s\n", cons_client_name, cons_client_version); + + fputs (STANDARD_HURD_VERSION (libcons) "\n", stream); +} + +void (*argp_program_version_hook) (FILE *stream, struct argp_state *state) + = _print_version; diff --git a/libcons/priv.h b/libcons/priv.h new file mode 100644 index 00000000..38971ff8 --- /dev/null +++ b/libcons/priv.h @@ -0,0 +1,93 @@ +/* Private declarations for cons library + Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. + + This program 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. + + This program 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef _CONS_PRIV_H +#define _CONS_PRIV_H + +#include "cons.h" + + +/* The kind of bells available. */ +typedef enum + { + BELL_OFF, + BELL_VISUAL, + BELL_AUDIBLE + } bell_type_t; + +#define CONS_EVT_MOUSE_MOVE (1 << 1) +#define CONS_EVT_MOUSE_BUTTON (1 << 2) +#define CONS_EVT_KEYPRESS (1 << 4) +#define CONS_EVT_OUTPUT (1 << 8) + + +/* Number of records the client is allowed to lag behind the + server. */ +extern int _cons_slack; + +/* If we jump down at input. */ +extern int _cons_jump_down_on_input; + +/* If we jump down at output. */ +extern int _cons_jump_down_on_output; + +/* The type of bell used for the visual bell. */ +extern bell_type_t _cons_visual_bell; + +/* The type of bell used for the audible bell. */ +extern bell_type_t _cons_audible_bell; + +/* The type of events that will make the mouse cursor visible. */ +extern int _cons_show_mouse; + +/* The type of events that will hide the mouse cursor. */ +extern int _cons_hide_mouse; + +/* The mouse sensitivity. */ +extern float _cons_mouse_sens; + + +/* Non-locking version of cons_vcons_scrollback. Does also not update + the display. */ +int _cons_vcons_scrollback (vcons_t vcons, cons_scroll_t type, float value); + +/* Non-locking version of cons_vcons_input. */ +error_t _cons_vcons_input (vcons_t vcons, char *buf, size_t size); + +/* Generate the console event EVENT for console VCONS. */ +void _cons_vcons_console_event (vcons_t vcons, int event); + + +/* Called by MiG to translate ports into cons_notify_t. mutations.h + arranges for this to happen for the fs_notify interfaces. */ +static inline cons_notify_t +begin_using_notify_port (fs_notify_t port) +{ + return ports_lookup_port (cons_port_bucket, port, cons_port_class); +} + +/* Called by MiG after server routines have been run; this balances + begin_using_notify_port, and is arranged for the fs_notify + interfaces by mutations.h. */ +static inline void +end_using_notify_port (cons_notify_t cred) +{ + if (cred) + ports_port_deref (cred); +} + +#endif /* _CONS_PRIV_H */ diff --git a/libcons/vcons-add.c b/libcons/vcons-add.c new file mode 100644 index 00000000..1a6eb204 --- /dev/null +++ b/libcons/vcons-add.c @@ -0,0 +1,30 @@ +/* vcons-add.c - Add a virtual console. + 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 <errno.h> + +#include "cons.h" + +/* The virtual console entry VCONS_ENTRY was just added. CONS is + locked. */ +void +cons_vcons_add (cons_t cons, vcons_list_t vcons_entry) +{ +} diff --git a/libcons/vcons-close.c b/libcons/vcons-close.c new file mode 100644 index 00000000..33a38982 --- /dev/null +++ b/libcons/vcons-close.c @@ -0,0 +1,45 @@ +/* vcons-close.c - Close a virtual console. + 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 <assert.h> + +#include <hurd.h> +#include <hurd/ports.h> +#include <cthreads.h> + +#include "cons.h" + +/* Close the virtual console VCONS. */ +void +cons_vcons_close (vcons_t vcons) +{ + cons_t cons = vcons->cons; + vcons_list_t vcons_entry = vcons->vcons_entry; + + mutex_lock (&cons->lock); + /* The same virtual console should never be opened twice. */ + assert (vcons_entry->vcons == vcons); + vcons_entry->vcons = NULL; + mutex_unlock (&cons->lock); + + /* Destroy the port. */ + ports_port_deref (vcons); + ports_destroy_right (vcons); +} diff --git a/libcons/vcons-destroy.c b/libcons/vcons-destroy.c new file mode 100644 index 00000000..ca1c5c37 --- /dev/null +++ b/libcons/vcons-destroy.c @@ -0,0 +1,52 @@ +/* vcons-destroy.c - Clean up the resources for a virtual console. + 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 <errno.h> +#include <unistd.h> +#include <stdio.h> +#include <sys/mman.h> +#include <sys/fcntl.h> + +#include <hurd.h> +#include <mach.h> + +#include "cons.h" + +/* Destroy the virtual console VCONS. */ +void +cons_vcons_destroy (void *port) +{ + cons_notify_t notify = (cons_notify_t) port; + vcons_t vcons = (vcons_t) port; + + if (notify->cons) + return; + + if (vcons->input >= 0) + { + close (vcons->input); + vcons->input = -1; + } + if (vcons->display != MAP_FAILED) + { + munmap (vcons->display, vcons->display_size); + vcons->display = MAP_FAILED; + } +} diff --git a/libcons/vcons-event.c b/libcons/vcons-event.c new file mode 100644 index 00000000..d8c31dc0 --- /dev/null +++ b/libcons/vcons-event.c @@ -0,0 +1,31 @@ +/* vcons-event.c - Handle console events. + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + Written by Marco Gerards. + + 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 "cons.h" +#include "priv.h" + +void +_cons_vcons_console_event (vcons_t vcons, int event) +{ + if (_cons_show_mouse & event) + cons_vcons_set_mousecursor_status (vcons, 1); + else if (_cons_hide_mouse & event) + cons_vcons_set_mousecursor_status (vcons, 0); +} diff --git a/libcons/vcons-input.c b/libcons/vcons-input.c new file mode 100644 index 00000000..e008b9c9 --- /dev/null +++ b/libcons/vcons-input.c @@ -0,0 +1,64 @@ +/* vcons-input.c - Add input to a virtual console. + Copyright (C) 2002, 2004, 2005 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 <errno.h> +#include <unistd.h> + +#include "cons.h" +#include "priv.h" + +/* Non-locking version of cons_vcons_input. */ +error_t +_cons_vcons_input (vcons_t vcons, char *buf, size_t size) +{ + int ret; + + do + { + ret = write (vcons->input, buf, size); + if (ret > 0) + { + size -= ret; + buf += ret; + } + } + while (size && (ret != -1 || errno == EINTR)); + + return 0; +} + + +/* Enter SIZE bytes from the buffer BUF into the virtual console + VCONS. */ +error_t +cons_vcons_input (vcons_t vcons, char *buf, size_t size) +{ + mutex_lock (&vcons->lock); + + _cons_vcons_console_event (vcons, CONS_EVT_KEYPRESS); + + if (vcons->scrolling && _cons_jump_down_on_input) + _cons_vcons_scrollback (vcons, CONS_SCROLL_ABSOLUTE_LINE, 0); + + _cons_vcons_input (vcons, buf, size); + + mutex_unlock (&vcons->lock); + return 0; +} diff --git a/libcons/vcons-move-mouse.c b/libcons/vcons-move-mouse.c new file mode 100644 index 00000000..1e5f7b9f --- /dev/null +++ b/libcons/vcons-move-mouse.c @@ -0,0 +1,103 @@ +/* vcons-move-mouse.c - Catch mouse events. + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + Written by Marco Gerards. + + 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 <errno.h> +#include <unistd.h> + +#include "cons.h" +#include "priv.h" + +static float mousepos_x; +static float mousepos_y; + +error_t +cons_vcons_move_mouse (vcons_t vcons, mouse_event_t ev) +{ + char event[CONS_MOUSE_EVENT_LENGTH]; + uint32_t report_events; + + mutex_lock (&vcons->lock); + report_events = vcons->display->flags & CONS_FLAGS_TRACK_MOUSE; + + switch (ev->mouse_movement) + { + case CONS_VCONS_MOUSE_MOVE_REL: + mousepos_x += ((float) ev->x / _cons_mouse_sens); + mousepos_y += ((float) ev->y / _cons_mouse_sens); + break; + + case CONS_VCONS_MOUSE_MOVE_ABS_PERCENT: + mousepos_x = vcons->state.screen.width * ev->x / 100; + mousepos_y = vcons->state.screen.height * ev->y / 100; + + case CONS_VCONS_MOUSE_MOVE_ABS: + mousepos_x = ev->x; + mousepos_y = ev->y; + break; + } + + /* Keep the mouse cursor in range of the VC. */ + if (mousepos_x < 0) + mousepos_x = 0; + if (mousepos_y < 0) + mousepos_y = 0; + if (mousepos_x >= (float) vcons->state.screen.width) + mousepos_x = vcons->state.screen.width - 1; + if (mousepos_y >= (float) vcons->state.screen.height) + mousepos_y = vcons->state.screen.height - 1; + + cons_vcons_set_mousecursor_pos (vcons, (float) mousepos_x, (float) mousepos_y); + + /* Report a mouse movement event. */ + if (ev->x || ev->y) + _cons_vcons_console_event (vcons, CONS_EVT_MOUSE_MOVE); + + /* Report a mouse button event. */ + if (ev->mouse_button != CONS_VCONS_MOUSE_BUTTON_NO_OP) + _cons_vcons_console_event (vcons, CONS_EVT_MOUSE_BUTTON); + + if (report_events) + { + switch (ev->mouse_button) + { + case CONS_VCONS_MOUSE_BUTTON_NO_OP: + break; + + case CONS_VCONS_MOUSE_BUTTON_PRESSED: + /* Make an xterm like event string. */ + CONS_MOUSE_EVENT (event, ev->button, (int) mousepos_x + 1, (int) mousepos_y + 1); + + _cons_vcons_input (vcons, event, CONS_MOUSE_EVENT_LENGTH); + /* And send it to the server. */ + break; + + case CONS_VCONS_MOUSE_BUTTON_RELEASED: + /* Make an xterm like event string. */ + CONS_MOUSE_EVENT (event, CONS_MOUSE_RELEASE, (int) mousepos_x + 1, (int) mousepos_y + 1); + + /* And send it to the server. */ + _cons_vcons_input (vcons, event, CONS_MOUSE_EVENT_LENGTH); + break; + } + } + + mutex_unlock (&vcons->lock); + return 0; +} diff --git a/libcons/vcons-open.c b/libcons/vcons-open.c new file mode 100644 index 00000000..8c34fc5e --- /dev/null +++ b/libcons/vcons-open.c @@ -0,0 +1,175 @@ +/* vcons-open.c - Open a virtual console. + 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 <errno.h> +#include <unistd.h> +#include <stdio.h> +#include <sys/mman.h> +#include <sys/fcntl.h> + +#include <hurd.h> +#include <mach.h> + +#include "cons.h" + +/* Open the virtual console for VCONS_ENTRY. CONS is locked. + Afterwards, R_VCONS will be locked. */ +error_t +cons_vcons_open (cons_t cons, vcons_list_t vcons_entry, vcons_t *r_vcons) +{ + error_t err = 0; + char *name; + file_t vconsp = MACH_PORT_NULL; + file_t file = MACH_PORT_NULL; + int fd = -1; + struct stat statbuf; + mach_port_t notify = MACH_PORT_NULL; + vcons_t vcons; + + if (asprintf (&name, "%u", vcons_entry->id) < 0) + return err; + + /* Set up the port we receive notification messages on. */ + err = ports_create_port (cons_port_class, cons_port_bucket, + sizeof (*vcons), &vcons); + if (err) + goto err; + vcons->notify.cons = NULL; + 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, + O_DIRECTORY | O_RDONLY, 0); + if (vconsp == MACH_PORT_NULL) + { + err = errno; + goto err; + } + + /* Within that directory, open the input node. */ + file = file_name_lookup_under (vconsp, "input", O_WRONLY /* | O_NONBLOCK */, 0); + if (file == MACH_PORT_NULL) + err = errno; + else + { + vcons->input = openport (file, O_WRONLY /* | O_NONBLOCK */); + if (vcons->input < 0) + err = errno; + else + /* openport() consumed the reference. */ + file = MACH_PORT_NULL; + } + if (err) + goto err; + + /* Within that directory, also open the display node. */ + file = file_name_lookup_under (vconsp, "display", O_RDONLY, 0); + if (file == MACH_PORT_NULL) + err = errno; + else + { + /* Acquire an additional reference for openport(). */ + err = mach_port_mod_refs (mach_task_self (), file, + MACH_PORT_RIGHT_SEND, +1); + if (err) + goto err; + fd = openport (file, O_RDONLY); + if (fd < 0) + err = errno; + } + if (err) + goto err; + + /* Map the whole file. */ + if (fstat (fd, &statbuf) < 0) + { + err = errno; + goto err; + } + vcons->display_size = statbuf.st_size; + vcons->display = mmap (0, vcons->display_size, PROT_READ, MAP_SHARED, fd, 0); + if (vcons->display == MAP_FAILED) + { + err = errno; + goto err; + } + + if (vcons->display->magic != CONS_MAGIC + || vcons->display->version >> CONS_VERSION_MAJ_SHIFT != 0) + { + err = EINVAL; + goto err; + } + vcons->state.screen.width = vcons->display->screen.width; + vcons->state.screen.height = vcons->display->screen.height; + vcons->state.screen.lines = vcons->display->screen.lines; + vcons->state.screen.matrix = (conchar_t *) + (((uint32_t *) vcons->display) + vcons->display->screen.matrix); + vcons->state.changes.length = vcons->display->changes.length; + vcons->state.changes.buffer = (cons_change_t *) + (((uint32_t *) vcons->display) + vcons->display->changes.buffer); + + /* Request notification messages. */ + notify = ports_get_right (vcons); + mach_port_set_qlimit (mach_task_self (), notify, 1); + + /* When this succeeds, we will immediately receive notification + messages for this virtual console. */ + mutex_lock (&vcons->lock); + err = file_notice_changes (file, notify, MACH_MSG_TYPE_MAKE_SEND); + if (!err) + { + *r_vcons = vcons; + goto out; + } + + err: + if (vcons->input >= 0) + { + close (vcons->input); + vcons->input = -1; + } + if (vcons->display != MAP_FAILED) + { + munmap (vcons->display, vcons->display_size); + vcons->display = MAP_FAILED; + } + if (notify) + { + mach_port_deallocate (mach_task_self (), notify); + ports_port_deref (vcons); + } + ports_destroy_right (vcons); + out: + if (fd > 0) + close (fd); + if (file != MACH_PORT_NULL) + mach_port_deallocate (mach_task_self (), file); + if (vconsp != MACH_PORT_NULL) + mach_port_deallocate (mach_task_self (), vconsp); + free (name); + return err; +} diff --git a/libcons/vcons-refresh.c b/libcons/vcons-refresh.c new file mode 100644 index 00000000..ce6807fe --- /dev/null +++ b/libcons/vcons-refresh.c @@ -0,0 +1,76 @@ +/* vcons-refresh.c - Redraw a virtual console. + Copyright (C) 2002, 2003, 2004, 2005 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 <errno.h> +#include <assert.h> + +#include "cons.h" +#include "priv.h" + +/* Redraw the virtual console VCONS, which is locked. */ +void +cons_vcons_refresh (vcons_t vcons) +{ + uint32_t start; + vcons->state.screen.cur_line = vcons->display->screen.cur_line; + vcons->state.screen.scr_lines = vcons->display->screen.scr_lines; + vcons->state.cursor.col = vcons->display->cursor.col; + vcons->state.cursor.row = vcons->display->cursor.row; + vcons->state.cursor.status = vcons->display->cursor.status; + vcons->state.bell.audible = vcons->display->bell.audible; + vcons->state.bell.visible = vcons->display->bell.visible; + vcons->state.flags = vcons->display->flags; + vcons->state.changes.written = vcons->display->changes.written; + + if (vcons->state.screen.scr_lines < vcons->scrolling) + vcons->scrolling = vcons->scrolling; + + cons_vcons_set_dimension (vcons, vcons->state.screen.width, + vcons->state.screen.height); + + if (vcons->state.screen.cur_line >= vcons->scrolling) + start = vcons->state.screen.cur_line - vcons->scrolling; + else + start = (UINT32_MAX + - (vcons->scrolling - vcons->state.screen.cur_line)) + 1; + start %= vcons->state.screen.lines; + + cons_vcons_write (vcons, vcons->state.screen.matrix + + start * vcons->state.screen.width, + ((vcons->state.screen.lines - start + < vcons->state.screen.height) + ? vcons->state.screen.lines - start + : vcons->state.screen.height) + * vcons->state.screen.width, 0, 0); + if (vcons->state.screen.lines - start < vcons->state.screen.height) + cons_vcons_write (vcons, vcons->state.screen.matrix, + vcons->state.screen.height * vcons->state.screen.width + - (vcons->state.screen.lines - start) + * vcons->state.screen.width, 0, + vcons->state.screen.lines - start); + + cons_vcons_set_cursor_pos (vcons, vcons->state.cursor.col, + vcons->state.cursor.row); + cons_vcons_set_cursor_status (vcons, vcons->state.cursor.status); + cons_vcons_set_scroll_lock (vcons, vcons->state.flags + & CONS_FLAGS_SCROLL_LOCK); + _cons_vcons_console_event (vcons, CONS_EVT_OUTPUT); + cons_vcons_update (vcons); +} diff --git a/libcons/vcons-remove.c b/libcons/vcons-remove.c new file mode 100644 index 00000000..34b31d6f --- /dev/null +++ b/libcons/vcons-remove.c @@ -0,0 +1,31 @@ +/* vcons-remove.c - Remove a virtual console. + 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 <assert.h> + +#include "cons.h" + +/* The virtual console VCONS_ENTRY is going to be removed. + VCONS_ENTRY->cons is locked. */ +void +cons_vcons_remove (cons_t cons, vcons_list_t vcons_entry) +{ + assert (!vcons_entry->vcons); +} diff --git a/libcons/vcons-scrollback.c b/libcons/vcons-scrollback.c new file mode 100644 index 00000000..77c8c211 --- /dev/null +++ b/libcons/vcons-scrollback.c @@ -0,0 +1,164 @@ +/* vcons-scrollback.c - Move forward and backward in the scrollback buffer. + Copyright (C) 2002, 2004, 2005 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" +#include "priv.h" + +/* Non-locking version of cons_vcons_scrollback. Does also not update + the display. */ +int +_cons_vcons_scrollback (vcons_t vcons, cons_scroll_t type, float value) +{ + int scrolling; + uint32_t new_scr; + + switch (type) + { + case CONS_SCROLL_DELTA_LINES: + scrolling = vcons->scrolling + ((uint32_t) value); + break; + case CONS_SCROLL_DELTA_SCREENS: + scrolling = vcons->scrolling + + ((uint32_t) (value * vcons->state.screen.height)); + break; + case CONS_SCROLL_ABSOLUTE_LINE: + scrolling = (uint32_t) value; + break; + case CONS_SCROLL_ABSOLUTE_PERCENTAGE: + scrolling = (uint32_t) (value * vcons->state.screen.scr_lines); + break; + default: + return 0; + } + + if (scrolling < 0) + new_scr = 0; + else if (scrolling > vcons->state.screen.scr_lines) + new_scr = vcons->state.screen.scr_lines; + else + new_scr = scrolling; + + if (new_scr == vcons->scrolling) + 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); + else if ((scrolling > 0 && scrolling == vcons->state.screen.height) + || (scrolling < 0 + && (uint32_t) (-scrolling) == vcons->state.screen.height)) + cons_vcons_clear (vcons, vcons->state.screen.width + * vcons->state.screen.height, 0, 0); + + 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); + } + + vcons->scrolling -= scrolling; + + return -scrolling; +} + +/* Scroll back into the history of VCONS. If TYPE is + CONS_SCROLL_DELTA_LINES, scroll up or down by VALUE lines. If TYPE + is CONS_SCROLL_DELTA_SCREENS, scroll up or down by VALUE multiples + of a screen height. If TYPE is CONS_SCROLL_ABSOLUTE_LINE, scroll to + line VALUE (where 0 is the lowest line). If TYPE is + CONS_SCROLL_ABSOLUTE_PERCENTAGE, scroll to the position determined + by VALUE, where 0 is the bottom and 1 is the top. + + The function returns the number of lines actually scrolled up or + down. */ +int +cons_vcons_scrollback (vcons_t vcons, cons_scroll_t type, float value) +{ + int ret; + + mutex_lock (&vcons->lock); + ret = _cons_vcons_scrollback (vcons, type, value); + _cons_vcons_console_event (vcons, CONS_EVT_OUTPUT); + cons_vcons_update (vcons); + mutex_unlock (&vcons->lock); + return ret; +} + |