~ubuntu-branches/ubuntu/natty/ibm-3270/natty

« back to all changes in this revision

Viewing changes to ws3270/kybd.c

  • Committer: Bazaar Package Importer
  • Author(s): Bastian Blank
  • Date: 2009-12-14 11:48:53 UTC
  • mfrom: (1.1.4 upstream) (2.1.2 sid)
  • Revision ID: james.westby@ubuntu.com-20091214114853-mywixml32hct9jr1
Tags: 3.3.10ga4-2
* Fix section to match override.
* Use debhelper compat level 7.
* Use 3.0 (quilt) source format.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 1993-2009, Paul Mattes.
 
3
 * Copyright (c) 1990, Jeff Sparkes.
 
4
 * Copyright (c) 1989, Georgia Tech Research Corporation (GTRC), Atlanta, GA
 
5
 *  30332.
 
6
 * All rights reserved.
 
7
 *
 
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.
 
18
 *
 
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.
 
30
 */
 
31
 
 
32
/*
 
33
 *      kybd.c
 
34
 *              This module handles the keyboard for the 3270 emulator.
 
35
 */
 
36
 
 
37
#include "globals.h"
 
38
 
 
39
#if defined(X3270_DISPLAY) /*[*/
 
40
#include <X11/Xatom.h>
 
41
#endif
 
42
#define XK_3270
 
43
#if defined(X3270_APL) /*[*/
 
44
#define XK_APL
 
45
#endif /*]*/
 
46
#include <X11/keysym.h>
 
47
 
 
48
#include <fcntl.h>
 
49
#include "3270ds.h"
 
50
#include "appres.h"
 
51
#include "ctlr.h"
 
52
#if defined(X3270_DISPLAY) /*[*/
 
53
#include "keysym2ucs.h"
 
54
#endif /*]*/
 
55
#include "resources.h"
 
56
 
 
57
#include "actionsc.h"
 
58
#include "ansic.h"
 
59
#include "aplc.h"
 
60
#include "charsetc.h"
 
61
#include "ctlrc.h"
 
62
#include "ftc.h"
 
63
#include "hostc.h"
 
64
#include "idlec.h"
 
65
#include "keymapc.h"
 
66
#include "keypadc.h"
 
67
#include "kybdc.h"
 
68
#include "macrosc.h"
 
69
#include "popupsc.h"
 
70
#include "printc.h"
 
71
#include "screenc.h"
 
72
#if defined(X3270_DISPLAY) /*[*/
 
73
#include "selectc.h"
 
74
#endif /*]*/
 
75
#include "statusc.h"
 
76
#include "tablesc.h"
 
77
#include "telnetc.h"
 
78
#include "togglesc.h"
 
79
#include "trace_dsc.h"
 
80
#include "unicodec.h"
 
81
#include "utf8c.h"
 
82
#include "utilc.h"
 
83
 
 
84
#if defined(_WIN32) /*[*/
 
85
#include <windows.h>
 
86
#endif /*]*/
 
87
 
 
88
/*#define KYBDLOCK_TRACE        1*/
 
89
 
 
90
/* Statics */
 
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
 
97
};
 
98
static unsigned char pa_xlate[] = { 
 
99
        AID_PA1, AID_PA2, AID_PA3
 
100
};
 
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,
 
106
                             Boolean *skipped);
 
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,
 
111
        ucs4_t *ucs4);
 
112
 
 
113
#if defined(X3270_DBCS) /*[*/
 
114
Boolean key_WCharacter(unsigned char code[], Boolean *skipped);
 
115
#endif /*]*/
 
116
 
 
117
static Boolean          insert = False;         /* insert mode */
 
118
static Boolean          reverse = False;        /* reverse-input mode */
 
119
 
 
120
/* Globals */
 
121
unsigned int    kybdlock = KL_NOT_CONNECTED;
 
122
unsigned char   aid = AID_NO;           /* current attention ID */
 
123
 
 
124
/* Composite key mappings. */
 
125
 
 
126
struct akeysym {
 
127
        KeySym keysym;
 
128
        enum keytype keytype;
 
129
};
 
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;
 
136
 
 
137
#define ak_eq(k1, k2)   (((k1).keysym  == (k2).keysym) && \
 
138
                         ((k1).keytype == (k2).keytype))
 
139
 
 
140
static struct ta {
 
141
        struct ta *next;
 
142
        XtActionProc fn;
 
143
        char *parm1;
 
144
        char *parm2;
 
145
} *ta_head = (struct ta *) NULL,
 
146
  *ta_tail = (struct ta *) NULL;
 
147
 
 
148
static char dxl[] = "0123456789abcdef";
 
149
#define FROM_HEX(c)     (strchr(dxl, tolower(c)) - dxl)
 
150
 
 
151
extern Widget *screen;
 
152
 
 
153
#define KYBDLOCK_IS_OERR        (kybdlock && !(kybdlock & ~KL_OERR_MASK))
 
154
 
 
155
 
 
156
/*
 
157
 * Put an action on the typeahead queue.
 
158
 */
 
159
static void
 
160
enq_ta(XtActionProc fn, char *parm1, char *parm2)
 
161
{
 
162
        struct ta *ta;
 
163
 
 
164
        /* If no connection, forget it. */
 
165
        if (!CONNECTED) {
 
166
                trace_event("  dropped (not connected)\n");
 
167
                return;
 
168
        }
 
169
 
 
170
        /* If operator error, complain and drop it. */
 
171
        if (kybdlock & KL_OERR_MASK) {
 
172
                ring_bell();
 
173
                trace_event("  dropped (operator error)\n");
 
174
                return;
 
175
        }
 
176
 
 
177
        /* If scroll lock, complain and drop it. */
 
178
        if (kybdlock & KL_SCROLLED) {
 
179
                ring_bell();
 
180
                trace_event("  dropped (scrolled)\n");
 
181
                return;
 
182
        }
 
183
 
 
184
        /* If typeahead disabled, complain and drop it. */
 
185
        if (!appres.typeahead) {
 
186
                trace_event("  dropped (no typeahead)\n");
 
187
                return;
 
188
        }
 
189
 
 
190
        ta = (struct ta *) Malloc(sizeof(*ta));
 
191
        ta->next = (struct ta *) NULL;
 
192
        ta->fn = fn;
 
193
        ta->parm1 = ta->parm2 = CN;
 
194
        if (parm1) {
 
195
                ta->parm1 = NewString(parm1);
 
196
                if (parm2)
 
197
                        ta->parm2 = NewString(parm2);
 
198
        }
 
199
        if (ta_head)
 
200
                ta_tail->next = ta;
 
201
        else {
 
202
                ta_head = ta;
 
203
                status_typeahead(True);
 
204
        }
 
205
        ta_tail = ta;
 
206
 
 
207
        trace_event("  action queued (kybdlock 0x%x)\n", kybdlock);
 
208
}
 
209
 
 
210
/*
 
211
 * Execute an action from the typeahead queue.
 
212
 */
 
213
Boolean
 
214
run_ta(void)
 
215
{
 
216
        struct ta *ta;
 
217
 
 
218
        if (kybdlock || (ta = ta_head) == (struct ta *)NULL)
 
219
                return False;
 
220
 
 
221
        if ((ta_head = ta->next) == (struct ta *)NULL) {
 
222
                ta_tail = (struct ta *)NULL;
 
223
                status_typeahead(False);
 
224
        }
 
225
 
 
226
        action_internal(ta->fn, IA_TYPEAHEAD, ta->parm1, ta->parm2);
 
227
        Free(ta->parm1);
 
228
        Free(ta->parm2);
 
229
        Free(ta);
 
230
 
 
231
        return True;
 
232
}
 
233
 
 
234
/*
 
235
 * Flush the typeahead queue.
 
236
 * Returns whether or not anything was flushed.
 
237
 */
 
238
static Boolean
 
239
flush_ta(void)
 
240
{
 
241
        struct ta *ta, *next;
 
242
        Boolean any = False;
 
243
 
 
244
        for (ta = ta_head; ta != (struct ta *) NULL; ta = next) {
 
245
                Free(ta->parm1);
 
246
                Free(ta->parm2);
 
247
                next = ta->next;
 
248
                Free(ta);
 
249
                any = True;
 
250
        }
 
251
        ta_head = ta_tail = (struct ta *) NULL;
 
252
        status_typeahead(False);
 
253
        return any;
 
254
}
 
255
 
 
256
/* Decode keyboard lock bits. */
 
257
static char *
 
258
kybdlock_decode(char *how, unsigned int bits)
 
259
{
 
260
        static char buf[1024];
 
261
        char *s = buf;
 
262
        char *space = "";
 
263
 
 
264
        if (bits == (unsigned int)-1)
 
265
                return "all";
 
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");
 
271
                        break;
 
272
                    case KL_OERR_NUMERIC:
 
273
                        s += sprintf(s, "NUMERIC");
 
274
                        break;
 
275
                    case KL_OERR_OVERFLOW:
 
276
                        s += sprintf(s, "OVERFLOW");
 
277
                        break;
 
278
                    case KL_OERR_DBCS:
 
279
                        s += sprintf(s, "DBCS");
 
280
                        break;
 
281
                    default:
 
282
                        s += sprintf(s, "?%d", bits & KL_OERR_MASK);
 
283
                        break;
 
284
                }
 
285
                s += sprintf(s, ")");
 
286
                space = " ";
 
287
        }
 
288
        if (bits & KL_NOT_CONNECTED) {
 
289
            s += sprintf(s, "%s%sNOT_CONNECTED", space, how);
 
290
            space = " ";
 
291
        }
 
292
        if (bits & KL_AWAITING_FIRST) {
 
293
            s += sprintf(s, "%s%sAWAITING_FIRST", space, how);
 
294
            space = " ";
 
295
        }
 
296
        if (bits & KL_OIA_TWAIT) {
 
297
            s += sprintf(s, "%s%sOIA_TWAIT", space, how);
 
298
            space = " ";
 
299
        }
 
300
        if (bits & KL_OIA_LOCKED) {
 
301
            s += sprintf(s, "%s%sOIA_LOCKED", space, how);
 
302
            space = " ";
 
303
        }
 
304
        if (bits & KL_DEFERRED_UNLOCK) {
 
305
            s += sprintf(s, "%s%sDEFERRED_UNLOCK", space, how);
 
306
            space = " ";
 
307
        }
 
308
        if (bits & KL_ENTER_INHIBIT) {
 
309
            s += sprintf(s, "%s%sENTER_INHIBIT", space, how);
 
310
            space = " ";
 
311
        }
 
312
        if (bits & KL_SCROLLED) {
 
313
            s += sprintf(s, "%s%sSCROLLED", space, how);
 
314
            space = " ";
 
315
        }
 
316
        if (bits & KL_OIA_MINUS) {
 
317
            s += sprintf(s, "%s%sOIA_MINUS", space, how);
 
318
            space = " ";
 
319
        }
 
320
 
 
321
        return buf;
 
322
}
 
323
 
 
324
/* Set bits in the keyboard lock. */
 
325
static void
 
326
kybdlock_set(unsigned int bits, const char *cause _is_unused)
 
327
{
 
328
        unsigned int n;
 
329
 
 
330
        trace_event("Keyboard lock(%s) %s\n", cause,
 
331
                kybdlock_decode("+", bits));
 
332
        n = kybdlock | bits;
 
333
        if (n != kybdlock) {
 
334
#if defined(KYBDLOCK_TRACE) /*[*/
 
335
               trace_event("  %s: kybdlock |= 0x%04x, 0x%04x -> 0x%04x\n",
 
336
                    cause, bits, kybdlock, n);
 
337
#endif /*]*/
 
338
                if ((kybdlock ^ bits) & KL_DEFERRED_UNLOCK) {
 
339
                        /* Turned on deferred unlock. */
 
340
                        unlock_delay_time = time(NULL);
 
341
                }
 
342
                kybdlock = n;
 
343
                status_kybdlock();
 
344
        }
 
345
}
 
346
 
 
347
/* Clear bits in the keyboard lock. */
 
348
void
 
349
kybdlock_clr(unsigned int bits, const char *cause _is_unused)
 
350
{
 
351
        unsigned int n;
 
352
 
 
353
        if (kybdlock & bits)
 
354
                trace_event("Keyboard unlock(%s) %s\n", cause,
 
355
                        kybdlock_decode("-", kybdlock & bits));
 
356
        n = kybdlock & ~bits;
 
357
        if (n != kybdlock) {
 
358
#if defined(KYBDLOCK_TRACE) /*[*/
 
359
                trace_event("  %s: kybdlock &= ~0x%04x, 0x%04x -> 0x%04x\n",
 
360
                    cause, bits, kybdlock, n);
 
361
#endif /*]*/
 
362
                if ((kybdlock ^ n) & KL_DEFERRED_UNLOCK) {
 
363
                        /* Turned off deferred unlock. */
 
364
                        unlock_delay_time = 0;
 
365
                }
 
366
                kybdlock = n;
 
367
                status_kybdlock();
 
368
        }
 
369
}
 
370
 
 
371
/*
 
372
 * Set or clear enter-inhibit mode.
 
373
 */
 
374
void
 
375
kybd_inhibit(Boolean inhibit)
 
376
{
 
377
        if (inhibit) {
 
378
                kybdlock_set(KL_ENTER_INHIBIT, "kybd_inhibit");
 
379
                if (kybdlock == KL_ENTER_INHIBIT)
 
380
                        status_reset();
 
381
        } else {
 
382
                kybdlock_clr(KL_ENTER_INHIBIT, "kybd_inhibit");
 
383
                if (!kybdlock)
 
384
                        status_reset();
 
385
        }
 
386
}
 
387
 
 
388
/*
 
389
 * Called when a host connects or disconnects.
 
390
 */
 
391
static void
 
392
kybd_connect(Boolean connected)
 
393
{
 
394
        if ((kybdlock & KL_DEFERRED_UNLOCK) && unlock_id) {
 
395
                RemoveTimeOut(unlock_id);
 
396
                unlock_id = 0;
 
397
        }
 
398
        kybdlock_clr(-1, "kybd_connect");
 
399
 
 
400
        if (connected) {
 
401
                /* Wait for any output or a WCC(restore) from the host */
 
402
                kybdlock_set(KL_AWAITING_FIRST, "kybd_connect");
 
403
        } else {
 
404
                kybdlock_set(KL_NOT_CONNECTED, "kybd_connect");
 
405
                (void) flush_ta();
 
406
        }
 
407
}
 
408
 
 
409
/*
 
410
 * Called when we switch between 3270 and ANSI modes.
 
411
 */
 
412
static void
 
413
kybd_in3270(Boolean in3270 _is_unused)
 
414
{
 
415
        if ((kybdlock & KL_DEFERRED_UNLOCK) && unlock_id) {
 
416
                RemoveTimeOut(unlock_id);
 
417
                unlock_id = 0;
 
418
        }
 
419
 
 
420
        switch ((int)cstate) {
 
421
        case CONNECTED_INITIAL_E:
 
422
                /*
 
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.
 
427
                 */
 
428
                kybdlock_set(KL_AWAITING_FIRST, "kybd_in3270");
 
429
                break;
 
430
        case CONNECTED_ANSI:
 
431
        case CONNECTED_NVT:
 
432
        case CONNECTED_SSCP:
 
433
                /*
 
434
                 * We just transitioned to ANSI, TN3270E NVT or TN3270E SSCP-LU
 
435
                 * mode.  Remove all lock bits.
 
436
                 */
 
437
                kybdlock_clr(-1, "kybd_in3270");
 
438
                break;
 
439
        default:
 
440
                /*
 
441
                 * We just transitioned into or out of 3270 mode.
 
442
                 * Remove all lock bits except AWAITING_FIRST.
 
443
                 */
 
444
                kybdlock_clr(~KL_AWAITING_FIRST, "kybd_in3270");
 
445
                break;
 
446
        }
 
447
 
 
448
        /* There might be a macro pending. */
 
449
        if (CONNECTED)
 
450
                ps_process();
 
451
}
 
452
 
 
453
/*
 
454
 * Called to initialize the keyboard logic.
 
455
 */
 
456
void
 
457
kybd_init(void)
 
458
{
 
459
        /* Register interest in connect and disconnect events. */
 
460
        register_schange(ST_CONNECT, kybd_connect);
 
461
        register_schange(ST_3270_MODE, kybd_in3270);
 
462
}
 
463
 
 
464
/*
 
465
 * Toggle insert mode.
 
466
 */
 
467
static void
 
468
insert_mode(Boolean on)
 
469
{
 
470
        insert = on;
 
471
        status_insert_mode(on);
 
472
}
 
473
 
 
474
/*
 
475
 * Toggle reverse mode.
 
476
 */
 
477
static void
 
478
reverse_mode(Boolean on)
 
479
{
 
480
#if defined(X3270_DBCS) /*[*/
 
481
        if (!dbcs)
 
482
#endif /*]*/
 
483
        {
 
484
                reverse = on;
 
485
                status_reverse_mode(on);
 
486
        }
 
487
}
 
488
 
 
489
/*
 
490
 * Lock the keyboard because of an operator error.
 
491
 */
 
492
static void
 
493
operator_error(int error_type)
 
494
{
 
495
        if (sms_redirect())
 
496
                popup_an_error("Keyboard locked");
 
497
        if (appres.oerr_lock || sms_redirect()) {
 
498
                status_oerr(error_type);
 
499
                mcursor_locked();
 
500
                kybdlock_set((unsigned int)error_type, "operator_error");
 
501
                (void) flush_ta();
 
502
        } else {
 
503
                ring_bell();
 
504
        }
 
505
}
 
506
 
 
507
 
 
508
/*
 
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).
 
511
 */
 
512
static void
 
513
key_AID(unsigned char aid_code)
 
514
{
 
515
#if defined(X3270_ANSI) /*[*/
 
516
        if (IN_ANSI) {
 
517
                register unsigned i;
 
518
 
 
519
                if (aid_code == AID_ENTER) {
 
520
                        net_sendc('\r');
 
521
                        return;
 
522
                }
 
523
                for (i = 0; i < PF_SZ; i++)
 
524
                        if (aid_code == pf_xlate[i]) {
 
525
                                ansi_send_pf(i+1);
 
526
                                return;
 
527
                        }
 
528
                for (i = 0; i < PA_SZ; i++)
 
529
                        if (aid_code == pa_xlate[i]) {
 
530
                                ansi_send_pa(i+1);
 
531
                                return;
 
532
                        }
 
533
                return;
 
534
        }
 
535
#endif /*]*/
 
536
#if defined(X3270_PLUGIN) /*[*/
 
537
        plugin_aid(aid_code);
 
538
#endif /*]*/
 
539
 
 
540
        if (IN_SSCP) {
 
541
                if (kybdlock & KL_OIA_MINUS)
 
542
                        return;
 
543
                switch (aid_code) {
 
544
                case AID_CLEAR:
 
545
                        /* Handled locally. */
 
546
                        break;
 
547
                case AID_ENTER:
 
548
                        /*
 
549
                         * Act as if the host had written our input, and
 
550
                         * send it as a Read Modified.
 
551
                         */
 
552
                        buffer_addr = cursor_addr;
 
553
                        aid = aid_code;
 
554
                        ctlr_read_modified(aid, False);
 
555
                        status_ctlr_done();
 
556
                        break;
 
557
                default:
 
558
                        /* Everything else is invalid in SSCP-LU mode. */
 
559
                        status_minus();
 
560
                        kybdlock_set(KL_OIA_MINUS, "key_AID");
 
561
                        return;
 
562
                }
 
563
                return;
 
564
        }
 
565
 
 
566
        status_twait();
 
567
        mcursor_waiting();
 
568
        insert_mode(False);
 
569
        kybdlock_set(KL_OIA_TWAIT | KL_OIA_LOCKED, "key_AID");
 
570
        aid = aid_code;
 
571
        ctlr_read_modified(aid, False);
 
572
        ticking_start(False);
 
573
        status_ctlr_done();
 
574
}
 
