Fix compilation on NetBSD.
[apps/madtty.git] / madtty / madtty.c
index af12870..317712c 100644 (file)
@@ -24,7 +24,7 @@
 #include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
-#include <pty.h>
+#include <langinfo.h>
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/types.h>
 #include <termios.h>
 #include <wchar.h>
-
+#ifdef __linux__
+# include <pty.h>
+#elif defined(__FreeBSD__)
+# include <libutil.h>
+#elif defined(__OpenBSD__) || defined(__NetBSD__)
+# include <util.h>
+#endif
 #include "madtty.h"
 
+#ifndef NCURSES_ATTR_SHIFT
+# define NCURSES_ATTR_SHIFT 8
+#endif
+
 #define IS_CONTROL(ch) !((ch) & 0xffffff60UL)
 
-static int has_default = 0;
+static int has_default, is_utf8;
 
 enum {
     C0_NUL = 0x00,
@@ -118,16 +128,26 @@ static char const * const keytable[KEY_MAX+1] = {
     [KEY_PPAGE]     = "\e[5~",
     [KEY_NPAGE]     = "\e[6~",
     [KEY_SUSPEND]   = "\x1A",  /* Ctrl+Z gets mapped to this */
-    [KEY_F(1)]      = "\e[[A",
-    [KEY_F(2)]      = "\e[[B",
-    [KEY_F(3)]      = "\e[[C",
-    [KEY_F(4)]      = "\e[[D",
-    [KEY_F(5)]      = "\e[[E",
+    [KEY_F(1)]      = "\e[11~",
+    [KEY_F(2)]      = "\e[12~",
+    [KEY_F(3)]      = "\e[13~",
+    [KEY_F(4)]      = "\e[14~",
+    [KEY_F(5)]      = "\e[15~",
     [KEY_F(6)]      = "\e[17~",
     [KEY_F(7)]      = "\e[18~",
     [KEY_F(8)]      = "\e[19~",
     [KEY_F(9)]      = "\e[20~",
     [KEY_F(10)]     = "\e[21~",
+    [KEY_F(11)]     = "\e[23~",
+    [KEY_F(12)]     = "\e[24~",
+    [KEY_F(13)]     = "\e[25~",
+    [KEY_F(14)]     = "\e[26~",
+    [KEY_F(15)]     = "\e[28~",
+    [KEY_F(16)]     = "\e[29~",
+    [KEY_F(17)]     = "\e[31~",
+    [KEY_F(18)]     = "\e[32~",
+    [KEY_F(19)]     = "\e[33~",
+    [KEY_F(20)]     = "\e[34~",
 };
 
 static void t_row_set(t_row_t *row, int start, int len, uint16_t attr)
@@ -668,10 +688,16 @@ static void madtty_process_nonprinting(madtty_t *t, wchar_t wc)
     }
 }
 
+static void is_utf8_locale(void)
+{
+    const char *cset = nl_langinfo(CODESET) ?: "ANSI_X3.4-1968";
+    is_utf8 = !strcmp(cset, "UTF-8");
+}
+
 // vt100 special graphics and line drawing
 // 5f-7e standard vt100
 // 40-5e rxvt extension for extra curses acs chars
