* usermap.c: Allow user-defined keyboard bindings for mcedit.

* usermap.h: Likewise.
	* Makefile.am: Likewise.
	* editcmd.c: Define new editor commands which had been coded
	inline before.
	This change also affects some other files.
	* edit-widget.h: Invented a new type edit_key_map_type instead of
	using long for.
	* editkeys.c: Using that type.
This commit is contained in:
Roland Illig 2005-07-20 11:56:30 +00:00
parent c9ab4e7566
commit 073907ec5f
13 changed files with 803 additions and 60 deletions

View File

@ -1,3 +1,18 @@
2005-07-20 Vitja Makarov <vitja.makarov@gmail.com>
* usermap.c: Allow user-defined keyboard bindings for mcedit.
* usermap.h: Likewise.
* Makefile.am: Likewise.
* editcmd.c: Define new editor commands which had been coded
inline before.
This change also affects some other files.
2005-07-20 Roland Illig <roland.illig@gmx.de>
* edit-widget.h: Invented a new type edit_key_map_type instead of
using long for.
* editkeys.c: Using that type.
2005-07-18 Roland Illig <roland.illig@gmx.de>
* editkeys.c: When typing literal characters after C-q, allow

View File

@ -9,6 +9,6 @@ endif
libedit_a_SOURCES = \
bookmark.c edit.c editcmd.c editwidget.c editdraw.c editkeys.c \
editmenu.c editoptions.c editcmddef.h edit.h edit-widget.h \
editlock.c editlock.h syntax.c wordproc.c
editlock.c editlock.h syntax.c usermap.c wordproc.c
EXTRA_DIST = ChangeLog

View File

@ -25,6 +25,11 @@ struct syntax_rule {
unsigned char border;
};
typedef struct edit_key_map_type {
long key;
long command;
} edit_key_map_type;
struct WEdit {
Widget widget;
@ -102,6 +107,14 @@ struct WEdit {
int macro_i; /* index to macro[], -1 if not recording a macro */
int macro_depth; /* depth of the macro recursion */
struct macro macro[MAX_MACRO_LENGTH];
/* user map stuff */
const edit_key_map_type *user_map;
const edit_key_map_type *ext_map;
int extmod;
char *labels[10];
};
#endif

View File

@ -38,11 +38,13 @@
#include "editlock.h"
#include "edit-widget.h"
#include "editcmddef.h"
#include "usermap.h"
#include "../src/cmd.h" /* view_other_cmd() */
#include "../src/user.h" /* user_menu_cmd() */
#include "../src/wtools.h" /* query_dialog() */
/*
what editor are we going to emulate? one of EDIT_KEY_EMULATION_NORMAL
or EDIT_KEY_EMULATION_EMACS
@ -558,6 +560,8 @@ edit_init (WEdit *edit, int lines, int columns, const char *filename,
edit_move_to_line (edit, line - 1);
}
edit_load_user_map(edit);
return edit;
}
@ -2112,7 +2116,7 @@ void edit_execute_key_command (WEdit *edit, int command, int char_for_insertion)
edit->macro[edit->macro_i++].ch = char_for_insertion;
}
/* record the beginning of a set of editing actions initiated by a key press */
if (command != CK_Undo)
if (command != CK_Undo && command != CK_Ext_Mode)
edit_push_key_press (edit);
edit_execute_cmd (edit, command, char_for_insertion);
@ -2549,6 +2553,21 @@ edit_execute_cmd (WEdit *edit, int command, int char_for_insertion)
case CK_Shell:
view_other_cmd ();
break;
case CK_Select_Codepage:
edit_select_codepage_cmd (edit);
break;
case CK_Insert_Literal:
edit_insert_literal_cmd (edit);
break;
case CK_Execute_Macro:
edit_execute_macro_cmd (edit);
break;
case CK_Begin_End_Macro:
edit_begin_end_macro_cmd (edit);
break;
case CK_Ext_Mode:
edit->extmod = 1;
break;
default:
break;
}

View File

