diff options
Diffstat (limited to 'src/input.c')
-rw-r--r-- | src/input.c | 128 |
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; -} - |