575
 
 
576
void
 
577
PF_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
 
578
{
 
579
        unsigned k;
 
580
 
 
581
        action_debug(PF_action, event, params, num_params);
 
582
        if (check_usage(PF_action, *num_params, 1, 1) < 0)
 
583
                return;
 
584
        k = atoi(params[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();
 
589
                return;
 
590
        }
 
591
        reset_idle_timer();
 
592
        if (kybdlock & KL_OIA_MINUS)
 
593
                return;
 
594
        else if (kybdlock)
 
595
                enq_ta(PF_action, params[0], CN);
 
596
        else
 
597
                key_AID(pf_xlate[k-1]);
 
598
}
 
599
 
 
600
void
 
601
PA_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
 
602
{
 
603
        unsigned k;
 
604
 
 
605
        action_debug(PA_action, event, params, num_params);
 
606
        if (check_usage(PA_action, *num_params, 1, 1) < 0)
 
607
                return;
 
608
        k = atoi(params[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();
 
613
                return;
 
614
        }
 
615
        reset_idle_timer();
 
616
        if (kybdlock & KL_OIA_MINUS)
 
617
                return;
 
618
        else if (kybdlock)
 
619
                enq_ta(PA_action, params[0], CN);
 
620
        else
 
621
                key_AID(pa_xlate[k-1]);
 
622
}
 
623
 
 
624
 
 
625
/*
 
626
 * ATTN key, per RFC 2355.  Sends IP, regardless.
 
627
 */
 
628
void
 
629
Attn_action(Widget w _is_unused, XEvent *event, String *params,
 
630
    Cardinal *num_params)
 
631
{
 
632
        action_debug(Attn_action, event, params, num_params);
 
633
        if (check_usage(Attn_action, *num_params, 0, 0) < 0)
 
634
                return;
 
635
        if (!IN_3270)
 
636
                return;
 
637
        reset_idle_timer();
 
638
 
 
639
        if (IN_E) {
 
640
            if (net_bound()) {
 
641
                net_interrupt();
 
642
            } else {
 
643
                status_minus();
 
644
                kybdlock_set(KL_OIA_MINUS, "Attn_action");
 
645
            }
 
646
        } else {
 
647
            net_break();
 
648
        }
 
649
}
 
650
 
 
651
/*
 
652
 * IAC IP, which works for 5250 System Request and interrupts the program
 
653
 * on an AS/400, even when the keyboard is locked.
 
654
 *
 
655
 * This is now the same as the Attn action.
 
656
 */
 
657
void
 
658
Interrupt_action(Widget w _is_unused, XEvent *event, String *params,
 
659
    Cardinal *num_params)
 
660
{
 
661
        action_debug(Interrupt_action, event, params, num_params);
 
662
        if (check_usage(Interrupt_action, *num_params, 0, 0) < 0)
 
663
                return;
 
664
        if (!IN_3270)
 
665
                return;
 
666
        reset_idle_timer();
 
667
        net_interrupt();
 
668
}
 
669
 
 
670
 
 
671
 
 
672
/*
 
673
 * Prepare for an insert of 'count' bytes.
 
674
 * Returns True if the insert is legal, False otherwise.
 
675
 */
 
676
static Boolean
 
677
ins_prep(int faddr, int baddr, int count, Boolean *no_room)
 
678
{
 
679
        int next_faddr;
 
680
        int xaddr;
 
681
        int need;
 
682
        int ntb;
 
683
        int tb_start = -1;
 
684
        int copy_len;
 
685
 
 
686
        *no_room = False;
 
687
 
 
688
        /* Find the end of the field. */
 
689
        if (faddr == -1) {
 
690
                /* Unformatted.  Use the end of the line. */
 
691
                next_faddr = (((baddr / COLS) + 1) * COLS) % (ROWS*COLS);
 
692
        } else {
 
693
                next_faddr = faddr;
 
694
                INC_BA(next_faddr);
 
695
                while (next_faddr != faddr && !ea_buf[next_faddr].fa) {
 
696
                        INC_BA(next_faddr);
 
697
                }
 
698
        }
 
699
 
 
700
        /* Are there enough NULLs or trailing blanks available? */
 
701
        xaddr = baddr;
 
702
        need = count;
 
703
        ntb = 0;
 
704
        while (need && (xaddr != next_faddr)) {
 
705
                if (ea_buf[xaddr].cc == EBC_null)
 
706
                        need--;
 
707
                else if (toggled(BLANK_FILL) &&
 
708
                        ((ea_buf[xaddr].cc == EBC_space) ||
 
709
                         (ea_buf[xaddr].cc == EBC_underscore))) {
 
710
                        if (tb_start == -1)
 
711
                                tb_start = xaddr;
 
712
                        ntb++;
 
713
                } else {
 
714
                        tb_start = -1;
 
715
                        ntb = 0;
 
716
                }
 
717
                INC_BA(xaddr);
 
718
        }
 
719
#if defined(_ST) /*[*/
 
720
        printf("need %d at %d, tb_start at %d\n", count, baddr, tb_start);
 
721
#endif /*]*/
 
722
        if (need - ntb > 0) {
 
723
                if (!reverse) {
 
724
                        operator_error(KL_OERR_OVERFLOW);
 
725
                        return False;
 
726
                } else {
 
727
                        *no_room = True;
 
728
                        return True;
 
729
                }
 
730
        }
 
731
 
 
732
        /*
 
733
         * Shift the buffer to the right until we've consumed the available
 
734
         * (and needed) NULLs.
 
735
         */
 
736
        need = count;
 
737
        xaddr = baddr;
 
738
        while (need && (xaddr != next_faddr)) {
 
739
                int n_nulls = 0;
 
740
                int first_null = -1;
 
741
 
 
742
                while (need &&
 
743
                       ((ea_buf[xaddr].cc == EBC_null) ||
 
744
                        (tb_start >= 0 && xaddr >= tb_start))) {
 
745
                        need--;
 
746
                        n_nulls++;
 
747
                        if (first_null == -1)
 
748
                                first_null = xaddr;
 
749
                        INC_BA(xaddr);
 
750
                }
 
751
                if (n_nulls) {
 
752
                        int to;
 
753
 
 
754
                        /* Shift right n_nulls worth. */
 
755
                        copy_len = first_null - baddr;
 
756
                        if (copy_len < 0)
 
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,
 
762
                            first_null);
 
763
#endif /*]*/
 
764
                        if (copy_len)
 
765
                                ctlr_wrapping_memmove(to, baddr, copy_len);
 
766
                }
 
767
                INC_BA(xaddr);
 
768
        }
 
769
 
 
770
        return True;
 
771
 
 
772
}
 
773
 
 
774
#define GE_WFLAG        0x100
 
775
#define PASTE_WFLAG     0x200
 
776
 
 
777
static void
 
778
key_Character_wrapper(Widget w _is_unused, XEvent *event _is_unused, String *params,
 
779
    Cardinal *num_params _is_unused)
 
780
{
 
781
        int code;
 
782
        Boolean with_ge = False;
 
783
        Boolean pasting = False;
 
784
        char mb[16];
 
785
        ucs4_t uc;
 
786
 
 
787
        code = atoi(params[0]);
 
788
        if (code & GE_WFLAG) {
 
789
                with_ge = True;
 
790
                code &= ~GE_WFLAG;
 
791
        }
 
792
        if (code & PASTE_WFLAG) {
 
793
                pasting = True;
 
794
                code &= ~PASTE_WFLAG;
 
795
        }
 
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);
 
802
}
 
803
 
 
804
/*
 
805
 * Handle an ordinary displayable character key.  Lots of stuff to handle
 
806
 * insert-mode, protected fields and etc.
 
807
 */
 
808
/*static*/ Boolean
 
809
key_Character(int code, Boolean with_ge, Boolean pasting, Boolean *skipped)
 
810
{
 
811
        register int    baddr, faddr, xaddr;
 
812
        register unsigned char  fa;
 
813
        enum dbcs_why why = DBCS_FIELD;
 
814
        Boolean no_room = False;
 
815
 
 
816
        reset_idle_timer();
 
817
 
 
818
        if (skipped != NULL)
 
819
                *skipped = False;
 
820
 
 
821
        if (kybdlock) {
 
822
                char codename[64];
 
823
 
 
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);
 
828
                return False;
 
829
        }
 
830
        baddr = cursor_addr;
 
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);
 
835
                return False;
 
836
        }
 
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);
 
841
                return False;
 
842
        }
 
843
 
 
844
        /* Can't put an SBCS in a DBCS field. */
 
845
        if (ea_buf[faddr].cs == CS_DBCS) {
 
846
                operator_error(KL_OERR_DBCS);
 
847
                return False;
 
848
        }
 
849
 
 
850
        /* If it's an SI (end of DBCS subfield), move over one position. */
 
851
        if (ea_buf[baddr].cc == EBC_si) {
 
852
                INC_BA(baddr);
 
853
                if (baddr == faddr) {
 
854
                        operator_error(KL_OERR_OVERFLOW);
 
855
                        return False;
 
856
                }
 
857
        }
 
858
 
 
859
        /* Add the character. */
 
860
        if (ea_buf[baddr].cc == EBC_so) {
 
861
 
 
862
                if (insert) {
 
863
                        if (!ins_prep(faddr, baddr, 1, &no_room))
 
864
                                return False;
 
865
                } else {
 
866
                        Boolean was_si = False;
 
867
 
 
868
                        /*
 
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
 
873
                         * x/space/SO.
 
874
                         */
 
875
                        xaddr = baddr;
 
876
                        INC_BA(xaddr);
 
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);
 
882
#endif /*]*/
 
883
                        if (!was_si) {
 
884
                                INC_BA(xaddr);
 
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);
 
889
#endif /*]*/
 
890
                        }
 
891
                }
 
892
 
 
893
        } else switch (ctlr_lookleft_state(baddr, &why)) {
 
894
        case DBCS_RIGHT:
 
895
                DEC_BA(baddr);
 
896
                /* fall through... */
 
897
        case DBCS_LEFT:
 
898
                if (why == DBCS_ATTRIBUTE) {
 
899
                        if (insert) {
 
900
                                if (!ins_prep(faddr, baddr, 1, &no_room))
 
901
                                        return False;
 
902
                        } else {
 
903
                                /*
 
904
                                 * Replace single DBCS char with
 
905
                                 * x/space.
 
906
                                 */
 
907
                                xaddr = baddr;
 
908
                                INC_BA(xaddr);
 
909
                                ctlr_add(xaddr, EBC_space, CS_BASE);
 
910
                                ctlr_add_fg(xaddr, 0);
 
911
                                ctlr_add_gr(xaddr, 0);
 
912
                        }
 
913
                } else {
 
914
                        Boolean was_si;
 
915
 
 
916
                        if (insert) {
 
917
                                /*
 
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
 
924
                                 * subfield again).
 
925
                                 */
 
926
                                xaddr = baddr;
 
927
                                DEC_BA(xaddr);
 
928
                                if (ea_buf[xaddr].cc == EBC_so) {
 
929
                                        DEC_BA(baddr);
 
930
                                        if (!ins_prep(faddr, baddr, 1,
 
931
                                                    &no_room))
 
932
                                                return False;
 
933
                                } else {
 
934
                                        if (!ins_prep(faddr, baddr, 3,
 
935
                                                    &no_room))
 
936
                                                return False;
 
937
                                        xaddr = baddr;
 
938
                                        ctlr_add(xaddr, EBC_si,
 
939
                                            CS_BASE);
 
940
                                        ctlr_add_fg(xaddr, 0);
 
941
                                        ctlr_add_gr(xaddr, 0);
 
942
                                        INC_BA(xaddr);
 
943
                                        INC_BA(baddr);
 
944
                                        INC_BA(xaddr);
 
945
                                        ctlr_add(xaddr, EBC_so,
 
946
                                            CS_BASE);
 
947
                                        ctlr_add_fg(xaddr, 0);
 
948
                                        ctlr_add_gr(xaddr, 0);
 
949
                                }
 
950
                        } else {
 
951
                                /* Overwriting part of a subfield. */
 
952
                                xaddr = baddr;
 
953
                                ctlr_add(xaddr, EBC_si, CS_BASE);
 
954
                                ctlr_add_fg(xaddr, 0);
 
955
                                ctlr_add_gr(xaddr, 0);
 
956
                                INC_BA(xaddr);
 
957
                                INC_BA(baddr);
 
958
                                INC_BA(xaddr);
 
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);
 
963
                                if (!was_si) {
 
964
                                        INC_BA(xaddr);
 
965
                                        ctlr_add(xaddr, EBC_so,
 
966
                                            CS_BASE);
 
967
                                        ctlr_add_fg(xaddr, 0);
 
968
                                        ctlr_add_gr(xaddr, 0);
 
969
                                }
 
970
                        }
 
971
                }
 
972
                break;
 
973
        default:
 
974
        case DBCS_NONE:
 
975
                if ((reverse || insert) && !ins_prep(faddr, baddr, 1, &no_room))
 
976
                        return False;
 
977
                break;
 
978
        }
 
979
        if (no_room) {
 
980
                do {
 
981
                        INC_BA(baddr);
 
982
                } while (ea_buf[baddr].fa);
 
983
        } else {
 
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);
 
988
                if (!reverse)
 
989
                        INC_BA(baddr);
 
990
        }
 
991
 
 
992
        /* Replace leading nulls with blanks, if desired. */
 
993
        if (formatted && toggled(BLANK_FILL)) {
 
994
                register int    baddr_fill = baddr;
 
995
 
 
996
                DEC_BA(baddr_fill);
 
997
                while (baddr_fill != faddr) {
 
998
 
 
999
                        /* Check for backward line wrap. */
 
1000
                        if ((baddr_fill % COLS) == COLS - 1) {
 
1001
                                Boolean aborted = True;
 
1002
                                register int baddr_scan = baddr_fill;
 
1003
 
 
1004
                                /*
 
1005
                                 * Check the field within the preceeding line
 
1006
                                 * for NULLs.
 
1007
                                 */
 
1008
                                while (baddr_scan != faddr) {
 
1009
                                        if (ea_buf[baddr_scan].cc != EBC_null) {
 
1010
                                                aborted = False;
 
1011
                                                break;
 
1012
                                        }
 
1013
                                        if (!(baddr_scan % COLS))
 
1014
                                                break;
 
1015
                                        DEC_BA(baddr_scan);
 
1016
                                }
 
1017
                                if (aborted)
 
1018
                                        break;
 
1019
                        }
 
1020
 
 
1021
                        if (ea_buf[baddr_fill].cc == EBC_null)
 
1022
                                ctlr_add(baddr_fill, EBC_space, 0);
 
1023
                        DEC_BA(baddr_fill);
 
1024
                }
 
1025
        }
 
1026
 
 
1027
        mdt_set(cursor_addr);
 
1028
 
 
1029
        /*
 
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.
 
1033
         */
 
1034
        if (pasting || (code != EBC_dup)) {
 
1035
                while (ea_buf[baddr].fa) {
 
1036
                        if (skipped != NULL)
 
1037
                                *skipped = True;
 
1038
                        if (FA_IS_SKIP(ea_buf[baddr].fa))
 
1039
                                baddr = next_unprotected(baddr);
 
1040
                        else
 
1041
                                INC_BA(baddr);
 
1042
                }
 
1043
                cursor_move(baddr);
 
1044
        }
 
1045
 
 
1046
        (void) ctlr_dbcs_postprocess();
 
1047
        return True;
 
1048
}
 
1049
 
 
1050
#if defined(X3270_DBCS) /*[*/
 
1051
static void
 
1052
key_WCharacter_wrapper(Widget w _is_unused, XEvent *event _is_unused, String *params,
 
1053
    Cardinal *num_params _is_unused)
 
1054
{
 
1055
        int code;
 
1056
        unsigned char codebuf[2];
 
1057
 
 
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);
 
1064
}
 
1065
 
 
1066
/*
 
1067
 * Input a DBCS character.
 
1068
 * Returns True if a character was stored in the buffer, False otherwise.
 
1069
 */
 
1070
Boolean
 
1071
key_WCharacter(unsigned char code[], Boolean *skipped)
 
