/// CommandLine of SearchReplace with Argument(s).

try
{
  var hMainWnd=AkelPad.GetMainWnd();
}
catch (oError)
{
  WScript.Quit();
}

if (!(AkelPad.Include("sr_function.js")))
{
  WScript.Quit();
}

//选项
var bShowCountOfChanges=false;

//变量
if (!AkelPad.GetArgLine(0))
{
  WScript.Quit();
}

var pFindIt=AkelPad.GetArgValue("Find", "");
if (pFindIt=="")
{
  WScript.Quit();
}

var oSys=AkelPad.SystemFunction();
var pScriptName=WScript.ScriptName;
var bAkelEdit=AkelPad.IsAkelEdit();

var pReplaceWithEsc;
var nSearchResult;
var i;

//按钮
var BT_FIND       =1;
var BT_REPLACE    =3;
var BT_REPLACEALL =4;

//方向
var DN_DOWN      =0x00000001;
var DN_UP        =0x00000002;
var DN_BEGINNING =0x00000004;
var DN_SELECTION =0x00000008;
var DN_ALLFILES  =0x00000010;

//字符串 ID
var STRID_SYNTAXERROR  =22;
var STRID_COUNTFILES   =24;
var STRID_COUNTCHANGES =25;

var pReplaceWith    =AkelPad.GetArgValue("Replace"        , "");
var bRegExp         =AkelPad.GetArgValue("RegExp"         , 1);
var bSensitive      =AkelPad.GetArgValue("Sensitive"      , 0);
var bMultiline      =AkelPad.GetArgValue("Multiline"      , 0);
var bEscSequences   =AkelPad.GetArgValue("EscSequences"   , 0);
var bReplaceFunction=AkelPad.GetArgValue("ReplaceFunction", 0);
var nDirection      =AkelPad.GetArgValue("Direction"      , DN_BEGINNING);
var nButton         =AkelPad.GetArgValue("Button"         , BT_REPLACEALL);

if (bRegExp != 0)
{
  bRegExp=1;
}
if (bSensitive != 1)
{
  bSensitive=0;
}
if (bMultiline != 1)
{
  bMultiline=0;
}
if (bEscSequences != 1)
{
  bEscSequences=0;
}
if (bReplaceFunction != 1)
{
  bReplaceFunction=0;
}
else
{
  bEscSequences=0;
}
if (nDirection==DN_DOWN || nDirection==DN_UP || nDirection==DN_BEGINNING || nDirection==DN_SELECTION || nDirection==DN_ALLFILES)
{
}
else
{
  nDirection=DN_BEGINNING;
}
if (nButton==BT_REPLACE || nButton==BT_REPLACEALL)
{
}
else
{
  nButton=BT_REPLACEALL;
}

