Attribute VB_Name = "App"

'Option Explicit



Public Const BI_RGB = 0&
Public Const CBM_INIT = &H4
Public Const DIB_RGB_COLORS = 0
Public Const SRCCOPY = &HCC0020

Public Type BITMAPINFOHEADER
    biSize As Long
    biWidth As Long
    biHeight As Long
    biPlanes As Integer
    biBitCount As Integer
    biCompression As Long
    biSizeImage As Long
    biXPelsPerMeter As Long
    biYPelsPerMeter As Long
    biClrUsed As Long
    biClrImportant As Long
End Type

Public Type BITMAPINFO_256
    bmiHeader As BITMAPINFOHEADER
    bmiColors(0 To 255) As Long
End Type
Public Type RGBQUAD
        rgbBlue As Byte
        rgbGreen As Byte
        rgbRed As Byte
        rgbReserved As Byte
End Type



'blitting
Public Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long
Public Declare Function StretchBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal widthSrc As Long, ByVal heightSrc As Long, ByVal dwRop As Long) As Long
Public Declare Function FloodFill Lib "gdi32" (ByVal hDestDC As Long, ByVal X As Long, ByVal Y As Long, ByVal color As Long) As Long
Public Declare Function CreateSolidBrush Lib "gdi32" (ByVal crColor As Long) As Long
Public Declare Function FillRgn Lib "gdi32" (ByVal hDestDC As Long, ByVal hRgn As Long, ByVal hBr As Long) As Long
'Public Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Public Declare Function CreateRectRgn Lib "gdi32" (ByVal nLeftRect As Long, ByVal nTopRect As Long, ByVal nRightRect As Long, ByVal nBottomRect As Long) As Long


'creating buffers / loading sprites
Public Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long
Public Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long

'loading sprites
Public Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long

'cleanup
Public Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
Public Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
Public Declare Function GetBitmapBits Lib "gdi32" (ByVal hBitmap As Long, ByVal dwCount As Long, lpBits As Any) As Long
Public Declare Function SetBitmapBits Lib "gdi32" (ByVal hBitmap As Long, ByVal dwCount As Long, lpBits As Any) As Long
'Public Declare Function SetPixelV Lib "gdi32.dll" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long, ByVal crColor As Long) As Long
'Public Declare Function SetPixel Lib "gdi32.dll" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long, ByVal crColor As Long) As Long
Public Declare Function GetLastError Lib "kernel32" () As Long
'Public Declare Function CreateDIBitmap Lib "gdi32" (ByVal hDC As Long, ByRef lpInfoHeader As Any, ByVal dwUsage As Long, ByRef lpInitBits As Object, ByRef lpInitInfo As Any, ByVal wUsage As Long) As Long
'Public Declare Function GetDIBColorTable Lib "gdi32" (ByVal hdc As Long, ByVal un1 As Long, ByVal un2 As Long, ByRef pcRGBQuad As Any) As Long
'Public Declare Function SetDIBColorTable Lib "gdi32" (ByVal hdc As Long, ByVal un1 As Long, ByVal un2 As Long, ByRef pcRGBQuad As Any) As Long
Public Declare Function GetDIBColorTable Lib "gdi32" (ByVal hdc As Long, ByVal un1 As Long, ByVal un2 As Long, ByRef pRGBQuad As Any) As Long
Public Declare Function SetDIBColorTable Lib "gdi32" (ByVal hdc As Long, ByVal un1 As Long, ByVal un2 As Long, ByRef pcRGBQuad As Any) As Long
Public Declare Function SetPixelV Lib "gdi32.dll" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long, ByVal crColor As Long) As Long
Public Declare Function SetPixel Lib "gdi32.dll" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long, ByVal crColor As Long) As Byte
Public Declare Function SetDIBits Lib "gdi32" (ByVal hdc As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As Any, lpBI As BITMAPINFO_256, ByVal wUsage As Long) As Long
Public Declare Function CreateDIBitmap Lib "gdi32" (ByVal hdc As Long, lpInfoHeader As BITMAPINFOHEADER, ByVal dwUsage As Long, lpInitBits As Any, lpInitInfo As BITMAPINFO_256, ByVal wUsage As Long) As Long
Public Declare Function CreateDIBSection Lib "gdi32" _
    (ByVal hdc As Long, _
    pBitmapInfo As BITMAPINFO_256, _
    ByVal un As Long, _
    lplpVoid As Long, _
    ByVal handle As Long, _
    ByVal dw As Long) As Long

