diff options
Diffstat (limited to 'Src/Zle')
-rw-r--r-- | Src/Zle/comp.h | 7 | ||||
-rw-r--r-- | Src/Zle/compcore.c | 79 | ||||
-rw-r--r-- | Src/Zle/complete.c | 6 | ||||
-rw-r--r-- | Src/Zle/complist.c | 81 | ||||
-rw-r--r-- | Src/Zle/compmatch.c | 8 | ||||
-rw-r--r-- | Src/Zle/compresult.c | 25 | ||||
-rw-r--r-- | Src/Zle/computil.c | 49 | ||||
-rw-r--r-- | Src/Zle/textobjects.c | 6 | ||||
-rw-r--r-- | Src/Zle/zle.h | 17 | ||||
-rw-r--r-- | Src/Zle/zle_hist.c | 12 | ||||
-rw-r--r-- | Src/Zle/zle_keymap.c | 64 | ||||
-rw-r--r-- | Src/Zle/zle_main.c | 33 | ||||
-rw-r--r-- | Src/Zle/zle_refresh.c | 502 | ||||
-rw-r--r-- | Src/Zle/zle_thingy.c | 6 | ||||
-rw-r--r-- | Src/Zle/zle_tricky.c | 71 | ||||
-rw-r--r-- | Src/Zle/zle_utils.c | 57 | ||||
-rw-r--r-- | Src/Zle/zle_vi.c | 9 |
17 files changed, 505 insertions, 527 deletions
diff --git a/Src/Zle/comp.h b/Src/Zle/comp.h index 0c5fbd4f0..2ca779fe5 100644 --- a/Src/Zle/comp.h +++ b/Src/Zle/comp.h @@ -85,8 +85,8 @@ struct cmgroup { #define CGF_NOSORT 1 /* don't sort this group */ #define CGF_LINES 2 /* these are to be printed on different lines */ #define CGF_HASDL 4 /* has display strings printed on separate lines */ -#define CGF_UNIQALL 8 /* remove all duplicates */ -#define CGF_UNIQCON 16 /* remove consecutive duplicates */ +#define CGF_UNIQALL 8 /* remove consecutive duplicates (if neither are set, */ +#define CGF_UNIQCON 16 /* don't deduplicate */ /* remove all dupes) */ #define CGF_PACKED 32 /* LIST_PACKED for this group */ #define CGF_ROWS 64 /* LIST_ROWS_FIRST for this group */ #define CGF_FILES 128 /* contains file names */ @@ -140,6 +140,7 @@ struct cmatch { #define CMF_ALL (1<<13) /* a match representing all other matches */ #define CMF_DUMMY (1<<14) /* unselectable dummy match */ #define CMF_MORDER (1<<15) /* order by matches, not display strings */ +#define CMF_DELETE (1<<16) /* used for deduplication of unsorted matches, don't set */ /* Stuff for completion matcher control. */ @@ -299,7 +300,7 @@ struct menuinfo { #define CAF_NOSORT 2 /* compadd -V: don't sort */ #define CAF_MATCH 4 /* compadd without -U: do matching */ #define CAF_UNIQCON 8 /* compadd -2: don't deduplicate */ -#define CAF_UNIQALL 16 /* compadd -1: deduplicate */ +#define CAF_UNIQALL 16 /* compadd -1: deduplicate consecutive only */ #define CAF_ARRAYS 32 /* compadd -a or -k: array/assoc parameter names */ #define CAF_KEYS 64 /* compadd -k: assoc parameter names */ #define CAF_ALL 128 /* compadd -C: _all_matches */ diff --git a/Src/Zle/compcore.c b/Src/Zle/compcore.c index c6deff756..09282d42d 100644 --- a/Src/Zle/compcore.c +++ b/Src/Zle/compcore.c @@ -1230,14 +1230,14 @@ check_param(char *s, int set, int test) else if (idigit(*e)) while (idigit(*e)) e++; - else if ((ie = itype_end(e, IIDENT, 0)) != e) { + else if ((ie = itype_end(e, INAMESPC, 0)) != e) { do { e = ie; if (comppatmatch && *comppatmatch && (*e == Star || *e == Quest)) ie = e + 1; else - ie = itype_end(e, IIDENT, 0); + ie = itype_end(e, INAMESPC, 0); } while (ie != e); } @@ -2249,8 +2249,9 @@ addmatches(Cadata dat, char **argv) llpl = strlen(lpre); llsl = strlen(lsuf); - if (llpl + (int)strlen(compqiprefix) + (int)strlen(lipre) != origlpre - || llsl + (int)strlen(compqisuffix) + (int)strlen(lisuf) != origlsuf) + /* This used to reference compqiprefix and compqisuffix, why? */ + if (llpl + (int)strlen(qipre) + (int)strlen(lipre) != origlpre + || llsl + (int)strlen(qisuf) + (int)strlen(lisuf) != origlsuf) lenchanged = 1; /* Test if there is an existing -P prefix. */ @@ -2898,9 +2899,9 @@ add_match_data(int alt, char *str, char *orig, Cline line, *t++ = '$'; *t++ = '\''; *t++ = '\\'; - *t++ = '0' + ((STOUC(curchar) >> 6) & 7); - *t++ = '0' + ((STOUC(curchar) >> 3) & 7); - *t++ = '0' + (STOUC(curchar) & 7); + *t++ = '0' + (((unsigned char) curchar >> 6) & 7); + *t++ = '0' + (((unsigned char) curchar >> 3) & 7); + *t++ = '0' + ((unsigned char) curchar & 7); *t++ = '\''; } while (cnt == MB_INCOMPLETE && fs < fe); /* Scanning restarts from the spot after the char we skipped. */ @@ -3247,17 +3248,20 @@ makearray(LinkList l, int type, int flags, int *np, int *nlp, int *llp) } *cp = NULL; } - } else { + } else if (n > 0) { if (!(flags & CGF_NOSORT)) { /* Now sort the array (it contains matches). */ matchorder = flags; qsort((void *) rp, n, sizeof(Cmatch), - (int (*) _((const void *, const void *)))matchcmp); + (int (*) (const void *, const void *))matchcmp); + /* since the matches are sorted and the default is to remove + * all duplicates, -1 (remove only consecutive dupes) is a no-op, + * so this condition only checks for -2 */ if (!(flags & CGF_UNIQCON)) { int dup; - /* And delete the ones that occur more than once. */ + /* we did not pass -2 so go ahead and remove those dupes */ for (ap = cp = rp; *ap; ap++) { *cp++ = *ap; for (bp = ap; bp[1] && matcheq(*ap, bp[1]); bp++, n--); @@ -3279,30 +3283,47 @@ makearray(LinkList l, int type, int flags, int *np, int *nlp, int *llp) if ((*ap)->flags & (CMF_NOLIST | CMF_MULT)) nl++; } + /* used -O nosort or -V, don't sort */ } else { + /* didn't use -1 or -2, so remove all duplicates (efficient) */ if (!(flags & CGF_UNIQALL) && !(flags & CGF_UNIQCON)) { - int dup; - - for (ap = rp; *ap; ap++) { - for (bp = cp = ap + 1; *bp; bp++) { - if (!matcheq(*ap, *bp)) - *cp++ = *bp; - else + int dup, del = 0; + + /* To avoid O(n^2) here, sort a copy of the list, then remove marked elements */ + matchorder = flags; + Cmatch *sp, *asp; + sp = (Cmatch *) zhalloc((n + 1) * sizeof(Cmatch)); + memcpy(sp, rp, (n + 1) * sizeof(Cmatch)); + qsort((void *) sp, n, sizeof(Cmatch), + (int (*) (const void *, const void *))matchcmp); + for (asp = sp + 1; *asp; asp++) { + Cmatch *ap = asp - 1, *bp = asp; + if (matcheq(*ap, *bp)) { + bp[0]->flags = CMF_DELETE; + del = 1; + } else if (!ap[0]->disp) { + /* Mark those, that would show the same string in the list. */ + for (dup = 0; bp[0] && !(bp[0])->disp && + !strcmp((*ap)->str, (bp[0])->str); bp = ++sp) { + (bp[0])->flags |= CMF_MULT; + dup = 1; + } + if (dup) + (*ap)->flags |= CMF_FMULT; + } + } + if (del) { + int n_orig = n; + for (bp = rp, ap = rp; bp < rp + n_orig; ap++, bp++) { + while (bp < rp + n_orig && (bp[0]->flags & CMF_DELETE)) { + bp++; n--; + } + *ap = *bp; } - *cp = NULL; - if (!(*ap)->disp) { - for (dup = 0, bp = ap + 1; *bp; bp++) - if (!(*bp)->disp && - !((*bp)->flags & CMF_MULT) && - !strcmp((*ap)->str, (*bp)->str)) { - (*bp)->flags |= CMF_MULT; - dup = 1; - } - if (dup) - (*ap)->flags |= CMF_FMULT; - } + *ap = NULL; } + /* passed -1 but not -2, so remove consecutive duplicates (efficient) */ } else if (!(flags & CGF_UNIQCON)) { int dup; diff --git a/Src/Zle/complete.c b/Src/Zle/complete.c index 67a60963e..342611f1f 100644 --- a/Src/Zle/complete.c +++ b/Src/Zle/complete.c @@ -518,7 +518,7 @@ parse_class(Cpattern p, char *iptr) ch = range_type((char *)iptr, nptr-iptr); iptr = nptr + 2; if (ch != PP_UNKWN) - *optr++ = STOUC(Meta) + ch; + *optr++ = (unsigned char) Meta + ch; } else { /* characters stay metafied */ char *ptr1 = iptr; @@ -829,7 +829,9 @@ bin_compadd(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) ca_args: - if (mstr && (match = parse_cmatcher(name, mstr)) == pcm_err) { + if (mstr && (dat.aflags & CAF_MATCH) && + (match = parse_cmatcher(name, mstr)) == pcm_err) + { zsfree(mstr); zfree(dat.dpar, dparsize); return 1; diff --git a/Src/Zle/complist.c b/Src/Zle/complist.c index 0dc64db6a..5619160a9 100644 --- a/Src/Zle/complist.c +++ b/Src/Zle/complist.c @@ -291,12 +291,12 @@ getcolval(char *s, int multi) case '?': *p = '\177'; break; default: if (*s >= '0' && *s <= '7') { - int i = STOUC(*s); + int i = (unsigned char) *s; if (*++s >= '0' && *s <= '7') { - i = (i * 8) + STOUC(*s); + i = (i * 8) + (unsigned char) *s; if (*++s >= '0' && *s <= '7') - i = (i * 8) + STOUC(*s); + i = (i * 8) + (unsigned char) *s; } *p = (char) i; } else @@ -305,7 +305,7 @@ getcolval(char *s, int multi) } else if (*s == '^') { if ((s[1] >= '@' && s[1] <= '_') || (s[1] >= 'a' && s[1] <= 'z')) - *p = (char) (STOUC(*s) & ~0x60); + *p = (char) ((unsigned char) *s & ~0x60); else if (s[1] == '?') *p = '\177'; else { @@ -794,7 +794,7 @@ clnicezputs(int do_colors, char *s, int ml) */ for (t = sptr; *t; t++) { /* Input is metafied... */ - int nc = (*t == Meta) ? STOUC(*++t ^ 32) : STOUC(*t); + int nc = (*t == Meta) ? (unsigned char) (*++t ^ 32) : (unsigned char) *t; /* Is the screen full? */ if (ml == mlend - 1 && col == zterm_columns - 1) { mlprinted = ml - oml; @@ -852,7 +852,7 @@ clnicezputs(int do_colors, char *s, int ml) cc = *s++ ^ 32; for (t = nicechar(cc); *t; t++) { - int nc = (*t == Meta) ? STOUC(*++t ^ 32) : STOUC(*t); + int nc = (*t == Meta) ? (unsigned char) (*++t ^ 32) : (unsigned char) *t; if (ml == mlend - 1 && col == zterm_columns - 1) { mlprinted = ml - oml; return 0; @@ -1072,7 +1072,7 @@ static int compprintfmt(char *fmt, int n, int dopr, int doesc, int ml, int *stop) { char *p, nc[2*DIGBUFSIZE + 12], nbuf[2*DIGBUFSIZE + 12]; - int l = 0, cc = 0, b = 0, s = 0, u = 0, m, ask, beg, stat; + int l = 0, cc = 0, m, ask, beg, stat; if ((stat = !fmt)) { if (mlbeg >= 0) { @@ -1118,48 +1118,46 @@ compprintfmt(char *fmt, int n, int dopr, int doesc, int ml, int *stop) m = 0; switch (cchar) { case ZWC('%'): - if (dopr == 1) + if (dopr == 1) { + applytextattributes(0); putc('%', shout); + } cc++; break; case ZWC('n'): if (!stat) { sprintf(nc, "%d", n); - if (dopr == 1) + if (dopr == 1) { + applytextattributes(0); fputs(nc, shout); + } /* everything here is ASCII... */ cc += strlen(nc); } break; case ZWC('B'): - b = 1; if (dopr) - tcout(TCBOLDFACEBEG); + tsetattrs(TXTBOLDFACE); break; case ZWC('b'): - b = 0; m = 1; if (dopr) - tcout(TCALLATTRSOFF); + tunsetattrs(TXTBOLDFACE); break; case ZWC('S'): - s = 1; if (dopr) - tcout(TCSTANDOUTBEG); + tsetattrs(TXTSTANDOUT); break; case ZWC('s'): - s = 0; m = 1; if (dopr) - tcout(TCSTANDOUTEND); + tunsetattrs(TXTSTANDOUT); break; case ZWC('U'): - u = 1; if (dopr) - tcout(TCUNDERLINEBEG); + tsetattrs(TXTUNDERLINE); break; case ZWC('u'): - u = 0; m = 1; if (dopr) - tcout(TCUNDERLINEEND); + tunsetattrs(TXTUNDERLINE); break; case ZWC('F'): case ZWC('K'): @@ -1173,20 +1171,28 @@ compprintfmt(char *fmt, int n, int dopr, int doesc, int ml, int *stop) } else atr = match_colour(NULL, is_fg, arg); if (atr != TXT_ERROR && dopr) - set_colour_attribute(atr, is_fg ? COL_SEQ_FG : - COL_SEQ_BG, 0); + tsetattrs(atr); break; case ZWC('f'): if (dopr) - set_colour_attribute(TXTNOFGCOLOUR, COL_SEQ_FG, 0); + tunsetattrs(TXTFGCOLOUR); break; case ZWC('k'): if (dopr) - set_colour_attribute(TXTNOBGCOLOUR, COL_SEQ_BG, 0); + tunsetattrs(TXTBGCOLOUR); + break; + case ZWC('H'): + if (*p == '{') { + p = parsehighlight(p + 1, '}', &atr); + if (atr != TXT_ERROR && dopr) + treplaceattrs(atr); + } break; case ZWC('{'): if (arg) cc += arg; + if (dopr) + applytextattributes(0); for (; *p && (*p != '%' || p[1] != '}'); p++) if (dopr) putc(*p == Meta ? *++p ^ 32 : *p, shout); @@ -1197,7 +1203,7 @@ compprintfmt(char *fmt, int n, int dopr, int doesc, int ml, int *stop) if (stat) { sprintf(nc, "%d/%d", (n ? mlastm : mselect), listdat.nlist); - m = 2; + m = 1; } break; case ZWC('M'): @@ -1205,20 +1211,20 @@ compprintfmt(char *fmt, int n, int dopr, int doesc, int ml, int *stop) sprintf(nbuf, "%d/%d", (n ? mlastm : mselect), listdat.nlist); sprintf(nc, "%-9s", nbuf); - m = 2; + m = 1; } break; case ZWC('l'): if (stat) { sprintf(nc, "%d/%d", ml + 1, listdat.nlines); - m = 2; + m = 1; } break; case ZWC('L'): if (stat) { sprintf(nbuf, "%d/%d", ml + 1, listdat.nlines); sprintf(nc, "%-9s", nbuf); - m = 2; + m = 1; } break; case ZWC('p'): @@ -1230,7 +1236,7 @@ compprintfmt(char *fmt, int n, int dopr, int doesc, int ml, int *stop) ((ml + 1) * 100) / listdat.nlines); else strcpy(nc, "Top"); - m = 2; + m = 1; } break; case ZWC('P'): @@ -1242,25 +1248,19 @@ compprintfmt(char *fmt, int n, int dopr, int doesc, int ml, int *stop) ((ml + 1) * 100) / listdat.nlines); else strcpy(nc, "Top "); - m = 2; + m = 1; } break; } - if (m == 2 && dopr == 1) { + if (m && dopr) { /* nc only contains ASCII text */ int l = strlen(nc); if (l + cc > zterm_columns - 2) nc[l -= l + cc - (zterm_columns - 2)] = '\0'; + applytextattributes(0); fputs(nc, shout); cc += l; - } else if (dopr && m == 1) { - if (b) - tcout(TCBOLDFACEBEG); - if (s) - tcout(TCSTANDOUTBEG); - if (u) - tcout(TCUNDERLINEBEG); } } else break; @@ -1276,6 +1276,7 @@ compprintfmt(char *fmt, int n, int dopr, int doesc, int ml, int *stop) cc = 0; } if (dopr == 1) { + applytextattributes(0); if (ml == mlend - 1 && (cc % zterm_columns) == zterm_columns - 1) { dopr = 0; @@ -1311,6 +1312,8 @@ compprintfmt(char *fmt, int n, int dopr, int doesc, int ml, int *stop) } } if (dopr) { + treplaceattrs(0); + applytextattributes(0); if (!(cc % zterm_columns)) fputs(" \010", shout); cleareol(); diff --git a/Src/Zle/compmatch.c b/Src/Zle/compmatch.c index 56e5509a4..ddcecd589 100644 --- a/Src/Zle/compmatch.c +++ b/Src/Zle/compmatch.c @@ -2045,12 +2045,12 @@ join_strs(int la, char *sa, int lb, char *sb) zlelineasstring(line, mp->llen, 0, &convlen, NULL, 0); if (rr <= convlen) { - char *or = rs; + ptrdiff_t diff = rp - rs; int alloclen = (convlen > 20) ? convlen : 20; rs = realloc(rs, (rl += alloclen)); rr += alloclen; - rp += rs - or; + rp = rs + diff; } memcpy(rp, convstr, convlen); rp += convlen; @@ -2073,11 +2073,11 @@ join_strs(int la, char *sa, int lb, char *sb) } else { /* Same character, just take it. */ if (rr <= 1 /* HERE charlen */) { - char *or = rs; + ptrdiff_t diff = rp - rs; rs = realloc(rs, (rl += 20)); rr += 20; - rp += rs - or; + rp = rs + diff; } /* HERE: multibyte char */ *rp++ = *sa; diff --git a/Src/Zle/compresult.c b/Src/Zle/compresult.c index 8b5955819..cd8c7dd64 100644 --- a/Src/Zle/compresult.c +++ b/Src/Zle/compresult.c @@ -612,9 +612,10 @@ instmatch(Cmatch m, int *scs) int pcs = zlemetacs; l = 0; - for (bp = brbeg, brpos = m->brpl, - bradd = (m->pre ? strlen(m->pre) : 0); - bp; bp = bp->next, brpos++) { + bradd = (m->pre ? strlen(m->pre) : 0); + for (bp = brbeg, brpos = m->brpl; + bp && brpos; + bp = bp->next, brpos++) { zlemetacs = a + *brpos + bradd; pcs = zlemetacs; l = strlen(bp->str); @@ -896,7 +897,7 @@ void do_allmatches(UNUSED(int end)) { int first = 1, nm = nmatches - 1, omc = menucmp, oma = menuacc, e; - Cmatch *mc; + Cmatch *mc = 0; struct menuinfo mi; char *p = (brbeg ? ztrdup(lastbrbeg->str) : NULL); @@ -914,10 +915,10 @@ do_allmatches(UNUSED(int end)) #endif } + if (minfo.group) + mc = (minfo.group)->matches; - mc = (minfo.group)->matches; - - while (1) { + while (mc) { if (!((*mc)->flags & CMF_ALL)) { if (!first) accept_last(); @@ -1730,8 +1731,6 @@ calclist(int showall) width < zterm_columns && nth < g->dcount; nth++, tcol++) { - m = *p; - if (tcol == tcols) { tcol = 0; tlines++; @@ -1993,7 +1992,6 @@ printlist(int over, CLPrintFunc printm, int showall) (listdat.onlyexpl & ((*e)->always > 0 ? 2 : 1)))) { if (pnl) { putc('\n', shout); - pnl = 0; ml++; if (cl >= 0 && --cl <= 1) { cl = -1; @@ -2086,7 +2084,6 @@ printlist(int over, CLPrintFunc printm, int showall) (showall || !(m->flags & (CMF_HIDE|CMF_NOLIST)))) { if (pnl) { putc('\n', shout); - pnl = 0; ml++; if (cl >= 0 && --cl <= 1) { cl = -1; @@ -2247,15 +2244,13 @@ iprintm(Cmgroup g, Cmatch *mp, UNUSED(int mc), UNUSED(int ml), int lastc, int wi #ifdef MULTIBYTE_SUPPORT len = mb_niceformat(m->disp, shout, NULL, 0); #else - nicezputs(m->disp, shout); - len = niceztrlen(m->disp); + len = sb_niceformat(m->disp, shout, NULL, 0); #endif } else { #ifdef MULTIBYTE_SUPPORT len = mb_niceformat(m->str, shout, NULL, 0); #else - nicezputs(m->str, shout); - len = niceztrlen(m->str); + len = sb_niceformat(m->str, shout, NULL, 0); #endif if ((g->flags & CGF_FILES) && m->modec) { diff --git a/Src/Zle/computil.c b/Src/Zle/computil.c index b311d6c5f..360667884 100644 --- a/Src/Zle/computil.c +++ b/Src/Zle/computil.c @@ -911,7 +911,7 @@ struct cadef { Caarg rest; /* the rest-argument */ char **defs; /* the original strings */ int ndefs; /* number of ... */ - int lastt; /* last time this was used */ + time_t lastt; /* last time this was used */ Caopt *single; /* array of single-letter options */ char *match; /* -M spec to use */ int argsactive; /* if normal arguments are still allowed */ @@ -1035,7 +1035,7 @@ freecadef(Cadef d) freecaargs(d->rest); zsfree(d->nonarg); if (d->single) - zfree(d->single, 256 * sizeof(Caopt)); + zfree(d->single, 188 * sizeof(Caopt)); zfree(d, sizeof(*d)); d = s; } @@ -1079,6 +1079,21 @@ bslashcolon(char *s) return r; } +/* Get an index into the single array used in struct cadef + * opt is the option letter and pre is either - or + + * we only keep an array for the 94 ASCII characters from ! to ~ so + * with - and + prefixes, the array is double that at 188 elements + * returns -1 if opt is out-of-range + */ +static int +single_index(char pre, char opt) +{ + if (opt <= 0x20 || opt > 0x7e) + return -1; + + return opt + (pre == '-' ? -0x21 : 94 - 0x21); +} + /* Parse an argument definition. */ static Caarg @@ -1151,8 +1166,8 @@ alloc_cadef(char **args, int single, char *match, char *nonarg, int flags) ret->lastt = time(0); ret->set = NULL; if (single) { - ret->single = (Caopt *) zalloc(256 * sizeof(Caopt)); - memset(ret->single, 0, 256 * sizeof(Caopt)); + ret->single = (Caopt *) zalloc(188 * sizeof(Caopt)); + memset(ret->single, 0, 188 * sizeof(Caopt)); } else ret->single = NULL; ret->match = ztrdup(match); @@ -1558,9 +1573,10 @@ parse_cadef(char *nam, char **args) * pointer for the definition in the array for fast lookup. * But don't treat '--' as a single option called '-' */ - - if (single && name[1] && !name[2] && name[1] != '-') - ret->single[STOUC(name[1])] = opt; + if (single && name[1] && !name[2] && name[1] != '-') { + int sidx = single_index(*name, name[1]); + if (sidx >= 0) ret->single[sidx] = opt; + } if (again == 1) { /* Do it all again for `*-...'. */ @@ -1738,11 +1754,12 @@ ca_get_sopt(Cadef d, char *line, char **end, LinkList *lp) Caopt p, pp = NULL; char pre = *line++; LinkList l = NULL; + int sidx; *lp = NULL; for (p = NULL; *line; line++) { - if ((p = d->single[STOUC(*line)]) && p->active && - p->args && p->name[0] == pre) { + if ((sidx = single_index(pre, *line)) != -1 && + (p = d->single[sidx]) && p->active && p->args) { if (p->type == CAO_NEXT) { if (!l) *lp = l = newlinklist(); @@ -1813,7 +1830,7 @@ ca_get_arg(Cadef d, int n) /* Mark options as inactive. * d: option definitions for a set * pass either: - * xor: a list if exclusions + * xor: a list of exclusions * opts: if set, all options excluded leaving only nornal/rest arguments */ static void @@ -2141,7 +2158,8 @@ ca_parse_line(Cadef d, Cadef all, int multi, int first) /* See if it's an option. */ - if (state.opt == 2 && (state.curopt = ca_get_opt(d, line, 0, &pe)) && + if (state.opt == 2 && (*line == '-' || *line == '+') && + (state.curopt = ca_get_opt(d, line, 0, &pe)) && (state.curopt->type == CAO_OEQUAL ? (compwords[cur] || pe[-1] == '=') : (state.curopt->type == CAO_EQUAL ? @@ -2189,12 +2207,14 @@ ca_parse_line(Cadef d, Cadef all, int multi, int first) state.curopt = NULL; } } else if (state.opt == 2 && d->single && + (*line == '-' || *line == '+') && ((state.curopt = ca_get_sopt(d, line, &pe, &sopts)) || (cur != compcurrent && sopts && nonempty(sopts)))) { /* Or maybe it's a single-letter option? */ char *p; Caopt tmpopt; + int sidx; if (cur != compcurrent && sopts && nonempty(sopts)) state.curopt = (Caopt) uremnode(sopts, firstnode(sopts)); @@ -2212,7 +2232,8 @@ ca_parse_line(Cadef d, Cadef all, int multi, int first) state.singles = (!pe || !*pe); for (p = line + 1; p < pe; p++) { - if ((tmpopt = d->single[STOUC(*p)])) { + if ((sidx = single_index(*line, *p)) != -1 && + (tmpopt = d->single[sidx])) { if (!state.oargs[tmpopt->num]) state.oargs[tmpopt->num] = znewlinklist(); @@ -2914,7 +2935,7 @@ struct cvdef { Cvval vals; /* value definitions */ char **defs; /* original strings */ int ndefs; /* number of ... */ - int lastt; /* last time used */ + time_t lastt; /* last time used */ int words; /* if to look at other words */ }; @@ -4362,7 +4383,7 @@ cfp_matcher_range(Cmatcher *ms, char *add) * word pattern. */ if ((ind = pattern_match_equivalence - (m->word, ind, mt, addc)) != CHR_INVALID) { + (m->word, ind+1, mt, addc)) != CHR_INVALID) { if (ret) { if (imeta(ind)) { *p++ = Meta; diff --git a/Src/Zle/textobjects.c b/Src/Zle/textobjects.c index c93777b65..a68c5296e 100644 --- a/Src/Zle/textobjects.c +++ b/Src/Zle/textobjects.c @@ -283,9 +283,9 @@ selectargument(UNUSED(char **args)) free(linein); if (IS_THINGY(bindk, selectinshellword)) { - ZLE_CHAR_T *match = ZWS("`\'\""); - ZLE_CHAR_T *lmatch = ZWS("\'({"), *rmatch = ZWS("\')}"); - ZLE_CHAR_T *ematch = match, *found; + const ZLE_CHAR_T *match = ZWS("`\'\""); + const ZLE_CHAR_T *lmatch = ZWS("\'({"), *rmatch = ZWS("\')}"); + const ZLE_CHAR_T *ematch = match, *found; int start, end = zlecs; /* for 'in' widget, don't include initial blanks ... */ while (mark < zlecs && ZC_iblank(zleline[mark])) diff --git a/Src/Zle/zle.h b/Src/Zle/zle.h index 391586c4a..5bb9e7a5e 100644 --- a/Src/Zle/zle.h +++ b/Src/Zle/zle.h @@ -186,7 +186,7 @@ typedef struct thingy *Thingy; /* widgets (ZLE functions) */ -typedef int (*ZleIntFunc) _((char **)); +typedef int (*ZleIntFunc) (char **); struct widget { int flags; /* flags (see below) */ @@ -258,6 +258,9 @@ struct modifier { #define MOD_NULL (1<<5) /* throw away text for the vi cut buffer */ #define MOD_CHAR (1<<6) /* force character-wise movement */ #define MOD_LINE (1<<7) /* force line-wise movement */ +#define MOD_PRI (1<<8) /* OS primary selection for the vi cut buffer */ +#define MOD_CLIP (1<<9) /* OS clipboard for the vi cut buffer */ +#define MOD_OSSEL (MOD_PRI | MOD_CLIP) /* either system selection */ /* current modifier status */ @@ -316,7 +319,7 @@ struct vichange { typedef struct keymap *Keymap; -typedef void (*KeyScanFunc) _((char *, Thingy, char *, void *)); +typedef void (*KeyScanFunc) (char *, Thingy, char *, void *); #define invicmdmode() (!strcmp(curkeymapname, "vicmd")) @@ -432,6 +435,8 @@ enum { struct region_highlight { /* Attributes turned on in the region */ zattr atr; + /* Priority for this region relative to others that overlap */ + int layer; /* Start of the region */ int start; /* Start of the region in metafied ZLE line */ @@ -487,11 +492,7 @@ typedef struct { */ REFRESH_CHAR chr; /* - * Its attributes. 'On' attributes (TXT_ATTR_ON_MASK) are - * applied before the character, 'off' attributes (TXT_ATTR_OFF_MASK) - * after it. 'On' attributes are present for all characters that - * need the effect; 'off' attributes are only present for the - * last character in the sequence. + * Its attributes. */ zattr atr; } REFRESH_ELEMENT; @@ -523,7 +524,7 @@ typedef REFRESH_ELEMENT *REFRESH_STRING; ((int)((unsigned)(x) - ZSH_INVALID_WCHAR_BASE)) /* Turn a single byte character into a private wide character */ #define ZSH_CHAR_TO_INVALID_WCHAR(x) \ - ((wchar_t)(STOUC(x) + ZSH_INVALID_WCHAR_BASE)) + ((wchar_t)((unsigned char) x + ZSH_INVALID_WCHAR_BASE)) #endif diff --git a/Src/Zle/zle_hist.c b/Src/Zle/zle_hist.c index cfaa70dae..0fdad70d9 100644 --- a/Src/Zle/zle_hist.c +++ b/Src/Zle/zle_hist.c @@ -68,6 +68,13 @@ Keymap isearch_keymap; */ #define GETZLETEXT(ent) ((ent)->zle_text ? (ent)->zle_text : (ent)->node.nam) +/* + * Flag that edits have been made to a zle line. + * If not set, nothing to forget. + */ +/**/ +int have_edits = 0; + /**/ void remember_edits(void) @@ -81,6 +88,7 @@ remember_edits(void) if (ent->zle_text) free(ent->zle_text); ent->zle_text = zlemetaline ? ztrdup(line) : line; + have_edits = 1; } else if (!zlemetaline) free(line); } @@ -90,6 +98,10 @@ remember_edits(void) void forget_edits(void) { + if (!have_edits) { + return; + } + have_edits = 0; Histent he; for (he = hist_ring; he; he = up_histent(he)) { diff --git a/Src/Zle/zle_keymap.c b/Src/Zle/zle_keymap.c index d90838f03..5012917f5 100644 --- a/Src/Zle/zle_keymap.c +++ b/Src/Zle/zle_keymap.c @@ -404,7 +404,7 @@ static void scankeys(HashNode hn, UNUSED(int flags)) { Key k = (Key) hn; - int f = k->nam[0] == Meta ? STOUC(k->nam[1])^32 : STOUC(k->nam[0]); + int f = k->nam[0] == Meta ? (unsigned char) k->nam[1]^32 : (unsigned char) k->nam[0]; char m[3]; while(skm_last < f) { @@ -566,7 +566,7 @@ mod_export int bindkey(Keymap km, const char *seq, Thingy bind, char *str) { Key k; - int f = seq[0] == Meta ? STOUC(seq[1])^32 : STOUC(seq[0]); + int f = seq[0] == Meta ? (unsigned char) seq[1]^32 : (unsigned char) seq[0]; char *buf, *ptr; if(km->flags & KM_IMMUTABLE) @@ -661,7 +661,7 @@ keybind(Keymap km, char *seq, char **strp) Key k; if(ztrlen(seq) == 1) { - int f = seq[0] == Meta ? STOUC(seq[1])^32 : STOUC(seq[0]); + int f = seq[0] == Meta ? (unsigned char) seq[1]^32 : (unsigned char) seq[0]; Thingy bind = km->first[f]; if(bind) @@ -687,7 +687,7 @@ keyisprefix(Keymap km, char *seq) if(!*seq) return 1; if(ztrlen(seq) == 1) { - int f = seq[0] == Meta ? STOUC(seq[1])^32 : STOUC(seq[0]); + int f = seq[0] == Meta ? (unsigned char) seq[1]^32 : (unsigned char) seq[0]; if(km->first[f]) return 0; @@ -745,7 +745,7 @@ bin_bindkey(char *name, char **argv, Options ops, UNUSED(int func)) static struct opn { char o; char selp; - int (*func) _((char *, char *, Keymap, char **, Options, char)); + int (*func) (char *, char *, Keymap, char **, Options, char); int min, max; } const opns[] = { { 'l', 0, bin_bindkey_lsmaps, 0, -1 }, @@ -764,10 +764,10 @@ bin_bindkey(char *name, char **argv, Options ops, UNUSED(int func)) int n; /* select operation and ensure no clashing arguments */ - for(op = opns; op->o && !OPT_ISSET(ops,STOUC(op->o)); op++) ; + for(op = opns; op->o && !OPT_ISSET(ops,(unsigned char) op->o); op++) ; if(op->o) for(opp = op; (++opp)->o; ) - if(OPT_ISSET(ops,STOUC(opp->o))) { + if(OPT_ISSET(ops,(unsigned char) opp->o)) { zwarnnam(name, "incompatible operation selection options"); return 1; } @@ -1049,7 +1049,7 @@ bin_bindkey_bind(char *name, char *kmname, Keymap km, char **argv, Options ops, char m[3]; if(len < 2 || len > 2 + (bseq[1] == '-') || - (first = STOUC(bseq[0])) > (last = STOUC(bseq[len - 1]))) { + (first = (unsigned char) bseq[0]) > (last = (unsigned char) bseq[len - 1])) { zwarnnam(name, "malformed key range `%s'", useq); ret = 1; } else { @@ -1149,8 +1149,8 @@ scanbindlist(char *seq, Thingy bind, char *str, void *magic) if(bind == bs->bind && (bind || !strcmp(str, bs->str)) && ztrlen(seq) == 1 && ztrlen(bs->lastseq) == 1) { int l = bs->lastseq[1] ? - STOUC(bs->lastseq[1]) ^ 32 : STOUC(bs->lastseq[0]); - int t = seq[1] ? STOUC(seq[1]) ^ 32 : STOUC(seq[0]); + (unsigned char) bs->lastseq[1] ^ 32 : (unsigned char) bs->lastseq[0]; + int t = seq[1] ? (unsigned char) seq[1] ^ 32 : (unsigned char) seq[0]; if(t == l + 1) { zsfree(bs->lastseq); @@ -1315,7 +1315,7 @@ default_bindings(void) Keymap vismap = newkeymap(NULL, "visual"); Keymap smap = newkeymap(NULL, ".safe"); Keymap vimaps[2], vilmaps[2], kptr; - char buf[3], *ed; + char buf[3]; int i; /* vi insert mode and emacs mode: * @@ -1445,20 +1445,14 @@ default_bindings(void) } /* Put the keymaps in the right namespace. The "main" keymap * - * will be linked to the "emacs" keymap, except that if VISUAL * - * or EDITOR contain the string "vi" then it will be linked to * - * the "viins" keymap. */ + * will be linked to the "emacs" keymap. */ linkkeymap(vmap, "viins", 0); linkkeymap(emap, "emacs", 0); linkkeymap(amap, "vicmd", 0); linkkeymap(oppmap, "viopp", 0); linkkeymap(vismap, "visual", 0); linkkeymap(smap, ".safe", 1); - if (((ed = zgetenv("VISUAL")) && strstr(ed, "vi")) || - ((ed = zgetenv("EDITOR")) && strstr(ed, "vi"))) - linkkeymap(vmap, "main", 0); - else - linkkeymap(emap, "main", 0); + linkkeymap(emap, "main", 0); /* the .safe map cannot be modified or deleted */ smap->flags |= KM_IMMUTABLE; @@ -1526,10 +1520,10 @@ getrestchar_keybuf(void) */ while (1) { if (bufind < buflen) { - c = STOUC(keybuf[bufind++]); + c = (unsigned char) keybuf[bufind++]; if (c == Meta) { DPUTS(bufind == buflen, "Meta at end of keybuf"); - c = STOUC(keybuf[bufind++]) ^ 32; + c = (unsigned char) keybuf[bufind++] ^ 32; } } else { /* @@ -1586,7 +1580,7 @@ getkeymapcmd(Keymap km, Thingy *funcp, char **strp) Thingy func = t_undefinedkey; char *str = NULL; int lastlen = 0, lastc = lastchar; - int timeout = 0; + int timeout = 0, csi = 0; keybuflen = 0; keybuf[0] = 0; @@ -1636,7 +1630,31 @@ getkeymapcmd(Keymap km, Thingy *funcp, char **strp) } #endif } - if (!ispfx) + + /* CSI key sequences have a well defined structure so if we currently + * have an incomplete one, loop so the rest of it will be included in + * the key sequence if that arrives within the timeout. */ + if (!csi && keybuflen >= 3 && keybuf[keybuflen - 3] == '\033' && + keybuf[keybuflen - 2] == '[') + csi = keybuflen - 1; + if (csi) { + if (keybuf[keybuflen - 2] == Meta || keybuf[keybuflen - 1] < 0x20 + || keybuf[keybuflen - 1] > 0x3f) { + /* If we reach the end of a valid CSI sequence and the matched key + * binding is for part of the CSI introduction, select instead the + * undefined-key widget and consume the full sequence from the + * input buffer. */ + if (keybuf[keybuflen - 1] >= 0x40 && + keybuf[keybuflen - 1] <= 0x7e && lastlen > csi - 2 && + lastlen <= csi) { + func = t_undefinedkey; + lastlen = keybuflen; + } + csi = 0; + } + } + + if (!ispfx && !csi) break; } if(!lastlen && keybuflen) diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c index 9edf30e01..1afb1bf58 100644 --- a/Src/Zle/zle_main.c +++ b/Src/Zle/zle_main.c @@ -737,6 +737,7 @@ raw_getbyte(long do_keytmout, char *cptr, int full) ) { /* Handle the fd. */ char *fdbuf; + Thingy save_lbindk = refthingy(lbindk); { char buf[BDIGBUFSIZE]; convbase(buf, lwatch_fd->fd, 10); @@ -779,6 +780,8 @@ raw_getbyte(long do_keytmout, char *cptr, int full) */ errtry = 1; } + unrefthingy(lbindk); + lbindk = save_lbindk; } } /* Function may have invalidated the display. */ @@ -876,7 +879,7 @@ getbyte(long do_keytmout, int *timeout, int full) #endif if (kungetct) - ret = STOUC(kungetbuf[--kungetct]); + ret = (unsigned char) kungetbuf[--kungetct]; else { for (;;) { int q = queue_signal_level(); @@ -940,7 +943,7 @@ getbyte(long do_keytmout, int *timeout, int full) else if (cc == '\n') cc = '\r'; - ret = STOUC(cc); + ret = (unsigned char) cc; } /* * curvichg.buf is raw bytes, not wide characters, so is dealt @@ -1230,9 +1233,9 @@ zleread(char **lp, char **rp, int flags, int context, char *init, char *finish) char *pptbuf; int pptlen; - pptbuf = unmetafy(promptexpand(lp ? *lp : NULL, 0, NULL, NULL, - &pmpt_attr), + pptbuf = unmetafy(promptexpand(lp ? *lp : NULL, 0, NULL, NULL), &pptlen); + pmpt_attr = txtcurrentattrs; write_loop(2, pptbuf, pptlen); free(pptbuf); return shingetline(); @@ -1267,10 +1270,13 @@ zleread(char **lp, char **rp, int flags, int context, char *init, char *finish) fetchttyinfo = 0; trashedzle = 0; raw_lp = lp; - lpromptbuf = promptexpand(lp ? *lp : NULL, 1, NULL, NULL, &pmpt_attr); + txtcurrentattrs = txtpendingattrs = txtunknownattrs = 0; + lpromptbuf = promptexpand(lp ? *lp : NULL, 1, NULL, NULL); + pmpt_attr = txtcurrentattrs; raw_rp = rp; - rpmpt_attr = pmpt_attr; - rpromptbuf = promptexpand(rp ? *rp : NULL, 1, NULL, NULL, &rpmpt_attr); + rpromptbuf = promptexpand(rp ? *rp : NULL, 1, NULL, NULL); + rpmpt_attr = txtcurrentattrs; + prompt_attr = mixattrs(pmpt_attr, rpmpt_attr); free_prepostdisplay(); zlereadflags = flags; @@ -2009,17 +2015,18 @@ reexpandprompt(void) char *new_lprompt, *new_rprompt; looping = reexpanding; - new_lprompt = promptexpand(raw_lp ? *raw_lp : NULL, 1, NULL, NULL, - &pmpt_attr); + txtcurrentattrs = txtpendingattrs = txtunknownattrs = 0; + new_lprompt = promptexpand(raw_lp ? *raw_lp : NULL, 1, NULL, NULL); + pmpt_attr = txtcurrentattrs; free(lpromptbuf); lpromptbuf = new_lprompt; if (looping != reexpanding) continue; - rpmpt_attr = pmpt_attr; - new_rprompt = promptexpand(raw_rp ? *raw_rp : NULL, 1, NULL, NULL, - &rpmpt_attr); + new_rprompt = promptexpand(raw_rp ? *raw_rp : NULL, 1, NULL, NULL); + rpmpt_attr = txtcurrentattrs; + prompt_attr = mixattrs(pmpt_attr, rpmpt_attr); free(rpromptbuf); rpromptbuf = new_rprompt; } while (looping != reexpanding); @@ -2065,6 +2072,8 @@ trashzle(void) trashedzle = 1; zrefresh(); showinglist = sl; + treplaceattrs(prompt_attr); + applytextattributes(0); moveto(nlnct, 0); if (clearflag && tccan(TCCLEAREOD)) { tcout(TCCLEAREOD); diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c index d9d9503e2..f076bdd61 100644 --- a/Src/Zle/zle_refresh.c +++ b/Src/Zle/zle_refresh.c @@ -36,8 +36,8 @@ * non-zero width followed by an arbitrary (but typically small) * number of characters that have zero width (combining characters). * - * The allocated size for each array is given by ?mw_size; nmw_ind - * is the next free element, i.e. nmwbuf[nmw_ind] will be the next + * The allocated size for each array is given by omw_size and nmw_size; + * nmw_ind is the next free element, i.e. nmwbuf[nmw_ind] will be the next * element to be written (we never insert into omwbuf). We initialise * nmw_ind to 1 to avoid the index stored in the character looking like a * NULL. This wastees a word but it's safer than messing with pointers. @@ -149,7 +149,7 @@ char *lpromptbuf, *rpromptbuf; /* Text attributes after displaying prompts */ /**/ -zattr pmpt_attr, rpmpt_attr; +zattr pmpt_attr, rpmpt_attr, prompt_attr; /* number of lines displayed */ @@ -203,12 +203,18 @@ int predisplaylen, postdisplaylen; /* - * Attributes used by default on the command line, and - * attributes for highlighting special (unprintable) characters - * displayed on screen. + * Attributes used by default on the command line, + * for highlighting special (unprintable) characters displayed on screen, + * and for ellipsis continuation markers. */ -static zattr default_atr_on, special_atr_on; +static zattr default_attr, special_attr, ellipsis_attr; + +/* + * Layer applied to highlighting for special characters + */ + +static int special_layer; /* * Array of region highlights, no special termination. @@ -245,18 +251,20 @@ char *tcout_func_name; int cost; # define SELECT_ADD_COST(X) (cost += X) -# define zputc(a) (zwcputc(a, NULL), cost++) +# define zputc(a) (zwcputc(a), cost++) # define zwrite(a, b) (zwcwrite((a), (b)), \ cost += ((b) * ZLE_CHAR_SIZE)) #else # define SELECT_ADD_COST(X) -# define zputc(a) zwcputc(a, NULL) +# define zputc(a) zwcputc(a) # define zwrite(a, b) zwcwrite((a), (b)) #endif -static const REFRESH_ELEMENT zr_cr = { ZWC('\r'), 0 }; -static const REFRESH_ELEMENT zr_dt = { ZWC('.'), 0 }; -static const REFRESH_ELEMENT zr_nl = { ZWC('\n'), 0 }; +static const REFRESH_ELEMENT zr_cr = { ZWC('\r'), TXT_ERROR }; +#ifdef MULTIBYTE_SUPPORT +static const REFRESH_ELEMENT zr_dt = { ZWC('.'), TXT_ERROR }; +#endif +static const REFRESH_ELEMENT zr_nl = { ZWC('\n'), TXT_ERROR }; static const REFRESH_ELEMENT zr_sp = { ZWC(' '), 0 }; static const REFRESH_ELEMENT zr_zr = { ZWC('\0'), 0 }; @@ -267,10 +275,10 @@ static const REFRESH_ELEMENT zr_zr = { ZWC('\0'), 0 }; static const REFRESH_ELEMENT zr_end_ellipsis[] = { { ZWC(' '), 0 }, { ZWC('<'), 0 }, - { ZWC('.'), 0 }, - { ZWC('.'), 0 }, - { ZWC('.'), 0 }, - { ZWC('.'), 0 }, + { ZWC('.'), TXT_ERROR }, + { ZWC('.'), TXT_ERROR }, + { ZWC('.'), TXT_ERROR }, + { ZWC('.'), TXT_ERROR }, { ZWC(' '), 0 }, }; #define ZR_END_ELLIPSIS_SIZE \ @@ -279,16 +287,16 @@ static const REFRESH_ELEMENT zr_end_ellipsis[] = { static const REFRESH_ELEMENT zr_mid_ellipsis1[] = { { ZWC(' '), 0 }, { ZWC('<'), 0 }, - { ZWC('.'), 0 }, - { ZWC('.'), 0 }, - { ZWC('.'), 0 }, - { ZWC('.'), 0 }, + { ZWC('.'), TXT_ERROR }, + { ZWC('.'), TXT_ERROR }, + { ZWC('.'), TXT_ERROR }, + { ZWC('.'), TXT_ERROR }, }; #define ZR_MID_ELLIPSIS1_SIZE \ ((int)(sizeof(zr_mid_ellipsis1)/sizeof(zr_mid_ellipsis1[0]))) static const REFRESH_ELEMENT zr_mid_ellipsis2[] = { - { ZWC('>'), 0 }, + { ZWC('>'), TXT_ERROR }, { ZWC(' '), 0 }, }; #define ZR_MID_ELLIPSIS2_SIZE \ @@ -296,10 +304,10 @@ static const REFRESH_ELEMENT zr_mid_ellipsis2[] = { static const REFRESH_ELEMENT zr_start_ellipsis[] = { { ZWC('>'), 0 }, - { ZWC('.'), 0 }, - { ZWC('.'), 0 }, - { ZWC('.'), 0 }, - { ZWC('.'), 0 }, + { ZWC('.'), TXT_ERROR }, + { ZWC('.'), TXT_ERROR }, + { ZWC('.'), TXT_ERROR }, + { ZWC('.'), TXT_ERROR }, }; #define ZR_START_ELLIPSIS_SIZE \ ((int)(sizeof(zr_start_ellipsis)/sizeof(zr_start_ellipsis[0]))) @@ -314,14 +322,15 @@ static void zle_set_highlight(void) { char **atrs = getaparam("zle_highlight"); - int special_atr_on_set = 0; - int region_atr_on_set = 0; - int isearch_atr_on_set = 0; - int suffix_atr_on_set = 0; - int paste_atr_on_set = 0; + int special_attr_set = 0; + int region_attr_set = 0; + int isearch_attr_set = 0; + int suffix_attr_set = 0; + int paste_attr_set = 0; + int ellipsis_attr_set = 0; struct region_highlight *rhp; - special_atr_on = default_atr_on = 0; + special_attr = default_attr = 0; if (!region_highlights) { region_highlights = (struct region_highlight *) zshcalloc(N_SPECIAL_HIGHLIGHTS*sizeof(struct region_highlight)); @@ -334,46 +343,63 @@ zle_set_highlight(void) } } + /* Default layers */ + region_highlights[0].layer = 20; /* region */ + region_highlights[1].layer = 20; /* isearch */ + region_highlights[2].layer = 10; /* suffix */ + region_highlights[3].layer = 15; /* paste */ + special_layer = 30; + if (atrs) { for (; *atrs; atrs++) { if (!strcmp(*atrs, "none")) { /* reset attributes for consistency... usually unnecessary */ - special_atr_on = default_atr_on = 0; - special_atr_on_set = 1; - paste_atr_on_set = region_atr_on_set = - isearch_atr_on_set = suffix_atr_on_set = 1; + special_attr = default_attr = 0; + special_attr_set = 1; + paste_attr_set = region_attr_set = + isearch_attr_set = suffix_attr_set = 1; } else if (strpfx("default:", *atrs)) { - match_highlight(*atrs + 8, &default_atr_on); + match_highlight(*atrs + 8, &default_attr, NULL); } else if (strpfx("special:", *atrs)) { - match_highlight(*atrs + 8, &special_atr_on); - special_atr_on_set = 1; + match_highlight(*atrs + 8, &special_attr, &special_layer); + special_attr_set = 1; } else if (strpfx("region:", *atrs)) { - match_highlight(*atrs + 7, ®ion_highlights[0].atr); - region_atr_on_set = 1; + match_highlight(*atrs + 7, &(region_highlights[0].atr), + &(region_highlights[0].layer)); + region_attr_set = 1; } else if (strpfx("isearch:", *atrs)) { - match_highlight(*atrs + 8, &(region_highlights[1].atr)); - isearch_atr_on_set = 1; + match_highlight(*atrs + 8, &(region_highlights[1].atr), + &(region_highlights[1].layer)); + isearch_attr_set = 1; } else if (strpfx("suffix:", *atrs)) { - match_highlight(*atrs + 7, &(region_highlights[2].atr)); - suffix_atr_on_set = 1; + match_highlight(*atrs + 7, &(region_highlights[2].atr), + &(region_highlights[2].layer)); + suffix_attr_set = 1; } else if (strpfx("paste:", *atrs)) { - match_highlight(*atrs + 6, &(region_highlights[3].atr)); - paste_atr_on_set = 1; + match_highlight(*atrs + 6, &(region_highlights[3].atr), + &(region_highlights[3].layer)); + paste_attr_set = 1; + } else if (strpfx("ellipsis:", *atrs)) { + match_highlight(*atrs + 9, &ellipsis_attr, NULL); + ellipsis_attr_set = 1; } } } - /* Defaults */ - if (!special_atr_on_set) - special_atr_on = TXTSTANDOUT; - if (!region_atr_on_set) + /* Default attributes */ + if (!special_attr_set) + special_attr = TXTSTANDOUT; + if (!region_attr_set) region_highlights[0].atr = TXTSTANDOUT; - if (!isearch_atr_on_set) + if (!isearch_attr_set) region_highlights[1].atr = TXTUNDERLINE; - if (!suffix_atr_on_set) + if (!suffix_attr_set) region_highlights[2].atr = TXTBOLDFACE; - if (!paste_atr_on_set) + if (!paste_attr_set) region_highlights[3].atr = TXTSTANDOUT; + if (!ellipsis_attr_set) + ellipsis_attr = TXTBGCOLOUR | ((zattr) 3 << TXT_ATTR_BG_COL_SHIFT) | + TXTFGCOLOUR | ((zattr) 4 << TXT_ATTR_FG_COL_SHIFT); allocate_colour_buffer(); } @@ -398,14 +424,13 @@ zle_free_highlight(void) char ** get_region_highlight(UNUSED(Param pm)) { - int arrsize = n_region_highlights; + int arrsize = n_region_highlights - N_SPECIAL_HIGHLIGHTS; char **retarr, **arrp; struct region_highlight *rhp; /* region_highlights may not have been set yet */ - if (!arrsize) + if (!n_region_highlights) return hmkarray(NULL); - arrsize -= N_SPECIAL_HIGHLIGHTS; DPUTS(arrsize < 0, "arrsize is negative from n_region_highlights"); arrp = retarr = (char **)zhalloc((arrsize+1)*sizeof(char *)); @@ -413,20 +438,18 @@ get_region_highlight(UNUSED(Param pm)) for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS; arrsize--; rhp++, arrp++) { - char digbuf1[DIGBUFSIZE], digbuf2[DIGBUFSIZE]; - int atrlen, alloclen; - const char memo_equals[] = "memo="; - - sprintf(digbuf1, "%d", rhp->start); - sprintf(digbuf2, "%d", rhp->end); - - atrlen = output_highlight(rhp->atr, NULL); - alloclen = atrlen + strlen(digbuf1) + strlen(digbuf2) + - 3; /* 2 spaces, 1 terminating NUL */ + char digbuf[2 * DIGBUFSIZE], layerbuf[7 + DIGBUFSIZE]; + int offset; + const char memo_equals[] = " memo="; + int alloclen = sprintf(digbuf, "%d %d", rhp->start, rhp->end) + + output_highlight(rhp->atr, NULL) + + 2; /* space and terminating NUL */ if (rhp->flags & ZRH_PREDISPLAY) - alloclen += 2; /* "P " */ + alloclen++; /* "P" */ + if (rhp->layer != 10) + alloclen += sprintf(layerbuf, ",layer=%d", rhp->layer); if (rhp->memo) - alloclen += 1 /* space */ + strlen(memo_equals) + strlen(rhp->memo); + alloclen += sizeof(memo_equals) - 1 + strlen(rhp->memo); *arrp = (char *)zhalloc(alloclen * sizeof(char)); /* * On input we allow a space after the flags. @@ -435,13 +458,14 @@ get_region_highlight(UNUSED(Param pm)) * into three words, and then check the first to * see if there are flags. However, it's arguable. */ - sprintf(*arrp, "%s%s %s ", + offset = sprintf(*arrp, "%s%s ", (rhp->flags & ZRH_PREDISPLAY) ? "P" : "", - digbuf1, digbuf2); - (void)output_highlight(rhp->atr, *arrp + strlen(*arrp)); + digbuf); + (void)output_highlight(rhp->atr, *arrp + offset); + if (rhp->layer != 10) + strcat(*arrp, layerbuf); if (rhp->memo) { - strcat(*arrp, " "); strcat(*arrp, memo_equals); strcat(*arrp, rhp->memo); } @@ -450,12 +474,10 @@ get_region_highlight(UNUSED(Param pm)) return retarr; } - /* * The parameter system requires the pm argument, but this * may be NULL if called directly. */ - /**/ void set_region_highlight(UNUSED(Param pm), char **aval) @@ -514,7 +536,8 @@ set_region_highlight(UNUSED(Param pm), char **aval) while (inblank(*strp)) strp++; - strp = (char*) match_highlight(strp, &rhp->atr); + rhp->layer = 10; /* default */ + strp = (char*) match_highlight(strp, &rhp->atr, &rhp->layer); while (inblank(*strp)) strp++; @@ -569,22 +592,6 @@ unset_region_highlight(Param pm, int exp) } -/* The last attributes that were on. */ -static zattr lastatr; - -/* - * Clear the last attributes that we set: used when we're going - * to be outputting stuff that shouldn't show up as text. - */ -static void -clearattributes(void) -{ - if (lastatr) { - settextattributes(TXT_ATTR_OFF_FROM_ON(lastatr)); - lastatr = 0; - } -} - /* * Output a termcap capability, clearing any text attributes so * as not to mess up the display. @@ -593,7 +600,7 @@ clearattributes(void) static void tcoutclear(int cap) { - clearattributes(); + cleartextattributes(0); tcout(cap); } @@ -601,47 +608,20 @@ tcoutclear(int cap) * Output the character. This must come from the new video * buffer, nbuf, since we access the multiword buffer nmwbuf * directly. - * - * curatrp may be NULL, otherwise points to an integer specifying - * what attributes were turned on for a character output immediately - * before, in order to optimise output of attribute changes. */ /**/ void -zwcputc(const REFRESH_ELEMENT *c, zattr *curatrp) +zwcputc(const REFRESH_ELEMENT *c) { - /* - * Safety: turn attributes off if last heard of turned on. - * This differs from *curatrp, which is an optimisation for - * writing lots of stuff at once. - */ #ifdef MULTIBYTE_SUPPORT mbstate_t mbstate; int i; VARARR(char, mbtmp, MB_CUR_MAX + 1); #endif - if (lastatr & ~c->atr) { - /* Stuff on we don't want, turn it off */ - settextattributes(TXT_ATTR_OFF_FROM_ON(lastatr & ~c->atr)); - lastatr = 0; - } - - /* - * Don't output "on" attributes in a string of characters with - * the same attributes. Be careful in case a different colour - * needs setting. - */ - if ((c->atr & TXT_ATTR_ON_MASK) && - (!curatrp || - ((*curatrp & TXT_ATTR_ON_VALUES_MASK) != - (c->atr & TXT_ATTR_ON_VALUES_MASK)))) { - /* Record just the control flags we might need to turn off... */ - lastatr = c->atr & TXT_ATTR_ON_MASK; - /* ...but set including the values for colour attributes */ - settextattributes(c->atr & TXT_ATTR_ON_VALUES_MASK); - } + treplaceattrs(c->atr); + applytextattributes(0); #ifdef MULTIBYTE_SUPPORT if (c->atr & TXT_MULTIWORD_MASK) { @@ -662,35 +642,15 @@ zwcputc(const REFRESH_ELEMENT *c, zattr *curatrp) #else fputc(c->chr, shout); #endif - - /* - * Always output "off" attributes since we only turn off at - * the end of a chunk of highlighted text. - */ - if (c->atr & TXT_ATTR_OFF_MASK) { - settextattributes(c->atr & TXT_ATTR_OFF_MASK); - lastatr &= ~((c->atr & TXT_ATTR_OFF_MASK) >> TXT_ATTR_OFF_ON_SHIFT); - } - if (curatrp) { - /* - * Remember the current attributes: those that are turned - * on, less those that are turned off again. Include - * colour attributes here in case the colour changes to - * another non-default one. - */ - *curatrp = (c->atr & TXT_ATTR_ON_VALUES_MASK) & - ~((c->atr & TXT_ATTR_OFF_MASK) >> TXT_ATTR_OFF_ON_SHIFT); - } } static int zwcwrite(const REFRESH_STRING s, size_t i) { size_t j; - zattr curatr = 0; for (j = 0; j < i; j++) - zwcputc(s + j, &curatr); + zwcputc(s + j); return i; /* TODO something better for error indication */ } @@ -937,29 +897,6 @@ snextline(Rparams rpms) rpms->sen = rpms->s + winw; } - -/**/ -static void -settextattributes(zattr atr) -{ - if (txtchangeisset(atr, TXTNOBOLDFACE)) - tsetcap(TCALLATTRSOFF, 0); - if (txtchangeisset(atr, TXTNOSTANDOUT)) - tsetcap(TCSTANDOUTEND, 0); - if (txtchangeisset(atr, TXTNOUNDERLINE)) - tsetcap(TCUNDERLINEEND, 0); - if (txtchangeisset(atr, TXTBOLDFACE)) - tsetcap(TCBOLDFACEBEG, 0); - if (txtchangeisset(atr, TXTSTANDOUT)) - tsetcap(TCSTANDOUTBEG, 0); - if (txtchangeisset(atr, TXTUNDERLINE)) - tsetcap(TCUNDERLINEBEG, 0); - if (txtchangeisset(atr, TXTFGCOLOUR|TXTNOFGCOLOUR)) - set_colour_attribute(atr, COL_SEQ_FG, 0); - if (txtchangeisset(atr, TXTBGCOLOUR|TXTNOBGCOLOUR)) - set_colour_attribute(atr, COL_SEQ_BG, 0); -} - #ifdef MULTIBYTE_SUPPORT /* * Add a multiword glyph at the screen location base. @@ -1041,7 +978,6 @@ zrefresh(void) int tmppos; /* t - tmpline */ int tmpalloced; /* flag to free tmpline when finished */ int remetafy; /* flag that zle line is metafied */ - zattr txtchange; /* attributes set after prompts */ int rprompt_off = 1; /* Offset of rprompt from right of screen */ struct rparams rpms; #ifdef MULTIBYTE_SUPPORT @@ -1190,9 +1126,7 @@ zrefresh(void) #endif /* we probably should only have explicitly set attributes */ tsetcap(TCALLATTRSOFF, 0); - tsetcap(TCSTANDOUTEND, 0); - tsetcap(TCUNDERLINEEND, 0); - txtattrmask = 0; + txtcurrentattrs = txtpendingattrs = txtunknownattrs = 0; if (trashedzle && !clearflag) reexpandprompt(); @@ -1216,9 +1150,8 @@ zrefresh(void) zputs(lpromptbuf, shout); if (lpromptwof == winw) zputs("\n", shout); /* works with both hasam and !hasam */ - } else { - txtchange = pmpt_attr; - settextattributes(txtchange); + /* lpromptbuf includes literal escapes so we need to update for it */ + txtcurrentattrs = txtpendingattrs = pmpt_attr; } if (clearflag) { zputc(&zr_cr); @@ -1261,45 +1194,40 @@ zrefresh(void) rpms.s = nbuf[rpms.ln = 0] + lpromptw; rpms.sen = *nbuf + winw; for (t = tmpline, tmppos = 0; tmppos < tmpll; t++, tmppos++) { - unsigned ireg; - zattr base_atr_on = default_atr_on, base_atr_off = 0; - zattr all_atr_on, all_atr_off; + zattr base_attr = mixattrs(default_attr, prompt_attr); + zattr all_attr; struct region_highlight *rhp; + int layer, nextlayer = 0; /* * Calculate attribute based on region. */ - for (ireg = 0, rhp = region_highlights; - ireg < n_region_highlights; - ireg++, rhp++) { - int offset; - if (rhp->flags & ZRH_PREDISPLAY) - offset = 0; /* include predisplay in start end */ - else - offset = predisplaylen; /* increment over it */ - if (rhp->start + offset <= tmppos && - tmppos < rhp->end + offset) { - if (rhp->atr & (TXTFGCOLOUR|TXTBGCOLOUR)) { - /* override colour with later entry */ - base_atr_on = (base_atr_on & ~TXT_ATTR_ON_VALUES_MASK) | - rhp->atr; - } else { - /* no colour set yet */ - base_atr_on |= rhp->atr; + do { + unsigned ireg; + layer = nextlayer; + nextlayer = special_layer; + for (ireg = 0, rhp = region_highlights; + ireg < n_region_highlights; + ireg++, rhp++) { + if (rhp->layer == layer) { + int offset; + if (rhp->flags & ZRH_PREDISPLAY) + offset = 0; /* include predisplay in start end */ + else + offset = predisplaylen; /* increment over it */ + if (rhp->start + offset <= tmppos && + tmppos < rhp->end + offset) { + base_attr = mixattrs(rhp->atr, base_attr); + if (layer > special_layer) + all_attr = mixattrs(rhp->atr, all_attr); + } + } else if (rhp->layer > layer && rhp->layer < nextlayer) { + nextlayer = rhp->layer; } - if (tmppos == rhp->end + offset - 1 || - tmppos == tmpll - 1) - base_atr_off |= TXT_ATTR_OFF_FROM_ON(rhp->atr); } - } - if (special_atr_on & (TXTFGCOLOUR|TXTBGCOLOUR)) { - /* keep colours from special attributes */ - all_atr_on = special_atr_on | - (base_atr_on & ~TXT_ATTR_COLOUR_ON_MASK); - } else { - /* keep colours from standard attributes */ - all_atr_on = special_atr_on | base_atr_on; - } - all_atr_off = TXT_ATTR_OFF_FROM_ON(all_atr_on); + if (special_layer == layer) { + all_attr = mixattrs(special_attr, base_attr); + } + } while (nextlayer > layer); if (t == scs) /* if cursor is here, remember it */ rpms.nvcs = rpms.s - nbuf[rpms.nvln = rpms.ln]; @@ -1317,10 +1245,9 @@ zrefresh(void) } else { do { rpms.s->chr = ZWC(' '); - rpms.s->atr = base_atr_on; + rpms.s->atr = base_attr; rpms.s++; } while ((++t0) & 7); - rpms.s[-1].atr |= base_atr_off; } } #ifdef MULTIBYTE_SUPPORT @@ -1339,11 +1266,9 @@ zrefresh(void) rpms.s->chr = ZWC(' '); if (!started) started = 1; - rpms.s->atr = all_atr_on; + rpms.s->atr = all_attr; rpms.s++; } while (rpms.s < rpms.sen); - if (started) - rpms.s[-1].atr |= all_atr_off; if (nextline(&rpms, 1)) break; if (t == scs) { @@ -1367,15 +1292,11 @@ zrefresh(void) * occurrence. */ rpms.s->chr = ZWC('?'); - rpms.s->atr = all_atr_on | all_atr_off; + rpms.s->atr = all_attr; rpms.s++; } else { /* We can fit it without reaching the end of the line. */ - /* - * As we don't actually output the WEOF, we attach - * any off attributes to the character itself. - */ - rpms.s->atr = base_atr_on | base_atr_off; + rpms.s->atr = base_attr; if (ichars > 1) { /* * Glyph includes combining characters. @@ -1391,7 +1312,7 @@ zrefresh(void) while (--width > 0) { rpms.s->chr = WEOF; /* Not used, but be consistent... */ - rpms.s->atr = base_atr_on | base_atr_off; + rpms.s->atr = base_attr; rpms.s++; } } @@ -1408,17 +1329,16 @@ zrefresh(void) #endif ) { /* other control character */ rpms.s->chr = ZWC('^'); - rpms.s->atr = all_atr_on; + rpms.s->atr = all_attr; rpms.s++; if (rpms.s == rpms.sen) { /* text wrapped */ - rpms.s[-1].atr |= all_atr_off; if (nextline(&rpms, 1)) break; } rpms.s->chr = (((unsigned int)*t & ~0x80u) > 31) ? ZWC('?') : (*t | ZWC('@')); - rpms.s->atr = all_atr_on | all_atr_off; + rpms.s->atr = all_attr; rpms.s++; } #ifdef MULTIBYTE_SUPPORT @@ -1430,7 +1350,6 @@ zrefresh(void) char dispchars[11]; char *dispptr = dispchars; wchar_t wc; - int started = 0; #ifdef __STDC_ISO_10646__ if (ZSH_INVALID_WCHAR_TEST(*t)) { @@ -1447,31 +1366,23 @@ zrefresh(void) if (mbtowc(&wc, dispptr, 1) == 1 /* paranoia */) { rpms.s->chr = wc; - if (!started) - started = 1; - rpms.s->atr = all_atr_on; + rpms.s->atr = all_attr; rpms.s++; if (rpms.s == rpms.sen) { /* text wrapped */ - if (started) { - rpms.s[-1].atr |= all_atr_off; - started = 0; - } if (nextline(&rpms, 1)) break; } } dispptr++; } - if (started) - rpms.s[-1].atr |= all_atr_off; if (*dispptr) /* nextline said stop processing */ break; } #else else { /* normal character */ rpms.s->chr = *t; - rpms.s->atr = base_atr_on | base_atr_off; + rpms.s->atr = base_attr; rpms.s++; } #endif @@ -1497,13 +1408,12 @@ zrefresh(void) if (statusline) { int outll, outsz; - zattr all_atr_on, all_atr_off; + zattr all_attr; char *statusdup = ztrdup(statusline); ZLE_STRING_T outputline = stringaszleline(statusdup, 0, &outll, &outsz, NULL); - all_atr_on = special_atr_on; - all_atr_off = TXT_ATTR_OFF_FROM_ON(all_atr_on); + all_attr = special_attr; rpms.tosln = rpms.ln + 1; nbuf[rpms.ln][winw + 1] = zr_zr; /* text not wrapped */ @@ -1523,7 +1433,7 @@ zrefresh(void) } if (width > rpms.sen - rpms.s) { rpms.s->chr = ZWC('?'); - rpms.s->atr = all_atr_on | all_atr_off; + rpms.s->atr = all_attr; rpms.s++; } else { rpms.s->chr = *u; @@ -1540,7 +1450,7 @@ zrefresh(void) #endif if (ZC_icntrl(*u)) { /* simplified processing in the status line */ rpms.s->chr = ZWC('^'); - rpms.s->atr = all_atr_on; + rpms.s->atr = all_attr; rpms.s++; if (rpms.s == rpms.sen) { nbuf[rpms.ln][winw + 1] = zr_nl;/* text wrapped */ @@ -1548,7 +1458,7 @@ zrefresh(void) } rpms.s->chr = (((unsigned int)*u & ~0x80u) > 31) ? ZWC('?') : (*u | ZWC('@')); - rpms.s->atr = all_atr_on | all_atr_off; + rpms.s->atr = all_attr; rpms.s++; } else { rpms.s->chr = *u; @@ -1601,6 +1511,7 @@ zrefresh(void) } #endif ZR_memcpy(rpms.sen, zr_end_ellipsis, ZR_END_ELLIPSIS_SIZE); + rpms.sen[1].atr = ellipsis_attr; #ifdef MULTIBYTE_SUPPORT /* Extend to the end if we backed off for a wide character */ if (extra_ellipsis) { @@ -1636,6 +1547,7 @@ zrefresh(void) } #endif ZR_memcpy(rpms.sen, zr_mid_ellipsis1, ZR_MID_ELLIPSIS1_SIZE); + rpms.sen[1].atr = ellipsis_attr; rpms.sen += ZR_MID_ELLIPSIS1_SIZE; #ifdef MULTIBYTE_SUPPORT /* Extend if we backed off for a wide character */ @@ -1645,6 +1557,7 @@ zrefresh(void) } #endif ZR_memcpy(rpms.sen, zr_mid_ellipsis2, ZR_MID_ELLIPSIS2_SIZE); + rpms.sen[1].atr = prompt_attr; nbuf[rpms.tosln][winw] = nbuf[rpms.tosln][winw + 1] = zr_zr; } @@ -1677,7 +1590,9 @@ zrefresh(void) t0 = winw - lpromptw; t0 = t0 > ZR_START_ELLIPSIS_SIZE ? ZR_START_ELLIPSIS_SIZE : t0; ZR_memcpy(nbuf[0] + lpromptw, zr_start_ellipsis, t0); + (*nbuf + lpromptw)->atr = ellipsis_attr; ZR_memset(nbuf[0] + lpromptw + t0, zr_sp, winw - t0 - lpromptw); + (*nbuf + lpromptw + t0)->atr = prompt_attr; nbuf[0][winw] = nbuf[0][winw + 1] = zr_zr; } @@ -1723,9 +1638,9 @@ zrefresh(void) /* output the right-prompt if appropriate */ if (put_rpmpt && !iln && !oput_rpmpt) { - zattr attrchange; - moveto(0, winw - rprompt_off - rpromptw); + treplaceattrs(pmpt_attr); + applytextattributes(0); zputs(rpromptbuf, shout); if (rprompt_off) { vcs = winw - rprompt_off; @@ -1733,39 +1648,7 @@ zrefresh(void) zputc(&zr_cr); vcs = 0; } - /* reset character attributes to that set by the main prompt */ - txtchange = pmpt_attr; - /* - * Keep attributes that have actually changed, - * which are ones off in rpmpt_attr and on in - * pmpt_attr, and vice versa. - */ - attrchange = txtchange & - (TXT_ATTR_OFF_FROM_ON(rpmpt_attr) | - TXT_ATTR_ON_FROM_OFF(rpmpt_attr)); - /* - * Careful in case the colour changed. - */ - if (txtchangeisset(txtchange, TXTFGCOLOUR) && - (!txtchangeisset(rpmpt_attr, TXTFGCOLOUR) || - ((txtchange ^ rpmpt_attr) & TXT_ATTR_FG_COL_MASK))) - { - attrchange |= - txtchange & (TXTFGCOLOUR | TXT_ATTR_FG_COL_MASK); - } - if (txtchangeisset(txtchange, TXTBGCOLOUR) && - (!txtchangeisset(rpmpt_attr, TXTBGCOLOUR) || - ((txtchange ^ rpmpt_attr) & TXT_ATTR_BG_COL_MASK))) - { - attrchange |= - txtchange & (TXTBGCOLOUR | TXT_ATTR_BG_COL_MASK); - } - /* - * Now feed these changes into the usual function, - * if necessary. - */ - if (attrchange) - settextattributes(attrchange); + txtcurrentattrs = txtpendingattrs = rpmpt_attr; } } @@ -1778,11 +1661,6 @@ individually */ refreshline(iln); } -/* reset character attributes */ - if (clearf && postedit) { - if ((txtchange = pmpt_attr ? pmpt_attr : rpmpt_attr)) - settextattributes(txtchange); - } clearf = 0; oput_rpmpt = put_rpmpt; @@ -1982,8 +1860,6 @@ refreshline(int ln) /* 3: main display loop - write out the buffer using whatever tricks we can */ for (;;) { - zattr now_off; - #ifdef MULTIBYTE_SUPPORT if ((!nl->chr || nl->chr != WEOF) && (!ol->chr || ol->chr != WEOF)) { #endif @@ -2085,7 +1961,7 @@ refreshline(int ln) * deletions, so turn off text attributes. */ if (first) { - clearattributes(); + cleartextattributes(0); first = 0; } tc_delchars(i); @@ -2174,13 +2050,8 @@ refreshline(int ln) break; do { #endif - /* - * If an attribute was on here but isn't any more, - * output the sequence to turn it off. - */ - now_off = ol->atr & ~nl->atr & TXT_ATTR_ON_MASK; - if (now_off) - settextattributes(TXT_ATTR_OFF_FROM_ON(now_off)); + treplaceattrs(nl->atr); + applytextattributes(0); /* * This is deliberately called if nl->chr is WEOF @@ -2558,8 +2429,8 @@ singlerefresh(ZLE_STRING_T tmpline, int tmpll, int tmpcs) for (t0 = 0; t0 < tmpll; t0++) { unsigned ireg; - zattr base_atr_on = 0, base_atr_off = 0; - zattr all_atr_on, all_atr_off; + zattr base_attr = 0; + zattr all_attr; struct region_highlight *rhp; /* * Calculate attribute based on region. @@ -2574,38 +2445,28 @@ singlerefresh(ZLE_STRING_T tmpline, int tmpll, int tmpcs) offset = predisplaylen; /* increment over it */ if (rhp->start + offset <= t0 && t0 < rhp->end + offset) { - if (base_atr_on & (TXTFGCOLOUR|TXTBGCOLOUR)) { + if (base_attr & (TXTFGCOLOUR|TXTBGCOLOUR)) { /* keep colour already set */ - base_atr_on |= rhp->atr & ~TXT_ATTR_COLOUR_ON_MASK; + base_attr |= rhp->atr & ~TXT_ATTR_COLOUR_MASK; } else { /* no colour set yet */ - base_atr_on |= rhp->atr; + base_attr |= rhp->atr; } - if (t0 == rhp->end + offset - 1 || - t0 == tmpll - 1) - base_atr_off |= TXT_ATTR_OFF_FROM_ON(rhp->atr); } } - if (special_atr_on & (TXTFGCOLOUR|TXTBGCOLOUR)) { - /* keep colours from special attributes */ - all_atr_on = special_atr_on | - (base_atr_on & ~TXT_ATTR_COLOUR_ON_MASK); - } else { - /* keep colours from standard attributes */ - all_atr_on = special_atr_on | base_atr_on; - } - all_atr_off = TXT_ATTR_OFF_FROM_ON(all_atr_on); + all_attr = mixattrs(special_attr, base_attr); + if (t0 == tmpcs) + nvcs = vp - vbuf; if (tmpline[t0] == ZWC('\t')) { for (*vp++ = zr_sp; (vp - vbuf) & 7; ) *vp++ = zr_sp; - vp[-1].atr |= base_atr_off; } else if (tmpline[t0] == ZWC('\n')) { vp->chr = ZWC('\\'); - vp->atr = all_atr_on; + vp->atr = all_attr; vp++; vp->chr = ZWC('n'); - vp->atr = all_atr_on | all_atr_off; + vp->atr = all_attr; vp++; #ifdef MULTIBYTE_SUPPORT } else if (WC_ISPRINT(tmpline[t0]) && @@ -2621,7 +2482,7 @@ singlerefresh(ZLE_STRING_T tmpline, int tmpll, int tmpcs) } } else ichars = 1; - vp->atr = base_atr_on | base_atr_off; + vp->atr = base_attr; if (ichars > 1) addmultiword(vp, tmpline+t0, ichars); else @@ -2629,7 +2490,7 @@ singlerefresh(ZLE_STRING_T tmpline, int tmpll, int tmpcs) vp++; while (--width > 0) { vp->chr = WEOF; - vp->atr = base_atr_on | base_atr_off; + vp->atr = base_attr; vp++; } t0 += ichars - 1; @@ -2639,14 +2500,14 @@ singlerefresh(ZLE_STRING_T tmpline, int tmpll, int tmpcs) && (unsigned)tmpline[t0] <= 0xffU #endif ) { - ZLE_INT_T t = tmpline[++t0]; + ZLE_INT_T t = tmpline[t0]; vp->chr = ZWC('^'); - vp->atr = all_atr_on; + vp->atr = all_attr; vp++; vp->chr = (((unsigned int)t & ~0x80u) > 31) ? ZWC('?') : (t | ZWC('@')); - vp->atr = all_atr_on | all_atr_off; + vp->atr = all_attr; vp++; } #ifdef MULTIBYTE_SUPPORT @@ -2654,7 +2515,6 @@ singlerefresh(ZLE_STRING_T tmpline, int tmpll, int tmpcs) char dispchars[11]; char *dispptr = dispchars; wchar_t wc; - int started = 0; if ((unsigned)tmpline[t0] > 0xffffU) { sprintf(dispchars, "<%.08x>", (unsigned)tmpline[t0]); @@ -2664,25 +2524,19 @@ singlerefresh(ZLE_STRING_T tmpline, int tmpll, int tmpcs) while (*dispptr) { if (mbtowc(&wc, dispptr, 1) == 1 /* paranoia */) { vp->chr = wc; - if (!started) - started = 1; - vp->atr = all_atr_on; + vp->atr = all_attr; vp++; } dispptr++; } - if (started) - vp[-1].atr |= all_atr_off; } #else else { vp->chr = tmpline[t0]; - vp->atr = base_atr_on | base_atr_off; + vp->atr = base_attr; vp++; } #endif - if (t0 == tmpcs) - nvcs = vp - vbuf - 1; } if (t0 == tmpcs) nvcs = vp - vbuf; @@ -2697,11 +2551,11 @@ singlerefresh(ZLE_STRING_T tmpline, int tmpll, int tmpcs) } if (winpos) { vbuf[winpos].chr = ZWC('<'); /* line continues to the left */ - vbuf[winpos].atr = 0; + vbuf[winpos].atr = ellipsis_attr; } if ((int)ZR_strlen(vbuf + winpos) > (winw - hasam)) { vbuf[winpos + winw - hasam - 1].chr = ZWC('>'); /* line continues to right */ - vbuf[winpos + winw - hasam - 1].atr = 0; + vbuf[winpos + winw - hasam - 1].atr = ellipsis_attr; vbuf[winpos + winw - hasam] = zr_zr; } ZR_strcpy(nbuf[0], vbuf + winpos); diff --git a/Src/Zle/zle_thingy.c b/Src/Zle/zle_thingy.c index cd3f2c356..f71435b01 100644 --- a/Src/Zle/zle_thingy.c +++ b/Src/Zle/zle_thingy.c @@ -344,7 +344,7 @@ bin_zle(char *name, char **args, Options ops, UNUSED(int func)) { static struct opn { char o; - int (*func) _((char *, char **, Options, char)); + int (*func) (char *, char **, Options, char); int min, max; } const opns[] = { { 'l', bin_zle_list, 0, -1 }, @@ -366,10 +366,10 @@ bin_zle(char *name, char **args, Options ops, UNUSED(int func)) int n; /* select operation and ensure no clashing arguments */ - for(op = opns; op->o && !OPT_ISSET(ops,STOUC(op->o)); op++) ; + for(op = opns; op->o && !OPT_ISSET(ops, (unsigned char) op->o); op++) ; if(op->o) for(opp = op; (++opp)->o; ) - if(OPT_ISSET(ops,STOUC(opp->o))) { + if(OPT_ISSET(ops, (unsigned char) opp->o)) { zwarnnam(name, "incompatible operation selection options"); return 1; } diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c index fdd168763..aa3c71bc2 100644 --- a/Src/Zle/zle_tricky.c +++ b/Src/Zle/zle_tricky.c @@ -576,7 +576,7 @@ parambeg(char *s) while (idigit(*e)) e++; else - e = itype_end(e, IIDENT, 0); + e = itype_end(e, INAMESPC, 0); /* Now make sure that the cursor is inside the name. */ if (offs <= e - s && offs >= b - s && n <= 0) { @@ -765,7 +765,7 @@ docomplete(int lst) else if (idigit(*q)) do q++; while (idigit(*q)); else - q = itype_end(q, IIDENT, 0); + q = itype_end(q, INAMESPC, 0); sav = *q; *q = '\0'; if (zlemetacs - wb == q - s && @@ -1315,6 +1315,8 @@ get_comp_string(void) ins = (tok == REPEAT ? 2 : (tok != STRING && tok != TYPESET)); zsfree(cmdstr); cmdstr = ztrdup(tokstr); + untokenize(cmdstr); + remnulargs(cmdstr); cmdtok = tok; /* * If everything before is a redirection, or anything @@ -1497,7 +1499,8 @@ get_comp_string(void) if (varq) tt = clwords[clwpos]; - s = itype_end(tt, IIDENT, 0); + /* The only place we complete namespaces, see IIDENT below */ + s = itype_end(tt, INAMESPC, 0); sav = *s; *s = '\0'; zsfree(varname); @@ -1568,6 +1571,8 @@ get_comp_string(void) i = 0; MB_METACHARINIT(); + /* All further uses of IIDENT in this file should change to * + * INAMESPC if this case is changed. Too ugly to risk now. */ if (itype_end(s, IIDENT, 1) == s) nnb = s + MB_METACHARLEN(s); else @@ -1641,7 +1646,7 @@ get_comp_string(void) } else { /* In mathematical expression, we complete parameter names * * (even if they don't have a `$' in front of them). So we * - * have to find that name. */ + * have to find that name. See above regarding INAMESPC */ char *cspos = zlemetaline + zlemetacs, *wptr, *cptr; we = itype_end(cspos, IIDENT, 0) - zlemetaline; @@ -2426,7 +2431,7 @@ mod_export int printfmt(char *fmt, int n, int dopr, int doesc) { char *p = fmt, nc[DIGBUFSIZE]; - int l = 0, cc = 0, b = 0, s = 0, u = 0, m; + int l = 0, cc = 0; MB_METACHARINIT(); for (; *p; ) { @@ -2437,48 +2442,45 @@ printfmt(char *fmt, int n, int dopr, int doesc) if (idigit(*++p)) arg = zstrtol(p, &p, 10); if (*p) { - m = 0; switch (*p) { case '%': - if (dopr) + if (dopr) { + applytextattributes(0); putc('%', shout); + } cc++; break; case 'n': sprintf(nc, "%d", n); - if (dopr) + if (dopr) { + applytextattributes(0); fputs(nc, shout); + } cc += MB_METASTRWIDTH(nc); break; case 'B': - b = 1; if (dopr) - tcout(TCBOLDFACEBEG); + tsetattrs(TXTBOLDFACE); break; case 'b': - b = 0; m = 1; if (dopr) - tcout(TCALLATTRSOFF); + tunsetattrs(TXTBOLDFACE); break; case 'S': - s = 1; if (dopr) - tcout(TCSTANDOUTBEG); + tsetattrs(TXTSTANDOUT); break; case 's': - s = 0; m = 1; if (dopr) - tcout(TCSTANDOUTEND); + tunsetattrs(TXTSTANDOUT); break; case 'U': - u = 1; if (dopr) - tcout(TCUNDERLINEBEG); + tsetattrs(TXTUNDERLINE); break; case 'u': - u = 0; m = 1; if (dopr) - tcout(TCUNDERLINEEND); + tunsetattrs(TXTUNDERLINE); break; case 'F': case 'K': @@ -2491,18 +2493,27 @@ printfmt(char *fmt, int n, int dopr, int doesc) } else atr = match_colour(NULL, is_fg, arg); if (atr != TXT_ERROR) - set_colour_attribute(atr, is_fg ? COL_SEQ_FG : - COL_SEQ_BG, 0); + tsetattrs(atr); break; case 'f': - set_colour_attribute(TXTNOFGCOLOUR, COL_SEQ_FG, 0); + tunsetattrs(TXTFGCOLOUR); break; case 'k': - set_colour_attribute(TXTNOBGCOLOUR, COL_SEQ_BG, 0); + tunsetattrs(TXTBGCOLOUR); + break; + case 'H': + if (p[1] == '{') { + p = parsehighlight(p + 2, '}', &atr); + --p; + if (atr != TXT_ERROR) + treplaceattrs(atr); + } break; case '{': if (arg) cc += arg; + if (dopr) + applytextattributes(0); for (p++; *p && (*p != '%' || p[1] != '}'); p++) { if (*p == Meta) { p++; @@ -2518,14 +2529,6 @@ printfmt(char *fmt, int n, int dopr, int doesc) p--; break; } - if (dopr && m) { - if (b) - tcout(TCBOLDFACEBEG); - if (s) - tcout(TCSTANDOUTBEG); - if (u) - tcout(TCUNDERLINEBEG); - } } else break; p++; @@ -2533,6 +2536,7 @@ printfmt(char *fmt, int n, int dopr, int doesc) if (*p == '\n') { cc++; if (dopr) { + applytextattributes(0); if (tccan(TCCLEAREOL)) tcout(TCCLEAREOL); else { @@ -2551,6 +2555,7 @@ printfmt(char *fmt, int n, int dopr, int doesc) convchar_t cchar; int clen = MB_METACHARLENCONV(p, &cchar); if (dopr) { + applytextattributes(0); while (clen--) { if (*p == Meta) { p++; @@ -2568,6 +2573,8 @@ printfmt(char *fmt, int n, int dopr, int doesc) } } if (dopr) { + treplaceattrs(0); + applytextattributes(0); if (!(cc % zterm_columns)) fputs(" \010", shout); if (tccan(TCCLEAREOL)) diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c index c85f8450d..e2b86e863 100644 --- a/Src/Zle/zle_utils.c +++ b/Src/Zle/zle_utils.c @@ -512,12 +512,13 @@ stringaszleline(char *instr, int incs, int *outll, int *outsz, int *outcs) *outcs = outptr - outstr; *outll = outptr - outstr; } else { + *outstr = ZWC('\0'); *outll = 0; if (outcs) *outcs = 0; } #else - memcpy(outstr, instr, ll); + strcpy(outstr, instr); *outll = ll; if (outcs) *outcs = incs; @@ -580,7 +581,7 @@ struct zle_region; struct zle_region { struct zle_region *next; /* Entries of region_highlight, as needed */ - int atr; + zattr atr; int start; int end; int flags; @@ -799,7 +800,7 @@ spaceinline(int ct) if (rhp->start_meta - sub >= zlemetacs) { rhp->start_meta += ct; } - if (rhp->end_meta - sub >= zlemetacs) { + if (rhp->end_meta - sub >= zlemetacs && (!predisplaylen || zlemetacs)) { rhp->end_meta += ct; } } @@ -827,7 +828,7 @@ spaceinline(int ct) if (rhp->start - sub >= zlecs) { rhp->start += ct; } - if (rhp->end - sub >= zlecs) { + if (rhp->end - sub >= zlecs && (!predisplaylen || zlecs)) { rhp->end += ct; } } @@ -866,13 +867,13 @@ shiftchars(int to, int cnt) if (rhp->start_meta - sub > to + cnt) rhp->start_meta -= cnt; else - rhp->start_meta = to; + rhp->start_meta = to + sub; } if (rhp->end_meta - sub > to) { if (rhp->end_meta - sub > to + cnt) rhp->end_meta -= cnt; else - rhp->end_meta = to; + rhp->end_meta = to + sub; } } } @@ -896,13 +897,13 @@ shiftchars(int to, int cnt) if (rhp->start - sub > to + cnt) rhp->start -= cnt; else - rhp->start = to; + rhp->start = to + sub; } if (rhp->end - sub > to) { if (rhp->end - sub > to + cnt) rhp->end -= cnt; else - rhp->end = to; + rhp->end = to + sub; } } } @@ -936,6 +937,28 @@ cut(int i, int ct, int flags) cuttext(zleline + i, ct, flags); } +static char* +base64_encode(const char *src, size_t len) { + static const char* base64_table = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + const unsigned char *end = (unsigned char *)src + len; + const unsigned char *in = (unsigned char *)src; + char *ret = zhalloc(1 + 4 * ((len + 2) / 3)); /* 4 bytes out for 3 in */ + char *cur = ret; + + for (; end - in > 0; in += 3, cur += 4) { + unsigned int n = *in << 16; + cur[3] = end - in > 2 ? base64_table[(n |= in[2]) & 0x3f] : '='; + cur[2] = end - in > 1 ? base64_table[((n |= in[1]<<8) >> 6) & 0x3f] : '='; + cur[1] = base64_table[(n >> 12) & 0x3f]; + cur[0] = base64_table[n >> 18]; + } + *cur = '\0'; + + return ret; +} + /* * As cut, but explicitly supply the text together with its length. */ @@ -948,7 +971,15 @@ cuttext(ZLE_STRING_T line, int ct, int flags) return; UNMETACHECK(); - if (zmod.flags & MOD_VIBUF) { + if (zmod.flags & MOD_OSSEL) { + int cutll; + char *mbcut = zlelineasstring(line, ct, 0, &cutll, NULL, 1); + unmetafy(mbcut, &cutll); + mbcut = base64_encode(mbcut, cutll); + + fprintf(shout, "\033]52;%c;%s\a", zmod.flags & MOD_CLIP ? 'c' : 'p', + mbcut); + } else if (zmod.flags & MOD_VIBUF) { struct cutbuffer *b = &vibuf[zmod.vibuf]; if (!(zmod.flags & MOD_VIAPP) || !b->buf) { @@ -1220,7 +1251,7 @@ getzlequery(void) REFRESH_ELEMENT re; re.chr = c; re.atr = 0; - zwcputc(&re, NULL); + zwcputc(&re); } return c == ZWC('y'); } @@ -1235,7 +1266,7 @@ bindztrdup(char *str) char *buf, *ptr, *ret; for(ptr = str; *ptr; ptr++) { - c = *ptr == Meta ? STOUC(*++ptr) ^ 32 : STOUC(*ptr); + c = *ptr == Meta ? (unsigned char) *++ptr ^ 32 : (unsigned char) *ptr; if(c & 0x80) { len += 3; c &= 0x7f; @@ -1249,7 +1280,7 @@ bindztrdup(char *str) } ptr = buf = zalloc(len); for(; *str; str++) { - c = *str == Meta ? STOUC(*++str) ^ 32 : STOUC(*str); + c = *str == Meta ? (unsigned char) *++str ^ 32 : (unsigned char) *str; if(c & 0x80) { *ptr++ = '\\'; *ptr++ = 'M'; @@ -1530,7 +1561,7 @@ mkundoent(void) struct change *ch; UNMETACHECK(); - if(lastll == zlell && !ZS_memcmp(lastline, zleline, zlell)) { + if(lastll == zlell && lastlinesz >= zlell && !ZS_memcmp(lastline, zleline, zlell)) { lastcs = zlecs; return; } diff --git a/Src/Zle/zle_vi.c b/Src/Zle/zle_vi.c index 0f198d0e8..6692df830 100644 --- a/Src/Zle/zle_vi.c +++ b/Src/Zle/zle_vi.c @@ -1014,6 +1014,9 @@ int visetbuffer(char **args) { ZLE_INT_T ch; + const ZLE_CHAR_T *match = ZWS("_*+"); + int registermod[] = { MOD_NULL, MOD_PRI, MOD_CLIP }; + ZLE_CHAR_T *found; if (*args) { ch = **args; @@ -1022,12 +1025,12 @@ visetbuffer(char **args) } else { ch = getfullchar(0); } - if (ch == ZWC('_')) { - zmod.flags |= MOD_NULL; + if ((found = ZS_strchr(match, ch))) { + zmod.flags |= registermod[found - match]; prefixflag = 1; return 0; } else - zmod.flags &= ~MOD_NULL; + zmod.flags &= ~(MOD_NULL | MOD_OSSEL); if ((ch < ZWC('0') || ch > ZWC('9')) && (ch < ZWC('a') || ch > ZWC('z')) && (ch < ZWC('A') || ch > ZWC('Z'))) |