From e74702b467171dbdafb56dfe354794a212e020d9 Mon Sep 17 00:00:00 2001 From: Tanaka Akira Date: Thu, 15 Apr 1999 18:05:38 +0000 Subject: Initial revision --- Src/Zle/zle_hist.c | 1139 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1139 insertions(+) create mode 100644 Src/Zle/zle_hist.c (limited to 'Src/Zle/zle_hist.c') diff --git a/Src/Zle/zle_hist.c b/Src/Zle/zle_hist.c new file mode 100644 index 000000000..76e421c1c --- /dev/null +++ b/Src/Zle/zle_hist.c @@ -0,0 +1,1139 @@ +/* + * zle_hist.c - history editing + * + * This file is part of zsh, the Z shell. + * + * Copyright (c) 1992-1997 Paul Falstad + * All rights reserved. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and to distribute modified versions of this software for any + * purpose, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * In no event shall Paul Falstad or the Zsh Development Group be liable + * to any party for direct, indirect, special, incidental, or consequential + * damages arising out of the use of this software and its documentation, + * even if Paul Falstad and the Zsh Development Group have been advised of + * the possibility of such damage. + * + * Paul Falstad and the Zsh Development Group specifically disclaim any + * warranties, including, but not limited to, the implied warranties of + * merchantability and fitness for a particular purpose. The software + * provided hereunder is on an "as is" basis, and Paul Falstad and the + * Zsh Development Group have no obligation to provide maintenance, + * support, updates, enhancements, or modifications. + * + */ + +#include "zle.mdh" +#include "zle_hist.pro" + +/* Are references to earlier history lines permitted? == 0 if * + * editing or reading a standalone line, such as in vared or select. */ + +/**/ +int histallowed; + +/* Column position of vi ideal cursor. -1 if it is unknown -- most * + * movements and changes do this. */ + +/**/ +int lastcol; + +/* current history line number */ + +/**/ +int histline; + +/* the last line in the history (the current one), metafied */ + +/**/ +char *curhistline; + +/**/ +void +remember_edits(void) +{ + if (histline == curhist) { + zsfree(curhistline); + curhistline = metafy((char *) line, ll, META_DUP); + } + else { + Histent ent = gethistent(histline); + + if (metadiffer(ent->zle_text ? ent->zle_text : ent->text, + (char *) line, ll)) { + zsfree(ent->zle_text); + ent->zle_text = metafy((char *) line, ll, META_DUP); + } + } +} + +/**/ +void +forget_edits(void) +{ + int i; + + for (i = 0; i < histentct; i++) { + zsfree(histentarr[i].zle_text); + histentarr[i].zle_text = NULL; + } +} + +/**/ +void +uphistory(void) +{ + if (zmult < 0) { + zmult = -zmult; + downhistory(); + zmult = -zmult; + } else if(!zle_goto_hist(histline - zmult) && isset(HISTBEEP)) + feep(); +} + +/**/ +int +upline(void) +{ + int n = zmult; + + if (n < 0) { + zmult = -zmult; + n = downline(); + zmult = -zmult; + return n; + } + if (lastcol == -1) + lastcol = cs - findbol(); + cs = findbol(); + while (n) { + if (!cs) + break; + cs--; + cs = findbol(); + n--; + } + if (!n) { + int x = findeol(); + + if ((cs += lastcol) >= x) { + cs = x; + if (cs > findbol() && invicmdmode()) + cs--; + } + } + return n; +} + +/**/ +void +uplineorhistory(void) +{ + int ocs = cs; + int n = upline(); + if (n) { + int m = zmult; + + cs = ocs; + if (virangeflag || !histallowed) { + feep(); + return; + } + zmult = n; + uphistory(); + zmult = m; + } +} + +/**/ +void +viuplineorhistory(void) +{ + int col = lastcol; + uplineorhistory(); + lastcol = col; + vifirstnonblank(); +} + + +/**/ +void +uplineorsearch(void) +{ + int ocs = cs; + int n = upline(); + if (n) { + int m = zmult; + + cs = ocs; + if (virangeflag || !histallowed) { + feep(); + return; + } + zmult = n; + historysearchbackward(); + zmult = m; + } +} + +/**/ +int +downline(void) +{ + int n = zmult; + + if (n < 0) { + zmult = -zmult; + n = upline(); + zmult = -zmult; + return n; + } + if (lastcol == -1) + lastcol = cs - findbol(); + while (n) { + int x = findeol(); + + if (x == ll) + break; + cs = x + 1; + n--; + } + if (!n) { + int x = findeol(); + + if ((cs += lastcol) >= x) { + cs = x; + if (cs > findbol() && invicmdmode()) + cs--; + } + } + return n; +} + +/**/ +void +downlineorhistory(void) +{ + int ocs = cs; + int n = downline(); + if (n) { + int m = zmult; + + cs = ocs; + if (virangeflag || !histallowed) { + feep(); + return; + } + zmult = n; + downhistory(); + zmult = m; + } +} + +/**/ +void +vidownlineorhistory(void) +{ + int col = lastcol; + downlineorhistory(); + lastcol = col; + vifirstnonblank(); +} + +/**/ +void +downlineorsearch(void) +{ + int ocs = cs; + int n = downline(); + if (n) { + int m = zmult; + + cs = ocs; + if (virangeflag || !histallowed) { + feep(); + return; + } + zmult = n; + historysearchforward(); + zmult = m; + } +} + +/**/ +void +acceptlineanddownhistory(void) +{ + char *s; + + if (!(s = zle_get_event(histline + 1))) { + feep(); + return; + } + pushnode(bufstack, ztrdup(s)); + done = 1; + stackhist = histline + 1; +} + +/**/ +void +downhistory(void) +{ + if (zmult < 0) { + zmult = -zmult; + uphistory(); + zmult = -zmult; + } else if(!zle_goto_hist(histline + zmult) && isset(HISTBEEP)) + feep(); +} + +/**/ +void +historysearchbackward(void) +{ + int histpos, histmpos, hl = histline; + int n = zmult; + char *s; + + if (!n) + return; + if (n < 0) { + zmult = -n; + historysearchforward(); + zmult = n; + return; + } + for (histpos = histmpos = 0; histpos < ll && !iblank(line[histpos]); + histpos++, histmpos++) + if(imeta(line[histpos])) + histmpos++; + for (;;) { + hl--; + if (!(s = zle_get_event(hl))) { + feep(); + return; + } + if (metadiffer(s, (char *) line, histpos) < 0 && + iblank(s[histmpos] == Meta ? s[histmpos+1]^32 : s[histmpos]) && + metadiffer(s, (char *) line, ll) && !--n) + break; + } + zle_goto_hist(hl); +} + +/**/ +void +historysearchforward(void) +{ + int histpos, histmpos, hl = histline; + int n = zmult; + char *s; + + if (!n) + return; + if (n < 0) { + zmult = -n; + historysearchbackward(); + zmult = n; + return; + } + for (histpos = histmpos = 0; histpos < ll && !iblank(line[histpos]); + histpos++, histmpos++) + if(imeta(line[histpos])) + histmpos++; + for (;;) { + hl++; + if (!(s = zle_get_event(hl))) { + feep(); + return; + } + if (metadiffer(s, (char *) line, histpos) < (histline == curhist) && + (!s[histmpos] || + iblank(s[histmpos] == Meta ? s[histmpos+1]^32 : s[histmpos])) && + metadiffer(s, (char *) line, ll) && !--n) + break; + } + zle_goto_hist(hl); +} + +/**/ +void +beginningofbufferorhistory(void) +{ + if (findbol()) + cs = 0; + else + beginningofhistory(); +} + +/**/ +void +beginningofhistory(void) +{ + if (!zle_goto_hist(firsthist()) && isset(HISTBEEP)) + feep(); +} + +/**/ +void +endofbufferorhistory(void) +{ + if (findeol() != ll) + cs = ll; + else + endofhistory(); +} + +/**/ +void +endofhistory(void) +{ + zle_goto_hist(curhist); +} + +/**/ +void +insertlastword(void) +{ + int n; + char *s, *t; + Histent he; + +/* multiple calls will now search back through the history, pem */ + static char *lastinsert; + static int lasthist, lastpos; + int evhist = curhist - 1, save; + + if (lastinsert) { + int lastlen = ztrlen(lastinsert); + int pos = cs; + + if (lastpos <= pos && + lastlen == pos - lastpos && + memcmp(lastinsert, (char *)&line[lastpos], lastlen) == 0) { + evhist = --lasthist; + cs = lastpos; + foredel(pos - cs); + } + zsfree(lastinsert); + lastinsert = NULL; + } + if (!(he = quietgethist(evhist)) || !he->nwords) { + feep(); + return; + } + if (zmult > 0) { + n = he->nwords - (zmult - 1); + } else { + n = 1 - zmult; + } + if (n < 1 || n > he->nwords) { + feep(); + return; + } + s = he->text + he->words[2*n-2]; + t = he->text + he->words[2*n-1]; + save = *t; + *t = '\0'; /* ignore trailing whitespace */ + + lasthist = evhist; + lastpos = cs; + lastinsert = ztrdup(s); + n = zmult; + zmult = 1; + doinsert(s); + zmult = n; + *t = save; +} + +/**/ +char * +qgetevent(int ev) +{ + return ((ev == curhist) ? curhistline : quietgetevent(ev)); +} + +/**/ +char * +zle_get_event(int ev) +{ + Histent ent; + + if (ev == curhist) + return curhistline; + if (! (ent = quietgethist(ev))) + return NULL; + if (ent->zle_text) + return ent->zle_text; + return ent->text; +} + +/**/ +static int +zle_goto_hist(int ev) +{ + char *t; + + remember_edits(); + if(!(t = zle_get_event(ev))) + return 0; + mkundoent(); + histline = ev; + setline(t); + setlastline(); + return 1; +} + +/**/ +void +pushline(void) +{ + int n = zmult; + + if (n < 0) + return; + pushnode(bufstack, metafy((char *) line, ll, META_DUP)); + while (--n) + pushnode(bufstack, ztrdup("")); + stackcs = cs; + *line = '\0'; + ll = cs = 0; +} + +/**/ +void +pushlineoredit(void) +{ + int ics; + unsigned char *s; + char *hline = hgetline(); + + if (zmult < 0) + return; + if (hline && *hline) { + ics = ztrlen(hline); + sizeline(ics + ll + 1); + for (s = line + ll; --s >= line; *(s + ics) = *s); + for (s = line; *hline; hline++) + *s++ = *hline == Meta ? *++hline ^ 32 : *hline; + ll += ics; + cs += ics; + } + pushline(); + if (!isfirstln) { + errflag = done = 1; + } +} + +/**/ +void +pushinput(void) +{ + int i; + + if (zmult < 0) + return; + zmult += i = !isfirstln; + pushlineoredit(); + zmult -= i; +} + +/**/ +void +getline(void) +{ + char *s = (char *)getlinknode(bufstack); + + if (!s) + feep(); + else { + int cc; + + unmetafy(s, &cc); + spaceinline(cc); + memcpy((char *)line + cs, s, cc); + cs += cc; + free(s); + } +} + +/**/ +void +historyincrementalsearchbackward(void) +{ + doisearch(-1); +} + +/**/ +void +historyincrementalsearchforward(void) +{ + doisearch(1); +} + +static struct isrch_spot { + int hl; /* This spot's histline */ + unsigned short pos; /* The search position in our metafied 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 */ +#define ISS_FAILING 1 +#define ISS_FORWARD 2 +} *isrch_spots; + +static int max_spot = 0; + +#ifdef MODULE + +/**/ +void +free_isrch_spots(void) +{ + zfree(isrch_spots, max_spot * sizeof(*isrch_spots)); +} + +#endif /* MODULE */ + +/**/ +static void +set_isrch_spot(int num, int hl, int pos, int cs, int len, int dir, int nomatch) +{ + if (num >= max_spot) { + if (!isrch_spots) { + isrch_spots = (struct isrch_spot*) + zalloc((max_spot = 64) * sizeof *isrch_spots); + } else { + isrch_spots = (struct isrch_spot*)realloc((char*)isrch_spots, + (max_spot += 64) * sizeof *isrch_spots); + } + } + + isrch_spots[num].hl = hl; + isrch_spots[num].pos = (unsigned short)pos; + isrch_spots[num].cs = (unsigned short)cs; + isrch_spots[num].len = (unsigned short)len; + isrch_spots[num].flags = (dir > 0? ISS_FORWARD : 0) + + (nomatch? ISS_FAILING : 0); +} + +/**/ +static void +get_isrch_spot(int num, int *hlp, int *posp, int *csp, int *lenp, int *dirp, int *nomatch) +{ + *hlp = isrch_spots[num].hl; + *posp = (int)isrch_spots[num].pos; + *csp = (int)isrch_spots[num].cs; + *lenp = (int)isrch_spots[num].len; + *dirp = (isrch_spots[num].flags & ISS_FORWARD)? 1 : -1; + *nomatch = (isrch_spots[num].flags & ISS_FAILING); +} + +#define ISEARCH_PROMPT "failing XXX-i-search: " +#define NORM_PROMPT_POS 8 +#define FIRST_SEARCH_CHAR (NORM_PROMPT_POS + 14) + +/**/ +static void +doisearch(int dir) +{ + char *s, *ibuf = halloc(80), *sbuf = ibuf + FIRST_SEARCH_CHAR; + int sbptr = 0, top_spot = 0, pos, sibuf = 80; + int nomatch = 0, skip_line = 0, skip_pos = 0; + int odir = dir, sens = zmult == 1 ? 3 : 1; + int hl = histline; + Thingy cmd; + char *okeymap = curkeymapname; + static char *previous_search = NULL; + static int previous_search_len = 0; + + strcpy(ibuf, ISEARCH_PROMPT); + memcpy(ibuf + NORM_PROMPT_POS, (dir == 1) ? "fwd" : "bck", 3); + remember_edits(); + s = zle_get_event(hl); + selectkeymap("main", 1); + pos = metalen(s, cs); + for (;;) { + /* Remember the current values in case search fails (doesn't push). */ + set_isrch_spot(top_spot, hl, pos, cs, sbptr, dir, nomatch); + if (sbptr == 1 && sbuf[0] == '^') { + cs = 0; + nomatch = 0; + statusline = ibuf + NORM_PROMPT_POS; + } else if (sbptr > 0) { + char *last_line = s; + + for (;;) { + char *t; + + if (skip_pos) { + if (dir < 0) { + if (pos == 0) + skip_line = 1; + else + pos -= 1 + (pos != 1 && s[pos-2] == Meta); + } else if (sbuf[0] != '^') { + if (pos >= strlen(s+1)) + skip_line = 1; + else + pos += 1 + (s[pos] == Meta); + } else + skip_line = 1; + skip_pos = 0; + } + if (!skip_line && ((sbuf[0] == '^') ? + (t = metadiffer(s, sbuf + 1, sbptr - 1) < sens ? s : NULL) : + (t = hstrnstr(s, pos, sbuf, sbptr, dir, sens)))) { + zle_goto_hist(hl); + pos = t - s; + cs = ztrsub(t, s) + (dir == 1? sbptr - (sbuf[0]=='^') : 0); + nomatch = 0; + statusline = ibuf + NORM_PROMPT_POS; + break; + } + hl += dir; + if (!(s = zle_get_event(hl))) { + if (sbptr == (int)isrch_spots[top_spot-1].len + && (isrch_spots[top_spot-1].flags & ISS_FAILING)) + top_spot--; + get_isrch_spot(top_spot, &hl, &pos, &cs, &sbptr, + &dir, &nomatch); + if (!nomatch) { + feep(); + nomatch = 1; + } + s = last_line; + skip_line = 0; + statusline = ibuf; + break; + } + pos = dir == 1? 0 : strlen(s); + skip_line = !strcmp(last_line, s); + } + } else { + top_spot = 0; + nomatch = 0; + statusline = ibuf + NORM_PROMPT_POS; + } + sbuf[sbptr] = '_'; + statusll = sbuf - statusline + sbptr + 1; + ref: + refresh(); + if (!(cmd = getkeycmd()) || cmd == Th(z_sendbreak)) { + int i; + get_isrch_spot(0, &hl, &pos, &i, &sbptr, &dir, &nomatch); + s = zle_get_event(hl); + zle_goto_hist(hl); + cs = i; + break; + } + if(cmd == Th(z_clearscreen)) { + clearscreen(); + goto ref; + } else if(cmd == Th(z_redisplay)) { + redisplay(); + goto ref; + } else if(cmd == Th(z_vicmdmode)) { + if(selectkeymap(invicmdmode() ? "main" : "vicmd", 0)) + feep(); + goto ref; + } else if(cmd == Th(z_vibackwarddeletechar) || + cmd == Th(z_backwarddeletechar)) { + if (top_spot) + get_isrch_spot(--top_spot, &hl, &pos, &cs, &sbptr, + &dir, &nomatch); + else + feep(); + if (nomatch) { + statusline = ibuf; + skip_pos = 1; + } + s = zle_get_event(hl); + if (nomatch || !sbptr || (sbptr == 1 && sbuf[0] == '^')) { + int i = cs; + zle_goto_hist(hl); + cs = i; + } + memcpy(ibuf + NORM_PROMPT_POS, (dir == 1) ? "fwd" : "bck", 3); + continue; + } else if(cmd == Th(z_acceptandhold)) { + acceptandhold(); + break; + } else if(cmd == Th(z_acceptandinfernexthistory)) { + acceptandinfernexthistory(); + break; + } else if(cmd == Th(z_acceptlineanddownhistory)) { + acceptlineanddownhistory(); + break; + } else if(cmd == Th(z_acceptline)) { + acceptline(); + break; + } else if(cmd == Th(z_historyincrementalsearchbackward)) { + set_isrch_spot(top_spot++, hl, pos, cs, sbptr, dir, nomatch); + if (dir != -1) + dir = -1; + else + skip_pos = 1; + goto rpt; + } else if(cmd == Th(z_historyincrementalsearchforward)) { + set_isrch_spot(top_spot++, hl, pos, cs, sbptr, dir, nomatch); + if (dir != 1) + dir = 1; + else + skip_pos = 1; + goto rpt; + } else if(cmd == Th(z_virevrepeatsearch)) { + set_isrch_spot(top_spot++, hl, pos, cs, sbptr, dir, nomatch); + dir = -odir; + skip_pos = 1; + goto rpt; + } else if(cmd == Th(z_virepeatsearch)) { + set_isrch_spot(top_spot++, hl, pos, cs, sbptr, dir, nomatch); + dir = odir; + skip_pos = 1; + rpt: + if (!sbptr && previous_search_len) { + if (previous_search_len > sibuf - FIRST_SEARCH_CHAR - 2) { + ibuf = hrealloc(ibuf, sibuf, sibuf + previous_search_len); + sbuf = ibuf + FIRST_SEARCH_CHAR; + sibuf += previous_search_len; + } + memcpy(sbuf, previous_search, sbptr = previous_search_len); + } + memcpy(ibuf + NORM_PROMPT_POS, (dir == 1) ? "fwd" : "bck", 3); + continue; + } else if(cmd == Th(z_viquotedinsert) || + cmd == Th(z_quotedinsert)) { + if(cmd == Th(z_viquotedinsert)) { + sbuf[sbptr] = '^'; + refresh(); + } + if ((c = getkey(0)) == EOF) + feep(); + else + goto ins; + } else { + if(cmd == Th(z_selfinsertunmeta)) { + c &= 0x7f; + if(c == '\r') + c = '\n'; + } else if (cmd == Th(z_magicspace)) + c = ' '; + else if (cmd != Th(z_selfinsert)) { + ungetkeycmd(); + if (cmd == Th(z_sendbreak)) + sbptr = 0; + break; + } + ins: + if (sbptr == PATH_MAX) { + feep(); + continue; + } + set_isrch_spot(top_spot++, hl, pos, cs, sbptr, dir, nomatch); + if (sbptr == sibuf - FIRST_SEARCH_CHAR - 2) { + ibuf = hrealloc(ibuf, sibuf, sibuf * 2); + sbuf = ibuf + FIRST_SEARCH_CHAR; + sibuf *= 2; + } + sbuf[sbptr++] = c; + } + handlefeep(); + } + if (sbptr) { + zfree(previous_search, previous_search_len); + previous_search = zalloc(sbptr); + memcpy(previous_search, sbuf, previous_search_len = sbptr); + } + statusline = NULL; + selectkeymap(okeymap, 1); +} + +/**/ +void +acceptandinfernexthistory(void) +{ + int t0; + char *s; + + done = 1; + for (t0 = histline - 2;; t0--) { + if (!(s = qgetevent(t0))) + return; + if (!metadiffer(s, (char *) line, ll)) + break; + } + if (!(s = qgetevent(t0 + 1))) + return; + pushnode(bufstack, ztrdup(s)); + stackhist = t0 + 1; +} + +/**/ +void +infernexthistory(void) +{ + int t0; + char *s; + + for (t0 = histline - 2;; t0--) { + if (!(s = qgetevent(t0))) { + feep(); + return; + } + if (! metadiffer(s, (char *) line, ll)) + break; + } + if (!(s = qgetevent(t0 + 1))) { + feep(); + return; + } + zle_goto_hist(t0 + 1); +} + +/**/ +void +vifetchhistory(void) +{ + if (zmult < 0) + return; + if (histline == curhist) { + if (!(zmod.flags & MOD_MULT)) { + cs = ll; + cs = findbol(); + return; + } + } + if (!zle_goto_hist((zmod.flags & MOD_MULT) ? zmult : curhist) && + isset(HISTBEEP)) + feep(); +} + +/* the last vi search */ + +static char *visrchstr; +static int visrchsense; + +/**/ +static int +getvisrchstr(void) +{ + char *sbuf = halloc(80); + int sptr = 1, ret = 0, ssbuf = 80; + Thingy cmd; + char *okeymap = curkeymapname; + + if (visrchstr) { + zsfree(visrchstr); + visrchstr = NULL; + } + statusline = sbuf; + sbuf[0] = (visrchsense == -1) ? '?' : '/'; + selectkeymap("main", 1); + while (sptr) { + sbuf[sptr] = '_'; + statusll = sptr + 1; + refresh(); + if (!(cmd = getkeycmd()) || cmd == Th(z_sendbreak)) { + ret = 0; + break; + } + if(cmd == Th(z_magicspace)) { + c = ' '; + cmd = Th(z_selfinsert); + } + if(cmd == Th(z_redisplay)) { + redisplay(); + } else if(cmd == Th(z_clearscreen)) { + clearscreen(); + } else if(cmd == Th(z_acceptline) || + cmd == Th(z_vicmdmode)) { + sbuf[sptr] = 0; + visrchstr = metafy(sbuf + 1, sptr - 1, META_DUP); + ret = 1; + sptr = 0; + } else if(cmd == Th(z_backwarddeletechar) || + cmd == Th(z_vibackwarddeletechar)) { + sptr--; + } else if(cmd == Th(z_backwardkillword) || + cmd == Th(z_vibackwardkillword)) { + while(sptr != 1 && iblank(sbuf[sptr - 1])) + sptr--; + if(iident(sbuf[sptr - 1])) + while(sptr != 1 && iident(sbuf[sptr - 1])) + sptr--; + else + while(sptr != 1 && !iident(sbuf[sptr - 1]) && !iblank(sbuf[sptr - 1])) + sptr--; + } else if(cmd == Th(z_viquotedinsert) || cmd == Th(z_quotedinsert)) { + if(cmd == Th(z_viquotedinsert)) { + sbuf[sptr] = '^'; + refresh(); + } + if ((c = getkey(0)) == EOF) + feep(); + else + goto ins; + } else if(cmd == Th(z_selfinsertunmeta) || cmd == Th(z_selfinsert)) { + if(cmd == Th(z_selfinsertunmeta)) { + c &= 0x7f; + if(c == '\r') + c = '\n'; + } + ins: + if(sptr == ssbuf - 1) { + char *newbuf = halloc(ssbuf *= 2); + strcpy(newbuf, sbuf); + statusline = sbuf = newbuf; + } + sbuf[sptr++] = c; + } else { + feep(); + } + handlefeep(); + } + statusline = NULL; + selectkeymap(okeymap, 1); + return ret; +} + +/**/ +void +vihistorysearchforward(void) +{ + visrchsense = 1; + if (getvisrchstr()) + virepeatsearch(); +} + +/**/ +void +vihistorysearchbackward(void) +{ + visrchsense = -1; + if (getvisrchstr()) + virepeatsearch(); +} + +/**/ +void +virepeatsearch(void) +{ + int hl = histline, t0; + int n = zmult; + char *s; + + if (!visrchstr) { + feep(); + return; + } + if (!n) + return; + if (n < 0) { + n = -n; + visrchsense = -visrchsense; + } + t0 = strlen(visrchstr); + for (;;) { + hl += visrchsense; + if (!(s = zle_get_event(hl))) { + feep(); + return; + } + if (!metadiffer(s, (char *) line, ll)) + continue; + if (*visrchstr == '^') { + if (strncmp(s, visrchstr + 1, t0 - 1) != 0) + continue; + } else if (!hstrnstr(s, 0, visrchstr, t0, 1, 1)) + continue; + if (--n <= 0) + break; + } + zle_goto_hist(hl); +} + +/**/ +void +virevrepeatsearch(void) +{ + visrchsense = -visrchsense; + virepeatsearch(); + visrchsense = -visrchsense; +} + +/* Extra function added by A.R. Iano-Fletcher. */ +/*The extern variable "cs" is the position of the cursor. */ +/* history-beginning-search-backward */ + +/**/ +void +historybeginningsearchbackward(void) +{ + int cpos = cs; /* save cursor position */ + int hl = histline; + int n = zmult; + char *s; + + if (!n) + return; + if (n < 0) { + zmult = -n; + historybeginningsearchforward(); + zmult = n; + return; + } + for (;;) { + hl--; + if (!(s = zle_get_event(hl))) { + feep(); + return; + } + if (metadiffer(s, (char *)line, cs) < 0 && + metadiffer(s, (char *)line, ll)) + if (--n <= 0) + break; + } + + zle_goto_hist(hl); + cs = cpos; +} + +/* Extra function added by A.R. Iano-Fletcher. */ + +/* history-beginning-search-forward */ +/**/ +void +historybeginningsearchforward(void) +{ + int cpos = cs; /* save cursor position */ + int hl = histline; + int n = zmult; + char *s; + + if (!n) + return; + if (n < 0) { + zmult = -n; + historybeginningsearchbackward(); + zmult = n; + return; + } + for (;;) { + hl++; + if (!(s = zle_get_event(hl))) { + feep(); + return; + } + if (metadiffer(s, (char *)line, cs) < (hl == curhist) && + metadiffer(s, (char *)line, ll)) + if (--n <= 0) + break; + } + + zle_goto_hist(hl); + cs = cpos; +} -- cgit 1.4.1