// http://akelpad.sourceforge.net/forum/viewtopic.php?p=12211#12211
// Version: 2019-09-23
// Author: KDJ
//
// *** Insert date/time from calendar ***
//
// Usage:
//   Call("Scripts::Main", 1, "InsertDateFromCalendar.js")
//
// In calendar window, press F1 for help, or press O(S) for options-settings

if (AkelPad.GetLangId(0 /*LANGID_FULL*/) == 0x0419) //Russian translation by AZJIO
{
  var sHelp = "      Клавиши быстрого доступа в календаре:\n" +
              " Left/Right        - предыдущий/следующий день\n" +
              " Up/Down         - предыдущая/следующая неделя\n" +
              " PgUp/PgDn      - предыдущий/следующий месяц\n" +
              " Ctrl+PgUp/Ctrl+PgDn   - предыдущий/следующий год\n" +
              " Home/End      - первый/последний день месяца\n" +
              " Ctrl+Home/Ctrl+End   - первый/последний видимый день\n" +
              " BackSpace      - перейти к сегодняшнему дню\n" +
              "\n" +
              " Shift+Alt+Left/Right   - сдвинуть календарь влево/вправо\n" +
              " Shift+Alt+Up/Down    - сдвинуть календарь вверх/вниз\n" +
              " Shift+Alt+Home/End   - сдвинуть влево/вправо к краю окна\n" +
              " Shift+Alt+PgUp/PgDn   - сдвинуть вверх/вниз к краю окна\n" +
              " Shift+Alt+C      - центрировать календарь\n" +
              "\n" +
              " +/-         - Добавить/удалить месяц из календаря\n" +
              " O (S)         - Опции\n" +
              "\n" +
              " Enter\n" +
              " Shift+Enter\n" +
              " Ctrl+Enter\n" +
              " Ctrl+Shift+Enter      - вставить дату/время (см опции)";

  var sHelpDF = " d   - день месяца без предшествующего нуля\n" +
                " dd   - день месяца с предшествующим нулём\n" +
                " ddd   - день недели, трёхбукв. аббревиатура\n" +
                " dddd   - день недели, полное название\n" +
                " M   - месяц без предшествующего нуля\n" +
                " MM   - месяц с предшествующим нулём\n" +
                " MMM   - месяц, трёхбуквенная аббревиатура\n" +
                " MMMM   - месяц, полное название\n" +
                " y   - год, две цифры без предшеств. нуля\n" +
                " yy   - год, две цифры с предшеств. нулём\n" +
                " yyyy   - год, четыре цифры";

  var sHelpTF = " h   - часы без предшествующего нуля (12)\n" +
                " hh   - час с предшествующим нулём (12)\n" +
                " H   - часы без предшествующего нуля (24)\n" +
                " HH   - час с предшествующим нулём (24)\n" +
                " m   - минуты без предшествующего нуля\n" +
                " mm   - минуты с предшествующим нулём\n" +
                " s   - секунды без предшествующего нуля\n" +
                " ss   - секунды с предшествующим нулём\n" +
                " t   - метка времени с 1 символом, (A/P)\n" +
                " tt   - метка времени с 2 символами, (AM/PM)";

  var sTxtOK       = "OK";
  var sTxtOptions  = "Опции";
  var sTxtHelp     = "Справка";
  var sTxtSettings = "Опции";
  var sTxtFormat   = "Формат вставки даты/времени";
  var sTxtSystem   = "Системный";
  var sTxtLongDate = "Длинная дата";
  var sTxtDateForm = "Дата";
  var sTxtTimeForm = "Время";
  var sTxtKeyAssig = "Вставка - горячая клавиша";
  var sTxtDate     = "Дата";
  var sTxtTime     = "Время";
  var sTxtOkBut    = "Кнопка OK";
  var sTxtCalendar = "Календарь";
  var sTxtMonths   = "Количество видимых месяцев";
  var sTxtColor1   = "Фон календаря";
  var sTxtColor2   = "Текст дней месяца";
  var sTxtColor3   = "Фон заголовка месяца";
  var sTxtColor4   = "Текст заголовка месяца";
  var sTxtColor5   = "Начальные и конечные дни";
  var sTxtReset    = "С\n" +
                     "б\n" +
                     "р\n" +
                     "о\n" +
                     "с";
}
else if (AkelPad.GetLangId(0 /*LANGID_FULL*/) == 0x0415) //Polish
{
  var sHelp = "   Klawisze skrótów dostępne w kalendarzu:\n" +
              " Left/Right      - poprzedni/następny dzień\n" +
              " Up/Down      - poprzedni/następny tydzień\n" +
              " PgUp/PgDn      - poprzedni/następny miesiąc\n" +
              " Ctrl+PgUp/Ctrl+PgDn   - poprzedni/następny rok\n" +
              " Home/End      - pierwszy/ostatni dzień miesiąca\n" +
              " Ctrl+Home/Ctrl+End   - pierwszy/ostatni widoczny dzień\n" +
              " BackSpace      - przejdź do dnia dzisiejszego\n" +
              "\n" +
              " Shift+Alt+Left/Right   - przesuń kalendarz w lewo/prawo\n" +
              " Shift+Alt+Up/Down   - przesuń kalendarz w górę/dół\n" +
              " Shift+Alt+Home/End   - przesuń do lewej/prawej krawędzi okna\n" +
              " Shift+Alt+PgUp/PgDn   - przesuń do górnej/dolnej krawędzi okna\n" +
              " Shift+Alt+C      - wyśrodkuj kalendarz\n" +
              "\n" +
              " +/-         - dodaj/usun miesiąc z kalendarza\n" +
              " O (S)         - opcje (ustawnienia)\n" +
              "\n" +
              " Enter\n" +
              " Shift+Enter\n" +
              " Ctrl+Enter\n" +
              " Ctrl+Shift+Enter      - wstaw datę/czas do tekstu (patrz opcje)";

  var sHelpDF = " d   - dzień miesiąca, cyfry bez wiodącego zera\n" +
                " dd   - dzień miesiąca, cyfry z wiodącym zerem\n" +
                " ddd   - dzień tygodnia, trzy-literowy skrót\n" +
                " dddd   - dzień tygodnia, pełna nazwa\n" +
                " M   - miesiąc, cyfry bez wiodącego zera\n" +
                " MM   - miesiąc, cyfry z wiodącym zerem\n" +
                " MMM   - miesiąc, trzy-literowy skrót\n" +
                " MMMM   - miesiąc, pełna nazwa\n" +
                " y   - rok, dwie cyfry bez wiodącego zera\n" +
                " yy   - rok, dwie cyfry z wiodącym zerem\n" +
                " yyyy   - rok, cztery cyfry";

  var sHelpTF = " h   - godziny bez wiodącego zera, zegar 12h\n" +
                " hh   - godziny z wiodącym zerem, zegar 12h\n" +
                " H   - godziny bez wiodącego zera, zegar 24h\n" +
                " HH   - godziny z wiodącym zerem, zegar 24h\n" +
                " m   - minuty bez wiodącego zera\n" +
                " mm   - minuty z wiodącym zerem\n" +
                " s   - sekundy bez wiodącego zera\n" +
                " ss   - sekundy z wiodącym zerem\n" +
                " t   - znacznik czasu jednoznakowy, (A/P)\n" +
                " tt   - znacznik czasu wieloznakowy, (AM/PM)";

  var sTxtOK       = "OK";
  var sTxtOptions  = "Opcje";
  var sTxtHelp     = "Pomoc";
  var sTxtSettings = "Opcje - ustawienia";
  var sTxtFormat   = "Wstaw - format daty/czasu";
  var sTxtSystem   = "System";
  var sTxtLongDate = "Data długa";
  var sTxtDateForm = "Format daty";
  var sTxtTimeForm = "Format czasu";
  var sTxtKeyAssig = "Wstaw - przydzielone klawisze";
  var sTxtDate     = "Data";
  var sTxtTime     = "Czas";
  var sTxtOkBut    = "Przycisk OK";
  var sTxtCalendar = "Kalendarz";
  var sTxtMonths   = "Liczba widocznych miesięcy";
  var sTxtColor1   = "Tło kalendarza";
  var sTxtColor2   = "Tekst dni miesiąca";
  var sTxtColor3   = "Tło nagłówka miesiąca";
  var sTxtColor4   = "Tekst nagłówka miesiąca";
  var sTxtColor5   = "Początkowe i końcowe dni";
  var sTxtReset    = "R\n" +
                     "e\n" +
                     "s\n" +
                     "e\n" +
                     "t";
}
else
{
  var sHelp = "   Shortcut keys in calendar:\n" +
              " Left/Right      - previous/next day\n" +
              " Up/Down      - previous/next week\n" +
              " PgUp/PgDn      - previous/next month\n" +
              " Ctrl+PgUp/Ctrl+PgDn   - previous/next year\n" +
              " Home/End      - first/last day of month\n" +
              " Ctrl+Home/Ctrl+End   - first/last day visible in calendar\n" +
              " BackSpace      - go to today\n" +
              "\n" +
              " Shift+Alt+Left/Right   - move calendar left/right\n" +
              " Shift+Alt+Up/Down   - move calendar up/down\n" +
              " Shift+Alt+Home/End   - move to left/right window edge\n" +
              " Shift+Alt+PgUp/PgDn   - move to top/bottom window edge\n" +
              " Shift+Alt+C      - center calendar\n" +
              "\n" +
              " +/-         - add/remove month from calendar\n" +
              " O (S)         - options (settings)\n" +
              "\n" +
              " Enter\n" +
              " Shift+Enter\n" +
              " Ctrl+Enter\n" +
              " Ctrl+Shift+Enter      - insert date/time in text (see options)";

  var sHelpDF = " d   - day of month, digits without leading zero\n" +
                " dd   - day of month, digits with leading zero\n" +
                " ddd   - day of week, three-letter abbreviation\n" +
                " dddd   - day of week, full name\n" +
                " M   - month, digits without leading zero\n" +
                " MM   - month, digits with leading zero\n" +
                " MMM   - month, three-letter abbreviation\n" +
                " MMMM   - month, full name\n" +
                " y   - year, two digits without leading zero\n" +
                " yy   - year, two digits with leading zero\n" +
                " yyyy   - year, four digits";

  var sHelpTF = " h   - hours without leading zero, 12-hour clock\n" +
                " hh   - hours with leading zero, 12-hour clock\n" +
                " H   - hours without leading zero, 24-hour clock\n" +
                " HH   - hours with leading zero, 24-hour clock\n" +
                " m   - minutes without leading zero\n" +
                " mm   - minutes with leading zero\n" +
                " s   - seconds without leading zero\n" +
                " ss   - seconds with leading zero\n" +
                " t   - one char time-marker, such as A or P\n" +
                " tt   - multichar time-marker, such as AM or PM";

  var sTxtOK       = "OK";
  var sTxtOptions  = "Options";
  var sTxtHelp     = "Help";
  var sTxtSettings = "Options - settings";
  var sTxtFormat   = "Insert - date/time format";
  var sTxtSystem   = "System";
  var sTxtLongDate = "Long date";
  var sTxtDateForm = "Date format";
  var sTxtTimeForm = "Time format";
  var sTxtKeyAssig = "Insert - key assignment";
  var sTxtDate     = "Date";
  var sTxtTime     = "Time";
  var sTxtOkBut    = "OK button";
  var sTxtCalendar = "Calendar";
  var sTxtMonths   = "Count of visible months";
  var sTxtColor1   = "Background within a month";
  var sTxtColor2   = "Text within a month";
  var sTxtColor3   = "Background calendar title";
  var sTxtColor4   = "Text calendar title";
  var sTxtColor5   = "Header day and trailing day";
  var sTxtReset    = "R\n" +
                     "e\n" +
                     "s\n" +
                     "e\n" +
                     "t";
}

