summaryrefslogtreecommitdiff
path: root/src/input.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/input.c')
-rw-r--r--src/input.c128
1 files changed, 103 insertions, 25 deletions
diff --git a/src/input.c b/src/input.c
index c9624a6..f0f9982 100644
--- a/src/input.c
+++ b/src/input.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008
+/* Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
@@ -46,10 +46,14 @@ struct inpline
char buf[101]; /* text buffer */
int len; /* length of the editible string */
int pos; /* cursor position in editable string */
+ struct inpline *next, *prev;
};
-static struct inpline inphist; /* XXX: should be a dynamic list */
-
+/* 'inphist' is used to store the current input when scrolling through history.
+ * inpline->prev == history-prev
+ * inpline->next == history-next
+ */
+static struct inpline inphist;
struct inpdata
{
@@ -61,6 +65,7 @@ struct inpdata
void (*inpfinfunc) __P((char *buf, int len, char *priv));
char *priv; /* private data for finfunc */
int privdata; /* private data space */
+ char *search; /* the search string */
};
static struct LayFuncs InpLf =
@@ -71,7 +76,8 @@ static struct LayFuncs InpLf =
DefClearLine,
DefRewrite,
DefResize,
- DefRestore
+ DefRestore,
+ 0
};
/*
@@ -143,10 +149,12 @@ int data;
}
if (InitOverlayPage(sizeof(*inpdata), &InpLf, 1))
return;
+ flayer->l_mode = 1;
inpdata = (struct inpdata *)flayer->l_data;
inpdata->inpmaxlen = len;
inpdata->inpfinfunc = finfunc;
inpdata->inp.pos = inpdata->inp.len = 0;
+ inpdata->inp.prev = inphist.prev;
inpdata->inpmode = mode;
inpdata->privdata = data;
if (!priv)
@@ -154,6 +162,7 @@ int data;
inpdata->priv = priv;
inpdata->inpstringlen = 0;
inpdata->inpstring = NULL;
+ inpdata->search = NULL;
if (istr)
inp_setprompt(istr, (char *)NULL);
}
@@ -204,10 +213,13 @@ int *plen;
char ch;
struct inpdata *inpdata;
struct display *inpdisplay;
+ int prev, next, search = 0;
inpdata = (struct inpdata *)flayer->l_data;
inpdisplay = display;
+#define RESET_SEARCH do { if (inpdata->search) Free(inpdata->search); } while (0)
+
LGotoPos(flayer, inpdata->inpstringlen + (inpdata->inpmode & INP_NOECHO ? 0 : inpdata->inp.pos), INPUTLINE);
if (ppbuf == 0)
{
@@ -265,14 +277,16 @@ int *plen;
LGotoPos(flayer, x, INPUTLINE);
}
}
+ RESET_SEARCH;
}
else if ((ch == '\b' || ch == 0177) && inpdata->inp.pos > 0)
{
erase_chars(inpdata, p-1, p, x, 1);
+ RESET_SEARCH;
}
else if (ch == '\025') /* CTRL-U */
{
- x = inpdata->inpstringlen;
+ x = inpdata->inpstringlen;
if (inpdata->inp.len && !(inpdata->inpmode & INP_NOECHO))
{
LClearArea(flayer, x, INPUTLINE, x + inpdata->inp.len - 1, INPUTLINE, 0, 0);
@@ -282,7 +296,7 @@ int *plen;
}
else if (ch == '\013') /* CTRL-K */
{
- x = inpdata->inpstringlen + inpdata->inp.pos;
+ x = inpdata->inpstringlen + inpdata->inp.pos;
if (inpdata->inp.len > inpdata->inp.pos && !(inpdata->inpmode & INP_NOECHO))
{
LClearArea(flayer, x, INPUTLINE, x + inpdata->inp.len - inpdata->inp.pos - 1, INPUTLINE, 0, 0);
@@ -298,10 +312,12 @@ int *plen;
while (p > inpdata->inp.buf && *(p - 1) != ' ')
p--;
erase_chars(inpdata, p, oldp, x, 1);
+ RESET_SEARCH;
}
else if (ch == '\004' && inpdata->inp.pos < inpdata->inp.len) /* CTRL-D */
{
erase_chars(inpdata, p, p+1, x, 0);
+ RESET_SEARCH;
}
else if (ch == '\001' || (unsigned char)ch == 0201) /* CTRL-A */
{
@@ -323,22 +339,57 @@ int *plen;
LGotoPos(flayer, ++x, INPUTLINE);
inpdata->inp.pos++;
}
- else if (ch == '\020' || (unsigned char)ch == 0220) /* CTRL-P */
- {
+ else if ((prev = ((ch == '\020' || (unsigned char)ch == 0220) && /* CTRL-P */
+ inpdata->inp.prev)) ||
+ (next = ((ch == '\016' || (unsigned char)ch == 0216) && /* CTRL-N */
+ inpdata->inp.next)) ||
+ (search = ((ch == '\022' || (unsigned char)ch == 0222) && inpdata->inp.prev)))
+ {
struct mchar mc;
+ struct inpline *sel;
+ int pos = -1;
+
mc = mchar_so;
+
+ if (prev)
+ sel = inpdata->inp.prev;
+ else if (next)
+ sel = inpdata->inp.next;
+ else
+ {
+ /* search */
+ inpdata->inp.buf[inpdata->inp.len] = 0; /* Remove the ctrl-r from the end */
+ if (!inpdata->search)
+ inpdata->search = SaveStr(inpdata->inp.buf);
+ for (sel = inpdata->inp.prev; sel; sel = sel->prev)
+ {
+ char *f;
+ if ((f = strstr(sel->buf, inpdata->search)))
+ {
+ pos = f - sel->buf;
+ break;
+ }
+ }
+ if (!sel)
+ continue; /* Did not find a match. Process the next input. */
+ }
+
if (inpdata->inp.len && !(inpdata->inpmode & INP_NOECHO))
LClearArea(flayer, inpdata->inpstringlen, INPUTLINE, inpdata->inpstringlen + inpdata->inp.len - 1, INPUTLINE, 0, 0);
- inpdata->inp = inphist; /* structure copy */
+ if ((prev || search) && !inpdata->inp.next)
+ inphist = inpdata->inp;
+ memcpy(&inpdata->inp, sel, sizeof(struct inpline));
+ if (pos != -1)
+ inpdata->inp.pos = pos;
if (inpdata->inp.len > inpdata->inpmaxlen)
inpdata->inp.len = inpdata->inpmaxlen;
if (inpdata->inp.pos > inpdata->inp.len)
inpdata->inp.pos = inpdata->inp.len;
- x = inpdata->inpstringlen;
+ x = inpdata->inpstringlen;
p = inpdata->inp.buf;
-
+
if (!(inpdata->inpmode & INP_NOECHO))
{
while (p < inpdata->inp.buf+inpdata->inp.len)
@@ -347,7 +398,7 @@ int *plen;
LPutChar(flayer, &mc, x++, INPUTLINE);
}
}
- x = inpdata->inpstringlen + inpdata->inp.pos;
+ x = inpdata->inpstringlen + inpdata->inp.pos;
LGotoPos(flayer, x, INPUTLINE);
}
@@ -359,9 +410,36 @@ int *plen;
inpdata->inp.buf[inpdata->inp.len] = 0;
if (inpdata->inp.len && !(inpdata->inpmode & (INP_NOECHO | INP_RAW)))
- inphist = inpdata->inp; /* structure copy */
-
- flayer->l_data = 0; /* so inpdata does not get freed */
+ {
+ struct inpline *store;
+
+ /* Look for a duplicate first */
+ for (store = inphist.prev; store; store = store->prev)
+ {
+ if (strcmp(store->buf, inpdata->inp.buf) == 0)
+ {
+ if (store->next)
+ store->next->prev = store->prev;
+ if (store->prev)
+ store->prev->next = store->next;
+ store->pos = inpdata->inp.pos;
+ break;
+ }
+ }
+
+ if (!store)
+ {
+ store = malloc(sizeof(struct inpline));
+ memcpy(store, &inpdata->inp, sizeof(struct inpline));
+ }
+ store->next = &inphist;
+ store->prev = inphist.prev;
+ if (inphist.prev)
+ inphist.prev->next = store;
+ inphist.prev = store;
+ }
+
+ flayer->l_data = 0; /* so inpdata does not get freed */
InpAbort(); /* redisplays... */
*ppbuf = pbuf;
*plen = len;
@@ -370,9 +448,17 @@ int *plen;
(*inpdata->inpfinfunc)(inpdata->inp.buf, inpdata->inp.len, inpdata->priv);
else
(*inpdata->inpfinfunc)(pbuf - 1, 0, inpdata->priv);
- free((char *)inpdata);
+ if (inpdata->search)
+ free(inpdata->search);
+ free(inpdata);
return;
}
+ else
+ {
+ /* The user was searching, and then pressed some non-control input. So reset
+ * the search string. */
+ RESET_SEARCH;
+ }
}
if (!(inpdata->inpmode & INP_RAW))
{
@@ -396,7 +482,7 @@ int y, xs, xe, isblank;
{
int q, r, s, l, v;
struct inpdata *inpdata;
-
+
inpdata = (struct inpdata *)flayer->l_data;
if (y != INPUTLINE)
{
@@ -440,11 +526,3 @@ int y, xs, xe, isblank;
}
}
-int
-InInput()
-{
- if (flayer && flayer->l_layfn == &InpLf)
- return 1;
- return 0;
-}
-