Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/teraterm/teraterm/filesys_log.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10804 - (show annotations) (download) (as text)
Sun Jul 23 07:07:16 2023 UTC (8 months, 2 weeks ago) by zmatsuo
File MIME type: text/x-c++src
File size: 27962 byte(s)
ログダイアログを logdlg.cpp,h に分離した

- teraterm/teraterm/logdlg.cpp,h 追加
1 /*
2 * (C) 2020- TeraTerm Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /* TERATERM.EXE, log routines */
30 #include <stdio.h>
31 #if !defined(_CRTDBG_MAP_ALLOC)
32 #define _CRTDBG_MAP_ALLOC
33 #endif
34 #include <stdlib.h>
35 #include <crtdbg.h>
36 #include <process.h>
37 #include <windows.h>
38 #include <htmlhelp.h>
39 #include <assert.h>
40
41 #include "teraterm.h"
42 #include "tttypes.h"
43 #include "ftdlg.h"
44 #include "ttwinman.h"
45 #include "commlib.h"
46 #include "ttcommon.h"
47 #include "ttlib.h"
48 #include "dlglib.h"
49 #include "vtterm.h"
50 #include "ftlib.h"
51 #include "buffer.h"
52 #include "helpid.h"
53 #include "codeconv.h"
54 #include "asprintf.h"
55 #include "win32helper.h"
56
57 #include "filesys_log_res.h"
58 #include "filesys_log.h"
59 #include "filesys.h" // for ProtoGetProtoFlag()
60
61 #define TitLog L"Log"
62
63 /*
64 Line Head flag for timestamping
65 2007.05.24 Gentaro
66 */
67 enum enumLineEnd {
68 Line_Other = 0,
69 Line_LineHead = 1,
70 Line_FileHead = 2,
71 };
72
73 typedef struct {
74 wchar_t *FullName;
75
76 HANDLE FileHandle;
77 LONG FileSize, ByteCount;
78
79 DWORD StartTime;
80
81 enum enumLineEnd eLineEnd;
82
83 // log rotate
84 int RotateMode; // enum rotate_mode RotateMode;
85 LONG RotateSize;
86 int RotateStep;
87
88 HANDLE LogThread;
89 DWORD LogThreadId;
90 HANDLE LogThreadEvent;
91
92 BOOL IsPause;
93
94 PFileTransDlg FLogDlg;
95
96 LogCode_t log_code;
97 BOOL bom;
98
99 BOOL FileLog;
100 BOOL BinLog;
101 } TFileVar;
102 typedef TFileVar *PFileVar;
103
104 static PFileVar LogVar = NULL;
105
106 static PCHAR cv_LogBuf;
107 static int cv_LogPtr, cv_LStart, cv_LCount;
108 static PCHAR cv_BinBuf;
109 static int cv_BinPtr, cv_BStart, cv_BCount;
110 static int cv_BinSkip;
111
112 // �x�����������p�X���b�h�����b�Z�[�W
113 #define WM_DPC_LOGTHREAD_SEND (WM_APP + 1)
114
115 static void Log1Bin(BYTE b);
116 static void LogBinSkip(int add);
117 static BOOL CreateLogBuf(void);
118 static BOOL CreateBinBuf(void);
119 void LogPut1(BYTE b);
120 static void OutputStr(const wchar_t *str);
121 static void LogToFile(PFileVar fv);
122 static void FLogOutputBOM(PFileVar fv);
123
124 static BOOL OpenFTDlg_(PFileVar fv)
125 {
126 PFileTransDlg FTDlg = new CFileTransDlg();
127 if (FTDlg == NULL) {
128 return FALSE;
129 }
130
131 wchar_t *DlgCaption;
132 wchar_t *uimsg;
133 GetI18nStrWW("Tera Term", "FILEDLG_TRANS_TITLE_LOG", TitLog, ts.UILanguageFileW, &uimsg);
134 aswprintf(&DlgCaption, L"Tera Term: %s", uimsg);
135 free(uimsg);
136
137 CFileTransDlg::Info info;
138 info.UILanguageFileW = ts.UILanguageFileW;
139 info.OpId = CFileTransDlg::OpLog;
140 info.DlgCaption = DlgCaption;
141 info.FileName = NULL;
142 info.FullName = fv->FullName;
143 info.HideDialog = ts.LogHideDialog ? TRUE : FALSE;
144 info.HMainWin = HVTWin;
145 FTDlg->Create(hInst, &info);
146 FTDlg->RefreshNum(0, fv->FileSize, fv->ByteCount);
147
148 fv->FLogDlg = FTDlg;
149
150 free(DlgCaption);
151 return TRUE;
152 }
153
154 /**
155 * �t�@�C�������������u������,���O�p
156 * �����������u��������
157 * &h �z�X�g�����u��
158 * &p TCP�|�[�g�������u��
159 * &u ���O�I���������[�U��
160 *
161 * @param pcv
162 * @param src �u���������O��������(�t�@�C����)
163 * @return �u������������������
164 * �s�v����������free()��������
165 */
166 static wchar_t *ConvertLognameW(const TComVar *pcv, const wchar_t *src)
167 {
168 const TTTSet *pts = pcv->ts;
169 size_t dest_len = wcslen(src) + 1;
170 wchar_t *dest = (wchar_t *)malloc(sizeof(wchar_t) * dest_len);
171
172 const wchar_t *s = src;
173 size_t i = 0;
174
175 while(*s != '\0') {
176 if (*s == '&' && *(s+1) != '\0') {
177 wchar_t c = *(s+1);
178 wchar_t *add_text = NULL;
179 switch (c) {
180 case 'h':
181 s += 2;
182 if (pcv->Open) {
183 switch(pcv->PortType) {
184 case IdTCPIP: {
185 // �z�X�g����IPv6�A�h���X�����A�t�@�C�������g�p������������(:)�����������u��
186 wchar_t *host = ToWcharA(pts->HostName);
187 wchar_t *host_fix = replaceInvalidFileNameCharW(host, '_');
188 free(host);
189 add_text = host_fix;
190 break;
191 }
192 case IdSerial: {
193 wchar_t *port;
194 aswprintf(&port, L"COM%d", ts.ComPort);
195 add_text = port;
196 break;
197 }
198 default:
199 ;
200 }
201 }
202 break;
203 case 'p':
204 s += 2;
205 if (pcv->Open) {
206 if (pcv->PortType == IdTCPIP) {
207 wchar_t *port;
208 aswprintf(&port, L"%d", ts.TCPPort);
209 add_text = port;
210 }
211 }
212 break;
213 case 'u': {
214 s += 2;
215 wchar_t user[256 + 1]; // 256=UNLEN
216 DWORD l = _countof(user);
217 if (GetUserNameW(user, &l) != 0) {
218 add_text = _wcsdup(user);
219 }
220 break;
221 }
222 default:
223 // pass '&'
224 s++;
225 add_text = NULL;
226 break;
227 }
228
229 if (add_text != NULL) {
230 size_t l = wcslen(add_text);
231 dest_len += l;
232 dest = (wchar_t *)realloc(dest, sizeof(wchar_t) * dest_len);
233 wcscpy(&dest[i], add_text);
234 free(add_text);
235 i += l;
236 }
237 }
238 else {
239 dest[i] = *s++;
240 i++;
241 }
242 }
243 dest[i] = 0;
244 return dest;
245 }
246
247 static void FixLogOption(void)
248 {
249 if (ts.LogBinary) {
250 ts.LogTypePlainText = false;
251 ts.LogTimestamp = false;
252 }
253 }
254
255
256 // �X���b�h���I�����t�@�C�����N���[�Y
257 static void CloseFileSync(PFileVar fv)
258 {
259 BOOL ret;
260
261 if (fv->FileHandle == INVALID_HANDLE_VALUE) {
262 return;
263 }
264
265 if (fv->LogThread != INVALID_HANDLE_VALUE) {
266 // �X���b�h���I������
267 ret = PostThreadMessage(fv->LogThreadId, WM_QUIT, 0, 0);
268 if (ret != 0) {
269 // �X���b�h�L���[���G���L���[���������������������������s���B
270 WaitForSingleObject(fv->LogThread, INFINITE);
271 }
272 else {
273 //DWORD code = GetLastError();
274 }
275 CloseHandle(fv->LogThread);
276 fv->LogThread = INVALID_HANDLE_VALUE;
277 }
278 CloseHandle(fv->FileHandle);
279 fv->FileHandle = INVALID_HANDLE_VALUE;
280 }
281
282 // �x�����������p�X���b�h
283 static unsigned _stdcall DeferredLogWriteThread(void *arg)
284 {
285 MSG msg;
286 PFileVar fv = (PFileVar)arg;
287 PCHAR buf;
288 DWORD buflen;
289 DWORD wrote;
290
291 PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
292
293 // �X���b�h�L���[���������I�������������X���b�h�����������m�����B
294 if (fv->LogThreadEvent != NULL) {
295 SetEvent(fv->LogThreadEvent);
296 }
297
298 while (GetMessage(&msg, NULL, 0, 0) > 0) {
299 switch (msg.message) {
300 case WM_DPC_LOGTHREAD_SEND:
301 buf = (PCHAR)msg.wParam;
302 buflen = (DWORD)msg.lParam;
303 WriteFile(fv->FileHandle, buf, buflen, &wrote, NULL);
304 free(buf); // ����������������
305 break;
306
307 case WM_QUIT:
308 goto end;
309 break;
310 }
311 }
312
313 end:
314 _endthreadex(0);
315 return (0);
316 }
317
318 // �x�����������p�X���b�h���N�����B
319 // (2013.4.19 yutaka)
320 // DeferredLogWriteThread �X���b�h���N�������A�X���b�h�L���[�����������������O���A
321 // ���O�t�@�C�����N���[�Y(CloseFileSync)���s���������A�G���L���[�����s���A�f�b�h���b�N
322 // �����������������C�������B
323 // �X���b�h�����������s�������A���O�����C�x���g�I�u�W�F�N�g���g�����A�X���b�h�L���[��
324 // ���������������������������������B���O�t���C�x���g�I�u�W�F�N�g���g���������A
325 // �V�X�e��(Windows OS)�������j�[�N�����O�������K�v�������B
326 // (2016.9.23 yutaka)
327 static void StartThread(PFileVar fv)
328 {
329 unsigned tid;
330 fv->LogThreadEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
331 fv->LogThread = (HANDLE)_beginthreadex(NULL, 0, DeferredLogWriteThread, fv, 0, &tid);
332 fv->LogThreadId = tid;
333 if (fv->LogThreadEvent != NULL) {
334 WaitForSingleObject(fv->LogThreadEvent, INFINITE);
335 CloseHandle(fv->LogThreadEvent);
336 }
337 }
338
339 static void OpenLogFile(PFileVar fv)
340 {
341 // LogLockExclusive ���L���������������������L���������A
342 // ���������������O�t�@�C���������G�f�B�^���J����������
343 int dwShareMode = FILE_SHARE_READ;
344 if (!ts.LogLockExclusive) {
345 dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
346 }
347 fv->FileHandle = CreateFileW(fv->FullName, GENERIC_WRITE, dwShareMode, NULL,
348 OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
349 }
350
351 static BOOL LogStart(PFileVar fv, const wchar_t *fname)
352 {
353 fv->FullName = _wcsdup(fname);
354 FixLogOption();
355
356 if (ts.LogBinary > 0)
357 {
358 fv->BinLog = TRUE;
359 fv->FileLog = FALSE;
360 if (! CreateBinBuf())
361 {
362 return FALSE;
363 }
364 }
365 else {
366 fv->BinLog = FALSE;
367 fv->FileLog = TRUE;
368 if (! CreateLogBuf())
369 {
370 return FALSE;
371 }
372 }
373 cv_LStart = cv_LogPtr;
374 cv_LCount = 0;
375
376 OpenLogFile(fv);
377 if (fv->FileHandle == INVALID_HANDLE_VALUE) {
378 return FALSE;
379 }
380
381 /* 2007.05.24 Gentaro */
382 fv->eLineEnd = Line_LineHead;
383 if (ts.Append > 0)
384 {
385 SetFilePointer(fv->FileHandle, 0, NULL, FILE_END);
386 /* 2007.05.24 Gentaro
387 If log file already exists,
388 a newline is inserted before the first timestamp.
389 */
390 fv->eLineEnd = Line_FileHead;
391 }
392
393 // BOM�o��
394 if (ts.Append == 0 && ts.LogBinary == 0 && fv->bom) {
395 // ���L��������(�V�K) && �o�C�i���������� && BOM ���o����
396 FLogOutputBOM(fv);
397 }
398
399 // Log rotate configuration
400 fv->RotateMode = ts.LogRotate;
401 fv->RotateSize = ts.LogRotateSize;
402 fv->RotateStep = ts.LogRotateStep;
403
404 // Log rotate���L���������A�����t�@�C���T�C�Y�����������B
405 // �������t�@�C�������������T�C�Y�����[�e�[�g�������������C���B
406 // (2016.4.9 yutaka)
407 if (fv->RotateMode != ROTATE_NONE) {
408 DWORD size = GetFileSize(fv->FileHandle, NULL);
409 if (size == -1) {
410 return FALSE;
411 }
412 fv->ByteCount = size;
413 }
414 else {
415 fv->ByteCount = 0;
416 }
417
418 if (! OpenFTDlg_(fv)) {
419 return FALSE;
420 }
421
422 fv->IsPause = FALSE;
423 fv->StartTime = GetTickCount();
424
425 if (ts.DeferredLogWriteMode) {
426 StartThread(fv);
427 }
428
429 if (fv->FileLog) {
430 cv.Log1Byte = LogPut1;
431 }
432 if (fv->BinLog) {
433 cv.Log1Bin = Log1Bin;
434 cv.LogBinSkip = LogBinSkip;
435 }
436
437 return TRUE;
438 }
439
440 /**
441 * �����o�b�t�@�������f�[�^�����������O�������o��
442 * (2013.9.29 yutaka)
443 *
444 * TODO
445 * 1�s������
446 */
447 void FLogOutputAllBuffer(void)
448 {
449 PFileVar fv = LogVar;
450 DWORD ofs;
451 int size;
452 wchar_t buf[512];
453 for (ofs = 0 ; ; ofs++ ) {
454 // 1�����s�����������B���������������A�G�X�P�[�v�V�[�P���X�������������B
455 size = BuffGetAnyLineDataW(ofs, buf, _countof(buf));
456 if (size == -1)
457 break;
458
459 OutputStr(buf);
460 OutputStr(L"\r\n");
461 LogToFile(fv);
462 }
463 }
464
465 /**
466 * ���O��1byte��������
467 * �o�b�t�@��������������
468 * ���������������� LogToFile() ���s������
469 */
470 void LogPut1(BYTE b)
471 {
472 PFileVar fv = LogVar;
473
474 cv_LogBuf[cv_LogPtr] = b;
475 cv_LogPtr++;
476 if (cv_LogPtr>=InBuffSize)
477 cv_LogPtr = cv_LogPtr-InBuffSize;
478
479 if (fv->FileLog)
480 {
481 if (cv_LCount>=InBuffSize)
482 {
483 cv_LCount = InBuffSize;
484 cv_LStart = cv_LogPtr;
485 }
486 else
487 cv_LCount++;
488 }
489 else
490 cv_LCount = 0;
491 }
492
493 static BOOL Get1(PCHAR Buf, int *Start, int *Count, PBYTE b)
494 {
495 if (*Count<=0) return FALSE;
496 *b = Buf[*Start];
497 (*Start)++;
498 if (*Start>=InBuffSize)
499 *Start = *Start-InBuffSize;
500 (*Count)--;
501 return TRUE;
502 }
503
504
505
506 static CRITICAL_SECTION g_filelog_lock; /* ���b�N�p���� */
507
508 void logfile_lock_initialize(void)
509 {
510 InitializeCriticalSection(&g_filelog_lock);
511 }
512
513 static inline void logfile_lock(void)
514 {
515 EnterCriticalSection(&g_filelog_lock);
516 }
517
518 static inline void logfile_unlock(void)
519 {
520 LeaveCriticalSection(&g_filelog_lock);
521 }
522
523 // ���O�����[�e�[�g�����B
524 // (2013.3.21 yutaka)
525 static void LogRotate(PFileVar fv)
526 {
527 int loopmax = 10000; // XXX
528 int i, k;
529
530 if (fv->RotateMode == ROTATE_NONE)
531 return;
532
533 if (fv->RotateMode == ROTATE_SIZE) {
534 if (fv->ByteCount <= fv->RotateSize)
535 return;
536 //OutputDebugPrintf("%s: mode %d size %ld\n", __FUNCTION__, fv->RotateMode, fv->ByteCount);
537 } else {
538 return;
539 }
540
541 logfile_lock();
542 // ���O�T�C�Y���������������B
543 fv->ByteCount = 0;
544
545 // �������������t�@�C�����N���[�Y�����A�������t�@�C�����I�[�v�������B
546 CloseFileSync(fv);
547
548 // �������[�e�[�V�������X�e�b�v�����w����������
549 if (fv->RotateStep > 0)
550 loopmax = fv->RotateStep;
551
552 for (i = 1 ; i <= loopmax ; i++) {
553 wchar_t *filename;
554 aswprintf(&filename, L"%s.%d", fv->FullName, i);
555 DWORD attr = GetFileAttributesW(filename);
556 free(filename);
557 if (attr == INVALID_FILE_ATTRIBUTES)
558 break;
559 }
560 if (i > loopmax) {
561 // �������������������������A�������t�@�C�������p�������B
562 i = loopmax;
563 }
564
565 // ���t�@�C�������l�[���B
566 for (k = i-1 ; k >= 0 ; k--) {
567 wchar_t *oldfile;
568 if (k == 0)
569 oldfile = _wcsdup(fv->FullName);
570 else
571 aswprintf(&oldfile, L"%s.%d", fv->FullName, k);
572 wchar_t *newfile;
573 aswprintf(&newfile, L"%s.%d", fv->FullName, k+1);
574 DeleteFileW(newfile);
575 if (MoveFileW(oldfile, newfile) == 0) {
576 OutputDebugPrintf("%s: rename %d\n", __FUNCTION__, errno);
577 }
578 free(oldfile);
579 free(newfile);
580 }
581
582 // ���I�[�v��
583 OpenLogFile(fv);
584 if (fv->bom) {
585 FLogOutputBOM(fv);
586 }
587 if (ts.DeferredLogWriteMode) {
588 StartThread(fv);
589 }
590
591 logfile_unlock();
592 }
593
594 static wchar_t *TimeStampStr(PFileVar fv)
595 {
596 char *strtime = NULL;
597 switch (ts.LogTimestampType) {
598 case TIMESTAMP_LOCAL:
599 default:
600 strtime = mctimelocal(ts.LogTimestampFormat, FALSE);
601 break;
602 case TIMESTAMP_UTC:
603 strtime = mctimelocal(ts.LogTimestampFormat, TRUE);
604 break;
605 case TIMESTAMP_ELAPSED_LOGSTART:
606 strtime = strelapsed(fv->StartTime);
607 break;
608 case TIMESTAMP_ELAPSED_CONNECTED:
609 strtime = strelapsed(cv.ConnectedTime);
610 break;
611 }
612
613 char tmp[128];
614 tmp[0] = 0;
615 strncat_s(tmp, sizeof(tmp), "[", _TRUNCATE);
616 strncat_s(tmp, sizeof(tmp), strtime, _TRUNCATE);
617 strncat_s(tmp, sizeof(tmp), "] ", _TRUNCATE);
618
619 return ToWcharA(tmp);
620 }
621
622 /**
623 * �o�b�t�@�������O���t�@�C������������
624 */
625 static void LogToFile(PFileVar fv)
626 {
627 PCHAR Buf;
628 int Start, Count;
629 BYTE b;
630
631 if (fv->FileLog)
632 {
633 Buf = cv_LogBuf;
634 Start = cv_LStart;
635 Count = cv_LCount;
636 }
637 else if (fv->BinLog)
638 {
639 Buf = cv_BinBuf;
640 Start = cv_BStart;
641 Count = cv_BCount;
642 }
643 else
644 return;
645
646 if (Buf==NULL) return;
647 if (Count==0) return;
648
649 // ���b�N������(2004.8.6 yutaka)
650 logfile_lock();
651
652 // ���������f�[�^����������
653 DWORD WriteBufMax = 8192;
654 DWORD WriteBufLen = 0;
655 PCHAR WriteBuf = (PCHAR)malloc(WriteBufMax);
656 while (Get1(Buf,&Start,&Count,&b)) {
657 if (FLogIsPause() || ProtoGetProtoFlag()) {
658 continue;
659 }
660
661 if (WriteBufLen >= (WriteBufMax*4/5)) {
662 WriteBufMax *= 2;
663 WriteBuf = (PCHAR)realloc(WriteBuf, WriteBufMax);
664 }
665
666 WriteBuf[WriteBufLen++] = b;
667
668 (fv->ByteCount)++;
669 }
670
671 // ��������
672 if (WriteBufLen > 0) {
673 if (ts.DeferredLogWriteMode) {
674 PostThreadMessage(fv->LogThreadId, WM_DPC_LOGTHREAD_SEND, (WPARAM)WriteBuf, WriteBufLen);
675 }
676 else {
677 DWORD wrote;
678 WriteFile(fv->FileHandle, WriteBuf, WriteBufLen, &wrote, NULL);
679 free(WriteBuf);
680 }
681 }
682
683 logfile_unlock();
684
685 if (fv->FileLog)
686 {
687 cv_LStart = Start;
688 cv_LCount = Count;
689 }
690 else {
691 cv_BStart = Start;
692 cv_BCount = Count;
693 }
694 if (FLogIsPause() || ProtoGetProtoFlag()) return;
695 fv->FLogDlg->RefreshNum(fv->StartTime, fv->FileSize, fv->ByteCount);
696
697
698 // ���O�E���[�e�[�g
699 LogRotate(fv);
700 }
701
702 static BOOL CreateLogBuf(void)
703 {
704 if (cv_LogBuf==NULL)
705 {
706 cv_LogBuf = (char *)malloc(InBuffSize);
707 cv_LogPtr = 0;
708 cv_LStart = 0;
709 cv_LCount = 0;
710 }
711 return (cv_LogBuf!=NULL);
712 }
713
714 static void FreeLogBuf(void)
715 {
716 free(cv_LogBuf);
717 cv_LogBuf = NULL;
718 cv_LogPtr = 0;
719 cv_LStart = 0;
720 cv_LCount = 0;
721 }
722
723 static BOOL CreateBinBuf(void)
724 {
725 if (cv_BinBuf==NULL)
726 {
727 cv_BinBuf = (PCHAR)malloc(InBuffSize);
728 cv_BinPtr = 0;
729 cv_BStart = 0;
730 cv_BCount = 0;
731 }
732 return (cv_BinBuf!=NULL);
733 }
734
735 static void FreeBinBuf(void)
736 {
737 free(cv_BinBuf);
738 cv_BinBuf = NULL;
739 cv_BinPtr = 0;
740 cv_BStart = 0;
741 cv_BCount = 0;
742 }
743
744 static void FileTransEnd_(PFileVar fv)
745 {
746 fv->FileLog = FALSE;
747 fv->BinLog = FALSE;
748 cv.Log1Byte = NULL;
749 cv.Log1Bin = NULL;
750 cv.LogBinSkip = NULL;
751 PFileTransDlg FLogDlg = fv->FLogDlg;
752 if (FLogDlg != NULL) {
753 FLogDlg->DestroyWindow();
754 FLogDlg = NULL;
755 fv->FLogDlg = NULL;
756 }
757 CloseFileSync(fv);
758 FreeLogBuf();
759 FreeBinBuf();
760 free(fv->FullName);
761 fv->FullName = NULL;
762 free(fv);
763
764 LogVar = NULL;
765 }
766
767 /**
768 * ���O���|�[�Y����
769 */
770 void FLogPause(BOOL Pause)
771 {
772 PFileVar fv = LogVar;
773 if (fv == NULL) {
774 return;
775 }
776 fv->IsPause = Pause;
777 fv->FLogDlg->ChangeButton(Pause);
778 }
779
780 /**
781 * ���O���[�e�[�g������
782 * ���O���T�C�Y��<size>�o�C�g���������������A���[�e�[�V��������������������
783 */
784 void FLogRotateSize(size_t size)
785 {
786 PFileVar fv = LogVar;
787 if (fv == NULL) {
788 return;
789 }
790 fv->RotateMode = ROTATE_SIZE;
791 fv->RotateSize = (LONG)size;
792 }
793
794 /**
795 * ���O���[�e�[�g������
796 * ���O�t�@�C������������������
797 */
798 void FLogRotateRotate(int step)
799 {
800 PFileVar fv = LogVar;
801 if (fv == NULL) {
802 return;
803 }
804 fv->RotateStep = step;
805 }
806
807 /**
808 * ���O���[�e�[�g������
809 * ���[�e�[�V���������~
810 */
811 void FLogRotateHalt(void)
812 {
813 PFileVar fv = LogVar;
814 if (fv == NULL) {
815 return;
816 }
817 fv->RotateMode = ROTATE_NONE;
818 fv->RotateSize = 0;
819 fv->RotateStep = 0;
820 }
821
822 static INT_PTR CALLBACK OnCommentDlgProc(HWND hDlgWnd, UINT msg, WPARAM wp, LPARAM)
823 {
824 static const DlgTextInfo TextInfos[] = {
825 { 0, "DLG_COMMENT_TITLE" },
826 { IDOK, "BTN_OK" }
827 };
828
829 switch (msg) {
830 case WM_INITDIALOG:
831 // �G�f�B�b�g�R���g���[�����t�H�[�J�X��������
832 SetFocus(GetDlgItem(hDlgWnd, IDC_EDIT_COMMENT));
833 SetDlgTextsW(hDlgWnd, TextInfos, _countof(TextInfos), ts.UILanguageFileW);
834 return FALSE;
835
836 case WM_COMMAND:
837 switch (LOWORD(wp)) {
838 case IDOK: {
839 size_t len = SendDlgItemMessageW(hDlgWnd, IDC_EDIT_COMMENT, WM_GETTEXTLENGTH, 0, 0);
840 len += 1;
841 wchar_t *buf = (wchar_t *)malloc(len * sizeof(wchar_t));
842 GetDlgItemTextW(hDlgWnd, IDC_EDIT_COMMENT, buf, (int)len);
843 FLogWriteStr(buf);
844 FLogWriteStr(L"\n"); // TODO ���s�R�[�h
845 free(buf);
846 TTEndDialog(hDlgWnd, IDOK);
847 break;
848 }
849 default:
850 return FALSE;
851 }
852 break;
853
854 case WM_CLOSE:
855 TTEndDialog(hDlgWnd, 0);
856 return TRUE;
857
858 default:
859 return FALSE;
860 }
861 return TRUE;
862 }
863
864 /**
865 * ���O�t�@�C�����R�����g���������� (2004.8.6 yutaka)
866 */
867 void FLogAddCommentDlg(HINSTANCE hInst, HWND hWnd)
868 {
869 PFileVar fv = LogVar;
870 if (fv == NULL) {
871 return;
872 }
873 TTDialogBox(hInst, MAKEINTRESOURCE(IDD_COMMENT_DIALOG),
874 hWnd, OnCommentDlgProc);
875 }
876
877 void FLogClose(void)
878 {
879 PFileVar fv = LogVar;
880 if (fv == NULL) {
881 return;
882 }
883
884 FileTransEnd_(fv);
885 }
886
887 /**
888 * ���O���I�[�v������
889 * @param[in] fname ���O�t�@�C����, CreateFile()���n������
890 *
891 * ���O�t�@�C������strftime���W�J�������s���������B
892 * FLogGetLogFilename() �� FLogOpenDialog() ��
893 * �t�@�C�����������������B
894 */
895 BOOL FLogOpen(const wchar_t *fname, LogCode_t code, BOOL bom)
896 {
897 if (LogVar != NULL) {
898 return FALSE;
899 }
900
901 //
902 PFileVar fv = (PFileVar)malloc(sizeof(*fv));
903 if (fv == NULL) {
904 return FALSE;
905 }
906 LogVar = fv;
907 memset(fv, 0, sizeof(TFileVar));
908 fv->FileHandle = INVALID_HANDLE_VALUE;
909 fv->LogThread = INVALID_HANDLE_VALUE;
910 fv->eLineEnd = Line_LineHead;
911
912 fv->log_code = code;
913 fv->bom = bom;
914 BOOL ret = LogStart(fv, fname);
915 if (ret == FALSE) {
916 FileTransEnd_(fv);
917 }
918
919 return ret;
920 }
921
922 BOOL FLogIsOpend(void)
923 {
924 return LogVar != NULL;
925 }
926
927 BOOL FLogIsOpendText(void)
928 {
929 return LogVar != NULL && LogVar->FileLog;
930 }
931
932 BOOL FLogIsOpendBin(void)
933 {
934 return LogVar != NULL && LogVar->BinLog;
935 }
936
937 void FLogWriteStr(const wchar_t *str)
938 {
939 if (LogVar != NULL) {
940 OutputStr(str);
941 }
942 }
943
944 void FLogInfo(char *param_ptr, size_t param_len)
945 {
946 PFileVar fv = LogVar;
947 if (fv) {
948 param_ptr[0] = '0'
949 + (ts.LogBinary != 0)
950 + ((ts.Append != 0) << 1)
951 + ((ts.LogTypePlainText != 0) << 2)
952 + ((ts.LogTimestamp != 0) << 3)
953 + ((ts.LogHideDialog != 0) << 4);
954 char *filenameU8 = ToU8W(fv->FullName);
955 strncpy_s(param_ptr + 1, param_len - 1, filenameU8, _TRUNCATE);
956 free(filenameU8);
957 }
958 else {
959 param_ptr[0] = '0' - 1;
960 param_ptr[1] = 0;
961 }
962 }
963
964 /**
965 * ���������O�t�@�C����������
966 */
967 const wchar_t *FLogGetFilename(void)
968 {
969 if (LogVar == NULL) {
970 return NULL;
971 }
972 return LogVar->FullName;
973 }
974
975 /**
976 * ���O�t�@�C�����p���C�����s��,�t�@�C������������
977 * - strftime() ���������t�W�J
978 * - �������������O�t�@�C���t�H���_������
979 * - �z�X�g��,�|�[�g�����W�J
980 *
981 * @param filename �t�@�C����(�p�X����������)
982 * @return �C�������t�@�C����
983 */
984 wchar_t *FLogGetLogFilenameBase(const wchar_t *filename)
985 {
986 // �t�@�C�������������o
987 const wchar_t *last_path_sep = wcsrchr(filename, L'\\');
988 wchar_t *format;
989 if (last_path_sep == NULL) {
990 format = _wcsdup(filename);
991 }
992 else {
993 format = _wcsdup(last_path_sep + 1);
994 }
995
996 // strftime ���g�p������������������
997 deleteInvalidStrftimeCharW(format);
998
999 // ����������0��������?
1000 if (format[0] == 0) {
1001 free(format);
1002 return _wcsdup(L"");
1003 }
1004
1005 // ��������������
1006 time_t time_local;
1007 time(&time_local);
1008 struct tm tm_local;
1009 localtime_s(&tm_local, &time_local);
1010
1011 // strftime()������
1012 // ���������������g��
1013 size_t len = 32;
1014 wchar_t *formated = NULL;
1015 while (1) {
1016 wchar_t *formated_realloc = (wchar_t *)realloc(formated, sizeof(wchar_t) * len);
1017 if (formated_realloc == NULL) {
1018 free(format);
1019 free(formated);
1020 return _wcsdup(L"");
1021 }
1022 formated = formated_realloc;
1023 size_t r = wcsftime(formated, len, format, &tm_local);
1024 if (r != 0) {
1025 // �t�H�[�}�b�g������
1026 break;
1027 }
1028 len *= 2;
1029 }
1030 free(format);
1031
1032 // �z�X�g������
1033 wchar_t *host = ConvertLognameW(&cv, formated);
1034 free(formated);
1035
1036 // �t�@�C�������g�p���������������u��
1037 //wchar_t *replaced = replaceInvalidFileNameCharW(host, 0); // ����
1038 wchar_t *replaced = replaceInvalidFileNameCharW(host, L'_');
1039 free(host);
1040
1041 return replaced;
1042 }
1043
1044 /**
1045 * ���O�t�@�C����������
1046 * ���O�t�@�C�����p���C�����s��
1047 * - strftime() ���������t�W�J
1048 * - �������������O�t�@�C���t�H���_������
1049 * - �z�X�g��,�|�[�g�����W�J
1050 *
1051 * @param[in] log_filename �t�@�C����(����/��������������ok)
1052 * NULL�������f�t�H���g�t�@�C����������
1053 * strftime�`��ok
1054 * @return �t���p�X�t�@�C����
1055 * �s�v���������� free() ��������
1056 */
1057 wchar_t *FLogGetLogFilename(const wchar_t *log_filename)
1058 {
1059 wchar_t *dir;
1060 wchar_t *fname;
1061 if (log_filename == NULL) {
1062 dir = _wcsdup(ts.LogDefaultPathW);
1063 fname = _wcsdup(ts.LogDefaultNameW);
1064 } else if (!IsRelativePathW(log_filename)) {
1065 // �����p�X������������
1066 dir = ExtractDirNameW(log_filename);
1067 fname = ExtractFileNameW(log_filename);
1068 }
1069 else {
1070 dir = _wcsdup(ts.LogDefaultPathW);
1071 fname = _wcsdup(log_filename);
1072 }
1073
1074 wchar_t *formated = FLogGetLogFilenameBase(fname);
1075 free(fname);
1076
1077 // �A������
1078 wchar_t *logfull = NULL;
1079 awcscats(&logfull, dir, L"\\", formated, NULL);
1080 free(formated);
1081 free(dir);
1082
1083 // ���K��
1084 wchar_t *normal;
1085 hGetFullPathNameW(logfull, &normal, NULL);
1086 free(logfull);
1087
1088 return normal;
1089 }
1090
1091 BOOL FLogIsPause()
1092 {
1093 if (LogVar == NULL) {
1094 return FALSE;
1095 }
1096 return LogVar->IsPause;
1097 }
1098
1099 void FLogWindow(int nCmdShow)
1100 {
1101 if (LogVar == NULL) {
1102 return;
1103 }
1104
1105 HWND HWndLog = LogVar->FLogDlg->m_hWnd;
1106 ShowWindow(HWndLog, nCmdShow);
1107 if (nCmdShow == SW_RESTORE) {
1108 // �g���X�^�C�� WS_EX_NOACTIVATE ��������������
1109 SetForegroundWindow(HWndLog);
1110 }
1111 }
1112
1113 void FLogShowDlg(void)
1114 {
1115 if (LogVar == NULL) {
1116 return;
1117 }
1118 HWND HWndLog = LogVar->FLogDlg->m_hWnd;
1119 ShowWindow(HWndLog, SW_SHOWNORMAL);
1120 SetForegroundWindow(HWndLog);
1121 }
1122
1123 /**
1124 * ���O��1byte��������
1125 * LogPut1() ������?
1126 */
1127 //void Log1Bin(PComVar cv, BYTE b)
1128 static void Log1Bin(BYTE b)
1129 {
1130 if (LogVar->IsPause || ProtoGetProtoFlag()) {
1131 return;
1132 }
1133 if (cv_BinSkip > 0) {
1134 cv_BinSkip--;
1135 return;
1136 }
1137 cv_BinBuf[cv_BinPtr] = b;
1138 cv_BinPtr++;
1139 if (cv_BinPtr>=InBuffSize) {
1140 cv_BinPtr = cv_BinPtr-InBuffSize;
1141 }
1142 if (cv_BCount>=InBuffSize) {
1143 cv_BCount = InBuffSize;
1144 cv_BStart = cv_BinPtr;
1145 }
1146 else {
1147 cv_BCount++;
1148 }
1149 }
1150
1151 static void LogBinSkip(int add)
1152 {
1153 if (cv_BinBuf != NULL) {
1154 cv_BinSkip += add;
1155 }
1156 }
1157
1158 /**
1159 * ���O�o�b�t�@���������������f�[�^���o�C�g��������
1160 */
1161 int FLogGetCount(void)
1162 {
1163 PFileVar fv = LogVar;
1164 if (fv == NULL) {
1165 return 0;
1166 }
1167 if (fv->FileLog) {
1168 return cv_LCount;
1169 }
1170 if (fv->BinLog) {
1171 return cv_BCount;
1172 }
1173 return 0;
1174 }
1175
1176 /**
1177 * ���O�o�b�t�@�������o�C�g��������
1178 */
1179 int FLogGetFreeCount(void)
1180 {
1181 PFileVar fv = LogVar;
1182 if (fv == NULL) {
1183 return 0;
1184 }
1185 if (fv->FileLog) {
1186 return InBuffSize - cv_LCount;
1187 }
1188 if (fv->BinLog) {
1189 return InBuffSize - cv_BCount;
1190 }
1191 return 0;
1192 }
1193
1194 /**
1195 * �o�b�t�@�������O���t�@�C������������
1196 */
1197 void FLogWriteFile(void)
1198 {
1199 PFileVar fv = LogVar;
1200 if (fv == NULL) {
1201 return;
1202 }
1203 if (cv_LogBuf!=NULL)
1204 {
1205 if (fv->FileLog) {
1206 LogToFile(fv);
1207 }
1208 }
1209
1210 if (cv_BinBuf!=NULL)
1211 {
1212 if (fv->BinLog) {
1213 LogToFile(fv);
1214 }
1215 }
1216 }
1217
1218 void FLogPutUTF32(unsigned int u32)
1219 {
1220 PFileVar fv = LogVar;
1221 BOOL log_available = (cv_LogBuf != 0);
1222
1223 if (!log_available) {
1224 // ���O�����o��������
1225 return;
1226 }
1227
1228 // �s����?(���s���o����������)
1229 if (ts.LogTimestamp && fv->eLineEnd) {
1230 // �^�C���X�^���v���o��
1231 fv->eLineEnd = Line_Other; /* clear endmark*/
1232 wchar_t* strtime = TimeStampStr(fv);
1233 FLogWriteStr(strtime);
1234 free(strtime);
1235 }
1236
1237 switch(fv->log_code) {
1238 case LOG_UTF8: {
1239 // UTF-8
1240 char u8_buf[4];
1241 size_t u8_len = UTF32ToUTF8(u32, u8_buf, _countof(u8_buf));
1242 for (size_t i = 0; i < u8_len; i++) {
1243 BYTE b = u8_buf[i];
1244 LogPut1(b);
1245 }
1246 break;
1247 }
1248 case LOG_UTF16LE:
1249 case LOG_UTF16BE: {
1250 // UTF-16
1251 wchar_t u16[2];
1252 size_t u16_len = UTF32ToUTF16(u32, u16, _countof(u16));
1253 for (size_t i = 0; i < u16_len; i++) {
1254 if (fv->log_code == LOG_UTF16LE) {
1255 // UTF-16LE
1256 LogPut1(u16[i] & 0xff);
1257 LogPut1((u16[i] >> 8) & 0xff);
1258 }
1259 else {
1260 // UTF-16BE
1261 LogPut1((u16[i] >> 8) & 0xff);
1262 LogPut1(u16[i] & 0xff);
1263 }
1264 }
1265 }
1266 }
1267
1268 if (u32 == 0x0a) {
1269 fv->eLineEnd = Line_LineHead; /* set endmark*/
1270 }
1271 }
1272
1273 static void FLogOutputBOM(PFileVar fv)
1274 {
1275 DWORD wrote;
1276
1277 switch(fv->log_code) {
1278 case 0: {
1279 // UTF-8
1280 const char *bom = "\xef\xbb\xbf";
1281 WriteFile(fv->FileHandle, bom, 3, &wrote, NULL);
1282 fv->ByteCount += 3;
1283 break;
1284 }
1285 case 1: {
1286 // UTF-16LE
1287 const char *bom = "\xff\xfe";
1288 WriteFile(fv->FileHandle, bom, 2, &wrote, NULL);
1289 fv->ByteCount += 2;
1290 break;
1291 }
1292 case 2: {
1293 // UTF-16BE
1294 const char *bom = "\xfe\xff";
1295 WriteFile(fv->FileHandle, bom, 2, &wrote, NULL);
1296 fv->ByteCount += 2;
1297 break;
1298 }
1299 default:
1300 break;
1301 }
1302 }
1303
1304 static void OutputStr(const wchar_t *str)
1305 {
1306 size_t len;
1307
1308 assert(str != NULL);
1309
1310 len = wcslen(str);
1311 while(*str != 0) {
1312 unsigned int u32;
1313 size_t u16_len = UTF16ToUTF32(str, len, &u32);
1314 switch (u16_len) {
1315 case 0:
1316 default:
1317 // ������������
1318 str++;
1319 len--;
1320 break;
1321 case 1:
1322 case 2: {
1323 FLogPutUTF32(u32);
1324 str += u16_len;
1325 len -= u16_len;
1326 break;
1327 }
1328 }
1329 }
1330 }

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