aboutsummaryrefslogtreecommitdiff
path: root/view.c
diff options
context:
space:
mode:
authorMarc André Tanner <mat@brain-dump.org>2017-03-14 16:53:53 +0100
committerMarc André Tanner <mat@brain-dump.org>2017-03-14 19:04:21 +0100
commit9bcf2667e7e239873597b7ec2172206a9af18071 (patch)
tree7e9ccb42fa665ba01be65b93fc995fa76719aaf7 /view.c
parentbed289a96e1ed17e4b9fa4f9e22227fcf13cc818 (diff)
downloadvis-9bcf2667e7e239873597b7ec2172206a9af18071.tar.gz
vis-9bcf2667e7e239873597b7ec2172206a9af18071.tar.xz
Restructure display code
Use pull instead of push based model for display code. Previously view.c was calling into the ui frontend code, with the new scheme this switches around: the necessary data is fetched by the ui as necessary. The UI independent display code is moved out of view.c/ui-curses.c into vis.c. The cell styles are now directly embedded into the Cell struct. New UI styles are introduced for: - status bar (focused / non-focused) - info message - window separator - EOF symbol You will have to update your color themes. The terminal output code is further abstracted into a generic ui-terminal.c part which keeps track of the whole in-memory cell matrix and #includes ui-terminal-curses.c for the actual terminal output. This architecture currently assumes that there are no overlapping windows. It will also allow non-curses based terminal user interfaces.
Diffstat (limited to 'view.c')
-rw-r--r--view.c147
1 files changed, 41 insertions, 106 deletions
diff --git a/view.c b/view.c
index d6a3f3f..ea6b70c 100644
--- a/view.c
+++ b/view.c
@@ -12,7 +12,6 @@
typedef struct {
char *symbol;
- int style;
} SyntaxSymbol;
enum {
@@ -20,7 +19,6 @@ enum {
SYNTAX_SYMBOL_TAB,
SYNTAX_SYMBOL_TAB_FILL,
SYNTAX_SYMBOL_EOL,
- SYNTAX_SYMBOL_EOF,
SYNTAX_SYMBOL_LAST,
};
@@ -70,6 +68,7 @@ struct Cursor { /* cursor position */
struct View {
Text *text; /* underlying text management */
UiWin *ui;
+ Cell cell_blank; /* used for empty/blank cells */
int width, height; /* size of display area */
size_t start, end; /* currently displayed area [start, end] in bytes from the start of the file */
size_t start_last; /* previously used start of visible area, used to update the mark */
@@ -93,7 +92,6 @@ struct View {
bool need_update; /* whether view has been redrawn */
bool large_file; /* optimize for displaying large files */
int colorcolumn;
- ViewEvent *events;
};
static const SyntaxSymbol symbols_none[] = {
@@ -101,7 +99,6 @@ static const SyntaxSymbol symbols_none[] = {
[SYNTAX_SYMBOL_TAB] = { " " },
[SYNTAX_SYMBOL_TAB_FILL] = { " " },
[SYNTAX_SYMBOL_EOL] = { " " },
- [SYNTAX_SYMBOL_EOF] = { "~" },
};
static const SyntaxSymbol symbols_default[] = {
@@ -109,15 +106,12 @@ static const SyntaxSymbol symbols_default[] = {
[SYNTAX_SYMBOL_TAB] = { "›" /* Single Right-Pointing Angle Quotation Mark U+203A */ },
[SYNTAX_SYMBOL_TAB_FILL] = { " " },
[SYNTAX_SYMBOL_EOL] = { "↵" /* Downwards Arrow with Corner Leftwards U+21B5 */ },
- [SYNTAX_SYMBOL_EOF] = { "~" },
};
static Cell cell_unused;
-static Cell cell_blank = { .data = " " };
static void view_clear(View *view);
static bool view_addch(View *view, Cell *cell);
-static bool view_coord_get(View *view, size_t pos, Line **retline, int *retrow, int *retcol);
static void view_cursors_free(Cursor *c);
/* set/move current cursor position to a given (line, column) pair */
static size_t cursor_set(Cursor *cursor, Line *line, int col);
@@ -178,6 +172,7 @@ static bool view_addch(View *view, Cell *cell) {
int width;
size_t lineno = view->line->lineno;
unsigned char ch = (unsigned char)cell->data[0];
+ cell->style = view->cell_blank.style;
switch (ch) {
case '\t':
@@ -195,7 +190,6 @@ static bool view_addch(View *view, Cell *cell) {
cell->len = w == 0 ? 1 : 0;
int t = w == 0 ? SYNTAX_SYMBOL_TAB : SYNTAX_SYMBOL_TAB_FILL;
strncpy(cell->data, view->symbols[t]->symbol, sizeof(cell->data)-1);
- cell->style = view->symbols[t]->style;
view->line->cells[view->col] = *cell;
view->line->len += cell->len;
view->line->width += cell->width;
@@ -214,13 +208,12 @@ static bool view_addch(View *view, Cell *cell) {
}
strncpy(cell->data, view->symbols[SYNTAX_SYMBOL_EOL]->symbol, sizeof(cell->data)-1);
- cell->style = view->symbols[SYNTAX_SYMBOL_EOL]->style;
view->line->cells[view->col] = *cell;
view->line->len += cell->len;
view->line->width += cell->width;
for (int i = view->col + 1; i < view->width; i++)
- view->line->cells[i] = cell_blank;
+ view->line->cells[i] = view->cell_blank;
view->line = view->line->next;
if (view->line)
@@ -240,13 +233,12 @@ static bool view_addch(View *view, Cell *cell) {
if (ch == ' ') {
strncpy(cell->data, view->symbols[SYNTAX_SYMBOL_SPACE]->symbol, sizeof(cell->data)-1);
- cell->style = view->symbols[SYNTAX_SYMBOL_SPACE]->style;
}
if (view->col + cell->width > view->width) {
for (int i = view->col; i < view->width; i++)
- view->line->cells[i] = cell_blank;
+ view->line->cells[i] = view->cell_blank;
view->line = view->line->next;
view->col = 0;
}
@@ -287,7 +279,7 @@ static void cursor_to(Cursor *c, size_t pos) {
view_draw(c->view);
}
-static bool view_coord_get(View *view, size_t pos, Line **retline, int *retrow, int *retcol) {
+bool view_coord_get(View *view, size_t pos, Line **retline, int *retrow, int *retcol) {
int row = 0, col = 0;
size_t cur = view->start;
Line *line = view->topline;
@@ -350,7 +342,7 @@ void view_draw(View *view) {
/* start from known multibyte state */
mbstate_t mbstate = { 0 };
- Cell cell = { 0 }, prev_cell = { 0 };
+ Cell cell = { .data = "", .len = 0, .width = 0, }, prev_cell = cell;
while (rem > 0) {
@@ -412,10 +404,11 @@ void view_draw(View *view) {
if (prev_cell.len && view_addch(view, &prev_cell))
pos += prev_cell.len;
- /* set end of vieviewg region */
+ /* set end of viewing region */
view->end = pos;
if (view->line) {
- if (view->line->len == 0 && view->end == text_size(view->text) && view->line->prev)
+ bool eof = view->end == text_size(view->text);
+ if (view->line->len == 0 && eof && view->line->prev)
view->lastline = view->line->prev;
else
view->lastline = view->line;
@@ -426,23 +419,14 @@ void view_draw(View *view) {
/* clear remaining of line, important to show cursor at end of file */
if (view->line) {
for (int x = view->col; x < view->width; x++)
- view->line->cells[x] = cell_blank;
+ view->line->cells[x] = view->cell_blank;
}
/* resync position of cursors within visible area */
for (Cursor *c = view->cursors; c; c = c->next) {
size_t pos = view_cursors_pos(c);
- if (view_coord_get(view, pos, &c->line, &c->row, &c->col)) {
- c->line->cells[c->col].cursor = true;
- c->line->cells[c->col].cursor_primary = (c == view->cursor);
- if (view->ui && !c->sel) {
- Line *line_match; int col_match;
- size_t pos_match = text_bracket_match_symbol(view->text, pos, "(){}[]\"'`");
- if (pos != pos_match && view_coord_get(view, pos_match, &line_match, NULL, &col_match)) {
- line_match->cells[col_match].selected = true;
- }
- }
- } else if (c == view->cursor) {
+ if (!view_coord_get(view, pos, &c->line, &c->row, &c->col) &&
+ c == view->cursor) {
c->line = view->topline;
c->row = 0;
c->col = 0;
@@ -452,77 +436,19 @@ void view_draw(View *view) {
view->need_update = true;
}
-void view_update(View *view) {
- if (!view->need_update)
- return;
-
- if (view->events->draw)
- view->events->draw(view->events->data);
-
- if (view->colorcolumn > 0) {
- size_t lineno = 0;
- int line_cols = 0; /* Track the number of columns we've passed on each line */
- bool line_cc_set = false; /* Has the colorcolumn attribute been set for this line yet */
-
- for (Line *l = view->topline; l; l = l->next) {
- if (l->lineno != lineno) {
- line_cols = 0;
- line_cc_set = false;
- }
-
- if (!line_cc_set) {
- line_cols += view->width;
-
- /* This screen line contains the cell we want to highlight */
- if (line_cols >= view->colorcolumn) {
- l->cells[(view->colorcolumn - 1) % view->width].style = UI_STYLE_COLOR_COLUMN;
- line_cc_set = true;
- }
- }
-
- lineno = l->lineno;
- }
- }
+void view_dirty(View *view) {
+ view->need_update = true;
+}
+bool view_update(View *view) {
+ if (!view->need_update)
+ return false;
for (Line *l = view->lastline->next; l; l = l->next) {
- strncpy(l->cells[0].data, view->symbols[SYNTAX_SYMBOL_EOF]->symbol, sizeof(l->cells[0].data));
- l->cells[0].style = view->symbols[SYNTAX_SYMBOL_EOF]->style;
- for (int x = 1; x < view->width; x++)
- l->cells[x] = cell_blank;
- l->width = 1;
- l->len = 0;
- }
-
- for (Selection *s = view->selections; s; s = s->next) {
- Filerange sel = view_selections_get(s);
- if (text_range_valid(&sel)) {
- Line *start_line; int start_col;
- Line *end_line; int end_col;
- view_coord_get(view, sel.start, &start_line, NULL, &start_col);
- view_coord_get(view, sel.end, &end_line, NULL, &end_col);
- if (start_line || end_line) {
- if (!start_line) {
- start_line = view->topline;
- start_col = 0;
- }
- if (!end_line) {
- end_line = view->lastline;
- end_col = end_line->width;
- }
- for (Line *l = start_line; l != end_line->next; l = l->next) {
- int col = (l == start_line) ? start_col : 0;
- int end = (l == end_line) ? end_col : l->width;
- while (col < end) {
- l->cells[col++].selected = true;
- }
- }
- }
- }
+ for (int x = 0; x < view->width; x++)
+ l->cells[x] = view->cell_blank;
}
-
- if (view->ui)
- view->ui->draw(view->ui);
view->need_update = false;
+ return true;
}
bool view_resize(View *view, int width, int height) {
@@ -544,8 +470,6 @@ bool view_resize(View *view, int width, int height) {
view->height = height;
memset(view->lines, 0, view->lines_size);
view_draw(view);
- if (view->ui)
- view_update(view);
return true;
}
@@ -574,7 +498,7 @@ void view_reload(View *view, Text *text) {
view_cursor_to(view, 0);
}
-View *view_new(Text *text, ViewEvent *events) {
+View *view_new(Text *text) {
if (!text)
return NULL;
View *view = calloc(1, sizeof(View));
@@ -585,6 +509,11 @@ View *view_new(Text *text, ViewEvent *events) {
return NULL;
}
+ view->cell_blank = (Cell) {
+ .width = 0,
+ .len = 0,
+ .data = " ",
+ };
view->text = text;
view->tabwidth = 8;
view_options_set(view, 0);
@@ -595,13 +524,13 @@ View *view_new(Text *text, ViewEvent *events) {
}
view_cursor_to(view, 0);
- view->events = events;
return view;
}
void view_ui(View *view, UiWin* ui) {
view->ui = ui;
+ view->cell_blank.style = view->ui->style_get(view->ui, UI_STYLE_DEFAULT);
}
static size_t cursor_set(Cursor *cursor, Line *line, int col) {
@@ -886,12 +815,16 @@ size_t view_cursor_get(View *view) {
return view_cursors_pos(view->cursor);
}
-const Line *view_lines_get(View *view) {
+Line *view_lines_first(View *view) {
return view->topline;
}
-const Line *view_line_get(View *view) {
- return view->cursor->line;
+Line *view_lines_last(View *view) {
+ return view->lastline;
+}
+
+Line *view_cursors_line_get(Cursor *c) {
+ return c->line;
}
void view_scroll_to(View *view, size_t pos) {
@@ -904,7 +837,6 @@ void view_options_set(View *view, enum UiOption options) {
[SYNTAX_SYMBOL_TAB] = UI_OPTION_SYMBOL_TAB,
[SYNTAX_SYMBOL_TAB_FILL] = UI_OPTION_SYMBOL_TAB_FILL,
[SYNTAX_SYMBOL_EOL] = UI_OPTION_SYMBOL_EOL,
- [SYNTAX_SYMBOL_EOF] = UI_OPTION_SYMBOL_EOF,
};
for (int i = 0; i < LENGTH(mapping); i++) {
@@ -917,8 +849,10 @@ void view_options_set(View *view, enum UiOption options) {
view->large_file = (options & UI_OPTION_LARGE_FILE);
- if (view->ui)
+ if (view->ui) {
view->ui->options_set(view->ui, options);
+ view->cell_blank.style = view->ui->style_get(view->ui, UI_STYLE_DEFAULT);
+ }
}
enum UiOption view_options_get(View *view) {
@@ -1428,13 +1362,14 @@ Text *view_text(View *view) {
}
bool view_style_define(View *view, enum UiStyle id, const char *style) {
- return view->ui->syntax_style(view->ui, id, style);
+ return view->ui->style_define(view->ui, id, style);
}
-void view_style(View *view, enum UiStyle style, size_t start, size_t end) {
+void view_style(View *view, enum UiStyle style_id, size_t start, size_t end) {
if (end < view->start || start > view->end)
return;
+ CellStyle style = view->ui->style_get(view->ui, style_id);
size_t pos = view->start;
Line *line = view->topline;