From 9e3a36537d07700ec49f432940b95cf2ee9689e8 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 14 Dec 2009 08:13:06 -0800 Subject: First insert of the various lua files. --- dalos.lua | 160 ++++++++++++++ ips-patcher.lua | 48 +++++ iupe-dbuffer.lua | 43 ++++ iupe-hexview-toolbox.lua | 272 +++++++++++++++++++++++ iupe-hexview.lua | 552 +++++++++++++++++++++++++++++++++++++++++++++++ iupe-tview.lua | 108 ++++++++++ 6 files changed, 1183 insertions(+) create mode 100644 dalos.lua create mode 100644 ips-patcher.lua create mode 100644 iupe-dbuffer.lua create mode 100644 iupe-hexview-toolbox.lua create mode 100644 iupe-hexview.lua create mode 100644 iupe-tview.lua 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 -- cgit v1.2.3