summaryrefslogtreecommitdiff
path: root/src/input.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/input.c')
-rw-r--r--src/input.c259
1 files changed, 118 insertions, 141 deletions
diff --git a/src/input.c b/src/input.c
index 80d17dc..31c901d 100644
--- a/src/input.c
+++ b/src/input.c
@@ -22,16 +22,13 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <X11/Xutil.h>
#include "ratpoison.h"
-/* Variables to keep track of input history. */
-static char *input_history[INPUT_MAX_HISTORY];
-static int input_num_history_entries = 0;
-
/* Convert an X11 modifier mask to the rp modifier mask equivalent, as
best it can (the X server may not have a hyper key defined, for
instance). */
@@ -275,73 +272,119 @@ read_key (KeySym *keysym, unsigned int *modifiers, char *keysym_name, int len)
}
static void
-update_input_window (rp_screen *s, char *prompt, char *input, int input_len)
+update_input_window (rp_screen *s, rp_input_line *line)
{
- int prompt_width = XTextWidth (defaults.font, prompt, strlen (prompt));
- int input_width = XTextWidth (defaults.font, input, input_len);
- int width, height;
-
- width = defaults.bar_x_padding * 2 + prompt_width + input_width;
+ int prompt_width = XTextWidth (defaults.font, line->prompt, strlen (line->prompt));
+ int input_width = XTextWidth (defaults.font, line->buffer, line->length);
+ int total_width;
+ GC lgc;
+ XGCValues gv;
+ int height;
+
+ total_width = defaults.bar_x_padding * 2 + prompt_width + input_width + MAX_FONT_WIDTH (defaults.font);
height = (FONT_HEIGHT (defaults.font) + defaults.bar_y_padding * 2);
- if (width < defaults.input_window_size + prompt_width)
+ if (total_width < defaults.input_window_size + prompt_width)
{
- width = defaults.input_window_size + prompt_width;
+ total_width = defaults.input_window_size + prompt_width;
}
XMoveResizeWindow (dpy, s->input_window,
- bar_x (s, width), bar_y (s, height), width, height);
+ bar_x (s, total_width), bar_y (s, height), total_width,
+ (FONT_HEIGHT (defaults.font) + defaults.bar_y_padding * 2));
XClearWindow (dpy, s->input_window);
XSync (dpy, False);
XDrawString (dpy, s->input_window, s->normal_gc,
- defaults.bar_x_padding,
- defaults.bar_y_padding + defaults.font->max_bounds.ascent, prompt,
- strlen (prompt));
-
+ defaults.bar_x_padding,
+ defaults.bar_y_padding + defaults.font->max_bounds.ascent,
+ line->prompt,
+ strlen (line->prompt));
+
XDrawString (dpy, s->input_window, s->normal_gc,
- defaults.bar_x_padding + prompt_width,
- defaults.bar_y_padding + defaults.font->max_bounds.ascent, input,
- input_len);
-
- /* Draw a cheap-o cursor. */
- XDrawLine (dpy, s->input_window, s->normal_gc,
- defaults.bar_x_padding + prompt_width + input_width + 2,
- defaults.bar_y_padding + 1,
- defaults.bar_x_padding + prompt_width + input_width + 2,
- defaults.bar_y_padding + FONT_HEIGHT (defaults.font) - 1);
+ defaults.bar_x_padding + prompt_width,
+ defaults.bar_y_padding + defaults.font->max_bounds.ascent,
+ line->buffer,
+ line->length);
+
+ gv.function = GXxor;
+ gv.foreground = s->fg_color ^ s->bg_color;
+ lgc = XCreateGC (dpy, s->input_window, GCFunction | GCForeground, &gv);
+
+ /* Draw a cheap-o cursor - MkII */
+ XFillRectangle (dpy, s->input_window, lgc,
+ defaults.bar_x_padding + prompt_width + XTextWidth (defaults.font, line->buffer, line->position),
+ defaults.bar_y_padding,
+ XTextWidth (defaults.font, &line->buffer[line->position], 1),
+ FONT_HEIGHT (defaults.font));
+
+ XFlush (dpy);
+ XFreeGC (dpy, lgc);
+}
+
+void
+ring_bell ()
+{
+#ifdef VISUAL_BELL
+ GC lgc;
+ XGCValues gv;
+ XWindowAttributes attr;
+ rp_screen *s = current_screen ();
+
+ XGetWindowAttributes (dpy, s->input_window, &attr);
+
+ gv.function = GXxor;
+ gv.foreground = s->fg_color ^ s->bg_color;
+ lgc = XCreateGC (dpy, s->input_window, GCFunction | GCForeground, &gv);
+
+ XFillRectangle (dpy, s->input_window, lgc, 0, 0, attr.width, attr.height);
+ XFlush (dpy);
+
+#ifdef HAVE_USLEEP
+ usleep (15000);
+#else
+ {
+ struct timeval tv;
+
+ tv.tv_sec = 0;
+ tv.tv_usec = 15000;
+ select (0, NULL, NULL, NULL, &tv);
+ }
+#endif
+ XFillRectangle (dpy, s->input_window, lgc, 0, 0, attr.width, attr.height);
+ XFlush (dpy);
+ XFreeGC (dpy, lgc);
+#else
+ XBell (dpy, 0);
+#endif
}
char *
-get_input (char *prompt)
+get_input (char *prompt, completion_fn fn)
{
- return get_more_input (prompt, "");
+ return get_more_input (prompt, "", fn);
}
char *
-get_more_input (char *prompt, char *preinput)
+get_more_input (char *prompt, char *preinput,
+ completion_fn compl_fn)
{
/* Emacs 21 uses a 513 byte string to store the keysym name. */
char keysym_buf[513];
int keysym_bufsize = sizeof (keysym_buf);
int nbytes;
rp_screen *s = current_screen ();
- int cur_len = 0; /* Current length of the string. */
- int allocated_len=100; /* The amount of memory we allocated for str */
KeySym ch;
unsigned int modifier;
int revert;
Window fwin;
- char *str;
- int history_index = input_num_history_entries;
-
- /* Allocate some memory to start with. */
- str = (char *) xmalloc ( allocated_len );
+ rp_input_line *line;
+ char *final_input;
+ edit_status status;
- /* load in the preinput */
- strcpy (str, preinput);
- cur_len = strlen (preinput);
+ /* Create our line structure */
+ line = input_line_new (prompt, preinput, compl_fn);
/* We don't want to draw overtop of the program bar. */
hide_bar (s);
@@ -351,117 +394,51 @@ get_more_input (char *prompt, char *preinput)
XClearWindow (dpy, s->input_window);
XSync (dpy, False);
- update_input_window (s, prompt, str, cur_len);
+ update_input_window (s, line);
XGetInputFocus (dpy, &fwin, &revert);
XSetInputFocus (dpy, s->input_window, RevertToPointerRoot, CurrentTime);
/* XSync (dpy, False); */
-
- nbytes = read_key (&ch, &modifier, keysym_buf, keysym_bufsize);
- while (ch != XK_Return)
+ for (;;)
{
- PRINT_DEBUG (("key %ld\n", ch));
- if (ch == XK_BackSpace)
- {
- if (cur_len > 0) cur_len--;
- update_input_window(s, prompt, str, cur_len);
- }
- else if (ch == INPUT_PREV_HISTORY_KEY
- && modifier == INPUT_PREV_HISTORY_MODIFIER)
- {
- /* Cycle through the history. */
- if (input_num_history_entries > 0)
- {
- history_index--;
- if (history_index < 0)
- {
- history_index = input_num_history_entries - 1;
- }
-
- free (str);
- str = xstrdup (input_history[history_index]);
- allocated_len = strlen (str) + 1;
- cur_len = allocated_len - 1;
-
- update_input_window (s, prompt, str, cur_len);
- }
- }
- else if (ch == INPUT_NEXT_HISTORY_KEY
- && modifier == INPUT_NEXT_HISTORY_MODIFIER)
- {
- /* Cycle through the history. */
- if (input_num_history_entries > 0)
- {
- history_index++;
- if (history_index >= input_num_history_entries)
- {
- history_index = 0;
- }
-
- free (str);
- str = xstrdup (input_history[history_index]);
- allocated_len = strlen (str) + 1;
- cur_len = allocated_len - 1;
-
- update_input_window (s, prompt, str, cur_len);
- }
- }
- else if (ch == INPUT_ABORT_KEY && modifier == INPUT_ABORT_MODIFIER)
- {
- /* User aborted. */
- free (str);
- XSetInputFocus (dpy, fwin, RevertToPointerRoot, CurrentTime);
- XUnmapWindow (dpy, s->input_window);
- return NULL;
- }
- else
- {
- if (cur_len + nbytes > allocated_len - 1)
- {
- allocated_len += nbytes + 100;
- str = xrealloc ( str, allocated_len );
- }
-
- strncpy (&str[cur_len], keysym_buf, nbytes);
-/* str[cur_len] = ch; */
- cur_len+=nbytes;
-
- update_input_window(s, prompt, str, cur_len);
- }
-
nbytes = read_key (&ch, &modifier, keysym_buf, keysym_bufsize);
+ modifier = x11_mask_to_rp_mask (modifier);
+ PRINT_DEBUG (("ch = %ld, modifier = %d, keysym_buf = %s, keysym_bufsize = %d\n",
+ ch, modifier, keysym_buf, keysym_bufsize));
+ status = execute_edit_action (line, ch, modifier, keysym_buf);
+
+ if (status == EDIT_DELETE || status == EDIT_INSERT || status == EDIT_MOVE
+ || status == EDIT_COMPLETE)
+ {
+ /* If the text changed (and we didn't just complete
+ something) then set the virgin bit. */
+ if (status != EDIT_COMPLETE)
+ line->compl->virgin = 1;
+ /* In all cases, we need to redisplay the input string. */
+ update_input_window (s, line);
+ }
+ else if (status == EDIT_NO_OP)
+ {
+ ring_bell ();
+ }
+ else if (status == EDIT_ABORT)
+ {
+ final_input = NULL;
+ break;
+ }
+ else if (status == EDIT_DONE)
+ {
+ final_input = xstrdup (line->buffer);
+ break;
+ }
}
- str[cur_len] = 0;
-
- /* Push the history entries down. */
- if (input_num_history_entries >= INPUT_MAX_HISTORY)
- {
- int i;
- free (input_history[0]);
- for (i=0; i<INPUT_MAX_HISTORY-1; i++)
- {
- input_history[i] = input_history[i+1];
- }
-
- input_num_history_entries--;
- }
-
- /* Store the string in the history. */
- input_history[input_num_history_entries] = xstrdup (str);
- input_num_history_entries++;
+ /* Clean up our line structure */
+ input_line_free (line);
XSetInputFocus (dpy, fwin, RevertToPointerRoot, CurrentTime);
XUnmapWindow (dpy, s->input_window);
- return str;
-}
-void
-free_history ()
-{
- int i;
-
- for (i=0; i<input_num_history_entries; i++)
- free (input_history[i]);
-}
+ return final_input;
+}