1 /*
2 * Copyright (c) 1993-2009, 2014-2015, 2018-2020 Paul Mattes.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of Paul Mattes nor his contributors may be used
14 * to endorse or promote products derived from this software without
15 * specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY PAUL MATTES "AS IS" AND ANY EXPRESS
18 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL PAUL MATTES BE LIABLE FOR ANY DIRECT,
21 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
26 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 /*
31 * keypad.c
32 * This module handles the keypad with buttons for each of the
33 * 3270 function keys.
34 */
35
36 #include "globals.h"
37 #include "xglobals.h"
38
39 #include <X11/Shell.h>
40 #include <X11/StringDefs.h>
41 #include <X11/Xaw/Command.h>
42 #include "appres.h"
43 #include "resources.h"
44
45 #include "actions.h"
46 #include "kybd.h"
47 #include "names.h"
48 #include "popups.h"
49 #include "utils.h"
50 #include "xappres.h"
51 #include "xkeypad.h"
52 #include "xmenubar.h"
53 #include "xscreen.h"
54 #include "xpopups.h"
55
56 #include "keypad.bm"
57
58 enum kp_placement kp_placement;
59
60 #define NUM_ROWS 4
61 #define NUM_VROWS 15
62 #define BORDER rescale(1)
63 #define TOP_MARGIN rescale(6)
64 #define BOTTOM_MARGIN rescale(6)
65
66 #define SPACING rescale(2)
67 #define FAT_SPACING rescale(3)
68 #define VGAP rescale(4)
69 #define HGAP rescale(4)
70 #define SIDE_MARGIN rescale(4)
71
72 #define HORIZ_WIDTH \
73 (SIDE_MARGIN + \
74 12*(pf_width+2*BORDER) + \
75 11*SPACING + \
76 HGAP + \
77 3*(pa_width+2*BORDER) + \
78 2*SPACING + \
79 SIDE_MARGIN)
80
81 #define VERT_WIDTH \
82 (SIDE_MARGIN + \
83 3*(pa_width+2*BORDER) + \
84 2*SPACING + \
85 SIDE_MARGIN)
86
87 /*
88 * Table of 3278 key labels and actions
89 */
90 struct button_list {
91 const char *label;
92 const char *name;
93 const char *bits;
94 int width;
95 int height;
96 const char *action_name;
97 const char *parm;
98 };
99
100 bool keypad_changed = false;
101
102 static char Lg[] = "large";
103 static char Bm[] = "bm";
104 static char Sm[] = "small";
105
106 enum scaled_button {
107 BTAB, DEL, DOWN, HOME, INS, LEFT, RIGHT, TAB, NEWLINE, UP, NUM_SCALED
108 };
109
110 struct button_list scaled_list[NUM_SCALED] = {
111 { "Btab", Bm, NULL, 0, 0, AnBackTab, NULL },
112 { "Del", Bm, NULL, 0, 0, AnDelete, NULL },
113 { "Down", Bm, NULL, 0, 0, AnDown, NULL },
114 { "Home", Bm, NULL, 0, 0, AnHome, NULL },
115 { "Ins", Bm, NULL, 0, 0, AnInsert, NULL },
116 { "Left", Bm, NULL, 0, 0, AnLeft, NULL },
117 { "Right", Bm, NULL, 0, 0, AnRight, NULL },
118 { "Tab", Bm, NULL, 0, 0, AnTab, NULL },
119 { "Tab", Bm, NULL, 0, 0, AnNewline, NULL },
120 { "Up" , Bm, NULL, 0, 0, AnUp, NULL },
121 };
122
123 enum unscaled_button {
124 NONE,
125 PF1, PF2, PF3, PF4, PF5, PF6, PF7, PF8, PF9, PF10, PF11, PF12,
126 PF13, PF14, PF15, PF16, PF17, PF18, PF19, PF20, PF21, PF22, PF23, PF24,
127 PA1, PA2, PA3,
128 CLEAR, RESET, ERASE_EOF, ERASE_INPUT, DUP, FIELD_MARK, SYS_REQ,
129 CURSOR_SELECT, ATTN, COMPOSE, ENTER, NUM_UNSCALED
130 };
131
132 struct button_list unscaled_list[NUM_UNSCALED] = {
133 { NULL, NULL, NULL, 0, 0, NULL, NULL },
134 { "PF1", Lg, NULL, 0, 0, AnPF, "1" },
135 { "PF2", Lg, NULL, 0, 0, AnPF, "2" },
136 { "PF3", Lg, NULL, 0, 0, AnPF, "3" },
137 { "PF4", Lg, NULL, 0, 0, AnPF, "4" },
138 { "PF5", Lg, NULL, 0, 0, AnPF, "5" },
139 { "PF6", Lg, NULL, 0, 0, AnPF, "6" },
140 { "PF7", Lg, NULL, 0, 0, AnPF, "7" },
141 { "PF8", Lg, NULL, 0, 0, AnPF, "8" },
142 { "PF9", Lg, NULL, 0, 0, AnPF, "9" },
143 { "PF10", Lg, NULL, 0, 0, AnPF, "10" },
144 { "PF11", Lg, NULL, 0, 0, AnPF, "11" },
145 { "PF12", Lg, NULL, 0, 0, AnPF, "12" },
146 { "PF13", Lg, NULL, 0, 0, AnPF, "13" },
147 { "PF14", Lg, NULL, 0, 0, AnPF, "14" },
148 { "PF15", Lg, NULL, 0, 0, AnPF, "15" },
149 { "PF16", Lg, NULL, 0, 0, AnPF, "16" },
150 { "PF17", Lg, NULL, 0, 0, AnPF, "17" },
151 { "PF18", Lg, NULL, 0, 0, AnPF, "18" },
152 { "PF19", Lg, NULL, 0, 0, AnPF, "19" },
153 { "PF20", Lg, NULL, 0, 0, AnPF, "20" },
154 { "PF21", Lg, NULL, 0, 0, AnPF, "21" },
155 { "PF22", Lg, NULL, 0, 0, AnPF, "22" },
156 { "PF23", Lg, NULL, 0, 0, AnPF, "23" },
157 { "PF24", Lg, NULL, 0, 0, AnPF, "24" },
158 { "PA1", Lg, NULL, 0, 0, AnPA, "1" },
159 { "PA2", Lg, NULL, 0, 0, AnPA, "2" },
160 { "PA3", Lg, NULL, 0, 0, AnPA, "3" },
161 { "Clear", Sm, NULL, 0, 0, AnClear, NULL },
162 { "Reset", Sm, NULL, 0, 0, AnReset, NULL },
163 { "Erase\nEOF", Sm, NULL, 0, 0, AnEraseEOF, NULL },
164 { "Erase\nInput", Sm, NULL, 0, 0, AnEraseInput,NULL },
165 { "Dup", Sm, NULL, 0, 0, AnDup, NULL },
166 { "Field\nMark", Sm, NULL, 0, 0, AnFieldMark,NULL },
167 { "Sys\nReq", Sm, NULL, 0, 0, AnSysReq, NULL },
168 { "Cursor\nSelect", Sm, NULL, 0, 0, AnCursorSelect,NULL },
169 { "Attn", Sm, NULL, 0, 0, AnAttn, NULL },
170 { "Compose", Sm, NULL, 0, 0, AnCompose, NULL },
171 { "Enter", Sm, NULL, 0, 0, AnEnter, NULL },
172 };
173
174 static struct button_list *pf_list[] = {
175 &unscaled_list[PF13],
176 &unscaled_list[PF14],
177 &unscaled_list[PF15],
178 &unscaled_list[PF16],
179 &unscaled_list[PF17],
180 &unscaled_list[PF18],
181 &unscaled_list[PF19],
182 &unscaled_list[PF20],
183 &unscaled_list[PF21],
184 &unscaled_list[PF22],
185 &unscaled_list[PF23],
186 &unscaled_list[PF24],
187 &unscaled_list[PF1],
188 &unscaled_list[PF2],
189 &unscaled_list[PF3],
190 &unscaled_list[PF4],
191 &unscaled_list[PF5],
192 &unscaled_list[PF6],
193 &unscaled_list[PF7],
194 &unscaled_list[PF8],
195 &unscaled_list[PF9],
196 &unscaled_list[PF10],
197 &unscaled_list[PF11],
198 &unscaled_list[PF12],
199 };
200 #define PF_SZ (sizeof(pf_list)/sizeof(pf_list[0]))
201
202 static struct button_list *pad_list[] = {
203 &unscaled_list[PA1],
204 &unscaled_list[PA2],
205 &unscaled_list[PA3],
206 &unscaled_list[NONE],
207 &scaled_list[UP],
208 &unscaled_list[NONE],
209 &scaled_list[LEFT],
210 &scaled_list[HOME],
211 &scaled_list[RIGHT],
212 &unscaled_list[NONE],
213 &scaled_list[DOWN],
214 &unscaled_list[NONE],
215 };
216 #define PAD_SZ (sizeof(pad_list)/sizeof(pad_list[0]))
217
218 static struct button_list *lower_list[] = {
219 &unscaled_list[CLEAR],
220 &unscaled_list[RESET],
221 &scaled_list[INS],
222 &scaled_list[DEL],
223 &unscaled_list[ERASE_EOF],
224 &unscaled_list[ERASE_INPUT],
225 &unscaled_list[DUP],
226 &unscaled_list[FIELD_MARK],
227 &unscaled_list[SYS_REQ],
228 &unscaled_list[CURSOR_SELECT],
229 &unscaled_list[ATTN],
230 &unscaled_list[COMPOSE],
231 &scaled_list[BTAB],
232 &scaled_list[TAB],
233 &scaled_list[NEWLINE],
234 &unscaled_list[ENTER],
235 };
236 #define LOWER_SZ (sizeof(lower_list)/sizeof(lower_list[0]))
237
238 static struct button_list *vpf_list[] = {
239 &unscaled_list[PF1],
240 &unscaled_list[PF2],
241 &unscaled_list[PF3],
242 &unscaled_list[PF4],
243 &unscaled_list[PF5],
244 &unscaled_list[PF6],
245 &unscaled_list[PF7],
246 &unscaled_list[PF8],
247 &unscaled_list[PF9],
248 &unscaled_list[PF10],
249 &unscaled_list[PF11],
250 &unscaled_list[PF12],
251 };
252 #define VPF_SZ (sizeof(vpf_list)/sizeof(vpf_list[0]))
253
254 static struct button_list *vspf_list[] = {
255 &unscaled_list[PF13],
256 &unscaled_list[PF14],
257 &unscaled_list[PF15],
258 &unscaled_list[PF16],
259 &unscaled_list[PF17],
260 &unscaled_list[PF18],
261 &unscaled_list[PF19],
262 &unscaled_list[PF20],
263 &unscaled_list[PF21],
264 &unscaled_list[PF22],
265 &unscaled_list[PF23],
266 &unscaled_list[PF24],
267 };
268 static Widget vpf_w[2][VPF_SZ];
269
270 static struct button_list *vpad_list[] = {
271 &unscaled_list[NONE],
272 &scaled_list[UP],
273 &unscaled_list[NONE],
274 &scaled_list[LEFT],
275 &scaled_list[HOME],
276 &scaled_list[RIGHT],
277 &scaled_list[INS],
278 &scaled_list[DOWN],
279 &scaled_list[DEL],
280 &unscaled_list[PA1],
281 &unscaled_list[PA2],
282 &unscaled_list[PA3],
283 };
284 #define VPAD_SZ (sizeof(vpad_list)/sizeof(vpad_list[0]))
285
286 static struct button_list *vfn_list[] = {
287 &scaled_list[BTAB],
288 &scaled_list[TAB],
289 &unscaled_list[CLEAR],
290 &unscaled_list[RESET],
291 &unscaled_list[ERASE_EOF],
292 &unscaled_list[ERASE_INPUT],
293 &unscaled_list[DUP],
294 &unscaled_list[FIELD_MARK],
295 &unscaled_list[SYS_REQ],
296 &unscaled_list[CURSOR_SELECT],
297 &unscaled_list[ATTN],
298 &unscaled_list[COMPOSE],
299 &scaled_list[NEWLINE],
300 &unscaled_list[ENTER],
301 };
302 #define VFN_SZ (sizeof(vfn_list)/sizeof(vfn_list[0]))
303
304 static Dimension pf_width;
305 static Dimension key_height;
306 static Dimension pa_width;
307 static Dimension key_width;
308 static Dimension large_key_width;
309
310 static Widget keypad_container = (Widget) NULL;
311 static Widget key_pad = NULL;
312 static XtTranslations keypad_t00 = (XtTranslations) NULL;
313 static XtTranslations keypad_t0 = (XtTranslations) NULL;
314 static XtTranslations saved_xt = (XtTranslations) NULL;
315
316 /* Initialize the keypad placement from the keypad resource. */
317 void
keypad_placement_init(void)318 keypad_placement_init(void)
319 {
320 if (!strcmp(xappres.keypad, KpLeft)) {
321 kp_placement = kp_left;
322 } else if (!strcmp(xappres.keypad, KpRight)) {
323 kp_placement = kp_right;
324 } else if (!strcmp(xappres.keypad, KpBottom)) {
325 kp_placement = kp_bottom;
326 } else if (!strcmp(xappres.keypad, KpIntegral)) {
327 kp_placement = kp_integral;
328 } else if (!strcmp(xappres.keypad, KpInsideRight)) {
329 kp_placement = kp_inside_right;
330 } else {
331 xs_error("Unknown value for %s", ResKeypad);
332 }
333 }
334
335 /*
336 * Callback for keypad buttons. Simply calls the function pointed to by the
337 * client data.
338 */
339 static void
callfn(Widget w _is_unused,XtPointer client_data,XtPointer call_data _is_unused)340 callfn(Widget w _is_unused, XtPointer client_data, XtPointer
341 call_data _is_unused)
342 {
343 struct button_list *keyd = (struct button_list *) client_data;
344
345 run_action(keyd->action_name, IA_KEYPAD, keyd->parm, NULL);
346 }
347
348 /*
349 * Create a button.
350 */
351 static Widget
make_a_button(Widget container,Position x,Position y,Dimension w,Dimension h,struct button_list * keyd)352 make_a_button(Widget container, Position x, Position y, Dimension w,
353 Dimension h, struct button_list *keyd)
354 {
355 Widget command;
356 Pixmap pixmap;
357
358 if (!keyd->label) {
359 return (Widget) 0;
360 }
361
362 command = XtVaCreateManagedWidget(
363 keyd->name, commandWidgetClass, container,
364 XtNx, x,
365 XtNy, y,
366 XtNwidth, w,
367 XtNheight, h,
368 XtNresize, False,
369 NULL);
370 XtAddCallback(command, XtNcallback, callfn, (XtPointer)keyd);
371 if (keyd->bits) {
372 pixmap = XCreateBitmapFromData(display, root_window, keyd->bits,
373 keyd->width, keyd->height);
374 XtVaSetValues(command, XtNbitmap, pixmap, NULL);
375 } else {
376 XtVaSetValues(command, XtNlabel, keyd->label, NULL);
377 }
378 return command;
379 }
380
381 /*
382 * Create the keys for a horizontal keypad
383 */
384 static void
keypad_keys_horiz(Widget container)385 keypad_keys_horiz(Widget container)
386 {
387 unsigned i;
388 Position row, col;
389 Position x0, y0;
390
391 /* PF Keys */
392 row = col = 0;
393 x0 = SIDE_MARGIN;
394 y0 = TOP_MARGIN;
395 for (i = 0; i < PF_SZ; i++) {
396 make_a_button(container,
397 (Position)(x0 + (col*(pf_width+2*BORDER+SPACING))),
398 (Position)(y0 + (row*(key_height+2*BORDER+SPACING))),
399 pf_width,
400 key_height,
401 pf_list[i]);
402 if (++col >= 12) {
403 col = 0;
404 row++;
405 }
406 }
407
408 /* Keypad */
409 row = col = 0;
410 x0 = SIDE_MARGIN + 12*(pf_width+2*BORDER+SPACING) + HGAP;
411 y0 = TOP_MARGIN;
412 for (i = 0; i < PAD_SZ; i++) {
413 make_a_button(container,
414 (Position)(x0 + (col*(pa_width+2*BORDER+SPACING))),
415 (Position)(y0 + (row*(key_height+2*BORDER+SPACING))),
416 pa_width,
417 key_height,
418 pad_list[i]);
419 if (++col >= 3) {
420 col = 0;
421 if (++row == 1) {
422 y0 += VGAP;
423 }
424 }
425 }
426
427 /* Bottom */
428 row = col = 0;
429 x0 = SIDE_MARGIN;
430 y0 = TOP_MARGIN + 2*(key_height+2*BORDER+SPACING) + VGAP;
431
432 for (i = 0; i < LOWER_SZ; i++) {
433 make_a_button(container,
434 (Position)(x0 + (col*(key_width+2*BORDER+FAT_SPACING))),
435 (Position)(y0 + (row*(key_height+2*BORDER+SPACING))),
436 key_width,
437 key_height,
438 lower_list[i]);
439 if (++row >= 2) {
440 ++col;
441 row = 0;
442 }
443 }
444 }
445
446 static bool vert_keypad = false;
447 static Widget spf_container;
448
449 /*
450 * Create the keys for a vertical keypad.
451 */
452 static void
keypad_keys_vert(Widget container)453 keypad_keys_vert(Widget container)
454 {
455 unsigned i;
456 Position row, col;
457 Position x0, y0;
458 Widget c1, c2;
459
460 vert_keypad = true;
461
462 /* Container for shifted PF keys */
463 spf_container = XtVaCreateManagedWidget(
464 "shift", compositeWidgetClass, container,
465 XtNmappedWhenManaged, False,
466 XtNborderWidth, 0,
467 XtNwidth, VERT_WIDTH,
468 XtNheight, TOP_MARGIN+4*(key_height+2*BORDER)+3*SPACING,
469 NULL);
470 if (appres.interactive.mono) {
471 XtVaSetValues(spf_container, XtNbackgroundPixmap, gray, NULL);
472 } else {
473 XtVaSetValues(spf_container, XtNbackground, keypadbg_pixel, NULL);
474 }
475
476 /* PF keys */
477 if (xappres.invert_kpshift) {
478 c1 = spf_container;
479 c2 = container;
480 } else {
481 c1 = container;
482 c2 = spf_container;
483 }
484 row = col = 0;
485 x0 = SIDE_MARGIN;
486 y0 = TOP_MARGIN;
487 for (i = 0; i < VPF_SZ; i++) {
488 vpf_w[0][i] = make_a_button(c1,
489 (Position)(x0 + (col*(pa_width+2*BORDER+SPACING))),
490 (Position)(y0 + (row*(key_height+2*BORDER+SPACING))),
491 pa_width,
492 key_height,
493 vpf_list[i]);
494 vpf_w[1][i] = make_a_button(c2,
495 (Position)(x0 + (col*(pa_width+2*BORDER+SPACING))),
496 (Position)(y0 + (row*(key_height+2*BORDER+SPACING))),
497 pa_width,
498 key_height,
499 vspf_list[i]);
500 if (++col >= 3) {
501 col = 0;
502 row++;
503 }
504 }
505
506 /* Cursor and PA keys */
507 for (i = 0; i < VPAD_SZ; i++) {
508 make_a_button(container,
509 (Position)(x0 + (col*(pa_width+2*BORDER+SPACING))),
510 (Position)(y0 + (row*(key_height+2*BORDER+SPACING))),
511 pa_width,
512 key_height,
513 vpad_list[i]);
514 if (++col >= 3) {
515 col = 0;
516 row++;
517 }
518 }
519
520 /* Other keys */
521 for (i = 0; i < VFN_SZ; i++) {
522 make_a_button(container,
523 (Position)(x0 + (col*(large_key_width+2*BORDER+SPACING))),
524 (Position)(y0 + (row*(key_height+2*BORDER+SPACING))),
525 large_key_width,
526 key_height,
527 vfn_list[i]);
528 if (++col >= 2) {
529 col = 0;
530 row++;
531 }
532 }
533 }
534
535 static Dimension
get_keypad_dimension(const char * name)536 get_keypad_dimension(const char *name)
537 {
538 char *d;
539 long v;
540
541 if ((d = get_fresource("%s.%s", ResKeypad, name)) == NULL) {
542 xs_error("Cannot find %s resource", ResKeypad);
543 }
544 if ((v = strtol(d, (char **)0, 0)) <= 0) {
545 xs_error("Illegal %s resource", ResKeypad);
546 }
547 return rescale((Dimension)v);
548 }
549
550 static void
init_keypad_dimensions(void)551 init_keypad_dimensions(void)
552 {
553 static bool done = false;
554
555 if (done) {
556 return;
557 }
558 key_height = get_keypad_dimension(ResKeyHeight);
559 key_width = get_keypad_dimension(ResKeyWidth);
560 pf_width = get_keypad_dimension(ResPfWidth);
561 pa_width = get_keypad_dimension(ResPaWidth);
562 large_key_width = get_keypad_dimension(ResLargeKeyWidth);
563
564 if (rescale(btab_width) >= btab20_width) {
565 scaled_list[BTAB].bits = (char *)btab20_bits;
566 scaled_list[BTAB].width = btab20_width;
567 scaled_list[BTAB].height = btab20_height;
568 scaled_list[DEL].bits = (char *)del20_bits;
569 scaled_list[DEL].width = del20_width;
570 scaled_list[DEL].height = del20_height;
571 scaled_list[DOWN].bits = (char *)down20_bits;
572 scaled_list[DOWN].width = down20_width;
573 scaled_list[DOWN].height = down20_height;
574 scaled_list[HOME].bits = (char *)home20_bits;
575 scaled_list[HOME].width = home20_width;
576 scaled_list[HOME].height = home20_height;
577 scaled_list[INS].bits = (char *)ins20_bits;
578 scaled_list[INS].width = ins20_width;
579 scaled_list[INS].height = ins20_height;
580 scaled_list[LEFT].bits = (char *)left20_bits;
581 scaled_list[LEFT].width = left20_width;
582 scaled_list[LEFT].height = left20_height;
583 scaled_list[NEWLINE].bits = (char *)newline20_bits;
584 scaled_list[NEWLINE].width = newline20_width;
585 scaled_list[NEWLINE].height = newline20_height;
586 scaled_list[RIGHT].bits = (char *)right20_bits;
587 scaled_list[RIGHT].width = right20_width;
588 scaled_list[RIGHT].height = right20_height;
589 scaled_list[TAB].bits = (char *)tab20_bits;
590 scaled_list[TAB].width = tab20_width;
591 scaled_list[TAB].height = tab20_height;
592 scaled_list[UP].bits = (char *)up20_bits;
593 scaled_list[UP].width = up20_width;
594 scaled_list[UP].height = up20_height;
595 } else if (rescale(btab_width) >= btab15_width) {
596 scaled_list[BTAB].bits = (char *)btab15_bits;
597 scaled_list[BTAB].width = btab15_width;
598 scaled_list[BTAB].height = btab15_height;
599 scaled_list[DEL].bits = (char *)del15_bits;
600 scaled_list[DEL].width = del15_width;
601 scaled_list[DEL].height = del15_height;
602 scaled_list[DOWN].bits = (char *)down15_bits;
603 scaled_list[DOWN].width = down15_width;
604 scaled_list[DOWN].height = down15_height;
605 scaled_list[HOME].bits = (char *)home15_bits;
606 scaled_list[HOME].width = home15_width;
607 scaled_list[HOME].height = home15_height;
608 scaled_list[INS].bits = (char *)ins15_bits;
609 scaled_list[INS].width = ins15_width;
610 scaled_list[INS].height = ins15_height;
611 scaled_list[LEFT].bits = (char *)left15_bits;
612 scaled_list[LEFT].width = left15_width;
613 scaled_list[LEFT].height = left15_height;
614 scaled_list[NEWLINE].bits = (char *)newline15_bits;
615 scaled_list[NEWLINE].width = newline15_width;
616 scaled_list[NEWLINE].height = newline15_height;
617 scaled_list[RIGHT].bits = (char *)right15_bits;
618 scaled_list[RIGHT].width = right15_width;
619 scaled_list[RIGHT].height = right15_height;
620 scaled_list[TAB].bits = (char *)tab15_bits;
621 scaled_list[TAB].width = tab15_width;
622 scaled_list[TAB].height = tab15_height;
623 scaled_list[UP].bits = (char *)up15_bits;
624 scaled_list[UP].width = up15_width;
625 scaled_list[UP].height = up15_height;
626 } else {
627 scaled_list[BTAB].bits = (char *)btab_bits;
628 scaled_list[BTAB].width = btab_width;
629 scaled_list[BTAB].height = btab_height;
630 scaled_list[DEL].bits = (char *)del_bits;
631 scaled_list[DEL].width = del_width;
632 scaled_list[DEL].height = del_height;
633 scaled_list[DOWN].bits = (char *)down_bits;
634 scaled_list[DOWN].width = down_width;
635 scaled_list[DOWN].height = down_height;
636 scaled_list[HOME].bits = (char *)home_bits;
637 scaled_list[HOME].width = home_width;
638 scaled_list[HOME].height = home_height;
639 scaled_list[INS].bits = (char *)ins_bits;
640 scaled_list[INS].width = ins_width;
641 scaled_list[INS].height = ins_height;
642 scaled_list[LEFT].bits = (char *)left_bits;
643 scaled_list[LEFT].width = left_width;
644 scaled_list[LEFT].height = left_height;
645 scaled_list[NEWLINE].bits = (char *)newline_bits;
646 scaled_list[NEWLINE].width = newline_width;
647 scaled_list[NEWLINE].height = newline_height;
648 scaled_list[RIGHT].bits = (char *)right_bits;
649 scaled_list[RIGHT].width = right_width;
650 scaled_list[RIGHT].height = right_height;
651 scaled_list[TAB].bits = (char *)tab_bits;
652 scaled_list[TAB].width = tab_width;
653 scaled_list[TAB].height = tab_height;
654 scaled_list[UP].bits = (char *)up_bits;
655 scaled_list[UP].width = up_width;
656 scaled_list[UP].height = up_height;
657 }
658
659 done = true;
660 }
661
662 Dimension
min_keypad_width(void)663 min_keypad_width(void)
664 {
665 init_keypad_dimensions();
666 return HORIZ_WIDTH;
667 }
668
669 Dimension
keypad_qheight(void)670 keypad_qheight(void)
671 {
672 init_keypad_dimensions();
673 return TOP_MARGIN +
674 (NUM_ROWS*(key_height+2*BORDER)) + (NUM_ROWS-1)*SPACING + VGAP +
675 BOTTOM_MARGIN;
676 }
677
678 /*
679 * Create a keypad.
680 */
681 Widget
keypad_init(Widget container,Dimension voffset,Dimension screen_width,bool floating,bool vert)682 keypad_init(Widget container, Dimension voffset, Dimension screen_width,
683 bool floating, bool vert)
684 {
685 Dimension height;
686 Dimension width = screen_width;
687 Dimension hoffset;
688
689 init_keypad_dimensions();
690
691 /* Figure out what dimensions to use */
692 if (vert) {
693 width = VERT_WIDTH;
694 } else {
695 width = HORIZ_WIDTH;
696 }
697
698 if (vert) {
699 height = TOP_MARGIN +
700 (NUM_VROWS*(key_height+2*BORDER)) + (NUM_VROWS-1)*SPACING +
701 BOTTOM_MARGIN;
702 } else {
703 height = keypad_qheight();
704 }
705
706 /* Create a container */
707 if (screen_width > width) {
708 hoffset = ((screen_width - width) / (unsigned) 2) & ~1;
709 } else {
710 hoffset = 0;
711 }
712 if (voffset & 1) {
713 voffset++;
714 }
715 if (key_pad == NULL) {
716 key_pad = XtVaCreateManagedWidget(
717 "keyPad", compositeWidgetClass, container,
718 XtNx, hoffset,
719 XtNy, voffset,
720 XtNborderWidth, (Dimension) (floating ? 1 : 0),
721 XtNwidth, width,
722 XtNheight, height,
723 NULL);
724 if (appres.interactive.mono) {
725 XtVaSetValues(key_pad, XtNbackgroundPixmap, gray, NULL);
726 } else {
727 XtVaSetValues(key_pad, XtNbackground, keypadbg_pixel, NULL);
728 }
729
730 /* Create the keys */
731 if (vert) {
732 keypad_keys_vert(key_pad);
733 } else {
734 keypad_keys_horiz(key_pad);
735 }
736 } else {
737 XtVaSetValues(key_pad,
738 XtNx, hoffset,
739 XtNy, voffset,
740 NULL);
741 }
742
743 return key_pad;
744 }
745
746 /*
747 * Swap PF1-12 and PF13-24 on the vertical popup keypad, by mapping or
748 * unmapping the window containing the shifted keys.
749 */
750 void
keypad_shift(void)751 keypad_shift(void)
752 {
753 if (!vert_keypad ||
754 (spf_container == NULL) ||
755 !XtIsRealized(spf_container)) {
756 return;
757 }
758
759 if (shifted) {
760 XtMapWidget(spf_container);
761 } else {
762 XtUnmapWidget(spf_container);
763 }
764 }
765
766 /*
767 * Keypad popup
768 */
769 Widget keypad_shell = NULL;
770 bool keypad_popped = false;
771
772 static bool TrueD = true;
773 static bool *TrueP = &TrueD;
774 static bool FalseD = false;
775 static bool *FalseP = &FalseD;
776 static enum placement *pp;
777
778 /*
779 * Called when the main screen is first exposed, to pop up the keypad the
780 * first time
781 */
782 void
keypad_first_up(void)783 keypad_first_up(void)
784 {
785 if (!xappres.keypad_on || kp_placement == kp_integral) {
786 return;
787 }
788 keypad_popup_init();
789 popup_popup(keypad_shell, XtGrabNone);
790 }
791
792 /* Called when the keypad popup pops up or down */
793 static void
keypad_updown(Widget w _is_unused,XtPointer client_data,XtPointer call_data)794 keypad_updown(Widget w _is_unused, XtPointer client_data, XtPointer call_data)
795 {
796 xappres.keypad_on = keypad_popped = *(bool *)client_data;
797 if (!keypad_popped) {
798 XtDestroyWidget(keypad_shell);
799 keypad_shell = NULL;
800 keypad_container = NULL;
801 key_pad = NULL;
802 spf_container = NULL;
803 }
804
805 if (xappres.keypad_on) {
806 place_popup(w, (XtPointer)pp, call_data);
807 }
808 menubar_keypad_changed();
809 }
810
811 /* Create the pop-up keypad */
812 void
keypad_popup_init(void)813 keypad_popup_init(void)
814 {
815 Widget w;
816 Dimension height, width, border;
817 bool vert = false;
818
819 if (keypad_shell != NULL) {
820 return;
821 }
822
823 switch (kp_placement) {
824 case kp_left:
825 vert = true;
826 pp = LeftP;
827 break;
828 case kp_right:
829 vert = true;
830 pp = RightP;
831 break;
832 case kp_bottom:
833 vert = false;
834 pp = BottomP;
835 break;
836 case kp_integral: /* can't happen */
837 return;
838 case kp_inside_right:
839 vert = true;
840 pp = InsideRightP;
841 break;
842 }
843
844 /* Create a popup shell */
845
846 keypad_shell = XtVaCreatePopupShell(
847 "keypadPopup", transientShellWidgetClass, toplevel,
848 NULL);
849 /*XtAddCallback(keypad_shell, XtNpopupCallback, place_popup,
850 (XtPointer)pp);*/
851 XtAddCallback(keypad_shell, XtNpopupCallback, keypad_updown,
852 (XtPointer) TrueP);
853 XtAddCallback(keypad_shell, XtNpopdownCallback, keypad_updown,
854 (XtPointer) FalseP);
855
856 /* Create a keypad in the popup */
857
858 keypad_container = XtVaCreateManagedWidget(
859 "container", compositeWidgetClass, keypad_shell,
860 XtNborderWidth, 0,
861 XtNheight, 10,
862 XtNwidth, 10,
863 NULL);
864 w = keypad_init(keypad_container, 0, 0, true, vert);
865
866 /* Fix the window size */
867
868 XtVaGetValues(w,
869 XtNheight, &height,
870 XtNwidth, &width,
871 XtNborderWidth, &border,
872 NULL);
873 height += 2*border;
874 width += 2*border;
875 XtVaSetValues(keypad_container,
876 XtNheight, height,
877 XtNwidth, width,
878 NULL);
879 XtVaSetValues(keypad_shell,
880 XtNheight, height,
881 XtNwidth, width,
882 XtNbaseHeight, height,
883 XtNbaseWidth, width,
884 XtNminHeight, height,
885 XtNminWidth, width,
886 XtNmaxHeight, height,
887 XtNmaxWidth, width,
888 NULL);
889
890 /* Make keystrokes in the popup apply to the main window */
891
892 save_00translations(keypad_container, &keypad_t00);
893 set_translations(keypad_container, NULL, &keypad_t0);
894 if (saved_xt != (XtTranslations) NULL) {
895 XtOverrideTranslations(keypad_container, saved_xt);
896 saved_xt = (XtTranslations) NULL;
897 }
898 }
899
900 /* Set a temporary keymap. */
901 void
keypad_set_temp_keymap(XtTranslations trans)902 keypad_set_temp_keymap(XtTranslations trans)
903 {
904 if (keypad_container != (Widget) NULL) {
905 if (trans == NULL) {
906 trans = keypad_t0;
907 XtUninstallTranslations(keypad_container);
908 }
909 XtOverrideTranslations(keypad_container, trans);
910 saved_xt = (XtTranslations) NULL;
911 } else {
912 saved_xt = trans;
913 }
914 }
915
916 /* Change the baseleve keymap. */
917 void
keypad_set_keymap(void)918 keypad_set_keymap(void)
919 {
920 if (keypad_container == NULL) {
921 return;
922 }
923 XtUninstallTranslations(keypad_container);
924 set_translations(keypad_container, &keypad_t00, &keypad_t0);
925 }
926
927 /* Move the keypad. */
928 void
keypad_move(void)929 keypad_move(void)
930 {
931 if (!keypad_popped) {
932 return;
933 }
934
935 move_popup(keypad_shell, pp, NULL);
936 }
937
938 void
keypad_popdown(bool * was_up)939 keypad_popdown(bool *was_up)
940 {
941 if (keypad_popped) {
942 *was_up = true;
943 XtPopdown(keypad_shell);
944 } else {
945 *was_up = false;
946 }
947 }
948
949 void
keypad_popup(void)950 keypad_popup(void)
951 {
952 #if 0
953 if (keypad_shell != NULL) {
954 XtPopup(keypad_shell, XtGrabNone);
955 }
956 #endif
957 xappres.keypad_on = True;
958 keypad_first_up();
959 }
960
961 void
ikeypad_destroy(void)962 ikeypad_destroy(void)
963 {
964 if (key_pad != NULL) {
965 XtDestroyWidget(key_pad);
966 key_pad = NULL;
967 }
968 }
969