//=======================================================================
//  Unit:  API Scripter
//=======================================================================
// [Purpose]
//  --  access to APIScripter object;
//      this object contains methods that access many non-automation
//      API functions (Win32, TWAIN, etc.)
// [Units]
// [Objects]
//  --  APIScripter
// [Files]
// [Notes]
//  --  see APIScripter.txt
//=======================================================================

//=======================================================================
function dllfunc(func, p1, p2, p3, p4, p5, p6, p7, p8, p9) {
//=======================================================================
// [Syntax]
//  --  Default definition:   dllfunc('DEFAULT=',  'dll="dllname"; i = "ll"');
//  --  Function definition:  dllfunc('funcname=', 'i = "lll"');
//  --  Function usage:       dllfunc('funcname',   param1, param2);
//  --  Free objects:         dllfunc();
//  --  NOTE:  Only assign function definitions for variables different
//             than the default.
//=======================================================================
  //------ init global variables (if necessary)
  try       {if (!dllfuncobj) return;}
  catch (e) {dllfuncobj = new Array(); dllfuncdef = new Array(); dllfuncdef['DEFAULT'] = '';}
  //------ free objects (if no parameters)
  if (!func) {for (var s in dllfuncobj) {dllfuncobj[s] = null;} return;}
  //-----  save non-default definitions (also includes DEFAULT)
  if (func.charAt(func.length-1) == '=') {
    func = func.substring(0,func.length-1);
    if (func != 'DEFAULT') dllfuncdef[func] = dllfuncdef['DEFAULT'] + ';' + p1;
    else                   dllfuncdef[func] = p1;
    return;
  }
  //-----  assign definition values (including pseudo-function info)
  var idxfunc = func; var dll = ''; var i = 'l'; var f = 's'; var r = 'l';
  if (dllfuncdef[idxfunc]) eval(dllfuncdef[idxfunc]);
  else                     eval(dllfuncdef['DEFAULT']);
  //-----  register (if necessary)
  if (!dllfuncobj[idxfunc]) {
    dllfuncobj[idxfunc] = new ActiveXObject('DynamicWrapper');
           evalstr  = 'dllfuncobj[idxfunc].Register(dll, func';
    if (i) evalstr += ', \"i=' + i + '\"';
    if (f) evalstr += ', \"f=' + f + '\"';
    if (r) evalstr += ', \"r=' + r + '\"';
           evalstr += ')';
    eval(evalstr);
  }
  //-----  execute
  evalstr = 'dllfuncobj["' + idxfunc + '"].' + func + '(';
  if ((p1 + '') != 'undefined') evalstr += 'p1';   if ((p2 + '') != 'undefined') evalstr += ',p2';
  if ((p3 + '') != 'undefined') evalstr += ',p3';  if ((p4 + '') != 'undefined') evalstr += ',p4';
  if ((p5 + '') != 'undefined') evalstr += ',p5';  if ((p6 + '') != 'undefined') evalstr += ',p6';
  if ((p7 + '') != 'undefined') evalstr += ',p7';  if ((p8 + '') != 'undefined') evalstr += ',p8';
  if ((p9 + '') != 'undefined') evalstr += ',p9';  evalstr += ')';
  return eval(evalstr);
}


//=======================================================================
//=======================================================================
//  Windows functions
//=======================================================================
//=======================================================================

//=======================================================================
//======  Special Constants  ============================================
//=======================================================================
var EWX_SHUTDOWN    = 0x00000001;
var EWX_REBOOT      = 0x00000002;
var GPTR            = 0x0040; // GMEM_FIXED|GMEM_ZEROINIT
var GW_CHILD        = 5;
var GW_HWNDFIRST    = 0;
var GW_HWNDNEXT     = 2;
var GW_HWNDPREV     = 3;
var HWND_TOP        = 0;
var SW_HIDE         = 0;
var SW_NORMAL       = 1;
var SW_SHOW         = 5;
var SW_RESTORE      = 9;
var WM_CLOSE        = 0x0010;
var WM_QUIT         = 0x0012;
var WM_USER         = 0x0400;

var fwt_TITEXACT    = 0x0000;
var fwt_TITPREFIX   = 0x0001;
var fwt_TITSUFFIX   = 0x0003;
var fwt_TITFLAGS    = 0x0003; // mask
var fwt_MAYBEINTRAY = 0x0004;

var DOWHILEHIDDEN   = true;
var RESTART         = true;

//=======================================================================
//======  Constants  ====================================================
//=======================================================================
var sizeofLONG      = 4;
var sizeofRECT      = 4 * sizeofLONG;
var sizeofDEFSTR    = 255;

