// http://akelpad.sourceforge.net/forum/viewtopic.php?p=23830#23830
// Version: 2016-06-05
// Author: KDJ
//
// *** Preview of AkelPad docs files (...\AkelPad\AkelFiles\Docs\) ***
//
// Required to include: BrowseForFolder_function.js and CreateDialog_functions.js
//
// Usage:
//   Call("Scripts::Main", 1, "AkelPadDocsView.js")
//   Call("Scripts::Main", 1, "AkelPadDocsView.js", '-DocDir="C:\Documents\AkelPad" -DocOwn=1')
//
// Arguments (are optional):
//   -DocDir - documents directory;
//             default is -DocDir="" - standard AkelPad Docs subdirectory
//   -DocOwn - if equal to 1 (true) - documents list is reading from the script ini file (variable aDocOwn);
//             ini file will be created after first start the script;
//             if the script is not running, you can edit ini file and change this list;
//             default value is 0 (false) - standard AkelPad documents list is reading
//
// Keyboard and mouse:
//   Tab - rigth <-> left panel
//   Ctrl(+Shift)+Tab - next/previous document
//   F1 - menu
//   F4 or Alt+Enter - maximize/restore window
//   right click on document name or contents - context menu
//   double click on document name - open/close file in AkelPad
//
// Remarks:
//   The script should be saved in Unicode format.
//   For proper operation of preview the files "AkelHelp-*.htm" on Win7, AkelPad must be run as administrator.

var oSys   = AkelPad.SystemFunction();
var sClass = "AkelPad::Scripts::" + WScript.ScriptName + "::" + AkelPad.GetInstanceDll();

if (IsScriptRunning() || (! (AkelPad.Include("BrowseForFolder_function.js") && AkelPad.Include("CreateDialog_functions.js"))))
  WScript.Quit();

GetLangStrings();

var sDocDir = AkelPad.GetArgValue("DocDir", "");
var bDocOwn = AkelPad.GetArgValue("DocOwn", 0);

if (! sDocDir)
  sDocDir = AkelPad.GetAkelDir(2 /*ADTYPE_DOCS*/) + "\\";
else if (sDocDir.slice(-1) != "\\")
  sDocDir += "\\";

var aDocStd = [
      ["AkelPad",        "htm"],
      ["AkelHistory",        "txt"],
      ["Clipboard",      "txt"],
      ["Coder",          "htm"],
      ["ContextMenu",    "txt"],
      ["Exit",           "txt"],
      ["Explorer",       "txt"],
      ["Fonts",          "txt"],
      ["Format",         "txt"],
      ["FullScreen",     "txt"],
      ["HexSel",         "txt"],
      ["Hotkeys",        "txt"],
      ["LineBoard",      "txt"],
      ["Log",            "txt"],
      ["Macros",         "txt"],
      ["MinimizeToTray", "txt"],
      ["QSearch",        "txt"],
      ["RecentFiles",    "txt"],
      ["SaveFile",       "txt"],
      ["Scripts",        "htm"],
      ["Scroll",         "txt"],
      ["Sessions",       "txt"],
      ["SmartSel",       "txt"],
      ["Sounds",         "txt"],
      ["SpecialChar",    "txt"],
      ["Speech",         "txt"],
      ["SpellCheck",     "txt"],
      ["Stats",          "txt"],
      ["Templates",      "txt"],
      ["ToolBar",        "txt"],
      ["XBrackets",      "txt"]];

var oFSO         = new ActiveXObject("Scripting.FileSystemObject");
var hAtlLib      = oSys.Call("Kernel32::LoadLibraryW", "Atl.dll");
var hMainWnd     = AkelPad.GetMainWnd();
var aIsLang      = new Array(2);
var bCaseFT      = 0;
var bAllDocFT    = 1;
var nDirectFT    = 0;
var bWordWrap    = 0;
var bSeparateWnd = 0;
var nLang        = 0;
var nAPDSel      = 0;
var sAPDSel      = "";
var aAPD         = [];
var aAESel;
var aFT;
var aDocOwn;
var oWB;
var hWndIES;
var bCloseDlg;
var bNewFT;
var hSubClass;

var nTextMax = 512;
var lpTextLV = AkelPad.MemAlloc(nTextMax * 2);
var lpLVITEM = AkelPad.MemAlloc(_X64 ? (72) : (60)); //sizeof(LVITEM)
AkelPad.MemCopy(lpLVITEM, 0x0001 /*LVIF_TEXT*/, 3 /*DT_DWORD*/);
AkelPad.MemCopy(_PtrAdd(lpLVITEM, _X64 ? 24 : 20), lpTextLV, 2 /*DT_QWORD*/);
AkelPad.MemCopy(_PtrAdd(lpLVITEM, _X64 ? 32 : 24), nTextMax, 3 /*DT_DWORD*/);

var IDFILE  = 1000;
var IDNAME  = 1001;
var IDTEXT  = 1002;
var IDWB    = 1003;
var IDLANG1 = 1004;
var IDLANG2 = 1005;
var IDMENU  = 1006;
var IDCLOSE = 1007;
var aDlg    = [];

aDlg.Class    = sClass;
aDlg.Title    = sTxtDlgTitle;
aDlg.Style    = WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_SIZEBOX|WS_MINIMIZEBOX|WS_MAXIMIZEBOX;
aDlg.Callback = DlgCallback;
aDlg.CtlFirst = IDFILE;
aDlg.CtlStyle = WS_VISIBLE;
aDlg.CtlFont  = oSys.Call("Gdi32::GetStockObject", 17 /*DEFAULT_GUI_FONT*/);
aDlg.MinW     = 640;
aDlg.MinH     = 300;
aDlg.X        = 100;
aDlg.Y        = 100;
aDlg.W        = aDlg.MinW;
aDlg.H        = aDlg.MinH;
aDlg.Maxim    = 0;

aDlg[IDFILE]  = {Class: "STATIC",        Style: SS_CENTER};
aDlg[IDNAME]  = {Class: "SysListView32", Style: WS_BORDER|LVS_NOSORTHEADER|LVS_SHOWSELALWAYS|LVS_SINGLESEL|LVS_REPORT};
aDlg[IDTEXT]  = {Class: "AkelEditW",     Style: WS_BORDER|WS_VSCROLL|WS_HSCROLL|ES_READONLY|ES_MULTILINE};
aDlg[IDWB]    = {Class: "AtlAxWin",      Style: WS_BORDER, Title: "Shell.Explorer.2"};
aDlg[IDLANG1] = {Style: BS_AUTORADIOBUTTON, Title: sTxtEnglish};
aDlg[IDLANG2] = {Style: BS_AUTORADIOBUTTON, Title: sTxtRussian};
aDlg[IDMENU]  = {Title: sTxtMenu};
aDlg[IDCLOSE] = {Title: sTxtClose};

var IDFTWHAT   = 2000;
var IDFTTEXT   = 2001;
var IDFTCASE   = 2002;
var IDFTALLDOC = 2003;
var IDFTDIRECT = 2004;
var IDFTBEGIN  = 2005;
var IDFTDOWN   = 2006;
var IDFTUP     = 2007;
var IDFTEND    = 2008;
var IDFTFIND   = 2009;
var IDFTCANCEL = 2010;
var aDlgFT     = [];

aDlgFT.Title    = sTxtFindInTxt;
aDlgFT.Style    = WS_POPUP|WS_VISIBLE|WS_CAPTION|WS_SYSMENU;
aDlgFT.W        = -280;
aDlgFT.H        = 138;
aDlgFT.Callback = FTDlgCallback;
aDlgFT.CtlFirst = IDFTWHAT;
aDlgFT.PosPix   = 1;
aDlgFT.PosPar   = 2;
aDlgFT.PosEdge  = "RT";
aDlgFT.CtlStyle = WS_VISIBLE;
aDlgFT.CtlFontN = "MS Shell Dlg";

aDlgFT[IDFTWHAT]   = {X:  10, Y:  13, W:  30, H:  13, Title: sTxtWhat,      Class: "STATIC"};
aDlgFT[IDFTTEXT]   = {X:  40, Y:  10, W: 230, H: 200,                       Class: "COMBOBOX", Style: WS_TABSTOP|CBS_AUTOHSCROLL|CBS_DROPDOWN};
aDlgFT[IDFTCASE]   = {X:  10, Y:  35, W:  85, H:  20, Title: sTxtMatchCase, Style: WS_TABSTOP|BS_AUTOCHECKBOX};
aDlgFT[IDFTALLDOC] = {X:  10, Y:  55, W:  85, H:  20, Title: sTxtAllDocs,   Style: WS_TABSTOP|BS_AUTOCHECKBOX};
aDlgFT[IDFTDIRECT] = {X: 100, Y:  37, W:  85, H:  91, Title: sTxtDirection, Style: BS_GROUPBOX};
aDlgFT[IDFTBEGIN]  = {X: 110, Y:  53, W:  65, H:  16, Title: sTxtBeginning, Style: BS_AUTORADIOBUTTON};
aDlgFT[IDFTDOWN]   = {X: 110, Y:  71, W:  65, H:  16, Title: sTxtDown,      Style: BS_AUTORADIOBUTTON};
aDlgFT[IDFTUP]     = {X: 110, Y:  89, W:  65, H:  16, Title: sTxtUp,        Style: BS_AUTORADIOBUTTON};
aDlgFT[IDFTEND]    = {X: 110, Y: 107, W:  65, H:  16, Title: sTxtEnd,       Style: BS_AUTORADIOBUTTON};
aDlgFT[IDFTFIND]   = {X: 195, Y:  79, W:  75, H:  23, Title: sTxtFindNext,  Style: WS_TABSTOP|BS_DEFPUSHBUTTON};
aDlgFT[IDFTCANCEL] = {X: 195, Y: 105, W:  75, H:  23, Title: sTxtCancel,    Style: WS_TABSTOP|BS_PUSHBUTTON};

