// http://akelpad.sourceforge.net/forum/viewtopic.php?p=27750#27750
// Version: 2018-05-22
// Author: KDJ
//
// *** GUI for PDFtk Server - manipulating PDF documents ***
// https://www.pdflabs.com/tools/pdftk-server
//
// Run in AkelPad window:
//   Call("Scripts::Main", 1, "PDFtk-G.js")
//   Call("Scripts::Main", 1, "PDFtk-G.js", "1")
// Run from command line (required registration: regsvr32.exe Scripts.dll):
//   wscript.exe PDFtk-G.js
//   wscript.exe PDFtk-G.js 1
//
// Argument:
//   0 - run only single instance of the script (default)
//   1 - allow to run the script in multiple instances of AkelPad.exe or wscript.exe
//
// Keyboard and mouse:
//   F1        - PDFtk help
//   F5 (F9)   - refresh source PDFs list
//   Alt+Enter - maximize/restore window
//   double click on PDF list - edit ranges
//   right click on list - context menu
//
// Note:
//   The script should be saved in Unicode format

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

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

if ((WScript.Arguments.length > 0) && (WScript.Arguments(0) == "1"))
  sClass += oSys.Call("Kernel32::GetCurrentProcessId");
else
  sClass += hInstDLL;

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

if (hDlg)
{
  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);
  WScript.Quit();
}

var hMainWnd = AkelPad.GetMainWnd();
var oFSO     = new ActiveXObject("Scripting.FileSystemObject");
var hGuiFont = oSys.Call("Gdi32::GetStockObject", 17 /*DEFAULT_GUI_FONT*/);
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 sDlgTitle   = 'PDFtk-G';
var sScriptDir  = oFSO.GetParentFolderName(WScript.ScriptFullName);
var nTotalPages = 0;
var nOutPages   = -1;
var nOutRanges  = 0;
var sPDFtkExe;
var hProcess;
var bCreating;
var bRefreshing;
var nExitCode;

var Scale =
{
  Init: function()
  {
    var hDC = oSys.Call("User32::GetDC", hMainWnd);
    this.ScaleX = oSys.Call("Gdi32::GetDeviceCaps", hDC, 88 /*LOGPIXELSX*/);
    this.ScaleY = oSys.Call("Gdi32::GetDeviceCaps", hDC, 90 /*LOGPIXELSY*/);
    oSys.Call("User32::ReleaseDC", hMainWnd, hDC);
    //Align to 16 pixel
    this.ScaleX += (16 - this.ScaleX % 16) % 16;
    this.ScaleY += (16 - this.ScaleY % 16) % 16;
  },
  X:  function(n) {return oSys.Call("Kernel32::MulDiv", n, this.ScaleX, 96);},
  Y:  function(n) {return oSys.Call("Kernel32::MulDiv", n, this.ScaleY, 96);},
  UX: function(n) {return oSys.Call("Kernel32::MulDiv", n, 96, this.ScaleX);},
  UY: function(n) {return oSys.Call("Kernel32::MulDiv", n, 96, this.ScaleY);}
}
Scale.Init();

var nTab       = 0;
var bCollateW  = 0;
var bShuffleW  = 0;
var bSplitAll  = 0;
var bWaterAll  = 0;
var nWater     = 0;
var nBook      = 0;
var bUTF8      = 0;
var bBOM       = 0;
var nData      = 0;
var sWaterAdd  = "_watermark";
var sWaterPDF  = "";
var sBookTXT   = "";
var sDataTXT   = "";
var sPDFtkDir  = "";
var sPDFReader = "";
var sTXTEditor = "";
var sLastDir   = "";
var nAfter     = 0;
var bSaveList  = 1;
var bSavePass  = 1;
var bPassProt  = 0;
var sOwnerPass = "";
var sUserPass  = "";
var bTopPrint  = 1;
var bLowPrint  = 1;
var bModCont   = 1;
var bAssembly  = 1;
var bCopyCont  = 1;
var bScrRead   = 1;
var bModAnnot  = 1;
var bFillIn    = 1;
var nPDF       = -1;
var aPDF       = [];
var aDlg       = [];

var IDTABTC      = 1000;
var IDCOLLATES   = 1001;
var IDCOLLATEIB  = 1002;
var IDCOLLATEWB  = 1003;
var IDSHUFFLES   = 1004;
var IDSHUFFLEIB  = 1005;
var IDSHUFFLEWB  = 1006;
var IDSPLITS     = 1007;
var IDSPLITALLB  = 1008;
var IDWATERS     = 1009;
var IDWATERALLB  = 1010;
var IDWATERADDS  = 1011;
var IDWATERADDE  = 1012;
var IDWATERBKB   = 1013;
var IDWATERBKMB  = 1014;
var IDWATERSTB   = 1015;
var IDWATERSTMB  = 1016;
var IDWATERPDFS  = 1017;
var IDWATERPDFE  = 1018;
var IDWATERPDFB  = 1019;
var IDWATEROPENB = 1020;
var IDBOOKUTF8B  = 1021;
var IDBOOKBOMB   = 1022;
var IDBOOKEXPB   = 1023;
var IDBOOKIMPB   = 1024;
var IDBOOKTXTE   = 1025;
var IDBOOKTXTB   = 1026;
var IDBOOKOPENB  = 1027;
var IDBOOKHELPB  = 1028;
var IDDATAUTF8B  = 1029;
var IDDATABOMB   = 1030;
var IDDATAANNOB  = 1031;
var IDDATAFIELB  = 1032;
var IDDATAINFOB  = 1033;
var IDDATAUPDB   = 1034;
var IDDATATXTE   = 1035;
var IDDATATXTB   = 1036;
var IDDATAOPENB  = 1037;
var IDPDFTKDIRS  = 1038;
var IDPDFTKDIRE  = 1039;
var IDPDFTKDIRB  = 1040;
var IDREADERS    = 1041;
var IDREADERE    = 1042;
var IDREADERB    = 1043;
var IDEDITORS    = 1044;
var IDEDITORE    = 1045;
var IDEDITORB    = 1046;
var IDAFTERS     = 1047;
var IDAFTERCB    = 1048;
var IDKEEPLISTB  = 1049;
var IDKEEPPASSB  = 1050;
var IDPDFLV      = 1051;
var IDADDB       = 1052;
var IDDUPB       = 1053;
var IDREMOVEB    = 1054;
var IDCLEARB     = 1055;
var IDUPB        = 1056;
var IDDOWNB      = 1057;
var IDRANGESB    = 1058;
var IDOPENB      = 1059;
var IDREFRESHB   = 1060;
var IDTOTALS     = 1061;
var IDOUTPDFS    = 1062;
var IDPASSPROTB  = 1063;
var IDOWNERPASS  = 1064;
var IDOWNERPASE  = 1065;
var IDUSERPASS   = 1066;
var IDUSERPASE   = 1067;
var IDTOPPRINTB  = 1068;
var IDLOWPRINTB  = 1069;
var IDMODCONTB   = 1070;
var IDASSEMBLYB  = 1071;
var IDCOPYCONTB  = 1072;
var IDSCRREADB   = 1073;
var IDMODANNOTB  = 1074;
var IDFILLINB    = 1075;
var IDALLPERMB   = 1076;
var IDCREATEB    = 1077;
var IDOPENPDFB   = 1078;
var IDOPENTXTB   = 1079;
var IDOPENDIRB   = 1080;
var IDHELPB      = 1081;
var IDSITEB      = 1082;
var IDEXITB      = 1083;
var IDPROGRESS   = 1084;

aDlg.MinW = Scale.X(793) + oSys.Call("User32::GetSystemMetrics", 7 /*SM_CXFIXEDFRAME*/) * 2;
aDlg.MinH = Scale.Y(460) + oSys.Call("User32::GetSystemMetrics", 8 /*SM_CYFIXEDFRAME*/) * 2 + oSys.Call("User32::GetSystemMetrics", 4 /*SM_CYCAPTION*/);
aDlg.X    = 100;
aDlg.Y    = 100;
aDlg.W    = aDlg.MinW;
aDlg.H    = aDlg.MinH;
aDlg.Max  = 0;

GetLangStrings();
ReadIni();

aDlg[IDTABTC]      = {W: 773, H: 23,        C: "SysTabControl32",   S: 0x50010500 /*WS_CHILD|WS_VISIBLE|WS_TABSTOP|TCS_FIXEDWIDTH|TCS_BUTTONS*/};
//Collate
aDlg[IDCOLLATES]   = {T: sTxtCollateDescr,  C: "STATIC",            S: 0x40000000 /*WS_CHILD*/};
aDlg[IDCOLLATEIB]  = {T: sTxtInsertWater,   C: "BUTTON",            S: 0x40010003 /*WS_CHILD|WS_TABSTOP|BS_AUTOCHECKBOX*/};
aDlg[IDCOLLATEWB]  = {T: sTxtWatermark,     C: "BUTTON",            S: 0x40010000 /*WS_CHILD|WS_TABSTOP*/};
//Shuffle
aDlg[IDSHUFFLES]   = {T: sTxtShuffleDescr,  C: "STATIC",            S: 0x40000000 /*WS_CHILD*/};
aDlg[IDSHUFFLEIB]  = {T: sTxtInsertWater,   C: "BUTTON",            S: 0x40010003 /*WS_CHILD|WS_TABSTOP|BS_AUTOCHECKBOX*/};
aDlg[IDSHUFFLEWB]  = {T: sTxtWatermark,     C: "BUTTON",            S: 0x40010000 /*WS_CHILD|WS_TABSTOP*/};
//Split
aDlg[IDSPLITS]     = {T: sTxtSplitDescr,    C: "STATIC",            S: 0x40000000 /*WS_CHILD*/};
aDlg[IDSPLITALLB]  = {T: sTxtAllDocs,       C: "BUTTON",            S: 0x40010003 /*WS_CHILD|WS_TABSTOP|BS_AUTOCHECKBOX*/};
//Watermark
aDlg[IDWATERS]     = {T: sTxtWaterDescr,    C: "STATIC",            S: 0x40000000 /*WS_CHILD*/};
aDlg[IDWATERALLB]  = {T: sTxtAllDocs,       C: "BUTTON",            S: 0x40010003 /*WS_CHILD|WS_TABSTOP|BS_AUTOCHECKBOX*/};
aDlg[IDWATERADDS]  = {T: sTxtAddToName,     C: "STATIC",            S: 0x40000000 /*WS_CHILD*/};
aDlg[IDWATERADDE]  = {T: sWaterAdd,         C: "EDIT",              S: 0x40010080 /*WS_CHILD|WS_TABSTOP|ES_AUTOHSCROLL*/, ES: 0x00000200 /*WS_EX_CLIENTEDGE*/};
aDlg[IDWATERBKB]   = {T: sTxtBackgr,        C: "BUTTON",            S: 0x40010009 /*WS_CHILD|WS_TABSTOP|BS_AUTORADIOBUTTON*/};
aDlg[IDWATERBKMB]  = {T: sTxtMultiBackgr,   C: "BUTTON",            S: 0x40010009 /*WS_CHILD|WS_TABSTOP|BS_AUTORADIOBUTTON*/};
aDlg[IDWATERSTB]   = {T: sTxtStamp,         C: "BUTTON",            S: 0x40010009 /*WS_CHILD|WS_TABSTOP|BS_AUTORADIOBUTTON*/};
aDlg[IDWATERSTMB]  = {T: sTxtMultiStamp,    C: "BUTTON",            S: 0x40010009 /*WS_CHILD|WS_TABSTOP|BS_AUTORADIOBUTTON*/};
aDlg[IDWATERPDFS]  = {T: sTxtWaterPDF,      C: "STATIC",            S: 0x40000000 /*WS_CHILD*/};
aDlg[IDWATERPDFE]  = {T: sWaterPDF,         C: "EDIT",              S: 0x40010080 /*WS_CHILD|WS_TABSTOP|ES_AUTOHSCROLL*/, ES: 0x00000200 /*WS_EX_CLIENTEDGE*/};
aDlg[IDWATERPDFB]  = {T: "...",             C: "BUTTON",            S: 0x40010000 /*WS_CHILD|WS_TABSTOP*/};
aDlg[IDWATEROPENB] = {T: ">>",              C: "BUTTON",            S: 0x40010000 /*WS_CHILD|WS_TABSTOP*/};
//Bookmarks
aDlg[IDBOOKUTF8B]  = {T: "UTF-8",           C: "BUTTON",            S: 0x40010003 /*WS_CHILD|WS_TABSTOP|BS_AUTOCHECKBOX*/};
aDlg[IDBOOKBOMB]   = {T: "BOM",             C: "BUTTON",            S: 0x40010003 /*WS_CHILD|WS_TABSTOP|BS_AUTOCHECKBOX*/};
aDlg[IDBOOKEXPB]   = {T: sTxtExportFrom,    C: "BUTTON",            S: 0x40010009 /*WS_CHILD|WS_TABSTOP|BS_AUTORADIOBUTTON*/};
aDlg[IDBOOKIMPB]   = {T: sTxtImportTo,      C: "BUTTON",            S: 0x40010009 /*WS_CHILD|WS_TABSTOP|BS_AUTORADIOBUTTON*/};
aDlg[IDBOOKTXTE]   = {T: sBookTXT,          C: "EDIT",              S: 0x40010080 /*WS_CHILD|WS_TABSTOP|ES_AUTOHSCROLL*/, ES: 0x00000200 /*WS_EX_CLIENTEDGE*/};
aDlg[IDBOOKTXTB]   = {T: "...",             C: "BUTTON",            S: 0x40010000 /*WS_CHILD|WS_TABSTOP*/};
aDlg[IDBOOKOPENB]  = {T: ">>",              C: "BUTTON",            S: 0x40010000 /*WS_CHILD|WS_TABSTOP*/};
aDlg[IDBOOKHELPB]  = {T: "?",               C: "BUTTON",            S: 0x40010000 /*WS_CHILD|WS_TABSTOP*/};
//PDF info
aDlg[IDDATAUTF8B]  = {T: "UTF-8",           C: "BUTTON",            S: 0x40010003 /*WS_CHILD|WS_TABSTOP|BS_AUTOCHECKBOX*/};
aDlg[IDDATABOMB]   = {T: "BOM",             C: "BUTTON",            S: 0x40010003 /*WS_CHILD|WS_TABSTOP|BS_AUTOCHECKBOX*/};
aDlg[IDDATAANNOB]  = {T: sTxtDumpAnnots,    C: "BUTTON",            S: 0x40010009 /*WS_CHILD|WS_TABSTOP|BS_AUTORADIOBUTTON*/};
aDlg[IDDATAFIELB]  = {T: sTxtDumpFields,    C: "BUTTON",            S: 0x40010009 /*WS_CHILD|WS_TABSTOP|BS_AUTORADIOBUTTON*/};
aDlg[IDDATAINFOB]  = {T: sTxtDumpInfo,      C: "BUTTON",            S: 0x40010009 /*WS_CHILD|WS_TABSTOP|BS_AUTORADIOBUTTON*/};
aDlg[IDDATAUPDB]   = {T: sTxtUpdateInfo,    C: "BUTTON",            S: 0x40010009 /*WS_CHILD|WS_TABSTOP|BS_AUTORADIOBUTTON*/};
aDlg[IDDATATXTE]   = {T: sDataTXT,          C: "EDIT",              S: 0x40010080 /*WS_CHILD|WS_TABSTOP|ES_AUTOHSCROLL*/, ES: 0x00000200 /*WS_EX_CLIENTEDGE*/};
aDlg[IDDATATXTB]   = {T: "...",             C: "BUTTON",            S: 0x40010000 /*WS_CHILD|WS_TABSTOP*/};
aDlg[IDDATAOPENB]  = {T: ">>",              C: "BUTTON",            S: 0x40010000 /*WS_CHILD|WS_TABSTOP*/};
//Settings
aDlg[IDPDFTKDIRS]  = {T: sTxtPDFtkDir,      C: "STATIC",            S: 0x40000002 /*WS_CHILD|SS_RIGHT*/};
aDlg[IDPDFTKDIRE]  = {T: sPDFtkDir,         C: "EDIT",              S: 0x40010080 /*WS_CHILD|WS_TABSTOP|ES_AUTOHSCROLL*/, ES: 0x00000200 /*WS_EX_CLIENTEDGE*/};
aDlg[IDPDFTKDIRB]  = {T: "...",             C: "BUTTON",            S: 0x40010000 /*WS_CHILD|WS_TABSTOP*/};
aDlg[IDREADERS]    = {T: sTxtPDFReader,     C: "STATIC",            S: 0x40000002 /*WS_CHILD|SS_RIGHT*/};
aDlg[IDREADERE]    = {T: sPDFReader,        C: "EDIT",              S: 0x40010080 /*WS_CHILD|WS_TABSTOP|ES_AUTOHSCROLL*/, ES: 0x00000200 /*WS_EX_CLIENTEDGE*/};
aDlg[IDREADERB]    = {T: "...",             C: "BUTTON",            S: 0x40010000 /*WS_CHILD|WS_TABSTOP*/};
aDlg[IDEDITORS]    = {T: sTxtTXTEditor,     C: "STATIC",            S: 0x40000002 /*WS_CHILD|SS_RIGHT*/};
aDlg[IDEDITORE]    = {T: sTXTEditor,        C: "EDIT",              S: 0x40010080 /*WS_CHILD|WS_TABSTOP|ES_AUTOHSCROLL*/, ES: 0x00000200 /*WS_EX_CLIENTEDGE*/};
aDlg[IDEDITORB]    = {T: "...",             C: "BUTTON",            S: 0x40010000 /*WS_CHILD|WS_TABSTOP*/};
aDlg[IDAFTERS]     = {T: sTxtAfterCreate,   C: "STATIC",            S: 0x40000000 /*WS_CHILD*/};
aDlg[IDAFTERCB]    = {                      C: "COMBOBOX",          S: 0x50010003 /*WS_CHILD|WS_VISIBLE|WS_TABSTOP|CBS_DROPDOWNLIST*/};
aDlg[IDKEEPLISTB]  = {T: sTxtKeepList,      C: "BUTTON",            S: 0x40010003 /*WS_CHILD|WS_TABSTOP|BS_AUTOCHECKBOX*/};
aDlg[IDKEEPPASSB]  = {T: sTxtKeepPass,      C: "BUTTON",            S: 0x40010003 /*WS_CHILD|WS_TABSTOP|BS_AUTOCHECKBOX*/};
//Source PDF list
aDlg[IDPDFLV]      = {                      C: "SysListView32",     S: 0x5080800D /*WS_CHILD|WS_VISIBLE|WS_BORDER|LVS_NOSORTHEADER|LVS_SHOWSELALWAYS|LVS_SINGLESEL|LVS_REPORT*/};
aDlg[IDADDB]       = {T: sTxtAdd,           C: "BUTTON",            S: 0x50010000 /*WS_CHILD|WS_VISIBLE|WS_TABSTOP*/, K: "Insert"};
aDlg[IDDUPB]       = {T: sTxtDuplicate,     C: "BUTTON",            S: 0x50010000 /*WS_CHILD|WS_VISIBLE|WS_TABSTOP*/, K: "Shift+Insert"};
aDlg[IDREMOVEB]    = {T: sTxtRemove,        C: "BUTTON",            S: 0x50010000 /*WS_CHILD|WS_VISIBLE|WS_TABSTOP*/, K: "Alt+Del"};
aDlg[IDCLEARB]     = {T: sTxtClear,         C: "BUTTON",            S: 0x50010000 /*WS_CHILD|WS_VISIBLE|WS_TABSTOP*/, K: "Shift+Alt+Del"};
aDlg[IDUPB]        = {T: sTxtMoveUp,        C: "BUTTON",            S: 0x50010000 /*WS_CHILD|WS_VISIBLE|WS_TABSTOP*/, K: "Alt+\Up"};
aDlg[IDDOWNB]      = {T: sTxtMoveDown,      C: "BUTTON",            S: 0x50010000 /*WS_CHILD|WS_VISIBLE|WS_TABSTOP*/, K: "Alt+Down"};
aDlg[IDRANGESB]    = {T: sTxtRanges,        C: "BUTTON",            S: 0x50010000 /*WS_CHILD|WS_VISIBLE|WS_TABSTOP*/, K: "Enter"};
aDlg[IDOPENB]      = {T: sTxtOpen,          C: "BUTTON",            S: 0x50010000 /*WS_CHILD|WS_VISIBLE|WS_TABSTOP*/, K: "Ctrl+Enter"};
aDlg[IDREFRESHB]   = {T: sTxtRefresh,       C: "BUTTON",            S: 0x50010000 /*WS_CHILD|WS_VISIBLE|WS_TABSTOP*/, K: "F5 (F9)"};
aDlg[IDTOTALS]     = {                      C: "STATIC",            S: 0x50000002 /*WS_CHILD|WS_VISIBLE|SS_RIGHT*/};
//Output PDF
aDlg[IDOUTPDFS]    = {T: sTxtOutputPermiss, C: "STATIC",            S: 0x50001001 /*WS_CHILD|WS_VISIBLE|SS_SUNKEN|SS_CENTER*/};
aDlg[IDPASSPROTB]  = {T: sTxtPassProt,      C: "BUTTON",            S: 0x50010003 /*WS_CHILD|WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX*/};
aDlg[IDOWNERPASS]  = {T: sTxtOwner,         C: "STATIC",            S: 0x50000002 /*WS_CHILD|WS_VISIBLE|SS_RIGHT*/};
aDlg[IDOWNERPASE]  = {T: sOwnerPass,        C: "EDIT",              S: 0x50010080 /*WS_CHILD|WS_VISIBLE|WS_TABSTOP|ES_AUTOHSCROLL*/, ES: 0x00000200 /*WS_EX_CLIENTEDGE*/};
aDlg[IDUSERPASS]   = {T: sTxtUser,          C: "STATIC",            S: 0x50000002 /*WS_CHILD|WS_VISIBLE|SS_RIGHT*/};
aDlg[IDUSERPASE]   = {T: sUserPass,         C: "EDIT",              S: 0x50010080 /*WS_CHILD|WS_VISIBLE|WS_TABSTOP|ES_AUTOHSCROLL*/, ES: 0x00000200 /*WS_EX_CLIENTEDGE*/};
aDlg[IDTOPPRINTB]  = {T: sTxtTopPrint,      C: "BUTTON",            S: 0x50010003 /*WS_CHILD|WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX*/};
aDlg[IDLOWPRINTB]  = {T: sTxtLowPrint,      C: "BUTTON",            S: 0x50010003 /*WS_CHILD|WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX*/};
aDlg[IDMODCONTB]   = {T: sTxtModCont,       C: "BUTTON",            S: 0x50010003 /*WS_CHILD|WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX*/};
aDlg[IDASSEMBLYB]  = {T: sTxtAssembly,      C: "BUTTON",            S: 0x50010003 /*WS_CHILD|WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX*/};
aDlg[IDCOPYCONTB]  = {T: sTxtCopyCont,      C: "BUTTON",            S: 0x50010003 /*WS_CHILD|WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX*/};
aDlg[IDSCRREADB]   = {T: sTxtScrRead,       C: "BUTTON",            S: 0x50010003 /*WS_CHILD|WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX*/};
aDlg[IDMODANNOTB]  = {T: sTxtModAnnot,      C: "BUTTON",            S: 0x50010003 /*WS_CHILD|WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX*/};
aDlg[IDFILLINB]    = {T: sTxtFillIn,        C: "BUTTON",            S: 0x50010003 /*WS_CHILD|WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX*/};
aDlg[IDALLPERMB]   = {T: sTxtAllPerm,       C: "BUTTON",            S: 0x50010003 /*WS_CHILD|WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX*/};
//Buttons
aDlg[IDCREATEB]    = {T: sTxtCreateFiles,   C: "BUTTON",            S: 0x50010000 /*WS_CHILD|WS_VISIBLE|WS_TABSTOP*/};
aDlg[IDOPENPDFB]   = {T: sTxtOpenPDF,       C: "BUTTON",            S: 0x50010000 /*WS_CHILD|WS_VISIBLE|WS_TABSTOP*/};
aDlg[IDOPENTXTB]   = {T: sTxtOpenTXT,       C: "BUTTON",            S: 0x50010000 /*WS_CHILD|WS_VISIBLE|WS_TABSTOP*/};
aDlg[IDOPENDIRB]   = {T: sTxtOpenDir,       C: "BUTTON",            S: 0x50010000 /*WS_CHILD|WS_VISIBLE|WS_TABSTOP*/};
aDlg[IDHELPB]      = {T: sTxtPDFtkHelp,     C: "BUTTON",            S: 0x50010000 /*WS_CHILD|WS_VISIBLE|WS_TABSTOP*/};
aDlg[IDSITEB]      = {T: sTxtPDFtkSite,     C: "BUTTON",            S: 0x50010000 /*WS_CHILD|WS_VISIBLE|WS_TABSTOP*/};
aDlg[IDEXITB]      = {T: sTxtExit,          C: "BUTTON",            S: 0x50010000 /*WS_CHILD|WS_VISIBLE|WS_TABSTOP*/};
aDlg[IDPROGRESS]   = {                      C: "msctls_progress32", S: 0x40000000 /*WS_CHILD*/};

AkelPad.ScriptNoMutex(0x11 /*ULT_LOCKSENDMESSAGE|ULT_UNLOCKSCRIPTSQUEUE*/);
AkelPad.WindowRegisterClass(sClass);

oSys.Call("User32::CreateWindowExW",
  0,               //dwExStyle
  sClass,          //lpClassName
  sDlgTitle,       //lpWindowName
  0x80CF0000,      //dwStyle=WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_SIZEBOX|WS_MINIMIZEBOX|WS_MAXIMIZEBOX
  aDlg.X,          //x
  aDlg.Y,          //y
  aDlg.W,          //nWidth
  aDlg.H,          //nHeight
  0,               //hWndParent
  0,               //hMenu
  hInstDLL,        //hInstance
  DialogCallback); //Script function callback. To use it class must be registered by WindowRegisterClass.

oSys.Call("User32::ShowWindow", hDlg, aDlg.Max ? 3 /*SW_MAXIMIZE*/ : 1 /*SW_SHOWNORMAL*/);

