// http://akelpad.sourceforge.net/forum/viewtopic.php?p=29221#29221
// Version: 2016-08-05
// Author: KDJ
//
// *** Preview html file in WebBrowser control ***
//
// Usage:
//   Call("Scripts::Main", 1, "HtmlView.js")             - preview of currently edited file
//   Call("Scripts::Main", 1, "HtmlView.js", "htmlFile") - preview file/url specified as an argument
// Run from command line (required registration: regsvr32.exe Scripts.dll):
//   wscript.exe HtmlView.js
//   wscript.exe HtmlView.js htmlFile
//
// Argument:
//   htmlFile - full file name with path or url
//
// Keyboard and mouse:
//   F5 - reload current file/url (refresh)
//   Alt+Left - navigate backward
//   Alt+Right - navigate forward
//   Ctrl+A - select all text
//   Ctrl+C or Ctrl+Ins - copy selected text
//   Ctrl+F - find dialog
//   Ctrl+H or RClick on status bar - history
//   Ctrl+O or LClick on status bar - "Open" input box
//   F4 or Alt+Enter- maximize/restore window
//   Alt+Del - in "Open" dialog (ComboBox list) - remove item from history list
//
// Remarks:
//   This script should be saved in Unicode format.
//   WebBrowser control displays html in IE7 mode by default (https://msdn.microsoft.com/en-us/library/ee330730%28v=vs.85%29.aspx). To change it, you should add in registry, eg:
//     [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION]
//     "AkelPad.exe"=dword:00002af8
//     "wscript.exe"=dword:00002af8

if (typeof AkelPad == "undefined")
{
  try
  {
    AkelPad = new ActiveXObject("AkelPad.Document");
    _PtrAdd = function(n1, n2) {return AkelPad.Global._PtrAdd(n1, n2);};
    _X64    = AkelPad.Constants._X64;
    AkelPad.ActiveXThis(this);
  }
  catch (oError)
  {
    WScript.Echo("You need to register Scripts.dll");
    WScript.Quit();
  }
}

var IDCANCEL = 2;
var IDWB     = 1000;
var IDSB     = 1001;
var hMainWnd = AkelPad.GetMainWnd();
var oSys     = AkelPad.SystemFunction();
var hInstDLL = AkelPad.GetInstanceDll();
var sClass   = "AkelPad::Scripts::" + WScript.ScriptName + "::" + hInstDLL;
var hDlg;

GetLangStrings();

if (IsScriptRunning())
  WScript.Quit();

var hIconSmall = oSys.Call("User32::LoadImageW",
                   hInstDLL, //hinst
                   101,      //lpszName
                   1,        //uType=IMAGE_ICON
                   16,       //cxDesired
                   16,       //cyDesired
                   0);       //fuLoad
var hIconBig = oSys.Call("User32::LoadImageW",
                 hInstDLL, //hinst
                 101,      //lpszName
                 1,        //uType=IMAGE_ICON
                 32,       //cxDesired
                 32,       //cyDesired
                 0);       //fuLoad
var aHotKey = [[0x1 /*MOD_ALT*/, 0x25 /*VK_LEFT*/],
               [0x1 /*MOD_ALT*/, 0x27 /*VK_RIGHT*/],
               [0x1 /*MOD_ALT*/, 0x0D /*VK_RETURN*/]];

var oFSO     = new ActiveXObject("Scripting.FileSystemObject");
var hAtlLib  = oSys.Call("Kernel32::LoadLibraryW", "Atl.dll");
var sWBTitle = "Shell.Explorer.2";
var nDlgX    = 200;
var nDlgY    = 100;
var nDlgW    = 600;
var nDlgH    = 400;
var bDlgMax  = 0;
var sLastDir = "";
var nHistMax = 15;
var aHist;
var hWndWB;
var hWndSB;
var oWB;

ReadIni();

