WBStudio.Dialog6Sort
;==========================================================================================================================================
; WBStudio.Dialog6Sort.wbt  v2.00
;==========================================================================================================================================
; This script is intended to be called from a WSP-USER.MNU menu entry from within WinBatch Studio.
; This script works with WinBatch dialog format "WWWDLGED,6.2", possibly with dialog format "WWWDLGED,6.1" too.
;
; User must hilight a block of dialog controls, for example:
;    MyDialog001=`035,035,120,046,STATICTEXT,StaticText_1,...`
;    MyDialog002=`015,055,120,054,DROPLISTBOX,DropListBox_1,...`
;    MyDialog003=`005,021,156,074,GROUPBOX,GroupBox_1,...`
;    MyDialog004=`015,035,120,046,STATICTEXT,StaticText_2,...`
;
; This script automatically sorts the dialog controls by column PosY and PosX and aligns columns by comma character.
;    MyDialog001 = `005,021,156,074,GROUPBOX   ,GroupBox_1   ,...`
;    MyDialog002 = `015,035,120,046,STATICTEXT ,StaticText_2 ,...`
;    MyDialog003 = `035,035,120,046,STATICTEXT ,StaticText_1 ,...`
;    MyDialog004 = `015,055,120,054,DROPLISTBOX,DropListBox_1,...`
;
; User can sort by any column when LAFFDB dialog dbDebug is active.
;------------------------------------------------------------------------------------------------------------------------------------------
; Call this script from WSP-USER.MNU, for example:
;
; Dialog6Sort
;    Call ("W:\WINBATCH\Scripts\WBStudioDialog6Sort.wbt", "")
;
;------------------------------------------------------------------------------------------------------------------------------------------
; Detlev Dalitz.20100101.
;------------------------------------------------------------------------------------------------------------------------------------------

blnInStudio = (RtStatus () == 10)
If !blnInStudio Then Exit
If !wGetSelstate ()
   Message ("Dialog6Sort Instructions", 'You must hilight a block of dialog controls' : @LF : 'beginning at "MyDialog001 = ...".')
   Goto CANCEL
EndIf

;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfAskYesNo (strAYN_Title, strAYN_Question)
:CANCEL
Return AskYesNo (strAYN_Title, strAYN_Question)
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------

; Define some constants.
@34 = '"'
@39 = "'"
@96 = "`"
@35 = "#"
@44 = ","
@61 = "="
@Q = @34 : @39 : @96
@D = "DEFAULT"

; Get selected text from clipboard.
wCopy ()
strClipGet = ClipGet ()

; Change EOL to @LF for itemlist usage.
strClipGet = StrReplace (strClipGet, @CRLF, @LF)
intCountItems = ItemCount (strClipGet, @LF)

; Collect list of DialogControls.
intMargin = 0
strDlgName = ""
strDlgNameSample = ""
strListDlgControls = ""
For intItem = 1 To intCountItems
   strDlgControl = ItemExtract (intItem, strClipGet, @LF)
   intMargin = StrLen (strDlgControl)
   strDlgControl = StrTrim (strDlgControl)
   intMargin = intMargin - StrLen (strDlgControl)
   If strDlgControl == "" Then Continue
   strDlgVar = StrTrim (ItemExtract (1, strDlgControl, @61))
   If strDlgVar == "" Then Continue
   strDlgNameSample = StrSub (strDlgVar, 1, StrLen (strDlgVar) - 3)
   Break
Next
If strDlgNameSample == ""
   Message ("Dialog6Sort Instructions", "Dialog control variable not found.")
   Goto CANCEL
EndIf

For intItem = 1 To intCountItems
   strDlgControl = StrTrim (ItemExtract (intItem, strClipGet, @LF))
   If strDlgControl == "" Then Continue
   strDlgVar = StrTrim (ItemExtract (1, strDlgControl, @61))
   If strDlgVar == "" Then Continue
   strDlgName = StrSub (strDlgVar, 1, StrLen (strDlgVar) - 3)
   If strDlgName != strDlgNameSample
      Message ("Dialog6Sort Instructions", "Dialog control variable name does not match" : @LF : '"' : strDlgNameSample : '"' : @LF : '"' : strDlgVar : '"')
      Goto CANCEL
   EndIf
   strListDlgControls = ItemInsert (strDlgControl, -1, strListDlgControls, @LF)
Next

; Load the LAFFDB extender.
; Note: Once an extender is loaded, it cannot be unloaded while WS-POPMENU is running.
AddExtender ("laffd34i.dll")
@DB_SUCCESS = 1  ; Returncode on success.
@DB_MUST_NOT_EXIST = 1 ; If file does not exist, then create an empty database.
@DB_MODEL_MEMORY = 1   ; Memory-based. No disk functions are used.
@DB_FORMAT_DELIM = 0   ; Delimiter-based.
@DB_RECNO_FIXED = 1    ; Recordnum is a fixed record number.
@DB_RECNO_VAR = 2      ; Recordnum is a variable record number.
@DB_RECNO_BOUND = 4    ; Require all columns to be bound with dbBindCol.


; Build the database from the control rows.
; Memory based. No diskfile envolved.
strDBFilename = ""
intDBCreateOK = @DB_MUST_NOT_EXIST
intDBModel = @DB_MODEL_MEMORY
intDBNumCols = 15
intDBFormat = @DB_FORMAT_DELIM
intDBDelimiter = @44
strDBOptionString = ""
hdlDB = dbOpen (strDBFilename, intDBCreateOK, intDBModel, intDBNumCols, intDBFormat, intDBDelimiter, strDBOptionString)
intResult = dbSetOptions (hdlDB, 1, 0, 0, 0) ; Set first column to 1.

