1 /*
2 * Copyright (c) 2001-2009, 2013-2015, 2019 Paul Mattes.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the names of Paul Mattes nor the names of his contributors
13 * may be used to endorse or promote products derived from this software
14 * without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY PAUL MATTES "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL PAUL MATTES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 /*
29 * codepage.c
30 * Limited code page support.
31 */
32
33 #include "globals.h"
34
35 #include <errno.h>
36 #include <ctype.h>
37 #include <stdlib.h>
38 #if !defined(_WIN32) /*[*/
39 # include <locale.h>
40 # include <langinfo.h>
41 #endif /*]*/
42
43 #if defined(__CYGWIN__) /*[*/
44 # include <w32api/windows.h>
45 #undef _WIN32
46 #endif /*]*/
47
48 #include "3270ds.h"
49 #include "codepage.h"
50 #include "unicodec.h"
51 #include "unicode_dbcs.h"
52 #include "utf8.h"
53
54 #if defined(_WIN32) /*[*/
55 # define LOCAL_CODEPAGE CP_ACP
56 #else /*][*/
57 # define LOCAL_CODEPAGE 0
58 #endif /*]*/
59
60 unsigned long cgcsgid = 0x02b90025;
61 unsigned long cgcsgid_dbcs = 0x02b90025;
62 int dbcs = 0;
63
64 char *encoding = NULL;
65 char *converters = NULL;
66
67 /*
68 * Change host code pages.
69 */
70 enum cs_result
codepage_init(const char * cpname)71 codepage_init(const char *cpname)
72 {
73 #if !defined(_WIN32) /*[*/
74 char *codeset_name;
75 #endif /*]*/
76 const char *host_codepage;
77 const char *cgcsgid_str;
78
79 #if !defined(_WIN32) /*[*/
80 setlocale(LC_ALL, "");
81 codeset_name = nl_langinfo(CODESET);
82 # if defined(__CYGWIN__) /*[*/
83 /*
84 * Cygwin's locale support is quite limited. If the locale
85 * indicates "US-ASCII", which appears to be the only supported
86 * encoding, ignore it and use the Windows ANSI code page, which
87 * observation indicates is what is actually supported.
88 *
89 * Hopefully at some point Cygwin will start returning something
90 * meaningful here and this logic will stop triggering.
91 *
92 * If this (lack of) functionality persists, then it will probably
93 * become necessary for pr3287 to support the wpr3287 '-printercp'
94 * option, so that the printer code page can be configured.
95 */
96 if (!strcmp(codeset_name, "US-ASCII")) {
97 codeset_name = Malloc(64);
98 sprintf(codeset_name, "CP%d", GetACP());
99 }
100 # endif /*]*/
101 set_codeset(codeset_name, false);
102 #endif /*]*/
103
104 if (!set_uni(cpname, LOCAL_CODEPAGE, &host_codepage, &cgcsgid_str, NULL,
105 NULL)) {
106 return CS_NOTFOUND;
107 }
108 cgcsgid = strtoul(cgcsgid_str, NULL, 0);
109 if (!(cgcsgid & ~0xffff)) {
110 cgcsgid |= 0x02b90000;
111 }
112
113 if (set_uni_dbcs(cpname, &cgcsgid_str) == 0) {
114 dbcs = 1;
115 cgcsgid_dbcs = strtoul(cgcsgid_str, NULL, 0);
116 }
117
118 return CS_OKAY;
119 }
120