if (oSys.Call("Atl::AtlAxWinInit"))
{
  AkelPad.ScriptNoMutex(0x11 /*ULT_LOCKSENDMESSAGE|ULT_UNLOCKSCRIPTSQUEUE*/);
  AkelPad.WindowRegisterClass(sClass);

  //0x50000000 = WS_VISIBLE|WS_CHILD
  //0x50000900 = WS_VISIBLE|WS_CHILD|SBARS_TOOLTIPS|SBARS_SIZEGRIP
  //0x90CF0040 = WS_VISIBLE|WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_SIZEBOX|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|DS_SETFONT
  AkelPad.CreateDialog(0, sClass, sTxtDlgTitle, 0x90CF0040, nDlgX, nDlgY, nDlgW, nDlgH, 0, DlgCallback, 0x2 /*CDF_PIXELS*/, 0, 0, "", 0, 0, "|",
    //ExSt, Class,                Title,    Style,      X, Y, W, H, ID,   lParam
    0x0000, "AtlAxWin",           sWBTitle, 0x50000000, 0, 0, 0, 0, IDWB, 0, "|",
    0x0000, "msctls_statusbar32", "",       0x50000900, 0, 0, 0, 0, IDSB, 0);

  if (hDlg)
    AkelPad.WindowGetMessage(0x4 /*WGM_KEYDOWNUP*/);

  AkelPad.WindowUnregisterClass(sClass);
}

oSys.Call("Kernel32::FreeLibrary", hAtlLib);
oSys.Call("User32::DestroyIcon", hIconSmall);
oSys.Call("User32::DestroyIcon", hIconBig);

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

  if (uMsg == 272 /*WM_INITDIALOG*/)
  {
    hDlg   = hWnd;
    hWndWB = GetDlgItem(hDlg, IDWB);
    hWndSB = GetDlgItem(hDlg, IDSB);

    SendMessage(hDlg, 128 /*WM_SETICON*/, 0 /*ICON_SMALL*/, hIconSmall);
    SendMessage(hDlg, 128 /*WM_SETICON*/, 1 /*ICON_BIG*/,   hIconBig);
    oSys.Call("User32::ShowWindow", hDlg, bDlgMax ? 3 /*SW_MAXIMIZE*/ : 1 /*SW_SHOWNORMAL*/);
    ResizeDlg();
    GetWBObject();

    if (oWB && (sWBTitle = GetFile(1)))
      Navigate(sWBTitle);
    else
      PostMessage(hDlg, 16 /*WM_CLOSE*/, 0, 0);
  }

  else if (uMsg == 0x8000 /*WM_APP*/)
    Navigate(GetTextSB());

  else if (uMsg == 36 /*WM_GETMINMAXINFO*/)
  {
    AkelPad.MemCopy(_PtrAdd(lParam, 24), 200, 3 /*DT_DWORD*/); //ptMinTrackSize_x
    AkelPad.MemCopy(_PtrAdd(lParam, 28), 200, 3 /*DT_DWORD*/); //ptMinTrackSize_y
  }

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

  else if (uMsg == 5 /*WM_SIZE*/)
  {
    if (wParam == 0 /*SIZE_RESTORED*/)
      GetDlgPos();

    ResizeDlg();
  }

  else if (uMsg == 6 /*WM_ACTIVATE*/)
  {
    if (LoWord(wParam))
    {
      for (i = 0; i < aHotKey.length; ++i)
        oSys.Call("User32::RegisterHotKey", hDlg, i, aHotKey[i][0], aHotKey[i][1]);
    }
    else
    {
      for (i = 0; i < aHotKey.length; ++i)
        oSys.Call("User32::UnregisterHotKey", hDlg, i);
    }
  }

  else if (uMsg == 786 /*WM_HOTKEY*/)
  {
    switch (wParam)
    {
      case 0: //Alt+Left
        try {oWB.GoBack();}
        catch (oError) {}
        break;
      case 1: //Alt+Right
        try {oWB.GoForward();}
        catch (oError) {}
        break;
      case 2: //Alt+Enter
        oSys.Call("User32::ShowWindow", hDlg, oSys.Call("User32::IsZoomed", hDlg) ? 9 /*SW_RESTORE*/ : 3 /*SW_MAXIMIZE*/);
    }
    }

  else if (uMsg == 256 /*WM_KEYDOWN*/)
  {
    if (wParam == 0x41 /*A key*/)
    {
      if (Ctrl() && (! Shift()) && (! Alt()))
        oWB.ExecWB(17 /*OLECMDID_SELECTALL*/, 0, 0, 0);
    }
    else if ((wParam == 0x43 /*C key*/) || (wParam == 0x2D /*VK_INSERT*/))
    {
      if (Ctrl() && (! Shift()) && (! Alt()))
        oWB.ExecWB(12 /*OLECMDID_COPY*/, 0, 0, 0);
    }
    else if (wParam == 0x46 /*F key*/)
    {
      if (Ctrl() && (! Shift()) && (! Alt()))
        oWB.ExecWB(32 /*OLECMDID_FIND*/, 0, 0, 0);
    }
    else if (wParam == 0x48 /*H key*/)
    {
      if (Ctrl() && (! Shift()) && (! Alt()))
        HistoryMenu(0);
    }
    else if (wParam == 0x4F /*O key*/)
    {
      if (Ctrl() && (! Shift()) && (! Alt()))
        Navigate(GetFile(0));
    }
    else if (wParam == 0x73 /*F4*/)
    {
      if ((!Ctrl()) && (! Shift()))
        oSys.Call("User32::ShowWindow", hDlg, oSys.Call("User32::IsZoomed", hDlg) ? 9 /*SW_RESTORE*/ : 3 /*SW_MAXIMIZE*/);
    }
    else if (wParam == 0x74 /*F5*/)
    {
      if ((!Ctrl()) && (! Shift()))
        oWB.Refresh();
    }
    else if (wParam == 0x09 /*VK_TAB*/)
      SetFocusWB();
  }

  else if (uMsg == 78 /*WM_NOTIFY*/)
  {
    if (wParam == IDSB)
    {
      switch (AkelPad.MemRead(_PtrAdd(lParam, _X64 ? 16 : 8), 3 /*DT_DWORD*/)) //NMMOUSE.NMHDR.code
      {
        case -2: //NM_CLICK
          Navigate(GetFile(0));
          break;
        case -5: //NM_RCLICK
          HistoryMenu(_PtrAdd(lParam, _X64 ? 32 : 20) /*NMMOUSE.pt*/);
      }
    }
  }

  else if (uMsg == 273 /*WM_COMMAND*/)
  {
    if (LoWord(wParam) == IDCANCEL)
      PostMessage(hDlg, 16 /*WM_CLOSE*/, 0, 0);
  }

  else if (uMsg == 16 /*WM_CLOSE*/)
  {
    WriteIni();
    AkelPad.DisconnectObject(oWB);
    oSys.Call("User32::PostQuitMessage", 0);
    oSys.Call("User32::DestroyWindow", hDlg);
  }

  return 0;
}

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

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

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 SendDlgItemMessage(hWnd, nID, uMsg, wParam, lParam)
{
  return oSys.Call("User32::SendDlgItemMessageW", hWnd, nID, uMsg, wParam, lParam);
}

