def ascii_to_zscii(string): result = [] i = 0 while i < len(string): c = string[i] if c == '\n': result.append(ord('\r')) # NOTE: gargoyle just ignores the tab key, S 3.8.2.3 says # output only. But since I want to keep expected tab behavior, # I make this compromise. elif c == '\t': result.append(ord(' ')) elif c in ('\r', '\b') or (len(c) == 1 and ord(c) > 31 and ord(c) < 127): result.append(ord(c)) # TODO (?): unicode for input (translate codes to zscii using the unicode table(s)) # TODO: keypad digits elif c == '\x1b': esc_key_tbl = { # arrow keys '[A': 129, '[B': 130, '[C': 132, '[D': 131, # fkeys 'OP': 133, 'OQ': 134, 'OR': 135, 'OS': 136, '[15~': 137, '[17~': 138, '[18~': 139, '[19~': 140, '[20~': 141, '[21~': 142, '[23~': 143, '[24~': 144, } found = False next_few = string[i + 1:i + 5] for seq in esc_key_tbl: if next_few.startswith(seq): result.append(esc_key_tbl[seq]) i += len(seq) found = True break if not found: result.append(ord(c)) else: if DBG: term.puts('\nthis ascii char not yet implemented in zscii: ' + str(c) + ' / ' + str(ord(c)) + '\n') term.puts('\nHIT ENTER TO CONTINUE\n') term.getch_or_esc_seq() result.append(ord('?')) i += 1 return result
def pause_scroll_for_user_input(self): # TODO: mark last paused line, set it up so such lines get # marked with a plus when still in the buffer, to help your # eye track the scroll. self.flush() if not buf_empty(self.textBuf): term_width, term_height = term.get_size() if term_width - self.env.hdr.screen_width_units > 0: term.home_cursor() term.cursor_down(term_height-1) # we reserve a one unit right margin for this status char term.cursor_right(self.env.hdr.screen_width_units) term.write_char_with_color('+', self.env.fg_color, self.env.bg_color) term.getch_or_esc_seq() self.update_seen_lines()
def getch_or_esc_seq(self): self.flush() c = term.getch_or_esc_seq() self.update_seen_lines() if c == '\x7f': #delete should be backspace c = '\b' if not is_valid_getch_char(c): return '?' return c
def ascii_to_zscii(string): result = [] i = 0 while i < len(string): c = string[i] if c == '\n': result.append(ord('\r')) # NOTE: gargoyle just ignores the tab key, S 3.8.2.3 says # output only. But since I want to keep expected tab behavior, # I make this compromise. elif c == '\t': result.append(ord(' ')) elif c in ('\r','\b') or (len(c) == 1 and ord(c) > 31 and ord(c) < 127): result.append(ord(c)) # TODO (?): unicode for input (translate codes to zscii using the unicode table(s)) # TODO: keypad digits elif c == '\x1b': esc_key_tbl = { # arrow keys '[A': 129, '[B': 130, '[C': 132, '[D':131, # fkeys 'OP': 133, 'OQ': 134, 'OR': 135, 'OS': 136, '[15~': 137, '[17~': 138, '[18~': 139, '[19~' :140, '[20~': 141, '[21~': 142, '[23~': 143, '[24~': 144, } found = False next_few = string[i+1:i+5] for seq in esc_key_tbl: if next_few.startswith(seq): result.append(esc_key_tbl[seq]) i += len(seq) found = True break if not found: result.append(ord(c)) else: if DBG: term.puts('\nthis ascii char not yet implemented in zscii: '+str(c)+' / '+str(ord(c)) + '\n') term.puts('\nHIT ENTER TO CONTINUE\n') term.getch_or_esc_seq() result.append(ord('?')) i += 1 return result
def msg(self, text): self.write(text) self.flush() term.getch_or_esc_seq()
def get_line_of_input(self, prompt='', prefilled=''): env = self.env for c in prompt: self.write_unwrapped( [ScreenChar(c, env.fg_color, env.bg_color, env.text_style)]) self.flush() self.update_seen_lines() row, col = env.cursor[env.current_window] term.home_cursor() term.cursor_down(row) term.cursor_right(col) term.set_color(env.fg_color, env.bg_color) if line_empty(self.textBuf[row][col:]): term.fill_to_eol_with_bg_color() term.show_cursor() col = max( 0, col - len(prefilled) ) # TODO: prefilled is a seldom-used old and crusty feature, but make unicode safe env.cursor[env.current_window] = row, col class CursorLine(object): def __init__(self, cursor_start, chars): self.cursor = cursor_start self.chars = chars def backspace(self): if self.cursor == 0: return self.left() self.delete_char() def delete_char(self): del self.chars[self.cursor:self.cursor + 1] self.refresh_rest_of_line(is_delete=True) def refresh_rest_of_line(self, is_delete=False): rest = self.chars[self.cursor:] term.puts(''.join(rest)) to_back_up = len(rest) if is_delete: term.puts(' ') to_back_up += 1 if to_back_up: term.cursor_left(to_back_up) def left(self): if self.cursor > 0: self.cursor -= 1 term.cursor_left() def right(self): if self.cursor < len(self.chars): self.cursor += 1 term.cursor_right() def home(self): while self.cursor > 0: self.left() def end(self): while self.cursor != len(self.chars): self.right() def kill_left(self): while self.chars[:self.cursor]: self.backspace() def kill_right(self): while self.chars[self.cursor:]: self.delete_char() def insert(self, c): self.chars.insert(self.cursor, c) term.puts(c) self.cursor += 1 self.refresh_rest_of_line() cursor_start = len(prefilled) cursor_line = CursorLine(cursor_start, [c for c in prefilled]) max_input_len = 120 # 120 char limit seen on gargoyle c = term.getch_or_esc_seq() while c != '\n' and c != '\r': if c == '\b' or c == '\x7f': cursor_line.backspace() # normal edit keys and a bit of readline flavor # left arrow or C-b elif c == '\x1b[D' or c == '\x02': cursor_line.left() # right arrow or C-f elif c == '\x1b[C' or c == '\x06': cursor_line.right() # home or C-a elif c == '\x1b[H' or c == '\x01': cursor_line.home() # end or C-e elif c == '\x1b[F' or c == '\x05': cursor_line.end() # delete or C-d elif c == '\x1b[3~' or c == '\x04': cursor_line.delete_char() # C-u, kill left of cursor elif c == '\x15': cursor_line.kill_left() # C-u, kill right of cursor elif c == '\x0b': cursor_line.kill_right() else: if is_valid_inline_char(c) and len( cursor_line.chars) < max_input_len: if c == '\t': if len(cursor_line.chars) + 4 <= max_input_len: for i in range(4): cursor_line.insert(' ') else: cursor_line.insert(c) c = term.getch_or_esc_seq() term.hide_cursor() term.flush() for c in cursor_line.chars: self.write_unwrapped( [ScreenChar(c, env.fg_color, env.bg_color, env.text_style)]) self.new_line_via_spaces(env.fg_color, env.bg_color, env.text_style) term.home_cursor() return ''.join(cursor_line.chars)
def msg(self, text): self.write(text) self.write('[press any key to continue]\n') self.flush() term.getch_or_esc_seq()