VERSION DVX 1.00
' resedit.frm -- DVX Resource Editor
'
' Graphical editor for the resource blocks appended to binary
' files (.app, .wgt, .lib). View, add, remove, and extract
' resources of type icon, text, or binary.
'
' Add commdlg.bas and resource.bas to your project, then click Run.

Begin Form ResEdit
    Caption   = "DVX Resource Editor"
    Layout    = VBox
    AutoSize  = False
    Resizable = True
    Centered  = True
    Width     = 500
    Height    = 340

    Begin Menu mnuFile
        Caption = "&File"
        Begin Menu mnuOpen
            Caption = "&Open..."
        End
        Begin Menu mnuClose
            Caption = "&Close"
            Enabled = False
        End
        Begin Menu mnuSep1
            Caption = "-"
        End
        Begin Menu mnuExit
            Caption = "E&xit"
        End
    End

    Begin Menu mnuResource
        Caption = "&Resource"
        Begin Menu mnuAddText
            Caption = "Add &Text..."
            Enabled = False
        End
        Begin Menu mnuAddFile
            Caption = "Add &File..."
            Enabled = False
        End
        Begin Menu mnuEditText
            Caption = "&Edit Text..."
            Enabled = False
        End
        Begin Menu mnuSep2
            Caption = "-"
        End
        Begin Menu mnuExtract
            Caption = "E&xtract..."
            Enabled = False
        End
        Begin Menu mnuRemove
            Caption = "&Remove"
            Enabled = False
        End
    End

    Begin ListView ResList
        Weight = 1
    End

    Begin Label LblStatus
        Caption = "No file loaded."
        Weight  = 0
    End
End

' The MIT License (MIT)
'
' Copyright (C) 2026 Scott Duensing
'
' Permission is hereby granted, free of charge, to any person obtaining a copy
' of this software and associated documentation files (the "Software"), to
' deal in the Software without restriction, including without limitation the
' rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
' sell copies of the Software, and to permit persons to whom the Software is
' furnished to do so, subject to the following conditions:
'
' The above copyright notice and this permission notice shall be included in
' all copies or substantial portions of the Software.
'
' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
' IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
' AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
' LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
' FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
' IN THE SOFTWARE.


OPTION EXPLICIT

DIM filePath AS STRING
DIM resHandle AS LONG
filePath  = ""
resHandle = 0

Load ResEdit
ResEdit.Show

ResList.SetColumns "Name,20|Type,8|Size,12"
LblStatus.Caption = "Ready. Use File > Open to load a DXE file."


' ============================================================
' Type name helper
' ============================================================

FUNCTION TypeName$(t AS LONG)
    IF t = RES_TYPE_ICON THEN
        TypeName$ = "Icon"
    ELSEIF t = RES_TYPE_TEXT THEN
        TypeName$ = "Text"
    ELSEIF t = RES_TYPE_BINARY THEN
        TypeName$ = "Binary"
    ELSE
        TypeName$ = "Unknown"
    END IF
END FUNCTION


' ============================================================
' Format a byte size for display
' ============================================================

FUNCTION FormatSize$(sz AS LONG)
    IF sz < 1024 THEN
        FormatSize$ = STR$(sz) + " B"
    ELSE
        FormatSize$ = STR$(sz \ 1024) + " KB"
    END IF
END FUNCTION


' ============================================================
' Refresh the resource list from the open handle
' ============================================================

SUB RefreshList
    ResList.Clear

    IF resHandle = 0 THEN
        EXIT SUB
    END IF

    DIM n AS LONG
    n = ResCount(resHandle)

    DIM ix AS LONG
    FOR ix = 0 TO n - 1
        ResList.AddItem ResName$(resHandle, ix)
        ResList.SetCell ix, 1, TypeName$(ResType(resHandle, ix))
        ResList.SetCell ix, 2, FormatSize$(ResSize(resHandle, ix))
    NEXT ix

    LblStatus.Caption = filePath + " - " + STR$(n) + " resource(s)"
END SUB


' ============================================================
' Close the current file
' ============================================================

SUB CloseFile
    IF resHandle <> 0 THEN
        ResClose resHandle
        resHandle = 0
    END IF
    filePath = ""
    ResList.Clear
    ResEdit.Caption = "DVX Resource Editor"
    mnuClose.Enabled    = False
    mnuAddText.Enabled  = False
    mnuAddFile.Enabled  = False
    mnuEditText.Enabled = False
    mnuExtract.Enabled  = False
    mnuRemove.Enabled   = False
    LblStatus.Caption = "No file loaded."
END SUB


' ============================================================
' Reopen the file (after modification) and refresh
' ============================================================

SUB ReopenAndRefresh
    DIM path AS STRING
    path = filePath

    IF resHandle <> 0 THEN
        ResClose resHandle
        resHandle = 0
    END IF

    resHandle = ResOpen(path)

    IF resHandle = 0 THEN
        ' File may have had all resources stripped
        filePath = path
        ResList.Clear
        LblStatus.Caption = path + " - 0 resource(s)"
    ELSE
        filePath = path
        RefreshList
    END IF
END SUB


' ============================================================
' Enable/disable selection-dependent menus
' ============================================================

SUB UpdateMenuState
    DIM hasSel AS INTEGER
    hasSel = (ResList.ListIndex >= 0)
    mnuExtract.Enabled  = hasSel
    mnuRemove.Enabled   = hasSel
    mnuEditText.Enabled = hasSel
END SUB


' ============================================================
' Menu handlers
' ============================================================

