*****************************************************************
***              ContextMenu AkelPad plugin v17.9             ***
*****************************************************************

2007-2018 Shengalts Aleksander aka Instructor (Shengalts@mail.ru)


*** Description ***

Configure main menu and context menu for edit control, MDI tabs,
hyperlinks and recent files.

Remarks:
- Left mouse click on non-special menu item with Ctrl key opens the
  preferences dialog with the item code selected.
- Recent files menu doesn't work in Win95.


*** Functions ***

ContextMenu::Main
Main dialog.

ContextMenu::Show
Show user's menu.


*** Syntax ***

Variables:
  %f active file
  %d directory of active file
  %a AkelPad's directory
  %m menu ID (handle)
  %i menu item ID
  %u URL address (work in "URL menu" only)
  %% symbol %
  %system variable%

Comments:
  # comment
  ; comment

Special menu items:
  SEPARATOR
    separator menu item.
  SEPARATOR1
    same as SEPARATOR, but:
    - if specified multiple SEPARATOR1 in sequence, then merged into a single SEPARATOR1;
    - if specified SEPARATOR1 at the beginning or at the end of submenu, then removed from submenu.
  EXPLORER
    explorer menu.
  FAVOURITES
    favourite files list.
  RECENTFILES
    recent files list.
  LANGUAGES
    language modules list.
  OPENCODEPAGES
    codepage list for file reopening.
  SAVECODEPAGES
    codepage list for file saving.
  MDIDOCUMENTS
    MDI documents list (work in "Main menu" with MDI mode only).
  CLEAR
    clear menu (work in "Main menu" only).
  INCLUDE("MENU NAME")
    "MENU NAME"
      Specified submenu name from "ContextMenu::Show menu".
    INCLUDE("SYNTAXTHEME")
      insert "SYNTAXTHEME" submenu items from "ContextMenu::Show menu".
  SET(flags[, additional parameters])
    set text parse flags (doesn't remove flags that already set). Sets by the sum of members:
      SET(1)
        ignore following lines, if SDI mode is used.
      SET(2)
        ignore following lines, if MDI mode is used.
      SET(4)
        ignore following lines, if PMDI mode is used.
      SET(8)
        when copying text from the main menu, don't capture the hotkey.
      SET(16)
        create menu items without plugin processing (turned off: icons, Menu() method, special item INCLUDE).
        It is necessary to locate SET(16) before the first menu item and UNSET(16) right after the last.
      SET(32, "%a\AkelFiles\Plugs\Scripts.dll")
        parse following lines, if "Scripts.dll" file exists.
      SET(64, If("expression"[, IfTrue, IfFalse]))
        parse following lines, if result not equal to zero.
          "expression"
            Expression could consist of::
            - mathematical operations:
              +, -, *, /, %, &, |, ^.
            - logical operations:
              >, <, ==, !=, >=, <=, &&, ||, x?y:z.
            - comments:
              /*comment*/
            - methods:
              SendMain(nMessage, wParam, lParam)
                nMessage
                  Specifies the message to be sent to the main window.
                wParam
                  Specifies additional message-specific information.
                lParam
                  Specifies additional message-specific information.
              SendEdit(nMessage, wParam, lParam)
                nMessage
                  Specifies the message to be sent to the current edit window.
                wParam
                  Specifies additional message-specific information.
                lParam
                  Specifies additional message-specific information.
              Call("Plugin::Function"[, additional parameters])
                - If a plugin is called, then exit code transfered via special parameter &nResult. &nResult must be located in a place where external call syntax requires a pointer to an integer.
                  SET(64, If(`Call("Coder::CodeFold", 1, &nResult)`)
                    parse following lines, if CodeFold window is open.
                - If a script is called, then it is necessary to use external calls 2 or 4 and also transfer exit code from script via AkelPad.ScriptExitCode.
                  SET(64, If(`Call("Scripts::Main", 4, "EvalCmd.js", 'if (AkelPad.GetEditFile(0)) AkelPad.ScriptExitCode(1);')`)
                    parse following lines, if current document has name.
                - It is possible to call Scripts plugin method directly.
                  SET(64, If(`AkelPad.Constants._X64 == 1`))
                    parse following lines, if program is x64.
          IfTrue
            Numeric value, if expression result is true (not equal to zero).
          IfFalse
            Numeric value, if expression result is false (equal to zero).
        SET(64, If(`SendMain(1222 /*AKD_GETMAININFO*/, 5 /*MI_SAVESETTINGS*/, 0) == 2 /*SS_INI*/`))
          parse following lines, if settings saved to ini file.
      SET(128, If("expression"[, IfTrue, IfFalse]))
        set menu item status.
          "expression"
            See SET(64) description.
          IfTrue
            0x0 //IFS_NORMAL    Normal item.
            0x1 //IFS_CHECKED   Checked item.
            0x2 //IFS_GRAYED    Disabled, grayed item.
            0x4 //IFS_DISABLED  Disabled item.
          IfFalse
            0x0 //IFS_NORMAL    Normal item.
            0x1 //IFS_CHECKED   Checked item.
            0x2 //IFS_GRAYED    Disabled, grayed item.
            0x4 //IFS_DISABLED  Disabled item.
        SET(128, If("SendMain(1223 /*AKD_GETFRAMEINFO*/, 69 /*FI_CARETOPTIONS*/, 0) & 0x2 /*CO_CARETVERTLINE*/", 0x1, 0x0))
          check following items, if caret active column is on.
        SET(128, If(`Call("Scripts::Main", 5, "SearchReplace.js", 2 /*SH_THISSCRIPT*/, &nResult)`, 0x1, 0x0))
          check following items, if script SearchReplace.js is working.
        SET(128, If(`AkelPad.IsPluginRunning("Coder::HighLight")`, 0x1, 0x0))
          check following items, if Coder::HighLight is working.
  UNSET(flags)
    unset text parse flags. See SET() for description.

Menu item creation:
  [-]"[menu item text]"  [Command() | Call() | +Call() | Exec() | OpenFile() | SaveFile() | Font() | Recode() | Insert() | Link() | Favourites() | Menu()] [Icon()]

  [-]"[menu item text]"
    "My Menu Item"
      menu item text.
    -"My Menu Item"
      at presence of a minus sign the menu item status will not change somehow (become inactive,
      be checked).
    ""
      at absence of the menu item text, and also use of method Command(), plugin uses main menu
      item text instead, to which Command() method refers.

    Command(number[, parameter])
      Command(4162)
        method calls the internal command at number 4162. In this case this code
        is responsible for opening a dialog box "Go to line...".
        For the full list of commands: see AkelHelp-Eng.htm or AkelDLL.h in source code of a plugin.
    Call("Plugin::Function"[, additional parameters])
      Call("Scripts::Main")
        method calls Scripts plugin and Main function.
    +Call("Plugin::Function"[, additional parameters])
      +Call("LineBoard::Main")
        method calls LineBoard plugin and Main function. Plug-in will work also after
        program restart.
    Exec("command line"[, "working directory"][, Wait][, WindowStyle])
      "command line"
        Command line string.
      "working directory"
        Working directory string. Default is "".
      Wait
        Wait until the program finishes. 1 - wait, 0 - return immediately (default).
      WindowStyle (one of the following):
        0 hidden window.
        1 window as is (by default).
        2 minimized window.
        3 maximized window.
        6 minimized, inactive window.
        9 non-maximized window.
        Note: programs could ignore this parameter.
      Exec("notepad.exe")
        method calls notepad.
      Exec(`notepad.exe`)
        method calls notepad.
      Exec('notepad.exe')
        method calls notepad.
      Exec('%windir%\notepad.exe')
        method calls notepad.
      Exec(`rundll32.exe shell32,ShellExec_RunDLL "%f"`, "%d")
        method pass an active file for opening on Windows association.
    OpenFile("file"[, OpenCodepage][, OpenBOM])
      "file"
        File to open.
      OpenCodepage
        Open codepage. If -1 or not specified, it will be autodetected.
      OpenBOM
        File byte order mark. If -1 or not specified, it will be autodetected.
      OpenFile("C:\File.txt", 65001, -1)
        method opens file in UTF-8 codepage.
    SaveFile("file"[, SaveCodepage][, SaveBOM])
      "file"
        Save current document to a specified file name.
      SaveCodepage
        Save codepage. If -1 or not specified, current codepage will be used.
      SaveBOM
        File byte order mark. 1 - exist, 0 - doesn't exist, -1 or not specified - current BOM will be used.
      SaveFile("C:\File.txt", 65001, 0)
        method saves file in UTF-8 codepage without BOM.
    Font("FaceName", Style, Size)
      "FaceName"
        Font face, for example, "Courier". Unchanged, if "".
      Style (one of the following):
        0  ignored.
        1  normal.
        2  bold.
        3  italic.
        4  bold italic.
      Size
        Font size. Unchanged, if 0.
      Font("Courier", 4, 10)
        method sets Courier bold italic font with 10 pt.
    Recode(RecodeFrom, RecodeTo)
      RecodeFrom
        Codepage source. If -1, it will be autodetected.
      RecodeTo
        Codepage target. If -1, it will be autodetected.
      Recode(1252, 437)
        method recodes the text from 1252 codepage to 437.
    Insert("text"[, Esc-sequences])
      "text"
        Inserted text.
      Esc-sequences:
        0  "text" isn't contain Esc-sequences (default).
        1  "text" contain Esc-sequences. A set of sequences similar to the
           find/replace dialog in the program, and also:
           "\s" - replaced by the selected text of the editing window;
           "\|" - set the caret position after text insertion.
      Insert("Some string")
        method replaces selection with the specified text.
      Insert("<B>\s</B>", 1)
        method enclose selection.
      Insert("\[0031 0032 0033]", 1)
        method replaces selection with "123".
    Link(number)
      Link(1)
        method opens hyperlink (work in "URL menu" only).
      Link(2)
        method copies hyperlink (work in "URL menu" only).
      Link(3)
        method selects hyperlink (work in "URL menu" only).
      Link(4)
        method cuts hyperlink (work in "URL menu" only).
      Link(5)
        method replaces hyperlink with the clipboard text (work in "URL menu" only).
      Link(6)
        method deletes hyperlink (work in "URL menu" only).
    Favourites(number)
      Favourites(1)
        method adds current file to favourites (with dialog).
      Favourites(2)
        method adds current file to favourites (without dialog).
      Favourites(3)
        method opens dialog to manage favourites.
      Favourites(4)
        method deletes current file from favourites.
    Menu("MENU NAME")
      "MENU NAME"
        Specified submenu name from "ContextMenu::Show menu".
      Menu("SYNTAXTHEME")
        method inserts "SYNTAXTHEME" submenu from "ContextMenu::Show menu".

    Icon(["file"][, index])
      Icon("Shell32.dll", 47)
        icon located in file Shell32.dll under index 47.
      Icon("%a\AkelFiles\Plugs\Explorer.dll")
        icon located in file Explorer.dll under index 0.
      Icon("%a\AkelFiles\Plugs\Toolbar\MyIcon.ico")
        icon located in file MyIcon.ico.
      Icon(12)
        icon located in file ContextMenu.dll under index 12.

Examples:
  "Recode selection" Command(4182)
  "" Command(4182)
  "Sort lines" Call("Format::LineSortStrAsc")
  -"Spell check" Call("Scripts::Main", 1, "SpellCheck.js", "")
  "Syntax highlighting" +Call("Coder::Highlight")
  "Registry editor" Exec("regedit.exe") Icon("regedit.exe")


Submenu creation:
  "[submenu text]" [Index() | Break() | Icon()]
  {
  }

  "[submenu text]"
    "My Submenu"
      submenu text.

    Index(number)
      Index(-1)
        method inserts submenu at the specified position in the main menu if the submenu number is negative, the calculation produced from the end of the main menu.
    Break(number)
      Break(-1)
        same as Index(), but submenu inserted on a new line of the main menu.
    Icon(["file"][, index])
      Icon(0)
        see description in menu item creation. Method Icon() don't work for submenu of the main menu.

Example:
  "&Codepages" Index(-1)
  {
    "Open as ANSI	Alt+W" Command(4122)
    "Open as OEM	Alt+D" Command(4123)
    "Open as UTF-16LE (standard)	Alt+L" Command(4125)
    "Open as UTF-16BE	Alt+B" Command(4126)
    "Open as UTF-8	Alt+U" Command(4127)
    SEPARATOR
    "&Open as " Icon("%a\AkelFiles\Plugs\ToolBar.dll", 36)
    {
      OPENCODEPAGES
    }
    SEPARATOR
    "Save as ANSI	Shift+Alt+W" Command(4131)
    "Save as OEM	Shift+Alt+D" Command(4132)
    "Save as UTF-16LE (standard)	Shift+Alt+L" Command(4134)
    "Save as UTF-16BE	Shift+Alt+B" Command(4135)
    "Save as UTF-8	Shift+Alt+U" Command(4136)
    "Save as UTF-8 (&without BOM)" Command(4137)
    SEPARATOR
    "&Save as" Icon("%a\AkelFiles\Plugs\ToolBar.dll", 5)
    {
      SAVECODEPAGES
    }
    SEPARATOR
    "Detect codepage	Alt+F5" Command(4121)
  }


*** External call ContextMenu::Main ***

Call("ContextMenu::Main", 1, INDEX, "STRING")
  Parameters:
    1
      Open dialog and select menu.
    INDEX
      Combobox index number (default is 0).
    STRING
      Find string and select (default is "").

Call("ContextMenu::Main", 2, OPERATION)
  Parameters:
    2
      External call for favourite files list.
    OPERATION
      Operation number. See description of Favourites() method.

Call("ContextMenu::Main", 10)
  Parameters:
    10
      Start/stop plugin without dialog.


*** External call ContextMenu::Show ***

Call("ContextMenu::Show", 1, "X", "Y", INDEX, "SUBMENU", *MENUHEIGHT)
  Parameters:
    1
      Open user menu at specified position.
    "X"
      X position in screen coordinates (default is "-1").
    "Y"
      Y position in screen coordinates (default is "-1").
    INDEX
      Open only specified submenu by number. If -1, show all menu (default).
    "SUBMENU"
      Open only specified submenu by name. INDEX must be equal to -1.
    *MENUHEIGHT
      Pointer to a buffer, that receives menu height. If specified, then menu not open.
  Remarks:
    - If X and Y equal to "-1", then edit window left-top corner position is used.
    - If X and Y equal to "-2", then edit window right-top corner position is used.
    - If X and Y equal to "-3", then edit window right-bottom corner position is used.
    - If X and Y equal to "-4", then edit window left-bottom corner position is used.
    - If X and Y equal to "-5", then edit window caret position is used.
    - If X and Y equal to "-6", then cursor position is used.
    - INDEX is zero-based.

Call("ContextMenu::Show", 2, "X", "Y")
  Parameters:
    2
      Open main menu at specified position.
    "X"
      X position in screen coordinates (default is "-1").
    "Y"
      Y position in screen coordinates (default is "-1").
  Remarks:
    - If X and Y equal to "-1", then edit window left-top corner position is used.
    - If X and Y equal to "-2", then edit window right-top corner position is used.
    - If X and Y equal to "-3", then edit window right-bottom corner position is used.
    - If X and Y equal to "-4", then edit window left-bottom corner position is used.
    - If X and Y equal to "-5", then edit window caret position is used.
    - If X and Y equal to "-6", then cursor position is used.