var DT_QWORD = 2;
var DT_DWORD = 3;
var DT_WORD  = 4;

var oSys        = AkelPad.SystemFunction();
var hMainWnd    = AkelPad.GetMainWnd();
var hEditWnd    = AkelPad.GetEditWnd();
var hInstDLL    = AkelPad.GetInstanceDll();
var sClassName  = "AkelPad::Scripts::" + WScript.ScriptName + "::" + hInstDLL;
var hGuiFont    = oSys.Call("Gdi32::GetStockObject", 17 /*DEFAULT_GUI_FONT*/);
var nOsVer      = GetOsVersion();
var lpSysTime   = AkelPad.MemAlloc(16); //SYSTEMTIME
var bSystem     = 1;
var bLongDate   = 0;
var sDateForm   = "yyyy-MM-dd";
var sTimeForm   = "HH:mm:ss";
var aKeyAssign  = [["Enter", 1], ["Shift+Enter", 0], ["Ctrl+Enter", 2], ["Ctrt+Shift+Enter", 3], [sTxtOkBut, 1]];
var nMonthCount = 1;
var nMonthMax   = 7;
var aColor;
var hDlgCal;
var hWndCal;
var hWndOK;
var hWndOpt;
var hWndF1;
var hBrushColor;
var bResetColors;
var aCalPos;
var aSetPos;

ReadWriteIni(0);

var aWnd         = [];
var IDFORMAT     = 1000;
var IDDATE       = 1001;
var IDTIME       = 1002;
var IDSYSTEM     = 1003;
var IDLONGDATE   = 1004;
var IDDF         = 1005;
var IDDFHLP      = 1006;
var IDDFDESCR    = 1007;
var IDTF         = 1008;
var IDTFHLP      = 1009;
var IDTFDESCR    = 1010;
var IDKEYASSIG   = 1011;
var IDASSIG0     = 1012;
var IDASSIG1     = 1013;
var IDASSIG2     = 1014;
var IDASSIG3     = 1015;
var IDASSIG4     = 1016;
var IDENTER      = 1017;
var IDSHENTER    = 1018;
var IDCTENTER    = 1019;
var IDCTSHENTER  = 1020;
var IDOKBUT      = 1021;
var IDCALENDAR   = 1022;
var IDMONTHCOUNT = 1023;
var IDMONTHDESCR = 1024;
var IDCOLOR1     = 1025;
var IDCOLOR2     = 1026;
var IDCOLOR3     = 1027;
var IDCOLOR4     = 1028;
var IDCOLOR5     = 1029;
var IDCOLOR1BUTT = 1030;
var IDCOLOR2BUTT = 1031;
var IDCOLOR3BUTT = 1032;
var IDCOLOR4BUTT = 1033;
var IDCOLOR5BUTT = 1034;
var IDRESET      = 1035;
var IDDFHLPTXT   = 1036;
var IDTFHLPTXT   = 1037;

var CLASS   = 0;
var WND     = 1;
var EXSTYLE = 2;
var STYLE   = 3;
var X       = 4;
var Y       = 5;
var W       = 6;
var H       = 7;
var TXT     = 8;

AkelPad.WindowRegisterClass(sClassName);

do
{
  hDlgCal = oSys.Call("User32::CreateWindowEx" + _TCHAR,
              0,               //dwExStyle
              sClassName,      //lpClassName
              sTxtCalendar,    //lpWindowName
              0x90C80000,      //dwStyle=WS_VISIBLE|WS_POPUP|WS_CAPTION|WS_SYSMENU
              0,               //x
              0,               //y
              0,               //nWidth
              0,               //nHeight
              hMainWnd,        //hWndParent
              0,               //ID
              hInstDLL,        //hInstance
              DialogCallback); //Script function callback. To use it class must be registered by WindowRegisterClass.

  //Disable main window, to make dialog modal
  oSys.Call("User32::EnableWindow", hMainWnd, false);

  //Message loop
  AkelPad.WindowGetMessage();
}
while (bResetColors);

AkelPad.MemFree(lpSysTime);
AkelPad.WindowUnregisterClass(sClassName);