1072
{
 
1073
        int baddr;
 
1074
        register unsigned char fa;
 
1075
        int faddr;
 
1076
        enum dbcs_state d;
 
1077
        int xaddr;
 
1078
        Boolean done = False;
 
1079
        Boolean no_si = False;
 
1080
        Boolean no_room = False;
 
1081
        extern unsigned char reply_mode; /* XXX */
 
1082
 
 
1083
        reset_idle_timer();
 
1084
 
 
1085
        if (kybdlock) {
 
1086
                char codename[64];
 
1087
 
 
1088
                (void) sprintf(codename, "%d", (code[0] << 8) | code[1]);
 
1089
                enq_ta(key_WCharacter_wrapper, codename, CN);
 
1090
                return False;
 
1091
        }
 
1092
 
 
1093
        if (skipped != NULL)
 
1094
                *skipped = False;
 
1095
 
 
1096
        /* In DBCS mode? */
 
1097
#if defined(X3270_DBCS) /*[*/
 
1098
        if (!dbcs)
 
1099
#endif /*]*/
 
1100
        {
 
1101
                trace_event("DBCS character received when not in DBCS mode, "
 
1102
                    "ignoring.\n");
 
1103
                return True;
 
1104
        }
 
1105
 
 
1106
#if defined(X3270_ANSI) /*[*/
 
1107
        /* In ANSI mode? */
 
1108
        if (IN_ANSI) {
 
1109
            char mb[16];
 
1110
 
 
1111
            (void) ebcdic_to_multibyte((code[0] << 8) | code[1], mb,
 
1112
                                       sizeof(mb));
 
1113
            net_sends(mb);
 
1114
            return True;
 
1115
        }
 
1116
#endif /*]*/
 
1117
 
 
1118
        baddr = cursor_addr;
 
1119
        fa = get_field_attribute(baddr);
 
1120
        faddr = find_field_attribute(baddr);
 
1121
 
 
1122
        /* Protected? */
 
1123
        if (ea_buf[baddr].fa || FA_IS_PROTECTED(fa)) {
 
1124
                operator_error(KL_OERR_PROTECTED);
 
1125
                return False;
 
1126
        }
 
1127
 
 
1128
        /* Numeric? */
 
1129
        if (appres.numeric_lock && FA_IS_NUMERIC(fa)) {
 
1130
                operator_error(KL_OERR_NUMERIC);
 
1131
                return False;
 
1132
        }
 
1133
 
 
1134
        /*
 
1135
         * Figure our what to do based on the DBCS state of the buffer.
 
1136
         * Leaves baddr pointing to the next unmodified position.
 
1137
         */
 
1138
retry:
 
1139
        switch (d = ctlr_dbcs_state(baddr)) {
 
1140
        case DBCS_RIGHT:
 
1141
        case DBCS_RIGHT_WRAP:
 
1142
                /* Back up one position and process it as a LEFT. */
 
1143
                DEC_BA(baddr);
 
1144
                /* fall through... */
 
1145
        case DBCS_LEFT:
 
1146
        case DBCS_LEFT_WRAP:
 
1147
                /* Overwrite the existing character. */
 
1148
                if (insert) {
 
1149
                        if (!ins_prep(faddr, baddr, 2, &no_room)) {
 
1150
                                return False;
 
1151
                        }
 
1152
                }
 
1153
                ctlr_add(baddr, code[0], ea_buf[baddr].cs);
 
1154
                INC_BA(baddr);
 
1155
                ctlr_add(baddr, code[1], ea_buf[baddr].cs);
 
1156
                INC_BA(baddr);
 
1157
                done = True;
 
1158
                break;
 
1159
        case DBCS_SB:
 
1160
                /* Back up one position and process it as an SI. */
 
1161
                DEC_BA(baddr);
 
1162
                /* fall through... */
 
1163
        case DBCS_SI:
 
1164
                /* Extend the subfield to the right. */
 
1165
                if (insert) {
 
1166
                        if (!ins_prep(faddr, baddr, 2, &no_room)) {
 
1167
                                return False;
 
1168
                        }
 
1169
                } else {
 
1170
                        /* Don't overwrite a field attribute or an SO. */
 
1171
                        xaddr = baddr;
 
1172
                        INC_BA(xaddr);  /* C1 */
 
1173
                        if (ea_buf[xaddr].fa)
 
1174
                                break;
 
1175
                        if (ea_buf[xaddr].cc == EBC_so)
 
1176
                                no_si = True;
 
1177
                        INC_BA(xaddr);  /* SI */
 
1178
                        if (ea_buf[xaddr].fa || ea_buf[xaddr].cc == EBC_so)
 
1179
                                break;
 
1180
                }
 
1181
                ctlr_add(baddr, code[0], ea_buf[baddr].cs);
 
1182
                INC_BA(baddr);
 
1183
                ctlr_add(baddr, code[1], ea_buf[baddr].cs);
 
1184
                if (!no_si) {
 
1185
                        INC_BA(baddr);
 
1186
                        ctlr_add(baddr, EBC_si, ea_buf[baddr].cs);
 
1187
                }
 
1188
                done = True;
 
1189
                break;
 
1190
        case DBCS_DEAD:
 
1191
                break;
 
1192
        case DBCS_NONE:
 
1193
                if (ea_buf[faddr].ic) {
 
1194
                        Boolean extend_left = False;
 
1195
 
 
1196
                        /* Is there room? */
 
1197
                        if (insert) {
 
1198
                                if (!ins_prep(faddr, baddr, 4, &no_room)) {
 
1199
                                        return False;
 
1200
                                }
 
1201
                        } else {
 
1202
                                xaddr = baddr;  /* baddr, SO */
 
1203
                                if (ea_buf[xaddr].cc == EBC_so) {
 
1204
                                        /*
 
1205
                                         * (baddr), where we would have put the
 
1206
                                         * SO, is already an SO.  Move to
 
1207
                                         * (baddr+1) and try again.
 
1208
                                         */
 
1209
#if defined(DBCS_RIGHT_DEBUG) /*[*/
 
1210
                                        printf("SO in position 0\n");
 
1211
#endif /*]*/
 
1212
                                        INC_BA(baddr);
 
1213
                                        goto retry;
 
1214
                                }
 
1215
 
 
1216
                                INC_BA(xaddr);  /* baddr+1, C0 */
 
1217
                                if (ea_buf[xaddr].fa)
 
1218
                                        break;
 
1219
                                if (ea_buf[xaddr].cc == EBC_so) {
 
1220
                                        enum dbcs_state e;
 
1221
 
 
1222
                                        /*
 
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
 
1227
                                         * stuck.
 
1228
                                         */
 
1229
                                        DEC_BA(xaddr);
 
1230
                                        DEC_BA(xaddr);
 
1231
                                        e = ctlr_dbcs_state(xaddr);
 
1232
                                        if (e == DBCS_NONE || e == DBCS_SB) {
 
1233
                                                extend_left = True;
 
1234
                                                no_si = True;
 
1235
#if defined(DBCS_RIGHT_DEBUG) /*[*/
 
1236
                                                printf("SO in position 1, "
 
1237
                                                        "extend left\n");
 
1238
#endif /*]*/
 
1239
                                        } else {
 
1240
                                                /*
 
1241
                                                 * Won't actually happen,
 
1242
                                                 * because this implies that
 
1243
                                                 * the buffer addr at baddr
 
1244
                                                 * is an SB.
 
1245
                                                 */
 
1246
#if defined(DBCS_RIGHT_DEBUG) /*[*/
 
1247
                                                printf("SO in position 1, "
 
1248
                                                        "no room on left, "
 
1249
                                                        "fail\n");
 
1250
#endif /*]*/
 
1251
                                                break;
 
1252
                                        }
 
1253
                                }
 
1254
 
 
1255
                                INC_BA(xaddr); /* baddr+2, C1 */
 
1256
                                if (ea_buf[xaddr].fa)
 
1257
                                        break;
 
1258
                                if (ea_buf[xaddr].cc == EBC_so) {
 
1259
                                        /*
 
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.
 
1265
                                         */
 
1266
                                        no_si = True;
 
1267
#if defined(DBCS_RIGHT_DEBUG) /*[*/
 
1268
                                        printf("SO in position 2, no SI\n");
 
1269
#endif /*]*/
 
1270
                                }
 
1271
 
 
1272
                                /*
 
1273
                                 * Check the fourth position only if we're
 
1274
                                 * not doing an extend-left.
 
1275
                                 */
 
1276
                                if (!no_si) {
 
1277
                                        INC_BA(xaddr); /* baddr+3, SI */
 
1278
                                        if (ea_buf[xaddr].fa)
 
1279
                                                break;
 
1280
                                        if (ea_buf[xaddr].cc == EBC_so) {
 
1281
                                                /*
 
1282
                                                 * (baddr+3), where we want to
 
1283
                                                 * put an
 
1284
                                                 * SI, is an SO.  Forget it.
 
1285
                                                 */
 
1286
#if defined(DBCS_RIGHT_DEBUG) /*[*/
 
1287
                                                printf("SO in position 3, "
 
1288
                                                        "retry right\n");
 
1289
                                                INC_BA(baddr);
 
1290
                                                goto retry;
 
1291
#endif /*]*/
 
1292
                                                break;
 
1293
                                        }
 
1294
                                }
 
1295
                        }
 
1296
                        /* Yes, add it. */
 
1297
                        if (extend_left)
 
1298
                                DEC_BA(baddr);
 
1299
                        ctlr_add(baddr, EBC_so, ea_buf[baddr].cs);
 
1300
                        INC_BA(baddr);
 
1301
                        ctlr_add(baddr, code[0], ea_buf[baddr].cs);
 
1302
                        INC_BA(baddr);
 
1303
                        ctlr_add(baddr, code[1], ea_buf[baddr].cs);
 
1304
                        if (!no_si) {
 
1305
                                INC_BA(baddr);
 
1306
                                ctlr_add(baddr, EBC_si, ea_buf[baddr].cs);
 
1307
                        }
 
1308
                        done = True;
 
1309
                } else if (reply_mode == SF_SRM_CHAR) {
 
1310
                        /* Use the character attribute. */
 
1311
                        if (insert) {
 
1312
                                if (!ins_prep(faddr, baddr, 2, &no_room)) {
 
1313
                                        return False;
 
1314
                                }
 
1315
                        } else {
 
1316
                                xaddr = baddr;
 
1317
                                INC_BA(xaddr);
 
1318
                                if (ea_buf[xaddr].fa)
 
1319
                                        break;
 
1320
                        }
 
1321
                        ctlr_add(baddr, code[0], CS_DBCS);
 
1322
                        INC_BA(baddr);
 
1323
                        ctlr_add(baddr, code[1], CS_DBCS);
 
1324
                        INC_BA(baddr);
 
1325
                        done = True;
 
1326
                }
 
1327
                break;
 
1328
        }
 
1329
 
 
1330
        if (done) {
 
1331
                /* Implement blank fill mode. */
 
1332
                if (toggled(BLANK_FILL)) {
 
1333
                        xaddr = faddr;
 
1334
                        INC_BA(xaddr);
 
1335
                        while (xaddr != baddr) {
 
1336
                                if (ea_buf[xaddr].cc == EBC_null)
 
1337
                                        ctlr_add(xaddr, EBC_space, CS_BASE);
 
1338
                                else
 
1339
                                        break;
 
1340
                                INC_BA(xaddr);
 
1341
                        }
 
1342
                }
 
1343
 
 
1344
                mdt_set(cursor_addr);
 
1345
 
 
1346
                /* Implement auto-skip. */
 
1347
                while (ea_buf[baddr].fa) {
 
1348
                        if (skipped != NULL)
 
1349
                                *skipped = True;
 
1350
                        if (FA_IS_SKIP(ea_buf[baddr].fa))
 
1351
                                baddr = next_unprotected(baddr);
 
1352
                        else
 
1353
                                INC_BA(baddr);
 
1354
                }
 
1355
                cursor_move(baddr);
 
1356
                (void) ctlr_dbcs_postprocess();
 
1357
                return True;
 
1358
        } else {
 
1359
                operator_error(KL_OERR_DBCS);
 
1360
                return False;
 
1361
        }
 
1362
}
 
1363
#endif /*]*/
 
1364
 
 
1365
/*
 
1366
 * Handle an ordinary character key, given its Unicode value.
 
1367
 */
 
1368
static void
 
1369
key_UCharacter(ucs4_t ucs4, enum keytype keytype, enum iaction cause,
 
1370
               Boolean *skipped)
 
1371
{
 
1372
        register int i;
 
1373
        struct akeysym ak;
 
1374
 
 
1375
        reset_idle_timer();
 
1376
 
 
1377
        if (skipped != NULL)
 
1378
                *skipped = False;
 
1379
 
 
1380
        ak.keysym = ucs4;
 
1381
        ak.keytype = keytype;
 
1382
 
 
1383
        switch (composing) {
 
1384
            case NONE:
 
1385
                break;
 
1386
            case COMPOSE:
 
1387
                for (i = 0; i < n_composites; i++)
 
1388
                        if (ak_eq(composites[i].k1, ak) ||
 
1389
                            ak_eq(composites[i].k2, ak))
 
1390
                                break;
 
1391
                if (i < n_composites) {
 
1392
                        cc_first.keysym = ucs4;
 
1393
                        cc_first.keytype = keytype;
 
1394
                        composing = FIRST;
 
1395
                        status_compose(True, ucs4, keytype);
 
1396
                } else {
 
1397
                        ring_bell();
 
1398
                        composing = NONE;
 
1399
                        status_compose(False, 0, KT_STD);
 
1400
                }
 
1401
                return;
 
1402
            case FIRST:
 
1403
                composing = NONE;
 
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)))
 
1410
                                break;
 
1411
                if (i < n_composites) {
 
1412
                        ucs4 = composites[i].translation.keysym;
 
1413
                        keytype = composites[i].translation.keytype;
 
1414
                } else {
 
1415
                        ring_bell();
 
1416
                        return;
 
1417
                }
 
1418
                break;
 
1419
        }
 
1420
 
 
1421
        trace_event(" %s -> Key(U+%04x)\n", ia_name[(int) cause], ucs4);
 
1422
        if (IN_3270) {
 
1423
                ebc_t ebc;
 
1424
                Boolean ge;
 
1425
 
 
1426
                if (ucs4 < ' ') {
 
1427
                        trace_event("  dropped (control char)\n");
 
1428
                        return;
 
1429
                }
 
1430
                ebc = unicode_to_ebcdic_ge(ucs4, &ge);
 
1431
                if (ebc == 0) {
 
1432
                        trace_event("  dropped (no EBCDIC translation)\n");
 
1433
                        return;
 
1434
                }
 
1435
#if defined(X3270_DBCS) /*[*/
 
1436
                if (ebc & 0xff00) {
 
1437
                        unsigned char code[2];
 
1438
 
 
1439
                        code[0] = (ebc & 0xff00)>> 8;
 
1440
                        code[1] = ebc & 0xff;
 
1441
                        (void) key_WCharacter(code, skipped);
 
1442
                } else
 
1443
#endif /*]*/
 
1444
                        (void) key_Character(ebc, (keytype == KT_GE) || ge,
 
1445
                                             False, skipped);
 
1446
        }
 
1447
#if defined(X3270_ANSI) /*[*/
 
1448
        else if (IN_ANSI) {
 
1449
                char mb[16];
 
1450
 
 
1451
                unicode_to_multibyte(ucs4, mb, sizeof(mb));
 
1452
                net_sends(mb);
 
1453
        }
 
1454
#endif /*]*/
 
1455
        else {
 
1456
                trace_event("  dropped (not connected)\n");
 
1457
        }
 
1458
}
 
1459
 
 
1460
#if defined(X3270_DISPLAY) /*[*/
 
1461
/*
 
1462
 * Handle an ordinary character key, given its NULL-terminated multibyte
 
1463
 * representation.
 
1464
 */
 
1465
static void
 
1466
key_ACharacter(char *mb, enum keytype keytype, enum iaction cause,
 
1467
               Boolean *skipped)
 
1468
{
 
1469
        ucs4_t ucs4;
 
1470
        int consumed;
 
1471
        enum me_fail error;
 
1472
 
 
1473
        reset_idle_timer();
 
1474
 
 
1475
        if (skipped != NULL)
 
1476
                *skipped = False;
 
1477
 
 
1478
        /* Convert the multibyte string to UCS4. */
 
1479
        ucs4 = multibyte_to_unicode(mb, strlen(mb), &consumed, &error);
 
1480
        if (ucs4 == 0) {
 
1481
                trace_event(" %s -> Key(?)\n", ia_name[(int) cause]);
 
1482
                trace_event("  dropped (invalid multibyte sequence)\n");
 
1483
                return;
 
1484
        }
 
1485
 
 
1486
        key_UCharacter(ucs4, keytype, cause, skipped);
 
1487
}
 
1488
#endif /*]*/
 
1489
 
 
1490
 
 
1491
/*
 
1492
 * Simple toggles.
 
1493
 */
 
1494
#if defined(X3270_DISPLAY) /*[*/
 
1495
void
 
1496
AltCursor_action(Widget w _is_unused, XEvent *event, String *params,
 
1497
    Cardinal *num_params)
 
1498
{
 
1499
        action_debug(AltCursor_action, event, params, num_params);
 
1500
        if (check_usage(AltCursor_action, *num_params, 0, 0) < 0)
 
1501
                return;
 
1502
        reset_idle_timer();
 
1503
        do_toggle(ALT_CURSOR);
 
1504
}
 
1505
#endif /*]*/
 
1506
 
 
1507
void
 
1508
MonoCase_action(Widget w _is_unused, XEvent *event, String *params,
 
1509
    Cardinal *num_params)
 
1510
{
 
1511
        action_debug(MonoCase_action, event, params, num_params);
 
1512
        if (check_usage(MonoCase_action, *num_params, 0, 0) < 0)
 
1513
                return;
 
1514
        reset_idle_timer();
 
1515
        do_toggle(MONOCASE);
 
1516
}
 
1517
 
 
1518
/*
 
1519
 * Flip the display left-to-right
 
1520
 */
 
1521
void
 
1522
Flip_action(Widget w _is_unused, XEvent *event, String *params,
 
1523
    Cardinal *num_params)
 
1524
{
 
1525
        action_debug(Flip_action, event, params, num_params);
 
1526
        if (check_usage(Flip_action, *num_params, 0, 0) < 0)
 
1527
                return;
 
1528
        reset_idle_timer();
 
1529
#if defined(X3270_DBCS) /*[*/
 
1530
        if (!dbcs)
 
1531
#endif /*]*/
 
1532
            screen_flip();
 
1533
}
 
1534
 
 
1535
 
 
1536
 
 
1537
/*
 
1538
 * Tab forward to next field.
 
1539
 */
 
1540
void
 
1541
Tab_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
 
1542
{
 
1543
        action_debug(Tab_action, event, params, num_params);
 
1544
        if (check_usage(Tab_action, *num_params, 0, 0) < 0)
 
1545
                return;
 
1546
        reset_idle_timer();
 
1547
        if (kybdlock) {
 
1548
                if (KYBDLOCK_IS_OERR) {
 
1549
                        kybdlock_clr(KL_OERR_MASK, "Tab");
 
1550
                        status_reset();
 
1551
                } else {
 
1552
                        enq_ta(Tab_action, CN, CN);
 
1553
                        return;
 
1554
                }
 
1555
        }
 
1556
#if defined(X3270_ANSI) /*[*/
 
1557
        if (IN_ANSI) {
 
1558
                net_sendc('\t');
 
1559
                return;
 
1560
        }
 
1561
#endif /*]*/
 
1562
        cursor_move(next_unprotected(cursor_addr));
 
1563
}
 
1564
 
 
1565
 
 
1566
/*
 
1567
 * Tab backward to previous field.
 
1568
 */
 
1569
void
 
1570
BackTab_action(Widget w _is_unused, XEvent *event, String *params,
 
1571
    Cardinal *num_params)
 
1572
{
 
1573
        register int    baddr, nbaddr;
 
1574
        int             sbaddr;
 
1575
 
 
1576
        action_debug(BackTab_action, event, params, num_params);
 
1577
        if (check_usage(BackTab_action, *num_params, 0, 0) < 0)
 
1578
                return;
 
1579
        reset_idle_timer();
 
1580
        if (kybdlock) {
 
1581
                if (KYBDLOCK_IS_OERR) {
 
1582
                        kybdlock_clr(KL_OERR_MASK, "BackTab");
 
1583
                        status_reset();
 
1584
                } else {
 
1585
                        enq_ta(BackTab_action, CN, CN);
 
1586
                        return;
 
1587
                }
 
1588
        }
 
1589
        if (!IN_3270)
 
1590
                return;
 
1591
        baddr = cursor_addr;
 
1592
        DEC_BA(baddr);
 
1593
        if (ea_buf[baddr].fa)   /* at bof */
 
1594
                DEC_BA(baddr);
 
1595
        sbaddr = baddr;
 
1596
        while (True) {
 
1597
                nbaddr = baddr;
 
1598
                INC_BA(nbaddr);
 
1599
                if (ea_buf[baddr].fa &&
 
1600
                    !FA_IS_PROTECTED(ea_buf[baddr].fa) &&
 
1601
                    !ea_buf[nbaddr].fa)
 
1602
                        break;
 
1603
                DEC_BA(baddr);
 
1604
                if (baddr == sbaddr) {
 
1605
                        cursor_move(0);
 
1606
                        return;
 
1607
                }
 
1608
        }
 
1609
        INC_BA(baddr);
 
1610
        cursor_move(baddr);
 
1611
}
 
1612
 
 
1613
 
 
1614
/*
 
1615
 * Deferred keyboard unlock.
 
1616
 */
 
1617
 
 
1618
static void
 
1619
defer_unlock(void)
 
1620
{
 
1621
        kybdlock_clr(KL_DEFERRED_UNLOCK, "defer_unlock");
 
1622
        status_reset();
 
1623
        if (CONNECTED)
 
1624
                ps_process();
 
1625
}
 
1626
 
 
1627
/*
 
1628
 * Reset keyboard lock.
 
1629
 */
 
1630
void
 
1631
do_reset(Boolean explicit)
 
1632
{
 
1633
        /*
 
1634
         * If explicit (from the keyboard) and there is typeahead or
 
1635
         * a half-composed key, simply flush it.
 
1636
         */
 
1637
        if (explicit
 
1638
#if defined(X3270_FT) /*[*/
 
1639
            || ft_state != FT_NONE
 
1640
#endif /*]*/
 
1641
            ) {
 
1642
                Boolean half_reset = False;
 
1643
 
 
1644
                if (flush_ta())
 
1645
                        half_reset = True;
 
1646
                if (composing != NONE) {
 
1647
                        composing = NONE;
 
1648
                        status_compose(False, 0, KT_STD);
 
1649
                        half_reset = True;
 
1650
                }
 
1651
                if (half_reset)
 
1652
                        return;
 
1653
        }
 
1654
 
 
1655
        /* Always clear insert mode. */
 
1656
        insert_mode(False);
 
1657
 
 
1658
        /* Otherwise, if not connect, reset is a no-op. */
 
1659
        if (!CONNECTED)
 
1660
                return;
 
1661
 
 
1662
        /*
 
1663
         * Remove any deferred keyboard unlock.  We will either unlock the
 
1664
         * keyboard now, or want to defer further into the future.
 
1665
         */
 
1666
        if ((kybdlock & KL_DEFERRED_UNLOCK) && unlock_id) {
 
1667
                RemoveTimeOut(unlock_id);
 
1668
                unlock_id = 0;
 
1669
        }
 
1670
 
 
1671
        /*
 
1672
         * If explicit (from the keyboard), unlock the keyboard now.
 
1673
         * Otherwise (from the host), schedule a deferred keyboard unlock.
 
1674
         */
 
1675
        if (explicit
 
1676
#if defined(X3270_FT) /*[*/
 
1677
            || ft_state != FT_NONE
 
1678
#endif /*]*/
 
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);
 
1690
        }
 
