from ctypes import * import vt100_raw class vt100_rgb_color(Structure): _fields_ = [ ("_r", c_ubyte), ("_g", c_ubyte), ("_b", c_ubyte), ] class vt100_color_type(Union): _anonymous_ = ("_rgb",) _fields_ = [ ("_rgb", vt100_rgb_color), ("_idx", c_ubyte), ] class vt100_color(Structure): _anonymous_ = ("_color",) _fields_ = [ ("_color", vt100_color_type), ("_type", c_ubyte), ] def type(self): if self._type == 0: return "default" elif self._type == 1: return "indexed" elif self._type == 2: return "rgb" else: raise Exception("unknown color type: %d" % self._type) def color(self): color_type = self.type() if color_type == "default": return None elif color_type == "indexed": return self._idx elif color_type == "rgb": return (self._r, self._g, self._b) else: raise Exception("unknown color type: %s" % color_type) class vt100_named_attrs(Structure): _fields_ = [ ("_bold", c_ubyte, 1), ("_italic", c_ubyte, 1), ("_underline", c_ubyte, 1), ("_inverse", c_ubyte, 1), ] class vt100_attrs(Union): _anonymous_ = ("_named",) _fields_ = [ ("_named", vt100_named_attrs), ("_attrs", c_ubyte), ] class vt100_cell_attrs(Structure): _anonymous_ = ("_cell_attrs",) _fields_ = [ ("_fgcolor", vt100_color), ("_bgcolor", vt100_color), ("_cell_attrs", vt100_attrs), ] class vt100_cell(Structure): _fields_ = [ ("_contents", c_char * 8), ("_len", c_size_t), ("_attrs", vt100_cell_attrs), ("_is_wide", c_ubyte, 1), ] def contents(self): return self._contents[:self._len].decode('utf-8') def fgcolor(self): return self._attrs._fgcolor def bgcolor(self): return self._attrs._bgcolor def all_attrs(self): return self._attrs._attrs def bold(self): return self._attrs._bold != 0 def italic(self): return self._attrs._italic != 0 def underline(self): return self._attrs._underline != 0 def inverse(self): return self._attrs._inverse != 0 def is_wide(self): return self._is_wide # XXX process/cell need mutexes class vt100(object): def __init__(self, rows, cols): self.vt = vt100_raw.new(rows, cols) def __del__(self): vt100_raw.delete(self.vt) def set_window_size(self, rows, cols): vt100_raw.set_window_size(self.vt, rows, cols) def process(self, string): return vt100_raw.process_string(self.vt, string) def get_string_formatted(self, row_start, col_start, row_end, col_end): return vt100_raw.get_string_formatted( self.vt, row_start, col_start, row_end, col_end ) def get_string_plaintext(self, row_start, col_start, row_end, col_end): return vt100_raw.get_string_plaintext( self.vt, row_start, col_start, row_end, col_end ) def cell(self, x, y): return vt100_cell.from_address(vt100_raw.cell_at(self.vt, x, y))