function DialogCallback(hWnd, uMsg, wParam, lParam)
{
  if (uMsg == 1) //WM_CREATE
  {
    hWndCal = oSys.Call("User32::CreateWindowEx" + _TCHAR,
                0,               //dwExStyle
                "SysMonthCal32", //lpClassName
                0,               //lpWindowName
                0x50800004,      //WS_VISIBLE|WS_CHILD|WS_BORDER|MCS_WEEKNUMBERS
                0,               //x
                0,               //y
                0,               //nWidth
                0,               //nHeight
                hWnd,            //hWndParent
                0,               //ID
                hInstDLL,        //hInstance
                0);              //lpParam
    AkelPad.SendMessage(hWndCal, 0x1014 /*MCM_SETMONTHDELTA*/, 1, 0);

    hWndOK = oSys.Call("User32::CreateWindowEx" + _TCHAR,
               0,          //dwExStyle
               "BUTTON",   //lpClassName
               sTxtOK,     //lpWindowName
               0x50000001, //WS_VISIBLE|WS_CHILD|BS_DEFPUSHBUTTON
               0,          //x
               0,          //y
               0,          //nWidth
               0,          //nHeight
               hWnd,       //hWndParent
               0,          //ID
               hInstDLL,   //hInstance
               0);         //lpParam

    hWndOpt = oSys.Call("User32::CreateWindowEx" + _TCHAR,
                0,           //dwExStyle
                "BUTTON",    //lpClassName
                sTxtOptions, //lpWindowName
                0x50000000,  //WS_VISIBLE|WS_CHILD
                0,           //x
                0,           //y
                0,           //nWidth
                0,           //nHeight
                hWnd,        //hWndParent
                0,           //ID
                hInstDLL,    //hInstance
                0);          //lpParam

    hWndF1 = oSys.Call("User32::CreateWindowEx" + _TCHAR,
               0,           //dwExStyle
               "BUTTON",    //lpClassName
               "? (F1)",    //lpWindowName
               0x50000000,  //WS_VISIBLE|WS_CHILD
               0,           //x
               0,           //y
               0,           //nWidth
               0,           //nHeight
               hWnd,        //hWndParent
               0,           //ID
               hInstDLL,    //hInstance
               0);          //lpParam

    SetWindowFont(hWndOK,  hGuiFont);
    SetWindowFont(hWndOpt, hGuiFont);
    SetWindowFont(hWndF1,  hGuiFont);

    SetWindowSize(hWnd);
    MoveWindow(hMainWnd, hWnd, (bResetColors ? aCalPos : ""));

    if (aColor)
    {
      for (var i = 1; i < 6; ++i)
        AkelPad.SendMessage(hWndCal, 0x100A /*MCM_SETCOLOR*/, i, aColor[i]);
    }
  }

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

  else if (uMsg == 0x0F) //WM_PAINT
  {
    if (bResetColors)
    {
      AkelPad.SendMessage(hWndCal, 0x1002 /*MCM_SETCURSEL*/, 0, lpSysTime);
      AkelPad.SendMessage(hWnd, 256 /*WM_KEYDOWN*/, 0x4F /*O*/, 0);
    }
  }

  else if (uMsg == 256) //WM_KEYDOWN
  {
    if ((wParam == 0x25 /*VK_LEFT*/) && (nOsVer < 6 /*Vista*/))
      SetDate(-1);
    else if ((wParam == 0x27 /*VK_RIGHT*/) && (nOsVer < 6))
      SetDate(1);
    else if ((wParam == 0x26 /*VK_UP*/) && (nOsVer < 6))
      SetDate(-7);
    else if ((wParam == 0x28 /*VK_DOWN*/) && (nOsVer < 6))
      SetDate(7);
    else if (wParam == 0x08 /*VK_BACK*/)
      SetDate(0); //today
    else if (wParam == 13) //VK_RETURN
    {
      if ((oSys.Call("User32::GetAsyncKeyState", 0x10 /*VK_SHIFT*/)) && (oSys.Call("User32::GetAsyncKeyState", 0x11 /*VK_CONTROL*/)))
        InsertDateTime(aKeyAssign[3][1]);
      else if (oSys.Call("User32::GetAsyncKeyState", 0x10 /*VK_SHIFT*/))
        InsertDateTime(aKeyAssign[1][1]);
      else if (oSys.Call("User32::GetAsyncKeyState", 0x11 /*VK_CONTROL*/))
        InsertDateTime(aKeyAssign[2][1]);
      else
        InsertDateTime(aKeyAssign[0][1]);
      oSys.Call("User32::PostMessage" + _TCHAR, hWnd, 16 /*WM_CLOSE*/, 0, 0);
    }
    else if (wParam == 27) //VK_ESCAPE
      oSys.Call("User32::PostMessage" + _TCHAR, hWnd, 16 /*WM_CLOSE*/, 0, 0);
    else if ((wParam == 109) || (wParam == 189))  //Num- or -
    {
      if (nMonthCount > 1)
      {
        --nMonthCount;
        SetWindowSize(hWnd);
        MoveWindow(hMainWnd, hWnd, "CV");
      }
    }
    else if ((wParam == 107) || (wParam == 187)) //Num+ or +
    {
      if (nMonthCount < nMonthMax)
      {
        ++nMonthCount;
        SetWindowSize(hWnd);
        MoveWindow(hMainWnd, hWnd, "CV");
      }
    }
    else if (wParam == 112) //VK_F1
      Help();
    else if ((wParam == 0x4F) || (wParam == 0x53)) //O or S
      oSys.Call("User32::PostMessage" + _TCHAR, hWnd, 273 /*WM_COMMAND*/, 0, hWndOpt);

    oSys.Call("User32::SetFocus", hWndCal);
  }

  else if (uMsg == 260) //WM_SYSKEYDOWN
  {
    if (oSys.Call("User32::GetAsyncKeyState", 0x10 /*VK_SHIFT*/))
    {
      if (wParam == 0x27) //VK_RIGHT
        MoveWindow(0, hWnd, "R");
      else if (wParam == 0x25) //VK_LEFT
        MoveWindow(0, hWnd, "L");
      else if (wParam == 0x28) //VK_DOWN
        MoveWindow(0, hWnd, "D");
      else if (wParam == 0x26) //VK_UP
        MoveWindow(0, hWnd, "U");
      else if (wParam == 0x23) //VK_END
        MoveWindow(0, hWnd, "E");
      else if (wParam == 0x24) //VK_HOME
        MoveWindow(0, hWnd, "H");
      else if (wParam == 0x22) //VK_NEXT
        MoveWindow(0, hWnd, "B");
      else if (wParam == 0x21) //VK_PRIOR
        MoveWindow(0, hWnd, "T");
      else if (wParam == 0x43) //C
        MoveWindow(hEditWnd, hWnd, "C");
    }
  }

  else if (uMsg == 273) //WM_COMMAND
  {
    if (lParam == hWndOK)
    {
      InsertDateTime(aKeyAssign[4][1]);
      oSys.Call("User32::PostMessage" + _TCHAR, hWnd, 16 /*WM_CLOSE*/, 0, 0);
    }
    else if (lParam == hWndOpt)
    {
      AkelPad.SendMessage(hWndOpt, 0x00F4 /*BM_SETSTYLE*/, 0 /*BS_PUSHBUTTON*/, 1);
      AkelPad.SendMessage(hWndOK,  0x00F4 /*BM_SETSTYLE*/, 1 /*BS_DEFPUSHBUTTON*/, 1);

      Settings();
      if (bResetColors)
        oSys.Call("User32::PostMessage" + _TCHAR, hWnd, 16 /*WM_CLOSE*/, 0, 0);
    }
    else if (lParam == hWndF1)
    {
      AkelPad.SendMessage(hWndF1, 0x00F4 /*BM_SETSTYLE*/, 0 /*BS_PUSHBUTTON*/, 1);
      AkelPad.SendMessage(hWndOK, 0x00F4 /*BM_SETSTYLE*/, 1 /*BS_DEFPUSHBUTTON*/, 1);
      Help();
    }
  }

  else if (uMsg == 16) //WM_CLOSE
  {
    ReadWriteIni(1);

    oSys.Call("User32::EnableWindow", hMainWnd, true);
    oSys.Call("User32::DestroyWindow", hWnd);
  }

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

  return 0;
}