1691
 
 
1692
        /* Clean up other modes. */
 
1693
        status_reset();
 
1694
        mcursor_normal();
 
1695
        composing = NONE;
 
1696
        status_compose(False, 0, KT_STD);
 
1697
}
 
1698
 
 
1699
void
 
1700
Reset_action(Widget w _is_unused, XEvent *event, String *params,
 
1701
    Cardinal *num_params)
 
1702
{
 
1703
        action_debug(Reset_action, event, params, num_params);
 
1704
        if (check_usage(Reset_action, *num_params, 0, 0) < 0)
 
1705
                return;
 
1706
        reset_idle_timer();
 
1707
        do_reset(True);
 
1708
}
 
1709
 
 
1710
 
 
1711
/*
 
1712
 * Move to first unprotected field on screen.
 
1713
 */
 
1714
void
 
1715
Home_action(Widget w _is_unused, XEvent *event, String *params,
 
1716
    Cardinal *num_params)
 
1717
{
 
1718
        action_debug(Home_action, event, params, num_params);
 
1719
        if (check_usage(Home_action, *num_params, 0, 0) < 0)
 
1720
                return;
 
1721
        reset_idle_timer();
 
1722
        if (kybdlock) {
 
1723
                enq_ta(Home_action, CN, CN);
 
1724
                return;
 
1725
        }
 
1726
#if defined(X3270_ANSI) /*[*/
 
1727
        if (IN_ANSI) {
 
1728
                ansi_send_home();
 
1729
                return;
 
1730
        }
 
1731
#endif /*]*/
 
1732
        if (!formatted) {
 
1733
                cursor_move(0);
 
1734
                return;
 
1735
        }
 
1736
        cursor_move(next_unprotected(ROWS*COLS-1));
 
1737
}
 
1738
 
 
1739
 
 
1740
/*
 
1741
 * Cursor left 1 position.
 
1742
 */
 
1743
static void
 
1744
do_left(void)
 
1745
{
 
1746
        register int    baddr;
 
1747
        enum dbcs_state d;
 
1748
 
 
1749
        baddr = cursor_addr;
 
1750
        DEC_BA(baddr);
 
1751
        d = ctlr_dbcs_state(baddr);
 
1752
        if (IS_RIGHT(d)) {
 
1753
                DEC_BA(baddr);
 
1754
        } else if (IS_LEFT(d)) {
 
1755
                DEC_BA(baddr);
 
1756
                d = ctlr_dbcs_state(baddr);
 
1757
                if (IS_RIGHT(d))
 
1758
                        DEC_BA(baddr);
 
1759
        }
 
1760
        cursor_move(baddr);
 
1761
}
 
1762
 
 
1763
void
 
1764
Left_action(Widget w _is_unused, XEvent *event, String *params,
 
1765
    Cardinal *num_params)
 
1766
{
 
1767
        action_debug(Left_action, event, params, num_params);
 
1768
        if (check_usage(Left_action, *num_params, 0, 0) < 0)
 
1769
                return;
 
1770
        reset_idle_timer();
 
1771
        if (kybdlock) {
 
1772
                if (KYBDLOCK_IS_OERR) {
 
1773
                        kybdlock_clr(KL_OERR_MASK, "Left");
 
1774
                        status_reset();
 
1775
                } else {
 
1776
                        enq_ta(Left_action, CN, CN);
 
1777
                        return;
 
1778
                }
 
1779
        }
 
1780
#if defined(X3270_ANSI) /*[*/
 
1781
        if (IN_ANSI) {
 
1782
                ansi_send_left();
 
1783
                return;
 
1784
        }
 
1785
#endif /*]*/
 
1786
        if (!flipped)
 
1787
                do_left();
 
1788
        else {
 
1789
                register int    baddr;
 
1790
 
 
1791
                baddr = cursor_addr;
 
1792
                INC_BA(baddr);
 
1793
                cursor_move(baddr);
 
1794
        }
 
1795
}
 
1796
 
 
1797
 
 
1798
/*
 
1799
 * Delete char key.
 
1800
 * Returns "True" if succeeds, "False" otherwise.
 
1801
 */
 
1802
static Boolean
 
1803
do_delete(void)
 
1804
{
 
1805
        register int    baddr, end_baddr;
 
1806
        int xaddr;
 
1807
        register unsigned char  fa;
 
1808
        int ndel;
 
1809
        register int i;
 
1810
 
 
1811
        baddr = cursor_addr;
 
1812
 
 
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);
 
1817
                return False;
 
1818
        }
 
1819
        if (ea_buf[baddr].cc == EBC_so || ea_buf[baddr].cc == EBC_si) {
 
1820
                /*
 
1821
                 * Can't delete SO or SI, unless it's adjacent to its
 
1822
                 * opposite.
 
1823
                 */
 
1824
                xaddr = baddr;
 
1825
                INC_BA(xaddr);
 
1826
                if (ea_buf[xaddr].cc == SOSI(ea_buf[baddr].cc)) {
 
1827
                        ndel = 2;
 
1828
                } else {
 
1829
                        operator_error(KL_OERR_PROTECTED);
 
1830
                        return False;
 
1831
                }
 
1832
        } else if (IS_DBCS(ea_buf[baddr].db)) {
 
1833
                if (IS_RIGHT(ea_buf[baddr].db))
 
1834
                        DEC_BA(baddr);
 
1835
                ndel = 2;
 
1836
        } else
 
1837
                ndel = 1;
 
1838
 
 
1839
        /* find next fa */
 
1840
        if (formatted) {
 
1841
                end_baddr = baddr;
 
1842
                do {
 
1843
                        INC_BA(end_baddr);
 
1844
                        if (ea_buf[end_baddr].fa)
 
1845
                                break;
 
1846
                } while (end_baddr != baddr);
 
1847
                DEC_BA(end_baddr);
 
1848
        } else {
 
1849
                if ((baddr % COLS) == COLS - ndel)
 
1850
                        return True;
 
1851
                end_baddr = baddr + (COLS - (baddr % COLS)) - 1;
 
1852
        }
 
1853
 
 
1854
        /* Shift the remainder of the field left. */
 
1855
        if (end_baddr > baddr) {
 
1856
                ctlr_bcopy(baddr + ndel, baddr, end_baddr - (baddr + ndel) + 1,
 
1857
                    0);
 
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);
 
1864
        }
 
1865
 
 
1866
        /* NULL fill at the end. */
 
1867
        for (i = 0; i < ndel; i++)
 
1868
                ctlr_add(end_baddr - i, EBC_null, 0);
 
1869
 
 
1870
        /* Set the MDT for this field. */
 
1871
        mdt_set(cursor_addr);
 
1872
 
 
1873
        /* Patch up the DBCS state for display. */
 
1874
        (void) ctlr_dbcs_postprocess();
 
1875
        return True;
 
1876
}
 
1877
 
 
1878
void
 
1879
Delete_action(Widget w _is_unused, XEvent *event, String *params,
 
1880
    Cardinal *num_params)
 
1881
{
 
1882
        action_debug(Delete_action, event, params, num_params);
 
1883
        reset_idle_timer();
 
1884
        if (kybdlock) {
 
1885
                enq_ta(Delete_action, CN, CN);
 
1886
                return;
 
1887
        }
 
1888
#if defined(X3270_ANSI) /*[*/
 
1889
        if (IN_ANSI) {
 
1890
                net_sendc('\177');
 
1891
                return;
 
1892
        }
 
1893
#endif /*]*/
 
1894
        if (!do_delete())
 
1895
                return;
 
1896
        if (reverse) {
 
1897
                int baddr = cursor_addr;
 
1898
 
 
1899
                DEC_BA(baddr);
 
1900
                if (!ea_buf[baddr].fa)
 
1901
                        cursor_move(baddr);
 
1902
        }
 
1903
}
 
1904
 
 
1905
 
 
1906
/*
 
1907
 * 3270-style backspace.
 
1908
 */
 
1909
void
 
1910
BackSpace_action(Widget w _is_unused, XEvent *event, String *params,
 
1911
    Cardinal *num_params)
 
1912
{
 
1913
        action_debug(BackSpace_action, event, params, num_params);
 
1914
        reset_idle_timer();
 
1915
        if (kybdlock) {
 
1916
                enq_ta(BackSpace_action, CN, CN);
 
1917
                return;
 
1918
        }
 
1919
#if defined(X3270_ANSI) /*[*/
 
1920
        if (IN_ANSI) {
 
1921
                net_send_erase();
 
1922
                return;
 
1923
        }
 
1924
#endif /*]*/
 
1925
        if (reverse)
 
1926
                (void) do_delete();
 
1927
        else if (!flipped)
 
1928
                do_left();
 
1929
        else {
 
1930
                register int    baddr;
 
1931
 
 
1932
                baddr = cursor_addr;
 
1933
                DEC_BA(baddr);
 
1934
                cursor_move(baddr);
 
1935
        }
 
1936
}
 
1937
 
 
1938
 
 
1939
/*
 
1940
 * Destructive backspace, like Unix "erase".
 
1941
 */
 
1942
static void
 
1943
do_erase(void)
 
1944
{
 
1945
        int     baddr, faddr;
 
1946
        enum dbcs_state d;
 
1947
 
 
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);
 
1952
                return;
 
1953
        }
 
1954
        if (baddr && faddr == baddr - 1)
 
1955
                return;
 
1956
        do_left();
 
1957
 
 
1958
        /*
 
1959
         * If we are now on an SI, move left again.
 
1960
         */
 
1961
        if (ea_buf[cursor_addr].cc == EBC_si) {
 
1962
                baddr = cursor_addr;
 
1963
                DEC_BA(baddr);
 
1964
                cursor_move(baddr);
 
1965
        }
 
1966
 
 
1967
        /*
 
1968
         * If we landed on the right-hand side of a DBCS character, move to the
 
1969
         * left-hand side.
 
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.
 
1972
         */
 
1973
        d = ctlr_dbcs_state(cursor_addr);
 
1974
        if (IS_RIGHT(d)) {
 
1975
                baddr = cursor_addr;
 
1976
                DEC_BA(baddr);
 
1977
                cursor_move(baddr);
 
1978
        }
 
1979
 
 
1980
        /*
 
1981
         * Try to delete this character.
 
1982
         */
 
1983
        if (!do_delete())
 
1984
                return;
 
1985
 
 
1986
        /*
 
1987
         * If we've just erased the last character of a DBCS subfield, erase
 
1988
         * the SO/SI pair as well.
 
1989
         */
 
1990
        baddr = cursor_addr;
 
1991
        DEC_BA(baddr);
 
1992
        if (ea_buf[baddr].cc == EBC_so && ea_buf[cursor_addr].cc == EBC_si) {
 
1993
                cursor_move(baddr);
 
1994
                (void) do_delete();
 
1995
        }
 
1996
}
 
1997
 
 
1998
void
 
1999
Erase_action(Widget w _is_unused, XEvent *event, String *params,
 
2000
    Cardinal *num_params)
 
2001
{
 
2002
        action_debug(Erase_action, event, params, num_params);
 
2003
        reset_idle_timer();
 
2004
        if (kybdlock) {
 
2005
                enq_ta(Erase_action, CN, CN);
 
2006
                return;
 
2007
        }
 
2008
#if defined(X3270_ANSI) /*[*/
 
2009
        if (IN_ANSI) {
 
2010
                net_send_erase();
 
2011
                return;
 
2012
        }
 
2013
#endif /*]*/
 
2014
        if (reverse)
 
2015
                do_delete();
 
2016
        else
 
2017
                do_erase();
 
2018
}
 
2019
 
 
2020
 
 
2021
/*
 
2022
 * Cursor right 1 position.
 
2023
 */
 
2024
void
 
2025
Right_action(Widget w _is_unused, XEvent *event, String *params,
 
2026
    Cardinal *num_params)
 
2027
{
 
2028
        register int    baddr;
 
2029
        enum dbcs_state d;
 
2030
 
 
2031
        action_debug(Right_action, event, params, num_params);
 
2032
        reset_idle_timer();
 
2033
        if (kybdlock) {
 
2034
                if (KYBDLOCK_IS_OERR) {
 
2035
                        kybdlock_clr(KL_OERR_MASK, "Right");
 
2036
                        status_reset();
 
2037
                } else {
 
2038
                        enq_ta(Right_action, CN, CN);
 
2039
                        return;
 
2040
                }
 
2041
        }
 
2042
#if defined(X3270_ANSI) /*[*/
 
2043
        if (IN_ANSI) {
 
2044
                ansi_send_right();
 
2045
                return;
 
2046
        }
 
2047
#endif /*]*/
 
2048
        if (!flipped) {
 
2049
                baddr = cursor_addr;
 
2050
                INC_BA(baddr);
 
2051
                d = ctlr_dbcs_state(baddr);
 
2052
                if (IS_RIGHT(d))
 
2053
                        INC_BA(baddr);
 
2054
                cursor_move(baddr);
 
2055
        } else
 
2056
                do_left();
 
2057
}
 
2058
 
 
2059
 
 
2060
/*
 
2061
 * Cursor left 2 positions.
 
2062
 */
 
2063
void
 
2064
Left2_action(Widget w _is_unused, XEvent *event, String *params,
 
2065
    Cardinal *num_params)
 
2066
{
 
2067
        register int    baddr;
 
2068
        enum dbcs_state d;
 
2069
 
 
2070
        action_debug(Left2_action, event, params, num_params);
 
2071
        reset_idle_timer();
 
2072
        if (kybdlock) {
 
2073
                if (KYBDLOCK_IS_OERR) {
 
2074
                        kybdlock_clr(KL_OERR_MASK, "Left2");
 
2075
                        status_reset();
 
2076
                } else {
 
2077
                        enq_ta(Left2_action, CN, CN);
 
2078
                        return;
 
2079
                }
 
2080
        }
 
2081
#if defined(X3270_ANSI) /*[*/
 
2082
        if (IN_ANSI)
 
2083
                return;
 
2084
#endif /*]*/
 
2085
        baddr = cursor_addr;
 
2086
        DEC_BA(baddr);
 
2087
        d = ctlr_dbcs_state(baddr);
 
2088
        if (IS_LEFT(d))
 
2089
                DEC_BA(baddr);
 
2090
        DEC_BA(baddr);
 
2091
        d = ctlr_dbcs_state(baddr);
 
2092
        if (IS_LEFT(d))
 
2093
                DEC_BA(baddr);
 
2094
        cursor_move(baddr);
 
2095
}
 
2096
 
 
2097
 
 
2098
/*
 
2099
 * Cursor to previous word.
 
2100
 */
 
2101
void
 
2102
PreviousWord_action(Widget w _is_unused, XEvent *event, String *params,
 
2103
    Cardinal *num_params)
 
2104
{
 
2105
        register int baddr;
 
2106
        int baddr0;
 
2107
        unsigned char  c;
 
2108
        Boolean prot;
 
2109
 
 
2110
        action_debug(PreviousWord_action, event, params, num_params);
 
2111
        reset_idle_timer();
 
2112
        if (kybdlock) {
 
2113
                enq_ta(PreviousWord_action, CN, CN);
 
2114
                return;
 
2115
        }
 
2116
#if defined(X3270_ANSI) /*[*/
 
2117
        if (IN_ANSI)
 
2118
                return;
 
2119
#endif /*]*/
 
2120
        if (!formatted)
 
2121
                return;
 
2122
 
 
2123
        baddr = cursor_addr;
 
2124
        prot = FA_IS_PROTECTED(get_field_attribute(baddr));
 
2125
 
 
2126
        /* Skip to before this word, if in one now. */
 
2127
        if (!prot) {
 
2128
                c = ea_buf[baddr].cc;
 
2129
                while (!ea_buf[baddr].fa && c != EBC_space && c != EBC_null) {
 
2130
                        DEC_BA(baddr);
 
2131
                        if (baddr == cursor_addr)
 
2132
                                return;
 
2133
                        c = ea_buf[baddr].cc;
 
2134
                }
 
2135
        }
 
2136
        baddr0 = baddr;
 
2137
 
 
2138
        /* Find the end of the preceding word. */
 
2139
        do {
 
2140
                c = ea_buf[baddr].cc;
 
2141
                if (ea_buf[baddr].fa) {
 
2142
                        DEC_BA(baddr);
 
2143
                        prot = FA_IS_PROTECTED(get_field_attribute(baddr));
 
2144
                        continue;
 
2145
                }
 
2146
                if (!prot && c != EBC_space && c != EBC_null)
 
2147
                        break;
 
2148
                DEC_BA(baddr);
 
2149
        } while (baddr != baddr0);
 
2150
 
 
2151
        if (baddr == baddr0)
 
2152
                return;
 
2153
 
 
2154
        /* Go it its front. */
 
2155
        for (;;) {
 
2156
                DEC_BA(baddr);
 
2157
                c = ea_buf[baddr].cc;
 
2158
                if (ea_buf[baddr].fa || c == EBC_space || c == EBC_null) {
 
2159
                        break;
 
2160
                }
 
2161
        }
 
2162
        INC_BA(baddr);
 
2163
        cursor_move(baddr);
 
2164
}
 
2165
 
 
2166
 
 
2167
/*
 
2168
 * Cursor right 2 positions.
 
2169
 */
 
2170
void
 
2171
Right2_action(Widget w _is_unused, XEvent *event, String *params,
 
2172
    Cardinal *num_params)
 
2173
{
 
2174
        register int    baddr;
 
2175
        enum dbcs_state d;
 
2176
 
 
2177
        action_debug(Right2_action, event, params, num_params);
 
2178
        reset_idle_timer();
 
2179
        if (kybdlock) {
 
2180
                if (KYBDLOCK_IS_OERR) {
 
2181
                        kybdlock_clr(KL_OERR_MASK, "Right2");
 
2182
                        status_reset();
 
2183
                } else {
 
2184
                        enq_ta(Right2_action, CN, CN);
 
2185
                        return;
 
2186
                }
 
2187
        }
 
2188
#if defined(X3270_ANSI) /*[*/
 
2189
        if (IN_ANSI)
 
2190
                return;
 
2191
#endif /*]*/
 
2192
        baddr = cursor_addr;
 
2193
        INC_BA(baddr);
 
2194
        d = ctlr_dbcs_state(baddr);
 
2195
        if (IS_RIGHT(d))
 
2196
                INC_BA(baddr);
 
2197
        INC_BA(baddr);
 
2198
        d = ctlr_dbcs_state(baddr);
 
2199
        if (IS_RIGHT(d))
 
2200
                INC_BA(baddr);
 
2201
        cursor_move(baddr);
 
2202
}
 
2203
 
 
2204
 
 
2205
/* Find the next unprotected word, or -1 */
 
2206
static int
 
2207
nu_word(int baddr)
 
2208
{
 
2209
        int baddr0 = baddr;
 
2210
        unsigned char c;
 
2211
        Boolean prot;
 
2212
 
 
2213
        prot = FA_IS_PROTECTED(get_field_attribute(baddr));
 
2214
 
 
2215
        do {
 
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)
 
2220
                        return baddr;
 
2221
                INC_BA(baddr);
 
2222
        } while (baddr != baddr0);
 
2223
 
 
2224
        return -1;
 
2225
}
 
2226
 
 
2227
/* Find the next word in this field, or -1 */
 
2228
static int
 
2229
nt_word(int baddr)
 