//=======================================================================
//======  WinAPI Function Definitions  ==================================
//=======================================================================
dllfunc('DEFAULT=',           '               dll = "user32.dll"');
dllfunc('EqualRect=',         'i = "ll"');
dllfunc('ExitWindowsEx=',     'i = "ll"');
dllfunc('FindWindow=',        'i = "ss"');
dllfunc('GetDesktopWindow=',  'i = ""');
dllfunc('GetWindow=',         'i = "ll"');
dllfunc('GetWindowText=',     'i = "lll"');
dllfunc('GetWindowRect=',     'i = "ll"');
dllfunc('GlobalAlloc=',       'i = "ll";      dll = "kernel32.dll"');
dllfunc('GlobalFree=',        '               dll = "kernel32.dll"');
dllfunc('IntersectRect=',     'i = "lll"');
dllfunc('lstrcmp=',           'i = "ll";      dll = "kernel32.dll"');
dllfunc('lstrcmpJS=',         'i = "ls";      dll = "kernel32.dll"; func = "lstrcmp"');
dllfunc('lstrcpyn=',          'i = "lll";     dll = "kernel32.dll"');
dllfunc('MessageBox=',        'i = "llll"');
dllfunc('PostMessage=',       'i = "llll"');
dllfunc('SendMessage=',       'i = "llll"');
dllfunc('SetWindowPos=',      'i = "lllllll"');
dllfunc('SetRect=',           'i = "lllll"');
dllfunc('ShowWindow=',        'i = "ll"');

//=======================================================================
function winfunc(func, p1, p2, p3, p4, p5, p6, p7, p8, p9) {
//=======================================================================
  dllfunc('DEFAULT=', 'dll = "user32.dll"');
  return dllfunc(func, p1, p2, p3, p4, p5, p6, p7, p8, p9);
}

//=======================================================================
function findWindow(cls, tit)                           {return winfunc('FindWindow', cls, tit);}
function getNextWindow(hwnd)                            {return winfunc('GetWindow', hwnd, GW_HWNDNEXT);}
function postMessageToWindow(hwnd, msg, wparam, lparam) {return winfunc('PostMessage', hwnd, msg, wparam, lparam);}
function postCloseToWindow(hwnd)                        {return winfunc('PostMessage', hwnd, WM_CLOSE, 0, 0);}
function postQuitToWindow(hwnd)                         {return winfunc('PostMessage', hwnd, WM_QUIT, 0, 0);}
function sendMessageToWindow(hwnd, msg, wparam, lparam) {return winfunc('SendMessage', hwnd, msg, wparam, lparam);}
function sendCloseToWindow(hwnd)                        {return winfunc('SendMessage', hwnd, WM_CLOSE, 0, 0);}
//=======================================================================

//=======================================================================
function getForegroundWindow() {
//=======================================================================
  // NOTE: for some reason, works better with WSH than actual API function
  var hwnd = winfunc('GetDesktopWindow');
  return winfunc('GetWindow', hwnd, GW_CHILD);
}

//=======================================================================
function focusWindow(hwnd) {
//=======================================================================
  if (winfunc('IsIconic', hwnd)) winfunc('ShowWindow', hwnd, SW_RESTORE);
  winfunc('SetForegroundWindow', hwnd);
}

//=======================================================================
function bringUpPositionedWindow(hwnd, lft, top, wid, hgt, dowhilehidden) {
//=======================================================================
  if (dowhilehidden) {
    winfunc('ShowWindow', hwnd, SW_HIDE);
    winfunc('ShowWindow', hwnd, SW_RESTORE);
  }
  winfunc('SetWindowPos', hwnd, HWND_TOP, lft, top, wid, hgt, 0);
}

//=======================================================================
function tileTopWindowInRegion(baselft, basetop, basewid, basehgt,
                               tglwid, tglhgt) {
//=======================================================================
  if ((baselft < 0)  || (basetop < 0)  ||
      (basewid <= 0) || (basehgt <= 0)) return;

  var pbaserect  = winfunc('GlobalAlloc', GPTR, sizeofRECT);
  var pchkrect   = winfunc('GlobalAlloc', GPTR, sizeofRECT);
  var pintersect = winfunc('GlobalAlloc', GPTR, sizeofRECT);
  winfunc('SetRect', pbaserect, baselft, basetop, baselft+basewid, basetop+basehgt);

  var hwnd = getForegroundWindow();
  while (hwnd) {
    if (winfunc('IsWindowVisible', hwnd)) {
      if (!winfunc('GetWindowRect', hwnd, pchkrect)) break;
      if (winfunc('IntersectRect', pintersect, pbaserect, pchkrect)) {
        var twid = basewid;
        var thgt = basehgt;
        if (winfunc('EqualRect', pbaserect, pchkrect)) {
          if (tglwid > 0) twid = tglwid;
          if (tglhgt > 0) thgt = tglhgt;
        }
        if (winfunc('SetWindowPos', hwnd, HWND_TOP, baselft, basetop, twid, thgt, 0)) {
          winfunc('SetForegroundWindow', hwnd);
        }
        break;
      }
    }
    hwnd = getNextWindow(hwnd);
  }

  winfunc('GlobalFree', pintersect);
  winfunc('GlobalFree', pchkrect);
  winfunc('GlobalFree', pbaserect);
} 