function GetDlgItem(hWnd, nID)
{
  return oSys.Call("User32::GetDlgItem", hWnd, nID);
}

function GetDlgPos()
{
  var lpRECT = AkelPad.MemAlloc(16 /*sizeof(RECT)*/);

  oSys.Call("User32::GetWindowRect", hDlg, lpRECT);
  nDlgX = AkelPad.MemRead(_PtrAdd(lpRECT,  0), 3 /*DT_DWORD*/);
  nDlgY = AkelPad.MemRead(_PtrAdd(lpRECT,  4), 3 /*DT_DWORD*/);
  oSys.Call("User32::GetClientRect", hDlg, lpRECT);
  nDlgW = AkelPad.MemRead(_PtrAdd(lpRECT,  8), 3 /*DT_DWORD*/);
  nDlgH = AkelPad.MemRead(_PtrAdd(lpRECT, 12), 3 /*DT_DWORD*/);

  AkelPad.MemFree(lpRECT);
}

function SetFocusWB()
{
  var oDoc = oWB.Document;

  if ((typeof oDoc == "object") && (oDoc != null))
  {
    if ((typeof oDoc.focus == "object") && (oDoc.focus != null))
      oDoc.focus();
  }
}

function GetTextSB()
{
  var sText    = "";
  var nTextLen = SendMessage(hWndSB, 1036 /*SB_GETTEXTLENGTHW*/, 0, 0);
  var lpText;

  if (nTextLen)
  {
    lpText = AkelPad.MemAlloc(nTextLen * 2 + 2);
    SendMessage(hWndSB, 1037 /*SB_GETTEXTW*/, 0, lpText);
    sText = AkelPad.MemRead(lpText, 1 /*DT_UNICODE*/);
    AkelPad.MemFree(lpText);
  }

  return sText;
}

