X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=st.c;h=ad6db0dbd2bb54e09b4fcfbb612925cddf694013;hb=0dbf9c8c12a5de35d1cef22349ab80e8f0a8f10e;hp=7ac02b9201d0db42fb3fa20d5c6a5925ee8d7a97;hpb=8e66b5cc16831583a1086f3ba9cd0eaa55f02230;p=st.git diff --git a/st.c b/st.c index 7ac02b9..ad6db0d 100644 --- a/st.c +++ b/st.c @@ -34,7 +34,7 @@ #endif #define USAGE \ - "st-" VERSION ", (c) 2010-2011 st engineers\n" \ + "st " VERSION " (c) 2010-2011 st engineers\n" \ "usage: st [-t title] [-c class] [-w windowid] [-v] [-e command...]\n" /* XEMBED messages */ @@ -47,6 +47,8 @@ #define ESC_ARG_SIZ 16 #define DRAW_BUF_SIZ 1024 #define UTF_SIZ 4 +#define XK_NO_MOD UINT_MAX +#define XK_ANY_MOD 0 #define SERRNO strerror(errno) #define MIN(a, b) ((a) < (b) ? (a) : (b)) @@ -109,6 +111,7 @@ typedef struct { int col; /* nb col */ Line* line; /* screen */ Line* alt; /* alternate screen */ + char* dirty; /* dirtyness of lines */ TCursor c; /* cursor */ int top; /* top scroll limit */ int bot; /* bottom scroll limit */ @@ -201,6 +204,7 @@ static void tsetattr(int*, int); static void tsetchar(char*); static void tsetscroll(int, int); static void tswapscreen(void); +static void tfulldirt(void); static void ttynew(void); static void ttyread(void); @@ -235,6 +239,7 @@ static void selinit(void); static inline int selected(int, int); static void selcopy(void); static void selpaste(); +static void selscroll(int, int); static int utf8decode(char *, long *); static int utf8encode(long *, char *); @@ -746,6 +751,14 @@ ttyresize(int x, int y) { } void +tfulldirt(void) +{ + int i; + for(i = 0; i < term.row; i++) + term.dirty[i] = 1; +} + +void tcursor(int mode) { static TCursor c; @@ -774,9 +787,12 @@ tnew(int col, int row) { term.row = row, term.col = col; term.line = malloc(term.row * sizeof(Line)); term.alt = malloc(term.row * sizeof(Line)); + term.dirty = malloc(term.row * sizeof(*term.dirty)); + for(row = 0; row < term.row; row++) { term.line[row] = malloc(term.col * sizeof(Glyph)); term.alt [row] = malloc(term.col * sizeof(Glyph)); + term.dirty[row] = 0; } /* setup screen */ treset(); @@ -788,6 +804,7 @@ tswapscreen(void) { term.line = term.alt; term.alt = tmp; term.mode ^= MODE_ALTSCREEN; + tfulldirt(); } void @@ -803,7 +820,12 @@ tscrolldown(int orig, int n) { temp = term.line[i]; term.line[i] = term.line[i-n]; term.line[i-n] = temp; + + term.dirty[i] = 1; + term.dirty[i-n] = 1; } + + selscroll(orig, n); } void @@ -818,6 +840,34 @@ tscrollup(int orig, int n) { temp = term.line[i]; term.line[i] = term.line[i+n]; term.line[i+n] = temp; + + term.dirty[i] = 1; + term.dirty[i+n] = 1; + } + + selscroll(orig, -n); +} + +void +selscroll(int orig, int n) { + if(sel.bx == -1) + return; + + if(BETWEEN(sel.by, orig, term.bot) || BETWEEN(sel.ey, orig, term.bot)) { + if((sel.by += n) > term.bot || (sel.ey += n) < term.top) { + sel.bx = -1; + return; + } + if(sel.by < term.top) { + sel.by = term.top; + sel.bx = 0; + } + if(sel.ey > term.bot) { + sel.ey = term.bot; + sel.ex = term.col; + } + sel.b.y = sel.by, sel.b.x = sel.bx; + sel.e.y = sel.ey, sel.e.x = sel.ex; } } @@ -866,6 +916,7 @@ tmoveto(int x, int y) { void tsetchar(char *c) { + term.dirty[term.c.y] = 1; term.line[term.c.y][term.c.x] = term.c.attr; memcpy(term.line[term.c.y][term.c.x].c, c, UTF_SIZ); term.line[term.c.y][term.c.x].state |= GLYPH_SET; @@ -885,9 +936,11 @@ tclearregion(int x1, int y1, int x2, int y2) { LIMIT(y1, 0, term.row-1); LIMIT(y2, 0, term.row-1); - for(y = y1; y <= y2; y++) + for(y = y1; y <= y2; y++) { + term.dirty[y] = 1; for(x = x1; x <= x2; x++) term.line[y][x].state = 0; + } } void @@ -895,6 +948,8 @@ tdeletechar(int n) { int src = term.c.x + n; int dst = term.c.x; int size = term.col - src; + + term.dirty[term.c.y] = 1; if(src >= term.col) { tclearregion(term.c.x, term.c.y, term.col-1, term.c.y); @@ -910,6 +965,8 @@ tinsertblank(int n) { int dst = src + n; int size = term.col - dst; + term.dirty[term.c.y] = 1; + if(dst >= term.col) { tclearregion(term.c.x, term.c.y, term.col-1, term.c.y); return; @@ -1075,6 +1132,7 @@ csihandle(void) { break; /* XXX: (CSI n I) CHT -- Cursor Forward Tabulation tab stops */ case 'J': /* ED -- Clear screen */ + sel.bx = -1; switch(escseq.arg[0]) { case 0: /* below */ tclearregion(term.c.x, term.c.y, term.col-1, term.c.y); @@ -1380,6 +1438,8 @@ tputc(char *c) { } } } else { + if(sel.bx != -1 && BETWEEN(term.c.y, sel.by, sel.ey)) + sel.bx = -1; switch(ascii) { case '\t': tputtab(); @@ -1447,9 +1507,11 @@ tresize(int col, int row) { /* resize to new height */ term.line = realloc(term.line, row * sizeof(Line)); term.alt = realloc(term.alt, row * sizeof(Line)); + term.dirty = realloc(term.dirty, row * sizeof(*term.dirty)); /* resize each row to new width, zero-pad if needed */ for(i = 0; i < minrow; i++) { + term.dirty[i] = 1; term.line[i] = realloc(term.line[i], col * sizeof(Glyph)); term.alt[i] = realloc(term.alt[i], col * sizeof(Glyph)); for(x = mincol; x < col; x++) { @@ -1460,6 +1522,7 @@ tresize(int col, int row) { /* allocate any new rows */ for(/* i == minrow */; i < row; i++) { + term.dirty[i] = 1; term.line[i] = calloc(col, sizeof(Glyph)); term.alt [i] = calloc(col, sizeof(Glyph)); } @@ -1470,6 +1533,7 @@ tresize(int col, int row) { tmoveto(term.c.x, term.c.y); /* reset scrolling region */ tsetscroll(0, row-1); + return (slide > 0); } @@ -1509,7 +1573,7 @@ xloadcols(void) { XColor color; unsigned long white = WhitePixel(xw.dpy, xw.scr); - for(i = 0; i < 16; i++) { + for(i = 0; i < LEN(colorname); i++) { if(!XAllocNamedColor(xw.dpy, xw.cmap, colorname[i], &color, &color)) { dc.col[i] = white; fprintf(stderr, "Could not allocate color '%s'\n", colorname[i]); @@ -1760,8 +1824,11 @@ drawregion(int x1, int y1, int x2, int y2) { if(!(xw.state & WIN_VISIBLE)) return; - xclear(x1, y1, x2-1, y2-1); for(y = y1; y < y2; y++) { + if(!term.dirty[y]) + continue; + xclear(0, y, term.col, y); + term.dirty[y] = 0; base = term.line[y][0]; ic = ib = ox = 0; for(x = x1; x < x2; x++) { @@ -1769,7 +1836,7 @@ drawregion(int x1, int y1, int x2, int y2) { if(sel.bx != -1 && *(new.c) && selected(x, y)) new.mode ^= ATTR_REVERSE; if(ib > 0 && (!(new.state & GLYPH_SET) || ATTRCMP(base, new) || - ib >= DRAW_BUF_SIZ-UTF_SIZ)) { + ib >= DRAW_BUF_SIZ-UTF_SIZ)) { xdraws(buf, base, ox, y, ic, ib); ic = ib = 0; } @@ -1840,9 +1907,12 @@ focus(XEvent *ev) { char* kmap(KeySym k, unsigned int state) { int i; - for(i = 0; i < LEN(key); i++) - if(key[i].k == k && (key[i].mask == 0 || key[i].mask & state)) + state &= ~Mod2Mask; + for(i = 0; i < LEN(key); i++) { + unsigned int mask = key[i].mask; + if(key[i].k == k && ((state & mask) == mask || (mask == XK_NO_MOD && !state))) return (char*)key[i].s; + } return NULL; }