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

« back to all changes in this revision

Viewing changes to s3270/charset.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
1
/*
2
 
 * Modifications Copyright 1993, 1994, 1995, 1996, 1999, 2000, 2001, 2002,
3
 
 *  2003, 2004, 2005, 2006, 2007 by Paul Mattes.
4
 
 * Original X11 Port Copyright 1990 by Jeff Sparkes.
5
 
 *  Permission to use, copy, modify, and distribute this software and its
6
 
 *  documentation for any purpose and without fee is hereby granted,
7
 
 *  provided that the above copyright notice appear in all copies and that
8
 
 *  both that copyright notice and this permission notice appear in
9
 
 *  supporting documentation.
10
 
 *
11
 
 * Copyright 1989 by Georgia Tech Research Corporation, Atlanta, GA 30332.
12
 
 *  All Rights Reserved.  GTRC hereby grants public use of this software.
13
 
 *  Derivative works based on this software must incorporate this copyright
14
 
 *  notice.
15
 
 *
16
 
 * x3270, c3270, s3270 and tcl3270 are distributed in the hope that they will
17
 
 * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the file LICENSE
19
 
 * for more details.
 
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.
20
30
 */
21
31
 
22
32
/*
26
36
 
27
37
#include "globals.h"
28
38
 
 
39
#include "3270ds.h"
29
40
#include "resources.h"
30
41
#include "appres.h"
31
42
#include "cg.h"
37
48
#include "screenc.h"
38
49
#endif /*]*/
39
50
#include "tablesc.h"
 
51
#include "unicodec.h"
 
52
#include "unicode_dbcsc.h"
40
53
#include "utf8c.h"
41
54
#include "utilc.h"
42
 
#include "widec.h"
43
55
 
44
56
#include <errno.h>
45
57
#include <locale.h>
47
59
#include <langinfo.h>
48
60
#endif /*]*/
49
61
 
50
 
#define EURO_SUFFIX     "-euro"
51
 
#define ES_SIZE         (sizeof(EURO_SUFFIX) - 1)
52
 
 
53
62
#if defined(_WIN32) /*[*/
54
 
extern void set_display_charset(char *dcs);
 
63
#include <windows.h>
 
64
#endif /*]*/
 
65
 
 
66
#if defined(__CYGWIN__) /*[*/
 
67
#include <w32api/windows.h>
 
68
#undef _WIN32
55
69
#endif /*]*/
56
70
 
57
71
/* Globals. */
61
75
unsigned long cgcsgid = DEFAULT_CGEN | DEFAULT_CSET;
62
76
unsigned long cgcsgid_dbcs = 0L;
63
77
char *default_display_charset = "3270cg-1a,3270cg-1,iso8859-1";
64
 
char *converter_names;
65
 
char *encoding;
66
 
#if defined(X3270_DISPLAY) /*[*/
67
 
unsigned char xk_selector = 0;
68
 
#endif
69
 
unsigned char auto_keymap = 0;
70
78
 
71
79
/* Statics. */
72
 
static enum cs_result resource_charset(char *csname, char *cs, char *ftcs);
73
 
typedef enum { CS_ONLY, FT_ONLY, BOTH } remap_scope;
74
 
static enum cs_result remap_chars(char *csname, char *spec, remap_scope scope,
75
 
    int *ne);
76
 
static void remap_one(unsigned char ebc, KeySym iso, remap_scope scope,
77
 
    Boolean one_way);
78
 
#if defined(DEBUG_CHARSET) /*[*/
79
 
static enum cs_result check_charset(void);
80
 
static char *char_if_ascii7(unsigned long l);
81
 
#endif /*]*/
82
 
static void set_cgcsgids(char *spec);
 
80
static enum cs_result charset_init2(char *csname, const char *codepage,
 
81
        const char *cgcsgid, const char *display_charsets);
 
82
static void set_cgcsgids(const char *spec);
83
83
static int set_cgcsgid(char *spec, unsigned long *idp);
 
84
static void set_host_codepage(char *codepage);
84
85
static void set_charset_name(char *csname);
85
86
 
 
87
static char *host_codepage = CN;
86
88
static char *charset_name = CN;
87
89
 
88
 
