From e964988c93786be71a42d2f98d16f59369a3149c Mon Sep 17 00:00:00 2001 From: Alex Alabuzhev Date: Wed, 18 May 2016 21:42:39 +0000 Subject: [PATCH] executor: determine appropriate mode for system associations, system.executor.batchtype dropped --- far/changelog | 8 +- far/config.cpp | 6 -- far/execute.cpp | 240 ++++++++++++++++++++++++----------------------- far/execute.hpp | 2 +- far/filelist.cpp | 139 ++++++++++----------------- far/filetype.cpp | 21 ----- far/filetype.hpp | 1 - far/vbuild.m4 | 2 +- 8 files changed, 179 insertions(+), 240 deletions(-) diff --git a/far/changelog b/far/changelog index 120e681e69..3a61049152 100644 --- a/far/changelog +++ b/far/changelog @@ -1,4 +1,10 @@ -zg 18.05.2016 19:37:11 +0200 - build 4678 +drkns 19.05.2016 00:40:27 +0200 - build 4679 + +1. Продолжение экспериментов с запускателем: + - тип запуска (консольный с ожиданием / тихий без ожидания) теперь определяется и для системных ассоциаций тоже. + - System.Executor.BatchType больше нет, всё должно корректно работать автоматически. + +zg 18.05.2016 19:37:11 +0200 - build 4678 1. при определённых условиях позиция курсора в текущей строке после ECTL_DELETESTRING была неверной. diff --git a/far/config.cpp b/far/config.cpp index 17fa951b39..278620d02f 100644 --- a/far/config.cpp +++ b/far/config.cpp @@ -81,8 +81,6 @@ static const wchar_t WordDiv0[] = L"~!%^&*()+|{}:\"<>?`-=\\[];',./"; // Стандартный набор разделителей для функции Xlat static const wchar_t WordDivForXlat0[] = L" \t!#$%^&*()+|=\\/@?"; -static const wchar_t constBatchExt[] = L".BAT;.CMD;"; - static const int DefaultTabSize = 8; @@ -1889,7 +1887,6 @@ void Options::InitConfigData() {FSSF_PRIVATE, NKeySystemException,L"Used", OPT_DEF(ExceptUsed, false)}, {FSSF_PRIVATE, NKeySystemExecutor,L"~", OPT_DEF(Exec.strHomeDir, L"%FARHOME%")}, - {FSSF_PRIVATE, NKeySystemExecutor,L"BatchType", OPT_DEF(Exec.strExecuteBatchType, constBatchExt)}, {FSSF_PRIVATE, NKeySystemExecutor,L"ExcludeCmds", OPT_DEF(Exec.strExcludeCmds, L"")}, {FSSF_PRIVATE, NKeySystemExecutor,L"FullTitle", OPT_DEF(Exec.ExecuteFullTitle, false)}, {FSSF_PRIVATE, NKeySystemExecutor,L"RestoreCP", OPT_DEF(Exec.RestoreCPAfterExecute, true)}, @@ -2129,9 +2126,6 @@ void Options::Load(const std::vector>& Overridden) Policies.ShowHiddenDrives&=OptPolicies_ShowHiddenDrives; */ - if (Exec.strExecuteBatchType.empty()) // предохраняемся - Exec.strExecuteBatchType=constBatchExt; - xlat_initialize(); FindOpt.OutColumns.clear(); diff --git a/far/execute.cpp b/far/execute.cpp index 18e65f2b6b..7e4b4a19fa 100644 --- a/far/execute.cpp +++ b/far/execute.cpp @@ -49,21 +49,16 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "console.hpp" #include "language.hpp" -struct IMAGE_HEADERS +enum class image_type { - DWORD Signature; - IMAGE_FILE_HEADER FileHeader; - union - { - IMAGE_OPTIONAL_HEADER32 OptionalHeader32; - IMAGE_OPTIONAL_HEADER64 OptionalHeader64; - }; + unknown, + console, + graphical, }; -static bool GetImageSubsystem(const string& FileName,DWORD& ImageSubsystem) +static bool GetImageType(const string& FileName, image_type& ImageType) { - bool Result=false; - ImageSubsystem=IMAGE_SUBSYSTEM_UNKNOWN; + auto Result = image_type::unknown; os::fs::file ModuleFile; if(ModuleFile.Open(FileName, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING)) { @@ -74,91 +69,90 @@ static bool GetImageSubsystem(const string& FileName,DWORD& ImageSubsystem) { if (DOSHeader.e_magic==IMAGE_DOS_SIGNATURE) { - //ImageSubsystem = IMAGE_SUBSYSTEM_DOS_EXECUTABLE; - Result=true; + Result = image_type::console; if (ModuleFile.SetPointer(DOSHeader.e_lfanew,nullptr,FILE_BEGIN)) { - IMAGE_HEADERS PEHeader; + union + { + struct + { + DWORD Signature; + IMAGE_FILE_HEADER FileHeader; + union + { + IMAGE_OPTIONAL_HEADER32 OptionalHeader32; + IMAGE_OPTIONAL_HEADER64 OptionalHeader64; + }; + } + PeHeader; - if (ModuleFile.Read(&PEHeader, sizeof(PEHeader), ReadSize) && ReadSize==sizeof(PEHeader)) + struct + { + WORD Signature; + IMAGE_OS2_HEADER Os2Header; + } + NeHeader; + } + ImageHeader; + + if (ModuleFile.Read(&ImageHeader, sizeof(ImageHeader), ReadSize) && ReadSize==sizeof(ImageHeader)) { - if (PEHeader.Signature==IMAGE_NT_SIGNATURE) + if (ImageHeader.PeHeader.Signature == IMAGE_NT_SIGNATURE) { - switch (PEHeader.OptionalHeader32.Magic) + const auto& PeHeader = ImageHeader.PeHeader; + + if (!(PeHeader.FileHeader.Characteristics & IMAGE_FILE_DLL)) { - case IMAGE_NT_OPTIONAL_HDR32_MAGIC: + auto ImageSubsystem = IMAGE_SUBSYSTEM_UNKNOWN; + + switch (PeHeader.OptionalHeader32.Magic) { - ImageSubsystem=PEHeader.OptionalHeader32.Subsystem; - } - break; + case IMAGE_NT_OPTIONAL_HDR32_MAGIC: + ImageSubsystem = PeHeader.OptionalHeader32.Subsystem; + break; case IMAGE_NT_OPTIONAL_HDR64_MAGIC: - { - ImageSubsystem=PEHeader.OptionalHeader64.Subsystem; + ImageSubsystem = PeHeader.OptionalHeader64.Subsystem; + break; } - break; - /*default: - { - // unknown magic - }*/ + if (ImageSubsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) + { + Result = image_type::graphical; + } } } - else if ((WORD)PEHeader.Signature==IMAGE_OS2_SIGNATURE) + else if (ImageHeader.NeHeader.Signature == IMAGE_OS2_SIGNATURE) { - /* - NE, хмм... а как определить что оно ГУЕВОЕ? - - Andrzej Novosiolov - AN> ориентироваться по флагу "Target operating system" NE-заголовка - AN> (1 байт по смещению 0x36). Если там Windows (значения 2, 4) - подразумеваем - AN> GUI, если OS/2 и прочая экзотика (остальные значения) - подразумеваем консоль. - */ - const auto OS2Hdr = reinterpret_cast(&PEHeader); - if (OS2Hdr->ne_exetyp==2 || OS2Hdr->ne_exetyp==4) + const auto& Os2Header = ImageHeader.NeHeader.Os2Header; + + if (!(HIBYTE(Os2Header.ne_flags) & 0x80)) // DLL or driver { - ImageSubsystem=IMAGE_SUBSYSTEM_WINDOWS_GUI; + enum + { + NE_WINDOWS = 0x2, + NE_WIN386 = 0x4, + }; + + if (Os2Header.ne_exetyp == NE_WIN386 || Os2Header.ne_exetyp == NE_WIN386) + { + Result = image_type::graphical; + } } } - - /*else - { - // unknown signature - }*/ } - - /*else - { - // обломс вышел с чтением следующего заголовка ;-( - }*/ } - - /*else - { - // видимо улетели куда нить в трубу, т.к. dos_head.e_lfanew указал - // слишком в неправдоподобное место (например это чистой воды DOS-файл) - }*/ } - - /*else - { - // это не исполняемый файл - у него нету заголовка MZ, например, NLM-модуль - // TODO: здесь можно разбирать POSIX нотацию, например "/usr/bin/sh" - }*/ } - - /*else - { - // ошибка чтения - }*/ } - /*else + if (Result != image_type::unknown) { - // ошибка открытия - }*/ - return Result; + ImageType = Result; + return true; + } + return false; } static bool IsProperProgID(const string& ProgID) @@ -205,8 +199,8 @@ static bool FindObject(const string& Module, string &strDest, bool &Internal) { string strFullName=Module; LPCWSTR ModuleExt=wcsrchr(PointToName(Module),L'.'); - string strPathExt = os::env::get_pathext(); - const auto PathExtList = split>(strPathExt, STLF_UNIQUE); + const auto strPathExt = L";" + os::env::get_pathext(); + const auto PathExtList = split>(strPathExt, STLF_UNIQUE | STLF_ALLOWEMPTY); for (const auto& i: PathExtList) // первый проход - в текущем каталоге { @@ -403,21 +397,14 @@ static bool RunAsSupported(LPCWSTR Name) return !Extension.empty() && GetShellType(Extension, Type) && os::reg::open_key(HKEY_CLASSES_ROOT, Type.append(L"\\shell\\runas\\command").data(), KEY_QUERY_VALUE); } -/* -по имени файла (по его расширению) получить команду активации -Дополнительно смотрится гуевость команды-активатора -(чтобы не ждать завершения) -*/ - // TODO: rewrite -static const wchar_t *GetShellActionImpl(const string& FileName, string& strAction, DWORD& ImageSubsystem,DWORD& Error) +static const wchar_t* GetShellActionAndAssociatedApplicationImpl(const string& FileName, string& strAction, string& Application, DWORD& Error) { string strValue; string strNewValue; const wchar_t *RetPtr; const wchar_t command_action[]=L"\\command"; Error = ERROR_SUCCESS; - ImageSubsystem = IMAGE_SUBSYSTEM_UNKNOWN; const auto ExtPtr = wcsrchr(FileName.data(), L'.'); if (!ExtPtr) @@ -521,7 +508,6 @@ static const wchar_t *GetShellActionImpl(const string& FileName, string& strActi { strValue += command_action; - // а теперь проверим ГУЕвость запускаемой проги if (os::reg::GetValue(HKEY_CLASSES_ROOT, strValue, L"", strNewValue) && !strNewValue.empty()) { strNewValue = os::env::expand_strings(strNewValue); @@ -544,7 +530,7 @@ static const wchar_t *GetShellActionImpl(const string& FileName, string& strActi strNewValue.resize(pos); } - GetImageSubsystem(strNewValue,ImageSubsystem); + Application = strNewValue; } else { @@ -556,10 +542,10 @@ static const wchar_t *GetShellActionImpl(const string& FileName, string& strActi return RetPtr; } -string GetShellAction(const string& FileName, DWORD& ImageSubsystem, DWORD& Error) +string GetShellActionAndAssociatedApplication(const string& FileName, string& Application, DWORD& Error) { string Action; - return NullToEmpty(GetShellActionImpl(FileName, Action, ImageSubsystem, Error)); + return NullToEmpty(GetShellActionAndAssociatedApplicationImpl(FileName, Action, Application, Error)); } bool GetShellType(const string& Ext, string &strType,ASSOCIATIONTYPE aType) @@ -689,39 +675,53 @@ bool Execute(execute_info& Info, bool FolderRun, bool Silent, const std::functio } else if (Info.ExecMode == Info.detect) { - auto GetSubsystemFromShellAction = [&Verb](const string& Str, DWORD& Subsystem) + auto GetAssociatedImageType = [&Verb](const string& Str, image_type& ImageType) { - if (const auto ExtPtr = wcsrchr(PointToName(Str), L'.')) + if (IsExecutable(Str)) { - if (IsBatchExtType(ExtPtr)) - { - Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI; - return true; - } - else - { - DWORD SaError = 0, SaSubSystem = 0; - Verb = GetShellAction(Str, SaSubSystem, SaError); + // We shouldn't get here if it's a PE image - only if bat / cmd + ImageType = image_type::console; + return true; + } + else + { + DWORD SaError = 0; + string Application; + Verb = GetShellActionAndAssociatedApplication(Str, Application, SaError); - if (!Verb.empty() && SaError != ERROR_NO_ASSOCIATION) - { - Subsystem = SaSubSystem; - return true; - } + if (!Verb.empty() && !Application.empty() && SaError != ERROR_NO_ASSOCIATION) + { + return GetImageType(Application, ImageType); } } return false; }; + auto GetImageTypeFallback = [](image_type& ImageType) + { + // Object is found, but its type is unknown. + // Decision is controversial: + + // - we can say it's console to be ready for some output + // ImageType = image_type::console; + // return true; + + // - we can say it's graphical and launch it in a neat silent way + ImageType = image_type::graphical; + return true; + + // - we can give up and let comspec take it + // return false; + }; + const auto ModuleName = Unquote(os::env::expand_strings(strNewCmdStr)); auto FoundModuleName = ModuleName; bool Internal = false; - DWORD dwSubSystem; - if (FindObject(ModuleName, FoundModuleName, Internal) && - (GetImageSubsystem(FoundModuleName, dwSubSystem) || GetSubsystemFromShellAction(ModuleName, dwSubSystem)) - ) + auto ImageType = image_type::unknown; + + if (FindObject(ModuleName, FoundModuleName, Internal)) { if (Internal) { @@ -729,14 +729,14 @@ bool Execute(execute_info& Info, bool FolderRun, bool Silent, const std::functio Info.ExecMode = Info.external; strNewCmdStr = Info.Command; } - else + else if (GetImageType(FoundModuleName, ImageType) || GetAssociatedImageType(FoundModuleName, ImageType) || GetImageTypeFallback(ImageType)) { // We can run it directly Info.ExecMode = Info.direct; strNewCmdStr = FoundModuleName; strNewCmdPar = os::env::expand_strings(strNewCmdPar); - if (dwSubSystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) + if (ImageType == image_type::graphical) { Silent = true; Info.NewWindow = true; @@ -812,11 +812,12 @@ bool Execute(execute_info& Info, bool FolderRun, bool Silent, const std::functio auto GetVerb = [&Verb](const string& Str) { - DWORD DummySubsystem, DummyError; - return GetShellAction(Str, DummySubsystem, DummyError); + DWORD DummyError; + string DummyString; + return GetShellActionAndAssociatedApplication(Str, DummyString, DummyError); }; - seInfo.lpVerb = IsDirectory? nullptr : (Verb.empty()? Verb = GetVerb(strNewCmdStr) : Verb).data(); + seInfo.lpVerb = IsDirectory? nullptr : EmptyToNull((Verb.empty()? Verb = GetVerb(strNewCmdStr) : Verb).data()); } else { @@ -1249,16 +1250,17 @@ bool ExtractIfExistCommand(string &strCommandText) return Result; } -/* -Проверить "Это батник?" -*/ -bool IsBatchExtType(const string& ExtPtr) +bool IsExecutable(const string& Filename) { - string strExecuteBatchType = os::env::expand_strings(Global->Opt->Exec.strExecuteBatchType); - if (strExecuteBatchType.empty()) - strExecuteBatchType = L".BAT;.CMD"; - const auto BatchExtList = split>(strExecuteBatchType, STLF_UNIQUE); - return std::any_of(CONST_RANGE(BatchExtList, i) {return !StrCmpI(i, ExtPtr);}); + auto DotPos = Filename.find_last_of('.'); + if (DotPos == string::npos || DotPos == Filename.size() - 1) + return false; + + auto Extension = Lower(Filename.substr(DotPos + 1)); + + // these guys have specific association in Windows Registry: "%1" %* + // That means we can't find the associated program etc., so they shall be hard-coded. + return Extension == L"exe" || Extension == L"com" || Extension == L"bat" || Extension == L"cmd"; } bool ExpandOSAliases(string &strStr) diff --git a/far/execute.hpp b/far/execute.hpp index 6b70a007c9..ff94d7b5af 100644 --- a/far/execute.hpp +++ b/far/execute.hpp @@ -41,7 +41,7 @@ void OpenFolderInShell(const string& Folder); bool Execute(struct execute_info& Info, bool FolderRun, bool Silent, const std::function& ConsoleActivator = nullptr); -bool IsBatchExtType(const string&ExtPtr); +bool IsExecutable(const string& Filename); bool ExpandOSAliases(string &strStr); diff --git a/far/filelist.cpp b/far/filelist.cpp index 71293e0a18..43bba401ed 100644 --- a/far/filelist.cpp +++ b/far/filelist.cpp @@ -89,6 +89,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "keybar.hpp" #include "panelctype.hpp" #include "diskmenu.hpp" +#include "execute.hpp" static int ListSortGroups,ListSelectedFirst,ListDirectoriesFirst; static panel_sort ListSortMode(panel_sort::UNSORTED); @@ -1648,9 +1649,7 @@ int FileList::ProcessKey(const Manager::Key& Key) return TRUE; } - ProcessEnter(1,LocalKey==KEY_SHIFTENTER||LocalKey==KEY_SHIFTNUMENTER, true, - LocalKey == KEY_CTRLALTENTER || LocalKey == KEY_RCTRLRALTENTER || LocalKey == KEY_CTRLRALTENTER || LocalKey == KEY_RCTRLALTENTER || - LocalKey == KEY_CTRLALTNUMENTER || LocalKey == KEY_RCTRLRALTNUMENTER || LocalKey == KEY_CTRLRALTNUMENTER || LocalKey == KEY_RCTRLALTNUMENTER, OFP_NORMAL); + ProcessEnter(true, (LocalKey & KEY_SHIFT) != 0, true, (LocalKey & KEY_CTRL || LocalKey & KEY_RCTRL) && (LocalKey & KEY_ALT || LocalKey & KEY_RALT), OFP_NORMAL); return TRUE; } case KEY_CTRLBACKSLASH: @@ -2533,7 +2532,7 @@ int FileList::ProcessKey(const Manager::Key& Key) case KEY_RCTRLSHIFTPGDN: case KEY_CTRLSHIFTNUMPAD3: case KEY_RCTRLSHIFTNUMPAD3: - ProcessEnter(0,0,!(LocalKey&KEY_SHIFT), false, OFP_ALTERNATIVE); + ProcessEnter(false, false, !(LocalKey&KEY_SHIFT), false, OFP_ALTERNATIVE); return TRUE; case KEY_APPS: @@ -2593,47 +2592,41 @@ void FileList::Select(FileListItem& SelItem, int Selection) void FileList::ProcessEnter(bool EnableExec,bool SeparateWindow,bool EnableAssoc, bool RunAs, OPENFILEPLUGINTYPE Type) { - string strFileName, strShortFileName; - if (m_CurFile >= static_cast(m_ListData.size())) return; - FileListItem *CurPtr = &m_ListData[m_CurFile]; - strFileName = CurPtr->strName; - - if (!CurPtr->strShortName.empty()) - strShortFileName = CurPtr->strShortName; - else - strShortFileName = CurPtr->strName; + auto& CurItem = m_ListData[m_CurFile]; + auto strFileName = CurItem.strName; + auto strShortFileName = CurItem.strShortName.empty()? CurItem.strName : CurItem.strShortName; - if (CurPtr->FileAttr & FILE_ATTRIBUTE_DIRECTORY) + if (CurItem.FileAttr & FILE_ATTRIBUTE_DIRECTORY) { - BOOL IsRealName=FALSE; + auto IsRealName = true; if (m_PanelMode == panel_mode::PLUGIN_PANEL) { Global->CtrlObject->Plugins->GetOpenPanelInfo(m_hPlugin, &m_CachedOpenPanelInfo); - IsRealName = m_CachedOpenPanelInfo.Flags&OPIF_REALNAMES; + IsRealName = (m_CachedOpenPanelInfo.Flags & OPIF_REALNAMES) != 0; } // Shift-Enter на каталоге вызывает проводник - if ((m_PanelMode != panel_mode::PLUGIN_PANEL || IsRealName) && SeparateWindow) + if (IsRealName && SeparateWindow) { string strFullPath; - if (!IsAbsolutePath(CurPtr->strName)) + if (!IsAbsolutePath(CurItem.strName)) { strFullPath = m_CurDir; AddEndSlash(strFullPath); /* 23.08.2001 VVM ! SHIFT+ENTER на ".." срабатывает для текущего каталога, а не родительского */ - if (!TestParentFolderName(CurPtr->strName)) - strFullPath += CurPtr->strName; + if (!TestParentFolderName(CurItem.strName)) + strFullPath += CurItem.strName; } else { - strFullPath = CurPtr->strName; + strFullPath = CurItem.strName; } QuoteSpace(strFullPath); @@ -2643,7 +2636,7 @@ void FileList::ProcessEnter(bool EnableExec,bool SeparateWindow,bool EnableAssoc { const auto CheckFullScreen = IsFullScreen(); const auto OldParent = Parent(); - ChangeDir(CurPtr->strName,false,true,CurPtr); + ChangeDir(CurItem.strName, false, true, &CurItem); //"this" может быть удалён в ChangeDir const auto ActivePanel = OldParent->ActivePanel(); @@ -2658,99 +2651,65 @@ void FileList::ProcessEnter(bool EnableExec,bool SeparateWindow,bool EnableAssoc } else { - bool PluginMode = m_PanelMode == panel_mode::PLUGIN_PANEL && !Global->CtrlObject->Plugins->UseFarCommand(m_hPlugin, PLUGIN_FARGETFILE); + const auto PluginMode = m_PanelMode == panel_mode::PLUGIN_PANEL && !Global->CtrlObject->Plugins->UseFarCommand(m_hPlugin, PLUGIN_FARGETFILE); + SCOPE_EXIT{ if (PluginMode) DeleteFileWithFolder(strFileName); }; if (PluginMode) { string strTempDir; - if (!FarMkTempEx(strTempDir)) return; os::CreateDirectory(strTempDir,nullptr); PluginPanelItem PanelItem; - FileListToPluginItem(*CurPtr, PanelItem); - int Result=Global->CtrlObject->Plugins->GetFile(m_hPlugin,&PanelItem,strTempDir,strFileName,OPM_SILENT|OPM_VIEW); - FreePluginPanelItem(PanelItem); + FileListToPluginItem(CurItem, PanelItem); + SCOPE_EXIT{ FreePluginPanelItem(PanelItem); }; - if (!Result) - { - os::RemoveDirectory(strTempDir); + if (!Global->CtrlObject->Plugins->GetFile(m_hPlugin, &PanelItem, strTempDir, strFileName, OPM_SILENT | OPM_VIEW)) return; - } ConvertNameToShort(strFileName,strShortFileName); } - if (EnableExec && SetCurPath() && !SeparateWindow && - ProcessLocalFileTypes(strFileName,strShortFileName,FILETYPE_EXEC,PluginMode)) //?? is was var! - { - if (PluginMode) - DeleteFileWithFolder(strFileName); - - return; - } - - const wchar_t *ExtPtr = wcsrchr(strFileName.data(), L'.'); - int ExeType=FALSE,BatType=FALSE; - if (ExtPtr) + if (EnableExec) { - ExeType=!StrCmpI(ExtPtr, L".exe") || !StrCmpI(ExtPtr, L".com"); - BatType=IsBatchExtType(ExtPtr); - } - - if (EnableExec && (ExeType || BatType)) - { - QuoteSpace(strFileName); - - if (!(Global->Opt->ExcludeCmdHistory&EXCLUDECMDHISTORY_NOTPANEL) && !PluginMode) //AN - Global->CtrlObject->CmdHistory->AddToHistory(strFileName, HR_DEFAULT, nullptr, nullptr, m_CurDir.data()); - - execute_info Info; - Info.Command = strFileName; - Info.WaitMode = PluginMode? Info.wait_finish : Info.no_wait; - Info.NewWindow = SeparateWindow; - Info.RunAs = RunAs; - - Parent()->GetCmdLine()->ExecString(Info); + // Enter + if (!SetCurPath()) + return; - if (PluginMode) - DeleteFileWithFolder(strFileName); - } - else if (SetCurPath()) - { - HANDLE hOpen = nullptr; + if (!SeparateWindow && ProcessLocalFileTypes(strFileName, strShortFileName, FILETYPE_EXEC, PluginMode)) + return; - if (EnableAssoc && - !EnableExec && // не запускаем и не в отдельном окне, - !SeparateWindow && // следовательно это Ctrl-PgDn - ProcessLocalFileTypes(strFileName,strShortFileName,FILETYPE_ALTEXEC, - PluginMode) - ) - { - if (PluginMode) - { - DeleteFileWithFolder(strFileName); - } + const auto IsItExecutable = IsExecutable(strFileName); + if (!IsItExecutable && !SeparateWindow && OpenFilePlugin(&strFileName, TRUE, Type)) return; - } - if (SeparateWindow || (hOpen = OpenFilePlugin(&strFileName,TRUE, Type)) == nullptr || - hOpen==PANEL_STOP) + if (SeparateWindow || Global->Opt->UseRegisteredTypes) { - if (EnableExec && hOpen!=PANEL_STOP) - if (SeparateWindow || Global->Opt->UseRegisteredTypes) - ProcessGlobalFileTypes(strFileName, PluginMode, RunAs); + QuoteSpace(strFileName); - if (PluginMode) - { - DeleteFileWithFolder(strFileName); - } + execute_info Info; + Info.Command = strFileName; + Info.WaitMode = PluginMode? Info.wait_finish : Info.no_wait; + Info.NewWindow = SeparateWindow; + Info.RunAs = RunAs; + + Parent()->GetCmdLine()->ExecString(Info); + + const auto ExclusionFlag = IsItExecutable? EXCLUDECMDHISTORY_NOTPANEL : EXCLUDECMDHISTORY_NOTWINASS; + if (!(Global->Opt->ExcludeCmdHistory & ExclusionFlag) && !PluginMode) + Global->CtrlObject->CmdHistory->AddToHistory(strFileName, HR_DEFAULT, nullptr, nullptr, m_CurDir.data()); } + } + else + { + // CtrlPgDn + if (EnableAssoc && ProcessLocalFileTypes(strFileName, strShortFileName, FILETYPE_ALTEXEC, PluginMode)) + return; - return; + OpenFilePlugin(&strFileName, TRUE, Type); } } } @@ -3135,7 +3094,7 @@ int FileList::ProcessMouse(const MOUSE_EVENT_RECORD *MouseEvent) */ ShowFileList(TRUE); FlushInputBuffer(); - ProcessEnter(true, IntKeyState.ShiftPressed!=0, true, false, OFP_NORMAL); + ProcessEnter(true, IntKeyState.ShiftPressed!=0, true, (IntKeyState.AltPressed || IntKeyState.RightAltPressed) && (IntKeyState.CtrlPressed || IntKeyState.RightCtrlPressed), OFP_NORMAL); return TRUE; } else diff --git a/far/filetype.cpp b/far/filetype.cpp index e4448206b4..654a129015 100644 --- a/far/filetype.cpp +++ b/far/filetype.cpp @@ -273,27 +273,6 @@ bool GetFiletypeOpenMode(int keyPressed, FILETYPE_MODE& mode, bool& shouldForceI return isModeFound; } -void ProcessGlobalFileTypes(const string& Name, bool AlwaysWaitFinish, bool RunAs) -{ - string strName(Name); - QuoteSpace(strName); - - execute_info Info; - Info.Command = strName; - Info.WaitMode = AlwaysWaitFinish? Info.wait_finish : Info.no_wait; - Info.NewWindow = true; - Info.ExecMode = Info.direct; - Info.RunAs = RunAs; - - Global->CtrlObject->CmdLine()->ExecString(Info); - - if (!(Global->Opt->ExcludeCmdHistory&EXCLUDECMDHISTORY_NOTWINASS) && !AlwaysWaitFinish) - { - const auto curDir = Global->CtrlObject->CmdLine()->GetCurDir(); - Global->CtrlObject->CmdHistory->AddToHistory(strName, HR_DEFAULT, nullptr, nullptr, curDir.data()); - } -} - /* Используется для запуска внешнего редактора и вьювера */ diff --git a/far/filetype.hpp b/far/filetype.hpp index aa916861f1..fb90f758a0 100644 --- a/far/filetype.hpp +++ b/far/filetype.hpp @@ -53,7 +53,6 @@ enum FILETYPE_MODE */ bool GetFiletypeOpenMode(int keyPressed, FILETYPE_MODE& mode, bool& shouldForceInternal); -void ProcessGlobalFileTypes(const string& Name, bool AlwaysWaitFinish, bool RunAs); bool ProcessLocalFileTypes(const string& Name, const string& ShortName, FILETYPE_MODE Mode, bool AlwaysWaitFinish); void ProcessExternal(const string& Command, const string& Name, const string& ShortName, bool AlwaysWaitFinish); void EditFileTypes(); diff --git a/far/vbuild.m4 b/far/vbuild.m4 index 233c0b31c5..e412e83e76 100644 --- a/far/vbuild.m4 +++ b/far/vbuild.m4 @@ -1 +1 @@ -m4_define(BUILD,4678)m4_dnl +m4_define(BUILD,4679)m4_dnl