AkelPad.WindowGetMessage();
AkelPad.WindowUnregisterClass(sClass);
oSys.Call("User32::DestroyIcon", hIconSmall);
oSys.Call("User32::DestroyIcon", hIconBig);

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

  if (uMsg == 1 /*WM_CREATE*/)
  {
    hDlg = hWnd;
    InitDlg();
  }

  else if (uMsg == 0x8000 /*WM_APP*/)
  {
    oSys.Call("User32::UpdateWindow", hDlg);

    if (aPDF.length)
      PostMessage(hDlg, 273 /*WM_COMMAND*/, IDREFRESHB, 0);
  }

  else if (uMsg == 0x8001 /*WM_APP+1*/)
    oSys.Call("User32::SetFocus", lParam);

  else if (uMsg == 6 /*WM_ACTIVATE*/)
  {
    if (wParam == 0 /*WA_INACTIVE*/)
      aDlg.Focus = oSys.Call("User32::GetFocus");
  }

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

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

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

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

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

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

  else if (uMsg == 256 /*WM_KEYDOWN*/)
  {
    if (wParam == 0x09 /*VK_TAB*/)
    {
      if (Ctrl() && ! Alt())
      {
        if (Shift())
        {
          if (nTab > 0)
            --nTab;
          else
            nTab = 6;
        }
        else
        {
          if (nTab < 6)
            ++nTab;
          else
            nTab = 0;
        }

        PostMessage(aDlg[IDTABTC].HWND, 4912 /*TCM_SETCURFOCUS*/, nTab, 0);
      }
    }
    else if (wParam == 0x70 /*VK_F1*/)
    {
      if (! Ctrl() && ! Shift())
        PDFtkHelp();
    }
    else if ((wParam == 0x74 /*VK_F5*/) || (wParam == 0x78 /*VK_F9*/))
    {
      if (! Ctrl() && ! Shift())
        PostMessage(hDlg, 273 /*WM_COMMAND*/, IDREFRESHB, 0);
    }
    else if (oSys.Call("User32::GetFocus") == aDlg[IDPDFLV].HWND)
    {
      if (wParam == 0x0D /*VK_RETURN*/)
      {
        if (! Alt())
        {
          if (Ctrl() || Shift())
            PostMessage(hDlg, 273 /*WM_COMMAND*/, IDOPENB, 0);
          else
            PostMessage(hDlg, 273 /*WM_COMMAND*/, IDRANGESB, 0);
        }
      }
      else if (wParam == 0x2D /*VK_INSERT*/)
      {
        if (! Ctrl())
          PostMessage(hDlg, 273 /*WM_COMMAND*/, Shift() ? IDDUPB : IDADDB, 0);
      }
      else if (wParam == 0x5D /*VK_APPS*/)
      {
        if (! Ctrl() && ! Shift())
          MenuPDFLV();
      }
    }
  }

  else if (uMsg == 260 /*WM_SYSKEYDOWN*/)
  {
    if (wParam == 13 /*VK_RETURN*/)
    {
      if (! Shift())
        oSys.Call("User32::ShowWindow", hDlg, oSys.Call("User32::IsZoomed", hDlg) ? 9 /*SW_RESTORE*/ : 3 /*SW_MAXIMIZE*/);
    }
    else if (oSys.Call("User32::GetFocus") == aDlg[IDPDFLV].HWND)
    {
      if (wParam == 0x2E /*VK_DELETE*/)
        PostMessage(hDlg, 273 /*WM_COMMAND*/, Shift() ? IDCLEARB : IDREMOVEB, 0);
      else if (wParam == 0x26 /*VK_UP*/)
      {
        if (! Shift())
          PostMessage(hDlg, 273 /*WM_COMMAND*/, IDUPB, 0);
      }
      else if (wParam == 0x28 /*VK_DOWN*/)
      {
        if (! Shift())
          PostMessage(hDlg, 273 /*WM_COMMAND*/, IDDOWNB, 0);
      }
    }
  }

  else if (uMsg == 78 /*WM_NOTIFY*/)
  {
    if (wParam == IDTABTC)
    {
      nTab = SendMessage(aDlg[IDTABTC].HWND, 4911 /*TCM_GETCURFOCUS*/, 0, 0);
      EnableControlsDlg();
      SetDefButton(0, IDTABTC);
      SetColumsWidthLV();
      PostMessage(aDlg[IDTABTC].HWND, 4876 /*TCM_SETCURSEL*/, nTab, 0);
    }
    else if (wParam == IDPDFLV)
    {
      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*/)
          {
            nPDF = GetCurSelLV(aDlg[IDPDFLV].HWND);
            EnableControlsDlg();
          }
          break;
        case -2 : //NM_CLICK
          if (AkelPad.MemRead(_PtrAdd(lParam, _X64 ? 24 : 12) /*NMITEMACTIVATE.iItem*/, 3 /*DT_DWORD*/) == -1)
            SetCurSelLV(aDlg[IDPDFLV].HWND, GetCurFocLV(aDlg[IDPDFLV].HWND));
          break;
        case -3 : //NM_DBLCLK
          if (AkelPad.MemRead(_PtrAdd(lParam, _X64 ? 24 : 12) /*NMITEMACTIVATE.iItem*/, 3 /*DT_DWORD*/) == -1)
            SetCurSelLV(aDlg[IDPDFLV].HWND, GetCurFocLV(aDlg[IDPDFLV].HWND));
          else
            PostMessage(hDlg, 273 /*WM_COMMAND*/, IDRANGESB, 0);
          break;
        case -5 : //NM_RCLICK
        case -6 : //NM_RDBLCLK
          if (AkelPad.MemRead(_PtrAdd(lParam, _X64 ? 24 : 12) /*NMITEMACTIVATE.iItem*/, 3 /*DT_DWORD*/) == -1)
            SetCurSelLV(aDlg[IDPDFLV].HWND, GetCurFocLV(aDlg[IDPDFLV].HWND));
          SetDefButton();
          if (! (bCreating || bRefreshing))
            MenuPDFLV(_PtrAdd(lParam, _X64 ? 44 : 32) /*NMITEMACTIVATE.ptAction*/);
          break;
      }
    }
  }

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

    if (nID == IDCOLLATEIB)
    {
      bCollateW = SendMessage(lParam, 240 /*BM_GETCHECK*/, 0, 0);
      EnableControlsDlg();
    }

    else if (nID == IDSHUFFLEIB)
    {
      bShuffleW = SendMessage(lParam, 240 /*BM_GETCHECK*/, 0, 0);
      EnableControlsDlg();
    }

    else if ((nID == IDCOLLATEWB) || (nID == IDSHUFFLEWB))
    {
      nTab = 3;
      SendMessage(aDlg[IDTABTC].HWND, 4912 /*TCM_SETCURFOCUS*/, nTab, 0);
      SendMessage(aDlg[IDWATERPDFE].HWND, 177 /*EM_SETSEL*/, 0, -1);
      oSys.Call("User32::SetFocus", aDlg[IDWATERPDFE].HWND);
    }

    else if (nID == IDSPLITALLB)
      bSplitAll = SendMessage(lParam, 240 /*BM_GETCHECK*/, 0, 0);

    else if (nID == IDWATERALLB)
    {
      bWaterAll = SendMessage(lParam, 240 /*BM_GETCHECK*/, 0, 0);
      EnableControlsDlg();
    }

    else if (nID == IDWATERADDE)
    {
      if (nCode == 0x0300 /*EN_CHANGE*/)
        sWaterAdd = GetWindowText(lParam);
    }

    else if ((nID >= IDWATERBKB) && (nID <= IDWATERSTMB))
      nWater = nID - IDWATERBKB;

    else if (nID == IDWATERPDFE)
    {
      if (nCode == 0x0300 /*EN_CHANGE*/)
      {
        sWaterPDF = GetWindowText(lParam);
        EnableControlsDlg();
      }
    }

    else if (nID == IDWATERPDFB)
      SetFileName(sTxtSelWaterPDF, "pdf", sWaterPDF, aDlg[IDWATERPDFE].HWND);

    else if (nID == IDWATEROPENB)
      OpenWaterPDF();

    else if (nID == IDBOOKUTF8B)
    {
      bUTF8 = SendMessage(lParam, 240 /*BM_GETCHECK*/, 0, 0);
      SendMessage(aDlg[IDDATAUTF8B].HWND, 241 /*BM_SETCHECK*/, bUTF8, 0);
      EnableControlsDlg();
    }

    else if (nID == IDBOOKBOMB)
    {
      bBOM = SendMessage(lParam, 240 /*BM_GETCHECK*/, 0, 0);
      SendMessage(aDlg[IDDATABOMB].HWND, 241 /*BM_SETCHECK*/, bBOM, 0);
    }

    else if ((nID == IDBOOKEXPB) || (nID == IDBOOKIMPB))
    {
      nBook = nID - IDBOOKEXPB;
      EnableControlsDlg();
    }

    else if (nID == IDBOOKTXTE)
    {
      if (nCode == 0x0300 /*EN_CHANGE*/)
      {
        sBookTXT = GetWindowText(lParam);
        EnableControlsDlg();
      }
    }

    else if (nID == IDBOOKTXTB)
      SetFileName(sTxtSelBookTXT, "txt", sBookTXT, aDlg[IDBOOKTXTE].HWND);

    else if (nID == IDBOOKOPENB)
      OpenBookTXT();

    else if (nID == IDBOOKHELPB)
      MsgBox(sTxtBookmarksHelp);

    else if (nID == IDDATAUTF8B)
    {
      bUTF8 = SendMessage(lParam, 240 /*BM_GETCHECK*/, 0, 0);
      SendMessage(aDlg[IDBOOKUTF8B].HWND, 241 /*BM_SETCHECK*/, bUTF8, 0);
      EnableControlsDlg();
    }

    else if (nID == IDDATABOMB)
    {
      bBOM = SendMessage(lParam, 240 /*BM_GETCHECK*/, 0, 0);
      SendMessage(aDlg[IDBOOKBOMB].HWND, 241 /*BM_SETCHECK*/, bBOM, 0);
    }

    else if ((nID >= IDDATAANNOB) && (nID <= IDDATAUPDB))
    {
      nData = nID - IDDATAANNOB;
      EnableControlsDlg();
    }

    else if (nID == IDDATATXTE)
    {
      if (nCode == 0x0300 /*EN_CHANGE*/)
      {
        sDataTXT = GetWindowText(lParam);
        EnableControlsDlg();
      }
    }

    else if (nID == IDDATATXTB)
      SetFileName(sTxtSelDataTXT, "txt", sDataTXT, aDlg[IDDATATXTE].HWND);

    else if (nID == IDDATAOPENB)
      OpenDataTXT();

    else if (nID == IDPDFTKDIRE)
    {
      if (nCode == 0x0300 /*EN_CHANGE*/)
        sPDFtkDir = GetWindowText(lParam);
    }

    else if (nID == IDPDFTKDIRB)
      SetPDFtkDir();

    else if (nID == IDREADERE)
    {
      if (nCode == 0x0300 /*EN_CHANGE*/)
        sPDFReader = GetWindowText(lParam);
    }

    else if (nID == IDREADERB)
      SetFileName(sTxtSelPDFReader, "exe", sPDFReader, aDlg[IDREADERE].HWND);

    else if (nID == IDEDITORE)
    {
      if (nCode == 0x0300 /*EN_CHANGE*/)
        sTXTEditor = GetWindowText(lParam);
    }

    else if (nID == IDEDITORB)
      SetFileName(sTxtSelTXTEditor, "exe", sTXTEditor, aDlg[IDEDITORE].HWND);

    else if (nID == IDAFTERCB)
    {
      if ((nCode == 1 /*CBN_SELCHANGE*/) || (nCode == 8 /*CBN_CLOSEUP*/))
        nAfter = SendMessage(lParam, 327 /*CB_GETCURSEL*/, 0, 0);
    }

    else if (nID == IDKEEPLISTB)
      bSaveList = SendMessage(lParam, 240 /*BM_GETCHECK*/, 0, 0);

    else if (nID == IDKEEPPASSB)
      bSavePass = SendMessage(lParam, 240 /*BM_GETCHECK*/, 0, 0);

    else if ((nID >= IDADDB) && (nID <= IDREFRESHB))
    {
      if (oSys.Call("User32::IsWindowEnabled", aDlg[nID].HWND))
      {
        if (nID == IDADDB)
          Add();
        else if (nID == IDDUPB)
          Duplicate();
        else if (nID == IDREMOVEB)
          Remove();
        else if (nID == IDCLEARB)
          Clear();
        else if (nID == IDUPB)
          MoveUp();
        else if (nID == IDDOWNB)
          MoveDown();
        else if (nID == IDRANGESB)
          Ranges();
        else if (nID == IDOPENB)
          Open();
        else
          Refresh(1);

        EnableControlsDlg();
      }
    }

    else if (nID == IDPASSPROTB)
    {
      bPassProt = SendMessage(lParam, 240 /*BM_GETCHECK*/, 0, 0);
      EnableControlsDlg();
    }

    else if ((nID == IDOWNERPASE) || (nID == IDUSERPASE))
    {
      if (nCode == 0x0300 /*EN_CHANGE*/)
      {
        if (nID == IDOWNERPASE)
          sOwnerPass = GetWindowText(lParam);
        else
          sUserPass = GetWindowText(lParam);
        EnableControlsDlg();
      }
    }

    else if ((nID >= IDTOPPRINTB) && (nID <= IDFILLINB))
    {
      if (nID == IDTOPPRINTB)
        bTopPrint = SendMessage(lParam, 240 /*BM_GETCHECK*/, 0, 0);
      else if (nID == IDLOWPRINTB)
        bLowPrint = SendMessage(lParam, 240 /*BM_GETCHECK*/, 0, 0);
      else if (nID == IDMODCONTB)
        bModCont = SendMessage(lParam, 240 /*BM_GETCHECK*/, 0, 0);
      else if (nID == IDASSEMBLYB)
        bAssembly = SendMessage(lParam, 240 /*BM_GETCHECK*/, 0, 0);
      else if (nID == IDCOPYCONTB)
        bCopyCont = SendMessage(lParam, 240 /*BM_GETCHECK*/, 0, 0);
      else if (nID == IDSCRREADB)
        bScrRead = SendMessage(lParam, 240 /*BM_GETCHECK*/, 0, 0);
      else if (nID == IDMODANNOTB)
        bModAnnot = SendMessage(lParam, 240 /*BM_GETCHECK*/, 0, 0);
      else if (nID == IDFILLINB)
        bFillIn = SendMessage(lParam, 240 /*BM_GETCHECK*/, 0, 0);

      EnableControlsDlg();
    }

    else if (nID == IDALLPERMB)
    {
      bTopPrint = bLowPrint = bModCont = bAssembly = bCopyCont = bScrRead = bModAnnot = bFillIn = SendMessage(lParam, 240 /*BM_GETCHECK*/, 0, 0);
      for (i = IDTOPPRINTB; i <= IDFILLINB; ++i)
        SendMessage(aDlg[i].HWND, 241 /*BM_SETCHECK*/, bTopPrint, 0);
    }

    else if (nID == IDCREATEB)
    {
      if (bCreating)
        StopCmd();
      else
        Create();
    }

    else if (nID == IDOPENPDFB)
      OpenPDF();

    else if (nID == IDOPENTXTB)
      OpenTXT();

    else if (nID == IDOPENDIRB)
      OpenFolder();

    else if (nID == IDHELPB)
      PDFtkHelp();

    else if (nID == IDSITEB)
      AkelPad.Exec('rundll32.exe shell32, ShellExec_RunDLL ' + 'https://www.pdflabs.com/tools/pdftk-server');

    else if ((nID == IDEXITB) || (nID == 2 /*IDCANCEL*/))
      PostMessage(hDlg, 16 /*WM_CLOSE*/, 0, 0);
  }

  else if (uMsg == 16 /*WM_CLOSE*/)
  {
    StopCmd();
    WriteIni();
    oSys.Call("User32::DestroyWindow", hDlg);
  }

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

  return 0;
}

function InitDlg()
{
  var lpTCITEM;
  var lpLVCOLUMN;
  var aText;
  var aFmt;
  var i;

  if (! hMainWnd)
  {
    SendMessage(hDlg, 128 /*WM_SETICON*/, 0 /*ICON_SMALL*/, hIconSmall);
    SendMessage(hDlg, 128 /*WM_SETICON*/, 1 /*ICON_BIG*/,   hIconBig);
  }

  for (i = IDTABTC; i < aDlg.length; ++i)
  {
    aDlg[i].HWND = oSys.Call("User32::CreateWindowExW",
      aDlg[i].ES, //dwExStyle
      aDlg[i].C,  //lpClassName
      aDlg[i].T,  //lpWindowName
      aDlg[i].S,  //dwStyle
      0,          //x
      0,          //y
      aDlg[i].W,  //nWidth
      aDlg[i].H,  //nHeight
      hDlg,       //hWndParent
      i,          //ID
      hInstDLL,   //hInstance
      0);         //lpParam
    SendMessage(aDlg[i].HWND, 48 /*WM_SETFONT*/, hGuiFont, 1);
  }

  //Split
  SendMessage(aDlg[IDSPLITALLB].HWND, 241 /*BM_SETCHECK*/, bSplitAll, 0);

  //Collate
  SendMessage(aDlg[IDCOLLATEIB].HWND, 241 /*BM_SETCHECK*/, bCollateW, 0);

  //Shuffle
  SendMessage(aDlg[IDSHUFFLEIB].HWND, 241 /*BM_SETCHECK*/, bShuffleW, 0);

  //Watermark
  SendMessage(aDlg[IDWATERALLB].HWND, 241 /*BM_SETCHECK*/, bWaterAll, 0);
  SendMessage(aDlg[IDWATERADDE].HWND, 197 /*EM_SETLIMITTEXT*/, 20, 0);
  for (i = IDWATERBKB; i <= IDWATERSTMB; ++i)
    SendMessage(aDlg[i].HWND, 241 /*BM_SETCHECK*/, 0, 0);
  SendMessage(aDlg[IDWATERBKB + nWater].HWND, 241 /*BM_SETCHECK*/, 1, 0);

  //Bookmarks
  SendMessage(aDlg[IDBOOKUTF8B].HWND, 241 /*BM_SETCHECK*/, bUTF8, 0);
  SendMessage(aDlg[IDBOOKBOMB].HWND, 241 /*BM_SETCHECK*/, bBOM, 0);
  for (i = IDBOOKEXPB; i <= IDBOOKIMPB; ++i)
    SendMessage(aDlg[i].HWND, 241 /*BM_SETCHECK*/, 0, 0);
  SendMessage(aDlg[IDBOOKEXPB + nBook].HWND, 241 /*BM_SETCHECK*/, 1, 0);

  //PDF info
  SendMessage(aDlg[IDDATAUTF8B].HWND, 241 /*BM_SETCHECK*/, bUTF8, 0);
  SendMessage(aDlg[IDDATABOMB].HWND, 241 /*BM_SETCHECK*/, bBOM, 0);
  for (i = IDDATAANNOB; i <= IDDATAUPDB; ++i)
    SendMessage(aDlg[i].HWND, 241 /*BM_SETCHECK*/, 0, 0);
  SendMessage(aDlg[IDDATAANNOB + nData].HWND, 241 /*BM_SETCHECK*/, 1, 0);

  //Settings
  SendMessage(aDlg[IDAFTERCB].HWND, 323 /*CB_ADDSTRING*/, 0, sTxtShowMessage);
  SendMessage(aDlg[IDAFTERCB].HWND, 323 /*CB_ADDSTRING*/, 0, sTxtOpenNewFile);
  SendMessage(aDlg[IDAFTERCB].HWND, 323 /*CB_ADDSTRING*/, 0, sTxtOpenOutDir);
  SendMessage(aDlg[IDAFTERCB].HWND, 334 /*CB_SETCURSEL*/, nAfter, 0);
  SendMessage(aDlg[IDKEEPLISTB].HWND, 241 /*BM_SETCHECK*/, bSaveList, 0);
  SendMessage(aDlg[IDKEEPPASSB].HWND, 241 /*BM_SETCHECK*/, bSavePass, 0);

  //Source PDF list
  lpLVCOLUMN = AkelPad.MemAlloc(_X64 ? 56 : 44 /*sizeof(LVCOLUMN)*/);
  aText      = [AkelPad.MemStrPtr(sTxtSourcePDFs), AkelPad.MemStrPtr(sTxtPageCount), AkelPad.MemStrPtr(sTxtPagesToCopy + "/" + sTxtRotation), AkelPad.MemStrPtr(sTxtOutPages)];
  aFmt       = [0 /*LVCFMT_LEFT*/, 1 /*LVCFMT_RIGHT*/, 0, 1]; //Alignment of the column header

  AkelPad.MemCopy(lpLVCOLUMN, 5 /*LVCF_FMT|LVCF_TEXT*/, 3 /*DT_DWORD*/); //mask
  for (i = 0; i < 4; ++i)
  {
    AkelPad.MemCopy(_PtrAdd(lpLVCOLUMN, 4), aFmt[i], 3 /*DT_DWORD*/);
    AkelPad.MemCopy(_PtrAdd(lpLVCOLUMN, _X64 ? 16 : 12), aText[i], 2 /*DT_QWORD*/);
    SendMessage(aDlg[IDPDFLV].HWND, 4193 /*LVM_INSERTCOLUMNW*/, i, lpLVCOLUMN);
  }
  AkelPad.MemFree(lpLVCOLUMN);

  for (i = 0; i < aPDF.length;)
  {
    if (oFSO.FileExists(aPDF[i].F))
    {
      aPDF[i].TP = 0;
      aPDF[i].OP = 0;
      aPDF[i].OR = 0;
      InsertItemLV(aDlg[IDPDFLV].HWND, i++);
    }
    else
      aPDF.splice(i, 1);
  }

  if ((nPDF < 0) && aPDF.length)
    nPDF = 0;
  else if (nPDF >= aPDF.length)
    nPDF = aPDF.length - 1;

  SendMessage(aDlg[IDPDFLV].HWND, 4150 /*LVM_SETEXTENDEDLISTVIEWSTYLE*/, 0, 0x0421 /*LVS_EX_INFOTIP|LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES*/);
  SetCurSelLV(aDlg[IDPDFLV].HWND, nPDF);

  //Output PDF
  SendMessage(aDlg[IDOWNERPASE].HWND, 197 /*EM_SETLIMITTEXT*/, 32, 0);
  SendMessage(aDlg[IDUSERPASE].HWND,  197 /*EM_SETLIMITTEXT*/, 32, 0);
  SendMessage(aDlg[IDPASSPROTB].HWND, 241 /*BM_SETCHECK*/, bPassProt, 0);
  SendMessage(aDlg[IDTOPPRINTB].HWND, 241 /*BM_SETCHECK*/, bTopPrint, 0);
  SendMessage(aDlg[IDLOWPRINTB].HWND, 241 /*BM_SETCHECK*/, bLowPrint, 0);
  SendMessage(aDlg[IDMODCONTB].HWND,  241 /*BM_SETCHECK*/, bModCont,  0);
  SendMessage(aDlg[IDASSEMBLYB].HWND, 241 /*BM_SETCHECK*/, bAssembly, 0);
  SendMessage(aDlg[IDCOPYCONTB].HWND, 241 /*BM_SETCHECK*/, bCopyCont, 0);
  SendMessage(aDlg[IDSCRREADB].HWND,  241 /*BM_SETCHECK*/, bScrRead, 0);
  SendMessage(aDlg[IDMODANNOTB].HWND, 241 /*BM_SETCHECK*/, bModAnnot, 0);
  SendMessage(aDlg[IDFILLINB].HWND,   241 /*BM_SETCHECK*/, bFillIn, 0);

  //Progress
  SendMessage(aDlg[IDPROGRESS].HWND, 1028 /*PBM_SETSTEP*/, 1, 0);

  //Tabs
  lpTCITEM = AkelPad.MemAlloc(_X64 ? 40 : 28 /*sizeof(TCITEM)*/);
  aText    = [AkelPad.MemStrPtr(sTxtCollate), AkelPad.MemStrPtr(sTxtShuffle), AkelPad.MemStrPtr(sTxtSplit), AkelPad.MemStrPtr(sTxtWatermark), AkelPad.MemStrPtr(sTxtBookmarks), AkelPad.MemStrPtr(sTxtPDFInfo), AkelPad.MemStrPtr(sTxtSettings)];

  AkelPad.MemCopy(lpTCITEM, 1 /*TCIF_TEXT*/, 3 /*DT_DWORD*/); //mask
  for (i = 0; i < aText.length; ++i)
  {
    AkelPad.MemCopy(_PtrAdd(lpTCITEM, _X64 ? 16 : 12), aText[i], 2 /*DT_QWORD*/); //pszText
    SendMessage(aDlg[IDTABTC].HWND, 4926 /*TCM_INSERTITEMW*/, i, lpTCITEM);
  }
  AkelPad.MemFree(lpTCITEM);
  SendMessage(aDlg[IDTABTC].HWND, 4912 /*TCM_SETCURFOCUS*/, nTab, 0);

  PostMessage(hDlg, 0x8000 /*WM_APP*/, 0, 0);

  aDlg.Focus = aDlg[IDTABTC].HWND;
}

function EnableControlsDlg()
{
  var bOutputPDF = ! ((nTab == 4) && (nBook == 0) || (nTab == 5) && (nData != 3));
  var lpLVCOLUMN = AkelPad.MemAlloc(_X64 ? 56 : 44 /*sizeof(LVCOLUMN)*/);
  var lpText     = AkelPad.MemAlloc(128);
  var i;

  oSys.Call("User32::EnableWindow", aDlg[IDTABTC].HWND, ! (bCreating || bRefreshing));

  for (i = IDCOLLATES; i <= IDCOLLATEWB; ++i)
    oSys.Call("User32::ShowWindow", aDlg[i].HWND, nTab == 0);
  oSys.Call("User32::EnableWindow", aDlg[IDCOLLATEIB].HWND, ! (bCreating || bRefreshing));
  oSys.Call("User32::EnableWindow", aDlg[IDCOLLATEWB].HWND, bCollateW && ! (bCreating || bRefreshing));

  for (i = IDSHUFFLES; i <= IDSHUFFLEWB; ++i)
    oSys.Call("User32::ShowWindow", aDlg[i].HWND, nTab == 1);
  oSys.Call("User32::EnableWindow", aDlg[IDSHUFFLEIB].HWND, ! (bCreating || bRefreshing));
  oSys.Call("User32::EnableWindow", aDlg[IDSHUFFLEWB].HWND, bShuffleW && ! (bCreating || bRefreshing));

  oSys.Call("User32::ShowWindow",   aDlg[IDSPLITS].HWND,    nTab == 2);
  oSys.Call("User32::ShowWindow",   aDlg[IDSPLITALLB].HWND, nTab == 2);
  oSys.Call("User32::EnableWindow", aDlg[IDSPLITALLB].HWND, (aPDF.length > 1) && ! (bCreating || bRefreshing));

  for (i = IDWATERS; i <= IDWATEROPENB; ++i)
    oSys.Call("User32::ShowWindow", aDlg[i].HWND, nTab == 3);
  oSys.Call("User32::EnableWindow", aDlg[IDWATERALLB].HWND, (aPDF.length > 1) && ! (bCreating || bRefreshing));
  oSys.Call("User32::EnableWindow", aDlg[IDWATERADDS].HWND, (aPDF.length > 1) && bWaterAll && ! (bCreating || bRefreshing));
  oSys.Call("User32::EnableWindow", aDlg[IDWATERADDE].HWND, (aPDF.length > 1) && bWaterAll && ! (bCreating || bRefreshing));
  for (i = IDWATERBKB; i <= IDWATERPDFB; ++i)
    oSys.Call("User32::EnableWindow", aDlg[i].HWND, ! (bCreating || bRefreshing));
  oSys.Call("User32::EnableWindow", aDlg[IDWATEROPENB].HWND, sWaterPDF.length && ! (bCreating || bRefreshing));

  for (i = IDBOOKUTF8B; i <= IDBOOKHELPB; ++i)
    oSys.Call("User32::ShowWindow", aDlg[i].HWND, nTab == 4);
  oSys.Call("User32::EnableWindow", aDlg[IDBOOKUTF8B].HWND, ! (bCreating || bRefreshing));
  oSys.Call("User32::EnableWindow", aDlg[IDBOOKBOMB].HWND,  bUTF8 && ! (bCreating || bRefreshing));
  for (i = IDBOOKEXPB; i <= IDBOOKIMPB; ++i)
    oSys.Call("User32::EnableWindow", aDlg[i].HWND, ! (bCreating || bRefreshing));
  oSys.Call("User32::EnableWindow", aDlg[IDBOOKTXTE].HWND,  (nBook == 1) && ! (bCreating || bRefreshing));
  oSys.Call("User32::EnableWindow", aDlg[IDBOOKTXTB].HWND,  (nBook == 1) && ! (bCreating || bRefreshing) );
  oSys.Call("User32::EnableWindow", aDlg[IDBOOKOPENB].HWND, (nBook == 1) && sBookTXT.length && ! (bCreating || bRefreshing) );
  oSys.Call("User32::EnableWindow", aDlg[IDBOOKHELPB].HWND, (nBook == 1) && ! (bCreating || bRefreshing) );

  for (i = IDDATAUTF8B; i <= IDDATAOPENB; ++i)
    oSys.Call("User32::ShowWindow", aDlg[i].HWND, nTab == 5);
  oSys.Call("User32::EnableWindow", aDlg[IDDATAUTF8B].HWND, ! (bCreating || bRefreshing));
  oSys.Call("User32::EnableWindow", aDlg[IDDATABOMB].HWND,  bUTF8 && ! (bCreating || bRefreshing));
  for (i = IDDATAANNOB; i <= IDDATAUPDB; ++i)
    oSys.Call("User32::EnableWindow", aDlg[i].HWND, ! (bCreating || bRefreshing));
  oSys.Call("User32::EnableWindow", aDlg[IDDATATXTE].HWND,  (nData == 3) && ! (bCreating || bRefreshing));
  oSys.Call("User32::EnableWindow", aDlg[IDDATATXTB].HWND,  (nData == 3) && ! (bCreating || bRefreshing));
  oSys.Call("User32::EnableWindow", aDlg[IDDATAOPENB].HWND, (nData == 3) && sDataTXT.length && ! (bCreating || bRefreshing));

  for (i = IDPDFTKDIRS; i <= IDKEEPPASSB; ++i)
  {
    oSys.Call("User32::ShowWindow",   aDlg[i].HWND, nTab == 6);
    oSys.Call("User32::EnableWindow", aDlg[i].HWND, ! (bCreating || bRefreshing));
  }

  oSys.Call("User32::EnableWindow", aDlg[IDADDB].HWND,     ! (bCreating || bRefreshing));
  oSys.Call("User32::EnableWindow", aDlg[IDDUPB].HWND,     aPDF.length && ! (bCreating || bRefreshing));
  oSys.Call("User32::EnableWindow", aDlg[IDREMOVEB].HWND,  aPDF.length && ! (bCreating || bRefreshing));
  oSys.Call("User32::EnableWindow", aDlg[IDCLEARB].HWND,   aPDF.length && ! (bCreating || bRefreshing));
  oSys.Call("User32::EnableWindow", aDlg[IDUPB].HWND,      (nPDF > 0) && ! (bCreating || bRefreshing));
  oSys.Call("User32::EnableWindow", aDlg[IDDOWNB].HWND,    (nPDF < aPDF.length - 1) && ! (bCreating || bRefreshing));
  oSys.Call("User32::EnableWindow", aDlg[IDRANGESB].HWND,  aPDF.length && aPDF[nPDF].TP && ((nTab < 2) || (nTab > 5)) && ! (bCreating || bRefreshing));
  oSys.Call("User32::EnableWindow", aDlg[IDOPENB].HWND,    aPDF.length && ! (bCreating || bRefreshing));
  oSys.Call("User32::ShowWindow",   aDlg[IDREFRESHB].HWND, aPDF.length && (nOutPages < 0) && ! (bCreating || bRefreshing));
  oSys.Call("User32::ShowWindow",   aDlg[IDTOTALS].HWND,   ! (aPDF.length && (nOutPages < 0)));
  if ((nTab < 2) || (nTab > 5))
    SetWindowText(aDlg[IDTOTALS].HWND, sTxtTotalOutPages + ((nOutPages < 0) ? "0" : nOutPages));
  else
    SetWindowText(aDlg[IDTOTALS].HWND, sTxtTotalPages + nTotalPages);

  oSys.Call("User32::EnableWindow", aDlg[IDOUTPDFS].HWND,   bOutputPDF);
  oSys.Call("User32::EnableWindow", aDlg[IDPASSPROTB].HWND, bOutputPDF && ! (bCreating || bRefreshing));
  for (i = IDOWNERPASS; i <= IDALLPERMB; ++i)
    oSys.Call("User32::EnableWindow", aDlg[i].HWND, bOutputPDF && bPassProt && ! (bCreating || bRefreshing));
  SendMessage(aDlg[IDALLPERMB].HWND, 241 /*BM_SETCHECK*/, bTopPrint && bLowPrint && bModCont && bAssembly && bCopyCont && bScrRead && bModAnnot && bFillIn, 0);

  oSys.Call("User32::EnableWindow", aDlg[IDCREATEB].HWND, aPDF.length && ((nTab != 3) || sWaterPDF.length) && ((nTab != 4) || (nBook == 0) || sBookTXT.length) && ((nTab != 5) || (nData != 3) || sDataTXT.length) && (nTab != 6) && ((! bOutputPDF) || (! bPassProt) || sOwnerPass.length || sUserPass.length) && (nOutPages >= 0) && (bCreating || ! bRefreshing));
  SetWindowText(aDlg[IDCREATEB].HWND, bCreating ? sTxtCancel : aDlg[IDCREATEB].T);

  for (i = IDOPENPDFB; i <= IDSITEB; ++i)
    oSys.Call("User32::EnableWindow", aDlg[i].HWND, ! (bCreating || bRefreshing));

  if (aPDF.length)
  {
    if (! (aDlg[IDPDFLV].S & 0x00010000 /*WS_TABSTOP*/))
      aDlg[IDPDFLV].S |= 0x00010000 /*WS_TABSTOP*/;
  }
  else
  {
    if (aDlg[IDPDFLV].S & 0x00010000 /*WS_TABSTOP*/)
      aDlg[IDPDFLV].S ^= 0x00010000 /*WS_TABSTOP*/;
  }
  oSys.Call("User32::SetWindowLongW", aDlg[IDPDFLV].HWND, -16 /*GWL_STYLE*/, aDlg[IDPDFLV].S);

  AkelPad.MemCopy(lpText, sTxtSourcePDFs + (aPDF.length ? " (" + (nPDF + 1) + "/" + aPDF.length + ")" : ""), 1 /*DT_UNICODE*/);
  AkelPad.MemCopy(lpLVCOLUMN, 4 /*LVCF_TEXT*/, 3 /*DT_DWORD*/); //mask
  AkelPad.MemCopy(_PtrAdd(lpLVCOLUMN, _X64 ? 16 : 12), lpText, 2 /*DT_QWORD*/);
  SendMessage(aDlg[IDPDFLV].HWND, 4192 /*LVM_SETCOLUMNW*/, 0, lpLVCOLUMN);
  AkelPad.MemFree(lpLVCOLUMN);
  AkelPad.MemFree(lpText);
}

