From: Michael D. Lowis Date: Wed, 5 Oct 2016 02:26:37 +0000 (-0400) Subject: Moved the screen scrolling logic from xedit.c to screen.c and fixed some odd behaviors X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=2da5d96b3e60e3c3103ec254ace107533ebff08f;p=projs%2Ftide.git Moved the screen scrolling logic from xedit.c to screen.c and fixed some odd behaviors --- diff --git a/.gitignore b/.gitignore index df5a986..1bd9b14 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,5 @@ *.d edit unittests +project.vim +tags diff --git a/edit.h b/edit.h index 9126b52..e4ceccb 100644 --- a/edit.h +++ b/edit.h @@ -4,7 +4,6 @@ #include #include -#include /* Definitons *****************************************************************************/ @@ -70,6 +69,7 @@ void screen_clearrow(unsigned row); void screen_setrowoff(unsigned row, unsigned off); unsigned screen_setcell(unsigned row, unsigned col, Rune r); Rune screen_getcell(unsigned row, unsigned col); +void screen_update(Buf* buf, unsigned crsr, unsigned* csrx, unsigned* csry); /* Miscellaneous Functions *****************************************************************************/ diff --git a/screen.c b/screen.c index 27f1fb9..2135b9c 100644 --- a/screen.c +++ b/screen.c @@ -4,8 +4,7 @@ static unsigned NumRows = 0; static unsigned NumCols = 0; static Row** Rows; -void screen_setsize(unsigned nrows, unsigned ncols) -{ +void screen_setsize(unsigned nrows, unsigned ncols) { if (Rows) free(Rows); Rows = calloc(nrows, sizeof(Row*)); for (unsigned i = 0; i < nrows; i++) @@ -14,24 +13,20 @@ void screen_setsize(unsigned nrows, unsigned ncols) NumCols = ncols; } -void screen_getsize(unsigned* nrows, unsigned* ncols) -{ +void screen_getsize(unsigned* nrows, unsigned* ncols) { *nrows = NumRows, *ncols = NumCols; } -void screen_clear(void) -{ +void screen_clear(void) { for (unsigned i = 0; i < NumRows; i++) screen_clearrow(i); } -Row* screen_getrow(unsigned row) -{ +Row* screen_getrow(unsigned row) { return (row < NumRows ? Rows[row] : NULL); } -void screen_clearrow(unsigned row) -{ +void screen_clearrow(unsigned row) { Row* scrrow = screen_getrow(row); if (!scrrow) return; for (unsigned i = 0; i < NumCols; i++) @@ -40,13 +35,11 @@ void screen_clearrow(unsigned row) scrrow->len = 0; } -void screen_setrowoff(unsigned row, unsigned off) -{ +void screen_setrowoff(unsigned row, unsigned off) { screen_getrow(row)->off = off; } -unsigned screen_setcell(unsigned row, unsigned col, Rune r) -{ +unsigned screen_setcell(unsigned row, unsigned col, Rune r) { if (row >= NumRows || col >= NumCols) return 0; Row* scrrow = screen_getrow(row); /* write the rune to the screen buf */ @@ -64,9 +57,75 @@ unsigned screen_setcell(unsigned row, unsigned col, Rune r) return ncols; } -Rune screen_getcell(unsigned row, unsigned col) -{ +Rune screen_getcell(unsigned row, unsigned col) { if (row >= NumRows || col >= NumCols) return 0; Row* scrrow = screen_getrow(row); return scrrow->cols[col]; } + +static unsigned linelen(Buf* buf, unsigned csr) { + unsigned eol = buf_eol(buf, csr); + unsigned bol = buf_bol(buf, csr); + return (eol - bol); +} + +static void fill_row(Buf* buf, unsigned row, unsigned pos) { + for (unsigned x = 0; x < NumCols;) { + Rune r = buf_get(buf, pos++); + x += screen_setcell(row, x, r); + if (r == '\n') break; + } +} + +static void scroll_up(Buf* buf, unsigned csr, unsigned first) { + while (csr < first) { + /* delete the last row and shift the others */ + free(Rows[NumRows - 1]); + memmove(&Rows[2], &Rows[1], sizeof(Row*) * (NumRows-2)); + Rows[1] = calloc(1, sizeof(Row) + (NumCols * sizeof(Rune))); + Rows[1]->off = buf_byline(buf, Rows[2]->off, -1); + /* fill in row content */ + fill_row(buf, 1, Rows[1]->off); + first = Rows[1]->off; + } +} + +static void scroll_dn(Buf* buf, unsigned csr, unsigned last) { + while (csr > last) { + /* delete the first row and shift the others */ + free(Rows[1]); + memmove(&Rows[1], &Rows[2], sizeof(Row*) * (NumRows-2)); + Rows[NumRows-1] = calloc(1, sizeof(Row) + (NumCols * sizeof(Rune))); + Rows[NumRows-1]->off = (Rows[NumRows-2]->off + Rows[NumRows-2]->rlen); + /* fill in row content */ + fill_row(buf, NumRows-1, Rows[NumRows-1]->off); + last = Rows[NumRows-1]->off + Rows[NumRows-1]->rlen - 1; + } +} + +static void sync_view(Buf* buf, unsigned csr) { + unsigned first = Rows[1]->off; + unsigned last = Rows[NumRows-1]->off + Rows[NumRows-1]->rlen - 1; + if (csr < first) { + scroll_up(buf, csr, first); + } else if (csr > last) { + scroll_dn(buf, csr, last); + } +} + +void screen_update(Buf* buf, unsigned csr, unsigned* csrx, unsigned* csry) { + sync_view(buf, csr); + screen_clearrow(0); + unsigned pos = Rows[1]->off; + for (unsigned y = 1; y < NumRows; y++) { + screen_clearrow(y); + screen_setrowoff(y, pos); + for (unsigned x = 0; x < NumCols;) { + if (csr == pos) + *csrx = x, *csry = y; + Rune r = buf_get(buf, pos++); + x += screen_setcell(y,x,r); + if (r == '\n') break; + } + } +} diff --git a/xedit.c b/xedit.c index c7a4ffa..d243691 100644 --- a/xedit.c +++ b/xedit.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "edit.h" @@ -25,9 +26,7 @@ struct { } X; Buf Buffer; bool InsertMode = false; -unsigned StartRow = 0; unsigned CursorPos = 0; -unsigned EndPos = 0; void die(char* m) { fprintf(stderr, "dying, %s\n", m); @@ -203,28 +202,6 @@ static void handle_event(XEvent* e) { } } -static void scroll_up(void) { - while (CursorPos < StartRow) - StartRow = buf_byline(&Buffer, StartRow, -1); -} - -static void scroll_dn(void) { - unsigned nrows, ncols; - screen_getsize(&nrows, &ncols); - while (CursorPos > EndPos) { - StartRow = buf_byline(&Buffer, StartRow, 1); - unsigned pos = StartRow; - for (unsigned y = 1; y < nrows; y++) { - for (unsigned x = 0; x < ncols; x++) { - Rune r = buf_get(&Buffer, pos++); - if (r == '\n') { break; } - if (r == '\t') { x += 4; } - } - } - EndPos = pos-1; - } -} - static void redraw(void) { int fheight = X.font->height; int fwidth = X.font->max_advance_width; @@ -234,37 +211,18 @@ static void redraw(void) { XftColor csrclr = xftcolor(CLR_BASE3); XftColor txtclr = xftcolor(CLR_BASE0); - /* Scroll up or down if needed */ - if (CursorPos < StartRow) - scroll_up(); - else if (CursorPos > EndPos) - scroll_dn(); - - /* Update the screen buffer */ - unsigned nrows, ncols, pos = StartRow; - unsigned csrx = 0, csry = 1; - screen_getsize(&nrows,&ncols); - screen_clearrow(0); - for (unsigned y = 1; y < nrows; y++) { - screen_clearrow(y); - screen_setrowoff(y, pos); - for (unsigned x = 0; x < ncols;) { - if (CursorPos == pos) - csrx = x, csry = y; - Rune r = buf_get(&Buffer, pos++); - unsigned cols = screen_setcell(y,x,r); - x += cols; - if (r == '\n') break; - } - } - EndPos = pos-1; - /* draw the background colors */ XftDrawRect(X.xft, &bkgclr, 0, 0, X.width, X.height); XftDrawRect(X.xft, >rclr, 0, 0, X.width, fheight); XftDrawRect(X.xft, >rclr, 79 * fwidth, 0, fwidth, X.height); + /* update the screen buffer and retrieve cursor coordinates */ + unsigned csrx, csry; + screen_update(&Buffer, CursorPos, &csrx, &csry); + /* flush the screen buffer */ + unsigned nrows, ncols; + screen_getsize(&nrows, &ncols); for (unsigned y = 0; y < nrows; y++) { Row* row = screen_getrow(y); XftDrawString32(X.xft, &txtclr, X.font, 0, (y+1) * fheight, (FcChar32*)(row->cols), (row->len));