class Kaitai::Struct::Visualizer::HexViewer

Constants

FMT
PAGE_ROWS
PER_GROUP
PER_LINE

Attributes

shift_x[RW]

Public Class Methods

line_width() click to toggle source
# File lib/kaitai/struct/visualizer/hex_viewer.rb, line 151
def self.line_width
  #8 + 2 + 3 * PER_LINE + 2 + PER_LINE
  12 + 4 * PER_LINE
end
new(ui, buf, tree = nil) click to toggle source
# File lib/kaitai/struct/visualizer/hex_viewer.rb, line 7
def initialize(ui, buf, tree = nil)
  @ui = ui
  @buf = buf
  @shift_x = 0
  @tree = tree

  @embedded = not(tree.nil?)
  @max_scr_ln = @ui.rows - 3

  @addr = 0
  @scroll_y = 0
  reset_cur
  raise if @cur_x.nil?
end

Public Instance Methods

addr() click to toggle source
# File lib/kaitai/struct/visualizer/hex_viewer.rb, line 26
def addr; @addr; end
addr=(a) click to toggle source
# File lib/kaitai/struct/visualizer/hex_viewer.rb, line 27
def addr=(a)
  @addr = a
  reset_cur
end
addr_to_col(addr) click to toggle source
# File lib/kaitai/struct/visualizer/hex_viewer.rb, line 287
def addr_to_col(addr)
  addr % PER_LINE
end
addr_to_row(addr) click to toggle source
# File lib/kaitai/struct/visualizer/hex_viewer.rb, line 283
def addr_to_row(addr)
  addr / PER_LINE
end
buf=(buf) click to toggle source
# File lib/kaitai/struct/visualizer/hex_viewer.rb, line 22
def buf=(buf)
  @buf = buf
end
byte_at(i) click to toggle source
# File lib/kaitai/struct/visualizer/hex_viewer.rb, line 266
def byte_at(i)
  v = @buf[i]
  if v.nil?
    nil
  else
    v.ord
  end
end
byte_to_display_char(x) click to toggle source
# File lib/kaitai/struct/visualizer/hex_viewer.rb, line 275
def byte_to_display_char(x)
  if x < 0x20 or x >= 0x7f
    '.'
  else
    x.chr
  end
end
clamp_cursor() click to toggle source
# File lib/kaitai/struct/visualizer/hex_viewer.rb, line 135
def clamp_cursor
  if @addr < 0
    @addr = 0
    @cur_x = 0
    @cur_y = 0
  elsif @addr >= @buf.size
    @addr = @buf.size - 1
    reset_cur
  end
end
col_to_col_char(c) click to toggle source
# File lib/kaitai/struct/visualizer/hex_viewer.rb, line 161
def col_to_col_char(c)
  #8 + 2 + 3 * PER_LINE + 2
  @shift_x + 12 + 3 * PER_LINE + c
end
col_to_col_hex(c) click to toggle source
# File lib/kaitai/struct/visualizer/hex_viewer.rb, line 156
def col_to_col_hex(c)
  #8 + 2 + 3 * c
  @shift_x + 10 + 3 * c
end
each_highlight_region() { |i, p1, p2| ... } click to toggle source
# File lib/kaitai/struct/visualizer/hex_viewer.rb, line 189
def each_highlight_region
  return if @hl_regions.nil?
  n = @hl_regions.size
  (n - 1).downto(0).each { |i|
    p1 = @hl_regions[i][0]
    p2 = @hl_regions[i][1]
    yield i, p1, p2 unless p1.nil?
  }
end
ensure_visible() click to toggle source
# File lib/kaitai/struct/visualizer/hex_viewer.rb, line 43
def ensure_visible
  scr_y = row_to_scr(@cur_y)
  if scr_y < 0
    @scroll_y = @cur_y
    redraw
    highlight_show
  elsif scr_y > @max_scr_ln
    @scroll_y = @cur_y - @max_scr_ln
    redraw
    highlight_show
  end
end
highlight(regions) click to toggle source
# File lib/kaitai/struct/visualizer/hex_viewer.rb, line 37
def highlight(regions)
  highlight_hide
  @hl_regions = regions
  highlight_show
end
highlight_draw(p1, p2) click to toggle source
# File lib/kaitai/struct/visualizer/hex_viewer.rb, line 214
def highlight_draw(p1, p2)
  r = row_to_scr(addr_to_row(p1))
  return if r > @max_scr_ln
  if r < 0
    c = 0
    r = 0
    i = row_col_to_addr(@scroll_y, 0)
    return if i >= p2
  else
    c = addr_to_col(p1)
    i = p1
  end

  highlight_draw_hex(r, c, i, p2)
  highlight_draw_char(r, c, i, p2)