if (oSys.Call("Atl::AtlAxWinInit"))
{
  AkelPad.ScriptNoMutex();
  AkelPad.WindowRegisterClass(sClass);

  while (! bCloseDlg)
  {
    ReadIni();
    GetArrayAPD(hMainWnd);
    if (! aAPD.length)
      break;

    bCloseDlg   = true;
    aDlg.HWND   = 0;
    aDlg.Parent = bSeparateWnd ? 0 : hMainWnd;
    oWB         = 0;
    hWndIES     = 0;

    SetForegroundWindow(hMainWnd);
    CreateDialogWindow(aDlg, 1);
    oSys.Call("User32::ShowWindow", aDlg.HWND, aDlg.Maxim ? 3 /*SW_MAXIMIZE*/ : 1 /*SW_SHOWNORMAL*/);
    AkelPad.WindowGetMessage();
  }
}

AkelPad.WindowUnregisterClass(sClass);
oSys.Call("Kernel32::FreeLibrary", hAtlLib);
AkelPad.MemFree(lpTextLV);
AkelPad.MemFree(lpLVITEM);

SetForegroundWindow(hMainWnd);

function DlgCallback(hWnd, uMsg, wParam, lParam)
{
  var nID, nCode;

  if (uMsg == 1 /*WM_CREATE*/)
  {
    aDlg.HWND = hWnd;
    CreateDialogWindow(aDlg, 2, hWnd);
    InitDialog();
    PostMessage(hWnd, 0x8000 /*WM_APP*/, 0, 0);
  }

  else if (uMsg == 0x8000 /*WM_APP*/)
  {
    if (aAESel[nLang][aAPD[nAPDSel][0]])
      SetSelAE(aAESel[nLang][aAPD[nAPDSel][0]][0], aAESel[nLang][aAPD[nAPDSel][0]][1]);
  }

  else if (uMsg == 7 /*WM_SETFOCUS*/)
    oSys.Call("User32::SetFocus", aDlg.Focus);

  else if (uMsg == 36 /*WM_GETMINMAXINFO*/)
  {
    AkelPad.MemCopy(_PtrAdd(lParam, 24), Scale.X(aDlg.MinW), 3 /*DT_DWORD*/); //ptMinTrackSize_x
    AkelPad.MemCopy(_PtrAdd(lParam, 28), Scale.Y(aDlg.MinH), 3 /*DT_DWORD*/); //ptMinTrackSize_y
  }

  else if (uMsg == 3 /*WM_MOVE*/)
  {
    if (! (oSys.Call("User32::IsZoomed", hWnd) || oSys.Call("User32::IsIconic", hWnd)))
      GetWindowPos(hWnd, aDlg);
  }

  else if (uMsg == 5 /*WM_SIZE*/)
  {
    if (wParam == 0 /*SIZE_RESTORED*/)
      GetWindowPos(hWnd, aDlg);

    ResizeDlg(LoWord(lParam), HiWord(lParam));
  }

  else if (uMsg == 15 /*WM_PAINT*/)
    PaintSizeGrip();

  else if (uMsg == 256 /*WM_KEYDOWN*/)
  {
    if (wParam == 9 /*VK_TAB*/)
    {
      if (Ctrl())
      {
        if (Shift())
        {
          if (--nAPDSel < 0)
            nAPDSel = aAPD.length - 1;
        }
        else
        {
          if (++nAPDSel >= aAPD.length)
            nAPDSel = 0;
        }

        SetCurSelLV(nAPDSel);

        if (oSys.Call("User32::IsWindowVisible", aDlg[IDWB].HWND))
        {
          if (aDlg.Focus == aDlg[IDTEXT].HWND)
            aDlg.Focus = hWndIES;
        }
        else if (aDlg.Focus != aDlg[IDNAME].HWND)
          aDlg.Focus = aDlg[IDTEXT].HWND;
      }
      else
      {
        if (aDlg.Focus == aDlg[IDNAME].HWND)
        {
          if (oSys.Call("User32::IsWindowVisible", aDlg[IDWB].HWND))
            aDlg.Focus = hWndIES;
          else
            aDlg.Focus = aDlg[IDTEXT].HWND;
        }
        else
          aDlg.Focus = aDlg[IDNAME].HWND;
      }
      oSys.Call("User32::SetFocus", aDlg.Focus);
    }
    else if (wParam == 0x41 /*A key*/)
    {
      if (Ctrl() && (! Shift()) && (! Alt()) && (aDlg.Focus == hWndIES))
        oWB.ExecWB(17 /*OLECMDID_SELECTALL*/, 0, 0, 0);
    }
    else if ((wParam == 0x43 /*C key*/) || (wParam == 0x2D /*VK_INSERT*/))
    {
      if (Ctrl() && (! Alt()))
      {
        if (aDlg.Focus == aDlg[IDNAME].HWND)
          InsertNameTo(! Shift(), false);
        else if (aDlg.Focus == aDlg[IDTEXT].HWND)
          InsertTextTo(! Shift());
        else if ((aDlg.Focus == hWndIES) && (! Shift()))
          oWB.ExecWB(12 /*OLECMDID_COPY*/, 0, 0, 0);
      }
    }
    else if (wParam == 0x46 /*F key*/)
    {
      if (Ctrl() && (! Shift()) && (! Alt()))
      {
        if (oSys.Call("User32::IsWindowVisible", aDlg[IDWB].HWND))
          oWB.ExecWB(32 /*OLECMDID_FIND*/, 0, 0, 0);
        else
          FTDialog();
      }
    }
    else if (wParam == 0x55 /*U key*/)
    {
      if (Ctrl() && (! Shift()) && (! Alt()))
      {
        bWordWrap = ! bWordWrap;
        SetWordWrapAE();
      }
    }
    else if (wParam == 0x70 /*VK_F1*/)
    {
      if ((! Ctrl()) && (! Shift()))
        MenuMain();
    }
    else if (wParam == 0x72 /*VK_F3*/)
    {
      if (! Ctrl())
      {
        if (oSys.Call("User32::IsWindowVisible", aDlg[IDWB].HWND))
          oWB.ExecWB(32 /*OLECMDID_FIND*/, 0, 0, 0);
        else
          FindTextNext(Shift() ? 2 : 1);
      }
    }
    else if (wParam == 0x73 /*VK_F4*/)
    {
      if ((! Ctrl()) && (! Shift()))
        oSys.Call("User32::ShowWindow", hWnd, oSys.Call("User32::IsZoomed", hWnd) ? 9 /*SW_RESTORE*/ : 3 /*SW_MAXIMIZE*/);
    }
    else if (wParam == 13 /*VK_RETURN*/)
    {
      if ((Ctrl() || Shift()) && (! Alt()) && (aDlg.Focus == aDlg[IDNAME].HWND))
        OpenOrCloseFile();
    }
  }

  else if (uMsg == 260 /*WM_SYSKEYDOWN*/)
  {
    if ((wParam == 0x43 /*C key*/) || (wParam == 0x2D /*VK_INSERT*/))
    {
      if (aDlg.Focus == aDlg[IDNAME].HWND)
        InsertNameTo(! Shift(), true);
    }
    else if ((wParam == 13 /*VK_RETURN*/) && (! Shift()))
      oSys.Call("User32::ShowWindow", hWnd, oSys.Call("User32::IsZoomed", hWnd) ? 9 /*SW_RESTORE*/ : 3 /*SW_MAXIMIZE*/);
  }

  else if (uMsg == 78 /*WM_NOTIFY*/)
  {
    if (wParam == IDNAME)
    {
      switch (AkelPad.MemRead(_PtrAdd(lParam, _X64 ? 16 : 8), 3 /*DT_DWORD*/))
      {
        case -101 : //LVN_ITEMCHANGED
          if (AkelPad.MemRead(_PtrAdd(lParam, _X64 ? 32 : 20) /*NMLISTVIEW.uNewState*/, 3 /*DT_DWORD*/) & 0x2 /*LVIS_SELECTED*/)
          {
            nAPDSel = GetCurSelLV();
            SendMessage(aDlg[IDFILE].HWND, 12 /*WM_SETTEXT*/, 0, aAPD[nAPDSel][2]);

            if ((aAPD[nAPDSel][2].slice(-3) == "htm") && oFSO.FileExists(aAPD[nAPDSel][2]) && oWB)
            {
              oSys.Call("User32::ShowWindow", aDlg[IDTEXT].HWND, 0 /*SW_HIDE*/);
              oSys.Call("User32::ShowWindow", aDlg[IDWB].HWND, 5 /*SW_SHOW*/);
              if (oWB.LocationName != aAPD[nAPDSel][2].substr(aAPD[nAPDSel][2].lastIndexOf("\\") + 1))
                oWB.Navigate(aAPD[nAPDSel][2]);
            }
            else
            {
              oSys.Call("User32::ShowWindow", aDlg[IDWB].HWND, 0 /*SW_HIDE*/);
              oSys.Call("User32::ShowWindow", aDlg[IDTEXT].HWND, 5 /*SW_SHOW*/);
              SendMessage(aDlg[IDTEXT].HWND, 12 /*WM_SETTEXT*/, 0, aAPD[nAPDSel][1]);

              if (aAESel[nLang][aAPD[nAPDSel][0]])
                SetSelAE(aAESel[nLang][aAPD[nAPDSel][0]][0], aAESel[nLang][aAPD[nAPDSel][0]][1]);
            }
          }
          break;
        case -3 : //NM_DBLCLK
          if (AkelPad.MemRead(_PtrAdd(lParam, _X64 ? 24 : 12) /*NMITEMACTIVATE.iItem*/, 3 /*DT_DWORD*/) > -1)
          {
            OpenOrCloseFile();
            break;
          }
        case -2 : //NM_CLICK
        case -5 : //NM_RCLICK
        case -6 : //NM_RDBLCLK
          if (AkelPad.MemRead(_PtrAdd(lParam, _X64 ? 24 : 12) /*NMITEMACTIVATE.iItem*/, 3 /*DT_DWORD*/) == -1)
            SetCurSelLV(GetCurFocLV());
          break;
        case -7 : //NM_SETFOCUS
          aDlg.Focus = aDlg[IDNAME].HWND;
          break;
      }
    }
    else if (wParam == IDTEXT)
    {
      if (AkelPad.MemRead(_PtrAdd(lParam, _X64 ? 16 : 8), 3 /*DT_DWORD*/) == 2103 /*AEN_LINK*/)
      {
        if (AkelPad.MemRead(_PtrAdd(lParam, _X64 ? 32 : 16) /*AENLINK.uMsg*/, 3 /*DT_DWORD*/) == 515 /*WM_LBUTTONDBLCLK*/)
        {
          OpenLinkAE(lParam);
          return 1;
        }
      }
    }
  }

  else if (uMsg == 123 /*WM_CONTEXTMENU*/)
  {
    if (wParam == aDlg[IDNAME].HWND)
      MenuName(LoWord(lParam), HiWord(lParam));
    else if (wParam == aDlg[IDTEXT].HWND)
    {
      oSys.Call("User32::SetFocus", aDlg[IDTEXT].HWND);
      MenuText(LoWord(lParam), HiWord(lParam));
    }
  }

  else if (uMsg == 273 /*WM_COMMAND*/)
  {
    nID   = LoWord(wParam);
    nCode = HiWord(wParam);

    if (nID == IDTEXT)
    {
      if (nCode == 0x0100 /*EN_SETFOCUS*/)
      {
        if (SendMessage(AkelPad.GetEditWnd(), 3227 /*AEM_GETOPTIONS*/, 0, 0) & 0x00000800 /*AECO_ACTIVELINE*/)
          SendMessage(lParam, 3228 /*AEM_SETOPTIONS*/, 2 /*AECOOP_OR*/, 0x00000800 /*AECO_ACTIVELINE*/);
        aDlg.Focus = lParam;
      }
      else if (nCode == 0x0200 /*EN_KILLFOCUS*/)
      {
        SendMessage(lParam, 3228 /*AEM_SETOPTIONS*/, 4 /*AECOOP_XOR*/, 0x00000800 /*AECO_ACTIVELINE*/);
        aAESel[nLang][aAPD[nAPDSel][0]] = [GetSelStartAE(), GetSelEndAE()];
      }
    }
    else if ((nID >= IDLANG1) && (nID <= IDLANG2))
    {
      sAPDSel = aAPD[nAPDSel][0];
  
      CheckButtons(nID);
      GetArrayAPD(hWnd);

      if (aAPD.length)
      {
        CheckButtons();
        FillLV(nAPDSel, sAPDSel.toUpperCase());
        oSys.Call("User32::SetFocus", aDlg.Focus);
      }
      else
        PostMessage(hWnd, 16 /*WM_CLOSE*/, 0, 0);
    }
    else if (nID == IDMENU)
    {
      oSys.Call("User32::SetFocus", aDlg.Focus);
      MenuMain();
      SendMessage(aDlg[IDMENU].HWND, 0xF4 /*BM_SETSTYLE*/, BS_PUSHBUTTON, 1);
    }
    else if ((nID == IDCLOSE) || (nID == 2 /*IDCANCEL*/))
      PostMessage(hWnd, 16 /*WM_CLOSE*/, 0, 0);
  }

  else if (uMsg == 16 /*WM_CLOSE*/)
  {
    aAESel[nLang][aAPD[nAPDSel][0]] = [GetSelStartAE(), GetSelEndAE()];
    WriteIni();
    AkelPad.WindowUnsubClass(hWndIES);
    oSys.Call("User32::DestroyWindow", hWnd);
  }

  else if (uMsg == 2 /*WM_DESTROY*/)
    oSys.Call("User32::PostQuitMessage", 0);

  return 0;
}

