Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/elfmz/far2l.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorelfmz <fenix1905@tut.by>2021-12-31 14:08:45 +0300
committerelfmz <fenix1905@tut.by>2021-12-31 14:08:45 +0300
commitbe3e39d471034827e156370b465183248558b668 (patch)
tree5d2e040450ee2b6c1511b32c251643f00e646932 /far2l/src/plug
parent6b7b5f7fe480107373a6ef3cbd6ee41378c93642 (diff)
continue sorting files..
Diffstat (limited to 'far2l/src/plug')
-rw-r--r--far2l/src/plug/PluginA.cpp1408
-rw-r--r--far2l/src/plug/PluginA.hpp226
-rw-r--r--far2l/src/plug/PluginW.cpp1311
-rw-r--r--far2l/src/plug/PluginW.hpp226
-rw-r--r--far2l/src/plug/plclass.cpp102
-rw-r--r--far2l/src/plug/plclass.hpp194
-rw-r--r--far2l/src/plug/plugapi.cpp2609
-rw-r--r--far2l/src/plug/plugapi.hpp175
-rw-r--r--far2l/src/plug/plugins.cpp2084
-rw-r--r--far2l/src/plug/plugins.hpp288
-rw-r--r--far2l/src/plug/wrap.cpp4089
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> &sections = 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> &sections = 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)&lt;
+ 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;
+}