end
highlight_draw_char(r, c, i, p2) click to toggle source
# File lib/kaitai/struct/visualizer/hex_viewer.rb, line 248
def highlight_draw_char(r, c, i, p2)
  @ui.goto(col_to_col_char(c), r)

  while i < p2
    v = byte_at(i)
    return if v.nil?
    print byte_to_display_char(v)
    c += 1
    if c >= PER_LINE
      c = 0
      r += 1
      return if r > @max_scr_ln
      @ui.goto(col_to_col_char(c), r)
    end
    i += 1
  end
end
highlight_draw_hex(r, c, i, p2) click to toggle source
# File lib/kaitai/struct/visualizer/hex_viewer.rb, line 231
def highlight_draw_hex(r, c, i, p2)
  @ui.goto(col_to_col_hex(c), r)
  while i < p2
    v = byte_at(i)
    return if v.nil?
    printf('%02x ', v)
    c += 1
    if c >= PER_LINE
      c = 0
      r += 1
      return if r > @max_scr_ln
      @ui.goto(col_to_col_hex(c), r)
    end
    i += 1
  end
end
highlight_hide() click to toggle source
# File lib/kaitai/struct/visualizer/hex_viewer.rb, line 199
def highlight_hide
  each_highlight_region { |i, p1, p2|
    highlight_draw(p1, p2)
  }
end
highlight_show() click to toggle source
# File lib/kaitai/struct/visualizer/hex_viewer.rb, line 205
def highlight_show
  each_highlight_region { |i, p1, p2|
    @ui.bg_color = @ui.highlight_colors[i]
    @ui.fg_color = :black
    highlight_draw(p1, p2)
  }
  @ui.reset_colors
end
redraw() click to toggle source
# File lib/kaitai/struct/visualizer/hex_viewer.rb, line 170
def redraw
  i = row_col_to_addr(@scroll_y, 0)
  row = 0

  while row <= @max_scr_ln do
    line = @buf[i, PER_LINE]
    return unless line

    @ui.goto(@shift_x, row)

    hex = line.bytes.map { |x| sprintf('%02x', x) }.join(' ')
    char = line.bytes.map { |x| byte_to_display_char(x) }.join

    printf FMT, i, hex, char
    i += PER_LINE
    row += 1
  end
end
reset_cur() click to toggle source
# File lib/kaitai/struct/visualizer/hex_viewer.rb, line 32
def reset_cur
  @cur_y = addr_to_row(@addr)
  @cur_x = addr_to_col(@addr)
end
row_col_to_addr(row, col) click to toggle source
# File lib/kaitai/struct/visualizer/hex_viewer.rb, line 291
def row_col_to_addr(row, col)
  row * PER_LINE + col
end
row_to_scr(r) click to toggle source
# File lib/kaitai/struct/visualizer/hex_viewer.rb, line 166
def row_to_scr(r)
  r - @scroll_y
end
run() click to toggle source
# File lib/kaitai/struct/visualizer/hex_viewer.rb, line 56
def run
  c = nil
  loop {
    @ui.goto(0, @max_scr_ln + 1)
    printf "%08x (%d, %d)", @addr, @cur_x, @cur_y

    @ui.goto(col_to_col_char(@cur_x), row_to_scr(@cur_y))
    c = @ui.read_char_mapped
    case c
    when :tab
      return if @embedded
    when :left_arrow
      if @addr > 0
        @addr -= 1
        @cur_x -= 1
        if @cur_x < 0
          @cur_y -= 1
          @cur_x = PER_LINE - 1
        end
      end
    when :right_arrow
      if @addr < @buf.size
        @addr += 1
        @cur_x += 1
        if @cur_x >= PER_LINE
          @cur_y += 1
          @cur_x = 0
        end
      end
    when :up_arrow
      @addr -= PER_LINE
      @cur_y -= 1
      clamp_cursor
    when :down_arrow
      @addr += PER_LINE
      @cur_y += 1
      clamp_cursor
    when :pg_dn
      @addr += PER_LINE * PAGE_ROWS
      @cur_y += PAGE_ROWS
      clamp_cursor
    when :pg_up
      @addr -= PER_LINE * PAGE_ROWS
      @cur_y -= PAGE_ROWS
      clamp_cursor
    when :home
      if @cur_x == 0
        @addr = 0
        @cur_y = 0
      else
        @addr -= @cur_x
        @cur_x = 0
      end
      clamp_cursor
    when :end
      if @cur_x == PER_LINE - 1
        @addr = @buf.size - 1
        reset_cur
      else
        @addr = @addr - @cur_x + PER_LINE - 1
        @cur_x = PER_LINE - 1
      end
      clamp_cursor
    when 'w'
      fn = @ui.input_str('Write buffer to file', 'Filename')
      File.open(fn, 'w') { |out|
        out.write(@buf)
      }
      @ui.clear
      redraw
    when 'q'
      @tree.do_exit if @tree
      return
    end

    ensure_visible
  }
end