function InitDialog()
{
  var hEditWnd = AkelPad.GetEditWnd();
  var lpRect;
  var lpAECOLORS;
  var lpPOINT;
  var lpIndex1;
  var lpIndex2;
  var nOffset1;
  var nOffset2;
  var lppUnknown;
  var lpLVCOLUMN;

  CheckButtons();

  //AkelEdit
  lpRect = AkelPad.MemAlloc(16); //sizeof(RECT)
  AkelPad.MemCopy(_PtrAdd(lpRect,  0), 4, 3 /*DT_DWORD*/);
  AkelPad.MemCopy(_PtrAdd(lpRect,  4), 4, 3 /*DT_DWORD*/);
  AkelPad.MemCopy(_PtrAdd(lpRect,  8), 4, 3 /*DT_DWORD*/);
  AkelPad.MemCopy(_PtrAdd(lpRect, 12), 4, 3 /*DT_DWORD*/);
  SendMessage(aDlg[IDTEXT].HWND, 3178 /*AEM_SETRECT*/, 0x03 /*AERC_MARGINS|AERC_UPDATE*/, lpRect);
  AkelPad.MemFree(lpRect);

  SendMessage(aDlg[IDTEXT].HWND, 48 /*WM_SETFONT*/, SendMessage(hMainWnd, 1233 /*AKD_GETFONTW*/, 0, 0), true);
  SendMessage(aDlg[IDTEXT].HWND, 3228 /*AEM_SETOPTIONS*/, 2 /*AECOOP_OR*/, 0x10000000 /*AECO_DISABLEBEEP*/);
  SendMessage(aDlg[IDTEXT].HWND, 3234 /*AEM_EXSETOPTIONS*/, 2 /*AECOOP_OR*/, 0x00000001 /*AECOE_DETECTURL*/);
  SendMessage(aDlg[IDTEXT].HWND, 3226 /*AEM_SETEVENTMASK*/, 0, 0x00040000 /*AENM_LINK*/);
  SetWordWrapAE();

  if (hEditWnd)
  {
    lpAECOLORS = AkelPad.MemAlloc(17 * 4);
    AkelPad.MemCopy(lpAECOLORS, 0x0001FFFE /*AECLR_ALL*/, 3 /*DT_DWORD*/);
    SendMessage(hEditWnd, 3231 /*AEM_GETCOLORS*/, 0, lpAECOLORS);
    SendMessage(aDlg[IDTEXT].HWND, 3232 /*AEM_SETCOLORS*/, 0, lpAECOLORS);
    AkelPad.MemFree(lpAECOLORS);

    if (SendMessage(hEditWnd, 3227 /*AEM_GETOPTIONS*/, 0, 0) & 0x00001000 /*AECO_ACTIVELINEBORDER*/)
      SendMessage(aDlg[IDTEXT].HWND, 3228 /*AEM_SETOPTIONS*/, 2 /*AECOOP_OR*/, 0x00001000 /*AECO_ACTIVELINEBORDER*/);

    lpPOINT = AkelPad.MemAlloc(8 /*sizeof(POINT)*/);
    SendMessage(hEditWnd, 3237 /*AEM_GETCARETWIDTH*/, 0, lpPOINT);
    SendMessage(aDlg[IDTEXT].HWND, 3238 /*AEM_SETCARETWIDTH*/, 0, lpPOINT);
    AkelPad.MemFree(lpPOINT);

    SendMessage(aDlg[IDTEXT].HWND, 3260 /*AEM_SETLINEGAP*/, SendMessage(hEditWnd, 3259 /*AEM_GETLINEGAP*/, 0, 0), 0);

    lpIndex1 = AkelPad.MemAlloc(_X64 ? 24 : 12 /*sizeof(AECHARINDEX)*/);
    lpIndex2 = AkelPad.MemAlloc(_X64 ? 24 : 12 /*sizeof(AECHARINDEX)*/);

    SendMessage(hEditWnd, 3130 /*AEM_GETINDEX*/, 3 /*AEGI_FIRSTSELCHAR*/, lpIndex1);
    SendMessage(hEditWnd, 3130 /*AEM_GETINDEX*/, 4 /*AEGI_LASTSELCHAR*/, lpIndex2);

    if (SendMessage(hEditWnd, 3133 /*AEM_INDEXCOMPARE*/, lpIndex1, lpIndex2) == 0)
    {
      if (! SendMessage(hEditWnd, 3146 /*AEM_ISDELIMITER*/, 0x11 /*AEDLM_WORD|AEDLM_PREVCHAR*/, lpIndex1))
        SendMessage(hEditWnd, 3145 /*AEM_GETPREVBREAK*/, 0x1 /*AEWB_LEFTWORDSTART*/, lpIndex1);
  
      if (! SendMessage(hEditWnd, 3146 /*AEM_ISDELIMITER*/, 0x10 /*AEDLM_WORD*/, lpIndex2))
        SendMessage(hEditWnd, 3144 /*AEM_GETNEXTBREAK*/, 0x8 /*AEWB_RIGHTWORDEND*/, lpIndex2);
    }

    nOffset1 = SendMessage(hEditWnd, 3136 /*AEM_INDEXTORICHOFFSET*/, 0, lpIndex1);
    nOffset2 = SendMessage(hEditWnd, 3136 /*AEM_INDEXTORICHOFFSET*/, 0, lpIndex2);

    AkelPad.MemFree(lpIndex1);
    AkelPad.MemFree(lpIndex2);

    if (nOffset1 != nOffset2)
      sAPDSel = AkelPad.GetTextRange(nOffset1, nOffset2).substr(0, 256);
  }

  //WebBrowser
  lppUnknown = AkelPad.MemAlloc(_X64 ? 8 : 4 /*sizeof(IUnknown**)*/);
  if (oSys.Call("Atl::AtlAxGetControl", aDlg[IDWB].HWND, lppUnknown) == 0 /*S_OK*/)
  {
    oWB = AkelPad.VarDispatch(AkelPad.MemRead(lppUnknown, 2 /*DT_QWORD*/));
    oWB.Silent = true;
    AkelPad.ConnectObject(oWB, "WB_", "{34A715A0-6587-11D0-924A-0020AFC7AC4D}" /*DIID_DWebBrowserEvents2*/);
  }
  AkelPad.MemFree(lppUnknown);

  //ListView
  lpLVCOLUMN = AkelPad.MemAlloc(_X64 ? 56 : 44); //sizeof(LVCOLUMN)
  AkelPad.MemCopy(lpLVCOLUMN, 4 /*mask=LVCF_TEXT*/, 3 /*DT_DWORD*/);
  AkelPad.MemCopy(_PtrAdd(lpLVCOLUMN, _X64 ? 16 : 12), lpTextLV, 2 /*DT_QWORD*/);
  AkelPad.MemCopy(lpTextLV, sTxtDocument, 1 /*DT_UNICODE*/);

  SendMessage(aDlg[IDNAME].HWND, 0x1036 /*LVM_SETEXTENDEDLISTVIEWSTYLE*/, 0x0020 /*LVS_EX_FULLROWSELECT*/, 0x0020);
  SendMessage(aDlg[IDNAME].HWND, 0x1061 /*LVM_INSERTCOLUMNW*/, 0, lpLVCOLUMN);
  AkelPad.MemFree(lpLVCOLUMN);

  FillLV(nAPDSel, sAPDSel.toUpperCase());

  oSys.Call("User32::SetFocus", aDlg[IDTEXT].HWND);
  oSys.Call("User32::SetFocus", aDlg[IDNAME].HWND);
}

