function RdsArrayToStruct(drs)
{
  var lpRds;
  var lpItem;
  var lpWnd;
  var i;

  if (lpRds=AkelPad.MemAlloc((drs.length + 1) * (_X64?16:12) /*sizeof(RESIZEDIALOG)*/))
  {
    for (i=0, lpItem=lpRds; i < drs.length; i+=1)
    {
      lpWnd=AkelPad.MemAlloc(_X64?8:4);
      AkelPad.MemCopy(lpWnd, drs[i][0], 2 /*DT_QWORD*/);
      AkelPad.MemCopy(_PtrAdd(lpItem, 0) /*offsetof(RESIZEDIALOG, lpWnd)*/, lpWnd, 2 /*DT_QWORD*/);
      AkelPad.MemCopy(_PtrAdd(lpItem, _X64?8:4) /*offsetof(RESIZEDIALOG, dwType)*/, drs[i][1], 3 /*DT_DWORD*/);

      lpItem=_PtrAdd(lpItem, _X64?16:12) /*sizeof(RESIZEDIALOG)*/;
    }
  }
  return lpRds;
}

function RdsFree(lpRds)
{
  var lpItem;
  var lpWnd;

  if (lpRds)
  {
    for (lpItem=lpRds; lpWnd=AkelPad.MemRead(lpItem, _PtrAdd(lpItem, 0) /*offsetof(RESIZEDIALOG, lpWnd)*/); lpItem=_PtrAdd(lpItem, _X64?16:12) /*sizeof(RESIZEDIALOG)*/)
    {
      AkelPad.MemFree(lpWnd);
    }
    AkelPad.MemFree(lpRds);
  }
}

