summaryrefslogtreecommitdiff
path: root/iupe-hexview.lua
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 /iupe-hexview.lua
parentbb07454bba0c0ba4d9f1ca6dfc94011ce8b65af0 (diff)
First insert of the various lua files.
Diffstat (limited to 'iupe-hexview.lua')
-rw-r--r--iupe-hexview.lua552
1 files changed, 552 insertions, 0 deletions
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