diff options
Diffstat (limited to 'Demo/cwilib/vt100.py')
-rwxr-xr-x | Demo/cwilib/vt100.py | 328 |
1 files changed, 0 insertions, 328 deletions
diff --git a/Demo/cwilib/vt100.py b/Demo/cwilib/vt100.py deleted file mode 100755 index 9edd4810b9..0000000000 --- a/Demo/cwilib/vt100.py +++ /dev/null @@ -1,328 +0,0 @@ -# VT100 terminal emulator. -# This is incomplete and slow, but will do for now... -# It shouldn't be difficult to extend it to be a more-or-less complete -# VT100 emulator. And little bit of profiling could go a long way... - -from array import array -import regex -import string - -# Tunable parameters -DEBUGLEVEL = 1 - -# Symbolic constants -ESC = '\033' - - -# VT100 emulation class - -class VT100: - - def __init__(self): - self.debuglevel = DEBUGLEVEL - # Unchangeable parameters (for now) - self.width = 80 - self.height = 24 - self.blankline = array('c', ' '*self.width) - self.blankattr = array('b', '\0'*self.width) - # Set mutable display state - self.reset() - # Set parser state - self.unfinished = '' - # Set screen recognition state - self.reset_recognizer() - - def msg(self, msg, *args): - if self.debuglevel > 0: - print 'VT100:', msg%args - - def set_debuglevel(self, debuglevel): - self.debuglevel = debuglevel - - def reset(self): - self.lines = [] - self.attrs = [] - self.fill_bottom() - self.x = 0 - self.y = 0 - self.curattrs = [] - - def show(self): - lineno = 0 - for line in self.lines: - lineno = lineno + 1 - i = len(line) - while i > 0 and line[i-1] == ' ': i = i-1 - print line[:i] - print 'CURSOR:', self.x, self.y - - def fill_bottom(self): - while len(self.lines) < self.height: - self.lines.append(self.blankline[:]) - self.attrs.append(self.blankattr[:]) - - def fill_top(self): - while len(self.lines) < self.height: - self.lines.insert(0, self.blankline[:]) - self.attrs.insert(0, self.blankattr[:]) - - def clear_all(self): - self.lines = [] - self.attrs = [] - self.fill_bottom() - - def clear_below(self): - del self.lines[self.y:] - del self.attrs[self.y:] - self.fill_bottom() - - def clear_above(self): - del self.lines[:self.y] - del self.attrs[:self.y] - self.fill_top() - - def send(self, buffer): - self.msg('send: unfinished=%s, buffer=%s', - `self.unfinished`, `buffer`) - self.unfinished = self.unfinished + buffer - i = 0 - n = len(self.unfinished) - while i < n: - c = self.unfinished[i] - i = i+1 - if c != ESC: - self.add_char(c) - continue - if i >= n: - i = i-1 - break - c = self.unfinished[i] - i = i+1 - if c == 'c': - self.reset() - continue - if c <> '[': - self.msg('unrecognized: ESC %s', `c`) - continue - argstr = '' - while i < n: - c = self.unfinished[i] - i = i+1 - if c not in '0123456789;': - break - argstr = argstr + c - else: - i = i - len(argstr) - 2 - break -## self.msg('found ESC [ %s %s' % (`argstr`, `c`)) - args = string.splitfields(argstr, ';') - for j in range(len(args)): - s = args[j] - while s[:1] == '0': s = s[1:] - if s: args[j] = eval(s) - else: args[j] = 0 - p1 = p2 = 0 - if args: p1 = args[0] - if args[1:]: p2 = args[1] - if c in '@ABCDH': - if not p1: p1 = 1 - if c in 'H': - if not p2: p2 = 1 - if c == '@': - for j in range(p1): - self.add_char(' ') - elif c == 'A': - self.move_by(0, -p1) - elif c == 'B': - self.move_by(0, p1) - elif c == 'C': - self.move_by(p1, 0) - elif c == 'D': - self.move_by(-p1, 0) - elif c == 'H': - self.move_to(p2-1, p1-1) - elif c == 'J': - if p1 == 0: self.clear_above() - elif p1 == 1: self.clear_below() - elif p1 == 2: self.clear_all() - else: self.msg('weird ESC [ %d J', p1) - elif c == 'K': - if p1 == 0: self.erase_right() - elif p1 == 1: self.erase_left() - elif p1 == 2: self.erase_line() - else: self.msg('weird ESC [ %d K', p1) - elif c == 'm': - if p1 == 0: - self.curattrs = [] - else: - if p1 not in self.curattrs: - self.curattrs.append(p1) - self.curattrs.sort() - else: - self.msg('unrecognized: ESC [ %s', `argstr+c`) - self.unfinished = self.unfinished[i:] - - def add_char(self, c): - if c == '\r': - self.move_to(0, self.y) - return - if c in '\n\f\v': - self.move_to(self.x, self.y + 1) - if self.y >= self.height: - self.scroll_up(1) - self.move_to(self.x, self.height - 1) - return - if c == '\b': - self.move_by(-1, 0) - return - if c == '\a': - self.msg('BELL') - return - if c == '\t': - self.move_to((self.x+8)/8*8, self.y) - return - if c == '\0': - return - if c < ' ' or c > '~': - self.msg('ignored control char: %s', `c`) - return - if self.x >= self.width: - self.move_to(0, self.y + 1) - if self.y >= self.height: - self.scroll_up(1) - self.move_to(self.x, self.height - 1) - self.lines[self.y][self.x] = c - if self.curattrs: - self.attrs[self.y][self.x] = max(self.curattrs) - else: - self.attrs[self.y][self.x] = 0 - self.move_by(1, 0) - - def move_to(self, x, y): - self.x = min(max(0, x), self.width) - self.y = min(max(0, y), self.height) - - def move_by(self, dx, dy): - self.move_to(self.x + dx, self.y + dy) - - def scroll_up(self, nlines): - del self.lines[:max(0, nlines)] - del self.attrs[:max(0, nlines)] - self.fill_bottom() - - def scroll_down(self, nlines): - del self.lines[-max(0, nlines):] - del self.attrs[-max(0, nlines):] - self.fill_top() - - def erase_left(self): - x = min(self.width-1, x) - y = min(self.height-1, y) - self.lines[y][:x] = self.blankline[:x] - self.attrs[y][:x] = self.blankattr[:x] - - def erase_right(self): - x = min(self.width-1, x) - y = min(self.height-1, y) - self.lines[y][x:] = self.blankline[x:] - self.attrs[y][x:] = self.blankattr[x:] - - def erase_line(self): - self.lines[y][:] = self.blankline - self.attrs[y][:] = self.blankattr - - # The following routines help automating the recognition of - # standard screens. A standard screen is characterized by - # a number of fields. A field is part of a line, - # characterized by a (lineno, begin, end) tuple; - # e.g. the first 10 characters of the second line are - # specified by the tuple (1, 0, 10). Fields can be: - # - regex: desired contents given by a regular expression, - # - extract: can be extracted, - # - cursor: screen is only valid if cursor in field, - # - copy: identical to another screen (position is ignored). - # A screen is defined as a dictionary full of fields. Screens - # also have names and are placed in a dictionary. - - def reset_recognizer(self): - self.screens = {} - - def define_screen(self, screenname, fields): - fieldscopy = {} - # Check if the fields make sense - for fieldname in fields.keys(): - field = fields[fieldname] - ftype, lineno, begin, end, extra = field - if ftype in ('match', 'search'): - extra = regex.compile(extra) - elif ftype == 'extract': - extra = None - elif ftype == 'cursor': - extra = None - elif ftype == 'copy': - if not self.screens.has_key(extra): - raise ValueError, 'bad copy ref' - else: - raise ValueError, 'bad ftype: %s' % `ftype` - fieldscopy[fieldname] = ( - ftype, lineno, begin, end, extra) - self.screens[screenname] = fieldscopy - - def which_screens(self): - self.busy = [] - self.okay = [] - self.fail = [] - for name in self.screens.keys(): - ok = self.match_screen(name) - return self.okay[:] - - def match_screen(self, name): - if name in self.busy: raise RuntimeError, 'recursive match' - if name in self.okay: return 1 - if name in self.fail: return 0 - self.busy.append(name) - fields = self.screens[name] - ok = 0 - for key in fields.keys(): - field = fields[key] - ftype, lineno, begin, end, extra = field - if ftype == 'copy': - if not self.match_screen(extra): break - elif ftype == 'search': - text = self.lines[lineno][begin:end].tostring() - if extra.search(text) < 0: - break - elif ftype == 'match': - text = self.lines[lineno][begin:end].tostring() - if extra.match(text) < 0: - break - elif ftype == 'cursor': - if self.x != lineno or not \ - begin <= self.y < end: - break - else: - ok = 1 - if ok: - self.okay.append(name) - else: - self.fail.append(name) - self.busy.remove(name) - return ok - - def extract_field(self, screenname, fieldname): - ftype, lineno, begin, end, extra = \ - self.screens[screenname][fieldname] - return stripright(self.lines[lineno][begin:end].tostring()) - - def extract_rect(self, left, top, right, bottom): - lines = [] - for i in range(top, bottom): - lines.append(stripright(self.lines[i][left:right]) - .tostring()) - return lines - - -def stripright(line): - i = len(line) - while i > 0 and line[i-1] in string.whitespace: i = i-1 - return line[:i] |