function WB_DocumentComplete(pDisp, URL)
{
  if (! hWndIES)
  {
    oWB.Document.focus(); //must be repeated, why?
    oWB.Document.focus();

    hWndIES   = oSys.Call("User32::GetFocus");
    hSubClass = AkelPad.WindowSubClass(hWndIES, IESCallback, 7 /*WM_SETFOCUS*/);

    if (oSys.Call("User32::IsWindowVisible", aDlg.Focus))
      oSys.Call("User32::SetFocus", aDlg.Focus);
    else
      aDlg.Focus = hWndIES;
  }
}

function IESCallback(hWnd, uMsg, wParam, lParam)
{
  if (uMsg == 7 /*WM_SETFOCUS*/)
    aDlg.Focus = hWndIES;

  return 0;
}

function LoWord(nDwNum)
{
  return nDwNum & 0xFFFF;
}

function HiWord(nDwNum)
{
  return (nDwNum >> 16) & 0xFFFF;
}

function MkLong(nLoWord, nHiWord)
{
  return (nLoWord & 0xFFFF) | (nHiWord << 16);
}

function Ctrl()
{
  return oSys.Call("User32::GetKeyState", 0x11 /*VK_CONTROL*/) & 0x8000;
}

function Shift()
{
  return oSys.Call("User32::GetKeyState", 0x10 /*VK_SHIFT*/) & 0x8000;
}

function Alt()
{
  return oSys.Call("user32::GetKeyState", 0x12 /*VK_MENU*/) & 0x8000;
}

function SendMessage(hWnd, uMsg, wParam, lParam)
{
  return AkelPad.SendMessage(hWnd, uMsg, wParam, lParam);
}

function PostMessage(hWnd, uMsg, wParam, lParam)
{
  return oSys.Call("User32::PostMessageW", hWnd, uMsg, wParam, lParam);
}

function PaintSizeGrip()
{
  var lpPaint = AkelPad.MemAlloc(_X64 ? 72 : 64); //sizeof(PAINTSTRUCT)
  var lpRect  = AkelPad.MemAlloc(16); //sizeof(RECT)
  var hDC;

  if (hDC = oSys.Call("User32::BeginPaint", aDlg.HWND, lpPaint))
  {
    oSys.Call("User32::GetClientRect", aDlg.HWND, lpRect);

    AkelPad.MemCopy(_PtrAdd(lpRect, 0), AkelPad.MemRead(_PtrAdd(lpRect,  8), 3 /*DT_DWORD*/) - oSys.Call("User32::GetSystemMetrics",  2 /*SM_CXVSCROLL*/), 3 /*DT_DWORD*/);
    AkelPad.MemCopy(_PtrAdd(lpRect, 4), AkelPad.MemRead(_PtrAdd(lpRect, 12), 3 /*DT_DWORD*/) - oSys.Call("User32::GetSystemMetrics", 20 /*SM_CYVSCROLL*/), 3 /*DT_DWORD*/);

    oSys.Call("User32::DrawFrameControl", hDC, lpRect, 3 /*DFC_SCROLL*/, 0x8 /*DFCS_SCROLLSIZEGRIP*/);
    oSys.Call("User32::EndPaint", aDlg.HWND, lpPaint);
  }

  AkelPad.MemFree(lpPaint);
  AkelPad.MemFree(lpRect);
}

function ResizeDlg(nW, nH)
{
  var nFlags = 0x14; //SWP_NOACTIVATE|SWP_NOZORDER
  var nGapW  = Scale.X(10);
  var nGapH  = Scale.Y(10);
  var nLVW   = Scale.X(110);
  var nAEW   = nW - nLVW - 3 * nGapW;
  var i;

  oSys.Call("User32::SetWindowPos",
    aDlg[IDFILE].HWND, 0,
    nW - nAEW - nGapW,
    nGapH,
    nAEW,
    Scale.Y(13),
    nFlags);
  oSys.Call("User32::SetWindowPos",
    aDlg[IDNAME].HWND, 0,
    nGapW,
    nGapH,
    nLVW,
    nH - nGapH - Scale.Y(23) - 2 * Scale.Y(25) - 2 * Scale.Y(20),
    nFlags);
  for (i = IDTEXT; i <= IDWB; ++i)
  {
    oSys.Call("User32::SetWindowPos",
      aDlg[i].HWND, 0,
      nW - nAEW - nGapW,
      3 * nGapH,
      nAEW,
      nH - 4 * nGapH,
      nFlags);
  }
  for (i = IDLANG1; i <= IDLANG2; ++i)
  {
    oSys.Call("User32::SetWindowPos",
      aDlg[i].HWND, 0,
      Scale.X(30),
      nH - nGapH - Scale.Y(23) - 2 * Scale.Y(25) - (IDLANG2 - i) * Scale.Y(20),
      Scale.X(70),
      Scale.Y(16),
      nFlags);
  }
  for (i = IDMENU; i <= IDCLOSE; ++i)
  {
    oSys.Call("User32::SetWindowPos",
      aDlg[i].HWND, 0,
      nGapW,
      nH - nGapH - Scale.Y(23) - (IDCLOSE - i) * Scale.Y(25),
      nLVW,
      Scale.Y(23),
      nFlags);
  }

  SendMessage(aDlg[IDNAME].HWND, 0x101E /*LVM_SETCOLUMNWIDTH*/, 0, -2 /*LVSCW_AUTOSIZE_USEHEADER*/);
  SendMessage(aDlg[IDNAME].HWND, 0x1013 /*LVM_ENSUREVISIBLE*/, GetCurSelLV(), false);
  oSys.Call("user32::InvalidateRect", aDlg.HWND, 0, true);
}

function CheckButtons(nButton)
{
  if ((nButton == IDLANG1) || (nButton == IDLANG2))
    nLang = nButton - IDLANG1;

  SendMessage(aDlg[IDLANG1].HWND, 241 /*BM_SETCHECK*/, (nLang == 0), 0);
  SendMessage(aDlg[IDLANG2].HWND, 241 /*BM_SETCHECK*/, (nLang == 1), 0);

  oSys.Call("User32::EnableWindow", aDlg[IDLANG1].HWND, aIsLang[0]);
  oSys.Call("User32::EnableWindow", aDlg[IDLANG2].HWND, aIsLang[1]);
}

function GetWindowPos(hWnd, oRect, bClient)
{
  var lpRect = AkelPad.MemAlloc(16); //sizeof(RECT)

  if (bClient)
    oSys.Call("User32::GetClientRect", hWnd, lpRect);
  else
    oSys.Call("User32::GetWindowRect", hWnd, lpRect);

  oRect.X = AkelPad.MemRead(_PtrAdd(lpRect,  0), 3 /*DT_DWORD*/);
  oRect.Y = AkelPad.MemRead(_PtrAdd(lpRect,  4), 3 /*DT_DWORD*/);
  oRect.W = AkelPad.MemRead(_PtrAdd(lpRect,  8), 3 /*DT_DWORD*/) - oRect.X;
  oRect.H = AkelPad.MemRead(_PtrAdd(lpRect, 12), 3 /*DT_DWORD*/) - oRect.Y;

  AkelPad.MemFree(lpRect);
}

