From: Michael D. Lowis Date: Mon, 14 Nov 2016 01:53:41 +0000 (-0500) Subject: added view module in order to support multiple buffer views X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=b02e5a2c03fbbe7b1f3253e44438f949a229ce3f;p=projs%2Ftide.git added view module in order to support multiple buffer views --- diff --git a/Makefile b/Makefile index ae1e2b4..34d6c54 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ LIBEDIT_OBJS = \ libedit/utf8.o \ libedit/utils.o \ libedit/exec.o \ - libedit/clip.o + libedit/view.o LIBX_OBJS = \ libx/x11.o diff --git a/inc/edit.h b/inc/edit.h index 2de0519..21f9373 100644 --- a/inc/edit.h +++ b/inc/edit.h @@ -50,6 +50,7 @@ typedef struct buf { typedef struct { size_t beg; size_t end; + size_t col; } Sel; void buf_load(Buf* buf, char* path); @@ -136,20 +137,29 @@ typedef struct { } Row; typedef struct { - size_t nrows; /* number of rows in the view */ - size_t ncols; /* number of columns in the view */ - Row** rows; /* array of row data structures */ - Buf buffer; /* the buffer used to populate the view */ + //size_t posx; + //size_t posy; + //size_t height; + //size_t width; + size_t nrows; /* number of rows in the view */ + size_t ncols; /* number of columns in the view */ + Row** rows; /* array of row data structures */ + Buf buffer; /* the buffer used to populate the view */ + Sel selection; /* range of currently selected text */ } View; -void view_update(View* view, unsigned crsr, unsigned* csrx, unsigned* csry); -size_t view_getoff(View* view, unsigned pos, unsigned row, unsigned col); -void view_setsize(View* view, unsigned nrows, unsigned ncols); -void view_getsize(View* view, unsigned* nrows, unsigned* ncols); -Row* view_getrow(View* view, unsigned row); -void view_clearrow(View* view, unsigned row); -size_t view_setcell(View* view, unsigned row, unsigned col, uint32_t attr, Rune r); -UGlyph* view_getglyph(View* view, unsigned row, unsigned col, unsigned* scrwidth); +void view_init(View* view, char* file); +void view_resize(View* view, size_t nrows, size_t ncols); +void view_update(View* view, size_t* csrx, size_t* csry); +Row* view_getrow(View* view, size_t row); +void view_byrune(View* view, int move); +void view_byline(View* view, int move); + +//size_t view_getoff(View* view, size_t pos, size_t row, size_t col); +//void view_getsize(View* view, size_t* nrows, size_t* ncols); +//void view_clearrow(View* view, size_t row); +//size_t view_setcell(View* view, size_t row, size_t col, uint32_t attr, Rune r); +//UGlyph* view_getglyph(View* view, size_t row, size_t col, size_t* scrwidth); void screen_update(Buf* buf, unsigned crsr, unsigned* csrx, unsigned* csry); unsigned screen_getoff(Buf* buf, unsigned pos, unsigned row, unsigned col); @@ -175,11 +185,6 @@ void terminate(Process* proc, int sig); char* cmdread(char** cmd); void cmdwrite(char** cmd, char* text); -/* Clipboard Access - *****************************************************************************/ -void clipcopy(char* text); -char* clippaste(void); - /* Color Scheme Handling *****************************************************************************/ /* color indexes for the colorscheme */ @@ -248,3 +253,4 @@ enum { 0xff2aa198, \ 0xff859900 \ } +#define DEFAULT_TAGS "Quit Save" diff --git a/inc/X.h b/inc/x11.h similarity index 80% rename from inc/X.h rename to inc/x11.h index 8a49295..6926efe 100644 --- a/inc/X.h +++ b/inc/x11.h @@ -1,5 +1,3 @@ -#include - typedef enum { MOUSE_ACT_UP, MOUSE_ACT_DOWN, @@ -22,32 +20,20 @@ typedef struct { uint32_t palette[16]; } XConfig; -#ifndef MAXFONTS -#define MAXFONTS 16 -#endif - -typedef struct { - struct { - int height; - int width; - int ascent; - int descent; - XftFont* match; - FcFontSet* set; - FcPattern* pattern; - } base; - struct { - XftFont* font; - uint32_t unicodep; - } cache[MAXFONTS]; - int ncached; -} XFont; +typedef void* XFont; typedef struct { uint32_t attr; /* attributes applied to this cell */ uint32_t rune; /* rune value for the cell */ } XGlyph; +typedef struct { + void* font; + uint32_t glyph; + short x; + short y; +} XGlyphSpec; + /* key definitions */ enum Keys { /* Define some runes in the private use area of unicode to represent @@ -126,11 +112,14 @@ void x11_window(char* name, int width, int height); void x11_dialog(char* name, int height, int width); void x11_show(void); void x11_loop(void); +XFont x11_font_load(char* name); +size_t x11_font_height(XFont fnt); +size_t x11_font_width(XFont fnt); +size_t x11_font_descent(XFont fnt); void x11_draw_rect(int color, int x, int y, int width, int height); -void x11_draw_glyphs(int fg, int bg, XftGlyphFontSpec* glyphs, size_t nglyphs); void x11_getsize(int* width, int* height); void x11_warp_mouse(int x, int y); -void x11_font_load(XFont* font, char* name); -void x11_font_getglyph(XFont* font, XftGlyphFontSpec* spec, uint32_t rune); -size_t x11_font_getglyphs(XftGlyphFontSpec* specs, const XGlyph* glyphs, int len, XFont* font, int x, int y); -void x11_draw_utf8(XFont* font, int fg, int bg, int x, int y, char* str); +void x11_draw_utf8(XFont font, int fg, int bg, int x, int y, char* str); +void x11_font_getglyph(XFont font, XGlyphSpec* spec, uint32_t rune); +size_t x11_font_getglyphs(XGlyphSpec* specs, const XGlyph* glyphs, int len, XFont font, int x, int y); +void x11_draw_glyphs(int fg, int bg, XGlyphSpec* glyphs, size_t nglyphs); diff --git a/libedit/clip.c b/libedit/clip.c deleted file mode 100644 index f1b0644..0000000 --- a/libedit/clip.c +++ /dev/null @@ -1,20 +0,0 @@ -#include -#include -#include -#include - -#ifdef __MACH__ -char* CopyCmd[] = { "pbcopy", NULL }; -char* PasteCmd[] = { "pbpaste", NULL }; -#else -char* CopyCmd[] = { "xsel", "-bi", NULL }; -char* PasteCmd[] = { "xsel", "-bo", NULL }; -#endif - -void clipcopy(char* text) { - cmdwrite(CopyCmd, text); -} - -char* clippaste(void) { - return cmdread(PasteCmd); -} diff --git a/libedit/view.c b/libedit/view.c new file mode 100644 index 0000000..570ced1 --- /dev/null +++ b/libedit/view.c @@ -0,0 +1,160 @@ +#include +#include +#include + +#define ATTR_NORMAL (CLR_BASE03 << 8 | CLR_BASE0) +#define ATTR_SELECTED (CLR_BASE0 << 8 | CLR_BASE03) + +static void clearrow(View* view, size_t row) { + Row* scrrow = view_getrow(view, row); + if (!scrrow) return; + for (size_t i = 0; i < view->ncols; i++) + scrrow->cols[i].rune = (Rune)' '; + scrrow->rlen = 0; + scrrow->len = 0; +} + +static size_t setcell(View* view, size_t row, size_t col, uint32_t attr, Rune r) { + if (row >= view->nrows || col >= view->ncols) return 0; + Row* scrrow = view_getrow(view, 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++) { + scrrow->cols[col].attr = attr; + scrrow->cols[col+i].rune = '\0'; + } + if ((col + ncols) > scrrow->len) + scrrow->len = col + ncols; + return ncols; +} + +static bool selected(View* view, size_t pos) { + Sel sel = view->selection; + if (sel.end < sel.beg) { + size_t temp = sel.beg; + sel.beg = sel.end; + sel.end = temp; + } + return (sel.beg <= pos && pos < sel.end); +} + +static size_t fill_row(View* view, unsigned row, size_t pos) { + view_getrow(view, row)->off = pos; + clearrow(view, row); + for (size_t x = 0; x < view->ncols;) { + uint32_t attr = (selected(view, pos) ? ATTR_SELECTED : ATTR_NORMAL); + Rune r = buf_get(&(view->buffer), pos++); + x += setcell(view, row, x, attr, r); + if (buf_iseol(&(view->buffer), pos-1)) break; + } + return pos; +} + +static void reflow(View* view) { + size_t pos = view->rows[0]->off; + for (size_t y = 0; y < view->nrows; y++) + pos = fill_row(view, y, pos); +} + +void view_init(View* view, char* file) { + memset(view, 0, sizeof(View)); + buf_init(&(view->buffer)); + if (file) + buf_load(&(view->buffer), file); +} + +void view_resize(View* view, size_t nrows, size_t ncols) { + if (view->nrows == nrows && view->ncols == ncols) return; + /* free the old row data */ + if (view->nrows) { + for (unsigned i = 0; i < view->nrows; i++) + free(view->rows[i]); + free(view->rows); + } + /* create the new row data */ + view->rows = calloc(nrows, sizeof(Row*)); + for (unsigned i = 0; i < nrows; i++) + view->rows[i] = calloc(1, sizeof(Row) + (ncols * sizeof(UGlyph))); + /* update dimensions */ + view->nrows = nrows; + view->ncols = ncols; + /* populate the screen buffer */ + reflow(view); +} + +void view_update(View* view, size_t* csrx, size_t* csry) { + size_t csr = view->selection.beg; + /* scroll the view and reflow the screen lines */ + //sync_view(buf, csr); + reflow(view); + /* find the cursor on the new screen */ + for (size_t y = 0; y < view->nrows; y++) { + size_t start = view->rows[y]->off; + size_t end = view->rows[y]->off + view->rows[y]->rlen - 1; + if (start <= csr && csr <= end) { + size_t pos = start; + for (size_t x = 0; x < view->ncols;) { + if (pos == csr) { + *csry = y, *csrx = x; + break; + } + x += runewidth(x, buf_get(&(view->buffer),pos++)); + } + break; + } + } +} + +Row* view_getrow(View* view, size_t row) { + return (row < view->nrows ? view->rows[row] : NULL); +} + +void view_byrune(View* view, int move) { + Sel sel = view->selection; + sel.beg = sel.end = buf_byrune(&(view->buffer), sel.end, move); + sel.col = buf_getcol(&(view->buffer), sel.end); + view->selection = sel; +} + +void view_byline(View* view, int move) { + Sel sel = view->selection; + sel.beg = sel.end = buf_byline(&(view->buffer), sel.end, move); + sel.beg = sel.end = buf_setcol(&(view->buffer), sel.end, sel.col); + view->selection = sel; +} + + +//void view_update(View* view, size_t crsr, size_t* csrx, size_t* csry) { +// +//} +// +//size_t view_getoff(View* view, size_t pos, size_t row, size_t col) { +// return 0; +//} +// +//void view_setsize(View* view, size_t nrows, size_t ncols) { +// +//} +// +//void view_getsize(View* view, size_t* nrows, size_t* ncols) { +// +//} +// +//void view_clearrow(View* view, size_t row) { +// +//} +// +//size_t view_setcell(View* view, size_t row, size_t col, uint32_t attr, Rune r) { +// return 0; +//} +// +//UGlyph* view_getglyph(View* view, size_t row, size_t col, size_t* scrwidth) { +// return NULL; +//} diff --git a/libx/x11.c b/libx/x11.c index 8570bd3..3739f99 100644 --- a/libx/x11.c +++ b/libx/x11.c @@ -1,10 +1,32 @@ -#include -#include #include #include +#include +#include +#include #include #include +#ifndef MAXFONTS +#define MAXFONTS 16 +#endif + +struct XFont { + struct { + int height; + int width; + int ascent; + int descent; + XftFont* match; + FcFontSet* set; + FcPattern* pattern; + } base; + struct { + XftFont* font; + uint32_t unicodep; + } cache[MAXFONTS]; + int ncached; +}; + static bool Running = true; static struct { Window root; @@ -215,19 +237,8 @@ void x11_loop(void) { XCloseDisplay(X.display); } -void x11_draw_rect(int color, int x, int y, int width, int height) { - XftColor clr; - xftcolor(&clr, Config->palette[color]); - XftDrawRect(X.xft, &clr, x, y, width, height); - XftColorFree(X.display, X.visual, X.colormap, &clr); -} - -void x11_getsize(int* width, int* height) { - *width = X.width; - *height = X.height; -} - -void x11_font_load(XFont* font, char* name) { +XFont x11_font_load(char* name) { + struct XFont* font = calloc(1, sizeof(struct XFont)); /* init the library and the base font pattern */ if (!FcInit()) die("Could not init fontconfig.\n"); @@ -255,9 +266,33 @@ void x11_font_load(XFont* font, char* name) { font->base.height = font->base.ascent + font->base.descent; font->base.width = ((extents.xOff + (sizeof(ascii) - 1)) / sizeof(ascii)); FcPatternDestroy(pattern); + return font; +} + +size_t x11_font_height(XFont fnt) { + struct XFont* font = fnt; + return font->base.height; +} + +size_t x11_font_width(XFont fnt) { + struct XFont* font = fnt; + return font->base.width; +} + +size_t x11_font_descent(XFont fnt) { + struct XFont* font = fnt; + return font->base.descent; +} + +void x11_draw_rect(int color, int x, int y, int width, int height) { + XftColor clr; + xftcolor(&clr, Config->palette[color]); + XftDrawRect(X.xft, &clr, x, y, width, height); + XftColorFree(X.display, X.visual, X.colormap, &clr); } -void x11_font_getglyph(XFont* font, XftGlyphFontSpec* spec, uint32_t rune) { +void x11_font_getglyph(XFont fnt, XGlyphSpec* spec, uint32_t rune) { + struct XFont* font = fnt; /* if the rune is in the base font, set it and return */ FT_UInt glyphidx = XftCharIndex(X.display, font->base.match, rune); if (glyphidx) { @@ -302,25 +337,8 @@ void x11_font_getglyph(XFont* font, XftGlyphFontSpec* spec, uint32_t rune) { FcCharSetDestroy(fccharset); } -void x11_draw_glyphs(int fg, int bg, XftGlyphFontSpec* specs, size_t nspecs) { - if (!nspecs) return; - XftFont* font = specs[0].font; - XftColor fgc, bgc; - if (bg > 0) { - XGlyphInfo extent; - XftTextExtentsUtf8(X.display, font, (const FcChar8*)"0", 1, &extent); - int w = extent.xOff; - int h = (font->height - font->descent); - xftcolor(&bgc, Config->palette[bg]); - x11_draw_rect(bg, specs[0].x, specs[0].y - h, nspecs * w, font->height); - XftColorFree(X.display, X.visual, X.colormap, &bgc); - } - xftcolor(&fgc, Config->palette[fg]); - XftDrawGlyphFontSpec(X.xft, &fgc, specs, nspecs); - XftColorFree(X.display, X.visual, X.colormap, &fgc); -} - -size_t x11_font_getglyphs(XftGlyphFontSpec* specs, const XGlyph* glyphs, int len, XFont* font, int x, int y) { +size_t x11_font_getglyphs(XGlyphSpec* specs, const XGlyph* glyphs, int len, XFont fnt, int x, int y) { + struct XFont* font = fnt; int winx = x * font->base.width, winy = y * font->base.ascent; size_t numspecs = 0; for (int i = 0, xp = winx, yp = winy + font->base.ascent; i < len;) { @@ -337,20 +355,38 @@ size_t x11_font_getglyphs(XftGlyphFontSpec* specs, const XGlyph* glyphs, int len return numspecs; } -void x11_draw_utf8(XFont* font, int fg, int bg, int x, int y, char* str) { - static XftGlyphFontSpec specs[256]; - size_t nspecs = 0; - while (*str && nspecs < 256) { - x11_font_getglyph(font, &(specs[nspecs]), *str); - specs[nspecs].x = x; - specs[nspecs].y = y; - x += font->base.width; - nspecs++; - str++; +void x11_draw_glyphs(int fg, int bg, XGlyphSpec* specs, size_t nspecs) { + if (!nspecs) return; + XftFont* font = specs[0].font; + XftColor fgc, bgc; + if (bg > 0) { + XGlyphInfo extent; + XftTextExtentsUtf8(X.display, font, (const FcChar8*)"0", 1, &extent); + int w = extent.xOff; + int h = (font->height - font->descent); + xftcolor(&bgc, Config->palette[bg]); + x11_draw_rect(bg, specs[0].x, specs[0].y - h, nspecs * w, font->height); + XftColorFree(X.display, X.visual, X.colormap, &bgc); } - x11_draw_glyphs(fg, bg, specs, nspecs); + xftcolor(&fgc, Config->palette[fg]); + XftDrawGlyphFontSpec(X.xft, &fgc, (XftGlyphFontSpec*)specs, nspecs); + XftColorFree(X.display, X.visual, X.colormap, &fgc); } -void x11_warp_mouse(int x, int y) { - XWarpPointer(X.display, X.window, X.window, 0, 0, X.width, X.height, x, y); -} +//void x11_draw_utf8(XFont* font, int fg, int bg, int x, int y, char* str) { +// static XftGlyphFontSpec specs[256]; +// size_t nspecs = 0; +// while (*str && nspecs < 256) { +// x11_font_getglyph(font, &(specs[nspecs]), *str); +// specs[nspecs].x = x; +// specs[nspecs].y = y; +// x += font->base.width; +// nspecs++; +// str++; +// } +// x11_draw_glyphs(fg, bg, specs, nspecs); +//} +// +//void x11_warp_mouse(int x, int y) { +// XWarpPointer(X.display, X.window, X.window, 0, 0, X.width, X.height, x, y); +//} diff --git a/xedit.c b/xedit.c index df6c528..8b9d309 100644 --- a/xedit.c +++ b/xedit.c @@ -1,5 +1,5 @@ #include -#include +#include #include #include #include @@ -10,15 +10,20 @@ static void key_handler(Rune key); /* Global Data *****************************************************************************/ -Buf Buffer; -Buf TagBuffer; -unsigned TargetCol = 0; -unsigned SelBeg = 0; -unsigned SelEnd = 0; -static unsigned ScrRows = 0; -static unsigned ScrCols = 0; +//Buf Buffer; +//Buf TagBuffer; +//unsigned TargetCol = 0; +//unsigned SelBeg = 0; +//unsigned SelEnd = 0; +//static unsigned ScrRows = 0; +//static unsigned ScrCols = 0; +//static XFont Fonts; + static bool TagWinExpanded = false; -static XFont Fonts; +static View TagView; +static View BufView; +static View* Focused = &BufView; +static XFont Font; static XConfig Config = { .redraw = redraw, .handle_key = key_handler, @@ -26,10 +31,210 @@ static XConfig Config = { .palette = COLOR_PALETTE }; -/* new view globals */ -static View TagView; -static View EditView; -static View* Active = &EditView; +/* UI Callbacks + *****************************************************************************/ +static void cursor_up(void) { + view_byline(Focused, -1); +} + +static void cursor_dn(void) { + view_byline(Focused, +1); +} + +static void cursor_left(void) { + view_byrune(Focused, -1); +} + +static void cursor_right(void) { + view_byrune(Focused, +1); +} + +/* UI Callbacks + *****************************************************************************/ +static void mouse_handler(MouseAct act, MouseBtn btn, int x, int y) { + +} + +/* Keyboard Bindings + *****************************************************************************/ +typedef struct { + Rune key; + void (*action)(void); +} KeyBinding_T; + +static KeyBinding_T Insert[] = { + { KEY_UP, cursor_up }, + { KEY_DOWN, cursor_dn }, + { KEY_LEFT, cursor_left }, + { KEY_RIGHT, cursor_right }, + //{ KEY_CTRL_Q, quit }, + //{ KEY_CTRL_S, write }, + //{ KEY_CTRL_T, tagwin }, + //{ KEY_CTRL_Z, undo }, + //{ KEY_CTRL_Y, redo }, + //{ KEY_CTRL_X, cut }, + //{ KEY_CTRL_C, copy }, + //{ KEY_CTRL_V, paste }, + //{ KEY_HOME, cursor_bol }, + //{ KEY_END, cursor_eol }, + //{ KEY_DELETE, delete }, + //{ KEY_BACKSPACE, backspace }, + { 0, NULL } +}; + +static void process_table(KeyBinding_T* bindings, Rune key) { + while (bindings->key) { + if (key == bindings->key) { + bindings->action(); + return; + } + bindings++; + } + /* skip control and nonprintable characters */ + if ((!isspace(key) && key < 0x20) || + (key >= 0xE000 && key <= 0xF8FF)) + return; + /* fallback to just inserting the rune */ + //buf_ins(&Buffer, SelEnd++, key); + //SelBeg = SelEnd; + //TargetCol = buf_getcol(&Buffer, SelEnd); +} + +static void key_handler(Rune key) { + /* ignore invalid keys */ + if (key == RUNE_ERR) return; + /* handle the proper line endings */ + if (key == '\r') key = '\n'; + if (key == '\n' && Focused->buffer.crlf) key = RUNE_CRLF; + /* handle the key */ + process_table(Insert, key); +} + +/* Redisplay Functions + *****************************************************************************/ +static void draw_runes(unsigned x, unsigned y, int fg, int bg, UGlyph* glyphs, size_t rlen) { + XGlyphSpec specs[rlen]; + while (rlen) { + size_t nspecs = x11_font_getglyphs(specs, (XGlyph*)glyphs, rlen, Font, x, y); + x11_draw_glyphs(fg, bg, specs, nspecs); + rlen -= nspecs; + } +} + +static void draw_glyphs(unsigned x, unsigned y, UGlyph* glyphs, size_t rlen, size_t ncols) { + XGlyphSpec specs[rlen]; + size_t i = 0; + while (rlen) { + int numspecs = 0; + uint32_t attr = glyphs[i].attr; + while (i < ncols && glyphs[i].attr == attr) { + x11_font_getglyph(Font, &(specs[numspecs]), glyphs[i].rune); + specs[numspecs].x = x; + specs[numspecs].y = y - x11_font_descent(Font); + x += x11_font_width(Font); + numspecs++; + i++; + /* skip over null chars which mark multi column runes */ + for (; i < ncols && !glyphs[i].rune; i++) + x += x11_font_width(Font); + } + /* Draw the glyphs with the proper colors */ + uint8_t bg = attr >> 8; + uint8_t fg = attr & 0xFF; + x11_draw_glyphs(fg, bg, specs, numspecs); + rlen -= numspecs; + } +} + +static void draw_status(int fg, unsigned ncols) { + UGlyph glyphs[ncols], *status = glyphs; + (status++)->rune = (BufView.buffer.charset == BINARY ? 'B' : 'U'); + (status++)->rune = (BufView.buffer.crlf ? 'C' : 'N'); + (status++)->rune = (BufView.buffer.modified ? '*' : ' '); + (status++)->rune = ' '; + char* path = (BufView.buffer.path ? BufView.buffer.path : "*scratch*"); + size_t len = strlen(path); + if (len > ncols-4) { + (status++)->rune = '.'; + (status++)->rune = '.'; + (status++)->rune = '.'; + path += (len - ncols) + 6; + } + while(*path) + (status++)->rune = *path++; + draw_runes(0, 0, fg, 0, glyphs, status - glyphs); +} + +static size_t stackvert(size_t off, size_t rows) { + return (off + 4 + (rows * x11_font_height(Font))); +} + +static size_t draw_view(size_t off, View* view, size_t rows, size_t width) { + size_t fheight = x11_font_height(Font); + size_t fwidth = x11_font_width(Font); + size_t cols = (width - 4) / fwidth; + view_resize(view, rows, cols); + /* update the screen buffer and retrieve cursor coordinates */ + size_t csrx, csry; + view_update(view, &csrx, &csry); + /* flush the screen buffer */ + for (size_t y = 0; y < rows; y++) { + Row* row = view_getrow(view, y); + draw_glyphs(2, off + ((y+1) * fheight), row->cols, row->rlen, row->len); + } + /* Place cursor on screen */ + x11_draw_rect(CLR_BASE3, 2 + csrx * fwidth, off + (csry * fheight), 1, fheight); + return (off + 4 + (rows * x11_font_height(Font))); +} + +static void redraw(int width, int height) { + size_t vmargin = 2; + size_t hmargin = 2; + size_t fheight = x11_font_height(Font); + size_t fwidth = x11_font_width(Font); + /* clear background and draw status */ + size_t vpos = 0; + x11_draw_rect(CLR_BASE03, 0, vpos, width, height); + draw_status(CLR_BASE3, width / fwidth); + /* draw the tag buffer */ + vpos = stackvert(vpos, 1); + x11_draw_rect(CLR_BASE01, 0, vpos++, width, 1); + size_t totrows = (height - vpos - 9) / fheight; + size_t tagrows = (TagWinExpanded ? (totrows / 4) : 1); + size_t bufrows = totrows - tagrows; + vpos = draw_view(3+vpos, &TagView, tagrows, width); + /* draw thee dit buffer */ + x11_draw_rect(CLR_BASE01, 0, ++vpos, width, 1); + vpos = draw_view(3+vpos, &BufView, bufrows, width); +} + +/* Main Routine + *****************************************************************************/ +int main(int argc, char** argv) { + /* load the buffer views */ + view_init(&TagView, NULL); + view_init(&BufView, (argc > 1 ? argv[1] : NULL)); + buf_putstr(&(TagView.buffer), 0, 0, DEFAULT_TAGS); + /* initialize the display engine */ + x11_init(&Config); + x11_window("edit", Width, Height); + x11_show(); + Font = x11_font_load(FONTNAME); + x11_loop(); + return 0; +} + +#if 0 +#if 0 +/* External Commands + *****************************************************************************/ +#ifdef __MACH__ +static char* CopyCmd[] = { "pbcopy", NULL }; +static char* PasteCmd[] = { "pbpaste", NULL }; +#else +static char* CopyCmd[] = { "xsel", "-bi", NULL }; +static char* PasteCmd[] = { "xsel", "-bo", NULL }; +#endif /* Keyboard Actions *****************************************************************************/ @@ -75,43 +280,23 @@ static void redo(void) { static void cut(void) { char* str = buf_getstr(&Buffer, SelBeg, SelEnd); - clipcopy(str); + cmdwrite(CopyCmd, str); free(str); delete(); } static void copy(void) { char* str = buf_getstr(&Buffer, SelBeg, SelEnd); - clipcopy(str); + cmdwrite(CopyCmd, str); free(str); } static void paste(void) { - char* str = clippaste(); + char* str = cmdread(PasteCmd); buf_putstr(&Buffer, SelBeg, SelEnd, str); free(str); } -static void cursor_up(void) { - SelBeg = SelEnd = buf_byline(&Buffer, SelEnd, -1); - SelBeg = SelEnd = buf_setcol(&Buffer, SelEnd, TargetCol); -} - -static void cursor_dn(void) { - SelBeg = SelEnd = buf_byline(&Buffer, SelEnd, 1); - SelBeg = SelEnd = buf_setcol(&Buffer, SelEnd, TargetCol); -} - -static void cursor_left(void) { - SelBeg = SelEnd = buf_byrune(&Buffer, SelEnd, -1); - TargetCol = buf_getcol(&Buffer, SelEnd); -} - -static void cursor_right(void) { - SelBeg = SelEnd = buf_byrune(&Buffer, SelEnd, 1); - TargetCol = buf_getcol(&Buffer, SelEnd); -} - static void cursor_bol(void) { SelBeg = SelEnd = buf_bol(&Buffer, SelEnd); TargetCol = 0; @@ -126,69 +311,17 @@ static void tagwin(void) { TagWinExpanded = !TagWinExpanded; } -/* Keyboard Bindings - *****************************************************************************/ -typedef struct { - Rune key; - void (*action)(void); -} KeyBinding_T; - -static KeyBinding_T Insert[] = { - { KEY_CTRL_Q, quit }, - { KEY_CTRL_S, write }, - { KEY_CTRL_T, tagwin }, - { KEY_CTRL_Z, undo }, - { KEY_CTRL_Y, redo }, - { KEY_CTRL_X, cut }, - { KEY_CTRL_C, copy }, - { KEY_CTRL_V, paste }, - { KEY_UP, cursor_up }, - { KEY_DOWN, cursor_dn }, - { KEY_LEFT, cursor_left }, - { KEY_RIGHT, cursor_right }, - { KEY_HOME, cursor_bol }, - { KEY_END, cursor_eol }, - { KEY_DELETE, delete }, - { KEY_BACKSPACE, backspace }, - { 0, NULL } -}; - -static void process_table(KeyBinding_T* bindings, Rune key) { - while (bindings->key) { - if (key == bindings->key) { - bindings->action(); - return; - } - bindings++; - } - /* skip control and nonprintable characters */ - if ((!isspace(key) && key < 0x20) || - (key >= 0xE000 && key <= 0xF8FF)) - return; - /* fallback to just inserting the rune */ - buf_ins(&Buffer, SelEnd++, key); - SelBeg = SelEnd; - TargetCol = buf_getcol(&Buffer, SelEnd); -} - -static void key_handler(Rune key) { - /* ignore invalid keys */ - if (key == RUNE_ERR) return; - /* handle the proper line endings */ - if (key == '\r') key = '\n'; - if (key == '\n' && Buffer.crlf) key = RUNE_CRLF; - /* handle the key */ - process_table(Insert, key); -} +#endif /* Mouse Actions *****************************************************************************/ +#if 0 void unused(int x, int y) { } void move_cursor(int x, int y) { if (y == 0) return; - SelBeg = SelEnd = screen_getoff(&Buffer, SelEnd, y-1, x); + //SelBeg = SelEnd = screen_getoff(&Buffer, SelEnd, y-1, x); TargetCol = buf_getcol(&Buffer, SelEnd); } @@ -223,18 +356,17 @@ void selection(int x, int y) { } void search(int x, int y) { - unsigned clickpos = screen_getoff(&Buffer, SelEnd, y-1, x); - if (clickpos < SelBeg || clickpos > SelEnd) { - move_cursor(x,y); - selection(x,y); - } else { - buf_find(&Buffer, &SelBeg, &SelEnd); - } - unsigned c, r; - screen_update(&Buffer, SelEnd, &c, &r); - extern void move_pointer(unsigned c, unsigned r); - move_pointer(c, r); - + //unsigned clickpos = screen_getoff(&Buffer, SelEnd, y-1, x); + //if (clickpos < SelBeg || clickpos > SelEnd) { + // move_cursor(x,y); + // selection(x,y); + //} else { + // buf_find(&Buffer, &SelBeg, &SelEnd); + //} + //unsigned c, r; + //screen_update(&Buffer, SelEnd, &c, &r); + //extern void move_pointer(unsigned c, unsigned r); + //move_pointer(c, r); } void scrollup(int x, int y) { @@ -244,7 +376,7 @@ void scrollup(int x, int y) { void scrolldn(int x, int y) { SelBeg = SelEnd = buf_byline(&Buffer, SelEnd, ScrollLines); } - +#endif /* Mouse Input Handler *****************************************************************************/ struct { @@ -252,105 +384,52 @@ struct { uint32_t count; } Buttons[5] = { 0 }; -void (*Actions[5][3])(int x, int y) = { +void (*Actions[5][3])(int x, int y) = { 0 /* Single Double Triple */ - [MOUSE_BTN_LEFT] = { move_cursor, selection, bigword, }, - [MOUSE_BTN_MIDDLE] = { unused, unused, unused, }, - [MOUSE_BTN_RIGHT] = { search, search, search, }, - [MOUSE_BTN_WHEELUP] = { scrollup, scrollup, scrollup, }, - [MOUSE_BTN_WHEELDOWN] = { scrolldn, scrolldn, scrolldn, }, + //[MOUSE_BTN_LEFT] = { move_cursor, selection, bigword, }, + //[MOUSE_BTN_MIDDLE] = { unused, unused, unused, }, + //[MOUSE_BTN_RIGHT] = { search, search, search, }, + //[MOUSE_BTN_WHEELUP] = { scrollup, scrollup, scrollup, }, + //[MOUSE_BTN_WHEELDOWN] = { scrolldn, scrolldn, scrolldn, }, }; static void mouse_handler(MouseAct act, MouseBtn btn, int x, int y) { - unsigned row = y / Fonts.base.height; - unsigned col = x / Fonts.base.width; - unsigned twsz = (TagWinExpanded ? ((ScrRows - 1) / 4) : 1); - - //if (row == 0) { - // puts("status"); - //} else if (row >= 1 && row <= twsz) { - // puts("tagwin"); - //} else { - // puts("editwin"); + //unsigned row = y / Fonts.base.height; + //unsigned col = x / Fonts.base.width; + //unsigned twsz = (TagWinExpanded ? ((ScrRows - 1) / 4) : 1); + + ////if (row == 0) { + //// puts("status"); + ////} else if (row >= 1 && row <= twsz) { + //// puts("tagwin"); + ////} else { + //// puts("editwin"); + ////} + + //if (act == MOUSE_ACT_DOWN) { + // //if (mevnt->button >= 5) return; + // ///* update the number of clicks */ + // //uint32_t now = getmillis(); + // //uint32_t elapsed = now - Buttons[mevnt->button].time; + // //if (elapsed <= 250) + // // Buttons[mevnt->button].count++; + // //else + // // Buttons[mevnt->button].count = 1; + // //Buttons[mevnt->button].time = now; + // ///* execute the click action */ + // //uint32_t nclicks = Buttons[mevnt->button].count; + // //nclicks = (nclicks > 3 ? 1 : nclicks); + // //Actions[mevnt->button][nclicks-1](mevnt); + //} else if (act == MOUSE_ACT_MOVE) { + // puts("move"); + // //if (mevnt->y == 0 || mevnt->button != MOUSE_LEFT) return; + // //SelEnd = screen_getoff(&Buffer, SelEnd, mevnt->y-1, mevnt->x); + // //TargetCol = buf_getcol(&Buffer, SelEnd); //} - - if (act == MOUSE_ACT_DOWN) { - //if (mevnt->button >= 5) return; - ///* update the number of clicks */ - //uint32_t now = getmillis(); - //uint32_t elapsed = now - Buttons[mevnt->button].time; - //if (elapsed <= 250) - // Buttons[mevnt->button].count++; - //else - // Buttons[mevnt->button].count = 1; - //Buttons[mevnt->button].time = now; - ///* execute the click action */ - //uint32_t nclicks = Buttons[mevnt->button].count; - //nclicks = (nclicks > 3 ? 1 : nclicks); - //Actions[mevnt->button][nclicks-1](mevnt); - } else if (act == MOUSE_ACT_MOVE) { - //if (mevnt->y == 0 || mevnt->button != MOUSE_LEFT) return; - //SelEnd = screen_getoff(&Buffer, SelEnd, mevnt->y-1, mevnt->x); - //TargetCol = buf_getcol(&Buffer, SelEnd); - } } - /* Screen Redraw *****************************************************************************/ -static void draw_runes(unsigned x, unsigned y, int fg, int bg, UGlyph* glyphs, size_t rlen) { - XftGlyphFontSpec specs[rlen]; - while (rlen) { - size_t nspecs = x11_font_getglyphs(specs, (XGlyph*)glyphs, rlen, &Fonts, x, y); - x11_draw_glyphs(fg, bg, specs, nspecs); - rlen -= nspecs; - } -} - -static void draw_glyphs(unsigned x, unsigned y, UGlyph* glyphs, size_t rlen, size_t ncols) { - XftGlyphFontSpec specs[rlen]; - size_t i = 0; - while (rlen) { - int numspecs = 0; - uint32_t attr = glyphs[i].attr; - while (i < ncols && glyphs[i].attr == attr) { - x11_font_getglyph(&Fonts, &(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; - x11_draw_glyphs(fg, bg, specs, numspecs); - rlen -= numspecs; - } -} - -static void draw_status(int fg, unsigned ncols) { - UGlyph glyphs[ncols], *status = glyphs; - (status++)->rune = (Buffer.charset == BINARY ? 'B' : 'U'); - (status++)->rune = (Buffer.crlf ? 'C' : 'N'); - (status++)->rune = (Buffer.modified ? '*' : ' '); - (status++)->rune = ' '; - char* path = (Buffer.path ? Buffer.path : "*scratch*"); - size_t len = strlen(path); - if (len > ncols-4) { - (status++)->rune = '.'; - (status++)->rune = '.'; - (status++)->rune = '.'; - path += (len - ncols) + 6; - } - while(*path) - (status++)->rune = *path++; - draw_runes(0, 0, fg, 0, glyphs, status - glyphs); -} - static void draw_tagwin(unsigned off, unsigned rows, unsigned cols) { //screen_setsize(&TagBuffer, rows, cols); @@ -358,45 +437,44 @@ static void draw_tagwin(unsigned off, unsigned rows, unsigned cols) { } static void draw_bufwin(unsigned off, unsigned rows, unsigned cols) { - screen_setsize(&Buffer, rows, cols); - /* update the screen buffer and retrieve cursor coordinates */ - unsigned csrx, csry; - screen_update(&Buffer, SelEnd, &csrx, &csry); - /* flush the screen buffer */ - unsigned nrows, ncols; - screen_getsize(&nrows, &ncols); - draw_status(CLR_BASE2, ncols); - for (unsigned y = 0; y < nrows; y++) { - Row* row = screen_getrow(y); - draw_glyphs(0, off + ((y+1) * Fonts.base.height), row->cols, row->rlen, row->len); - } - /* Place cursor on screen */ - x11_draw_rect(CLR_BASE3, csrx * Fonts.base.width, off + (csry * Fonts.base.height), 1, Fonts.base.height); + //screen_setsize(&Buffer, rows, cols); + ///* update the screen buffer and retrieve cursor coordinates */ + //unsigned csrx, csry; + //screen_update(&Buffer, SelEnd, &csrx, &csry); + ///* flush the screen buffer */ + //unsigned nrows, ncols; + //screen_getsize(&nrows, &ncols); + //draw_status(CLR_BASE2, ncols); + //for (unsigned y = 0; y < nrows; y++) { + // Row* row = screen_getrow(y); + // draw_glyphs(0, off + ((y+1) * Fonts.base.height), row->cols, row->rlen, row->len); + //} + ///* Place cursor on screen */ + //x11_draw_rect(CLR_BASE3, csrx * Fonts.base.width, off + (csry * Fonts.base.height), 1, Fonts.base.height); } static void redraw(int width, int height) { - unsigned fheight = Fonts.base.height; - unsigned fwidth = Fonts.base.width; - ScrRows = height / Fonts.base.height; - ScrCols = width / Fonts.base.width; - /* clear background and draw status */ - x11_draw_rect(CLR_BASE03, 0, 0, width, height); - draw_status(CLR_BASE2, ScrCols); - /* draw the tag window */ - unsigned twsz = (TagWinExpanded ? ((ScrRows - 1) / 4) : 1); - x11_draw_rect(CLR_BASE02, 0, fheight, width, twsz * fheight); - x11_draw_rect(CLR_BASE01, 0, fheight, width, 1); - draw_tagwin(fheight, twsz, ScrCols); - /* draw the file window */ - x11_draw_rect(CLR_BASE01, 0, (twsz+1) * fheight, width, 1); - draw_bufwin((twsz+1) * fheight, ScrRows - (twsz), ScrCols); + //unsigned fheight = Fonts.base.height; + //unsigned fwidth = Fonts.base.width; + //ScrRows = height / Fonts.base.height; + //ScrCols = width / Fonts.base.width; + ///* clear background and draw status */ + //x11_draw_rect(CLR_BASE03, 0, 0, width, height); + //draw_status(CLR_BASE2, ScrCols); + ///* draw the tag window */ + //unsigned twsz = (TagWinExpanded ? ((ScrRows - 1) / 4) : 1); + //x11_draw_rect(CLR_BASE02, 0, fheight, width, twsz * fheight); + //x11_draw_rect(CLR_BASE01, 0, fheight, width, 1); + //draw_tagwin(fheight, twsz, ScrCols); + ///* draw the file window */ + //x11_draw_rect(CLR_BASE01, 0, (twsz+1) * fheight, width, 1); + //draw_bufwin((twsz+1) * fheight, ScrRows - (twsz), ScrCols); } int main(int argc, char** argv) { - /* load the buffer */ - buf_init(&Buffer); - if (argc > 1) - buf_load(&Buffer, argv[1]); + /* load the buffer views */ + view_init(&TagView, NULL); + view_init(&BufView, (argc > 1 ? argv[1] : NULL)); /* initialize the display engine */ x11_init(&Config); x11_window("edit", Width, Height); @@ -411,3 +489,4 @@ void move_pointer(unsigned x, unsigned y) { y = ((y+1) * Fonts.base.height) + (Fonts.base.height / 2); x11_warp_mouse(x,y); } +#endif diff --git a/xpick.c b/xpick.c index ac36baf..72e5866 100644 --- a/xpick.c +++ b/xpick.c @@ -1,5 +1,5 @@ #include -#include +#include #include #include #include