1
0
mirror of git://git.code.sf.net/p/zsh/code synced 2024-11-20 05:53:52 +01:00
zsh/Src/Zle/zle_hist.c
Wayne Davison f18dca3266 Fixed acceptandinfernexthistory() to work when called repeatedly.
Also changed it to not accept the line if the infer fails.  Ignore
transient edits in the history when searching for an inference and
grabbing the next line (affecting acceptandinfernexthistory(),
infernexthistory(), and acceptlineanddownhistory()).
2001-05-26 20:57:16 +00:00

1200 lines
24 KiB
C

/*
* 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"
/* 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;
#define ZLETEXT(X) ((X)->zle_text ? (X)->zle_text : (X)->text)
/**/
void
remember_edits(void)
{
Histent ent = quietgethist(histline);
if (metadiffer(ZLETEXT(ent), (char *) line, ll)) {
zsfree(ent->zle_text);
ent->zle_text = metafy((char *) line, ll, META_DUP);
}
}
/**/
void
forget_edits(void)
{
Histent he;
for (he = hist_ring; he; he = up_histent(he)) {
zsfree(he->zle_text);
he->zle_text = NULL;
}
}
/**/
int
uphistory(char **args)
{
int nodups = isset(HISTIGNOREDUPS);
if (!zle_goto_hist(histline, -zmult, nodups) && isset(HISTBEEP))
return 1;
return 0;
}
/**/
static 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;
}
/**/
int
uplineorhistory(char **args)
{
int ocs = cs;
int n = upline();
if (n) {
int m = zmult, ret;
cs = ocs;
if (virangeflag || !(zlereadflags & ZLRF_HISTORY))
return 1;
zmult = n;
ret = uphistory(args);
zmult = m;
return ret;
}
return 0;
}
/**/
int
viuplineorhistory(char **args)
{
int col = lastcol;
uplineorhistory(args);
lastcol = col;
return vifirstnonblank(args);
}
/**/
int
uplineorsearch(char **args)
{
int ocs = cs;
int n = upline();
if (n) {
int m = zmult, ret;
cs = ocs;
if (virangeflag || !(zlereadflags & ZLRF_HISTORY))
return 1;
zmult = n;
ret = historysearchbackward(args);
zmult = m;
return ret;
}
return 0;
}
/**/
static 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;
}
/**/
int
downlineorhistory(char **args)
{
int ocs = cs;
int n = downline();
if (n) {
int m = zmult, ret;
cs = ocs;
if (virangeflag || !(zlereadflags & ZLRF_HISTORY))
return 1;
zmult = n;
ret = downhistory(args);
zmult = m;
return ret;
}
return 0;
}
/**/
int
vidownlineorhistory(char **args)
{
int col = lastcol;
downlineorhistory(args);
lastcol = col;
return vifirstnonblank(zlenoargs);
}
/**/
int
downlineorsearch(char **args)
{
int ocs = cs;
int n = downline();
if (n) {
int m = zmult, ret;
cs = ocs;
if (virangeflag || !(zlereadflags & ZLRF_HISTORY))
return 1;
zmult = n;
ret = historysearchforward(args);
zmult = m;
return ret;
}
return 0;
}
/**/
int
acceptlineanddownhistory(char **args)
{
Histent he;
if (!(he = movehistent(quietgethist(histline), 1, HIST_FOREIGN)))
return 1;
zpushnode(bufstack, ztrdup(he->text));
done = 1;
stackhist = he->histnum;
return 0;
}
/**/
int
downhistory(char **args)
{
int nodups = isset(HISTIGNOREDUPS);
if (!zle_goto_hist(histline, zmult, nodups) && isset(HISTBEEP))
return 1;
return 0;
}
static int histpos, srch_hl, srch_cs = -1;
static char *srch_str;
/**/
int
historysearchbackward(char **args)
{
Histent he;
int n = zmult, hp;
char *s, *str;
if (zmult < 0) {
int ret;
zmult = -n;
ret = historysearchforward(args);
zmult = n;
return ret;
}
if ((str = *args))
hp = strlen(str);
else {
if (histline == curhist || histline != srch_hl || cs != srch_cs ||
mark != 0 || memcmp(srch_str, line, histpos) != 0) {
zfree(srch_str, histpos);
for (histpos = 0; histpos < ll && !iblank(line[histpos]); histpos++) ;
if (histpos < ll)
histpos++;
srch_str = zalloc(histpos);
memcpy(srch_str, line, histpos);
}
str = srch_str;
hp = histpos;
}
he = quietgethist(histline);
while ((he = movehistent(he, -1, hist_skip_flags))) {
if (isset(HISTFINDNODUPS) && he->flags & HIST_DUP)
continue;
s = ZLETEXT(he);
if (metadiffer(s, str, hp) < 0 &&
(*args || metadiffer(s, str, ll))) {
if (--n <= 0) {
zle_setline(he);
srch_hl = histline;
srch_cs = cs;
return 0;
}
}
}
return 1;
}
/**/
int
historysearchforward(char **args)
{
Histent he;
int n = zmult, hp;
char *s, *str;
if (zmult < 0) {
int ret;
zmult = -n;
ret = historysearchbackward(args);
zmult = n;
return ret;
}
if ((str = *args))
hp = strlen(str);
else {
if (histline == curhist || histline != srch_hl || cs != srch_cs ||
mark != 0 || memcmp(srch_str, line, histpos) != 0) {
zfree(srch_str, histpos);
for (histpos = 0; histpos < ll && !iblank(line[histpos]); histpos++) ;
if (histpos < ll)
histpos++;
srch_str = zalloc(histpos);
memcpy(srch_str, line, histpos);
}
str = srch_str;
hp = histpos;
}
he = quietgethist(histline);
while ((he = movehistent(he, 1, hist_skip_flags))) {
if (isset(HISTFINDNODUPS) && he->flags & HIST_DUP)
continue;
s = ZLETEXT(he);
if (metadiffer(s, str, hp) < (he->histnum == curhist) &&
(*args || metadiffer(s, str, ll))) {
if (--n <= 0) {
zle_setline(he);
srch_hl = histline;
srch_cs = cs;
return 0;
}
}
}
return 1;
}
/**/
int
beginningofbufferorhistory(char **args)
{
if (findbol())
cs = 0;
else
return beginningofhistory(args);
return 0;
}
/**/
int
beginningofhistory(char **args)
{
if (!zle_goto_hist(firsthist(), 0, 0) && isset(HISTBEEP))
return 1;
return 0;
}
/**/
int
endofbufferorhistory(char **args)
{
if (findeol() != ll)
cs = ll;
else
return endofhistory(args);
return 0;
}
/**/
int
endofhistory(char **args)
{
zle_goto_hist(curhist, 0, 0);
return 0;
}
/**/
int
insertlastword(char **args)
{
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 = addhistnum(curhist, -1, HIST_FOREIGN), save;
if (lastinsert) {
int lastlen = ztrlen(lastinsert);
int pos = cs;
if (lastpos <= pos &&
lastlen == pos - lastpos &&
memcmp(lastinsert, (char *)&line[lastpos], lastlen) == 0) {
evhist = addhistnum(lasthist, -1, HIST_FOREIGN);
cs = lastpos;
foredel(pos - cs);
}
zsfree(lastinsert);
lastinsert = NULL;
}
if (!(he = quietgethist(evhist)) || !he->nwords)
return 1;
if (zmult > 0) {
n = he->nwords - (zmult - 1);
} else {
n = 1 - zmult;
}
if (n < 1 || n > he->nwords)
return 1;
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;
return 0;
}
/**/
void
zle_setline(Histent he)
{
remember_edits();
mkundoent();
histline = he->histnum;
setline(ZLETEXT(he));
setlastline();
clearlist = 1;
}
/**/
int
setlocalhistory(char **args)
{
if (zmod.flags & MOD_MULT) {
hist_skip_flags = zmult? HIST_FOREIGN : 0;
} else {
hist_skip_flags ^= HIST_FOREIGN;
}
return 0;
}
/**/
int
zle_goto_hist(int ev, int n, int skipdups)
{
Histent he = movehistent(quietgethist(ev), n, hist_skip_flags);
if (skipdups && n) {
n = n < 0? -1 : 1;
while (he && !metadiffer(ZLETEXT(he), (char *) line, ll))
he = movehistent(he, n, hist_skip_flags);
}
if (!he)
return 0;
zle_setline(he);
return 1;
}
/**/
int
pushline(char **args)
{
int n = zmult;
if (n < 0)
return 1;
zpushnode(bufstack, metafy((char *) line, ll, META_DUP));
while (--n)
zpushnode(bufstack, ztrdup(""));
stackcs = cs;
*line = '\0';
ll = cs = 0;
clearlist = 1;
return 0;
}
/**/
int
pushlineoredit(char **args)
{
int ics, ret;
unsigned char *s;
char *hline = hgetline();
if (zmult < 0)
return 1;
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;
}
ret = pushline(args);
if (!isfirstln)
errflag = done = 1;
clearlist = 1;
return ret;
}
/**/
int
pushinput(char **args)
{
int i, ret;
if (zmult < 0)
return 1;
zmult += i = !isfirstln;
ret = pushlineoredit(args);
zmult -= i;
return ret;
}
/**/
int
getline(char **args)
{
char *s = (char *)getlinknode(bufstack);
if (!s) {
return 1;
} else {
int cc;
unmetafy(s, &cc);
spaceinline(cc);
memcpy((char *)line + cs, s, cc);
cs += cc;
free(s);
clearlist = 1;
}
return 0;
}
/**/
int
historyincrementalsearchbackward(char **args)
{
doisearch(args, -1);
return 0;
}
/**/
int
historyincrementalsearchforward(char **args)
{
doisearch(args, 1);
return 0;
}
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;
/**/
void
free_isrch_spots(void)
{
zfree(isrch_spots, max_spot * sizeof(*isrch_spots));
}
/**/
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(char **args, int dir)
{
char *s, *ibuf = zhalloc(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, savekeys = -1, feep = 0;
Thingy cmd;
char *okeymap = curkeymapname;
static char *previous_search = NULL;
static int previous_search_len = 0;
Histent he;
clearlist = 1;
if (*args) {
int len;
char *arg;
savekeys = kungetct;
arg = getkeystring(*args, &len, 2, NULL);
ungetkeys(arg, len);
}
strcpy(ibuf, ISEARCH_PROMPT);
memcpy(ibuf + NORM_PROMPT_POS, (dir == 1) ? "fwd" : "bck", 3);
remember_edits();
he = quietgethist(hl);
s = ZLETEXT(he);
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_setline(he);
pos = t - s;
cs = ztrsub(t, s) + (dir == 1? sbptr - (sbuf[0]=='^') : 0);
nomatch = 0;
statusline = ibuf + NORM_PROMPT_POS;
break;
}
if (!(he = movehistent(he, dir, hist_skip_flags))) {
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 = 1;
nomatch = 1;
}
he = quietgethist(hl);
s = ZLETEXT(he);
skip_line = 0;
statusline = ibuf;
break;
}
hl = he->histnum;
s = ZLETEXT(he);
pos = dir == 1? 0 : strlen(s);
skip_line = isset(HISTFINDNODUPS)? !!(he->flags & HIST_DUP)
: !strcmp(last_line, s);
}
} else {
top_spot = 0;
nomatch = 0;
statusline = ibuf + NORM_PROMPT_POS;
}
sbuf[sbptr] = '_';
statusll = sbuf - statusline + sbptr + 1;
ref:
zrefresh();
if (!(cmd = getkeycmd()) || cmd == Th(z_sendbreak)) {
int i;
get_isrch_spot(0, &hl, &pos, &i, &sbptr, &dir, &nomatch);
he = quietgethist(hl);
zle_setline(he);
s = ZLETEXT(he);
cs = i;
break;
}
if(cmd == Th(z_clearscreen)) {
clearscreen(zlenoargs);
goto ref;
} else if(cmd == Th(z_redisplay)) {
redisplay(zlenoargs);
goto ref;
} else if(cmd == Th(z_vicmdmode)) {
if(selectkeymap(invicmdmode() ? "main" : "vicmd", 0))
feep = 1;
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 = 1;
if (nomatch) {
statusline = ibuf;
skip_pos = 1;
}
he = quietgethist(hl);
s = ZLETEXT(he);
if (nomatch || !sbptr || (sbptr == 1 && sbuf[0] == '^')) {
int i = cs;
zle_setline(he);
cs = i;
}
memcpy(ibuf + NORM_PROMPT_POS, (dir == 1) ? "fwd" : "bck", 3);
continue;
} else if(cmd == Th(z_acceptandhold)) {
acceptandhold(zlenoargs);
break;
} else if(cmd == Th(z_acceptandinfernexthistory)) {
acceptandinfernexthistory(zlenoargs);
break;
} else if(cmd == Th(z_acceptlineanddownhistory)) {
acceptlineanddownhistory(zlenoargs);
break;
} else if(cmd == Th(z_acceptline)) {
acceptline(zlenoargs);
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] = '^';
zrefresh();
}
if ((c = getkey(0)) == EOF)
feep = 1;
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 = 1;
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;
}
if (feep)
handlefeep(zlenoargs);
feep = 0;
}
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);
/*
* Don't allow unused characters provided as a string to the
* widget to overflow and be used as separated commands.
*/
if (savekeys >= 0 && kungetct > savekeys)
kungetct = savekeys;
}
static Histent
infernexthist(Histent he, char **args)
{
for (he = movehistent(he, -2, HIST_FOREIGN);
he; he = movehistent(he, -1, HIST_FOREIGN)) {
if (!metadiffer(he->text, (char *) line, ll))
return movehistent(he, 1, HIST_FOREIGN);
}
return NULL;
}
/**/
int
acceptandinfernexthistory(char **args)
{
Histent he;
if (!(he = infernexthist(hist_ring, args)))
return 1;
zpushnode(bufstack, ztrdup(he->text));
done = 1;
stackhist = he->histnum;
return 0;
}
/**/
int
infernexthistory(char **args)
{
Histent he;
if (!(he = infernexthist(quietgethist(histline), args)))
return 1;
zle_setline(he);
return 0;
}
/**/
int
vifetchhistory(char **args)
{
if (zmult < 0)
return 1;
if (histline == curhist) {
if (!(zmod.flags & MOD_MULT)) {
cs = ll;
cs = findbol();
return 0;
}
}
if (!zle_goto_hist((zmod.flags & MOD_MULT) ? zmult : curhist, 0, 0) &&
isset(HISTBEEP)) {
return 1;
}
return 0;
}
/* the last vi search */
static char *visrchstr;
static int visrchsense;
/**/
static int
getvisrchstr(void)
{
char *sbuf = zhalloc(80);
int sptr = 1, ret = 0, ssbuf = 80, feep = 0;
Thingy cmd;
char *okeymap = curkeymapname;
if (visrchstr) {
zsfree(visrchstr);
visrchstr = NULL;
}
clearlist = 1;
statusline = sbuf;
sbuf[0] = (visrchsense == -1) ? '?' : '/';
selectkeymap("main", 1);
while (sptr) {
sbuf[sptr] = '_';
statusll = sptr + 1;
zrefresh();
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(zlenoargs);
} else if(cmd == Th(z_clearscreen)) {
clearscreen(zlenoargs);
} 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] = '^';
zrefresh();
}
if ((c = getkey(0)) == EOF)
feep = 1;
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 = zhalloc(ssbuf *= 2);
strcpy(newbuf, sbuf);
statusline = sbuf = newbuf;
}
sbuf[sptr++] = c;
} else {
feep = 1;
}
if (feep)
handlefeep(zlenoargs);
feep = 0;
}
statusline = NULL;
selectkeymap(okeymap, 1);
return ret;
}
/**/
int
vihistorysearchforward(char **args)
{
if (*args) {
int ose = visrchsense, ret;
char *ost = visrchstr;
visrchsense = 1;
visrchstr = *args;
ret = virepeatsearch(zlenoargs);
visrchsense = ose;
visrchstr = ost;
return ret;
}
visrchsense = 1;
if (getvisrchstr())
return virepeatsearch(zlenoargs);
return 1;
}
/**/
int
vihistorysearchbackward(char **args)
{
if (*args) {
int ose = visrchsense, ret;
char *ost = visrchstr;
visrchsense = -1;
visrchstr = *args;
ret = virepeatsearch(zlenoargs);
visrchsense = ose;
visrchstr = ost;
return ret;
}
visrchsense = -1;
if (getvisrchstr())
return virepeatsearch(zlenoargs);
return 1;
}
/**/
int
virepeatsearch(char **args)
{
Histent he;
int t0;
int n = zmult;
char *s;
if (!visrchstr)
return 1;
if (zmult < 0) {
n = -n;
visrchsense = -visrchsense;
}
t0 = strlen(visrchstr);
he = quietgethist(histline);
while ((he = movehistent(he, visrchsense, hist_skip_flags))) {
if (isset(HISTFINDNODUPS) && he->flags & HIST_DUP)
continue;
s = ZLETEXT(he);
if (metadiffer(s, (char *) line, ll)
&& (*visrchstr == '^'? strncmp(s, visrchstr + 1, t0 - 1) == 0
: hstrnstr(s, 0, visrchstr, t0, 1, 1) != 0)) {
if (--n <= 0) {
zle_setline(he);
return 0;
}
}
}
return 1;
}
/**/
int
virevrepeatsearch(char **args)
{
int ret;
visrchsense = -visrchsense;
ret = virepeatsearch(args);
visrchsense = -visrchsense;
return ret;
}
/* Extra function added by A.R. Iano-Fletcher. */
/*The extern variable "cs" is the position of the cursor. */
/* history-beginning-search-backward */
/**/
int
historybeginningsearchbackward(char **args)
{
Histent he;
int cpos = cs; /* save cursor position */
int n = zmult;
char *s;
if (zmult < 0) {
int ret;
zmult = -n;
ret = historybeginningsearchforward(args);
zmult = n;
return ret;
}
he = quietgethist(histline);
while ((he = movehistent(he, -1, hist_skip_flags))) {
if (isset(HISTFINDNODUPS) && he->flags & HIST_DUP)
continue;
s = ZLETEXT(he);
if (metadiffer(s, (char *)line, cs) < 0 &&
metadiffer(s, (char *)line, ll)) {
if (--n <= 0) {
zle_setline(he);
cs = cpos;
return 0;
}
}
}
return 1;
}
/* Extra function added by A.R. Iano-Fletcher. */
/* history-beginning-search-forward */
/**/
int
historybeginningsearchforward(char **args)
{
Histent he;
int cpos = cs; /* save cursor position */
int n = zmult;
char *s;
if (zmult < 0) {
int ret;
zmult = -n;
ret = historybeginningsearchbackward(args);
zmult = n;
return ret;
}
he = quietgethist(histline);
while ((he = movehistent(he, 1, hist_skip_flags))) {
if (isset(HISTFINDNODUPS) && he->flags & HIST_DUP)
continue;
s = ZLETEXT(he);
if (metadiffer(s, (char *)line, cs) < (he->histnum == curhist) &&
metadiffer(s, (char *)line, ll)) {
if (--n <= 0) {
zle_setline(he);
cs = cpos;
return 0;
}
}
}
return 1;
}