User:Andrew Nikitin/HexView

From J Wiki
Jump to: navigation, search

Once in a while some people (including myself) feel a need to modify several bytes in some binary files. Traditionally, piece of software called binary editor is used to complete this task.

In most cases J itself can be used as binary editor. For example,

   D=.1!:1 <'temp\data.bin' NB. read data from file
   a. i. 0 1{ D             NB. inspect data
   D=.'BM' 0 1}D            NB. modify data
   D 1!:2 <'temp\data.bin'  NB. write data back to disk

However, sometimes the file either is too big to comfortably fit in memory or it is desirable to have better view of bytes.

Hexview.png Download script: hexedit.ijs

NB. Hex editor for string noun
«history»

require 'jzgrid jmf'

«hexview class»

cocurrent 'base'

«startup cover verbs»

hexview class

The functionality of an editor is implemented in hexview class. It consists of a form with a single grid control in it. Grid control displays contents of a desired noun. Download script: hexview class

coclass 'hexview'

Formatting verbs are used to format

a) address

b) data

c) top row of offsets

Formatting verbs together with menuitem IDs and captions are stored in VIEWFORMATS noun. VIEWFORMATS is used to build a menu and performa actual string transformations. Download script: hexview class

hexformat=:'0123456789abcdef' {~ ] #:~ 16 #~ [