static void
89
 
charset_defaults(void)
90
 
{
91
 
        /* Go to defaults first. */
92
 
        (void) memcpy((char *)ebc2cg, (char *)ebc2cg0, 256);
93
 
        (void) memcpy((char *)cg2ebc, (char *)cg2ebc0, 256);
94
 
        (void) memcpy((char *)ebc2asc, (char *)ebc2asc0, 256);
95
 
        (void) memcpy((char *)asc2ebc, (char *)asc2ebc0, 256);
96
 
#if defined(X3270_FT) /*[*/
97
 
        (void) memcpy((char *)ft2asc, (char *)ft2asc0, 256);
98
 
        (void) memcpy((char *)asc2ft, (char *)asc2ft0, 256);
99
 
#endif /*]*/
100
 
        clear_xks();
101
 
}
102
 
 
103
 
static unsigned char save_ebc2cg[256];
104
 
static unsigned char save_cg2ebc[256];
105
 
static unsigned char save_ebc2asc[256];
106
 
static unsigned char save_asc2ebc[256];
107
 
#if defined(X3270_FT) /*[*/
108
 
static unsigned char save_ft2asc[256];
109
 
static unsigned char save_asc2ft[256];
110
 
#endif /*]*/
111
 
 
112
 
static void
113
 
save_charset(void)
114
 
{
115
 
        (void) memcpy((char *)save_ebc2cg, (char *)ebc2cg, 256);
116
 
        (void) memcpy((char *)save_cg2ebc, (char *)cg2ebc, 256);
117
 
        (void) memcpy((char *)save_ebc2asc, (char *)ebc2asc, 256);
118
 
        (void) memcpy((char *)save_asc2ebc, (char *)asc2ebc, 256);
119
 
#if defined(X3270_FT) /*[*/
120
 
        (void) memcpy((char *)save_ft2asc, (char *)ft2asc, 256);
121
 
        (void) memcpy((char *)save_asc2ft, (char *)asc2ft, 256);
122
 
#endif /*]*/
123
 
}
124
 
 
125
 
static void
126
 
restore_charset(void)
127
 
{
128
 
        (void) memcpy((char *)ebc2cg, (char *)save_ebc2cg, 256);
129
 
        (void) memcpy((char *)cg2ebc, (char *)save_cg2ebc, 256);
130
 
        (void) memcpy((char *)ebc2asc, (char *)save_ebc2asc, 256);
131
 
        (void) memcpy((char *)asc2ebc, (char *)save_asc2ebc, 256);
132
 
#if defined(X3270_FT) /*[*/
133
 
        (void) memcpy((char *)ft2asc, (char *)save_ft2asc, 256);
134
 
        (void) memcpy((char *)asc2ft, (char *)save_asc2ft, 256);
135
 
#endif /*]*/
136
 
}
137
 
 
138
 
/* Get a character set definition. */
139
 
static char *
140
 
get_charset_def(const char *csname)
141
 
{
142
 
        return get_fresource("%s.%s", ResCharset, csname);
143
 
}
144
 
 
145
 
#if defined(X3270_DBCS) /*[*/
146
 
/*
147
 
 * Initialize the DBCS conversion functions, based on resource values.
148
 
 */
149
 
static int
150
 
wide_resource_init(char *csname)
151
 
{
152
 
        char *cn, *en;
153
 
 
154
 
        cn = get_fresource("%s.%s", ResDbcsConverters, csname);
155
 
        if (cn == CN)
156
 
                return 0;
157
 
 
158
 
        en = get_fresource("%s.%s", ResLocalEncoding, csname);
159
 
        if (en == CN)
160
 
                en = appres.local_encoding;
161
 
        Replace(converter_names, cn);
162
 
        Replace(encoding, en);
163
 
 
164
 
        return wide_init(cn, en);
165
 
 
166
 
}
167
 
#endif /*]*/
168
 
 
169
90
/*
170
91
 * Change character sets.
171
92
 */
