1 /*======================================================================*\
2 |*		Editor mined						*|
3 |*		keyboard mapping tables					*|
4 \*======================================================================*/
5 
6 #include "mined.h"
7 #include "termprop.h"
8 
9 
10 #if defined (msdos)
11 #define noCJKkeymaps
12 #endif
13 
14 
15 #define use_CJKkeymaps
16 
17 #if defined (noCJKkeymaps) || defined (NOCJK)
18 #undef use_CJKkeymaps
19 #endif
20 
21 
22 /*======================================================================*\
23 |*		Keyboard mapping tables format and type			*|
24 \*======================================================================*/
25 
26 #ifndef NOSTRINGTABLES
27 #define keymapping_stringtables
28 #endif
29 
30 
31 #ifdef keymapping_stringtables
32 #define keymaptableelem char
33 #else
34 #define keymaptableelem struct keymap
35 struct keymap {
36 	char * fk;
37 	char * fp;
38 };
39 #endif
40 #define keymaptabletype keymaptableelem *
41 
42 
43 struct keymapping {
44 	keymaptabletype table;
45 	char * shortcut;
46 };
47 
48 
49 /*======================================================================*\
50 |*		Keyboard mapping tables					*|
51 \*======================================================================*/
52 
53 #define use_keymap_tables
54 
55 
56 #ifdef use_keymap_tables
57 
58 #ifndef use_concatenated_keymaps
59 #define use_concatenated_keymaps
60 #endif
61 
62 #define no_extern_keymap_tables
63 
64 #ifdef extern_keymap_tables
65 
66 # include "keymapsx.h"
67 # ifdef keymapping_stringtables
68 	/* link with keymaps1/*.o */
69 # else
70 	/* link with keymaps0/*.o from keymaps0/*.h */
71 # endif
72 
73 #else
74 
75 # ifdef keymapping_stringtables
76 #  ifdef use_concatenated_keymaps
77 #  include "keymaps.t"
78 #  else
79 #  include "keymapsc.h"
80 	/* #includes keymaps1/*.c, link with -Ikeymaps1 */
81 #  endif
82 # else
83 #  include "keymapsi.h"
84 	/* #includes keymaps0/*.h, link with -Ikeymaps0 */
85 # endif
86 
87 #endif
88 
89 #endif
90 
91 
92 /*======================================================================*\
93 |*		Table of tables						*|
94 \*======================================================================*/
95 
96 static struct keymapping keymappingtable [] = {
97 # ifdef use_keymap_tables
98 # include "keymapsk.t"
99 # else
100 	{0, "--"},	/* some compilers don't like empty arrays */
101 # endif
102 };
103 
104 static unsigned int keymappingtable_len = arrlen (keymappingtable);
105 
106 
107 /*======================================================================*\
108 |*		Input method switching					*|
109 \*======================================================================*/
110 
111 char * keyboard_mapping = "--";
112 char * last_keyboard_mapping = "--";
113 static char * next_keyboard_mapping = "";
114 
115 static keymaptabletype keyboard_map = (keymaptabletype) NIL_PTR;
116 static keymaptabletype last_keyboard_map = (keymaptabletype) NIL_PTR;
117 
118 /**
119    Notify user of changed input method
120  */
121 static
122 void
notify_input_method()123 notify_input_method ()
124 {
125   menuitemtype * km = lookup_Keymap_menuitem (keyboard_mapping);
126   char * source = NIL_PTR;
127 
128   switch (km->extratag ? km->extratag [0] : ' ') {
129 	case 'U':	source = "UnicodeData"; break;
130 	case 'H':	source = "Unihan"; break;
131 	case 'C':	source = "cxterm"; break;
132 	case 'M':	source = "m17n"; break;
133 	case 'Y':	source = "yudit"; break;
134 	case 'V':	source = "vim"; break;
135 	case 'X':	source = "X"; break;
136   }
137   if (source) {
138 	build_string (text_buffer, "Input method: %s (source: %s)",
139 			km->itemname, source);
140   } else {
141 	build_string (text_buffer, "Input method: %s", km->itemname);
142   }
143   status_uni (text_buffer);
144 }
145 
146 /**
147    Set keymap.
148  */
149 static
150 void
set_keymap(new_keymap,current,next)151 set_keymap (new_keymap, current, next)
152   keymaptabletype new_keymap;
153   char * current;
154   char * next;
155 {
156   last_keyboard_map = keyboard_map;
157   last_keyboard_mapping = keyboard_mapping;
158   keyboard_map = new_keymap;
159   keyboard_mapping = current;
160   next_keyboard_mapping = next;
161 
162   if (! loading && ! stat_visible && ! input_active) {
163 	notify_input_method ();
164   }
165 }
166 
167 /**
168    Exchange current and previous keyboard mapping; set previous active.
169    With HOP, reset keyboard mapping to none.
170  */
171 void
toggleKEYMAP()172 toggleKEYMAP ()
173 {
174   if (allow_keymap) {
175 	if (hop_flag > 0) {
176 		set_keymap ((keymaptabletype) NIL_PTR, "--", keymappingtable [0].shortcut);
177 	} else {
178 		set_keymap (last_keyboard_map, last_keyboard_mapping, last_keyboard_mapping);
179 	}
180 	flags_changed = True;
181   } else {
182 	error ("Keyboard mapping not active");
183   }
184 }
185 
186 /**
187    Set keyboard mapping.
188  */
189 static
190 FLAG
selectKEYMAP(script)191 selectKEYMAP (script)
192   char * script;
193 {
194   if (script == NIL_PTR || * script == '\0') {
195 	set_keymap ((keymaptabletype) NIL_PTR, "--", keymappingtable [0].shortcut);
196 	flags_changed = True;
197 	return True;
198   } else {
199 	/* map alternative shortcuts */
200 	int i;
201 	if (strisprefix ("el", script)) {
202 		script = "gr";
203 	} else if (strisprefix ("ru", script)) {
204 		script = "cy";
205 	}
206 	/* map shortcut to keymap */
207 	for (i = 0; i < keymappingtable_len; i ++) {
208 	    if (strisprefix (keymappingtable [i].shortcut, script)) {
209 		set_keymap (keymappingtable [i].table,
210 			    keymappingtable [i].shortcut,
211 			    i + 1 == keymappingtable_len ?
212 			      "" : keymappingtable [i + 1].shortcut);
213 		flags_changed = True;
214 		return True;
215 	    }
216 	}
217 	return False;
218   }
219 }
220 
221 /**
222    Set keyboard mapping.
223  */
224 FLAG
setKEYMAP(script)225 setKEYMAP (script)
226   char * script;
227 {
228   if (script != NIL_PTR && * script == '-') {
229 	/* set keymap as secondary map */
230 	script ++;
231 	(void) selectKEYMAP (script);
232 	(void) selectKEYMAP (NIL_PTR);
233   } else if (script != NIL_PTR) {
234 	char * secondary = strchr (script, '-');
235 	if (secondary != NIL_PTR) {
236 		secondary ++;
237 		(void) selectKEYMAP (secondary);
238 	}
239 	return selectKEYMAP (script);
240   }
241   return True;
242 }
243 
244 #ifdef not_used
245 /**
246    Cycle through keyboard mappings.
247  */
248 void
cycleKEYMAP()249 cycleKEYMAP ()
250 {
251   (void) selectKEYMAP (next_keyboard_mapping);
252 }
253 #endif
254 
255 /**
256    Enable keyboard mapping interactively.
257    With HOP, cycle through keyboard mappings.
258  */
259 void
setupKEYMAP()260 setupKEYMAP ()
261 {
262   if (allow_keymap) {
263 	if (hop_flag > 0) {
264 		hop_flag = 0;
265 		(void) selectKEYMAP (next_keyboard_mapping);
266 	} else {
267 		handleKeymapmenu ();
268 	}
269   } else {
270 	error ("Keyboard mapping not active");
271   }
272 }
273 
274 
275 /*======================================================================*\
276 |*		Key mapping lookup					*|
277 \*======================================================================*/
278 
279 /*
280    Look up key sequence in keyboard mapping table.
281    Similar to findkeyin but with modified parameter details.
282  * if matchmode == 0 (not used):
283  * mapkb (str) >=  0: key sequence str found
284  *			* mapped set to mapped string
285  *		 == -1: key sequence prefix recognised
286  *				(str is prefix of some table entry)
287  *		 == -2: key sequence not found
288  *				(str is not contained in table)
289  * * found == index of exact match if found
290  * if matchmode == 1:
291  * return -1 if any prefix detected (even if other exact match found)
292  * if matchmode == 2:
293  * don't return -1, only report exact or no match
294  */
295 static
296 int
mapkb(str,kbmap,matchmode,found,mapped)297 mapkb (str, kbmap, matchmode, found, mapped)
298   char * str;
299   keymaptabletype kbmap;
300   int matchmode;
301   char * * found;
302   char * * mapped;
303 {
304 #ifdef keymapping_stringtables
305 
306   int lastmatch = 0;	/* last index with string matching prefix */
307   register int i;
308   int ret = -2;
309   int len = strlen (str);
310 
311   * found = NIL_PTR;
312 
313   if (* kbmap == '\0') {
314 	return ret;
315   }
316 
317   i = lastmatch;
318   do {
319 	if (strncmp (str, kbmap, len) == 0) {
320 		/* str is prefix of current entry */
321 		lastmatch = i;
322 		if (len == strlen (kbmap)) {
323 			/* str is equal to current entry */
324 			* found = kbmap;
325 			* mapped = kbmap + len + 1;
326 			if (matchmode == 1) {
327 				/* return index unless other prefix
328 				   was or will be found */
329 				if (ret == -2) {
330 					ret = i;
331 				}
332 			} else {
333 				return i;
334 			}
335 		} else {
336 			/* str is partial prefix of current entry */
337 			if (matchmode == 1) {
338 				/* return -1 but continue to search
339 				   for exact match */
340 				ret = -1;
341 			} else if (matchmode != 2) {
342 				return -1;
343 			} else {
344 			}
345 		}
346 	}
347 	++ i;
348 	kbmap += strlen (kbmap) + 1;
349 	kbmap += strlen (kbmap) + 1;
350 	if (* kbmap == '\0') {
351 		i = 0;
352 		return ret;
353 	}
354   } while (i != lastmatch);
355 
356   return ret;
357 
358 #else
359 
360   int lastmatch = 0;	/* last index with string matching prefix */
361   register int i;
362   int ret = -2;
363 
364   * found = NIL_PTR;
365 
366   if (kbmap [0].fk == NIL_PTR) {
367 	return ret;
368   }
369 
370   i = lastmatch;
371   do {
372 	if (strncmp (str, kbmap [i].fk, strlen (str)) == 0) {
373 		/* str is prefix of current entry */
374 		lastmatch = i;
375 		if (strlen (str) == strlen (kbmap [i].fk)) {
376 			/* str is equal to current entry */
377 			* found = kbmap [i].fk;
378 			* mapped = kbmap [i].fp;
379 			if (! * mapped) {
380 				/* fix missing mapping in keyboard mapping table */
381 				* mapped = "";
382 			}
383 			if (matchmode == 1) {
384 				/* return index unless other prefix
385 				   was or will be found */
386 				if (ret == -2) {
387 					ret = i;
388 				}
389 			} else {
390 				return i;
391 			}
392 		} else {
393 			/* str is partial prefix of current entry */
394 			if (matchmode == 1) {
395 				/* return -1 but continue to search
396 				   for exact match */
397 				ret = -1;
398 			} else if (matchmode != 2) {
399 				return -1;
400 			} else {
401 			}
402 		}
403 	}
404 	++ i;
405 	if (kbmap [i].fk == NIL_PTR) {
406 		i = 0;
407 		return ret;
408 	}
409   } while (i != lastmatch);
410 
411   return ret;
412 
413 #endif
414 }
415 
416 int
map_key(str,matchmode,found,mapped)417 map_key (str, matchmode, found, mapped)
418   char * str;
419   int matchmode;
420   char * * found;
421   char * * mapped;
422 {
423   return mapkb (str, keyboard_map, matchmode, found, mapped);
424 }
425 
426 int
keyboard_mapping_active()427 keyboard_mapping_active ()
428 {
429   return keyboard_map != (keymaptabletype) NIL_PTR;
430 }
431 
432 
433 /*======================================================================*\
434 |*				End					*|
435 \*======================================================================*/
436