diff --git a/GUI.cpp b/GUI.cpp index 9f3739e..28227cc 100644 --- a/GUI.cpp +++ b/GUI.cpp @@ -43,6 +43,7 @@ #include "XG_BoxWindow.hpp" #include "XG_CanvasWindow.hpp" #include "XG_UILanguageDialog.hpp" +#include "XG_PatEditDialog.hpp" #undef HANDLE_WM_MOUSEWHEEL // might be wrong #define HANDLE_WM_MOUSEWHEEL(hwnd, wParam, lParam, fn) \ @@ -5658,6 +5659,117 @@ void __fastcall XgGoNextPane(HWND hwnd, BOOL bNext) } } +// パターンを現在の盤面から取得。 +XG_PATDATA XgGetCurrentPat(void) +{ + // コピーする盤を選ぶ。 + XG_Board *pxw = (xg_bSolved && xg_bShowAnswer) ? &xg_solution : &xg_xword; + + // クロスワードの文字列を取得する。 + std::wstring text; + pxw->GetString(text); + + for (auto& ch : text){ + switch (ch) + { + case ZEN_SPACE: + case ZEN_BLACK: + case '\n': + case '\r': + case 0x250F: // ┏ + case 0x2501: // ━ + case 0x2513: // ┓ + case 0x2503: // ┃ + case 0x2517: // ┗ + case 0x251B: // ┛ + break; + default: + ch = ZEN_SPACE; + break; + } + } + + XG_PATDATA pat = { xg_nCols, xg_nRows, text }; + + XgGetPatternData(pat); + return pat; +} + +// パターン編集。 +BOOL XgPatEdit(HWND hwnd, BOOL bAdd) +{ + // パターンを読み込む。 + patterns_t patterns; + if (!XgLoadPatterns(L"PAT.txt", patterns)) + return FALSE; + + // ソートして一意化する。 + XgSortAndUniquePatterns(patterns); + + // 現在の盤面のパターンを取得。 + XG_PATDATA cur_pat = XgGetCurrentPat(); + + // 分断禁。 + if (XgIsPatternDividedByBlocks(cur_pat)) + return FALSE; + + // 反転・転置した盤面も考慮。 + auto transposed = XgTransposePattern(cur_pat); + auto flip_h = XgFlipPatternH(cur_pat); + auto flip_v = XgFlipPatternV(cur_pat); + auto flip_hv = XgFlipPatternH(flip_v); + + if (bAdd) { // 追加。 + patterns.push_back(cur_pat); + patterns.push_back(transposed); + patterns.push_back(flip_h); + patterns.push_back(flip_v); + patterns.push_back(flip_hv); + } else { // 削除。 + patterns_t temp_pats; // 一時的なパターン + for (const auto& pat : patterns) { + if (pat.text == cur_pat.text || + pat.text == transposed.text || + pat.text == flip_h.text || + pat.text == flip_v.text || + pat.text == flip_hv.text) + { + continue; + } + temp_pats.push_back(pat); + } + patterns = std::move(temp_pats); + } + + // 反転・転置を考慮して一意化する。 + patterns_t temp_pats; // 一時的なパターン + for (const auto& pat : patterns) { + if (XgIsPatternDividedByBlocks(pat)) + continue; + auto transposed = XgTransposePattern(pat); + auto flip_h = XgFlipPatternH(pat); + auto flip_v = XgFlipPatternV(pat); + auto flip_hv = XgFlipPatternH(flip_v); + temp_pats.erase( + std::remove_if(temp_pats.begin(), temp_pats.end(), [&](const XG_PATDATA& pat2) noexcept { + return transposed.text == pat2.text || + flip_h.text == pat2.text || + flip_v.text == pat2.text || + flip_hv.text == pat2.text; + }), + temp_pats.end() + ); + temp_pats.push_back(pat); + } + patterns = std::move(temp_pats); + + // ソートして一意化する。 + XgSortAndUniquePatterns(patterns); + + // パターンを書き込む。 + return XgSavePatterns(L"PAT2.txt", patterns); +} + // コマンドを実行する。 void __fastcall MainWnd_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT /*codeNotify*/) { @@ -6959,13 +7071,23 @@ void __fastcall MainWnd_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT /*codeNo // THEME.txtを開く。 XgOpenLocalFile(hwnd, L"THEME.txt"); break; - case ID_CLEARUNDOBUFFER: - // Undoバッファをクリアする。 - xg_ubUndoBuffer.clear(); - // 音を鳴らす。 - Beep(0x1000, 50); - Beep(0x800, 450); - bUpdateImage = TRUE; + case ID_PATEDIT: + { + // パターン編集。 + XG_PatEditDialog dialog; + if (dialog.DoModal(hwnd) != IDOK) + break; + + if (XgPatEdit(hwnd, dialog.s_bAdd)) { + // 成功メッセージ。 + XgCenterMessageBoxW(hwnd, XgLoadStringDx1(IDS_WROTEPAT), + XgLoadStringDx2(IDS_APPNAME), MB_ICONINFORMATION); + } else { + // 失敗メッセージ。 + XgCenterMessageBoxW(hwnd, XgLoadStringDx1(IDS_CANTWRITEPAT), + nullptr, MB_ICONERROR); + } + } break; case ID_DOWNLOADDICT: ShellExecuteW(hwnd, nullptr, L"https://katahiromz.web.fc2.com/xword/dict", nullptr, nullptr, SW_SHOWNORMAL); diff --git a/HISTORY.txt b/HISTORY.txt index 2b9c6ef..e8c3a38 100644 --- a/HISTORY.txt +++ b/HISTORY.txt @@ -267,6 +267,7 @@ - Supported TIFF images. - Improved Input Palette. - 2024-XX-YY ver.5.1.7 + - Added trick "Ctrl+Alt+Shift+Q". # 開発履歴 (Japanese) @@ -849,3 +850,4 @@ - TIFF画像のサポート。 - 入力パレットの改良。 - 2024年XX月YY日 ver.5.1.7 + - 裏技「Ctrl+Alt+Shift+Q」を追加。 diff --git a/PAT.txt b/PAT.txt index 6dc0e06..5f98525 100644 --- a/PAT.txt +++ b/PAT.txt @@ -17356,6 +17356,22 @@ ┃ ■ ■  ■    ■ ┃ ┗━━━━━━━━━━━━━┛ +┏━━━━━━━━━━━━━┓ +┃ ■ ■   ■   ■ ┃ +┃    ■   ■ ■  ┃ +┃■ ■   ■      ┃ +┃   ■    ■ ■ ■┃ +┃ ■   ■ ■     ┃ +┃  ■      ■ ■ ┃ +┃■   ■ ■ ■   ■┃ +┃ ■ ■      ■  ┃ +┃     ■ ■   ■ ┃ +┃■ ■ ■    ■   ┃ +┃      ■   ■ ■┃ +┃  ■ ■   ■    ┃ +┃ ■   ■   ■ ■ ┃ +┗━━━━━━━━━━━━━┛ + ┏━━━━━━━━━━━━━┓ ┃ ■ ■     ■ ■ ┃ ┃     ■ ■     ┃ @@ -17404,22 +17420,6 @@ ┃ ■   ■ ■ ■   ┃ ┗━━━━━━━━━━━━━┛ -┏━━━━━━━━━━━━━┓ -┃ ■   ■   ■ ■ ┃ -┃  ■ ■   ■    ┃ -┃      ■   ■ ■┃ -┃■ ■ ■  ■ ■   ┃ -┃     ■     ■ ┃ -┃ ■ ■      ■  ┃ -┃■   ■ ■ ■   ■┃ -┃  ■      ■ ■ ┃ -┃ ■     ■     ┃ -┃   ■ ■  ■ ■ ■┃ -┃■ ■   ■      ┃ -┃    ■   ■ ■  ┃ -┃ ■ ■   ■   ■ ┃ -┗━━━━━━━━━━━━━┛ - ┏━━━━━━━━━━━━━┓ ┃ ■   ■     ■ ┃ ┃    ■   ■    ┃ diff --git a/XG_PatEditDialog.hpp b/XG_PatEditDialog.hpp new file mode 100644 index 0000000..18cdcba --- /dev/null +++ b/XG_PatEditDialog.hpp @@ -0,0 +1,96 @@ +#pragma once + +#include "XG_Window.hpp" + +// 「パターン編集」ダイアログ。 +class XG_PatEditDialog : public XG_Dialog +{ +public: + static inline BOOL s_bAdd = TRUE; + static inline HBITMAP s_hbm = NULL; + + XG_PatEditDialog() noexcept + { + } + + // [パターン編集]ダイアログの初期化。 + BOOL OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam) + { + XgCenterDialog(hwnd); + + HWND hCmb1 = ::GetDlgItem(hwnd, cmb1); + ComboBox_AddString(hCmb1, XgLoadStringDx1(IDS_ADD)); + ComboBox_AddString(hCmb1, XgLoadStringDx1(IDS_DELETE)); + + if (s_bAdd) + ComboBox_SetCurSel(hCmb1, 0); + else + ComboBox_SetCurSel(hCmb1, 1); + + OnCmb1(hwnd); + + return TRUE; + } + + void OnCmb1(HWND hwnd) + { + HWND hCmb1 = ::GetDlgItem(hwnd, cmb1); + INT iItem = ComboBox_GetCurSel(hCmb1); + + HBITMAP hbm = NULL; + switch (iItem) + { + case 0: + hbm = ::LoadBitmapW(xg_hInstance, MAKEINTRESOURCEW(IDB_ADDPAT)); + break; + case 1: + hbm = ::LoadBitmapW(xg_hInstance, MAKEINTRESOURCEW(IDB_DELETEPAT)); + break; + default: + break; + } + + ::DeleteObject(s_hbm); + s_hbm = hbm; + SendDlgItemMessageW(m_hWnd, stc1, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)s_hbm); + } + + void OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify) + { + switch (id) + { + case IDOK: + case IDCANCEL: + { + HWND hCmb1 = ::GetDlgItem(hwnd, cmb1); + INT iItem = ComboBox_GetCurSel(hCmb1); + s_bAdd = (iItem == 0); + ::DeleteObject(s_hbm); + s_hbm = NULL; + ::EndDialog(hwnd, id); + } + break; + case cmb1: + OnCmb1(hwnd); + break; + } + } + + INT_PTR CALLBACK + DialogProcDx(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) override + { + switch (uMsg) + { + HANDLE_MSG(hwnd, WM_INITDIALOG, OnInitDialog); + HANDLE_MSG(hwnd, WM_COMMAND, OnCommand); + default: + break; + } + return 0; + } + + INT_PTR DoModal(HWND hwnd) + { + return DialogBoxDx(hwnd, IDD_ADDDELETEPAT); + } +}; diff --git a/XWordGiver.hpp b/XWordGiver.hpp index 0e922a3..d4a6441 100644 --- a/XWordGiver.hpp +++ b/XWordGiver.hpp @@ -1495,6 +1495,10 @@ XG_PATDATA XgFlipPatternV(const XG_PATDATA& pat); VOID XgSortAndUniquePatterns(patterns_t& patterns); // パターンが黒マスルールに適合するか? BOOL __fastcall XgPatternRuleIsOK(const XG_PATDATA& pat); +// パターンのデータを扱いやすいよう、加工する。 +void XgGetPatternData(XG_PATDATA& pat); +// パターンデータを書き込む。 +BOOL XgSavePatterns(LPCWSTR pszFileName, const patterns_t& patterns); ////////////////////////////////////////////////////////////////////////////// // ボックス。 diff --git a/XWordGiver_res.rc b/XWordGiver_res.rc index 63038a7..58e98b8 100644 --- a/XWordGiver_res.rc +++ b/XWordGiver_res.rc @@ -1,5 +1,5 @@ // XWordGiver_res.rc -// This file is automatically generated by RisohEditor 5.7.7. +// This file is automatically generated by RisohEditor 5.7.9. // † <-- This dagger helps UTF-8 detection. #include "resource.h" @@ -82,7 +82,7 @@ IDB_FROMWORDS BITMAP "res/Bitmap_100.bmp" VK_LEFT, ID_ONLINEDICTH, ALT, VIRTKEY VK_RIGHT, ID_ONLINEDICTH, ALT, VIRTKEY VK_RETURN, ID_HEADERANDNOTES, CONTROL, VIRTKEY - "Q", ID_CLEARUNDOBUFFER, ALT, CONTROL, SHIFT, VIRTKEY + "Q", ID_PATEDIT, ALT, CONTROL, SHIFT, VIRTKEY } ////////////////////////////////////////////////////////////////////////////// diff --git a/lang/en_US.rc b/lang/en_US.rc index 557f816..5181a92 100644 --- a/lang/en_US.rc +++ b/lang/en_US.rc @@ -1,10 +1,17 @@ -// This file is automatically generated by RisohEditor 5.7.7. +// This file is automatically generated by RisohEditor 5.7.9. // † <-- This dagger helps UTF-8 detection. #pragma code_page(65001) // UTF-8 LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT +////////////////////////////////////////////////////////////////////////////// +// RT_BITMAP + +IDB_ADDPAT BITMAP "res/1033_Bitmap_101.bmp" + +IDB_DELETEPAT BITMAP "res/1033_Bitmap_102.bmp" + ////////////////////////////////////////////////////////////////////////////// // RT_MENU @@ -1506,6 +1513,18 @@ FONT 9, "Tahoma" PUSHBUTTON "&Clear double-frame", psh5, 5, 185, 80, 17 } +IDD_ADDDELETEPAT DIALOG 0, 0, 325, 240 +CAPTION "Pattern Edit" +STYLE DS_CENTER | DS_MODALFRAME | WS_POPUPWINDOW | WS_CAPTION +FONT 9, "Tahoma" +{ + RTEXT "&Operation:", -1, 10, 10, 55, 10, SS_CENTERIMAGE | NOT WS_GROUP + COMBOBOX cmb1, 75, 10, 75, 300, CBS_HASSTRINGS | CBS_AUTOHSCROLL | CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + CONTROL "", stc1, "STATIC", SS_CENTERIMAGE | SS_BITMAP | WS_GROUP, 10, 30, 305, 185 + DEFPUSHBUTTON "OK", IDOK, 190, 220, 60, 15 + PUSHBUTTON "Cancel", IDCANCEL, 255, 220, 60, 15 +} + ////////////////////////////////////////////////////////////////////////////// // RT_VERSION @@ -1722,7 +1741,11 @@ STRINGTABLE IDS_POLICYPRESET_JPN_LOOSE_3, "0x011B: Japanese publisher policy (Loose): Horizontal symmetry" IDS_MARKINGTYPE, "Error: There is a missing character '%c' on the board." IDS_MARKINGEMPTY, "Enter a word or choose from the suggestions below:" + IDS_ADD, "Add" + IDS_DELETE, "Delete" IDS_TT_NEW, "New crossword" + IDS_CANTWRITEPAT, "Failed to write PAT2.txt. Sorry." + IDS_WROTEPAT, "Success! PAT2.txt has been written." IDS_TT_GENERATE, "Generate crossword" IDS_TT_OPEN, "Open crossword" IDS_TT_SAVEAS, "Save crossword" diff --git a/lang/ja_JP.rc b/lang/ja_JP.rc index 1f076f9..f96e33d 100644 --- a/lang/ja_JP.rc +++ b/lang/ja_JP.rc @@ -1,10 +1,17 @@ -// This file is automatically generated by RisohEditor 5.7.7. +// This file is automatically generated by RisohEditor 5.7.9. // † <-- This dagger helps UTF-8 detection. #pragma code_page(65001) // UTF-8 LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT +////////////////////////////////////////////////////////////////////////////// +// RT_BITMAP + +IDB_ADDPAT BITMAP "res/1041_Bitmap_101.bmp" + +IDB_DELETEPAT BITMAP "res/1041_Bitmap_102.bmp" + ////////////////////////////////////////////////////////////////////////////// // RT_MENU @@ -1509,6 +1516,18 @@ FONT 9, "MS UI Gothic" PUSHBUTTON "二重マス単語をクリア(&C)", psh5, 5, 185, 80, 17 } +IDD_ADDDELETEPAT DIALOG 0, 0, 325, 240 +CAPTION "パターン編集" +STYLE DS_CENTER | DS_MODALFRAME | WS_POPUPWINDOW | WS_CAPTION +FONT 9, "MS UI Gothic" +{ + RTEXT "処理(&O):", -1, 10, 10, 55, 10, SS_CENTERIMAGE | NOT WS_GROUP + COMBOBOX cmb1, 75, 10, 75, 300, CBS_HASSTRINGS | CBS_AUTOHSCROLL | CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + CONTROL "", stc1, "STATIC", SS_CENTERIMAGE | SS_BITMAP | WS_GROUP, 10, 30, 305, 185 + DEFPUSHBUTTON "OK", IDOK, 190, 220, 60, 15 + PUSHBUTTON "キャンセル", IDCANCEL, 255, 220, 60, 15 +} + ////////////////////////////////////////////////////////////////////////////// // RT_VERSION @@ -1725,6 +1744,10 @@ STRINGTABLE IDS_POLICYPRESET_JPN_LOOSE_3, "0x011B: 日本の出版社ルール (ゆるい): 左右対称" IDS_MARKINGTYPE, "エラー: 盤面に足りない文字「%c」があります。" IDS_MARKINGEMPTY, "単語を入力、または下の候補から選択して下さい:" + IDS_ADD, "追加" + IDS_DELETE, "削除" + IDS_CANTWRITEPAT, "失敗。PAT2.txtの書き込みに失敗しました。書き込めないフォルダの可能性があります。" + IDS_WROTEPAT, "PAT2.txt の書き込みに成功しました。" IDS_TT_NEW, "新規作成" IDS_TT_GENERATE, "問題を自動生成する" IDS_TT_OPEN, "問題を開く" diff --git a/res/1033_Bitmap_101.bmp b/res/1033_Bitmap_101.bmp new file mode 100644 index 0000000..2df5431 Binary files /dev/null and b/res/1033_Bitmap_101.bmp differ diff --git a/res/1033_Bitmap_102.bmp b/res/1033_Bitmap_102.bmp new file mode 100644 index 0000000..1af8e00 Binary files /dev/null and b/res/1033_Bitmap_102.bmp differ diff --git a/res/1041_Bitmap_101.bmp b/res/1041_Bitmap_101.bmp new file mode 100644 index 0000000..18cd128 Binary files /dev/null and b/res/1041_Bitmap_101.bmp differ diff --git a/res/1041_Bitmap_102.bmp b/res/1041_Bitmap_102.bmp new file mode 100644 index 0000000..5790d52 Binary files /dev/null and b/res/1041_Bitmap_102.bmp differ diff --git a/resource.h b/resource.h index d1ba9a0..84cc7df 100644 --- a/resource.h +++ b/resource.h @@ -1,9 +1,11 @@ //{{NO_DEPENDENCIES}} // Microsoft Visual C++ Compatible -// This file is automatically generated by RisohEditor 5.7.7. +// This file is automatically generated by RisohEditor 5.7.9. // XWordGiver_res.rc #define IDB_FROMWORDS 100 +#define IDB_ADDPAT 101 +#define IDB_DELETEPAT 102 #define IDC_MYHAND 100 @@ -34,6 +36,7 @@ #define IDD_UILANGID 130 #define IDD_ABOUT 131 #define IDD_MARKING 132 +#define IDD_ADDDELETEPAT 133 #define IDS_VERSION 101 #define IDS_APPNAME 102 @@ -219,6 +222,10 @@ #define IDS_POLICYPRESET_JPN_LOOSE_3 302 #define IDS_MARKINGTYPE 303 #define IDS_MARKINGEMPTY 304 +#define IDS_ADD 305 +#define IDS_DELETE 306 +#define IDS_CANTWRITEPAT 307 +#define IDS_WROTEPAT 308 #define IDS_TT_NEW 10100 #define IDS_TT_GENERATE 10101 #define IDS_TT_OPEN 10102 @@ -476,6 +483,7 @@ #define ID_RECENT_09 599 #define ID_SWAP_LEFT_RIGHT 600 #define ID_SWAP_TOP_BOTTOM 601 +#define ID_PATEDIT 602 #define ID_TT_BASE 10000 #define ctl2 1185