-static uint16_t const vt100_0[62] = { // 41 .. 7e
+static uint16_t const vt100_utf8[62] = { // 41 .. 7e
             0x2191, 0x2193, 0x2192, 0x2190, 0x2588, 0x259a, 0x2603, // 41-47 hi mr. snowman!
          0,      0,      0,      0,      0,      0,      0,      0, // 48-4f
          0,      0,      0,      0,      0,      0,      0,      0, // 50-57
@@ -682,6 +708,46 @@ static uint16_t const vt100_0[62] = { // 41 .. 7e
     0x2502, 0x2264, 0x2265, 0x03c0, 0x2260, 0x00a3, 0x00b7,         // 78-7e
 };
 
+static uint32_t vt100[62];
+
+void madtty_init_vt100_graphics(void)
+{
+    vt100['l' - 0x41] = ACS_ULCORNER;
+    vt100['m' - 0x41] = ACS_LLCORNER;
+    vt100['k' - 0x41] = ACS_URCORNER;
+    vt100['j' - 0x41] = ACS_LRCORNER;
+    vt100['u' - 0x41] = ACS_RTEE;
+    vt100['t' - 0x41] = ACS_LTEE;
+    vt100['v' - 0x41] = ACS_TTEE;
+    vt100['w' - 0x41] = ACS_BTEE;
+    vt100['q' - 0x41] = ACS_HLINE;
+    vt100['x' - 0x41] = ACS_VLINE;
+    vt100['n' - 0x41] = ACS_PLUS;
+    vt100['o' - 0x41] = ACS_S1;
+    vt100['s' - 0x41] = ACS_S9;
+    vt100['`' - 0x41] = ACS_DIAMOND;
+    vt100['a' - 0x41] = ACS_CKBOARD;
+    vt100['f' - 0x41] = ACS_DEGREE;
+    vt100['g' - 0x41] = ACS_PLMINUS;
+    vt100['~' - 0x41] = ACS_BULLET;
+    vt100[',' - 0x41] = ACS_LARROW;
+    vt100['+' - 0x41] = ACS_RARROW;
+    vt100['.' - 0x41] = ACS_DARROW;
+    vt100['-' - 0x41] = ACS_UARROW;
+    vt100['h' - 0x41] = ACS_BOARD;
+    vt100['i' - 0x41] = ACS_LANTERN;
+    vt100['0' - 0x41] = ACS_BLOCK;
+    /* these defaults were invented for ncurses */
+    vt100['p' - 0x41] = ACS_S3;
+    vt100['r' - 0x41] = ACS_S7;
+    vt100['y' - 0x41] = ACS_LEQUAL;
+    vt100['z' - 0x41] = ACS_GEQUAL;
+    vt100['{' - 0x41] = ACS_PI;
+    vt100['|' - 0x41] = ACS_NEQUAL;
+    vt100['}' - 0x41] = ACS_STERLING;
+    is_utf8_locale();
+}
+
 static void madtty_putc(madtty_t *t, wchar_t wc)
 {
     int width = 0;
@@ -702,8 +768,10 @@ static void madtty_putc(madtty_t *t, wchar_t wc)
         t_row_t *tmp;
 
         if (t->graphmode) {
-            if (wc >= 0x41 && wc <= 0x7e && vt100_0[wc - 0x41]) {
-                wc = vt100_0[wc - 0x41];
+            if (wc >= 0x41 && wc <= 0x7e) {
+                wchar_t gc = is_utf8 ? vt100_utf8[wc - 0x41] : vt100[wc - 0x41];
+                if (gc)
+                    wc = gc;
             }
             width = 1;
         } else {
@@ -847,6 +915,8 @@ void madtty_resize(madtty_t *t, int rows, int cols)
             lines[row].attr = realloc(lines[row].attr, sizeof(uint16_t) * cols);
             if (t->cols < cols)
                 t_row_set(lines + row, t->cols, cols - t->cols, 0);
+            else
+                lines[row].dirty = true;
         }
         t->cols = cols;
     }
@@ -854,14 +924,13 @@ void madtty_resize(madtty_t *t, int rows, int cols)
     while (t->rows < rows) {
         lines[t->rows].text = (wchar_t *)calloc(sizeof(wchar_t), cols);
         lines[t->rows].attr = (uint16_t *)calloc(sizeof(uint16_t), cols);
+        t_row_set(lines + t->rows, 0, t->cols, 0);
         t->rows++;
     }
 
     t->curs_row   += lines - t->lines;
-    t->scroll_top += lines - t->lines;
-    t->scroll_bot += lines - t->lines;
-    if (t->scroll_bot > lines + t->rows)
-        t->scroll_bot = lines + t->rows;
+    t->scroll_top = lines;
+    t->scroll_bot = lines + rows;
     t->lines = lines;
     clamp_cursor_to_bounds(t);
     ioctl(t->pty, TIOCSWINSZ, &ws);
@@ -976,7 +1045,6 @@ void madtty_init_colors(void)
 {
     if (COLOR_PAIRS > 64) {
         use_default_colors();
-        assume_default_colors(-1, -1);
         has_default = 1;
 
         for (int bg = -1; bg < 8; bg++) {
@@ -985,9 +1053,16 @@ void madtty_init_colors(void)
             }
         }
     } else {
+        int use_default = use_default_colors() == OK;
         for (int bg = 0; bg < 8; bg++) {
             for (int fg = 0; fg < 8; fg++) {
-                init_pair((7 - fg) * 8 + bg, fg, bg);
+                if (use_default) {
+                    init_pair((7 - fg) * 8 + bg,
+                              fg == COLOR_WHITE ? -1 : fg,
+                              bg == COLOR_BLACK ? -1 : bg);
+                } else {
+                    init_pair((7 - fg) * 8 + bg, fg, bg);
+                }
             }
         }
     }