172
93
enum cs_result
173
94
charset_init(char *csname)
174
95
{
175
 
        char *cs, *ftcs;
176
 
        enum cs_result rc;
177
 
        char *ccs, *cftcs;
178
 
#if defined(X3270_DISPLAY) /*[*/
179
 
        char *xks;
180
 
#endif /*]*/
181
 
        char *ak;
 
96
        enum cs_result rc;
182
97
#if !defined(_WIN32) /*[*/
183
98
        char *codeset_name;
184
99
#endif /*]*/
 
100
        const char *codepage;
 
101
        const char *cgcsgid;
 
102
        const char *display_charsets;
 
103
#if defined(X3270_DBCS) /*[*/
 
104
        const char *dbcs_cgcsgid = NULL;
 
105
        const char *dbcs_display_charsets = NULL;
 
106
        Boolean need_free = False;
 
107
#endif /*]*/
185
108
 
186
109
#if !defined(_WIN32) /*[*/
187
110
        /* Get all of the locale stuff right. */
189
112
 
190
113
        /* Figure out the locale code set (character set encoding). */
191
114
        codeset_name = nl_langinfo(CODESET);
 
115
#if defined(__CYGWIN__) /*[*/
 
116
        /*
 
117
         * Cygwin's locale support is quite limited.  If the locale
 
118
         * indicates "US-ASCII", which appears to be the only supported
 
119
         * encoding, ignore it and use the Windows ANSI code page, which
 
120
         * observation indicates is what is actually supported.
 
121
         *
 
122
         * Hopefully at some point Cygwin will start returning something
 
123
         * meaningful here and this logic will stop triggering.
 
124
         */
 
125
        if (!strcmp(codeset_name, "US-ASCII"))
 
126
                codeset_name = xs_buffer("CP%d", GetACP());
 
127
#endif /*]*/
192
128
        set_codeset(codeset_name);
193
129
#endif /*]*/
194
130
 
195
131
        /* Do nothing, successfully. */
196
132
        if (csname == CN || !strcasecmp(csname, "us")) {
197
 
                charset_defaults();
198
133
                set_cgcsgids(CN);
 
134
                set_host_codepage(CN);
199
135
                set_charset_name(CN);
200
 
#if defined(X3270_DISPLAY) || (defined(C3270) && !defined(_WIN32)) /*[*/
 
136
#if defined(X3270_DISPLAY) /*[*/
201
137
                (void) screen_new_display_charsets(default_display_charset,
202
138
                    "us");
203
 
#else /*][*/
204
 
#if defined(_WIN32) /*[*/
205
 
                set_display_charset("iso8859-1");
206
 
#else /*][*/
207
 
                utf8_set_display_charsets(default_display_charset, "us");
208
139
#endif /*]*/
 
140
                (void) set_uni(CN, &codepage, &cgcsgid, &display_charsets);
 
141
#if defined(X3270_DBCS) /*[*/
 
142
                (void) set_uni_dbcs("", NULL, NULL);
209
143
#endif /*]*/
210
144
                return CS_OKAY;
211
145
        }
212
146
 
213
 
        /* Figure out if it's already in a resource or in a file. */
214
 
        cs = get_charset_def(csname);
215
 
        if (cs == CN &&
216
 
            strlen(csname) > ES_SIZE &&
217
 
            !strcasecmp(csname + strlen(csname) - ES_SIZE, EURO_SUFFIX)) {
218
 
                char *basename;
219
 
 
220
 
                /* Grab the non-Euro definition. */
221
 
                basename = xs_buffer("%.*s", (int)(strlen(csname) - ES_SIZE),
222
 
                        csname);
223
 
                cs = get_charset_def(basename);
224
 
                Free(basename);
225
 
        }
226
 
        if (cs == CN)
227
 
                return CS_NOTFOUND;
228
 
 
229
 
        /* Grab the File Transfer character set. */
230
 
        ftcs = get_fresource("%s.%s", ResFtCharset, csname);
231
 
 
232
 
        /* Copy strings. */
233
 
        ccs = NewString(cs);
234
 
        cftcs = (ftcs == NULL)? NULL: NewString(ftcs);
235
 
 
236
 
        /* Save the current definitions, and start over with the defaults. */
237
 
        save_charset();
238
 
        charset_defaults();
239
 
 
240
 
        /* Check for auto-keymap. */
241
 
        ak = get_fresource("%s.%s", ResAutoKeymap, csname);
242
 
        if (ak != NULL)
243
 
                auto_keymap = !strcasecmp(ak, "true");
244
 
        else
245
 
                auto_keymap = 0;
246
 
 
247
 
        /* Interpret them. */
248
 
        rc = resource_charset(csname, ccs, cftcs);
249
 
 
250
 
        /* Free them. */
251
 
        Free(ccs);
252
 
        Free(cftcs);
253
 
 
254
 
#if defined(DEBUG_CHARSET) /*[*/
255
 
        if (rc == CS_OKAY)
256
 
                rc = check_charset();
257
 
#endif /*]*/
258
 
 
259
 
        if (rc != CS_OKAY)
260
 
                restore_charset();
261
 
#if defined(X3270_DBCS) /*[*/
262
 
        else if (wide_resource_init(csname) < 0) {
263
 
                restore_charset();
264
 
                return CS_NOTFOUND;
265
 
        }
266
 
#endif /*]*/
267
 
 
268
 
#if defined(X3270_DISPLAY) /*[*/
269
 
        /* Check for an XK selector. */
270
 
        xks = get_fresource("%s.%s", ResXkSelector, csname);
271
 
        if (xks != NULL)
272
 
                xk_selector = (unsigned char) strtoul(xks, NULL, 0);
273
 
        else
274
 
                xk_selector = 0;
275
 
#endif /*]*/
276
 
 
277
 
        return rc;
 
147
        if (set_uni(csname, &codepage, &cgcsgid, &display_charsets) < 0)
 
148
                return CS_NOTFOUND;
 
149
        if (appres.sbcs_cgcsgid != CN)
 
150
                cgcsgid = appres.sbcs_cgcsgid; /* override */
 
151
#if defined(X3270_DBCS) /*[*/
 
152
        if (set_uni_dbcs(csname, &dbcs_cgcsgid, &dbcs_display_charsets) == 0) {
 
153
            if (appres.dbcs_cgcsgid != CN)
 
154
                    dbcs_cgcsgid = appres.dbcs_cgcsgid; /* override */
 
155
            cgcsgid = xs_buffer("%s+%s", cgcsgid, dbcs_cgcsgid);
 
156
            display_charsets = xs_buffer("%s+%s", display_charsets,
 
157
                    dbcs_display_charsets);
 
158
            need_free = True;
 
159
        }
 
160
#endif /*]*/
 
161
 
 
162
        rc = charset_init2(csname, codepage, cgcsgid, display_charsets);
 
163
#if defined(X3270_DBCS) /*[*/
 
164
        if (need_free) {
 
165
            Free((char *)cgcsgid);
 
166
            Free((char *)display_charsets);
 
167
        }
 
168
#endif /*]*/
 
169
        if (rc != CS_OKAY) {
 
170
                return rc;
 
171
        }
 
172
 
 
173
        return CS_OKAY;
278
174
}
279
175
 