2230
{
 
2231
        int baddr0 = baddr;
 
2232
        unsigned char c;
 
2233
        Boolean in_word = True;
 
2234
 
 
2235
        do {
 
2236
                c = ea_buf[baddr].cc;
 
2237
                if (ea_buf[baddr].fa)
 
2238
                        return -1;
 
2239
                if (in_word) {
 
2240
                        if (c == EBC_space || c == EBC_null)
 
2241
                                in_word = False;
 
2242
                } else {
 
2243
                        if (c != EBC_space && c != EBC_null)
 
2244
                                return baddr;
 
2245
                }
 
2246
                INC_BA(baddr);
 
2247
        } while (baddr != baddr0);
 
2248
 
 
2249
        return -1;
 
2250
}
 
2251
 
 
2252
 
 
2253
/*
 
2254
 * Cursor to next unprotected word.
 
2255
 */
 
2256
void
 
2257
NextWord_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
 
2258
{
 
2259
        register int    baddr;
 
2260
        unsigned char c;
 
2261
 
 
2262
        action_debug(NextWord_action, event, params, num_params);
 
2263
        reset_idle_timer();
 
2264
        if (kybdlock) {
 
2265
                enq_ta(NextWord_action, CN, CN);
 
2266
                return;
 
2267
        }
 
2268
#if defined(X3270_ANSI) /*[*/
 
2269
        if (IN_ANSI)
 
2270
                return;
 
2271
#endif /*]*/
 
2272
        if (!formatted)
 
2273
                return;
 
2274
 
 
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);
 
2279
                if (baddr != -1)
 
2280
                        cursor_move(baddr);
 
2281
                return;
 
2282
        }
 
2283
 
 
2284
        /* If there's another word in this field, go to it. */
 
2285
        baddr = nt_word(cursor_addr);
 
2286
        if (baddr != -1) {
 
2287
                cursor_move(baddr);
 
2288
                return;
 
2289
        }
 
2290
 
 
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;
 
2295
                do {
 
2296
                        c = ea_buf[baddr].cc;
 
2297
                        if (c == EBC_space || c == EBC_null) {
 
2298
                                cursor_move(baddr);
 
2299
                                return;
 
2300
                        } else if (ea_buf[baddr].fa) {
 
2301
                                baddr = nu_word(baddr);
 
2302
                                if (baddr != -1)
 
2303
                                        cursor_move(baddr);
 
2304
                                return;
 
2305
                        }
 
2306
                        INC_BA(baddr);
 
2307
                } while (baddr != cursor_addr);
 
2308
        }
 
2309
        /* Otherwise, go to the next unprotected word. */
 
2310
        else {
 
2311
                baddr = nu_word(cursor_addr);
 
2312
                if (baddr != -1)
 
2313
                        cursor_move(baddr);
 
2314
        }
 
2315
}
 
2316
 
 
2317
 
 
2318
/*
 
2319
 * Cursor up 1 position.
 
2320
 */
 
2321
void
 
2322
Up_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
 
2323
{
 
2324
        register int    baddr;
 
2325
 
 
2326
        action_debug(Up_action, event, params, num_params);
 
2327
        reset_idle_timer();
 
2328
        if (kybdlock) {
 
2329
                if (KYBDLOCK_IS_OERR) {
 
2330
                        kybdlock_clr(KL_OERR_MASK, "Up");
 
2331
                        status_reset();
 
2332
                } else {
 
2333
                        enq_ta(Up_action, CN, CN);
 
2334
                        return;
 
2335
                }
 
2336
        }
 
2337
#if defined(X3270_ANSI) /*[*/
 
2338
        if (IN_ANSI) {
 
2339
                ansi_send_up();
 
2340
                return;
 
2341
        }
 
2342
#endif /*]*/
 
2343
        baddr = cursor_addr - COLS;
 
2344
        if (baddr < 0)
 
2345
                baddr = (cursor_addr + (ROWS * COLS)) - COLS;
 
2346
        cursor_move(baddr);
 
2347
}
 
2348
 
 
2349
 
 
2350
/*
 
2351
 * Cursor down 1 position.
 
2352
 */
 
2353
void
 
2354
Down_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
 
2355
{
 
2356
        register int    baddr;
 
2357
 
 
2358
        action_debug(Down_action, event, params, num_params);
 
2359
        reset_idle_timer();
 
2360
        if (kybdlock) {
 
2361
                if (KYBDLOCK_IS_OERR) {
 
2362
                        kybdlock_clr(KL_OERR_MASK, "Down");
 
2363
                        status_reset();
 
2364
                } else {
 
2365
                        enq_ta(Down_action, CN, CN);
 
2366
                        return;
 
2367
                }
 
2368
        }
 
2369
#if defined(X3270_ANSI) /*[*/
 
2370
        if (IN_ANSI) {
 
2371
                ansi_send_down();
 
2372
                return;
 
2373
        }
 
2374
#endif /*]*/
 
2375
        baddr = (cursor_addr + COLS) % (COLS * ROWS);
 
2376
        cursor_move(baddr);
 
2377
}
 
2378
 
 
2379
 
 
2380
/*
 
2381
 * Cursor to first field on next line or any lines after that.
 
2382
 */
 
2383
void
 
2384
Newline_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
 
2385
{
 
2386
        register int    baddr, faddr;
 
2387
        register unsigned char  fa;
 
2388
 
 
2389
        action_debug(Newline_action, event, params, num_params);
 
2390
        if (check_usage(Newline_action, *num_params, 0, 0) < 0)
 
2391
                return;
 
2392
        reset_idle_timer();
 
2393
        if (kybdlock) {
 
2394
                enq_ta(Newline_action, CN, CN);
 
2395
                return;
 
2396
        }
 
2397
#if defined(X3270_ANSI) /*[*/
 
2398
        if (IN_ANSI) {
 
2399
                net_sendc('\n');
 
2400
                return;
 
2401
        }
 
2402
#endif /*]*/
 
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))
 
2408
                cursor_move(baddr);
 
2409
        else
 
2410
                cursor_move(next_unprotected(baddr));
 
2411
}
 
2412
 
 
2413
 
 
2414
/*
 
2415
 * DUP key
 
2416
 */
 
2417
void
 
2418
Dup_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
 
2419
{
 
2420
        action_debug(Dup_action, event, params, num_params);
 
2421
        if (check_usage(Dup_action, *num_params, 0, 0) < 0)
 
2422
                return;
 
2423
        reset_idle_timer();
 
2424
        if (kybdlock) {
 
2425
                enq_ta(Dup_action, CN, CN);
 
2426
                return;
 
2427
        }
 
2428
#if defined(X3270_ANSI) /*[*/
 
2429
        if (IN_ANSI)
 
2430
                return;
 
2431
#endif /*]*/
 
2432
        if (key_Character(EBC_dup, False, False, NULL))
 
2433
                cursor_move(next_unprotected(cursor_addr));
 
2434
}
 
2435
 
 
2436
 
 
2437
/*
 
2438
 * FM key
 
2439
 */
 
2440
void
 
2441
FieldMark_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
 
2442
{
 
2443
        action_debug(FieldMark_action, event, params, num_params);
 
2444
        if (check_usage(FieldMark_action, *num_params, 0, 0) < 0)
 
2445
                return;
 
2446
        reset_idle_timer();
 
2447
        if (kybdlock) {
 
2448
                enq_ta(FieldMark_action, CN, CN);
 
2449
                return;
 
2450
        }
 
2451
#if defined(X3270_ANSI) /*[*/
 
2452
        if (IN_ANSI)
 
2453
                return;
 
2454
#endif /*]*/
 
2455
        (void) key_Character(EBC_fm, False, False, NULL);
 
2456
}
 
2457
 
 
2458
 
 
2459
/*
 
2460
 * Vanilla AID keys.
 
2461
 */
 
2462
void
 
2463
Enter_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
 
2464
{
 
2465
        action_debug(Enter_action, event, params, num_params);
 
2466
        if (check_usage(Enter_action, *num_params, 0, 0) < 0)
 
2467
                return;
 
2468
        reset_idle_timer();
 
2469
        if (kybdlock & KL_OIA_MINUS)
 
2470
                return;
 
2471
        else if (kybdlock)
 
2472
                enq_ta(Enter_action, CN, CN);
 
2473
        else
 
2474
                key_AID(AID_ENTER);
 
2475
}
 
2476
 
 
2477
 
 
2478
void
 
2479
SysReq_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
 
2480
{
 
2481
        action_debug(SysReq_action, event, params, num_params);
 
2482
        if (check_usage(SysReq_action, *num_params, 0, 0) < 0)
 
2483
                return;
 
2484
        reset_idle_timer();
 
2485
        if (IN_ANSI)
 
2486
                return;
 
2487
#if defined(X3270_TN3270E) /*[*/
 
2488
        if (IN_E) {
 
2489
                net_abort();
 
2490
        } else
 
2491
#endif /*]*/
 
2492
        {
 
2493
                if (kybdlock & KL_OIA_MINUS)
 
2494
                        return;
 
2495
                else if (kybdlock)
 
2496
                        enq_ta(SysReq_action, CN, CN);
 
2497
                else
 
2498
                        key_AID(AID_SYSREQ);
 
2499
        }
 
2500
}
 
2501
 
 
2502
 
 
2503
/*
 
2504
 * Clear AID key
 
2505
 */
 
2506
void
 
2507
Clear_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
 
2508
{
 
2509
        action_debug(Clear_action, event, params, num_params);
 
2510
        if (check_usage(Clear_action, *num_params, 0, 0) < 0)
 
2511
                return;
 
2512
        reset_idle_timer();
 
2513
        if (kybdlock & KL_OIA_MINUS)
 
2514
                return;
 
2515
        if (kybdlock && CONNECTED) {
 
2516
                enq_ta(Clear_action, CN, CN);
 
2517
                return;
 
2518
        }
 
2519
#if defined(X3270_ANSI) /*[*/
 
2520
        if (IN_ANSI) {
 
2521
                ansi_send_clear();
 
2522
                return;
 
2523
        }
 
2524
#endif /*]*/
 
2525
        buffer_addr = 0;
 
2526
        ctlr_clear(True);
 
2527
        cursor_move(0);
 
2528
        if (CONNECTED)
 
2529
                key_AID(AID_CLEAR);
 
2530
}
 
2531
 
 
2532
 
 
2533
/*
 
2534
 * Cursor Select key (light pen simulator).
 
2535
 */
 
2536
static void
 
2537
lightpen_select(int baddr)
 
2538
{
 
2539
        int faddr;
 
2540
        register unsigned char  fa;
 
2541
        int designator;
 
2542
#if defined(X3270_DBCS) /*[*/
 
2543
        int designator2;
 
2544
#endif /*]*/
 
2545
 
 
2546
        faddr = find_field_attribute(baddr);
 
2547
        fa = ea_buf[faddr].fa;
 
2548
        if (!FA_IS_SELECTABLE(fa)) {
 
2549
                ring_bell();
 
2550
                return;
 
2551
        }
 
2552
        designator = faddr;
 
2553
        INC_BA(designator);
 
2554
 
 
2555
#if defined(X3270_DBCS) /*[*/
 
2556
        if (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)) {
 
2564
                                ring_bell();
 
2565
                                return;
 
2566
                        }
 
2567
                        if (ea_buf[designator].cc == 0x42 &&
 
2568
                            ea_buf[designator2].cc == EBC_greater) {
 
2569
                                ctlr_add(designator2, EBC_question, CS_DBCS);
 
2570
                                mdt_clear(faddr);
 
2571
                        } else if (ea_buf[designator].cc == 0x42 &&
 
2572
                                   ea_buf[designator2].cc == EBC_question) {
 
2573
                                ctlr_add(designator2, EBC_greater, CS_DBCS);
 
2574
                                mdt_clear(faddr);
 
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);
 
2580
                                mdt_set(faddr);
 
2581
                                key_AID(AID_SELECT);
 
2582
                        } else if (ea_buf[designator].cc == 0x42 &&
 
2583
                                   ea_buf[designator2].cc == EBC_ampersand) {
 
2584
                                mdt_set(faddr);
 
2585
                                key_AID(AID_ENTER);
 
2586
                        } else {
 
2587
                                ring_bell();
 
2588
                        }
 
2589
                        return;
 
2590
                }
 
2591
        } 
 
2592
#endif /*]*/
 
2593
 
 
2594
        switch (ea_buf[designator].cc) {
 
2595
            case EBC_greater:           /* > */
 
2596
                ctlr_add(designator, EBC_question, 0); /* change to ? */
 
2597
                mdt_clear(faddr);
 
2598
                break;
 
2599
            case EBC_question:          /* ? */
 
2600
                ctlr_add(designator, EBC_greater, 0);   /* change to > */
 
2601
                mdt_set(faddr);
 
2602
                break;
 
2603
            case EBC_space:             /* space */
 
2604
            case EBC_null:              /* null */
 
2605
                mdt_set(faddr);
 
2606
                key_AID(AID_SELECT);
 
2607
                break;
 
2608
            case EBC_ampersand:         /* & */
 
2609
                mdt_set(faddr);
 
2610
                key_AID(AID_ENTER);
 
2611
                break;
 
2612
            default:
 
2613
                ring_bell();
 
2614
                break;
 
2615
        }
 
2616
}
 
2617
 
 
2618
/*
 
2619
 * Cursor Select key (light pen simulator) -- at the current cursor location.
 
2620
 */
 
2621
void
 
2622
CursorSelect_action(Widget w _is_unused, XEvent *event, String *params,
 
2623
    Cardinal *num_params)
 
2624
{
 
2625
        action_debug(CursorSelect_action, event, params, num_params);
 
2626
        if (check_usage(CursorSelect_action, *num_params, 0, 0) < 0)
 
2627
                return;
 
2628
        reset_idle_timer();
 
2629
        if (kybdlock) {
 
2630
                enq_ta(CursorSelect_action, CN, CN);
 
2631
                return;
 
2632
        }
 
2633
 
 
2634
#if defined(X3270_ANSI) /*[*/
 
2635
        if (IN_ANSI)
 
2636
                return;
 
2637
#endif /*]*/
 
2638
        lightpen_select(cursor_addr);
 
2639
}
 
2640
 
 
2641
#if defined(X3270_DISPLAY) /*[*/
 
2642
/*
 
2643
 * Cursor Select mouse action (light pen simulator).
 
2644
 */
 
2645
void
 
2646
MouseSelect_action(Widget w, XEvent *event, String *params,
 
2647
    Cardinal *num_params)
 
2648
{
 
2649
        action_debug(MouseSelect_action, event, params, num_params);
 
2650
        if (check_usage(MouseSelect_action, *num_params, 0, 0) < 0)
 
2651
                return;
 
2652
        if (w != *screen)
 
2653
                return;
 
2654
        reset_idle_timer();
 
2655
        if (kybdlock)
 
2656
                return;
 
2657
#if defined(X3270_ANSI) /*[*/
 
2658
        if (IN_ANSI)
 
2659
                return;
 
2660
#endif /*]*/
 
2661
        lightpen_select(mouse_baddr(w, event));
 
2662
}
 
2663
#endif /*]*/
 
2664
 
 
2665
 
 
2666
/*
 
2667
 * Erase End Of Field Key.
 
2668
 */
 
2669
void
 
2670
EraseEOF_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
 
2671
{
 
2672
        register int    baddr;
 
2673
        register unsigned char  fa;
 
2674
        enum dbcs_state d;
 
2675
        enum dbcs_why why = DBCS_FIELD;
 
2676
 
 
2677
        action_debug(EraseEOF_action, event, params, num_params);
 
2678
        if (check_usage(EraseEOF_action, *num_params, 0, 0) < 0)
 
2679
                return;
 
2680
        reset_idle_timer();
 
2681
        if (kybdlock) {
 
2682
                enq_ta(EraseEOF_action, CN, CN);
 
2683
                return;
 
2684
        }
 
2685
#if defined(X3270_ANSI) /*[*/
 
2686
        if (IN_ANSI)
 
2687
                return;
 
2688
#endif /*]*/
 
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);
 
2693
                return;
 
2694
        }
 
2695
        if (formatted) {        /* erase to next field attribute */
 
2696
                do {
 
2697
                        ctlr_add(baddr, EBC_null, 0);
 
2698
                        INC_BA(baddr);
 
2699
                } while (!ea_buf[baddr].fa);
 
2700
                mdt_set(cursor_addr);
 
2701
        } else {        /* erase to end of screen */
 
2702
                do {
 
2703
                        ctlr_add(baddr, EBC_null, 0);
 
2704
                        INC_BA(baddr);
 
2705
                } while (baddr != 0);
 
2706
        }
 
2707
 
 
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;
 
2713
                        DEC_BA(baddr);
 
2714
                        ea_buf[baddr].cc = EBC_si;
 
2715
                } else
 
2716
                        ea_buf[cursor_addr].cc = EBC_si;
 
2717
        }
 
2718
        (void) ctlr_dbcs_postprocess();
 
2719
}
 
2720
 
 
2721
 
 
2722
/*
 
2723
 * Erase all Input Key.
 
2724
 */
 
2725
void
 
2726
EraseInput_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
 
2727
{
 
2728
        register int    baddr, sbaddr;
 
2729
        unsigned char   fa;
 
2730
        Boolean         f;
 
2731
 
 
2732
        action_debug(EraseInput_action, event, params, num_params);
 
2733
        if (check_usage(EraseInput_action, *num_params, 0, 0) < 0)
 
2734
                return;
 
2735
        reset_idle_timer();
 
2736
        if (kybdlock) {
 
2737
                enq_ta(EraseInput_action, CN, CN);
 
2738
                return;
 
2739
        }
 
2740
#if defined(X3270_ANSI) /*[*/
 
2741
        if (IN_ANSI)
 
2742
                return;
 
2743
#endif /*]*/
 
2744
        if (formatted) {
 
2745
                /* find first field attribute */
 
2746
                baddr = 0;
 
2747
                do {
 
2748
                        if (ea_buf[baddr].fa)
 
2749
                                break;
 
2750
                        INC_BA(baddr);
 
2751
                } while (baddr != 0);
 
2752
                sbaddr = baddr;
 
2753
                f = False;
 
2754
                do {
 
2755
                        fa = ea_buf[baddr].fa;
 
2756
                        if (!FA_IS_PROTECTED(fa)) {
 
2757
                                mdt_clear(baddr);
 
2758
                                do {
 
2759
                                        INC_BA(baddr);
 
2760
                                        if (!f) {
 
2761
                                                cursor_move(baddr);
 
2762
                                                f = True;
 
2763
                                        }
 
2764
                                        if (!ea_buf[baddr].fa) {
 
2765
                                                ctlr_add(baddr, EBC_null, 0);
 
2766
                                        }
 
2767
                                } while (!ea_buf[baddr].fa);
 
2768
                        } else {        /* skip protected */
 
2769
                                do {
 
2770
                                        INC_BA(baddr);
 
2771
                                } while (!ea_buf[baddr].fa);
 
2772
                        }
 
2773
                } while (baddr != sbaddr);
 
2774
                if (!f)
 
2775
                        cursor_move(0);
 
2776
        } else {
 
2777
                ctlr_clear(True);
 
2778
                cursor_move(0);
 
2779
        }
 
2780
}
 
2781
 
 
2782
 
 
2783
 
 
2784
/*
 
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
 
2787
 * but the last.
 
2788
 *
 
2789
 * Which is to say, does a ^W.
 
2790
 */
 
2791
void
 
2792
DeleteWord_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
 
2793
{
 
2794
        register int baddr;
 
2795
        register unsigned char  fa;
 
2796
 
 
2797
        action_debug(DeleteWord_action, event, params, num_params);
 
2798
        if (check_usage(DeleteWord_action, *num_params, 0, 0) < 0)
 
2799
                return;
 
2800
        reset_idle_timer();
 
2801
        if (kybdlock) {
 
2802
                enq_ta(DeleteWord_action, CN, CN);
 
2803
                return;
 
2804
        }
 
2805
#if defined(X3270_ANSI) /*[*/
 
2806
        if (IN_ANSI) {
 
2807
                net_send_werase();
 
2808
                return;
 
2809
        }
 
2810
#endif /*]*/
 
2811
        if (!formatted)
 
2812
                return;
 
2813
 
 
2814
        baddr = cursor_addr;
 
2815
        fa = get_field_attribute(baddr);
 
2816
 
 
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);
 
