diff -urN cui77/cui.c cui78/cui.c --- cui77/cui.c Sun Mar 23 22:00:00 2014 +++ cui78/cui.c Wed Mar 26 22:00:00 2014 @@ -135,12 +135,13 @@ { int ix, iy; int n = strlen(s); + char *buf; - for(iy=0; iyw * 2 - 2) - (term->w - 1)); + y = abs(cnt % (term->h * 2 - 2) - (term->h - 1)); + sprintf(buf, "\033[%d;%dH", y+1, x+1); + cui_term_puts(term, buf); + + if(cnt % 10 == 0){ + int lst[] = {0, 4, 7, 24, 27}; + sprintf(buf, "\033[%dm", lst[(cnt/10)%5]); + cui_term_puts(term, buf); + } + cui_term_putc(term, ' ' + cnt % (0x7e - ' ')); + usleep(10*1000); + } + break; } return TRUE; } diff -urN cui77/term.c cui78/term.c --- cui77/term.c Tue Mar 25 22:00:00 2014 +++ cui78/term.c Wed Mar 26 22:00:00 2014 @@ -3,6 +3,9 @@ #include #include #include +#include + +#define UPDATE_FLG (1<<7) cui cui_term_new(cui parent, int x, int y, int w, int h) @@ -23,23 +26,70 @@ p->cursor_onoff = TRUE; p->attr = CUI_ATTR_NORMAL; + p->update_all = FALSE; + p->esc_buf_n = 0; + cui_bind(obj, CUI_EVT_DRAW|CUI_EVT_RESIZE, cui_term_hdr, NULL); } +static void +hdr_update_flush(cui obj, int *attr, char *lp, int x, int y) +{ + cui_term p = (cui_term)obj; + + if(*attr == -1) return; + *lp = '\0'; + cui_draw_str(obj, x, y, p->lbuf, *attr & ~UPDATE_FLG); + *attr = -1; +} + +static void +hdr_update(cui obj) +{ + cui_term p = (cui_term)obj; + char *lp = p->lbuf; + int x, y, attr = -1, lx = 0; + + if(p->update_all) cui_clear(obj); + for(y=0; yh; y++){ + for(x=0; xw; x++){ + char *bp = cui_term_buf(obj, x, y); + if(bp[0] && (p->update_all || (bp[1] & UPDATE_FLG))){ + if(attr != -1 && bp[1] != attr) hdr_update_flush(obj, &attr, lp, lx, y); + if(attr == -1){ + lp = p->lbuf; + *lp++ = bp[0]; + attr = bp[1]; + lx = x; + bp[1] &= ~UPDATE_FLG; + continue; + } + /* bp[1] == attr */ + *lp++ = bp[0]; + bp[1] &= ~UPDATE_FLG; + continue; + } + hdr_update_flush(obj, &attr, lp, lx, y); + } + hdr_update_flush(obj, &attr, lp, lx, y); + } + if(p->cursor_onoff){ + char buf[2]; + buf[0] = cui_term_buf(obj, p->cx, p->cy)[0]; + buf[1] = '\0'; + if(!buf[0]) buf[0] = ' '; + cui_draw_str(obj, p->cx, p->cy, buf, CUI_ATTR_REVERSE); + } + p->update_all = FALSE; +} + int cui_term_hdr(cui obj, int evt, int val, void *prm) { - cui_term p = (cui_term)obj; - int y; - switch(evt){ case CUI_EVT_DRAW: - p->lbuf[obj->w] = '\0'; - for(y=0; yh; y++){ - memcpy(p->lbuf, cui_term_buf(obj, 0, y), obj->w); - cui_draw_str(obj, 0, y, p->lbuf, p->attr); - } - break; + hdr_update(obj); + return TRUE; case CUI_EVT_RESIZE: // ... break; @@ -51,10 +101,10 @@ cui_term_buf_alloc(cui obj) { cui_term p = (cui_term)obj; - int size = obj->w * obj->h; + int size = 2 * obj->w * obj->h; /* 2 : char, attr */ int sz = size + obj->w + 1; /* for lbuf */ if((p->buf = malloc(sz)) == NULL) ERR("No Mem"); - memset(p->buf, ' ', size); + memset(p->buf, 0, size); p->lbuf = p->buf + size; } @@ -71,29 +121,181 @@ void cui_term_putc(cui obj, char c) { + cui_term_putc_buf(obj, c); + cui_term_update(obj); +} + +static int +esc_cmp(cui obj, char *targ) +{ + cui_term p = (cui_term)obj; + + if(strcmp(p->esc_buf, targ) == 0) return 0; /* equal */ + if(strncmp(p->esc_buf, targ, p->esc_buf_n) == 0) return 1; /* continue */ + return -1; /* not equal */ +} + +static void +esc_flush(cui obj) +{ + cui_term p = (cui_term)obj; + cui_term_puts_buf_inner(obj, p->esc_buf); + p->esc_buf_n = 0; +} + +static void +esc_do(cui obj, char c) +{ + cui_term p = (cui_term)obj; + int ret, i, x, y; + + p->esc_buf[ p->esc_buf_n++ ] = c; + p->esc_buf[ p->esc_buf_n ] = '\0'; + + if(p->esc_buf_n == 1) return; + if(p->esc_buf_n == 2){ + if(c == '[') return; + esc_flush(obj); + return; + } + if(p->esc_buf_n == 3){ + if(c == '?') return; + if(isdigit(c)) return; + esc_flush(obj); + return; + } + + /* esc_buf_n >= 4 */ + + if(p->esc_buf[2] == '?'){ + if((ret = esc_cmp(obj, "\033[?25h")) == 1) return; + if(ret == 0){ + p->cursor_onoff = TRUE; + p->esc_buf_n = 0; + cui_term_update(obj); + return; + } + if((ret = esc_cmp(obj, "\033[?25l")) == 1) return; + if(ret == 0){ + p->cursor_onoff = FALSE; + p->esc_buf_n = 0; + cui_term_update(obj); + return; + } + esc_flush(obj); + return; + } + + /* esc_buf[2] is digit */ + + if((ret = esc_cmp(obj, "\033[0m")) == 1) return; + if(ret == 0){ + p->attr = CUI_ATTR_NORMAL; + p->esc_buf_n = 0; + return; + } + if((ret = esc_cmp(obj, "\033[4m")) == 1) return; + if(ret == 0){ + p->attr |= CUI_ATTR_ULINE; + p->esc_buf_n = 0; + return; + } + if((ret = esc_cmp(obj, "\033[7m")) == 1) return; + if(ret == 0){ + p->attr |= CUI_ATTR_REVERSE; + p->esc_buf_n = 0; + return; + } + if((ret = esc_cmp(obj, "\033[24m")) == 1) return; + if(ret == 0){ + p->attr &= ~CUI_ATTR_ULINE; + p->esc_buf_n = 0; + return; + } + if((ret = esc_cmp(obj, "\033[27m")) == 1) return; + if(ret == 0){ + p->attr &= ~CUI_ATTR_REVERSE; + p->esc_buf_n = 0; + return; + } + + /* ESC "[(y);(x)H" */ + + x = y = 0; + i = 2; + while(p->esc_buf[i] && isdigit(p->esc_buf[i])){ + y = y * 10 + (p->esc_buf[i++] - '0'); + } + if(p->esc_buf[i] == '\0') return; + if(p->esc_buf[i++] != ';'){ + esc_flush(obj); + return; + } + while(p->esc_buf[i] && isdigit(p->esc_buf[i])){ + x = x * 10 + (p->esc_buf[i++] - '0'); + } + if(p->esc_buf[i] == '\0') return; + if(p->esc_buf[i++] != 'H'){ + esc_flush(obj); + return; + } + cui_term_move(obj, x-1, y-1); + p->esc_buf_n = 0; +} + +void +cui_term_putc_buf(cui obj, char c) +{ + cui_term p = (cui_term)obj; + if(c == '\033' || p->esc_buf_n > 0){ + esc_do(obj, c); + return; + } + cui_term_putc_buf_inner(obj, c); +} + +void +cui_term_putc_buf_inner(cui obj, char c) +{ cui_term p = (cui_term)obj; int cx; + char *bp; switch(c){ case '\n': cui_term_nl(obj); return; case '\t': - cx = (p->cx/8 + 1) * 8; + cx = (p->cx / 8 + 1) * 8; if(cx < obj->w) cui_term_move(obj, cx, p->cy); else cui_term_nl(obj); return; } - *cui_term_buf(obj, p->cx, p->cy) = c; + + bp = cui_term_buf(obj, p->cx, p->cy); + bp[0] = c; + bp[1] = p->attr | UPDATE_FLG; + if(++p->cx >= obj->w) cui_term_nl(obj); - - cui_handler_call(obj, CUI_EVT_DRAW, 0); } void cui_term_puts(cui obj, char *s) { - while(*s) cui_term_putc(obj, *s++); + cui_term_puts_buf(obj, s); + cui_term_update(obj); +} + +void +cui_term_puts_buf(cui obj, char *s) +{ + while(*s) cui_term_putc_buf(obj, *s++); +} + +void +cui_term_puts_buf_inner(cui obj, char *s) +{ + while(*s) cui_term_putc_buf_inner(obj, *s++); } void @@ -104,8 +306,9 @@ p->cx = 0; if(p->cy < obj->h-1) p->cy++; else{ - memset(&p->buf[ obj->w * p->bfy ], ' ', obj->w); + memset(cui_term_buf(obj, 0, 0), 0, obj->w * 2); /* 2 : char, attr */ if(++p->bfy >= obj->h) p->bfy = 0; + p->update_all = TRUE; } } @@ -114,16 +317,22 @@ { cui_term p = (cui_term)obj; int iy = (p->bfy + cy) % obj->h; - int i = obj->w * iy + cx; + int i = (obj->w * iy + cx) * 2; /* 2 : char, attr */ return &p->buf[i]; } void cui_term_move(cui obj, int cx, int cy) { - cui_term p = (cui_term)obj; + cui_term p = (cui_term)obj; p->cx = cx; p->cy = cy; +} + +void +cui_term_update(cui obj) +{ + cui_handler_call(obj, CUI_EVT_DRAW, 0); } /* EOF */ diff -urN cui77/term.h cui78/term.h --- cui77/term.h Tue Mar 25 22:00:00 2014 +++ cui78/term.h Wed Mar 26 22:00:00 2014 @@ -9,6 +9,11 @@ int cx, cy, bfy; int cursor_onoff; int attr; + + int update_all; + + char esc_buf[16]; + int esc_buf_n; } *cui_term; cui cui_term_new(cui parent, int x, int y, int w, int h); @@ -16,11 +21,18 @@ int cui_term_hdr(cui obj, int evt, int val, void *prm); void cui_term_buf_alloc(cui obj); void cui_term_buf_free(cui obj); + void cui_term_putc(cui obj, char c); +void cui_term_putc_buf(cui obj, char c); +void cui_term_putc_buf_inner(cui obj, char c); + void cui_term_puts(cui obj, char *s); +void cui_term_puts_buf(cui obj, char *s); +void cui_term_puts_buf_inner(cui obj, char *s); void cui_term_nl(cui obj); char *cui_term_buf(cui obj, int cx, int cy); void cui_term_move(cui obj, int cx, int cy); +void cui_term_update(cui obj); #endif