280
176
/* Set a CGCSGID.  Return 0 for success, -1 for failure. */
299
195
 
300
196
/* Set the CGCSGIDs. */
301
197
static void
302
 
set_cgcsgids(char *spec)
 
198
set_cgcsgids(const char *spec)
303
199
{
304
200
        int n_ids = 0;
305
201
        char *spec_copy;
340
236
                        return;
341
237
        }
342
238
 
343
 
        cgcsgid = DEFAULT_CGEN | DEFAULT_CSET;
 
239
        if (appres.sbcs_cgcsgid != CN)
 
240
                cgcsgid = strtoul(appres.sbcs_cgcsgid, NULL, 0);
 
241
        else
 
242
                cgcsgid = DEFAULT_CGEN | DEFAULT_CSET;
344
243
#if defined(X3270_DBCS) /*[*/
345
 
        cgcsgid_dbcs = 0L;
 
244
        if (appres.dbcs_cgcsgid != CN)
 
245
                cgcsgid_dbcs = strtoul(appres.dbcs_cgcsgid, NULL, 0);
 
246
        else
 
247
                cgcsgid_dbcs = 0L;
346
248
#endif /*]*/
347
249
}
348
250
 
 
251
/* Set the host codepage. */
 
252
static void
 
253
set_host_codepage(char *codepage)
 