function GetOsVersion()
{
  var nVerLen = 4 * 5 + 128 * _TSIZE; //sizeof(OSVERSIONINFO)
  var lpOsVer = AkelPad.MemAlloc(nVerLen);
  var nMajorVer;

  AkelPad.MemCopy(lpOsVer, nVerLen, 3 /*DT_DWORD*/);
  oSys.Call("Kernel32::GetVersionEx" + _TCHAR, lpOsVer);
  nMajorVer = AkelPad.MemRead(_PtrAdd(lpOsVer, 4), 3 /*DT_DWORD*/);
  AkelPad.MemFree(lpOsVer);

  return nMajorVer;
}

function GetWindowText(hWnd)
{
  var lpBuffer = AkelPad.MemAlloc(256 * _TSIZE);
  var sText;

  oSys.Call("User32::GetWindowText" + _TCHAR, hWnd, lpBuffer, 256);
  sText = AkelPad.MemRead(lpBuffer, _TSTR);
  AkelPad.MemFree(lpBuffer);
  return sText;
}

function SetWindowText(hWnd, sText)
{
  oSys.Call("User32::SetWindowText" + _TCHAR, hWnd, sText);
}

function SetWindowFont(hWnd, hFont)
{
  AkelPad.SendMessage(hWnd, 48 /*WM_SETFONT*/, hFont, true);
}

function SetWindowSize(hDlg)
{
  var lpRect = AkelPad.MemAlloc(16); //sizeof(RECT)
  var nCY    = oSys.Call("User32::GetSystemMetrics", 4 /*SM_CYCAPTION*/);
  var nFX    = oSys.Call("User32::GetSystemMetrics", 7 /*SM_CXFIXEDFRAME*/);
  var nFY    = oSys.Call("User32::GetSystemMetrics", 8 /*SM_CYFIXEDFRAME*/);
  var nW, nH, nBW;

  AkelPad.SendMessage(hWndCal, 0x1009 /*MCM_GETMINREQRECT*/, 0, lpRect);

  nW  = Math.max(AkelPad.MemRead(_PtrAdd(lpRect, 8), DT_DWORD), AkelPad.SendMessage(hWndCal, 0x1015 /*MCM_GETMAXTODAYWIDTH*/, 0, 0));
  nH  = AkelPad.MemRead(_PtrAdd(lpRect, 12), DT_DWORD) * nMonthCount - ((nOsVer < 6) ? 13 : 27) * (nMonthCount - 1);
  nBW = Math.round((nW - 20) / 3);

  oSys.Call("User32::SetWindowPos", hDlg,    0, 0, 0, nW + 2 * nFX, nH + 2 * nFY + nCY + 30, 0x16 /*SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE*/);

  oSys.Call("User32::SetWindowPos", hWndCal, 0, 0, 0, nW, nH, 0x16 /*SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE*/);

  oSys.Call("User32::SetWindowPos", hWndOK,  0, 5,            nH + 5, nBW, 21, 0x14 /*SWP_NOZORDER|SWP_NOACTIVATE*/);
  oSys.Call("User32::SetWindowPos", hWndOpt, 0, nBW + 10,     nH + 5, nBW, 21, 0x14 /*SWP_NOZORDER|SWP_NOACTIVATE*/);
  oSys.Call("User32::SetWindowPos", hWndF1,  0, nW - nBW - 5, nH + 5, nBW, 21, 0x14 /*SWP_NOZORDER|SWP_NOACTIVATE*/);

  AkelPad.MemFree(lpRect);
}