function SetTextSB(sText)
{
  SendMessage(hWndSB, 1035 /*SB_SETTEXTW*/, 0, sText);
  SendMessage(hWndSB, 1041 /*SB_SETTIPTEXTW*/, 0, sText);
}

function ResizeDlg()
{
  var lpRECT = AkelPad.MemAlloc(16 /*sizeof(RECT)*/);
  var nW, nH, nSBH;

  oSys.Call("User32::GetClientRect", hDlg, lpRECT);
  nW = AkelPad.MemRead(_PtrAdd(lpRECT,  8), 3 /*DT_DWORD*/);
  nH = AkelPad.MemRead(_PtrAdd(lpRECT, 12), 3 /*DT_DWORD*/);

  oSys.Call("User32::GetClientRect", hWndSB, lpRECT);
  nSBH = AkelPad.MemRead(_PtrAdd(lpRECT, 12), 3 /*DT_DWORD*/);
  AkelPad.MemFree(lpRECT);

  oSys.Call("User32::SetWindowPos",
    hWndWB, 0,
    0,
    0,
    nW,
    nH - nSBH,
    0x14 /*SWP_NOACTIVATE|SWP_NOZORDER*/);

  SendMessage(hWndSB, 5 /*WM_SIZE*/, 0, 0);
}

function GetWBObject()
{
  var lppUnknown = AkelPad.MemAlloc(_X64 ? 8 : 4 /*sizeof(IUnknown**)*/);
  var lpUnknown;

  if (oSys.Call("Atl::AtlAxGetControl", hWndWB, lppUnknown) == 0 /*S_OK*/)
  {
    lpUnknown  = AkelPad.MemRead(lppUnknown, 2 /*DT_QWORD*/);
    oWB        = AkelPad.VarDispatch(lpUnknown);
    oWB.Silent = true;
    AkelPad.ConnectObject(oWB, "WB_", "{34A715A0-6587-11D0-924A-0020AFC7AC4D}" /*DIID_DWebBrowserEvents2*/);
  }

  AkelPad.MemFree(lppUnknown);
}

function Navigate(sFile)
{
  if (sFile)
  {
    if (oWB.Busy)
      oWB.Stop();

    sWBTitle = sFile;
    HistoryAdd();
    SetTextSB(sFile);
    oWB.Navigate(sFile);
  }
}

function WB_NavigateComplete2(pDisp, URL)
{
  SetFocusWB();
}

function WB_DocumentComplete(pDisp, URL)
{
  SetTextSB(URL);
  SetFocusWB();
}

function IsScriptRunning()
{
  var sFile;

  if (hDlg = oSys.Call("User32::FindWindowExW", 0, 0, sClass, 0))
  {
    if (! oSys.Call("User32::IsWindowVisible", hDlg))
      oSys.Call("User32::ShowWindow", hDlg, 8 /*SW_SHOWNA*/);
    if (oSys.Call("User32::IsIconic", hDlg))
      oSys.Call("User32::ShowWindow", hDlg, 9 /*SW_RESTORE*/);
  
    oSys.Call("User32::SetForegroundWindow", hDlg);

    if (sFile = GetFile(2))
    {
      SendMessage(GetDlgItem(hDlg, IDSB), 12 /*WM_SETTEXT*/, 0, sFile);
      SendMessage(hDlg, 0x8000 /*WM_APP*/, 0, 0);
    }
  }

  return hDlg;
}

