This is zle_hist.c in view mode; [Download] [Up]
/*
* $Id: zle_hist.c,v 2.24 1996/10/15 20:16:35 hzoli Exp $
*
* zle_hist.c - history editing
*
* This file is part of zsh, the Z shell.
*
* Copyright (c) 1992-1996 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.
*
*/
#define ZLE
#include "zsh.h"
/**/
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)
{
char *s;
if (zmult < 0) {
zmult = -zmult;
downhistory();
return;
}
remember_edits();
histline -= zmult;
if (!(s = zle_get_event(histline))) {
if (isset(HISTBEEP))
feep();
histline += zmult;
} else
setline(s);
}
/**/
void
uplineorhistory(void)
{
int ocs = cs;
if (zmult < 0) {
zmult = -zmult;
downlineorhistory();
return;
}
if ((lastcmd & ZLE_LINEMOVE) != ZLE_LINEMOVE)
lastcol = cs - findbol();
cs = findbol();
while (zmult) {
if (!cs)
break;
cs--;
cs = findbol();
zmult--;
}
if (zmult) {
cs = ocs;
if (virangeflag || in_vared) {
feep();
return;
}
uphistory();
} else {
int x = findeol();
if ((cs += lastcol) >= x) {
cs = x;
if (cs > findbol() && bindtab == altbindtab)
cs--;
}
}
}
/**/
void
viuplineorhistory(void)
{
int ocs = cs;
if (zmult < 0) {
zmult = -zmult;
downlineorhistory();
return;
}
cs = findbol();
while (zmult) {
if (!cs)
break;
cs--;
cs = findbol();
zmult--;
}
if (zmult) {
cs = ocs;
if (virangeflag || in_vared) {
feep();
return;
}
uphistory();
}
vifirstnonblank();
lastcol = cs - findbol();
}
/**/
void
uplineorsearch(void)
{
int ocs = cs;
if (zmult < 0) {
zmult = -zmult;
downlineorsearch();
return;
}
if ((lastcmd & ZLE_LINEMOVE) != ZLE_LINEMOVE)
lastcol = cs - findbol();
cs = findbol();
while (zmult) {
if (!cs)
break;
cs--;
cs = findbol();
zmult--;
}
if (zmult) {
cs = ocs;
if (virangeflag || in_vared) {
feep();
return;
}
historysearchbackward();
} else {
int x = findeol();
if ((cs += lastcol) >= x) {
cs = x;
if (cs && bindtab == altbindtab)
cs--;
}
}
}
/**/
void
downlineorhistory(void)
{
int ocs = cs;
if (zmult < 0) {
zmult = -zmult;
uplineorhistory();
return;
}
if ((lastcmd & ZLE_LINEMOVE) != ZLE_LINEMOVE)
lastcol = cs - findbol();
while (zmult) {
int x = findeol();
if (x == ll)
break;
cs = x + 1;
zmult--;
}
if (zmult) {
cs = ocs;
if (virangeflag || in_vared) {
feep();
return;
}
downhistory();
} else {
int x = findeol();
if ((cs += lastcol) >= x) {
cs = x;
if (cs > findbol() && bindtab == altbindtab)
cs--;
}
}
}
/**/
void
vidownlineorhistory(void)
{
int ocs = cs;
if (zmult < 0) {
zmult = -zmult;
uplineorhistory();
return;
}
while (zmult) {
int x = findeol();
if (x == ll)
break;
cs = x + 1;
zmult--;
}
if (zmult) {
cs = ocs;
if (virangeflag || in_vared) {
feep();
return;
}
downhistory();
}
vifirstnonblank();
lastcol = cs - findbol();
}
/**/
void
downlineorsearch(void)
{
int ocs = cs;
if (zmult < 0) {
zmult = -zmult;
uplineorsearch();
return;
}
if ((lastcmd & ZLE_LINEMOVE) != ZLE_LINEMOVE)
lastcol = cs - findbol();
while (zmult) {
int x = findeol();
if (x == ll)
break;
cs = x + 1;
zmult--;
}
if (zmult) {
cs = ocs;
if (virangeflag || in_vared) {
feep();
return;
}
historysearchforward();
} else {
int x = findeol();
if ((cs += lastcol) >= x) {
cs = x;
if (cs && bindtab == altbindtab)
cs--;
}
}
}
/**/
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)
{
char *s;
if (zmult < 0) {
zmult = -zmult;
uphistory();
return;
}
remember_edits();
histline += zmult;
if (!(s = zle_get_event(histline))) {
if (isset(HISTBEEP))
feep();
histline -= zmult;
return;
}
setline(s);
}
static int histpos;
/**/
void
historysearchbackward(void)
{
int t0, ohistline = histline;
char *s;
remember_edits();
if (lastcmd & ZLE_HISTSEARCH)
t0 = histpos;
else {
for (t0 = 0; t0 < ll && !iblank(line[t0]); t0++);
if (t0 < ll)
t0++;
histpos = t0;
}
for (;;) {
histline--;
if (!(s = zle_get_event(histline))) {
feep();
histline = ohistline;
return;
}
if (metadiffer(s, (char *) line, t0) < 0 &&
metadiffer(s, (char *) line, ll))
break;
}
setline(s);
}
/**/
void
historysearchforward(void)
{
int t0, ohistline = histline;
char *s;
remember_edits();
if (lastcmd & ZLE_HISTSEARCH)
t0 = histpos;
else {
for (t0 = 0; t0 < ll && !iblank(line[t0]); t0++);
if (t0 < ll)
t0++;
histpos = t0;
}
for (;;) {
histline++;
if (!(s = zle_get_event(histline))) {
feep();
histline = ohistline;
return;
}
if (metadiffer(s, (char *) line, t0) < (histline == curhist) &&
metadiffer(s, (char *) line, ll))
break;
}
setline(s);
}
/**/
void
beginningofbufferorhistory(void)
{
if (findbol())
cs = 0;
else
beginningofhistory();
}
/**/
void
beginningofhistory(void)
{
char *s;
remember_edits();
if (!(s = zle_get_event(firsthist()))) {
if (isset(HISTBEEP))
feep();
return;
}
histline = firsthist();
setline(s);
}
/**/
void
endofbufferorhistory(void)
{
if (findeol() != ll)
cs = ll;
else
endofhistory();
}
/**/
void
endofhistory(void)
{
if (histline == curhist) {
if (isset(HISTBEEP))
feep();
} else {
remember_edits();
histline = curhist;
setline(curhistline);
}
}
/**/
void
insertlastword(void)
{
char *s, *t;
int len;
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 = strlen(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) {
zmult = he->nwords - (zmult - 1);
} else {
zmult = 1 - zmult;
}
if (zmult < 1 || zmult > he->nwords) {
feep();
return;
}
s = he->text + he->words[2*zmult-2];
t = he->text + he->words[2*zmult-1];
save = *t;
*t = '\0'; /* ignore trailing whitespace */
lasthist = evhist;
lastpos = cs;
lastinsert = ztrdup(s);
spaceinline(len = ztrlen(s));
while (len--) {
line[cs++] = *s == Meta ? *++s ^ 32 : *s;
s++;
}
*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;
}
/**/
void
pushline(void)
{
if (zmult < 0)
return;
pushnode(bufstack, metafy((char *) line, ll, META_DUP));
while (--zmult)
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)
{
if (zmult < 0)
return;
if (!isfirstln)
zmult++;
pushlineoredit();
}
/**/
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;
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)
/**/
void
doisearch(int dir)
{
char *s, *ibuf = halloc(80), *sbuf = ibuf + FIRST_SEARCH_CHAR;
int sbptr = 0, cmd, top_spot = 0, pos, sibuf = 80;
int nomatch = 0, skip_line = 0, skip_pos = 0;
int odir = dir, *obindtab = bindtab, sens = zmult == 1 ? 3 : 1;
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(histline);
bindtab = mainbindtab;
pos = metalen(s, cs);
for (;;) {
/* Remember the current values in case search fails (doesn't push). */
set_isrch_spot(top_spot, histline, 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)))) {
setline(s);
pos = t - s;
cs = ztrsub(t, s) + (dir == 1? sbptr - (sbuf[0]=='^') : 0);
nomatch = 0;
statusline = ibuf + NORM_PROMPT_POS;
break;
}
histline += dir;
if (!(s = zle_get_event(histline))) {
if (sbptr == (int)isrch_spots[top_spot-1].len
&& (isrch_spots[top_spot-1].flags & ISS_FAILING))
top_spot--;
get_isrch_spot(top_spot, &histline, &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()) < 0 || cmd == z_sendbreak) {
int i;
get_isrch_spot(0, &histline, &pos, &i, &sbptr, &dir, &nomatch);
s = zle_get_event(histline);
setline(s);
cs = i;
break;
}
switch (cmd) {
case z_clearscreen:
clearscreen();
goto ref;
case z_redisplay:
redisplay();
goto ref;
case z_vicmdmode:
bindtab = (bindtab == mainbindtab) ? altbindtab : mainbindtab;
goto ref;
case z_vibackwarddeletechar:
case z_backwarddeletechar:
if (top_spot)
get_isrch_spot(--top_spot, &histline, &pos, &cs, &sbptr,
&dir, &nomatch);
else
feep();
if (nomatch) {
statusline = ibuf;
skip_pos = 1;
}
s = zle_get_event(histline);
if (nomatch || !sbptr || (sbptr == 1 && sbuf[0] == '^')) {
int i = cs;
setline(s);
cs = i;
}
memcpy(ibuf + NORM_PROMPT_POS, (dir == 1) ? "fwd" : "bck", 3);
continue;
case z_acceptandhold:
acceptandhold();
goto brk;
case z_acceptandinfernexthistory:
acceptandinfernexthistory();
goto brk;
case z_acceptlineanddownhistory:
acceptlineanddownhistory();
goto brk;
case z_acceptline:
acceptline();
goto brk;
case z_historyincrementalsearchbackward:
set_isrch_spot(top_spot++, histline, pos, cs, sbptr, dir, nomatch);
if (dir != -1)
dir = -1;
else
skip_pos = 1;
goto rpt;
case z_historyincrementalsearchforward:
set_isrch_spot(top_spot++, histline, pos, cs, sbptr, dir, nomatch);
if (dir != 1)
dir = 1;
else
skip_pos = 1;
goto rpt;
case z_virevrepeatsearch:
set_isrch_spot(top_spot++, histline, pos, cs, sbptr, dir, nomatch);
dir = -odir;
skip_pos = 1;
goto rpt;
case z_virepeatsearch:
set_isrch_spot(top_spot++, histline, 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;
case z_sendstring:
sendstring();
goto ref;
case z_viquotedinsert:
sbuf[sbptr] = '^';
refresh();
case z_quotedinsert:
if ((c = getkey(0)) == EOF) {
feep();
continue;
}
goto ins;
default:
if(cmd == z_selfinsertunmeta) {
c &= 0x7f;
if(c == '\r')
c = '\n';
} else if (cmd == z_magicspace)
c = ' ';
else if (cmd != z_selfinsert) {
ungetkeycmd();
if (cmd == z_sendbreak)
sbptr = 0;
goto brk;
}
ins:
if (sbptr == PATH_MAX) {
feep();
break;
}
set_isrch_spot(top_spot++, histline, 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;
}
}
brk:
if (sbptr) {
zfree(previous_search, previous_search_len);
previous_search = zalloc(sbptr);
memcpy(previous_search, sbuf, previous_search_len = sbptr);
}
statusline = NULL;
bindtab = obindtab;
}
/**/
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;
}
remember_edits();
histline = t0 + 1;
setline(s);
}
/**/
void
vifetchhistory(void)
{
char *s;
if (zmult < 0)
return;
if (histline == curhist) {
if (!gotmult) {
cs = ll;
cs = findbol();
return;
}
}
remember_edits();
if (!gotmult)
zmult = curhist;
if (!(s = qgetevent(zmult)))
feep();
else {
histline = zmult;
setline(s);
}
}
/**/
int
getvisrchstr(void)
{
char *sbuf = halloc(80);
int sptr = 1, cmd, ret = 0, ssbuf = 80;
int *obindtab = bindtab;
if (visrchstr) {
zsfree(visrchstr);
visrchstr = NULL;
}
statusline = sbuf;
sbuf[0] = (visrchsense == -1) ? '?' : '/';
bindtab = mainbindtab;
while (sptr) {
sbuf[sptr] = '_';
statusll = sptr + 1;
refresh();
if ((cmd = getkeycmd()) < 0 || cmd == z_sendbreak) {
ret = 0;
break;
}
if(cmd == z_magicspace) {
c = ' ';
cmd = z_selfinsert;
}
switch(cmd) {
case z_redisplay:
redisplay();
break;
case z_clearscreen:
clearscreen();
break;
case z_acceptline:
case z_vicmdmode:
sbuf[sptr] = 0;
visrchstr = metafy(sbuf + 1, sptr - 1, META_DUP);
ret = 1;
sptr = 0;
break;
case z_backwarddeletechar:
case z_vibackwarddeletechar:
sptr--;
break;
case z_backwardkillword:
case 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--;
break;
case z_sendstring:
sendstring();
break;
case z_viquotedinsert:
sbuf[sptr] = '^';
refresh();
/* fall through */
case z_quotedinsert:
if ((c = getkey(0)) == EOF) {
feep();
break;
}
goto ins;
case z_selfinsertunmeta:
c &= 0x7f;
if(c == '\r')
c = '\n';
case z_selfinsert:
ins:
if(sptr == ssbuf - 1) {
char *newbuf = halloc(ssbuf *= 2);
strcpy(newbuf, sbuf);
statusline = sbuf = newbuf;
}
sbuf[sptr++] = c;
break;
default:
feep();
}
}
statusline = NULL;
bindtab = obindtab;
return ret;
}
/**/
void
vihistorysearchforward(void)
{
visrchsense = 1;
if (getvisrchstr())
virepeatsearch();
}
/**/
void
vihistorysearchbackward(void)
{
visrchsense = -1;
if (getvisrchstr())
virepeatsearch();
}
/**/
void
virepeatsearch(void)
{
int ohistline = histline, t0;
char *s;
if (!visrchstr) {
feep();
return;
}
t0 = strlen(visrchstr);
remember_edits();
for (;;) {
histline += visrchsense;
if (!(s = zle_get_event(histline))) {
feep();
histline = ohistline;
return;
}
if (!metadiffer(s, (char *) line, ll))
continue;
if (*visrchstr == '^') {
if (!strncmp(s, visrchstr + 1, t0 - 1))
break;
} else if (hstrnstr(s, 0, visrchstr, t0, 1, 1))
break;
}
setline(s);
}
/**/
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 ohistline = histline;
char *s;
remember_edits();
for (;;) {
histline--;
if (!(s = zle_get_event(histline))) {
feep();
histline = ohistline;
return;
}
if (metadiffer(s, (char *)line, cs) < 0 &&
metadiffer(s, (char *)line, ll))
break;
}
setline(s);
cs = cpos;
}
/* Extra function added by A.R. Iano-Fletcher. */
/* history-beginning-search-forward */
/**/
void
historybeginningsearchforward(void)
{
int cpos = cs; /* save cursor position */
int ohistline = histline;
char *s;
remember_edits();
for (;;) {
histline++;
if (!(s = zle_get_event(histline))) {
feep();
histline = ohistline;
return;
}
if (metadiffer(s, (char *)line, cs) < (histline == curhist) &&
metadiffer(s, (char *)line, ll))
break;
}
setline(s);
cs = cpos;
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.