function DialogResizeMessages(drs, rcMinMax, rcCurrent, dwFlags, hDlg, uMsg, wParam, lParam)
{
  if (uMsg == 0x1   || //WM_CREATE
      uMsg == 0x110)   //WM_INITDIALOG
  {
    var rcTemplate=[];
    var rcControl=[];
    var i;

    rcTemplate.left=rcCurrent.left;
    rcTemplate.top=rcCurrent.top;
    rcTemplate.right=rcCurrent.right;
    rcTemplate.bottom=rcCurrent.bottom;

    GetWindowSize(hDlg, 0, rcCurrent);

    for (i=0; i < drs.length; ++i)
    {
      if (drs[i][0])
      {
        GetWindowSize(drs[i][0], hDlg, rcControl);
        if (drs[i][1] & DRS_SIZE)
        {
          if (drs[i][1] & DRS_X)
            drs[i][3]=rcCurrent.right - (rcControl.left + rcControl.right);
          else if (drs[i][1] & DRS_Y)
            drs[i][3]=rcCurrent.bottom - (rcControl.top + rcControl.bottom);
        }
        else if (drs[i][1] & DRS_MOVE)
        {
          if (drs[i][1] & DRS_X)
            drs[i][3]=rcCurrent.right - rcControl.left;
          else if (drs[i][1] & DRS_Y)
            drs[i][3]=rcCurrent.bottom - rcControl.top;
        }
      }
    }

    if (rcTemplate.right && rcTemplate.bottom)
    {
      if (oSys.Call("user32::GetWindowLong" + _TCHAR, hDlg, -16 /*GWL_STYLE*/) & 0x800 /*DS_CENTER*/)
      {
        rcTemplate.left=rcCurrent.left + (rcCurrent.right - rcTemplate.right) / 2;
        rcTemplate.top=rcCurrent.top + (rcCurrent.bottom - rcTemplate.bottom) / 2;
      }
      oSys.Call("user32::SetWindowPos", hDlg, 0, rcTemplate.left, rcTemplate.top, rcTemplate.right, rcTemplate.bottom, 0x14 /*SWP_NOZORDER|SWP_NOACTIVATE*/);
    }
  }
  else if (uMsg == 36) //WM_GETMINMAXINFO
  {
    if (rcMinMax.left)
      AkelPad.MemCopy(_PtrAdd(lParam, 24) /*offsetof(MINMAXINFO, ptMinTrackSize.x)*/, rcMinMax.left, 3 /*DT_DWORD*/);
    if (rcMinMax.top)
      AkelPad.MemCopy(_PtrAdd(lParam, 28) /*offsetof(MINMAXINFO, ptMinTrackSize.y)*/, rcMinMax.top, 3 /*DT_DWORD*/);
    if (rcMinMax.right)
      AkelPad.MemCopy(_PtrAdd(lParam, 32) /*offsetof(MINMAXINFO, ptMaxTrackSize.x)*/, rcMinMax.right, 3 /*DT_DWORD*/);
    if (rcMinMax.bottom)
      AkelPad.MemCopy(_PtrAdd(lParam, 36) /*offsetof(MINMAXINFO, ptMaxTrackSize.y)*/, rcMinMax.bottom, 3 /*DT_DWORD*/);
  }
  else if (uMsg == 3) //WM_MOVE
  {
    if (!(oSys.Call("user32::GetWindowLong" + _TCHAR, hDlg, -16 /*GWL_STYLE*/) & 0x800 /*DS_CENTER*/))
    {
      var rcTemplate=[];

      GetWindowSize(hDlg, 0, rcTemplate);
      rcCurrent.left=rcTemplate.left;
      rcCurrent.top=rcTemplate.top;
      return true;
    }
  }
  else if (uMsg == 5) //WM_SIZE
  {
    if (lParam)
    {
      var rcControl=[];
      var dwFlags;
      var i;

      GetWindowSize(hDlg, 0, rcCurrent);

      for (i=0; i < drs.length; ++i)
      {
        if (drs[i][0])
        {
          dwFlags=0;
          if (drs[i][1] & DRS_SIZE)
            dwFlags|=0x2 /*SWP_NOMOVE*/;
          else if (drs[i][1] & DRS_MOVE)
            dwFlags|=0x1 /*SWP_NOSIZE*/;
          else
            continue;

          GetWindowSize(drs[i][0], hDlg, rcControl);
          oSys.Call("user32::SetWindowPos", drs[i][0], 0, (drs[i][1] & DRS_X)?(rcCurrent.right - drs[i][3]):rcControl.left,
                                                          (drs[i][1] & DRS_Y)?(rcCurrent.bottom - drs[i][3]):rcControl.top,
                                                          (drs[i][1] & DRS_X)?(rcCurrent.right - rcControl.left - drs[i][3]):rcControl.right,
                                                          (drs[i][1] & DRS_Y)?(rcCurrent.bottom - rcControl.top - drs[i][3]):rcControl.bottom,
                                                           dwFlags | 0x14 /*SWP_NOZORDER|SWP_NOACTIVATE*/);
        }
      }
      oSys.Call("user32::InvalidateRect", hDlg, 0, true);
      return true;
    }
  }
  else if (uMsg == 15) //WM_PAINT
  {
    if (dwFlags & 0x2 /*DRM_PAINTSIZEGRIP*/)
    {
      var ps;
      var rcGrip=[];
      var lpGrip;
      var hDC;

      if (ps=AkelPad.MemAlloc(_X64?72:64 /*sizeof(PAINTSTRUCT)*/))
      {
        if (hDC=oSys.Call("user32::BeginPaint", hDlg, ps))
        {
          if (lpGrip=AkelPad.MemAlloc(16 /*sizeof(RECT)*/))
          {
            if (oSys.Call("user32::GetClientRect", hDlg, lpGrip))
            {
              RectToArray(lpGrip, rcGrip);
              rcGrip.left=rcGrip.right - oSys.Call("user32::GetSystemMetrics", 2 /*SM_CXVSCROLL*/);
              rcGrip.top=rcGrip.bottom - oSys.Call("user32::GetSystemMetrics", 20 /*SM_CYVSCROLL*/);
              ArrayToRect(rcGrip, lpGrip);

              oSys.Call("user32::DrawFrameControl", hDC, lpGrip, 3 /*DFC_SCROLL*/, 0x8 /*DFCS_SCROLLSIZEGRIP*/);
            }
            AkelPad.MemFree(lpGrip);
          }
          oSys.Call("user32::EndPaint", hDlg, ps);
        }
        AkelPad.MemFree(ps);
      }
    }
  }
  return false;
}

function InsertInArray(lpArray, lpItem, nPos)
{
  //为了 MS JScript 的向后兼容性
  var i;

  if (nPos < 0) nPos=lpArray.length + nPos + 1;
  if (nPos < 0) nPos=0;
  if (nPos > lpArray.length) nPos=lpArray.length;

  for (i=lpArray.length; i >= 0; --i)
  {
    if (i == nPos)
    {
      lpArray[i]=lpItem;
      break;
    }
    lpArray[i]=lpArray[i - 1];
  }
}

function DeleteFromArray(lpArray, nPos, nCount)
{
  //为了 MS JScript 的向后兼容性
  var i;

  if (nPos < 0) nPos=lpArray.length + nPos;
  if (nPos < 0 || nPos >= lpArray.length) return;
  if (nPos + nCount >= lpArray.length) nCount=lpArray.length - nPos;

  for (i=nPos, l=lpArray.length; i+nCount<l; i+=1)
  {
    lpArray[i]=lpArray[i + nCount];
  }
  lpArray.length-=nCount;
}