'end of copy-paste here...
Public dlg_progresswindow As New ProgressWindow
Public dlg_objectlist As New ObjectList
Public dlg_itemtypeeditor As New ItemTypeEditor
Public dlg_comboeditor As New ComboEditor
Public dlg_attackeditor As New AttackEditor
Public dlg_dooreditor As New DoorEditor
Public dlg_monsterdropeditor As New MonsterDropEditor
Public dlg_spelleditor As New SpellEditor
Public dlg_runeeditor As New RuneEditor
Public dlg_monstereditor As New MonsterEditor
Public dlg_importmanager As New ImportManager
Public dlg_graphicsstructure As New GraphicsStructure

Public dlg_floordecorationgraphicinfoeditor As New FloorDecorationGraphicInfoEditor
Public dlg_walldecorationgraphicinfoeditor As New WallDecorationGraphicInfoEditor
Public dlg_doordecorationgraphicinfoeditor As New DoorDecorationGraphicInfoEditor
Public dlg_buttongraphicinfoeditor As New ButtonGraphicInfoEditor
Public dlg_buttoneditor As New ButtonEditor
Public dlg_itemgraphicinfoeditor As New ItemGraphicInfoEditor
Public dlg_monstergraphicinfoeditor As New MonsterGraphicInfoEditor
Public dlg_missilegraphicinfoeditor As New MissileGraphicInfoEditor
Public dlg_flooritemgraphicinfoeditor As New FloorItemGraphicInfoEditor
Public dlg_creaturegraphicinfoeditor As New CreatureGraphicInfoEditor
Public dlg_teleporterinfoeditor As New TeleporterEditor
Public dlg_graphicrectinfoeditor As New GraphicRectInfoEditor
Public graphics As New graphics
Public mapfile As New mapfile
Public dbg_file
Dim dbg As Boolean
Public apppath As String

Public Dictionary
Public LZWByteIndex, BitBuffer, BitsInBuffer, itemdata

Private CSBWinObjNames(180) As String

Public Function CSBWinObjName(num As Integer) As String
    CSBWinObjName = CSBWinObjNames(num)
End Function

Public Function zerostr(ByVal num As Long, count As Long) As String
    Dim i As Integer
    zerostr = Trim(Str(num))
    i = Len(zerostr)
    i = count - Len(zerostr)
    If i > 0 Then
        zerostr = String(count - Len(zerostr), "0") + zerostr
    End If
End Function
Public Function zerohex(num As Integer, count As Integer) As String
    Dim i As Integer
    zerohex = Trim(Hex(num))
    i = Len(zerohex)
    i = count - Len(zerohex)
    If i > 0 Then
        zerohex = String(i, "0") + zerohex
    End If