2820
                return;
 
2821
        }
 
2822
 
 
2823
        /* Backspace over any spaces to the left of the cursor. */
 
2824
        for (;;) {
 
2825
                baddr = cursor_addr;
 
2826
                DEC_BA(baddr);
 
2827
                if (ea_buf[baddr].fa)
 
2828
                        return;
 
2829
                if (ea_buf[baddr].cc == EBC_null ||
 
2830
                    ea_buf[baddr].cc == EBC_space)
 
2831
                        do_erase();
 
2832
                else
 
2833
                        break;
 
2834
        }
 
2835
 
 
2836
        /* Backspace until the character to the left of the cursor is blank. */
 
2837
        for (;;) {
 
2838
                baddr = cursor_addr;
 
2839
                DEC_BA(baddr);
 
2840
                if (ea_buf[baddr].fa)
 
2841
                        return;
 
2842
                if (ea_buf[baddr].cc == EBC_null ||
 
2843
                    ea_buf[baddr].cc == EBC_space)
 
2844
                        break;
 
2845
                else
 
2846
                        do_erase();
 
2847
        }
 
2848
}
 
2849
 
 
2850
 
 
2851
 
 
2852
/*
 
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.
 
2856
 *
 
2857
 * Which is to say, does a ^U.
 
2858
 */
 
2859
void
 
2860
DeleteField_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
 
2861
{
 
2862
        register int    baddr;
 
2863
        register unsigned char  fa;
 
2864
 
 
2865
        action_debug(DeleteField_action, event, params, num_params);
 
2866
        if (check_usage(DeleteField_action, *num_params, 0, 0) < 0)
 
2867
                return;
 
2868
        reset_idle_timer();
 
2869
        if (kybdlock) {
 
2870
                enq_ta(DeleteField_action, CN, CN);
 
2871
                return;
 
2872
        }
 
2873
#if defined(X3270_ANSI) /*[*/
 
2874
        if (IN_ANSI) {
 
2875
                net_send_kill();
 
2876
                return;
 
2877
        }
 
2878
#endif /*]*/
 
2879
        if (!formatted)
 
2880
                return;
 
2881
 
 
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);
 
2886
                return;
 
2887
        }
 
2888
        while (!ea_buf[baddr].fa)
 
2889
                DEC_BA(baddr);
 
2890
        INC_BA(baddr);
 
2891
        mdt_set(cursor_addr);
 
2892
        cursor_move(baddr);
 
2893
        while (!ea_buf[baddr].fa) {
 
2894
                ctlr_add(baddr, EBC_null, 0);
 
2895
                INC_BA(baddr);
 
2896
        }
 
2897
}
 
2898
 
 
2899
 
 
2900
 
 
2901
/*
 
2902
 * Set insert mode key.
 
2903
 */
 
2904
void
 
2905
Insert_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
 
2906
{
 
2907
        action_debug(Insert_action, event, params, num_params);
 
2908
        if (check_usage(Insert_action, *num_params, 0, 0) < 0)
 
2909
                return;
 
2910
        reset_idle_timer();
 
2911
        if (kybdlock) {
 
2912
                enq_ta(Insert_action, CN, CN);
 
2913
                return;
 
2914
        }
 
2915
#if defined(X3270_ANSI) /*[*/
 
2916
        if (IN_ANSI)
 
2917
                return;
 
2918
#endif /*]*/
 
2919
        insert_mode(True);
 
2920
}
 
2921
 
 
2922
 
 
2923
/*
 
2924
 * Toggle insert mode key.
 
2925
 */
 
2926
void
 
2927
ToggleInsert_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
 
2928
{
 
2929
        action_debug(ToggleInsert_action, event, params, num_params);
 
2930
        if (check_usage(ToggleInsert_action, *num_params, 0, 0) < 0)
 
2931
                return;
 
2932
        reset_idle_timer();
 
2933
        if (kybdlock) {
 
2934
                enq_ta(ToggleInsert_action, CN, CN);
 
2935
                return;
 
2936
        }
 
2937
#if defined(X3270_ANSI) /*[*/
 
2938
        if (IN_ANSI)
 
2939
                return;
 
2940
#endif /*]*/
 
2941
        if (insert)
 
2942
                insert_mode(False);
 
2943
        else
 
2944
                insert_mode(True);
 
2945
}
 
2946
 
 
2947
 
 
2948
/*
 
2949
 * Toggle reverse mode key.
 
2950
 */
 
2951
void
 
2952
ToggleReverse_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
 
2953
{
 
2954
        action_debug(ToggleReverse_action, event, params, num_params);
 
2955
        if (check_usage(ToggleReverse_action, *num_params, 0, 0) < 0)
 
2956
                return;
 
2957
        reset_idle_timer();
 
2958
        if (kybdlock) {
 
2959
                enq_ta(ToggleReverse_action, CN, CN);
 
2960
                return;
 
2961
        }
 
2962
#if defined(X3270_ANSI) /*[*/
 
2963
        if (IN_ANSI)
 
2964
                return;
 
2965
#endif /*]*/
 
2966
        reverse_mode(!reverse);
 
2967
}
 
2968
 
 
2969
 
 
2970
/*
 
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.
 
2973
 */
 
2974
void
 
2975
FieldEnd_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
 
2976
{
 
2977
        int     baddr, faddr;
 
2978
        unsigned char   fa, c;
 
2979
        int     last_nonblank = -1;
 
2980
 
 
2981
        action_debug(FieldEnd_action, event, params, num_params);
 
2982
        if (check_usage(FieldEnd_action, *num_params, 0, 0) < 0)
 
2983
                return;
 
2984
        reset_idle_timer();
 
2985
        if (kybdlock) {
 
2986
                enq_ta(FieldEnd_action, CN, CN);
 
2987
                return;
 
2988
        }
 
2989
#if defined(X3270_ANSI) /*[*/
 
2990
        if (IN_ANSI)
 
2991
                return;
 
2992
#endif /*]*/
 
2993
        if (!formatted)
 
2994
                return;
 
2995
        baddr = cursor_addr;
 
2996
        faddr = find_field_attribute(baddr);
 
2997
        fa = ea_buf[faddr].fa;
 
2998
        if (faddr == baddr || FA_IS_PROTECTED(fa))
 
2999
                return;
 
3000
 
 
3001
        baddr = faddr;
 
3002
        while (True) {
 
3003
                INC_BA(baddr);
 
3004
                c = ea_buf[baddr].cc;
 
3005
                if (ea_buf[baddr].fa)
 
3006
                        break;
 
3007
                if (c != EBC_null && c != EBC_space)
 
3008
                        last_nonblank = baddr;
 
3009
        }
 
3010
 
 
3011
        if (last_nonblank == -1) {
 
3012
                baddr = faddr;
 
3013
                INC_BA(baddr);
 
3014
        } else {
 
3015
                baddr = last_nonblank;
 
3016
                INC_BA(baddr);
 
3017
                if (ea_buf[baddr].fa)
 
3018
                        baddr = last_nonblank;
 
3019
        }
 
3020
        cursor_move(baddr);
 
3021
}
 
3022
 
 
3023
/*
 
3024
 * MoveCursor action.  Depending on arguments, this is either a move to the
 
3025
 * mouse cursor position, or to an absolute location.
 
3026
 */
 
3027
void
 
3028
MoveCursor_action(Widget w, XEvent *event, String *params, Cardinal *num_params)
 
3029
{
 
3030
        register int baddr;
 
3031
        int row, col;
 
3032
 
 
3033
        action_debug(MoveCursor_action, event, params, num_params);
 
3034
 
 
3035
        reset_idle_timer();
 
3036
        if (kybdlock) {
 
3037
                if (*num_params == 2)
 
3038
                        enq_ta(MoveCursor_action, params[0], params[1]);
 
3039
                return;
 
3040
        }
 
3041
 
 
3042
        switch (*num_params) {
 
3043
#if defined(X3270_DISPLAY) /*[*/
 
3044
            case 0:             /* mouse click, presumably */
 
3045
                if (w != *screen)
 
3046
                        return;
 
3047
                cursor_move(mouse_baddr(w, event));
 
3048
                break;
 
3049
#endif /*]*/
 
3050
            case 2:             /* probably a macro call */
 
3051
                row = atoi(params[0]);
 
3052
                col = atoi(params[1]);
 
3053
                if (!IN_3270) {
 
3054
                        row--;
 
3055
                        col--;
 
3056
                }
 
3057
                if (row < 0)
 
3058
                        row = 0;
 
3059
                if (col < 0)
 
3060
                        col = 0;
 
3061
                baddr = ((row * COLS) + col) % (ROWS * COLS);
 
3062
                cursor_move(baddr);
 
3063
                break;
 
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();
 
3068
                break;
 
3069
        }
 
3070
}
 
3071
 
 
3072
 
 
3073
#if defined(X3270_DBCS) && defined(X3270_DISPLAY) /*[*/
 
3074
/*
 
3075
 * Run a KeyPress through XIM.
 
3076
 * Returns True if there is further processing to do, False otherwise.
 
3077
 */
 
3078
static Boolean
 
3079
xim_lookup(XKeyEvent *event)
 
3080
{
 
3081
        static char *buf = NULL;
 
3082
        static int buf_len = 0, rlen;
 
3083
        KeySym k;
 
3084
        Status status;
 
3085
        extern XIC ic;
 
3086
        int i;
 
3087
        Boolean rv = False;
 
3088
#define BASE_BUFSIZE 50
 
3089
 
 
3090
        if (ic == NULL)
 
3091
                return True;
 
3092
 
 
3093
        if (buf == NULL) {
 
3094
                buf_len = BASE_BUFSIZE;
 
3095
                buf = Malloc(buf_len);
 
3096
        }
 
3097
 
 
3098
        for (;;) {
 
3099
                memset(buf, '\0', buf_len);
 
3100
                rlen = XmbLookupString(ic, event, buf, buf_len - 1, &k,
 
3101
                                        &status);
 
3102
                if (status != XBufferOverflow)
 
3103
                        break;
 
3104
                buf_len += BASE_BUFSIZE;
 
3105
                buf = Realloc(buf, buf_len);
 
3106
        }
 
3107
 
 
3108
        switch (status) {
 
3109
        case XLookupNone:
 
3110
                rv = False;
 
3111
                break;
 
3112
        case XLookupKeySym:
 
3113
                rv = True;
 
3114
                break;
 
3115
        case XLookupChars:
 
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);
 
3119
                }
 
3120
                trace_event("\n");
 
3121
                buf[rlen] = '\0';
 
3122
                key_ACharacter(buf, KT_STD, ia_cause, NULL);
 
3123
                rv = False;
 
3124
                break;
 
3125
        case XLookupBoth:
 
3126
                rv = True;
 
3127
                break;
 
3128
        }
 
3129
        return rv;
 
3130
}
 
3131
#endif /*]*/
 
3132
 
 
3133
 
 
3134
/*
 
3135
 * Key action.
 
3136
 */
 
3137
void
 
3138
Key_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
 
3139
{
 
3140
        Cardinal i;
 
3141
        KeySym k;
 
3142
        enum keytype keytype;
 
3143
        ucs4_t ucs4;
 
3144
 
 
3145
        action_debug(Key_action, event, params, num_params);
 
3146
        reset_idle_timer();
 
3147
 
 
3148
        for (i = 0; i < *num_params; i++) {
 
3149
                char *s = params[i];
 
3150
 
 
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();
 
3156
                        continue;
 
3157
                }
 
3158
                if (k & ~0xff) {
 
3159
                        /*
 
3160
                         * Can't pass symbolic KeySyms that aren't in the
 
3161
                         * range 0x01..0xff.
 
3162
                         */
 
3163
                        popup_an_error("%s: Invalid KeySym: %s",
 
3164
                            action_name(Key_action), s);
 
3165
                        cancel_if_idle_command();
 
3166
                        continue;
 
3167
                }
 
3168
                if (k != NoSymbol)
 
3169
                        key_UCharacter(k, keytype, IA_KEY, NULL);
 
3170
                else
 
3171
                        key_UCharacter(ucs4, keytype, IA_KEY, NULL);
 
3172
        }
 
3173
}
 
3174
 
 
3175
/*
 
3176
 * String action.
 
3177
 */
 
3178
void
 
3179
String_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
 
3180
{
 
3181
        Cardinal i;
 
3182
        int len = 0;
 
3183
        char *s;
 
3184
 
 
3185
        action_debug(String_action, event, params, num_params);
 
3186
        reset_idle_timer();
 
3187
 
 
3188
        /* Determine the total length of the strings. */
 
3189
        for (i = 0; i < *num_params; i++)
 
3190
                len += strlen(params[i]);
 
3191
        if (!len)
 
3192
                return;
 
3193
 
 
3194
        /* Allocate a block of memory and copy them in. */
 
3195
        s = Malloc(len + 1);
 
3196
        s[0] = '\0';
 
3197
        for (i = 0; i < *num_params; i++) {
 
3198
                strcat(s, params[i]);
 
3199
        }
 
3200
 
 
3201
        /* Set a pending string. */
 
3202
        ps_set(s, False);
 
3203
        Free(s);
 
3204
}
 
3205
 
 
3206
/*
 
3207
 * HexString action.
 
3208
 */
 
3209
void
 
3210
HexString_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
 
3211
{
 
3212
        Cardinal i;
 
3213
        int len = 0;
 
3214
        char *s;
 
3215
        char *t;
 
3216
 
 
3217
        action_debug(HexString_action, event, params, num_params);
 
3218
        reset_idle_timer();
 
3219
 
 
3220
        /* Determine the total length of the strings. */
 
3221
        for (i = 0; i < *num_params; i++) {
 
3222
                t = params[i];
 
3223
                if (!strncmp(t, "0x", 2) || !strncmp(t, "0X", 2))
 
3224
                        t += 2;
 
3225
                len += strlen(t);
 
3226
        }
 
3227
        if (!len)
 
3228
                return;
 
3229
 
 
3230
        /* Allocate a block of memory and copy them in. */
 
3231
        s = Malloc(len + 1);
 
3232
        *s = '\0';
 
3233
        for (i = 0; i < *num_params; i++) {
 
3234
                t = params[i];
 
3235
                if (!strncmp(t, "0x", 2) || !strncmp(t, "0X", 2))
 
3236
                        t += 2;
 
3237
                (void) strcat(s, t);
 
3238
        }
 
3239
 
 
3240
        /* Set a pending string. */
 
3241
        ps_set(s, True);
 
3242
}
 
3243
 
 
3244
/*
 
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.
 
3250
 */
 
3251
void
 
3252
CircumNot_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
 
3253
{
 
3254
        action_debug(CircumNot_action, event, params, num_params);
 
3255
        if (check_usage(CircumNot_action, *num_params, 0, 0) < 0)
 
3256
                return;
 
3257
        reset_idle_timer();
 
3258
 
 
3259
        if (IN_3270 && composing == NONE)
 
3260
                key_UCharacter(0xac, KT_STD, IA_KEY, NULL);
 
3261
        else
 
3262
                key_UCharacter('^', KT_STD, IA_KEY, NULL);
 
3263
}
 
3264
 
 
3265
/* PA key action for String actions */
 
3266
static void
 
3267
do_pa(unsigned n)
 
3268
{
 
3269
        if (n < 1 || n > PA_SZ) {
 
3270
                popup_an_error("Unknown PA key %d", n);
 
3271
                cancel_if_idle_command();
 
3272
                return;
 
3273
        }
 
3274
        if (kybdlock) {
 
3275
                char nn[3];
 
3276
 
 
3277
                (void) sprintf(nn, "%d", n);
 
3278
                enq_ta(PA_action, nn, CN);
 
3279
                return;
 
3280
        }
 
3281
        key_AID(pa_xlate[n-1]);
 
3282
}
 
3283
 
 
3284
/* PF key action for String actions */
 
3285
static void
 
3286
do_pf(unsigned n)
 
3287
{
 
3288
        if (n < 1 || n > PF_SZ) {
 
3289
                popup_an_error("Unknown PF key %d", n);
 
3290
                cancel_if_idle_command();
 
3291
                return;
 
3292
        }
 
3293
        if (kybdlock) {
 
3294
                char nn[3];
 
3295
 
 
3296
                (void) sprintf(nn, "%d", n);
 
3297
                enq_ta(PF_action, nn, CN);
 
3298
                return;
 
3299
        }
 
3300
        key_AID(pf_xlate[n-1]);
 
3301
}
 
3302
 
 
3303
/*
 
3304
 * Set or clear the keyboard scroll lock.
 
3305
 */
 
3306
void
 
3307
kybd_scroll_lock(Boolean lock)
 
3308
{
 
3309
        if (!IN_3270)
 
3310
                return;
 
3311
        if (lock)
 
3312
                kybdlock_set(KL_SCROLLED, "kybd_scroll_lock");
 
3313
        else
 
3314
                kybdlock_clr(KL_SCROLLED, "kybd_scroll_lock");
 
3315
}
 
3316
 
 
3317
/*
 
3318
 * Move the cursor back within the legal paste area.
 
3319
 * Returns a Boolean indicating success.
 
3320
 */
 
3321
static Boolean
 
3322
remargin(int lmargin)
 
3323
{
 
3324
        Boolean ever = False;
 
3325
        int baddr, b0 = 0;
 
3326
        int faddr;
 
3327
        unsigned char fa;
 
3328
 
 
3329
        baddr = cursor_addr;
 
3330
        while (BA_TO_COL(baddr) < lmargin) {
 
3331
                baddr = ROWCOL_TO_BA(BA_TO_ROW(baddr), lmargin);
 
3332
                if (!ever) {
 
3333
                        b0 = baddr;
 
3334
                        ever = True;
 
3335
                }
 
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);
 
3340
                        if (baddr <= b0)
 
3341
                                return False;
 
3342
                }
 
3343
        }
 
3344
 
 
3345
        cursor_move(baddr);
 
3346
        return True;
 
3347
}
 
3348
 
 
3349
/*
 
3350
 * Pretend that a sequence of keys was entered at the keyboard.
 
3351
 *
 
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.
 
3356
 *
 
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.
 
3361
 *
 
3362
 * Returns the number of unprocessed characters.
 
3363
 */
 
3364
int
 
3365
emulate_uinput(ucs4_t *ws, int xlen, Boolean pasting)
 