function SetForegroundWindow(hWnd)
{
  if (! oSys.Call("User32::IsWindowVisible", hWnd))
    oSys.Call("User32::ShowWindow", hWnd, 8 /*SW_SHOWNA*/);
  if (oSys.Call("User32::IsIconic", hWnd))
    oSys.Call("User32::ShowWindow", hWnd, 9 /*SW_RESTORE*/);

  oSys.Call("User32::SetForegroundWindow", hWnd);
}

function OpenLinkAE(lpAENLINK)
{
  var nOffset1 = SendMessage(aDlg[IDTEXT].HWND, 3136 /*AEM_INDEXTORICHOFFSET*/, 0, _PtrAdd(lpAENLINK, _X64 ? 56 : 28));
  var nOffset2 = SendMessage(aDlg[IDTEXT].HWND, 3136 /*AEM_INDEXTORICHOFFSET*/, 0, _PtrAdd(lpAENLINK, _X64 ? 80 : 40));
  var sLink;

  AkelPad.SetEditWnd(aDlg[IDTEXT].HWND);
  sLink = AkelPad.GetTextRange(nOffset1, nOffset2);
  AkelPad.SetEditWnd(0);

  oSys.Call("Shell32::ShellExecuteW", 0, "open", sLink, 0, 0, 1 /*SW_SHOWNORMAL*/);
}

function GetSelStartAE()
{
  AkelPad.SetEditWnd(aDlg[IDTEXT].HWND);
  var nSelStart = AkelPad.GetSelStart();
  AkelPad.SetEditWnd(0);
  return nSelStart;
}

function GetSelEndAE()
{
  AkelPad.SetEditWnd(aDlg[IDTEXT].HWND);
  var nSelEnd = AkelPad.GetSelEnd();
  AkelPad.SetEditWnd(0);
  return nSelEnd;
}

function SetSelAE(nSelStart, nSelEnd)
{
  AkelPad.SetEditWnd(aDlg[IDTEXT].HWND);
  AkelPad.SetSel(nSelStart, nSelEnd);
  AkelPad.SetEditWnd(0);
}

function GetSelTextAE()
{
  AkelPad.SetEditWnd(aDlg[IDTEXT].HWND);
  var sText = AkelPad.GetSelText(0);
  AkelPad.SetEditWnd(0);
  return sText;
}

function SetWordWrapAE()
{
  SendMessage(aDlg[IDTEXT].HWND, 0x0CAA /*AEM_SETWORDWRAP*/, bWordWrap ? 1 /*AEWW_WORD*/ : 0 /*AEWW_NONE*/, 0);

  if (oSys.Call("User32::IsWindowVisible", aDlg[IDWB].HWND))
    oSys.Call("User32::UpdateWindow", aDlg[IDWB].HWND);
}

function GetCurFocLV()
{
  return SendMessage(aDlg[IDNAME].HWND, 0x100C /*LVM_GETNEXTITEM*/, -1, 0x0001 /*LVNI_FOCUSED*/);
}

function GetCurSelLV()
{
  return SendMessage(aDlg[IDNAME].HWND, 0x100C /*LVM_GETNEXTITEM*/, -1, 0x0002 /*LVNI_SELECTED*/);
}

function SetCurSelLV(nItem)
{
  AkelPad.MemCopy(_PtrAdd(lpLVITEM, 12), 0x0003 /*LVIS_SELECTED|LVIS_FOCUSED*/, 3 /*DT_DWORD*/);
  AkelPad.MemCopy(_PtrAdd(lpLVITEM, 16), 0x0003 /*LVIS_SELECTED|LVIS_FOCUSED*/, 3 /*DT_DWORD*/);
  SendMessage(aDlg[IDNAME].HWND, 0x102B /*LVM_SETITEMSTATE*/, nItem, lpLVITEM);
  SendMessage(aDlg[IDNAME].HWND, 0x1013 /*LVM_ENSUREVISIBLE*/, nItem, false);
}

function FillLV(nSel, sFind)
{
  var i;

  SendMessage(aDlg[IDNAME].HWND, 0x000B /*WM_SETREDRAW*/, false, 0);
  SendMessage(aDlg[IDNAME].HWND, 0x1009 /*LVM_DELETEALLITEMS*/, 0, 0);

  for (i = 0; i < aAPD.length; ++i)
  {
    AkelPad.MemCopy(_PtrAdd(lpLVITEM, 4), i, 3 /*DT_DWORD*/);
    AkelPad.MemCopy(lpTextLV, aAPD[i][0], 1 /*DT_UNICODE*/);
    SendMessage(aDlg[IDNAME].HWND, 0x104D /*LVM_INSERTITEMW*/, 0, lpLVITEM);

    if (aAPD[i][0].toUpperCase() == sFind)
      nSel = i;
  }

  if (nSel >= aAPD.length)
    nSel = aAPD.length - 1;
  else if (nSel < 0)
    nSel = 0;

  SetCurSelLV(nSel);
  SendMessage(aDlg[IDNAME].HWND, 0x000B /*WM_SETREDRAW*/, true, 0);
}

function GetArrayAPD(hWnd)
{
  var aDoc  = bDocOwn ? aDocOwn : aDocStd;
  var aLang = ["-Eng", "-Rus"];
  var lpFile;
  var lpDetectFile;
  var sFile;
  var nCodePage;
  var bBOM;
  var i, n;

  aIsLang[0]  = false;
  aIsLang[1]  = false;
  aAPD.length = 0;

  while (! (aIsLang[0] || aIsLang[1]))
  {
    for (i = 0; i < 2; ++i)
    {
      for (n = 0; n < aDoc.length; ++n)
      {
        if (oFSO.FileExists(sDocDir + aDoc[n][0] + aLang[i] + "." + aDoc[n][1]))
        {
          aIsLang[i] = true;
          break;
        }
      }
    }

    if (! (aIsLang[0] || aIsLang[1]))
    {
      AkelPad.MessageBox(hWnd, sTxtNoFilesInDir + "\n" + sDocDir, sTxtDlgTitle, 0x30 /*MB_ICONWARNING*/);

      if (! oFSO.FolderExists(sDocDir))
        sDocDir = AkelPad.GetAkelDir(0 /*ADTYPE_ROOT*/) + "\\";

      sDocDir = BrowseForFolder(hWnd, sTxtChooseDir, sDocDir);

      if (! sDocDir)
        return;
      else if (sDocDir.slice(-1) != "\\")
        sDocDir += "\\";
    }
  }

  if (! aIsLang[nLang])
    nLang = Number(! nLang);

  lpFile       = AkelPad.MemAlloc(260 * 2 /*MAX_PATH * sizeof(wchar_t)*/);
  lpDetectFile = AkelPad.MemAlloc(_X64 ? 24 : 20 /*sizeof(DETECTFILEW)*/);

  AkelPad.MemCopy(lpDetectFile, lpFile, 2 /*DT_QWORD*/);
  AkelPad.MemCopy(_PtrAdd(lpDetectFile, _X64 ?  8 : 4), 1024, 3 /*DT_DWORD*/); //dwBytesToCheck
  AkelPad.MemCopy(_PtrAdd(lpDetectFile, _X64 ? 12 : 8), 0x1D /*ADT_BINARY_ERROR|ADT_DETECT_CODEPAGE|ADT_DETECT_BOM|ADT_NOMESSAGES*/, 3 /*DT_DWORD*/); //dwFlags

  for (n = 0; n < aDoc.length; ++n)
  {
    sFile = sDocDir + aDoc[n][0] + aLang[nLang] + "." + aDoc[n][1];

    if (oFSO.FileExists(sFile))
    {
      if (aDoc[n][1] == "htm")
          aAPD.push([aDoc[n][0], "", sFile]);
      else
      {
        AkelPad.MemCopy(lpFile, sFile, 1 /*DT_UNICODE*/);
        AkelPad.MemCopy(_PtrAdd(lpDetectFile, _X64 ? 16 : 12), 0, 3 /*DT_DWORD*/); //nCodePage
        AkelPad.MemCopy(_PtrAdd(lpDetectFile, _X64 ? 20 : 16), 0, 3 /*DT_DWORD*/); //bBOM

        if (SendMessage(hMainWnd, 1177 /*AKD_DETECTFILEW*/, 0, lpDetectFile) == 0 /*EDT_SUCCESS*/)
        {
          nCodePage = AkelPad.MemRead(_PtrAdd(lpDetectFile, _X64 ? 16 : 12), 3 /*DT_DWORD*/);
          bBOM      = AkelPad.MemRead(_PtrAdd(lpDetectFile, _X64 ? 20 : 16), 3 /*DT_DWORD*/);

          if ((nCodePage != 65000) && (nCodePage != 65001) && (nCodePage != 1200) && (nCodePage != 1201) && (nCodePage != 12000) && (nCodePage != 12001))
            nCodePage = 1251 /*ANSI Cyrillic*/;

          aAPD.push([aDoc[n][0], AkelPad.ReadFile(sFile, 0, nCodePage, bBOM).replace(/\r\n/g, "\n"), sFile]);
        }
      }
    }
  }

  AkelPad.MemFree(lpFile);
  AkelPad.MemFree(lpDetectFile);
}