SUB mnuOpen_Click
    DIM path AS STRING
    path = basFileOpen("Open DXE File", "Applications (*.app)|Widget Modules (*.wgt)|Libraries (*.lib)|All Files (*.*)")
    IF path = "" THEN
        EXIT SUB
    END IF

    CloseFile

    filePath = path
    ResEdit.Caption = path + " - DVX Resource Editor"
    mnuClose.Enabled   = True
    mnuAddText.Enabled = True
    mnuAddFile.Enabled = True

    resHandle = ResOpen(path)
    IF resHandle = 0 THEN
        LblStatus.Caption = "No resources in " + path
        EXIT SUB
    END IF

    RefreshList
END SUB


SUB mnuClose_Click
    CloseFile
END SUB


SUB mnuExit_Click
    Unload ResEdit
END SUB


SUB mnuAddText_Click
    IF filePath = "" THEN
        EXIT SUB
    END IF

    DIM rName AS STRING
    rName = basInputBox2("Add Text Resource", "Resource name:", "")
    IF basInputCancelled OR rName = "" THEN
        EXIT SUB
    END IF

    DIM text AS STRING
    text = basInputBox2("Add Text Resource", "Text value:", "")
    IF basInputCancelled THEN
        EXIT SUB
    END IF

    IF ResAddText(filePath, rName, text) THEN
        ReopenAndRefresh
        LblStatus.Caption = "Added text resource: " + rName
    ELSE
        LblStatus.Caption = "Failed to add resource."
    END IF
END SUB


SUB mnuAddFile_Click
    IF filePath = "" THEN
        EXIT SUB
    END IF

    DIM rName AS STRING
    rName = basInputBox2("Add File Resource", "Resource name:", "")
    IF basInputCancelled OR rName = "" THEN
        EXIT SUB
    END IF

    DIM typeChoice AS LONG
    typeChoice = basChoiceDialog("Resource Type", "Select resource type:", "Icon|Binary", 0)
    IF typeChoice < 0 THEN
        EXIT SUB
    END IF

    DIM typeVal AS LONG
    IF typeChoice = 0 THEN
        typeVal = RES_TYPE_ICON
    ELSE
        typeVal = RES_TYPE_BINARY
    END IF

    DIM srcPath AS STRING
    srcPath = basFileOpen("Select Source File", "All Files (*.*)")
    IF srcPath = "" THEN
        EXIT SUB
    END IF

    IF ResAddFile(filePath, rName, typeVal, srcPath) THEN
        ReopenAndRefresh
        LblStatus.Caption = "Added resource: " + rName
    ELSE
        LblStatus.Caption = "Failed to add resource."
    END IF
END SUB


SUB mnuEditText_Click
    IF filePath = "" THEN
        EXIT SUB
    END IF

    DIM sel AS LONG
    sel = ResList.ListIndex
    IF sel < 0 THEN
        EXIT SUB
    END IF

    DIM rName AS STRING
    rName = ResName$(resHandle, sel)

    DIM t AS LONG
    t = ResType(resHandle, sel)
    IF t <> RES_TYPE_TEXT THEN
        LblStatus.Caption = "Only text resources can be edited inline."
        EXIT SUB
    END IF

    DIM oldText AS STRING
    oldText = ResGetText$(filePath, rName)

    DIM newText AS STRING
    newText = basInputBox2("Edit Text Resource", "Value for '" + rName + "':", oldText)

    IF basInputCancelled THEN
        EXIT SUB
    END IF

    IF ResAddText(filePath, rName, newText) THEN
        ReopenAndRefresh
        LblStatus.Caption = "Updated: " + rName
    ELSE
        LblStatus.Caption = "Failed to update resource."
    END IF
END SUB


SUB mnuExtract_Click
    IF filePath = "" OR resHandle = 0 THEN
        EXIT SUB
    END IF

    DIM sel AS LONG
    sel = ResList.ListIndex
    IF sel < 0 THEN
        EXIT SUB
    END IF

    DIM rName AS STRING
    rName = ResName$(resHandle, sel)

    DIM outPath AS STRING
    outPath = basFileSave("Extract Resource", "All Files (*.*)")
    IF outPath = "" THEN
        EXIT SUB
    END IF

    IF ResExtract(filePath, rName, outPath) THEN
        LblStatus.Caption = "Extracted '" + rName + "' to " + outPath
    ELSE
        LblStatus.Caption = "Failed to extract resource."
    END IF
END SUB


SUB mnuRemove_Click
    IF filePath = "" THEN
        EXIT SUB
    END IF

    DIM sel AS LONG
    sel = ResList.ListIndex
    IF sel < 0 THEN
        EXIT SUB
    END IF

    DIM rName AS STRING
    rName = ResName$(resHandle, sel)

    DIM ans AS INTEGER
    ans = MsgBox("Remove resource '" + rName + "'?", vbYesNo)
    IF ans = vbNo THEN
        EXIT SUB
    END IF

    ' Close handle before modifying
    ResClose resHandle
    resHandle = 0

    IF ResRemove(filePath, rName) THEN
        ReopenAndRefresh
        LblStatus.Caption = "Removed: " + rName
    ELSE
        ReopenAndRefresh
        LblStatus.Caption = "Failed to remove resource."
    END IF
END SUB


' ============================================================
' ListView selection change
' ============================================================

SUB ResList_Click
    UpdateMenuState
END SUB


SUB ResList_DblClick
    IF filePath = "" OR resHandle = 0 THEN
        EXIT SUB
    END IF

    DIM sel AS LONG
    sel = ResList.ListIndex
    IF sel < 0 THEN
        EXIT SUB
    END IF

    DIM t AS LONG
    t = ResType(resHandle, sel)

    IF t = RES_TYPE_TEXT THEN
        mnuEditText_Click
    ELSE
        mnuExtract_Click
    END IF
END SUB