function SetDefButton(nDefID, nFocusID)
{
  var i;

  SendMessage(aDlg[IDCOLLATEWB].HWND,  244 /*BM_SETSTYLE*/, 0 /*BS_PUSHBUTTON*/, 1);
  SendMessage(aDlg[IDSHUFFLEWB].HWND,  244 /*BM_SETSTYLE*/, 0 /*BS_PUSHBUTTON*/, 1);
  SendMessage(aDlg[IDWATERPDFB].HWND,  244 /*BM_SETSTYLE*/, 0 /*BS_PUSHBUTTON*/, 1);
  SendMessage(aDlg[IDWATEROPENB].HWND, 244 /*BM_SETSTYLE*/, 0 /*BS_PUSHBUTTON*/, 1);
  SendMessage(aDlg[IDBOOKTXTB].HWND,   244 /*BM_SETSTYLE*/, 0 /*BS_PUSHBUTTON*/, 1);
  SendMessage(aDlg[IDBOOKOPENB].HWND,  244 /*BM_SETSTYLE*/, 0 /*BS_PUSHBUTTON*/, 1);
  SendMessage(aDlg[IDBOOKHELPB].HWND,  244 /*BM_SETSTYLE*/, 0 /*BS_PUSHBUTTON*/, 1);
  SendMessage(aDlg[IDDATATXTB].HWND,   244 /*BM_SETSTYLE*/, 0 /*BS_PUSHBUTTON*/, 1);
  SendMessage(aDlg[IDDATAOPENB].HWND,  244 /*BM_SETSTYLE*/, 0 /*BS_PUSHBUTTON*/, 1);
  SendMessage(aDlg[IDPDFTKDIRB].HWND,  244 /*BM_SETSTYLE*/, 0 /*BS_PUSHBUTTON*/, 1);
  SendMessage(aDlg[IDREADERB].HWND,    244 /*BM_SETSTYLE*/, 0 /*BS_PUSHBUTTON*/, 1);
  SendMessage(aDlg[IDEDITORB].HWND,    244 /*BM_SETSTYLE*/, 0 /*BS_PUSHBUTTON*/, 1);

  for (i = IDADDB; i <= IDREFRESHB; ++i)
    SendMessage(aDlg[i].HWND, 244 /*BM_SETSTYLE*/, 0 /*BS_PUSHBUTTON*/, 1);

  for (i = IDCREATEB; i <= IDEXITB; ++i)
    SendMessage(aDlg[i].HWND, 244 /*BM_SETSTYLE*/, 0 /*BS_PUSHBUTTON*/, 1);

  if (nDefID)
    SendMessage(aDlg[nDefID].HWND, 244 /*BM_SETSTYLE*/, 1 /*BS_DRFPUSHBUTTON*/, 1);
  if (nFocusID)
    oSys.Call("User32::SetFocus", aDlg[nFocusID].HWND);
}

function ResizeDlg(nW, nH)
{
  var nFlags = 0x14; //SWP_NOACTIVATE|SWP_NOZORDER
  var nX3    = Scale.X(3);
  var nX5    = Scale.X(5);
  var nX10   = Scale.X(10);
  var nX16   = Scale.X(16);
  var nX20   = Scale.X(20);
  var nX70   = Scale.X(70);
  var nX90   = Scale.X(90);
  var nX110  = Scale.X(110);
  var nX130  = Scale.X(130);
  var nX150  = Scale.X(150);
  var nX170  = Scale.X(170);
  var nX200  = Scale.X(200);
  var nX250  = Scale.X(250);
  var nX350  = Scale.X(350);
  var nX400  = Scale.X(400);
  var nX600  = Scale.X(600);
  var nX640  = Scale.X(640);
  var nX750  = Scale.X(750);
  var nY3    = Scale.Y(3);
  var nY5    = Scale.Y(5);
  var nY10   = Scale.Y(10);
  var nY13   = Scale.Y(13);
  var nY16   = Scale.Y(16);
  var nY20   = Scale.Y(20);
  var nY21   = Scale.Y(21);
  var nY23   = Scale.Y(23);
  var nY26   = Scale.Y(26);
  var nX, nY;
  var i;

  oSys.Call("User32::SetWindowPos", aDlg[IDTABTC].HWND, 0,
    nX10,
    nY10,
    nW - nX10 * 2,
    nY23,
    nFlags);
  SendMessage(aDlg[IDTABTC].HWND, 4905 /*TCM_SETITEMSIZE*/, 0, MkLong(Math.floor((nW - nX10 * 2 - nX3 * 8) / 7), nY23));

  //Collate
  nX = Math.round((nW - nX400) / 2);
  oSys.Call("User32::SetWindowPos", aDlg[IDCOLLATES].HWND, 0,
    nX,
    Scale.Y(50),
    nX400,
    nY13 * 3,
    nFlags);
  oSys.Call("User32::SetWindowPos", aDlg[IDCOLLATEIB].HWND, 0,
    nX,
    Scale.Y(103),
    nX250,
    nY16,
    nFlags);
  oSys.Call("User32::SetWindowPos", aDlg[IDCOLLATEWB].HWND, 0,
    nX + nX250 + nX5,
    Scale.Y(100),
    nX90,
    nY23,
    nFlags);

  //Shuffle
  nX = Math.round((nW - nX640) / 2);
  oSys.Call("User32::SetWindowPos", aDlg[IDSHUFFLES].HWND, 0,
    nX,
    Scale.Y(50),
    nX640,
    nY13 * 3,
    nFlags);
  oSys.Call("User32::SetWindowPos", aDlg[IDSHUFFLEIB].HWND, 0,
    nX,
    Scale.Y(103),
    nX250,
    nY16,
    nFlags);
  oSys.Call("User32::SetWindowPos", aDlg[IDSHUFFLEWB].HWND, 0,
    nX + nX250 + nX5,
    Scale.Y(100),
    nX90,
    nY23,
    nFlags);

  //Split
  nX = Math.round((nW - nX600) / 2);
  oSys.Call("User32::SetWindowPos", aDlg[IDSPLITS].HWND, 0,
    nX,
    Scale.Y(60),
    nX600,
    nY13 * 2,
    nFlags);
  oSys.Call("User32::SetWindowPos", aDlg[IDSPLITALLB].HWND, 0,
    nX,
    Scale.Y(95),
    nX130,
    nY16,
    nFlags);

  //Watermark
  nX = Math.round((nW - nX750) / 2);
  oSys.Call("User32::SetWindowPos", aDlg[IDWATERS].HWND, 0,
    nX,
    Scale.Y(50),
    nX750,
    nY13,
    nFlags);
  oSys.Call("User32::SetWindowPos", aDlg[IDWATERALLB].HWND, 0,
    nX,
    Scale.Y(70),
    nX130,
    nY16,
    nFlags);
  oSys.Call("User32::SetWindowPos", aDlg[IDWATERADDS].HWND, 0,
    nX,
    Scale.Y(90),
    nX90,
    nY13,
    nFlags);
  oSys.Call("User32::SetWindowPos", aDlg[IDWATERADDE].HWND, 0,
    nX,
    Scale.Y(105),
    nX90,
    nY21,
    nFlags);
  nX += nX130 + nX20;
  for (i = 0; i < 2; ++i)
    oSys.Call("User32::SetWindowPos", aDlg[IDWATERBKB + i].HWND, 0,
      nX,
      Scale.Y(80) + nY20 * i,
      nX110,
      nY16,
      nFlags);
  nX += nX110 + nX5;
  for (i = 0; i < 2; ++i)
    oSys.Call("User32::SetWindowPos", aDlg[IDWATERSTB + i].HWND, 0,
      nX,
      Scale.Y(80) + nY20 * i,
      nX90,
      nY16,
      nFlags);
  nX += nX90 + nX5;
  oSys.Call("User32::SetWindowPos", aDlg[IDWATERPDFS].HWND, 0,
    nX,
    Scale.Y(80),
    nX350,
    nY13,
    nFlags);
  oSys.Call("User32::SetWindowPos", aDlg[IDWATERPDFE].HWND, 0,
    nX,
    Scale.Y(96),
    nX350,
    nY21,
    nFlags);
  for (i = 0; i < 2; ++i)
    oSys.Call("User32::SetWindowPos", aDlg[IDWATERPDFB + i].HWND, 0,
      nX + nX350 + nX20 * i,
      Scale.Y(95),
      nX20,
      nY23,
      nFlags);

  //Bookmarks
  nX = Math.round((nW - Scale.X(505)) / 2);
  oSys.Call("User32::SetWindowPos", aDlg[IDBOOKUTF8B].HWND, 0,
    nX,
    Scale.Y(50),
    Scale.X(50),
    nY16,
    nFlags);
  oSys.Call("User32::SetWindowPos", aDlg[IDBOOKBOMB].HWND, 0,
    nX,
    Scale.Y(50) + nY20,
    Scale.X(50),
    nY16,
    nFlags);
  nX += Scale.X(80);
  for (i = 0; i < 2; ++i)
    oSys.Call("User32::SetWindowPos", aDlg[IDBOOKEXPB + i].HWND, 0,
      nX,
      Scale.Y(50) + nY20 * i,
      nX350,
      nY16,
      nFlags);
  oSys.Call("User32::SetWindowPos", aDlg[IDBOOKTXTE].HWND, 0,
    nX + nX16,
    Scale.Y(90),
    nX350,
    nY21,
    nFlags);
  for (i = 0; i < 3; ++i)
    oSys.Call("User32::SetWindowPos", aDlg[IDBOOKTXTB + i].HWND, 0,
      nX + nX16 + nX350 + nX20 * i,
      Scale.Y(89),
      nX20,
      nY23,
      nFlags);

  //PDF info
  nX = Math.round((nW - Scale.X(705)) / 2);
  oSys.Call("User32::SetWindowPos", aDlg[IDDATAUTF8B].HWND, 0,
    nX,
    Scale.Y(50),
    Scale.X(50),
    nY16,
    nFlags);
  oSys.Call("User32::SetWindowPos", aDlg[IDDATABOMB].HWND, 0,
    nX,
    Scale.Y(50) + nY20,
    Scale.X(50),
    nY16,
    nFlags);
  nX += Scale.X(80);
  for (i = 0; i < 2; ++i)
    oSys.Call("User32::SetWindowPos", aDlg[IDDATAANNOB + i].HWND, 0,
      nX,
      Scale.Y(50) + nY20 * i,
      nX200,
      nY16,
      nFlags);
  nX += Scale.X(220);
  for (i = 0; i < 2; ++i)
    oSys.Call("User32::SetWindowPos", aDlg[IDDATAINFOB + i].HWND, 0,
      nX,
      Scale.Y(50) + nY20 * i,
      nX350,
      nY16,
      nFlags);
  oSys.Call("User32::SetWindowPos", aDlg[IDDATATXTE].HWND, 0,
    nX + nX16,
    Scale.Y(90),
    nX350,
    nY21,
    nFlags);
  for (i = 0; i < 2; ++i)
    oSys.Call("User32::SetWindowPos", aDlg[IDDATATXTB + i].HWND, 0,
      nX + nX16 + nX350 + nX20 * i,
      Scale.Y(89),
      nX20,
      nY23,
      nFlags);

  //Settings
  nX = Math.round((nW - Scale.X(700)) / 2);
  for (i = 0; i < 3; ++i)
  {
    oSys.Call("User32::SetWindowPos", aDlg[IDPDFTKDIRS + i * 3].HWND, 0,
      nX,
      Scale.Y(55) + nY26 * i,
      nX90,
      nY13,
      nFlags);
    oSys.Call("User32::SetWindowPos", aDlg[IDPDFTKDIRE + i * 3].HWND, 0,
      nX + nX90 + nX3,
      Scale.Y(51) + nY26 * i,
      nX350,
      nY21,
      nFlags);
    oSys.Call("User32::SetWindowPos", aDlg[IDPDFTKDIRB + i * 3].HWND, 0,
      nX + nX90 + nX3 + nX350,
      Scale.Y(50) + nY26 * i,
      nX20,
      nY23,
      nFlags);
  }
  nX += Scale.X(530),
  oSys.Call("User32::SetWindowPos", aDlg[IDAFTERS].HWND, 0,
    nX,
    Scale.Y(45),
    nX170,
    nY13,
    nFlags);
  oSys.Call("User32::SetWindowPos", aDlg[IDAFTERCB].HWND, 0,
    nX,
    Scale.Y(60),
    nX170,
    Scale.Y(100),
    nFlags);
  for (i = 0; i < 2; ++i)
    oSys.Call("User32::SetWindowPos", aDlg[IDKEEPLISTB + i].HWND, 0,
      nX,
      Scale.Y(91) + nY20 * i,
      nX170,
      nY16,
      nFlags);

  //Source PDFs
  nY = Scale.Y(150);
  oSys.Call("User32::SetWindowPos", aDlg[IDPDFLV].HWND, 0,
    nX10,
    nY,
    nW - nX10 * 2,
    nH - Scale.Y(154) - nY5 * 2 - nY23 - nY,
    nFlags);
  nY = nH - Scale.Y(154) - nY5 - nY23;
  for (i = 0; i < 8; ++i)
    oSys.Call("User32::SetWindowPos", aDlg[IDADDB + i].HWND, 0,
      nX10 + nX5 + (nX70 + nX3) * i,
      nY,
      nX70,
      nY23,
      nFlags);
  oSys.Call("User32::SetWindowPos", aDlg[IDREFRESHB].HWND, 0,
    nW - nX10 - nX5 - nX70,
    nY,
    nX70,
    nY23,
    nFlags);
  oSys.Call("User32::SetWindowPos", aDlg[IDTOTALS].HWND, 0,
    nW - nX10 - nX5 - (nX150 + nX10),
    nY + nY5,
    nX150 + nX10,
    nY13,
    nFlags);

  //Output PDF - permissions
  nX = Math.round((nW - nX70 - 3 - nX150 * 4 - nX10 * 8) / 2);
  nY = nH - Scale.Y(136) + nY13;
  oSys.Call("User32::SetWindowPos", aDlg[IDOUTPDFS].HWND, 0,
    (nW - nX200) / 2,
    nY - nY13 - nY5,
    nX200,
    nY16,
    nFlags);
  oSys.Call("User32::SetWindowPos", aDlg[IDPASSPROTB].HWND, 0,
    nX + nX70 + nX3,
    nY,
    nX150,
    nY16,
    nFlags);
  for (i = 0; i < 2; ++i)
  {
    oSys.Call("User32::SetWindowPos", aDlg[IDOWNERPASS + i * 2].HWND, 0,
      nX,
      nY + nY20 + nY26 * i + nY3,
      nX70,
      nY13,
      nFlags);
    oSys.Call("User32::SetWindowPos", aDlg[IDOWNERPASE + i * 2].HWND, 0,
      nX + nX70 + nX3,
      nY + nY20 + nY26 * i,
      nX150,
      nY21,
      nFlags);
  }
  nX += nX70 + nX3 + nX150 + nX10 * 6;
  nY += nY13;
  for (i = 0; i < 9; ++i)
    oSys.Call("User32::SetWindowPos", aDlg[IDTOPPRINTB + i].HWND, 0,
      nX + (nX150 + nX10) * Math.floor(i / 3),
      nY + nY20 * (i % 3),
      nX150,
      nY16,
      nFlags);

  //buttons
  oSys.Call("User32::SetWindowPos", aDlg[IDCREATEB].HWND, 0,
    nX10,
    nH - nY10 - nY26,
    nX90,
    nY26,
    nFlags);
  for (i = IDOPENPDFB; i <= IDEXITB; ++i)
    oSys.Call("User32::SetWindowPos", aDlg[i].HWND, 0,
      nW - nX10 - nX90 * (IDEXITB - i + 1) - nX5 * (IDEXITB - i),
      nH - nY10 - nY26,
      nX90,
      nY26,
      nFlags);
  oSys.Call("User32::SetWindowPos", aDlg[IDPROGRESS].HWND, 0,
    nX10 + nX90 + nX5,
    nH - nY10 - nY26,
    Scale.X(105),
    nY26,
    nFlags);

  SetColumsWidthLV();
  SendMessage(aDlg[IDPDFLV].HWND, 4115 /*LVM_ENSUREVISIBLE*/, nPDF, false);
  oSys.Call("user32::InvalidateRect", hDlg, 0, true);
}

