From: Michael D. Lowis Date: Fri, 21 Oct 2016 02:07:00 +0000 (-0400) Subject: implemented color logic for screen buffer and adjusted colors for the status bar X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=07b974f72938d304f986f7a4a3cc5fcc055bd1e8;p=projs%2Ftide.git implemented color logic for screen buffer and adjusted colors for the status bar --- diff --git a/edit.h b/edit.h index b6d013c..3d136a7 100644 --- a/edit.h +++ b/edit.h @@ -184,9 +184,8 @@ void handle_mouse(MouseEvent* mevnt); /* Screen management functions *****************************************************************************/ typedef struct { - Rune rune; - uint8_t fg; - uint8_t bg; + uint32_t attr; /* attributes applied to this cell */ + Rune rune; /* rune value for the cell */ } UGlyph; typedef struct { @@ -202,7 +201,7 @@ void screen_setsize(Buf* buf, unsigned nrows, unsigned ncols); void screen_getsize(unsigned* nrows, unsigned* ncols); Row* screen_getrow(unsigned row); void screen_clearrow(unsigned row); -unsigned screen_setcell(unsigned row, unsigned col, Rune r); +unsigned screen_setcell(unsigned row, unsigned col, uint32_t attr, Rune r); UGlyph* screen_getglyph(unsigned row, unsigned col, unsigned* scrwidth); /* Color Scheme Handling diff --git a/mouse.c b/mouse.c index ae3073c..f6c602d 100644 --- a/mouse.c +++ b/mouse.c @@ -5,7 +5,8 @@ void unused(MouseEvent* mevnt) { } void move_cursor(MouseEvent* mevnt) { - CursorPos = screen_getoff(&Buffer, CursorPos, mevnt->y, mevnt->x); + if (mevnt->y == 0) return; + CursorPos = screen_getoff(&Buffer, CursorPos, mevnt->y-1, mevnt->x); TargetCol = buf_getcol(&Buffer, CursorPos); } diff --git a/screen.c b/screen.c index 7fbe46d..cb084cb 100644 --- a/screen.c +++ b/screen.c @@ -4,17 +4,25 @@ static unsigned NumRows = 0; static unsigned NumCols = 0; static Row** Rows; +#define ATTR_NORMAL (CLR_BASE03 << 8 | CLR_BASE0) +#define ATTR_SELECTED (CLR_BASE0 << 8 | CLR_BASE03) + +static unsigned fill_row(Buf* buf, unsigned row, unsigned pos) { + screen_getrow(row)->off = pos; + screen_clearrow(row); + for (unsigned x = 0; x < NumCols;) { + uint32_t attr = (DotBeg <= pos && pos < DotEnd ? ATTR_SELECTED : ATTR_NORMAL); + Rune r = buf_get(buf, pos++); + x += screen_setcell(row, x, attr, r); + if (buf_iseol(buf, pos-1)) break; + } + return pos; +} + static void screen_reflow(Buf* buf) { unsigned pos = Rows[0]->off; - for (unsigned y = 0; y < NumRows; y++) { - screen_clearrow(y); - screen_getrow(y)->off = pos; - for (unsigned x = 0; x < NumCols;) { - Rune r = buf_get(buf, pos++); - x += screen_setcell(y,x,r); - if (buf_iseol(buf, pos-1)) break; - } - } + for (unsigned y = 0; y < NumRows; y++) + pos = fill_row(buf, y, pos); } void screen_setsize(Buf* buf, unsigned nrows, unsigned ncols) { @@ -72,19 +80,22 @@ void screen_clearrow(unsigned row) { scrrow->len = 0; } -unsigned screen_setcell(unsigned row, unsigned col, Rune r) { +unsigned screen_setcell(unsigned row, unsigned col, uint32_t attr, Rune r) { if (row >= NumRows || col >= NumCols) return 0; Row* scrrow = screen_getrow(row); int ncols = runewidth(col, r); /* write the rune to the screen buf */ + scrrow->cols[col].attr = attr; if (r == '\t' || r == '\n' || r == RUNE_CRLF) scrrow->cols[col].rune = ' '; else scrrow->cols[col].rune = r; /* Update lengths */ scrrow->rlen += 1; - for (int i = 1; i < ncols; i++) + for (int i = 1; i < ncols; i++) { + scrrow->cols[col].attr = attr; scrrow->cols[col+i].rune = '\0'; + } if ((col + ncols) > scrrow->len) scrrow->len = col + ncols; return ncols; @@ -100,15 +111,6 @@ UGlyph* screen_getglyph(unsigned row, unsigned col, unsigned* scrwidth) { return glyph; } -static void fill_row(Buf* buf, unsigned row, unsigned pos) { - screen_clearrow(row); - for (unsigned x = 0; x < NumCols;) { - Rune r = buf_get(buf, pos++); - x += screen_setcell(row, x, r); - if (buf_iseol(buf, pos-1)) break; - } -} - static unsigned prev_screen_line(Buf* buf, unsigned bol, unsigned off) { unsigned pos = bol; while (true) { @@ -163,8 +165,7 @@ static void sync_view(Buf* buf, unsigned csr) { void screen_update(Buf* buf, unsigned csr, unsigned* csrx, unsigned* csry) { /* scroll the view and reflow the screen lines */ sync_view(buf, csr); - if (buf->insert_mode) - screen_reflow(buf); + screen_reflow(buf); /* find the cursor on the new screen */ for (unsigned y = 0; y < NumRows; y++) { unsigned start = Rows[y]->off; diff --git a/tests/tests.c b/tests/tests.c index 0c037bc..fd409e3 100644 --- a/tests/tests.c +++ b/tests/tests.c @@ -5,6 +5,8 @@ Buf Buffer; unsigned CursorPos; unsigned TargetCol; +unsigned DotBeg; +unsigned DotEnd; enum ColorScheme ColorBase; int main(int argc, char** argv) { diff --git a/xedit.c b/xedit.c index d45d6de..96f965b 100644 --- a/xedit.c +++ b/xedit.c @@ -132,7 +132,7 @@ void font_find(XftGlyphFontSpec* spec, Rune rune) { } int font_makespecs(XftGlyphFontSpec* specs, const UGlyph* glyphs, int len, int x, int y) { - int winx = x * Fonts.base.width, winy = y * Fonts.base.height; + int winx = x * Fonts.base.width, winy = y * Fonts.base.ascent; int numspecs = 0; for (int i = 0, xp = winx, yp = winy + Fonts.base.ascent; i < len;) { font_find(&(specs[numspecs]), glyphs[i].rune); @@ -277,7 +277,7 @@ static MouseEvent* getmouse(XEvent* e) { event.type = MouseMove; event.button = MOUSE_NONE; event.x = e->xmotion.x / Fonts.base.width; - event.y = e->xmotion.y / (Fonts.base.ascent + Fonts.base.descent); + event.y = e->xmotion.y / Fonts.base.height; } else { event.type = (e->type = ButtonPress ? MouseDown : MouseUp); /* set the button id */ @@ -290,7 +290,7 @@ static MouseEvent* getmouse(XEvent* e) { default: event.button = MOUSE_NONE; break; } event.x = e->xbutton.x / Fonts.base.width; - event.y = e->xbutton.y / (Fonts.base.ascent + Fonts.base.descent); + event.y = e->xbutton.y / Fonts.base.height; } return &event; } @@ -319,13 +319,46 @@ static void handle_event(XEvent* e) { void draw_runes(unsigned x, unsigned y, XftColor* fg, XftColor* bg, UGlyph* glyphs, size_t rlen) { (void)bg; XftGlyphFontSpec specs[rlen]; - size_t nspecs = font_makespecs(specs, glyphs, rlen, x, y); - XftDrawGlyphFontSpec(X.xft, fg, specs, nspecs); + while (rlen) { + size_t nspecs = font_makespecs(specs, glyphs, rlen, x, y); + XftDrawGlyphFontSpec(X.xft, fg, specs, nspecs); + rlen -= nspecs; + } +} + +void draw_glyphs(unsigned x, unsigned y, UGlyph* glyphs, size_t rlen, size_t ncols) { + XftGlyphFontSpec specs[rlen]; + int i = 0; + while (rlen) { + int numspecs = 0; + int attr = glyphs[i].attr; + while (i < ncols && glyphs[i].attr == attr) { + font_find(&(specs[numspecs]), glyphs[i].rune); + specs[numspecs].x = x; + specs[numspecs].y = y - Fonts.base.descent; + x += Fonts.base.width; + numspecs++; + i++; + /* skip over null chars which mark multi column runes */ + for (; i < ncols && !glyphs[i].rune; i++) + x += Fonts.base.width; + } + /* Draw the glyphs with the proper colors */ + uint8_t bg = attr >> 8; + uint8_t fg = attr & 0xFF; + if (bg != CLR_BASE03) + XftDrawRect(X.xft, clr(bg), specs[0].x, y-Fonts.base.height, x-specs[0].x, Fonts.base.height); + XftDrawGlyphFontSpec(X.xft, clr(fg), specs, numspecs); + rlen -= numspecs; + } +} + +void draw_row(unsigned x, unsigned y, Row* row) { + draw_glyphs(x, y, row->cols, row->rlen, row->len); } static void draw_status(XftColor* fg, unsigned ncols) { - UGlyph glyphs[ncols]; - UGlyph* status = glyphs; + UGlyph glyphs[ncols], *status = glyphs; (status++)->rune = (Buffer.charset == BINARY ? 'B' : 'U'); (status++)->rune = (Buffer.crlf ? 'C' : 'N'); (status++)->rune = (Buffer.modified ? '*' : ' '); @@ -336,11 +369,25 @@ static void draw_status(XftColor* fg, unsigned ncols) { draw_runes(0, 0, fg, NULL, glyphs, status - glyphs); } +static void draw_cursor(unsigned csrx, unsigned csry) { + unsigned rwidth; + UGlyph* csrrune = screen_getglyph(csry, csrx, &rwidth); + csrrune->attr = (CLR_BASE3 << 8 | CLR_BASE03); + if (Buffer.insert_mode) { + XftDrawRect(X.xft, CSRCLR, csrx * Fonts.base.width, (csry+1) * Fonts.base.height, 1, Fonts.base.height); + } else { + XftDrawRect(X.xft, CSRCLR, csrx * Fonts.base.width, (csry+1) * Fonts.base.height, rwidth * Fonts.base.width, Fonts.base.height); + draw_glyphs(csrx * Fonts.base.width, (csry+2) * Fonts.base.height, csrrune, 1, rwidth); + } +} + static void redraw(void) { + uint32_t start = getmillis(); /* draw the background colors */ XftDrawRect(X.xft, BKGCLR, 0, 0, X.width, X.height); XftDrawRect(X.xft, GTRCLR, 79 * Fonts.base.width, 0, Fonts.base.width, X.height); - XftDrawRect(X.xft, TXTCLR, 0, 0, X.width, Fonts.base.height); + XftDrawRect(X.xft, clr(CLR_BASE02), 0, 0, X.width, Fonts.base.height); + XftDrawRect(X.xft, clr(CLR_BASE01), 0, Fonts.base.height, X.width, 1); /* update the screen buffer and retrieve cursor coordinates */ unsigned csrx, csry; @@ -349,25 +396,19 @@ static void redraw(void) { /* flush the screen buffer */ unsigned nrows, ncols; screen_getsize(&nrows, &ncols); - draw_status(BKGCLR, ncols); + draw_status(clr(CLR_BASE2), ncols); for (unsigned y = 0; y < nrows; y++) { Row* row = screen_getrow(y); - draw_runes(0, y+1, TXTCLR, NULL, row->cols, row->len); + draw_glyphs(0, (y+2) * Fonts.base.height, row->cols, row->rlen, row->len); } /* Place cursor on screen */ - unsigned rwidth; - UGlyph* csrrune = screen_getglyph(csry, csrx, &rwidth); - if (Buffer.insert_mode) { - XftDrawRect(X.xft, CSRCLR, csrx * Fonts.base.width, (csry+1) * Fonts.base.height, 1, Fonts.base.height); - } else { - XftDrawRect(X.xft, CSRCLR, csrx * Fonts.base.width, (csry+1) * Fonts.base.height, rwidth * Fonts.base.width, Fonts.base.height); - draw_runes(csrx, csry+1, BKGCLR, NULL, csrrune, 1); - } + draw_cursor(csrx, csry); /* flush pixels to the screen */ XCopyArea(X.display, X.pixmap, X.window, X.gc, 0, 0, X.width, X.height, 0, 0); XFlush(X.display); + printf("refresh: %u\n", getmillis() - start); } int main(int argc, char** argv) {