VIEWFORMATS=:i.0 0
VIEWFORMATS=:VIEWFORMATS,'hex';'&Hex';(8&hexformat)`(2&hexformat)`(1&hexformat)
VIEWFORMATS=:VIEWFORMATS,'dec';'&Decimal';":`":`":

addr_format=:3 : '(FMT{VIEWFORMATS)@.2 y'
data_format=:3 : '(FMT{VIEWFORMATS)@.3 y'
col_format=: 3 : '(FMT{VIEWFORMATS)@.4 y'

Download script: hexview class

VIEWCPS=:i.0 0
VIEWCPS=:VIEWCPS, 'ascii';'&ASCII';16 16$'.' ((i.32),127+i.129)}2 u: a.
VIEWCPS=:VIEWCPS, 'iso88591';'&ISO8859-1'; '.' (,0 128+/i.32)} 2 u: a.

Form definition noun is split in two so that View menu can be constructed from VIEWFORMATS and VIEWCPS. Download script: hexview class

HEXVIEW_MENU=: 0 : 0
pc hexview;
menupop "Data";
menu file "&File" "Ctrl-O" "" "";
menu noun "&Noun" "Ctrl-N" "" "";
menusep;
menu cancel "&Exit" "" "" "";
menupopz;
menupop "Edit";
menu goto "&Go to..." "Ctrl-G" "" "";
menusep;
menu apply "&Apply changes" "" "" "";
menupopz;
menupop "View";
)
HEXVIEW_FORM=: 0 : 0
menupopz;
xywh 5 5 420 120;cc grid isigraph rightmove bottommove;
pas 5 5;pcenter;
rem form end;
)

(The width of grid control was determined by issuing wd 'qchildxywh grid;' after manually resizing form so that grid fits with a little extra room) Download script: hexview class

create=: 3 : 0
  wd HEXVIEW_MENU
  ([: wd 'menu ', >@(0&{), ' "' , >@(1&{) , '" "" "" "";'"_)"1 VIEWFORMATS
  wd 'menusep;'
  ([: wd 'menu ', >@(0&{), ' "' , >@(1&{) , '" "" "" "";'"_)"1 VIEWCPS
  wd HEXVIEW_FORM
  grid=:conew 'jzgrid'

WIDTH is number of bytes per row of display, Grid control displays 1+WIDTH columns, where last column is text representation of WIDTH bytes shown in this row. Download script: hexview class

  WIDTH=:16

DATA is character noun holding the bytes to display. This noun can be mapped to a file on disk to view files. Download script: hexview class

  DATA=:y

Table of views defines how data is displayed. It can be hex or decimal. FMT is index in the table of viewed. Another parameter affecting display is CP -- index in list of codepages to use in text representation of the data. Download script: hexview class

  FMT=:0
  CP=:0

In case DATA is a mapped to a file, the name of this file is stored in FILE. Download script: hexview class

  FILE=:''

Grid operates in virtual mode. This enables use of mapped nouns to view large files. Download script: hexview class

  CELLRANGE__grid=:1 0+<:WIDTH ([ , *@| + <.@%~) # DATA
  HDRTOP__grid=:<'Address'
  HDRCOL__grid=:<@(col_format)"0 i.WIDTH
  HDRCOL__grid=:HDRCOL__grid,<'Text'
  GRIDVIRTUALMODE__grid=:1
  CELLFONT__grid=:1
  CELLCOLORS__grid=:CELLCOLORS__grid,24$192 192 192
  wd 'set ',(>0{FMT{VIEWFORMATS),' 1'
  wd 'set ',(>0{CP{VIEWCPS),' 1'
  show__grid ''
  wd 'pshow;'
)

Destructor

When object is destroyed it first closes the form, unmaps mapped file, if any, and then destroys member grid. Download script: hexview class

destroy=:3 : 0
  wd 'pclose'
  closefile ''
  destroy__grid''
  codestroy ''
)

Form's close and cancel events simply destroy parent object, which also takes care of GUI. Download script: hexview class

hexview_close=: 3 : 0
destroy ''
)

Download script: hexview class

hexview_cancel_button=: destroy

Event processing

Download script: hexview class

grid_gridhandler=:3 : 0
  select. y
  case. 'get' do.
    NB. smoutput Cls__grid;Rws__grid
    i=.(WIDTH*Rws__grid) +/ }:Cls__grid
    t=.<@(data_format)@(a.&i.)"0 DATA{~(<:#DATA)<.i
    text=.(,>2{CP{VIEWCPS) <@:(7&u:)@:{"1 ~a.i.DATA{~(<:#DATA)<.i
    CELLCOLOR__grid=:(2 1{~i<#DATA),.0
    CELLEDIT__grid=:(i<#DATA),.0
    CELLDATA__grid=:t,.((<"1 i<#DATA) (8 u: #)&.> text)
    HDRROW__grid=:<@(addr_format)"0 Rws__grid*WIDTH
    HDRCOL__grid=:<@(col_format)"0 i.WIDTH
    HDRCOL__grid=:HDRCOL__grid,-.&'&'&.>1{CP{VIEWCPS
  end.
  1
)

Since grid control accepts data in utf8, 8&u: had to be issued before assigning formatted text to CELLDATA.

--- Download script: hexview class

closefile=:3 : 0
if. -.''-:FILE do.
  n=.'DATA_',(>coname''),'_'
  smoutput 'closing ',FILE,' as ',n
  unmap_jmf_ n
  FILE=:''
  wd 'pn *'
end.
)

hexview_file_button=: 3 : 0
  FILE=:wd 'mbopen "Select file" "" "" "All files (*.*)|*.*" ofn_filemustexist'
  JCHAR map_jmf_ ('DATA_',(>coname''),'_');FILE
  CELLRANGE__grid=:1 0+<:WIDTH ([ , *@| + <.@%~) # DATA
  wd 'pn *',FILE
)

Since items of View menu are generated from nouns, default driver provides processing events from these elements -- change of format or change of displayed codepage. Download script: hexview class

hexview_default=:3 : 0
 NB. smoutput syschild,' ',sysevent
 if. (<syschild) e. 0{"1 VIEWFORMATS do.
   i=.(<syschild) i.~ 0{"1 VIEWFORMATS
   FMT=:i
   ([: wd 'set ' , ] , ' 0'"_)&> 0{"1 VIEWFORMATS
   wd 'set ',(>0{i{VIEWFORMATS),' 1'
   show__grid''
 elseif. (<syschild) e. 0&{"1 VIEWCPS do.
   i=.(<syschild) i.~ 0&{"1 VIEWCPS
   CP=:i
   ([: wd 'set ' , ] , ' 0'"_)&> 0{"1 VIEWCPS
   wd 'set ',(>0{i{VIEWCPS),' 1'
   show__grid''
 end.
)

Cover verbs

Download script: startup cover verbs

newhexview=:3 : 0
  a=.a:
  a=.conew 'hexview'
  try.
    create__a y
  catchd.
    smoutput 13!:12 ''
    destroy__a ''
    a=.a:
  end.
  a
)
z=:newhexview a.

History

Download script: history

NB. 2007-10-10 12:51:11
NB. 2007-11-14 16:48:53

TODO and comments

  • allow updates; store list of addresses and modifications and apply in a

single step (or save delta to a file)

  • (?) noun browser
  • Goto address
  • Search
  • Copy/paste

CategoryLiterate CategoryWorkInProgress