| 31 |
#include <stdio.h> |
#include <stdio.h> |
| 32 |
#include <io.h> |
#include <io.h> |
| 33 |
#include <process.h> |
#include <process.h> |
| 34 |
|
#include <windows.h> |
| 35 |
|
#include <htmlhelp.h> |
| 36 |
|
#include <assert.h> |
| 37 |
|
|
| 38 |
#include "teraterm.h" |
#include "teraterm.h" |
| 39 |
#include "tttypes.h" |
#include "tttypes.h" |
| 40 |
#include "ttftypes.h" |
#include "ttftypes.h" |
|
#include "tt_res.h" |
|
| 41 |
#include "ftdlg.h" |
#include "ftdlg.h" |
| 42 |
#include "protodlg.h" |
#include "protodlg.h" |
| 43 |
#include "ttwinman.h" |
#include "ttwinman.h" |
| 48 |
#include "dlglib.h" |
#include "dlglib.h" |
| 49 |
#include "vtterm.h" |
#include "vtterm.h" |
| 50 |
#include "win16api.h" |
#include "win16api.h" |
|
|
|
|
#include "filesys.h" |
|
| 51 |
#include "ftlib.h" |
#include "ftlib.h" |
|
|
|
| 52 |
#include "buffer.h" |
#include "buffer.h" |
| 53 |
|
#include "helpid.h" |
| 54 |
|
#include "layer_for_unicode.h" |
| 55 |
|
|
| 56 |
#include <io.h> |
#include "filesys.h" |
| 57 |
#include <process.h> |
#include "tt_res.h" |
| 58 |
|
#include "filesys_log_res.h" |
| 59 |
|
|
| 60 |
#define FS_BRACKET_NONE 0 |
#define FS_BRACKET_NONE 0 |
| 61 |
#define FS_BRACKET_START 1 |
#define FS_BRACKET_START 1 |
| 62 |
#define FS_BRACKET_END 2 |
#define FS_BRACKET_END 2 |
| 63 |
|
|
| 64 |
PFileVar LogVar = NULL; |
static PFileVar LogVar = NULL; |
| 65 |
PFileVar SendVar = NULL; |
PFileVar SendVar = NULL; |
| 66 |
PFileVar FileVar = NULL; |
PFileVar FileVar = NULL; |
| 67 |
static PCHAR ProtoVar = NULL; |
static PCHAR ProtoVar = NULL; |
| 95 |
static int TTFILECount = 0; |
static int TTFILECount = 0; |
| 96 |
|
|
| 97 |
PGetSetupFname GetSetupFname; |
PGetSetupFname GetSetupFname; |
| 98 |
PGetTransFname GetTransFname; |
static PGetTransFname GetTransFname; |
| 99 |
PGetMultiFname GetMultiFname; |
PGetMultiFname GetMultiFname; |
| 100 |
PGetGetFname GetGetFname; |
PGetGetFname GetGetFname; |
| 101 |
PSetFileVar SetFileVar; |
PSetFileVar SetFileVar; |
| 352 |
} |
} |
| 353 |
} |
} |
| 354 |
|
|
| 355 |
// &h をホスト名に置換 (2007.5.14) |
/** |
| 356 |
// &p をTCPポート番号に置換 (2009.6.12) |
* ファイル名文字列の置き換え |
| 357 |
void ConvertLogname(char *c, int destlen) |
* &h ホスト名に置換 (2007.5.14) |
| 358 |
|
* &p TCPポート番号に置換 (2009.6.12) |
| 359 |
|
* &u ログオン中のユーザ名 |
| 360 |
|
*/ |
| 361 |
|
static void ConvertLogname(char *c, int destlen) |
| 362 |
{ |
{ |
| 363 |
char buf[MAXPATHLEN], buf2[MAXPATHLEN], *p = c; |
char buf[MAXPATHLEN], buf2[MAXPATHLEN], *p = c; |
| 364 |
char tmphost[1024]; |
char tmphost[1024]; |
| 416 |
strncpy_s(c, destlen, buf, _TRUNCATE); |
strncpy_s(c, destlen, buf, _TRUNCATE); |
| 417 |
} |
} |
| 418 |
|
|
| 419 |
void FixLogOption() |
static void FixLogOption() |
| 420 |
{ |
{ |
| 421 |
if (ts.LogBinary) { |
if (ts.LogBinary) { |
| 422 |
ts.LogTypePlainText = false; |
ts.LogTypePlainText = false; |
| 429 |
static void CloseFileSync(PFileVar ptr) |
static void CloseFileSync(PFileVar ptr) |
| 430 |
{ |
{ |
| 431 |
BOOL ret; |
BOOL ret; |
|
DWORD code; |
|
| 432 |
|
|
| 433 |
if (!ptr->FileOpen) |
if (!ptr->FileOpen) |
| 434 |
return; |
return; |
| 441 |
WaitForSingleObject(ptr->LogThread, INFINITE); |
WaitForSingleObject(ptr->LogThread, INFINITE); |
| 442 |
} |
} |
| 443 |
else { |
else { |
| 444 |
code = GetLastError(); |
//DWORD code = GetLastError(); |
| 445 |
} |
} |
| 446 |
CloseHandle(ptr->LogThread); |
CloseHandle(ptr->LogThread); |
| 447 |
ptr->LogThread = INVALID_HANDLE_VALUE; |
ptr->LogThread = INVALID_HANDLE_VALUE; |
| 485 |
return (0); |
return (0); |
| 486 |
} |
} |
| 487 |
|
|
| 488 |
|
/** |
| 489 |
BOOL LogStart() |
* ダイアログの内容を ts に書き戻し |
| 490 |
{ |
* |
| 491 |
LONG Option; |
* TODO |
| 492 |
char *logdir; |
* ダイアログで設定した値は一時的なもので |
| 493 |
unsigned tid; |
* 設定を上書きするのは良くないのではないだろうか? |
| 494 |
DWORD ofs, size, written_size; |
*/ |
| 495 |
char buf[512]; |
static void SetLogFlags(HWND Dialog) |
| 496 |
const char *crlf = "\r\n"; |
{ |
| 497 |
DWORD crlf_len = 2; |
WORD BinFlag, val; |
| 498 |
char FileDirExpanded[MAX_PATH]; |
|
| 499 |
|
GetRB(Dialog, &BinFlag, IDC_FOPTBIN, IDC_FOPTBIN); |
| 500 |
if ((FileLog) || (BinLog)) return FALSE; |
ts.LogBinary = BinFlag; |
| 501 |
|
|
| 502 |
if (! LoadTTFILE()) return FALSE; |
GetRB(Dialog, &val, IDC_FOPTAPPEND, IDC_FOPTAPPEND); |
| 503 |
if (! NewFileVar(&LogVar)) |
ts.Append = val; |
| 504 |
{ |
|
| 505 |
FreeTTFILE(); |
if (!BinFlag) { |
| 506 |
return FALSE; |
GetRB(Dialog, &val, IDC_PLAINTEXT, IDC_PLAINTEXT); |
| 507 |
|
ts.LogTypePlainText = val; |
| 508 |
|
|
| 509 |
|
GetRB(Dialog, &val, IDC_TIMESTAMP, IDC_TIMESTAMP); |
| 510 |
|
ts.LogTimestamp = val; |
| 511 |
|
} |
| 512 |
|
|
| 513 |
|
GetRB(Dialog, &val, IDC_HIDEDIALOG, IDC_HIDEDIALOG); |
| 514 |
|
ts.LogHideDialog = val; |
| 515 |
|
|
| 516 |
|
GetRB(Dialog, &val, IDC_ALLBUFF_INFIRST, IDC_ALLBUFF_INFIRST); |
| 517 |
|
ts.LogAllBuffIncludedInFirst = val; |
| 518 |
|
|
| 519 |
|
ts.LogTimestampType = (GetCurSel(Dialog, IDC_TIMESTAMPTYPE) - 1); |
| 520 |
|
} |
| 521 |
|
|
| 522 |
|
/** |
| 523 |
|
* ログファイルチェック |
| 524 |
|
* |
| 525 |
|
* @param[in] filename |
| 526 |
|
* @param[out] exist TURE/FALSE |
| 527 |
|
* @param[out] bom 0 no BOM (or file not exist) |
| 528 |
|
* 1 UTF-8 |
| 529 |
|
* 2 UTF-16LE |
| 530 |
|
* 3 UTF-16BE |
| 531 |
|
*/ |
| 532 |
|
static void CheckLogFile(const char *filename, BOOL *exist, int *bom) |
| 533 |
|
{ |
| 534 |
|
// ファイルが存在する? |
| 535 |
|
DWORD logdir = GetFileAttributes(filename); |
| 536 |
|
if ((logdir != INVALID_FILE_ATTRIBUTES) && ((logdir & FILE_ATTRIBUTE_DIRECTORY) == 0)) { |
| 537 |
|
// ファイルがあった , アペンドするつもり |
| 538 |
|
*exist = TRUE; |
| 539 |
|
|
| 540 |
|
// BOM有り/無しチェック |
| 541 |
|
FILE *fp = fopen(filename, "rb"); |
| 542 |
|
unsigned char tmp[4]; |
| 543 |
|
size_t l = fread(tmp, 1, sizeof(tmp), fp); |
| 544 |
|
fclose(fp); |
| 545 |
|
if (l < 2) { |
| 546 |
|
*bom = 0; |
| 547 |
|
} else if (l >= 2 && tmp[0] == 0xff && tmp[1] == 0xfe) { |
| 548 |
|
// UTF-16LE |
| 549 |
|
*bom = 2; |
| 550 |
|
} else if (l >= 2 && tmp[0] == 0xfe && tmp[1] == 0xff) { |
| 551 |
|
// UTF-16BE |
| 552 |
|
*bom = 3; |
| 553 |
|
} else if (l >= 3 && tmp[0] == 0xef && tmp[1] == 0xbb && tmp[2] == 0xbf) { |
| 554 |
|
// UTF-8 |
| 555 |
|
*bom = 1; |
| 556 |
|
} else { |
| 557 |
|
*bom = 0; |
| 558 |
|
} |
| 559 |
} |
} |
| 560 |
LogVar->OpId = OpLog; |
else { |
| 561 |
|
// ファイルがない、新規 |
| 562 |
if (strlen(ts.LogDefaultPath) > 0) { |
*exist = FALSE; |
| 563 |
logdir = ts.LogDefaultPath; |
*bom = 0; |
| 564 |
} |
} |
| 565 |
else if (strlen(ts.FileDir) > 0) { |
} |
| 566 |
ExpandEnvironmentStrings(ts.FileDir, FileDirExpanded, sizeof(FileDirExpanded)); |
|
| 567 |
logdir = FileDirExpanded; |
static void CheckLogFile(HWND Dialog, const char *filename) |
| 568 |
|
{ |
| 569 |
|
BOOL exist; |
| 570 |
|
int bom; |
| 571 |
|
CheckLogFile(filename, &exist, &bom); |
| 572 |
|
if (exist) { |
| 573 |
|
// ファイルが存在する -> アペンドするつもり? |
| 574 |
|
CheckDlgButton(Dialog, IDC_FOPTAPPEND, BST_CHECKED); |
| 575 |
|
if (bom != 0) { |
| 576 |
|
// BOM有り |
| 577 |
|
CheckDlgButton(Dialog, IDC_BOM, BST_CHECKED); |
| 578 |
|
} |
| 579 |
|
else { |
| 580 |
|
// BOMなし |
| 581 |
|
CheckDlgButton(Dialog, IDC_BOM, BST_UNCHECKED); |
| 582 |
|
} |
| 583 |
} |
} |
| 584 |
else { |
else { |
| 585 |
logdir = ts.HomeDir; |
// ファイルがない、新規 |
| 586 |
|
CheckDlgButton(Dialog, IDC_FOPTAPPEND, BST_UNCHECKED); |
| 587 |
|
CheckDlgButton(Dialog, IDC_BOM, BST_CHECKED); |
| 588 |
} |
} |
| 589 |
|
} |
| 590 |
|
|
| 591 |
if (strlen(&(LogVar->FullName[LogVar->DirLen]))==0) { |
typedef struct { |
| 592 |
Option = 0; |
char *filename; |
| 593 |
|
BOOL append; |
| 594 |
|
BOOL bom; |
| 595 |
|
} LogDlgData_t; |
| 596 |
|
|
| 597 |
|
static INT_PTR CALLBACK LogFnHook(HWND Dialog, UINT Message, WPARAM wParam, LPARAM lParam) |
| 598 |
|
{ |
| 599 |
|
static const DlgTextInfo TextInfos[] = { |
| 600 |
|
{ 0, "DLG_TABSHEET_TITLE_LOG" }, |
| 601 |
|
{ IDC_FOPTBIN, "DLG_FOPT_BINARY" }, |
| 602 |
|
{ IDC_FOPTAPPEND, "DLG_FOPT_APPEND" }, |
| 603 |
|
{ IDC_PLAINTEXT, "DLG_FOPT_PLAIN" }, |
| 604 |
|
{ IDC_HIDEDIALOG, "DLG_FOPT_HIDEDIALOG" }, |
| 605 |
|
{ IDC_ALLBUFF_INFIRST, "DLG_FOPT_ALLBUFFINFIRST" }, |
| 606 |
|
{ IDC_TIMESTAMP, "DLG_FOPT_TIMESTAMP" }, |
| 607 |
|
}; |
| 608 |
|
static const I18nTextInfo timestamp_list[] = { |
| 609 |
|
{ "DLG_FOPT_TIMESTAMP_LOCAL", L"Local Time" }, |
| 610 |
|
{ "DLG_FOPT_TIMESTAMP_UTC", L"UTC" }, |
| 611 |
|
{ "DLG_FOPT_TIMESTAMP_ELAPSED_LOGGING", L"Elapsed Time (Logging)" }, |
| 612 |
|
{ "DLG_FOPT_TIMESTAMP_ELAPSED_CONNECTION", L"Elapsed Time (Connection)" }, |
| 613 |
|
}; |
| 614 |
|
const char *UILanguageFile = ts.UILanguageFile; |
| 615 |
|
LogDlgData_t *data = (LogDlgData_t *)GetWindowLongPtr(Dialog, DWLP_USER); |
| 616 |
|
|
| 617 |
|
if (Message == RegisterWindowMessage(HELPMSGSTRING)) { |
| 618 |
|
// コモンダイアログからのヘルプメッセージを付け替える |
| 619 |
|
Message = WM_COMMAND; |
| 620 |
|
wParam = IDHELP; |
| 621 |
|
} |
| 622 |
|
switch (Message) { |
| 623 |
|
case WM_INITDIALOG: { |
| 624 |
|
data = (LogDlgData_t *)lParam; |
| 625 |
|
SetWindowLongPtr(Dialog, DWLP_USER, (LONG_PTR)data); |
| 626 |
|
::DragAcceptFiles(Dialog, TRUE); |
| 627 |
|
|
| 628 |
|
SetDlgTexts(Dialog, TextInfos, _countof(TextInfos), UILanguageFile); |
| 629 |
|
SetI18nList("Tera Term", Dialog, IDC_TIMESTAMPTYPE, timestamp_list, _countof(timestamp_list), |
| 630 |
|
UILanguageFile, 0); |
| 631 |
|
|
| 632 |
|
SendDlgItemMessage(Dialog, IDC_TEXTCODING_DROPDOWN, CB_ADDSTRING, 0, (LPARAM)"UTF-8"); |
| 633 |
|
SendDlgItemMessage(Dialog, IDC_TEXTCODING_DROPDOWN, CB_SETCURSEL, 0, 0); |
| 634 |
|
|
| 635 |
|
SetDlgItemTextA(Dialog, IDC_FOPT_FILENAME_EDIT, data->filename); |
| 636 |
|
free(data->filename); |
| 637 |
|
data->filename = NULL; |
| 638 |
|
|
| 639 |
|
// Binary/Text チェックボックス |
| 640 |
if (ts.LogBinary) { |
if (ts.LogBinary) { |
| 641 |
Option |= LOGDLG_BINARY; |
SendDlgItemMessage(Dialog, IDC_FOPTBIN, BM_SETCHECK, BST_CHECKED, 0); |
| 642 |
} |
} |
| 643 |
|
else { |
| 644 |
|
SendDlgItemMessage(Dialog, IDC_FOPTTEXT, BM_SETCHECK, BST_CHECKED, 0); |
| 645 |
|
} |
| 646 |
|
|
| 647 |
|
// Append チェックボックス |
| 648 |
if (ts.Append) { |
if (ts.Append) { |
| 649 |
Option |= LOGDLG_APPEND; |
SetRB(Dialog, 1, IDC_FOPTAPPEND, IDC_FOPTAPPEND); |
| 650 |
} |
} |
| 651 |
if (ts.LogTypePlainText) { |
|
| 652 |
Option |= LOGDLG_PLAINTEXT; |
// Plain Text チェックボックス |
| 653 |
|
if (ts.LogBinary) { |
| 654 |
|
// Binaryフラグが有効なときはチェックできない |
| 655 |
|
DisableDlgItem(Dialog, IDC_PLAINTEXT, IDC_PLAINTEXT); |
| 656 |
} |
} |
| 657 |
if (ts.LogTimestamp) { |
else if (ts.LogTypePlainText) { |
| 658 |
Option |= LOGDLG_TIMESTAMP; |
SetRB(Dialog, 1, IDC_PLAINTEXT, IDC_PLAINTEXT); |
| 659 |
} |
} |
| 660 |
|
|
| 661 |
|
// Hide dialogチェックボックス (2008.1.30 maya) |
| 662 |
if (ts.LogHideDialog) { |
if (ts.LogHideDialog) { |
| 663 |
Option |= LOGDLG_HIDEDIALOG; |
SetRB(Dialog, 1, IDC_HIDEDIALOG, IDC_HIDEDIALOG); |
| 664 |
} |
} |
| 665 |
|
|
| 666 |
|
// Include screen bufferチェックボックス (2013.9.29 yutaka) |
| 667 |
if (ts.LogAllBuffIncludedInFirst) { |
if (ts.LogAllBuffIncludedInFirst) { |
| 668 |
Option |= LOGDLG_INCSCRBUFF; |
SetRB(Dialog, 1, IDC_ALLBUFF_INFIRST, IDC_ALLBUFF_INFIRST); |
| 669 |
} |
} |
| 670 |
|
|
| 671 |
switch (ts.LogTimestampType) { |
// timestampチェックボックス (2006.7.23 maya) |
| 672 |
case TIMESTAMP_LOCAL: |
if (ts.LogBinary) { |
| 673 |
// nothing to do |
// Binaryフラグが有効なときはチェックできない |
| 674 |
break; |
DisableDlgItem(Dialog, IDC_TIMESTAMP, IDC_TIMESTAMP); |
| 675 |
case TIMESTAMP_UTC: |
} |
| 676 |
Option |= LOGDLG_UTC; |
else if (ts.LogTimestamp) { |
| 677 |
break; |
SetRB(Dialog, 1, IDC_TIMESTAMP, IDC_TIMESTAMP); |
|
case TIMESTAMP_ELAPSED_LOGSTART: |
|
|
Option |= LOGDLG_ELAPSED; |
|
|
break; |
|
|
case TIMESTAMP_ELAPSED_CONNECTED: |
|
|
Option |= LOGDLG_ELAPSED | LOGDLG_ELAPSEDCON; |
|
|
break; |
|
|
default: |
|
|
// not reached |
|
|
break; |
|
| 678 |
} |
} |
| 679 |
|
|
| 680 |
// ログのデフォルトファイル名を設定 (2006.8.28 maya) |
// timestamp 種別 |
| 681 |
strncat_s(LogVar->FullName, sizeof(LogVar->FullName), ts.LogDefaultName, _TRUNCATE); |
int tstype = ts.LogTimestampType == TIMESTAMP_LOCAL ? 0 : |
| 682 |
ParseStrftimeFileName(LogVar->FullName, sizeof(LogVar->FullName)); |
ts.LogTimestampType == TIMESTAMP_UTC ? 1 : |
| 683 |
ConvertLogname(LogVar->FullName, sizeof(LogVar->FullName)); |
ts.LogTimestampType == TIMESTAMP_ELAPSED_LOGSTART ? 2 : |
| 684 |
|
ts.LogTimestampType == TIMESTAMP_ELAPSED_CONNECTED ? 3 : 0; |
| 685 |
strncpy_s(LogVar->LogDefaultPath, sizeof(LogVar->LogDefaultPath), ts.LogDefaultPath, _TRUNCATE); |
SendDlgItemMessage(Dialog, IDC_TIMESTAMPTYPE, CB_SETCURSEL, tstype, 0); |
| 686 |
if (! (*GetTransFname)(LogVar, logdir, GTF_LOG, &Option)) { |
if (ts.LogBinary || !ts.LogTimestamp) { |
| 687 |
FreeFileVar(&LogVar); |
DisableDlgItem(Dialog, IDC_TIMESTAMPTYPE, IDC_TIMESTAMPTYPE); |
|
FreeTTFILE(); |
|
|
return FALSE; |
|
| 688 |
} |
} |
| 689 |
|
|
| 690 |
ts.LogBinary = CheckFlag(Option, LOGDLG_BINARY); |
CenterWindow(Dialog, GetParent(Dialog)); |
| 691 |
CheckFlag(Option, LOGDLG_BINARY); |
|
| 692 |
ts.Append = |
return TRUE; |
| 693 |
CheckFlag(Option, LOGDLG_APPEND); |
} |
| 694 |
ts.LogTypePlainText = |
|
| 695 |
CheckFlag(Option, LOGDLG_PLAINTEXT); |
case WM_COMMAND: |
| 696 |
ts.LogTimestamp = |
switch (LOWORD(wParam)) { |
| 697 |
CheckFlag(Option, LOGDLG_TIMESTAMP); |
case IDOK: { |
| 698 |
ts.LogHideDialog = |
char filename[MAX_PATH]; |
| 699 |
CheckFlag(Option, LOGDLG_HIDEDIALOG); |
GetDlgItemTextA(Dialog, IDC_FOPT_FILENAME_EDIT, filename, _countof(filename)); |
| 700 |
ts.LogAllBuffIncludedInFirst = |
data->filename = _strdup(filename); |
| 701 |
CheckFlag(Option, LOGDLG_INCSCRBUFF); |
data->append = IsDlgButtonChecked(Dialog, IDC_FOPTAPPEND) == BST_CHECKED; |
| 702 |
|
data->bom = IsDlgButtonChecked(Dialog, IDC_BOM) == BST_CHECKED; |
| 703 |
if (Option & LOGDLG_ELAPSED) { |
SetLogFlags(Dialog); |
| 704 |
// 経過時間 |
EndDialog(Dialog, IDOK); |
| 705 |
if (Option & LOGDLG_ELAPSEDCON) { |
break; |
| 706 |
ts.LogTimestampType = TIMESTAMP_ELAPSED_CONNECTED; |
} |
| 707 |
|
case IDCANCEL: |
| 708 |
|
EndDialog(Dialog, IDCANCEL); |
| 709 |
|
break; |
| 710 |
|
case IDHELP: |
| 711 |
|
OpenHelp(HH_HELP_CONTEXT, HlpFileLog, ts.UILanguageFile); |
| 712 |
|
break; |
| 713 |
|
case IDC_FOPT_FILENAME_BUTTON: { |
| 714 |
|
/* save current dir */ |
| 715 |
|
wchar_t curdir[MAXPATHLEN]; |
| 716 |
|
_GetCurrentDirectoryW(_countof(curdir), curdir); |
| 717 |
|
|
| 718 |
|
char fname[MAX_PATH]; |
| 719 |
|
GetDlgItemTextA(Dialog, IDC_FOPT_FILENAME_EDIT, fname, _countof(fname)); |
| 720 |
|
|
| 721 |
|
char FNFilter[128*3]; |
| 722 |
|
get_lang_msg("FILEDLG_ALL_FILTER", FNFilter, sizeof(FNFilter), "All(*.*)\\0*.*\\0\\0", UILanguageFile); |
| 723 |
|
|
| 724 |
|
char caption[MAX_PATH]; |
| 725 |
|
char uimsg[MAX_UIMSG]; |
| 726 |
|
get_lang_msg("FILEDLG_TRANS_TITLE_LOG", uimsg, sizeof(uimsg), TitLog, UILanguageFile); |
| 727 |
|
strncpy_s(caption, sizeof(caption),"Tera Term: ", _TRUNCATE); |
| 728 |
|
strncat_s(caption, sizeof(caption), uimsg, _TRUNCATE); |
| 729 |
|
|
| 730 |
|
OPENFILENAME ofn = {}; |
| 731 |
|
ofn.lStructSize = get_OPENFILENAME_SIZEA(); |
| 732 |
|
//ofn.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT; |
| 733 |
|
ofn.Flags |= OFN_EXPLORER | OFN_ENABLESIZING; |
| 734 |
|
ofn.Flags |= OFN_SHOWHELP; |
| 735 |
|
ofn.Flags |= OFN_NOCHANGEDIR; // うまく動作しない環境もあるようだ |
| 736 |
|
ofn.hwndOwner = Dialog; |
| 737 |
|
ofn.lpstrFilter = FNFilter; |
| 738 |
|
ofn.nFilterIndex = 1; |
| 739 |
|
ofn.lpstrFile = fname; |
| 740 |
|
ofn.nMaxFile = sizeof(fname); |
| 741 |
|
ofn.lpstrTitle = caption; |
| 742 |
|
BOOL Ok = GetSaveFileName(&ofn); |
| 743 |
|
if (Ok) { |
| 744 |
|
SetDlgItemTextA(Dialog, IDC_FOPT_FILENAME_EDIT, fname); |
| 745 |
|
} |
| 746 |
|
|
| 747 |
|
/* restore dir */ |
| 748 |
|
_SetCurrentDirectoryW(curdir); |
| 749 |
|
|
| 750 |
|
break; |
| 751 |
|
} |
| 752 |
|
case IDC_FOPTBIN: |
| 753 |
|
DisableDlgItem(Dialog, IDC_PLAINTEXT, IDC_TIMESTAMP); |
| 754 |
|
DisableDlgItem(Dialog, IDC_TIMESTAMPTYPE, IDC_TIMESTAMPTYPE); |
| 755 |
|
EnableWindow(GetDlgItem(Dialog, IDC_TEXTCODING_DROPDOWN), FALSE); |
| 756 |
|
break; |
| 757 |
|
case IDC_FOPTTEXT: |
| 758 |
|
EnableWindow(GetDlgItem(Dialog, IDC_TEXTCODING_DROPDOWN), TRUE); |
| 759 |
|
EnableDlgItem(Dialog, IDC_PLAINTEXT, IDC_TIMESTAMP); |
| 760 |
|
// FALLTHROUGH -- BinFlag が off の時は Timestamp 種別の有効/無効を設定する |
| 761 |
|
case IDC_TIMESTAMP: |
| 762 |
|
if (IsDlgButtonChecked(Dialog, IDC_TIMESTAMP) == BST_CHECKED) { |
| 763 |
|
EnableDlgItem(Dialog, IDC_TIMESTAMPTYPE, IDC_TIMESTAMPTYPE); |
| 764 |
} |
} |
| 765 |
else { |
else { |
| 766 |
ts.LogTimestampType = TIMESTAMP_ELAPSED_LOGSTART; |
DisableDlgItem(Dialog, IDC_TIMESTAMPTYPE, IDC_TIMESTAMPTYPE); |
| 767 |
} |
} |
| 768 |
} |
break; |
| 769 |
else { |
case IDC_FOPT_FILENAME_EDIT: |
| 770 |
// 日時形式 |
if (HIWORD(wParam) == EN_CHANGE){ |
| 771 |
if (Option & LOGDLG_UTC) { |
char filename[MAX_PATH]; |
| 772 |
ts.LogTimestampType = TIMESTAMP_UTC; |
GetDlgItemTextA(Dialog, IDC_FOPT_FILENAME_EDIT, filename, _countof(filename)); |
| 773 |
} |
CheckLogFile(Dialog, filename); |
|
else { |
|
|
ts.LogTimestampType = TIMESTAMP_LOCAL; |
|
| 774 |
} |
} |
| 775 |
|
break; |
| 776 |
} |
} |
| 777 |
|
break; |
| 778 |
|
case WM_DROPFILES: { |
| 779 |
|
// 複数ドロップされても最初の1つだけを扱う |
| 780 |
|
HDROP hDrop = (HDROP)wParam; |
| 781 |
|
const UINT len = _DragQueryFileW(hDrop, 0, NULL, 0); |
| 782 |
|
if (len == 0) { |
| 783 |
|
DragFinish(hDrop); |
| 784 |
|
return TRUE; |
| 785 |
|
} |
| 786 |
|
wchar_t *filename = (wchar_t *)malloc(sizeof(wchar_t) * (len + 1)); |
| 787 |
|
_DragQueryFileW(hDrop, 0, filename, len + 1); |
| 788 |
|
filename[len] = '\0'; |
| 789 |
|
_SetDlgItemTextW(Dialog, IDC_FOPT_FILENAME_EDIT, filename); |
| 790 |
|
SendDlgItemMessage(Dialog, IDC_FOPT_FILENAME_EDIT, EM_SETSEL, len, len); |
| 791 |
|
free(filename); |
| 792 |
|
DragFinish(hDrop); |
| 793 |
|
return TRUE; |
| 794 |
} |
} |
| 795 |
else { |
} |
| 796 |
// LogVar->DirLen = 0 だとここに来る |
return FALSE; |
| 797 |
// フルパス・相対パスともに LogVar->FullName に入れておく必要がある |
} |
|
char FileName[MAX_PATH]; |
|
| 798 |
|
|
| 799 |
// フルパス化 |
static BOOL LogStart() |
| 800 |
strncpy_s(FileName, sizeof(FileName), LogVar->FullName, _TRUNCATE); |
{ |
| 801 |
ConvFName(logdir, FileName, sizeof(FileName), "", LogVar->FullName, sizeof(LogVar->FullName)); |
unsigned tid; |
| 802 |
|
|
| 803 |
ParseStrftimeFileName(LogVar->FullName, sizeof(LogVar->FullName)); |
if ((FileLog) || (BinLog)) return FALSE; |
|
ConvertLogname(LogVar->FullName, sizeof(LogVar->FullName)); |
|
| 804 |
|
|
| 805 |
(*SetFileVar)(LogVar); |
assert(LogVar != NULL); |
| 806 |
|
|
| 807 |
FixLogOption(); |
if (strlen(&(LogVar->FullName[LogVar->DirLen]))==0) { |
| 808 |
|
// ファイル名が設定されていない |
| 809 |
|
return FALSE; |
| 810 |
} |
} |
| 811 |
|
|
| 812 |
|
if (! LoadTTFILE()) return FALSE; |
| 813 |
|
|
| 814 |
|
LogVar->OpId = OpLog; |
| 815 |
|
(*SetFileVar)(LogVar); |
| 816 |
|
FixLogOption(); |
| 817 |
|
|
| 818 |
if (ts.LogBinary > 0) |
if (ts.LogBinary > 0) |
| 819 |
{ |
{ |
| 820 |
BinLog = TRUE; |
BinLog = TRUE; |
| 892 |
// 最初のファイルが設定したサイズでローテートしない問題の修正。 |
// 最初のファイルが設定したサイズでローテートしない問題の修正。 |
| 893 |
// (2016.4.9 yutaka) |
// (2016.4.9 yutaka) |
| 894 |
if (LogVar->RotateMode != ROTATE_NONE) { |
if (LogVar->RotateMode != ROTATE_NONE) { |
| 895 |
size = GetFileSize(LogVar->FileHandle, NULL); |
DWORD size = GetFileSize(LogVar->FileHandle, NULL); |
| 896 |
if (size != -1) |
if (size != -1) |
| 897 |
LogVar->ByteCount = size; |
LogVar->ByteCount = size; |
| 898 |
} |
} |
| 923 |
// ログ採取を開始する。 |
// ログ採取を開始する。 |
| 924 |
// (2013.9.29 yutaka) |
// (2013.9.29 yutaka) |
| 925 |
if (ts.LogAllBuffIncludedInFirst) { |
if (ts.LogAllBuffIncludedInFirst) { |
| 926 |
|
DWORD ofs, size, written_size; |
| 927 |
|
char buf[512]; |
| 928 |
|
const char *crlf = "\r\n"; |
| 929 |
|
DWORD crlf_len = 2; |
| 930 |
for (ofs = 0 ; ; ofs++ ) { |
for (ofs = 0 ; ; ofs++ ) { |
| 931 |
// 1つの行を取得する。文字だけなので、エスケープシーケンスは含まれない。 |
// 1つの行を取得する。文字だけなので、エスケープシーケンスは含まれない。 |
| 932 |
size = BuffGetAnyLineData(ofs, buf, sizeof(buf)); |
size = BuffGetAnyLineData(ofs, buf, sizeof(buf)); |
| 1026 |
} |
} |
| 1027 |
|
|
| 1028 |
// コメントをログへ追加する |
// コメントをログへ追加する |
| 1029 |
void CommentLogToFile(char *buf, int size) |
static void CommentLogToFile(char *buf, int size) |
| 1030 |
{ |
{ |
| 1031 |
DWORD wrote; |
DWORD wrote; |
| 1032 |
|
|
| 1675 |
case PROTO_QV: |
case PROTO_QV: |
| 1676 |
vsize = sizeof(TQVVar); |
vsize = sizeof(TQVVar); |
| 1677 |
break; |
break; |
| 1678 |
|
default: |
| 1679 |
|
vsize = 0; |
| 1680 |
|
assert(FALSE); |
| 1681 |
|
break; |
| 1682 |
} |
} |
| 1683 |
ProtoVar = (PCHAR)malloc(vsize); |
ProtoVar = (PCHAR)malloc(vsize); |
| 1684 |
if (ProtoVar==NULL) |
if (ProtoVar==NULL) |
| 2120 |
if (! OpenProtoDlg(FileVar,PROTO_QV,mode,0,0)) |
if (! OpenProtoDlg(FileVar,PROTO_QV,mode,0,0)) |
| 2121 |
ProtoEnd(); |
ProtoEnd(); |
| 2122 |
} |
} |
| 2123 |
|
|
| 2124 |
|
/** |
| 2125 |
|
* ログローテートの設定 |
| 2126 |
|
* ログのサイズが<size>バイトを超えていれば、ローテーションするよう設定する |
| 2127 |
|
*/ |
| 2128 |
|
void LogRotateSize(size_t size) |
| 2129 |
|
{ |
| 2130 |
|
if (LogVar == NULL) { |
| 2131 |
|
return; |
| 2132 |
|
} |
| 2133 |
|
LogVar->RotateMode = ROTATE_SIZE; |
| 2134 |
|
LogVar->RotateSize = size; |
| 2135 |
|
} |
| 2136 |
|
|
| 2137 |
|
/** |
| 2138 |
|
* ログローテートの設定 |
| 2139 |
|
* ログファイルの世代を設定する |
| 2140 |
|
*/ |
| 2141 |
|
void LogRotateRotate(int step) |
| 2142 |
|
{ |
| 2143 |
|
if (LogVar == NULL) { |
| 2144 |
|
return; |
| 2145 |
|
} |
| 2146 |
|
LogVar->RotateStep = step; |
| 2147 |
|
} |
| 2148 |
|
|
| 2149 |
|
/** |
| 2150 |
|
* ログローテートの設定 |
| 2151 |
|
* ローテーションを停止 |
| 2152 |
|
*/ |
| 2153 |
|
void LogRotateHalt(void) |
| 2154 |
|
{ |
| 2155 |
|
if (LogVar == NULL) { |
| 2156 |
|
return; |
| 2157 |
|
} |
| 2158 |
|
LogVar->RotateMode = ROTATE_NONE; |
| 2159 |
|
LogVar->RotateSize = 0; |
| 2160 |
|
LogVar->RotateStep = 0; |
| 2161 |
|
} |
| 2162 |
|
|
| 2163 |
|
static INT_PTR CALLBACK OnCommentDlgProc(HWND hDlgWnd, UINT msg, WPARAM wp, LPARAM lp) |
| 2164 |
|
{ |
| 2165 |
|
static const DlgTextInfo TextInfos[] = { |
| 2166 |
|
{ 0, "DLG_COMMENT_TITLE" }, |
| 2167 |
|
{ IDOK, "BTN_OK" } |
| 2168 |
|
}; |
| 2169 |
|
char buf[256]; |
| 2170 |
|
UINT ret; |
| 2171 |
|
|
| 2172 |
|
switch (msg) { |
| 2173 |
|
case WM_INITDIALOG: |
| 2174 |
|
//SetDlgItemText(hDlgWnd, IDC_EDIT_COMMENT, "サンプル"); |
| 2175 |
|
// エディットコントロールにフォーカスをあてる |
| 2176 |
|
SetFocus(GetDlgItem(hDlgWnd, IDC_EDIT_COMMENT)); |
| 2177 |
|
SetDlgTexts(hDlgWnd, TextInfos, _countof(TextInfos), ts.UILanguageFile); |
| 2178 |
|
return FALSE; |
| 2179 |
|
|
| 2180 |
|
case WM_COMMAND: |
| 2181 |
|
switch (LOWORD(wp)) { |
| 2182 |
|
case IDOK: |
| 2183 |
|
memset(buf, 0, sizeof(buf)); |
| 2184 |
|
ret = GetDlgItemTextA(hDlgWnd, IDC_EDIT_COMMENT, buf, sizeof(buf) - 1); |
| 2185 |
|
if (ret > 0) { // テキスト取得成功 |
| 2186 |
|
//buf[sizeof(buf) - 1] = '\0'; // null-terminate |
| 2187 |
|
CommentLogToFile(buf, ret); |
| 2188 |
|
} |
| 2189 |
|
TTEndDialog(hDlgWnd, IDOK); |
| 2190 |
|
break; |
| 2191 |
|
default: |
| 2192 |
|
return FALSE; |
| 2193 |
|
} |
| 2194 |
|
break; |
| 2195 |
|
case WM_CLOSE: |
| 2196 |
|
TTEndDialog(hDlgWnd, 0); |
| 2197 |
|
return TRUE; |
| 2198 |
|
|
| 2199 |
|
default: |
| 2200 |
|
return FALSE; |
| 2201 |
|
} |
| 2202 |
|
return TRUE; |
| 2203 |
|
} |
| 2204 |
|
|
| 2205 |
|
void LogAddCommentDlg(HINSTANCE hInst, HWND hWnd) |
| 2206 |
|
{ |
| 2207 |
|
// ログファイルへコメントを追加する (2004.8.6 yutaka) |
| 2208 |
|
TTDialogBox(hInst, MAKEINTRESOURCE(IDD_COMMENT_DIALOG), |
| 2209 |
|
HVTWin, OnCommentDlgProc); |
| 2210 |
|
} |
| 2211 |
|
|
| 2212 |
|
void LogClose() |
| 2213 |
|
{ |
| 2214 |
|
if (LogVar != NULL) |
| 2215 |
|
FileTransEnd(OpLog); |
| 2216 |
|
} |
| 2217 |
|
|
| 2218 |
|
BOOL LogOpen(const char *fname) |
| 2219 |
|
{ |
| 2220 |
|
BOOL ret; |
| 2221 |
|
|
| 2222 |
|
if ((LogVar==NULL) && !NewFileVar(&LogVar)) { |
| 2223 |
|
return FALSE; |
| 2224 |
|
} |
| 2225 |
|
|
| 2226 |
|
LogVar->DirLen = 0; |
| 2227 |
|
LogVar->NoMsg = TRUE; |
| 2228 |
|
strncpy_s(LogVar->FullName, sizeof(LogVar->FullName), fname, _TRUNCATE); |
| 2229 |
|
ret = LogStart(); |
| 2230 |
|
return ret; |
| 2231 |
|
} |
| 2232 |
|
|
| 2233 |
|
BOOL LogIsOpend() |
| 2234 |
|
{ |
| 2235 |
|
// LogVar->FileOpen |
| 2236 |
|
return LogVar != NULL; |
| 2237 |
|
} |
| 2238 |
|
|
| 2239 |
|
void LogWriteStr(const char *str) |
| 2240 |
|
{ |
| 2241 |
|
if (LogVar != NULL) |
| 2242 |
|
{ |
| 2243 |
|
DWORD wrote; |
| 2244 |
|
size_t len = strlen(str); |
| 2245 |
|
WriteFile(LogVar->FileHandle, str, len, &wrote, NULL); |
| 2246 |
|
LogVar->ByteCount = |
| 2247 |
|
LogVar->ByteCount + len; |
| 2248 |
|
FLogRefreshNum(); |
| 2249 |
|
} |
| 2250 |
|
} |
| 2251 |
|
|
| 2252 |
|
void LogInfo(char *param_ptr, size_t param_len) |
| 2253 |
|
{ |
| 2254 |
|
if (LogVar) { |
| 2255 |
|
param_ptr[0] = '0' |
| 2256 |
|
+ (ts.LogBinary != 0) |
| 2257 |
|
+ ((ts.Append != 0) << 1) |
| 2258 |
|
+ ((ts.LogTypePlainText != 0) << 2) |
| 2259 |
|
+ ((ts.LogTimestamp != 0) << 3) |
| 2260 |
|
+ ((ts.LogHideDialog != 0) << 4); |
| 2261 |
|
strncpy_s(param_ptr + 1, param_len - 1, LogVar->FullName, _TRUNCATE); |
| 2262 |
|
} |
| 2263 |
|
else { |
| 2264 |
|
param_ptr[0] = '0' - 1; |
| 2265 |
|
param_ptr[1] = 0; |
| 2266 |
|
} |
| 2267 |
|
} |
| 2268 |
|
|
| 2269 |
|
/** |
| 2270 |
|
* 現在のログファイル名を取得 |
| 2271 |
|
*/ |
| 2272 |
|
const char *LogGetFilename() |
| 2273 |
|
{ |
| 2274 |
|
if (LogVar == NULL) { |
| 2275 |
|
return NULL; |
| 2276 |
|
} |
| 2277 |
|
return LogVar->FullName; |
| 2278 |
|
} |
| 2279 |
|
|
| 2280 |
|
/** |
| 2281 |
|
* ログダイアログを開く |
| 2282 |
|
* @retval TRUE [ok] が押された |
| 2283 |
|
* @retval FALSE キャンセルされた |
| 2284 |
|
* @param[in,out] filename OK時、ファイル名、不要になったらfree()すること |
| 2285 |
|
*/ |
| 2286 |
|
BOOL LogOpenDialog(char **filename) |
| 2287 |
|
{ |
| 2288 |
|
LogDlgData_t *data = (LogDlgData_t *)calloc(sizeof(LogDlgData_t), 1); |
| 2289 |
|
data->filename = LogGetLogFilename(NULL); |
| 2290 |
|
INT_PTR ret = TTDialogBoxParam( |
| 2291 |
|
hInst, MAKEINTRESOURCE(IDD_LOGDLG), |
| 2292 |
|
HVTWin, LogFnHook, (LPARAM)data); |
| 2293 |
|
if (ret == IDOK) { |
| 2294 |
|
*filename = data->filename; |
| 2295 |
|
} |
| 2296 |
|
free(data); |
| 2297 |
|
return ret == IDOK ? TRUE : FALSE; |
| 2298 |
|
} |
| 2299 |
|
|
| 2300 |
|
/** |
| 2301 |
|
* ログファイル名を取得 |
| 2302 |
|
* ログファイル名用の修飾を行う |
| 2303 |
|
* - strftime() と同じ日付展開 |
| 2304 |
|
* - 設定されたログファイルフォルダを追加 |
| 2305 |
|
* - ホスト名,ポート番号展開 |
| 2306 |
|
* |
| 2307 |
|
* @param[in] log_filename ファイル名(相対/絶対どちらでもok) |
| 2308 |
|
* NULLの場合デフォルトファイル名となる |
| 2309 |
|
* strftime形式ok |
| 2310 |
|
* @return フルパスファイル名 |
| 2311 |
|
* 不要になったら free() すること |
| 2312 |
|
*/ |
| 2313 |
|
char *LogGetLogFilename(const char *log_filename) |
| 2314 |
|
{ |
| 2315 |
|
// フォルダ |
| 2316 |
|
char FileDirExpanded[MAX_PATH]; |
| 2317 |
|
char *logdir; |
| 2318 |
|
if (strlen(ts.LogDefaultPath) > 0) { |
| 2319 |
|
logdir = ts.LogDefaultPath; |
| 2320 |
|
} |
| 2321 |
|
else if (strlen(ts.FileDir) > 0) { |
| 2322 |
|
ExpandEnvironmentStrings(ts.FileDir, FileDirExpanded, sizeof(FileDirExpanded)); |
| 2323 |
|
logdir = FileDirExpanded; |
| 2324 |
|
} |
| 2325 |
|
else { |
| 2326 |
|
logdir = ts.HomeDir; |
| 2327 |
|
} |
| 2328 |
|
|
| 2329 |
|
// 元となるファイル名 |
| 2330 |
|
char base_name[MAX_PATH]; |
| 2331 |
|
if (log_filename == NULL) { |
| 2332 |
|
strncpy_s(base_name, _countof(base_name), ts.LogDefaultName, _TRUNCATE); |
| 2333 |
|
} |
| 2334 |
|
else { |
| 2335 |
|
strncpy_s(base_name, _countof(base_name), log_filename, _TRUNCATE); |
| 2336 |
|
} |
| 2337 |
|
|
| 2338 |
|
// フルパス化 |
| 2339 |
|
char full_path[MAX_PATH]; |
| 2340 |
|
ConvFName(logdir, base_name, sizeof(base_name), "", full_path, sizeof(full_path)); |
| 2341 |
|
ParseStrftimeFileName(full_path, sizeof(full_path)); |
| 2342 |
|
ConvertLogname(full_path, sizeof(full_path)); |
| 2343 |
|
|
| 2344 |
|
return _strdup(full_path); |
| 2345 |
|
} |