From 6cc80f10f7cb3de33626cf178bda532d741cf388 Mon Sep 17 00:00:00 2001 From: sabetts Date: Tue, 27 May 2003 07:51:03 +0000 Subject: * 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. --- src/input.c | 259 +++++++++++++++++++++++++++--------------------------------- 1 file changed, 118 insertions(+), 141 deletions(-) (limited to 'src/input.c') 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 #include #include +#include #include #include #include #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; iinput_window); - return str; -} -void -free_history () -{ - int i; - - for (i=0; i