3366
{
 
3367
        enum {
 
3368
            BASE, BACKSLASH, BACKX, BACKE, BACKP, BACKPA, BACKPF, OCTAL,
 
3369
            HEX, EBC, XGE
 
3370
        } state = BASE;
 
3371
        int literal = 0;
 
3372
        int nc = 0;
 
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;
 
3377
        ucs4_t c;
 
3378
 
 
3379
        /*
 
3380
         * In the switch statements below, "break" generally means "consume
 
3381
         * this character," while "continue" means "rescan this character."
 
3382
         */
 
3383
        while (xlen) {
 
3384
 
 
3385
                /*
 
3386
                 * It isn't possible to unlock the keyboard from a string,
 
3387
                 * so if the keyboard is locked, it's fatal
 
3388
                 */
 
3389
                if (kybdlock) {
 
3390
                        trace_event("  keyboard locked, string dropped\n");
 
3391
                        return 0;
 
3392
                }
 
3393
 
 
3394
                if (pasting && IN_3270) {
 
3395
 
 
3396
                        /* Check for cursor wrap to top of screen. */
 
3397
                        if (cursor_addr < orig_addr)
 
3398
                                return xlen-1;          /* wrapped */
 
3399
 
 
3400
                        /* Jump cursor over left margin. */
 
3401
                        if (toggled(MARGINED_PASTE) &&
 
3402
                            BA_TO_COL(cursor_addr) < orig_col) {
 
3403
                                if (!remargin(orig_col))
 
3404
                                        return xlen-1;
 
3405
                                skipped = True;
 
3406
                        }
 
3407
                }
 
3408
 
 
3409
                c = *ws;
 
3410
 
 
3411
                switch (state) {
 
3412
                    case BASE:
 
3413
                        switch (c) {
 
3414
                            case '\b':
 
3415
                                action_internal(Left_action, ia, CN, CN);
 
3416
                                skipped = False;
 
3417
                                break;
 
3418
                            case '\f':
 
3419
                                if (pasting) {
 
3420
                                        key_UCharacter(' ', KT_STD, ia,
 
3421
                                                &skipped);
 
3422
                                } else {
 
3423
                                        action_internal(Clear_action, ia, CN,
 
3424
                                                        CN);
 
3425
                                        skipped = False;
 
3426
                                        if (IN_3270)
 
3427
                                                return xlen-1;
 
3428
                                }
 
3429
                                break;
 
3430
                            case '\n':
 
3431
                                if (pasting) {
 
3432
                                        if (!skipped)
 
3433
                                                action_internal(Newline_action,
 
3434
                                                                ia, CN, CN);
 
3435
                                        skipped = False;
 
3436
                                } else {
 
3437
                                        action_internal(Enter_action, ia, CN,
 
3438
                                                        CN);
 
3439
                                        skipped = False;
 
3440
                                        if (IN_3270)
 
3441
                                                return xlen-1;
 
3442
                                }
 
3443
                                break;
 
3444
                            case '\r':
 
3445
                                if (!pasting) {
 
3446
                                        action_internal(Newline_action, ia, CN,
 
3447
                                                        CN);
 
3448
                                        skipped = False;
 
3449
                                }
 
3450
                                break;
 
3451
                            case '\t':
 
3452
                                action_internal(Tab_action, ia, CN, CN);
 
3453
                                skipped = False;
 
3454
                                break;
 
3455
                            case '\\':  /* backslashes are NOT special when
 
3456
                                           pasting */
 
3457
                                if (!pasting)
 
3458
                                        state = BACKSLASH;
 
3459
                                else
 
3460
                                        key_UCharacter((unsigned char)c,
 
3461
                                                KT_STD, ia, &skipped);
 
3462
                                break;
 
3463
                            case '\033': /* ESC is special only when pasting */
 
3464
                                if (pasting)
 
3465
                                        state = XGE;
 
3466
                                break;
 
3467
                            case '[':   /* APL left bracket */
 
3468
                                if (pasting && appres.apl_mode)
 
3469
                                        key_UCharacter(XK_Yacute, KT_GE, ia,
 
3470
                                                &skipped);
 
3471
                                else
 
3472
                                        key_UCharacter((unsigned char)c,
 
3473
                                                KT_STD, ia, &skipped);
 
3474
                                break;
 
3475
                            case ']':   /* APL right bracket */
 
3476
                                if (pasting && appres.apl_mode)
 
3477
                                        key_UCharacter(XK_diaeresis, KT_GE, ia,
 
3478
                                                &skipped);
 
3479
                                else
 
3480
                                        key_UCharacter((unsigned char)c,
 
3481
                                                KT_STD, ia,
 
3482
                                                &skipped);
 
3483
                                break;
 
3484
                            case UPRIV_fm: /* private-use FM */
 
3485
                                if (pasting)
 
3486
                                        key_Character(EBC_fm, False, True,
 
3487
                                                &skipped);
 
3488
                                break;
 
3489
                            case UPRIV_dup: /* private-use DUP */
 
3490
                                if (pasting)
 
3491
                                        key_Character(EBC_dup, False, True,
 
3492
                                                &skipped);
 
3493
                                break;
 
3494
                            case UPRIV_eo: /* private-use EO */
 
3495
                                if (pasting)
 
3496
                                        key_Character(EBC_eo, False, True,
 
3497
                                                &skipped);
 
3498
                                break;
 
3499
                            case UPRIV_sub: /* private-use SUB */
 
3500
                                if (pasting)
 
3501
                                        key_Character(EBC_sub, False, True,
 
3502
                                                &skipped);
 
3503
                                break;
 
3504
                        default:
 
3505
                                if (pasting &&
 
3506
                                        (c >= UPRIV_GE_00 &&
 
3507
                                         c <= UPRIV_GE_ff))
 
3508
                                        key_Character(c - UPRIV_GE_00, KT_GE,
 
3509
                                                ia, &skipped);
 
3510
                                else
 
3511
                                        key_UCharacter(c, KT_STD, ia,
 
3512
                                                &skipped);
 
3513
                                break;
 
3514
                        }
 
3515
                        break;
 
3516
                    case BACKSLASH:     /* last character was a backslash */
 
3517
                        switch (c) {
 
3518
                            case 'a':
 
3519
                                popup_an_error("%s: Bell not supported",
 
3520
                                    action_name(String_action));
 
3521
                                cancel_if_idle_command();
 
3522
                                state = BASE;
 
3523
                                break;
 
3524
                            case 'b':
 
3525
                                action_internal(Left_action, ia, CN, CN);
 
3526
                                skipped = False;
 
3527
                                state = BASE;
 
3528
                                break;
 
3529
                            case 'f':
 
3530
                                action_internal(Clear_action, ia, CN, CN);
 
3531
                                skipped = False;
 
3532
                                state = BASE;
 
3533
                                if (IN_3270)
 
3534
                                        return xlen-1;
 
3535
                                else
 
3536
                                        break;
 
3537
                            case 'n':
 
3538
                                action_internal(Enter_action, ia, CN, CN);
 
3539
                                skipped = False;
 
3540
                                state = BASE;
 
3541
                                if (IN_3270)
 
3542
                                        return xlen-1;
 
3543
                                else
 
3544
                                        break;
 
3545
                            case 'p':
 
3546
                                state = BACKP;
 
3547
                                break;
 
3548
                            case 'r':
 
3549
                                action_internal(Newline_action, ia, CN, CN);
 
3550
                                skipped = False;
 
3551
                                state = BASE;
 
3552
                                break;
 
3553
                            case 't':
 
3554
                                action_internal(Tab_action, ia, CN, CN);
 
3555
                                skipped = False;
 
3556
                                state = BASE;
 
3557
                                break;
 
3558
                            case 'T':
 
3559
                                action_internal(BackTab_action, ia, CN, CN);
 
3560
                                skipped = False;
 
3561
                                state = BASE;
 
3562
                                break;
 
3563
                            case 'v':
 
3564
                                popup_an_error("%s: Vertical tab not supported",
 
3565
                                    action_name(String_action));
 
3566
                                cancel_if_idle_command();
 
3567
                                state = BASE;
 
3568
                                break;
 
3569
                            case 'u':
 
3570
                            case 'x':
 
3571
                                state = BACKX;
 
3572
                                break;
 
3573
                            case 'e':
 
3574
                                state = BACKE;
 
3575
                                break;
 
3576
                            case '\\':
 
3577
                                key_UCharacter((unsigned char) c, KT_STD, ia,
 
3578
                                                &skipped);
 
3579
                                state = BASE;
 
3580
                                break;
 
3581
                            case '0': 
 
3582
                            case '1': 
 
3583
                            case '2': 
 
3584
                            case '3':
 
3585
                            case '4': 
 
3586
                            case '5': 
 
3587
                            case '6': 
 
3588
                            case '7':
 
3589
                                state = OCTAL;
 
3590
                                literal = 0;
 
3591
                                nc = 0;
 
3592
                                continue;
 
3593
                        default:
 
3594
                                state = BASE;
 
3595
                                continue;
 
3596
                        }
 
3597
                        break;
 
3598
                    case BACKP: /* last two characters were "\p" */
 
3599
                        switch (c) {
 
3600
                            case 'a':
 
3601
                                literal = 0;
 
3602
                                nc = 0;
 
3603
                                state = BACKPA;
 
3604
                                break;
 
3605
                            case 'f':
 
3606
                                literal = 0;
 
3607
                                nc = 0;
 
3608
                                state = BACKPF;
 
3609
                                break;
 
3610
                            default:
 
3611
                                popup_an_error("%s: Unknown character "
 
3612
                                                "after \\p",
 
3613
                                    action_name(String_action));
 
3614
                                cancel_if_idle_command();
 
3615
                                state = BASE;
 
3616
                                break;
 
3617
                        }
 
3618
                        break;
 
3619
                    case BACKPF: /* last three characters were "\pf" */
 
3620
                        if (nc < 2 && isdigit(c)) {
 
3621
                                literal = (literal * 10) + (c - '0');
 
3622
                                nc++;
 
3623
                        } else if (!nc) {
 
3624
                                popup_an_error("%s: Unknown character "
 
3625
                                                "after \\pf",
 
3626
                                    action_name(String_action));
 
3627
                                cancel_if_idle_command();
 
3628
                                state = BASE;
 
3629
                        } else {
 
3630
                                do_pf(literal);
 
3631
                                skipped = False;
 
3632
                                if (IN_3270) {
 
3633
                                        return xlen;
 
3634
                                }
 
3635
                                state = BASE;
 
3636
                                continue;
 
3637
                        }
 
3638
                        break;
 
3639
                    case BACKPA: /* last three characters were "\pa" */
 
3640
                        if (nc < 1 && isdigit(c)) {
 
3641
                                literal = (literal * 10) + (c - '0');
 
3642
                                nc++;
 
3643
                        } else if (!nc) {
 
3644
                                popup_an_error("%s: Unknown character "
 
3645
                                                "after \\pa",
 
3646
                                    action_name(String_action));
 
3647
                                cancel_if_idle_command();
 
3648
                                state = BASE;
 
3649
                        } else {
 
3650
                                do_pa(literal);
 
3651
                                skipped = False;
 
3652
                                if (IN_3270)
 
3653
                                        return xlen-1;
 
3654
                                state = BASE;
 
3655
                                continue;
 
3656
                        }
 
3657
                        break;
 
3658
                    case BACKX: /* last two characters were "\x" or "\u" */
 
3659
                        if (isxdigit(c)) {
 
3660
                                state = HEX;
 
3661
                                literal = 0;
 
3662
                                nc = 0;
 
3663
                                continue;
 
3664
                        } else {
 
3665
                                popup_an_error("%s: Missing hex digits after \\x",
 
3666
                                    action_name(String_action));
 
3667
                                cancel_if_idle_command();
 
3668
                                state = BASE;
 
3669
                                continue;
 
3670
                        }
 
3671
                    case BACKE: /* last two characters were "\e" */
 
3672
                        if (isxdigit(c)) {
 
3673
                                state = EBC;
 
3674
                                literal = 0;
 
3675
                                nc = 0;
 
3676
                                continue;
 
3677
                        } else {
 
3678
                                popup_an_error("%s: Missing hex digits after \\e",
 
3679
                                    action_name(String_action));
 
3680
                                cancel_if_idle_command();
 
3681
                                state = BASE;
 
3682
                                continue;
 
3683
                        }
 
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);
 
3687
                                nc++;
 
3688
                                break;
 
3689
                        } else {
 
3690
                                key_UCharacter((unsigned char) literal, KT_STD,
 
3691
                                    ia, &skipped);
 
3692
                                state = BASE;
 
3693
                                continue;
 
3694
                        }
 
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);
 
3698
                                nc++;
 
3699
                                break;
 
3700
                        } else {
 
3701
                                key_UCharacter((unsigned char) literal, KT_STD,
 
3702
                                    ia, &skipped);
 
3703
                                state = BASE;
 
3704
                                continue;
 
3705
                        }
 
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);
 
3709
                                nc++;
 
3710
                                break;
 
3711
                        } else {
 
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);
 
3717
                                else {
 
3718
#if defined(X3270_DBCS) /*[*/
 
3719
                                        unsigned char code[2];
 
3720
 
 
3721
                                        code[0] = (literal >> 8) & 0xff;
 
3722
                                        code[1] = literal & 0xff;
 
3723
                                        key_WCharacter(code, &skipped);
 
3724
#else /*][*/
 
3725
                                        popup_an_error("%s: EBCDIC code > 255",
 
3726
                                            action_name(String_action));
 
3727
                                        cancel_if_idle_command();
 
3728
#endif /*]*/
 
3729
                                }
 
3730
                                state = BASE;
 
3731
                                continue;
 
3732
                        }
 
3733
                    case XGE:   /* have seen ESC */
 
3734
                        switch (c) {
 
3735
                            case ';':   /* FM */
 
3736
                                key_Character(EBC_fm, False, True, &skipped);
 
3737
                                break;
 
3738
                            case '*':   /* DUP */
 
3739
                                key_Character(EBC_dup, False, True, &skipped);
 
3740
                                break;
 
3741
                            default:
 
3742
                                key_UCharacter((unsigned char) c, KT_GE, ia,
 
3743
                                                &skipped);
 
3744
                                break;
 
3745
                        }
 
3746
                        state = BASE;
 
3747
                        break;
 
3748
                }
 
3749
                ws++;
 
3750
                xlen--;
 
3751
        }
 
3752
 
 
3753
        switch (state) {
 
3754
            case BASE:
 
3755
                if (toggled(MARGINED_PASTE) &&
 
3756
                    BA_TO_COL(cursor_addr) < orig_col) {
 
3757
                        (void) remargin(orig_col);
 
3758
                }
 
3759
                break;
 
3760
            case OCTAL:
 
3761
            case HEX:
 
3762
                key_UCharacter((unsigned char) literal, KT_STD, ia, &skipped);
 
3763
                state = BASE;
 
3764
                if (toggled(MARGINED_PASTE) &&
 
3765
                    BA_TO_COL(cursor_addr) < orig_col) {
 
3766
                        (void) remargin(orig_col);
 
3767
                }
 
3768
                break;
 
3769
            case EBC:
 
3770
                /* XXX: line below added after 3.3.7p7 */
 
3771
                trace_event(" %s -> Key(X'%02X')\n", ia_name[(int) ia],
 
3772
                        literal);
 
3773
                key_Character((unsigned char) literal, False, True, &skipped);
 
3774
                state = BASE;
 
3775
                if (toggled(MARGINED_PASTE) &&
 
3776
                    BA_TO_COL(cursor_addr) < orig_col) {
 
3777
                        (void) remargin(orig_col);
 
3778
                }
 
3779
                break;
 
3780
            case BACKPF:
 
3781
                if (nc > 0) {
 
3782
                        do_pf(literal);
 
3783
                        state = BASE;
 
3784
                }
 
3785
                break;
 
3786
            case BACKPA:
 
3787
                if (nc > 0) {
 
3788
                        do_pa(literal);
 
3789
                        state = BASE;
 
3790
                }
 
3791
                break;
 
3792
            default:
 
3793
                popup_an_error("%s: Missing data after \\",
 
3794
                    action_name(String_action));
 
3795
                cancel_if_idle_command();
 
3796
                break;
 
3797
        }
 
3798
 
 
3799
        return xlen;
 
3800
}
 
3801
 
 
3802
/* Multibyte version of emulate_uinput. */
 
3803
int
 
3804
emulate_input(char *s, int len, Boolean pasting)
 
3805
{
 
3806
        static ucs4_t *w_ibuf = NULL;
 
3807
        static size_t w_ibuf_len = 0;
 
3808
        int xlen;
 
3809
 
 
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));
 
3814
        }
 
3815
        xlen = multibyte_to_unicode_string(s, len, w_ibuf, w_ibuf_len);
 
3816
        if (xlen < 0) {
 
3817
                return 0; /* failed */
 
3818
        }
 
3819
 
 
3820
        /* Process it as Unicode. */
 
3821
        return emulate_uinput(w_ibuf, xlen, pasting);
 
3822
}
 
3823
 
 
3824
/*
 
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.
 
3829
 *
 
3830
 * Graphic Escapes are handled as \E.
 
3831
 */
 
3832
void
 
3833
hex_input(char *s)
 
3834
{
 
3835
        char *t;
 
3836
        Boolean escaped;
 
3837
#if defined(X3270_ANSI) /*[*/
 
3838
        unsigned char *xbuf = (unsigned char *)NULL;
 
3839
        unsigned char *tbuf = (unsigned char *)NULL;
 
3840
        int nbytes = 0;
 
3841
#endif /*]*/
 
3842
 
 
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();
 
3848
                return;
 
3849
        }
 
3850
        t = s;
 
3851
        escaped = False;
 
3852
        while (*t) {
 
3853
                if (isxdigit(*t) && isxdigit(*(t + 1))) {
 
3854
                        escaped = False;
 
3855
#if defined(X3270_ANSI) /*[*/
 
3856
                        nbytes++;
 
3857
#endif /*]*/
 
3858
                } else if (!strncmp(t, "\\E", 2) || !strncmp(t, "\\e", 2)) {
 
3859
                        if (escaped) {
 
3860
                                popup_an_error("%s: Double \\E",
 
3861
                                    action_name(HexString_action));
 
3862
                                cancel_if_idle_command();
 
3863
                                return;
 
3864
                        }
 
3865
                        if (!IN_3270) {
 
3866
                                popup_an_error("%s: \\E in ANSI mode",
 
3867
                                    action_name(HexString_action));
 
3868
                                cancel_if_idle_command();
 
3869
                                return;
 
3870
                        }
 
3871
                        escaped = True;
 
3872
                } else {
 
3873
                        popup_an_error("%s: Illegal character in specification",
 
3874
                            action_name(HexString_action));
 
3875
                        cancel_if_idle_command();
 
3876
                        return;
 
3877
                }
 
3878
                t += 2;
 
3879
        }
 
3880
        if (escaped) {
 
3881
                popup_an_error("%s: Nothing follows \\E",
 
3882
                    action_name(HexString_action));
 
3883
                cancel_if_idle_command();
 
3884
                return;
 
3885
        }
 
3886
 
 
3887
#if defined(X3270_ANSI) /*[*/
 
3888
        /* Allocate a temporary buffer. */
 
3889
        if (!IN_3270 && nbytes)
 
3890
                tbuf = xbuf = (unsigned char *)Malloc(nbytes);
 
3891
#endif /*]*/
 
3892
 
 
3893
        /* Pump it in. */
 
3894
        t = s;
 
3895
        escaped = False;
 
3896
        while (*t) {
 
3897
                if (isxdigit(*t) && isxdigit(*(t + 1))) {
 
3898
                        unsigned c;
 
3899
 
 
3900
                        c = (FROM_HEX(*t) * 16) + FROM_HEX(*(t + 1));
 
3901
                        if (IN_3270)
 
3902
                                key_Character(c, escaped, True, NULL);
 
3903
#if defined(X3270_ANSI) /*[*/
 
3904
                        else
 
3905
                                *tbuf++ = (unsigned char)c;
 
3906
#endif /*]*/
 
3907
                        escaped = False;
 
3908
                } else if (!strncmp(t, "\\E", 2) || !strncmp(t, "\\e", 2)) {
 
3909
                        escaped = True;
 
3910
                }
 
3911
                t += 2;
 
3912
        }
 
3913
#if defined(X3270_ANSI) /*[*/
 
3914
        if (!IN_3270 && nbytes) {
 
3915
                net_hexansi_out(xbuf, nbytes);
 
3916
                Free(xbuf);
 
3917
        }
 
3918
#endif /*]*/
 
3919
}
 
3920
 
 
3921
void
 
3922
ignore_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
 
3923
{
 
3924
        action_debug(ignore_action, event, params, num_params);
 
3925
        reset_idle_timer();
 
3926
}
 
3927
 
 
3928
#if defined(X3270_FT) /*[*/
 
3929
/*
 
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
 
3932
 * to set up.
 
3933
 */
 
3934
int
 
3935
kybd_prime(void)
 