@ -35,6 +35,7 @@
#define EDIT_KEY_EMULATION_NORMAL 0
#define EDIT_KEY_EMULATION_EMACS 1
#define EDIT_KEY_EMULATION_USER 2
#define REDRAW_LINE (1 << 0)
#define REDRAW_LINE_ABOVE (1 << 1)
@ -198,6 +199,11 @@ int edit_copy_to_X_buf_cmd (WEdit * edit);
int edit_cut_to_X_buf_cmd (WEdit * edit);
void edit_paste_from_X_buf_cmd (WEdit * edit);
void edit_select_codepage_cmd (WEdit *edit);
void edit_insert_literal_cmd (WEdit *edit);
void edit_execute_macro_cmd (WEdit *edit);
void edit_begin_end_macro_cmd(WEdit *edit);
void edit_paste_from_history (WEdit *edit);
void edit_set_filename (WEdit *edit, const char *name);

View File

@ -53,6 +53,7 @@
#include "../src/dialog.h" /* do_refresh() */
#include "../src/wtools.h" /* message() */
#include "../src/charsets.h"
#include "../src/selcodepage.h"
#define edit_get_load_file(f,h) input_expand_dialog (h, _(" Enter file name: "), f)
#define edit_get_save_file(f,h) input_expand_dialog (h, _(" Enter file name: "), f)
@ -2894,3 +2895,50 @@ edit_complete_word_cmd (WEdit *edit)
/* restore search parameters */
edit_set_search_parameters (old_rs, old_rb, old_rr, old_rw, old_rc);
}
void
edit_select_codepage_cmd (WEdit *edit)
{
#ifdef HAVE_CHARSET
do_select_codepage ();
edit->force = REDRAW_COMPLETELY;
edit_refresh_cmd (edit);
#endif
}
void
edit_insert_literal_cmd (WEdit *edit)
{
int char_for_insertion =
edit_raw_key_query (_(" Insert Literal "),
_(" Press any key: "), 0);
edit_execute_key_command (edit, -1,
ascii_alpha_to_cntrl (char_for_insertion));
}
void
edit_execute_macro_cmd (WEdit *edit)
{
int command =
CK_Macro (edit_raw_key_query
(_(" Execute Macro "), _(" Press macro hotkey: "),
1));
if (command == CK_Macro (0))
command = CK_Insert_Char;
edit_execute_key_command (edit, command, -1);
}
void
edit_begin_end_macro_cmd(WEdit *edit)
{
int command;
/* edit is a pointer to the widget */
if (edit) {
command =
edit->macro_i <
0 ? CK_Begin_Record_Macro : CK_End_Record_Macro;
edit_execute_key_command (edit, command, -1);
}
}

View File