End Function
Public Sub InitCSBWinObjNames()

    Dim i As Integer
    
    i = 1
    CSBWinObjNames(i) = "OPEN SCROLL"
    i = i + 1
    CSBWinObjNames(i) = "CHEST"
    i = i + 1
    CSBWinObjNames(i) = "MON POTION(STAMINA)"
    i = i + 1
    CSBWinObjNames(i) = "UM POTION"
    i = i + 1
    CSBWinObjNames(i) = "DES POTION"
    i = i + 1
    CSBWinObjNames(i) = "VEN POTION(POISON)"
    i = i + 1
    CSBWinObjNames(i) = "SAR POTION"
    i = i + 1
    CSBWinObjNames(i) = "ZO POTION"
    i = i + 1
    CSBWinObjNames(i) = "ROS POTION(DEXTERITY)"
    i = i + 1
    CSBWinObjNames(i) = "KU POTION(STRENGTH)"
    i = i + 1
    CSBWinObjNames(i) = "DANE POTION(WISDOM)"
    i = i + 1
    CSBWinObjNames(i) = "NETA POTION(VITALITY"
    i = i + 1
    CSBWinObjNames(i) = "ANTIVENIN(CURE POISON)"
    i = i + 1
    CSBWinObjNames(i) = "MON POTION(STAMINA)"
    i = i + 1
    CSBWinObjNames(i) = "YA POTION(MAGIC SHIELD)"
    i = i + 1
    CSBWinObjNames(i) = "EE POTION(MANA)"
    i = i + 1
    CSBWinObjNames(i) = "VI POTION(HEALTH)"
    i = i + 1
    CSBWinObjNames(i) = "WATER FLASK"
    i = i + 1
    CSBWinObjNames(i) = "KATH BOMB"
    i = i + 1
    CSBWinObjNames(i) = "PEW BOMB"
    i = i + 1
    CSBWinObjNames(i) = "RA BOMB"
    i = i + 1
    CSBWinObjNames(i) = "FUL BOMB"
    i = i + 1
    CSBWinObjNames(i) = "EMPTY FLASK"
    i = i + 1
    CSBWinObjNames(i) = "EYE OF TIME"
    i = i + 1
    CSBWinObjNames(i) = "STORMRING"
    i = i + 1
    CSBWinObjNames(i) = "TORCH"
    i = i + 1
    CSBWinObjNames(i) = "FLAMITT"
    i = i + 1
    CSBWinObjNames(i) = "STAFF OF CLAWS"
    i = i + 1
    CSBWinObjNames(i) = "STORM"
    i = i + 1
    CSBWinObjNames(i) = "RA BLADE"
    i = i + 1
    CSBWinObjNames(i) = "THE FIRESTAFF"
    i = i + 1
    CSBWinObjNames(i) = "DAGGER"
    i = i + 1
    CSBWinObjNames(i) = "FALCHION"
    i = i + 1
    CSBWinObjNames(i) = "SWORD"
    i = i + 1
    CSBWinObjNames(i) = "RAPIER"
    i = i + 1
    CSBWinObjNames(i) = "BITER"
    i = i + 1
    CSBWinObjNames(i) = "SAMURAI SWORD"
    i = i + 1
    CSBWinObjNames(i) = "SIDE SPLITTER"
    i = i + 1
    CSBWinObjNames(i) = "DIAMOND EDGE"
    i = i + 1
    CSBWinObjNames(i) = "VORPAL BLADE"
    i = i + 1
    CSBWinObjNames(i) = "DRAGON FANG"
    i = i + 1
    CSBWinObjNames(i) = "AXE"
    i = i + 1
    CSBWinObjNames(i) = "EXECUTIONER"
    i = i + 1
    CSBWinObjNames(i) = "MACE"
    i = i + 1
    CSBWinObjNames(i) = "MACE OF ORDER"
    i = i + 1
    CSBWinObjNames(i) = "MORNINGSTAR"
    i = i + 1
    CSBWinObjNames(i) = "CLUB"
    i = i + 1
    CSBWinObjNames(i) = "STONE CLUB"
    i = i + 1
    CSBWinObjNames(i) = "CLAW BOW"
    i = i + 1
    CSBWinObjNames(i) = "CROSSBOW"
    i = i + 1
    CSBWinObjNames(i) = "ARROW"
    i = i + 1
    CSBWinObjNames(i) = "SLAYER"
    i = i + 1
    CSBWinObjNames(i) = "SLING"
    i = i + 1
    CSBWinObjNames(i) = "ROCK"
    i = i + 1
    CSBWinObjNames(i) = "POISON DART"
    i = i + 1
    CSBWinObjNames(i) = "THROWING STAR"
    i = i + 1
    CSBWinObjNames(i) = "STICK"
    i = i + 1
    CSBWinObjNames(i) = "STAFF"
    i = i + 1
    CSBWinObjNames(i) = "WAND"
    i = i + 1
    CSBWinObjNames(i) = "TEOWAND"
    i = i + 1
    CSBWinObjNames(i) = "YEW STAFF"
    i = i + 1
    CSBWinObjNames(i) = "STAFF OF IRRA"
    i = i + 1
    CSBWinObjNames(i) = "CROSS OF NETA"
    i = i + 1
    CSBWinObjNames(i) = "SERPENT STAFF"
    i = i + 1
    CSBWinObjNames(i) = "DRAGON SPIT"
    i = i + 1
    CSBWinObjNames(i) = "SCEPTRE OF LYF"
    i = i + 1
    CSBWinObjNames(i) = "HORN OF FEAR"
    i = i + 1
    CSBWinObjNames(i) = "SPEEDBOW"
    i = i + 1
    CSBWinObjNames(i) = "THE FIRESTAFF+"
    i = i + 1
    CSBWinObjNames(i) = "CAPE"
    i = i + 1
    CSBWinObjNames(i) = "CLOAK OF NIGHT"
    i = i + 1
    CSBWinObjNames(i) = "TATTERED PANTS"
    i = i + 1
    CSBWinObjNames(i) = "SANDALS"
    i = i + 1
    CSBWinObjNames(i) = "LEATHER BOOTS"
    i = i + 1
    CSBWinObjNames(i) = "TATTERED SHIRT"
    i = i + 1
    CSBWinObjNames(i) = "ROBE"
    i = i + 1
    CSBWinObjNames(i) = "FINE ROBE(TOP)"
    i = i + 1
    CSBWinObjNames(i) = "FINE ROBE(BOTTOM)"
    i = i + 1
    CSBWinObjNames(i) = "KIRTLE"
    i = i + 1
    CSBWinObjNames(i) = "SILK SHIRT"
    i = i + 1
    CSBWinObjNames(i) = "TABARD"
    i = i + 1
    CSBWinObjNames(i) = "GUNNA"
    i = i + 1
    CSBWinObjNames(i) = "ELVEN DOUBLET"
    i = i + 1
    CSBWinObjNames(i) = "ELVEN HUKE"
    i = i + 1
    CSBWinObjNames(i) = "ELVEN BOOTS"
    i = i + 1
    CSBWinObjNames(i) = "LEATHER JERKIN"
    i = i + 1
    CSBWinObjNames(i) = "LEATHER PANTS"
    i = i + 1
    CSBWinObjNames(i) = "SUEDE BOOTS"
    i = i + 1
    CSBWinObjNames(i) = "BLUE PANTS"
    i = i + 1
    CSBWinObjNames(i) = "TUNIC"
    i = i + 1
    CSBWinObjNames(i) = "GHI"
    i = i + 1
    CSBWinObjNames(i) = "GHI TROUSERS"
    i = i + 1
    CSBWinObjNames(i) = "CALISTA"
    i = i + 1
    CSBWinObjNames(i) = "CROWN OF NERRA"
    i = i + 1
    CSBWinObjNames(i) = "BEZERKER HELM"
    i = i + 1
    CSBWinObjNames(i) = "HELMET"
    i = i + 1
    CSBWinObjNames(i) = "BASINET"
    i = i + 1
    CSBWinObjNames(i) = "NETA SHIELD"
    i = i + 1
    CSBWinObjNames(i) = "CRYSTAL SHIELD"
    i = i + 1
    CSBWinObjNames(i) = "WOODEN SHIELD"
    i = i + 1
    CSBWinObjNames(i) = "SMALL SHIELD"
    i = i + 1
    CSBWinObjNames(i) = "MAIL AKETON"
    i = i + 1
    CSBWinObjNames(i) = "LEG MAIL"
    i = i + 1
    CSBWinObjNames(i) = "MITHRAL AKETON"
    i = i + 1
    CSBWinObjNames(i) = "MITHRAL MAIL"
    i = i + 1
    CSBWinObjNames(i) = "CASQUE 'N COIF"
    i = i + 1
    CSBWinObjNames(i) = "HOSEN"
    i = i + 1
    CSBWinObjNames(i) = "ARMET"
    i = i + 1
    CSBWinObjNames(i) = "TORSO PLATE"
    i = i + 1
    CSBWinObjNames(i) = "LEG PLATE"
    i = i + 1
    CSBWinObjNames(i) = "FOOT PLATE"
    i = i + 1
    CSBWinObjNames(i) = "SAR SHIELD"
    i = i + 1
    CSBWinObjNames(i) = "HELM OF RA"
    i = i + 1
    CSBWinObjNames(i) = "PLATE OF RA"
    i = i + 1
    CSBWinObjNames(i) = "POLEYN OF RA"
    i = i + 1
    CSBWinObjNames(i) = "GREAVE OF RA"
    i = i + 1
    CSBWinObjNames(i) = "SHIELD OF RA"
    i = i + 1
    CSBWinObjNames(i) = "DRAGON HELM"
    i = i + 1
    CSBWinObjNames(i) = "DRAGON PLATE"
    i = i + 1
    CSBWinObjNames(i) = "DRAGON POLEYN"
    i = i + 1
    CSBWinObjNames(i) = "DRAGON GREAVE"
    i = i + 1
    CSBWinObjNames(i) = "DRAGON SHIELD"
    i = i + 1
    CSBWinObjNames(i) = "DEXHELM"
    i = i + 1
    CSBWinObjNames(i) = "FLAMEBAIN"
    i = i + 1
    CSBWinObjNames(i) = "POWERTOWERS"
    i = i + 1
    CSBWinObjNames(i) = "BOOTS OF SPEED"
    i = i + 1
    CSBWinObjNames(i) = "HALTER"
    i = i + 1
    CSBWinObjNames(i) = "COMPASS"
    i = i + 1
    CSBWinObjNames(i) = "WATERSKIN"
    i = i + 1
    CSBWinObjNames(i) = "JEWEL SYMAL"
    i = i + 1
    CSBWinObjNames(i) = "ILLUMULET"
    i = i + 1
    CSBWinObjNames(i) = "ASHES"
    i = i + 1
    CSBWinObjNames(i) = "BONES(PARTY)"
    i = i + 1
    CSBWinObjNames(i) = "SAR COIN"
    i = i + 1
    CSBWinObjNames(i) = "SILVER COIN"
    i = i + 1
    CSBWinObjNames(i) = "GOR COIN"
    i = i + 1
    CSBWinObjNames(i) = "IRON KEY"
    i = i + 1
    CSBWinObjNames(i) = "KEY OF B"
    i = i + 1
    CSBWinObjNames(i) = "SOLID KEY"
    i = i + 1
    CSBWinObjNames(i) = "SQUARE KEY"
    i = i + 1
    CSBWinObjNames(i) = "TOURQUOISE KEY"
    i = i + 1
    CSBWinObjNames(i) = "CROSS KEY"
    i = i + 1
    CSBWinObjNames(i) = "ONYX KEY"
    i = i + 1
    CSBWinObjNames(i) = "SKELETON KEY"
    i = i + 1
    CSBWinObjNames(i) = "GOLD KEY"
    i = i + 1
    CSBWinObjNames(i) = "WINGED KEY"
    i = i + 1
    CSBWinObjNames(i) = "TOPAZ KEY"
    i = i + 1
    CSBWinObjNames(i) = "SAPPHIRE KEY"
    i = i + 1
    CSBWinObjNames(i) = "EMERALD KEY"
    i = i + 1
    CSBWinObjNames(i) = "RUBY KEY"
    i = i + 1
    CSBWinObjNames(i) = "RA KEY"
    i = i + 1
    CSBWinObjNames(i) = "MASTER KEY"
    i = i + 1
    CSBWinObjNames(i) = "BOULDER"
    i = i + 1
    CSBWinObjNames(i) = "BLUE GEM"
    i = i + 1
    CSBWinObjNames(i) = "ORANGE GEM"
    i = i + 1
    CSBWinObjNames(i) = "GREEN GEM"
    i = i + 1
    CSBWinObjNames(i) = "APPLE"
    i = i + 1
    CSBWinObjNames(i) = "CORN"
    i = i + 1
    CSBWinObjNames(i) = "BREAD"
    i = i + 1
    CSBWinObjNames(i) = "CHEESE"
    i = i + 1
    CSBWinObjNames(i) = "SCREAMER SLICE"
    i = i + 1
    CSBWinObjNames(i) = "WORM ROUND"
    i = i + 1
    CSBWinObjNames(i) = "SHANK"
    i = i + 1
    CSBWinObjNames(i) = "DRAGON STEAK"
    i = i + 1
    CSBWinObjNames(i) = "GEM OF AGES"
    i = i + 1
    CSBWinObjNames(i) = "EKKHARD CROSS"
    i = i + 1
    CSBWinObjNames(i) = "MOONSTONE"
    i = i + 1
    CSBWinObjNames(i) = "THE HELLION"
    i = i + 1
    CSBWinObjNames(i) = "PENDANT FERAL"
    i = i + 1
    CSBWinObjNames(i) = "MAGIC BOX(BLUE)"
    i = i + 1
    CSBWinObjNames(i) = "MAGIC BOX(GREEN)"
    i = i + 1
    CSBWinObjNames(i) = "MIRROR OF DAWN"
    i = i + 1
    CSBWinObjNames(i) = "ROPE"
    i = i + 1
    CSBWinObjNames(i) = "RABBIT'S FOOT"
    i = i + 1
    CSBWinObjNames(i) = "CORBUM"
    i = i + 1
    CSBWinObjNames(i) = "CHOKER"
    i = i + 1
    CSBWinObjNames(i) = "LOCK PICKS"
    i = i + 1
    CSBWinObjNames(i) = "MAGNIFIER"
    i = i + 1
    CSBWinObjNames(i) = "ZOKATHRA SPELL"
    i = i + 1
    CSBWinObjNames(i) = "BONES"

