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