Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/teraterm/teraterm/logdlg.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 11020 - (show annotations) (download) (as text)
Sat Oct 21 15:16:14 2023 UTC (7 months, 1 week ago) by zmatsuo
File MIME type: text/x-c++src
File size: 15462 byte(s)
hDragQueryFileW() を win32helper に追加
1 /*
2 * (C) 2023- 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 #include <stdio.h>
30 #if !defined(_CRTDBG_MAP_ALLOC)
31 #define _CRTDBG_MAP_ALLOC
32 #endif
33 #include <stdlib.h>
34 #include <crtdbg.h>
35 #include <windows.h>
36 #include <htmlhelp.h>
37 #include <assert.h>
38
39 #include "teraterm.h"
40 #include "tttypes.h"
41 #include "ftdlg.h"
42 #include "ttcommon.h"
43 #include "ttlib.h"
44 #include "dlglib.h"
45 #include "helpid.h"
46 #include "asprintf.h"
47 #include "win32helper.h"
48
49 #include "filesys_log_res.h"
50 #include "filesys_log.h"
51
52 #include "logdlg.h"
53
54 #define ID_EVENT 0
55
56 typedef struct {
57 FLogDlgInfo_t *info;
58 // work
59 bool file_exist;
60 int current_bom; // ���������t�@�C�����G���R�[�f�B���O�i�t�@�C����BOM���������j
61 bool available_timer;
62 bool enable_timer;
63 bool on_initdialog;
64 WNDPROC proc;
65 TTTSet *pts;
66 TComVar *pcv;
67 } LogDlgWork_t;
68
69 /**
70 * �_�C�A���O�����e�� ts ����������
71 *
72 * TODO
73 * �_�C�A���O�����������l�������I��������
74 * ����������������������������������������������?
75 */
76 static void SetLogFlags(HWND Dialog, TTTSet *pts)
77 {
78 WORD BinFlag, val;
79
80 GetRB(Dialog, &BinFlag, IDC_FOPTBIN, IDC_FOPTBIN);
81 pts->LogBinary = BinFlag;
82
83 GetRB(Dialog, &val, IDC_APPEND, IDC_APPEND);
84 pts->Append = val;
85
86 if (!BinFlag) {
87 GetRB(Dialog, &val, IDC_PLAINTEXT, IDC_PLAINTEXT);
88 pts->LogTypePlainText = val;
89
90 GetRB(Dialog, &val, IDC_TIMESTAMP, IDC_TIMESTAMP);
91 pts->LogTimestamp = val;
92 }
93
94 GetRB(Dialog, &val, IDC_HIDEDIALOG, IDC_HIDEDIALOG);
95 pts->LogHideDialog = val;
96
97 GetRB(Dialog, &val, IDC_ALLBUFF_INFIRST, IDC_ALLBUFF_INFIRST);
98 pts->LogAllBuffIncludedInFirst = val;
99
100 pts->LogTimestampType = (WORD)(GetCurSel(Dialog, IDC_TIMESTAMPTYPE) - 1);
101 }
102
103 /**
104 * ���O�t�@�C���`�F�b�N
105 *
106 * @param[in] filename
107 * @param[out] exist ture/false
108 * @param[out] bom 0 no BOM (or file not exist or too short)
109 * 1 UTF-8
110 * 2 UTF-16LE
111 * 3 UTF-16BE
112 */
113 static void CheckLogFile(const wchar_t *filename, bool *exist, int *bom)
114 {
115 *exist = FALSE;
116 *bom = 0;
117
118 // �t�@�C������������?
119 DWORD logdir = GetFileAttributesW(filename);
120 if ((logdir != INVALID_FILE_ATTRIBUTES) && ((logdir & FILE_ATTRIBUTE_DIRECTORY) == 0)) {
121 // �t�@�C����������
122 *exist = TRUE;
123
124 // BOM�L��/�����`�F�b�N
125 FILE *fp;
126 errno_t e = _wfopen_s(&fp, filename, L"rb");
127 if (e == 0 && fp != NULL) {
128 unsigned char tmp[4];
129 size_t l = fread(tmp, 1, sizeof(tmp), fp);
130 fclose(fp);
131 if (l < 2) {
132 *bom = 0;
133 } else if (l >= 2 && tmp[0] == 0xff && tmp[1] == 0xfe) {
134 // UTF-16LE
135 *bom = 2;
136 } else if (l >= 2 && tmp[0] == 0xfe && tmp[1] == 0xff) {
137 // UTF-16BE
138 *bom = 3;
139 } else if (l >= 3 && tmp[0] == 0xef && tmp[1] == 0xbb && tmp[2] == 0xbf) {
140 // UTF-8
141 *bom = 1;
142 } else {
143 *bom = 0;
144 }
145 }
146 }
147 }
148
149 static void CheckLogFile(const wchar_t *filename, LogDlgWork_t *work)
150 {
151 bool exist;
152 int bom;
153 CheckLogFile(filename, &exist, &bom);
154 work->file_exist = exist;
155 work->current_bom = bom;
156 }
157
158 /**
159 * ���W�I�{�^���A�t�@�C�������������R���g���[����Enable/Disable����
160 */
161 static void ArrangeControls(HWND Dialog, LogDlgWork_t *work)
162 {
163 // Append ���W�I�{�^��
164 if (work->file_exist) {
165 // �w���������t�@�C������������������ Enable
166 EnableWindow(GetDlgItem(Dialog, IDC_APPEND), TRUE);
167 }
168 else {
169 // �w���������t�@�C�������������������� Disable
170 EnableWindow(GetDlgItem(Dialog, IDC_APPEND), FALSE);
171 }
172
173 const bool log_binary = IsDlgButtonChecked(Dialog, IDC_FOPTBIN) == BST_CHECKED;
174 const bool new_overwrite = IsDlgButtonChecked(Dialog, IDC_NEW_OVERWRITE) == BST_CHECKED;
175
176 // BOM, Encoding
177 if (!log_binary && new_overwrite) {
178 // Text ���� New/Overwrite �������� Enable
179 EnableWindow(GetDlgItem(Dialog, IDC_BOM), TRUE);
180 EnableWindow(GetDlgItem(Dialog, IDC_TEXTCODING_DROPDOWN), TRUE);
181 }
182 else {
183 // ���������������� Disable
184 // BOM ���t�@�C��������������������������������������
185 // Encoding �����L�����������������A�����t�@�C�����G���R�[�f�B���O��
186 // �����I���_�C�A���O�����f���������A���[�U�������w������������
187 EnableWindow(GetDlgItem(Dialog, IDC_BOM), FALSE);
188 EnableWindow(GetDlgItem(Dialog, IDC_TEXTCODING_DROPDOWN), FALSE);
189 }
190
191 // Plain Text, Timestamp, Timestamp ����
192 if (log_binary) {
193 // Binary �������� Disable
194 DisableDlgItem(Dialog, IDC_PLAINTEXT, IDC_PLAINTEXT);
195 DisableDlgItem(Dialog, IDC_TIMESTAMP, IDC_TIMESTAMP);
196 DisableDlgItem(Dialog, IDC_TIMESTAMPTYPE, IDC_TIMESTAMPTYPE);
197 }
198 else {
199 // Text �������� Enable
200 EnableDlgItem(Dialog, IDC_PLAINTEXT, IDC_PLAINTEXT);
201 EnableDlgItem(Dialog, IDC_TIMESTAMP, IDC_TIMESTAMP);
202
203 // Timestamp ����
204 if (IsDlgButtonChecked(Dialog, IDC_TIMESTAMP) == BST_UNCHECKED) {
205 // Timestamp=off �������� Disable
206 DisableDlgItem(Dialog, IDC_TIMESTAMPTYPE, IDC_TIMESTAMPTYPE);
207 } else {
208 // Timestamp=on �������� Enable
209 EnableDlgItem(Dialog, IDC_TIMESTAMPTYPE, IDC_TIMESTAMPTYPE);
210 }
211 }
212
213 if (work->file_exist && !new_overwrite) {
214 // �����t�@�C�����G���R�[�f�B���O�����f����
215 int bom = work->current_bom;
216 int cur =
217 bom == 1 ? 0 :
218 bom == 2 ? 1 :
219 bom == 3 ? 2 : 0;
220 SendDlgItemMessage(Dialog, IDC_TEXTCODING_DROPDOWN, CB_SETCURSEL, cur, 0);
221 }
222 }
223
224 static LRESULT CALLBACK FNameEditProc(HWND dlg, UINT msg,
225 WPARAM wParam, LPARAM lParam)
226 {
227 LogDlgWork_t *work = (LogDlgWork_t *)GetWindowLongPtr(dlg, GWLP_USERDATA);
228 switch (msg) {
229 case WM_KEYDOWN:
230 case WM_LBUTTONDOWN:
231 case WM_RBUTTONDOWN:
232 case WM_KILLFOCUS:
233 work->enable_timer = false;
234 break;
235 }
236 return CallWindowProcW(work->proc, dlg, msg, wParam, lParam);
237 }
238
239 static INT_PTR CALLBACK LogFnHook(HWND Dialog, UINT Message, WPARAM wParam, LPARAM lParam)
240 {
241 static const DlgTextInfo TextInfos[] = {
242 { 0, "DLG_TABSHEET_TITLE_LOG" },
243 { IDC_SENDFILE_FILENAME_TITLE, "DLG_FOPT_FILENAME_TITLE" },
244 { IDC_FOPTTEXT, "DLG_FOPT_TEXT" },
245 { IDC_FOPTBIN, "DLG_FOPT_BINARY" },
246 { IDC_BOM, "DLG_FOPT_BOM" },
247 { IDC_APPEND, "DLG_FOPT_APPEND" },
248 { IDC_PLAINTEXT, "DLG_FOPT_PLAIN" },
249 { IDC_HIDEDIALOG, "DLG_FOPT_HIDEDIALOG" },
250 { IDC_ALLBUFF_INFIRST, "DLG_FOPT_ALLBUFFINFIRST" },
251 { IDC_TIMESTAMP, "DLG_FOPT_TIMESTAMP" },
252 { IDC_NEW_OVERWRITE, "DLG_FOPT_NEW_OVERWRITE" },
253 { IDC_APPEND_GROUP, "DLG_FOPT_APPEND_LABEL" },
254 { IDC_BINARY_GROUP, "DLG_FOPT_BINARY_LABEL" },
255 };
256 static const I18nTextInfo timestamp_list[] = {
257 { "DLG_FOPT_TIMESTAMP_LOCAL", L"Local Time" },
258 { "DLG_FOPT_TIMESTAMP_UTC", L"UTC" },
259 { "DLG_FOPT_TIMESTAMP_ELAPSED_LOGGING", L"Elapsed Time (Logging)" },
260 { "DLG_FOPT_TIMESTAMP_ELAPSED_CONNECTION", L"Elapsed Time (Connection)" },
261 };
262 LogDlgWork_t *work = (LogDlgWork_t *)GetWindowLongPtr(Dialog, DWLP_USER);
263
264 if (Message == RegisterWindowMessage(HELPMSGSTRING)) {
265 // �R�����_�C�A���O�������w���v���b�Z�[�W���t��������
266 Message = WM_COMMAND;
267 wParam = IDHELP;
268 }
269 switch (Message) {
270 case WM_INITDIALOG: {
271 work = (LogDlgWork_t *)lParam;
272 work->on_initdialog = true;
273 TTTSet *pts = work->pts;
274 SetWindowLongPtr(Dialog, DWLP_USER, (LONG_PTR)work);
275 ::DragAcceptFiles(Dialog, TRUE);
276
277 SetDlgTextsW(Dialog, TextInfos, _countof(TextInfos), pts->UILanguageFileW);
278 SetI18nListW("Tera Term", Dialog, IDC_TIMESTAMPTYPE, timestamp_list, _countof(timestamp_list),
279 pts->UILanguageFileW, 0);
280
281 SendDlgItemMessageA(Dialog, IDC_TEXTCODING_DROPDOWN, CB_ADDSTRING, 0, (LPARAM)"UTF-8");
282 SendDlgItemMessageA(Dialog, IDC_TEXTCODING_DROPDOWN, CB_ADDSTRING, 0, (LPARAM)"UTF-16LE");
283 SendDlgItemMessageA(Dialog, IDC_TEXTCODING_DROPDOWN, CB_ADDSTRING, 0, (LPARAM)"UTF-16BE");
284 SendDlgItemMessageA(Dialog, IDC_TEXTCODING_DROPDOWN, CB_SETCURSEL, 0, 0);
285
286 // new(overwrite)/append radio button
287 CheckRadioButton(Dialog, IDC_NEW_OVERWRITE, IDC_APPEND,
288 pts->Append == 0 ? IDC_NEW_OVERWRITE : IDC_APPEND);
289
290 // timestamp
291 CheckDlgButton(Dialog, IDC_TIMESTAMP, pts->LogTimestamp == 0 ? BST_UNCHECKED : BST_CHECKED);
292
293 // timestamp ����
294 int tstype = pts->LogTimestampType == TIMESTAMP_LOCAL ? 0 :
295 pts->LogTimestampType == TIMESTAMP_UTC ? 1 :
296 pts->LogTimestampType == TIMESTAMP_ELAPSED_LOGSTART ? 2 :
297 pts->LogTimestampType == TIMESTAMP_ELAPSED_CONNECTED ? 3 : 0;
298 SendDlgItemMessageA(Dialog, IDC_TIMESTAMPTYPE, CB_SETCURSEL, tstype, 0);
299
300 // plain text
301 CheckDlgButton(Dialog, IDC_PLAINTEXT, pts->LogTypePlainText == 0 ? BST_UNCHECKED : BST_CHECKED);
302
303 // Hide dialog �`�F�b�N�{�b�N�X
304 if (pts->LogHideDialog) {
305 SetRB(Dialog, 1, IDC_HIDEDIALOG, IDC_HIDEDIALOG);
306 }
307
308 // Include screen buffer �`�F�b�N�{�b�N�X
309 if (pts->LogAllBuffIncludedInFirst) {
310 SetRB(Dialog, 1, IDC_ALLBUFF_INFIRST, IDC_ALLBUFF_INFIRST);
311 }
312
313 // text/binary radio button
314 CheckRadioButton(Dialog, IDC_FOPTBIN, IDC_FOPTTEXT, pts->LogBinary == 0 ? IDC_FOPTTEXT : IDC_FOPTBIN);
315
316 // �t�@�C��������������
317 // �t�@�C�����`�F�b�N�A�R���g���[�����������s������
318 // WM_COMMAND, EN_CHANGE ����������
319 wchar_t *fname = FLogGetLogFilename(work->info->filename);
320 SetDlgItemTextW(Dialog, IDC_FOPT_FILENAME_EDIT, fname);
321 free(fname);
322 HWND file_edit = GetDlgItem(Dialog, IDC_FOPT_FILENAME_EDIT);
323 SetWindowLongPtr(file_edit, GWLP_USERDATA, (LONG_PTR)work);
324 work->proc = (WNDPROC)SetWindowLongPtrW(file_edit, GWLP_WNDPROC, (LONG_PTR)FNameEditProc);
325
326 CenterWindow(Dialog, GetParent(Dialog));
327
328 SetFocus(GetDlgItem(Dialog, IDC_FOPT_FILENAME_EDIT));
329
330 work->enable_timer = true;
331 work->available_timer = true;
332 SetTimer(Dialog, ID_EVENT, 1000, NULL);
333
334 work->on_initdialog = false;
335
336 return TRUE;
337 }
338
339 case WM_COMMAND:
340 switch (LOWORD(wParam)) {
341 case IDOK: {
342 wchar_t *filename;
343 hGetDlgItemTextW(Dialog, IDC_FOPT_FILENAME_EDIT, &filename);
344 work->info->filename = filename;
345 work->info->append = IsDlgButtonChecked(Dialog, IDC_APPEND) == BST_CHECKED;
346 work->info->bom = IsDlgButtonChecked(Dialog, IDC_BOM) == BST_CHECKED;
347 work->info->code = (LogCode_t)SendDlgItemMessageA(Dialog, IDC_TEXTCODING_DROPDOWN, CB_GETCURSEL, 0, 0);
348 SetLogFlags(Dialog, work->pts);
349 EndDialog(Dialog, IDOK);
350 break;
351 }
352 case IDCANCEL:
353 EndDialog(Dialog, IDCANCEL);
354 break;
355 case IDHELP:
356 OpenHelpCV(work->pcv, HH_HELP_CONTEXT, HlpFileLog);
357 break;
358 case IDC_FOPT_FILENAME_BUTTON: {
359 /* save current dir */
360 const wchar_t *UILanguageFile = work->pts->UILanguageFileW;
361
362 wchar_t *fname_ini;
363 hGetDlgItemTextW(Dialog, IDC_FOPT_FILENAME_EDIT, &fname_ini);
364
365 const wchar_t* simple_log_filter = L"*.txt;*.log";
366 wchar_t *FNFilter = GetCommonDialogFilterWW(simple_log_filter, UILanguageFile);
367
368 wchar_t *uimsg;
369 GetI18nStrWW("Tera Term", "FILEDLG_TRANS_TITLE_LOG",
370 L"Log", UILanguageFile, &uimsg);
371 wchar_t *caption;
372 aswprintf(&caption, L"Tera Term: %s", uimsg);
373 free(uimsg);
374
375 TTOPENFILENAMEW ofn = {};
376 //ofn.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT;
377 ofn.Flags |= OFN_EXPLORER | OFN_ENABLESIZING;
378 ofn.Flags |= OFN_SHOWHELP;
379 ofn.hwndOwner = Dialog;
380 ofn.lpstrFilter = FNFilter;
381 ofn.nFilterIndex = 1;
382 ofn.lpstrFile = fname_ini;
383 ofn.lpstrTitle = caption;
384 ofn.lpstrInitialDir = work->pts->LogDefaultPathW;
385 wchar_t *fname;
386 BOOL Ok = TTGetSaveFileNameW(&ofn, &fname);
387 if (Ok) {
388 SetDlgItemTextW(Dialog, IDC_FOPT_FILENAME_EDIT, fname);
389 free(fname);
390 }
391 free(caption);
392 free(FNFilter);
393 free(fname_ini);
394
395 break;
396 }
397 case IDC_NEW_OVERWRITE:
398 case IDC_APPEND:
399 case IDC_FOPTTEXT:
400 case IDC_FOPTBIN:
401 case IDC_TIMESTAMP:
402 ArrangeControls(Dialog, work);
403 break;
404 case IDC_FOPT_FILENAME_EDIT:
405 if (HIWORD(wParam) == EN_CHANGE){
406 wchar_t *filename;
407 hGetDlgItemTextW(Dialog, IDC_FOPT_FILENAME_EDIT, &filename);
408 const bool file_exist_prev = work->file_exist;
409 CheckLogFile(filename, work);
410 free(filename);
411 if (work->on_initdialog || file_exist_prev != work->file_exist) {
412 if (work->file_exist) {
413 // �t�@�C�������������A���������������V�K(������)/���L���I������
414 CheckRadioButton(Dialog, IDC_NEW_OVERWRITE, IDC_APPEND,
415 work->pts->Append == 0 ? IDC_NEW_OVERWRITE : IDC_APPEND);
416 }
417 else {
418 // �t�@�C���������������A�V�K���I������
419 CheckRadioButton(Dialog, IDC_NEW_OVERWRITE, IDC_APPEND, IDC_NEW_OVERWRITE);
420 }
421 ArrangeControls(Dialog, work);
422 }
423 }
424 break;
425 }
426 break;
427 case WM_DROPFILES: {
428 // �����h���b�v��������������1������������
429 HDROP hDrop = (HDROP)wParam;
430 wchar_t *filename;
431 hDragQueryFileW(hDrop, 0, &filename);
432 DragFinish(hDrop);
433 CheckRadioButton(Dialog, IDC_NEW_OVERWRITE, IDC_APPEND, IDC_APPEND);
434 SetDlgItemTextW(Dialog, IDC_FOPT_FILENAME_EDIT, filename);
435 SendDlgItemMessageW(Dialog, IDC_FOPT_FILENAME_EDIT, EM_SETSEL, 0, -1);
436 free(filename);
437 return TRUE;
438 }
439 case WM_TIMER: {
440 if (!work->enable_timer) {
441 KillTimer(Dialog, ID_EVENT);
442 work->available_timer = false;
443 break;
444 }
445 wchar_t *fname = FLogGetLogFilename(work->info->filename);
446 SetDlgItemTextW(Dialog, IDC_FOPT_FILENAME_EDIT, fname);
447 SendDlgItemMessageW(Dialog, IDC_FOPT_FILENAME_EDIT, EM_SETSEL, 0, -1);
448 free(fname);
449 break;
450 }
451 case WM_DESTROY:
452 if (work->available_timer) {
453 KillTimer(Dialog, ID_EVENT);
454 work->available_timer = false;
455 }
456 break;
457 }
458 return FALSE;
459 }
460
461 /**
462 * ���O�_�C�A���O���J��
463 * @param[in,out] info.filename �t�@�C���������l
464 * OK���A�t�@�C�����A�s�v����������free()��������
465 * @retval TRUE [ok] ����������
466 * @retval FALSE �L�����Z��������
467 */
468 BOOL FLogOpenDialog(HINSTANCE hInst_, HWND hWnd, FLogDlgInfo_t *info)
469 {
470 LogDlgWork_t *work = (LogDlgWork_t *)calloc(sizeof(LogDlgWork_t), 1);
471 work->info = info;
472 work->pts = info->pts;
473 work->pcv = info->pcv;
474 INT_PTR ret = TTDialogBoxParam(
475 hInst_, MAKEINTRESOURCE(IDD_LOGDLG),
476 hWnd, LogFnHook, (LPARAM)work);
477 free(work);
478 return ret == IDOK ? TRUE : FALSE;
479 }

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