End Sub

Public Function EFChange16(ByRef ctrl As TextBox, low As Long, high As Long) As Long
    EFChange16 = val(ctrl.Text)
    If EFChange16 > high Then
        EFChange16 = high
    End If
    If EFChange16 < low Then
        EFChange16 = low
    End If
    
    If Str(EFChange16) <> ctrl.Text Then
        ctrl.Text = Str(EFChange16)
        ctrl.selstart = 150
        ctrl.SelLength = 2
    End If
    
End Function
Public Function EFChange8(ByRef ctrl As TextBox, low As Long, high As Long) As Integer
    EFChange8 = val(ctrl.Text)
    If EFChange8 > high Then
        EFChange8 = high
    End If
    If EFChange8 < low Then
        EFChange8 = low
    End If
    
    If low < 0 Then
        If ctrl.Text = "-" Then
            Exit Function
        End If
    End If
    If Str(EFChange8) <> ctrl.Text Then
        ctrl.Text = Str(EFChange8)
        ctrl.selstart = 150
        ctrl.SelLength = 2
    End If
    
End Function
Sub Main()
    
    apppath = VB.App.Path
    dbg = False
    debug_init
    dprint ("debug file initialized")
    Dim window As MainWindow
    Set window = New MainWindow
    
    window.Show
    
    InitCSBWinObjNames