function PaintFrames()
{
  var lpPaint = AkelPad.MemAlloc(_X64 ? 72 : 64 /*sizeof(PAINTSTRUCT)*/);
  var lpRect  = AkelPad.MemAlloc(16 /*sizeof(RECT)*/);
  var hDC     = oSys.Call("User32::BeginPaint", hDlg, lpPaint);
  var nW, nH;

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

  if (! (oSys.Call("User32::IsZoomed", hDlg) || oSys.Call("User32::IsIconic", hDlg)))
  {
    AkelPad.MemCopy(_PtrAdd(lpRect, 0), nW - oSys.Call("User32::GetSystemMetrics",  2 /*SM_CXVSCROLL*/), 3 /*DT_DWORD*/);
    AkelPad.MemCopy(_PtrAdd(lpRect, 4), nH - oSys.Call("User32::GetSystemMetrics", 20 /*SM_CYVSCROLL*/), 3 /*DT_DWORD*/);
    oSys.Call("User32::DrawFrameControl", hDC, lpRect, 3 /*DFC_SCROLL*/, 0x8 /*DFCS_SCROLLSIZEGRIP*/);
  }

  AkelPad.MemCopy(_PtrAdd(lpRect,  0), Scale.X(10), 3 /*DT_DWORD*/);
  AkelPad.MemCopy(_PtrAdd(lpRect,  4), Scale.Y(33), 3 /*DT_DWORD*/);
  AkelPad.MemCopy(_PtrAdd(lpRect,  8), nW - Scale.X(10), 3 /*DT_DWORD*/);
  AkelPad.MemCopy(_PtrAdd(lpRect, 12), Scale.Y(135), 3 /*DT_DWORD*/);
  oSys.Call("User32::DrawEdge", hDC, lpRect, 0x9 /*EDGE_BUMP*/, 0x800F /*BF_MONO|BF_RECT*/);

  AkelPad.MemCopy(_PtrAdd(lpRect,  4), Scale.Y(150), 3 /*DT_DWORD*/);
  AkelPad.MemCopy(_PtrAdd(lpRect, 12), nH - Scale.Y(154), 3 /*DT_DWORD*/);
  oSys.Call("User32::DrawEdge", hDC, lpRect, 0x9 /*EDGE_BUMP*/, 0x800F /*BF_MONO|BF_RECT*/);

  AkelPad.MemCopy(_PtrAdd(lpRect,  4), nH - Scale.Y(136), 3 /*DT_DWORD*/);
  AkelPad.MemCopy(_PtrAdd(lpRect, 12), nH - Scale.Y(46),  3 /*DT_DWORD*/);
  oSys.Call("User32::DrawEdge", hDC, lpRect, 0x9 /*EDGE_BUMP*/, 0x800F /*BF_MONO|BF_RECT*/);

  oSys.Call("User32::EndPaint", hDlg, lpPaint);

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

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

  if (hWnd)
    oSys.Call("User32::GetWindowRect", hWnd, lpRect);
  else
    oSys.Call("User32::SystemParametersInfoW", 0x30 /*SPI_GETWORKAREA*/, 0, lpRect, 0);

  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 GetWindowText(hWnd)
{
  var sText    = "";
  var nTextLen = SendMessage(hWnd, 14 /*WM_GETTEXTLENGTH*/, 0, 0);
  var lpText;

  if (nTextLen)
  {
    lpText = AkelPad.MemAlloc(nTextLen * 2 + 2);
    SendMessage(hWnd, 13 /*WM_GETTEXT*/, nTextLen + 1, lpText);
    sText = AkelPad.MemRead(lpText, 1 /*DT_UNICODE*/);
    AkelPad.MemFree(lpText);
  }

  return sText;
}

function SetWindowText(hWnd, sText)
{
  SendMessage(hWnd, 12 /*WM_SETTEXT*/, 0, sText.toString());
}

function ReplaceEditText(hWnd, sText)
{
  SendMessage(hWnd, 177 /*EM_SETSEL*/, 0, -1);
  SendMessage(hWnd, 194 /*EM_REPLACESEL*/, 1, sText);
  SendMessage(hWnd, 177 /*EM_SETSEL*/, 0, -1);
}

function GetItemRectLV(hWnd, nItem, oRect)
{
  var lpRect = AkelPad.MemAlloc(16 /*sizeof(RECT)*/);

  SendMessage(hWnd, 4110 /*LVM_GETITEMRECT*/, nItem, lpRect);
  oSys.Call("User32::ClientToScreen", hWnd, lpRect);
  oSys.Call("User32::ClientToScreen", hWnd, _PtrAdd(lpRect, 8));

  oRect.X1 = AkelPad.MemRead(_PtrAdd(lpRect,  0), 3 /*DT_DWORD*/);
  oRect.Y1 = AkelPad.MemRead(_PtrAdd(lpRect,  4), 3 /*DT_DWORD*/);
  oRect.X2 = AkelPad.MemRead(_PtrAdd(lpRect,  8), 3 /*DT_DWORD*/);
  oRect.Y2 = AkelPad.MemRead(_PtrAdd(lpRect, 12), 3 /*DT_DWORD*/);

  AkelPad.MemFree(lpRect);
}

function GetCurFocLV(hWnd)
{
  return SendMessage(hWnd, 4108 /*LVM_GETNEXTITEM*/, -1, 0x1 /*LVNI_FOCUSED*/)
}

function GetCurSelLV(hWnd)
{
  return SendMessage(hWnd, 4108 /*LVM_GETNEXTITEM*/, -1, 0x2 /*LVNI_SELECTED*/);
}

function SetCurSelLV(hWnd, nItem)
{
  var lpLVITEM = AkelPad.MemAlloc(_X64 ? 72 : 60 /*sizeof(LVITEM)*/);

  AkelPad.MemCopy(_PtrAdd(lpLVITEM, 12), 0x3, 3 /*DT_DWORD*/); //state=LVIS_SELECTED|LVIS_FOCUSED
  AkelPad.MemCopy(_PtrAdd(lpLVITEM, 16),  -1, 3 /*DT_DWORD*/); //stateMask
  SendMessage(hWnd, 4139 /*LVM_SETITEMSTATE*/, nItem, lpLVITEM);
  SendMessage(hWnd, 4115 /*LVM_ENSUREVISIBLE*/, nItem, 0);

  AkelPad.MemFree(lpLVITEM);
}

function InsertItemLV(hWnd, nItem, sText)
{
  var lpText   = AkelPad.MemAlloc(512 * 2);
  var lpLVITEM = AkelPad.MemAlloc(_X64 ? 72 : 60 /*sizeof(LVITEM)*/);

  AkelPad.MemCopy(lpText, (hWnd == aDlg[IDPDFLV].HWND) ? aPDF[nItem].F : sText, 1 /*DT_UNICODE*/);
  AkelPad.MemCopy(_PtrAdd(lpLVITEM, 0),              0x0001, 3 /*DT_DWORD*/); //mask=LVIF_TEXT
  AkelPad.MemCopy(_PtrAdd(lpLVITEM, 4),               nItem, 3 /*DT_DWORD*/); //iItem
  AkelPad.MemCopy(_PtrAdd(lpLVITEM, _X64 ? 24 : 20), lpText, 2 /*DT_QWORD*/); //pszText
  AkelPad.MemCopy(_PtrAdd(lpLVITEM, _X64 ? 32 : 24),   1024, 3 /*DT_DWORD*/); //cchTextMax
  SendMessage(hWnd, 4173 /*LVM_INSERTITEMW*/, 0, lpLVITEM);

  if (hWnd == aDlg[IDPDFLV].HWND)
  {
    AkelPad.MemCopy(lpText, aPDF[nItem].TP ? aPDF[nItem].TP.toString() : "?", 1 /*DT_UNICODE*/);
    AkelPad.MemCopy(_PtrAdd(lpLVITEM, 8), 1, 3 /*DT_DWORD*/); //iSubItem
    SendMessage(hWnd, 4212 /*LVM_SETITEMTEXTW*/, nItem, lpLVITEM);

    AkelPad.MemCopy(lpText, aPDF[nItem].R ? aPDF[nItem].R.substr(0, 511) : sTxtAll, 1 /*DT_UNICODE*/);
    AkelPad.MemCopy(_PtrAdd(lpLVITEM, 8), 2, 3 /*DT_DWORD*/); //iSubItem
    SendMessage(hWnd, 4212 /*LVM_SETITEMTEXTW*/, nItem, lpLVITEM);

    AkelPad.MemCopy(lpText, aPDF[nItem].OP.toString(), 1 /*DT_UNICODE*/);
    AkelPad.MemCopy(_PtrAdd(lpLVITEM, 8), 3, 3 /*DT_DWORD*/); //iSubItem
    SendMessage(hWnd, 4212 /*LVM_SETITEMTEXTW*/, nItem, lpLVITEM);
  }

  AkelPad.MemFree(lpText);
  AkelPad.MemFree(lpLVITEM);
}

function SetItemTextLV(hWnd, nItem, nSubItem, sText)
{
  var lpText   = AkelPad.MemAlloc(512 * 2);
  var lpLVITEM = AkelPad.MemAlloc(_X64 ? 72 : 60 /*sizeof(LVITEM)*/);

  AkelPad.MemCopy(lpText, sText.toString().substr(0, 511), 1 /*DT_UNICODE*/);
  AkelPad.MemCopy(_PtrAdd(lpLVITEM, 0),              0x0001, 3 /*DT_DWORD*/); //mask=LVIF_TEXT
  AkelPad.MemCopy(_PtrAdd(lpLVITEM, 8),            nSubItem, 3 /*DT_DWORD*/); //iSubItem
  AkelPad.MemCopy(_PtrAdd(lpLVITEM, _X64 ? 24 : 20), lpText, 2 /*DT_QWORD*/); //pszText
  AkelPad.MemCopy(_PtrAdd(lpLVITEM, _X64 ? 32 : 24),   1024, 3 /*DT_DWORD*/); //cchTextMax

  SendMessage(hWnd, 4212 /*LVM_SETITEMTEXTW*/, nItem, lpLVITEM);

  AkelPad.MemFree(lpText);
  AkelPad.MemFree(lpLVITEM);
}

function DeleteItemLV(hWnd, nItem)
{
  SendMessage(hWnd, 4104 /*LVM_DELETEITEM*/, nItem, 0);
}

function SetColumsWidthLV()
{
  var oRect  = {};
  var aWidth = [0, Scale.X(75), 0, 0];
  var i;

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

  if ((nTab < 2) || (nTab == 6))
  {
    aWidth[2] = Scale.X(190);
    aWidth[3] = Scale.X(105);
  }

  aWidth[0] = oRect.W - oSys.Call("User32::GetSystemMetrics", 2 /*SM_CXVSCROLL*/) - aWidth[1] - aWidth[2] - aWidth[3];

  for (i = 0; i <= 3; ++i)
    SendMessage(aDlg[IDPDFLV].HWND, 4126 /*LVM_SETCOLUMNWIDTH*/, i, aWidth[i]);
}

function IsPDFtkExists()
{
  var sDir = sPDFtkDir ? sPDFtkDir : sScriptDir;

  sPDFtkExe = sDir + ((sDir.slice(-1) == "\\") ? "" : "\\") + "pdftk.exe";

  if (oFSO.FileExists(sPDFtkExe))
    return true;

  nTab = 6;
  SendMessage(aDlg[IDTABTC].HWND, 4912 /*TCM_SETCURFOCUS*/, nTab, 0);
  SendMessage(aDlg[IDPDFTKDIRE].HWND, 177 /*EM_SETSEL*/, 0, -1);
  oSys.Call("User32::SetFocus", aDlg[IDPDFTKDIRE].HWND);
  MsgBox(sPDFtkExe + "\n\n" + sTxtNoFile);

  return false;
}

function IsReaderExists()
{
  var bExists = true;
  var sFile;

  if (! oFSO.FileExists(sPDFReader))
  {
    if (sFile = GetAssocString(".pdf"))
    {
      sPDFReader = sFile;
      ReplaceEditText(aDlg[IDREADERE].HWND, sPDFReader);
    }
    else
    {
      bExists = false;
      nTab    = 6;

      SendMessage(aDlg[IDTABTC].HWND, 4912 /*TCM_SETCURFOCUS*/, nTab, 0);
      SendMessage(aDlg[IDREADERE].HWND, 177 /*EM_SETSEL*/, 0, -1);
      oSys.Call("User32::SetFocus", aDlg[IDREADERE].HWND);
      MsgBox(sTxtNoPDFReader);
    }
  }

  return bExists;
}

function IsEditorExists()
{
  var bExists = true;
  var sFile;

  if (! oFSO.FileExists(sTXTEditor))
  {
    if (hMainWnd)
    {
      sTXTEditor = GetAkelExe();
      ReplaceEditText(aDlg[IDEDITORE].HWND, sTXTEditor);
    }
    else if (sFile = GetAssocString(".txt"))
    {
      sTXTEditor = sFile;
      ReplaceEditText(aDlg[IDEDITORE].HWND, sTXTEditor);
    }
    else
    {
      bExists = false;
      nTab    = 6;

      SendMessage(aDlg[IDTABTC].HWND, 4912 /*TCM_SETCURFOCUS*/, nTab, 0);
      SendMessage(aDlg[IDEDITORE].HWND, 177 /*EM_SETSEL*/, 0, -1);
      oSys.Call("User32::SetFocus", aDlg[IDEDITORE].HWND);
      MsgBox(sTxtNoTXTEditor);
    }
  }

  return bExists;
}

function GetAssocString(sStr)
{
  var sFile  = "";
  var lpFile = AkelPad.MemAlloc(260 * 2);;
  var lpSize = AkelPad.MemAlloc(4);

  AkelPad.MemCopy(lpSize, 260, 3 /*DT_DWORD*/);

  if (oSys.Call("Shlwapi::AssocQueryStringW", 0, 2 /*ASSOCSTR_EXECUTABLE*/, sStr, "open", lpFile, lpSize) == 0 /*S_OK*/)
    sFile = AkelPad.MemRead(lpFile, 1 /*DT_UNICODE*/);

  AkelPad.MemFree(lpFile);
  AkelPad.MemFree(lpSize);

  return sFile;
}

function GetAkelExe()
{
  var lpFile = AkelPad.MemAlloc(260 * 2);
  var sFile;

  oSys.Call("Kernel32::GetModuleFileNameW", 0, lpFile, 260);
  sFile = AkelPad.MemRead(lpFile, 1 /*DT_UNICODE*/);
  AkelPad.MemFree(lpFile);

  return sFile;
}

function SetPDFtkDir()
{
  var oRect = {};
  var sDir;

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

  if (sDir = BrowseForFolder(sPDFtkDir, "\n" + sTxtSelPDFtkDir, oRect.X, oRect.Y + oRect.H + 3))
  {
    ReplaceEditText(aDlg[IDPDFTKDIRE].HWND, sDir);
    SetDefButton(0, IDPDFTKDIRE);
  }
}

function SetFileName(sTitle, sExt, sFile, hWndEdit)
{
  var oRect = {};

  GetWindowPos(hWndEdit, oRect);

  if (sFile = GetOpenSaveFileName(0, sTitle, sExt, sFile, 0, oRect.X, oRect.Y + oRect.H + 3))
  {
    ReplaceEditText(hWndEdit, sFile);
    oSys.Call("User32::SetFocus", hWndEdit);
    SetDefButton();
  }
}

function OpenWaterPDF()
{
  if (oFSO.FileExists(sWaterPDF))
  {
    if (IsReaderExists())
      AkelPad.Exec('"' + sPDFReader + '" "' + sWaterPDF + '"');
  }
  else
  {
    SendMessage(aDlg[IDWATERPDFE].HWND, 177 /*EM_SETSEL*/, 0, -1);
    SetDefButton(0, IDWATERPDFE);
    MsgBox(sWaterPDF + "\n\n" + sTxtNoFile);
  }
}

function OpenBookTXT()
{
  if (oFSO.FileExists(sBookTXT))
  {
    if (IsEditorExists())
      AkelPad.Exec('"' + sTXTEditor + '" "' + sBookTXT + '"');
  }
  else
  {
    SendMessage(aDlg[IDBOOKTXTE].HWND, 177 /*EM_SETSEL*/, 0, -1);
    SetDefButton(0, IDBOOKTXTE);
    MsgBox(sBookTXT + "\n\n" + sTxtNoFile);
  }
}

function OpenDataTXT()
{
  if (oFSO.FileExists(sDataTXT))
  {
    if (IsEditorExists())
      AkelPad.Exec('"' + sTXTEditor + '" "' + sDataTXT + '"');
  }
  else
  {
    SendMessage(aDlg[IDDATATXTE].HWND, 177 /*EM_SETSEL*/, 0, -1);
    SetDefButton(0, IDDATATXTE);
    MsgBox(sDataTXT + "\n\n" + sTxtNoFile);
  }
}

function MenuPDFLV(lpPoint)
{
  var MF_STRING = 0x0000;
  var MF_GRAYED = 0x0001;
  var hMenu     = oSys.Call("User32::CreatePopupMenu");
  var oRect;
  var nX, nY;
  var nCmd;
  var i;

  //menu from mouse r-click
  if (lpPoint)
  {
    oSys.Call("User32::ClientToScreen", aDlg[IDPDFLV].HWND, lpPoint);
    nX = AkelPad.MemRead(_PtrAdd(lpPoint, 0), 3 /*DT_DWORD*/);
    nY = AkelPad.MemRead(_PtrAdd(lpPoint, 4), 3 /*DT_DWORD*/);
  }
  //menu from keyboard
  else
  {
    oRect = {};
    GetWindowPos(aDlg[IDPDFLV].HWND, oRect);
    nX = oRect.X + (oRect.W - Scale.X(200)) / 2;
    GetItemRectLV(aDlg[IDPDFLV].HWND, nPDF, oRect);
    nY = oRect.Y2;
  }

  for (i = IDADDB; i <= IDOPENB; ++i)
    oSys.Call("User32::AppendMenuW", hMenu, oSys.Call("User32::IsWindowEnabled", aDlg[i].HWND) ? MF_STRING : MF_GRAYED, i, aDlg[i].T + "\t" + aDlg[i].K);

  oSys.Call("user32::AppendMenuW", hMenu, 0x0800 /*MF_SEPARATOR*/, 0);
  oSys.Call("User32::AppendMenuW", hMenu, aPDF.length ? MF_STRING : MF_GRAYED, IDREFRESHB, aDlg[IDREFRESHB].T + "\t" + aDlg[IDREFRESHB].K);

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

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

  if (nCmd)
    PostMessage(hDlg, 273 /*WM_COMMAND*/, nCmd, 0);
}

function Add()
{
  var oRect = {};
  var sDir  = "";
  var aFile;
  var i;

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

  if (aPDF.length)
    sDir = oFSO.GetParentFolderName(aPDF[nPDF].F);

  aFile = GetOpenSaveFileName(0, sTxtSelSourcePDFs, "pdf", sDir, 1, null, oRect.Y + Scale.X(20));

  if (aFile.length)
  {
    nOutPages = -1;
    nPDF      = aPDF.length;

    for (i = 0; i < aFile.length; ++i)
    {
      aPDF.push({F: aFile[i], R: "", P: "", TP: 0, OP: 0, OR: 0});
      InsertItemLV(aDlg[IDPDFLV].HWND, aPDF.length - 1);
    }

    SetCurSelLV(aDlg[IDPDFLV].HWND, nPDF);
    Refresh();
  }
}

function Duplicate()
{
  if (nOutPages >= 0)
  {
    nTotalPages += aPDF[nPDF].TP;
    nOutPages   += aPDF[nPDF].OP;
    nOutRanges  += aPDF[nPDF].OR;
  }

  aPDF.splice(nPDF + 1, 0, {F: aPDF[nPDF].F, R: aPDF[nPDF].R, P: aPDF[nPDF].P, TP: aPDF[nPDF].TP, OP: aPDF[nPDF].OP, OR: aPDF[nPDF].OR});
  InsertItemLV(aDlg[IDPDFLV].HWND, ++nPDF);
  SetCurSelLV(aDlg[IDPDFLV].HWND, nPDF);
}

function Remove()
{
  if (nOutPages >= 0)
  {
    nTotalPages -= aPDF[nPDF].TP;
    nOutPages   -= aPDF[nPDF].OP;
    nOutRanges  -= aPDF[nPDF].OR;
  }

  aPDF.splice(nPDF, 1);
  DeleteItemLV(aDlg[IDPDFLV].HWND, nPDF);

  if (nPDF >= aPDF.length)
    --nPDF;

  SetCurSelLV(aDlg[IDPDFLV].HWND, nPDF);

  if (! aPDF.length)
  {
    nTotalPages = 0;
    nOutPages   = -1;
    nOutRanges  = 0;
    SetDefButton(IDADDB, IDADDB);
  }
}

function Clear()
{
  nTotalPages = 0;
  nOutPages   = -1;
  nOutRanges  = 0;
  nPDF        = -1;
  aPDF.length = 0;

  SendMessage(aDlg[IDPDFLV].HWND, 4105 /*LVM_DELETEALLITEMS*/, 0, 0);
  SetCurSelLV(aDlg[IDPDFLV].HWND, nPDF);
  SetDefButton(IDADDB, IDADDB);
}

function MoveUp()
{
  var hFocus = oSys.Call("User32::GetFocus");

  aPDF.splice(nPDF - 1, 0, {F: aPDF[nPDF].F, R: aPDF[nPDF].R, P: aPDF[nPDF].P, TP: aPDF[nPDF].TP, OP: aPDF[nPDF].OP, OR: aPDF[nPDF].OR});
  aPDF.splice(nPDF + 1, 1);
  DeleteItemLV(aDlg[IDPDFLV].HWND, nPDF--);
  InsertItemLV(aDlg[IDPDFLV].HWND, nPDF);
  SetCurSelLV(aDlg[IDPDFLV].HWND, nPDF);

  if ((nPDF == 0) && (hFocus == aDlg[IDUPB].HWND))
    SetDefButton(IDDOWNB, IDDOWNB);
}

function MoveDown()
{
  var hFocus = oSys.Call("User32::GetFocus");

  aPDF.splice(nPDF + 2, 0, {F: aPDF[nPDF].F, R: aPDF[nPDF].R, P: aPDF[nPDF].P, TP: aPDF[nPDF].TP, OP: aPDF[nPDF].OP, OR: aPDF[nPDF].OR});
  aPDF.splice(nPDF, 1);
  DeleteItemLV(aDlg[IDPDFLV].HWND, nPDF++);
  InsertItemLV(aDlg[IDPDFLV].HWND, nPDF);
  SetCurSelLV(aDlg[IDPDFLV].HWND, nPDF);

  if ((nPDF == aPDF.length - 1) && (hFocus == aDlg[IDDOWNB].HWND))
    SetDefButton(IDUPB, IDUPB);
}

function Ranges()
{
  var aEven = [["",     sTxtAll],
               ["even", sTxtEven],
               ["odd",  sTxtOdd]];
  var aRotation = [["",      sTxtNone],
                   ["north", sTxtNorth + " (0°)"],
                   ["east",  sTxtEast  + " (90°)"],
                   ["south", sTxtSouth + " (180°)"],
                   ["west",  sTxtWest  + " (270°)"],
                   ["left",  sTxtLeft  + " (-90°)"],
                   ["right", sTxtRight + " (+90°)"],
                   ["down",  sTxtDown  + " (+180°)"]];
  var aRange = aPDF[nPDF].R.split(/ /);
  var nRange = 0;
  var oRect  = {};
  var nWAY2;
  var bCloseCB;

  var aWnd       = [];
  var IDRPDFS    = 2000;
  var IDRRANGELV = 2001;
  var IDRPAGESG  = 2002;
  var IDRFROMS   = 2003;
  var IDRFROME   = 2004;
  var IDRFROMB   = 2005;
  var IDRTOS     = 2006;
  var IDRTOE     = 2007;
  var IDRTOB     = 2008;
  var IDRLASTS   = 2009;
  var IDREVENS   = 2010;
  var IDREVENCB  = 2011;
  var IDRROTS    = 2012;
  var IDRROTCB   = 2013;
  var IDRNEWB    = 2014;
  var IDRREMOVEB = 2015;
  var IDRCLEARB  = 2016;
  var IDRUPB     = 2017;
  var IDRDOWNB   = 2018;
  var IDROKB     = 2019;
  var IDRCANCELB = 2020;

  aWnd[IDRPDFS]    = {X:  10, Y:  10, W: 380, H:  13, T: oFSO.GetFileName(aPDF[nPDF].F),   C: "STATIC",        S: 0x50000080 /*WS_CHILD|WS_VISIBLE|SS_NOPREFIX*/};
  aWnd[IDRRANGELV] = {X:  10, Y:  30, W: 160, H: 193,                                      C: "SysListView32", S: 0x5081800D /*WS_CHILD|WS_VISIBLE|WS_BORDER|WS_TABSTOP|LVS_NOSORTHEADER|LVS_SHOWSELALWAYS|LVS_SINGLESEL|LVS_REPORT*/};
  aWnd[IDRPAGESG]  = {X: 180, Y:  35, W: 170, H: 144, T: sTxtPages,                        C: "BUTTON",        S: 0x50000307 /*WS_CHILD|WS_VISIBLE|BS_CENTER|BS_GROUPBOX*/};
  aWnd[IDRFROMS]   = {X: 190, Y:  50, W:  70, H:  13, T: sTxtFrom,                         C: "STATIC",        S: 0x50000000 /*WS_CHILD|WS_VISIBLE*/};
  aWnd[IDRFROME]   = {X: 190, Y:  65, W:  70, H:  21,                                      C: "EDIT",          S: 0x50010000 /*WS_CHILD|WS_VISIBLE|WS_TABSTOP*/, ES: 0x00000200 /*WS_EX_CLIENTEDGE*/};
  aWnd[IDRFROMB]   = {X: 190, Y:  90, W:  70, H:  16, T: sTxtFromEnd,                      C: "BUTTON",        S: 0x50010003 /*WS_CHILD|WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX*/};
  aWnd[IDRTOS]     = {X: 270, Y:  50, W:  70, H:  13, T: sTxtTo,                           C: "STATIC",        S: 0x50000000 /*WS_CHILD|WS_VISIBLE*/};
  aWnd[IDRTOE]     = {X: 270, Y:  65, W:  70, H:  21,                                      C: "EDIT",          S: 0x50010000 /*WS_CHILD|WS_VISIBLE|WS_TABSTOP*/, ES: 0x00000200 /*WS_EX_CLIENTEDGE*/};
  aWnd[IDRTOB]     = {X: 270, Y:  90, W:  70, H:  16, T: sTxtFromEnd,                      C: "BUTTON",        S: 0x50010003 /*WS_CHILD|WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX*/};
  aWnd[IDRLASTS]   = {X: 190, Y: 110, W: 150, H:  13, T: "e = " + sTxtNumLastPage,         C: "STATIC",        S: 0x50000001 /*WS_CHILD|WS_VISIBLE|SS_CENTER*/};
  aWnd[IDREVENS]   = {X: 210, Y: 130, W: 110, H:  13, T: sTxtEven + "/" + sTxtOdd + ":",   C: "STATIC",        S: 0x50000000 /*WS_CHILD|WS_VISIBLE*/};
  aWnd[IDREVENCB]  = {X: 210, Y: 145, W: 110, H: 100,                                      C: "COMBOBOX",      S: 0x50010003 /*WS_CHILD|WS_VISIBLE|WS_TABSTOP|CBS_DROPDOWNLIST*/};
  aWnd[IDRROTS]    = {X: 210, Y: 187, W: 110, H:  13, T: sTxtRotation + ":",               C: "STATIC",        S: 0x50000000 /*WS_CHILD|WS_VISIBLE*/};
  aWnd[IDRROTCB]   = {X: 210, Y: 202, W: 110, H: 300,                                      C: "COMBOBOX",      S: 0x50010003 /*WS_CHILD|WS_VISIBLE|WS_TABSTOP|CBS_DROPDOWNLIST*/};
  aWnd[IDRNEWB]    = {X: 360, Y:  30, W:  70, H:  23, T: sTxtNew,                          C: "BUTTON",        S: 0x50000000 /*WS_CHILD|WS_VISIBLE*/, K: "Insert"};
  aWnd[IDRREMOVEB] = {X: 360, Y:  55, W:  70, H:  23, T: sTxtRemove,                       C: "BUTTON",        S: 0x50000000 /*WS_CHILD|WS_VISIBLE*/, K: "Alt+Del"};
  aWnd[IDRCLEARB]  = {X: 360, Y:  80, W:  70, H:  23, T: sTxtClear,                        C: "BUTTON",        S: 0x50000000 /*WS_CHILD|WS_VISIBLE*/, K: "Shift+Alt+Del"};
  aWnd[IDRUPB]     = {X: 360, Y: 105, W:  70, H:  23, T: sTxtMoveUp,                       C: "BUTTON",        S: 0x50000000 /*WS_CHILD|WS_VISIBLE*/, K: "Alt+Up"};
  aWnd[IDRDOWNB]   = {X: 360, Y: 130, W:  70, H:  23, T: sTxtMoveDown,                     C: "BUTTON",        S: 0x50000000 /*WS_CHILD|WS_VISIBLE*/, K: "Alt+Down"};
  aWnd[IDROKB]     = {X: 360, Y: 175, W:  70, H:  23, T: sTxtOK,                           C: "BUTTON",        S: 0x50000001 /*WS_CHILD|WS_VISIBLE|BS_DEFPUSHBUTTON*/};
  aWnd[IDRCANCELB] = {X: 360, Y: 200, W:  70, H:  23, T: sTxtCancel,                       C: "BUTTON",        S: 0x50000000 /*WS_CHILD|WS_VISIBLE*/};

  GetWindowPos(0, oRect);
  nWAY2 = oRect.Y + oRect.H;
  GetWindowPos(aDlg[IDPDFLV].HWND, oRect);
  aWnd.W = Scale.X(440) + oSys.Call("User32::GetSystemMetrics", 7 /*SM_CXFIXEDFRAME*/) * 2;
  aWnd.H = Scale.Y(233) + oSys.Call("User32::GetSystemMetrics", 8 /*SM_CYFIXEDFRAME*/) * 2 + oSys.Call("User32::GetSystemMetrics", 4 /*SM_CYCAPTION*/);
  aWnd.X = oRect.X + (oRect.W - aWnd.W) / 2;
  GetItemRectLV(aDlg[IDPDFLV].HWND, nPDF, oRect);
  aWnd.Y = (oRect.Y2 + aWnd.H < nWAY2) ? oRect.Y2 + 2 : oRect.Y1 - aWnd.H - 2;
  aWnd.T = sTxtPagesToCopy + "/" + sTxtRotation;

  oSys.Call("User32::CreateWindowExW",
    0,              //dwExStyle
    sClass,         //lpClassName
    aWnd.T,         //lpWindowName
    0x90C80000,     //dwStyle=WS_POPUP|WS_VISIBLE|WS_CAPTION|WS_SYSMENU
    aWnd.X,         //x
    aWnd.Y,         //y
    aWnd.W,         //nWidth
    aWnd.H,         //nHeight
    hDlg,           //hWndParent
    0,              //hMenu
    hInstDLL,       //hInstance
    RangeCallback); //Script function callback. To use it class must be registered by WindowRegisterClass.

  nOutPages  -= aPDF[nPDF].OP;
  nOutRanges -= aPDF[nPDF].OR;

  oSys.Call("User32::EnableWindow", hDlg, 0);
  AkelPad.WindowGetMessage();

  nOutPages  += aPDF[nPDF].OP;
  nOutRanges += aPDF[nPDF].OR;

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

    if (uMsg == 1 /*WM_CREATE*/)
    {
      aWnd.HWND = hWnd;

      if (! hMainWnd)
        SendMessage(hWnd, 128 /*WM_SETICON*/, 0 /*ICON_SMALL*/, hIconSmall);

      for (i = IDRPDFS; i < aWnd.length; ++i)
      {
        aWnd[i].HWND = oSys.Call("User32::CreateWindowExW",
          aWnd[i].ES,         //dwExStyle
          aWnd[i].C,          //lpClassName
          aWnd[i].T,          //lpWindowName
          aWnd[i].S,          //dwStyle
          Scale.X(aWnd[i].X), //x
          Scale.Y(aWnd[i].Y), //y
          Scale.X(aWnd[i].W), //nWidth
          Scale.Y(aWnd[i].H), //nHeight
          hWnd,               //hWndParent
          i,                  //ID
          hInstDLL,           //hInstance
          0);                 //lpParam
        SendMessage(aWnd[i].HWND, 48 /*WM_SETFONT*/, hGuiFont, 1);
      }

      SendMessage(aWnd[IDRFROME].HWND, 197 /*EM_SETLIMITTEXT*/, 6, 0);
      SendMessage(aWnd[IDRTOE].HWND,   197 /*EM_SETLIMITTEXT*/, 6, 0);

      for (i = 0; i < aEven.length; ++i)
        SendMessage(aWnd[IDREVENCB].HWND, 323 /*CB_ADDSTRING*/, i, aEven[i][1]);

      for (i = 0; i < aRotation.length; ++i)
        SendMessage(aWnd[IDRROTCB].HWND, 323 /*CB_ADDSTRING*/, i, aRotation[i][1]);

      FillRangeLV();

      aWnd.Focus = aWnd[IDRRANGELV].HWND;
    }

    else if (uMsg == 0x8001 /*WM_APP+1*/)
      oSys.Call("User32::SetFocus", lParam);

    else if (uMsg == 6 /*WM_ACTIVATE*/)
    {
      if (wParam == 0 /*WA_INACTIVE*/)
        aWnd.Focus = oSys.Call("User32::GetFocus");
    }

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

    else if (uMsg == 256 /*WM_KEYDOWN*/)
    {
      nID = oSys.Call("User32::GetDlgCtrlID", oSys.Call("User32::GetFocus"))

      if (wParam == 0x0D /*VK_RETURN*/)
      {
        if ((nID < IDRNEWB) && bCloseCB && ! Ctrl() && ! Shift())
          PostMessage(hWnd, 273 /*WM_COMMAND*/, IDROKB, 0);
      }
      else if ((nID == IDRRANGELV) && ! Ctrl() && ! Shift())
      {
        if (wParam == 0x2D /*VK_INSERT*/)
          PostMessage(hWnd, 273 /*WM_COMMAND*/, IDRNEWB, 0);
        else if (wParam == 0x5D /*VK_APPS*/)
          MenuRangeLV();
      }
    }

    else if (uMsg == 260 /*WM_SYSKEYDOWN*/)
    {
      if (oSys.Call("User32::GetFocus") == aWnd[IDRRANGELV].HWND)
      {
        if (wParam == 0x2E /*VK_DELETE*/)
          PostMessage(hWnd, 273 /*WM_COMMAND*/, Shift() ? IDRCLEARB : IDRREMOVEB, 0);
        else if (wParam == 0x26 /*VK_UP*/)
        {
          if (! Shift())
            PostMessage(hWnd, 273 /*WM_COMMAND*/, IDRUPB, 0);
        }
        else if (wParam == 0x28 /*VK_DOWN*/)
        {
          if (! Shift())
            PostMessage(hWnd, 273 /*WM_COMMAND*/, IDRDOWNB, 0);
        }
      }
    }

    else if (uMsg == 78 /*WM_NOTIFY*/)
    {
      if (wParam == IDRRANGELV)
      {
        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*/)
            {
              nRange = GetCurSelLV(aWnd[IDRRANGELV].HWND);
              SetPages();
              EnableControlsRange();
            }
            break;
          case -2 : //NM_CLICK
          case -3 : //NM_DBLCLK
            if (AkelPad.MemRead(_PtrAdd(lParam, _X64 ? 24 : 12) /*NMITEMACTIVATE.iItem*/, 3 /*DT_DWORD*/) == -1)
              SetCurSelLV(aWnd[IDRRANGELV].HWND, GetCurFocLV(aWnd[IDRRANGELV].HWND));
            break;
          case -5 : //NM_RCLICK
          case -6 : //NM_RDBLCLK
            if (AkelPad.MemRead(_PtrAdd(lParam, _X64 ? 24 : 12) /*NMITEMACTIVATE.iItem*/, 3 /*DT_DWORD*/) == -1)
              SetCurSelLV(aWnd[IDRRANGELV].HWND, GetCurFocLV(aWnd[IDRRANGELV].HWND));
            MenuRangeLV(_PtrAdd(lParam, _X64 ? 44 : 32) /*NMITEMACTIVATE.ptAction*/);
            break;
          }
      }
    }

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

      if ((nID == IDRFROME) || (nID == IDRTOE))
      {
        if (nCode == 0x0300 /*EN_CHANGE*/)
          SetRange();
          EnableControlsRange();
      }

      else if ((nID == IDRFROMB) || (nID == IDRTOB))
        SetRange();

      else if ((nID == IDREVENCB) || (nID == IDRROTCB))
      {
        if ((nCode == 1 /*CBN_SELCHANGE*/) || (nCode == 8 /*CBN_CLOSEUP*/))
        {
          SetRange();
          EnableControlsRange();

          if (nCode == 8 /*CBN_CLOSEUP*/)
            bCloseCB = 0;
        }
      }

      else if ((nID >= IDRNEWB) && (nID <= IDRDOWNB))
      {
        if (oSys.Call("User32::IsWindowEnabled", aWnd[nID].HWND))
        {
          if (nID == IDRNEWB)
            NewRange();
          else if (nID == IDRREMOVEB)
            RemoveRange();
          else if (nID == IDRCLEARB)
            ClearRange();
          else if (nID == IDRUPB)
            MoveUpRange();
          else
            MoveDownRange();

          for (i = IDRNEWB; i <= IDRDOWNB; ++i)
            SendMessage(aWnd[i].HWND, 244 /*BM_SETSTYLE*/, 0 /*BS_PUSHBUTTON*/, 1);
          SendMessage(aWnd[IDROKB].HWND, 244 /*BM_SETSTYLE*/, 1 /*BS_DEFPUSHBUTTON*/, 1);
          EnableControlsRange();
          PostMessage(hWnd, 0x8001 /*WM_APP+1*/, 0, aWnd[IDRRANGELV].HWND);
        }
      }

      else if (nID == IDROKB)
      {
        aPDF[nPDF].R = aRange.join(" ");
        CheckRanges(nPDF);
        PostMessage(hWnd, 16 /*WM_CLOSE*/, 0, 0);
      }

      else if ((nID == IDRCANCELB) || (nID == 2 /*IDCANCEL*/))
        PostMessage(hWnd, 16 /*WM_CLOSE*/, 0, 0);
    }

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

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

    return 0;
  }

  function EnableControlsRange()
  {
    var nFrom      = SendMessage(aWnd[IDRFROME].HWND, 14 /*WM_GETTEXTLENGTH*/, 0, 0);
    var nTo        = SendMessage(aWnd[IDRTOE].HWND,   14 /*WM_GETTEXTLENGTH*/, 0, 0);
    var nEven      = SendMessage(aWnd[IDREVENCB].HWND, 327 /*CB_GETCURSEL*/, 0, 0);
    var nRot       = SendMessage(aWnd[IDRROTCB].HWND,  327 /*CB_GETCURSEL*/, 0, 0);
    var lpLVCOLUMN = AkelPad.MemAlloc(_X64 ? 56 : 44 /*sizeof(LVCOLUMN)*/);
    var lpText     = AkelPad.MemAlloc(64);

    oSys.Call("User32::EnableWindow", aWnd[IDRFROMB].HWND,   (nFrom || (aRange.length > 1)));
    oSys.Call("User32::EnableWindow", aWnd[IDRTOS].HWND,     (nFrom || (aRange.length > 1)));
    oSys.Call("User32::EnableWindow", aWnd[IDRTOE].HWND,     (nFrom || (aRange.length > 1)));
    oSys.Call("User32::EnableWindow", aWnd[IDRTOB].HWND,     (nFrom || (aRange.length > 1)) && nTo);
    oSys.Call("User32::EnableWindow", aWnd[IDRNEWB].HWND,    nFrom);
    oSys.Call("User32::EnableWindow", aWnd[IDRREMOVEB].HWND, aRange.length > 1);
    oSys.Call("User32::EnableWindow", aWnd[IDRCLEARB].HWND,  (nFrom || (aRange.length > 1)) || (nEven > 0) || (nRot > 0));
    oSys.Call("User32::EnableWindow", aWnd[IDRUPB].HWND,     nRange > 0);
    oSys.Call("User32::EnableWindow", aWnd[IDRDOWNB].HWND,   nRange < aRange.length - 1);

    AkelPad.MemCopy(lpText, sTxtRanges + (aRange.length ? " (" + (nRange + 1) + "/" + aRange.length + ")" : ""), 1 /*DT_UNICODE*/);
    AkelPad.MemCopy(lpLVCOLUMN, 4 /*LVCF_TEXT*/, 3 /*DT_DWORD*/); //mask
    AkelPad.MemCopy(_PtrAdd(lpLVCOLUMN, _X64 ? 16 : 12), lpText, 2 /*DT_QWORD*/);
    SendMessage(aWnd[IDRRANGELV].HWND, 4192 /*LVM_SETCOLUMNW*/, 0, lpLVCOLUMN);
    AkelPad.MemFree(lpLVCOLUMN);
    AkelPad.MemFree(lpText);
  }

  function SetPages()
  {
    var aP = aRange[nRange].split(/-/);
    var aMatch;
    var i;

    if (! aP[1]) aP[1] = "";

    i = 0;
    if (aMatch = aRange[nRange].match(/north|east|south|west|left|right|down/))
    {
      for (; i < aRotation.length; ++i)
      {
        if (aRotation[i][0] == aMatch[0])
          break;
      }
    }
    SendMessage(aWnd[IDRROTCB].HWND, 334 /*CB_SETCURSEL*/, i, 0);

    i = 0;
    if (aMatch = aRange[nRange].match(/even|odd/))
    {
      for (; i < aEven.length; ++i)
      {
        if (aEven[i][0] == aMatch[0])
          break;
      }
    }
    SendMessage(aWnd[IDREVENCB].HWND, 334 /*CB_SETCURSEL*/, i, 0);

    SendMessage(aWnd[IDRFROMB].HWND, 241 /*BM_SETCHECK*/, /^r/.test(aP[0]), 0);
    SendMessage(aWnd[IDRTOB].HWND,   241 /*BM_SETCHECK*/, /^r/.test(aP[1]), 0);

    if (/end|\d+/.test(aP[0]))
      aP[0] = aP[0].replace(/^r?(e(?=nd)|\d+).*/, "$1");
    else
      aP[0] = "";

    SetWindowText(aWnd[IDRFROME].HWND, aP[0]);
    SetWindowText(aWnd[IDRTOE].HWND,   aP[1].replace(/^r?(e(?=nd)|\d+).*/, "$1"));
  }

  function SetRange()
  {
    var sFrom = GetWindowText(aWnd[IDRFROME].HWND);
    var sTo   = GetWindowText(aWnd[IDRTOE].HWND);

    if (sFrom || (aRange.length > 1))
    {
      if (sFrom.toLowerCase() == "e")
        sFrom = "end";
      else if (/^0*[1-9]\d*$/.test(sFrom))
        sFrom = parseInt(sFrom, 10).toString();
      else
        sFrom = "1";

      if (SendMessage(aWnd[IDRFROMB].HWND, 240 /*BM_GETCHECK*/, 0, 0))
        sFrom = "r" + sFrom;
    }
    else
    {
      sFrom = aEven[SendMessage(aWnd[IDREVENCB].HWND, 327 /*CB_GETCURSEL*/, 0, 0)][0];
      sTo   = "";
    }

    if (sTo)
    {
      if (sTo.toLowerCase() == "e")
        sTo = "end";
      else if (/^0*[1-9]\d*$/.test(sTo))
        sTo = parseInt(sTo, 10).toString();
      else
        sTo = aPDF[nPDF].TP;

      if (SendMessage(aWnd[IDRTOB].HWND, 240 /*BM_GETCHECK*/, 0, 0))
        sTo = "r" + sTo;

      sTo = "-" + sTo + aEven[SendMessage(aWnd[IDREVENCB].HWND, 327 /*CB_GETCURSEL*/, 0, 0)][0];
    }

    aRange[nRange] = sFrom + sTo + aRotation[SendMessage(aWnd[IDRROTCB].HWND, 327 /*CB_GETCURSEL*/, 0, 0)][0];
    SetItemTextLV(aWnd[IDRRANGELV].HWND, nRange, 0, aRange[nRange] ? aRange[nRange] : sTxtAll);
  }

  function FillRangeLV()
  {
    var lpLVCOLUMN = AkelPad.MemAlloc(_X64 ? 56 : 44 /*sizeof(LVCOLUMN)*/);
    var i;

    AkelPad.MemCopy(lpLVCOLUMN, 4 /*LVCF_TEXT*/, 3 /*DT_DWORD*/); //mask
    AkelPad.MemCopy(_PtrAdd(lpLVCOLUMN, _X64 ? 16 : 12), AkelPad.MemStrPtr(sTxtRanges), 2 /*DT_QWORD*/); //pszText
    SendMessage(aWnd[IDRRANGELV].HWND, 4193 /*LVM_INSERTCOLUMNW*/, 0, lpLVCOLUMN);
    AkelPad.MemFree(lpLVCOLUMN);

    for (i = 0; i < aRange.length; ++i)
      InsertItemLV(aWnd[IDRRANGELV].HWND, i, aRange[i]);

    SendMessage(aWnd[IDRRANGELV].HWND, 4150 /*LVM_SETEXTENDEDLISTVIEWSTYLE*/, 0, 0x0421 /*LVS_EX_INFOTIP|LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES*/);
    SendMessage(aWnd[IDRRANGELV].HWND, 4126 /*LVM_SETCOLUMNWIDTH*/, 0, -2 /*LVSCW_AUTOSIZE_USEHEADER*/);
    SetCurSelLV(aWnd[IDRRANGELV].HWND, nRange);
  }

  function MenuRangeLV(lpPoint)
  {
    var MF_STRING = 0x0000;
    var MF_GRAYED = 0x0001;
    var hMenu     = oSys.Call("User32::CreatePopupMenu");
    var oRect;
    var nX, nY;
    var nCmd;
    var i;

    //menu from mouse r-click
    if (lpPoint)
    {
      oSys.Call("User32::ClientToScreen", aWnd[IDRRANGELV].HWND, lpPoint);
      nX = AkelPad.MemRead(_PtrAdd(lpPoint, 0), 3 /*DT_DWORD*/);
      nY = AkelPad.MemRead(_PtrAdd(lpPoint, 4), 3 /*DT_DWORD*/);
    }
    //menu from keyboard
    else
    {
      oRect = {};
      GetItemRectLV(aWnd[IDRRANGELV].HWND, nRange, oRect);
      nX = oRect.X1;
      nY = oRect.Y2;
    }

    for (i = IDRNEWB; i <= IDRDOWNB; ++i)
      oSys.Call("User32::AppendMenuW", hMenu, oSys.Call("User32::IsWindowEnabled", aWnd[i].HWND) ? MF_STRING : MF_GRAYED, i, aWnd[i].T + "\t" + aWnd[i].K);

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

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

    if (nCmd)
      PostMessage(aWnd.HWND, 273 /*WM_COMMAND*/, nCmd, 0);
  }

  function NewRange()
  {
    aRange.splice(nRange, 0, aRange[nRange]);
    InsertItemLV(aWnd[IDRRANGELV].HWND, nRange, aRange[nRange]);
    SetCurSelLV(aWnd[IDRRANGELV].HWND, ++nRange);
  }

  function RemoveRange()
  {
    aRange.splice(nRange, 1);
    DeleteItemLV(aWnd[IDRRANGELV].HWND, nRange);

    if (nRange >= aRange.length)
      --nRange;

    SetCurSelLV(aWnd[IDRRANGELV].HWND, nRange);
  }

  function ClearRange()
  {
    aRange.length = 1;
    SendMessage(aWnd[IDRRANGELV].HWND, 4105 /*LVM_DELETEALLITEMS*/, 0, 0);

    aRange[0] = "";
    InsertItemLV(aWnd[IDRRANGELV].HWND, 0, aRange[0]);
    SetCurSelLV(aWnd[IDRRANGELV].HWND, 0);
  }

  function MoveUpRange()
  {
    aRange.splice(nRange - 1, 0, aRange[nRange]);
    aRange.splice(nRange + 1, 1);
    DeleteItemLV(aWnd[IDRRANGELV].HWND, nRange--);
    InsertItemLV(aWnd[IDRRANGELV].HWND, nRange);
    SetCurSelLV(aWnd[IDRRANGELV].HWND, nRange);
  }

  function MoveDownRange()
  {
    aRange.splice(nRange + 2, 0, aRange[nRange]);
    aRange.splice(nRange, 1);
    DeleteItemLV(aWnd[IDRRANGELV].HWND, nRange++);
    InsertItemLV(aWnd[IDRRANGELV].HWND, nRange);
    SetCurSelLV(aWnd[IDRRANGELV].HWND, nRange);
  }
}

