aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc André Tanner <mat@brain-dump.org>2015-11-23 11:12:12 +0100
committerMarc André Tanner <mat@brain-dump.org>2015-11-23 14:18:27 +0100
commit0613073092b9f4172b5b87e9c7f243ff6d61f723 (patch)
tree3ba8304237facd50a08ceac45eebe28903c9022e
parent51e92f0c8e7b50c684287bea1a55edbde128053f (diff)
downloadvis-0613073092b9f4172b5b87e9c7f243ff6d61f723.tar.gz
vis-0613073092b9f4172b5b87e9c7f243ff6d61f723.tar.xz
view: fix cell placement of combining characters
They now belong to the cell holding the corresponding regular (i.e. non-combining) character. This also means that at least in theory a cell could hold arbitrary amounts of data, in practice it is limited to 16 bytes.
-rw-r--r--view.c24
-rw-r--r--view.h5
2 files changed, 20 insertions, 9 deletions
diff --git a/view.c b/view.c
index bd46e85..a340293 100644
--- a/view.c
+++ b/view.c
@@ -123,6 +123,7 @@ void view_tabwidth_set(View *view, int tabwidth) {
/* reset internal view data structures (cell matrix, line offsets etc.) */
static void view_clear(View *view) {
+ memset(view->lines, 0, view->lines_size);
if (view->start != view->start_last) {
view->start_mark = text_mark_set(view->text, view->start);
} else {
@@ -130,19 +131,17 @@ static void view_clear(View *view) {
if (start != EPOS)
view->start = start;
}
+
view->start_last = view->start;
view->topline = view->lines;
view->topline->lineno = text_lineno_by_pos(view->text, view->start);
view->lastline = view->topline;
- /* reset all other lines */
size_t line_size = sizeof(Line) + view->width*sizeof(Cell);
size_t end = view->height * line_size;
Line *prev = NULL;
for (size_t i = 0; i < end; i += line_size) {
Line *line = (Line*)(((char*)view->lines) + i);
- line->width = 0;
- line->len = 0;
line->prev = prev;
if (prev)
prev->next = line;
@@ -365,12 +364,12 @@ void view_draw(View *view) {
/* start from known multibyte state */
mbstate_t mbstate = { 0 };
+ Cell cell = { 0 }, prev_cell = { 0 };
+
while (rem > 0) {
/* current 'parsed' character' */
wchar_t wchar;
- Cell cell;
- memset(&cell, 0, sizeof cell);
size_t len = mbrtowc(&wchar, cur, rem, &mbstate);
if (len == (size_t)-1 && errno == EILSEQ) {
@@ -407,14 +406,25 @@ void view_draw(View *view) {
cell = (Cell){ .data = "\n", .len = 2, .width = 1, .istab = false };
}
- if (!view_addch(view, &cell))
- break;
+ if (cell.width == 0 && prev_cell.len + cell.len < sizeof(cell.len)) {
+ prev_cell.len += cell.len;
+ strcat(prev_cell.data, cell.data);
+ } else {
+ if (prev_cell.len && !view_addch(view, &prev_cell))
+ break;
+ prev_cell = cell;
+ }
rem -= cell.len;
cur += cell.len;
pos += cell.len;
+
+ memset(&cell, 0, sizeof cell);
}
+ if (prev_cell.len && view_addch(view, &prev_cell))
+ pos += prev_cell.len;
+
/* set end of vieviewg region */
view->end = pos;
view->lastline = view->line ? view->line : view->bottomline;
diff --git a/view.h b/view.h
index d43deb4..d650ec6 100644
--- a/view.h
+++ b/view.h
@@ -23,8 +23,9 @@ typedef struct {
character which use more than 1 column to display, their lenght
is stored in the leftmost cell wheras all following cells
occupied by the same character have a length of 0. */
- char data[8]; /* utf8 encoded character displayed in this cell might not be the
- the same as in the underlying text, for example tabs get expanded */
+ char data[16]; /* utf8 encoded character displayed in this cell (might be more than
+ one Unicode codepoint. might also not be the same as in the
+ underlying text, for example tabs get expanded */
unsigned int attr;
bool istab;
bool selected; /* whether this cell is part of a selected region */