function GetFile(nOnInit)
{
  var sFile = "";

  if (nOnInit)
  {
    if (WScript.Arguments.length)
      sFile = LRTrim(WScript.Arguments(0));
    else
      sFile = AkelPad.GetEditFile(0);
  }

  if (sFile)
  {
    if ((! WScript.Arguments.length) && AkelPad.GetEditModified(0))
    {
      switch (AkelPad.MessageBox(hDlg, sTxtDocMod, sTxtDlgTitle, 0x23 /*MB_ICONQUESTION|MB_YESNOCANCEL*/))
      {
        case 6 /*IDYES*/:
          AkelPad.SaveFile(0, sFile);
          break;
        case 2 /*IDCANCEL*/:
          sFile = "";
      }
    }
  }
  else if (nOnInit < 2)
  {
    if (nOnInit == 1)
    {
      if (aHist.length)
        sFile = aHist[0];
      else
      {
        if (hMainWnd)
          sFile = AkelPad.GetAkelDir(2 /*ADTYPE_DOCS*/) + "\\AkelHelp-Chs.htm";
        else
          sFile = "http://akelpad.sourceforge.net";
      }
    }
    else
      sFile = sWBTitle;

    sFile = InputBox(sFile);

    if (sFile)
      sFile = LRTrim(sFile);
  }

  return sFile;
}

function LRTrim(sText)
{
  return sText.replace(/^\s+|\s+$/g, "");
}

function HistoryAdd()
{
  var i;

  for (i = aHist.length - 1; i >= 0; --i)
  {
    if (aHist[i].toLowerCase() == sWBTitle.toLowerCase())
      aHist.splice(i, 1);
  }

  aHist.unshift(sWBTitle);

  if (aHist.length > nHistMax)
    aHist.length = nHistMax;
}

function HistoryMenu(lpPOINT)
{
  if (! aHist.length)
    return;

  var MF_STRING    = 0x0000;
  var MF_SEPARATOR = 0x0800;
  var nFlags = 0x01A0 /*TPM_RETURNCMD|TPM_NONOTIFY|TPM_BOTTOMALIGN*/;
  var hMenu  = oSys.Call("User32::CreatePopupMenu");
  var lpRECT;
  var nX, nY;
  var nCmd;
  var i;

  if (lpPOINT)
  {
    //menu from mouse
    oSys.Call("User32::ClientToScreen", hWndSB, lpPOINT);
    nX = AkelPad.MemRead(_PtrAdd(lpPOINT, 0), 3 /*DT_DWORD*/);
    nY = AkelPad.MemRead(_PtrAdd(lpPOINT, 4), 3 /*DT_DWORD*/);
    nFlags |= 0x0004 /*TPM_CENTERALIGN*/;
  }
  else
  {
    lpRECT = AkelPad.MemAlloc(16 /*sizeof(RECT)*/);
    oSys.Call("User32::GetWindowRect", hWndSB, lpRECT);
    nX = AkelPad.MemRead(_PtrAdd(lpRECT, 0), 3 /*DT_DWORD*/);
    nY = AkelPad.MemRead(_PtrAdd(lpRECT, 4), 3 /*DT_DWORD*/);
    AkelPad.MemFree(lpRECT);
  }

  for (i = 0; i < aHist.length; ++i)
    oSys.Call("User32::AppendMenuW", hMenu, MF_STRING, i + 1, aHist[i]);

  oSys.Call("User32::AppendMenuW", hMenu, MF_SEPARATOR, 0, 0);
  oSys.Call("User32::AppendMenuW", hMenu, MF_STRING, aHist.length + 1, sTxtClearHist);

  nCmd = oSys.Call("User32::TrackPopupMenu", hMenu, nFlags, nX, nY, 0, hDlg, 0);

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

  if (nCmd--)
  {
    if (nCmd == aHist.length)
      aHist.length = 0;
    else
      Navigate(aHist[nCmd]);
  }
}

