summaryrefslogtreecommitdiff
path: root/src/input.c
diff options
context:
space:
mode:
authorsabetts <sabetts>2003-05-27 07:51:03 +0000
committersabetts <sabetts>2003-05-27 07:51:03 +0000
commit6cc80f10f7cb3de33626cf178bda532d741cf388 (patch)
tree87c04a9e6b4ecee8c49dcff7ad9be54b3fceb874 /src/input.c
parent785627843a7aa83ebf451add7b9a97e0b800e390 (diff)
downloadratpoison-6cc80f10f7cb3de33626cf178bda532d741cf388.zip
* src/editor.c (saved_command): new local global
(edit_binding): new typedef (edit_binding): new struct (edit_bindings): new local global (input_line_new): new function (input_line_free): likewise (execute_edit_action): likewise (editor_forward_char): likewise (editor_backward_char): likewise (editor_forward_word): likewise (editor_backward_word): likewise (editor_beginning_of_line): likewise (editor_end_of_line): likewise (editor_delete_char): likewise (editor_backward_delete_char): likewise (editor_kill_word): likewise (editor_backward_kill_word): likewise (editor_kill_line): likewise (editor_backward_kill_line): likewise (editor_history_previous): likewise (editor_history_next): likewise (editor_abort): likewise (editor_no_action): likewise (editor_insert): likewise (editor_enter): likewise (paste_cut_buffer): likewise (paste_primary_selection): likewise (editor_paste_selection): likewise (editor_complete): likewise (editor_forward_char): new prototype (editor_backward_char): likewise (editor_forward_word): likewise (editor_backward_word): likewise (editor_beginning_of_line): likewise (editor_end_of_line): likewise (editor_delete_char): likewise (editor_backward_delete_char): likewise (editor_kill_word): likewise (editor_backward_kill_word): likewise (editor_kill_line): likewise (editor_paste_selection): likewise (editor_abort): likewise (editor_no_action): likewise (editor_enter): likewise (editor_history_previous): likewise (editor_history_next): likewise (editor_complete): likewise (editor_backward_kill_line): likewise * src/sbuf.h (sbuf): add node field. * src/main.c (xrealloc): don't print debugger output (init_defaults): init history_size (main): initialize rp_selection (main): load history (clean_up): save history * src/linkedlist.h (list_first): new macro * src/input.h (free_history): remove prototype (ring_bell): new function * src/input.c: include unistd.h (input_history): remove (input_num_history_entries): likewise (update_input_window): remove prompt, input, and input_len arguments. add line argument. (update_input_window): use line argument. (ring_bell): new function (get_input): take completion_fn argument. prototype and callers updated. (free_history): remove function (get_more_input): take completion_fn argument. prototype and callers updated. use line structure and its functionality. * src/globals.h (MAX_FONT_WIDTH): new define (rp_selection): new extern * src/globals.c (rp_selection): new global * src/completions.h (completions_new): new prototype (completions_free): likewise (completions_assign): likewise (completions_update): likewise (completions_next_completion): likewise * src/completions.c (completions_new): new function (completions_free): likewise (completions_assign): likewise (completions_update): likewise (completions_next_completion): likewise * src/Makefile.am (ratpoison_SOURCES): add editor.c editor.h history.h and history.c * src/data.h (rp_completions): new typedef (rp_input_line): likewise (completion_fn): likewise (rp_defaults): new field, history_size (rp_completions): new struct (rp_input_line): new struct * src/conf.h (MAX_HISTORY_SIZE): new define (HISTORY_FILE): likewise (VISUAL_BELL): likewise (MODIFIER_PREFIX): set to RP_CONTROL_MASK (INPUT_ABORT_MODIFIER): likewise (INPUT_PREV_HISTORY_MODIFIER): likewise (INPUT_NEXT_HISTORY_MODIFIER): likewise (RESIZE_VGROW_MODIFIER): likewise (RESIZE_VSHRINK_MODIFIER): likewise (RESIZE_HGROW_MODIFIER): likewise (RESIZE_HSHRINK_MODIFIER): likewise * src/actions.c (trivial_completions): new function (window_completions): likewise (colon_completions): likewise (exec_completions): likewise (cmd_select): pass window_completions to get_input (cmd_rename): pass trivial_completions to get_input (cmd_colon): pass colon_completions to get_input and get_more_input (cmd_exec): pass exec_completions to get_input (cmd_newwm): pass trivial_completions to get_input (cmd_resize): convert the keysym modifier to something ratpoison understands.
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;
+}