/* findfile.cpp Поиск (Alt-F7) */ /* Copyright (c) 1996 Eugene Roshal Copyright (c) 2000 Far Group All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the authors may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "headers.hpp" #pragma hdrstop #include "findfile.hpp" #include "flink.hpp" #include "lang.hpp" #include "keys.hpp" #include "ctrlobj.hpp" #include "dialog.hpp" #include "filepanels.hpp" #include "panel.hpp" #include "fileview.hpp" #include "fileedit.hpp" #include "filelist.hpp" #include "cmdline.hpp" #include "chgprior.hpp" #include "namelist.hpp" #include "scantree.hpp" #include "manager.hpp" #include "scrbuf.hpp" #include "CFileMask.hpp" #include "filefilter.hpp" #include "farexcpt.hpp" #include "syslog.hpp" #include "localOEM.hpp" #include "gettable.hpp" #include "registry.hpp" #include "cddrv.hpp" #include "TaskBar.hpp" #include "interf.hpp" #include "palette.hpp" #include "message.hpp" #include "delete.hpp" #include "datetime.hpp" #include "drivemix.hpp" #include "pathmix.hpp" #include "strmix.hpp" #include "mix.hpp" #define DLG_HEIGHT 23 #define DLG_WIDTH 74 #define CHAR_TABLE_SIZE 5 #define LIST_DELTA 64 DWORD LIST_INDEX_NONE = (DWORD)-1; // Список найденных файлов. Индекс из списка хранится в меню. struct FINDLIST { FAR_FIND_DATA_EX FindData; size_t ArcIndex; DWORD Used; // BYTE Addons[6]; }; FINDLIST **FindList; size_t FindListCapacity=0; size_t FindListCount=0; // Список архивов. Если файл найден в архиве, то FindList->ArcIndex указывает сюда. struct ARCLIST { string strArcName; HANDLE hPlugin; // Plugin handle DWORD Flags; // OpenPluginInfo.Flags string strRootPath; // Root path in plugin after opening. }; ARCLIST **ArcList; size_t ArcListCapacity=0; size_t ArcListCount=0; CriticalSection ffCS; // чтобы не ресайзили список найденных файлов, пока мы из него читаем CriticalSection statusCS; // чтобы не писали в FindMessage/FindFileCount/FindDirCount пока мы оттуда читаем size_t FindFileArcIndex; // Используются для отправки файлов на временную панель. // индекс текущего элемента в списке и флаг для отправки. DWORD FindExitIndex; int FindExitCode; string strFindMask, strFindStr; int SearchMode,CmpCase,WholeWords,SearchInArchives,SearchHex; int FindFoldersChanged; int SearchFromChanged; int DlgWidth,DlgHeight; volatile int StopSearch,PauseSearch,SearchDone,LastFoundNumber,FindFileCount,FindDirCount; string strFindMessage; string strLastDirName; int FindMessageReady,FindCountReady,FindPositionChanged; string strPluginSearchPath; int RecurseLevel; bool BreakMainThread; int PluginMode; HANDLE hPluginMutex; bool UseFilter=false; UINT CodePage=CP_AUTODETECT; UINT64 SearchInFirst=0; #define readBufferSizeA 32768 #define readBufferSize (readBufferSizeA*sizeof(wchar_t)) char *readBufferA; wchar_t *readBuffer; int codePagesCount; struct CodePageInfo { UINT CodePage; UINT MaxCharSize; wchar_t LastSymbol; bool WordFound; } *codePages; unsigned char *hexFindString; size_t hexFindStringSize; wchar_t *findString,*findStringBuffer; size_t *skipCharsTable; int favoriteCodePages = 0; TaskBar *TB=NULL; bool InFileSearchInited=false; CFileMask FileMaskForFindFile; FileFilter *Filter; enum { FIND_EXIT_NONE, FIND_EXIT_SEARCHAGAIN, FIND_EXIT_GOTO, FIND_EXIT_PANEL }; enum ADVANCEDDLG { AD_DOUBLEBOX, AD_TEXT_SEARCHFIRST, AD_EDIT_SEARCHFIRST, AD_CHECKBOX_FINDALTERNATESTREAMS, AD_SEPARATOR1, AD_BUTTON_OK, AD_BUTTON_CANCEL, }; enum FINDASKDLG { FAD_DOUBLEBOX, FAD_TEXT_MASK, FAD_EDIT_MASK, FAD_SEPARATOR0, FAD_TEXT_TEXTHEX, FAD_EDIT_TEXT, FAD_EDIT_HEX, FAD_TEXT_CP, FAD_COMBOBOX_CP, FAD_SEPARATOR1, FAD_CHECKBOX_CASE, FAD_CHECKBOX_WHOLEWORDS, FAD_CHECKBOX_HEX, FAD_CHECKBOX_ARC, FAD_CHECKBOX_DIRS, FAD_CHECKBOX_LINKS, FAD_SEPARATOR_2, FAD_SEPARATOR_3, FAD_TEXT_WHERE, FAD_COMBOBOX_WHERE, FAD_SEPARATOR_4, FAD_CHECKBOX_FILTER, FAD_SEPARATOR_5, FAD_BUTTON_FIND, FAD_BUTTON_DRIVE, FAD_BUTTON_FILTER, FAD_BUTTON_ADVANCED, FAD_BUTTON_CANCEL, }; enum FINDASKDLGCOMBO { FADC_ALLDISKS, FADC_ALLBUTNET, FADC_PATH, FADC_ROOT, FADC_FROMCURRENT, FADC_INCURRENT, FADC_SELECTED, }; enum FINDDLG { FD_DOUBLEBOX, FD_LISTBOX, FD_SEPARATOR1, FD_TEXT_STATUS, FD_SEPARATOR2, FD_BUTTON_NEW, FD_BUTTON_GOTO, FD_BUTTON_VIEW, FD_BUTTON_PANEL, FD_BUTTON_STOP, }; /* int _cdecl SortItems(const void *p1,const void *p2) { PluginPanelItem *Item1=(PluginPanelItem *)p1; PluginPanelItem *Item2=(PluginPanelItem *)p2; string strN1=Item1->FindData.lpwszFileName; string strN2=Item2->FindData.lpwszFileName; CutToSlash(strN1); CutToSlash(strN2); return StrCmpI(strN2,strN1); } */ void InitInFileSearch() { if (!InFileSearchInited && !strFindStr.IsEmpty()) { size_t findStringCount = strFindStr.GetLength(); // Инициализируем буферы чтения из файла readBufferA = (char *)xf_malloc(readBufferSizeA); readBuffer = (wchar_t *)xf_malloc(readBufferSize); if (!SearchHex) { // Формируем строку поиска if (!CmpCase) { findStringBuffer = (wchar_t *)xf_malloc(2*findStringCount*sizeof(wchar_t)); findString=findStringBuffer; for (size_t index = 0; indexCodePage)) cp->MaxCharSize = 2; else { CPINFO cpi; if (!GetCPInfo(cp->CodePage, &cpi)) cpi.MaxCharSize = 0; //Считаем, что ошибка и потом такие таблицы в поиске пропускаем cp->MaxCharSize = cpi.MaxCharSize; } cp->LastSymbol = NULL; cp->WordFound = false; } } else { // Формируем hex-строку для поиска hexFindStringSize = 0; if (SearchHex) { bool flag = false; hexFindString = (unsigned char *)xf_malloc((findStringCount-findStringCount/3+1)/2); for (size_t index = 0; index < strFindStr.GetLength(); index++) { wchar_t symbol = strFindStr.At(index); byte offset = 0; if (symbol >= L'a' && symbol <= L'f') offset = 87; else if (symbol >= L'A' && symbol <= L'F') offset = 55; else if (symbol >= L'0' && symbol <= L'9') offset = 48; else continue; if (!flag) hexFindString[hexFindStringSize++] = ((byte)symbol-offset)<<4; else hexFindString[hexFindStringSize-1] |= ((byte)symbol-offset); flag = !flag; } } // Инизиализируем данные для аглоритма поиска skipCharsTable = (size_t *)xf_malloc((255+1)*sizeof(size_t)); for (size_t index = 0; index < 255+1; index++) skipCharsTable[index] = hexFindStringSize; for (size_t index = 0; index < (size_t)hexFindStringSize-1; index++) skipCharsTable[hexFindString[index]] = hexFindStringSize-1-index; } InFileSearchInited=true; } } void ReleaseInFileSearch() { if (InFileSearchInited && !strFindStr.IsEmpty()) { if(readBufferA) { xf_free(readBufferA); readBufferA=NULL; } if(readBuffer) { xf_free(readBuffer); readBuffer=NULL; } if(skipCharsTable) { xf_free(skipCharsTable); skipCharsTable=NULL; } if(codePages) { xf_free(codePages); codePages=NULL; } if(findStringBuffer) { xf_free(findStringBuffer); findStringBuffer=NULL; } if(hexFindString) { xf_free(hexFindString); hexFindString=NULL; } InFileSearchInited=false; } } string &PrepareDriveNameStr(string &strSearchFromRoot) { string strCurDir; CtrlObject->CmdLine->GetCurDir(strCurDir); GetPathRootOne(strCurDir,strCurDir); DeleteEndSlash(strCurDir); if( strCurDir.IsEmpty()|| (CtrlObject->Cp()->ActivePanel->GetMode()==PLUGIN_PANEL && CtrlObject->Cp()->ActivePanel->IsVisible()) ) { strSearchFromRoot = MSG(MSearchFromRootFolder); } else { strSearchFromRoot= MSG(MSearchFromRootOfDrive); strSearchFromRoot+=L" "; strSearchFromRoot+=strCurDir; } return strSearchFromRoot; } // Проверяем символ на принадлежность разделителям слов bool IsWordDiv(const wchar_t symbol) { // Так же разделителем является конец строки и пробельные символы return symbol==0||IsSpace(symbol)||IsEol(symbol)||IsWordDiv(Opt.strWordDiv,symbol); } void ClearAllLists() { CriticalSectionLock Lock(ffCS); FindFileArcIndex=LIST_INDEX_NONE; if(FindList) { for(size_t i=0;i(xf_realloc(FindList,(FindListCapacity+Delta)*sizeof(*FindList))); if(NewList) { FindList=NewList; FindListCapacity+=Delta; Result=true; } return Result; } bool ArcListGrow() { bool Result=false; size_t Delta=(ArcListCapacity<256)?LIST_DELTA:ArcListCapacity/2; ARCLIST** NewList=reinterpret_cast(xf_realloc(ArcList,(ArcListCapacity+Delta)*sizeof(*ArcList))); if(NewList) { ArcList = NewList; ArcListCapacity+= Delta; Result=true; } return Result; } void SetPluginDirectory(const wchar_t *DirName,HANDLE hPlugin,bool UpdatePanel=false) { if(DirName && *DirName) { string strName(DirName); wchar_t* DirPtr = strName.GetBuffer(); wchar_t* NamePtr = (wchar_t*) PointToName(DirPtr); if (NamePtr != DirPtr) { *(NamePtr-1) = 0; // force plugin to update its file list (that can be empty at this time) // if not done SetDirectory may fail { int FileCount=0; PluginPanelItem *PanelData=NULL; if(CtrlObject->Plugins.GetFindData(hPlugin,&PanelData,&FileCount,OPM_SILENT)) { CtrlObject->Plugins.FreeFindData(hPlugin,PanelData,FileCount); } } if (*DirPtr) { CtrlObject->Plugins.SetDirectory(hPlugin,DirPtr,OPM_SILENT); } else { CtrlObject->Plugins.SetDirectory(hPlugin,L"\\",OPM_SILENT); } } // Отрисуем панель при необходимости. if (UpdatePanel) { CtrlObject->Cp()->ActivePanel->Update(UPDATE_KEEP_SELECTION); CtrlObject->Cp()->ActivePanel->GoToFile(NamePtr); CtrlObject->Cp()->ActivePanel->Show(); } //strName.ReleaseBuffer(); Не надо. Строка все ровно удаляется, лишний вызов StrLength. } } LONG_PTR WINAPI AdvancedDlgProc(HANDLE hDlg,int Msg,int Param1,LONG_PTR Param2) { switch (Msg) { case DN_CLOSE: if(Param1==AD_BUTTON_OK) { LPCWSTR Data=reinterpret_cast(Dialog::SendDlgMessage(hDlg,DM_GETCONSTTEXTPTR,AD_EDIT_SEARCHFIRST,NULL)); if(Data && *Data && !CheckFileSizeStringFormat(Data)) { Message(MSG_WARNING,1,MSG(MFindFileAdvancedTitle),MSG(MBadFileSizeFormat),MSG(MOk)); return FALSE; } } break; } return Dialog::DefDlgProc(hDlg,Msg,Param1,Param2); } void AdvancedDialog() { DialogDataEx AdvancedDlgData[]= { /* 00 */DI_DOUBLEBOX,3,1,52,7,0,0,0,0,MSG(MFindFileAdvancedTitle), /* 01 */DI_TEXT,5,2,0,2,0,0,0,0,MSG(MFindFileSearchFirst), /* 02 */DI_EDIT,5,3,50,3,0,0,0,0,Opt.FindOpt.strSearchInFirstSize, /* 03 */DI_CHECKBOX,5,4,0,4,0,Opt.FindOpt.FindAlternateStreams,0,0,MSG(MFindAlternateStreams), /* 04 */DI_TEXT,3,5,0,5,0,0,DIF_BOXCOLOR|DIF_SEPARATOR,0,L"", /* 05 */DI_BUTTON,0,6,0,6,0,0,DIF_CENTERGROUP,1,MSG(MOk), /* 06 */DI_BUTTON,0,6,0,6,0,0,DIF_CENTERGROUP,0,MSG(MCancel), }; MakeDialogItemsEx(AdvancedDlgData,AdvancedDlg); Dialog Dlg(AdvancedDlg,countof(AdvancedDlg),AdvancedDlgProc); Dlg.SetHelp(L"FindFileAdvanced"); Dlg.SetPosition(-1,-1,52+4,7+2); Dlg.Process(); int ExitCode=Dlg.GetExitCode(); if(ExitCode==AD_BUTTON_OK) { Opt.FindOpt.strSearchInFirstSize = AdvancedDlg[AD_EDIT_SEARCHFIRST].strData; SearchInFirst=ConvertFileSizeString(Opt.FindOpt.strSearchInFirstSize); Opt.FindOpt.FindAlternateStreams=(AdvancedDlg[AD_CHECKBOX_FINDALTERNATESTREAMS].Selected==BSTATE_CHECKED); } } LONG_PTR WINAPI MainDlgProc(HANDLE hDlg,int Msg,int Param1,LONG_PTR Param2) { switch(Msg) { case DN_INITDIALOG: { bool Hex=(Dialog::SendDlgMessage(hDlg,DM_GETCHECK,FAD_CHECKBOX_HEX,NULL)==BSTATE_CHECKED); Dialog::SendDlgMessage(hDlg,DM_SHOWITEM,FAD_EDIT_TEXT,!Hex); Dialog::SendDlgMessage(hDlg,DM_SHOWITEM,FAD_EDIT_HEX,Hex); Dialog::SendDlgMessage(hDlg,DM_ENABLE,FAD_TEXT_CP,!Hex); Dialog::SendDlgMessage(hDlg,DM_ENABLE,FAD_COMBOBOX_CP,!Hex); Dialog::SendDlgMessage(hDlg,DM_ENABLE,FAD_CHECKBOX_CASE,!Hex); Dialog::SendDlgMessage(hDlg,DM_ENABLE,FAD_CHECKBOX_WHOLEWORDS,!Hex); Dialog::SendDlgMessage(hDlg,DM_ENABLE,FAD_CHECKBOX_DIRS,!Hex); Dialog::SendDlgMessage(hDlg,DM_EDITUNCHANGEDFLAG,FAD_EDIT_TEXT,1); Dialog::SendDlgMessage(hDlg,DM_EDITUNCHANGEDFLAG,FAD_EDIT_HEX,1); Dialog::SendDlgMessage(hDlg,DM_SETTEXTPTR,FAD_TEXT_TEXTHEX,(LONG_PTR)(Hex?MSG(MFindFileHex):MSG(MFindFileText))); Dialog::SendDlgMessage(hDlg,DM_SETTEXTPTR,FAD_TEXT_CP,(LONG_PTR)MSG(MFindFileCodePage)); Dialog::SendDlgMessage(hDlg,DM_SETCOMBOBOXEVENT,FAD_COMBOBOX_CP,CBET_KEY); /* Установка запомненных ранее параметров */ CodePage = Opt.FindCodePage; /* -------------------------------------- */ favoriteCodePages = AddCodepagesToList(hDlg, FAD_COMBOBOX_CP, CodePage, false, true); // Текущее значение в в списке выбора кодовых страниц в общем случае модет не совпадать с CodePage, // так что получаем CodePage из списка выбора FarListPos Position; Dialog::SendDlgMessage(hDlg, DM_LISTGETCURPOS, FAD_COMBOBOX_CP, (LONG_PTR)&Position); FarListGetItem Item = { Position.SelectPos }; Dialog::SendDlgMessage(hDlg, DM_LISTGETITEM, FAD_COMBOBOX_CP, (LONG_PTR)&Item); CodePage = (UINT)Dialog::SendDlgMessage(hDlg, DM_LISTGETDATA, FAD_COMBOBOX_CP, Position.SelectPos); FindFoldersChanged = FALSE; SearchFromChanged = FALSE; return TRUE; } case DN_CLOSE: { switch(Param1) { case FAD_BUTTON_FIND: { LPCWSTR Mask=(LPCWSTR)Dialog::SendDlgMessage(hDlg,DM_GETCONSTTEXTPTR,FAD_EDIT_MASK,NULL); if(!Mask||!*Mask) Mask=L"*"; return FileMaskForFindFile.Set(Mask,0); } case FAD_BUTTON_DRIVE: { IsRedrawFramesInProcess++; CtrlObject->Cp()->ActivePanel->ChangeDisk(); // Ну что ж, раз пошла такая пьянка рефрешить фреймы // будем таким способом. //FrameManager->ProcessKey(KEY_CONSOLE_BUFFER_RESIZE); FrameManager->ResizeAllFrame(); IsRedrawFramesInProcess--; string strSearchFromRoot; PrepareDriveNameStr(strSearchFromRoot); FarListGetItem item={FADC_ROOT}; Dialog::SendDlgMessage(hDlg,DM_LISTGETITEM,FAD_COMBOBOX_WHERE,(LONG_PTR)&item); item.Item.Text=strSearchFromRoot; Dialog::SendDlgMessage(hDlg,DM_LISTUPDATE,FAD_COMBOBOX_WHERE,(LONG_PTR)&item); PluginMode=CtrlObject->Cp()->ActivePanel->GetMode()==PLUGIN_PANEL; Dialog::SendDlgMessage(hDlg,DM_ENABLE,FAD_CHECKBOX_DIRS,PluginMode?FALSE:TRUE); item.ItemIndex=FADC_ALLDISKS; Dialog::SendDlgMessage(hDlg,DM_LISTGETITEM,FAD_COMBOBOX_WHERE,(LONG_PTR)&item); if(PluginMode) item.Item.Flags|=LIF_GRAYED; else item.Item.Flags&=~LIF_GRAYED; Dialog::SendDlgMessage(hDlg,DM_LISTUPDATE,FAD_COMBOBOX_WHERE,(LONG_PTR)&item); item.ItemIndex=FADC_ALLBUTNET; Dialog::SendDlgMessage(hDlg,DM_LISTGETITEM,FAD_COMBOBOX_WHERE,(LONG_PTR)&item); if(PluginMode) item.Item.Flags|=LIF_GRAYED; else item.Item.Flags&=~LIF_GRAYED; Dialog::SendDlgMessage(hDlg,DM_LISTUPDATE,FAD_COMBOBOX_WHERE,(LONG_PTR)&item); } break; case FAD_BUTTON_FILTER: Filter->FilterEdit(); break; case FAD_BUTTON_ADVANCED: AdvancedDialog(); break; case -2: case -1: case FAD_BUTTON_CANCEL: return TRUE; } return FALSE; } case DN_BTNCLICK: { switch(Param1) { case FAD_CHECKBOX_DIRS: FindFoldersChanged = TRUE; break; case FAD_CHECKBOX_HEX: { Dialog::SendDlgMessage(hDlg,DM_ENABLEREDRAW,FALSE,0); string strDataStr; Transform(strDataStr,(LPCWSTR)Dialog::SendDlgMessage(hDlg,DM_GETCONSTTEXTPTR,Param2?FAD_EDIT_TEXT:FAD_EDIT_HEX,NULL),Param2?L'X':L'S'); Dialog::SendDlgMessage(hDlg,DM_SETTEXTPTR,Param2?FAD_EDIT_HEX:FAD_EDIT_TEXT,(LONG_PTR)(const wchar_t*)strDataStr); Dialog::SendDlgMessage(hDlg,DM_SHOWITEM,FAD_EDIT_TEXT,!Param2); Dialog::SendDlgMessage(hDlg,DM_SHOWITEM,FAD_EDIT_HEX,Param2); Dialog::SendDlgMessage(hDlg,DM_ENABLE,FAD_TEXT_CP,!Param2); Dialog::SendDlgMessage(hDlg,DM_ENABLE,FAD_COMBOBOX_CP,!Param2); Dialog::SendDlgMessage(hDlg,DM_ENABLE,FAD_CHECKBOX_CASE,!Param2); Dialog::SendDlgMessage(hDlg,DM_ENABLE,FAD_CHECKBOX_WHOLEWORDS,!Param2); Dialog::SendDlgMessage(hDlg,DM_ENABLE,FAD_CHECKBOX_DIRS,!Param2); Dialog::SendDlgMessage(hDlg,DM_SETTEXTPTR,FAD_TEXT_TEXTHEX,(LONG_PTR)(const wchar_t*)(Param2?MSG(MFindFileHex):MSG(MFindFileText))); if (strDataStr.GetLength()>0) { int UnchangeFlag=(int)Dialog::SendDlgMessage(hDlg,DM_EDITUNCHANGEDFLAG,FAD_EDIT_TEXT,-1); Dialog::SendDlgMessage(hDlg,DM_EDITUNCHANGEDFLAG,FAD_EDIT_HEX,UnchangeFlag); } Dialog::SendDlgMessage(hDlg,DM_ENABLEREDRAW,TRUE,0); } break; } break; } case DM_KEY: { // Обработка установки/снятия флажков для стандартных и любимых таблиц символов if (Param1==FAD_COMBOBOX_CP && (Param2==KEY_INS || Param2==KEY_NUMPAD0 || Param2==KEY_SPACE)) { // Получаем текущую позицию в выпадающем списке таблиц символов FarListPos Position; Dialog::SendDlgMessage(hDlg, DM_LISTGETCURPOS, FAD_COMBOBOX_CP, (LONG_PTR)&Position); // Получаем номер выбранной таблицы симолов FarListGetItem Item = { Position.SelectPos }; Dialog::SendDlgMessage(hDlg, DM_LISTGETITEM, FAD_COMBOBOX_CP, (LONG_PTR)&Item); UINT SelectedCodePage = (UINT)Dialog::SendDlgMessage(hDlg, DM_LISTGETDATA, FAD_COMBOBOX_CP, Position.SelectPos); // Разрешаем отмечать только стандартные и любимые таблицы символов int FavoritesIndex = 2 + StandardCPCount + 2; if (Position.SelectPos > 1 && Position.SelectPos < FavoritesIndex + (favoriteCodePages ? favoriteCodePages + 1 : 0)) { // Преобразуем номер таблицы сиволов к строке string strCodePageName; strCodePageName.Format(L"%u", SelectedCodePage); // Получаем текущее состояние флага в реестре int SelectType = 0; GetRegKey(FavoriteCodePagesKey, strCodePageName, SelectType, 0); // Отмечаем/разотмечаем таблицу символов if (Item.Item.Flags & LIF_CHECKED) { // Для стандартных таблиц символов просто удаляем значение из рееста, для // любимых же оставляем в реестре флаг, что таблица символов любимая if (SelectType & CPST_FAVORITE) SetRegKey(FavoriteCodePagesKey, strCodePageName, CPST_FAVORITE); else DeleteRegValue(FavoriteCodePagesKey, strCodePageName); Item.Item.Flags &= ~LIF_CHECKED; } else { SetRegKey(FavoriteCodePagesKey, strCodePageName, CPST_FIND | (SelectType & CPST_FAVORITE ? CPST_FAVORITE : 0)); Item.Item.Flags |= LIF_CHECKED; } // Обновляем текущий элемент в выпадающем списке Dialog::SendDlgMessage(hDlg, DM_LISTUPDATE, FAD_COMBOBOX_CP, (LONG_PTR)&Item); // Обрабатываем случай, когда таблица символов может присутствовать, как в стандартных, так и в любимых, // т.е. выбор/снятие флага автоматичекски происходуит у обоих элементов bool bStandardCodePage = Position.SelectPos < FavoritesIndex; for (int Index = bStandardCodePage ? FavoritesIndex : 0; Index < (bStandardCodePage ? FavoritesIndex + favoriteCodePages : FavoritesIndex); Index++) { // Получаем элемент таблицы симолов FarListGetItem CheckItem = { Index }; Dialog::SendDlgMessage(hDlg, DM_LISTGETITEM, FAD_COMBOBOX_CP, (LONG_PTR)&CheckItem); // Обрабатываем только таблицы симовлов if (!(CheckItem.Item.Flags&LIF_SEPARATOR)) { if (SelectedCodePage == (UINT)Dialog::SendDlgMessage(hDlg, DM_LISTGETDATA, FAD_COMBOBOX_CP, Index)) { if (Item.Item.Flags & LIF_CHECKED) CheckItem.Item.Flags |= LIF_CHECKED; else CheckItem.Item.Flags &= ~LIF_CHECKED; Dialog::SendDlgMessage(hDlg, DM_LISTUPDATE, FAD_COMBOBOX_CP, (LONG_PTR)&CheckItem); break; } } } } } break; } case DN_EDITCHANGE: { FarDialogItem &Item=*reinterpret_cast(Param2); switch (Param1) { case FAD_EDIT_TEXT: // Строка "Содержащих текст" if (!FindFoldersChanged) { BOOL Checked = (Item.PtrData && *Item.PtrData)?FALSE:Opt.FindOpt.FindFolders; Dialog::SendDlgMessage(hDlg, DM_SETCHECK, FAD_CHECKBOX_DIRS, Checked?BSTATE_CHECKED:BSTATE_UNCHECKED); } return TRUE; case FAD_COMBOBOX_CP: { // Получаем выбранную в выпадающем списке таблицу символов CodePage = (UINT)Dialog::SendDlgMessage(hDlg, DM_LISTGETDATA, FAD_COMBOBOX_CP, Dialog::SendDlgMessage(hDlg, DM_LISTGETCURPOS, FAD_COMBOBOX_CP, NULL)); } return TRUE; case FAD_COMBOBOX_WHERE: SearchFromChanged=TRUE; return TRUE; } } case DN_HOTKEY: { if (Param1==FAD_TEXT_TEXTHEX) { bool Hex=(Dialog::SendDlgMessage(hDlg,DM_GETCHECK,FAD_CHECKBOX_HEX,NULL)==BSTATE_CHECKED); Dialog::SendDlgMessage(hDlg,DM_SETFOCUS,Hex?FAD_EDIT_HEX:FAD_EDIT_TEXT,0); return FALSE; } } } return Dialog::DefDlgProc(hDlg,Msg,Param1,Param2); } bool GetPluginFile(size_t ArcIndex, const FAR_FIND_DATA_EX *FindData,const wchar_t *DestPath, string &strResultName) { _ALGO(CleverSysLog clv(L"FindFiles::GetPluginFile()")); HANDLE hPlugin=ArcList[ArcIndex]->hPlugin; OpenPluginInfo Info; CtrlObject->Plugins.GetOpenPluginInfo(hPlugin,&Info); string strSaveDir = NullToEmpty(Info.CurDir); AddEndSlash(strSaveDir); CtrlObject->Plugins.SetDirectory(hPlugin,L"\\",OPM_SILENT); //SetPluginDirectory(ArcList[ArcIndex]->strRootPath,hPlugin); SetPluginDirectory(FindData->strFileName,hPlugin); const wchar_t *lpFileNameToFind = PointToName(FindData->strFileName); const wchar_t *lpFileNameToFindShort = PointToName(FindData->strAlternateFileName); PluginPanelItem *pItems; int nItemsNumber; bool nResult=false; if(CtrlObject->Plugins.GetFindData(hPlugin,&pItems,&nItemsNumber,OPM_SILENT)) { for(int i=0;i(PointToName(NullToEmpty(pItems[i].FindData.lpwszFileName))); Item.FindData.lpwszAlternateFileName=const_cast(PointToName(NullToEmpty(pItems[i].FindData.lpwszAlternateFileName))); if(!StrCmp(lpFileNameToFind,Item.FindData.lpwszFileName) && !StrCmp(lpFileNameToFindShort,Item.FindData.lpwszAlternateFileName)) { nResult=(CtrlObject->Plugins.GetFile(hPlugin,&Item,DestPath,strResultName,OPM_SILENT)!=0); break; } } CtrlObject->Plugins.FreeFindData(hPlugin,pItems,nItemsNumber); } CtrlObject->Plugins.SetDirectory(hPlugin,L"\\",OPM_SILENT); //SetPluginDirectory(ArcList[ArcIndex].RootPath,hPlugin); SetPluginDirectory(strSaveDir,hPlugin); return nResult; } size_t AddArcListItem(const wchar_t *ArcName,HANDLE hPlugin,DWORD dwFlags,const wchar_t *RootPath) { if((ArcListCount == ArcListCapacity) && (!ArcListGrow())) return LIST_INDEX_NONE; ArcList[ArcListCount] = new ARCLIST; ArcList[ArcListCount]->strArcName = ArcName; ArcList[ArcListCount]->hPlugin = hPlugin; ArcList[ArcListCount]->Flags = dwFlags; ArcList[ArcListCount]->strRootPath = RootPath; AddEndSlash(ArcList[ArcListCount]->strRootPath); return ArcListCount++; } size_t AddFindListItem(FAR_FIND_DATA_EX *FindData) { if((FindListCount == FindListCapacity)&&(!FindListGrow())) return LIST_INDEX_NONE; FindList[FindListCount] = new FINDLIST; FindList[FindListCount]->FindData = *FindData; FindList[FindListCount]->ArcIndex = LIST_INDEX_NONE; return FindListCount++; } // Алгоритма Бойера-Мура-Хорспула поиска подстроки (Unicode версия) const int FindStringBMH(const wchar_t* searchBuffer, size_t searchBufferCount) { size_t findStringCount = strFindStr.GetLength(); const wchar_t *buffer = searchBuffer; const wchar_t *findStringLower = CmpCase ? NULL : findString+findStringCount; size_t lastBufferChar = findStringCount-1; while (searchBufferCount>=findStringCount) { for (size_t index = lastBufferChar; buffer[index]==findString[index] || (CmpCase ? 0 : buffer[index]==findStringLower[index]); index--) if (index == 0) return static_cast(buffer-searchBuffer); size_t offset = skipCharsTable[buffer[lastBufferChar]]; searchBufferCount -= offset; buffer += offset; } return -1; } // Алгоритма Бойера-Мура-Хорспула поиска подстроки (Char версия) const int FindStringBMH(const unsigned char* searchBuffer, size_t searchBufferCount) { const unsigned char *buffer = searchBuffer; size_t lastBufferChar = hexFindStringSize-1; while (searchBufferCount>=hexFindStringSize) { for (size_t index = lastBufferChar; buffer[index]==hexFindString[index]; index--) if (index == 0) return static_cast(buffer-searchBuffer); size_t offset = skipCharsTable[buffer[lastBufferChar]]; searchBufferCount -= offset; buffer += offset; } return -1; } int LookForString(const wchar_t *Name) { #define RETURN(r) { result = (r); goto exit; } #define CONTINUE(r) { if ((r) || cpIndex==codePagesCount-1) RETURN(r) else continue; } // Длина строки поиска size_t findStringCount; // Если строки поиска пустая, то считаем, что мы всегда что-нибудь найдём if ((findStringCount = strFindStr.GetLength()) == 0) return (TRUE); // Результат поиска BOOL result = FALSE; // Открываем файл HANDLE fileHandle = apiCreateFile( Name, FILE_READ_ATTRIBUTES | FILE_READ_DATA | FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN ); // Время последнего доступа к файлу (нужно для его восстановления после поиска) FILETIME lastAccessTime; // Признак того, что время доуступа к файлу было получено BOOL isTimeReaded = FALSE; // Если файл не удалось открыть изначальным способом, то пытаемся получить к нему // доступ только на чтение, иначе получаем запоминаем последнего доступа к файлу if (fileHandle == INVALID_HANDLE_VALUE) // Открыаем файл только на чтение fileHandle = apiCreateFile( Name, FILE_READ_DATA, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN ); else // Запоминаем время последнего доуступа к файлу isTimeReaded = GetFileTime(fileHandle, NULL, &lastAccessTime, NULL); // Если файл открыть не удалось, то считаем, что ничего не нашли if (fileHandle==INVALID_HANDLE_VALUE) return (FALSE); // Количество считанных из файла байт DWORD readBlockSize = 0; // Количество прочитанных из файла байт unsigned __int64 alreadyRead = _i64(0); // Смещение на которое мы отступили при переходе между блоками int offset=0; if (SearchHex) offset = (int)hexFindStringSize-1; // Основной цикл чтения из файла while (!StopSearch && ReadFile(fileHandle,readBufferA,(!SearchInFirst || alreadyRead+readBufferSizeA<=SearchInFirst)?readBufferSizeA:static_cast(SearchInFirst-alreadyRead),&readBlockSize,NULL)) { // Увеличиваем счётчик прочитыннх байт alreadyRead += readBlockSize; // Для hex и обыкновенного поиска разные ветки if (SearchHex) { // Выходим, если ничего не прочитали или прочитали мало if (readBlockSize == 0 || readBlockSizeMaxCharSize) CONTINUE (FALSE) // Если начало файла очищаем информацию о поиске по словам if (WholeWords && alreadyRead==readBlockSize) { cpi->WordFound = false; cpi->LastSymbol = NULL; } // Если ничего не прочитали if (readBlockSize == 0) // Если поиск по словам и в конце предыдущего блока было что-то найдено, // то считаем, что нашли то, что нужно CONTINUE (WholeWords && cpi->WordFound) // Выходим, если прочитали меньше размера строки поиска и нет поиска по словам if (readBlockSize < findStringCount && !(WholeWords && cpi->WordFound)) CONTINUE (FALSE) // Количество символов в выходном буфере unsigned int bufferCount; // Буфер для поиска wchar_t *buffer; // Перегоняем буфер в UTF-16 if (IsUnicodeCP(cpi->CodePage)) { // Вычисляем размер буфера в UTF-16 bufferCount = readBlockSize/sizeof(wchar_t); // Выходим, если размер буфера меньше длины строки посика if (bufferCount < findStringCount) CONTINUE (FALSE) // Копируем буфер чтения в буфер сравнения if (cpi->CodePage==CP_REVERSEBOM) { // Для UTF-16 (big endian) преобразуем буфер чтения в буфер сравнения bufferCount = LCMapStringW( LOCALE_NEUTRAL,//LOCALE_INVARIANT, LCMAP_BYTEREV, (wchar_t *)readBufferA, (int)bufferCount, readBuffer, readBufferSize ); if (!bufferCount) CONTINUE (FALSE) // Устанавливаем буфер стравнения buffer = readBuffer; } else { // Если поиск в UTF-16 (little endian), то используем исходный буфер buffer = (wchar_t *)readBufferA; } } else { // Конвертируем буфер чтения из кодировки поиска в UTF-16 bufferCount = MultiByteToWideChar( cpi->CodePage, 0, (char *)readBufferA, readBlockSize, readBuffer, readBufferSize ); // Выходим, если нам не удалось сконвертировать строку if (!bufferCount) CONTINUE (FALSE) // Если прочитали меньше размера строки поиска и поиска по словам, то проверяем // первый символ блока на разделитель и выходим // Если у нас поиск по словам и в конце предыдущего блока было вхождение if (WholeWords && cpi->WordFound) { // Если конец файла, то считаем, что есть разделитель в конце if (findStringCount-1>=bufferCount) RETURN (TRUE) // Проверяем первый символ текущего блока с учётом обратного смещения, которое делается // при переходе между блоками cpi->LastSymbol = readBuffer[findStringCount-1]; if (IsWordDiv(cpi->LastSymbol)) RETURN (TRUE) // Если размер буфера меньше размера слова, то выходим if (readBlockSize < findStringCount) CONTINUE (FALSE) } // Устанавливаем буфер стравнения buffer = readBuffer; } unsigned int index = 0; do { // Ищем подстроку в буфере и возвращаем индекс её начала в случае успеха int foundIndex = FindStringBMH(buffer+index, bufferCount-index); // Если подстрока не найдена идём на следующий шаг if (foundIndex == -1) break; // Если посдстрока найдена и отключен поиск по словам, то считаем что всё хорошо if (!WholeWords) RETURN (TRUE) // Устанавливаем позицию в исходном буфере index += foundIndex; // Если идёт поиск по словам, то делаем соответвующие проверки bool firstWordDiv = false; // Если мы находимся вначале блока if (index == 0) { // Если мы находимся вначале файла, то считаем, что разделитель есть // Если мы находимся вначале блока, то проверяем является // или нет последний символ предыдущего блока разделителем if (alreadyRead==readBlockSize || IsWordDiv(cpi->LastSymbol)) firstWordDiv = true; } else { // Проверяем является или нет предыдущий найденому символ блока разделителем cpi->LastSymbol = buffer[index-1]; if (IsWordDiv(cpi->LastSymbol)) firstWordDiv = true; } // Проверяем разделитель в конце, только если найден разделитель вначале if (firstWordDiv) { // Если блок выбран не до конца if (index+findStringCount!=bufferCount) { // Проверяем является или нет последующий за найденым символ блока разделителем cpi->LastSymbol = buffer[index+findStringCount]; if (IsWordDiv(cpi->LastSymbol)) RETURN (TRUE) } else cpi->WordFound = true; } } while (++index<=bufferCount-findStringCount); // Выходим, если мы вышли за пределы количества байт разрешённых для поиска if(SearchInFirst && SearchInFirst>=alreadyRead) CONTINUE (FALSE) // Запоминаем последний символ блока cpi->LastSymbol = buffer[bufferCount-1]; } // Получаем смещение на которое мы отступили при переходе между блоками offset = (int)((CodePage==CP_AUTODETECT?sizeof(wchar_t):codePages->MaxCharSize)*(findStringCount-1)); } // Если мы потенциально прочитали не весь файл if (readBlockSize==readBufferSizeA) { // Отступаем назад на длину слова поиска минус 1 if (!apiSetFilePointerEx(fileHandle, -1*offset, NULL, FILE_CURRENT)) RETURN (FALSE) alreadyRead -= offset; } } exit: // Восстаналиваем время доступа if (isTimeReaded) SetFileTime(fileHandle, NULL, &lastAccessTime, NULL); // Закрываем хэндл файла CloseHandle(fileHandle); // Возвращаем результат return (result); #undef CONTINUE #undef RETURN } bool IsFileIncluded(PluginPanelItem *FileItem,const wchar_t *FullName,DWORD FileAttr) { CriticalSectionLock Lock (ffCS); bool FileFound=FileMaskForFindFile.Compare(FullName); HANDLE hPlugin=FindFileArcIndex == LIST_INDEX_NONE?INVALID_HANDLE_VALUE:ArcList[FindFileArcIndex]->hPlugin; while(FileFound) { /* $ 24.09.2003 KM Если включен режим поиска hex-кодов, тогда папки в поиск не включаем */ /* $ 17.01.2002 VVM ! Поскольку работу с поиском в папках вынесли в диалог - флаг в плагине потерял свою актуальность */ if ((FileAttr & FILE_ATTRIBUTE_DIRECTORY) && ((Opt.FindOpt.FindFolders==0) || SearchHex)) // ((hPlugin == INVALID_HANDLE_VALUE) || // (ArcList[FindFileArcIndex].Flags & OPIF_FINDFOLDERS)==0)) return FALSE; if ( !strFindStr.IsEmpty() && FileFound) { FileFound=false; if (FileAttr & FILE_ATTRIBUTE_DIRECTORY) break; string strSearchFileName; bool RemoveTemp=false; if (hPlugin != INVALID_HANDLE_VALUE) { if (!CtrlObject->Plugins.UseFarCommand(hPlugin, PLUGIN_FARGETFILES)) { string strTempDir; FarMkTempEx(strTempDir); // А проверка на NULL??? apiCreateDirectory(strTempDir,NULL); WaitForSingleObject(hPluginMutex,INFINITE); if (!CtrlObject->Plugins.GetFile(hPlugin,FileItem,strTempDir,strSearchFileName,OPM_SILENT|OPM_FIND)) { ReleaseMutex(hPluginMutex); apiRemoveDirectory(strTempDir); break; } else { ReleaseMutex(hPluginMutex); } RemoveTemp=true; } else { strSearchFileName = strPluginSearchPath + FullName; } } else { strSearchFileName = FullName; } if (LookForString(strSearchFileName)) FileFound=true; if(RemoveTemp) { DeleteFileWithFolder(strSearchFileName); } } break; } return FileFound; } LONG_PTR WINAPI FindFiles::FindDlgProc(HANDLE hDlg,int Msg,int Param1,LONG_PTR Param2) { Dialog* Dlg=reinterpret_cast(hDlg); VMenu *ListBox=Dlg->Item[FD_LISTBOX]->ListPtr; if(StopSearch && TB) { delete TB; TB=NULL; } CriticalSectionLock Lock(Dlg->CS); switch(Msg) { case DN_DRAWDIALOGDONE: { Dialog::DefDlgProc(hDlg,Msg,Param1,Param2); // Переместим фокус на кнопку [Go To] if((FindDirCount || FindFileCount) && !FindPositionChanged) { FindPositionChanged=TRUE; Dialog::SendDlgMessage(hDlg,DM_SETFOCUS,FD_BUTTON_GOTO,0); } // else // ScrBuf.Flush(); return TRUE; } case DN_KEY: { switch(Param2) { case KEY_ESC: case KEY_F10: { if(!StopSearch) { PauseSearch=TRUE; IsProcessAssignMacroKey++; // запретим спец клавиши int LocalRes=TRUE; if (Opt.Confirm.Esc) LocalRes=AbortMessage(); IsProcessAssignMacroKey--; PauseSearch=FALSE; StopSearch=LocalRes; return TRUE; } } break; // Некоторые спец.клавиши все-же обработаем. case KEY_CTRLALTSHIFTPRESS: case KEY_ALTF9: { IsProcessAssignMacroKey--; FrameManager->ProcessKey((DWORD)Param2); IsProcessAssignMacroKey++; return TRUE; } break; case KEY_RIGHT: case KEY_NUMPAD6: case KEY_TAB: { if(Param1==FD_BUTTON_STOP) { FindPositionChanged=TRUE; Dialog::SendDlgMessage(hDlg,DM_SETFOCUS,FD_BUTTON_NEW,0); return TRUE; } } break; case KEY_LEFT: case KEY_NUMPAD4: case KEY_SHIFTTAB: { if(Param1==FD_BUTTON_NEW) { FindPositionChanged=TRUE; Dialog::SendDlgMessage(hDlg,DM_SETFOCUS,FD_BUTTON_STOP,0); return TRUE; } } break; case KEY_UP: case KEY_DOWN: case KEY_NUMPAD8: case KEY_NUMPAD2: case KEY_PGUP: case KEY_PGDN: case KEY_NUMPAD9: case KEY_NUMPAD3: case KEY_HOME: case KEY_END: case KEY_NUMPAD7: case KEY_NUMPAD1: case KEY_MSWHEEL_UP: case KEY_MSWHEEL_DOWN: case KEY_MSWHEEL_LEFT: case KEY_MSWHEEL_RIGHT: { ListBox->ProcessKey((int)Param2); return TRUE; } break; case KEY_F3: case KEY_NUMPAD5: case KEY_SHIFTNUMPAD5: case KEY_F4: { if (ListBox->GetItemCount()==0) { return TRUE; } ffCS.Enter (); size_t ItemIndex = reinterpret_cast(ListBox->GetUserData(NULL,0)); int RemoveTemp=FALSE; int ClosePlugin=FALSE; // Плагины надо закрывать, если открыли. string strSearchFileName; string strTempDir; if (FindList[ItemIndex]->FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { ffCS.Leave (); return TRUE; } // FindFileArcIndex нельзя здесь использовать // Он может быть уже другой. if ((FindList[ItemIndex]->ArcIndex != LIST_INDEX_NONE) && (!(ArcList[FindList[ItemIndex]->ArcIndex]->Flags & OPIF_REALNAMES))) { string strFindArcName = ArcList[FindList[ItemIndex]->ArcIndex]->strArcName; if (ArcList[FindList[ItemIndex]->ArcIndex]->hPlugin == INVALID_HANDLE_VALUE) { LPBYTE Buffer=new BYTE[Opt.PluginMaxReadData]; if (Buffer) { HANDLE hProcessFile=apiCreateFile(strFindArcName,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,NULL,OPEN_EXISTING,0); if(hProcessFile!=INVALID_HANDLE_VALUE) { DWORD ReadSize=0; bool Result=(ReadFile(hProcessFile,Buffer,Opt.PluginMaxReadData,&ReadSize,NULL)!=FALSE); CloseHandle(hProcessFile); if(Result) { int SavePluginsOutput=DisablePluginsOutput; DisablePluginsOutput=TRUE; WaitForSingleObject(hPluginMutex,INFINITE); ArcList[FindList[ItemIndex]->ArcIndex]->hPlugin = CtrlObject->Plugins.OpenFilePlugin(strFindArcName,Buffer,ReadSize,0); ReleaseMutex(hPluginMutex); DisablePluginsOutput=SavePluginsOutput; delete[] Buffer; if (ArcList[FindList[ItemIndex]->ArcIndex]->hPlugin == (HANDLE)-2 || ArcList[FindList[ItemIndex]->ArcIndex]->hPlugin == INVALID_HANDLE_VALUE) { ArcList[FindList[ItemIndex]->ArcIndex]->hPlugin = INVALID_HANDLE_VALUE; ffCS.Leave(); return TRUE; } ClosePlugin = TRUE; } } else { delete[] Buffer; ffCS.Leave(); return TRUE; } } } FarMkTempEx(strTempDir); apiCreateDirectory(strTempDir, NULL); // if (!CtrlObject->Plugins.GetFile(ArcList[FindList[ItemIndex].ArcIndex].hPlugin,&FileItem,TempDir,SearchFileName,OPM_SILENT|OPM_FIND)) WaitForSingleObject(hPluginMutex,INFINITE); if (!GetPluginFile(FindList[ItemIndex]->ArcIndex,&FindList[ItemIndex]->FindData,strTempDir,strSearchFileName)) { apiRemoveDirectory(strTempDir); if (ClosePlugin) { CtrlObject->Plugins.ClosePlugin(ArcList[FindList[ItemIndex]->ArcIndex]->hPlugin); ArcList[FindList[ItemIndex]->ArcIndex]->hPlugin = INVALID_HANDLE_VALUE; } ReleaseMutex(hPluginMutex); ffCS.Leave (); return FALSE; } else { if (ClosePlugin) { CtrlObject->Plugins.ClosePlugin(ArcList[FindList[ItemIndex]->ArcIndex]->hPlugin); ArcList[FindList[ItemIndex]->ArcIndex]->hPlugin = INVALID_HANDLE_VALUE; } ReleaseMutex(hPluginMutex); } RemoveTemp=TRUE; } else { strSearchFileName = FindList[ItemIndex]->FindData.strFileName; if(apiGetFileAttributes(strSearchFileName) == INVALID_FILE_ATTRIBUTES && apiGetFileAttributes(FindList[ItemIndex]->FindData.strAlternateFileName) != INVALID_FILE_ATTRIBUTES) strSearchFileName = FindList[ItemIndex]->FindData.strAlternateFileName; } DWORD FileAttr=apiGetFileAttributes(strSearchFileName); if(FileAttr!=INVALID_FILE_ATTRIBUTES) { string strOldTitle; apiGetConsoleTitle (strOldTitle); if (Param2==KEY_F3 || Param2==KEY_NUMPAD5 || Param2==KEY_SHIFTNUMPAD5) { int ListSize=ListBox->GetItemCount(); NamesList ViewList; // Возьмем все файлы, которые имеют реальные имена... if(Opt.FindOpt.CollectFiles) { for (int I=0;I(ListBox->GetUserData(NULL,0,I))]; if((PtrFindList->ArcIndex == LIST_INDEX_NONE)||(ArcList[PtrFindList->ArcIndex]->Flags & OPIF_REALNAMES)) { // Не учитывали файлы в архивах с OPIF_REALNAMES if ( !PtrFindList->FindData.strFileName.IsEmpty() && !(PtrFindList->FindData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)) ViewList.AddName(PtrFindList->FindData.strFileName, PtrFindList->FindData.strAlternateFileName); } } /* for */ string strCurDir = FindList[ItemIndex]->FindData.strFileName; ViewList.SetCurName(strCurDir); } Dialog::SendDlgMessage(hDlg,DM_SHOWDIALOG,FALSE,0); Dialog::SendDlgMessage(hDlg,DM_ENABLEREDRAW,FALSE,0); { FileViewer ShellViewer (strSearchFileName,FALSE,FALSE,FALSE,-1,NULL,(FindList[ItemIndex]->ArcIndex != LIST_INDEX_NONE)?NULL:(Opt.FindOpt.CollectFiles?&ViewList:NULL)); ShellViewer.SetDynamicallyBorn(FALSE); ShellViewer.SetEnableF6(TRUE); // FindFileArcIndex нельзя здесь использовать // Он может быть уже другой. if ((FindList[ItemIndex]->ArcIndex != LIST_INDEX_NONE) && (!(ArcList[FindList[ItemIndex]->ArcIndex]->Flags & OPIF_REALNAMES))) ShellViewer.SetSaveToSaveAs(TRUE); //!Mutex.Unlock(); ffCS.Leave (); // чтобы поиск продолжался, пока мы тут кнопки давим IsProcessVE_FindFile++; FrameManager->EnterModalEV(); FrameManager->ExecuteModal(); FrameManager->ExitModalEV(); IsProcessVE_FindFile--; ffCS.Enter (); // заставляем рефрешится экран FrameManager->ProcessKey(KEY_CONSOLE_BUFFER_RESIZE); } Dialog::SendDlgMessage(hDlg,DM_ENABLEREDRAW,TRUE,0); Dialog::SendDlgMessage(hDlg,DM_SHOWDIALOG,TRUE,0); } else { Dialog::SendDlgMessage(hDlg,DM_SHOWDIALOG,FALSE,0); Dialog::SendDlgMessage(hDlg,DM_ENABLEREDRAW,FALSE,0); { /* $ 14.08.2002 VVM ! Пока-что запретим из поиска переключаться в активный редактор. К сожалению, манагер на это не способен сейчас int FramePos=FrameManager->FindFrameByFile(MODALTYPE_EDITOR,SearchFileName); int SwitchTo=FALSE; if (FramePos!=-1) { if (!(*FrameManager)[FramePos]->GetCanLoseFocus(TRUE) || Opt.Confirm.AllowReedit) { char MsgFullFileName[NM]; xstrncpy(MsgFullFileName,SearchFileName,sizeof(MsgFullFileName)-1); int MsgCode=Message(0,2,MSG(MFindFileTitle), TruncPathStr(MsgFullFileName,ScrX-16), MSG(MAskReload), MSG(MCurrent),MSG(MNewOpen)); if (MsgCode==0) { SwitchTo=TRUE; } else if (MsgCode==1) { SwitchTo=FALSE; } else { Dialog::SendDlgMessage(hDlg,DM_ENABLEREDRAW,TRUE,0); Dialog::SendDlgMessage(hDlg,DM_SHOWDIALOG,TRUE,0); return TRUE; } } else { SwitchTo=TRUE; } } if (SwitchTo) { (*FrameManager)[FramePos]->SetCanLoseFocus(FALSE); (*FrameManager)[FramePos]->SetDynamicallyBorn(FALSE); FrameManager->ActivateFrame(FramePos); IsProcessVE_FindFile++; FrameManager->EnterModalEV(); FrameManager->ExecuteModal (); FrameManager->ExitModalEV(); // FrameManager->ExecuteNonModal(); IsProcessVE_FindFile--; // заставляем рефрешится экран FrameManager->ProcessKey(KEY_CONSOLE_BUFFER_RESIZE); } else */ { FileEditor ShellEditor (strSearchFileName,CP_AUTODETECT,0); ShellEditor.SetDynamicallyBorn(FALSE); ShellEditor.SetEnableF6 (TRUE); // FindFileArcIndex нельзя здесь использовать // Он может быть уже другой. if ((FindList[ItemIndex]->ArcIndex != LIST_INDEX_NONE) && (!(ArcList[FindList[ItemIndex]->ArcIndex]->Flags & OPIF_REALNAMES))) ShellEditor.SetSaveToSaveAs(TRUE); ffCS.Leave (); // чтобы поиск продолжался, пока мы тут кнопки давим IsProcessVE_FindFile++; FrameManager->EnterModalEV(); FrameManager->ExecuteModal (); FrameManager->ExitModalEV(); IsProcessVE_FindFile--; ffCS.Enter (); // заставляем рефрешится экран FrameManager->ProcessKey(KEY_CONSOLE_BUFFER_RESIZE); } } Dialog::SendDlgMessage(hDlg,DM_ENABLEREDRAW,TRUE,0); Dialog::SendDlgMessage(hDlg,DM_SHOWDIALOG,TRUE,0); } SetConsoleTitle (strOldTitle); } if (RemoveTemp) { DeleteFileWithFolder(strSearchFileName); } ffCS.Leave (); return TRUE; } } return Dialog::DefDlgProc(hDlg,Msg,Param1,Param2); } case DN_BTNCLICK: { FindPositionChanged = TRUE; switch(Param1) { case FD_BUTTON_NEW: { StopSearch=TRUE; FindExitCode=FIND_EXIT_SEARCHAGAIN; return FALSE; } case FD_BUTTON_STOP: { if (StopSearch) return FALSE; StopSearch=TRUE; return TRUE; } case FD_BUTTON_GOTO: { if (!ListBox) { return FALSE; } // Переход будем делать так же после выхода из диалога. // Причину смотри для [ Panel ] if (ListBox->GetItemCount()==0) { return TRUE; } FindExitIndex = (DWORD)(DWORD_PTR)ListBox->GetUserData(NULL, 0); FindExitCode = FIND_EXIT_GOTO; return FALSE; } case FD_BUTTON_VIEW: { FindDlgProc(hDlg,DN_KEY,FD_LISTBOX,KEY_F3); return TRUE; } case FD_BUTTON_PANEL: { if(ListBox) { // На панель будем посылать не в диалоге, а после. // После окончания поиска. Иначе возможна ситуация, когда мы // ищем на панели, потом ее грохаем и создаем новую (а поиск-то // идет!) и в результате ФАР трапается. if (ListBox->GetItemCount()==0) { return TRUE; } FindExitCode=FIND_EXIT_PANEL; FindExitIndex=(DWORD)(DWORD_PTR)ListBox->GetUserData(NULL, 0); } return FALSE; } } break; } case DN_CTLCOLORDLGLIST: { if(Param2) reinterpret_cast(Param2)->Colors[VMenuColorDisabled]=FarColorToReal(COL_DIALOGLISTTEXT); return TRUE; } case DN_CLOSE: { if(Param1==FD_LISTBOX) { FindDlgProc(hDlg,DN_BTNCLICK,FD_BUTTON_GOTO,0); // emulates a [ Go to ] button pressing; } StopSearch=TRUE; return TRUE; } case DN_RESIZECONSOLE: { PCOORD pCoord=reinterpret_cast(Param2); short IncY=pCoord->Y-DlgHeight-3; Dialog::SendDlgMessage(hDlg,DM_ENABLEREDRAW,FALSE,0); for(int i=0;i<=FD_BUTTON_STOP;i++) { Dialog::SendDlgMessage(hDlg,DM_SHOWITEM,i,FALSE); } SMALL_RECT rect; Dialog::SendDlgMessage(hDlg,DM_GETDLGRECT,0,(LONG_PTR)&rect); pCoord->X=rect.Right-rect.Left+1; DlgHeight+=IncY; pCoord->Y=DlgHeight+1; if(IncY>0) { Dialog::SendDlgMessage(hDlg,DM_RESIZEDIALOG,0,(LONG_PTR)pCoord); } for(int i=0;iCp()->ActivePanel; HANDLE hPlugin=ActivePanel->GetPluginHandle(); OpenPluginInfo Info; CtrlObject->Plugins.GetOpenPluginInfo(hPlugin,&Info); FindFileArcIndex = AddArcListItem(Info.HostFile, hPlugin, Info.Flags, Info.CurDir); if (FindFileArcIndex == LIST_INDEX_NONE) return false; if ((Info.Flags & OPIF_REALNAMES)==0) { FindDlg[FD_BUTTON_PANEL].Type=DI_TEXT; FindDlg[FD_BUTTON_PANEL].strData=L""; } } bool AnySetFindList=false; for (int i=0;iPlugins.GetPluginsCount(); i++) { if (CtrlObject->Plugins.GetPlugin(i)->HasSetFindList()) { AnySetFindList=true; break; } } if(!AnySetFindList) { FindDlg[FD_BUTTON_PANEL].Type=DI_TEXT; FindDlg[FD_BUTTON_PANEL].strData=L""; } Dialog Dlg=Dialog(FindDlg,countof(FindDlg),FindDlgProc); // pDlg->SetDynamicallyBorn(); Dlg.SetHelp(L"FindFileResult"); Dlg.SetPosition(-1,-1,DLG_WIDTH+4,DLG_HEIGHT-1+IncY); // Надо бы показать диалог, а то инициализация элементов запаздывает // иногда при поиске и первые элементы не добавляются Dlg.InitDialog(); Dlg.Show(); LastFoundNumber=0; SearchDone=FALSE; StopSearch=FALSE; PauseSearch=FALSE; FindFileCount=FindDirCount=0; FindExitIndex = LIST_INDEX_NONE; FindExitCode = FIND_EXIT_NONE; FindMessageReady=FindCountReady=FindPositionChanged=0; strLastDirName = L""; strFindMessage = L""; HANDLE Threads[]={NULL,NULL}; #define THREAD_WORK 0 #define THREAD_DISPLAY 1 Threads[THREAD_WORK]=CreateThread(NULL,0,PluginMode?PreparePluginList:PrepareFilesList,&Dlg,0,NULL); if(Threads[THREAD_WORK]) { // Нитка для вывода в диалоге информации о ходе поиска Threads[THREAD_DISPLAY]=CreateThread(NULL,0,WriteDialogData,&Dlg,0,NULL); if(Threads[THREAD_DISPLAY]) { TB=new TaskBar; IsProcessAssignMacroKey++; // отключим все спец. клавиши Dlg.Process(); IsProcessAssignMacroKey--; WaitForMultipleObjects(2,Threads,TRUE,INFINITE); CloseHandle(Threads[THREAD_WORK]); CloseHandle(Threads[THREAD_DISPLAY]); switch(FindExitCode) { case FIND_EXIT_SEARCHAGAIN: { return true; } case FIND_EXIT_PANEL: // Отработаем переброску на временную панель { size_t ListSize = FindListCount; PluginPanelItem *PanelItems=new PluginPanelItem[ListSize]; if (PanelItems==NULL) ListSize=0; int ItemsNumber=0; for (size_t i=0;iFindData.strFileName)>0 && FindList[i]->Used) // Добавляем всегда, если имя задано { // Для плагинов с виртуальными именами заменим имя файла на имя архива. // панель сама уберет лишние дубли. bool IsArchive = ((FindList[i]->ArcIndex != LIST_INDEX_NONE) && !(ArcList[FindList[i]->ArcIndex]->Flags&OPIF_REALNAMES)); // Добавляем только файлы или имена архивов или папки когда просили if (IsArchive || (Opt.FindOpt.FindFolders && !SearchHex) || !(FindList[i]->FindData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)) { if (IsArchive) FindList[i]->FindData.strFileName = ArcList[FindList[i]->ArcIndex]->strArcName; PluginPanelItem *pi=&PanelItems[ItemsNumber++]; memset(pi,0,sizeof(*pi)); apiFindDataExToData (&FindList[i]->FindData, &pi->FindData); if (IsArchive) pi->FindData.dwFileAttributes = 0; /* $ 21.03.2002 VVM + Передаем имена каталогов без заключительного "\" */ if (pi->FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { int Length = StrLength(pi->FindData.lpwszFileName); if ((Length) && IsSlash(pi->FindData.lpwszFileName[Length-1])) pi->FindData.lpwszFileName[Length-1] = 0; } } } } HANDLE hNewPlugin=CtrlObject->Plugins.OpenFindListPlugin(PanelItems,ItemsNumber); if (hNewPlugin!=INVALID_HANDLE_VALUE) { Panel *ActivePanel=CtrlObject->Cp()->ActivePanel; Panel *NewPanel=CtrlObject->Cp()->ChangePanel(ActivePanel,FILE_PANEL,TRUE,TRUE); NewPanel->SetPluginMode(hNewPlugin,L"",true); NewPanel->SetVisible(TRUE); NewPanel->Update(0); //if (FindExitIndex != LIST_INDEX_NONE) //NewPanel->GoToFile(FindList[FindExitIndex].FindData.cFileName); NewPanel->Show(); } for (int i = 0; i < ItemsNumber; i++) apiFreeFindData (&PanelItems[i].FindData); delete[] PanelItems; break; } case FIND_EXIT_GOTO: { string strFileName=FindList[FindExitIndex]->FindData.strFileName; Panel *FindPanel=CtrlObject->Cp()->ActivePanel; if (FindList[FindExitIndex]->ArcIndex != LIST_INDEX_NONE) { HANDLE hPlugin = ArcList[FindList[FindExitIndex]->ArcIndex]->hPlugin; if (hPlugin == INVALID_HANDLE_VALUE) { string strArcName = ArcList[FindList[FindExitIndex]->ArcIndex]->strArcName; if(FindPanel->GetType()!=FILE_PANEL) { FindPanel=CtrlObject->Cp()->ChangePanel(FindPanel,FILE_PANEL,TRUE,TRUE); } string strArcPath=strArcName; CutToSlash(strArcPath); FindPanel->SetCurDir(strArcPath,TRUE); hPlugin=((FileList *)FindPanel)->OpenFilePlugin(strArcName,FALSE); if (hPlugin==(HANDLE)-2) hPlugin = INVALID_HANDLE_VALUE; } if (hPlugin != INVALID_HANDLE_VALUE) { OpenPluginInfo Info; CtrlObject->Plugins.GetOpenPluginInfo(hPlugin,&Info); /* $ 19.01.2003 KM Уточнение перехода в нужный каталог плагина. */ if (SearchMode==FFSEARCH_ROOT || SearchMode==FFSEARCH_ALL || SearchMode==FFSEARCH_ALL_BUTNETWORK || SearchMode==FFSEARCH_INPATH) CtrlObject->Plugins.SetDirectory(hPlugin,L"\\",0); SetPluginDirectory(strFileName,hPlugin,TRUE); } } else { string strSetName; size_t Length=strFileName.GetLength(); if(!Length) break; if (Length>1 && IsSlash(strFileName.At(Length-1)) && strFileName.At(Length-2)!=L':') strFileName.SetLength(Length-1); if ( (apiGetFileAttributes(strFileName)==INVALID_FILE_ATTRIBUTES) && (GetLastError () != ERROR_ACCESS_DENIED)) break; { const wchar_t *NamePtr = PointToName(strFileName); strSetName = NamePtr; if(Opt.FindOpt.FindAlternateStreams) { size_t Pos=0; if(strSetName.Pos(Pos,L':')) strSetName.SetLength(Pos); } strFileName.SetLength(NamePtr-(const wchar_t *)strFileName); Length=strFileName.GetLength(); if (Length>1 && IsSlash(strFileName.At(Length-1)) && strFileName.At(Length-2)!=L':') strFileName.SetLength(Length-1); } if ( strFileName.IsEmpty() ) break; if (FindPanel->GetType()!=FILE_PANEL && CtrlObject->Cp()->GetAnotherPanel(FindPanel)->GetType()==FILE_PANEL) FindPanel=CtrlObject->Cp()->GetAnotherPanel(FindPanel); if ((FindPanel->GetType()!=FILE_PANEL) || (FindPanel->GetMode()!=NORMAL_PANEL)) // Сменим панель на обычную файловую... { FindPanel=CtrlObject->Cp()->ChangePanel(FindPanel,FILE_PANEL,TRUE,TRUE); FindPanel->SetVisible(TRUE); FindPanel->Update(0); } /* $ 09.06.2001 IS ! Не меняем каталог, если мы уже в нем находимся. Тем самым добиваемся того, что выделение с элементов панели не сбрасывается. */ { string strDirTmp; FindPanel->GetCurDir(strDirTmp); Length=strDirTmp.GetLength(); if (Length>1 && IsSlash(strDirTmp.At(Length-1)) && strDirTmp.At(Length-2)!=L':') strDirTmp.SetLength(Length-1); if (StrCmpI(strFileName, strDirTmp)) FindPanel->SetCurDir(strFileName,TRUE); } if ( !strSetName.IsEmpty() ) FindPanel->GoToFile(strSetName); FindPanel->Show(); FindPanel->SetFocus(); } break; } } } } return false; } void FindFiles::DoScanTree(HANDLE hDlg,string& strRoot, FAR_FIND_DATA_EX& FindData, string& strFullName) { { ScanTree ScTree(FALSE,!(SearchMode==FFSEARCH_CURRENT_ONLY||SearchMode==FFSEARCH_INPATH),Opt.FindOpt.FindSymLinks); string strSelName; DWORD FileAttr; if (SearchMode==FFSEARCH_SELECTED) CtrlObject->Cp()->ActivePanel->GetSelName(NULL,FileAttr); InitInFileSearch(); while (1) { string strCurRoot; if (SearchMode==FFSEARCH_SELECTED) { if (!CtrlObject->Cp()->ActivePanel->GetSelName(&strSelName,FileAttr)) break; if ((FileAttr & FILE_ATTRIBUTE_DIRECTORY)==0 || TestParentFolderName(strSelName) || StrCmp(strSelName,L".")==0) continue; strCurRoot = strRoot; AddEndSlash(strCurRoot); strCurRoot += strSelName; } else { strCurRoot = strRoot; } ScTree.SetFindPath(strCurRoot,L"*.*"); statusCS.Enter (); strFindMessage = strCurRoot; FindMessageReady=TRUE; statusCS.Leave (); while (!StopSearch && ScTree.GetNextName(&FindData,strFullName)) { while (PauseSearch) { Sleep(1); } bool bContinue=false; WIN32_FIND_STREAM_DATA sd; HANDLE hFindStream=INVALID_HANDLE_VALUE; bool FirstCall=true; string strFindDataFileName=FindData.strFileName; if(Opt.FindOpt.FindAlternateStreams) { hFindStream=apiFindFirstStream(strFullName,FindStreamInfoStandard,&sd); } while(true) { string strFullStreamName=strFullName; if(Opt.FindOpt.FindAlternateStreams) { if(hFindStream!=INVALID_HANDLE_VALUE) { if(!FirstCall) { if(!apiFindNextStream(hFindStream,&sd)) { apiFindStreamClose(hFindStream); break; } } else { FirstCall=false; } LPWSTR NameEnd=wcschr(sd.cStreamName+1,L':'); if(NameEnd) { *NameEnd=L'\0'; } if(sd.cStreamName[1]) // alternate stream { strFullStreamName+=sd.cStreamName; FindData.strFileName=strFindDataFileName+sd.cStreamName; FindData.nFileSize=sd.StreamSize.QuadPart; } } else { if(bContinue) { break; } } } if(UseFilter) { enumFileInFilterType foundType; if (!Filter->FileInFilter(&FindData,&foundType)) { // сюда заходим, если не попали в фильтр или попали в Exclude-фильтр if((FindData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) && foundType==FIFT_EXCLUDE) ScTree.SkipDir(); // скипаем только по Exclude-фильтру, т.к. глубже тоже нужно просмотреть { bContinue=true; if(Opt.FindOpt.FindAlternateStreams) { continue; } else { break; } } } } if(((FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && strFindStr.IsEmpty()) || (!(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && !strFindStr.IsEmpty())) { statusCS.Enter(); strFindMessage = strFullName; FindMessageReady=TRUE; statusCS.Leave(); } if(IsFileIncluded(NULL,strFullStreamName,FindData.dwFileAttributes)) { AddMenuRecord(hDlg,strFullStreamName,&FindData); } if(!Opt.FindOpt.FindAlternateStreams || hFindStream==INVALID_HANDLE_VALUE) { break; } } if(bContinue) { continue; } if (SearchInArchives) ArchiveSearch(hDlg,strFullName); } if (SearchMode!=FFSEARCH_SELECTED) break; } ReleaseInFileSearch(); } } void _cdecl FindFiles::DoPrepareFileList(HANDLE hDlg,string& strRoot, FAR_FIND_DATA_EX& FindData, string& strFullName) { TRY { string *strPathEnv = new string; wchar_t *PathEnv=NULL, *Ptr=NULL; DWORD DiskMask=FarGetLogicalDrives(); //string strRoot; //BUGBUG CtrlObject->CmdLine->GetCurDir(strRoot); if (SearchMode==FFSEARCH_INPATH && strPathEnv) { apiGetEnvironmentVariable(L"PATH",*strPathEnv); PathEnv = strPathEnv->GetBuffer(strPathEnv->GetLength()+1); if (PathEnv) { PathEnv[strPathEnv->GetLength()]=0; Ptr=PathEnv; while (*Ptr) { if (*Ptr==L';') *Ptr=0; ++Ptr; } } Ptr=PathEnv; } for (int CurrentDisk=0;;CurrentDisk++,DiskMask>>=1) { if (SearchMode==FFSEARCH_ALL || SearchMode==FFSEARCH_ALL_BUTNETWORK) { if (DiskMask==0) break; if ((DiskMask & 1)==0) continue; const wchar_t Root[]={L'A'+CurrentDisk,L':',L'\\',L'\0'}; strRoot=Root; int DriveType=FAR_GetDriveType(strRoot); if (DriveType==DRIVE_REMOVABLE || IsDriveTypeCDROM(DriveType) || (DriveType==DRIVE_REMOTE && SearchMode==FFSEARCH_ALL_BUTNETWORK)) { if (DiskMask==1) break; else continue; } } else if (SearchMode==FFSEARCH_ROOT) { GetPathRootOne(strRoot,strRoot); } else if (SearchMode==FFSEARCH_INPATH) { if(!*Ptr) break; strRoot = Ptr; Ptr+=StrLength(Ptr)+1; } DoScanTree(hDlg,strRoot, FindData, strFullName); if (SearchMode!=FFSEARCH_ALL && SearchMode!=FFSEARCH_ALL_BUTNETWORK && SearchMode!=FFSEARCH_INPATH) break; } delete strPathEnv; while (!StopSearch && FindMessageReady) { Sleep(1); } statusCS.Enter (); strFindMessage.Format (MSG(MFindDone),FindFileCount,FindDirCount); SetFarTitle(strFindMessage); SearchDone=TRUE; FindMessageReady=TRUE; statusCS.Leave (); } EXCEPT (xfilter((int)(INT_PTR)INVALID_HANDLE_VALUE,GetExceptionInformation(),NULL,1)) { TerminateProcess( GetCurrentProcess(), 1); } } DWORD WINAPI FindFiles::PrepareFilesList(void *Param) { FAR_FIND_DATA_EX FindData; string strFullName,strRoot; DoPrepareFileList(reinterpret_cast(Param),strRoot, FindData, strFullName); return 0; } void FindFiles::ArchiveSearch(HANDLE hDlg,const wchar_t *ArcName) { _ALGO(CleverSysLog clv(L"FindFiles::ArchiveSearch()")); _ALGO(SysLog(L"ArcName='%s'",(ArcName?ArcName:L"NULL"))); char *Buffer=new char[Opt.PluginMaxReadData]; if ( !Buffer ) { _ALGO(SysLog(L"ERROR: alloc buffer (size=%u)",Opt.PluginMaxReadData)); return; } FILE *ProcessFile=_wfopen(ArcName,L"rb"); if (ProcessFile==NULL) { delete[] Buffer; return; } int ReadSize=(int)fread(Buffer,1,Opt.PluginMaxReadData,ProcessFile); fclose(ProcessFile); int SavePluginsOutput=DisablePluginsOutput; DisablePluginsOutput=TRUE; string strArcName = ArcName; HANDLE hArc=CtrlObject->Plugins.OpenFilePlugin(strArcName,(unsigned char *)Buffer,ReadSize,OPM_FIND); DisablePluginsOutput=SavePluginsOutput; delete[] Buffer; if (hArc==(HANDLE)-2) { BreakMainThread=true; _ALGO(SysLog(L"return: hArc==(HANDLE)-2")); return; } if (hArc==INVALID_HANDLE_VALUE) { _ALGO(SysLog(L"return: hArc==INVALID_HANDLE_VALUE")); return; } int SaveSearchMode=SearchMode; size_t SaveArcIndex = FindFileArcIndex; { SearchMode=FFSEARCH_FROM_CURRENT; OpenPluginInfo Info; CtrlObject->Plugins.GetOpenPluginInfo(hArc,&Info); FindFileArcIndex = AddArcListItem(ArcName, hArc, Info.Flags, Info.CurDir); /* $ 11.12.2001 VVM - Запомним каталог перед поиском в архиве. И если ничего не нашли - не рисуем его снова */ { string strSaveDirName, strSaveSearchPath; size_t SaveListCount = FindListCount; /* $ 19.01.2003 KM Запомним пути поиска в плагине, они могут измениться. */ strSaveSearchPath = strPluginSearchPath; strSaveDirName = strLastDirName; strLastDirName = L""; string strTmp; DoPreparePluginList(hDlg,strTmp,true); strPluginSearchPath = strSaveSearchPath; WaitForSingleObject(hPluginMutex,INFINITE); CtrlObject->Plugins.ClosePlugin(ArcList[FindFileArcIndex]->hPlugin); ArcList[FindFileArcIndex]->hPlugin = INVALID_HANDLE_VALUE; ReleaseMutex(hPluginMutex); if (SaveListCount == FindListCount) strLastDirName = strSaveDirName; } } FindFileArcIndex = SaveArcIndex; SearchMode=SaveSearchMode; } void FindFiles::AddMenuRecord(HANDLE hDlg,const wchar_t *FullName, FAR_FIND_DATA *FindData) { FAR_FIND_DATA_EX fdata; apiFindDataToDataEx (FindData, &fdata); AddMenuRecord(hDlg,FullName,&fdata); } void FindFiles::AddMenuRecord(HANDLE hDlg,const wchar_t *FullName, FAR_FIND_DATA_EX *FindData) { if (!hDlg) return; VMenu *ListBox=reinterpret_cast(hDlg)->Item[1]->ListPtr; if (!ListBox) return; MenuItemEx ListItem; ListItem.Clear(); string strMenuText, strSizeText; string strDateStr, strTimeStr, strDate; if (FindData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { strSizeText.Format (L"%13s", MSG(MFindFileFolder)); } else { wchar_t *wszSizeText = strSizeText.GetBuffer (100); //BUGBUG, function!!! _ui64tow(FindData->nFileSize, wszSizeText, 10); strSizeText.ReleaseBuffer (); } const wchar_t *DisplayName=FindData->strFileName; /* $ 24.03.2002 KM В плагинах принудительно поставим указатель в имени на имя для корректного его отображения в списке, отбросив путь, т.к. некоторые плагины возвращают имя вместе с полным путём, к примеру временная панель. */ if (FindFileArcIndex != LIST_INDEX_NONE) DisplayName=PointToName(DisplayName); string strDisplayName=DisplayName; TruncStrFromEnd(strDisplayName,24); strMenuText.Format (L" %-25.25s%c%13.13s",(LPCWSTR)strDisplayName,BoxSymbols[BS_V1],(const wchar_t*)strSizeText); /* $ 05.10.2003 KM При использовании фильтра по дате будем отображать тот тип даты, который задан в фильтре. $ 24.01.2007 AY Так как теперь есть больше чем один фильтр то этот момент я пока не знаю как красиво сделать. if (UseFilter && Filter->GetParams()->FDate.Used) { switch(Filter->GetParams()->FDate.DateType) { case FDATE_MODIFIED: // Отображаем дату последнего изменения ConvertDate(FindData->ftLastWriteTime,strDateStr,strTimeStr,5); break; case FDATE_CREATED: // Отображаем дату создания ConvertDate(FindData->ftCreationTime,strDateStr,strTimeStr,5); break; case FDATE_OPENED: // Отображаем дату последнего доступа ConvertDate(FindData->ftLastAccessTime,strDateStr,strTimeStr,5); break; } } else */ { // Отображаем дату последнего изменения ConvertDate(FindData->ftLastWriteTime,strDateStr,strTimeStr,5); strDate.Format (L"%c%8.8s%c%5.5s",BoxSymbols[BS_V1],(const wchar_t*)strDateStr,BoxSymbols[BS_V1],(const wchar_t*)strTimeStr); } strMenuText += strDate; /* $ 05.10.2003 KM Отобразим в панели поиска атрибуты найденных файлов */ const wchar_t AttrStr[]= { BoxSymbols[BS_V1], FindData->dwFileAttributes&FILE_ATTRIBUTE_READONLY? L'R':L' ', FindData->dwFileAttributes&FILE_ATTRIBUTE_SYSTEM?L'S':L' ', FindData->dwFileAttributes&FILE_ATTRIBUTE_HIDDEN?L'H':L' ', FindData->dwFileAttributes&FILE_ATTRIBUTE_ARCHIVE?L'A':L' ', FindData->dwFileAttributes&FILE_ATTRIBUTE_REPARSE_POINT? L'L':FindData->dwFileAttributes&FILE_ATTRIBUTE_SPARSE_FILE?L'$':L' ', FindData->dwFileAttributes&FILE_ATTRIBUTE_COMPRESSED?L'C':FindData->dwFileAttributes&FILE_ATTRIBUTE_ENCRYPTED?L'E':L' ', FindData->dwFileAttributes&FILE_ATTRIBUTE_TEMPORARY?L'T':L' ', FindData->dwFileAttributes&FILE_ATTRIBUTE_NOT_CONTENT_INDEXED?L'I':L' ', FindData->dwFileAttributes&FILE_ATTRIBUTE_OFFLINE?L'O':L' ', FindData->dwFileAttributes&FILE_ATTRIBUTE_VIRTUAL?L'V':L' ', 0 }; strMenuText += AttrStr; string strPathName=FullName; { size_t pos; if(LastSlash(strPathName,pos)) strPathName.SetLength(pos); else strPathName.SetLength(0); } AddEndSlash(strPathName); if ( StrCmpI(strPathName,strLastDirName)!=0) { if ( !strLastDirName.IsEmpty() ) { ListItem.Flags|=LIF_SEPARATOR; ListBox->AddItem(&ListItem); ListItem.Flags&=~LIF_SEPARATOR; } ffCS.Enter (); strLastDirName = strPathName; if ((FindFileArcIndex != LIST_INDEX_NONE) && (!(ArcList[FindFileArcIndex]->Flags & OPIF_REALNAMES)) && (!ArcList[FindFileArcIndex]->strArcName.IsEmpty())) { string strArcPathName=ArcList[FindFileArcIndex]->strArcName; strArcPathName+=L":"; if(!IsSlash(strPathName.At(0))) AddEndSlash(strArcPathName); strArcPathName+=(!StrCmp(strPathName,L".\\")?L"\\":(const wchar_t*)strPathName); strPathName = strArcPathName; } ListItem.strName=TruncPathStr(strPathName,DLG_WIDTH-8); size_t ItemIndex = AddFindListItem(FindData); if (ItemIndex != LIST_INDEX_NONE) { // Сбросим данные в FindData. Они там от файла FindList[ItemIndex]->FindData.Clear(); // Используем LastDirName, т.к. PathName уже может быть искажена FindList[ItemIndex]->FindData.strFileName = strLastDirName; /* $ 07.04.2002 KM - Вместо пустого имени используем флаг, в противном случае не работает переход на каталог из списка. Used=0 - Имя не попададёт во временную панель. */ FindList[ItemIndex]->Used=0; // Поставим атрибут у каталога, что-бы он не был файлом :) FindList[ItemIndex]->FindData.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY; if (FindFileArcIndex != LIST_INDEX_NONE) FindList[ItemIndex]->ArcIndex = FindFileArcIndex; ListBox->SetUserData((void*)(DWORD_PTR)ItemIndex,sizeof(ItemIndex),ListBox->AddItem(&ListItem)); } ffCS.Leave (); } /* $ 24.03.2002 KM Дополнительно добавляем в список найденного папки. Так было в 1.65 и в 3 бете, но при полной переделке поиска я это где-то отломил, теперь возвращаю на место. */ ffCS.Enter (); size_t ItemIndex = AddFindListItem(FindData); if (ItemIndex != LIST_INDEX_NONE) { FindList[ItemIndex]->FindData.strFileName = FullName; /* $ 07.04.2002 KM Used=1 - Имя попададёт во временную панель. */ FindList[ItemIndex]->Used=1; if (FindFileArcIndex != LIST_INDEX_NONE) FindList[ItemIndex]->ArcIndex = FindFileArcIndex; } ListItem.strName = strMenuText; ffCS.Leave (); int ListPos = ListBox->AddItem(&ListItem); ListBox->SetUserData((void*)(DWORD_PTR)ItemIndex,sizeof(ItemIndex), ListPos); // Выделим как положено - в списке. if(!FindFileCount && !FindDirCount) ListBox->SetSelectPos(ListPos, -1); statusCS.Enter(); if (FindData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) FindDirCount++; else FindFileCount++; statusCS.Leave(); LastFoundNumber++; FindCountReady=TRUE; } void FindFiles::DoPreparePluginList(HANDLE hDlg,string& strSaveDir,bool Internal) { TRY { Sleep(1); HANDLE hPlugin=ArcList[FindFileArcIndex]->hPlugin; OpenPluginInfo Info; CtrlObject->Plugins.GetOpenPluginInfo(hPlugin,&Info); strSaveDir = Info.CurDir; strPluginSearchPath=Info.CurDir; if (!strPluginSearchPath.IsEmpty()) AddEndSlash(strPluginSearchPath); WaitForSingleObject(hPluginMutex,INFINITE); if (SearchMode==FFSEARCH_ROOT || SearchMode==FFSEARCH_ALL || SearchMode==FFSEARCH_ALL_BUTNETWORK || SearchMode==FFSEARCH_INPATH) CtrlObject->Plugins.SetDirectory(hPlugin,L"\\",OPM_FIND); ReleaseMutex(hPluginMutex); RecurseLevel=0; ScanPluginTree(hDlg,hPlugin,ArcList[FindFileArcIndex]->Flags); WaitForSingleObject(hPluginMutex,INFINITE); if (SearchMode==FFSEARCH_ROOT || SearchMode==FFSEARCH_ALL || SearchMode==FFSEARCH_ALL_BUTNETWORK || SearchMode==FFSEARCH_INPATH) CtrlObject->Plugins.SetDirectory(hPlugin,strSaveDir,OPM_FIND); ReleaseMutex(hPluginMutex); while (!StopSearch && FindMessageReady) { Sleep(1); } if(!Internal) { statusCS.Enter(); strFindMessage.Format(MSG(MFindDone),FindFileCount,FindDirCount); FindMessageReady=TRUE; SearchDone=TRUE; statusCS.Leave(); } } EXCEPT (xfilter((int)(INT_PTR)INVALID_HANDLE_VALUE,GetExceptionInformation(),NULL,1)) { TerminateProcess( GetCurrentProcess(), 1); } } DWORD WINAPI FindFiles::PreparePluginList(void *Param) { string strSaveDir; InitInFileSearch(); DoPreparePluginList(Param, strSaveDir,false); ReleaseInFileSearch(); return 0; } void FindFiles::ScanPluginTree(HANDLE hDlg,HANDLE hPlugin, DWORD Flags) { PluginPanelItem *PanelData=NULL; int ItemCount=0; WaitForSingleObject(hPluginMutex,INFINITE); if (StopSearch || !CtrlObject->Plugins.GetFindData(hPlugin,&PanelData,&ItemCount,OPM_FIND)) { ReleaseMutex(hPluginMutex); return; } else { ReleaseMutex(hPluginMutex); } RecurseLevel++; /* $ 19.01.2003 KM Отключу пока сортировку, что-то результаты получаются не совсем те, которые я ожидал. */ /* $ 24.03.2002 KM Сортировку в плагинах по именам папок делаем в случае, если имя файла содержит в себе путь, а не только при OPIF_REALNAMES, в противном случае в результатах поиска получается некрасивый визуальный эффект разбросанности одинаковых папок по списку. */ // if (PanelData && strlen(PointToName(PanelData->FindData.cFileName))>0) // far_qsort((void *)PanelData,ItemCount,sizeof(*PanelData),SortItems); if (SearchMode!=FFSEARCH_SELECTED || RecurseLevel!=1) { for (int I=0;IFindData.lpwszFileName; string strFullName; if (StrCmp(strCurName,L".")==0 || TestParentFolderName(strCurName)) continue; strFullName = strPluginSearchPath; strFullName += strCurName; /* $ 30.09.2003 KM Отфильтруем файлы не попадающие в действующий фильтр */ if (!UseFilter || Filter->FileInFilter(&CurPanelItem->FindData)) { /* $ 14.06.2004 KM Уточнение действия при обработке каталогов */ if (((CurPanelItem->FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && strFindStr.IsEmpty()) || (!(CurPanelItem->FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && !strFindStr.IsEmpty())) { statusCS.Enter(); strFindMessage = strFullName; FindMessageReady=TRUE; statusCS.Leave(); } if (IsFileIncluded(CurPanelItem,strCurName,CurPanelItem->FindData.dwFileAttributes)) AddMenuRecord(hDlg,strFullName,&CurPanelItem->FindData); if (SearchInArchives && (hPlugin != INVALID_HANDLE_VALUE) && (Flags & OPIF_REALNAMES)) ArchiveSearch(hDlg,strFullName); } } } if (SearchMode!=FFSEARCH_CURRENT_ONLY) { for (int I=0;IFindData.lpwszFileName; if ((CurPanelItem->FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && StrCmp(strCurName,L".")!=0 && !TestParentFolderName(strCurName) && (!UseFilter || Filter->FileInFilter(&CurPanelItem->FindData)) && (SearchMode!=FFSEARCH_SELECTED || RecurseLevel!=1 || CtrlObject->Cp()->ActivePanel->IsSelected(strCurName))) { WaitForSingleObject(hPluginMutex,INFINITE); size_t pos; if (CtrlObject->Plugins.SetDirectory(hPlugin,strCurName,OPM_FIND)) { ReleaseMutex(hPluginMutex); strPluginSearchPath += strCurName; strPluginSearchPath += L"\\"; ScanPluginTree(hDlg, hPlugin, Flags); if (strPluginSearchPath.RPos(pos,L'\\')) strPluginSearchPath.SetLength(pos); if (strPluginSearchPath.RPos(pos,L'\\')) strPluginSearchPath.SetLength(pos+1); else strPluginSearchPath.SetLength(0); WaitForSingleObject(hPluginMutex,INFINITE); if (!CtrlObject->Plugins.SetDirectory(hPlugin,L"..",OPM_FIND)) StopSearch=TRUE; ReleaseMutex(hPluginMutex); } else { ReleaseMutex(hPluginMutex); } } if (StopSearch) break; } } CtrlObject->Plugins.FreeFindData(hPlugin,PanelData,ItemCount); RecurseLevel--; } DWORD WINAPI FindFiles::WriteDialogData(void *Param) { string strDataStr; Dialog* Dlg=reinterpret_cast(Param); HANDLE hDlg=reinterpret_cast(Param); if(Dlg) { while( true ) { VMenu *ListBox=Dlg->Item[1]->ListPtr; if (ListBox && !PauseSearch && !ScreenSaverActive) { if (BreakMainThread) StopSearch=TRUE; if (FindCountReady) { statusCS.Enter (); strDataStr.Format (L" %s: %d ", MSG(MFindFound),FindFileCount+FindDirCount); statusCS.Leave (); Dialog::SendDlgMessage(hDlg,DM_SETTEXTPTR,2,(LONG_PTR)(const wchar_t*)strDataStr); FindCountReady=FALSE; } if (FindMessageReady) { string strSearchStr; if ( !strFindStr.IsEmpty() ) { string strTemp, strFStr; strFStr = strFindStr; TruncStrFromEnd(strFStr,10); strTemp.Format (L" \"%s\"", (const wchar_t*)strFStr); strSearchStr.Format (MSG(MFindSearchingIn), (const wchar_t*)strTemp); } else strSearchStr.Format (MSG(MFindSearchingIn), L""); int Wid1=(int)strSearchStr.GetLength(); int Wid2=DlgWidth-(int)strSearchStr.GetLength()-1; if (SearchDone) { Dialog::SendDlgMessage(hDlg,DM_ENABLEREDRAW,FALSE,0); strDataStr = MSG(MFindCancel); Dialog::SendDlgMessage(hDlg,DM_SETTEXTPTR,9,(LONG_PTR)(const wchar_t*)strDataStr); statusCS.Enter (); strDataStr.Format (L"%-*.*s",DlgWidth,DlgWidth, (const wchar_t*)strFindMessage); statusCS.Leave (); Dialog::SendDlgMessage(hDlg,DM_SETTEXTPTR,3,(LONG_PTR)(const wchar_t*)strDataStr); strDataStr = L""; Dialog::SendDlgMessage(hDlg,DM_SETTEXTPTR,2,(LONG_PTR)(const wchar_t*)strDataStr); Dialog::SendDlgMessage(hDlg,DM_ENABLEREDRAW,TRUE,0); SetFarTitle(strFindMessage); StopSearch=TRUE; } else { statusCS.Enter (); TruncPathStr(strFindMessage, Wid2); strDataStr.Format(L"%-*.*s %-*.*s",Wid1,Wid1, (const wchar_t*)strSearchStr,Wid2,Wid2,(const wchar_t*)strFindMessage); statusCS.Leave (); Dialog::SendDlgMessage(hDlg,DM_SETTEXTPTR,3,(LONG_PTR)(const wchar_t*)strDataStr); } FindMessageReady=FALSE; } if (LastFoundNumber && ListBox) { LastFoundNumber=0; if ( ListBox->UpdateRequired () ) Dialog::SendDlgMessage(hDlg,DM_SHOWITEM,1,1); } } if (StopSearch && SearchDone && !FindMessageReady && !FindCountReady && !LastFoundNumber) break; Sleep(1); } } return 0; } FindFiles::FindFiles() { _ALGO(CleverSysLog clv(L"FindFiles::FindFiles()")); static string strLastFindMask=L"*.*", strLastFindStr; // Статической структуре и статические переменные static string strSearchFromRoot; static int LastCmpCase=0,LastWholeWords=0,LastSearchInArchives=0,LastSearchHex=0; // Создадим объект фильтра Filter=new FileFilter(CtrlObject->Cp()->ActivePanel,FFT_FINDFILE); CmpCase=LastCmpCase; WholeWords=LastWholeWords; SearchInArchives=LastSearchInArchives; SearchHex=LastSearchHex; SearchMode=Opt.FindOpt.FileSearchMode; UseFilter=Opt.FindOpt.UseFilter; strFindMask = strLastFindMask; strFindStr = strLastFindStr; BreakMainThread=false; strSearchFromRoot = MSG(MSearchFromRootFolder); FindList = NULL; ArcList = NULL; hPluginMutex=CreateMutexW(NULL,FALSE,NULL); do { ClearAllLists(); Panel *ActivePanel=CtrlObject->Cp()->ActivePanel; PluginMode=ActivePanel->GetMode()==PLUGIN_PANEL && ActivePanel->IsVisible(); PrepareDriveNameStr(strSearchFromRoot); const wchar_t *MasksHistoryName=L"Masks",*TextHistoryName=L"SearchText"; const wchar_t *HexMask=L"HH HH HH HH HH HH HH HH HH HH HH HH HH HH HH HH HH HH HH HH HH HH HH"; static const wchar_t VSeparator[]={BoxSymbols[BS_T_H1V1],BoxSymbols[BS_V1],BoxSymbols[BS_V1],BoxSymbols[BS_V1],BoxSymbols[BS_B_H1V1],0}; struct DialogDataEx FindAskDlgData[]= { /* 00 */DI_DOUBLEBOX,3,1,74,20,0,0,0,0,(const wchar_t *)MFindFileTitle, /* 01 */DI_TEXT,5,2,0,2,0,0,0,0,(const wchar_t *)MFindFileMasks, /* 02 */DI_EDIT,5,3,72,3,1,(DWORD_PTR)MasksHistoryName,DIF_HISTORY|DIF_USELASTHISTORY,0,L"", /* 03 */DI_TEXT,3,4,0,4,0,0,DIF_BOXCOLOR|DIF_SEPARATOR,0,L"", /* 04 */DI_TEXT,5,5,0,5,0,0,0,0,L"", /* 05 */DI_EDIT,5,6,72,6,0,(DWORD_PTR)TextHistoryName,DIF_HISTORY,0,L"", /* 06 */DI_FIXEDIT,5,6,72,6,0,(DWORD_PTR)HexMask,DIF_MASKEDIT,0,L"", /* 07 */DI_TEXT,5,7,0,7,0,0,0,0,L"", /* 08 */DI_COMBOBOX,5,8,72,8,0,0,DIF_DROPDOWNLIST|DIF_LISTNOAMPERSAND,0,L"", /* 09 */DI_TEXT,3,9,0,9,0,0,DIF_BOXCOLOR|DIF_SEPARATOR,0,L"", /* 10 */DI_CHECKBOX,5,10,0,10,0,0,0,0,(const wchar_t *)MFindFileCase, /* 11 */DI_CHECKBOX,5,11,0,11,0,0,0,0,(const wchar_t *)MFindFileWholeWords, /* 12 */DI_CHECKBOX,5,12,0,12,0,0,0,0,(const wchar_t *)MSearchForHex, /* 13 */DI_CHECKBOX,40,10,0,10,0,0,0,0,(const wchar_t *)MFindArchives, /* 14 */DI_CHECKBOX,40,11,0,11,0,0,0,0,(const wchar_t *)MFindFolders, /* 15 */DI_CHECKBOX,40,12,0,12,0,0,0,0,(const wchar_t *)MFindSymLinks, /* 16 */DI_TEXT,3,13,0,13,0,0,DIF_BOXCOLOR|DIF_SEPARATOR,0,L"", /* 17 */DI_VTEXT,38,9,0,9,0,0,DIF_BOXCOLOR,0,VSeparator, /* 18 */DI_TEXT,5,14,0,14,0,0,0,0,(const wchar_t *)MSearchWhere, /* 19 */DI_COMBOBOX,5,15,72,15,0,0,DIF_DROPDOWNLIST|DIF_LISTNOAMPERSAND,0,L"", /* 20 */DI_TEXT,3,16,0,16,0,0,DIF_BOXCOLOR|DIF_SEPARATOR,0,L"", /* 21 */DI_CHECKBOX,5,17,0,17,0,0,0,0,(const wchar_t *)MFindUseFilter, /* 22 */DI_TEXT,3,18,0,18,0,0,DIF_BOXCOLOR|DIF_SEPARATOR,0,L"", /* 23 */DI_BUTTON,0,19,0,19,0,0,DIF_CENTERGROUP,1,(const wchar_t *)MFindFileFind, /* 24 */DI_BUTTON,0,19,0,19,0,0,DIF_CENTERGROUP,0,(const wchar_t *)MFindFileDrive, /* 25 */DI_BUTTON,0,19,0,19,0,0,DIF_CENTERGROUP,0,(const wchar_t *)MFindFileSetFilter, /* 26 */DI_BUTTON,0,19,0,19,0,0,DIF_CENTERGROUP,0,(const wchar_t *)MFindFileAdvanced, /* 27 */DI_BUTTON,0,19,0,19,0,0,DIF_CENTERGROUP,0,(const wchar_t *)MCancel, }; MakeDialogItemsEx(FindAskDlgData,FindAskDlg); if ( strFindStr.IsEmpty() ) FindAskDlg[FAD_CHECKBOX_DIRS].Selected=Opt.FindOpt.FindFolders; FarListItem li[]= { {0,MSG(MSearchAllDisks)}, {0,MSG(MSearchAllButNetwork)}, {0,MSG(MSearchInPATH)}, {0,strSearchFromRoot}, {0,MSG(MSearchFromCurrent)}, {0,MSG(MSearchInCurrent)}, {0,MSG(MSearchInSelected)}, }; li[FADC_ALLDISKS+SearchMode].Flags|=LIF_SELECTED; FarList l={countof(li),li}; FindAskDlg[FAD_COMBOBOX_WHERE].ListItems=&l; if(PluginMode) { OpenPluginInfo Info; CtrlObject->Plugins.GetOpenPluginInfo(ActivePanel->GetPluginHandle(),&Info); if(!(Info.Flags & OPIF_REALNAMES)) FindAskDlg[FAD_CHECKBOX_ARC].Flags |= DIF_DISABLE; if(FADC_ALLDISKS+SearchMode==FADC_ALLDISKS || FADC_ALLDISKS+SearchMode==FADC_ALLBUTNET) { li[FADC_ALLDISKS].Flags=0; li[FADC_ALLBUTNET].Flags=0; li[FADC_ROOT].Flags|=LIF_SELECTED; } li[FADC_ALLDISKS].Flags|=LIF_GRAYED; li[FADC_ALLBUTNET].Flags|=LIF_GRAYED; FindAskDlg[FAD_CHECKBOX_LINKS].Selected=0; FindAskDlg[FAD_CHECKBOX_LINKS].Flags|=DIF_DISABLE; } else FindAskDlg[FAD_CHECKBOX_LINKS].Selected=Opt.FindOpt.FindSymLinks; /* $ 14.05.2001 DJ не селектим чекбокс, если нельзя искать в архивах */ if (!(FindAskDlg[FAD_CHECKBOX_ARC].Flags & DIF_DISABLE)) FindAskDlg[FAD_CHECKBOX_ARC].Selected=SearchInArchives; FindAskDlg[FAD_EDIT_MASK].strData = strFindMask; if (SearchHex) FindAskDlg[FAD_EDIT_HEX].strData = strFindStr; else FindAskDlg[FAD_EDIT_TEXT].strData = strFindStr; FindAskDlg[FAD_CHECKBOX_CASE].Selected=CmpCase; FindAskDlg[FAD_CHECKBOX_WHOLEWORDS].Selected=WholeWords; FindAskDlg[FAD_CHECKBOX_HEX].Selected=SearchHex; // Использовать фильтр. KM FindAskDlg[FAD_CHECKBOX_FILTER].Selected=UseFilter?BSTATE_CHECKED:BSTATE_UNCHECKED; int ExitCode; Dialog Dlg(FindAskDlg,countof(FindAskDlg),MainDlgProc); Dlg.SetHelp(L"FindFile"); Dlg.SetPosition(-1,-1,78,22); Dlg.Process(); ExitCode=Dlg.GetExitCode(); //Рефреш текущему времени для фильтра сразу после выхода из диалога Filter->UpdateCurrentTime(); if(ExitCode!=FAD_BUTTON_FIND) { CloseHandle(hPluginMutex); return; } /* Запоминание установленных параметров */ Opt.FindCodePage = CodePage; CmpCase=FindAskDlg[FAD_CHECKBOX_CASE].Selected; WholeWords=FindAskDlg[FAD_CHECKBOX_WHOLEWORDS].Selected; SearchHex=FindAskDlg[FAD_CHECKBOX_HEX].Selected; SearchInArchives=FindAskDlg[FAD_CHECKBOX_ARC].Selected; if (FindFoldersChanged) { Opt.FindOpt.FindFolders=(FindAskDlg[FAD_CHECKBOX_DIRS].Selected==BSTATE_CHECKED); } if (!PluginMode) { Opt.FindOpt.FindSymLinks=(FindAskDlg[FAD_CHECKBOX_LINKS].Selected==BSTATE_CHECKED); } // Запомнить признак использования фильтра. KM UseFilter=(FindAskDlg[FAD_CHECKBOX_FILTER].Selected==BSTATE_CHECKED); Opt.FindOpt.UseFilter=UseFilter; strFindMask = !FindAskDlg[FAD_EDIT_MASK].strData.IsEmpty() ? FindAskDlg[FAD_EDIT_MASK].strData:L"*"; if (SearchHex) { strFindStr = FindAskDlg[FAD_EDIT_HEX].strData; RemoveTrailingSpaces(strFindStr); } else strFindStr = FindAskDlg[FAD_EDIT_TEXT].strData; if ( !strFindStr.IsEmpty()) { strGlobalSearchString = strFindStr; GlobalSearchCase=CmpCase; GlobalSearchWholeWords=WholeWords; GlobalSearchHex=SearchHex; } switch(FindAskDlg[FAD_COMBOBOX_WHERE].ListPos) { case FADC_ALLDISKS: SearchMode=FFSEARCH_ALL; break; case FADC_ALLBUTNET: SearchMode=FFSEARCH_ALL_BUTNETWORK; break; case FADC_PATH: SearchMode=FFSEARCH_INPATH; break; case FADC_ROOT: SearchMode=FFSEARCH_ROOT; break; case FADC_FROMCURRENT: SearchMode=FFSEARCH_FROM_CURRENT; break; case FADC_INCURRENT: SearchMode=FFSEARCH_CURRENT_ONLY; break; case FADC_SELECTED: SearchMode=FFSEARCH_SELECTED; break; } if (SearchFromChanged) { Opt.FindOpt.FileSearchMode=SearchMode; } LastCmpCase=CmpCase; LastWholeWords=WholeWords; LastSearchHex=SearchHex; LastSearchInArchives=SearchInArchives; strLastFindMask = strFindMask; strLastFindStr = strFindStr; if ( !strFindStr.IsEmpty() ) Editor::SetReplaceMode(FALSE); } while (FindFilesProcess()); CloseHandle(hPluginMutex); CtrlObject->Cp()->ActivePanel->SetTitle(); } FindFiles::~FindFiles() { FileMaskForFindFile.Free(); ClearAllLists(); ScrBuf.ResetShadow(); if (Filter) delete Filter; }