// http://akelpad.sourceforge.net/forum/viewtopic.php?p=25572#25572
// Version: 2016-07-07
// Author: KDJ
//
// *** Set font in AkelPad tabs (MDI/PMDI) ***
//
// Required to include: ChooseFont_function.js
//
// Usage:
//   Call("Scripts::Main", 1, "TabFont.js", `"sFont" nStyle nSize`)
//
// Arguments:
//   "sFont":
//     Font face name, for example "Courier New", if "" - unchanged
//     Or it may be (in this case, arguments nStyle and nSize are ignored):
//       "0" - default GUI font
//       "1" - system font
//       "2" - AkelPad edit font
//       "8" - font that was previously set by this script (saved in TabFont.ini)
//       "9" - "Choose Font" dialog box
//       "+" - increase font size
//       "-" - decrease font size
//   nStyle:
//     0 - unchanged
//     1 - normal
//     2 - bold
//     3 - italic
//     4 - bold italic
//   nSize:
//     Font size in points, if 0 - unchanged
//
// Examples:
//   Call("Scripts::Main", 1, "TabFont.js")                       - without arguments, switching between three fonts: default GUI font, system font, AkelPad font
//   Call("Scripts::Main", 1, "TabFont.js", `"2"`)                - AkelPad font
//   Call("Scripts::Main", 1, "TabFont.js", `"Courier New" 3 12`) - Courier New, italic, 12 pt
//
// Remark:
//   In MDI mode, the height of tabs is adjusted to the height of characters (doesn't work in PMDI mode).
//
// For autostart, in AkelPad.ini or registry CmdLineBegin/CmdLineEnd key, need to add eg:
//   /Call("Scripts::Main", 1, "TabFont.js", `"8"`)

if ((! AkelPad.IsMDI()) || (! (AkelPad.Include("ChooseFont_function.js"))))
  WScript.Quit();

var oSys        = AkelPad.SystemFunction();
var hMainWnd    = AkelPad.GetMainWnd();
var hWndTab     = AkelPad.SendMessage(hMainWnd, 1222 /*AKD_GETMAININFO*/, 13 /*MI_WNDTAB*/, 0);
var hFontGUI    = oSys.Call("Gdi32::GetStockObject", 17 /*DEFAULT_GUI_FONT*/);
var hFontSYS    = oSys.Call("Gdi32::GetStockObject", 13 /*SYSTEM_FONT*/);
var hFontAP     = AkelPad.SendMessage(hMainWnd, 1231 /*AKD_GETFONT*/, 0, 0);
var hFontTabCur = AkelPad.SendMessage(hWndTab, 49 /*WM_GETFONT*/, 0, 0);
var hFontTabNew;
var nTabOpt;
var lpSize;
var hDC;
var nNewH;
var nDiffH;
var hWndMDI;
var oRectTab;
var oRectMDI;

if (WScript.Arguments.length)
{
  if (WScript.Arguments(0) == "0")
    hFontTabNew = hFontGUI;

  else if (WScript.Arguments(0) == "1")
    hFontTabNew = hFontSYS;

  else if (WScript.Arguments(0) == "2")
    hFontTabNew = ConvertFontFormat(hFontAP, 2, 2);

  else if (WScript.Arguments(0) == "8")
    hFontTabNew = GetPrevFont();

  else if (WScript.Arguments(0) == "9")
    hFontTabNew = ChooseFont(hMainWnd, 2, hFontTabCur, 0, 0, 2, WScript.ScriptBaseName);

  else if (WScript.Arguments(0) == "+")
    hFontTabNew = ResizeFont(hFontTabCur, 1);

  else if (WScript.Arguments(0) == "-")
    hFontTabNew = ResizeFont(hFontTabCur, -1);

  else if (WScript.Arguments.length > 2)
    hFontTabNew = GetFontFromArgumets(WScript.Arguments(0), parseInt(WScript.Arguments(1), 10), parseInt(WScript.Arguments(2), 10), hFontTabCur);
}
else
{
  if (hFontTabCur == hFontGUI)
    hFontTabNew = hFontSYS;
  else if (hFontTabCur == hFontSYS)
    hFontTabNew = ConvertFontFormat(hFontAP, 2, 2);
  else
    hFontTabNew = hFontGUI;
}

