X-Git-Url: https://git.danieliu.xyz/?a=blobdiff_plain;f=st.c;h=6dcded58996e7796bb0f6e8957c6980a9a88e313;hb=7d88cf88d05c5f5fffbe096da9fac79d7d8957f9;hp=9b77a0b6fe0710d2f075bb20dda948e61af5430f;hpb=2181040594ae63f2821899caba0bef34257a6c2b;p=st.git diff --git a/st.c b/st.c index 9b77a0b..6dcded5 100644 --- a/st.c +++ b/st.c @@ -46,8 +46,9 @@ /* Attribute, Cursor, Character state, Terminal mode, Screen draw mode */ enum { ATTR_NULL=0 , ATTR_REVERSE=1 , ATTR_UNDERLINE=2, ATTR_BOLD=4, ATTR_GFX=8 }; -enum { CURSOR_UP, CURSOR_DOWN, CURSOR_LEFT, CURSOR_RIGHT, CURSOR_HIDE, CURSOR_DRAW, +enum { CURSOR_UP, CURSOR_DOWN, CURSOR_LEFT, CURSOR_RIGHT, CURSOR_SAVE, CURSOR_LOAD }; +enum { CURSOR_DEFAULT = 0, CURSOR_HIDE = 1, CURSOR_WRAPNEXT = 2 }; enum { GLYPH_SET=1, GLYPH_DIRTY=2 }; enum { MODE_WRAP=1, MODE_INSERT=2, MODE_APPKEYPAD=4 }; enum { ESC_START=1, ESC_CSI=2, ESC_OSC=4, ESC_TITLE=8, ESC_ALTCHARSET=16 }; @@ -67,7 +68,7 @@ typedef struct { Glyph attr; /* current char attributes */ int x; int y; - char hide; + char state; } TCursor; /* CSI Escape sequence structs */ @@ -164,7 +165,7 @@ static void xbell(void); static void xdraws(char *, Glyph, int, int, int); static void xhints(void); static void xclear(int, int, int, int); -static void xcursor(int); +static void xcursor(void); static void xinit(void); static void xloadcols(void); @@ -230,6 +231,7 @@ void xbell(void) { XSetForeground(xw.dis, dc.gc, dc.col[BellCol]); XFillRectangle(xw.dis, xw.win, dc.gc, BORDER, BORDER, xw.bufw, xw.bufh); + XFlush(xw.dis); usleep(BellTime); draw(SCREEN_REDRAW); } @@ -328,7 +330,7 @@ treset(void) { .mode = ATTR_NULL, .fg = DefaultFG, .bg = DefaultBG - }, .x = 0, .y = 0, .hide = 0}; + }, .x = 0, .y = 0, .state = CURSOR_DEFAULT}; term.top = 0, term.bot = term.row - 1; term.mode = MODE_WRAP; @@ -372,11 +374,11 @@ tscrollup (int n) { for(i = 0; i < n; i++) memset(term.line[term.top+i], 0, term.col*sizeof(Glyph)); - for(i = term.top; i <= term.bot-n; i++) { + for(i = term.top; i <= term.bot-n; i++) { temp = term.line[i]; term.line[i] = term.line[i+n]; term.line[i+n] = temp; - } + } } void @@ -413,8 +415,11 @@ csiparse(void) { void tmoveto(int x, int y) { - term.c.x = x < 0 ? 0 : x >= term.col ? term.col-1 : x; - term.c.y = y < 0 ? 0 : y >= term.row ? term.row-1 : y; + LIMIT(x, 0, term.col-1); + LIMIT(y, 0, term.row-1); + term.c.state &= ~CURSOR_WRAPNEXT; + term.c.x = x; + term.c.y = y; } void @@ -710,7 +715,7 @@ csihandle(void) { case 12: /* att610 -- Stop blinking cursor (IGNORED) */ break; case 25: - term.c.hide = 1; + term.c.state |= CURSOR_HIDE; break; case 1048: /* XXX: no alt. screen to erase/save */ case 1049: @@ -759,7 +764,7 @@ csihandle(void) { case 12: /* att610 -- Start blinking cursor (IGNORED) */ break; case 25: - term.c.hide = 0; + term.c.state &= ~CURSOR_HIDE; break; case 1048: case 1049: /* XXX: no alt. screen to erase/save */ @@ -787,6 +792,7 @@ csihandle(void) { DEFAULT(escseq.arg[0], 1); DEFAULT(escseq.arg[1], term.row); tsetscroll(escseq.arg[0]-1, escseq.arg[1]-1); + tmoveto(0, 0); } break; case 's': /* DECSC -- Save cursor position (ANSI.SYS) */ @@ -866,20 +872,11 @@ tputc(char c) { case '(': term.esc |= ESC_ALTCHARSET; break; - case 'A': - tmoveto(term.c.x, term.c.y-1); - term.esc = 0; - break; - case 'B': - tmoveto(term.c.x, term.c.y+1); - term.esc = 0; - break; - case 'C': - tmoveto(term.c.x+1, term.c.y); - term.esc = 0; - break; - case 'D': /* XXX: CUP (VT100) or IND (VT52) ... */ - tmoveto(term.c.x-1, term.c.y); + case 'D': /* IND -- Linefeed */ + if(term.c.y == term.bot) + tscrollup(1); + else + tmoveto(term.c.x, term.c.y+1); term.esc = 0; break; case 'E': /* NEL -- Next line */ @@ -940,11 +937,13 @@ tputc(char c) { term.esc = ESC_START; break; default: + if(IS_SET(MODE_WRAP) && term.c.state & CURSOR_WRAPNEXT) + tnewline(); tsetchar(c); - if(term.c.x+1 < term.col) { + if(term.c.x+1 < term.col) tmoveto(term.c.x+1, term.c.y); - } else if(IS_SET(MODE_WRAP)) - tnewline(); + else + term.c.state |= CURSOR_WRAPNEXT; break; } } @@ -982,13 +981,12 @@ tresize(int col, int row) { for(/* i == minrow */; i < row; i++) term.line[i] = calloc(col, sizeof(Glyph)); - LIMIT(term.c.x, 0, col-1); - LIMIT(term.c.y, 0, row-1); - LIMIT(term.top, 0, row-1); - LIMIT(term.bot, 0, row-1); - - term.bot = row-1; + /* update terminal size */ term.col = col, term.row = row; + /* make use of the LIMIT in tmoveto */ + tmoveto(term.c.x, term.c.y); + /* reset scrolling region */ + tsetscroll(0, row-1); } void @@ -1120,7 +1118,7 @@ xdraws(char *s, Glyph base, int x, int y, int len) { } void -xcursor(int mode) { +xcursor(void) { static int oldx = 0; static int oldy = 0; Glyph g = {' ', ATTR_NULL, DefaultBG, DefaultCS, 0}; @@ -1138,7 +1136,7 @@ xcursor(int mode) { xclear(oldx, oldy, oldx, oldy); /* draw the new one */ - if(mode == CURSOR_DRAW) { + if(!(term.c.state & CURSOR_HIDE)) { xdraws(&g.c, g, term.c.x, term.c.y, 1); oldx = term.c.x, oldy = term.c.y; } @@ -1165,8 +1163,7 @@ draw(int dummy) { if(term.line[y][x].state & GLYPH_SET) xdrawc(x, y, term.line[y][x]); - if(!term.c.hide) - xcursor(CURSOR_DRAW); + xcursor(); XCopyArea(xw.dis, xw.buf, xw.win, dc.gc, 0, 0, xw.bufw, xw.bufh, BORDER, BORDER); XFlush(xw.dis); } @@ -1180,25 +1177,29 @@ draw(int redraw_all) { char buf[DRAW_BUF_SIZ]; XSetForeground(xw.dis, dc.gc, dc.col[DefaultBG]); - XFillRectangle(xw.dis, xw.buf, dc.gc, 0, 0, xw.w, xw.h); + XFillRectangle(xw.dis, xw.buf, dc.gc, 0, 0, xw.bufw, xw.bufh); for(y = 0; y < term.row; y++) { base = term.line[y][0]; i = ox = 0; for(x = 0; x < term.col; x++) { new = term.line[y][x]; - if(!ATTRCMP(base, new) && i < DRAW_BUF_SIZ) - buf[i++] = new.c; - else { + if(i > 0 && (!(new.state & GLYPH_SET) || ATTRCMP(base, new) || + i >= DRAW_BUF_SIZ)) { xdraws(buf, base, ox, y, i); - buf[0] = new.c; - i = 1; - ox = x; - base = new; + i = 0; + } + if(new.state & GLYPH_SET) { + if(i == 0) { + ox = x; + base = new; + } + buf[i++] = new.c; } } - xdraws(buf, base, ox, y, i); + if(i > 0) + xdraws(buf, base, ox, y, i); } - xcursor(term.c.hide ? CURSOR_HIDE : CURSOR_DRAW); + xcursor(); XCopyArea(xw.dis, xw.buf, xw.win, dc.gc, 0, 0, xw.bufw, xw.bufh, BORDER, BORDER); XFlush(xw.dis); } @@ -1293,7 +1294,7 @@ run(void) { FD_ZERO(&rfd); FD_SET(cmdfd, &rfd); FD_SET(xfd, &rfd); - if(select(MAX(xfd, cmdfd)+1, &rfd, NULL, NULL, NULL) == -1) { + if(select(MAX(xfd, cmdfd)+1, &rfd, NULL, NULL, NULL) < 0) { if(errno == EINTR) continue; die("select failed: %s\n", SERRNO);