static void ui_curses_blit(UiTerm *tui) { int w = tui->width, h = tui->height; Cell *cell = tui->cells; for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { attrset(style_to_attr(&cell->style)); mvaddstr(y, x, cell->data); cell++; } } wnoutrefresh(stdscr); doupdate(); }
static bool ui_window_draw_sidebar(UiCursesWin *win) { if (!win->winside) return true; const Line *line = view_lines_get(win->view); int sidebar_width = snprintf(NULL, 0, "%zd", line->lineno + win->height - 2) + 1; if (win->sidebar_width != sidebar_width) { win->sidebar_width = sidebar_width; ui_window_resize(win, win->width, win->height); ui_window_move(win, win->x, win->y); return false; } else { int i = 0; size_t prev_lineno = 0; const Line *cursor_line = view_line_get(win->view); size_t cursor_lineno = cursor_line->lineno; 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) { mvwprintw(win->winside, i, 0, "%*u", sidebar_width-1, l->lineno); } else if (win->options & UI_OPTION_LINE_NUMBERS_RELATIVE) { size_t rel = (win->options & UI_OPTION_LARGE_FILE) ? 0 : l->lineno; if (l->lineno > cursor_lineno) rel = l->lineno - cursor_lineno; else if (l->lineno < cursor_lineno) rel = cursor_lineno - l->lineno; mvwprintw(win->winside, i, 0, "%*u", sidebar_width-1, rel); } } prev_lineno = l->lineno; } mvwvline(win->winside, 0, sidebar_width-1, ACS_VLINE, win->height-1); return true; } }
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; size_t cursor_lineno = -1; if (win->options & UI_OPTION_CURSOR_LINE && win->ui->selwin == win) { Cursor *cursor = view_cursors(win->view); Filerange selection = view_cursors_selection_get(cursor); if (!view_cursors_next(cursor) && !text_range_valid(&selection)) cursor_lineno = view_cursor_getpos(win->view).line; } short selection_bg = win->styles[UI_STYLE_SELECTION].bg; short cursor_line_bg = win->styles[UI_STYLE_CURSOR_LINE].bg; bool multiple_cursors = view_cursors_multiple(win->view); attr_t attr = A_NORMAL; for (const Line *l = view_lines_get(win->view); l; l = l->next) { bool cursor_line = l->lineno == cursor_lineno; for (int x = 0; x < width; x++) { enum UiStyles style_id = l->cells[x].style; if (style_id == 0) style_id = UI_STYLE_DEFAULT; CellStyle *style = &win->styles[style_id]; if (l->cells[x].cursor && win->ui->selwin == win) { if (multiple_cursors && l->cells[x].cursor_primary) attr = style_to_attr(&win->styles[UI_STYLE_CURSOR_PRIMARY]); else attr = style_to_attr(&win->styles[UI_STYLE_CURSOR]); prev_style = NULL; } else if (l->cells[x].selected) { if (style->fg == selection_bg) attr |= A_REVERSE; else attr = style->attr | COLOR_PAIR(color_pair_get(style->fg, selection_bg)); prev_style = NULL; } else if (cursor_line) { attr = style->attr | COLOR_PAIR(color_pair_get(style->fg, cursor_line_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); } /* try to fixup display issues, in theory we should always output a full line */ int x, y; getyx(win->win, y, x); (void)y; wattrset(win->win, A_NORMAL); for (; 0 < x && x < width; x++) waddstr(win->win, " "); } wclrtobot(win->win); if (win->winstatus) ui_window_draw_status(w); }