function MenuMain()
{
  var MF_STRING    = 0x0000;
  var MF_GRAYED    = 0x0001;
  var MF_CHECKED   = 0x0008;
  var MF_POPUP     = 0x0010;
  var MF_SEPARATOR = 0x0800;
  var hMenu1 = oSys.Call("User32::CreatePopupMenu");
  var hMenu  = oSys.Call("User32::CreatePopupMenu");
  var oRect  = {};
  var nCmd;
  var nCmd1;

  oSys.Call("User32::AppendMenuW", hMenu1, MF_STRING, 0x0002, sTxtFind + "\tCtrl+F");
  oSys.Call("User32::AppendMenuW", hMenu1, MF_STRING, 0x0102, sTxtFindNextDn + "\tF3");
  oSys.Call("User32::AppendMenuW", hMenu1, MF_STRING, 0x0202, sTxtFindNextUp + "\tShift+F3");

  oSys.Call("User32::AppendMenuW", hMenu, (oSys.Call("User32::IsWindowVisible", aDlg[IDWB].HWND) ? MF_STRING : MF_GRAYED), 0x0001, sTxtFindInHtm + "\tCtrl+F");
  oSys.Call("User32::AppendMenuW", hMenu, (oSys.Call("User32::IsWindowVisible", aDlg[IDTEXT].HWND) ? MF_POPUP : MF_GRAYED), hMenu1, sTxtFindInTxt);
  oSys.Call("user32::AppendMenuW", hMenu, MF_SEPARATOR, 0);
  oSys.Call("User32::AppendMenuW", hMenu, (bWordWrap ? MF_CHECKED : MF_STRING), 0x0003, sTxtWrapLines + "\tCtrl+U");
  oSys.Call("User32::AppendMenuW", hMenu, (bSeparateWnd ? MF_CHECKED : MF_STRING), 0x0004, sTxtSeparateWnd);

  GetWindowPos(aDlg[IDMENU].HWND, oRect);

  nCmd = oSys.Call("User32::TrackPopupMenu", hMenu, 0x01A0 /*TPM_NONOTIFY|TPM_RETURNCMD|TPM_BOTTOMALIGN*/, oRect.X, oRect.Y, 0, aDlg.HWND, 0);

  oSys.Call("User32::DestroyMenu", hMenu1);
  oSys.Call("User32::DestroyMenu", hMenu);

  nCmd1 = (nCmd >> 8) & 0xFF;
  nCmd  = nCmd & 0xFF;

  if (nCmd == 1)
    oWB.ExecWB(32 /*OLECMDID_FIND*/, 0, 0, 0);
  else if (nCmd == 2)
  {
    if (nCmd1 == 0)
      FTDialog();
    else
      FindTextNext(nCmd1);
  }
  else if (nCmd == 3)
  {
    bWordWrap = ! bWordWrap;
    SetWordWrapAE();
  }
  else if (nCmd == 4)
  {
    bSeparateWnd = ! bSeparateWnd;
    bCloseDlg    = false;
    PostMessage(aDlg.HWND, 16 /*WM_CLOSE*/, 0, 0);
  }
}

function MenuName(nX, nY)
{
  var lpRect;
  var nX1, nY1, nY2;
  var hMenu;
  var nCmd;

  if ((nAPDSel < 0) || (aAPD[nAPDSel][0].charAt(0) == "*"))
    return;

  //menu from keyboard
  if (nX == 0xFFFF)
    SendMessage(aDlg[IDNAME].HWND, 0x1013 /*LVM_ENSUREVISIBLE*/, nAPDSel, false);

  lpRect = AkelPad.MemAlloc(16 /*sizeof(RECT)*/);
  SendMessage(aDlg[IDNAME].HWND, 0x100E /*LVM_GETITEMRECT*/, nAPDSel, lpRect);
  oSys.Call("User32::ClientToScreen", aDlg[IDNAME].HWND, lpRect);
  oSys.Call("User32::ClientToScreen", aDlg[IDNAME].HWND, _PtrAdd(lpRect, 8));
  nX1 = AkelPad.MemRead(_PtrAdd(lpRect,  0), 3 /*DT_DWORD*/);
  nY1 = AkelPad.MemRead(_PtrAdd(lpRect,  4), 3 /*DT_DWORD*/);
  nY2 = AkelPad.MemRead(_PtrAdd(lpRect, 12), 3 /*DT_DWORD*/);
  AkelPad.MemFree(lpRect);

  if (nX == 0xFFFF)
  {
    nX = nX1;
    nY = nY2;
  }
  else if ((nY < nY1) || (nY > nY2))
    return;

  hMenu = oSys.Call("User32::CreatePopupMenu");
  oSys.Call("User32::AppendMenuW", hMenu, 0 /*MF_STRING*/, 1, sTxtOpenClose + "\tShift+Enter");
  oSys.Call("User32::AppendMenuW", hMenu, 0x01 /*MF_GRAYED*/, 0, sTxtFileName);
  oSys.Call("User32::AppendMenuW", hMenu, 0 /*MF_STRING*/, 2, "   " + sTxtCopyToCB + "\tCtrl+C");
  oSys.Call("User32::AppendMenuW", hMenu, AkelPad.GetEditWnd() && (! AkelPad.GetEditReadOnly(0)) ? 0 /*MF_STRING*/ : 0x01 /*MF_GRAYED*/, 3, "   " + sTxtInsertToAP + "\tCtrl+Shift+C");
  oSys.Call("User32::AppendMenuW", hMenu, 0x01 /*MF_GRAYED*/, 0, sTxtFileNamePath);
  oSys.Call("User32::AppendMenuW", hMenu, 0 /*MF_STRING*/, 4, "   " + sTxtCopyToCB + "\tAlt+C");
  oSys.Call("User32::AppendMenuW", hMenu, AkelPad.GetEditWnd() && (! AkelPad.GetEditReadOnly(0)) ? 0 /*MF_STRING*/ : 0x01 /*MF_GRAYED*/, 5, "   " + sTxtInsertToAP + "\tShift+Alt+C");

  nCmd = oSys.Call("User32::TrackPopupMenu", hMenu, 0x0180 /*TPM_NONOTIFY|TPM_RETURNCMD*/, nX, nY, 0, aDlg.HWND, 0);

  oSys.Call("User32::DestroyMenu", hMenu);

  if (nCmd == 1)
    OpenOrCloseFile();
  else if (nCmd == 2)
    InsertNameTo(true, false);
  else if (nCmd == 3)
    InsertNameTo(false, false);
  else if (nCmd == 4)
    InsertNameTo(true, true);
  else if (nCmd == 5)
    InsertNameTo(false, true);
}

function MenuText(nX, nY)
{
  var bSel  = SendMessage(aDlg[IDTEXT].HWND, 3125 /*AEM_GETSEL*/, 0, 0);
  var hMenu = oSys.Call("User32::CreatePopupMenu");
  var lpPOINT;
  var nCmd;

  //menu from keyboard
  if (nX == 0xFFFF)
  {
    lpPOINT = AkelPad.MemAlloc(8 /*sizeof(POINT)*/);
    oSys.Call("User32::GetCaretPos", lpPOINT);
    oSys.Call("User32::ClientToScreen", aDlg[IDTEXT].HWND, lpPOINT);
    nX = AkelPad.MemRead(_PtrAdd(lpPOINT, 0), 3 /*DT_DWORD*/);
    nY = AkelPad.MemRead(_PtrAdd(lpPOINT, 4), 3 /*DT_DWORD*/) + SendMessage(aDlg[IDTEXT].HWND, 3188 /*AEM_GETCHARSIZE*/, 0 /*AECS_HEIGHT*/, 0);
    AkelPad.MemFree(lpPOINT);
  }

  oSys.Call("User32::AppendMenuW", hMenu, bSel ? 0 /*MF_STRING*/ : 0x01 /*MF_GRAYED*/, 1, sTxtCopyToCB + "\tCtrl+C");
  oSys.Call("User32::AppendMenuW", hMenu, AkelPad.GetEditWnd() && (! AkelPad.GetEditReadOnly(0)) && bSel ? 0 /*MF_STRING*/ : 0x01 /*MF_GRAYED*/, 2, sTxtInsertToAP + "\tCtrl+Shift+C");
  oSys.Call("user32::AppendMenuW", hMenu, 0x0800 /*MF_SEPARATOR*/, 0);
  oSys.Call("User32::AppendMenuW", hMenu, 0 /*MF_STRING*/, 3, sTxtSelectAll + "\tCtrl+A");

  nCmd = oSys.Call("User32::TrackPopupMenu", hMenu, 0x0180 /*TPM_NONOTIFY|TPM_RETURNCMD*/, nX, nY, 0, aDlg.HWND, 0);

  oSys.Call("User32::DestroyMenu", hMenu);

  if (nCmd == 1)
    InsertTextTo(true);
  else if (nCmd == 2)
    InsertTextTo(false);
  else if (nCmd == 3)
    SetSelAE(0, -1);
}

