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 8899 - (show annotations) (download) (as text)
Tue Aug 18 15:29:19 2020 UTC (3 years, 7 months ago) by zmatsuo
File MIME type: text/x-c++src
File size: 40368 byte(s)
ログに関するAPIをUnicode化した

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

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