aboutsummaryrefslogtreecommitdiff
path: root/ui-curses.c
diff options
context:
space:
mode:
authorMarc André Tanner <mat@brain-dump.org>2015-10-09 10:31:25 +0200
committerMarc André Tanner <mat@brain-dump.org>2015-10-14 10:33:26 +0200
commit9e391f5e3b2baaee0bf73e5273daf84be8a76ce2 (patch)
treee15479ec06d6b8c2eb83a2cd8fd1dd0125eabb00 /ui-curses.c
parentd05b8805325c2d1836c1a60280bb097340bbd03f (diff)
downloadvis-9e391f5e3b2baaee0bf73e5273daf84be8a76ce2.tar.gz
vis-9e391f5e3b2baaee0bf73e5273daf84be8a76ce2.tar.xz
ui: refactor syntax style definitions
Styles can now be specified as strings which will make them easier to specify from outside the editor. The following style attributes can be given in a comma separated list: bold italics underlined fore:color back:color where color is either a hex value of the form #aabbcc or one of the predefined colors: black red green yellow blue magenta cyan white
Diffstat (limited to 'ui-curses.c')
-rw-r--r--ui-curses.c422
1 files changed, 410 insertions, 12 deletions
diff --git a/ui-curses.c b/ui-curses.c
index 999da1b..7e74919 100644
--- a/ui-curses.c
+++ b/ui-curses.c
@@ -1,6 +1,14 @@
+/* parts of the color handling code originates from tmux/colour.c and is
+ *
+ * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
+ *
+ */
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
+#include <strings.h>
+#include <limits.h>
+#include <ctype.h>
#include <signal.h>
#include <locale.h>
#include <poll.h>
@@ -80,6 +88,7 @@ struct UiCursesWin {
int sidebar_width; /* width of the sidebar showing line numbers etc. */
UiCursesWin *next, *prev; /* pointers to neighbouring windows */
enum UiOption options; /* display settings for this window */
+ attr_t styles[UI_STYLES_MAX];
};
static volatile sig_atomic_t need_resize; /* TODO */
@@ -88,7 +97,362 @@ static void sigwinch_handler(int sig) {
need_resize = true;
}
-static unsigned int color_hash(short fg, short bg) {
+typedef struct {
+ unsigned char i;
+ unsigned char r;
+ unsigned char g;
+ unsigned char b;
+} Color;
+
+static int color_compare(const void *lhs0, const void *rhs0) {
+ const Color *lhs = lhs0, *rhs = rhs0;
+
+ if (lhs->r < rhs->r)
+ return -1;
+ if (lhs->r > rhs->r)
+ return 1;
+
+ if (lhs->g < rhs->g)
+ return -1;
+ if (lhs->g > rhs->g)
+ return 1;
+
+ if (lhs->b < rhs->b)
+ return -1;
+ if (lhs->b > rhs->b)
+ return 1;
+
+ return 0;
+}
+
+/* Work out the nearest color from the 256 color set. */
+static int color_find_rgb(unsigned char r, unsigned char g, unsigned char b)
+{
+ static const Color color_from_256[] = {
+ { 0, 0x00, 0x00, 0x00 }, { 1, 0x00, 0x00, 0x5f },
+ { 2, 0x00, 0x00, 0x87 }, { 3, 0x00, 0x00, 0xaf },
+ { 4, 0x00, 0x00, 0xd7 }, { 5, 0x00, 0x00, 0xff },
+ { 6, 0x00, 0x5f, 0x00 }, { 7, 0x00, 0x5f, 0x5f },
+ { 8, 0x00, 0x5f, 0x87 }, { 9, 0x00, 0x5f, 0xaf },
+ { 10, 0x00, 0x5f, 0xd7 }, { 11, 0x00, 0x5f, 0xff },
+ { 12, 0x00, 0x87, 0x00 }, { 13, 0x00, 0x87, 0x5f },
+ { 14, 0x00, 0x87, 0x87 }, { 15, 0x00, 0x87, 0xaf },
+ { 16, 0x00, 0x87, 0xd7 }, { 17, 0x00, 0x87, 0xff },
+ { 18, 0x00, 0xaf, 0x00 }, { 19, 0x00, 0xaf, 0x5f },
+ { 20, 0x00, 0xaf, 0x87 }, { 21, 0x00, 0xaf, 0xaf },
+ { 22, 0x00, 0xaf, 0xd7 }, { 23, 0x00, 0xaf, 0xff },
+ { 24, 0x00, 0xd7, 0x00 }, { 25, 0x00, 0xd7, 0x5f },
+ { 26, 0x00, 0xd7, 0x87 }, { 27, 0x00, 0xd7, 0xaf },
+ { 28, 0x00, 0xd7, 0xd7 }, { 29, 0x00, 0xd7, 0xff },
+ { 30, 0x00, 0xff, 0x00 }, { 31, 0x00, 0xff, 0x5f },
+ { 32, 0x00, 0xff, 0x87 }, { 33, 0x00, 0xff, 0xaf },
+ { 34, 0x00, 0xff, 0xd7 }, { 35, 0x00, 0xff, 0xff },
+ { 36, 0x5f, 0x00, 0x00 }, { 37, 0x5f, 0x00, 0x5f },
+ { 38, 0x5f, 0x00, 0x87 }, { 39, 0x5f, 0x00, 0xaf },
+ { 40, 0x5f, 0x00, 0xd7 }, { 41, 0x5f, 0x00, 0xff },
+ { 42, 0x5f, 0x5f, 0x00 }, { 43, 0x5f, 0x5f, 0x5f },
+ { 44, 0x5f, 0x5f, 0x87 }, { 45, 0x5f, 0x5f, 0xaf },
+ { 46, 0x5f, 0x5f, 0xd7 }, { 47, 0x5f, 0x5f, 0xff },
+ { 48, 0x5f, 0x87, 0x00 }, { 49, 0x5f, 0x87, 0x5f },
+ { 50, 0x5f, 0x87, 0x87 }, { 51, 0x5f, 0x87, 0xaf },
+ { 52, 0x5f, 0x87, 0xd7 }, { 53, 0x5f, 0x87, 0xff },
+ { 54, 0x5f, 0xaf, 0x00 }, { 55, 0x5f, 0xaf, 0x5f },
+ { 56, 0x5f, 0xaf, 0x87 }, { 57, 0x5f, 0xaf, 0xaf },
+ { 58, 0x5f, 0xaf, 0xd7 }, { 59, 0x5f, 0xaf, 0xff },
+ { 60, 0x5f, 0xd7, 0x00 }, { 61, 0x5f, 0xd7, 0x5f },
+ { 62, 0x5f, 0xd7, 0x87 }, { 63, 0x5f, 0xd7, 0xaf },
+ { 64, 0x5f, 0xd7, 0xd7 }, { 65, 0x5f, 0xd7, 0xff },
+ { 66, 0x5f, 0xff, 0x00 }, { 67, 0x5f, 0xff, 0x5f },
+ { 68, 0x5f, 0xff, 0x87 }, { 69, 0x5f, 0xff, 0xaf },
+ { 70, 0x5f, 0xff, 0xd7 }, { 71, 0x5f, 0xff, 0xff },
+ { 72, 0x87, 0x00, 0x00 }, { 73, 0x87, 0x00, 0x5f },
+ { 74, 0x87, 0x00, 0x87 }, { 75, 0x87, 0x00, 0xaf },
+ { 76, 0x87, 0x00, 0xd7 }, { 77, 0x87, 0x00, 0xff },
+ { 78, 0x87, 0x5f, 0x00 }, { 79, 0x87, 0x5f, 0x5f },
+ { 80, 0x87, 0x5f, 0x87 }, { 81, 0x87, 0x5f, 0xaf },
+ { 82, 0x87, 0x5f, 0xd7 }, { 83, 0x87, 0x5f, 0xff },
+ { 84, 0x87, 0x87, 0x00 }, { 85, 0x87, 0x87, 0x5f },
+ { 86, 0x87, 0x87, 0x87 }, { 87, 0x87, 0x87, 0xaf },
+ { 88, 0x87, 0x87, 0xd7 }, { 89, 0x87, 0x87, 0xff },
+ { 90, 0x87, 0xaf, 0x00 }, { 91, 0x87, 0xaf, 0x5f },
+ { 92, 0x87, 0xaf, 0x87 }, { 93, 0x87, 0xaf, 0xaf },
+ { 94, 0x87, 0xaf, 0xd7 }, { 95, 0x87, 0xaf, 0xff },
+ { 96, 0x87, 0xd7, 0x00 }, { 97, 0x87, 0xd7, 0x5f },
+ { 98, 0x87, 0xd7, 0x87 }, { 99, 0x87, 0xd7, 0xaf },
+ { 100, 0x87, 0xd7, 0xd7 }, { 101, 0x87, 0xd7, 0xff },
+ { 102, 0x87, 0xff, 0x00 }, { 103, 0x87, 0xff, 0x5f },
+ { 104, 0x87, 0xff, 0x87 }, { 105, 0x87, 0xff, 0xaf },
+ { 106, 0x87, 0xff, 0xd7 }, { 107, 0x87, 0xff, 0xff },
+ { 108, 0xaf, 0x00, 0x00 }, { 109, 0xaf, 0x00, 0x5f },
+ { 110, 0xaf, 0x00, 0x87 }, { 111, 0xaf, 0x00, 0xaf },
+ { 112, 0xaf, 0x00, 0xd7 }, { 113, 0xaf, 0x00, 0xff },
+ { 114, 0xaf, 0x5f, 0x00 }, { 115, 0xaf, 0x5f, 0x5f },
+ { 116, 0xaf, 0x5f, 0x87 }, { 117, 0xaf, 0x5f, 0xaf },
+ { 118, 0xaf, 0x5f, 0xd7 }, { 119, 0xaf, 0x5f, 0xff },
+ { 120, 0xaf, 0x87, 0x00 }, { 121, 0xaf, 0x87, 0x5f },
+ { 122, 0xaf, 0x87, 0x87 }, { 123, 0xaf, 0x87, 0xaf },
+ { 124, 0xaf, 0x87, 0xd7 }, { 125, 0xaf, 0x87, 0xff },
+ { 126, 0xaf, 0xaf, 0x00 }, { 127, 0xaf, 0xaf, 0x5f },
+ { 128, 0xaf, 0xaf, 0x87 }, { 129, 0xaf, 0xaf, 0xaf },
+ { 130, 0xaf, 0xaf, 0xd7 }, { 131, 0xaf, 0xaf, 0xff },
+ { 132, 0xaf, 0xd7, 0x00 }, { 133, 0xaf, 0xd7, 0x5f },
+ { 134, 0xaf, 0xd7, 0x87 }, { 135, 0xaf, 0xd7, 0xaf },
+ { 136, 0xaf, 0xd7, 0xd7 }, { 137, 0xaf, 0xd7, 0xff },
+ { 138, 0xaf, 0xff, 0x00 }, { 139, 0xaf, 0xff, 0x5f },
+ { 140, 0xaf, 0xff, 0x87 }, { 141, 0xaf, 0xff, 0xaf },
+ { 142, 0xaf, 0xff, 0xd7 }, { 143, 0xaf, 0xff, 0xff },
+ { 144, 0xd7, 0x00, 0x00 }, { 145, 0xd7, 0x00, 0x5f },
+ { 146, 0xd7, 0x00, 0x87 }, { 147, 0xd7, 0x00, 0xaf },
+ { 148, 0xd7, 0x00, 0xd7 }, { 149, 0xd7, 0x00, 0xff },
+ { 150, 0xd7, 0x5f, 0x00 }, { 151, 0xd7, 0x5f, 0x5f },
+ { 152, 0xd7, 0x5f, 0x87 }, { 153, 0xd7, 0x5f, 0xaf },
+ { 154, 0xd7, 0x5f, 0xd7 }, { 155, 0xd7, 0x5f, 0xff },
+ { 156, 0xd7, 0x87, 0x00 }, { 157, 0xd7, 0x87, 0x5f },
+ { 158, 0xd7, 0x87, 0x87 }, { 159, 0xd7, 0x87, 0xaf },
+ { 160, 0xd7, 0x87, 0xd7 }, { 161, 0xd7, 0x87, 0xff },
+ { 162, 0xd7, 0xaf, 0x00 }, { 163, 0xd7, 0xaf, 0x5f },
+ { 164, 0xd7, 0xaf, 0x87 }, { 165, 0xd7, 0xaf, 0xaf },
+ { 166, 0xd7, 0xaf, 0xd7 }, { 167, 0xd7, 0xaf, 0xff },
+ { 168, 0xd7, 0xd7, 0x00 }, { 169, 0xd7, 0xd7, 0x5f },
+ { 170, 0xd7, 0xd7, 0x87 }, { 171, 0xd7, 0xd7, 0xaf },
+ { 172, 0xd7, 0xd7, 0xd7 }, { 173, 0xd7, 0xd7, 0xff },
+ { 174, 0xd7, 0xff, 0x00 }, { 175, 0xd7, 0xff, 0x5f },
+ { 176, 0xd7, 0xff, 0x87 }, { 177, 0xd7, 0xff, 0xaf },
+ { 178, 0xd7, 0xff, 0xd7 }, { 179, 0xd7, 0xff, 0xff },
+ { 180, 0xff, 0x00, 0x00 }, { 181, 0xff, 0x00, 0x5f },
+ { 182, 0xff, 0x00, 0x87 }, { 183, 0xff, 0x00, 0xaf },
+ { 184, 0xff, 0x00, 0xd7 }, { 185, 0xff, 0x00, 0xff },
+ { 186, 0xff, 0x5f, 0x00 }, { 187, 0xff, 0x5f, 0x5f },
+ { 188, 0xff, 0x5f, 0x87 }, { 189, 0xff, 0x5f, 0xaf },
+ { 190, 0xff, 0x5f, 0xd7 }, { 191, 0xff, 0x5f, 0xff },
+ { 192, 0xff, 0x87, 0x00 }, { 193, 0xff, 0x87, 0x5f },
+ { 194, 0xff, 0x87, 0x87 }, { 195, 0xff, 0x87, 0xaf },
+ { 196, 0xff, 0x87, 0xd7 }, { 197, 0xff, 0x87, 0xff },
+ { 198, 0xff, 0xaf, 0x00 }, { 199, 0xff, 0xaf, 0x5f },
+ { 200, 0xff, 0xaf, 0x87 }, { 201, 0xff, 0xaf, 0xaf },
+ { 202, 0xff, 0xaf, 0xd7 }, { 203, 0xff, 0xaf, 0xff },
+ { 204, 0xff, 0xd7, 0x00 }, { 205, 0xff, 0xd7, 0x5f },
+ { 206, 0xff, 0xd7, 0x87 }, { 207, 0xff, 0xd7, 0xaf },
+ { 208, 0xff, 0xd7, 0xd7 }, { 209, 0xff, 0xd7, 0xff },
+ { 210, 0xff, 0xff, 0x00 }, { 211, 0xff, 0xff, 0x5f },
+ { 212, 0xff, 0xff, 0x87 }, { 213, 0xff, 0xff, 0xaf },
+ { 214, 0xff, 0xff, 0xd7 }, { 215, 0xff, 0xff, 0xff },
+ { 216, 0x08, 0x08, 0x08 }, { 217, 0x12, 0x12, 0x12 },
+ { 218, 0x1c, 0x1c, 0x1c }, { 219, 0x26, 0x26, 0x26 },
+ { 220, 0x30, 0x30, 0x30 }, { 221, 0x3a, 0x3a, 0x3a },
+ { 222, 0x44, 0x44, 0x44 }, { 223, 0x4e, 0x4e, 0x4e },
+ { 224, 0x58, 0x58, 0x58 }, { 225, 0x62, 0x62, 0x62 },
+ { 226, 0x6c, 0x6c, 0x6c }, { 227, 0x76, 0x76, 0x76 },
+ { 228, 0x80, 0x80, 0x80 }, { 229, 0x8a, 0x8a, 0x8a },
+ { 230, 0x94, 0x94, 0x94 }, { 231, 0x9e, 0x9e, 0x9e },
+ { 232, 0xa8, 0xa8, 0xa8 }, { 233, 0xb2, 0xb2, 0xb2 },
+ { 234, 0xbc, 0xbc, 0xbc }, { 235, 0xc6, 0xc6, 0xc6 },
+ { 236, 0xd0, 0xd0, 0xd0 }, { 237, 0xda, 0xda, 0xda },
+ { 238, 0xe4, 0xe4, 0xe4 }, { 239, 0xee, 0xee, 0xee },
+ };
+
+ static const Color color_to_256[] = {
+ { 0, 0x00, 0x00, 0x00 }, { 1, 0x00, 0x00, 0x5f },
+ { 2, 0x00, 0x00, 0x87 }, { 3, 0x00, 0x00, 0xaf },
+ { 4, 0x00, 0x00, 0xd7 }, { 5, 0x00, 0x00, 0xff },
+ { 6, 0x00, 0x5f, 0x00 }, { 7, 0x00, 0x5f, 0x5f },
+ { 8, 0x00, 0x5f, 0x87 }, { 9, 0x00, 0x5f, 0xaf },
+ { 10, 0x00, 0x5f, 0xd7 }, { 11, 0x00, 0x5f, 0xff },
+ { 12, 0x00, 0x87, 0x00 }, { 13, 0x00, 0x87, 0x5f },
+ { 14, 0x00, 0x87, 0x87 }, { 15, 0x00, 0x87, 0xaf },
+ { 16, 0x00, 0x87, 0xd7 }, { 17, 0x00, 0x87, 0xff },
+ { 18, 0x00, 0xaf, 0x00 }, { 19, 0x00, 0xaf, 0x5f },
+ { 20, 0x00, 0xaf, 0x87 }, { 21, 0x00, 0xaf, 0xaf },
+ { 22, 0x00, 0xaf, 0xd7 }, { 23, 0x00, 0xaf, 0xff },
+ { 24, 0x00, 0xd7, 0x00 }, { 25, 0x00, 0xd7, 0x5f },
+ { 26, 0x00, 0xd7, 0x87 }, { 27, 0x00, 0xd7, 0xaf },
+ { 28, 0x00, 0xd7, 0xd7 }, { 29, 0x00, 0xd7, 0xff },
+ { 30, 0x00, 0xff, 0x00 }, { 31, 0x00, 0xff, 0x5f },
+ { 32, 0x00, 0xff, 0x87 }, { 33, 0x00, 0xff, 0xaf },
+ { 34, 0x00, 0xff, 0xd7 }, { 35, 0x00, 0xff, 0xff },
+ { 216, 0x08, 0x08, 0x08 }, { 217, 0x12, 0x12, 0x12 },
+ { 218, 0x1c, 0x1c, 0x1c }, { 219, 0x26, 0x26, 0x26 },
+ { 220, 0x30, 0x30, 0x30 }, { 221, 0x3a, 0x3a, 0x3a },
+ { 222, 0x44, 0x44, 0x44 }, { 223, 0x4e, 0x4e, 0x4e },
+ { 224, 0x58, 0x58, 0x58 }, { 36, 0x5f, 0x00, 0x00 },
+ { 37, 0x5f, 0x00, 0x5f }, { 38, 0x5f, 0x00, 0x87 },
+ { 39, 0x5f, 0x00, 0xaf }, { 40, 0x5f, 0x00, 0xd7 },
+ { 41, 0x5f, 0x00, 0xff }, { 42, 0x5f, 0x5f, 0x00 },
+ { 43, 0x5f, 0x5f, 0x5f }, { 44, 0x5f, 0x5f, 0x87 },
+ { 45, 0x5f, 0x5f, 0xaf }, { 46, 0x5f, 0x5f, 0xd7 },
+ { 47, 0x5f, 0x5f, 0xff }, { 48, 0x5f, 0x87, 0x00 },
+ { 49, 0x5f, 0x87, 0x5f }, { 50, 0x5f, 0x87, 0x87 },
+ { 51, 0x5f, 0x87, 0xaf }, { 52, 0x5f, 0x87, 0xd7 },
+ { 53, 0x5f, 0x87, 0xff }, { 54, 0x5f, 0xaf, 0x00 },
+ { 55, 0x5f, 0xaf, 0x5f }, { 56, 0x5f, 0xaf, 0x87 },
+ { 57, 0x5f, 0xaf, 0xaf }, { 58, 0x5f, 0xaf, 0xd7 },
+ { 59, 0x5f, 0xaf, 0xff }, { 60, 0x5f, 0xd7, 0x00 },
+ { 61, 0x5f, 0xd7, 0x5f }, { 62, 0x5f, 0xd7, 0x87 },
+ { 63, 0x5f, 0xd7, 0xaf }, { 64, 0x5f, 0xd7, 0xd7 },
+ { 65, 0x5f, 0xd7, 0xff }, { 66, 0x5f, 0xff, 0x00 },
+ { 67, 0x5f, 0xff, 0x5f }, { 68, 0x5f, 0xff, 0x87 },
+ { 69, 0x5f, 0xff, 0xaf }, { 70, 0x5f, 0xff, 0xd7 },
+ { 71, 0x5f, 0xff, 0xff }, { 225, 0x62, 0x62, 0x62 },
+ { 226, 0x6c, 0x6c, 0x6c }, { 227, 0x76, 0x76, 0x76 },
+ { 228, 0x80, 0x80, 0x80 }, { 72, 0x87, 0x00, 0x00 },
+ { 73, 0x87, 0x00, 0x5f }, { 74, 0x87, 0x00, 0x87 },
+ { 75, 0x87, 0x00, 0xaf }, { 76, 0x87, 0x00, 0xd7 },
+ { 77, 0x87, 0x00, 0xff }, { 78, 0x87, 0x5f, 0x00 },
+ { 79, 0x87, 0x5f, 0x5f }, { 80, 0x87, 0x5f, 0x87 },
+ { 81, 0x87, 0x5f, 0xaf }, { 82, 0x87, 0x5f, 0xd7 },
+ { 83, 0x87, 0x5f, 0xff }, { 84, 0x87, 0x87, 0x00 },
+ { 85, 0x87, 0x87, 0x5f }, { 86, 0x87, 0x87, 0x87 },
+ { 87, 0x87, 0x87, 0xaf }, { 88, 0x87, 0x87, 0xd7 },
+ { 89, 0x87, 0x87, 0xff }, { 90, 0x87, 0xaf, 0x00 },
+ { 91, 0x87, 0xaf, 0x5f }, { 92, 0x87, 0xaf, 0x87 },
+ { 93, 0x87, 0xaf, 0xaf }, { 94, 0x87, 0xaf, 0xd7 },
+ { 95, 0x87, 0xaf, 0xff }, { 96, 0x87, 0xd7, 0x00 },
+ { 97, 0x87, 0xd7, 0x5f }, { 98, 0x87, 0xd7, 0x87 },
+ { 99, 0x87, 0xd7, 0xaf }, { 100, 0x87, 0xd7, 0xd7 },
+ { 101, 0x87, 0xd7, 0xff }, { 102, 0x87, 0xff, 0x00 },
+ { 103, 0x87, 0xff, 0x5f }, { 104, 0x87, 0xff, 0x87 },
+ { 105, 0x87, 0xff, 0xaf }, { 106, 0x87, 0xff, 0xd7 },
+ { 107, 0x87, 0xff, 0xff }, { 229, 0x8a, 0x8a, 0x8a },
+ { 230, 0x94, 0x94, 0x94 }, { 231, 0x9e, 0x9e, 0x9e },
+ { 232, 0xa8, 0xa8, 0xa8 }, { 108, 0xaf, 0x00, 0x00 },
+ { 109, 0xaf, 0x00, 0x5f }, { 110, 0xaf, 0x00, 0x87 },
+ { 111, 0xaf, 0x00, 0xaf }, { 112, 0xaf, 0x00, 0xd7 },
+ { 113, 0xaf, 0x00, 0xff }, { 114, 0xaf, 0x5f, 0x00 },
+ { 115, 0xaf, 0x5f, 0x5f }, { 116, 0xaf, 0x5f, 0x87 },
+ { 117, 0xaf, 0x5f, 0xaf }, { 118, 0xaf, 0x5f, 0xd7 },
+ { 119, 0xaf, 0x5f, 0xff }, { 120, 0xaf, 0x87, 0x00 },
+ { 121, 0xaf, 0x87, 0x5f }, { 122, 0xaf, 0x87, 0x87 },
+ { 123, 0xaf, 0x87, 0xaf }, { 124, 0xaf, 0x87, 0xd7 },
+ { 125, 0xaf, 0x87, 0xff }, { 126, 0xaf, 0xaf, 0x00 },
+ { 127, 0xaf, 0xaf, 0x5f }, { 128, 0xaf, 0xaf, 0x87 },
+ { 129, 0xaf, 0xaf, 0xaf }, { 130, 0xaf, 0xaf, 0xd7 },
+ { 131, 0xaf, 0xaf, 0xff }, { 132, 0xaf, 0xd7, 0x00 },
+ { 133, 0xaf, 0xd7, 0x5f }, { 134, 0xaf, 0xd7, 0x87 },
+ { 135, 0xaf, 0xd7, 0xaf }, { 136, 0xaf, 0xd7, 0xd7 },
+ { 137, 0xaf, 0xd7, 0xff }, { 138, 0xaf, 0xff, 0x00 },
+ { 139, 0xaf, 0xff, 0x5f }, { 140, 0xaf, 0xff, 0x87 },
+ { 141, 0xaf, 0xff, 0xaf }, { 142, 0xaf, 0xff, 0xd7 },
+ { 143, 0xaf, 0xff, 0xff }, { 233, 0xb2, 0xb2, 0xb2 },
+ { 234, 0xbc, 0xbc, 0xbc }, { 235, 0xc6, 0xc6, 0xc6 },
+ { 236, 0xd0, 0xd0, 0xd0 }, { 144, 0xd7, 0x00, 0x00 },
+ { 145, 0xd7, 0x00, 0x5f }, { 146, 0xd7, 0x00, 0x87 },
+ { 147, 0xd7, 0x00, 0xaf }, { 148, 0xd7, 0x00, 0xd7 },
+ { 149, 0xd7, 0x00, 0xff }, { 150, 0xd7, 0x5f, 0x00 },
+ { 151, 0xd7, 0x5f, 0x5f }, { 152, 0xd7, 0x5f, 0x87 },
+ { 153, 0xd7, 0x5f, 0xaf }, { 154, 0xd7, 0x5f, 0xd7 },
+ { 155, 0xd7, 0x5f, 0xff }, { 156, 0xd7, 0x87, 0x00 },
+ { 157, 0xd7, 0x87, 0x5f }, { 158, 0xd7, 0x87, 0x87 },
+ { 159, 0xd7, 0x87, 0xaf }, { 160, 0xd7, 0x87, 0xd7 },
+ { 161, 0xd7, 0x87, 0xff }, { 162, 0xd7, 0xaf, 0x00 },
+ { 163, 0xd7, 0xaf, 0x5f }, { 164, 0xd7, 0xaf, 0x87 },
+ { 165, 0xd7, 0xaf, 0xaf }, { 166, 0xd7, 0xaf, 0xd7 },
+ { 167, 0xd7, 0xaf, 0xff }, { 168, 0xd7, 0xd7, 0x00 },
+ { 169, 0xd7, 0xd7, 0x5f }, { 170, 0xd7, 0xd7, 0x87 },
+ { 171, 0xd7, 0xd7, 0xaf }, { 172, 0xd7, 0xd7, 0xd7 },
+ { 173, 0xd7, 0xd7, 0xff }, { 174, 0xd7, 0xff, 0x00 },
+ { 175, 0xd7, 0xff, 0x5f }, { 176, 0xd7, 0xff, 0x87 },
+ { 177, 0xd7, 0xff, 0xaf }, { 178, 0xd7, 0xff, 0xd7 },
+ { 179, 0xd7, 0xff, 0xff }, { 237, 0xda, 0xda, 0xda },
+ { 238, 0xe4, 0xe4, 0xe4 }, { 239, 0xee, 0xee, 0xee },
+ { 180, 0xff, 0x00, 0x00 }, { 181, 0xff, 0x00, 0x5f },
+ { 182, 0xff, 0x00, 0x87 }, { 183, 0xff, 0x00, 0xaf },
+ { 184, 0xff, 0x00, 0xd7 }, { 185, 0xff, 0x00, 0xff },
+ { 186, 0xff, 0x5f, 0x00 }, { 187, 0xff, 0x5f, 0x5f },
+ { 188, 0xff, 0x5f, 0x87 }, { 189, 0xff, 0x5f, 0xaf },
+ { 190, 0xff, 0x5f, 0xd7 }, { 191, 0xff, 0x5f, 0xff },
+ { 192, 0xff, 0x87, 0x00 }, { 193, 0xff, 0x87, 0x5f },
+ { 194, 0xff, 0x87, 0x87 }, { 195, 0xff, 0x87, 0xaf },
+ { 196, 0xff, 0x87, 0xd7 }, { 197, 0xff, 0x87, 0xff },
+ { 198, 0xff, 0xaf, 0x00 }, { 199, 0xff, 0xaf, 0x5f },
+ { 200, 0xff, 0xaf, 0x87 }, { 201, 0xff, 0xaf, 0xaf },
+ { 202, 0xff, 0xaf, 0xd7 }, { 203, 0xff, 0xaf, 0xff },
+ { 204, 0xff, 0xd7, 0x00 }, { 205, 0xff, 0xd7, 0x5f },
+ { 206, 0xff, 0xd7, 0x87 }, { 207, 0xff, 0xd7, 0xaf },
+ { 208, 0xff, 0xd7, 0xd7 }, { 209, 0xff, 0xd7, 0xff },
+ { 210, 0xff, 0xff, 0x00 }, { 211, 0xff, 0xff, 0x5f },
+ { 212, 0xff, 0xff, 0x87 }, { 213, 0xff, 0xff, 0xaf },
+ { 214, 0xff, 0xff, 0xd7 }, { 215, 0xff, 0xff, 0xff },
+ };
+
+ static const unsigned char color_256_to_16[256] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 0, 4, 4, 4, 12, 12, 2, 6, 4, 4, 12, 12, 2, 2, 6, 4,
+ 12, 12, 2, 2, 2, 6, 12, 12, 10, 10, 10, 10, 14, 12, 10, 10,
+ 10, 10, 10, 14, 1, 5, 4, 4, 12, 12, 3, 8, 4, 4, 12, 12,
+ 2, 2, 6, 4, 12, 12, 2, 2, 2, 6, 12, 12, 10, 10, 10, 10,
+ 14, 12, 10, 10, 10, 10, 10, 14, 1, 1, 5, 4, 12, 12, 1, 1,
+ 5, 4, 12, 12, 3, 3, 8, 4, 12, 12, 2, 2, 2, 6, 12, 12,
+ 10, 10, 10, 10, 14, 12, 10, 10, 10, 10, 10, 14, 1, 1, 1, 5,
+ 12, 12, 1, 1, 1, 5, 12, 12, 1, 1, 1, 5, 12, 12, 3, 3,
+ 3, 7, 12, 12, 10, 10, 10, 10, 14, 12, 10, 10, 10, 10, 10, 14,
+ 9, 9, 9, 9, 13, 12, 9, 9, 9, 9, 13, 12, 9, 9, 9, 9,
+ 13, 12, 9, 9, 9, 9, 13, 12, 11, 11, 11, 11, 7, 12, 10, 10,
+ 10, 10, 10, 14, 9, 9, 9, 9, 9, 13, 9, 9, 9, 9, 9, 13,
+ 9, 9, 9, 9, 9, 13, 9, 9, 9, 9, 9, 13, 9, 9, 9, 9,
+ 9, 13, 11, 11, 11, 11, 11, 15, 0, 0, 0, 0, 0, 0, 8, 8,
+ 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 15, 15, 15, 15, 15, 15
+ };
+
+ Color rgb = { .r = r, .g = g, .b = b };
+ const Color *found = bsearch(&rgb, color_to_256, LENGTH(color_to_256),
+ sizeof color_to_256[0], color_compare);
+
+ if (!found) {
+ unsigned lowest = UINT_MAX;
+ found = color_from_256;
+ for (int i = 0; i < 240; i++) {
+ int dr = (int)color_from_256[i].r - r;
+ int dg = (int)color_from_256[i].g - g;
+ int db = (int)color_from_256[i].b - b;
+
+ unsigned int distance = dr * dr + dg * dg + db * db;
+ if (distance < lowest) {
+ lowest = distance;
+ found = &color_from_256[i];
+ }
+ }
+ }
+
+ if (COLORS <= 16)
+ return color_256_to_16[found->i + 16];
+ return found->i + 16;
+}
+
+/* Convert color from string. */
+static int color_fromstring(const char *s)
+{
+ if (*s == '#' && strlen(s) == 7) {
+ const char *cp;
+ unsigned char r, g, b;
+ for (cp = s + 1; isxdigit((unsigned char)*cp); cp++);
+ if (*cp != '\0')
+ return -1;
+ int n = sscanf(s + 1, "%2hhx%2hhx%2hhx", &r, &g, &b);
+ if (n != 3)
+ return -1;
+ return color_find_rgb(r, g, b);
+ }
+
+ if (strcasecmp(s, "black") == 0)
+ return 0;
+ if (strcasecmp(s, "red") == 0)
+ return 1;
+ if (strcasecmp(s, "green") == 0)
+ return 2;
+ if (strcasecmp(s, "yellow") == 0)
+ return 3;
+ if (strcasecmp(s, "blue") == 0)
+ return 4;
+ if (strcasecmp(s, "magenta") == 0)
+ return 5;
+ if (strcasecmp(s, "cyan") == 0)
+ return 6;
+ if (strcasecmp(s, "white") == 0)
+ return 7;
+ return -1;
+}
+
+static unsigned int color_pair_hash(short fg, short bg) {
if (fg == -1)
fg = COLORS;
if (bg == -1)
@@ -96,7 +460,7 @@ static unsigned int color_hash(short fg, short bg) {
return fg * (COLORS + 2) + bg;
}
-static short color_get(short fg, short bg) {
+static short color_pair_get(short fg, short bg) {
static bool has_default_colors;
static short *color2palette, default_fg, default_bg;
static short color_pairs_max, color_pair_current;
@@ -128,13 +492,13 @@ static short color_get(short fg, short bg) {
if (!color2palette || (fg == -1 && bg == -1))
return 0;
- unsigned int index = color_hash(fg, bg);
+ unsigned int index = color_pair_hash(fg, bg);
if (color2palette[index] == 0) {
short oldfg, oldbg;
if (++color_pair_current >= color_pairs_max)
color_pair_current = 1;
pair_content(color_pair_current, &oldfg, &oldbg);
- unsigned int old_index = color_hash(oldfg, oldbg);
+ unsigned int old_index = color_pair_hash(oldfg, oldbg);
if (init_pair(color_pair_current, fg, bg) == OK) {
color2palette[old_index] = 0;
color2palette[index] = color_pair_current;
@@ -144,6 +508,45 @@ static short color_get(short fg, short bg) {
return color2palette[index];
}
+static bool ui_window_syntax_style(UiWin *w, int id, const char *style) {
+ UiCursesWin *win = (UiCursesWin*)w;
+ if (id >= UI_STYLES_MAX)
+ return false;
+ short fg = -1, bg = -1;
+ attr_t attr = A_NORMAL;
+ char *style_copy = strdup(style), *option = style_copy, *next, *p;
+ while (option) {
+ if ((next = strchr(option, ',')))
+ *next++ = '\0';
+ if ((p = strchr(option, ':')))
+ *p++ = '\0';
+ if (!strcasecmp(option, "bold")) {
+ attr |= A_BOLD;
+ } else if (!strcasecmp(option, "notbold")) {
+ attr &= ~A_BOLD;
+#ifdef A_ITALIC
+ } else if (!strcasecmp(option, "italics")) {
+ attr |= A_ITALIC;
+ } else if (!strcasecmp(option, "notitalics")) {
+ attr &= ~A_ITALIC;
+#endif
+ } else if (!strcasecmp(option, "underlined")) {
+ attr |= A_UNDERLINE;
+ } else if (!strcasecmp(option, "notunderlined")) {
+ attr &= ~A_UNDERLINE;
+ } else if (!strcasecmp(option, "fore")) {
+ fg = color_fromstring(p);
+ } else if (!strcasecmp(option, "back")) {
+ bg = color_fromstring(p);
+ }
+ option = next;
+ }
+ attr |= COLOR_PAIR(color_pair_get(fg, bg));
+ win->styles[id] = attr;
+ free(style_copy);
+ return true;
+}
+
static void ui_window_resize(UiCursesWin *win, int width, int height) {
win->width = width;
win->height = height;
@@ -365,7 +768,7 @@ static void ui_window_draw_text(UiWin *w, const Line *line) {
int width = view_width_get(win->view);
for (const Line *l = line; l; l = l->next) {
for (int x = 0; x < width; x++) {
- int attr = l->cells[x].attr;
+ int attr = win->styles[l->cells[x].attr];
if (l->cells[x].cursor && (win->ui->selwin == win || win->ui->prompt_win == win))
attr = A_NORMAL | A_REVERSE;
if (l->cells[x].selected)
@@ -427,6 +830,7 @@ static UiWin *ui_window_new(Ui *ui, View *view, File *file) {
.draw_text = ui_window_draw_text,
.options = ui_window_options,
.reload = ui_window_reload,
+ .syntax_style = ui_window_syntax_style,
};
if (!(win->win = newwin(0, 0, 0, 0)) || !(win->winstatus = newwin(1, 0, 0, 0))) {
@@ -574,7 +978,7 @@ static void ui_terminal_restore(Ui *ui) {
termkey_start(uic->termkey);
}
-Ui *ui_curses_new(Color *colors) {
+Ui *ui_curses_new(void) {
UiCurses *uic = calloc(1, sizeof(UiCurses));
Ui *ui = (Ui*)uic;
@@ -628,12 +1032,6 @@ Ui *ui_curses_new(Color *colors) {
.terminal_restore = ui_terminal_restore,
};
- for (Color *color = colors; color && color->fg; color++) {
- if (color->attr == 0)
- color->attr = A_NORMAL;
- color->attr |= COLOR_PAIR(color_get(color->fg, color->bg));
- }
-
struct sigaction sa;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);