if (hFontTabNew)
{
  oSys.Call("Gdi32::DeleteObject", hFontTabCur);
  AkelPad.SendMessage(hWndTab, 48 /*WM_SETFONT*/, hFontTabNew, true);

  if ((AkelPad.IsMDI() == 1 /*WMD_MDI*/) && (! ((nTabOpt = AkelPad.SendMessage(hMainWnd, 1222 /*AKD_GETMAININFO*/, 157 /*MI_TABOPTIONSMDI*/, 0)) & 0x1 /*TAB_VIEW_NONE*/)))
  {
    lpSize = AkelPad.MemAlloc(8); //SIZE
    hDC    = oSys.Call("User32::GetDC", hWndTab);

    oSys.Call("Gdi32::SelectObject", hDC, hFontTabNew);
    oSys.Call("Gdi32::SetMapMode", hDC, 1 /*MM_TEXT*/);
    oSys.Call("Gdi32::GetTextExtentPoint32W", hDC, "", 1, lpSize);
    nNewH = Math.ceil(AkelPad.MemRead(_PtrAdd(lpSize, 4), 3 /*DT_DWORD*/) * 1.5);
    oSys.Call("User32::ReleaseDC", hWndTab, hDC);
    AkelPad.MemFree(lpSize);

    if (nDiffH = nNewH - HiWord(AkelPad.SendMessage(hWndTab, 4905 /*TCM_SETITEMSIZE*/, 0, MakeLong(0, nNewH))))
    {
      hWndMDI  = AkelPad.SendMessage(hMainWnd, 1222 /*AKD_GETMAININFO*/, 12 /*MI_WNDMDICLIENT*/, 0);
      oRectTab = {};
      oRectMDI = {};

      GetWindowPos(hWndTab, oRectTab);
      GetWindowPos(hWndMDI, oRectMDI);

      if (nTabOpt & 0x2 /*TAB_VIEW_TOP*/)
      {
        oSys.Call("User32::SetWindowPos", hWndTab, 0, 0, 0, oRectTab.W, oRectTab.H + nDiffH, 0x16 /*SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE*/);
        oSys.Call("User32::SetWindowPos", hWndMDI, 0, oRectMDI.X, oRectMDI.Y + nDiffH, oRectMDI.W, oRectMDI.H - nDiffH, 0x14 /*SWP_NOACTIVATE|SWP_NOZORDER*/);
      }
      else
      {
        oSys.Call("User32::SetWindowPos", hWndTab, 0, oRectTab.X, oRectTab.Y - nDiffH, oRectTab.W, oRectTab.H + nDiffH, 0x14 /*SWP_NOACTIVATE|SWP_NOZORDER*/);
        oSys.Call("User32::SetWindowPos", hWndMDI, 0, 0, 0, oRectMDI.W, oRectMDI.H - nDiffH, 0x16 /*SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE*/);
      }
    }
  }

  WriteIni();
}

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

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

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

  oSys.Call("User32::GetWindowRect", hWnd, lpRect);
  oSys.Call("User32::ScreenToClient", hMainWnd, _PtrAdd(lpRect, 0));
  oSys.Call("User32::ScreenToClient", hMainWnd, _PtrAdd(lpRect, 8));

  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 ResizeFont(hFont, nIncrease)
{
  var aFont = ConvertFontFormat(hFont, 2, 3);

  aFont[2] = Math.abs(aFont[2]) + nIncrease;

  if (((nIncrease > 0) && (aFont[2] < 37)) || ((nIncrease < 0) && (aFont[2] > 0)))
    return ConvertFontFormat(aFont, 3, 2);
}

function GetFontFromArgumets(sFont, nStyle, nSize, hFontCur)
{
  var aFontCur = ConvertFontFormat(hFontCur, 2, 3);

  if (! sFont)
    sFont = aFontCur[0];

  if ((! nStyle) || (nStyle < 1) || (nStyle > 4))
    nStyle = aFontCur[1];

  if (! nSize)
    nSize = aFontCur[2];

  return ConvertFontFormat([sFont, nStyle, nSize], 3, 2);
}

function GetPrevFont()
{
  var aFontTab;

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

  if (! aFontTab)
    aFontTab = ["0", 0, 0];

  if (aFontTab[0] == "0")
    return hFontGUI;
  else if (aFontTab[0] == "1")
    return hFontSYS;
  else
    return ConvertFontFormat(aFontTab, 3, 2);
}

function WriteIni()
{
  var aFontTab;
  var sIniTxt;

  if (hFontTabNew == hFontGUI)
    aFontTab = ["0", 0, 0];
  else if (hFontTabNew == hFontSYS)
    aFontTab = ["1", 0, 0];
  else
    aFontTab = ConvertFontFormat(hFontTabNew, 2, 3);

  sIniTxt = 'aFontTab=["' + aFontTab[0] + '",' + aFontTab[1] + ',' + aFontTab[2] + '];';

  AkelPad.WriteFile(WScript.ScriptFullName.replace(/\.js$/i, ".ini"), sIniTxt, sIniTxt.length, 1200 /*UTF-16LE*/, true);
}