3936
{
 
3937
        int baddr;
 
3938
        register unsigned char fa;
 
3939
        int len = 0;
 
3940
 
 
3941
        /*
 
3942
         * No point in trying if the screen isn't formatted, the keyboard
 
3943
         * is locked, or we aren't in 3270 mode.
 
3944
         */
 
3945
        if (!formatted || kybdlock || !IN_3270)
 
3946
                return 0;
 
3947
 
 
3948
        fa = get_field_attribute(cursor_addr);
 
3949
        if (ea_buf[cursor_addr].fa || FA_IS_PROTECTED(fa)) {
 
3950
                /*
 
3951
                 * The cursor is not in an unprotected field.  Find the
 
3952
                 * next one.
 
3953
                 */
 
3954
                baddr = next_unprotected(cursor_addr);
 
3955
 
 
3956
                /* If there isn't any, give up. */
 
3957
                if (!baddr)
 
3958
                        return 0;
 
3959
 
 
3960
                /* Move the cursor there. */
 
3961
        } else {
 
3962
                /* Already in an unprotected field.  Find its start. */
 
3963
                baddr = cursor_addr;
 
3964
                while (!ea_buf[baddr].fa) {
 
3965
                        DEC_BA(baddr);
 
3966
                }
 
3967
                INC_BA(baddr);
 
3968
        }
 
3969
 
 
3970
        /* Move the cursor to the beginning of the field. */
 
3971
        cursor_move(baddr);
 
3972
 
 
3973
        /* Erase it. */
 
3974
        while (!ea_buf[baddr].fa) {
 
3975
                ctlr_add(baddr, 0, 0);
 
3976
                len++;
 
3977
                INC_BA(baddr);
 
3978
        }
 
3979
 
 
3980
        /* Return the field length. */
 
3981
        return len;
 
3982
}
 
3983
#endif /*]*/
 
3984
 
 
3985
/*
 
3986
 * Translate a keysym name to a keysym, including APL and extended
 
3987
 * characters.
 
3988
 */
 
3989
static KeySym
 
3990
MyStringToKeysym(char *s, enum keytype *keytypep, ucs4_t *ucs4)
 
3991
{
 
3992
        KeySym k;
 
3993
        int consumed;
 
3994
        enum me_fail error;
 
3995
 
 
3996
        /* No UCS-4 yet. */
 
3997
        *ucs4 = 0L;
 
3998
 
 
3999
#if defined(X3270_APL) /*[*/
 
4000
        /* Look for my contrived APL symbols. */
 
4001
        if (!strncmp(s, "apl_", 4)) {
 
4002
                int is_ge;
 
4003
 
 
4004
                k = APLStringToKeysym(s, &is_ge);
 
4005
                if (is_ge)
 
4006
                        *keytypep = KT_GE;
 
4007
                else
 
4008
                        *keytypep = KT_STD;
 
4009
                return k;
 
4010
        } else
 
4011
#endif /*]*/
 
4012
        {
 
4013
                /* Look for a standard X11 keysym. */
 
4014
                k = StringToKeysym(s);
 
4015
                *keytypep = KT_STD;
 
4016
                if (k != NoSymbol)
 
4017
                        return k;
 
4018
        }
 
4019
 
 
4020
        /* Look for "euro". */
 
4021
        if (!strcasecmp(s, "euro")) {
 
4022
                *ucs4 = 0x20ac;
 
4023
                return NoSymbol;
 
4024
        }
 
4025
 
 
4026
        /* Look for U+nnnn of 0xXXXX. */
 
4027
        if (!strncasecmp(s, "U+", 2) || !strncasecmp(s, "0x", 2)) {
 
4028
                *ucs4 = strtoul(s + 2, NULL, 16);
 
4029
                return NoSymbol;
 
4030
        }
 
4031
 
 
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))
 
4035
                *ucs4 = 0;
 
4036
        return NoSymbol;
 
4037
}
 
4038
 
 
4039
#if defined(X3270_DISPLAY) /*[*/
 
4040
/*
 
4041
 * X-dependent code starts here.
 
4042
 */
 
4043
 
 
4044
/*
 
4045
 * Translate a keymap (from an XQueryKeymap or a KeymapNotify event) into
 
4046
 * a bitmap of Shift, Meta or Alt keys pressed.
 
4047
 */
 
4048
#define key_is_down(kc, bitmap) (kc && ((bitmap)[(kc)/8] & (1<<((kc)%8))))
 
4049
int
 
4050
state_from_keymap(char keymap[32])
 
4051
{
 
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;
 
4057
 
 
4058
        if (!initted) {
 
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);
 
4065
                initted = True;
 
4066
        }
 
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;
 
4077
}
 
4078
#undef key_is_down
 
4079
 
 
4080
/*
 
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.
 
4087
 *
 
4088
 * This function is also called as part of Focus event processing.
 
4089
 */
 
4090
void
 
4091
PA_Shift_action(Widget w _is_unused, XEvent *event _is_unused, String *params _is_unused,
 
4092
    Cardinal *num_params _is_unused)
 
4093
{
 
4094
        char    keys[32];
 
4095
 
 
4096
#if defined(INTERNAL_ACTION_DEBUG) /*[*/
 
4097
        action_debug(PA_Shift_action, event, params, num_params);
 
4098
#endif /*]*/
 
4099
        XQueryKeymap(display, keys);
 
4100
        shift_event(state_from_keymap(keys));
 
4101
}
 
4102
#endif /*]*/
 
4103
 
 
4104
#if defined(X3270_DISPLAY) || defined(C3270) /*[*/
 
4105
static Boolean
 
4106
build_composites(void)
 
4107
{
 
4108
        char *c, *c0, *c1;
 
4109
        char *ln;
 
4110
        char ksname[3][64];
 
4111
        char junk[2];
 
4112
        KeySym k[3];
 
4113
        enum keytype a[3];
 
4114
        int i;
 
4115
        struct composite *cp;
 
4116
 
 
4117
        if (appres.compose_map == CN) {
 
4118
                popup_an_error("%s: No %s defined", action_name(Compose_action),
 
4119
                    ResComposeMap);
 
4120
                return False;
 
4121
        }
 
4122
        c0 = get_fresource("%s.%s", ResComposeMap, appres.compose_map);
 
4123
        if (c0 == CN) {
 
4124
                popup_an_error("%s: Cannot find %s \"%s\"",
 
4125
                    action_name(Compose_action), ResComposeMap,
 
4126
                    appres.compose_map);
 
4127
                return False;
 
4128
        }
 
4129
        c1 = c = NewString(c0); /* will be modified by strtok */
 
4130
        while ((ln = strtok(c, "\n"))) {
 
4131
                Boolean okay = True;
 
4132
 
 
4133
                c = NULL;
 
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);
 
4138
                        continue;
 
4139
                }
 
4140
                for (i = 0; i < 3; i++) {
 
4141
                        ucs4_t ucs4;
 
4142
 
 
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]);
 
4148
                                okay = False;
 
4149
                                break;
 
4150
                        }
 
4151
                }
 
4152
                if (!okay)
 
4153
                        continue;
 
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];
 
4163
                n_composites++;
 
4164
        }
 
4165
        Free(c1);
 
4166
        return True;
 
4167
}
 
4168
 
 
4169
/*
 
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).
 
4175
 *
 
4176
 * The mechanism breaks down a little when the user presses "Compose" and
 
4177
 * then a non-data key.  Oh well.
 
4178
 */
 
4179
void
 
4180
Compose_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
 
4181
{
 
4182
        action_debug(Compose_action, event, params, num_params);
 
4183
        if (check_usage(Compose_action, *num_params, 0, 0) < 0)
 
4184
                return;
 
4185
        reset_idle_timer();
 
4186
 
 
4187
        if (!composites && !build_composites())
 
4188
                return;
 
4189
 
 
4190
        if (composing == NONE) {
 
4191
                composing = COMPOSE;
 
4192
                status_compose(True, 0, KT_STD);
 
4193
        }
 
4194
}
 
4195
#endif /*]*/
 
4196
 
 
4197
#if defined(X3270_DISPLAY) /*[*/
 
4198
 
 
4199
/*
 
4200
 * Called by the toolkit for any key without special actions.
 
4201
 */
 
4202
void
 
4203
Default_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
 
4204
{
 
4205
        XKeyEvent       *kevent = (XKeyEvent *)event;
 
4206
        char            buf[32];
 
4207
        KeySym          ks;
 
4208
        int             ll;
 
4209
 
 
4210
        action_debug(Default_action, event, params, num_params);
 
4211
        if (check_usage(Default_action, *num_params, 0, 0) < 0)
 
4212
                return;
 
4213
        switch (event->type) {
 
4214
            case KeyPress:
 
4215
#if defined(X3270_DBCS) /*[*/
 
4216
                if (!xim_lookup((XKeyEvent *)event))
 
4217
                        return;
 
4218
#endif /*]*/
 
4219
                ll = XLookupString(kevent, buf, 32, &ks, (XComposeStatus *) 0);
 
4220
                buf[ll] = '\0';
 
4221
                if (ll > 1) {
 
4222
                        key_ACharacter(buf, KT_STD, IA_DEFAULT, NULL);
 
4223
                        return;
 
4224
                }
 
4225
                if (ll == 1) {
 
4226
                        /* Remap certain control characters. */
 
4227
                        if (!IN_ANSI) switch (buf[0]) {
 
4228
                            case '\t':
 
4229
                                action_internal(Tab_action, IA_DEFAULT, CN, CN);
 
4230
                                break;
 
4231
                           case '\177':
 
4232
                                action_internal(Delete_action, IA_DEFAULT, CN,
 
4233
                                    CN);
 
4234
                                break;
 
4235
                            case '\b':
 
4236
                                action_internal(Erase_action, IA_DEFAULT,
 
4237
                                    CN, CN);
 
4238
                                break;
 
4239
                            case '\r':
 
4240
                                action_internal(Enter_action, IA_DEFAULT, CN,
 
4241
                                    CN);
 
4242
                                break;
 
4243
                            case '\n':
 
4244
                                action_internal(Newline_action, IA_DEFAULT, CN,
 
4245
                                    CN);
 
4246
                                break;
 
4247
                            default:
 
4248
                                key_ACharacter(buf, KT_STD, IA_DEFAULT, NULL);
 
4249
                                break;
 
4250
                        } else {
 
4251
                                key_ACharacter(buf, KT_STD, IA_DEFAULT, NULL);
 
4252
                        }
 
4253
                        return;
 
4254
                }
 
4255
 
 
4256
                /* Pick some other reasonable defaults. */
 
4257
                switch (ks) {
 
4258
                    case XK_Up:
 
4259
                        action_internal(Up_action, IA_DEFAULT, CN, CN);
 
4260
                        break;
 
4261
                    case XK_Down:
 
4262
                        action_internal(Down_action, IA_DEFAULT, CN, CN);
 
4263
                        break;
 
4264
                    case XK_Left:
 
4265
                        action_internal(Left_action, IA_DEFAULT, CN, CN);
 
4266
                        break;
 
4267
                    case XK_Right:
 
4268
                        action_internal(Right_action, IA_DEFAULT, CN, CN);
 
4269
                        break;
 
4270
                    case XK_Insert:
 
4271
#if defined(XK_KP_Insert) /*[*/
 
4272
                    case XK_KP_Insert:
 
4273
#endif /*]*/
 
4274
                        action_internal(Insert_action, IA_DEFAULT, CN, CN);
 
4275
                        break;
 
4276
                    case XK_Delete:
 
4277
                        action_internal(Delete_action, IA_DEFAULT, CN, CN);
 
4278
                        break;
 
4279
                    case XK_Home:
 
4280
                        action_internal(Home_action, IA_DEFAULT, CN, CN);
 
4281
                        break;
 
4282
                    case XK_Tab:
 
4283
                        action_internal(Tab_action, IA_DEFAULT, CN, CN);
 
4284
                        break;
 
4285
#if defined(XK_ISO_Left_Tab) /*[*/
 
4286
                    case XK_ISO_Left_Tab:
 
4287
                        action_internal(BackTab_action, IA_DEFAULT, CN, CN);
 
4288
                        break;
 
4289
#endif /*]*/
 
4290
                    case XK_Clear:
 
4291
                        action_internal(Clear_action, IA_DEFAULT, CN, CN);
 
4292
                        break;
 
4293
                    case XK_Sys_Req:
 
4294
                        action_internal(SysReq_action, IA_DEFAULT, CN, CN);
 
4295
                        break;
 
4296
#if defined(XK_EuroSign) /*[*/
 
4297
                    case XK_EuroSign:
 
4298
                        action_internal(Key_action, IA_DEFAULT, "currency",
 
4299
                                CN);
 
4300
                        break;
 
4301
#endif /*]*/
 
4302
 
 
4303
#if defined(XK_3270_Duplicate) /*[*/
 
4304
                    /* Funky 3270 keysyms. */
 
4305
                    case XK_3270_Duplicate:
 
4306
                        action_internal(Dup_action, IA_DEFAULT, CN, CN);
 
4307
                        break;
 
4308
                    case XK_3270_FieldMark:
 
4309
                        action_internal(FieldMark_action, IA_DEFAULT, CN, CN);
 
4310
                        break;
 
4311
                    case XK_3270_Right2:
 
4312
                        action_internal(Right2_action, IA_DEFAULT, CN, CN);
 
4313
                        break;
 
4314
                    case XK_3270_Left2:
 
4315
                        action_internal(Left2_action, IA_DEFAULT, CN, CN);
 
4316
                        break;
 
4317
                    case XK_3270_BackTab:
 
4318
                        action_internal(BackTab_action, IA_DEFAULT, CN, CN);
 
4319
                        break;
 
4320
                    case XK_3270_EraseEOF:
 
4321
                        action_internal(EraseEOF_action, IA_DEFAULT, CN, CN);
 
4322
                        break;
 
4323
                    case XK_3270_EraseInput:
 
4324
                        action_internal(EraseInput_action, IA_DEFAULT, CN, CN);
 
4325
                        break;
 
4326
                    case XK_3270_Reset:
 
4327
                        action_internal(Reset_action, IA_DEFAULT, CN, CN);
 
4328
                        break;
 
4329
                    case XK_3270_PA1:
 
4330
                        action_internal(PA_action, IA_DEFAULT, "1", CN);
 
4331
                        break;
 
4332
                    case XK_3270_PA2:
 
4333
                        action_internal(PA_action, IA_DEFAULT, "2", CN);
 
4334
                        break;
 
4335
                    case XK_3270_PA3:
 
4336
                        action_internal(PA_action, IA_DEFAULT, "3", CN);
 
4337
                        break;
 
4338
                    case XK_3270_Attn:
 
4339
                        action_internal(Attn_action, IA_DEFAULT, CN, CN);
 
4340
                        break;
 
4341
                    case XK_3270_AltCursor:
 
4342
                        action_internal(AltCursor_action, IA_DEFAULT, CN, CN);
 
4343
                        break;
 
4344
                    case XK_3270_CursorSelect:
 
4345
                        action_internal(CursorSelect_action, IA_DEFAULT, CN,
 
4346
                            CN);
 
4347
                        break;
 
4348
                    case XK_3270_Enter:
 
4349
                        action_internal(Enter_action, IA_DEFAULT, CN, CN);
 
4350
                        break;
 
4351
#endif /*]*/
 
4352
 
 
4353
#if defined(X3270_APL) /*[*/
 
4354
                    /* Funky APL keysyms. */
 
4355
                    case XK_downcaret:
 
4356
                        action_internal(Key_action, IA_DEFAULT, "apl_downcaret",
 
4357
                            CN);
 
4358
                        break;
 
4359
                    case XK_upcaret:
 
4360
                        action_internal(Key_action, IA_DEFAULT, "apl_upcaret",
 
4361
                            CN);
 
4362
                        break;
 
4363
                    case XK_overbar:
 
4364
                        action_internal(Key_action, IA_DEFAULT, "apl_overbar",
 
4365
                            CN);
 
4366
                        break;
 
4367
                    case XK_downtack:
 
4368
                        action_internal(Key_action, IA_DEFAULT, "apl_downtack",
 
4369
                            CN);
 
4370
                        break;
 
4371
                    case XK_upshoe:
 
4372
                        action_internal(Key_action, IA_DEFAULT, "apl_upshoe",
 
4373
                            CN);
 
4374
                        break;
 
4375
                    case XK_downstile:
 
4376
                        action_internal(Key_action, IA_DEFAULT, "apl_downstile",
 
4377
                            CN);
 
4378
                        break;
 
4379
                    case XK_underbar:
 
4380
                        action_internal(Key_action, IA_DEFAULT, "apl_underbar",
 
4381
                            CN);
 
4382
                        break;
 
4383
                    case XK_jot:
 
4384
                        action_internal(Key_action, IA_DEFAULT, "apl_jot", CN);
 
4385
                        break;
 
4386
                    case XK_quad:
 
4387
                        action_internal(Key_action, IA_DEFAULT, "apl_quad", CN);
 
4388
                        break;
 
4389
                    case XK_uptack:
 
4390
                        action_internal(Key_action, IA_DEFAULT, "apl_uptack",
 
4391
                            CN);
 
4392
                        break;
 
4393
                    case XK_circle:
 
4394
                        action_internal(Key_action, IA_DEFAULT, "apl_circle",
 
4395
                            CN);
 
4396
                        break;
 
4397
                    case XK_upstile:
 
4398
                        action_internal(Key_action, IA_DEFAULT, "apl_upstile",
 
4399
                            CN);
 
4400
                        break;
 
4401
                    case XK_downshoe:
 
4402
                        action_internal(Key_action, IA_DEFAULT, "apl_downshoe",
 
4403
                            CN);
 
4404
                        break;
 
4405
                    case XK_rightshoe:
 
4406
                        action_internal(Key_action, IA_DEFAULT, "apl_rightshoe",
 
4407
                            CN);
 
4408
                        break;
 
4409
                    case XK_leftshoe:
 
4410
                        action_internal(Key_action, IA_DEFAULT, "apl_leftshoe",
 
4411
                            CN);
 
4412
                        break;
 
4413
                    case XK_lefttack:
 
4414
                        action_internal(Key_action, IA_DEFAULT, "apl_lefttack",
 
4415
                            CN);
 
4416
                        break;
 
4417
                    case XK_righttack:
 
4418
                        action_internal(Key_action, IA_DEFAULT, "apl_righttack",
 
4419
                            CN);
 
4420
                        break;
 
4421
#endif /*]*/
 
4422
 
 
4423
                    default:
 
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);
 
4427
                        } else {
 
4428
                                ucs4_t ucs4;
 
4429
 
 
4430
                                ucs4 = keysym2ucs(ks);
 
4431
                                if (ucs4 != (ucs4_t)-1) {
 
4432
                                        key_UCharacter(ucs4, KT_STD, IA_KEY,
 
4433
                                                NULL);
 
4434
                                } else {
 
4435
                                        trace_event(
 
4436
                                            " %s: dropped (unknown keysym)\n",
 
4437
                                            action_name(Default_action));
 
4438
                                }
 
4439
                        }
 
4440
                        break;
 
4441
                }
 
4442
                break;
 
4443
 
 
4444
            case ButtonPress:
 
4445
            case ButtonRelease:
 
4446
                trace_event(" %s: dropped (no action configured)\n",
 
4447
                    action_name(Default_action));
 
4448
                break;
 
4449
            default:
 
4450
                trace_event(" %s: dropped (unknown event type)\n",
 
4451
                    action_name(Default_action));
 
4452
                break;
 
4453
        }
 
4454
}
 
4455
 
 
4456
/*
 
4457
 * Set or clear a temporary keymap.
 
4458
 *
 
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
 
4463
 */
 
4464
void
 
4465
TemporaryKeymap_action(Widget w _is_unused, XEvent *event, String *params, Cardinal *num_params)
 
4466
{
 
4467
        action_debug(TemporaryKeymap_action, event, params, num_params);
 
4468
        reset_idle_timer();
 
4469
 
 
4470
        if (check_usage(TemporaryKeymap_action, *num_params, 0, 1) < 0)
 
4471
                return;
 
4472
 
 
4473
        if (*num_params == 0 || !strcmp(params[0], "None")) {
 
4474
                (void) temporary_keymap(CN);
 
4475
                return;
 
4476
        }
 
4477
 
 
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();
 
4482
        }
 
4483
}
 
4484
 
 
4485
#endif /*]*/