diff --git a/HISTORY.txt b/HISTORY.txt index 5e53db0..3935398 100644 --- a/HISTORY.txt +++ b/HISTORY.txt @@ -320,6 +320,7 @@ - This time, we do exclusive control properly. - Added a function to display the dictionary update date and time. - The "Jump" dialog has been made modeless. + - Added "Jump to letter or word" function. # 開発履歴 (Japanese) @@ -959,3 +960,4 @@ - 今度こそ排他制御をちゃんとする。 - 辞書の更新日時を表示する機能を追加。 - 「ジャンプ」ダイアログをモードレス化した。 + - 「文字または単語にジャンプ」機能を追加。 diff --git a/XG_JumpDialog.hpp b/XG_JumpDialog.hpp index e63ecf4..b808cad 100644 --- a/XG_JumpDialog.hpp +++ b/XG_JumpDialog.hpp @@ -18,33 +18,49 @@ class XG_JumpDialog : public XG_Dialog void UpdateUI(HWND hwnd) { if (!xg_bSolved) { - m_nType = 0; + if (m_nType == 1) + m_nType = 0; } if (m_nType == 0) { EnableWindow(GetDlgItem(hwnd, edt1), TRUE); EnableWindow(GetDlgItem(hwnd, edt2), TRUE); EnableWindow(GetDlgItem(hwnd, edt3), FALSE); + EnableWindow(GetDlgItem(hwnd, edt4), FALSE); EnableWindow(GetDlgItem(hwnd, rad3), FALSE); EnableWindow(GetDlgItem(hwnd, rad4), FALSE); CheckRadioButton(hwnd, rad1, rad2, rad1); SetDlgItemInt(hwnd, edt1, m_jCol, FALSE); SetDlgItemInt(hwnd, edt2, m_iRow, FALSE); - } else { + } else if (m_nType == 1) { EnableWindow(GetDlgItem(hwnd, edt1), FALSE); EnableWindow(GetDlgItem(hwnd, edt2), FALSE); EnableWindow(GetDlgItem(hwnd, edt3), TRUE); + EnableWindow(GetDlgItem(hwnd, edt4), FALSE); EnableWindow(GetDlgItem(hwnd, rad3), TRUE); EnableWindow(GetDlgItem(hwnd, rad4), TRUE); CheckRadioButton(hwnd, rad1, rad2, rad2); SetDlgItemInt(hwnd, edt3, m_nNumber, FALSE); CheckRadioButton(hwnd, rad3, rad4, (m_bVert ? rad4 : rad3)); + } else if (m_nType == 2) { + EnableWindow(GetDlgItem(hwnd, edt1), FALSE); + EnableWindow(GetDlgItem(hwnd, edt2), FALSE); + EnableWindow(GetDlgItem(hwnd, edt3), FALSE); + EnableWindow(GetDlgItem(hwnd, edt4), TRUE); + EnableWindow(GetDlgItem(hwnd, rad3), FALSE); + EnableWindow(GetDlgItem(hwnd, rad4), FALSE); } } BOOL OnOK(HWND hwnd) { - m_nType = (IsDlgButtonChecked(hwnd, rad2) == BST_CHECKED); + if (IsDlgButtonChecked(hwnd, rad2) == BST_CHECKED) + m_nType = 1; + else if (IsDlgButtonChecked(hwnd, rad5) == BST_CHECKED) + m_nType = 2; + else + m_nType = 0; + m_bVert = (IsDlgButtonChecked(hwnd, rad4) == BST_CHECKED); m_jCol = GetDlgItemInt(hwnd, edt1, NULL, FALSE); m_iRow = GetDlgItemInt(hwnd, edt2, NULL, FALSE); @@ -181,6 +197,90 @@ class XG_JumpDialog : public XG_Dialog case 1: // カギ位置。 XgJumpNumber(hwnd, m_nNumber, m_bVert); break; + case 2: // 文字または単語。 + { + // テキストを取得する。 + WCHAR szText[64]; + GetDlgItemText(hwnd, edt4, szText, _countof(szText)); + StrTrimW(szText, XG_WHITE_SPACES); + if (!szText[0]) + return; + + auto str = XgNormalizeString(szText); + XG_Board& xw = (xg_bSolved && xg_bShowAnswer) ? xg_solution : xg_xword; + + // 次に進む関数。 + auto GetNext = [&](INT& jCol, INT& iRow) { + ++jCol; + if (jCol == xg_nCols) { + jCol = 0; + ++iRow; + if (iRow == xg_nRows) { + iRow = 0; + } + } + }; + // ヨコの単語を取得する関数。 + auto GetHorzWord = [&](INT jCol, INT iRow) -> XGStringW { + if (xw.GetAt(iRow, jCol) == ZEN_BLACK) { + return { ZEN_BLACK }; + } + if (jCol == 0 || xw.GetAt(iRow, jCol - 1) == ZEN_BLACK) { + XGStringW ret; + for (INT j = jCol; j < xg_nCols; ++j) { + WCHAR ch = xw.GetAt(iRow, j); + if (ch == ZEN_BLACK) + break; + ret += ch; + } + return ret; + } + return { xw.GetAt(iRow, jCol) }; + }; + // タテの単語を取得する関数。 + auto GetVertWord = [&](INT jCol, INT iRow) -> XGStringW { + if (xw.GetAt(iRow, jCol) == ZEN_BLACK) { + return { ZEN_BLACK }; + } + if (iRow == 0 || xw.GetAt(iRow - 1, jCol) == ZEN_BLACK) { + XGStringW ret; + for (INT i = iRow; i < xg_nRows; ++i) { + WCHAR ch = xw.GetAt(i, jCol); + if (ch == ZEN_BLACK) + break; + ret += ch; + } + return ret; + } + return { xw.GetAt(iRow, jCol) }; + }; + + // 検索する。 + INT j = xg_caret_pos.m_j, i = xg_caret_pos.m_i; + for (INT n = 0; n < xg_nRows * xg_nCols; ++n) { + GetNext(j, i); + auto word0 = GetHorzWord(j, i); + auto j0 = word0.find(str); + if (j0 != word0.npos) { + xg_caret_pos.m_j = j + j0; + xg_caret_pos.m_i = i; + break; + } + auto word1 = GetVertWord(j, i); + auto i0 = word1.find(str); + if (i0 != word1.npos) { + xg_caret_pos.m_j = j; + xg_caret_pos.m_i = i + i0; + break; + } + } + } + // 表示を更新する。 + XgEnsureCaretVisible(hwnd); + XgUpdateStatusBar(hwnd); + // すぐに入力できるようにする。 + SetFocus(hwnd); + break; } } break; @@ -201,6 +301,12 @@ class XG_JumpDialog : public XG_Dialog UpdateUI(hwnd); } break; + case rad5: + if (IsDlgButtonChecked(hwnd, rad5) == BST_CHECKED) { + m_nType = 2; + UpdateUI(hwnd); + } + break; default: break; } diff --git a/lang/en_US.rc b/lang/en_US.rc index d15d804..5fc2eaa 100644 --- a/lang/en_US.rc +++ b/lang/en_US.rc @@ -1469,13 +1469,14 @@ FONT 9, "Tahoma" PUSHBUTTON "&Clear double-frame", psh5, 5, 185, 80, 17 } -IDD_JUMP DIALOG 0, 0, 193, 135 +IDD_JUMP DIALOG 0, 0, 193, 185 CAPTION "Jump" STYLE DS_CENTER | DS_MODALFRAME | WS_POPUPWINDOW | WS_CAPTION FONT 9, "Tahoma" { - AUTORADIOBUTTON "Jump to &position", rad1, 10, 10, 90, 15, WS_GROUP | WS_TABSTOP - AUTORADIOBUTTON "Jump to &clue", rad2, 10, 60, 90, 15, WS_TABSTOP + AUTORADIOBUTTON "Jump to &position", rad1, 10, 10, 110, 15, WS_GROUP | WS_TABSTOP + AUTORADIOBUTTON "Jump to &clue", rad2, 10, 60, 110, 15, WS_TABSTOP + AUTORADIOBUTTON "Jump to letter or &word", rad5, 10, 110, 110, 15, WS_TABSTOP EDITTEXT edt1, 20, 35, 30, 15, ES_NUMBER | ES_AUTOHSCROLL | ES_RIGHT CONTROL "", scr1, "msctls_updown32", UDS_ARROWKEYS | UDS_AUTOBUDDY | UDS_ALIGNRIGHT | UDS_SETBUDDYINT, 40, 35, 10, 20 LTEXT "th from left", -1, 55, 40, 45, 10 @@ -1486,8 +1487,10 @@ FONT 9, "Tahoma" AUTORADIOBUTTON "&Down", rad4, 75, 85, 35, 15, WS_TABSTOP EDITTEXT edt3, 120, 85, 30, 15, ES_NUMBER | ES_AUTOHSCROLL | ES_RIGHT CONTROL "", scr3, "msctls_updown32", UDS_ARROWKEYS | UDS_AUTOBUDDY | UDS_ALIGNRIGHT | UDS_SETBUDDYINT, 100, 25, 10, 20 - DEFPUSHBUTTON "&Jump", IDOK, 65, 115, 60, 15 - PUSHBUTTON "Cancel", IDCANCEL, 130, 115, 60, 15 + LTEXT "Letter or word:", -1, 27, 137, 66, 12 + EDITTEXT edt4, 97, 135, 85, 14, ES_AUTOHSCROLL + DEFPUSHBUTTON "&Jump", IDOK, 65, 165, 60, 15 + PUSHBUTTON "Cancel", IDCANCEL, 130, 165, 60, 15 } IDD_FILESETTINGS DIALOG 0, 0, 270, 245 diff --git a/lang/ja_JP.rc b/lang/ja_JP.rc index af95e9d..2c49a20 100644 --- a/lang/ja_JP.rc +++ b/lang/ja_JP.rc @@ -1472,13 +1472,14 @@ FONT 9, "MS UI Gothic" PUSHBUTTON "二重マス単語をクリア(&C)", psh5, 5, 185, 80, 17 } -IDD_JUMP DIALOG 0, 0, 193, 135 +IDD_JUMP DIALOG 0, 0, 193, 185 CAPTION "ジャンプ" STYLE DS_CENTER | DS_MODALFRAME | WS_POPUPWINDOW | WS_CAPTION FONT 9, "MS UI Gothic" { - AUTORADIOBUTTON "指定位置にジャンプ(&P)", rad1, 10, 10, 90, 15, WS_GROUP | WS_TABSTOP - AUTORADIOBUTTON "カギにジャンプ(&C)", rad2, 10, 60, 90, 15, WS_TABSTOP + AUTORADIOBUTTON "指定位置にジャンプ(&P)", rad1, 10, 10, 110, 15, WS_GROUP | WS_TABSTOP + AUTORADIOBUTTON "カギにジャンプ(&C)", rad2, 10, 60, 110, 15, WS_TABSTOP + AUTORADIOBUTTON "文字または単語にジャンプ(&W)", rad5, 10, 110, 110, 15, WS_TABSTOP RTEXT "左から", -1, 10, 40, 30, 10 EDITTEXT edt1, 50, 35, 30, 15, ES_NUMBER | ES_AUTOHSCROLL | ES_RIGHT CONTROL "", scr1, "msctls_updown32", UDS_ARROWKEYS | UDS_AUTOBUDDY | UDS_ALIGNRIGHT | UDS_SETBUDDYINT, 70, 35, 10, 20 @@ -1490,8 +1491,10 @@ FONT 9, "MS UI Gothic" AUTORADIOBUTTON "タテ(&D)", rad4, 75, 85, 35, 15, WS_TABSTOP EDITTEXT edt3, 120, 85, 30, 15, ES_NUMBER | ES_AUTOHSCROLL | ES_RIGHT CONTROL "", scr3, "msctls_updown32", UDS_ARROWKEYS | UDS_AUTOBUDDY | UDS_ALIGNRIGHT | UDS_SETBUDDYINT, 100, 25, 10, 20 - DEFPUSHBUTTON "ジャンプ", IDOK, 65, 115, 60, 15 - PUSHBUTTON "キャンセル", IDCANCEL, 130, 115, 60, 15 + LTEXT "文字または単語:", -1, 27, 137, 66, 12 + EDITTEXT edt4, 97, 135, 85, 14, ES_AUTOHSCROLL + DEFPUSHBUTTON "ジャンプ", IDOK, 65, 165, 60, 15 + PUSHBUTTON "キャンセル", IDCANCEL, 130, 165, 60, 15 } IDD_FILESETTINGS DIALOG 0, 0, 270, 245