From 1a5381e07e97fe482c2b3a7c75f99938f0b105d4 Mon Sep 17 00:00:00 2001 From: Thomas Roessler Date: Mon, 8 Jun 1998 09:16:03 +0000 Subject: Initial revision --- enter.c | 525 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 525 insertions(+) create mode 100644 enter.c (limited to 'enter.c') diff --git a/enter.c b/enter.c new file mode 100644 index 00000000..a7981ccc --- /dev/null +++ b/enter.c @@ -0,0 +1,525 @@ +/* + * Copyright (C) 1996-8 Michael R. Elkins + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "mutt.h" +#include "mutt_menu.h" +#include "mutt_curses.h" +#include "keymap.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +/* macro to print control chars in reverse-video */ +#define ADDCH(x) addch (IsPrint (x) ? x : (ColorDefs[MT_COLOR_MARKERS] | (x + '@'))) + +/* global vars used for the string-history routines */ +static char **Hist = NULL; +static short HistCur = 0; +static short HistLast = 0; + +void mutt_init_history (void) +{ + int i; + static int OldSize = 0; + + if (Hist) + { + for (i = 0 ; i < OldSize ; i ++) + safe_free ((void **) &Hist[i]); + safe_free ((void **) &Hist); + } + + if (HistSize) + Hist = safe_calloc (HistSize, sizeof (char *)); + HistCur = 0; + HistLast = 0; + OldSize = HistSize; +} + +static void sh_add (char *s) +{ + int prev; + + if (!HistSize) + return; /* disabled */ + + if (*s) + { + prev = HistLast - 1; + if (prev < 0) prev = HistSize - 1; + if (!Hist[prev] || strcmp (Hist[prev], s) != 0) + { + safe_free ((void **) &Hist[HistLast]); + Hist[HistLast++] = safe_strdup (s); + if (HistLast > HistSize - 1) + HistLast = 0; + } + } + HistCur = HistLast; /* reset to the last entry */ +} + +static char *sh_next (void) +{ + int next; + + if (!HistSize) + return (""); /* disabled */ + + next = HistCur + 1; + if (next > HistLast - 1) + next = 0; + if (Hist[next]) + HistCur = next; + return (Hist[HistCur] ? Hist[HistCur] : ""); +} + +static char *sh_prev (void) +{ + int prev; + + if (!HistSize) + return (""); /* disabled */ + + prev = HistCur - 1; + if (prev < 0) + { + prev = HistLast - 1; + if (prev < 0) + { + prev = HistSize - 1; + while (prev > 0 && Hist[prev] == NULL) + prev--; + } + } + if (Hist[prev]) + HistCur = prev; + return (Hist[HistCur] ? Hist[HistCur] : ""); +} + +/* redraw flags for mutt_enter_string() */ +enum +{ + M_REDRAW_INIT = 1, /* recalculate lengths */ + M_REDRAW_LINE, /* redraw entire line */ + M_REDRAW_EOL, /* redraw from current position to eol */ + M_REDRAW_PREV_EOL /* redraw from curpos-1 to eol */ +}; + +/* Returns: + * 1 need to redraw the screen and call me again + * 0 if input was given + * -1 if abort. + * + */ +int mutt_enter_string (unsigned char *buf, size_t buflen, int y, int x, + int flags) +{ + int curpos = 0; /* the location of the cursor */ + int lastchar = 0; /* offset of the last char in the string */ + int begin = 0; /* first character displayed on the line */ + int ch; /* last typed character */ + int width = COLS - x - 1; /* width of field */ + int redraw = M_REDRAW_INIT; /* when/what to redraw */ + int pass = (flags == M_PASS); + int first = 1; + int j; + char tempbuf[_POSIX_PATH_MAX] = ""; + + FOREVER + { + if (redraw) + { + if (redraw == M_REDRAW_INIT) + { + /* full redraw */ + lastchar = curpos = strlen ((char *) buf); + begin = lastchar - width; + } + if (begin < 0) + begin = 0; + switch (redraw) + { + case M_REDRAW_PREV_EOL: + j = curpos - 1; + break; + case M_REDRAW_EOL: + j = curpos; + break; + default: + j = begin; + } + move (y, x + j - begin); + for (; j < lastchar && j < begin + width; j++) + ADDCH (buf[j]); + clrtoeol (); + if (redraw != M_REDRAW_INIT) + move (y, x + curpos - begin); + redraw = 0; + } + mutt_refresh (); + + /* first look to see if a keypress is an editor operation. km_dokey() + * returns 0 if there is no entry in the keymap, so restore the last + * keypress and continue normally. + */ + if ((ch = km_dokey (MENU_EDITOR)) == -1) + { + buf[curpos] = 0; + return (-1); + } + + if (ch != 0) + { + first = 0; /* make sure not to clear the buffer */ + switch (ch) + { + case OP_EDITOR_HISTORY_UP: + if (!pass) + { + strfcpy ((char *) buf, sh_prev (), buflen); + redraw = M_REDRAW_INIT; + } + break; + case OP_EDITOR_HISTORY_DOWN: + if (!pass) + { + strfcpy ((char *) buf, sh_next (), buflen); + redraw = M_REDRAW_INIT; + } + break; + case OP_EDITOR_BACKSPACE: + if (curpos == 0) + { + BEEP (); + break; + } + for (j = curpos ; j < lastchar ; j++) + buf[j - 1] = buf[j]; + curpos--; + lastchar--; + if (!pass) + { + if (curpos > begin) + { + if (lastchar == curpos) + { + move (y, x + curpos - begin); + delch (); + } + else + redraw = M_REDRAW_EOL; + } + else + { + begin -= width / 2; + redraw = M_REDRAW_LINE; + } + } + break; + case OP_EDITOR_BOL: + /* reposition the cursor at the begininning of the line */ + curpos = 0; + if (!pass) + { + if (begin) + { + /* the first char is not displayed, so readjust */ + begin = 0; + redraw = M_REDRAW_LINE; + } + else + move (y, x); + } + break; + case OP_EDITOR_EOL: + curpos = lastchar; + if (!pass) + { + if (lastchar < begin + width) + move (y, x + lastchar - begin); + else + { + begin = lastchar - width / 2; + redraw = M_REDRAW_LINE; + } + } + break; + case OP_EDITOR_KILL_LINE: + lastchar = curpos = 0; + if (!pass) + { + begin = 0; + redraw = M_REDRAW_LINE; + } + break; + case OP_EDITOR_KILL_EOL: + lastchar = curpos; + if (!pass) + clrtoeol (); + break; + case OP_EDITOR_BACKWARD_CHAR: + if (curpos == 0) + { + BEEP (); + } + else + { + curpos--; + if (!pass) + { + if (curpos < begin) + { + begin -= width / 2; + redraw = M_REDRAW_LINE; + } + else + move (y, x + curpos - begin); + } + } + break; + case OP_EDITOR_FORWARD_CHAR: + if (curpos == lastchar) + { + BEEP (); + } + else + { + curpos++; + if (!pass) + { + if (curpos >= begin + width) + { + begin = curpos - width / 2; + redraw = M_REDRAW_LINE; + } + else + move (y, x + curpos - begin); + } + } + break; + case OP_EDITOR_DELETE_CHAR: + if (curpos != lastchar) + { + for (j = curpos; j < lastchar; j++) + buf[j] = buf[j + 1]; + lastchar--; + if (!pass) + redraw = M_REDRAW_EOL; + } + else + BEEP (); + break; + case OP_EDITOR_KILL_WORD: + /* delete to begining of word */ + if (curpos != 0) + { + j = curpos; + while (j > 0 && ISSPACE (buf[j - 1])) + j--; + if (j > 0) + { + if (isalnum (buf[j - 1])) + { + for (j--; j > 0 && isalnum (buf[j - 1]); j--) + ; + } + else + j--; + } + ch = j; /* save current position */ + while (curpos < lastchar) + buf[j++] = buf[curpos++]; + lastchar = j; + curpos = ch; /* restore current position */ + /* update screen */ + if (!pass) + { + if (curpos < begin) + { + begin = curpos - width / 2; + redraw = M_REDRAW_LINE; + } + else + redraw = M_REDRAW_EOL; + } + } + break; + case OP_EDITOR_BUFFY_CYCLE: + if (flags & M_EFILE) + { + first = 1; /* clear input if user types a real key later */ + buf[curpos] = 0; + mutt_buffy ((char *) buf); + redraw = M_REDRAW_INIT; + break; + } + else if (!(flags & M_FILE)) + goto self_insert; + /* fall through to completion routine (M_FILE) */ + + case OP_EDITOR_COMPLETE: + if (flags & M_CMD) + { + buf[curpos] = 0; + for (j = curpos - 1; j >= 0 && buf[j] != ' '; j--); + if (strcmp (tempbuf, (char *) buf) == 0) + { + mutt_select_file ((char *) buf + j + 1, buflen - j - 1, 0); + set_option (OPTNEEDREDRAW); + return (1); + } + if (mutt_complete ((char *) buf + j + 1) == 0) + strfcpy (tempbuf, (char *) buf + j + 1, sizeof (tempbuf)); + else + BEEP (); + redraw = M_REDRAW_INIT; + } + else if (flags & M_ALIAS) + { + /* invoke the alias-menu to get more addresses */ + buf[curpos] = 0; + if (curpos) + { + for (j = curpos - 1 ; j >= 0 && buf[j] != ' ' && buf[j] != ',' ; j--); + if (mutt_alias_complete ((char *) buf + j + 1, buflen - j - 1)) + { + redraw = M_REDRAW_INIT; + continue; + } + } + else + mutt_alias_menu ((char *) buf, buflen, Aliases); + return (1); + } + else if (flags & (M_FILE | M_EFILE)) + { + buf[curpos] = 0; + + /* see if the path has changed from the last time */ + if (strcmp (tempbuf, (char *) buf) == 0) + { + mutt_select_file ((char *) buf, buflen, 0); + set_option (OPTNEEDREDRAW); + if (buf[0]) + { + mutt_pretty_mailbox ((char *) buf); + sh_add ((char *) buf); + return (0); + } + return (-1); + } + + if (mutt_complete ((char *) buf) == 0) + strfcpy (tempbuf, (char *) buf, sizeof (tempbuf)); + else + BEEP (); /* let the user know that nothing matched */ + redraw = M_REDRAW_INIT; + } + else + goto self_insert; + break; + + case OP_EDITOR_COMPLETE_QUERY: + if (flags & M_ALIAS) + { + /* invoke the query-menu to get more addresses */ + buf[curpos] = 0; + if (curpos) + { + for (j = curpos - 1 ; j >= 0 && buf[j] != ' ' && buf[j] != ',' ; j--); + mutt_query_complete ((char *) buf + j + 1, buflen - j - 1); + } + else + mutt_query_menu ((char *) buf, buflen); + return (1); + } + else + goto self_insert; + + case OP_EDITOR_QUOTE_CHAR: + ADDCH (LastKey); + LastKey = mutt_getch (); + move (y, x + curpos - begin); + goto self_insert; + + default: + BEEP (); + } + } + else + { + +self_insert: + + /* use the raw keypress */ + ch = LastKey; + + if (first && (flags & M_CLEAR)) + { + first = 0; + if (IsPrint (ch)) + { + mutt_ungetch (ch); + buf[0] = 0; + redraw = M_REDRAW_INIT; + continue; + } + } + + if (CI_is_return (ch)) + { + buf[lastchar] = 0; + if (!pass) + sh_add ((char *) buf); + return (0); + } + else if ((ch < ' ' || IsPrint (ch)) && (lastchar + 1 < buflen)) + { + for (j = lastchar; j > curpos; j--) + buf[j] = buf[j - 1]; + buf[curpos++] = ch; + lastchar++; + + if (!pass) + { + if (curpos >= begin + width) + { + begin = curpos - width / 2; + redraw = M_REDRAW_LINE; + } + else if (curpos == lastchar) + ADDCH (ch); + else + redraw = M_REDRAW_PREV_EOL; + } + } + else + { + mutt_flushinp (); + BEEP (); + } + } + } + /* not reached */ +} -- cgit v1.2.3