? action.c Index: Makefile =================================================================== RCS file: /cvsroot/src/usr.sbin/wsmoused/Makefile,v retrieving revision 1.4 diff -u -r1.4 Makefile --- Makefile 2003/03/07 01:31:30 1.4 +++ Makefile 2003/08/06 17:30:18 @@ -2,9 +2,16 @@ # PROG= wsmoused -SRCS= wsmoused.c config.c config_yacc.y config_lex.l events.c selection.c +SRCS= wsmoused.c config.c config_yacc.y config_lex.l MAN= wsmoused.conf.5 wsmoused.8 + +WSMOUSED_SELECTION_MODE?= yes + +.if !empty(WSMOUSED_SELECTION_MODE:M[Yy][Ee][Ss]) +CPPFLAGS+= -DWSMOUSED_SELECTION_MODE +SRCS+= selection.c +.endif CPPFLAGS+= -I${.CURDIR} -I. LDADD+= -lutil Index: config.c =================================================================== RCS file: /cvsroot/src/usr.sbin/wsmoused/config.c,v retrieving revision 1.2 diff -u -r1.2 config.c --- config.c 2003/03/04 19:28:59 1.2 +++ config.c 2003/08/06 17:30:19 @@ -5,7 +5,7 @@ * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation - * by Julio Merino. + * by Julio M. Merino Vidal. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,6 +37,7 @@ #include #include + #include #include #include @@ -46,14 +47,22 @@ #include "pathnames.h" #include "wsmoused.h" +/* --------------------------------------------------------------------- */ + +/* + * Global variables. + */ + static struct block *Global = NULL; +/* --------------------------------------------------------------------- */ + /* Prototypes for config_yacc.y (only used here) */ struct block *config_parse(FILE *); -/* - * Creates a new, empty property. Returns a pointer to it. - */ +/* --------------------------------------------------------------------- */ + +/* Creates a new, empty property. Returns a pointer to it. */ struct prop * prop_new(void) { @@ -65,22 +74,23 @@ return p; } -/* - * Frees a property created with prop_new. All data stored in the property - * is also destroyed. - */ +/* --------------------------------------------------------------------- */ + +/* Frees a property created with prop_new. All data stored in the property + * is also destroyed. */ void prop_free(struct prop *p) { + free(p->p_name); free(p->p_value); free(p); } -/* - * Creates a new, empty block, with the specified type (see BLOCK_* macros). - * Returns a pointer to it. - */ +/* --------------------------------------------------------------------- */ + +/* Creates a new, empty block, with the specified type (see BLOCK_* macros). + * Returns a pointer to it. */ struct block * block_new(int type) { @@ -93,10 +103,10 @@ return b; } -/* - * Frees a block created with block_new. All data contained inside the block - * is also destroyed. - */ +/* --------------------------------------------------------------------- */ + +/* Frees a block created with block_new. All data contained inside the block + * is also destroyed. */ void block_free(struct block *b) { @@ -113,12 +123,13 @@ free(b); } -/* - * Add a property to a block. - */ +/* --------------------------------------------------------------------- */ + +/* Adds a property to a block. */ void block_add_prop(struct block *b, struct prop *p) { + if (p == NULL) return; @@ -130,12 +141,13 @@ } } -/* - * Add a child (block) to a block. - */ +/* --------------------------------------------------------------------- */ + +/* Adds a child (block) to a block. */ void block_add_child(struct block *b, struct block *c) { + if (c == NULL) return; @@ -148,12 +160,12 @@ } } -/* - * Get the value of a property in the specified block (or in its parents). - * If not found, return the value given in def. - */ +/* --------------------------------------------------------------------- */ + +/* Get the value of a property in the specified block (or in its parents). + * If not found, return the value given in def. */ char * -block_get_propval(struct block *b, char *pname, char *def) +block_get_propval(struct block *b, const char *pname, char *def) { int pc; @@ -170,17 +182,17 @@ return def; } -/* - * Get the value of a property in the specified block converting it to an +/* --------------------------------------------------------------------- */ + +/* Get the value of a property in the specified block converting it to an * integer, if possible. If the property cannot be found in the given * block, all its parents are tried. If after all not found (or conversion - * not possible), return the value given in def. - */ + * not possible), return the value given in def. */ int -block_get_propval_int(struct block *b, char *pname, int def) +block_get_propval_int(struct block *b, const char *pname, int def) { - int pc, ret; char *ptr; + int pc, ret; if (b == NULL) return def; @@ -203,16 +215,21 @@ return def; } -/* - * Get a mode block (childs of the global scope), which matches the specified - * name. - */ +/* --------------------------------------------------------------------- */ + +/* Gets a mode block (childs of the global scope), which matches the + * specified name. */ struct block * -config_get_mode(char *modename) +config_get_mode(const char *modename) { - struct block *b = Global; int bc; + struct block *b; + b = Global; + + if (strcmp(modename, "Global") == 0) + return Global; + if (b != NULL) for (bc = 0; bc < b->b_child_count; bc++) if (strcmp(b->b_child[bc]->b_name, modename) == 0) @@ -221,11 +238,11 @@ return NULL; } -/* - * Read the configuration file. - */ +/* --------------------------------------------------------------------- */ + +/* Reads the configuration file. */ void -config_read(char *conffile, int opt) +config_read(const char *conffile, int opt) { FILE *f; @@ -241,12 +258,13 @@ } } -/* - * Destroy all the configuration data. - */ +/* --------------------------------------------------------------------- */ + +/* Destroys all the configuration data. */ void config_free(void) { + if (Global != NULL) block_free(Global); } Index: config_lex.l =================================================================== RCS file: /cvsroot/src/usr.sbin/wsmoused/config_lex.l,v retrieving revision 1.2 diff -u -r1.2 config_lex.l --- config_lex.l 2003/03/04 22:31:15 1.2 +++ config_lex.l 2003/08/06 17:30:36 @@ -5,7 +5,7 @@ * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation - * by Julio Merino. + * by Julio M. Merino Vidal. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -55,7 +55,8 @@ %option noyywrap STRING [\$A-Za-z\.\/_\-0-9]* -MODE_PROPS device|fifo|lefthanded|nodaemon|pidfile|slowdown_x|slowdown_y|ttystat|xconsole +SP_STRING [\$A-Za-z\.\/_\-0-9 ]* +MODE_PROPS device|fifo|lefthanded|modes|nodaemon|pidfile|slowdown_x|slowdown_y|ttystat|xconsole EVENT_PROPS button|do %% @@ -72,6 +73,8 @@ mode { return TK_MODE; } {EVENT_PROPS} { yylval.string = strdup(yytext); return TK_EVENTPROP; } {MODE_PROPS} { yylval.string = strdup(yytext); return TK_MODEPROP; } +\"{SP_STRING}\" { yylval.string = strdup(yytext + 1); + yylval.string[strlen(yytext) - 2] = '\0'; return TK_STRING; } {STRING} { yylval.string = strdup(yytext); return TK_STRING; } -. { yyerror("illegal token `%s'", yytext); } +. { yyerror("illegal token `%s'", yytext); } Index: config_yacc.y =================================================================== RCS file: /cvsroot/src/usr.sbin/wsmoused/config_yacc.y,v retrieving revision 1.1 diff -u -r1.1 config_yacc.y --- config_yacc.y 2003/03/04 14:33:55 1.1 +++ config_yacc.y 2003/08/06 17:30:36 @@ -5,7 +5,7 @@ * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation - * by Julio Merino. + * by Julio M. Merino Vidal. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions Index: pathnames.h =================================================================== RCS file: /cvsroot/src/usr.sbin/wsmoused/pathnames.h,v retrieving revision 1.4 diff -u -r1.4 pathnames.h --- pathnames.h 2003/03/04 22:31:15 1.4 +++ pathnames.h 2003/08/06 17:30:36 @@ -1,11 +1,11 @@ /* $NetBSD: pathnames.h,v 1.4 2003/03/04 22:31:15 jmmv Exp $ */ /* - * Copyright (c) 2002 The NetBSD Foundation, Inc. + * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation - * by Julio Merino. + * by Julio M. Merino Vidal. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions Index: selection.c =================================================================== RCS file: /cvsroot/src/usr.sbin/wsmoused/selection.c,v retrieving revision 1.3 diff -u -r1.3 selection.c --- selection.c 2002/12/25 19:04:27 1.3 +++ selection.c 2003/08/06 17:30:36 @@ -1,11 +1,11 @@ /* $NetBSD: selection.c,v 1.3 2002/12/25 19:04:27 jmmv Exp $ */ /* - * Copyright (c) 2002 The NetBSD Foundation, Inc. + * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation - * by Julio Merino. + * by Julio M. Merino Vidal. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -42,9 +42,8 @@ #include #include -#include #include -#include +#include #include #include #include @@ -52,44 +51,394 @@ #include "pathnames.h" #include "wsmoused.h" + +/* ---------------------------------------------------------------------- */ + +/* + * Public interface exported by the `selection' mode. + */ + +int selection_startup(struct mouse *m); +int selection_cleanup(void); +void selection_wsmouse_event(struct wscons_event); +void selection_wscons_event(struct wscons_event); +void selection_poll_timeout(void); + +struct mode_bootstrap Selection_Mode = { + "selection", + selection_startup, + selection_cleanup, + selection_wsmouse_event, + selection_wscons_event, + selection_poll_timeout +}; + +/* ---------------------------------------------------------------------- */ + +/* + * Structures used in this module only. + */ + +/* The `selarea' structure is used to describe a selection in the screen. + It also holds a copy of the selected text. */ +struct selarea { + size_t sa_x1; /* Start column */ + size_t sa_y1; /* Start row */ + size_t sa_x2; /* End column */ + size_t sa_y2; /* End row */ + size_t sa_startoff; /* Absolute offset of start position */ + size_t sa_endoff; /* Absolute offset of end position */ + size_t sa_buflen; /* Length of selected text */ + char *sa_buf; /* A copy of the selected text */ +}; + +/* The `selmouse' structure extends the `mouse' structure adding all fields + required for this module to work. */ +struct selmouse { + struct mouse *sm_mouse; /* Pointer to parent structure */ + + int sm_ttyfd; /* Active TTY file descriptor */ + + size_t sm_x; /* Mouse pointer column */ + size_t sm_y; /* Mouse pointer row */ + size_t sm_max_x; /* Maximun column allowed */ + size_t sm_max_y; /* Maximun row allowed */ + + size_t sm_slowdown_x; /* X axis slowdown */ + size_t sm_slowdown_y; /* Y axis slowdown */ + size_t sm_count_x; /* Number of X movements skipped */ + size_t sm_count_y; /* Number of Y movements skipped */ + + int sm_visible; /* Whether pointer is visible or not */ + int sm_selecting; /* Whether we are selecting or not */ + + int sm_but_select; /* Button number to select an area */ + int sm_but_paste; /* Button number to paste buffer */ +}; + +/* ---------------------------------------------------------------------- */ + +/* + * Global variables. + */ + +static struct selmouse Selmouse; +static struct selarea Selarea; +static int Initialized = 0; + +/* ---------------------------------------------------------------------- */ + +/* + * Prototypes for functions private to this module. + */ + +static void cursor_hide(void); +static void cursor_show(void); +static void open_tty(int); +static void char_invert(size_t, size_t); +static void *alloc_sel(size_t); +static char *fill_buf(char *, size_t, size_t, size_t); +static size_t row_length(size_t); +static void selarea_copy_text(void); +static void selarea_start(void); +static void selarea_end(void); +static void selarea_calculate(void); +static void selarea_hide(void); +static void selarea_show(void); +static void selarea_paste(void); + +/* ---------------------------------------------------------------------- */ + +/* Mode initialization. Reads configuration, checks if the kernel has + * support for mouse pointer and opens required files. */ +int +selection_startup(struct mouse *m) +{ + int i; + struct winsize ws; + struct wsdisplay_char ch; + struct block *conf; + + if (Initialized) { + warnx("selection mode already initialized"); + return 1; + } + + (void)memset(&Selmouse, 0, sizeof(struct selmouse)); + Selmouse.sm_mouse = m; + + conf = config_get_mode("selection"); + Selmouse.sm_slowdown_x = block_get_propval_int(conf, "slowdown_x", 0); + Selmouse.sm_slowdown_y = block_get_propval_int(conf, "slowdown_y", 3); + if (block_get_propval_int(conf, "lefthanded", 0)) { + Selmouse.sm_but_select = 2; + Selmouse.sm_but_paste = 0; + } else { + Selmouse.sm_but_select = 0; + Selmouse.sm_but_paste = 2; + } + + /* Get terminal size */ + if (ioctl(0, TIOCGWINSZ, &ws) < 0) { + warn("cannot get terminal size"); + return 0; + } + + /* Open current tty */ + (void)ioctl(Selmouse.sm_mouse->m_statfd, WSDISPLAYIO_GETACTIVESCREEN, + &i); + Selmouse.sm_ttyfd = -1; + open_tty(i); + + /* Check if the kernel has character functions */ + ch.row = ch.col = 0; + if (ioctl(Selmouse.sm_ttyfd, WSDISPLAYIO_GETWSCHAR, &ch) < 0) { + (void)close(Selmouse.sm_ttyfd); + warn("ioctl(WSDISPLAYIO_GETWSCHAR) failed"); + return 0; + } + + Selmouse.sm_max_y = ws.ws_row - 1; + Selmouse.sm_max_x = ws.ws_col - 1; + Selmouse.sm_y = Selmouse.sm_max_y / 2; + Selmouse.sm_x = Selmouse.sm_max_x / 2; + Selmouse.sm_count_y = 0; + Selmouse.sm_count_x = 0; + Selmouse.sm_visible = 0; + Selmouse.sm_selecting = 0; + Initialized = 1; + + return 1; +} + +/* ---------------------------------------------------------------------- */ + +/* Mode cleanup. */ +int +selection_cleanup(void) +{ + + cursor_hide(); + if (Selmouse.sm_ttyfd >= 0) + (void)close(Selmouse.sm_ttyfd); + return 1; +} + +/* ---------------------------------------------------------------------- */ + +/* Parse wsmouse events. Both motion and button events are handled. The + * former move the mouse across the screen and the later create a new + * selection or paste the buffer. */ +void +selection_wsmouse_event(struct wscons_event evt) +{ + + if (IS_MOTION_EVENT(evt.type)) { + if (Selmouse.sm_selecting) + selarea_hide(); + cursor_hide(); + + switch (evt.type) { + case WSCONS_EVENT_MOUSE_DELTA_X: + if (Selmouse.sm_count_x >= Selmouse.sm_slowdown_x) { + Selmouse.sm_count_x = 0; + if (evt.value > 0) + Selmouse.sm_x++; + else if (Selmouse.sm_x != 0) + Selmouse.sm_x--; + if (Selmouse.sm_x > Selmouse.sm_max_x) + Selmouse.sm_x = Selmouse.sm_max_x; + } else + Selmouse.sm_count_x++; + break; + + case WSCONS_EVENT_MOUSE_DELTA_Y: + if (Selmouse.sm_count_y >= Selmouse.sm_slowdown_y) { + Selmouse.sm_count_y = 0; + if (evt.value < 0) + Selmouse.sm_y++; + else if (Selmouse.sm_y != 0) + Selmouse.sm_y--; + if (Selmouse.sm_y > Selmouse.sm_max_y) + Selmouse.sm_y = Selmouse.sm_max_y; + } else + Selmouse.sm_count_y++; + break; + + case WSCONS_EVENT_MOUSE_DELTA_Z: + break; + + default: + warnx("unknown event"); + } + + if (Selmouse.sm_selecting) + selarea_show(); + cursor_show(); + + } else if (IS_BUTTON_EVENT(evt.type)) { + switch (evt.type) { + case WSCONS_EVENT_MOUSE_UP: + if (evt.value == Selmouse.sm_but_select) { + /* End selection */ + selarea_end(); + selarea_hide(); + } + break; + + case WSCONS_EVENT_MOUSE_DOWN: + if (evt.value == Selmouse.sm_but_select) { + /* Start selection */ + selarea_start(); + cursor_hide(); + selarea_show(); + } else if (evt.value == Selmouse.sm_but_paste) { + /* Paste selection */ + selarea_paste(); + break; + } + break; + + default: + warnx("unknown button event"); + } + } +} + +/* ---------------------------------------------------------------------- */ + +/* Parse wscons status events. */ +void +selection_wscons_event(struct wscons_event evt) +{ + + switch (evt.type) { + case WSCONS_EVENT_SCREEN_SWITCH: + if (Selmouse.sm_selecting) + selarea_hide(); + cursor_hide(); + + open_tty(evt.value); + + cursor_show(); + if (Selmouse.sm_selecting) + selarea_show(); + + break; + } +} + +/* ---------------------------------------------------------------------- */ + +/* Device polling has timed out, so we hide the mouse to avoid further + * console pollution. */ +void +selection_poll_timeout(void) +{ + + if (!Selmouse.sm_selecting) + cursor_hide(); +} + +/* ---------------------------------------------------------------------- */ + +/* Hides the mouse pointer, if visible. */ +static void +cursor_hide(void) +{ -/* This struct holds information about a sel. For now there is - * only one global instace, but using a structre gives us a place for - * maintaining all the variables together. Also, someone may want to - * allow multiple sels, so it is easier this way. */ -static struct selection { - size_t start_row, start_col; - size_t end_row, end_col; - size_t abs_start, abs_end; - size_t text_size; - char *text; -} sel; + if (Selmouse.sm_visible) { + char_invert(Selmouse.sm_y, Selmouse.sm_x); + Selmouse.sm_visible = 0; + } +} + +/* ---------------------------------------------------------------------- */ + +/* Shows the mouse pointer, if not visible. */ +static void +cursor_show(void) +{ + + if (!Selmouse.sm_visible) { + char_invert(Selmouse.sm_y, Selmouse.sm_x); + Selmouse.sm_visible = 1; + } +} + +/* ---------------------------------------------------------------------- */ +/* Opens the specified TTY device, used when switching consoles. */ +static void +open_tty(int ttyno) +{ + char buf[20]; + + if (Selmouse.sm_ttyfd >= 0) + (void)close(Selmouse.sm_ttyfd); + + if (!Selmouse.sm_mouse->m_disabled) { + (void)snprintf(buf, sizeof(buf), _PATH_TTYPREFIX "%d", ttyno); + Selmouse.sm_ttyfd = open(buf, O_RDONLY | O_NONBLOCK); + if (Selmouse.sm_ttyfd < 0) + warnx("cannot open %s", buf); + } +} + +/* ---------------------------------------------------------------------- */ +/* Flips the background and foreground colors of the specified screen + * position. */ +static void +char_invert(size_t row, size_t col) +{ + int t; + struct wsdisplay_char ch; + + ch.row = row; + ch.col = col; + + if (ioctl(Selmouse.sm_ttyfd, WSDISPLAYIO_GETWSCHAR, &ch) == -1) { + warn("ioctl(WSDISPLAYIO_GETWSCHAR) failed"); + return; + } + + t = ch.foreground; + ch.foreground = ch.background; + ch.background = t; + + if (ioctl(Selmouse.sm_ttyfd, WSDISPLAYIO_PUTWSCHAR, &ch) == -1) + warn("ioctl(WSDISPLAYIO_PUTWSCHAR) failed"); +} + +/* ---------------------------------------------------------------------- */ + +/* Allocates memory for a selection. This function is very simple but is + * used to get a consistent warning message. */ static void * alloc_sel(size_t len) { void *ptr; - if ((ptr = malloc(len)) == NULL) { - warn("Cannot allocate memory for sel %lu", + + ptr = malloc(len); + if (ptr == NULL) + warn("cannot allocate memory for selection (%lu bytes)", (unsigned long)len); - return NULL; - } return ptr; } -/* - * Copies a region of a line inside the buffer pointed by ptr. We use - * a double pointer because we modify the pointer. When the function - * finishes, ptr points to the end of the buffer. - */ +/* ---------------------------------------------------------------------- */ + +/* Copies a region of a line inside the buffer pointed by `ptr'. */ static char * -fill_buf(char *ptr, struct mouse *m, size_t row, size_t col, size_t end) +fill_buf(char *ptr, size_t row, size_t col, size_t end) { struct wsdisplay_char ch; + ch.row = row; for (ch.col = col; ch.col < end; ch.col++) { - if (ioctl(m->tty_fd, WSDISPLAYIO_GETWSCHAR, &ch) == -1) { + if (ioctl(Selmouse.sm_ttyfd, WSDISPLAYIO_GETWSCHAR, + &ch) == -1) { warn("ioctl(WSDISPLAYIO_GETWSCHAR) failed"); *ptr++ = ' '; } else { @@ -99,207 +448,198 @@ return ptr; } +/* ---------------------------------------------------------------------- */ -/* - * This function scans the specified line and checks its - * length. Characters at the end of it which match isspace() are not - * counted. - */ +/* Scans the specified line and checks its length. Characters at the end + * of it which match isspace() are discarded. */ static size_t -row_length(struct mouse *m, size_t row) +row_length(size_t row) { struct wsdisplay_char ch; - ch.col = m->max_col; + ch.col = Selmouse.sm_max_x; ch.row = row; do { - if (ioctl(m->tty_fd, WSDISPLAYIO_GETWSCHAR, &ch) == -1) + if (ioctl(Selmouse.sm_ttyfd, WSDISPLAYIO_GETWSCHAR, &ch) == -1) warn("ioctl(WSDISPLAYIO_GETWSCHAR) failed"); ch.col--; } while (isspace((unsigned char)ch.letter) && ch.col >= 0); return ch.col + 2; } -/* - * This (complex) function copies all the text englobed in the current - * sel to the sel buffer. It does space trimming at end of - * lines if it is selected. - */ +/* ---------------------------------------------------------------------- */ + +/* Copies all the text selected to the selection buffer. Whitespace at + * end of lines is trimmed. */ static void -sel_copy_text(struct mouse *m) +selarea_copy_text(void) { - char *str, *ptr; - size_t r, l; + char *ptr, *str; + size_t l, r; - if (sel.start_row == sel.end_row) { + if (Selarea.sa_y1 == Selarea.sa_y2) { /* Selection is one row */ - l = row_length(m, sel.start_row); - if (sel.start_col > l) + l = row_length(Selarea.sa_y1); + if (Selarea.sa_x1 > l) /* Selection is after last character, * therefore it is empty */ str = NULL; else { - if (sel.end_col > l) - sel.end_col = l; - ptr = str = alloc_sel(sel.end_col - sel.start_col + 1); + if (Selarea.sa_x2 > l) + Selarea.sa_x2 = l; + ptr = str = + alloc_sel(Selarea.sa_x2 - Selarea.sa_x1 + 1); if (ptr == NULL) return; - ptr = fill_buf(ptr, m, sel.start_row, sel.start_col, - sel.end_col); + ptr = fill_buf(ptr, Selarea.sa_y1, Selarea.sa_x1, + Selarea.sa_x2); *ptr = '\0'; } } else { /* Selection is multiple rows */ - ptr = str = alloc_sel(sel.abs_end - sel.abs_start + 1); + ptr = str = + alloc_sel(Selarea.sa_endoff - Selarea.sa_startoff + 1); if (ptr == NULL) return; /* Calculate and copy first line */ - l = row_length(m, sel.start_row); - if (sel.start_col < l) { - ptr = fill_buf(ptr, m, sel.start_row, sel.start_col, l); + l = row_length(Selarea.sa_y1); + if (Selarea.sa_x1 < l) { + ptr = fill_buf(ptr, Selarea.sa_y1, Selarea.sa_x1, l); *ptr++ = '\r'; } /* Copy mid lines if there are any */ - if ((sel.end_row - sel.start_row) > 1) { - for (r = sel.start_row + 1; r <= sel.end_row - 1; r++) { - ptr = fill_buf(ptr, m, r, 0, row_length(m, r)); + if ((Selarea.sa_y2 - Selarea.sa_y1) > 1) { + for (r = Selarea.sa_y1 + 1; r <= Selarea.sa_y2 - 1; + r++) { + ptr = fill_buf(ptr, r, 0, row_length(r)); *ptr++ = '\r'; } } /* Calculate and copy end line */ - l = row_length(m, sel.end_row); - if (sel.end_col < l) - l = sel.end_col; - ptr = fill_buf(ptr, m, sel.end_row, 0, l); + l = row_length(Selarea.sa_y2); + if (Selarea.sa_x2 < l) + l = Selarea.sa_x2; + ptr = fill_buf(ptr, Selarea.sa_y2, 0, l); *ptr = '\0'; } - if (sel.text != NULL) { - free(sel.text); - sel.text = NULL; + if (Selarea.sa_buf != NULL) { + free(Selarea.sa_buf); + Selarea.sa_buf = NULL; } if (str != NULL) { - sel.text = str; - sel.text_size = ptr - str; + Selarea.sa_buf = str; + Selarea.sa_buflen = ptr - str; } } -/* - * Initializes sel data. It should be called only once, at - * wsmoused startup to initialize pointers. - */ -void -mouse_sel_init() -{ - memset(&sel, 0, sizeof(struct selection)); -} +/* ---------------------------------------------------------------------- */ -/* - * Starts a sel (when mouse is pressed). - */ -void -mouse_sel_start(struct mouse *m) +/* Starts a selection. */ +static void +selarea_start(void) { - if (sel.text != NULL) { - free(sel.text); - sel.text = NULL; + + if (Selarea.sa_buf != NULL) { + free(Selarea.sa_buf); + Selarea.sa_buf = NULL; } - sel.start_row = m->row; - sel.start_col = m->col; - mouse_sel_calculate(m); - m->selecting = 1; + Selarea.sa_y1 = Selmouse.sm_y; + Selarea.sa_x1 = Selmouse.sm_x; + selarea_calculate(); + Selmouse.sm_selecting = 1; } -/* - * Ends a sel. Text is copied to memory for future pasting and - * highlighted region is returned to normal state. - */ -void -mouse_sel_end(struct mouse *m) +/* ---------------------------------------------------------------------- */ + +/* Ends a selection. Highlighted text is copied to the buffer. */ +static void +selarea_end(void) { size_t i; - mouse_sel_calculate(m); + selarea_calculate(); /* Invert sel coordinates if needed */ - if (sel.start_col > sel.end_col) { - i = sel.end_col; - sel.end_col = sel.start_col; - sel.start_col = i; - } - if (sel.start_row > sel.end_row) { - i = sel.end_row; - sel.end_row = sel.start_row; - sel.start_row = i; + if (Selarea.sa_x1 > Selarea.sa_x2) { + i = Selarea.sa_x2; + Selarea.sa_x2 = Selarea.sa_x1; + Selarea.sa_x1 = i; + } + if (Selarea.sa_y1 > Selarea.sa_y2) { + i = Selarea.sa_y2; + Selarea.sa_y2 = Selarea.sa_y1; + Selarea.sa_y1 = i; } - sel_copy_text(m); - m->selecting = 0; + selarea_copy_text(); + Selmouse.sm_selecting = 0; } -/* - * Calculates sel absolute postitions. - */ -void -mouse_sel_calculate(struct mouse *m) -{ - size_t i = m->max_col + 1; +/* ---------------------------------------------------------------------- */ - sel.end_row = m->row; - sel.end_col = m->col; - sel.abs_start = sel.start_row * i + sel.start_col; - sel.abs_end = sel.end_row * i + sel.end_col; - - if (sel.abs_start > sel.abs_end) { - i = sel.abs_end; - sel.abs_end = sel.abs_start; - sel.abs_start = i; +/* Calculates selection absolute positions in the screen buffer. */ +static void +selarea_calculate(void) +{ + size_t i; + + i = Selmouse.sm_max_x + 1; + Selarea.sa_y2 = Selmouse.sm_y; + Selarea.sa_x2 = Selmouse.sm_x; + Selarea.sa_startoff = Selarea.sa_y1 * i + Selarea.sa_x1; + Selarea.sa_endoff = Selarea.sa_y2 * i + Selarea.sa_x2; + + if (Selarea.sa_startoff > Selarea.sa_endoff) { + i = Selarea.sa_endoff; + Selarea.sa_endoff = Selarea.sa_startoff; + Selarea.sa_startoff = i; } } -/* - * Hides highlighted region, returning it to normal colors. - */ -void -mouse_sel_hide(struct mouse *m) +/* ---------------------------------------------------------------------- */ + +/* Hides the highlighted region, returning it to normal colors. */ +static void +selarea_hide(void) { size_t i; - for (i = sel.abs_start; i <= sel.abs_end; i++) - char_invert(m, 0, i); + for (i = Selarea.sa_startoff; i <= Selarea.sa_endoff; i++) + char_invert(0, i); } -/* - * Highlights selected region. - */ -void -mouse_sel_show(struct mouse *m) +/* ---------------------------------------------------------------------- */ + +/* Highlights the selected region. */ +static void +selarea_show(void) { size_t i; - mouse_sel_calculate(m); - for (i = sel.abs_start; i <= sel.abs_end; i++) - char_invert(m, 0, i); + selarea_calculate(); + for (i = Selarea.sa_startoff; i <= Selarea.sa_endoff; i++) + char_invert(0, i); } +/* ---------------------------------------------------------------------- */ -/* - * Pastes selected text into the active console. - */ -void -mouse_sel_paste(struct mouse *m) +/* Pastes selected text into the active console. */ +static void +selarea_paste(void) { size_t i; - if (sel.text == NULL) + if (Selarea.sa_buf == NULL) return; - for (i = 0; i < sel.text_size; i++) - if (ioctl(m->tty_fd, TIOCSTI, &sel.text[i]) == -1) + for (i = 0; i < Selarea.sa_buflen; i++) + if (ioctl(Selmouse.sm_ttyfd, TIOCSTI, + &Selarea.sa_buf[i]) == -1) warn("ioctl(TIOCSTI)"); } Index: wsmoused.8 =================================================================== RCS file: /cvsroot/src/usr.sbin/wsmoused/wsmoused.8,v retrieving revision 1.11 diff -u -r1.11 wsmoused.8 --- wsmoused.8 2003/04/16 08:42:16 1.11 +++ wsmoused.8 2003/08/06 17:30:36 @@ -4,7 +4,7 @@ .\" All rights reserved. .\" .\" This code is derived from software contributed to The NetBSD Foundation -.\" by Julio Merino. +.\" by Julio M. Merino Vidal. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -27,7 +27,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd March 4, 2003 +.Dd August 6, 2003 .Dt WSMOUSED 8 .Os .Sh NAME @@ -37,6 +37,7 @@ .Nm .Op Fl d Ar device .Op Fl f Ar conf_file +.Op Fl m Ar modes .Op Fl n .Sh DESCRIPTION The @@ -58,8 +59,17 @@ specifies the configuration file to be used. Defaults to .Pa /etc/wsmoused.conf . +.It Fl m Ar modes +specifies which modes should be activated. +Mode names are given in the argument as a whitespace separated list. +Overrides the +.Sq modes +directive in the configuration file. .It Fl n do not fork in the background (for debugging purposes). +Overrides the +.Sq nodaemon +directive in the configuration file. .El .Pp Many other details can be tuned. @@ -125,5 +135,5 @@ The .Nm command was developed by -.An Julio Merino +.An Julio M. Merino Vidal .Aq jmmv@NetBSD.org . Index: wsmoused.c =================================================================== RCS file: /cvsroot/src/usr.sbin/wsmoused/wsmoused.c,v retrieving revision 1.10 diff -u -r1.10 wsmoused.c --- wsmoused.c 2003/03/05 10:51:43 1.10 +++ wsmoused.c 2003/08/06 17:30:36 @@ -5,7 +5,7 @@ * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation - * by Julio Merino. + * by Julio M. Merino Vidal. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,6 +32,8 @@ #include #ifndef lint +__COPYRIGHT("@(#) Copyright (c) 2002, 2003\n" +"The NetBSD Foundation, Inc. All rights reserved.\n"); __RCSID("$NetBSD: wsmoused.c,v 1.10 2003/03/05 10:51:43 jmmv Exp $"); #endif /* not lint */ @@ -42,113 +44,133 @@ #include #include -#include #include #include #include #include #include #include -#include #include #include #include "pathnames.h" #include "wsmoused.h" -#define IS_MOTION_EVENT(type) (((type) == WSCONS_EVENT_MOUSE_DELTA_X) || \ - ((type) == WSCONS_EVENT_MOUSE_DELTA_Y) || \ - ((type) == WSCONS_EVENT_MOUSE_DELTA_Z)) -#define IS_BUTTON_EVENT(type) (((type) == WSCONS_EVENT_MOUSE_UP) || \ - ((type) == WSCONS_EVENT_MOUSE_DOWN)) - -static struct mouse mouse; -static char *PidFile = NULL; -static int XConsole = -1; +/* --------------------------------------------------------------------- */ /* - * Show program usage information + * Global variables. */ + +static struct mouse Mouse; +static char *Pid_File = NULL; +static int X_Console = -1; + +#ifdef WSMOUSED_SELECTION_MODE +extern struct mode_bootstrap Selection_Mode; +#endif + +#define MAX_MODES 1 +static struct mode_bootstrap *Modes[MAX_MODES]; +static struct mode_bootstrap *Avail_Modes[] = { +#ifdef WSMOUSED_SELECTION_MODE + &Selection_Mode, +#endif +}; + +/* --------------------------------------------------------------------- */ + +/* + * Prototypes for functions private to this module. + */ + +static void usage(void); +static void open_device(unsigned int); +static void init_mouse(void); +static void event_loop(void); +static void generic_wscons_event(struct wscons_event); +static int attach_mode(const char *); +static void attach_modes(char *); +static void detach_mode(const char *); +static void detach_modes(void); +static void signal_terminate(int); +int main(int, char **); + +/* --------------------------------------------------------------------- */ + +/* Shows program usage information and exits. */ static void usage(void) { + (void)fprintf(stderr, - "Usage: %s [-d device] [-f config_file] [-n]\n", + "Usage: %s [-d device] [-f config_file] [-m modes] [-n]\n", getprogname()); exit(EXIT_FAILURE); } -/* - * Handler for close signals - */ -static void -signal_terminate(int sig) -{ - mouse_cursor_hide(&mouse); - config_free(); - exit(EXIT_SUCCESS); -} +/* --------------------------------------------------------------------- */ -/* - * Open the mouse device (i.e. /dev/wsmouse). The argument secs - * specifies the number of seconds we must wait before opening the - * device. This is used when returning from X. See mouse_open_tty(). - */ +/* Initializes mouse information. Basically, it opens required files + * for the daemon to work. */ static void -mouse_open_device(struct mouse *m, int secs) +init_mouse(void) { - if (m->fd != -1) return; - sleep(secs); + Mouse.m_devfd = -1; + open_device(0); - /* Open mouse file descriptor */ - m->fd = open(m->device_name, - O_RDONLY | O_NONBLOCK, 0); - if (m->fd == -1) { - err(EXIT_FAILURE, "cannot open %s", m->device_name); + /* Open FIFO, if wanted */ + Mouse.m_fifofd = -1; + if (Mouse.m_fifoname != NULL) { + Mouse.m_fifofd = open(Mouse.m_fifoname, + O_RDWR | O_NONBLOCK, 0); + if (Mouse.m_fifofd == -1) + err(EXIT_FAILURE, "cannot open %s", Mouse.m_fifoname); } } -/* - * Prepare mouse file descriptors - */ +/* --------------------------------------------------------------------- */ + +/* Opens the mouse device (if not already opened). The argument `secs' + * specifies how much seconds the function will wait before trying to + * open the device; this is used when returning from the X console. */ static void -open_files(void) +open_device(unsigned int secs) { - /* Open wsdisplay status device */ - mouse.stat_fd = open(_PATH_TTYSTAT, O_RDONLY | O_NONBLOCK, 0); - if (mouse.stat_fd == -1) - err(EXIT_FAILURE, "cannot open %s", mouse.tstat_name); - mouse.fd = -1; - mouse_open_device(&mouse, 0); + if (Mouse.m_devfd != -1) + return; - /* Open FIFO, if wanted */ - mouse.fifo_fd = -1; - if (mouse.fifo_name != NULL) { - mouse.fifo_fd = open(mouse.fifo_name, O_RDWR | O_NONBLOCK, 0); - if (mouse.fifo_fd == -1) - err(EXIT_FAILURE, "cannot open %s", mouse.fifo_name); - } + sleep(secs); + + /* Open mouse file descriptor */ + Mouse.m_devfd = open(Mouse.m_devname, O_RDONLY | O_NONBLOCK, 0); + if (Mouse.m_devfd == -1) + err(EXIT_FAILURE, "cannot open %s", Mouse.m_devname); } -/* - * Mouse event loop - */ +/* --------------------------------------------------------------------- */ + +/* Main program event loop. This function polls the wscons status + * device and the mouse device; whenever an event is received, the + * appropiate callback is fired for all attached modes. If the polls + * times out (which only appens when the mouse is disabled), another + * callback is launched. */ static void event_loop(void) { - int res; + int i, res; struct pollfd fds[2]; struct wscons_event event; - fds[0].fd = mouse.stat_fd; + fds[0].fd = Mouse.m_statfd; fds[0].events = POLLIN; for (;;) { - fds[1].fd = mouse.fd; + fds[1].fd = Mouse.m_devfd; fds[1].events = POLLIN; - if (mouse.disabled) + if (Mouse.m_disabled) res = poll(fds, 1, INFTIM); else res = poll(fds, 2, 300); @@ -157,169 +179,220 @@ warn("failed to read from devices"); if (fds[0].revents & POLLIN) { - res = read(mouse.stat_fd, &event, sizeof(event)); + res = read(Mouse.m_statfd, &event, sizeof(event)); if (res != sizeof(event)) warn("failed to read from mouse stat"); - screen_event(&mouse, &event); + + generic_wscons_event(event); + + for (i = 0; i < MAX_MODES && Modes[i] != NULL; i++) + if (Modes[i]->mb_wscons_event != NULL) + Modes[i]->mb_wscons_event(event); + } else if (fds[1].revents & POLLIN) { - res = read(mouse.fd, &event, sizeof(event)); + res = read(Mouse.m_devfd, &event, sizeof(event)); if (res != sizeof(event)) warn("failed to read from mouse"); - if (mouse.fifo_fd >= 0) { - res = write(mouse.fifo_fd, &event, + if (Mouse.m_fifofd >= 0) { + res = write(Mouse.m_fifofd, &event, sizeof(event)); if (res != sizeof(event)) warn("failed to write to fifo"); } - if (IS_MOTION_EVENT(event.type)) { - mouse_motion_event(&mouse, &event); - } else if (IS_BUTTON_EVENT(event.type)) { - mouse_button_event(&mouse, &event); - } else { - warn("unknown wsmouse event"); - } - } else - if (!mouse.selecting) mouse_cursor_hide(&mouse); + for (i = 0; i < MAX_MODES && Modes[i] != NULL; i++) + if (Modes[i]->mb_wsmouse_event != NULL) + Modes[i]->mb_wsmouse_event(event); + } else { + for (i = 0; i < MAX_MODES && Modes[i] != NULL; i++) + if (Modes[i]->mb_poll_timeout != NULL) + Modes[i]->mb_poll_timeout(); + } } } -/* - * Initializes mouse structure coordinate information. The mouse will - * be displayed at the center of the screen at start. - */ +/* --------------------------------------------------------------------- */ + +/* This function parses generic wscons status events. Actually, it + * handles the screen switch event to enable or disable the mouse, + * depending if we are entering or leaving the X console. */ static void -mouse_init(void) +generic_wscons_event(struct wscons_event evt) { - struct winsize ws; - struct wsdisplay_char ch; - int i; - /* Get terminal size */ - if (ioctl(0, TIOCGWINSZ, &ws) < 0) - err(EXIT_FAILURE, "cannot get terminal size"); - - /* Open current tty */ - ioctl(mouse.stat_fd, WSDISPLAYIO_GETACTIVESCREEN, &i); - mouse.tty_fd = -1; - mouse_open_tty(&mouse, i); - - /* Check if the kernel has character functions */ - ch.row = ch.col = 0; - if (ioctl(mouse.tty_fd, WSDISPLAYIO_GETWSCHAR, &ch) < 0) - err(EXIT_FAILURE, "ioctl(WSDISPLAYIO_GETWSCHAR) failed"); - - mouse.max_row = ws.ws_row - 1; - mouse.max_col = ws.ws_col - 1; - mouse.row = mouse.max_row / 2; - mouse.col = mouse.max_col / 2; - mouse.count_row = 0; - mouse.count_col = 0; - mouse.cursor = 0; - mouse.selecting = 0; + switch (evt.type) { + case WSCONS_EVENT_SCREEN_SWITCH: + if (evt.value == X_Console) { + Mouse.m_disabled = 1; + (void)close(Mouse.m_devfd); + Mouse.m_devfd = -1; + } else { + if (Mouse.m_disabled) { + open_device(5); + Mouse.m_disabled = 0; + } else { + (void)close(Mouse.m_devfd); + Mouse.m_devfd = -1; + open_device(0); + } + } + break; + } } -/* - * Hides the mouse cursor - */ -void -mouse_cursor_hide(struct mouse *m) -{ - if (!m->cursor) return; - char_invert(m, m->row, m->col); - m->cursor = 0; +/* --------------------------------------------------------------------- */ + +/* Attaches a mode to the list of active modes, based on its name. + * Returns 1 on success or 0 if the mode fails to initialize or there is + * any other problem. */ +static int +attach_mode(const char *name) +{ + int i, pos; + struct mode_bootstrap *mb; + + for (i = 0, pos = -1; i < MAX_MODES; i++) + if (Modes[i] == NULL) { + pos = i; + break; + } + if (pos == -1) { + warnx("modes table full; cannot register `%s'", name); + return 0; + } + + for (i = 0; i < MAX_MODES; i++) { + mb = Avail_Modes[i]; + if (mb != NULL && strcmp(name, mb->mb_name) == 0) { + int res; + + res = mb->mb_startup(&Mouse); + if (res == 0) { + warnx("startup failed for `%s' mode", + mb->mb_name); + return 0; + } else { + Modes[pos] = mb; + return 1; + } + } + } + + warnx("unknown mode `%s' (see the `modes' directive)", name); + return 0; } -/* - * Shows the mouse cursor - */ -void -mouse_cursor_show(struct mouse *m) +/* --------------------------------------------------------------------- */ + +/* Attaches all modes given in the whitespace separated string `list'. + * A fatal error is produced if no active modes can be attached. */ +static void +attach_modes(char *list) { - if (m->cursor) return; - char_invert(m, m->row, m->col); - m->cursor = 1; + char *last, *p; + int count; + + /* Attach all requested modes */ + (void)memset(&Modes, 0, sizeof(struct mode_bootstrap) * MAX_MODES); + for (count = 0, (p = strtok_r(list, " ", &last)); p; + (p = strtok_r(NULL, " ", &last))) { + if (attach_mode(p)) + count++; + } + + if (count == 0) + errx(EXIT_FAILURE, "no active modes found; exiting..."); } -/* - * Opens the specified tty (we want it for ioctl's). If tty_fd in - * mouse structure is -1, no close is performed. Otherwise, the old - * file descriptor is closed and the new one opened. - */ -void -mouse_open_tty(struct mouse *m, int ttyno) +/* --------------------------------------------------------------------- */ + +/* Detaches a mode from the active modes list based on its name. */ +static void +detach_mode(const char *name) { - char buf[20]; + int i; + struct mode_bootstrap *mb; - if (m->tty_fd >= 0) close(m->tty_fd); - if (ttyno == XConsole) { - m->disabled = 1; - (void)close(m->fd); - m->fd = -1; - return; + for (i = 0; i < MAX_MODES; i++) { + mb = Modes[i]; + if (mb != NULL && strcmp(name, mb->mb_name) == 0) { + int res; + + res = mb->mb_cleanup(); + if (res == 0) { + warnx("cleanup failed for `%s' mode", + mb->mb_name); + return; + } else { + Modes[i] = NULL; + return; + } + } } - /* Open with delay. When returning from X, wsmoused keeps busy - some seconds so we have to wait. */ - mouse_open_device(m, 5); - (void)snprintf(buf, sizeof(buf), _PATH_TTYPREFIX "%d", ttyno); - m->tty_fd = open(buf, O_RDONLY | O_NONBLOCK); - if (m->tty_fd < 0) - errx(EXIT_FAILURE, "cannot open %s", buf); - m->disabled = 0; + + warnx("unknown mode `%s' (see the `modes' directive)", name); } -/* - * Flip the foreground and background colors on char at coordinates - */ -void -char_invert(struct mouse *m, size_t row, size_t col) +/* --------------------------------------------------------------------- */ + +/* Detaches all active modes. */ +static void +detach_modes(void) { - struct wsdisplay_char ch; - int t; + int i; - ch.row = row; - ch.col = col; + for (i = 0; i < MAX_MODES && Modes[i] != NULL; i++) + detach_mode(Modes[i]->mb_name); +} - if (ioctl(m->tty_fd, WSDISPLAYIO_GETWSCHAR, &ch) == -1) { - warn("ioctl(WSDISPLAYIO_GETWSCHAR) failed"); - return; - } +/* --------------------------------------------------------------------- */ - t = ch.foreground; - ch.foreground = ch.background; - ch.background = t; +/* Signal handler for close signals. The program can only be exited + * through this function. */ +/* ARGSUSED */ +static void +signal_terminate(int sig) +{ - if (ioctl(m->tty_fd, WSDISPLAYIO_PUTWSCHAR, &ch) == -1) - warn("ioctl(WSDISPLAYIO_PUTWSCHAR) failed"); + detach_modes(); + config_free(); + exit(EXIT_SUCCESS); } -/* - * Main function - */ +/* --------------------------------------------------------------------- */ + +/* Main program. Parses command line options, reads the configuration + * file, initializes the mouse and associated files and launches the main + * event loop. */ int main(int argc, char **argv) { - int opt, nodaemon = -1; - int needconf = 0; - char *conffile; - struct block *mode; + char *conffile, *modelist, *tstat; + int needconf, nodaemon, opt; + struct block *conf; setprogname(argv[0]); - memset(&mouse, 0, sizeof(struct mouse)); + (void)memset(&Mouse, 0, sizeof(struct mouse)); conffile = _PATH_CONF; + modelist = NULL; + needconf = 0; + nodaemon = -1; /* Parse command line options */ - while ((opt = getopt(argc, argv, "d:f:n")) != -1) { + while ((opt = getopt(argc, argv, "d:f:m:n")) != -1) { switch (opt) { case 'd': /* Mouse device name */ - mouse.device_name = optarg; + Mouse.m_devname = optarg; break; case 'f': /* Configuration file name */ needconf = 1; conffile = optarg; break; + case 'm': /* List of modes to activate */ + modelist = optarg; + break; case 'n': /* No daemon */ nodaemon = 1; break; @@ -329,34 +402,28 @@ } } - /* Read the configuration file and get our mode configuration */ + /* Read the configuration file and get some basic properties */ config_read(conffile, needconf); - mode = config_get_mode("sel"); - - /* Set values according to the configuration file */ - if (mouse.device_name == NULL) - mouse.device_name = block_get_propval(mode, "device", - _PATH_DEFAULT_MOUSE); - + conf = config_get_mode("Global"); if (nodaemon == -1) - nodaemon = block_get_propval_int(mode, "nodaemon", 0); - - mouse.slowdown_x = block_get_propval_int(mode, "slowdown_x", 0); - mouse.slowdown_y = block_get_propval_int(mode, "slowdown_y", 3); - mouse.tstat_name = block_get_propval(mode, "ttystat", _PATH_TTYSTAT); - XConsole = block_get_propval_int(mode, "xconsole", -1); - - if (block_get_propval_int(mode, "lefthanded", 0)) { - mouse.but_select = 2; - mouse.but_paste = 0; - } else { - mouse.but_select = 0; - mouse.but_paste = 2; - } + nodaemon = block_get_propval_int(conf, "nodaemon", 0); + X_Console = block_get_propval_int(conf, "xconsole", -1); - open_files(); - mouse_init(); - mouse_sel_init(); + /* Open wsdisplay status device */ + tstat = block_get_propval(conf, "ttystat", _PATH_TTYSTAT); + Mouse.m_statfd = open(tstat, O_RDONLY | O_NONBLOCK, 0); + if (Mouse.m_statfd == -1) + err(EXIT_FAILURE, "cannot open %s", tstat); + + /* Initialize mouse information and attach modes */ + if (Mouse.m_devname == NULL) + Mouse.m_devname = block_get_propval(conf, "device", + _PATH_DEFAULT_MOUSE); + init_mouse(); + if (modelist != NULL) + attach_modes(modelist); + else + attach_modes(block_get_propval(conf, "modes", "selection")); /* Setup signal handlers */ (void)signal(SIGINT, signal_terminate); @@ -370,10 +437,11 @@ err(EXIT_FAILURE, "failed to become a daemon"); /* Create the pidfile, if wanted */ - PidFile = block_get_propval(mode, "pidfile", NULL); - if (pidfile(PidFile) == -1) - warn("pidfile %s", PidFile); + Pid_File = block_get_propval(conf, "pidfile", NULL); + if (pidfile(Pid_File) == -1) + warn("pidfile %s", Pid_File); } + event_loop(); /* NOTREACHED */ Index: wsmoused.conf.5 =================================================================== RCS file: /cvsroot/src/usr.sbin/wsmoused/wsmoused.conf.5,v retrieving revision 1.3 diff -u -r1.3 wsmoused.conf.5 --- wsmoused.conf.5 2003/03/04 22:31:15 1.3 +++ wsmoused.conf.5 2003/08/06 17:30:36 @@ -4,7 +4,7 @@ .\" All rights reserved. .\" .\" This code is derived from software contributed to The NetBSD Foundation -.\" by Julio Merino. +.\" by Julio M. Merino Vidal. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -27,7 +27,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd March 4, 2003 +.Dd August 6, 2003 .Dt WSMOUSED.CONF 5 .Os .Sh NAME @@ -58,9 +58,11 @@ which goes to the right. The assignment ends with a semicolon. It looks like: +.Pp .Dl name = value; .Pp There is no difference between string or integer values when defining them. +The value must be surrounded by double quotes if it contains whitespace. Booleans are specified as integers, where .Sq 0 means false and @@ -85,7 +87,7 @@ .Ed .Pp Actually, there is only one recognized mode, the -.Ql sel +.Ql selection mode. .Ss Properties common to all modes The following properties can be defined in the global scope, thus @@ -98,6 +100,10 @@ device name to use. Defaults to .Pa /dev/wsmouse . +.It modes = string; +Whitespace separated list of modes to be activated when running. +Defaults to +.Sq selection . .It nodaemon = boolean; Set to 1 to not fork in the background. .It pidfile = basename; @@ -109,9 +115,9 @@ extension automatically added. By default it is set to daemon's program name. .El -.Ss Properties specific to the sel mode +.Ss Properties specific to the selection mode The following properties are only useful when running in the -.Em sel +.Em selection mode: .Bl -tag -width indent .It fifo = pathname; Index: wsmoused.h =================================================================== RCS file: /cvsroot/src/usr.sbin/wsmoused/wsmoused.h,v retrieving revision 1.3 diff -u -r1.3 wsmoused.h --- wsmoused.h 2003/03/04 14:33:55 1.3 +++ wsmoused.h 2003/08/06 17:30:36 @@ -1,11 +1,11 @@ /* $NetBSD: wsmoused.h,v 1.3 2003/03/04 14:33:55 jmmv Exp $ */ /* - * Copyright (c) 2002 The NetBSD Foundation, Inc. + * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation - * by Julio Merino. + * by Julio M. Merino Vidal. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,31 +32,28 @@ #ifndef _WSMOUSED_WSMOUSED_H #define _WSMOUSED_WSMOUSED_H +#define IS_MOTION_EVENT(type) (((type) == WSCONS_EVENT_MOUSE_DELTA_X) || \ + ((type) == WSCONS_EVENT_MOUSE_DELTA_Y) || \ + ((type) == WSCONS_EVENT_MOUSE_DELTA_Z)) +#define IS_BUTTON_EVENT(type) (((type) == WSCONS_EVENT_MOUSE_UP) || \ + ((type) == WSCONS_EVENT_MOUSE_DOWN)) + struct mouse { - /* File descriptors and names */ - int fd; - int tty_fd; - int stat_fd; - int fifo_fd; - char *device_name; - char *fifo_name; - char *tstat_name; - - /* Screen coordinates */ - size_t row, col; - size_t max_row, max_col; - - /* Movement information */ - size_t slowdown_x, slowdown_y; - size_t count_row, count_col; - - int cursor; - int selecting; - int disabled; - - /* Button configuration */ - int but_select; - int but_paste; + int m_devfd; /* File descriptor of wsmouse device */ + int m_fifofd; /* File descriptor of fifo */ + int m_statfd; /* File descriptor of wscons status device */ + char *m_devname; /* File name of wsmouse device */ + char *m_fifoname; /* File name of fifo */ + int m_disabled; /* Whether if the mouse is disabled or not */ +}; + +struct mode_bootstrap { + char *mb_name; + int (*mb_startup)(struct mouse *); + int (*mb_cleanup)(void); + void (*mb_wsmouse_event)(struct wscons_event); + void (*mb_wscons_event)(struct wscons_event); + void (*mb_poll_timeout)(void); }; struct prop { @@ -80,12 +77,6 @@ struct block *b_parent; }; -/* Prototypes for wsmoused.c */ -void char_invert(struct mouse *, size_t, size_t); -void mouse_cursor_show(struct mouse *); -void mouse_cursor_hide(struct mouse *); -void mouse_open_tty(struct mouse *, int); - /* Prototypes for config.c */ struct prop *prop_new(void); void prop_free(struct prop *); @@ -93,24 +84,10 @@ void block_free(struct block *); void block_add_prop(struct block *, struct prop *); void block_add_child(struct block *, struct block *); -char *block_get_propval(struct block *, char *, char *); -int block_get_propval_int(struct block *, char *, int); -struct block *config_get_mode(char *); -void config_read(char *, int); +char *block_get_propval(struct block *, const char *, char *); +int block_get_propval_int(struct block *, const char *, int); +struct block *config_get_mode(const char *); +void config_read(const char *, int); void config_free(void); - -/* Prototypes for event.c */ -void mouse_motion_event(struct mouse *, struct wscons_event *); -void mouse_button_event(struct mouse *, struct wscons_event *); -void screen_event(struct mouse *, struct wscons_event *); - -/* Prototypes for selection.c */ -void mouse_sel_init(void); -void mouse_sel_start(struct mouse *); -void mouse_sel_end(struct mouse *); -void mouse_sel_calculate(struct mouse *); -void mouse_sel_hide(struct mouse *); -void mouse_sel_show(struct mouse *); -void mouse_sel_paste(struct mouse *); #endif /* _WSMOUSED_WSMOUSED_H */