End Sub

Public Sub debug_deinit()
    If dbg = False Then
        Exit Sub
    End If
    
    dbg_file.Close
End Sub
Public Sub debug_init()
    If dbg = False Then
        Exit Sub
    End If
    
    Dim fs
    Dim f
    
    Set fs = CreateObject("Scripting.FileSystemObject")
    'If fs.FileExists("debug.txt") Then
    '    Set f = fs.GetFile("debug.txt")
    '    f.Delete
    'End If
    
    Set dbg_file = fs.CreateTextFile(App.apppath + "\debug.txt")
End Sub

Public Sub dprint(ByVal s As String)
    
    If dbg = False Then
        Exit Sub
    End If
    
    dbg_file.WriteLine (s)
    
End Sub

Function GetNextLZWCode(n)
    While (BitsInBuffer < n) And (LZWByteIndex < LenB(itemdata))     ' If there are enough bits in the buffer to make a code
        BitBuffer = BitBuffer + (AscB(MidB(itemdata, LZWByteIndex + 1, 1)) * 2 ^ BitsInBuffer) ' Add the next character to the left of the BitBuffer (hence the shift to the left)
        BitsInBuffer = BitsInBuffer + 8             ' 8 bits were added to the buffer
        LZWByteIndex = LZWByteIndex + 1             ' Go to the next input character
    Wend
    'MsgBox     "BitsInBuffer: " & BitsInBuffer & vbCrLf & _
    '   "n: " & n & vbCrLf & _
    '   "LZWByteIndex: " & LZWByteIndex & vbCrLf & _
    '   "Len(ItemData): " & Len(ItemData) & vbCrLf & _
    '   "BitBuffer: " & BitBuffer

    If BitsInBuffer >= n Then               ' If there are enough bits in the buffer to make a code
        GetNextLZWCode = BitBuffer And (2 ^ n - 1)  ' Add to the list of codes the code made with the BitsInCode most significant bits in the buffer
        BitBuffer = BitBuffer \ (2 ^ n)         ' Remove the output bits from the buffer by shifting the buffer to the right
        BitsInBuffer = BitsInBuffer - n     ' The number of bits in the buffer is decreased
    Else
        GetNextLZWCode = -1
    End If
    'MsgBox "NextLZWCode Is: " & GetNextLZWCode