pReplaceWithEsc=pReplaceWith;
if (bRegExp && bReplaceFunction)
{
  //使用函数替换: Infocatcher 写的代码。
  if (!/(^|[^\w.])return(\s+\S|\s*\()/.test(pReplaceWithEsc))
  {
    pReplaceWithEsc="return " + pReplaceWithEsc;
  }
  pReplaceWithEsc='var args={}, l=arguments.length;'
                + 'for (var i=0; i < l; i+=1)\n'
                + '  args["$" + i]=arguments[i];\n'
                + 'args.offset=arguments[l - 2];\n'
                + 'args.s=arguments[l - 1];\n'
                + 'with (args)\n'
                + '{\n'
                +    pReplaceWithEsc
                + '\n}';
  try
  {
    pReplaceWithEsc=new Function(pReplaceWithEsc);
  }
  catch (oError)
  {
    MessageBox(hMainWnd, oError.description, pScriptName, 16 /*MB_ICONERROR*/);
    WScript.Quit();
  }
}
else if (bEscSequences)
{
  if (!bRegExp)
  {
    if (!(pFindIt=TranslateEscapeString(pFindIt)))
    {
      MessageBox(hMainWnd, GetLangString(STRID_SYNTAXERROR), pScriptName, 16 /*MB_ICONERROR*/);
      WScript.Quit();
    }
  }
}

if (!bReplaceFunction && pReplaceWithEsc)
{
  if (bEscSequences)
  {
    pReplaceWithEsc=pReplaceWithEsc.replace(/\\\\/g, "\0");

    if (bRegExp && pFindIt.search(/\([^\(\)]*?\)/g) != -1)
    {
      if (pReplaceWithEsc.search(/\\[^rnt1-9]/g) != -1)
      {
        MessageBox(hWndDialog, GetLangString(STRID_SYNTAXERROR), pScriptName, 16 /*MB_ICONERROR*/);
        oSys.Call("user32::SetFocus", hWndWith);
        WScript.Quit();
      }
    }
    else
    {
      if (pReplaceWithEsc.search(/\\[^rnt]/g) != -1)
      {
        MessageBox(hWndDialog, GetLangString(STRID_SYNTAXERROR), pScriptName, 16 /*MB_ICONERROR*/);
        oSys.Call("user32::SetFocus", hWndWith);
        WScript.Quit();
      }
    }

    pReplaceWithEsc=pReplaceWithEsc.replace(/\\r\\n|\\r|\\n/g, "\n");
    pReplaceWithEsc=pReplaceWithEsc.replace(/\\t/g, "\t");
  }

  if (bRegExp && pFindIt.search(/\([^\(\)]*?\)/g) != -1)
  {
    pReplaceWithEsc=pReplaceWithEsc.replace(/\\(\d)/g,"$$$1");
  }

  if (bEscSequences)
  {
    pReplaceWithEsc=pReplaceWithEsc.replace(/\0/g, "\\");
  }
}

if (bRegExp && AkelPad.Include("cnRegExp.js"))
{
  pFindIt=cnRegExp(pFindIt);
}

nSearchResult=SearchReplace();

if (nSearchResult == -1)
{
  if (nDirection & DN_ALLFILES)
  {
    nDirection&=~DN_DOWN;
  }
  else if (nDirection & DN_BEGINNING)
  {
    nDirection&=~DN_DOWN;
  }
}
else
{
  if (nDirection == DN_ALLFILES)
  {
    nDirection|=DN_DOWN;
  }
  else if (nDirection == DN_BEGINNING)
  {
    nDirection|=DN_DOWN;
  }
}


//函数
function SearchReplace()
{
  var lpFrameInit=AkelPad.SendMessage(hMainWnd, 1288 /*AKD_FRAMEFIND*/, 1 /*FWF_CURRENT*/, 0);
  var hWndEditCur=AkelPad.GetEditWnd();
  var oPattern;
  var lpArray;
  var pSelText;
  var pResult;
  var dwOptions;
  var nInitialSelStart;
  var nInitialSelEnd;
  var nSelStart;
  var nSelEnd;
  var nMatches=-1;
  var nChanges=0;
  var nChangedFiles=0;
  var nError;
  var nResult=-1;
  var i;

  try
  {
    oPattern=new RegExp((bRegExp?pFindIt:EscRegExp(pFindIt)), (bSensitive?"":"i") + ((nButton == BT_REPLACEALL || nDirection & DN_UP)?"g":"") + (bMultiline?"m":""));
  }
  catch (oError)
  {
    MessageBox(hMainWnd, oError.description, pScriptName, 16 /*MB_ICONERROR*/);
    return nResult;
  }

  for (;;)
  {
    nInitialSelStart=AkelPad.GetSelStart();
    nInitialSelEnd=AkelPad.GetSelEnd();

    //检查当前选定范围以便替换
    if (nButton == BT_REPLACE)
    {
      if (nInitialSelStart != nInitialSelEnd)
      {
        pSelText=AkelPad.GetSelText(2 /*\n*/);
        if (!bAkelEdit)
        {
          pSelText=pSelText.replace(/\r/g, "\n");
        }

        if (/\(\?[=!].*\)/.test(pFindIt)) // Lookahead assertions: x(?=y) or x(?!y)
        {
          var pEndText=AkelPad.GetTextRange(nInitialSelStart, -1, 2 /*\n*/);
          if (!bAkelEdit)
          {
            pEndText=pEndText.replace(/\r/g, "\n");
          }

          if (oPattern.test(pEndText) && RegExp.lastMatch == pSelText)
          {
            pResult=pEndText.replace(oPattern, pReplaceWithEsc);
            pResult=pResult.substr(0, pResult.length - (pEndText.length - pSelText.length));
            AkelPad.ReplaceSel(pResult);

            nInitialSelStart=AkelPad.GetSelStart();
            nInitialSelEnd=AkelPad.GetSelEnd();
          }
        }
        else
        {
          if (lpArray=pSelText.match(oPattern))
          {
            if (lpArray.index == 0 && lpArray[0].length == (nInitialSelEnd - nInitialSelStart))
            {
              pResult=pSelText.replace(oPattern, pReplaceWithEsc);
              AkelPad.ReplaceSel(pResult);

              nInitialSelStart=AkelPad.GetSelStart();
              nInitialSelEnd=AkelPad.GetSelEnd();
            }
          }
        }
      }
      nButton=BT_FIND;
    }

    //获取范围
    if (nDirection & DN_DOWN)
    {
      if (nButton == BT_FIND)
      {
        nSelStart=nInitialSelEnd;
        nSelEnd=-1;
      }
      else
      {
        nSelStart=nInitialSelStart;
        nSelEnd=-1;
      }
    }
    else if (nDirection & DN_UP)
    {
      if (nButton == BT_FIND)
      {
        nSelStart=0;
        nSelEnd=nInitialSelStart;
      }
      else
      {
        nSelStart=0;
        nSelEnd=nInitialSelEnd;
      }
    }
    else if (nDirection & DN_BEGINNING)
    {
      nSelStart=0;
      nSelEnd=-1;
    }
    else if (nDirection & DN_SELECTION)
    {
      if (AkelPad.SendMessage(hWndEditCur, 3125 /*AEM_GETSEL*/, 0, 0))
      {
        nSelStart=nInitialSelStart;
        nSelEnd=nInitialSelEnd;
      }
      else
      {
        nSelStart=0;
        nSelEnd=-1;
        nDirection=DN_BEGINNING;
      }
    }
    else if (nDirection & DN_ALLFILES)
    {
      nSelStart=0;
      nSelEnd=-1;
    }

    //查找或替换
    try
    {
      pSelText=AkelPad.GetTextRange(nSelStart, nSelEnd, 2 /*\n*/);

      if (nButton == BT_FIND)
      {
        if (lpArray=pSelText.match(oPattern))
        {
          if (nDirection & DN_UP)
          {
            for (i=0; lpArray[i]; i+=1)
            {
              AkelPad.SetSel(nSelStart + (lpArray.lastIndex - lpArray[i - 1].length), nSelStart + lpArray.lastIndex, 0x8 /*AESELT_LOCKSCROLL*/);
            }
          }
          else
          {
            AkelPad.SetSel(nSelStart + lpArray.index, nSelStart + lpArray.index + lpArray[0].length, 0x8 /*AESELT_LOCKSCROLL*/);
          }

          ScrollCaret(hWndEditCur);
          nResult=AkelPad.GetSelStart();
        }
        else
        {
          if (nDirection & DN_ALLFILES)
          {
            nDirection&=~DN_DOWN;

            //下一个 MDI 帧
            lpFrameCur=AkelPad.Command(4316 /*IDM_WINDOW_FRAMENEXT*/);
            hWndEditCur=AkelPad.GetEditWnd();
            if (lpFrameCur != lpFrameInit)
            {
              continue;
            }
          }
        }
      }
      else if (nButton == BT_REPLACEALL)
      {
        if (bShowCountOfChanges)
        {
          nMatches=pSelText.match(oPattern);
          nMatches=nMatches?nMatches.length:0;
          nChanges+=nMatches;
          if (nMatches)
          {
            nChangedFiles+=1;
          }
        }

        if (nMatches)
        {
          var nFirstLine;
          var nInitialLine;
          var nInitialCharInLine;

          pResult=pSelText.replace(oPattern, pReplaceWithEsc);

          //保存选定范围
          nFirstLine=SaveLineScroll(hWndEditCur);
          nInitialLine=AkelPad.SendMessage(hWndEditCur, 1078 /*EM_EXLINEFROMCHAR*/, 0, nInitialSelStart);
          nInitialCharInLine=nInitialSelStart - AkelPad.SendMessage(hWndEditCur, 187 /*EM_LINEINDEX*/, nInitialLine, 0);

          //替换选定范围
          if (bAkelEdit)
          {
            if (nDirection & DN_SELECTION)
            {
              dwOptions=AkelPad.SendMessage(hWndEditCur, 3227 /*AEM_GETOPTIONS*/, 0, 0);
              if (!(dwOptions & 0x40 /*AECO_PASTESELECTCOLUMN*/))
              {
                AkelPad.SendMessage(hWndEditCur, 3228 /*AEM_SETOPTIONS*/, 2 /*AECOOP_OR*/, 0x40 /*AECO_PASTESELECTCOLUMN*/);
              }
            }
          }

          AkelPad.SetSel(nSelStart, nSelEnd, 0x8 /*AESELT_LOCKSCROLL*/);
          AkelPad.ReplaceSel(pResult);

          if (bAkelEdit)
          {
            if (nDirection & DN_SELECTION)
            {
              if (!(dwOptions & 0x40 /*AECO_PASTESELECTCOLUMN*/))
              {
                AkelPad.SendMessage(hWndEditCur, 3228 /*AEM_SETOPTIONS*/, 4 /*AECOOP_XOR*/, 0x40 /*AECO_PASTESELECTCOLUMN*/);
              }
            }
          }

          //恢复选定范围
          if (nDirection & DN_SELECTION)
          {
            if (!AkelPad.SendMessage(hWndEditCur, 3127 /*AEM_GETCOLUMNSEL*/, 0, 0))
            {
              AkelPad.SetSel(nSelStart, nSelStart + pResult.length, 0x8 /*AESELT_LOCKSCROLL*/);
            }
          }
          else
          {
            i=AkelPad.SendMessage(hWndEditCur, 187 /*EM_LINEINDEX*/, nInitialLine, 0) + nInitialCharInLine;
            AkelPad.SetSel(i, i + (nInitialSelEnd - nInitialSelStart), 0x8 /*AESELT_LOCKSCROLL*/);
          }

          RestoreLineScroll(hWndEditCur, nFirstLine);
        }

        if (nDirection & DN_ALLFILES)
        {
          nDirection&=~DN_DOWN;

          //下一个 MDI 帧
          lpFrameCur=AkelPad.Command(4316 /*IDM_WINDOW_FRAMENEXT*/);
          hWndEditCur=AkelPad.GetEditWnd();
          if (lpFrameCur != lpFrameInit)
          {
            continue;
          }
        }

        if (bShowCountOfChanges)
        {
          if (nDirection & DN_ALLFILES)
          {
            MessageBox(hMainWnd, GetLangString(STRID_COUNTFILES) + nChangedFiles + "\n" + GetLangString(STRID_COUNTCHANGES) + nChanges, pScriptName, 64 /*MB_ICONINFORMATION*/);
          }
          else
          {
            MessageBox(hMainWnd, GetLangString(STRID_COUNTCHANGES) + nChanges, pScriptName, 64 /*MB_ICONINFORMATION*/);
          }
        }
      }
    }
    catch (oError)
    {
      MessageBox(hMainWnd, oError.description, pScriptName, 16 /*MB_ICONERROR*/);
    }
    break;
  }
  return nResult;
}

function GetLangString(nStringID)
{
  var nLangID=AkelPad.GetLangId(1 /*LANGID_PRIMARY*/);

  if (nLangID == 0x4) //LANG_CHINESE
  {
    if (nStringID == STRID_SYNTAXERROR)
    {
      return "语法错误：\n \\\\ - 反斜线\n \\r - 换行符\n \\t - 制表符";
    }
    if (nStringID == STRID_COUNTFILES)
    {
      return "替换文件数: ";
    }
    if (nStringID == STRID_COUNTCHANGES)
    {
      return "替换次数: ";
    }
  }
  else
  {
    if (nStringID == STRID_SYNTAXERROR)
    {
      return "Syntax error:\n \\\\ - backslash\n \\r - line feed\n \\t - tabulation";
    }
    if (nStringID == STRID_COUNTFILES)
    {
      return "Changed files: ";
    }
    if (nStringID == STRID_COUNTCHANGES)
    {
      return "Count of changes: ";
    }
  }
  return "";
}