function SetWindowFontAndText(hWnd, hFont, pText)
{
  if (hFont)
  {
    AkelPad.SendMessage(hWnd, 48 /*WM_SETFONT*/, hFont, 1);
  }

  oSys.Call("user32::SetWindowText" + _TCHAR, hWnd, pText);
}

function SaveLineScroll(hWnd)
{
  AkelPad.SendMessage(hWnd, 11 /*WM_SETREDRAW*/, false, 0);
  return AkelPad.SendMessage(hWnd, 3129 /*AEM_GETLINENUMBER*/, 4 /*AEGL_FIRSTVISIBLELINE*/, 0);
}

function RestoreLineScroll(hWnd, nBeforeLine)
{
  if (AkelPad.SendMessage(hWnd, 3129 /*AEM_GETLINENUMBER*/, 4 /*AEGL_FIRSTVISIBLELINE*/, 0) != nBeforeLine)
  {
    var lpScrollPos;
    var nPosY=AkelPad.SendMessage(hWnd, 3198 /*AEM_VPOSFROMLINE*/, 0 /*AECT_GLOBAL*/, nBeforeLine);

    if (lpScrollPos=AkelPad.MemAlloc(_X64?16:8 /*sizeof(POINT64)*/))
    {
      AkelPad.MemCopy(_PtrAdd(lpScrollPos, 0) /*offsetof(POINT64, x)*/, -1, 2 /*DT_QWORD*/);
      AkelPad.MemCopy(_PtrAdd(lpScrollPos, _X64?8:4) /*offsetof(POINT64, y)*/, nPosY, 2 /*DT_QWORD*/);
      AkelPad.SendMessage(hWnd, 3180 /*AEM_SETSCROLLPOS*/, 0, lpScrollPos);
      AkelPad.MemFree(lpScrollPos);
    }
  }
  AkelPad.SendMessage(hWnd, 3377 /*AEM_UPDATECARET*/, 0, 0);
  AkelPad.SendMessage(hWnd, 11 /*WM_SETREDRAW*/, true, 0);
  oSys.Call("user32::InvalidateRect", hWnd, 0, true);
}

function RectToArray(lpRect, rcRect)
{
  rcRect.left=AkelPad.MemRead(_PtrAdd(lpRect, 0) /*offsetof(RECT, left)*/, 3 /*DT_DWORD*/);
  rcRect.top=AkelPad.MemRead(_PtrAdd(lpRect, 4) /*offsetof(RECT, top)*/, 3 /*DT_DWORD*/);
  rcRect.right=AkelPad.MemRead(_PtrAdd(lpRect, 8) /*offsetof(RECT, right)*/, 3 /*DT_DWORD*/);
  rcRect.bottom=AkelPad.MemRead(_PtrAdd(lpRect, 12) /*offsetof(RECT, bottom)*/, 3 /*DT_DWORD*/);
  return rcRect;
}

function ArrayToRect(rcRect, lpRect)
{
  if (!lpRect)
    lpRect=AkelPad.MemAlloc(16 /*sizeof(RECT)*/);

  if (lpRect)
  {
    AkelPad.MemCopy(_PtrAdd(lpRect, 0) /*offsetof(RECT, left)*/, rcRect.left, 3 /*DT_DWORD*/);
    AkelPad.MemCopy(_PtrAdd(lpRect, 4) /*offsetof(RECT, top)*/, rcRect.top, 3 /*DT_DWORD*/);
    AkelPad.MemCopy(_PtrAdd(lpRect, 8) /*offsetof(RECT, right)*/, rcRect.right, 3 /*DT_DWORD*/);
    AkelPad.MemCopy(_PtrAdd(lpRect, 12) /*offsetof(RECT, bottom)*/, rcRect.bottom, 3 /*DT_DWORD*/);
  }
  return lpRect;
}

function GetWindowSize(hWnd, hWndOwner, rcRect)
{
  var lpRect;
  var bResult=false;

  if (lpRect=AkelPad.MemAlloc(16 /*sizeof(RECT)*/))
  {
    if (oSys.Call("user32::GetWindowRect", hWnd, lpRect))
    {
      RectToArray(lpRect, rcRect);
      rcRect.right-=rcRect.left;
      rcRect.bottom-=rcRect.top;

      if (hWndOwner)
        bResult=oSys.Call("user32::ScreenToClient", hWndOwner, lpRect);
      else
        bResult=true;
      rcRect.left=AkelPad.MemRead(_PtrAdd(lpRect, 0) /*offsetof(RECT, left)*/, 3 /*DT_DWORD*/);
      rcRect.top=AkelPad.MemRead(_PtrAdd(lpRect, 4) /*offsetof(RECT, top)*/, 3 /*DT_DWORD*/);
    }
    AkelPad.MemFree(lpRect);
  }
  return bResult;
}

