diff options
| author | Quentin Carbonneaux | 2014-08-29 13:23:30 -0400 |
|---|---|---|
| committer | Quentin Carbonneaux | 2014-08-29 13:23:30 -0400 |
| commit | 46f7bf9ee38212d481754d0c7d8d2c6d36ed1c09 (patch) | |
| tree | de2fa58b533bd4dc08031911341667ff27926fd7 | |
| parent | d1e58cb2608044a0146299e0988fc3119ee58197 (diff) | |
burry old directory in history
| -rw-r--r-- | old/buf.c | 255 | ||||
| -rw-r--r-- | old/win-efficient.c | 356 | ||||
| -rw-r--r-- | old/win-scroll-halfclean.c | 461 | ||||
| -rw-r--r-- | old/win-ugly.c | 30 | ||||
| -rw-r--r-- | old/win.c-1 | 454 | ||||
| -rw-r--r-- | old/win.c-2 | 449 | ||||
| -rw-r--r-- | old/xmess/.comfile | 1 | ||||
| -rw-r--r-- | old/xmess/gui.h | 102 | ||||
| -rw-r--r-- | old/xmess/win.c | 401 | ||||
| -rw-r--r-- | old/xmess/win.h | 30 | ||||
| -rwxr-xr-x | old/xmess/x11 | bin | 27160 -> 0 bytes | |||
| -rw-r--r-- | old/xmess/x11.c | 357 | ||||
| -rw-r--r-- | old/xmess/x11.o | bin | 9664 -> 0 bytes |
13 files changed, 0 insertions, 2896 deletions
diff --git a/old/buf.c b/old/buf.c deleted file mode 100644 index 5d7afda..0000000 --- a/old/buf.c +++ /dev/null @@ -1,255 +0,0 @@ -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "buf.h" -#include "unicode.h" - -static Rune *hend(Page *); -static void ins(Buf *, unsigned, Rune); -static void move(Rune *, Rune *, unsigned); -static Page *newpage(void); -static Page *page(Buf *, unsigned *); -static void setnl(Page *); - -Buf * -buf_new(char path[]) -{ - Buf *b; - - b = malloc(sizeof *b); - if (!b) - return 0; - snprintf(b->path, PathLen, "%s", path); - b->p = newpage(); - b->last = 0; - return b; -} - -/* buf_ins_utf8 - Insert raw utf8 encoded text in buffer [b] - * at position [pos]. The number of bytes processed is returned. - */ -int -buf_ins_utf8(Buf *b, unsigned pos, unsigned char *data, int len) -{ - Rune r; - int rd, total; - - total = 0; - while ((rd = utf8_decode_rune(&r, data, len))) { - ins(b, pos++, r); - data += rd; - len -= rd; - total += rd; - } - return total; -} - -unsigned -buf_read(Buf *b, unsigned off, Rune *rs, unsigned len) -{ - unsigned n, m; - Page *p; - - if (len == 0) - return 0; - - p = page(b, &off); - - if (off >= p->len) { - if (p->n) { - p = p->n; - off = 0; - } else - return 0; - } - - n = 0; - do { - m = p->hbeg - p->buf; - if (off < m) { - if (m - off > len - n) - m = len - n; - else - m -= off; - move(rs+n, p->buf+off, m); - off += m; - n += m; - } else { - off -= m; // offset after hole - m = p->len - m; - if (m - off > len - n) - m = len - n; - else - m -= off; - move(rs+n, hend(p)+off, m); - n += m; - if (p->n) { - p = p->n; - off = 0; - } else - return n; - } - } while (n < len); - - return n; -} - -Rune -buf_get(Buf *b, unsigned pos) -{ - Rune r; - - r = NORUNE; - buf_read(b, pos, &r, 1); - return r; -} - -/* static functions */ - -/* hend - Get a pointer on the end of the hole in page [p]. - */ -static Rune * -hend(Page *p) -{ - return p->hbeg + (PageLen - p->len); -} - -/* ins - Insert a rune in the buffer [b] at position [pos]. - */ -static void -ins(Buf *b, unsigned pos, Rune r) -{ - Page *p; - unsigned off; - long int shft; - - off = pos; - p = page(b, &off); - - if (p->len == PageLen) { /* bad luck, grow a page */ - Page *q; - enum { l = PageLen/2 }; - - q = newpage(); - q->n = p->n; - p->n = q; - - move(q->buf, &p->buf[l], PageLen-l); - q->hbeg = q->buf + PageLen-l; - q->len = PageLen-l; - - p->hbeg = p->buf + l; - p->len = l; - - setnl(p); - setnl(q); - ins(b, pos, r); - return; - } - - shft = off - (p->hbeg - p->buf); - if (shft) { - if (shft>0) - move(p->hbeg, hend(p), shft); - else - move(hend(p) + shft, p->hbeg + shft, -shft); - - p->hbeg += shft; - } - - /* there we go */ - *p->hbeg++ = r; - p->len++; - if (r == '\n') - p->nl++; -} - -/* move - Move some runes in an array, works like - * memmove the zones must not overlap. - */ -static void -move(Rune *dest, Rune *from, unsigned cnt) -{ - memmove(dest, from, cnt * sizeof(Rune)); -} - -static Page * -newpage(void) -{ - Page *p; - - p = malloc(sizeof *p); - assert(p); - p->hbeg = p->buf; - p->len = 0; - p->nl = 0; - p->n = 0; - return p; -} - -/* page - Get a page containing the [*ppos]'th position. - * *ppos is also modified to represent the offset in the - * page. - */ -static Page * -page(Buf *b, unsigned *ppos) -{ - Page *p; - unsigned off, pos; - - pos = *ppos; - if (b->last) { - if (pos < b->lastbeg) { - off = 0; - p = b->p; - } - else if (pos > b->lastbeg + b->last->len) { - off = b->lastbeg; - p = b->last; - } - else { - *ppos -= b->lastbeg; - return b->last; - } - } else { - off = 0; - p = b->p; - } - - for (; p->n; p=p->n) { - if (pos >= off && pos <= off + p->len) - break; - off += p->len; - } - - b->lastbeg = off; - b->last = p; - - pos -= off; - if (pos > p->len) - pos = p->len; - *ppos = pos; - return p; -} - -/* setnl - Update the line count of a page. - */ -static void -setnl(Page *p) -{ - Rune *r; - int cnt; - - cnt = 0; - for (r = p->buf; r < p->hbeg; r++) - if (*r == '\n') - cnt++; - - for (r = hend(p); r < &p->buf[PageLen]; r++) - if (*r == '\n') - cnt++; - - p->nl = cnt; -} diff --git a/old/win-efficient.c b/old/win-efficient.c deleted file mode 100644 index 80bdb80..0000000 --- a/old/win-efficient.c +++ /dev/null @@ -1,356 +0,0 @@ -/*% clang -DWIN_TEST -Wall -g -I/usr/include/freetype2 -lX11 -lXft obj/unicode.o obj/buf.o obj/x11.o % -o # - * - * Windowing module - */ - -#include <assert.h> -#include <string.h> - -#include "unicode.h" -#include "buf.h" -#include "gui.h" -#include "win.h" - -enum { - Draw = 1, - Line = 2, -}; - -static void put(W *w, int flags); - -static W wins[MaxWins]; -static int nwins; -static struct gui *g; -static GFont font; -static int fwidth, fheight; - -/* win_init - initialize the module using [gui] as a - * graphical backed. - */ -void -win_init(struct gui *gui) -{ - g = gui; - - g->init(); - g->getfont(&font); - - /* the gui module does not give a way to access the screen - * dimension, instead, the first event generated will always - * be a GResize, so we can adjust these dummy values with - * win_resize_frame - */ - fwidth = fheight = 10; -} - -/* win_new - insert a new window if possible and - * return it. In case of error (more than MaxWins - * windows), 0 is returned. - */ -W * -win_new(Buf *b) -{ - if (nwins!=0) - return 0; - - memset(&wins[nwins], 0, sizeof(W)); - wins[nwins].b = b; - wins[nwins].gw = g->newwin(0, 0, fwidth, fheight); - wins[nwins].frac = FScale; - - nwins = 1; - return &wins[0]; -} - -/* win_delete - delete a window created by win_new. - */ -void -win_delete(W *w) -{ - assert(w >= wins); - assert(w < wins+nwins); - nwins = 0; -} - -/* win_resize_frame - called when the whole frame - * is resized. - */ -void -win_resize_frame(int w, int h) -{ - GColor white = { 255, 255, 255 }; - int x, ww; - W *pw; - - if (w!=0 && h!=0) { - fwidth = w; - fheight = h; - } - - for (x=0, pw=wins; pw-wins<nwins; pw++) { - ww = (fwidth * pw->frac) / FScale; - g->movewin(pw->gw, x, 0, ww, fheight); - g->drawrect(pw->gw, 0, 0, ww, fheight, white); - put(pw, Draw); - g->putwin(pw->gw); - x += ww; - } -} - -/* win_redraw_frame - redraw the whole frame. - */ -void -win_redraw_frame(void) -{ - win_resize_frame(0, 0); -} - -/* win_scroll - scroll the window by [n] lines. - * If [n] is negative it will scroll backwards. - * The number of lines scrolled must not be - * bigger than the number of lines currently on - * the screen. - */ -void -win_scroll(W *w, int n) -{ - int top; - unsigned off, bol; - W wscratch; - - if (w->nls == 0 || n == 0) - return; - - assert(n < 0 || n <= w->nls); - - wscratch.b = w->b; - wscratch.gw = w->gw; - - if (n<0) { - off = w->loff[0]; - - do { - if (off == 0) - break; - - bol = buf_bol(w->b, off-1); - wscratch.loff[0] = bol; - put(&wscratch, Line); - - top = wscratch.nls - 1; - do { - off = wscratch.loff[top--]; - if (off < w->loff[0]) - ++n; - } while (off >= w->loff[0] || (top>=0 && n<0)); - } while (n<0); - } else - off = w->loff[n]; - - w->loff[0] = off; - put(w, 0); /* update line offsets */ - - if (w->cl == -1) { /* fix the cursor position */ - if (n>0) - w->coff = w->loff[0]; - else - w->coff = w->loff[w->nls-1]; - } -} - -/* static functions */ - - -/* this function tries to factor calls to the pretty expensive - * [drawtext] function of the gui module, we basically try to aggregate - * all potential calls into one. Sometimes it is necessary to flush, - * for instance when the are displaying a new line or when a tabulation - * has to be printed. Tabs are treated specially because they have - * a width the drawtext function does not know a priori. - * - * Calling this function with [r == NORUNE] will force a flush. - * - * Before using this I called drawtext for each char, on a big screen - * the slowdown was significative. - */ -static void -draw(GWin *gw, Rune r, int x, int y, int rw, int cu) -{ - static int fragx = -1, fragy, cx = -1, cy, cw; - static Rune frag[MaxWidth], *p = frag; - int flush; - GColor color = { .blue = 255 }, - xor = { .x = 1 }; - - flush = 0; - - if (r != NORUNE && fragx == -1) { - fragx = x; - fragy = y; - } - - if (r != NORUNE && y == fragy) { - if (cu) { - cx = x; - cy = y-font.ascent; - cw = rw; - } - - if (r != '\t') { - assert(p-frag < MaxWidth); - *p++ = r; - } else - flush = 1; - } else - flush = 1; - - /* we flush the current fragment if one - * of the following conditions is met - * - the current rune is a tab - * - the current rune is a NORUNE (signaling eof) - * - the rune's y is different from the fragment's y - * (signaling a newline) - */ - if (flush) { -#if 0 - printf("flushing: fragx = %d\n" - " fragy = %d\n" - " r = %u\n" - " len = %zd\n", - fragx, fragy, r, p-frag); -#endif - if (fragx == -1) - return; - - g->drawtext(gw, frag, p-frag, fragx, fragy, color); - if (cx != -1) - g->drawrect(gw, cx, cy, cw, font.height, xor); - - fragx = cx = -1; - p = frag; - - if (r != NORUNE && r != '\n' && fragy != y) - /* push r on frag with a recursive call */ - draw(gw, r, x, y, rw, cu); - } -} - -static void -put(W *w, int flags) -{ - unsigned off, i, nl; - int rw, x, y, lnum; - Rune r; - GWin *gw; - - off = w->loff[0]; - gw = w->gw; - x = 0; - y = font.ascent; - lnum = 0; - w->loff[lnum++] = off; - w->cl = -1; - - for (i=0; y < gw->h || (flags & Line); i++) { - r = buf_get(w->b, off+i); - if (r == NORUNE) { - lnum++; - break; - } - - - if (r == '\t') { - rw = TabWidth * font.width; - rw -= x % (TabWidth * font.width); - } else { - nl = 0; - if (r != '\n') { - if (unicode_rune_width(r) == 0) - continue; - rw = g->textwidth(&r, 1); - if (x+rw > gw->w) - nl = off+i; - } else if ((flags & Line) == 0) { - nl = off+i+1; - rw = 0; - } else { - lnum++; - break; - } - - if (nl) { - y += font.height; - x = 0; - if (lnum < MaxLines) - w->loff[lnum++] = nl; - else { - /* should use a ring buffer... */ - assert(lnum == MaxLines); - memmove(w->loff, w->loff+1, - (MaxLines-1) * sizeof(int)); - w->loff[MaxLines-1] = nl; - } - } - } - - if (w->coff == off+i) - w->cl = lnum; - if ((flags & Draw) - draw(gw, r, x, y, rw, w->coff == off+i); - - x += rw; - } - - if (flags & Draw) - draw(gw, NORUNE, 0, 0, 0, 0); - w->nls = lnum - 1; -} - -#ifdef WIN_TEST -/* test */ - -#include <stdlib.h> - -void die(char *m) { exit(1); } - -int main(void) -{ - GEvent e; - Buf *b; - W *w; - unsigned char s[] = - "je suis\n" - "\tQuentin\n" - "tab\ttest\n" - "une longue longue longue longue longue longue longue longue longue longue longue longue longue ligne\n" - "un peu d'unicode: ä æ ç\n" - "et voila!\n"; - - b = buf_new("*"); - win_init(&gui_x11); - w = win_new(b); - - for (int i=0; i<20; i++) - buf_ins_utf8(b, 0, s, sizeof s - 1); - - do { - g->nextevent(&e); - if (e.type == GResize) - win_resize_frame(e.resize.width, e.resize.height); - if (e.type == GKey) { - switch (e.key) { - case 'l': w->coff++; break; - case 'h': w->coff--; break; - case 'e'-'a' + 1: win_scroll(w, 1); break; - case 'y'-'a' + 1: win_scroll(w, -1); break; - default: continue; - } - win_redraw_frame(); - } - } while (e.type != GKey || e.key != 'q'); - - g->fini(); - return 0; -} - -#endif diff --git a/old/win-scroll-halfclean.c b/old/win-scroll-halfclean.c deleted file mode 100644 index 390b9c5..0000000 --- a/old/win-scroll-halfclean.c +++ /dev/null @@ -1,461 +0,0 @@ -/*% clang -DWIN_TEST -Wall -g -I/usr/include/freetype2 -lX11 -lXft obj/unicode.o obj/buf.o obj/x11.o % -o # - * - * Windowing module - */ - -#include <assert.h> -#include <string.h> - -#include "unicode.h" -#include "buf.h" -#include "gui.h" -#include "win.h" - -enum CursorPos { Top, Bot }; -enum Focus { FocusBol, FocusEol, FocusCu }; - -enum { RingSize = 32 }; -struct lineinfo { - int beg, len; /* begining and len of the sl ring buffer */ - unsigned sl[RingSize]; /* ring buffer of screen line offsets */ - int cul; /* cursor line in sl */ -}; - -static void pushrune(GWin *gw, Rune r, int x, int y, int w, int cu); -static void draw(W *w); -static unsigned lineinfo(W *w, unsigned off, struct lineinfo *li, enum Focus f); - -static W wins[MaxWins]; -static int nwins; -static struct gui *g; -static GFont font; -static int fwidth, fheight; - -/* win_init - initialize the module using [gui] as a - * graphical backed. - */ -void -win_init(struct gui *gui) -{ - g = gui; - - g->init(); - g->getfont(&font); - - /* the gui module does not give a way to access the screen - * dimension, instead, the first event generated will always - * be a GResize, so we can adjust these dummy values with - * win_resize_frame - */ - fwidth = fheight = 10; -} - -/* win_new - insert a new window if possible and - * return it. In case of error (more than MaxWins - * windows), 0 is returned. - */ -W * -win_new(Buf *b) -{ - if (nwins!=0) - return 0; - - memset(&wins[nwins], 0, sizeof(W)); - wins[nwins].b = b; - wins[nwins].gw = g->newwin(0, 0, fwidth, fheight); - wins[nwins].vfrac = FScale; - - nwins = 1; - return &wins[0]; -} - -/* win_delete - delete a window created by win_new. - */ -void -win_delete(W *w) -{ - assert(w >= wins); - assert(w < wins+nwins); - nwins = 0; -} - -/* win_resize_frame - called when the whole frame - * is resized. - */ -void -win_resize_frame(int w, int h) -{ - GColor white = { 255, 255, 255 }; - int x, ww; - W *pw; - - if (w!=0 && h!=0) { - fwidth = w; - fheight = h; - } - - for (x=0, pw=wins; pw-wins<nwins; pw++) { - pw->height = fheight; - ww = (fwidth * pw->vfrac) / FScale; - g->movewin(pw->gw, x, 0, ww, fheight); - g->drawrect(pw->gw, 0, 0, ww, fheight, white); - draw(pw); - g->putwin(pw->gw); - x += ww; - } -} - -/* win_redraw_frame - redraw the whole frame. - */ -void -win_redraw_frame() -{ - win_resize_frame(0, 0); -} - -/* win_scroll - scroll the window by [n] lines. - * If [n] is negative it will scroll backwards. - * The algorithm is guaranteed to work properly - * when RingSize is larger than the number of - * lines on a screen. In any cases, it should - * not crash. - */ -void -win_scroll(W *w, int n) -{ - - struct lineinfo li; - unsigned start, bol, eol; - int dir; - - if (n == 0) - return; - - dir = n; - li.cul = -1; - - if (n < 0) { - start = w->start; - do { - int top; - - if (start == 0) - /* already at the top */ - break; - bol = buf_bol(w->b, start-1); - - li.beg = li.len = 0; - lineinfo(w, bol, &li, FocusEol); - top = li.len - 1; - for (; n<0; top--) { - if (top < 0) { - /* move to prev line */ - start = bol; - n++; - break; - } - start = li.sl[(li.beg + top) % RingSize]; - if (start < w->start) - n++; - } - } while (n<0); - w->start = start; - } else { - start = w->start; - do { - int top; - - li.beg = li.len = 0; - eol = lineinfo(w, start, &li, FocusBol); - top = 0; - for (; n>0; top++, n--) { - if (top >= li.len) { - /* move to next line */ - start = eol; - n--; - break; - } - start = li.sl[(li.beg + top) % RingSize]; - } - } while (n>0); - w->start = start; - } -} - -/* win_show_cursor - find the cursor in [w] and adjust - * the text view so that the cursor is displayed on the - * screen. Depending on [where], the cursor will be - * displayed at the top or at the bottom of the screen. - */ -void -win_show_cursor(W *w, enum CursorPos where) -{ - // XXX implement me -} - -/* static functions */ - -typedef int (*LineFn)(void *data, unsigned off, Rune r, int x, int rw, int sl); - -static unsigned -line(W *w, unsigned off, LineFn f, void *data) -{ - Rune r; - int l, x, rw; - - x = 0; - l = 0; - - for (;; off++) { - r = buf_get(w->b, off); - if (r == NORUNE) - break; - if (r == '\n') { - off++; - break; - } - - if (r == '\t') { - int tw; - - tw = TabWidth * font.width; - rw = tw - x % tw; - } else - rw = g->textwidth(&r, 1); - - if (x+rw > w->gw->w) - if (x != 0) { /* force progress */ - x = 0; - l++; - } - - if (!f(data, off, r, x, rw, l)) { - off++; - break; - } - - x += rw; - } - - return off; -} - -/* aggregate all calls to [drawtext] into batches, it - * will flush if the current character is \n or \t. - */ -static void -pushrune(GWin *gw, Rune r, int x, int y, int w, int cu) -{ - static int fragx = -1, fragy, cx = -1, cy, cw; - static Rune frag[MaxWidth], *p = frag; - GColor color = { .blue = 255 }, - xor = { .x = 1 }; - - assert(r == '\n' || fragx == -1 || y == fragy); - - if (fragx == -1) { - fragx = x; - fragy = y; - } - - if (cu) { - cx = x; - cy = y - font.ascent; - cw = w; - } - - if (r == '\t' || r == '\n') { -#if 0 - printf("flushing: fragx = %d\n" - " fragy = %d\n" - " r = %u\n" - " len = %td\n", - fragx, fragy, r, p-frag); -#endif - assert(fragx != -1); - g->drawtext(gw, frag, p-frag, fragx, fragy, color); - if (cx != -1) - g->drawrect(gw, cx, cy, cw, font.height, xor); - - fragx = cx = -1; - p = frag; - return; - } - - assert(p-frag < MaxWidth); - *p++ = r; -} - -struct dstatus { - W *w; - int begl, curl; - unsigned stop; -}; - -/* to be called as a LineFn by the [line] function */ -static int -drawfn(void *data, unsigned off, Rune r, int x, int rw, int sl) -{ - int y; - struct dstatus *ds = data; - - y = (ds->begl + sl) * font.height + font.ascent; - if (y > ds->w->height) { - ds->stop = off; - return 0; - } - - if (ds->curl != sl) { /* need a flush, we changed screen line */ - assert(x == 0); - pushrune(ds->w->gw, '\n', 0, 0, 0, 0); - ds->curl = sl; - } - - pushrune(ds->w->gw, r, x, y, rw, off == ds->w->cu); - return 1; -} - -static void -draw(W *w) -{ - unsigned boff, eoff; - struct dstatus ds; - - ds.w = w; - ds.begl = 0; - ds.curl = 0; - ds.stop = -1; - eoff = w->start; - - do { - boff = eoff; - eoff = line(w, boff, drawfn, &ds); - pushrune(w->gw, '\n', 0, 0, 0, 0); /* flush */ - ds.begl += ds.curl + 1; - } while (ds.stop == -1u && eoff != boff); - - if (eoff == boff) - w->stop = eoff; - else - w->stop = ds.stop; -} - -static void -pushoff(struct lineinfo *li, unsigned off) -{ - assert(li->len <= RingSize); - - if (li->len == RingSize) { - li->sl[li->beg] = off; - li->beg++; - li->beg %= RingSize; - if (li->cul != -1) - li->cul--; - } else { - int n; - - n = (li->beg + li->len) % RingSize; - li->sl[n] = off; - li->len++; - } -} - -struct lstatus { - enum Focus f; - unsigned cu; - struct lineinfo *li; - int curl; -}; - -static int -lineinfofn(void *data, unsigned off, - __attribute__((unused)) Rune r, - __attribute__((unused)) int x, - __attribute__((unused)) int rw, - int sl) -{ - struct lstatus *ls = data; - - if (ls->curl != sl) { - assert(ls->curl == sl-1); - - if (ls->f == FocusEol - || (ls->f == FocusBol && ls->li->len < RingSize) - || (ls->f == FocusCu && ls->li->cul == -1)) - pushoff(ls->li, off); - - ls->curl = sl; - } - - if (ls->f == FocusCu && off == ls->cu) - ls->li->cul = ls->li->len - 1; - - return 1; -} - -/* the api is not yet perfect: we should be able to specify - * a maximum offset that makes lineinfofn return 0 to block - * the line function - */ -static unsigned -lineinfo(W *w, unsigned off, struct lineinfo *li, enum Focus f) -{ - struct lstatus ls; - - ls.f = f; - ls.cu = w->cu; - ls.li = li; - ls.curl = 0; - - return line(w, off, lineinfofn, &ls); -} - -#ifdef WIN_TEST -/* test */ - -#include <stdlib.h> - -void die(char *m) { exit(1); } - -int main() -{ - GEvent e; - Buf *b; - W *w; - enum CursorPos cpos; - unsigned char s[] = - "je suis\n" - "\tQuentin\n" - "tab\ttest\n" - "une longue longue longue longue longue longue longue longue longue longue longue longue longue ligne\n" - "un peu d'unicode: ä æ ç\n" - "et voila!\n"; - - b = buf_new("*"); - win_init(&gui_x11); - w = win_new(b); - - for (int i=0; i<20; i++) - buf_ins_utf8(b, 0, s, sizeof s - 1); - - do { - g->nextevent(&e); - if (e.type == GResize) - win_resize_frame(e.resize.width, e.resize.height); - if (e.type == GKey) { - switch (e.key) { - case 'l': ++w->cu; cpos = Bot; break; - case 'h': --w->cu; cpos = Top; break; - case 'e'-'a' + 1: win_scroll(w, 1); break; - case 'y'-'a' + 1: win_scroll(w, -1); break; - default: continue; - } - win_redraw_frame(); - } - } while (e.type != GKey || e.key != 'q'); - - g->fini(); - return 0; -} - -#endif diff --git a/old/win-ugly.c b/old/win-ugly.c deleted file mode 100644 index ea37ef5..0000000 --- a/old/win-ugly.c +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef WIN_H -#define WIN_H - -#include "unicode.h" -#include "buf.h" -#include "gui.h" - -enum { - FScale = 16384, /* fixed point scale */ - TabWidth = 8, /* tabulation width */ - MaxLines = 1000, /* max number of lines on screen */ - MaxWidth = 500, /* max width of the screen */ -}; - -typedef struct w W; -struct w { - unsigned start, stop; /* offset of the first/last character displayed */ - unsigned coff; /* cursor offset */ - int cl; /* cursor line (on screen) */ - int nls; /* number of displayed lines on screen */ - int vfrac, height; /* vertical fraction and height of the window */ - Buf *b; /* underlying buffer object */ - GWin *gw; /* graphical window associated */ -}; - -void win_init(struct gui *g); -W *win_new(Buf *b); -void win_resize_frame(int w, int h); - -#endif /* ndef WIN_H */ diff --git a/old/win.c-1 b/old/win.c-1 deleted file mode 100644 index 004b39b..0000000 --- a/old/win.c-1 +++ /dev/null @@ -1,454 +0,0 @@ -/*% clang -DWIN_TEST -Wall -g -I/usr/include/freetype2 -lX11 -lXft obj/unicode.o obj/buf.o obj/x11.o % -o # - * - * Windowing module - */ - -#include <assert.h> -#include <string.h> - -#include "unicode.h" -#include "buf.h" -#include "gui.h" -#include "win.h" - -enum CursorPos { Top, Bot }; - -enum { RingSize = 2 }; /* bigger is (a bit) faster */ -_Static_assert(RingSize >= 2, "RingSize must be at least 2"); - -struct lineinfo { - int beg, len; /* begining and len of the sl ring buffer */ - unsigned sl[RingSize]; /* ring buffer of screen line offsets */ -}; - -static void draw(W *w); -static void lineinfo(W *w, unsigned off, unsigned lim, struct lineinfo *li); - -static W wins[MaxWins]; -static int nwins; -static struct gui *g; -static GFont font; -static int fwidth, fheight; - -/* win_init - initialize the module using [gui] as a - * graphical backed. - */ -void -win_init(struct gui *gui) -{ - g = gui; - - g->init(); - g->getfont(&font); - - /* the gui module does not give a way to access the screen - * dimension, instead, the first event generated will always - * be a GResize, so we can adjust these dummy values with - * win_resize_frame - */ - fwidth = fheight = 10; -} - -/* win_new - insert a new window if possible and - * return it. In case of error (more than MaxWins - * windows), 0 is returned. - */ -W * -win_new(Buf *b) -{ - if (nwins!=0) - return 0; - - memset(&wins[nwins], 0, sizeof(W)); - wins[nwins].b = b; - wins[nwins].gw = g->newwin(0, 0, fwidth, fheight); - wins[nwins].vfrac = FScale; - - nwins = 1; - return &wins[0]; -} - -/* win_delete - delete a window created by win_new. - */ -void -win_delete(W *w) -{ - assert(w >= wins); - assert(w < wins+nwins); - nwins = 0; -} - -/* win_resize_frame - called when the whole frame - * is resized. - */ -void -win_resize_frame(int w, int h) -{ - GColor white = { 255, 255, 255 }; - int x, ww; - W *pw; - - if (w!=0 && h!=0) { - fwidth = w; - fheight = h; - } - - for (x=0, pw=wins; pw-wins<nwins; pw++) { - pw->height = fheight; - ww = (fwidth * pw->vfrac) / FScale; - g->movewin(pw->gw, x, 0, ww, fheight); - g->drawrect(pw->gw, 0, 0, ww, fheight, white); - draw(pw); - g->putwin(pw->gw); - x += ww; - } -} - -/* win_redraw_frame - redraw the whole frame. - */ -void -win_redraw_frame() -{ - win_resize_frame(0, 0); -} - -/* win_scroll - scroll the window by [n] lines. - * If [n] is negative it will scroll backwards. - */ -void -win_scroll(W *w, int n) -{ - - struct lineinfo li; - unsigned start, bol; - int dir; - - if (n == 0) - return; - - dir = n; - - if (n < 0) { - start = w->start; - do { - int top; - - if (start == 0) - /* already at the top */ - break; - bol = buf_bol(w->b, start-1); - - li.beg = li.len = 0; - lineinfo(w, bol, start-1, &li); - top = li.len - 2; - assert(top >= 0); - for (; n<0 && top>=0; top--, n++) { - start = li.sl[(li.beg + top) % RingSize]; - assert(start < w->start); - } - } while (n<0); - w->start = start; - } else { - start = w->start; - do { - int top; - - li.beg = li.len = 0; - lineinfo(w, start, -1, &li); - top = 1; - assert(top < li.len); - for (; n>0 && top<li.len; top++, n--) { - start = li.sl[(li.beg + top) % RingSize]; - assert(start > w->start); - } - } while (n>0); - w->start = start; - } -} - -/* win_show_cursor - find the cursor in [w] and adjust - * the text view so that the cursor is displayed on the - * screen. Depending on [where], the cursor will be - * displayed at the top or at the bottom of the screen. - */ -void -win_show_cursor(W *w, enum CursorPos where) -{ - struct lineinfo li; - unsigned bol; - - bol = buf_bol(w->b, w->cu); - li.beg = li.len = 0; - lineinfo(w, bol, w->cu, &li); - assert(li.len >= 2); - w->start = li.sl[(li.beg + li.len-2) % RingSize]; - if (where == Bot) - win_scroll(w, -w->height/font.height + 1); -} - -/* static functions */ - -typedef int (*LineFn)(void *data, unsigned off, Rune r, int x, int rw, int sl); - -static unsigned -line(W *w, unsigned off, LineFn f, void *data) -{ - Rune r; - int l, x, rw; - - x = 0; - l = 0; - - for (;; off++) { - r = buf_get(w->b, off); - if (r == NORUNE) - break; - if (r == '\n') { - off++; - break; - } - - if (r == '\t') { - int tw; - - tw = TabWidth * font.width; - rw = tw - x % tw; - } else - rw = g->textwidth(&r, 1); - - if (x+rw > w->gw->w) - if (x != 0) { /* force progress */ - x = 0; - l++; - } - - if (!f(data, off, r, x, rw, l)) - break; - - x += rw; - } - - return off; -} - -/* aggregate all calls to [drawtext] into batches, it - * will flush if the current character is \n or \t. - */ -static void -pushrune(GWin *gw, Rune r, int x, int y, int w, int cu) -{ - static int fragx = -1, fragy, cx = -1, cy, cw; - static Rune frag[MaxWidth], *p = frag; - GColor color = { .blue = 255 }, - xor = { .x = 1 }; - - assert(r == '\n' || fragx == -1 || y == fragy); - - if (fragx == -1) { - fragx = x; - fragy = y; - } - - if (cu) { - cx = x; - cy = y - font.ascent; - cw = w; - } - - if (r == '\t' || r == '\n') { -#if 0 - printf("flushing: fragx = %d\n" - " fragy = %d\n" - " r = %u\n" - " len = %td\n" - " frag = '", - fragx, fragy, r, p-frag); - for (int i=0; i<p-frag; i++) - printf("%c", (char)frag[i]); - printf("'\n"); -#endif - assert(fragx != -1); - g->drawtext(gw, frag, p-frag, fragx, fragy, color); - if (cx != -1) - g->drawrect(gw, cx, cy, cw, font.height, xor); - - fragx = cx = -1; - p = frag; - return; - } - - assert(p-frag < MaxWidth); - *p++ = r; -} - -struct dstatus { - W *w; - int begl, curl; -}; - -/* to be called as a LineFn by the [line] function */ -static int -drawfn(void *data, unsigned off, Rune r, int x, int rw, int sl) -{ - int y; - struct dstatus *ds = data; - - y = (ds->begl + sl) * font.height + font.ascent; - if (y + font.descent > ds->w->height) - return 0; - - if (ds->curl != sl) { /* need a flush, we changed screen line */ - assert(x == 0); - ds->curl = sl; - pushrune(ds->w->gw, '\n', 0, 0, 0, 0); - } - - pushrune(ds->w->gw, r, x, y, rw, off == ds->w->cu); - return 1; -} - -static void -draw(W *w) -{ - int nls; - unsigned off; - struct dstatus ds; - - ds.w = w; - ds.begl = 0; - ds.curl = 0; - off = w->start; - nls = w->height/font.height; - - do { - off = line(w, off, drawfn, &ds); - pushrune(w->gw, '\n', 0, 0, 0, 0); /* flush */ - ds.begl += ds.curl + 1; - ds.curl = 0; - } while (ds.begl < nls); - - w->stop = off; -} - -static int -pushoff(struct lineinfo *li, unsigned off, int overwrite) -{ - assert(li->len <= RingSize); - - if (li->len == RingSize) { - if (!overwrite) - return 0; - li->sl[li->beg] = off; - li->beg++; - li->beg %= RingSize; - } else { - int n; - - n = (li->beg + li->len) % RingSize; - li->sl[n] = off; - li->len++; - } - return 1; -} - -struct lstatus { - unsigned lim; - struct lineinfo *li; - int curl; -}; - -static int -lineinfofn(void *data, unsigned off, - __attribute__((unused)) Rune r, - __attribute__((unused)) int x, - __attribute__((unused)) int rw, - int sl) -{ - struct lstatus *ls = data; - - if (off > ls->lim) - return 0; - - if (ls->curl != sl) { - assert(ls->curl == sl-1); - ls->curl = sl; - return pushoff(ls->li, off, ls->lim != -1u); - } - - return 1; -} - -/* if [lim == -1] the lineinfo will only contain information - * about the first RingSize screen lines - */ -static void -lineinfo(W *w, unsigned off, unsigned lim, struct lineinfo *li) -{ - struct lstatus ls; - - assert(RingSize >= 2); - - ls.lim = lim; - ls.li = li; - ls.curl = 0; - - pushoff(li, off, lim != -1u); - off = line(w, off, lineinfofn, &ls); - pushoff(li, off, lim != -1u); -} - -#ifdef WIN_TEST -/* test */ - -#include <stdlib.h> - -void die(char *m) { exit(1); } - -int main() -{ - GEvent e; - Buf *b; - W *w; - enum CursorPos cpos; - unsigned char s[] = - "je suis\n" - "\tQuentin\n" - "tab\ttest\n" - "une longue longue longue longue longue longue longue longue longue longue longue longue longue ligne\n" - "un peu d'unicode: ä æ ç\n" - "et voila!\n\n"; - - b = buf_new("*"); - win_init(&gui_x11); - w = win_new(b); - - for (int i=0; i<20; i++) - buf_ins_utf8(b, 0, s, sizeof s - 1); - - do { - g->nextevent(&e); - if (e.type == GResize) - win_resize_frame(e.resize.width, e.resize.height); - if (e.type == GKey) { - switch (e.key) { - case 'l': ++w->cu; cpos = Bot; break; - case 'h': --w->cu; cpos = Top; break; - case 'e'-'a' + 1: win_scroll(w, 1); break; - case 'y'-'a' + 1: win_scroll(w, -1); break; - default: continue; - } - win_redraw_frame(); - if (e.key == 'l' || e.key == 'h') - if (w->cu < w->start || w->cu >= w->stop) { - win_show_cursor(w, cpos); - win_redraw_frame(); - } - - } - } while (e.type != GKey || e.key != 'q'); - - g->fini(); - return 0; -} - -#endif diff --git a/old/win.c-2 b/old/win.c-2 deleted file mode 100644 index bc6d712..0000000 --- a/old/win.c-2 +++ /dev/null @@ -1,449 +0,0 @@ -/*% clang -DWIN_TEST -Wall -g $(pkg-config --libs x11 xft) obj/{unicode,buf,x11}.o % -o # - * - * Windowing module - */ - -#include <assert.h> -#include <string.h> - -#include "tools.h" -#include "unicode.h" -#include "buf.h" -#include "gui.h" -#include "win.h" - -enum { - RingSize = 2, /* bigger is (a bit) faster */ -}; -static_assert(RingSize >= 2, "too small"); - -struct lineinfo { - int beg, len; - unsigned sl[RingSize]; /* screen line offsets */ -}; - -static void draw(W *w); -static void lineinfo(W *w, unsigned off, unsigned lim, struct lineinfo *li); - -static W wins[MaxWins]; -static int nwins; -static struct gui *g; -static GFont font; -static int fwidth, fheight; - -/* win_init - Initialize the module using [gui] as a - * graphical backed. - */ -void -win_init(struct gui *gui) -{ - g = gui; - - g->init(); - g->getfont(&font); - - /* the gui module does not give a way to access the screen - * dimension, instead, the first event generated will always - * be a GResize, so we can adjust these dummy values with - * win_resize_frame - */ - fwidth = fheight = 10; -} - -/* win_new - Insert a new window if possible and - * return it. In case of error (more than MaxWins - * windows), 0 is returned. - */ -W * -win_new(Buf *b) -{ - if (nwins!=0) - return 0; - - memset(&wins[nwins], 0, sizeof(W)); - wins[nwins].b = b; - wins[nwins].gw = g->newwin(0, 0, fwidth, fheight); - wins[nwins].vfrac = FScale; - - nwins = 1; - return &wins[0]; -} - -/* win_delete - Delete a window created by win_new. - */ -void -win_delete(W *w) -{ - assert(w >= wins); - assert(w < wins+nwins); - nwins = 0; -} - -/* win_resize_frame - Called when the whole frame - * is resized. - */ -void -win_resize_frame(int w, int h) -{ - GColor white = { 255, 255, 255 }; - int x, ww; - W *pw; - - if (w!=0 && h!=0) { - fwidth = w; - fheight = h; - } - - for (x=0, pw=wins; pw-wins<nwins; pw++) { - pw->height = fheight; - ww = (fwidth * pw->vfrac) / FScale; - g->movewin(pw->gw, x, 0, ww, fheight); - g->drawrect(pw->gw, 0, 0, ww, fheight, white); - draw(pw); - g->putwin(pw->gw); - x += ww; - } -} - -/* win_redraw_frame - Redraw the whole frame. - */ -void -win_redraw_frame() -{ - win_resize_frame(0, 0); -} - -/* win_scroll - Scroll the window by [n] lines. - * If [n] is negative it will scroll backwards. - */ -void -win_scroll(W *w, int n) -{ - - struct lineinfo li; - unsigned start, bol; - int dir; - - if (n == 0) - return; - - dir = n; // XXX this is for cursor handling, do we do this here? - - if (n < 0) { - start = w->start; - do { - int top; - - if (start == 0) - /* already at the top */ - break; - bol = buf_bol(w->b, start-1); - - li.beg = li.len = 0; - lineinfo(w, bol, start-1, &li); - top = li.len - 2; - assert(top >= 0); - for (; n<0 && top>=0; top--, n++) { - start = li.sl[(li.beg + top) % RingSize]; - assert(start < w->start); - } - } while (n<0); - w->start = start; - } else { - start = w->start; - do { - int top; - - li.beg = li.len = 0; - lineinfo(w, start, -1, &li); - top = 1; - assert(top < li.len); - for (; n>0 && top<li.len; top++, n--) { - start = li.sl[(li.beg + top) % RingSize]; - assert(start > w->start - || buf_get(w->b, w->start) == '\n'); // change this to test size XXX - } - } while (n>0); - w->start = start; - } -} - -/* win_show_cursor - Find the cursor in [w] and adjust - * the text view so that the cursor is displayed on the - * screen. Depending on [where], the cursor will be - * displayed at the top or at the bottom of the screen. - */ -void -win_show_cursor(W *w, enum CursorLoc where) -{ - struct lineinfo li; - unsigned bol; - - bol = buf_bol(w->b, w->cu); - li.beg = li.len = 0; - lineinfo(w, bol, w->cu, &li); - assert(li.len >= 2); - w->start = li.sl[(li.beg + li.len-2) % RingSize]; - if (where == CBot) - win_scroll(w, -w->height/font.height + 1); -} - -/* static functions */ - -typedef int LineFn(void *data, unsigned off, Rune r, int x, int rw, int sl); - -static unsigned -line(W *w, unsigned off, LineFn f, void *data) -{ - Rune r; - int l, x, rw; - - r = 0; - l = 0; - x = 0; - - for (; r != '\n'; x+=rw, off++) { - r = buf_get(w->b, off); - - if (r == '\t') { - int tw; - - tw = TabWidth * font.width; - rw = tw - x % tw; - } else if (r == '\n') { - rw = 0; - } else - rw = g->textwidth(&r, 1); - - if (x+rw > w->gw->w) - if (x != 0) { /* force progress */ - x = 0; - l++; - } - - if (!f(data, off, r, x, rw, l)) - break; - } - - return off; -} - -/* aggregate all calls to [drawtext] into batches, it - * will flush if the current character is \n or \t. - */ -static void -pushrune(GWin *gw, Rune r, int x, int y, int w, int cu) -{ - static int fragx = -1, fragy, cx = -1, cy, cw; - static Rune frag[MaxWidth], *p = frag; - GColor color = { .blue = 255 }, - xor = { .x = 1 }; - - assert(r == '\n' || fragx == -1 || y == fragy); - - if (fragx == -1) { - fragx = x; - fragy = y; - } - - if (cu) { - cx = x; - cy = y - font.ascent; - cw = w ? w : 4; - } - - if (r == '\t' || r == '\n') { -#if 0 - printf("flushing: fragx = %d\n" - " fragy = %d\n" - " r = %u\n" - " len = %td\n" - " frag = '", - fragx, fragy, r, p-frag); - for (int i=0; i<p-frag; i++) - printf("%c", (char)frag[i]); - printf("'\n"); -#endif - assert(fragx != -1); - g->drawtext(gw, frag, p-frag, fragx, fragy, color); - if (cx != -1) - g->drawrect(gw, cx, cy, cw, font.height, xor); - - fragx = cx = -1; - p = frag; - return; - } - - assert(p-frag < MaxWidth); - *p++ = r; -} - -struct dstatus { - W *w; - int begl, curl; -}; - -static int -drawfn(void *data, unsigned off, Rune r, int x, int rw, int sl) -{ - int y; - struct dstatus *ds = data; - - y = (ds->begl + sl) * font.height + font.ascent; - - if (ds->curl != sl) { /* need a flush, we changed screen line */ - assert(x == 0); - ds->curl = sl; - pushrune(ds->w->gw, '\n', 0, 0, 0, 0); - if (y + font.descent > ds->w->height) - return 0; - } - - pushrune(ds->w->gw, r, x, y, rw, off == ds->w->cu); - return 1; -} - -static void -draw(W *w) -{ - int nls; - unsigned off; - struct dstatus ds; - - ds.w = w; - ds.begl = 0; - ds.curl = 0; - off = w->start; - nls = w->height/font.height; - - do { - off = line(w, off, drawfn, &ds); - ds.begl += ds.curl + 1; - ds.curl = 0; - } while (ds.begl < nls); - - w->stop = off; -} - -static int -pushoff(struct lineinfo *li, unsigned off, int overwrite) -{ - assert(li->len <= RingSize); - - if (li->len == RingSize) { - if (!overwrite) - return 0; - li->sl[li->beg] = off; - li->beg++; - li->beg %= RingSize; - } else { - int n; - - n = (li->beg + li->len) % RingSize; - li->sl[n] = off; - li->len++; - } - return 1; -} - -struct lstatus { - unsigned lim; - struct lineinfo *li; - int curl; -}; - -static int -lineinfofn(void *data, unsigned off, Rune r, int x, int rw, int sl) -{ - struct lstatus *ls = data; - - unused(r); - unused(x); - unused(rw); - - if (off > ls->lim) - return 0; - - if (ls->curl != sl) { - assert(ls->curl == sl-1); - ls->curl = sl; - return pushoff(ls->li, off, ls->lim != -1u); - } - - return 1; -} - -/* if [lim == -1] the lineinfo will only contain information - * about the first RingSize screen lines - */ -static void -lineinfo(W *w, unsigned off, unsigned lim, struct lineinfo *li) -{ - struct lstatus ls; - - assert(RingSize >= 2); - - ls.lim = lim; - ls.li = li; - ls.curl = 0; - - pushoff(li, off, lim != -1u); - off = line(w, off, lineinfofn, &ls); - pushoff(li, off, lim != -1u); -} - -#ifdef WIN_TEST -/* test */ - -#include <stdlib.h> - -void die(char *m) { exit(1); } - -int main() -{ - GEvent e; - Buf *b; - W *w; - enum culoc cloc; - unsigned char s[] = - "je suis\n" - "\tQcar\n" - "tab\ttest\n" - "une longue longue longue longue longue longue longue longue longue longue longue longue longue ligne\n" - "un peu d'unicode: ä æ ç\n" - "et voila!\n\n"; - - b = buf_new("*"); - win_init(&gui_x11); - w = win_new(b); - - for (int i=0; i<5; i++) - buf_ins_utf8(b, 0, s, sizeof s - 1); - - do { - g->nextevent(&e); - if (e.type == GResize) - win_resize_frame(e.resize.width, e.resize.height); - if (e.type == GKey) { - switch (e.key) { - case 'l': ++w->cu; cloc = CBot; break; - case 'h': --w->cu; cloc = CTop; break; - case 'e'-'a' + 1: win_scroll(w, 1); break; - case 'y'-'a' + 1: win_scroll(w, -1); break; - default: continue; - } - win_redraw_frame(); - if (e.key == 'l' || e.key == 'h') - if (w->cu < w->start || w->cu >= w->stop) { - win_show_cursor(w, cloc); - win_redraw_frame(); - } - - } - } while (e.type != GKey || e.key != 'q'); - - g->fini(); - return 0; -} - -#endif diff --git a/old/xmess/.comfile b/old/xmess/.comfile deleted file mode 100644 index b103278..0000000 --- a/old/xmess/.comfile +++ /dev/null @@ -1 +0,0 @@ -win.c diff --git a/old/xmess/gui.h b/old/xmess/gui.h deleted file mode 100644 index d1abe04..0000000 --- a/old/xmess/gui.h +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef GUI_H -#define GUI_H -/* GUI module definition */ - -#include "unicode.h" - -typedef struct gcolor GColor; -typedef struct gfont GFont; -typedef struct gwin GWin; -typedef struct gevent GEvent; - -enum { - MaxWins = 9, -}; - -struct gcolor { - unsigned char red; - unsigned char green; - unsigned char blue; - unsigned char x; -}; - -struct gfont { - void *data; - int ascent; - int descent; - int width; - int height; -}; - -struct gwin { - int x, y; - int w, h; -}; - -struct gevent { - enum { - GResize, - GKey, - GButPress, - GButRelease, - } type; - - union { - struct { - int width; - int height; - } resize; - Rune key; - enum { - GBLeft, - GBMiddle, - GBRight, - GBWheelUp, - GBWheelDown, - } button; - }; -}; - -enum { - GKEsc = 0x1b, - - GKF1 = 0xe001, /* unicode private use area */ - GKF2, - GKF3, - GKF4, - GKF5, - GKF6, - GKF7, - GKF8, - GKF9, - GKF10, - GKF11, - GKF12, - GKLeft, - GKRight, - GKUp, - GKDown, - GKPageUp, - GKPageDown, - GKBackspace, -}; - -struct gui { - void (*init)(void); - void (*fini)(void); - void (*getfont)(GFont *fret); - GWin *(*newwin)(int x, int y, int w, int h); - void (*movewin)(GWin *gw, int x, int y, int w, int h); - void (*delwin)(GWin *gw); - void (*drawtext)(GWin *gw, Rune *str, int len, - int x, int y, GColor color); - void (*drawrect)(GWin *gw, int x, int y, int w, int h, GColor c); - void (*putwin)(GWin *gw); - int (*textwidth)(Rune *str, int len); - void (*nextevent)(GEvent *eret); -}; - -/* Available gui modules */ -extern struct gui gui_x11; - -#endif /* ndef GUI_H */ diff --git a/old/xmess/win.c b/old/xmess/win.c deleted file mode 100644 index b56ad77..0000000 --- a/old/xmess/win.c +++ /dev/null @@ -1,401 +0,0 @@ -/*% clang -DWIN_TEST -Wall -g -I/usr/include/freetype2 -lX11 -lXft obj/unicode.o obj/buf.o obj/x11.o % -o # - * - * Windowing module - */ - -#include <assert.h> -#include <string.h> - -#include "unicode.h" -#include "buf.h" -#include "gui.h" -#include "win.h" - -enum CursorPos { - Top, - Bot, -}; - -enum { - Draw = 1, - Line = 2, - BLine = 4 | Line, - ELine = 8 | Line, - CLine = 16 | Line, -}; - -static void put(W *w, int flags); - -static W wins[MaxWins]; -static int nwins; -static struct gui *g; -static GFont font; -static int fwidth, fheight; - -/* win_init - initialize the module using [gui] as a - * graphical backed. - */ -void -win_init(struct gui *gui) -{ - g = gui; - - g->init(); - g->getfont(&font); - - /* the gui module does not give a way to access the screen - * dimension, instead, the first event generated will always - * be a GResize, so we can adjust these dummy values with - * win_resize_frame - */ - fwidth = fheight = 10; -} - -/* win_new - insert a new window if possible and - * return it. In case of error (more than MaxWins - * windows), 0 is returned. - */ -W * -win_new(Buf *b) -{ - if (nwins!=0) - return 0; - - memset(&wins[nwins], 0, sizeof(W)); - wins[nwins].b = b; - wins[nwins].gw = g->newwin(0, 0, fwidth, fheight); - wins[nwins].vfrac = FScale; - - nwins = 1; - return &wins[0]; -} - -/* win_delete - delete a window created by win_new. - */ -void -win_delete(W *w) -{ - assert(w >= wins); - assert(w < wins+nwins); - nwins = 0; -} - -/* win_resize_frame - called when the whole frame - * is resized. - */ -void -win_resize_frame(int w, int h) -{ - GColor white = { 255, 255, 255 }; - int x, ww; - W *pw; - - if (w!=0 && h!=0) { - fwidth = w; - fheight = h; - } - - for (x=0, pw=wins; pw-wins<nwins; pw++) { - pw->height = fheight / font.height; - ww = (fwidth * pw->vfrac) / FScale; - g->movewin(pw->gw, x, 0, ww, fheight); - g->drawrect(pw->gw, 0, 0, ww, fheight, white); - put(pw, Draw); - g->putwin(pw->gw); - x += ww; - } -} - -/* win_redraw_frame - redraw the whole frame. - */ -void -win_redraw_frame(void) -{ - win_resize_frame(0, 0); -} - -/* win_scroll - scroll the window by [n] lines. - * If [n] is negative it will scroll backwards. - * The number of lines scrolled must not be - * bigger than the number of lines currently on - * the screen. - */ -void -win_scroll(W *w, int n) -{ - int top; - unsigned off, bol; - W wscratch; - - if (w->nls == 0 || n == 0) - return; - - assert(n < 0 || n <= w->nls); - - wscratch.b = w->b; - wscratch.gw = w->gw; - - if (n<0) { - off = w->loff[0]; - - do { - if (off == 0) - break; - - bol = buf_bol(w->b, off-1); - wscratch.loff[0] = bol; - put(&wscratch, ELine); - - top = wscratch.nls - 1; - do { - off = wscratch.loff[top--]; - if (off < w->loff[0]) - ++n; - } while (off >= w->loff[0] || (top>=0 && n<0)); - } while (n<0); - } else - off = w->loff[n]; - - w->loff[0] = off; - put(w, 0); /* update line offsets */ - - if (w->cl == -1) { /* fix the cursor position */ - if (n>0) - w->cl = 0; - else - w->cl = w->nls-1; - w->coff = w->loff[w->cl]; - } -} - -/* win_show_cursor - find the cursor in [w] and adjust - * the text view so that the cursor is displayed on the - * screen. Depending on [where], the cursor will be - * displayed at the top or at the bottom of the screen. - */ -void -win_show_cursor(W *w, enum CursorPos where) -{ - unsigned bol; - W wscratch; - - wscratch.b = w->b; - wscratch.gw = w->gw; - wscratch.coff = w->coff; - - bol = buf_bol(w->b, w->coff); - wscratch.loff[0] = bol; - - put(&wscratch, CLine); /* find cursor line */ - assert(wscratch.cl < wscratch.nls); - assert(wscratch.cl >= 0); - - w->loff[0] = wscratch.loff[wscratch.cl]; - - put(w, 0); - if (where == Bot) - win_scroll(w, -w->height + 1); -} - -/* static functions */ - - -/* this function tries to factor calls to the pretty expensive - * [drawtext] function of the gui module, we basically try to aggregate - * all potential calls into one. Sometimes it is necessary to flush, - * for instance when the are displaying a new line or when a tabulation - * has to be printed. Tabs are treated specially because they have - * a width the drawtext function does not know a priori. - * - * Calling this function with [r == NORUNE] will force a flush. - * - * Before using this I called drawtext for each char, on a big screen - * the slowdown was significative. - */ -static void -draw(GWin *gw, Rune r, int x, int y, int rw, int cu) -{ - static int fragx = -1, fragy, cx = -1, cy, cw; - static Rune frag[MaxWidth], *p = frag; - int flush; - GColor color = { .blue = 255 }, - xor = { .x = 1 }; - - flush = 0; - - if (r != NORUNE && fragx == -1) { - fragx = x; - fragy = y; - } - - if (r != NORUNE && y == fragy) { - if (cu) { - cx = x; - cy = y-font.ascent; - cw = rw; - } - - if (r != '\t') { - assert(p-frag < MaxWidth); - *p++ = r; - } else - flush = 1; - } else - flush = 1; - - /* we flush the current fragment if one - * of the following conditions is met - * - the current rune is a tab - * - the current rune is a NORUNE (signaling eof) - * - the rune's y is different from the fragment's y - * (signaling a newline) - */ - if (flush) { -#if 0 - printf("flushing: fragx = %d\n" - " fragy = %d\n" - " r = %u\n" - " len = %zd\n", - fragx, fragy, r, p-frag); -#endif - if (fragx == -1) - return; - - g->drawtext(gw, frag, p-frag, fragx, fragy, color); - if (cx != -1) - g->drawrect(gw, cx, cy, cw, font.height, xor); - - fragx = cx = -1; - p = frag; - - if (r != NORUNE && r != '\n' && fragy != y) - /* push r on frag with a recursive call */ - draw(gw, r, x, y, rw, cu); - } -} - -static void -put(W *w, int flags) -{ - unsigned off, i, nl; - int rw, x, y, lnum; - Rune r; - GWin *gw; - - off = w->loff[0]; - gw = w->gw; - x = 0; - y = font.ascent; - lnum = 0; - w->loff[lnum++] = off; - w->cl = -1; - - for (i=0; y < gw->h || (flags & Line); i++) { - r = buf_get(w->b, off+i); - if (r == NORUNE) { - lnum++; - break; - } - - if (w->coff == off+i) - w->cl = lnum - 1; - - if (r == '\t') { - rw = TabWidth * font.width; - rw -= x % (TabWidth * font.width); - } else { - nl = 0; - if (r != '\n') { - if (unicode_rune_width(r) == 0) - continue; - rw = g->textwidth(&r, 1); - if (x+rw > gw->w) - nl = off+i; - } else if ((flags & Line) == 0) { - nl = off+i+1; - rw = 0; - } else { - lnum++; - break; - } - - if (nl) { - y += font.height; - x = 0; - if (lnum < MaxLines) - w->loff[lnum++] = nl; - else if ((flags & ELine) - || ((flags & CLine) && w->cl == -1)) { - /* should use a ring buffer... */ - assert(lnum == MaxLines); - memmove(w->loff, w->loff+1, - (MaxLines-1) * sizeof(int)); - w->loff[MaxLines-1] = nl; - } - } - } - - if (flags & Draw) - draw(gw, r, x, y, rw, w->coff == off+i); - - x += rw; - } - - if (flags & Draw) - draw(gw, NORUNE, 0, 0, 0, 0); - w->nls = lnum - 1; -} - -#ifdef WIN_TEST -/* test */ - -#include <stdlib.h> - -void die(char *m) { exit(1); } - -int main(void) -{ - GEvent e; - Buf *b; - W *w; - enum CursorPos cpos; - unsigned char s[] = - "je suis\n" - "\t\tQuentin\n" - "tab\ttest\n" - "une longue longue longue longue longue longue longue longue longue longue longue longue longue ligne\n" - "un peu d'unicode: ä æ ç\n" - "et voila!\n"; - - b = buf_new("*"); - win_init(&gui_x11); - w = win_new(b); - - for (int i=0; i<20; i++) - buf_ins_utf8(b, 0, s, sizeof s - 1); - - do { - g->nextevent(&e); - if (e.type == GResize) - win_resize_frame(e.resize.width, e.resize.height); - if (e.type == GKey) { - switch (e.key) { - case 'l': ++w->coff; cpos = Bot; break; - case 'h': --w->coff; cpos = Top; break; - case 'e'-'a' + 1: win_scroll(w, 1); break; - case 'y'-'a' + 1: win_scroll(w, -1); break; - default: continue; - } - win_redraw_frame(); - if (w->cl == -1) { - win_show_cursor(w, cpos); - win_redraw_frame(); - } - } - } while (e.type != GKey || e.key != 'q'); - - g->fini(); - return 0; -} - -#endif diff --git a/old/xmess/win.h b/old/xmess/win.h deleted file mode 100644 index 296b5ce..0000000 --- a/old/xmess/win.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef WIN_H -#define WIN_H - -#include "unicode.h" -#include "buf.h" -#include "gui.h" - -enum { - FScale = 16384, /* fixed point scale */ - TabWidth = 8, /* tabulation width */ - MaxLines = 1000, /* max number of lines on screen */ - MaxWidth = 500, /* max width of the screen */ -}; - -typedef struct w W; -struct w { - unsigned loff[MaxLines]; - unsigned coff; - int cl; - int nls; - int vfrac, height; - Buf *b; - GWin *gw; -}; - -void win_init(struct gui *g); -W *win_new(Buf *b); -void win_resize_frame(int w, int h); - -#endif /* ndef WIN_H */ diff --git a/old/xmess/x11 b/old/xmess/x11 Binary files differdeleted file mode 100755 index 383049a..0000000 --- a/old/xmess/x11 +++ /dev/null diff --git a/old/xmess/x11.c b/old/xmess/x11.c deleted file mode 100644 index eda0047..0000000 --- a/old/xmess/x11.c +++ /dev/null @@ -1,357 +0,0 @@ -/* A GUI module for X11 */ - -#include <assert.h> -#include <stdio.h> -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <X11/Xft/Xft.h> - -#include "gui.h" - -void die(char *); - -#define FONTNAME "DejaVu Sans Mono:pixelsize=12" - -enum { - Width = 640, - Height = 480, -}; - -typedef struct xwin XWin; -struct xwin { - GWin gw; - Pixmap p; - XftDraw *xft; - int used; -}; - -static Display *d; -static Visual *visual; -static Colormap cmap; -static unsigned int depth; -static int screen; -static GC gc; -static XftFont *font; -static Window win; -static int w, h; -static XWin wins[MaxWins]; - -static void -init(void) -{ - XWindowAttributes wa; - XSetWindowAttributes swa; - XGCValues gcv; - Window root; - XConfigureEvent ce; - - d = XOpenDisplay(0); - if (!d) - die("cannot open display"); - root = DefaultRootWindow(d); - XGetWindowAttributes(d, root, &wa); - visual = wa.visual; - cmap = wa.colormap; - screen = DefaultScreen(d); - depth = DefaultDepth(d, screen); - - /* create the main window */ - win = XCreateSimpleWindow(d, root, 0, 0, Width, Height, 0, 0, - WhitePixel(d, screen)); - swa.backing_store = WhenMapped; - swa.bit_gravity = NorthWestGravity; - XChangeWindowAttributes(d, win, CWBackingStore|CWBitGravity, &swa); - XStoreName(d, win, "ED"); - XSelectInput(d, win, StructureNotifyMask|ButtonPressMask|KeyPressMask|ExposureMask); - - /* simulate an initial resize and map the window */ - ce.type = ConfigureNotify; - ce.width = Width; - ce.height = Height; - XSendEvent(d, win, False, StructureNotifyMask, (XEvent *)&ce); - XMapWindow(d, win); - - /* allocate font */ - font = XftFontOpenName(d, screen, FONTNAME); - if (!font) - die("cannot open default font"); - - /* initialize gc */ - gcv.foreground = WhitePixel(d, screen); - gcv.graphics_exposures = False; - gc = XCreateGC(d, win, GCForeground|GCGraphicsExposures, &gcv); -} - -static void -fini(void) -{ - XCloseDisplay(d); -} - -static void -getfont(GFont *ret) -{ - ret->data = font; - ret->ascent = font->ascent; - ret->descent = font->descent; - ret->width = font->max_advance_width; - ret->height = font->height; -} - -static void -movewin(GWin *gw, int x, int y, int w, int h) -{ - XWin *xw; - - gw->x = x; - gw->y = y; - if (gw->w == w & gw->h == h) - return; - - xw = (XWin *)gw; - gw->w = w; - gw->h = h; - if (xw->xft) { - XftDrawDestroy(xw->xft); - XFreePixmap(d, xw->p); - } - - xw->p = XCreatePixmap(d, win, w, h, depth); - xw->xft = XftDrawCreate(d, xw->p, visual, cmap); - XFillRectangle(d, xw->p, gc, 0, 0, w, h); -} - -static GWin * -newwin(int x, int y, int w, int h) -{ - int i; - XWin *xw; - - assert(w != 0 || h != 0); - - xw = 0; - for (i=0; i<MaxWins; i++) { - if (wins[i].used) - continue; - xw = &wins[i]; - break; - } - if (!xw) - return 0; - - xw->used = 1; - xw->gw.w = 0; - xw->gw.h = 0; - xw->xft = NULL; - movewin((GWin *)xw, x, y, w, h); - return (GWin *)xw; -} - -static void -delwin(GWin *gw) -{ - XWin *xw; - - xw = (XWin *)gw; - XftDrawDestroy(xw->xft); - XFreePixmap(d, xw->p); - xw->used = 0; -} - -static void -xftcolor(XftColor *xc, GColor c) -{ - xc->color.red = c.red << 8; - xc->color.green = c.green << 8; - xc->color.blue = c.blue << 8; - xc->color.alpha = 65535; - XftColorAllocValue(d, visual, cmap, &xc->color, xc); -} - -static void -drawtext(GWin *gw, Rune *str, int len, int x, int y, GColor c) -{ - XftColor col; - XWin *xw; - - xw = (XWin *)gw; - xftcolor(&col, c); - XftDrawString32(xw->xft, &col, font, x, y, (FcChar32 *)str, len); -} - -static void -drawrect(GWin *gw, int x, int y, int w, int h, GColor c) -{ - XWin *xw; - - xw = (XWin *)gw; - if (c.x) { - XGCValues gcv; - GC gc; - - gcv.foreground = WhitePixel(d, screen); - gcv.function = GXxor; - gc = XCreateGC(d, xw->p, GCFunction|GCForeground, &gcv); - XFillRectangle(d, xw->p, gc, x, y, w, h); - XFreeGC(d, gc); - } else { - XftColor col; - - xftcolor(&col, c); - XftDrawRect(xw->xft, &col, x, y, w, h); - } -} - -static void -putwin(GWin *gw) -{ - XWin *xw; - - xw = (XWin *)gw; - XCopyArea(d, xw->p, win, gc, 0, 0, gw->w, gw->h, gw->x, gw->y); -} - -static int -textwidth(Rune *str, int len) -{ - XGlyphInfo gi; - - XftTextExtents32(d, font, (FcChar32 *)str, len, &gi); - return gi.xOff; -} - -static void -nextevent(GEvent *gev) -{ - XEvent e; - - do { - XNextEvent(d, &e); - switch (e.type) { - - case Expose: - { - XWin *w; - - /* we could suck all exposes here */ - for (w=wins; w-wins<MaxWins; w++) { - if (!w->used) - continue; - putwin((GWin *)w); - } - continue; - } - - case ConfigureNotify: - if (e.xconfigure.width == w) - if (e.xconfigure.height == h) - continue; - - w = e.xconfigure.width; - h = e.xconfigure.height; - - gev->type = GResize; - gev->resize.width = w; - gev->resize.height = h; - break; - - case ButtonPress: - case ButtonRelease: - if (e.type == ButtonPress) - gev->type = GButPress; - else - gev->type = GButRelease; - switch (e.xbutton.button) { - case Button1: - gev->button = GBLeft; - break; - case Button2: - gev->button = GBMiddle; - break; - case Button3: - gev->button = GBRight; - break; - case Button4: - gev->button = GBWheelUp; - break; - case Button5: - gev->button = GBWheelDown; - break; - default: - continue; - } - break; - - case KeyPress: - { - int len; - char buf[8]; - KeySym key; - - gev->type = GKey; - len = XLookupString(&e.xkey, buf, 8, &key, 0); - switch (key) { - case XK_F1: - case XK_F2: - case XK_F3: - case XK_F4: - case XK_F5: - case XK_F6: - case XK_F7: - case XK_F8: - case XK_F9: - case XK_F10: - case XK_F11: - case XK_F12: - gev->key = GKF1 + (key - XK_F1); - break; - case XK_Up: - gev->key = GKUp; - break; - case XK_Down: - gev->key = GKDown; - break; - case XK_Left: - gev->key = GKLeft; - break; - case XK_Right: - gev->key = GKRight; - break; - case XK_Prior: - gev->key = GKPageUp; - break; - case XK_Next: - gev->key = GKPageDown; - break; - case XK_BackSpace: - gev->key = GKBackspace; - break; - default: - if (len == 0) - continue; - gev->key = buf[0]; - break; - } - break; - } - - default: - continue; - } - return; - } while (1); -} - -struct gui gui_x11 = { - .init = init, - .fini = fini, - .getfont = getfont, - .newwin = newwin, - .movewin = movewin, - .delwin = delwin, - .drawtext = drawtext, - .drawrect = drawrect, - .putwin = putwin, - .textwidth = textwidth, - .nextevent = nextevent, -}; diff --git a/old/xmess/x11.o b/old/xmess/x11.o Binary files differdeleted file mode 100644 index 5408196..0000000 --- a/old/xmess/x11.o +++ /dev/null |
