diff options
author | Marcus Brinkmann <marcus@gnu.org> | 2002-06-24 01:05:27 +0000 |
---|---|---|
committer | Marcus Brinkmann <marcus@gnu.org> | 2002-06-24 01:05:27 +0000 |
commit | 52be5cefb4852e6c2921fd1b19c4d0b4952860ea (patch) | |
tree | c2c5d6d53248df64e218b6148a95c26825a5b5bf | |
parent | 98f81ca345424f0e3af7bd4c4eb492481b7f3573 (diff) |
2002-06-24 Marcus Brinkmann <marcus@gnu.org>
* console.h (cons_color_t): New enum type replacing color macros.
(CONS_COLOR_MAX): New macro.
(cons_change_t): New type.
(struct cons_display): New member CHANGES.
* console.c: Include "console.h".
(DEFAULT_FOREGROUND, DEFAULT_FOREGROUND_NAME, DEFAULT_BACKGROUND,
DEFAULT_BACKGROUND_NAME): New macros.
(struct cons): New members foreground and background.
(vcons_lookup): Pass colors to display_create invocation.
(new_node): Fix st_size for display node.
(color_names): New array.
(options): Add options to set default foreground and background
color.
(parse_color): New function.
(parse_opt): Implement new options.
(netfs_append_args): Add new options to output.
(main): Set default colors.
* Makefile (DIST_FILES): Remove target.
(MIGSTUBS): Remove ourfs_notifyUser.o and add notifyServer.o.
* display.c: Do not include "ourfs_notify_U.h".
(struct modreq): New member PENDING.
(struct notify): New structure.
(struct display): New members FILEMOD_REQS_PENDING and
NOTIFY_PORT.
(pager_read_page): Hand out previously returned pages.
(pager_unlock_page): Assert that this is not called.
(notify_class, notify_bucket): New port class and bucket global
variables.
(nowait_file_changed): New function, modified from mig output.
(do_mach_notify_port_deleted): New stub function.
(do_mach_notify_port_destroyed): New stub function.
(do_mach_notify_no_senders): New stub function.
(do_mach_notify_dead_name): New stub function.
(do_mach_notify_send_once): New stub function.
(do_mach_notify_msg_accepted): New function.
(service_notifications): New function.
(display_notice_changes): Call nowait_file_changed with new
argument. Initialize REQ->pending.
(display_notice_filechange): Remove arguments except DISPLAY. Set
PENDING flags in pending filemod requests. Call
nowait_file_changed with new notify argument. If notification
will be sent, move modreq structure to pending list.
(display_flush_filechange): Rewritten to use ring buffer to store
changes.
(user_create): Initialize new members of struct cons_display.
(display_init): Initialize notify_class and notify_bucket.
(display_create): Accept new arguments for default colors.
Initialize new members of struct display.
(display_destroy): Remove pending filemod requests and destroy the
notification port. Do not free the display structure memory.
(display_destroy_complete): New function.
* display.h: Add new arguments to prototype of display_create.
-rw-r--r-- | console/ChangeLog | 56 | ||||
-rw-r--r-- | console/Makefile | 3 | ||||
-rw-r--r-- | console/console.c | 90 | ||||
-rw-r--r-- | console/console.h | 46 | ||||
-rw-r--r-- | console/display.c | 436 | ||||
-rw-r--r-- | console/display.h | 5 |
6 files changed, 520 insertions, 116 deletions
diff --git a/console/ChangeLog b/console/ChangeLog index 9e86d139..806c95aa 100644 --- a/console/ChangeLog +++ b/console/ChangeLog @@ -1,3 +1,59 @@ +2002-06-24 Marcus Brinkmann <marcus@gnu.org> + + * console.h (cons_color_t): New enum type replacing color macros. + (CONS_COLOR_MAX): New macro. + (cons_change_t): New type. + (struct cons_display): New member CHANGES. + * console.c: Include "console.h". + (DEFAULT_FOREGROUND, DEFAULT_FOREGROUND_NAME, DEFAULT_BACKGROUND, + DEFAULT_BACKGROUND_NAME): New macros. + (struct cons): New members foreground and background. + (vcons_lookup): Pass colors to display_create invocation. + (new_node): Fix st_size for display node. + (color_names): New array. + (options): Add options to set default foreground and background + color. + (parse_color): New function. + (parse_opt): Implement new options. + (netfs_append_args): Add new options to output. + (main): Set default colors. + + * Makefile (DIST_FILES): Remove target. + (MIGSTUBS): Remove ourfs_notifyUser.o and add notifyServer.o. + * display.c: Do not include "ourfs_notify_U.h". + (struct modreq): New member PENDING. + (struct notify): New structure. + (struct display): New members FILEMOD_REQS_PENDING and + NOTIFY_PORT. + (pager_read_page): Hand out previously returned pages. + (pager_unlock_page): Assert that this is not called. + (notify_class, notify_bucket): New port class and bucket global + variables. + (nowait_file_changed): New function, modified from mig output. + (do_mach_notify_port_deleted): New stub function. + (do_mach_notify_port_destroyed): New stub function. + (do_mach_notify_no_senders): New stub function. + (do_mach_notify_dead_name): New stub function. + (do_mach_notify_send_once): New stub function. + (do_mach_notify_msg_accepted): New function. + (service_notifications): New function. + (display_notice_changes): Call nowait_file_changed with new + argument. Initialize REQ->pending. + (display_notice_filechange): Remove arguments except DISPLAY. Set + PENDING flags in pending filemod requests. Call + nowait_file_changed with new notify argument. If notification + will be sent, move modreq structure to pending list. + (display_flush_filechange): Rewritten to use ring buffer to store + changes. + (user_create): Initialize new members of struct cons_display. + (display_init): Initialize notify_class and notify_bucket. + (display_create): Accept new arguments for default colors. + Initialize new members of struct display. + (display_destroy): Remove pending filemod requests and destroy the + notification port. Do not free the display structure memory. + (display_destroy_complete): New function. + * display.h: Add new arguments to prototype of display_create. + 2002-06-18 Marcus Brinkmann <marcus@gnu.org> * console.h: Update all CONS_KEY_* macros to match other terminfo diff --git a/console/Makefile b/console/Makefile index 2f15f1a1..6498e8e4 100644 --- a/console/Makefile +++ b/console/Makefile @@ -25,9 +25,8 @@ target = console SRCS = console.c display.c input.c LCLHDRS = console.h display.h input.h -DIST_FILES = ourfs_notify.defs -MIGSTUBS = ourfs_notifyUser.o +MIGSTUBS = notifyServer.o HURDLIBS = netfs fshelp iohelp threads ports ihash shouldbeinlibc OBJS = $(sort $(SRCS:.c=.o) $(MIGSTUBS)) diff --git a/console/console.c b/console/console.c index 8500c84c..43f18e6e 100644 --- a/console/console.c +++ b/console/console.c @@ -39,6 +39,8 @@ #include "display.h" #include "input.h" +/* We include console.h for the color numbers. */ +#include "console.h" const char *argp_program_version = STANDARD_HURD_VERSION (console); @@ -50,6 +52,12 @@ int netfs_maxsymlinks = 16; /* Arbitrary. */ volatile struct mapped_time_value *console_maptime; #define DEFAULT_ENCODING "ISO-8859-1" +#define DEFAULT_FOREGROUND CONS_COLOR_WHITE +/* For the help output. */ +#define DEFAULT_FOREGROUND_NAME "white" +#define DEFAULT_BACKGROUND CONS_COLOR_BLACK +/* For the help output. */ +#define DEFAULT_BACKGROUND_NAME "black" /* A handle for a console device. */ @@ -91,6 +99,9 @@ struct cons vcons_t vcons_list; /* The encoding. */ char *encoding; + /* Default foreground and background colors. */ + int foreground; + int background; struct node *node; mach_port_t underlying; @@ -163,7 +174,8 @@ vcons_lookup (cons_t cons, int id, int create, vcons_t *r_vcons) /* XXX Error checking. */ mutex_init (&vcons->lock); - err = display_create (&vcons->display, cons->encoding ?: DEFAULT_ENCODING); + err = display_create (&vcons->display, cons->encoding ?: DEFAULT_ENCODING, + cons->foreground, cons->background); if (err) { free (vcons->name); @@ -302,7 +314,7 @@ new_node (struct node **np, vcons_t vcons, vcons_node_type type) (*np)->nn_stat.st_mode |= S_IFREG; (*np)->nn_stat.st_mode &= ~(S_IXUSR | S_IXGRP | S_IXOTH); (*np)->nn_stat.st_size = 80*50 * (sizeof (wchar_t) + 4) - + 11 * 4; /* XXX */ + + 14 * 4 + 512 * 8; /* XXX */ break; case VCONS_NODE_INPUT: (*np)->nn_stat.st_ino = (vcons->id << 2) + 3; @@ -1190,14 +1202,59 @@ netfs_S_file_notice_changes (struct protid *cred, mach_port_t notify) } +static const char *color_names[CONS_COLOR_MAX + 1] = + { + [CONS_COLOR_BLACK] = "black", + [CONS_COLOR_RED] = "red", + [CONS_COLOR_GREEN] = "green", + [CONS_COLOR_YELLOW] = "yellow", + [CONS_COLOR_BLUE] = "blue", + [CONS_COLOR_MAGENTA] = "magenta", + [CONS_COLOR_CYAN] = "cyan", + [CONS_COLOR_WHITE] = "white" + }; + static const struct argp_option options[] = { - {"encoding", 'e', "NAME", 0, "Set encoding of virtual consoles to" - " NAME (default `" DEFAULT_ENCODING "')" }, + { "foreground",'f', "COLOR", 0, "Set foreground color to" + " COLOR (default `" DEFAULT_FOREGROUND_NAME "')" }, + { "background",'b', "COLOR", 0, "Set background color to" + " COLOR (default `" DEFAULT_BACKGROUND_NAME "')" }, + { "encoding", 'e', "NAME", 0, "Set encoding of virtual consoles to" + " NAME (default `" DEFAULT_ENCODING "')" }, {0} }; static error_t +parse_color (const char *name, int *number) +{ + if (isdigit (*name)) + { + long int nr; + char *tail; + + errno = 0; + + nr = strtol (name, &tail, 0); + if (errno || &tail || nr < 0 || nr > CONS_COLOR_MAX) + return EINVAL; + *number = nr; + return 0; + } + else + { + int i; + for (i = 0; i <= CONS_COLOR_MAX; i++) + if (!strcmp (color_names[i], name)) + { + *number = i; + return 0; + } + return EINVAL; + } +} + +static error_t parse_opt (int opt, char *arg, struct argp_state *state) { cons_t cons = state->input; @@ -1218,6 +1275,11 @@ parse_opt (int opt, char *arg, struct argp_state *state) mutex_unlock (&cons->lock); break; + case 'f': + return parse_color (arg, &cons->foreground); + case 'b': + return parse_color (arg, &cons->background); + case 'e': /* XXX Check validity of encoding. Can we perform all necessary conversions? */ @@ -1252,6 +1314,24 @@ netfs_append_args (char **argz, size_t *argz_len) else err = errno; } + if (cons->foreground != DEFAULT_FOREGROUND) + { + char *buf; + asprintf (&buf, "--foreground=%s", color_names[cons->foreground]); + if (buf) + err = argz_add (argz, argz_len, buf); + else + err = errno; + } + if (cons->background != DEFAULT_BACKGROUND) + { + char *buf; + asprintf (&buf, "--background=%s", color_names[cons->background]); + if (buf) + err = argz_add (argz, argz_len, buf); + else + err = errno; + } return err; } @@ -1272,6 +1352,8 @@ main (int argc, char **argv) error (1, ENOMEM, "Cannot create console structure"); mutex_init (&cons->lock); cons->encoding = NULL; + cons->foreground = DEFAULT_FOREGROUND; + cons->background = DEFAULT_BACKGROUND; cons->vcons_list = NULL; root_nn.cons = cons; diff --git a/console/console.h b/console/console.h index 36ad54a1..81940f9e 100644 --- a/console/console.h +++ b/console/console.h @@ -21,14 +21,12 @@ #include <stdint.h> -#define CONS_COLOR_BLACK 0 -#define CONS_COLOR_RED 1 -#define CONS_COLOR_GREEN 2 -#define CONS_COLOR_YELLOW 3 -#define CONS_COLOR_BLUE 4 -#define CONS_COLOR_MAGENTA 5 -#define CONS_COLOR_CYAN 6 -#define CONS_COLOR_WHITE 7 +typedef enum + { + CONS_COLOR_BLACK = 0, CONS_COLOR_RED, CONS_COLOR_GREEN, CONS_COLOR_YELLOW, + CONS_COLOR_BLUE, CONS_COLOR_MAGENTA, CONS_COLOR_CYAN, CONS_COLOR_WHITE + } cons_color_t; +#define CONS_COLOR_MAX (CONS_COLOR_WHITE) typedef struct { @@ -50,6 +48,25 @@ typedef struct conchar_attr_t attr; } conchar_t; +typedef union +{ + struct + { + /* Only the first 31 bits are available (see WHAT.not_matrix). */ + uint32_t start; + uint32_t end; + } matrix; + struct + { + uint32_t cursor_pos : 1; + uint32_t cursor_status : 1; + uint32_t screen_cur_line : 1; + uint32_t screen_scr_lines : 1; + uint32_t _unused : 27; + uint32_t not_matrix : 1; + } what; +} cons_change_t; + struct cons_display { #define CONS_MAGIC 0x48555244 /* Hex for "HURD". */ @@ -68,7 +85,7 @@ struct cons_display uint32_t cur_line; /* Beginning of visible area. This is only ever increased by the server, so clients can optimize scrolling. */ - uint32_t scr_lines;/* Number of lines in scrollback buffer + uint32_t scr_lines; /* Number of lines in scrollback buffer preceeding CUR_LINE. */ uint32_t height; /* Number of lines in visible area following (and including) CUR_LINE. */ @@ -87,6 +104,17 @@ struct cons_display uint32_t status; /* Visibility status of cursor. */ } cursor; + struct + { + uint32_t buffer; /* Index (in uint32_t) of the beginning of the + changes buffer in this structure. */ + uint32_t length; /* Length of buffer. */ + uint32_t written; /* Number of records written by server. */ + +#define _CONS_CHANGES_LENGTH 512 + cons_change_t _buffer[_CONS_CHANGES_LENGTH]; + } changes; + /* Don't use this, use ((wchar_t *) cons_display + cons_display.screen.matrix) instead. This will make your client upward compatible with future versions of this interface. */ diff --git a/console/display.c b/console/display.c index 5528ff98..a70902c0 100644 --- a/console/display.c +++ b/console/display.c @@ -37,8 +37,6 @@ #include <hurd.h> #include <hurd/pager.h> -#include "ourfs_notify_U.h" - #ifndef __STDC_ISO_10646__ #error It is required that wchar_t is UCS-4. #endif @@ -141,6 +139,17 @@ struct modreq { mach_port_t port; struct modreq *next; + /* If the port should have been notified, but it was blocking, we + set this. */ + int pending; +}; + +/* For each display, a notification port is created to which the + kernel sends message accepted notifications. */ +struct notify +{ + struct port_info pi; + struct display *display; }; struct display @@ -166,6 +175,10 @@ struct display /* A list of ports to send file change notifications to. */ struct modreq *filemod_reqs; + /* Those ports which currently have a pending notification. */ + struct modreq *filemod_reqs_pending; + /* The notify port. */ + struct notify *notify_port; }; @@ -201,13 +214,17 @@ error_t pager_read_page (struct user_pager_info *upi, vm_offset_t page, vm_address_t *buf, int *writelock) { - assert (upi->memobj_pages[page / vm_page_size] == (vm_address_t) NULL); + /* XXX clients should get a read only object. */ + *writelock = 0; - /* This is a read-only medium */ - *writelock = 1; - - *buf = (vm_address_t) mmap (0, vm_page_size, PROT_READ|PROT_WRITE, - MAP_ANON, 0, 0); + if (upi->memobj_pages[page / vm_page_size] != (vm_address_t) NULL) + { + *buf = upi->memobj_pages[page / vm_page_size]; + upi->memobj_pages[page / vm_page_size] = (vm_address_t) NULL; + } + else + *buf = (vm_address_t) mmap (0, vm_page_size, PROT_READ|PROT_WRITE, + MAP_ANON, 0, 0); return 0; } @@ -224,6 +241,7 @@ error_t pager_unlock_page (struct user_pager_info *pager, vm_offset_t address) { + assert (!"unlocking requested on unlocked page"); return 0; } @@ -258,6 +276,88 @@ service_paging_requests (any_t arg) } +/* The bucket and class for notification messages. */ +static struct port_bucket *notify_bucket; +static struct port_class *notify_class; + +#define msgh_request_port msgh_remote_port +#define msgh_reply_port msgh_local_port + +/* SimpleRoutine file_changed */ +kern_return_t +nowait_file_changed (mach_port_t notify_port, file_changed_type_t change, + off_t start, off_t end, mach_port_t notify) +{ + typedef struct + { + mach_msg_header_t Head; + mach_msg_type_t changeType; + file_changed_type_t change; + mach_msg_type_t startType; + off_t start; + mach_msg_type_t endType; + off_t end; + } Request; + union + { + Request In; + } Mess; + register Request *InP = &Mess.In; + + static const mach_msg_type_t changeType = { + /* msgt_name = */ 2, + /* msgt_size = */ 32, + /* msgt_number = */ 1, + /* msgt_inline = */ TRUE, + /* msgt_longform = */ FALSE, + /* msgt_deallocate = */ FALSE, + /* msgt_unused = */ 0 + }; + + static const mach_msg_type_t startType = { + /* msgt_name = */ 2, + /* msgt_size = */ 32, + /* msgt_number = */ 1, + /* msgt_inline = */ TRUE, + /* msgt_longform = */ FALSE, + /* msgt_deallocate = */ FALSE, + /* msgt_unused = */ 0 + }; + + static const mach_msg_type_t endType = { + /* msgt_name = */ 2, + /* msgt_size = */ 32, + /* msgt_number = */ 1, + /* msgt_inline = */ TRUE, + /* msgt_longform = */ FALSE, + /* msgt_deallocate = */ FALSE, + /* msgt_unused = */ 0 + }; + + InP->changeType = changeType; + InP->change = change; + InP->startType = startType; + InP->start = start; + InP->endType = endType; + InP->end = end; + + InP->Head.msgh_bits = MACH_MSGH_BITS(19, 0); + /* msgh_size passed as argument. */ + InP->Head.msgh_request_port = notify_port; + InP->Head.msgh_reply_port = MACH_PORT_NULL; + InP->Head.msgh_seqno = 0; + InP->Head.msgh_id = 20501; + + if (notify == MACH_PORT_NULL) + return mach_msg (&InP->Head, MACH_SEND_MSG | MACH_MSG_OPTION_NONE, + 48, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, + MACH_PORT_NULL); + else + return mach_msg (&InP->Head, MACH_SEND_MSG | MACH_SEND_NOTIFY, + 48, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, + notify); +} + /* Free the list of modification requests MR */ static void free_modreqs (struct modreq *mr) @@ -271,6 +371,106 @@ free_modreqs (struct modreq *mr) } } +void do_mach_notify_port_deleted (void) { assert (0); } +void do_mach_notify_port_destroyed (void) { assert (0); } +void do_mach_notify_no_senders (void) { assert (0); } +void do_mach_notify_dead_name (void) { assert (0); } + +kern_return_t +do_mach_notify_send_once (mach_port_t notify) +{ + /* XXX Not sure when this is called. */ + assert (0); +} + +kern_return_t +do_mach_notify_msg_accepted (mach_port_t notify, mach_port_t send) +{ + struct notify *notify_port = ports_lookup_port (notify_bucket, + notify, notify_class); + struct display *display; + struct modreq **preq; + struct modreq *req; + + if (!notify_port) + return EOPNOTSUPP; + + /* If we deallocated the send right in display_destroy before the + notification was created. We have nothing to do in this + case. */ + if (!send) + { + assert(0); + ports_port_deref (notify_port); + return 0; + } + + display = notify_port->display; + mutex_lock (&display->lock); + /* Find request in pending queue. */ + preq = &display->filemod_reqs_pending; + while (*preq && (*preq)->port != send) + preq = &(*preq)->next; + /* If we don't find the request, it was destroyed in + display_destroy. In this case, there is nothing left to do + here. */ + if (! *preq) + { + assert(0); + mutex_unlock (&display->lock); + ports_port_deref (notify_port); + return 0; + } + req = *preq; + + if (req->pending) + { + error_t err; + /* A request was desired while we were blocking. Send it now + and stay in pending queue. */ + req->pending = 0; + err = nowait_file_changed (req->port, FILE_CHANGED_WRITE, -1, -1, + notify); + if (err && err != MACH_SEND_WILL_NOTIFY) + { + *preq = req->next; + mutex_unlock (&display->lock); + mach_port_deallocate (mach_task_self (), req->port); + free (req); + ports_port_deref (notify_port); + return err; + } + if (err == MACH_SEND_WILL_NOTIFY) + { + mutex_unlock (&display->lock); + return 0; + } + /* The message was succesfully queued, fall through. */ + } + /* Remove request from pending queue. */ + *preq = req->next; + /* Insert request into active queue. */ + req->next = display->filemod_reqs; + display->filemod_reqs = req; + mutex_unlock (&display->lock); + ports_port_deref (notify_port); + return 0; +} + +/* A top-level function for the notification thread that just services + notification messages. */ +static void +service_notifications (any_t arg) +{ + struct port_bucket *notify_bucket = arg; + extern int notify_server (mach_msg_header_t *inp, mach_msg_header_t *outp); + + for (;;) + ports_manage_port_operations_one_thread (notify_bucket, + notify_server, + 1000 * 60 * 10); +} + error_t display_notice_changes (display_t display, mach_port_t notify) { @@ -278,7 +478,7 @@ display_notice_changes (display_t display, mach_port_t notify) struct modreq *req; mutex_lock (&display->lock); - err = nowait_file_changed (notify, FILE_CHANGED_NULL, 0, 0); + err = nowait_file_changed (notify, FILE_CHANGED_NULL, 0, 0, MACH_PORT_NULL); if (err) { mutex_unlock (&display->lock); @@ -291,6 +491,7 @@ display_notice_changes (display_t display, mach_port_t notify) return errno; } req->port = notify; + req->pending = 0; req->next = display->filemod_reqs; display->filemod_reqs = req; mutex_unlock (&display->lock); @@ -299,24 +500,41 @@ display_notice_changes (display_t display, mach_port_t notify) /* Requires DISPLAY to be locked. */ static void -display_notice_filechange (display_t display, enum file_changed_type type, - off_t start, off_t end) +display_notice_filechange (display_t display) { error_t err; - struct modreq **preq; + struct modreq *req = display->filemod_reqs_pending; + struct modreq **preq = &display->filemod_reqs; + mach_port_t notify_port = ports_get_right (display->notify_port); + + while (req) + { + req->pending = 1; + req = req->next; + } - preq = &display->filemod_reqs; while (*preq) { - struct modreq *req = *preq; - err = nowait_file_changed (req->port, type, start, end); + req = *preq; + + err = nowait_file_changed (req->port, FILE_CHANGED_WRITE, -1, -1, + notify_port); if (err) { /* Remove notify port. */ - *preq = req->next; - mach_port_deallocate (mach_task_self (), req->port); - free (req); - } + *preq = req->next; + + if (err == MACH_SEND_WILL_NOTIFY) + { + req->next = display->filemod_reqs_pending; + display->filemod_reqs_pending = req; + } + else + { + mach_port_deallocate (mach_task_self (), req->port); + free (req); + } + } else preq = &req->next; } @@ -326,71 +544,71 @@ static void display_flush_filechange (display_t display, unsigned int type) { struct cons_display *user = display->user; + cons_change_t *next = &user->changes._buffer[(user->changes.written + 1) + % _CONS_CHANGES_LENGTH]; + int notify = 0; + int bump_written = 0; if (type & DISPLAY_CHANGE_MATRIX && display->changes.which & DISPLAY_CHANGE_MATRIX) { - display_notice_filechange (display, FILE_CHANGED_WRITE, - sizeof (struct cons_display) - + display->changes.start * sizeof (conchar_t), - sizeof (struct cons_display) - + (display->changes.end + 1) - * sizeof (conchar_t) - 1); - type &= ~DISPLAY_CHANGE_MATRIX; + notify = 1; + next->matrix.start = display->changes.start; + next->matrix.end = display->changes.end; + user->changes.written++; + next = &user->changes._buffer[(user->changes.written + 1) + % _CONS_CHANGES_LENGTH]; + display->changes.which &= ~DISPLAY_CHANGE_MATRIX; } + memset (next, 0, sizeof (cons_change_t)); + next->what.not_matrix = 1; + if (type & DISPLAY_CHANGE_CURSOR_POS - || type & DISPLAY_CHANGE_CURSOR_STATUS) + && display->changes.which & DISPLAY_CHANGE_CURSOR_POS + && (display->changes.cursor.col != user->cursor.col + || display->changes.cursor.row != user->cursor.row)) { - off_t start; - off_t len = 0; + notify = 1; + next->what.cursor_pos = 1; + bump_written = 1; + display->changes.which &= ~DISPLAY_CHANGE_CURSOR_POS; + } - if (type & DISPLAY_CHANGE_CURSOR_POS - && display->changes.which & DISPLAY_CHANGE_CURSOR_POS - && (display->changes.cursor.col != user->cursor.col - || display->changes.cursor.row != user->cursor.row)) - { - start = offsetof (struct cons_display, cursor.col); - len += 2; - } - if (type & DISPLAY_CHANGE_CURSOR_STATUS - && display->changes.which & DISPLAY_CHANGE_CURSOR_STATUS - && display->changes.cursor.status != user->cursor.status) - { - if (!len) - start = offsetof (struct cons_display, cursor.status); - len += 1; - } - if (len) - display_notice_filechange (display, FILE_CHANGED_WRITE, start, - start + len * sizeof (uint32_t) - 1); + if (type & DISPLAY_CHANGE_CURSOR_STATUS + && display->changes.which & DISPLAY_CHANGE_CURSOR_STATUS + && display->changes.cursor.status != user->cursor.status) + { + notify = 1; + next->what.cursor_status = 1; + bump_written = 1; + display->changes.which &= ~DISPLAY_CHANGE_CURSOR_STATUS; } if (type & DISPLAY_CHANGE_SCREEN_CUR_LINE - || type & DISPLAY_CHANGE_SCREEN_SCR_LINES) + && display->changes.which & DISPLAY_CHANGE_SCREEN_CUR_LINE + && display->changes.screen.cur_line != user->screen.cur_line) { - off_t start; - off_t len = 0; + notify = 1; + next->what.screen_cur_line = 1; + bump_written = 1; + display->changes.which &= ~DISPLAY_CHANGE_SCREEN_CUR_LINE; + } - if (type & DISPLAY_CHANGE_SCREEN_CUR_LINE - && display->changes.which & DISPLAY_CHANGE_SCREEN_CUR_LINE - && display->changes.screen.cur_line != user->screen.cur_line) - { - start = offsetof (struct cons_display, screen.cur_line); - len += 2; - } - if (type & DISPLAY_CHANGE_SCREEN_SCR_LINES - && display->changes.which & DISPLAY_CHANGE_SCREEN_SCR_LINES - && display->changes.screen.scr_lines != user->screen.scr_lines) - { - if (!len) - start = offsetof (struct cons_display, screen.scr_lines); - len += 1; - } - if (len) - display_notice_filechange (display, FILE_CHANGED_WRITE, start, - start + len * sizeof (uint32_t) - 1); + if (type & DISPLAY_CHANGE_SCREEN_SCR_LINES + && display->changes.which & DISPLAY_CHANGE_SCREEN_SCR_LINES + && display->changes.screen.scr_lines != user->screen.scr_lines) + { + notify = 1; + next->what.screen_scr_lines = 1; + bump_written = 1; + display->changes.which &= ~DISPLAY_CHANGE_SCREEN_SCR_LINES; } + + if (bump_written) + user->changes.written++; + if (notify) + display_notice_filechange (display); } /* Record a change in the matrix ringbuffer. */ @@ -536,6 +754,9 @@ user_create (display_t display, uint32_t width, uint32_t height, user->magic = CONS_MAGIC; user->version = CONS_VERSION_MAJ << 16 | CONS_VERSION_AGE; + user->changes.buffer = offsetof (struct cons_display, changes._buffer) + / sizeof (uint32_t); + user->changes.length = _CONS_CHANGES_LENGTH; user->screen.width = width; user->screen.height = height; user->screen.lines = lines; @@ -619,19 +840,6 @@ screen_shift_left (display_t display, size_t col1, size_t row1, size_t col2, } display_record_filechange (display, start, end); -#if 0 - display_flush_filechange (display, DISPLAY_CHANGE_MATRIX); - display_notice_filechange (display, FILE_CHANGED_TRUNCATE, - sizeof (struct cons_display) - + start * sizeof (conchar_t), - sizeof (struct cons_display) - + (start + shift) * sizeof (conchar_t) - 1); - display_notice_filechange (display, FILE_CHANGED_EXTEND, - sizeof (struct cons_display) - + (end - shift + 1) * sizeof (conchar_t), - sizeof (struct cons_display) - + (end + 1) * sizeof (conchar_t) - 1); -#endif } else screen_fill (display, col1, row1, col2, row2, chr, attr); @@ -669,19 +877,6 @@ screen_shift_right (display_t display, size_t col1, size_t row1, size_t col2, } display_record_filechange (display, start, end); -#if 0 - display_flush_filechange (display, DISPLAY_CHANGE_MATRIX); - display_notice_filechange (display, FILE_CHANGED_EXTEND, - sizeof (struct cons_display) - + start * sizeof (conchar_t), - sizeof (struct cons_display) - + (start + shift) * sizeof (conchar_t) - 1); - display_notice_filechange (display, FILE_CHANGED_TRUNCATE, - sizeof (struct cons_display) - + (end - shift + 1) * sizeof (conchar_t), - sizeof (struct cons_display) - + (end + 1) * sizeof (conchar_t) - 1); -#endif } else screen_fill (display, col1, row1, col2, row2, chr, attr); @@ -1395,6 +1590,9 @@ display_output_some (display_t display, char **buffer, size_t *length) } +/* Forward declaration. */ +void display_destroy_complete (void *pi); + void display_init (void) { @@ -1405,14 +1603,26 @@ display_init (void) /* Make a thread to service paging requests. */ cthread_detach (cthread_fork ((cthread_fn_t) service_paging_requests, - (any_t)pager_bucket)); + (any_t) pager_bucket)); + + /* Create the notify bucket, and start to serve notifications. */ + notify_bucket = ports_create_bucket (); + if (! notify_bucket) + error (5, errno, "Cannot create notify bucket"); + notify_class = ports_create_class (display_destroy_complete, NULL); + if (! notify_class) + error (5, errno, "Cannot create notify class"); + + cthread_detach (cthread_fork ((cthread_fn_t) service_notifications, + (any_t) notify_bucket)); } /* Create a new virtual console display, with the system encoding being ENCODING. */ error_t -display_create (display_t *r_display, const char *encoding) +display_create (display_t *r_display, const char *encoding, + int foreground, int background) { error_t err = 0; display_t display; @@ -1425,15 +1635,25 @@ display_create (display_t *r_display, const char *encoding) if (!display) return ENOMEM; + err = ports_create_port (notify_class, notify_bucket, sizeof (struct notify), + &display->notify_port); + if (err) + { + free (display); + return err; + } + display->notify_port->display = display; + mutex_init (&display->lock); - display->attr.bgcol_def = CONS_COLOR_BLACK; - display->attr.fgcol_def = CONS_COLOR_WHITE; + display->attr.bgcol_def = background; + display->attr.fgcol_def = foreground; display->attr.current.bgcol = display->attr.bgcol_def; display->attr.current.fgcol = display->attr.fgcol_def; err = user_create (display, width, height, lines, L' ', display->attr.current); if (err) { + ports_destroy_right (display->notify_port); free (display); return err; } @@ -1442,6 +1662,7 @@ display_create (display_t *r_display, const char *encoding) if (err) { user_destroy (display); + ports_destroy_right (display->notify_port); free (display); } *r_display = display; @@ -1453,10 +1674,27 @@ display_create (display_t *r_display, const char *encoding) void display_destroy (display_t display) { + if (display->filemod_reqs_pending) + free_modreqs (display->filemod_reqs_pending); if (display->filemod_reqs) free_modreqs (display->filemod_reqs); + ports_destroy_right (display->notify_port); output_deinit (&display->output); user_destroy (display); + /* We can not free the display structure here, because it might + still be needed by pending modification requests when msg + accepted notifications are handled. So we have to wait until all + notifications have arrived and the notify port is completely + deallocated, which will invoke display_destroy_complete + below. */ +} + + +/* Complete destruction of the display DISPLAY. */ +void +display_destroy_complete (void *pi) +{ + struct display *display = ((struct notify *) pi)->display; free (display); } diff --git a/console/display.h b/console/display.h index 303c42e2..4f9b7586 100644 --- a/console/display.h +++ b/console/display.h @@ -29,8 +29,9 @@ typedef struct display *display_t; void display_init (void); /* Create a new virtual console display, with the system encoding - being ENCODING. */ -error_t display_create (display_t *r_display, const char *encoding); + being ENCODING and the default colors being FOREGROUND and BACKGROUND. */ +error_t display_create (display_t *r_display, const char *encoding, + int foreground, int background); /* Destroy the display DISPLAY. */ void display_destroy (display_t display); |