function OpenOrCloseFile()
{
  var bModified;
  var hFocus;

  if (bSeparateWnd)
  {
    SetForegroundWindow(hMainWnd);
    SetForegroundWindow(aDlg.HWND);
    WScript.Sleep(20);
  }

  if (aAPD[nAPDSel][2].toUpperCase() == AkelPad.GetEditFile(0).toUpperCase())
  {
    bModified = AkelPad.GetEditModified(0);

    if (bModified)
    {
      hFocus = oSys.Call("User32::GetFocus");

      if (bSeparateWnd)
        SetForegroundWindow(hMainWnd);

      oSys.Call("User32::EnableWindow", aDlg.HWND, 0);
      AkelPad.ScriptNoMutex(0x20 /*ULT_UNLOCKSENDMESSAGE*/);
    }

    if (AkelPad.IsMDI())
      AkelPad.Command(4318 /*IDM_WINDOW_FRAMECLOSE*/);
    else
      AkelPad.Command(4324 /*IDM_WINDOW_FILECLOSE*/);

    if (bModified)
    {
      AkelPad.ScriptNoMutex(0x10 /*ULT_LOCKSENDMESSAGE*/);
      oSys.Call("User32::EnableWindow", aDlg.HWND, 1);

      if (bSeparateWnd)
        SetForegroundWindow(aDlg.HWND);

      oSys.Call("User32::SetFocus", hFocus);
    }
  }
  else
  {
    if (oFSO.FileExists(aAPD[nAPDSel][2]))
      AkelPad.OpenFile(aAPD[nAPDSel][2]);
    else
      AkelPad.MessageBox(aDlg.HWND, aAPD[nAPDSel][2] + "\n\n" + sTxtNoFile, sTxtDlgTitle, 0x30 /*MB_ICONWARNING*/);
  }
}

function InsertNameTo(bClipboard, bFull)
{
  if (nAPDSel >= 0)
  {
    var sName = aAPD[nAPDSel][2];

    if (! bFull)
      sName = sName.replace(/.+\\/, "");

    if (bClipboard)
      AkelPad.SetClipboardText(sName);
    else if (AkelPad.GetEditWnd() && (! AkelPad.GetEditReadOnly(0)))
      AkelPad.ReplaceSel(sName, -1);
  }
}

function InsertTextTo(bClipboard)
{
  var sText = GetSelTextAE();

  if (sText)
  {
    if (bClipboard)
      AkelPad.SetClipboardText(sText);
    else
      AkelPad.ReplaceSel(sText, -1);
  }
}

function FTDialog()
{
  aDlgFT.Parent = aDlg[IDTEXT].HWND;
  aDlgFT.Icon   = oSys.Call("User32::LoadImageW", AkelPad.GetInstanceDll(), 101, 1 /*uType=IMAGE_ICON*/, 0, 0, 0x40 /*LR_DEFAULTSIZE*/);

  oSys.Call("User32::SetFocus", aDlg[IDTEXT].HWND);
  SendMessage(aDlg[IDTEXT].HWND, 3228 /*AEM_SETOPTIONS*/, 2 /*AECOOP_OR*/, 0x00000004 /*AECO_NOHIDESEL*/);

  CreateDialogBox(aDlgFT);

  SendMessage(aDlg[IDTEXT].HWND, 3228 /*AEM_SETOPTIONS*/, 4 /*AECOOP_XOR*/, 0x00000004 /*AECO_NOHIDESEL*/);
  oSys.Call("User32::DestroyIcon", aDlgFT.Icon);
}

function FTDlgCallback(hWnd, uMsg, wParam, lParam)
{
  var nID, nCode;

  if (uMsg == 272 /*WM_INITDIALOG*/)
  {
    FillCB();
    SendMessage(aDlgFT[IDFTTEXT].HWND, 12 /*WM_SETTEXT*/, 0, GetSelTextAE() || aFT[0]);
    SendMessage(aDlgFT[IDFTCASE].HWND, 241 /*BM_SETCHECK*/, bCaseFT, 0);
    SendMessage(aDlgFT[IDFTALLDOC].HWND, 241 /*BM_SETCHECK*/, bAllDocFT, 0);
    SendMessage(aDlgFT[IDFTBEGIN + nDirectFT].HWND, 241 /*BM_SETCHECK*/, 1, 0);
    SendMessage(hWnd, 273 /*WM_COMMAND*/, MkLong(IDFTTEXT, 5 /*CBN_EDITCHANGE*/), aDlgFT[IDFTTEXT].HWND);

    if (SendMessage(AkelPad.GetEditWnd(), 3227 /*AEM_GETOPTIONS*/, 0, 0) & 0x00000800 /*AECO_ACTIVELINE*/)
      PostMessage(aDlg[IDTEXT].HWND, 3228 /*AEM_SETOPTIONS*/, 2 /*AECOOP_OR*/, 0x00000800 /*AECO_ACTIVELINE*/);
  }

  else if (uMsg == 6 /*WM_ACTIVATE*/)
  {
    if (wParam)
    {
      oSys.Call("User32::RegisterHotKey", hWnd, 1, 0, 0x72 /*VK_F3*/);
      oSys.Call("User32::RegisterHotKey", hWnd, 2, 0x4 /*MOD_SHIFT*/, 0x72 /*VK_F3*/);
    }
    else
    {
      oSys.Call("User32::UnregisterHotKey", hWnd, 1);
      oSys.Call("User32::UnregisterHotKey", hWnd, 2);
    }
  }

  else if (uMsg == 786 /*WM_HOTKEY*/)
  {
    if (oSys.Call("User32::IsWindowEnabled", aDlgFT[IDFTFIND].HWND) && ((wParam == 1) || (wParam == 2)))
    {
      FindText(wParam);
      PostMessage(aDlgFT.HWND, 16 /*WM_CLOSE*/, 0, 0);
    }
  }

  else if (uMsg == 273 /*WM_COMMAND*/)
  {
    nID   = LoWord(wParam);
    nCode = HiWord(wParam);

    if (nID == IDFTTEXT)
    {
      if (nCode == 1 /*CBN_SELCHANGE*/)
      {
        oSys.Call("User32::EnableWindow", aDlgFT[IDFTFIND].HWND, SendMessage(lParam, 327 /*CB_GETCURSEL*/, 0, 0) >= 0);
        bNewFT = 1;
      }
      else if (nCode == 5 /*CBN_EDITCHANGE*/)
      {
        oSys.Call("User32::EnableWindow", aDlgFT[IDFTFIND].HWND, SendMessage(lParam, 14 /*WM_GETTEXTLENGTH*/, 0, 0));
        bNewFT = 1;
      }
    }
    else if (nID == IDFTCASE)
    {
      bCaseFT = ! bCaseFT;
      bNewFT  = 1;
    }
    else if (nID == IDFTALLDOC)
    {
      bAllDocFT = ! bAllDocFT;
      bNewFT    = 1;
    }
    else if ((nID >= IDFTBEGIN) && (nID <= IDFTEND))
    {
      nDirectFT = nID - IDFTBEGIN;
      bNewFT    = 1;
    }
    else if (nID == IDFTFIND)
      FindText(nDirectFT, 1);
    else if ((nID == IDFTCANCEL) || (nID == 2 /*IDCANCEL*/))
      PostMessage(hWnd, 16 /*WM_CLOSE*/, 0, 0);
  }

  else if (uMsg == 16 /*WM_CLOSE*/)
    oSys.Call("User32::EndDialog", hWnd, wParam);
}

function FillCB()
{
  SendMessage(aDlgFT[IDFTTEXT].HWND, 331 /*CB_RESETCONTENT*/, 0, 0);

  for (var i = 0; i < aFT.length; ++i)
    SendMessage(aDlgFT[IDFTTEXT].HWND, 323 /*CB_ADDSTRING*/, 0, aFT[i]);
}

function FindText(nDirection, bMessage)
{
  var nTextLen = SendMessage(aDlgFT[IDFTTEXT].HWND, 14 /*WM_GETTEXTLENGTH*/, 0, 0) + 1;
  var lpText   = AkelPad.MemAlloc(nTextLen * 2);
  var sText;
  var i;

  SendMessage(aDlgFT[IDFTTEXT].HWND, 13 /*WM_GETTEXT*/, nTextLen, lpText);
  sText = AkelPad.MemRead(lpText, 1 /*DT_UNICODE*/);
  AkelPad.MemFree(lpText);

  for (i = 0; i < aFT.length; ++i)
  {
    if (aFT[i] == sText)
    {
      aFT.splice(i, 1);
      break;
    }
  }

  aFT.unshift(sText);
  if (aFT.length > 10) aFT.length = 10;
  FillCB();
  SendMessage(aDlgFT[IDFTTEXT].HWND, 334 /*CB_SETCURSEL*/, 0, 0);

  if (! bNewFT)
  {
    if (nDirection == 0)
      nDirection = 1;
    else if (nDirection == 3)
      nDirection = 2;
  }

  if (FindTextNext(nDirection))
    bNewFT = 0;
  else
  {
    bNewFT = 1;
    if (bMessage)
      AkelPad.MessageBox(aDlgFT.HWND, sTxtNotFound, aDlgFT.Title, 0x30 /*MB_ICONWARNING*/);
  }
}

