/* -*- mode: C; mode: fold; -*- */ /* Copyright (c) 1992, 1998, 2000, 2002, 2003, 2004, 2005, 2006 John E. Davis * This file is part of JED editor library source. * * You may distribute this file under the terms the GNU General Public * License. See the file COPYING for more information. */ #include "config.h" #include "jed-feat.h" /*{{{ Include Files */ #include #include #include "jdmacros.h" #include #include #include "buffer.h" #include "cmds.h" #include "paste.h" #include "screen.h" #include "window.h" #include "text.h" #include "ledit.h" #include "keymap.h" #include "sysdep.h" #include "misc.h" #include "display.h" #include "file.h" #include "undo.h" #include "ins.h" #include "hooks.h" #include "replace.h" #include "indent.h" #if JED_HAS_TTY_MENUS # include "menu.h" #endif #ifdef IBMPC_SYSTEM # include "doskeys.h" #endif /*}}}*/ #if (SLANG_VERSION < 20003) && defined(SLKEY_F_SLANG) # undef SLKEY_F_SLANG #endif void (*X_Define_Keys_Hook)(SLKeyMap_List_Type *); int (*X_Set_Abort_Char_Hook) (unsigned char); unsigned char Jed_Abort_Char = 7; /* ^G */ typedef struct /*{{{*/ { jmp_buf b; } /*}}}*/ jmp_buf_struct; jmp_buf_struct Jump_Buffer, *Jump_Buffer_Ptr; FVOID_STAR Last_Key_Function; FVOID_STAR Jed_This_Key_Function; int *Repeat_Factor; /* repeats a key sequence if non null */ char *Read_This_Character = NULL; /* alternate keyboard buffer */ char Jed_Key_Buffer[SLANG_MAX_KEYMAP_KEY_SEQ + 1]; char Key_Buffer[SLANG_MAX_KEYMAP_KEY_SEQ + 1]; char *Key_Bufferp = Key_Buffer; static int Last_Key_Buffer_Len; int Jed_Max_Hits = 300; int jed_beep (void) /*{{{*/ { tt_beep (); flush_output (); return 1; } /*}}}*/ static int redraw (void) { jed_redraw_screen (0); return 0; } #if HAS_MOUSE #ifndef IBMPC_SYSTEM static int xterm_mouse_cmd (void) { int b, id; static int last_down = JMOUSE_BUTTON_1; JMouse_Type m; b = my_getkey (); m.x = (unsigned char) my_getkey () - 32; m.y = (unsigned char) my_getkey () - 32; b -= 32; if ((b & 3) == 3) { m.type = JMOUSE_UP; m.button = last_down; m.state = last_down; } else { m.type = JMOUSE_DOWN; if ((b & 3) == 0) m.button = JMOUSE_BUTTON_1; else if (b & 1) m.button = JMOUSE_BUTTON_2; else if (b & 2) m.button = JMOUSE_BUTTON_3; m.state = 0; } last_down = m.button; if (-1 == (id = jed_mouse_add_event (&m))) return -1; ungetkey (&id); jed_mouse_cmd (); return 1; } #endif #endif /* HAS_MOUSE */ SLKeymap_Function_Type Jed_Functions[] = /*{{{*/ { /* Put common cases here to speedup lookup */ {"self_insert_cmd", ins_char_cmd}, {"next_char_cmd", next_char_cmd}, {"next_line_cmd", next_line_cmd}, {"previous_char_cmd", previous_char_cmd}, {"previous_line_cmd", previous_line_cmd}, {"delete_char_cmd", delete_char_cmd}, {"beg_of_line", bol}, {"eol_cmd", eol_cmd}, {"beg_of_buffer", bob}, {"end_of_buffer", eob}, {"newline_and_indent", newline_and_indent}, {"newline", newline_cmd}, {"page_down", pagedown_cmd}, {"page_up", pageup_cmd}, {"backward_delete_char", backward_delete_char_cmd}, {"backward_delete_char_untabify", backward_delete_char_untabify}, {"beep", jed_beep}, {"begin_macro", begin_keyboard_macro}, {"center_line", center_line}, {"copy_region", copy_to_pastebuffer}, #if (defined(__MSDOS__) && !defined(__WIN32__)) || (defined(__QNX__) && defined(__WATCOMC__)) {"coreleft", show_memory}, #endif {"delete_window", delete_window}, {"digit_arg", digit_arg}, /* {"double_line", double_line}, */ {"end_macro", end_keyboard_macro}, {"enlarge_window", enlarge_window}, {"evaluate_cmd", evaluate_cmd}, {"execute_macro", execute_keyboard_macro}, {"exchange",exchange_point_mark}, {"exit_jed", jed_exit_jed_cmd}, {"exit_mini", exit_minibuffer}, {"find_file", find_file}, {"format_paragraph", text_format_paragraph}, {"goto_match", goto_match}, {"indent_line", indent_line}, {"insert_file", insert_file_cmd}, #ifdef HAS_MOUSE {"mouse_cmd", jed_mouse_cmd}, #endif {"kbd_quit", kbd_quit}, {"kill_buffer", kill_buffer}, {"kill_line", kill_line}, {"kill_region", kill_region}, {"macro_query", macro_query}, {"mark_spot", mark_spot}, {"mini_complete", mini_complete}, {"narrow", narrow_to_lines}, {"narrow_paragraph", narrow_paragraph}, {"narrow_to_region", narrow_to_region}, {"one_window", one_window}, {"other_window", other_window}, {"pop_spot", pop_spot}, {"quoted_insert", quoted_insert}, {"redraw", redraw}, /* {"replace", replace}, */ {"save_some_buffers", save_some_buffers}, {"scroll_left", jed_scroll_left_cmd}, {"scroll_right", jed_scroll_right_cmd}, /* {"search_backward", search_backward_cmd}, {"search_forward", search_forward_cmd}, */ {"set_mark_cmd", set_mark_cmd}, {"split_window", split_window}, {"switch_to_buffer", get_buffer}, {"sys_spawn_cmd", sys_spawn_cmd}, {"text_smart_quote", text_smart_quote}, /* {"transpose_lines", transpose_lines}, */ {"trim_whitespace", jed_trim_whitespace}, {"undo", undo}, {"widen", widen}, {"widen_region", widen_region}, {"write_buffer", jed_save_buffer_as_cmd}, {"yank", yank}, #if JED_HAS_TTY_MENUS {"select_menubar", jed_select_menu_bar}, #endif {(char *) NULL, NULL} }; /*}}}*/ SLKeyMap_List_Type *Global_Map; int kbd_quit(void) /*{{{*/ { int sle = SLang_get_error (); SLKeyBoard_Quit = 1; #if JED_HAS_TTY_MENUS if (Jed_Menus_Active) jed_exit_menu_bar (); #endif msg_error("Quit!"); if (Ignore_User_Abort) SLang_set_error (sle); #ifdef UNDO_HAS_REDO set_current_undo (); #endif return(1); } /*}}}*/ void init_keymaps(void) /*{{{*/ { int ch; char simple[2]; simple[1] = 0; if (NULL == (Global_Map = SLang_create_keymap ("global", NULL))) exit_error ("Malloc error creating keymap.", 0); Global_Map->functions = Jed_Functions; /* This breaks under some DEC ALPHA compilers (scary!) */ #ifndef __DECC for (ch = ' '; ch < 256; ch++) { simple[0] = (char) ch; SLkm_define_key (simple, (FVOID_STAR) ins_char_cmd, Global_Map); } #else ch = ' '; while (1) { simple[0] = (char) ch; SLkm_define_key (simple, (FVOID_STAR) ins_char_cmd, Global_Map); ch = ch + 1; if (ch == 256) break; } #endif SLkm_define_key ("^[1", (FVOID_STAR) digit_arg, Global_Map); SLkm_define_key ("^[2", (FVOID_STAR) digit_arg, Global_Map); SLkm_define_key ("^[3", (FVOID_STAR) digit_arg, Global_Map); SLkm_define_key ("^[4", (FVOID_STAR) digit_arg, Global_Map); SLkm_define_key ("^[5", (FVOID_STAR) digit_arg, Global_Map); SLkm_define_key ("^[6", (FVOID_STAR) digit_arg, Global_Map); SLkm_define_key ("^[7", (FVOID_STAR) digit_arg, Global_Map); SLkm_define_key ("^[8", (FVOID_STAR) digit_arg, Global_Map); SLkm_define_key ("^[9", (FVOID_STAR) digit_arg, Global_Map); SLkm_define_key ("^[0", (FVOID_STAR) digit_arg, Global_Map); #ifdef IBMPC_SYSTEM SLkm_define_key (PC_DEL, (FVOID_STAR) delete_char_cmd, Global_Map); SLkm_define_key (PC_DEL1, (FVOID_STAR) delete_char_cmd, Global_Map); SLkm_define_key (PC_NULL, (FVOID_STAR) set_mark_cmd, Global_Map); SLkm_define_key (PC_LT, (FVOID_STAR) previous_char_cmd, Global_Map); SLkm_define_key (PC_LT1, (FVOID_STAR) previous_char_cmd, Global_Map); SLkm_define_key (PC_UP, (FVOID_STAR) previous_line_cmd, Global_Map); SLkm_define_key (PC_UP1, (FVOID_STAR) previous_line_cmd, Global_Map); SLkm_define_key (PC_DN, (FVOID_STAR) next_line_cmd, Global_Map); SLkm_define_key (PC_DN1, (FVOID_STAR) next_line_cmd, Global_Map); SLkm_define_key (PC_RT, (FVOID_STAR) next_char_cmd, Global_Map); SLkm_define_key (PC_RT1, (FVOID_STAR) next_char_cmd, Global_Map); SLkm_define_key (PC_PGUP, (FVOID_STAR) pageup_cmd, Global_Map); SLkm_define_key (PC_PGUP1, (FVOID_STAR) pageup_cmd, Global_Map); SLkm_define_key (PC_PGDN, (FVOID_STAR) pagedown_cmd, Global_Map); SLkm_define_key (PC_PGDN1, (FVOID_STAR) pagedown_cmd, Global_Map); SLkm_define_key (PC_HOME, (FVOID_STAR) bol, Global_Map); SLkm_define_key (PC_HOME1, (FVOID_STAR) bol, Global_Map); SLkm_define_key (PC_END, (FVOID_STAR) eol_cmd, Global_Map); SLkm_define_key (PC_END1, (FVOID_STAR) eol_cmd, Global_Map); /* Now special keypad stuff */ SLkm_define_key (PC_ENTER, (FVOID_STAR) newline_cmd, Global_Map); /* wordperfect type stuff */ SLkm_define_key (PC_F1, (FVOID_STAR) kbd_quit, Global_Map); /* SLkm_define_key (PC_F2, (FVOID_STAR) search_forward_cmd, Global_Map); SLkm_define_key (PC_SHIFT_F2, (FVOID_STAR) search_backward_cmd, Global_Map); */ SLkm_define_key (PC_F4, (FVOID_STAR) indent_line, Global_Map); SLkm_define_key (PC_ALT_F5, (FVOID_STAR) set_mark_cmd, Global_Map); SLkm_define_key (PC_SHIFT_F4, (FVOID_STAR) narrow_paragraph, Global_Map); SLkm_define_key (PC_SHIFT_F6, (FVOID_STAR) center_line, Global_Map); SLkm_define_key (PC_F7, (FVOID_STAR) jed_exit_jed_cmd, Global_Map); #else /* give vtxxx arrow keys */ SLkm_define_key ("^[[D", (FVOID_STAR) previous_char_cmd, Global_Map); SLkm_define_key ("^[OD", (FVOID_STAR) previous_char_cmd, Global_Map); SLkm_define_key ("^[[A", (FVOID_STAR) previous_line_cmd, Global_Map); SLkm_define_key ("^[OA", (FVOID_STAR) previous_line_cmd, Global_Map); SLkm_define_key ("^[[B", (FVOID_STAR) next_line_cmd, Global_Map); SLkm_define_key ("^[OB", (FVOID_STAR) next_line_cmd, Global_Map); SLkm_define_key ("^[[C", (FVOID_STAR) next_char_cmd, Global_Map); SLkm_define_key ("^[OC", (FVOID_STAR) next_char_cmd, Global_Map); SLkm_define_key ("^[[6~", (FVOID_STAR) pagedown_cmd, Global_Map); SLkm_define_key ("^[[5~", (FVOID_STAR) pageup_cmd, Global_Map); SLkm_define_key ("^K^[[C", (FVOID_STAR) jed_scroll_left_cmd, Global_Map); SLkm_define_key ("^K^[[D", (FVOID_STAR) jed_scroll_right_cmd, Global_Map); SLkm_define_key ("^K^[[A", (FVOID_STAR) bob, Global_Map); SLkm_define_key ("^K^[[B", (FVOID_STAR)eob, Global_Map); #if HAS_MOUSE SLkm_define_key ("\033[M", (FVOID_STAR)xterm_mouse_cmd, Global_Map); #endif #ifdef sun SLkm_define_key ("\033[216z", (FVOID_STAR) pageup_cmd, Global_Map); SLkm_define_key ("\033[222z", (FVOID_STAR) pagedown_cmd, Global_Map); SLkm_define_key ("\033[214z", (FVOID_STAR) bol, Global_Map); SLkm_define_key ("\033[220z", (FVOID_STAR) eol_cmd, Global_Map); #endif #endif /* SLkm_define_key ("'", (FVOID_STAR) text_smart_quote, Global_Map); SLkm_define_key ("\"", (FVOID_STAR) text_smart_quote, Global_Map); */ SLkm_define_key ("^_", (FVOID_STAR) undo, Global_Map); SLkm_define_key ("^?", (FVOID_STAR) backward_delete_char_untabify, Global_Map); #ifndef IBMPC_SYSTEM SLkm_define_key ("^H", (FVOID_STAR) backward_delete_char_untabify, Global_Map); #endif SLkm_define_key ("^B", (FVOID_STAR) bol, Global_Map); SLkm_define_key ("^D", (FVOID_STAR) pagedown_cmd, Global_Map); SLkm_define_key ("^E", (FVOID_STAR) eol_cmd, Global_Map); /* SLkm_define_key ("^FB", (FVOID_STAR) search_backward_cmd, Global_Map); SLkm_define_key ("^FF", (FVOID_STAR) search_forward_cmd, Global_Map); */ SLkm_define_key ("^G", (FVOID_STAR) kbd_quit, Global_Map); SLkm_define_key ("^I", (FVOID_STAR) indent_line, Global_Map); SLkm_define_key ("^K(", (FVOID_STAR) begin_keyboard_macro, Global_Map); SLkm_define_key ("^K)", (FVOID_STAR) end_keyboard_macro, Global_Map); SLkm_define_key ("^KD", (FVOID_STAR) evaluate_cmd, Global_Map); SLkm_define_key ("^KE", (FVOID_STAR) jed_exit_jed_cmd, Global_Map); SLkm_define_key ("^KG", (FVOID_STAR) find_file, Global_Map); SLkm_define_key ("^KK", (FVOID_STAR) copy_to_pastebuffer, Global_Map); SLkm_define_key ("^KM", (FVOID_STAR) mark_spot, Global_Map); SLkm_define_key ("^KX", (FVOID_STAR) execute_keyboard_macro, Global_Map); SLkm_define_key ("^K^B", (FVOID_STAR) set_mark_cmd, Global_Map); SLkm_define_key ("^K^I", (FVOID_STAR) insert_file_cmd, Global_Map); /* SLang_define_key1("^K^L", (VOID_STAR) double_line, SLKEY_F_INTRINSIC, Global_Map); */ SLkm_define_key ("^K^M", (FVOID_STAR) pop_spot, Global_Map); SLkm_define_key ("^K^P", (FVOID_STAR) yank, Global_Map); /* SLang_define_key1("^K^R", (VOID_STAR) replace, SLKEY_F_INTRINSIC, Global_Map); */ SLkm_define_key ("^K^V", (FVOID_STAR) kill_region, Global_Map); SLkm_define_key ("^K^W", (FVOID_STAR) jed_save_buffer_as_cmd, Global_Map); SLkm_define_key ("^L", (FVOID_STAR) kill_line, Global_Map); SLkm_define_key ("^M", (FVOID_STAR) newline_and_indent, Global_Map); SLkm_define_key ("^R", (FVOID_STAR) redraw, Global_Map); SLkm_define_key ("^U", (FVOID_STAR) pageup_cmd, Global_Map); SLkm_define_key ("^V", (FVOID_STAR) delete_char_cmd, Global_Map); SLkm_define_key ("^W0", (FVOID_STAR) delete_window, Global_Map); SLkm_define_key ("^W1", (FVOID_STAR) one_window, Global_Map); SLkm_define_key ("^W2", (FVOID_STAR) split_window, Global_Map); SLkm_define_key ("^WO", (FVOID_STAR) other_window, Global_Map); SLkm_define_key ("^XB", (FVOID_STAR) get_buffer, Global_Map); SLkm_define_key ("^XK", (FVOID_STAR) kill_buffer, Global_Map); SLkm_define_key ("^XN", (FVOID_STAR) narrow_to_region, Global_Map); SLkm_define_key ("^XQ", (FVOID_STAR) macro_query, Global_Map); SLkm_define_key ("^XS", (FVOID_STAR) save_some_buffers, Global_Map); SLkm_define_key ("^XW", (FVOID_STAR) widen_region, Global_Map); SLkm_define_key ("^X^", (FVOID_STAR) enlarge_window, Global_Map); /* SLang_define_key1("^X^T", (VOID_STAR) transpose_lines, SLKEY_F_INTRINSIC, Global_Map); */ SLkm_define_key ("^X^[", (FVOID_STAR) evaluate_cmd, Global_Map); SLkm_define_key ("^X^X", (FVOID_STAR) exchange_point_mark, Global_Map); SLkm_define_key ("^Z", (FVOID_STAR) sys_spawn_cmd, Global_Map); SLkm_define_key ("^[<", (FVOID_STAR) bob, Global_Map); SLkm_define_key ("^[>", (FVOID_STAR) eob, Global_Map); SLkm_define_key ("^[N", (FVOID_STAR) narrow_paragraph, Global_Map); SLkm_define_key ("^[Q", (FVOID_STAR) text_format_paragraph, Global_Map); SLkm_define_key ("^[S", (FVOID_STAR) center_line, Global_Map); SLkm_define_key ("^[X", (FVOID_STAR) evaluate_cmd, Global_Map); SLkm_define_key ("^[\\", (FVOID_STAR) jed_trim_whitespace, Global_Map); SLkm_define_key ("^\\", (FVOID_STAR) goto_match, Global_Map); SLkm_define_key ("`", (FVOID_STAR) quoted_insert, Global_Map); if (X_Define_Keys_Hook != NULL) (*X_Define_Keys_Hook)(Global_Map); } /*}}}*/ char Last_Kbd_Command_String[32]; char Current_Kbd_Command_String[32]; void set_current_kbd_command (char *s) /*{{{*/ { strncpy (Current_Kbd_Command_String, s, 31); Current_Kbd_Command_String[31] = 0; } /*}}}*/ static void update_jed_keybuffer (void) /*{{{*/ { Last_Key_Buffer_Len = (int) (Key_Bufferp - Key_Buffer); if (Last_Key_Buffer_Len == 1) { *Jed_Key_Buffer = *Key_Buffer; *(Jed_Key_Buffer + 1) = 0; } else { *Key_Bufferp = 0; strcpy (Jed_Key_Buffer, Key_Buffer); } Key_Bufferp = Key_Buffer; } /*}}}*/ static int do_macro_string (char *str, int repeat) { static int macro_depth; char *rtc_save; int ret = 0; if (macro_depth > 10) { macro_depth = 0; msg_error ("Possible runaway macro aborted."); return -1; } macro_depth++; rtc_save = Read_This_Character; while (repeat > 0) { repeat--; Read_This_Character = str; while ((SLang_get_error () == 0) && (SLKeyBoard_Quit == 0) && (Read_This_Character != NULL)) jed_do_key(); if (Read_This_Character != NULL) { ret = -1; break; } } Read_This_Character = rtc_save; macro_depth--; return ret; } static int key_interpret (SLang_Key_Type *key) /*{{{*/ { char *str; int ret; strcpy (Last_Kbd_Command_String, Current_Kbd_Command_String); Jed_This_Key_Function = key->f.f; switch (key->type) { case SLKEY_F_INTRINSIC: set_current_kbd_command (Jed_Key_Buffer); ret = (key->f.f) (); break; case SLKEY_F_INTERPRET: str = key->f.s; set_current_kbd_command (str); if (*str == ' ') { /* string to insert */ (void) jed_insert_string(str + 1); } else if (*str == '@') { int repeat; if (Repeat_Factor != NULL) { repeat = *Repeat_Factor; Repeat_Factor = NULL; } else repeat = 1; (void) do_macro_string (str + 1, repeat); } else if ((*str == '.') || !SLang_execute_function(str)) SLang_load_string(str); ret = 1; break; #ifdef SLKEY_F_SLANG case SLKEY_F_SLANG: ret = SLexecute_function (key->f.slang_fun); break; #endif default: SLang_verror (SL_NOT_IMPLEMENTED, "Keymap key-type %d is not supported", (int)key->type); return -1; } Last_Key_Function = Jed_This_Key_Function; return(ret); } /*}}}*/ static char *find_function_string (FVOID_STAR f) /*{{{*/ { SLKeymap_Function_Type *fp; if (f == (FVOID_STAR) ins_char_cmd) return "self_insert_cmd"; fp = Jed_Functions; while ((fp != NULL) && (fp->name != NULL)) { if ((FVOID_STAR) fp->f == f) return fp->name; fp++; } return NULL; } /*}}}*/ static char *lookup_key_function_string (SLang_Key_Type *key) { if (key == NULL) return NULL; switch (key->type) { case SLKEY_F_INTRINSIC: return find_function_string (key->f.f); case SLKEY_F_INTERPRET: return key->f.s; #ifdef SLKEY_F_SLANG case SLKEY_F_SLANG: return key->f.slang_fun->name; #endif default: return ""; } } static int do_key (void) /*{{{*/ { SLang_Key_Type *key; int repeat; if (SLang_Key_TimeOut_Flag == 0) { Key_Bufferp = Key_Buffer; *Key_Bufferp = 0; } #if JED_HAS_TTY_MENUS if (Jed_Menus_Active) key = jed_menu_do_key (); else #endif { key = SLang_do_key (CBuf->keymap, jed_getkey); if ((IS_MINIBUFFER == 0) && (key != NULL) && jed_hook_exists ("_jed_before_key_hooks")) { (void) jed_va_run_hooks ("_jed_before_key_hooks", JED_HOOKS_RUN_ALL, 1, lookup_key_function_string (key)); } } update_jed_keybuffer (); if ((key != NULL) && (key->f.f != NULL)) { if (Repeat_Factor == NULL) return key_interpret (key); repeat = *Repeat_Factor; Suspend_Screen_Update = 1; /* some routines may use the repeat factor as a prefix argument */ while (repeat > 0) { repeat--; if (SLKeyBoard_Quit || SLang_get_error () || (Repeat_Factor == NULL)) break; key_interpret (key); } Repeat_Factor = NULL; return(1); } else if (!Executing_Keyboard_Macro && !SLKeyBoard_Quit) { jed_beep (); flush_input (); } if (SLKeyBoard_Quit) kbd_quit(); return(0); } /*}}}*/ int jed_do_key (void) { int ret = do_key (); if (SLang_get_error ()) { jed_abort_keyboard_macro (); Read_This_Character = NULL; Repeat_Factor = NULL; } return ret; } void do_jed(void) /*{{{*/ { char *mode; Buffer *tthis; tthis = CBuf; mode = tthis->mode_string; /* Mark Undo boundary now because this might not be valid later */ mark_undo_boundary (tthis); Repeat_Factor = NULL; Replace_Preserve_Case = 0; if (jed_do_key()) JWindow->trashed = 1; /* internal editing commands may have selected a different buffer * so put it back to the one associated with the window. */ if (CBuf != JWindow->buffer) { char *name; if (buffer_exists(JWindow->buffer)) name = JWindow->buffer->name; else name = "*scratch*"; switch_to_buffer_cmd(name); } #if JED_HAS_TTY_MENUS if ((tthis != CBuf) || (CBuf->mode_string != mode)) jed_notify_menu_buffer_changed (); #endif } /*}}}*/ static int run_switch_active_buffer_hooks (char **bnamep) { char *buffer_name = *bnamep; if (buffer_name == CBuf->name) return 0; if (buffer_name == NULL) (void) jed_va_run_hooks ("_jed_switch_active_buffer_hooks", JED_HOOKS_RUN_ALL, 1, ""); else { (void) jed_va_run_hooks ("_jed_switch_active_buffer_hooks", JED_HOOKS_RUN_ALL, 1, buffer_name); SLang_free_slstring (buffer_name); } /* This should not fail because CBuf->name is an slstring, and if it * does fail, it is not important. */ *bnamep = SLang_create_slstring (CBuf->name); return 0; } void jed (void) /*{{{*/ { /* This routine is called from main. So before actually strting, check one more hook to just to make sure all things are go. */ char *buffer_name; if (SLang_get_error ()) { update (NULL, 1, 1, 0); SLang_restart (1); SLang_set_error (0); jed_sleep (2); } #if JED_HAS_TTY_MENUS jed_notify_menu_buffer_changed (); #endif buffer_name = NULL; (void) run_switch_active_buffer_hooks (&buffer_name); (void) jed_va_run_hooks ("_jed_startup_hooks", JED_HOOKS_RUN_ALL, 0); (void) run_switch_active_buffer_hooks (&buffer_name); Jump_Buffer_Ptr = &Jump_Buffer; if (setjmp(Jump_Buffer.b) != 0) { SLang_restart(1); /* just in case */ } if (CBuf != JWindow->buffer) { switch_to_buffer(JWindow->buffer); window_buffer(CBuf); } #if JED_HAS_TTY_MENUS jed_notify_menu_buffer_changed (); #endif JWindow->trashed = 1; update((Line *) NULL, 0, 0, 1); Read_This_Character = NULL; while(1) { int had_err = 0; Suspend_Screen_Update = 0; do_jed(); if (SLang_get_error ()) { update (NULL, 1, 0, 0); SLang_restart (1); SLang_set_error (0); had_err = 1; } if (!SLKeyBoard_Quit && (CBuf->flags & BUFFER_MODIFIED) && (!Cursor_Motion)) CBuf->hits += 1; SLKeyBoard_Quit = 0; if (CBuf->hits > Jed_Max_Hits) { auto_save_buffer(CBuf); check_buffers(); /* check files on disk to see if they are recent */ } (void) run_switch_active_buffer_hooks (&buffer_name); if (Jed_Menus_Active == 0) (void) jed_va_run_hooks ("_jed_after_key_hooks", JED_HOOKS_RUN_ALL, 0); if ((Last_Key_Function != (FVOID_STAR) ins_char_cmd) || (JWindow->trashed) || (JWindow != JWindow->next) || Suspend_Screen_Update || (Mini_Ghost) || (*Message_Buffer) || (*Error_Buffer)) { update((Line *) NULL, 0, had_err, 1); } } } /*}}}*/ int digit_arg(void) /*{{{*/ { static int repeat; char buf[20]; int key; unsigned int i; i = 0; buf[i++] = (char) SLang_Last_Key_Char; /* After jed_do_key (what called this), Key_Bufferp is reset. However, I want * to keep it for echoing subsequent characters. I restore its previous * value so that echoing will continue. */ Key_Bufferp = Key_Buffer + Last_Key_Buffer_Len; SLang_Key_TimeOut_Flag = 1; while (i < sizeof(buf)-1) { buf[i] = 0; key = jed_getkey(); if ((key < '0') || (key > '9')) break; buf[i++] = (char) key; } buf[i] = 0; repeat = atoi(buf); Repeat_Factor = &repeat; if (Executing_Keyboard_Macro) Macro_Buffer_Ptr--; else { ungetkey (&key); if (Defining_Keyboard_Macro) Macro_Buffer_Ptr--; } if (Key_Bufferp != Key_Buffer) Key_Bufferp--; /* Key_Timeout is still active and is only reset after this call. */ jed_do_key(); return(1); } /*}}}*/ static int which_key (char *f) /*{{{*/ { int num = 0, i; SLang_Key_Type *key, *key_root; FVOID_STAR fp; unsigned char type; unsigned char buf[5]; if (NULL == (fp = (FVOID_STAR) SLang_find_key_function(f, CBuf->keymap))) type = SLKEY_F_INTERPRET; else type = SLKEY_F_INTRINSIC; i = 256; key_root = CBuf->keymap->keymap; while (i--) { key = key_root->next; if ((key == NULL) && (type == key_root->type) && (((type == SLKEY_F_INTERPRET) && (!strcmp((char *) f, key_root->f.s))) || ((type == SLKEY_F_INTRINSIC) && (fp == key_root->f.f)))) { buf[0] = 2; buf[1] = 256 - 1 - i; buf[2] = 0; SLang_push_string(SLang_make_keystring(buf)); num++; } while (key != NULL) { if ((key->type == type) && (((type == SLKEY_F_INTERPRET) && (!strcmp((char *) f, key->f.s))) || ((type == SLKEY_F_INTRINSIC) && (fp == key->f.f)))) { SLang_push_string(SLang_make_keystring(key->str)); num++; } key = key->next; } key_root++; } return(num); } /*}}}*/ static void dump_this_binding (SLang_Key_Type *key) /*{{{*/ { unsigned char ch, *s; char *str, ctrl[2]; char *fun; int n, len; s = key->str; ctrl[0] = '^'; len = *s++ - 1;; while (len-- > 0) { n = 1; ch = *s++; if (ch == 127) { str = "DEL"; n = 3; } else if (ch > ' ') str = (char *) &ch; else if (ch == 27) { str = "ESC"; n = 3; } else if (ch == ' ') { str = "SPACE"; n = 5; } else if (ch == '\t') { str = "TAB"; n = 3; } else { str = ctrl; *(str + 1) = ch + '@'; n = 2; } (void) jed_quick_insert((unsigned char *) str, n); (void) jed_insert_byte (' '); } (void) jed_insert_wchar_n_times('\t', 3); fun = lookup_key_function_string (key); if (fun == NULL) fun = "** Unknown **"; (void) jed_insert_string (fun); (void) jed_insert_newline (); } /*}}}*/ static void dump_bindings(char *map) /*{{{*/ { int i; SLang_Key_Type *next, *key_root; SLKeyMap_List_Type *kml; CHECK_READ_ONLY_VOID if (NULL == (kml = SLang_find_keymap(map))) { msg_error("Keymap undefined."); return; } key_root = kml->keymap; for (i = 0; i < 256; i++) { next = key_root->next; if (next != NULL) { while (next != NULL) { dump_this_binding (next); next = next->next; } } else if (key_root->f.f != NULL) dump_this_binding (key_root); key_root++; } } /*}}}*/ static void use_keymap(char *name) /*{{{*/ { SLKeyMap_List_Type *map; if ((name == NULL) || (*name == 0) || (NULL == (map = SLang_find_keymap(name)))) { msg_error("Unknown keymap."); } else CBuf->keymap = map; } /*}}}*/ static char *what_keymap (void) /*{{{*/ { return CBuf->keymap->name; } /*}}}*/ void jed_set_abort_char (int *c) /*{{{*/ { char str[2]; char ch = (char) *c; #if SLANG_VERSION >= 20000 SLkeymap_Type *km; #else int i; #endif if (X_Set_Abort_Char_Hook != NULL) (void) (*X_Set_Abort_Char_Hook) ((unsigned char) ch); Jed_Abort_Char = (int) ch; str[0] = ch; str[1] = 0; #if SLANG_VERSION < 20000 for (i = 0; i < SLANG_MAX_KEYMAPS; i++) { if (SLKeyMap_List[i].keymap == NULL) continue; SLang_undefine_key(str, &SLKeyMap_List[i]); SLkm_define_key (str, (FVOID_STAR) kbd_quit, &SLKeyMap_List[i]); } #else km = SLKeyMap_List_Root; while (km != NULL) { SLang_undefine_key(str, km); SLkm_define_key (str, (FVOID_STAR) kbd_quit, km); km = km->next; } #endif } /*}}}*/ static SLKeymap_Function_Type *Flist_Context; static int Flist_Context_Len; static char *Slang_Functions[JED_MAX_ADD_COMPLETIONS]; static char **Slang_Flist_Context; int next_function_list(char *buf) /*{{{*/ { register char *name; char **max; /* Convert '-' to '_' */ name = buf; while (*name != 0) { if (*name == '-') *name = '_'; name++; } while (1) { SLKeymap_Function_Type *tthis = Flist_Context; name = tthis->name; if (name == NULL) break; Flist_Context++; if (!Flist_Context_Len || !strncmp(buf, name, Flist_Context_Len)) { strcpy(buf, name); return(1); } } max = Slang_Functions + JED_MAX_ADD_COMPLETIONS; while (Slang_Flist_Context < max) { name = *Slang_Flist_Context; if (name == NULL) return(0); #if 0 name++; /* skip past hash mark */ #endif Slang_Flist_Context++; if (!Flist_Context_Len || !strncmp(buf, name, Flist_Context_Len)) { strcpy(buf, name); return(1); } } return(0); } /*}}}*/ int open_function_list(char *buf) /*{{{*/ { Flist_Context = Jed_Functions; Slang_Flist_Context = Slang_Functions; Flist_Context_Len = strlen(buf); return next_function_list(buf); } /*}}}*/ int add_to_completion(char *name) /*{{{*/ { static char **last = Slang_Functions; if (last == Slang_Functions + JED_MAX_ADD_COMPLETIONS) return 0; if (0 == SLang_is_defined (name)) { jed_verror ("add_completion: %s undefined", name); return -1; } name = SLang_create_slstring (name); if (name == NULL) return -1; *last++ = name; return 0; } /*}}}*/ int is_internal(char *f) /*{{{*/ { if (NULL == SLang_find_key_function(f, CBuf->keymap)) return(0); return 1; } /*}}}*/ static void copy_keymap_cmd (char *dest, char *src) { SLKeyMap_List_Type *ksrc; ksrc = SLang_find_keymap (src); if (ksrc == NULL) { jed_verror ("Keymap \"%s\" does not exist", src); return; } if (NULL != SLang_find_keymap (dest)) { jed_verror ("Keymap \"%s\" already exists", dest); return; } if (NULL == SLang_create_keymap (dest, ksrc)) jed_verror ("Unable to create keymap \"%s\"", dest); } void jed_call_cmd (char *str) { SLKeyMap_List_Type *km; int (*fp)(void); if (*str == ' ') { jed_insert_string (str + 1); return; } if (*str == '@') { (void) do_macro_string (str + 1, 1); return; } km = CBuf->keymap; if (NULL == (fp = (int (*)(void)) (SLang_find_key_function(str, km)))) jed_verror ("Internal function %s does not exist", str); else (void) (*fp)(); } typedef struct { unsigned char *key; unsigned int len; unsigned int num_read; } Getkey_Callback_Data_Type; static Getkey_Callback_Data_Type Getkey_Callback_Data; static int get_key_function_callback (void) { unsigned int i = Getkey_Callback_Data.num_read; if (i == Getkey_Callback_Data.len) return SLANG_GETKEY_ERROR; Getkey_Callback_Data.num_read += 1; return (int) Getkey_Callback_Data.key[i]; } static int push_key_binding (unsigned char *keystr) { SLang_Key_Type *key; char *fun; int type; #ifdef SLKEY_F_SLANG SLang_Name_Type *ref = NULL; #endif SLang_Key_TimeOut_Flag = 0; if (keystr == NULL) { Key_Bufferp = Key_Buffer; key = SLang_do_key (CBuf->keymap, jed_getkey); update_jed_keybuffer (); if (key == NULL) flush_input (); if (SLKeyBoard_Quit || (SLang_get_error () == USER_BREAK)) { SLang_set_error (0); SLKeyBoard_Quit = 0; } } else { Getkey_Callback_Data.len = (unsigned int) keystr[0]; Getkey_Callback_Data.key = keystr + 1; Getkey_Callback_Data.num_read = 0; key = SLang_do_key (CBuf->keymap, get_key_function_callback); } fun = NULL; type = -1; if (key != NULL) switch (key->type) { case SLKEY_F_INTRINSIC: type = 1; fun = find_function_string (key->f.f); break; case SLKEY_F_INTERPRET: fun = key->f.s; type = 0; if (fun[0] == '@') type = 2; else if (fun[0] == ' ') type = 3; break; #ifdef SLKEY_F_SLANG case SLKEY_F_SLANG: type = 4; ref = key->f.slang_fun; break; #endif } if (-1 == SLang_push_integer (type)) return -1; #ifdef SLKEY_F_SLANG if (type == 4) type = SLang_push_function (ref); else #endif type = SLang_push_string (fun); return type; } /*}}}*/ static void get_key_binding (void) { unsigned char *s = NULL; if (SLang_Num_Function_Args == 1) { char *str; if (-1 == SLang_pop_slstring (&str)) return; s = (unsigned char *) SLang_process_keystring (str); SLang_free_slstring (str); if (s == NULL) return; } (void) push_key_binding (s); } /* This is weird, Ultrix cc will not compile if set_key comes before unset_key */ static void unset_key (char *key) /*{{{*/ { if (*key) SLang_undefine_key(key, Global_Map); } /*}}}*/ static void unset_key_in_keymap(char *key, char *map) /*{{{*/ { SLKeyMap_List_Type *kmap; if (NULL == (kmap = SLang_find_keymap(map))) { jed_verror ("Unknown keymap: %s", map); return; } if (*key) SLang_undefine_key(key, kmap); } /*}}}*/ static void set_key_in_keymap_1 (SLKeyMap_List_Type *kmap) { char *key, *func; if (-1 == SLang_pop_slstring (&key)) return; #ifdef SLKEY_F_SLANG if (SLang_peek_at_stack () == SLANG_REF_TYPE) { SLang_Name_Type *nt = SLang_pop_function (); if (nt == NULL) { SLang_free_slstring (key); return; } if (-1 == SLkm_define_slkey (key, nt, kmap)) { SLang_free_function (nt); SLang_free_slstring (key); return; } SLang_free_slstring (key); return; } #endif if (-1 == SLang_pop_slstring (&func)) { SLang_free_slstring (key); return; } if (*key) (void) SLang_define_key(key, func, kmap); SLang_free_slstring (func); SLang_free_slstring (key); } static void set_key_in_keymap (void) { char *keymap; SLKeyMap_List_Type *kmap; if (-1 == SLang_pop_slstring (&keymap)) return; if (NULL == (kmap = SLang_find_keymap(keymap))) jed_verror ("Unknown keymap: %s", keymap); else set_key_in_keymap_1 (kmap); SLang_free_slstring (keymap); } /*}}}*/ static void set_key (void) { set_key_in_keymap_1 (Global_Map); } /*}}}*/ static int keymap_p(char *name) /*{{{*/ { return ! (NULL == SLang_find_keymap(name)); } /*}}}*/ static void make_keymap_cmd (char *km) { copy_keymap_cmd (km, "global"); } static void get_keymaps (void) { int j, n; char **keymaps; SLang_Array_Type *at; #if SLANG_VERSION < 20000 unsigned int i; #else SLkeymap_Type *km; #endif n = 0; #if SLANG_VERSION < 20000 for (i = 0; i < SLANG_MAX_KEYMAPS; i++) { if (SLKeyMap_List[i].keymap == NULL) continue; n++; } #else km = SLKeyMap_List_Root; while (km != NULL) { n++; km = km->next; } #endif if (NULL == (at = SLang_create_array (SLANG_STRING_TYPE, 0, NULL, &n, 1))) return; keymaps = (char **)at->data; j = 0; #if SLANG_VERSION < 20000 for (i = 0; i < SLANG_MAX_KEYMAPS; i++) { if (SLKeyMap_List[i].keymap == NULL) continue; if (j == n) break; /* keymap list changing?? */ if (NULL == (keymaps[j] = SLang_create_slstring (SLKeyMap_List[i].name))) { SLang_free_array (at); return; } j++; } #else km = SLKeyMap_List_Root; while (km != NULL) { if (j == n) break; /* keymap list changing?? */ if (NULL == (keymaps[j] = SLang_create_slstring (km->name))) { SLang_free_array (at); return; } km = km->next; j++; } #endif SLang_push_array (at, 1); } static void getkey_wchar_intrin (void) { int ch; SLwchar_Type wch; if (-1 == jed_getkey_wchar (&wch)) { ch = (int) wch; (void) SLang_push_integer (-ch); return; } (void) SLclass_push_long_obj (SLANG_LONG_TYPE, (long)wch); } static void ungetkey_wchar_intrin (long *chp) { if (*chp < 0) { int ch = -(int)*chp; ungetkey (&ch); return; } jed_ungetkey_wchar ((SLwchar_Type)*chp); } static SLang_Intrin_Fun_Type Keymap_Intrinsics [] = { MAKE_INTRINSIC_0("setkey", set_key, VOID_TYPE), MAKE_INTRINSIC_0("definekey", set_key_in_keymap, VOID_TYPE), MAKE_INTRINSIC_S("unsetkey", unset_key, VOID_TYPE), MAKE_INTRINSIC("what_keymap", what_keymap, STRING_TYPE, 0), MAKE_INTRINSIC_0("get_keymaps", get_keymaps, VOID_TYPE), MAKE_INTRINSIC_S("keymap_p", keymap_p, INT_TYPE), MAKE_INTRINSIC("get_key_binding", get_key_binding, VOID_TYPE, 0), MAKE_INTRINSIC_S("dump_bindings", dump_bindings, VOID_TYPE), MAKE_INTRINSIC_SS("undefinekey", unset_key_in_keymap, VOID_TYPE), MAKE_INTRINSIC_S("which_key", which_key, INT_TYPE), MAKE_INTRINSIC_S("make_keymap", make_keymap_cmd, VOID_TYPE), MAKE_INTRINSIC_SS("copy_keymap", copy_keymap_cmd, VOID_TYPE), MAKE_INTRINSIC_S("use_keymap", use_keymap, VOID_TYPE), MAKE_INTRINSIC("_getkey", jed_getkey, INT_TYPE, 0), MAKE_INTRINSIC_I("_ungetkey", ungetkey, VOID_TYPE), MAKE_INTRINSIC_0("getkey", getkey_wchar_intrin, VOID_TYPE), MAKE_INTRINSIC_1("ungetkey", ungetkey_wchar_intrin, VOID_TYPE, SLANG_LONG_TYPE), SLANG_END_INTRIN_FUN_TABLE }; static char *Key_Buffer_Ptr = Jed_Key_Buffer; static char *Last_Kbd_Command_Str_Ptr = Last_Kbd_Command_String; static char *Current_Kbd_Command_Str_Ptr = Current_Kbd_Command_String; static SLang_Intrin_Var_Type Keymap_Variables [] = { MAKE_VARIABLE("LASTKEY", &Key_Buffer_Ptr, STRING_TYPE, 1), MAKE_VARIABLE("LAST_KBD_COMMAND", &Last_Kbd_Command_Str_Ptr, STRING_TYPE, 1), MAKE_VARIABLE("CURRENT_KBD_COMMAND", &Current_Kbd_Command_Str_Ptr, STRING_TYPE, 1), MAKE_VARIABLE(NULL, NULL, 0, 0) }; int jed_init_keymap_intrinsics (void) { if ((-1 == SLadd_intrin_fun_table (Keymap_Intrinsics, NULL)) || (-1 == SLadd_intrin_var_table (Keymap_Variables, NULL))) return -1; return 0; }