summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <Pixel@.(none)>2009-12-14 08:13:06 -0800
committerunknown <Pixel@.(none)>2009-12-14 08:13:06 -0800
commit9e3a36537d07700ec49f432940b95cf2ee9689e8 (patch)
treefb8b327a09741297bc71867547ac144dec655767
parentbb07454bba0c0ba4d9f1ca6dfc94011ce8b65af0 (diff)
First insert of the various lua files.
-rw-r--r--dalos.lua160
-rw-r--r--ips-patcher.lua48
-rw-r--r--iupe-dbuffer.lua43
-rw-r--r--iupe-hexview-toolbox.lua272
-rw-r--r--iupe-hexview.lua552
-rw-r--r--iupe-tview.lua108
6 files changed, 1183 insertions, 0 deletions
diff --git a/dalos.lua b/dalos.lua
new file mode 100644
index 0000000..5381411
--- /dev/null
+++ b/dalos.lua
@@ -0,0 +1,160 @@
+loadmodule "luaiup"
+loadmodule "luahandle"
+loadmodule "lualibs"
+
+load "iupe-dbuffer.lua"
+load "iupe-hexview.lua"
+load "iupe-hexview-toolbox.lua"
+load "iupe-tview.lua"
+
+if not dalosp then dalosp = {} end
+if not dalos then dalos = {} end
+
+dalosp.canvas = {
+ draw = function (self)
+ local cvdb = self.cvdb
+ if not cvdb then return iup.DEFAULT end
+ cvdb:Clear()
+
+ for k, v in ipairs(self.objects) do
+ v.obj:draw(cvdb, v.x, v.y, v.w, v.h)
+ end
+
+ cvdb:Flush()
+
+ return iup.DEFAULT
+ end,
+
+ addobj = function (self, obj, x, y, w, h)
+ table.insert(self.objects, { obj = obj, x = x, y = y, w = w, h = h })
+ self:draw()
+ end,
+
+ findobj = function (self, x, y)
+ local obj, ind
+
+ x = x + 0
+ y = y + 0
+
+ for k, v in ipairs(self.objects) do
+ if v.x <= x and (v.x + v.w) >= x and v.y <= y and (v.y + v.h) >= y then
+ obj, ind = v, k
+ end
+ end
+
+ return obj, ind
+ end,
+
+ moveobj = function (self, obj, x, y)
+ obj.x, obj.y = x, y
+ self:draw()
+ end,
+
+ focus_cb = function (self, focus)
+ end,
+
+ motion_cb = function (self, x, y, status)
+ if iup.isbutton1(status) then
+ elseif iup.isbutton3(status) then
+ elseif iup.isbutton2(status) then
+ local moving = self.moving
+ if moving then
+ local ox, oy = self.ox, self.oy
+ local dx, dy = x - ox, y - oy
+ self:moveobj(moving, moving.x + dx, moving.y + dy)
+ self.ox, self.oy = x, y
+ end
+ end
+ end,
+
+ button_cb = function (self, button, pressed, x, y, status)
+ if button == iup.BUTTON1 then
+ if pressed == 1 then
+ else
+ end
+ elseif button == iup.BUTTON3 then
+ if pressed == 1 then
+ else
+ end
+ elseif button == iup.BUTTON2 then
+ if pressed == 1 then
+ self.moving = self:findobj(x, y)
+ self.ox, self.oy = x, y
+ else
+ self.moving = nil
+ end
+ end
+ end,
+
+ create = function (tab)
+ tab.border = "No"
+ tab.expand = "Yes"
+ tab.shrink = "Yes"
+ tab.minsize = "1x1"
+ tab.size = "1x1"
+ local r = iup.canvas(tab)
+ r.action = iupep.dbuffer.action
+ r.draw = dalosp.canvas.draw
+ r.resize_cb = iupep.dbuffer.resize_cb
+ r.map_cb = iupep.dbuffer.map_cb
+ r.unmap_cb = iupep.dbuffer.unmap_cb
+ r.focus_cb = dalosp.canvas.focus_cb
+ r.motion_cb = dalosp.canvas.motion_cb
+ r.button_cb = dalosp.canvas.button_cb
+ r.addobj = dalosp.canvas.addobj
+ r.findobj = dalosp.canvas.findobj
+ r.moveobj = dalosp.canvas.moveobj
+
+ r.objects = {}
+
+ return r
+ end,
+}
+
+dalosp.menu = {
+ action_exit = function (self)
+ return iup.CLOSE
+ end,
+
+ create = function (tab)
+ local item_exit = iup.item { title = "Exit" }
+ item_exit.action = dalosp.menu.action_exit
+ local item_about = iup.item { title = "About" }
+ local menu_file = iup.submenu { iup.menu { item_exit }, title = "File" }
+ local menu_help = iup.submenu { iup.menu { item_about }, title = "Help" }
+ return iup.menu { menu_file, menu_help }
+ end,
+}
+
+dalosp.object = {
+ default_draw = function (self, cv, x, y, w, h )
+ cv:Foreground(self.color)
+ local x1, x2, y1, y2 = x, x + w, y, y + h
+ cv:Box(x1, x2, cv:InvertYAxis(y2), cv:InvertYAxis(y1))
+ end,
+
+ create = function (dcanvas, x, y, w, h, c)
+ local obj = {
+ draw = dalosp.object.default_draw,
+ color = c or cd.BLACK
+ }
+
+ dcanvas:addobj(obj, x or 0, y or 0, w or 50, h or 50)
+ end,
+}
+
+dalos.canvas = dalosp.canvas.create
+dalos.menu = dalosp.menu.create
+dalos.object = dalosp.object.create
+
+----------------
+
+d = dalos.canvas {}
+m = dalos.menu {}
+o = dalos.object(d)
+
+dlg = iup.dialog { d, title = "Dalos", menu = m }
+
+dlg:show()
+iup.MainLoop()
+dlg:hide()
diff --git a/ips-patcher.lua b/ips-patcher.lua
new file mode 100644
index 0000000..316f8da
--- /dev/null
+++ b/ips-patcher.lua
@@ -0,0 +1,48 @@
+-- based on http://zerosoft.zophar.net/ips.php (note the data is big endian - this isn't clear from the text)
+
+local function read_some_bytes(fin, siz)
+ local ret = 0
+
+ for _ = 1, siz do
+ ret = ret * 256 + fin:readU8()
+ end
+
+ return ret
+end
+
+function ips_patch(buffer, ips)
+ local header, offset, size, b = "", 0, 0
+
+ for _ = 1, 5 do
+ header = header .. string.char(ips:readU8())
+ end
+
+ if header ~= "PATCH" then error "Wrong IPS file format - bad header" end
+
+ while true do
+ offset = read_some_bytes(ips, 3)
+
+ -- that's one of the most stupid thing ever... you can NOT patch the offset
+ -- 0x454F46 since this is the end of the ips file marker... whomever came
+ -- with this brillant design needs a smack in the face.
+ if offset == 0x454F46 then
+ break
+ end
+
+ buffer:seek(offset)
+ if buffer.wseek then buffer:wseek(offset) end
+
+ size = read_some_bytes(ips, 2)
+
+ if size == 0 then
+ size = read_some_bytes(ips, 2)
+ b = ips:readU8()
+ for _ = 1, size do buffer:writeU8(b) end
+ else
+ ips:copyto(buffer, size)
+ end
+ end
+
+ buffer:seek(0)
+ if buffer.wseek then buffer:wseek(0) end
+end
diff --git a/iupe-dbuffer.lua b/iupe-dbuffer.lua
new file mode 100644
index 0000000..4321206
--- /dev/null
+++ b/iupe-dbuffer.lua
@@ -0,0 +1,43 @@
+loadmodule "luaiup"
+loadmodule "luahandle"
+loadmodule "lualibs"
+
+if not iupep then iupep = {} end
+
+iupep.dbuffer = {
+ map_cb = function (self)
+ self.cv = cd.CreateCanvas(cd.IUP, self)
+ if not self.cv then return iup.DEFAULT end
+ local cvdb = cd.CreateCanvas(cd.DBUFFER, self.cv)
+ self.cvdb = cvdb
+ return iup.DEFAULT
+ end,
+
+ unmap_cb = function(self)
+ if self.cv then cd.KillCanvas(self.cv) end
+ if self.cvdb then cd.KillCanvas(self.cvdb) end
+ end,
+
+ resize_cb = function(self, width, height)
+ local cv = self.cv
+ local cvdb = self.cvdb
+ if not cvdb then
+ cv:Activate()
+ self.cvdb = cd.CreateCanvas(cd.DBUFFER, cv)
+ cvdb = self.cvdb
+ end
+ self.width = width
+ self.height = height
+ if not cvdb then return iup.DEFAULT end
+ cvdb:Activate()
+ return self:draw()
+ end,
+
+ action = function(self, posx, posy)
+ local cvdb = self.cvdb
+ if not cvdb then return end
+ cvdb:Flush()
+
+ return iup.DEFAULT
+ end,
+}
diff --git a/iupe-hexview-toolbox.lua b/iupe-hexview-toolbox.lua
new file mode 100644
index 0000000..7cfb7a4
--- /dev/null
+++ b/iupe-hexview-toolbox.lua
@@ -0,0 +1,272 @@
+loadmodule "luaiup"
+loadmodule "luahandle"
+loadmodule "lualibs"
+
+if not iupe then iupe = {} end
+if not iupep then iupep = {} end
+
+iupep.hexview_toolbox = {
+ clipboard = iup.clipboard{},
+
+ getcursor = function (self, hexview)
+ local rcursor = self.cursorlist.value - 3
+ local r
+ if rcursor == -2 then
+ r = hexview.kcursor
+ elseif rcursor == -1 then
+ r = hexview.mcursor
+ else
+ r = hexview.markers[rcursor]
+ end
+
+ return r + 0, markercolors[rcursor]
+ end,
+
+ hexview_cb = function (self, hexview)
+ local filecursor = hexview.filecursor
+ local filesize = hexview.filesize
+ local fcl = self.cursors.file
+ fcl.dec.title = filecursor
+ fcl.hex.title = hex(filecursor, "0x%08x")
+ local rend = filesize - filecursor
+ fcl.rend_dec.title = rend
+ fcl.rend_hex.title = hex(rend, "0x%08x")
+
+ local cursor, bgcolor = self:getcursor(hexview)
+ local oldcursor = self.oldcursor + 0
+ if oldcursor == cursor or cursor == -1 then return iup.DEFAULT end
+ self.oldcursor = cursor
+ local cl = self.cursors.normal
+ cl.dec.title = cursor
+ cl.hex.title = hex(cursor, "0x%08x")
+ rend = filesize - cursor
+ cl.rend_dec.title = rend
+ cl.rend_hex.title = hex(rend, "0x%08x")
+
+ cl.dec.bgcolor = bgcolor
+ cl.hex.bgcolor = bgcolor
+ cl.rend_dec.bgcolor = bgcolor
+ cl.rend_hex.bgcolor = bgcolor
+
+ local endianess = self.endianess.value + 0
+ local nbbytes = math.min(4, filesize - cursor)
+
+ local handle = hexview.handle
+ local v = self.values
+ if not handle or nbbytes == 0 then
+ for _, w in ipairs(v) do w.title = "n/a" end
+ return iup.DEFAULT
+ end
+
+ local buf = Buffer(true)
+ handle:seek(cursor)
+ buf:copyfrom(handle, nbbytes)
+
+ local u8 = buf:readU8()
+ buf:seek(0)
+ v.u8.title = u8
+ v.i8.title = u8 > 127 and u8 - 256 or u8
+
+ if nbbytes >= 2 then
+ local u16
+ if endianess == 1 then
+ u16 = buf:readU16()
+ else
+ local u1, u2
+ u1 = buf:readU8()
+ u2 = buf:readU8()
+ u16 = u2 + u1 * 256
+ end
+ buf:seek(0)
+ v.u16.title = u16
+ v.i16.title = u16 > 32767 and u16 - 65536 or u16
+ else
+ v.u16.title = "n/a"
+ v.i16.title = "n/a"
+ end
+
+ if nbbytes >= 4 then
+ local u32
+ if endianess == 1 then
+ u32 = buf:readU32()
+ else
+ local u1, u2, u3, u4
+ u1 = buf:readU8()
+ u2 = buf:readU8()
+ u3 = buf:readU8()
+ u4 = buf:readU8()
+ u32 = u4 + u3 * 256 + u2 * 65536 + u1 * 16777216
+ end
+ buf:seek(0)
+ if endianess == 2 then
+ local u1, u2, u3, u4
+ u1 = buf:readU8()
+ u2 = buf:readU8()
+ u3 = buf:readU8()
+ u4 = buf:readU8()
+ buf:reset()
+ buf:writeU8(u4)
+ buf:writeU8(u3)
+ buf:writeU8(u2)
+ buf:writeU8(u1)
+ end
+ local flt = buf:readFloat()
+ v.u32.title = u32
+ v.i32.title = u32 > 2147483647 and u32 - 4294967296 or u32
+ v.flt.title = flt
+ else
+ v.u16.title = "n/a"
+ v.i16.title = "n/a"
+ v.flt.title = "n/a"
+ end
+
+ buf:destroy()
+
+ return iup.DEFAULT
+ end,
+
+ cursor_change = function (self, hexview, toolbox, rend)
+ local ok, value = iup.GetParam("Cursor change", nil, "%s\n", self.title)
+ local isint
+ isint, value = pcall(function() return value + 0 end)
+ if not isint then return iup.DEFAULT end
+ local newvalue = rend and (hexview.filesize - value) or value
+ hexview:setcursor(toolbox.cursorlist.value - 3, newvalue)
+ return iup.DEFAULT
+ end,
+
+ filecursor_change = function (self, hexview, toolbox, rend)
+ local ok, value = iup.GetParam("File position change", nil, "%s\n", self.title)
+ local isint
+ isint, value = pcall(function() return value + 0 end)
+ if not isint then return iup.DEFAULT end
+ hexview.filecursor = math.min(math.max(rend and (hexview.filesize - value) or value, 0), hexview.filesize)
+ toolbox:hexview_cb(hexview)
+ hexview:updatescrollbar()
+ hexview:draw()
+ return iup.DEFAULT
+ end,
+
+ value_enquery = function (self)
+ -- iup.GetParam("Value copy/paste", nil, "%s\n", self.title)
+ iupep.hexview_toolbox.clipboard.text = self.title
+ end,
+
+ create = function (tab)
+ local hexview = tab.hexview
+ tab.hexview = nil
+ local cursorlabel_dec = iup.button{ tip = "Position of active cursor.\nClick to select/change.", expand = "Horizontal", font = "Courier", alignment = "ARIGHT", flat = "Yes", spacing = "0", canfocus = "No", focusonclick = "No" }
+ local cursorlabel_hex = iup.button{ tip = "Position of active cursor.\nClick to select/change.", expand = "Horizontal", font = "Courier", alignment = "ARIGHT", flat = "Yes", spacing = "0", canfocus = "No", focusonclick = "No" }
+ local cursorlabel_rend_dec = iup.button{ tip = "Position of active cursor,\nrelative to the end.\nClick to select/change.", expand = "Horizontal", font = "Courier", alignment = "ARIGHT", flat = "Yes", spacing = "0", canfocus = "No", focusonclick = "No" }
+ local cursorlabel_rend_hex = iup.button{ tip = "Position of active cursor,\nrelative to the end.\nClick to select/change.", expand = "Horizontal", font = "Courier", alignment = "ARIGHT", flat = "Yes", spacing = "0", canfocus = "No", focusonclick = "No" }
+ local filecursorlabel_dec = iup.button{ tip = "Position of window.\nClick to select/change.", expand = "Horizontal", font = "Courier", alignment = "ARIGHT", flat = "Yes", spacing = "0", canfocus = "No", focusonclick = "No" }
+ local filecursorlabel_hex = iup.button{ tip = "Position of window.\nClick to select/change.", expand = "Horizontal", font = "Courier", alignment = "ARIGHT", flat = "Yes", spacing = "0", canfocus = "No", focusonclick = "No" }
+ local filecursorlabel_rend_dec = iup.button{ tip = "Position of window,\nrelative to the end.\nClick to select/change.", expand = "Horizontal", font = "Courier", alignment = "ARIGHT", flat = "Yes", spacing = "0", canfocus = "No", focusonclick = "No" }
+ local filecursorlabel_rend_hex = iup.button{ tip = "Position of window,\nrelative to the end.\nClick to select/change.", expand = "Horizontal", font = "Courier", alignment = "ARIGHT", flat = "Yes", spacing = "0", canfocus = "No", focusonclick = "No" }
+ local cursorlist = iup.list{ tip = "Active cursor.", dropdown = "Yes", value = "1", "Keyboard", "Mouse", "Cursor 0", "Cursor 1", "Cursor 2", "Cursor 3", "Cursor 4", "Cursor 5", "Cursor 6", "Cursor 7", "Cursor 8", "Cursor 9", "Cursor 10" }
+ local endianess = iup.list{ tip = "Display value endianess.", dropdown = "Yes", value = "1", "Little Endian", "Big Endian" }
+ local cvlabel_u8 = iup.button{ tip = "Type: uint8.\nClick to copy value in clipboard", expand = "Horizontal", font = "Courier", alignment = "ARIGHT", flat = "Yes", spacing = "0", canfocus = "No", focusonclick = "No" }
+ local cvlabel_i8 = iup.button{ tip = "Type: int8.\nClick to copy value in clipboard", expand = "Horizontal", font = "Courier", alignment = "ARIGHT", flat = "Yes", spacing = "0", canfocus = "No", focusonclick = "No" }
+ local cvlabel_u16 = iup.button{ tip = "Type: uint16.\nClick to copy value in clipboard", expand = "Horizontal", font = "Courier", alignment = "ARIGHT", flat = "Yes", spacing = "0", canfocus = "No", focusonclick = "No" }
+ local cvlabel_i16 = iup.button{ tip = "Type: int16.\nClick to copy value in clipboard", expand = "Horizontal", font = "Courier", alignment = "ARIGHT", flat = "Yes", spacing = "0", canfocus = "No", focusonclick = "No" }
+ local cvlabel_u32 = iup.button{ tip = "Type: uint32.\nClick to copy value in clipboard", expand = "Horizontal", font = "Courier", alignment = "ARIGHT", flat = "Yes", spacing = "0", canfocus = "No", focusonclick = "No" }
+ local cvlabel_i32 = iup.button{ tip = "Type: int32.\nClick to copy value in clipboard", expand = "Horizontal", font = "Courier", alignment = "ARIGHT", flat = "Yes", spacing = "0", canfocus = "No", focusonclick = "No" }
+ local cvlabel_flt = iup.button{ tip = "Type: float.\nClick to copy value in clipboard", expand = "Horizontal", font = "Courier", alignment = "ARIGHT", flat = "Yes", spacing = "0", canfocus = "No", focusonclick = "No" }
+ local r = iup.frame {
+ iup.vbox {
+ iup.label{ title = "Cursor", font = "Helvetica, Bold 10" },
+ cursorlist,
+ iup.label{ separator = "Horizontal" },
+ iup.label{ title = "Cursor position", font = "Helvetica, Bold 10" },
+ cursorlabel_dec,
+ cursorlabel_rend_dec,
+ cursorlabel_hex,
+ cursorlabel_rend_hex,
+ iup.label{ separator = "Horizontal" },
+ iup.label{ title = "Cursor value", font = "Helvetica, Bold 10" },
+ endianess,
+ cvlabel_i8,
+ cvlabel_u8,
+ cvlabel_i16,
+ cvlabel_u16,
+ cvlabel_i32,
+ cvlabel_u32,
+ cvlabel_flt,
+ iup.label{ separator = "Horizontal" },
+ iup.label{ title = "File position", font = "Helvetica, Bold 10" },
+ filecursorlabel_dec,
+ filecursorlabel_rend_dec,
+ filecursorlabel_hex,
+ filecursorlabel_rend_hex,
+ iup.fill{},
+ },
+
+ unpack(tab),
+ }
+
+ r.cursors = {
+ normal = {
+ dec = cursorlabel_dec,
+ hex = cursorlabel_hex,
+ rend_dec = cursorlabel_rend_dec,
+ rend_hex = cursorlabel_rend_hex,
+ },
+ file = {
+ dec = filecursorlabel_dec,
+ hex = filecursorlabel_hex,
+ rend_dec = filecursorlabel_rend_dec,
+ rend_hex = filecursorlabel_rend_hex,
+ },
+ }
+
+ r.values = {
+ u8 = cvlabel_u8,
+ i8 = cvlabel_i8,
+ u16 = cvlabel_u16,
+ i16 = cvlabel_i16,
+ u32 = cvlabel_u32,
+ i32 = cvlabel_i32,
+ flt = cvlabel_flt,
+ }
+
+ r.cursorlist = cursorlist
+ r.endianess = endianess
+ r.getcursor = iupep.hexview_toolbox.getcursor
+ r.hexview_cb = iupep.hexview_toolbox.hexview_cb
+ r.oldcursor = -1
+
+ hexview:registercb(r.hexview_cb, r)
+
+ function cursorlist:action(text, pos, state)
+ r:hexview_cb(hexview)
+ end
+
+ function endianess:action(text, pos, state)
+ r.oldcursor = -1
+ r:hexview_cb(hexview)
+ end
+
+ cursorlabel_dec.action = function (self) return iupep.hexview_toolbox.cursor_change(self, hexview, r, false) end
+ cursorlabel_hex.action = function (self) return iupep.hexview_toolbox.cursor_change(self, hexview, r, false) end
+ cursorlabel_rend_dec.action = function (self) return iupep.hexview_toolbox.cursor_change(self, hexview, r, true) end
+ cursorlabel_rend_hex.action = function (self) return iupep.hexview_toolbox.cursor_change(self, hexview, r, true) end
+
+ filecursorlabel_dec.action = function (self) return iupep.hexview_toolbox.filecursor_change(self, hexview, r, false) end
+ filecursorlabel_hex.action = function (self) return iupep.hexview_toolbox.filecursor_change(self, hexview, r, false) end
+ filecursorlabel_rend_dec.action = function (self) return iupep.hexview_toolbox.filecursor_change(self, hexview, r, true) end
+ filecursorlabel_rend_hex.action = function (self) return iupep.hexview_toolbox.filecursor_change(self, hexview, r, true) end
+
+ cvlabel_u8.action = iupep.hexview_toolbox.value_enquery
+ cvlabel_i8.action = iupep.hexview_toolbox.value_enquery
+ cvlabel_u16.action = iupep.hexview_toolbox.value_enquery
+ cvlabel_i16.action = iupep.hexview_toolbox.value_enquery
+ cvlabel_u32.action = iupep.hexview_toolbox.value_enquery
+ cvlabel_i32.action = iupep.hexview_toolbox.value_enquery
+ cvlabel_flt.action = iupep.hexview_toolbox.value_enquery
+
+ r:hexview_cb(hexview)
+ return r
+ end,
+}
+
+iupe.hexview_toolbox = iupep.hexview_toolbox.create
diff --git a/iupe-hexview.lua b/iupe-hexview.lua
new file mode 100644
index 0000000..12ec90c
--- /dev/null
+++ b/iupe-hexview.lua
@@ -0,0 +1,552 @@
+loadmodule "luaiup"
+loadmodule "luahandle"
+loadmodule "lualibs"
+
+load "iupe-dbuffer.lua"
+
+if not iupe then iupe = {} end
+if not iupep then iupep = {} end
+
+local cursorcolors = {
+ GREEN = cd.EncodeColor(0, 224, 0),
+ LIGHTGREEN = cd.EncodeColor(224, 255, 224),
+}
+
+local mousecolors = {
+ YELLOW = cd.EncodeColor(255, 255, 0),
+ LIGHTYELLOW = cd.EncodeColor(255, 255, 192),
+}
+
+markercolors = {
+ [-2] = cursorcolors.GREEN,
+ [-1] = mousecolors.YELLOW,
+ [0] = cd.EncodeColor(0, 255, 178), -- 0.45
+ [1] = cd.EncodeColor(0, 255, 255), -- 0.50
+ [2] = cd.EncodeColor(0, 178, 255), -- 0.55
+ [3] = cd.EncodeColor(0, 102, 255), -- 0.60
+ [4] = cd.EncodeColor(0, 25, 255), -- 0.65
+ [5] = cd.EncodeColor(50, 0, 255), -- 0.70
+ [6] = cd.EncodeColor(127, 0, 255), -- 0.75
+ [7] = cd.EncodeColor(204, 0, 255), -- 0.80
+ [8] = cd.EncodeColor(255, 0, 229), -- 0.85
+ [9] = cd.EncodeColor(255, 0, 152), -- 0.90
+ [10] = cd.EncodeColor(255, 0, 76), -- 0.95
+}
+
+iupep.hexview = {
+ printgrid = function (self, msg, y, x)
+ local cvdb = self.cvdb
+ if not x then x = self.textcursor.x end
+ if not y then y = self.textcursor.y end
+ cvdb:Foreground(cd.BLACK)
+ cvdb:Text(x * self.gridsize.x, self.height - self.gridsize.y * (y + 1), msg)
+ self.textcursor.x = x + msg:len()
+ self.textcursor.y = y
+ end,
+
+ colorgrid = function (self, color, len, y, x, height)
+ local cvdb = self.cvdb
+ if not len then len = 1 end
+ if not height then height = 1 end
+ if not x then x = self.textcursor.x end
+ if not y then y = self.textcursor.y end
+ cvdb:Foreground(color)
+ local xmin, xmax, ymin, ymax = x * self.gridsize.x, (x + len) * self.gridsize.x - 1, self.height - self.gridsize.y * (y + 1 - height) - 2, self.height - self.gridsize.y * (y + 1) - 1
+ cvdb:Box(xmin, xmax, ymin, ymax)
+ end,
+
+ byte2char = function(self, b)
+ if b >= 32 and b <= 127 then
+ return string.char(b)
+ else
+ return "."
+ end
+ end,
+
+ draw = function (self)
+ local cvdb = self.cvdb
+ if not cvdb then return iup.DEFAULT end
+ cvdb:Clear()
+ local handle = self.handle
+ local filecursor = self.filecursor + 0
+ local nbbytes = self.nbbytes + 0
+ local filesize = self.filesize + 0
+ local oldfilecursor = self.oldfilecursor + 0
+ local buf = self.buf
+ local max_bytes = math.max(math.min(filesize - filecursor, nbbytes), 0)
+ local old_max_bytes = (self.old_max_bytes or -1) + 0
+ if handle then
+ handle:seek(filecursor)
+ if ((filecursor ~= oldfilecursor or max_bytes ~= old_max_bytes) and max_bytes ~= 0) or not buf then
+ if buf then buf:destroy() end
+ buf = Buffer(true)
+ self.buf = buf
+ handle:copyto(buf, max_bytes)
+ self.oldfilecursor = filecursor
+ self.old_max_bytes = max_bytes
+ else
+ buf:seek(0)
+ end
+ end
+ local line = 0
+ local rcursor = 0
+ local b
+ local kline, kcolumn
+ local mline, mcolumn
+ local krcursor = self.kcursor - filecursor
+ local mrcursor = self.mcursor - filecursor
+ local columns = self.columns + 0
+ local nblines = self.nblines + 0
+ kline = math.floor(krcursor / columns)
+ kcolumn = krcursor % columns
+ mline = math.floor(mrcursor / columns)
+ mcolumn = mrcursor % columns
+
+ if self.mcursor ~= "-1" then
+ self:colorgrid(mousecolors.LIGHTYELLOW, 12 + columns * 4, mline, 0)
+ self:colorgrid(mousecolors.LIGHTYELLOW, 2, nblines - 1, mcolumn * 3 + 10, nblines)
+ self:colorgrid(mousecolors.LIGHTYELLOW, 1, nblines - 1, mcolumn + 12 + columns * 3, nblines)
+ self:colorgrid(mousecolors.YELLOW, 2, mline, mcolumn * 3 + 10)
+ self:colorgrid(mousecolors.YELLOW, 1, mline, mcolumn + 12 + columns * 3)
+ end
+
+ self:colorgrid(cursorcolors.LIGHTGREEN, 12 + columns * 4, kline, 0)
+ self:colorgrid(cursorcolors.LIGHTGREEN, 2, nblines - 1, kcolumn * 3 + 10, nblines)
+ self:colorgrid(cursorcolors.LIGHTGREEN, 1, nblines - 1, kcolumn + 12 + columns * 3, nblines)
+ self:colorgrid(cursorcolors.GREEN, 2, kline, kcolumn * 3 + 10)
+ self:colorgrid(cursorcolors.GREEN, 1, kline, kcolumn + 12 + columns * 3)
+
+ local marker
+ for i = 0, 10 do
+ marker = self.markers[i]
+ if marker ~= -1 then
+ mline = math.floor(marker / columns)
+ mcolumn = marker % columns
+ self:colorgrid(markercolors[i], 2, mline, mcolumn * 3 + 10)
+ self:colorgrid(markercolors[i], 1, mline, mcolumn + 12 + columns * 3)
+ end
+ end
+
+ while rcursor < max_bytes do
+ local dstring = ""
+ self:printgrid(hex(buf:tell() + filecursor, "%08x "), line, 0)
+ for c = 1, columns do
+ b = buf:readU8()
+ self:printgrid(hex(b, "%02x "))
+ dstring = dstring .. self:byte2char(b)
+ rcursor = rcursor + 1
+ if rcursor >= max_bytes then break end
+ end
+ self:printgrid(dstring, line, 12 + columns * 3)
+ line = line + 1
+ end
+
+ cvdb:Flush()
+
+ return iup.DEFAULT
+ end,
+
+ updatescrollbar = function (self)
+ self.ymax = math.floor(self.filesize / self.columns)
+ self.dy = 1
+ self.posy = math.floor(self.filecursor / self.columns)
+ iup.Update(self)
+ end,
+
+ resize_cb = function (self, width, height)
+ local displaylines = self.displaylines + 0
+ self.nblines = displaylines > 0 and displaylines or math.floor(height / self.gridsize.y)
+ self.nbbytes = self.nblines * self.columns
+ self:updatescrollbar()
+ iupep.dbuffer.resize_cb(self, width, height)
+ end,
+
+ keypress_cb = function (self, c, press)
+ if press == 0 then return iup.DEFAULT end
+ local kaction = false
+ local raction = false
+ local kcursor = self.kcursor + 0
+ local columns = self.columns + 0
+ local filesize = self.filesize + 0
+ local filecursor = self.filecursor + 0
+ local nbbytes = self.nbbytes + 0
+ if c == iup.K_UP then
+ kaction = true
+ kcursor = math.max(kcursor - columns, 0)
+ elseif c == iup.K_DOWN then
+ kaction = true
+ kcursor = math.min(kcursor + columns, filesize - 1)
+ elseif c == iup.K_LEFT then
+ kaction = true
+ kcursor = math.max(kcursor - 1, 0)
+ elseif c == iup.K_RIGHT then
+ kaction = true
+ kcursor = math.min(kcursor + 1, filesize - 1)
+ elseif c == iup.K_PGUP then
+ kaction = true
+ kcursor = math.max(kcursor - nbbytes + columns, 0)
+ elseif c == iup.K_PGDN then
+ kaction = true
+ kcursor = math.min(kcursor + nbbytes - columns, filesize - 1)
+ elseif c == iup.K_HOME then
+ kaction = true
+ kcursor = kcursor - (kcursor % columns)
+ elseif c == iup.K_END then
+ kaction = true
+ kcursor = math.min(kcursor + columns - (kcursor % columns) - 1, filesize - 1)
+ elseif c == iup.K_cUP then
+ kaction = true
+ if filecursor - columns >= 0 then
+ kcursor = kcursor - columns
+ filecursor = filecursor - columns
+ end
+ elseif c == iup.K_cDOWN then
+ kaction = true
+ if filecursor + columns < filesize then
+ kcursor = kcursor + columns
+ filecursor = filecursor + columns
+ end
+ elseif c == iup.K_cLEFT then
+ kaction = true
+ kcursor = math.max(kcursor - 1, 0)
+ filecursor = math.max(filecursor - 1, 0)
+ elseif c == iup.K_cRIGHT then
+ kaction = true
+ kcursor = math.min(kcursor + 1, filesize - 1)
+ filecursor = math.min(filecursor + 1, filesize)
+ elseif c == iup.K_cPGUP then
+ kaction = true
+ if filecursor - nbbytes >= 0 then
+ kcursor = math.max(kcursor - nbbytes, 0)
+ filecursor = math.max(filecursor - nbbytes, 0)
+ end
+ elseif c == iup.K_cPGDN then
+ kaction = true
+ if filecursor + nbbytes < filesize then
+ kcursor = math.min(kcursor + nbbytes, filesize - 1)
+ filecursor = math.min(filecursor + nbbytes, filesize)
+ end
+ elseif c == iup.K_cHOME then
+ kaction = true
+ kcursor = 0
+ elseif c == iup.K_cEND then
+ kaction = true
+ kcursor = filesize - 1
+ elseif c == iup.K_mLEFT then
+ raction = true
+ columns = columns - 1
+ elseif c == iup.K_mRIGHT then
+ raction = true
+ columns = columns + 1
+ elseif c == iup.K_mUP then
+ raction = true
+ filecursor = math.max(filecursor - columns, 0)
+ elseif c == iup.K_mDOWN then
+ raction = true
+ filecursor = math.min(filecursor + columns, filesize)
+ elseif c == iup.K_mPGUP then
+ raction = true
+ filecursor = math.max(filecursor - nbbytes, 0)
+ elseif c == iup.K_mPGDN then
+ raction = true
+ filecursor = math.min(filecursor + nbbytes, filesize)
+ elseif c == iup.K_1 then
+ kaction = true
+ local m = self.markers[1]
+ if m ~= -1 then
+ kcursor = m
+ end
+ elseif c == iup.K_2 then
+ kaction = true
+ local m = self.markers[2]
+ if m ~= -1 then
+ kcursor = m
+ end
+ elseif c == iup.K_3 then
+ kaction = true
+ local m = self.markers[3]
+ if m ~= -1 then
+ kcursor = m
+ end
+ elseif c == iup.K_4 then
+ kaction = true
+ local m = self.markers[4]
+ if m ~= -1 then
+ kcursor = m
+ end
+ elseif c == iup.K_5 then
+ kaction = true
+ local m = self.markers[5]
+ if m ~= -1 then
+ kcursor = m
+ end
+ elseif c == iup.K_6 then
+ kaction = true
+ local m = self.markers[6]
+ if m ~= -1 then
+ kcursor = m
+ end
+ elseif c == iup.K_7 then
+ kaction = true
+ local m = self.markers[7]
+ if m ~= -1 then
+ kcursor = m
+ end
+ elseif c == iup.K_8 then
+ kaction = true
+ local m = self.markers[8]
+ if m ~= -1 then
+ kcursor = m
+ end
+ elseif c == iup.K_9 then
+ kaction = true
+ local m = self.markers[9]
+ if m ~= -1 then
+ kcursor = m
+ end
+ elseif c == iup.K_0 then
+ kaction = true
+ local m = self.markers[10]
+ if m ~= -1 then
+ kcursor = m
+ end
+ elseif c == iup.K_m1 then
+ kaction = true
+ self.markers[1] = kcursor
+ elseif c == iup.K_m2 then
+ kaction = true
+ self.markers[2] = kcursor
+ elseif c == iup.K_m3 then
+ kaction = true
+ self.markers[3] = kcursor
+ elseif c == iup.K_m4 then
+ kaction = true
+ self.markers[4] = kcursor
+ elseif c == iup.K_m5 then
+ kaction = true
+ self.markers[5] = kcursor
+ elseif c == iup.K_m6 then
+ kaction = true
+ self.markers[6] = kcursor
+ elseif c == iup.K_m7 then
+ kaction = true
+ self.markers[7] = kcursor
+ elseif c == iup.K_m8 then
+ kaction = true
+ self.markers[8] = kcursor
+ elseif c == iup.K_m9 then
+ kaction = true
+ self.markers[9] = kcursor
+ elseif c == iup.K_m0 then
+ kaction = true
+ self.markers[10] = kcursor
+ elseif c == iup.K_SP then
+ kaction = true
+ end
+ if kaction then
+ while kcursor < filecursor do filecursor = filecursor - columns end
+ while (kcursor - filecursor) >= nbbytes do filecursor = filecursor + columns end
+ filecursor = math.min(math.max(filecursor, 0), filesize)
+ self.kcursor = kcursor
+ self.filecursor = filecursor
+ self.columns = columns
+ self:setcursor()
+ return iup.IGNORE
+ end
+ if raction then
+ self.filecursor = filecursor
+ self:updatescrollbar()
+ self:updatecolumns(columns)
+ self:draw()
+ return iup.IGNORE
+ end
+ return iup.DEFAULT
+ end,
+
+ updatehandle = function (self, handle)
+ self.handle = handle
+ self.filesize = handle and handle:getsize() or 0
+ self.old_max_bytes = -1
+ self.old_filecursor = -1
+ self:updatescrollbar()
+ self:draw()
+ end,
+
+ map_cb = function (self)
+ iupep.dbuffer.map_cb(self)
+ local cvdb = self.cvdb
+ if not cvdb then return iup.DEFAULT end
+ cvdb:Font("Courier", cd.PLAIN, -self.gridsize.y)
+ -- self.rastersize = (self.gridsize.x * (self.columns * 4 + 14)) .. "x" -- will not allow the control to be shrinked.
+ -- self.gridsize.x = cvdb:GetFontDim() -- doesn't work as expected
+ end,
+
+ setcursor = function (self, markerid, value)
+ if markerid then
+ markerid = markerid + 0
+ if markerid >= 0 and markerid <= 10 then
+ self.markers[markerid] = value + 0
+ elseif markerid == -2 then
+ self.kcursor = value + 0
+ self:keypress_cb(iup.K_SP, 1)
+ end
+ end
+ for _, v in ipairs(self.cbs) do
+ v.cb(v.opaque, self)
+ end
+ self:updatescrollbar()
+ self:draw()
+ end,
+
+ registercb = function (self, cb, opaque)
+ table.insert(self.cbs, { cb = cb, opaque = opaque })
+ end,
+
+ wheel_cb = function (self, delta, x, y, status)
+ if delta > 0 then
+ for i = 1, delta do self:keypress_cb(iup.K_cPGUP) end
+ else
+ for i = 1, -delta do self:keypress_cb(iup.K_cPGDN) end
+ end
+ end,
+
+ scroll_cb = function (self, op, posx, posy)
+ if op == iup.SBUP then
+ self:keypress_cb(iup.K_mUP, 1)
+ elseif op == iup.SBDN then
+ self:keypress_cb(iup.K_mDOWN, 1)
+ elseif op == iup.SBPGUP then
+ self:keypress_cb(iup.K_mPGUP, 1)
+ elseif op == iup.SBPGDN then
+ self:keypress_cb(iup.K_mPGDN, 1)
+ else
+ local columns = self.columns + 0
+ local startoffset = self.filecursor % columns
+ self.filecursor = math.min(math.max(math.floor(self.posy) * columns + startoffset, 0), self.filesize)
+ self:draw()
+ end
+ return iup.DEFAULT
+ end,
+
+ motion_cb = function (self, x, y, status)
+ local r = self:resolvepos(x, y)
+ if r ~= -1 then self.mcursor = r end
+ self:setcursor()
+ return iup.DEFAULT
+ end,
+
+ resolvepos = function (self, x, y)
+ local line = math.floor(y / self.gridsize.y)
+ local column = math.floor(x / self.gridsize.x)
+ local filecursor = self.filecursor + 0
+ local columns = self.columns + 0
+
+ -- offset display
+ if column <= 7 then
+ return filecursor + columns * line
+ end
+
+ -- gap 1
+ if column <= 9 then return -1 end
+
+ -- hex display
+ if column <= (columns * 3 + 10) then
+ -- interhex gap
+ if (column - 10) % 3 == 2 then return -1 end
+ return math.floor((column - 10) / 3) + filecursor + columns * line
+ end
+
+ -- gap 2
+ if column <= (columns * 3 + 11) then return -1 end
+
+ -- ascii display
+ if column <= (columns * 4 + 11) then
+ return column - columns * 3 - 12 + filecursor + columns * line
+ end
+
+ return -1
+ end,
+
+ button_cb = function (self, button, pressed, x, y, status)
+ if pressed == 1 then return iup.DEFAULT end
+ if button == iup.BUTTON1 then
+ local newpos = self:resolvepos(x, y)
+ if newpos ~= -1 then
+ self.kcursor = newpos
+ self:setcursor()
+ return iup.IGNORE
+ end
+ elseif button == iup.BUTTON3 then
+ local newpos = self:resolvepos(x, y)
+ if newpos ~= -1 then
+ self.markers[0] = newpos
+ self:setcursor()
+ return iup.IGNORE
+ end
+ end
+ return iup.DEFAULT
+ end,
+
+ updategridsize = function (self, gridsize)
+ self.gridsize = gridsize or { x = 8, y = 14 }
+ self:resize_cb(self.width, self.height)
+ end,
+
+ updatecolumns = function (self, columns)
+ self.columns = columns or 16
+ self:resize_cb(self.width, self.height)
+ end,
+
+ create = function (tab)
+ local handle = tab.handle
+ local columns = tab.columns
+ local gridsize = tab.gridsize
+ tab.handle = nil
+ tab.columns = nil
+ tab.gridsize = nil
+ tab.cursor = "TEXT"
+ tab.expand = "Yes"
+ tab.shrink = "Yes"
+ tab.border = "No"
+ tab.minsize = "0x0"
+ tab.size = "0x0"
+ tab.scrollbar = "vertical"
+ local r = iup.canvas(tab)
+ r.action = iupep.dbuffer.action
+ r.draw = iupep.hexview.draw
+ r.resize_cb = iupep.hexview.resize_cb
+ r.keypress_cb = iupep.hexview.keypress_cb
+ r.button_cb = iupep.hexview.button_cb
+ r.map_cb = iupep.hexview.map_cb
+ r.unmap_cb = iupep.dbuffer.unmap_cb
+ r.scroll_cb = iupep.hexview.scroll_cb
+ r.motion_cb = iupep.hexview.motion_cb
+ r.wheel_cb = iupep.hexview.wheel_cb
+ r.printgrid = iupep.hexview.printgrid
+ r.colorgrid = iupep.hexview.colorgrid
+ r.updatehandle = iupep.hexview.updatehandle
+ r.updategridsize = iupep.hexview.updategridsize
+ r.updatecolumns = iupep.hexview.updatecolumns
+ r.updatescrollbar = iupep.hexview.updatescrollbar
+ r.resolvepos = iupep.hexview.resolvepos
+ r.setcursor = iupep.hexview.setcursor
+ r.registercb = iupep.hexview.registercb
+ r.byte2char = iupep.hexview.byte2char
+ r.cbs = {}
+ r.handle = handle
+ r.columns = columns or 16
+ r.filecursor = 0
+ r.oldfilecursor = -1
+ r.kcursor = 0
+ r.filesize = handle and handle:getsize() or 0
+ r.mcursor = -1
+ r.markers = {}
+ r.displaylines = -1
+ for i = 0, 10 do r.markers[i] = -1 end
+ r.gridsize = gridsize or { x = 8, y = 14 }
+ r.textcursor = { x = 0, y = 0 }
+ return r
+ end,
+}
+
+iupe.hexview = iupep.hexview.create
diff --git a/iupe-tview.lua b/iupe-tview.lua
new file mode 100644
index 0000000..4048b56
--- /dev/null
+++ b/iupe-tview.lua
@@ -0,0 +1,108 @@
+loadmodule "luaiup"
+
+if not iupe then iupe = {} end
+if not iupep then iupep = {} end
+
+iupep.tableview = {
+ build_branches_r = function (t, branch)
+ for k, v in pairs(t) do
+ local isstr, ks = pcall(function() return k .. "" end)
+ if type(v) == "table" and isstr then
+ local subbranch = { branchname = ks, userid = v }
+ iupep.tableview.build_branches_r(v, subbranch)
+ table.insert(branch, subbranch)
+ end
+ end
+ end,
+
+ updatetable = function (self, t, name)
+ if type(t) ~= "table" then error "You need a table to display something in the tableview." end
+
+ local ttreeview = self.ttreeview
+
+ ttreeview.DELNODE0 = "CHILDREN"
+
+ local branches = { branchname = name, userid = t }
+ iupep.tableview.build_branches_r(t, branches)
+ iup.TreeSetValue(ttreeview, branches)
+ ttreeview.value = 0
+ ttreeview:selection_cb(0, 1)
+ self.table = t
+ self.tablename = name
+ end,
+
+ selection_cb = function (self, id, status)
+ if status == 0 then return end
+ local val = iup.TreeGetUserId(self, id)
+ local attributes = self.attributes
+ attributes.numlin = #val
+ attributes.numlin_visible = #val
+ local l = 1
+ local isstr, ks, vs
+ for k, v in pairs(val) do
+ isstr, ks = pcall(function() return k .. "" end)
+ if not isstr then
+ ks = "<" .. type(k) .. ">"
+ end
+ attributes:setcell(l, 1, ks)
+ isstr, vs = pcall(function() return v .. "" end)
+ if type(v) == "function" then
+ vs = "--function(...) ... end"
+ elseif not isstr then
+ vs = "<" .. type(v) .. ">"
+ end
+ attributes:setcell(l, 2, vs)
+ l = l + 1
+ end
+ attributes.redraw = "all"
+ end,
+
+ map_cb = function (self)
+ iup.TreeSetValue(self, { branchname = "nil" })
+ end,
+
+ create = function (tab)
+ local ttreeview = iup.tree {}
+ local attributes = iup.matrix { readonly = "Yes", numcol = 2, numcol_visible = 2, resizematrix = "Yes", markmode = "Single" }
+ ttreeview.selection_cb = iupep.tableview.selection_cb
+ ttreeview.attributes = attributes
+ ttreeview.map_cb = iupep.tableview.map_cb
+ attributes:setcell(0, 1, "Name")
+ attributes:setcell(0, 2, "Value")
+ attributes.alignment1 = "ALEFT"
+ attributes.alignment2 = "ALEFT"
+
+ local refresh_btn = iup.button { title = "Refresh" }
+
+ local r = iup.frame {
+ iup.vbox {
+ iup.hbox {
+ iup.sbox {
+ ttreeview,
+ },
+ iup.frame {
+ attributes,
+ }
+ },
+ iup.hbox {
+ iup.fill {},
+ refresh_btn,
+ },
+ },
+ unpack(tab),
+ }
+
+ function refresh_btn:action()
+ r:updatetable(r.table, r.tablename)
+ end
+
+ r.ttreeview = ttreeview
+ r.updatetable = iupep.tableview.updatetable
+ r.table = {}
+ r.tablename = "nil"
+
+ return r
+ end,
+}
+
+iupe.tableview = iupep.tableview.create