strColNames = "DlgVar,X,Y,Width,Height,Type,CtrlName,VarName,Preset,RetValue,TabOrder,Style,Font,TextColor,BGColor"
For intCol = 1 To intDBNumCols
   intResult = dbBindCol (hdlDB, intCol, "strCol%intCol%")
   intResult = dbNameColumn (hdlDB, intCol, ItemExtract (intCol, strColNames, @44))
Next

intCountDlgControls = ItemCount (strListDlgControls, @LF)
For intItem = 1 To intCountDlgControls
   strDlgControl = ItemExtract (intItem, strListDlgControls, @LF)
   strCol1 = ItemExtract (1, strDlgControl, @61)
   strDlgControl = ItemRemove (1, strDlgControl, @61)
   strDlgControl = ItemRemove (1, strDlgControl, @96)
   strDlgControl = ItemRemove (-1, strDlgControl, @96)
   For intCol = 2 To intDBNumCols
      strCol%intCol% = ItemExtractCSV (intCol - 1, strDlgControl, 0, @44)
      ; Try to make column datatype integer (for _numerical_ sort). ; Bug? LAFFDB cannot see it.
      Switch intCol
      Case 9
      Case 10
      Case 11
         If IsNumber (strCol%intCol%) Then strCol%intCol% = 0 + strCol%intCol%
      EndSwitch
   Next
   intRecord = dbSetEntireRecord (hdlDB, dbMakeNewItem (hdlDB, @DB_RECNO_FIXED), 1)
Next


; Sort automatically.
dbSort (hdlDB, 02, 1) ; X.
dbSort (hdlDB, 03, 1) ; Y.
; dbSort (hdlDB, 01, 1) ; DialogVar (dialog variable name combined with the ordinal position of the control in the dialog box.
; dbSort (hdlDB, 02, 1) ; X.
; dbSort (hdlDB, 03, 1) ; Y.
; dbSort (hdlDB, 04, 1) ; Width.
; dbSort (hdlDB, 05, 1) ; height.
; dbSort (hdlDB, 06, 1) ; Type.
; dbSort (hdlDB, 07, 1) ; ControlName.
; dbSort (hdlDB, 08, 1) ; VarName (variable or license string or parent name).
; dbSort (hdlDB, 09, 1) ; Preset (text or pre-selected item or progid or classid or moniker).
; dbSort (hdlDB, 10, 1) ; ReturnValue.
; dbSort (hdlDB, 11, 1) ; TabOrder or MenuPosition.
; dbSort (hdlDB, 12, 1) ; Style.
; dbSort (hdlDB, 13, 1) ; Font.
; dbSort (hdlDB, 14, 1) ; TextColor.
; dbSort (hdlDB, 15, 1) ; BackgroundColor.
; ToDo: Create a user menu dialog with some options to click.
; ToDo: Create a better editable listview than dbDebug().


; View dialog data and manipulate.
; Note: Bug? Either Esc key or Cancel button closes dbDebug window, but returns always 1.
; Note: Bug? When manually edit an integer cell or manually change one integer value in a column full of integers,
;       dbDebug() will change the datatype from (S) to (I) in all other integer alike columns.
intResult = dbDebug (hdlDB) ; Return value is always 1.
intRecCount = dbGetRecordCount (hdlDB)
intColCount = dbGetColumnCount (hdlDB)


; Ask user for column alignment.
blnColAlign = udfAskYesNo ("Dialog6Sort Instructions", "Align dialog control columns?") ; Returns @YES, @NO.


; Measure column width for maximal sized columns.
If blnColAlign
   For intCol = 1 To intColCount
      intColSize%intCol% = 0
   Next
   For intItem = 1 To intRecCount
      intResult = dbGetEntireRecord (hdlDB, intItem - 1, @DB_RECNO_VAR + @DB_RECNO_BOUND)
      For intCol = 2 To intColCount
         If intCol > 7 Then If !IsNumber (strCol%intCol%) Then If strCol%intCol% != @D Then strCol%intCol% = @34 : strCol%intCol% : @34
         intColSize%intCol% = Max (intColSize%intCol%, StrLen (strCol%intCol%))
      Next
   Next
EndIf


; Create new list of dialog control rows from database.
; Note: This code re-enumerates the dialog controls.
;       If the user has changed the sort order of the control variables from within dbDebug(),
;       the control numbers in the switch-case block within a dialog callback routine have to be changed accordingly.
strListDlgControls = ""
For intItem = 1 To intRecCount
   intResult = dbGetEntireRecord (hdlDB, intItem - 1, @DB_RECNO_VAR + @DB_RECNO_BOUND)
   strDlgControl = ""
   For intCol = 2 To intColCount
      If intCol > 7 Then If !IsNumber (strCol%intCol%) Then If strCol%intCol% != @D Then strCol%intCol% = @34 : strCol%intCol% : @34
      If blnColAlign Then strCol%intCol% = StrFix (strCol%intCol%, " ", intColSize%intCol%) ; Column alignment.
      strDlgControl = ItemInsert (strCol%intCol%, -1, strDlgControl, @44)
   Next
   strDlgControl = StrFill (" ", intMargin) : strDlgName : StrFixLeft (intItem, 0, 3) : " = " : @96 : strDlgControl : @96
   strListDlgControls = ItemInsert (strDlgControl, -1, strListDlgControls, @LF)
Next
dbClose (hdlDB)


; Change EOL to @CRLF for normal text usage.
strListDlgControls = StrReplace (strListDlgControls : @LF, @LF, @CRLF)

; Put the dialog back to clipboard.
ClipPut (strListDlgControls)

; Paste the dialog back to the selection.
wPaste ()


:CANCEL
wClearSel ()
DropWild ("str*")
DropWild ("hdl*")
DropWild ("int*")
DropWild ("@*")

Exit
;==========================================================================================================================================