254
{
 
255
        if (codepage == CN) {
 
256
                Replace(host_codepage, NewString("037"));
 
257
                return;
 
258
        }
 
259
        if (host_codepage == CN || strcmp(host_codepage, codepage)) {
 
260
                Replace(host_codepage, NewString(codepage));
 
261
        }
 
262
}
 
263
 
349
264
/* Set the global charset name. */
350
265
static void
351
266
set_charset_name(char *csname)
362
277
        }
363
278
}
364
279
 
365
 
/* Define a charset from resources. */
 
280
/* Character set init, part 2. */
366
281
static enum cs_result
367
 
resource_charset(char *csname, char *cs, char *ftcs)
 
282
charset_init2(char *csname, const char *codepage, const char *cgcsgid,
 
283
        const char *display_charsets)
368
284
{
369
 
        enum cs_result rc;
370
 
        int ne = 0;
371
 
        char *rcs = CN;
 
285
        const char *rcs = display_charsets;
372
286
        int n_rcs = 0;
373
 
#if defined(_WIN32) /*[*/
374
 
        char *dcs;
375
 
#endif /*]*/
376
 
 
377
 
        /* Interpret the spec. */
378
 
        rc = remap_chars(csname, cs, (ftcs == NULL)? BOTH: CS_ONLY, &ne);
379
 
        if (rc != CS_OKAY)
380
 
                return rc;
381
 
        if (ftcs != NULL) {
382
 
                rc = remap_chars(csname, ftcs, FT_ONLY, &ne);
383
 
                if (rc != CS_OKAY)
384
 
                        return rc;
385
 
        }
386
 
 
387
 
        rcs = get_fresource("%s.%s", ResDisplayCharset, csname);
 
287
        char *rcs_copy, *buf, *token;
388
288
 
389
289
        /* Isolate the pieces. */
390
 
        if (rcs != CN) {
391
 
                char *rcs_copy, *buf, *token;
392
 
 
393
 
                buf = rcs_copy = NewString(rcs);
394
 
                while ((token = strtok(buf, "+")) != CN) {
395
 
                        buf = CN;
396
 
                        switch (n_rcs) {
397
 
                        case 0:
 
290
        buf = rcs_copy = NewString(rcs);
 
291
        while ((token = strtok(buf, "+")) != CN) {
 
292
                buf = CN;
 
293
                switch (n_rcs) {
 
294
                case 0:
398
295
#if defined(X3270_DBCS) /*[*/
399
 
                        case 1:
 
296
                case 1:
400
297
#endif /*]*/
401
 
                            break;
402
 
                        default:
403
 
                            popup_an_error("Extra %s value(s), ignoring",
404
 
                                ResDisplayCharset);
405
 
                            break;
406
 
                        }
407
 
                        n_rcs++;
 
298
                    break;
 
299
                default:
 
300
                    popup_an_error("Extra charset value(s), ignoring");
 
301
                    break;
408
302
                }
 
303
                n_rcs++;
409
304
        }
 
305
        Free(rcs_copy);
410
306
 
411
307
#if defined(X3270_DBCS) /*[*/
412
308
        /* Can't swap DBCS modes while connected. */
416
312
        }
417
313
#endif /*]*/
418
314
 
419
 
#if defined(X3270_DISPLAY) || (defined(C3270) && !defined(_WIN32)) /*[*/
 
315
#if defined(X3270_DISPLAY) /*[*/
420
316
        if (!screen_new_display_charsets(
421
317
                    rcs? rcs: default_display_charset,
422
318
                    csname)) {
423
319
                return CS_PREREQ;
424
320
        }
425
321
#else /*][*/
426
 
#if !defined(_WIN32) /*[*/
427
 
        utf8_set_display_charsets(rcs? rcs: default_display_charset, csname);
428
 
#endif /*]*/
429
322
#if defined(X3270_DBCS) /*[*/
430
323
        if (n_rcs > 1)
431
324
                dbcs = True;
434
327
#endif /*]*/
435
328
#endif /*]*/
436
329
 
437
 
        /* Set up the cgcsgid. */
438
 
        set_cgcsgids(get_fresource("%s.%s", ResCodepage, csname));
 
330
        /* Set up the cgcsgids. */
 
331
        set_cgcsgids(cgcsgid);
439
332
 
440
 
#if defined(_WIN32) /*[*/
441
 
       /* See about changing the console output code page. */
442
 
       dcs = get_fresource("%s.%s", ResDisplayCharset, csname);
443
 
       if (dcs != NULL) {
444
 
               set_display_charset(dcs);
445
 
       } else {
446
 
               set_display_charset("iso8859-1");
447
 
       }
448
 
#endif /*]*/
 
333
        /* Set up the host code page. */
 
334
        set_host_codepage((char *)codepage);
449
335
 
450
336
        /* Set up the character set name. */
451
337
        set_charset_name(csname);
453
339
        return CS_OKAY;
454
340
}
455
341
 
456
 
/*
457
 
 * Map a keysym name or literal string into a character.
458
 
 * Returns NoSymbol if there is a problem.
459
 
 */
460
 
static KeySym
461
 
parse_keysym(char *s, Boolean extended)
462
 
{
463
 
        KeySym  k;
464
 
 
465
 
        k = StringToKeysym(s);
466
 
        if (k == NoSymbol) {
467
 
                if (strlen(s) == 1)
468
 
                        k = *s & 0xff;
469
 
                else if (s[0] == '0' && s[1] == 'x') {
470
 
                        unsigned long l;
471
 
                        char *ptr;
472
 
 
473
 
                        l = strtoul(s, &ptr, 16);
474
 
                        if (*ptr != '\0' || (l & ~0xffff))
475
 
                                return NoSymbol;
476
 
                        return (KeySym)l;
477
 
                } else
478
 
                        return NoSymbol;
479
 
        }
480
 
        if (k < ' ' || (!extended && k > 0xff))
481
 
                return NoSymbol;
482
 
        else
483
 
                return k;
484
 
}
485
 
 
486
 
/* Process a single character definition. */
487
 
static void
488
 
remap_one(unsigned char ebc, KeySym iso, remap_scope scope, Boolean one_way)
489
 
{
490
 
        unsigned char cg;
491
 
 
492
 
        /* Ignore mappings of EBCDIC control codes and the space character. */
493
 
        if (ebc <= 0x40)
494
 
                return;
495
 
 
496
 
        /* If they want to map to a NULL or a blank, make it a one-way blank. */
497
 
        if (iso == 0x0)
498
 
                iso = 0x20;
499
 
        if (iso == 0x20)
500
 
                one_way = True;
501
 
 
502
 
        if (!auto_keymap || iso <= 0xff) {
503
 
#if defined(X3270_FT) /*[*/
504
 
                unsigned char aa;
505
 
#endif /*]*/
506
 
 
507
 
                if (scope == BOTH || scope == CS_ONLY) {
508
 
                        if (iso <= 0xff) {
509
 
                                cg = asc2cg[iso];
510
 
 
511
 
                                if (cg2asc[cg] == iso || iso == 0) {
512
 
                                        /* well-defined */
513
 
                                        ebc2cg[ebc] = cg;
514
 
                                        if (!one_way)
515
 
                                                cg2ebc[cg] = ebc;
516
 
                                } else {
517
 
                                        /* into a hole */
518
 
                                        ebc2cg[ebc] = CG_boxsolid;
519
 
                                }
520
 
                        }
521
 
                        if (ebc > 0x40) {
522
 
                                ebc2asc[ebc] = iso;
523
 
                                if (!one_way)
524
 
                                        asc2ebc[iso] = ebc;
525
 
                        }
526
 
                }
527
 
#if defined(X3270_FT) /*[*/
528
 
                if (iso <= 0xff && ebc > 0x40) {
529
 
                        /* Change the file transfer translation table. */
530
 
                        if (scope == BOTH) {
531
 
                                /*
532
 
                                 * We have an alternate mapping of an EBCDIC
533
 
                                 * code to an ASCII code.  Modify the existing
534
 
                                 * ASCII(ft)-to-ASCII(desired) maps.
535
 
                                 *
536
 
                                 * This is done by figuring out which ASCII
537
 
                                 * code the host usually translates the given
538
 
                                 * EBCDIC code to (asc2ft0[ebc2asc0[ebc]]).
539
 
                                 * Now we want to translate that code to the
540
 
                                 * given ISO code, and vice-versa.
541
 
                                 */
542
 
                                aa = asc2ft0[ebc2asc0[ebc]];
543
 
                                if (aa != ' ') {
544
 
                                        ft2asc[aa] = iso;
545
 
                                        asc2ft[iso] = aa;
546
 
                                }
547
 
                        } else if (scope == FT_ONLY) {
548
 
                                /*
549
 
                                 * We have a map of how the host translates
550
 
                                 * the given EBCDIC code to an ASCII code.
551
 
                                 * Generate the translation between that code
552
 
                                 * and the ISO code that we would normally
553
 
                                 * use to display that EBCDIC code.
554
 
                                 */
555
 
                                ft2asc[iso] = ebc2asc[ebc];
556
 
                                asc2ft[ebc2asc[ebc]] = iso;
557
 
                        }
558
 
                }
559
 
#endif /*]*/
560
 
        } else {
561
 
                /* Auto-keymap. */
562
 
                add_xk(iso, (KeySym)ebc2asc[ebc]);
563
 
        }
564
 
}
565
 
 
566
 
/*
567
 
 * Parse an EBCDIC character set map, a series of pairs of numeric EBCDIC codes
568
 
 * and keysyms.
569
 
 *
570
 
 * If the keysym is in the range 1..255, it is a remapping of the EBCDIC code
571
 
 * for a standard Latin-1 graphic, and the CG-to-EBCDIC map will be modified
572
 
 * to match.
573
 
 *
574
 
 * Otherwise (keysym > 255), it is a definition for the EBCDIC code to use for
575
 
 * a multibyte keysym.  This is intended for 8-bit fonts that with special
576
 
 * characters that replace certain standard Latin-1 graphics.  The keysym
577
 
 * will be entered into the extended keysym translation table.
578
 
 */
579
 
static enum cs_result
580
 
remap_chars(char *csname, char *spec, remap_scope scope, int *ne)
581
 
{
582
 
        char *s;
583
 
        char *ebcs, *isos;
584
 
        unsigned char ebc;
585
 
        KeySym iso;
586
 
        int ns;
587
 
        enum cs_result rc = CS_OKAY;
588
 
        Boolean is_table = False;
589
 
        Boolean one_way = False;
590
 
 
591
 
        /* Pick apart a copy of the spec. */
592
 
        s = spec = NewString(spec);
593
 
        while (isspace(*s)) {
594
 
                s++;
595
 
        }
596
 
        if (!strncmp(s, "#table", 6)) {
597
 
                is_table = True;
598
 
                s += 6;
599
 
        }
600
 
 
601
 
        if (is_table) {
602
 
                int ebc = 0;
603
 
                char *tok;
604
 
                char *ptr;
605
 
 
606
 
                while ((tok = strtok(s, " \t\n")) != CN) {
607
 
                        if (ebc >= 256) {
608
 
                                popup_an_error("Charset has more than 256 "
609
 
                                    "entries");
610
 
                                rc = CS_BAD;
611
 
                                break;
612
 
                        }
613
 
                        if (tok[0] == '*') {
614
 
                                one_way = True;
615
 
                                tok++;
616
 
                        } else
617
 
                                one_way = False;
618
 
                        iso = strtoul(tok, &ptr, 0);
619
 
                        if (ptr == tok || *ptr != '\0' || iso > 256L) {
620
 
                                if (strlen(tok) == 1)
621
 
                                        iso = tok[0] & 0xff;
622
 
                                else {
623
 
                                        popup_an_error("Invalid charset "
624
 
                                            "entry '%s' (#%d)",
625
 
                                            tok, ebc);
626
 
                                        rc = CS_BAD;
627
 
                                        break;
628
 
                                }
629
 
                        }
630
 
                        remap_one(ebc, iso, scope, one_way);
631
 
 
632
 
                        ebc++;
633
 
                        s = CN;
634
 
                }
635
 
                if (ebc != 256) {
636
 
                        popup_an_error("Charset has %d entries, need 256", ebc);
637
 
                        rc = CS_BAD;
638
 
                } else {
639
 
                        /*
640
 
                         * The entire EBCDIC-to-ASCII mapping has been defined.
641
 
                         * Make sure that any printable ASCII character that
642
 
                         * doesn't now map back onto itself is mapped onto an
643
 
                         * EBCDIC NUL.
644
 
                         */
645
 
                        int i;
646
 
 
647
 
                        for (i = 0; i < 256; i++) {
648
 
                                if ((i & 0x7f) > 0x20 && i != 0x7f &&
649
 
                                                asc2ebc[i] != 0 &&
650
 
                                                ebc2asc[asc2ebc[i]] != i) {
651
 
                                        asc2ebc[i] = 0;
652
 
                                }
653
 
                        }
654
 
                }
655
 
        } else {
656
 
                while ((ns = split_dresource(&s, &ebcs, &isos))) {
657
 
                        char *ptr;
658
 
 
659
 
                        (*ne)++;
660
 
                        if (ebcs[0] == '*') {
661
 
                                one_way = True;
662
 
                                ebcs++;
663
 
                        } else
664
 
                                one_way = False;
665
 
                        if (ns < 0 ||
666
 
                            ((ebc = strtoul(ebcs, &ptr, 0)),
667
 
                             ptr == ebcs || *ptr != '\0') ||
668
 
                            (iso = parse_keysym(isos, True)) == NoSymbol) {
669
 
                                popup_an_error("Cannot parse %s \"%s\", entry %d",
670
 
                                    ResCharset, csname, *ne);
671
 
                                rc = CS_BAD;
672
 
                                break;
673
 
                        }
674
 
                        remap_one(ebc, iso, scope, one_way);
675
 
                }
676
 
        }
677
 
        Free(spec);
678
 
        return rc;
679
 
}
680
 
 
681
 
#if defined(DEBUG_CHARSET) /*[*/
682
 
static char *
683
 
char_if_ascii7(unsigned long l)
684
 
{
685
 
        static char buf[6];
686
 
 
687
 
        if (((l & 0x7f) > ' ' && (l & 0x7f) < 0x7f) || l == 0xff) {
688
 
                (void) sprintf(buf, " ('%c')", (char)l);
689
 
                return buf;
690
 
        } else
691
 
                return "";
692
 
}
693
 
#endif /*]*/
694
 
 
695
 
 
696
 
#if defined(DEBUG_CHARSET) /*[*/
697
 
/*
698
 
 * Verify that a character set is not ambiguous.
699
 
 * (All this checks is that multiple EBCDIC codes map onto the same ISO code.
700
 
 *  Hmm.  God, I find the CG stuff confusing.)
701
 
 */
702
 
static enum cs_result
703
 
check_charset(void)
704
 
{
705
 
        unsigned long iso;
706
 
        unsigned char ebc;
707
 
        enum cs_result rc = CS_OKAY;
708
 
 
709
 
        for (iso = 1; iso <= 255; iso++) {
710
 
                unsigned char multi[256];
711
 
                int n_multi = 0;
712
 
 
713
 
                if (iso == ' ')
714
 
                        continue;
715
 
 
716
 
                for (ebc = 0x41; ebc < 0xff; ebc++) {
717
 
                        if (cg2asc[ebc2cg[ebc]] == iso) {
718
 
                                multi[n_multi] = ebc;
719
 
                                n_multi++;
720
 
                        }
721
 
                }
722
 
                if (n_multi > 1) {
723
 
                        xs_warning("Display character 0x%02x%s has multiple "
724
 
                            "EBCDIC definitions: X'%02X', X'%02X'%s",
725
 
                            iso, char_if_ascii7(iso),
726
 
                            multi[0], multi[1], (n_multi > 2)? ", ...": "");
727
 
                        rc = CS_BAD;
728
 
                }
729
 
        }
730
 
        return rc;
731
 
}
732
 
#endif /*]*/
 
342
/* Return the current host codepage. */
 
343
char *
 
344
get_host_codepage(void)
 
345
{
 
346
        return (host_codepage != CN)? host_codepage: "037";
 
347
}
733
348
 
734
349
/* Return the current character set name. */
735
350
char *