1 |
#include <stdlib.h> |
2 |
#include <stdio.h> |
3 |
#include <string.h> |
4 |
#include <ctype.h> |
5 |
#include "teraterm.h" |
6 |
#include "tttypes.h" |
7 |
#include "ttplugin.h" |
8 |
#include "tt_res.h" |
9 |
|
10 |
#include <winsock2.h> |
11 |
#include <ws2tcpip.h> |
12 |
|
13 |
#define ORDER 4800 |
14 |
|
15 |
#define IdModeFirst 0 |
16 |
#define IdModeESC 1 |
17 |
#define IdModeOSC 2 |
18 |
#define IdModeESC2 3 |
19 |
#define IdModeProc 4 |
20 |
|
21 |
static HANDLE hInst; /* Instance handle of TTX*.DLL */ |
22 |
|
23 |
typedef struct cfgstack { |
24 |
int val; |
25 |
struct cfgstack *next; |
26 |
} TStack; |
27 |
typedef TStack *PStack; |
28 |
|
29 |
typedef struct { |
30 |
PTTSet ts; |
31 |
PComVar cv; |
32 |
PStack config[2]; |
33 |
Trecv origPrecv; |
34 |
Tsend origPsend; |
35 |
TReadFile origPReadFile; |
36 |
TWriteFile origPWriteFile; |
37 |
} TInstVar; |
38 |
|
39 |
static TInstVar *pvar; |
40 |
static TInstVar InstVar; |
41 |
|
42 |
static void PASCAL TTXInit(PTTSet ts, PComVar cv) { |
43 |
pvar->ts = ts; |
44 |
pvar->cv = cv; |
45 |
pvar->config[0] = NULL; |
46 |
pvar->config[1] = NULL; |
47 |
pvar->origPrecv = NULL; |
48 |
pvar->origPsend = NULL; |
49 |
pvar->origPReadFile = NULL; |
50 |
pvar->origPWriteFile = NULL; |
51 |
} |
52 |
|
53 |
void CommOut(char *str, int len) { |
54 |
int outlen, c; |
55 |
char *p; |
56 |
|
57 |
if (len > OutBuffSize - pvar->cv->OutBuffCount) |
58 |
outlen = OutBuffSize - pvar->cv->OutBuffCount; |
59 |
else |
60 |
outlen = len; |
61 |
|
62 |
if (pvar->cv->OutPtr > 0) { |
63 |
memmove(pvar->cv->OutBuff, &(pvar->cv->OutBuff[pvar->cv->OutPtr]), pvar->cv->OutBuffCount); |
64 |
pvar->cv->OutPtr = 0; |
65 |
} |
66 |
|
67 |
c = pvar->cv->OutBuffCount; |
68 |
for (p = str; outlen>0; p++, outlen--) { |
69 |
switch (*p) { |
70 |
case 0x0d: |
71 |
switch (pvar->cv->CRSend) { |
72 |
case IdCR: |
73 |
pvar->cv->OutBuff[c++] = 0x0d; |
74 |
if (c < OutBuffSize && pvar->cv->TelFlag && ! pvar->cv->TelBinSend) { |
75 |
pvar->cv->OutBuff[c++] = 0; |
76 |
} |
77 |
break; |
78 |
case IdLF: |
79 |
pvar->cv->OutBuff[c++] = 0x0a; |
80 |
break; |
81 |
case IdCRLF: |
82 |
pvar->cv->OutBuff[c++] = 0x0d; |
83 |
if (c < OutBuffSize) { |
84 |
pvar->cv->OutBuff[c++] = 0x0a; |
85 |
} |
86 |
break; |
87 |
} |
88 |
if (c + outlen > OutBuffSize) { |
89 |
outlen--; |
90 |
} |
91 |
break; |
92 |
case 0xff: |
93 |
if (pvar->cv->TelFlag) { |
94 |
if (c < OutBuffSize - 1) { |
95 |
pvar->cv->OutBuff[c++] = 0xff; |
96 |
pvar->cv->OutBuff[c++] = 0xff; |
97 |
} |
98 |
} |
99 |
else { |
100 |
pvar->cv->OutBuff[c++] = 0xff; |
101 |
} |
102 |
if (c + outlen > OutBuffSize) { |
103 |
outlen--; |
104 |
} |
105 |
break; |
106 |
default: |
107 |
pvar->cv->OutBuff[c++] = *p; |
108 |
} |
109 |
} |
110 |
|
111 |
pvar->cv->OutBuffCount = c; |
112 |
} |
113 |
|
114 |
void ParseInputStr(unsigned char *rstr, int rcount) { |
115 |
static WORD mode = IdModeFirst; |
116 |
static unsigned char buff[InBuffSize]; |
117 |
static unsigned int blen; |
118 |
unsigned char *p, *p2; |
119 |
int i; |
120 |
unsigned int func; |
121 |
PStack t; |
122 |
|
123 |
#define AcceptC1Control \ |
124 |
((pvar->cv->KanjiCodeEcho == IdEUC || pvar->cv->KanjiCodeEcho == IdJIS) && \ |
125 |
pvar->ts->TerminalID >= IdVT220J && (pvar->ts->TermFlag & TF_ACCEPT8BITCTRL) != 0) |
126 |
|
127 |
for (i=0; i<rcount; i++) { |
128 |
switch (mode) { |
129 |
case IdModeFirst: |
130 |
if (rstr[i] == ESC) { |
131 |
mode = IdModeESC; |
132 |
} |
133 |
else if (rstr[i] == OSC && AcceptC1Control) { |
134 |
mode = IdModeOSC; |
135 |
} |
136 |
break; |
137 |
case IdModeESC: |
138 |
if (rstr[i] == ']') { |
139 |
mode = IdModeOSC; |
140 |
} |
141 |
else { |
142 |
mode = IdModeFirst; |
143 |
} |
144 |
break; |
145 |
case IdModeOSC: |
146 |
if (rstr[i] == ESC) { |
147 |
mode = IdModeESC2; |
148 |
} |
149 |
else if (rstr[i] == '\a' || rstr[i] == ST && AcceptC1Control) { |
150 |
mode = IdModeProc; |
151 |
i--; |
152 |
} |
153 |
else if (blen < InBuffSize - 1) { |
154 |
buff[blen++] = rstr[i]; |
155 |
} |
156 |
if (blen >= InBuffSize - 1) { |
157 |
mode = IdModeProc; |
158 |
i--; |
159 |
} |
160 |
break; |
161 |
case IdModeESC2: |
162 |
if (rstr[i] == '\\') { |
163 |
mode = IdModeProc; |
164 |
i--; |
165 |
} |
166 |
else { |
167 |
if (blen < InBuffSize - 1) { |
168 |
buff[blen++] = ESC; |
169 |
buff[blen++] = rstr[i]; |
170 |
} |
171 |
if (blen >= InBuffSize - 1) { |
172 |
mode = IdModeProc; |
173 |
i--; |
174 |
} |
175 |
else { |
176 |
mode = IdModeOSC; |
177 |
} |
178 |
} |
179 |
break; |
180 |
case IdModeProc: |
181 |
buff[(blen<InBuffSize)?blen:InBuffSize-1] = '\0'; |
182 |
p = buff; |
183 |
|
184 |
for (p=buff, func=0; isdigit(*p); p++) { |
185 |
func = func * 10 + *p - '0'; |
186 |
} |
187 |
if (*p != ';' || p == buff) { |
188 |
blen = 0; |
189 |
mode = IdModeFirst; |
190 |
break; |
191 |
} |
192 |
p++; |
193 |
switch (func) { |
194 |
case 5963: |
195 |
while (p && *p) { |
196 |
if ((p2 = strchr(p, ';')) != NULL) |
197 |
*p2++ = '\0'; |
198 |
if (_strnicmp(p, "kt=", 3) == 0) { |
199 |
p+= 3; |
200 |
if (_stricmp(p, "SJIS") == 0) |
201 |
pvar->cv->KanjiCodeSend = pvar->ts->KanjiCodeSend = IdSJIS; |
202 |
else if (_stricmp(p, "EUC") == 0) |
203 |
pvar->cv->KanjiCodeSend = pvar->ts->KanjiCodeSend = IdEUC; |
204 |
else if (_stricmp(p, "JIS") == 0) |
205 |
pvar->cv->KanjiCodeSend = pvar->ts->KanjiCodeSend = IdJIS; |
206 |
else if (_stricmp(p, "UTF8") == 0 || _stricmp(p, "UTF-8") == 0) |
207 |
pvar->cv->KanjiCodeSend = pvar->ts->KanjiCodeSend = IdUTF8; |
208 |
} |
209 |
else if (_strnicmp(p, "kr=", 3) == 0) { |
210 |
p += 3; |
211 |
if (_stricmp(p, "SJIS") == 0) |
212 |
pvar->cv->KanjiCodeEcho = pvar->ts->KanjiCode = IdSJIS; |
213 |
else if (_stricmp(p, "EUC") == 0) |
214 |
pvar->cv->KanjiCodeEcho = pvar->ts->KanjiCode = IdEUC; |
215 |
else if (_stricmp(p, "JIS") == 0) |
216 |
pvar->cv->KanjiCodeEcho = pvar->ts->KanjiCode = IdJIS; |
217 |
else if (_stricmp(p, "UTF8") == 0 || _stricmp(p, "UTF-8") == 0) |
218 |
pvar->cv->KanjiCodeEcho = pvar->ts->KanjiCode = IdUTF8; |
219 |
else if (_stricmp(p, "UTF8m") == 0 || _stricmp(p, "UTF-8m") == 0) |
220 |
pvar->cv->KanjiCodeEcho = pvar->ts->KanjiCode = IdUTF8; |
221 |
} |
222 |
p = p2; |
223 |
} |
224 |
break; |
225 |
case 5964: |
226 |
while (p && *p) { |
227 |
if ((p2 = strchr(p, ';')) != NULL) |
228 |
*p2++ = '\0'; |
229 |
if (_stricmp(p, "kt") == 0) { |
230 |
switch (pvar->cv->KanjiCodeSend) { |
231 |
case IdSJIS: |
232 |
CommOut("kt=SJIS;", 8); |
233 |
break; |
234 |
case IdEUC: |
235 |
CommOut("kt=EUC;", 7); |
236 |
break; |
237 |
case IdJIS: |
238 |
CommOut("kt=JIS;", 7); |
239 |
break; |
240 |
case IdUTF8: |
241 |
CommOut("kt=UTF8;", 8); |
242 |
break; |
243 |
} |
244 |
} |
245 |
else if (_stricmp(p, "kr") == 0) { |
246 |
switch (pvar->cv->KanjiCodeEcho) { |
247 |
case IdSJIS: |
248 |
CommOut("kr=SJIS;", 8); |
249 |
break; |
250 |
case IdEUC: |
251 |
CommOut("kr=EUC;", 7); |
252 |
break; |
253 |
case IdJIS: |
254 |
CommOut("kr=JIS;", 7); |
255 |
break; |
256 |
case IdUTF8: |
257 |
CommOut("kr=UTF8;", 8); |
258 |
break; |
259 |
} |
260 |
} |
261 |
p = p2; |
262 |
} |
263 |
CommOut("\r", 1); |
264 |
break; |
265 |
case 5965: |
266 |
while (p && *p) { |
267 |
if ((p2 = strchr(p, ';')) != NULL) |
268 |
*p2++ = '\0'; |
269 |
if (_stricmp(p, "kt") == 0) { |
270 |
if ((t=malloc(sizeof(TStack))) != NULL) { |
271 |
t->val = pvar->cv->KanjiCodeSend; |
272 |
t->next = pvar->config[0]; |
273 |
pvar->config[0] = t; |
274 |
} |
275 |
} |
276 |
else if (_stricmp(p, "kr") == 0) { |
277 |
if ((t=malloc(sizeof(TStack))) != NULL) { |
278 |
t->val = pvar->cv->KanjiCodeEcho; |
279 |
t->next = pvar->config[1]; |
280 |
pvar->config[1] = t; |
281 |
} |
282 |
} |
283 |
p = p2; |
284 |
} |
285 |
break; |
286 |
case 5966: |
287 |
while (p && *p) { |
288 |
if ((p2 = strchr(p, ';')) != NULL) |
289 |
*p2++ = '\0'; |
290 |
if (_stricmp(p, "kt") == 0) { |
291 |
if (pvar->config[0] != NULL) { |
292 |
t = pvar->config[0]; |
293 |
pvar->cv->KanjiCodeSend = pvar->ts->KanjiCodeSend = t->val; |
294 |
pvar->config[0] = t->next; |
295 |
free(t); |
296 |
} |
297 |
} |
298 |
else if (_stricmp(p, "kr") == 0) { |
299 |
if (pvar->config[1] != NULL) { |
300 |
t = pvar->config[1]; |
301 |
pvar->cv->KanjiCodeEcho = pvar->ts->KanjiCode = t->val; |
302 |
pvar->config[1] = t->next; |
303 |
free(t); |
304 |
} |
305 |
} |
306 |
p = p2; |
307 |
} |
308 |
break; |
309 |
default: |
310 |
; /* nothing to do */ |
311 |
} |
312 |
blen = 0; |
313 |
mode = IdModeFirst; |
314 |
default: |
315 |
; /* not reached */ |
316 |
} |
317 |
} |
318 |
} |
319 |
|
320 |
int PASCAL TTXrecv(SOCKET s, char *buff, int len, int flags) { |
321 |
int rlen; |
322 |
|
323 |
if ((rlen = pvar->origPrecv(s, buff, len, flags)) > 0) { |
324 |
ParseInputStr(buff, rlen); |
325 |
} |
326 |
return rlen; |
327 |
} |
328 |
|
329 |
BOOL PASCAL TTXReadFile(HANDLE fh, LPVOID buff, DWORD len, LPDWORD rbytes, LPOVERLAPPED rol) { |
330 |
BOOL result; |
331 |
|
332 |
if ((result = pvar->origPReadFile(fh, buff, len, rbytes, rol)) != FALSE) |
333 |
ParseInputStr(buff, *rbytes); |
334 |
return result; |
335 |
} |
336 |
|
337 |
static void PASCAL TTXOpenTCP(TTXSockHooks *hooks) { |
338 |
pvar->origPrecv = *hooks->Precv; |
339 |
*hooks->Precv = TTXrecv; |
340 |
} |
341 |
|
342 |
static void PASCAL TTXCloseTCP(TTXSockHooks *hooks) { |
343 |
if (pvar->origPrecv) { |
344 |
*hooks->Precv = pvar->origPrecv; |
345 |
} |
346 |
} |
347 |
|
348 |
static void PASCAL TTXOpenFile(TTXFileHooks *hooks) { |
349 |
pvar->origPReadFile = *hooks->PReadFile; |
350 |
*hooks->PReadFile = TTXReadFile; |
351 |
} |
352 |
|
353 |
static void PASCAL TTXCloseFile(TTXFileHooks *hooks) { |
354 |
if (pvar->origPReadFile) { |
355 |
*hooks->PReadFile = pvar->origPReadFile; |
356 |
} |
357 |
} |
358 |
|
359 |
static TTXExports Exports = { |
360 |
sizeof(TTXExports), |
361 |
ORDER, |
362 |
|
363 |
TTXInit, |
364 |
NULL, // TTXGetUIHooks, |
365 |
NULL, // TTXGetSetupHooks, |
366 |
TTXOpenTCP, |
367 |
TTXCloseTCP, |
368 |
NULL, // TTXSetWinSize, |
369 |
NULL, // TTXModifyMenu, |
370 |
NULL, // TTXModifyPopupMenu, |
371 |
NULL, // TTXProcessCommand, |
372 |
NULL, // TTXEnd, |
373 |
NULL, // TTXSetCommandLine, |
374 |
TTXOpenFile, |
375 |
TTXCloseFile |
376 |
}; |
377 |
|
378 |
BOOL __declspec(dllexport) PASCAL TTXBind(WORD Version, TTXExports *exports) { |
379 |
int size = sizeof(Exports) - sizeof(exports->size); |
380 |
|
381 |
if (size > exports->size) { |
382 |
size = exports->size; |
383 |
} |
384 |
memcpy((char *)exports + sizeof(exports->size), |
385 |
(char *)&Exports + sizeof(exports->size), |
386 |
size); |
387 |
return TRUE; |
388 |
} |
389 |
|
390 |
BOOL WINAPI DllMain(HANDLE hInstance, |
391 |
ULONG ul_reason_for_call, |
392 |
LPVOID lpReserved) |
393 |
{ |
394 |
switch( ul_reason_for_call ) { |
395 |
case DLL_THREAD_ATTACH: |
396 |
/* do thread initialization */ |
397 |
break; |
398 |
case DLL_THREAD_DETACH: |
399 |
/* do thread cleanup */ |
400 |
break; |
401 |
case DLL_PROCESS_ATTACH: |
402 |
/* do process initialization */ |
403 |
hInst = hInstance; |
404 |
pvar = &InstVar; |
405 |
break; |
406 |
case DLL_PROCESS_DETACH: |
407 |
/* do process cleanup */ |
408 |
break; |
409 |
} |
410 |
return TRUE; |
411 |
} |