UserGuide - Memory access
Some PureBasic instructions, for example those from the Cipher library and many operating system API calls, require a pointer to a memory buffer as an argument rather than the data directly itself. PureBasic provides a number of instructions to manipulate memory buffers to facilitate this. ;- Compiler Directives
EnableExplicit
;- Constants
; Window
Enumeration
#WindowHex
EndEnumeration
; Gadgets
Enumeration
#GadgetFiles
#GadgetOpen
#GadgetClose
#GadgetHex
EndEnumeration
;- Variables
Define.l Event, EventWindow, EventGadget, EventType, EventMenu
Define.l Length
Define.s File
Define *Buffer
;- Declarations
Declare WindowCreate()
Declare WindowResize()
Declare FileClose()
Declare FileDisplay()
Declare FileRead()
;- Implementation
Procedure WindowCreate()
; Create the window.
Protected.l Col
Protected.s Label
If OpenWindow(#WindowHex, 50, 50, 500, 400, "Hex View", #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_MinimizeGadget | #PB_Window_TitleBar)
; Set minimum window size.
WindowBounds(#WindowHex, 175, 175, #PB_Ignore, #PB_Ignore)
; Create Explorer List and set to user's home directory.
ExplorerListGadget(#GadgetFiles, 5, 5, 490, 175, GetHomeDirectory())
; Buttons.
ButtonGadget(#GadgetOpen, 5, 185, 80, 25, "Open")
ButtonGadget(#GadgetClose, 100, 185, 80, 25, "Close")
; List Icon Gadget.
ListIconGadget(#GadgetHex, 5, 215, 490, 180, "Offset", 80, #PB_ListIcon_AlwaysShowSelection | #PB_ListIcon_GridLines | #PB_ListIcon_FullRowSelect)
; Column Headings.
For Col = 0 To 7
Label = RSet(Hex(Col, #PB_Byte), 2, "0")
AddGadgetColumn(#GadgetHex, Col + 1, Label, 38)
Next Col
AddGadgetColumn(#GadgetHex, 9, "Text", 80)
EndIf
EndProcedure
Procedure WindowResize()
; Resize gadgets to new window size.
Protected.l X, Y, W, H
; Explorer List
W = WindowWidth(#WindowHex) - 10
H = (WindowHeight(#WindowHex) - 35) / 2
ResizeGadget(#GadgetFiles, #PB_Ignore, #PB_Ignore, W, H)
; Buttons
Y = GadgetHeight(#GadgetFiles) + 10
ResizeGadget(#GadgetOpen, #PB_Ignore, Y, #PB_Ignore, #PB_Ignore)
ResizeGadget(#GadgetClose, #PB_Ignore, Y, #PB_Ignore, #PB_Ignore)
; List Icon View
Y = (WindowHeight(#WindowHex) / 2) + 23
W = WindowWidth(#WindowHex) - 10
H = WindowHeight(#WindowHex) - (Y + 5)
ResizeGadget(#GadgetHex, #PB_Ignore, Y, W, H)
EndProcedure
Procedure FileClose()
; Clear the list view and release the memory buffer.
Shared Length, *Buffer
ClearGadgetItems(#GadgetHex)
FillMemory(*Buffer, Length)
FreeMemory(*Buffer)
EndProcedure
Procedure FileDisplay()
; Display the file buffer in the list view.
Shared Length, *Buffer
Protected *Byte
Protected Peek
Protected.l Rows, Cols, Offset
Protected.s OffsetString, Row, String
; Clear current contents.
ClearGadgetItems(#GadgetHex)
; Loop through rows.
For Rows = 0 To Length - 1 Step 8
; Clear the text value for each row.
String = ""
; Convert the offset value to a fixed length string.
Row = RSet(Hex(Rows, #PB_Long), 6, "0") + Chr(10)
; Loop through columns.
For Cols = 0 To 7
; Calculate the offset for the current column.
Offset = Rows + Cols
; Compare the offset with the file length.
If Offset < Length
; The offset is less than the length of the file.
; Obtain the byte from the buffer.
*Byte = *Buffer + Offset
Peek = PeekB(*Byte)
; Convert the byte to text.
Row + RSet(Hex(Peek, #PB_Byte), 2, "0") + Chr(10)
; Add the character to the text version.
Select Peek
Case 0 To 31, 127
; Unprintable characters.
String + Chr(129)
Default
; Printable characters.
String + Chr(Peek)
EndSelect
Else
; The offset is greater than the length of the file.
; Add an empty column.
Row + Chr(10)
EndIf
Next Cols
; Add the text version at the end of the hex columns.
Row + String
; Add the completed row to the list view.
AddGadgetItem(#GadgetHex, -1, Row)
Next Rows
EndProcedure
Procedure FileRead()
; Read the file into the memory buffer.
Shared Length, File, *Buffer
Protected.b ReadByte
Protected.l FileNumber, ReadLong, Size
; Stop if file is empty.
If File = ""
ProcedureReturn
EndIf
; Stop if file size is invalid.
Size = FileSize(File)
If Size < 1
ProcedureReturn
EndIf
; Open the file.
FileNumber = OpenFile(#PB_Any, File)
Length = Lof(FileNumber)
If File And Length
; Allocate a memory buffer to hold the file.
*Buffer = AllocateMemory(Length)
; Read the file into the buffer.
Length = ReadData(FileNumber, *Buffer, Length)
EndIf
; Close the file.
CloseFile(FileNumber)
EndProcedure
;- Main
WindowCreate()
;- Event Loop
Repeat
; Obtain event parameters.
Event = WaitWindowEvent()
EventGadget = EventGadget()
EventType = EventType()
EventWindow = EventWindow()
; Handle events.
Select Event
Case #PB_Event_Gadget
If EventGadget = #GadgetFiles
; Do nothing.
ElseIf EventGadget = #GadgetOpen
File = GetGadgetText(#GadgetFiles) + GetGadgetItemText(#GadgetFiles, GetGadgetState(#GadgetFiles))
If FileSize(File) > 0
FileRead()
FileDisplay()
EndIf
ElseIf EventGadget = #GadgetClose
FileClose()
ElseIf EventGadget = #GadgetHex
; Do nothing.
EndIf
Case #PB_Event_CloseWindow
If EventWindow = #WindowHex
CloseWindow(#WindowHex)
Break
EndIf
Case #PB_Event_SizeWindow
WindowResize()
EndSelect
ForEver
UserGuide Navigation
< Previous: Reading and writing files | Overview | Next: Dynamic numbering using #PB_Any >