function CenterWindow(hWndParent, hWnd)
{
  var lpRect;
  var rcWndParent=[];
  var rcWnd=[];
  var X;
  var Y;

  if (lpRect=AkelPad.MemAlloc(16 /*sizeof(RECT)*/))
  {
    if (!hWndParent)
      hWndParent=oSys.Call("user32::GetDesktopWindow");

    oSys.Call("user32::GetWindowRect", hWndParent, lpRect);
    RectToArray(lpRect, rcWndParent);

    oSys.Call("user32::GetWindowRect", hWnd, lpRect);
    RectToArray(lpRect, rcWnd);

    //窗口居中
    X=rcWndParent.left + ((rcWndParent.right - rcWndParent.left) / 2 - (rcWnd.right - rcWnd.left) / 2);
    Y=rcWndParent.top + ((rcWndParent.bottom - rcWndParent.top) / 2 - (rcWnd.bottom - rcWnd.top) / 2);

    oSys.Call("user32::SetWindowPos", hWnd, 0, X, Y, 0, 0, 0x15 /*SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE*/);

    AkelPad.MemFree(lpRect);
  }
}

function IsFileExist(pFile)
{
  if (oSys.Call("kernel32::GetFileAttributes" + _TCHAR, pFile) == -1)
    return false;
  return true;
}

function GetOutputWindow()
{
  var lpWnd;
  var hWnd=0;

  if (lpWnd=AkelPad.MemAlloc(_X64?8:4 /*sizeof(HWND)*/))
  {
    AkelPad.Call("Log::Output", 2, lpWnd);
    hWnd=AkelPad.MemRead(lpWnd, 2 /*DT_QWORD*/);
    AkelPad.MemFree(lpWnd);
  }
  return hWnd;
}

function PeekMessages(hWnd, bSendChild)
{
  var lpMsg;
  var uMsg;
  var wParam;
  var lParam;

  if (lpMsg=AkelPad.MemAlloc(_X64?48:28 /*sizeof(MSG)*/))
  {
    while (oSys.Call("user32::PeekMessage" + _TCHAR, lpMsg, hWnd, 0, 0, 0x1 /*PM_REMOVE*/))
    {
      if (bSendChild)
      {
        //Send key press from child
        uMsg=AkelPad.MemRead(_PtrAdd(lpMsg, _X64?8:4) /*offsetof(MSG, message)*/, 3 /*DT_DWORD*/);

        if (uMsg >= 0x0100 /*WM_KEYFIRST*/ && uMsg <= 0x0109 /*WM_KEYLAST*/)
        {
          wParam=AkelPad.MemRead(_PtrAdd(lpMsg, _X64?16:8) /*offsetof(MSG, wParam)*/, 2 /*DT_QWORD*/);
          lParam=AkelPad.MemRead(_PtrAdd(lpMsg, _X64?24:12) /*offsetof(MSG, lParam)*/, 2 /*DT_QWORD*/);
          AkelPad.SendMessage(hWnd, uMsg, wParam, lParam);
        }
      }

      //Standard processing
      oSys.Call("user32::TranslateMessage", lpMsg);
      oSys.Call("user32::DispatchMessage" + _TCHAR, lpMsg);
    }
    AkelPad.MemFree(lpMsg);
  }
}

function MessageBox(hHandle, pText, pCaption, nType)
{
  var nResult;

  bMessageBox=true;
  nResult=AkelPad.MessageBox(hHandle, pText, pCaption, nType);
  bMessageBox=false;
  return nResult;
}

