WBStudio.StrCatToColon
;==========================================================================================================================================
; WinBatch Studio Tool
; StrCatToColon
;
; This WBStudio tool "StrCatToColon" converts the method of string concatenation
; from function "StrCat()" to colon ":" character.
; The colon string concatenator was introduced in WB 2006D, Sep 22, 2006, DLL 5.12del.
;
; 20090709: Version 1.01 : Small refinements when bookmarks are not wanted.
; 20090708: Version 1.00 : Initial published.
;
; Detlev Dalitz.20090708.
;==========================================================================================================================================

;------------------------------------------------------------------------------------------------------------------------------------------
; Example for integration into wsp-user.mnu:
;
;   _StrCatToColon ; Convert string concatenation from "StrCat()" to colon ":" character.
;    StrCatToColon
;       Call("W:\WBT\WBSTUDIO\WBStudio.StrCatToColon.wbt",0) ; No bookmarks (default).
;    StrCatToColon (with bookmarks)
;       Call("WD:\WBT\WBSTUDIO\WBStudio.StrCatToColon.wbt",1) ; Set bookmarks.
;------------------------------------------------------------------------------------------------------------------------------------------

;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfStrCatToColon (strString, blnInStrCatLast)
; Recursive function. First call must have set blnInStrCatLast = @FALSE.
If strString == "" Then Return ""
blnInStrCatNow = @FALSE
intPos = 0
intLen = StrLen (strString)
While intPos < intLen
   intPos = intPos + 1
   strChar = StrSub (strString, intPos, 1)
   ; Skip Literals
   If !!StrScan ("""'`", strChar, 1, @FWDSCAN)
      intPos = StrScan (strString, strChar, intPos + 1, @FWDSCAN) + 1
      If intPos >= intLen Then Break
      strChar = StrSub (strString, intPos, 1)
   EndIf
   ; Try to detect "StrCat " or "StrCat(".
   If !blnInStrCatNow
      strProbe = StrSub (strString, intPos, 6)
      If 1 == StrIndexNC (strProbe, "StrCat", 1, @FWDSCAN)
         intPos = intPos + 6
         strChar = StrSub (strString, intPos, 1)
         If StrScan (" (", strChar, 1, @FWDSCAN)
            blnInStrCatNow = @TRUE
            strStringL = StrSub (strString, 1, intPos - 7)
            While " " == StrSub (strString, intPos + 1, 1)
               intPos = intPos + 1
            EndWhile
            strString = StrTrim (StrSub (strString, intPos, -1))
            intLen = StrLen (strString)
            intPos = 1
         Else
            intPos = intPos + 1
         EndIf
         strChar = StrSub (strString, intPos, 1)
      EndIf
   EndIf
   ; Look at char.
   Switch @TRUE
   Case strChar == "("
      intPosEnd = intPos
      intCount = 1
      While intPosEnd < intLen
         intPosEnd = intPosEnd + 1
         strChar = StrSub (strString, intPosEnd, 1)
         If StrScan ("""'`", strChar, 1, @FWDSCAN) Then intPosEnd = StrScan (strString, strChar, intPosEnd + 1, @FWDSCAN)
         intCount = intCount + (strChar == "(")
         intCount = intCount - (strChar == ")")
         If !intCount Then Break
      EndWhile
      intPos = intPos + 1
      intLenSub = intPosEnd - intPos
      If intLenSub
         strResult = udfStrCatToColon (StrSub (strString, intPos, intLenSub), blnInStrCatNow)
         If blnInStrCatNow
            strStringR = StrSub (strString, intPosEnd + 1, -1)
            strString = strStringL : strResult
            blnInStrCatNow = @FALSE
         Else
            strStringR = StrSub (strString, intPosEnd, -1)
            strString = StrSub (strString, 1, intPos - 1) : strResult
         EndIf
         intPos = StrLen (strString)
         strString = strString : strStringR
         intLen = StrLen (strString)
      EndIf
      Break
   Case strChar == ","
      If blnInStrCatLast
         intPosNext = intPos + 1
         While " " == StrSub (strString, intPosNext, 1)
            intPosNext = intPosNext + 1
         EndWhile
         strString = StrSub (strString, 1, intPos - 1) : ":" : StrSub (strString, intPosNext, -1)
         intLen = StrLen (strString)
      EndIf
      Break
   Case strChar == ";"
      intPos = intLen
      Break
   EndSwitch
EndWhile
Return strString
;..........................................................................................................................................
; This function "udfStrCatToColon" converts a WinBatch script codeline
; which contains one or more "StrCat" function calls
; from "StrCat()" notation to ":" (colon) notation.
; The colon string concatenator was introduced in WB 2006D, Sep 22, DLL 5.12del.
;
; Example
;    From:  x = StrCat ("1", "2")
;      To:  x = "1":"2"
;
; Detlev Dalitz.20090618.
;..........................................................................................................................................
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------


intOptionSetBookmarks = @FALSE ; Default is not to set bookmarks.
If param0 Then intOptionSetBookmarks = !!param1

strScriptName = "WBStudio.StrCatToColon"
strMsgTitle = "WinBatch script terminated."
strMsgText = "This WinBatch script " : '"' : strScriptName : '"' : @LF : " is designed only to work from user menu in WinBatch Studio."
Terminate (RtStatus () != 10, strMsgTitle, strMsgText)

strMsgRunning = "Running... " : strScriptName : ": "
strMsgReady = "Ready. " : strScriptName : ": "

intLineNo = wGetLineNo ()
intColNo = wGetColNo ()
If !wGetSelstate ()
   Pause (strScriptName, "Convert entire document?") ; Pressing "Escape" jumps to label :CANCEL.
   wSelectAll ()
EndIf

; Get selection information.
strSelInfo = wSelInfo ()
intSelStartLine = ItemExtract (1, strSelInfo, @TAB)
; intSelStartCol   = ItemExtract (2, strSelInfo, @TAB)
; intSelStopLine   = ItemExtract (3, strSelInfo, @TAB)
; intSelStopCol    = ItemExtract (4, strSelInfo, @TAB)

strListBookmarks = ""
intCount = 0

wCopy ()
arrClip = Arrayize (StrReplace (ClipGet (), @CRLF, @LF), @LF)
intHigh = ArrInfo (arrClip, 1) - 1

If intHigh < 0 Then Goto CANCEL

Exclusive (@ON)
If intOptionSetBookmarks
   For intI = 0 To intHigh
      If !StrIndexNC (arrClip [intI], "StrCat", 1, @FWDSCAN) Then Continue ; Skip lines which have no "StrCat" in there.
      strTemp = arrClip [intI]
      arrClip [intI] = udfStrCatToColon (arrClip [intI], @FALSE)
      If !!StrCmp (strTemp, arrClip [intI])
         strListBookmarks = ItemInsert (intI, -1, strListBookmarks, @TAB) ; Zero based line numbers.
         intCount = intCount + 1
         wStatusMsg (strMsgRunning : intCount)
      EndIf
   Next
Else
   For intI = 0 To intHigh
      If !StrIndexNC (arrClip [intI], "StrCat", 1, @FWDSCAN) Then Continue ; Skip lines which have no "StrCat" in there.
      strTemp = arrClip [intI]
      arrClip [intI] = udfStrCatToColon (arrClip [intI], @FALSE)
      intCount = intCount + !!StrCmp (strTemp, arrClip [intI])
      wStatusMsg (strMsgRunning : intCount)
   Next
EndIf
Exclusive (@OFF)

If !intCount Then Goto CANCEL

strFileTemp = FileCreateTemp ("")
intBytesWritten = ArrayFilePut (strFileTemp, arrClip)
ClipPut (StrSub (FileGet (strFileTemp), 1, intBytesWritten - 2)) ; Remove trailing @CRLF.
FileDelete (strFileTemp)
wPaste ()

If intOptionSetBookmarks
   For intI = 1 To intCount
      wGotoLine (ItemExtract (intI, strListBookmarks, @TAB) + intSelStartLine)
      wSetBookmark ()
   Next
EndIf

:CANCEL
wClearSel ()
wGotoLine (intLineNo)
wGotoCol (intColNo)
wStatusMsg (strMsgReady : intCount)
Drop (arrClip, strListBookmarks)
Exit