1 | /* |
---|
2 | * Modifications Copyright 1993, 1994, 1995, 1996 by Paul Mattes. |
---|
3 | * Original X11 Port Copyright 1990 by Jeff Sparkes. |
---|
4 | * Permission to use, copy, modify, and distribute this software and its |
---|
5 | * documentation for any purpose and without fee is hereby granted, |
---|
6 | * provided that the above copyright notice appear in all copies and that |
---|
7 | * both that copyright notice and this permission notice appear in |
---|
8 | * supporting documentation. |
---|
9 | * |
---|
10 | * Copyright 1989 by Georgia Tech Research Corporation, Atlanta, GA 30332. |
---|
11 | * All Rights Reserved. GTRC hereby grants public use of this software. |
---|
12 | * Derivative works based on this software must incorporate this copyright |
---|
13 | * notice. |
---|
14 | */ |
---|
15 | |
---|
16 | /* |
---|
17 | * kybd.c |
---|
18 | * This module handles the keyboard for the 3270 emulator. |
---|
19 | */ |
---|
20 | |
---|
21 | #include "globals.h" |
---|
22 | #include <X11/Xatom.h> |
---|
23 | #include <X11/keysym.h> |
---|
24 | #include <fcntl.h> |
---|
25 | #include "3270ds.h" |
---|
26 | #include "appres.h" |
---|
27 | #include "ctlr.h" |
---|
28 | #include "cg.h" |
---|
29 | #include "resources.h" |
---|
30 | |
---|
31 | #include "actionsc.h" |
---|
32 | #include "ansic.h" |
---|
33 | #include "aplc.h" |
---|
34 | #include "ctlrc.h" |
---|
35 | #include "ftc.h" |
---|
36 | #include "keypadc.h" |
---|
37 | #include "kybdc.h" |
---|
38 | #include "macrosc.h" |
---|
39 | #include "popupsc.h" |
---|
40 | #include "printc.h" |
---|
41 | #include "screenc.h" |
---|
42 | #include "statusc.h" |
---|
43 | #include "tablesc.h" |
---|
44 | #include "telnetc.h" |
---|
45 | #include "trace_dsc.h" |
---|
46 | #include "utilc.h" |
---|
47 | |
---|
48 | /* Statics */ |
---|
49 | #define NP 5 |
---|
50 | static Atom paste_atom[NP]; |
---|
51 | static int n_pasting = 0; |
---|
52 | static int pix = 0; |
---|
53 | static Time paste_time; |
---|
54 | static enum { NONE, COMPOSE, FIRST } composing = NONE; |
---|
55 | static unsigned char pf_xlate[] = { |
---|
56 | AID_PF1, AID_PF2, AID_PF3, AID_PF4, AID_PF5, AID_PF6, |
---|
57 | AID_PF7, AID_PF8, AID_PF9, AID_PF10, AID_PF11, AID_PF12, |
---|
58 | AID_PF13, AID_PF14, AID_PF15, AID_PF16, AID_PF17, AID_PF18, |
---|
59 | AID_PF19, AID_PF20, AID_PF21, AID_PF22, AID_PF23, AID_PF24 |
---|
60 | }; |
---|
61 | static unsigned char pa_xlate[] = { |
---|
62 | AID_PA1, AID_PA2, AID_PA3 |
---|
63 | }; |
---|
64 | #define PF_SZ (sizeof(pf_xlate)/sizeof(pf_xlate[0])) |
---|
65 | #define PA_SZ (sizeof(pa_xlate)/sizeof(pa_xlate[0])) |
---|
66 | static XtIntervalId unlock_id; |
---|
67 | #define UNLOCK_MS 350 |
---|
68 | static Boolean key_Character(); |
---|
69 | |
---|
70 | static int nxk = 0; |
---|
71 | static struct xks { |
---|
72 | KeySym key; |
---|
73 | KeySym assoc; |
---|
74 | } *xk; |
---|
75 | static struct trans_list *tkm_last; |
---|
76 | |
---|
77 | static Boolean insert = False; /* insert mode */ |
---|
78 | static Boolean reverse = False; /* reverse-input mode */ |
---|
79 | |
---|
80 | /* Globals */ |
---|
81 | unsigned int kybdlock; |
---|
82 | unsigned char aid = AID_NO; /* current attention ID */ |
---|
83 | struct trans_list *temp_keymaps; /* temporary keymap list */ |
---|
84 | |
---|
85 | /* Composite key mappings. */ |
---|
86 | |
---|
87 | struct akeysym { |
---|
88 | KeySym keysym; |
---|
89 | enum keytype keytype; |
---|
90 | }; |
---|
91 | static struct akeysym cc_first; |
---|
92 | static struct composite { |
---|
93 | struct akeysym k1, k2; |
---|
94 | struct akeysym translation; |
---|
95 | } *composites = NULL; |
---|
96 | static int n_composites = 0; |
---|
97 | |
---|
98 | #define ak_eq(k1, k2) (((k1).keysym == (k2).keysym) && \ |
---|
99 | ((k1).keytype == (k2).keytype)) |
---|
100 | |
---|
101 | static struct ta { |
---|
102 | struct ta *next; |
---|
103 | void (*fn)(); |
---|
104 | char *parm1; |
---|
105 | char *parm2; |
---|
106 | } *ta_head = (struct ta *) NULL, |
---|
107 | *ta_tail = (struct ta *) NULL; |
---|
108 | |
---|
109 | |
---|
110 | /* |
---|
111 | * Put an action on the typeahead queue. |
---|
112 | */ |
---|
113 | void |
---|
114 | enq_ta(fn, parm1, parm2) |
---|
115 | void (*fn)(); |
---|
116 | char *parm1; |
---|
117 | char *parm2; |
---|
118 | { |
---|
119 | struct ta *ta; |
---|
120 | |
---|
121 | /* If no connection, forget it. */ |
---|
122 | if (!CONNECTED) { |
---|
123 | if (toggled(EVENT_TRACE)) |
---|
124 | (void) fprintf(tracef, " dropped (not connected)\n"); |
---|
125 | return; |
---|
126 | } |
---|
127 | |
---|
128 | /* If operator error, complain and drop it. */ |
---|
129 | if (kybdlock & KL_OERR_MASK) { |
---|
130 | ring_bell(); |
---|
131 | if (toggled(EVENT_TRACE)) |
---|
132 | (void) fprintf(tracef, " dropped (operator error)\n"); |
---|
133 | return; |
---|
134 | } |
---|
135 | |
---|
136 | /* If scroll lock, complain and drop it. */ |
---|
137 | if (kybdlock & KL_SCROLLED) { |
---|
138 | ring_bell(); |
---|
139 | if (toggled(EVENT_TRACE)) |
---|
140 | (void) fprintf(tracef, " dropped (scrolled)\n"); |
---|
141 | return; |
---|
142 | } |
---|
143 | |
---|
144 | /* If typeahead disabled, complain and drop it. */ |
---|
145 | if (!appres.typeahead) { |
---|
146 | if (toggled(EVENT_TRACE)) |
---|
147 | (void) fprintf(tracef, " dropped (no typeahead)\n"); |
---|
148 | return; |
---|
149 | } |
---|
150 | |
---|
151 | ta = (struct ta *) XtMalloc(sizeof(*ta)); |
---|
152 | ta->next = (struct ta *) NULL; |
---|
153 | ta->fn = fn; |
---|
154 | ta->parm1 = ta->parm2 = CN; |
---|
155 | if (parm1) { |
---|
156 | ta->parm1 = XtNewString(parm1); |
---|
157 | if (parm2) |
---|
158 | ta->parm2 = XtNewString(parm2); |
---|
159 | } |
---|
160 | if (ta_head) |
---|
161 | ta_tail->next = ta; |
---|
162 | else { |
---|
163 | ta_head = ta; |
---|
164 | status_typeahead(True); |
---|
165 | } |
---|
166 | ta_tail = ta; |
---|
167 | |
---|
168 | if (toggled(EVENT_TRACE)) |
---|
169 | (void) fprintf(tracef, " action queued (kybdlock 0x%x)\n", |
---|
170 | kybdlock); |
---|
171 | } |
---|
172 | |
---|
173 | /* |
---|
174 | * Execute an action from the typeahead queue. |
---|
175 | */ |
---|
176 | Boolean |
---|
177 | run_ta() |
---|
178 | { |
---|
179 | struct ta *ta; |
---|
180 | |
---|
181 | if (kybdlock || (ta = ta_head) == (struct ta *)NULL) |
---|
182 | return False; |
---|
183 | |
---|
184 | if ((ta_head = ta->next) == (struct ta *)NULL) { |
---|
185 | ta_tail = (struct ta *) NULL; |
---|
186 | status_typeahead(False); |
---|
187 | } |
---|
188 | |
---|
189 | action_internal(ta->fn, IA_TYPEAHEAD, ta->parm1, ta->parm2); |
---|
190 | if (ta->parm1 != CN) |
---|
191 | XtFree(ta->parm1); |
---|
192 | if (ta->parm2 != CN) |
---|
193 | XtFree(ta->parm2); |
---|
194 | XtFree((XtPointer)ta); |
---|
195 | |
---|
196 | return True; |
---|
197 | } |
---|
198 | |
---|
199 | /* |
---|
200 | * Flush the typeahead queue. |
---|
201 | * Returns whether or not anything was flushed. |
---|
202 | */ |
---|
203 | Boolean |
---|
204 | flush_ta() |
---|
205 | { |
---|
206 | struct ta *ta, *next; |
---|
207 | Boolean any = False; |
---|
208 | |
---|
209 | for (ta = ta_head; ta != (struct ta *) NULL; ta = next) { |
---|
210 | if (ta->parm1) |
---|
211 | XtFree(ta->parm1); |
---|
212 | if (ta->parm2) |
---|
213 | XtFree(ta->parm2); |
---|
214 | next = ta->next; |
---|
215 | XtFree((XtPointer)ta); |
---|
216 | any = True; |
---|
217 | } |
---|
218 | ta_head = ta_tail = (struct ta *) NULL; |
---|
219 | status_typeahead(False); |
---|
220 | return any; |
---|
221 | } |
---|
222 | |
---|
223 | /* |
---|
224 | * Translation table cache. |
---|
225 | */ |
---|
226 | XtTranslations |
---|
227 | lookup_tt(name, table) |
---|
228 | char *name; |
---|
229 | char *table; |
---|
230 | { |
---|
231 | struct tt_cache { |
---|
232 | char *name; |
---|
233 | XtTranslations trans; |
---|
234 | struct tt_cache *next; |
---|
235 | }; |
---|
236 | # define TTN (struct tt_cache *)NULL |
---|
237 | static struct tt_cache *tt_cache = TTN; |
---|
238 | struct tt_cache *t; |
---|
239 | |
---|
240 | /* Look for an old one. */ |
---|
241 | for (t = tt_cache; t != TTN; t = t->next) |
---|
242 | if (!strcmp(name, t->name)) |
---|
243 | return t->trans; |
---|
244 | |
---|
245 | /* Allocate and translate a new one. */ |
---|
246 | t = (struct tt_cache *)XtMalloc(sizeof(*t)); |
---|
247 | t->name = XtNewString(name); |
---|
248 | t->trans = XtParseTranslationTable(table); |
---|
249 | t->next = tt_cache; |
---|
250 | tt_cache = t; |
---|
251 | |
---|
252 | return t->trans; |
---|
253 | } |
---|
254 | #undef TTN |
---|
255 | |
---|
256 | /* Set bits in the keyboard lock. */ |
---|
257 | /*ARGSUSED*/ |
---|
258 | void |
---|
259 | kybdlock_set(bits, cause) |
---|
260 | unsigned int bits; |
---|
261 | char *cause; |
---|
262 | { |
---|
263 | unsigned int n; |
---|
264 | |
---|
265 | n = kybdlock | bits; |
---|
266 | if (n != kybdlock) { |
---|
267 | #if defined(KYBDLOCK_TRACE) /*[*/ |
---|
268 | if (toggled(EVENT_TRACE)) |
---|
269 | (void) fprintf(tracef, |
---|
270 | " %s: kybdlock |= 0x%04x, 0x%04x -> 0x%04x\n", |
---|
271 | cause, bits, kybdlock, n); |
---|
272 | #endif /*]*/ |
---|
273 | kybdlock = n; |
---|
274 | status_kybdlock(); |
---|
275 | } |
---|
276 | } |
---|
277 | |
---|
278 | /* Clear bits in the keyboard lock. */ |
---|
279 | /*ARGSUSED*/ |
---|
280 | void |
---|
281 | kybdlock_clr(bits, cause) |
---|
282 | unsigned int bits; |
---|
283 | char *cause; |
---|
284 | { |
---|
285 | unsigned int n; |
---|
286 | |
---|
287 | n = kybdlock & ~bits; |
---|
288 | if (n != kybdlock) { |
---|
289 | #if defined(KYBDLOCK_TRACE) /*[*/ |
---|
290 | if (toggled(EVENT_TRACE)) |
---|
291 | (void) fprintf(tracef, |
---|
292 | " %s: kybdlock &= ~0x%04x, 0x%04x -> 0x%04x\n", |
---|
293 | cause, bits, kybdlock, n); |
---|
294 | #endif /*]*/ |
---|
295 | kybdlock = n; |
---|
296 | status_kybdlock(); |
---|
297 | } |
---|
298 | } |
---|
299 | |
---|
300 | /* |
---|
301 | * Set or clear enter-inhibit mode. |
---|
302 | */ |
---|
303 | void |
---|
304 | kybd_inhibit(inhibit) |
---|
305 | Boolean inhibit; |
---|
306 | { |
---|
307 | if (inhibit) { |
---|
308 | kybdlock_set(KL_ENTER_INHIBIT, "kybd_inhibit"); |
---|
309 | if (kybdlock == KL_ENTER_INHIBIT) |
---|
310 | status_reset(); |
---|
311 | } else { |
---|
312 | kybdlock_clr(KL_ENTER_INHIBIT, "kybd_inhibit"); |
---|
313 | if (!kybdlock) |
---|
314 | status_reset(); |
---|
315 | } |
---|
316 | } |
---|
317 | |
---|
318 | /* |
---|
319 | * Called when a host connects or disconnects. |
---|
320 | */ |
---|
321 | void |
---|
322 | kybd_connect() |
---|
323 | { |
---|
324 | if (kybdlock & KL_DEFERRED_UNLOCK) |
---|
325 | XtRemoveTimeOut(unlock_id); |
---|
326 | kybdlock_clr(-1, "kybd_connect"); |
---|
327 | |
---|
328 | if (CONNECTED) { |
---|
329 | /* Wait for any output or a WCC(restore) from the host */ |
---|
330 | kybdlock_set(KL_AWAITING_FIRST, "kybd_connect"); |
---|
331 | } else { |
---|
332 | kybdlock_set(KL_NOT_CONNECTED, "kybd_connect"); |
---|
333 | (void) flush_ta(); |
---|
334 | } |
---|
335 | } |
---|
336 | |
---|
337 | /* |
---|
338 | * Toggle insert mode. |
---|
339 | */ |
---|
340 | static void |
---|
341 | insert_mode(on) |
---|
342 | Boolean on; |
---|
343 | { |
---|
344 | insert = on; |
---|
345 | status_insert_mode(on); |
---|
346 | } |
---|
347 | |
---|
348 | /* |
---|
349 | * Toggle reverse mode. |
---|
350 | */ |
---|
351 | static void |
---|
352 | reverse_mode(on) |
---|
353 | Boolean on; |
---|
354 | { |
---|
355 | reverse = on; |
---|
356 | status_reverse_mode(on); |
---|
357 | } |
---|
358 | |
---|
359 | /* |
---|
360 | * Lock the keyboard because of an operator error. |
---|
361 | */ |
---|
362 | static void |
---|
363 | operator_error(error_type) |
---|
364 | int error_type; |
---|
365 | { |
---|
366 | if (sms_redirect()) |
---|
367 | popup_an_error("Keyboard locked"); |
---|
368 | if (appres.oerr_lock || sms_redirect()) { |
---|
369 | status_oerr(error_type); |
---|
370 | mcursor_locked(); |
---|
371 | kybdlock_set((unsigned int)error_type, "operator_error"); |
---|
372 | (void) flush_ta(); |
---|
373 | } else |
---|
374 | ring_bell(); |
---|
375 | } |
---|
376 | |
---|
377 | |
---|
378 | /* |
---|
379 | * Handle an AID (Attention IDentifier) key. This is the common stuff that |
---|
380 | * gets executed for all AID keys (PFs, PAs, Clear and etc). |
---|
381 | */ |
---|
382 | void |
---|
383 | key_AID(aid_code) |
---|
384 | unsigned char aid_code; |
---|
385 | { |
---|
386 | if (IN_ANSI) { |
---|
387 | register int i; |
---|
388 | |
---|
389 | if (aid_code == AID_ENTER) { |
---|
390 | net_sendc('\r'); |
---|
391 | return; |
---|
392 | } |
---|
393 | for (i = 0; i < PF_SZ; i++) |
---|
394 | if (aid_code == pf_xlate[i]) { |
---|
395 | ansi_send_pf(i+1); |
---|
396 | return; |
---|
397 | } |
---|
398 | for (i = 0; i < PA_SZ; i++) |
---|
399 | if (aid_code == pa_xlate[i]) { |
---|
400 | ansi_send_pa(i+1); |
---|
401 | return; |
---|
402 | } |
---|
403 | return; |
---|
404 | } |
---|
405 | status_twait(); |
---|
406 | mcursor_waiting(); |
---|
407 | insert_mode(False); |
---|
408 | kybdlock_set(KL_OIA_TWAIT | KL_OIA_LOCKED, "key_AID"); |
---|
409 | aid = aid_code; |
---|
410 | ctlr_read_modified(aid, False); |
---|
411 | ticking_start(False); |
---|
412 | status_ctlr_done(); |
---|
413 | } |
---|
414 | |
---|
415 | /*ARGSUSED*/ |
---|
416 | void |
---|
417 | PF_action(w, event, params, num_params) |
---|
418 | Widget w; |
---|
419 | XEvent *event; |
---|
420 | String *params; |
---|
421 | Cardinal *num_params; |
---|
422 | { |
---|
423 | int k; |
---|
424 | |
---|
425 | action_debug(PF_action, event, params, num_params); |
---|
426 | if (check_usage(PF_action, *num_params, 1, 1) < 0) |
---|
427 | return; |
---|
428 | k = atoi(params[0]); |
---|
429 | if (k < 0 || k > PF_SZ) { |
---|
430 | popup_an_error("%s: invalid argument", action_name(PF_action)); |
---|
431 | return; |
---|
432 | } |
---|
433 | if (kybdlock) |
---|
434 | enq_ta(PF_action, params[0], CN); |
---|
435 | else |
---|
436 | key_AID(pf_xlate[k-1]); |
---|
437 | } |
---|
438 | |
---|
439 | /*ARGSUSED*/ |
---|
440 | void |
---|
441 | PA_action(w, event, params, num_params) |
---|
442 | Widget w; |
---|
443 | XEvent *event; |
---|
444 | String *params; |
---|
445 | Cardinal *num_params; |
---|
446 | { |
---|
447 | int k; |
---|
448 | |
---|
449 | action_debug(PA_action, event, params, num_params); |
---|
450 | if (check_usage(PA_action, *num_params, 1, 1) < 0) |
---|
451 | return; |
---|
452 | k = atoi(params[0]); |
---|
453 | if (k < 0 || k > PA_SZ) { |
---|
454 | popup_an_error("%s: invalid argument %d", |
---|
455 | action_name(PA_action), k); |
---|
456 | return; |
---|
457 | } |
---|
458 | if (kybdlock) |
---|
459 | enq_ta(PA_action, params[0], CN); |
---|
460 | else |
---|
461 | key_AID(pa_xlate[k-1]); |
---|
462 | } |
---|
463 | |
---|
464 | |
---|
465 | /* |
---|
466 | * ATTN key, similar to an AID key but without the read_modified call. |
---|
467 | */ |
---|
468 | /*ARGSUSED*/ |
---|
469 | void |
---|
470 | Attn_action(w, event, params, num_params) |
---|
471 | Widget w; |
---|
472 | XEvent *event; |
---|
473 | String *params; |
---|
474 | Cardinal *num_params; |
---|
475 | { |
---|
476 | action_debug(Attn_action, event, params, num_params); |
---|
477 | if (!IN_3270) |
---|
478 | return; |
---|
479 | if (kybdlock) { |
---|
480 | enq_ta(Attn_action, CN, CN); |
---|
481 | return; |
---|
482 | } |
---|
483 | if (appres.attn_lock) { |
---|
484 | status_twait(); |
---|
485 | mcursor_waiting(); |
---|
486 | insert_mode(False); |
---|
487 | kybdlock_set(KL_OIA_TWAIT | KL_OIA_LOCKED, "Attn_action"); |
---|
488 | } |
---|
489 | net_break(); |
---|
490 | if (appres.attn_lock) { |
---|
491 | ticking_start(False); |
---|
492 | status_ctlr_done(); |
---|
493 | } |
---|
494 | } |
---|
495 | |
---|
496 | |
---|
497 | |
---|
498 | /*ARGSUSED*/ |
---|
499 | static void |
---|
500 | key_Character_wrapper(w, event, params, num_params) |
---|
501 | Widget w; |
---|
502 | XEvent *event; |
---|
503 | String *params; |
---|
504 | Cardinal *num_params; |
---|
505 | { |
---|
506 | int cgcode; |
---|
507 | Boolean with_ge = False; |
---|
508 | |
---|
509 | cgcode = atoi(params[0]); |
---|
510 | if (cgcode & 0x100) { |
---|
511 | with_ge = True; |
---|
512 | cgcode &= 0xff; |
---|
513 | } |
---|
514 | if (toggled(EVENT_TRACE)) { |
---|
515 | (void) fprintf(tracef, " %s -> Key(%s\"%s\")\n", |
---|
516 | ia_name[(int) ia_cause], |
---|
517 | with_ge ? "GE " : "", |
---|
518 | ctl_see((int) cg2asc[cgcode])); |
---|
519 | } |
---|
520 | (void) key_Character(cgcode, with_ge); |
---|
521 | } |
---|
522 | |
---|
523 | /* |
---|
524 | * Handle an ordinary displayable character key. Lots of stuff to handle |
---|
525 | * insert-mode, protected fields and etc. |
---|
526 | */ |
---|
527 | static Boolean |
---|
528 | key_Character(cgcode, with_ge) |
---|
529 | int cgcode; |
---|
530 | Boolean with_ge; |
---|
531 | { |
---|
532 | register int baddr, end_baddr; |
---|
533 | register unsigned char *fa; |
---|
534 | Boolean no_room = False; |
---|
535 | |
---|
536 | if (kybdlock) { |
---|
537 | char code[64]; |
---|
538 | |
---|
539 | (void) sprintf(code, "%d", cgcode | (with_ge ? 0x100 : 0)); |
---|
540 | enq_ta(key_Character_wrapper, code, CN); |
---|
541 | return False; |
---|
542 | } |
---|
543 | baddr = cursor_addr; |
---|
544 | fa = get_field_attribute(baddr); |
---|
545 | if (IS_FA(screen_buf[baddr]) || FA_IS_PROTECTED(*fa)) { |
---|
546 | operator_error(KL_OERR_PROTECTED); |
---|
547 | return False; |
---|
548 | } |
---|
549 | if (appres.numeric_lock && FA_IS_NUMERIC(*fa) && |
---|
550 | !((cgcode >= CG_0 && cgcode <= CG_9) || |
---|
551 | cgcode == CG_minus || cgcode == CG_period)) { |
---|
552 | operator_error(KL_OERR_NUMERIC); |
---|
553 | return False; |
---|
554 | } |
---|
555 | if (reverse || (insert && screen_buf[baddr])) { |
---|
556 | int last_blank = -1; |
---|
557 | |
---|
558 | /* Find next null, next fa, or last blank */ |
---|
559 | end_baddr = baddr; |
---|
560 | if (screen_buf[end_baddr] == CG_space) |
---|
561 | last_blank = end_baddr; |
---|
562 | do { |
---|
563 | INC_BA(end_baddr); |
---|
564 | if (screen_buf[end_baddr] == CG_space) |
---|
565 | last_blank = end_baddr; |
---|
566 | if (screen_buf[end_baddr] == CG_null |
---|
567 | || IS_FA(screen_buf[end_baddr])) |
---|
568 | break; |
---|
569 | } while (end_baddr != baddr); |
---|
570 | |
---|
571 | /* Pretend a trailing blank is a null, if desired. */ |
---|
572 | if (toggled(BLANK_FILL) && last_blank != -1) { |
---|
573 | INC_BA(last_blank); |
---|
574 | if (last_blank == end_baddr) { |
---|
575 | DEC_BA(end_baddr); |
---|
576 | ctlr_add(end_baddr, CG_null, 0); |
---|
577 | } |
---|
578 | } |
---|
579 | |
---|
580 | /* Check for field overflow. */ |
---|
581 | if (screen_buf[end_baddr] != CG_null) { |
---|
582 | if (insert) { |
---|
583 | operator_error(KL_OERR_OVERFLOW); |
---|
584 | return False; |
---|
585 | } else { /* reverse */ |
---|
586 | no_room = True; |
---|
587 | } |
---|
588 | } else { |
---|
589 | /* Shift data over. */ |
---|
590 | if (end_baddr > baddr) { |
---|
591 | /* At least one byte to copy, no wrap. */ |
---|
592 | ctlr_bcopy(baddr, baddr+1, end_baddr - baddr, |
---|
593 | 0); |
---|
594 | } else if (end_baddr < baddr) { |
---|
595 | /* At least one byte to copy, wraps to top. */ |
---|
596 | ctlr_bcopy(0, 1, end_baddr, 0); |
---|
597 | ctlr_add(0, screen_buf[(ROWS * COLS) - 1], 0); |
---|
598 | ctlr_bcopy(baddr, baddr+1, |
---|
599 | ((ROWS * COLS) - 1) - baddr, 0); |
---|
600 | } |
---|
601 | } |
---|
602 | |
---|
603 | } |
---|
604 | |
---|
605 | /* Replace leading nulls with blanks, if desired. */ |
---|
606 | if (formatted && toggled(BLANK_FILL)) { |
---|
607 | int baddr_sof = fa - screen_buf; |
---|
608 | register int baddr_fill = baddr; |
---|
609 | |
---|
610 | DEC_BA(baddr_fill); |
---|
611 | while (baddr_fill != baddr_sof) { |
---|
612 | |
---|
613 | /* Check for backward line wrap. */ |
---|
614 | if ((baddr_fill % COLS) == COLS - 1) { |
---|
615 | Boolean aborted = True; |
---|
616 | register int baddr_scan = baddr_fill; |
---|
617 | |
---|
618 | /* |
---|
619 | * Check the field within the preceeding line |
---|
620 | * for NULLs. |
---|
621 | */ |
---|
622 | while (baddr_scan != baddr_sof) { |
---|
623 | if (screen_buf[baddr_scan] != CG_null) { |
---|
624 | aborted = False; |
---|
625 | break; |
---|
626 | } |
---|
627 | if (!(baddr_scan % COLS)) |
---|
628 | break; |
---|
629 | DEC_BA(baddr_scan); |
---|
630 | } |
---|
631 | if (aborted) |
---|
632 | break; |
---|
633 | } |
---|
634 | |
---|
635 | if (screen_buf[baddr_fill] == CG_null) |
---|
636 | ctlr_add(baddr_fill, CG_space, 0); |
---|
637 | DEC_BA(baddr_fill); |
---|
638 | } |
---|
639 | } |
---|
640 | |
---|
641 | /* Add the character. */ |
---|
642 | if (no_room) { |
---|
643 | do { |
---|
644 | INC_BA(baddr); |
---|
645 | } while (!IS_FA(screen_buf[baddr])); |
---|
646 | } else { |
---|
647 | ctlr_add(baddr, (unsigned char)cgcode, |
---|
648 | (unsigned char)(with_ge ? CS_GE : 0)); |
---|
649 | ctlr_add_fg(baddr, 0); |
---|
650 | ctlr_add_gr(baddr, 0); |
---|
651 | if (!reverse) |
---|
652 | INC_BA(baddr); |
---|
653 | } |
---|
654 | |
---|
655 | /* Implement auto-skip, and don't land on attribute bytes. */ |
---|
656 | if (cgcode != CG_dup) { |
---|
657 | if (IS_FA(screen_buf[baddr]) && |
---|
658 | FA_IS_SKIP(screen_buf[baddr])) |
---|
659 | baddr = next_unprotected(baddr); |
---|
660 | else while (IS_FA(screen_buf[baddr])) |
---|
661 | INC_BA(baddr); |
---|
662 | |
---|
663 | cursor_move(baddr); |
---|
664 | } |
---|
665 | |
---|
666 | mdt_set(fa); |
---|
667 | return True; |
---|
668 | } |
---|
669 | |
---|
670 | /* |
---|
671 | * Handle an ordinary character key, given an ASCII code. |
---|
672 | */ |
---|
673 | static void |
---|
674 | key_ACharacter(c, keytype, cause) |
---|
675 | unsigned char c; |
---|
676 | enum keytype keytype; |
---|
677 | enum iaction cause; |
---|
678 | { |
---|
679 | register int i; |
---|
680 | struct akeysym ak; |
---|
681 | |
---|
682 | ak.keysym = c; |
---|
683 | ak.keytype = keytype; |
---|
684 | |
---|
685 | switch (composing) { |
---|
686 | case NONE: |
---|
687 | break; |
---|
688 | case COMPOSE: |
---|
689 | for (i = 0; i < n_composites; i++) |
---|
690 | if (ak_eq(composites[i].k1, ak) || |
---|
691 | ak_eq(composites[i].k2, ak)) |
---|
692 | break; |
---|
693 | if (i < n_composites) { |
---|
694 | cc_first.keysym = c; |
---|
695 | cc_first.keytype = keytype; |
---|
696 | composing = FIRST; |
---|
697 | status_compose(True, c, keytype); |
---|
698 | } else { |
---|
699 | ring_bell(); |
---|
700 | composing = NONE; |
---|
701 | status_compose(False, 0, KT_STD); |
---|
702 | } |
---|
703 | return; |
---|
704 | case FIRST: |
---|
705 | composing = NONE; |
---|
706 | status_compose(False, 0, KT_STD); |
---|
707 | for (i = 0; i < n_composites; i++) |
---|
708 | if ((ak_eq(composites[i].k1, cc_first) && |
---|
709 | ak_eq(composites[i].k2, ak)) || |
---|
710 | (ak_eq(composites[i].k1, ak) && |
---|
711 | ak_eq(composites[i].k2, cc_first))) |
---|
712 | break; |
---|
713 | if (i < n_composites) { |
---|
714 | c = composites[i].translation.keysym; |
---|
715 | keytype = composites[i].translation.keytype; |
---|
716 | } else { |
---|
717 | ring_bell(); |
---|
718 | return; |
---|
719 | } |
---|
720 | break; |
---|
721 | } |
---|
722 | |
---|
723 | if (toggled(EVENT_TRACE)) { |
---|
724 | (void) fprintf(tracef, " %s -> Key(\"%s\")\n", |
---|
725 | ia_name[(int) cause], ctl_see((int) c)); |
---|
726 | } |
---|
727 | if (IN_3270) { |
---|
728 | if (c < ' ') { |
---|
729 | if (toggled(EVENT_TRACE)) |
---|
730 | (void) fprintf(tracef, |
---|
731 | " dropped (control char)\n"); |
---|
732 | return; |
---|
733 | } |
---|
734 | (void) key_Character((int) asc2cg[c], keytype == KT_GE); |
---|
735 | } else if (IN_ANSI) { |
---|
736 | net_sendc((char) c); |
---|
737 | } else { |
---|
738 | if (toggled(EVENT_TRACE)) |
---|
739 | (void) fprintf(tracef, " dropped (not connected)\n"); |
---|
740 | } |
---|
741 | } |
---|
742 | |
---|
743 | |
---|
744 | /* |
---|
745 | * Simple toggles. |
---|
746 | */ |
---|
747 | /*ARGSUSED*/ |
---|
748 | void |
---|
749 | AltCursor_action(w, event, params, num_params) |
---|
750 | Widget w; |
---|
751 | XEvent *event; |
---|
752 | String *params; |
---|
753 | Cardinal *num_params; |
---|
754 | { |
---|
755 | action_debug(AltCursor_action, event, params, num_params); |
---|
756 | do_toggle(ALT_CURSOR); |
---|
757 | } |
---|
758 | |
---|
759 | /*ARGSUSED*/ |
---|
760 | void |
---|
761 | MonoCase_action(w, event, params, num_params) |
---|
762 | Widget w; |
---|
763 | XEvent *event; |
---|
764 | String *params; |
---|
765 | Cardinal *num_params; |
---|
766 | { |
---|
767 | action_debug(MonoCase_action, event, params, num_params); |
---|
768 | do_toggle(MONOCASE); |
---|
769 | } |
---|
770 | |
---|
771 | /* |
---|
772 | * Flip the display left-to-right |
---|
773 | */ |
---|
774 | /*ARGSUSED*/ |
---|
775 | void |
---|
776 | Flip_action(w, event, params, num_params) |
---|
777 | Widget w; |
---|
778 | XEvent *event; |
---|
779 | String *params; |
---|
780 | Cardinal *num_params; |
---|
781 | { |
---|
782 | action_debug(Flip_action, event, params, num_params); |
---|
783 | screen_flip(); |
---|
784 | } |
---|
785 | |
---|
786 | |
---|
787 | |
---|
788 | /* |
---|
789 | * Tab forward to next field. |
---|
790 | */ |
---|
791 | /*ARGSUSED*/ |
---|
792 | void |
---|
793 | Tab_action(w, event, params, num_params) |
---|
794 | Widget w; |
---|
795 | XEvent *event; |
---|
796 | String *params; |
---|
797 | Cardinal *num_params; |
---|
798 | { |
---|
799 | action_debug(Tab_action, event, params, num_params); |
---|
800 | if (IN_ANSI) { |
---|
801 | net_sendc('\t'); |
---|
802 | return; |
---|
803 | } |
---|
804 | if (kybdlock) { |
---|
805 | enq_ta(Tab_action, CN, CN); |
---|
806 | return; |
---|
807 | } |
---|
808 | cursor_move(next_unprotected(cursor_addr)); |
---|
809 | } |
---|
810 | |
---|
811 | |
---|
812 | /* |
---|
813 | * Tab backward to previous field. |
---|
814 | */ |
---|
815 | /*ARGSUSED*/ |
---|
816 | void |
---|
817 | BackTab_action(w, event, params, num_params) |
---|
818 | Widget w; |
---|
819 | XEvent *event; |
---|
820 | String *params; |
---|
821 | Cardinal *num_params; |
---|
822 | { |
---|
823 | register int baddr, nbaddr; |
---|
824 | int sbaddr; |
---|
825 | |
---|
826 | action_debug(BackTab_action, event, params, num_params); |
---|
827 | if (!IN_3270) |
---|
828 | return; |
---|
829 | if (kybdlock) { |
---|
830 | enq_ta(BackTab_action, CN, CN); |
---|
831 | return; |
---|
832 | } |
---|
833 | baddr = cursor_addr; |
---|
834 | DEC_BA(baddr); |
---|
835 | if (IS_FA(screen_buf[baddr])) /* at bof */ |
---|
836 | DEC_BA(baddr); |
---|
837 | sbaddr = baddr; |
---|
838 | while (True) { |
---|
839 | nbaddr = baddr; |
---|
840 | INC_BA(nbaddr); |
---|
841 | if (IS_FA(screen_buf[baddr]) |
---|
842 | && !FA_IS_PROTECTED(screen_buf[baddr]) |
---|
843 | && !IS_FA(screen_buf[nbaddr])) |
---|
844 | break; |
---|
845 | DEC_BA(baddr); |
---|
846 | if (baddr == sbaddr) { |
---|
847 | cursor_move(0); |
---|
848 | return; |
---|
849 | } |
---|
850 | } |
---|
851 | INC_BA(baddr); |
---|
852 | cursor_move(baddr); |
---|
853 | } |
---|
854 | |
---|
855 | |
---|
856 | /* |
---|
857 | * Deferred keyboard unlock. |
---|
858 | */ |
---|
859 | |
---|
860 | /*ARGSUSED*/ |
---|
861 | static void |
---|
862 | defer_unlock(closure, id) |
---|
863 | XtPointer closure; |
---|
864 | XtIntervalId *id; |
---|
865 | { |
---|
866 | kybdlock_clr(KL_DEFERRED_UNLOCK, "defer_unlock"); |
---|
867 | status_reset(); |
---|
868 | if (CONNECTED) |
---|
869 | ps_process(); |
---|
870 | } |
---|
871 | |
---|
872 | /* |
---|
873 | * Reset keyboard lock. |
---|
874 | */ |
---|
875 | void |
---|
876 | do_reset(explicit) |
---|
877 | Boolean explicit; |
---|
878 | { |
---|
879 | /* |
---|
880 | * If explicit (from the keyboard) and there is typeahead or |
---|
881 | * a half-composed key, simply flush it. |
---|
882 | */ |
---|
883 | if (explicit) { |
---|
884 | Boolean half_reset = False; |
---|
885 | |
---|
886 | if (flush_ta()) |
---|
887 | half_reset = True; |
---|
888 | if (composing != NONE) { |
---|
889 | composing = NONE; |
---|
890 | status_compose(False, 0, KT_STD); |
---|
891 | half_reset = True; |
---|
892 | } |
---|
893 | if (half_reset) |
---|
894 | return; |
---|
895 | } |
---|
896 | |
---|
897 | /* Always clear insert mode. */ |
---|
898 | insert_mode(False); |
---|
899 | |
---|
900 | /* Otherwise, if not connect, reset is a no-op. */ |
---|
901 | if (!CONNECTED) |
---|
902 | return; |
---|
903 | |
---|
904 | /* |
---|
905 | * Remove any deferred keyboard unlock. We will either unlock the |
---|
906 | * keyboard now, or want to defer further into the future. |
---|
907 | */ |
---|
908 | if (kybdlock & KL_DEFERRED_UNLOCK) |
---|
909 | XtRemoveTimeOut(unlock_id); |
---|
910 | |
---|
911 | /* |
---|
912 | * If explicit (from the keyboard), unlock the keyboard now. |
---|
913 | * Otherwise (from the host), schedule a deferred keyboard unlock. |
---|
914 | */ |
---|
915 | if (explicit || ft_state != FT_NONE) { |
---|
916 | kybdlock_clr(-1, "do_reset"); |
---|
917 | } else if (kybdlock & |
---|
918 | (KL_DEFERRED_UNLOCK | KL_OIA_TWAIT | KL_OIA_LOCKED | KL_AWAITING_FIRST)) { |
---|
919 | kybdlock_clr(~KL_DEFERRED_UNLOCK, "do_reset"); |
---|
920 | kybdlock_set(KL_DEFERRED_UNLOCK, "do_reset"); |
---|
921 | unlock_id = XtAppAddTimeOut(appcontext, UNLOCK_MS, |
---|
922 | defer_unlock, 0); |
---|
923 | } |
---|
924 | |
---|
925 | /* Clean up other modes. */ |
---|
926 | status_reset(); |
---|
927 | mcursor_normal(); |
---|
928 | composing = NONE; |
---|
929 | status_compose(False, 0, KT_STD); |
---|
930 | } |
---|
931 | |
---|
932 | /*ARGSUSED*/ |
---|
933 | void |
---|
934 | Reset_action(w, event, params, num_params) |
---|
935 | Widget w; |
---|
936 | XEvent *event; |
---|
937 | String *params; |
---|
938 | Cardinal *num_params; |
---|
939 | { |
---|
940 | action_debug(Reset_action, event, params, num_params); |
---|
941 | do_reset(True); |
---|
942 | } |
---|
943 | |
---|
944 | |
---|
945 | /* |
---|
946 | * Move to first unprotected field on screen. |
---|
947 | */ |
---|
948 | /*ARGSUSED*/ |
---|
949 | void |
---|
950 | Home_action(w, event, params, num_params) |
---|
951 | Widget w; |
---|
952 | XEvent *event; |
---|
953 | String *params; |
---|
954 | Cardinal *num_params; |
---|
955 | { |
---|
956 | action_debug(Home_action, event, params, num_params); |
---|
957 | if (IN_ANSI) { |
---|
958 | ansi_send_home(); |
---|
959 | return; |
---|
960 | } |
---|
961 | if (kybdlock) { |
---|
962 | enq_ta(Home_action, CN, CN); |
---|
963 | return; |
---|
964 | } |
---|
965 | if (!formatted) { |
---|
966 | cursor_move(0); |
---|
967 | return; |
---|
968 | } |
---|
969 | cursor_move(next_unprotected(ROWS*COLS-1)); |
---|
970 | } |
---|
971 | |
---|
972 | |
---|
973 | /* |
---|
974 | * Cursor left 1 position. |
---|
975 | */ |
---|
976 | static void |
---|
977 | do_left() |
---|
978 | { |
---|
979 | register int baddr; |
---|
980 | |
---|
981 | baddr = cursor_addr; |
---|
982 | DEC_BA(baddr); |
---|
983 | cursor_move(baddr); |
---|
984 | } |
---|
985 | |
---|
986 | /*ARGSUSED*/ |
---|
987 | void |
---|
988 | Left_action(w, event, params, num_params) |
---|
989 | Widget w; |
---|
990 | XEvent *event; |
---|
991 | String *params; |
---|
992 | Cardinal *num_params; |
---|
993 | { |
---|
994 | action_debug(Left_action, event, params, num_params); |
---|
995 | if (IN_ANSI) { |
---|
996 | ansi_send_left(); |
---|
997 | return; |
---|
998 | } |
---|
999 | if (kybdlock) { |
---|
1000 | enq_ta(Left_action, CN, CN); |
---|
1001 | return; |
---|
1002 | } |
---|
1003 | if (!flipped) |
---|
1004 | do_left(); |
---|
1005 | else { |
---|
1006 | register int baddr; |
---|
1007 | |
---|
1008 | baddr = cursor_addr; |
---|
1009 | INC_BA(baddr); |
---|
1010 | cursor_move(baddr); |
---|
1011 | } |
---|
1012 | } |
---|
1013 | |
---|
1014 | |
---|
1015 | /* |
---|
1016 | * Delete char key. |
---|
1017 | * Returns "True" if succeeds, "False" otherwise. |
---|
1018 | */ |
---|
1019 | static Boolean |
---|
1020 | do_delete() |
---|
1021 | { |
---|
1022 | register int baddr, end_baddr; |
---|
1023 | register unsigned char *fa; |
---|
1024 | |
---|
1025 | baddr = cursor_addr; |
---|
1026 | fa = get_field_attribute(baddr); |
---|
1027 | if (FA_IS_PROTECTED(*fa) || IS_FA(screen_buf[baddr])) { |
---|
1028 | operator_error(KL_OERR_PROTECTED); |
---|
1029 | return False; |
---|
1030 | } |
---|
1031 | /* find next fa */ |
---|
1032 | end_baddr = baddr; |
---|
1033 | do { |
---|
1034 | INC_BA(end_baddr); |
---|
1035 | if (IS_FA(screen_buf[end_baddr])) |
---|
1036 | break; |
---|
1037 | } while (end_baddr != baddr); |
---|
1038 | DEC_BA(end_baddr); |
---|
1039 | if (end_baddr > baddr) { |
---|
1040 | ctlr_bcopy(baddr+1, baddr, end_baddr - baddr, 0); |
---|
1041 | } else if (end_baddr != baddr) { |
---|
1042 | ctlr_bcopy(baddr+1, baddr, ((ROWS * COLS) - 1) - baddr, 0); |
---|
1043 | ctlr_add((ROWS * COLS) - 1, screen_buf[0], 0); |
---|
1044 | ctlr_bcopy(1, 0, end_baddr, 0); |
---|
1045 | } |
---|
1046 | ctlr_add(end_baddr, CG_null, 0); |
---|
1047 | mdt_set(fa); |
---|
1048 | return True; |
---|
1049 | } |
---|
1050 | |
---|
1051 | /*ARGSUSED*/ |
---|
1052 | void |
---|
1053 | Delete_action(w, event, params, num_params) |
---|
1054 | Widget w; |
---|
1055 | XEvent *event; |
---|
1056 | String *params; |
---|
1057 | Cardinal *num_params; |
---|
1058 | { |
---|
1059 | action_debug(Delete_action, event, params, num_params); |
---|
1060 | if (IN_ANSI) { |
---|
1061 | net_sendc('\177'); |
---|
1062 | return; |
---|
1063 | } |
---|
1064 | if (kybdlock) { |
---|
1065 | enq_ta(Delete_action, CN, CN); |
---|
1066 | return; |
---|
1067 | } |
---|
1068 | if (!do_delete()) |
---|
1069 | return; |
---|
1070 | if (reverse) { |
---|
1071 | int baddr = cursor_addr; |
---|
1072 | |
---|
1073 | DEC_BA(baddr); |
---|
1074 | if (!IS_FA(screen_buf[baddr])) |
---|
1075 | cursor_move(baddr); |
---|
1076 | } |
---|
1077 | } |
---|
1078 | |
---|
1079 | |
---|
1080 | /* |
---|
1081 | * Backspace. |
---|
1082 | */ |
---|
1083 | /*ARGSUSED*/ |
---|
1084 | void |
---|
1085 | BackSpace_action(w, event, params, num_params) |
---|
1086 | Widget w; |
---|
1087 | XEvent *event; |
---|
1088 | String *params; |
---|
1089 | Cardinal *num_params; |
---|
1090 | { |
---|
1091 | action_debug(BackSpace_action, event, params, num_params); |
---|
1092 | if (IN_ANSI) { |
---|
1093 | net_send_erase(); |
---|
1094 | } else { |
---|
1095 | if (kybdlock) { |
---|
1096 | enq_ta(BackSpace_action, CN, CN); |
---|
1097 | return; |
---|
1098 | } |
---|
1099 | if (reverse) |
---|
1100 | (void) do_delete(); |
---|
1101 | else if (!flipped) |
---|
1102 | do_left(); |
---|
1103 | else { |
---|
1104 | register int baddr; |
---|
1105 | |
---|
1106 | baddr = cursor_addr; |
---|
1107 | INC_BA(baddr); |
---|
1108 | cursor_move(baddr); |
---|
1109 | } |
---|
1110 | } |
---|
1111 | } |
---|
1112 | |
---|
1113 | |
---|
1114 | /* |
---|
1115 | * Destructive backspace, like Unix "erase". |
---|
1116 | */ |
---|
1117 | /*ARGSUSED*/ |
---|
1118 | void |
---|
1119 | Erase_action(w, event, params, num_params) |
---|
1120 | Widget w; |
---|
1121 | XEvent *event; |
---|
1122 | String *params; |
---|
1123 | Cardinal *num_params; |
---|
1124 | { |
---|
1125 | int baddr; |
---|
1126 | unsigned char *fa; |
---|
1127 | |
---|
1128 | action_debug(Erase_action, event, params, num_params); |
---|
1129 | if (IN_ANSI) { |
---|
1130 | net_send_erase(); |
---|
1131 | return; |
---|
1132 | } |
---|
1133 | if (kybdlock) { |
---|
1134 | enq_ta(Erase_action, CN, CN); |
---|
1135 | return; |
---|
1136 | } |
---|
1137 | baddr = cursor_addr; |
---|
1138 | fa = get_field_attribute(baddr); |
---|
1139 | if (fa == &screen_buf[baddr] || FA_IS_PROTECTED(*fa)) { |
---|
1140 | operator_error(KL_OERR_PROTECTED); |
---|
1141 | return; |
---|
1142 | } |
---|
1143 | if (baddr && fa == &screen_buf[baddr - 1]) |
---|
1144 | return; |
---|
1145 | do_left(); |
---|
1146 | (void) do_delete(); |
---|
1147 | } |
---|
1148 | |
---|
1149 | |
---|
1150 | /* |
---|
1151 | * Cursor right 1 position. |
---|
1152 | */ |
---|
1153 | /*ARGSUSED*/ |
---|
1154 | void |
---|
1155 | Right_action(w, event, params, num_params) |
---|
1156 | Widget w; |
---|
1157 | XEvent *event; |
---|
1158 | String *params; |
---|
1159 | Cardinal *num_params; |
---|
1160 | { |
---|
1161 | register int baddr; |
---|
1162 | |
---|
1163 | action_debug(Right_action, event, params, num_params); |
---|
1164 | if (IN_ANSI) { |
---|
1165 | ansi_send_right(); |
---|
1166 | return; |
---|
1167 | } |
---|
1168 | if (kybdlock) { |
---|
1169 | enq_ta(Right_action, CN, CN); |
---|
1170 | return; |
---|
1171 | } |
---|
1172 | if (!flipped) { |
---|
1173 | baddr = cursor_addr; |
---|
1174 | INC_BA(baddr); |
---|
1175 | cursor_move(baddr); |
---|
1176 | } else |
---|
1177 | do_left(); |
---|
1178 | } |
---|
1179 | |
---|
1180 | |
---|
1181 | /* |
---|
1182 | * Cursor left 2 positions. |
---|
1183 | */ |
---|
1184 | /*ARGSUSED*/ |
---|
1185 | void |
---|
1186 | Left2_action(w, event, params, num_params) |
---|
1187 | Widget w; |
---|
1188 | XEvent *event; |
---|
1189 | String *params; |
---|
1190 | Cardinal *num_params; |
---|
1191 | { |
---|
1192 | register int baddr; |
---|
1193 | |
---|
1194 | action_debug(Left2_action, event, params, num_params); |
---|
1195 | if (IN_ANSI) |
---|
1196 | return; |
---|
1197 | if (kybdlock) { |
---|
1198 | enq_ta(Left2_action, CN, CN); |
---|
1199 | return; |
---|
1200 | } |
---|
1201 | baddr = cursor_addr; |
---|
1202 | DEC_BA(baddr); |
---|
1203 | DEC_BA(baddr); |
---|
1204 | cursor_move(baddr); |
---|
1205 | } |
---|
1206 | |
---|
1207 | |
---|
1208 | /* |
---|
1209 | * Cursor to previous word. |
---|
1210 | */ |
---|
1211 | /*ARGSUSED*/ |
---|
1212 | void |
---|
1213 | PreviousWord_action(w, event, params, num_params) |
---|
1214 | Widget w; |
---|
1215 | XEvent *event; |
---|
1216 | String *params; |
---|
1217 | Cardinal *num_params; |
---|
1218 | { |
---|
1219 | register int baddr; |
---|
1220 | int baddr0; |
---|
1221 | unsigned char c; |
---|
1222 | Boolean prot; |
---|
1223 | |
---|
1224 | action_debug(PreviousWord_action, event, params, num_params); |
---|
1225 | if (IN_ANSI) |
---|
1226 | return; |
---|
1227 | if (kybdlock) { |
---|
1228 | enq_ta(PreviousWord_action, CN, CN); |
---|
1229 | return; |
---|
1230 | } |
---|
1231 | if (!formatted) |
---|
1232 | return; |
---|
1233 | |
---|
1234 | baddr = cursor_addr; |
---|
1235 | prot = FA_IS_PROTECTED(*get_field_attribute(baddr)); |
---|
1236 | |
---|
1237 | /* Skip to before this word, if in one now. */ |
---|
1238 | if (!prot) { |
---|
1239 | c = screen_buf[baddr]; |
---|
1240 | while (!IS_FA(c) && c != CG_space && c != CG_null) { |
---|
1241 | DEC_BA(baddr); |
---|
1242 | if (baddr == cursor_addr) |
---|
1243 | return; |
---|
1244 | c = screen_buf[baddr]; |
---|
1245 | } |
---|
1246 | } |
---|
1247 | baddr0 = baddr; |
---|
1248 | |
---|
1249 | /* Find the end of the preceding word. */ |
---|
1250 | do { |
---|
1251 | c = screen_buf[baddr]; |
---|
1252 | if (IS_FA(c)) { |
---|
1253 | DEC_BA(baddr); |
---|
1254 | prot = FA_IS_PROTECTED(*get_field_attribute(baddr)); |
---|
1255 | continue; |
---|
1256 | } |
---|
1257 | if (!prot && c != CG_space && c != CG_null) |
---|
1258 | break; |
---|
1259 | DEC_BA(baddr); |
---|
1260 | } while (baddr != baddr0); |
---|
1261 | |
---|
1262 | if (baddr == baddr0) |
---|
1263 | return; |
---|
1264 | |
---|
1265 | /* Go it its front. */ |
---|
1266 | for (;;) { |
---|
1267 | DEC_BA(baddr); |
---|
1268 | c = screen_buf[baddr]; |
---|
1269 | if (IS_FA(c) || c == CG_space || c == CG_null) { |
---|
1270 | break; |
---|
1271 | } |
---|
1272 | } |
---|
1273 | INC_BA(baddr); |
---|
1274 | cursor_move(baddr); |
---|
1275 | } |
---|
1276 | |
---|
1277 | |
---|
1278 | /* |
---|
1279 | * Cursor right 2 positions. |
---|
1280 | */ |
---|
1281 | /*ARGSUSED*/ |
---|
1282 | void |
---|
1283 | Right2_action(w, event, params, num_params) |
---|
1284 | Widget w; |
---|
1285 | XEvent *event; |
---|
1286 | String *params; |
---|
1287 | Cardinal *num_params; |
---|
1288 | { |
---|
1289 | register int baddr; |
---|
1290 | |
---|
1291 | action_debug(Right2_action, event, params, num_params); |
---|
1292 | if (IN_ANSI) |
---|
1293 | return; |
---|
1294 | if (kybdlock) { |
---|
1295 | enq_ta(Right2_action, CN, CN); |
---|
1296 | return; |
---|
1297 | } |
---|
1298 | baddr = cursor_addr; |
---|
1299 | INC_BA(baddr); |
---|
1300 | INC_BA(baddr); |
---|
1301 | cursor_move(baddr); |
---|
1302 | } |
---|
1303 | |
---|
1304 | |
---|
1305 | /* Find the next unprotected word, or -1 */ |
---|
1306 | static int |
---|
1307 | nu_word(baddr) |
---|
1308 | int baddr; |
---|
1309 | { |
---|
1310 | int baddr0 = baddr; |
---|
1311 | unsigned char c; |
---|
1312 | Boolean prot; |
---|
1313 | |
---|
1314 | prot = FA_IS_PROTECTED(*get_field_attribute(baddr)); |
---|
1315 | |
---|
1316 | do { |
---|
1317 | c = screen_buf[baddr]; |
---|
1318 | if (IS_FA(c)) |
---|
1319 | prot = FA_IS_PROTECTED(c); |
---|
1320 | else if (!prot && c != CG_space && c != CG_null) |
---|
1321 | return baddr; |
---|
1322 | INC_BA(baddr); |
---|
1323 | } while (baddr != baddr0); |
---|
1324 | |
---|
1325 | return -1; |
---|
1326 | } |
---|
1327 | |
---|
1328 | /* Find the next word in this field, or -1 */ |
---|
1329 | static int |
---|
1330 | nt_word(baddr) |
---|
1331 | int baddr; |
---|
1332 | { |
---|
1333 | int baddr0 = baddr; |
---|
1334 | unsigned char c; |
---|
1335 | Boolean in_word = True; |
---|
1336 | |
---|
1337 | do { |
---|
1338 | c = screen_buf[baddr]; |
---|
1339 | if (IS_FA(c)) |
---|
1340 | return -1; |
---|
1341 | if (in_word) { |
---|
1342 | if (c == CG_space || c == CG_null) |
---|
1343 | in_word = False; |
---|
1344 | } else { |
---|
1345 | if (c != CG_space && c != CG_null) |
---|
1346 | return baddr; |
---|
1347 | } |
---|
1348 | INC_BA(baddr); |
---|
1349 | } while (baddr != baddr0); |
---|
1350 | |
---|
1351 | return -1; |
---|
1352 | } |
---|
1353 | |
---|
1354 | |
---|
1355 | /* |
---|
1356 | * Cursor to next unprotected word. |
---|
1357 | */ |
---|
1358 | /*ARGSUSED*/ |
---|
1359 | void |
---|
1360 | NextWord_action(w, event, params, num_params) |
---|
1361 | Widget w; |
---|
1362 | XEvent *event; |
---|
1363 | String *params; |
---|
1364 | Cardinal *num_params; |
---|
1365 | { |
---|
1366 | register int baddr; |
---|
1367 | unsigned char c; |
---|
1368 | |
---|
1369 | action_debug(NextWord_action, event, params, num_params); |
---|
1370 | if (IN_ANSI) |
---|
1371 | return; |
---|
1372 | if (kybdlock) { |
---|
1373 | enq_ta(NextWord_action, CN, CN); |
---|
1374 | return; |
---|
1375 | } |
---|
1376 | if (!formatted) |
---|
1377 | return; |
---|
1378 | |
---|
1379 | /* If not in an unprotected field, go to the next unprotected word. */ |
---|
1380 | if (IS_FA(screen_buf[cursor_addr]) || |
---|
1381 | FA_IS_PROTECTED(*get_field_attribute(cursor_addr))) { |
---|
1382 | baddr = nu_word(cursor_addr); |
---|
1383 | if (baddr != -1) |
---|
1384 | cursor_move(baddr); |
---|
1385 | return; |
---|
1386 | } |
---|
1387 | |
---|
1388 | /* If there's another word in this field, go to it. */ |
---|
1389 | baddr = nt_word(cursor_addr); |
---|
1390 | if (baddr != -1) { |
---|
1391 | cursor_move(baddr); |
---|
1392 | return; |
---|
1393 | } |
---|
1394 | |
---|
1395 | /* If in a word, go to just after its end. */ |
---|
1396 | c = screen_buf[cursor_addr]; |
---|
1397 | if (c != CG_space && c != CG_null) { |
---|
1398 | baddr = cursor_addr; |
---|
1399 | do { |
---|
1400 | c = screen_buf[baddr]; |
---|
1401 | if (c == CG_space || c == CG_null) { |
---|
1402 | cursor_move(baddr); |
---|
1403 | return; |
---|
1404 | } else if (IS_FA(c)) { |
---|
1405 | baddr = nu_word(baddr); |
---|
1406 | if (baddr != -1) |
---|
1407 | cursor_move(baddr); |
---|
1408 | return; |
---|
1409 | } |
---|
1410 | INC_BA(baddr); |
---|
1411 | } while (baddr != cursor_addr); |
---|
1412 | } |
---|
1413 | /* Otherwise, go to the next unprotected word. */ |
---|
1414 | else { |
---|
1415 | baddr = nu_word(cursor_addr); |
---|
1416 | if (baddr != -1) |
---|
1417 | cursor_move(baddr); |
---|
1418 | } |
---|
1419 | } |
---|
1420 | |
---|
1421 | |
---|
1422 | /* |
---|
1423 | * Cursor up 1 position. |
---|
1424 | */ |
---|
1425 | /*ARGSUSED*/ |
---|
1426 | void |
---|
1427 | Up_action(w, event, params, num_params) |
---|
1428 | Widget w; |
---|
1429 | XEvent *event; |
---|
1430 | String *params; |
---|
1431 | Cardinal *num_params; |
---|
1432 | { |
---|
1433 | register int baddr; |
---|
1434 | |
---|
1435 | action_debug(Up_action, event, params, num_params); |
---|
1436 | if (IN_ANSI) { |
---|
1437 | ansi_send_up(); |
---|
1438 | return; |
---|
1439 | } |
---|
1440 | if (kybdlock) { |
---|
1441 | enq_ta(Up_action, CN, CN); |
---|
1442 | return; |
---|
1443 | } |
---|
1444 | baddr = cursor_addr - COLS; |
---|
1445 | if (baddr < 0) |
---|
1446 | baddr = (cursor_addr + (ROWS * COLS)) - COLS; |
---|
1447 | cursor_move(baddr); |
---|
1448 | } |
---|
1449 | |
---|
1450 | |
---|
1451 | /* |
---|
1452 | * Cursor down 1 position. |
---|
1453 | */ |
---|
1454 | /*ARGSUSED*/ |
---|
1455 | void |
---|
1456 | Down_action(w, event, params, num_params) |
---|
1457 | Widget w; |
---|
1458 | XEvent *event; |
---|
1459 | String *params; |
---|
1460 | Cardinal *num_params; |
---|
1461 | { |
---|
1462 | register int baddr; |
---|
1463 | |
---|
1464 | action_debug(Down_action, event, params, num_params); |
---|
1465 | if (IN_ANSI) { |
---|
1466 | ansi_send_down(); |
---|
1467 | return; |
---|
1468 | } |
---|
1469 | if (kybdlock) { |
---|
1470 | enq_ta(Down_action, CN, CN); |
---|
1471 | return; |
---|
1472 | } |
---|
1473 | baddr = (cursor_addr + COLS) % (COLS * ROWS); |
---|
1474 | cursor_move(baddr); |
---|
1475 | } |
---|
1476 | |
---|
1477 | |
---|
1478 | /* |
---|
1479 | * Cursor to first field on next line or any lines after that. |
---|
1480 | */ |
---|
1481 | /*ARGSUSED*/ |
---|
1482 | void |
---|
1483 | Newline_action(w, event, params, num_params) |
---|
1484 | Widget w; |
---|
1485 | XEvent *event; |
---|
1486 | String *params; |
---|
1487 | Cardinal *num_params; |
---|
1488 | { |
---|
1489 | register int baddr; |
---|
1490 | register unsigned char *fa; |
---|
1491 | |
---|
1492 | action_debug(Newline_action, event, params, num_params); |
---|
1493 | if (IN_ANSI) { |
---|
1494 | net_sendc('\n'); |
---|
1495 | return; |
---|
1496 | } |
---|
1497 | if (kybdlock) { |
---|
1498 | enq_ta(Newline_action, CN, CN); |
---|
1499 | return; |
---|
1500 | } |
---|
1501 | baddr = (cursor_addr + COLS) % (COLS * ROWS); /* down */ |
---|
1502 | baddr = (baddr / COLS) * COLS; /* 1st col */ |
---|
1503 | fa = get_field_attribute(baddr); |
---|
1504 | if (fa != (&screen_buf[baddr]) && !FA_IS_PROTECTED(*fa)) |
---|
1505 | cursor_move(baddr); |
---|
1506 | else |
---|
1507 | cursor_move(next_unprotected(baddr)); |
---|
1508 | } |
---|
1509 | |
---|
1510 | |
---|
1511 | /* |
---|
1512 | * DUP key |
---|
1513 | */ |
---|
1514 | /*ARGSUSED*/ |
---|
1515 | void |
---|
1516 | Dup_action(w, event, params, num_params) |
---|
1517 | Widget w; |
---|
1518 | XEvent *event; |
---|
1519 | String *params; |
---|
1520 | Cardinal *num_params; |
---|
1521 | { |
---|
1522 | action_debug(Dup_action, event, params, num_params); |
---|
1523 | if (IN_ANSI) |
---|
1524 | return; |
---|
1525 | if (kybdlock) { |
---|
1526 | enq_ta(Dup_action, CN, CN); |
---|
1527 | return; |
---|
1528 | } |
---|
1529 | if (key_Character(CG_dup, False)) |
---|
1530 | cursor_move(next_unprotected(cursor_addr)); |
---|
1531 | } |
---|
1532 | |
---|
1533 | |
---|
1534 | /* |
---|
1535 | * FM key |
---|
1536 | */ |
---|
1537 | /*ARGSUSED*/ |
---|
1538 | void |
---|
1539 | FieldMark_action(w, event, params, num_params) |
---|
1540 | Widget w; |
---|
1541 | XEvent *event; |
---|
1542 | String *params; |
---|
1543 | Cardinal *num_params; |
---|
1544 | { |
---|
1545 | action_debug(FieldMark_action, event, params, num_params); |
---|
1546 | if (IN_ANSI) |
---|
1547 | return; |
---|
1548 | if (kybdlock) { |
---|
1549 | enq_ta(FieldMark_action, CN, CN); |
---|
1550 | return; |
---|
1551 | } |
---|
1552 | (void) key_Character(CG_fm, False); |
---|
1553 | } |
---|
1554 | |
---|
1555 | |
---|
1556 | /* |
---|
1557 | * Vanilla AID keys. |
---|
1558 | */ |
---|
1559 | /*ARGSUSED*/ |
---|
1560 | void |
---|
1561 | Enter_action(w, event, params, num_params) |
---|
1562 | Widget w; |
---|
1563 | XEvent *event; |
---|
1564 | String *params; |
---|
1565 | Cardinal *num_params; |
---|
1566 | { |
---|
1567 | action_debug(Enter_action, event, params, num_params); |
---|
1568 | if (kybdlock) |
---|
1569 | enq_ta(Enter_action, CN, CN); |
---|
1570 | else |
---|
1571 | key_AID(AID_ENTER); |
---|
1572 | } |
---|
1573 | |
---|
1574 | |
---|
1575 | /*ARGSUSED*/ |
---|
1576 | void |
---|
1577 | SysReq_action(w, event, params, num_params) |
---|
1578 | Widget w; |
---|
1579 | XEvent *event; |
---|
1580 | String *params; |
---|
1581 | Cardinal *num_params; |
---|
1582 | { |
---|
1583 | action_debug(SysReq_action, event, params, num_params); |
---|
1584 | if (kybdlock) |
---|
1585 | enq_ta(SysReq_action, CN, CN); |
---|
1586 | else |
---|
1587 | key_AID(AID_SYSREQ); |
---|
1588 | } |
---|
1589 | |
---|
1590 | |
---|
1591 | /* |
---|
1592 | * Clear AID key |
---|
1593 | */ |
---|
1594 | /*ARGSUSED*/ |
---|
1595 | void |
---|
1596 | Clear_action(w, event, params, num_params) |
---|
1597 | Widget w; |
---|
1598 | XEvent *event; |
---|
1599 | String *params; |
---|
1600 | Cardinal *num_params; |
---|
1601 | { |
---|
1602 | action_debug(Clear_action, event, params, num_params); |
---|
1603 | if (IN_ANSI) { |
---|
1604 | ansi_send_clear(); |
---|
1605 | return; |
---|
1606 | } |
---|
1607 | if (kybdlock && CONNECTED) { |
---|
1608 | enq_ta(Clear_action, CN, CN); |
---|
1609 | return; |
---|
1610 | } |
---|
1611 | buffer_addr = 0; |
---|
1612 | ctlr_clear(True); |
---|
1613 | cursor_move(0); |
---|
1614 | if (CONNECTED) |
---|
1615 | key_AID(AID_CLEAR); |
---|
1616 | } |
---|
1617 | |
---|
1618 | |
---|
1619 | /* |
---|
1620 | * Cursor Select key (light pen simulator). |
---|
1621 | */ |
---|
1622 | /*ARGSUSED*/ |
---|
1623 | void |
---|
1624 | CursorSelect_action(w, event, params, num_params) |
---|
1625 | Widget w; |
---|
1626 | XEvent *event; |
---|
1627 | String *params; |
---|
1628 | Cardinal *num_params; |
---|
1629 | { |
---|
1630 | register unsigned char *fa, *sel; |
---|
1631 | |
---|
1632 | action_debug(CursorSelect_action, event, params, num_params); |
---|
1633 | if (IN_ANSI) |
---|
1634 | return; |
---|
1635 | if (kybdlock) { |
---|
1636 | enq_ta(CursorSelect_action, CN, CN); |
---|
1637 | return; |
---|
1638 | } |
---|
1639 | fa = get_field_attribute(cursor_addr); |
---|
1640 | if (!FA_IS_SELECTABLE(*fa)) { |
---|
1641 | operator_error(KL_OERR_PROTECTED); |
---|
1642 | return; |
---|
1643 | } |
---|
1644 | sel = fa + 1; |
---|
1645 | switch (*sel) { |
---|
1646 | case CG_greater: /* > */ |
---|
1647 | ctlr_add(cursor_addr, CG_question, 0); /* change to ? */ |
---|
1648 | mdt_clear(fa); |
---|
1649 | break; |
---|
1650 | case CG_question: /* ? */ |
---|
1651 | ctlr_add(cursor_addr, CG_greater, 0); /* change to > */ |
---|
1652 | mdt_set(fa); |
---|
1653 | break; |
---|
1654 | case CG_space: /* space */ |
---|
1655 | case CG_null: /* null */ |
---|
1656 | mdt_set(fa); |
---|
1657 | key_AID(AID_SELECT); |
---|
1658 | break; |
---|
1659 | case CG_ampersand: /* & */ |
---|
1660 | mdt_set(fa); |
---|
1661 | key_AID(AID_ENTER); |
---|
1662 | break; |
---|
1663 | default: |
---|
1664 | operator_error(KL_OERR_PROTECTED); |
---|
1665 | } |
---|
1666 | } |
---|
1667 | |
---|
1668 | |
---|
1669 | /* |
---|
1670 | * Erase End Of Field Key. |
---|
1671 | */ |
---|
1672 | /*ARGSUSED*/ |
---|
1673 | void |
---|
1674 | EraseEOF_action(w, event, params, num_params) |
---|
1675 | Widget w; |
---|
1676 | XEvent *event; |
---|
1677 | String *params; |
---|
1678 | Cardinal *num_params; |
---|
1679 | { |
---|
1680 | register int baddr; |
---|
1681 | register unsigned char *fa; |
---|
1682 | |
---|
1683 | action_debug(EraseEOF_action, event, params, num_params); |
---|
1684 | if (IN_ANSI) |
---|
1685 | return; |
---|
1686 | if (kybdlock) { |
---|
1687 | enq_ta(EraseEOF_action, CN, CN); |
---|
1688 | return; |
---|
1689 | } |
---|
1690 | baddr = cursor_addr; |
---|
1691 | fa = get_field_attribute(baddr); |
---|
1692 | if (FA_IS_PROTECTED(*fa) || IS_FA(screen_buf[baddr])) { |
---|
1693 | operator_error(KL_OERR_PROTECTED); |
---|
1694 | return; |
---|
1695 | } |
---|
1696 | if (formatted) { /* erase to next field attribute */ |
---|
1697 | do { |
---|
1698 | ctlr_add(baddr, CG_null, 0); |
---|
1699 | INC_BA(baddr); |
---|
1700 | } while (!IS_FA(screen_buf[baddr])); |
---|
1701 | mdt_set(fa); |
---|
1702 | } else { /* erase to end of screen */ |
---|
1703 | do { |
---|
1704 | ctlr_add(baddr, CG_null, 0); |
---|
1705 | INC_BA(baddr); |
---|
1706 | } while (baddr != 0); |
---|
1707 | } |
---|
1708 | } |
---|
1709 | |
---|
1710 | |
---|
1711 | /* |
---|
1712 | * Erase all Input Key. |
---|
1713 | */ |
---|
1714 | /*ARGSUSED*/ |
---|
1715 | void |
---|
1716 | EraseInput_action(w, event, params, num_params) |
---|
1717 | Widget w; |
---|
1718 | XEvent *event; |
---|
1719 | String *params; |
---|
1720 | Cardinal *num_params; |
---|
1721 | { |
---|
1722 | register int baddr, sbaddr; |
---|
1723 | unsigned char fa; |
---|
1724 | Boolean f; |
---|
1725 | |
---|
1726 | action_debug(EraseInput_action, event, params, num_params); |
---|
1727 | if (IN_ANSI) |
---|
1728 | return; |
---|
1729 | if (kybdlock) { |
---|
1730 | enq_ta(EraseInput_action, CN, CN); |
---|
1731 | return; |
---|
1732 | } |
---|
1733 | if (formatted) { |
---|
1734 | /* find first field attribute */ |
---|
1735 | baddr = 0; |
---|
1736 | do { |
---|
1737 | if (IS_FA(screen_buf[baddr])) |
---|
1738 | break; |
---|
1739 | INC_BA(baddr); |
---|
1740 | } while (baddr != 0); |
---|
1741 | sbaddr = baddr; |
---|
1742 | f = False; |
---|
1743 | do { |
---|
1744 | fa = screen_buf[baddr]; |
---|
1745 | if (!FA_IS_PROTECTED(fa)) { |
---|
1746 | mdt_clear(&screen_buf[baddr]); |
---|
1747 | do { |
---|
1748 | INC_BA(baddr); |
---|
1749 | if (!f) { |
---|
1750 | cursor_move(baddr); |
---|
1751 | f = True; |
---|
1752 | } |
---|
1753 | if (!IS_FA(screen_buf[baddr])) { |
---|
1754 | ctlr_add(baddr, CG_null, 0); |
---|
1755 | } |
---|
1756 | } while (!IS_FA(screen_buf[baddr])); |
---|
1757 | } else { /* skip protected */ |
---|
1758 | do { |
---|
1759 | INC_BA(baddr); |
---|
1760 | } while (!IS_FA(screen_buf[baddr])); |
---|
1761 | } |
---|
1762 | } while (baddr != sbaddr); |
---|
1763 | if (!f) |
---|
1764 | cursor_move(0); |
---|
1765 | } else { |
---|
1766 | ctlr_clear(True); |
---|
1767 | cursor_move(0); |
---|
1768 | } |
---|
1769 | } |
---|
1770 | |
---|
1771 | |
---|
1772 | |
---|
1773 | /* |
---|
1774 | * Delete word key. Backspaces the cursor until it hits the front of a word, |
---|
1775 | * deletes characters until it hits a blank or null, and deletes all of these |
---|
1776 | * but the last. |
---|
1777 | * |
---|
1778 | * Which is to say, does a ^W. |
---|
1779 | */ |
---|
1780 | /*ARGSUSED*/ |
---|
1781 | void |
---|
1782 | DeleteWord_action(w, event, params, num_params) |
---|
1783 | Widget w; |
---|
1784 | XEvent *event; |
---|
1785 | String *params; |
---|
1786 | Cardinal *num_params; |
---|
1787 | { |
---|
1788 | register int baddr, baddr2, front_baddr, back_baddr, end_baddr; |
---|
1789 | register unsigned char *fa; |
---|
1790 | |
---|
1791 | action_debug(DeleteWord_action, event, params, num_params); |
---|
1792 | if (IN_ANSI) { |
---|
1793 | net_send_werase(); |
---|
1794 | return; |
---|
1795 | } |
---|
1796 | if (kybdlock) { |
---|
1797 | enq_ta(DeleteWord_action, CN, CN); |
---|
1798 | return; |
---|
1799 | } |
---|
1800 | if (!formatted) |
---|
1801 | return; |
---|
1802 | |
---|
1803 | baddr = cursor_addr; |
---|
1804 | fa = get_field_attribute(baddr); |
---|
1805 | |
---|
1806 | /* Make sure we're on a modifiable field. */ |
---|
1807 | if (FA_IS_PROTECTED(*fa) || IS_FA(screen_buf[baddr])) { |
---|
1808 | operator_error(KL_OERR_PROTECTED); |
---|
1809 | return; |
---|
1810 | } |
---|
1811 | |
---|
1812 | /* Search backwards for a non-blank character. */ |
---|
1813 | front_baddr = baddr; |
---|
1814 | while (screen_buf[front_baddr] == CG_space || |
---|
1815 | screen_buf[front_baddr] == CG_null) |
---|
1816 | DEC_BA(front_baddr); |
---|
1817 | |
---|
1818 | /* If we ran into the edge of the field without seeing any non-blanks, |
---|
1819 | there isn't any word to delete; just move the cursor. */ |
---|
1820 | if (IS_FA(screen_buf[front_baddr])) { |
---|
1821 | cursor_move(front_baddr+1); |
---|
1822 | return; |
---|
1823 | } |
---|
1824 | |
---|
1825 | /* front_baddr is now pointing at a non-blank character. Now search |
---|
1826 | for the first blank to the left of that (or the edge of the field), |
---|
1827 | leaving front_baddr pointing at the the beginning of the word. */ |
---|
1828 | while (!IS_FA(screen_buf[front_baddr]) && |
---|
1829 | screen_buf[front_baddr] != CG_space && |
---|
1830 | screen_buf[front_baddr] != CG_null) |
---|
1831 | DEC_BA(front_baddr); |
---|
1832 | INC_BA(front_baddr); |
---|
1833 | |
---|
1834 | /* Find the end of the word, searching forward for the edge of the |
---|
1835 | field or a non-blank. */ |
---|
1836 | back_baddr = front_baddr; |
---|
1837 | while (!IS_FA(screen_buf[back_baddr]) && |
---|
1838 | screen_buf[back_baddr] != CG_space && |
---|
1839 | screen_buf[back_baddr] != CG_null) |
---|
1840 | INC_BA(back_baddr); |
---|
1841 | |
---|
1842 | /* Find the start of the next word, leaving back_baddr pointing at it |
---|
1843 | or at the end of the field. */ |
---|
1844 | while (screen_buf[back_baddr] == CG_space || |
---|
1845 | screen_buf[back_baddr] == CG_null) |
---|
1846 | INC_BA(back_baddr); |
---|
1847 | |
---|
1848 | /* Find the end of the field, leaving end_baddr pointing at the field |
---|
1849 | attribute of the start of the next field. */ |
---|
1850 | end_baddr = back_baddr; |
---|
1851 | while (!IS_FA(screen_buf[end_baddr])) |
---|
1852 | INC_BA(end_baddr); |
---|
1853 | |
---|
1854 | /* Copy any text to the right of the word we are deleting. */ |
---|
1855 | baddr = front_baddr; |
---|
1856 | baddr2 = back_baddr; |
---|
1857 | while (baddr2 != end_baddr) { |
---|
1858 | ctlr_add(baddr, screen_buf[baddr2], 0); |
---|
1859 | INC_BA(baddr); |
---|
1860 | INC_BA(baddr2); |
---|
1861 | } |
---|
1862 | |
---|
1863 | /* Insert nulls to pad out the end of the field. */ |
---|
1864 | while (baddr != end_baddr) { |
---|
1865 | ctlr_add(baddr, CG_null, 0); |
---|
1866 | INC_BA(baddr); |
---|
1867 | } |
---|
1868 | |
---|
1869 | /* Set the MDT and move the cursor. */ |
---|
1870 | mdt_set(fa); |
---|
1871 | cursor_move(front_baddr); |
---|
1872 | } |
---|
1873 | |
---|
1874 | |
---|
1875 | |
---|
1876 | /* |
---|
1877 | * Delete field key. Similar to EraseEOF, but it wipes out the entire field |
---|
1878 | * rather than just to the right of the cursor, and it leaves the cursor at |
---|
1879 | * the front of the field. |
---|
1880 | * |
---|
1881 | * Which is to say, does a ^U. |
---|
1882 | */ |
---|
1883 | /*ARGSUSED*/ |
---|
1884 | void |
---|
1885 | DeleteField_action(w, event, params, num_params) |
---|
1886 | Widget w; |
---|
1887 | XEvent *event; |
---|
1888 | String *params; |
---|
1889 | Cardinal *num_params; |
---|
1890 | { |
---|
1891 | register int baddr; |
---|
1892 | register unsigned char *fa; |
---|
1893 | |
---|
1894 | action_debug(DeleteField_action, event, params, num_params); |
---|
1895 | if (IN_ANSI) { |
---|
1896 | net_send_kill(); |
---|
1897 | return; |
---|
1898 | } |
---|
1899 | if (kybdlock) { |
---|
1900 | enq_ta(DeleteField_action, CN, CN); |
---|
1901 | return; |
---|
1902 | } |
---|
1903 | if (!formatted) |
---|
1904 | return; |
---|
1905 | |
---|
1906 | baddr = cursor_addr; |
---|
1907 | fa = get_field_attribute(baddr); |
---|
1908 | if (FA_IS_PROTECTED(*fa) || IS_FA(screen_buf[baddr])) { |
---|
1909 | operator_error(KL_OERR_PROTECTED); |
---|
1910 | return; |
---|
1911 | } |
---|
1912 | while (!IS_FA(screen_buf[baddr])) |
---|
1913 | DEC_BA(baddr); |
---|
1914 | INC_BA(baddr); |
---|
1915 | cursor_move(baddr); |
---|
1916 | while (!IS_FA(screen_buf[baddr])) { |
---|
1917 | ctlr_add(baddr, CG_null, 0); |
---|
1918 | INC_BA(baddr); |
---|
1919 | } |
---|
1920 | mdt_set(fa); |
---|
1921 | } |
---|
1922 | |
---|
1923 | |
---|
1924 | |
---|
1925 | /* |
---|
1926 | * Set insert mode key. |
---|
1927 | */ |
---|
1928 | /*ARGSUSED*/ |
---|
1929 | void |
---|
1930 | Insert_action(w, event, params, num_params) |
---|
1931 | Widget w; |
---|
1932 | XEvent *event; |
---|
1933 | String *params; |
---|
1934 | Cardinal *num_params; |
---|
1935 | { |
---|
1936 | action_debug(Insert_action, event, params, num_params); |
---|
1937 | if (IN_ANSI) |
---|
1938 | return; |
---|
1939 | if (kybdlock) { |
---|
1940 | enq_ta(Insert_action, CN, CN); |
---|
1941 | return; |
---|
1942 | } |
---|
1943 | insert_mode(True); |
---|
1944 | } |
---|
1945 | |
---|
1946 | |
---|
1947 | /* |
---|
1948 | * Toggle insert mode key. |
---|
1949 | */ |
---|
1950 | /*ARGSUSED*/ |
---|
1951 | void |
---|
1952 | ToggleInsert_action(w, event, params, num_params) |
---|
1953 | Widget w; |
---|
1954 | XEvent *event; |
---|
1955 | String *params; |
---|
1956 | Cardinal *num_params; |
---|
1957 | { |
---|
1958 | action_debug(ToggleInsert_action, event, params, num_params); |
---|
1959 | if (IN_ANSI) |
---|
1960 | return; |
---|
1961 | if (kybdlock) { |
---|
1962 | enq_ta(ToggleInsert_action, CN, CN); |
---|
1963 | return; |
---|
1964 | } |
---|
1965 | if (insert) |
---|
1966 | insert_mode(False); |
---|
1967 | else |
---|
1968 | insert_mode(True); |
---|
1969 | } |
---|
1970 | |
---|
1971 | |
---|
1972 | /* |
---|
1973 | * Toggle reverse mode key. |
---|
1974 | */ |
---|
1975 | /*ARGSUSED*/ |
---|
1976 | void |
---|
1977 | ToggleReverse_action(w, event, params, num_params) |
---|
1978 | Widget w; |
---|
1979 | XEvent *event; |
---|
1980 | String *params; |
---|
1981 | Cardinal *num_params; |
---|
1982 | { |
---|
1983 | action_debug(ToggleReverse_action, event, params, num_params); |
---|
1984 | if (IN_ANSI) |
---|
1985 | return; |
---|
1986 | if (kybdlock) { |
---|
1987 | enq_ta(ToggleReverse_action, CN, CN); |
---|
1988 | return; |
---|
1989 | } |
---|
1990 | reverse_mode(!reverse); |
---|
1991 | } |
---|
1992 | |
---|
1993 | |
---|
1994 | /* |
---|
1995 | * Move the cursor to the first blank after the last nonblank in the |
---|
1996 | * field, or if the field is full, to the last character in the field. |
---|
1997 | */ |
---|
1998 | /*ARGSUSED*/ |
---|
1999 | void |
---|
2000 | FieldEnd_action(w, event, params, num_params) |
---|
2001 | Widget w; |
---|
2002 | XEvent *event; |
---|
2003 | String *params; |
---|
2004 | Cardinal *num_params; |
---|
2005 | { |
---|
2006 | int baddr; |
---|
2007 | unsigned char *fa, c; |
---|
2008 | int last_nonblank = -1; |
---|
2009 | |
---|
2010 | action_debug(FieldEnd_action, event, params, num_params); |
---|
2011 | if (IN_ANSI) |
---|
2012 | return; |
---|
2013 | if (kybdlock) { |
---|
2014 | enq_ta(FieldEnd_action, CN, CN); |
---|
2015 | return; |
---|
2016 | } |
---|
2017 | if (!formatted) |
---|
2018 | return; |
---|
2019 | baddr = cursor_addr; |
---|
2020 | fa = get_field_attribute(baddr); |
---|
2021 | if (fa == &screen_buf[baddr] || FA_IS_PROTECTED(*fa)) |
---|
2022 | return; |
---|
2023 | |
---|
2024 | baddr = fa - screen_buf; |
---|
2025 | while (True) { |
---|
2026 | INC_BA(baddr); |
---|
2027 | c = screen_buf[baddr]; |
---|
2028 | if (IS_FA(c)) |
---|
2029 | break; |
---|
2030 | if (c != CG_null && c != CG_space) |
---|
2031 | last_nonblank = baddr; |
---|
2032 | } |
---|
2033 | |
---|
2034 | if (last_nonblank == -1) { |
---|
2035 | baddr = fa - screen_buf; |
---|
2036 | INC_BA(baddr); |
---|
2037 | } else { |
---|
2038 | baddr = last_nonblank; |
---|
2039 | INC_BA(baddr); |
---|
2040 | if (IS_FA(screen_buf[baddr])) |
---|
2041 | baddr = last_nonblank; |
---|
2042 | } |
---|
2043 | cursor_move(baddr); |
---|
2044 | } |
---|
2045 | |
---|
2046 | |
---|
2047 | /* |
---|
2048 | * X-dependent code starts here. |
---|
2049 | */ |
---|
2050 | |
---|
2051 | /* |
---|
2052 | * Translate a keymap (from an XQueryKeymap or a KeymapNotify event) into |
---|
2053 | * a bitmap of Shift, Meta or Alt keys pressed. |
---|
2054 | */ |
---|
2055 | #define key_is_down(kc, bitmap) (kc && ((bitmap)[(kc)/8] & (1<<((kc)%8)))) |
---|
2056 | int |
---|
2057 | state_from_keymap(keymap) |
---|
2058 | char keymap[32]; |
---|
2059 | { |
---|
2060 | static Boolean initted = False; |
---|
2061 | static KeyCode kc_Shift_L, kc_Shift_R; |
---|
2062 | static KeyCode kc_Meta_L, kc_Meta_R; |
---|
2063 | static KeyCode kc_Alt_L, kc_Alt_R; |
---|
2064 | int pseudo_state = 0; |
---|
2065 | |
---|
2066 | if (!initted) { |
---|
2067 | kc_Shift_L = XKeysymToKeycode(display, XK_Shift_L); |
---|
2068 | kc_Shift_R = XKeysymToKeycode(display, XK_Shift_R); |
---|
2069 | kc_Meta_L = XKeysymToKeycode(display, XK_Meta_L); |
---|
2070 | kc_Meta_R = XKeysymToKeycode(display, XK_Meta_R); |
---|
2071 | kc_Alt_L = XKeysymToKeycode(display, XK_Alt_L); |
---|
2072 | kc_Alt_R = XKeysymToKeycode(display, XK_Alt_R); |
---|
2073 | initted = True; |
---|
2074 | } |
---|
2075 | if (key_is_down(kc_Shift_L, keymap) || |
---|
2076 | key_is_down(kc_Shift_R, keymap)) |
---|
2077 | pseudo_state |= ShiftKeyDown; |
---|
2078 | if (key_is_down(kc_Meta_L, keymap) || |
---|
2079 | key_is_down(kc_Meta_R, keymap)) |
---|
2080 | pseudo_state |= MetaKeyDown; |
---|
2081 | if (key_is_down(kc_Alt_L, keymap) || |
---|
2082 | key_is_down(kc_Alt_R, keymap)) |
---|
2083 | pseudo_state |= AltKeyDown; |
---|
2084 | return pseudo_state; |
---|
2085 | } |
---|
2086 | #undef key_is_down |
---|
2087 | |
---|
2088 | /* |
---|
2089 | * Process shift keyboard events. The code has to look for the raw Shift keys, |
---|
2090 | * rather than using the handy "state" field in the event structure. This is |
---|
2091 | * because the event state is the state _before_ the key was pressed or |
---|
2092 | * released. This isn't enough information to distinguish between "left |
---|
2093 | * shift released" and "left shift released, right shift still held down" |
---|
2094 | * events, for example. |
---|
2095 | * |
---|
2096 | * This function is also called as part of Focus event processing. |
---|
2097 | */ |
---|
2098 | /*ARGSUSED*/ |
---|
2099 | void |
---|
2100 | Shift_action(w, event, params, num_params) |
---|
2101 | Widget w; |
---|
2102 | XEvent *event; |
---|
2103 | String *params; |
---|
2104 | Cardinal *num_params; |
---|
2105 | { |
---|
2106 | char keys[32]; |
---|
2107 | |
---|
2108 | XQueryKeymap(display, keys); |
---|
2109 | shift_event(state_from_keymap(keys)); |
---|
2110 | } |
---|
2111 | |
---|
2112 | /* Add a key to the extended association table. */ |
---|
2113 | void |
---|
2114 | add_xk(key, assoc) |
---|
2115 | KeySym key; |
---|
2116 | KeySym assoc; |
---|
2117 | { |
---|
2118 | int i; |
---|
2119 | |
---|
2120 | for (i = 0; i < nxk; i++) |
---|
2121 | if (xk[i].key == key) { |
---|
2122 | xk[i].assoc = assoc; |
---|
2123 | return; |
---|
2124 | } |
---|
2125 | xk = (struct xks *)XtRealloc((XtPointer)xk, |
---|
2126 | (nxk + 1) * sizeof(struct xks)); |
---|
2127 | xk[nxk].key = key; |
---|
2128 | xk[nxk].assoc = assoc; |
---|
2129 | nxk++; |
---|
2130 | } |
---|
2131 | |
---|
2132 | /* Clear the extended association table. */ |
---|
2133 | void |
---|
2134 | clear_xks() |
---|
2135 | { |
---|
2136 | if (nxk) { |
---|
2137 | XtFree((XtPointer)xk); |
---|
2138 | xk = (struct xks *)NULL; |
---|
2139 | nxk = 0; |
---|
2140 | } |
---|
2141 | } |
---|
2142 | |
---|
2143 | /* |
---|
2144 | * Translate a keysym name to a keysym, including APL and extended |
---|
2145 | * characters. |
---|
2146 | */ |
---|
2147 | static KeySym |
---|
2148 | StringToKeysym(s, keytypep) |
---|
2149 | char *s; |
---|
2150 | enum keytype *keytypep; |
---|
2151 | { |
---|
2152 | KeySym k; |
---|
2153 | int is_ge; |
---|
2154 | |
---|
2155 | if (!strncmp(s, "apl_", 4)) { |
---|
2156 | k = APLStringToKeysym(s, &is_ge); |
---|
2157 | if (is_ge) |
---|
2158 | *keytypep = KT_GE; |
---|
2159 | else |
---|
2160 | *keytypep = KT_STD; |
---|
2161 | } else { |
---|
2162 | k = XStringToKeysym(s); |
---|
2163 | *keytypep = KT_STD; |
---|
2164 | } |
---|
2165 | if (k == NoSymbol && strlen(s) == 1) |
---|
2166 | k = s[0] & 0xff; |
---|
2167 | if (k < ' ') |
---|
2168 | k = NoSymbol; |
---|
2169 | else if (k > 0xff) { |
---|
2170 | int i; |
---|
2171 | |
---|
2172 | for (i = 0; i < nxk; i++) |
---|
2173 | if (xk[i].key == k) { |
---|
2174 | k = xk[i].assoc; |
---|
2175 | break; |
---|
2176 | } |
---|
2177 | if (k > 0xff) |
---|
2178 | k = NoSymbol; |
---|
2179 | } |
---|
2180 | return k; |
---|
2181 | } |
---|
2182 | |
---|
2183 | static Boolean |
---|
2184 | build_composites() |
---|
2185 | { |
---|
2186 | char *c; |
---|
2187 | char *cn; |
---|
2188 | char *ln; |
---|
2189 | char ksname[3][64]; |
---|
2190 | char junk[2]; |
---|
2191 | KeySym k[3]; |
---|
2192 | enum keytype a[3]; |
---|
2193 | int i; |
---|
2194 | struct composite *cp; |
---|
2195 | |
---|
2196 | if (!appres.compose_map) { |
---|
2197 | xs_warning("%s: No %s defined", action_name(Compose_action), |
---|
2198 | ResComposeMap); |
---|
2199 | return False; |
---|
2200 | } |
---|
2201 | cn = xs_buffer("%s.%s", ResComposeMap, appres.compose_map); |
---|
2202 | if ((c = get_resource(cn)) == NULL) { |
---|
2203 | xs_warning("%s: Cannot find %s \"%s\"", |
---|
2204 | action_name(Compose_action), ResComposeMap, |
---|
2205 | appres.compose_map); |
---|
2206 | return False; |
---|
2207 | } |
---|
2208 | XtFree(cn); |
---|
2209 | while ((ln = strtok(c, "\n"))) { |
---|
2210 | Boolean okay = True; |
---|
2211 | |
---|
2212 | c = NULL; |
---|
2213 | if (sscanf(ln, " %63[^+ \t] + %63[^= \t] =%63s%1s", |
---|
2214 | ksname[0], ksname[1], ksname[2], junk) != 3) { |
---|
2215 | xs_warning("%s: Invalid syntax: %s", |
---|
2216 | action_name(Compose_action), ln); |
---|
2217 | continue; |
---|
2218 | } |
---|
2219 | for (i = 0; i < 3; i++) { |
---|
2220 | k[i] = StringToKeysym(ksname[i], &a[i]); |
---|
2221 | if (k[i] == NoSymbol) { |
---|
2222 | xs_warning("%s: Invalid KeySym: \"%s\"", |
---|
2223 | action_name(Compose_action), ksname[i]); |
---|
2224 | okay = False; |
---|
2225 | break; |
---|
2226 | } |
---|
2227 | } |
---|
2228 | if (!okay) |
---|
2229 | continue; |
---|
2230 | composites = (struct composite *) XtRealloc((char *)composites, |
---|
2231 | (n_composites + 1) * sizeof(struct composite)); |
---|
2232 | cp = composites + n_composites; |
---|
2233 | cp->k1.keysym = k[0]; |
---|
2234 | cp->k1.keytype = a[0]; |
---|
2235 | cp->k2.keysym = k[1]; |
---|
2236 | cp->k2.keytype = a[1]; |
---|
2237 | cp->translation.keysym = k[2]; |
---|
2238 | cp->translation.keytype = a[2]; |
---|
2239 | n_composites++; |
---|
2240 | } |
---|
2241 | return True; |
---|
2242 | } |
---|
2243 | |
---|
2244 | /* |
---|
2245 | * Called by the toolkit when the "Compose" key is pressed. "Compose" is |
---|
2246 | * implemented by pressing and releasing three keys: "Compose" and two |
---|
2247 | * data keys. For example, "Compose" "s" "s" gives the German "ssharp" |
---|
2248 | * character, and "Compose" "C", "," gives a capital "C" with a cedilla |
---|
2249 | * (symbol Ccedilla). |
---|
2250 | * |
---|
2251 | * The mechanism breaks down a little when the user presses "Compose" and |
---|
2252 | * then a non-data key. Oh well. |
---|
2253 | */ |
---|
2254 | /*ARGSUSED*/ |
---|
2255 | void |
---|
2256 | Compose_action(w, event, params, num_params) |
---|
2257 | Widget w; |
---|
2258 | XEvent *event; |
---|
2259 | String *params; |
---|
2260 | Cardinal *num_params; |
---|
2261 | { |
---|
2262 | action_debug(Compose_action, event, params, num_params); |
---|
2263 | |
---|
2264 | if (!composites && !build_composites()) |
---|
2265 | return; |
---|
2266 | |
---|
2267 | if (composing == NONE) { |
---|
2268 | composing = COMPOSE; |
---|
2269 | status_compose(True, 0, KT_STD); |
---|
2270 | } |
---|
2271 | } |
---|
2272 | |
---|
2273 | /* |
---|
2274 | * Called by the toolkit for any key without special actions. |
---|
2275 | */ |
---|
2276 | /*ARGSUSED*/ |
---|
2277 | void |
---|
2278 | Default_action(w, event, params, num_params) |
---|
2279 | Widget w; |
---|
2280 | XEvent *event; |
---|
2281 | String *params; |
---|
2282 | Cardinal *num_params; |
---|
2283 | { |
---|
2284 | XKeyEvent *kevent = (XKeyEvent *)event; |
---|
2285 | char buf[32]; |
---|
2286 | KeySym ks; |
---|
2287 | int ll; |
---|
2288 | |
---|
2289 | action_debug(Default_action, event, params, num_params); |
---|
2290 | ll = XLookupString(kevent, buf, 32, &ks, (XComposeStatus *) 0); |
---|
2291 | if (ll == 1) { |
---|
2292 | /* Remap certain control characters. */ |
---|
2293 | switch (buf[0]) { |
---|
2294 | case '\t': |
---|
2295 | action_internal(Tab_action, IA_DEFAULT, CN, CN); |
---|
2296 | break; |
---|
2297 | case '\177': |
---|
2298 | action_internal(Delete_action, IA_DEFAULT, CN, CN); |
---|
2299 | break; |
---|
2300 | case '\b': |
---|
2301 | action_internal(BackSpace_action, IA_DEFAULT, CN, CN); |
---|
2302 | break; |
---|
2303 | case '\r': |
---|
2304 | action_internal(Enter_action, IA_DEFAULT, CN, CN); |
---|
2305 | break; |
---|
2306 | case '\n': |
---|
2307 | action_internal(Newline_action, IA_DEFAULT, CN, CN); |
---|
2308 | break; |
---|
2309 | default: |
---|
2310 | key_ACharacter((unsigned char) buf[0], KT_STD, |
---|
2311 | IA_DEFAULT); |
---|
2312 | } |
---|
2313 | return; |
---|
2314 | } |
---|
2315 | |
---|
2316 | /* Pick some other reasonable defaults. */ |
---|
2317 | switch (ks) { |
---|
2318 | case XK_Up: |
---|
2319 | action_internal(Up_action, IA_DEFAULT, CN, CN); |
---|
2320 | break; |
---|
2321 | case XK_Down: |
---|
2322 | action_internal(Down_action, IA_DEFAULT, CN, CN); |
---|
2323 | break; |
---|
2324 | case XK_Left: |
---|
2325 | action_internal(Left_action, IA_DEFAULT, CN, CN); |
---|
2326 | break; |
---|
2327 | case XK_Right: |
---|
2328 | action_internal(Right_action, IA_DEFAULT, CN, CN); |
---|
2329 | break; |
---|
2330 | case XK_Insert: |
---|
2331 | #if defined(XK_KP_Insert) /*[*/ |
---|
2332 | case XK_KP_Insert: |
---|
2333 | #endif /*]*/ |
---|
2334 | action_internal(Insert_action, IA_DEFAULT, CN, CN); |
---|
2335 | break; |
---|
2336 | case XK_Delete: |
---|
2337 | action_internal(Delete_action, IA_DEFAULT, CN, CN); |
---|
2338 | break; |
---|
2339 | case XK_Home: |
---|
2340 | action_internal(Home_action, IA_DEFAULT, CN, CN); |
---|
2341 | break; |
---|
2342 | case XK_Tab: |
---|
2343 | action_internal(Tab_action, IA_DEFAULT, CN, CN); |
---|
2344 | break; |
---|
2345 | default: |
---|
2346 | if (toggled(EVENT_TRACE)) |
---|
2347 | (void) fprintf(tracef, " %s: Unknown keysym\n", |
---|
2348 | action_name(Default_action)); |
---|
2349 | break; |
---|
2350 | } |
---|
2351 | } |
---|
2352 | |
---|
2353 | |
---|
2354 | /* |
---|
2355 | * Key action. |
---|
2356 | */ |
---|
2357 | /*ARGSUSED*/ |
---|
2358 | void |
---|
2359 | Key_action(w, event, params, num_params) |
---|
2360 | Widget w; |
---|
2361 | XEvent *event; |
---|
2362 | String *params; |
---|
2363 | Cardinal *num_params; |
---|
2364 | { |
---|
2365 | int i; |
---|
2366 | KeySym k; |
---|
2367 | enum keytype keytype; |
---|
2368 | |
---|
2369 | action_debug(Key_action, event, params, num_params); |
---|
2370 | for (i = 0; i < *num_params; i++) { |
---|
2371 | char *s = params[i]; |
---|
2372 | |
---|
2373 | k = StringToKeysym(s, &keytype); |
---|
2374 | if (k == NoSymbol) { |
---|
2375 | popup_an_error("%s: Nonexistent or invalid KeySym: %s", |
---|
2376 | action_name(Key_action), s); |
---|
2377 | continue; |
---|
2378 | } |
---|
2379 | if (k & ~0xff) { |
---|
2380 | popup_an_error("%s: Invalid KeySym: %s", |
---|
2381 | action_name(Key_action), s); |
---|
2382 | continue; |
---|
2383 | } |
---|
2384 | key_ACharacter((unsigned char)(k & 0xff), keytype, IA_KEY); |
---|
2385 | } |
---|
2386 | } |
---|
2387 | |
---|
2388 | /* |
---|
2389 | * String action. |
---|
2390 | */ |
---|
2391 | /*ARGSUSED*/ |
---|
2392 | void |
---|
2393 | String_action(w, event, params, num_params) |
---|
2394 | Widget w; |
---|
2395 | XEvent *event; |
---|
2396 | String *params; |
---|
2397 | Cardinal *num_params; |
---|
2398 | { |
---|
2399 | int i; |
---|
2400 | int len = 0; |
---|
2401 | char *s; |
---|
2402 | |
---|
2403 | action_debug(String_action, event, params, num_params); |
---|
2404 | |
---|
2405 | /* Determine the total length of the strings. */ |
---|
2406 | for (i = 0; i < *num_params; i++) |
---|
2407 | len += strlen(params[i]); |
---|
2408 | if (!len) |
---|
2409 | return; |
---|
2410 | |
---|
2411 | /* Allocate a block of memory and copy them in. */ |
---|
2412 | s = XtMalloc(len + 1); |
---|
2413 | *s = '\0'; |
---|
2414 | for (i = 0; i < *num_params; i++) |
---|
2415 | (void) strcat(s, params[i]); |
---|
2416 | |
---|
2417 | /* Set a pending string. */ |
---|
2418 | ps_set(s); |
---|
2419 | } |
---|
2420 | |
---|
2421 | /* |
---|
2422 | * Dual-mode action for the "asciicircum" ("^") key: |
---|
2423 | * If in ANSI mode, pass through untranslated. |
---|
2424 | * If in 3270 mode, translate to "notsign". |
---|
2425 | */ |
---|
2426 | /*ARGSUSED*/ |
---|
2427 | void |
---|
2428 | CircumNot_action(w, event, params, num_params) |
---|
2429 | Widget w; |
---|
2430 | XEvent *event; |
---|
2431 | String *params; |
---|
2432 | Cardinal *num_params; |
---|
2433 | { |
---|
2434 | action_debug(CircumNot_action, event, params, num_params); |
---|
2435 | |
---|
2436 | if (IN_3270 && composing == NONE) |
---|
2437 | key_ACharacter(0xac, KT_STD, IA_KEY); |
---|
2438 | else |
---|
2439 | key_ACharacter('^', KT_STD, IA_KEY); |
---|
2440 | } |
---|
2441 | |
---|
2442 | /* PA key action for String actions */ |
---|
2443 | static void |
---|
2444 | do_pa(n) |
---|
2445 | int n; |
---|
2446 | { |
---|
2447 | if (n < 1 || n > PA_SZ) { |
---|
2448 | popup_an_error("Unknown PA key %d", n); |
---|
2449 | return; |
---|
2450 | } |
---|
2451 | if (kybdlock) { |
---|
2452 | char nn[3]; |
---|
2453 | |
---|
2454 | (void) sprintf(nn, "%d", n); |
---|
2455 | enq_ta(PA_action, nn, CN); |
---|
2456 | return; |
---|
2457 | } |
---|
2458 | key_AID(pa_xlate[n-1]); |
---|
2459 | } |
---|
2460 | |
---|
2461 | /* PF key action for String actions */ |
---|
2462 | static void |
---|
2463 | do_pf(n) |
---|
2464 | int n; |
---|
2465 | { |
---|
2466 | if (n < 1 || n > PF_SZ) { |
---|
2467 | popup_an_error("Unknown PF key %d", n); |
---|
2468 | return; |
---|
2469 | } |
---|
2470 | if (kybdlock) { |
---|
2471 | char nn[3]; |
---|
2472 | |
---|
2473 | (void) sprintf(nn, "%d", n); |
---|
2474 | enq_ta(PF_action, nn, CN); |
---|
2475 | return; |
---|
2476 | } |
---|
2477 | key_AID(pf_xlate[n-1]); |
---|
2478 | } |
---|
2479 | |
---|
2480 | /* |
---|
2481 | * Set or clear the keyboard scroll lock. |
---|
2482 | */ |
---|
2483 | void |
---|
2484 | kybd_scroll_lock(lock) |
---|
2485 | Boolean lock; |
---|
2486 | { |
---|
2487 | if (!IN_3270) |
---|
2488 | return; |
---|
2489 | if (lock) |
---|
2490 | kybdlock_set(KL_SCROLLED, "kybd_scroll_lock"); |
---|
2491 | else |
---|
2492 | kybdlock_clr(KL_SCROLLED, "kybd_scroll_lock"); |
---|
2493 | } |
---|
2494 | |
---|
2495 | /* |
---|
2496 | * Move the cursor back within the legal paste area. |
---|
2497 | * Returns a Boolean indicating success. |
---|
2498 | */ |
---|
2499 | static Boolean |
---|
2500 | remargin(lmargin) |
---|
2501 | int lmargin; |
---|
2502 | { |
---|
2503 | Boolean ever = False; |
---|
2504 | int baddr, b0; |
---|
2505 | unsigned char *fa; |
---|
2506 | |
---|
2507 | baddr = cursor_addr; |
---|
2508 | while (BA_TO_COL(baddr) < lmargin) { |
---|
2509 | baddr = ROWCOL_TO_BA(BA_TO_ROW(baddr), lmargin); |
---|
2510 | if (!ever) { |
---|
2511 | b0 = baddr; |
---|
2512 | ever = True; |
---|
2513 | } |
---|
2514 | fa = get_field_attribute(baddr); |
---|
2515 | if (fa == &screen_buf[baddr] || FA_IS_PROTECTED(*fa)) { |
---|
2516 | baddr = next_unprotected(baddr); |
---|
2517 | if (baddr <= b0) |
---|
2518 | return False; |
---|
2519 | } |
---|
2520 | } |
---|
2521 | |
---|
2522 | cursor_move(baddr); |
---|
2523 | return True; |
---|
2524 | } |
---|
2525 | |
---|
2526 | /* |
---|
2527 | * Pretend that a sequence of keys was entered at the keyboard. |
---|
2528 | * |
---|
2529 | * "Pasting" means that the sequence came from the X clipboard. Returns are |
---|
2530 | * ignored; newlines mean "move to beginning of next line"; tabs and formfeeds |
---|
2531 | * become spaces. Backslashes are not special, but ASCII ESC characters are |
---|
2532 | * used to signify 3270 Graphic Escapes. |
---|
2533 | * |
---|
2534 | * "Not pasting" means that the sequence is a login string specified in the |
---|
2535 | * hosts file, or a parameter to the String action. Returns are "move to |
---|
2536 | * beginning of next line"; newlines mean "Enter AID" and the termination of |
---|
2537 | * processing the string. Backslashes are processed as in C. |
---|
2538 | * |
---|
2539 | * Returns the number of unprocessed characters. |
---|
2540 | */ |
---|
2541 | int |
---|
2542 | emulate_input(s, len, pasting) |
---|
2543 | char *s; |
---|
2544 | int len; |
---|
2545 | Boolean pasting; |
---|
2546 | { |
---|
2547 | char c; |
---|
2548 | enum { BASE, BACKSLASH, BACKX, BACKP, BACKPA, BACKPF, OCTAL, HEX, |
---|
2549 | XGE } state = BASE; |
---|
2550 | int literal; |
---|
2551 | int nc; |
---|
2552 | enum iaction ia = pasting ? IA_PASTE : IA_STRING; |
---|
2553 | int orig_addr = cursor_addr; |
---|
2554 | int orig_col = BA_TO_COL(cursor_addr); |
---|
2555 | static char dxl[] = "0123456789abcdef"; |
---|
2556 | |
---|
2557 | /* |
---|
2558 | * In the switch statements below, "break" generally means "consume |
---|
2559 | * this character," while "continue" means "rescan this character." |
---|
2560 | */ |
---|
2561 | while (len) { |
---|
2562 | |
---|
2563 | /* |
---|
2564 | * It isn't possible to unlock the keyboard from a string, |
---|
2565 | * so if the keyboard is locked, it's fatal |
---|
2566 | */ |
---|
2567 | if (kybdlock) { |
---|
2568 | if (toggled(EVENT_TRACE)) |
---|
2569 | (void) fprintf(tracef, |
---|
2570 | " keyboard locked, string dropped\n"); |
---|
2571 | return 0; |
---|
2572 | } |
---|
2573 | |
---|
2574 | if (pasting && IN_3270) { |
---|
2575 | |
---|
2576 | /* Check for cursor wrap to top of screen. */ |
---|
2577 | if (cursor_addr < orig_addr) |
---|
2578 | return len-1; /* wrapped */ |
---|
2579 | |
---|
2580 | /* Jump cursor over left margin. */ |
---|
2581 | if (toggled(MARGINED_PASTE) && |
---|
2582 | BA_TO_COL(cursor_addr) < orig_col) { |
---|
2583 | if (!remargin(orig_col)) |
---|
2584 | return len-1; |
---|
2585 | } |
---|
2586 | } |
---|
2587 | |
---|
2588 | c = *s; |
---|
2589 | switch (state) { |
---|
2590 | case BASE: |
---|
2591 | switch (c) { |
---|
2592 | case '\b': |
---|
2593 | action_internal(Left_action, ia, CN, CN); |
---|
2594 | continue; |
---|
2595 | case '\f': |
---|
2596 | if (pasting) { |
---|
2597 | key_ACharacter((unsigned char) ' ', |
---|
2598 | KT_STD, ia); |
---|
2599 | } else { |
---|
2600 | action_internal(Clear_action, ia, CN, CN); |
---|
2601 | if (IN_3270) |
---|
2602 | return len-1; |
---|
2603 | else |
---|
2604 | break; |
---|
2605 | } |
---|
2606 | case '\n': |
---|
2607 | if (pasting) |
---|
2608 | action_internal(Newline_action, ia, CN, CN); |
---|
2609 | else { |
---|
2610 | action_internal(Enter_action, ia, CN, CN); |
---|
2611 | if (IN_3270) |
---|
2612 | return len-1; |
---|
2613 | } |
---|
2614 | break; |
---|
2615 | case '\r': /* ignored */ |
---|
2616 | break; |
---|
2617 | case '\t': |
---|
2618 | action_internal(Tab_action, ia, CN, CN); |
---|
2619 | break; |
---|
2620 | case '\\': /* backslashes are NOT special when pasting */ |
---|
2621 | if (!pasting) |
---|
2622 | state = BACKSLASH; |
---|
2623 | else |
---|
2624 | key_ACharacter((unsigned char) c, |
---|
2625 | KT_STD, ia); |
---|
2626 | break; |
---|
2627 | case '\033': /* ESC is special only when pasting */ |
---|
2628 | if (pasting) |
---|
2629 | state = XGE; |
---|
2630 | break; |
---|
2631 | case '[': /* APL left bracket */ |
---|
2632 | if (pasting && appres.apl_mode) |
---|
2633 | key_ACharacter( |
---|
2634 | (unsigned char) XK_Yacute, |
---|
2635 | KT_GE, ia); |
---|
2636 | else |
---|
2637 | key_ACharacter((unsigned char) c, |
---|
2638 | KT_STD, ia); |
---|
2639 | break; |
---|
2640 | case ']': /* APL right bracket */ |
---|
2641 | if (pasting && appres.apl_mode) |
---|
2642 | key_ACharacter( |
---|
2643 | (unsigned char) XK_diaeresis, |
---|
2644 | KT_GE, ia); |
---|
2645 | else |
---|
2646 | key_ACharacter((unsigned char) c, |
---|
2647 | KT_STD, ia); |
---|
2648 | break; |
---|
2649 | default: |
---|
2650 | key_ACharacter((unsigned char) c, KT_STD, |
---|
2651 | ia); |
---|
2652 | break; |
---|
2653 | } |
---|
2654 | break; |
---|
2655 | case BACKSLASH: /* last character was a backslash */ |
---|
2656 | switch (c) { |
---|
2657 | case 'a': |
---|
2658 | popup_an_error("%s: bell not supported", |
---|
2659 | action_name(String_action)); |
---|
2660 | state = BASE; |
---|
2661 | break; |
---|
2662 | case 'b': |
---|
2663 | action_internal(Left_action, ia, CN, CN); |
---|
2664 | state = BASE; |
---|
2665 | break; |
---|
2666 | case 'f': |
---|
2667 | action_internal(Clear_action, ia, CN, CN); |
---|
2668 | state = BASE; |
---|
2669 | if (IN_3270) |
---|
2670 | return len-1; |
---|
2671 | else |
---|
2672 | break; |
---|
2673 | case 'n': |
---|
2674 | action_internal(Enter_action, ia, CN, CN); |
---|
2675 | state = BASE; |
---|
2676 | if (IN_3270) |
---|
2677 | return len-1; |
---|
2678 | else |
---|
2679 | break; |
---|
2680 | case 'p': |
---|
2681 | state = BACKP; |
---|
2682 | break; |
---|
2683 | case 'r': |
---|
2684 | action_internal(Newline_action, ia, CN, CN); |
---|
2685 | state = BASE; |
---|
2686 | break; |
---|
2687 | case 't': |
---|
2688 | action_internal(Tab_action, ia, CN, CN); |
---|
2689 | state = BASE; |
---|
2690 | break; |
---|
2691 | case 'v': |
---|
2692 | popup_an_error("%s: vertical tab not supported", |
---|
2693 | action_name(String_action)); |
---|
2694 | state = BASE; |
---|
2695 | break; |
---|
2696 | case 'x': |
---|
2697 | state = BACKX; |
---|
2698 | break; |
---|
2699 | case '\\': |
---|
2700 | key_ACharacter((unsigned char) c, KT_STD, ia); |
---|
2701 | state = BASE; |
---|
2702 | break; |
---|
2703 | case '0': |
---|
2704 | case '1': |
---|
2705 | case '2': |
---|
2706 | case '3': |
---|
2707 | case '4': |
---|
2708 | case '5': |
---|
2709 | case '6': |
---|
2710 | case '7': |
---|
2711 | state = OCTAL; |
---|
2712 | literal = 0; |
---|
2713 | nc = 0; |
---|
2714 | continue; |
---|
2715 | default: |
---|
2716 | state = BASE; |
---|
2717 | continue; |
---|
2718 | } |
---|
2719 | break; |
---|
2720 | case BACKP: /* last two characters were "\p" */ |
---|
2721 | switch (c) { |
---|
2722 | case 'a': |
---|
2723 | literal = 0; |
---|
2724 | nc = 0; |
---|
2725 | state = BACKPA; |
---|
2726 | break; |
---|
2727 | case 'f': |
---|
2728 | literal = 0; |
---|
2729 | nc = 0; |
---|
2730 | state = BACKPF; |
---|
2731 | break; |
---|
2732 | default: |
---|
2733 | popup_an_error("%s: unknown character after \\p", |
---|
2734 | action_name(String_action)); |
---|
2735 | state = BASE; |
---|
2736 | break; |
---|
2737 | } |
---|
2738 | break; |
---|
2739 | case BACKPF: /* last three characters were "\pf" */ |
---|
2740 | if (nc < 2 && isdigit(c)) { |
---|
2741 | literal = (literal * 10) + (c - '0'); |
---|
2742 | nc++; |
---|
2743 | } else if (!nc) { |
---|
2744 | popup_an_error("%s: unknown character after \\pf", |
---|
2745 | action_name(String_action)); |
---|
2746 | state = BASE; |
---|
2747 | } else { |
---|
2748 | do_pf(literal); |
---|
2749 | if (IN_3270) |
---|
2750 | return len-1; |
---|
2751 | state = BASE; |
---|
2752 | continue; |
---|
2753 | } |
---|
2754 | break; |
---|
2755 | case BACKPA: /* last three characters were "\pa" */ |
---|
2756 | if (nc < 1 && isdigit(c)) { |
---|
2757 | literal = (literal * 10) + (c - '0'); |
---|
2758 | nc++; |
---|
2759 | } else if (!nc) { |
---|
2760 | popup_an_error("%s: unknown character after \\pa", |
---|
2761 | action_name(String_action)); |
---|
2762 | state = BASE; |
---|
2763 | } else { |
---|
2764 | do_pa(literal); |
---|
2765 | if (IN_3270) |
---|
2766 | return len-1; |
---|
2767 | state = BASE; |
---|
2768 | continue; |
---|
2769 | } |
---|
2770 | break; |
---|
2771 | case BACKX: /* last two characters were "\x" */ |
---|
2772 | if (isxdigit(c)) { |
---|
2773 | state = HEX; |
---|
2774 | literal = 0; |
---|
2775 | nc = 0; |
---|
2776 | continue; |
---|
2777 | } else { |
---|
2778 | popup_an_error("%s: missing hex digits after \\x", |
---|
2779 | action_name(String_action)); |
---|
2780 | state = BASE; |
---|
2781 | continue; |
---|
2782 | } |
---|
2783 | case OCTAL: /* have seen \ and one or more octal digits */ |
---|
2784 | if (nc < 3 && isdigit(c) && c < '8') { |
---|
2785 | literal = (literal * 8) + (strchr(dxl, c) - dxl); |
---|
2786 | nc++; |
---|
2787 | break; |
---|
2788 | } else { |
---|
2789 | key_ACharacter((unsigned char) literal, KT_STD, |
---|
2790 | ia); |
---|
2791 | state = BASE; |
---|
2792 | continue; |
---|
2793 | } |
---|
2794 | case HEX: /* have seen \ and one or more hex digits */ |
---|
2795 | if (nc < 2 && isxdigit(c)) { |
---|
2796 | literal = (literal * 16) + (strchr(dxl, tolower(c)) - dxl); |
---|
2797 | nc++; |
---|
2798 | break; |
---|
2799 | } else { |
---|
2800 | key_ACharacter((unsigned char) literal, KT_STD, |
---|
2801 | ia); |
---|
2802 | state = BASE; |
---|
2803 | continue; |
---|
2804 | } |
---|
2805 | case XGE: /* have seen ESC */ |
---|
2806 | key_ACharacter((unsigned char) c, KT_GE, ia); |
---|
2807 | state = BASE; |
---|
2808 | break; |
---|
2809 | } |
---|
2810 | s++; |
---|
2811 | len--; |
---|
2812 | } |
---|
2813 | |
---|
2814 | switch (state) { |
---|
2815 | case OCTAL: |
---|
2816 | case HEX: |
---|
2817 | key_ACharacter((unsigned char) literal, KT_STD, ia); |
---|
2818 | state = BASE; |
---|
2819 | break; |
---|
2820 | case BACKPF: |
---|
2821 | if (nc > 0) { |
---|
2822 | do_pf(literal); |
---|
2823 | state = BASE; |
---|
2824 | } |
---|
2825 | break; |
---|
2826 | case BACKPA: |
---|
2827 | if (nc > 0) { |
---|
2828 | do_pa(literal); |
---|
2829 | state = BASE; |
---|
2830 | } |
---|
2831 | break; |
---|
2832 | default: |
---|
2833 | break; |
---|
2834 | } |
---|
2835 | |
---|
2836 | if (state != BASE) |
---|
2837 | popup_an_error("%s: missing data after \\", |
---|
2838 | action_name(String_action)); |
---|
2839 | |
---|
2840 | return len; |
---|
2841 | } |
---|
2842 | |
---|
2843 | /*ARGSUSED*/ |
---|
2844 | static void |
---|
2845 | paste_callback(w, client_data, selection, type, value, length, format) |
---|
2846 | Widget w; |
---|
2847 | XtPointer client_data; |
---|
2848 | Atom *selection; |
---|
2849 | Atom *type; |
---|
2850 | XtPointer value; |
---|
2851 | unsigned long *length; |
---|
2852 | int *format; |
---|
2853 | { |
---|
2854 | char *s; |
---|
2855 | unsigned long len; |
---|
2856 | |
---|
2857 | if ((value == NULL) || (*length == 0)) { |
---|
2858 | XtFree(value); |
---|
2859 | |
---|
2860 | /* Try the next one. */ |
---|
2861 | if (n_pasting > pix) |
---|
2862 | XtGetSelectionValue(w, paste_atom[pix++], XA_STRING, |
---|
2863 | paste_callback, NULL, paste_time); |
---|
2864 | return; |
---|
2865 | } |
---|
2866 | |
---|
2867 | s = (char *)value; |
---|
2868 | len = *length; |
---|
2869 | (void) emulate_input(s, (int) len, True); |
---|
2870 | n_pasting = 0; |
---|
2871 | |
---|
2872 | XtFree(value); |
---|
2873 | } |
---|
2874 | |
---|
2875 | void |
---|
2876 | insert_selection_action(w, event, params, num_params) |
---|
2877 | Widget w; |
---|
2878 | XButtonEvent *event; |
---|
2879 | String *params; |
---|
2880 | Cardinal *num_params; |
---|
2881 | { |
---|
2882 | int i; |
---|
2883 | Atom a; |
---|
2884 | |
---|
2885 | action_debug(insert_selection_action, (XEvent *)event, params, |
---|
2886 | num_params); |
---|
2887 | n_pasting = 0; |
---|
2888 | for (i = 0; i < *num_params; i++) { |
---|
2889 | a = XInternAtom(display, params[i], True); |
---|
2890 | if (a == None) { |
---|
2891 | popup_an_error("%s: no atom for selection", |
---|
2892 | action_name(insert_selection_action)); |
---|
2893 | continue; |
---|
2894 | } |
---|
2895 | if (n_pasting < NP) |
---|
2896 | paste_atom[n_pasting++] = a; |
---|
2897 | } |
---|
2898 | pix = 0; |
---|
2899 | if (n_pasting > pix) { |
---|
2900 | paste_time = event->time; |
---|
2901 | XtGetSelectionValue(w, paste_atom[pix++], XA_STRING, |
---|
2902 | paste_callback, NULL, paste_time); |
---|
2903 | } |
---|
2904 | } |
---|
2905 | |
---|
2906 | /*ARGSUSED*/ |
---|
2907 | void |
---|
2908 | ignore_action(w, event, params, num_params) |
---|
2909 | Widget w; |
---|
2910 | XButtonEvent *event; |
---|
2911 | String *params; |
---|
2912 | Cardinal *num_params; |
---|
2913 | { |
---|
2914 | action_debug(ignore_action, (XEvent *)event, params, num_params); |
---|
2915 | } |
---|
2916 | |
---|
2917 | /* |
---|
2918 | * Set or clear a temporary keymap. |
---|
2919 | * |
---|
2920 | * Keymap(x) toggle keymap "x" (add "x" to the keymap, or if "x" |
---|
2921 | * was already added, remove it) |
---|
2922 | * Keymap() removes the previous keymap, if any |
---|
2923 | * Keymap(None) removes the previous keymap, if any |
---|
2924 | */ |
---|
2925 | /*ARGSUSED*/ |
---|
2926 | void |
---|
2927 | Keymap_action(w, event, params, num_params) |
---|
2928 | Widget w; |
---|
2929 | XEvent *event; |
---|
2930 | String *params; |
---|
2931 | Cardinal *num_params; |
---|
2932 | { |
---|
2933 | char *k; |
---|
2934 | char *kmname, *km; |
---|
2935 | XtTranslations trans; |
---|
2936 | struct trans_list *t, *prev; |
---|
2937 | # define TN (struct trans_list *)NULL |
---|
2938 | |
---|
2939 | action_debug(Keymap_action, event, params, num_params); |
---|
2940 | |
---|
2941 | if (check_usage(Keymap_action, *num_params, 0, 1) < 0) |
---|
2942 | return; |
---|
2943 | |
---|
2944 | if (*num_params == 0 || !strcmp(params[0], "None")) { |
---|
2945 | struct trans_list *next; |
---|
2946 | |
---|
2947 | /* Delete all temporary keymaps. */ |
---|
2948 | for (t = temp_keymaps; t != TN; t = next) { |
---|
2949 | XtFree((XtPointer)t->name); |
---|
2950 | next = t->next; |
---|
2951 | XtFree((XtPointer)t); |
---|
2952 | } |
---|
2953 | tkm_last = temp_keymaps = TN; |
---|
2954 | screen_set_temp_keymap((XtTranslations)NULL); |
---|
2955 | keypad_set_temp_keymap((XtTranslations)NULL); |
---|
2956 | status_kmap(False); |
---|
2957 | return; |
---|
2958 | } |
---|
2959 | |
---|
2960 | k = params[0]; |
---|
2961 | |
---|
2962 | /* Check for deleting one keymap. */ |
---|
2963 | for (prev = TN, t = temp_keymaps; t != TN; prev = t, t = t->next) |
---|
2964 | if (!strcmp(k, t->name)) |
---|
2965 | break; |
---|
2966 | if (t != TN) { |
---|
2967 | |
---|
2968 | /* Delete the keymap from the list. */ |
---|
2969 | if (prev != TN) |
---|
2970 | prev->next = t->next; |
---|
2971 | else |
---|
2972 | temp_keymaps = t->next; |
---|
2973 | if (tkm_last == t) |
---|
2974 | tkm_last = prev; |
---|
2975 | XtFree((XtPointer)t->name); |
---|
2976 | XtFree((XtPointer)t); |
---|
2977 | |
---|
2978 | /* Rebuild the translation tables from the remaining ones. */ |
---|
2979 | screen_set_temp_keymap((XtTranslations)NULL); |
---|
2980 | keypad_set_temp_keymap((XtTranslations)NULL); |
---|
2981 | for (t = temp_keymaps; t != TN; t = t->next) { |
---|
2982 | trans = lookup_tt(t->name, CN); |
---|
2983 | screen_set_temp_keymap(trans); |
---|
2984 | keypad_set_temp_keymap(trans); |
---|
2985 | } |
---|
2986 | |
---|
2987 | /* Update the status line. */ |
---|
2988 | if (temp_keymaps == TN) |
---|
2989 | status_kmap(False); |
---|
2990 | return; |
---|
2991 | } |
---|
2992 | |
---|
2993 | /* Add a keymap. */ |
---|
2994 | |
---|
2995 | /* Look up the resource. */ |
---|
2996 | kmname = xs_buffer("%s.%s", ResKeymap, k); |
---|
2997 | km = get_resource(kmname); |
---|
2998 | XtFree(kmname); |
---|
2999 | if (km == CN) { |
---|
3000 | popup_an_error("%s: can't find %s.%s", |
---|
3001 | action_name(Keymap_action), ResKeymap, k); |
---|
3002 | return; |
---|
3003 | } |
---|
3004 | |
---|
3005 | /* Update the translation tables. */ |
---|
3006 | trans = lookup_tt(k, km); |
---|
3007 | XtFree(km); |
---|
3008 | screen_set_temp_keymap(trans); |
---|
3009 | keypad_set_temp_keymap(trans); |
---|
3010 | |
---|
3011 | /* Add it to the list. */ |
---|
3012 | t = (struct trans_list *)XtMalloc(sizeof(*t)); |
---|
3013 | t->name = XtNewString(k); |
---|
3014 | t->next = TN; |
---|
3015 | if (tkm_last != TN) |
---|
3016 | tkm_last->next = t; |
---|
3017 | else |
---|
3018 | temp_keymaps = t; |
---|
3019 | tkm_last = t; |
---|
3020 | |
---|
3021 | /* Update the status line. */ |
---|
3022 | status_kmap(True); |
---|
3023 | } |
---|
3024 | #undef TN |
---|
3025 | |
---|
3026 | /* |
---|
3027 | * Set up the cursor and input field for command input. |
---|
3028 | * Returns the length of the input field, or 0 if there is no field |
---|
3029 | * to set up. |
---|
3030 | */ |
---|
3031 | int |
---|
3032 | kybd_prime() |
---|
3033 | { |
---|
3034 | int baddr; |
---|
3035 | register unsigned char *fa; |
---|
3036 | int len = 0; |
---|
3037 | |
---|
3038 | /* |
---|
3039 | * No point in trying if the screen isn't formatted, the keyboard |
---|
3040 | * is locked, or we aren't in 3270 mode. |
---|
3041 | */ |
---|
3042 | if (!formatted || kybdlock || !IN_3270) |
---|
3043 | return 0; |
---|
3044 | |
---|
3045 | fa = get_field_attribute(cursor_addr); |
---|
3046 | if (IS_FA(screen_buf[cursor_addr]) || FA_IS_PROTECTED(*fa)) { |
---|
3047 | /* |
---|
3048 | * The cursor is not in an unprotected field. Find the |
---|
3049 | * next one. |
---|
3050 | */ |
---|
3051 | baddr = next_unprotected(cursor_addr); |
---|
3052 | |
---|
3053 | /* If there isn't any, give up. */ |
---|
3054 | if (!baddr) |
---|
3055 | return 0; |
---|
3056 | |
---|
3057 | /* Move the cursor there. */ |
---|
3058 | } else { |
---|
3059 | /* Already in an unprotected field. Find its start. */ |
---|
3060 | baddr = cursor_addr; |
---|
3061 | while (!IS_FA(screen_buf[baddr])) { |
---|
3062 | DEC_BA(baddr); |
---|
3063 | } |
---|
3064 | INC_BA(baddr); |
---|
3065 | } |
---|
3066 | |
---|
3067 | /* Move the cursor to the beginning of the field. */ |
---|
3068 | cursor_move(baddr); |
---|
3069 | |
---|
3070 | /* Erase it. */ |
---|
3071 | while (!IS_FA(screen_buf[baddr])) { |
---|
3072 | ctlr_add(baddr, 0, 0); |
---|
3073 | len++; |
---|
3074 | INC_BA(baddr); |
---|
3075 | } |
---|
3076 | |
---|
3077 | /* Return the field length. */ |
---|
3078 | return len; |
---|
3079 | } |
---|