2
* Copyright (c) 1993-2009, Paul Mattes.
3
* Copyright (c) 1990, Jeff Sparkes.
4
* Copyright (c) 1989, Georgia Tech Research Corporation (GTRC), Atlanta, GA
8
* Redistribution and use in source and binary forms, with or without
9
* modification, are permitted provided that the following conditions are met:
10
* * Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
* * Redistributions in binary form must reproduce the above copyright
13
* notice, this list of conditions and the following disclaimer in the
14
* documentation and/or other materials provided with the distribution.
15
* * Neither the names of Paul Mattes, Jeff Sparkes, GTRC nor the names of
16
* their contributors may be used to endorse or promote products derived
17
* from this software without specific prior written permission.
19
* THIS SOFTWARE IS PROVIDED BY PAUL MATTES, JEFF SPARKES AND GTRC "AS IS" AND
20
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
* ARE DISCLAIMED. IN NO EVENT SHALL PAUL MATTES, JEFF SPARKES OR GTRC BE
23
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
* POSSIBILITY OF SUCH DAMAGE.
34
* This module handles the keyboard for the 3270 emulator.
39
#if defined(X3270_DISPLAY) /*[*/
40
#include <X11/Xatom.h>
43
#if defined(X3270_APL) /*[*/
46
#include <X11/keysym.h>
52
#if defined(X3270_DISPLAY) /*[*/
53
#include "keysym2ucs.h"
55
#include "resources.h"
72
#if defined(X3270_DISPLAY) /*[*/
79
#include "trace_dsc.h"
84
#if defined(_WIN32) /*[*/
88
/*#define KYBDLOCK_TRACE 1*/
91
static enum { NONE, COMPOSE, FIRST } composing = NONE;
92
static unsigned char pf_xlate[] = {
93
AID_PF1, AID_PF2, AID_PF3, AID_PF4, AID_PF5, AID_PF6,
94
AID_PF7, AID_PF8, AID_PF9, AID_PF10, AID_PF11, AID_PF12,
95
AID_PF13, AID_PF14, AID_PF15, AID_PF16, AID_PF17, AID_PF18,
96
AID_PF19, AID_PF20, AID_PF21, AID_PF22, AID_PF23, AID_PF24
98
static unsigned char pa_xlate[] = {
99
AID_PA1, AID_PA2, AID_PA3
101
#define PF_SZ (sizeof(pf_xlate)/sizeof(pf_xlate[0]))
102
#define PA_SZ (sizeof(pa_xlate)/sizeof(pa_xlate[0]))
103
static unsigned long unlock_id;
104
static time_t unlock_delay_time;
105
Boolean key_Character(int code, Boolean with_ge, Boolean pasting,
107
static Boolean flush_ta(void);
108
static void key_AID(unsigned char aid_code);
109
static void kybdlock_set(unsigned int bits, const char *cause);
110
static KeySym MyStringToKeysym(char *s, enum keytype *keytypep,
113
#if defined(X3270_DBCS) /*[*/
114
Boolean key_WCharacter(unsigned char code[], Boolean *skipped);
117
static Boolean insert = False; /* insert mode */
118
static Boolean reverse = False; /* reverse-input mode */
121
unsigned int kybdlock = KL_NOT_CONNECTED;
122
unsigned char aid = AID_NO; /* current attention ID */
124
/* Composite key mappings. */
128
enum keytype keytype;
130
static struct akeysym cc_first;
131
static struct composite {
132
struct akeysym k1, k2;
133
struct akeysym translation;
134
} *composites = NULL;
135
static int n_composites = 0;
137
#define ak_eq(k1, k2) (((k1).keysym == (k2).keysym) && \
138
((k1).keytype == (k2).keytype))
145
} *ta_head = (struct ta *) NULL,
146
*ta_tail = (struct ta *) NULL;
148
static char dxl[] = "0123456789abcdef";
149
#define FROM_HEX(c) (strchr(dxl, tolower(c)) - dxl)
151
extern Widget *screen;
153
#define KYBDLOCK_IS_OERR (kybdlock && !(kybdlock & ~KL_OERR_MASK))
157
* Put an action on the typeahead queue.
160
enq_ta(XtActionProc fn, char *parm1, char *parm2)
164
/* If no connection, forget it. */
166
trace_event(" dropped (not connected)\n");
170
/* If operator error, complain and drop it. */
171
if (kybdlock & KL_OERR_MASK) {
173
trace_event(" dropped (operator error)\n");
177
/* If scroll lock, complain and drop it. */
178
if (kybdlock & KL_SCROLLED) {
180
trace_event(" dropped (scrolled)\n");
184
/* If typeahead disabled, complain and drop it. */
185
if (!appres.typeahead) {
186
trace_event(" dropped (no typeahead)\n");
190
ta = (struct ta *) Malloc(sizeof(*ta));
191
ta->next = (struct ta *) NULL;
193
ta->parm1 = ta->parm2 = CN;
195
ta->parm1 = NewString(parm1);
197
ta->parm2 = NewString(parm2);
203
status_typeahead(True);
207
trace_event(" action queued (kybdlock 0x%x)\n", kybdlock);
211
* Execute an action from the typeahead queue.
218
if (kybdlock || (ta = ta_head) == (struct ta *)NULL)
221
if ((ta_head = ta->next) == (struct ta *)NULL) {
222
ta_tail = (struct ta *)NULL;
223
status_typeahead(False);
226
action_internal(ta->fn, IA_TYPEAHEAD, ta->parm1, ta->parm2);
235
* Flush the typeahead queue.
236
* Returns whether or not anything was flushed.
241
struct ta *ta, *next;
244
for (ta = ta_head; ta != (struct ta *) NULL; ta = next) {
251
ta_head = ta_tail = (struct ta *) NULL;
252
status_typeahead(False);
256
/* Decode keyboard lock bits. */
258
kybdlock_decode(char *how, unsigned int bits)
260
static char buf[1024];
264
if (bits == (unsigned int)-1)
266
if (bits & KL_OERR_MASK) {
267
s += sprintf(s, "%sOERR(", how);
268
switch(bits & KL_OERR_MASK) {
269
case KL_OERR_PROTECTED:
270
s += sprintf(s, "PROTECTED");
272
case KL_OERR_NUMERIC:
273
s += sprintf(s, "NUMERIC");
275
case KL_OERR_OVERFLOW:
276
s += sprintf(s, "OVERFLOW");
279
s += sprintf(s, "DBCS");
282
s += sprintf(s, "?%d", bits & KL_OERR_MASK);
285
s += sprintf(s, ")");
288
if (bits & KL_NOT_CONNECTED) {
289
s += sprintf(s, "%s%sNOT_CONNECTED", space, how);
292
if (bits & KL_AWAITING_FIRST) {
293
s += sprintf(s, "%s%sAWAITING_FIRST", space, how);
296
if (bits & KL_OIA_TWAIT) {
297
s += sprintf(s, "%s%sOIA_TWAIT", space, how);
300
if (bits & KL_OIA_LOCKED) {
301
s += sprintf(s, "%s%sOIA_LOCKED", space, how);
304
if (bits & KL_DEFERRED_UNLOCK) {
305
s += sprintf(s, "%s%sDEFERRED_UNLOCK", space, how);
308
if (bits & KL_ENTER_INHIBIT) {
309
s += sprintf(s, "%s%sENTER_INHIBIT", space, how);
312
if (bits & KL_SCROLLED) {
313
s += sprintf(s, "%s%sSCROLLED", space, how);
316
if (bits & KL_OIA_MINUS) {
317
s += sprintf(s, "%s%sOIA_MINUS", space, how);
324
/* Set bits in the keyboard lock. */
326
kybdlock_set(unsigned int bits, const char *cause _is_unused)
330
trace_event("Keyboard lock(%s) %s\n", cause,
331
kybdlock_decode("+", bits));
334
#if defined(KYBDLOCK_TRACE) /*[*/
335
trace_event(" %s: kybdlock |= 0x%04x, 0x%04x -> 0x%04x\n",
336
cause, bits, kybdlock, n);
338
if ((kybdlock ^ bits) & KL_DEFERRED_UNLOCK) {
339
/* Turned on deferred unlock. */
340
unlock_delay_time = time(NULL);
347
/* Clear bits in the keyboard lock. */
349
kybdlock_clr(unsigned int bits, const char *cause _is_unused)
354
trace_event("Keyboard unlock(%s) %s\n", cause,
355
kybdlock_decode("-", kybdlock & bits));
356
n = kybdlock & ~bits;
358
#if defined(KYBDLOCK_TRACE) /*[*/
359
trace_event(" %s: kybdlock &= ~0x%04x, 0x%04x -> 0x%04x\n",
360
cause, bits, kybdlock, n);
362
if ((kybdlock ^ n) & KL_DEFERRED_UNLOCK) {
363
/* Turned off deferred unlock. */
364
unlock_delay_time = 0;
372
* Set or clear enter-inhibit mode.
375
kybd_inhibit(Boolean inhibit)
378
kybdlock_set(KL_ENTER_INHIBIT, "kybd_inhibit");
379
if (kybdlock == KL_ENTER_INHIBIT)
382
kybdlock_clr(KL_ENTER_INHIBIT, "kybd_inhibit");
389
* Called when a host connects or disconnects.
392
kybd_connect(Boolean connected)
394
if ((kybdlock & KL_DEFERRED_UNLOCK) && unlock_id) {
395
RemoveTimeOut(unlock_id);
398
kybdlock_clr(-1, "kybd_connect");
401
/* Wait for any output or a WCC(restore) from the host */
402
kybdlock_set(KL_AWAITING_FIRST, "kybd_connect");
404
kybdlock_set(KL_NOT_CONNECTED, "kybd_connect");
410
* Called when we switch between 3270 and ANSI modes.
413
kybd_in3270(Boolean in3270 _is_unused)
415
if ((kybdlock & KL_DEFERRED_UNLOCK) && unlock_id) {
416
RemoveTimeOut(unlock_id);
420
switch ((int)cstate) {
421
case CONNECTED_INITIAL_E:
423
* Either we just negotiated TN3270E, or we just processed
424
* and UNBIND from the host. In either case, we are now
425
* awaiting a first unlock from the host, or a transition to
426
* 3270, NVT or SSCP-LU mode.
428
kybdlock_set(KL_AWAITING_FIRST, "kybd_in3270");
434
* We just transitioned to ANSI, TN3270E NVT or TN3270E SSCP-LU
435
* mode. Remove all lock bits.
437
kybdlock_clr(-1, "kybd_in3270");
441
* We just transitioned into or out of 3270 mode.
442
* Remove all lock bits except AWAITING_FIRST.
444
kybdlock_clr(~KL_AWAITING_FIRST, "kybd_in3270");
448
/* There might be a macro pending. */
454
* Called to initialize the keyboard logic.
459
/* Register interest in connect and disconnect events. */
460
register_schange(ST_CONNECT, kybd_connect);
461
register_schange(ST_3270_MODE, kybd_in3270);
465
* Toggle insert mode.
468
insert_mode(Boolean on)
471
status_insert_mode(on);
475
* Toggle reverse mode.
478
reverse_mode(Boolean on)
480
#if defined(X3270_DBCS) /*[*/
485
status_reverse_mode(on);
490
* Lock the keyboard because of an operator error.
493
operator_error(int error_type)
496
popup_an_error("Keyboard locked");
497
if (appres.oerr_lock || sms_redirect()) {
498
status_oerr(error_type);
500
kybdlock_set((unsigned int)error_type, "operator_error");
509
* Handle an AID (Attention IDentifier) key. This is the common stuff that
510
* gets executed for all AID keys (PFs, PAs, Clear and etc).
513
key_AID(unsigned char aid_code)
515
#if defined(X3270_ANSI) /*[*/
519
if (aid_code == AID_ENTER) {
523
for (i = 0; i < PF_SZ; i++)
524
if (aid_code == pf_xlate[i]) {
528
for (i = 0; i < PA_SZ; i++)
529
if (aid_code == pa_xlate[i]) {
536
#if defined(X3270_PLUGIN) /*[*/
537
plugin_aid(aid_code);
541
if (kybdlock & KL_OIA_MINUS)
545
/* Handled locally. */
549
* Act as if the host had written our input, and
550
* send it as a Read Modified.
552
buffer_addr = cursor_addr;
554
ctlr_read_modified(aid, False);
558
/* Everything else is invalid in SSCP-LU mode. */
560
kybdlock_set(KL_OIA_MINUS, "key_AID");
569
kybdlock_set(KL_OIA_TWAIT | KL_OIA_LOCKED, "key_AID");
571
ctlr_read_modified(aid, False);
572
ticking_start(False);
577
PF_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
581
action_debug(PF_action, event, params, num_params);
582
if (check_usage(PF_action, *num_params, 1, 1) < 0)
585
if (k < 1 || k > PF_SZ) {
586
popup_an_error("%s: Invalid argument '%s'",
587
action_name(PF_action), params[0]);
588
cancel_if_idle_command();
592
if (kybdlock & KL_OIA_MINUS)
595
enq_ta(PF_action, params[0], CN);
597
key_AID(pf_xlate[k-1]);
601
PA_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
605
action_debug(PA_action, event, params, num_params);
606
if (check_usage(PA_action, *num_params, 1, 1) < 0)
609
if (k < 1 || k > PA_SZ) {
610
popup_an_error("%s: Invalid argument '%s'",
611
action_name(PA_action), params[0]);
612
cancel_if_idle_command();
616
if (kybdlock & KL_OIA_MINUS)
619
enq_ta(PA_action, params[0], CN);
621
key_AID(pa_xlate[k-1]);
626
* ATTN key, per RFC 2355. Sends IP, regardless.
629
Attn_action(Widget w _is_unused, XEvent *event, String *params,
630
Cardinal *num_params)
632
action_debug(Attn_action, event, params, num_params);
633
if (check_usage(Attn_action, *num_params, 0, 0) < 0)
644
kybdlock_set(KL_OIA_MINUS, "Attn_action");
652
* IAC IP, which works for 5250 System Request and interrupts the program
653
* on an AS/400, even when the keyboard is locked.
655
* This is now the same as the Attn action.
658
Interrupt_action(Widget w _is_unused, XEvent *event, String *params,
659
Cardinal *num_params)
661
action_debug(Interrupt_action, event, params, num_params);
662
if (check_usage(Interrupt_action, *num_params, 0, 0) < 0)
673
* Prepare for an insert of 'count' bytes.
674
* Returns True if the insert is legal, False otherwise.
677
ins_prep(int faddr, int baddr, int count, Boolean *no_room)
688
/* Find the end of the field. */
690
/* Unformatted. Use the end of the line. */
691
next_faddr = (((baddr / COLS) + 1) * COLS) % (ROWS*COLS);
695
while (next_faddr != faddr && !ea_buf[next_faddr].fa) {
700
/* Are there enough NULLs or trailing blanks available? */
704
while (need && (xaddr != next_faddr)) {
705
if (ea_buf[xaddr].cc == EBC_null)
707
else if (toggled(BLANK_FILL) &&
708
((ea_buf[xaddr].cc == EBC_space) ||
709
(ea_buf[xaddr].cc == EBC_underscore))) {
719
#if defined(_ST) /*[*/
720
printf("need %d at %d, tb_start at %d\n", count, baddr, tb_start);
722
if (need - ntb > 0) {
724
operator_error(KL_OERR_OVERFLOW);
733
* Shift the buffer to the right until we've consumed the available
734
* (and needed) NULLs.
738
while (need && (xaddr != next_faddr)) {
743
((ea_buf[xaddr].cc == EBC_null) ||
744
(tb_start >= 0 && xaddr >= tb_start))) {
747
if (first_null == -1)
754
/* Shift right n_nulls worth. */
755
copy_len = first_null - baddr;
757
copy_len += ROWS*COLS;
758
to = (baddr + n_nulls) % (ROWS*COLS);
759
#if defined(_ST) /*[*/
760
printf("found %d NULLs at %d\n", n_nulls, first_null);
761
printf("copying %d from %d to %d\n", copy_len, to,
765
ctlr_wrapping_memmove(to, baddr, copy_len);
774
#define GE_WFLAG 0x100
775
#define PASTE_WFLAG 0x200
778
key_Character_wrapper(Widget w _is_unused, XEvent *event _is_unused, String *params,
779
Cardinal *num_params _is_unused)
782
Boolean with_ge = False;
783
Boolean pasting = False;
787
code = atoi(params[0]);
788
if (code & GE_WFLAG) {
792
if (code & PASTE_WFLAG) {
794
code &= ~PASTE_WFLAG;
796
ebcdic_to_multibyte_x(code, with_ge? CS_GE: CS_BASE,
797
mb, sizeof(mb), EUO_BLANK_UNDEF, &uc);
798
trace_event(" %s -> Key(%s\"%s\")\n",
799
ia_name[(int) ia_cause],
800
with_ge ? "GE " : "", mb);
801
(void) key_Character(code, with_ge, pasting, NULL);
805
* Handle an ordinary displayable character key. Lots of stuff to handle
806
* insert-mode, protected fields and etc.
809
key_Character(int code, Boolean with_ge, Boolean pasting, Boolean *skipped)
811
register int baddr, faddr, xaddr;
812
register unsigned char fa;
813
enum dbcs_why why = DBCS_FIELD;
814
Boolean no_room = False;
824
(void) sprintf(codename, "%d", code |
825
(with_ge ? GE_WFLAG : 0) |
826
(pasting ? PASTE_WFLAG : 0));
827
enq_ta(key_Character_wrapper, codename, CN);
831
faddr = find_field_attribute(baddr);
832
fa = get_field_attribute(baddr);
833
if (ea_buf[baddr].fa || FA_IS_PROTECTED(fa)) {
834
operator_error(KL_OERR_PROTECTED);
837
if (appres.numeric_lock && FA_IS_NUMERIC(fa) &&
838
!((code >= EBC_0 && code <= EBC_9) ||
839
code == EBC_minus || code == EBC_period)) {
840
operator_error(KL_OERR_NUMERIC);
844
/* Can't put an SBCS in a DBCS field. */
845
if (ea_buf[faddr].cs == CS_DBCS) {
846
operator_error(KL_OERR_DBCS);
850
/* If it's an SI (end of DBCS subfield), move over one position. */
851
if (ea_buf[baddr].cc == EBC_si) {
853
if (baddr == faddr) {
854
operator_error(KL_OERR_OVERFLOW);
859
/* Add the character. */
860
if (ea_buf[baddr].cc == EBC_so) {
863
if (!ins_prep(faddr, baddr, 1, &no_room))
866
Boolean was_si = False;
869
* Overwriting an SO (start of DBCS subfield).
870
* If it's followed by an SI, replace the SO/SI
871
* pair with x/space. If not, replace it and
872
* the following DBCS character with
877
was_si = (ea_buf[xaddr].cc == EBC_si);
878
ctlr_add(xaddr, EBC_space, CS_BASE);
879
ctlr_add_fg(xaddr, 0);
880
#if defined(X3270_ANSI) /*[*/
881
ctlr_add_bg(xaddr, 0);
885
ctlr_add(xaddr, EBC_so, CS_BASE);
886
ctlr_add_fg(xaddr, 0);
887
#if defined(X3270_ANSI) /*[*/
888
ctlr_add_bg(xaddr, 0);
893
} else switch (ctlr_lookleft_state(baddr, &why)) {
896
/* fall through... */
898
if (why == DBCS_ATTRIBUTE) {
900
if (!ins_prep(faddr, baddr, 1, &no_room))
904
* Replace single DBCS char with
909
ctlr_add(xaddr, EBC_space, CS_BASE);
910
ctlr_add_fg(xaddr, 0);
911
ctlr_add_gr(xaddr, 0);
918
* Inserting SBCS into a DBCS subfield.
919
* If this is the first position, we
920
* can just insert one character in
921
* front of the SO. Otherwise, we'll
922
* need room for SI (to end subfield),
923
* the character, and SO (to begin the
928
if (ea_buf[xaddr].cc == EBC_so) {
930
if (!ins_prep(faddr, baddr, 1,
934
if (!ins_prep(faddr, baddr, 3,
938
ctlr_add(xaddr, EBC_si,
940
ctlr_add_fg(xaddr, 0);
941
ctlr_add_gr(xaddr, 0);
945
ctlr_add(xaddr, EBC_so,
947
ctlr_add_fg(xaddr, 0);
948
ctlr_add_gr(xaddr, 0);
951
/* Overwriting part of a subfield. */
953
ctlr_add(xaddr, EBC_si, CS_BASE);
954
ctlr_add_fg(xaddr, 0);
955
ctlr_add_gr(xaddr, 0);
959
was_si = (ea_buf[xaddr].cc == EBC_si);
960
ctlr_add(xaddr, EBC_space, CS_BASE);
961
ctlr_add_fg(xaddr, 0);
962
ctlr_add_gr(xaddr, 0);
965
ctlr_add(xaddr, EBC_so,
967
ctlr_add_fg(xaddr, 0);
968
ctlr_add_gr(xaddr, 0);
975
if ((reverse || insert) && !ins_prep(faddr, baddr, 1, &no_room))
982
} while (ea_buf[baddr].fa);
984
ctlr_add(baddr, (unsigned char)code,
985
(unsigned char)(with_ge ? CS_GE : 0));
986
ctlr_add_fg(baddr, 0);
987
ctlr_add_gr(baddr, 0);
992
/* Replace leading nulls with blanks, if desired. */
993
if (formatted && toggled(BLANK_FILL)) {
994
register int baddr_fill = baddr;
997
while (baddr_fill != faddr) {
999
/* Check for backward line wrap. */
1000
if ((baddr_fill % COLS) == COLS - 1) {
1001
Boolean aborted = True;
1002
register int baddr_scan = baddr_fill;
1005
* Check the field within the preceeding line
1008
while (baddr_scan != faddr) {
1009
if (ea_buf[baddr_scan].cc != EBC_null) {
1013
if (!(baddr_scan % COLS))
1021
if (ea_buf[baddr_fill].cc == EBC_null)
1022
ctlr_add(baddr_fill, EBC_space, 0);
1027
mdt_set(cursor_addr);
1030
* Implement auto-skip, and don't land on attribute bytes.
1031
* This happens for all pasted data (even DUP), and for all
1032
* keyboard-generated data except DUP.
1034
if (pasting || (code != EBC_dup)) {
1035
while (ea_buf[baddr].fa) {
1036
if (skipped != NULL)
1038
if (FA_IS_SKIP(ea_buf[baddr].fa))
1039
baddr = next_unprotected(baddr);
1046
(void) ctlr_dbcs_postprocess();
1050
#if defined(X3270_DBCS) /*[*/
1052
key_WCharacter_wrapper(Widget w _is_unused, XEvent *event _is_unused, String *params,
1053
Cardinal *num_params _is_unused)
1056
unsigned char codebuf[2];
1058
code = atoi(params[0]);
1059
trace_event(" %s -> Key(0x%04x)\n",
1060
ia_name[(int) ia_cause], code);
1061
codebuf[0] = (code >> 8) & 0xff;
1062
codebuf[1] = code & 0xff;
1063
(void) key_WCharacter(codebuf, NULL);
1067
* Input a DBCS character.
1068
* Returns True if a character was stored in the buffer, False otherwise.
1071
key_WCharacter(unsigned char code[], Boolean *skipped)
1074
register unsigned char fa;
1078
Boolean done = False;
1079
Boolean no_si = False;
1080
Boolean no_room = False;
1081
extern unsigned char reply_mode; /* XXX */
1088
(void) sprintf(codename, "%d", (code[0] << 8) | code[1]);
1089
enq_ta(key_WCharacter_wrapper, codename, CN);
1093
if (skipped != NULL)
1097
#if defined(X3270_DBCS) /*[*/
1101
trace_event("DBCS character received when not in DBCS mode, "
1106
#if defined(X3270_ANSI) /*[*/
1111
(void) ebcdic_to_multibyte((code[0] << 8) | code[1], mb,
1118
baddr = cursor_addr;
1119
fa = get_field_attribute(baddr);
1120
faddr = find_field_attribute(baddr);
1123
if (ea_buf[baddr].fa || FA_IS_PROTECTED(fa)) {
1124
operator_error(KL_OERR_PROTECTED);
1129
if (appres.numeric_lock && FA_IS_NUMERIC(fa)) {
1130
operator_error(KL_OERR_NUMERIC);
1135
* Figure our what to do based on the DBCS state of the buffer.
1136
* Leaves baddr pointing to the next unmodified position.
1139
switch (d = ctlr_dbcs_state(baddr)) {
1141
case DBCS_RIGHT_WRAP:
1142
/* Back up one position and process it as a LEFT. */
1144
/* fall through... */
1146
case DBCS_LEFT_WRAP:
1147
/* Overwrite the existing character. */
1149
if (!ins_prep(faddr, baddr, 2, &no_room)) {
1153
ctlr_add(baddr, code[0], ea_buf[baddr].cs);
1155
ctlr_add(baddr, code[1], ea_buf[baddr].cs);
1160
/* Back up one position and process it as an SI. */
1162
/* fall through... */
1164
/* Extend the subfield to the right. */
1166
if (!ins_prep(faddr, baddr, 2, &no_room)) {
1170
/* Don't overwrite a field attribute or an SO. */
1172
INC_BA(xaddr); /* C1 */
1173
if (ea_buf[xaddr].fa)
1175
if (ea_buf[xaddr].cc == EBC_so)
1177
INC_BA(xaddr); /* SI */
1178
if (ea_buf[xaddr].fa || ea_buf[xaddr].cc == EBC_so)
1181
ctlr_add(baddr, code[0], ea_buf[baddr].cs);
1183
ctlr_add(baddr, code[1], ea_buf[baddr].cs);
1186
ctlr_add(baddr, EBC_si, ea_buf[baddr].cs);
1193
if (ea_buf[faddr].ic) {
1194
Boolean extend_left = False;
1196
/* Is there room? */
1198
if (!ins_prep(faddr, baddr, 4, &no_room)) {
1202
xaddr = baddr; /* baddr, SO */
1203
if (ea_buf[xaddr].cc == EBC_so) {
1205
* (baddr), where we would have put the
1206
* SO, is already an SO. Move to
1207
* (baddr+1) and try again.
1209
#if defined(DBCS_RIGHT_DEBUG) /*[*/
1210
printf("SO in position 0\n");
1216
INC_BA(xaddr); /* baddr+1, C0 */
1217
if (ea_buf[xaddr].fa)
1219
if (ea_buf[xaddr].cc == EBC_so) {
1223
* (baddr+1), where we would have put
1224
* the left side of the DBCS, is a SO.
1225
* If there's room, we can extend the
1226
* subfield to the left. If not, we're
1231
e = ctlr_dbcs_state(xaddr);
1232
if (e == DBCS_NONE || e == DBCS_SB) {
1235
#if defined(DBCS_RIGHT_DEBUG) /*[*/
1236
printf("SO in position 1, "
1241
* Won't actually happen,
1242
* because this implies that
1243
* the buffer addr at baddr
1246
#if defined(DBCS_RIGHT_DEBUG) /*[*/
1247
printf("SO in position 1, "
1255
INC_BA(xaddr); /* baddr+2, C1 */
1256
if (ea_buf[xaddr].fa)
1258
if (ea_buf[xaddr].cc == EBC_so) {
1260
* (baddr+2), where we want to put the
1261
* right half of the DBCS character, is
1262
* a SO. This is a natural extension
1263
* to the left -- just make sure we
1264
* don't write an SI.
1267
#if defined(DBCS_RIGHT_DEBUG) /*[*/
1268
printf("SO in position 2, no SI\n");
1273
* Check the fourth position only if we're
1274
* not doing an extend-left.
1277
INC_BA(xaddr); /* baddr+3, SI */
1278
if (ea_buf[xaddr].fa)
1280
if (ea_buf[xaddr].cc == EBC_so) {
1282
* (baddr+3), where we want to
1284
* SI, is an SO. Forget it.
1286
#if defined(DBCS_RIGHT_DEBUG) /*[*/
1287
printf("SO in position 3, "
1299
ctlr_add(baddr, EBC_so, ea_buf[baddr].cs);
1301
ctlr_add(baddr, code[0], ea_buf[baddr].cs);
1303
ctlr_add(baddr, code[1], ea_buf[baddr].cs);
1306
ctlr_add(baddr, EBC_si, ea_buf[baddr].cs);
1309
} else if (reply_mode == SF_SRM_CHAR) {
1310
/* Use the character attribute. */
1312
if (!ins_prep(faddr, baddr, 2, &no_room)) {
1318
if (ea_buf[xaddr].fa)
1321
ctlr_add(baddr, code[0], CS_DBCS);
1323
ctlr_add(baddr, code[1], CS_DBCS);
1331
/* Implement blank fill mode. */
1332
if (toggled(BLANK_FILL)) {
1335
while (xaddr != baddr) {
1336
if (ea_buf[xaddr].cc == EBC_null)
1337
ctlr_add(xaddr, EBC_space, CS_BASE);
1344
mdt_set(cursor_addr);
1346
/* Implement auto-skip. */
1347
while (ea_buf[baddr].fa) {
1348
if (skipped != NULL)
1350
if (FA_IS_SKIP(ea_buf[baddr].fa))
1351
baddr = next_unprotected(baddr);
1356
(void) ctlr_dbcs_postprocess();
1359
operator_error(KL_OERR_DBCS);
1366
* Handle an ordinary character key, given its Unicode value.
1369
key_UCharacter(ucs4_t ucs4, enum keytype keytype, enum iaction cause,
1377
if (skipped != NULL)
1381
ak.keytype = keytype;
1383
switch (composing) {
1387
for (i = 0; i < n_composites; i++)
1388
if (ak_eq(composites[i].k1, ak) ||
1389
ak_eq(composites[i].k2, ak))
1391
if (i < n_composites) {
1392
cc_first.keysym = ucs4;
1393
cc_first.keytype = keytype;
1395
status_compose(True, ucs4, keytype);
1399
status_compose(False, 0, KT_STD);
1404
status_compose(False, 0, KT_STD);
1405
for (i = 0; i < n_composites; i++)
1406
if ((ak_eq(composites[i].k1, cc_first) &&
1407
ak_eq(composites[i].k2, ak)) ||
1408
(ak_eq(composites[i].k1, ak) &&
1409
ak_eq(composites[i].k2, cc_first)))
1411
if (i < n_composites) {
1412
ucs4 = composites[i].translation.keysym;
1413
keytype = composites[i].translation.keytype;
1421
trace_event(" %s -> Key(U+%04x)\n", ia_name[(int) cause], ucs4);
1427
trace_event(" dropped (control char)\n");
1430
ebc = unicode_to_ebcdic_ge(ucs4, &ge);
1432
trace_event(" dropped (no EBCDIC translation)\n");
1435
#if defined(X3270_DBCS) /*[*/
1437
unsigned char code[2];
1439
code[0] = (ebc & 0xff00)>> 8;
1440
code[1] = ebc & 0xff;
1441
(void) key_WCharacter(code, skipped);
1444
(void) key_Character(ebc, (keytype == KT_GE) || ge,
1447
#if defined(X3270_ANSI) /*[*/
1451
unicode_to_multibyte(ucs4, mb, sizeof(mb));
1456
trace_event(" dropped (not connected)\n");
1460
#if defined(X3270_DISPLAY) /*[*/
1462
* Handle an ordinary character key, given its NULL-terminated multibyte
1466
key_ACharacter(char *mb, enum keytype keytype, enum iaction cause,
1475
if (skipped != NULL)
1478
/* Convert the multibyte string to UCS4. */
1479
ucs4 = multibyte_to_unicode(mb, strlen(mb), &consumed, &error);
1481
trace_event(" %s -> Key(?)\n", ia_name[(int) cause]);
1482
trace_event(" dropped (invalid multibyte sequence)\n");
1486
key_UCharacter(ucs4, keytype, cause, skipped);
1494
#if defined(X3270_DISPLAY) /*[*/
1496
AltCursor_action(Widget w _is_unused, XEvent *event, String *params,
1497
Cardinal *num_params)
1499
action_debug(AltCursor_action, event, params, num_params);
1500
if (check_usage(AltCursor_action, *num_params, 0, 0) < 0)
1503
do_toggle(ALT_CURSOR);
1508
MonoCase_action(Widget w _is_unused, XEvent *event, String *params,
1509
Cardinal *num_params)
1511
action_debug(MonoCase_action, event, params, num_params);
1512
if (check_usage(MonoCase_action, *num_params, 0, 0) < 0)
1515
do_toggle(MONOCASE);
1519
* Flip the display left-to-right
1522
Flip_action(Widget w _is_unused, XEvent *event, String *params,
1523
Cardinal *num_params)
1525
action_debug(Flip_action, event, params, num_params);
1526
if (check_usage(Flip_action, *num_params, 0, 0) < 0)
1529
#if defined(X3270_DBCS) /*[*/
1538
* Tab forward to next field.
1541
Tab_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
1543
action_debug(Tab_action, event, params, num_params);
1544
if (check_usage(Tab_action, *num_params, 0, 0) < 0)
1548
if (KYBDLOCK_IS_OERR) {
1549
kybdlock_clr(KL_OERR_MASK, "Tab");
1552
enq_ta(Tab_action, CN, CN);
1556
#if defined(X3270_ANSI) /*[*/
1562
cursor_move(next_unprotected(cursor_addr));
1567
* Tab backward to previous field.
1570
BackTab_action(Widget w _is_unused, XEvent *event, String *params,
1571
Cardinal *num_params)
1573
register int baddr, nbaddr;
1576
action_debug(BackTab_action, event, params, num_params);
1577
if (check_usage(BackTab_action, *num_params, 0, 0) < 0)
1581
if (KYBDLOCK_IS_OERR) {
1582
kybdlock_clr(KL_OERR_MASK, "BackTab");
1585
enq_ta(BackTab_action, CN, CN);
1591
baddr = cursor_addr;
1593
if (ea_buf[baddr].fa) /* at bof */
1599
if (ea_buf[baddr].fa &&
1600
!FA_IS_PROTECTED(ea_buf[baddr].fa) &&
1604
if (baddr == sbaddr) {
1615
* Deferred keyboard unlock.
1621
kybdlock_clr(KL_DEFERRED_UNLOCK, "defer_unlock");
1628
* Reset keyboard lock.
1631
do_reset(Boolean explicit)
1634
* If explicit (from the keyboard) and there is typeahead or
1635
* a half-composed key, simply flush it.
1638
#if defined(X3270_FT) /*[*/
1639
|| ft_state != FT_NONE
1642
Boolean half_reset = False;
1646
if (composing != NONE) {
1648
status_compose(False, 0, KT_STD);
1655
/* Always clear insert mode. */
1658
/* Otherwise, if not connect, reset is a no-op. */
1663
* Remove any deferred keyboard unlock. We will either unlock the
1664
* keyboard now, or want to defer further into the future.
1666
if ((kybdlock & KL_DEFERRED_UNLOCK) && unlock_id) {
1667
RemoveTimeOut(unlock_id);
1672
* If explicit (from the keyboard), unlock the keyboard now.
1673
* Otherwise (from the host), schedule a deferred keyboard unlock.
1676
#if defined(X3270_FT) /*[*/
1677
|| ft_state != FT_NONE
1679
|| (!appres.unlock_delay && !sms_in_macro())
1680
|| (unlock_delay_time != 0 && (time(NULL) - unlock_delay_time) > 1)
1681
|| !appres.unlock_delay_ms) {
1682
kybdlock_clr(-1, "do_reset");
1683
} else if (kybdlock &
1684
(KL_DEFERRED_UNLOCK | KL_OIA_TWAIT | KL_OIA_LOCKED | KL_AWAITING_FIRST)) {
1685
kybdlock_clr(~KL_DEFERRED_UNLOCK, "do_reset");
1686
kybdlock_set(KL_DEFERRED_UNLOCK, "do_reset");
1687
unlock_id = AddTimeOut(appres.unlock_delay_ms, defer_unlock);
1688
trace_event("Deferring keyboard unlock %dms\n",
1689
appres.unlock_delay_ms);
1692
/* Clean up other modes. */
1696
status_compose(False, 0, KT_STD);
1700
Reset_action(Widget w _is_unused, XEvent *event, String *params,
1701
Cardinal *num_params)
1703
action_debug(Reset_action, event, params, num_params);
1704
if (check_usage(Reset_action, *num_params, 0, 0) < 0)
1712
* Move to first unprotected field on screen.
1715
Home_action(Widget w _is_unused, XEvent *event, String *params,
1716
Cardinal *num_params)
1718
action_debug(Home_action, event, params, num_params);
1719
if (check_usage(Home_action, *num_params, 0, 0) < 0)
1723
enq_ta(Home_action, CN, CN);
1726
#if defined(X3270_ANSI) /*[*/
1736
cursor_move(next_unprotected(ROWS*COLS-1));
1741
* Cursor left 1 position.
1749
baddr = cursor_addr;
1751
d = ctlr_dbcs_state(baddr);
1754
} else if (IS_LEFT(d)) {
1756
d = ctlr_dbcs_state(baddr);
1764
Left_action(Widget w _is_unused, XEvent *event, String *params,
1765
Cardinal *num_params)
1767
action_debug(Left_action, event, params, num_params);
1768
if (check_usage(Left_action, *num_params, 0, 0) < 0)
1772
if (KYBDLOCK_IS_OERR) {
1773
kybdlock_clr(KL_OERR_MASK, "Left");
1776
enq_ta(Left_action, CN, CN);
1780
#if defined(X3270_ANSI) /*[*/
1791
baddr = cursor_addr;
1800
* Returns "True" if succeeds, "False" otherwise.
1805
register int baddr, end_baddr;
1807
register unsigned char fa;
1811
baddr = cursor_addr;
1813
/* Can't delete a field attribute. */
1814
fa = get_field_attribute(baddr);
1815
if (FA_IS_PROTECTED(fa) || ea_buf[baddr].fa) {
1816
operator_error(KL_OERR_PROTECTED);
1819
if (ea_buf[baddr].cc == EBC_so || ea_buf[baddr].cc == EBC_si) {
1821
* Can't delete SO or SI, unless it's adjacent to its
1826
if (ea_buf[xaddr].cc == SOSI(ea_buf[baddr].cc)) {
1829
operator_error(KL_OERR_PROTECTED);
1832
} else if (IS_DBCS(ea_buf[baddr].db)) {
1833
if (IS_RIGHT(ea_buf[baddr].db))
1844
if (ea_buf[end_baddr].fa)
1846
} while (end_baddr != baddr);
1849
if ((baddr % COLS) == COLS - ndel)
1851
end_baddr = baddr + (COLS - (baddr % COLS)) - 1;
1854
/* Shift the remainder of the field left. */
1855
if (end_baddr > baddr) {
1856
ctlr_bcopy(baddr + ndel, baddr, end_baddr - (baddr + ndel) + 1,
1858
} else if (end_baddr != baddr) {
1859
/* XXX: Need to verify this. */
1860
ctlr_bcopy(baddr + ndel, baddr,
1861
((ROWS * COLS) - 1) - (baddr + ndel) + 1, 0);
1862
ctlr_bcopy(0, (ROWS * COLS) - ndel, ndel, 0);
1863
ctlr_bcopy(ndel, 0, end_baddr - ndel + 1, 0);
1866
/* NULL fill at the end. */
1867
for (i = 0; i < ndel; i++)
1868
ctlr_add(end_baddr - i, EBC_null, 0);
1870
/* Set the MDT for this field. */
1871
mdt_set(cursor_addr);
1873
/* Patch up the DBCS state for display. */
1874
(void) ctlr_dbcs_postprocess();
1879
Delete_action(Widget w _is_unused, XEvent *event, String *params,
1880
Cardinal *num_params)
1882
action_debug(Delete_action, event, params, num_params);
1885
enq_ta(Delete_action, CN, CN);
1888
#if defined(X3270_ANSI) /*[*/
1897
int baddr = cursor_addr;
1900
if (!ea_buf[baddr].fa)
1907
* 3270-style backspace.
1910
BackSpace_action(Widget w _is_unused, XEvent *event, String *params,
1911
Cardinal *num_params)
1913
action_debug(BackSpace_action, event, params, num_params);
1916
enq_ta(BackSpace_action, CN, CN);
1919
#if defined(X3270_ANSI) /*[*/
1932
baddr = cursor_addr;
1940
* Destructive backspace, like Unix "erase".
1948
baddr = cursor_addr;
1949
faddr = find_field_attribute(baddr);
1950
if (faddr == baddr || FA_IS_PROTECTED(ea_buf[baddr].fa)) {
1951
operator_error(KL_OERR_PROTECTED);
1954
if (baddr && faddr == baddr - 1)
1959
* If we are now on an SI, move left again.
1961
if (ea_buf[cursor_addr].cc == EBC_si) {
1962
baddr = cursor_addr;
1968
* If we landed on the right-hand side of a DBCS character, move to the
1970
* This ensures that if this is the end of a DBCS subfield, we will
1971
* land on the SI, instead of on the character following.
1973
d = ctlr_dbcs_state(cursor_addr);
1975
baddr = cursor_addr;
1981
* Try to delete this character.
1987
* If we've just erased the last character of a DBCS subfield, erase
1988
* the SO/SI pair as well.
1990
baddr = cursor_addr;
1992
if (ea_buf[baddr].cc == EBC_so && ea_buf[cursor_addr].cc == EBC_si) {
1999
Erase_action(Widget w _is_unused, XEvent *event, String *params,
2000
Cardinal *num_params)
2002
action_debug(Erase_action, event, params, num_params);
2005
enq_ta(Erase_action, CN, CN);
2008
#if defined(X3270_ANSI) /*[*/
2022
* Cursor right 1 position.
2025
Right_action(Widget w _is_unused, XEvent *event, String *params,
2026
Cardinal *num_params)
2031
action_debug(Right_action, event, params, num_params);
2034
if (KYBDLOCK_IS_OERR) {
2035
kybdlock_clr(KL_OERR_MASK, "Right");
2038
enq_ta(Right_action, CN, CN);
2042
#if defined(X3270_ANSI) /*[*/
2049
baddr = cursor_addr;
2051
d = ctlr_dbcs_state(baddr);
2061
* Cursor left 2 positions.
2064
Left2_action(Widget w _is_unused, XEvent *event, String *params,
2065
Cardinal *num_params)
2070
action_debug(Left2_action, event, params, num_params);
2073
if (KYBDLOCK_IS_OERR) {
2074
kybdlock_clr(KL_OERR_MASK, "Left2");
2077
enq_ta(Left2_action, CN, CN);
2081
#if defined(X3270_ANSI) /*[*/
2085
baddr = cursor_addr;
2087
d = ctlr_dbcs_state(baddr);
2091
d = ctlr_dbcs_state(baddr);
2099
* Cursor to previous word.
2102
PreviousWord_action(Widget w _is_unused, XEvent *event, String *params,
2103
Cardinal *num_params)
2110
action_debug(PreviousWord_action, event, params, num_params);
2113
enq_ta(PreviousWord_action, CN, CN);
2116
#if defined(X3270_ANSI) /*[*/
2123
baddr = cursor_addr;
2124
prot = FA_IS_PROTECTED(get_field_attribute(baddr));
2126
/* Skip to before this word, if in one now. */
2128
c = ea_buf[baddr].cc;
2129
while (!ea_buf[baddr].fa && c != EBC_space && c != EBC_null) {
2131
if (baddr == cursor_addr)
2133
c = ea_buf[baddr].cc;
2138
/* Find the end of the preceding word. */
2140
c = ea_buf[baddr].cc;
2141
if (ea_buf[baddr].fa) {
2143
prot = FA_IS_PROTECTED(get_field_attribute(baddr));
2146
if (!prot && c != EBC_space && c != EBC_null)
2149
} while (baddr != baddr0);
2151
if (baddr == baddr0)
2154
/* Go it its front. */
2157
c = ea_buf[baddr].cc;
2158
if (ea_buf[baddr].fa || c == EBC_space || c == EBC_null) {
2168
* Cursor right 2 positions.
2171
Right2_action(Widget w _is_unused, XEvent *event, String *params,
2172
Cardinal *num_params)
2177
action_debug(Right2_action, event, params, num_params);
2180
if (KYBDLOCK_IS_OERR) {
2181
kybdlock_clr(KL_OERR_MASK, "Right2");
2184
enq_ta(Right2_action, CN, CN);
2188
#if defined(X3270_ANSI) /*[*/
2192
baddr = cursor_addr;
2194
d = ctlr_dbcs_state(baddr);
2198
d = ctlr_dbcs_state(baddr);
2205
/* Find the next unprotected word, or -1 */
2213
prot = FA_IS_PROTECTED(get_field_attribute(baddr));
2216
c = ea_buf[baddr].cc;
2217
if (ea_buf[baddr].fa)
2218
prot = FA_IS_PROTECTED(ea_buf[baddr].fa);
2219
else if (!prot && c != EBC_space && c != EBC_null)
2222
} while (baddr != baddr0);
2227
/* Find the next word in this field, or -1 */
2233
Boolean in_word = True;
2236
c = ea_buf[baddr].cc;
2237
if (ea_buf[baddr].fa)
2240
if (c == EBC_space || c == EBC_null)
2243
if (c != EBC_space && c != EBC_null)
2247
} while (baddr != baddr0);
2254
* Cursor to next unprotected word.
2257
NextWord_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
2262
action_debug(NextWord_action, event, params, num_params);
2265
enq_ta(NextWord_action, CN, CN);
2268
#if defined(X3270_ANSI) /*[*/
2275
/* If not in an unprotected field, go to the next unprotected word. */
2276
if (ea_buf[cursor_addr].fa ||
2277
FA_IS_PROTECTED(get_field_attribute(cursor_addr))) {
2278
baddr = nu_word(cursor_addr);
2284
/* If there's another word in this field, go to it. */
2285
baddr = nt_word(cursor_addr);
2291
/* If in a word, go to just after its end. */
2292
c = ea_buf[cursor_addr].cc;
2293
if (c != EBC_space && c != EBC_null) {
2294
baddr = cursor_addr;
2296
c = ea_buf[baddr].cc;
2297
if (c == EBC_space || c == EBC_null) {
2300
} else if (ea_buf[baddr].fa) {
2301
baddr = nu_word(baddr);
2307
} while (baddr != cursor_addr);
2309
/* Otherwise, go to the next unprotected word. */
2311
baddr = nu_word(cursor_addr);
2319
* Cursor up 1 position.
2322
Up_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
2326
action_debug(Up_action, event, params, num_params);
2329
if (KYBDLOCK_IS_OERR) {
2330
kybdlock_clr(KL_OERR_MASK, "Up");
2333
enq_ta(Up_action, CN, CN);
2337
#if defined(X3270_ANSI) /*[*/
2343
baddr = cursor_addr - COLS;
2345
baddr = (cursor_addr + (ROWS * COLS)) - COLS;
2351
* Cursor down 1 position.
2354
Down_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
2358
action_debug(Down_action, event, params, num_params);
2361
if (KYBDLOCK_IS_OERR) {
2362
kybdlock_clr(KL_OERR_MASK, "Down");
2365
enq_ta(Down_action, CN, CN);
2369
#if defined(X3270_ANSI) /*[*/
2375
baddr = (cursor_addr + COLS) % (COLS * ROWS);
2381
* Cursor to first field on next line or any lines after that.
2384
Newline_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
2386
register int baddr, faddr;
2387
register unsigned char fa;
2389
action_debug(Newline_action, event, params, num_params);
2390
if (check_usage(Newline_action, *num_params, 0, 0) < 0)
2394
enq_ta(Newline_action, CN, CN);
2397
#if defined(X3270_ANSI) /*[*/
2403
baddr = (cursor_addr + COLS) % (COLS * ROWS); /* down */
2404
baddr = (baddr / COLS) * COLS; /* 1st col */
2405
faddr = find_field_attribute(baddr);
2406
fa = ea_buf[faddr].fa;
2407
if (faddr != baddr && !FA_IS_PROTECTED(fa))
2410
cursor_move(next_unprotected(baddr));
2418
Dup_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
2420
action_debug(Dup_action, event, params, num_params);
2421
if (check_usage(Dup_action, *num_params, 0, 0) < 0)
2425
enq_ta(Dup_action, CN, CN);
2428
#if defined(X3270_ANSI) /*[*/
2432
if (key_Character(EBC_dup, False, False, NULL))
2433
cursor_move(next_unprotected(cursor_addr));
2441
FieldMark_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
2443
action_debug(FieldMark_action, event, params, num_params);
2444
if (check_usage(FieldMark_action, *num_params, 0, 0) < 0)
2448
enq_ta(FieldMark_action, CN, CN);
2451
#if defined(X3270_ANSI) /*[*/
2455
(void) key_Character(EBC_fm, False, False, NULL);
2463
Enter_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
2465
action_debug(Enter_action, event, params, num_params);
2466
if (check_usage(Enter_action, *num_params, 0, 0) < 0)
2469
if (kybdlock & KL_OIA_MINUS)
2472
enq_ta(Enter_action, CN, CN);
2479
SysReq_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
2481
action_debug(SysReq_action, event, params, num_params);
2482
if (check_usage(SysReq_action, *num_params, 0, 0) < 0)
2487
#if defined(X3270_TN3270E) /*[*/
2493
if (kybdlock & KL_OIA_MINUS)
2496
enq_ta(SysReq_action, CN, CN);
2498
key_AID(AID_SYSREQ);
2507
Clear_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
2509
action_debug(Clear_action, event, params, num_params);
2510
if (check_usage(Clear_action, *num_params, 0, 0) < 0)
2513
if (kybdlock & KL_OIA_MINUS)
2515
if (kybdlock && CONNECTED) {
2516
enq_ta(Clear_action, CN, CN);
2519
#if defined(X3270_ANSI) /*[*/
2534
* Cursor Select key (light pen simulator).
2537
lightpen_select(int baddr)
2540
register unsigned char fa;
2542
#if defined(X3270_DBCS) /*[*/
2546
faddr = find_field_attribute(baddr);
2547
fa = ea_buf[faddr].fa;
2548
if (!FA_IS_SELECTABLE(fa)) {
2555
#if defined(X3270_DBCS) /*[*/
2557
if (ea_buf[baddr].cs == CS_DBCS) {
2558
designator2 = designator;
2559
INC_BA(designator2);
2560
if ((ea_buf[designator].db != DBCS_LEFT &&
2561
ea_buf[designator].db != DBCS_LEFT_WRAP) &&
2562
(ea_buf[designator2].db != DBCS_RIGHT &&
2563
ea_buf[designator2].db != DBCS_RIGHT_WRAP)) {
2567
if (ea_buf[designator].cc == 0x42 &&
2568
ea_buf[designator2].cc == EBC_greater) {
2569
ctlr_add(designator2, EBC_question, CS_DBCS);
2571
} else if (ea_buf[designator].cc == 0x42 &&
2572
ea_buf[designator2].cc == EBC_question) {
2573
ctlr_add(designator2, EBC_greater, CS_DBCS);
2575
} else if ((ea_buf[designator].cc == EBC_space &&
2576
ea_buf[designator2].cc == EBC_space) ||
2577
(ea_buf[designator].cc == EBC_null &&
2578
ea_buf[designator2].cc == EBC_null)) {
2579
ctlr_add(designator2, EBC_greater, CS_DBCS);
2581
key_AID(AID_SELECT);
2582
} else if (ea_buf[designator].cc == 0x42 &&
2583
ea_buf[designator2].cc == EBC_ampersand) {
2594
switch (ea_buf[designator].cc) {
2595
case EBC_greater: /* > */
2596
ctlr_add(designator, EBC_question, 0); /* change to ? */
2599
case EBC_question: /* ? */
2600
ctlr_add(designator, EBC_greater, 0); /* change to > */
2603
case EBC_space: /* space */
2604
case EBC_null: /* null */
2606
key_AID(AID_SELECT);
2608
case EBC_ampersand: /* & */
2619
* Cursor Select key (light pen simulator) -- at the current cursor location.
2622
CursorSelect_action(Widget w _is_unused, XEvent *event, String *params,
2623
Cardinal *num_params)
2625
action_debug(CursorSelect_action, event, params, num_params);
2626
if (check_usage(CursorSelect_action, *num_params, 0, 0) < 0)
2630
enq_ta(CursorSelect_action, CN, CN);
2634
#if defined(X3270_ANSI) /*[*/
2638
lightpen_select(cursor_addr);
2641
#if defined(X3270_DISPLAY) /*[*/
2643
* Cursor Select mouse action (light pen simulator).
2646
MouseSelect_action(Widget w, XEvent *event, String *params,
2647
Cardinal *num_params)
2649
action_debug(MouseSelect_action, event, params, num_params);
2650
if (check_usage(MouseSelect_action, *num_params, 0, 0) < 0)
2657
#if defined(X3270_ANSI) /*[*/
2661
lightpen_select(mouse_baddr(w, event));
2667
* Erase End Of Field Key.
2670
EraseEOF_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
2673
register unsigned char fa;
2675
enum dbcs_why why = DBCS_FIELD;
2677
action_debug(EraseEOF_action, event, params, num_params);
2678
if (check_usage(EraseEOF_action, *num_params, 0, 0) < 0)
2682
enq_ta(EraseEOF_action, CN, CN);
2685
#if defined(X3270_ANSI) /*[*/
2689
baddr = cursor_addr;
2690
fa = get_field_attribute(baddr);
2691
if (FA_IS_PROTECTED(fa) || ea_buf[baddr].fa) {
2692
operator_error(KL_OERR_PROTECTED);
2695
if (formatted) { /* erase to next field attribute */
2697
ctlr_add(baddr, EBC_null, 0);
2699
} while (!ea_buf[baddr].fa);
2700
mdt_set(cursor_addr);
2701
} else { /* erase to end of screen */
2703
ctlr_add(baddr, EBC_null, 0);
2705
} while (baddr != 0);
2708
/* If the cursor was in a DBCS subfield, re-create the SI. */
2709
d = ctlr_lookleft_state(cursor_addr, &why);
2710
if (IS_DBCS(d) && why == DBCS_SUBFIELD) {
2711
if (d == DBCS_RIGHT) {
2712
baddr = cursor_addr;
2714
ea_buf[baddr].cc = EBC_si;
2716
ea_buf[cursor_addr].cc = EBC_si;
2718
(void) ctlr_dbcs_postprocess();
2723
* Erase all Input Key.
2726
EraseInput_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
2728
register int baddr, sbaddr;
2732
action_debug(EraseInput_action, event, params, num_params);
2733
if (check_usage(EraseInput_action, *num_params, 0, 0) < 0)
2737
enq_ta(EraseInput_action, CN, CN);
2740
#if defined(X3270_ANSI) /*[*/
2745
/* find first field attribute */
2748
if (ea_buf[baddr].fa)
2751
} while (baddr != 0);
2755
fa = ea_buf[baddr].fa;
2756
if (!FA_IS_PROTECTED(fa)) {
2764
if (!ea_buf[baddr].fa) {
2765
ctlr_add(baddr, EBC_null, 0);
2767
} while (!ea_buf[baddr].fa);
2768
} else { /* skip protected */
2771
} while (!ea_buf[baddr].fa);
2773
} while (baddr != sbaddr);
2785
* Delete word key. Backspaces the cursor until it hits the front of a word,
2786
* deletes characters until it hits a blank or null, and deletes all of these
2789
* Which is to say, does a ^W.
2792
DeleteWord_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
2795
register unsigned char fa;
2797
action_debug(DeleteWord_action, event, params, num_params);
2798
if (check_usage(DeleteWord_action, *num_params, 0, 0) < 0)
2802
enq_ta(DeleteWord_action, CN, CN);
2805
#if defined(X3270_ANSI) /*[*/
2814
baddr = cursor_addr;
2815
fa = get_field_attribute(baddr);
2817
/* Make sure we're on a modifiable field. */
2818
if (FA_IS_PROTECTED(fa) || ea_buf[baddr].fa) {
2819
operator_error(KL_OERR_PROTECTED);
2823
/* Backspace over any spaces to the left of the cursor. */
2825
baddr = cursor_addr;
2827
if (ea_buf[baddr].fa)
2829
if (ea_buf[baddr].cc == EBC_null ||
2830
ea_buf[baddr].cc == EBC_space)
2836
/* Backspace until the character to the left of the cursor is blank. */
2838
baddr = cursor_addr;
2840
if (ea_buf[baddr].fa)
2842
if (ea_buf[baddr].cc == EBC_null ||
2843
ea_buf[baddr].cc == EBC_space)
2853
* Delete field key. Similar to EraseEOF, but it wipes out the entire field
2854
* rather than just to the right of the cursor, and it leaves the cursor at
2855
* the front of the field.
2857
* Which is to say, does a ^U.
2860
DeleteField_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
2863
register unsigned char fa;
2865
action_debug(DeleteField_action, event, params, num_params);
2866
if (check_usage(DeleteField_action, *num_params, 0, 0) < 0)
2870
enq_ta(DeleteField_action, CN, CN);
2873
#if defined(X3270_ANSI) /*[*/
2882
baddr = cursor_addr;
2883
fa = get_field_attribute(baddr);
2884
if (FA_IS_PROTECTED(fa) || ea_buf[baddr].fa) {
2885
operator_error(KL_OERR_PROTECTED);
2888
while (!ea_buf[baddr].fa)
2891
mdt_set(cursor_addr);
2893
while (!ea_buf[baddr].fa) {
2894
ctlr_add(baddr, EBC_null, 0);
2902
* Set insert mode key.
2905
Insert_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
2907
action_debug(Insert_action, event, params, num_params);
2908
if (check_usage(Insert_action, *num_params, 0, 0) < 0)
2912
enq_ta(Insert_action, CN, CN);
2915
#if defined(X3270_ANSI) /*[*/
2924
* Toggle insert mode key.
2927
ToggleInsert_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
2929
action_debug(ToggleInsert_action, event, params, num_params);
2930
if (check_usage(ToggleInsert_action, *num_params, 0, 0) < 0)
2934
enq_ta(ToggleInsert_action, CN, CN);
2937
#if defined(X3270_ANSI) /*[*/
2949
* Toggle reverse mode key.
2952
ToggleReverse_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
2954
action_debug(ToggleReverse_action, event, params, num_params);
2955
if (check_usage(ToggleReverse_action, *num_params, 0, 0) < 0)
2959
enq_ta(ToggleReverse_action, CN, CN);
2962
#if defined(X3270_ANSI) /*[*/
2966
reverse_mode(!reverse);
2971
* Move the cursor to the first blank after the last nonblank in the
2972
* field, or if the field is full, to the last character in the field.
2975
FieldEnd_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
2978
unsigned char fa, c;
2979
int last_nonblank = -1;
2981
action_debug(FieldEnd_action, event, params, num_params);
2982
if (check_usage(FieldEnd_action, *num_params, 0, 0) < 0)
2986
enq_ta(FieldEnd_action, CN, CN);
2989
#if defined(X3270_ANSI) /*[*/
2995
baddr = cursor_addr;
2996
faddr = find_field_attribute(baddr);
2997
fa = ea_buf[faddr].fa;
2998
if (faddr == baddr || FA_IS_PROTECTED(fa))
3004
c = ea_buf[baddr].cc;
3005
if (ea_buf[baddr].fa)
3007
if (c != EBC_null && c != EBC_space)
3008
last_nonblank = baddr;
3011
if (last_nonblank == -1) {
3015
baddr = last_nonblank;
3017
if (ea_buf[baddr].fa)
3018
baddr = last_nonblank;
3024
* MoveCursor action. Depending on arguments, this is either a move to the
3025
* mouse cursor position, or to an absolute location.
3028
MoveCursor_action(Widget w, XEvent *event, String *params, Cardinal *num_params)
3033
action_debug(MoveCursor_action, event, params, num_params);
3037
if (*num_params == 2)
3038
enq_ta(MoveCursor_action, params[0], params[1]);
3042
switch (*num_params) {
3043
#if defined(X3270_DISPLAY) /*[*/
3044
case 0: /* mouse click, presumably */
3047
cursor_move(mouse_baddr(w, event));
3050
case 2: /* probably a macro call */
3051
row = atoi(params[0]);
3052
col = atoi(params[1]);
3061
baddr = ((row * COLS) + col) % (ROWS * COLS);
3064
default: /* couln't say */
3065
popup_an_error("%s requires 0 or 2 arguments",
3066
action_name(MoveCursor_action));
3067
cancel_if_idle_command();
3073
#if defined(X3270_DBCS) && defined(X3270_DISPLAY) /*[*/
3075
* Run a KeyPress through XIM.
3076
* Returns True if there is further processing to do, False otherwise.
3079
xim_lookup(XKeyEvent *event)
3081
static char *buf = NULL;
3082
static int buf_len = 0, rlen;
3088
#define BASE_BUFSIZE 50
3094
buf_len = BASE_BUFSIZE;
3095
buf = Malloc(buf_len);
3099
memset(buf, '\0', buf_len);
3100
rlen = XmbLookupString(ic, event, buf, buf_len - 1, &k,
3102
if (status != XBufferOverflow)
3104
buf_len += BASE_BUFSIZE;
3105
buf = Realloc(buf, buf_len);
3116
trace_event("%d XIM char%s:", rlen, (rlen != 1)? "s": "");
3117
for (i = 0; i < rlen; i++) {
3118
trace_event(" %02x", buf[i] & 0xff);
3122
key_ACharacter(buf, KT_STD, ia_cause, NULL);
3138
Key_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
3142
enum keytype keytype;
3145
action_debug(Key_action, event, params, num_params);
3148
for (i = 0; i < *num_params; i++) {
3149
char *s = params[i];
3151
k = MyStringToKeysym(s, &keytype, &ucs4);
3152
if (k == NoSymbol && !ucs4) {
3153
popup_an_error("%s: Nonexistent or invalid KeySym: %s",
3154
action_name(Key_action), s);
3155
cancel_if_idle_command();
3160
* Can't pass symbolic KeySyms that aren't in the
3163
popup_an_error("%s: Invalid KeySym: %s",
3164
action_name(Key_action), s);
3165
cancel_if_idle_command();
3169
key_UCharacter(k, keytype, IA_KEY, NULL);
3171
key_UCharacter(ucs4, keytype, IA_KEY, NULL);
3179
String_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
3185
action_debug(String_action, event, params, num_params);
3188
/* Determine the total length of the strings. */
3189
for (i = 0; i < *num_params; i++)
3190
len += strlen(params[i]);
3194
/* Allocate a block of memory and copy them in. */
3195
s = Malloc(len + 1);
3197
for (i = 0; i < *num_params; i++) {
3198
strcat(s, params[i]);
3201
/* Set a pending string. */
3210
HexString_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
3217
action_debug(HexString_action, event, params, num_params);
3220
/* Determine the total length of the strings. */
3221
for (i = 0; i < *num_params; i++) {
3223
if (!strncmp(t, "0x", 2) || !strncmp(t, "0X", 2))
3230
/* Allocate a block of memory and copy them in. */
3231
s = Malloc(len + 1);
3233
for (i = 0; i < *num_params; i++) {
3235
if (!strncmp(t, "0x", 2) || !strncmp(t, "0X", 2))
3237
(void) strcat(s, t);
3240
/* Set a pending string. */
3245
* Dual-mode action for the "asciicircum" ("^") key:
3246
* If in ANSI mode, pass through untranslated.
3247
* If in 3270 mode, translate to "notsign".
3248
* This action is obsoleted by the use of 3270-mode and NVT-mode keymaps, but
3249
* is still defined here for backwards compatibility with old keymaps.
3252
CircumNot_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
3254
action_debug(CircumNot_action, event, params, num_params);
3255
if (check_usage(CircumNot_action, *num_params, 0, 0) < 0)
3259
if (IN_3270 && composing == NONE)
3260
key_UCharacter(0xac, KT_STD, IA_KEY, NULL);
3262
key_UCharacter('^', KT_STD, IA_KEY, NULL);
3265
/* PA key action for String actions */
3269
if (n < 1 || n > PA_SZ) {
3270
popup_an_error("Unknown PA key %d", n);
3271
cancel_if_idle_command();
3277
(void) sprintf(nn, "%d", n);
3278
enq_ta(PA_action, nn, CN);
3281
key_AID(pa_xlate[n-1]);
3284
/* PF key action for String actions */
3288
if (n < 1 || n > PF_SZ) {
3289
popup_an_error("Unknown PF key %d", n);
3290
cancel_if_idle_command();
3296
(void) sprintf(nn, "%d", n);
3297
enq_ta(PF_action, nn, CN);
3300
key_AID(pf_xlate[n-1]);
3304
* Set or clear the keyboard scroll lock.
3307
kybd_scroll_lock(Boolean lock)
3312
kybdlock_set(KL_SCROLLED, "kybd_scroll_lock");
3314
kybdlock_clr(KL_SCROLLED, "kybd_scroll_lock");
3318
* Move the cursor back within the legal paste area.
3319
* Returns a Boolean indicating success.
3322
remargin(int lmargin)
3324
Boolean ever = False;
3329
baddr = cursor_addr;
3330
while (BA_TO_COL(baddr) < lmargin) {
3331
baddr = ROWCOL_TO_BA(BA_TO_ROW(baddr), lmargin);
3336
faddr = find_field_attribute(baddr);
3337
fa = ea_buf[faddr].fa;
3338
if (faddr == baddr || FA_IS_PROTECTED(fa)) {
3339
baddr = next_unprotected(baddr);
3350
* Pretend that a sequence of keys was entered at the keyboard.
3352
* "Pasting" means that the sequence came from the X clipboard. Returns are
3353
* ignored; newlines mean "move to beginning of next line"; tabs and formfeeds
3354
* become spaces. Backslashes are not special, but ASCII ESC characters are
3355
* used to signify 3270 Graphic Escapes.
3357
* "Not pasting" means that the sequence is a login string specified in the
3358
* hosts file, or a parameter to the String action. Returns are "move to
3359
* beginning of next line"; newlines mean "Enter AID" and the termination of
3360
* processing the string. Backslashes are processed as in C.
3362
* Returns the number of unprocessed characters.
3365
emulate_uinput(ucs4_t *ws, int xlen, Boolean pasting)
3368
BASE, BACKSLASH, BACKX, BACKE, BACKP, BACKPA, BACKPF, OCTAL,
3373
enum iaction ia = pasting ? IA_PASTE : IA_STRING;
3374
int orig_addr = cursor_addr;
3375
int orig_col = BA_TO_COL(cursor_addr);
3376
Boolean skipped = False;
3380
* In the switch statements below, "break" generally means "consume
3381
* this character," while "continue" means "rescan this character."
3386
* It isn't possible to unlock the keyboard from a string,
3387
* so if the keyboard is locked, it's fatal
3390
trace_event(" keyboard locked, string dropped\n");
3394
if (pasting && IN_3270) {
3396
/* Check for cursor wrap to top of screen. */
3397
if (cursor_addr < orig_addr)
3398
return xlen-1; /* wrapped */
3400
/* Jump cursor over left margin. */
3401
if (toggled(MARGINED_PASTE) &&
3402
BA_TO_COL(cursor_addr) < orig_col) {
3403
if (!remargin(orig_col))
3415
action_internal(Left_action, ia, CN, CN);
3420
key_UCharacter(' ', KT_STD, ia,
3423
action_internal(Clear_action, ia, CN,
3433
action_internal(Newline_action,
3437
action_internal(Enter_action, ia, CN,
3446
action_internal(Newline_action, ia, CN,
3452
action_internal(Tab_action, ia, CN, CN);
3455
case '\\': /* backslashes are NOT special when
3460
key_UCharacter((unsigned char)c,
3461
KT_STD, ia, &skipped);
3463
case '\033': /* ESC is special only when pasting */
3467
case '[': /* APL left bracket */
3468
if (pasting && appres.apl_mode)
3469
key_UCharacter(XK_Yacute, KT_GE, ia,
3472
key_UCharacter((unsigned char)c,
3473
KT_STD, ia, &skipped);
3475
case ']': /* APL right bracket */
3476
if (pasting && appres.apl_mode)
3477
key_UCharacter(XK_diaeresis, KT_GE, ia,
3480
key_UCharacter((unsigned char)c,
3484
case UPRIV_fm: /* private-use FM */
3486
key_Character(EBC_fm, False, True,
3489
case UPRIV_dup: /* private-use DUP */
3491
key_Character(EBC_dup, False, True,
3494
case UPRIV_eo: /* private-use EO */
3496
key_Character(EBC_eo, False, True,
3499
case UPRIV_sub: /* private-use SUB */
3501
key_Character(EBC_sub, False, True,
3506
(c >= UPRIV_GE_00 &&
3508
key_Character(c - UPRIV_GE_00, KT_GE,
3511
key_UCharacter(c, KT_STD, ia,
3516
case BACKSLASH: /* last character was a backslash */
3519
popup_an_error("%s: Bell not supported",
3520
action_name(String_action));
3521
cancel_if_idle_command();
3525
action_internal(Left_action, ia, CN, CN);
3530
action_internal(Clear_action, ia, CN, CN);
3538
action_internal(Enter_action, ia, CN, CN);
3549
action_internal(Newline_action, ia, CN, CN);
3554
action_internal(Tab_action, ia, CN, CN);
3559
action_internal(BackTab_action, ia, CN, CN);
3564
popup_an_error("%s: Vertical tab not supported",
3565
action_name(String_action));
3566
cancel_if_idle_command();
3577
key_UCharacter((unsigned char) c, KT_STD, ia,
3598
case BACKP: /* last two characters were "\p" */
3611
popup_an_error("%s: Unknown character "
3613
action_name(String_action));
3614
cancel_if_idle_command();
3619
case BACKPF: /* last three characters were "\pf" */
3620
if (nc < 2 && isdigit(c)) {
3621
literal = (literal * 10) + (c - '0');
3624
popup_an_error("%s: Unknown character "
3626
action_name(String_action));
3627
cancel_if_idle_command();
3639
case BACKPA: /* last three characters were "\pa" */
3640
if (nc < 1 && isdigit(c)) {
3641
literal = (literal * 10) + (c - '0');
3644
popup_an_error("%s: Unknown character "
3646
action_name(String_action));
3647
cancel_if_idle_command();
3658
case BACKX: /* last two characters were "\x" or "\u" */
3665
popup_an_error("%s: Missing hex digits after \\x",
3666
action_name(String_action));
3667
cancel_if_idle_command();
3671
case BACKE: /* last two characters were "\e" */
3678
popup_an_error("%s: Missing hex digits after \\e",
3679
action_name(String_action));
3680
cancel_if_idle_command();
3684
case OCTAL: /* have seen \ and one or more octal digits */
3685
if (nc < 3 && isdigit(c) && c < '8') {
3686
literal = (literal * 8) + FROM_HEX(c);
3690
key_UCharacter((unsigned char) literal, KT_STD,
3695
case HEX: /* have seen \x and one or more hex digits */
3696
if (nc < 4 && isxdigit(c)) {
3697
literal = (literal * 16) + FROM_HEX(c);
3701
key_UCharacter((unsigned char) literal, KT_STD,
3706
case EBC: /* have seen \e and one or more hex digits */
3707
if (nc < 4 && isxdigit(c)) {
3708
literal = (literal * 16) + FROM_HEX(c);
3712
trace_event(" %s -> Key(X'%02X')\n",
3713
ia_name[(int) ia], literal);
3714
if (!(literal & ~0xff))
3715
key_Character((unsigned char) literal,
3716
False, True, &skipped);
3718
#if defined(X3270_DBCS) /*[*/
3719
unsigned char code[2];
3721
code[0] = (literal >> 8) & 0xff;
3722
code[1] = literal & 0xff;
3723
key_WCharacter(code, &skipped);
3725
popup_an_error("%s: EBCDIC code > 255",
3726
action_name(String_action));
3727
cancel_if_idle_command();
3733
case XGE: /* have seen ESC */
3736
key_Character(EBC_fm, False, True, &skipped);
3739
key_Character(EBC_dup, False, True, &skipped);
3742
key_UCharacter((unsigned char) c, KT_GE, ia,
3755
if (toggled(MARGINED_PASTE) &&
3756
BA_TO_COL(cursor_addr) < orig_col) {
3757
(void) remargin(orig_col);
3762
key_UCharacter((unsigned char) literal, KT_STD, ia, &skipped);
3764
if (toggled(MARGINED_PASTE) &&
3765
BA_TO_COL(cursor_addr) < orig_col) {
3766
(void) remargin(orig_col);
3770
/* XXX: line below added after 3.3.7p7 */
3771
trace_event(" %s -> Key(X'%02X')\n", ia_name[(int) ia],
3773
key_Character((unsigned char) literal, False, True, &skipped);
3775
if (toggled(MARGINED_PASTE) &&
3776
BA_TO_COL(cursor_addr) < orig_col) {
3777
(void) remargin(orig_col);
3793
popup_an_error("%s: Missing data after \\",
3794
action_name(String_action));
3795
cancel_if_idle_command();
3802
/* Multibyte version of emulate_uinput. */
3804
emulate_input(char *s, int len, Boolean pasting)
3806
static ucs4_t *w_ibuf = NULL;
3807
static size_t w_ibuf_len = 0;
3810
/* Convert from a multi-byte string to a Unicode string. */
3811
if ((size_t)(len + 1) > w_ibuf_len) {
3812
w_ibuf_len = len + 1;
3813
w_ibuf = (ucs4_t *)Realloc(w_ibuf, w_ibuf_len * sizeof(ucs4_t));
3815
xlen = multibyte_to_unicode_string(s, len, w_ibuf, w_ibuf_len);
3817
return 0; /* failed */
3820
/* Process it as Unicode. */
3821
return emulate_uinput(w_ibuf, xlen, pasting);
3825
* Pretend that a sequence of hexadecimal characters was entered at the
3826
* keyboard. The input is a sequence of hexadecimal bytes, 2 characters
3827
* per byte. If connected in ANSI mode, these are treated as ASCII
3828
* characters; if in 3270 mode, they are considered EBCDIC.
3830
* Graphic Escapes are handled as \E.
3837
#if defined(X3270_ANSI) /*[*/
3838
unsigned char *xbuf = (unsigned char *)NULL;
3839
unsigned char *tbuf = (unsigned char *)NULL;
3843
/* Validate the string. */
3844
if (strlen(s) % 2) {
3845
popup_an_error("%s: Odd number of characters in specification",
3846
action_name(HexString_action));
3847
cancel_if_idle_command();
3853
if (isxdigit(*t) && isxdigit(*(t + 1))) {
3855
#if defined(X3270_ANSI) /*[*/
3858
} else if (!strncmp(t, "\\E", 2) || !strncmp(t, "\\e", 2)) {
3860
popup_an_error("%s: Double \\E",
3861
action_name(HexString_action));
3862
cancel_if_idle_command();
3866
popup_an_error("%s: \\E in ANSI mode",
3867
action_name(HexString_action));
3868
cancel_if_idle_command();
3873
popup_an_error("%s: Illegal character in specification",
3874
action_name(HexString_action));
3875
cancel_if_idle_command();
3881
popup_an_error("%s: Nothing follows \\E",
3882
action_name(HexString_action));
3883
cancel_if_idle_command();
3887
#if defined(X3270_ANSI) /*[*/
3888
/* Allocate a temporary buffer. */
3889
if (!IN_3270 && nbytes)
3890
tbuf = xbuf = (unsigned char *)Malloc(nbytes);
3897
if (isxdigit(*t) && isxdigit(*(t + 1))) {
3900
c = (FROM_HEX(*t) * 16) + FROM_HEX(*(t + 1));
3902
key_Character(c, escaped, True, NULL);
3903
#if defined(X3270_ANSI) /*[*/
3905
*tbuf++ = (unsigned char)c;
3908
} else if (!strncmp(t, "\\E", 2) || !strncmp(t, "\\e", 2)) {
3913
#if defined(X3270_ANSI) /*[*/
3914
if (!IN_3270 && nbytes) {
3915
net_hexansi_out(xbuf, nbytes);
3922
ignore_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
3924
action_debug(ignore_action, event, params, num_params);
3928
#if defined(X3270_FT) /*[*/
3930
* Set up the cursor and input field for command input.
3931
* Returns the length of the input field, or 0 if there is no field
3938
register unsigned char fa;
3942
* No point in trying if the screen isn't formatted, the keyboard
3943
* is locked, or we aren't in 3270 mode.
3945
if (!formatted || kybdlock || !IN_3270)
3948
fa = get_field_attribute(cursor_addr);
3949
if (ea_buf[cursor_addr].fa || FA_IS_PROTECTED(fa)) {
3951
* The cursor is not in an unprotected field. Find the
3954
baddr = next_unprotected(cursor_addr);
3956
/* If there isn't any, give up. */
3960
/* Move the cursor there. */
3962
/* Already in an unprotected field. Find its start. */
3963
baddr = cursor_addr;
3964
while (!ea_buf[baddr].fa) {
3970
/* Move the cursor to the beginning of the field. */
3974
while (!ea_buf[baddr].fa) {
3975
ctlr_add(baddr, 0, 0);
3980
/* Return the field length. */
3986
* Translate a keysym name to a keysym, including APL and extended
3990
MyStringToKeysym(char *s, enum keytype *keytypep, ucs4_t *ucs4)
3999
#if defined(X3270_APL) /*[*/
4000
/* Look for my contrived APL symbols. */
4001
if (!strncmp(s, "apl_", 4)) {
4004
k = APLStringToKeysym(s, &is_ge);
4013
/* Look for a standard X11 keysym. */
4014
k = StringToKeysym(s);
4020
/* Look for "euro". */
4021
if (!strcasecmp(s, "euro")) {
4026
/* Look for U+nnnn of 0xXXXX. */
4027
if (!strncasecmp(s, "U+", 2) || !strncasecmp(s, "0x", 2)) {
4028
*ucs4 = strtoul(s + 2, NULL, 16);
4032
/* Look for a valid local multibyte character. */
4033
*ucs4 = multibyte_to_unicode(s, strlen(s), &consumed, &error);
4034
if ((size_t)consumed != strlen(s))
4039
#if defined(X3270_DISPLAY) /*[*/
4041
* X-dependent code starts here.
4045
* Translate a keymap (from an XQueryKeymap or a KeymapNotify event) into
4046
* a bitmap of Shift, Meta or Alt keys pressed.
4048
#define key_is_down(kc, bitmap) (kc && ((bitmap)[(kc)/8] & (1<<((kc)%8))))
4050
state_from_keymap(char keymap[32])
4052
static Boolean initted = False;
4053
static KeyCode kc_Shift_L, kc_Shift_R;
4054
static KeyCode kc_Meta_L, kc_Meta_R;
4055
static KeyCode kc_Alt_L, kc_Alt_R;
4056
int pseudo_state = 0;
4059
kc_Shift_L = XKeysymToKeycode(display, XK_Shift_L);
4060
kc_Shift_R = XKeysymToKeycode(display, XK_Shift_R);
4061
kc_Meta_L = XKeysymToKeycode(display, XK_Meta_L);
4062
kc_Meta_R = XKeysymToKeycode(display, XK_Meta_R);
4063
kc_Alt_L = XKeysymToKeycode(display, XK_Alt_L);
4064
kc_Alt_R = XKeysymToKeycode(display, XK_Alt_R);
4067
if (key_is_down(kc_Shift_L, keymap) ||
4068
key_is_down(kc_Shift_R, keymap))
4069
pseudo_state |= ShiftKeyDown;
4070
if (key_is_down(kc_Meta_L, keymap) ||
4071
key_is_down(kc_Meta_R, keymap))
4072
pseudo_state |= MetaKeyDown;
4073
if (key_is_down(kc_Alt_L, keymap) ||
4074
key_is_down(kc_Alt_R, keymap))
4075
pseudo_state |= AltKeyDown;
4076
return pseudo_state;
4081
* Process shift keyboard events. The code has to look for the raw Shift keys,
4082
* rather than using the handy "state" field in the event structure. This is
4083
* because the event state is the state _before_ the key was pressed or
4084
* released. This isn't enough information to distinguish between "left
4085
* shift released" and "left shift released, right shift still held down"
4086
* events, for example.
4088
* This function is also called as part of Focus event processing.
4091
PA_Shift_action(Widget w _is_unused, XEvent *event _is_unused, String *params _is_unused,
4092
Cardinal *num_params _is_unused)
4096
#if defined(INTERNAL_ACTION_DEBUG) /*[*/
4097
action_debug(PA_Shift_action, event, params, num_params);
4099
XQueryKeymap(display, keys);
4100
shift_event(state_from_keymap(keys));
4104
#if defined(X3270_DISPLAY) || defined(C3270) /*[*/
4106
build_composites(void)
4115
struct composite *cp;
4117
if (appres.compose_map == CN) {
4118
popup_an_error("%s: No %s defined", action_name(Compose_action),
4122
c0 = get_fresource("%s.%s", ResComposeMap, appres.compose_map);
4124
popup_an_error("%s: Cannot find %s \"%s\"",
4125
action_name(Compose_action), ResComposeMap,
4126
appres.compose_map);
4129
c1 = c = NewString(c0); /* will be modified by strtok */
4130
while ((ln = strtok(c, "\n"))) {
4131
Boolean okay = True;
4134
if (sscanf(ln, " %63[^+ \t] + %63[^= \t] =%63s%1s",
4135
ksname[0], ksname[1], ksname[2], junk) != 3) {
4136
popup_an_error("%s: Invalid syntax: %s",
4137
action_name(Compose_action), ln);
4140
for (i = 0; i < 3; i++) {
4143
k[i] = MyStringToKeysym(ksname[i], &a[i], &ucs4);
4144
if (k[i] == NoSymbol) {
4145
/* For now, ignore UCS4. XXX: Fix this. */
4146
popup_an_error("%s: Invalid KeySym: \"%s\"",
4147
action_name(Compose_action), ksname[i]);
4154
composites = (struct composite *) Realloc((char *)composites,
4155
(n_composites + 1) * sizeof(struct composite));
4156
cp = composites + n_composites;
4157
cp->k1.keysym = k[0];
4158
cp->k1.keytype = a[0];
4159
cp->k2.keysym = k[1];
4160
cp->k2.keytype = a[1];
4161
cp->translation.keysym = k[2];
4162
cp->translation.keytype = a[2];
4170
* Called by the toolkit when the "Compose" key is pressed. "Compose" is
4171
* implemented by pressing and releasing three keys: "Compose" and two
4172
* data keys. For example, "Compose" "s" "s" gives the German "ssharp"
4173
* character, and "Compose" "C", "," gives a capital "C" with a cedilla
4174
* (symbol Ccedilla).
4176
* The mechanism breaks down a little when the user presses "Compose" and
4177
* then a non-data key. Oh well.
4180
Compose_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
4182
action_debug(Compose_action, event, params, num_params);
4183
if (check_usage(Compose_action, *num_params, 0, 0) < 0)
4187
if (!composites && !build_composites())
4190
if (composing == NONE) {
4191
composing = COMPOSE;
4192
status_compose(True, 0, KT_STD);
4197
#if defined(X3270_DISPLAY) /*[*/
4200
* Called by the toolkit for any key without special actions.
4203
Default_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
4205
XKeyEvent *kevent = (XKeyEvent *)event;
4210
action_debug(Default_action, event, params, num_params);
4211
if (check_usage(Default_action, *num_params, 0, 0) < 0)
4213
switch (event->type) {
4215
#if defined(X3270_DBCS) /*[*/
4216
if (!xim_lookup((XKeyEvent *)event))
4219
ll = XLookupString(kevent, buf, 32, &ks, (XComposeStatus *) 0);
4222
key_ACharacter(buf, KT_STD, IA_DEFAULT, NULL);
4226
/* Remap certain control characters. */
4227
if (!IN_ANSI) switch (buf[0]) {
4229
action_internal(Tab_action, IA_DEFAULT, CN, CN);
4232
action_internal(Delete_action, IA_DEFAULT, CN,
4236
action_internal(Erase_action, IA_DEFAULT,
4240
action_internal(Enter_action, IA_DEFAULT, CN,
4244
action_internal(Newline_action, IA_DEFAULT, CN,
4248
key_ACharacter(buf, KT_STD, IA_DEFAULT, NULL);
4251
key_ACharacter(buf, KT_STD, IA_DEFAULT, NULL);
4256
/* Pick some other reasonable defaults. */
4259
action_internal(Up_action, IA_DEFAULT, CN, CN);
4262
action_internal(Down_action, IA_DEFAULT, CN, CN);
4265
action_internal(Left_action, IA_DEFAULT, CN, CN);
4268
action_internal(Right_action, IA_DEFAULT, CN, CN);
4271
#if defined(XK_KP_Insert) /*[*/
4274
action_internal(Insert_action, IA_DEFAULT, CN, CN);
4277
action_internal(Delete_action, IA_DEFAULT, CN, CN);
4280
action_internal(Home_action, IA_DEFAULT, CN, CN);
4283
action_internal(Tab_action, IA_DEFAULT, CN, CN);
4285
#if defined(XK_ISO_Left_Tab) /*[*/
4286
case XK_ISO_Left_Tab:
4287
action_internal(BackTab_action, IA_DEFAULT, CN, CN);
4291
action_internal(Clear_action, IA_DEFAULT, CN, CN);
4294
action_internal(SysReq_action, IA_DEFAULT, CN, CN);
4296
#if defined(XK_EuroSign) /*[*/
4298
action_internal(Key_action, IA_DEFAULT, "currency",
4303
#if defined(XK_3270_Duplicate) /*[*/
4304
/* Funky 3270 keysyms. */
4305
case XK_3270_Duplicate:
4306
action_internal(Dup_action, IA_DEFAULT, CN, CN);
4308
case XK_3270_FieldMark:
4309
action_internal(FieldMark_action, IA_DEFAULT, CN, CN);
4311
case XK_3270_Right2:
4312
action_internal(Right2_action, IA_DEFAULT, CN, CN);
4315
action_internal(Left2_action, IA_DEFAULT, CN, CN);
4317
case XK_3270_BackTab:
4318
action_internal(BackTab_action, IA_DEFAULT, CN, CN);
4320
case XK_3270_EraseEOF:
4321
action_internal(EraseEOF_action, IA_DEFAULT, CN, CN);
4323
case XK_3270_EraseInput:
4324
action_internal(EraseInput_action, IA_DEFAULT, CN, CN);
4327
action_internal(Reset_action, IA_DEFAULT, CN, CN);
4330
action_internal(PA_action, IA_DEFAULT, "1", CN);
4333
action_internal(PA_action, IA_DEFAULT, "2", CN);
4336
action_internal(PA_action, IA_DEFAULT, "3", CN);
4339
action_internal(Attn_action, IA_DEFAULT, CN, CN);
4341
case XK_3270_AltCursor:
4342
action_internal(AltCursor_action, IA_DEFAULT, CN, CN);
4344
case XK_3270_CursorSelect:
4345
action_internal(CursorSelect_action, IA_DEFAULT, CN,
4349
action_internal(Enter_action, IA_DEFAULT, CN, CN);
4353
#if defined(X3270_APL) /*[*/
4354
/* Funky APL keysyms. */
4356
action_internal(Key_action, IA_DEFAULT, "apl_downcaret",
4360
action_internal(Key_action, IA_DEFAULT, "apl_upcaret",
4364
action_internal(Key_action, IA_DEFAULT, "apl_overbar",
4368
action_internal(Key_action, IA_DEFAULT, "apl_downtack",
4372
action_internal(Key_action, IA_DEFAULT, "apl_upshoe",
4376
action_internal(Key_action, IA_DEFAULT, "apl_downstile",
4380
action_internal(Key_action, IA_DEFAULT, "apl_underbar",
4384
action_internal(Key_action, IA_DEFAULT, "apl_jot", CN);
4387
action_internal(Key_action, IA_DEFAULT, "apl_quad", CN);
4390
action_internal(Key_action, IA_DEFAULT, "apl_uptack",
4394
action_internal(Key_action, IA_DEFAULT, "apl_circle",
4398
action_internal(Key_action, IA_DEFAULT, "apl_upstile",
4402
action_internal(Key_action, IA_DEFAULT, "apl_downshoe",
4406
action_internal(Key_action, IA_DEFAULT, "apl_rightshoe",
4410
action_internal(Key_action, IA_DEFAULT, "apl_leftshoe",
4414
action_internal(Key_action, IA_DEFAULT, "apl_lefttack",
4418
action_internal(Key_action, IA_DEFAULT, "apl_righttack",
4424
if (ks >= XK_F1 && ks <= XK_F24) {
4425
(void) sprintf(buf, "%ld", ks - XK_F1 + 1);
4426
action_internal(PF_action, IA_DEFAULT, buf, CN);
4430
ucs4 = keysym2ucs(ks);
4431
if (ucs4 != (ucs4_t)-1) {
4432
key_UCharacter(ucs4, KT_STD, IA_KEY,
4436
" %s: dropped (unknown keysym)\n",
4437
action_name(Default_action));
4446
trace_event(" %s: dropped (no action configured)\n",
4447
action_name(Default_action));
4450
trace_event(" %s: dropped (unknown event type)\n",
4451
action_name(Default_action));
4457
* Set or clear a temporary keymap.
4459
* TemporaryKeymap(x) toggle keymap "x" (add "x" to the keymap, or if
4460
* "x" was already added, remove it)
4461
* TemporaryKeymap() removes the previous keymap, if any
4462
* TemporaryKeymap(None) removes the previous keymap, if any
4465
TemporaryKeymap_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
4467
action_debug(TemporaryKeymap_action, event, params, num_params);
4470
if (check_usage(TemporaryKeymap_action, *num_params, 0, 1) < 0)
4473
if (*num_params == 0 || !strcmp(params[0], "None")) {
4474
(void) temporary_keymap(CN);
4478
if (temporary_keymap(params[0]) < 0) {
4479
popup_an_error("%s: Can't find %s %s",
4480
action_name(TemporaryKeymap_action), ResKeymap, params[0]);
4481
cancel_if_idle_command();