Commit d714f42ebb08bccac7466c7b0925b1334b88995c
1 parent
5c448d47
Exists in
master
Criando projeto codeblocks para testar a lib3270 separada da parte GUI facilitan…
…do a identificação de erros de memória e o desenvolvimento paralelo de duas GUIs.
Showing
11 changed files
with
774 additions
and
543 deletions
Show diff stats
src/lib/Makefile.in
@@ -123,7 +123,11 @@ version.c: ./mkversion.sh | @@ -123,7 +123,11 @@ version.c: ./mkversion.sh | ||
123 | @chmod +x ./mkversion.sh | 123 | @chmod +x ./mkversion.sh |
124 | @./mkversion.sh | 124 | @./mkversion.sh |
125 | 125 | ||
126 | -$(OBJDIR)/fallbacks@OBJEXT@: $(BINDIR)/mkfb@EXEEXT@ X3270.xad | 126 | +fallbacks.c: $(BINDIR)/mkfb.exe X3270.xad |
127 | + @mkdir -p $(TMPDIR) | ||
128 | + @$(BINDIR)/mkfb.exe -c X3270.xad falbacks.c | ||
129 | + | ||
130 | +$(OBJDIR)/fallbacks@OBJEXT@: fallbacks.c | ||
127 | @echo $@ ... | 131 | @echo $@ ... |
128 | @mkdir -p `dirname $@` | 132 | @mkdir -p `dirname $@` |
129 | @mkdir -p $(TMPDIR) | 133 | @mkdir -p $(TMPDIR) |
@@ -146,6 +150,7 @@ distclean: | @@ -146,6 +150,7 @@ distclean: | ||
146 | 150 | ||
147 | clean: | 151 | clean: |
148 | @rm -f version.c | 152 | @rm -f version.c |
153 | + @rm -f fallbacks.c | ||
149 | @rm -fr debian | 154 | @rm -fr debian |
150 | @rm -fr .tmp | 155 | @rm -fr .tmp |
151 | 156 |
src/lib/globals.h
@@ -348,5 +348,6 @@ enum state_change | @@ -348,5 +348,6 @@ enum state_change | ||
348 | #endif /*]*/ | 348 | #endif /*]*/ |
349 | 349 | ||
350 | /* Library internal calls */ | 350 | /* Library internal calls */ |
351 | +void key_ACharacter(unsigned char c, enum keytype keytype, enum iaction cause,Boolean *skipped); | ||
351 | 352 | ||
352 | 353 |
src/lib/glue.c
@@ -186,9 +186,10 @@ void lib3270_session_init(H3270 *hSession, const char *model) | @@ -186,9 +186,10 @@ void lib3270_session_init(H3270 *hSession, const char *model) | ||
186 | 186 | ||
187 | /* | 187 | /* |
188 | * Sort out model and color modes, based on the model number resource. | 188 | * Sort out model and color modes, based on the model number resource. |
189 | - */ | ||
190 | - if(*appres.model) | 189 | + */ /* |
190 | + if(appres.model && *appres.model) | ||
191 | model = appres.model; | 191 | model = appres.model; |
192 | + */ | ||
192 | 193 | ||
193 | if(!*model) | 194 | if(!*model) |
194 | model = "2"; // No model, use the default one | 195 | model = "2"; // No model, use the default one |
@@ -1057,6 +1058,13 @@ popup_an_errno(int errn, const char *fmt, ...) | @@ -1057,6 +1058,13 @@ popup_an_errno(int errn, const char *fmt, ...) | ||
1057 | Error(vmsgbuf); | 1058 | Error(vmsgbuf); |
1058 | } | 1059 | } |
1059 | 1060 | ||
1061 | +#ifdef DEBUG | ||
1062 | +extern void lib3270_initialize(void) | ||
1063 | +{ | ||
1064 | + initialize(); | ||
1065 | +} | ||
1066 | +#endif | ||
1067 | + | ||
1060 | void | 1068 | void |
1061 | action_output(const char *fmt, ...) | 1069 | action_output(const char *fmt, ...) |
1062 | { | 1070 | { |
src/lib/host.c
@@ -83,6 +83,7 @@ | @@ -83,6 +83,7 @@ | ||
83 | 83 | ||
84 | static void try_reconnect(H3270 *session); | 84 | static void try_reconnect(H3270 *session); |
85 | 85 | ||
86 | +/* | ||
86 | static char * stoken(char **s) | 87 | static char * stoken(char **s) |
87 | { | 88 | { |
88 | char *r; | 89 | char *r; |
@@ -101,7 +102,7 @@ static char * stoken(char **s) | @@ -101,7 +102,7 @@ static char * stoken(char **s) | ||
101 | *s = ss; | 102 | *s = ss; |
102 | return r; | 103 | return r; |
103 | } | 104 | } |
104 | - | 105 | +*/ |
105 | 106 | ||
106 | /* | 107 | /* |
107 | * Read the host file | 108 | * Read the host file |
@@ -490,7 +491,7 @@ static int do_connect(H3270 *hSession, const char *n) | @@ -490,7 +491,7 @@ static int do_connect(H3270 *hSession, const char *n) | ||
490 | char nb[2048]; /* name buffer */ | 491 | char nb[2048]; /* name buffer */ |
491 | char *s; /* temporary */ | 492 | char *s; /* temporary */ |
492 | const char *chost; /* to whom we will connect */ | 493 | const char *chost; /* to whom we will connect */ |
493 | - char *target_name; | 494 | +// char *target_name; |
494 | char *ps = CN; | 495 | char *ps = CN; |
495 | char *port = CN; | 496 | char *port = CN; |
496 | Boolean resolving; | 497 | Boolean resolving; |
src/lib/kybd.c
@@ -103,7 +103,7 @@ static Boolean key_Character(int code, Boolean with_ge, Boolean pasting, | @@ -103,7 +103,7 @@ static Boolean key_Character(int code, Boolean with_ge, Boolean pasting, | ||
103 | static Boolean flush_ta(void); | 103 | static Boolean flush_ta(void); |
104 | static void key_AID(unsigned char aid_code); | 104 | static void key_AID(unsigned char aid_code); |
105 | static void kybdlock_set(unsigned int bits, const char *cause); | 105 | static void kybdlock_set(unsigned int bits, const char *cause); |
106 | -static KeySym MyStringToKeysym(char *s, enum keytype *keytypep); | 106 | +// static KeySym MyStringToKeysym(char *s, enum keytype *keytypep); |
107 | 107 | ||
108 | #if defined(X3270_DBCS) /*[*/ | 108 | #if defined(X3270_DBCS) /*[*/ |
109 | Boolean key_WCharacter(unsigned char code[], Boolean *skipped); | 109 | Boolean key_WCharacter(unsigned char code[], Boolean *skipped); |
@@ -1289,9 +1289,7 @@ retry: | @@ -1289,9 +1289,7 @@ retry: | ||
1289 | /* | 1289 | /* |
1290 | * Handle an ordinary character key, given an ASCII code. | 1290 | * Handle an ordinary character key, given an ASCII code. |
1291 | */ | 1291 | */ |
1292 | -void | ||
1293 | -key_ACharacter(unsigned char c, enum keytype keytype, enum iaction cause, | ||
1294 | - Boolean *skipped) | 1292 | +void key_ACharacter(unsigned char c, enum keytype keytype, enum iaction cause,Boolean *skipped) |
1295 | { | 1293 | { |
1296 | // register int i; | 1294 | // register int i; |
1297 | struct akeysym ak; | 1295 | struct akeysym ak; |
@@ -0,0 +1,211 @@ | @@ -0,0 +1,211 @@ | ||
1 | +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> | ||
2 | +<CodeBlocks_project_file> | ||
3 | + <FileVersion major="1" minor="6" /> | ||
4 | + <Project> | ||
5 | + <Option title="lib3270" /> | ||
6 | + <Option pch_mode="2" /> | ||
7 | + <Option compiler="gcc" /> | ||
8 | + <Build> | ||
9 | + <Target title="Debug"> | ||
10 | + <Option output=".bin\Debug\lib3270" prefix_auto="1" extension_auto="1" /> | ||
11 | + <Option object_output=".obj\Debug\" /> | ||
12 | + <Option type="1" /> | ||
13 | + <Option compiler="gcc" /> | ||
14 | + <Compiler> | ||
15 | + <Add option="-g" /> | ||
16 | + <Add option="-DDEBUG=1" /> | ||
17 | + </Compiler> | ||
18 | + </Target> | ||
19 | + <Target title="Release"> | ||
20 | + <Option output=".bin\Release\lib3270" prefix_auto="1" extension_auto="1" /> | ||
21 | + <Option object_output=".obj\Release\" /> | ||
22 | + <Option type="3" /> | ||
23 | + <Option compiler="gcc" /> | ||
24 | + <Option createDefFile="1" /> | ||
25 | + <Option createStaticLib="1" /> | ||
26 | + <Compiler> | ||
27 | + <Add option="-O2" /> | ||
28 | + </Compiler> | ||
29 | + <Linker> | ||
30 | + <Add option="-s" /> | ||
31 | + </Linker> | ||
32 | + </Target> | ||
33 | + </Build> | ||
34 | + <Compiler> | ||
35 | + <Add option="-Wall" /> | ||
36 | + <Add directory="..\include" /> | ||
37 | + <Add directory="..\include\lib3270" /> | ||
38 | + </Compiler> | ||
39 | + <Unit filename="Makefile.in" /> | ||
40 | + <Unit filename="XtGlue.c"> | ||
41 | + <Option compilerVar="CC" /> | ||
42 | + </Unit> | ||
43 | + <Unit filename="actions.c"> | ||
44 | + <Option compilerVar="CC" /> | ||
45 | + </Unit> | ||
46 | + <Unit filename="actionsc.h" /> | ||
47 | + <Unit filename="ansi.c"> | ||
48 | + <Option compilerVar="CC" /> | ||
49 | + </Unit> | ||
50 | + <Unit filename="ansic.h" /> | ||
51 | + <Unit filename="apl.c"> | ||
52 | + <Option compilerVar="CC" /> | ||
53 | + </Unit> | ||
54 | + <Unit filename="aplc.h" /> | ||
55 | + <Unit filename="appres.h" /> | ||
56 | + <Unit filename="arpa_telnet.h" /> | ||
57 | + <Unit filename="cg.h" /> | ||
58 | + <Unit filename="charset.c"> | ||
59 | + <Option compilerVar="CC" /> | ||
60 | + </Unit> | ||
61 | + <Unit filename="charsetc.h" /> | ||
62 | + <Unit filename="childc.h" /> | ||
63 | + <Unit filename="control.in" /> | ||
64 | + <Unit filename="ctlr.c"> | ||
65 | + <Option compilerVar="CC" /> | ||
66 | + </Unit> | ||
67 | + <Unit filename="ctlr.h" /> | ||
68 | + <Unit filename="ctlrc.h" /> | ||
69 | + <Unit filename="dialogc.h" /> | ||
70 | + <Unit filename="falbacks.c"> | ||
71 | + <Option compilerVar="CC" /> | ||
72 | + </Unit> | ||
73 | + <Unit filename="ft.c"> | ||
74 | + <Option compilerVar="CC" /> | ||
75 | + </Unit> | ||
76 | + <Unit filename="ft_cut.c"> | ||
77 | + <Option compilerVar="CC" /> | ||
78 | + </Unit> | ||
79 | + <Unit filename="ft_cut_ds.h" /> | ||
80 | + <Unit filename="ft_cutc.h" /> | ||
81 | + <Unit filename="ft_dft.c"> | ||
82 | + <Option compilerVar="CC" /> | ||
83 | + </Unit> | ||
84 | + <Unit filename="ft_dft_ds.h" /> | ||
85 | + <Unit filename="ft_dftc.h" /> | ||
86 | + <Unit filename="ftc.h" /> | ||
87 | + <Unit filename="globals.h" /> | ||
88 | + <Unit filename="glue.c"> | ||
89 | + <Option compilerVar="CC" /> | ||
90 | + </Unit> | ||
91 | + <Unit filename="gluec.h" /> | ||
92 | + <Unit filename="host.c"> | ||
93 | + <Option compilerVar="CC" /> | ||
94 | + </Unit> | ||
95 | + <Unit filename="hostc.h" /> | ||
96 | + <Unit filename="icmdc.h" /> | ||
97 | + <Unit filename="keypadc.h" /> | ||
98 | + <Unit filename="kybd.c"> | ||
99 | + <Option compilerVar="CC" /> | ||
100 | + </Unit> | ||
101 | + <Unit filename="kybdc.h" /> | ||
102 | + <Unit filename="localdefs.h" /> | ||
103 | + <Unit filename="log.c"> | ||
104 | + <Option compilerVar="CC" /> | ||
105 | + </Unit> | ||
106 | + <Unit filename="macros.c"> | ||
107 | + <Option compilerVar="CC" /> | ||
108 | + </Unit> | ||
109 | + <Unit filename="menubarc.h" /> | ||
110 | + <Unit filename="mkversion.sh.in" /> | ||
111 | + <Unit filename="objects.h" /> | ||
112 | + <Unit filename="paste.c"> | ||
113 | + <Option compilerVar="CC" /> | ||
114 | + </Unit> | ||
115 | + <Unit filename="popupsc.h" /> | ||
116 | + <Unit filename="print.c"> | ||
117 | + <Option compilerVar="CC" /> | ||
118 | + </Unit> | ||
119 | + <Unit filename="printc.h" /> | ||
120 | + <Unit filename="printer.c"> | ||
121 | + <Option compilerVar="CC" /> | ||
122 | + </Unit> | ||
123 | + <Unit filename="printerc.h" /> | ||
124 | + <Unit filename="proxy.c"> | ||
125 | + <Option compilerVar="CC" /> | ||
126 | + </Unit> | ||
127 | + <Unit filename="proxyc.h" /> | ||
128 | + <Unit filename="resolver.c"> | ||
129 | + <Option compilerVar="CC" /> | ||
130 | + </Unit> | ||
131 | + <Unit filename="resolverc.h" /> | ||
132 | + <Unit filename="resources.c"> | ||
133 | + <Option compilerVar="CC" /> | ||
134 | + </Unit> | ||
135 | + <Unit filename="resources.h" /> | ||
136 | + <Unit filename="rpq.c"> | ||
137 | + <Option compilerVar="CC" /> | ||
138 | + </Unit> | ||
139 | + <Unit filename="savec.h" /> | ||
140 | + <Unit filename="screen.c"> | ||
141 | + <Option compilerVar="CC" /> | ||
142 | + </Unit> | ||
143 | + <Unit filename="screen.h" /> | ||
144 | + <Unit filename="screenc.h" /> | ||
145 | + <Unit filename="scrollc.h" /> | ||
146 | + <Unit filename="see.c"> | ||
147 | + <Option compilerVar="CC" /> | ||
148 | + </Unit> | ||
149 | + <Unit filename="seec.h" /> | ||
150 | + <Unit filename="selectc.h" /> | ||
151 | + <Unit filename="session.h" /> | ||
152 | + <Unit filename="sf.c"> | ||
153 | + <Option compilerVar="CC" /> | ||
154 | + </Unit> | ||
155 | + <Unit filename="sfc.h" /> | ||
156 | + <Unit filename="shlobj_missing.h" /> | ||
157 | + <Unit filename="statusc.h" /> | ||
158 | + <Unit filename="tables.c"> | ||
159 | + <Option compilerVar="CC" /> | ||
160 | + </Unit> | ||
161 | + <Unit filename="tablesc.h" /> | ||
162 | + <Unit filename="telnet.c"> | ||
163 | + <Option compilerVar="CC" /> | ||
164 | + </Unit> | ||
165 | + <Unit filename="telnetc.h" /> | ||
166 | + <Unit filename="tesprogram.c"> | ||
167 | + <Option compilerVar="CC" /> | ||
168 | + <Option target="Debug" /> | ||
169 | + </Unit> | ||
170 | + <Unit filename="tn3270e.h" /> | ||
171 | + <Unit filename="toggles.c"> | ||
172 | + <Option compilerVar="CC" /> | ||
173 | + </Unit> | ||
174 | + <Unit filename="togglesc.h" /> | ||
175 | + <Unit filename="trace_ds.c"> | ||
176 | + <Option compilerVar="CC" /> | ||
177 | + </Unit> | ||
178 | + <Unit filename="trace_dsc.h" /> | ||
179 | + <Unit filename="utf8.c"> | ||
180 | + <Option compilerVar="CC" /> | ||
181 | + </Unit> | ||
182 | + <Unit filename="utf8c.h" /> | ||
183 | + <Unit filename="util.c"> | ||
184 | + <Option compilerVar="CC" /> | ||
185 | + </Unit> | ||
186 | + <Unit filename="utilc.h" /> | ||
187 | + <Unit filename="version.c"> | ||
188 | + <Option compilerVar="CC" /> | ||
189 | + </Unit> | ||
190 | + <Unit filename="w3misc.c"> | ||
191 | + <Option compilerVar="CC" /> | ||
192 | + </Unit> | ||
193 | + <Unit filename="w3miscc.h" /> | ||
194 | + <Unit filename="widec.h" /> | ||
195 | + <Unit filename="winvers.c"> | ||
196 | + <Option compilerVar="CC" /> | ||
197 | + </Unit> | ||
198 | + <Unit filename="winversc.h" /> | ||
199 | + <Unit filename="xio.c"> | ||
200 | + <Option compilerVar="CC" /> | ||
201 | + </Unit> | ||
202 | + <Unit filename="xioc.h" /> | ||
203 | + <Unit filename="xl.h" /> | ||
204 | + <Extensions> | ||
205 | + <code_completion /> | ||
206 | + <envvars /> | ||
207 | + <debugger /> | ||
208 | + <lib_finder disable_auto="1" /> | ||
209 | + </Extensions> | ||
210 | + </Project> | ||
211 | +</CodeBlocks_project_file> |
src/lib/macros.c
@@ -59,12 +59,14 @@ | @@ -59,12 +59,14 @@ | ||
59 | return macro_list; | 59 | return macro_list; |
60 | } | 60 | } |
61 | 61 | ||
62 | +/* | ||
62 | static char * value_as_string(int val) | 63 | static char * value_as_string(int val) |
63 | { | 64 | { |
64 | char buffer[10]; | 65 | char buffer[10]; |
65 | snprintf(buffer,9,"%d",val); | 66 | snprintf(buffer,9,"%d",val); |
66 | return strdup(buffer); | 67 | return strdup(buffer); |
67 | } | 68 | } |
69 | +*/ | ||
68 | 70 | ||
69 | static const char * get_state(H3270 *h) | 71 | static const char * get_state(H3270 *h) |
70 | { | 72 | { |
@@ -313,6 +315,6 @@ | @@ -313,6 +315,6 @@ | ||
313 | 315 | ||
314 | LIB3270_MACRO( disconnect ) | 316 | LIB3270_MACRO( disconnect ) |
315 | { | 317 | { |
316 | - host_disconnect(hSession,0); | 318 | + lib3270_disconnect(hSession); |
317 | return strdup("0"); | 319 | return strdup("0"); |
318 | } | 320 | } |
src/lib/proxy.c
@@ -707,7 +707,7 @@ proxy_socks5(int fd, char *host, unsigned short port, int force_d) | @@ -707,7 +707,7 @@ proxy_socks5(int fd, char *host, unsigned short port, int force_d) | ||
707 | trace_dsn("SOCKS5 Proxy: xmit version 5 nmethods 1 (no auth)\n"); | 707 | trace_dsn("SOCKS5 Proxy: xmit version 5 nmethods 1 (no auth)\n"); |
708 | trace_netdata('>', rbuf, 3); | 708 | trace_netdata('>', rbuf, 3); |
709 | #endif /*]*/ | 709 | #endif /*]*/ |
710 | - if (send(fd, rbuf, 3, 0) < 0) { | 710 | + if (send(fd, (const char *) rbuf, 3, 0) < 0) { |
711 | popup_a_sockerr("SOCKS5 Proxy: send error"); | 711 | popup_a_sockerr("SOCKS5 Proxy: send error"); |
712 | return -1; | 712 | return -1; |
713 | } | 713 | } |
@@ -734,7 +734,7 @@ proxy_socks5(int fd, char *host, unsigned short port, int force_d) | @@ -734,7 +734,7 @@ proxy_socks5(int fd, char *host, unsigned short port, int force_d) | ||
734 | return -1; | 734 | return -1; |
735 | } | 735 | } |
736 | 736 | ||
737 | - nr = recv(fd, &rbuf[nread], 1, 0); | 737 | + nr = recv(fd, (char *) &rbuf[nread], 1, 0); |
738 | if (nr < 0) { | 738 | if (nr < 0) { |
739 | popup_a_sockerr("SOCKS5 Proxy: receive error"); | 739 | popup_a_sockerr("SOCKS5 Proxy: receive error"); |
740 | #if defined(X3270_TRACE) /*[*/ | 740 | #if defined(X3270_TRACE) /*[*/ |
@@ -839,7 +839,7 @@ proxy_socks5(int fd, char *host, unsigned short port, int force_d) | @@ -839,7 +839,7 @@ proxy_socks5(int fd, char *host, unsigned short port, int force_d) | ||
839 | return -1; | 839 | return -1; |
840 | } | 840 | } |
841 | 841 | ||
842 | - nr = recv(fd, &r, 1, 0); | 842 | + nr = recv(fd, (char *) &r, 1, 0); |
843 | if (nr < 0) { | 843 | if (nr < 0) { |
844 | popup_a_sockerr("SOCKS5 Proxy: receive error"); | 844 | popup_a_sockerr("SOCKS5 Proxy: receive error"); |
845 | #if defined(X3270_TRACE) /*[*/ | 845 | #if defined(X3270_TRACE) /*[*/ |
src/lib/tesprogram.c
1 | 1 | ||
2 | +#include <stdio.h> | ||
2 | #include <lib3270.h> | 3 | #include <lib3270.h> |
3 | 4 | ||
4 | int main(int numpar, char *param[]) | 5 | int main(int numpar, char *param[]) |
5 | { | 6 | { |
6 | H3270 *h; | 7 | H3270 *h; |
7 | 8 | ||
9 | + lib3270_initialize(); | ||
10 | + | ||
8 | h = lib3270_session_new(""); | 11 | h = lib3270_session_new(""); |
12 | + printf("3270 session %p created\n",h); | ||
9 | 13 | ||
10 | 14 | ||
11 | 15 | ||
12 | 16 | ||
17 | + printf("Ending 3270 session %p\n",h); | ||
13 | lib3270_session_free(h); | 18 | lib3270_session_free(h); |
14 | 19 | ||
15 | return 0; | 20 | return 0; |
src/lib/wide.c
@@ -1,530 +0,0 @@ | @@ -1,530 +0,0 @@ | ||
1 | -/* | ||
2 | - * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270 e X3270 | ||
3 | - * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a | ||
4 | - * aplicativos mainframe. Registro no INPI sob o nome G3270. Registro no INPI sob o nome G3270. | ||
5 | - * | ||
6 | - * Copyright (C) <2008> <Banco do Brasil S.A.> | ||
7 | - * | ||
8 | - * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob | ||
9 | - * os termos da GPL v.2 - Licença Pública Geral GNU, conforme publicado pela | ||
10 | - * Free Software Foundation. | ||
11 | - * | ||
12 | - * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER | ||
13 | - * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO | ||
14 | - * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para | ||
15 | - * obter mais detalhes. | ||
16 | - * | ||
17 | - * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este | ||
18 | - * programa; se não, escreva para a Free Software Foundation, Inc., 59 Temple | ||
19 | - * Place, Suite 330, Boston, MA, 02111-1307, USA | ||
20 | - * | ||
21 | - * Este programa está nomeado como wide.c e possui 530 linhas de código. | ||
22 | - * | ||
23 | - * Contatos: | ||
24 | - * | ||
25 | - * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck) | ||
26 | - * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça) | ||
27 | - * licinio@bb.com.br (Licínio Luis Branco) | ||
28 | - * kraucer@bb.com.br (Kraucer Fernandes Mazuco) | ||
29 | - * macmiranda@bb.com.br (Marco Aurélio Caldas Miranda) | ||
30 | - * | ||
31 | - */ | ||
32 | - | ||
33 | -/* | ||
34 | - * wide.c | ||
35 | - * A 3270 Terminal Emulator for X11 | ||
36 | - * Wide character translation functions. | ||
37 | - */ | ||
38 | - | ||
39 | -#include "globals.h" | ||
40 | -#include <errno.h> | ||
41 | -#include <locale.h> | ||
42 | -#include <langinfo.h> | ||
43 | - | ||
44 | -#include "3270ds.h" | ||
45 | -#if !defined(PR3287) /*[*/ | ||
46 | -#include "appres.h" | ||
47 | -#endif /*]*/ | ||
48 | - | ||
49 | -#include "popupsc.h" | ||
50 | -#include "tablesc.h" | ||
51 | -#include "trace_dsc.h" | ||
52 | -#if !defined(PR3287) /*[*/ | ||
53 | -#include "utilc.h" | ||
54 | -#endif /*]*/ | ||
55 | - | ||
56 | -#include "widec.h" | ||
57 | - | ||
58 | -#define ICU_DATA "ICU_DATA" | ||
59 | - | ||
60 | -char *local_encoding = CN; | ||
61 | - | ||
62 | -static UConverter *dbcs_converter = NULL; | ||
63 | -static char *dbcs_converter_name = CN; | ||
64 | -static UConverter *sbcs_converter = NULL; | ||
65 | -static char *sbcs_converter_name = CN; | ||
66 | -static UConverter *local_converter = NULL; | ||
67 | -#if defined(X3270_DISPLAY) /*[*/ | ||
68 | -static UConverter *wdisplay_converter = NULL; | ||
69 | -#endif /*]*/ | ||
70 | -static Boolean same_converter = False; | ||
71 | - | ||
72 | -/* Initialize, or reinitialize the EBCDIC DBCS converters. */ | ||
73 | -int | ||
74 | -wide_init(char *converter_names, char *local_name) | ||
75 | -{ | ||
76 | - UErrorCode err = U_ZERO_ERROR; | ||
77 | - char *cur_path = CN; | ||
78 | - Boolean lib_ok = False; | ||
79 | - Boolean dot_ok = False; | ||
80 | - char *cn_copy, *buf, *token; | ||
81 | - char *sbcs_converters = NULL; | ||
82 | - char *dbcs_converters = NULL; | ||
83 | - int n_converter_sets = 0; | ||
84 | - int n_sbcs_converters = 0; | ||
85 | - int n_dbcs_converters = 0; | ||
86 | - | ||
87 | - /* This may be a reinit. */ | ||
88 | - if (local_converter != NULL) { | ||
89 | - ucnv_close(local_converter); | ||
90 | - local_converter = NULL; | ||
91 | - } | ||
92 | - Replace(local_encoding, CN); | ||
93 | - if (sbcs_converter != NULL) { | ||
94 | - ucnv_close(sbcs_converter); | ||
95 | - sbcs_converter = NULL; | ||
96 | - } | ||
97 | - Replace(sbcs_converter_name, CN); | ||
98 | - if (dbcs_converter != NULL) { | ||
99 | - ucnv_close(dbcs_converter); | ||
100 | - dbcs_converter = NULL; | ||
101 | - } | ||
102 | - Replace(dbcs_converter_name, CN); | ||
103 | -#if defined(X3270_DISPLAY) /*[*/ | ||
104 | - if (wdisplay_converter != NULL) { | ||
105 | - ucnv_close(wdisplay_converter); | ||
106 | - wdisplay_converter = NULL; | ||
107 | - } | ||
108 | -#endif /*]*/ | ||
109 | - same_converter = False; | ||
110 | - | ||
111 | - /* Make sure that $ICU_DATA has LIBX3270DIR and . in it. */ | ||
112 | - cur_path = getenv(ICU_DATA); | ||
113 | - if (cur_path != CN) { | ||
114 | - char *t = NewString(cur_path); | ||
115 | - char *token; | ||
116 | - char *buf = t; | ||
117 | - | ||
118 | - while (!(lib_ok && dot_ok) && | ||
119 | - (token = strtok(buf, ":")) != CN) { | ||
120 | - buf = CN; | ||
121 | - if (!strcmp(token, LIBX3270DIR)) { | ||
122 | - lib_ok = True; | ||
123 | - } else if (!strcmp(token, ".")) { | ||
124 | - dot_ok = True; | ||
125 | - } | ||
126 | - } | ||
127 | - Free(t); | ||
128 | - } | ||
129 | - if (!lib_ok || !dot_ok) { | ||
130 | - char *s, *new_path; | ||
131 | - | ||
132 | - s = new_path = Malloc(strlen(ICU_DATA) + | ||
133 | - (cur_path? strlen(cur_path): 0) + | ||
134 | - strlen(LIBX3270DIR) + 5 /* ICU_DATA=*:*:.\n */); | ||
135 | - | ||
136 | - s += sprintf(s, "%s=", ICU_DATA); | ||
137 | - if (cur_path != CN) | ||
138 | - s += sprintf(s, "%s", cur_path); | ||
139 | - if (!lib_ok) { | ||
140 | - if (s[-1] != '=' && s[-1] != ':') | ||
141 | - *s++ = ':'; | ||
142 | - s += sprintf(s, "%s", LIBX3270DIR); | ||
143 | - } | ||
144 | - if (!dot_ok) { | ||
145 | - if (s[-1] != '=' && s[-1] != ':') | ||
146 | - *s++ = ':'; | ||
147 | - *s++ = '.'; | ||
148 | - } | ||
149 | - *s = '\0'; | ||
150 | - if (putenv(new_path) < 0) { | ||
151 | - popup_an_errno(errno, "putenv for " ICU_DATA " failed"); | ||
152 | - return -1; | ||
153 | - } | ||
154 | - } | ||
155 | - | ||
156 | - /* Decode local converter name. */ | ||
157 | - if (local_name == CN) { | ||
158 | - (void) setlocale(LC_CTYPE, ""); | ||
159 | - local_name = nl_langinfo(CODESET); | ||
160 | - } | ||
161 | - if (local_name != CN) { | ||
162 | - err = U_ZERO_ERROR; | ||
163 | - local_converter = ucnv_open(local_name, &err); | ||
164 | - if (local_converter == NULL) { | ||
165 | - popup_an_error("Cannot find ICU converter for " | ||
166 | - "local encoding:\n%s", | ||
167 | - local_name); | ||
168 | - } | ||
169 | - Replace(local_encoding, NewString(local_name)); | ||
170 | - } | ||
171 | - | ||
172 | - /* Decode host and display converter names. */ | ||
173 | - if (converter_names == CN) | ||
174 | - return 0; | ||
175 | - | ||
176 | - /* | ||
177 | - * Split into SBCS and DBCS converters, separated by '+'. If only one | ||
178 | - * converter is specified, it's the DBCS converter. | ||
179 | - */ | ||
180 | - n_converter_sets = 0; | ||
181 | - buf = cn_copy = NewString(converter_names); | ||
182 | - while ((token = strtok(buf, "+")) != CN) { | ||
183 | - buf = CN; | ||
184 | - switch (n_converter_sets) { | ||
185 | - case 0: /* DBCS or SBCS */ | ||
186 | - dbcs_converters = token; | ||
187 | - break; | ||
188 | - case 1: /* DBCS */ | ||
189 | - sbcs_converters = dbcs_converters; | ||
190 | - dbcs_converters = token; | ||
191 | - break; | ||
192 | - default: /* extra */ | ||
193 | - popup_an_error("Extra converter set '%s' ignored", token); | ||
194 | - break; | ||
195 | - } | ||
196 | - n_converter_sets++; | ||
197 | - } | ||
198 | - | ||
199 | - if (sbcs_converters != NULL) { | ||
200 | - n_sbcs_converters = 0; | ||
201 | - buf = sbcs_converters; | ||
202 | - while ((token = strtok(buf, ",")) != CN) { | ||
203 | - buf = CN; | ||
204 | - switch (n_sbcs_converters) { | ||
205 | - case 0: /* EBCDIC */ | ||
206 | - err = U_ZERO_ERROR; | ||
207 | - sbcs_converter = ucnv_open(token, &err); | ||
208 | - if (sbcs_converter == NULL) { | ||
209 | - popup_an_error("Cannot find ICU converter " | ||
210 | - "for host SBCS:\n%s", token); | ||
211 | - Free(cn_copy); | ||
212 | - return -1; | ||
213 | - } | ||
214 | - Replace(sbcs_converter_name, NewString(token)); | ||
215 | - break; | ||
216 | - default: /* extra */ | ||
217 | - popup_an_error("Extra converter name '%s' ignored", | ||
218 | - token); | ||
219 | - break; | ||
220 | - } | ||
221 | - n_sbcs_converters++; | ||
222 | - } | ||
223 | - } | ||
224 | - | ||
225 | - if (dbcs_converters != NULL) { | ||
226 | - n_dbcs_converters = 0; | ||
227 | - buf = dbcs_converters; | ||
228 | - while ((token = strtok(buf, ",")) != CN) { | ||
229 | - buf = CN; | ||
230 | - switch (n_dbcs_converters) { | ||
231 | - case 0: /* EBCDIC */ | ||
232 | - err = U_ZERO_ERROR; | ||
233 | - dbcs_converter = ucnv_open(token, &err); | ||
234 | - if (dbcs_converter == NULL) { | ||
235 | - popup_an_error("Cannot find ICU converter " | ||
236 | - "for host DBCS:\n%s", token); | ||
237 | - Free(cn_copy); | ||
238 | - return -1; | ||
239 | - } | ||
240 | - Replace(dbcs_converter_name, NewString(token)); | ||
241 | - break; | ||
242 | - case 1: /* display */ | ||
243 | -#if defined(X3270_DISPLAY) /*[*/ | ||
244 | - err = U_ZERO_ERROR; | ||
245 | - wdisplay_converter = ucnv_open(token, &err); | ||
246 | - if (wdisplay_converter == NULL) { | ||
247 | - popup_an_error("Cannot find ICU converter " | ||
248 | - "for display DBCS:\n%s", token); | ||
249 | - Free(cn_copy); | ||
250 | - return -1; | ||
251 | - } | ||
252 | -#endif /*]*/ | ||
253 | - break; | ||
254 | - default: /* extra */ | ||
255 | - popup_an_error("Extra converter name '%s' ignored", | ||
256 | - token); | ||
257 | - break; | ||
258 | - } | ||
259 | - n_dbcs_converters++; | ||
260 | - } | ||
261 | - } | ||
262 | - | ||
263 | - Free(cn_copy); | ||
264 | - | ||
265 | - if (n_dbcs_converters < 2) { | ||
266 | - popup_an_error("Missing DBCS converter value"); | ||
267 | - return -1; | ||
268 | - } | ||
269 | - if (dbcs_converter_name != CN && | ||
270 | - sbcs_converter_name != CN && | ||
271 | - !strcmp(dbcs_converter_name, sbcs_converter_name)) { | ||
272 | - same_converter = True; | ||
273 | - } | ||
274 | - | ||
275 | - return 0; | ||
276 | -} | ||
277 | - | ||
278 | -static void | ||
279 | -xlate1(unsigned char from0, unsigned char from1, unsigned char to_buf[], | ||
280 | - UConverter *from_cnv, const char *from_name, | ||
281 | - UConverter *to_cnv, const char *to_name) | ||
282 | -{ | ||
283 | - UErrorCode err = U_ZERO_ERROR; | ||
284 | - UChar Ubuf[2]; | ||
285 | - char from_buf[4]; | ||
286 | - int from_len; | ||
287 | - char tmp_to_buf[3]; | ||
288 | - int32_t len; | ||
289 | -#if defined(WIDE_DEBUG) /*[*/ | ||
290 | - int i; | ||
291 | -#endif /*]*/ | ||
292 | - | ||
293 | - /* Do something reasonable in case of failure. */ | ||
294 | - to_buf[0] = to_buf[1] = 0; | ||
295 | - | ||
296 | - /* Convert string from source to Unicode. */ | ||
297 | - if (same_converter) { | ||
298 | - from_buf[0] = EBC_so; | ||
299 | - from_buf[1] = from0; | ||
300 | - from_buf[2] = from1; | ||
301 | - from_buf[3] = EBC_si; | ||
302 | - from_len = 4; | ||
303 | - } else { | ||
304 | - from_buf[0] = from0; | ||
305 | - from_buf[1] = from1; | ||
306 | - from_len = 2; | ||
307 | - } | ||
308 | - len = ucnv_toUChars(from_cnv, Ubuf, 2, from_buf, from_len, &err); | ||
309 | - if (err != U_ZERO_ERROR) { | ||
310 | - trace_ds("[%s toUnicode of DBCS X'%02x%02x' failed, ICU " | ||
311 | - "error %d]\n", from_name, from0, from1, (int)err); | ||
312 | - return; | ||
313 | - } | ||
314 | - if (Ubuf[0] == 0xfffd) { | ||
315 | - /* No translation. */ | ||
316 | - trace_ds("[%s toUnicode of DBCS X'%02x%02x' failed]\n", | ||
317 | - from_name, from0, from1); | ||
318 | - return; | ||
319 | - } | ||
320 | -#if defined(WIDE_DEBUG) /*[*/ | ||
321 | - printf("Got Unicode %x\n", Ubuf[0]); | ||
322 | -#endif /*]*/ | ||
323 | - | ||
324 | - if (to_cnv != NULL) { | ||
325 | - /* Convert string from Unicode to Destination. */ | ||
326 | - len = ucnv_fromUChars(to_cnv, tmp_to_buf, 3, Ubuf, len, &err); | ||
327 | - if (err != U_ZERO_ERROR) { | ||
328 | - trace_ds("[fromUnicode of U+%04x to %s failed, ICU " | ||
329 | - "error %d]\n", Ubuf[0], to_name, (int)err); | ||
330 | - return; | ||
331 | - } | ||
332 | - to_buf[0] = tmp_to_buf[0]; | ||
333 | - to_buf[1] = tmp_to_buf[1]; | ||
334 | -#if defined(WIDE_DEBUG) /*[*/ | ||
335 | - printf("Got %u %s characters:", len, to_name); | ||
336 | - for (i = 0; i < len; i++) { | ||
337 | - printf(" %02x", to_buf[i]); | ||
338 | - } | ||
339 | - printf("\n"); | ||
340 | -#endif /*]*/ | ||
341 | - } else { | ||
342 | - to_buf[0] = (Ubuf[0] >> 8) & 0xff; | ||
343 | - to_buf[1] = Ubuf[0] & 0xff; | ||
344 | - } | ||
345 | -} | ||
346 | - | ||
347 | -#if defined(X3270_DISPLAY) /*[*/ | ||
348 | -/* Translate a DBCS EBCDIC character to a display character. */ | ||
349 | -void | ||
350 | -dbcs_to_display(unsigned char ebc1, unsigned char ebc2, unsigned char c[]) | ||
351 | -{ | ||
352 | - xlate1(ebc1, ebc2, c, dbcs_converter, "host DBCS", wdisplay_converter, | ||
353 | - "wide display"); | ||
354 | -} | ||
355 | -#endif /*]*/ | ||
356 | - | ||
357 | -/* Translate a DBCS EBCDIC character to a 2-byte Unicode character. */ | ||
358 | -void | ||
359 | -dbcs_to_unicode16(unsigned char ebc1, unsigned char ebc2, unsigned char c[]) | ||
360 | -{ | ||
361 | - xlate1(ebc1, ebc2, c, dbcs_converter, "host DBCS", NULL, NULL); | ||
362 | -} | ||
363 | - | ||
364 | -/* | ||
365 | - * Translate a DBCS EBCDIC character to a local multi-byte character. | ||
366 | - * Returns -1 for error, or the mb length. NULL terminates. | ||
367 | - */ | ||
368 | -int | ||
369 | -dbcs_to_mb(unsigned char ebc1, unsigned char ebc2, char *mb) | ||
370 | -{ | ||
371 | - UErrorCode err = U_ZERO_ERROR; | ||
372 | - unsigned char w[2]; | ||
373 | - UChar Ubuf; | ||
374 | - int len; | ||
375 | - | ||
376 | - if (local_converter == NULL) { | ||
377 | - *mb = '?'; | ||
378 | - *(mb + 1) = '\0'; | ||
379 | - return 1; | ||
380 | - } | ||
381 | - | ||
382 | - /* Translate to Unicode first. */ | ||
383 | - dbcs_to_unicode16(ebc1, ebc2, w); | ||
384 | - Ubuf = (w[0] << 8) | w[1]; | ||
385 | - | ||
386 | - /* Then translate to the local encoding. */ | ||
387 | - len = ucnv_fromUChars(local_converter, mb, 16, &Ubuf, 1, &err); | ||
388 | - if (err != U_ZERO_ERROR) { | ||
389 | - trace_ds("[fromUnicode of U+%04x to local failed, ICU " | ||
390 | - "error %d]\n", Ubuf, (int)err); | ||
391 | - return -1; | ||
392 | - } | ||
393 | - return len; | ||
394 | -} | ||
395 | - | ||
396 | -/* | ||
397 | - * Translate an SBCS EBCDIC character to a local multi-byte character. | ||
398 | - * Returns -1 for error, or the mb length. NULL terminates. | ||
399 | - */ | ||
400 | -int | ||
401 | -sbcs_to_mb(unsigned char ebc, char *mb) | ||
402 | -{ | ||
403 | - UErrorCode err = U_ZERO_ERROR; | ||
404 | - UChar Ubuf; | ||
405 | - int len; | ||
406 | - | ||
407 | - if (sbcs_converter == NULL) { | ||
408 | - /* No SBCS converter, do EBCDIC to latin-1. */ | ||
409 | - if (local_converter == NULL) { | ||
410 | - /* No local converter either, latin-1 is it. */ | ||
411 | - *mb = ebc2asc[ebc]; | ||
412 | - *(mb + 1) = '\0'; | ||
413 | - return 1; | ||
414 | - } | ||
415 | - | ||
416 | - /* Have a local converter; use it below. */ | ||
417 | - Ubuf = ebc2asc[ebc]; | ||
418 | - } else { | ||
419 | - /* Have an SBCS converter. Convert from SBCS to Unicode. */ | ||
420 | - err = U_ZERO_ERROR; | ||
421 | - len = ucnv_toUChars(sbcs_converter, &Ubuf, 1, (char *)&ebc, 1, | ||
422 | - &err); | ||
423 | - if (err != U_ZERO_ERROR && | ||
424 | - err != U_STRING_NOT_TERMINATED_WARNING) { | ||
425 | - trace_ds("[toUChars failed, ICU error %d]\n", | ||
426 | - (int)err); | ||
427 | - return -1; | ||
428 | - } | ||
429 | - } | ||
430 | - | ||
431 | - /* Convert from Unicode to the local encoding. */ | ||
432 | - len = ucnv_fromUChars(local_converter, mb, 16, &Ubuf, 1, &err); | ||
433 | - if (err != U_ZERO_ERROR) { | ||
434 | - trace_ds("[fromUnicode of U+%04x to local failed, ICU " | ||
435 | - "error %d]\n", Ubuf, (int)err); | ||
436 | - return -1; | ||
437 | - } | ||
438 | - return len; | ||
439 | -} | ||
440 | - | ||
441 | -/* | ||
442 | - * Translate a local multi-byte string to Unicode characters. | ||
443 | - * Returns -1 for error, or the length. NULL terminates. | ||
444 | - */ | ||
445 | -int | ||
446 | -mb_to_unicode(char *mb, int mblen, UChar *u, int ulen, UErrorCode *err) | ||
447 | -{ | ||
448 | - UErrorCode local_err; | ||
449 | - int len; | ||
450 | - Boolean print_errs = False; | ||
451 | - | ||
452 | - if (local_converter == NULL) { | ||
453 | - int i; | ||
454 | - | ||
455 | - for (i = 0; i < mblen; i++) { | ||
456 | - u[i] = mb[i] & 0xff; | ||
457 | - } | ||
458 | - return mblen; | ||
459 | - } | ||
460 | - if (err == NULL) { | ||
461 | - err = &local_err; | ||
462 | - print_errs = True; | ||
463 | - } | ||
464 | - *err = U_ZERO_ERROR; | ||
465 | - len = ucnv_toUChars(local_converter, u, ulen, mb, mblen, err); | ||
466 | - if (*err != U_ZERO_ERROR && *err != U_STRING_NOT_TERMINATED_WARNING) { | ||
467 | - if (print_errs) | ||
468 | - trace_ds("[toUChars failed, ICU error %d]\n", | ||
469 | - (int)*err); | ||
470 | - return -1; | ||
471 | - } | ||
472 | - return len; | ||
473 | -} | ||
474 | - | ||
475 | -/* | ||
476 | - * Try to map a Unicode character to the Host SBCS character set. | ||
477 | - * Returns ASCII in cp[0]. | ||
478 | - */ | ||
479 | -int | ||
480 | -dbcs_map8(UChar u, unsigned char *cp) | ||
481 | -{ | ||
482 | - UErrorCode err = U_ZERO_ERROR; | ||
483 | - int len; | ||
484 | - | ||
485 | - if (!(u & ~0xff)) { | ||
486 | - *cp = u; | ||
487 | - return 1; | ||
488 | - } | ||
489 | - if (sbcs_converter != NULL) { | ||
490 | - len = ucnv_fromUChars(sbcs_converter, (char *)cp, 1, &u, 1, | ||
491 | - &err); | ||
492 | - if ((err != U_ZERO_ERROR && | ||
493 | - err != U_STRING_NOT_TERMINATED_WARNING) || | ||
494 | - (*cp == '?' && u != '?')) { | ||
495 | - *cp = ebc2asc[*cp]; | ||
496 | - return 0; | ||
497 | - } else | ||
498 | - return 1; | ||
499 | - } | ||
500 | - return 0; | ||
501 | -} | ||
502 | - | ||
503 | -/* | ||
504 | - * Try to map a Unicode character to the Host DBCS character set. | ||
505 | - * Returns EBCDIC in cp[]. | ||
506 | - */ | ||
507 | -int | ||
508 | -dbcs_map16(UChar u, unsigned char *cp) | ||
509 | -{ | ||
510 | - UErrorCode err = U_ZERO_ERROR; | ||
511 | - int len; | ||
512 | - | ||
513 | - if (same_converter) { | ||
514 | - char tmp_cp[5]; | ||
515 | - | ||
516 | - len = ucnv_fromUChars(dbcs_converter, tmp_cp, 5, &u, 1, &err); | ||
517 | - if (err != U_ZERO_ERROR || | ||
518 | - len < 3 || | ||
519 | - tmp_cp[0] != EBC_so) | ||
520 | - return 0; | ||
521 | - cp[0] = tmp_cp[1]; | ||
522 | - cp[1] = tmp_cp[2]; | ||
523 | - return 1; | ||
524 | - } else { | ||
525 | - len = ucnv_fromUChars(dbcs_converter, (char *)cp, 2, &u, 1, | ||
526 | - &err); | ||
527 | - return (err == U_ZERO_ERROR || | ||
528 | - err == U_STRING_NOT_TERMINATED_WARNING); | ||
529 | - } | ||
530 | -} |
@@ -0,0 +1,530 @@ | @@ -0,0 +1,530 @@ | ||
1 | +/* | ||
2 | + * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270 e X3270 | ||
3 | + * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a | ||
4 | + * aplicativos mainframe. Registro no INPI sob o nome G3270. Registro no INPI sob o nome G3270. | ||
5 | + * | ||
6 | + * Copyright (C) <2008> <Banco do Brasil S.A.> | ||
7 | + * | ||
8 | + * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob | ||
9 | + * os termos da GPL v.2 - Licença Pública Geral GNU, conforme publicado pela | ||
10 | + * Free Software Foundation. | ||
11 | + * | ||
12 | + * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER | ||
13 | + * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO | ||
14 | + * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para | ||
15 | + * obter mais detalhes. | ||
16 | + * | ||
17 | + * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este | ||
18 | + * programa; se não, escreva para a Free Software Foundation, Inc., 59 Temple | ||
19 | + * Place, Suite 330, Boston, MA, 02111-1307, USA | ||
20 | + * | ||
21 | + * Este programa está nomeado como wide.c e possui 530 linhas de código. | ||
22 | + * | ||
23 | + * Contatos: | ||
24 | + * | ||
25 | + * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck) | ||
26 | + * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça) | ||
27 | + * licinio@bb.com.br (Licínio Luis Branco) | ||
28 | + * kraucer@bb.com.br (Kraucer Fernandes Mazuco) | ||
29 | + * macmiranda@bb.com.br (Marco Aurélio Caldas Miranda) | ||
30 | + * | ||
31 | + */ | ||
32 | + | ||
33 | +/* | ||
34 | + * wide.c | ||
35 | + * A 3270 Terminal Emulator for X11 | ||
36 | + * Wide character translation functions. | ||
37 | + */ | ||
38 | + | ||
39 | +#include "globals.h" | ||
40 | +#include <errno.h> | ||
41 | +#include <locale.h> | ||
42 | +#include <langinfo.h> | ||
43 | + | ||
44 | +#include "3270ds.h" | ||
45 | +#if !defined(PR3287) /*[*/ | ||
46 | +#include "appres.h" | ||
47 | +#endif /*]*/ | ||
48 | + | ||
49 | +#include "popupsc.h" | ||
50 | +#include "tablesc.h" | ||
51 | +#include "trace_dsc.h" | ||
52 | +#if !defined(PR3287) /*[*/ | ||
53 | +#include "utilc.h" | ||
54 | +#endif /*]*/ | ||
55 | + | ||
56 | +#include "widec.h" | ||
57 | + | ||
58 | +#define ICU_DATA "ICU_DATA" | ||
59 | + | ||
60 | +char *local_encoding = CN; | ||
61 | + | ||
62 | +static UConverter *dbcs_converter = NULL; | ||
63 | +static char *dbcs_converter_name = CN; | ||
64 | +static UConverter *sbcs_converter = NULL; | ||
65 | +static char *sbcs_converter_name = CN; | ||
66 | +static UConverter *local_converter = NULL; | ||
67 | +#if defined(X3270_DISPLAY) /*[*/ | ||
68 | +static UConverter *wdisplay_converter = NULL; | ||
69 | +#endif /*]*/ | ||
70 | +static Boolean same_converter = False; | ||
71 | + | ||
72 | +/* Initialize, or reinitialize the EBCDIC DBCS converters. */ | ||
73 | +int | ||
74 | +wide_init(char *converter_names, char *local_name) | ||
75 | +{ | ||
76 | + UErrorCode err = U_ZERO_ERROR; | ||
77 | + char *cur_path = CN; | ||
78 | + Boolean lib_ok = False; | ||
79 | + Boolean dot_ok = False; | ||
80 | + char *cn_copy, *buf, *token; | ||
81 | + char *sbcs_converters = NULL; | ||
82 | + char *dbcs_converters = NULL; | ||
83 | + int n_converter_sets = 0; | ||
84 | + int n_sbcs_converters = 0; | ||
85 | + int n_dbcs_converters = 0; | ||
86 | + | ||
87 | + /* This may be a reinit. */ | ||
88 | + if (local_converter != NULL) { | ||
89 | + ucnv_close(local_converter); | ||
90 | + local_converter = NULL; | ||
91 | + } | ||
92 | + Replace(local_encoding, CN); | ||
93 | + if (sbcs_converter != NULL) { | ||
94 | + ucnv_close(sbcs_converter); | ||
95 | + sbcs_converter = NULL; | ||
96 | + } | ||
97 | + Replace(sbcs_converter_name, CN); | ||
98 | + if (dbcs_converter != NULL) { | ||
99 | + ucnv_close(dbcs_converter); | ||
100 | + dbcs_converter = NULL; | ||
101 | + } | ||
102 | + Replace(dbcs_converter_name, CN); | ||
103 | +#if defined(X3270_DISPLAY) /*[*/ | ||
104 | + if (wdisplay_converter != NULL) { | ||
105 | + ucnv_close(wdisplay_converter); | ||
106 | + wdisplay_converter = NULL; | ||
107 | + } | ||
108 | +#endif /*]*/ | ||
109 | + same_converter = False; | ||
110 | + | ||
111 | + /* Make sure that $ICU_DATA has LIBX3270DIR and . in it. */ | ||
112 | + cur_path = getenv(ICU_DATA); | ||
113 | + if (cur_path != CN) { | ||
114 | + char *t = NewString(cur_path); | ||
115 | + char *token; | ||
116 | + char *buf = t; | ||
117 | + | ||
118 | + while (!(lib_ok && dot_ok) && | ||
119 | + (token = strtok(buf, ":")) != CN) { | ||
120 | + buf = CN; | ||
121 | + if (!strcmp(token, LIBX3270DIR)) { | ||
122 | + lib_ok = True; | ||
123 | + } else if (!strcmp(token, ".")) { | ||
124 | + dot_ok = True; | ||
125 | + } | ||
126 | + } | ||
127 | + Free(t); | ||
128 | + } | ||
129 | + if (!lib_ok || !dot_ok) { | ||
130 | + char *s, *new_path; | ||
131 | + | ||
132 | + s = new_path = Malloc(strlen(ICU_DATA) + | ||
133 | + (cur_path? strlen(cur_path): 0) + | ||
134 | + strlen(LIBX3270DIR) + 5 /* ICU_DATA=*:*:.\n */); | ||
135 | + | ||
136 | + s += sprintf(s, "%s=", ICU_DATA); | ||
137 | + if (cur_path != CN) | ||
138 | + s += sprintf(s, "%s", cur_path); | ||
139 | + if (!lib_ok) { | ||
140 | + if (s[-1] != '=' && s[-1] != ':') | ||
141 | + *s++ = ':'; | ||
142 | + s += sprintf(s, "%s", LIBX3270DIR); | ||
143 | + } | ||
144 | + if (!dot_ok) { | ||
145 | + if (s[-1] != '=' && s[-1] != ':') | ||
146 | + *s++ = ':'; | ||
147 | + *s++ = '.'; | ||
148 | + } | ||
149 | + *s = '\0'; | ||
150 | + if (putenv(new_path) < 0) { | ||
151 | + popup_an_errno(errno, "putenv for " ICU_DATA " failed"); | ||
152 | + return -1; | ||
153 | + } | ||
154 | + } | ||
155 | + | ||
156 | + /* Decode local converter name. */ | ||
157 | + if (local_name == CN) { | ||
158 | + (void) setlocale(LC_CTYPE, ""); | ||
159 | + local_name = nl_langinfo(CODESET); | ||
160 | + } | ||
161 | + if (local_name != CN) { | ||
162 | + err = U_ZERO_ERROR; | ||
163 | + local_converter = ucnv_open(local_name, &err); | ||
164 | + if (local_converter == NULL) { | ||
165 | + popup_an_error("Cannot find ICU converter for " | ||
166 | + "local encoding:\n%s", | ||
167 | + local_name); | ||
168 | + } | ||
169 | + Replace(local_encoding, NewString(local_name)); | ||
170 | + } | ||
171 | + | ||
172 | + /* Decode host and display converter names. */ | ||
173 | + if (converter_names == CN) | ||
174 | + return 0; | ||
175 | + | ||
176 | + /* | ||
177 | + * Split into SBCS and DBCS converters, separated by '+'. If only one | ||
178 | + * converter is specified, it's the DBCS converter. | ||
179 | + */ | ||
180 | + n_converter_sets = 0; | ||
181 | + buf = cn_copy = NewString(converter_names); | ||
182 | + while ((token = strtok(buf, "+")) != CN) { | ||
183 | + buf = CN; | ||
184 | + switch (n_converter_sets) { | ||
185 | + case 0: /* DBCS or SBCS */ | ||
186 | + dbcs_converters = token; | ||
187 | + break; | ||
188 | + case 1: /* DBCS */ | ||
189 | + sbcs_converters = dbcs_converters; | ||
190 | + dbcs_converters = token; | ||
191 | + break; | ||
192 | + default: /* extra */ | ||
193 | + popup_an_error("Extra converter set '%s' ignored", token); | ||
194 | + break; | ||
195 | + } | ||
196 | + n_converter_sets++; | ||
197 | + } | ||
198 | + | ||
199 | + if (sbcs_converters != NULL) { | ||
200 | + n_sbcs_converters = 0; | ||
201 | + buf = sbcs_converters; | ||
202 | + while ((token = strtok(buf, ",")) != CN) { | ||
203 | + buf = CN; | ||
204 | + switch (n_sbcs_converters) { | ||
205 | + case 0: /* EBCDIC */ | ||
206 | + err = U_ZERO_ERROR; | ||
207 | + sbcs_converter = ucnv_open(token, &err); | ||
208 | + if (sbcs_converter == NULL) { | ||
209 | + popup_an_error("Cannot find ICU converter " | ||
210 | + "for host SBCS:\n%s", token); | ||
211 | + Free(cn_copy); | ||
212 | + return -1; | ||
213 | + } | ||
214 | + Replace(sbcs_converter_name, NewString(token)); | ||
215 | + break; | ||
216 | + default: /* extra */ | ||
217 | + popup_an_error("Extra converter name '%s' ignored", | ||
218 | + token); | ||
219 | + break; | ||
220 | + } | ||
221 | + n_sbcs_converters++; | ||
222 | + } | ||
223 | + } | ||
224 | + | ||
225 | + if (dbcs_converters != NULL) { | ||
226 | + n_dbcs_converters = 0; | ||
227 | + buf = dbcs_converters; | ||
228 | + while ((token = strtok(buf, ",")) != CN) { | ||
229 | + buf = CN; | ||
230 | + switch (n_dbcs_converters) { | ||
231 | + case 0: /* EBCDIC */ | ||
232 | + err = U_ZERO_ERROR; | ||
233 | + dbcs_converter = ucnv_open(token, &err); | ||
234 | + if (dbcs_converter == NULL) { | ||
235 | + popup_an_error("Cannot find ICU converter " | ||
236 | + "for host DBCS:\n%s", token); | ||
237 | + Free(cn_copy); | ||
238 | + return -1; | ||
239 | + } | ||
240 | + Replace(dbcs_converter_name, NewString(token)); | ||
241 | + break; | ||
242 | + case 1: /* display */ | ||
243 | +#if defined(X3270_DISPLAY) /*[*/ | ||
244 | + err = U_ZERO_ERROR; | ||
245 | + wdisplay_converter = ucnv_open(token, &err); | ||
246 | + if (wdisplay_converter == NULL) { | ||
247 | + popup_an_error("Cannot find ICU converter " | ||
248 | + "for display DBCS:\n%s", token); | ||
249 | + Free(cn_copy); | ||
250 | + return -1; | ||
251 | + } | ||
252 | +#endif /*]*/ | ||
253 | + break; | ||
254 | + default: /* extra */ | ||
255 | + popup_an_error("Extra converter name '%s' ignored", | ||
256 | + token); | ||
257 | + break; | ||
258 | + } | ||
259 | + n_dbcs_converters++; | ||
260 | + } | ||
261 | + } | ||
262 | + | ||
263 | + Free(cn_copy); | ||
264 | + | ||
265 | + if (n_dbcs_converters < 2) { | ||
266 | + popup_an_error("Missing DBCS converter value"); | ||
267 | + return -1; | ||
268 | + } | ||
269 | + if (dbcs_converter_name != CN && | ||
270 | + sbcs_converter_name != CN && | ||
271 | + !strcmp(dbcs_converter_name, sbcs_converter_name)) { | ||
272 | + same_converter = True; | ||
273 | + } | ||
274 | + | ||
275 | + return 0; | ||
276 | +} | ||
277 | + | ||
278 | +static void | ||
279 | +xlate1(unsigned char from0, unsigned char from1, unsigned char to_buf[], | ||
280 | + UConverter *from_cnv, const char *from_name, | ||
281 | + UConverter *to_cnv, const char *to_name) | ||
282 | +{ | ||
283 | + UErrorCode err = U_ZERO_ERROR; | ||
284 | + UChar Ubuf[2]; | ||
285 | + char from_buf[4]; | ||
286 | + int from_len; | ||
287 | + char tmp_to_buf[3]; | ||
288 | + int32_t len; | ||
289 | +#if defined(WIDE_DEBUG) /*[*/ | ||
290 | + int i; | ||
291 | +#endif /*]*/ | ||
292 | + | ||
293 | + /* Do something reasonable in case of failure. */ | ||
294 | + to_buf[0] = to_buf[1] = 0; | ||
295 | + | ||
296 | + /* Convert string from source to Unicode. */ | ||
297 | + if (same_converter) { | ||
298 | + from_buf[0] = EBC_so; | ||
299 | + from_buf[1] = from0; | ||
300 | + from_buf[2] = from1; | ||
301 | + from_buf[3] = EBC_si; | ||
302 | + from_len = 4; | ||
303 | + } else { | ||
304 | + from_buf[0] = from0; | ||
305 | + from_buf[1] = from1; | ||
306 | + from_len = 2; | ||
307 | + } | ||
308 | + len = ucnv_toUChars(from_cnv, Ubuf, 2, from_buf, from_len, &err); | ||
309 | + if (err != U_ZERO_ERROR) { | ||
310 | + trace_ds("[%s toUnicode of DBCS X'%02x%02x' failed, ICU " | ||
311 | + "error %d]\n", from_name, from0, from1, (int)err); | ||
312 | + return; | ||
313 | + } | ||
314 | + if (Ubuf[0] == 0xfffd) { | ||
315 | + /* No translation. */ | ||
316 | + trace_ds("[%s toUnicode of DBCS X'%02x%02x' failed]\n", | ||
317 | + from_name, from0, from1); | ||
318 | + return; | ||
319 | + } | ||
320 | +#if defined(WIDE_DEBUG) /*[*/ | ||
321 | + printf("Got Unicode %x\n", Ubuf[0]); | ||
322 | +#endif /*]*/ | ||
323 | + | ||
324 | + if (to_cnv != NULL) { | ||
325 | + /* Convert string from Unicode to Destination. */ | ||
326 | + len = ucnv_fromUChars(to_cnv, tmp_to_buf, 3, Ubuf, len, &err); | ||
327 | + if (err != U_ZERO_ERROR) { | ||
328 | + trace_ds("[fromUnicode of U+%04x to %s failed, ICU " | ||
329 | + "error %d]\n", Ubuf[0], to_name, (int)err); | ||
330 | + return; | ||
331 | + } | ||
332 | + to_buf[0] = tmp_to_buf[0]; | ||
333 | + to_buf[1] = tmp_to_buf[1]; | ||
334 | +#if defined(WIDE_DEBUG) /*[*/ | ||
335 | + printf("Got %u %s characters:", len, to_name); | ||
336 | + for (i = 0; i < len; i++) { | ||
337 | + printf(" %02x", to_buf[i]); | ||
338 | + } | ||
339 | + printf("\n"); | ||
340 | +#endif /*]*/ | ||
341 | + } else { | ||
342 | + to_buf[0] = (Ubuf[0] >> 8) & 0xff; | ||
343 | + to_buf[1] = Ubuf[0] & 0xff; | ||
344 | + } | ||
345 | +} | ||
346 | + | ||
347 | +#if defined(X3270_DISPLAY) /*[*/ | ||
348 | +/* Translate a DBCS EBCDIC character to a display character. */ | ||
349 | +void | ||
350 | +dbcs_to_display(unsigned char ebc1, unsigned char ebc2, unsigned char c[]) | ||
351 | +{ | ||
352 | + xlate1(ebc1, ebc2, c, dbcs_converter, "host DBCS", wdisplay_converter, | ||
353 | + "wide display"); | ||
354 | +} | ||
355 | +#endif /*]*/ | ||
356 | + | ||
357 | +/* Translate a DBCS EBCDIC character to a 2-byte Unicode character. */ | ||
358 | +void | ||
359 | +dbcs_to_unicode16(unsigned char ebc1, unsigned char ebc2, unsigned char c[]) | ||
360 | +{ | ||
361 | + xlate1(ebc1, ebc2, c, dbcs_converter, "host DBCS", NULL, NULL); | ||
362 | +} | ||
363 | + | ||
364 | +/* | ||
365 | + * Translate a DBCS EBCDIC character to a local multi-byte character. | ||
366 | + * Returns -1 for error, or the mb length. NULL terminates. | ||
367 | + */ | ||
368 | +int | ||
369 | +dbcs_to_mb(unsigned char ebc1, unsigned char ebc2, char *mb) | ||
370 | +{ | ||
371 | + UErrorCode err = U_ZERO_ERROR; | ||
372 | + unsigned char w[2]; | ||
373 | + UChar Ubuf; | ||
374 | + int len; | ||
375 | + | ||
376 | + if (local_converter == NULL) { | ||
377 | + *mb = '?'; | ||
378 | + *(mb + 1) = '\0'; | ||
379 | + return 1; | ||
380 | + } | ||
381 | + | ||
382 | + /* Translate to Unicode first. */ | ||
383 | + dbcs_to_unicode16(ebc1, ebc2, w); | ||
384 | + Ubuf = (w[0] << 8) | w[1]; | ||
385 | + | ||
386 | + /* Then translate to the local encoding. */ | ||
387 | + len = ucnv_fromUChars(local_converter, mb, 16, &Ubuf, 1, &err); | ||
388 | + if (err != U_ZERO_ERROR) { | ||
389 | + trace_ds("[fromUnicode of U+%04x to local failed, ICU " | ||
390 | + "error %d]\n", Ubuf, (int)err); | ||
391 | + return -1; | ||
392 | + } | ||
393 | + return len; | ||
394 | +} | ||
395 | + | ||
396 | +/* | ||
397 | + * Translate an SBCS EBCDIC character to a local multi-byte character. | ||
398 | + * Returns -1 for error, or the mb length. NULL terminates. | ||
399 | + */ | ||
400 | +int | ||
401 | +sbcs_to_mb(unsigned char ebc, char *mb) | ||
402 | +{ | ||
403 | + UErrorCode err = U_ZERO_ERROR; | ||
404 | + UChar Ubuf; | ||
405 | + int len; | ||
406 | + | ||
407 | + if (sbcs_converter == NULL) { | ||
408 | + /* No SBCS converter, do EBCDIC to latin-1. */ | ||
409 | + if (local_converter == NULL) { | ||
410 | + /* No local converter either, latin-1 is it. */ | ||
411 | + *mb = ebc2asc[ebc]; | ||
412 | + *(mb + 1) = '\0'; | ||
413 | + return 1; | ||
414 | + } | ||
415 | + | ||
416 | + /* Have a local converter; use it below. */ | ||
417 | + Ubuf = ebc2asc[ebc]; | ||
418 | + } else { | ||
419 | + /* Have an SBCS converter. Convert from SBCS to Unicode. */ | ||
420 | + err = U_ZERO_ERROR; | ||
421 | + len = ucnv_toUChars(sbcs_converter, &Ubuf, 1, (char *)&ebc, 1, | ||
422 | + &err); | ||
423 | + if (err != U_ZERO_ERROR && | ||
424 | + err != U_STRING_NOT_TERMINATED_WARNING) { | ||
425 | + trace_ds("[toUChars failed, ICU error %d]\n", | ||
426 | + (int)err); | ||
427 | + return -1; | ||
428 | + } | ||
429 | + } | ||
430 | + | ||
431 | + /* Convert from Unicode to the local encoding. */ | ||
432 | + len = ucnv_fromUChars(local_converter, mb, 16, &Ubuf, 1, &err); | ||
433 | + if (err != U_ZERO_ERROR) { | ||
434 | + trace_ds("[fromUnicode of U+%04x to local failed, ICU " | ||
435 | + "error %d]\n", Ubuf, (int)err); | ||
436 | + return -1; | ||
437 | + } | ||
438 | + return len; | ||
439 | +} | ||
440 | + | ||
441 | +/* | ||
442 | + * Translate a local multi-byte string to Unicode characters. | ||
443 | + * Returns -1 for error, or the length. NULL terminates. | ||
444 | + */ | ||
445 | +int | ||
446 | +mb_to_unicode(char *mb, int mblen, UChar *u, int ulen, UErrorCode *err) | ||
447 | +{ | ||
448 | + UErrorCode local_err; | ||
449 | + int len; | ||
450 | + Boolean print_errs = False; | ||
451 | + | ||
452 | + if (local_converter == NULL) { | ||
453 | + int i; | ||
454 | + | ||
455 | + for (i = 0; i < mblen; i++) { | ||
456 | + u[i] = mb[i] & 0xff; | ||
457 | + } | ||
458 | + return mblen; | ||
459 | + } | ||
460 | + if (err == NULL) { | ||
461 | + err = &local_err; | ||
462 | + print_errs = True; | ||
463 | + } | ||
464 | + *err = U_ZERO_ERROR; | ||
465 | + len = ucnv_toUChars(local_converter, u, ulen, mb, mblen, err); | ||
466 | + if (*err != U_ZERO_ERROR && *err != U_STRING_NOT_TERMINATED_WARNING) { | ||
467 | + if (print_errs) | ||
468 | + trace_ds("[toUChars failed, ICU error %d]\n", | ||
469 | + (int)*err); | ||
470 | + return -1; | ||
471 | + } | ||
472 | + return len; | ||
473 | +} | ||
474 | + | ||
475 | +/* | ||
476 | + * Try to map a Unicode character to the Host SBCS character set. | ||
477 | + * Returns ASCII in cp[0]. | ||
478 | + */ | ||
479 | +int | ||
480 | +dbcs_map8(UChar u, unsigned char *cp) | ||
481 | +{ | ||
482 | + UErrorCode err = U_ZERO_ERROR; | ||
483 | + int len; | ||
484 | + | ||
485 | + if (!(u & ~0xff)) { | ||
486 | + *cp = u; | ||
487 | + return 1; | ||
488 | + } | ||
489 | + if (sbcs_converter != NULL) { | ||
490 | + len = ucnv_fromUChars(sbcs_converter, (char *)cp, 1, &u, 1, | ||
491 | + &err); | ||
492 | + if ((err != U_ZERO_ERROR && | ||
493 | + err != U_STRING_NOT_TERMINATED_WARNING) || | ||
494 | + (*cp == '?' && u != '?')) { | ||
495 | + *cp = ebc2asc[*cp]; | ||
496 | + return 0; | ||
497 | + } else | ||
498 | + return 1; | ||
499 | + } | ||
500 | + return 0; | ||
501 | +} | ||
502 | + | ||
503 | +/* | ||
504 | + * Try to map a Unicode character to the Host DBCS character set. | ||
505 | + * Returns EBCDIC in cp[]. | ||
506 | + */ | ||
507 | +int | ||
508 | +dbcs_map16(UChar u, unsigned char *cp) | ||
509 | +{ | ||
510 | + UErrorCode err = U_ZERO_ERROR; | ||
511 | + int len; | ||
512 | + | ||
513 | + if (same_converter) { | ||
514 | + char tmp_cp[5]; | ||
515 | + | ||
516 | + len = ucnv_fromUChars(dbcs_converter, tmp_cp, 5, &u, 1, &err); | ||
517 | + if (err != U_ZERO_ERROR || | ||
518 | + len < 3 || | ||
519 | + tmp_cp[0] != EBC_so) | ||
520 | + return 0; | ||
521 | + cp[0] = tmp_cp[1]; | ||
522 | + cp[1] = tmp_cp[2]; | ||
523 | + return 1; | ||
524 | + } else { | ||
525 | + len = ucnv_fromUChars(dbcs_converter, (char *)cp, 2, &u, 1, | ||
526 | + &err); | ||
527 | + return (err == U_ZERO_ERROR || | ||
528 | + err == U_STRING_NOT_TERMINATED_WARNING); | ||
529 | + } | ||
530 | +} |