From 91a10708b25b78d36549de0177e2330670fe163d Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Sat, 26 Apr 2008 22:52:50 +0000 Subject: 24822: highlighting of isearch matches unposted: not in NEWS that COMBINING_CHARS is not on by default --- Src/Zle/zle_hist.c | 77 ++++++++++++++++++++++++++++++++++++++------------- Src/Zle/zle_refresh.c | 55 ++++++++++++++++++++++++++++-------- 2 files changed, 100 insertions(+), 32 deletions(-) (limited to 'Src/Zle') diff --git a/Src/Zle/zle_hist.c b/Src/Zle/zle_hist.c index 9f0288d0b..203492b55 100644 --- a/Src/Zle/zle_hist.c +++ b/Src/Zle/zle_hist.c @@ -907,6 +907,7 @@ static struct isrch_spot { int pat_hl; /* histline where pattern search started */ unsigned short pos; /* The search position in our metafied str */ unsigned short pat_pos; /* pos where pattern search started */ + unsigned short end_pos; /* The position of the end of the matched str */ unsigned short cs; /* The visible search position to the user */ unsigned short len; /* The search string's length */ unsigned short flags; /* This spot's flags */ @@ -928,7 +929,7 @@ free_isrch_spots(void) /**/ static void set_isrch_spot(int num, int hl, int pos, int pat_hl, int pat_pos, - int cs, int len, int dir, int nomatch) + int end_pos, int cs, int len, int dir, int nomatch) { if (num >= max_spot) { if (!isrch_spots) { @@ -944,6 +945,7 @@ set_isrch_spot(int num, int hl, int pos, int pat_hl, int pat_pos, isrch_spots[num].pos = (unsigned short)pos; isrch_spots[num].pat_hl = pat_hl; isrch_spots[num].pat_pos = (unsigned short)pat_pos; + isrch_spots[num].end_pos = (unsigned short)end_pos; isrch_spots[num].cs = (unsigned short)cs; isrch_spots[num].len = (unsigned short)len; isrch_spots[num].flags = (dir > 0? ISS_FORWARD : 0) @@ -953,12 +955,13 @@ set_isrch_spot(int num, int hl, int pos, int pat_hl, int pat_pos, /**/ static void get_isrch_spot(int num, int *hlp, int *posp, int *pat_hlp, int *pat_posp, - int *csp, int *lenp, int *dirp, int *nomatch) + int *end_posp, int *csp, int *lenp, int *dirp, int *nomatch) { *hlp = isrch_spots[num].hl; *posp = (int)isrch_spots[num].pos; *pat_hlp = isrch_spots[num].pat_hl; *pat_posp = (int)isrch_spots[num].pat_pos; + *end_posp = (int)isrch_spots[num].end_pos; *csp = (int)isrch_spots[num].cs; *lenp = (int)isrch_spots[num].len; *dirp = (isrch_spots[num].flags & ISS_FORWARD)? 1 : -1; @@ -1010,6 +1013,9 @@ isearch_newpos(LinkList matchlist, int curpos, int dir, #define NORM_PROMPT_POS (BAD_TEXT_LEN+1) #define FIRST_SEARCH_CHAR (NORM_PROMPT_POS + 14) +/**/ +int isearch_active, isearch_startpos, isearch_endpos; + /**/ static void doisearch(char **args, int dir, int pattern) @@ -1087,6 +1093,12 @@ doisearch(char **args, int dir, int pattern) * case it's OK. */ int dup_ok = 0; + /* + * End position of the match. + * When forward matching, this is the position for the cursor. + * When backward matching, the cursor position is pos. + */ + int end_pos = 0; /* * savekeys records the unget buffer, so that if we have arguments * they don't pollute the input. @@ -1138,7 +1150,7 @@ doisearch(char **args, int dir, int pattern) pat_pos = pos = zlemetacs; for (;;) { /* Remember the current values in case search fails (doesn't push). */ - set_isrch_spot(top_spot, hl, pos, pat_hl, pat_pos, + set_isrch_spot(top_spot, hl, pos, pat_hl, pat_pos, end_pos, zlemetacs, sbptr, dir, nomatch); if (sbptr == 1 && sbuf[0] == '^') { zlemetacs = 0; @@ -1147,11 +1159,6 @@ doisearch(char **args, int dir, int pattern) } else if (sbptr > 0) { /* The matched text, used as flag that we matched */ char *t = NULL; - /* - * When forward matching, position for the cursor. - * When backward matching, the position is pos. - */ - int forwardmatchpos = 0; last_line = zt; sbuf[sbptr] = '\0'; @@ -1233,7 +1240,7 @@ doisearch(char **args, int dir, int pattern) */ if (!skip_pos && pattryrefs(patprog, zt, -1, -1, 0, NULL, NULL, - &forwardmatchpos)) + &end_pos)) t = zt; } else { if (!matchlist && !skip_pos) { @@ -1268,7 +1275,7 @@ doisearch(char **args, int dir, int pattern) newpos = pos + 1; } newpos = isearch_newpos(matchlist, newpos, - dir, &forwardmatchpos); + dir, &end_pos); /* need a new list next time if off the end */ if (newpos < 0) { freematchlist(matchlist); @@ -1316,7 +1323,7 @@ doisearch(char **args, int dir, int pattern) } else t = zlinefind(zt, pos, sbuf, dir, sens); if (t) - forwardmatchpos = pos + sbptr - (sbuf[0] == '^'); + end_pos = pos + sbptr - (sbuf[0] == '^'); } } if (t) { @@ -1333,7 +1340,8 @@ doisearch(char **args, int dir, int pattern) && (isrch_spots[top_spot-1].flags >> ISS_NOMATCH_SHIFT)) top_spot--; get_isrch_spot(top_spot, &hl, &pos, &pat_hl, &pat_pos, - &zlemetacs, &sbptr, &dir, &nomatch); + &end_pos, &zlemetacs, &sbptr, &dir, + &nomatch); if (!nomatch) { feep = 1; nomatch = 1; @@ -1366,7 +1374,7 @@ doisearch(char **args, int dir, int pattern) if (t || (nosearch && !nomatch)) { zle_setline(he); if (dir == 1) - zlemetacs = forwardmatchpos; + zlemetacs = end_pos; else zlemetacs = pos; statusline = ibuf + NORM_PROMPT_POS; @@ -1384,11 +1392,39 @@ doisearch(char **args, int dir, int pattern) } sbuf[sbptr] = '_'; sbuf[sbptr+1] = '\0'; + if (!nomatch && sbptr && (sbptr > 1 || sbuf[0] != '^')) { +#ifdef MULTIBYTE_SUPPORT + int charpos = 0, charcount = 0, ret; + wint_t wc; + mbstate_t mbs; + + /* + * Count unmetafied character positions for the + * start and end of the match for the benefit of + * highlighting. + */ + memset(&mbs, 0, sizeof(mbs)); + while (charpos < end_pos) { + ret = mb_metacharlenconv_r(zlemetaline + charpos, &wc, &mbs); + if (charpos <= pos && pos < charpos + ret) + isearch_startpos = charcount; + charcount++; + charpos += ret; + } + isearch_endpos = charcount; +#else + isearch_startpos = ztrsub(zlemetaline + pos, zlemetaline); + isearch_endpos = ztrsub(zlemetaline + end_pos, + zlemetaline); +#endif + isearch_active = 1; + } else + isearch_active = 0; ref: zrefresh(); if (!(cmd = getkeycmd()) || cmd == Th(z_sendbreak)) { int i; - get_isrch_spot(0, &hl, &pos, &pat_hl, &pat_pos, + get_isrch_spot(0, &hl, &pos, &pat_hl, &pat_pos, &end_pos, &i, &sbptr, &dir, &nomatch); he = quietgethist(hl); zle_setline(he); @@ -1410,7 +1446,7 @@ doisearch(char **args, int dir, int pattern) cmd == Th(z_backwarddeletechar)) { if (top_spot) { get_isrch_spot(--top_spot, &hl, &pos, &pat_hl, &pat_pos, - &zlemetacs, &sbptr, &dir, &nomatch); + &end_pos, &zlemetacs, &sbptr, &dir, &nomatch); patprog = NULL; nosearch = 1; } else @@ -1452,7 +1488,7 @@ doisearch(char **args, int dir, int pattern) cmd == Th(z_historyincrementalpatternsearchbackward)) { pat_hl = hl; pat_pos = pos; - set_isrch_spot(top_spot++, hl, pos, pat_hl, pat_pos, + set_isrch_spot(top_spot++, hl, pos, pat_hl, pat_pos, end_pos, zlemetacs, sbptr, dir, nomatch); if (dir != -1) dir = -1; @@ -1463,7 +1499,7 @@ doisearch(char **args, int dir, int pattern) cmd == Th(z_historyincrementalpatternsearchforward)) { pat_hl = hl; pat_pos = pos; - set_isrch_spot(top_spot++, hl, pos, pat_hl, pat_pos, + set_isrch_spot(top_spot++, hl, pos, pat_hl, pat_pos, end_pos, zlemetacs, sbptr, dir, nomatch); if (dir != 1) dir = 1; @@ -1473,7 +1509,7 @@ doisearch(char **args, int dir, int pattern) } else if(cmd == Th(z_virevrepeatsearch)) { pat_hl = hl; pat_pos = pos; - set_isrch_spot(top_spot++, hl, pos, pat_hl, pat_pos, + set_isrch_spot(top_spot++, hl, pos, pat_hl, pat_pos, end_pos, zlemetacs, sbptr, dir, nomatch); dir = -odir; skip_pos = 1; @@ -1481,7 +1517,7 @@ doisearch(char **args, int dir, int pattern) } else if(cmd == Th(z_virepeatsearch)) { pat_hl = hl; pat_pos = pos; - set_isrch_spot(top_spot++, hl, pos, pat_hl, pat_pos, + set_isrch_spot(top_spot++, hl, pos, pat_hl, pat_pos, end_pos, zlemetacs, sbptr, dir, nomatch); dir = odir; skip_pos = 1; @@ -1534,7 +1570,7 @@ doisearch(char **args, int dir, int pattern) feep = 1; continue; } - set_isrch_spot(top_spot++, hl, pos, pat_hl, pat_pos, + set_isrch_spot(top_spot++, hl, pos, pat_hl, pat_pos, end_pos, zlemetacs, sbptr, dir, nomatch); if (sbptr >= sibuf - FIRST_SEARCH_CHAR - 2 #ifdef MULTIBYTE_SUPPORT @@ -1569,6 +1605,7 @@ doisearch(char **args, int dir, int pattern) zsfree(okeymap); if (matchlist) freematchlist(matchlist); + isearch_active = 0; /* * Don't allow unused characters provided as a string to the * widget to overflow and be used as separated commands. diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c index 66cae9f97..cc0dbe4c0 100644 --- a/Src/Zle/zle_refresh.c +++ b/Src/Zle/zle_refresh.c @@ -241,9 +241,16 @@ struct region_highlight { * via the parameter region_highlight. */ struct region_highlight *region_highlights; +/* + * Count of special uses of region highlighting, which account + * for the first few elements of region_highlights. + * 0: region between point and mark + * 1: isearch region + */ +#define N_SPECIAL_HIGHLIGHTS (2) /* * Number of elements in region_highlights. - * This includes the region between point and mark, element 0. + * This includes the special elements above. */ int n_region_highlights; @@ -380,12 +387,14 @@ 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; + struct region_highlight *rhp; special_atr_on = 0; if (!region_highlights) { region_highlights = (struct region_highlight *) - zshcalloc(sizeof(struct region_highlight)); - n_region_highlights = 1; + zshcalloc(N_SPECIAL_HIGHLIGHTS*sizeof(struct region_highlight)); + n_region_highlights = N_SPECIAL_HIGHLIGHTS; } else { region_highlights->atr = 0; } @@ -394,14 +403,23 @@ void zle_set_highlight(void) for (; *atrs; atrs++) { if (!strcmp(*atrs, "none")) { /* reset attributes for consistency... usually unnecessary */ - special_atr_on = region_highlights->atr = 0; - special_atr_on_set = region_atr_on_set = 1; + special_atr_on = 0; + special_atr_on_set = region_atr_on_set = + isearch_atr_on_set = 1; + for (rhp = region_highlights; + rhp < region_highlights + N_SPECIAL_HIGHLIGHTS; + rhp++) { + rhp->atr = 0; + } } else if (strpfx("special:", *atrs)) { match_highlight(*atrs + 8, &special_atr_on); special_atr_on_set = 1; } else if (strpfx("region:", *atrs)) { match_highlight(*atrs + 7, ®ion_highlights->atr); region_atr_on_set = 1; + } else if (strpfx("isearch:", *atrs)) { + match_highlight(*atrs + 8, &(region_highlights[1].atr)); + isearch_atr_on_set = 1; } } } @@ -411,6 +429,8 @@ void zle_set_highlight(void) special_atr_on = TXTSTANDOUT; if (!region_atr_on_set) region_highlights->atr = TXTSTANDOUT; + if (!isearch_atr_on_set) + region_highlights[1].atr = TXTUNDERLINE; special_atr_off = special_atr_on << TXT_ATTR_OFF_ON_SHIFT; } @@ -432,15 +452,17 @@ get_region_highlight(UNUSED(Param pm)) /* region_highlights may not have been set yet */ if (!arrsize) - arrsize = 1; + arrsize = N_SPECIAL_HIGHLIGHTS; arrp = retarr = (char **)zhalloc(arrsize*sizeof(char *)); /* ignore NULL termination */ arrsize--; if (arrsize) { struct region_highlight *rhp; - /* ignore point/mark at start */ - for (rhp = region_highlights+1; arrsize--; rhp++, arrp++) { + /* ignore special highlighting */ + for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS; + arrsize--; + rhp++, arrp++) { char digbuf1[DIGBUFSIZE], digbuf2[DIGBUFSIZE]; int atrlen = 0, alloclen, done1; const struct highlight *hp; @@ -503,9 +525,9 @@ set_region_highlight(UNUSED(Param pm), char **aval) struct region_highlight *rhp; len = aval ? arrlen(aval) : 0; - if (n_region_highlights != len + 1) { - /* no null termination, but include point/mark region at start */ - n_region_highlights = len + 1; + if (n_region_highlights != len + N_SPECIAL_HIGHLIGHTS) { + /* no null termination, but include special highlighting at start */ + n_region_highlights = len + N_SPECIAL_HIGHLIGHTS; region_highlights = (struct region_highlight *) zrealloc(region_highlights, sizeof(struct region_highlight) * n_region_highlights); @@ -514,7 +536,9 @@ set_region_highlight(UNUSED(Param pm), char **aval) if (!aval) return; - for (rhp = region_highlights + 1; *aval; rhp++, aval++) { + for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS; + *aval; + rhp++, aval++) { char *strp, *oldstrp; oldstrp = *aval; @@ -1050,6 +1074,13 @@ zrefresh(void) } else { region_highlights->start = region_highlights->end = -1; } + /* check for isearch string to highlight */ + if (isearch_active) { + region_highlights[1].start = isearch_startpos; + region_highlights[1].end = isearch_endpos; + } else { + region_highlights[1].start = region_highlights[1].end = -1; + } if (clearlist && listshown > 0) { if (tccan(TCCLEAREOD)) { -- cgit 1.4.1