diff options
Diffstat (limited to 'ui-curses.c')
| -rw-r--r-- | ui-curses.c | 78 |
1 files changed, 56 insertions, 22 deletions
diff --git a/ui-curses.c b/ui-curses.c index 7c1f5b3..d00dbf3 100644 --- a/ui-curses.c +++ b/ui-curses.c @@ -59,6 +59,11 @@ int ESCDELAY; } while (0); #endif +typedef struct { + attr_t attr; + short fg, bg; +} CellStyle; + typedef struct UiCursesWin UiCursesWin; typedef struct { @@ -88,7 +93,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]; + CellStyle styles[UI_STYLE_MAX]; }; static volatile sig_atomic_t need_resize; /* TODO */ @@ -454,7 +459,7 @@ static int color_fromstring(const char *s) return -1; } -static unsigned int color_pair_hash(short fg, short bg) { +static inline unsigned int color_pair_hash(short fg, short bg) { if (fg == -1) fg = COLORS; if (bg == -1) @@ -510,41 +515,47 @@ static short color_pair_get(short fg, short bg) { return color2palette[index]; } +static inline attr_t style_to_attr(CellStyle *style) { + return style->attr | COLOR_PAIR(color_pair_get(style->fg, style->bg)); +} + static bool ui_window_syntax_style(UiWin *w, int id, const char *style) { UiCursesWin *win = (UiCursesWin*)w; - if (id >= UI_STYLES_MAX) + if (id >= UI_STYLE_MAX) return false; - short fg = -1, bg = -1; - attr_t attr = A_NORMAL; + if (!style) + return true; + CellStyle cell_style = win->styles[UI_STYLE_DEFAULT]; 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; + if (!strcasecmp(option, "reverse")) { + cell_style.attr |= A_REVERSE; + } else if (!strcasecmp(option, "bold")) { + cell_style.attr |= A_BOLD; } else if (!strcasecmp(option, "notbold")) { - attr &= ~A_BOLD; + cell_style.attr &= ~A_BOLD; #ifdef A_ITALIC } else if (!strcasecmp(option, "italics")) { - attr |= A_ITALIC; + cell_style.attr |= A_ITALIC; } else if (!strcasecmp(option, "notitalics")) { - attr &= ~A_ITALIC; + cell_style.attr &= ~A_ITALIC; #endif } else if (!strcasecmp(option, "underlined")) { - attr |= A_UNDERLINE; + cell_style.attr |= A_UNDERLINE; } else if (!strcasecmp(option, "notunderlined")) { - attr &= ~A_UNDERLINE; + cell_style.attr &= ~A_UNDERLINE; } else if (!strcasecmp(option, "fore")) { - fg = color_fromstring(p); + cell_style.fg = color_fromstring(p); } else if (!strcasecmp(option, "back")) { - bg = color_fromstring(p); + cell_style.bg = color_fromstring(p); } option = next; } - attr |= COLOR_PAIR(color_pair_get(fg, bg)); - win->styles[id] = attr; + win->styles[id] = cell_style; free(style_copy); return true; } @@ -585,6 +596,8 @@ static bool ui_window_draw_sidebar(UiCursesWin *win) { size_t prev_lineno = 0; size_t cursor_lineno = view_cursor_getpos(win->view).line; werase(win->winside); + wbkgd(win->winside, style_to_attr(&win->styles[UI_STYLE_DEFAULT])); + wattrset(win->winside, style_to_attr(&win->styles[UI_STYLE_LINENUMBER])); for (const Line *l = line; l; l = l->next, i++) { if (l->lineno && l->lineno != prev_lineno) { if (win->options & UI_OPTION_LINE_NUMBERS_ABSOLUTE) { @@ -632,15 +645,25 @@ static void ui_window_draw(UiWin *w) { UiCursesWin *win = (UiCursesWin*)w; if (!ui_window_draw_sidebar(win)) return; + wbkgd(win->win, style_to_attr(&win->styles[UI_STYLE_DEFAULT])); wmove(win->win, 0, 0); int width = view_width_get(win->view); + CellStyle *prev_style = NULL; + short selection_bg = win->styles[UI_STYLE_SELECTION].bg; + attr_t attr; for (const Line *l = view_lines_get(win->view); l; l = l->next) { for (int x = 0; x < width; x++) { - 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) - attr |= A_REVERSE; + CellStyle *style = &win->styles[l->cells[x].attr]; + if (l->cells[x].cursor && (win->ui->selwin == win || win->ui->prompt_win == win)) { + attr = style_to_attr(&win->styles[UI_STYLE_CURSOR]); + prev_style = NULL; + } else if (l->cells[x].selected) { + attr = style->attr | COLOR_PAIR(color_pair_get(style->fg, selection_bg)); + prev_style = NULL; + } else if (style != prev_style) { + attr = style_to_attr(style); + prev_style = style; + } wattrset(win->win, attr); waddstr(win->win, l->cells[x].data); } @@ -841,6 +864,18 @@ static UiWin *ui_window_new(Ui *ui, View *view, File *file) { return NULL; } + CellStyle style = (CellStyle) { + .fg = -1, .bg = -1, .attr = A_NORMAL, + }; + + for (int i = 0; i < UI_STYLE_MAX; i++) { + win->styles[i] = style; + } + + style.attr |= A_REVERSE; + win->styles[UI_STYLE_CURSOR] = style; + win->styles[UI_STYLE_SELECTION] = style; + win->ui = uic; win->view = view; win->file = file; @@ -1071,4 +1106,3 @@ void ui_curses_free(Ui *ui) { termkey_destroy(uic->termkey); free(uic); } - |
