summaryrefslogtreecommitdiffstats
path: root/enter.c
diff options
context:
space:
mode:
authorThomas Roessler <roessler@does-not-exist.org>1998-06-08 09:16:03 +0000
committerThomas Roessler <roessler@does-not-exist.org>1998-06-08 09:16:03 +0000
commit1a5381e07e97fe482c2b3a7c75f99938f0b105d4 (patch)
treeb4fa4088bbbf5fc9217ee6f87ab60034175e6899 /enter.c
Initial revision
Diffstat (limited to 'enter.c')
-rw-r--r--enter.c525
1 files changed, 525 insertions, 0 deletions
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 <me@cs.hmc.edu>
+ *
+ * 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 <termios.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+
+/* 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 */
+}