--- screen-4.0.2.orig/input.c +++ screen-4.0.2/input.c @@ -41,10 +41,12 @@ char buf[101]; /* text buffer */ int len; /* length of the editible string */ int pos; /* cursor position in editable string */ + struct inpline *prev, *next; }; -static struct inpline inphist; /* XXX: should be a dynamic list */ - +/* History list: inphist is the head of the list, inpcur is a pointer to + the current position when walking the list. */ +static struct inpline *inphist, *inpcur; struct inpdata { @@ -275,14 +277,32 @@ LGotoPos(flayer, ++x, INPUTLINE); inpdata->inp.pos++; } - else if (ch == '\020' || (unsigned char)ch == 0220) /* CTRL-P */ - { + else if ((ch == '\020' || (unsigned char)ch == 0220 + || ch == '\016' || (unsigned char)ch == 0216) + && inphist) /* CTRL-P or CTRL-N */ + { struct mchar mc; mc = mchar_so; 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 (ch == '\020' || (unsigned char)ch == 0220) /* CTRL-P */ + { + if (!inpcur) + inpcur = inphist; + else if (inpcur->next) + inpcur = inpcur->next; + } + else if (ch == '\016' || (unsigned char)ch == 0216) /* CTRL-N */ + { + if (!inpcur) + for (inpcur = inphist; inpcur && inpcur->next; + inpcur = inpcur->next); + else if (inpcur->prev) + inpcur = inpcur->prev; + } + memcpy(&inpdata->inp, inpcur, sizeof(struct inpline)); + if (inpdata->inp.len > inpdata->inpmaxlen) inpdata->inp.len = inpdata->inpmaxlen; if (inpdata->inp.pos > inpdata->inp.len) @@ -309,9 +329,45 @@ if (ch != '\004' && ch != '\n' && ch != '\r') inpdata->inp.len = 0; inpdata->inp.buf[inpdata->inp.len] = 0; + inpcur = NULL; if (inpdata->inp.len && inpdata->inpmode == 0) - inphist = inpdata->inp; /* structure copy */ + { + struct inpline *inpelt, *inpdupe = NULL; + for (inpelt = inphist; inpelt && !inpdupe; inpelt = inpelt->next) + if (strcmp(inpdata->inp.buf, inpelt->buf) == 0) + inpdupe = inpelt; + if (!inpdupe) + { + if ((inpelt = malloc(sizeof(struct inpline))) == NULL) + { + Msg(0, "No memory for history element, not saving"); + } + else + { + memcpy(inpelt, &inpdata->inp, sizeof(struct inpline)); + if (inphist) + inphist->prev = inpelt; + inpelt->next = inphist; + inpelt->prev = NULL; + inphist = inpelt; + } + } + else + { + /* Move duplicate element to the front. */ + if (inpdupe->prev) + { + inpdupe->prev->next = inpdupe->next; + if (inpdupe->next) + inpdupe->next->prev = inpdupe->prev; + inpdupe->next = inphist; + inpdupe->prev = NULL; + inphist->prev = inpdupe; + inphist = inpdupe; + } + } + } flayer->l_data = 0; InpAbort(); /* redisplays... */