function Open()
{
  if (oFSO.FileExists(aPDF[nPDF].F))
  {
    if (IsReaderExists())
      AkelPad.Exec('"' + sPDFReader + '" "' + aPDF[nPDF].F + '"');
  }
  else
    MsgBox(aPDF[nPDF].F + "\n\n" + sTxtNoFile);
}

function Refresh(bAll)
{
  var nPDFCur = nPDF;
  var oFile   = {};
  var sOutput;
  var aMatch;
  var sPass;
  var bDelete;
  var i;

  if (! IsPDFtkExists())
    return;

  bRefreshing = 1;
  EnableControlsDlg();

  nTotalPages = 0;
  nOutPages   = 0;
  nOutRanges  = 0;

  for (i = 0; i < aPDF.length; ++i)
  {
    if ((! bAll) && aPDF[i].TP)
    {
      nTotalPages += aPDF[i].TP;
      nOutPages   += aPDF[i].OP;
      nOutRanges  += aPDF[i].OR;
    }
    else
    {
      SetCurSelLV(aDlg[IDPDFLV].HWND, i);
      SetItemTextLV(aDlg[IDPDFLV].HWND, i, 1, sTxtReading);

      if (oFile[aPDF[i].F.toUpperCase()])
      {
        aPDF[i].P  = oFile[aPDF[i].F.toUpperCase()].P;
        aPDF[i].TP = oFile[aPDF[i].F.toUpperCase()].TP;
        SetItemTextLV(aDlg[IDPDFLV].HWND, i, 1, aPDF[i].TP);
        CheckRanges(i);
        nTotalPages += aPDF[i].TP;
        nOutPages   += aPDF[i].OP;
        nOutRanges  += aPDF[i].OR;
      }
      else
      {
        sPass = aPDF[i].P;

        for (;;)
        {
          sOutput = RunCmd('"' + sPDFtkExe + '" "' + aPDF[i].F + '" input_pw "' + sPass + '" dump_data_annots');
          aMatch  = sOutput.match(/NumberOfPages: (\d+)/);

          if (aMatch && (aMatch.length == 2))
          {
            aPDF[i].P  = sPass;
            aPDF[i].TP = parseInt(aMatch[1]);
            SetItemTextLV(aDlg[IDPDFLV].HWND, i, 1, aPDF[i].TP);
            CheckRanges(i);
            nTotalPages += aPDF[i].TP;
            nOutPages   += aPDF[i].OP;
            nOutRanges  += aPDF[i].OR;
            break;
          }
          else
          {
            if ((nExitCode == 1) && /OWNER PASSWORD REQUIRED/.test(sOutput))
            {
              if (oFile[aPDF[i].F.toUpperCase()])
                sPass = oFile[aPDF[i].F.toUpperCase()].P;
              else
              {
                sPass = EnterPassword(oFSO.GetFileName(aPDF[i].F), sPass);

                if (typeof sPass != "string")
                {
                  bDelete = 1;
                  break;
                }
              }
            }
            else
            {
              bDelete = 1;
              break;
            }
          }
        }

        if (bDelete)
        {
          if (i <= nPDFCur)
            --nPDFCur;

          aPDF.splice(i, 1);
          DeleteItemLV(aDlg[IDPDFLV].HWND, i);
        }
      }
    }

    if (bDelete)
    {
      bDelete = 0;
      --i;
    }
    else
      oFile[aPDF[i].F.toUpperCase()] = {P: aPDF[i].P, TP: aPDF[i].TP};
  }

  bRefreshing = 0;
  oSys.Call("User32::UpdateWindow", aDlg[IDPDFLV].HWND);
  SetCurSelLV(aDlg[IDPDFLV].HWND, nPDFCur);
  EnableControlsDlg();

  if (aPDF.length)
  {
    if (! bCreating)
    {
      SetDefButton();
      PostMessage(hDlg, 0x8001 /*WM_APP+1*/, 0, aDlg[IDPDFLV].HWND);
    }
  }
  else
    SetDefButton(IDADDB, IDADDB);
}

function CheckRanges(nPDF)
{
  var aR;
  var nFrom;
  var nTo;
  var nTmp;
  var aMatch;
  var i;

  aPDF[nPDF].OP = 0;
  aR = aPDF[nPDF].R.toLowerCase().replace(/^ +| +$/g, "").split(/ +/);

  for (i = 0; i < aR.length; ++i)
  {
    aR[i] = aR[i].replace(/^-+|-+$/g, "").split(/-+/, 2);

    if (aR[i][0])
    {
      if (/^r?(end|\d+)(north|east|south|west|left|right|down)?$/.test(aR[i][0]))
      {
        aMatch = aR[i][0].match(/end|\d+/);

        if (aMatch[0] == "end")
          nFrom = aPDF[nPDF].TP;
        else
        {
          nFrom = parseInt(aMatch[0], 10);

          if (nFrom == 0)
            nFrom = 1;
          else if (nFrom > aPDF[nPDF].TP)
            nFrom = aPDF[nPDF].TP;

          aR[i][0] = aR[i][0].replace(/\d+/, nFrom.toString());
        }

        if (/^r/.test(aR[i][0]))
          nFrom = aPDF[nPDF].TP - nFrom + 1;

        if (/north|east|south|west|left|right|down/.test(aR[i][0]))
          aR[i][1] = "";

        nTo = nFrom;
      }
      else if (/^(even|odd)?(north|east|south|west|left|right|down)?$/.test(aR[i][0]))
      {
        aR[i][1] = "";
        nFrom    = 1;
        nTo      = aPDF[nPDF].TP;

        if (nFrom == nTo)
          aR[i][0] = aR[i][0].replace(/even|odd/, "");
        else
        {
          if (/even/.test(aR[i][0]))
          {
            if ((nFrom % 2) == 1)
              ++nFrom;
            if ((nTo % 2) == 1)
              --nTo;
            nTo = nFrom + (nTo - nFrom) / 2;
          }
          else if (/odd/.test(aR[i][0]))
          {
            if ((nFrom % 2) == 0)
              ++nFrom;
            if ((nTo % 2) == 0)
              --nTo;
            nTo = nFrom + (nTo - nFrom) / 2;
          }
        }
      }
      else
        aR[i][0] = "";
    }

    if (! aR[i][0])
    {
      aR[i][1] = "";
      nFrom    = 1;
      nTo      = aPDF[nPDF].TP;
    }

    if (aR[i][1])
    {
      if (/^r?(end|\d+)(even|odd)?(north|east|south|west|left|right|down)?$/.test(aR[i][1]))
      {
        aMatch = aR[i][1].match(/end|\d+/);

        if (aMatch[0] == "end")
          nTo = aPDF[nPDF].TP;
        else
        {
          nTo = parseInt(aMatch[0], 10);

          if (nTo == 0)
            nTo = 1;
          else if (nTo > aPDF[nPDF].TP)
            nTo = aPDF[nPDF].TP;

          aR[i][1] = aR[i][1].replace(/\d+/, nTo.toString());
        }

        if (/^r/.test(aR[i][1]))
          nTo = aPDF[nPDF].TP - nTo + 1;

        if (nFrom == nTo)
          aR[i][1] = aR[i][1].replace(/even|odd/, "");
        else
        {
          if (nFrom > nTo)
          {
            nTmp  = nFrom;
            nFrom = nTo;
            nTo   = nTmp;
          }

          if (/even/.test(aR[i][1]))
          {
            if ((nFrom % 2) == 1)
              ++nFrom;
            if ((nTo % 2) == 1)
              --nTo;
            nTo = nFrom + (nTo - nFrom) / 2;
          }
          else if (/odd/.test(aR[i][1]))
          {
            if ((nFrom % 2) == 0)
              ++nFrom;
            if ((nTo % 2) == 0)
              --nTo;
            nTo = nFrom + (nTo - nFrom) / 2;
          }
        }
      }
      else
        aR[i][1] = "";
    }

    aR[i] = aR[i][0] + (aR[i][1] ? ("-" + aR[i][1]) : "");
    aPDF[nPDF].OP += nTo - nFrom + 1;
  }

  aPDF[nPDF].R  = aR.join(" ");
  aPDF[nPDF].OR = aR.length;
  SetItemTextLV(aDlg[IDPDFLV].HWND, nPDF, 2, aPDF[nPDF].R ? aPDF[nPDF].R : sTxtAll);
  SetItemTextLV(aDlg[IDPDFLV].HWND, nPDF, 3, aPDF[nPDF].OP);
}

function Create()
{
  if (IsPDFtkExists())
  {
    if (! oFSO.FolderExists(sLastDir))
      sLastDir = sScriptDir;

    if (nTab == 0)
      Collate();
    else if (nTab == 1)
      Shuffle();
    else if (nTab == 2)
      Split();
    else if (nTab == 3)
      Watermark();
    else if (nTab == 4)
      Bookmarks();
    else if (nTab == 5)
      PDFInfo();
  }
}

function Collate()
{
  var sOutFile;
  var sTmpFile;
  var sTmpDir;
  var sFiles;
  var sPass;
  var sHandle;
  var sRanges;
  var nMaxRange;
  var aRange;
  var nRange;
  var sCmd;
  var sCmdOut;
  var bFileExists;
  var aInList;
  var aTmp;
  var nChoice;
  var i, n;

  if (bCollateW && ! oFSO.FileExists(sWaterPDF))
  {
    nTab = 3;
    SendMessage(aDlg[IDTABTC].HWND, 4912 /*TCM_SETCURFOCUS*/, nTab, 0);
    SendMessage(aDlg[IDWATERPDFE].HWND, 177 /*EM_SETSEL*/, 0, -1);
    oSys.Call("User32::SetFocus", aDlg[IDWATERPDFE].HWND);
    MsgBox(sWaterPDF ? sWaterPDF + "\n\n" + sTxtNoFile : sTxtNoWaterFile);
    return;
  }

  if (! (sOutFile = GetOpenSaveFileName(1, "", "pdf", GetFileUniqueName(sLastDir, oFSO.GetFileName(aPDF[nPDF].F)))))
    return;

  if (! (sTmpDir = CreateTempDir()))
  {
    MsgBox(sTxtNoTempDir);
    return;
  }

  bCreating = 1;
  EnableControlsDlg();
  SetDefButton(IDCREATEB, IDCREATEB);

  sFiles      = '';
  sPass       = '';
  sRanges     = '';
  nMaxRange   = 10;
  bFileExists = oFSO.FileExists(sOutFile);
  aInList     = [];
  aTmp        = [];
  nExitCode   = 0

  if (nOutRanges > nMaxRange)
  {
    nRange = 0;
    i      = 0;

    for (n = 1; n <= nOutRanges; ++n)
    {
      if (nRange == 0)
      {
        aRange  = aPDF[i].R.split(" ");
        sHandle = GetInputPDFHandle(i);
        sFiles  += sHandle + '="' + aPDF[i].F + '" ';

        if (aPDF[i].P)
          sPass += sHandle + '="' + aPDF[i].P + '" ';

        if (bFileExists && (aPDF[i].F.toUpperCase() == sOutFile.toUpperCase()))
          aInList.push(i);
      }

      sRanges += sHandle + aRange[nRange] + ' ';

      if ((n % nMaxRange == 0) || (n == nOutRanges))
      {
        if (sPass)
          sPass = 'input_pw ' + sPass;

        aTmp.push(GetTempFile(sTmpDir));

        sCmdOut = RunCmd('"' + sPDFtkExe + '" ' + sFiles + sPass + 'cat ' + sRanges + 'output "' + aTmp[aTmp.length - 1] + '"');

        if (nExitCode > 0)
        {
          if (nExitCode < 258)
            MsgBox(sCmdOut, sTxtPDFtkError);
          break;
        }

        if (nRange == aRange.length - 1)
        {
          sFiles = '';
          sPass  = '';
        }

        sRanges = '';
      }

      if (nRange == aRange.length - 1)
      {
        ++i;
        nRange = 0;
      }
      else
        ++nRange;
    }

    while ((aTmp.length > 1) && (nExitCode == 0))
    {
      sFiles = '';
      n      = aTmp.length;

      for (i = 0; i < n; ++i)
      {
        sFiles += '"' + aTmp[i] + '" ';

        if (((i + 1) % nMaxRange == 0) || (i + 1 == n))
        {
          aTmp.push(GetTempFile(sTmpDir));

          sCmdOut = RunCmd('"' + sPDFtkExe + '" ' + sFiles + 'cat output "' + aTmp[aTmp.length - 1] + '"');

          if (nExitCode > 0)
          {
            if (nExitCode < 258)
              MsgBox(sCmdOut, sTxtPDFtkError);
            break;
          }

          sFiles  = '';
        }
      }

      aTmp.splice(0, n);
    }

    if (nExitCode == 0)
    {
      if (bCollateW && oFSO.FileExists(sWaterPDF))
        sCmd = '"' + sPDFtkExe + '" "' + aTmp[0] + '" ' + GetWaterString();
      else
        sCmd = '"' + sPDFtkExe + '" "' + aTmp[0] + '" ' + 'cat ';
    }
  }
  else
  {
    for (i = 0; i < aPDF.length; ++i)
    {
      sHandle  = GetInputPDFHandle(i);
      sFiles  += sHandle + '="' + aPDF[i].F + '" ';
      sRanges += sHandle + aPDF[i].R.replace(/ /g, ' ' + sHandle) + ' ';

      if (aPDF[i].P)
        sPass += sHandle + '="' + aPDF[i].P + '" ';

      if (bFileExists && (aPDF[i].F.toUpperCase() == sOutFile.toUpperCase()))
        aInList.push(i);
    }

    if (sPass)
      sPass = 'input_pw ' + sPass;

    if (bCollateW && oFSO.FileExists(sWaterPDF))
    {
      aTmp[0] = GetTempFile(sTmpDir);
      sCmdOut = RunCmd('"' + sPDFtkExe + '" ' + sFiles + sPass + 'cat ' + sRanges + 'output "' + aTmp[0] + '"');

      if (nExitCode == 0)
        sCmd = '"' + sPDFtkExe + '" "' + aTmp[0] + '" ' + GetWaterString();
      else if (nExitCode < 258)
        MsgBox(sCmdOut, sTxtPDFtkError);
    }
    else
      sCmd = '"' + sPDFtkExe + '" ' + sFiles + sPass + 'cat ' + sRanges;
  }

  if (nExitCode == 0)
  {
    sTmpFile = bFileExists ? GetTempFile(sTmpDir) : sOutFile;
    sCmdOut  = RunCmd(sCmd + 'output "' + sTmpFile + '"' + GetPermissString());

    if (nExitCode == 0)
    {
      if (bFileExists)
      {
        while (sOutFile)
        {
          if (DeleteFile(sOutFile))
          {
            CopyFile(sTmpFile, sOutFile, 1);
            break;
          }
          else
          {
            if (MsgBox(sOutFile + "\n\n" + sTxtWriteError + "\n" + sTxtSelOtherName, 0, 0, [sTxtOK, sTxtCancel]) == 0)
              sOutFile = GetOpenSaveFileName(1, "", "pdf", sOutFile);
            else
              sOutFile = "";
          }
        }
      }

      if (oFSO.FileExists(sOutFile))
      {
        if (aInList.length)
        {
          for (i = 0; i < aInList.length; ++i)
            aPDF[aInList[i]].TP = 0;
          Refresh();
        }

        if (nAfter == 0)
          nChoice = MsgBox(sTxtCreated + "\n" + sOutFile, 0, 0, [sTxtOK, sTxtOpenPDF, sTxtOpenDir]);

        if ((nAfter == 1) || (nChoice == 1))
        {
          if (IsReaderExists())
            AkelPad.Exec('"' + sPDFReader + '" "' + sOutFile + '"');
        }
        else if ((nAfter == 2) || (nChoice == 2))
          OpenFolder(sOutFile);
      }
    }
    else if (nExitCode < 258)
      MsgBox(sCmdOut, sTxtPDFtkError);
  }

  bCreating = 0;
  EnableControlsDlg();
  DeleteFolder(sTmpDir);
}

function Shuffle()
{
  var sOutFile;
  var sTmpFile;
  var sTmpDir;
  var sTmp;
  var sFiles;
  var sPass;
  var sRanges;
  var sHandle;
  var sCmd;
  var sCmdOut;
  var bFileExists;
  var aInList;
  var nChoice;
  var i;

  if (bShuffleW && ! oFSO.FileExists(sWaterPDF))
  {
    nTab = 3;
    SendMessage(aDlg[IDTABTC].HWND, 4912 /*TCM_SETCURFOCUS*/, nTab, 0);
    SendMessage(aDlg[IDWATERPDFE].HWND, 177 /*EM_SETSEL*/, 0, -1);
    oSys.Call("User32::SetFocus", aDlg[IDWATERPDFE].HWND);
    MsgBox(sWaterPDF ? sWaterPDF + "\n\n" + sTxtNoFile : sTxtNoWaterFile);
    return;
  }

  if (! (sOutFile = GetOpenSaveFileName(1, "", "pdf", GetFileUniqueName(sLastDir, oFSO.GetFileName(aPDF[nPDF].F)))))
    return;

  if (! (sTmpDir = CreateTempDir()))
  {
    MsgBox(sTxtNoTempDir);
    return;
  }

  if (bFileExists = oFSO.FileExists(sOutFile))
    sTmpFile = GetTempFile(sTmpDir);
  else
    sTmpFile = sOutFile;

  sFiles   = '';
  sPass    = '';
  sRanges  = '';
  aInList  = [];

  for (i = 0; i < aPDF.length; ++i)
  {
    sHandle  = GetInputPDFHandle(i);
    sFiles  += sHandle + '="' + aPDF[i].F + '" ';
    sRanges += sHandle + aPDF[i].R.replace(/ /g, ' ' + sHandle) + ' ';

    if (aPDF[i].P)
      sPass += sHandle + '="' + aPDF[i].P + '" ';

    if (bFileExists && (aPDF[i].F.toUpperCase() == sOutFile.toUpperCase()))
      aInList.push(i);
  }

  if (sPass)
    sPass = 'input_pw ' + sPass;

  if (bShuffleW && oFSO.FileExists(sWaterPDF))
  {
    sTmp = GetTempFile(sTmpDir);
    sCmd = '"' + sPDFtkExe + '" ' + sFiles + sPass + 'shuffle ' + sRanges + 'output "' + sTmp;
  }
  else
    sCmd = '"' + sPDFtkExe + '" ' + sFiles + sPass + 'shuffle ' + sRanges + 'output "' + sTmpFile + '"' + GetPermissString();

  if (sCmd.length > 32767)
  {
    DeleteFolder(sTmpDir);
    MsgBox(sTxtTooManyDocs);
    return;
  }

  bCreating = 1;
  EnableControlsDlg();
  SetDefButton(IDCREATEB, IDCREATEB);

  sCmdOut = RunCmd(sCmd);

  if ((nExitCode == 0) && bShuffleW && oFSO.FileExists(sWaterPDF))
    sCmdOut = RunCmd('"' + sPDFtkExe + '" "' + sTmp + '" ' + GetWaterString() + 'output "' + sTmpFile + '"' + GetPermissString());

  if (nExitCode == 0)
  {
    if (bFileExists)
    {
      while (sOutFile)
      {
        if (DeleteFile(sOutFile))
        {
          CopyFile(sTmpFile, sOutFile, 1);
          break;
        }
        else
        {
          if (MsgBox(sOutFile + "\n\n" + sTxtWriteError + "\n" + sTxtSelOtherName, 0, 0, [sTxtOK, sTxtCancel]) == 0)
            sOutFile = GetOpenSaveFileName(1, "", "pdf", sOutFile);
          else
            sOutFile = "";
        }
      }
    }

    if (oFSO.FileExists(sOutFile))
    {
      if (aInList.length)
      {
        for (i = 0; i < aInList.length; ++i)
          aPDF[aInList[i]].TP = 0;
        Refresh();
      }

      if (nAfter == 0)
        nChoice = MsgBox(sTxtCreated + "\n" + sOutFile, 0, 0, [sTxtOK, sTxtOpenPDF, sTxtOpenDir]);

      if ((nAfter == 1) || (nChoice == 1))
      {
        if (IsReaderExists())
          AkelPad.Exec('"' + sPDFReader + '" "' + sOutFile + '"');
      }
      else if ((nAfter == 2) || (nChoice == 2))
        OpenFolder(sOutFile);
    }
  }
  else if (nExitCode < 258)
    MsgBox(sCmdOut, sTxtPDFtkError);

  bCreating = 0;
  EnableControlsDlg();
  DeleteFolder(sTmpDir);
}

function Split()
{
  var sOutDir;
  var sOutFile;
  var sCmdOut;
  var nFrom;
  var nTo;
  var aInpFile;
  var nChoice;
  var sNumber;
  var i, n;

  if (! (sOutDir = BrowseForFolder(sLastDir, "\n" + sTxtSelOutDir)))
    return;

  sLastDir  = sOutDir;
  sOutDir  += (sOutDir.slice(-1) == "\\") ? "" : "\\";
  aInpFile  = [];

  if (bSplitAll)
  {
    nFrom = 0;
    nTo   = aPDF.length - 1;
  }
  else
  {
    nFrom = nPDF;
    nTo   = nPDF;
  }

  bCreating = 1;
  EnableControlsDlg();
  SetDefButton(IDCREATEB, IDCREATEB);

  for (i = nFrom; i <= nTo; ++i)
  {
    SetCurSelLV(aDlg[IDPDFLV].HWND, i);

    if (! aInpFile[aPDF[i].F.toUpperCase()])
    {
      sOutFile = sOutDir + AkelPad.GetFilePath(aPDF[i].F, 3 /*CPF_FILEBASENAME*/) + "_%0" + aPDF[i].TP.toString().length.toString() + "d.pdf";
      sCmdOut  = RunCmd('"' + sPDFtkExe + '" "' + aPDF[i].F + '" ' + (aPDF[i].P ? 'input_pw "' + aPDF[i].P + '" ': '') + 'burst output "' + sOutFile + '"' + GetPermissString());

      if (nExitCode == 0)
      {
        aInpFile[aPDF[i].F.toUpperCase()] = 1;
        aInpFile.push(i);
      }
      else
      {
        if (nExitCode < 259)
          aInpFile.push(i);
        if (nExitCode < 258)
          MsgBox(sCmdOut, sTxtPDFtkError);

        break;
      }
    }
  }

  DeleteFile(sOutDir + "doc_data.txt");

  if (nExitCode == 0)
  {
    nChoice = 0;
    if (nAfter == 0)
    {
      sOutFile = "";
      if (aInpFile.length > 20)
      {
        for (i = 0; i < 18; ++i)
          sOutFile += "\n" + aPDF[aInpFile[i]].F;
        sOutFile += "\n...\n" + aPDF[aInpFile[aInpFile.length - 1]].F;
      }
      else
      {
        for (i = 0; i < aInpFile.length; ++i)
          sOutFile += "\n" + aPDF[aInpFile[i]].F;
      }

      nChoice = MsgBox(sTxtSplitted + sOutFile, 0, 0, [sTxtOK, sTxtOpenPDF, sTxtOpenDir]);
    }

    sOutFile = sOutDir + AkelPad.GetFilePath(aPDF[aInpFile[aInpFile.length - 1]].F, 3 /*CPF_FILEBASENAME*/) + "_" + aPDF[aInpFile[aInpFile.length - 1]].TP.toString() + ".pdf";

    if ((nAfter == 1) || (nChoice == 1))
    {
      if (IsReaderExists())
        AkelPad.Exec('"' + sPDFReader + '" "' + sOutFile + '"');
    }
    else if ((nAfter == 2) || (nChoice == 2))
      OpenFolder(sOutFile);
  }
  else
  {
    for (i = 0; i < aInpFile.length; ++i)
    {
      sOutFile = sOutDir + AkelPad.GetFilePath(aPDF[aInpFile[i]].F, 3 /*CPF_FILEBASENAME*/) + "_";

      for (n = 1; n <= aPDF[aInpFile[i]].TP; ++n)
      {
        sNumber = n.toString();

        while (sNumber.length < aPDF[aInpFile[i]].TP.toString().length)
          sNumber = "0" + sNumber;

        DeleteFile(sOutFile + sNumber + ".pdf");
      }
    }
  }

  bCreating = 0;
  EnableControlsDlg();
}