function ScrollCaret(hWnd)
{
  if (nAkelEdit)
  {
    var lpStp;
    var dwScrollFlags=0;
    var dwScrollResult;

    if (lpStp=AkelPad.MemAlloc(_X64?32:20 /*sizeof(AESCROLLTOPOINT)*/))
    {
      //Test scroll to caret
      dwScrollFlags=0x1|0x10|0x400|0x800 /*AESC_TEST|AESC_POINTCARET|AESC_OFFSETCHARX|AESC_OFFSETCHARY*/;
      AkelPad.MemCopy(_PtrAdd(lpStp, 0) /*offsetof(AESCROLLTOPOINT, dwFlags)*/, dwScrollFlags, 3 /*DT_DWORD*/);
      AkelPad.MemCopy(_PtrAdd(lpStp, _X64?24:12) /*offsetof(AESCROLLTOPOINT, nOffsetX)*/, 1, 3 /*DT_DWORD*/);
      AkelPad.MemCopy(_PtrAdd(lpStp, _X64?28:16) /*offsetof(AESCROLLTOPOINT, nOffsetY)*/, 0, 3 /*DT_DWORD*/);
      dwScrollResult=AkelPad.SendMessage(hWnd, 3183 /*AEM_SCROLLTOPOINT*/, 0, lpStp);

      dwScrollFlags=0x10 /*AESC_POINTCARET*/;
      if (dwScrollResult & 0x1 /*AECSE_SCROLLEDX*/)
        dwScrollFlags|=0x1000 /*AESC_OFFSETRECTDIVX*/;
      if (dwScrollResult & 0x2 /*AECSE_SCROLLEDY*/)
        dwScrollFlags|=0x2000 /*AESC_OFFSETRECTDIVY*/;

      //Scroll to caret
      AkelPad.MemCopy(_PtrAdd(lpStp, 0) /*offsetof(AESCROLLTOPOINT, dwFlags)*/, dwScrollFlags, 3 /*DT_DWORD*/);
      AkelPad.MemCopy(_PtrAdd(lpStp, _X64?24:12) /*offsetof(AESCROLLTOPOINT, nOffsetX)*/, 3, 3 /*DT_DWORD*/);
      AkelPad.MemCopy(_PtrAdd(lpStp, _X64?28:16) /*offsetof(AESCROLLTOPOINT, nOffsetY)*/, 2, 3 /*DT_DWORD*/);
      AkelPad.SendMessage(hWnd, 3183 /*AEM_SCROLLTOPOINT*/, 0, lpStp);

      AkelPad.MemFree(lpStp);
    }
  }
}

function TranslateEscapeString(pString)
{
  pString=pString.replace(/\\\\/g, "\0");
  if (pString.search(/\\[^rnt]/g) != -1)
    return "";
  pString=pString.replace(/\\r\\n|\\r|\\n/g, "\n");
  pString=pString.replace(/\\t/g, "\t");
  pString=pString.replace(/\0/g, "\\");
  return pString;
}

function EscRegExp(pString)
{
  return pString.replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&");
}

function PatternToString(pPattern)
{
  var pString="";
  var pCharCode;
  var i;

  for (i=0, l=pPattern.length; i<l; i+=1)
  {
    pCharCode=pPattern.charCodeAt(i).toString(16);
    while (pCharCode.length < 4) pCharCode="0" + pCharCode;
    pString+="\\u" + pCharCode;
  }
  return pString;
}

function LOWORD(dwNumber)
{
  return (dwNumber & 0xffff);
}

function HIWORD(dwNumber)
{
  return (dwNumber >> 16);
}

function MAKELONG(a, b)
{
  return (a & 0xffff) | ((b & 0xffff) << 16);
}

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

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

function MkLong(nLoWord, nHiWord)
{
  return (nHiWord << 16) | (nLoWord & 0xffff);
}

function max(a, b)
{
  return a >= b?a:b;
}

function min(a, b)
{
  return a <= b?a:b;
}

function ScaleInit(hDC, hWnd)
{
  if (!ptScale.x && !ptScale.y)
  {
    var hNewDC=hDC;

    if (!hDC) hNewDC=oSys.Call("user32::GetDC", hWnd);

    if (hNewDC)
    {
      ptScale.x=oSys.Call("gdi32::GetDeviceCaps", hNewDC, 88 /*LOGPIXELSX*/);
      ptScale.y=oSys.Call("gdi32::GetDeviceCaps", hNewDC, 90 /*LOGPIXELSY*/);

      //对齐到 16 像素
      if (ptScale.x % 16) ptScale.x+=16 - ptScale.x % 16;
      if (ptScale.y % 16) ptScale.y+=16 - ptScale.y % 16;
    }
    else return false;

    if (!hDC) oSys.Call("user32::ReleaseDC", hWnd, hNewDC);
  }
  return true;
}

function ScaleX(x)
{
  if (ptScale.x)
    return oSys.Call("kernel32::MulDiv", x, ptScale.x, 96);
  return x;
}

function ScaleY(y)
{
  if (ptScale.y)
    return oSys.Call("kernel32::MulDiv", y, ptScale.y, 96);
  return y;
}