//=======================================================================
function findWindowTitle(title, flags) {
//=======================================================================
  var pchktitle = winfunc('GlobalAlloc', GPTR, sizeofDEFSTR);

  var hwnd = getForegroundWindow();
  while (hwnd) {
    if ((flags & fwt_MAYBEINTRAY) || winfunc('IsWindowVisible', hwnd)) {
      var ln = winfunc('GetWindowText', hwnd, pchktitle, sizeofDEFSTR);
      if (ln >= title.length) {
        var pofs = 0;
        switch (flags & fwt_TITFLAGS) {
          case fwt_TITPREFIX: winfunc('lstrcpyn', pchktitle, pchktitle, title.length + 1); break;
          case fwt_TITSUFFIX: pofs = ln - title.length; break;
        }
        if (!winfunc('lstrcmpJS', pchktitle + pofs, title)) break;
      }
    }
    hwnd = getNextWindow(hwnd);
  }

  winfunc('GlobalFree', pchktitle);
  return hwnd;
}

//=======================================================================
function findWindowTitlePrefix(title) {return findWindowTitle(title, fwt_TITPREFIX);}
function findWindowTitleSuffix(title) {return findWindowTitle(title, fwt_TITSUFFIX);}
//=======================================================================

//=======================================================================
function shutdownWindows(restart) {
//=======================================================================
  if (restart) var exitflg = EWX_REBOOT;
  else         var exitflg = EWX_SHUTDOWN;
  return winfunc('ExitWindowsEx', exitflg, 0);
}


//=======================================================================
//=======================================================================
//  TWAIN functions
//=======================================================================
//=======================================================================

//=======================================================================
//======  Special Constants  ============================================
//=======================================================================
var TWUN_INCHES = 0;
var TWPT_BW     = 0x00000001;
var TWPT_GRAY   = 0x00000002;
var TWPT_RGB    = 0x00000004;
var HIDE_UI     = 1;

//=======================================================================
//======  EZTWAIN Function Definitions  =================================
//=======================================================================
dllfunc('DEFAULT=',                     '             dll = "eztw32.dll"');
dllfunc('TWAIN_LoadSourceManager=',     'i = ""');
dllfunc('TWAIN_OpenDefaultSource=',     'i = ""');
dllfunc('TWAIN_SetCurrentResolution=',  'i = "d"');
dllfunc('TWAIN_SetImageLayout=',        'i = "dddd"');
dllfunc('TWAIN_AcquireToFilename=',     'i = "ls"');
dllfunc('TWAIN_CloseSource=',           'i = ""');
dllfunc('TWAIN_UnloadSourceManager=',   'i = ""');

//=======================================================================
function twainfunc(func, p1, p2, p3, p4, p5, p6, p7, p8, p9) {
//=======================================================================
  dllfunc('DEFAULT=', 'dll = "eztw32.dll"');
  return dllfunc(func, p1, p2, p3, p4, p5, p6, p7, p8, p9);
}

//=======================================================================
function scanInBitmapFile(pthfil, width, height, resolution, type) {
//=======================================================================
// NOTE: type="B&W"|"GRAY"|"COLOR"
//=======================================================================
  if (!width || !height) return;

  var units = TWUN_INCHES;
  if (!resolution) resolution = 100;
  var pix = TWPT_RGB;
  switch (type) {
    case 'B&W':   pix = TWPT_BW;   break;
    case 'GRAY':  pix = TWPT_GRAY; break;
    case 'COLOR': pix = TWPT_RGB;  break;
  }

  twainfunc('TWAIN_LoadSourceManager');
  twainfunc('TWAIN_OpenSourceManager',    0);
  twainfunc('TWAIN_OpenDefaultSource');

  twainfunc('TWAIN_SetHideUI',            HIDE_UI);
  twainfunc('TWAIN_SetCurrentUnits',      units);
  twainfunc('TWAIN_SetCurrentPixelType',  pix);
  twainfunc('TWAIN_SetCurrentResolution', resolution);
  twainfunc('TWAIN_SetImageLayout',       0, 0, width, height);
  twainfunc('TWAIN_AcquireToFilename',    0, pthfil);

  twainfunc('TWAIN_CloseSource');
  twainfunc('TWAIN_CloseSourceManager',   0);
  twainfunc('TWAIN_UnloadSourceManager');
}

//=======================================================================
function APIScripterObject() {
//=======================================================================
  //------ Windows methods
  this.bringUpPositionedWindow = bringUpPositionedWindow;
  this.findWindow              = findWindow;
  this.findWindowTitle         = findWindowTitle;
  this.findWindowTitlePrefix   = findWindowTitlePrefix;
  this.findWindowTitleSuffix   = findWindowTitleSuffix;
  this.focusWindow             = focusWindow;
  this.postCloseToWindow       = postCloseToWindow;
  this.postQuitToWindow        = postQuitToWindow;
  this.sendCloseToWindow       = sendCloseToWindow;
  this.sendMessageToWindow     = sendMessageToWindow;
  this.shutdownWindows         = shutdownWindows;
  this.tileTopWindowInRegion   = tileTopWindowInRegion;
  //-----  TWAIN methods
  this.scanInBitmapFile        = scanInBitmapFile;
}