function Watermark()
{
  var sOutFile;
  var sTmpFile;
  var sOutDir;
  var sTmpDir;
  var sCmdOut;
  var bFileExists;
  var nChoice;
  var nIndex;
  var aInpFile;
  var aOutFile;
  var i;

  if (! oFSO.FileExists(sWaterPDF))
  {
    SendMessage(aDlg[IDWATERPDFE].HWND, 177 /*EM_SETSEL*/, 0, -1);
    SetDefButton(0, IDWATERPDFE);
    MsgBox(sWaterPDF + "\n\n" + sTxtNoFile);
    return;
  }

  if (bWaterAll && (aPDF.length > 1))
  {
    nIndex = sWaterAdd.search(/[<>:"\/\\|?*]/);

    if (nIndex >= 0)
    {
      SendMessage(aDlg[IDWATERADDE].HWND, 177 /*EM_SETSEL*/, nIndex, nIndex + 1);
      SetDefButton(0, IDWATERADDE);
      MsgBox(sTxtInvalidChar);
      return;
    }

    if (! (sOutDir = BrowseForFolder(sLastDir, "\n" + sTxtSelOutDir)))
      return;

    if (! (sTmpDir = CreateTempDir()))
    {
      MsgBox(sTxtNoTempDir);
      return;
    }

    sLastDir  = sOutDir;
    sOutDir  += (sOutDir.slice(-1) == "\\") ? "" : "\\";
    aInpFile  = [];
    aOutFile  = [];
    nExitCode = 0;

    bCreating = 1;
    EnableControlsDlg();
    SetDefButton(IDCREATEB, IDCREATEB);

    for (i = 0; (i < aPDF.length) && (nExitCode == 0); ++i)
    {
      SetCurSelLV(aDlg[IDPDFLV].HWND, i);

      if (! aInpFile[aPDF[i].F.toUpperCase()])
      {
        sOutFile = sOutDir + AkelPad.GetFilePath(aPDF[i].F, 3 /*CPF_FILEBASENAME*/) + sWaterAdd + "." + AkelPad.GetFilePath(aPDF[i].F, 4 /*CPF_FILEEXT*/);

        if (bFileExists = oFSO.FileExists(sOutFile))
          sTmpFile = GetTempFile(sTmpDir);
        else
          sTmpFile = sOutFile;

        sCmdOut = RunCmd('"' + sPDFtkExe + '" "' + aPDF[i].F + '" ' + (aPDF[i].P ? 'input_pw "' + aPDF[i].P + '" ': '') + GetWaterString() + 'output "' + sTmpFile + '"' + GetPermissString());

        if (nExitCode == 0)
        {
          if (bFileExists)
          {
            if ((nChoice != 1) && (nChoice != 3))
              nChoice = MsgBox(sOutFile + "\n\n" + sTxtFileExists, 0, 0, [sTxtReplace, sTxtReplaceAll, sTxtSkip, sTxtSkipAll, sTxtCancel]);

            if ((nChoice == -1) || (nChoice == 4))
              nExitCode = 260;
            else if ((nChoice == 0) || (nChoice == 1))
            {
              for (;;)
              {
                if (DeleteFile(sOutFile))
                {
                  CopyFile(sTmpFile, sOutFile, 1);
                  aInpFile[aPDF[i].F.toUpperCase()] = 1;
                  aOutFile[sOutFile.toUpperCase()]  = 1;
                  aOutFile.push(sOutFile);
                  break;
                }
                else if (MsgBox(sOutFile + "\n\n" + sTxtWriteError + " " + sTxtUnlockFile, 0, 0, [sTxtRetry, sTxtSkip]) != 0)
                  break;
              }
            }
          }
          else
          {
            aInpFile[aPDF[i].F.toUpperCase()] = 1;
            aOutFile[sOutFile.toUpperCase()]  = 1;
            aOutFile.push(sOutFile);
          }
        }
        else if (nExitCode < 258)
          MsgBox(sCmdOut, sTxtPDFtkError);
      }
    }

    if (aOutFile.length)
    {
      for (i = 0; i < aPDF.length; ++i)
      {
        if (aOutFile[aPDF[i].F.toUpperCase()])
          aPDF[i].TP = 0;
      }
      Refresh();

      nChoice = 0;
      if (nAfter == 0)
      {
        sOutFile = "";
        if (aOutFile.length > 20)
        {
          for (i = 0; i < 18; ++i)
            sOutFile += "\n" + aOutFile[i];
          sOutFile += "\n...\n" + aOutFile[aOutFile.length - 1];
        }
        else
        {
          for (i = 0; i < aOutFile.length; ++i)
            sOutFile += "\n" + aOutFile[i];
        }

        nChoice = MsgBox(sTxtCreated + sOutFile, 0, 0, [sTxtOK, sTxtOpenPDF, sTxtOpenDir]);
      }

      if ((nAfter == 1) || (nChoice == 1))
      {
        if (IsReaderExists())
          AkelPad.Exec('"' + sPDFReader + '" "' + aOutFile[aOutFile.length - 1] + '"');
      }
      else if ((nAfter == 2) || (nChoice == 2))
        OpenFolder(aOutFile[aOutFile.length - 1]);
    }
  }
  else
  {
    if (! (sOutFile = GetOpenSaveFileName(1, "", "pdf", GetFileUniqueName(sLastDir, oFSO.GetFileName(aPDF[nPDF].F)))))
      return;

    if (! (sTmpDir = CreateTempDir()))
    {
      MsgBox(sTxtNoTempDir);
      return;
    }

    if (bFileExists = oFSO.FileExists(sOutFile))
      sTmpFile = GetTempFile(sTmpDir);
    else
      sTmpFile = sOutFile;

    bCreating = 1;
    EnableControlsDlg();
    SetDefButton(IDCREATEB, IDCREATEB);

    sCmdOut = RunCmd('"' + sPDFtkExe + '" "' + aPDF[nPDF].F + '" ' + (aPDF[nPDF].P ? 'input_pw "' + aPDF[nPDF].P + '" ': '') + GetWaterString() + 'output "' + sTmpFile + '"' + GetPermissString());

    if (nExitCode == 0)
    {
      if (bFileExists)
      {
        while (sOutFile)
        {
          if (DeleteFile(sOutFile))
          {
            CopyFile(sTmpFile, sOutFile, 1);
            break;
          }
          else
          {
            if (MsgBox(sOutFile + "\n\n" + sTxtWriteError + "\n" + sTxtSelOtherName, 0, 0, [sTxtOK, sTxtCancel]) == 0)
              sOutFile = GetOpenSaveFileName(1, "", "pdf", sOutFile);
            else
              sOutFile = "";
          }
        }
      }

      if (oFSO.FileExists(sOutFile))
      {
        if (bFileExists)
        {
          for (i = 0; i < aPDF.length; ++i)
          {
            if (aPDF[i].F.toUpperCase() == sOutFile.toUpperCase())
              aPDF[i].TP = 0;
          }
          Refresh();
        }

        if (nAfter == 0)
          nChoice = MsgBox(sTxtCreated + "\n" + sOutFile, 0, 0, [sTxtOK, sTxtOpenPDF, sTxtOpenDir]);

        if ((nAfter == 1) || (nChoice == 1))
        {
          if (IsReaderExists())
            AkelPad.Exec('"' + sPDFReader + '" "' + sOutFile + '"');
        }
        else if ((nAfter == 2) || (nChoice == 2))
          OpenFolder(sOutFile);
      }
    }
    else if (nExitCode < 258)
      MsgBox(sCmdOut, sTxtPDFtkError);
  }

  bCreating = 0;
  EnableControlsDlg();
  DeleteFolder(sTmpDir);
}

function Bookmarks()
{
  var sInfoFile;
  var sOutFile;
  var sTmpFile;
  var sTmpDir;
  var sCmdOut;
  var aBookmark;
  var sBookmark;
  var nLevel;
  var bFileExists;
  var nChoice;
  var i, n;

  if (nBook == 0)
  {
    bCreating = 1;
    EnableControlsDlg();
    SetDefButton(IDCREATEB, IDCREATEB);

    sCmdOut = RunCmd('"' + sPDFtkExe + '" "' + aPDF[nPDF].F + '" ' + (aPDF[nPDF].P ? 'input_pw "' + aPDF[nPDF].P + '" ': '') + 'dump_data' + (bUTF8 ? '_utf8' : ''));

    if (nExitCode == 0)
    {
      aBookmark = sCmdOut.match(/^BookmarkBegin\r\nBookmarkTitle: [\s\S]+?\r\nBookmarkLevel: \d+\r\nBookmarkPageNumber: \d+$/gm);

      if (aBookmark)
      {
        sCmdOut = "";

        for (i = 0; i < aBookmark.length; ++i)
        {
          nLevel = parseInt(aBookmark[i].match(/^BookmarkLevel: (\d+)$/m)[1]);

          for (n = 2; n <= nLevel; ++n)
            sCmdOut += "\t";

          sCmdOut += aBookmark[i].match(/^BookmarkTitle: ([\s\S]+?)\r\nBookmarkLevel: /m)[1].replace(/(\r\r\n)|(\r\n)|\r|\n/g, " ") + "/" + aBookmark[i].match(/^BookmarkPageNumber: (\d+)$/m)[1] + "\r\n";
        }

        if (sOutFile = GetOpenSaveFileName(1, "", "txt", GetFileUniqueName(sLastDir, oFSO.GetBaseName(aPDF[nPDF].F) + ".txt")))
        {
          if (bUTF8 && bBOM)
            sCmdOut = "ď»ż" + sCmdOut;

          while (sOutFile && (! WriteFile(sOutFile, sCmdOut, 0)))
          {
            if (MsgBox(sOutFile + "\n\n" + sTxtWriteError + "\n" + sTxtSelOtherName, 0, 0, [sTxtOK, sTxtCancel]) == 0)
              sOutFile = GetOpenSaveFileName(1, "", "txt", sOutFile);
            else
              sOutFile = "";
          }

          if (oFSO.FileExists(sOutFile))
          {
            if (nAfter == 0)
              nChoice = MsgBox(sTxtCreated + "\n" + sOutFile, 0, 0, [sTxtOK, sTxtOpenTXT, sTxtOpenDir]);

            if ((nAfter == 1) || (nChoice == 1))
            {
              if (IsEditorExists())
                AkelPad.Exec('"' + sTXTEditor + '" "' + sOutFile + '"');
            }
            else if ((nAfter == 2) || (nChoice == 2))
              OpenFolder(sOutFile);
          }
        }
      }
      else
        MsgBox(aPDF[nPDF].F + "\n\n" + sTxtNoPDFBookmarks);
    }
    else if (nExitCode < 258)
      MsgBox(sCmdOut, sTxtPDFtkError);
  }
  else
  {
    if (! oFSO.FileExists(sBookTXT))
    {
      SendMessage(aDlg[IDBOOKTXTE].HWND, 177 /*EM_SETSEL*/, 0, -1);
      SetDefButton(0, IDBOOKTXTE);
      MsgBox(sBookTXT + "\n\n" + sTxtNoFile);
      return;
    }

    sBookmark = "";
    aBookmark = ReadFile(sBookTXT, 0).split(/(\r\r\n)|(\r\n)|\r|\n/);

    if (bUTF8 && bBOM && (aBookmark[0].substr(0, 3) == "ď»ż"))
      aBookmark[0] = aBookmark[0].substr(3);

    for (i = 0; i < aBookmark.length; ++i)
    {
      if (/\S/.test(aBookmark[i]))
      {
        aBookmark[i] = aBookmark[i].match(/^(\t*)(.+?)(\/(\d+))*$/);
        sBookmark   += "BookmarkBegin" + "\r\n";
        sBookmark   += "BookmarkTitle: " + aBookmark[i][2] + "\r\n";
        sBookmark   += "BookmarkLevel: " + (aBookmark[i][1].length + 1) + "\r\n";
        sBookmark   += "BookmarkPageNumber: " + aBookmark[i][4] + "\r\n";
      }
    }

    if (! sBookmark)
    {
      SendMessage(aDlg[IDBOOKTXTE].HWND, 177 /*EM_SETSEL*/, 0, -1);
      SetDefButton(0, IDBOOKTXTE);
      MsgBox(sBookTXT + "\n\n" + sTxtNoTXTBookmarks);
      return;
    }

    if (! (sOutFile = GetOpenSaveFileName(1, "", "pdf", GetFileUniqueName(sLastDir, oFSO.GetFileName(aPDF[nPDF].F)))))
      return;

    if (! (sTmpDir = CreateTempDir()))
    {
      MsgBox(sTxtNoTempDir);
      return;
    }

    sInfoFile = GetTempFile(sTmpDir);
    if (! WriteFile(sInfoFile, sBookmark, 0))
    {
      MsgBox(sInfoFile + "\n\n" + sTxtWriteError);
      DeleteFolder(sTmpDir);
      return;
    }

    if (bFileExists = oFSO.FileExists(sOutFile))
      sTmpFile = GetTempFile(sTmpDir);
    else
      sTmpFile = sOutFile;

    bCreating = 1;
    EnableControlsDlg();
    SetDefButton(IDCREATEB, IDCREATEB);

    sCmdOut = RunCmd('"' + sPDFtkExe + '" "' + aPDF[nPDF].F + '" ' + (aPDF[nPDF].P ? 'input_pw "' + aPDF[nPDF].P + '" ': '') + 'update_info' + (bUTF8 ? '_utf8' : '') + ' "' + sInfoFile + '" ' + 'output "' + sTmpFile + '"' + GetPermissString());

    if (nExitCode == 0)
    {
      if (bFileExists)
      {
        while (sOutFile)
        {
          if (DeleteFile(sOutFile))
          {
            CopyFile(sTmpFile, sOutFile, 1);
            break;
          }
          else
          {
            if (MsgBox(sOutFile + "\n\n" + sTxtWriteError + "\n" + sTxtSelOtherName, 0, 0, [sTxtOK, sTxtCancel]) == 0)
              sOutFile = GetOpenSaveFileName(1, "", "pdf", sOutFile);
            else
              sOutFile = "";
          }
        }
      }

      if (oFSO.FileExists(sOutFile))
      {
        if (bFileExists)
        {
          for (i = 0; i < aPDF.length; ++i)
          {
            if (aPDF[i].F.toUpperCase() == sOutFile.toUpperCase())
              aPDF[i].TP = 0;
          }
          Refresh();
        }

        if (nAfter == 0)
          nChoice = MsgBox(sTxtCreated + "\n" + sOutFile, 0, 0, [sTxtOK, sTxtOpenPDF, sTxtOpenDir]);

        if ((nAfter == 1) || (nChoice == 1))
        {
          if (IsReaderExists())
            AkelPad.Exec('"' + sPDFReader + '" "' + sOutFile + '"');
        }
        else if ((nAfter == 2) || (nChoice == 2))
          OpenFolder(sOutFile);
      }
    }
    else if (nExitCode < 258)
      MsgBox(sCmdOut, sTxtPDFtkError);

    DeleteFolder(sTmpDir);
  }

  bCreating = 0;
  EnableControlsDlg();
}

function PDFInfo()
{
  var sInfoFile;
  var sOutFile;
  var sTmpFile;
  var sTmpDir;
  var sOperation;
  var sCmdOut;
  var bFileExists;
  var nChoice;
  var i;

  if (nData < 3)
  {
    bCreating = 1;
    EnableControlsDlg();
    SetDefButton(IDCREATEB, IDCREATEB);

    if (nData == 0)
      sOperation = "dump_data_annots";
    else if (nData == 1)
      sOperation = "dump_data_fields" + (bUTF8 ? "_utf8" : "");
    else if (nData == 2)
      sOperation = "dump_data" + (bUTF8 ? "_utf8" : "");

    sCmdOut = RunCmd('"' + sPDFtkExe + '" "' + aPDF[nPDF].F + '" ' + (aPDF[nPDF].P ? 'input_pw "' + aPDF[nPDF].P + '" ': '') + sOperation);

    if (nExitCode == 0)
    {
      if (sCmdOut)
      {
        if (sOutFile = GetOpenSaveFileName(1, "", "txt", GetFileUniqueName(sLastDir, oFSO.GetBaseName(aPDF[nPDF].F) + ".txt")))
        {
          if (bUTF8 && bBOM)
            sCmdOut = "ď»ż" + sCmdOut;

          while (sOutFile && (! WriteFile(sOutFile, sCmdOut, 0)))
          {
            if (MsgBox(sOutFile + "\n\n" + sTxtWriteError + "\n" + sTxtSelOtherName, 0, 0, [sTxtOK, sTxtCancel]) == 0)
              sOutFile = GetOpenSaveFileName(1, "", "txt", sOutFile);
            else
              sOutFile = "";
          }

          if (oFSO.FileExists(sOutFile))
          {
            if (nAfter == 0)
              nChoice = MsgBox(sTxtCreated + "\n" + sOutFile, 0, 0, [sTxtOK, sTxtOpenTXT, sTxtOpenDir]);

            if ((nAfter == 1) || (nChoice == 1))
            {
              if (IsEditorExists())
                AkelPad.Exec('"' + sTXTEditor + '" "' + sOutFile + '"');
            }
            else if ((nAfter == 2) || (nChoice == 2))
              OpenFolder(sOutFile);
          }
        }
      }
      else
        MsgBox(aPDF[nPDF].F + "\n\n" + sTxtNoPDFData);
    }
    else if (nExitCode < 258)
      MsgBox(sCmdOut, sTxtPDFtkError);
  }
  else
  {
    if (! oFSO.FileExists(sDataTXT))
    {
      SendMessage(aDlg[IDDATATXTE].HWND, 177 /*EM_SETSEL*/, 0, -1);
      SetDefButton(0, IDDATATXTE);
      MsgBox(sDataTXT + "\n\n" + sTxtNoFile);
      return;
    }

    if (! (sOutFile = GetOpenSaveFileName(1, "", "pdf", GetFileUniqueName(sLastDir, oFSO.GetFileName(aPDF[nPDF].F)))))
      return;

    if (! (sTmpDir = CreateTempDir()))
    {
      MsgBox(sTxtNoTempDir);
      return;
    }

    bCreating = 1;
    EnableControlsDlg();
    SetDefButton(IDCREATEB, IDCREATEB);

    if (bFileExists = oFSO.FileExists(sOutFile))
      sTmpFile = GetTempFile(sTmpDir);
    else
      sTmpFile = sOutFile;

    sInfoFile = GetTempFile(sTmpDir);
    CopyFile(sDataTXT, sInfoFile);

    sCmdOut = RunCmd('"' + sPDFtkExe + '" "' + aPDF[nPDF].F + '" ' + (aPDF[nPDF].P ? 'input_pw "' + aPDF[nPDF].P + '" ': '') + 'update_info' + (bUTF8 ? '_utf8' : '') + ' "' + sInfoFile + '" ' + 'output "' + sTmpFile + '"' + GetPermissString());

    if (nExitCode == 0)
    {
      if (bFileExists)
      {
        while (sOutFile)
        {
          if (DeleteFile(sOutFile))
          {
            CopyFile(sTmpFile, sOutFile, 1);
            break;
          }
          else
          {
            if (MsgBox(sOutFile + "\n\n" + sTxtWriteError + "\n" + sTxtSelOtherName, 0, 0, [sTxtOK, sTxtCancel]) == 0)
              sOutFile = GetOpenSaveFileName(1, "", "pdf", sOutFile);
            else
              sOutFile = "";
          }
        }
      }

      if (oFSO.FileExists(sOutFile))
      {
        if (bFileExists)
        {
          for (i = 0; i < aPDF.length; ++i)
          {
            if (aPDF[i].F.toUpperCase() == sOutFile.toUpperCase())
              aPDF[i].TP = 0;
          }
          Refresh();
        }

        if (nAfter == 0)
          nChoice = MsgBox(sTxtCreated + "\n" + sOutFile, 0, 0, [sTxtOK, sTxtOpenPDF, sTxtOpenDir]);

        if ((nAfter == 1) || (nChoice == 1))
        {
          if (IsReaderExists())
            AkelPad.Exec('"' + sPDFReader + '" "' + sOutFile + '"');
        }
        else if ((nAfter == 2) || (nChoice == 2))
          OpenFolder(sOutFile);
      }
    }
    else if (nExitCode < 258)
      MsgBox(sCmdOut, sTxtPDFtkError);

    DeleteFolder(sTmpDir);
  }

  bCreating = 0;
  EnableControlsDlg();
}

function ReadFile(sFile, bUnicode)
{
  var sText = "";
  var oFile;

  try
  {
    oFile = oFSO.OpenTextFile(sFile, 1, false, bUnicode ? -1 : 0);
  }
  catch (oError)
  {
    return sText;
  }

  try
  {
    sText = oFile.ReadAll();
  }
  catch (oError)
  {}

  oFile.Close();
  return sText;
}

function WriteFile(sFile, sText, bUnicode)
{
  var bWrite = false;
  var oFile;

  try
  {
    oFile = oFSO.OpenTextFile(sFile, 2, true, bUnicode ? -1 : 0);
  }
  catch (oError)
  {
    return bWrite;
  }

  try
  {
    oFile.Write(sText);
    bWrite = true;
  }
  catch (oError)
  {}

  oFile.Close();
  return bWrite;
}

function CopyFile(sSource, sTarget, bMove)
{
  var bSuccess = true;

  try
  {
    if (bMove)
      oFSO.MoveFile(sSource, sTarget);
    else
      oFSO.CopyFile(sSource, sTarget);
  }
  catch (oError)
  {
    bSuccess = false;
  }

  return bSuccess;
}

function DeleteFile(sFile)
{
  try
  {
    oFSO.DeleteFile(sFile, 1);
  }
  catch (oError)
  {}

  return ! oFSO.FileExists(sFile);
}

function CreateFolder(sDir)
{
  try
  {
    oFSO.CreateFolder(sDir);
  }
  catch (oError)
  {}

  return oFSO.FolderExists(sDir);
}

function DeleteFolder(sDir)
{
  try
  {
    oFSO.DeleteFolder(sDir, 1);
  }
  catch (oError)
  {}

  return ! oFSO.FolderExists(sDir);
}

function CreateTempDir()
{
  var nBufSize = 260;
  var lpDir    = AkelPad.MemAlloc(nBufSize * 2);
  var lpName   = AkelPad.MemAlloc(nBufSize * 2);
  var sDir;

  oSys.Call("Kernel32::GetTempPathW", nBufSize, lpDir);
  sDir = AkelPad.MemRead(lpDir, 1 /*DT_UNICODE*/);

  if ((! oFSO.FolderExists(sDir)) && (! CreateFolder(sDir)))
    sDir = "";

  if (sDir)
  {
    oSys.Call("Shell32::PathMakeUniqueName", lpName, nBufSize, sDlgTitle, 0, sDir);
    sDir = AkelPad.MemRead(lpName, 1 /*DT_UNICODE*/);

    if (! CreateFolder(sDir))
      sDir = "";
  }

  AkelPad.MemFree(lpDir);
  AkelPad.MemFree(lpName);

  return sDir;
}

function GetTempFile(sDir)
{
  var lpFile = AkelPad.MemAlloc(260 * 2);
  var sFile;

  oSys.Call("Kernel32::GetTempFileNameW", sDir, "pdf", 0, lpFile);
  sFile = AkelPad.MemRead(lpFile, 1 /*DT_UNICODE*/);
  AkelPad.MemFree(lpFile);

  return sFile;
}

function GetFileUniqueName(sDir, sFile)
{
  var nBufSize;
  var lpDir;
  var lpName;

  sDir += (sDir.slice(-1) == "\\") ? "" : "\\";

  if (oFSO.FileExists(sDir + sFile) || oFSO.FolderExists(sDir + sFile))
  {
    nBufSize = 260;
    lpDir    = AkelPad.MemAlloc(nBufSize * 2);
    lpName   = AkelPad.MemAlloc(nBufSize * 2);

    oSys.Call("Shell32::PathMakeUniqueName", lpName, nBufSize, sFile, 0, sDir);
    sFile = AkelPad.MemRead(lpName, 1 /*DT_UNICODE*/);
    AkelPad.MemFree(lpName);
  }
  else
    sFile = sDir + sFile;

  return sFile;
}

function GetInputPDFHandle(n)
{
  var aN = [];
  var i;

  for (i = 3; i >= 0; --i)
  {
    aN[i] = Math.floor(n / Math.pow(26, i));
    n     = n % Math.pow(26, i);
  }

  return String.fromCharCode(aN[3] + 65, aN[2] + 65, aN[1] + 65, aN[0] + 65).replace(/^A{1,3}(.+)$/, "$1");
}

function GetWaterString()
{
  var sWater;

  if (nWater == 0)
    sWater = 'background';
  else if (nWater == 1)
    sWater = 'multibackground';
  else if (nWater == 2)
    sWater = 'stamp';
  else
    sWater = 'multistamp';

  return sWater + ' "' + sWaterPDF + '" ';
}

function GetPermissString()
{
  var sPermiss = '';

  if (bPassProt)
  {
    if (bTopPrint && bLowPrint && bModCont && bAssembly && bCopyCont && bScrRead && bModAnnot && bFillIn)
      sPermiss = ' AllFeatures';
    else
    {
      if (bTopPrint)
        sPermiss += ' Printing';
      if (bLowPrint)
        sPermiss += ' DegradedPrinting';
      if (bModCont)
        sPermiss += ' ModifyContents';
      if (bAssembly)
        sPermiss += ' Assembly';
      if (bCopyCont)
        sPermiss += ' CopyContents';
      if (bScrRead)
        sPermiss += ' ScreenReaders';
      if (bModAnnot)
        sPermiss += ' ModifyAnnotations';
      if (bFillIn)
        sPermiss += ' FillIn';
    }

    if (sPermiss)
      sPermiss = ' allow' + sPermiss;
    if (sOwnerPass)
      sPermiss += ' owner_pw "' + sOwnerPass + '"';
    if (sUserPass)
      sPermiss += ' user_pw "' + sUserPass + '"';
  }

  return sPermiss;
}

function OpenPDF()
{
  var sFile;

  if (IsReaderExists() && (sFile = GetOpenSaveFileName(0, sTxtOpenPDF.replace("&", ""), "pdf", "", 0)))
    AkelPad.Exec('"' + sPDFReader + '" "' + sFile + '"');
}

function OpenTXT()
{
  var sFile;

  if (IsEditorExists() && (sFile = GetOpenSaveFileName(0, sTxtOpenTXT.replace("&", ""), "txt", "", 0)))
    AkelPad.Exec('"' + sTXTEditor + '" "' + sFile + '"');
}

function OpenFolder(sFile)
{
  var nCount;
  var lpNull;
  var lpIDL;

  if (! oFSO.FileExists(sFile))
  {
    nCount = 1;
    lpNull = AkelPad.MemAlloc(1);

    if (oFSO.FolderExists(sLastDir))
      sFile = sLastDir;
    else
      sFile = sScriptDir;
  }

  lpIDL = oSys.Call("Shell32::ILCreateFromPathW", sFile);
  oSys.Call("Shell32::SHOpenFolderAndSelectItems", lpIDL, nCount, lpNull, 0);
  oSys.Call("Shell32::ILFree", lpIDL);
  AkelPad.MemFree(lpNull);
}

function PDFtkHelp()
{
  var sFile;

  if (IsPDFtkExists())
  {
    sFile = sPDFtkDir + ((sPDFtkDir.slice(-1) == "\\") ? "" : "\\") + "pdftk_help.txt";

    if (! oFSO.FileExists(sFile))
      RunCmd('cmd.exe /c ""' + sPDFtkExe + '" --help > "' + sFile + '""');

    if (IsEditorExists() && oFSO.FileExists(sFile))
      AkelPad.Exec('"' + sTXTEditor + '" "' + sFile + '"');
  }
}

function RunCmd(sCmd)
{
  var sOutput       = "";
  var hCurProcess   = oSys.Call("Kernel32::GetCurrentProcess");
  var nBufSize      = 65536;
  var lpBuffer      = AkelPad.MemAlloc(nBufSize);
  var lpBytesAvail  = AkelPad.MemAlloc(4);
  var lpBytesRead   = AkelPad.MemAlloc(4);
  var lpExitCode    = AkelPad.MemAlloc(4);
  var lpMsg         = AkelPad.MemAlloc(_X64 ? 48 : 28 /*sizeof(MSG)*/);
  var lpSA          = AkelPad.MemAlloc(_X64 ? 24 : 12 /*sizeof(SECURITY_ATTRIBUTES)*/);
  var lpSI          = AkelPad.MemAlloc(_X64 ? 104 : 68 /*sizeof(STARTUPINFO)*/);
  var lpPI          = AkelPad.MemAlloc(_X64 ? 24 : 16 /*sizeof(PROCESS_INFORMATION)*/);
  var lpInpRead     = AkelPad.MemAlloc(_X64 ? 8 : 4);
  var lpInpWriteTmp = AkelPad.MemAlloc(_X64 ? 8 : 4);
  var lpInpWrite    = AkelPad.MemAlloc(_X64 ? 8 : 4);
  var lpOutReadTmp  = AkelPad.MemAlloc(_X64 ? 8 : 4);
  var lpOutRead     = AkelPad.MemAlloc(_X64 ? 8 : 4);
  var lpOutWrite    = AkelPad.MemAlloc(_X64 ? 8 : 4);
  var lpErrWrite    = AkelPad.MemAlloc(_X64 ? 8 : 4);
  var hInpRead;
  var hInpWriteTmp;
  var hInpWrite;
  var hOutReadTmp;
  var hOutRead;
  var hOutWrite;
  var hErrWrite;
  var hThread;
  var nBytesAvail;

  AkelPad.MemCopy(_PtrAdd(lpSA, 0), _X64 ? 24 : 12, 3 /*DT_DWORD*/); //nLength
  AkelPad.MemCopy(_PtrAdd(lpSA, _X64 ? 16 : 8),  1, 3 /*DT_DWORD*/); //bInheritHandle

  oSys.Call("Kernel32::CreatePipe", lpInpRead,    lpInpWriteTmp, lpSA, nBufSize);
  oSys.Call("Kernel32::CreatePipe", lpOutReadTmp, lpOutWrite,    lpSA, nBufSize);
  hInpRead     = AkelPad.MemRead(lpInpRead,     2 /*DT_QWORD*/);
  hInpWriteTmp = AkelPad.MemRead(lpInpWriteTmp, 2 /*DT_QWORD*/);
  hOutReadTmp  = AkelPad.MemRead(lpOutReadTmp,  2 /*DT_QWORD*/);
  hOutWrite    = AkelPad.MemRead(lpOutWrite,    2 /*DT_QWORD*/);

  oSys.Call("Kernel32::DuplicateHandle", hCurProcess, hInpWriteTmp, hCurProcess, lpInpWrite, 0, 0 /*bInheritHandle*/, 2 /*DUPLICATE_SAME_ACCESS*/);
  oSys.Call("Kernel32::DuplicateHandle", hCurProcess, hOutReadTmp,  hCurProcess, lpOutRead,  0, 0 /*bInheritHandle*/, 2 /*DUPLICATE_SAME_ACCESS*/);
  oSys.Call("Kernel32::DuplicateHandle", hCurProcess, hOutWrite,    hCurProcess, lpErrWrite, 0, 1 /*bInheritHandle*/, 2 /*DUPLICATE_SAME_ACCESS*/);
  hInpWrite = AkelPad.MemRead(lpInpWrite, 2 /*DT_QWORD*/);
  hOutRead  = AkelPad.MemRead(lpOutRead,  2 /*DT_QWORD*/);
  hErrWrite = AkelPad.MemRead(lpErrWrite, 2 /*DT_QWORD*/);

  AkelPad.MemCopy(_PtrAdd(lpSI, 0),         _X64 ? 104 : 68, 3 /*DT_DWORD*/); //cb=sizeof(STARTUPINFO)
  AkelPad.MemCopy(_PtrAdd(lpSI, _X64 ? 60 : 44), 0x00000101, 3 /*DT_DWORD*/); //dwFlags=STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW
  AkelPad.MemCopy(_PtrAdd(lpSI, _X64 ? 80 : 56),   hInpRead, 2 /*DT_QWORD*/); //hStdInput
  AkelPad.MemCopy(_PtrAdd(lpSI, _X64 ? 88 : 60),  hOutWrite, 2 /*DT_QWORD*/); //hStdOutput
  AkelPad.MemCopy(_PtrAdd(lpSI, _X64 ? 96 : 64),  hErrWrite, 2 /*DT_QWORD*/); //hStdError

  if (oSys.Call("Kernel32::CreateProcessW", 0, sCmd, 0, 0, 1 /*bInheritHandles*/, 0x10 /*CREATE_NEW_CONSOLE*/, 0, 0, lpSI, lpPI))
  {
    hProcess = AkelPad.MemRead(_PtrAdd(lpPI, 0),             2 /*DT_QWORD*/);
    hThread  = AkelPad.MemRead(_PtrAdd(lpPI, _X64 ?  8 : 4), 2 /*DT_QWORD*/);

    oSys.Call("User32::ShowWindow", aDlg[IDPROGRESS].HWND, 1);
    oSys.Call("User32::UpdateWindow", hDlg);

    while (oSys.Call("Kernel32::PeekNamedPipe", hOutRead, 0, 0, 0, lpBytesAvail, 0) && oSys.Call("Kernel32::GetExitCodeProcess", hProcess, lpExitCode))
    {
      while (oSys.Call("User32::PeekMessageW", lpMsg, hDlg, 0, 0, 0x1 /*PM_REMOVE*/))
      {
        oSys.Call("User32::TranslateMessage", lpMsg);
        oSys.Call("User32::DispatchMessageW", lpMsg);
      }

      nExitCode = AkelPad.MemRead(lpExitCode, 3 /*DT_DWORD*/);

      if (nBytesAvail = AkelPad.MemRead(lpBytesAvail, 3 /*DT_DWORD*/))
      {
        if (nBytesAvail >= nBufSize)
          nBytesAvail = nBufSize - 1;

        oSys.Call("Kernel32::ReadFile", hOutRead, lpBuffer, nBytesAvail, lpBytesRead, 0);
        sOutput += AkelPad.MemRead(lpBuffer, 0 /*DT_ANSI*/, AkelPad.MemRead(lpBytesRead, 3 /*DT_DWORD*/));
      }
      else if (nExitCode == 259 /*STILL_ACTIVE*/)
        WScript.Sleep(10);
      else
        break;

      SendMessage(aDlg[IDPROGRESS].HWND, 1029 /*PBM_STEPIT*/, 0, 0);
    }

    oSys.Call("User32::ShowWindow", aDlg[IDPROGRESS].HWND, 0);
  }
  else
  {
    nExitCode = 260;
    MsgBox(sTxtCantExec + "\n" + sCmd);
  }

  AkelPad.MemFree(lpBuffer);
  AkelPad.MemFree(lpBytesAvail);
  AkelPad.MemFree(lpBytesRead);
  AkelPad.MemFree(lpExitCode);
  AkelPad.MemFree(lpMsg);
  AkelPad.MemFree(lpSA);
  AkelPad.MemFree(lpPI);
  AkelPad.MemFree(lpSI);
  AkelPad.MemFree(lpInpRead);
  AkelPad.MemFree(lpInpWriteTmp);
  AkelPad.MemFree(lpInpWrite);
  AkelPad.MemFree(lpOutReadTmp);
  AkelPad.MemFree(lpOutRead);
  AkelPad.MemFree(lpOutWrite);
  AkelPad.MemFree(lpErrWrite);

  oSys.Call("Kernel32::CloseHandle", hInpRead);
  oSys.Call("Kernel32::CloseHandle", hInpWriteTmp);
  oSys.Call("Kernel32::CloseHandle", hInpWrite);
  oSys.Call("Kernel32::CloseHandle", hOutReadTmp);
  oSys.Call("Kernel32::CloseHandle", hOutRead);
  oSys.Call("Kernel32::CloseHandle", hOutWrite);
  oSys.Call("Kernel32::CloseHandle", hErrWrite);
  oSys.Call("Kernel32::CloseHandle", hProcess);
  oSys.Call("Kernel32::CloseHandle", hThread);

  hProcess = 0;

  return sOutput;
}

function StopCmd()
{
  if (hProcess)
  {
    oSys.Call("Kernel32::TerminateProcess", hProcess, 258);
    oSys.Call("Kernel32::WaitForSingleObject", hProcess, 100);
  }
}

function GetOpenSaveFileName(bSave, sTitle, sExt, sFile, bMultiSelect, nX, nY)
{
  var sFunc    = bSave ? "GetSaveFileNameW" : "GetOpenFileNameW";
  var lpCurDir = AkelPad.MemAlloc(260 * 2);
  var oRect    = {};
  var sFilter  = "*." + sExt + "\0*." + sExt + "\0\0";
  var lpFilter = AkelPad.MemAlloc(sFilter.length * 2 + 2);
  var lpFile   = AkelPad.MemAlloc(0x80000 * 2);
  var lpDir    = AkelPad.MemAlloc(260 * 2);
  var lpTitle  = AkelPad.MemAlloc(sTitle.length * 2 + 2);
  var lpDefExt = AkelPad.MemAlloc(sFilter.length * 2 + 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 vFile;
  var nOffset;
  var i;

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

  GetWindowPos(hDlg, oRect);
  if (typeof nX != "number")
    nX = oRect.X + (oRect.W - Scale.X(560)) / 2;
  if (typeof nY != "number")
    nY = oRect.Y + (oRect.H - Scale.Y(420)) / 2 + 15;

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

  AkelPad.MemCopy(lpFilter, sFilter, 1 /*DT_UNICODE*/);
  AkelPad.MemCopy(lpTitle,  sTitle,  1 /*DT_UNICODE*/);
  AkelPad.MemCopy(lpDefExt, sExt,    1 /*DT_UNICODE*/);

  if (sFile)
  {
    if (oFSO.FileExists(sFile))
      AkelPad.MemCopy(lpFile, sFile, 1 /*DT_UNICODE*/);
    else if (oFSO.FolderExists(sFile))
      AkelPad.MemCopy(lpDir, sFile, 1 /*DT_UNICODE*/);
    else
    {
      AkelPad.MemCopy(lpFile, oFSO.GetFileName(sFile), 1 /*DT_UNICODE*/);
      AkelPad.MemCopy(lpDir, oFSO.GetParentFolderName(sFile), 1 /*DT_UNICODE*/);
    }
  }
  else
    AkelPad.MemCopy(lpDir, oFSO.FolderExists(sLastDir) ? sLastDir : sScriptDir, 1 /*DT_UNICODE*/);

  if (bMultiSelect)
    nFlags |= 0x00000200 /*OFN_ALLOWMULTISELECT*/;

  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),  0x80000, 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
  AkelPad.MemCopy(_PtrAdd(lpOFN, _X64 ? 104 : 60), lpDefExt, 2 /*DT_QWORD*/); //lpstrDefExt

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

  if (oSys.Call("Comdlg32::" + sFunc, lpOFN))
  {
    if (bMultiSelect)
    {
      vFile   = [];
      nOffset = 0;

      while (sFile = AkelPad.MemRead(_PtrAdd(lpFile, nOffset), 1 /*DT_UNICODE*/))
      {
        vFile.push(sFile);
        nOffset += (sFile.length + 1) * 2;
      }

      if (vFile.length == 1)
        sLastDir = oFSO.GetParentFolderName(vFile[0]);
      else
      {
        sLastDir = vFile[0];

        if (vFile[0].slice(-1) != "\\") vFile[0] += "\\";

        for (i = 1; i < vFile.length; ++i)
          vFile[i] = vFile[0] + vFile[i];

        vFile.shift();
      }
    }
    else
    {
      vFile    = AkelPad.MemRead(lpFile, 1 /*DT_UNICODE*/);
      sLastDir = oFSO.GetParentFolderName(vFile);
    }
  }
  else
    vFile = bMultiSelect ? [] : "";

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

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

  return vFile;
}

function BrowseForFolder(sDir, sTitle, nX, nY)
{
  try
  {
    oSys.RegisterCallback(BFFCallback);
  }
  catch (oError)
  {
    MsgBox(sTxtNoCallback);
    return;
  }

  var lpDir    = AkelPad.MemAlloc(260 * 2 /*sizeof(MAX_PATH)*/);
  var lpTitle  = AkelPad.MemAlloc((sTitle.length + 1) * 2);
  var lpBrowse = AkelPad.MemAlloc(_X64 ? 64 : 32 /*sizeof(BROWSEINFO)*/);
  var lpIDL;

  AkelPad.MemCopy(lpDir, oFSO.FolderExists(sDir) ? sDir : sScriptDir, 1 /*DT_UNICODE*/);
  AkelPad.MemCopy(lpTitle, sTitle, 1 /*DT_UNICODE*/);

  AkelPad.MemCopy(_PtrAdd(lpBrowse, 0),                     hDlg, 2 /*DT_QWORD*/); //hWndOwner
  AkelPad.MemCopy(_PtrAdd(lpBrowse, _X64 ? 16 :  8),       lpDir, 2 /*DT_QWORD*/); //pszDisplayName
  AkelPad.MemCopy(_PtrAdd(lpBrowse, _X64 ? 24 : 12),     lpTitle, 2 /*DT_QWORD*/); //lpszTitle
  AkelPad.MemCopy(_PtrAdd(lpBrowse, _X64 ? 32 : 16),  0x00000041, 3 /*DT_DWORD*/); //ulFlags=BIF_NEWDIALOGSTYLE|BIF_RETURNONLYFSDIRS
  AkelPad.MemCopy(_PtrAdd(lpBrowse, _X64 ? 40 : 20), BFFCallback, 2 /*DT_QWORD*/); //lpfn
  AkelPad.MemCopy(_PtrAdd(lpBrowse, _X64 ? 48 : 24),       lpDir, 2 /*DT_QWORD*/); //lParam

  if (lpIDL = oSys.Call("Shell32::SHBrowseForFolderW", lpBrowse))
  {
    oSys.Call("Shell32::SHGetPathFromIDListW", lpIDL, lpDir);
    oSys.Call("Ole32::CoTaskMemFree", lpIDL);
    sDir = AkelPad.MemRead(lpDir, 1 /*DT_UNICODE*/);
  }
  else
    sDir = "";

  oSys.UnregisterCallback(BFFCallback);
  AkelPad.MemFree(lpDir);
  AkelPad.MemFree(lpTitle);
  AkelPad.MemFree(lpBrowse);

  return sDir;

  function BFFCallback(hWnd, uMsg, lParam, lpData)
  {
    if (uMsg == 1 /*BFFM_INITIALIZED*/)
    {
      var hWndNS;
      var hWndTV;
      var oRect1;
      var oRect2;

      SendMessage(hWnd, 0x0080 /*WM_SETICON*/, 0 /*ICON_SMALL*/, hIconSmall);
      SendMessage(hWnd, 0x0467 /*BFFM_SETSELECTIONW*/, 1, lpData);

      //set focus to TreeView
      if (hWndNS = oSys.Call("User32::FindWindowExW", hWnd, 0, "SHBrowseForFolder ShellNameSpace Control", 0))
      {
        if (hWndTV = oSys.Call("User32::FindWindowExW", hWndNS, 0, "SysTreeView32", 0))
        {
          WScript.Sleep(50);
          PostMessage(hWnd, 40 /*WM_NEXTDLGCTL*/, hWndTV, 1);
          PostMessage(hWndTV, 4372 /*TVM_ENSUREVISIBLE*/, 0, SendMessage(hWndTV, 4362 /*TVM_GETNEXTITEM*/, 0x0009 /*TVGN_CARET*/, 0));
        }
      }

      if ((typeof nX != "number") || (typeof nY != "number"))
      {
        oRect1 = {};
        oRect2 = {};
        GetWindowPos(hDlg, oRect1);
        GetWindowPos(hWnd, oRect2);
        nX = oRect1.X + (oRect1.W - oRect2.W) / 2;
        nY = oRect1.Y + (oRect1.H - oRect2.H) / 2;
      }

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

    return 0;
  }
}

function EnterPassword(sFile, sPass)
{
  var lpSize = AkelPad.MemAlloc(8);
  var hDC    = oSys.Call("User32::GetDC", hDlg);
  var sText  = sFile + "\n\n" + sTxtEnterPass;
  var oRect  = {};
  var nEH = Scale.Y(21);
  var nBW = Scale.X(80);
  var nBH = Scale.Y(23);
  var nBX;
  var nTW, nTH;
  var nWX, nWY, nWW, nWH;
  var nWAY2;
  var hWndPass, hWndOK, hWndCancel, hFocus;

  oSys.Call("Gdi32::SetMapMode", hDC, 1 /*MM_TEXT*/);
  oSys.Call("Gdi32::SelectObject", hDC, hGuiFont);
  oSys.Call("Gdi32::GetTextExtentPoint32W", hDC, sFile, sFile.length, lpSize);
  nTW = AkelPad.MemRead(lpSize, 3 /*DT_DWORD*/);
  nTH = AkelPad.MemRead(_PtrAdd(lpSize, 4), 3 /*DT_DWORD*/) * 3;

  oSys.Call("Gdi32::GetTextExtentPoint32W", hDC, sTxtEnterPass, sTxtEnterPass.length, lpSize);
  nTW = Math.max(Scale.X(200), nTW, AkelPad.MemRead(lpSize, 3 /*DT_DWORD*/));

  oSys.Call("User32::ReleaseDC", hDlg, hDC); 
  AkelPad.MemFree(lpSize);

  nBX = nTW - nBW * 2;
  nWW = nTW + 20 + oSys.Call("User32::GetSystemMetrics", 7 /*SM_CXFIXEDFRAME*/) * 2;
  nWH = nTH + nEH + nBH + 35 + oSys.Call("User32::GetSystemMetrics", 8 /*SM_CYFIXEDFRAME*/) * 2 + oSys.Call("User32::GetSystemMetrics", 4 /*SM_CYCAPTION*/);

  GetWindowPos(0, oRect);
  nWAY2 = oRect.Y + oRect.H;
  GetWindowPos(aDlg[IDPDFLV].HWND, oRect);
  nWX = oRect.X + (oRect.W - nWW) / 2;
  GetItemRectLV(aDlg[IDPDFLV].HWND, nPDF, oRect);
  nWY = (oRect.Y2 + nWH < nWAY2) ? oRect.Y2 + 2 : oRect.Y1 - nWH - 2;

  oSys.Call("User32::CreateWindowExW",
    0,             //dwExStyle
    sClass,        //lpClassName
    sDlgTitle,     //lpWindowName
    0x90C80000,    //dwStyle=WS_POPUP|WS_VISIBLE|WS_CAPTION|WS_SYSMENU
    nWX,           //x
    nWY,           //y
    nWW,           //nWidth
    nWH,           //nHeight
    hDlg,          //hWndParent
    0,             //hMenu
    hInstDLL,      //hInstance
    PassCallback); //Script function callback. To use it class must be registered by WindowRegisterClass.

  oSys.Call("User32::EnableWindow", hDlg, 0);
  AkelPad.WindowGetMessage();

  return sPass;

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

    if (uMsg == 1 /*WM_CREATE*/)
    {
      if (! hMainWnd)
        SendMessage(hWnd, 0x0080 /*WM_SETICON*/, 0 /*ICON_SMALL*/, hIconSmall);

      SendMessage(oSys.Call("User32::CreateWindowExW",
        0,          //dwExStyle
        "STATIC",   //lpClassName
        sText,      //lpWindowName
        0x50000080, //dwStyle=WS_CHILD|WS_VISIBLE|SS_NOPREFIX
        10,         //x
        10,         //y
        nTW,        //nWidth
        nTH,        //nHeight
        hWnd,       //hWndParent
        -1,         //ID
        hInstDLL,   //hInstance
        0),         //lpParam
        48 /*WM_SETFONT*/, hGuiFont, 1);

      SendMessage(oSys.Call("User32::CreateWindowExW",
        0x00000200, //dwExStyle=WS_EX_CLIENTEDGE
        "EDIT",     //lpClassName
        sPass,      //lpWindowName
        0x50010080, //dwStyle=WS_CHILD|WS_VISIBLE|WS_TABSTOP|ES_AUTOHSCROLL
        10,         //x
        nTH + 15,   //y
        nTW,        //nWidth
        nEH,        //nHeight
        hWnd,       //hWndParent
        3000,       //ID
        hInstDLL,   //hInstance
        0),         //lpParam
        48 /*WM_SETFONT*/, hGuiFont, 1);

      for (i = 0; i < 2; ++i)
        SendMessage(oSys.Call("User32::CreateWindowExW",
          0,                            //dwExStyle
          "BUTTON",                     //lpClassName
          i == 0 ? sTxtOK : sTxtCancel, //lpWindowName
          0x50010000,                   //dwStyle=WS_CHILD|WS_VISIBLE|WS_TABSTOP
          nBX + (nBW + 10) * i,         //x
          nTH + nEH + 25,               //y
          nBW,                          //nWidth
          nBH,                          //nHeight
          hWnd,                         //hWndParent
          i + 3001,                     //ID
          hInstDLL,                     //hInstance
          0),                           //lpParam
          48 /*WM_SETFONT*/, hGuiFont, 1);

      hWndPass   = oSys.Call("User32::GetDlgItem", hWnd, 3000);
      hWndOK     = oSys.Call("User32::GetDlgItem", hWnd, 3001);
      hWndCancel = oSys.Call("User32::GetDlgItem", hWnd, 3002);
      hFocus     = hWndPass;

      SendMessage(hWndPass, 197 /*EM_SETLIMITTEXT*/, 32, 0);
      SendMessage(hWndPass, 177 /*EM_SETSEL*/, 0, -1);
      PostMessage(hWnd, 273 /*WM_COMMAND*/, MkLong(3000, 0x0300 /*EN_CHANGE*/), hWndPass);
    }

    else if (uMsg == 6 /*WM_ACTIVATE*/)
    {
      if (wParam == 0 /*WA_INACTIVE*/)
        hFocus = oSys.Call("User32::GetFocus");
    }

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

    else if (uMsg == 256 /*WM_KEYDOWN*/)
    {
      if (wParam == 0x0D /*VK_RETURN*/)
      {
        if ((oSys.Call("User32::GetFocus") == hWndPass) && SendMessage(hWndPass, 14 /*WM_GETTEXTLENGTH*/, 0, 0))
          PostMessage(hWnd, 273 /*WM_COMMAND*/, 3001, hWndOK);
      }
    }

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

      if (nID == 3000)
      {
        if (nCode == 0x0100 /*EN_SETFOCUS*/)
          PostMessage(hWndOK, 244 /*BM_SETSTYLE*/, SendMessage(hWndPass, 14 /*WM_GETTEXTLENGTH*/, 0, 0) ? 1 /*BS_DEFPUSHBUTTON*/ : 0 /*BS_PUSHBUTTON*/, 1);
        else if (nCode == 0x0200 /*EN_KILLFOCUS*/)
          SendMessage(hWndOK, 244 /*BM_SETSTYLE*/, 0 /*BS_PUSHBUTTON*/, 1);
        else if (nCode == 0x0300 /*EN_CHANGE*/)
        {
          oSys.Call("User32::EnableWindow", hWndOK, SendMessage(hWndPass, 14 /*WM_GETTEXTLENGTH*/, 0, 0));
          PostMessage(hWndOK, 244 /*BM_SETSTYLE*/, SendMessage(hWndPass, 14 /*WM_GETTEXTLENGTH*/, 0, 0) ? 1 /*BS_DEFPUSHBUTTON*/ : 0 /*BS_PUSHBUTTON*/, 1);
        }
      }
      else if ((nID == 3001) || (nID == 3002) || (nID == 2 /*IDCANCEL*/))
        PostMessage(hWnd, 16 /*WM_CLOSE*/, (nID == 3001), 0);
    }

    else if (uMsg == 16 /*WM_CLOSE*/)
    {
      if (wParam)
        sPass = GetWindowText(hWndPass);
      else
        sPass = undefined;

      oSys.Call("User32::EnableWindow", hDlg, 1);
      oSys.Call("User32::DestroyWindow", hWnd);
    }

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

    return 0;
  }
}

function MsgBox(sText, sTitle, hWndOwn, aBut, nDefBut)
{
  var lpSize = AkelPad.MemAlloc(8);
  var hDC    = oSys.Call("User32::GetDC", hDlg);
  var oRect  = {};
  var nTW    = 0;
  var nTH    = 0;
  var nBW    = Scale.X(70);
  var nTX;
  var nBX;
  var nCW;
  var nWX, nWY, nWW, nWH;
  var aLine;
  var hFocus;
  var nButton;
  var i;

  if (typeof sText != "string")
    sText = sText.toString();

  if (! sTitle)
    sTitle = sDlgTitle;

  if (! hWndOwn)
  {
    if (hDlg)
      hWndOwn = hDlg;
    else if (hMainWnd)
      hWndOwn = hMainWnd;
  }

  if ((typeof aBut != "object") || (! aBut.length))
    aBut = [sTxtOK];

  if ((typeof nDefBut != "number") || (nDefBut < 0) || (nDefBut >= aBut.length))
    nDefBut = 0;

  oSys.Call("Gdi32::SetMapMode", hDC, 1 /*MM_TEXT*/);
  oSys.Call("Gdi32::GetTextExtentPoint32W", hDC, sDlgTitle, sDlgTitle.length, lpSize);
  nCW = AkelPad.MemRead(lpSize, 3 /*DT_DWORD*/) + oSys.Call("User32::GetSystemMetrics", 49 /*SM_CXSMICON*/) + oSys.Call("User32::GetSystemMetrics", 30 /*SM_CXSIZE*/) + 10;

  oSys.Call("Gdi32::SelectObject", hDC, hGuiFont);

  aLine = sText.split("\n");
  for (i = 0; i < aLine.length; ++i)
  {
    oSys.Call("Gdi32::GetTextExtentPoint32W", hDC, aLine[i], aLine[i].length, lpSize);
    nTW = Math.max(nTW, AkelPad.MemRead(lpSize, 3 /*DT_DWORD*/));
    nTH = Math.max(nTH, AkelPad.MemRead(_PtrAdd(lpSize, 4), 3 /*DT_DWORD*/));
  }

  nTH = nTH * aLine.length;

  for (i = 0; i < aBut.length; ++i)
  {
    oSys.Call("Gdi32::GetTextExtentPoint32W", hDC, aBut[i], aBut[i].length, lpSize)
    nBW = Math.max(nBW, AkelPad.MemRead(lpSize, 3 /*DT_DWORD*/) + 8);
  }

  oSys.Call("User32::ReleaseDC", hDlg, hDC); 
  AkelPad.MemFree(lpSize);

  nCW = Math.max(Scale.X(120), nCW, nTW, nBW * aBut.length + 10 * (aBut.length - 1)) + 20;
  nWW = nCW + oSys.Call("User32::GetSystemMetrics", 7 /*SM_CXFIXEDFRAME*/) * 2;
  nWH = nTH + Scale.Y(23) + 35 + oSys.Call("User32::GetSystemMetrics", 8 /*SM_CYFIXEDFRAME*/) * 2 + oSys.Call("User32::GetSystemMetrics", 4 /*SM_CYCAPTION*/);
  nBX = (nCW - nBW * aBut.length - 10 * (aBut.length - 1)) / 2;
  nTX = (nCW - nTW) / 2;

  GetWindowPos(hWndOwn, oRect);
  nWX = oRect.X + (oRect.W - nWW) / 2;
  nWY = oRect.Y + (oRect.H - nWH) / 2;

  oSys.Call("User32::CreateWindowExW",
    0,            //dwExStyle
    sClass,       //lpClassName
    sTitle,       //lpWindowName
    0x90C80000,   //dwStyle=WS_POPUP|WS_VISIBLE|WS_CAPTION|WS_SYSMENU
    nWX,          //x
    nWY,          //y
    nWW,          //nWidth
    nWH,          //nHeight
    hWndOwn,      //hWndParent
    0,            //hMenu
    hInstDLL,     //hInstance
    MsgCallback); //Script function callback. To use it class must be registered by WindowRegisterClass.

  oSys.Call("User32::EnableWindow", hWndOwn, 0);
  AkelPad.WindowGetMessage();

  return nButton;

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

    if (uMsg == 1 /*WM_CREATE*/)
    {
      if (! hMainWnd)
        SendMessage(hWnd, 0x0080 /*WM_SETICON*/, 0 /*ICON_SMALL*/, hIconSmall);

      SendMessage(oSys.Call("User32::CreateWindowExW",
        0,          //dwExStyle
        "STATIC",   //lpClassName
        sText,      //lpWindowName
        0x50000080, //dwStyle=WS_CHILD|WS_VISIBLE|SS_NOPREFIX
        nTX,        //x
        10,         //y
        nTW,        //nWidth
        nTH,        //nHeight
        hWnd,       //hWndParent
        -1,         //ID
        hInstDLL,   //hInstance
        0),         //lpParam
        48 /*WM_SETFONT*/, hGuiFont, 1);

      for (i = 0; i < aBut.length; ++i)
        SendMessage(oSys.Call("User32::CreateWindowExW",
          0,                    //dwExStyle
          "BUTTON",             //lpClassName
          aBut[i],              //lpWindowName
          0x50010000,           //dwStyle=WS_CHILD|WS_VISIBLE|WS_TABSTOP
          nBX + (nBW + 10) * i, //x
          nTH + 25,             //y
          nBW,                  //nWidth
          Scale.Y(23),          //nHeight
          hWnd,                 //hWndParent
          i + 4000,             //ID
          hInstDLL,             //hInstance
          0),                   //lpParam
          48 /*WM_SETFONT*/, hGuiFont, 1);

      oSys.Call("User32::DefDlgProcW", hWnd, 1025 /*DM_SETDEFID*/, nDefBut + 4000, 0);
      hFocus = oSys.Call("User32::GetDlgItem", hWnd, nDefBut + 4000);
    }

    else if (uMsg == 6 /*WM_ACTIVATE*/)
    {
      if (wParam == 0 /*WA_INACTIVE*/)
        hFocus = oSys.Call("User32::GetFocus");
    }

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

    else if (uMsg == 273 /*WM_COMMAND*/)
      PostMessage(hWnd, 16 /*WM_CLOSE*/, LoWord(wParam), 0);

    else if (uMsg == 16 /*WM_CLOSE*/)
    {
      if (wParam >= 4000)
        nButton = wParam - 4000;
      else
        nButton = -1;

      oSys.Call("User32::EnableWindow", hWndOwn, 1);
      oSys.Call("User32::DestroyWindow", hWnd);
    }

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

    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 ReadIni()
{
  try
  {
    eval(ReadFile(WScript.ScriptFullName.replace(/js$/i, "ini"), 1));
  }
  catch (oError)
  {}

  aDlg.W = Math.max(Scale.X(aDlg.W), aDlg.MinW);
  aDlg.H = Math.max(Scale.Y(aDlg.H), aDlg.MinH);
}

function WriteIni()
{
  var sText;
  var i;

  if (! bSaveList)
  {
    nPDF = -1;
    aPDF = [];
  }

  if (! bSavePass)
  {
    sOwnerPass = "";
    sUserPass  = "";

    for (i = 0; i < aPDF.length; ++i)
      aPDF[i].P = "";
  }

  sText =
    'aDlg.X='      + aDlg.X + ';\r\n' +
    'aDlg.Y='      + aDlg.Y + ';\r\n' +
    'aDlg.W='      + Scale.UX(aDlg.W) + ';\r\n' +
    'aDlg.H='      + Scale.UY(aDlg.H) + ';\r\n' +
    'aDlg.Max='    + oSys.Call("User32::IsZoomed", hDlg) + ';\r\n' +
    'nTab='        + nTab + ';\r\n' +
    'bCollateW='   + bCollateW + ';\r\n' +
    'bShuffleW='   + bShuffleW + ';\r\n' +
    'bSplitAll='   + bSplitAll + ';\r\n' +
    'bWaterAll='   + bWaterAll + ';\r\n' +
    'nWater='      + nWater + ';\r\n' +
    'nBook='       + nBook + ';\r\n' +
    'bUTF8='       + bUTF8 + ';\r\n' +
    'bBOM='        + bBOM + ';\r\n' +
    'nData='       + nData + ';\r\n' +
    'sWaterAdd="'  + EscapeStr(sWaterAdd) + '";\r\n' +
    'sWaterPDF="'  + EscapeStr(sWaterPDF) + '";\r\n' +
    'sBookTXT="'   + EscapeStr(sBookTXT) + '";\r\n' +
    'sDataTXT="'   + EscapeStr(sDataTXT) + '";\r\n' +
    'sPDFtkDir="'  + EscapeStr(sPDFtkDir) + '";\r\n' +
    'sPDFReader="' + EscapeStr(sPDFReader) + '";\r\n' +
    'sTXTEditor="' + EscapeStr(sTXTEditor) + '";\r\n' +
    'sLastDir="'   + EscapeStr(sLastDir) + '";\r\n' +
    'nAfter='      + nAfter + ';\r\n' +
    'bSaveList='   + bSaveList + ';\r\n' +
    'bSavePass='   + bSavePass + ';\r\n' +
    'bPassProt='   + bPassProt + ';\r\n' +
    'sOwnerPass="' + EscapeStr(sOwnerPass) + '";\r\n' +
    'sUserPass="'  + EscapeStr(sUserPass) + '";\r\n' +
    'bTopPrint='   + bTopPrint + ';\r\n' +
    'bLowPrint='   + bLowPrint + ';\r\n' +
    'bModCont='    + bModCont + ';\r\n' +
    'bAssembly='   + bAssembly + ';\r\n' +
    'bCopyCont='   + bCopyCont + ';\r\n' +
    'bScrRead='    + bScrRead + ';\r\n' +
    'bModAnnot='   + bModAnnot + ';\r\n' +
    'bFillIn='     + bFillIn + ';\r\n' +
    'nPDF='        + nPDF + ';\r\naPDF=[';

  for (i = 0; i < aPDF.length; ++i)
    sText +=
      '{' +
      'F:"' + EscapeStr(aPDF[i].F) + '",' +
      'R:"' + EscapeStr(aPDF[i].R) + '",' +
      'P:"' + EscapeStr(aPDF[i].P) + '"}' +
      ((i == aPDF.length - 1) ? '' : ',');

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

  WriteFile(WScript.ScriptFullName.replace(/js$/i, "ini"), sText, 1);
}

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

function GetLangStrings()
{
  if ((hMainWnd && (AkelPad.GetLangId(0 /*LANGID_FULL*/) == 1045)) || ((! hMainWnd) && (oSys.Call("Kernel32::GetUserDefaultLangID") == 1045))) //Polish
  {
    //main dialog box
    sTxtCollate        = 'Zestaw';
    sTxtShuffle        = 'Potasuj';
    sTxtSplit          = 'Wydziel';
    sTxtWatermark      = 'Znak wodny';
    sTxtBookmarks      = 'Zakładki';
    sTxtPDFInfo        = 'PDF info';
    sTxtSettings       = 'Ustawienia';
    sTxtCollateDescr   = 'Zbiera strony ze wszystkich źródłowych dokumentów PDF i tworzy nowy plik PDF.\nMożesz użyć tej operacji w celu wydzielenia, obrotu i połączenia stron PDF.\nKolejność stron w nowym pliku PDF jest określona przez podane zakresy stron.';
    sTxtShuffleDescr   = 'Działa podobnie jak "Zestaw" z tą różnicą, że pobiera po jednej stronie z każdego zakresu aby dołączyć je do wyjściowego pliku PDF.\nJeśli w jednym zakresie zabraknie stron, operacja jet kontynuowana dla pozostałych zakresów.\nTa funkcja jest przeznaczona do zestawienia stron PDF po zeskanowaniu dokumentów papierowych.';
    sTxtSplitDescr     = 'Dzieli jeden lub wszystkie źródłowe dokumenty PDF na pojedyncze strony.\nKażda strona zostanie zapisana w odrębnym pliku nazwanym: NazwaŻródłowegoDokumentu_NumerStronyŹródłowej.pdf';
    sTxtWaterDescr     = 'Wstawia znak wodny jako tło lub stempel do jednego lub wszystkich dokumentów PDF.';
    sTxtInsertWater    = 'Wstaw znak wodny do dokumentu wyjściowego';
    sTxtAllDocs        = 'Wszystkie dokumenty';
    sTxtAddToName      = 'Dodaj do nazwy:';
    sTxtBackgr         = 'Obraz tła';
    sTxtMultiBackgr    = 'Wiele obrazów tła';
    sTxtStamp          = 'Stempel';
    sTxtMultiStamp     = 'Wiele stempli';
    sTxtWaterPDF       = 'Plik PDF ze znakiem wodnym (nie może być zabezpieczony hasłem):';
    sTxtExportFrom     = 'Eksport z pojedynczego dokumentu źródłowego PDF do pliku TXT';
    sTxtImportTo       = 'Import do dokumentu PDF z poniższego pliku TXT:';
    sTxtDumpAnnots     = 'Dump data annotations to TXT file';
    sTxtDumpFields     = 'Dump data fields to TXT file';
    sTxtDumpInfo       = 'Dump data info to TXT file';
    sTxtUpdateInfo     = 'Update data info in PDF document from following TXT file:';
    sTxtPDFtkDir       = 'Katalog PDFtk:';
    sTxtPDFReader      = 'Czytnik PDF:';
    sTxtTXTEditor      = 'Edytor TXT:';
    sTxtAfterCreate    = 'Po utworzeniu plików wyjściowych:';
    sTxtShowMessage    = 'Pokaż komunikat';
    sTxtOpenNewFile    = 'Otwórz nowy plik';
    sTxtOpenOutDir     = 'Otwórz katalog docelowy';
    sTxtKeepList       = 'Zachowaj listę PDF przy wyjściu';
    sTxtKeepPass       = 'Zachowaj hasła';
    sTxtSourcePDFs     = 'Źródłowe dokumenty PDF';
    sTxtPageCount      = 'Liczba stron';
    sTxtPagesToCopy    = 'Zakresy stron do skopiowania';
    sTxtRotation       = 'Obrót';
    sTxtOutPages       = 'Stron wyjściowych';
    sTxtAdd            = '&Dodaj';
    sTxtDuplicate      = 'Powiel';
    sTxtRemove         = 'Usuń';
    sTxtClear          = 'Wyczyść';
    sTxtMoveUp         = 'W górę';
    sTxtMoveDown       = 'W dół';
    sTxtRanges         = 'Zakresy';
    sTxtOpen           = 'Otwórz';
    sTxtRefresh        = 'Odśwież';
    sTxtTotalPages     = 'Suma stron: ';
    sTxtTotalOutPages  = 'Suma stron wyjściowych: ';
    sTxtReading        = 'czyta';
    sTxtOutputPermiss  = 'Wyjściowy dokument PDF - uprawnienia';
    sTxtPassProt       = 'Zabezpiecz hasłami';
    sTxtOwner          = 'Właściciel:';
    sTxtUser           = 'Użytkownik:';
    sTxtTopPrint       = 'Druk wysokiej jakości';
    sTxtLowPrint       = 'Druk niskiej jakości';
    sTxtModCont        = 'Modyfikacja zawartości';
    sTxtAssembly       = 'Składanie dokumentów';
    sTxtCopyCont       = 'Kopiowanie zawartości';
    sTxtScrRead        = 'Czytanie z ekranu';
    sTxtModAnnot       = 'Modyfikacja przypisów';
    sTxtFillIn         = 'Wypełnianie pól formularza';
    sTxtAllPerm        = 'Wszystkie uprawnienia';
    sTxtCreateFiles    = '&Utwórz plik(i)';
    sTxtOpenPDF        = 'Otwórz &PDF';
    sTxtOpenTXT        = 'Otwórz &TXT';
    sTxtOpenDir        = 'Otwórz &katalog';
    sTxtPDFtkHelp      = 'Pomoc PDFtk';
    sTxtPDFtkSite      = 'Strona PDFtk';
    sTxtExit           = 'Zakończ';
    //edit ranges
    sTxtPages          = 'Strony';
    sTxtFrom           = 'Od:';
    sTxtTo             = 'Do:';
    sTxtFromEnd        = 'Od końca';
    sTxtNumLastPage    = 'numer ostatniej strony';
    sTxtAll            = 'Wszystkie';
    sTxtEven           = 'Parzyste';
    sTxtOdd            = 'Nieparzyste';
    sTxtNone           = 'Brak';
    sTxtNorth          = 'Północ';
    sTxtEast           = 'Wschód';
    sTxtSouth          = 'Południe';
    sTxtWest           = 'Zachód';
    sTxtLeft           = 'W lewo';
    sTxtRight          = 'W prawo';
    sTxtDown           = 'Do dołu';
    sTxtNew            = 'Nowy';
    //EnterPassword()
    sTxtEnterPass      = 'Podaj hasło właściciela dla dokumentu PDF:';
    //MsgBox()
    sTxtNoFile         = 'Ten plik nie istnieje.';
    sTxtNoWaterFile    = 'Brak pliku PDF ze znakiem wodnym.';
    sTxtNoPDFReader    = 'Nie ma czytnika plików PDF.';
    sTxtNoTXTEditor    = 'Nie ma edytora plików TXT.';
    sTxtCantExec       = 'Nie można wykonać tego polecenia:';
    sTxtNoCallback     = 'Nie można zarejestrować funkcji zwrotnej.';
    sTxtPDFtkError     = 'Błąd PDFtk';
    sTxtNoTempDir      = 'Nie można utworzyć katalogu tymczasowego.';
    sTxtWriteError     = 'Błąd zapisu do tego pliku.';
    sTxtSelOtherName   = 'Wybierz inną nazwę lub odblokuj plik.';
    sTxtUnlockFile     = 'Odblokuj plik i wciśnij "Ponów"';
    sTxtTooManyDocs    = 'Za dużo dokumentów lub zakresów jest do przetworzenia.\nNie można utworzyć dokumentu wyjściowego.'
    sTxtCreated        = 'Utworzono:';
    sTxtSplitted       = 'Podzielono:';
    sTxtFileExists     = 'Ten plik już istnieje. Czy chcesz go zastąpić?';
    sTxtReplace        = 'Zastąp';
    sTxtReplaceAll     = 'Zastąp wszystkie';
    sTxtSkip           = 'Pomiń';
    sTxtSkipAll        = 'Pomiń wszystkie';
    sTxtRetry          = 'Ponów';
    sTxtInvalidChar    = 'Nieprawidłowy znak w nazwie pliku.';
    sTxtNoPDFBookmarks = 'Ten dokument PDF nie zawiera zakładek.';
    sTxtNoTXTBookmarks = 'Ten plik TXT nie zawiera zakładek.';
    sTxtBookmarksHelp  = 'Każdy wiersz pliku z zakładkami powinien zawierać opis jednej zakładki w formacie:\n[TAB...]Tekst zakładki/Numer strony w dokumencie PDF\n\nPrzykład:\nZakładka - poziom 0 (bez TAB na początku wiersza)/2\n\tZakładka - poziom 1 (jeden znak TAB na początku wiersza)/14\n\t\tZakładka - poziom 2 (dwa znaki TAB na początku wiersza)/29\n\tZakładka - poziom 1 (jeden znak TAB na początku wiersza)/35\nZakładka - poziom 0 (bez TAB na początku wiersza)/47';
    sTxtNoPDFData      = 'Ten dokument PDF nie zawiera wymaganych danych.';
    //GetOpenSaveFileName()
    sTxtSelWaterPDF    = 'Wybierz plik PDF zawierający znaki wodne';
    sTxtSelBookTXT     = 'Wybierz plik TXT zawierający zakładki';
    sTxtSelDataTXT     = 'Wybierz plik TXT zawierający dane';
    sTxtSelPDFReader   = 'Wybierz czytnik PDF';
    sTxtSelTXTEditor   = 'Wybierz edytor TXT';
    sTxtSelSourcePDFs  = 'Wybierz źródłowe dokumenty PDF';
    //BrowseForFolder()
    sTxtSelOutDir      = 'Wybierz katalog docelowy:';
    sTxtSelPDFtkDir    = 'Wybierz katalog zawierający PDFtk.exe:';
    sTxtSelAkelDir     = 'Wybierz katalog zawierający AkelPad.exe:';
    //common
    sTxtOK             = 'OK';
    sTxtCancel         = 'Anuluj';
  }
  //Russian translation by YuS
  else if ((hMainWnd && (AkelPad.GetLangId(0 /*LANGID_FULL*/) == 1049)) || ((! hMainWnd) && (oSys.Call("Kernel32::GetUserDefaultLangID") == 1049)))
  {
    sTxtCollate        = 'Слияние';
    sTxtShuffle        = 'Перемешивание';
    sTxtSplit          = 'Разделение';
    sTxtWatermark      = 'Водяные знаки';
    sTxtBookmarks      = 'Закладки';
    sTxtPDFInfo        = 'PDF инфо';
    sTxtSettings       = 'Настройки';
    sTxtCollateDescr   = 'Слияние страниц из всех исходных PDF-документов в новом файле PDF. Это можно использовать для разделения, поворота и слияния страниц. Порядок страниц в новом файле PDF задается порядком диапазона страниц.';
    sTxtShuffleDescr   = 'Работает как и "Слияние", только страницы выбираются из каждого диапазона поочередно. Если у диапазона заканчиваются страницы, переходит к оставшимися диапазонам. Предназначена для сопоставления страниц PDF после сканирования бумажных документов.';
    sTxtSplitDescr     = 'Разделение одного или всех исходных PDF-документов на отдельные страницы. Каждая страница будет сохранена в отдельном файле с именем: ИсходноеИмяДокумента_ИсходныйНомерСтраницы.pdf';
    sTxtWaterDescr     = 'Вставить водяной знак фоном или штампом во все PDF?';
    sTxtInsertWater    = 'Вставить водяной знак в выходной PDF';
    sTxtAllDocs        = 'Все документы';
    sTxtAddToName      = 'Добавить в имя:';
    sTxtBackgr         = 'Фон';
    sTxtMultiBackgr    = 'Мультифон';
    sTxtStamp          = 'Штамп';
    sTxtMultiStamp     = 'Мультиштамп';
    sTxtWaterPDF       = 'Файл PDF с водяным знаком (без защиты паролем):';
    sTxtExportFrom     = 'Экспорт из одного исходного PDF в TXT файл';
    sTxtImportTo       = 'Импорт в PDF из следующего TXT файла:';
    sTxtDumpAnnots     = 'Дамп примечаний в TXT файл';
    sTxtDumpFields     = 'Дамп полей в TXT файл';
    sTxtDumpInfo       = 'Дамп информации в TXT файл';
    sTxtUpdateInfo     = 'Обновить информацию в PDF из TXT файла:';
    sTxtPDFtkDir       = 'PDFtk каталог:';
    sTxtPDFReader      = 'PDF читалка:';
    sTxtTXTEditor      = 'TXT редактор:';
    sTxtAfterCreate    = 'После создания вых. файла(ов):';
    sTxtShowMessage    = 'Показать сообщение';
    sTxtOpenNewFile    = 'Открыть новый файл';
    sTxtOpenOutDir     = 'Открыть вых. каталог';
    sTxtKeepList       = 'Хранить список PDF при вых.';
    sTxtKeepPass       = 'Хранить пароли';
    sTxtSourcePDFs     = 'Исходные PDF документы';
    sTxtPageCount      = 'Кол-во стр-ц';
    sTxtPagesToCopy    = 'Диап-н стр-ц в Копии';
    sTxtRotation       = 'Вращение';
    sTxtOutPages       = 'Вых. стр-цы';
    sTxtAdd            = 'Доба&вить';
    sTxtDuplicate      = 'Дубликат';
    sTxtRemove         = 'Удалить';
    sTxtClear          = 'Очистить';
    sTxtMoveUp         = 'Вверх';
    sTxtMoveDown       = 'Вниз';
    sTxtRanges         = 'Диапазон';
    sTxtOpen           = 'Открыть';
    sTxtRefresh        = 'Обновить';
    sTxtTotalPages     = 'Всего стр.: ';
    sTxtTotalOutPages  = 'Всего вых. стр.: ';
    sTxtReading        = 'чтение';
    sTxtOutputPermiss  = 'Выходной PDF - разрешения';
    sTxtPassProt       = 'Защита паролем';
    sTxtOwner          = 'Владелец:';
    sTxtUser           = 'Польз-тель:';
    sTxtTopPrint       = 'Высококачест. печать';
    sTxtLowPrint       = 'Низкокачест. печать';
    sTxtModCont        = 'Изменение контента';
    sTxtAssembly       = 'Слияние';
    sTxtCopyCont       = 'Копирование контента';
    sTxtScrRead        = 'Чтение экрана';
    sTxtModAnnot       = 'Изменение примечаний';
    sTxtFillIn         = 'Заполнение полей формы';
    sTxtAllPerm        = 'Все разрешения';
    sTxtCreateFiles    = '&Созд. файл(ы)';
    sTxtOpenPDF        = 'Открыть &PDF';
    sTxtOpenTXT        = 'Открыть &TXT';
    sTxtOpenDir        = 'Откр. &каталог';
    sTxtPDFtkHelp      = 'PDFtk помощь';
    sTxtPDFtkSite      = 'PDFtk сайт';
    sTxtExit           = 'Выход';
    //edit ranges
    sTxtPages          = 'Страницы';
    sTxtFrom           = 'От:';
    sTxtTo             = 'До:';
    sTxtFromEnd        = 'С конца';
    sTxtNumLastPage    = 'номер последней стр.';
    sTxtAll            = 'Все';
    sTxtEven           = 'Четн.';
    sTxtOdd            = 'Нечет.';
    sTxtNone           = 'Нет';
    sTxtNorth          = 'Север';
    sTxtEast           = 'Восток';
    sTxtSouth          = 'Юг';
    sTxtWest           = 'Запад';
    sTxtLeft           = 'Влево';
    sTxtRight          = 'Вправо';
    sTxtDown           = 'Вниз';
    sTxtNew            = 'Новый';
    //EnterPassword()
    sTxtEnterPass      = 'Пароль владельца PDF-док.:';
    //MsgBox()
    sTxtNoFile         = 'Этот файл отсутствует.';
    sTxtNoWaterFile    = 'Файл PDF не содержит водяных знаков .';
    sTxtNoPDFReader    = 'Не указана PDF-читалка.';
    sTxtNoTXTEditor    = 'Не указан редактор TXT.';
    sTxtCantExec       = 'Команду невозможно выполнить:';
    sTxtNoCallback     = 'Невозможно зарегистрировать функцию callback.';
    sTxtPDFtkError     = 'PDFtk Ошибка';
    sTxtNoTempDir      = 'Невозможно создать временный каталог.';
    sTxtWriteError     = 'Ошибка записи файла.';
    sTxtSelOtherName   = 'Выберите другое наименование или разблокируйте файл.';
    sTxtUnlockFile     = 'Разблокируйте файл и нажмите "Повтор"';
    sTxtTooManyDocs    = 'Слишком большой документ или диапазон.\nНевозможно создать выходной документ.'
    sTxtCreated        = 'Создание:';
    sTxtSplitted       = 'Разделение:';
    sTxtFileExists     = 'Этот файл уже существует. Заменить?';
    sTxtReplace        = 'Заменить';
    sTxtReplaceAll     = 'Заменить всё';
    sTxtSkip           = 'Пропустить';
    sTxtSkipAll        = 'Пропустить всё';
    sTxtRetry          = 'Повтор';
    sTxtInvalidChar    = 'Некорректные символы в имени файла.';
    sTxtNoPDFBookmarks = 'Этот PDF документ не содержит закладок.';
    sTxtNoTXTBookmarks = 'Этот TXT файл не содержит закладок.';
    sTxtBookmarksHelp  = 'Каждая строка файла закладок должна содержать описание одной закладки в следующем формате:\n[TAB...]Текст закладки/номер_стр в PDF документе\n\nПример:\nЗакладка - уровень 0 (без TAB в начале строки)/2\n\tЗакладка - уровень 1 (один TAB символ в начале строки)/14\n\t\tЗакладка - уровень 2 (два TAB символа в начале строки)/29\n\tЗакладка - уровень 1 (один TAB символ в начале строки)/35\nЗакладка - уровень 0 (без TAB в начале строки)/47';
    sTxtNoPDFData      = 'Этот PDF документ не содержит требуемых данных.';
    //GetOpenSaveFileName()
    sTxtSelWaterPDF    = 'Выберите PDF файл с водяныи знаками';
    sTxtSelBookTXT     = 'Выберите TXT файл с примечаниями';
    sTxtSelDataTXT     = 'Выберите TXT файл с данными';
    sTxtSelPDFReader   = 'Выберите PDF читалку';
    sTxtSelTXTEditor   = 'Выберите TXT редактор';
    sTxtSelSourcePDFs  = 'Выберите исходный PDF документ(ы)';
    //BrowseForFolder()
    sTxtSelOutDir      = 'Выберите выходной каталог:';
    sTxtSelPDFtkDir    = 'Выберите каталог с файлом PDFtk.exe:';
    sTxtSelAkelDir     = 'Выберите каталог с файлом AkelPad.exe:';
    //common
    sTxtOK             = 'OK';
    sTxtCancel         = 'Отмена';
  }
  else
  {
    //main dialog box
    sTxtCollate        = 'Collate';
    sTxtShuffle        = 'Shuffle';
    sTxtSplit          = 'Split';
    sTxtWatermark      = 'Watermark';
    sTxtBookmarks      = 'Bookmarks';
    sTxtPDFInfo        = 'PDF info';
    sTxtSettings       = 'Settings';
    sTxtCollateDescr   = 'Assembles pages from all source PDF documents to create new PDF file.\nYou can use this operation to split, rotate and merge PDF pages.\nPage order in new PDF file is specified by the order of the given page ranges.';
    sTxtShuffleDescr   = 'Works like "Collate" operation except that it takes one page at a time from each page range to assemble the output PDF.\nIf one range runs out of pages, it continues with the remaining ranges.\nThis feature is designed to collate PDF pages after scanning paper documents.';
    sTxtSplitDescr     = 'Splits one or all source PDF documents into individual pages.\nEach page will be saved in a separate file named: SourceDocumentName_SourcePageNumber.pdf';
    sTxtWaterDescr     = 'Inserts a watermark as the background or stamp into one or all PDF documents.';
    sTxtInsertWater    = 'Insert watermark into output PDF document';
    sTxtAllDocs        = 'All documents';
    sTxtAddToName      = 'Add to name:';
    sTxtBackgr         = 'Background';
    sTxtMultiBackgr    = 'MultiBackground';
    sTxtStamp          = 'Stamp';
    sTxtMultiStamp     = 'MultiStamp';
    sTxtWaterPDF       = 'Watermark PDF file (cannot be password-protected):';
    sTxtExportFrom     = 'Export from single source PDF document to TXT file';
    sTxtImportTo       = 'Import to PDF document from following TXT file:';
    sTxtDumpAnnots     = 'Dump data annotations to TXT file';
    sTxtDumpFields     = 'Dump data fields to TXT file';
    sTxtDumpInfo       = 'Dump data info to TXT file';
    sTxtUpdateInfo     = 'Update data info in PDF document from following TXT file:';
    sTxtPDFtkDir       = 'PDFtk directory:';
    sTxtPDFReader      = 'PDF reader:';
    sTxtTXTEditor      = 'TXT editor:';
    sTxtAfterCreate    = 'After creating output file(s):';
    sTxtShowMessage    = 'Show message';
    sTxtOpenNewFile    = 'Open new file';
    sTxtOpenOutDir     = 'Open output directory';
    sTxtKeepList       = 'Kepp PDF list on exit';
    sTxtKeepPass       = 'Keep passwords';
    sTxtSourcePDFs     = 'Source PDF documents';
    sTxtPageCount      = 'Page count';
    sTxtPagesToCopy    = 'Page ranges to copy';
    sTxtRotation       = 'Rotation';
    sTxtOutPages       = 'Output pages';
    sTxtAdd            = '&Add';
    sTxtDuplicate      = 'Duplicate';
    sTxtRemove         = 'Remove';
    sTxtClear          = 'Clear';
    sTxtMoveUp         = 'Move up';
    sTxtMoveDown       = 'Move down';
    sTxtRanges         = 'Ranges';
    sTxtOpen           = 'Open';
    sTxtRefresh        = 'Refresh';
    sTxtTotalPages     = 'Total pages: ';
    sTxtTotalOutPages  = 'Total output pages: ';
    sTxtReading        = 'reading';
    sTxtOutputPermiss  = 'Output PDF document - permissions';
    sTxtPassProt       = 'Passwords protection';
    sTxtOwner          = 'Owner:';
    sTxtUser           = 'User:';
    sTxtTopPrint       = 'Top quality printing';
    sTxtLowPrint       = 'Lower quality printing';
    sTxtModCont        = 'Modify contents';
    sTxtAssembly       = 'Assembly';
    sTxtCopyCont       = 'Copy contents';
    sTxtScrRead        = 'Screen readers';
    sTxtModAnnot       = 'Modify annotations';
    sTxtFillIn         = 'Fill in form fields';
    sTxtAllPerm        = 'All permissions';
    sTxtCreateFiles    = '&Create file(s)';
    sTxtOpenPDF        = 'Open &PDF';
    sTxtOpenTXT        = 'Open &TXT';
    sTxtOpenDir        = 'Open &directory';
    sTxtPDFtkHelp      = 'PDFtk help';
    sTxtPDFtkSite      = 'PDFtk site';
    sTxtExit           = 'Exit';
    //edit ranges
    sTxtPages          = 'Pages';
    sTxtFrom           = 'From:';
    sTxtTo             = 'To:';
    sTxtFromEnd        = 'From end';
    sTxtNumLastPage    = 'number of last page';
    sTxtAll            = 'All';
    sTxtEven           = 'Even';
    sTxtOdd            = 'Odd';
    sTxtNone           = 'None';
    sTxtNorth          = 'North';
    sTxtEast           = 'East';
    sTxtSouth          = 'South';
    sTxtWest           = 'West';
    sTxtLeft           = 'Left';
    sTxtRight          = 'Right';
    sTxtDown           = 'Down';
    sTxtNew            = 'New';
    //EnterPassword()
    sTxtEnterPass      = 'Enter owner password for PDF document:';
    //MsgBox()
    sTxtNoFile         = 'This file does not exists.';
    sTxtNoWaterFile    = 'There is no PDF watermark file.';
    sTxtNoPDFReader    = 'There is no PDF reader.';
    sTxtNoTXTEditor    = 'There is no TXT editor.';
    sTxtCantExec       = 'Can not execute this command:';
    sTxtNoCallback     = 'Unable to register callback function.';
    sTxtPDFtkError     = 'PDFtk Error';
    sTxtNoTempDir      = 'Unable to create temporary directory.';
    sTxtWriteError     = 'Write error to this file.';
    sTxtSelOtherName   = 'Select another name or unlock the file.';
    sTxtUnlockFile     = 'Unlock the file and press "Retry"';
    sTxtTooManyDocs    = 'Too many documents or ranges are to be processed.\nUnable to create the output document.'
    sTxtCreated        = 'Created:';
    sTxtSplitted       = 'Splitted:';
    sTxtFileExists     = 'This file already exists. Do you want to replace it?';
    sTxtReplace        = 'Replace';
    sTxtReplaceAll     = 'Replace all';
    sTxtSkip           = 'Skip';
    sTxtSkipAll        = 'Skip all';
    sTxtRetry          = 'Retry';
    sTxtInvalidChar    = 'Invalid character in file name.';
    sTxtNoPDFBookmarks = 'This PDF document does not contain any bookmarks.';
    sTxtNoTXTBookmarks = 'This TXT file does not contain any bookmarks.';
    sTxtBookmarksHelp  = 'Each line of bookmarks file should contain a description of one bookmark in the following format:\n[TAB...]Bookmark text/Page number in PDF document\n\nExample:\nBookmark - level 0 (without TAB at beginning of line)/2\n\tBookmark - level 1 (one TAB char at beginning of line)/14\n\t\tBookmark - level 2 (two TAB chars at beginning of line)/29\n\tBookmark - level 1 (one TAB char at beginning of line)/35\nBookmark - level 0 (without TAB at beginning of line)/47';
    sTxtNoPDFData      = 'This PDF document does not contain the required data.';
    //GetOpenSaveFileName()
    sTxtSelWaterPDF    = 'Select PDF file containing watermarks';
    sTxtSelBookTXT     = 'Select TXT file containing bookmarks';
    sTxtSelDataTXT     = 'Select TXT file containing data info';
    sTxtSelPDFReader   = 'Select PDF reader';
    sTxtSelTXTEditor   = 'Select TXT editor';
    sTxtSelSourcePDFs  = 'Select source PDF documents';
    //BrowseForFolder()
    sTxtSelOutDir      = 'Select output directory:';
    sTxtSelPDFtkDir    = 'Select directory containing PDFtk.exe:';
    sTxtSelAkelDir     = 'Select directory containing AkelPad.exe:';
    //common
    sTxtOK             = 'OK';
    sTxtCancel         = 'Cancel';
  }
}
