Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/teraterm/ttpcmn/ttcmn.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10276 - (show annotations) (download) (as text)
Mon Sep 19 15:40:58 2022 UTC (18 months, 3 weeks ago) by zmatsuo
File MIME type: text/x-csrc
File size: 29465 byte(s)
新しい接続でcomポートが存在する時、メモリリークしていたので修正

- ComPortInfoGet() を使用するようにした
  - DetectComPorts() を使用しないようにした
- ダイアログのプロシージャ関数内でstatic変数を使用しないようにした
- comポートの情報は動的なメモリ上に取得するので内部的には上限がなくなった
  - tttypes.h で MAXCOMPORT は 4096 としてある
1 /*
2 * Copyright (C) 1994-1998 T. Teranishi
3 * (C) 2004- TeraTerm Project
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. 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 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 /* TTCMN.DLL, main */
31 #include <string.h>
32 #include <stdio.h>
33 #include <windows.h>
34 #include <setupapi.h>
35 #include <htmlhelp.h>
36 #include <assert.h>
37 #define _CRTDBG_MAP_ALLOC
38 #include <stdlib.h>
39 #include <crtdbg.h>
40
41 #define DllExport __declspec(dllexport)
42 #include "language.h"
43 #undef DllExport
44
45 #include "teraterm.h"
46 #include "tttypes.h"
47 #include "ttlib.h"
48 #include "codeconv.h"
49 #include "compat_win.h"
50 #include "win32helper.h"
51 #include "../teraterm/unicode.h"
52
53 #include "ttcmn_shared_memory.h"
54 #include "ttcommon.h"
55 #include "ttcmn_i.h"
56
57 static PMap pm;
58
59 #define VTCLASSNAME "VTWin32"
60 #define TEKCLASSNAME "TEKWin32"
61
62 enum window_style {
63 WIN_CASCADE,
64 WIN_STACKED,
65 WIN_SIDEBYSIDE,
66 };
67
68 void WINAPI SetCOMFlag(int Com)
69 {
70 if (Com <= 0 || MAXCOMPORT <= Com) return;
71 pm->ComFlag[(Com-1)/CHAR_BIT] |= 1 << ((Com-1)%CHAR_BIT);
72 }
73
74 void WINAPI ClearCOMFlag(int Com)
75 {
76 if (Com <= 0 || MAXCOMPORT <= Com) return;
77 pm->ComFlag[(Com-1)/CHAR_BIT] &= ~(1 << ((Com-1)%CHAR_BIT));
78 }
79
80 int WINAPI CheckCOMFlag(int Com)
81 {
82 if (Com <= 0) return 0;
83 if (Com > MAXCOMPORT) return 1;
84 return ((pm->ComFlag[(Com-1)/CHAR_BIT] & 1 << (Com-1)%CHAR_BIT) > 0);
85 }
86
87 int WINAPI RegWin(HWND HWinVT, HWND HWinTEK)
88 {
89 int i, j;
90
91 if (pm->NWin>=MAXNWIN)
92 return 0;
93 if (HWinVT==NULL)
94 return 0;
95 if (HWinTEK!=NULL) {
96 i = 0;
97 while ((i<pm->NWin) && (pm->WinList[i]!=HWinVT))
98 i++;
99 if (i>=pm->NWin)
100 return 0;
101 for (j=pm->NWin-1 ; j>i ; j--)
102 pm->WinList[j+1] = pm->WinList[j];
103 pm->WinList[i+1] = HWinTEK;
104 pm->NWin++;
105 return 0;
106 }
107 pm->WinList[pm->NWin++] = HWinVT;
108 memset(&pm->WinPrevRect[pm->NWin - 1], 0, sizeof(pm->WinPrevRect[pm->NWin - 1])); // RECT clear
109 if (pm->NWin==1) {
110 return 1;
111 }
112 else {
113 return (int)(SendMessage(pm->WinList[pm->NWin-2],
114 WM_USER_GETSERIALNO,0,0)+1);
115 }
116 }
117
118 void WINAPI UnregWin(HWND HWin)
119 {
120 int i, j;
121
122 i = 0;
123 while ((i<pm->NWin) && (pm->WinList[i]!=HWin)) {
124 i++;
125 }
126 if (pm->WinList[i]!=HWin) {
127 return;
128 }
129 for (j=i ; j<pm->NWin-1 ; j++) {
130 pm->WinList[j] = pm->WinList[j+1];
131 pm->WinPrevRect[j] = pm->WinPrevRect[j+1]; // RECT shift
132 }
133 if (pm->NWin>0) {
134 pm->NWin--;
135 }
136 }
137
138 static char GetWindowTypeChar(HWND Hw, HWND HWin)
139 {
140 #if 0
141 if (HWin == Hw)
142 return '*';
143 else if (!IsWindowVisible(Hw))
144 #else
145 if (!IsWindowVisible(Hw))
146 #endif
147 return '#';
148 else if (IsIconic(Hw))
149 return '-';
150 else if (IsZoomed(Hw))
151 return '@';
152 else
153 return '+';
154 }
155
156 void WINAPI SetWinMenu(HMENU menu, PCHAR buf, int buflen, PCHAR langFile, int VTFlag)
157 {
158 int i;
159 char Temp[MAXPATHLEN];
160 HWND Hw;
161 wchar_t uimsg[MAX_UIMSG];
162
163 // delete all items in Window menu
164 i = GetMenuItemCount(menu);
165 if (i>0)
166 do {
167 i--;
168 RemoveMenu(menu,i,MF_BYPOSITION);
169 } while (i>0);
170
171 i = 0;
172 while (i<pm->NWin) {
173 Hw = pm->WinList[i]; // get window handle
174 if ((GetClassName(Hw,Temp,sizeof(Temp))>0) &&
175 ((strcmp(Temp,VTCLASSNAME)==0) ||
176 (strcmp(Temp,TEKCLASSNAME)==0))) {
177 Temp[0] = '&';
178 Temp[1] = (char)(0x31 + i);
179 Temp[2] = ' ';
180 Temp[3] = GetWindowTypeChar(Hw, NULL);
181 Temp[4] = ' ';
182 GetWindowText(Hw,&Temp[5],sizeof(Temp)-6);
183 AppendMenu(menu,MF_ENABLED | MF_STRING,ID_WINDOW_1+i,Temp);
184 i++;
185 if (i>8) {
186 i = pm->NWin;
187 }
188 }
189 else {
190 UnregWin(Hw);
191 }
192 }
193 if (VTFlag == 1) {
194 static const DlgTextInfo MenuTextInfo[] = {
195 { ID_WINDOW_WINDOW, "MENU_WINDOW_WINDOW" },
196 { ID_WINDOW_MINIMIZEALL, "MENU_WINDOW_MINIMIZEALL" },
197 { ID_WINDOW_RESTOREALL, "MENU_WINDOW_RESTOREALL" },
198 { ID_WINDOW_CASCADEALL, "MENU_WINDOW_CASCADE" },
199 { ID_WINDOW_STACKED, "MENU_WINDOW_STACKED" },
200 { ID_WINDOW_SIDEBYSIDE, "MENU_WINDOW_SIDEBYSIDE" },
201 };
202
203 AppendMenu(menu, MF_SEPARATOR, 0, NULL);
204 AppendMenu(menu, MF_ENABLED | MF_STRING, ID_WINDOW_WINDOW, "&Window");
205 AppendMenu(menu, MF_ENABLED | MF_STRING, ID_WINDOW_MINIMIZEALL, "&Minimize All");
206 AppendMenu(menu, MF_ENABLED | MF_STRING, ID_WINDOW_RESTOREALL, "&Restore All");
207 AppendMenu(menu, MF_ENABLED | MF_STRING, ID_WINDOW_CASCADEALL, "&Cascade");
208 AppendMenu(menu, MF_ENABLED | MF_STRING, ID_WINDOW_STACKED, "&Stacked");
209 AppendMenu(menu, MF_ENABLED | MF_STRING, ID_WINDOW_SIDEBYSIDE, "Side &by Side");
210
211 SetI18nMenuStrs("Tera Term", menu, MenuTextInfo, _countof(MenuTextInfo), langFile);
212
213 if (pm->WinUndoFlag) {
214 if (pm->WinUndoStyle == WIN_CASCADE)
215 get_lang_msgW("MENU_WINDOW_CASCADE_UNDO", uimsg, _countof(uimsg), L"&Undo - Cascade", langFile);
216 else if (pm->WinUndoStyle == WIN_STACKED)
217 get_lang_msgW("MENU_WINDOW_STACKED_UNDO", uimsg, _countof(uimsg), L"&Undo - Stacked", langFile);
218 else
219 get_lang_msgW("MENU_WINDOW_SIDEBYSIDE_UNDO", uimsg, _countof(uimsg), L"&Undo - Side by Side", langFile);
220 AppendMenuW(menu, MF_ENABLED | MF_STRING, ID_WINDOW_UNDO, uimsg); // TODO UNICODE
221 }
222
223 }
224 else {
225 get_lang_msgW("MENU_WINDOW_WINDOW", uimsg, _countof(uimsg), L"&Window", langFile);
226 AppendMenuW(menu,MF_ENABLED | MF_STRING,ID_TEKWINDOW_WINDOW, uimsg);
227 }
228 }
229
230 void WINAPI SetWinList(HWND HWin, HWND HDlg, int IList)
231 {
232 int i;
233 char Temp[MAXPATHLEN];
234 HWND Hw;
235
236 for (i=0; i<pm->NWin; i++) {
237 Hw = pm->WinList[i]; // get window handle
238 if ((GetClassName(Hw,Temp,sizeof(Temp))>0) &&
239 ((strcmp(Temp,VTCLASSNAME)==0) ||
240 (strcmp(Temp,TEKCLASSNAME)==0))) {
241 Temp[0] = GetWindowTypeChar(Hw, HWin);
242 Temp[1] = ' ';
243 GetWindowText(Hw,&Temp[2],sizeof(Temp)-3);
244 SendDlgItemMessage(HDlg, IList, LB_ADDSTRING,
245 0, (LPARAM)Temp);
246 if (Hw==HWin) {
247 SendDlgItemMessage(HDlg, IList, LB_SETCURSEL, i,0);
248 }
249 }
250 else {
251 UnregWin(Hw);
252 }
253 }
254 }
255
256 void WINAPI SelectWin(int WinId)
257 {
258 if ((WinId>=0) && (WinId<pm->NWin)) {
259 /* �E�B���h�E�����������������������������������A���������������������������A
260 * SW_SHOWNORMAL ���� SW_SHOW �����X�����B
261 * (2009.11.8 yutaka)
262 * �E�B���h�E�����������������������������T�C�Y������(SW_RESTORE)�����������B
263 * (2009.11.9 maya)
264 */
265 if (IsIconic(pm->WinList[WinId])) {
266 ShowWindow(pm->WinList[WinId],SW_RESTORE);
267 }
268 else {
269 ShowWindow(pm->WinList[WinId],SW_SHOW);
270 }
271 SetForegroundWindow(pm->WinList[WinId]);
272 }
273 }
274
275 void WINAPI SelectNextWin(HWND HWin, int Next, BOOL SkipIconic)
276 {
277 int i;
278
279 i = 0;
280 while ((i < pm->NWin) && (pm->WinList[i]!=HWin)) {
281 i++;
282 }
283 if (pm->WinList[i]!=HWin) {
284 return;
285 }
286
287 do {
288 i += Next;
289 if (i >= pm->NWin) {
290 i = 0;
291 }
292 else if (i < 0) {
293 i = pm->NWin-1;
294 }
295
296 if (pm->WinList[i] == HWin) {
297 break;
298 }
299 } while ((SkipIconic && IsIconic(pm->WinList[i])) || !IsWindowVisible(pm->WinList[i]));
300
301 SelectWin(i);
302 }
303
304 void WINAPI ShowAllWin(int stat) {
305 int i;
306
307 for (i=0; i < pm->NWin; i++) {
308 ShowWindow(pm->WinList[i], stat);
309 }
310 }
311
312 void WINAPI UndoAllWin(void) {
313 int i;
314 WINDOWPLACEMENT rc0;
315 RECT rc;
316 int stat = SW_RESTORE;
317 int multi_mon = 0;
318
319 if (HasMultiMonitorSupport()) {
320 multi_mon = 1;
321 }
322
323 // ���x�A�����������t���O���������B
324 pm->WinUndoFlag = FALSE;
325
326 memset(&rc0, 0, sizeof(rc0));
327
328 for (i=0; i < pm->NWin; i++) {
329 // �����w�����A�O�����������c���������������A�E�B���h�E�����������������B
330 if (stat == SW_RESTORE && memcmp(&pm->WinPrevRect[i], &rc0, sizeof(rc0)) != 0) {
331 rc = pm->WinPrevRect[i].rcNormalPosition;
332
333 // NT4.0, 95 ���}���`���j�^API��������
334 if (multi_mon) {
335 // �������j�^������������
336 HMONITOR hMonitor;
337 MONITORINFO mi;
338 hMonitor = pMonitorFromRect(&rc, MONITOR_DEFAULTTONEAREST);
339 mi.cbSize = sizeof(MONITORINFO);
340 pGetMonitorInfoA(hMonitor, &mi);
341
342 // ���u�����i�����O���������x���������������������������j
343 if (rc.right > mi.rcMonitor.right) {
344 rc.left -= rc.right - mi.rcMonitor.right;
345 rc.right = mi.rcMonitor.right;
346 }
347 if (rc.left < mi.rcMonitor.left) {
348 rc.right += mi.rcMonitor.left - rc.left;
349 rc.left = mi.rcMonitor.left;
350 }
351 if (rc.bottom > mi.rcMonitor.bottom) {
352 rc.top -= rc.bottom - mi.rcMonitor.bottom;
353 rc.bottom = mi.rcMonitor.bottom;
354 }
355 if (rc.top < mi.rcMonitor.top) {
356 rc.bottom += mi.rcMonitor.top - rc.top;
357 rc.top = mi.rcMonitor.top;
358 }
359 }
360
361 // �E�B���h�E���u����
362 SetWindowPos(
363 pm->WinList[i], NULL,
364 rc.left,
365 rc.top,
366 rc.right - rc.left,
367 rc.bottom - rc.top,
368 SWP_NOZORDER);
369
370 // �E�B���h�E����������
371 ShowWindow(pm->WinList[i], pm->WinPrevRect[i].showCmd);
372
373 } else {
374 ShowWindow(pm->WinList[i], stat);
375 }
376 }
377 }
378
379 HWND WINAPI GetNthWin(int n)
380 {
381 if (n<pm->NWin) {
382 return pm->WinList[n];
383 }
384 else {
385 return NULL;
386 }
387 }
388
389 int WINAPI GetRegisteredWindowCount(void)
390 {
391 return (pm->NWin);
392 }
393
394 // �L�����E�B���h�E���T���A�������u���L�������������B
395 static void get_valid_window_and_memorize_rect(HWND myhwnd, HWND hwnd[], int *num, int style)
396 {
397 int i, n;
398 WINDOWPLACEMENT wndPlace;
399
400 // ��������(Undo)���j���[�����x�����\���������B
401 if (pm->WinUndoFlag == FALSE) {
402 pm->WinUndoFlag = TRUE;
403 } else {
404 // ���������j���[���\�������������A�������O�������X�^�C�����I�����������A
405 // ���j���[�������B
406 // Windows8�����A�������A�����������X�^�C�����I�����������j���[�����������������A
407 // Tera Term�������j���[���\�������������A�������������B
408 if (pm->WinUndoStyle == style)
409 pm->WinUndoFlag = FALSE;
410 }
411 pm->WinUndoStyle = style;
412
413 n = 0;
414 for (i = 0 ; i < pm->NWin ; i++) {
415 // �������u���o���������B
416 wndPlace.length = sizeof(WINDOWPLACEMENT);
417 GetWindowPlacement(pm->WinList[i], &wndPlace);
418 pm->WinPrevRect[i] = wndPlace;
419
420 // �������g�������������B
421 if (pm->WinList[i] == myhwnd) {
422 hwnd[n] = hwnd[0];
423 hwnd[0] = myhwnd;
424 } else {
425 hwnd[n] = pm->WinList[i];
426 }
427 n++;
428 }
429 *num = n;
430 }
431
432 // �E�B���h�E�����E���������\������(Show Windows Side by Side)
433 void WINAPI ShowAllWinSidebySide(HWND myhwnd)
434 {
435 int n;
436 HWND hwnd[MAXNWIN];
437
438 get_valid_window_and_memorize_rect(myhwnd, hwnd, &n, WIN_SIDEBYSIDE);
439 TileWindows(NULL, MDITILE_VERTICAL, NULL, n, hwnd);
440 }
441
442 // �E�B���h�E���������������\������(Show Windows Stacked)
443 void WINAPI ShowAllWinStacked(HWND myhwnd)
444 {
445 int n;
446 HWND hwnd[MAXNWIN];
447
448 get_valid_window_and_memorize_rect(myhwnd, hwnd, &n, WIN_STACKED);
449 TileWindows(NULL, MDITILE_HORIZONTAL, NULL, n, hwnd);
450 }
451
452 // �E�B���h�E���d�����\������(Cascade)
453 void WINAPI ShowAllWinCascade(HWND myhwnd)
454 {
455 int n;
456 HWND hwnd[MAXNWIN];
457
458 get_valid_window_and_memorize_rect(myhwnd, hwnd, &n, WIN_CASCADE);
459 CascadeWindows(NULL, MDITILE_SKIPDISABLED, NULL, n, hwnd);
460 }
461
462 // �STera Term���I���w�����o���B
463 void WINAPI BroadcastClosingMessage(HWND myhwnd)
464 {
465 int i, max;
466 HWND hwnd[MAXNWIN];
467
468 // Tera Term���I�����������A���L���������������������A
469 // ���������o�b�t�@���R�s�[���������B
470 max = pm->NWin;
471 for (i = 0 ; i < pm->NWin ; i++) {
472 hwnd[i] = pm->WinList[i];
473 }
474
475 for (i = 0 ; i < max ; i++) {
476 // �������g�������������B
477 if (hwnd[i] == myhwnd)
478 continue;
479
480 PostMessage(hwnd[i], WM_USER_NONCONFIRM_CLOSE, 0, 0);
481 }
482 PostMessage(myhwnd, WM_USER_NONCONFIRM_CLOSE, 0, 0);
483 }
484
485
486 int WINAPI CommReadRawByte(PComVar cv, LPBYTE b)
487 {
488 if ( ! cv->Ready ) {
489 return 0;
490 }
491
492 if ( cv->InBuffCount>0 ) {
493 *b = cv->InBuff[cv->InPtr];
494 cv->InPtr++;
495 cv->InBuffCount--;
496 if ( cv->InBuffCount==0 ) {
497 cv->InPtr = 0;
498 }
499 return 1;
500 }
501 else {
502 cv->InPtr = 0;
503 return 0;
504 }
505 }
506
507 static void LogBinSkip(PComVar cv, int add)
508 {
509 if (cv->LogBinSkip != NULL) {
510 cv->LogBinSkip(add);
511 }
512 }
513
514 void WINAPI CommInsert1Byte(PComVar cv, BYTE b)
515 {
516 if ( ! cv->Ready ) {
517 return;
518 }
519
520 if (cv->InPtr == 0) {
521 memmove(&(cv->InBuff[1]),&(cv->InBuff[0]),cv->InBuffCount);
522 }
523 else {
524 cv->InPtr--;
525 }
526 cv->InBuff[cv->InPtr] = b;
527 cv->InBuffCount++;
528
529 LogBinSkip(cv, 1);
530 }
531
532 static void Log1Bin(PComVar cv, BYTE b)
533 {
534 if (cv->Log1Bin != NULL) {
535 cv->Log1Bin(b);
536 }
537 }
538
539 int WINAPI CommRead1Byte(PComVar cv, LPBYTE b)
540 {
541 int c;
542
543 if ( ! cv->Ready ) {
544 return 0;
545 }
546
547 if ( cv->TelMode ) {
548 c = 0;
549 }
550 else {
551 c = CommReadRawByte(cv,b);
552 }
553
554 if ((c==1) && cv->TelCRFlag) {
555 cv->TelCRFlag = FALSE;
556 if (*b==0) {
557 c = 0;
558 }
559 }
560
561 if ( c==1 ) {
562 if ( cv->IACFlag ) {
563 cv->IACFlag = FALSE;
564 if ( *b != 0xFF ) {
565 cv->TelMode = TRUE;
566 CommInsert1Byte(cv,*b);
567 LogBinSkip(cv, -1);
568 c = 0;
569 }
570 }
571 else if ((cv->PortType==IdTCPIP) && (*b==0xFF)) {
572 if (!cv->TelFlag && cv->TelAutoDetect) { /* TTPLUG */
573 cv->TelFlag = TRUE;
574 }
575 if (cv->TelFlag) {
576 cv->IACFlag = TRUE;
577 c = 0;
578 }
579 }
580 else if (cv->TelFlag && ! cv->TelBinRecv && (*b==0x0D)) {
581 cv->TelCRFlag = TRUE;
582 }
583 }
584
585 if (c == 1) {
586 Log1Bin(cv, *b);
587 }
588
589 return c;
590 }
591
592 int WINAPI CommRawOut(PComVar cv, /*const*/ PCHAR B, int C)
593 {
594 int a;
595
596 if ( ! cv->Ready ) {
597 return C;
598 }
599
600 if (C > OutBuffSize - cv->OutBuffCount) {
601 a = OutBuffSize - cv->OutBuffCount;
602 }
603 else {
604 a = C;
605 }
606 if ( cv->OutPtr > 0 ) {
607 memmove(&(cv->OutBuff[0]),&(cv->OutBuff[cv->OutPtr]),cv->OutBuffCount);
608 cv->OutPtr = 0;
609 }
610 memcpy(&(cv->OutBuff[cv->OutBuffCount]),B,a);
611 cv->OutBuffCount = cv->OutBuffCount + a;
612 return a;
613 }
614
615 int WINAPI CommBinaryOut(PComVar cv, PCHAR B, int C)
616 {
617 int a, i, Len;
618 char d[3];
619
620 if ( ! cv->Ready ) {
621 return C;
622 }
623
624 i = 0;
625 a = 1;
626 while ((a>0) && (i<C)) {
627 Len = 0;
628
629 d[Len] = B[i];
630 Len++;
631
632 if ( cv->TelFlag && (B[i]=='\x0d') && ! cv->TelBinSend ) {
633 d[Len++] = '\x00';
634 }
635 else if ( cv->TelFlag && (B[i]=='\xff') ) {
636 d[Len++] = '\xff';
637 }
638
639 if ( OutBuffSize - cv->OutBuffCount - Len >= 0 ) {
640 CommRawOut(cv, d, Len);
641 a = 1;
642 }
643 else {
644 a = 0;
645 }
646
647 i += a;
648 }
649 return i;
650 }
651
652 /**
653 * �f�[�^(������)���o���o�b�t�@����������
654 *
655 * �w���f�[�^��������������������������������������
656 * CommRawOut() ��������������������������
657 *
658 * @retval TRUE �o��������
659 * @retval FALSE �o��������������(buffer full)
660 */
661 static BOOL WriteOutBuff(PComVar cv, const char *TempStr, int TempLen)
662 {
663 BOOL output;
664
665 if (TempLen == 0) {
666 // ����0������������������������
667 return TRUE;
668 }
669
670 output = FALSE;
671 if (cv->TelLineMode) {
672 const BOOL Full = OutBuffSize - cv->LineModeBuffCount - TempLen < 0;
673 if (!Full) {
674 output = TRUE;
675 memcpy(&(cv->LineModeBuff[cv->LineModeBuffCount]), TempStr, TempLen);
676 cv->LineModeBuffCount += TempLen;
677 if (cv->Flush) {
678 cv->FlushLen = cv->LineModeBuffCount;
679 }
680 }
681 if (cv->FlushLen > 0) {
682 const int OutLen = CommRawOut(cv, cv->LineModeBuff, cv->FlushLen);
683 cv->FlushLen -= OutLen;
684 cv->LineModeBuffCount -= OutLen;
685 memmove(cv->LineModeBuff, &(cv->LineModeBuff[OutLen]), cv->LineModeBuffCount);
686 }
687 cv->Flush = FALSE;
688 }
689 else {
690 const BOOL Full = OutBuffSize-cv->OutBuffCount-TempLen < 0;
691 if (! Full) {
692 output = TRUE;
693 CommRawOut(cv, (char *)TempStr, TempLen);
694 }
695 }
696 return output;
697 }
698
699 /**
700 * �f�[�^(������)�������o�b�t�@����������
701 * �����o�b�t�@�������� -> �G�R�[������
702 *
703 * @retval TRUE �o��������
704 * @retval FALSE �o��������������(buffer full)
705 */
706 static BOOL WriteInBuff(PComVar cv, const char *TempStr, int TempLen)
707 {
708 BOOL Full;
709
710 if (TempLen == 0) {
711 return TRUE;
712 }
713
714 Full = InBuffSize-cv->InBuffCount-TempLen < 0;
715 if (! Full) {
716 memcpy(&(cv->InBuff[cv->InBuffCount]),TempStr,TempLen);
717 cv->InBuffCount = cv->InBuffCount + TempLen;
718 return TRUE;
719 }
720 return FALSE;
721 }
722
723 /**
724 * �����o�b�t�@�����������������������l����
725 */
726 static void PackInBuff(PComVar cv)
727 {
728 if ( (cv->InPtr>0) && (cv->InBuffCount>0) ) {
729 memmove(cv->InBuff,&(cv->InBuff[cv->InPtr]),cv->InBuffCount);
730 cv->InPtr = 0;
731 }
732 }
733
734 int WINAPI CommBinaryBuffOut(PComVar cv, PCHAR B, int C)
735 {
736 int a, i, Len;
737 char d[3];
738
739 if ( ! cv->Ready ) {
740 return C;
741 }
742
743 i = 0;
744 a = 1;
745 while ((a>0) && (i<C)) {
746 Len = 0;
747
748 d[Len] = B[i];
749 Len++;
750
751 if (B[i] == CR) {
752 if ( cv->TelFlag && ! cv->TelBinSend ) {
753 d[Len++] = '\x00';
754 }
755 if (cv->TelLineMode) {
756 cv->Flush = TRUE;
757 }
758 }
759 else if ( cv->TelFlag && (B[i]=='\xff') ) {
760 d[Len++] = '\xff';
761 }
762
763 if (WriteOutBuff(cv, d, Len)) {
764 a = 1;
765 i++;
766 } else {
767 a = 0;
768 }
769 }
770 return i;
771 }
772
773 /**
774 * @retval true ���{�������p�J�^�J�i
775 * @retval false ������
776 */
777 static BOOL IsHalfWidthKatakana(unsigned int u32)
778 {
779 // Halfwidth CJK punctuation (U+FF61�`FF64)
780 // Halfwidth Katakana variants (U+FF65�`FF9F)
781 return (0xff61 <= u32 && u32 <= 0xff9f);
782 }
783
784 /**
785 * �o���p�A TODO echo�p������
786 * @param cv
787 * @param u32 ��������
788 * @param check_only TRUE���������s�����A
789 * @param TempStr �o��������
790 * @param StrLen TempStr�����o��������
791 * @retval �������s����
792 */
793 static BOOL OutControl(PComVar cv, unsigned int u32, BOOL check_only, char *TempStr, size_t *StrLen)
794 {
795 const wchar_t d = u32;
796 size_t TempLen = 0;
797 BOOL retval = FALSE;
798 if (check_only == TRUE) {
799 /* �`�F�b�N���� */
800 if (d == CR || d == BS || d == 0x15/*ctrl-u*/) {
801 return TRUE;
802 } else {
803 return FALSE;
804 }
805 }
806 if (d==CR) {
807 TempStr[TempLen++] = 0x0d;
808 if (cv->CRSend==IdCRLF) {
809 TempStr[TempLen++] = 0x0a;
810 }
811 else if ((cv->CRSend ==IdCR) &&
812 cv->TelFlag && ! cv->TelBinSend) {
813 TempStr[TempLen++] = 0;
814 }
815 else if (cv->CRSend == IdLF) {
816 TempStr[TempLen-1] = 0x0a;
817 }
818 if (cv->TelLineMode) {
819 cv->Flush = TRUE;
820 }
821 retval = TRUE;
822 }
823 else if (d== BS) {
824 if (cv->TelLineMode) {
825 if (cv->FlushLen < cv->LineModeBuffCount) {
826 cv->LineModeBuffCount--;
827 }
828 }
829 else {
830 TempStr[TempLen++] = BS;
831 }
832 retval = TRUE;
833 }
834 else if (d==0x15) { // ctrl-u
835 if (cv->TelLineMode) {
836 cv->LineModeBuffCount = cv->FlushLen;
837 }
838 else {
839 TempStr[TempLen++] = 0x15;
840 }
841 retval = TRUE;
842 }
843 *StrLen = TempLen;
844 return retval;
845 }
846 static BOOL ControlEcho(PComVar cv, unsigned int u32, BOOL check_only, char *TempStr, size_t *StrLen)
847 {
848 const wchar_t d = u32;
849 size_t TempLen = 0;
850 BOOL retval = FALSE;
851 if (check_only == TRUE) {
852 /* �`�F�b�N���� */
853 if (d == CR || (d == 0x15/*ctrl-u*/ && cv->TelLineMode)) {
854 return TRUE;
855 } else {
856 return FALSE;
857 }
858 }
859 if (d==CR) {
860 TempStr[TempLen++] = 0x0d;
861 if (cv->CRSend==IdCRLF) {
862 TempStr[TempLen++] = 0x0a;
863 }
864 else if ((cv->CRSend ==IdCR) && cv->TelFlag && ! cv->TelBinSend) {
865 TempStr[TempLen++] = 0;
866 }
867 else if (cv->CRSend == IdLF) {
868 TempStr[TempLen-1] = 0x0a;
869 }
870 retval = TRUE;
871 }
872 else if (d==0x15/*ctrl-u*/ && cv->TelLineMode) {
873 // Move to top of line (CHA "\033[G") and erase line (EL "\033[K")
874 memcpy(TempStr, "\033[G\033[K", 6);
875 TempLen += 6;
876 retval = TRUE;
877 }
878 *StrLen = TempLen;
879 return retval;
880 }
881
882 /**
883 * �o���p����������������
884 *
885 * @retval ��������������
886 */
887 typedef struct {
888 int KanjiCode; // [in]�o�������R�[�h(sjis,jis����)
889 BOOL (*ControlOut)(PComVar cv, unsigned int u32, BOOL check_only, char *TempStr, size_t *StrLen);
890 // state�����������K�v�����������R�[�h���g�p
891 BOOL JIS7Katakana; // [in](Kanji JIS)kana
892 int SendCode; // [in,out](Kanji JIS)���O�����M�R�[�h Ascii/Kana/Kanji
893 BOOL KanjiFlag; // [in,out](MBCS)���O��1byte��������������?(2byte������������?)
894 BYTE KanjiFirst; // [in,out](MBCS)���O��1byte
895 } OutputCharState;
896
897 /**
898 * unicode(UTF-16)����unicode(UTF-32)��1���������o����
899 * �o���f�[�^(TempStr)����������
900 */
901 static size_t MakeOutputString(PComVar cv, OutputCharState *states,
902 const wchar_t *B, int C,
903 char *TempStr, int *TempLen_)
904 {
905 BOOL (*ControlOut)(PComVar cv, unsigned int u32, BOOL check_only, char *TempStr, size_t *StrLen)
906 = states->ControlOut;
907 //
908 int TempLen = 0;
909 size_t TempLen2;
910 size_t output_char_count; // ��������������
911
912 // UTF-32 ��1���������o��
913 unsigned int u32;
914 size_t u16_len = UTF16ToUTF32(B, C, &u32);
915 if (u16_len == 0) {
916 // �f�R�[�h��������? ����������������?
917 assert(FALSE);
918 u32 = '?';
919 u16_len = 1;
920 }
921 output_char_count = u16_len;
922
923 // �e���V�t�g����������������
924 if (u32 < 0x100 || ControlOut(cv, u32, TRUE, NULL, NULL)) {
925 if (cv->Language == IdJapanese && states->KanjiCode == IdJIS) {
926 // �����������A���{��,JIS��������
927 if (cv->SendCode == IdKanji) {
928 // �����������������A����OUT
929 TempStr[TempLen++] = 0x1B;
930 TempStr[TempLen++] = '(';
931 switch (cv->KanjiOut) {
932 case IdKanjiOutJ:
933 TempStr[TempLen++] = 'J';
934 break;
935 case IdKanjiOutH:
936 TempStr[TempLen++] = 'H';
937 break;
938 default:
939 TempStr[TempLen++] = 'B';
940 }
941 }
942
943 if (states->JIS7Katakana == 1) {
944 if (cv->SendCode == IdKatakana) {
945 TempStr[TempLen++] = SO;
946 }
947 }
948
949 states->SendCode = IdASCII;
950 }
951 }
952
953 // 1������������
954 if (ControlOut(cv, u32, FALSE, TempStr, &TempLen2)) {
955 // ��������������������
956 TempLen += TempLen2;
957 output_char_count = 1;
958 } else if (cv->Language == IdUtf8 ||
959 (cv->Language == IdJapanese && states->KanjiCode == IdUTF8) ||
960 (cv->Language == IdKorean && states->KanjiCode == IdUTF8) ||
961 (cv->Language == IdChinese && states->KanjiCode == IdUTF8))
962 {
963 // UTF-8 ���o��
964 size_t utf8_len = sizeof(TempStr);
965 utf8_len = UTF32ToUTF8(u32, TempStr, utf8_len);
966 TempLen += utf8_len;
967 } else if (cv->Language == IdJapanese) {
968 // ���{��
969 // ���� CP932(SJIS) ���������������o��
970 char mb_char[2];
971 size_t mb_len = sizeof(mb_char);
972 mb_len = UTF32ToMBCP(u32, 932, mb_char, mb_len);
973 if (mb_len == 0) {
974 // SJIS��������������
975 TempStr[TempLen++] = '?';
976 } else {
977 switch (states->KanjiCode) {
978 case IdEUC:
979 // TODO ���p�J�i
980 if (mb_len == 1) {
981 TempStr[TempLen++] = mb_char[0];
982 } else {
983 WORD K;
984 K = (((WORD)(unsigned char)mb_char[0]) << 8) +
985 (WORD)(unsigned char)mb_char[1];
986 K = SJIS2EUC(K);
987 TempStr[TempLen++] = HIBYTE(K);
988 TempStr[TempLen++] = LOBYTE(K);
989 }
990 break;
991 case IdJIS:
992 if (u32 < 0x100) {
993 // ASCII
994 TempStr[TempLen++] = mb_char[0];
995 states->SendCode = IdASCII;
996 } else if (IsHalfWidthKatakana(u32)) {
997 // ���p�J�^�J�i
998 if (states->JIS7Katakana==1) {
999 if (cv->SendCode != IdKatakana) {
1000 TempStr[TempLen++] = SI;
1001 }
1002 TempStr[TempLen++] = mb_char[0] & 0x7f;
1003 } else {
1004 TempStr[TempLen++] = mb_char[0];
1005 }
1006 states->SendCode = IdKatakana;
1007 } else {
1008 // ����
1009 WORD K;
1010 K = (((WORD)(unsigned char)mb_char[0]) << 8) +
1011 (WORD)(unsigned char)mb_char[1];
1012 K = SJIS2JIS(K);
1013 if (states->SendCode != IdKanji) {
1014 // ����IN
1015 TempStr[TempLen++] = 0x1B;
1016 TempStr[TempLen++] = '$';
1017 if (cv->KanjiIn == IdKanjiInB) {
1018 TempStr[TempLen++] = 'B';
1019 }
1020 else {
1021 TempStr[TempLen++] = '@';
1022 }
1023 states->SendCode = IdKanji;
1024 }
1025 TempStr[TempLen++] = HIBYTE(K);
1026 TempStr[TempLen++] = LOBYTE(K);
1027 }
1028 break;
1029 case IdSJIS:
1030 if (mb_len == 1) {
1031 TempStr[TempLen++] = mb_char[0];
1032 } else {
1033 TempStr[TempLen++] = mb_char[0];
1034 TempStr[TempLen++] = mb_char[1];
1035 }
1036 break;
1037 default:
1038 assert(FALSE);
1039 break;
1040 }
1041 }
1042 } else if (cv->Language == IdRussian) {
1043 /* ����CP1251�����������o�� */
1044 char mb_char[2];
1045 size_t mb_len = sizeof(mb_char);
1046 BYTE b;
1047 mb_len = UTF32ToMBCP(u32, 1251, mb_char, mb_len);
1048 if (mb_len != 1) {
1049 b = '?';
1050 } else {
1051 b = RussConv(IdWindows, states->KanjiCode, mb_char[0]);
1052 }
1053 TempStr[TempLen++] = b;
1054 } else if (cv->Language == IdKorean || cv->Language == IdChinese) {
1055 int code_page;
1056 char mb_char[2];
1057 size_t mb_len;
1058 if (cv->Language == IdKorean) {
1059 code_page = 51949;
1060 } else if (cv->Language == IdChinese) {
1061 switch (states->KanjiCode) {
1062 case IdCnGB2312:
1063 code_page = 936;
1064 break;
1065 case IdCnBig5:
1066 code_page = 950;
1067 break;
1068 default:
1069 assert(FALSE);
1070 code_page = 936;
1071 break;
1072 }
1073 } else {
1074 assert(FALSE);
1075 code_page = 0;
1076 }
1077 /* code_page �����������o�� */
1078 mb_len = sizeof(mb_char);
1079 mb_len = UTF32ToMBCP(u32, code_page, mb_char, mb_len);
1080 if (mb_len == 0) {
1081 TempStr[TempLen++] = '?';
1082 }
1083 else if (mb_len == 1) {
1084 TempStr[TempLen++] = mb_char[0];
1085 } else {
1086 TempStr[TempLen++] = mb_char[0];
1087 TempStr[TempLen++] = mb_char[1];
1088 }
1089 } else if (cv->Language == IdEnglish) {
1090 char byte;
1091 int part = KanjiCodeToISO8859Part(states->KanjiCode);
1092 int r = UnicodeToISO8859(part, u32, &byte);
1093 if (r == 0) {
1094 // �����������������R�[�h������
1095 byte = '?';
1096 }
1097 TempStr[TempLen++] = byte;
1098 } else {
1099 assert(FALSE);
1100 }
1101
1102 *TempLen_ = TempLen;
1103 return output_char_count;
1104 }
1105
1106
1107 /**
1108 * CommTextOut() �� wchar_t ��
1109 *
1110 * @retval �o��������(wchar_t�P��)
1111 */
1112 int WINAPI CommTextOutW(PComVar cv, const wchar_t *B, int C)
1113 {
1114 char TempStr[12];
1115 BOOL Full = FALSE;
1116 int i = 0;
1117 while (! Full && (i < C)) {
1118 // �o���p�f�[�^������
1119 int TempLen = 0;
1120 size_t output_char_count; // ��������������
1121 OutputCharState state;
1122 state.KanjiCode = cv->KanjiCodeSend;
1123 state.ControlOut = OutControl;
1124 state.SendCode = cv->SendCode;
1125 state.JIS7Katakana = cv->JIS7KatakanaSend;
1126 output_char_count = MakeOutputString(cv, &state, &B[i], C-i, TempStr, &TempLen);
1127
1128 // �f�[�^���o���o�b�t�@��
1129 if (WriteOutBuff(cv, TempStr, TempLen)) {
1130 i += output_char_count; // output_char_count ������ ��������
1131 // ��������������������
1132 cv->SendCode = state.SendCode;
1133 } else {
1134 Full = TRUE;
1135 }
1136 } // end of "while {}"
1137 _CrtCheckMemory();
1138 return i;
1139 }
1140
1141 /**
1142 * CommTextEcho() �� wchar_t ��
1143 *
1144 * @retval �o��������(wchar_t�P��)
1145 */
1146 int WINAPI CommTextEchoW(PComVar cv, const wchar_t *B, int C)
1147 {
1148 char TempStr[12];
1149 BOOL Full = FALSE;
1150 int i = 0;
1151 while (! Full && (i < C)) {
1152 // �o���p�f�[�^������
1153 int TempLen = 0;
1154 size_t output_char_count; // ��������������
1155 OutputCharState state;
1156 state.KanjiCode = cv->KanjiCodeEcho;
1157 state.ControlOut = ControlEcho;
1158 state.SendCode = cv->EchoCode;
1159 state.JIS7Katakana = cv->JIS7KatakanaEcho;
1160 output_char_count = MakeOutputString(cv, &state, &B[i], C-i, TempStr, &TempLen);
1161
1162 // �f�[�^���o���o�b�t�@��
1163 if (WriteInBuff(cv, TempStr, TempLen)) {
1164 i += output_char_count; // output_char_count ������ ��������
1165 // ��������������������
1166 cv->EchoCode = state.SendCode;
1167 } else {
1168 Full = TRUE;
1169 }
1170 } // end of "while {}"
1171 _CrtCheckMemory();
1172 return i;
1173 }
1174
1175 int WINAPI CommBinaryEcho(PComVar cv, PCHAR B, int C)
1176 {
1177 int a, i, Len;
1178 char d[3];
1179
1180 if ( ! cv->Ready )
1181 return C;
1182
1183 PackInBuff(cv);
1184
1185 i = 0;
1186 a = 1;
1187 while ((a>0) && (i<C)) {
1188 Len = 0;
1189
1190 d[Len] = B[i];
1191 Len++;
1192
1193 if ( cv->TelFlag && (B[i]=='\x0d') &&
1194 ! cv->TelBinSend ) {
1195 d[Len] = 0x00;
1196 Len++;
1197 }
1198
1199 if ( cv->TelFlag && (B[i]=='\xff') ) {
1200 d[Len] = '\xff';
1201 Len++;
1202 }
1203
1204 if (WriteInBuff(cv, d, Len)) {
1205 a = 1;
1206 i++;
1207 } else {
1208 a = 0;
1209 }
1210 }
1211 return i;
1212 }
1213
1214 /**
1215 * ���L�����������|�C���^���Z�b�g
1216 */
1217 DllExport void WINAPI SetPMPtr(PMap pm_)
1218 {
1219 pm = pm_;
1220 }
1221
1222 BOOL WINAPI DllMain(HANDLE hInstance,
1223 ULONG ul_reason_for_call,
1224 LPVOID lpReserved)
1225 {
1226 switch( ul_reason_for_call ) {
1227 case DLL_THREAD_ATTACH:
1228 /* do thread initialization */
1229 break;
1230 case DLL_THREAD_DETACH:
1231 /* do thread cleanup */
1232 break;
1233 case DLL_PROCESS_ATTACH:
1234 /* do process initialization */
1235 #ifdef _DEBUG
1236 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
1237 #endif
1238 WinCompatInit();
1239 break;
1240 case DLL_PROCESS_DETACH:
1241 /* do process cleanup */
1242 // TODO ttermpro.exe���s��
1243 // CloseSharedMemory(pm, HMap);
1244 break;
1245 }
1246 return TRUE;
1247 }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26