function InputBox(sText)
{
  var IDSTATIC   = -1;
  var IDOK       = 1;
  var IDCOMBO    = 9000;
  var IDBROWSE   = 9001;
  var nLimitText = 2048;
  var lpText     = AkelPad.MemAlloc((nLimitText + 1) * 2);
  var hWndIB;
  var hWndCB;

  //0x50000000 = WS_VISIBLE|WS_CHILD
  //0x50010000 = WS_VISIBLE|WS_CHILD|WS_TABSTOP
  //0x50010001 = WS_VISIBLE|WS_CHILD|WS_TABSTOP|BS_DEFPUSHBUTTON
  //0x50010042 = WS_VISIBLE|WS_CHILD|WS_TABSTOP|CBS_AUTOHSCROLL|CBS_DROPDOWN
  //0x90C80040 = WS_VISIBLE|WS_POPUP|WS_CAPTION|WS_SYSMENU|DS_SETFONT
  AkelPad.CreateDialog(0, sClass, sTxtOpen, 0x90C80040, 0, 0, 400, 90, hDlg, InputBoxCallback, 0x3 /*CDF_PIXELS|CDF_MODAL*/, 0, 0, "", 0, 0, "|",
    //ExSt, Class,      Title,              Style,        X,  Y,   W,   H, ID,       lParam
    0x0000, "STATIC",   sTxtFileUrl,        0x50000000,  10, 10, 380,  13, IDSTATIC, 0, "|",
    0x0000, "COMBOBOX", "",                 0x50010042,  10, 26, 380, 300, IDCOMBO,  0, "|",
    0x0000, "BUTTON",   sTxtOK,             0x50010001, 130, 57,  80,  23, IDOK,     0, "|",
    0x0000, "BUTTON",   sTxtCancel,         0x50010000, 220, 57,  80,  23, IDCANCEL, 0, "|",
    0x0000, "BUTTON",   sTxtBrowse + "...", 0x50010000, 310, 57,  80,  23, IDBROWSE, 0);

  sText = AkelPad.MemRead(lpText, 1 /*DT_UNICODE*/);
  AkelPad.MemFree(lpText);
  return sText;

  function InputBoxCallback(hWnd, uMsg, wParam, lParam)
  {
    var i;

    if (uMsg == 272 /*WM_INITDIALOG*/)
    {
      hWndIB = hWnd;
      hWndCB = GetDlgItem(hWndIB, IDCOMBO);

      SendMessage(hWndIB, 128 /*WM_SETICON*/, 0 /*ICON_SMALL*/, hIconSmall);

      SendMessage(hWndCB, 341 /*CB_SETEXTENDEDUI*/, 1, 0);
      SendMessage(hWndCB, 321 /*CB_LIMITTEXT*/, nLimitText, 0);
      SendMessage(hWndCB, 12 /*WM_SETTEXT*/, 0, sText);
      for (i = 0; i < aHist.length; ++i)
        SendMessage(hWndCB, 323 /*CB_ADDSTRING*/, 0, aHist[i]);

      InputBoxCenter();
    }

    else if (uMsg == 786 /*WM_HOTKEY*/)
    {
      if (wParam == 1)
        HistoryDelete();
    }

    else if (uMsg == 273 /*WM_COMMAND*/)
    {
      switch (LoWord(wParam))
      {
        case IDCOMBO:
          switch (HiWord(wParam))
          {
            case 7: //CBN_DROPDOWN
              oSys.Call("User32::RegisterHotKey", hWndIB, 1, 0x1 /*MOD_ALT*/, 0x2E /*VK_DELETE*/);
              break;
            case 8: //CBN_CLOSEUP
              oSys.Call("User32::UnregisterHotKey", hWndIB, 1);
          }
          break;
        case IDOK:
          SendMessage(hWndCB, 13 /*WM_GETTEXT*/, nLimitText + 1, lpText);
        case IDCANCEL:
          oSys.Call("User32::EndDialog", hWndIB, 0);
          break;
        case IDBROWSE:
          GetOpenFileName();
      }
    }

    return 0;
  }

  function InputBoxCenter()
  {
    var lpRECT1 = AkelPad.MemAlloc(16 /*sizeof(RECT)*/);
    var lpRECT2 = AkelPad.MemAlloc(16 /*sizeof(RECT)*/);
    var nX, nY;

    oSys.Call("User32::GetWindowRect", hDlg,   lpRECT1);
    oSys.Call("User32::GetWindowRect", hWndIB, lpRECT2);
    nX = (AkelPad.MemRead(_PtrAdd(lpRECT1,  0), 3 /*DT_DWORD*/) + AkelPad.MemRead(_PtrAdd(lpRECT1,  8), 3 /*DT_DWORD*/) + AkelPad.MemRead(_PtrAdd(lpRECT2,  0), 3 /*DT_DWORD*/) - AkelPad.MemRead(_PtrAdd(lpRECT2,  8), 3 /*DT_DWORD*/)) / 2;
    nY = (AkelPad.MemRead(_PtrAdd(lpRECT1,  4), 3 /*DT_DWORD*/) + AkelPad.MemRead(_PtrAdd(lpRECT1, 12), 3 /*DT_DWORD*/) + AkelPad.MemRead(_PtrAdd(lpRECT2,  4), 3 /*DT_DWORD*/) - AkelPad.MemRead(_PtrAdd(lpRECT2, 12), 3 /*DT_DWORD*/)) / 2;
    AkelPad.MemFree(lpRECT1);
    AkelPad.MemFree(lpRECT2);

    oSys.Call("User32::SetWindowPos", hWndIB, 0, nX, nY, 0, 0, 0x15 /*SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE*/);
  }

  function HistoryDelete()
  {
    var nSel = SendMessage(hWndCB, 327 /*CB_GETCURSEL*/, 0, 0);

    if (nSel >= 0)
    {
      aHist.splice(nSel, 1);
      SendMessage(hWndCB, 324 /*CB_DELETESTRING*/, nSel, 0);

      if (nSel == aHist.length)
        --nSel;

      if (nSel == -1)
        SendMessage(hWndCB, 335 /*CB_SHOWDROPDOWN*/, 0, 0);
      else
        SendMessage(hWndCB, 334 /*CB_SETCURSEL*/, nSel, 0);
    }
  }

  function GetOpenFileName()
  {
    var sFilter  = "*.htm; *.html\0*.htm;*.html\0*.*\0*.*\0\0";
    var sTitle   = sTxtBrowse.replace("&", "");
    var lpRECT   = AkelPad.MemAlloc(16 /*sizeof(RECT)*/);
    var lpCurDir = AkelPad.MemAlloc(260 * 2);
    var lpFilter = AkelPad.MemAlloc((sFilter.length + 1) * 2);
    var lpFile   = AkelPad.MemAlloc(260 * 2);
    var lpDir    = AkelPad.MemAlloc(260 * 2);
    var lpTitle  = AkelPad.MemAlloc((sTitle.length + 1) * 2);
    var nOFNSize = _X64 ? 152 : 88 /*sizeof(OPENFILENAME)*/;
    var lpOFN    = AkelPad.MemAlloc(nOFNSize);
    var nFlags   = 0x02081026 /*OFN_DONTADDTORECENT|OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_ENABLEHOOK|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT*/;
    var sCurDir;
    var hWndOwn;
    var nX, nY;
    var bOpen;

    oSys.Call("Kernel32::GetCurrentDirectoryW", 260, lpCurDir);
    sCurDir = AkelPad.MemRead(lpCurDir, 1 /*DT_UNICODE*/);

    oSys.Call("User32::GetWindowRect", hWndCB, lpRECT);
    nX = AkelPad.MemRead(_PtrAdd(lpRECT,  0), 3 /*DT_DWORD*/);
    nY = AkelPad.MemRead(_PtrAdd(lpRECT, 12), 3 /*DT_DWORD*/) + 3;

    hWndOwn = oSys.Call("User32::CreateWindowExW", 0, "STATIC", 0, 0x80000000 /*WS_POPUP*/, nX, nY, 0, 0, hWndIB, 0, hInstDLL, 0);

    AkelPad.MemCopy(lpFilter, sFilter, 1 /*DT_UNICODE*/);
    AkelPad.MemCopy(lpTitle,  sTitle,  1 /*DT_UNICODE*/);
    AkelPad.MemCopy(lpDir, oFSO.FolderExists(sLastDir) ? sLastDir : sCurDir, 1 /*DT_UNICODE*/);

    AkelPad.MemCopy(_PtrAdd(lpOFN,               0), nOFNSize, 3 /*DT_DWORD*/); //lStructSize
    AkelPad.MemCopy(_PtrAdd(lpOFN, _X64 ?   8 :  4),  hWndOwn, 2 /*DT_QWORD*/); //hwndOwner
    AkelPad.MemCopy(_PtrAdd(lpOFN, _X64 ?  24 : 12), lpFilter, 2 /*DT_QWORD*/); //lpstrFilter
    AkelPad.MemCopy(_PtrAdd(lpOFN, _X64 ?  44 : 24),        1, 3 /*DT_DWORD*/); //nFilterIndex
    AkelPad.MemCopy(_PtrAdd(lpOFN, _X64 ?  48 : 28),   lpFile, 2 /*DT_QWORD*/); //lpstrFile
    AkelPad.MemCopy(_PtrAdd(lpOFN, _X64 ?  56 : 32),      260, 3 /*DT_DWORD*/); //nMaxFile
    AkelPad.MemCopy(_PtrAdd(lpOFN, _X64 ?  80 : 44),    lpDir, 2 /*DT_QWORD*/); //lpstrInitialDir
    AkelPad.MemCopy(_PtrAdd(lpOFN, _X64 ?  88 : 48),  lpTitle, 2 /*DT_QWORD*/); //lpstrTitle
    AkelPad.MemCopy(_PtrAdd(lpOFN, _X64 ?  96 : 52),   nFlags, 3 /*DT_DWORD*/); //Flags

    oSys.Call("User32::EnableWindow", hWndIB, 0);

    bOpen = oSys.Call("Comdlg32::GetOpenFileNameW", lpOFN);

    oSys.Call("User32::EnableWindow", hWndIB, 1);
    oSys.Call("User32::DestroyWindow", hWndOwn);
    oSys.Call("Kernel32::SetCurrentDirectoryW", sCurDir);

    if (bOpen)
    {
      sLastDir = oFSO.GetParentFolderName(AkelPad.MemRead(lpFile, 1 /*DT_UNICODE*/));
      SendMessage(hWndCB, 12 /*WM_SETTEXT*/, 0, lpFile);
      oSys.Call("User32::SetFocus", hWndCB);
      SendDlgItemMessage(hWndIB, IDOK,     244 /*BM_SETSTYLE*/, 1 /*BS_DRFPUSHBUTTON*/, 1)
      SendDlgItemMessage(hWndIB, IDCANCEL, 244 /*BM_SETSTYLE*/, 0 /*BS_PUSHBUTTON*/, 1)
      SendDlgItemMessage(hWndIB, IDBROWSE, 244 /*BM_SETSTYLE*/, 0 /*BS_PUSHBUTTON*/, 1)
    }

    AkelPad.MemFree(lpRECT);
    AkelPad.MemFree(lpCurDir);
    AkelPad.MemFree(lpFilter);
    AkelPad.MemFree(lpFile);
    AkelPad.MemFree(lpDir);
    AkelPad.MemFree(lpTitle);
    AkelPad.MemFree(lpOFN);
  }
}

