|
30 | 30 | #include "CSearchAgent.h" |
31 | 31 | #include "dlg/CDlgCancel.h" |
32 | 32 | #include "_main/CAppMode.h" |
| 33 | +#include "_main/CMutex.h" |
| 34 | +#include "env/CShareData.h" |
| 35 | +#include "env/CSakuraEnvironment.h" |
33 | 36 | #include "COpeBlk.h" |
34 | 37 | #include "window/CEditWnd.h" |
35 | 38 | #include "charset/CCodeMediator.h" |
|
46 | 49 | #include <iterator> |
47 | 50 | #include <deque> |
48 | 51 | #include <memory> |
| 52 | +#include "apiwrap/StdApi.h" |
49 | 53 | #include "apiwrap/StdControl.h" |
50 | 54 | #include "CSelectLang.h" |
51 | 55 | #include "sakura_rc.h" |
@@ -105,6 +109,93 @@ std::wstring FormatPathList( const ContainerType& containter ) |
105 | 109 | return strPatterns; |
106 | 110 | } |
107 | 111 |
|
| 112 | +class CFileLoadOrWnd{ |
| 113 | + CFileLoad m_cfl; |
| 114 | + HWND m_hWnd; |
| 115 | + int m_nLineCurrent; |
| 116 | + int m_nLineNum; |
| 117 | +public: |
| 118 | + CFileLoadOrWnd(const SEncodingConfig& encode, HWND hWnd) |
| 119 | + : m_cfl(encode) |
| 120 | + , m_hWnd(hWnd) |
| 121 | + , m_nLineCurrent(0) |
| 122 | + , m_nLineNum(0) |
| 123 | + { |
| 124 | + } |
| 125 | + ~CFileLoadOrWnd(){ |
| 126 | + } |
| 127 | + ECodeType FileOpen(const WCHAR* pszFile, bool bBigFile, ECodeType charCode, int nFlag) |
| 128 | + { |
| 129 | + if( m_hWnd ){ |
| 130 | + DWORD_PTR dwMsgResult = 0; |
| 131 | + if( 0 == ::SendMessageTimeout(m_hWnd, MYWM_GETLINECOUNT, 0, 0, SMTO_NORMAL, 10000, &dwMsgResult) ){ |
| 132 | + // エラーかタイムアウト |
| 133 | + throw CError_FileOpen(); |
| 134 | + } |
| 135 | + m_nLineCurrent = 0; |
| 136 | + m_nLineNum = (int)dwMsgResult; |
| 137 | + ::SendMessageAny(m_hWnd, MYWM_GETFILEINFO, 0, 0); |
| 138 | + const EditInfo* editInfo = &GetDllShareData().m_sWorkBuffer.m_EditInfo_MYWM_GETFILEINFO; |
| 139 | + return editInfo->m_nCharCode; |
| 140 | + } |
| 141 | + return m_cfl.FileOpen(pszFile, bBigFile, charCode, nFlag); |
| 142 | + } |
| 143 | + EConvertResult ReadLine(CNativeW* buffer, CEol* pcEol){ |
| 144 | + if( m_hWnd ){ |
| 145 | + const int max_size = (int)GetDllShareData().m_sWorkBuffer.GetWorkBufferCount<const WCHAR>(); |
| 146 | + const WCHAR* pLineData = GetDllShareData().m_sWorkBuffer.GetWorkBuffer<const WCHAR>(); |
| 147 | + buffer->SetStringHoldBuffer(L"", 0); |
| 148 | + if( m_nLineNum <= m_nLineCurrent ){ |
| 149 | + return RESULT_FAILURE; |
| 150 | + } |
| 151 | + int nLineOffset = 0; |
| 152 | + int nLineLen = 0; //初回用仮値 |
| 153 | + do{ |
| 154 | + // m_sWorkBuffer#m_Workの排他制御。外部コマンド出力/TraceOut/Diffが対象 |
| 155 | + LockGuard<CMutex> guard( CShareData::GetMutexShareWork() ); |
| 156 | + { |
| 157 | + nLineLen = ::SendMessageAny(m_hWnd, MYWM_GETLINEDATA, m_nLineCurrent, nLineOffset); |
| 158 | + if( nLineLen == 0 ){ return RESULT_FAILURE; } // EOF => 正常終了 |
| 159 | + if( nLineLen < 0 ){ return RESULT_FAILURE; } // 何かエラー |
| 160 | + buffer->AllocStringBuffer(max_size); |
| 161 | + buffer->AppendString(pLineData, t_min(nLineLen, max_size)); |
| 162 | + } |
| 163 | + nLineOffset += max_size; |
| 164 | + }while(max_size < nLineLen); |
| 165 | + if( 0 < nLineLen ){ |
| 166 | + if( 1 < nLineLen && (*buffer)[nLineLen - 2] == WCODE::CR && |
| 167 | + (*buffer)[nLineLen - 1] == WCODE::LF){ |
| 168 | + pcEol->SetType(EEolType::cr_and_lf); |
| 169 | + }else{ |
| 170 | + pcEol->SetTypeByString(buffer->GetStringPtr() + nLineLen - 1, 1); |
| 171 | + } |
| 172 | + } |
| 173 | + m_nLineCurrent++; |
| 174 | + return RESULT_COMPLETE; |
| 175 | + } |
| 176 | + return m_cfl.ReadLine(buffer, pcEol); |
| 177 | + } |
| 178 | + LONGLONG GetFileSize(){ |
| 179 | + if( m_hWnd ){ |
| 180 | + return 0; |
| 181 | + } |
| 182 | + return m_cfl.GetFileSize(); |
| 183 | + } |
| 184 | + int GetPercent(){ |
| 185 | + if( m_hWnd ){ |
| 186 | + return (int)(m_nLineCurrent * 100.0 / m_nLineNum); |
| 187 | + } |
| 188 | + return m_cfl.GetPercent(); |
| 189 | + } |
| 190 | + |
| 191 | + void FileClose(){ |
| 192 | + if( m_hWnd ){ |
| 193 | + return; |
| 194 | + } |
| 195 | + m_cfl.FileClose(); |
| 196 | + } |
| 197 | +}; |
| 198 | + |
108 | 199 | CGrepAgent::CGrepAgent() |
109 | 200 | : m_bGrepMode( false ) /* Grepモードか */ |
110 | 201 | , m_bGrepRunning( false ) /* Grep処理中 */ |
@@ -207,6 +298,60 @@ void CGrepAgent::AddTail( CEditView* pcEditView, const CNativeW& cmem, bool bAdd |
207 | 298 | } |
208 | 299 | } |
209 | 300 |
|
| 301 | +int GetHwndTitle(HWND& hWndTarget, CNativeW* pmemTitle, WCHAR* pszWindowName, WCHAR* pszWindowPath, const WCHAR* pszFile) |
| 302 | +{ |
| 303 | + if( 0 != wcsncmp(L":HWND:", pszFile, 6) ){ |
| 304 | + return 0; // ハンドルGrepではない |
| 305 | + } |
| 306 | +#ifdef _WIN64 |
| 307 | + _stscanf(pszFile + 6, L"%016I64x", &hWndTarget); |
| 308 | +#else |
| 309 | + _stscanf(pszFile + 6, L"%08x", &hWndTarget); |
| 310 | +#endif |
| 311 | + if( pmemTitle ){ |
| 312 | + const wchar_t* p = L"Window:["; |
| 313 | + pmemTitle->SetStringHoldBuffer(p, 8); |
| 314 | + } |
| 315 | + if( !IsSakuraMainWindow(hWndTarget) ){ |
| 316 | + return -1; |
| 317 | + } |
| 318 | + ::SendMessageAny(hWndTarget, MYWM_GETFILEINFO, 0, 0); |
| 319 | + EditInfo* editInfo = &(GetDllShareData().m_sWorkBuffer.m_EditInfo_MYWM_GETFILEINFO); |
| 320 | + if( '\0' == editInfo->m_szPath[0] ){ |
| 321 | + // Grepかアウトプットか無題 |
| 322 | + WCHAR szTitle[_MAX_PATH]{}; |
| 323 | + WCHAR szGrep[100]{}; |
| 324 | + editInfo->m_bIsModified = false; |
| 325 | + const EditNode* node = CAppNodeManager::getInstance()->GetEditNode(hWndTarget); |
| 326 | + WCHAR* pszTagName = szTitle; |
| 327 | + if( editInfo->m_bIsGrep ){ |
| 328 | + // Grepは検索キーとタグがぶつかることがあるので単に(Grep)と表示 |
| 329 | + pszTagName = szGrep; |
| 330 | + wcsncpy_s(pszTagName, _countof(szGrep), L"(Grep)", _TRUNCATE); |
| 331 | + } |
| 332 | + CFileNameManager::getInstance()->GetMenuFullLabel_WinListNoEscape(szTitle, _countof(szTitle), editInfo, node->m_nId, -1, NULL ); |
| 333 | +#ifdef _WIN64 |
| 334 | + auto_sprintf(pszWindowName, L":HWND:[%016I64x]%s", hWndTarget, pszTagName); |
| 335 | +#else |
| 336 | + auto_sprintf(pszWindowName, L":HWND:[%08x]%s", hWndTarget, pszTagName); |
| 337 | +#endif |
| 338 | + if( pmemTitle ){ |
| 339 | + pmemTitle->AppendString(szTitle); |
| 340 | + } |
| 341 | + pszWindowPath[0] = L'\0'; |
| 342 | + }else{ |
| 343 | + SplitPath_FolderAndFile(editInfo->m_szPath, pszWindowPath, pszWindowName); |
| 344 | + if( pmemTitle ){ |
| 345 | + pmemTitle->AppendString(pszWindowName); |
| 346 | + } |
| 347 | + } |
| 348 | + if( pmemTitle ){ |
| 349 | + pmemTitle->AppendString(L"]"); |
| 350 | + } |
| 351 | + return 1; |
| 352 | +} |
| 353 | + |
| 354 | + |
210 | 355 | /*! Grep実行 |
211 | 356 |
|
212 | 357 | @param[in] pcmGrepKey 検索パターン |
@@ -458,13 +603,28 @@ DWORD CGrepAgent::DoGrep( |
458 | 603 | } |
459 | 604 | } |
460 | 605 |
|
461 | | - cmemMessage.AppendString( LS( STR_GREP_SEARCH_TARGET ) ); //L"検索対象 " |
| 606 | + HWND hWndTarget = NULL; |
| 607 | + WCHAR szWindowName[_MAX_PATH]; |
| 608 | + WCHAR szWindowPath[_MAX_PATH]; |
462 | 609 | { |
463 | | - // 解析済みのファイルパターン配列を取得する |
464 | | - const auto& vecSearchFileKeys = cGrepEnumKeys.m_vecSearchFileKeys; |
465 | | - std::wstring strPatterns = FormatPathList( vecSearchFileKeys ); |
466 | | - cmemMessage.AppendString( strPatterns.c_str(), strPatterns.length() ); |
| 610 | + int nHwndRet = GetHwndTitle(hWndTarget, &cmemWork, szWindowName, szWindowPath, pcmGrepFile->GetStringPtr()); |
| 611 | + if( -1 == nHwndRet ){ |
| 612 | + cmemMessage.AppendString(L"HWND handle error.\n"); |
| 613 | + if( sGrepOption.bGrepHeader ){ |
| 614 | + AddTail(pcViewDst, cmemMessage, sGrepOption.bGrepStdout); |
| 615 | + } |
| 616 | + return 0; |
| 617 | + }else if( 0 == nHwndRet ){ |
| 618 | + { |
| 619 | + // 解析済みのファイルパターン配列を取得する |
| 620 | + const auto& vecSearchFileKeys = cGrepEnumKeys.m_vecSearchFileKeys; |
| 621 | + std::wstring strPatterns = FormatPathList( vecSearchFileKeys ); |
| 622 | + cmemWork.SetString( strPatterns.c_str(), strPatterns.length() ); |
| 623 | + } |
| 624 | + } |
467 | 625 | } |
| 626 | + cmemMessage.AppendString( LS( STR_GREP_SEARCH_TARGET ) ); //L"検索対象 " |
| 627 | + cmemMessage += cmemWork; |
468 | 628 | cmemMessage.AppendString( L"\r\n" ); |
469 | 629 |
|
470 | 630 | cmemMessage.AppendString( LS( STR_GREP_SEARCH_FOLDER ) ); //L"フォルダ " |
@@ -586,38 +746,87 @@ DWORD CGrepAgent::DoGrep( |
586 | 746 |
|
587 | 747 | int nGrepTreeResult = 0; |
588 | 748 |
|
589 | | - for( int nPath = 0; nPath < (int)vPaths.size(); nPath++ ){ |
590 | | - bool bOutputBaseFolder = false; |
591 | | - std::wstring sPath = ChopYen( vPaths[nPath] ); |
592 | | - int nTreeRet = DoGrepTree( |
593 | | - pcViewDst, |
594 | | - &cDlgCancel, |
595 | | - pcmGrepKey->GetStringPtr(), |
596 | | - cmemReplace, |
597 | | - cGrepEnumKeys, |
598 | | - cGrepExceptAbsFiles, |
599 | | - cGrepExceptAbsFolders, |
600 | | - sPath.c_str(), |
601 | | - sPath.c_str(), |
602 | | - sSearchOption, |
603 | | - sGrepOption, |
604 | | - pattern, |
605 | | - &cRegexp, |
606 | | - 0, |
607 | | - bOutputBaseFolder, |
608 | | - &nHitCount, |
609 | | - cmemMessage, |
610 | | - cUnicodeBuffer |
611 | | - ); |
612 | | - if( nTreeRet == -1 ){ |
613 | | - nGrepTreeResult = -1; |
614 | | - break; |
| 749 | + if( hWndTarget ){ |
| 750 | + for( HWND hwnd = hWndTarget; NULL != hwnd; hwnd = NULL ){ |
| 751 | + bool bOutputBaseFolder = false; |
| 752 | + bool bOutputFolderName = false; |
| 753 | + // 複数ウィンドウループ予約 |
| 754 | + auto nPathLen = wcsnlen_s(szWindowPath, _countof(szWindowPath)); |
| 755 | + std::wstring currentFile = szWindowPath; |
| 756 | + if( currentFile.size() ){ |
| 757 | + currentFile += L'\\'; |
| 758 | + nPathLen += 1; |
| 759 | + } |
| 760 | + currentFile += szWindowName; |
| 761 | + int nHitCount = nGrepTreeResult; |
| 762 | + int nTreeRet = DoGrepFile( |
| 763 | + pcViewDst, |
| 764 | + &cDlgCancel, |
| 765 | + hwnd, |
| 766 | + pcmGrepKey->GetStringPtr(), |
| 767 | + szWindowName, |
| 768 | + sSearchOption, |
| 769 | + sGrepOption, |
| 770 | + pattern, |
| 771 | + &cRegexp, |
| 772 | + &nHitCount, |
| 773 | + currentFile.c_str(), |
| 774 | + szWindowPath, |
| 775 | + (sGrepOption.bGrepSeparateFolder && sGrepOption.bGrepOutputBaseFolder ? L"" : szWindowPath), |
| 776 | + (sGrepOption.bGrepSeparateFolder ? szWindowName : currentFile.c_str() + nPathLen), |
| 777 | + bOutputBaseFolder, |
| 778 | + bOutputFolderName, |
| 779 | + cmemMessage, |
| 780 | + cUnicodeBuffer |
| 781 | + ); |
| 782 | + if( nTreeRet == -1 ){ |
| 783 | + nGrepTreeResult = -1; |
| 784 | + break; |
| 785 | + } |
| 786 | + nGrepTreeResult += nTreeRet; |
| 787 | + } |
| 788 | + if( 0 < cmemMessage.GetStringLength() ){ |
| 789 | + AddTail( pcViewDst, cmemMessage, sGrepOption.bGrepStdout ); |
| 790 | + pcViewDst->GetCommander().Command_GOFILEEND( false ); |
| 791 | + if( !CEditWnd::getInstance()->UpdateTextWrap() ) |
| 792 | + CEditWnd::getInstance()->RedrawAllViews( pcViewDst ); |
| 793 | + cmemMessage.Clear(); |
| 794 | + } |
| 795 | + nHitCount = nGrepTreeResult; |
| 796 | + }else{ |
| 797 | + for( int nPath = 0; nPath < (int)vPaths.size(); nPath++ ){ |
| 798 | + bool bOutputBaseFolder = false; |
| 799 | + std::wstring sPath = ChopYen( vPaths[nPath] ); |
| 800 | + int nTreeRet = DoGrepTree( |
| 801 | + pcViewDst, |
| 802 | + &cDlgCancel, |
| 803 | + pcmGrepKey->GetStringPtr(), |
| 804 | + cmemReplace, |
| 805 | + cGrepEnumKeys, |
| 806 | + cGrepExceptAbsFiles, |
| 807 | + cGrepExceptAbsFolders, |
| 808 | + sPath.c_str(), |
| 809 | + sPath.c_str(), |
| 810 | + sSearchOption, |
| 811 | + sGrepOption, |
| 812 | + pattern, |
| 813 | + &cRegexp, |
| 814 | + 0, |
| 815 | + bOutputBaseFolder, |
| 816 | + &nHitCount, |
| 817 | + cmemMessage, |
| 818 | + cUnicodeBuffer |
| 819 | + ); |
| 820 | + if( nTreeRet == -1 ){ |
| 821 | + nGrepTreeResult = -1; |
| 822 | + break; |
| 823 | + } |
| 824 | + nGrepTreeResult += nTreeRet; |
| 825 | + } |
| 826 | + if( 0 < cmemMessage.GetStringLength() ) { |
| 827 | + AddTail( pcViewDst, cmemMessage, sGrepOption.bGrepStdout ); |
| 828 | + cmemMessage._SetStringLength(0); |
615 | 829 | } |
616 | | - nGrepTreeResult += nTreeRet; |
617 | | - } |
618 | | - if( 0 < cmemMessage.GetStringLength() ) { |
619 | | - AddTail( pcViewDst, cmemMessage, sGrepOption.bGrepStdout ); |
620 | | - cmemMessage._SetStringLength(0); |
621 | 830 | } |
622 | 831 | if( -1 == nGrepTreeResult && sGrepOption.bGrepHeader ){ |
623 | 832 | const wchar_t* p = LS( STR_GREP_SUSPENDED ); //L"中断しました。\r\n" |
@@ -781,6 +990,7 @@ int CGrepAgent::DoGrepTree( |
781 | 990 | nRet = DoGrepFile( |
782 | 991 | pcViewDst, |
783 | 992 | pcDlgCancel, |
| 993 | + NULL, |
784 | 994 | pszKey, |
785 | 995 | lpFileName, |
786 | 996 | sSearchOption, |
@@ -1101,6 +1311,7 @@ static void OutputPathInfo( |
1101 | 1311 | int CGrepAgent::DoGrepFile( |
1102 | 1312 | CEditView* pcViewDst, //!< |
1103 | 1313 | CDlgCancel* pcDlgCancel, //!< [in] Cancelダイアログへのポインタ |
| 1314 | + HWND hWndTarget, //!< [in] 対象Windows(NULLでファイル) |
1104 | 1315 | const wchar_t* pszKey, //!< [in] 検索パターン |
1105 | 1316 | const WCHAR* pszFile, //!< [in] 処理対象ファイル名(表示用) |
1106 | 1317 | const SSearchOption& sSearchOption, //!< [in] 検索オプション |
@@ -1132,7 +1343,7 @@ int CGrepAgent::DoGrepFile( |
1132 | 1343 | if( !CDocTypeManager().GetTypeConfigMini( CDocTypeManager().GetDocumentTypeOfPath( pszFile ), &type ) ){ |
1133 | 1344 | return -1; |
1134 | 1345 | } |
1135 | | - CFileLoad cfl( type->m_encoding ); // 2012/12/18 Uchi 検査するファイルのデフォルトの文字コードを取得する様に |
| 1346 | + CFileLoadOrWnd cfl( type->m_encoding, hWndTarget ); // 2012/12/18 Uchi 検査するファイルのデフォルトの文字コードを取得する様に |
1136 | 1347 | int nOldPercent = 0; |
1137 | 1348 |
|
1138 | 1349 | int nKeyLen = wcslen( pszKey ); |
|
0 commit comments