End Function

Function LZWUncompress()
    Dim Dictionary, i, j, k, l, LZWString, LZWChar, NumberOfCodes, BitsInCode, OldCode, NewCode
Dim a, b, c
    Dim d
    ' Initialize LZW bit buffer
    BitBuffer = 0           ' The BitBuffer is empty
    BitsInBuffer = 0        ' So there are no bits stored in the buffer
    LZWByteIndex = 0        ' Start uncompressing LZW data at the first character in string
    BitsInCode = 9
    d = 0
    
    LZWUncompress = ""
    If LenB(itemdata) > 1 Then       ' We need at least one 9 bits code, which means at least two bytes
        ' Create and populate the dictionary for the LZW algorithm
        Set Dictionary = CreateObject("Scripting.Dictionary")
        For i = 0 To 255
            Dictionary.add Dictionary.count, ChrB(i)
        Next
        Dictionary.add 256, "Flush Dictionary"
        d = Dictionary.count
        OldCode = GetNextLZWCode(BitsInCode)                ' Get the first code
        LZWUncompress = Dictionary.Item(OldCode)            ' Output the string (which is a character) associated with the first code
        LZWChar = Dictionary.Item(OldCode)              ' Get the string associated with the first code

        NewCode = GetNextLZWCode(BitsInCode)
        While NewCode <> -1
            If NewCode <> 256 Then                  ' If the code is not the special value 256
                If Dictionary.Exists(NewCode) Then      ' If the current code is already in the dictionary
                    LZWString = Dictionary.Item(NewCode)    ' Get the string associated with that current code
                Else
                    LZWString = Dictionary.Item(OldCode)    ' Get the string associated with the previously read code
                    LZWString = LZWString & LZWChar     ' Add the latest input character read to the string
                End If
                LZWUncompress = LZWUncompress + LZWString   ' Output the string
                LZWChar = LeftB(LZWString, 1)            ' Get the first character of the string
                Dictionary.add d, (Dictionary.Item(OldCode) + LZWChar)  ' Add the new string to the dictionary
                d = d + 1
                If BitsInCode < 12 Then
                    If d = 2 ^ BitsInCode Then   ' If there are not anymore enough bits in a code to store the code's value
                        BitsInCode = BitsInCode + 1     ' Add a bit to the code length
                        'MsgBox "BitsInCode increased and is now: " & BitsInCode
                    End If
                End If

                OldCode = NewCode               ' Go on to next code
            Else
                'MsgBox "Code 256 found, flushing dictionary...", vbOKOnly + vbInformation, "Information"
                Dictionary.RemoveAll
                For i = 0 To 255
                    Dictionary.add Dictionary.count, ChrB(i)
                Next
                Dictionary.add 256, "Flush Dictionary"
                d = Dictionary.count
                BitsInCode = 9
            End If
            NewCode = GetNextLZWCode(BitsInCode)
        Wend

        i = 1
        While i < LenB(LZWUncompress)
            j = MidB(LZWUncompress, i, 1)
            If AscB(j) = 144 Then
                App.dprint ("found 0x90 byte")
                k = AscB(MidB(LZWUncompress, i + 1, 1))
                If k = 0 Then
                    App.dprint ("item in lzw if k=0 statement")
                    ' Remove the '00h' byte
                    'LZWUncompress = LeftB(LZWUncompress, i) + MidB(LZWUncompress, i + 2)
                    LZWUncompress = LeftB(LZWUncompress, i) + RightB(LZWUncompress, LenB(LZWUncompress) - i - 1)
                    i = i + 1
                Else
                    App.dprint ("item in lzw else statement (k=" + Str(k) + ")")
                    l = MidB(LZWUncompress, i - 1, 1)
                    a = LeftB(LZWUncompress, i - 1)
                    b = ""
                    For c = 1 To k - 1
                    b = b & l
                    Next
                    If LenB(b) <> k - 1 Then
                        MsgBox "lenb(b) != k-1 (" + Str(LenB(b)) + " != " + Str(k - 1) + ")"
                    End If
                    'b = String(k - 1, AscB(ChrB(l)))
                    c = RightB(LZWUncompress, LenB(LZWUncompress) - i - 1)
                    'c = MidB(LZWUncompress, i + 2)
                    LZWUncompress = a & b & c
                    i = i + k - 1
                End If
            Else
                i = i + 1
            End If
        Wend
    End If
End Function



'gread = read from a file, specified as fnum
'gwrite = write to a file, specified as fnum
'gsread = read from a string?
'gswrite = write to a string?

Function gread_bytes(ByVal length As Long, ByVal fnum As Long) As String
    gread_bytes = InputB(length, fnum)
End Function
Function gread_byte(ByVal fnum As Long) As Byte
    gread_byte = AscB(InputB(1, fnum))
End Function

Function gread_int(ByVal fnum As Long) As Long
    Dim b1, b2 As Byte
    Dim l1 As Long
    b2 = gread_byte(fnum)
    b1 = gread_byte(fnum)
    
    gread_int = b2
    gread_int = gread_int * 256
    gread_int = gread_int + b1
End Function
