#pragma once /* macro.hpp Макросы */ /* Copyright © 1996 Eugene Roshal Copyright © 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 "TStack.hpp" #include "macrocompiler.hpp" #include "tvar.hpp" #include "macroopcode.hpp" enum MACRODISABLEONLOAD { MDOL_ALL = 0x80000000, // дисаблим все макросы при загрузке MDOL_AUTOSTART = 0x00000001, // дисаблим автостартующие макросы }; // области действия макросов (начало исполнения) - НЕ БОЛЕЕ 0xFF областей! enum MACROMODEAREA { MACRO_FUNCS = -3, MACRO_CONSTS = -2, MACRO_VARS = -1, // see also plugin.hpp # FARMACROAREA MACRO_OTHER = 0, // Режим копирования текста с экрана, вертикальные меню MACRO_SHELL = 1, // Файловые панели MACRO_VIEWER = 2, // Внутренняя программа просмотра MACRO_EDITOR = 3, // Редактор MACRO_DIALOG = 4, // Диалоги MACRO_SEARCH = 5, // Быстрый поиск в панелях MACRO_DISKS = 6, // Меню выбора дисков MACRO_MAINMENU = 7, // Основное меню MACRO_MENU = 8, // Прочие меню MACRO_HELP = 9, // Система помощи MACRO_INFOPANEL = 10, // Информационная панель MACRO_QVIEWPANEL = 11, // Панель быстрого просмотра MACRO_TREEPANEL = 12, // Панель дерева папок MACRO_FINDFOLDER = 13, // Поиск папок MACRO_USERMENU = 14, // Меню пользователя MACRO_SHELLAUTOCOMPLETION = 15, // Список автодополнения в панелях в ком.строке MACRO_DIALOGAUTOCOMPLETION = 16, // Список автодополнения в диалоге MACRO_COMMON, // ВЕЗДЕ! - должен быть предпоследним, т.к. приоритет самый низший !!! MACRO_LAST // Должен быть всегда последним! Используется в циклах }; typedef unsigned __int64 MACROFLAGS_MFLAGS; static const MACROFLAGS_MFLAGS MFLAGS_MODEMASK =0x00000000000000FF, // маска для выделения области действия (области начала исполнения) макроса MFLAGS_DISABLEOUTPUT =0x0000000000000100, // подавить обновление экрана во время выполнения макроса MFLAGS_NOSENDKEYSTOPLUGINS =0x0000000000000200, // НЕ передавать плагинам клавиши во время записи/воспроизведения макроса MFLAGS_RUNAFTERFARSTARTED =0x0000000000000400, // этот макрос уже запускался при старте ФАРа MFLAGS_RUNAFTERFARSTART =0x0000000000000800, // этот макрос запускается при старте ФАРа MFLAGS_EMPTYCOMMANDLINE =0x0000000000001000, // запускать, если командная линия пуста MFLAGS_NOTEMPTYCOMMANDLINE =0x0000000000002000, // запускать, если командная линия не пуста MFLAGS_EDITSELECTION =0x0000000000004000, // запускать, если есть выделение в редакторе MFLAGS_EDITNOSELECTION =0x0000000000008000, // запускать, если есть нет выделения в редакторе MFLAGS_SELECTION =0x0000000000010000, // активная: запускать, если есть выделение MFLAGS_PSELECTION =0x0000000000020000, // пассивная: запускать, если есть выделение MFLAGS_NOSELECTION =0x0000000000040000, // активная: запускать, если есть нет выделения MFLAGS_PNOSELECTION =0x0000000000080000, // пассивная: запускать, если есть нет выделения MFLAGS_NOFILEPANELS =0x0000000000100000, // активная: запускать, если это плагиновая панель MFLAGS_PNOFILEPANELS =0x0000000000200000, // пассивная: запускать, если это плагиновая панель MFLAGS_NOPLUGINPANELS =0x0000000000400000, // активная: запускать, если это файловая панель MFLAGS_PNOPLUGINPANELS =0x0000000000800000, // пассивная: запускать, если это файловая панель MFLAGS_NOFOLDERS =0x0000000001000000, // активная: запускать, если текущий объект "файл" MFLAGS_PNOFOLDERS =0x0000000002000000, // пассивная: запускать, если текущий объект "файл" MFLAGS_NOFILES =0x0000000004000000, // активная: запускать, если текущий объект "папка" MFLAGS_PNOFILES =0x0000000008000000, // пассивная: запускать, если текущий объект "папка" MFLAGS_POSTFROMPLUGIN =0x0000000020000000, // последовательность пришла от АПИ MFLAGS_NEEDSAVEMACRO =0x0000000040000000, // необходимо этот макрос запомнить MFLAGS_DISABLEMACRO =0x0000000080000000; // этот макрос отключен // коды возврата для KeyMacro::GetCurRecord() enum MACRORECORDANDEXECUTETYPE { MACROMODE_NOMACRO =0, // не в режиме макро MACROMODE_EXECUTING =1, // исполнение: без передачи плагину пимп MACROMODE_EXECUTING_COMMON =2, // исполнение: с передачей плагину пимп MACROMODE_RECORDING =3, // запись: без передачи плагину пимп MACROMODE_RECORDING_COMMON =4, // запись: с передачей плагину пимп }; class Panel; struct TMacroFunction; typedef bool (*INTMACROFUNC)(const TMacroFunction*); enum INTMF_FLAGS{ IMFF_UNLOCKSCREEN =0x00000001, IMFF_DISABLEINTINPUT =0x00000002, }; struct TMacroFunction { const wchar_t *Name; // имя функции const wchar_t *fnGUID; // GUID обработчика функции //wchar_t *Src; // оригинальный "текст" макроса //wchar_t *Description; // описание макроса const wchar_t *Syntax; // Синтаксис функции INTMACROFUNC Func; // функция DWORD *Buffer; // компилированная последовательность (OpCode) макроса int BufferSize; // Размер буфера компилированной последовательности DWORD IntFlags; // флаги из INTMF_FLAGS (в основном отвечающие "как вызывать функцию") TMacroOpCode Code; // байткод функции int nParam; // количество параметров int oParam; // необязательные параметры }; struct MacroRecord { MACROFLAGS_MFLAGS Flags; // Флаги макропоследовательности int Key; // Назначенная клавиша int BufferSize; // Размер буфера компилированной последовательности DWORD *Buffer; // компилированная последовательность (OpCode) макроса wchar_t *Src; // оригинальный "текст" макроса wchar_t *Description; // описание макроса GUID Guid; //Гуид владельца макроса void* Id; //параметр калбака FARMACROCALLBACK Callback; // каллбак для плагинов DWORD Reserved[2]; // зарезервировано }; #define STACKLEVEL 32 struct MacroState { INPUT_RECORD cRec; // "описание реально нажатой клавиши" int Executing; struct MacroRecord *MacroWORK; // т.н. текущее исполнение TVarTable *locVarTable; int KeyProcess; int MacroPC; int ExecLIBPos; int MacroWORKCount; DWORD HistoryDisable; bool UseInternalClipboard; bool AllocVarTable; void Init(TVarTable *tbl); }; struct MacroPanelSelect { __int64 Index; TVar *Item; int Action; DWORD ActionFlags; int Mode; }; /* $TODO: 1. Удалить IndexMode[], Sort() 2. Из MacroLIB сделать struct MacroRecord *MacroLIB[MACRO_LAST]; */ class KeyMacro { private: DWORD MacroVersion; static DWORD LastOpCodeUF; // последний не занятый OpCode для UserFunction (относительно KEY_MACRO_U_BASE) // для функций static size_t CMacroFunction; static size_t AllocatedFuncCount; static TMacroFunction *AMacroFunction; // тип записи - с вызовом диалога настроек или... // 0 - нет записи, 1 - простая запись, 2 - вызов диалога настроек int Recording; int InternalInput; int IsRedrawEditor; int Mode; int StartMode; struct MacroState Work; struct MacroState PCStack[STACKLEVEL]; int CurPCStack; bool StopMacro; // сюда "могут" писать только при чтении макросов (занесение нового), // а исполнять через MacroWORK int MacroLIBCount; struct MacroRecord *MacroLIB; int IndexMode[MACRO_LAST][2]; int RecBufferSize; DWORD *RecBuffer; wchar_t *RecSrc; wchar_t *RecDescription; class LockScreen *LockScr; private: void DestroyMacroLib(); int ReadVarsConst(int ReadMode, string &strBuffer); int ReadMacroFunction(int ReadMode, string &strBuffer); int WriteVarsConst(int WriteMode); int ReadMacros(int ReadMode, string &strBuffer); void SavePluginFunctionToDB(const TMacroFunction *MF); void SaveMacroRecordToDB(const MacroRecord *MR); void ReadVarsConsts(); void ReadPluginFunctions(); int ReadKeyMacro(int Area); void WriteVarsConsts(); void WritePluginFunctions(); void WriteMacroRecords(); int AssignMacroKey(DWORD &MacroKey, UINT64 &Flags); int GetMacroSettings(int Key,UINT64 &Flags,const wchar_t *Src=nullptr,const wchar_t *Descr=nullptr); void InitInternalVars(BOOL InitedRAM=TRUE); void InitInternalLIBVars(); void ReleaseWORKBuffer(BOOL All=FALSE); // удалить временный буфер UINT64 SwitchFlags(UINT64& Flags,UINT64 Value); BOOL CheckEditSelected(UINT64 CurFlags); BOOL CheckInsidePlugin(UINT64 CurFlags); BOOL CheckPanel(int PanelMode,UINT64 CurFlags, BOOL IsPassivePanel); BOOL CheckCmdLine(int CmdLength,UINT64 Flags); BOOL CheckFileFolder(Panel *ActivePanel,UINT64 CurFlags, BOOL IsPassivePanel); BOOL CheckAll(int CheckMode,UINT64 CurFlags); void Sort(); TVar FARPseudoVariable(UINT64 Flags,DWORD Code,DWORD& Err); DWORD GetOpCode(struct MacroRecord *MR,int PC); DWORD SetOpCode(struct MacroRecord *MR,int PC,DWORD OpCode); private: static INT_PTR WINAPI AssignMacroDlgProc(HANDLE hDlg,int Msg,int Param1,void* Param2); static INT_PTR WINAPI ParamMacroDlgProc(HANDLE hDlg,int Msg,int Param1,void* Param2); public: KeyMacro(); ~KeyMacro(); public: int ProcessEvent(const struct FAR_INPUT_RECORD *Rec); int GetKey(); int PeekKey(); bool IsOpCode(DWORD p); bool CheckWaitKeyFunc(); int PushState(bool CopyLocalVars=FALSE); int PopState(); int GetLevelState() {return CurPCStack;}; int IsRecording() {return(Recording);}; int IsExecuting() {return(Work.Executing);}; int IsExecutingLastKey(); int IsDsableOutput() {return CheckCurMacroFlags(MFLAGS_DISABLEOUTPUT);}; void SetMode(int Mode) {KeyMacro::Mode=Mode;}; int GetMode() {return(Mode);}; void DropProcess(); // послать сигнал на прерывание макроса void SendDropProcess(); void RunStartMacro(); // Поместить временное строковое представление макроса int PostNewMacro(const wchar_t *PlainText,UINT64 Flags=0,DWORD AKey=0,bool onlyCheck=false); // Поместить временный рекорд (бинарное представление) int PostNewMacro(struct MacroRecord *MRec,BOOL NeedAddSendFlag=0,bool IsPluginSend=false); bool LoadVarFromDB(const wchar_t *Name, TVar &Value); bool SaveVarToDB(const wchar_t *Name, TVar Value); int LoadMacros(BOOL InitedRAM=TRUE,BOOL LoadAll=TRUE); void SaveMacros(); int GetStartIndex(int Mode) {return IndexMode[Mode { private: const TVar Error; public: TVMStack() {} ~TVMStack() {} public: const TVar &Pop(); TVar &Pop(TVar &dest); const TVar &Peek(); }; extern TVarTable glbVarTable; extern TVarTable glbConstTable; extern TVMStack VMStack;