summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcus Brinkmann <marcus@gnu.org>2002-08-22 21:33:02 +0000
committerMarcus Brinkmann <marcus@gnu.org>2002-08-22 21:33:02 +0000
commit057b2a310582ea16dc147e948fc42bb61dc53b0d (patch)
tree03c90b80811f4fde29939e63c6bc920bc7ed18d9
parent7fdb626470facba99422511754f0e6be11c7f81c (diff)
2002-08-22 Marcus Brinkmann <marcus@gnu.org>
* aclocal.m4 (hurd_LIB_NCURSESW): New test, modified from GNU inetutils 1.4.0. * configure.in: Use hurd_LIB_NCURSESW. * config.make.in (LIBNCURSESW): New variable, substituted by configure. (NCURSESW_INCLUDE): Likewise. * Makefile (lib-subdirs): Add libcons. (prog-subdirs): Add console. console/ 2002-08-22 Marcus Brinkmann <marcus@gnu.org> * console.h: Move file to ../hurd/. * Makefile (LCLHDRS): Remove console.h. * display.c: Include <hurd/console.h> instead "console.h". * console.c: Likewise. hurd/ 2002-08-22 Marcus Brinkmann <marcus@gnu.org> * console.h: Move here from ../console/. * Makefile (INSTHDRS): Add console.h. utils/ 2002-08-22 Marcus Brinkmann <marcus@gnu.org> * Makefile: Include `../config.make' early on to get LIBNCURSESW variable from configure before including Makeconf. (targets) [LIBNCURSES]: Add console-ncurses. (SRCS) [LIBNCURSES]: Add console-ncurses.c. (HURDLIBS) [LIBNCURSES]: Add cons. (console-ncurses): New target. (console-ncurses-CPPFLAGS): New variable. (console-ncurses-LDLIBS): Likewise.
-rw-r--r--hurd/console.h (renamed from console/console.h)0
-rw-r--r--utils/console-ncurses.c584
2 files changed, 584 insertions, 0 deletions
diff --git a/console/console.h b/hurd/console.h
index a6728a26..a6728a26 100644
--- a/console/console.h
+++ b/hurd/console.h
diff --git a/utils/console-ncurses.c b/utils/console-ncurses.c
new file mode 100644
index 00000000..4ec60d7d
--- /dev/null
+++ b/utils/console-ncurses.c
@@ -0,0 +1,584 @@
+/* console-ncurses.c -- A console client based on ncurses.
+ 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 <argp.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <wchar.h>
+#include <error.h>
+#include <assert.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 <hurd/cons.h>
+
+#include <version.h>
+
+struct mutex ncurses_lock;
+
+const char *cons_client_name = "console-ncurses";
+const char *cons_client_version = HURD_VERSION;
+
+
+struct curses_kc_to_cons_kc
+{
+ int curses;
+ char *cons;
+};
+
+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. */
+ };
+
+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 vcons_t active_vcons = NULL;
+
+error_t
+cons_vcons_activate (vcons_t vcons)
+{
+ error_t err;
+
+ assert (vcons);
+ assert (vcons != active_vcons);
+
+ err = cons_vcons_open (vcons);
+ if (err)
+ return err;
+
+ if (active_vcons)
+ cons_vcons_close (active_vcons);
+ active_vcons = vcons;
+ return 0;
+}
+
+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);
+ /* XXX: We ignore any error here. */
+ cons_switch (active_vcons->cons, 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)
+ {
+ if (active_vcons)
+ {
+ mutex_lock (&active_vcons->lock);
+ do
+ {
+ ret = write (active_vcons->input, buf, size);
+ if (ret > 0)
+ {
+ size -= ret;
+ buf += ret;
+ }
+ }
+ while (size && (ret != -1 || errno == EINTR));
+ mutex_unlock (&active_vcons->lock);
+ }
+ }
+ }
+ }
+}
+
+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));
+}
+
+inline short
+conchar_attr_to_color_pair (conchar_attr_t attr)
+{
+ return COLOR_PAIR (attr.bgcol << 3 | attr.fgcol);
+}
+
+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++;
+ }
+}
+
+
+void
+cons_vcons_update (vcons_t vcons)
+{
+ if (vcons != active_vcons)
+ return;
+ refresh ();
+}
+
+void
+cons_vcons_set_cursor_pos (vcons_t vcons, uint32_t col, uint32_t row)
+{
+ if (vcons != active_vcons)
+ return;
+ mutex_lock (&ncurses_lock);
+ move (row, col);
+ mutex_unlock (&ncurses_lock);
+}
+
+void
+cons_vcons_set_cursor_status (vcons_t vcons, uint32_t status)
+{
+ if (vcons != active_vcons)
+ return;
+ mutex_lock (&ncurses_lock);
+ curs_set (status ? (status == 1 ? 1 : 2) : 0);
+ mutex_unlock (&ncurses_lock);
+}
+
+void
+cons_vcons_scroll (vcons_t vcons, int delta)
+{
+ assert (delta >= 0);
+ if (vcons != active_vcons)
+ return;
+
+ mutex_lock (&ncurses_lock);
+ idlok (stdscr, TRUE);
+ scrollok (stdscr, TRUE);
+ scrl (delta);
+ idlok (stdscr, FALSE);
+ scrollok (stdscr, FALSE);
+ mutex_unlock (&ncurses_lock);
+}
+
+void
+cons_vcons_write (vcons_t vcons, conchar_t *str, size_t length,
+ uint32_t col, uint32_t row)
+{
+ int x;
+ int y;
+
+ if (vcons != active_vcons)
+ return;
+
+ mutex_lock (&ncurses_lock);
+ getsyx (y, x);
+ mvwputsn (str, length, col, row);
+ setsyx (y, x);
+ mutex_unlock (&ncurses_lock);
+}
+
+void
+cons_vcons_beep (vcons_t vcons)
+{
+ if (vcons != active_vcons)
+ return;
+
+ mutex_lock (&ncurses_lock);
+ beep ();
+ mutex_unlock (&ncurses_lock);
+}
+
+void
+cons_vcons_flash (vcons_t vcons)
+{
+ if (vcons != active_vcons)
+ return;
+
+ mutex_lock (&ncurses_lock);
+ flash ();
+ mutex_unlock (&ncurses_lock);
+}
+
+
+int
+main (int argc, char *argv[])
+{
+ error_t err;
+ int i;
+
+ /* Parse our command line. This shouldn't ever return an error. */
+ argp_parse (&cons_startup_argp, argc, argv, 0, 0, 0);
+
+ mutex_init (&ncurses_lock);
+
+ 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);
+
+ cthread_detach (cthread_fork (input_loop, NULL));
+
+ err = cons_init ();
+ if (err)
+ error (5, err, "Console library initialization failed");
+
+ cons_server_loop ();
+
+ /* Never reached. */
+ endwin ();
+ return 0;
+}