WBT2HTML v3.11
Download: WBT2HTML v3.11 and more as zip package
;==========================================================================================================================================
; WBT2HTML v3.11  20090709                                                                                        (c)20010729.Detlev Dalitz
;==========================================================================================================================================
:Main
IntControl (73, 1, 0, 0, 0) ; On Error Goto Label :WBERRORHANDLER

sFolderStart = DirGet ()

GoSub DefineUDF
GoSub SetMyInitsFirst
GoSub CheckWBVersion
GoSub CheckTempFolder
GoSub CheckIni

GoSub GetParams
If (iResult == -1) Then Goto CANCEL
If (iResult == 0)
   GoSub AskParams
   GoSub GetParams
   If (iResult == -1) Then Goto CANCEL
EndIf

If UseVerbose
   BoxOpen ("", "")
   BoxTitle (sProgLogoLong)
Else
   WinPlaceSet (@NORMAL, "", "0 0 600 0")
   WinActivate ("")
EndIf

sFileInGUID = udfGetGUID ()
sFileInCrc = udfGetFileChecksum (sFileIn, 2)
sFileInName = '"' : ItemExtract (-1, ItemExtract (-1, sFileIn, ":"), "\") : '"'
GoSub WriteLog
GoSub CreateTempFilenames
GoSub LoadCAMKeyword
GoSub CreateCAMColor
GoSub CreateListColorUsed
GoSub ConvertSourceFile
If UseLineNumberLen Then GoSub AddLineNumber
GoSub CreateListColorUsed
GoSub DefineMasks
GoSub CreateWriteTargetFile
GoSub WriteLog

If UseVerbose
   sMsgText = sFileOut : @LF : "Ready."
   BoxText (sMsgText)
EndIf

; Run standard browser application.
If UseRunOutput Then If FileSizeEx (sFileOut) > 0 Then Run (sFileOut, "")

:CANCEL
GoSub DeleteTempFilenames
If UseVerbose Then BoxShut ()
DirChange (sFolderStart)
Exit
;==========================================================================================================================================




;==========================================================================================================================================
:SetMyInitsFirst
;------------------------------------------------------------------------------------------------------------------------------------------
; Current script version.
sProgProduct = "WBT2HTML"
sProgVersion = "3.11"
sProgVersionDate = "20090709"

; Needed WinBatch version.
sVersionDLLWB = "4.0gda"
sVersionDateWB = "WB 2003G 30 Jun 2003"

; Needed xCAM extender version.
sFileExtCAM = "xCAM34i.dll"
sVersionDLLExtCAM = "34030"

; Associated inifile.
sFileMyIni = sProgProduct : ".ini"
Return
;==========================================================================================================================================



;==========================================================================================================================================
:SetMyInits
;------------------------------------------------------------------------------------------------------------------------------------------
; Create section WBT2HTML
sProgCreationDate = "20010729"
sProgCompanyName = "Detlev Dalitz"
sProgCopyright = "(c){1} {2}"
sProgCopyright = StrReplace (sProgCopyright, "{1}", sProgCreationDate)
sProgCopyright = StrReplace (sProgCopyright, "{2}", sProgCompanyName)
IniWritePvt (sProgProduct, "InternalName", "wbt2html.wbt", sFileMyIni)
IniWritePvt (sProgProduct, "FileVersion", sProgVersion, sFileMyIni)
IniWritePvt (sProgProduct, "FileVersionDate", sProgVersionDate, sFileMyIni)
IniWritePvt (sProgProduct, "FileDescription", "WBT to coloured HTML Script Converter", sFileMyIni)
IniWritePvt (sProgProduct, "OriginalFilename", "WBT2HTML.WBT", sFileMyIni)
IniWritePvt (sProgProduct, "ProductName", sProgProduct, sFileMyIni)
IniWritePvt (sProgProduct, "ProductVersion", "3", sFileMyIni)
IniWritePvt (sProgProduct, "CompanyName", sProgCompanyName, sFileMyIni)
IniWritePvt (sProgProduct, "LegalCopyright", sProgCopyright, sFileMyIni)
IniWritePvt (sProgProduct, "CreationDate", sProgCreationDate, sFileMyIni)
IniWritePvt (sProgProduct, "Comments", "emailto:dd@dalitz-im-netz.de", sFileMyIni)
IniWritePvt (sProgProduct, "YmdHms", TimeYmdHms (), sFileMyIni)
;..........................................................................................................................................
; Create section User.
IniWritePvt ("USER", "UseAllowOverwrite", "0", sFileMyIni)
IniWritePvt ("USER", "UseAskFilename", "", sFileMyIni)
IniWritePvt ("USER", "UseCase", "4", sFileMyIni)
IniWritePvt ("USER", "UseImageBg", "", sFileMyIni)
IniWritePvt ("USER", "UseMakeHtmlTag", "0", sFileMyIni)
IniWritePvt ("USER", "UseHtmlShortComment", "0", sFileMyIni)
IniWritePvt ("USER", "UseNoIndentation", "0", sFileMyIni)
IniWritePvt ("USER", "UseRGB", "0", sFileMyIni)
IniWritePvt ("USER", "UseRunOutput", "1", sFileMyIni)
IniWritePvt ("USER", "UseTabReplaceSize", "3", sFileMyIni)
IniWritePvt ("USER", "UseVerbose", "1", sFileMyIni)
IniWritePvt ("USER", "UseWriteLogfile", "1", sFileMyIni)
IniWritePvt ("USER", "UseLineNumberLen", "0", sFileMyIni)
IniWritePvt ("USER", "UseLineNumberFiller", " ", sFileMyIni)
IniWritePvt ("USER", "UseLineNumberLink", "2", sFileMyIni)

IniDeletePvt ("USERINFO", @WHOLESECTION, sFileMyIni)
IniWritePvt ("USERINFO", "UseAllowOverwrite..=", "> Suppress dialog when overwriting existing target html file may occur.", sFileMyIni)
IniWritePvt ("USERINFO", "UseAskFilename.....=", "> Local URL of recently used folder from AskFilename dialog.", sFileMyIni)
IniWritePvt ("USERINFO", "UseCase............=", "> 4=Case as defined in WIL.CLR, 3=Uppercase, 2=Lowercase, 1=Leave as is.", sFileMyIni)
IniWritePvt ("USERINFO", "UseImageBg.........=", "> Web related URL to the background image.", sFileMyIni)
IniWritePvt ("USERINFO", "UseMakeHtmlTag.....=", "> 0=PRE tag only, 1=PRE tag embedded in HTML tag.", sFileMyIni)
IniWritePvt ("USERINFO", "UseHtmlShortComment=", "> 0=Standard tag '<!--', 1=Short tag '<!' for use in WinBatch forum.", sFileMyIni)
IniWritePvt ("USERINFO", "UseNoIndentation...=", "> 0=Leave indentation as is, 1=Shift all lines to the left margin.", sFileMyIni)
IniWritePvt ("USERINFO", "UseRGB.............=", "> Font mode: 0='#000000', 1='rgb(0,0,0)'", sFileMyIni)
IniWritePvt ("USERINFO", "UseRunOutput.......=", "> Run standard browser application after converting.", sFileMyIni)
IniWritePvt ("USERINFO", "UseTabReplaceSize..=", "> Replace each @TAB with n spaces.", sFileMyIni)
IniWritePvt ("USERINFO", "UseVerbose.........=", "> Info: 0=none, 1=normal, 2=more, 3=more detailed.", sFileMyIni)
IniWritePvt ("USERINFO", "UseWriteLogfile....=", "> 0=No logfile, 1=Inistyle logfile will be created in a WBT2HTML subfolder of the current user tempfolder.", sFileMyIni)
IniWritePvt ("USERINFO", "UseLineNumberLen...=", "> The width of the line number. 0=no number, -1=current max width, n=fix width of n chars.", sFileMyIni)
IniWritePvt ("USERINFO", "UseLineNumberFiller=", "> The padchar of the line number.", sFileMyIni)
IniWritePvt ("USERINFO", "UseLineNumberLink..=", "> 0=None, 1=A_NAME, 2=A_NAME and A_HREF.", sFileMyIni)
;..........................................................................................................................................
; Create section COLORS.
IniWritePvt ("COLORS", "CON", "128,000,128", sFileMyIni)
IniWritePvt ("COLORS", "EXT", "255,000,255", sFileMyIni)
IniWritePvt ("COLORS", "CONSTANT", "000,128,255", sFileMyIni)
IniWritePvt ("COLORS", "WED", "000,128,000", sFileMyIni)
IniWritePvt ("COLORS", "Operator", "032,032,032", sFileMyIni)
IniWritePvt ("COLORS", "Number", "096,000,000", sFileMyIni)
IniWritePvt ("COLORS", ";Bracket", "000,128,000", sFileMyIni)
IniWritePvt ("COLORS", ";Special", "000,032,128", sFileMyIni)
IniWritePvt ("COLORS", "LineNumber", "160,160,160", sFileMyIni)
IniWritePvt ("COLORS", "Background", "253,253,253", sFileMyIni)
;..........................................................................................................................................
; Create section CAMColor.
IniWritePvt ("CAMColor", "URL", "", sFileMyIni)
IniWritePvt ("CAMColor", "YmdHms", "", sFileMyIni)
IniWritePvt ("CAMColor", "MD5", "", sFileMyIni)
;..........................................................................................................................................
; Create section CAMKeyword.
IniWritePvt ("CAMKeyword", "URL", "", sFileMyIni)
IniWritePvt ("CAMKeyword", "YmdHms", "", sFileMyIni)
IniWritePvt ("CAMKeyword", "MD5", "", sFileMyIni)
;..........................................................................................................................................
; Create section xCAM.
IniWritePvt ("xCAM", "URL", "", sFileMyIni)
IniWritePvt ("xCAM", "YmdHms", "", sFileMyIni)
IniWritePvt ("xCAM", "MD5", "", sFileMyIni)
;..........................................................................................................................................
; Create section WIL.CLR.
sFileWilClr = "WIL.CLR"
IniWritePvt ("WIL.CLR", "URL", sFileWilClr, sFileMyIni)
IniWritePvt ("WIL.CLR", "YmdHms", "", sFileMyIni)
IniWritePvt ("WIL.CLR", "MD5", "", sFileMyIni)
;..........................................................................................................................................
; Create section MyClr.
sFileMyClr = sProgProduct : ".clr"
sSection = StrUpper (sFileMyClr)
IniWritePvt (sSection, "URL", sFileMyClr, sFileMyIni)
IniWritePvt (sSection, "YmdHms", "", sFileMyIni)
IniWritePvt (sSection, "MD5", "", sFileMyIni)
;..........................................................................................................................................
IniWritePvt ("", "", "", sFileMyIni)
;..........................................................................................................................................
Return
;==========================================================================================================================================



;==========================================================================================================================================
:CheckWBVersion
;------------------------------------------------------------------------------------------------------------------------------------------
; Make sure to have a proper WinBatch version.
iTermBool = VersionDLL () < sVersionDLLWB
If iTermBool
   sTermTitle = "Error"
   sTermText = "This WinBatch script needs a WinBatch version of '{1} ({2})' or newer."
   sTermText = StrReplace (sTermText, "{1}", sVersionDLLWB)
   sTermText = StrReplace (sTermText, "{2}", sVersionDateWB)
   Terminate (iTermBool, sTermTitle, sTermText)
EndIf
Return
;==========================================================================================================================================



;==========================================================================================================================================
:CheckTempFolder
;------------------------------------------------------------------------------------------------------------------------------------------
sFolderTemp = udfGetTempPath ()
iTermBool = !DirMake (sFolderTemp)
If iTermBool
   sTermTitle = "Error"
   sTermText = "Cannot access current user temp folder:" : @LF : "{1}"
   sTermText = StrReplace (sTermText, "{1}", sFolderTemp)
   Terminate (iTermBool, sTermTitle, sTermText)
EndIf

sFolderTemp = sFolderTemp : sProgProduct : "\"
iTermBool = !DirMake (sFolderTemp)
If iTermBool
   sTermTitle = "Error"
   sTermText = "Cannot create subfolder in current user temp folder:" : @LF : "{1}"
   sTermText = StrReplace (sTermText, "{1}", sFolderTemp)
   Terminate (iTermBool, sTermTitle, sTermText)
EndIf

Return
;==========================================================================================================================================



;==========================================================================================================================================
:CheckIni
;------------------------------------------------------------------------------------------------------------------------------------------
; The inifile must reside in the same folder as the script.
sFolderProgHome = FilePath (IntControl (1004, 0, 0, 0, 0))
sFolderProgHome = udfGetLongPathNameA (sFolderProgHome)
If (sFolderProgHome != "") Then sFileMyIni = FileMapName (sFileMyIni, sFolderProgHome)

sIniYmdHms = IniReadPvt (sProgProduct, "YmdHms", "", sFileMyIni)
If (sIniYmdHms == "")
   GoSub SetMyInits
EndIf

GoSub ReadIni

Switch @TRUE
Case @TRUE
   sSection = "WIL.CLR"
   sURL = IniReadPvt (sSection, "URL", "", sFileMyIni)
   Switch @TRUE
   Case (sURL == "")
      GoSub ForceUpdate
      Break
   Case FileSizeEx (sURL) == 0
      GoSub ForceUpdate
      Break
   Case (IniReadPvt (sSection, "YmdHms", "", sFileMyIni) != FileYmdHms (sURL))
      GoSub ForceUpdate
      Break
   Case (IniReadPvt (sSection, "MD5", "", sFileMyIni) != udfGetFileChecksum (sURl, 0))
      GoSub ForceUpdate
      Break
   EndSwitch
   Continue
Case @TRUE
   sSection = sProgProduct
   Switch @TRUE
   Case (IniReadPvt (sSection, "FileVersion", "", sFileMyIni) != sProgVersion)
      GoSub SetMyInits
      GoSub ForceUpdate
      Break
   Case (IniReadPvt (sSection, "FileVersionDate", "", sFileMyIni) != sProgVersionDate)
      GoSub SetMyInits
      GoSub ForceUpdate
      Break
   Case (IniReadPvt (sSection, "ProductName", "", sFileMyIni) != sProgProduct)
      GoSub SetMyInits
      GoSub ForceUpdate
      Break
   EndSwitch
   Continue
Case @TRUE
   sSection = "xCAM"
   sURL = IniReadPvt (sSection, "URL", "", sFileMyIni)
   Switch @TRUE
   Case (sURL == "")
      GoSub ForceUpdate
      Break
   Case FileSizeEx (sURL) == 0
      GoSub ForceUpdate
      Break
   Case (IniReadPvt (sSection, "YmdHms", "", sFileMyIni) != FileYmdHms (sURL))
      GoSub ForceUpdate
      Break
   Case (IniReadPvt (sSection, "MD5", "", sFileMyIni) != udfGetFileChecksum (sURl, 0))
   Case 0
      GoSub ForceUpdate
      Break
   EndSwitch
   Continue
Case @TRUE
   sSection = "CAMKeyword"
   sURL = IniReadPvt (sSection, "URL", "", sFileMyIni)
   Switch @TRUE
   Case (sURL == "")
      GoSub ForceUpdate
      Break
   Case FileSizeEx (sURL) == 0
      GoSub ForceUpdate
      Break
   Case (IniReadPvt (sSection, "YmdHms", "", sFileMyIni) != FileYmdHms (sURL))
      GoSub ForceUpdate
      Break
   Case (IniReadPvt (sSection, "MD5", "", sFileMyIni) != udfGetFileChecksum (sURl, 0))
      GoSub ForceUpdate
      Break
   EndSwitch
   Continue
   ; Following Case block is deactivated because we want to read the current colors on each run.
   ;   Case @TRUE
   ;      sSection = "CAMColor"
   ;      sURL = IniReadPvt (sSection, "URL", "", sFileMyIni)
   ;      Switch @TRUE
   ;      Case FileSizeEx (sURL) == 0
   ;         GoSub ForceUpdate
   ;         Break
   ;      Case (IniReadPvt (sSection, "YmdHms", "", sFileMyIni) != FileYmdHms (sURL))
   ;         GoSub ForceUpdate
   ;         Break
   ;      Case (IniReadPvt (sSection, "MD5", "", sFileMyIni) != udfGetFileCheckSum (sURl, 0))
   ;         GoSub ForceUpdate
   ;         Break
   ;      EndSwitch
   ;      Continue
EndSwitch
Return
;==========================================================================================================================================



;==========================================================================================================================================
:ForceUpdate
;------------------------------------------------------------------------------------------------------------------------------------------
sMsgText = "Installation is going to be refreshed now ..."
Pause (sProgLogoLong, sMsgText)

; Check WIL.CLR
GoSub FindFileMyClr

; Check Extender xCAM.
GoSub FindFileExtCAM

; Check Keyword CAM table.
GoSub CreateCAMKeyword

; Check Color CAM table.
GoSub CreateCAMColor

Return
;------------------------------------------------------------------------------------------------------------------------------------------



;==========================================================================================================================================
:ReadIni
;------------------------------------------------------------------------------------------------------------------------------------------
UseWriteLogfile = IniReadPvt ("User", "UseWriteLogfile", 1, sFileMyIni)
UseMakeHtmlTag = IniReadPvt ("User", "UseMakeHtmlTag", 0, sFileMyIni)
UseHtmlShortComment = IniReadPvt ("User", "UseHtmlShortComment", 0, sFileMyIni)
UseNoIndentation = IniReadPvt ("User", "UseNoIndentation", 0, sFileMyIni)
UseTabReplaceSize = IniReadPvt ("User", "UseTabReplaceSize", 3, sFileMyIni)
UseVerbose = IniReadPvt ("User", "UseVerbose", 0, sFileMyIni)
UseCase = IniReadPvt ("User", "UseCase", 4, sFileMyIni)
UseRGB = IniReadPvt ("User", "UseRGB", 0, sFileMyIni)
UseRunOutput = IniReadPvt ("User", "UseRunOutput", 1, sFileMyIni)
UseImageBg = IniReadPvt ("User", "UseImageBg", "", sFileMyIni)
UseProgHome = IniReadPvt ("User", "UseProgHome", "", sFileMyIni)
UseAskFilename = IniReadPvt ("User", "UseAskFilename", "", sFileMyIni)
UseAllowOverwrite = IniReadPvt ("USER", "UseAllowOverwrite", 0, sFileMyIni)
UseLineNumberLen = IniReadPvt ("USER", "UseLineNumberLen", 0, sFileMyIni)
UseLineNumberFiller = IniReadPvt ("USER", "UseLineNumberFiller", " ", sFileMyIni)
UseLineNumberLink = IniReadPvt ("USER", "UseLineNumberLink", 2, sFileMyIni)

sFileWilClr = IniReadPvt ("WIL.CLR", "URL", "", sFileMyIni)
sFileMyClr = IniReadPvt (sProgProduct : ".CLR", "URL", "", sFileMyIni)

sProgCopyright = IniReadPvt (sProgProduct, "LegalCopyright", "", sFileMyIni)
sProgLogoLong = "{1} v{2} {3}          {4}"
sProgLogoLong = StrReplace (sProgLogoLong, "{1}", sProgProduct)
sProgLogoLong = StrReplace (sProgLogoLong, "{2}", sProgVersion)
sProgLogoLong = StrReplace (sProgLogoLong, "{3}", sProgVersionDate)
sProgLogoLong = StrReplace (sProgLogoLong, "{4}", sProgCopyright)
Return
;------------------------------------------------------------------------------------------------------------------------------------------


;==========================================================================================================================================
:FindFileMyClr
;------------------------------------------------------------------------------------------------------------------------------------------
; Note: For compiled scripts: DirHome () returns the path to the compiled EXE file.

Switch RtStatus ()
Case 0  ; "WinBatch Interpreted Script"
Case 10 ; "WinBatch Studio Debug"
   sDirHome = udfGetLongPathNameA (DirHome ())
   Break
Case 1  ; "Compiled WinBatch EXE file"
Case 5  ; "Compiled WinBatch Service (EXS file)"
Case 14 ; "WebBatch"
Case 13 ; "PopMenu"
Case 12 ; "FileMenu"
   ; Find out if there exist a WinBatch interpreter environment with a WIL.CLR file.
   sRegSubKey = "SOFTWARE\Wilson WindowWare\WinBatch\CurrentVersion"
   If RegExistKey (@REGMACHINE, sRegSubKey)
      hRegKey = RegOpenKey (@REGMACHINE, sRegSubKey)
      sDirHome = RegQueryStr (hRegKey, "")
   EndIf
   sDirHome = udfGetLongPathNameA (sDirHome)
   sDirHome = sDirHome : "System\"
   Break
EndSwitch

If (sDirHome != "")
   ;sFileWilClr = ItemExtract (-1, itemExtract (-1, sFileWilClr, ":"), "\") ; FileRootExt.
   sFileWilClr = FileBaseName (sFileWilClr)
   sFileWilClr = sDirHome : sFileWilClr
EndIf

iTermBool = FileSizeEx (sFileWilClr) == 0
If iTermBool
   sTermTitle = "Error"
   sTermText = "Cannot access file 'WIL.CLR':" : @LF : "{1}"
   sTermText = StrReplace (sTermText, "{1}", sFileWilClr)
   Terminate (iTermBool, sTermTitle, sTermText)
EndIf

sFolderProgHome = udfGetLongPathNameA (sFolderProgHome)
;sFileMyClr = ItemExtract (-1, itemExtract (-1, sFileMyClr, ":"), "\") ; FileRootExt.
sFileMyClr = FileBaseName (sFileMyClr)
sFileMyClr = sFolderProgHome : sFileMyClr

iTermBool = !FileCopy (sFileWilClr, sFileMyClr, @TRUE)
WinActivate ("") ; Get back to the main window.
If iTermBool
   sTermTitle = "Error"
   sTermText = "Cannot copy 'WIL.CLR' to 'WBT2HTML.CLR':" : @LF : "{1}" : @LF : "{2}"
   sTermText = StrReplace (sTermText, "{1}", sFileWilClr)
   sTermText = StrReplace (sTermText, "{2}", sFileMyClr)
   Terminate (iTermBool, sTermTitle, sTermText)
EndIf


;sSection = ItemExtract (-1, itemExtract (-1, sFileWilClr, ":"), "\") ; FileRootExt.
sSection = FileBaseName (sFileWilClr)
sSection = StrUpper (sSection)
IniWritePvt (sSection, "URL", sFileWilClr, sFileMyIni)
IniWritePvt (sSection, "YmdHms", FileYmdHms (sFileWilClr), sFileMyIni)
IniWritePvt (sSection, "MD5", udfGetFileChecksum (sFileWilClr, 0), sFileMyIni)
IniWritePvt ("", "", "", sFileMyIni)

;sSection = ItemExtract (-1, itemExtract (-1, sFileMyClr, ":"), "\") ; FileRootExt.
sSection = FileBaseName (sFileMyClr)
sSection = StrUpper (sSection)
IniWritePvt (sSection, "URL", sFileMyClr, sFileMyIni)
IniWritePvt (sSection, "YmdHms", FileYmdHms (sFileMyClr), sFileMyIni)
IniWritePvt (sSection, "MD5", udfGetFileChecksum (sFileMyClr, 0), sFileMyIni)
IniWritePvt ("", "", "", sFileMyIni)

Drop (iTermBool, sTermText, sTermTitle)
Return
;==========================================================================================================================================



;==========================================================================================================================================
:FindFileExtCAM
;------------------------------------------------------------------------------------------------------------------------------------------
; Note: For compiled scripts: DirHome () returns the path to the compiled EXE file.
sDirHome = udfGetLongPathNameA (DirHome ())
;sFileExtCAM = ItemExtract (-1, itemExtract (-1, sFileExtCAm, ":"), "\") ; FileRootExt.
sFileExtCAM = FileBaseName (sFileExtCAM)
sFileExtCAM = FileMapName (sFileExtCAm, sDirHome)

iTermBool = FileSizeEx (sFileExtCAM) == 0
If iTermBool
   sTermTitle = "Error"
   sTermText = "Cannot access file 'xCAM34i.dll':" : @LF : "{1}"
   sTermText = StrReplace (sTermText, "{1}", sFileWilClr)
   Terminate (iTermBool, sTermTitle, sTermText)
EndIf

iTermBool = !AddExtender (sFileExtCAm, sVersionDLLExtCAM)
If iTermBool
   sTermTitle = "Error"
   sTermText = "Cannot load extender file 'xCAM34i.dll':" : @LF : "{1}"
   sTermText = StrReplace (sTermText, "{1}", sFileExtCAM)
   Terminate (iTermBool, sTermTitle, sTermText)
EndIf

IniWritePvt ("xCAM", "URL", sFileExtCAM, sFileMyIni)
IniWritePvt ("xCAM", "YmdHms", FileYmdHms (sFileExtCAM), sFileMyIni)
IniWritePvt ("xCAM", "MD5", udfGetFileChecksum (sFileExtCAm, 0), sFileMyIni)
IniWritePvt ("xCAM", "VersionDLL", camExtenderInfo (0), sFileMyIni)
IniWritePvt ("", "", "", sFileMyIni)

Drop (iTermBool, sTermText, sTermTitle)
Return
;==========================================================================================================================================



;==========================================================================================================================================
:CollectColors
;------------------------------------------------------------------------------------------------------------------------------------------
; Collect names and rgb color values.
; We use the default rgb color values as defined in WSINIT.DLL
; and try to update them from the Current User Registry.
sListColorName = "Keyword|Quote|Comment|Default Text|Background"
sListColorValue = "0,0,255|255,0,0|0,128,0|0,0,0|255,255,255"
sListColorName = StrReplace (sListColorName, "|", @TAB)
sListColorValue = StrReplace (sListColorValue, "|", @TAB)

;--- Read colors for WIL files from WinBatch Studio Registry. -----------------------------------------------------------------------------
sRegKeySub = "Software\Wilson WindowWare\WinBatch Studio\Settings\File types\WIL Files"
If RegExistKey (@REGCURRENT, sRegKeySub)
   hRegKey = RegOpenKeyEx (@REGCURRENT, sRegKeySub, 1, "", "")
   ; Mode=1=KEY_QUERY_VALUE=Permission to query subkey data ; We only need read access.

   iCount = ItemCount (sListColorName, @TAB)
   For ii = 1 To iCount
      sItemColorName = ItemExtract (ii, sListColorName, @TAB)
      sRegKeySub = "[" : sItemColorName : "]"
      If RegExistValue (hRegKey, sRegKeySub)
         sItemColorValue = RegQueryValue (hRegKey, sRegKeySub)
         sListColorValue = ItemReplace (sItemColorValue, ii, sListColorValue, @TAB)
      EndIf
   Next
   Drop (ii, iCount)

   RegCloseKey (hRegKey)
   Drop (hRegKey, sItemColorName, sItemColorValue)
EndIf
Drop (sRegKeySub)


;--- Additional colors from WIL.CLR -------------------------------------------------------------------------------------------------------
; Resp. from WBT2HTML.CLR (just a copy of WIL.CLR)
; For example: CON=128,0,128; EXT=255,0,255; CONSTANT=0,128,255; WED=0,128,0; UDF=128,096,048; OPERATOR=0,48,128

sColorList = IniItemizePvt ("COLORS", sFileMyClr)
iCount = ItemCount (sColorList, @TAB)
For ii = 1 To iCount
   sItemColorName = ItemExtract (ii, sColorList, @TAB)
   sItemColorValue = IniReadPvt ("COLORS", sItemColorName, "000,000,000", sFileMyClr)
   sListColorValue = ItemInsert (sItemColorValue, -1, sListColorValue, @TAB)
   sListColorName = ItemInsert (sItemColorName, -1, sListColorName, @TAB)
Next
Drop (ii, iCount)
Drop (sItemColorName, sItemColorValue)


;--- Additional colors from my own inspiration. -------------------------------------------------------------------------------------------
; Note: The color settings in the WBT2HTML.ini file have at least
; the highest priority against all other previous color settings.

sIniSection = "COLORS"
sIniList = IniItemizePvt (sIniSection, sFileMyIni)
iCount = ItemCount (sIniList, @TAB)
For ii = 1 To iCount
   sIniKey = ItemExtract (ii, sIniList, @TAB)
   sIniValue = IniReadPvt (sIniSection, sIniKey, "0,0,0", sFileMyIni)
   sListColorName = ItemInsert (sIniKey, -1, sListColorName, @TAB)
   sListColorValue = ItemInsert (sIniValue, -1, sListColorValue, @TAB)
Next
Drop (ii, iCount, sIniKey, sIniList, sIniSection, sIniValue)


;------------------------------------------------------------------------------------------------------------------------------------------
; Set all color name items to lower case.
; Delete duplicates, last item in list will win.
; This is implicitely done by putting items into CAM array.

aColorName = camArrayFromList (sListColorName, @TAB, 0)
aColorValue = camArrayFromList (sListColorValue, @TAB, 0)
aCAMTemp = camCAMFromArray (camArrayMerge (aColorName, 1, aColorValue, 0, 1), 0, 1)
Drop (aColorName, aColorName)

aColorName = camArrayFromList (camKeyList (aCAMTemp, @TAB, 0), @TAB, 0)
aColorValue = camArrayFromList (camDataList (aCAMTemp, @TAB, 0), @TAB, 0)
Drop (aCAMTemp)

; 1. If UseRGB==1 Then format as rgb(r,g,b).
; 2. If UseRGB==0 Then format as hex #rrggbb.

iHigh = ArrInfo (aColorValue, 1) - 1
If UseRGB
   For ii = 0 To iHigh
      iRGB_R = 0 + ItemExtract (1, aColorValue[ii], ",")
      iRGB_G = 0 + ItemExtract (2, aColorValue[ii], ",")
      iRGB_B = 0 + ItemExtract (3, aColorValue[ii], ",")
      aColorValue[ii] = "rgb(" : iRGB_R : "," : iRGB_G : "," : iRGB_b : ")"
   Next
Else
   For ii = 0 To iHigh
      iRGB_R = 0 + ItemExtract (1, aColorValue[ii], ",")
      iRGB_G = 0 + ItemExtract (2, aColorValue[ii], ",")
      iRGB_B = 0 + ItemExtract (3, aColorValue[ii], ",")
      aColorValue[ii] = "000000"
      If (iRGB_R | iRGB_G | iRGB_B) Then aColorValue[ii] = udfByteToHex (iRGB_R) : udfByteToHex (iRGB_G) : udfByteToHex (iRGB_B)
      aColorValue[ii] = "#" : aColorValue[ii]
   Next
EndIf
Drop (ii, iHigh)
DropWild ("iRGB*")

Return
;==========================================================================================================================================



;==========================================================================================================================================
:CreateListColorUsed
;------------------------------------------------------------------------------------------------------------------------------------------
; First Call.
If !IsDefined (aCAMColorUsed)
   aCAMColorUsed = camInit (ItemCount (camKeyList (aCAMColor, @TAB, 0), @TAB))
   Return
EndIf
;..........................................................................................................................................
;Second Call.
; Create a list of used colors to embed in htm output file, for information purpose only.
sListColorNameUsed = camKeyList (aCAMColorUsed, @TAB, 0)
sListHtmColor = ""
iCount = ItemCount (sListColorNameUsed, @TAB)
For ii = 1 To iCount
   sColorName = ItemExtract (ii, sListColorNameUsed, @TAB)
   GoSub GetColorValue
   sListHtmColor = ItemInsert ('"' : sColorName : '"="' : sColorValue : '"', -1, sListHtmColor, ";")
Next
Drop (ii, iCount)
Drop (sListColorNameUsed, sColorName, sColorValue)
Drop (aCAMColorUsed)
Return
;------------------------------------------------------------------------------------------------------------------------------------------



;==========================================================================================================================================
:CreateCAMKeyword
;------------------------------------------------------------------------------------------------------------------------------------------
sMsgText = "Creating CAM Keyword ... be patient ..."
If (UseVerbose >= 1)
   BoxText (sMsgText)
EndIf

; Write CAM data to my inifile.
sFileCAMKeyword = sFolderProgHome : sProgProduct : ".cam.keyword.txt"
IniWritePvt ("CAMKeyword", "URL", sFileCAMKeyword, sFileMyIni)


If !IsDefined (aCAMKeyword)
   AddExtender (sFileExtCAM)

   ; This implements a fast read routine for reading large section from an inifile.
   ; All lines of inifile must be terminated by @CRLF sequence.

   ; Read my .CLR file completely into a string.
   ; Insert one helper @LF at the beginning of the stream, and one helper @CR at end of stream.
   sIni = @LF : FileGet (sFileMyClr) : @CR

   ; Remove empty lines.
   sSearch = @LF : @CR
   sReplace = ""
   While StrIndex (sIni, sSearch, 1, @FWDSCAN)
      sIni = StrReplace (sIni, sSearch, sReplace)
   EndWhile

   ; For sure, remove leading blanks.
   sSearch = @LF : " "
   sReplace = @LF
   While StrIndex (sIni, sSearch, 1, @FWDSCAN)
      sIni = StrReplace (sIni, sSearch, sReplace)
   EndWhile

   ; Find the proper section and skip over section header line.
   iScan = StrIndexNC (sIni, "[keywords]", 1, @FWDSCAN)
   If !iScan
      sTermTitle = "Error"
      sTermText = "Inifile is damaged:" : @LF : "{1}"
      sTermText = StrReplace (sTermText, "{1}", sFileWilClr)
      Terminate (@TRUE, sTermTitle, sTermText)
   EndIf
   iScan = StrIndex (sIni, @LF, iScan, @FWDSCAN)
   If !iScan
      sTermTitle = "Error"
      sTermText = "Inifile is damaged:" : @LF : "{1}"
      sTermText = StrReplace (sTermText, "{1}", sFileWilClr)
      Terminate (@TRUE, sTermTitle, sTermText)
   EndIf
   iSection = iScan

   ; Find end of section.
   iScan = StrIndex (sIni, @LF : "[", iScan, @FWDSCAN)
   ; Get section.
   If iScan
      sIni = StrSub (sIni, iSection, iScan - iSection + 1)
   Else
      sIni = StrSub (sIni, iSection, -1)
   EndIf

   ; Delete comment lines.
   sSearch = @LF : ";"
   sSearchWild = @LF : ";*" : @CR
   iScan = 0
   While @TRUE
      iScan = StrIndex (sIni, sSearch, iScan, @FWDSCAN)
      If !iScan Then Break
      sWild = StrSubWild (sIni, sSearchWild, iScan)
      sIni = StrReplace (sIni, sWild, "")
   EndWhile

   ; Remove all @CR.
   sIni = StrReplace (sIni, @CR, "")

   ; Remove blanks around the equal sign separator.
   sReplace = "="
   sSearch = " ="
   While StrIndex (sIni, sSearch, 1, @FWDSCAN)
      sIni = StrReplace (sIni, sSearch, sReplace)
   EndWhile
   sSearch = "= "
   While StrIndex (sIni, sSearch, 1, @FWDSCAN)
      sIni = StrReplace (sIni, sSearch, sReplace)
   EndWhile

   ; Change color=1 to color=Keyword, as defined in Registry.
   sIni = StrReplace (sIni, "=1", "=Keyword")

   ; Read list of key=value items into Dim2-array. Skip helper @LF.
   aTemp = camArrayFromList (StrSub (sIni, 2, -1), @LF : "=", 0)

   ; Swap and merge array columns.
   aTemp0 = camArrayRange (aTemp, "*,0", "*,0")      ; Giving the key column.
   aTemp1 = camArrayRange (aTemp, "*,1", "*,1")      ; Giving the value column.
   aTemp = camArrayMerge (aTemp1, 1, aTemp0, 0, 1)  ; Giving two columns: value, key.
   aTemp = camArrayFromList (camArrayToList (aTemp, @LF : @TAB, 0), @LF, 0) ; Giving one column of value@TABkey items.
   aTemp = camArrayMerge (aTemp0, 1, aTemp, 0, 1)    ; Giving two columns: key, value@TABkey.
   Drop (aTemp0, aTemp1)

   ;Create CAM array.
   aCAMKeyword = camCAMFromArray (aTemp, 0, 1)
   Drop (aTemp)

EndIf


If (UseVerbose > 1)
   sMsgText = "Saving CAM Keyword ..."
   BoxText (sMsgText)
EndIf

iTermBool = !camArrayToFile (aCAMKeyword, sFileCAMKeyword)
If iTermBool
   sTermTitle = "Error"
   sTermText = "Cannot write CAM file:" : @LF : "{1}"
   sTermText = StrReplace (sTermText, "{1}", sFileCAMKeyword)
   Terminate (iTermBool, sTermTitle, sTermText)
EndIf

; Write CAM data to my inifile.
IniWritePvt ("CAMKeyword", "YmdHms", FileYmdHms (sFileCAMKeyword), sFileMyIni)
IniWritePvt ("CAMKeyword", "MD5", udfGetFileChecksum (sFileCAMKeyword, 0), sFileMyIni)
IniWritePvt ("", "", "", sFileMyIni)

; Write CLR data to my inifile.
;sSection = ItemExtract (-1, itemExtract (-1, sFileMyClr, ":"), "\") ; FileRootExt.
sSection = FileBaseName (sFileMyClr)
sSection = StrUpper (sSection)
IniWritePvt (sSection, "URL", sFileMyClr, sFileMyIni)
IniWritePvt (sSection, "YmdHms", FileYmdHms (sFileMyClr), sFileMyIni)
IniWritePvt (sSection, "MD5", udfGetFileChecksum (sFileMyClr, 0), sFileMyIni)
IniWritePvt ("", "", "", sFileMyIni)

If (UseVerbose > 1)
   If FileSizeEx (sFileCAMKeyword) > 0
      sMsgText = "Saving CAM Keyword ... OK"
      BoxText (sMsgText)
   EndIf
EndIf

Drop (aTemp, iScan, iTermBool, sIni)
Drop (sMsgText, sReplace, sSearch, sTermText, sTermTitle, sWild)

Return
;==========================================================================================================================================



;==========================================================================================================================================
:CreateCAMColor
;------------------------------------------------------------------------------------------------------------------------------------------
sMsgText = "Creating CAM Color ... be patient ..."
If (UseVerbose >= 1)
   BoxText (sMsgText)
EndIf

GoSub CollectColors

If !IsDefined (aCAMColor)
   AddExtender (sFileExtCAM)

   aCAMColor = camCAMFromArray (camArrayMerge (aColorName, 1, aColorValue, 0, 1), 0, 1)

EndIf
Drop (aColorName, aColorValue) ; We do not need the color lists any longer.


;........................................................................................
; User may activate or deactivate following Goto to enable or disable creating disk file.
Goto skip
;........................................................................................


If (UseVerbose > 1)
   sMsgText = "Saving CAM Color ..."
   BoxText (sMsgText)
EndIf

; Write filename of my keyword CAM table into my inifile.
sFileCAMColor = sFolderProgHome : sProgProduct : ".cam.color.txt"
IniWritePvt ("CAMColor", "URL", sFileCAMColor, sFileMyIni)

iTermBool = !camArrayToFile (aCAMColor, sFileCAMColor)
If iTermBool
   sTermTitle = "Error"
   sTermText = "Cannot write CAM file:" : @LF : "{1}"
   sTermText = StrReplace (sTermText, "{1}", sFileCAMColor)
   Terminate (iTermBool, sTermTitle, sTermText)
EndIf

IniWritePvt ("CAMColor", "YmdHms", FileYmdHms (sFileCAMColor), sFileMyIni)
IniWritePvt ("CAMColor", "MD5", udfGetFileChecksum (sFileCAMColor, 0), sFileMyIni)
IniWritePvt ("", "", "", sFileMyIni)

If (UseVerbose > 1)
   If FileSizeEx (sFileCAMColor) > 0
      sMsgText = "Saving CAM Color ... OK"
      BoxText (sMsgText)
   EndIf
EndIf

;........................................................................................
:skip
;........................................................................................

Drop (i, iCount, iTermBool, sMsgText, sTermText, sTermTitle)
Return
;==========================================================================================================================================



;==========================================================================================================================================
:DefineUDF
;==========================================================================================================================================
#DefineFunction udfGetTempPath ()
sFileTemp = FileCreateTemp ("")
FileDelete (sFileTemp)
sFolderTemp = FilePath (sFileTemp)
Terminate (!DirMake (sFolderTemp), "udfGetTempPath", "Cannot access temporary folder:" : @LF : sFolderTemp)
Return sFolderTemp
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGetLongPathNameA (sPath)
iMAX_PATH = 260
hBB = BinaryAlloc (iMAX_PATH)
BinaryEodSet (hBB, iMAX_PATH)
iLength = DllCall (DirWindows (1) : "KERNEL32.DLL", long : "GetLongPathNameA", lpstr : sPath, lpbinary : hBB, long : iMAX_PATH)
sLongPathName = BinaryPeekStr (hBB, 0, iLength)
BinaryFree (hBB)
Return sLongPathName
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfByteToHex (Byte)
Return Num2Char (48 + (Byte >> 4) + (39 * ((Byte >> 4) > 9))) : Num2Char (48 + (Byte & 15) + (39 * ((Byte & 15) > 9))) ; lowercase.
; Return StrCat (Num2Char (48 + (Byte>>4) + (7 * ((Byte>>4) > 9))), Num2Char (48 + (Byte&15) + (7 * ((Byte&15) > 9)))) ; UPPERCASE.
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGetFileChecksum (sFilename, iRequest)
;If (VersionDLL () < "3.8hch") Then Return ""
iBBSize = FileSizeEx (sFilename)
If !iBBSize Then Return ""
hBB = BinaryAlloc (iBBSize)
BinaryRead (hBB, sFilename)
sChecksum = BinaryChecksum (hBB, Min (2, Max (0, iRequest)))
BinaryFree (hBB)
Return sChecksum
;..........................................................................................................................................
;   Request Meaning    Return String Format (x=hex character)
;   0       MD5 digest "xxxxxxxx-xxxxxxxx-xxxxxxxx-xxxxxxxx"
;   1       16-bit CRC "xxxx"
;   2       32-bit CRC "xxxxxxxx"
;..........................................................................................................................................
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGetFileLineCount (strFilename)
hdlBB = BinaryAlloc (FileSize (strFilename, 1))
intLines = BinaryStrCnt (hdlBB, 0, BinaryRead (hdlBB, strFilename) - 1, @LF)
hdlBB = BinaryFree (hdlBB)
Return intLines
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGetGUID ()
intBBSizeHex = 16
hdlBB = BinaryAlloc (intBBSizeHex)
BinaryEodSet (hdlBB, intBbSizeHex)
DllCall (DirWindows (1) : "OLE32.DLL", long : "CoCreateGuid", lpbinary : hdlBB)
strGUIDHex = BinaryPeekHex (hdlBB, 0, intBBSizeHex)
hdlBB = BinaryFree (hdlBB)
Return strGUIDHex
;..........................................................................................................................................
; Returns a 128-bit-GUID as a string of 16 hex values, i. e. 32 ansi chars, e. g. "402380BC5856214AA956C7EE6D4A084A".
;..........................................................................................................................................
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
Return ; from "GoSub DefineUDF"
;==========================================================================================================================================



;==========================================================================================================================================
:DefineMasks
;------------------------------------------------------------------------------------------------------------------------------------------
sHtmComment = "<!--" ; Standard HTML comment opening tag.
If UseHtmlShortComment Then sHtmComment = "<!" ; Shorted tag for use in WinBatch forum.
sMaskHtmPre = sHtmComment : ' [{1}] Colorized HTML by {2} v{3} {4} -->' : @CRLF
sMaskHtmPre = sMaskHtmPre : sHtmComment : ' {5} -->' : @CRLF
sMaskHtmPre = sMaskHtmPre : '<pre id="GUID_{17}_CRC32_{16}" style="{6}{7}{8}{9}{10}{11}{12}{13}{14}{15}" title="Colorized by {2} v{3}">' : @CRLF
sMaskHtmPre = sMaskHtmPre : '{18}'
;sMaskHtmPre = StrCat (sMaskHtmPre, '<script type="text/javascript">function CopyParentToClipboard(oObject){var r=document.body.createControlRange();r.add(oObject.parentElement);r.execCommand("Copy");}</script>', @CRLF)
;sMaskHtmPre = StrCat (sMaskHtmPre, '<input style="border:1pt dashed #dddddd; background-color:#fafafa; width:150px; color:navy; cursor:hand; " ')
;sMaskHtmPre = StrCat (sMaskHtmPre, 'type="button" title="Copy script to clipboard" alt="Copy script to clipboard" value="Copy script to clipboard" onclick="CopyParentToClipboard(this);">', @CRLF)
sMaskHtmPre = sMaskHtmPre : '</pre>' : @CRLF


If UseMakeHtmlTag Then sMaskHtmPre = '<html>' : @CRLF : '<body>' : @CRLF : sMaskHtmPre : '</body>' : @CRLF : '</html>' : @CRLF
; {1}  TimeYmdHms ()
; {2}  sProgProduct
; {3}  sProgVersion
; {4}  sProgCopyright
; {5}  sListHtmColor
; {6}  sStyleImageBg
; {7}  sStyleColorBg
; {8}  sStyleBorder
; {9}  sStylePadding
; {10} sStyleWidth
; {11} sStyleFontFamily
; {12} sStyleFontSize
; {13} sStyleFontWeight
; {14} sStyleFontStyle
; {15} sStyleColorFg
; {16} CRC32 checksum number of the sFileIn, used as id attribute.
; {17} GUID, used as id attribute.
; {18} Content of sFileOut2
;..........................................................................................................................................
sStyleBorder = 'border:1pt solid #dddddd; '
sStylePadding = 'padding:3pt; '
sStyleWidth = 'width:100%%; '
;..........................................................................................................................................
sMaskStyleFontFamily = "font-family:'{1}'; "
sMaskStyleFontSize = "font-size:{1}pt; "
sMaskStyleFontWeight = "font-weight:{1}; "
sMaskStyleFontStyle = "font-style:{1}; "
sMaskStyleColorBg = "background-color:{1}; "
sMaskStyleColorFg = "color:{1}; "
sMaskStyleImageBg = "background-image:url({1}); "
;..........................................................................................................................................
; Set background image from inifile entry, e. g. "UseImageBg=../images/gif/grid.gif".
sStyleImageBg = ""
sImageBg = IniReadPvt ("User", "UseImageBg", "", sFileMyIni)
If (sImageBg != "") Then sStyleImageBg = StrReplace (sMaskStyleImageBg, "{1}", sImageBg)
Drop (sImageBg)
;..........................................................................................................................................
; Get font attributes for WIL files.

; Set default font style attributes.
sFontFamily = "Courier New"
sFontSize = "9"
sFontWeight = "400"
sFontStyle = "0"

; Read font attributes for WIL files from WinBatch Studio Registry.
sRegKeySub = "Software\Wilson WindowWare\WinBatch Studio\Settings\File types\WIL Files"
If RegExistKey (@REGCURRENT, sRegKeySub)
   hRegKey = RegOpenKeyEx (@REGCURRENT, sRegKeySub, 1, "", "")
   ; Mode=1=KEY_QUERY_VALUE=Permission to query subkey data ; We only need read access.
   sRegKeySub = "[Font name]"
   If RegExistValue (hRegKey, sRegKeySub) Then sFontFamily = RegQueryValue (hRegKey, sRegKeySub)
   sRegKeySub = "[Font size]"
   If RegExistValue (hRegKey, sRegKeySub) Then sFontSize = RegQueryValue (hRegKey, sRegKeySub)
   sRegKeySub = "[Font weight]"
   If RegExistValue (hRegKey, sRegKeySub) Then sFontWeight = RegQueryValue (hRegKey, sRegKeySub)
   sRegKeySub = "[Font Italic]"
   If RegExistValue (hRegKey, sRegKeySub) Then sFontStyle = RegQueryValue (hRegKey, sRegKeySub)
   RegCloseKey (hRegKey)
   Drop (hRegKey, sRegKeySub)
EndIf
sFontStyle = ItemExtract (1 + sFontStyle, "normal, italic", ",") ; Translate number to string.
;..........................................................................................................................................
sStyleFontStyle = StrReplace (sMaskStyleFontStyle, "{1}", sFontStyle)
sStyleFontFamily = StrReplace (sMaskStyleFontFamily, "{1}", sFontFamily)
sStyleFontSize = StrReplace (sMaskStyleFontSize, "{1}", sFontSize)
sStyleFontWeight = StrReplace (sMaskStyleFontWeight, "{1}", sFontWeight)
;..........................................................................................................................................
sColorValueBg = camGet (aCAMColor, "Background")
sColorValueFg = camGet (aCAMColor, "Default Text")
If UseRGB
   sColorValueBg = StrReplace ("rgb({1})", "{1}", sColorValueBg)
   sColorValueFg = StrReplace ("rgb({1})", "{1}", sColorValueFg)
EndIf
sStyleColorBg = StrReplace (sMaskStyleColorBg, "{1}", sColorValueBg)
sStyleColorFg = StrReplace (sMaskStyleColorFg, "{1}", sColorValueFg)
;..........................................................................................................................................
Return
;------------------------------------------------------------------------------------------------------------------------------------------



;==========================================================================================================================================
:LoadCAMKeyword
;------------------------------------------------------------------------------------------------------------------------------------------
If (UseVerbose > 1)
   sMsgText = "Loading CAM Keyword ..."
   BoxText (sMsgText)
EndIf

sFileCAMKeyword = IniReadPvt ("CAMKeyword", "URL", "", sFileMyIni)

iTermBool = FileSizeEx (sFileCAMKeyword) == 0
If iTermBool
   sTermTitle = "Error"
   sTermText = "Cannot access CAM file:" : @LF : "{1}"
   sTermText = StrReplace (sTermText, "{1}", sFileCAMkeyword)
   Terminate (iTermBool, sTermTitle, sTermText)
EndIf

If !IsDefined (aCAMKeyword)
   AddExtender (sFileExtCAM)
   aCAMKeyword = camArrayFromFile (sFileCAMKeyword)
   iTermBool = !camCheck (aCAMKeyword)
   If iTermBool
      sTermTitle = "Error"
      sTermText = "Execution halted." : @LF : "This array dumpfile seems not to be a valid CAM array:" : @LF : "{1}"
      sTermText = StrReplace (sTermText, "{1}", sFileCAMKeyword)
      Terminate (iTermBool, sTermTitle, sTermText)
   EndIf
EndIf

Return
;------------------------------------------------------------------------------------------------------------------------------------------



;==========================================================================================================================================
:LoadCAMColor
;------------------------------------------------------------------------------------------------------------------------------------------
If (UseVerbose > 1)
   sMsgText = "Loading CAM Color ..."
   BoxText (sMsgText)
EndIf

sFileCAMColor = IniReadPvt ("CAMColor", "URL", "", sFileMyIni)

iTermBool = FileSizeEx (sFileCAMColor) == 0
If iTermBool
   sTermTitle = "Error"
   sTermText = "Cannot access CAM file:" : @LF : "{1}"
   sTermText = StrReplace (sTermText, "{1}", sFileCAMColor)
   Terminate (iTermBool, sTermTitle, sTermText)
EndIf

If !IsDefined (aCAMColor)
   AddExtender (sFileExtCAM)
   aCAMColor = camArrayFromFile (sFileCAMColor)
   iTermBool = !camCheck (aCAMColor)
   If iTermBool
      sTermTitle = "Error"
      sTermText = "Execution halted." : @LF : "This array dumpfile seems not to be a valid CAM array:" : @LF : "{1}"
      sTermText = StrReplace (sTermText, "{1}", sFileCAMColor)
      Terminate (iTermBool, sTermTitle, sTermText)
   EndIf
EndIf

Return
;------------------------------------------------------------------------------------------------------------------------------------------



;==========================================================================================================================================
:GetColorValue
;------------------------------------------------------------------------------------------------------------------------------------------
If (sColorName == "") Then sColorName = "default text"
sColorValue = camGet (aCAMColor, sColorName)
If (sColorValue == "*EOF*CAM*")
   sColorValue = "#000000"
   If UseRGB Then sColorValue = "rgb(0,0,0)"
EndIf
Return
;------------------------------------------------------------------------------------------------------------------------------------------



;==========================================================================================================================================
:ConvertSourceFile
;------------------------------------------------------------------------------------------------------------------------------------------
sMaskMsg1 = sFileIn : @LF : "Converting ... line # {1}/{2}"
sMaskMsg2 = sProgProduct : "  " : sFileInName : "  Converting line # {1}/{2}"
sMaskMsg3 = sFileIn : @LF : "Colorizing word ({1}) ..." : @LF : "{2}"
;..........................................................................................................................................
; Note: Ampersand char is mostly a safe char, but it is not safe when encoding of named entities is done by global StrReplace.
sSafeChars = "&0123456789@$_/\!?,.;:=-+*'()[]# abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" ; Included ampersand.
sEncChars = ""
For ii = 1 To 255
   sEncChars = sEncChars : Num2Char (ii)
Next
sEncChars = StrClean (sEncChars, sSafeChars, "", @TRUE, 1)
sEncChars = "&" : sEncChars ; Add Ampersand in the first position.

sOperatorChars = "=<>!*/+-&|^~"
sQuoteChars = """'`"
sBracketChars = "()[]{}"
sSpecialChars = ",@#:%%"
sNumChars = "0123456789"
sCommentChar = ";"
; sAlphaChars  = all chars from the ansi charset excluding the above defined subsets.
sStopChars = " =,:()[]!*/+-&|^~<>@#:."

sColorName = "Default Text"
GoSub GetColorValue
sMaskFontDefault = '<span style="color:' : sColorValue : '">{1}</span>'
sFontPoint = '<span style="color:' : sColorValue : '">.</span>'

sColorName = "Operator"
GoSub GetColorValue
sMaskFontOperator = '<span style="color:' : sColorValue : '">{1}</span>'

sColorName = "Comment"
GoSub GetColorValue
sMaskFontComment = '<span style="color:' : sColorValue : '">{1}</span>'

sColorName = "Special"
GoSub GetColorValue
sMaskFontSpecial = '<span style="color:' : sColorValue : '">{1}</span>'

sColorName = "Bracket"
GoSub GetColorValue
sMaskFontBracket = '<span style="color:' : sColorValue : '">{1}</span>'

sColorName = "Number"
GoSub GetColorValue
sMaskFontNumber = '<span style="color:' : sColorValue : '">{1}</span>'

sColorName = "Quote"
GoSub GetColorValue
sMaskFontQuote = '<span style="color:' : sColorValue : '">{1}</span>'

sMaskFontName = '<span style="color:{1}">{2}</span>'

;sColorName        = "Default Text"
;GoSub GetColorValue
;sMaskFontDefault  = StrCat ('<font color="', sColorValue, '">{1}</font>')
;sFontPoint        = StrCat ('<font color="', sColorValue, '">.</font>')
;
;sColorName        = "Operator"
;GoSub GetColorValue
;sMaskFontOperator = StrCat ('<font color="', sColorValue, '">{1}</font>')
;
;sColorName        = "Comment"
;GoSub GetColorValue
;sMaskFontComment  = StrCat ('<font color="', sColorValue, '">{1}</font>')
;
;sColorName        = "Special"
;GoSub GetColorValue
;sMaskFontSpecial  = StrCat ('<font color="', sColorValue, '">{1}</font>')
;
;sColorName        = "Bracket"
;GoSub GetColorValue
;sMaskFontBracket  = StrCat ('<font color="', sColorValue, '">{1}</font>')
;
;sColorName        = "Number"
;GoSub GetColorValue
;sMaskFontNumber   = StrCat ('<font color="', sColorValue, '">{1}</font>')
;
;sColorName        = "Quote"
;GoSub GetColorValue
;sMaskFontQuote    = StrCat ('<font color="', sColorValue, '">{1}</font>')
;
;sMaskFontName     = '<font color="{1}">{2}</font>'
;.......................................................................................................................................
;iInputLines = ItemCount (FileGet (sFileIn), @LF)- (StrSub (FileGet (sFileIn), fileSize (sFileIn), 1)==@LF)
iInputLines = udfGetFileLineCount (sFileIn)
;.......................................................................................................................................
If (UseVerbose > 1)
   sMsgText = sFileIn : @LF : "Reading ..."
   BoxText (sMsgText)
EndIf

iLastIC65 = IntControl (65, 4096 * Min (64, 1 + (FileSize (sFileIn) / 4096)), 0, 0, 0) ; Set size of internal FileRead buffer.
hFR = FileOpen (sFileIn, "READ")
;..........................................................................................................................................
If (UseVerbose > 1)
   sMsgText = sFileOut1 : @LF : "Writing ..."
   BoxText (sMsgText)
EndIf

IntControl (53, 1, 0, 0, 0) ; Set line terminator for FileWrite. p1: 0=None, 1=@CRLF, 2=@LF, 3=@CR, 4=@TAB.
If UseLineNumberLen Then hFW = FileOpen (sFileOut1, "WRITE")
   Else hFW = FileOpen (sFileOut2, "WRITE")
;..........................................................................................................................................

iLastExclusive = Exclusive (@ON)

sCurrent = ""  ; Current line to scan.
iCountLine = 0 ; Linecounter.
While @TRUE
   sCurrent = FileRead (hFR)
   ;If iCountLine > 100 Then sCurrent="*EOF*" ; Debug.

   If (sCurrent == ";;;") Then Break ; My Breaker.
   If (sCurrent == "*EOF*") Then Break
   ; Note: If a line in the input file begins with the text "*EOF*",
   ; then the loop ends at this line.
   ; That can make the file not read entirely.

   iCountLine = iCountLine + 1

   If (sCurrent == "")
      FileWrite (hFw, "")
      Continue
   EndIf

   ; Replace tabs with white spaces.
   sCurrent = StrReplace (sCurrent, @TAB, StrFill (" ", useTabReplaceSize))

   ; Always trim right and optional trim left.
   sCurrent = ItemExtract (2, StrTrim (@LF : sCurrent), @LF)
   If UseNoIndentation Then sCurrent = StrTrim (sCurrent)

   If (sCurrent == "")
      FileWrite (hFw, "")
      Continue
   EndIf

   If UseVerbose
      sMsgText = StrReplace (StrReplace (sMaskMsg1, "{1}", iInputLines), "{2}", iCountLine)
      BoxText (sMsgText)
   Else
      sMsgText = StrReplace (StrReplace (sMaskMsg2, "{1}", iInputLines), "{2}", iCountLine)
      WinTitle ("", sMsgText)
   EndIf


   sOut = ""
   aCurrent = camArrayFromList (" " : sCurrent, "", 0)
   iCount = ArrInfo (aCurrent, 1)

   iCurrent = 1
   While (iCurrent < iCount)
      Switch @TRUE

      ; Operators.
      Case !!StrIndex (sOperatorChars, aCurrent[iCurrent], 1, @FWDSCAN)
         Switch StrIndex ("<>&", aCurrent[iCurrent], 1, @FWDSCAN)
         Case 1
            sTemp = StrReplace (sMaskFontOperator, "{1}", "&#60;")
            Break
         Case 2
            sTemp = StrReplace (sMaskFontOperator, "{1}", "&#62;")
            Break
         Case 3
            sTemp = StrReplace (sMaskFontOperator, "{1}", "&#38;")
            Break
         Case 0
            sTemp = StrReplace (sMaskFontOperator, "{1}", aCurrent[iCurrent])
            Break
         EndSwitch

         iCurrent = iCurrent + 1

         camPut (aCAMColorUsed, "Operator", "")
         Break

      ; Quotes.
      Case !!StrIndex (sQuoteChars, aCurrent[iCurrent], 1, @FWDSCAN)
         sQuote = aCurrent[iCurrent]
         iCurrent = iCurrent + 1
         iScanStart = iCurrent
         iCurrent = StrIndex (sCurrent, sQuote, iScanStart, @FWDSCAN)

         If iCurrent
            sTemp = StrSub (sCurrent, iScanStart, iCurrent - iScanStart)

            If (StrTrim (sTemp) != "")
               ; Encode named entities.
               sClean = StrClean (sEncChars, sTemp, "", @TRUE, 2)
               iCleanCount = StrLen (sClean)
               For iClean = 1 To iCleanCount
                  sChar = StrSub (sClean, iClean, 1)
                  sTemp = StrReplace (sTemp, sChar, StrReplace ("&#n;", "n", Char2Num (sChar)))
               Next

               sTemp = StrReplace (sMaskFontQuote, "{1}", sTemp)
            EndIf

            sQuote = StrReplace (sMaskFontDefault, "{1}", sQuote)
            sTemp = sQuote : sTemp : sQuote
         Else
            sTemp = StrReplace (sMaskFontDefault, "{1}", sQuote)
         EndIf

         iCurrent = iCurrent + 1

         camPut (aCAMColorUsed, "Quote", "")
         Break

      ; Comments.
      Case !!StrIndex (sCommentChar, aCurrent[iCurrent], 1, @FWDSCAN)
         sTemp = StrSub (sCurrent, iCurrent, -1)

         ; Encode named entities.
         sClean = StrClean (sEncChars, sTemp, "", @TRUE, 2)
         iCleanCount = StrLen (sClean)
         For iClean = 1 To iCleanCount
            sChar = StrSub (sClean, iClean, 1)
            sTemp = StrReplace (sTemp, sChar, StrReplace ("&#n;", "n", Char2Num (sChar)))
         Next

         sTemp = StrReplace (sMaskFontComment, "{1}", sTemp)

         iCurrent = iCount

         camPut (aCAMColorUsed, "Comment", "")
         Break

      ; Blank char needs no colorizing.
      Case (" " == aCurrent[iCurrent])
         sTemp = " "
         iCurrent = iCurrent + 1
         Break

      ; Numbers, integer and float including decimal point.
      Case !!StrIndex (sNumChars, aCurrent[iCurrent], 1, @FWDSCAN)
         iPoint = @FALSE
         iScanStart = iCurrent
         iCurrent = iCurrent + 1
         While (iCurrent < iCount)
            If !StrIndex (sNumChars, aCurrent[iCurrent], 1, @FWDSCAN)
               If ("." == aCurrent[iCurrent]) Then iPoint = @TRUE
                  Else Break
            EndIf
            iCurrent = iCurrent + 1
         EndWhile

         sTemp = StrSub (sCurrent, iScanStart, iCurrent - iScanStart)

         If iPoint
            sNum1 = ItemExtract (1, sTemp, ".")
            sNum2 = ItemExtract (2, sTemp, ".")
            sNum1 = StrReplace (sMaskFontNumber, "{1}", sNum1)
            If (sNum2 != "")
               sNum2 = StrReplace (sMaskFontNumber, "{1}", sNum2)
               sTemp = sNum1 : sFontPoint : sNum2
            Else
               sTemp = sNum1 : sFontPoint
            EndIf
         Else
            sTemp = StrReplace (sMaskFontNumber, "{1}", sTemp)
         EndIf

         camPut (aCAMColorUsed, "Number", "")
         Break

      ; Brackets.
      Case !!StrIndex (sBracketChars, aCurrent[iCurrent], 1, @FWDSCAN)
         sTemp = StrReplace (sMaskFontBracket, "{1}", aCurrent[iCurrent])
         iCurrent = iCurrent + 1
         camPut (aCAMColorUsed, "Bracket", "")
         Break

      ; Special chars.
      Case !!StrIndex (sSpecialChars, aCurrent[iCurrent], 1, @FWDSCAN)
         sTemp = StrReplace (sMaskFontSpecial, "{1}", aCurrent[iCurrent])
         iCurrent = iCurrent + 1
         camPut (aCAMColorUsed, "Special", "")
         Break

      ; All other chars are variable names and keywords.
      Case @TRUE
         iScanStart = iCurrent + 1
         iCurrent = StrScan (sCurrent, sStopChars, iScanStart, @FWDSCAN)
         If iCurrent
            sTemp = StrSub (sCurrent, iScanStart - 1, iCurrent - iScanStart + 1)
         Else
            sTemp = StrSub (sCurrent, iScanStart - 1, -1)
            iCurrent = iCount
         EndIf

         If (sTemp != "")
            ; Find word in Keyword CAM Table, get colorname and standard writing.
            sColorName = "default text"
            sKeywordValue = camGet (aCAMKeyword, sTemp)
            If (sKeywordValue != "*EOF*CAM*")
               sColorName = ItemExtract (1, sKeywordValue, @TAB)
               Switch UseCase
               Case 4
                  sTemp = ItemExtract (2, sKeywordValue, @TAB)
                  Break
               Case 3
                  sTemp = StrUpper (sTemp)
                  Break
               Case 2
                  sTemp = StrLower (sTemp)
                  Break
               Case 1
                  ; sTemp = sTemp ; Freestyle, no change.
                  Break
               EndSwitch
            EndIf
            If (UseVerbose > 2)
               sMsgText = StrReplace (StrReplace (sMaskMsg3, "{1}", sColorName), "{2}", sTemp)
               BoxText (sMsgText)
            EndIf

            GoSub GetColorValue
            sTemp = StrReplace (StrReplace (sMaskFontName, "{1}", sColorValue), "{2}", sTemp)
         EndIf

         camPut (aCAMColorUsed, sColorName, 0)
         Break

      EndSwitch

      sOut = sOut : sTemp
   EndWhile

   FileWrite (hFw, sOut)
EndWhile

Exclusive (iLastExclusive)

;..........................................................................................................................................
If (UseVerbose > 1)
   sMsgText = sFileOut1 : @LF : "Closing ..."
   BoxText (sMsgText)
EndIf

FileClose (hFW)
;..........................................................................................................................................
If (UseVerbose > 1)
   sMsgText = sFileIn : @LF : "Closing ..."
   BoxText (sMsgText)
EndIf

FileClose (hFR)
;..........................................................................................................................................
Drop (aCurrent, hFr, hFw, i, iClean, iCleanCount, iCount)
Drop (iCurrent, iLastExclusive, iLastIC65, iPoint, iScanStart, sBracketChars, sChar)
Drop (sClean, sColorName, sCommentChar, sCurrent, sEncChars, sFontPoint, sKeywordValue, sMaskFontBracket)
Drop (sMaskFontComment, sMaskFontDefault, sMaskFontNumber, sMaskFontOperator, sMaskFontQuote, sMaskFontSpecial, sMsgText, sNum1)
Drop (sNum2, sNumChars, sOperatorChars, sOut, sQuote, sQuoteChars, sSafeChars, sSpecialChars)
Drop (sTemp)
Return
;------------------------------------------------------------------------------------------------------------------------------------------



;==========================================================================================================================================
:AddLineNumber
;------------------------------------------------------------------------------------------------------------------------------------------
sMaskFont = '<font color="{1}">{2}</font>'
;..........................................................................................................................................
sColorName = "LineNumber"
GoSub GetColorValue
;..........................................................................................................................................
iLineNoLen = UseLineNumberLen
If (UseLineNumberLen < 0) Then iLineNoLen = StrLen (iInputLines)
;..........................................................................................................................................
Switch UseLineNumberLink
Case 2
   ;   sMaskAnchorId = '<a id="id{1}_{2}" href="#id{1}_{2}">{3}</a>'
   ;   sMaskAnchorId = StrReplace (sMaskAnchorId, "{1}", sFileInCrc)
   sMaskAnchorId = '<a id="{2}" href="#{2}">{3}</a>'
   Break
Case 1
   ;   sMaskAnchorId = '<a id="id{1}_{2}">{3}</a>'
   ;   sMaskAnchorId = StrReplace (sMaskAnchorId, "{1}", sFileInCrc)
   sMaskAnchorId = '<a id="{2}">{3}</a>'
   Break
Case 0
   sMaskAnchorId = ''
   Break
EndSwitch
;..........................................................................................................................................
iLastIC65 = IntControl (65, 4096 * Min (64, 1 + (FileSize (sFileIn) / 4096)), 0, 0, 0) ; Set size of internal FileRead buffer.
hFR = FileOpen (sFileOut1, "READ")
IntControl (53, 1, 0, 0, 0) ; Set line terminator for FileWrite. p1: 0=None, 1=@CRLF, 2=@LF, 3=@CR, 4=@TAB.
hFW = FileOpen (sFileOut2, "WRITE")

iCountLine = 0
iLastExclusive = Exclusive (@ON)
While @TRUE
   sCurrent = FileRead (hFR)
   If (sCurrent == "*EOF*") Then Break
   iCountLine = iCountLine + 1
   sLineNo = StrFixLeft (iCountLine, useLineNumberFiller, iLineNoLen)
   sLineNo = StrReplace (StrReplace (sMaskFont, "{1}", sColorValue), "{2}", sLineNo)
   Switch UseLineNumberLink
   Case 2
   Case 1
      sAnchorId = StrReplace (sMaskAnchorId, "{2}", iCountLine)
      sAnchorId = StrReplace (sAnchorId, "{3}", sLineNo)
      sCurrent = sAnchorId : "  " : sCurrent
      Break
   Case 0
      sCurrent = sLineNo : "  " : sCurrent
      Break
   EndSwitch
   FileWrite (hFw, sCurrent)
EndWhile
Exclusive (iLastExclusive)

FileClose (hFW)
FileClose (hFR)

Drop (hFr, hFw, iLastExclusive, iLastIC65, iLineNoLen, sAnchorId, sColorName)
Drop (sColorValue, sCurrent, sLineNo, sMaskAnchorId)
Return
;------------------------------------------------------------------------------------------------------------------------------------------



;==========================================================================================================================================
:CreateTempFilenames
;------------------------------------------------------------------------------------------------------------------------------------------
; Create random filenames.
sFileTemp = FileCreateTemp ("")
FileDelete (sFileTemp)
sMaskFN = FilePath (sFileTemp) : sProgProduct : "." : FileRoot (sFileTemp) : "{1}"
sFileOut1 = StrReplace (sMaskFn, "{1}", ".1.txt")
sFileOut2 = StrReplace (sMaskFn, "{1}", ".2.txt")
Drop (sFileTemp, sMaskFN)
Return
;------------------------------------------------------------------------------------------------------------------------------------------



;==========================================================================================================================================
:DeleteTempFilenames
;------------------------------------------------------------------------------------------------------------------------------------------
If IsDefined (sFileOut1) Then If FileExist (sFileOut1) == 1 Then FileDelete (sFileOut1)
If IsDefined (sFileOut2) Then If FileExist (sFileOut2) == 1 Then FileDelete (sFileOut2)
Return
;------------------------------------------------------------------------------------------------------------------------------------------



;==========================================================================================================================================
:CreateWriteTargetFile
;------------------------------------------------------------------------------------------------------------------------------------------
; Create the HTML output from previously defined template.
sMaskHtmPre = StrReplace (sMaskHtmPre, "{1}", TimeYmdHms ())
sMaskHtmPre = StrReplace (sMaskHtmPre, "{2}", sProgProduct)
sMaskHtmPre = StrReplace (sMaskHtmPre, "{3}", sProgVersion)
sMaskHtmPre = StrReplace (sMaskHtmPre, "{4}", sProgCopyright)
sMaskHtmPre = StrReplace (sMaskHtmPre, "{5}", sListHtmColor)
sMaskHtmPre = StrReplace (sMaskHtmPre, "{6}", sStyleImageBg)
sMaskHtmPre = StrReplace (sMaskHtmPre, "{7}", sStyleColorBg)
sMaskHtmPre = StrReplace (sMaskHtmPre, "{8}", sStyleBorder)
sMaskHtmPre = StrReplace (sMaskHtmPre, "{9}", sStylePadding)
sMaskHtmPre = StrReplace (sMaskHtmPre, "{10}", sStyleWidth)
sMaskHtmPre = StrReplace (sMaskHtmPre, "{11}", sStyleFontFamily)
sMaskHtmPre = StrReplace (sMaskHtmPre, "{12}", sStyleFontSize)
sMaskHtmPre = StrReplace (sMaskHtmPre, "{13}", sStyleFontWeight)
sMaskHtmPre = StrReplace (sMaskHtmPre, "{14}", sStyleFontStyle)
sMaskHtmPre = StrReplace (sMaskHtmPre, "{15}", sStyleColorFg)
sMaskHtmPre = StrReplace (sMaskHtmPre, "{16}", sFileInCrc)
sMaskHtmPre = StrReplace (sMaskHtmPre, "{17}", sFileInGUID)
sMaskHtmPre = StrReplace (sMaskHtmPre, "{18}", FileGet (sFileOut2))
;..........................................................................................................................................
FilePut (sFileOut, sMaskHtmPre)
;..........................................................................................................................................

If (UseVerbose > 1)
   sMsgText = sFileOut : @LF : "Closing targetfile ..."
   BoxText (sMsgText)
EndIf

Drop (sMaskHtmPre, sMsgText)
Return
;------------------------------------------------------------------------------------------------------------------------------------------



;==========================================================================================================================================
:GetParams
;------------------------------------------------------------------------------------------------------------------------------------------
sMsgTitle = "Error"
iResult = 0

If !IsDefined (sFileIn) Then sFileIn = ""
If sFileIn == ""
   strCmdLine = IntControl (1006, 0, 0, 0, 0) ; Full commandline.
   intParams = ParseData (strCmdLine)
   If (intParams < 2) Then Return ; No parameters given, immediately return.
   sFileIn = udfGetLongPathNameA (Param2)
   DropWild ("Param*")
EndIf

If FileSizeEx (sFileIn) == 0
   sMsgText = sFileIn : @LF : "Cannot handle input file." : @LF : "FileSize may be zero."
   Message (sMsgTitle, sMsgText)
   iResult = -1
   Return
EndIf
If !ItemLocate (StrLower (FileExtension (sFileIn)), "wbt|web", "|")
   sMsgText = sFileIn : @LF : "Cannot handle input file." : @LF : "Filename has wrong extension." : @LF : "Must be '.wbt' or '.web'."
   Message (sMsgTitle, sMsgText)
   iResult = -1
   Return
EndIf

If IsDefined (Param2)
   ; Force extension.
   sFileOut = FilePath (Param2) : FileRoot (Param2) : ".htm"
Else
   ; Simply add extension.
   sFileOut = sFileIn : ".htm"
EndIf

If FileExist (sFileOut) == 2
   sMsgText = sFileOut : @LF : "Cannot handle output file." : @LF : "File is currently open by another application."
   Message (sMsgTitle, sMsgText)
   iResult = -1
   Return
EndIf
If FileSizeEx (sFileOut) > 0
   If !UseAllowOverwrite
      sMsgText = sFileOut : @LF : "Cannot handle output file." : @LF : "File may exist." : @LF : "Allow to overwrite?"
      If (@YES != AskYesNo (sMsgTitle, sMsgText))
         iResult = -1
         Return
      EndIf
   EndIf
   FileAttrSet (sFileOut, "rash")
   iResult = 1
   Return
EndIf
If FileExist (sFileOut) == 0
   FileClose (FileOpen (sFileOut, "WRITE")) ; Create zero byte file.
   If FileExist (sFileOut) == 0
      sMsgText = sFileOut : @LF : "Cannot handle output file." : @LF : "File cannot be created."
      Message (sMsgTitle, sMsgText)
      iResult = -1
      Return
   EndIf
Else
   FileDelete (sFileOut)
   If FileExist (sFileOut) != 0
      sMsgText = sFileOut : @LF : "Cannot handle output file." : @LF : "File cannot be deleted."
      Message (sMsgTitle, sMsgText)
      iResult = -1
      Return
   EndIf
EndIf

; If we arrive here, then input and output filenames seem to be useful.
iResult = 1
;..........................................................................................................................................
Return
;==========================================================================================================================================



;==========================================================================================================================================
:AskParams
;------------------------------------------------------------------------------------------------------------------------------------------
AF_folder = UseAskFilename ; Define your standard folder here.
AF_folder = FilePath (IniReadPvt ("User", "UseAskFilename", AF_folder, sFileMyIni))
AF_title = "WBT2HTML: Select WBT or WEB File to convert to HTM"
AF_filetypes = "WIL Files|*.wbt;*.web|HTML Files|*.htm;*.html|All Files|*.*|"
AF_default = "*.wbt;*.web"
AF_default = FileBaseName (IniReadPvt ("User", "UseAskFilename", AF_default, sFileMyIni))
AF_flag = 1  ; Open single file.

sFileIn = AskFilename (AF_title, aF_folder, aF_filetypes, aF_default, aF_flag)
AF_folder = FilePath (sFileIn)

;IniWritePvt ("User", "UseAskFilename", aF_folder, sFileMyIni)
IniWritePvt ("User", "UseAskFilename", sFileIn, sFileMyIni)
IniWritePvt ("", "", "", sFileMyIni)

DropWild ("AF_*")

If sFileIn != "" Then Return

:CANCEL
Exit
;==========================================================================================================================================



;==========================================================================================================================================
:WriteLog
;------------------------------------------------------------------------------------------------------------------------------------------
; Start performance test.
If !IsDefined (iPerfStart)
   iPerfStart = GetTickCount ()
   Return
EndIf
;..........................................................................................................................................
; Stop performance test.
iPerfStop = GetTickCount ()
iPerfLinesIn = udfGetFileLineCount (sFileIn)
iPerfLinesOut = iCountLine
iPerfSecs = (iPerfStop - iPerfStart) / 1000.0
iPerfLinesOutPerSec = iPerfLinesOut / iPerfSecs
;..........................................................................................................................................
If !UseWriteLogfile Then Return
;..........................................................................................................................................
Decimals (2)
sPerfIni = sFolderTemp : sProgProduct : ".log.txt"
sPerfSection = TimeYmdHms () : "|" : StrFixLeft (GetTickCount (), " ", 10)

sPerfKey = "Version"
sPerfValue = sProgVersion
IniWritePvt (sPerfSection, sPerfKey, sPerfValue, sPerfIni)

sPerfKey = "FileIn"
sPerfValue = sFileIn
IniWritePvt (sPerfSection, sPerfKey, sPerfValue, sPerfIni)

sPerfKey = "FileOut"
sPerfValue = sFileOut
IniWritePvt (sPerfSection, sPerfKey, sPerfValue, sPerfIni)

sPerfKey = "LinesIn"
sPerfValue = iPerfLinesIn
IniWritePvt (sPerfSection, sPerfKey, sPerfValue, sPerfIni)

sPerfKey = "LinesOut"
sPerfValue = iPerfLinesOut
IniWritePvt (sPerfSection, sPerfKey, sPerfValue, sPerfIni)

sPerfKey = "Secs"
sPerfValue = iPerfSecs
IniWritePvt (sPerfSection, sPerfKey, sPerfValue, sPerfIni)

sPerfKey = "LinesOutPerSec"
sPerfValue = iPerfLinesOutPerSec
IniWritePvt (sPerfSection, sPerfKey, sPerfValue, sPerfIni)

Return
;==========================================================================================================================================



;==========================================================================================================================================
:WBERRORHANDLER
;------------------------------------------------------------------------------------------------------------------------------------------
WbError = LastError ()
WbTextcode = WbError
If (WbError == 1668 || WbError == 2669 || WbError == 3670)
   ; 1668 ; "Minor user-defined error"
   ; 2669 ; "Moderate user-defined error"
   ; 3670 ; "Severe user-defined error"
   WbError = ItemExtract (1, IntControl (34, -1, 0, 0, 0), ":")
   WbTextcode = -1
EndIf
WbErrorString = IntControl (34, WbTextcode, 0, 0, 0)
WbErrorDateTime = TimeYmdHms () : "|" : StrFixLeft (GetTickCount (), " ", 10) : "|"
If (VersionDLL () <= "4.4add") Then WbErrorHandlerFile = IntControl (1004, 0, 0, 0, 0)   ; "4.4add" = "2004A"

; WbErrorFile = StrCat (DirWindows (0), "WWWBATCH.INI") ; Before Windows VISTA.
WbErrorFile = FileLocate (ShortCutDir ("AppData", 0, 0) : "\WinBatch\Settings\WWWBATCH.INI")
IniWritePvt (WbErrorDateTime, "CurrentScript", WbErrorHandlerFile, WbErrorFile)
IniWritePvt (WbErrorDateTime, "ErrorValue", WbError, WbErrorFile)
IniWritePvt (WbErrorDateTime, "ErrorString", WbErrorString, WbErrorFile)
IniWritePvt (WbErrorDateTime, "ScriptLine", WbErrorHandlerLine, WbErrorFile)
IniWritePvt (WbErrorDateTime, "ScriptOffset", WbErrorHandlerOffset, WbErrorFile)
IniWritePvt (WbErrorDateTime, "VarAssignment", WbErrorHandlerAssignment, WbErrorFile)
IniWritePvt ("", "", "", WbErrorFile)

WbErrorMsgText = WbErrorDateTime : @LF : @LF
WbErrorMsgText = WbErrorMsgText : "Current Script:" : @LF : WbErrorHandlerFile : @LF : @LF
WbErrorMsgText = WbErrorMsgText : "LastError value:" : @LF : WbError : @LF : @LF
WbErrorMsgText = WbErrorMsgText : "LastError string:" : @LF : WbErrorString : @LF : @LF
; Line in script that caused Error.
WbErrorMsgText = WbErrorMsgText : "WbErrorHandlerLine:" : @LF : WbErrorHandlerLine : @LF : @LF
; Offset into script of error line, in bytes.
WbErrorMsgText = WbErrorMsgText : "WbErrorHandlerOffset:" : @LF : WbErrorHandlerOffset : @LF : @LF
; Variable being assigned on error line, or "" if none.
WbErrorMsgText = WbErrorMsgText : "WbErrorHandlerAssignment:" : @LF : WbErrorHandlerAssignment : @LF : @LF
If (WbErrorHandlerAssignment != "") Then %WbErrorHandlerAssignment% = "eeek"
ClipPut (WbErrorMsgText)
WbErrorMsgText = WbErrorMsgText : "Note: This error message is just copied to the clipboard for further usage."
Message ("WbErrorHandler", WbErrorMsgText)
Exit
;==========================================================================================================================================

;------------------------------------------------------------------------------------------------------------------------------------------
; Changelog
;
;   20090709 Version 3.11
;   - Changed: All (= 96) StrCat() functions have been replaced by the colon ":" string concatenator.
;              Script reformatted with Les Ferch's Beautifier.
;
;   20090416 Version 3.10
;   - Added: UDF "udfGetGUID" for setting the name attribute of the <pre> section in html output to a GUID.
;   - Changed: Name of UDF "udfFileCheckSum" to "udfGetFileCheckSum".
;   - Changed: GoSub AddLineNumber: Name of Variable "sMaskAnchorNameId" to "sMaskAnchorId".
;   - Changed: GoSub AddLineNumber: Name of Variable "sAnchorNameId" to "sAnchorId".
;   - Changed: GoSub AddLineNumber: sMaskAnchorId set to line number only, no longer FileCRC info as id content.
;
;   20090404 Version 3.09
;   - Small changes in procedures GetParams and AskParams regarding detection of commandline parameter.
;
;   20081018 Version 3.08
;   - Some small changes, mostly cosmetics, for better readability of script code.
;   - Remember last used input filename in inifile for AskFilename dialog.
;
;   20080824 Version 3.07
;   - Some small changes, mostly cosmetics.
;------------------------------------------------------------------------------------------------------------------------------------------