diff options
author | elfmz <fenix1905@tut.by> | 2021-12-31 14:08:45 +0300 |
---|---|---|
committer | elfmz <fenix1905@tut.by> | 2021-12-31 14:08:45 +0300 |
commit | be3e39d471034827e156370b465183248558b668 (patch) | |
tree | 5d2e040450ee2b6c1511b32c251643f00e646932 /far2l/src/plug | |
parent | 6b7b5f7fe480107373a6ef3cbd6ee41378c93642 (diff) |
continue sorting files..
Diffstat (limited to 'far2l/src/plug')
-rw-r--r-- | far2l/src/plug/PluginA.cpp | 1408 | ||||
-rw-r--r-- | far2l/src/plug/PluginA.hpp | 226 | ||||
-rw-r--r-- | far2l/src/plug/PluginW.cpp | 1311 | ||||
-rw-r--r-- | far2l/src/plug/PluginW.hpp | 226 | ||||
-rw-r--r-- | far2l/src/plug/plclass.cpp | 102 | ||||
-rw-r--r-- | far2l/src/plug/plclass.hpp | 194 | ||||
-rw-r--r-- | far2l/src/plug/plugapi.cpp | 2609 | ||||
-rw-r--r-- | far2l/src/plug/plugapi.hpp | 175 | ||||
-rw-r--r-- | far2l/src/plug/plugins.cpp | 2084 | ||||
-rw-r--r-- | far2l/src/plug/plugins.hpp | 288 | ||||
-rw-r--r-- | far2l/src/plug/wrap.cpp | 4089 |
11 files changed, 12712 insertions, 0 deletions
diff --git a/far2l/src/plug/PluginA.cpp b/far2l/src/plug/PluginA.cpp new file mode 100644 index 00000000..76ca5b49 --- /dev/null +++ b/far2l/src/plug/PluginA.cpp @@ -0,0 +1,1408 @@ +/* +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" + +#include "plugins.hpp" +#include "lang.hpp" +#include "keys.hpp" +#include "codepage.hpp" +//#include "flink.hpp" +#include "scantree.hpp" +#include "chgprior.hpp" +#include "constitle.hpp" +#include "cmdline.hpp" +#include "filepanels.hpp" +#include "panel.hpp" +#include "vmenu.hpp" +#include "dialog.hpp" +#include "rdrwdsk.hpp" +#include "savescr.hpp" +#include "ctrlobj.hpp" +#include "scrbuf.hpp" +#include "udlist.hpp" +//#include "farexcpt.hpp" +#include "fileedit.hpp" +#include "RefreshFrameManager.hpp" +#include "InterThreadCall.hpp" +#include "plclass.hpp" +#include "PluginA.hpp" +//#include "localOEM.hpp" +#include "plugapi.hpp" +#include "keyboard.hpp" +#include "message.hpp" +#include "interf.hpp" +#include "clipboard.hpp" +#include "xlat.hpp" +#include "fileowner.hpp" +#include "pathmix.hpp" +#include "dirmix.hpp" +#include "processname.hpp" +#include "mix.hpp" +#include "execute.hpp" +#include "flink.hpp" +#include "ConfigRW.hpp" +#include "wrap.cpp" +#include <KeyFileHelper.h> + +static const char *szCache_Preload = "Preload"; +static const char *szCache_Preopen = "Preopen"; +static const char *szCache_SysID = "SysID"; + +static const char szCache_OpenPlugin[] = "OpenPlugin"; +static const char szCache_OpenFilePlugin[] = "OpenFilePlugin"; +static const char szCache_SetFindList[] = "SetFindList"; +static const char szCache_ProcessEditorInput[] = "ProcessEditorInput"; +static const char szCache_ProcessEditorEvent[] = "ProcessEditorEvent"; +static const char szCache_ProcessViewerEvent[] = "ProcessViewerEvent"; +static const char szCache_ProcessDialogEvent[] = "ProcessDialogEvent"; +static const char szCache_Configure[] = "Configure"; + +static const char NFMP_OpenPlugin[] = "OpenPlugin"; +static const char NFMP_OpenFilePlugin[] = "OpenFilePlugin"; +static const char NFMP_SetFindList[] = "SetFindList"; +static const char NFMP_ProcessEditorInput[] = "ProcessEditorInput"; +static const char NFMP_ProcessEditorEvent[] = "ProcessEditorEvent"; +static const char NFMP_ProcessViewerEvent[] = "ProcessViewerEvent"; +static const char NFMP_ProcessDialogEvent[] = "ProcessDialogEvent"; +static const char NFMP_SetStartupInfo[] = "SetStartupInfo"; +static const char NFMP_ClosePlugin[] = "ClosePlugin"; +static const char NFMP_GetPluginInfo[] = "GetPluginInfo"; +static const char NFMP_GetOpenPluginInfo[] = "GetOpenPluginInfo"; +static const char NFMP_GetFindData[] = "GetFindData"; +static const char NFMP_FreeFindData[] = "FreeFindData"; +static const char NFMP_GetVirtualFindData[] = "GetVirtualFindData"; +static const char NFMP_FreeVirtualFindData[] = "FreeVirtualFindData"; +static const char NFMP_SetDirectory[] = "SetDirectory"; +static const char NFMP_GetFiles[] = "GetFiles"; +static const char NFMP_PutFiles[] = "PutFiles"; +static const char NFMP_DeleteFiles[] = "DeleteFiles"; +static const char NFMP_MakeDirectory[] = "MakeDirectory"; +static const char NFMP_ProcessHostFile[] = "ProcessHostFile"; +static const char NFMP_Configure[] = "Configure"; +static const char NFMP_MayExitFAR[] = "MayExitFAR"; +static const char NFMP_ExitFAR[] = "ExitFAR"; +static const char NFMP_ProcessKey[] = "ProcessKey"; +static const char NFMP_ProcessEvent[] = "ProcessEvent"; +static const char NFMP_Compare[] = "Compare"; +static const char NFMP_GetMinFarVersion[] = "GetMinFarVersion"; + + +static void CheckScreenLock() +{ + if (ScrBuf.GetLockCount() > 0 && !CtrlObject->Macro.PeekKey()) + { + ScrBuf.SetLockCount(0); + ScrBuf.Flush(); + } +} + + + +PluginA::PluginA(PluginManager *owner, const FARString &strModuleName, + const std::string &settingsName, const std::string &moduleID) + : + Plugin(owner, strModuleName, settingsName, moduleID), + pFDPanelItemA(nullptr), + pVFDPanelItemA(nullptr) + //more initialization here!!! +{ + ClearExports(); + memset(&PI,0,sizeof(PI)); + memset(&OPI,0,sizeof(OPI)); +} + +PluginA::~PluginA() +{ + FreePluginInfo(); + FreeOpenPluginInfo(); +} + + +bool PluginA::LoadFromCache() +{ + KeyFileReadSection kfh(PluginsIni(), GetSettingsName()); + + if (!kfh.SectionLoaded()) + return false; + + //PF_PRELOAD plugin, skip cache + if (kfh.GetInt(szCache_Preload) != 0) + return Load(); + + //одинаковые ли бинарники? + if (kfh.GetString("ID") != m_strModuleID) + return false; + + SysID = kfh.GetUInt(szCache_SysID,0); + pOpenPlugin = (PLUGINOPENPLUGIN)(INT_PTR)kfh.GetUInt(szCache_OpenPlugin, 0); + pOpenFilePlugin = (PLUGINOPENFILEPLUGIN)(INT_PTR)kfh.GetUInt(szCache_OpenFilePlugin, 0); + pSetFindList = (PLUGINSETFINDLIST)(INT_PTR)kfh.GetUInt(szCache_SetFindList, 0); + pProcessEditorInput = (PLUGINPROCESSEDITORINPUT)(INT_PTR)kfh.GetUInt(szCache_ProcessEditorInput, 0); + pProcessEditorEvent = (PLUGINPROCESSEDITOREVENT)(INT_PTR)kfh.GetUInt(szCache_ProcessEditorEvent, 0); + pProcessViewerEvent = (PLUGINPROCESSVIEWEREVENT)(INT_PTR)kfh.GetUInt(szCache_ProcessViewerEvent, 0); + pProcessDialogEvent = (PLUGINPROCESSDIALOGEVENT)(INT_PTR)kfh.GetUInt(szCache_ProcessDialogEvent, 0); + pConfigure = (PLUGINCONFIGURE)(INT_PTR)kfh.GetUInt(szCache_Configure, 0); + WorkFlags.Set(PIWF_CACHED); //too much "cached" flags + + if (kfh.GetInt(szCache_Preopen) != 0) + OpenModule(); + + return true; +} + +bool PluginA::SaveToCache() +{ + if (!pGetPluginInfo && + !pOpenPlugin && + !pOpenFilePlugin && + !pSetFindList && + !pProcessEditorInput && + !pProcessEditorEvent && + !pProcessViewerEvent && + !pProcessDialogEvent) + { + return false; + } + + KeyFileHelper kfh(PluginsIni()); + kfh.RemoveSection(GetSettingsName()); + + const std::string &module = m_strModuleName.GetMB(); + + struct stat st{}; + if (stat(module.c_str(), &st) == -1) + { + fprintf(stderr, "%s: stat('%s') error %u\n", + __FUNCTION__, module.c_str(), errno); + return false; + } + + kfh.SetString(GetSettingsName(), "Module", module.c_str()); + + PluginInfo Info{}; + GetPluginInfo(&Info); + SysID = Info.SysID; //LAME!!! + + kfh.SetInt(GetSettingsName(), szCache_Preopen, ((Info.Flags & PF_PREOPEN) != 0)); + + if ((Info.Flags & PF_PRELOAD) != 0) + { + kfh.SetInt(GetSettingsName(), szCache_Preload, 1); + WorkFlags.Change(PIWF_PRELOADED, TRUE); + return true; + } + WorkFlags.Change(PIWF_PRELOADED, FALSE); + + kfh.SetString(GetSettingsName(), "ID", m_strModuleID.c_str()); + + for (int i = 0; i < Info.DiskMenuStringsNumber; i++) + { + kfh.SetString(GetSettingsName(), + StrPrintf(FmtDiskMenuStringD, i).c_str(), + Info.DiskMenuStrings[i]); + } + + for (int i = 0; i < Info.PluginMenuStringsNumber; i++) + { + kfh.SetString(GetSettingsName(), + StrPrintf(FmtPluginMenuStringD, i).c_str(), + Info.PluginMenuStrings[i]); + } + + for (int i = 0; i < Info.PluginConfigStringsNumber; i++) + { + kfh.SetString(GetSettingsName(), + StrPrintf(FmtPluginConfigStringD, i).c_str(), + Info.PluginConfigStrings[i]); + } + + kfh.SetString(GetSettingsName(), "CommandPrefix", Info.CommandPrefix); + kfh.SetUInt(GetSettingsName(), "Flags", Info.Flags); + + kfh.SetUInt(GetSettingsName(), szCache_SysID, SysID); + kfh.SetUInt(GetSettingsName(), szCache_OpenPlugin, pOpenPlugin!=nullptr); + kfh.SetUInt(GetSettingsName(), szCache_OpenFilePlugin, pOpenFilePlugin!=nullptr); + kfh.SetUInt(GetSettingsName(), szCache_SetFindList, pSetFindList!=nullptr); + kfh.SetUInt(GetSettingsName(), szCache_ProcessEditorInput, pProcessEditorInput!=nullptr); + kfh.SetUInt(GetSettingsName(), szCache_ProcessEditorEvent, pProcessEditorEvent!=nullptr); + kfh.SetUInt(GetSettingsName(), szCache_ProcessViewerEvent, pProcessViewerEvent!=nullptr); + kfh.SetUInt(GetSettingsName(), szCache_ProcessDialogEvent, pProcessDialogEvent!=nullptr); + kfh.SetUInt(GetSettingsName(), szCache_Configure, pConfigure!=nullptr); + return true; +} + +bool PluginA::Load() +{ + if (m_Loaded) + return true; + + if (!OpenModule()) + return false; + + m_Loaded = true; + + WorkFlags.Clear(PIWF_CACHED); + GetModuleFN(pSetStartupInfo, NFMP_SetStartupInfo); + GetModuleFN(pOpenPlugin, NFMP_OpenPlugin); + GetModuleFN(pOpenFilePlugin, NFMP_OpenFilePlugin); + GetModuleFN(pClosePlugin, NFMP_ClosePlugin); + GetModuleFN(pGetPluginInfo, NFMP_GetPluginInfo); + GetModuleFN(pGetOpenPluginInfo, NFMP_GetOpenPluginInfo); + GetModuleFN(pGetFindData, NFMP_GetFindData); + GetModuleFN(pFreeFindData, NFMP_FreeFindData); + GetModuleFN(pGetVirtualFindData, NFMP_GetVirtualFindData); + GetModuleFN(pFreeVirtualFindData, NFMP_FreeVirtualFindData); + GetModuleFN(pSetDirectory, NFMP_SetDirectory); + GetModuleFN(pGetFiles, NFMP_GetFiles); + GetModuleFN(pPutFiles, NFMP_PutFiles); + GetModuleFN(pDeleteFiles, NFMP_DeleteFiles); + GetModuleFN(pMakeDirectory, NFMP_MakeDirectory); + GetModuleFN(pProcessHostFile, NFMP_ProcessHostFile); + GetModuleFN(pSetFindList, NFMP_SetFindList); + GetModuleFN(pConfigure, NFMP_Configure); + GetModuleFN(pExitFAR, NFMP_ExitFAR); + GetModuleFN(pMayExitFAR, NFMP_MayExitFAR); + GetModuleFN(pProcessKey, NFMP_ProcessKey); + GetModuleFN(pProcessEvent, NFMP_ProcessEvent); + GetModuleFN(pCompare, NFMP_Compare); + GetModuleFN(pProcessEditorInput, NFMP_ProcessEditorInput); + GetModuleFN(pProcessEditorEvent, NFMP_ProcessEditorEvent); + GetModuleFN(pProcessViewerEvent, NFMP_ProcessViewerEvent); + GetModuleFN(pProcessDialogEvent, NFMP_ProcessDialogEvent); + GetModuleFN(pMinFarVersion, NFMP_GetMinFarVersion); + + bool bUnloaded = false; + if (!CheckMinFarVersion(bUnloaded) || !SetStartupInfo(bUnloaded)) + { + if (!bUnloaded) + Unload(); + + //чтоб не пытаться загрузить опять а то ошибка будет постоянно показываться. + WorkFlags.Set(PIWF_DONTLOADAGAIN); + + return false; + } + + FuncFlags.Set(PICFF_LOADED); + SaveToCache(); + return true; +} + + +static void farDisplayNotificationA(const char *action, const char *object) +{ + DisplayNotification(action, object); +} + +static int farDispatchInterThreadCallsA() +{ + return DispatchInterThreadCalls(); +} + +static void WINAPI farBackgroundTaskA(const char *Info, BOOL Started) +{ + if (Started) + CtrlObject->Plugins.BackroundTaskStarted(MB2Wide(Info).c_str()); + else + CtrlObject->Plugins.BackroundTaskFinished(MB2Wide(Info).c_str()); +} + + +static void CreatePluginStartupInfoA(PluginA *pPlugin, oldfar::PluginStartupInfo *PSI, oldfar::FarStandardFunctions *FSF) +{ + static oldfar::PluginStartupInfo StartupInfo{}; + static oldfar::FarStandardFunctions StandardFunctions{}; + + // заполняем структуру StandardFunctions один раз!!! + if (!StandardFunctions.StructSize) + { + StandardFunctions.StructSize=sizeof(StandardFunctions); + StandardFunctions.sprintf=sprintf; + StandardFunctions.snprintf=snprintf; + StandardFunctions.sscanf=sscanf; + StandardFunctions.qsort=FarQsort; + StandardFunctions.qsortex=FarQsortEx; + StandardFunctions.atoi=FarAtoiA; + StandardFunctions.atoi64=FarAtoi64A; + StandardFunctions.itoa=FarItoaA; + StandardFunctions.itoa64=FarItoa64A; + StandardFunctions.bsearch=FarBsearch; + StandardFunctions.Unquote=UnquoteA; + StandardFunctions.LTrim=RemoveLeadingSpacesA; + StandardFunctions.RTrim=RemoveTrailingSpacesA; + StandardFunctions.Trim=RemoveExternalSpacesA; + StandardFunctions.TruncStr=TruncStrA; + StandardFunctions.TruncPathStr=TruncPathStrA; + StandardFunctions.QuoteSpaceOnly=QuoteSpaceOnlyA; + StandardFunctions.PointToName=PointToNameA; + StandardFunctions.GetPathRoot=GetPathRootA; + StandardFunctions.AddEndSlash=AddEndSlashA; + StandardFunctions.CopyToClipboard=CopyToClipboardA; + StandardFunctions.PasteFromClipboard=PasteFromClipboardA; + StandardFunctions.FarKeyToName=FarKeyToNameA; + StandardFunctions.FarNameToKey=KeyNameToKeyA; + StandardFunctions.FarInputRecordToKey=InputRecordToKeyA; + StandardFunctions.XLat=XlatA; + StandardFunctions.GetFileOwner=GetFileOwnerA; + StandardFunctions.GetNumberOfLinks=GetNumberOfLinksA; + StandardFunctions.FarRecursiveSearch=FarRecursiveSearchA; + StandardFunctions.MkTemp=FarMkTempA; + StandardFunctions.DeleteBuffer=DeleteBufferA; + StandardFunctions.ProcessName=ProcessNameA; + StandardFunctions.MkLink=FarMkLinkA; + StandardFunctions.ConvertNameToReal=ConvertNameToRealA; + StandardFunctions.GetReparsePointInfo=FarGetReparsePointInfoA; + StandardFunctions.ExpandEnvironmentStr=ExpandEnvironmentStrA; + StandardFunctions.Execute = farExecuteA; + StandardFunctions.ExecuteLibrary = farExecuteLibraryA; + StandardFunctions.DisplayNotification = farDisplayNotificationA; + StandardFunctions.DispatchInterThreadCalls = farDispatchInterThreadCallsA; + StandardFunctions.BackgroundTask = farBackgroundTaskA; + } + + if (!StartupInfo.StructSize) + { + StartupInfo.StructSize=sizeof(StartupInfo); + StartupInfo.Menu=FarMenuFnA; + StartupInfo.Dialog=FarDialogFnA; + StartupInfo.GetMsg=FarGetMsgFnA; + StartupInfo.Message=FarMessageFnA; + StartupInfo.Control=FarControlA; + StartupInfo.SaveScreen=FarSaveScreen; + StartupInfo.RestoreScreen=FarRestoreScreen; + StartupInfo.GetDirList=FarGetDirListA; + StartupInfo.GetPluginDirList=FarGetPluginDirListA; + StartupInfo.FreeDirList=FarFreeDirListA; + StartupInfo.Viewer=FarViewerA; + StartupInfo.Editor=FarEditorA; + StartupInfo.CmpName=FarCmpNameA; + StartupInfo.CharTable=FarCharTableA; + StartupInfo.Text=FarTextA; + StartupInfo.EditorControl=FarEditorControlA; + StartupInfo.ViewerControl=FarViewerControlA; + StartupInfo.ShowHelp=FarShowHelpA; + StartupInfo.AdvControl=FarAdvControlA; + StartupInfo.DialogEx=FarDialogExA; + StartupInfo.SendDlgMessage=FarSendDlgMessageA; + StartupInfo.DefDlgProc=FarDefDlgProcA; + StartupInfo.InputBox=FarInputBoxA; + } + + *PSI=StartupInfo; + *FSF=StandardFunctions; + PSI->ModuleNumber=(INT_PTR)pPlugin; + PSI->FSF=FSF; + pPlugin->GetModuleName().GetCharString(PSI->ModuleName,sizeof(PSI->ModuleName)); + PSI->RootKey=nullptr; +} + +struct ExecuteStruct +{ + int id; //function id + union + { + INT_PTR nResult; + HANDLE hResult; + BOOL bResult; + }; + + union + { + INT_PTR nDefaultResult; + HANDLE hDefaultResult; + BOOL bDefaultResult; + }; + + bool bUnloaded; +}; + + +#define EXECUTE_FUNCTION(function, es) \ + { \ + es.nResult = 0; \ + es.nDefaultResult = 0; \ + es.bUnloaded = false; \ + function; \ + } + + +#define EXECUTE_FUNCTION_EX(function, es) \ + { \ + es.bUnloaded = false; \ + es.nResult = 0; \ + es.nResult = (INT_PTR)function; \ + } + + +bool PluginA::SetStartupInfo(bool &bUnloaded) +{ + if (pSetStartupInfo) + { + oldfar::PluginStartupInfo _info; + oldfar::FarStandardFunctions _fsf; + + CreatePluginStartupInfoA(this, &_info, &_fsf); + // скорректируем адреса и плагино-зависимые поля + if (mbRootKey.empty()) + mbRootKey = strRootKey.GetMB(); + _info.RootKey = mbRootKey.c_str(); + ExecuteStruct es; + es.id = EXCEPT_SETSTARTUPINFO; + EXECUTE_FUNCTION(pSetStartupInfo(&_info), es); + + if (es.bUnloaded) + { + bUnloaded = true; + return false; + } + } + + return true; +} + +static void ShowMessageAboutIllegalPluginVersion(const wchar_t* plg,int required) +{ + FARString strMsg1, strMsg2; + strMsg1.Format(MSG(MPlgRequired),(WORD)HIWORD(required),(WORD)LOWORD(required)); + strMsg2.Format(MSG(MPlgRequired2),(WORD)HIWORD(FAR_VERSION),(WORD)LOWORD(FAR_VERSION)); + Message(MSG_WARNING,1,MSG(MError),MSG(MPlgBadVers),plg,strMsg1,strMsg2,MSG(MOk)); +} + + +bool PluginA::CheckMinFarVersion(bool &bUnloaded) +{ + if (pMinFarVersion) + { + ExecuteStruct es; + es.id = EXCEPT_MINFARVERSION; + es.nDefaultResult = 0; + EXECUTE_FUNCTION_EX(pMinFarVersion(), es); + + if (es.bUnloaded) + { + bUnloaded = true; + return false; + } + + DWORD FVer = (DWORD)es.nResult; + + if (LOWORD(FVer) > LOWORD(FAR_VERSION) || + (LOWORD(FVer) == LOWORD(FAR_VERSION) && + HIWORD(FVer) > HIWORD(FAR_VERSION))) + { + ShowMessageAboutIllegalPluginVersion(m_strModuleName,FVer); + return false; + } + } + + return true; +} + +int PluginA::Unload(bool bExitFAR) +{ + int nResult = TRUE; + + if (bExitFAR) + ExitFAR(); + + if (!WorkFlags.Check(PIWF_CACHED)) + ClearExports(); + + CloseModule(); + + m_Loaded = false; + FuncFlags.Clear(PICFF_LOADED); //?? + return nResult; +} + +bool PluginA::IsPanelPlugin() +{ + return pSetFindList || + pGetFindData || + pGetVirtualFindData || + pSetDirectory || + pGetFiles || + pPutFiles || + pDeleteFiles || + pMakeDirectory || + pProcessHostFile || + pProcessKey || + pProcessEvent || + pCompare || + pGetOpenPluginInfo || + pFreeFindData || + pFreeVirtualFindData || + pClosePlugin; +} + +HANDLE PluginA::OpenPlugin(int OpenFrom, INT_PTR Item) +{ + //ChangePriority *ChPriority = new ChangePriority(THREAD_PRIORITY_NORMAL); + + CheckScreenLock(); //?? + + { +// FARString strCurDir; +// CtrlObject->CmdLine->GetCurDir(strCurDir); +// FarChDir(strCurDir); + g_strDirToSet.Clear(); + } + + HANDLE hResult = INVALID_HANDLE_VALUE; + + if (Load() && pOpenPlugin) + { + //CurPluginItem=this; //BUGBUG + ExecuteStruct es; + es.id = EXCEPT_OPENPLUGIN; + es.hDefaultResult = INVALID_HANDLE_VALUE; + es.hResult = INVALID_HANDLE_VALUE; + char *ItemA = nullptr; + + if (Item && (OpenFrom == OPEN_COMMANDLINE || OpenFrom == OPEN_SHORTCUT)) + { + ItemA = UnicodeToAnsi((const wchar_t *)Item); + Item = (INT_PTR)ItemA; + } + + EXECUTE_FUNCTION_EX(pOpenPlugin(OpenFrom,Item), es); + + if (ItemA) free(ItemA); + + hResult = es.hResult; + //CurPluginItem=nullptr; //BUGBUG + /* CtrlObject->Macro.SetRedrawEditor(TRUE); //BUGBUG + + if ( !es.bUnloaded ) + { + + if(OpenFrom == OPEN_EDITOR && + !CtrlObject->Macro.IsExecuting() && + CtrlObject->Plugins.CurEditor && + CtrlObject->Plugins.CurEditor->IsVisible() ) + { + CtrlObject->Plugins.ProcessEditorEvent(EE_REDRAW,EEREDRAW_CHANGE); + CtrlObject->Plugins.ProcessEditorEvent(EE_REDRAW,EEREDRAW_ALL); + CtrlObject->Plugins.CurEditor->Show(); + } + if (hInternal!=INVALID_HANDLE_VALUE) + { + PluginHandle *hPlugin=new PluginHandle; + hPlugin->InternalHandle=es.hResult; + hPlugin->PluginNumber=(INT_PTR)this; + return((HANDLE)hPlugin); + } + else + if ( !g_strDirToSet.IsEmpty() ) + { + CtrlObject->Cp()->ActivePanel->SetCurDir(g_strDirToSet,TRUE); + CtrlObject->Cp()->ActivePanel->Redraw(); + } + } */ + } + +// delete ChPriority; + + return hResult; +} + +////////////////////////////////// + +HANDLE PluginA::OpenFilePlugin( + const wchar_t *Name, + const unsigned char *Data, + int DataSize, + int OpMode +) +{ + HANDLE hResult = INVALID_HANDLE_VALUE; + + if (Load() && pOpenFilePlugin) + { + ExecuteStruct es; + es.id = EXCEPT_OPENFILEPLUGIN; + es.hDefaultResult = INVALID_HANDLE_VALUE; + char *NameA = nullptr; + + if (Name) + NameA = UnicodeToAnsi(Name); + + EXECUTE_FUNCTION_EX(pOpenFilePlugin(NameA, Data, DataSize, OpMode), es); + + if (NameA) free(NameA); + + hResult = es.hResult; + } + + return hResult; +} + + +int PluginA::SetFindList( + HANDLE hPlugin, + const PluginPanelItem *PanelItem, + int ItemsNumber +) +{ + BOOL bResult = FALSE; + + if (pSetFindList) + { + ExecuteStruct es; + es.id = EXCEPT_SETFINDLIST; + es.bDefaultResult = FALSE; + oldfar::PluginPanelItem *PanelItemA = nullptr; + ConvertPanelItemsArrayToAnsi(PanelItem,PanelItemA,ItemsNumber); + EXECUTE_FUNCTION_EX(pSetFindList(hPlugin, PanelItemA, ItemsNumber), es); + FreePanelItemA(PanelItemA,ItemsNumber); + bResult = es.bResult; + } + + return bResult; +} + +int PluginA::ProcessEditorInput( + const INPUT_RECORD *D +) +{ + BOOL bResult = FALSE; + + if (Load() && pProcessEditorInput) + { + ExecuteStruct es; + es.id = EXCEPT_PROCESSEDITORINPUT; + es.bDefaultResult = TRUE; //(TRUE) treat the result as a completed request on exception! + const INPUT_RECORD *Ptr=D; + INPUT_RECORD OemRecord; + + if (Ptr->EventType==KEY_EVENT) + { + OemRecord=*D; + int r = WINPORT(WideCharToMultiByte)(CP_UTF8, 0, &D->Event.KeyEvent.uChar.UnicodeChar, + 1, &OemRecord.Event.KeyEvent.uChar.AsciiChar,1, nullptr, nullptr); + if (r<0) fprintf(stderr, "PluginA::ProcessEditorInput: convert failed\n"); + //CharToOemBuff(&D->Event.KeyEvent.uChar.UnicodeChar,&OemRecord.Event.KeyEvent.uChar.AsciiChar,1); + Ptr=&OemRecord; + } + + EXECUTE_FUNCTION_EX(pProcessEditorInput(Ptr), es); + bResult = es.bResult; + } + + return bResult; +} + +int PluginA::ProcessEditorEvent( + int Event, + PVOID Param +) +{ + if (Load() && pProcessEditorEvent) + { + ExecuteStruct es; + es.id = EXCEPT_PROCESSEDITOREVENT; + es.nDefaultResult = 0; + EXECUTE_FUNCTION_EX(pProcessEditorEvent(Event, Param), es); + (void)es; // supress 'set but not used' warning + } + + return 0; //oops! +} + +int PluginA::ProcessViewerEvent( + int Event, + void *Param +) +{ + if (Load() && pProcessViewerEvent) + { + ExecuteStruct es; + es.id = EXCEPT_PROCESSVIEWEREVENT; + es.nDefaultResult = 0; + EXECUTE_FUNCTION_EX(pProcessViewerEvent(Event, Param), es); + (void)es; // supress 'set but not used' warning + } + + return 0; //oops, again! +} + +int PluginA::ProcessDialogEvent( + int Event, + void *Param +) +{ + BOOL bResult = FALSE; + + if (Load() && pProcessDialogEvent) + { + ExecuteStruct es; + es.id = EXCEPT_PROCESSDIALOGEVENT; + es.bDefaultResult = FALSE; + EXECUTE_FUNCTION_EX(pProcessDialogEvent(Event, Param), es); + bResult = es.bResult; + } + + return bResult; +} + +int PluginA::GetVirtualFindData( + HANDLE hPlugin, + PluginPanelItem **pPanelItem, + int *pItemsNumber, + const wchar_t *Path +) +{ + BOOL bResult = FALSE; + + if (pGetVirtualFindData) + { + ExecuteStruct es; + es.id = EXCEPT_GETVIRTUALFINDDATA; + es.bDefaultResult = FALSE; + pVFDPanelItemA = nullptr; + size_t Size=StrLength(Path)+1; + LPSTR PathA=new char[Size * 4]; + PWZ_to_PZ(Path,PathA, Size * 4); + EXECUTE_FUNCTION_EX(pGetVirtualFindData(hPlugin, &pVFDPanelItemA, pItemsNumber, PathA), es); + bResult = es.bResult; + delete[] PathA; + + if (bResult && *pItemsNumber) + { + ConvertPanelItemA(pVFDPanelItemA, pPanelItem, *pItemsNumber); + } + } + + return bResult; +} + + +void PluginA::FreeVirtualFindData( + HANDLE hPlugin, + PluginPanelItem *PanelItem, + int ItemsNumber +) +{ + FreeUnicodePanelItem(PanelItem, ItemsNumber); + + if (pFreeVirtualFindData && pVFDPanelItemA) + { + ExecuteStruct es; + es.id = EXCEPT_FREEVIRTUALFINDDATA; + EXECUTE_FUNCTION(pFreeVirtualFindData(hPlugin, pVFDPanelItemA, ItemsNumber), es); + pVFDPanelItemA = nullptr; + (void)es; // supress 'set but not used' warning + } +} + + + +int PluginA::GetFiles( + HANDLE hPlugin, + PluginPanelItem *PanelItem, + int ItemsNumber, + int Move, + const wchar_t **DestPath, + int OpMode +) +{ + int nResult = -1; + + if (pGetFiles) + { + ExecuteStruct es; + es.id = EXCEPT_GETFILES; + es.nDefaultResult = -1; + oldfar::PluginPanelItem *PanelItemA = nullptr; + ConvertPanelItemsArrayToAnsi(PanelItem,PanelItemA,ItemsNumber); + char DestA[oldfar::NM]; + PWZ_to_PZ(*DestPath,DestA,sizeof(DestA)); + EXECUTE_FUNCTION_EX(pGetFiles(hPlugin, PanelItemA, ItemsNumber, Move, DestA, OpMode), es); + static wchar_t DestW[oldfar::NM]; + PZ_to_PWZ(DestA,DestW,ARRAYSIZE(DestW)); + *DestPath=DestW; + FreePanelItemA(PanelItemA,ItemsNumber); + nResult = (int)es.nResult; + } + + return nResult; +} + + +int PluginA::PutFiles( + HANDLE hPlugin, + PluginPanelItem *PanelItem, + int ItemsNumber, + int Move, + int OpMode +) +{ + int nResult = -1; + + if (pPutFiles) + { + ExecuteStruct es; + es.id = EXCEPT_PUTFILES; + es.nDefaultResult = -1; + oldfar::PluginPanelItem *PanelItemA = nullptr; + ConvertPanelItemsArrayToAnsi(PanelItem,PanelItemA,ItemsNumber); + EXECUTE_FUNCTION_EX(pPutFiles(hPlugin, PanelItemA, ItemsNumber, Move, OpMode), es); + FreePanelItemA(PanelItemA,ItemsNumber); + nResult = (int)es.nResult; + } + + return nResult; +} + +int PluginA::DeleteFiles( + HANDLE hPlugin, + PluginPanelItem *PanelItem, + int ItemsNumber, + int OpMode +) +{ + BOOL bResult = FALSE; + + if (pDeleteFiles) + { + ExecuteStruct es; + es.id = EXCEPT_DELETEFILES; + es.bDefaultResult = FALSE; + oldfar::PluginPanelItem *PanelItemA = nullptr; + ConvertPanelItemsArrayToAnsi(PanelItem,PanelItemA,ItemsNumber); + EXECUTE_FUNCTION_EX(pDeleteFiles(hPlugin, PanelItemA, ItemsNumber, OpMode), es); + FreePanelItemA(PanelItemA,ItemsNumber); + bResult = (int)es.bResult; + } + + return bResult; +} + + +int PluginA::MakeDirectory( + HANDLE hPlugin, + const wchar_t **Name, + int OpMode +) +{ + int nResult = -1; + + if (pMakeDirectory) + { + ExecuteStruct es; + es.id = EXCEPT_MAKEDIRECTORY; + es.nDefaultResult = -1; + char NameA[oldfar::NM]; + PWZ_to_PZ(*Name,NameA,sizeof(NameA)); + EXECUTE_FUNCTION_EX(pMakeDirectory(hPlugin, NameA, OpMode), es); + static wchar_t NameW[oldfar::NM]; + PZ_to_PWZ(NameA,NameW,ARRAYSIZE(NameW)); + *Name=NameW; + nResult = (int)es.nResult; + } + + return nResult; +} + + +int PluginA::ProcessHostFile( + HANDLE hPlugin, + PluginPanelItem *PanelItem, + int ItemsNumber, + int OpMode +) +{ + BOOL bResult = FALSE; + + if (pProcessHostFile) + { + ExecuteStruct es; + es.id = EXCEPT_PROCESSHOSTFILE; + es.bDefaultResult = FALSE; + oldfar::PluginPanelItem *PanelItemA = nullptr; + ConvertPanelItemsArrayToAnsi(PanelItem,PanelItemA,ItemsNumber); + EXECUTE_FUNCTION_EX(pProcessHostFile(hPlugin, PanelItemA, ItemsNumber, OpMode), es); + FreePanelItemA(PanelItemA,ItemsNumber); + bResult = es.bResult; + } + + return bResult; +} + + +int PluginA::ProcessEvent( + HANDLE hPlugin, + int Event, + PVOID Param +) +{ + BOOL bResult = FALSE; + + if (pProcessEvent) + { + ExecuteStruct es; + es.id = EXCEPT_PROCESSEVENT; + es.bDefaultResult = FALSE; + PVOID ParamA = Param; + + if (Param && (Event == FE_COMMAND || Event == FE_CHANGEVIEWMODE)) + ParamA = (PVOID)UnicodeToAnsi((const wchar_t *)Param); + + EXECUTE_FUNCTION_EX(pProcessEvent(hPlugin, Event, ParamA), es); + + if (ParamA && (Event == FE_COMMAND || Event == FE_CHANGEVIEWMODE)) + free(ParamA); + + bResult = es.bResult; + } + + return bResult; +} + + +int PluginA::Compare( + HANDLE hPlugin, + const PluginPanelItem *Item1, + const PluginPanelItem *Item2, + DWORD Mode +) +{ + int nResult = -2; + + if (pCompare) + { + ExecuteStruct es; + es.id = EXCEPT_COMPARE; + es.nDefaultResult = -2; + oldfar::PluginPanelItem *Item1A = nullptr; + oldfar::PluginPanelItem *Item2A = nullptr; + ConvertPanelItemsArrayToAnsi(Item1,Item1A,1); + ConvertPanelItemsArrayToAnsi(Item2,Item2A,1); + EXECUTE_FUNCTION_EX(pCompare(hPlugin, Item1A, Item2A, Mode), es); + FreePanelItemA(Item1A,1); + FreePanelItemA(Item2A,1); + nResult = (int)es.nResult; + } + + return nResult; +} + + +int PluginA::GetFindData( + HANDLE hPlugin, + PluginPanelItem **pPanelItem, + int *pItemsNumber, + int OpMode +) +{ + BOOL bResult = FALSE; + + if (pGetFindData) + { + ExecuteStruct es; + es.id = EXCEPT_GETFINDDATA; + es.bDefaultResult = FALSE; + pFDPanelItemA = nullptr; + EXECUTE_FUNCTION_EX(pGetFindData(hPlugin, &pFDPanelItemA, pItemsNumber, OpMode), es); + bResult = es.bResult; + + if (bResult && *pItemsNumber) + { + ConvertPanelItemA(pFDPanelItemA, pPanelItem, *pItemsNumber); + } + } + + return bResult; +} + + +void PluginA::FreeFindData( + HANDLE hPlugin, + PluginPanelItem *PanelItem, + int ItemsNumber +) +{ + FreeUnicodePanelItem(PanelItem, ItemsNumber); + + if (pFreeFindData && pFDPanelItemA) + { + ExecuteStruct es; + es.id = EXCEPT_FREEFINDDATA; + EXECUTE_FUNCTION(pFreeFindData(hPlugin, pFDPanelItemA, ItemsNumber), es); + pFDPanelItemA = nullptr; + (void)es; // supress 'set but not used' warning + } +} + +int PluginA::ProcessKey( + HANDLE hPlugin, + int Key, + unsigned int dwControlState +) +{ + BOOL bResult = FALSE; + + if (pProcessKey) + { + ExecuteStruct es; + es.id = EXCEPT_PROCESSKEY; + es.bDefaultResult = TRUE; // do not pass this key to far on exception + EXECUTE_FUNCTION_EX(pProcessKey(hPlugin, Key, dwControlState), es); + bResult = es.bResult; + } + + return bResult; +} + + +void PluginA::ClosePlugin( + HANDLE hPlugin +) +{ + if (pClosePlugin) + { + ExecuteStruct es; + es.id = EXCEPT_CLOSEPLUGIN; + EXECUTE_FUNCTION(pClosePlugin(hPlugin), es); + (void)es; // supress 'set but not used' warning + } + + FreeOpenPluginInfo(); + // m_pManager->m_pCurrentPlugin = (Plugin*)-1; +} + + +int PluginA::SetDirectory( + HANDLE hPlugin, + const wchar_t *Dir, + int OpMode +) +{ + BOOL bResult = FALSE; + + if (pSetDirectory) + { + ExecuteStruct es; + es.id = EXCEPT_SETDIRECTORY; + es.bDefaultResult = FALSE; + char *DirA = UnicodeToAnsi(Dir); + EXECUTE_FUNCTION_EX(pSetDirectory(hPlugin, DirA, OpMode), es); + + if (DirA) free(DirA); + + bResult = es.bResult; + } + + return bResult; +} + +void PluginA::FreeOpenPluginInfo() +{ + if (OPI.CurDir) + free((void *)OPI.CurDir); + + if (OPI.HostFile) + free((void *)OPI.HostFile); + + if (OPI.Format) + free((void *)OPI.Format); + + if (OPI.PanelTitle) + free((void *)OPI.PanelTitle); + + if (OPI.InfoLines && OPI.InfoLinesNumber) + { + FreeUnicodeInfoPanelLines((InfoPanelLine*)OPI.InfoLines,OPI.InfoLinesNumber); + } + + if (OPI.DescrFiles) + { + FreeArrayUnicode((wchar_t**)OPI.DescrFiles); + } + + if (OPI.PanelModesArray) + { + FreeUnicodePanelModes((PanelMode*)OPI.PanelModesArray, OPI.PanelModesNumber); + } + + if (OPI.KeyBar) + { + FreeUnicodeKeyBarTitles((KeyBarTitles*)OPI.KeyBar); + free((void *)OPI.KeyBar); + } + + if (OPI.ShortcutData) + free((void *)OPI.ShortcutData); + + memset(&OPI,0,sizeof(OPI)); +} + +void PluginA::ConvertOpenPluginInfo(oldfar::OpenPluginInfo &Src, OpenPluginInfo *Dest) +{ + FreeOpenPluginInfo(); + OPI.StructSize = sizeof(OPI); + OPI.Flags = Src.Flags; + + if (Src.CurDir) + OPI.CurDir = AnsiToUnicode(Src.CurDir); + + if (Src.HostFile) + OPI.HostFile = AnsiToUnicode(Src.HostFile); + + if (Src.Format) + OPI.Format = AnsiToUnicode(Src.Format); + + if (Src.PanelTitle) + OPI.PanelTitle = AnsiToUnicode(Src.PanelTitle); + + if (Src.InfoLines && Src.InfoLinesNumber) + { + ConvertInfoPanelLinesA(Src.InfoLines, (InfoPanelLine**)&OPI.InfoLines, Src.InfoLinesNumber); + OPI.InfoLinesNumber = Src.InfoLinesNumber; + } + + if (Src.DescrFiles && Src.DescrFilesNumber) + { + OPI.DescrFiles = ArrayAnsiToUnicode((char**)Src.DescrFiles, Src.DescrFilesNumber); + OPI.DescrFilesNumber = Src.DescrFilesNumber; + } + + if (Src.PanelModesArray && Src.PanelModesNumber) + { + ConvertPanelModesA(Src.PanelModesArray, (PanelMode**)&OPI.PanelModesArray, Src.PanelModesNumber); + OPI.PanelModesNumber = Src.PanelModesNumber; + OPI.StartPanelMode = Src.StartPanelMode; + OPI.StartSortMode = Src.StartSortMode; + OPI.StartSortOrder = Src.StartSortOrder; + } + + if (Src.KeyBar) + { + OPI.KeyBar=(KeyBarTitles*) malloc(sizeof(KeyBarTitles)); + ConvertKeyBarTitlesA(Src.KeyBar, (KeyBarTitles*)OPI.KeyBar, Src.StructSize>=(int)sizeof(oldfar::OpenPluginInfo)); + } + + if (Src.ShortcutData) + OPI.ShortcutData = AnsiToUnicode(Src.ShortcutData); + + *Dest=OPI; +} + +void PluginA::GetOpenPluginInfo( + HANDLE hPlugin, + OpenPluginInfo *pInfo +) +{ +// m_pManager->m_pCurrentPlugin = this; + pInfo->StructSize = sizeof(OpenPluginInfo); + + if (pGetOpenPluginInfo) + { + ExecuteStruct es; + es.id = EXCEPT_GETOPENPLUGININFO; + oldfar::OpenPluginInfo InfoA{}; + EXECUTE_FUNCTION(pGetOpenPluginInfo(hPlugin, &InfoA), es); + ConvertOpenPluginInfo(InfoA,pInfo); + (void)es; // supress 'set but not used' warning + } +} + + +int PluginA::Configure( + int MenuItem +) +{ + BOOL bResult = FALSE; + + if (Load() && pConfigure) + { + ExecuteStruct es; + es.id = EXCEPT_CONFIGURE; + es.bDefaultResult = FALSE; + EXECUTE_FUNCTION_EX(pConfigure(MenuItem), es); + bResult = es.bResult; + } + + return bResult; +} + +void PluginA::FreePluginInfo() +{ + if (PI.DiskMenuStringsNumber) + { + for (int i=0; i<PI.DiskMenuStringsNumber; i++) + free((void *)PI.DiskMenuStrings[i]); + + free((void *)PI.DiskMenuStrings); + } + + if (PI.PluginMenuStringsNumber) + { + for (int i=0; i<PI.PluginMenuStringsNumber; i++) + free((void *)PI.PluginMenuStrings[i]); + + free((void *)PI.PluginMenuStrings); + } + + if (PI.PluginConfigStringsNumber) + { + for (int i=0; i<PI.PluginConfigStringsNumber; i++) + free((void *)PI.PluginConfigStrings[i]); + + free((void *)PI.PluginConfigStrings); + } + + if (PI.CommandPrefix) + free((void *)PI.CommandPrefix); + + memset(&PI,0,sizeof(PI)); +} + +void PluginA::ConvertPluginInfo(oldfar::PluginInfo &Src, PluginInfo *Dest) +{ + FreePluginInfo(); + PI.StructSize = sizeof(PI); + PI.Flags = Src.Flags; + + if (Src.DiskMenuStringsNumber) + { + wchar_t **p = (wchar_t **) malloc(Src.DiskMenuStringsNumber*sizeof(wchar_t*)); + + for (int i=0; i<Src.DiskMenuStringsNumber; i++) + p[i] = AnsiToUnicode(Src.DiskMenuStrings[i]); + + PI.DiskMenuStrings = p; + PI.DiskMenuStringsNumber = Src.DiskMenuStringsNumber; + } + + if (Src.PluginMenuStringsNumber) + { + wchar_t **p = (wchar_t **) malloc(Src.PluginMenuStringsNumber*sizeof(wchar_t*)); + + for (int i=0; i<Src.PluginMenuStringsNumber; i++) + p[i] = AnsiToUnicode(Src.PluginMenuStrings[i]); + + PI.PluginMenuStrings = p; + PI.PluginMenuStringsNumber = Src.PluginMenuStringsNumber; + } + + if (Src.PluginConfigStringsNumber) + { + wchar_t **p = (wchar_t **) malloc(Src.PluginConfigStringsNumber*sizeof(wchar_t*)); + + for (int i=0; i<Src.PluginConfigStringsNumber; i++) + p[i] = AnsiToUnicode(Src.PluginConfigStrings[i]); + + PI.PluginConfigStrings = p; + PI.PluginConfigStringsNumber = Src.PluginConfigStringsNumber; + } + + if (Src.CommandPrefix) + PI.CommandPrefix = AnsiToUnicode(Src.CommandPrefix); + + *Dest=PI; +} + +bool PluginA::GetPluginInfo(PluginInfo *pi) +{ + memset(pi, 0, sizeof(PluginInfo)); + + if (pGetPluginInfo) + { + ExecuteStruct es; + es.id = EXCEPT_GETPLUGININFO; + oldfar::PluginInfo InfoA{}; + EXECUTE_FUNCTION(pGetPluginInfo(&InfoA), es); + + if (!es.bUnloaded) + { + ConvertPluginInfo(InfoA, pi); + return true; + } + } + + return false; +} + +bool PluginA::MayExitFAR() +{ + if (pMayExitFAR) + { + ExecuteStruct es; + es.id = EXCEPT_MAYEXITFAR; + es.bDefaultResult = 1; + EXECUTE_FUNCTION_EX(pMayExitFAR(), es); + return es.bResult; + } + + return true; +} + +void PluginA::ExitFAR() +{ + if (pExitFAR) + { + ExecuteStruct es; + es.id = EXCEPT_EXITFAR; + EXECUTE_FUNCTION(pExitFAR(), es); + (void)es; // supress 'set but not used' warning + } +} + +void PluginA::ClearExports() +{ + pSetStartupInfo=nullptr; + pOpenPlugin=nullptr; + pOpenFilePlugin=nullptr; + pClosePlugin=nullptr; + pGetPluginInfo=nullptr; + pGetOpenPluginInfo=nullptr; + pGetFindData=nullptr; + pFreeFindData=nullptr; + pGetVirtualFindData=nullptr; + pFreeVirtualFindData=nullptr; + pSetDirectory=nullptr; + pGetFiles=nullptr; + pPutFiles=nullptr; + pDeleteFiles=nullptr; + pMakeDirectory=nullptr; + pProcessHostFile=nullptr; + pSetFindList=nullptr; + pConfigure=nullptr; + pExitFAR=nullptr; + pMayExitFAR=nullptr; + pProcessKey=nullptr; + pProcessEvent=nullptr; + pCompare=nullptr; + pProcessEditorInput=nullptr; + pProcessEditorEvent=nullptr; + pProcessViewerEvent=nullptr; + pProcessDialogEvent=nullptr; + pMinFarVersion=nullptr; +} diff --git a/far2l/src/plug/PluginA.hpp b/far2l/src/plug/PluginA.hpp new file mode 100644 index 00000000..07572609 --- /dev/null +++ b/far2l/src/plug/PluginA.hpp @@ -0,0 +1,226 @@ +#pragma once + +/* +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 "fpsdk/plugin.hpp" +#include "plclass.hpp" +#include "fpsdk/pluginold.hpp" + +typedef void (WINAPI *PLUGINCLOSEPLUGIN)(HANDLE hPlugin); +typedef int (WINAPI *PLUGINCOMPARE)(HANDLE hPlugin,const oldfar::PluginPanelItem *Item1,const oldfar::PluginPanelItem *Item2,unsigned int Mode); +typedef int (WINAPI *PLUGINCONFIGURE)(int ItemNumber); +typedef int (WINAPI *PLUGINDELETEFILES)(HANDLE hPlugin,oldfar::PluginPanelItem *PanelItem,int ItemsNumber,int OpMode); +typedef void (WINAPI *PLUGINEXITFAR)(); +typedef int (WINAPI *PLUGINMAYEXITFAR)(); +typedef void (WINAPI *PLUGINFREEFINDDATA)(HANDLE hPlugin,oldfar::PluginPanelItem *PanelItem,int ItemsNumber); +typedef void (WINAPI *PLUGINFREEVIRTUALFINDDATA)(HANDLE hPlugin,oldfar::PluginPanelItem *PanelItem,int ItemsNumber); +typedef int (WINAPI *PLUGINGETFILES)(HANDLE hPlugin,oldfar::PluginPanelItem *PanelItem,int ItemsNumber,int Move,char *DestPath,int OpMode); +typedef int (WINAPI *PLUGINGETFINDDATA)(HANDLE hPlugin,oldfar::PluginPanelItem **pPanelItem,int *pItemsNumber,int OpMode); +typedef int (WINAPI *PLUGINMINFARVERSION)(); +typedef void (WINAPI *PLUGINGETOPENPLUGININFO)(HANDLE hPlugin,oldfar::OpenPluginInfo *Info); +typedef void (WINAPI *PLUGINGETPLUGININFO)(oldfar::PluginInfo *Info); +typedef int (WINAPI *PLUGINGETVIRTUALFINDDATA)(HANDLE hPlugin,oldfar::PluginPanelItem **pPanelItem,int *pItemsNumber,const char *Path); +typedef int (WINAPI *PLUGINMAKEDIRECTORY)(HANDLE hPlugin,char *Name,int OpMode); +typedef HANDLE(WINAPI *PLUGINOPENFILEPLUGIN)(char *Name,const unsigned char *Data,int DataSize,int OpMode); +typedef HANDLE(WINAPI *PLUGINOPENPLUGIN)(int OpenFrom,INT_PTR Item); +typedef int (WINAPI *PLUGINPROCESSEDITOREVENT)(int Event,void *Param); +typedef int (WINAPI *PLUGINPROCESSEDITORINPUT)(const INPUT_RECORD *Rec); +typedef int (WINAPI *PLUGINPROCESSEVENT)(HANDLE hPlugin,int Event,void *Param); +typedef int (WINAPI *PLUGINPROCESSHOSTFILE)(HANDLE hPlugin,oldfar::PluginPanelItem *PanelItem,int ItemsNumber,int OpMode); +typedef int (WINAPI *PLUGINPROCESSKEY)(HANDLE hPlugin,int Key,unsigned int ControlState); +typedef int (WINAPI *PLUGINPUTFILES)(HANDLE hPlugin,oldfar::PluginPanelItem *PanelItem,int ItemsNumber,int Move,int OpMode); +typedef int (WINAPI *PLUGINSETDIRECTORY)(HANDLE hPlugin,const char *Dir,int OpMode); +typedef int (WINAPI *PLUGINSETFINDLIST)(HANDLE hPlugin,const oldfar::PluginPanelItem *PanelItem,int ItemsNumber); +typedef void (WINAPI *PLUGINSETSTARTUPINFO)(const oldfar::PluginStartupInfo *Info); +typedef int (WINAPI *PLUGINPROCESSVIEWEREVENT)(int Event,void *Param); +typedef int (WINAPI *PLUGINPROCESSDIALOGEVENT)(int Event,void *Param); + + +class PluginA: public Plugin +{ + private: + FARString strRootKey; + std::string mbRootKey; + + PluginInfo PI; + OpenPluginInfo OPI; + + oldfar::PluginPanelItem *pFDPanelItemA; + oldfar::PluginPanelItem *pVFDPanelItemA; + + PLUGINSETSTARTUPINFO pSetStartupInfo; + PLUGINOPENPLUGIN pOpenPlugin; + PLUGINOPENFILEPLUGIN pOpenFilePlugin; + PLUGINCLOSEPLUGIN pClosePlugin; + PLUGINGETPLUGININFO pGetPluginInfo; + PLUGINGETOPENPLUGININFO pGetOpenPluginInfo; + PLUGINGETFINDDATA pGetFindData; + PLUGINFREEFINDDATA pFreeFindData; + PLUGINGETVIRTUALFINDDATA pGetVirtualFindData; + PLUGINFREEVIRTUALFINDDATA pFreeVirtualFindData; + PLUGINSETDIRECTORY pSetDirectory; + PLUGINGETFILES pGetFiles; + PLUGINPUTFILES pPutFiles; + PLUGINDELETEFILES pDeleteFiles; + PLUGINMAKEDIRECTORY pMakeDirectory; + PLUGINPROCESSHOSTFILE pProcessHostFile; + PLUGINSETFINDLIST pSetFindList; + PLUGINCONFIGURE pConfigure; + PLUGINMAYEXITFAR pMayExitFAR; + PLUGINEXITFAR pExitFAR; + PLUGINPROCESSKEY pProcessKey; + PLUGINPROCESSEVENT pProcessEvent; + PLUGINPROCESSEDITOREVENT pProcessEditorEvent; + PLUGINCOMPARE pCompare; + PLUGINPROCESSEDITORINPUT pProcessEditorInput; + PLUGINMINFARVERSION pMinFarVersion; + PLUGINPROCESSVIEWEREVENT pProcessViewerEvent; + PLUGINPROCESSDIALOGEVENT pProcessDialogEvent; + + public: + + PluginA(PluginManager *owner, + const FARString &strModuleName, + const std::string &settingsName, + const std::string &moduleID); + ~PluginA(); + + bool IsOemPlugin() {return true;} + + bool Load(); + bool LoadFromCache(); + + bool SaveToCache(); + + int Unload(bool bExitFAR = false); + + bool IsPanelPlugin(); + + bool HasOpenPlugin() { return pOpenPlugin!=nullptr; } + bool HasMakeDirectory() { return pMakeDirectory!=nullptr; } + bool HasDeleteFiles() { return pDeleteFiles!=nullptr; } + bool HasPutFiles() { return pPutFiles!=nullptr; } + bool HasGetFiles() { return pGetFiles!=nullptr; } + bool HasSetStartupInfo() { return pSetStartupInfo!=nullptr; } + bool HasOpenFilePlugin() { return pOpenFilePlugin!=nullptr; } + bool HasClosePlugin() { return pClosePlugin!=nullptr; } + bool HasGetPluginInfo() { return pGetPluginInfo!=nullptr; } + bool HasGetOpenPluginInfo() { return pGetOpenPluginInfo!=nullptr; } + bool HasGetFindData() { return pGetFindData!=nullptr; } + bool HasFreeFindData() { return pFreeFindData!=nullptr; } + bool HasGetVirtualFindData() { return pGetVirtualFindData!=nullptr; } + bool HasFreeVirtualFindData() { return pFreeVirtualFindData!=nullptr; } + bool HasSetDirectory() { return pSetDirectory!=nullptr; } + bool HasProcessHostFile() { return pProcessHostFile!=nullptr; } + bool HasSetFindList() { return pSetFindList!=nullptr; } + bool HasConfigure() { return pConfigure!=nullptr; } + bool HasMayExitFAR() { return pMayExitFAR!=nullptr; } + bool HasExitFAR() { return pExitFAR!=nullptr; } + bool HasProcessKey() { return pProcessKey!=nullptr; } + bool HasProcessEvent() { return pProcessEvent!=nullptr; } + bool HasProcessEditorEvent() { return pProcessEditorEvent!=nullptr; } + bool HasCompare() { return pCompare!=nullptr; } + bool HasProcessEditorInput() { return pProcessEditorInput!=nullptr; } + bool HasMinFarVersion() { return pMinFarVersion!=nullptr; } + bool HasProcessViewerEvent() { return pProcessViewerEvent!=nullptr; } + bool HasProcessDialogEvent() { return pProcessDialogEvent!=nullptr; } + bool HasProcessSynchroEvent() { return false; } +#if defined(PROCPLUGINMACROFUNC) + bool HasProcessMacroFunc() { return false; } +#endif + bool HasAnalyse() { return false; } + bool HasGetCustomData() { return false; } + bool HasFreeCustomData() { return false; } + + const FARString &GetModuleName() { return m_strModuleName; } + const char *GetSettingsName() { return m_strSettingsName.c_str(); } + DWORD GetSysID() { return SysID; } + bool CheckWorkFlags(DWORD flags) { return WorkFlags.Check(flags)==TRUE; } + DWORD GetWorkFlags() { return WorkFlags.Flags; } + DWORD GetFuncFlags() { return FuncFlags.Flags; } + + bool InitLang(const wchar_t *Path) { return Lang.Init(Path,false); } + void CloseLang() { Lang.Close(); } + const char *GetMsgA(int nID) { return Lang.GetMsgA(nID); } + + public: + + bool SetStartupInfo(bool &bUnloaded); + bool CheckMinFarVersion(bool &bUnloaded); + + HANDLE OpenPlugin(int OpenFrom, INT_PTR Item); + HANDLE OpenFilePlugin(const wchar_t *Name, const unsigned char *Data, int DataSize, int OpMode); + + int SetFindList(HANDLE hPlugin, const PluginPanelItem *PanelItem, int ItemsNumber); + int GetFindData(HANDLE hPlugin, PluginPanelItem **pPanelItem, int *pItemsNumber, int OpMode); + int GetVirtualFindData(HANDLE hPlugin, PluginPanelItem **pPanelItem, int *pItemsNumber, const wchar_t *Path); + int SetDirectory(HANDLE hPlugin, const wchar_t *Dir, int OpMode); + int GetFiles(HANDLE hPlugin, PluginPanelItem *PanelItem, int ItemsNumber, int Move, const wchar_t **DestPath, int OpMode); + int PutFiles(HANDLE hPlugin, PluginPanelItem *PanelItem, int ItemsNumber, int Move, int OpMode); + int DeleteFiles(HANDLE hPlugin, PluginPanelItem *PanelItem, int ItemsNumber, int OpMode); + int MakeDirectory(HANDLE hPlugin, const wchar_t **Name, int OpMode); + int ProcessHostFile(HANDLE hPlugin, PluginPanelItem *PanelItem, int ItemsNumber, int OpMode); + int ProcessKey(HANDLE hPlugin, int Key, unsigned int dwControlState); + int ProcessEvent(HANDLE hPlugin, int Event, PVOID Param); + int Compare(HANDLE hPlugin, const PluginPanelItem *Item1, const PluginPanelItem *Item2, DWORD Mode); + + int GetCustomData(const wchar_t *FilePath, wchar_t **CustomData) { return 0; } + void FreeCustomData(wchar_t *CustomData) {} + + void GetOpenPluginInfo(HANDLE hPlugin, OpenPluginInfo *Info); + void FreeFindData(HANDLE hPlugin, PluginPanelItem *PanelItem, int ItemsNumber); + void FreeVirtualFindData(HANDLE hPlugin, PluginPanelItem *PanelItem, int ItemsNumber); + void ClosePlugin(HANDLE hPlugin); + + int ProcessEditorInput(const INPUT_RECORD *D); + int ProcessEditorEvent(int Event, PVOID Param); + int ProcessViewerEvent(int Event, PVOID Param); + int ProcessDialogEvent(int Event, PVOID Param); + int ProcessSynchroEvent(int Event, PVOID Param) { return 0; } +#if defined(PROCPLUGINMACROFUNC) + int ProcessMacroFunc(const wchar_t *Name, const FarMacroValue *Params, int nParams, FarMacroValue **Results, int *nResults) {return 0;} +#endif + + int Analyse(const AnalyseData *pData) { return FALSE; } + + bool GetPluginInfo(PluginInfo *pi); + int Configure(int MenuItem); + + bool MayExitFAR(); + void ExitFAR(); + + private: + + void ClearExports(); + + void FreePluginInfo(); + void ConvertPluginInfo(oldfar::PluginInfo &Src, PluginInfo *Dest); + void FreeOpenPluginInfo(); + void ConvertOpenPluginInfo(oldfar::OpenPluginInfo &Src, OpenPluginInfo *Dest); +}; diff --git a/far2l/src/plug/PluginW.cpp b/far2l/src/plug/PluginW.cpp new file mode 100644 index 00000000..ea17f07d --- /dev/null +++ b/far2l/src/plug/PluginW.cpp @@ -0,0 +1,1311 @@ +/* +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" + + +#include "plugins.hpp" +#include "plugapi.hpp" +#include "lang.hpp" +#include "keys.hpp" +#include "scantree.hpp" +#include "chgprior.hpp" +#include "constitle.hpp" +#include "cmdline.hpp" +#include "filepanels.hpp" +#include "panel.hpp" +#include "vmenu.hpp" +#include "dialog.hpp" +#include "rdrwdsk.hpp" +#include "savescr.hpp" +#include "ctrlobj.hpp" +#include "scrbuf.hpp" +#include "udlist.hpp" +#include "fileedit.hpp" +#include "RefreshFrameManager.hpp" +#include "InterThreadCall.hpp" +#include "plclass.hpp" +#include "PluginW.hpp" +#include "keyboard.hpp" +#include "message.hpp" +#include "clipboard.hpp" +#include "xlat.hpp" +#include "pathmix.hpp" +#include "dirmix.hpp" +#include "strmix.hpp" +#include "processname.hpp" +#include "mix.hpp" +#include "interf.hpp" +#include "execute.hpp" +#include "flink.hpp" +#include <string> +#include <list> +#include <vector> +#include <KeyFileHelper.h> + +static const char *szCache_Preload = "Preload"; +static const char *szCache_Preopen = "Preopen"; +static const char *szCache_SysID = "SysID"; + +static const char szCache_OpenPlugin[] = "OpenPluginW"; +static const char szCache_OpenFilePlugin[] = "OpenFilePluginW"; +static const char szCache_SetFindList[] = "SetFindListW"; +static const char szCache_ProcessEditorInput[] = "ProcessEditorInputW"; +static const char szCache_ProcessEditorEvent[] = "ProcessEditorEventW"; +static const char szCache_ProcessViewerEvent[] = "ProcessViewerEventW"; +static const char szCache_ProcessDialogEvent[] = "ProcessDialogEventW"; +static const char szCache_ProcessSynchroEvent[] = "ProcessSynchroEventW"; +#if defined(PROCPLUGINMACROFUNC) +static const char szCache_ProcessMacroFunc[] = "ProcessMacroFuncW"; +#endif +static const char szCache_Configure[] = "ConfigureW"; +static const char szCache_Analyse[] = "AnalyseW"; +static const char szCache_GetCustomData[] = "GetCustomDataW"; + +static const char NFMP_OpenPlugin[] = "OpenPluginW"; +static const char NFMP_OpenFilePlugin[] = "OpenFilePluginW"; +static const char NFMP_SetFindList[] = "SetFindListW"; +static const char NFMP_ProcessEditorInput[] = "ProcessEditorInputW"; +static const char NFMP_ProcessEditorEvent[] = "ProcessEditorEventW"; +static const char NFMP_ProcessViewerEvent[] = "ProcessViewerEventW"; +static const char NFMP_ProcessDialogEvent[] = "ProcessDialogEventW"; +static const char NFMP_ProcessSynchroEvent[] = "ProcessSynchroEventW"; +#if defined(PROCPLUGINMACROFUNC) +static const char NFMP_ProcessMacroFunc[] = "ProcessMacroFuncW"; +#endif +static const char NFMP_SetStartupInfo[] = "SetStartupInfoW"; +static const char NFMP_ClosePlugin[] = "ClosePluginW"; +static const char NFMP_GetPluginInfo[] = "GetPluginInfoW"; +static const char NFMP_GetOpenPluginInfo[] = "GetOpenPluginInfoW"; +static const char NFMP_GetFindData[] = "GetFindDataW"; +static const char NFMP_FreeFindData[] = "FreeFindDataW"; +static const char NFMP_GetVirtualFindData[] = "GetVirtualFindDataW"; +static const char NFMP_FreeVirtualFindData[] = "FreeVirtualFindDataW"; +static const char NFMP_SetDirectory[] = "SetDirectoryW"; +static const char NFMP_GetFiles[] = "GetFilesW"; +static const char NFMP_PutFiles[] = "PutFilesW"; +static const char NFMP_DeleteFiles[] = "DeleteFilesW"; +static const char NFMP_MakeDirectory[] = "MakeDirectoryW"; +static const char NFMP_ProcessHostFile[] = "ProcessHostFileW"; +static const char NFMP_Configure[] = "ConfigureW"; +static const char NFMP_MayExitFAR[] = "MayExitFARW"; +static const char NFMP_ExitFAR[] = "ExitFARW"; +static const char NFMP_ProcessKey[] = "ProcessKeyW"; +static const char NFMP_ProcessEvent[] = "ProcessEventW"; +static const char NFMP_Compare[] = "CompareW"; +static const char NFMP_GetMinFarVersion[] = "GetMinFarVersionW"; +static const char NFMP_Analyse[] = "AnalyseW"; +static const char NFMP_GetCustomData[] = "GetCustomDataW"; +static const char NFMP_FreeCustomData[] = "FreeCustomDataW"; + + +static void CheckScreenLock() +{ + if (ScrBuf.GetLockCount() > 0 && !CtrlObject->Macro.PeekKey()) + { + ScrBuf.SetLockCount(0); + ScrBuf.Flush(); + } +} + +static size_t WINAPI FarKeyToName(int Key,wchar_t *KeyText,size_t Size) +{ + FARString strKT; + + if (!KeyToText(Key,strKT)) + return 0; + + size_t len = strKT.GetLength(); + + if (Size && KeyText) + { + if (Size <= len) len = Size-1; + + wmemcpy(KeyText, strKT.CPtr(), len); + KeyText[len] = 0; + } + else if (KeyText) *KeyText = 0; + + return (len+1); +} + +int WINAPI KeyNameToKeyW(const wchar_t *Name) +{ + FARString strN(Name); + return (int)KeyNameToKey(strN); +} + +PluginW::PluginW(PluginManager *owner, const FARString &strModuleName, + const std::string &settingsName, const std::string &moduleID) + : + Plugin(owner, strModuleName, settingsName, moduleID) +{ + ClearExports(); +} + +PluginW::~PluginW() +{ +} + +bool PluginW::LoadFromCache() +{ + KeyFileReadSection kfh(PluginsIni(), GetSettingsName()); + + if (!kfh.SectionLoaded()) + return false; + + //PF_PRELOAD plugin, skip cache + if (kfh.GetInt(szCache_Preload) != 0) + return Load(); + + //одинаковые ли бинарники? + if (kfh.GetString("ID") != m_strModuleID) + return false; + + SysID = kfh.GetUInt(szCache_SysID, 0); + pOpenPluginW = (PLUGINOPENPLUGINW)(INT_PTR)kfh.GetUInt(szCache_OpenPlugin, 0); + pOpenFilePluginW = (PLUGINOPENFILEPLUGINW)(INT_PTR)kfh.GetUInt(szCache_OpenFilePlugin, 0); + pSetFindListW = (PLUGINSETFINDLISTW)(INT_PTR)kfh.GetUInt(szCache_SetFindList, 0); + pProcessEditorInputW = (PLUGINPROCESSEDITORINPUTW)(INT_PTR)kfh.GetUInt(szCache_ProcessEditorInput, 0); + pProcessEditorEventW = (PLUGINPROCESSEDITOREVENTW)(INT_PTR)kfh.GetUInt(szCache_ProcessEditorEvent, 0); + pProcessViewerEventW = (PLUGINPROCESSVIEWEREVENTW)(INT_PTR)kfh.GetUInt(szCache_ProcessViewerEvent, 0); + pProcessDialogEventW = (PLUGINPROCESSDIALOGEVENTW)(INT_PTR)kfh.GetUInt(szCache_ProcessDialogEvent, 0); + pProcessSynchroEventW = (PLUGINPROCESSSYNCHROEVENTW)(INT_PTR)kfh.GetUInt(szCache_ProcessSynchroEvent, 0); +#if defined(PROCPLUGINMACROFUNC) + pProcessMacroFuncW = (PLUGINPROCESSMACROFUNCW)(INT_PTR)kfh.GetUInt(szCache_ProcessMacroFunc, 0); +#endif + pConfigureW = (PLUGINCONFIGUREW)(INT_PTR)kfh.GetUInt(szCache_Configure, 0); + pAnalyseW = (PLUGINANALYSEW)(INT_PTR)kfh.GetUInt(szCache_Analyse, 0); + pGetCustomDataW = (PLUGINGETCUSTOMDATAW)(INT_PTR)kfh.GetUInt(szCache_GetCustomData, 0); + WorkFlags.Set(PIWF_CACHED); //too much "cached" flags + + if (kfh.GetInt(szCache_Preopen) != 0) + OpenModule(); + + return true; +} + +bool PluginW::SaveToCache() +{ + if (!pGetPluginInfoW && + !pOpenPluginW && + !pOpenFilePluginW && + !pSetFindListW && + !pProcessEditorInputW && + !pProcessEditorEventW && + !pProcessViewerEventW && + !pProcessDialogEventW && + !pProcessSynchroEventW && +#if defined(PROCPLUGINMACROFUNC) + !pProcessMacroFuncW && +#endif + !pAnalyseW && + !pGetCustomDataW + ) + { + return false; + } + + KeyFileHelper kfh(PluginsIni()); + kfh.RemoveSection(GetSettingsName()); + + struct stat st{}; + const std::string &module = m_strModuleName.GetMB(); + if (stat(module.c_str(), &st) == -1) + { + fprintf(stderr, "%s: stat('%s') error %u\n", + __FUNCTION__, module.c_str(), errno); + return false; + } + + kfh.SetString(GetSettingsName(), "Module", module.c_str()); + + PluginInfo Info{}; + GetPluginInfo(&Info); + SysID = Info.SysID; //LAME!!! + + kfh.SetInt(GetSettingsName(), szCache_Preopen, ((Info.Flags & PF_PREOPEN) != 0)); + + if ((Info.Flags & PF_PRELOAD) != 0) + { + kfh.SetInt(GetSettingsName(), szCache_Preload, 1); + WorkFlags.Change(PIWF_PRELOADED, TRUE); + return true; + } + WorkFlags.Change(PIWF_PRELOADED, FALSE); + + kfh.SetString(GetSettingsName(), "ID", m_strModuleID.c_str()); + + for (int i = 0; i < Info.DiskMenuStringsNumber; i++) + { + kfh.SetString(GetSettingsName(), + StrPrintf(FmtDiskMenuStringD, i).c_str(), + Info.DiskMenuStrings[i]); + } + + for (int i = 0; i < Info.PluginMenuStringsNumber; i++) + { + kfh.SetString(GetSettingsName(), + StrPrintf(FmtPluginMenuStringD, i).c_str(), + Info.PluginMenuStrings[i]); + } + + for (int i = 0; i < Info.PluginConfigStringsNumber; i++) + { + kfh.SetString(GetSettingsName(), + StrPrintf(FmtPluginConfigStringD, i).c_str(), + Info.PluginConfigStrings[i]); + } + + kfh.SetString(GetSettingsName(), "CommandPrefix", Info.CommandPrefix); + kfh.SetUInt(GetSettingsName(), "Flags", Info.Flags); + + kfh.SetUInt(GetSettingsName(), szCache_SysID, SysID); + kfh.SetUInt(GetSettingsName(), szCache_OpenPlugin, pOpenPluginW!=nullptr); + kfh.SetUInt(GetSettingsName(), szCache_OpenFilePlugin, pOpenFilePluginW!=nullptr); + kfh.SetUInt(GetSettingsName(), szCache_SetFindList, pSetFindListW!=nullptr); + kfh.SetUInt(GetSettingsName(), szCache_ProcessEditorInput, pProcessEditorInputW!=nullptr); + kfh.SetUInt(GetSettingsName(), szCache_ProcessEditorEvent, pProcessEditorEventW!=nullptr); + kfh.SetUInt(GetSettingsName(), szCache_ProcessViewerEvent, pProcessViewerEventW!=nullptr); + kfh.SetUInt(GetSettingsName(), szCache_ProcessDialogEvent, pProcessDialogEventW!=nullptr); + kfh.SetUInt(GetSettingsName(), szCache_ProcessSynchroEvent, pProcessSynchroEventW!=nullptr); +#if defined(PROCPLUGINMACROFUNC) + kfh.SetUInt(GetSettingsName(), szCache_ProcessMacroFunc, pProcessMacroFuncW!=nullptr); +#endif + kfh.SetUInt(GetSettingsName(), szCache_Configure, pConfigureW!=nullptr); + kfh.SetUInt(GetSettingsName(), szCache_Analyse, pAnalyseW!=nullptr); + kfh.SetUInt(GetSettingsName(), szCache_GetCustomData, pGetCustomDataW!=nullptr); + + return true; +} + +bool PluginW::Load() +{ + if (m_Loaded) + return true; + + if (!OpenModule()) + return false; + + m_Loaded = true; + + WorkFlags.Clear(PIWF_CACHED); + GetModuleFN(pSetStartupInfoW, NFMP_SetStartupInfo); + GetModuleFN(pOpenPluginW, NFMP_OpenPlugin); + GetModuleFN(pOpenFilePluginW, NFMP_OpenFilePlugin); + GetModuleFN(pClosePluginW, NFMP_ClosePlugin); + GetModuleFN(pGetPluginInfoW, NFMP_GetPluginInfo); + GetModuleFN(pGetOpenPluginInfoW, NFMP_GetOpenPluginInfo); + GetModuleFN(pGetFindDataW, NFMP_GetFindData); + GetModuleFN(pFreeFindDataW, NFMP_FreeFindData); + GetModuleFN(pGetVirtualFindDataW, NFMP_GetVirtualFindData); + GetModuleFN(pFreeVirtualFindDataW, NFMP_FreeVirtualFindData); + GetModuleFN(pSetDirectoryW, NFMP_SetDirectory); + GetModuleFN(pGetFilesW, NFMP_GetFiles); + GetModuleFN(pPutFilesW, NFMP_PutFiles); + GetModuleFN(pDeleteFilesW, NFMP_DeleteFiles); + GetModuleFN(pMakeDirectoryW, NFMP_MakeDirectory); + GetModuleFN(pProcessHostFileW, NFMP_ProcessHostFile); + GetModuleFN(pSetFindListW, NFMP_SetFindList); + GetModuleFN(pConfigureW, NFMP_Configure); + GetModuleFN(pExitFARW, NFMP_ExitFAR); + GetModuleFN(pMayExitFARW, NFMP_MayExitFAR); + GetModuleFN(pProcessKeyW, NFMP_ProcessKey); + GetModuleFN(pProcessEventW, NFMP_ProcessEvent); + GetModuleFN(pCompareW, NFMP_Compare); + GetModuleFN(pProcessEditorInputW, NFMP_ProcessEditorInput); + GetModuleFN(pProcessEditorEventW, NFMP_ProcessEditorEvent); + GetModuleFN(pProcessViewerEventW, NFMP_ProcessViewerEvent); + GetModuleFN(pProcessDialogEventW, NFMP_ProcessDialogEvent); + GetModuleFN(pProcessSynchroEventW, NFMP_ProcessSynchroEvent); +#if defined(PROCPLUGINMACROFUNC) + GetModuleFN(pProcessMacroFuncW, NFMP_ProcessMacroFunc); +#endif + GetModuleFN(pMinFarVersionW,NFMP_GetMinFarVersion); + GetModuleFN(pAnalyseW, NFMP_Analyse); + GetModuleFN(pGetCustomDataW, NFMP_GetCustomData); + GetModuleFN(pFreeCustomDataW, NFMP_FreeCustomData); + + bool bUnloaded = false; + + if (!CheckMinFarVersion(bUnloaded) || !SetStartupInfo(bUnloaded)) + { + if (!bUnloaded) + Unload(); + + //чтоб не пытаться загрузить опять а то ошибка будет постоянно показываться. + WorkFlags.Set(PIWF_DONTLOADAGAIN); + + return false; + } + + FuncFlags.Set(PICFF_LOADED); + SaveToCache(); + return true; +} + +static int WINAPI farExecuteW(const wchar_t *CmdStr, unsigned int flags) +{ + return farExecuteA(Wide2MB(CmdStr).c_str(), flags); +} + +static int WINAPI farExecuteLibraryW(const wchar_t *Library, const wchar_t *Symbol, const wchar_t *CmdStr, unsigned int flags) +{ + return farExecuteLibraryA(Wide2MB(Library).c_str(), Wide2MB(Symbol).c_str(), Wide2MB(CmdStr).c_str(), flags); +} + +static void farDisplayNotificationW(const wchar_t *action, const wchar_t *object) +{ + DisplayNotification(action, object); +} + +static int farDispatchInterThreadCallsW() +{ + return DispatchInterThreadCalls(); +} + +static void WINAPI farBackgroundTaskW(const wchar_t *Info, BOOL Started) +{ + if (Started) + CtrlObject->Plugins.BackroundTaskStarted(Info); + else + CtrlObject->Plugins.BackroundTaskFinished(Info); +} + +void CreatePluginStartupInfo(Plugin *pPlugin, PluginStartupInfo *PSI, FarStandardFunctions *FSF) +{ + static PluginStartupInfo StartupInfo{}; + static FarStandardFunctions StandardFunctions{}; + + // заполняем структуру StandardFunctions один раз!!! + if (!StandardFunctions.StructSize) + { + StandardFunctions.StructSize=sizeof(StandardFunctions); + StandardFunctions.snprintf=swprintf; + StandardFunctions.BoxSymbols=BoxSymbols; + StandardFunctions.sscanf=swscanf; + StandardFunctions.qsort=FarQsort; + StandardFunctions.qsortex=FarQsortEx; + StandardFunctions.atoi=FarAtoi; + StandardFunctions.atoi64=FarAtoi64; + StandardFunctions.itoa=FarItoa; + StandardFunctions.itoa64=FarItoa64; + StandardFunctions.bsearch=FarBsearch; + StandardFunctions.LIsLower = farIsLower; + StandardFunctions.LIsUpper = farIsUpper; + StandardFunctions.LIsAlpha = farIsAlpha; + StandardFunctions.LIsAlphanum = farIsAlphaNum; + StandardFunctions.LUpper = farUpper; + StandardFunctions.LUpperBuf = farUpperBuf; + StandardFunctions.LLowerBuf = farLowerBuf; + StandardFunctions.LLower = farLower; + StandardFunctions.LStrupr = farStrUpper; + StandardFunctions.LStrlwr = farStrLower; + StandardFunctions.LStricmp = farStrCmpI; + StandardFunctions.LStrnicmp = farStrCmpNI; + StandardFunctions.Unquote=Unquote; + StandardFunctions.LTrim=RemoveLeadingSpaces; + StandardFunctions.RTrim=RemoveTrailingSpaces; + StandardFunctions.Trim=RemoveExternalSpaces; + StandardFunctions.TruncStr=TruncStr; + StandardFunctions.TruncPathStr=TruncPathStr; + StandardFunctions.QuoteSpaceOnly=QuoteSpaceOnly; + StandardFunctions.PointToName=PointToName; + StandardFunctions.GetPathRoot=farGetPathRoot; + StandardFunctions.AddEndSlash=AddEndSlash; + StandardFunctions.CopyToClipboard=CopyToClipboard; + StandardFunctions.PasteFromClipboard=PasteFromClipboard; + StandardFunctions.FarKeyToName=FarKeyToName; + StandardFunctions.FarNameToKey=KeyNameToKeyW; + StandardFunctions.FarInputRecordToKey=InputRecordToKey; + StandardFunctions.XLat=Xlat; + StandardFunctions.GetFileOwner=farGetFileOwner; + StandardFunctions.GetNumberOfLinks=GetNumberOfLinks; + StandardFunctions.FarRecursiveSearch=FarRecursiveSearch; + StandardFunctions.MkTemp=FarMkTemp; + StandardFunctions.DeleteBuffer=DeleteBuffer; + StandardFunctions.ProcessName=ProcessName; + StandardFunctions.MkLink=FarMkLink; + StandardFunctions.ConvertPath=farConvertPath; + StandardFunctions.GetReparsePointInfo=farGetReparsePointInfo; + StandardFunctions.GetCurrentDirectory=farGetCurrentDirectory; + StandardFunctions.Execute = farExecuteW; + StandardFunctions.ExecuteLibrary = farExecuteLibraryW; + StandardFunctions.DisplayNotification = farDisplayNotificationW; + StandardFunctions.DispatchInterThreadCalls = farDispatchInterThreadCallsW; + StandardFunctions.BackgroundTask = farBackgroundTaskW; + } + + if (!StartupInfo.StructSize) + { + StartupInfo.StructSize=sizeof(StartupInfo); + StartupInfo.Menu=FarMenuFn; + StartupInfo.GetMsg=FarGetMsgFn; + StartupInfo.Message=FarMessageFn; + StartupInfo.Control=FarControl; + StartupInfo.SaveScreen=FarSaveScreen; + StartupInfo.RestoreScreen=FarRestoreScreen; + StartupInfo.GetDirList=FarGetDirList; + StartupInfo.GetPluginDirList=FarGetPluginDirList; + StartupInfo.FreeDirList=FarFreeDirList; + StartupInfo.FreePluginDirList=FarFreePluginDirList; + StartupInfo.Viewer=FarViewer; + StartupInfo.Editor=FarEditor; + StartupInfo.CmpName=FarCmpName; + StartupInfo.Text=FarText; + StartupInfo.EditorControl=FarEditorControl; + StartupInfo.ViewerControl=FarViewerControl; + StartupInfo.ShowHelp=FarShowHelp; + StartupInfo.AdvControl=FarAdvControl; + StartupInfo.DialogInit=FarDialogInit; + StartupInfo.DialogRun=FarDialogRun; + StartupInfo.DialogFree=FarDialogFree; + StartupInfo.SendDlgMessage=FarSendDlgMessage; + StartupInfo.DefDlgProc=FarDefDlgProc; + StartupInfo.InputBox=FarInputBox; + StartupInfo.PluginsControl=farPluginsControl; + StartupInfo.FileFilterControl=farFileFilterControl; + StartupInfo.RegExpControl=farRegExpControl; + } + + *PSI=StartupInfo; + *FSF=StandardFunctions; + PSI->FSF=FSF; + PSI->RootKey=nullptr; + PSI->ModuleNumber=(INT_PTR)pPlugin; + + if (pPlugin) + { + PSI->ModuleName = pPlugin->GetModuleName().CPtr(); + } +} + + +struct ExecuteStruct +{ + int id; //function id + union + { + INT_PTR nResult; + HANDLE hResult; + BOOL bResult; + }; + + union + { + INT_PTR nDefaultResult; + HANDLE hDefaultResult; + BOOL bDefaultResult; + }; + + bool bUnloaded; +}; + + +#define EXECUTE_FUNCTION(function, es) \ + { \ + es.nResult = 0; \ + es.nDefaultResult = 0; \ + es.bUnloaded = false; \ + function; \ + } + + +#define EXECUTE_FUNCTION_EX(function, es) \ + { \ + es.bUnloaded = false; \ + es.nResult = 0; \ + es.nResult = (INT_PTR)function; \ + } + +bool PluginW::SetStartupInfo(bool &bUnloaded) +{ + if (pSetStartupInfoW) + { + PluginStartupInfo _info; + FarStandardFunctions _fsf; + CreatePluginStartupInfo(this, &_info, &_fsf); + // скорректируем адреса и плагино-зависимые поля + _info.RootKey = strRootKey.CPtr(); + ExecuteStruct es; + es.id = EXCEPT_SETSTARTUPINFO; + EXECUTE_FUNCTION(pSetStartupInfoW(&_info), es); + + if (es.bUnloaded) + { + bUnloaded = true; + return false; + } + } + + return true; +} + +static void ShowMessageAboutIllegalPluginVersion(const wchar_t* plg,int required) +{ + FARString strMsg1, strMsg2; + FARString strPlgName; + strMsg1.Format(MSG(MPlgRequired), + (WORD)(HIWORD(required)),(WORD)(LOWORD(required))); + strMsg2.Format(MSG(MPlgRequired2), + (WORD)(HIWORD(FAR_VERSION)),(WORD)(LOWORD(FAR_VERSION))); + Message(MSG_WARNING,1,MSG(MError),MSG(MPlgBadVers),plg,strMsg1,strMsg2,MSG(MOk)); +} + + +bool PluginW::CheckMinFarVersion(bool &bUnloaded) +{ + if (pMinFarVersionW) + { + ExecuteStruct es; + es.id = EXCEPT_MINFARVERSION; + es.nDefaultResult = 0; + EXECUTE_FUNCTION_EX(pMinFarVersionW(), es); + + if (es.bUnloaded) + { + bUnloaded = true; + return false; + } + + DWORD FVer = (DWORD)es.nResult; + + if (LOWORD(FVer) > LOWORD(FAR_VERSION) || + (LOWORD(FVer) == LOWORD(FAR_VERSION) && + HIWORD(FVer) > HIWORD(FAR_VERSION))) + { + ShowMessageAboutIllegalPluginVersion(m_strModuleName,FVer); + return false; + } + } + + return true; +} + +int PluginW::Unload(bool bExitFAR) +{ + int nResult = TRUE; + + if (bExitFAR) + ExitFAR(); + + if (!WorkFlags.Check(PIWF_CACHED)) + ClearExports(); + + CloseModule(); + + m_Loaded = false; + FuncFlags.Clear(PICFF_LOADED); //?? + return nResult; +} + +bool PluginW::IsPanelPlugin() +{ + return pSetFindListW || + pGetFindDataW || + pGetVirtualFindDataW || + pSetDirectoryW || + pGetFilesW || + pPutFilesW || + pDeleteFilesW || + pMakeDirectoryW || + pProcessHostFileW || + pProcessKeyW || + pProcessEventW || + pCompareW || + pGetOpenPluginInfoW || + pFreeFindDataW || + pFreeVirtualFindDataW || + pClosePluginW; +} + +int PluginW::Analyse(const AnalyseData *pData) +{ + if (Load() && pAnalyseW) + { + ExecuteStruct es; + es.id = EXCEPT_ANALYSE; + es.bDefaultResult = FALSE; + es.bResult = FALSE; + EXECUTE_FUNCTION_EX(pAnalyseW(pData), es); + return es.bResult; + } + + return FALSE; +} + +HANDLE PluginW::OpenPlugin(int OpenFrom, INT_PTR Item) +{ + ChangePriority *ChPriority = new ChangePriority(ChangePriority::NORMAL); + + CheckScreenLock(); //?? + + { +// FARString strCurDir; +// CtrlObject->CmdLine->GetCurDir(strCurDir); +// FarChDir(strCurDir); + g_strDirToSet.Clear(); + } + + HANDLE hResult = INVALID_HANDLE_VALUE; + + if (Load() && pOpenPluginW) + { + //CurPluginItem=this; //BUGBUG + ExecuteStruct es; + es.id = EXCEPT_OPENPLUGIN; + es.hDefaultResult = INVALID_HANDLE_VALUE; + es.hResult = INVALID_HANDLE_VALUE; + EXECUTE_FUNCTION_EX(pOpenPluginW(OpenFrom,Item), es); + hResult = es.hResult; + //CurPluginItem=nullptr; //BUGBUG + /* CtrlObject->Macro.SetRedrawEditor(TRUE); //BUGBUG + + if ( !es.bUnloaded ) + { + + if(OpenFrom == OPEN_EDITOR && + !CtrlObject->Macro.IsExecuting() && + CtrlObject->Plugins.CurEditor && + CtrlObject->Plugins.CurEditor->IsVisible() ) + { + CtrlObject->Plugins.ProcessEditorEvent(EE_REDRAW,EEREDRAW_CHANGE); + CtrlObject->Plugins.ProcessEditorEvent(EE_REDRAW,EEREDRAW_ALL); + CtrlObject->Plugins.CurEditor->Show(); + } + if (hInternal!=INVALID_HANDLE_VALUE) + { + PluginHandle *hPlugin=new PluginHandle; + hPlugin->InternalHandle=es.hResult; + hPlugin->PluginNumber=(INT_PTR)this; + return((HANDLE)hPlugin); + } + else + if ( !g_strDirToSet.IsEmpty() ) + { + CtrlObject->Cp()->ActivePanel->SetCurDir(g_strDirToSet,TRUE); + CtrlObject->Cp()->ActivePanel->Redraw(); + } + } */ + } + + delete ChPriority; + + return hResult; +} + +////////////////////////////////// + +HANDLE PluginW::OpenFilePlugin( + const wchar_t *Name, + const unsigned char *Data, + int DataSize, + int OpMode +) +{ + HANDLE hResult = INVALID_HANDLE_VALUE; + + if (Load() && pOpenFilePluginW) + { + ExecuteStruct es; + es.id = EXCEPT_OPENFILEPLUGIN; + es.hDefaultResult = INVALID_HANDLE_VALUE; + EXECUTE_FUNCTION_EX(pOpenFilePluginW(Name, Data, DataSize, OpMode), es); + hResult = es.hResult; + } + + return hResult; +} + + +int PluginW::SetFindList( + HANDLE hPlugin, + const PluginPanelItem *PanelItem, + int ItemsNumber +) +{ + BOOL bResult = FALSE; + + if (pSetFindListW) + { + ExecuteStruct es; + es.id = EXCEPT_SETFINDLIST; + es.bDefaultResult = FALSE; + EXECUTE_FUNCTION_EX(pSetFindListW(hPlugin, PanelItem, ItemsNumber), es); + bResult = es.bResult; + } + + return bResult; +} + +int PluginW::ProcessEditorInput( + const INPUT_RECORD *D +) +{ + BOOL bResult = FALSE; + + if (Load() && pProcessEditorInputW) + { + ExecuteStruct es; + es.id = EXCEPT_PROCESSEDITORINPUT; + es.bDefaultResult = TRUE; //(TRUE) treat the result as a completed request on exception! + EXECUTE_FUNCTION_EX(pProcessEditorInputW(D), es); + bResult = es.bResult; + } + + return bResult; +} + +int PluginW::ProcessEditorEvent( + int Event, + PVOID Param +) +{ + if (Load() && pProcessEditorEventW) + { + ExecuteStruct es; + es.id = EXCEPT_PROCESSEDITOREVENT; + es.nDefaultResult = 0; + EXECUTE_FUNCTION_EX(pProcessEditorEventW(Event, Param), es); + (void)es; // supress 'set but not used' warning + } + + return 0; //oops! +} + +int PluginW::ProcessViewerEvent( + int Event, + void *Param +) +{ + if (Load() && pProcessViewerEventW) + { + ExecuteStruct es; + es.id = EXCEPT_PROCESSVIEWEREVENT; + es.nDefaultResult = 0; + EXECUTE_FUNCTION_EX(pProcessViewerEventW(Event, Param), es); + (void)es; // supress 'set but not used' warning + } + + return 0; //oops, again! +} + +int PluginW::ProcessDialogEvent( + int Event, + void *Param +) +{ + BOOL bResult = FALSE; + + if (Load() && pProcessDialogEventW) + { + ExecuteStruct es; + es.id = EXCEPT_PROCESSDIALOGEVENT; + es.bDefaultResult = FALSE; + EXECUTE_FUNCTION_EX(pProcessDialogEventW(Event, Param), es); + bResult = es.bResult; + } + + return bResult; +} + +int PluginW::ProcessSynchroEvent( + int Event, + void *Param +) +{ + if (Load() && pProcessSynchroEventW) + { + ExecuteStruct es; + es.id = EXCEPT_PROCESSSYNCHROEVENT; + es.nDefaultResult = 0; + EXECUTE_FUNCTION_EX(pProcessSynchroEventW(Event, Param), es); + (void)es; // supress 'set but not used' warning + } + + return 0; //oops, again! +} + +#if defined(PROCPLUGINMACROFUNC) +int PluginW::ProcessMacroFunc( + const wchar_t *Name, + const FarMacroValue *Params, + int nParams, + FarMacroValue **Results, + int *nResults +) +{ + int nResult = 0; + + if (Load() && pProcessMacroFuncW) + { + ExecuteStruct es; + es.id = EXCEPT_PROCESSMACROFUNC; + es.nDefaultResult = 0; + EXECUTE_FUNCTION_EX(pProcessMacroFuncW(Name,Params,nParams,Results,nResults), es); + nResult = (int)es.nResult; + } + + return nResult; +} +#endif + +int PluginW::GetVirtualFindData( + HANDLE hPlugin, + PluginPanelItem **pPanelItem, + int *pItemsNumber, + const wchar_t *Path +) +{ + BOOL bResult = FALSE; + + if (pGetVirtualFindDataW) + { + ExecuteStruct es; + es.id = EXCEPT_GETVIRTUALFINDDATA; + es.bDefaultResult = FALSE; + EXECUTE_FUNCTION_EX(pGetVirtualFindDataW(hPlugin, pPanelItem, pItemsNumber, Path), es); + bResult = es.bResult; + } + + return bResult; +} + + +void PluginW::FreeVirtualFindData( + HANDLE hPlugin, + PluginPanelItem *PanelItem, + int ItemsNumber +) +{ + if (pFreeVirtualFindDataW) + { + ExecuteStruct es; + es.id = EXCEPT_FREEVIRTUALFINDDATA; + EXECUTE_FUNCTION(pFreeVirtualFindDataW(hPlugin, PanelItem, ItemsNumber), es); + (void)es; // supress 'set but not used' warning + } +} + + + +int PluginW::GetFiles( + HANDLE hPlugin, + PluginPanelItem *PanelItem, + int ItemsNumber, + int Move, + const wchar_t **DestPath, + int OpMode +) +{ + int nResult = -1; + + if (pGetFilesW) + { + ExecuteStruct es; + es.id = EXCEPT_GETFILES; + es.nDefaultResult = -1; + EXECUTE_FUNCTION_EX(pGetFilesW(hPlugin, PanelItem, ItemsNumber, Move, DestPath, OpMode), es); + nResult = (int)es.nResult; + } + + return nResult; +} + + +int PluginW::PutFiles( + HANDLE hPlugin, + PluginPanelItem *PanelItem, + int ItemsNumber, + int Move, + int OpMode +) +{ + int nResult = -1; + + if (pPutFilesW) + { + ExecuteStruct es; + es.id = EXCEPT_PUTFILES; + es.nDefaultResult = -1; + static FARString strCurrentDirectory; + apiGetCurrentDirectory(strCurrentDirectory); + EXECUTE_FUNCTION_EX(pPutFilesW(hPlugin, PanelItem, ItemsNumber, Move, strCurrentDirectory, OpMode), es); + nResult = (int)es.nResult; + } + + return nResult; +} + +int PluginW::DeleteFiles( + HANDLE hPlugin, + PluginPanelItem *PanelItem, + int ItemsNumber, + int OpMode +) +{ + BOOL bResult = FALSE; + + if (pDeleteFilesW) + { + ExecuteStruct es; + es.id = EXCEPT_DELETEFILES; + es.bDefaultResult = FALSE; + EXECUTE_FUNCTION_EX(pDeleteFilesW(hPlugin, PanelItem, ItemsNumber, OpMode), es); + bResult = (int)es.bResult; + } + + return bResult; +} + + +int PluginW::MakeDirectory( + HANDLE hPlugin, + const wchar_t **Name, + int OpMode +) +{ + int nResult = -1; + + if (pMakeDirectoryW) + { + ExecuteStruct es; + es.id = EXCEPT_MAKEDIRECTORY; + es.nDefaultResult = -1; + EXECUTE_FUNCTION_EX(pMakeDirectoryW(hPlugin, Name, OpMode), es); + nResult = (int)es.nResult; + } + + return nResult; +} + + +int PluginW::ProcessHostFile( + HANDLE hPlugin, + PluginPanelItem *PanelItem, + int ItemsNumber, + int OpMode +) +{ + BOOL bResult = FALSE; + + if (pProcessHostFileW) + { + ExecuteStruct es; + es.id = EXCEPT_PROCESSHOSTFILE; + es.bDefaultResult = FALSE; + EXECUTE_FUNCTION_EX(pProcessHostFileW(hPlugin, PanelItem, ItemsNumber, OpMode), es); + bResult = es.bResult; + } + + return bResult; +} + + +int PluginW::ProcessEvent( + HANDLE hPlugin, + int Event, + PVOID Param +) +{ + BOOL bResult = FALSE; + + if (pProcessEventW) + { + ExecuteStruct es; + es.id = EXCEPT_PROCESSEVENT; + es.bDefaultResult = FALSE; + EXECUTE_FUNCTION_EX(pProcessEventW(hPlugin, Event, Param), es); + bResult = es.bResult; + } + + return bResult; +} + + +int PluginW::Compare( + HANDLE hPlugin, + const PluginPanelItem *Item1, + const PluginPanelItem *Item2, + DWORD Mode +) +{ + int nResult = -2; + + if (pCompareW) + { + ExecuteStruct es; + es.id = EXCEPT_COMPARE; + es.nDefaultResult = -2; + EXECUTE_FUNCTION_EX(pCompareW(hPlugin, Item1, Item2, Mode), es); + nResult = (int)es.nResult; + } + + return nResult; +} + + +int PluginW::GetFindData( + HANDLE hPlugin, + PluginPanelItem **pPanelItem, + int *pItemsNumber, + int OpMode +) +{ + BOOL bResult = FALSE; + + if (pGetFindDataW) + { + ExecuteStruct es; + es.id = EXCEPT_GETFINDDATA; + es.bDefaultResult = FALSE; + EXECUTE_FUNCTION_EX(pGetFindDataW(hPlugin, pPanelItem, pItemsNumber, OpMode), es); + bResult = es.bResult; + } + + return bResult; +} + + +void PluginW::FreeFindData( + HANDLE hPlugin, + PluginPanelItem *PanelItem, + int ItemsNumber +) +{ + if (pFreeFindDataW) + { + ExecuteStruct es; + es.id = EXCEPT_FREEFINDDATA; + EXECUTE_FUNCTION(pFreeFindDataW(hPlugin, PanelItem, ItemsNumber), es); + (void)es; // supress 'set but not used' warning + } +} + +int PluginW::ProcessKey( + HANDLE hPlugin, + int Key, + unsigned int dwControlState +) +{ + BOOL bResult = FALSE; + + if (pProcessKeyW) + { + ExecuteStruct es; + es.id = EXCEPT_PROCESSKEY; + es.bDefaultResult = TRUE; // do not pass this key to far on exception + EXECUTE_FUNCTION_EX(pProcessKeyW(hPlugin, Key, dwControlState), es); + bResult = es.bResult; + } + + return bResult; +} + + +void PluginW::ClosePlugin( + HANDLE hPlugin +) +{ + if (pClosePluginW) + { + ExecuteStruct es; + es.id = EXCEPT_CLOSEPLUGIN; + EXECUTE_FUNCTION(pClosePluginW(hPlugin), es); + (void)es; // supress 'set but not used' warning + } + +// m_pManager->m_pCurrentPlugin = (Plugin*)-1; +} + + +int PluginW::SetDirectory( + HANDLE hPlugin, + const wchar_t *Dir, + int OpMode +) +{ + BOOL bResult = FALSE; + + if (pSetDirectoryW) + { + ExecuteStruct es; + es.id = EXCEPT_SETDIRECTORY; + es.bDefaultResult = FALSE; + EXECUTE_FUNCTION_EX(pSetDirectoryW(hPlugin, Dir, OpMode), es); + bResult = es.bResult; + } + + return bResult; +} + + +void PluginW::GetOpenPluginInfo( + HANDLE hPlugin, + OpenPluginInfo *pInfo +) +{ +// m_pManager->m_pCurrentPlugin = this; + pInfo->StructSize = sizeof(OpenPluginInfo); + + if (pGetOpenPluginInfoW) + { + ExecuteStruct es; + es.id = EXCEPT_GETOPENPLUGININFO; + EXECUTE_FUNCTION(pGetOpenPluginInfoW(hPlugin, pInfo), es); + (void)es; // supress 'set but not used' warning + } +} + + +int PluginW::Configure( + int MenuItem +) +{ + BOOL bResult = FALSE; + + if (Load() && pConfigureW) + { + ExecuteStruct es; + es.id = EXCEPT_CONFIGURE; + es.bDefaultResult = FALSE; + EXECUTE_FUNCTION_EX(pConfigureW(MenuItem), es); + bResult = es.bResult; + } + + return bResult; +} + + +bool PluginW::GetPluginInfo(PluginInfo *pi) +{ + memset(pi, 0, sizeof(PluginInfo)); + + if (pGetPluginInfoW) + { + ExecuteStruct es; + es.id = EXCEPT_GETPLUGININFO; + EXECUTE_FUNCTION(pGetPluginInfoW(pi), es); + + if (!es.bUnloaded) + return true; + } + + return false; +} + +int PluginW::GetCustomData(const wchar_t *FilePath, wchar_t **CustomData) +{ + if (Load() && pGetCustomDataW) + { + ExecuteStruct es; + es.id = EXCEPT_GETCUSTOMDATA; + es.bDefaultResult = 0; + es.bResult = 0; + EXECUTE_FUNCTION_EX(pGetCustomDataW(FilePath, CustomData), es); + return es.bResult; + } + + return 0; +} + +void PluginW::FreeCustomData(wchar_t *CustomData) +{ + if (Load() && pFreeCustomDataW) + { + ExecuteStruct es; + es.id = EXCEPT_FREECUSTOMDATA; + EXECUTE_FUNCTION(pFreeCustomDataW(CustomData), es); + (void)es; // supress 'set but not used' warning + } +} + +bool PluginW::MayExitFAR() +{ + if (pMayExitFARW) + { + ExecuteStruct es; + es.id = EXCEPT_MAYEXITFAR; + es.bDefaultResult = 1; + EXECUTE_FUNCTION_EX(pMayExitFARW(), es); + return es.bResult; + } + + return true; +} + +void PluginW::ExitFAR() +{ + if (pExitFARW) + { + ExecuteStruct es; + es.id = EXCEPT_EXITFAR; + EXECUTE_FUNCTION(pExitFARW(), es); + (void)es; // supress 'set but not used' warning + } +} + +void PluginW::ClearExports() +{ + pSetStartupInfoW = nullptr; + pOpenPluginW = nullptr; + pOpenFilePluginW = nullptr; + pClosePluginW = nullptr; + pGetPluginInfoW = nullptr; + pGetOpenPluginInfoW = nullptr; + pGetFindDataW = nullptr; + pFreeFindDataW = nullptr; + pGetVirtualFindDataW = nullptr; + pFreeVirtualFindDataW = nullptr; + pSetDirectoryW = nullptr; + pGetFilesW = nullptr; + pPutFilesW = nullptr; + pDeleteFilesW = nullptr; + pMakeDirectoryW = nullptr; + pProcessHostFileW = nullptr; + pSetFindListW = nullptr; + pConfigureW = nullptr; + pExitFARW = nullptr; + pMayExitFARW = nullptr; + pProcessKeyW = nullptr; + pProcessEventW = nullptr; + pCompareW = nullptr; + pProcessEditorInputW = nullptr; + pProcessEditorEventW = nullptr; + pProcessViewerEventW = nullptr; + pProcessDialogEventW = nullptr; + pProcessSynchroEventW = nullptr; +#if defined(PROCPLUGINMACROFUNC) + pProcessMacroFuncW = nullptr; +#endif + pMinFarVersionW = nullptr; + pAnalyseW = nullptr; + pGetCustomDataW = nullptr; + pFreeCustomDataW = nullptr; +} + diff --git a/far2l/src/plug/PluginW.hpp b/far2l/src/plug/PluginW.hpp new file mode 100644 index 00000000..bbcd4777 --- /dev/null +++ b/far2l/src/plug/PluginW.hpp @@ -0,0 +1,226 @@ +#pragma once + +/* +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 "fpsdk/plugin.hpp" +#include "plclass.hpp" +#include "FARString.hpp" + + +typedef void (WINAPI *PLUGINCLOSEPLUGINW)(HANDLE hPlugin); +typedef int (WINAPI *PLUGINCOMPAREW)(HANDLE hPlugin,const PluginPanelItem *Item1,const PluginPanelItem *Item2,unsigned int Mode); +typedef int (WINAPI *PLUGINCONFIGUREW)(int ItemNumber); +typedef int (WINAPI *PLUGINDELETEFILESW)(HANDLE hPlugin,PluginPanelItem *PanelItem,int ItemsNumber,int OpMode); +typedef int (WINAPI *PLUGINMAYEXITFARW)(); +typedef void (WINAPI *PLUGINEXITFARW)(); +typedef void (WINAPI *PLUGINFREEFINDDATAW)(HANDLE hPlugin,PluginPanelItem *PanelItem,int ItemsNumber); +typedef void (WINAPI *PLUGINFREEVIRTUALFINDDATAW)(HANDLE hPlugin,PluginPanelItem *PanelItem,int ItemsNumber); +typedef int (WINAPI *PLUGINGETFILESW)(HANDLE hPlugin,PluginPanelItem *PanelItem,int ItemsNumber,int Move,const wchar_t **DestPath,int OpMode); +typedef int (WINAPI *PLUGINGETFINDDATAW)(HANDLE hPlugin,PluginPanelItem **pPanelItem,int *pItemsNumber,int OpMode); +typedef int (WINAPI *PLUGINMINFARVERSIONW)(); +typedef void (WINAPI *PLUGINGETOPENPLUGININFOW)(HANDLE hPlugin,OpenPluginInfo *Info); +typedef void (WINAPI *PLUGINGETPLUGININFOW)(PluginInfo *Info); +typedef int (WINAPI *PLUGINGETVIRTUALFINDDATAW)(HANDLE hPlugin,PluginPanelItem **pPanelItem,int *pItemsNumber,const wchar_t *Path); +typedef int (WINAPI *PLUGINMAKEDIRECTORYW)(HANDLE hPlugin,const wchar_t **Name,int OpMode); +typedef HANDLE(WINAPI *PLUGINOPENFILEPLUGINW)(const wchar_t *Name,const unsigned char *Data,int DataSize,int OpMode); +typedef HANDLE(WINAPI *PLUGINOPENPLUGINW)(int OpenFrom,INT_PTR Item); +typedef int (WINAPI *PLUGINPROCESSEDITOREVENTW)(int Event,void *Param); +typedef int (WINAPI *PLUGINPROCESSEDITORINPUTW)(const INPUT_RECORD *Rec); +typedef int (WINAPI *PLUGINPROCESSEVENTW)(HANDLE hPlugin,int Event,void *Param); +typedef int (WINAPI *PLUGINPROCESSHOSTFILEW)(HANDLE hPlugin,PluginPanelItem *PanelItem,int ItemsNumber,int OpMode); +typedef int (WINAPI *PLUGINPROCESSKEYW)(HANDLE hPlugin,int Key,unsigned int ControlState); +typedef int (WINAPI *PLUGINPUTFILESW)(HANDLE hPlugin,PluginPanelItem *PanelItem,int ItemsNumber,int Move,const wchar_t *SrcPath,int OpMode); +typedef int (WINAPI *PLUGINSETDIRECTORYW)(HANDLE hPlugin,const wchar_t *Dir,int OpMode); +typedef int (WINAPI *PLUGINSETFINDLISTW)(HANDLE hPlugin,const PluginPanelItem *PanelItem,int ItemsNumber); +typedef void (WINAPI *PLUGINSETSTARTUPINFOW)(const PluginStartupInfo *Info); +typedef int (WINAPI *PLUGINPROCESSVIEWEREVENTW)(int Event,void *Param); //* $ 27.09.2000 SVS - События во вьювере +typedef int (WINAPI *PLUGINPROCESSDIALOGEVENTW)(int Event,void *Param); +typedef int (WINAPI *PLUGINPROCESSSYNCHROEVENTW)(int Event,void *Param); +#if defined(PROCPLUGINMACROFUNC) +typedef int (WINAPI *PLUGINPROCESSMACROFUNCW)(const wchar_t *Name, const FarMacroValue *Params, int nParams, FarMacroValue **Results, int *nResults); +#endif +typedef int (WINAPI *PLUGINANALYSEW)(const AnalyseData *pData); +typedef int (WINAPI *PLUGINGETCUSTOMDATAW)(const wchar_t *FilePath, wchar_t **CustomData); +typedef void (WINAPI *PLUGINFREECUSTOMDATAW)(wchar_t *CustomData); + + +class PluginW: public Plugin +{ + private: + PLUGINSETSTARTUPINFOW pSetStartupInfoW; + PLUGINOPENPLUGINW pOpenPluginW; + PLUGINOPENFILEPLUGINW pOpenFilePluginW; + PLUGINCLOSEPLUGINW pClosePluginW; + PLUGINGETPLUGININFOW pGetPluginInfoW; + PLUGINGETOPENPLUGININFOW pGetOpenPluginInfoW; + PLUGINGETFINDDATAW pGetFindDataW; + PLUGINFREEFINDDATAW pFreeFindDataW; + PLUGINGETVIRTUALFINDDATAW pGetVirtualFindDataW; + PLUGINFREEVIRTUALFINDDATAW pFreeVirtualFindDataW; + PLUGINSETDIRECTORYW pSetDirectoryW; + PLUGINGETFILESW pGetFilesW; + PLUGINPUTFILESW pPutFilesW; + PLUGINDELETEFILESW pDeleteFilesW; + PLUGINMAKEDIRECTORYW pMakeDirectoryW; + PLUGINPROCESSHOSTFILEW pProcessHostFileW; + PLUGINSETFINDLISTW pSetFindListW; + PLUGINCONFIGUREW pConfigureW; + PLUGINMAYEXITFARW pMayExitFARW; + PLUGINEXITFARW pExitFARW; + PLUGINPROCESSKEYW pProcessKeyW; + PLUGINPROCESSEVENTW pProcessEventW; + PLUGINPROCESSEDITOREVENTW pProcessEditorEventW; + PLUGINCOMPAREW pCompareW; + PLUGINPROCESSEDITORINPUTW pProcessEditorInputW; + PLUGINMINFARVERSIONW pMinFarVersionW; + PLUGINPROCESSVIEWEREVENTW pProcessViewerEventW; + PLUGINPROCESSDIALOGEVENTW pProcessDialogEventW; + PLUGINPROCESSSYNCHROEVENTW pProcessSynchroEventW; +#if defined(PROCPLUGINMACROFUNC) + PLUGINPROCESSMACROFUNCW pProcessMacroFuncW; +#endif + PLUGINANALYSEW pAnalyseW; + PLUGINGETCUSTOMDATAW pGetCustomDataW; + PLUGINFREECUSTOMDATAW pFreeCustomDataW; + + public: + + PluginW(PluginManager *owner, + const FARString &strModuleName, + const std::string &settingsName, + const std::string &moduleID); + ~PluginW(); + + bool IsOemPlugin() {return false;} + + bool Load(); + bool LoadFromCache(); + + bool SaveToCache(); + + int Unload(bool bExitFAR = false); + + bool IsPanelPlugin(); + + bool HasOpenPlugin() { return pOpenPluginW!=nullptr; } + bool HasMakeDirectory() { return pMakeDirectoryW!=nullptr; } + bool HasDeleteFiles() { return pDeleteFilesW!=nullptr; } + bool HasPutFiles() { return pPutFilesW!=nullptr; } + bool HasGetFiles() { return pGetFilesW!=nullptr; } + bool HasSetStartupInfo() { return pSetStartupInfoW!=nullptr; } + bool HasOpenFilePlugin() { return pOpenFilePluginW!=nullptr; } + bool HasClosePlugin() { return pClosePluginW!=nullptr; } + bool HasGetPluginInfo() { return pGetPluginInfoW!=nullptr; } + bool HasGetOpenPluginInfo() { return pGetOpenPluginInfoW!=nullptr; } + bool HasGetFindData() { return pGetFindDataW!=nullptr; } + bool HasFreeFindData() { return pFreeFindDataW!=nullptr; } + bool HasGetVirtualFindData() { return pGetVirtualFindDataW!=nullptr; } + bool HasFreeVirtualFindData() { return pFreeVirtualFindDataW!=nullptr; } + bool HasSetDirectory() { return pSetDirectoryW!=nullptr; } + bool HasProcessHostFile() { return pProcessHostFileW!=nullptr; } + bool HasSetFindList() { return pSetFindListW!=nullptr; } + bool HasConfigure() { return pConfigureW!=nullptr; } + bool HasMayExitFAR() { return pMayExitFARW!=nullptr; } + bool HasExitFAR() { return pExitFARW!=nullptr; } + bool HasProcessKey() { return pProcessKeyW!=nullptr; } + bool HasProcessEvent() { return pProcessEventW!=nullptr; } + bool HasProcessEditorEvent() { return pProcessEditorEventW!=nullptr; } + bool HasCompare() { return pCompareW!=nullptr; } + bool HasProcessEditorInput() { return pProcessEditorInputW!=nullptr; } + bool HasMinFarVersion() { return pMinFarVersionW!=nullptr; } + bool HasProcessViewerEvent() { return pProcessViewerEventW!=nullptr; } + bool HasProcessDialogEvent() { return pProcessDialogEventW!=nullptr; } + bool HasProcessSynchroEvent() { return pProcessSynchroEventW!=nullptr; } +#if defined(PROCPLUGINMACROFUNC) + bool HasProcessMacroFunc() { return pProcessMacroFuncW!=nullptr; } +#endif + bool HasAnalyse() { return pAnalyseW!=nullptr; } + bool HasGetCustomData() { return pGetCustomDataW!=nullptr; } + bool HasFreeCustomData() { return pFreeCustomDataW!=nullptr; } + const FARString &GetModuleName() { return m_strModuleName; } + const char *GetSettingsName() { return m_strSettingsName.c_str(); } + DWORD GetSysID() { return SysID; } + bool CheckWorkFlags(DWORD flags) { return WorkFlags.Check(flags)==TRUE; } + DWORD GetWorkFlags() { return WorkFlags.Flags; } + DWORD GetFuncFlags() { return FuncFlags.Flags; } + + bool InitLang(const wchar_t *Path) { return Lang.Init(Path,true); } + void CloseLang() { Lang.Close(); } + const wchar_t *GetMsg(int nID) { return Lang.GetMsg(nID); } + + public: + + bool SetStartupInfo(bool &bUnloaded); + bool CheckMinFarVersion(bool &bUnloaded); + + int Analyse(const AnalyseData *pData); + + HANDLE OpenPlugin(int OpenFrom, INT_PTR Item); + HANDLE OpenFilePlugin(const wchar_t *Name, const unsigned char *Data, int DataSize, int OpMode); + + int SetFindList(HANDLE hPlugin, const PluginPanelItem *PanelItem, int ItemsNumber); + int GetFindData(HANDLE hPlugin, PluginPanelItem **pPanelItem, int *pItemsNumber, int OpMode); + int GetVirtualFindData(HANDLE hPlugin, PluginPanelItem **pPanelItem, int *pItemsNumber, const wchar_t *Path); + int SetDirectory(HANDLE hPlugin, const wchar_t *Dir, int OpMode); + int GetFiles(HANDLE hPlugin, PluginPanelItem *PanelItem, int ItemsNumber, int Move, const wchar_t **DestPath, int OpMode); + int PutFiles(HANDLE hPlugin, PluginPanelItem *PanelItem, int ItemsNumber, int Move, int OpMode); + int DeleteFiles(HANDLE hPlugin, PluginPanelItem *PanelItem, int ItemsNumber, int OpMode); + int MakeDirectory(HANDLE hPlugin, const wchar_t **Name, int OpMode); + int ProcessHostFile(HANDLE hPlugin, PluginPanelItem *PanelItem, int ItemsNumber, int OpMode); + int ProcessKey(HANDLE hPlugin, int Key, unsigned int dwControlState); + int ProcessEvent(HANDLE hPlugin, int Event, PVOID Param); + int Compare(HANDLE hPlugin, const PluginPanelItem *Item1, const PluginPanelItem *Item2, DWORD Mode); + + int GetCustomData(const wchar_t *FilePath, wchar_t **CustomData); + void FreeCustomData(wchar_t *CustomData); + + void GetOpenPluginInfo(HANDLE hPlugin, OpenPluginInfo *Info); + void FreeFindData(HANDLE hPlugin, PluginPanelItem *PanelItem, int ItemsNumber); + void FreeVirtualFindData(HANDLE hPlugin, PluginPanelItem *PanelItem, int ItemsNumber); + void ClosePlugin(HANDLE hPlugin); + + int ProcessEditorInput(const INPUT_RECORD *D); + int ProcessEditorEvent(int Event, PVOID Param); + int ProcessViewerEvent(int Event, PVOID Param); + int ProcessDialogEvent(int Event, PVOID Param); + int ProcessSynchroEvent(int Event, PVOID Param); +#if defined(PROCPLUGINMACROFUNC) + int ProcessMacroFunc(const wchar_t *Name, const FarMacroValue *Params, int nParams, FarMacroValue **Results, int *nResults); +#endif + + bool GetPluginInfo(PluginInfo *pi); + int Configure(int MenuItem); + + bool MayExitFAR(); + void ExitFAR(); + + private: + + void ClearExports(); +}; diff --git a/far2l/src/plug/plclass.cpp b/far2l/src/plug/plclass.cpp new file mode 100644 index 00000000..5ded795f --- /dev/null +++ b/far2l/src/plug/plclass.cpp @@ -0,0 +1,102 @@ +#include "headers.hpp" +#include "plclass.hpp" +#include "config.hpp" +#include "pathmix.hpp" +#include "dirmix.hpp" +#include "lang.hpp" +#include "message.hpp" +#include "plugins.hpp" + +#include <errno.h> +#include <dlfcn.h> + +Plugin::Plugin(PluginManager *owner, + const FARString &strModuleName, + const std::string &settingsName, + const std::string &moduleID) + : + m_owner(owner), + m_strModuleName(strModuleName), + m_strSettingsName(settingsName), + m_strModuleID(moduleID) +{ + strRootKey = Opt.strRegRoot; + strRootKey += L"/Plugins"; +} + +Plugin::~Plugin() +{ + Lang.Close(); +} + +void *Plugin::GetModulePFN(const char *fn) +{ + void *out = dlsym(m_hModule, fn); + if (!out) + fprintf(stderr, "Plugin '%ls' doesn't export '%s'\n", PointToName(m_strModuleName), fn); + + return out; +} + +bool Plugin::OpenModule() +{ + if (m_hModule) + return true; + + if (WorkFlags.Check(PIWF_DONTLOADAGAIN)) + return false; + + char saved_cwd_buf[MAX_PATH + 1]{}; + char *saved_cwd = sdc_getcwd(saved_cwd_buf, MAX_PATH); + + FARString strModulePath = m_strModuleName.Clone(); + CutToSlash(strModulePath); + if (sdc_chdir(strModulePath.GetMB().c_str()) == -1 ) + fprintf(stderr, "Error %d chdir for plugin '%ls'\n", errno, m_strModuleName.CPtr()); + + const std::string &mbPath = m_strModuleName.GetMB(); + m_hModule = dlopen(mbPath.c_str(), RTLD_LOCAL|RTLD_LAZY); + + if (m_hModule) + { + void (*pPluginModuleOpen)(const char *path); + GetModuleFN(pPluginModuleOpen, "PluginModuleOpen"); + if (pPluginModuleOpen) + pPluginModuleOpen(mbPath.c_str()); + } + else + { + std::wstring strerr; + const char *dle = dlerror(); + if (dle) { + fprintf(stderr, "dlerror: %s\n", dle); + const char *colon = strchr(dle, ':'); + MB2Wide(colon ? colon + 1 : dle, strerr); + } + + // avoid recurring and even recursive error message + WorkFlags.Set(PIWF_DONTLOADAGAIN); + if (!Opt.LoadPlug.SilentLoadPlugin) //убрать в PluginSet + { + SetMessageHelp(L"ErrLoadPlugin module"); + //|MSG_ERRORTYPE + Message(MSG_WARNING, 1, MSG(MError), strerr.c_str(), MSG(MPlgLoadPluginError), m_strModuleName, MSG(MOk)); + } + } + + ErrnoSaver Err; + if (saved_cwd) + sdc_chdir(saved_cwd); + + return (!!m_hModule); +} + +void Plugin::CloseModule() +{ + if (m_hModule) + { + dlclose(m_hModule); + m_hModule = nullptr; + } +} + diff --git a/far2l/src/plug/plclass.hpp b/far2l/src/plug/plclass.hpp new file mode 100644 index 00000000..5d42decc --- /dev/null +++ b/far2l/src/plug/plclass.hpp @@ -0,0 +1,194 @@ +#pragma once + +/* +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 "fpsdk/plugin.hpp" +#include "language.hpp" +#include "bitflags.hpp" +#include "FARString.hpp" +#include <string> + +struct AnalyseData +{ + int StructSize; + const wchar_t *lpwszFileName; + const unsigned char *pBuffer; + DWORD dwBufferSize; + int OpMode; +}; + + +class PluginManager; + +class Plugin +{ + void *m_hModule = nullptr; + void *GetModulePFN(const char *fn); + + protected: + PluginManager *m_owner; //BUGBUG + + FARString m_strModuleName; + std::string m_strSettingsName; + std::string m_strModuleID; + FARString strRootKey; + + BitFlags WorkFlags{}; // рабочие флаги текущего плагина + BitFlags FuncFlags{}; // битовые маски вызова эксп.функций плагина + + bool m_Loaded = false; + + /* $ 21.09.2000 SVS + поле - системный идентификатор плагина + Плагин должен сам задавать, например для + Network = 0x5774654E (NetW) + PrintManager = 0x6E614D50 (PMan) SYSID_PRINTMANAGER + */ + DWORD SysID = 0; + + Language Lang; // implicitly used by MSG(..) macro + + bool OpenModule(); + void CloseModule(); + + template <class TFN> + void GetModuleFN(TFN &fn, const char *api) + { + fn = (TFN)GetModulePFN(api); + } + + public: + Plugin(PluginManager *owner, + const FARString &strModuleName, + const std::string &settingsName, + const std::string &moduleID); + + virtual ~Plugin(); + + virtual bool IsOemPlugin() = 0; + + virtual bool Load() = 0; + virtual bool LoadFromCache() = 0; + + virtual bool SaveToCache() = 0; + + virtual int Unload(bool bExitFAR = false) = 0; + + virtual bool IsPanelPlugin() = 0; + + virtual bool HasOpenPlugin() = 0; + virtual bool HasMakeDirectory() = 0; + virtual bool HasDeleteFiles() = 0; + virtual bool HasPutFiles() = 0; + virtual bool HasGetFiles() = 0; + virtual bool HasSetStartupInfo() = 0; + virtual bool HasOpenFilePlugin() = 0; + virtual bool HasClosePlugin() = 0; + virtual bool HasGetPluginInfo() = 0; + virtual bool HasGetOpenPluginInfo() = 0; + virtual bool HasGetFindData() = 0; + virtual bool HasFreeFindData() = 0; + virtual bool HasGetVirtualFindData() = 0; + virtual bool HasFreeVirtualFindData() = 0; + virtual bool HasSetDirectory() = 0; + virtual bool HasProcessHostFile() = 0; + virtual bool HasSetFindList() = 0; + virtual bool HasConfigure() = 0; + virtual bool HasMayExitFAR() = 0; + virtual bool HasExitFAR() = 0; + virtual bool HasProcessKey() = 0; + virtual bool HasProcessEvent() = 0; + virtual bool HasProcessEditorEvent() = 0; + virtual bool HasCompare() = 0; + virtual bool HasProcessEditorInput() = 0; + virtual bool HasMinFarVersion() = 0; + virtual bool HasProcessViewerEvent() = 0; + virtual bool HasProcessDialogEvent() = 0; + virtual bool HasProcessSynchroEvent() = 0; + virtual bool HasAnalyse() = 0; + virtual bool HasGetCustomData() = 0; + virtual bool HasFreeCustomData() = 0; +#if defined(PROCPLUGINMACROFUNC) + virtual bool HasProcessMacroFunc() = 0; +#endif + + virtual const FARString &GetModuleName() = 0; + virtual const char *GetSettingsName() = 0; + virtual DWORD GetSysID() = 0; + virtual bool CheckWorkFlags(DWORD flags) = 0; + virtual DWORD GetWorkFlags() = 0; + virtual DWORD GetFuncFlags() = 0; + + virtual bool InitLang(const wchar_t *Path) = 0; + virtual void CloseLang() = 0; + + virtual bool SetStartupInfo(bool &bUnloaded) = 0; + virtual bool CheckMinFarVersion(bool &bUnloaded) = 0; + + virtual HANDLE OpenPlugin(int OpenFrom, INT_PTR Item) = 0; + virtual HANDLE OpenFilePlugin(const wchar_t *Name, const unsigned char *Data, int DataSize, int OpMode) = 0; + + virtual int SetFindList(HANDLE hPlugin, const PluginPanelItem *PanelItem, int ItemsNumber) = 0; + virtual int GetFindData(HANDLE hPlugin, PluginPanelItem **pPanelItem, int *pItemsNumber, int OpMode) = 0; + virtual int GetVirtualFindData(HANDLE hPlugin, PluginPanelItem **pPanelItem, int *pItemsNumber, const wchar_t *Path) = 0; + virtual int SetDirectory(HANDLE hPlugin, const wchar_t *Dir, int OpMode) = 0; + virtual int GetFiles(HANDLE hPlugin, PluginPanelItem *PanelItem, int ItemsNumber, int Move, const wchar_t **DestPath, int OpMode) = 0; + virtual int PutFiles(HANDLE hPlugin, PluginPanelItem *PanelItem, int ItemsNumber, int Move, int OpMode) = 0; + virtual int DeleteFiles(HANDLE hPlugin, PluginPanelItem *PanelItem, int ItemsNumber, int OpMode) = 0; + virtual int MakeDirectory(HANDLE hPlugin, const wchar_t **Name, int OpMode) = 0; + virtual int ProcessHostFile(HANDLE hPlugin, PluginPanelItem *PanelItem, int ItemsNumber, int OpMode) = 0; + virtual int ProcessKey(HANDLE hPlugin, int Key, unsigned int dwControlState) = 0; + virtual int ProcessEvent(HANDLE hPlugin, int Event, PVOID Param) = 0; + virtual int Compare(HANDLE hPlugin, const PluginPanelItem *Item1, const PluginPanelItem *Item2, DWORD Mode) = 0; + + virtual int GetCustomData(const wchar_t *FilePath, wchar_t **CustomData) = 0; + virtual void FreeCustomData(wchar_t *CustomData) = 0; + + virtual void GetOpenPluginInfo(HANDLE hPlugin, OpenPluginInfo *Info) = 0; + virtual void FreeFindData(HANDLE hPlugin, PluginPanelItem *PanelItem, int ItemsNumber) = 0; + virtual void FreeVirtualFindData(HANDLE hPlugin, PluginPanelItem *PanelItem, int ItemsNumber) = 0; + virtual void ClosePlugin(HANDLE hPlugin) = 0; + + virtual int ProcessEditorInput(const INPUT_RECORD *D) = 0; + virtual int ProcessEditorEvent(int Event, PVOID Param) = 0; + virtual int ProcessViewerEvent(int Event, PVOID Param) = 0; + virtual int ProcessDialogEvent(int Event, PVOID Param) = 0; + virtual int ProcessSynchroEvent(int Event, PVOID Param) = 0; +#if defined(PROCPLUGINMACROFUNC) + virtual int ProcessMacroFunc(const wchar_t *Name, const FarMacroValue *Params, int nParams, FarMacroValue **Results, int *nResults) = 0; +#endif + + virtual int Analyse(const AnalyseData *pData) = 0; + + virtual bool GetPluginInfo(PluginInfo *pi) = 0; + virtual int Configure(int MenuItem) = 0; + + virtual bool MayExitFAR() = 0; + virtual void ExitFAR() = 0; +}; diff --git a/far2l/src/plug/plugapi.cpp b/far2l/src/plug/plugapi.cpp new file mode 100644 index 00000000..6a616926 --- /dev/null +++ b/far2l/src/plug/plugapi.cpp @@ -0,0 +1,2609 @@ +/* +plugapi.cpp + +API, доступное плагинам (диалоги, меню, ...) +*/ +/* +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" + + +#include "plugapi.hpp" +#include "keys.hpp" +#include "lang.hpp" +#include "help.hpp" +#include "vmenu.hpp" +#include "dialog.hpp" +#include "filepanels.hpp" +#include "panel.hpp" +#include "cmdline.hpp" +#include "scantree.hpp" +#include "rdrwdsk.hpp" +#include "fileview.hpp" +#include "fileedit.hpp" +#include "plugins.hpp" +#include "savescr.hpp" +#include "manager.hpp" +#include "ctrlobj.hpp" +#include "frame.hpp" +#include "scrbuf.hpp" +#include "lockscrn.hpp" +#include "constitle.hpp" +#include "TPreRedrawFunc.hpp" +#include "syslog.hpp" +#include "interf.hpp" +#include "keyboard.hpp" +#include "palette.hpp" +#include "message.hpp" +#include "filefilter.hpp" +#include "fileowner.hpp" +#include "stddlg.hpp" +#include "pathmix.hpp" +#include "exitcode.hpp" +#include "processname.hpp" +#include "synchro.hpp" +#include "RegExp.hpp" +#include "console.hpp" +#include "InterThreadCall.hpp" + +wchar_t *WINAPI FarItoa(int value, wchar_t *string, int radix) +{ + if (string) + return _itow(value,string,radix); + + return nullptr; +} + +wchar_t *WINAPI FarItoa64(int64_t value, wchar_t *string, int radix) +{ + if (string) + return _i64tow(value, string, radix); + + return nullptr; +} + +int WINAPI FarAtoi(const wchar_t *s) +{ + if (s) + return _wtoi(s); + + return 0; +} +int64_t WINAPI FarAtoi64(const wchar_t *s) +{ + return s?_wtoi64(s):0; +} + +void WINAPI FarQsort(void *base, size_t nelem, size_t width, + int (__cdecl *fcmp)(const void *, const void *)) +{ + if (base && fcmp) + far_qsort(base,nelem,width,fcmp); +} + +void WINAPI FarQsortEx(void *base, size_t nelem, size_t width, + int (__cdecl *fcmp)(const void *, const void *,void *user),void *user) +{ + if (base && fcmp) + far_qsortex(base,nelem,width,fcmp,user); +} + +void *WINAPI FarBsearch(const void *key, const void *base, size_t nelem, size_t width, int (__cdecl *fcmp)(const void *, const void *)) +{ + if (key && fcmp && base) + return bsearch(key,base,nelem,width,fcmp); + + return nullptr; +} + +void WINAPI DeleteBuffer(void *Buffer) +{ + if (Buffer) free(Buffer); +} + +static void ScanPluginDir(); + +/* $ 07.12.2001 IS + Обертка вокруг GetString для плагинов - с меньшей функциональностью. + Сделано для того, чтобы не дублировать код GetString. +*/ +static int FarInputBoxSynched( + const wchar_t *Title, + const wchar_t *Prompt, + const wchar_t *HistoryName, + const wchar_t *SrcText, + wchar_t *DestText, + int DestLength, + const wchar_t *HelpTopic, + DWORD Flags +) +{ + if (FrameManager->ManagerIsDown()) + return FALSE; + + FARString strDest; + int nResult = GetString(Title,Prompt,HistoryName,SrcText,strDest,HelpTopic,Flags&~FIB_CHECKBOX,nullptr,nullptr); + far_wcsncpy(DestText, strDest, DestLength+1); + return nResult; +} + +int WINAPI FarInputBox( + const wchar_t *Title, + const wchar_t *Prompt, + const wchar_t *HistoryName, + const wchar_t *SrcText, + wchar_t *DestText, + int DestLength, + const wchar_t *HelpTopic, + DWORD Flags +) +{ + return InterThreadCall<int, 0>(std::bind(FarInputBoxSynched, Title, Prompt, HistoryName, SrcText, DestText, DestLength, HelpTopic, Flags)); +} + +/* Функция вывода помощи */ +BOOL WINAPI FarShowHelpSynched( + const wchar_t *ModuleName, + const wchar_t *HelpTopic, + DWORD Flags +) +{ + if (FrameManager->ManagerIsDown()) + return FALSE; + + if (!HelpTopic) + HelpTopic=L"Contents"; + + DWORD OFlags=Flags; + Flags&=~(FHELP_NOSHOWERROR|FHELP_USECONTENTS); + FARString strPath, strTopic; + FARString strMask; + + // двоеточие в начале топика надо бы игнорировать и в том случае, + // если стоит FHELP_FARHELP... + if ((Flags&FHELP_FARHELP) || *HelpTopic==L':') + strTopic = HelpTopic+((*HelpTopic == L':')?1:0); + else + { + if (ModuleName) + { + // FHELP_SELFHELP=0 - трактовать первый пар-р как Info.ModuleName + // и показать топик из хелпа вызвавшего плагина + /* $ 17.11.2000 SVS + А значение FHELP_SELFHELP равно чему? Правильно - 0 + И фигля здесь удивлятся тому, что функция не работает :-( + */ + if (Flags == FHELP_SELFHELP || (Flags&(FHELP_CUSTOMFILE|FHELP_CUSTOMPATH))) + { + strPath = ModuleName; + + if (Flags == FHELP_SELFHELP || (Flags&(FHELP_CUSTOMFILE))) + { + if (Flags&FHELP_CUSTOMFILE) + strMask=PointToName(strPath); + else + strMask.Clear(); + + CutToSlash(strPath); + } + } + else + return FALSE; + + strTopic.Format(HelpFormatLink,strPath.CPtr(),HelpTopic); + } + else + return FALSE; + } + + { + Help Hlp(strTopic,strMask,OFlags); + + if (Hlp.GetError()) + return FALSE; + } + + return TRUE; +} + +BOOL WINAPI FarShowHelp( + const wchar_t *ModuleName, + const wchar_t *HelpTopic, + DWORD Flags ) +{ + return InterThreadCall<BOOL, FALSE>(std::bind(FarShowHelpSynched, ModuleName, HelpTopic, Flags)); +} + +/* $ 05.07.2000 IS + Функция, которая будет действовать и в редакторе, и в панелях, и... +*/ +static INT_PTR WINAPI FarAdvControlSynched(INT_PTR ModuleNumber, int Command, void *Param) +{ + if (ACTL_SYNCHRO==Command) //must be first + { + PluginSynchroManager.Synchro(true, ModuleNumber, Param); + return 0; + } + + struct Opt2Flags + { + int *Opt; + DWORD Flags; + }; + + switch (Command) + { + case ACTL_GETFARVERSION: + case ACTL_GETSYSWORDDIV: + case ACTL_GETCOLOR: + case ACTL_GETARRAYCOLOR: + case ACTL_GETFARHWND: + case ACTL_GETSYSTEMSETTINGS: + case ACTL_GETPANELSETTINGS: + case ACTL_GETINTERFACESETTINGS: + case ACTL_GETCONFIRMATIONS: + case ACTL_GETDESCSETTINGS: + case ACTL_GETPOLICIES: + case ACTL_GETPLUGINMAXREADDATA: + case ACTL_GETMEDIATYPE: + case ACTL_SETPROGRESSSTATE: + case ACTL_SETPROGRESSVALUE: + case ACTL_GETFARRECT: + case ACTL_GETCURSORPOS: + case ACTL_SETCURSORPOS: + case ACTL_PROGRESSNOTIFY: + break; + default: + + if (FrameManager && FrameManager->ManagerIsDown()) + return 0; + } + + switch (Command) + { + case ACTL_GETFARVERSION: + { + if (Param) + *(DWORD*)Param=FAR_VERSION; + + return FAR_VERSION; + } + case ACTL_GETPLUGINMAXREADDATA: + { + return Opt.PluginMaxReadData; + } + case ACTL_GETSYSWORDDIV: + { + if (Param) + wcscpy((wchar_t *)Param,Opt.strWordDiv); + + return (int)Opt.strWordDiv.GetLength()+1; + } + /* $ 24.08.2000 SVS + ожидать определенную (или любую) клавишу + (int)Param - внутренний код клавиши, которую ожидаем, или -1 + если все равно какую клавишу ждать. + возвращает 0; + */ + case ACTL_WAITKEY: + { + return WaitKey(Param?(DWORD)(DWORD_PTR)Param:(DWORD)-1,0,false); + } + /* $ 04.12.2000 SVS + ACTL_GETCOLOR - получить определенный цвет по индекс, определенному + в farcolor.hpp + (int)Param - индекс. + Return - значение цвета или -1 если индекс неверен. + */ + case ACTL_GETCOLOR: + { + if ((int)(INT_PTR)Param < SizeArrayPalette && (int)(INT_PTR)Param >= 0) + return (int)((unsigned int)Palette[(int)(INT_PTR)Param]); + + return -1; + } + /* $ 04.12.2000 SVS + ACTL_GETARRAYCOLOR - получить весь массив цветов + Param - указатель на массив или nullptr - чтобы получить размер буфера + Return - размер массива. + */ + case ACTL_GETARRAYCOLOR: + { + if (Param) + memcpy(Param,Palette,SizeArrayPalette); + + return SizeArrayPalette; + } + /* + Param=FARColor{ + DWORD Flags; + int StartIndex; + int ColorItem; + LPBYTE Colors; + }; + */ + case ACTL_SETARRAYCOLOR: + { + if (Param) + { + FarSetColors *Pal=(FarSetColors*)Param; + + if (Pal->Colors && + Pal->StartIndex >= 0 && + Pal->StartIndex+Pal->ColorCount <= SizeArrayPalette) + { + memmove(Palette+Pal->StartIndex,Pal->Colors,Pal->ColorCount); + + if (Pal->Flags&FCLR_REDRAW) + { + ScrBuf.Lock(); // отменяем всякую прорисовку + FrameManager->ResizeAllFrame(); + FrameManager->PluginCommit(); // коммитим. + ScrBuf.Unlock(); // разрешаем прорисовку + } + + return TRUE; + } + } + + return FALSE; + } + /* $ 14.12.2000 SVS + ACTL_EJECTMEDIA - извлечь диск из съемного накопителя + Param - указатель на структуру ActlEjectMedia + Return - TRUE - успешное извлечение, FALSE - ошибка. + */ + case ACTL_EJECTMEDIA: + { + return FALSE;/*Param?EjectVolume((wchar_t)((ActlEjectMedia*)Param)->Letter, + ((ActlEjectMedia*)Param)->Flags):FALSE;*/ + /* + if(Param) + { + ActlEjectMedia *aem=(ActlEjectMedia *)Param; + char DiskLetter[4]=" :/"; + DiskLetter[0]=(char)aem->Letter; + int DriveType = FAR_GetDriveType(DiskLetter,nullptr,FALSE); // здесь не определяем тип CD + + if(DriveType == DRIVE_USBDRIVE && RemoveUSBDrive((char)aem->Letter,aem->Flags)) + return TRUE; + if(DriveType == DRIVE_SUBSTITUTE && DelSubstDrive(DiskLetter)) + return TRUE; + if(IsDriveTypeCDROM(DriveType) && EjectVolume((char)aem->Letter,aem->Flags)) + return TRUE; + + } + return FALSE; + */ + } + /* + case ACTL_GETMEDIATYPE: + { + ActlMediaType *amt=(ActlMediaType *)Param; + char DiskLetter[4]=" :/"; + DiskLetter[0]=(amt)?(char)amt->Letter:0; + return FAR_GetDriveType(DiskLetter,nullptr,(amt && !(amt->Flags&MEDIATYPE_NODETECTCDROM)?TRUE:FALSE)); + } + */ + /* $ 21.12.2000 SVS + Macro API + */ + case ACTL_KEYMACRO: + { + if (CtrlObject && Param) // все зависит от этой бадяги. + { + KeyMacro& Macro=CtrlObject->Macro; //?? + ActlKeyMacro *KeyMacro=(ActlKeyMacro*)Param; + + switch (KeyMacro->Command) + { + case MCMD_LOADALL: // из реестра в память ФАР с затиранием предыдущего + { + if (Macro.IsRecording()) + return FALSE; + + return Macro.LoadMacros(!Macro.IsExecuting()); + } + case MCMD_SAVEALL: // из памяти ФАРа в реестра + { + if (Macro.IsRecording()) // || Macro.IsExecuting()) + return FALSE; + + Macro.SaveMacros(); + return TRUE; + } + case MCMD_POSTMACROSTRING: + { + if (KeyMacro->Param.PlainText.SequenceText && *KeyMacro->Param.PlainText.SequenceText) + return Macro.PostNewMacro(KeyMacro->Param.PlainText.SequenceText,KeyMacro->Param.PlainText.Flags<<8,KeyMacro->Param.PlainText.AKey); + + return FALSE; + } + case MCMD_RUNMACROSTRING: + { + return FALSE; + } + case MCMD_CHECKMACRO: // проверка макроса + { + MacroRecord CurMacro{}; + int Ret=Macro.ParseMacroString(&CurMacro,KeyMacro->Param.PlainText.SequenceText,(KeyMacro->Param.PlainText.Flags&KSFLAGS_SILENTCHECK)?TRUE:FALSE); + + if (Ret) + { + if (CurMacro.BufferSize > 1) + free(CurMacro.Buffer); + memset(&KeyMacro->Param.MacroResult,0,sizeof(struct MacroParseResult)); + } + else + { + static FARString ErrSrc; + Macro.GetMacroParseError(&KeyMacro->Param.MacroResult.ErrCode,&KeyMacro->Param.MacroResult.ErrPos,&ErrSrc); + KeyMacro->Param.MacroResult.ErrSrc=ErrSrc; + } + + return Ret; + } + case MCMD_GETSTATE: + { + return Macro.GetCurRecord(nullptr,nullptr); + } + + case MCMD_GETAREA: + { + return Macro.GetMode(); + } +#if 0 + case MCMD_COMPILEMACRO: + { + MacroRecord CurMacro={0}; + int Ret=Macro.ParseMacroString(&CurMacro,KeyMacro->Param.PlainText.SequenceText); + + if (Ret) + { + //KeyMacro->Params.Compile.Flags=CurMacro.Flags; + KeyMacro->Param.Compile.Sequence=CurMacro.Buffer; + KeyMacro->Param.Compile.Count=CurMacro.BufferSize; + } + + return Ret; + } +#endif + } + } + + return FALSE; + } + case ACTL_POSTKEYSEQUENCE: + { + if (CtrlObject && Param && ((KeySequence*)Param)->Count > 0) + { + MacroRecord MRec{}; + MRec.Flags=(((KeySequence*)Param)->Flags)<<8; + MRec.BufferSize=((KeySequence*)Param)->Count; + + if (MRec.BufferSize == 1) + MRec.Buffer=(DWORD *)(DWORD_PTR)((KeySequence*)Param)->Sequence[0]; + else + MRec.Buffer=const_cast<DWORD*>(((KeySequence*)Param)->Sequence); + + return CtrlObject->Macro.PostNewMacro(&MRec,TRUE,TRUE); +#if 0 + // Этот кусок - для дальнейших экспериментов + { + //CtrlObject->Macro.PostNewMacro(&MRec); + for (int I=0; I < MRec.BufferSize; ++I) + { + int Key=MRec.Buffer[I]; + + if (CtrlObject->Macro.ProcessKey(Key)) + { + while ((Key=CtrlObject->Macro.GetKey()) ) + { + FrameManager->ProcessKey(Key); + } + } + else + FrameManager->ProcessKey(Key); + + FrameManager->PluginCommit(); + } + + return TRUE; + } +#endif + } + + return FALSE; + } + /* $ 05.06.2001 tran + новые ACTL_ для работы с фреймами */ + case ACTL_GETWINDOWINFO: + /* $ 12.04.2005 AY + thread safe window info */ + case ACTL_GETSHORTWINDOWINFO: + { + if (FrameManager && Param) + { + FARString strType, strName; + WindowInfo *wi=(WindowInfo*)Param; + Frame *f; + + /* $ 22.12.2001 VVM + + Если Pos == -1 то берем текущий фрейм */ + if (wi->Pos == -1) + f=FrameManager->GetCurrentFrame(); + else + f=FrameManager->operator[](wi->Pos); + + if (!f) + return FALSE; + + if (Command==ACTL_GETWINDOWINFO) + { + f->GetTypeAndName(strType, strName); + + if (wi->TypeNameSize && wi->TypeName) + { + far_wcsncpy(wi->TypeName,strType,wi->TypeNameSize); + } + else + { + wi->TypeNameSize=static_cast<int>(strType.GetLength()+1); + } + + if (wi->NameSize && wi->Name) + { + far_wcsncpy(wi->Name,strName,wi->NameSize); + } + else + { + wi->NameSize=static_cast<int>(strName.GetLength()+1); + } + } + else + { + wi->TypeName=nullptr; + wi->Name=nullptr; + wi->NameSize=0; + wi->TypeName=0; + } + + wi->Pos=FrameManager->IndexOf(f); + wi->Type=f->GetType(); + wi->Modified=f->IsFileModified(); + wi->Current=f==FrameManager->GetCurrentFrame(); + return TRUE; + } + + return FALSE; + } + case ACTL_GETWINDOWCOUNT: + { + return FrameManager?FrameManager->GetFrameCount():0; + } + case ACTL_SETCURRENTWINDOW: + { + // Запретим переключение фрэймов, если находимся в модальном редакторе/вьюере. + if (FrameManager && !FrameManager->InModalEV() && FrameManager->operator[]((int)(INT_PTR)Param)) + { + int TypeFrame=FrameManager->GetCurrentFrame()->GetType(); + + // Запретим переключение фрэймов, если находимся в хелпе или диалоге (тоже модальных) + if (TypeFrame != MODALTYPE_HELP && TypeFrame != MODALTYPE_DIALOG) + { + Frame* PrevFrame = FrameManager->GetCurrentFrame(); + FrameManager->ActivateFrame((int)(INT_PTR)Param); + FrameManager->DeactivateFrame(PrevFrame, 0); + return TRUE; + } + } + + return FALSE; + } + /*$ 26.06.2001 SKV + Для полноценной работы с ACTL_SETCURRENTWINDOW + (и может еще для чего в будущем) + */ + case ACTL_COMMIT: + { + return FrameManager?FrameManager->PluginCommit():FALSE; + } + /* $ 15.09.2001 tran + пригодится плагинам */ + case ACTL_GETFARHWND: + { + return 0; + } + case ACTL_GETDIALOGSETTINGS: + { + DWORD Options=0; + static Opt2Flags ODlg[]= + { + {&Opt.Dialogs.EditHistory,FDIS_HISTORYINDIALOGEDITCONTROLS}, + {&Opt.Dialogs.EditBlock,FDIS_PERSISTENTBLOCKSINEDITCONTROLS}, + {&Opt.Dialogs.AutoComplete,FDIS_AUTOCOMPLETEININPUTLINES}, + {&Opt.Dialogs.EULBsClear,FDIS_BSDELETEUNCHANGEDTEXT}, + {&Opt.Dialogs.DelRemovesBlocks,FDIS_DELREMOVESBLOCKS}, + {&Opt.Dialogs.MouseButton,FDIS_MOUSECLICKOUTSIDECLOSESDIALOG}, + }; + + for (size_t I=0; I < ARRAYSIZE(ODlg); ++I) + if (*ODlg[I].Opt) + Options|=ODlg[I].Flags; + + return Options; + } + /* $ 24.11.2001 IS + Ознакомим с настройками системными, панели, интерфейса, подтверждений + */ + case ACTL_GETSYSTEMSETTINGS: + { + DWORD Options=0; + static Opt2Flags OSys[]= + { + {&Opt.DeleteToRecycleBin,FSS_DELETETORECYCLEBIN}, + {&Opt.CMOpt.WriteThrough,FSS_WRITETHROUGH}, +// {&Opt.CMOpt.CopyOpened,FSS_RESERVED}, + {&Opt.ScanJunction,FSS_SCANSYMLINK}, + {&Opt.SaveHistory,FSS_SAVECOMMANDSHISTORY}, + {&Opt.SaveFoldersHistory,FSS_SAVEFOLDERSHISTORY}, + {&Opt.SaveViewHistory,FSS_SAVEVIEWANDEDITHISTORY}, +// {&Opt.UseRegisteredTypes,FSS_USEWINDOWSREGISTEREDTYPES}, + {&Opt.AutoSaveSetup,FSS_AUTOSAVESETUP}, + }; + + for (size_t I=0; I < ARRAYSIZE(OSys); ++I) + if (*OSys[I].Opt) + Options|=OSys[I].Flags; + + return Options; + } + case ACTL_GETPANELSETTINGS: + { + DWORD Options=0; + static Opt2Flags OSys[]= + { + {&Opt.ShowHidden,FPS_SHOWHIDDENANDSYSTEMFILES}, + {&Opt.Highlight,FPS_HIGHLIGHTFILES}, + {&Opt.Tree.AutoChangeFolder,FPS_AUTOCHANGEFOLDER}, + {&Opt.SelectFolders,FPS_SELECTFOLDERS}, + {&Opt.ReverseSort,FPS_ALLOWREVERSESORTMODES}, + {&Opt.ShowColumnTitles,FPS_SHOWCOLUMNTITLES}, + {&Opt.ShowPanelStatus,FPS_SHOWSTATUSLINE}, + {&Opt.ShowPanelTotals,FPS_SHOWFILESTOTALINFORMATION}, + {&Opt.ShowPanelFree,FPS_SHOWFREESIZE}, + {&Opt.ShowPanelScrollbar,FPS_SHOWSCROLLBAR}, + {&Opt.ShowScreensNumber,FPS_SHOWBACKGROUNDSCREENSNUMBER}, + {&Opt.ShowSortMode,FPS_SHOWSORTMODELETTER}, + }; + + for (size_t I=0; I < ARRAYSIZE(OSys); ++I) + if (*OSys[I].Opt) + Options|=OSys[I].Flags; + + return Options; + } + case ACTL_GETINTERFACESETTINGS: + { + DWORD Options=0; + static Opt2Flags OSys[]= + { + {&Opt.Clock,FIS_CLOCKINPANELS}, + {&Opt.ViewerEditorClock,FIS_CLOCKINVIEWERANDEDITOR}, + {&Opt.Mouse,FIS_MOUSE}, + {&Opt.ShowKeyBar,FIS_SHOWKEYBAR}, + {&Opt.ShowMenuBar,FIS_ALWAYSSHOWMENUBAR}, + {&Opt.CMOpt.CopyShowTotal,FIS_SHOWTOTALCOPYPROGRESSINDICATOR}, + {&Opt.CMOpt.CopyTimeRule,FIS_SHOWCOPYINGTIMEINFO}, + {&Opt.PgUpChangeDisk,FIS_USECTRLPGUPTOCHANGEDRIVE}, + {&Opt.DelOpt.DelShowTotal,FIS_SHOWTOTALDELPROGRESSINDICATOR}, + }; + + for (size_t I=0; I < ARRAYSIZE(OSys); ++I) + if (*OSys[I].Opt) + Options|=OSys[I].Flags; + + return Options; + } + case ACTL_GETCONFIRMATIONS: + { + DWORD Options=0; + static Opt2Flags OSys[]= + { + {&Opt.Confirm.Copy,FCS_COPYOVERWRITE}, + {&Opt.Confirm.Move,FCS_MOVEOVERWRITE}, + {&Opt.Confirm.RO,FCS_OVERWRITEDELETEROFILES}, + {&Opt.Confirm.Drag,FCS_DRAGANDDROP}, + {&Opt.Confirm.Delete,FCS_DELETE}, + {&Opt.Confirm.DeleteFolder,FCS_DELETENONEMPTYFOLDERS}, + {&Opt.Confirm.Esc,FCS_INTERRUPTOPERATION}, + {&Opt.Confirm.RemoveConnection,FCS_DISCONNECTNETWORKDRIVE}, + {&Opt.Confirm.AllowReedit,FCS_RELOADEDITEDFILE}, + {&Opt.Confirm.HistoryClear,FCS_CLEARHISTORYLIST}, + {&Opt.Confirm.Exit,FCS_EXIT}, + }; + + for (size_t I=0; I < ARRAYSIZE(OSys); ++I) + if (*OSys[I].Opt) + Options|=OSys[I].Flags; + + return Options; + } + case ACTL_GETDESCSETTINGS: + { + // опций мало - с массивом не заморачиваемся + DWORD Options=0; + + if (Opt.Diz.UpdateMode == DIZ_UPDATE_IF_DISPLAYED) + Options |= FDS_UPDATEIFDISPLAYED; + else if (Opt.Diz.UpdateMode == DIZ_UPDATE_ALWAYS) + Options |= FDS_UPDATEALWAYS; + + if (Opt.Diz.SetHidden) + Options |= FDS_SETHIDDEN; + + if (Opt.Diz.ROUpdate) + Options |= FDS_UPDATEREADONLY; + + return Options; + } + case ACTL_GETPOLICIES: + { + return Opt.Policies.DisabledOptions|(Opt.Policies.ShowHiddenDrives?FFPOL_SHOWHIDDENDRIVES:0); + } + case ACTL_REDRAWALL: + { + int Ret=FrameManager->ProcessKey(KEY_CONSOLE_BUFFER_RESIZE); + FrameManager->PluginCommit(); + return Ret; + } + + case ACTL_SETPROGRESSSTATE: + { + return TRUE; + } + + case ACTL_SETPROGRESSVALUE: + { + BOOL Result=FALSE; + if(Param) + { + //PROGRESSVALUE* PV=reinterpret_cast<PROGRESSVALUE*>(Param); + Result=TRUE; + } + return Result; + } + + case ACTL_QUIT: + { + CloseFARMenu=TRUE; + FrameManager->ExitMainLoop(FALSE); + return TRUE; + } + + case ACTL_GETFARRECT: + { + BOOL Result=FALSE; + if(Param) + { + SMALL_RECT& Rect=*reinterpret_cast<PSMALL_RECT>(Param); + if(Opt.WindowMode) + { + Result=Console.GetWorkingRect(Rect); + } + else + { + COORD Size; + if(Console.GetSize(Size)) + { + Rect.Left=0; + Rect.Top=0; + Rect.Right=Size.X-1; + Rect.Bottom=Size.Y-1; + Result=TRUE; + } + } + } + return Result; + } + break; + + case ACTL_GETCURSORPOS: + { + BOOL Result=FALSE; + if(Param) + { + COORD& Pos=*reinterpret_cast<PCOORD>(Param); + Result=Console.GetCursorPosition(Pos); + } + return Result; + } + break; + + case ACTL_SETCURSORPOS: + { + BOOL Result=FALSE; + if(Param) + { + COORD& Pos=*reinterpret_cast<PCOORD>(Param); + Result=Console.SetCursorPosition(Pos); + } + return Result; + } + break; + + case ACTL_PROGRESSNOTIFY: + { + return TRUE; + } + + } + + return FALSE; +} + +INT_PTR WINAPI FarAdvControl(INT_PTR ModuleNumber, int Command, void *Param) +{ + return InterThreadCall<LONG_PTR, 0>(std::bind(FarAdvControlSynched, ModuleNumber, Command, Param)); +} + +static int FarMenuFnSynched( + INT_PTR PluginNumber, + int X, + int Y, + int MaxHeight, + DWORD Flags, + const wchar_t *Title, + const wchar_t *Bottom, + const wchar_t *HelpTopic, + const int *BreakKeys, + int *BreakCode, + const FarMenuItem *Item, + int ItemsNumber +) +{ + if (FrameManager->ManagerIsDown()) + return -1; + + if (DisablePluginsOutput) + return -1; + + int ExitCode; + { + VMenu FarMenu(Title,nullptr,0,MaxHeight); + CtrlObject->Macro.SetMode(MACRO_MENU); + FarMenu.SetPosition(X,Y,0,0); + + if (BreakCode) + *BreakCode=-1; + + { + FARString strTopic; + + if (Help::MkTopic(PluginNumber,HelpTopic,strTopic)) + FarMenu.SetHelp(strTopic); + } + + if (Bottom) + FarMenu.SetBottomTitle(Bottom); + + // общие флаги меню + DWORD MenuFlags=0; + + if (Flags & FMENU_SHOWAMPERSAND) + MenuFlags|=VMENU_SHOWAMPERSAND; + + if (Flags & FMENU_WRAPMODE) + MenuFlags|=VMENU_WRAPMODE; + + if (Flags & FMENU_CHANGECONSOLETITLE) + MenuFlags|=VMENU_CHANGECONSOLETITLE; + + FarMenu.SetFlags(MenuFlags); + MenuItemEx CurItem; + CurItem.Clear(); + int Selected=0; + + if (Flags&FMENU_USEEXT) + { + FarMenuItemEx *ItemEx=(FarMenuItemEx*)Item; + + for (int i=0; i < ItemsNumber; i++) + { + CurItem.Flags=ItemEx[i].Flags; + CurItem.strName.Clear(); + // исключаем MultiSelected, т.к. у нас сейчас движок к этому не приспособлен, оставляем только первый + DWORD SelCurItem=CurItem.Flags&LIF_SELECTED; + CurItem.Flags&=~LIF_SELECTED; + + if (!Selected && !(CurItem.Flags&LIF_SEPARATOR) && SelCurItem) + { + CurItem.Flags|=SelCurItem; + Selected++; + } + + CurItem.strName=ItemEx[i].Text; + CurItem.AccelKey=(CurItem.Flags&LIF_SEPARATOR)?0:ItemEx[i].AccelKey; + FarMenu.AddItem(&CurItem); + } + } + else + { + for (int i=0; i<ItemsNumber; i++) + { + CurItem.Flags=Item[i].Checked?(LIF_CHECKED|(Item[i].Checked&0xFFFF)):0; + CurItem.Flags|=Item[i].Selected?LIF_SELECTED:0; + CurItem.Flags|=Item[i].Separator?LIF_SEPARATOR:0; + + if (Item[i].Separator) + CurItem.strName.Clear(); + else + CurItem.strName = Item[i].Text; + + DWORD SelCurItem=CurItem.Flags&LIF_SELECTED; + CurItem.Flags&=~LIF_SELECTED; + + if (!Selected && !(CurItem.Flags&LIF_SEPARATOR) && SelCurItem) + { + CurItem.Flags|=SelCurItem; + Selected++; + } + + FarMenu.AddItem(&CurItem); + } + } + + if (!Selected) + FarMenu.SetSelectPos(0,1); + + // флаги меню, с забитым контентом + if (Flags & FMENU_AUTOHIGHLIGHT) + FarMenu.AssignHighlights(FALSE); + + if (Flags & FMENU_REVERSEAUTOHIGHLIGHT) + FarMenu.AssignHighlights(TRUE); + + FarMenu.SetTitle(Title); + FarMenu.Show(); + + while (!FarMenu.Done() && !CloseFARMenu) + { + INPUT_RECORD ReadRec; + int ReadKey=GetInputRecord(&ReadRec); + + if (ReadKey==KEY_CONSOLE_BUFFER_RESIZE) + { + LockScreen LckScr; + FarMenu.Hide(); + FarMenu.Show(); + } + else if (ReadRec.EventType==MOUSE_EVENT) + { + FarMenu.ProcessMouse(&ReadRec.Event.MouseEvent); + } + else if (ReadKey!=KEY_NONE) + { + if (BreakKeys) + { + for (int I=0; BreakKeys[I]; I++) + { + if (CtrlObject->Macro.IsExecuting()) + { + int VirtKey,ControlState; + TranslateKeyToVK(ReadKey,VirtKey,ControlState,&ReadRec); + } + + if (ReadRec.Event.KeyEvent.wVirtualKeyCode==(BreakKeys[I] & 0xffff)) + { + DWORD Flags=BreakKeys[I]>>16; + DWORD RealFlags=ReadRec.Event.KeyEvent.dwControlKeyState & + (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED| + LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED|SHIFT_PRESSED); + DWORD f = 0; + + if (RealFlags & (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED)) + f |= PKF_CONTROL; + + if (RealFlags & (LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED)) + f |= PKF_ALT; + + if (RealFlags & SHIFT_PRESSED) + f |= PKF_SHIFT; + + if (f == Flags) + { + if (BreakCode) + *BreakCode=I; + + FarMenu.Hide(); +// CheckScreenLock(); + return FarMenu.GetSelectPos(); + } + } + } + } + + FarMenu.ProcessKey(ReadKey); + } + } + + ExitCode=FarMenu.Modal::GetExitCode(); + } +// CheckScreenLock(); + return(ExitCode); +} + +int WINAPI FarMenuFn( + INT_PTR PluginNumber, + int X, + int Y, + int MaxHeight, + DWORD Flags, + const wchar_t *Title, + const wchar_t *Bottom, + const wchar_t *HelpTopic, + const int *BreakKeys, + int *BreakCode, + const FarMenuItem *Item, + int ItemsNumber +) +{ + return InterThreadCall<int, -1>(std::bind(FarMenuFnSynched, PluginNumber, X, Y, + MaxHeight, Flags, Title, Bottom, HelpTopic, BreakKeys, BreakCode, Item, ItemsNumber)); +} + +// Функция FarDefDlgProc обработки диалога по умолчанию +LONG_PTR WINAPI FarDefDlgProc(HANDLE hDlg,int Msg,int Param1,LONG_PTR Param2) +{ + if (hDlg) // исключаем лишний вызов для hDlg=0 + return DefDlgProc(hDlg,Msg,Param1,Param2); + + return 0; +} + +// Посылка сообщения диалогу +LONG_PTR WINAPI FarSendDlgMessage(HANDLE hDlg,int Msg,int Param1,LONG_PTR Param2) +{ + if (hDlg) // исключаем лишний вызов для hDlg=0 + return SendDlgMessage(hDlg,Msg,Param1,Param2); + + return 0; +} + +static HANDLE FarDialogInitSynched(INT_PTR PluginNumber, int X1, int Y1, int X2, int Y2, + const wchar_t *HelpTopic, FarDialogItem *Item, + unsigned int ItemsNumber, DWORD Reserved, DWORD Flags, + FARWINDOWPROC DlgProc, LONG_PTR Param) +{ + HANDLE hDlg=INVALID_HANDLE_VALUE; + + if (FrameManager->ManagerIsDown()) + return hDlg; + + if (DisablePluginsOutput || ItemsNumber <= 0 || !Item) + return hDlg; + + // ФИЧА! нельзя указывать отрицательные X2 и Y2 + if (X2 < 0 || Y2 < 0) + return hDlg; + + { + Dialog *FarDialog = new(std::nothrow) Dialog(Item,ItemsNumber,DlgProc,Param); + + if (!FarDialog) + return hDlg; + + hDlg = (HANDLE)FarDialog; + FarDialog->SetPosition(X1,Y1,X2,Y2); + + if (Flags & FDLG_WARNING) + FarDialog->SetDialogMode(DMODE_WARNINGSTYLE); + + if (Flags & FDLG_SMALLDIALOG) + FarDialog->SetDialogMode(DMODE_SMALLDIALOG); + + if (Flags & FDLG_NODRAWSHADOW) + FarDialog->SetDialogMode(DMODE_NODRAWSHADOW); + + if (Flags & FDLG_NODRAWPANEL) + FarDialog->SetDialogMode(DMODE_NODRAWPANEL); + + if (Flags & FDLG_KEEPCONSOLETITLE) + FarDialog->SetDialogMode(DMODE_KEEPCONSOLETITLE); + + if (Flags & FDLG_NONMODAL) + FarDialog->SetCanLoseFocus(TRUE); + + if (Flags & FDLG_REGULARIDLE) + FarDialog->SetRegularIdle(TRUE); + + FarDialog->SetHelp(HelpTopic); + /* $ 29.08.2000 SVS + Запомним номер плагина - сейчас в основном для формирования HelpTopic + */ + FarDialog->SetPluginNumber(PluginNumber); + } + return hDlg; +} + +static int FarDialogRunSynched(HANDLE hDlg) +{ + if (hDlg==INVALID_HANDLE_VALUE) + return -1; + + if (FrameManager->ManagerIsDown()) + return -1; + + Frame *frame=FrameManager->GetBottomFrame(); + + if (frame ) + frame->Lock(); // отменим прорисовку фрейма + + int ExitCode=-1; + Dialog *FarDialog = (Dialog *)hDlg; + + //CtrlObject->Plugins.Flags.Clear(PSIF_DIALOG); + FarDialog->Process(); + ExitCode=FarDialog->GetExitCode(); + + /* $ 15.05.2002 SKV + Однако разлочивать нужно ровно то, что залочили. + */ + if (frame ) + frame->Unlock(); // теперь можно :-) + + //CheckScreenLock(); + FrameManager->RefreshFrame(); //?? - //AY - это нужно чтоб обновлять панели после выхода из диалога + return(ExitCode); +} + +static bool FarDialogFreeSynched(HANDLE hDlg) +{ + if (hDlg == INVALID_HANDLE_VALUE) + return false; + + Dialog *FarDialog = (Dialog *)hDlg; + delete FarDialog; + return true; +} + + +///////// + +HANDLE WINAPI FarDialogInit(INT_PTR PluginNumber, int X1, int Y1, int X2, int Y2, + const wchar_t *HelpTopic, FarDialogItem *Item, + unsigned int ItemsNumber, DWORD Reserved, DWORD Flags, + FARWINDOWPROC DlgProc, LONG_PTR Param) +{ + HANDLE out = InterThreadCall<HANDLE, nullptr>(std::bind(FarDialogInitSynched, + PluginNumber, X1, Y1, X2, Y2, HelpTopic, Item, ItemsNumber, Reserved, Flags, DlgProc, Param)); + + return (out != nullptr) ? out : INVALID_HANDLE_VALUE; +} + +int WINAPI FarDialogRun(HANDLE hDlg) +{ + return InterThreadCall<int, -1>(std::bind(FarDialogRunSynched, hDlg)); +} + +void WINAPI FarDialogFree(HANDLE hDlg) +{ + InterThreadCall<bool, false>(std::bind(FarDialogFreeSynched, hDlg)); +} + +///////// + + +static CriticalSection s_get_msg_cs; +const wchar_t* FarGetMsgFn(INT_PTR PluginHandle,int MsgId) +{ + //BUGBUG, надо проверять, что PluginHandle - плагин + PluginW *pPlugin = (PluginW*)PluginHandle; + std::wstring strPath = pPlugin->GetModuleName().CPtr(); + CutToSlash(strPath); + + CriticalSectionLock lock(s_get_msg_cs); + if (!pPlugin->InitLang(strPath.c_str())) { + return nullptr; + } + + return pPlugin->GetMsg(MsgId); +} + +static int FarMessageFnSynched(INT_PTR PluginNumber,DWORD Flags,const wchar_t *HelpTopic, + const wchar_t * const *Items,int ItemsNumber, + int ButtonsNumber) +{ + if (FrameManager->ManagerIsDown()) + return -1; + + if (DisablePluginsOutput) + return -1; + + if ((!(Flags&(FMSG_ALLINONE|FMSG_ERRORTYPE)) && ItemsNumber<2) || !Items) + return -1; + + wchar_t *SingleItems=nullptr; + wchar_t *Msg; + + // анализ количества строк для FMSG_ALLINONE + if (Flags&FMSG_ALLINONE) + { + ItemsNumber=0; + + if (!(SingleItems=(wchar_t *)malloc((StrLength((const wchar_t *)Items)+2)*sizeof(wchar_t)))) + return -1; + + Msg=wcscpy(SingleItems,(const wchar_t *)Items); + + while ((Msg = wcschr(Msg, L'\n')) ) + { +// *Msg='\0'; + if (*++Msg == L'\0') + break; + + ++ItemsNumber; + } + + ItemsNumber++; //?? + } + + const wchar_t **MsgItems=(const wchar_t **)malloc(sizeof(wchar_t*)*(ItemsNumber+ADDSPACEFORPSTRFORMESSAGE)); + + if (!MsgItems) + { + free(SingleItems); + return -1; + } + + memset(MsgItems,0,sizeof(wchar_t*)*(ItemsNumber+ADDSPACEFORPSTRFORMESSAGE)); + + if (Flags&FMSG_ALLINONE) + { + int I=0; + Msg=SingleItems; + // анализ количества строк и разбивка на пункты + wchar_t *MsgTemp; + + while ((MsgTemp = wcschr(Msg, L'\n')) ) + { + *MsgTemp=L'\0'; + MsgItems[I]=Msg; + Msg+=StrLength(Msg)+1; + + if (*Msg == L'\0') + break; + + ++I; + } + + if (*Msg) + { + MsgItems[I]=Msg; + } + } + else + { + for (int i=0; i < ItemsNumber; i++) { + MsgItems[i]=Items[i]; + } + } + + // ограничение на строки + if (ItemsNumber > ScrY-2) + { + ItemsNumber=ScrY-2-(Flags&0x000F0000?1:0); + } + + /* $ 22.03.2001 tran + ItemsNumber++ -> ++ItemsNumber + тереялся последний элемент */ + switch (Flags&0x000F0000) + { + case FMSG_MB_OK: + ButtonsNumber=1; + MsgItems[ItemsNumber++]=MSG(MOk); + break; + case FMSG_MB_OKCANCEL: + ButtonsNumber=2; + MsgItems[ItemsNumber++]=MSG(MOk); + MsgItems[ItemsNumber++]=MSG(MCancel); + break; + case FMSG_MB_ABORTRETRYIGNORE: + ButtonsNumber=3; + MsgItems[ItemsNumber++]=MSG(MAbort); + MsgItems[ItemsNumber++]=MSG(MRetry); + MsgItems[ItemsNumber++]=MSG(MIgnore); + break; + case FMSG_MB_YESNO: + ButtonsNumber=2; + MsgItems[ItemsNumber++]=MSG(MYes); + MsgItems[ItemsNumber++]=MSG(MNo); + break; + case FMSG_MB_YESNOCANCEL: + ButtonsNumber=3; + MsgItems[ItemsNumber++]=MSG(MYes); + MsgItems[ItemsNumber++]=MSG(MNo); + MsgItems[ItemsNumber++]=MSG(MCancel); + break; + case FMSG_MB_RETRYCANCEL: + ButtonsNumber=2; + MsgItems[ItemsNumber++]=MSG(MRetry); + MsgItems[ItemsNumber++]=MSG(MCancel); + break; + } + + // запоминаем топик + if (PluginNumber != -1) + { + FARString strTopic; + + if (Help::MkTopic(PluginNumber,HelpTopic,strTopic)) + SetMessageHelp(strTopic); + } + + // непосредственно... вывод + Frame *frame; + + if ((frame=FrameManager->GetBottomFrame()) ) + frame->Lock(); // отменим прорисовку фрейма + + int MsgCode=Message(Flags,ButtonsNumber,MsgItems[0],MsgItems+1,ItemsNumber-1,PluginNumber); + + /* $ 15.05.2002 SKV + Однако разлочивать надо ровно то, что залочили. + */ + if (frame ) + frame->Unlock(); // теперь можно :-) + + //CheckScreenLock(); + + if (SingleItems) + free(SingleItems); + + free(MsgItems); + return(MsgCode); +} + +int WINAPI FarMessageFn(INT_PTR PluginNumber,DWORD Flags,const wchar_t *HelpTopic, + const wchar_t * const *Items,int ItemsNumber, + int ButtonsNumber) +{ + return InterThreadCall<int, -1>(std::bind(FarMessageFnSynched, PluginNumber, Flags, HelpTopic, Items, ItemsNumber, ButtonsNumber)); +} + +static int FarControlSynched(HANDLE hPlugin,int Command,int Param1,LONG_PTR Param2) +{ + _FCTLLOG(CleverSysLog CSL(L"Control")); + _FCTLLOG(SysLog(L"(hPlugin=0x%08X, Command=%ls, Param1=[%d/0x%08X], Param2=[%d/0x%08X])",hPlugin,_FCTL_ToName(Command),(int)Param1,Param1,(int)Param2,Param2)); + _ALGO(CleverSysLog clv(L"FarControl")); + _ALGO(SysLog(L"(hPlugin=0x%08X, Command=%ls, Param1=[%d/0x%08X], Param2=[%d/0x%08X])",hPlugin,_FCTL_ToName(Command),(int)Param1,Param1,(int)Param2,Param2)); + + if (Command == FCTL_CHECKPANELSEXIST) + return Opt.OnlyEditorViewerUsed? FALSE:TRUE; + + if (Opt.OnlyEditorViewerUsed || !CtrlObject || !FrameManager || FrameManager->ManagerIsDown()) + return 0; + + FilePanels *FPanels=CtrlObject->Cp(); + CommandLine *CmdLine=CtrlObject->CmdLine; + + switch (Command) + { + case FCTL_CLOSEPLUGIN: + g_strDirToSet = (wchar_t *)Param2; + case FCTL_GETPANELINFO: + case FCTL_GETPANELITEM: + case FCTL_GETSELECTEDPANELITEM: + case FCTL_GETCURRENTPANELITEM: + case FCTL_GETPANELDIR: + case FCTL_GETCOLUMNTYPES: + case FCTL_GETCOLUMNWIDTHS: + case FCTL_UPDATEPANEL: + case FCTL_REDRAWPANEL: + case FCTL_SETPANELDIR: + case FCTL_BEGINSELECTION: + case FCTL_SETSELECTION: + case FCTL_CLEARSELECTION: + case FCTL_ENDSELECTION: + case FCTL_SETVIEWMODE: + case FCTL_SETSORTMODE: + case FCTL_SETSORTORDER: + case FCTL_SETNUMERICSORT: + case FCTL_SETCASESENSITIVESORT: + case FCTL_SETDIRECTORIESFIRST: + case FCTL_GETPANELFORMAT: + case FCTL_GETPANELHOSTFILE: + case FCTL_GETPANELPLUGINHANDLE: + case FCTL_SETPANELLOCATION: + { + if (!FPanels) + return FALSE; + + if ((hPlugin == PANEL_ACTIVE) || (hPlugin == PANEL_PASSIVE)) + { + Panel *pPanel = (hPlugin == PANEL_ACTIVE)?FPanels->ActivePanel:FPanels->GetAnotherPanel(FPanels->ActivePanel); + + if (pPanel) + { + return pPanel->SetPluginCommand(Command,Param1,Param2); + } + + return FALSE; //??? + } + + HANDLE hInternal; + Panel *LeftPanel=FPanels->LeftPanel; + Panel *RightPanel=FPanels->RightPanel; + int Processed=FALSE; + PluginHandle *PlHandle; + + if (LeftPanel && LeftPanel->GetMode()==PLUGIN_PANEL) + { + PlHandle=(PluginHandle *)LeftPanel->GetPluginHandle(); + + if (PlHandle) + { + hInternal=PlHandle->hPlugin; + + if (hPlugin==hInternal) + { + Processed=LeftPanel->SetPluginCommand(Command,Param1,Param2); + } + } + } + + if (RightPanel && RightPanel->GetMode()==PLUGIN_PANEL) + { + PlHandle=(PluginHandle *)RightPanel->GetPluginHandle(); + + if (PlHandle) + { + hInternal=PlHandle->hPlugin; + + if (hPlugin==hInternal) + { + Processed=RightPanel->SetPluginCommand(Command,Param1,Param2); + } + } + } + + return(Processed); + } + case FCTL_SETUSERSCREEN: + { + if (!FPanels || !FPanels->LeftPanel || !FPanels->RightPanel) + return FALSE; + + KeepUserScreen++; + FPanels->LeftPanel->ProcessingPluginCommand++; + FPanels->RightPanel->ProcessingPluginCommand++; + ScrBuf.FillBuf(); + ScrollScreen(1); + SaveScreen SaveScr; + { + RedrawDesktop Redraw; + CmdLine->Hide(); + SaveScr.RestoreArea(FALSE); + } + KeepUserScreen--; + FPanels->LeftPanel->ProcessingPluginCommand--; + FPanels->RightPanel->ProcessingPluginCommand--; + return TRUE; + } + case FCTL_GETUSERSCREEN: + { + FrameManager->ShowBackground(); + int Lock=ScrBuf.GetLockCount(); + ScrBuf.SetLockCount(0); + MoveCursor(0,ScrY-1); + SetInitialCursorType(); + ScrBuf.Flush(); + ScrBuf.SetLockCount(Lock); + return TRUE; + } + case FCTL_GETCMDLINE: + case FCTL_GETCMDLINESELECTEDTEXT: + { + FARString strParam; + + if (Command==FCTL_GETCMDLINE) + CmdLine->GetString(strParam); + else + CmdLine->GetSelString(strParam); + + if (Param1&&Param2) + far_wcsncpy((wchar_t*)Param2,strParam,Param1); + + return (int)strParam.GetLength()+1; + } + case FCTL_SETCMDLINE: + case FCTL_INSERTCMDLINE: + { + CmdLine->DisableAC(); + if (Command==FCTL_SETCMDLINE) + CmdLine->SetString((const wchar_t*)Param2); + else + CmdLine->InsertString((const wchar_t*)Param2); + CmdLine->RevertAC(); + CmdLine->Redraw(); + return TRUE; + } + case FCTL_SETCMDLINEPOS: + { + CmdLine->SetCurPos(Param1); + CmdLine->Redraw(); + return TRUE; + } + case FCTL_GETCMDLINEPOS: + { + if (Param2) + { + *(int *)Param2=CmdLine->GetCurPos(); + return TRUE; + } + + return FALSE; + } + case FCTL_GETCMDLINESELECTION: + { + if (Param2) + { + CmdLineSelect *sel=(CmdLineSelect*)Param2; + CmdLine->GetSelection(sel->SelStart,sel->SelEnd); + return TRUE; + } + + return FALSE; + } + case FCTL_SETCMDLINESELECTION: + { + if (Param2) + { + CmdLineSelect *sel=(CmdLineSelect*)Param2; + CmdLine->Select(sel->SelStart,sel->SelEnd); + CmdLine->Redraw(); + return TRUE; + } + + return FALSE; + } + case FCTL_ISACTIVEPANEL: + { + if (hPlugin == PANEL_ACTIVE) + return TRUE; + + Panel *pPanel = FPanels->ActivePanel; + PluginHandle *PlHandle; + + if (pPanel && (pPanel->GetMode() == PLUGIN_PANEL)) + { + PlHandle = (PluginHandle *)pPanel->GetPluginHandle(); + + if (PlHandle) + { + if (PlHandle->hPlugin == hPlugin) + return TRUE; + } + } + + return FALSE; + } + } + + return FALSE; +} + +int WINAPI FarControl(HANDLE hPlugin,int Command,int Param1,LONG_PTR Param2) +{ + return InterThreadCall<int, 0>(std::bind(FarControlSynched, hPlugin, Command, Param1, Param2)); +} + +// + +HANDLE WINAPI FarSaveScreen(int X1,int Y1,int X2,int Y2) +{ + if (DisablePluginsOutput || FrameManager->ManagerIsDown()) + return nullptr; + + if (X2==-1) + X2=ScrX; + + if (Y2==-1) + Y2=ScrY; + + return((HANDLE)(new SaveScreen(X1,Y1,X2,Y2))); +} + +void WINAPI FarRestoreScreen(HANDLE hScreen) +{ + if (DisablePluginsOutput || FrameManager->ManagerIsDown()) + return; + + if (!hScreen) + ScrBuf.FillBuf(); + + if (hScreen) + delete(SaveScreen *)hScreen; +} + + +static void PR_FarGetDirListMsg() +{ + Message(0,0,L"",MSG(MPreparingList)); +} + +static int FarGetDirListSynched(const wchar_t *Dir,FAR_FIND_DATA **pPanelItem,int *pItemsNumber) +{ + if (FrameManager->ManagerIsDown() || !Dir || !*Dir || !pItemsNumber || !pPanelItem) + return FALSE; + + FARString strDirName; + ConvertNameToFull(Dir, strDirName); + { + TPreRedrawFuncGuard preRedrawFuncGuard(PR_FarGetDirListMsg); + SaveScreen SaveScr; + clock_t StartTime=GetProcessUptimeMSec(); + int MsgOut=0; + FAR_FIND_DATA_EX FindData; + FARString strFullName; + ScanTree ScTree(FALSE); + ScTree.SetFindPath(strDirName,L"*"); + *pItemsNumber=0; + *pPanelItem=nullptr; + FAR_FIND_DATA *ItemsList=nullptr; + int ItemsNumber=0; + + while (ScTree.GetNextName(&FindData,strFullName)) + { + if (!(ItemsNumber & 31)) + { + if (CheckForEsc()) + { + if (ItemsList) + FarFreeDirList(ItemsList,ItemsNumber); + + return FALSE; + } + + if (!MsgOut && GetProcessUptimeMSec()-StartTime > 500) + { + SetCursorType(FALSE,0); + PR_FarGetDirListMsg(); + MsgOut=1; + } + + ItemsList=(FAR_FIND_DATA*)realloc(ItemsList,sizeof(*ItemsList)*(ItemsNumber+32+1)); + + if (!ItemsList) + { + return FALSE; + } + } + + ItemsList[ItemsNumber].dwFileAttributes = FindData.dwFileAttributes; + ItemsList[ItemsNumber].nFileSize = FindData.nFileSize; + ItemsList[ItemsNumber].nPhysicalSize = FindData.nPhysicalSize; + ItemsList[ItemsNumber].ftCreationTime = FindData.ftCreationTime; + ItemsList[ItemsNumber].ftLastAccessTime = FindData.ftLastAccessTime; + ItemsList[ItemsNumber].ftLastWriteTime = FindData.ftLastWriteTime; + ItemsList[ItemsNumber].lpwszFileName = wcsdup(strFullName.CPtr()); + ItemsNumber++; + } + + *pPanelItem=ItemsList; + *pItemsNumber=ItemsNumber; + } + return TRUE; +} + +int WINAPI FarGetDirList(const wchar_t *Dir,FAR_FIND_DATA **pPanelItem,int *pItemsNumber) +{ + return InterThreadCall<int, 0>(std::bind(FarGetDirListSynched, Dir, pPanelItem, pItemsNumber)); +} + +static PluginPanelItem *PluginDirList; +static int DirListItemsNumber; +static FARString strPluginSearchPath; +static int StopSearch; +static HANDLE hDirListPlugin; +static int PluginSearchMsgOut; + +static void FarGetPluginDirListMsg(const wchar_t *Name,DWORD Flags) +{ + Message(Flags,0,L"",MSG(MPreparingList),Name); + PreRedrawItem preRedrawItem=PreRedraw.Peek(); + preRedrawItem.Param.Flags=Flags; + preRedrawItem.Param.Param1=(void*)Name; + PreRedraw.SetParam(preRedrawItem.Param); +} + +static void PR_FarGetPluginDirListMsg() +{ + PreRedrawItem preRedrawItem=PreRedraw.Peek(); + FarGetPluginDirListMsg((const wchar_t *)preRedrawItem.Param.Param1,preRedrawItem.Param.Flags&(~MSG_KEEPBACKGROUND)); +} + +int FarGetPluginDirListSynched(INT_PTR PluginNumber, + HANDLE hPlugin, + const wchar_t *Dir, + PluginPanelItem **pPanelItem, + int *pItemsNumber) +{ + if (FrameManager->ManagerIsDown() || !Dir || !*Dir || !pItemsNumber || !pPanelItem) + return FALSE; + + { + if (!StrCmp(Dir,L".") || TestParentFolderName(Dir)) + return FALSE; + + static PluginHandle DirListPlugin; + + // А не хочет ли плагин посмотреть на текущую панель? + if (hPlugin==PANEL_ACTIVE || hPlugin==PANEL_PASSIVE) + { + /* $ 30.11.2001 DJ + А плагиновая ли это панель? + */ + HANDLE Handle = ((hPlugin==PANEL_ACTIVE)?CtrlObject->Cp()->ActivePanel:CtrlObject->Cp()->GetAnotherPanel(CtrlObject->Cp()->ActivePanel))->GetPluginHandle(); + + if (!Handle || Handle == INVALID_HANDLE_VALUE) + return FALSE; + + DirListPlugin=*(PluginHandle *)Handle; + } + else + { + DirListPlugin.pPlugin=(Plugin*)PluginNumber; + DirListPlugin.hPlugin=hPlugin; + } + + { + SaveScreen SaveScr; + TPreRedrawFuncGuard preRedrawFuncGuard(PR_FarGetPluginDirListMsg); + { + FARString strDirName; + strDirName = Dir; + TruncStr(strDirName,30); + CenterStr(strDirName,strDirName,30); + SetCursorType(FALSE,0); + FarGetPluginDirListMsg(strDirName,0); + PluginSearchMsgOut=FALSE; + hDirListPlugin=(HANDLE)&DirListPlugin; + StopSearch=FALSE; + *pItemsNumber=DirListItemsNumber=0; + *pPanelItem=PluginDirList=nullptr; + OpenPluginInfo Info; + CtrlObject->Plugins.GetOpenPluginInfo(hDirListPlugin,&Info); + FARString strPrevDir = Info.CurDir; + + if (CtrlObject->Plugins.SetDirectory(hDirListPlugin,Dir,OPM_SILENT)) + { + strPluginSearchPath = Dir; + strPluginSearchPath += L"\x1"; + ScanPluginDir(); + *pPanelItem=PluginDirList; + *pItemsNumber=DirListItemsNumber; + CtrlObject->Plugins.SetDirectory(hDirListPlugin,L"..",OPM_SILENT); + OpenPluginInfo NewInfo; + CtrlObject->Plugins.GetOpenPluginInfo(hDirListPlugin,&NewInfo); + + if (StrCmp(strPrevDir, NewInfo.CurDir) ) + { + PluginPanelItem *PanelData=nullptr; + int ItemCount=0; + + if (CtrlObject->Plugins.GetFindData(hDirListPlugin,&PanelData,&ItemCount,OPM_SILENT)) + { + CtrlObject->Plugins.FreeFindData(hDirListPlugin,PanelData,ItemCount); + } + + CtrlObject->Plugins.SetDirectory(hDirListPlugin,strPrevDir,OPM_SILENT); + } + } + } + } + } + return(!StopSearch); +} + +int WINAPI FarGetPluginDirList(INT_PTR PluginNumber, HANDLE hPlugin, + const wchar_t *Dir, PluginPanelItem **pPanelItem, int *pItemsNumber) +{ + return InterThreadCall<int, 0>(std::bind(FarGetPluginDirListSynched, PluginNumber, hPlugin, Dir, pPanelItem, pItemsNumber)); +} + +/* $ 30.11.2001 DJ + вытащим в функцию общий код для копирования айтема в ScanPluginDir() +*/ + +static void CopyPluginDirItem(PluginPanelItem *CurPanelItem) +{ + FARString strFullName; + strFullName = strPluginSearchPath; + strFullName += CurPanelItem->FindData.lpwszFileName; + wchar_t *lpwszFullName = strFullName.GetBuffer(); + + for (int I=0; lpwszFullName[I]; I++) + if (lpwszFullName[I]==L'\x1') + lpwszFullName[I]=GOOD_SLASH; + + strFullName.ReleaseBuffer(); + PluginPanelItem *DestItem=PluginDirList+DirListItemsNumber; + *DestItem=*CurPanelItem; + + if (CurPanelItem->UserData && (CurPanelItem->Flags & PPIF_USERDATA)) + { + DWORD Size=*(DWORD *)CurPanelItem->UserData; + DestItem->UserData=(DWORD_PTR)malloc(Size); + memcpy((void *)DestItem->UserData,(void *)CurPanelItem->UserData,Size); + } + + DestItem->FindData.lpwszFileName = wcsdup(strFullName); + DirListItemsNumber++; +} + +static void ScanPluginDir() +{ + PluginPanelItem *PanelData=nullptr; + int ItemCount=0; + int AbortOp=FALSE; + FARString strDirName; + strDirName = strPluginSearchPath; + wchar_t *lpwszDirName = strDirName.GetBuffer(); + + for (int i=0; lpwszDirName[i]; i++) + if (lpwszDirName[i]=='\x1') + lpwszDirName[i]=lpwszDirName[i+1]? GOOD_SLASH : 0; + + strDirName.ReleaseBuffer(); + TruncStr(strDirName,30); + CenterStr(strDirName,strDirName,30); + + if (CheckForEscSilent()) + { + if (Opt.Confirm.Esc) // Будет выдаваться диалог? + AbortOp=TRUE; + + if (ConfirmAbortOp()) + StopSearch=TRUE; + } + + FarGetPluginDirListMsg(strDirName,AbortOp?0:MSG_KEEPBACKGROUND); + + if (StopSearch || !CtrlObject->Plugins.GetFindData(hDirListPlugin,&PanelData,&ItemCount,OPM_FIND)) + return; + + PluginPanelItem *NewList=(PluginPanelItem *)realloc(PluginDirList,1+sizeof(*PluginDirList)*(DirListItemsNumber+ItemCount)); + + if (!NewList) + { + StopSearch=TRUE; + return; + } + + PluginDirList=NewList; + + for (int i=0; i<ItemCount && !StopSearch; i++) + { + PluginPanelItem *CurPanelItem=PanelData+i; + + if (!(CurPanelItem->FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + CopyPluginDirItem(CurPanelItem); + } + + for (int i=0; i<ItemCount && !StopSearch; i++) + { + PluginPanelItem *CurPanelItem=PanelData+i; + + if ((CurPanelItem->FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && + StrCmp(CurPanelItem->FindData.lpwszFileName,L".") && + !TestParentFolderName(CurPanelItem->FindData.lpwszFileName)) + { + PluginPanelItem *NewList=(PluginPanelItem *)realloc(PluginDirList,sizeof(*PluginDirList)*(DirListItemsNumber+1)); + + if (!NewList) + { + StopSearch=TRUE; + return; + } + + PluginDirList=NewList; + /* $ 30.11.2001 DJ + используем общую функцию для копирования FindData (не забываем + обработать PPIF_USERDATA) + */ + CopyPluginDirItem(CurPanelItem); + FARString strFileName = CurPanelItem->FindData.lpwszFileName; + + if (CtrlObject->Plugins.SetDirectory(hDirListPlugin,strFileName,OPM_FIND)) + { + strPluginSearchPath += CurPanelItem->FindData.lpwszFileName; + strPluginSearchPath += L"\x1"; + ScanPluginDir(); + size_t pos = (size_t)-1; + strPluginSearchPath.RPos(pos,L'\x1'); + strPluginSearchPath.Truncate(pos); + + if (strPluginSearchPath.RPos(pos,L'\x1')) + strPluginSearchPath.Truncate(pos+1); + else + strPluginSearchPath.Clear(); + + if (!CtrlObject->Plugins.SetDirectory(hDirListPlugin,L"..",OPM_FIND)) + { + StopSearch=TRUE; + break; + } + } + } + } + + CtrlObject->Plugins.FreeFindData(hDirListPlugin,PanelData,ItemCount); +} + + +void WINAPI FarFreeDirList(FAR_FIND_DATA *PanelItem, int nItemsNumber) +{ + for (int I=0; I<nItemsNumber; I++) + { + FAR_FIND_DATA *CurPanelItem=PanelItem+I; + apiFreeFindData(CurPanelItem); + } + + free(PanelItem); +} + + +void WINAPI FarFreePluginDirList(PluginPanelItem *PanelItem, int ItemsNumber) +{ + if (!PanelItem) + return; + + for (int I=0; I<ItemsNumber; I++) + { + PluginPanelItem *CurPanelItem=PanelItem+I; + + if (CurPanelItem->UserData && (CurPanelItem->Flags & PPIF_USERDATA)) + { + free((void *)CurPanelItem->UserData); + } + + apiFreeFindData(&CurPanelItem->FindData); + } + + free(PanelItem); +} + +static int FarViewerSynched(const wchar_t *FileName,const wchar_t *Title, + int X1,int Y1,int X2, int Y2,DWORD Flags, UINT CodePage) +{ + if (FrameManager->ManagerIsDown()) + return FALSE; + + class ConsoleTitle ct; + int DisableHistory=(Flags & VF_DISABLEHISTORY)?TRUE:FALSE; + + // $ 15.05.2002 SKV - Запретим вызов немодального редактора вьюера из модального. + if (FrameManager->InModalEV()) + { + Flags&=~VF_NONMODAL; + } + + if (Flags & VF_NONMODAL) + { + /* 09.09.2001 IS ! Добавим имя файла в историю, если потребуется */ + FileViewer *Viewer=new(std::nothrow) FileViewer(FileName,TRUE,DisableHistory,Title,X1,Y1,X2,Y2,CodePage); + + if (!Viewer) + return FALSE; + + /* $ 14.06.2002 IS + Обработка VF_DELETEONLYFILEONCLOSE - этот флаг имеет более низкий + приоритет по сравнению с VF_DELETEONCLOSE + */ + if (Flags & (VF_DELETEONCLOSE|VF_DELETEONLYFILEONCLOSE)) + Viewer->SetTempViewName(FileName,(Flags&VF_DELETEONCLOSE)?TRUE:FALSE); + + Viewer->SetEnableF6((Flags & VF_ENABLE_F6) ); + + /* $ 21.05.2002 SKV + Запускаем свой цикл только если не был указан флаг. + */ + if (!(Flags&VF_IMMEDIATERETURN)) + { + FrameManager->ExecuteNonModal(); + } + else + { + if (GlobalSaveScrPtr) + GlobalSaveScrPtr->Discard(); + + FrameManager->PluginCommit(); + } + } + else + { + /* 09.09.2001 IS ! Добавим имя файла в историю, если потребуется */ + FileViewer Viewer(FileName,FALSE,DisableHistory,Title,X1,Y1,X2,Y2,CodePage); + /* $ 28.05.2001 По умолчанию Вьюер, поэтому нужно здесь признак выставиль явно */ + Viewer.SetDynamicallyBorn(false); + FrameManager->EnterModalEV(); + FrameManager->ExecuteModal(); + FrameManager->ExitModalEV(); + + /* $ 14.06.2002 IS + Обработка VF_DELETEONLYFILEONCLOSE - этот флаг имеет более низкий + приоритет по сравнению с VF_DELETEONCLOSE + */ + if (Flags & (VF_DELETEONCLOSE|VF_DELETEONLYFILEONCLOSE)) + Viewer.SetTempViewName(FileName,(Flags&VF_DELETEONCLOSE)?TRUE:FALSE); + + Viewer.SetEnableF6((Flags & VF_ENABLE_F6) ); + + if (!Viewer.GetExitCode()) + { + return FALSE; + } + } + + return TRUE; +} + +int WINAPI FarViewer(const wchar_t *FileName,const wchar_t *Title, + int X1,int Y1,int X2, int Y2,DWORD Flags, UINT CodePage) +{ + return InterThreadCall<int, 0>(std::bind(FarViewerSynched, FileName, Title, X1, Y1, X2, Y2, Flags, CodePage)); +} + +int FarEditorSynched( const wchar_t *FileName, const wchar_t *Title, + int X1, int Y1, int X2, int Y2, DWORD Flags, int StartLine, int StartChar, UINT CodePage) +{ + if (FrameManager->ManagerIsDown()) + return EEC_OPEN_ERROR; + + ConsoleTitle ct; + /* $ 12.07.2000 IS + Проверка флагов редактора (раньше они игнорировались) и открытие + немодального редактора, если есть соответствующий флаг + */ + int CreateNew = (Flags & EF_CREATENEW)?TRUE:FALSE; + int Locked=(Flags & EF_LOCKED)?TRUE:FALSE; + int DisableHistory=(Flags & EF_DISABLEHISTORY)?TRUE:FALSE; + /* $ 14.06.2002 IS + Обработка EF_DELETEONLYFILEONCLOSE - этот флаг имеет более низкий + приоритет по сравнению с EF_DELETEONCLOSE + */ + int DeleteOnClose = 0; + + if (Flags & EF_DELETEONCLOSE) + DeleteOnClose = 1; + else if (Flags & EF_DELETEONLYFILEONCLOSE) + DeleteOnClose = 2; + + int OpMode=FEOPMODE_QUERY; + + if ((Flags&EF_OPENMODE_MASK) ) + OpMode=Flags&EF_OPENMODE_MASK; + + /*$ 15.05.2002 SKV + Запретим вызов немодального редактора, если находимся в модальном + редакторе или вьюере. + */ + if (FrameManager->InModalEV()) + { + Flags&=~EF_NONMODAL; + } + + int editorExitCode; + int ExitCode=EEC_OPEN_ERROR; + + if (Flags & EF_NONMODAL) + { + /* 09.09.2001 IS ! Добавим имя файла в историю, если потребуется */ + FileEditor *Editor=new(std::nothrow) FileEditor(FileName,CodePage,(CreateNew?FFILEEDIT_CANNEWFILE:0)|FFILEEDIT_ENABLEF6|(DisableHistory?FFILEEDIT_DISABLEHISTORY:0)|(Locked?FFILEEDIT_LOCKED:0), + StartLine,StartChar,Title, + X1,Y1,X2,Y2, + DeleteOnClose,OpMode); + + if (Editor) + { + editorExitCode=Editor->GetExitCode(); + + // добавочка - проверка кода возврата (почему возникает XC_OPEN_ERROR - см. код FileEditor::Init()) + if (editorExitCode == XC_OPEN_ERROR || editorExitCode == XC_LOADING_INTERRUPTED) + { + delete Editor; + Editor=nullptr; + return editorExitCode; + } + + Editor->SetEnableF6((Flags & EF_ENABLE_F6) ); + Editor->SetPluginTitle(Title); + + /* $ 21.05.2002 SKV - Запускаем свой цикл, только если не был указан флаг. */ + if (!(Flags&EF_IMMEDIATERETURN)) + { + FrameManager->ExecuteNonModal(); + } + else + { + if (GlobalSaveScrPtr) + GlobalSaveScrPtr->Discard(); + + FrameManager->PluginCommit(); + } + + ExitCode=XC_MODIFIED; + } + } + else + { + /* 09.09.2001 IS ! Добавим имя файла в историю, если потребуется */ + FileEditor Editor(FileName,CodePage,(CreateNew?FFILEEDIT_CANNEWFILE:0)|(DisableHistory?FFILEEDIT_DISABLEHISTORY:0)|(Locked?FFILEEDIT_LOCKED:0), + StartLine,StartChar,Title, + X1,Y1,X2,Y2, + DeleteOnClose,OpMode); + editorExitCode=Editor.GetExitCode(); + + // выполним предпроверку (ошибки разные могут быть) + if (editorExitCode == XC_OPEN_ERROR || editorExitCode == XC_LOADING_INTERRUPTED) + ExitCode=editorExitCode; + else + { + Editor.SetDynamicallyBorn(false); + Editor.SetEnableF6((Flags & EF_ENABLE_F6) ); + Editor.SetPluginTitle(Title); + /* $ 15.05.2002 SKV + Зафиксируем вход и выход в/из модального редактора. + */ + FrameManager->EnterModalEV(); + FrameManager->ExecuteModal(); + FrameManager->ExitModalEV(); + ExitCode = Editor.GetExitCode(); + + if (ExitCode) + { +#if 0 + + if (OpMode==FEOPMODE_BREAKIFOPEN && ExitCode==XC_QUIT) + ExitCode = XC_OPEN_ERROR; + else +#endif + ExitCode = Editor.IsFileChanged()?XC_MODIFIED:XC_NOT_MODIFIED; + } + } + } + + return ExitCode; +} + +int WINAPI FarEditor( const wchar_t *FileName, const wchar_t *Title, + int X1, int Y1, int X2, int Y2, DWORD Flags, int StartLine, int StartChar, UINT CodePage) +{ + return InterThreadCall<int, EEC_OPEN_ERROR>(std::bind(FarEditorSynched, + FileName, Title, X1, Y1, X2, Y2, Flags, StartLine, StartChar, CodePage)); +} + + +int WINAPI FarCmpName(const wchar_t *pattern,const wchar_t *string,int skippath) +{ + return(CmpName(pattern,string,skippath!=0) ? TRUE : FALSE); +} + + +static bool FarTextSynched(int X,int Y,int Color,const wchar_t *Str) +{ + if (DisablePluginsOutput || FrameManager->ManagerIsDown()) + return false; + + if (!Str) + { + int PrevLockCount=ScrBuf.GetLockCount(); + ScrBuf.SetLockCount(0); + ScrBuf.Flush(); + ScrBuf.SetLockCount(PrevLockCount); + } + else + { + Text(X,Y,Color,Str); + } + return true; +} + + +void WINAPI FarText(int X,int Y,int Color,const wchar_t *Str) +{ + InterThreadCall<bool>(std::bind(FarTextSynched, X, Y, Color, Str)); +} + +static int FarEditorControlSynched(int Command,void *Param) +{ + if (FrameManager->ManagerIsDown() || !CtrlObject->Plugins.CurEditor) + return 0; + + return(CtrlObject->Plugins.CurEditor->EditorControl(Command,Param)); +} + +int WINAPI FarEditorControl(int Command,void *Param) +{ + return InterThreadCall<int, 0>(std::bind(FarEditorControlSynched, Command, Param)); +} + + +static int FarViewerControlSynched(int Command,void *Param) +{ + if (FrameManager->ManagerIsDown() || !CtrlObject->Plugins.CurViewer) + return 0; + + return(CtrlObject->Plugins.CurViewer->ViewerControl(Command,Param)); +} + +int WINAPI FarViewerControl(int Command,void *Param) +{ + return InterThreadCall<int, 0>(std::bind(FarViewerControlSynched, Command, Param)); +} + + +void WINAPI farUpperBuf(wchar_t *Buf, int Length) +{ + return UpperBuf(Buf, Length); +} + +void WINAPI farLowerBuf(wchar_t *Buf, int Length) +{ + return LowerBuf(Buf, Length); +} + +void WINAPI farStrUpper(wchar_t *s1) +{ + return StrUpper(s1); +} + +void WINAPI farStrLower(wchar_t *s1) +{ + return StrLower(s1); +} + +wchar_t WINAPI farUpper(wchar_t Ch) +{ + return Upper(Ch); +} + +wchar_t WINAPI farLower(wchar_t Ch) +{ + return Lower(Ch); +} + +int WINAPI farStrCmpNI(const wchar_t *s1, const wchar_t *s2, int n) +{ + return StrCmpNI(s1, s2, n); +} + +int WINAPI farStrCmpI(const wchar_t *s1, const wchar_t *s2) +{ + return StrCmpI(s1, s2); +} + +int WINAPI farIsLower(wchar_t Ch) +{ + return IsLower(Ch); +} + +int WINAPI farIsUpper(wchar_t Ch) +{ + return IsUpper(Ch); +} + +int WINAPI farIsAlpha(wchar_t Ch) +{ + return IsAlpha(Ch); +} + +int WINAPI farIsAlphaNum(wchar_t Ch) +{ + return IsAlphaNum(Ch); +} + +int WINAPI farGetFileOwner(const wchar_t *Computer,const wchar_t *Name, wchar_t *Owner,int Size) +{ + FARString strOwner; + /*int Ret=*/GetFileOwner(Computer,Name,strOwner); + + if (Owner && Size) + far_wcsncpy(Owner,strOwner,Size); + + return static_cast<int>(strOwner.GetLength()+1); +} + +int WINAPI farConvertPath(CONVERTPATHMODES Mode,const wchar_t *Src, wchar_t *Dest, int DestSize) +{ + if (Src && *Src) + { + FARString strDest; + + switch (Mode) + { + case CPM_NATIVE: + strDest=NTPath(Src).Get(); + break; + case CPM_REAL: + ConvertNameToReal(Src, strDest); + break; + case CPM_FULL: + default: + ConvertNameToFull(Src, strDest); + break; + } + + if (Dest && DestSize) + far_wcsncpy(Dest, strDest.CPtr(), DestSize); + + return static_cast<int>(strDest.GetLength()) + 1; + } + else + { + if (Dest && DestSize) + *Dest = 0; + + return 1; + } +} + +int WINAPI farGetReparsePointInfo(const wchar_t *Src,wchar_t *Dest,int DestSize) +{ + _LOGCOPYR(CleverSysLog Clev(L"farGetReparsePointInfo()")); + _LOGCOPYR(SysLog(L"Params: Src='%ls'",Src)); + /* + if (Src && *Src) + { + FARString strSrc(Src); + FARString strDest; + AddEndSlash(strDest); + DWORD Size=GetReparsePointInfo(strSrc,strDest,nullptr); + _LOGCOPYR(SysLog(L"return -> %d strSrc='%ls', strDest='%ls'",__LINE__,strSrc.CPtr(),strDest.CPtr())); + + if (DestSize && Dest) + far_wcsncpy(Dest,strDest,DestSize); + + return Size; + }*/ + + return 0; +} + +int WINAPI farGetPathRoot(const wchar_t *Path, wchar_t *Root, int DestSize) +{ + fprintf(stderr, "DEPRECATED: %s('%ls')\n", __FUNCTION__, Path); + + if (Path && *Path) + { + if (DestSize >= 2 && Root) + { + Root[0] = GOOD_SLASH; + Root[1] = 0; + } + + return 2; + } + else + { + if (DestSize >= 1 && Root) + { + Root[0] = 0; + } + + return 1; + } +} + +static int farPluginsControlSynched(HANDLE hHandle, int Command, int Param1, LONG_PTR Param2) +{ + switch (Command) + { + case PCTL_CACHEFORGET: + case PCTL_LOADPLUGIN: + case PCTL_UNLOADPLUGIN: + case PCTL_FORCEDLOADPLUGIN: + { + if (Param1 == PLT_PATH) + { + if (Param2 ) + { + FARString strPath; + ConvertNameToFull((const wchar_t *)Param2, strPath); + + if (Command == PCTL_CACHEFORGET) + return CtrlObject->Plugins.CacheForget(strPath); + if (Command == PCTL_LOADPLUGIN) + return CtrlObject->Plugins.LoadPluginExternal(strPath, false); + if (Command == PCTL_FORCEDLOADPLUGIN) + return CtrlObject->Plugins.LoadPluginExternal(strPath, true); + else + return CtrlObject->Plugins.UnloadPluginExternal(strPath); + } + } + + break; + } + } + + return 0; +} + +int WINAPI farPluginsControl(HANDLE hHandle, int Command, int Param1, LONG_PTR Param2) +{ + return InterThreadCall<int, 0>(std::bind(farPluginsControlSynched, hHandle, Command, Param1, Param2)); +} + +int WINAPI farFileFilterControl(HANDLE hHandle, int Command, int Param1, LONG_PTR Param2) +{ + FileFilter *Filter=nullptr; + + if (Command != FFCTL_CREATEFILEFILTER) + { + if (hHandle == INVALID_HANDLE_VALUE) + return FALSE; + + Filter = (FileFilter *)hHandle; + } + + switch (Command) + { + case FFCTL_CREATEFILEFILTER: + { + if (!Param2) + break; + + *((HANDLE *)Param2) = INVALID_HANDLE_VALUE; + + if (hHandle != PANEL_ACTIVE && hHandle != PANEL_PASSIVE && hHandle != PANEL_NONE) + break; + + switch (Param1) + { + case FFT_PANEL: + case FFT_FINDFILE: + case FFT_COPY: + case FFT_SELECT: + case FFT_CUSTOM: + break; + default: + return FALSE; + } + + Filter = new(std::nothrow) FileFilter((Panel *)hHandle, (FAR_FILE_FILTER_TYPE)Param1); + + if (Filter) + { + *((HANDLE *)Param2) = (HANDLE)Filter; + return TRUE; + } + + break; + } + case FFCTL_FREEFILEFILTER: + { + delete Filter; + return TRUE; + } + case FFCTL_OPENFILTERSMENU: + { + return Filter->FilterEdit() ? TRUE : FALSE; + } + case FFCTL_STARTINGTOFILTER: + { + Filter->UpdateCurrentTime(); + return TRUE; + } + case FFCTL_ISFILEINFILTER: + { + if (!Param2) + break; + + return Filter->FileInFilter(*(const FAR_FIND_DATA *)Param2) ? TRUE : FALSE; + } + } + + return FALSE; +} + +int WINAPI farRegExpControl(HANDLE hHandle, int Command, LONG_PTR Param) +{ + RegExp* re=nullptr; + + if (Command != RECTL_CREATE) + { + if (hHandle == INVALID_HANDLE_VALUE) + return FALSE; + + re = (RegExp*)hHandle; + } + + switch (Command) + { + case RECTL_CREATE: + + if (!Param) + break; + + *((HANDLE*)Param) = INVALID_HANDLE_VALUE; + re = new(std::nothrow) RegExp; + + if (re) + { + *((HANDLE*)Param) = (HANDLE)re; + return TRUE; + } + + break; + case RECTL_FREE: + delete re; + return TRUE; + case RECTL_COMPILE: + return re->Compile((const wchar_t*)Param,OP_PERLSTYLE); + case RECTL_OPTIMIZE: + return re->Optimize(); + case RECTL_MATCHEX: + { + RegExpSearch* data=(RegExpSearch*)Param; + return re->MatchEx(ReStringView(data->Text,data->Length),data->Position,data->Match,data->Count +#ifdef NAMEDBRACKETS + ,data->Reserved +#endif + ); + } + case RECTL_SEARCHEX: + { + RegExpSearch* data=(RegExpSearch*)Param; + return re->SearchEx(ReStringView(data->Text,data->Length),data->Position,data->Match,data->Count +#ifdef NAMEDBRACKETS + ,data->Reserved +#endif + ); + } + case RECTL_BRACKETSCOUNT: + return re->GetBracketsCount(); + } + + return FALSE; +} + +DWORD WINAPI farGetCurrentDirectory(DWORD Size,wchar_t* Buffer) +{ + FARString strCurDir; + apiGetCurrentDirectory(strCurDir); + + if (Buffer && Size) + { + far_wcsncpy(Buffer,strCurDir,Size); + } + + return static_cast<DWORD>(strCurDir.GetLength()+1); +} diff --git a/far2l/src/plug/plugapi.hpp b/far2l/src/plug/plugapi.hpp new file mode 100644 index 00000000..442f7403 --- /dev/null +++ b/far2l/src/plug/plugapi.hpp @@ -0,0 +1,175 @@ +#pragma once + +/* +plugapi.hpp + +API, доступное плагинам (диалоги, меню, ...) +*/ +/* +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. +*/ + +//----------- PLUGIN API/FSF --------------------------------------------------- +//все эти функции, за исключение sprintf/sscanf имеют тип вызова __stdcall + +wchar_t *WINAPI FarItoa(int value, wchar_t *string, int radix); +int64_t WINAPI FarAtoi64(const wchar_t *s); +wchar_t *WINAPI FarItoa64(int64_t value, wchar_t *string, int radix); +int WINAPI FarAtoi(const wchar_t *s); +void WINAPI FarQsort(void *base, size_t nelem, size_t width, int (__cdecl *fcmp)(const void *, const void *)); +void WINAPI FarQsortEx(void *base, size_t nelem, size_t width, int (__cdecl *fcmp)(const void *, const void *,void *),void*); +void *WINAPI FarBsearch(const void *key, const void *base, size_t nelem, size_t width, int (__cdecl *fcmp)(const void *, const void *)); + +void WINAPI DeleteBuffer(void* Buffer); + +void WINAPI farUpperBuf(wchar_t *Buf, int Length); +void WINAPI farLowerBuf(wchar_t *Buf, int Length); +void WINAPI farStrUpper(wchar_t *s1); +void WINAPI farStrLower(wchar_t *s1); +wchar_t WINAPI farUpper(wchar_t Ch); +wchar_t WINAPI farLower(wchar_t Ch); +int WINAPI farStrCmpNI(const wchar_t *s1, const wchar_t *s2, int n); +int WINAPI farStrCmpI(const wchar_t *s1, const wchar_t *s2); +int WINAPI farIsLower(wchar_t Ch); +int WINAPI farIsUpper(wchar_t Ch); +int WINAPI farIsAlpha(wchar_t Ch); +int WINAPI farIsAlphaNum(wchar_t Ch); + +int WINAPI farGetFileOwner(const wchar_t *Computer,const wchar_t *Name, wchar_t *Owner,int Size); + +int WINAPI farConvertPath(CONVERTPATHMODES Mode,const wchar_t *Src,wchar_t *Dest,int DestSize); + +int WINAPI farGetReparsePointInfo(const wchar_t *Src,wchar_t *Dest,int DestSize); + +int WINAPI farGetPathRoot(const wchar_t *Path, wchar_t *Root, int DestSize); + +int WINAPI FarGetPluginDirList(INT_PTR PluginNumber,HANDLE hPlugin, + const wchar_t *Dir,struct PluginPanelItem **pPanelItem, + int *pItemsNumber); +void WINAPI FarFreePluginDirList(PluginPanelItem *PanelItem, int ItemsNumber); + +int WINAPI FarMenuFn(INT_PTR PluginNumber,int X,int Y,int MaxHeight, + DWORD Flags,const wchar_t *Title,const wchar_t *Bottom, + const wchar_t *HelpTopic,const int *BreakKeys,int *BreakCode, + const struct FarMenuItem *Item, int ItemsNumber); +const wchar_t* WINAPI FarGetMsgFn(INT_PTR PluginHandle,int MsgId); +int WINAPI FarMessageFn(INT_PTR PluginNumber,DWORD Flags, + const wchar_t *HelpTopic,const wchar_t * const *Items,int ItemsNumber, + int ButtonsNumber); +int WINAPI FarControl(HANDLE hPlugin,int Command,int Param1,LONG_PTR Param2); +HANDLE WINAPI FarSaveScreen(int X1,int Y1,int X2,int Y2); +void WINAPI FarRestoreScreen(HANDLE hScreen); + +int WINAPI FarGetDirList(const wchar_t *Dir, FAR_FIND_DATA **pPanelItem, int *pItemsNumber); +void WINAPI FarFreeDirList(FAR_FIND_DATA *PanelItem, int nItemsNumber); + +int WINAPI FarViewer(const wchar_t *FileName,const wchar_t *Title, + int X1,int Y1,int X2,int Y2,DWORD Flags, UINT CodePage); +int WINAPI FarEditor(const wchar_t *FileName,const wchar_t *Title, + int X1,int Y1,int X2, int Y2,DWORD Flags, + int StartLine,int StartChar, UINT CodePage); +int WINAPI FarCmpName(const wchar_t *pattern,const wchar_t *string,int skippath); +void WINAPI FarText(int X,int Y,int Color,const wchar_t *Str); +int WINAPI TextToCharInfo(const char *Text,WORD Attr, CHAR_INFO *CharInfo, int Length, DWORD Reserved); +int WINAPI FarEditorControl(int Command,void *Param); + +int WINAPI FarViewerControl(int Command,void *Param); + +/* Функция вывода помощи */ +BOOL WINAPI FarShowHelp(const wchar_t *ModuleName, + const wchar_t *HelpTopic,DWORD Flags); + +/* Обертка вокруг GetString для плагинов - с меньшей функциональностью. + Сделано для того, чтобы не дублировать код GetString.*/ + +int WINAPI FarInputBox(const wchar_t *Title,const wchar_t *Prompt, + const wchar_t *HistoryName,const wchar_t *SrcText, + wchar_t *DestText,int DestLength, + const wchar_t *HelpTopic,DWORD Flags); +/* Функция, которая будет действовать и в редакторе, и в панелях, и... */ +INT_PTR WINAPI FarAdvControl(INT_PTR ModuleNumber, int Command, void *Param); +// Функция расширенного диалога +HANDLE WINAPI FarDialogInit(INT_PTR PluginNumber, int X1, int Y1, int X2, int Y2, + const wchar_t *HelpTopic, struct FarDialogItem *Item, + unsigned int ItemsNumber, DWORD Reserved, DWORD Flags, + FARWINDOWPROC Proc, LONG_PTR Param); +int WINAPI FarDialogRun(HANDLE hDlg); +void WINAPI FarDialogFree(HANDLE hDlg); +// Функция обработки диалога по умолчанию +LONG_PTR WINAPI FarDefDlgProc(HANDLE hDlg,int Msg,int Param1,LONG_PTR Param2); +// Посылка сообщения диалогу +LONG_PTR WINAPI FarSendDlgMessage(HANDLE hDlg,int Msg,int Param1, LONG_PTR Param2); + +int WINAPI farPluginsControl(HANDLE hHandle, int Command, int Param1, LONG_PTR Param2); + +int WINAPI farFileFilterControl(HANDLE hHandle, int Command, int Param1, LONG_PTR Param2); + +int WINAPI farRegExpControl(HANDLE hHandle, int Command, LONG_PTR Param); + +DWORD WINAPI farGetCurrentDirectory(DWORD Size,wchar_t* Buffer); + + +enum ExceptFunctionsType +{ + EXCEPT_KERNEL=-1, + EXCEPT_SETSTARTUPINFO, + EXCEPT_GETVIRTUALFINDDATA, + EXCEPT_OPENPLUGIN, + EXCEPT_OPENFILEPLUGIN, + EXCEPT_CLOSEPLUGIN, + EXCEPT_GETPLUGININFO, + EXCEPT_GETOPENPLUGININFO, + EXCEPT_GETFINDDATA, + EXCEPT_FREEFINDDATA, + EXCEPT_FREEVIRTUALFINDDATA, + EXCEPT_SETDIRECTORY, + EXCEPT_GETFILES, + EXCEPT_PUTFILES, + EXCEPT_DELETEFILES, + EXCEPT_MAKEDIRECTORY, + EXCEPT_PROCESSHOSTFILE, + EXCEPT_SETFINDLIST, + EXCEPT_CONFIGURE, + EXCEPT_EXITFAR, + EXCEPT_MAYEXITFAR, + EXCEPT_PROCESSKEY, + EXCEPT_PROCESSEVENT, + EXCEPT_PROCESSEDITOREVENT, + EXCEPT_COMPARE, + EXCEPT_PROCESSEDITORINPUT, + EXCEPT_MINFARVERSION, + EXCEPT_PROCESSVIEWEREVENT, + EXCEPT_PROCESSVIEWERINPUT, + EXCEPT_PROCESSDIALOGEVENT, + EXCEPT_PROCESSSYNCHROEVENT, + EXCEPT_ANALYSE, + EXCEPT_GETCUSTOMDATA, + EXCEPT_FREECUSTOMDATA, +#if defined(PROCPLUGINMACROFUNC) + EXCEPT_PROCESSMACROFUNC, +#endif +}; diff --git a/far2l/src/plug/plugins.cpp b/far2l/src/plug/plugins.cpp new file mode 100644 index 00000000..cfe7c9f3 --- /dev/null +++ b/far2l/src/plug/plugins.cpp @@ -0,0 +1,2084 @@ +/* +plugins.cpp + +Работа с плагинами (низкий уровень, кое-что повыше в flplugin.cpp) +*/ +/* +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" + + +#include "plugins.hpp" +#include "lang.hpp" +#include "keys.hpp" +#include "scantree.hpp" +#include "chgprior.hpp" +#include "chgmmode.hpp" +#include "constitle.hpp" +#include "cmdline.hpp" +#include "filepanels.hpp" +#include "panel.hpp" +#include "vmenu.hpp" +#include "dialog.hpp" +#include "rdrwdsk.hpp" +#include "savescr.hpp" +#include "ctrlobj.hpp" +#include "scrbuf.hpp" +#include "udlist.hpp" +#include "fileedit.hpp" +#include "RefreshFrameManager.hpp" +#include "plugapi.hpp" +#include "pathmix.hpp" +#include "strmix.hpp" +#include "processname.hpp" +#include "interf.hpp" +#include "filelist.hpp" +#include "message.hpp" +#include "SafeMMap.hpp" +#include "HotkeyLetterDialog.hpp" +#include "InterThreadCall.hpp" +#include <KeyFileHelper.h> +#include <crc64.h> + +const char *FmtDiskMenuStringD = "DiskMenuString%d"; +const char *FmtPluginMenuStringD = "PluginMenuString%d"; +const char *FmtPluginConfigStringD = "PluginConfigString%d"; +const char *SettingsSection = "Settings"; +static const wchar_t *PluginsFolderName = L"Plugins"; + +static int _cdecl PluginsSort(const void *el1,const void *el2); + +enum PluginType +{ + NOT_PLUGIN = 0, + WIDE_PLUGIN, + MULTIBYTE_PLUGIN +}; + +//// + +const char *PluginsIni() +{ + static std::string s_out(InMyConfig("plugins/state.ini")); + return s_out.c_str(); +} + +// Return string used as ini file key that represents given +// plugin object file. To reduce overhead encode less meaningful +// components like file path and extension as CRC suffix, leaded +// by actual plugin file name. +// If plugins resided in a path that is nested under g_strFarPath +// then dismiss g_strFarPath from CRC to make result invariant to +// whole package relocation. +static std::string PluginSettingsName(const FARString &strModuleName) +{ + std::string pathname; + + const size_t FarPathLength = g_strFarPath.GetLength(); + if (FarPathLength < strModuleName.GetLength() + && !StrCmpNI(strModuleName, g_strFarPath, (int)FarPathLength)) + { + Wide2MB(strModuleName.CPtr() + FarPathLength, pathname); + } + else + { + Wide2MB(strModuleName.CPtr(), pathname); + } + + FilePathHashSuffix(pathname); + + return pathname; +} + +static PluginType PluginTypeByExtension(const wchar_t *lpModuleName) +{ + const wchar_t *ext = wcsrchr(lpModuleName, L'.'); + if (ext) { + if (wcscmp(ext, L".far-plug-wide")==0) + return WIDE_PLUGIN; + if (wcscmp(ext, L".far-plug-mb")==0) + return MULTIBYTE_PLUGIN; + } + + return NOT_PLUGIN; +} + + +PluginManager::PluginManager(): + PluginsData(nullptr), + PluginsCount(0), + OemPluginsCount(0), + CurPluginItem(nullptr), + CurEditor(nullptr), + CurViewer(nullptr) +{ +} + +PluginManager::~PluginManager() +{ + CurPluginItem=nullptr; + Plugin *pPlugin; + + for (int i = 0; i < PluginsCount; i++) + { + pPlugin = PluginsData[i]; + pPlugin->Unload(true); + delete pPlugin; + } + if(PluginsData) + { + free(PluginsData); + } +} + +bool PluginManager::AddPlugin(Plugin *pPlugin) +{ + Plugin **NewPluginsData=(Plugin**)realloc(PluginsData,sizeof(*PluginsData)*(PluginsCount+1)); + + if (!NewPluginsData) + return false; + + PluginsData = NewPluginsData; + PluginsData[PluginsCount]=pPlugin; + PluginsCount++; + if(pPlugin->IsOemPlugin()) + { + OemPluginsCount++; + } + return true; +} + +bool PluginManager::RemovePlugin(Plugin *pPlugin) +{ + for (int i = 0; i < PluginsCount; i++) + { + if (PluginsData[i] == pPlugin) + { + if(pPlugin->IsOemPlugin()) + { + OemPluginsCount--; + } + delete pPlugin; + memmove(&PluginsData[i], &PluginsData[i+1], (PluginsCount-i-1)*sizeof(Plugin*)); + PluginsCount--; + return true; + } + } + + return false; +} + + +bool PluginManager::LoadPlugin( + const FARString &strModuleName, + bool UncachedLoad +) +{ + const PluginType PlType = PluginTypeByExtension(strModuleName); + + if (PlType == NOT_PLUGIN) + return false; + + struct stat st{}; + if (stat(strModuleName.GetMB().c_str(), &st) == -1) + { + fprintf(stderr, "%s: stat error %u for '%ls'\n", + __FUNCTION__, errno, strModuleName.CPtr()); + return false; + } + + const std::string &SettingsName = PluginSettingsName(strModuleName); + const std::string &ModuleID = StrPrintf("%llx.%llx.%llx.%llx", + (unsigned long long)st.st_ino, (unsigned long long)st.st_size, + (unsigned long long)st.st_mtime, (unsigned long long)st.st_ctime); + + Plugin *pPlugin = nullptr; + + switch (PlType) + { + case WIDE_PLUGIN: + pPlugin = new(std::nothrow) PluginW(this, strModuleName, SettingsName, ModuleID); + break; + case MULTIBYTE_PLUGIN: + pPlugin = new(std::nothrow) PluginA(this, strModuleName, SettingsName, ModuleID); + break; + default: + abort(); + } + + if (!pPlugin) + return false; + + if (!AddPlugin(pPlugin)) + { + delete pPlugin; + return false; + } + + bool bResult = false; + + if (!UncachedLoad) + { + bResult = pPlugin->LoadFromCache(); + fprintf(stderr, "%s: cache %s for '%ls'\n", + __FUNCTION__, bResult ? "hit" : "miss", strModuleName.CPtr()); + } + + if (!bResult && !Opt.LoadPlug.PluginsCacheOnly) + { + bResult = pPlugin->Load(); + + if (!bResult) + RemovePlugin(pPlugin); + } + + return bResult; +} + +bool PluginManager::CacheForget(const wchar_t *lpwszModuleName) +{ + KeyFileHelper kfh(PluginsIni()); + const std::string &SettingsName = PluginSettingsName(lpwszModuleName); + if (!kfh.RemoveSection(SettingsName)) + { + fprintf(stderr, "%s: nothing to forget for '%ls'\n", __FUNCTION__, lpwszModuleName); + return false; + } + fprintf(stderr, "%s: forgotten - '%ls'\n", __FUNCTION__, lpwszModuleName); + return true; +} + +bool PluginManager::LoadPluginExternal(const wchar_t *lpwszModuleName, bool LoadToMem) +{ + Plugin *pPlugin = GetPlugin(lpwszModuleName); + + if (pPlugin) + { + if (LoadToMem && !pPlugin->Load()) + { + RemovePlugin(pPlugin); + return false; + } + } + else + { + if (!LoadPlugin(lpwszModuleName, LoadToMem)) + return false; + + far_qsort(PluginsData, PluginsCount, sizeof(*PluginsData), PluginsSort); + } + return true; +} + +int PluginManager::UnloadPlugin(Plugin *pPlugin, DWORD dwException, bool bRemove) +{ + int nResult = FALSE; + + if (pPlugin && (dwException != EXCEPT_EXITFAR)) //схитрим, если упали в EXITFAR, не полезем в рекурсию, мы и так в Unload + { + //какие-то непонятные действия... + CurPluginItem=nullptr; + Frame *frame; + + if ((frame = FrameManager->GetBottomFrame()) ) + frame->Unlock(); + + if (Flags.Check(PSIF_DIALOG)) // BugZ#52 exception handling for floating point incorrect + { + Flags.Clear(PSIF_DIALOG); + FrameManager->DeleteFrame(); + FrameManager->PluginCommit(); + } + + bool bPanelPlugin = pPlugin->IsPanelPlugin(); + + if (dwException != (DWORD)-1) + nResult = pPlugin->Unload(true); + else + nResult = pPlugin->Unload(false); + + if (bPanelPlugin /*&& bUpdatePanels*/) + { + CtrlObject->Cp()->ActivePanel->SetCurDir(L".",TRUE); + Panel *ActivePanel=CtrlObject->Cp()->ActivePanel; + ActivePanel->Update(UPDATE_KEEP_SELECTION); + ActivePanel->Redraw(); + Panel *AnotherPanel=CtrlObject->Cp()->GetAnotherPanel(ActivePanel); + AnotherPanel->Update(UPDATE_KEEP_SELECTION|UPDATE_SECONDARY); + AnotherPanel->Redraw(); + } + + if (bRemove) + RemovePlugin(pPlugin); + } + + return nResult; +} + +int PluginManager::UnloadPluginExternal(const wchar_t *lpwszModuleName) +{ +//BUGBUG нужны проверки на легальность выгрузки + int nResult = FALSE; + Plugin *pPlugin = GetPlugin(lpwszModuleName); + + if (pPlugin) + { + nResult = pPlugin->Unload(true); + RemovePlugin(pPlugin); + } + + return nResult; +} + +Plugin *PluginManager::GetPlugin(const wchar_t *lpwszModuleName) +{ + Plugin *pPlugin; + + for (int i = 0; i < PluginsCount; i++) + { + pPlugin = PluginsData[i]; + + if (!StrCmp(lpwszModuleName, pPlugin->GetModuleName())) + return pPlugin; + } + + return nullptr; +} + +Plugin *PluginManager::GetPlugin(int PluginNumber) +{ + if (PluginNumber < PluginsCount && PluginNumber >= 0) + return PluginsData[PluginNumber]; + + return nullptr; +} + +void PluginManager::LoadPlugins() +{ + Flags.Clear(PSIF_PLUGINSLOADDED); + + if (Opt.LoadPlug.PluginsCacheOnly) // $ 01.09.2000 tran '/co' switch + { + LoadPluginsFromCache(); + } + else if (Opt.LoadPlug.MainPluginDir || !Opt.LoadPlug.strCustomPluginsPath.IsEmpty() || (Opt.LoadPlug.PluginsPersonal && !Opt.LoadPlug.strPersonalPluginsPath.IsEmpty())) + { + ScanTree ScTree(FALSE,TRUE,Opt.LoadPlug.ScanSymlinks); + UserDefinedList PluginPathList; // хранение списка каталогов + FARString strPluginsDir; + FARString strFullName; + FAR_FIND_DATA_EX FindData; + PluginPathList.SetParameters(0,0,ULF_UNIQUE); + + // сначала подготовим список + if (Opt.LoadPlug.MainPluginDir) // только основные и персональные? + { + strPluginsDir = g_strFarPath + PluginsFolderName; + PluginPathList.AddItem(strPluginsDir); + + if (TranslateFarString<TranslateInstallPath_Share2Lib>(strPluginsDir)) { + PluginPathList.AddItem(strPluginsDir); + } + + // ...а персональные есть? + if (Opt.LoadPlug.PluginsPersonal && !Opt.LoadPlug.strPersonalPluginsPath.IsEmpty() && !(Opt.Policies.DisabledOptions&FFPOL_PERSONALPATH)) + PluginPathList.AddItem(Opt.LoadPlug.strPersonalPluginsPath); + } + else if (!Opt.LoadPlug.strCustomPluginsPath.IsEmpty()) // только "заказные" пути? + { + PluginPathList.AddItem(Opt.LoadPlug.strCustomPluginsPath); + } + + const wchar_t *NamePtr; + + // теперь пройдемся по всему ранее собранному списку + for (size_t PPLI = 0; nullptr!=(NamePtr=PluginPathList.Get(PPLI)); ++PPLI) + { + // расширяем значение пути + apiExpandEnvironmentStrings(NamePtr,strFullName); + Unquote(strFullName); //??? здесь ХЗ + + if (!IsAbsolutePath(strFullName)) + { + strPluginsDir = g_strFarPath; + strPluginsDir += strFullName; + strFullName = strPluginsDir; + } + + // Получим реальное значение полного длинного пути + ConvertNameToFull(strFullName,strFullName); + strPluginsDir = strFullName; + + if (strPluginsDir.IsEmpty()) // Хмм... а нужно ли ЭТО условие после такой модернизации алгоритма загрузки? + continue; + + // ставим на поток очередной путь из списка... + ScTree.SetFindPath(strPluginsDir,L"*.far-plug-*", 0); + + // ...и пройдемся по нему + while (ScTree.GetNextName(&FindData,strFullName)) + { + if (!(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + { + // this will check filename extension + LoadPlugin(strFullName, false); + } + } // end while + } + } + + Flags.Set(PSIF_PLUGINSLOADDED); + + far_qsort(PluginsData, PluginsCount, sizeof(*PluginsData), PluginsSort); +} + +/* $ 01.09.2000 tran + Load cache only plugins - '/co' switch */ +void PluginManager::LoadPluginsFromCache() +{ + KeyFileReadHelper kfh(PluginsIni()); + const std::vector<std::string> §ions = kfh.EnumSections(); + FARString strModuleName; + for (const auto &s : sections) + { + if (s != SettingsSection) + { + const std::string &module = kfh.GetString(s, "Module"); + if (!module.empty()) { + strModuleName = module; + LoadPlugin(strModuleName, false); + } + } + } +} + +int _cdecl PluginsSort(const void *el1,const void *el2) +{ + Plugin *Plugin1=*((Plugin**)el1); + Plugin *Plugin2=*((Plugin**)el2); + return (StrCmpI(PointToName(Plugin1->GetModuleName()),PointToName(Plugin2->GetModuleName()))); +} + +HANDLE PluginManager::OpenFilePlugin( + const wchar_t *Name, + int OpMode, + OPENFILEPLUGINTYPE Type, + Plugin *pDesiredPlugin +) +{ + ChangePriority ChPriority(ChangePriority::NORMAL); + ConsoleTitle ct(Opt.ShowCheckingFile?MSG(MCheckingFileInPlugin):nullptr); + HANDLE hResult = INVALID_HANDLE_VALUE; + PluginHandle *pResult = nullptr; + TPointerArray<PluginHandle> items; + FARString strFullName; + + if (Name) + { + ConvertNameToFull(Name,strFullName); + Name = strFullName; + } + + bool ShowMenu = Opt.PluginConfirm.OpenFilePlugin==BSTATE_3STATE? !(Type == OFP_NORMAL || Type == OFP_SEARCH) : Opt.PluginConfirm.OpenFilePlugin != 0; + if (Type==OFP_ALTERNATIVE) OpMode|= OPM_PGDN; + if (Type==OFP_COMMANDS) OpMode|= OPM_COMMANDS; + + Plugin *pPlugin = nullptr; + std::unique_ptr<SafeMMap> smm; + + for (int i = 0; i < PluginsCount; i++) + { + pPlugin = PluginsData[i]; + if (pDesiredPlugin != nullptr && pDesiredPlugin != pPlugin) + continue; + + if (!pPlugin->HasOpenFilePlugin() && !(pPlugin->HasAnalyse() && pPlugin->HasOpenPlugin())) + continue; + + if(Name && !smm) + { + try + { + smm.reset(new SafeMMap(Wide2MB(Name).c_str(), SafeMMap::M_READ, Opt.PluginMaxReadData)); + } + catch (std::exception &e) + { + fprintf(stderr, "PluginManager::OpenFilePlugin: %s\n", e.what()); + + if(!OpMode) + { + Message(MSG_WARNING|MSG_ERRORTYPE, 1, MB2Wide(e.what()).c_str(), + MSG(MOpenPluginCannotOpenFile), Name, MSG(MOk)); + } + break; + } + } + + if (pPlugin->HasOpenFilePlugin()) + { + if (Opt.ShowCheckingFile) + ct.Set(L"%ls - [%ls]...",MSG(MCheckingFileInPlugin),PointToName(pPlugin->GetModuleName())); + + HANDLE hPlugin = pPlugin->OpenFilePlugin(Name, + smm ? (const unsigned char *)smm->View() : nullptr, + smm ? (DWORD)smm->Length() : 0, OpMode); + + if (hPlugin == (HANDLE)-2) //сразу на выход, плагин решил нагло обработать все сам (Autorun/PictureView)!!! + { + hResult = (HANDLE)-2; + break; + } + + if (hPlugin != INVALID_HANDLE_VALUE) + { + PluginHandle *handle=items.addItem(); + handle->hPlugin = hPlugin; + handle->pPlugin = pPlugin; + } + } + else + { + AnalyseData AData; + AData.lpwszFileName = Name; + AData.pBuffer = smm ? (const unsigned char *)smm->View() : nullptr; + AData.dwBufferSize = smm ? (DWORD)smm->Length() : 0; + AData.OpMode = OpMode; + + if (pPlugin->Analyse(&AData)) + { + PluginHandle *handle=items.addItem(); + handle->pPlugin = pPlugin; + handle->hPlugin = INVALID_HANDLE_VALUE; + } + } + + if (items.getCount() && !ShowMenu) + break; + } + + if (items.getCount() && (hResult != (HANDLE)-2)) + { + bool OnlyOne = (items.getCount() == 1) && !(Name && Opt.PluginConfirm.OpenFilePlugin && Opt.PluginConfirm.StandardAssociation && Opt.PluginConfirm.EvenIfOnlyOnePlugin); + + if(!OnlyOne && ShowMenu) + { + VMenu menu(MSG(MPluginConfirmationTitle), nullptr, 0, ScrY-4); + menu.SetPosition(-1, -1, 0, 0); + menu.SetHelp(L"ChoosePluginMenu"); + menu.SetFlags(VMENU_SHOWAMPERSAND|VMENU_WRAPMODE); + MenuItemEx mitem; + + for (size_t i = 0; i < items.getCount(); i++) + { + PluginHandle *handle = items.getItem(i); + mitem.Clear(); + mitem.strName = PointToName(handle->pPlugin->GetModuleName()); + //NB: here is really should be used sizeof(handle), not sizeof(*handle) + //cuz sizeof(void *) has special meaning in SetUserData! + menu.SetUserData(handle, sizeof(handle), menu.AddItem(&mitem)); + } + + if (Opt.PluginConfirm.StandardAssociation && Type == OFP_NORMAL) + { + mitem.Clear(); + mitem.Flags |= MIF_SEPARATOR; + menu.AddItem(&mitem); + mitem.Clear(); + mitem.strName = MSG(MMenuPluginStdAssociation); + menu.AddItem(&mitem); + } + + menu.Show(); + + while (!menu.Done()) + { + menu.ReadInput(); + menu.ProcessInput(); + } + + if (menu.GetExitCode() == -1) + hResult = (HANDLE)-2; + else + pResult = (PluginHandle*)menu.GetUserData(nullptr, 0); + } + else + { + pResult = items.getItem(0); + } + + if (pResult && pResult->hPlugin == INVALID_HANDLE_VALUE) + { + HANDLE h = pResult->pPlugin->OpenPlugin(OPEN_ANALYSE, 0); + + if (h != INVALID_HANDLE_VALUE) + pResult->hPlugin = h; + else + pResult = nullptr; + } + } + + for (size_t i = 0; i < items.getCount(); i++) + { + PluginHandle *handle = items.getItem(i); + + if (handle != pResult) + { + if (handle->hPlugin != INVALID_HANDLE_VALUE) + handle->pPlugin->ClosePlugin(handle->hPlugin); + } + } + + if (pResult) + { + PluginHandle* pDup=new PluginHandle; + pDup->hPlugin=pResult->hPlugin; + pDup->pPlugin=pResult->pPlugin; + hResult=reinterpret_cast<HANDLE>(pDup); + } + + return hResult; +} + +HANDLE PluginManager::OpenFindListPlugin(const PluginPanelItem *PanelItem, int ItemsNumber) +{ + ChangePriority ChPriority(ChangePriority::NORMAL); + PluginHandle *pResult = nullptr; + TPointerArray<PluginHandle> items; + Plugin *pPlugin=nullptr; + + for (int i = 0; i < PluginsCount; i++) + { + pPlugin = PluginsData[i]; + + if (!pPlugin->HasSetFindList()) + continue; + + HANDLE hPlugin = pPlugin->OpenPlugin(OPEN_FINDLIST, 0); + + if (hPlugin != INVALID_HANDLE_VALUE) + { + PluginHandle *handle=items.addItem(); + handle->hPlugin = hPlugin; + handle->pPlugin = pPlugin; + } + + if (items.getCount() && !Opt.PluginConfirm.SetFindList) + break; + } + + if (items.getCount()) + { + if (items.getCount()>1) + { + VMenu menu(MSG(MPluginConfirmationTitle), nullptr, 0, ScrY-4); + menu.SetPosition(-1, -1, 0, 0); + menu.SetHelp(L"ChoosePluginMenu"); + menu.SetFlags(VMENU_SHOWAMPERSAND|VMENU_WRAPMODE); + MenuItemEx mitem; + + for (size_t i=0; i<items.getCount(); i++) + { + PluginHandle *handle = items.getItem(i); + mitem.Clear(); + mitem.strName=PointToName(handle->pPlugin->GetModuleName()); + menu.AddItem(&mitem); + } + + menu.Show(); + + while (!menu.Done()) + { + menu.ReadInput(); + menu.ProcessInput(); + } + + int ExitCode=menu.GetExitCode(); + + if (ExitCode>=0) + { + pResult=items.getItem(ExitCode); + } + } + else + { + pResult=items.getItem(0); + } + } + + if (pResult) + { + if (!pResult->pPlugin->SetFindList(pResult->hPlugin, PanelItem, ItemsNumber)) + { + pResult=nullptr; + } + } + + for (size_t i=0; i<items.getCount(); i++) + { + PluginHandle *handle=items.getItem(i); + + if (handle!=pResult) + { + if (handle->hPlugin!=INVALID_HANDLE_VALUE) + handle->pPlugin->ClosePlugin(handle->hPlugin); + } + } + + if (pResult) + { + PluginHandle* pDup=new PluginHandle; + pDup->hPlugin=pResult->hPlugin; + pDup->pPlugin=pResult->pPlugin; + pResult=pDup; + } + + return pResult?reinterpret_cast<HANDLE>(pResult):INVALID_HANDLE_VALUE; +} + + +void PluginManager::ClosePlugin(HANDLE hPlugin) +{ + ChangePriority ChPriority(ChangePriority::NORMAL); + PluginHandle *ph = (PluginHandle*)hPlugin; + ph->pPlugin->ClosePlugin(ph->hPlugin); + delete ph; +} + +HANDLE PluginManager::GetRealPluginHandle(HANDLE hPlugin) +{ + PluginHandle *ph = (PluginHandle*)hPlugin; + return ph->hPlugin; +} + +FARString PluginManager::GetPluginModuleName(HANDLE hPlugin) +{ + PluginHandle *ph = (PluginHandle*)hPlugin; + return ph->pPlugin->GetModuleName(); +} + + +int PluginManager::ProcessEditorInput(INPUT_RECORD *Rec) +{ + for (int i = 0; i < PluginsCount; i++) + { + Plugin *pPlugin = PluginsData[i]; + + if (pPlugin->HasProcessEditorInput() && pPlugin->ProcessEditorInput(Rec)) + return TRUE; + } + + return FALSE; +} + + +int PluginManager::ProcessEditorEvent(int Event,void *Param) +{ + int nResult = 0; + + if (CtrlObject->Plugins.CurEditor) + { + Plugin *pPlugin = nullptr; + + for (int i = 0; i < PluginsCount; i++) + { + pPlugin = PluginsData[i]; + + if (pPlugin->HasProcessEditorEvent()) + nResult = pPlugin->ProcessEditorEvent(Event, Param); + } + } + + return nResult; +} + + +int PluginManager::ProcessViewerEvent(int Event, void *Param) +{ + int nResult = 0; + + for (int i = 0; i < PluginsCount; i++) + { + Plugin *pPlugin = PluginsData[i]; + + if (pPlugin->HasProcessViewerEvent()) + nResult = pPlugin->ProcessViewerEvent(Event, Param); + } + + return nResult; +} + +int PluginManager::ProcessDialogEvent(int Event, void *Param) +{ + for (int i=0; i<PluginsCount; i++) + { + Plugin *pPlugin = PluginsData[i]; + + if (pPlugin->HasProcessDialogEvent() && pPlugin->ProcessDialogEvent(Event,Param)) + return TRUE; + } + + return FALSE; +} + +#if defined(PROCPLUGINMACROFUNC) +int PluginManager::ProcessMacroFunc(const wchar_t *Name, const FarMacroValue *Params, int nParams, FarMacroValue **Results, int *nResults) +{ + int nResult = 0; + + for (int i=0; i<PluginsCount; i++) + { + Plugin *pPlugin = PluginsData[i]; + + if (pPlugin->HasProcessMacroFunc()) + if ((nResult = pPlugin->ProcessMacroFunc(Name,Params,nParams,Results,nResults)) != 0) + break; + } + + return nResult; +} +#endif + +int PluginManager::GetFindData( + HANDLE hPlugin, + PluginPanelItem **pPanelData, + int *pItemsNumber, + int OpMode +) +{ + ChangePriority ChPriority(ChangePriority::NORMAL); + PluginHandle *ph = (PluginHandle *)hPlugin; + *pItemsNumber = 0; + return ph->pPlugin->GetFindData(ph->hPlugin, pPanelData, pItemsNumber, OpMode); +} + + +void PluginManager::FreeFindData( + HANDLE hPlugin, + PluginPanelItem *PanelItem, + int ItemsNumber +) +{ + PluginHandle *ph = (PluginHandle *)hPlugin; + ph->pPlugin->FreeFindData(ph->hPlugin, PanelItem, ItemsNumber); +} + + +int PluginManager::GetVirtualFindData( + HANDLE hPlugin, + PluginPanelItem **pPanelData, + int *pItemsNumber, + const wchar_t *Path +) +{ + ChangePriority ChPriority(ChangePriority::NORMAL); + PluginHandle *ph = (PluginHandle*)hPlugin; + *pItemsNumber=0; + return ph->pPlugin->GetVirtualFindData(ph->hPlugin, pPanelData, pItemsNumber, Path); +} + + +void PluginManager::FreeVirtualFindData( + HANDLE hPlugin, + PluginPanelItem *PanelItem, + int ItemsNumber +) +{ + PluginHandle *ph = (PluginHandle*)hPlugin; + return ph->pPlugin->FreeVirtualFindData(ph->hPlugin, PanelItem, ItemsNumber); +} + + +int PluginManager::SetDirectory( + HANDLE hPlugin, + const wchar_t *Dir, + int OpMode +) +{ + ChangePriority ChPriority(ChangePriority::NORMAL); + PluginHandle *ph = (PluginHandle*)hPlugin; + return ph->pPlugin->SetDirectory(ph->hPlugin, Dir, OpMode); +} + + +int PluginManager::GetFile( + HANDLE hPlugin, + PluginPanelItem *PanelItem, + const wchar_t *DestPath, + FARString &strResultName, + int OpMode +) +{ + ChangePriority ChPriority(ChangePriority::NORMAL); + PluginHandle *ph = (PluginHandle*)hPlugin; + SaveScreen *SaveScr=nullptr; + int Found=FALSE; + KeepUserScreen=FALSE; + + if (!(OpMode & OPM_FIND)) + SaveScr = new SaveScreen; //??? + + UndoGlobalSaveScrPtr UndSaveScr(SaveScr); + int GetCode = ph->pPlugin->GetFiles(ph->hPlugin, PanelItem, 1, 0, &DestPath, OpMode); + FARString strFindPath; + strFindPath = DestPath; + AddEndSlash(strFindPath); + strFindPath += L"*"; + FAR_FIND_DATA_EX fdata; + FindFile Find(strFindPath); + bool Done = true; + while(Find.Get(fdata)) + { + if(!(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + { + Done = false; + break; + } + } + + if (!Done) + { + strResultName = DestPath; + AddEndSlash(strResultName); + strResultName += fdata.strFileName; + + if (GetCode!=1) + { + apiSetFileAttributes(strResultName,FILE_ATTRIBUTE_NORMAL); + apiDeleteFile(strResultName); //BUGBUG + } + else + Found=TRUE; + } + + ReadUserBackgound(SaveScr); + delete SaveScr; + return Found; +} + + +int PluginManager::DeleteFiles( + HANDLE hPlugin, + PluginPanelItem *PanelItem, + int ItemsNumber, + int OpMode +) +{ + ChangePriority ChPriority(ChangePriority::NORMAL); + PluginHandle *ph = (PluginHandle*)hPlugin; + SaveScreen SaveScr; + KeepUserScreen=FALSE; + int Code = ph->pPlugin->DeleteFiles(ph->hPlugin, PanelItem, ItemsNumber, OpMode); + + if (Code) + ReadUserBackgound(&SaveScr); //??? + + return Code; +} + + +int PluginManager::MakeDirectory( + HANDLE hPlugin, + const wchar_t **Name, + int OpMode +) +{ + ChangePriority ChPriority(ChangePriority::NORMAL); + PluginHandle *ph = (PluginHandle*)hPlugin; + SaveScreen SaveScr; + KeepUserScreen=FALSE; + int Code = ph->pPlugin->MakeDirectory(ph->hPlugin, Name, OpMode); + + if (Code != -1) //???BUGBUG + ReadUserBackgound(&SaveScr); + + return Code; +} + + +int PluginManager::ProcessHostFile( + HANDLE hPlugin, + PluginPanelItem *PanelItem, + int ItemsNumber, + int OpMode +) +{ + PluginHandle *ph = (PluginHandle*)hPlugin; + ChangePriority ChPriority(ChangePriority::NORMAL); + SaveScreen SaveScr; + KeepUserScreen=FALSE; + int Code = ph->pPlugin->ProcessHostFile(ph->hPlugin, PanelItem, ItemsNumber, OpMode); + + if (Code) //BUGBUG + ReadUserBackgound(&SaveScr); + + return Code; +} + + +int PluginManager::GetFiles( + HANDLE hPlugin, + PluginPanelItem *PanelItem, + int ItemsNumber, + int Move, + const wchar_t **DestPath, + int OpMode +) +{ + ChangePriority ChPriority(ChangePriority::NORMAL); + PluginHandle *ph=(PluginHandle*)hPlugin; + return ph->pPlugin->GetFiles(ph->hPlugin, PanelItem, ItemsNumber, Move, DestPath, OpMode); +} + + +int PluginManager::PutFiles( + HANDLE hPlugin, + PluginPanelItem *PanelItem, + int ItemsNumber, + int Move, + int OpMode +) +{ + PluginHandle *ph = (PluginHandle*)hPlugin; + ChangePriority ChPriority(ChangePriority::NORMAL); + SaveScreen SaveScr; + KeepUserScreen=FALSE; + int Code = ph->pPlugin->PutFiles(ph->hPlugin, PanelItem, ItemsNumber, Move, OpMode); + + if (Code) //BUGBUG + ReadUserBackgound(&SaveScr); + + return Code; +} + +void PluginManager::GetOpenPluginInfo( + HANDLE hPlugin, + OpenPluginInfo *Info +) +{ + if (!Info) + return; + + memset(Info, 0, sizeof(*Info)); + PluginHandle *ph = (PluginHandle*)hPlugin; + ph->pPlugin->GetOpenPluginInfo(ph->hPlugin, Info); + + if (!Info->CurDir) //хмм... + Info->CurDir = L""; + + if ((Info->Flags & OPIF_REALNAMES) && (CtrlObject->Cp()->ActivePanel->GetPluginHandle() == hPlugin) && *Info->CurDir && !IsNetworkServerPath(Info->CurDir)) + apiSetCurrentDirectory(Info->CurDir, false); +} + + +int PluginManager::ProcessKey( + HANDLE hPlugin, + int Key, + unsigned int ControlState +) +{ + PluginHandle *ph = (PluginHandle*)hPlugin; + return ph->pPlugin->ProcessKey(ph->hPlugin, Key, ControlState); +} + + +int PluginManager::ProcessEvent( + HANDLE hPlugin, + int Event, + void *Param +) +{ + PluginHandle *ph = (PluginHandle*)hPlugin; + return ph->pPlugin->ProcessEvent(ph->hPlugin, Event, Param); +} + + +int PluginManager::Compare( + HANDLE hPlugin, + const PluginPanelItem *Item1, + const PluginPanelItem *Item2, + unsigned int Mode +) +{ + PluginHandle *ph = (PluginHandle*)hPlugin; + return ph->pPlugin->Compare(ph->hPlugin, Item1, Item2, Mode); +} + +void PluginManager::ConfigureCurrent(Plugin *pPlugin, int INum) +{ + if (pPlugin->Configure(INum)) + { + int PMode[2]; + PMode[0]=CtrlObject->Cp()->LeftPanel->GetMode(); + PMode[1]=CtrlObject->Cp()->RightPanel->GetMode(); + + for (size_t I=0; I < ARRAYSIZE(PMode); ++I) + { + if (PMode[I] == PLUGIN_PANEL) + { + Panel *pPanel=(I?CtrlObject->Cp()->RightPanel:CtrlObject->Cp()->LeftPanel); + pPanel->Update(UPDATE_KEEP_SELECTION); + pPanel->SetViewMode(pPanel->GetViewMode()); + pPanel->Redraw(); + } + } + pPlugin->SaveToCache(); + } +} + +struct PluginMenuItemData +{ + Plugin *pPlugin; + int nItem; +}; + +/* $ 29.05.2001 IS + ! При настройке "параметров внешних модулей" закрывать окно с их + списком только при нажатии на ESC +*/ + +bool PluginManager::CheckIfHotkeyPresent(const char *HotKeyType) +{ + for (int I=0; I<PluginsCount; I++) + { + Plugin *pPlugin = PluginsData[I]; + PluginInfo Info{}; + bool bCached = pPlugin->CheckWorkFlags(PIWF_CACHED) ? true : false; + if (!bCached && !pPlugin->GetPluginInfo(&Info)) + { + continue; + } + + for (int J = 0; ; ++J) + { + if (bCached) + { + KeyFileReadSection kfh(PluginsIni(), pPlugin->GetSettingsName()); + if (!kfh.HasKey(StrPrintf(FmtPluginConfigStringD, J))) + break; + } + else if (J >= Info.PluginConfigStringsNumber) + { + break; + } + + FARString strHotKey; + GetPluginHotKey(pPlugin, J, HotKeyType, strHotKey); + if (!strHotKey.IsEmpty()) + { + return true; + } + } + } + return false; +} + +void PluginManager::Configure(int StartPos) +{ + // Полиция 4 - Параметры внешних модулей + if (Opt.Policies.DisabledOptions&FFPOL_MAINMENUPLUGINS) + return; + + { + VMenu PluginList(MSG(MPluginConfigTitle),nullptr,0,ScrY-4); + PluginList.SetFlags(VMENU_WRAPMODE); + PluginList.SetHelp(L"PluginsConfig"); + + for (;;) + { + BOOL NeedUpdateItems=TRUE; + int MenuItemNumber=0; + bool HotKeysPresent = CheckIfHotkeyPresent("ConfHotkey"); + + if (NeedUpdateItems) + { + PluginList.ClearDone(); + PluginList.DeleteItems(); + PluginList.SetPosition(-1,-1,0,0); + MenuItemNumber=0; + LoadIfCacheAbsent(); + FARString strHotKey, strValue, strName; + PluginInfo Info{}; + + for (int I=0; I<PluginsCount; I++) + { + Plugin *pPlugin = PluginsData[I]; + bool bCached = pPlugin->CheckWorkFlags(PIWF_CACHED)?true:false; + + if (!bCached && !pPlugin->GetPluginInfo(&Info)) + { + continue; + } + + for (int J=0; ; J++) + { + if (bCached) + { + KeyFileReadSection kfh(PluginsIni(), pPlugin->GetSettingsName()); + const std::string &key = StrPrintf(FmtPluginConfigStringD, J); + if (!kfh.HasKey(key)) + break; + + strName = kfh.GetString(key, ""); + } + else + { + if (J >= Info.PluginConfigStringsNumber) + break; + + strName = Info.PluginConfigStrings[J]; + } + + GetPluginHotKey(pPlugin,J,"ConfHotkey",strHotKey); + MenuItemEx ListItem; + ListItem.Clear(); + + if (pPlugin->IsOemPlugin()) + ListItem.Flags=LIF_CHECKED|L'A'; + + if (!HotKeysPresent) + ListItem.strName = strName; + else if (!strHotKey.IsEmpty()) + ListItem.strName.Format(L"&%c%ls %ls",strHotKey.At(0),(strHotKey.At(0)==L'&'?L"&":L""), strName.CPtr()); + else + ListItem.strName.Format(L" %ls", strName.CPtr()); + + //ListItem.SetSelect(MenuItemNumber++ == StartPos); + MenuItemNumber++; + PluginMenuItemData item; + item.pPlugin = pPlugin; + item.nItem = J; + PluginList.SetUserData(&item, sizeof(PluginMenuItemData),PluginList.AddItem(&ListItem)); + } + } + + PluginList.AssignHighlights(FALSE); + PluginList.SetBottomTitle(MSG(MPluginHotKeyBottom)); + PluginList.ClearDone(); + PluginList.SortItems(0,HotKeysPresent?3:0); + PluginList.SetSelectPos(StartPos,1); + NeedUpdateItems=FALSE; + } + + FARString strPluginModuleName; + PluginList.Show(); + + while (!PluginList.Done()) + { + DWORD Key=PluginList.ReadInput(); + int SelPos=PluginList.GetSelectPos(); + PluginMenuItemData *item = (PluginMenuItemData*)PluginList.GetUserData(nullptr,0,SelPos); + + switch (Key) + { + case KEY_SHIFTF1: + strPluginModuleName = item->pPlugin->GetModuleName(); + + if (!FarShowHelp(strPluginModuleName,L"Config",FHELP_SELFHELP|FHELP_NOSHOWERROR) && + !FarShowHelp(strPluginModuleName,L"Configure",FHELP_SELFHELP|FHELP_NOSHOWERROR)) + { + FarShowHelp(strPluginModuleName,nullptr,FHELP_SELFHELP|FHELP_NOSHOWERROR); + } + + break; + case KEY_F4: + + if (PluginList.GetItemCount() > 0 && SelPos<MenuItemNumber) + { + FARString strName00; + int nOffset = HotKeysPresent?3:0; + strName00 = PluginList.GetItemPtr()->strName.CPtr()+nOffset; + RemoveExternalSpaces(strName00); + + if (SetHotKeyDialog(strName00, + GetHotKeySettingName(item->pPlugin, item->nItem, "ConfHotkey"))) + { + PluginList.Hide(); + NeedUpdateItems=TRUE; + StartPos=SelPos; + PluginList.SetExitCode(SelPos); + PluginList.Show(); + break; + } + } + + break; + default: + PluginList.ProcessInput(); + break; + } + } + + if (!NeedUpdateItems) + { + StartPos=PluginList.Modal::GetExitCode(); + PluginList.Hide(); + + if (StartPos<0) + break; + + PluginMenuItemData *item = (PluginMenuItemData*)PluginList.GetUserData(nullptr,0,StartPos); + ConfigureCurrent(item->pPlugin, item->nItem); + } + } + } +} + +int PluginManager::CommandsMenu(int ModalType,int StartPos,const wchar_t *HistoryName) +{ + if(ModalType == MODALTYPE_DIALOG) + { + if(reinterpret_cast<Dialog*>(FrameManager->GetCurrentFrame())->CheckDialogMode(DMODE_NOPLUGINS)) + { + return 0; + } + } + + int MenuItemNumber=0; + ChangeMacroMode CMM(MACRO_MENU); + int Editor = ModalType==MODALTYPE_EDITOR, + Viewer = ModalType==MODALTYPE_VIEWER, + Dialog = ModalType==MODALTYPE_DIALOG; + PluginMenuItemData item; + { + VMenu PluginList(MSG(MPluginCommandsMenuTitle),nullptr,0,ScrY-4); + PluginList.SetFlags(VMENU_WRAPMODE); + PluginList.SetHelp(L"PluginCommands"); + BOOL NeedUpdateItems=TRUE; + BOOL Done=FALSE; + + while (!Done) + { + bool HotKeysPresent = CheckIfHotkeyPresent("Hotkey"); + + if (NeedUpdateItems) + { + PluginList.ClearDone(); + PluginList.DeleteItems(); + PluginList.SetPosition(-1,-1,0,0); + LoadIfCacheAbsent(); + FARString strHotKey, strValue, strName; + PluginInfo Info{}; + KeyFileReadHelper kfh(PluginsIni()); + + for (int I=0; I<PluginsCount; I++) + { + Plugin *pPlugin = PluginsData[I]; + bool bCached = pPlugin->CheckWorkFlags(PIWF_CACHED)?true:false; + int IFlags; + + if (bCached) + { + IFlags = kfh.GetUInt(pPlugin->GetSettingsName(), "Flags",0); + } + else + { + if (!pPlugin->GetPluginInfo(&Info)) + continue; + + IFlags = Info.Flags; + } + + if ((Editor && !(IFlags & PF_EDITOR)) || + (Viewer && !(IFlags & PF_VIEWER)) || + (Dialog && !(IFlags & PF_DIALOG)) || + (!Editor && !Viewer && !Dialog && (IFlags & PF_DISABLEPANELS))) + continue; + + for (int J=0; ; J++) + { + if (bCached) + { + const std::string &key = StrPrintf(FmtPluginMenuStringD, J); + if (!kfh.HasKey(pPlugin->GetSettingsName(), key)) + break; + strName = kfh.GetString(pPlugin->GetSettingsName(), key, ""); + } + else + { + if (J >= Info.PluginMenuStringsNumber) + break; + + strName = Info.PluginMenuStrings[J]; + } + + GetPluginHotKey(pPlugin,J,"Hotkey",strHotKey); + MenuItemEx ListItem; + ListItem.Clear(); + + if (pPlugin->IsOemPlugin()) + ListItem.Flags=LIF_CHECKED|L'A'; + + if (!HotKeysPresent) + ListItem.strName = strName; + else if (!strHotKey.IsEmpty()) + ListItem.strName.Format(L"&%c%ls %ls",strHotKey.At(0),(strHotKey.At(0)==L'&'?L"&":L""), strName.CPtr()); + else + ListItem.strName.Format(L" %ls", strName.CPtr()); + + //ListItem.SetSelect(MenuItemNumber++ == StartPos); + MenuItemNumber++; + PluginMenuItemData item; + item.pPlugin = pPlugin; + item.nItem = J; + PluginList.SetUserData(&item, sizeof(PluginMenuItemData),PluginList.AddItem(&ListItem)); + } + } + + PluginList.AssignHighlights(FALSE); + PluginList.SetBottomTitle(MSG(MPluginHotKeyBottom)); + PluginList.SortItems(0,HotKeysPresent?3:0); + PluginList.SetSelectPos(StartPos,1); + NeedUpdateItems=FALSE; + } + + PluginList.Show(); + + while (!PluginList.Done()) + { + DWORD Key=PluginList.ReadInput(); + int SelPos=PluginList.GetSelectPos(); + PluginMenuItemData *item = (PluginMenuItemData*)PluginList.GetUserData(nullptr,0,SelPos); + + switch (Key) + { + case KEY_SHIFTF1: + // Вызываем нужный топик, который передали в CommandsMenu() + FarShowHelp(item->pPlugin->GetModuleName(),HistoryName,FHELP_SELFHELP|FHELP_NOSHOWERROR|FHELP_USECONTENTS); + break; + case KEY_ALTF11: + //todo WriteEvent(FLOG_PLUGINSINFO); + break; + case KEY_F4: + + if (PluginList.GetItemCount() > 0 && SelPos<MenuItemNumber) + { + FARString strName00; + int nOffset = HotKeysPresent?3:0; + strName00 = PluginList.GetItemPtr()->strName.CPtr()+nOffset; + RemoveExternalSpaces(strName00); + + if (SetHotKeyDialog(strName00, + GetHotKeySettingName(item->pPlugin, item->nItem, "Hotkey"))) + { + PluginList.Hide(); + NeedUpdateItems=TRUE; + StartPos=SelPos; + PluginList.SetExitCode(SelPos); + PluginList.Show(); + } + } + + break; + case KEY_ALTSHIFTF9: + { + PluginList.Hide(); + NeedUpdateItems=TRUE; + StartPos=SelPos; + PluginList.SetExitCode(SelPos); + Configure(); + PluginList.Show(); + break; + } + case KEY_SHIFTF9: + { + if (PluginList.GetItemCount() > 0 && SelPos<MenuItemNumber) + { + NeedUpdateItems=TRUE; + StartPos=SelPos; + + if (item->pPlugin->HasConfigure()) + ConfigureCurrent(item->pPlugin, item->nItem); + + PluginList.SetExitCode(SelPos); + PluginList.Show(); + } + + break; + } + default: + PluginList.ProcessInput(); + break; + } + } + + if (!NeedUpdateItems && PluginList.Done()) + break; + } + + int ExitCode=PluginList.Modal::GetExitCode(); + PluginList.Hide(); + + if (ExitCode<0) + { + return FALSE; + } + + ScrBuf.Flush(); + item = *(PluginMenuItemData*)PluginList.GetUserData(nullptr,0,ExitCode); + } + + Panel *ActivePanel=CtrlObject->Cp()->ActivePanel; + int OpenCode=OPEN_PLUGINSMENU; + INT_PTR Item=item.nItem; + OpenDlgPluginData pd; + + if (Editor) + { + OpenCode=OPEN_EDITOR; + } + else if (Viewer) + { + OpenCode=OPEN_VIEWER; + } + else if (Dialog) + { + OpenCode=OPEN_DIALOG; + pd.hDlg=(HANDLE)FrameManager->GetCurrentFrame(); + pd.ItemNumber=item.nItem; + Item=(INT_PTR)&pd; + } + + HANDLE hPlugin=OpenPlugin(item.pPlugin,OpenCode,Item); + + if (hPlugin!=INVALID_HANDLE_VALUE && !Editor && !Viewer && !Dialog) + { + if (ActivePanel->ProcessPluginEvent(FE_CLOSE,nullptr)) + { + ClosePlugin(hPlugin); + return FALSE; + } + + Panel *NewPanel=CtrlObject->Cp()->ChangePanel(ActivePanel,FILE_PANEL,TRUE,TRUE); + NewPanel->SetPluginMode(hPlugin,L"",true); + NewPanel->Update(0); + NewPanel->Show(); + } + + // restore title for old plugins only. + if (item.pPlugin->IsOemPlugin() && Editor && CurEditor) + { + CurEditor->SetPluginTitle(nullptr); + } + + return TRUE; +} + +std::string PluginManager::GetHotKeySettingName(Plugin *pPlugin, int ItemNumber, const char *HotKeyType) +{ + std::string out = pPlugin->GetSettingsName(); + out+= StrPrintf(":%s#%d", HotKeyType, ItemNumber); + return out; +} + +void PluginManager::GetPluginHotKey(Plugin *pPlugin, int ItemNumber, const char *HotKeyType, FARString &strHotKey) +{ + strHotKey = KeyFileReadSection(PluginsIni(), SettingsSection).GetString( + GetHotKeySettingName(pPlugin, ItemNumber, HotKeyType)); +} + +bool PluginManager::SetHotKeyDialog( + const wchar_t *DlgPluginTitle, // имя плагина + const std::string &SettingName // ключ, откуда берем значение в state.ini/Settings +) +{ + KeyFileHelper kfh(PluginsIni()); + const auto &Setting = kfh.GetString(SettingsSection, SettingName); + WCHAR Letter[2] = {Setting.empty() ? 0 : Setting[0], 0}; + if (!HotkeyLetterDialog(MSG(MPluginHotKeyTitle), DlgPluginTitle, Letter[0])) + return false; + + if (Letter[0]) + kfh.SetString(SettingsSection, SettingName, Letter); + else + kfh.RemoveKey(SettingsSection, SettingName); + return true; +} + +bool PluginManager::GetDiskMenuItem( + Plugin *pPlugin, + int PluginItem, + bool &ItemPresent, + wchar_t& PluginHotkey, + FARString &strPluginText +) +{ + LoadIfCacheAbsent(); + + FARString strHotKey; + GetPluginHotKey(pPlugin,PluginItem,"DriveMenuHotkey",strHotKey); + PluginHotkey = strHotKey.At(0); + + if (pPlugin->CheckWorkFlags(PIWF_CACHED)) + { + KeyFileReadSection kfh(PluginsIni(), pPlugin->GetSettingsName()); + strPluginText = kfh.GetString( + StrPrintf(FmtDiskMenuStringD, PluginItem), ""); + ItemPresent = !strPluginText.IsEmpty(); + return true; + } + + PluginInfo Info; + + if (!pPlugin->GetPluginInfo(&Info) || Info.DiskMenuStringsNumber <= PluginItem) + { + ItemPresent=false; + } + else + { + strPluginText = Info.DiskMenuStrings[PluginItem]; + ItemPresent=true; + } + + return true; +} + +int PluginManager::UseFarCommand(HANDLE hPlugin,int CommandType) +{ + OpenPluginInfo Info; + GetOpenPluginInfo(hPlugin,&Info); + + if (!(Info.Flags & OPIF_REALNAMES)) + return FALSE; + + PluginHandle *ph = (PluginHandle*)hPlugin; + + switch (CommandType) + { + case PLUGIN_FARGETFILE: + case PLUGIN_FARGETFILES: + return(!ph->pPlugin->HasGetFiles() || (Info.Flags & OPIF_EXTERNALGET)); + case PLUGIN_FARPUTFILES: + return(!ph->pPlugin->HasPutFiles() || (Info.Flags & OPIF_EXTERNALPUT)); + case PLUGIN_FARDELETEFILES: + return(!ph->pPlugin->HasDeleteFiles() || (Info.Flags & OPIF_EXTERNALDELETE)); + case PLUGIN_FARMAKEDIRECTORY: + return(!ph->pPlugin->HasMakeDirectory() || (Info.Flags & OPIF_EXTERNALMKDIR)); + } + + return TRUE; +} + + +void PluginManager::ReloadLanguage() +{ + Plugin *PData; + + for (int I=0; I<PluginsCount; I++) + { + PData = PluginsData[I]; + PData->CloseLang(); + } + + DiscardCache(); +} + + +void PluginManager::DiscardCache() +{ + for (int I=0; I<PluginsCount; I++) + { + Plugin *pPlugin = PluginsData[I]; + pPlugin->Load(); + } + + KeyFileHelper kfh(PluginsIni()); + const std::vector<std::string> §ions = kfh.EnumSections(); + for (const auto &s : sections) + { + if (s != SettingsSection) + kfh.RemoveSection(s); + } +} + + +void PluginManager::LoadIfCacheAbsent() +{ + struct stat st; + if (stat(PluginsIni(), &st) == -1) + { + for (int I=0; I<PluginsCount; I++) + { + Plugin *pPlugin = PluginsData[I]; + pPlugin->Load(); + } + } +} + +//template parameters must have external linkage +struct PluginData +{ + Plugin *pPlugin; + DWORD PluginFlags; +}; + +int PluginManager::ProcessCommandLine(const wchar_t *CommandParam,Panel *Target) +{ + size_t PrefixLength=0; + FARString strCommand=CommandParam; + UnquoteExternal(strCommand); + RemoveLeadingSpaces(strCommand); + + for (;;) + { + wchar_t Ch=strCommand.At(PrefixLength); + + if (!Ch || IsSpace(Ch) || Ch==L'/' || PrefixLength>64) + return FALSE; + + if (Ch==L':' && PrefixLength>0) + break; + + PrefixLength++; + } + + LoadIfCacheAbsent(); + FARString strPrefix(strCommand,PrefixLength); + FARString strPluginPrefix; + TPointerArray<PluginData> items; + + for (int I=0; I<PluginsCount; I++) + { + int PluginFlags=0; + + if (PluginsData[I]->CheckWorkFlags(PIWF_CACHED)) + { + KeyFileReadSection kfh(PluginsIni(), PluginsData[I]->GetSettingsName()); + strPluginPrefix = kfh.GetString("CommandPrefix", ""); + PluginFlags = kfh.GetUInt("Flags", 0); + } + else + { + PluginInfo Info; + + if (PluginsData[I]->GetPluginInfo(&Info)) + { + strPluginPrefix = Info.CommandPrefix; + PluginFlags = Info.Flags; + } + else + continue; + } + + if (strPluginPrefix.IsEmpty()) + continue; + + const wchar_t *PrStart = strPluginPrefix; + PrefixLength=strPrefix.GetLength(); + + for (;;) + { + const wchar_t *PrEnd = wcschr(PrStart, L':'); + size_t Len=PrEnd ? (PrEnd-PrStart):StrLength(PrStart); + + if (Len<PrefixLength)Len=PrefixLength; + + if (!StrCmpNI(strPrefix, PrStart, (int)Len)) + { + if (PluginsData[I]->Load() && PluginsData[I]->HasOpenPlugin()) + { + PluginData *pD=items.addItem(); + pD->pPlugin=PluginsData[I]; + pD->PluginFlags=PluginFlags; + break; + } + } + + if (!PrEnd) + break; + + PrStart = ++PrEnd; + } + + if (items.getCount() && !Opt.PluginConfirm.Prefix) + break; + } + + if (!items.getCount()) + return FALSE; + + Panel *ActivePanel=CtrlObject->Cp()->ActivePanel; + Panel *CurPanel=(Target)?Target:ActivePanel; + + if (CurPanel->ProcessPluginEvent(FE_CLOSE,nullptr)) + return FALSE; + + PluginData* PData=nullptr; + + if (items.getCount()>1) + { + VMenu menu(MSG(MPluginConfirmationTitle), nullptr, 0, ScrY-4); + menu.SetPosition(-1, -1, 0, 0); + menu.SetHelp(L"ChoosePluginMenu"); + menu.SetFlags(VMENU_SHOWAMPERSAND|VMENU_WRAPMODE); + MenuItemEx mitem; + + for (size_t i=0; i<items.getCount(); i++) + { + mitem.Clear(); + mitem.strName=PointToName(items.getItem(i)->pPlugin->GetModuleName()); + menu.AddItem(&mitem); + } + + menu.Show(); + + while (!menu.Done()) + { + menu.ReadInput(); + menu.ProcessInput(); + } + + int ExitCode=menu.GetExitCode(); + + if (ExitCode>=0) + { + PData=items.getItem(ExitCode); + } + } + else + { + PData=items.getItem(0); + } + + if (PData) + { + CtrlObject->CmdLine->SetString(L""); + FARString strPluginCommand=strCommand.CPtr()+(PData->PluginFlags & PF_FULLCMDLINE ? 0:PrefixLength+1); + RemoveTrailingSpaces(strPluginCommand); + HANDLE hPlugin=OpenPlugin(PData->pPlugin,OPEN_COMMANDLINE,(INT_PTR)strPluginCommand.CPtr()); //BUGBUG + + if (hPlugin!=INVALID_HANDLE_VALUE) + { + Panel *NewPanel=CtrlObject->Cp()->ChangePanel(CurPanel,FILE_PANEL,TRUE,TRUE); + NewPanel->SetPluginMode(hPlugin,L"",!Target || Target == ActivePanel); + NewPanel->Update(0); + NewPanel->Show(); + } + } + + return TRUE; +} + + +void PluginManager::ReadUserBackgound(SaveScreen *SaveScr) +{ + FilePanels *FPanel=CtrlObject->Cp(); + FPanel->LeftPanel->ProcessingPluginCommand++; + FPanel->RightPanel->ProcessingPluginCommand++; + + if (KeepUserScreen) + { + if (SaveScr) + SaveScr->Discard(); + + RedrawDesktop Redraw; + } + + FPanel->LeftPanel->ProcessingPluginCommand--; + FPanel->RightPanel->ProcessingPluginCommand--; +} + + +/* $ 27.09.2000 SVS + Функция CallPlugin - найти плагин по ID и запустить + в зачаточном состоянии! +*/ +int PluginManager::CallPlugin(DWORD SysID,int OpenFrom, void *Data,int *Ret) +{ + Plugin *pPlugin = FindPlugin(SysID); + + if (pPlugin) + { + if (pPlugin->HasOpenPlugin()) + { + HANDLE hNewPlugin=OpenPlugin(pPlugin,OpenFrom,(INT_PTR)Data); + bool process=false; + + if (OpenFrom & OPEN_FROMMACRO) + { + // <????> + ; + // </????> + } + else + { + process=OpenFrom == OPEN_PLUGINSMENU || OpenFrom == OPEN_FILEPANEL; + } + + if (hNewPlugin!=INVALID_HANDLE_VALUE && process) + { + int CurFocus=CtrlObject->Cp()->ActivePanel->GetFocus(); + Panel *NewPanel=CtrlObject->Cp()->ChangePanel(CtrlObject->Cp()->ActivePanel,FILE_PANEL,TRUE,TRUE); + NewPanel->SetPluginMode(hNewPlugin,L"",CurFocus || !CtrlObject->Cp()->GetAnotherPanel(NewPanel)->IsVisible()); + + if (Data && *(const wchar_t *)Data) + SetDirectory(hNewPlugin,(const wchar_t *)Data,0); + + /* $ 04.04.2001 SVS + Код закомментирован! Попытка исключить ненужные вызовы в CallPlugin() + Если что-то не так - раскомментировать!!! + */ + //NewPanel->Update(0); + //NewPanel->Show(); + } + + if (Ret) + { + PluginHandle *handle=(PluginHandle *)hNewPlugin; + *Ret=hNewPlugin == INVALID_HANDLE_VALUE || handle->hPlugin?1:0; + } + + return TRUE; + } + } + + return FALSE; +} + +Plugin *PluginManager::FindPlugin(DWORD SysID) +{ + if (SysID && SysID != 0xFFFFFFFFUl) // не допускается 0 и -1 + { + Plugin *PData; + + for (int I=0; I<PluginsCount; I++) + { + PData = PluginsData[I]; + + if (PData->GetSysID() == SysID) + return PData; + } + } + + return nullptr; +} + +HANDLE PluginManager::OpenPlugin(Plugin *pPlugin,int OpenFrom,INT_PTR Item) +{ + HANDLE hPlugin = pPlugin->OpenPlugin(OpenFrom, Item); + + if (hPlugin != INVALID_HANDLE_VALUE) + { + PluginHandle *handle = new PluginHandle; + handle->hPlugin = hPlugin; + handle->pPlugin = pPlugin; + return (HANDLE)handle; + } + + return hPlugin; +} + +void PluginManager::GetCustomData(FileListItem *ListItem) +{ + FARString FilePath(NTPath(ListItem->strName).Get()); + + for (int i=0; i<PluginsCount; i++) + { + Plugin *pPlugin = PluginsData[i]; + + wchar_t *CustomData = nullptr; + + if (pPlugin->HasGetCustomData() && pPlugin->GetCustomData(FilePath.CPtr(), &CustomData)) + { + if (!ListItem->strCustomData.IsEmpty()) + ListItem->strCustomData += L" "; + ListItem->strCustomData += CustomData; + + if (pPlugin->HasFreeCustomData()) + pPlugin->FreeCustomData(CustomData); + } + } +} + +bool PluginManager::MayExitFar() +{ + bool out = true; + for (int i=0; i<PluginsCount; i++) + { + Plugin *pPlugin = PluginsData[i]; + + if (pPlugin->HasMayExitFAR() && !pPlugin->MayExitFAR()) + { + out = false; + } + } + + return out; +} + +static void OnBackgroundTasksChangedSynched() +{ + if (FrameManager) + FrameManager->RefreshFrame(); +} + +void PluginManager::BackroundTaskStarted(const wchar_t *Info) +{ + { + std::lock_guard<std::mutex> lock(BgTasks); + auto ir = BgTasks.emplace(Info, 0); + ir.first->second++; + fprintf(stderr, "PluginManager::BackroundTaskStarted('%ls') - count=%d\n", Info, ir.first->second); + } + + InterThreadCallAsync(std::bind(OnBackgroundTasksChangedSynched)); +} + +void PluginManager::BackroundTaskFinished(const wchar_t *Info) +{ + { + std::lock_guard<std::mutex> lock(BgTasks); + auto it = BgTasks.find(Info); + if (it == BgTasks.end()) + { + fprintf(stderr, "PluginManager::BackroundTaskFinished('%ls') - no such task!\n", Info); + return; + } + + it->second--; + fprintf(stderr, "PluginManager::BackroundTaskFinished('%ls') - count=%d\n", Info, it->second); + if (it->second == 0) + BgTasks.erase(it); + } + + InterThreadCallAsync(std::bind(OnBackgroundTasksChangedSynched)); +} + +bool PluginManager::HasBackgroundTasks() +{ + std::lock_guard<std::mutex> lock(BgTasks); + return !BgTasks.empty(); +} + +std::map<std::wstring, unsigned int> PluginManager::BackgroundTasks() +{ + std::lock_guard<std::mutex> lock(BgTasks); + return BgTasks; +} + +//////////////////////// diff --git a/far2l/src/plug/plugins.hpp b/far2l/src/plug/plugins.hpp new file mode 100644 index 00000000..55aba7ba --- /dev/null +++ b/far2l/src/plug/plugins.hpp @@ -0,0 +1,288 @@ +#pragma once + +/* +plugins.hpp + +Работа с плагинами (низкий уровень, кое-что повыше в flplugin.cpp) +*/ +/* +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 "language.hpp" +#include "bitflags.hpp" +#include "fpsdk/plugin.hpp" +#include "plclass.hpp" +#include "PluginA.hpp" +#include "PluginW.hpp" +#include <string> +#include <map> +#include <mutex> + +extern const char *FmtDiskMenuStringD; +extern const char *FmtPluginMenuStringD; +extern const char *FmtPluginConfigStringD; + + +class SaveScreen; +class FileEditor; +class Viewer; +class Frame; +class Panel; +struct FileListItem; + +enum +{ + SYSID_PRINTMANAGER =0x6E614D50, + SYSID_NETWORK =0x5774654E, +}; + +enum +{ + PLUGIN_FARGETFILE, + PLUGIN_FARGETFILES, + PLUGIN_FARPUTFILES, + PLUGIN_FARDELETEFILES, + PLUGIN_FARMAKEDIRECTORY, + PLUGIN_FAROTHER +}; + +// флаги для поля Plugin.WorkFlags +enum PLUGINITEMWORKFLAGS +{ + PIWF_CACHED = 0x00000001, // кешируется + PIWF_PRELOADED = 0x00000002, // + PIWF_DONTLOADAGAIN = 0x00000004, // не загружать плагин снова, ставится в + // результате проверки требуемой версии фара +}; + +// флаги для поля Plugin.FuncFlags - активности функций +enum PLUGINITEMCALLFUNCFLAGS +{ + PICFF_LOADED = 0x00000001, // DLL загружен ;-) + PICFF_SETSTARTUPINFO = 0x00000002, // + PICFF_OPENPLUGIN = 0x00000004, // + PICFF_OPENFILEPLUGIN = 0x00000008, // + PICFF_CLOSEPLUGIN = 0x00000010, // + PICFF_GETPLUGININFO = 0x00000020, // + PICFF_GETOPENPLUGININFO = 0x00000040, // + PICFF_GETFINDDATA = 0x00000080, // + PICFF_FREEFINDDATA = 0x00000100, // + PICFF_GETVIRTUALFINDDATA = 0x00000200, // + PICFF_FREEVIRTUALFINDDATA = 0x00000400, // + PICFF_SETDIRECTORY = 0x00000800, // + PICFF_GETFILES = 0x00001000, // + PICFF_PUTFILES = 0x00002000, // + PICFF_DELETEFILES = 0x00004000, // + PICFF_MAKEDIRECTORY = 0x00008000, // + PICFF_PROCESSHOSTFILE = 0x00010000, // + PICFF_SETFINDLIST = 0x00020000, // + PICFF_CONFIGURE = 0x00040000, // + PICFF_EXITFAR = 0x00080000, // + PICFF_PROCESSKEY = 0x00100000, // + PICFF_PROCESSEVENT = 0x00200000, // + PICFF_PROCESSEDITOREVENT = 0x00400000, // + PICFF_COMPARE = 0x00800000, // + PICFF_PROCESSEDITORINPUT = 0x01000000, // + PICFF_MINFARVERSION = 0x02000000, // + PICFF_PROCESSVIEWEREVENT = 0x04000000, // + PICFF_PROCESSDIALOGEVENT = 0x08000000, // + PICFF_PROCESSSYNCHROEVENT = 0x10000000, // +#if defined(PROCPLUGINMACROFUNC) + PICFF_PROCESSMACROFUNC = 0x20000000, // +#endif + // PICFF_PANELPLUGIN - первая попытка определиться с понятием "это панель" + PICFF_PANELPLUGIN = PICFF_OPENFILEPLUGIN| + PICFF_GETFINDDATA| + PICFF_FREEFINDDATA| + PICFF_GETVIRTUALFINDDATA| + PICFF_FREEVIRTUALFINDDATA| + PICFF_SETDIRECTORY| + PICFF_GETFILES| + PICFF_PUTFILES| + PICFF_DELETEFILES| + PICFF_MAKEDIRECTORY| + PICFF_PROCESSHOSTFILE| + PICFF_SETFINDLIST| + PICFF_PROCESSKEY| + PICFF_PROCESSEVENT| + PICFF_COMPARE| + PICFF_GETOPENPLUGININFO, +}; + +// флаги для поля PluginManager.Flags +enum PLUGINSETFLAGS +{ + PSIF_ENTERTOOPENPLUGIN = 0x00000001, // ввалились в плагин OpenPlugin + PSIF_DIALOG = 0x00000002, // была бадяга с диалогом + PSIF_PLUGINSLOADDED = 0x80000000, // плагины загружены +}; + +enum OPENFILEPLUGINTYPE +{ + OFP_NORMAL, + OFP_ALTERNATIVE, + OFP_SEARCH, + OFP_SHORTCUT, + OFP_CREATE, + OFP_EXTRACT, + OFP_COMMANDS, +}; + +struct PluginHandle +{ + HANDLE hPlugin; + class Plugin *pPlugin; +}; + +class PluginManager +{ + private: + + Plugin **PluginsData; + int PluginsCount; + int OemPluginsCount; + struct BackgroundTasks : std::map<std::wstring, unsigned int>, std::mutex {} BgTasks; + + public: + + BitFlags Flags; // флаги манагера плагинов + + Plugin *CurPluginItem; + + FileEditor *CurEditor; + Viewer *CurViewer; // 27.09.2000 SVS: Указатель на текущий Viewer + + private: + + void LoadIfCacheAbsent(); + void ReadUserBackgound(SaveScreen *SaveScr); + + void GetPluginHotKey(Plugin *pPlugin, int ItemNumber, const char *HotKeyType, FARString &strHotKey); + + bool TestPluginInfo(Plugin *Item,PluginInfo *Info); + bool TestOpenPluginInfo(Plugin *Item,OpenPluginInfo *Info); + bool CheckIfHotkeyPresent(const char *HotKeyType); + + bool LoadPlugin(const FARString &strModuleName, bool LoadUncached); + + bool AddPlugin(Plugin *pPlugin); + bool RemovePlugin(Plugin *pPlugin); + + void LoadPluginsFromCache(); + + void SetFlags(DWORD NewFlags) { Flags.Set(NewFlags); } + void SkipFlags(DWORD NewFlags) { Flags.Clear(NewFlags); } + + public: + + PluginManager(); + ~PluginManager(); + + public: + + bool CacheForget(const wchar_t *lpwszModuleName); + bool LoadPluginExternal(const wchar_t *lpwszModuleName, bool LoadToMem); + + int UnloadPlugin(Plugin *pPlugin, DWORD dwException, bool bRemove = false); + int UnloadPluginExternal(const wchar_t *lpwszModuleName); + + void LoadPlugins(); + + Plugin *GetPlugin(const wchar_t *lpwszModuleName); + Plugin *GetPlugin(int PluginNumber); + + int GetPluginsCount() { return PluginsCount; } + int GetOemPluginsCount() { return OemPluginsCount; } + + BOOL IsPluginsLoaded() { return Flags.Check(PSIF_PLUGINSLOADDED); } + + BOOL CheckFlags(DWORD NewFlags) { return Flags.Check(NewFlags); } + + void Configure(int StartPos=0); + void ConfigureCurrent(Plugin *pPlugin,int INum); + int CommandsMenu(int ModalType,int StartPos,const wchar_t *HistoryName=nullptr); + bool GetDiskMenuItem(Plugin *pPlugin,int PluginItem,bool &ItemPresent, wchar_t& PluginHotkey, FARString &strPluginText); + + int UseFarCommand(HANDLE hPlugin,int CommandType); + void ReloadLanguage(); + void DiscardCache(); + int ProcessCommandLine(const wchar_t *Command,Panel *Target=nullptr); + + bool SetHotKeyDialog(const wchar_t *DlgPluginTitle, const std::string &SettingName); + std::string GetHotKeySettingName(Plugin *pPlugin, int ItemNumber, const char *HotKeyType); + + // $ .09.2000 SVS - Функция CallPlugin - найти плагин по ID и запустить OpenFrom = OPEN_* + int CallPlugin(DWORD SysID,int OpenFrom, void *Data, int *Ret=nullptr); + Plugin *FindPlugin(DWORD SysID); + +//api functions + + public: + + Plugin *Analyse(const AnalyseData *pData); + + HANDLE OpenPlugin(Plugin *pPlugin,int OpenFrom,INT_PTR Item); + HANDLE OpenFilePlugin(const wchar_t *Name, int OpMode, OPENFILEPLUGINTYPE Type, Plugin *pDesiredPlugin = nullptr); + HANDLE OpenFindListPlugin(const PluginPanelItem *PanelItem,int ItemsNumber); + HANDLE GetRealPluginHandle(HANDLE hPlugin); + FARString GetPluginModuleName(HANDLE hPlugin); + void ClosePlugin(HANDLE hPlugin); + void GetOpenPluginInfo(HANDLE hPlugin, OpenPluginInfo *Info); + int GetFindData(HANDLE hPlugin,PluginPanelItem **pPanelItem,int *pItemsNumber,int Silent); + void FreeFindData(HANDLE hPlugin,PluginPanelItem *PanelItem,int ItemsNumber); + int GetVirtualFindData(HANDLE hPlugin,PluginPanelItem **pPanelItem,int *pItemsNumber,const wchar_t *Path); + void FreeVirtualFindData(HANDLE hPlugin,PluginPanelItem *PanelItem,int ItemsNumber); + int SetDirectory(HANDLE hPlugin,const wchar_t *Dir,int OpMode); + int GetFile(HANDLE hPlugin,PluginPanelItem *PanelItem,const wchar_t *DestPath,FARString &strResultName,int OpMode); + int GetFiles(HANDLE hPlugin,PluginPanelItem *PanelItem,int ItemsNumber,int Move,const wchar_t **DestPath,int OpMode); + int PutFiles(HANDLE hPlugin,PluginPanelItem *PanelItem,int ItemsNumber,int Move,int OpMode); + int DeleteFiles(HANDLE hPlugin,PluginPanelItem *PanelItem,int ItemsNumber,int OpMode); + int MakeDirectory(HANDLE hPlugin,const wchar_t **Name,int OpMode); + int ProcessHostFile(HANDLE hPlugin,PluginPanelItem *PanelItem,int ItemsNumber,int OpMode); + int ProcessKey(HANDLE hPlugin,int Key,unsigned int ControlState); + int ProcessEvent(HANDLE hPlugin,int Event,void *Param); + int Compare(HANDLE hPlugin,const PluginPanelItem *Item1,const PluginPanelItem *Item2,unsigned int Mode); + int ProcessEditorInput(INPUT_RECORD *Rec); + int ProcessEditorEvent(int Event,void *Param); + int ProcessViewerEvent(int Event,void *Param); + int ProcessDialogEvent(int Event,void *Param); +#if defined(PROCPLUGINMACROFUNC) + int ProcessMacroFunc(const wchar_t *Name, const FarMacroValue *Params, int nParams, FarMacroValue **Results, int *nResults); +#endif + void GetCustomData(FileListItem *ListItem); + bool MayExitFar(); + + void BackroundTaskStarted(const wchar_t *Info); + void BackroundTaskFinished(const wchar_t *Info); + bool HasBackgroundTasks(); + std::map<std::wstring, unsigned int> BackgroundTasks(); + + friend class Plugin; +}; + +const char *PluginsIni(); diff --git a/far2l/src/plug/wrap.cpp b/far2l/src/plug/wrap.cpp new file mode 100644 index 00000000..51698953 --- /dev/null +++ b/far2l/src/plug/wrap.cpp @@ -0,0 +1,4089 @@ +/* +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. +*/ + + +//#define PW_to_PWZ(src,dst,lendst) WINPORT(MultiByteToWideChar)(CP_UTF8,0, (src),-1,(dst),(int)(lendst)) + +static int PWZ_to_PZ(const wchar_t *src, char *dst, int lendst) +{ + ErrnoSaver ErSr; + return WINPORT(WideCharToMultiByte)(CP_UTF8,0,(src),-1,(dst),(int)(lendst),nullptr,nullptr); +} + +static int PZ_to_PWZ(const char *src, wchar_t *dst, int lendst) +{ + ErrnoSaver ErSr; + return WINPORT(MultiByteToWideChar)(CP_UTF8,0, (src),-1,(dst),(int)(lendst)); +} + + +const char *FirstSlashA(const char *String) +{ + do + { + if (IsSlashA(*String)) + return String; + } + while (*String++); + + return nullptr; +} + +bool FirstSlashA(const char *String,size_t &pos) +{ + bool Ret=false; + const char *Ptr=FirstSlashA(String); + + if (Ptr) + { + pos=Ptr-String; + Ret=true; + } + + return Ret; +} + +const char *LastSlashA(const char *String) +{ + const char *Start = String; + + while (*String++) + ; + + while (--String!=Start && !IsSlashA(*String)) + ; + + return IsSlashA(*String)?String:nullptr; +} + +bool LastSlashA(const char *String,size_t &pos) +{ + bool Ret=false; + const char *Ptr=LastSlashA(String); + + if (Ptr) + { + pos=Ptr-String; + Ret=true; + } + + return Ret; +} + +void AnsiToUnicodeBin(const char *lpszAnsiString, wchar_t *lpwszUnicodeString, int nLength, UINT CodePage=CP_UTF8) +{ + if (lpszAnsiString && lpwszUnicodeString && nLength) + { + ErrnoSaver ErSr; + wmemset(lpwszUnicodeString, 0, nLength); + WINPORT(MultiByteToWideChar)(CodePage,0,lpszAnsiString,nLength,lpwszUnicodeString,nLength); + } +} + +wchar_t *AnsiToUnicodeBin(const char *lpszAnsiString, int nLength, UINT CodePage=CP_UTF8) +{ + wchar_t *lpResult = (wchar_t*)malloc(nLength*sizeof(wchar_t)); + AnsiToUnicodeBin(lpszAnsiString,lpResult,nLength,CodePage); + return lpResult; +} + +wchar_t *AnsiToUnicode(const char *lpszAnsiString, UINT CodePage=CP_UTF8) +{ + if (!lpszAnsiString) + return nullptr; + + return AnsiToUnicodeBin(lpszAnsiString,(int)strlen(lpszAnsiString)+1,CodePage); +} + +char *UnicodeToAnsiBin(const wchar_t *lpwszUnicodeString, int nLength, UINT CodePage=CP_UTF8) +{ + /* $ 06.01.2008 TS + ! Увеличил размер выделяемой под строку памяти на 1 байт для нормальной + работы старых плагинов, которые не знали, что надо смотреть на длину, + а не на завершающий ноль (например в EditorGetString.StringText). + */ + if (!lpwszUnicodeString || (nLength < 0)) + return nullptr; + + ErrnoSaver ErSr; + int dst_length = WINPORT(WideCharToMultiByte)( + CodePage, + 0, + lpwszUnicodeString, + nLength, + NULL, + 0, + nullptr, + nullptr + ); + if (dst_length<=0) dst_length = nLength + 1; else ++dst_length; + char *lpResult = (char*)malloc(dst_length); + if (!dst_length) return NULL; + memset(lpResult, 0, dst_length); + + if (nLength) + { + WINPORT(WideCharToMultiByte)( + CodePage, + 0, + lpwszUnicodeString, + nLength, + lpResult, + dst_length, + nullptr, + nullptr + ); + } + + return lpResult; +} + +char *UnicodeToAnsi(const wchar_t *lpwszUnicodeString, UINT CodePage=CP_UTF8) +{ + if (!lpwszUnicodeString) + return nullptr; + + return UnicodeToAnsiBin(lpwszUnicodeString,StrLength(lpwszUnicodeString)+1,CodePage); +} + +wchar_t **ArrayAnsiToUnicode(char ** lpaszAnsiString, int iCount) +{ + wchar_t** lpaResult = nullptr; + + if (lpaszAnsiString) + { + lpaResult = (wchar_t**) malloc((iCount+1)*sizeof(wchar_t*)); + + if (lpaResult) + { + for (int i=0; i<iCount; i++) + { + lpaResult[i]=(lpaszAnsiString[i])?AnsiToUnicode(lpaszAnsiString[i]):nullptr; + } + + lpaResult[iCount] = (wchar_t*)(LONG_PTR) 1; //Array end mark + } + } + + return lpaResult; +} + +void FreeArrayUnicode(wchar_t ** lpawszUnicodeString) +{ + if (lpawszUnicodeString) + { + for (int i=0; (LONG_PTR)lpawszUnicodeString[i] != 1; i++) //Until end mark + { + if (lpawszUnicodeString[i]) free(lpawszUnicodeString[i]); + } + + free(lpawszUnicodeString); + } +} + +DWORD OldKeyToKey(DWORD dOldKey) +{ + if (dOldKey&0x100) + { + dOldKey=(dOldKey^0x100)|EXTENDED_KEY_BASE; + } + else if (dOldKey&0x200) + { + dOldKey=(dOldKey^0x200)|INTERNAL_KEY_BASE; + } + else + { + DWORD CleanKey=dOldKey&~KEY_CTRLMASK; + + if (CleanKey>0x80 && CleanKey<0x100) + { + ErrnoSaver ErSr; + char OemChar=static_cast<char>(CleanKey); + wchar_t WideChar=0; + WINPORT(MultiByteToWideChar)(CP_UTF8,0,&OemChar,1,&WideChar,1); + dOldKey=(dOldKey^CleanKey)|WideChar; + } + } + + return dOldKey; +} + +DWORD KeyToOldKey(DWORD dKey) +{ + if (dKey&EXTENDED_KEY_BASE) + { + dKey=(dKey^EXTENDED_KEY_BASE)|0x100; + } + else if (dKey&INTERNAL_KEY_BASE) + { + dKey=(dKey^INTERNAL_KEY_BASE)|0x200; + } + else + { + DWORD CleanKey=dKey&~KEY_CTRLMASK; + + if (CleanKey>0x80 && CleanKey<0x10000) + { + ErrnoSaver ErSr; + wchar_t WideChar=static_cast<wchar_t>(CleanKey); + char OemChar=0; + WINPORT(WideCharToMultiByte)(CP_UTF8,0,&WideChar,1,&OemChar,1,0,nullptr); + dKey=(dKey^CleanKey)|OemChar; + } + } + + return dKey; +} + + +void ConvertInfoPanelLinesA(const oldfar::InfoPanelLine *iplA, InfoPanelLine **piplW, int iCount) +{ + if (iplA && piplW && (iCount>0)) + { + InfoPanelLine *iplW = (InfoPanelLine *) malloc(iCount*sizeof(InfoPanelLine)); + + if (iplW) + { + for (int i=0; i<iCount; i++) + { + iplW[i].Text=AnsiToUnicodeBin(iplA[i].Text,80); //BUGBUG + iplW[i].Data=AnsiToUnicodeBin(iplA[i].Data,80); //BUGBUG + iplW[i].Separator=iplA[i].Separator; + } + } + + *piplW = iplW; + } +} + +void FreeUnicodeInfoPanelLines(InfoPanelLine *iplW,int InfoLinesNumber) +{ + for (int i=0; i<InfoLinesNumber; i++) + { + if (iplW[i].Text) + free((void*)iplW[i].Text); + + if (iplW[i].Data) + free((void*)iplW[i].Data); + } + + if (iplW) + free((void*)iplW); +} + +void ConvertPanelModesA(const oldfar::PanelMode *pnmA, PanelMode **ppnmW, int iCount) +{ + if (pnmA && ppnmW && (iCount>0)) + { + PanelMode *pnmW = new(std::nothrow) PanelMode[iCount](); + if (pnmW) + { + for (int i=0; i<iCount; i++) + { + int iColumnCount = 0; + + if (pnmA[i].ColumnTypes) + { + char *lpTypes = strdup(pnmA[i].ColumnTypes); + const char *lpToken = strtok(lpTypes, ","); + + while (lpToken && *lpToken) + { + iColumnCount++; + lpToken = strtok(nullptr, ","); + } + + free(lpTypes); + } + + pnmW[i].ColumnTypes = (pnmA[i].ColumnTypes)?AnsiToUnicode(pnmA[i].ColumnTypes):nullptr; + pnmW[i].ColumnWidths = (pnmA[i].ColumnWidths)?AnsiToUnicode(pnmA[i].ColumnWidths):nullptr; + pnmW[i].ColumnTitles = (pnmA[i].ColumnTitles && (iColumnCount>0))?ArrayAnsiToUnicode(pnmA[i].ColumnTitles,iColumnCount):nullptr; + pnmW[i].FullScreen = pnmA[i].FullScreen; + pnmW[i].DetailedStatus = pnmA[i].DetailedStatus; + pnmW[i].AlignExtensions = pnmA[i].AlignExtensions; + pnmW[i].CaseConversion = pnmA[i].CaseConversion; + pnmW[i].StatusColumnTypes = (pnmA[i].StatusColumnTypes)?AnsiToUnicode(pnmA[i].StatusColumnTypes):nullptr; + pnmW[i].StatusColumnWidths = (pnmA[i].StatusColumnWidths)?AnsiToUnicode(pnmA[i].StatusColumnWidths):nullptr; + } + } + + *ppnmW = pnmW; + } +} + +void FreeUnicodePanelModes(PanelMode *pnmW, int iCount) +{ + if (pnmW) + { + for (int i=0; i<iCount; i++) + { + if (pnmW[i].ColumnTypes) free((void*)pnmW[i].ColumnTypes); + + if (pnmW[i].ColumnWidths) free((void*)pnmW[i].ColumnWidths); + + if (pnmW[i].ColumnTitles) FreeArrayUnicode((wchar_t**)pnmW[i].ColumnTitles); + + if (pnmW[i].StatusColumnTypes) free((void*)pnmW[i].StatusColumnTypes); + + if (pnmW[i].StatusColumnWidths) free((void*)pnmW[i].StatusColumnWidths); + } + + delete[] pnmW; + } +} + +void ConvertKeyBarTitlesA(const oldfar::KeyBarTitles *kbtA, KeyBarTitles *kbtW, bool FullStruct=true) +{ + if (kbtA && kbtW) + { + for (int i=0; i<12; i++) + { + kbtW->Titles[i] = kbtA->Titles[i]? AnsiToUnicode(kbtA->Titles[i]): nullptr; + kbtW->CtrlTitles[i] = kbtA->CtrlTitles[i]? AnsiToUnicode(kbtA->CtrlTitles[i]): nullptr; + kbtW->AltTitles[i] = kbtA->AltTitles[i]? AnsiToUnicode(kbtA->AltTitles[i]): nullptr; + kbtW->ShiftTitles[i] = kbtA->ShiftTitles[i]? AnsiToUnicode(kbtA->ShiftTitles[i]): nullptr; + kbtW->CtrlShiftTitles[i] = FullStruct && kbtA->CtrlShiftTitles[i]? AnsiToUnicode(kbtA->CtrlShiftTitles[i]): nullptr; + kbtW->AltShiftTitles[i] = FullStruct && kbtA->AltShiftTitles[i]? AnsiToUnicode(kbtA->AltShiftTitles[i]): nullptr; + kbtW->CtrlAltTitles[i] = FullStruct && kbtA->CtrlAltTitles[i]? AnsiToUnicode(kbtA->CtrlAltTitles[i]): nullptr; + } + } +} + +void FreeUnicodeKeyBarTitles(KeyBarTitles *kbtW) +{ + if (kbtW) + { + for (int i=0; i<12; i++) + { + if (kbtW->Titles[i]) free(kbtW->Titles[i]); + + if (kbtW->CtrlTitles[i]) free(kbtW->CtrlTitles[i]); + + if (kbtW->AltTitles[i]) free(kbtW->AltTitles[i]); + + if (kbtW->ShiftTitles[i]) free(kbtW->ShiftTitles[i]); + + if (kbtW->CtrlShiftTitles[i]) free(kbtW->CtrlShiftTitles[i]); + + if (kbtW->AltShiftTitles[i]) free(kbtW->AltShiftTitles[i]); + + if (kbtW->CtrlAltTitles[i]) free(kbtW->CtrlAltTitles[i]); + } + } +} + +void ConvertPanelItemA(const oldfar::PluginPanelItem *PanelItemA, PluginPanelItem **PanelItemW, int ItemsNumber) +{ + *PanelItemW = (PluginPanelItem *)malloc(ItemsNumber*sizeof(PluginPanelItem)); + memset(*PanelItemW,0,ItemsNumber*sizeof(PluginPanelItem)); + + for (int i=0; i<ItemsNumber; i++) + { + (*PanelItemW)[i].FindData.ftCreationTime = PanelItemA[i].FindData.ftCreationTime; + (*PanelItemW)[i].FindData.ftLastAccessTime = PanelItemA[i].FindData.ftLastAccessTime; + (*PanelItemW)[i].FindData.ftLastWriteTime = PanelItemA[i].FindData.ftLastWriteTime; + (*PanelItemW)[i].FindData.nPhysicalSize = PanelItemA[i].FindData.nPhysicalSize; + (*PanelItemW)[i].FindData.nFileSize = PanelItemA[i].FindData.nFileSize; + (*PanelItemW)[i].FindData.dwFileAttributes = PanelItemA[i].FindData.dwFileAttributes; + (*PanelItemW)[i].FindData.dwUnixMode = PanelItemA[i].FindData.dwUnixMode; + (*PanelItemW)[i].UserData = PanelItemA[i].UserData; + (*PanelItemW)[i].Flags = PanelItemA[i].Flags; + (*PanelItemW)[i].NumberOfLinks = PanelItemA[i].NumberOfLinks; + (*PanelItemW)[i].CRC32 = PanelItemA[i].CRC32; + (*PanelItemW)[i].FindData.lpwszFileName = AnsiToUnicode(PanelItemA[i].FindData.cFileName); + + if (PanelItemA[i].Description) + (*PanelItemW)[i].Description = AnsiToUnicode(PanelItemA[i].Description); + + if (PanelItemA[i].Owner) + (*PanelItemW)[i].Owner = AnsiToUnicode(PanelItemA[i].Owner); + + if (PanelItemA[i].Group) + (*PanelItemW)[i].Group = AnsiToUnicode(PanelItemA[i].Group); + + if (PanelItemA[i].CustomColumnNumber) + { + (*PanelItemW)[i].CustomColumnNumber = PanelItemA[i].CustomColumnNumber; + (*PanelItemW)[i].CustomColumnData = ArrayAnsiToUnicode(PanelItemA[i].CustomColumnData,PanelItemA[i].CustomColumnNumber); + } + } +} + +void ConvertPanelItemToAnsi(const PluginPanelItem &PanelItem, oldfar::PluginPanelItem &PanelItemA) +{ + PanelItemA.Flags = PanelItem.Flags; + PanelItemA.NumberOfLinks=PanelItem.NumberOfLinks; + + if (PanelItem.Description) + PanelItemA.Description=UnicodeToAnsi(PanelItem.Description); + + if (PanelItem.Owner) + PanelItemA.Owner=UnicodeToAnsi(PanelItem.Owner); + + if (PanelItem.Group) + PanelItemA.Group=UnicodeToAnsi(PanelItem.Group); + + if (PanelItem.CustomColumnNumber) + { + PanelItemA.CustomColumnNumber=PanelItem.CustomColumnNumber; + PanelItemA.CustomColumnData=(char **)malloc(PanelItem.CustomColumnNumber*sizeof(char *)); + + for (int j=0; j<PanelItem.CustomColumnNumber; j++) + PanelItemA.CustomColumnData[j] = UnicodeToAnsi(PanelItem.CustomColumnData[j]); + } + + if (PanelItem.UserData&&PanelItem.Flags&PPIF_USERDATA) + { + DWORD Size=*(DWORD *)PanelItem.UserData; + PanelItemA.UserData=(DWORD_PTR)malloc(Size); + memcpy((void *)PanelItemA.UserData,(void *)PanelItem.UserData,Size); + } + else + PanelItemA.UserData = PanelItem.UserData; + + PanelItemA.CRC32 = PanelItem.CRC32; + PanelItemA.FindData.dwFileAttributes = PanelItem.FindData.dwFileAttributes; + PanelItemA.FindData.ftCreationTime = PanelItem.FindData.ftCreationTime; + PanelItemA.FindData.ftLastAccessTime = PanelItem.FindData.ftLastAccessTime; + PanelItemA.FindData.ftLastWriteTime = PanelItem.FindData.ftLastWriteTime; + PanelItemA.FindData.nFileSize = PanelItem.FindData.nFileSize; + PanelItemA.FindData.nPhysicalSize = PanelItem.FindData.nPhysicalSize; + PWZ_to_PZ(PanelItem.FindData.lpwszFileName,PanelItemA.FindData.cFileName,ARRAYSIZE(PanelItemA.FindData.cFileName)); +} + +void ConvertPanelItemsArrayToAnsi(const PluginPanelItem *PanelItemW, oldfar::PluginPanelItem *&PanelItemA, int ItemsNumber) +{ + PanelItemA = (oldfar::PluginPanelItem *)malloc(ItemsNumber*sizeof(oldfar::PluginPanelItem)); + memset(PanelItemA,0,ItemsNumber*sizeof(oldfar::PluginPanelItem)); + + for (int i=0; i<ItemsNumber; i++) + { + ConvertPanelItemToAnsi(PanelItemW[i],PanelItemA[i]); + } +} + +void FreeUnicodePanelItem(PluginPanelItem *PanelItem, int ItemsNumber) +{ + for (int i=0; i<ItemsNumber; i++) + { + if (PanelItem[i].Description) + free((void*)PanelItem[i].Description); + + if (PanelItem[i].Owner) + free((void*)PanelItem[i].Owner); + + if (PanelItem[i].Group) + free((void*)PanelItem[i].Group); + + if (PanelItem[i].CustomColumnNumber) + { + for (int j=0; j<PanelItem[i].CustomColumnNumber; j++) + free((void*)PanelItem[i].CustomColumnData[j]); + + free((void*)PanelItem[i].CustomColumnData); + } + + apiFreeFindData(&PanelItem[i].FindData); + } + + free(PanelItem); +} + +void FreePanelItemA(oldfar::PluginPanelItem *PanelItem, int ItemsNumber, bool bFreeArray=true) +{ + for (int i=0; i<ItemsNumber; i++) + { + if (PanelItem[i].Description) + free(PanelItem[i].Description); + + if (PanelItem[i].Owner) + free(PanelItem[i].Owner); + + if (PanelItem[i].Group) + free(PanelItem[i].Group); + + if (PanelItem[i].CustomColumnNumber) + { + for (int j=0; j<PanelItem[i].CustomColumnNumber; j++) + free(PanelItem[i].CustomColumnData[j]); + + free(PanelItem[i].CustomColumnData); + } + + if (PanelItem[i].UserData&&PanelItem[i].Flags&oldfar::PPIF_USERDATA) + { + free((PVOID)PanelItem[i].UserData); + } + } + + if (bFreeArray) + free(PanelItem); +} + +char* WINAPI RemoveTrailingSpacesA(char *Str) +{ + if (!Str) + return nullptr; + + if (*Str == '\0') + return Str; + + char *ChPtr; + size_t I; + + for (ChPtr=Str+(I=strlen(Str))-1; I > 0; I--, ChPtr--) + { + if (IsSpace(*ChPtr) || IsEol(*ChPtr)) + *ChPtr=0; + else + break; + } + + return Str; +} + +char *WINAPI FarItoaA(int value, char *string, int radix) +{ + if (string) + return _itoa(value,string,radix); + + return nullptr; +} + +char *WINAPI FarItoa64A(int64_t value, char *string, int radix) +{ + if (string) + return _i64toa(value, string, radix); + + return nullptr; +} + +int WINAPI FarAtoiA(const char *s) +{ + if (s) + return atoi(s); + + return 0; +} + +int64_t WINAPI FarAtoi64A(const char *s) +{ + return s ? atoll(s) : 0; +} + +char* WINAPI PointToNameA(char *Path) +{ + if (!Path) + return nullptr; + + char *NamePtr=Path; + + while (*Path) + { + if (IsSlashA(*Path)) + NamePtr=Path+1; + + Path++; + } + + return(NamePtr); +} + +void WINAPI UnquoteA(char *Str) +{ + if (!Str) + return; + + char *Dst=Str; + + while (*Str) + { + if (*Str!='\"') + *Dst++=*Str; + + Str++; + } + + *Dst=0; +} + +char* WINAPI RemoveLeadingSpacesA(char *Str) +{ + char *ChPtr; + + if (!(ChPtr=Str)) + return nullptr; + + for (; IsSpace(*ChPtr); ChPtr++) + ; + + if (ChPtr!=Str) + memmove(Str,ChPtr,strlen(ChPtr)+1); + + return Str; +} + +char* WINAPI RemoveExternalSpacesA(char *Str) +{ + return RemoveTrailingSpacesA(RemoveLeadingSpacesA(Str)); +} + +char* WINAPI TruncStrA(char *Str,int MaxLength) +{ + if (Str) + { + int Length; + + if (MaxLength<0) + MaxLength=0; + + if ((Length=(int)strlen(Str))>MaxLength) + { + if (MaxLength>3) + { + char *MovePos = Str+Length-MaxLength+3; + memmove(Str+3,MovePos,strlen(MovePos)+1); + memcpy(Str,"...",3); + } + + Str[MaxLength]=0; + } + } + + return(Str); +} + +char* WINAPI TruncPathStrA(char *Str, int MaxLength) +{ + if (Str) + { + int nLength = (int)strlen(Str); + + if (nLength > MaxLength) + { + char *lpStart = nullptr; + +/* if (*Str && (Str[1] == ':') && IsSlash(Str[2])) + lpStart = Str+3; + else*/ + { + if ((Str[0] == GOOD_SLASH) && (Str[1] == GOOD_SLASH)) + { + if ((lpStart = const_cast<char*>(FirstSlashA(Str+2))) ) + if ((lpStart = const_cast<char*>(FirstSlashA(lpStart+1)))) + lpStart++; + } + } + + if (!lpStart || (lpStart-Str > MaxLength-5)) + return TruncStrA(Str, MaxLength); + + char *lpInPos = lpStart+3+(nLength-MaxLength); + memmove(lpStart+3, lpInPos, strlen(lpInPos)+1); + memcpy(lpStart, "...", 3); + } + } + + return Str; +} + +char *InsertQuoteA(char *Str) +{ + size_t l = strlen(Str); + + if (*Str != '"') + { + memmove(Str+1,Str,++l); + *Str='"'; + } + + if (Str[l-1] != '"') + { + Str[l++] = '\"'; + Str[l] = 0; + } + + return Str; +} + +char* WINAPI QuoteSpaceOnlyA(char *Str) +{ + if (Str && strchr(Str,' ')) + InsertQuoteA(Str); + + return(Str); +} + +BOOL AddEndSlashA(char *Path,char TypeSlash) +{ + BOOL Result=FALSE; + + if (Path) + { + /* $ 06.12.2000 IS + ! Теперь функция работает с обоими видами слешей, также происходит + изменение уже существующего конечного слеша на такой, который + встречается чаще. + */ + char *end=Path+strlen(Path); + int Length=(int)(end-Path); + char c = (TypeSlash == '\\') ? '\\' : '/'; + Result=TRUE; + + if (!Length) + { + *end=c; + end[1]=0; + } + else + { + end--; + + if (!IsSlashA(*end)) + { + end[1]=c; + end[2]=0; + } + else + *end=c; + } + + /* IS $ */ + } + + return Result; +} + +BOOL WINAPI AddEndSlashA(char *Path) +{ + return AddEndSlashA(Path,0); +} + +void WINAPI GetPathRootA(const char *Path, char *Root) +{ + fprintf(stderr, "DEPRECATED: %s('%s')\n", __FUNCTION__, Path); + Root[0] = GOOD_SLASH; + Root[1] = 0; +} + +int WINAPI CopyToClipboardA(const char *Data) +{ + wchar_t *p = Data?AnsiToUnicode(Data):nullptr; + int ret = CopyToClipboard(p); + + if (p) free(p); + + return ret; +} + +char* WINAPI PasteFromClipboardA() +{ + wchar_t *p = PasteFromClipboard(); + + if (p) { + char *pa = UnicodeToAnsi(p); + free(p); + return pa; + } + + return nullptr; +} + +void WINAPI DeleteBufferA(void *Buffer) +{ + if (Buffer) free(Buffer); +} + +int WINAPI ProcessNameA(const char *Param1,char *Param2,DWORD Flags) +{ + FARString strP1(Param1), strP2(Param2); + int size = (int)(strP1.GetLength()+strP2.GetLength()+oldfar::NM)+1; //а хрен ещё как угадать скока там этот Param2 для PN_GENERATENAME + wchar_t *p=(wchar_t *)malloc(size*sizeof(wchar_t)); + wcscpy(p,strP2); + int newFlags = 0; + + if (Flags&oldfar::PN_SKIPPATH) + { + newFlags|=PN_SKIPPATH; + Flags &= ~oldfar::PN_SKIPPATH; + } + + if (Flags == oldfar::PN_CMPNAME) + { + newFlags|=PN_CMPNAME; + } + else if (Flags == oldfar::PN_CMPNAMELIST) + { + newFlags|=PN_CMPNAMELIST; + } + else if (Flags&oldfar::PN_GENERATENAME) + { + newFlags|=PN_GENERATENAME|(Flags&0xFF); + } + + int ret = ProcessName(strP1,p,size,newFlags); + + if (newFlags&PN_GENERATENAME) + PWZ_to_PZ(p,Param2,size); + + free(p); + return ret; +} + +int WINAPI KeyNameToKeyA(const char *Name) +{ + FARString strN(Name); + return KeyToOldKey(KeyNameToKey(strN)); +} + +BOOL WINAPI FarKeyToNameA(int Key,char *KeyText,int Size) +{ + FARString strKT; + int ret=KeyToText(OldKeyToKey(Key),strKT); + + if (ret) + strKT.GetCharString(KeyText,Size>0?Size+1:32); + + return ret; +} + +int WINAPI InputRecordToKeyA(const INPUT_RECORD *r) +{ + return KeyToOldKey(InputRecordToKey(r)); +} + +char* WINAPI FarMkTempA(char *Dest, const char *Prefix) +{ + FARString strP(Prefix); + wchar_t D[oldfar::NM] = {0}; + FarMkTemp(D,ARRAYSIZE(D),strP); + PWZ_to_PZ(D,Dest,sizeof(D)); + return Dest; +} + +int WINAPI FarMkLinkA(const char *Src,const char *Dest, DWORD Flags) +{ + FARString s(Src), d(Dest); + int flg=0; + + switch (Flags&0xf) + { + case oldfar::FLINK_HARDLINK: flg = FLINK_HARDLINK; break; + case oldfar::FLINK_JUNCTION: flg = FLINK_JUNCTION; break; + case oldfar::FLINK_VOLMOUNT: flg = FLINK_VOLMOUNT; break; + case oldfar::FLINK_SYMLINKFILE: flg = FLINK_SYMLINKFILE; break; + case oldfar::FLINK_SYMLINKDIR: flg = FLINK_SYMLINKDIR; break; + } + + if (Flags&oldfar::FLINK_SHOWERRMSG) flg|=FLINK_SHOWERRMSG; + + if (Flags&oldfar::FLINK_DONOTUPDATEPANEL) flg|=FLINK_DONOTUPDATEPANEL; + + return FarMkLink(s, d, flg); +} + +int WINAPI GetNumberOfLinksA(const char *Name) +{ + fprintf(stderr, "TODO: GetNumberOfLinksA(%s)\n", Name); + return 1; + //FARString n(Name); + //return GetNumberOfLinks(n); +} + +int WINAPI ConvertNameToRealA(const char *Src,char *Dest,int DestSize) +{ + FARString strSrc(Src),strDest; + ConvertNameToReal(strSrc,strDest); + + if (!Dest) + return (int)strDest.GetLength(); + else + strDest.GetCharString(Dest,DestSize); + + return Min((int)strDest.GetLength(),DestSize); +} + +int WINAPI FarGetReparsePointInfoA(const char *Src,char *Dest,int DestSize) +{ + + /*if (Src && *Src) + { + FARString strSrc(Src); + FARString strDest; + DWORD Size=GetReparsePointInfo(strSrc,strDest,nullptr); + + if (DestSize && Dest) + strDest.GetCharString(Dest,DestSize); + + return Size; + }*/ + + return 0; +} + +struct FAR_SEARCH_A_CALLBACK_PARAM +{ + oldfar::FRSUSERFUNC Func; + void *Param; +}; + +static int WINAPI FarRecursiveSearchA_Callback(const FAR_FIND_DATA *FData,const wchar_t *FullName,void *param) +{ + FAR_SEARCH_A_CALLBACK_PARAM* pCallbackParam = static_cast<FAR_SEARCH_A_CALLBACK_PARAM*>(param); + WIN32_FIND_DATAA FindData{}; + FindData.dwFileAttributes = FData->dwFileAttributes; + FindData.ftCreationTime = FData->ftCreationTime; + FindData.ftLastAccessTime = FData->ftLastAccessTime; + FindData.ftLastWriteTime = FData->ftLastWriteTime; + FindData.nFileSize = (DWORD)FData->nFileSize; + PWZ_to_PZ(FData->lpwszFileName,FindData.cFileName,ARRAYSIZE(FindData.cFileName)); + char FullNameA[oldfar::NM]; + PWZ_to_PZ(FullName,FullNameA,sizeof(FullNameA)); + return pCallbackParam->Func(&FindData,FullNameA,pCallbackParam->Param); +} + +void WINAPI FarRecursiveSearchA(const char *InitDir,const char *Mask,oldfar::FRSUSERFUNC Func,DWORD Flags,void *Param) +{ + FARString strInitDir(InitDir); + FARString strMask(Mask); + FAR_SEARCH_A_CALLBACK_PARAM CallbackParam; + CallbackParam.Func = Func; + CallbackParam.Param = Param; + int newFlags = 0; + + if (Flags&oldfar::FRS_RETUPDIR) newFlags|=FRS_RETUPDIR; + + if (Flags&oldfar::FRS_RECUR) newFlags|=FRS_RECUR; + + if (Flags&oldfar::FRS_SCANSYMLINK) newFlags|=FRS_SCANSYMLINK; + + FarRecursiveSearch(static_cast<const wchar_t *>(strInitDir),static_cast<const wchar_t *>(strMask),FarRecursiveSearchA_Callback,newFlags,static_cast<void *>(&CallbackParam)); +} + +DWORD WINAPI ExpandEnvironmentStrA(const char *src, char *dest, size_t size) +{ + FARString strS(src), strD; + apiExpandEnvironmentStrings(strS,strD); + DWORD len = (DWORD)Min(strD.GetLength(),size-1); + strD.GetCharString(dest,len+1); + return len; +} + +int WINAPI FarViewerA(const char *FileName,const char *Title,int X1,int Y1,int X2,int Y2,DWORD Flags) +{ + FARString strFN(FileName), strT(Title); + return FarViewer(strFN,strT,X1,Y1,X2,Y2,Flags,CP_AUTODETECT); +} + +int WINAPI FarEditorA(const char *FileName,const char *Title,int X1,int Y1,int X2,int Y2,DWORD Flags,int StartLine,int StartChar) +{ + FARString strFN(FileName), strT(Title); + return FarEditor(strFN,strT,X1,Y1,X2,Y2,Flags,StartLine,StartChar,CP_AUTODETECT); +} + +int WINAPI FarCmpNameA(const char *pattern,const char *str,int skippath) +{ + FARString strP(pattern), strS(str); + return FarCmpName(strP,strS,skippath); +} + +void WINAPI FarTextA(int X,int Y,int Color,const char *Str) +{ + if (!Str) return FarText(X,Y,Color,nullptr); + + FARString strS(Str); + return FarText(X,Y,Color,strS); +} + +BOOL WINAPI FarShowHelpA(const char *ModuleName,const char *HelpTopic,DWORD Flags) +{ + FARString strMN(ModuleName), strHT(HelpTopic); + return FarShowHelp(strMN,(HelpTopic?strHT.CPtr():nullptr),Flags); +} + +int WINAPI FarInputBoxA(const char *Title,const char *Prompt,const char *HistoryName,const char *SrcText,char *DestText,int DestLength,const char *HelpTopic,DWORD Flags) +{ + FARString strT(Title), strP(Prompt), strHN(HistoryName), strST(SrcText), strD, strHT(HelpTopic); + wchar_t *D = strD.GetBuffer(DestLength); + int ret = FarInputBox((Title?strT.CPtr():nullptr),(Prompt?strP.CPtr():nullptr),(HistoryName?strHN.CPtr():nullptr),(SrcText?strST.CPtr():nullptr),D,DestLength,(HelpTopic?strHT.CPtr():nullptr),Flags); + strD.ReleaseBuffer(); + + if (ret && DestText) + strD.GetCharString(DestText,DestLength+1); + + return ret; +} + +int WINAPI FarMessageFnA(INT_PTR PluginNumber,DWORD Flags,const char *HelpTopic,const char * const *Items,int ItemsNumber,int ButtonsNumber) +{ + FARString strHT(HelpTopic); + wchar_t **p; + int c=0; + + Flags&=~oldfar::FMSG_DOWN; + + if (Flags&oldfar::FMSG_ALLINONE) + { + fprintf(stderr, "FMSG_ALLINONE\n"); + p = (wchar_t **)AnsiToUnicode((const char *)Items); + } + else + { + c = ItemsNumber; + p = (wchar_t **)malloc(c*sizeof(wchar_t*)); + + for (int i=0; i<c; i++) + p[i] = AnsiToUnicode(Items[i]); + } + + int ret = FarMessageFn(PluginNumber,Flags,(HelpTopic?strHT.CPtr():nullptr),p,ItemsNumber,ButtonsNumber); + + for (int i=0; i<c; i++) + free(p[i]); + + free(p); + return ret; +} + +static CriticalSection s_get_msga_cs; +const char * WINAPI FarGetMsgFnA(INT_PTR PluginHandle,int MsgId) +{ + //BUGBUG, надо проверять, что PluginHandle - плагин + PluginA *pPlugin = (PluginA*)PluginHandle; + + std::wstring strPath = pPlugin->GetModuleName().CPtr(); + CutToSlash(strPath); + + CriticalSectionLock lock(s_get_msga_cs); +// fprintf(stderr,"FarGetMsgFnA: strPath=%ls\n", strPath.CPtr()); + + if (!pPlugin->InitLang(strPath.c_str())) { + return ""; + } + + return pPlugin->GetMsgA(MsgId); +} + +int WINAPI FarMenuFnA(INT_PTR PluginNumber,int X,int Y,int MaxHeight,DWORD Flags,const char *Title,const char *Bottom,const char *HelpTopic,const int *BreakKeys,int *BreakCode,const oldfar::FarMenuItem *Item,int ItemsNumber) +{ + FARString strT(Title), strB(Bottom), strHT(HelpTopic); + const wchar_t *wszT = Title?strT.CPtr():nullptr; + const wchar_t *wszB = Bottom?strB.CPtr():nullptr; + const wchar_t *wszHT = HelpTopic?strHT.CPtr():nullptr; + + if (!Item || !ItemsNumber) + return FarMenuFn(PluginNumber,X,Y,MaxHeight,Flags,wszT,wszB,wszHT,BreakKeys,BreakCode,nullptr,0); + + FarMenuItemEx *mi = (FarMenuItemEx *)malloc(ItemsNumber*sizeof(*mi)); + + if (Flags&FMENU_USEEXT) + { + oldfar::FarMenuItemEx *p = (oldfar::FarMenuItemEx *)Item; + + for (int i=0; i<ItemsNumber; i++) + { + mi[i].Flags = p[i].Flags&~oldfar::MIF_USETEXTPTR; + mi[i].Text = AnsiToUnicode(p[i].Flags&oldfar::MIF_USETEXTPTR?p[i].Text.TextPtr:p[i].Text.Text); + mi[i].AccelKey = OldKeyToKey(p[i].AccelKey); + mi[i].Reserved = p[i].Reserved; + mi[i].UserData = p[i].UserData; + } + } + else + { + for (int i=0; i<ItemsNumber; i++) + { + mi[i].Flags=0; + + if (Item[i].Selected) + mi[i].Flags|=MIF_SELECTED; + + if (Item[i].Checked) + { + mi[i].Flags|=MIF_CHECKED; + + if (Item[i].Checked>1) + AnsiToUnicodeBin((const char*)&Item[i].Checked,(wchar_t*)&mi[i].Flags,1); + } + + if (Item[i].Separator) + { + mi[i].Flags|=MIF_SEPARATOR; + mi[i].Text = 0; + } + else + mi[i].Text = AnsiToUnicode(Item[i].Text); + + mi[i].AccelKey = 0; + mi[i].Reserved = 0; + mi[i].UserData = 0; + } + } + + int ret = FarMenuFn(PluginNumber,X,Y,MaxHeight,Flags|FMENU_USEEXT,wszT,wszB,wszHT,BreakKeys,BreakCode,(FarMenuItem *)mi,ItemsNumber); + + for (int i=0; i<ItemsNumber; i++) + if (mi[i].Text) free((wchar_t *)mi[i].Text); + + if (mi) free(mi); + + return ret; +} + +typedef struct DialogData +{ + FARWINDOWPROC DlgProc; + HANDLE hDlg; + oldfar::FarDialogItem *diA; + FarDialogItem *di; + FarList *l; +} *PDialogData; + +DList<PDialogData>DialogList; + +oldfar::FarDialogItem* OneDialogItem=nullptr; + +PDialogData FindCurrentDialogData(HANDLE hDlg) +{ + PDialogData Result=nullptr; + for(PDialogData* i=DialogList.Last();i;i=DialogList.Prev(i)) + { + if((*i)->hDlg==hDlg) + { + Result=*i; + break; + } + } + return Result; +} + +oldfar::FarDialogItem* CurrentDialogItemA(HANDLE hDlg,int ItemNumber) +{ + PDialogData Data=FindCurrentDialogData(hDlg); + return Data?&Data->diA[ItemNumber]:nullptr; +} + +FarDialogItem* CurrentDialogItem(HANDLE hDlg,int ItemNumber) +{ + PDialogData Data=FindCurrentDialogData(hDlg); + return Data?&Data->di[ItemNumber]:nullptr; +} + +FarList* CurrentList(HANDLE hDlg,int ItemNumber) +{ + PDialogData Data=FindCurrentDialogData(hDlg); + return Data?&Data->l[ItemNumber]:nullptr; +} + +LONG_PTR WINAPI CurrentDlgProc(HANDLE hDlg, int Msg, int Param1, LONG_PTR Param2) +{ + LONG_PTR Ret=0; + PDialogData Data=FindCurrentDialogData(hDlg); + + if (Data && Data->DlgProc) + Ret=Data->DlgProc(Data->hDlg,Msg,Param1,Param2); + + return Ret; +} + +void UnicodeListItemToAnsi(FarListItem* li, oldfar::FarListItem* liA) +{ + PWZ_to_PZ(li->Text, liA->Text, sizeof(liA->Text)-1); + liA->Flags=0; + + if (li->Flags&LIF_SELECTED) liA->Flags|=oldfar::LIF_SELECTED; + + if (li->Flags&LIF_CHECKED) liA->Flags|=oldfar::LIF_CHECKED; + + if (li->Flags&LIF_SEPARATOR) liA->Flags|=oldfar::LIF_SEPARATOR; + + if (li->Flags&LIF_DISABLE) liA->Flags|=oldfar::LIF_DISABLE; + + if (li->Flags&LIF_GRAYED) liA->Flags|=oldfar::LIF_GRAYED; + + if (li->Flags&LIF_HIDDEN) liA->Flags|=oldfar::LIF_HIDDEN; + + if (li->Flags&LIF_DELETEUSERDATA) liA->Flags|=oldfar::LIF_DELETEUSERDATA; +} + +size_t GetAnsiVBufSize(oldfar::FarDialogItem &diA) +{ + return (diA.X2-diA.X1+1)*(diA.Y2-diA.Y1+1); +} + +PCHAR_INFO GetAnsiVBufPtr(PCHAR_INFO VBuf, size_t Size) +{ + PCHAR_INFO VBufA=nullptr; + if (VBuf) + { + VBufA=*reinterpret_cast<PCHAR_INFO*>(&VBuf[Size]); + } + return VBufA; +} + +void SetAnsiVBufPtr(PCHAR_INFO VBuf, PCHAR_INFO VBufA, size_t Size) +{ + if (VBuf) + { + *reinterpret_cast<PCHAR_INFO*>(&VBuf[Size])=VBufA; + } +} + +void AnsiVBufToUnicode(PCHAR_INFO VBufA, PCHAR_INFO VBuf, size_t Size,bool NoCvt) +{ + if (VBuf && VBufA) + { + for (size_t i=0; i<Size; i++) + { + if (NoCvt) + { + VBuf[i].Char.UnicodeChar=VBufA[i].Char.UnicodeChar; + } + else + { + AnsiToUnicodeBin(&VBufA[i].Char.AsciiChar,&VBuf[i].Char.UnicodeChar,1); + } + + VBuf[i].Attributes = VBufA[i].Attributes; + } + } +} + +PCHAR_INFO AnsiVBufToUnicode(oldfar::FarDialogItem &diA) +{ + PCHAR_INFO VBuf = nullptr; + + if (diA.Param.VBuf) + { + size_t Size = GetAnsiVBufSize(diA); + // +sizeof(PCHAR_INFO) потому что там храним поинтер на анси vbuf. + VBuf = reinterpret_cast<PCHAR_INFO>(malloc(Size*sizeof(CHAR_INFO)+sizeof(PCHAR_INFO))); + + if (VBuf) + { + AnsiVBufToUnicode(diA.Param.VBuf, VBuf, Size,(diA.Flags&oldfar::DIF_NOTCVTUSERCONTROL)==oldfar::DIF_NOTCVTUSERCONTROL); + SetAnsiVBufPtr(VBuf, diA.Param.VBuf, Size); + } + } + + return VBuf; +} + +void AnsiListItemToUnicode(oldfar::FarListItem* liA, FarListItem* li) +{ + wchar_t* ListItemText=(wchar_t*)malloc(ARRAYSIZE(liA->Text)*sizeof(wchar_t)); + PZ_to_PWZ(liA->Text, ListItemText, sizeof(liA->Text)-1); + ListItemText[ARRAYSIZE(liA->Text) - 1] = 0; + li->Text=ListItemText; + li->Flags=0; + + if (liA->Flags&oldfar::LIF_SELECTED) li->Flags|=LIF_SELECTED; + + if (liA->Flags&oldfar::LIF_CHECKED) li->Flags|=LIF_CHECKED; + + if (liA->Flags&oldfar::LIF_SEPARATOR) li->Flags|=LIF_SEPARATOR; + + if (liA->Flags&oldfar::LIF_DISABLE) li->Flags|=LIF_DISABLE; + + if (liA->Flags&oldfar::LIF_GRAYED) li->Flags|=LIF_GRAYED; + + if (liA->Flags&oldfar::LIF_HIDDEN) li->Flags|=LIF_HIDDEN; + + if (liA->Flags&oldfar::LIF_DELETEUSERDATA) li->Flags|=LIF_DELETEUSERDATA; +} + +void AnsiDialogItemToUnicodeSafe(oldfar::FarDialogItem &diA, FarDialogItem &di) +{ + switch (diA.Type) + { + case oldfar::DI_TEXT: + di.Type=DI_TEXT; + break; + case oldfar::DI_VTEXT: + di.Type=DI_VTEXT; + break; + case oldfar::DI_SINGLEBOX: + di.Type=DI_SINGLEBOX; + break; + case oldfar::DI_DOUBLEBOX: + di.Type=DI_DOUBLEBOX; + break; + case oldfar::DI_EDIT: + di.Type=DI_EDIT; + break; + case oldfar::DI_PSWEDIT: + di.Type=DI_PSWEDIT; + break; + case oldfar::DI_FIXEDIT: + di.Type=DI_FIXEDIT; + break; + case oldfar::DI_BUTTON: + di.Type=DI_BUTTON; + di.Param.Selected=diA.Param.Selected; + break; + case oldfar::DI_CHECKBOX: + di.Type=DI_CHECKBOX; + di.Param.Selected=diA.Param.Selected; + break; + case oldfar::DI_RADIOBUTTON: + di.Type=DI_RADIOBUTTON; + di.Param.Selected=diA.Param.Selected; + break; + case oldfar::DI_COMBOBOX: + di.Type=DI_COMBOBOX; + di.Param.ListPos=diA.Param.ListPos; + break; + case oldfar::DI_LISTBOX: + di.Type=DI_LISTBOX; + di.Param.ListPos=diA.Param.ListPos; + break; + case oldfar::DI_MEMOEDIT: + di.Type=DI_MEMOEDIT; + break; + case oldfar::DI_USERCONTROL: + di.Type=DI_USERCONTROL; + break; + } + + di.X1=diA.X1; + di.Y1=diA.Y1; + di.X2=diA.X2; + di.Y2=diA.Y2; + di.Focus=diA.Focus; + di.Flags=0; + + if (diA.Flags) + { + if (diA.Flags&oldfar::DIF_SETCOLOR) + di.Flags|=DIF_SETCOLOR|(diA.Flags&oldfar::DIF_COLORMASK); + + if (diA.Flags&oldfar::DIF_BOXCOLOR) + di.Flags|=DIF_BOXCOLOR; + + if (diA.Flags&oldfar::DIF_GROUP) + di.Flags|=DIF_GROUP; + + if (diA.Flags&oldfar::DIF_LEFTTEXT) + di.Flags|=DIF_LEFTTEXT; + + if (diA.Flags&oldfar::DIF_MOVESELECT) + di.Flags|=DIF_MOVESELECT; + + if (diA.Flags&oldfar::DIF_SHOWAMPERSAND) + di.Flags|=DIF_SHOWAMPERSAND; + + if (diA.Flags&oldfar::DIF_CENTERGROUP) + di.Flags|=DIF_CENTERGROUP; + + if (diA.Flags&oldfar::DIF_NOBRACKETS) + di.Flags|=DIF_NOBRACKETS; + + if (diA.Flags&oldfar::DIF_MANUALADDHISTORY) + di.Flags|=DIF_MANUALADDHISTORY; + + if (diA.Flags&oldfar::DIF_SEPARATOR) + di.Flags|=DIF_SEPARATOR; + + if (diA.Flags&oldfar::DIF_SEPARATOR2) + di.Flags|=DIF_SEPARATOR2; + + if (diA.Flags&oldfar::DIF_EDITOR) + di.Flags|=DIF_EDITOR; + + if (diA.Flags&oldfar::DIF_LISTNOAMPERSAND) + di.Flags|=DIF_LISTNOAMPERSAND; + + if (diA.Flags&oldfar::DIF_LISTNOBOX) + di.Flags|=DIF_LISTNOBOX; + + if (diA.Flags&oldfar::DIF_HISTORY) + di.Flags|=DIF_HISTORY; + + if (diA.Flags&oldfar::DIF_BTNNOCLOSE) + di.Flags|=DIF_BTNNOCLOSE; + + if (diA.Flags&oldfar::DIF_CENTERTEXT) + di.Flags|=DIF_CENTERTEXT; + + if (diA.Flags&oldfar::DIF_SEPARATORUSER) + di.Flags|=DIF_SEPARATORUSER; + + if (diA.Flags&oldfar::DIF_EDITEXPAND) + di.Flags|=DIF_EDITEXPAND; + + if (diA.Flags&oldfar::DIF_DROPDOWNLIST) + di.Flags|=DIF_DROPDOWNLIST; + + if (diA.Flags&oldfar::DIF_USELASTHISTORY) + di.Flags|=DIF_USELASTHISTORY; + + if (diA.Flags&oldfar::DIF_MASKEDIT) + di.Flags|=DIF_MASKEDIT; + + if (diA.Flags&oldfar::DIF_SELECTONENTRY) + di.Flags|=DIF_SELECTONENTRY; + + if (diA.Flags&oldfar::DIF_3STATE) + di.Flags|=DIF_3STATE; + + if (diA.Flags&oldfar::DIF_EDITPATH) + di.Flags|=DIF_EDITPATH; + + if (diA.Flags&oldfar::DIF_LISTWRAPMODE) + di.Flags|=DIF_LISTWRAPMODE; + + if (diA.Flags&oldfar::DIF_LISTAUTOHIGHLIGHT) + di.Flags|=DIF_LISTAUTOHIGHLIGHT; + + if (diA.Flags&oldfar::DIF_AUTOMATION) + di.Flags|=DIF_AUTOMATION; + + if (diA.Flags&oldfar::DIF_HIDDEN) + di.Flags|=DIF_HIDDEN; + + if (diA.Flags&oldfar::DIF_READONLY) + di.Flags|=DIF_READONLY; + + if (diA.Flags&oldfar::DIF_NOFOCUS) + di.Flags|=DIF_NOFOCUS; + + if (diA.Flags&oldfar::DIF_DISABLE) + di.Flags|=DIF_DISABLE; + } + + di.DefaultButton=diA.DefaultButton; +} + +void AnsiDialogItemToUnicode(oldfar::FarDialogItem &diA, FarDialogItem &di,FarList &l) +{ + memset(&di,0,sizeof(FarDialogItem)); + AnsiDialogItemToUnicodeSafe(diA,di); + + switch (di.Type) + { + case DI_LISTBOX: + case DI_COMBOBOX: + { + if (diA.Param.ListItems && IsPtr(diA.Param.ListItems)) + { + l.Items = (FarListItem *)malloc(diA.Param.ListItems->ItemsNumber*sizeof(FarListItem)); + l.ItemsNumber = diA.Param.ListItems->ItemsNumber; + + for (int j=0; j<diA.Param.ListItems->ItemsNumber; j++) { + AnsiListItemToUnicode(&diA.Param.ListItems->Items[j],&l.Items[j]); + } + di.Param.ListItems=&l; + } + + break; + } + case DI_USERCONTROL: + di.Param.VBuf = AnsiVBufToUnicode(diA); + break; + case DI_EDIT: + case DI_FIXEDIT: + { + if (diA.Flags&oldfar::DIF_HISTORY && diA.Param.History) + di.Param.History=AnsiToUnicode(diA.Param.History); + else if (diA.Flags&oldfar::DIF_MASKEDIT && diA.Param.Mask) + di.Param.Mask=AnsiToUnicode(diA.Param.Mask); + + break; + } + } + + if (diA.Type==oldfar::DI_USERCONTROL) + { + di.PtrData = (wchar_t*)malloc(sizeof(diA.Data.Data)); + + if (di.PtrData) memcpy((char*)di.PtrData,diA.Data.Data,sizeof(diA.Data.Data)); + + di.MaxLen = 0; + } + else if ((diA.Type==oldfar::DI_EDIT || diA.Type==oldfar::DI_COMBOBOX) && diA.Flags&oldfar::DIF_VAREDIT) + di.PtrData = AnsiToUnicode(diA.Data.Ptr.PtrData); + else + di.PtrData = AnsiToUnicode(diA.Data.Data); + + //BUGBUG тут надо придумать как сделать лучше: maxlen=513 например и также подумать что делать для DIF_VAREDIT + //di->MaxLen = 0; +} + +void FreeUnicodeDialogItem(FarDialogItem &di) +{ + switch (di.Type) + { + case DI_EDIT: + case DI_FIXEDIT: + + if ((di.Flags&DIF_HISTORY) && di.Param.History) + free((void *)di.Param.History); + else if ((di.Flags&DIF_MASKEDIT) && di.Param.Mask) + free((void *)di.Param.Mask); + + break; + case DI_LISTBOX: + case DI_COMBOBOX: + + if (di.Param.ListItems) + { + if (di.Param.ListItems->Items) + { + for (int i=0; i<di.Param.ListItems->ItemsNumber; i++) + { + if (di.Param.ListItems->Items[i].Text) + free((void *)di.Param.ListItems->Items[i].Text); + } + + free(di.Param.ListItems->Items); + di.Param.ListItems->Items=nullptr; + } + } + + break; + case DI_USERCONTROL: + + if (di.Param.VBuf) + free(di.Param.VBuf); + + break; + } + + if (di.PtrData) + free((void *)di.PtrData); +} + +void FreeAnsiDialogItem(oldfar::FarDialogItem &diA) +{ + if ((diA.Type==oldfar::DI_EDIT || diA.Type==oldfar::DI_FIXEDIT) && + (diA.Flags&oldfar::DIF_HISTORY ||diA.Flags&oldfar::DIF_MASKEDIT) && + diA.Param.History) + free((void*)diA.Param.History); + + if ((diA.Type==oldfar::DI_EDIT || diA.Type==oldfar::DI_COMBOBOX) && + diA.Flags&oldfar::DIF_VAREDIT && diA.Data.Ptr.PtrData) + free(diA.Data.Ptr.PtrData); + + memset(&diA,0,sizeof(oldfar::FarDialogItem)); +} + +void UnicodeDialogItemToAnsiSafe(FarDialogItem &di,oldfar::FarDialogItem &diA) +{ + switch (di.Type) + { + case DI_TEXT: + diA.Type=oldfar::DI_TEXT; + break; + case DI_VTEXT: + diA.Type=oldfar::DI_VTEXT; + break; + case DI_SINGLEBOX: + diA.Type=oldfar::DI_SINGLEBOX; + break; + case DI_DOUBLEBOX: + diA.Type=oldfar::DI_DOUBLEBOX; + break; + case DI_EDIT: + diA.Type=oldfar::DI_EDIT; + break; + case DI_PSWEDIT: + diA.Type=oldfar::DI_PSWEDIT; + break; + case DI_FIXEDIT: + diA.Type=oldfar::DI_FIXEDIT; + break; + case DI_BUTTON: + diA.Type=oldfar::DI_BUTTON; + diA.Param.Selected=di.Param.Selected; + break; + case DI_CHECKBOX: + diA.Type=oldfar::DI_CHECKBOX; + diA.Param.Selected=di.Param.Selected; + break; + case DI_RADIOBUTTON: + diA.Type=oldfar::DI_RADIOBUTTON; + diA.Param.Selected=di.Param.Selected; + break; + case DI_COMBOBOX: + diA.Type=oldfar::DI_COMBOBOX; + diA.Param.ListPos=di.Param.ListPos; + break; + case DI_LISTBOX: + diA.Type=oldfar::DI_LISTBOX; + diA.Param.ListPos=di.Param.ListPos; + break; + case DI_MEMOEDIT: + diA.Type=oldfar::DI_MEMOEDIT; + break; + case DI_USERCONTROL: + diA.Type=oldfar::DI_USERCONTROL; + break; + } + + diA.X1=di.X1; + diA.Y1=di.Y1; + diA.X2=di.X2; + diA.Y2=di.Y2; + diA.Focus=di.Focus; + diA.Flags=0; + + if (di.Flags) + { + if (di.Flags&DIF_SETCOLOR) + diA.Flags|=oldfar::DIF_SETCOLOR|(di.Flags&DIF_COLORMASK); + + if (di.Flags&DIF_BOXCOLOR) + diA.Flags|=oldfar::DIF_BOXCOLOR; + + if (di.Flags&DIF_GROUP) + diA.Flags|=oldfar::DIF_GROUP; + + if (di.Flags&DIF_LEFTTEXT) + diA.Flags|=oldfar::DIF_LEFTTEXT; + + if (di.Flags&DIF_MOVESELECT) + diA.Flags|=oldfar::DIF_MOVESELECT; + + if (di.Flags&DIF_SHOWAMPERSAND) + diA.Flags|=oldfar::DIF_SHOWAMPERSAND; + + if (di.Flags&DIF_CENTERGROUP) + diA.Flags|=oldfar::DIF_CENTERGROUP; + + if (di.Flags&DIF_NOBRACKETS) + diA.Flags|=oldfar::DIF_NOBRACKETS; + + if (di.Flags&DIF_MANUALADDHISTORY) + diA.Flags|=oldfar::DIF_MANUALADDHISTORY; + + if (di.Flags&DIF_SEPARATOR) + diA.Flags|=oldfar::DIF_SEPARATOR; + + if (di.Flags&DIF_SEPARATOR2) + diA.Flags|=oldfar::DIF_SEPARATOR2; + + if (di.Flags&DIF_EDITOR) + diA.Flags|=oldfar::DIF_EDITOR; + + if (di.Flags&DIF_LISTNOAMPERSAND) + diA.Flags|=oldfar::DIF_LISTNOAMPERSAND; + + if (di.Flags&DIF_LISTNOBOX) + diA.Flags|=oldfar::DIF_LISTNOBOX; + + if (di.Flags&DIF_HISTORY) + diA.Flags|=oldfar::DIF_HISTORY; + + if (di.Flags&DIF_BTNNOCLOSE) + diA.Flags|=oldfar::DIF_BTNNOCLOSE; + + if (di.Flags&DIF_CENTERTEXT) + diA.Flags|=oldfar::DIF_CENTERTEXT; + + if (di.Flags&DIF_SEPARATORUSER) + diA.Flags|=oldfar::DIF_SEPARATORUSER; + + if (di.Flags&DIF_EDITEXPAND) + diA.Flags|=oldfar::DIF_EDITEXPAND; + + if (di.Flags&DIF_DROPDOWNLIST) + diA.Flags|=oldfar::DIF_DROPDOWNLIST; + + if (di.Flags&DIF_USELASTHISTORY) + diA.Flags|=oldfar::DIF_USELASTHISTORY; + + if (di.Flags&DIF_MASKEDIT) + diA.Flags|=oldfar::DIF_MASKEDIT; + + if (di.Flags&DIF_SELECTONENTRY) + diA.Flags|=oldfar::DIF_SELECTONENTRY; + + if (di.Flags&DIF_3STATE) + diA.Flags|=oldfar::DIF_3STATE; + + if (di.Flags&DIF_EDITPATH) + diA.Flags|=oldfar::DIF_EDITPATH; + + if (di.Flags&DIF_LISTWRAPMODE) + diA.Flags|=oldfar::DIF_LISTWRAPMODE; + + if (di.Flags&DIF_LISTAUTOHIGHLIGHT) + diA.Flags|=oldfar::DIF_LISTAUTOHIGHLIGHT; + + if (di.Flags&DIF_AUTOMATION) + diA.Flags|=oldfar::DIF_AUTOMATION; + + if (di.Flags&DIF_HIDDEN) + diA.Flags|=oldfar::DIF_HIDDEN; + + if (di.Flags&DIF_READONLY) + diA.Flags|=oldfar::DIF_READONLY; + + if (di.Flags&DIF_NOFOCUS) + diA.Flags|=oldfar::DIF_NOFOCUS; + + if (di.Flags&DIF_DISABLE) + diA.Flags|=oldfar::DIF_DISABLE; + } + + diA.DefaultButton=di.DefaultButton; +} + +oldfar::FarDialogItem* UnicodeDialogItemToAnsi(FarDialogItem &di,HANDLE hDlg,int ItemNumber) +{ + oldfar::FarDialogItem *diA=CurrentDialogItemA(hDlg,ItemNumber); + + if (!diA) + { + if (OneDialogItem) + free(OneDialogItem); + + OneDialogItem=(oldfar::FarDialogItem*)malloc(sizeof(oldfar::FarDialogItem)); + memset(OneDialogItem,0,sizeof(oldfar::FarDialogItem)); + diA=OneDialogItem; + } + + FreeAnsiDialogItem(*diA); + UnicodeDialogItemToAnsiSafe(di,*diA); + + switch (diA->Type) + { + case oldfar::DI_USERCONTROL: + diA->Param.VBuf=GetAnsiVBufPtr(di.Param.VBuf, GetAnsiVBufSize(*diA)); + break; + case oldfar::DI_EDIT: + case oldfar::DI_FIXEDIT: + { + if (di.Flags&DIF_HISTORY) + diA->Param.History=UnicodeToAnsi(di.Param.History); + else if (di.Flags&DIF_MASKEDIT) + diA->Param.Mask=UnicodeToAnsi(di.Param.Mask); + } + break; + } + + if (diA->Type==oldfar::DI_USERCONTROL) + { + if (di.PtrData) memcpy(diA->Data.Data,(char*)di.PtrData,sizeof(diA->Data.Data)); + } + else if ((diA->Type==oldfar::DI_EDIT || diA->Type==oldfar::DI_COMBOBOX) && diA->Flags&oldfar::DIF_VAREDIT) + { + diA->Data.Ptr.PtrLength=StrLength(di.PtrData); + diA->Data.Ptr.PtrData=(char*)malloc(4 * (diA->Data.Ptr.PtrLength+1)); + PWZ_to_PZ(di.PtrData,diA->Data.Ptr.PtrData, 4 *(diA->Data.Ptr.PtrLength+1)); + } + else + PWZ_to_PZ(di.PtrData,diA->Data.Data,sizeof(diA->Data.Data)); + + return diA; +} + +LONG_PTR WINAPI DlgProcA(HANDLE hDlg, int Msg, int Param1, LONG_PTR Param2) +{ + static wchar_t* HelpTopic = nullptr; + + switch (Msg) + { + case DN_LISTHOTKEY: Msg=oldfar::DN_LISTHOTKEY; break; + case DN_BTNCLICK: Msg=oldfar::DN_BTNCLICK; break; + case DN_CTLCOLORDIALOG: Msg=oldfar::DN_CTLCOLORDIALOG; break; + case DN_CTLCOLORDLGITEM: Msg=oldfar::DN_CTLCOLORDLGITEM; break; + case DN_CTLCOLORDLGLIST: Msg=oldfar::DN_CTLCOLORDLGLIST; break; + case DN_DRAWDIALOG: Msg=oldfar::DN_DRAWDIALOG; break; + case DN_DRAWDLGITEM: + { + Msg=oldfar::DN_DRAWDLGITEM; + FarDialogItem *di = (FarDialogItem *)Param2; + oldfar::FarDialogItem *FarDiA=UnicodeDialogItemToAnsi(*di,hDlg,Param1); + LONG_PTR ret = CurrentDlgProc(hDlg, Msg, Param1, (LONG_PTR)FarDiA); + + if (ret && (di->Type==DI_USERCONTROL) && (di->Param.VBuf)) + { + AnsiVBufToUnicode(FarDiA->Param.VBuf, di->Param.VBuf, GetAnsiVBufSize(*FarDiA),(FarDiA->Flags&oldfar::DIF_NOTCVTUSERCONTROL)==oldfar::DIF_NOTCVTUSERCONTROL); + } + + return ret; + } + case DN_EDITCHANGE: + Msg=oldfar::DN_EDITCHANGE; + return Param2?CurrentDlgProc(hDlg,Msg,Param1,(LONG_PTR)UnicodeDialogItemToAnsi(*((FarDialogItem *)Param2),hDlg,Param1)):FALSE; + case DN_ENTERIDLE: Msg=oldfar::DN_ENTERIDLE; break; + case DN_GOTFOCUS: Msg=oldfar::DN_GOTFOCUS; break; + case DN_HELP: + { + char* HelpTopicA = UnicodeToAnsi((const wchar_t *)Param2); + LONG_PTR ret = CurrentDlgProc(hDlg, oldfar::DN_HELP, Param1, (LONG_PTR)HelpTopicA); + + if (ret) + { + if (HelpTopic) free(HelpTopic); + + HelpTopic = AnsiToUnicode((const char *)ret); + ret = (LONG_PTR)HelpTopic; + } + + free(HelpTopicA); + return ret; + } + case DN_HOTKEY: + Msg=oldfar::DN_HOTKEY; + break; + case DN_INITDIALOG: + Msg=oldfar::DN_INITDIALOG; + break; + case DN_KILLFOCUS: Msg=oldfar::DN_KILLFOCUS; break; + case DN_LISTCHANGE: Msg=oldfar::DN_LISTCHANGE; break; + case DN_MOUSECLICK: Msg=oldfar::DN_MOUSECLICK; break; + case DN_DRAGGED: Msg=oldfar::DN_DRAGGED; break; + case DN_RESIZECONSOLE: Msg=oldfar::DN_RESIZECONSOLE; break; + case DN_MOUSEEVENT: Msg=oldfar::DN_MOUSEEVENT; break; + case DN_DRAWDIALOGDONE: Msg=oldfar::DN_DRAWDIALOGDONE; break; + case DM_KILLSAVESCREEN: Msg=oldfar::DM_KILLSAVESCREEN; break; + case DM_ALLKEYMODE: Msg=oldfar::DM_ALLKEYMODE; break; + case DN_ACTIVATEAPP: Msg=oldfar::DN_ACTIVATEAPP; break; + case DN_KEY: + Msg=oldfar::DN_KEY; + Param2=KeyToOldKey((DWORD)Param2); + break; + } + + return CurrentDlgProc(hDlg, Msg, Param1, Param2); +} + +LONG_PTR WINAPI FarDefDlgProcA(HANDLE hDlg, int Msg, int Param1, LONG_PTR Param2) +{ + return FarDefDlgProc(hDlg, Msg, Param1, Param2); +} + +LONG_PTR WINAPI FarSendDlgMessageA(HANDLE hDlg, int Msg, int Param1, LONG_PTR Param2) +{ + switch (Msg) + { + case oldfar::DM_CLOSE: Msg = DM_CLOSE; break; + case oldfar::DM_ENABLE: Msg = DM_ENABLE; break; + case oldfar::DM_ENABLEREDRAW: Msg = DM_ENABLEREDRAW; break; + case oldfar::DM_GETDLGDATA: Msg = DM_GETDLGDATA; break; + case oldfar::DM_GETDLGITEM: + { + size_t item_size=FarSendDlgMessage(hDlg, DM_GETDLGITEM, Param1, 0); + + if (item_size) + { + FarDialogItem *di = (FarDialogItem *)malloc(item_size); + + if (di) + { + FarSendDlgMessage(hDlg, DM_GETDLGITEM, Param1, (LONG_PTR)di); + oldfar::FarDialogItem *FarDiA=UnicodeDialogItemToAnsi(*di,hDlg,Param1); + free(di); + *reinterpret_cast<oldfar::FarDialogItem*>(Param2)=*FarDiA; + return TRUE; + } + } + + return FALSE; + } + case oldfar::DM_GETDLGRECT: Msg = DM_GETDLGRECT; break; + case oldfar::DM_GETTEXT: + { + if (!Param2) + return FarSendDlgMessage(hDlg, DM_GETTEXT, Param1, 0); + + oldfar::FarDialogItemData* didA = (oldfar::FarDialogItemData*)Param2; + if (!didA->PtrLength) //вот такой хреновый API!!! + didA->PtrLength = static_cast<int>(FarSendDlgMessage(hDlg, DM_GETTEXT, Param1, 0)); + wchar_t* text = (wchar_t*) malloc((didA->PtrLength+1)*sizeof(wchar_t)); + //BUGBUG: если didA->PtrLength=0, то вернётся с учётом '\0', в Энц написано, что без, хз как правильно. + FarDialogItemData did = {(size_t)didA->PtrLength, text}; + LONG_PTR ret = FarSendDlgMessage(hDlg, DM_GETTEXT, Param1, (LONG_PTR)&did); + didA->PtrLength = (unsigned)did.PtrLength; + PWZ_to_PZ(text,didA->PtrData,didA->PtrLength+1); + free(text); + return ret; + } + case oldfar::DM_GETTEXTLENGTH: Msg = DM_GETTEXTLENGTH; break; + case oldfar::DM_KEY: + { + if (!Param1 || !Param2) return FALSE; + + int Count = (int)Param1; + DWORD* KeysA = (DWORD*)Param2; + DWORD* KeysW = (DWORD*)malloc(Count*sizeof(DWORD)); + + for (int i=0; i<Count; i++) + { + KeysW[i]=OldKeyToKey(KeysA[i]); + } + + LONG_PTR ret = FarSendDlgMessage(hDlg, DM_KEY, Param1, (LONG_PTR)KeysW); + free(KeysW); + return ret; + } + case oldfar::DM_MOVEDIALOG: Msg = DM_MOVEDIALOG; break; + case oldfar::DM_SETDLGDATA: Msg = DM_SETDLGDATA; break; + case oldfar::DM_SETDLGITEM: + { + if (!Param2) + return FALSE; + + FarDialogItem *di=CurrentDialogItem(hDlg,Param1); + + if (di->Type==DI_LISTBOX || di->Type==DI_COMBOBOX) + di->Param.ListItems=CurrentList(hDlg,Param1); + + FreeUnicodeDialogItem(*di); + oldfar::FarDialogItem *diA = (oldfar::FarDialogItem *)Param2; + AnsiDialogItemToUnicode(*diA,*di,*di->Param.ListItems); + return FarSendDlgMessage(hDlg, DM_SETDLGITEM, Param1, (LONG_PTR)di); + } + case oldfar::DM_SETFOCUS: Msg = DM_SETFOCUS; break; + case oldfar::DM_REDRAW: Msg = DM_REDRAW; break; + case oldfar::DM_SETTEXT: + { + if (!Param2)return 0; + + oldfar::FarDialogItemData* didA = (oldfar::FarDialogItemData*)Param2; + + if (!didA->PtrData) return 0; + + wchar_t* text = AnsiToUnicode(didA->PtrData); + //BUGBUG - PtrLength ни на что не влияет. + FarDialogItemData di = {(size_t)didA->PtrLength,text}; + LONG_PTR ret = FarSendDlgMessage(hDlg, DM_SETTEXT, Param1, (LONG_PTR)&di); + free(text); + return ret; + } + case oldfar::DM_SETMAXTEXTLENGTH: Msg = DM_SETMAXTEXTLENGTH; break; + case oldfar::DM_SHOWDIALOG: Msg = DM_SHOWDIALOG; break; + case oldfar::DM_GETFOCUS: Msg = DM_GETFOCUS; break; + case oldfar::DM_GETCURSORPOS: Msg = DM_GETCURSORPOS; break; + case oldfar::DM_SETCURSORPOS: Msg = DM_SETCURSORPOS; break; + case oldfar::DM_GETTEXTPTR: + { + LONG_PTR length = FarSendDlgMessage(hDlg, DM_GETTEXTPTR, Param1, 0); + + //if (!Param2) return length; + + wchar_t* text = (wchar_t *) malloc((length +1)* sizeof(wchar_t)); + length = FarSendDlgMessage(hDlg, DM_GETTEXTPTR, Param1, (LONG_PTR)text); + length = PWZ_to_PZ(text, (char *)Param2, Param2 ? length+1 : 0); + free(text); + return length + 1; + } + case oldfar::DM_SETTEXTPTR: + { + if (!Param2) return FALSE; + + wchar_t* text = AnsiToUnicode((char*)Param2); + LONG_PTR ret = FarSendDlgMessage(hDlg, DM_SETTEXTPTR, Param1, (LONG_PTR)text); + free(text); + return ret; + } + case oldfar::DM_SHOWITEM: Msg = DM_SHOWITEM; break; + case oldfar::DM_ADDHISTORY: + { + if (!Param2) return FALSE; + + wchar_t* history = AnsiToUnicode((char*)Param2); + LONG_PTR ret = FarSendDlgMessage(hDlg, DM_ADDHISTORY, Param1, (LONG_PTR)history); + free(history); + return ret; + } + case oldfar::DM_GETCHECK: + { + LONG_PTR ret = FarSendDlgMessage(hDlg, DM_GETCHECK, Param1, 0); + LONG_PTR state = 0; + + if (ret == oldfar::BSTATE_UNCHECKED) state=BSTATE_UNCHECKED; + else if (ret == oldfar::BSTATE_CHECKED) state=BSTATE_CHECKED; + else if (ret == oldfar::BSTATE_3STATE) state=BSTATE_3STATE; + + return state; + } + case oldfar::DM_SETCHECK: + { + LONG_PTR state = 0; + + if (Param2 == oldfar::BSTATE_UNCHECKED) state=BSTATE_UNCHECKED; + else if (Param2 == oldfar::BSTATE_CHECKED) state=BSTATE_CHECKED; + else if (Param2 == oldfar::BSTATE_3STATE) state=BSTATE_3STATE; + else if (Param2 == oldfar::BSTATE_TOGGLE) state=BSTATE_TOGGLE; + + return FarSendDlgMessage(hDlg, DM_SETCHECK, Param1, state); + } + case oldfar::DM_SET3STATE: Msg = DM_SET3STATE; break; + case oldfar::DM_LISTSORT: Msg = DM_LISTSORT; break; + case oldfar::DM_LISTGETITEM: //BUGBUG, недоделано в фаре + { + if (!Param2) return FALSE; + + oldfar::FarListGetItem* lgiA = (oldfar::FarListGetItem*)Param2; + FarListGetItem lgi = {lgiA->ItemIndex}; + LONG_PTR ret = FarSendDlgMessage(hDlg, DM_LISTGETITEM, Param1, (LONG_PTR)&lgi); + UnicodeListItemToAnsi(&lgi.Item, &lgiA->Item); + return ret; + } + case oldfar::DM_LISTGETCURPOS: + + if (Param2) + { + FarListPos lp; + LONG_PTR ret=FarSendDlgMessage(hDlg, DM_LISTGETCURPOS, Param1, (LONG_PTR)&lp); + oldfar::FarListPos *lpA = (oldfar::FarListPos *)Param2; + lpA->SelectPos=lp.SelectPos; + lpA->TopPos=lp.TopPos; + return ret; + } + else return FarSendDlgMessage(hDlg, DM_LISTGETCURPOS, Param1, 0); + + case oldfar::DM_LISTSETCURPOS: + { + if (!Param2) return FALSE; + + oldfar::FarListPos *lpA = (oldfar::FarListPos *)Param2; + FarListPos lp = {lpA->SelectPos,lpA->TopPos}; + return FarSendDlgMessage(hDlg, DM_LISTSETCURPOS, Param1, (LONG_PTR)&lp); + } + case oldfar::DM_LISTDELETE: + { + oldfar::FarListDelete *ldA = (oldfar::FarListDelete *)Param2; + FarListDelete ld; + + if (Param2) + { + ld.Count = ldA->Count; + ld.StartIndex = ldA->StartIndex; + } + + return FarSendDlgMessage(hDlg, DM_LISTDELETE, Param1, Param2?(LONG_PTR)&ld:0); + } + case oldfar::DM_LISTADD: + { + FarList newlist = {0,0}; + + if (Param2) + { + oldfar::FarList *oldlist = (oldfar::FarList*) Param2; + newlist.ItemsNumber = oldlist->ItemsNumber; + + if (newlist.ItemsNumber) + { + newlist.Items = (FarListItem*)malloc(newlist.ItemsNumber*sizeof(FarListItem)); + + if (newlist.Items) + { + for (int i=0; i<newlist.ItemsNumber; i++) + AnsiListItemToUnicode(&oldlist->Items[i], &newlist.Items[i]); + } + } + } + + LONG_PTR ret = FarSendDlgMessage(hDlg, DM_LISTADD, Param1, Param2?(LONG_PTR)&newlist:0); + + if (newlist.Items) + { + for (int i=0; i<newlist.ItemsNumber; i++) + if (newlist.Items[i].Text) free((void*)newlist.Items[i].Text); + + free(newlist.Items); + } + + return ret; + } + case oldfar::DM_LISTADDSTR: + { + wchar_t* newstr = nullptr; + + if (Param2) + { + newstr = AnsiToUnicode((char*)Param2); + } + + LONG_PTR ret = FarSendDlgMessage(hDlg, DM_LISTADDSTR, Param1, (LONG_PTR)newstr); + + if (newstr) free(newstr); + + return ret; + } + case oldfar::DM_LISTUPDATE: + { + FarListUpdate newui{}; + + if (Param2) + { + oldfar::FarListUpdate *oldui = (oldfar::FarListUpdate*) Param2; + newui.Index=oldui->Index; + AnsiListItemToUnicode(&oldui->Item, &newui.Item); + } + + LONG_PTR ret = FarSendDlgMessage(hDlg, DM_LISTUPDATE, Param1, Param2?(LONG_PTR)&newui:0); + + if (newui.Item.Text) free((void*)newui.Item.Text); + + return ret; + } + case oldfar::DM_LISTINSERT: + { + FarListInsert newli{}; + + if (Param2) + { + oldfar::FarListInsert *oldli = (oldfar::FarListInsert*) Param2; + newli.Index=oldli->Index; + AnsiListItemToUnicode(&oldli->Item, &newli.Item); + } + + LONG_PTR ret = FarSendDlgMessage(hDlg, DM_LISTINSERT, Param1, Param2?(LONG_PTR)&newli:0); + + if (newli.Item.Text) free((void*)newli.Item.Text); + + return ret; + } + case oldfar::DM_LISTFINDSTRING: + { + FarListFind newlf = {0,0,0,0}; + + if (Param2) + { + oldfar::FarListFind *oldlf = (oldfar::FarListFind*) Param2; + newlf.StartIndex=oldlf->StartIndex; + newlf.Pattern = (oldlf->Pattern)?AnsiToUnicode(oldlf->Pattern):nullptr; + + if (oldlf->Flags&oldfar::LIFIND_EXACTMATCH) newlf.Flags|=LIFIND_EXACTMATCH; + } + + LONG_PTR ret = FarSendDlgMessage(hDlg, DM_LISTFINDSTRING, Param1, Param2?(LONG_PTR)&newlf:0); + + if (newlf.Pattern) free((void*)newlf.Pattern); + + return ret; + } + case oldfar::DM_LISTINFO: + { + if (!Param2) return FALSE; + + oldfar::FarListInfo *liA = (oldfar::FarListInfo *)Param2; + FarListInfo li={0,liA->ItemsNumber,liA->SelectPos,liA->TopPos,liA->MaxHeight,liA->MaxLength}; + + if (liA ->Flags&oldfar::LINFO_SHOWNOBOX) li.Flags|=LINFO_SHOWNOBOX; + + if (liA ->Flags&oldfar::LINFO_AUTOHIGHLIGHT) li.Flags|=LINFO_AUTOHIGHLIGHT; + + if (liA ->Flags&oldfar::LINFO_REVERSEHIGHLIGHT) li.Flags|=LINFO_REVERSEHIGHLIGHT; + + if (liA ->Flags&oldfar::LINFO_WRAPMODE) li.Flags|=LINFO_WRAPMODE; + + if (liA ->Flags&oldfar::LINFO_SHOWAMPERSAND) li.Flags|=LINFO_SHOWAMPERSAND; + + return FarSendDlgMessage(hDlg, DM_LISTINFO, Param1, Param2); + } + case oldfar::DM_LISTGETDATA: Msg = DM_LISTGETDATA; break; + case oldfar::DM_LISTSETDATA: + { + FarListItemData newlid = {0,0,0,0}; + + if (Param2) + { + oldfar::FarListItemData *oldlid = (oldfar::FarListItemData*) Param2; + newlid.Index=oldlid->Index; + newlid.DataSize=oldlid->DataSize; + newlid.Data=oldlid->Data; + } + + LONG_PTR ret = FarSendDlgMessage(hDlg, DM_LISTSETDATA, Param1, Param2?(LONG_PTR)&newlid:0); + return ret; + } + case oldfar::DM_LISTSETTITLES: + { + if (!Param2) return FALSE; + + oldfar::FarListTitles *ltA = (oldfar::FarListTitles *)Param2; + FarListTitles lt = {0,ltA->Title?AnsiToUnicode(ltA->Title):nullptr,0,ltA->Bottom?AnsiToUnicode(ltA->Bottom):nullptr}; + Param2 = (LONG_PTR)< + LONG_PTR ret = FarSendDlgMessage(hDlg, DM_LISTSETTITLES, Param1, Param2); + + if (lt.Bottom) free((wchar_t *)lt.Bottom); + + if (lt.Title) free((wchar_t *)lt.Title); + + return ret; + } + case oldfar::DM_LISTGETTITLES: + { + if (Param2) + { + oldfar::FarListTitles *OldListTitle=(oldfar::FarListTitles *)Param2; + FarListTitles ListTitle={0,nullptr,0,nullptr}; + + if (OldListTitle->Title) + { + ListTitle.TitleLen=OldListTitle->TitleLen; + ListTitle.Title=(wchar_t *)malloc(sizeof(wchar_t)*ListTitle.TitleLen); + } + + if (OldListTitle->BottomLen) + { + ListTitle.BottomLen=OldListTitle->BottomLen; + ListTitle.Bottom=(wchar_t *)malloc(sizeof(wchar_t)*ListTitle.BottomLen); + } + + LONG_PTR Ret=FarSendDlgMessage(hDlg,DM_LISTGETTITLES,Param1,(LONG_PTR)&ListTitle); + + if (Ret) + { + PWZ_to_PZ(ListTitle.Title,OldListTitle->Title,OldListTitle->TitleLen); + PWZ_to_PZ(ListTitle.Bottom,OldListTitle->Bottom,OldListTitle->BottomLen); + } + + if (ListTitle.Title) + free((wchar_t *)ListTitle.Title); + + if (ListTitle.Bottom) + free((wchar_t *)ListTitle.Bottom); + + return Ret; + } + + return FALSE; + } + case oldfar::DM_RESIZEDIALOG: Msg = DM_RESIZEDIALOG; break; + case oldfar::DM_SETITEMPOSITION: Msg = DM_SETITEMPOSITION; break; + case oldfar::DM_GETDROPDOWNOPENED: Msg = DM_GETDROPDOWNOPENED; break; + case oldfar::DM_SETDROPDOWNOPENED: Msg = DM_SETDROPDOWNOPENED; break; + case oldfar::DM_SETHISTORY: + + if (!Param2) + return FarSendDlgMessage(hDlg, DM_SETHISTORY, Param1, 0); + else + { + FarDialogItem *di=CurrentDialogItem(hDlg,Param1); + free((void*)di->Param.History); + di->Param.History = AnsiToUnicode((const char *)Param2); + return FarSendDlgMessage(hDlg, DM_SETHISTORY, Param1, (LONG_PTR)di->Param.History); + } + + case oldfar::DM_GETITEMPOSITION: Msg = DM_GETITEMPOSITION; break; + case oldfar::DM_SETMOUSEEVENTNOTIFY: Msg = DM_SETMOUSEEVENTNOTIFY; break; + case oldfar::DM_EDITUNCHANGEDFLAG: Msg = DM_EDITUNCHANGEDFLAG; break; + case oldfar::DM_GETITEMDATA: Msg = DM_GETITEMDATA; break; + case oldfar::DM_SETITEMDATA: Msg = DM_SETITEMDATA; break; + case oldfar::DM_LISTSET: + { + FarList newlist = {0,0}; + + if (Param2) + { + oldfar::FarList *oldlist = (oldfar::FarList*) Param2; + newlist.ItemsNumber = oldlist->ItemsNumber; + + if (newlist.ItemsNumber) + { + newlist.Items = (FarListItem*)malloc(newlist.ItemsNumber*sizeof(FarListItem)); + + if (newlist.Items) + { + for (int i=0; i<newlist.ItemsNumber; i++) + AnsiListItemToUnicode(&oldlist->Items[i], &newlist.Items[i]); + } + } + } + + LONG_PTR ret = FarSendDlgMessage(hDlg, DM_LISTSET, Param1, Param2?(LONG_PTR)&newlist:0); + + if (newlist.Items) + { + for (int i=0; i<newlist.ItemsNumber; i++) + if (newlist.Items[i].Text) free((void*)newlist.Items[i].Text); + + free(newlist.Items); + } + + return ret; + } + case oldfar::DM_LISTSETMOUSEREACTION: + { + LONG_PTR type=0; + + if (Param2 == oldfar::LMRT_ONLYFOCUS) type=LMRT_ONLYFOCUS; + else if (Param2 == oldfar::LMRT_ALWAYS) type=LMRT_ALWAYS; + else if (Param2 == oldfar::LMRT_NEVER) type=LMRT_NEVER; + + return FarSendDlgMessage(hDlg, DM_LISTSETMOUSEREACTION, Param1, type); + } + case oldfar::DM_GETCURSORSIZE: Msg = DM_GETCURSORSIZE; break; + case oldfar::DM_SETCURSORSIZE: Msg = DM_SETCURSORSIZE; break; + case oldfar::DM_LISTGETDATASIZE: Msg = DM_LISTGETDATASIZE; break; + case oldfar::DM_GETSELECTION: + { + if (!Param2) return FALSE; + + EditorSelect es; + LONG_PTR ret=FarSendDlgMessage(hDlg, DM_GETSELECTION, Param1, (LONG_PTR)&es); + oldfar::EditorSelect *esA = (oldfar::EditorSelect *)Param2; + esA->BlockType = es.BlockType; + esA->BlockStartLine = es.BlockStartLine; + esA->BlockStartPos = es.BlockStartPos; + esA->BlockWidth = es.BlockWidth; + esA->BlockHeight = es.BlockHeight; + return ret; + } + case oldfar::DM_SETSELECTION: + { + if (!Param2) return FALSE; + + oldfar::EditorSelect *esA = (oldfar::EditorSelect *)Param2; + EditorSelect es; + es.BlockType = esA->BlockType; + es.BlockStartLine = esA->BlockStartLine; + es.BlockStartPos = esA->BlockStartPos; + es.BlockWidth = esA->BlockWidth; + es.BlockHeight = esA->BlockHeight; + return FarSendDlgMessage(hDlg, DM_SETSELECTION, Param1, (LONG_PTR)&es); + } + case oldfar::DM_GETEDITPOSITION: + Msg=DM_GETEDITPOSITION; + break; + case oldfar::DM_SETEDITPOSITION: + Msg=DM_SETEDITPOSITION; + break; + case oldfar::DM_SETCOMBOBOXEVENT: + Msg=DM_SETCOMBOBOXEVENT; + break; + case oldfar::DM_GETCOMBOBOXEVENT: + Msg=DM_GETCOMBOBOXEVENT; + break; + case oldfar::DM_KILLSAVESCREEN: + case oldfar::DM_ALLKEYMODE: + case oldfar::DN_ACTIVATEAPP: + break; + } + + return FarSendDlgMessage(hDlg, Msg, Param1, Param2); +} + +int WINAPI FarDialogExA(INT_PTR PluginNumber,int X1,int Y1,int X2,int Y2,const char *HelpTopic,oldfar::FarDialogItem *Item,int ItemsNumber,DWORD Reserved,DWORD Flags,oldfar::FARWINDOWPROC DlgProc,LONG_PTR Param) +{ + FARString strHT(HelpTopic); + + if (!Item || !ItemsNumber) + return -1; + + oldfar::FarDialogItem* diA=new oldfar::FarDialogItem[ItemsNumber](); + FarDialogItem* di = new FarDialogItem[ItemsNumber](); + FarList* l = new FarList[ItemsNumber](); + + for (int i=0; i<ItemsNumber; i++) + { + AnsiDialogItemToUnicode(Item[i],di[i],l[i]); + } + + DWORD DlgFlags = 0; + + if (Flags&oldfar::FDLG_WARNING) DlgFlags|=FDLG_WARNING; + + if (Flags&oldfar::FDLG_SMALLDIALOG) DlgFlags|=FDLG_SMALLDIALOG; + + if (Flags&oldfar::FDLG_NODRAWSHADOW) DlgFlags|=FDLG_NODRAWSHADOW; + + if (Flags&oldfar::FDLG_NODRAWPANEL) DlgFlags|=FDLG_NODRAWPANEL; + + if (Flags&oldfar::FDLG_NONMODAL) DlgFlags|=FDLG_NONMODAL; + + if (Flags&oldfar::FDLG_KEEPCONSOLETITLE) DlgFlags|=FDLG_KEEPCONSOLETITLE; + + if (Flags&oldfar::FDLG_REGULARIDLE) DlgFlags|=FDLG_REGULARIDLE; + + int ret = -1; + HANDLE hDlg = FarDialogInit(PluginNumber, X1, Y1, X2, Y2, (HelpTopic?strHT.CPtr():nullptr), (FarDialogItem *)di, ItemsNumber, 0, DlgFlags, DlgProc?DlgProcA:0, Param); + PDialogData NewDialogData=new DialogData; + NewDialogData->DlgProc=DlgProc; + NewDialogData->hDlg=hDlg; + NewDialogData->diA=diA; + NewDialogData->di=di; + NewDialogData->l=l; + DialogList.Push(&NewDialogData); + + if (hDlg != INVALID_HANDLE_VALUE) + { + ret = FarDialogRun(hDlg); + + for (int i=0; i<ItemsNumber; i++) + { + FarDialogItem *pdi = (FarDialogItem *)malloc(FarSendDlgMessage(hDlg, DM_GETDLGITEM, i, 0)); + + if (pdi) + { + FarSendDlgMessage(hDlg, DM_GETDLGITEM, i, (LONG_PTR)pdi); + UnicodeDialogItemToAnsiSafe(*pdi,Item[i]); + const wchar_t *res = pdi->PtrData; + + if (!res) res = L""; + + if ((di[i].Type==DI_EDIT || di[i].Type==DI_COMBOBOX) && Item[i].Flags&oldfar::DIF_VAREDIT) + PWZ_to_PZ(res, Item[i].Data.Ptr.PtrData, Item[i].Data.Ptr.PtrLength+1); + else + PWZ_to_PZ(res, Item[i].Data.Data, sizeof(Item[i].Data.Data)); + + if (pdi->Type==DI_USERCONTROL) + { + di[i].Param.VBuf=pdi->Param.VBuf; + Item[i].Param.VBuf=GetAnsiVBufPtr(pdi->Param.VBuf,GetAnsiVBufSize(Item[i])); + } + + free(pdi); + } + + FreeAnsiDialogItem(diA[i]); + } + + FarDialogFree(hDlg); + + for (int i=0; i<ItemsNumber; i++) + { + if (di[i].Type==DI_LISTBOX || di[i].Type==DI_COMBOBOX) + di[i].Param.ListItems=CurrentList(hDlg,i); + } + } + + for (int i=0; i<ItemsNumber; i++) + { + FreeUnicodeDialogItem(di[i]); + } + + for(PDialogData* i=DialogList.Last();i;i=DialogList.Prev(i)) + { + if((*i)->hDlg==hDlg) + { + delete *i; + DialogList.Delete(i); + break; + } + } + + delete[] diA; + delete[] di; + delete[] l; + + return ret; +} + +int WINAPI FarDialogFnA(INT_PTR PluginNumber,int X1,int Y1,int X2,int Y2,const char *HelpTopic,oldfar::FarDialogItem *Item,int ItemsNumber) +{ + return FarDialogExA(PluginNumber, X1, Y1, X2, Y2, HelpTopic, Item, ItemsNumber, 0, 0, 0, 0); +} + +void ConvertUnicodePanelInfoToAnsi(PanelInfo* PIW, oldfar::PanelInfo* PIA) +{ + PIA->PanelType = 0; + + switch (PIW->PanelType) + { + case PTYPE_FILEPANEL: PIA->PanelType = oldfar::PTYPE_FILEPANEL; break; + case PTYPE_TREEPANEL: PIA->PanelType = oldfar::PTYPE_TREEPANEL; break; + case PTYPE_QVIEWPANEL: PIA->PanelType = oldfar::PTYPE_QVIEWPANEL; break; + case PTYPE_INFOPANEL: PIA->PanelType = oldfar::PTYPE_INFOPANEL; break; + } + + PIA->Plugin = PIW->Plugin; + PIA->PanelRect.left = PIW->PanelRect.left; + PIA->PanelRect.top = PIW->PanelRect.top; + PIA->PanelRect.right = PIW->PanelRect.right; + PIA->PanelRect.bottom = PIW->PanelRect.bottom; + PIA->ItemsNumber = PIW->ItemsNumber; + PIA->SelectedItemsNumber = PIW->SelectedItemsNumber; + PIA->PanelItems = nullptr; + PIA->SelectedItems = nullptr; + PIA->CurrentItem = PIW->CurrentItem; + PIA->TopPanelItem = PIW->TopPanelItem; + PIA->Visible = PIW->Visible; + PIA->Focus = PIW->Focus; + PIA->ViewMode = PIW->ViewMode; + PIA->SortMode = 0; + + switch (PIW->SortMode) + { + case SM_DEFAULT: PIA->SortMode = oldfar::SM_DEFAULT; break; + case SM_UNSORTED: PIA->SortMode = oldfar::SM_UNSORTED; break; + case SM_NAME: PIA->SortMode = oldfar::SM_NAME; break; + case SM_EXT: PIA->SortMode = oldfar::SM_EXT; break; + case SM_MTIME: PIA->SortMode = oldfar::SM_MTIME; break; + case SM_CTIME: PIA->SortMode = oldfar::SM_CTIME; break; + case SM_ATIME: PIA->SortMode = oldfar::SM_ATIME; break; + case SM_SIZE: PIA->SortMode = oldfar::SM_SIZE; break; + case SM_DESCR: PIA->SortMode = oldfar::SM_DESCR; break; + case SM_OWNER: PIA->SortMode = oldfar::SM_OWNER; break; + case SM_COMPRESSEDSIZE: PIA->SortMode = oldfar::SM_COMPRESSEDSIZE; break; + case SM_NUMLINKS: PIA->SortMode = oldfar::SM_NUMLINKS; break; + } + + PIA->Flags = 0; + + if (PIW->Flags&PFLAGS_SHOWHIDDEN) PIA->Flags|=oldfar::PFLAGS_SHOWHIDDEN; + + if (PIW->Flags&PFLAGS_HIGHLIGHT) PIA->Flags|=oldfar::PFLAGS_HIGHLIGHT; + + if (PIW->Flags&PFLAGS_REVERSESORTORDER) PIA->Flags|=oldfar::PFLAGS_REVERSESORTORDER; + + if (PIW->Flags&PFLAGS_USESORTGROUPS) PIA->Flags|=oldfar::PFLAGS_USESORTGROUPS; + + if (PIW->Flags&PFLAGS_SELECTEDFIRST) PIA->Flags|=oldfar::PFLAGS_SELECTEDFIRST; + + if (PIW->Flags&PFLAGS_REALNAMES) PIA->Flags|=oldfar::PFLAGS_REALNAMES; + + if (PIW->Flags&PFLAGS_NUMERICSORT) PIA->Flags|=oldfar::PFLAGS_NUMERICSORT; + + if (PIW->Flags&PFLAGS_PANELLEFT) PIA->Flags|=oldfar::PFLAGS_PANELLEFT; + + PIA->Reserved = PIW->Reserved; +} + +void FreeAnsiPanelInfo(oldfar::PanelInfo* PIA) +{ + if (PIA->PanelItems) + FreePanelItemA(PIA->PanelItems,PIA->ItemsNumber); + + if (PIA->SelectedItems) + FreePanelItemA(PIA->SelectedItems,PIA->SelectedItemsNumber); + + memset(PIA,0,sizeof(oldfar::PanelInfo)); +} + +int WINAPI FarControlA(HANDLE hPlugin,int Command,void *Param) +{ + static oldfar::PanelInfo PanelInfoA{},AnotherPanelInfoA{}; + static int Reenter=0; + + if (hPlugin==INVALID_HANDLE_VALUE) + hPlugin=PANEL_ACTIVE; + + switch (Command) + { + case oldfar::FCTL_CHECKPANELSEXIST: + return FarControl(hPlugin,FCTL_CHECKPANELSEXIST,0,(LONG_PTR)Param); + case oldfar::FCTL_CLOSEPLUGIN: + { + wchar_t *ParamW = nullptr; + + if (Param) + ParamW = AnsiToUnicode((const char *)Param); + + int ret = FarControl(hPlugin,FCTL_CLOSEPLUGIN,0,(LONG_PTR)ParamW); + + if (ParamW) free(ParamW); + + return ret; + } + case oldfar::FCTL_GETANOTHERPANELINFO: + case oldfar::FCTL_GETPANELINFO: + { + if (!Param) + return FALSE; + + bool Passive=Command==oldfar::FCTL_GETANOTHERPANELINFO; + + if (Reenter) + { + //Попытка борьбы с рекурсией (вызов GET*PANELINFO из GetOpenPluginInfo). + //Так как у нас всё статик то должно сработать нормально в 99% случаев + *(oldfar::PanelInfo*)Param=Passive?AnotherPanelInfoA:PanelInfoA; + return TRUE; + } + + Reenter++; + + if (Passive) + hPlugin=PANEL_PASSIVE; + + oldfar::PanelInfo* OldPI=Passive?&AnotherPanelInfoA:&PanelInfoA; + PanelInfo PI; + int ret = FarControl(hPlugin,FCTL_GETPANELINFO,0,(LONG_PTR)&PI); + FreeAnsiPanelInfo(OldPI); + + if (ret) + { + ConvertUnicodePanelInfoToAnsi(&PI,OldPI); + + if (PI.ItemsNumber) + { + OldPI->PanelItems = (oldfar::PluginPanelItem *)malloc(PI.ItemsNumber*sizeof(oldfar::PluginPanelItem)); + + if (OldPI->PanelItems) + { + memset(OldPI->PanelItems,0,PI.ItemsNumber*sizeof(oldfar::PluginPanelItem)); + PluginPanelItem* PPI=nullptr; int PPISize=0; + + for (int i=0; i<PI.ItemsNumber; i++) + { + int NewPPISize=FarControl(hPlugin,FCTL_GETPANELITEM,i,0); + + if (NewPPISize>PPISize) + { + PluginPanelItem* NewPPI=(PluginPanelItem*)realloc(PPI,NewPPISize); + + if (NewPPI) + { + PPI=NewPPI; + PPISize=NewPPISize; + } + else + break; + } + + FarControl(hPlugin,FCTL_GETPANELITEM,i,(LONG_PTR)PPI); + if(PPI) + { + ConvertPanelItemToAnsi(*PPI,OldPI->PanelItems[i]); + } + } + + if (PPI) + free(PPI); + } + } + + if (PI.SelectedItemsNumber) + { + OldPI->SelectedItems = (oldfar::PluginPanelItem *)malloc(PI.SelectedItemsNumber*sizeof(oldfar::PluginPanelItem)); + + if (OldPI->SelectedItems) + { + memset(OldPI->SelectedItems,0,PI.SelectedItemsNumber*sizeof(oldfar::PluginPanelItem)); + PluginPanelItem* PPI=nullptr; int PPISize=0; + + for (int i=0; i<PI.SelectedItemsNumber; i++) + { + int NewPPISize=FarControl(hPlugin,FCTL_GETSELECTEDPANELITEM,i,0); + + if (NewPPISize>PPISize) + { + PluginPanelItem* NewPPI=(PluginPanelItem*)realloc(PPI,NewPPISize); + + if (NewPPI) + { + PPI=NewPPI; + PPISize=NewPPISize; + } + else + break; + } + + FarControl(hPlugin,FCTL_GETSELECTEDPANELITEM,i,(LONG_PTR)PPI); + if(PPI) + { + ConvertPanelItemToAnsi(*PPI,OldPI->SelectedItems[i]); + } + } + + if (PPI) + free(PPI); + } + } + + wchar_t CurDir[sizeof(OldPI->CurDir)]; + FarControl(hPlugin,FCTL_GETPANELDIR,sizeof(OldPI->CurDir),(LONG_PTR)CurDir); + PWZ_to_PZ(CurDir,OldPI->CurDir,sizeof(OldPI->CurDir)); + wchar_t ColumnTypes[sizeof(OldPI->ColumnTypes)]; + FarControl(hPlugin,FCTL_GETCOLUMNTYPES,sizeof(OldPI->ColumnTypes),(LONG_PTR)ColumnTypes); + PWZ_to_PZ(ColumnTypes,OldPI->ColumnTypes,sizeof(OldPI->ColumnTypes)); + wchar_t ColumnWidths[sizeof(OldPI->ColumnWidths)]; + FarControl(hPlugin,FCTL_GETCOLUMNWIDTHS,sizeof(OldPI->ColumnWidths),(LONG_PTR)ColumnWidths); + PWZ_to_PZ(ColumnWidths,OldPI->ColumnWidths,sizeof(OldPI->ColumnWidths)); + *(oldfar::PanelInfo*)Param=*OldPI; + } + else + { + memset((oldfar::PanelInfo*)Param,0,sizeof(oldfar::PanelInfo)); + } + + Reenter--; + return ret; + } + case oldfar::FCTL_GETANOTHERPANELSHORTINFO: + case oldfar::FCTL_GETPANELSHORTINFO: + { + if (!Param) + return FALSE; + + oldfar::PanelInfo *OldPI=(oldfar::PanelInfo*)Param; + memset(OldPI,0,sizeof(oldfar::PanelInfo)); + + if (Command==oldfar::FCTL_GETANOTHERPANELSHORTINFO) + hPlugin=PANEL_PASSIVE; + + PanelInfo PI; + int ret = FarControl(hPlugin,FCTL_GETPANELINFO,0,(LONG_PTR)&PI); + + if (ret) + { + ConvertUnicodePanelInfoToAnsi(&PI,OldPI); + wchar_t CurDir[sizeof(OldPI->CurDir)]; + FarControl(hPlugin,FCTL_GETPANELDIR,sizeof(OldPI->CurDir),(LONG_PTR)CurDir); + PWZ_to_PZ(CurDir,OldPI->CurDir,sizeof(OldPI->CurDir)); + wchar_t ColumnTypes[sizeof(OldPI->ColumnTypes)]; + FarControl(hPlugin,FCTL_GETCOLUMNTYPES,sizeof(OldPI->ColumnTypes),(LONG_PTR)ColumnTypes); + PWZ_to_PZ(ColumnTypes,OldPI->ColumnTypes,sizeof(OldPI->ColumnTypes)); + wchar_t ColumnWidths[sizeof(OldPI->ColumnWidths)]; + FarControl(hPlugin,FCTL_GETCOLUMNWIDTHS,sizeof(OldPI->ColumnWidths),(LONG_PTR)ColumnWidths); + PWZ_to_PZ(ColumnWidths,OldPI->ColumnWidths,sizeof(OldPI->ColumnWidths)); + } + + return ret; + } + case oldfar::FCTL_SETANOTHERSELECTION: + hPlugin=PANEL_PASSIVE; + case oldfar::FCTL_SETSELECTION: + { + if (!Param) + return FALSE; + + oldfar::PanelInfo *OldPI=(oldfar::PanelInfo*)Param; + FarControl(hPlugin,FCTL_BEGINSELECTION,0,0); + + for (int i=0; i<OldPI->ItemsNumber; i++) + { + FarControl(hPlugin,FCTL_SETSELECTION,i,OldPI->PanelItems[i].Flags & oldfar::PPIF_SELECTED); + } + + FarControl(hPlugin,FCTL_ENDSELECTION,0,0); + return TRUE; + } + case oldfar::FCTL_REDRAWANOTHERPANEL: + hPlugin = PANEL_PASSIVE; + case oldfar::FCTL_REDRAWPANEL: + { + if (!Param) + return FarControl(hPlugin, FCTL_REDRAWPANEL,0,0); + + oldfar::PanelRedrawInfo* priA = (oldfar::PanelRedrawInfo*)Param; + PanelRedrawInfo pri = {priA->CurrentItem,priA->TopPanelItem}; + return FarControl(hPlugin, FCTL_REDRAWPANEL,0,(LONG_PTR)&pri); + } + case oldfar::FCTL_SETANOTHERNUMERICSORT: + hPlugin = PANEL_PASSIVE; + case oldfar::FCTL_SETNUMERICSORT: + return FarControl(hPlugin, FCTL_SETNUMERICSORT,(Param&&(*(int*)Param))?1:0,0); + case oldfar::FCTL_SETANOTHERPANELDIR: + hPlugin = PANEL_PASSIVE; + case oldfar::FCTL_SETPANELDIR: + { + if (!Param) + return FALSE; + + wchar_t* Dir = AnsiToUnicode((char*)Param); + int ret = FarControl(hPlugin, FCTL_SETPANELDIR,0,(LONG_PTR)Dir); + free(Dir); + return ret; + } + case oldfar::FCTL_SETANOTHERSORTMODE: + hPlugin = PANEL_PASSIVE; + case oldfar::FCTL_SETSORTMODE: + + if (!Param) + return FALSE; + + return FarControl(hPlugin, FCTL_SETSORTMODE,*(int*)Param,0); + case oldfar::FCTL_SETANOTHERSORTORDER: + hPlugin = PANEL_PASSIVE; + case oldfar::FCTL_SETSORTORDER: + return FarControl(hPlugin, FCTL_SETSORTORDER,(Param&&(*(int*)Param))?TRUE:FALSE,0); + case oldfar::FCTL_SETANOTHERVIEWMODE: + hPlugin = PANEL_PASSIVE; + case oldfar::FCTL_SETVIEWMODE: + return FarControl(hPlugin, FCTL_SETVIEWMODE,(Param?*(int *)Param:0),0); + case oldfar::FCTL_UPDATEANOTHERPANEL: + hPlugin = PANEL_PASSIVE; + case oldfar::FCTL_UPDATEPANEL: + return FarControl(hPlugin, FCTL_UPDATEPANEL,Param?1:0,0); + case oldfar::FCTL_GETCMDLINE: + case oldfar::FCTL_GETCMDLINESELECTEDTEXT: + { + if (Param) + { + int CmdW=(Command==oldfar::FCTL_GETCMDLINE)?FCTL_GETCMDLINE:FCTL_GETCMDLINESELECTEDTEXT; + wchar_t s[1024]; + FarControl(hPlugin,CmdW,ARRAYSIZE(s),(LONG_PTR)s); + PWZ_to_PZ(s, (char*)Param,ARRAYSIZE(s)); + return TRUE; + } + + return FALSE; + } + case oldfar::FCTL_GETCMDLINEPOS: + + if (!Param) + return FALSE; + + return FarControl(hPlugin,FCTL_GETCMDLINEPOS,0,(LONG_PTR)Param); + case oldfar::FCTL_GETCMDLINESELECTION: + { + if (!Param) + return FALSE; + + CmdLineSelect cls; + int ret = FarControl(hPlugin, FCTL_GETCMDLINESELECTION,0,(LONG_PTR)&cls); + + if (ret) + { + oldfar::CmdLineSelect* clsA = (oldfar::CmdLineSelect*)Param; + clsA->SelStart = cls.SelStart; + clsA->SelEnd = cls.SelEnd; + } + + return ret; + } + case oldfar::FCTL_INSERTCMDLINE: + { + if (!Param) + return FALSE; + + wchar_t* s = AnsiToUnicode((const char*)Param); + int ret = FarControl(hPlugin, FCTL_INSERTCMDLINE,0,(LONG_PTR)s); + free(s); + return ret; + } + case oldfar::FCTL_SETCMDLINE: + { + if (!Param) + return FALSE; + + wchar_t* s = AnsiToUnicode((const char*)Param); + int ret = FarControl(hPlugin, FCTL_SETCMDLINE,0,(LONG_PTR)s); + free(s); + return ret; + } + case oldfar::FCTL_SETCMDLINEPOS: + + if (!Param) + return FALSE; + + return FarControl(hPlugin, FCTL_SETCMDLINEPOS,*(int*)Param,0); + case oldfar::FCTL_SETCMDLINESELECTION: + { + if (!Param) + return FALSE; + + oldfar::CmdLineSelect* clsA = (oldfar::CmdLineSelect*)Param; + CmdLineSelect cls = {clsA->SelStart,clsA->SelEnd}; + return FarControl(hPlugin, FCTL_SETCMDLINESELECTION,0,(LONG_PTR)&cls); + } + case oldfar::FCTL_GETUSERSCREEN: + return FarControl(hPlugin, FCTL_GETUSERSCREEN,0,0); + case oldfar::FCTL_SETUSERSCREEN: + return FarControl(hPlugin, FCTL_SETUSERSCREEN,0,0); + } + + return FALSE; +} + +int WINAPI FarGetDirListA(const char *Dir,oldfar::PluginPanelItem **pPanelItem,int *pItemsNumber) +{ + if (!Dir || !*Dir || !pPanelItem || !pItemsNumber) + return FALSE; + + *pPanelItem=nullptr; + *pItemsNumber=0; + FARString strDir(Dir); + DeleteEndSlash(strDir, true); + + FAR_FIND_DATA *pItems; + int ItemsNumber; + int ret=FarGetDirList(strDir, &pItems, &ItemsNumber); + + size_t PathOffset = ExtractFilePath(strDir).GetLength() + 1; + + if (ret && ItemsNumber) + { + //+sizeof(int) чтоб хранить ItemsNumber ибо в FarFreeDirListA как то надо знать + *pPanelItem=(oldfar::PluginPanelItem *)malloc(ItemsNumber*sizeof(oldfar::PluginPanelItem)+sizeof(int)); + + if (*pPanelItem) + { + *pItemsNumber = ItemsNumber; + **((int **)pPanelItem) = ItemsNumber; + (*((int **)pPanelItem))++; + memset(*pPanelItem,0,ItemsNumber*sizeof(oldfar::PluginPanelItem)); + + for (int i=0; i<ItemsNumber; i++) + { + (*pPanelItem)[i].FindData.dwFileAttributes = pItems[i].dwFileAttributes; + (*pPanelItem)[i].FindData.ftCreationTime = pItems[i].ftCreationTime; + (*pPanelItem)[i].FindData.ftLastAccessTime = pItems[i].ftLastAccessTime; + (*pPanelItem)[i].FindData.ftLastWriteTime = pItems[i].ftLastWriteTime; + (*pPanelItem)[i].FindData.nFileSize = (DWORD)pItems[i].nFileSize; + PWZ_to_PZ(pItems[i].lpwszFileName+PathOffset, (*pPanelItem)[i].FindData.cFileName, ARRAYSIZE((*pPanelItem)[i].FindData.cFileName) ); + } + } + else + { + ret = FALSE; + } + + FarFreeDirList(pItems,ItemsNumber); + } + + return ret; +} + +int WINAPI FarGetPluginDirListA(INT_PTR PluginNumber,HANDLE hPlugin,const char *Dir,oldfar::PluginPanelItem **pPanelItem,int *pItemsNumber) +{ + if (!Dir || !*Dir || !pPanelItem || !pItemsNumber) + return FALSE; + + *pPanelItem=nullptr; + *pItemsNumber=0; + FARString strDir(Dir); + + PluginPanelItem *pPanelItemW; + int ItemsNumber; + int ret=FarGetPluginDirList(PluginNumber, hPlugin, strDir, &pPanelItemW, &ItemsNumber); + + if (ret && ItemsNumber) + { + //+sizeof(int) чтоб хранить ItemsNumber ибо в FarFreeDirListA как то надо знать + *pPanelItem=(oldfar::PluginPanelItem *)malloc(ItemsNumber*sizeof(oldfar::PluginPanelItem)+sizeof(int)); + + if (*pPanelItem) + { + *pItemsNumber = ItemsNumber; + **((int **)pPanelItem) = ItemsNumber; + (*((int **)pPanelItem))++; + memset(*pPanelItem,0,ItemsNumber*sizeof(oldfar::PluginPanelItem)); + + for (int i=0; i<ItemsNumber; i++) + { + ConvertPanelItemToAnsi(pPanelItemW[i],(*pPanelItem)[i]); + } + } + else + { + ret = FALSE; + } + + FarFreePluginDirList(pPanelItemW, ItemsNumber); + } + + return ret; +} + +void WINAPI FarFreeDirListA(const oldfar::PluginPanelItem *PanelItem) +{ + if (!PanelItem) + return; + + //Тут хранится ItemsNumber полученный в FarGetDirListA или FarGetPluginDirListA + int *base = ((int *)PanelItem) - 1; + FreePanelItemA((oldfar::PluginPanelItem *)PanelItem, *base, false); + free(base); +} + +INT_PTR WINAPI FarAdvControlA(INT_PTR ModuleNumber,int Command,void *Param) +{ + static char *ErrMsg1 = nullptr; + static char *ErrMsg2 = nullptr; + static char *ErrMsg3 = nullptr; + + switch (Command) + { + case oldfar::ACTL_GETFARVERSION: + { + DWORD FarVer=(DWORD)FarAdvControl(ModuleNumber,ACTL_GETFARVERSION,nullptr); + + if (Param) + *(DWORD*)Param=FarVer; + + return FarVer; + } + case oldfar::ACTL_CONSOLEMODE: + return IsFullscreen(); + + case oldfar::ACTL_GETSYSWORDDIV: + { + INT_PTR Length = FarAdvControl(ModuleNumber, ACTL_GETSYSWORDDIV, nullptr); + + if (Param) + { + wchar_t *SysWordDiv = (wchar_t*)malloc((Length+1)*sizeof(wchar_t)); + FarAdvControl(ModuleNumber, ACTL_GETSYSWORDDIV, SysWordDiv); + PWZ_to_PZ(SysWordDiv,(char*)Param,oldfar::NM); + free(SysWordDiv); + } + + return Length; + } + case oldfar::ACTL_WAITKEY: + return FarAdvControl(ModuleNumber, ACTL_WAITKEY, Param); + case oldfar::ACTL_GETCOLOR: + return FarAdvControl(ModuleNumber, ACTL_GETCOLOR, Param); + case oldfar::ACTL_GETARRAYCOLOR: + return FarAdvControl(ModuleNumber, ACTL_GETARRAYCOLOR, Param); + case oldfar::ACTL_EJECTMEDIA: + return FarAdvControl(ModuleNumber, ACTL_EJECTMEDIA, Param); + case oldfar::ACTL_KEYMACRO: + { + if (!Param) return FALSE; + + ActlKeyMacro km{}; + oldfar::ActlKeyMacro *kmA=(oldfar::ActlKeyMacro *)Param; + + switch (kmA->Command) + { + case oldfar::MCMD_LOADALL: + km.Command=MCMD_LOADALL; + break; + case oldfar::MCMD_SAVEALL: + km.Command=MCMD_SAVEALL; + break; + case oldfar::MCMD_POSTMACROSTRING: + km.Command=MCMD_POSTMACROSTRING; + km.Param.PlainText.SequenceText=AnsiToUnicode(kmA->Param.PlainText.SequenceText); + + if (kmA->Param.PlainText.Flags&oldfar::KSFLAGS_DISABLEOUTPUT) km.Param.PlainText.Flags|=KSFLAGS_DISABLEOUTPUT; + + if (kmA->Param.PlainText.Flags&oldfar::KSFLAGS_NOSENDKEYSTOPLUGINS) km.Param.PlainText.Flags|=KSFLAGS_NOSENDKEYSTOPLUGINS; + + break; + case oldfar::MCMD_GETSTATE: + km.Command=MCMD_GETSTATE; + break; + /* + case oldfar::MCMD_COMPILEMACRO: + km.Command=MCMD_COMPILEMACRO; + km.Param.Compile.Count = kmA->Param.Compile.Count; + km.Param.Compile.Flags = kmA->Param.Compile.Flags; + km.Param.Compile.Sequence = AnsiToUnicode(kmA->Param.Compile.Sequence); + break; + */ + case oldfar::MCMD_CHECKMACRO: + km.Command=MCMD_CHECKMACRO; + km.Param.PlainText.SequenceText=AnsiToUnicode(kmA->Param.PlainText.SequenceText); + break; + } + + INT_PTR res = FarAdvControl(ModuleNumber, ACTL_KEYMACRO, &km); + + switch (km.Command) + { + case MCMD_CHECKMACRO: + { + + if (ErrMsg1) free(ErrMsg1); + + if (ErrMsg2) free(ErrMsg2); + + if (ErrMsg3) free(ErrMsg3); + + FARString ErrMessage[3]; + + CtrlObject->Macro.GetMacroParseError(&ErrMessage[0],&ErrMessage[1],&ErrMessage[2],nullptr); + + kmA->Param.MacroResult.ErrMsg1 = ErrMsg1 = UnicodeToAnsi(ErrMessage[0]); + kmA->Param.MacroResult.ErrMsg2 = ErrMsg2 = UnicodeToAnsi(ErrMessage[1]); + kmA->Param.MacroResult.ErrMsg3 = ErrMsg3 = UnicodeToAnsi(ErrMessage[2]); + + if (km.Param.PlainText.SequenceText) + free((void*)km.Param.PlainText.SequenceText); + + break; + } + + case MCMD_COMPILEMACRO: + + if (km.Param.Compile.Sequence) + free((void*)km.Param.Compile.Sequence); + + break; + case MCMD_POSTMACROSTRING: + + if (km.Param.PlainText.SequenceText) + free((void*)km.Param.PlainText.SequenceText); + + break; + } + + return res; + } + case oldfar::ACTL_POSTKEYSEQUENCE: + { + if (!Param) return FALSE; + + KeySequence ks{}; + oldfar::KeySequence *ksA = (oldfar::KeySequence*)Param; + + if (!ksA->Count || !ksA->Sequence) return FALSE; + + ks.Count = ksA->Count; + + if (ksA->Flags&oldfar::KSFLAGS_DISABLEOUTPUT) ks.Flags|=KSFLAGS_DISABLEOUTPUT; + + if (ksA->Flags&oldfar::KSFLAGS_NOSENDKEYSTOPLUGINS) ks.Flags|=KSFLAGS_NOSENDKEYSTOPLUGINS; + + DWORD* Sequence = (DWORD*)malloc(ks.Count*sizeof(DWORD)); + for (int i=0; i<ks.Count; i++) + { + Sequence[i]=OldKeyToKey(ksA->Sequence[i]); + } + ks.Sequence = Sequence; + + LONG_PTR ret = FarAdvControl(ModuleNumber, ACTL_POSTKEYSEQUENCE, &ks); + free(Sequence); + return ret; + } + case oldfar::ACTL_GETSHORTWINDOWINFO: + case oldfar::ACTL_GETWINDOWINFO: + { + if (!Param) + return FALSE; + + int cmd = (Command==oldfar::ACTL_GETWINDOWINFO)?ACTL_GETWINDOWINFO:ACTL_GETSHORTWINDOWINFO; + oldfar::WindowInfo *wiA = (oldfar::WindowInfo *)Param; + WindowInfo wi{}; + wi.Pos = wiA->Pos; + INT_PTR ret = FarAdvControl(ModuleNumber, cmd, &wi); + + if (ret) + { + switch (wi.Type) + { + case WTYPE_PANELS: wiA->Type = oldfar::WTYPE_PANELS; break; + case WTYPE_VIEWER: wiA->Type = oldfar::WTYPE_VIEWER; break; + case WTYPE_EDITOR: wiA->Type = oldfar::WTYPE_EDITOR; break; + case WTYPE_DIALOG: wiA->Type = oldfar::WTYPE_DIALOG; break; + case WTYPE_VMENU: wiA->Type = oldfar::WTYPE_VMENU; break; + case WTYPE_HELP: wiA->Type = oldfar::WTYPE_HELP; break; + } + + wiA->Modified = wi.Modified; + wiA->Current = wi.Current; + + if (cmd==ACTL_GETWINDOWINFO) + { + if (wi.TypeNameSize) + { + wi.TypeName=new wchar_t[wi.TypeNameSize]; + } + + if (wi.NameSize) + { + wi.Name=new wchar_t[wi.NameSize]; + } + + if (wi.TypeName && wi.Name) + { + FarAdvControl(ModuleNumber,ACTL_GETWINDOWINFO,&wi); + PWZ_to_PZ(wi.TypeName,wiA->TypeName,sizeof(wiA->TypeName)); + PWZ_to_PZ(wi.Name,wiA->Name,sizeof(wiA->Name)); + } + + if (wi.TypeName) + { + delete[] wi.TypeName; + } + + if (wi.Name) + { + delete[] wi.Name; + } + } + else + { + *wiA->TypeName=0; + *wiA->Name=0; + } + } + + return ret; + } + case oldfar::ACTL_GETWINDOWCOUNT: + return FarAdvControl(ModuleNumber, ACTL_GETWINDOWCOUNT, 0); + case oldfar::ACTL_SETCURRENTWINDOW: + return FarAdvControl(ModuleNumber, ACTL_SETCURRENTWINDOW, Param); + case oldfar::ACTL_COMMIT: + return FarAdvControl(ModuleNumber, ACTL_COMMIT, 0); + case oldfar::ACTL_GETFARHWND: + return FarAdvControl(ModuleNumber, ACTL_GETFARHWND, 0); + case oldfar::ACTL_GETSYSTEMSETTINGS: + { + INT_PTR ss = FarAdvControl(ModuleNumber, ACTL_GETSYSTEMSETTINGS, 0); + INT_PTR ret = 0; + + if (ss&oldfar::FSS_DELETETORECYCLEBIN) ret|=FSS_DELETETORECYCLEBIN; + + if (ss&oldfar::FSS_WRITETHROUGH) ret|=FSS_WRITETHROUGH; + + if (ss&oldfar::FSS_SAVECOMMANDSHISTORY) ret|=FSS_SAVECOMMANDSHISTORY; + + if (ss&oldfar::FSS_SAVEFOLDERSHISTORY) ret|=FSS_SAVEFOLDERSHISTORY; + + if (ss&oldfar::FSS_SAVEVIEWANDEDITHISTORY) ret|=FSS_SAVEVIEWANDEDITHISTORY; + + if (ss&oldfar::FSS_USEWINDOWSREGISTEREDTYPES) ret|=FSS_USEWINDOWSREGISTEREDTYPES; + + if (ss&oldfar::FSS_AUTOSAVESETUP) ret|=FSS_AUTOSAVESETUP; + + if (ss&oldfar::FSS_SCANSYMLINK) ret|=FSS_SCANSYMLINK; + + return ret; + } + case oldfar::ACTL_GETPANELSETTINGS: + { + INT_PTR ps = FarAdvControl(ModuleNumber, ACTL_GETPANELSETTINGS, 0); + INT_PTR ret = 0; + + if (ps&oldfar::FPS_SHOWHIDDENANDSYSTEMFILES) ret|=FPS_SHOWHIDDENANDSYSTEMFILES; + + if (ps&oldfar::FPS_HIGHLIGHTFILES) ret|=FPS_HIGHLIGHTFILES; + + if (ps&oldfar::FPS_AUTOCHANGEFOLDER) ret|=FPS_AUTOCHANGEFOLDER; + + if (ps&oldfar::FPS_SELECTFOLDERS) ret|=FPS_SELECTFOLDERS; + + if (ps&oldfar::FPS_ALLOWREVERSESORTMODES) ret|=FPS_ALLOWREVERSESORTMODES; + + if (ps&oldfar::FPS_SHOWCOLUMNTITLES) ret|=FPS_SHOWCOLUMNTITLES; + + if (ps&oldfar::FPS_SHOWSTATUSLINE) ret|=FPS_SHOWSTATUSLINE; + + if (ps&oldfar::FPS_SHOWFILESTOTALINFORMATION) ret|=FPS_SHOWFILESTOTALINFORMATION; + + if (ps&oldfar::FPS_SHOWFREESIZE) ret|=FPS_SHOWFREESIZE; + + if (ps&oldfar::FPS_SHOWSCROLLBAR) ret|=FPS_SHOWSCROLLBAR; + + if (ps&oldfar::FPS_SHOWBACKGROUNDSCREENSNUMBER) ret|=FPS_SHOWBACKGROUNDSCREENSNUMBER; + + if (ps&oldfar::FPS_SHOWSORTMODELETTER) ret|=FPS_SHOWSORTMODELETTER; + + return ret; + } + case oldfar::ACTL_GETINTERFACESETTINGS: + { + INT_PTR is = FarAdvControl(ModuleNumber, ACTL_GETINTERFACESETTINGS, 0); + INT_PTR ret = 0; + + if (is&oldfar::FIS_CLOCKINPANELS) ret|=FIS_CLOCKINPANELS; + + if (is&oldfar::FIS_CLOCKINVIEWERANDEDITOR) ret|=FIS_CLOCKINVIEWERANDEDITOR; + + if (is&oldfar::FIS_MOUSE) ret|=FIS_MOUSE; + + if (is&oldfar::FIS_SHOWKEYBAR) ret|=FIS_SHOWKEYBAR; + + if (is&oldfar::FIS_ALWAYSSHOWMENUBAR) ret|=FIS_ALWAYSSHOWMENUBAR; + + if (is&oldfar::FIS_SHOWTOTALCOPYPROGRESSINDICATOR) ret|=FIS_SHOWTOTALCOPYPROGRESSINDICATOR; + + if (is&oldfar::FIS_SHOWCOPYINGTIMEINFO) ret|=FIS_SHOWCOPYINGTIMEINFO; + + if (is&oldfar::FIS_USECTRLPGUPTOCHANGEDRIVE) ret|=FIS_USECTRLPGUPTOCHANGEDRIVE; + + return ret; + } + case oldfar::ACTL_GETCONFIRMATIONS: + { + INT_PTR cs = FarAdvControl(ModuleNumber, ACTL_GETCONFIRMATIONS, 0); + INT_PTR ret = 0; + + if (cs&oldfar::FCS_COPYOVERWRITE) ret|=FCS_COPYOVERWRITE; + + if (cs&oldfar::FCS_MOVEOVERWRITE) ret|=FCS_MOVEOVERWRITE; + + if (cs&oldfar::FCS_DRAGANDDROP) ret|=FCS_DRAGANDDROP; + + if (cs&oldfar::FCS_DELETE) ret|=FCS_DELETE; + + if (cs&oldfar::FCS_DELETENONEMPTYFOLDERS) ret|=FCS_DELETENONEMPTYFOLDERS; + + if (cs&oldfar::FCS_INTERRUPTOPERATION) ret|=FCS_INTERRUPTOPERATION; + + if (cs&oldfar::FCS_DISCONNECTNETWORKDRIVE) ret|=FCS_DISCONNECTNETWORKDRIVE; + + if (cs&oldfar::FCS_RELOADEDITEDFILE) ret|=FCS_RELOADEDITEDFILE; + + if (cs&oldfar::FCS_CLEARHISTORYLIST) ret|=FCS_CLEARHISTORYLIST; + + if (cs&oldfar::FCS_EXIT) ret|=FCS_EXIT; + + return ret; + } + case oldfar::ACTL_GETDESCSETTINGS: + { + INT_PTR ds = FarAdvControl(ModuleNumber, ACTL_GETDESCSETTINGS, 0); + INT_PTR ret = 0; + + if (ds&oldfar::FDS_UPDATEALWAYS) ret|=FDS_UPDATEALWAYS; + + if (ds&oldfar::FDS_UPDATEIFDISPLAYED) ret|=FDS_UPDATEIFDISPLAYED; + + if (ds&oldfar::FDS_SETHIDDEN) ret|=FDS_SETHIDDEN; + + if (ds&oldfar::FDS_UPDATEREADONLY) ret|=FDS_UPDATEREADONLY; + + return ret; + } + case oldfar::ACTL_SETARRAYCOLOR: + { + if (!Param) return FALSE; + + oldfar::FarSetColors *scA = (oldfar::FarSetColors *)Param; + FarSetColors sc = {0, scA->StartIndex, scA->ColorCount, scA->Colors}; + + if (scA->Flags&oldfar::FCLR_REDRAW) sc.Flags|=FCLR_REDRAW; + + return FarAdvControl(ModuleNumber, ACTL_SETARRAYCOLOR, &sc); + } + case oldfar::ACTL_GETWCHARMODE: + return TRUE; + case oldfar::ACTL_GETPLUGINMAXREADDATA: + return FarAdvControl(ModuleNumber, ACTL_GETPLUGINMAXREADDATA, 0); + case oldfar::ACTL_GETDIALOGSETTINGS: + { + INT_PTR ds = FarAdvControl(ModuleNumber, ACTL_GETDIALOGSETTINGS, 0); + INT_PTR ret = 0; + + if (ds&oldfar::FDIS_HISTORYINDIALOGEDITCONTROLS) ret|=FDIS_HISTORYINDIALOGEDITCONTROLS; + + if (ds&oldfar::FDIS_AUTOCOMPLETEININPUTLINES) ret|=FDIS_AUTOCOMPLETEININPUTLINES; + + if (ds&oldfar::FDIS_PERSISTENTBLOCKSINEDITCONTROLS) ret|=FDIS_PERSISTENTBLOCKSINEDITCONTROLS; + + if (ds&oldfar::FDIS_BSDELETEUNCHANGEDTEXT) ret|=FDIS_BSDELETEUNCHANGEDTEXT; + + return ret; + } + case oldfar::ACTL_REMOVEMEDIA: + case oldfar::ACTL_GETMEDIATYPE: + case oldfar::ACTL_GETPOLICIES: + return FALSE; + case oldfar::ACTL_REDRAWALL: + return FarAdvControl(ModuleNumber, ACTL_REDRAWALL, 0); + } + + return FALSE; +} + +UINT GetEditorCodePageA() +{ + EditorInfo info{}; + FarEditorControl(ECTL_GETINFO,&info); + UINT CodePage=info.CodePage; + CPINFO cpi; + + if (!WINPORT(GetCPInfo)(CodePage, &cpi) || cpi.MaxCharSize>1) + CodePage=WINPORT(GetACP)(); + + return CodePage; +} + +int GetEditorCodePageFavA() +{ + UINT CodePage=GetEditorCodePageA(); + DWORD FavIndex=2; + int result=-((int)CodePage+2); + + if (WINPORT(GetOEMCP)()==CodePage) + { + result=0; + } + else if (WINPORT(GetACP)()==CodePage) + { + result=1; + } + else + { + ConfigReader cfg_reader; + const auto &codepages = cfg_reader.EnumKeys(); + for (const auto &cp : codepages) + { + int selectType = cfg_reader.GetInt(cp, 0); + if (!(selectType&CPST_FAVORITE)) continue; + + UINT nCP = atoi(cp.c_str()); + + if (nCP==CodePage) + { + result=FavIndex; + break; + } + + FavIndex++; + } + } + + return result; +} + +void MultiByteRecode(UINT nCPin, UINT nCPout, char *szBuffer, int nLength) +{ + if (szBuffer && nLength > 0) + { + wchar_t *wszTempTable = (wchar_t *) malloc(nLength * sizeof(wchar_t)); + + if (wszTempTable) + { + ErrnoSaver ErSr; + WINPORT(MultiByteToWideChar)(nCPin, 0, szBuffer, nLength, wszTempTable, nLength); + WINPORT(WideCharToMultiByte)(nCPout, 0, wszTempTable, nLength, szBuffer, nLength, nullptr, nullptr); + free(wszTempTable); + } + } +}; + +static UINT ConvertCharTableToCodePage(int Command) +{ + UINT nCP = CP_AUTODETECT; + + if (Command<0) + { + nCP=-(Command+2); + } + else + { + switch (Command) + { + case 0 /* OEM */: nCP = WINPORT(GetOEMCP)(); break; + case 1 /* ANSI */: nCP = WINPORT(GetACP)(); break; + default: + { + int FavIndex=2; + ConfigReader cfg_reader(FavoriteCodePagesKey); + const auto &codepages = cfg_reader.EnumKeys(); + for (const auto &cp : codepages) + { + int selectType = cfg_reader.GetInt(cp, 0); + if (!(selectType&CPST_FAVORITE)) continue; + + if (FavIndex==Command) + { + nCP = atoi(cp.c_str()); + break; + } + + FavIndex++; + } + } + } + } + + return nCP; +} + +int WINAPI FarEditorControlA(int Command,void* Param) +{ + static char *gt=nullptr; + static char *geol=nullptr; + static char *fn=nullptr; + + switch (Command) + { + case oldfar::ECTL_ADDCOLOR: Command = ECTL_ADDCOLOR; break; + case oldfar::ECTL_DELETEBLOCK: Command = ECTL_DELETEBLOCK; break; + case oldfar::ECTL_DELETECHAR: Command = ECTL_DELETECHAR; break; + case oldfar::ECTL_DELETESTRING: Command = ECTL_DELETESTRING; break; + case oldfar::ECTL_EXPANDTABS: Command = ECTL_EXPANDTABS; break; + case oldfar::ECTL_GETCOLOR: Command = ECTL_GETCOLOR; break; + case oldfar::ECTL_GETBOOKMARKS: Command = ECTL_GETBOOKMARKS; break; + case oldfar::ECTL_INSERTSTRING: Command = ECTL_INSERTSTRING; break; + case oldfar::ECTL_QUIT: Command = ECTL_QUIT; break; + case oldfar::ECTL_REALTOTAB: Command = ECTL_REALTOTAB; break; + case oldfar::ECTL_REDRAW: Command = ECTL_REDRAW; break; + case oldfar::ECTL_SELECT: Command = ECTL_SELECT; break; + case oldfar::ECTL_SETPOSITION: Command = ECTL_SETPOSITION; break; + case oldfar::ECTL_TABTOREAL: Command = ECTL_TABTOREAL; break; + case oldfar::ECTL_TURNOFFMARKINGBLOCK: Command = ECTL_TURNOFFMARKINGBLOCK; break; + case oldfar::ECTL_ADDSTACKBOOKMARK: Command = ECTL_ADDSTACKBOOKMARK; break; + case oldfar::ECTL_PREVSTACKBOOKMARK: Command = ECTL_PREVSTACKBOOKMARK; break; + case oldfar::ECTL_NEXTSTACKBOOKMARK: Command = ECTL_NEXTSTACKBOOKMARK; break; + case oldfar::ECTL_CLEARSTACKBOOKMARKS: Command = ECTL_CLEARSTACKBOOKMARKS; break; + case oldfar::ECTL_DELETESTACKBOOKMARK: Command = ECTL_DELETESTACKBOOKMARK; break; + case oldfar::ECTL_GETSTACKBOOKMARKS: Command = ECTL_GETSTACKBOOKMARKS; break; + case oldfar::ECTL_GETSTRING: + { + EditorGetString egs; + oldfar::EditorGetString *oegs=(oldfar::EditorGetString *)Param; + + if (!oegs) return FALSE; + + egs.StringNumber=oegs->StringNumber; + int ret=FarEditorControl(ECTL_GETSTRING,&egs); + + if (ret) + { + oegs->StringNumber=egs.StringNumber; + oegs->StringLength=egs.StringLength; + oegs->SelStart=egs.SelStart; + oegs->SelEnd=egs.SelEnd; + + if (gt) free(gt); + + if (geol) free(geol); + + UINT CodePage=GetEditorCodePageA(); + gt = UnicodeToAnsiBin(egs.StringText,egs.StringLength,CodePage); + geol = UnicodeToAnsi(egs.StringEOL,CodePage); + oegs->StringText=gt; + oegs->StringEOL=geol; + return TRUE; + } + + return FALSE; + } + case oldfar::ECTL_INSERTTEXT: + { + const char *p=(const char *)Param; + + if (!p) return FALSE; + + FARString strP(p); + return FarEditorControl(ECTL_INSERTTEXT,(void *)strP.CPtr()); + } + case oldfar::ECTL_GETINFO: + { + EditorInfo ei{}; + oldfar::EditorInfo *oei=(oldfar::EditorInfo *)Param; + + if (!oei) + return FALSE; + + int ret=FarEditorControl(ECTL_GETINFO,&ei); + + if (ret) + { + if (fn) + free(fn); + + memset(oei,0,sizeof(*oei)); + size_t FileNameSize=FarEditorControl(ECTL_GETFILENAME,nullptr); + + if (FileNameSize) + { + LPWSTR FileName=new wchar_t[FileNameSize]; + FarEditorControl(ECTL_GETFILENAME,FileName); + fn = UnicodeToAnsi(FileName); + oei->FileName=fn; + delete[] FileName; + } + + oei->EditorID=ei.EditorID; + oei->WindowSizeX=ei.WindowSizeX; + oei->WindowSizeY=ei.WindowSizeY; + oei->TotalLines=ei.TotalLines; + oei->CurLine=ei.CurLine; + oei->CurPos=ei.CurPos; + oei->CurTabPos=ei.CurTabPos; + oei->TopScreenLine=ei.TopScreenLine; + oei->LeftPos=ei.LeftPos; + oei->Overtype=ei.Overtype; + oei->BlockType=ei.BlockType; + oei->BlockStartLine=ei.BlockStartLine; + oei->AnsiMode=0; + oei->TableNum=GetEditorCodePageFavA(); + oei->Options=ei.Options; + oei->TabSize=ei.TabSize; + oei->BookMarkCount=ei.BookMarkCount; + oei->CurState=ei.CurState; + return TRUE; + } + + return FALSE; + } + case oldfar::ECTL_EDITORTOOEM: + case oldfar::ECTL_OEMTOEDITOR: + { + if (!Param) + return FALSE; + + oldfar::EditorConvertText *ect=(oldfar::EditorConvertText*) Param; + UINT CodePage=GetEditorCodePageA(); + MultiByteRecode(Command==oldfar::ECTL_OEMTOEDITOR ? CP_UTF8 : CodePage, Command==oldfar::ECTL_OEMTOEDITOR ? CodePage : CP_OEMCP, ect->Text, ect->TextLength); + return TRUE; + } + case oldfar::ECTL_SAVEFILE: + { + EditorSaveFile newsf{}; + + if (Param) + { + oldfar::EditorSaveFile *oldsf = (oldfar::EditorSaveFile*) Param; + newsf.FileName=AnsiToUnicode(oldsf->FileName); + newsf.FileEOL=(oldsf->FileEOL)?AnsiToUnicode(oldsf->FileEOL):nullptr; + } + + int ret = FarEditorControl(ECTL_SAVEFILE, Param?(void *)&newsf:0); + + if (newsf.FileName) free((void*)newsf.FileName); + + if (newsf.FileEOL) free((void*)newsf.FileEOL); + + return ret; + } + case oldfar::ECTL_PROCESSINPUT: //BUGBUG? + { + if (Param) + { + INPUT_RECORD *pIR = (INPUT_RECORD*) Param; + + switch (pIR->EventType) + { + case KEY_EVENT: + case FARMACRO_KEY_EVENT: + { + wchar_t res; + ErrnoSaver ErSr; + WINPORT(MultiByteToWideChar)( + CP_OEMCP, + 0, + &pIR->Event.KeyEvent.uChar.AsciiChar, + 1, + &res, + 1 + ); + pIR->Event.KeyEvent.uChar.UnicodeChar=res; + } + } + } + + return FarEditorControl(ECTL_PROCESSINPUT, Param); + } + case oldfar::ECTL_PROCESSKEY: + { + return FarEditorControl(ECTL_PROCESSKEY, (void*)(DWORD_PTR)OldKeyToKey((DWORD)(DWORD_PTR)Param)); + } + case oldfar::ECTL_READINPUT: //BUGBUG? + { + int ret = FarEditorControl(ECTL_READINPUT, Param); + + if (Param) + { + INPUT_RECORD *pIR = (INPUT_RECORD*) Param; + + switch (pIR->EventType) + { + case KEY_EVENT: + case FARMACRO_KEY_EVENT: + { + char res; + ErrnoSaver ErSr; + WINPORT(WideCharToMultiByte)( + CP_OEMCP, + 0, + &pIR->Event.KeyEvent.uChar.UnicodeChar, + 1, + &res, + 1, + nullptr, + nullptr + ); + pIR->Event.KeyEvent.uChar.UnicodeChar=res; + } + } + } + + return ret; + } + case oldfar::ECTL_SETKEYBAR: + { + switch ((LONG_PTR)Param) + { + case 0: + case -1: + return FarEditorControl(ECTL_SETKEYBAR, Param); + default: + oldfar::KeyBarTitles* oldkbt = (oldfar::KeyBarTitles*)Param; + KeyBarTitles newkbt; + ConvertKeyBarTitlesA(oldkbt, &newkbt); + int ret = FarEditorControl(ECTL_SETKEYBAR, &newkbt); + FreeUnicodeKeyBarTitles(&newkbt); + return ret; + } + } + case oldfar::ECTL_SETPARAM: + { + EditorSetParameter newsp{}; + + if (Param) + { + oldfar::EditorSetParameter *oldsp= (oldfar::EditorSetParameter*) Param; + newsp.Param.iParam = oldsp->Param.iParam; + + switch (oldsp->Type) + { + case oldfar::ESPT_AUTOINDENT: newsp.Type = ESPT_AUTOINDENT; break; + case oldfar::ESPT_CHARCODEBASE: newsp.Type = ESPT_CHARCODEBASE; break; + case oldfar::ESPT_CURSORBEYONDEOL: newsp.Type = ESPT_CURSORBEYONDEOL; break; + case oldfar::ESPT_LOCKMODE: newsp.Type = ESPT_LOCKMODE; break; + case oldfar::ESPT_SAVEFILEPOSITION: newsp.Type = ESPT_SAVEFILEPOSITION; break; + case oldfar::ESPT_TABSIZE: newsp.Type = ESPT_TABSIZE; break; + case oldfar::ESPT_CHARTABLE: //BUGBUG, недоделано в фаре + { + if (!oldsp->Param.iParam) return FALSE; + + newsp.Type = ESPT_CODEPAGE; + + switch (oldsp->Param.iParam) + { + case 1: + newsp.Param.iParam=WINPORT(GetOEMCP)(); + break; + case 2: + newsp.Param.iParam=WINPORT(GetACP)(); + break; + default: + newsp.Param.iParam=oldsp->Param.iParam; + + if (newsp.Param.iParam>0) newsp.Param.iParam-=3; + + newsp.Param.iParam=ConvertCharTableToCodePage(newsp.Param.iParam); + + if ((UINT)newsp.Param.iParam==CP_AUTODETECT) return FALSE; + + break; + } + + break; + } + case oldfar::ESPT_EXPANDTABS: + { + newsp.Type = ESPT_EXPANDTABS; + + switch (oldsp->Param.iParam) + { + case oldfar::EXPAND_NOTABS: newsp.Param.iParam = EXPAND_NOTABS; break; + case oldfar::EXPAND_ALLTABS: newsp.Param.iParam = EXPAND_ALLTABS; break; + case oldfar::EXPAND_NEWTABS: newsp.Param.iParam = EXPAND_NEWTABS; break; + default: return FALSE; + } + + break; + } + case oldfar::ESPT_SETWORDDIV: + { + newsp.Type = ESPT_SETWORDDIV; + newsp.Param.wszParam = (oldsp->Param.cParam)?AnsiToUnicode(oldsp->Param.cParam):nullptr; + int ret = FarEditorControl(ECTL_SETPARAM, (void *)&newsp); + + if (newsp.Param.wszParam) free(newsp.Param.wszParam); + + return ret; + } + case oldfar::ESPT_GETWORDDIV: + { + if (!oldsp->Param.cParam) return FALSE; + + *oldsp->Param.cParam=0; + newsp.Type = ESPT_GETWORDDIV; + newsp.Param.wszParam = nullptr; + newsp.Size = 0; + newsp.Size = FarEditorControl(ECTL_SETPARAM, (void *)&newsp); + newsp.Param.wszParam = (wchar_t*)malloc(newsp.Size*sizeof(wchar_t)); + + if (newsp.Param.wszParam) + { + int ret = FarEditorControl(ECTL_SETPARAM, (void *)&newsp); + char *olddiv = UnicodeToAnsi(newsp.Param.wszParam); + + if (olddiv) + { + far_strncpy(oldsp->Param.cParam, olddiv, 0x100); + free(olddiv); + } + + free(newsp.Param.wszParam); + return ret; + } + + return FALSE; + } + default: + return FALSE; + } + } + + return FarEditorControl(ECTL_SETPARAM, Param?(void *)&newsp:0); + } + case oldfar::ECTL_SETSTRING: + { + EditorSetString newss = {0,0,0,0}; + + if (Param) + { + oldfar::EditorSetString *oldss = (oldfar::EditorSetString*) Param; + newss.StringNumber=oldss->StringNumber; + UINT CodePage=GetEditorCodePageA(); + newss.StringText=(oldss->StringText)?AnsiToUnicodeBin(oldss->StringText, oldss->StringLength,CodePage):nullptr; + newss.StringEOL=(oldss->StringEOL)?AnsiToUnicode(oldss->StringEOL,CodePage):nullptr; + newss.StringLength=oldss->StringLength; + } + + int ret = FarEditorControl(ECTL_SETSTRING, Param?(void *)&newss:0); + + if (newss.StringText) free((void*)newss.StringText); + + if (newss.StringEOL) free((void*)newss.StringEOL); + + return ret; + } + case oldfar::ECTL_SETTITLE: + { + wchar_t* newtit = nullptr; + + if (Param) + { + newtit=AnsiToUnicode((char*)Param); + } + + int ret = FarEditorControl(ECTL_SETTITLE, (void *)newtit); + + if (newtit) free(newtit); + + return ret; + } + default: + return FALSE; + } + + return FarEditorControl(Command,Param); +} + +int WINAPI FarViewerControlA(int Command,void* Param) +{ + static char* filename=nullptr; + + switch (Command) + { + case oldfar::VCTL_GETINFO: + { + if (!Param) return FALSE; + + oldfar::ViewerInfo* viA = (oldfar::ViewerInfo*)Param; + + if (!viA->StructSize) return FALSE; + + ViewerInfo viW; + viW.StructSize = sizeof(ViewerInfo); //BUGBUG? + + if (FarViewerControl(VCTL_GETINFO, &viW) == FALSE) return FALSE; + + viA->ViewerID = viW.ViewerID; + + if (filename) free(filename); + + filename = UnicodeToAnsi(viW.FileName); + viA->FileName = filename; + viA->FileSize = viW.FileSize; + viA->FilePos = viW.FilePos; + viA->WindowSizeX = viW.WindowSizeX; + viA->WindowSizeY = viW.WindowSizeY; + viA->Options = 0; + + if (viW.Options&VOPT_SAVEFILEPOSITION) viA->Options |= oldfar::VOPT_SAVEFILEPOSITION; + + if (viW.Options&VOPT_AUTODETECTCODEPAGE) viA->Options |= oldfar::VOPT_AUTODETECTTABLE; + + viA->TabSize = viW.TabSize; + viA->CurMode.UseDecodeTable = 0; + viA->CurMode.TableNum = 0; + viA->CurMode.AnsiMode = viW.CurMode.CodePage == WINPORT(GetACP)(); + viA->CurMode.Unicode = IsFullWideCodePage(viW.CurMode.CodePage); + viA->CurMode.Wrap = viW.CurMode.Wrap; + viA->CurMode.WordWrap = viW.CurMode.WordWrap; + viA->CurMode.Processed = viW.CurMode.Processed; + viA->CurMode.Hex = viW.CurMode.Hex; + viA->LeftPos = (int)viW.LeftPos; + viA->Reserved3 = 0; + break; + } + case oldfar::VCTL_QUIT: + return FarViewerControl(VCTL_QUIT, nullptr); + case oldfar::VCTL_REDRAW: + return FarViewerControl(VCTL_REDRAW, nullptr); + case oldfar::VCTL_SETKEYBAR: + { + switch ((LONG_PTR)Param) + { + case 0: + case -1: + return FarViewerControl(VCTL_SETKEYBAR, Param); + default: + oldfar::KeyBarTitles* kbtA = (oldfar::KeyBarTitles*)Param; + KeyBarTitles kbt; + ConvertKeyBarTitlesA(kbtA, &kbt); + int ret=FarViewerControl(VCTL_SETKEYBAR, &kbt); + FreeUnicodeKeyBarTitles(&kbt); + return ret; + } + } + case oldfar::VCTL_SETPOSITION: + { + if (!Param) return FALSE; + + oldfar::ViewerSetPosition* vspA = (oldfar::ViewerSetPosition*)Param; + ViewerSetPosition vsp; + vsp.Flags = 0; + + if (vspA->Flags&oldfar::VSP_NOREDRAW) vsp.Flags|=VSP_NOREDRAW; + + if (vspA->Flags&oldfar::VSP_PERCENT) vsp.Flags|=VSP_PERCENT; + + if (vspA->Flags&oldfar::VSP_RELATIVE) vsp.Flags|=VSP_RELATIVE; + + if (vspA->Flags&oldfar::VSP_NORETNEWPOS) vsp.Flags|=VSP_NORETNEWPOS; + + vsp.StartPos = vspA->StartPos; + vsp.LeftPos = vspA->LeftPos; + int ret = FarViewerControl(VCTL_SETPOSITION, &vsp); + vspA->StartPos = vsp.StartPos; + return ret; + } + case oldfar::VCTL_SELECT: + { + if (!Param) return FarViewerControl(VCTL_SELECT, nullptr); + + oldfar::ViewerSelect* vsA = (oldfar::ViewerSelect*)Param; + ViewerSelect vs = {vsA->BlockStartPos,vsA->BlockLen}; + return FarViewerControl(VCTL_SELECT, &vs); + } + case oldfar::VCTL_SETMODE: + { + if (!Param) return FALSE; + + oldfar::ViewerSetMode* vsmA = (oldfar::ViewerSetMode*)Param; + ViewerSetMode vsm; + vsm.Type = 0; + + switch (vsmA->Type) + { + case oldfar::VSMT_HEX: vsm.Type = VSMT_HEX; break; + case oldfar::VSMT_WRAP: vsm.Type = VSMT_WRAP; break; + case oldfar::VSMT_WORDWRAP: vsm.Type = VSMT_WORDWRAP; break; + } + + vsm.Param.iParam = vsmA->Param.iParam; + vsm.Flags = 0; + + if (vsmA->Flags&oldfar::VSMFL_REDRAW) vsm.Flags|=VSMFL_REDRAW; + + vsm.Reserved = 0; + return FarViewerControl(VCTL_SETMODE, &vsm); + } + } + + return TRUE; +} + +int WINAPI FarCharTableA(int Command, char *Buffer, int BufferSize) +{ + if (Command != oldfar::FCT_DETECT) + { + if (BufferSize != (int) sizeof(oldfar::CharTableSet)) + return -1; + + oldfar::CharTableSet *TableSet=(oldfar::CharTableSet*)Buffer; + //Preset. Also if Command != FCT_DETECT and failed, buffer must be filled by OEM data. + strcpy(TableSet->TableName,"<failed>"); + + for (unsigned int i = 0; i < 256; ++i) + { + TableSet->EncodeTable[i] = TableSet->DecodeTable[i] = i; + TableSet->UpperTable[i] = _toupper(i); + TableSet->LowerTable[i] = _tolower(i); + } + + FormatString sTableName; + UINT nCP = ConvertCharTableToCodePage(Command); + + if (nCP==CP_AUTODETECT) return -1; + + //CPINFOEX cpiex; + //if (!GetCPInfoEx(nCP, 0, &cpiex)) { + CPINFO cpi; + + if (!WINPORT(GetCPInfo)(nCP, &cpi)) + return -1; + + //cpiex.MaxCharSize = cpi.MaxCharSize; + //cpiex.CodePageName[0] = L'\0'; + //} + + //if (cpiex.MaxCharSize != 1) + if (cpi.MaxCharSize != 1) + return -1; + + ErrnoSaver ErSr; + const wchar_t *codePageName = L"";//FormatCodePageName(nCP, cpiex.CodePageName, sizeof(cpiex.CodePageName)/sizeof(wchar_t)); + sTableName<<fmt::Width(5)<<nCP<<BoxSymbols[BS_V1]<<L" "<<codePageName; + sTableName.strValue().GetCharString(TableSet->TableName, sizeof(TableSet->TableName) - 1, CP_OEMCP); + wchar_t *us=AnsiToUnicodeBin((char*)TableSet->DecodeTable, sizeof(TableSet->DecodeTable), nCP); + WINPORT(CharLowerBuff)(us, sizeof(TableSet->DecodeTable)); + WINPORT(WideCharToMultiByte)(nCP, 0, us, sizeof(TableSet->DecodeTable), (char*)TableSet->LowerTable, sizeof(TableSet->DecodeTable), nullptr, nullptr); + WINPORT(CharUpperBuff)(us, sizeof(TableSet->DecodeTable)); + WINPORT(WideCharToMultiByte)(nCP, 0, us, sizeof(TableSet->DecodeTable), (char*)TableSet->UpperTable, sizeof(TableSet->DecodeTable), nullptr, nullptr); + free(us); + MultiByteRecode(nCP, CP_OEMCP, (char *) TableSet->DecodeTable, sizeof(TableSet->DecodeTable)); + MultiByteRecode(CP_OEMCP, nCP, (char *) TableSet->EncodeTable, sizeof(TableSet->EncodeTable)); + return Command; + } + + return -1; +} + +char* WINAPI XlatA( + char *Line, // исходная строка + int StartPos, // начало переконвертирования + int EndPos, // конец переконвертирования + const oldfar::CharTableSet *TableSet, // перекодировочная таблица (может быть nullptr) + DWORD Flags) // флаги (см. enum XLATMODE) +{ + FARString strLine(Line); + DWORD NewFlags = 0; + + if (Flags&oldfar::XLAT_SWITCHKEYBLAYOUT) + NewFlags|=XLAT_SWITCHKEYBLAYOUT; + + if (Flags&oldfar::XLAT_SWITCHKEYBBEEP) + NewFlags|=XLAT_SWITCHKEYBBEEP; + + if (Flags&oldfar::XLAT_USEKEYBLAYOUTNAME) + NewFlags|=XLAT_USEKEYBLAYOUTNAME; + + if (Flags&oldfar::XLAT_CONVERTALLCMDLINE) + NewFlags|=XLAT_CONVERTALLCMDLINE; + + Xlat(strLine.GetBuffer(),StartPos,EndPos,NewFlags); + strLine.ReleaseBuffer(); + strLine.GetCharString(Line,strLine.GetLength()+1); + return Line; +} + +int WINAPI GetFileOwnerA(const char *Computer,const char *Name, char *Owner) +{ + FARString strComputer(Computer), strName(Name), strOwner; + int Ret=GetFileOwner(strComputer,strName,strOwner); + strOwner.GetCharString(Owner,oldfar::NM); + return Ret; +} |