;========================================================================================================================================== ; WinBatch Studio Tool ; AddUdfSyntaxToMenu ;------------------------------------------------------------------------------------------------------------------------------------------ ; This WinBatch WBStudio Tool "AddUdfSyntaxToMenu" (runtime filename: "wsp-udf.wbt") embeds menu entries ; for user defined UDFs into the "wspopup.mnu" file under the menu topic "Insert WIL function...". ;------------------------------------------------------------------------------------------------------------------------------------------ ; 20110203: Version 3.00 ; Changed to simple line format in "wsp-udf.mnu" and other enhancements by Detlev Dalitz. ; 20110201: Version 2.00 ; Recoded and enhanced version by Detlev Dalitz. ; 20101211: Version 1.00 ; Initial idea and first code version by Lars M. Doornbos, published in WinBatch forum. ; ; (c)Detlev Dalitz.20110201.20110203. ;========================================================================================================================================== ; ; Installation ; ; - Run this script file. It will create a copy of itself using the name "wsp-udf.wbt" into the ; folder "DirHome() : 'wsp-udf\'" (typically "C:\Program Files\WinBatch\System\wsp-udf\"). ; The new "wsp-udf.wbt" file from within the new folder will be called from the popup menu further on. ; ; - Integration into "wsp-user.mnu", insert this menu entry: ; ------------------------------------------------------------------- ; _Embed UDF Syntax Template Into WBS &Menu ; If wGetSelState () ; wGotoLine (ItemExtract (1, wSelInfo (), @TAB)) ; wClearSel () ; EndIf ; wCopyLine() ; Call (DirHome() : "wsp-udf\wsp-udf.wbt", '"' : ClipGet() : '"') ; Drop (intLine) ; Return ; ------------------------------------------------------------------- ; ;------------------------------------------------------------------------------------------------------------------------------------------ ; ; Usage in WinBatch Studio ; ; - Place the cursor on the script line containing the text "#DefineFunction" resp. "#DefineSubRoutine". ; - Open the context menu (MouseRightClick or [Shift+F10]) and choose "Add UDF Syntax Template To WBS &Menu" from the menu. ; Then the embedding process, using the given text line, will start and "wspopup.mnu" will be updated. ; ;------------------------------------------------------------------------------------------------------------------------------------------ ; ; Additional informations ; ; When needed, this tool creates a backup file in the folder DirHome() : "Backup\" for the files: ; - wspopup.mnu ; - wsp-udf.mnu ; ; The "wsp-udf.mnu" file is not compatible with the WIL "wspopup.mnu" file. ; The "wsp-udf.mnu" file holds lines with each line containing the menu title, the menu item and the comment. ; During the embedding process into the "wspopup.mnu" file, each line will be transformed into the correct WIL menu entry. ; ; Each line in the "wsp-udf.mnu" file holds an item list of three items delimited by the caret character "^". ; Each line has the structure: "<menu_title>^<udf_with_paramlist>^<comment>". ; The menu items in the "wsp-udf.mnu" can be manually edited. ; ; Example: ; ; The UDF menu file "wsp-udf.mnu" ... ; ; |<menu_title>^<udf_with_paramlist>^<comment> ; ------------------------------------------------------------------ ; |My Functions ABC^A_Function (Param1, Param2)^Any Comment. ; |My Functions ABC^B_Function (Param1)^Any Comment. ; |My Functions DEF^F_Function (Param1, Param2, Param3)^Any Comment. ; ------------------------------------------------------------------ ; ; ... will be transformed to "wspopup.mnu" ... ; -------------------------------------------------------------------------------------- ; |Insert WIL Function.... ; Insert function template into document. ; |;[>>> Begin === User Defined Menu Entries ===] ; | User Defined.... ; | My Functions ABC.... ; | A_Function ;^A_Function^(Param1, Param2)^Any Comment. ; | Call(zxc,"A_Function") ; | B_Function ;^B_Function^(Param1)^Any Comment. ; | Call(zxc,"B_Function") ; | My Functions DEF.... ; | F_Function ;^F_Function^(Param1, Param2, Param3)^Any Comment. ; | Call(zxc,"F_Function") ; |;[<<< End === User Defined Menu Entries ===] ; -------------------------------------------------------------------------------------- ; ;========================================================================================================================================== ;------------------------------------------------------------------------------------------------------------------------------------------ #DefineFunction udfStrSplitAtStr (strString, strSplit) ; Split a string into three parts by another string. arrResult = ArrDimension (3) ArrInitialize (arrResult, "") arrResult[0] = strString arrResult[1] = strSplit If !StrIndex (strString, strSplit, 1, @FWDSCAN) Then Return arrResult intPosMax = StrScan (strString, """'`", 1, @FWDSCAN) If intPosMax arrQ = Arrayize ("""*"",'*',`*`", ",") For intQ = 0 To 2 While @TRUE intPos = StrIndexWild (strString, arrQ[intQ], intPosMax) If intPos == 0 Then Break intLen = StrLenWild (strString, arrQ[intQ], intPos) ; strWild = StrSubWild (strString, arrQ[intQ], intPos) intPosMax = intPos + intLen EndWhile Next EndIf intPos = StrIndex (strString, strSplit, intPosMax, @FWDSCAN) If intPos arrResult[0] = StrSub (strString, 1, intPos - 1) ; Leave as is, no trimming. arrResult[2] = StrSub (strString, intPos + StrLen (strSplit), -1) ; Leave as is, no trimming. EndIf Return arrResult ;.......................................................................................................................................... ; This UDF udfStrSplitAtStr splits a given string into three parts, parted by another given string. ; Character sequences in the original string, which are enclosed in pairs of comment chars ; (double quote, single quote, back quote) will be skipped and left untouched. ; ; Example 1 (split): Example 2 (no split): ; strString = "This is a test string." strString = "This is a `test` string." ; strSplit = " test" strSplit = "`test`" ; arrResult[0] = "This is a" arrResult[0] = "This is a `test` string." ; arrResult[1] = " test" arrResult[1] = "`test`" ; arrResult[2] = " string." arrResult[2] = "" ; ; 20110203.Detlev Dalitz. ;.......................................................................................................................................... #EndFunction ;------------------------------------------------------------------------------------------------------------------------------------------ ;------------------------------------------------------------------------------------------------------------------------------------------ #DefineFunction udfItemLocateIndexWild (strPattern, strItemList, intStart, strDelimiter) intCount = ItemCount (strItemList, strDelimiter) For intPos = intStart To intCount If StrIndexWild (ItemExtract (intPos, strItemList, strDelimiter), strPattern, 1) == 1 Then Return intPos Next Return 0 ;.......................................................................................................................................... ; This UDF udfItemLocateIndexWild uses a given pattern string 'strPattern' to search for a similar item in a given itemlist 'strItemList' ; and returns the index position of the first similar item. ; ; The start position for the search is given by parameter 'intStart'. ; For repeated searching increment the parameter 'intStart' accordingly. ; ; Meaning of pattern symbols: '*' matches zero or more characters, '?' matches any one character. ; ; 20110203.Detlev Dalitz. ;.......................................................................................................................................... #EndFunction ;------------------------------------------------------------------------------------------------------------------------------------------ ; Define constants. strMsgTitle = "Embed UDF Syntax Template Into WBS Menu" strMsgTitleTerm = strMsgTitle : " - Terminated" strMsgTextTerm = "Not found ..." : @LF : 'UDF statement "#Define..."' : @LF : @LF : "Try again!" strFolderHome = DirHome () ; WinBatch system folder. strFolderUDF = strFolderHome : "wsp-udf\" ; Our working folder within WinBatch system folder. strFolderBackup = strFolderHome : "Backup\" ; Our backup folder within WinBatch system folder. blnResult = DirMake (strFolderUDF) blnResult = DirMake (strFolderBackup) strFileWspMnu = strFolderHome : "wspopup.mnu" strFileWspUdfWbt = strFolderUDF : "wsp-udf.wbt" ; Use our working folder to hold our wbt file. strFileWspUdfMnu = strFolderUDF : "wsp-udf.mnu" ; Use our working folder to hold our menu file. ;strFileWspUdfWbt = strFolderHome : "wsp-udf.wbt" ; Use WinBatch system folder to hold our wbt file. ;strFileWspUdfMnu = strFolderHome : "wsp-udf.mnu" ; Use WinBatch system folder to hold our menu file. strFileWspMnuBackupMask = "Backup.wspopup.mnu.{1}" strFileWspUdfMnuBackupMask = "Backup.wsp-udf.mnu.{1}" strM0 = "" ; Wspopup menu level 0. strM1 = " " ; Wspopup menu level 1. strM2 = " " ; Wspopup menu level 2. strM3 = " " ; Wspopup menu level 3. strM4 = " " ; Wspopup menu level 4 is code area. ; Get the filename of the currently running script. ; Note: There is a failure with IntControl (77, 72, 0, 0, 0), the last item is missing, what is the filename. ; Note: 20110202 reported to WinBatch. ; Note: Ugly workaround. to detect the filename of the running script from within the Popup Menu system. If RtStatus () == 10 ; WinBatch Studio debug. strFileThis = ItemExtract (4, ItemExtract (1, IntControl (77, 72, 0, 0, 0), @LF), @TAB) ; '1@TABcall@TAB13@TABCall (DirHome() : "wsp-udf\wsp-udf.wbt", strLine) @TAB' ; Structure stack position, structure type, line number, script line, file name strFileThis = ItemRemove (1, strFileThis, "(") strFileThis = ItemRemove (-1, strFileThis, ")") strFileThis = ItemRemove (-1, strFileThis, ",") strFileThis = "strFileThis=" : strFileThis Execute %strFileThis% Else strFileThis = IntControl (1004, 0, 0, 0, 0) ; Pause ("RtStatus", RtStatus ()) EndIf ; Pause ("Debug", strFileThis) ; Put a copy of this file into our system related working folder. If FileExist (strFileWspUdfWbt) == 0 Then blnResult = FileCopy (strFileThis, strFileWspUdfWbt, @FALSE) If FileTimeCode (strFileThis) > FileTimeCode (strFileWspUdfWbt) blnResult = FileCopy (strFileThis, strFileWspUdfWbt, @FALSE) EndIf ; Get parameter from clipboard or command line. If !Param0 ; Get Clipboard content. Clipboard can have other format than text, so catch the error. intEMLast = ErrorMode (@OFF) LastError () strUdf = ClipGet () intLastError = LastError () ErrorMode (intEMLast) Drop (intEMLast) Terminate (intLastError > 0, strMsgTitleTerm : " (1)", strMsgTextTerm) strUdf = StrTrim (strUdf) Terminate (StrIndex (strUdf, "#", 1, @FWDSCAN) != 1, strMsgTitleTerm : " (2)", strMsgTextTerm) Else strUdf = Param1 ; Pause ("Param1",strUdf) EndIf ClipPut ("") ; Clear ClipBoard. ; Check line for keyword starting with "#Define". strUdf = ItemExtract (1, strUdf, @CR) strUdf = ItemExtract (-1, strUdf, @LF) Terminate (StrIndexWild (ItemExtract (1, strUdf, " "), "#define", 1) != 1, strMsgTitleTerm : " (3)", strMsgTextTerm) strUdf = StrTrim (ItemRemove (1, strUdf, " ")) arrResult = udfStrSplitAtStr (strUdf, ";") strUdf = StrTrim (arrResult[0]) strComment = StrTrim (arrResult[2]) ; Prepare list of existing menu entries from "wsp-udf.mnu". strWspUdfs = "" strSubMenus = "" If FileExist (strFileWspUdfMnu) == 1 strWspUdfs = FileGet (strFileWspUdfMnu) strWspUdfs = StrReplace (strWspUdfs, @CRLF, @LF) intCountUdf = ItemCount (strWspUdfs, @LF) For intI = 1 To intCountUdf strItem = StrTrim (ItemExtract (intI, strWspUdfs, @LF)) If strItem == "" Then Continue strSubMenu = ItemExtract (1, strItem, "^") If !ItemLocate (strSubMenu, strSubMenus, @TAB) Then strSubMenus = ItemInsert (strSubMenu, -1, strSubMenus, @TAB) Next ; If no comment is given, then get existing comment, if any. If strComment == "" intPos = udfItemLocateIndexWild ("*^" : strUdf : "*", strWspUdfs, 1, @LF) If intPos strComment = ItemExtract (intPos, strWspUdfs, @LF) strComment = ItemExtract (-1, strComment, "^") EndIf EndIf EndIf ; Ask for a menu entry from the existing entries or let create a new menu entry. strNew = "___New_Submenu___" strAskTitle = "Select Submenu ..." strSubMenus = ItemInsert (strNew, 1, strSubMenus, @TAB) IntControl (28, 1, 0, 0, 0) ; p1=1 fixed pitch font. strSubMenu = AskItemlist (strAskTitle, strSubMenus, @TAB, @SORTED, @SINGLE, @TRUE) ; ToDo: CANCEL processing. If strSubMenu == strNew strPrompt = "Enter Menu Title ..." IntControl (28, 1, 0, 0, 0) ; p1=1 fixed pitch font. strSubMenu = AskLine (strMsgTitle, strPrompt, "") ; ToDo: CANCEL processing. strSubMenu = StrTrim (strSubMenu) EndIf strSubMenuNew = strSubMenu ; Enter comment for the new function entry. strPrompt = "Enter Comment ..." : @LF : @LF : strUdf IntControl (28, 1, 0, 0, 0) ; p1=1 fixed pitch font. strComment = AskLine (strMsgTitle, strPrompt, strComment) ; ToDo: CANCEL processing. strComment = StrTrim (strComment) ; Update "wsp-udf.mnu". strEntry = strSubMenuNew : "^" : strUdf : "^" : strComment intPos = udfItemLocateIndexWild (ItemExtract (1, strEntry, "(") : "*", strWspUdfs, 1, @LF) If intPos strWspUdfs = ItemRemove (intPos, strWspUdfs, @LF) EndIf strWspUdfs = ItemInsert (strEntry, -1, strWspUdfs, @LF) strWspUdfs = ItemSort (strWspUdfs, @LF) strWspUdfs = StrReplace (strWspUdfs, @LF, @CRLF) FilePut (strFileWspUdfMnu, strWspUdfs) ; Update "wspopup.mnu". ; Allow changes to make into "wspopup.mnu". strEntry = StrReplace (StrReplace (strEntry, @TAB, @LF), "^", @LF) strPrompt = 'Insert this entry into "wspopup.mnu"?' : @LF : @LF : strEntry Terminate (@YES != AskYesNo (strMsgTitle, strPrompt), strMsgTitleTerm : " (4)", "No changes." : @LF : @LF : "Ready.") ; Copy current "wspopup.mnu" file to Backup folder. If FileExist (strFileWspMnu) strFileWspMnuBackup = StrReplace (strFileWspMnuBackupMask, "{1}", StrReplace (TimeYmdHms (), ':', '')) blnResult = FileCopy (strFileWspMnu, strFolderBackup : strFileWspMnuBackup, @FALSE) EndIf ; Copy current "wsp-udf.mnu" file to Backup folder. If FileExist (strFileWspUdfMnu) strFileWspUdfMnuBackup = StrReplace (strFileWspUdfMnuBackupMask, "{1}", StrReplace (TimeYmdHms (), ':', '')) blnResult = FileCopy (strFileWspUdfMnu, strFolderBackup : strFileWspUdfMnuBackup, @FALSE) EndIf ; Prepare block markers. strTagBase = "Insert WIL Function" strTagBegin = ";[>>> Begin === User Defined Menu Entries ===]" strTagEnd = ";[<<< End === User Defined Menu Entries ===]" strTagBaseWild = strTagBase : "*" strTagBeginWild = strTagBegin : "*" strTagEndWild = strTagEnd : "*" ; Get current "wspopup.mnu". strWspMnu = FileGet (strFileWspMnu) ; Find current block markers. ;intTagBase = udfItemLocateIndexWild (strTagBaseWild, strWspMnu, 1, @LF) ; For sure. intTagBase = udfItemLocateIndexWild (strTagBaseWild, strWspMnu, 145, @LF) ; In practice. If !StrIndex (ItemExtract (intTagBase + 1, strWspMnu, @LF), strTagBegin, 1, @FWDSCAN) strWspMnu = ItemInsert (strTagEnd : @CR, intTagBase, strWspMnu, @LF) strWspMnu = ItemInsert (strTagBegin : @CR, intTagBase, strWspMnu, @LF) EndIf ; Find block edges. intTagBegin = udfItemLocateIndexWild (strTagBeginWild, strWspMnu, intTagBase + 1, @LF) intTagEnd = udfItemLocateIndexWild (strTagEndWild, strWspMnu, intTagBegin + 1, @LF) ; Create new block entry. strUdfBlockNew = " User Defined...." : @CR strWspUdfs = StrReplace (strWspUdfs, @CR, "") intCountUdf = ItemCount (strWspUdfs, @LF) strSubMenuPrev = "" For intI = 1 To intCountUdf strItem = ItemExtract (intI, strWspUdfs, @LF) If strItem == "" Then Continue strSubMenu = ItemExtract (1, strItem, "^") If strSubMenu != strSubMenuPrev strUdfBlockNew = ItemInsert (strM2 : strSubMenu : "...." : @CR, -1, strUdfBlockNew, @LF) strSubMenuPrev = strSubMenu EndIf strUdf = ItemExtract (2, strItem, "^") strComment = ItemExtract (-1, strItem, "^") strUdfName = StrTrim (ItemExtract (1, strUdf, "(")) strUdfParms = "(" : ItemExtract (2, strUdf, "(") strLine = strM3 : strUdfName : " ;^" : strUdfName : "^" : strUdfParms strLine1 = strLine : "^" : strComment strUdfBlockNew = ItemInsert (strLine1 : @CR, -1, strUdfBlockNew, @LF) strLine2 = strM4 : 'Call(zxc,"' : strUdfName : '")' strUdfBlockNew = ItemInsert (strLine2 : @CR, -1, strUdfBlockNew, @LF) Next ; Get old block. strUdfBlockOld = "" intFirst = intTagBegin + 1 intLast = intTagEnd - 1 For intI = intFirst To intLast strUdfBlockOld = ItemInsert (ItemExtract (intI, strWspMnu, @LF), -1, strUdfBlockOld, @LF) Next ; If old block is the same as the new block, then exit. Terminate (strUdfBlockOld == strUdfBlockNew, strMsgTitleTerm : " (5)", "Ready. (No changes)") ; Remove old block. For intI = intFirst To intLast strWspMnu = ItemRemove (intTagBegin + 1, strWspMnu, @LF) Next ; Insert new block. intCount = ItemCount (strUdfBlockNew, @LF) For intI = intCount To 1 By -1 strItem = ItemExtract (intI, strUdfBlockNew, @LF) strWspMnu = ItemInsert (strItem, intTagBegin, strWspMnu, @LF) Next ; Write new file "wspopup.mnu". FilePut (strFileWspMnu, strWspMnu) ; Display what line has been added. strMsgText = "Added menu entry:" : @LF : @LF : strEntry : @LF : @LF : "Ready." : @LF : @LF : "(WIL menus will be reloaded on the next usage.)" Message (strMsgTitle, strMsgText) :CANCEL Exit ; Test cases. #DefineFunction A_Function (Param1, Param2) ; Any Comment. #EndFunction #DefineFunction B_Function (Param1) ; Any Comment. #EndFunction #DefineFunction F_Function (Param1, Param2, Param3) ; Any Comment about F_Function. #EndFunction