1 /* Editor key translation.
3 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
4 2005, 2006, 2007 Free Software Foundation, Inc.
6 Authors: 1996, 1997 Paul Sheer
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 * \brief Source: editor key translation
33 #include <sys/types.h>
42 #include "../src/global.h"
44 #include "edit-impl.h"
45 #include "edit-widget.h" /* edit->macro_i */
46 #include "editcmd_dialogs.h"
47 #include "editcmddef.h" /* list of commands */
49 #include "../src/tty/tty.h" /* keys */
50 #include "../src/tty/key.h" /* KEY_M_SHIFT */
52 #include "../src/charsets.h" /* convert_from_input_c() */
53 #include "../src/main.h" /* display_codepage */
54 #include "../src/strutil.h" /* str_isutf8 () */
57 * Ordinary translations. Note that the keys listed first take priority
58 * when the key is assigned to more than one command.
60 static const edit_key_map_type cooledit_key_map
[] = {
61 { ALT ('b'), CK_Match_Bracket
},
62 { ALT ('m'), CK_Mail
},
63 { XCTRL ('f'), CK_Save_Block
},
64 { XCTRL ('n'), CK_New
},
65 { XCTRL ('p'), CK_Pipe_Block (1) }, /* spell check */
66 { XCTRL ('x'), CK_Word_Right
},
67 { XCTRL ('y'), CK_Delete_Line
},
68 { XCTRL ('z'), CK_Word_Left
},
72 static const edit_key_map_type emacs_key_map
[] = {
73 { ALT ('$'), CK_Pipe_Block (1) }, /* spell check */
74 { ALT ('b'), CK_Word_Left
},
75 { ALT ('f'), CK_Word_Right
},
76 { ALT ('v'), CK_Page_Up
},
77 { ALT ('w'), CK_XStore
},
78 { XCTRL ('@'), CK_Mark
},
79 { XCTRL ('a'), CK_Home
},
80 { XCTRL ('b'), CK_Left
},
81 { XCTRL ('e'), CK_End
},
82 { XCTRL ('f'), CK_Right
},
83 { XCTRL ('g'), CK_Ignore_Key
},
84 { XCTRL ('n'), CK_Down
},
85 { XCTRL ('p'), CK_Up
},
86 { XCTRL ('s'), CK_Find
},
87 { XCTRL ('v'), CK_Page_Down
},
88 { XCTRL ('w'), CK_XCut
},
89 { XCTRL ('y'), CK_XPaste
},
93 static const edit_key_map_type common_key_map
[] = {
97 { ESC_CHAR
, CK_Exit
},
98 { KEY_BACKSPACE
, CK_BackSpace
},
99 { KEY_DC
, CK_Delete
},
100 { KEY_DOWN
, CK_Down
},
102 { KEY_HOME
, CK_Home
},
103 { KEY_IC
, CK_Toggle_Insert
},
104 { KEY_LEFT
, CK_Left
},
105 { KEY_NPAGE
, CK_Page_Down
},
106 { KEY_PPAGE
, CK_Page_Up
},
107 { KEY_RIGHT
, CK_Right
},
110 { ALT ('\n'), CK_Find_Definition
},
111 { ALT ('\t'), CK_Complete_Word
},
112 { ALT ('l'), CK_Goto
},
113 { ALT ('L'), CK_Goto
},
114 { ALT ('p'), CK_Paragraph_Format
},
115 { ALT ('t'), CK_Sort
},
116 { ALT ('u'), CK_ExtCmd
},
117 { ALT ('<'), CK_Beginning_Of_Text
},
118 { ALT ('>'), CK_End_Of_Text
},
119 { ALT ('-'), CK_Load_Prev_File
},
120 { ALT ('='), CK_Load_Next_File
},
121 { ALT ('d'), CK_Delete_Word_Right
},
122 { ALT (KEY_BACKSPACE
), CK_Delete_Word_Left
},
123 { ALT ('n'), CK_Toggle_Line_State
},
124 { ALT ('_'), CK_Toggle_Tab_TWS
},
125 { ALT ('k'), CK_Toggle_Bookmark
},
126 { ALT ('i'), CK_Prev_Bookmark
},
127 { ALT ('j'), CK_Next_Bookmark
},
128 { ALT ('o'), CK_Flush_Bookmarks
},
130 { XCTRL ('k'), CK_Delete_To_Line_End
},
131 { XCTRL ('l'), CK_Refresh
},
132 { XCTRL ('o'), CK_Shell
},
133 { XCTRL ('s'), CK_Toggle_Syntax
},
134 { XCTRL ('u'), CK_Undo
},
135 { XCTRL ('t'), CK_Select_Codepage
},
136 { XCTRL ('q'), CK_Insert_Literal
},
137 { XCTRL ('a'), CK_Execute_Macro
},
138 { XCTRL ('r'), CK_Begin_End_Macro
},
140 { KEY_F (1), CK_Help
},
141 { KEY_F (2), CK_Save
},
142 { KEY_F (3), CK_Mark
},
143 { KEY_F (4), CK_Replace
},
144 { KEY_F (5), CK_Copy
},
145 { KEY_F (6), CK_Move
},
146 { KEY_F (7), CK_Find
},
147 { KEY_F (8), CK_Remove
},
148 { KEY_F (10), CK_Exit
},
149 { KEY_F (11), CK_User_Menu
}, /* edit user menu */
150 { KEY_F (12), CK_Save_As
},
151 { KEY_F (13), CK_Column_Mark
},
152 { KEY_F (14), CK_Replace_Again
},
153 { KEY_F (15), CK_Insert_File
},
154 { KEY_F (17), CK_Find_Again
},
155 { KEY_F (19), CK_Pipe_Block (0) }, /* C formatter */
158 { KEY_M_SHIFT
| KEY_PPAGE
, CK_Page_Up_Highlight
},
159 { KEY_M_SHIFT
| KEY_NPAGE
, CK_Page_Down_Highlight
},
160 { KEY_M_SHIFT
| KEY_LEFT
, CK_Left_Highlight
},
161 { KEY_M_SHIFT
| KEY_RIGHT
, CK_Right_Highlight
},
162 { KEY_M_SHIFT
| KEY_UP
, CK_Up_Highlight
},
163 { KEY_M_SHIFT
| KEY_DOWN
, CK_Down_Highlight
},
164 { KEY_M_SHIFT
| KEY_HOME
, CK_Home_Highlight
},
165 { KEY_M_SHIFT
| KEY_END
, CK_End_Highlight
},
166 { KEY_M_SHIFT
| KEY_IC
, CK_XPaste
},
167 { KEY_M_SHIFT
| KEY_DC
, CK_XCut
},
168 { KEY_M_SHIFT
| '\n', CK_Return
}, /* useful for pasting multiline text */
171 { KEY_M_ALT
| KEY_PPAGE
, CK_Page_Up_Alt_Highlight
},
172 { KEY_M_ALT
| KEY_NPAGE
, CK_Page_Down_Highlight
},
173 { KEY_M_ALT
| KEY_LEFT
, CK_Left_Alt_Highlight
},
174 { KEY_M_ALT
| KEY_RIGHT
, CK_Right_Alt_Highlight
},
175 { KEY_M_ALT
| KEY_UP
, CK_Up_Alt_Highlight
},
176 { KEY_M_ALT
| KEY_DOWN
, CK_Down_Alt_Highlight
},
177 { KEY_M_ALT
| KEY_HOME
, CK_Home_Highlight
},
178 { KEY_M_ALT
| KEY_END
, CK_End_Alt_Highlight
},
181 { KEY_M_CTRL
| (KEY_F (2)), CK_Save_As
},
182 { KEY_M_CTRL
| (KEY_F (4)), CK_Replace_Again
},
183 { KEY_M_CTRL
| (KEY_F (7)), CK_Find_Again
},
184 { KEY_M_CTRL
| KEY_BACKSPACE
, CK_Undo
},
185 { KEY_M_CTRL
| KEY_PPAGE
, CK_Beginning_Of_Text
},
186 { KEY_M_CTRL
| KEY_NPAGE
, CK_End_Of_Text
},
187 { KEY_M_CTRL
| KEY_HOME
, CK_Beginning_Of_Text
},
188 { KEY_M_CTRL
| KEY_END
, CK_End_Of_Text
},
189 { KEY_M_CTRL
| KEY_UP
, CK_Scroll_Up
},
190 { KEY_M_CTRL
| KEY_DOWN
, CK_Scroll_Down
},
191 { KEY_M_CTRL
| KEY_LEFT
, CK_Word_Left
},
192 { KEY_M_CTRL
| KEY_RIGHT
, CK_Word_Right
},
193 { KEY_M_CTRL
| KEY_IC
, CK_XStore
},
194 { KEY_M_CTRL
| KEY_DC
, CK_Remove
},
197 { KEY_M_SHIFT
| KEY_M_CTRL
| KEY_PPAGE
, CK_Beginning_Of_Text_Highlight
},
198 { KEY_M_SHIFT
| KEY_M_CTRL
| KEY_NPAGE
, CK_End_Of_Text_Highlight
},
199 { KEY_M_SHIFT
| KEY_M_CTRL
| KEY_LEFT
, CK_Word_Left_Highlight
},
200 { KEY_M_SHIFT
| KEY_M_CTRL
| KEY_RIGHT
, CK_Word_Right_Highlight
},
201 { KEY_M_SHIFT
| KEY_M_CTRL
| KEY_UP
, CK_Scroll_Up_Highlight
},
202 { KEY_M_SHIFT
| KEY_M_CTRL
| KEY_DOWN
, CK_Scroll_Down_Highlight
},
209 * Translate the keycode into either 'command' or 'char_for_insertion'.
210 * 'command' is one of the editor commands from editcmddef.h.
213 edit_translate_key (WEdit
*edit
, long x_key
, int *cmd
, int *ch
)
215 int command
= CK_Insert_Char
;
216 int char_for_insertion
= -1;
221 const edit_key_map_type
*key_map
= NULL
;
222 switch (edit_key_emulation
) {
223 case EDIT_KEY_EMULATION_NORMAL
:
224 key_map
= cooledit_key_map
;
226 case EDIT_KEY_EMULATION_EMACS
:
227 key_map
= emacs_key_map
;
228 if (x_key
== XCTRL ('x')) {
231 editcmd_dialog_raw_key_query (" Ctrl-X ", _(" Emacs key: "), 0);
244 CK_Macro (editcmd_dialog_raw_key_query
245 (_(" Execute Macro "),
246 _(" Press macro hotkey: "), 1));
247 if (command
== CK_Macro (0))
248 command
= CK_Insert_Char
;
255 case EDIT_KEY_EMULATION_USER
:
256 if (edit
->user_map
!= NULL
) {
257 if (edit
->extmod
&& edit
->ext_map
!= NULL
) {
258 key_map
= edit
->ext_map
;
261 key_map
= edit
->user_map
;
265 key_map
= edit
->user_map
= cooledit_key_map
;
269 assert (key_map
!= NULL
);
271 /* an ordinary insertable character */
272 if (x_key
< 256 && !extmod
) {
274 if ( edit
->charpoint
>= 4 ) {
276 edit
->charbuf
[edit
->charpoint
] = '\0';
278 if ( edit
->charpoint
< 4 ) {
279 edit
->charbuf
[edit
->charpoint
++] = x_key
;
280 edit
->charbuf
[edit
->charpoint
] = '\0';
283 /* input from 8-bit locale */
284 if ( !utf8_display
) {
285 /* source in 8-bit codeset */
288 c
= convert_from_input_c (x_key
);
289 if (is_printable (c
)) {
290 char_for_insertion
= c
;
295 c
= convert_from_input_c (x_key
);
296 if (is_printable (c
)) {
297 char_for_insertion
= convert_from_8bit_to_utf_c2((unsigned char) x_key
);
303 /* source in UTF-8 codeset */
305 int res
= str_is_valid_char (edit
->charbuf
, edit
->charpoint
);
308 edit
->charpoint
= 0; /* broken multibyte char, skip */
311 char_for_insertion
= x_key
;
314 edit
->charbuf
[edit
->charpoint
]='\0';
316 if ( g_unichar_isprint (g_utf8_get_char(edit
->charbuf
))) {
317 char_for_insertion
= x_key
;
324 int res
= str_is_valid_char (edit
->charbuf
, edit
->charpoint
);
327 edit
->charpoint
= 0; /* broken multibyte char, skip */
330 /* not finised multibyte input (in meddle multibyte utf-8 char) */
333 if ( g_unichar_isprint (g_utf8_get_char(edit
->charbuf
)) ) {
334 c
= convert_from_utf_to_current ( edit
->charbuf
);
335 edit
->charbuf
[0] = '\0';
337 char_for_insertion
= c
;
340 /* unprinteble utf input, skip it */
341 edit
->charbuf
[0] = '\0';
349 /* Commands specific to the key emulation */
350 for (i
= 0; key_map
[i
].key
!= 0 && key_map
[i
].key
!= x_key
; i
++)
352 if (key_map
[i
].key
!= 0) {
353 command
= key_map
[i
].command
;
357 /* Commands common for the key emulations */
358 key_map
= common_key_map
;
359 for (i
= 0; key_map
[i
].key
!= 0 && key_map
[i
].key
!= x_key
; i
++)
361 if (key_map
[i
].key
!= 0) {
362 command
= key_map
[i
].command
;
366 /* Function still not found for this key, so try macros */
367 /* This allows the same macro to be
368 enabled by either eg "ALT('f')" or "XCTRL('f')" or "XCTRL('a'), 'f'" */
370 if (x_key
& ALT (0)) { /* is an alt key ? */
371 command
= CK_Macro (x_key
- ALT (0));
374 if (x_key
< ' ') { /* is a ctrl key ? */
375 command
= CK_Macro (x_key
);
381 *ch
= char_for_insertion
;
383 if (command
== CK_Insert_Char
&& char_for_insertion
== -1) {
384 /* unchanged, key has no function here */