function MoveWindow(hWndParent, hWnd, sAction)
{
  var aRectParent;
  var aRect;
  var lpPoint;
  var nX;
  var nY;
  var nWndWidth;
  var nWndHeight;
  var nCharHeight;

  if (! hWndParent)
    hWndParent = oSys.Call("User32::GetDesktopWindow");

  aRectParent = GetWindowPos(hWndParent);
  aRect       = GetWindowPos(hWnd);

  nX = aRect.left;
  nY = aRect.top;

  if (! sAction) //to caret
  {
    if (lpPoint = AkelPad.MemAlloc(8)) //sizeof(POINT)
    {
      AkelPad.SendMessage(hEditWnd, 3190 /*AEM_GETCARETPOS*/, lpPoint, 0);
      oSys.Call("User32::ClientToScreen", hEditWnd, lpPoint);
      nX = AkelPad.MemRead(_PtrAdd(lpPoint, 0), DT_DWORD);
      nY = AkelPad.MemRead(_PtrAdd(lpPoint, 4), DT_DWORD);

      nWndWidth   = aRect.right - aRect.left;
      nWndHeight  = aRect.bottom - aRect.top;
      nCharHeight = AkelPad.SendMessage(hEditWnd, 3188 /*AEM_GETCHARSIZE*/, 0 /*AECS_HEIGHT*/, 0);

      if ((nX + nWndWidth) > aRectParent.right)
        nX = aRectParent.right - nWndWidth - 10;

      if ((nY + nCharHeight + nWndHeight) < aRectParent.bottom)
        nY = nY + nCharHeight;
      else if ((nY - nWndHeight) > aRectParent.top)
        nY = nY - nWndHeight;
      else
        nY = aRectParent.top  + ((aRectParent.bottom - aRectParent.top) / 2 - (aRect.bottom - aRect.top) / 2);

      AkelPad.MemFree(lpPoint);
    }
  }
  else if (sAction == "R") //Move right
    nX = aRect.left + ((aRect.right < aRectParent.right) ? 10: 0);
  else if (sAction == "L") //Move left
    nX = aRect.left - ((aRect.left > aRectParent.left) ? 10: 0);
  else if (sAction == "D") //Move down
    nY = aRect.top + ((aRect.bottom < aRectParent.bottom) ? 10: 0);
  else if (sAction == "U") //Move up
    nY = aRect.top - ((aRect.top > aRectParent.top) ? 10: 0);
  else if (sAction == "E") //Move end (right)
    nX = aRect.left + (aRectParent.right - aRect.right);
  else if (sAction == "H") //Move home (left)
    nX = aRect.left + (aRectParent.left - aRect.left);
  else if (sAction == "B") //Move bottom
    nY = aRect.top + (aRectParent.bottom - aRect.bottom);
  else if (sAction == "T") //Move top
    nY = aRect.top + (aRectParent.top - aRect.top);
  else if (sAction == "C") //Center window
  {
    nX = aRectParent.left + ((aRectParent.right  - aRectParent.left) / 2 - (aRect.right  - aRect.left) / 2);
    nY = aRectParent.top  + ((aRectParent.bottom - aRectParent.top)  / 2 - (aRect.bottom - aRect.top)  / 2);
  }
  else if (sAction == "CV") //Center vertically
  {
    nY = aRectParent.top  + ((aRectParent.bottom - aRectParent.top)  / 2 - (aRect.bottom - aRect.top)  / 2);
  }
  else if (sAction == "LT") //Move left top
  {
    nX = aRectParent.left;
    nY = aRectParent.top;
  }
  else if (sAction == "RT") //Move right top
  {
    nX = aRect.left + (aRectParent.right - aRect.right);
    nY = aRectParent.top;
  }
  else if (sAction == "LB") //Move left bottom
  {
    nX = aRectParent.left;
    nY = aRect.top + (aRectParent.bottom - aRect.bottom);
  }
  else if (sAction == "RB") //Move right bottom
  {
    nX = aRect.left + (aRectParent.right - aRect.right);
    nY = aRect.top + (aRectParent.bottom - aRect.bottom);
  }
  else
  {
    nX = sAction.left;
    nY = sAction.top;
  }

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

function GetWindowPos(hWnd)
{
  var lpRect = AkelPad.MemAlloc(16) //sizeof(RECT);
  var aRect  = [];

  oSys.Call("User32::GetWindowRect", hWnd, lpRect);

  aRect.left   = AkelPad.MemRead(_PtrAdd(lpRect,  0), DT_DWORD);
  aRect.top    = AkelPad.MemRead(_PtrAdd(lpRect,  4), DT_DWORD);
  aRect.right  = AkelPad.MemRead(_PtrAdd(lpRect,  8), DT_DWORD);
  aRect.bottom = AkelPad.MemRead(_PtrAdd(lpRect, 12), DT_DWORD);
  AkelPad.MemFree(lpRect);

  return aRect;
}

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

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

function ReadWriteIni(bWrite)
{
  var sIniName = WScript.ScriptFullName.substring(0, WScript.ScriptFullName.lastIndexOf(".")) + ".ini";
  var oFSO     = new ActiveXObject("Scripting.FileSystemObject");
  var oFile;
  var sIniTxt;

  if (bWrite)
  {
    sIniTxt = 'bSystem='          + bSystem     + ';\r\n' +
              'bLongDate='        + bLongDate   + ';\r\n' +
              'sDateForm="'       + sDateForm.replace(/[\\"]/g, "\\$&") + '";\r\n' +
              'sTimeForm="'       + sTimeForm.replace(/[\\"]/g, "\\$&") + '";\r\n' +
              'aKeyAssign[0][1]=' + aKeyAssign[0][1] + ';\r\n' +
              'aKeyAssign[1][1]=' + aKeyAssign[1][1] + ';\r\n' +
              'aKeyAssign[2][1]=' + aKeyAssign[2][1] + ';\r\n' +
              'aKeyAssign[3][1]=' + aKeyAssign[3][1] + ';\r\n' +
              'aKeyAssign[4][1]=' + aKeyAssign[4][1] + ';\r\n' +
              'nMonthCount='      + nMonthCount + ';\r\n' +
              'aColor='

    if (aColor)
      sIniTxt += '[' + aColor + ']';
    else
      sIniTxt += aColor;

    sIniTxt += ';';

    oFile = oFSO.OpenTextFile(sIniName, 2, true, -1);
    oFile.Write(sIniTxt);
    oFile.Close();
  }

  else if (oFSO.FileExists(sIniName))
  {
    try
    {
      eval(AkelPad.ReadFile(sIniName));
    }
    catch (oError)
    {
    }
  }
}

function SetDate(nShift)
{
  var nYear, nMonth, nDay, dDate;

  if (nShift)
  {
    AkelPad.SendMessage(hWndCal, 0x1001 /*MCM_GETCURSEL*/, 0, lpSysTime);

    nYear  = AkelPad.MemRead(_PtrAdd(lpSysTime, 0), DT_WORD);
    nMonth = AkelPad.MemRead(_PtrAdd(lpSysTime, 2), DT_WORD) - 1;
    nDay   = AkelPad.MemRead(_PtrAdd(lpSysTime, 6), DT_WORD);
    dDate  = new Date(nYear, nMonth, nDay);

    dDate.setDate(nDay + nShift);

    nYear  = dDate.getFullYear();
    nMonth = dDate.getMonth() + 1;
    nDay   = dDate.getDate();

    AkelPad.MemCopy(_PtrAdd(lpSysTime, 0), nYear,  DT_WORD);
    AkelPad.MemCopy(_PtrAdd(lpSysTime, 2), nMonth, DT_WORD);
    AkelPad.MemCopy(_PtrAdd(lpSysTime, 6), nDay,   DT_WORD);
  }
  else
    AkelPad.SendMessage(hWndCal, 0x100D /*MCM_GETTODAY*/, 0, lpSysTime);

  AkelPad.SendMessage(hWndCal, 0x1002 /*MCM_SETCURSEL*/, 0, lpSysTime);
}

function GetDate()
{
  var lpString = AkelPad.MemAlloc(256 * _TSIZE);
  var lpFormat = AkelPad.MemAlloc(256 * _TSIZE);
  var nFlag    = 0;
  var sDate;

  AkelPad.SendMessage(hWndCal, 0x1001 /*MCM_GETCURSEL*/, 0, lpSysTime);

  if (bSystem)
    nFlag = bLongDate ? 0x2 /*DATE_LONGDATE*/ : 0x1 /*DATE_SHORTDATE*/;
  else
    AkelPad.MemCopy(lpFormat, sDateForm, _TSTR);

  oSys.Call("Kernel32::GetDateFormat" + _TCHAR,
            0x400, //LOCALE_USER_DEFAULT
            nFlag,
            lpSysTime,
            (bSystem ? 0 : lpFormat),
            lpString,
            256);
  sDate = AkelPad.MemRead(lpString, _TSTR);

  AkelPad.MemFree(lpString);
  AkelPad.MemFree(lpFormat);

  return sDate;
}

function GetTime()
{
  var lpString = AkelPad.MemAlloc(256 * _TSIZE);
  var lpFormat = AkelPad.MemAlloc(256 * _TSIZE);
  var dDate    = new Date();
  var sTime;

  AkelPad.MemCopy(_PtrAdd(lpSysTime,  8), dDate.getHours(),        DT_WORD);
  AkelPad.MemCopy(_PtrAdd(lpSysTime, 10), dDate.getMinutes(),      DT_WORD);
  AkelPad.MemCopy(_PtrAdd(lpSysTime, 12), dDate.getSeconds(),      DT_WORD);
  AkelPad.MemCopy(_PtrAdd(lpSysTime, 14), dDate.getMilliseconds(), DT_WORD);

  if (! bSystem)
    AkelPad.MemCopy(lpFormat, sTimeForm, _TSTR);

  oSys.Call("Kernel32::GetTimeFormat" + _TCHAR,
            0x007F, //LOCALE_INVARIANT
            0,
            lpSysTime,
            (bSystem ? 0 : lpFormat),
            lpString,
            256);
  sTime = AkelPad.MemRead(lpString, _TSTR);

  AkelPad.MemFree(lpString);
  AkelPad.MemFree(lpFormat);

  return sTime;
}

function InsertDateTime(nWhat)
{
  var bColSel = AkelPad.SendMessage(hEditWnd, 3127 /*AEM_GETCOLUMNSEL*/, 0, 0);
  var sDateTime;
  var nLines;
  var aTxt;
  var i;

  if (nWhat == 0)
    sDateTime = GetDate();
  else if (nWhat == 1)
    sDateTime = GetDate() + " " + GetTime();
  else if (nWhat == 2)
    sDateTime = GetTime();
  else
    sDateTime = GetTime() + " " + GetDate();

  if (bColSel)
  {
    nLines = AkelPad.SendMessage(hEditWnd, 3129 /*AEM_GETLINENUMBER*/, 2 /*AEGL_LASTSELLINE*/, 0) - AkelPad.SendMessage(hEditWnd, 3129 /*AEM_GETLINENUMBER*/, 1 /*AEGL_FIRSTSELLINE*/, 0) + 1;
    aTxt   = [];

    for (i = 0; i < nLines; ++i)
      aTxt[i] = sDateTime;

    sDateTime = aTxt.join("\r");
  }

  AkelPad.ReplaceSel(sDateTime, (AkelPad.GetSelStart() == AkelPad.GetSelEnd()) ? 0 : -1);
  AkelPad.SendMessage(hEditWnd, 3128 /*AEM_UPDATESEL*/, bColSel, 0);
}

function Help()
{
  var aRectDesk = GetWindowPos(oSys.Call("User32::GetDesktopWindow"));
  var aRect     = GetWindowPos(hDlgCal);
  var nWidth    = 350;
  var nHeight   = 350;
  var nX        = aRect.right;
  var nY        = aRect.top;
  var hDlgHlp;

  if ((nX + nWidth) > aRectDesk.right)
    nX = aRect.left - nWidth;
  if ((nY + nHeight) > aRectDesk.bottom)
    nY = aRect.bottom - nHeight;

  hDlgHlp = oSys.Call("User32::CreateWindowEx" + _TCHAR,
              0,          //dwExStyle
              sClassName, //lpClassName
              sTxtHelp,   //lpWindowName
              0x90C80000, //WS_VISIBLE|WS_POPUP|WS_CAPTION|WS_SYSMENU
              nX,         //x
              nY,         //y
              nWidth,     //nWidth
              nHeight,    //nHeight
              hDlgCal,    //hWndParent
              0,          //ID
              hInstDLL,   //hInstance
              DialogCallbackHlp); //Script function callback

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

function DialogCallbackHlp(hWnd, uMsg, wParam, lParam)
{
  if (uMsg == 1) //WM_CREATE
  {
    hWndHlp = oSys.Call("User32::CreateWindowEx" + _TCHAR,
                0x000,      //dwExStyle
                "STATIC",   //lpClassName
                sHelp,      //lpWindowName
                0x50400000, //WS_VISIBLE|WS_CHILD|WS_DLGFRAME
                10,         //x
                10,         //y
                325,        //nWidth
                300,        //nHeight
                hWnd,       //hWndParent
                0,          //ID
                hInstDLL,   //hInstance
                0);         //lpParam
    SetWindowFont(hWndHlp, hGuiFont);
  }

  else if (uMsg == 256) //WM_KEYDOWN
  {
    if (wParam == 112 /*VK_F1*/)
      oSys.Call("User32::PostMessage" + _TCHAR, hWnd, 16 /*WM_CLOSE*/, 0, 0);
  }

  else if (uMsg == 273) //WM_COMMAND
  {
    if (LoWord(wParam) == 2 /*IDCANCEL*/)
      oSys.Call("User32::PostMessage" + _TCHAR, hWnd, 16 /*WM_CLOSE*/, 0, 0);
  }

  else if (uMsg == 16) //WM_CLOSE
  {
    oSys.Call("User32::EnableWindow", hDlgCal, 1);
    oSys.Call("User32::DestroyWindow", hWnd);
  }

  return 0;
}

function Settings()
{
  var nWidth  = 265
  var nHeight = 485;
  var aRectDesk;
  var aRect;
  var nX;
  var nY;
  var hDlgSet;
  var i;

  if (bResetColors)
  {
    nX = aSetPos.left;
    nY = aSetPos.top;
  }
  else
  {
    aRectDesk = GetWindowPos(oSys.Call("User32::GetDesktopWindow"));
    aRect     = GetWindowPos(hDlgCal);
    nX        = aRect.right;
    nY        = aRect.top;

    if ((nX + nWidth) > aRectDesk.right)
      nX = aRect.left - nWidth;
    if ((nY + nHeight) > aRectDesk.bottom)
      nY = aRect.bottom - nHeight;
  }

  if (! aColor)
  {
    //i=0 - MCSC_BACKGROUND (not used)
    //i=4 - MCSC_MONTHBK
    //i=1 - MCSC_TEXT
    //i=2 - MCSC_TITLEBK
    //i=3 - MCSC_TITLETEXT
    //i=5 - MCSC_TRAILINGTEXT
    aColor = [];
    for (i = 1; i < 6; ++i)
      aColor[i] = AkelPad.SendMessage(hWndCal, 0x100B /*MCM_GETCOLOR*/, i, 0);
  }

  //0x40400000 - WS_CHILD|WS_DLGFRAME (no visible)
  //0x50000000 - WS_VISIBLE|WS_CHILD
  //0x50000007 - WS_VISIBLE|WS_CHILD|BS_GROUPBOX
  //0x50010000 - WS_VISIBLE|WS_CHILD|WS_TABSTOP
  //0x50012000 - WS_VISIBLE|WS_CHILD|WS_TABSTOP|BS_MULTILINE
  //0x50010003 - WS_VISIBLE|WS_CHILD|WS_TABSTOP|BS_AUTOCHECKBOX
  //0x50010003 - WS_VISIBLE|WS_CHILD|WS_TABSTOP|CBS_DROPDOWNLIST
  //0x50010080 - WS_VISIBLE|WS_CHILD|WS_TABSTOP|ES_AUTOHSCROLL
  //0x50800000 - WS_VISIBLE|WS_CHILD|WS_BORDER
  //Windows                CLASS, WND, EXSTYLE,      STYLE,   X,   Y,   W,   H, TXT
  aWnd[IDFORMAT    ] = ["BUTTON",   0,       0, 0x50000007,  10,  10, 240, 130, sTxtFormat];
  aWnd[IDDATE      ] = ["STATIC",   0,       0, 0x50000000,  20,  30, 220,  13, ""];
  aWnd[IDTIME      ] = ["STATIC",   0,       0, 0x50000000,  20,  50, 220,  13, ""];
  aWnd[IDSYSTEM    ] = ["BUTTON",   0,       0, 0x50010003,  20,  70,  80,  16, sTxtSystem];
  aWnd[IDLONGDATE  ] = ["BUTTON",   0,       0, 0x50010003, 120,  70,  90,  16, sTxtLongDate];
  aWnd[IDDF        ] = ["EDIT",     0,   0x200, 0x50010080,  20,  90, 135,  20, sDateForm];
  aWnd[IDDFHLP     ] = ["BUTTON",   0,       0, 0x50010000, 155,  90,  15,  20, "?"];
  aWnd[IDDFDESCR   ] = ["STATIC",   0,       0, 0x50000000, 175,  90,  70,  13, sTxtDateForm];
  aWnd[IDTF        ] = ["EDIT",     0,   0x200, 0x50010080,  20, 110, 135,  20, sTimeForm];
  aWnd[IDTFHLP     ] = ["BUTTON",   0,       0, 0x50010000, 155, 110,  15,  20, "?"];
  aWnd[IDTFDESCR   ] = ["STATIC",   0,       0, 0x50000000, 175, 110,  70,  13, sTxtTimeForm];
  aWnd[IDKEYASSIG  ] = ["BUTTON",   0,       0, 0x50000007,  10, 150, 240, 130, sTxtKeyAssig];
  aWnd[IDASSIG0    ] = ["COMBOBOX", 0,       0, 0x50010003,  20, 170, 100,  20, ""];
  aWnd[IDASSIG1    ] = ["COMBOBOX", 0,       0, 0x50010003,  20, 190, 100,  20, ""];
  aWnd[IDASSIG2    ] = ["COMBOBOX", 0,       0, 0x50010003,  20, 210, 100,  20, ""];
  aWnd[IDASSIG3    ] = ["COMBOBOX", 0,       0, 0x50010003,  20, 230, 100,  20, ""];
  aWnd[IDASSIG4    ] = ["COMBOBOX", 0,       0, 0x50010003,  20, 250, 100,  20, ""];
  aWnd[IDENTER     ] = ["STATIC",   0,       0, 0x50000000, 125, 170,  80,  13, aKeyAssign[0][0]];
  aWnd[IDSHENTER   ] = ["STATIC",   0,       0, 0x50000000, 125, 190,  80,  13, aKeyAssign[1][0]];
  aWnd[IDCTENTER   ] = ["STATIC",   0,       0, 0x50000000, 125, 210,  80,  13, aKeyAssign[2][0]];
  aWnd[IDCTSHENTER ] = ["STATIC",   0,       0, 0x50000000, 125, 230,  80,  13, aKeyAssign[3][0]];
  aWnd[IDOKBUT     ] = ["STATIC",   0,       0, 0x50000000, 125, 250,  80,  13, aKeyAssign[4][0]];
  aWnd[IDCALENDAR  ] = ["BUTTON",   0,       0, 0x50000007,  10, 290, 240, 155, sTxtCalendar];
  aWnd[IDMONTHCOUNT] = ["COMBOBOX", 0,       0, 0x50010003,  20, 310,  40,  20, ""];
  aWnd[IDMONTHDESCR] = ["STATIC",   0,       0, 0x50000000,  65, 310, 180,  13, sTxtMonths];
  aWnd[IDCOLOR1    ] = ["STATIC",   0,       0, 0x50800000,  20, 340,  18,  18, ""];
  aWnd[IDCOLOR2    ] = ["STATIC",   0,       0, 0x50800000,  20, 360,  18,  18, ""];
  aWnd[IDCOLOR3    ] = ["STATIC",   0,       0, 0x50800000,  20, 380,  18,  18, ""];
  aWnd[IDCOLOR4    ] = ["STATIC",   0,       0, 0x50800000,  20, 400,  18,  18, ""];
  aWnd[IDCOLOR5    ] = ["STATIC",   0,       0, 0x50800000,  20, 420,  18,  18, ""];
  aWnd[IDCOLOR1BUTT] = ["BUTTON",   0,       0, 0x50010000,  45, 340, 170,  20, sTxtColor1];
  aWnd[IDCOLOR2BUTT] = ["BUTTON",   0,       0, 0x50010000,  45, 360, 170,  20, sTxtColor2];
  aWnd[IDCOLOR3BUTT] = ["BUTTON",   0,       0, 0x50010000,  45, 380, 170,  20, sTxtColor3];
  aWnd[IDCOLOR4BUTT] = ["BUTTON",   0,       0, 0x50010000,  45, 400, 170,  20, sTxtColor4];
  aWnd[IDCOLOR5BUTT] = ["BUTTON",   0,       0, 0x50010000,  45, 420, 170,  20, sTxtColor5];
  aWnd[IDRESET     ] = ["BUTTON",   0,       0, 0x50012000, 220, 340,  20, 100, sTxtReset];
  aWnd[IDDFHLPTXT  ] = ["STATIC",   0,       0, 0x40400000,   0, 110, 255, 155, sHelpDF];
  aWnd[IDTFHLPTXT  ] = ["STATIC",   0,       0, 0x40400000,   0, 130, 255, 140, sHelpTF];

  hDlgSet = oSys.Call("User32::CreateWindowEx" + _TCHAR,
              0,            //dwExStyle
              sClassName,   //lpClassName
              sTxtSettings, //lpWindowName
              0x90C80000,   //WS_VISIBLE|WS_POPUP|WS_CAPTION|WS_SYSMENU
              nX,           //x
              nY,           //y
              nWidth,       //nWidth
              nHeight,      //nHeight
              hDlgCal,      //hWndParent
              0,            //ID
              hInstDLL,     //hInstance
              DialogCallbackSet); //Script function callback

  oSys.Call("User32::EnableWindow", hDlgCal, 0);
  AkelPad.WindowGetMessage(0x4 /*WGM_KEYDOWNUP*/);
}

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

  if (uMsg == 1) //WM_CREATE
  {
    for (i = 1000; i < aWnd.length; ++i)
    {
      aWnd[i][WND] = oSys.Call("User32::CreateWindowEx" + _TCHAR,
                       aWnd[i][EXSTYLE],//dwExStyle
                       aWnd[i][CLASS],  //lpClassName
                       0,               //lpWindowName
                       aWnd[i][STYLE],  //dwStyle
                       aWnd[i][X],      //x
                       aWnd[i][Y],      //y
                       aWnd[i][W],      //nWidth
                       aWnd[i][H],      //nHeight
                       hWnd,            //hWndParent
                       i,               //ID
                       hInstDLL,        //hInstance
                       0);              //lpParam
      SetWindowFont(aWnd[i][WND], hGuiFont);
      SetWindowText(aWnd[i][WND], aWnd[i][TXT]);
    }

    //Set limit edit text
    AkelPad.SendMessage(aWnd[IDDF][WND], 197 /*EM_SETLIMITTEXT*/, 24, 0);
    AkelPad.SendMessage(aWnd[IDTF][WND], 197 /*EM_SETLIMITTEXT*/, 24, 0);

    //Fill comboboxes
    for (i = 0; i < aKeyAssign.length; ++i)
    {
      AkelPad.SendMessage(aWnd[IDASSIG0 + i][WND], 0x143 /*CB_ADDSTRING*/, 0, sTxtDate);
      AkelPad.SendMessage(aWnd[IDASSIG0 + i][WND], 0x143 /*CB_ADDSTRING*/, 0, sTxtDate + " " + sTxtTime);
      AkelPad.SendMessage(aWnd[IDASSIG0 + i][WND], 0x143 /*CB_ADDSTRING*/, 0, sTxtTime);
      AkelPad.SendMessage(aWnd[IDASSIG0 + i][WND], 0x143 /*CB_ADDSTRING*/, 0, sTxtTime + " " + sTxtDate);
      AkelPad.SendMessage(aWnd[IDASSIG0 + i][WND], 0x14E /*CB_SETCURSEL*/, aKeyAssign[i][1], 0);
    }
    for (i = 1; i < nMonthMax + 1; ++i)
      AkelPad.SendMessage(aWnd[IDMONTHCOUNT][WND], 0x143 /*CB_ADDSTRING*/, 0, " " + i + " ");
    AkelPad.SendMessage(aWnd[IDMONTHCOUNT][WND], 0x14E /*CB_SETCURSEL*/, nMonthCount - 1, 0);

    CheckButtons();
  }

  else if (uMsg == 7) //WM_SETFOCUS
  {
    if (bResetColors)
    {
      bResetColors = false;
      oSys.Call("User32::SetFocus", aWnd[IDRESET][WND]);
      oSys.Call("User32::DefDlgProc" + _TCHAR, hWnd, 1025 /*DM_SETDEFID*/, IDRESET, 0);
    }
    else
      oSys.Call("User32::SetFocus", aWnd[IDSYSTEM][WND]);
  }

  else if (uMsg == 256) //WM_KEYDOWN
  {
    if (wParam == 112) //VK_F1
    {
      if (oSys.Call("User32::GetFocus") == aWnd[IDDF][WND])
        oSys.Call("User32::PostMessage" + _TCHAR, hWnd, 273 /*WM_COMMAND*/, IDDFHLP, 0);
      else if (oSys.Call("User32::GetFocus") == aWnd[IDTF][WND])
        oSys.Call("User32::PostMessage" + _TCHAR, hWnd, 273 /*WM_COMMAND*/, IDTFHLP, 0);
    }
    else if ((wParam == 9 /*VK_TAB*/) || (wParam == 27 /*VK_ESCAPE*/))
    {
      if (oSys.Call("User32::IsWindowVisible", aWnd[IDDFHLPTXT][WND]))
        ShowFormatHelp(hWnd, aWnd[IDDFHLPTXT][WND], 0);
      else if (oSys.Call("User32::IsWindowVisible", aWnd[IDTFHLPTXT][WND]))
        ShowFormatHelp(hWnd, aWnd[IDTFHLPTXT][WND], 0);
    }
  }

  else if ((uMsg == 0x0201 /*WM_LBUTTONDOWN*/) || (uMsg == 0x0204 /*WM_RBUTTONDOWN*/) ||
           (uMsg == 0x0207 /*WM_MBUTTONDOWN*/) || (uMsg == 0x020b /*WM_XBUTTONDOWN*/))
  {
    if (oSys.Call("User32::IsWindowVisible", aWnd[IDDFHLPTXT][WND]))
      ShowFormatHelp(hWnd, aWnd[IDDFHLPTXT][WND], 0);
    else if (oSys.Call("User32::IsWindowVisible", aWnd[IDTFHLPTXT][WND]))
      ShowFormatHelp(hWnd, aWnd[IDTFHLPTXT][WND], 0);
  }

  else if (uMsg == 0x0138) //WM_CTLCOLORSTATIC
  {
    if ((lParam == aWnd[IDDFHLPTXT][WND]) || (lParam == aWnd[IDTFHLPTXT][WND]))
    {
      oSys.Call("Gdi32::DeleteObject", hBrushColor);
      oSys.Call("Gdi32::SetTextColor", wParam, 0x006000);
      oSys.Call("Gdi32::SetBkColor", wParam, 0xFFFFFF);
      hBrushColor = oSys.Call("Gdi32::CreateSolidBrush", 0xFFFFFF);
      return hBrushColor;
    }
    if (lParam == aWnd[IDCOLOR1][WND])
    {
      oSys.Call("Gdi32::DeleteObject", hBrushColor);
      hBrushColor = oSys.Call("Gdi32::CreateSolidBrush", aColor[4]);
      return hBrushColor;
    }
    if (lParam == aWnd[IDCOLOR2][WND])
    {
      oSys.Call("Gdi32::DeleteObject", hBrushColor);
      hBrushColor = oSys.Call("Gdi32::CreateSolidBrush", aColor[1]);
      return hBrushColor;
    }
    if (lParam == aWnd[IDCOLOR3][WND])
    {
      oSys.Call("Gdi32::DeleteObject", hBrushColor);
      hBrushColor = oSys.Call("Gdi32::CreateSolidBrush", aColor[2]);
      return hBrushColor;
    }
    if (lParam == aWnd[IDCOLOR4][WND])
    {
      oSys.Call("Gdi32::DeleteObject", hBrushColor);
      hBrushColor = oSys.Call("Gdi32::CreateSolidBrush", aColor[3]);
      return hBrushColor;
    }
    if (lParam == aWnd[IDCOLOR5][WND])
    {
      oSys.Call("Gdi32::DeleteObject", hBrushColor);
      hBrushColor = oSys.Call("Gdi32::CreateSolidBrush", aColor[5]);
      return hBrushColor;
    }
  }

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

    if ((nID == IDSYSTEM) || (nID == IDLONGDATE))
    {
      CheckButtons(nID);
    }
    else if ((nID == IDDF) && (nCode == 0x300 /*EN_CHANGE*/))
    {
      sDateForm = GetWindowText(aWnd[IDDF][WND]);
      SetWindowText(aWnd[IDDATE][WND], GetDate());
    }
    else if ((nID == IDTF) && (nCode == 0x300 /*EN_CHANGE*/))
    {
      sTimeForm = GetWindowText(aWnd[IDTF][WND]);
      SetWindowText(aWnd[IDTIME][WND], GetTime());
    }
    else if (nID == IDDFHLP)
      ShowFormatHelp(hWnd, aWnd[IDDFHLPTXT][WND], ! oSys.Call("User32::IsWindowVisible", aWnd[IDDFHLPTXT][WND]));
    else if (nID == IDTFHLP)
      ShowFormatHelp(hWnd, aWnd[IDTFHLPTXT][WND], ! oSys.Call("User32::IsWindowVisible", aWnd[IDTFHLPTXT][WND]));
    else if ((nID >= IDASSIG0) && (nID <= IDASSIG4) && (nCode == 1 /*CBN_SELCHANGE*/))
      aKeyAssign[nID - IDASSIG0][1] = AkelPad.SendMessage(aWnd[nID][WND], 0x147 /*CB_GETCURSEL*/, 0, 0);
    else if ((nID == IDMONTHCOUNT) && (nCode == 1 /*CBN_SELCHANGE*/))
    {
      nMonthCount = AkelPad.SendMessage(aWnd[IDMONTHCOUNT][WND], 0x147 /*CB_GETCURSEL*/, 0, 0) + 1;
      SetWindowSize(hDlgCal);
      MoveWindow(hMainWnd, hDlgCal, "CV");
    }
    else if ((nID >= IDCOLOR1BUTT) && (nID <= IDCOLOR5BUTT))
      ChangeColor(hWnd, nID);
    else if (nID == IDRESET)
    {
      bResetColors = true;
      aColor       = undefined;
      aCalPos      = GetWindowPos(hDlgCal);
      aSetPos      = GetWindowPos(hWnd);
      AkelPad.SendMessage(hWndCal, 0x1001 /*MCM_GETCURSEL*/, 0, lpSysTime);
      oSys.Call("User32::PostMessage" + _TCHAR, hWnd, 16 /*WM_CLOSE*/, 0, 0);
    }
    else if (nID == 2 /*IDCANCEL*/)
    {
      if ((! oSys.Call("User32::IsWindowVisible", aWnd[IDDFHLPTXT][WND])) && (! oSys.Call("User32::IsWindowVisible", aWnd[IDTFHLPTXT][WND])))
        oSys.Call("User32::PostMessage" + _TCHAR, hWnd, 16 /*WM_CLOSE*/, 0, 0);
    }
  }

  else if (uMsg == 16) //WM_CLOSE
  {
    oSys.Call("Gdi32::DeleteObject", hBrushColor);
    oSys.Call("User32::EnableWindow", hDlgCal, 1);
    oSys.Call("User32::DestroyWindow", hWnd);
  }

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

  return 0;
}

function CheckButtons(nButton)
{
  if (nButton == IDSYSTEM)
    bSystem = ! bSystem;
  else if (nButton == IDLONGDATE)
    bLongDate = ! bLongDate;

  AkelPad.SendMessage(aWnd[IDSYSTEM][WND],   241 /*BM_SETCHECK*/, bSystem,   0);
  AkelPad.SendMessage(aWnd[IDLONGDATE][WND], 241 /*BM_SETCHECK*/, bLongDate, 0);

  oSys.Call("User32::EnableWindow", aWnd[IDLONGDATE][WND], bSystem);
  oSys.Call("User32::EnableWindow", aWnd[IDDF][WND], ! bSystem);
  oSys.Call("User32::EnableWindow", aWnd[IDTF][WND], ! bSystem);
  oSys.Call("User32::EnableWindow", aWnd[IDDFHLP][WND], ! bSystem);
  oSys.Call("User32::EnableWindow", aWnd[IDTFHLP][WND], ! bSystem);

  SetWindowText(aWnd[IDDATE][WND], GetDate());
  SetWindowText(aWnd[IDTIME][WND], GetTime());
}

function ShowFormatHelp(hDlg, hWndHlp, bShow)
{
  if (bShow)
    oSys.Call("User32::SetCapture", hDlg);
  else
    oSys.Call("User32::ReleaseCapture");

  oSys.Call("User32::ShowWindow", hWndHlp, bShow);
}

function ChangeColor(hWnd, nButton)
{
  var nCo        = nButton - IDCOLOR1BUTT;
  var nChoCoSize = _X64 ? 72 : 36; //sizeof(CHOOSECOLOR)
  var lpChoCo    = AkelPad.MemAlloc(nChoCoSize); //CHOOSECOLOR
  var lpCusCo    = AkelPad.MemAlloc(4 * 16); //sizeof(COLORREF) * 16
  var hFocus     = oSys.Call("User32::GetFocus");

  if (nButton == IDCOLOR1BUTT)
    nCo = 4;
  else if (nButton == IDCOLOR5BUTT)
    nCo = 5;

  AkelPad.MemCopy(_PtrAdd(lpChoCo,              0), nChoCoSize,  DT_DWORD); //lStructSize
  AkelPad.MemCopy(_PtrAdd(lpChoCo, _X64 ?  8 :  4), hWnd,        DT_QWORD); //hWndOwner
  AkelPad.MemCopy(_PtrAdd(lpChoCo, _X64 ? 24 : 12), aColor[nCo], DT_DWORD); //rgbResult
  AkelPad.MemCopy(_PtrAdd(lpChoCo, _X64 ? 32 : 16), lpCusCo,     DT_QWORD); //lpCustColors
  AkelPad.MemCopy(_PtrAdd(lpChoCo, _X64 ? 40 : 20), 0x103,       DT_DWORD); //Flags - CC_ANYCOLOR|CC_FULLOPEN|CC_RGBINIT

  if (oSys.Call("Comdlg32::ChooseColor" + _TCHAR, lpChoCo))
  {
    aColor[nCo] = AkelPad.MemRead(_PtrAdd(lpChoCo, _X64 ? 24 : 12), DT_DWORD);
    SetWindowText(aWnd[nButton - 5][WND], aWnd[nButton - 5][TXT]);
    AkelPad.SendMessage(hWndCal, 0x100A /*MCM_SETCOLOR*/, nCo, aColor[nCo]);
  }

  AkelPad.MemFree(lpChoCo);
  AkelPad.MemFree(lpCusCo);
  oSys.Call("User32::SetFocus", hFocus);
}

