// http://akelpad.sourceforge.net/forum/viewtopic.php?p=1908#1908
// Version: 1.7
// Author: Shengalts Aleksander aka Instructor
//
//
// Description(1033): Wrap lines in specified format.
// Description(1049): Перенести строки по заданному формату.
//
// Arguments:
// -ParaIndent="    "          -Paragraph indent (default is "    ").
// -LineIndent="  "            -Line indent (default is "").
// -MaxLength=40               -Maximum line length is 40 (default is 80). Special values:
//                               -1 Wrap limit value.
//                               -2 Marker value.
// -KeepFirstLineIndent=false  -Keep first line indent (default is true).
// -ShowInput=false            -Show input dialog (default is true).
//
// Usage:
// Call("Scripts::Main", 1, "LinesWrap.js", `-ParaIndent="" -LineIndent="  " -MaxLength=40 -ShowInput=false`)

//Arguments
var pParaIndent=AkelPad.GetArgValue("ParaIndent", "    ");
var pLineIndent=AkelPad.GetArgValue("LineIndent", "");
var nMaxLength=AkelPad.GetArgValue("MaxLength", 80);
var bKeepFirstLineIndent=AkelPad.GetArgValue("KeepFirstLineIndent", true);
var bShowInput=AkelPad.GetArgValue("ShowInput", true);

//Variables
var hMainWnd=AkelPad.GetMainWnd();
var hWndEdit=AkelPad.GetEditWnd();
var oSys=AkelPad.SystemFunction();
var hWndStatus=0;
var hWndProgress=0;
var pFirstLineIndent="";
var pSelText;
var lpResultArray=[];
var lpMatchArray=[];
var lpLinesArray=[];
var pLineCut;
var pLineEnd;
var nLine;
var nLineMaxLength=0;
var bParagraph;
var nCharInLine;
var pContinueLineEnd;
var dwOptions;

if (nMaxLength == -1)
  nMaxLength=AkelPad.SendMessage(hMainWnd, 1223 /*AKD_GETFRAMEINFO*/, 63 /*FI_WRAPLIMIT*/, 0);
else if (nMaxLength == -2)
  nMaxLength=AkelPad.SendMessage(hMainWnd, 1223 /*AKD_GETFRAMEINFO*/, 64 /*FI_MARKER*/, 0);
if (bShowInput)
  nMaxLength=AkelPad.InputBox(hMainWnd, WScript.ScriptName, GetLangString(0), nMaxLength);