function FindTextNext(nDirection)
{
  var bFound = false;
  var nNameStart;
  var nNameEnd;
  var nTextStart;
  var nSel;
  var i;

  oSys.Call("User32::SetFocus", aDlg[IDTEXT].HWND);

  if (nDirection < 2)
  {
    nNameStart = (nDirection == 0) && bAllDocFT ? 0 : nAPDSel;
    nNameEnd   = bAllDocFT ? aAPD.length - 1 : nAPDSel;
    nTextStart = (nDirection == 0) ? 0 : GetSelEndAE();

    for (i = nNameStart; i <= nNameEnd; ++i)
    {
      if (bCaseFT)
        nSel = aAPD[i][1].indexOf(aFT[0], (i == nNameStart) ? nTextStart : 0);
      else
        nSel = aAPD[i][1].toUpperCase().indexOf(aFT[0].toUpperCase(), (i == nNameStart) ? nTextStart : 0);

      if (nSel > -1)
      {
        SetCurSelLV(i);
        SetSelAE(nSel, nSel + aFT[0].length);
        bFound = true;
        break;
      }
    }
  }
  else
  {
    nNameEnd = bAllDocFT ? 0 : nAPDSel;

    if (nDirection == 2)
    {
      nNameStart = nAPDSel;
      nTextStart = GetSelStartAE() - aFT[0].length;

      if ((nTextStart < 0) && (--nNameStart >= 0))
        nTextStart = aAPD[nNameStart][1].length;
    }
    else
    {
      nNameStart = bAllDocFT ? aAPD.length - 1 : nAPDSel;
      nTextStart = aAPD[nNameStart][1].length;
    }

    for (i = nNameStart; i >= nNameEnd; --i)
    {
      if (bCaseFT)
        nSel = aAPD[i][1].lastIndexOf(aFT[0], (i == nNameStart) ? nTextStart : aAPD[i][1].length);
      else
        nSel = aAPD[i][1].toUpperCase().lastIndexOf(aFT[0].toUpperCase(), (i == nNameStart) ? nTextStart : aAPD[i][1].length);

      if (nSel > -1)
      {
        SetCurSelLV(i);
        SetSelAE(nSel, nSel + aFT[0].length);
        bFound = true;
        break;
      }
    }
  }

  return bFound;
}

function IsScriptRunning()
{
  var hDlg = oSys.Call("User32::FindWindowExW", 0, 0, sClass, 0);

  if (hDlg)
  {
    SetForegroundWindow(hDlg);
    return true;
  }
}

function ReadIni()
{
  var i;

  try
  {
    eval(AkelPad.ReadFile(WScript.ScriptFullName.replace(/\.js$/i, ".ini"), 0x10 /*OD_ADT_NOMESSAGES*/, 1200 /*UTF-16LE*/, true));
  }
  catch (oError)
  {}

  aDlg.W = Math.max(aDlg.W, aDlg.MinW);
  aDlg.H = Math.max(aDlg.H, aDlg.MinH);

  if (! (aAESel instanceof Array))
    aAESel = [{}, {}];
  if (! (aFT instanceof Array))
    aFT = [];
  if (! (aDocOwn instanceof Array))
    aDocOwn = [];

  for (i = aDocOwn.length - 1; i >= 0; --i)
  {
    if ((! (aDocOwn[i] instanceof Array)) || (aDocOwn[i].length < 2) || (typeof aDocOwn[i][0] != "string") || (typeof aDocOwn[i][1] != "string"))
      aDocOwn.splice(i, 1);
  }

  if (! aDocOwn.length)
  {
    for (i = 0; i < aDocStd.length; ++i)
      aDocOwn[i] = [aDocStd[i][0], aDocStd[i][1]];
  }
}

function WriteIni()
{
  var oRW = {};
  var oRC = {};
  var sText;
  var i;

  GetWindowPos(aDlg.HWND, oRW);
  GetWindowPos(aDlg.HWND, oRC, 1);

  sText =
    'aDlg.X='       + Scale.UX(aDlg.X) + ';\r\n' +
    'aDlg.Y='       + Scale.UY(aDlg.Y) + ';\r\n' +
    'aDlg.W='       + (Scale.UX(aDlg.W - (oRW.W - oRC.W)) + (oRW.W - oRC.W)) + ';\r\n' +
    'aDlg.H='       + (Scale.UY(aDlg.H - (oRW.H - oRC.H)) + (oRW.H - oRC.H)) + ';\r\n' +
    'aDlg.Maxim='   + oSys.Call("User32::IsZoomed", aDlg.HWND) + ';\r\n' +
    'bCaseFT='      + bCaseFT + ';\r\n' +
    'bAllDocFT='    + bAllDocFT + ';\r\n' +
    'nDirectFT='    + nDirectFT + ';\r\n' +
    'bWordWrap='    + bWordWrap + ';\r\n' +
    'bSeparateWnd=' + bSeparateWnd + ';\r\n' +
    'nLang='        + nLang + ';\r\n' +
    'nAPDSel='      + nAPDSel + ';\r\n' +
    'sAPDSel="'     + aAPD[nAPDSel][0] + '";\r\n' +
    'aAESel=[';

  for (i = 0; i < aAESel.length; ++i)
  {
    sText += '{';
    for (n in aAESel[i])
      sText += '"' + n + '":[' + aAESel[i][n] + '],';
    if (sText.slice(-1) == ',')
      sText = sText.slice(0, -1);
    sText += '}' + (i < aAESel.length - 1 ? ',' : '');
  }

  sText += '];\r\naFT=[';

  for (i = 0; i < aFT.length; ++i)
    sText += '"' + EscapeStr(aFT[i]) + '"' + (i < aFT.length - 1 ? ',' : '');

  sText += '];\r\n\r\n//you can edit array of documents:\r\naDocOwn=[\r\n';

  for (i = 0; i < aDocOwn.length; ++i)
    sText += '["' + aDocOwn[i][0] + '","' + aDocOwn[i][1] + '"]' + (i < aDocOwn.length - 1 ? ',' : '') + '\r\n';

  sText += '];\r\n';
	
  AkelPad.WriteFile(WScript.ScriptFullName.replace(/\.js$/i, ".ini"), sText, sText.length, 1200 /*UTF-16LE*/, true);
}

function EscapeStr(sText)
{
  return sText.replace(/[\\"]/g, '\\$&').replace(/\n/g, '\\n').replace(/\r/g, '\\r');
}

function GetLangStrings()
{
  if (AkelPad.GetLangId(0 /*LANGID_FULL*/) == 1049 /*Russian*/)
  {
    //translated by Andrey_A_A
    sTxtDlgTitle     = "Просмотр документации AkelPad";
    sTxtDocument     = "Документ";
    sTxtEnglish      = "&Английский";
    sTxtRussian      = "&Русский";
    sTxtMenu         = "&Меню";
    sTxtClose        = "Закрыть";
    sTxtFindInHtm    = "Поиск в документе htm";
    sTxtFindInTxt    = "Поиск в документах *.txt";
    sTxtWrapLines    = "Перенос строк в документах *.txt";
    sTxtSeparateWnd  = "Запускать в отдельном окне";
    sTxtOpenClose    = "Открыть/Закрыть файл в AkelPad";
    sTxtFileName     = "Имя файла:";
    sTxtFileNamePath = "Полный путь файла:";
    sTxtCopyToCB     = "Копировать";
    sTxtInsertToAP   = "Вставить в AkelPad";
    sTxtSelectAll    = "Выделить всё";
    sTxtWhat         = "&Что:";
    sTxtMatchCase    = "&Регистр";
    sTxtAllDocs      = "&Во всех";
    sTxtDirection    = "Направление";
    sTxtBeginning    = "&С начала";
    sTxtDown         = "&Вниз";
    sTxtUp           = "&Вверх";
    sTxtEnd          = "&C конца";
    sTxtFindNext     = "&Найти далее";
    sTxtCancel       = "Отмена";
    sTxtFind         = "Поиск...";
    sTxtFindNextDn   = "Найти далее вниз";
    sTxtFindNextUp   = "Найти далее ввех";
    sTxtNotFound     = "Не найдено.";
    sTxtNoFilesInDir = "В каталоге нет файлов:";
    sTxtChooseDir    = "Выберите каталог с документацией AkelPad:";
    sTxtNoFile       = "Файл не существует.";
    sTxtNoIE         = "Нет в наличии Internet Explorer.";
    sTxtNoCallback   = "Невозможно зарегистрировать функцию обратного вызова.";
    sTxtErrMessage   = "Сообщение об ошибке: ";
    sTxtErrNumber    = "Номер ошибки: ";
  }
  else
  {
    sTxtDlgTitle     = "AkelPad documents view";
    sTxtDocument     = "Document";
    sTxtEnglish      = "&English";
    sTxtRussian      = "&Russian";
    sTxtMenu         = "&Menu";
    sTxtClose        = "Close";
    sTxtFindInHtm    = "Find in htm document";
    sTxtFindInTxt    = "Find in *.txt documents";
    sTxtWrapLines    = "Wrap lines in *.txt documents";
    sTxtSeparateWnd  = "Run in separate window";
    sTxtOpenClose    = "Open/close file in AkelPad";
    sTxtFileName     = "File name:";
    sTxtFileNamePath = "Full  file name with path:";
    sTxtCopyToCB     = "Copy to clipboard";
    sTxtInsertToAP   = "Insert to AkelPad";
    sTxtSelectAll    = "Select all";
    sTxtWhat         = "&What:";
    sTxtMatchCase    = "&Match case";
    sTxtAllDocs      = "&All documents";
    sTxtDirection    = "Direction";
    sTxtBeginning    = "&Beginning";
    sTxtDown         = "&Down";
    sTxtUp           = "&up";
    sTxtEnd          = "&End";
    sTxtFindNext     = "&Find next";
    sTxtCancel       = "Cancel";
    sTxtFind         = "Find...";
    sTxtFindNextDn   = "Find next down";
    sTxtFindNextUp   = "Find next up";
    sTxtNotFound     = "Not found.";
    sTxtNoFilesInDir = "Files not found in directory:";
    sTxtChooseDir    = "Choose directory with AkelPad documentation:";
    sTxtNoFile       = "File does not exists.";
    sTxtNoIE         = "Internet Explorer is not available.";
    sTxtNoCallback   = "Unable to register callback function.";
    sTxtErrMessage   = "Error message: ";
    sTxtErrNumber    = "Error number: ";
  }
}
