summaryrefslogtreecommitdiff
path: root/console-client/ncursesw.c
diff options
context:
space:
mode:
authorMarcus Brinkmann <marcus@gnu.org>2002-09-17 12:26:10 +0000
committerMarcus Brinkmann <marcus@gnu.org>2002-09-17 12:26:10 +0000
commit09e69605b16070de8ce317d86ad736d665a58906 (patch)
tree7c0dc29f4fc660a44d2f7d6ec9d099cc4f8301a6 /console-client/ncursesw.c
parentdbe4c7712b652b7ad3126e94c47b00fa2bbb0a05 (diff)
2002-09-17 Marcus Brinkmann <marcus@gnu.org>
* Makefile (prog-subdirs): Add console-client. sutils/ 2002-09-17 Marcus Brinkmann <marcus@gnu.org> * MAKEDEV.sh (mkdev: vcs): New console device. (mkdev: tty[0-9a-f]|tty[0-9][0-9a-f]): Replaced with new rules for tty[1-9][0-9]. utils/ 2002-09-17 Marcus Brinkmann <marcus@gnu.org> * console-ncurses.c: File removed (the ncursesw console client is now a driver in the console-client). * Makefile: Revert 2002-08-22 change: Do not include`../config.make'. (targets) [LIBNCURSES]: Removed. (SRCS) [LIBNCURSES]: Likewise. (HURDLIBS) [LIBNCURSES]: Likewise. (console-ncurses): Target removed. (console-ncurses-CPPFLAGS): Removed. (console-ncurses-LDLIBS): Likewise. console-client/ 2002-09-17 Marcus Brinkmann <marcus@gnu.org> * Makefile, bdf.c, bdf.h, bell.h, console.c, display.h, driver.c, driver.h, generic-speaker.c, input.h, pc-kbd.c, timer.c, timer.h, unicode.h, vga.c, vga-dynacolor.c, vga-dynacolor.h, vga-dynafont.c, vga-dynafont.h, vga-hw.h, vga-support.c, vga-support.h: New file.
Diffstat (limited to 'console-client/ncursesw.c')
-rw-r--r--console-client/ncursesw.c611
1 files changed, 611 insertions, 0 deletions
diff --git a/console-client/ncursesw.c b/console-client/ncursesw.c
new file mode 100644
index 00000000..b47d6513
--- /dev/null
+++ b/console-client/ncursesw.c
@@ -0,0 +1,611 @@
+/* ncursesw.c - The ncursesw console driver.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+ Written by Marcus Brinkmann.
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <assert.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <wchar.h>
+
+/* The makefiles make sure that this program is compiled with
+ -I${prefix}/ncursesw. */
+#include <curses.h>
+
+#include <cthreads.h>
+#include <hurd/console.h>
+
+#include "driver.h"
+
+
+/* ncurses is not thread-safe. This lock protects all calls into the
+ ncurses library. */
+struct mutex ncurses_lock;
+
+/* Forward declaration. */
+static struct display_ops ncursesw_display_ops;
+static struct input_ops ncursesw_input_ops;
+static struct bell_ops ncursesw_bell_ops;
+
+struct curses_kc_to_cons_kc
+{
+ int curses;
+ char *cons;
+};
+
+static struct curses_kc_to_cons_kc keycodes[] =
+ {
+ { KEY_BREAK, NULL }, /* XXX */
+ { KEY_DOWN, CONS_KEY_DOWN },
+ { KEY_UP, CONS_KEY_UP },
+ { KEY_RIGHT, CONS_KEY_RIGHT },
+ { KEY_LEFT, CONS_KEY_LEFT },
+ { KEY_HOME, CONS_KEY_HOME },
+ { KEY_BACKSPACE, CONS_KEY_BACKSPACE },
+ { KEY_F(1), CONS_KEY_F1 },
+ { KEY_F(2), CONS_KEY_F2 },
+ { KEY_F(3), CONS_KEY_F3 },
+ { KEY_F(4), CONS_KEY_F4 },
+ { KEY_F(5), CONS_KEY_F5 },
+ { KEY_F(6), CONS_KEY_F6 },
+ { KEY_F(7), CONS_KEY_F7 },
+ { KEY_F(8), CONS_KEY_F8 },
+ { KEY_F(9), CONS_KEY_F9 },
+ { KEY_F(10), CONS_KEY_F10 },
+ { KEY_DL, NULL }, /* XXX Delete line. */
+ { KEY_IL, NULL }, /* XXX Insert line. */
+ { KEY_DC, CONS_KEY_DC },
+ { KEY_IC, CONS_KEY_IC },
+ { KEY_EIC, NULL }, /* XXX Exit insert mode. */
+ { KEY_CLEAR, NULL }, /* XXX Clear screen. */
+ { KEY_EOS, NULL }, /* XXX Clear to end of screen. */
+ { KEY_EOL, NULL }, /* XXX Clear to end of line. */
+ { KEY_SF, NULL }, /* XXX Scroll one line forward. */
+ { KEY_SR, NULL }, /* XXX Scroll one line backward. */
+ { KEY_NPAGE, CONS_KEY_NPAGE },
+ { KEY_PPAGE, CONS_KEY_PPAGE },
+ { KEY_STAB, NULL }, /* XXX Set tab. */
+ { KEY_CTAB, NULL }, /* XXX Clear tab. */
+ { KEY_CATAB, NULL }, /* XXX Clear all tabs. */
+ { KEY_ENTER, NULL }, /* XXX Enter or send. */
+ { KEY_SRESET, NULL }, /* XXX Soft (partial) reset. */
+ { KEY_RESET, NULL }, /* XXX Reset or hard reset. */
+ { KEY_PRINT, NULL }, /* XXX Print or copy. */
+ { KEY_LL, NULL }, /* XXX Home down or bottom (lower left). */
+ { KEY_A1, NULL }, /* XXX Upper left of keypad. */
+ { KEY_A3, NULL }, /* XXX Upper right of keypad. */
+ { KEY_B2, NULL }, /* XXX Center of keypad. */
+ { KEY_C1, NULL }, /* XXX Lower left of keypad. */
+ { KEY_C3, NULL }, /* XXX Lower right of keypad. */
+ { KEY_BTAB, CONS_KEY_BTAB },
+ { KEY_BEG, NULL }, /* XXX Beg(inning) key. */
+ { KEY_CANCEL, NULL }, /* XXX Cancel key. */
+ { KEY_CLOSE, NULL }, /* XXX Close key. */
+ { KEY_COMMAND, NULL }, /* XXX Cmd (command) key. */
+ { KEY_COPY, NULL }, /* XXX Copy key. */
+ { KEY_CREATE, NULL }, /* XXX Create key. */
+ { KEY_END, CONS_KEY_END },
+ { KEY_EXIT, NULL }, /* XXX Exit key. */
+ { KEY_FIND, NULL }, /* XXX Find key. */
+ { KEY_HELP, NULL }, /* XXX Help key. */
+ { KEY_MARK, NULL }, /* XXX Mark key. */
+ { KEY_MESSAGE, NULL }, /* XXX Message key. */
+ { KEY_MOUSE, NULL }, /* XXX Mouse event read. */
+ { KEY_MOVE, NULL }, /* XXX Move key. */
+ { KEY_NEXT, NULL }, /* XXX Next object key. */
+ { KEY_OPEN, NULL }, /* XXX Open key. */
+ { KEY_OPTIONS, NULL }, /* XXX Options key. */
+ { KEY_PREVIOUS, NULL }, /* XXX Previous object key. */
+ { KEY_REDO, NULL }, /* XXX Redo key. */
+ { KEY_REFERENCE, NULL }, /* XXX Ref(erence) key. */
+ { KEY_REFRESH, NULL }, /* XXX Refresh key. */
+ { KEY_REPLACE, NULL }, /* XXX Replace key. */
+ { KEY_RESIZE, NULL }, /* XXX Screen resized. */
+ { KEY_RESTART, NULL }, /* XXX Restart key. */
+ { KEY_RESUME, NULL }, /* XXX Resume key. */
+ { KEY_SAVE, NULL }, /* XXX Save key. */
+ { KEY_SBEG, NULL }, /* XXX Shifted beginning key. */
+ { KEY_SCANCEL, NULL }, /* XXX Shifted cancel key. */
+ { KEY_SCOMMAND, NULL }, /* XXX Shifted command key. */
+ { KEY_SCOPY, NULL }, /* XXX Shifted copy key. */
+ { KEY_SCREATE, NULL }, /* XXX Shifted create key. */
+ { KEY_SDC, NULL }, /* XXX Shifted delete char key. */
+ { KEY_SDL, NULL }, /* XXX Shifted delete line key. */
+ { KEY_SELECT, NULL }, /* XXX Select key. */
+ { KEY_SEND, NULL }, /* XXX Shifted end key. */
+ { KEY_SEOL, NULL }, /* XXX Shifted clear line key. */
+ { KEY_SEXIT, NULL }, /* XXX Shifted exit key. */
+ { KEY_SFIND, NULL }, /* XXX Shifted find key. */
+ { KEY_SHELP, NULL }, /* XXX Shifted help key. */
+ { KEY_SHOME, NULL }, /* XXX Shifted home key. */
+ { KEY_SIC, NULL }, /* XXX Shifted input key. */
+ { KEY_SLEFT, NULL }, /* XXX Shifted left arrow key. */
+ { KEY_SMESSAGE, NULL }, /* XXX Shifted message key. */
+ { KEY_SMOVE, NULL }, /* XXX Shifted move key. */
+ { KEY_SNEXT, NULL }, /* XXX Shifted next key. */
+ { KEY_SOPTIONS, NULL }, /* XXX Shifted options key. */
+ { KEY_SPREVIOUS, NULL }, /* XXX Shifted prev key. */
+ { KEY_SPRINT, NULL }, /* XXX Shifted print key. */
+ { KEY_SREDO, NULL }, /* XXX Shifted redo key. */
+ { KEY_SREPLACE, NULL }, /* XXX Shifted replace key. */
+ { KEY_SRIGHT, NULL }, /* XXX Shifted right arrow. */
+ { KEY_SRSUME, NULL }, /* XXX Shifted resume key. */
+ { KEY_SSAVE, NULL }, /* XXX Shifted save key. */
+ { KEY_SSUSPEND, NULL }, /* XXX Shifted suspend key. */
+ { KEY_SUNDO, NULL }, /* XXX Shifted undo key. */
+ { KEY_SUSPEND, NULL }, /* XXX Suspend key. */
+ { KEY_UNDO, NULL } /* XXX Undo key. */
+ };
+
+static int
+ucs4_to_altchar (wchar_t chr, chtype *achr)
+{
+ switch (chr)
+ {
+ case CONS_CHAR_RARROW:
+ *achr = ACS_RARROW;
+ break;
+ case CONS_CHAR_LARROW:
+ *achr = ACS_LARROW;
+ break;
+ case CONS_CHAR_UARROW:
+ *achr = ACS_UARROW;
+ break;
+ case CONS_CHAR_DARROW:
+ *achr = ACS_DARROW;
+ break;
+ case CONS_CHAR_BLOCK:
+ *achr = ACS_BLOCK;
+ break;
+ case CONS_CHAR_LANTERN:
+ *achr = ACS_LANTERN;
+ break;
+ case CONS_CHAR_DIAMOND:
+ *achr = ACS_DIAMOND;
+ break;
+ case CONS_CHAR_CKBOARD:
+ *achr = ACS_CKBOARD;
+ break;
+ case CONS_CHAR_DEGREE:
+ *achr = ACS_DEGREE;
+ break;
+ case CONS_CHAR_PLMINUS:
+ *achr = ACS_PLMINUS;
+ break;
+ case CONS_CHAR_BOARD:
+ *achr = ACS_BOARD;
+ break;
+ case CONS_CHAR_LRCORNER:
+ *achr = ACS_LRCORNER;
+ break;
+ case CONS_CHAR_URCORNER:
+ *achr = ACS_URCORNER;
+ break;
+ case CONS_CHAR_ULCORNER:
+ *achr = ACS_ULCORNER;
+ break;
+ case CONS_CHAR_LLCORNER:
+ *achr = ACS_LLCORNER;
+ break;
+ case CONS_CHAR_PLUS:
+ *achr = ACS_PLUS;
+ break;
+ case CONS_CHAR_S1:
+ *achr = ACS_S1;
+ break;
+ case CONS_CHAR_S3:
+ *achr = ACS_S3;
+ break;
+ case CONS_CHAR_HLINE:
+ *achr = ACS_HLINE;
+ break;
+ case CONS_CHAR_S7:
+ *achr = ACS_S7;
+ break;
+ case CONS_CHAR_S9:
+ *achr = ACS_S9;
+ break;
+ case CONS_CHAR_LTEE:
+ *achr = ACS_LTEE;
+ break;
+ case CONS_CHAR_RTEE:
+ *achr = ACS_RTEE;
+ break;
+ case CONS_CHAR_BTEE:
+ *achr = ACS_BTEE;
+ break;
+ case CONS_CHAR_TTEE:
+ *achr = ACS_TTEE;
+ break;
+ case CONS_CHAR_VLINE:
+ *achr = ACS_VLINE;
+ break;
+ case CONS_CHAR_LEQUAL:
+ *achr = ACS_LEQUAL;
+ break;
+ case CONS_CHAR_GEQUAL:
+ *achr = ACS_GEQUAL;
+ break;
+ case CONS_CHAR_PI:
+ *achr = ACS_PI;
+ break;
+ case CONS_CHAR_NEQUAL:
+ *achr = ACS_NEQUAL;
+ break;
+ case CONS_CHAR_STERLING:
+ *achr = ACS_STERLING;
+ break;
+ case CONS_CHAR_BULLET:
+ *achr = ACS_BULLET;
+ break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+static any_t
+input_loop (any_t unused)
+{
+ int fd = 0;
+ fd_set rfds;
+ int w_escaped = 0;
+
+ FD_ZERO (&rfds);
+ FD_SET (fd, &rfds);
+
+ while (1)
+ {
+ int ret;
+
+ FD_SET (fd, &rfds);
+
+ ret = select (fd + 1, &rfds, 0, 0, 0);
+ if (ret == 1)
+ {
+ char buffer[100];
+ char *buf = buffer;
+ size_t size = 0;
+
+ mutex_lock (&ncurses_lock);
+ while ((ret = getch ()) != ERR)
+ {
+ int i;
+ int found;
+
+ if (w_escaped)
+ {
+ switch (ret)
+ {
+ case 'x':
+ endwin ();
+ exit (0);
+ break;
+ case 23: /* ^W */
+ assert (size < 100);
+ buf[size++] = ret;
+ break;
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ /* Avoid a dead lock. */
+ mutex_unlock (&ncurses_lock);
+ console_switch (1 + (ret - '1'), 0);
+ mutex_lock (&ncurses_lock);
+ break;
+ default:
+ break;
+ }
+ w_escaped = 0;
+ }
+ else
+ switch (ret)
+ {
+ case 23: /* ^W */
+ w_escaped = 1;
+ break;
+ default:
+ found = 0;
+ for (i =0; i < sizeof(keycodes) / sizeof(keycodes[0]); i++)
+ {
+ if (keycodes[i].curses == ret)
+ {
+ if (keycodes[i].cons)
+ {
+ assert (size < 101 - strlen(keycodes[i].cons));
+ strcpy (&buf[size], keycodes[i].cons);
+ size += strlen (keycodes[i].cons);
+ }
+ found = 1;
+ break;
+ }
+ }
+ if (!found)
+ {
+ assert (size < 100);
+ buf[size++] = ret;
+ }
+ break;
+ }
+ }
+ mutex_unlock (&ncurses_lock);
+ if (size)
+ console_input (buf, size);
+ }
+ }
+}
+
+static inline attr_t
+conchar_attr_to_attr (conchar_attr_t attr)
+{
+ return ((attr.intensity == CONS_ATTR_INTENSITY_BOLD
+ ? A_BOLD : (attr.intensity == CONS_ATTR_INTENSITY_DIM
+ ? A_DIM : A_NORMAL))
+ | (attr.underlined ? A_UNDERLINE : 0)
+ | (attr.reversed ? A_REVERSE : 0)
+ | (attr.blinking ? A_BLINK: 0)
+ | (attr.concealed ? A_INVIS : 0));
+}
+
+static inline short
+conchar_attr_to_color_pair (conchar_attr_t attr)
+{
+ return COLOR_PAIR (attr.bgcol << 3 | attr.fgcol);
+}
+
+static void
+mvwputsn (conchar_t *str, size_t len, off_t x, off_t y)
+{
+ cchar_t chr;
+ wchar_t wch[2] = { L'\0', L'\0' };
+ uint32_t last_attr = * (uint32_t *) &str->attr;
+ attr_t attr = conchar_attr_to_attr (str->attr);
+ short color_pair = conchar_attr_to_color_pair (str->attr);
+
+ move (y, x);
+ while (len)
+ {
+ int ret;
+ chtype ac;
+
+ if (last_attr != *(uint32_t *) &str->attr)
+ {
+ last_attr = * (uint32_t *) &str->attr;
+ attr = conchar_attr_to_attr (str->attr);
+ color_pair = conchar_attr_to_color_pair (str->attr);
+ }
+
+ if (ucs4_to_altchar (str->chr, &ac))
+ addch (ac | attr | color_pair);
+ else
+ {
+ wch[0] = str->chr;
+ ret = setcchar (&chr, wch, attr, color_pair, NULL);
+#if 0
+ if (ret == ERR)
+ {
+ printf ("setcchar failed: %s\n", strerror (errno));
+ printf ("[%lc]\n", wch[0]);
+ assert (!"Do something if setcchar fails.");
+ }
+#endif
+ ret = add_wch (&chr);
+#if 0
+ if (ret == ERR)
+ {
+ printf ("add_wch failed: %i, %s\n", ret, strerror (errno));
+ printf ("[%lc]\n", wch[0]);
+ assert (!"Do something if add_wchr fails.");
+ }
+#endif
+ }
+ len--;
+ str++;
+ }
+}
+
+
+static error_t
+ncursesw_update (void *handle)
+{
+ mutex_lock (&ncurses_lock);
+ refresh ();
+ mutex_unlock (&ncurses_lock);
+ return 0;
+}
+
+
+static error_t
+ncursesw_set_cursor_pos (void *handle, uint32_t col, uint32_t row)
+{
+ mutex_lock (&ncurses_lock);
+ move (row, col);
+ mutex_unlock (&ncurses_lock);
+ return 0;
+}
+
+
+static error_t
+ncursesw_set_cursor_status (void *handle, uint32_t status)
+{
+ mutex_lock (&ncurses_lock);
+ curs_set (status ? (status == 1 ? 1 : 2) : 0);
+ mutex_unlock (&ncurses_lock);
+ return 0;
+}
+
+
+static error_t
+ncursesw_scroll (void *handle, int delta)
+{
+ /* XXX We don't support scrollback for now. */
+ assert (delta >= 0);
+
+ mutex_lock (&ncurses_lock);
+ idlok (stdscr, TRUE);
+ scrollok (stdscr, TRUE);
+ scrl (delta);
+ idlok (stdscr, FALSE);
+ scrollok (stdscr, FALSE);
+ mutex_unlock (&ncurses_lock);
+ return 0;
+}
+
+
+static error_t
+ncursesw_write (void *handle, conchar_t *str, size_t length,
+ uint32_t col, uint32_t row)
+{
+ int x;
+ int y;
+
+ mutex_lock (&ncurses_lock);
+ getyx (stdscr, y, x);
+ mvwputsn (str, length, col, row);
+ wmove (stdscr, y, x);
+ mutex_unlock (&ncurses_lock);
+ return 0;
+}
+
+
+static error_t
+ncursesw_flash (void *handle)
+{
+ mutex_lock (&ncurses_lock);
+ flash ();
+ mutex_unlock (&ncurses_lock);
+ return 0;
+}
+
+
+/* Bell driver operations. */
+error_t
+ncursesw_beep (void *handle)
+{
+ mutex_lock (&ncurses_lock);
+ beep ();
+ mutex_unlock (&ncurses_lock);
+ return 0;
+}
+
+
+
+static error_t
+ncursesw_driver_init (void **handle, int no_exit,
+ int argc, char *argv[], int *next)
+{
+ mutex_init (&ncurses_lock);
+ return 0;
+}
+
+static error_t
+ncursesw_driver_start (void *handle)
+{
+ error_t err;
+ int i;
+
+ initscr ();
+ start_color ();
+ for (i = 0; i < 64; i++)
+ init_pair (i, i & 7, i >> 3);
+ raw ();
+ noecho ();
+ nonl ();
+ intrflush (stdscr, FALSE);
+ nodelay (stdscr, TRUE);
+ timeout (1);
+ keypad (stdscr, TRUE);
+
+ err = driver_add_display (&ncursesw_display_ops, NULL);
+ if (err)
+ {
+ endwin ();
+ return err;
+ }
+ err = driver_add_input (&ncursesw_input_ops, NULL);
+ if (err)
+ {
+ err = driver_remove_display (&ncursesw_display_ops, NULL);
+ endwin ();
+ return err;
+ }
+ err = driver_add_bell (&ncursesw_bell_ops, NULL);
+ if (err)
+ {
+ err = driver_remove_input (&ncursesw_input_ops, NULL);
+ err = driver_remove_display (&ncursesw_display_ops, NULL);
+ endwin ();
+ return err;
+ }
+
+ cthread_detach (cthread_fork (input_loop, NULL));
+ endwin ();
+
+ return err;
+}
+
+/* Destroy the display HANDLE. */
+static error_t
+ncursesw_driver_fini (void *handle, int force)
+{
+ /* XXX Cancel the input thread. */
+ mutex_lock (&ncurses_lock);
+ driver_remove_display (&ncursesw_display_ops, NULL);
+ driver_remove_input (&ncursesw_input_ops, NULL);
+ driver_remove_bell (&ncursesw_bell_ops, NULL);
+ mutex_unlock (&ncurses_lock);
+
+ endwin ();
+ return 0;
+}
+
+
+struct driver_ops driver_ncursesw_ops =
+ {
+ ncursesw_driver_init,
+ ncursesw_driver_start,
+ ncursesw_driver_fini,
+ };
+
+static struct display_ops ncursesw_display_ops =
+ {
+ ncursesw_set_cursor_pos,
+ ncursesw_set_cursor_status,
+ ncursesw_scroll,
+ ncursesw_write,
+ ncursesw_update,
+ ncursesw_flash,
+ NULL
+ };
+
+static struct input_ops ncursesw_input_ops =
+ {
+ NULL,
+ NULL
+ };
+
+static struct bell_ops ncursesw_bell_ops =
+ {
+ ncursesw_beep,
+ NULL
+ };