pmacs3/mode/hex.py

253 lines
10 KiB
Python

import string, struct
import color, mode
from lex import Grammar, PatternRule, RegionRule
from method import Method, Argument
from point import Point
class Hex(mode.Fundamental):
modename = 'Hex'
lmargin = 12
rmargin = 18
_ctrans = ['.'] * 256
cgreen = color.build('green', 'default', 'bold')
ccyan = color.build('cyan', 'default', 'bold')
ccursor = color.build('default', 'default', 'bold', 'reverse')
for c in string.letters + string.digits + string.punctuation + ' ':
_ctrans[ord(c)] = c
ctrans = ''.join(_ctrans)
def __init__(self, w):
mode.Fundamental.__init__(self, w)
self.bindings = {}
self.add_bindings('center-view', ('C-l',))
self.add_bindings('next-line', ('C-n', 'D_ARROW',))
self.add_bindings('previous-line', ('C-p', 'U_ARROW',))
self.add_bindings('next-section', ('M-n', 'M-D_ARROW',))
self.add_bindings('previous-section', ('M-p', 'M-U_ARROW',))
self.add_bindings('page-down', ('C-v', 'PG_DN',))
self.add_bindings('page-up', ('M-v', 'PG_UP',))
self.add_bindings('goto-beginning', ('M-<',))
self.add_bindings('goto-end', ('M->',))
self.add_bindings('right-word', ('M-f',))
self.add_bindings('left-word', ('M-b',))
self.add_bindings('set-mark', ('C-@',))
self.add_bindings('switch-buffer', ('C-x b',))
self.add_bindings('switch-mark', ('C-x C-x',))
self.add_bindings('undo', ('C-/', 'C-x u',))
self.add_bindings('redo', ('M-/', 'M-_', 'C-x r',))
self.add_bindings('goto-line', ('M-g',))
self.add_bindings('forward-chars', ('C-x M-c',))
self.add_bindings('forward-lines', ('C-x M-n',))
self.add_bindings('search', ('C-s',))
self.add_bindings('reverse-search', ('C-r',))
self.add_bindings('regex-search', ('M-C-s',))
self.add_bindings('regex-reverse-search', ('M-C-r',))
self.add_bindings('toggle-margins', ('M-m',))
self.add_bindings('open-file', ('C-x C-f',))
self.add_bindings('kill-buffer', ('C-x k',))
self.add_bindings('list-buffers', ('C-x C-b',))
self.add_bindings('meta-x', ('M-x',))
self.add_bindings('save-buffer', ('C-x C-s',))
self.add_bindings('save-buffer-as', ('C-x C-w',))
self.add_bindings('exit', ('C-x C-c',))
self.add_bindings('split-window', ('C-x s', 'C-x 2',))
self.add_bindings('unsplit-window', ('C-u s', 'C-x 1',))
self.add_bindings('toggle-window', ('C-x o',))
self.add_bindings('open-console', ('M-e',))
self.add_bindings('show-bindings-buffer', ('C-c M-h',))
self.add_bindings('show-functions-buffer', ('C-c M-?',))
self.add_bindings('which-command', ('M-h',))
self.add_bindings('cmd-help-buffer', ('M-?',))
self.add_bindings('set-mode', ('C-x m',))
self.add_bindings('cancel', ('C-]',))
self.add_bindings('exec', ('C-c e', 'C-c !'))
self.add_bindings('grep', ('C-c g',))
self.add_bindings('pipe', ('C-c p', 'C-c |'))
self.add_bindings('view-buffer-parent', ('C-c .',))
self.add_bindings('get-token', ('C-c t',))
self.add_action_and_bindings(HexForward(), ('C-f', 'R_ARROW',))
self.add_action_and_bindings(HexBackward(), ('C-b', 'L_ARROW',))
self.add_action_and_bindings(HexForwardWord(), ('M-f', 'M-R_ARROW',))
self.add_action_and_bindings(HexBackwardWord(), ('M-b', 'M-L_ARROW',))
self.add_action_and_bindings(HexStartOfLine(), ('C-a', 'HOME',))
self.add_action_and_bindings(HexEndOfLine(), ('C-e', 'END',))
self.add_action_and_bindings(HexRead('int', 'i'), ('C-u i',))
self.add_action_and_bindings(HexRead('uint', 'I'), ('C-u I',))
self.add_action_and_bindings(HexRead('long', 'l'), ('C-u l',))
self.add_action_and_bindings(HexRead('ulong', 'L'), ('C-u L',))
self.add_action_and_bindings(HexRead('float', 'f'), ('C-u f',))
self.add_action_and_bindings(HexRead('double', 'd'), ('C-u d',))
self.add_action_and_bindings(HexReadAligned('int', 'i'), ('C-c i',))
self.add_action_and_bindings(HexReadAligned('uint', 'I'), ('C-c I',))
self.add_action_and_bindings(HexReadAligned('long', 'l'), ('C-c l',))
self.add_action_and_bindings(HexReadAligned('ulong', 'L'), ('C-c L',))
self.add_action_and_bindings(HexReadAligned('float', 'f'), ('C-c f',))
self.add_action_and_bindings(HexReadAligned('double', 'd'), ('C-c d',))
self.add_action_and_bindings(ShowAddress(), ('C-c a',))
self.add_action_and_bindings(GotoAddress(), ('C-c M-g',))
# create all the insert actions for the basic text input
for c in string.letters + string.digits + string.punctuation:
if c in string.hexdigits:
self.add_action_and_bindings(HexOverwriteChar(c), (c,))
def get_address(self, y, x):
return (y * 16) + x
def get_lmargin(self, y, x=0, ended=False, cont=False):
lm = self.lmargin
if ended:
s = ' -------- '
else:
addr = self.get_address(y, x)
s = '0x%08x ' % addr
return ((0, s, self.ccyan),)
def get_rmargin(self, y, x=0, ended=False, cont=False):
if ended:
return ((0, '', 0),)
else:
(cx, cy) = self.window.cursor.xy()
s = string.translate(self.window.buffer.rawdata[y], self.ctrans)
if cy == y:
i = self.window.buffer.cursorx_to_datax(cy, cx)
if i is None:
rmargins = ((0, s, self.cgreen),)
elif i < len(s):
rmargins = ((0, s[0:i], self.cgreen),
(i, s[i], self.ccursor),
(i + 1, s[i+1:], self.cgreen))
else:
rmargins= ((0, s[0:i], self.cgreen),
(i, s[i], self.cgreen),)
return rmargins
else:
return ((0, s, self.cgreen),)
def read_data(self, cy, ix, fmt, size):
b = self.window.buffer
s = b.rawdata[cy][ix:]
if len(s) < size:
if cy < len(b.rawdata) - 1:
s += b.rawdata[cy + 1]
else:
return None
s = s[:size]
return struct.unpack(fmt, s)[0]
class HexForward(Method):
def _execute(self, w, **vargs):
w.forward()
end = w.buffer.get_buffer_end()
while w.cursor_char().isspace() and w.cursor < end:
w.forward()
class HexBackward(Method):
def _execute(self, w, **vargs):
w.backward()
start = w.buffer.get_buffer_start()
while w.cursor_char().isspace() and w.cursor > start:
w.backward()
class HexForwardWord(Method):
def _execute(self, w, **vargs):
hf = w.application.methods['hex-forward']
for i in range(0, w.buffer.wordsize * 2):
hf.execute(w, **vargs)
class HexBackwardWord(Method):
def _execute(self, w, **vargs):
hb = w.application.methods['hex-backward']
for i in range(0, w.buffer.wordsize * 2):
hb.execute(w, **vargs)
class HexStartOfLine(Method):
'''Move the cursor to the start of the current hex line'''
def _execute(self, w, **vargs):
w.start_of_line()
class HexEndOfLine(Method):
'''Move the cursor to the end of the current hex line'''
def _execute(self, w, **vargs):
w.end_of_line()
if w.cursor_char() == '\n':
w.backward()
class HexRead(Method):
_is_method = False
def __init__(self, type_, fmt):
self.name = 'hex-read-%s' % type_.lower()
self.type_ = type_
self.fmt = fmt
self.size = struct.calcsize(fmt)
self.args = []
self.help = "Read %r from address in the current buffer." % self.type_
def _get_ix(self, b, cy, cx):
ix = b.cursorx_to_datax(cy, cx)
return ix
def _execute(self, w, **vargs):
b = w.buffer
hb = w.application.methods['hex-backward']
(cx, cy) = w.cursor.xy()
ix = self._get_ix(b, cy, cx)
addr = b.get_address(cy, 0) + ix
try:
v = w.mode.read_data(cy, ix, self.fmt, self.size)
if v is None:
w.set_error("not enough data to read %s" % self.type_)
else:
w.set_error("%s at 0x%08x: %r" % (self.type_, addr, v))
except Exception, e:
w.set_error("%s could not be read at 0x%08x" % (self.type_, addr))
class HexReadAligned(HexRead):
_is_method = False
def __init__(self, type_, fmt):
self.name = 'hex-read-aligned-%s' % type_.lower()
self.type_ = type_
self.fmt = fmt
self.size = struct.calcsize(fmt)
self.args = []
self.help = "Read %r from word-aligned address in the current buffer." % self.type_
def _get_ix(self, b, cy, cx):
ix = b.cursorx_to_datax(cy, cx)
ix -= ix % b.wordsize
return ix
class HexOverwriteChar(Method):
_is_method = False
def __init__(self, c):
self.name = 'hex-overwrite-char-%s' % c
self.args = []
self.help = "Overwrite %r into the current hex buffer." % c
self.char = c
def _execute(self, w, **vargs):
w.overwrite_char_at_cursor(self.char)
end = w.buffer.get_buffer_end()
while w.cursor_char().isspace() and w.cursor < end:
w.forward()
class GotoAddress(Method):
'''Jump to the specified line number'''
args = [Argument("address", type=type(0), prompt="Goto address: ")]
def _execute(self, w, **vargs):
b = w.buffer
addr = vargs["address"]
if addr < 0:
w.set_error("Negative address not supported.")
ix = addr % (b.groupsize * b.numgroups)
cx = w.buffer.datax_to_cursorx(ix)
cy = addr // (b.groupsize * b.numgroups)
w.goto(Point(cx, cy))
w.set_error("Goto 0x%08x (%r, %r)" % (addr, cx, cy))
class ShowAddress(Method):
'''Show the cursor's address in the current buffer'''
def _execute(self, w, **vargs):
(cx, cy) = w.cursor.xy()
ix = w.buffer.cursorx_to_datax(cy, cx)
addr = w.buffer.get_address(cy, ix)
w.set_error("Cursor's address is 0x%08x" % addr)
install = Hex.install