function ReadIni()
{
  var sFile = WScript.ScriptFullName.replace(/js$/i, "ini");
  var oFile;

  if (oFSO.FileExists(sFile))
  {
    oFile = oFSO.OpenTextFile(sFile, 1, false, -1);

    try
    {
      eval(oFile.ReadAll());
    }
    catch (oError)
    {}

    oFile.Close();
  }

  if (! aHist)
    aHist = [];
}

function WriteIni()
{
  var oFile = oFSO.OpenTextFile(WScript.ScriptFullName.replace(/js$/i, "ini"), 2, true, -1);
  var sText =
    'nDlgX='     + nDlgX + ';\r\n' +
    'nDlgY='     + nDlgY + ';\r\n' +
    'nDlgW='     + nDlgW + ';\r\n' +
    'nDlgH='     + nDlgH + ';\r\n' +
    'bDlgMax='   + oSys.Call("User32::IsZoomed", hDlg) + ';\r\n' +
    'sLastDir="' + sLastDir.replace(/[\\"]/g, '\\$&') + '";\r\naHist=[';

  for (var i = 0; i < aHist.length; ++i)
    sText += '"' + aHist[i].replace(/[\\"]/g, '\\$&') + ((i < aHist.length - 1) ? '",' : '"');

  sText += '];\r\n';

  oFile.Write(sText);
  oFile.Close();
}

function GetLangStrings()
{
  sTxtDlgTitle  = "HTML view";
  sTxtDocMod    = "文档已被修改。是否想在浏览前保存?";
  sTxtOpen      = "打开";
  sTxtFileUrl   = "文件名或网址:";
  sTxtOK        = "确定";
  sTxtCancel    = "取消";
  sTxtBrowse    = "浏览(&B)";
  sTxtClearHist = "清除历史记录";
}
