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 8900 - (show annotations) (download) (as text)
Tue Aug 18 15:29:32 2020 UTC (3 years, 7 months ago) by zmatsuo
File MIME type: text/x-c++src
File size: 40362 byte(s)
filesys_log.h を作成

- filesys.h から分離
- 使用していないので filesys_log から ttpfile.dll のロードを行わないようにした
- ログのポーズに cv.FilePause を使用しないようにした
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 "ttftypes.h"
44 #include "ftdlg.h"
45 #include "ttwinman.h"
46 #include "commlib.h"
47 #include "ttcommon.h"
48 #include "ttlib.h"
49 #include "dlglib.h"
50 #include "vtterm.h"
51 #include "ftlib.h"
52 #include "buffer.h"
53 #include "helpid.h"
54 #include "layer_for_unicode.h"
55 #include "layer_for_unicode_crt.h"
56 #include "codeconv.h"
57 #include "asprintf.h"
58
59 #include "filesys_log_res.h"
60 #include "filesys_log.h"
61
62 typedef struct {
63 wchar_t *FullName;
64 wchar_t *FileName;
65
66 BOOL FileOpen;
67 HANDLE FileHandle;
68 LONG FileSize, ByteCount;
69
70 DWORD StartTime;
71
72 // log rotate
73 int RotateMode; // enum rotate_mode RotateMode;
74 LONG RotateSize;
75 int RotateStep;
76
77 HANDLE LogThread;
78 DWORD LogThreadId;
79 HANDLE LogThreadEvent;
80
81 BOOL IsPause;
82 } TFileVar_;
83 typedef TFileVar_ *PFileVar_;
84
85 #define PFileVar PFileVar_
86 #define TFileVar TFileVar_
87
88 static PFileVar LogVar = NULL;
89
90 static BOOL FileLog = FALSE;
91 static BOOL BinLog = FALSE;
92
93 /*
94 Line Head flag for timestamping
95 2007.05.24 Gentaro
96 */
97 enum enumLineEnd {
98 Line_Other = 0,
99 Line_LineHead = 1,
100 Line_FileHead = 2,
101 };
102
103 static enum enumLineEnd eLineEnd = Line_LineHead;
104
105
106 // �x�����������p�X���b�h�����b�Z�[�W
107 #define WM_DPC_LOGTHREAD_SEND (WM_APP + 1)
108
109 static void FileTransEnd_(void);
110 static void Log1Bin(BYTE b);
111 static void LogBinSkip(int add);
112 static BOOL CreateLogBuf(void);
113 static BOOL CreateBinBuf(void);
114
115 static PFileTransDlg FLogDlg = NULL;
116
117 static BOOL OpenFTDlg_(PFileVar fv)
118 {
119 PFileTransDlg FTDlg = new CFileTransDlg();
120 if (FTDlg == NULL) {
121 return FALSE;
122 }
123
124 wchar_t *DlgCaption;
125 wchar_t uimsg[MAX_UIMSG];
126 #define TitLogW L"Log"
127 get_lang_msgW("FILEDLG_TRANS_TITLE_LOG", uimsg, _countof(uimsg), TitLogW, ts.UILanguageFile);
128 aswprintf(&DlgCaption, L"Tera Term: %s", uimsg);
129
130 CFileTransDlgInfo info;
131 info.UILanguageFile = ts.UILanguageFile;
132 info.OpId = OpLog;
133 info.DlgCaption = DlgCaption;
134 info.FileName = fv->FileName;
135 info.FullName = fv->FullName;
136 info.HideDialog = ts.LogHideDialog ? TRUE : FALSE;
137 info.HMainWin = HVTWin;
138 FTDlg->Create(hInst, &info);
139 FTDlg->RefreshNum(0, fv->FileSize, fv->ByteCount);
140
141 FLogDlg = FTDlg;
142
143 free(DlgCaption);
144 return TRUE;
145 }
146
147 /**
148 * �t�@�C�������������u������
149 * &h �z�X�g�����u�� (2007.5.14)
150 * &p TCP�|�[�g�������u�� (2009.6.12)
151 * &u ���O�I���������[�U��
152 */
153 static void ConvertLogname(char *c, int destlen)
154 {
155 char buf[MAXPATHLEN], buf2[MAXPATHLEN], *p = c;
156 char tmphost[1024];
157 char tmpuser[256+1];
158 DWORD len_user = sizeof(tmpuser);
159
160 memset(buf, 0, sizeof(buf));
161
162 while(*p != '\0') {
163 if (*p == '&' && *(p+1) != '\0') {
164 switch (*(p+1)) {
165 case 'h':
166 if (cv.Open) {
167 if (cv.PortType == IdTCPIP) {
168 // �z�X�g����IPv6�A�h���X�����A�t�@�C�������g�p�����������������������A
169 // �]�v�����������������B
170 // (2013.3.9 yutaka)
171 strncpy_s(tmphost, sizeof(tmphost), ts.HostName, _TRUNCATE);
172 //strncpy_s(tmphost, sizeof(tmphost), "2001:0db8:bd05:01d2:288a:1fc0:0001:10ee", _TRUNCATE);
173 replaceInvalidFileNameChar(tmphost, '_');
174 strncat_s(buf,sizeof(buf), tmphost, _TRUNCATE);
175 }
176 else if (cv.PortType == IdSerial) {
177 strncpy_s(buf2,sizeof(buf2),buf,_TRUNCATE);
178 _snprintf_s(buf, sizeof(buf), _TRUNCATE, "%sCOM%d", buf2, ts.ComPort);
179 }
180 }
181 break;
182 case 'p':
183 if (cv.Open) {
184 if (cv.PortType == IdTCPIP) {
185 char port[6];
186 _snprintf_s(port, sizeof(port), _TRUNCATE, "%d", ts.TCPPort);
187 strncat_s(buf,sizeof(buf),port,_TRUNCATE);
188 }
189 }
190 break;
191 case 'u':
192 if (GetUserName(tmpuser, &len_user) != 0) {
193 strncat_s(buf,sizeof(buf),tmpuser,_TRUNCATE);
194 }
195 break;
196 default:
197 strncpy_s(buf2,sizeof(buf2),p,2);
198 strncat_s(buf,sizeof(buf),buf2,_TRUNCATE);
199 }
200 p++;
201 }
202 else {
203 strncpy_s(buf2,sizeof(buf2),p,1);
204 strncat_s(buf,sizeof(buf),buf2,_TRUNCATE);
205 }
206 p++;
207 }
208 strncpy_s(c, destlen, buf, _TRUNCATE);
209 }
210
211 static void FixLogOption(void)
212 {
213 if (ts.LogBinary) {
214 ts.LogTypePlainText = false;
215 ts.LogTimestamp = false;
216 }
217 }
218
219
220 // �X���b�h���I�����t�@�C�����N���[�Y
221 static void CloseFileSync(PFileVar ptr)
222 {
223 BOOL ret;
224
225 if (!ptr->FileOpen)
226 return;
227
228 if (ptr->LogThread != INVALID_HANDLE_VALUE) {
229 // �X���b�h���I������
230 ret = PostThreadMessage(ptr->LogThreadId, WM_QUIT, 0, 0);
231 if (ret != 0) {
232 // �X���b�h�L���[���G���L���[���������������������������s���B
233 WaitForSingleObject(ptr->LogThread, INFINITE);
234 }
235 else {
236 //DWORD code = GetLastError();
237 }
238 CloseHandle(ptr->LogThread);
239 ptr->LogThread = INVALID_HANDLE_VALUE;
240 }
241 CloseHandle(ptr->FileHandle);
242 }
243
244 // �x�����������p�X���b�h
245 static unsigned _stdcall DeferredLogWriteThread(void *arg)
246 {
247 MSG msg;
248 PFileVar fv = (PFileVar)arg;
249 PCHAR buf;
250 DWORD buflen;
251 DWORD wrote;
252
253 PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
254
255 // �X���b�h�L���[���������I�������������X���b�h�����������m�����B
256 if (fv->LogThreadEvent != NULL) {
257 SetEvent(fv->LogThreadEvent);
258 }
259
260 while (GetMessage(&msg, NULL, 0, 0) > 0) {
261 switch (msg.message) {
262 case WM_DPC_LOGTHREAD_SEND:
263 buf = (PCHAR)msg.wParam;
264 buflen = (DWORD)msg.lParam;
265 WriteFile(LogVar->FileHandle, buf, buflen, &wrote, NULL);
266 free(buf); // ����������������
267 break;
268
269 case WM_QUIT:
270 goto end;
271 break;
272 }
273 }
274
275 end:
276 _endthreadex(0);
277 return (0);
278 }
279
280 /**
281 * �_�C�A���O�����e�� ts ����������
282 *
283 * TODO
284 * �_�C�A���O�����������l�������I��������
285 * ����������������������������������������������?
286 */
287 static void SetLogFlags(HWND Dialog)
288 {
289 WORD BinFlag, val;
290
291 GetRB(Dialog, &BinFlag, IDC_FOPTBIN, IDC_FOPTBIN);
292 ts.LogBinary = BinFlag;
293
294 GetRB(Dialog, &val, IDC_APPEND, IDC_APPEND);
295 ts.Append = val;
296
297 if (!BinFlag) {
298 GetRB(Dialog, &val, IDC_PLAINTEXT, IDC_PLAINTEXT);
299 ts.LogTypePlainText = val;
300
301 GetRB(Dialog, &val, IDC_TIMESTAMP, IDC_TIMESTAMP);
302 ts.LogTimestamp = val;
303 }
304
305 GetRB(Dialog, &val, IDC_HIDEDIALOG, IDC_HIDEDIALOG);
306 ts.LogHideDialog = val;
307
308 GetRB(Dialog, &val, IDC_ALLBUFF_INFIRST, IDC_ALLBUFF_INFIRST);
309 ts.LogAllBuffIncludedInFirst = val;
310
311 ts.LogTimestampType = (GetCurSel(Dialog, IDC_TIMESTAMPTYPE) - 1);
312 }
313
314 /**
315 * ���O�t�@�C���`�F�b�N
316 *
317 * @param[in] filename
318 * @param[out] exist TURE/FALSE
319 * @param[out] bom 0 no BOM (or file not exist)
320 * 1 UTF-8
321 * 2 UTF-16LE
322 * 3 UTF-16BE
323 */
324 static void CheckLogFile(const wchar_t *filename, BOOL *exist, int *bom)
325 {
326 *exist = FALSE;
327 *bom = 0;
328
329 // �t�@�C������������?
330 DWORD logdir = _GetFileAttributesW(filename);
331 if ((logdir != INVALID_FILE_ATTRIBUTES) && ((logdir & FILE_ATTRIBUTE_DIRECTORY) == 0)) {
332 // �t�@�C����������
333 *exist = TRUE;
334
335 // BOM�L��/�����`�F�b�N
336 FILE *fp = __wfopen(filename, L"rb");
337 if (fp != NULL) {
338 unsigned char tmp[4];
339 size_t l = fread(tmp, 1, sizeof(tmp), fp);
340 fclose(fp);
341 if (l < 2) {
342 *bom = 0;
343 } else if (l >= 2 && tmp[0] == 0xff && tmp[1] == 0xfe) {
344 // UTF-16LE
345 *bom = 2;
346 } else if (l >= 2 && tmp[0] == 0xfe && tmp[1] == 0xff) {
347 // UTF-16BE
348 *bom = 3;
349 } else if (l >= 3 && tmp[0] == 0xef && tmp[1] == 0xbb && tmp[2] == 0xbf) {
350 // UTF-8
351 *bom = 1;
352 } else {
353 *bom = 0;
354 }
355 }
356 }
357 }
358
359 typedef struct {
360 FLogDlgInfo_t *info;
361 // work
362 BOOL file_exist;
363 int current_bom;
364 TTTSet *pts;
365 } LogDlgWork_t;
366
367 static void ArrangeControls(HWND Dialog, LogDlgWork_t *work)
368 {
369 if (work->file_exist) {
370 EnableWindow(GetDlgItem(Dialog, IDC_APPEND), TRUE);
371 if (work->pts->Append > 0) {
372 CheckRadioButton(Dialog, IDC_NEW_OVERWRITE, IDC_APPEND, IDC_APPEND);
373 }
374 }
375 else {
376 // �t�@�C�������� -> �V�K
377 EnableWindow(GetDlgItem(Dialog, IDC_APPEND), FALSE);
378 CheckRadioButton(Dialog, IDC_NEW_OVERWRITE, IDC_APPEND, IDC_NEW_OVERWRITE);
379 }
380
381 if (work->file_exist && IsDlgButtonChecked(Dialog, IDC_APPEND) == BST_CHECKED) {
382 // �t�@�C������������ && append
383 int bom = work->current_bom;
384 if (bom != 0) {
385 // BOM�L��
386 CheckDlgButton(Dialog, IDC_BOM, BST_CHECKED);
387 int cur =
388 bom == 1 ? 0 :
389 bom == 2 ? 1 :
390 bom == 3 ? 2 : 0;
391 SendDlgItemMessage(Dialog, IDC_TEXTCODING_DROPDOWN, CB_SETCURSEL, cur, 0);
392 }
393 else {
394 // BOM����
395 CheckDlgButton(Dialog, IDC_BOM, BST_UNCHECKED);
396 SendDlgItemMessage(Dialog, IDC_TEXTCODING_DROPDOWN, CB_SETCURSEL, 0, 0);
397 }
398 if (IsDlgButtonChecked(Dialog, IDC_FOPTTEXT) == BST_CHECKED) {
399 EnableWindow(GetDlgItem(Dialog, IDC_BOM), FALSE);
400 if (bom != 0) {
401 // BOM�L��
402 EnableWindow(GetDlgItem(Dialog, IDC_TEXTCODING_DROPDOWN), FALSE);
403 }
404 else {
405 // BOM����
406 EnableWindow(GetDlgItem(Dialog, IDC_TEXTCODING_DROPDOWN), TRUE);
407 }
408 }
409 }
410 else {
411 // �t�@�C�������� ���� append��������(������)
412 CheckRadioButton(Dialog, IDC_NEW_OVERWRITE, IDC_APPEND, IDC_NEW_OVERWRITE);
413 CheckDlgButton(Dialog, IDC_BOM, BST_CHECKED);
414 SendDlgItemMessage(Dialog, IDC_TEXTCODING_DROPDOWN, CB_SETCURSEL, 0, 0);
415 if (IsDlgButtonChecked(Dialog, IDC_FOPTTEXT) == BST_CHECKED) {
416 EnableWindow(GetDlgItem(Dialog, IDC_BOM), TRUE);
417 }
418 }
419 }
420
421 static void CheckLogFile(HWND Dialog, const wchar_t *filename, LogDlgWork_t *work)
422 {
423 BOOL exist;
424 int bom;
425 CheckLogFile(filename, &exist, &bom);
426 work->file_exist = exist;
427 work->current_bom = bom;
428 ArrangeControls(Dialog, work);
429 }
430
431 static INT_PTR CALLBACK LogFnHook(HWND Dialog, UINT Message, WPARAM wParam, LPARAM lParam)
432 {
433 static const DlgTextInfo TextInfos[] = {
434 { 0, "DLG_TABSHEET_TITLE_LOG" },
435 { IDC_FOPTBIN, "DLG_FOPT_BINARY" },
436 { IDC_APPEND, "DLG_FOPT_APPEND" },
437 { IDC_PLAINTEXT, "DLG_FOPT_PLAIN" },
438 { IDC_HIDEDIALOG, "DLG_FOPT_HIDEDIALOG" },
439 { IDC_ALLBUFF_INFIRST, "DLG_FOPT_ALLBUFFINFIRST" },
440 { IDC_TIMESTAMP, "DLG_FOPT_TIMESTAMP" },
441 };
442 static const I18nTextInfo timestamp_list[] = {
443 { "DLG_FOPT_TIMESTAMP_LOCAL", L"Local Time" },
444 { "DLG_FOPT_TIMESTAMP_UTC", L"UTC" },
445 { "DLG_FOPT_TIMESTAMP_ELAPSED_LOGGING", L"Elapsed Time (Logging)" },
446 { "DLG_FOPT_TIMESTAMP_ELAPSED_CONNECTION", L"Elapsed Time (Connection)" },
447 };
448 LogDlgWork_t *work = (LogDlgWork_t *)GetWindowLongPtr(Dialog, DWLP_USER);
449
450 if (Message == RegisterWindowMessage(HELPMSGSTRING)) {
451 // �R�����_�C�A���O�������w���v���b�Z�[�W���t��������
452 Message = WM_COMMAND;
453 wParam = IDHELP;
454 }
455 switch (Message) {
456 case WM_INITDIALOG: {
457 work = (LogDlgWork_t *)lParam;
458 TTTSet *pts = work->pts;
459 const char *UILanguageFile = pts->UILanguageFile;
460 SetWindowLongPtr(Dialog, DWLP_USER, (LONG_PTR)work);
461 ::DragAcceptFiles(Dialog, TRUE);
462
463 SetDlgTexts(Dialog, TextInfos, _countof(TextInfos), UILanguageFile);
464 SetI18nList("Tera Term", Dialog, IDC_TIMESTAMPTYPE, timestamp_list, _countof(timestamp_list),
465 UILanguageFile, 0);
466
467 SendDlgItemMessage(Dialog, IDC_TEXTCODING_DROPDOWN, CB_ADDSTRING, 0, (LPARAM)"UTF-8");
468 SendDlgItemMessage(Dialog, IDC_TEXTCODING_DROPDOWN, CB_ADDSTRING, 0, (LPARAM)"UTF-16LE");
469 SendDlgItemMessage(Dialog, IDC_TEXTCODING_DROPDOWN, CB_ADDSTRING, 0, (LPARAM)"UTF-16BE");
470 SendDlgItemMessage(Dialog, IDC_TEXTCODING_DROPDOWN, CB_SETCURSEL, 0, 0);
471
472 _SetDlgItemTextW(Dialog, IDC_FOPT_FILENAME_EDIT, work->info->filename);
473 work->info->filename = NULL;
474
475 // Binary/Text �`�F�b�N�{�b�N�X
476 if (pts->LogBinary) {
477 CheckRadioButton(Dialog, IDC_FOPTBIN, IDC_FOPTTEXT, IDC_FOPTBIN);
478 }
479 else {
480 CheckRadioButton(Dialog, IDC_FOPTBIN, IDC_FOPTTEXT, IDC_FOPTTEXT);
481 }
482
483 // Plain Text �`�F�b�N�{�b�N�X
484 if (pts->LogBinary) {
485 // Binary�t���O���L�����������`�F�b�N��������
486 DisableDlgItem(Dialog, IDC_PLAINTEXT, IDC_PLAINTEXT);
487 }
488 else if (pts->LogTypePlainText) {
489 SetRB(Dialog, 1, IDC_PLAINTEXT, IDC_PLAINTEXT);
490 }
491
492 // Hide dialog�`�F�b�N�{�b�N�X (2008.1.30 maya)
493 if (pts->LogHideDialog) {
494 SetRB(Dialog, 1, IDC_HIDEDIALOG, IDC_HIDEDIALOG);
495 }
496
497 // Include screen buffer�`�F�b�N�{�b�N�X (2013.9.29 yutaka)
498 if (pts->LogAllBuffIncludedInFirst) {
499 SetRB(Dialog, 1, IDC_ALLBUFF_INFIRST, IDC_ALLBUFF_INFIRST);
500 }
501
502 // timestamp�`�F�b�N�{�b�N�X (2006.7.23 maya)
503 if (pts->LogBinary) {
504 // Binary�t���O���L�����������`�F�b�N��������
505 DisableDlgItem(Dialog, IDC_TIMESTAMP, IDC_TIMESTAMP);
506 }
507 else if (pts->LogTimestamp) {
508 SetRB(Dialog, 1, IDC_TIMESTAMP, IDC_TIMESTAMP);
509 }
510
511 // timestamp ����
512 int tstype = pts->LogTimestampType == TIMESTAMP_LOCAL ? 0 :
513 pts->LogTimestampType == TIMESTAMP_UTC ? 1 :
514 pts->LogTimestampType == TIMESTAMP_ELAPSED_LOGSTART ? 2 :
515 pts->LogTimestampType == TIMESTAMP_ELAPSED_CONNECTED ? 3 : 0;
516 SendDlgItemMessage(Dialog, IDC_TIMESTAMPTYPE, CB_SETCURSEL, tstype, 0);
517 if (pts->LogBinary || !pts->LogTimestamp) {
518 DisableDlgItem(Dialog, IDC_TIMESTAMPTYPE, IDC_TIMESTAMPTYPE);
519 }
520
521 CenterWindow(Dialog, GetParent(Dialog));
522
523 return TRUE;
524 }
525
526 case WM_COMMAND:
527 switch (LOWORD(wParam)) {
528 case IDOK: {
529 wchar_t filename[MAX_PATH];
530 _GetDlgItemTextW(Dialog, IDC_FOPT_FILENAME_EDIT, filename, _countof(filename));
531 work->info->filename = _wcsdup(filename);
532 work->info->append = IsDlgButtonChecked(Dialog, IDC_APPEND) == BST_CHECKED;
533 work->info->bom = IsDlgButtonChecked(Dialog, IDC_BOM) == BST_CHECKED;
534 work->info->code = (int)SendDlgItemMessageA(Dialog, IDC_TEXTCODING_DROPDOWN, CB_GETCURSEL, 0, 0);
535 SetLogFlags(Dialog);
536 EndDialog(Dialog, IDOK);
537 break;
538 }
539 case IDCANCEL:
540 EndDialog(Dialog, IDCANCEL);
541 break;
542 case IDHELP:
543 OpenHelp(HH_HELP_CONTEXT, HlpFileLog, work->pts->UILanguageFile);
544 break;
545 case IDC_FOPT_FILENAME_BUTTON: {
546 /* save current dir */
547 const char *UILanguageFile = work->pts->UILanguageFile;
548 wchar_t curdir[MAXPATHLEN];
549 _GetCurrentDirectoryW(_countof(curdir), curdir);
550
551 wchar_t fname[MAX_PATH];
552 GetDlgItemTextW(Dialog, IDC_FOPT_FILENAME_EDIT, fname, _countof(fname));
553
554 wchar_t FNFilter[128*3];
555 get_lang_msgW("FILEDLG_ALL_FILTER", FNFilter, sizeof(FNFilter), L"All(*.*)\\0*.*\\0\\0", UILanguageFile);
556
557 wchar_t caption[MAX_PATH];
558 wchar_t uimsg[MAX_UIMSG];
559 #define TitLogW L"Log"
560 get_lang_msgW("FILEDLG_TRANS_TITLE_LOG", uimsg, _countof(uimsg), TitLogW, UILanguageFile);
561 wcsncpy_s(caption, _countof(caption), L"Tera Term: ", _TRUNCATE);
562 wcsncat_s(caption, _countof(caption), uimsg, _TRUNCATE);
563
564 OPENFILENAMEW ofn = {};
565 ofn.lStructSize = get_OPENFILENAME_SIZEW();
566 //ofn.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT;
567 ofn.Flags |= OFN_EXPLORER | OFN_ENABLESIZING;
568 ofn.Flags |= OFN_SHOWHELP;
569 ofn.Flags |= OFN_NOCHANGEDIR; // ��������������������������������
570 ofn.hwndOwner = Dialog;
571 ofn.lpstrFilter = FNFilter;
572 ofn.nFilterIndex = 1;
573 ofn.lpstrFile = fname;
574 ofn.nMaxFile = _countof(fname);
575 ofn.lpstrTitle = caption;
576 BOOL Ok = GetSaveFileNameW(&ofn);
577 if (Ok) {
578 SetDlgItemTextW(Dialog, IDC_FOPT_FILENAME_EDIT, fname);
579 }
580
581 /* restore dir */
582 _SetCurrentDirectoryW(curdir);
583
584 break;
585 }
586 case IDC_FOPTBIN:
587 EnableWindow(GetDlgItem(Dialog, IDC_TEXTCODING_DROPDOWN), FALSE);
588 EnableWindow(GetDlgItem(Dialog, IDC_BOM), FALSE);
589 DisableDlgItem(Dialog, IDC_PLAINTEXT, IDC_TIMESTAMP);
590 DisableDlgItem(Dialog, IDC_TIMESTAMPTYPE, IDC_TIMESTAMPTYPE);
591 break;
592 case IDC_FOPTTEXT:
593 ArrangeControls(Dialog, work);
594 EnableDlgItem(Dialog, IDC_PLAINTEXT, IDC_TIMESTAMP);
595 // FALLTHROUGH -- BinFlag �� off ������ Timestamp �������L��/��������������
596 case IDC_TIMESTAMP:
597 if (IsDlgButtonChecked(Dialog, IDC_TIMESTAMP) == BST_CHECKED) {
598 EnableDlgItem(Dialog, IDC_TIMESTAMPTYPE, IDC_TIMESTAMPTYPE);
599 }
600 else {
601 DisableDlgItem(Dialog, IDC_TIMESTAMPTYPE, IDC_TIMESTAMPTYPE);
602 }
603 break;
604 case IDC_FOPT_FILENAME_EDIT:
605 if (HIWORD(wParam) == EN_CHANGE){
606 wchar_t filename[MAX_PATH];
607 GetDlgItemTextW(Dialog, IDC_FOPT_FILENAME_EDIT, filename, _countof(filename));
608 CheckLogFile(Dialog, filename, work);
609 }
610 break;
611 case IDC_NEW_OVERWRITE:
612 if (IsDlgButtonChecked(Dialog, IDC_FOPTTEXT) == BST_CHECKED) {
613 EnableWindow(GetDlgItem(Dialog, IDC_BOM), TRUE);
614 EnableWindow(GetDlgItem(Dialog, IDC_TEXTCODING_DROPDOWN), TRUE);
615 CheckDlgButton(Dialog, IDC_BOM, BST_CHECKED);
616 SendDlgItemMessage(Dialog, IDC_TEXTCODING_DROPDOWN, CB_SETCURSEL, 0, 0);
617 }
618 break;
619 case IDC_APPEND:
620 ArrangeControls(Dialog, work);
621 break;
622 }
623 break;
624 case WM_DROPFILES: {
625 // �����h���b�v��������������1������������
626 HDROP hDrop = (HDROP)wParam;
627 const UINT len = _DragQueryFileW(hDrop, 0, NULL, 0);
628 if (len == 0) {
629 DragFinish(hDrop);
630 return TRUE;
631 }
632 wchar_t *filename = (wchar_t *)malloc(sizeof(wchar_t) * (len + 1));
633 _DragQueryFileW(hDrop, 0, filename, len + 1);
634 filename[len] = '\0';
635 CheckRadioButton(Dialog, IDC_NEW_OVERWRITE, IDC_APPEND, IDC_APPEND);
636 _SetDlgItemTextW(Dialog, IDC_FOPT_FILENAME_EDIT, filename);
637 SendDlgItemMessage(Dialog, IDC_FOPT_FILENAME_EDIT, EM_SETSEL, len, len);
638 free(filename);
639 DragFinish(hDrop);
640 return TRUE;
641 }
642 }
643 return FALSE;
644 }
645
646 static BOOL LogStart(const wchar_t *fname)
647 {
648 unsigned tid;
649
650 LogVar->FullName = _wcsdup(fname);
651
652 PFileVar fv = LogVar;
653 wchar_t *p = wcsrchr(fv->FullName, L'\\');
654 if (p == NULL) {
655 p = wcsrchr(fv->FullName, L'/');
656 }
657 if (p == NULL) {
658 fv->FileName = _wcsdup(fv->FullName);
659 }
660 else {
661 fv->FileName = _wcsdup(p++);
662 }
663 FixLogOption();
664
665 if (ts.LogBinary > 0)
666 {
667 BinLog = TRUE;
668 FileLog = FALSE;
669 if (! CreateBinBuf())
670 {
671 FileTransEnd_();
672 return FALSE;
673 }
674 }
675 else {
676 BinLog = FALSE;
677 FileLog = TRUE;
678 if (! CreateLogBuf())
679 {
680 FileTransEnd_();
681 return FALSE;
682 }
683 }
684 cv.LStart = cv.LogPtr;
685 cv.LCount = 0;
686
687 /* 2007.05.24 Gentaro */
688 eLineEnd = Line_LineHead;
689
690 if (ts.Append > 0)
691 {
692 int dwShareMode = FILE_SHARE_READ;
693 if (!ts.LogLockExclusive) {
694 dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
695 }
696 LogVar->FileHandle = _CreateFileW(LogVar->FullName, GENERIC_WRITE, dwShareMode, NULL,
697 OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
698 if (LogVar->FileHandle != INVALID_HANDLE_VALUE){
699 SetFilePointer(LogVar->FileHandle, 0, NULL, FILE_END);
700 /* 2007.05.24 Gentaro
701 If log file already exists,
702 a newline is inserted before the first timestamp.
703 */
704 eLineEnd = Line_FileHead;
705 }
706 }
707 else {
708 int dwShareMode = FILE_SHARE_READ;
709 if (!ts.LogLockExclusive) {
710 dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
711 }
712 LogVar->FileHandle = _CreateFileW(LogVar->FullName, GENERIC_WRITE, dwShareMode, NULL,
713 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
714 }
715 LogVar->FileOpen = (LogVar->FileHandle != INVALID_HANDLE_VALUE);
716 if (! LogVar->FileOpen)
717 {
718 FileTransEnd_();
719 return FALSE;
720 }
721 LogVar->ByteCount = 0;
722
723 // Log rotate configuration
724 LogVar->RotateMode = ts.LogRotate;
725 LogVar->RotateSize = ts.LogRotateSize;
726 LogVar->RotateStep = ts.LogRotateStep;
727
728 // Log rotate���L���������A�����t�@�C���T�C�Y�����������B
729 // �������t�@�C�������������T�C�Y�����[�e�[�g�������������C���B
730 // (2016.4.9 yutaka)
731 if (LogVar->RotateMode != ROTATE_NONE) {
732 DWORD size = GetFileSize(LogVar->FileHandle, NULL);
733 if (size != -1)
734 LogVar->ByteCount = size;
735 }
736
737 if (! OpenFTDlg_(LogVar)) {
738 FileTransEnd_();
739 return FALSE;
740 }
741
742 LogVar->IsPause = FALSE;
743 LogVar->StartTime = GetTickCount();
744
745 // �x�����������p�X���b�h���N�����B
746 // (2013.4.19 yutaka)
747 // DeferredLogWriteThread �X���b�h���N�������A�X���b�h�L���[�����������������O���A
748 // ���O�t�@�C�����N���[�Y(CloseFileSync)���s���������A�G���L���[�����s���A�f�b�h���b�N
749 // �����������������C�������B
750 // �X���b�h�����������s�������A���O�����C�x���g�I�u�W�F�N�g���g�����A�X���b�h�L���[��
751 // ���������������������������������B���O�t���C�x���g�I�u�W�F�N�g���g���������A
752 // �V�X�e��(Windows OS)�������j�[�N�����O�������K�v�������B
753 // (2016.9.23 yutaka)
754 LogVar->LogThreadEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
755 LogVar->LogThread = (HANDLE)_beginthreadex(NULL, 0, DeferredLogWriteThread, LogVar, 0, &tid);
756 LogVar->LogThreadId = tid;
757 if (LogVar->LogThreadEvent != NULL) {
758 WaitForSingleObject(LogVar->LogThreadEvent, INFINITE);
759 CloseHandle(LogVar->LogThreadEvent);
760 }
761
762 // �����o�b�t�@�������f�[�^�������������o���������A
763 // ���O�������J�n�����B
764 // (2013.9.29 yutaka)
765 if (ts.LogAllBuffIncludedInFirst) {
766 DWORD ofs, size, written_size;
767 char buf[512];
768 const char *crlf = "\r\n";
769 DWORD crlf_len = 2;
770 for (ofs = 0 ; ; ofs++ ) {
771 // 1�����s�����������B���������������A�G�X�P�[�v�V�[�P���X�������������B
772 size = BuffGetAnyLineData(ofs, buf, sizeof(buf));
773 if (size == -1)
774 break;
775
776 #if 0
777 if (ts.DeferredLogWriteMode) { // �x����������
778 char *pbuf = (char *)malloc(size + 2);
779 memcpy(pbuf, buf, size);
780 pbuf[size] = '\r';
781 pbuf[size+1] = '\n';
782 Sleep(1); // �X���b�h�L���[�����������������A�R���e�L�X�g�X�C�b�`�������B
783 PostThreadMessage(LogVar->LogThreadId, WM_DPC_LOGTHREAD_SEND, (WPARAM)pbuf, size + 2);
784 } else { // �������B�l�b�g���[�N�o�R�����x���B
785 #endif
786 WriteFile(LogVar->FileHandle, buf, size, &written_size, NULL);
787 WriteFile(LogVar->FileHandle, crlf, crlf_len, &written_size, NULL);
788 #if 0
789 }
790 #endif
791 }
792 }
793
794 if (FileLog) {
795 cv.Log1Byte = LogPut1;
796 }
797 if (BinLog) {
798 cv.Log1Bin = Log1Bin;
799 cv.LogBinSkip = LogBinSkip;
800 }
801
802 return TRUE;
803 }
804
805 /**
806 * ���O��1byte��������
807 * �o�b�t�@��������������
808 * ���������������� LogToFile() ���s������
809 */
810 void LogPut1(BYTE b)
811 {
812 cv.LogBuf[cv.LogPtr] = b;
813 cv.LogPtr++;
814 if (cv.LogPtr>=InBuffSize)
815 cv.LogPtr = cv.LogPtr-InBuffSize;
816
817 if (FileLog)
818 {
819 if (cv.LCount>=InBuffSize)
820 {
821 cv.LCount = InBuffSize;
822 cv.LStart = cv.LogPtr;
823 }
824 else
825 cv.LCount++;
826 }
827 else
828 cv.LCount = 0;
829 }
830
831 static BOOL Get1(PCHAR Buf, int *Start, int *Count, PBYTE b)
832 {
833 if (*Count<=0) return FALSE;
834 *b = Buf[*Start];
835 (*Start)++;
836 if (*Start>=InBuffSize)
837 *Start = *Start-InBuffSize;
838 (*Count)--;
839 return TRUE;
840 }
841
842
843
844 static CRITICAL_SECTION g_filelog_lock; /* ���b�N�p���� */
845
846 void logfile_lock_initialize(void)
847 {
848 InitializeCriticalSection(&g_filelog_lock);
849 }
850
851 static inline void logfile_lock(void)
852 {
853 EnterCriticalSection(&g_filelog_lock);
854 }
855
856 static inline void logfile_unlock(void)
857 {
858 LeaveCriticalSection(&g_filelog_lock);
859 }
860
861 // �R�����g�����O����������
862 static void CommentLogToFile(char *buf, int size)
863 {
864 DWORD wrote;
865
866 if (LogVar == NULL || !LogVar->FileOpen) {
867 char uimsg[MAX_UIMSG];
868 get_lang_msg("MSG_ERROR", uimsg, sizeof(uimsg), "ERROR", ts.UILanguageFile);
869 get_lang_msg("MSG_COMMENT_LOG_OPEN_ERROR", ts.UIMsg, sizeof(ts.UIMsg),
870 "It is not opened by the log file yet.", ts.UILanguageFile);
871 ::MessageBox(NULL, ts.UIMsg, uimsg, MB_OK|MB_ICONEXCLAMATION);
872 return;
873 }
874
875 logfile_lock();
876 WriteFile(LogVar->FileHandle, buf, size, &wrote, NULL);
877 WriteFile(LogVar->FileHandle, "\r\n", 2, &wrote, NULL); // ���s
878 /* Set Line End Flag
879 2007.05.24 Gentaro
880 */
881 eLineEnd = Line_LineHead;
882 logfile_unlock();
883 }
884
885 // ���O�����[�e�[�g�����B
886 // (2013.3.21 yutaka)
887 static void LogRotate(void)
888 {
889 int loopmax = 10000; // XXX
890 int i, k;
891 int dwShareMode = FILE_SHARE_READ;
892 unsigned tid;
893
894 if (! LogVar->FileOpen) return;
895
896 if (LogVar->RotateMode == ROTATE_NONE)
897 return;
898
899 if (LogVar->RotateMode == ROTATE_SIZE) {
900 if (LogVar->ByteCount <= LogVar->RotateSize)
901 return;
902 //OutputDebugPrintf("%s: mode %d size %ld\n", __FUNCTION__, LogVar->RotateMode, LogVar->ByteCount);
903 } else {
904 return;
905 }
906
907 logfile_lock();
908 // ���O�T�C�Y���������������B
909 LogVar->ByteCount = 0;
910
911 // �������������t�@�C�����N���[�Y�����A�������t�@�C�����I�[�v�������B
912 CloseFileSync(LogVar);
913 //_lclose(LogVar->FileHandle);
914
915 // �������[�e�[�V�������X�e�b�v�����w����������
916 if (LogVar->RotateStep > 0)
917 loopmax = LogVar->RotateStep;
918
919 for (i = 1 ; i <= loopmax ; i++) {
920 wchar_t *filename;
921 aswprintf(&filename, L"%s.%d", LogVar->FullName, i);
922 DWORD attr = _GetFileAttributesW(filename);
923 free(filename);
924 if ((attr != INVALID_FILE_ATTRIBUTES) && ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0))
925 break;
926 }
927 if (i > loopmax) {
928 // �������������������������A�������t�@�C�������p�������B
929 i = loopmax;
930 }
931
932 // ���t�@�C�������l�[���B
933 for (k = i-1 ; k >= 0 ; k--) {
934 wchar_t *oldfile;
935 if (k == 0)
936 oldfile = _wcsdup(LogVar->FullName);
937 else
938 aswprintf(&oldfile, L"%s.%d", LogVar->FullName, k);
939 wchar_t *newfile;
940 aswprintf(&newfile, L"%s.%d", LogVar->FullName, k+1);
941 _DeleteFileW(newfile);
942 if (_MoveFileW(oldfile, newfile) == 0) {
943 OutputDebugPrintf("%s: rename %d\n", __FUNCTION__, errno);
944 }
945 free(oldfile);
946 free(newfile);
947 }
948
949 // ���I�[�v��
950 if (!ts.LogLockExclusive) {
951 dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
952 }
953 LogVar->FileHandle = _CreateFileW(LogVar->FullName, GENERIC_WRITE, dwShareMode, NULL,
954 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
955
956 // �x�����������p�X���b�h���N�����B
957 // (2013.4.19 yutaka)
958 // DeferredLogWriteThread �X���b�h���N�������A�X���b�h�L���[�����������������O���A
959 // ���O�t�@�C�����N���[�Y(CloseFileSync)���s���������A�G���L���[�����s���A�f�b�h���b�N
960 // �����������������C�������B
961 // �X���b�h�����������s�������A���O�����C�x���g�I�u�W�F�N�g���g�����A�X���b�h�L���[��
962 // ���������������������������������B���O�t���C�x���g�I�u�W�F�N�g���g���������A
963 // �V�X�e��(Windows OS)�������j�[�N�����O�������K�v�������B
964 // (2016.9.26 yutaka)
965 LogVar->LogThreadEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
966 LogVar->LogThread = (HANDLE)_beginthreadex(NULL, 0, DeferredLogWriteThread, LogVar, 0, &tid);
967 LogVar->LogThreadId = tid;
968 if (LogVar->LogThreadEvent != NULL) {
969 WaitForSingleObject(LogVar->LogThreadEvent, INFINITE);
970 CloseHandle(LogVar->LogThreadEvent);
971 }
972
973 logfile_unlock();
974
975 }
976
977 /**
978 * �o�b�t�@�������O���t�@�C������������
979 */
980 static void LogToFile(void)
981 {
982 PCHAR Buf;
983 int Start, Count;
984 BYTE b;
985 PCHAR WriteBuf;
986 DWORD WriteBufMax, WriteBufLen;
987 CHAR tmp[128];
988 DWORD wrote;
989
990 if (! LogVar->FileOpen) return;
991 if (FileLog)
992 {
993 Buf = cv.LogBuf;
994 Start = cv.LStart;
995 Count = cv.LCount;
996 }
997 else if (BinLog)
998 {
999 Buf = cv.BinBuf;
1000 Start = cv.BStart;
1001 Count = cv.BCount;
1002 }
1003 else
1004 return;
1005
1006 if (Buf==NULL) return;
1007 if (Count==0) return;
1008
1009 // ���b�N������(2004.8.6 yutaka)
1010 logfile_lock();
1011
1012 if (ts.DeferredLogWriteMode) {
1013 WriteBufMax = 8192;
1014 WriteBufLen = 0;
1015 WriteBuf = (PCHAR)malloc(WriteBufMax);
1016 while (Get1(Buf,&Start,&Count,&b)) {
1017 if (!FLogIsPause() && (! cv.ProtoFlag))
1018 {
1019 tmp[0] = 0;
1020 if ( ts.LogTimestamp && eLineEnd ) {
1021 char *strtime = NULL;
1022
1023 switch (ts.LogTimestampType) {
1024 case TIMESTAMP_LOCAL:
1025 strtime = mctimelocal(ts.LogTimestampFormat, FALSE);
1026 break;
1027 case TIMESTAMP_UTC:
1028 strtime = mctimelocal(ts.LogTimestampFormat, TRUE);
1029 break;
1030 case TIMESTAMP_ELAPSED_LOGSTART:
1031 strtime = strelapsed(LogVar->StartTime);
1032 break;
1033 case TIMESTAMP_ELAPSED_CONNECTED:
1034 strtime = strelapsed(cv.ConnectedTime);
1035 break;
1036 }
1037
1038 /* 2007.05.24 Gentaro */
1039 if( eLineEnd == Line_FileHead ){
1040 strncat_s(tmp, sizeof(tmp), "\r\n", _TRUNCATE);
1041 }
1042 strncat_s(tmp, sizeof(tmp), "[", _TRUNCATE);
1043 strncat_s(tmp, sizeof(tmp), strtime, _TRUNCATE);
1044 strncat_s(tmp, sizeof(tmp), "] ", _TRUNCATE);
1045 }
1046
1047 /* 2007.05.24 Gentaro */
1048 if( b == 0x0a ){
1049 eLineEnd = Line_LineHead; /* set endmark*/
1050 }
1051 else {
1052 eLineEnd = Line_Other; /* clear endmark*/
1053 }
1054
1055 if (WriteBufLen >= (WriteBufMax*4/5)) {
1056 WriteBufMax *= 2;
1057 WriteBuf = (PCHAR)realloc(WriteBuf, WriteBufMax);
1058 }
1059 memcpy(&WriteBuf[WriteBufLen], tmp, strlen(tmp));
1060 WriteBufLen += strlen(tmp);
1061 WriteBuf[WriteBufLen++] = b;
1062
1063 (LogVar->ByteCount)++;
1064 }
1065 }
1066
1067 PostThreadMessage(LogVar->LogThreadId, WM_DPC_LOGTHREAD_SEND, (WPARAM)WriteBuf, WriteBufLen);
1068
1069 } else {
1070
1071 while (Get1(Buf,&Start,&Count,&b))
1072 {
1073 if (!FLogIsPause() && (! cv.ProtoFlag))
1074 {
1075 if ( ts.LogTimestamp && eLineEnd ) {
1076 char *strtime = NULL;
1077
1078 switch (ts.LogTimestampType) {
1079 case TIMESTAMP_LOCAL:
1080 strtime = mctimelocal(ts.LogTimestampFormat, FALSE);
1081 break;
1082 case TIMESTAMP_UTC:
1083 strtime = mctimelocal(ts.LogTimestampFormat, TRUE);
1084 break;
1085 case TIMESTAMP_ELAPSED_LOGSTART:
1086 strtime = strelapsed(LogVar->StartTime);
1087 break;
1088 case TIMESTAMP_ELAPSED_CONNECTED:
1089 strtime = strelapsed(cv.ConnectedTime);
1090 break;
1091 }
1092 WriteFile(LogVar->FileHandle, "[", 1, &wrote, NULL);
1093 WriteFile(LogVar->FileHandle, strtime, strlen(strtime), &wrote, NULL);
1094 WriteFile(LogVar->FileHandle, "] ", 2, &wrote, NULL);
1095 }
1096
1097 /* 2007.05.24 Gentaro */
1098 if( b == 0x0a ){
1099 eLineEnd = Line_LineHead; /* set endmark*/
1100 }
1101 else {
1102 eLineEnd = Line_Other; /* clear endmark*/
1103 }
1104
1105 WriteFile(LogVar->FileHandle, (PCHAR)&b, 1, &wrote, NULL);
1106 (LogVar->ByteCount)++;
1107 }
1108 }
1109
1110 }
1111
1112 logfile_unlock();
1113
1114 if (FileLog)
1115 {
1116 cv.LStart = Start;
1117 cv.LCount = Count;
1118 }
1119 else {
1120 cv.BStart = Start;
1121 cv.BCount = Count;
1122 }
1123 if (FLogIsPause() || cv.ProtoFlag) return;
1124 if (FLogDlg!=NULL)
1125 FLogDlg->RefreshNum(LogVar->StartTime, LogVar->FileSize, LogVar->ByteCount);
1126
1127
1128 // ���O�E���[�e�[�g
1129 LogRotate();
1130
1131 }
1132
1133 static BOOL CreateLogBuf(void)
1134 {
1135 if (cv.HLogBuf==NULL)
1136 {
1137 cv.HLogBuf = GlobalAlloc(GMEM_MOVEABLE,InBuffSize);
1138 cv.LogBuf = NULL;
1139 cv.LogPtr = 0;
1140 cv.LStart = 0;
1141 cv.LCount = 0;
1142 }
1143 return (cv.HLogBuf!=NULL);
1144 }
1145
1146 static void FreeLogBuf(void)
1147 {
1148 if ((cv.HLogBuf==NULL) || FileLog)
1149 return;
1150 if (cv.LogBuf!=NULL)
1151 GlobalUnlock(cv.HLogBuf);
1152 GlobalFree(cv.HLogBuf);
1153 cv.HLogBuf = NULL;
1154 cv.LogBuf = NULL;
1155 cv.LogPtr = 0;
1156 cv.LStart = 0;
1157 cv.LCount = 0;
1158 }
1159
1160 static BOOL CreateBinBuf(void)
1161 {
1162 if (cv.HBinBuf==NULL)
1163 {
1164 cv.HBinBuf = GlobalAlloc(GMEM_MOVEABLE,InBuffSize);
1165 cv.BinBuf = NULL;
1166 cv.BinPtr = 0;
1167 cv.BStart = 0;
1168 cv.BCount = 0;
1169 }
1170 return (cv.HBinBuf!=NULL);
1171 }
1172
1173 static void FreeBinBuf(void)
1174 {
1175 if ((cv.HBinBuf==NULL) || BinLog)
1176 return;
1177 if (cv.BinBuf!=NULL)
1178 GlobalUnlock(cv.HBinBuf);
1179 GlobalFree(cv.HBinBuf);
1180 cv.HBinBuf = NULL;
1181 cv.BinBuf = NULL;
1182 cv.BinPtr = 0;
1183 cv.BStart = 0;
1184 cv.BCount = 0;
1185 }
1186
1187 static void FileTransEnd_(void)
1188 {
1189 if (LogVar == NULL) {
1190 return;
1191 }
1192 FileLog = FALSE;
1193 BinLog = FALSE;
1194 cv.Log1Byte = NULL;
1195 cv.Log1Bin = NULL;
1196 cv.LogBinSkip = NULL;
1197 if (FLogDlg!=NULL)
1198 {
1199 FLogDlg->DestroyWindow();
1200 FLogDlg = NULL;
1201 }
1202 CloseFileSync(LogVar);
1203 FreeLogBuf();
1204 FreeBinBuf();
1205 free(LogVar);
1206 LogVar = NULL;
1207 }
1208
1209 /**
1210 * ���O���|�[�Y����
1211 */
1212 void FLogPause(BOOL Pause)
1213 {
1214 if (LogVar == NULL) {
1215 return;
1216 }
1217 LogVar->IsPause = Pause;
1218 FLogDlg->ChangeButton(Pause);
1219 }
1220
1221 /**
1222 * ���O���[�e�[�g������
1223 * ���O���T�C�Y��<size>�o�C�g���������������A���[�e�[�V��������������������
1224 */
1225 void FLogRotateSize(size_t size)
1226 {
1227 if (LogVar == NULL) {
1228 return;
1229 }
1230 LogVar->RotateMode = ROTATE_SIZE;
1231 LogVar->RotateSize = size;
1232 }
1233
1234 /**
1235 * ���O���[�e�[�g������
1236 * ���O�t�@�C������������������
1237 */
1238 void FLogRotateRotate(int step)
1239 {
1240 if (LogVar == NULL) {
1241 return;
1242 }
1243 LogVar->RotateStep = step;
1244 }
1245
1246 /**
1247 * ���O���[�e�[�g������
1248 * ���[�e�[�V���������~
1249 */
1250 void FLogRotateHalt(void)
1251 {
1252 if (LogVar == NULL) {
1253 return;
1254 }
1255 LogVar->RotateMode = ROTATE_NONE;
1256 LogVar->RotateSize = 0;
1257 LogVar->RotateStep = 0;
1258 }
1259
1260 static INT_PTR CALLBACK OnCommentDlgProc(HWND hDlgWnd, UINT msg, WPARAM wp, LPARAM lp)
1261 {
1262 static const DlgTextInfo TextInfos[] = {
1263 { 0, "DLG_COMMENT_TITLE" },
1264 { IDOK, "BTN_OK" }
1265 };
1266 char buf[256];
1267 UINT ret;
1268
1269 switch (msg) {
1270 case WM_INITDIALOG:
1271 //SetDlgItemText(hDlgWnd, IDC_EDIT_COMMENT, "�T���v��");
1272 // �G�f�B�b�g�R���g���[�����t�H�[�J�X��������
1273 SetFocus(GetDlgItem(hDlgWnd, IDC_EDIT_COMMENT));
1274 SetDlgTexts(hDlgWnd, TextInfos, _countof(TextInfos), ts.UILanguageFile);
1275 return FALSE;
1276
1277 case WM_COMMAND:
1278 switch (LOWORD(wp)) {
1279 case IDOK:
1280 memset(buf, 0, sizeof(buf));
1281 ret = GetDlgItemTextA(hDlgWnd, IDC_EDIT_COMMENT, buf, sizeof(buf) - 1);
1282 if (ret > 0) { // �e�L�X�g��������
1283 //buf[sizeof(buf) - 1] = '\0'; // null-terminate
1284 CommentLogToFile(buf, ret);
1285 }
1286 TTEndDialog(hDlgWnd, IDOK);
1287 break;
1288 default:
1289 return FALSE;
1290 }
1291 break;
1292 case WM_CLOSE:
1293 TTEndDialog(hDlgWnd, 0);
1294 return TRUE;
1295
1296 default:
1297 return FALSE;
1298 }
1299 return TRUE;
1300 }
1301
1302 void FLogAddCommentDlg(HINSTANCE hInst, HWND hWnd)
1303 {
1304 // ���O�t�@�C�����R�����g���������� (2004.8.6 yutaka)
1305 TTDialogBox(hInst, MAKEINTRESOURCE(IDD_COMMENT_DIALOG),
1306 HVTWin, OnCommentDlgProc);
1307 }
1308
1309 void FLogClose(void)
1310 {
1311 if (LogVar == NULL) {
1312 return;
1313 }
1314
1315 FileTransEnd_();
1316 }
1317
1318 /**
1319 * ���O���I�[�v������
1320 * @param[in] fname ���O�t�@�C����, CreateFile()���n������
1321 *
1322 * ���O�t�@�C������strftime���W�J�������s���������B
1323 * FLogGetLogFilename() �� FLogOpenDialog() ��
1324 * �t�@�C�����������������B
1325 */
1326 BOOL FLogOpen(const wchar_t *fname)
1327 {
1328 BOOL ret;
1329
1330 if (LogVar != NULL) {
1331 return FALSE;
1332 }
1333 if ((FileLog) || (BinLog)) return FALSE;
1334
1335 //
1336 PFileVar fv = (PFileVar)malloc(sizeof(TFileVar));
1337 if (fv == NULL) {
1338 return FALSE;
1339 }
1340 LogVar = fv;
1341 memset(fv, 0, sizeof(TFileVar));
1342
1343 fv->FileOpen = FALSE;
1344
1345 ret = LogStart(fname);
1346 return ret;
1347 }
1348
1349 BOOL FLogIsOpend(void)
1350 {
1351 // LogVar->FileOpen
1352 return LogVar != NULL;
1353 }
1354
1355 void FLogWriteStr(const char *str)
1356 {
1357 if (LogVar != NULL)
1358 {
1359 DWORD wrote;
1360 size_t len = strlen(str);
1361 WriteFile(LogVar->FileHandle, str, len, &wrote, NULL);
1362 LogVar->ByteCount =
1363 LogVar->ByteCount + len;
1364 if (FLogDlg!=NULL)
1365 FLogDlg->RefreshNum(LogVar->StartTime, LogVar->FileSize, LogVar->ByteCount);
1366 }
1367 }
1368
1369 void FLogInfo(char *param_ptr, size_t param_len)
1370 {
1371 if (LogVar) {
1372 param_ptr[0] = '0'
1373 + (ts.LogBinary != 0)
1374 + ((ts.Append != 0) << 1)
1375 + ((ts.LogTypePlainText != 0) << 2)
1376 + ((ts.LogTimestamp != 0) << 3)
1377 + ((ts.LogHideDialog != 0) << 4);
1378 char *filenameU8 = ToU8W(LogVar->FullName);
1379 strncpy_s(param_ptr + 1, param_len - 1, filenameU8, _TRUNCATE);
1380 free(filenameU8);
1381 }
1382 else {
1383 param_ptr[0] = '0' - 1;
1384 param_ptr[1] = 0;
1385 }
1386 }
1387
1388 /**
1389 * ���������O�t�@�C����������
1390 */
1391 const wchar_t *FLogGetFilename(void)
1392 {
1393 if (LogVar == NULL) {
1394 return NULL;
1395 }
1396 return LogVar->FullName;
1397 }
1398
1399 /**
1400 * ���O�_�C�A���O���J��
1401 * @param[in,out] info.filename �t�@�C���������l
1402 * OK���A�t�@�C�����A�s�v����������free()��������
1403 * @retval TRUE [ok] ����������
1404 * @retval FALSE �L�����Z��������
1405 */
1406 BOOL FLogOpenDialog(HINSTANCE hInst, HWND hWnd, FLogDlgInfo_t *info)
1407 {
1408 LogDlgWork_t *work = (LogDlgWork_t *)calloc(sizeof(LogDlgWork_t), 1);
1409 wchar_t *srcfnameW = FLogGetLogFilename(info->filename);
1410 work->info = info;
1411 work->info->filename = srcfnameW;
1412 work->pts = &ts;
1413 INT_PTR ret = TTDialogBoxParam(
1414 hInst, MAKEINTRESOURCE(IDD_LOGDLG),
1415 hWnd, LogFnHook, (LPARAM)work);
1416 free(srcfnameW);
1417 free(work);
1418 return ret == IDOK ? TRUE : FALSE;
1419 }
1420
1421 /**
1422 * ���O�t�@�C����������
1423 * ���O�t�@�C�����p���C�����s��
1424 * - strftime() ���������t�W�J
1425 * - �������������O�t�@�C���t�H���_������
1426 * - �z�X�g��,�|�[�g�����W�J
1427 *
1428 * @param[in] log_filename �t�@�C����(����/��������������ok)
1429 * NULL�������f�t�H���g�t�@�C����������
1430 * strftime�`��ok
1431 * @return �t���p�X�t�@�C����
1432 * �s�v���������� free() ��������
1433 */
1434 wchar_t *FLogGetLogFilename(const wchar_t *log_filename)
1435 {
1436 // �t�H���_
1437 char FileDirExpanded[MAX_PATH];
1438 const char *logdir;
1439 if (strlen(ts.LogDefaultPath) > 0) {
1440 logdir = ts.LogDefaultPath;
1441 }
1442 else if (strlen(ts.FileDir) > 0) {
1443 ExpandEnvironmentStrings(ts.FileDir, FileDirExpanded, sizeof(FileDirExpanded));
1444 logdir = FileDirExpanded;
1445 }
1446 else {
1447 logdir = ts.HomeDir;
1448 }
1449
1450 // ���������t�@�C����
1451 char base_name[MAX_PATH];
1452 if (log_filename == NULL) {
1453 strncpy_s(base_name, _countof(base_name), ts.LogDefaultName, _TRUNCATE);
1454 }
1455 else {
1456 char *filenameA = ToCharW(log_filename);
1457 strncpy_s(base_name, _countof(base_name), filenameA, _TRUNCATE);
1458 free(filenameA);
1459 }
1460
1461 // �t���p�X��
1462 char full_path[MAX_PATH];
1463 ConvFName(logdir, base_name, sizeof(base_name), "", full_path, sizeof(full_path));
1464 ParseStrftimeFileName(full_path, sizeof(full_path));
1465 ConvertLogname(full_path, sizeof(full_path));
1466
1467 return ToWcharA(full_path);
1468 }
1469
1470 BOOL FLogIsPause()
1471 {
1472 if (LogVar == NULL) {
1473 return FALSE;
1474 }
1475 return LogVar->IsPause;
1476 }
1477
1478 void FLogWindow(int nCmdShow)
1479 {
1480 if (LogVar == NULL) {
1481 return;
1482 }
1483 if (FLogDlg == NULL)
1484 return;
1485
1486 HWND HWndLog = FLogDlg->m_hWnd;
1487 ShowWindow(HWndLog, nCmdShow);
1488 if (nCmdShow == SW_RESTORE) {
1489 // �g���X�^�C�� WS_EX_NOACTIVATE ��������������
1490 SetForegroundWindow(HWndLog);
1491 }
1492 }
1493
1494 void FLogShowDlg(void)
1495 {
1496 if (LogVar == NULL) {
1497 return;
1498 }
1499 if (FLogDlg != NULL) {
1500 FLogDlg->ShowWindow(SW_SHOWNORMAL);
1501 SetForegroundWindow(FLogDlg->GetSafeHwnd());
1502 }
1503 }
1504
1505 /**
1506 * ���O��1byte��������
1507 * LogPut1() ������?
1508 */
1509 //void Log1Bin(PComVar cv, BYTE b)
1510 static void Log1Bin(BYTE b)
1511 {
1512 if (LogVar->IsPause || cv.ProtoFlag) {
1513 return;
1514 }
1515 if (cv.BinSkip > 0) {
1516 cv.BinSkip--;
1517 return;
1518 }
1519 cv.BinBuf[cv.BinPtr] = b;
1520 cv.BinPtr++;
1521 if (cv.BinPtr>=InBuffSize) {
1522 cv.BinPtr = cv.BinPtr-InBuffSize;
1523 }
1524 if (cv.BCount>=InBuffSize) {
1525 cv.BCount = InBuffSize;
1526 cv.BStart = cv.BinPtr;
1527 }
1528 else {
1529 cv.BCount++;
1530 }
1531 }
1532
1533 static void LogBinSkip(int add)
1534 {
1535 if (cv.HBinBuf!=0 ) {
1536 cv.BinSkip += add;
1537 }
1538 }
1539
1540 /**
1541 * ���O�o�b�t�@���������������f�[�^���o�C�g��������
1542 */
1543 int FLogGetCount(void)
1544 {
1545 if (FileLog) {
1546 return cv.LCount;
1547 }
1548 if (BinLog) {
1549 return cv.BCount;
1550 }
1551 return 0;
1552 }
1553
1554 /**
1555 * �o�b�t�@�������O���t�@�C������������
1556 */
1557 void FLogWriteFile(void)
1558 {
1559 if (cv.LogBuf!=NULL)
1560 {
1561 if (FileLog) {
1562 LogToFile();
1563 }
1564 GlobalUnlock(cv.HLogBuf);
1565 cv.LogBuf = NULL;
1566 }
1567
1568 if (cv.BinBuf!=NULL)
1569 {
1570 if (BinLog) {
1571 LogToFile();
1572 }
1573 GlobalUnlock(cv.HBinBuf);
1574 cv.BinBuf = NULL;
1575 }
1576 }

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