Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/lib/libedit/refresh.c,v rcsdiff: /ftp/cvs/cvsroot/src/lib/libedit/refresh.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.34 retrieving revision 1.35 diff -u -p -r1.34 -r1.35 --- src/lib/libedit/refresh.c 2009/12/28 22:15:36 1.34 +++ src/lib/libedit/refresh.c 2009/12/30 22:37:40 1.35 @@ -1,4 +1,4 @@ -/* $NetBSD: refresh.c,v 1.34 2009/12/28 22:15:36 christos Exp $ */ +/* $NetBSD: refresh.c,v 1.35 2009/12/30 22:37:40 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)refresh.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: refresh.c,v 1.34 2009/12/28 22:15:36 christos Exp $"); +__RCSID("$NetBSD: refresh.c,v 1.35 2009/12/30 22:37:40 christos Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -52,14 +52,14 @@ __RCSID("$NetBSD: refresh.c,v 1.34 2009/ #include "el.h" private void re_nextline(EditLine *); -private void re_addc(EditLine *, int); -private void re_update_line(EditLine *, char *, char *, int); -private void re_insert (EditLine *, char *, int, int, char *, int); -private void re_delete(EditLine *, char *, int, int, int); -private void re_fastputc(EditLine *, int); +private void re_addc(EditLine *, Int); +private void re_update_line(EditLine *, Char *, Char *, int); +private void re_insert (EditLine *, Char *, int, int, Char *, int); +private void re_delete(EditLine *, Char *, int, int, int); +private void re_fastputc(EditLine *, Int); private void re_clear_eol(EditLine *, int, int, int); -private void re__strncopy(char *, char *, size_t); -private void re__copy_and_pad(char *, const char *, size_t); +private void re__strncopy(Char *, Char *, size_t); +private void re__copy_and_pad(Char *, const Char *, size_t); #ifdef DEBUG_REFRESH private void re_printstr(EditLine *, const char *, char *, char *); @@ -105,7 +105,7 @@ re_nextline(EditLine *el) */ if (el->el_refresh.r_cursor.v + 1 >= el->el_term.t_size.v) { int i, lins = el->el_term.t_size.v; - char *firstline = el->el_vdisplay[0]; + Char *firstline = el->el_vdisplay[0]; for(i = 1; i < lins; i++) el->el_vdisplay[i - 1] = el->el_vdisplay[i]; @@ -125,38 +125,34 @@ re_nextline(EditLine *el) * Draw c, expanding tabs, control chars etc. */ private void -re_addc(EditLine *el, int c) +re_addc(EditLine *el, Int c) { - - if (isprint(c)) { - re_putc(el, c, 1); - return; - } - if (c == '\n') { /* expand the newline */ - int oldv = el->el_refresh.r_cursor.v; - re_putc(el, '\0', 0); /* assure end of line */ - if (oldv == el->el_refresh.r_cursor.v) /* XXX */ - re_nextline(el); - return; - } - if (c == '\t') { /* expand the tab */ + switch (ct_chr_class((Char)c)) { + case CHTYPE_TAB: /* expand the tab */ for (;;) { re_putc(el, ' ', 1); if ((el->el_refresh.r_cursor.h & 07) == 0) break; /* go until tab stop */ } - } else if (iscntrl(c)) { - re_putc(el, '^', 1); - if (c == '\177') - re_putc(el, '?', 1); - else - /* uncontrolify it; works only for iso8859-1 like sets */ - re_putc(el, (c | 0100), 1); - } else { - re_putc(el, '\\', 1); - re_putc(el, (int) ((((unsigned int) c >> 6) & 07) + '0'), 1); - re_putc(el, (int) ((((unsigned int) c >> 3) & 07) + '0'), 1); - re_putc(el, (c & 07) + '0', 1); + break; + case CHTYPE_NL: { + int oldv = el->el_refresh.r_cursor.v; + re_putc(el, '\0', 0); /* assure end of line */ + if (oldv == el->el_refresh.r_cursor.v) /* XXX */ + re_nextline(el); + break; + } + case CHTYPE_PRINT: + re_putc(el, c, 1); + break; + default: { + Char visbuf[VISUAL_WIDTH_MAX]; + ssize_t i, n = + ct_visual_char(visbuf, VISUAL_WIDTH_MAX, (Char)c); + for (i = 0; n-- > 0; ++i) + re_putc(el, visbuf[i], 1); + break; + } } } @@ -165,23 +161,32 @@ re_addc(EditLine *el, int c) * Draw the character given */ protected void -re_putc(EditLine *el, int c, int shift) +re_putc(EditLine *el, Int c, int shift) { + int i, w = Width(c); + ELRE_DEBUG(1, (__F, "printing %5x '%c'\r\n", c, c)); + + while (shift && (el->el_refresh.r_cursor.h + w > el->el_term.t_size.h)) + re_putc(el, ' ', 1); - ELRE_DEBUG(1, (__F, "printing %3.3o '%c'\r\n", c, c)); + el->el_vdisplay[el->el_refresh.r_cursor.v] + [el->el_refresh.r_cursor.h] = c; + /* assumes !shift is only used for single-column chars */ + i = w; + while (--i > 0) + el->el_vdisplay[el->el_refresh.r_cursor.v] + [el->el_refresh.r_cursor.h + i] = MB_FILL_CHAR; - el->el_vdisplay[el->el_refresh.r_cursor.v][el->el_refresh.r_cursor.h] = c; if (!shift) return; - el->el_refresh.r_cursor.h++; /* advance to next place */ + el->el_refresh.r_cursor.h += w; /* advance to next place */ if (el->el_refresh.r_cursor.h >= el->el_term.t_size.h) { /* assure end of line */ el->el_vdisplay[el->el_refresh.r_cursor.v][el->el_term.t_size.h] = '\0'; re_nextline(el); } - } @@ -195,7 +200,7 @@ protected void re_refresh(EditLine *el) { int i, rhdiff; - char *cp, *st; + Char *cp, *st; coord_t cur; #ifdef notyet size_t termsz; @@ -247,11 +252,18 @@ re_refresh(EditLine *el) for (cp = st; cp < el->el_line.lastchar; cp++) { if (cp == el->el_line.cursor) { + int w = Width(*cp); /* save for later */ cur.h = el->el_refresh.r_cursor.h; cur.v = el->el_refresh.r_cursor.v; + /* handle being at a linebroken doublewidth char */ + if (w > 1 && el->el_refresh.r_cursor.h + w > + el->el_term.t_size.h) { + cur.h = 0; + cur.v++; + } } - re_addc(el, (unsigned char) *cp); + re_addc(el, *cp); } if (cur.h == -1) { /* if I haven't been set yet, I'm at the end */ @@ -282,7 +294,7 @@ re_refresh(EditLine *el) ELRE_DEBUG(1, (__F, "term.h=%d vcur.h=%d vcur.v=%d vdisplay[0]=\r\n:%80.80s:\r\n", el->el_term.t_size.h, el->el_refresh.r_cursor.h, - el->el_refresh.r_cursor.v, el->el_vdisplay[0])); + el->el_refresh.r_cursor.v, ct_encode_string(el->el_vdisplay[0]))); ELRE_DEBUG(1, (__F, "updating %d lines.\r\n", el->el_refresh.r_newcv)); for (i = 0; i <= el->el_refresh.r_newcv; i++) { @@ -307,7 +319,8 @@ re_refresh(EditLine *el) for (; i <= el->el_refresh.r_oldcv; i++) { term_move_to_line(el, i); term_move_to_char(el, 0); - term_clear_EOL(el, (int) strlen(el->el_display[i])); + /* This Strlen should be safe even with MB_FILL_CHARs */ + term_clear_EOL(el, (int) Strlen(el->el_display[i])); #ifdef DEBUG_REFRESH term_overwrite(el, "C\b", (size_t)2); #endif /* DEBUG_REFRESH */ @@ -345,9 +358,9 @@ re_goto_bottom(EditLine *el) private void /*ARGSUSED*/ re_insert(EditLine *el __attribute__((__unused__)), - char *d, int dat, int dlen, char *s, int num) + Char *d, int dat, int dlen, Char *s, int num) { - char *a, *b; + Char *a, *b; if (num <= 0) return; @@ -356,8 +369,8 @@ re_insert(EditLine *el __attribute__((__ ELRE_DEBUG(1, (__F, "re_insert() starting: %d at %d max %d, d == \"%s\"\n", - num, dat, dlen, d)); - ELRE_DEBUG(1, (__F, "s == \"%s\"\n", s)); + num, dat, dlen, ct_encode_string(d))); + ELRE_DEBUG(1, (__F, "s == \"%s\"\n", ct_encode_string(s))); /* open up the space for num chars */ if (num > 0) { @@ -367,19 +380,24 @@ re_insert(EditLine *el __attribute__((__ *b-- = *a--; d[dlen] = '\0'; /* just in case */ } + ELRE_DEBUG(1, (__F, "re_insert() after insert: %d at %d max %d, d == \"%s\"\n", - num, dat, dlen, d)); - ELRE_DEBUG(1, (__F, "s == \"%s\"\n", s)); + num, dat, dlen, ct_encode_string(d))); + ELRE_DEBUG(1, (__F, "s == \"%s\"\n", ct_encode_string(s))); /* copy the characters */ for (a = d + dat; (a < d + dlen) && (num > 0); num--) *a++ = *s++; +#ifdef notyet + /* ct_encode_string() uses a static buffer, so we can't conveniently + * encode both d & s here */ ELRE_DEBUG(1, (__F, "re_insert() after copy: %d at %d max %d, %s == \"%s\"\n", num, dat, dlen, d, s)); ELRE_DEBUG(1, (__F, "s == \"%s\"\n", s)); +#endif } @@ -389,9 +407,9 @@ re_insert(EditLine *el __attribute__((__ private void /*ARGSUSED*/ re_delete(EditLine *el __attribute__((__unused__)), - char *d, int dat, int dlen, int num) + Char *d, int dat, int dlen, int num) { - char *a, *b; + Char *a, *b; if (num <= 0) return; @@ -401,7 +419,7 @@ re_delete(EditLine *el __attribute__((__ } ELRE_DEBUG(1, (__F, "re_delete() starting: %d at %d max %d, d == \"%s\"\n", - num, dat, dlen, d)); + num, dat, dlen, ct_encode_string(d))); /* open up the space for num chars */ if (num > 0) { @@ -413,7 +431,7 @@ re_delete(EditLine *el __attribute__((__ } ELRE_DEBUG(1, (__F, "re_delete() after delete: %d at %d max %d, d == \"%s\"\n", - num, dat, dlen, d)); + num, dat, dlen, ct_encode_string(d))); } @@ -421,7 +439,7 @@ re_delete(EditLine *el __attribute__((__ * Like strncpy without padding. */ private void -re__strncopy(char *a, char *b, size_t n) +re__strncopy(Char *a, Char *b, size_t n) { while (n-- && *b) @@ -432,7 +450,7 @@ re__strncopy(char *a, char *b, size_t n) * Find the number of characters we need to clear till the end of line * in order to make sure that we have cleared the previous contents of * the line. fx and sx is the number of characters inserted or deleted - * int the first or second diff, diff is the difference between the + * in the first or second diff, diff is the difference between the * number of characters between the new and old line. */ private void @@ -480,11 +498,11 @@ new: eddie> Oh, my little buggy says to #define MIN_END_KEEP 4 private void -re_update_line(EditLine *el, char *old, char *new, int i) +re_update_line(EditLine *el, Char *old, Char *new, int i) { - char *o, *n, *p, c; - char *ofd, *ols, *oe, *nfd, *nls, *ne; - char *osb, *ose, *nsb, *nse; + Char *o, *n, *p, c; + Char *ofd, *ols, *oe, *nfd, *nls, *ne; + Char *osb, *ose, *nsb, *nse; int fx, sx; size_t len; @@ -950,7 +968,7 @@ re_update_line(EditLine *el, char *old, * Copy string and pad with spaces */ private void -re__copy_and_pad(char *dst, const char *src, size_t width) +re__copy_and_pad(Char *dst, const Char *src, size_t width) { size_t i; @@ -973,8 +991,8 @@ re__copy_and_pad(char *dst, const char * protected void re_refresh_cursor(EditLine *el) { - char *cp, c; - int h, v, th; + Char *cp; + int h, v, th, w; if (el->el_line.cursor >= el->el_line.lastchar) { if (el->el_map.current == el->el_map.alt @@ -991,32 +1009,37 @@ re_refresh_cursor(EditLine *el) /* do input buffer to el->el_line.cursor */ for (cp = el->el_line.buffer; cp < el->el_line.cursor; cp++) { - c = *cp; - - switch (c) { - case '\n': /* handle newline in data part too */ + switch (ct_chr_class(*cp)) { + case CHTYPE_NL: /* handle newline in data part too */ h = 0; v++; break; - case '\t': /* if a tab, to next tab stop */ + case CHTYPE_TAB: /* if a tab, to next tab stop */ while (++h & 07) continue; break; default: - if (iscntrl((unsigned char) c)) - h += 2; /* ^x */ - else if (!isprint((unsigned char) c)) - h += 4; /* octal \xxx */ - else - h++; + w = Width(*cp); + if (w > 1 && h + w > th) { /* won't fit on line */ + h = 0; + v++; + } + h += ct_visual_width(*cp); break; - } + } if (h >= th) { /* check, extra long tabs picked up here also */ h -= th; v++; } } + /* if we have a next character, and it's a doublewidth one, we need to + * check whether we need to linebreak for it to fit */ + if (cp < el->el_line.lastchar && (w = Width(*cp)) > 1) + if (h + w > th) { + h = 0; + v++; + } /* now go there */ term_move_to_line(el, v); @@ -1029,11 +1052,18 @@ re_refresh_cursor(EditLine *el) * Add a character fast. */ private void -re_fastputc(EditLine *el, int c) +re_fastputc(EditLine *el, Int c) { + int w = Width((Char)c); + while (w > 1 && el->el_cursor.h + w > el->el_term.t_size.h) + re_fastputc(el, ' '); term__putc(el, c); el->el_display[el->el_cursor.v][el->el_cursor.h++] = c; + while (--w > 0) + el->el_display[el->el_cursor.v][el->el_cursor.h++] + = MB_FILL_CHAR; + if (el->el_cursor.h >= el->el_term.t_size.h) { /* if we must overflow */ el->el_cursor.h = 0; @@ -1046,12 +1076,12 @@ re_fastputc(EditLine *el, int c) */ if (el->el_cursor.v + 1 >= el->el_term.t_size.v) { int i, lins = el->el_term.t_size.v; - char *firstline = el->el_display[0]; + Char *firstline = el->el_display[0]; for(i = 1; i < lins; i++) el->el_display[i - 1] = el->el_display[i]; - re__copy_and_pad(firstline, "", 0); + re__copy_and_pad(firstline, STR(""), 0); el->el_display[i - 1] = firstline; } else { el->el_cursor.v++; @@ -1077,7 +1107,7 @@ re_fastputc(EditLine *el, int c) protected void re_fastaddc(EditLine *el) { - char c; + Char c; int rhdiff; c = el->el_line.cursor[-1]; @@ -1092,17 +1122,22 @@ re_fastaddc(EditLine *el) re_refresh(el); /* clear out rprompt if less than 1 char gap */ return; } /* else (only do at end of line, no TAB) */ - if (iscntrl((unsigned char) c)) { /* if control char, do caret */ - char mc = (c == '\177') ? '?' : (c | 0100); - re_fastputc(el, '^'); - re_fastputc(el, mc); - } else if (isprint((unsigned char) c)) { /* normal char */ + switch (ct_chr_class(c)) { + case CHTYPE_TAB: /* already handled, should never happen here */ + break; + case CHTYPE_NL: + case CHTYPE_PRINT: re_fastputc(el, c); - } else { - re_fastputc(el, '\\'); - re_fastputc(el, (int)(((((unsigned int)c) >> 6) & 3) + '0')); - re_fastputc(el, (int)(((((unsigned int)c) >> 3) & 7) + '0')); - re_fastputc(el, (c & 7) + '0'); + break; + case CHTYPE_ASCIICTL: + case CHTYPE_NONPRINT: { + Char visbuf[VISUAL_WIDTH_MAX]; + ssize_t i, n = + ct_visual_char(visbuf, VISUAL_WIDTH_MAX, (Char)c); + for (i = 0; n-- > 0; ++i) + re_fastputc(el, visbuf[i]); + break; + } } term__flush(el); }