@ -148,6 +148,16 @@
#define CK_Shell 801
/* C-x or similar */
#define CK_Ext_Mode 820
#define CK_Select_Codepage 850
#define CK_Insert_Literal 851
#define CK_Execute_Macro 852
#define CK_Begin_End_Macro 853
/*
Process a block through a shell command: CK_Pipe_Block(i) executes shell_cmd[i].
shell_cmd[i] must process the file ~/cooledit.block and output ~/cooledit.block

View File

@ -22,6 +22,7 @@
#include <config.h>
#include <assert.h>
#include <stdio.h>
#include <stdarg.h>
#include <sys/types.h>
@ -47,7 +48,7 @@
* Ordinary translations. Note that the keys listed first take priority
* when the key is assigned to more than one command.
*/
static const long cooledit_key_map[] = {
static const edit_key_map_type cooledit_key_map[] = {
ALT ('b'), CK_Match_Bracket,
ALT ('m'), CK_Mail,
XCTRL ('f'), CK_Save_Block,
@ -59,7 +60,7 @@ static const long cooledit_key_map[] = {
0, 0
};
static long const emacs_key_map[] = {
static const edit_key_map_type emacs_key_map[] = {
ALT ('$'), CK_Pipe_Block (1), /* spell check */
ALT ('b'), CK_Word_Left,
ALT ('f'), CK_Word_Right,
@ -80,7 +81,7 @@ static long const emacs_key_map[] = {
0, 0
};
static long const common_key_map[] = {
static const edit_key_map_type common_key_map[] = {
'\n', CK_Enter,
'\t', CK_Tab,
@ -112,6 +113,10 @@ static long const common_key_map[] = {
XCTRL ('l'), CK_Refresh,
XCTRL ('o'), CK_Shell,
XCTRL ('u'), CK_Undo,
XCTRL ('t'), CK_Select_Codepage,
XCTRL ('q'), CK_Insert_Literal,
XCTRL ('a'), CK_Execute_Macro,
XCTRL ('r'), CK_Begin_End_Macro,
KEY_F (1), CK_Help,
KEY_F (2), CK_Save,
@ -181,7 +186,8 @@ edit_translate_key (WEdit *edit, long x_key, int *cmd, int *ch)
int command = CK_Insert_Char;
int char_for_insertion = -1;
int i = 0;
static const long *key_map;
int extmod = 0;
const edit_key_map_type *key_map = NULL;
switch (edit_key_emulation) {
case EDIT_KEY_EMULATION_NORMAL:
@ -215,46 +221,25 @@ edit_translate_key (WEdit *edit, long x_key, int *cmd, int *ch)
goto fin;
}
break;
}
#ifdef HAVE_CHARSET
if (x_key == XCTRL ('t')) {
do_select_codepage ();
edit->force = REDRAW_COMPLETELY;
command = CK_Refresh;
goto fin;
}
#endif
if (x_key == XCTRL ('q')) {
char_for_insertion = ascii_alpha_to_cntrl (
edit_raw_key_query (_(" Insert Literal "),
_(" Press any key: "), 0));
goto fin;
}
if (x_key == XCTRL ('a')
&& edit_key_emulation != EDIT_KEY_EMULATION_EMACS) {
command =
CK_Macro (edit_raw_key_query
(_(" Execute Macro "), _(" Press macro hotkey: "),
1));
if (command == CK_Macro (0))
command = CK_Insert_Char;
goto fin;
}
/* edit is a pointer to the widget */
if (edit)
if (x_key == XCTRL ('r')) {
command =
edit->macro_i <
0 ? CK_Begin_Record_Macro : CK_End_Record_Macro;
goto fin;
case EDIT_KEY_EMULATION_USER:
if (edit->user_map != NULL) {
if (edit->extmod && edit->ext_map != NULL) {
key_map = edit->ext_map;
extmod = 1;
} else {
key_map = edit->user_map;
}
edit->extmod = 0;
} else {
key_map = edit->user_map = cooledit_key_map;
}
break;
}
assert (key_map != NULL);
/* an ordinary insertable character */
if (x_key < 256) {
if (x_key < 256 && !extmod) {
int c = convert_from_input_c (x_key);
if (is_printable (c)) {
@ -264,21 +249,19 @@ edit_translate_key (WEdit *edit, long x_key, int *cmd, int *ch)
}
/* Commands specific to the key emulation */
i = 0;
while (key_map[i] && (key_map[i] != x_key))
i += 2;
if (key_map[i]) {
command = key_map[i + 1];
for (i = 0; key_map[i].key != 0 && key_map[i].key != x_key; i++)
continue;
if (key_map[i].key != 0) {
command = key_map[i].command;
goto fin;
}
/* Commands common for the key emulations */
key_map = common_key_map;
i = 0;
while (key_map[i] && (key_map[i] != x_key))
i += 2;
if (key_map[i]) {
command = key_map[i + 1];
for (i = 0; key_map[i].key != 0 && key_map[i].key != x_key; i++)
continue;
if (key_map[i].key != 0) {
command = key_map[i].command;
goto fin;
}

View File

@ -443,6 +443,7 @@ edit_init_menu (void)
struct Menu **EditMenuBar = g_new(struct Menu *, N_menus);
switch (edit_key_emulation) {
default:
case EDIT_KEY_EMULATION_NORMAL:
edit_init_menu_normal (EditMenuBar);
break;

View File

@ -38,6 +38,7 @@
#include "../src/global.h"
#include "edit.h"
#include "usermap.h"
#include "../src/dialog.h" /* B_CANCEL */
#include "../src/wtools.h" /* QuickDialog */
@ -49,7 +50,7 @@
#endif
static const char *key_emu_str[] =
{N_("Intuitive"), N_("Emacs"), NULL};
{N_("Intuitive"), N_("Emacs"), N_("User-defined"), NULL};
static const char *wrap_str[] =
{N_("None"), N_("Dynamic paragraphing"), N_("Type writer wrap"), NULL};
@ -128,7 +129,7 @@ edit_options_dialog (void)
N_("Wrap mode"), 0, 0,
0, 0, NULL},
/* 15 */
{quick_radio, 5, OPT_DLG_W, OPT_DLG_H - 13, OPT_DLG_H, "", 2, 0, 0,
{quick_radio, 5, OPT_DLG_W, OPT_DLG_H - 13, OPT_DLG_H, "", 3, 0, 0,
const_cast(char **, key_emu_str), "keyemu"},
/* 16 */
{quick_label, 4, OPT_DLG_W, OPT_DLG_H - 14, OPT_DLG_H,
@ -221,4 +222,6 @@ edit_options_dialog (void)
/* Load or unload syntax rules if the option has changed */
if (option_syntax_highlighting != old_syntax_hl)
edit_load_syntax (wedit, 0, 0);
/* Load usermap if it's needed */
edit_load_user_map (wedit);
}

View File

@ -232,6 +232,7 @@ edit_file (const char *_file, int line)
static void edit_my_define (Dlg_head * h, int idx, const char *text,
void (*fn) (WEdit *), WEdit * edit)
{
text = edit->labels[idx - 1]? edit->labels[idx - 1] : text;
/* function-cast ok */
buttonbar_set_label_data (h, idx, text, (buttonbarfn) fn, edit);
}
@ -351,15 +352,17 @@ edit_callback (Widget *w, widget_msg_t msg, int parm)
{
int cmd, ch;
/* first check alt-f, alt-e, alt-s, etc for drop menus */
if (edit_drop_hotkey_menu (e, parm))
/* The user may override the access-keys for the menu bar. */
if (edit_translate_key (e, parm, &cmd, &ch)) {
edit_execute_key_command (e, cmd, ch);
edit_update_screen (e);
return MSG_HANDLED;
if (!edit_translate_key (e, parm, &cmd, &ch))
} else if (edit_drop_hotkey_menu (e, parm)) {
return MSG_HANDLED;
} else {
return MSG_NOT_HANDLED;
edit_execute_key_command (e, cmd, ch);
edit_update_screen (e);
}
}
return MSG_HANDLED;
case WIDGET_CURSOR:
widget_move (&e->widget, e->curs_row + EDIT_TEXT_VERTICAL_OFFSET,

631
edit/usermap.c Normal file
View File

@ -0,0 +1,631 @@
/* cooledit.bindings file parser
Authors: 2005 Vitja Makarov
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., 59 Temple Place, Suite 330, Boston, MA
02111-1307, USA.
*/
#include <config.h>
#include <ctype.h>
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "../src/global.h"
#include "edit.h"
#include "edit-widget.h"
#include "editcmddef.h" /* list of commands */
#include "usermap.h"
#include "../src/key.h" /* KEY_M_* */
#include "../src/tty.h" /* keys */
#include "../src/wtools.h"
#include "../src/widget.h" /* buttonbar_redraw() */
typedef struct NameMap {
const char *name;
int val;
} name_map_t;
typedef struct Config {
time_t mtime; /* mtime at the moment we read config file */
GArray *keymap;
GArray *ext_keymap;
gchar *labels[10];
} config_t;
typedef struct Command {
const char *name;
int (*handler) (config_t *cfg, int argc, char *argv[]);
} command_t;
static char error_msg[200] = "Nobody see this";
static const name_map_t key_names[] = {
{"backspace", KEY_BACKSPACE},
{"end", KEY_END},
{"up", KEY_UP},
{"down", KEY_DOWN},
{"left", KEY_LEFT},
{"right", KEY_RIGHT},
{"home", KEY_HOME},
{"a1", KEY_A1},
{"c1", KEY_C1},
{"npage", KEY_NPAGE},
{"ppage", KEY_PPAGE},
{"ic", KEY_IC},
{"enter", KEY_ENTER},
{"dc", KEY_DC},
{"scancel", KEY_SCANCEL},
{"btab", KEY_BTAB},
{"f11", KEY_F(11)},
{"f12", KEY_F(12)},
{"f13", KEY_F(13)},
{"f14", KEY_F(14)},
{"f15", KEY_F(15)},
{"f16", KEY_F(16)},
{"f17", KEY_F(17)},
{"f18", KEY_F(18)},
{"f19", KEY_F(19)},
{"f20", KEY_F(20)},
{"tab", '\t'},
{"return", '\n'},
{NULL, 0}
};
static const name_map_t command_names[] = {
{"No-Command", CK_Ignore_Key},
{"Ignore-Key", CK_Ignore_Key},
{"BackSpace", CK_BackSpace},
{"Delete", CK_Delete},
{"Enter", CK_Enter},
{"Page-Up", CK_Page_Up},
{"Page-Down", CK_Page_Down},
{"Left", CK_Left},
{"Right", CK_Right},
{"Word-Left", CK_Word_Left},
{"Word-Right", CK_Word_Right},
{"Up", CK_Up},
{"Down", CK_Down},
{"Home", CK_Home},
{"End", CK_End},
{"Tab", CK_Tab},
{"Undo", CK_Undo},
{"Beginning-Of-Text", CK_Beginning_Of_Text},
{"End-Of-Text", CK_End_Of_Text},
{"Scroll-Up", CK_Scroll_Up},
{"Scroll-Down", CK_Scroll_Down},
{"Return", CK_Return},
{"Begin-Page", CK_Begin_Page},
{"End-Page", CK_End_Page},
{"Delete-Word-Left", CK_Delete_Word_Left},
{"Delete-Word-Right", CK_Delete_Word_Right},
{"Paragraph-Up", CK_Paragraph_Up},
{"Paragraph-Down", CK_Paragraph_Down},
{"Save", CK_Save},
{"Load", CK_Load},
{"New", CK_New},
{"Save-as", CK_Save_As},
{"Mark", CK_Mark},
{"Copy", CK_Copy},
{"Move", CK_Move},
{"Remove", CK_Remove},
{"Unmark", CK_Unmark},
{"Save-Block", CK_Save_Block},
{"Column-Mark", CK_Column_Mark},
{"Find", CK_Find},
{"Find-Again", CK_Find_Again},
{"Replace", CK_Replace},
{"Replace-Again", CK_Replace_Again},
{"Complete-Word", CK_Complete_Word},
{"Debug-Start", CK_Debug_Start},
{"Debug-Stop", CK_Debug_Stop},
{"Debug-Toggle-Break", CK_Debug_Toggle_Break},
{"Debug-Clear", CK_Debug_Clear},
{"Debug-Next", CK_Debug_Next},
{"Debug-Step", CK_Debug_Step},
{"Debug-Back-Trace", CK_Debug_Back_Trace},
{"Debug-Continue", CK_Debug_Continue},
{"Debug-Enter-Command", CK_Debug_Enter_Command},
{"Debug-Until-Curser", CK_Debug_Until_Curser},
{"Insert-File", CK_Insert_File},
{"Exit", CK_Exit},
{"Toggle-Insert", CK_Toggle_Insert},
{"Help", CK_Help},
{"Date", CK_Date},
{"Refresh", CK_Refresh},
{"Goto", CK_Goto},
{"Delete-Line", CK_Delete_Line},
{"Delete-To-Line-End", CK_Delete_To_Line_End},
{"Delete-To-Line-Begin", CK_Delete_To_Line_Begin},
{"Man-Page", CK_Man_Page},
{"Sort", CK_Sort},
{"Mail", CK_Mail},
{"Cancel", CK_Cancel},
{"Complete", CK_Complete},
{"Paragraph-Format", CK_Paragraph_Format},
{"Util", CK_Util},
{"Type-Load-Python", CK_Type_Load_Python},
{"Find-File", CK_Find_File},
{"Ctags", CK_Ctags},
{"Match-Bracket", CK_Match_Bracket},
{"Terminal", CK_Terminal},
{"Terminal-App", CK_Terminal_App},
{"ExtCmd", CK_ExtCmd},
{"User-Menu", CK_User_Menu},
{"Save-Desktop", CK_Save_Desktop},
{"New-Window", CK_New_Window},
{"Cycle", CK_Cycle},
{"Menu", CK_Menu},
{"Save-And-Quit", CK_Save_And_Quit},
{"Run-Another", CK_Run_Another},
{"Check-Save-And-Quit", CK_Check_Save_And_Quit},
{"Maximize", CK_Maximize},
{"Begin-Record-Macro", CK_Begin_Record_Macro},
{"End-Record-Macro", CK_End_Record_Macro},
{"Delete-Macro", CK_Delete_Macro},
{"Toggle-Bookmark", CK_Toggle_Bookmark},
{"Flush-Bookmarks", CK_Flush_Bookmarks},
{"Next-Bookmark", CK_Next_Bookmark},
{"Prev-Bookmark", CK_Prev_Bookmark},
{"Page-Up-Highlight", CK_Page_Up_Highlight},
{"Page-Down-Highlight", CK_Page_Down_Highlight},
{"Left-Highlight", CK_Left_Highlight},
{"Right-Highlight", CK_Right_Highlight},
{"Word-Left-Highlight", CK_Word_Left_Highlight},
{"Word-Right-Highlight", CK_Word_Right_Highlight},
{"Up-Highlight", CK_Up_Highlight},
{"Down-Highlight", CK_Down_Highlight},
{"Home-Highlight", CK_Home_Highlight},
{"End-Highlight", CK_End_Highlight},
{"Beginning-Of-Text-Highlight", CK_Beginning_Of_Text_Highlight},
{"End-Of-Text_Highlight", CK_End_Of_Text_Highlight},
{"Begin-Page-Highlight", CK_Begin_Page_Highlight},
{"End-Page-Highlight", CK_End_Page_Highlight},
{"Scroll-Up-Highlight", CK_Scroll_Up_Highlight},
{"Scroll-Down-Highlight", CK_Scroll_Down_Highlight},
{"Paragraph-Up-Highlight", CK_Paragraph_Up_Highlight},
{"Paragraph-Down-Highlight", CK_Paragraph_Down_Highlight},
{"XStore", CK_XStore},
{"XCut", CK_XCut},
{"XPaste", CK_XPaste},
{"Selection-History", CK_Selection_History},
{"Shell", CK_Shell},
{"Select-Codepage", CK_Select_Codepage},
{"Insert-Literal", CK_Insert_Literal},
{"Execute-Macro", CK_Execute_Macro},
{"Begin-or-End-Macro", CK_Begin_End_Macro},
{"Ext-mode", CK_Ext_Mode},
#if 0
{"Focus-Next", CK_Focus_Next},
{"Focus-Prev", CK_Focus_Prev},
{"Height-Inc", CK_Height_Inc},
{"Height-Dec", CK_Height_Dec},
{"Make", CK_Make},
{"Error-Next", CK_Error_Next},
{"Error-Prev", CK_Error_Prev},
#endif
{NULL, 0}
};
static void
cfg_free_maps(config_t *cfg)
{
int i;
if (cfg->keymap)
g_array_free(cfg->keymap, TRUE);
cfg->keymap = NULL;
if (cfg->ext_keymap)
g_array_free(cfg->ext_keymap, TRUE);
cfg->ext_keymap = NULL;
for (i = 0; i < 10; i++)
g_free(cfg->labels[i]);
}
/* Returns an array containing the words in str. WARNING: As long as
* the result is used, str[...] must be valid memory. This function
* modifies str[...] and uses it, so the caller should not use it until
* g_ptr_array_free() is called for the returned result.
*/
static GPtrArray *
split_line(char *str)
{
gboolean inside_quote = FALSE;
int move = 0;
GPtrArray *args;
args = g_ptr_array_new();
/* skip spaces */
while (isspace((unsigned char) *str))
str++;
g_ptr_array_add(args, str);
for (;; str++) {
switch (*str) {
case '#': /* cut off comments */
if (inside_quote)
break;
/* FALLTHROUGH */
case '\n': /* end of line */
case '\r':
case '\0':
if (str == g_ptr_array_index(args, args->len - 1))
g_ptr_array_remove_index(args, args->len - 1);
else
*(str - move) = '\0';
return args;
case '"': /* quote */
case '\'':
inside_quote = !inside_quote;
move++;
continue;
case ' ': /* spaces */
case '\t':
if (inside_quote)
break;
*(str++ - move) = '\0';
move = 0;
/* skip spaces */
while (isspace((unsigned char) *str))
str++;
g_ptr_array_add(args, str--);
break;
case '\\':
switch (*(++str)) {
case 'n':
*str = '\n';
break;
case 'r':
*str = '\r';
break;
case 't':
*str = '\t';
break;
}
move++;
break;
}
if (move != 0)
*(str - move) = *str;
}
/* never be here */
}
static void
keymap_add(GArray *keymap, int key, int cmd)
{
edit_key_map_type new_one, *map;
guint i;
map = &(g_array_index(keymap, edit_key_map_type, 0));
for (i = 0; i < keymap->len; i++) {
if (map[i].key == key) {
map[i].command = cmd;
return;
}
}
new_one.key = key;
new_one.command = cmd;
g_array_append_val(keymap, new_one);
}
/* bind <key> <command> */
static gboolean
cmd_bind(config_t *cfg, int argc, char *argv[])
{
char *keyname, *command;
const name_map_t *key = key_names;
const name_map_t *cmd = command_names;
int mod = 0, k = -1, m = 0;
if (argc != 3) {
snprintf(error_msg, sizeof(error_msg),
_("bind: Wrong argument number, bind <key> <command>"));
return FALSE;
}
keyname = argv[1];
command = argv[2];
while (*keyname) {
switch (*keyname++) {
case 'C':
m = KEY_M_CTRL;
continue;
case 'M':
case 'A':
m = KEY_M_ALT;
continue;
case 'S':
m = KEY_M_SHIFT;
continue;
case '-':
if (!m) { /* incorrect key */
snprintf(error_msg, sizeof(error_msg),
_("bind: Bad key value `%s'"), keyname);
return FALSE;
}
mod |= m;
m = 0;
continue;
}
keyname--;
break;
}
/* no key */
if (keyname[0] == '\0') {
snprintf(error_msg, sizeof(error_msg), _("bind: Ehh...no key?"));
return FALSE;
}
/* ordinary key */
if (keyname[1] == '\0') {
k = keyname[0];
} else {
while (key->name && strcasecmp(key->name, keyname) != 0)
key++;
}
if (k < 0 && !key->name) {
snprintf(error_msg, sizeof(error_msg),
_("bind: Unknown key: `%s'"), keyname);
return FALSE;
}
while (cmd->name && strcasecmp(cmd->name, command) != 0)
cmd++;
if (!cmd->name) {
snprintf(error_msg, sizeof(error_msg),
_("bind: Unknown command: `%s'"), command);
return FALSE;
}
if (mod & KEY_M_CTRL) {
if (k < 256)
k = XCTRL(k);
else
k |= KEY_M_CTRL;
}
if (mod & KEY_M_ALT)
k |= KEY_M_ALT;
if (mod & KEY_M_SHIFT)
k |= KEY_M_SHIFT;
if (!strcasecmp("bind-ext", argv[0]))
keymap_add(cfg->ext_keymap, k, cmd->val);
else
keymap_add(cfg->keymap, k, cmd->val);
return TRUE;
}
#if 0
#define CMD_F(x) \
static void cmd_F ## x (WEdit * edit) \
{ \
send_message ((Widget *) edit, WIDGET_KEY, KEY_F (x)); \
}
CMD_F(1)
CMD_F(2)
CMD_F(3)
CMD_F(4)
CMD_F(5)
CMD_F(6)
CMD_F(7)
CMD_F(8)
CMD_F(9)
CMD_F(10)
void (*cmd_Fx[]) (WEdit *) = {
cmd_F1, cmd_F2, cmd_F3, cmd_F4, cmd_F5,
cmd_F6, cmd_F7, cmd_F8, cmd_F9, cmd_F10
} ;
/* move me! */
static void edit_my_define (Dlg_head * h, int idx, const char *text,
void (*fn) (WEdit *), WEdit * edit)
{
/* function-cast ok */
buttonbar_set_label_data (h, idx, text, (buttonbarfn) fn, edit);
}
#endif
/* label <number> <command> <label> */
static gboolean
cmd_label(config_t *cfg, int argc, char *argv[])
{
const name_map_t *cmd = command_names;
const char *command, *label;
int fn;
if (argc != 4) {
snprintf(error_msg, sizeof(error_msg),
_("%s: Syntax: %s <n> <command> <label>"),
argv[0], argv[0]);
return FALSE;
}
fn = strtol(argv[1], NULL, 0);
command = argv[2];
label = argv[3];
while (cmd->name && strcasecmp(cmd->name, command) != 0)
cmd++;
if (!cmd->name) {
snprintf(error_msg, sizeof(error_msg),
_("%s: Unknown command: `%s'"), argv[0], command);
return FALSE;
}
if (fn < 1 || fn > 10) {
snprintf(error_msg, sizeof(error_msg),
_("%s: fn should be 1-10"), argv[0]);
return FALSE;
}
keymap_add(cfg->keymap, KEY_F(fn), cmd->val);
cfg->labels[fn - 1] = g_strdup(label);
return TRUE;
}
static gboolean
parse_file(config_t *cfg, const char *file, const command_t *cmd)
{
char buf[200];
int line = 0;
FILE *fp = fopen(file, "r");
if (!fp) {
snprintf(error_msg, sizeof(error_msg), _("%s: fopen(): %s"),
file, strerror(errno));
return FALSE;
}
while (fgets(buf, sizeof(buf), fp)) {
const command_t *c = cmd;
GPtrArray *args;
char **argv;
line++;
args = split_line(buf);
argv = (char **) args->pdata;
if (args->len == 0) {
g_ptr_array_free(args, TRUE);
continue;
}
while (c->name != NULL && strcasecmp(c->name, argv[0]) != 0)
c++;
if (c->name == NULL) {
snprintf(error_msg, sizeof(error_msg),
_("%s:%d: unknown command `%s'"), file, line,
argv[0]);
g_ptr_array_free(args, TRUE);
fclose(fp);
return FALSE;
}
if (!(c->handler(cfg, args->len, argv))) {
char *ss = g_strdup(error_msg);
snprintf(error_msg, sizeof(error_msg),
_("%s:%d: %s"), file, line, ss);
g_free(ss);
g_ptr_array_free(args, TRUE);
fclose(fp);
return FALSE;
}
g_ptr_array_free(args, TRUE);
}
fclose(fp);
return TRUE;
}
gboolean
load_user_keymap(config_t *cfg, const char *file)
{
const command_t cmd[] = {
{"bind", cmd_bind},
{"bind-ext", cmd_bind},
{"label", cmd_label},
{0, 0}
};
cfg->keymap = g_array_new(TRUE, FALSE, sizeof(edit_key_map_type));
cfg->ext_keymap = g_array_new(TRUE, FALSE, sizeof(edit_key_map_type));
if (!parse_file(cfg, file, cmd)) {
return FALSE;
}
return TRUE;
}
gboolean
edit_load_user_map(WEdit *edit)
{
static config_t cfg;
config_t new_cfg;
char *file;
struct stat s;
if (edit_key_emulation != EDIT_KEY_EMULATION_USER)
return TRUE;
file = concat_dir_and_file(home_dir, MC_USERMAP);
if (stat(file, &s) < 0) {
char *msg = g_strdup_printf(_("%s not found!"), file);
edit_error_dialog(_("Error"), msg);
g_free(msg);
g_free(file);
return FALSE;
}
if (s.st_mtime != cfg.mtime) {
memset(&new_cfg, 0, sizeof(new_cfg));
new_cfg.mtime = s.st_mtime;
if (!load_user_keymap(&new_cfg, file)) {
edit_error_dialog(_("Error"), error_msg);
cfg_free_maps(&new_cfg);
g_free(file);
return FALSE;
} else {
cfg_free_maps(&cfg);
cfg = new_cfg;
}
}
edit->user_map = (edit_key_map_type *) cfg.keymap->data;
edit->ext_map = (edit_key_map_type *) cfg.ext_keymap->data;
memcpy(edit->labels, cfg.labels, sizeof(edit->labels));
g_free(file);
return TRUE;
}

11
edit/usermap.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef MC_USERMAP_H
#define MC_USERMAP_H
#define MC_USERMAP ".mc/cedit/cooledit.bindings"
#include "edit.h"
/* load user map */
gboolean edit_load_user_map(WEdit *);
#endif