if (hWndEdit && nMaxLength)
{
  if (AkelPad.GetSelStart() == AkelPad.GetSelEnd())
    AkelPad.SetSel(0, -1);
  pSelText=AkelPad.GetSelText(2 /*\n*/);

  if (bKeepFirstLineIndent)
  {
    if (pFirstLineIndent=pSelText.match(/^[ \t]+/))
      pFirstLineIndent=pFirstLineIndent[0];
    else
      pFirstLineIndent="";
  }
  pParaIndent=pFirstLineIndent + pParaIndent;
  pLineIndent=pFirstLineIndent + pLineIndent;
  nMaxLength=parseInt(nMaxLength);

  if (nMaxLength - pParaIndent.length <= 0 ||
      nMaxLength - pLineIndent.length <= 0)
  {
    AkelPad.MessageBox(hMainWnd, GetLangString(1), WScript.ScriptName, 48 /*MB_ICONEXCLAMATION*/);
    WScript.Quit();
  }

  //Trim leading and trailing spaces
  pSelText=pSelText.replace(/(^[ \t]+)|([ \t]+$)/gm, "");

  //Unwrap lines
  pSelText=pSelText.replace(/([^.?!:;\n\(\)\[\]\-\=])\n[ \t]*([^\n])/g, "$1 $2");

  if (lpLinesArray=pSelText.split("\n"))
  {
    //Lock edit window and show progress bar
    dwOptions=AkelPad.SendMessage(hWndEdit, 3227 /*AEM_GETOPTIONS*/, 0, 0);
    if (!(dwOptions & 0x1 /*AECO_READONLY*/))
    {
      AkelPad.SendMessage(hWndEdit, 3228 /*AEM_SETOPTIONS*/, 2 /*AECOOP_OR*/, 0x1 /*AECO_READONLY*/);
      AkelPad.SendMessage(hWndEdit, 3234 /*AEM_EXSETOPTIONS*/, 2 /*AECOOP_OR*/, 0x2 /*AECOE_LOCKSELECTION*/);
    }
    if (hWndStatus=oSys.Call("user32::GetDlgItem", hMainWnd, 10002 /*ID_STATUS*/))
    {
      if (hWndProgress=oSys.Call("user32::GetDlgItem", hWndStatus, 10004 /*ID_PROGRESS*/))
      {
        AkelPad.SendMessage(hWndProgress, 1030 /*PBM_SETRANGE32*/, 0, lpLinesArray.length);
        AkelPad.SendMessage(hWndProgress, 1026 /*PBM_SETPOS*/, 0, 0);
        oSys.Call("user32::ShowWindow", hWndProgress, 5 /*SW_SHOW*/);
      }
    }

    pSelText="";
    lpResultArray[0]=pParaIndent;
    nLineMaxLength=nMaxLength - pParaIndent.length;
    bParagraph=true;

    for (nLine=0; nLine < lpLinesArray.length; ++nLine)
    {
      if (hWndProgress)
        AkelPad.SendMessage(hWndProgress, 1026 /*PBM_SETPOS*/, nLine, 0);
      pLineEnd=nLine < lpLinesArray.length - 1?"\n":"";

      if (lpLinesArray[nLine].length > nLineMaxLength)
      {
        for (nCharInLine=0; nCharInLine < lpLinesArray[nLine].length;)
        {
          pLineCut=lpLinesArray[nLine].substr(nCharInLine, nLineMaxLength);

          if (pLineCut.length == nLineMaxLength && (lpMatchArray=pLineCut.match(/[ \t]+/g)))
          {
            lpResultArray[nLine]+=(bParagraph?"":pLineIndent) + pLineCut.substr(0, lpMatchArray.lastIndex) + "\n";
            nCharInLine+=lpMatchArray.lastIndex;
          }
          else
          {
            if (pLineCut.length != nLineMaxLength && nLine == lpLinesArray.length - 1)
              pContinueLineEnd="";
            else
              pContinueLineEnd="\n";
            lpResultArray[nLine]+=(bParagraph?"":pLineIndent) + pLineCut + pContinueLineEnd;
            nCharInLine+=pLineCut.length;
          }
          nLineMaxLength=nMaxLength - pLineIndent.length;
          bParagraph=false;
        }
      }
      else
      {
        if (lpLinesArray[nLine])
        {
          lpResultArray[nLine]+=(bParagraph?"":pLineIndent) + lpLinesArray[nLine] + pLineEnd;
          nLineMaxLength=nMaxLength - pLineIndent.length;
          bParagraph=false;
        }
        else
        {
          lpResultArray[nLine]+=pLineEnd + pParaIndent;
          nLineMaxLength=nMaxLength - pParaIndent.length;
          bParagraph=true;
        }
      }
      lpResultArray[nLine + 1]="";
      lpLinesArray[nLine]="";
    }
    lpLinesArray=[];

    pSelText=lpResultArray.join("");
    lpResultArray=[];
    if (pLineIndent || pParaIndent)
      pSelText=pSelText.replace(/[ \t]+$/gm, "");

    //Hide progress bar and unlock edit window
    if (hWndProgress)
      oSys.Call("user32::ShowWindow", hWndProgress, 0 /*SW_HIDE*/);
    if (!(dwOptions & 0x1 /*AECO_READONLY*/))
    {
      AkelPad.SendMessage(hWndEdit, 3228 /*AEM_SETOPTIONS*/, 4 /*AECOOP_XOR*/, 0x1 /*AECO_READONLY*/);
      AkelPad.SendMessage(hWndEdit, 3234 /*AEM_EXSETOPTIONS*/, 4 /*AECOOP_XOR*/, 0x2 /*AECOE_LOCKSELECTION*/);
    }
    if (nLineMaxLength >= 0)
      AkelPad.ReplaceSel(pSelText, -2);
  }
}

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

  if (nLangID == 0x19) //LANG_RUSSIAN
  {
    if (nStringID == 0)
      return "\u041C\u0430\u043A\u0441\u0438\u043C\u0430\u043B\u044C\u043D\u044B\u0439\u0020\u0440\u0430\u0437\u043C\u0435\u0440\u0020\u0441\u0442\u0440\u043E\u043A\u0438:";
    if (nStringID == 1)
      return "\u041E\u0442\u0441\u0442\u0443\u043F\u0020\u0431\u043E\u043B\u044C\u0448\u0435\u0020\u043C\u0430\u043A\u0441\u0438\u043C\u0430\u043B\u044C\u043D\u043E\u0439\u0020\u0434\u043B\u0438\u043D\u044B\u0020\u0441\u0442\u0440\u043E\u043A\u0438\u002E";
  }
  else
  {
    if (nStringID == 0)
      return "Maximum line length:";
    if (nStringID == 1)
      return "Indents are more than line limit.";
  }
  return "";
}
