Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 1 | """This implements an ANSI terminal emulator as a subclass of screen. |
| 2 | |
| 3 | $Id: ANSI.py 491 2007-12-16 20:04:57Z noah $ |
| 4 | """ |
| 5 | # references: |
| 6 | # http://www.retards.org/terminals/vt102.html |
| 7 | # http://vt100.net/docs/vt102-ug/contents.html |
| 8 | # http://vt100.net/docs/vt220-rm/ |
| 9 | # http://www.termsys.demon.co.uk/vtansi.htm |
| 10 | |
| 11 | import screen |
| 12 | import FSM |
| 13 | import copy |
| 14 | import string |
| 15 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 16 | |
| 17 | def Emit(fsm): |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 18 | |
| 19 | screen = fsm.memory[0] |
| 20 | screen.write_ch(fsm.input_symbol) |
| 21 | |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 22 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 23 | def StartNumber(fsm): |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 24 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 25 | fsm.memory.append(fsm.input_symbol) |
| 26 | |
| 27 | |
| 28 | def BuildNumber(fsm): |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 29 | |
| 30 | ns = fsm.memory.pop() |
| 31 | ns = ns + fsm.input_symbol |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 32 | fsm.memory.append(ns) |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 33 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 34 | |
| 35 | def DoBackOne(fsm): |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 36 | |
| 37 | screen = fsm.memory[0] |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 38 | screen.cursor_back() |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 39 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 40 | |
| 41 | def DoBack(fsm): |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 42 | |
| 43 | count = int(fsm.memory.pop()) |
| 44 | screen = fsm.memory[0] |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 45 | screen.cursor_back(count) |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 46 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 47 | |
| 48 | def DoDownOne(fsm): |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 49 | |
| 50 | screen = fsm.memory[0] |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 51 | screen.cursor_down() |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 52 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 53 | |
| 54 | def DoDown(fsm): |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 55 | |
| 56 | count = int(fsm.memory.pop()) |
| 57 | screen = fsm.memory[0] |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 58 | screen.cursor_down(count) |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 59 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 60 | |
| 61 | def DoForwardOne(fsm): |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 62 | |
| 63 | screen = fsm.memory[0] |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 64 | screen.cursor_forward() |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 65 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 66 | |
| 67 | def DoForward(fsm): |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 68 | |
| 69 | count = int(fsm.memory.pop()) |
| 70 | screen = fsm.memory[0] |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 71 | screen.cursor_forward(count) |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 72 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 73 | |
| 74 | def DoUpReverse(fsm): |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 75 | |
| 76 | screen = fsm.memory[0] |
| 77 | screen.cursor_up_reverse() |
| 78 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 79 | |
| 80 | def DoUpOne(fsm): |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 81 | |
| 82 | screen = fsm.memory[0] |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 83 | screen.cursor_up() |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 84 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 85 | |
| 86 | def DoUp(fsm): |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 87 | |
| 88 | count = int(fsm.memory.pop()) |
| 89 | screen = fsm.memory[0] |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 90 | screen.cursor_up(count) |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 91 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 92 | |
| 93 | def DoHome(fsm): |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 94 | |
| 95 | c = int(fsm.memory.pop()) |
| 96 | r = int(fsm.memory.pop()) |
| 97 | screen = fsm.memory[0] |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 98 | screen.cursor_home(r, c) |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 99 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 100 | |
| 101 | def DoHomeOrigin(fsm): |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 102 | |
| 103 | c = 1 |
| 104 | r = 1 |
| 105 | screen = fsm.memory[0] |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 106 | screen.cursor_home(r, c) |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 107 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 108 | |
| 109 | def DoEraseDown(fsm): |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 110 | |
| 111 | screen = fsm.memory[0] |
| 112 | screen.erase_down() |
| 113 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 114 | |
| 115 | def DoErase(fsm): |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 116 | |
| 117 | arg = int(fsm.memory.pop()) |
| 118 | screen = fsm.memory[0] |
| 119 | if arg == 0: |
| 120 | screen.erase_down() |
| 121 | elif arg == 1: |
| 122 | screen.erase_up() |
| 123 | elif arg == 2: |
| 124 | screen.erase_screen() |
| 125 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 126 | |
| 127 | def DoEraseEndOfLine(fsm): |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 128 | |
| 129 | screen = fsm.memory[0] |
| 130 | screen.erase_end_of_line() |
| 131 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 132 | |
| 133 | def DoEraseLine(fsm): |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 134 | |
| 135 | screen = fsm.memory[0] |
| 136 | if arg == 0: |
| 137 | screen.end_of_line() |
| 138 | elif arg == 1: |
| 139 | screen.start_of_line() |
| 140 | elif arg == 2: |
| 141 | screen.erase_line() |
| 142 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 143 | |
| 144 | def DoEnableScroll(fsm): |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 145 | |
| 146 | screen = fsm.memory[0] |
| 147 | screen.scroll_screen() |
| 148 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 149 | |
| 150 | def DoCursorSave(fsm): |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 151 | |
| 152 | screen = fsm.memory[0] |
| 153 | screen.cursor_save_attrs() |
| 154 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 155 | |
| 156 | def DoCursorRestore(fsm): |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 157 | |
| 158 | screen = fsm.memory[0] |
| 159 | screen.cursor_restore_attrs() |
| 160 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 161 | |
| 162 | def DoScrollRegion(fsm): |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 163 | |
| 164 | screen = fsm.memory[0] |
| 165 | r2 = int(fsm.memory.pop()) |
| 166 | r1 = int(fsm.memory.pop()) |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 167 | screen.scroll_screen_rows(r1, r2) |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 168 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 169 | |
| 170 | def DoMode(fsm): |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 171 | |
| 172 | screen = fsm.memory[0] |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 173 | mode = fsm.memory.pop() # Should be 4 |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 174 | # screen.setReplaceMode () |
| 175 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 176 | |
| 177 | def Log(fsm): |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 178 | |
| 179 | screen = fsm.memory[0] |
| 180 | fsm.memory = [screen] |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 181 | fout = open('log', 'a') |
| 182 | fout.write(fsm.input_symbol + ',' + fsm.current_state + '\n') |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 183 | fout.close() |
| 184 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 185 | |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 186 | class term (screen.screen): |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 187 | """This is a placeholder. |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 188 | In theory I might want to add other terminal types. |
| 189 | """ |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 190 | |
| 191 | def __init__(self, r=24, c=80): |
| 192 | screen.screen.__init__(self, r, c) |
| 193 | |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 194 | |
| 195 | class ANSI (term): |
| 196 | |
| 197 | """This class encapsulates a generic terminal. It filters a stream and |
| 198 | maintains the state of a screen object. """ |
| 199 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 200 | def __init__(self, r=24, c=80): |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 201 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 202 | term.__init__(self, r, c) |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 203 | |
| 204 | #self.screen = screen (24,80) |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 205 | self.state = FSM.FSM('INIT', [self]) |
| 206 | self.state.set_default_transition(Log, 'INIT') |
| 207 | self.state.add_transition_any('INIT', Emit, 'INIT') |
| 208 | self.state.add_transition('\x1b', 'INIT', None, 'ESC') |
| 209 | self.state.add_transition_any('ESC', Log, 'INIT') |
| 210 | self.state.add_transition('(', 'ESC', None, 'G0SCS') |
| 211 | self.state.add_transition(')', 'ESC', None, 'G1SCS') |
| 212 | self.state.add_transition_list('AB012', 'G0SCS', None, 'INIT') |
| 213 | self.state.add_transition_list('AB012', 'G1SCS', None, 'INIT') |
| 214 | self.state.add_transition('7', 'ESC', DoCursorSave, 'INIT') |
| 215 | self.state.add_transition('8', 'ESC', DoCursorRestore, 'INIT') |
| 216 | self.state.add_transition('M', 'ESC', DoUpReverse, 'INIT') |
| 217 | self.state.add_transition('>', 'ESC', DoUpReverse, 'INIT') |
| 218 | self.state.add_transition('<', 'ESC', DoUpReverse, 'INIT') |
| 219 | # Selects application keypad. |
| 220 | self.state.add_transition('=', 'ESC', None, 'INIT') |
| 221 | self.state.add_transition('#', 'ESC', None, 'GRAPHICS_POUND') |
| 222 | self.state.add_transition_any('GRAPHICS_POUND', None, 'INIT') |
| 223 | self.state.add_transition('[', 'ESC', None, 'ELB') |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 224 | # ELB means Escape Left Bracket. That is ^[[ |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 225 | self.state.add_transition('H', 'ELB', DoHomeOrigin, 'INIT') |
| 226 | self.state.add_transition('D', 'ELB', DoBackOne, 'INIT') |
| 227 | self.state.add_transition('B', 'ELB', DoDownOne, 'INIT') |
| 228 | self.state.add_transition('C', 'ELB', DoForwardOne, 'INIT') |
| 229 | self.state.add_transition('A', 'ELB', DoUpOne, 'INIT') |
| 230 | self.state.add_transition('J', 'ELB', DoEraseDown, 'INIT') |
| 231 | self.state.add_transition('K', 'ELB', DoEraseEndOfLine, 'INIT') |
| 232 | self.state.add_transition('r', 'ELB', DoEnableScroll, 'INIT') |
| 233 | self.state.add_transition('m', 'ELB', None, 'INIT') |
| 234 | self.state.add_transition('?', 'ELB', None, 'MODECRAP') |
| 235 | self.state.add_transition_list( |
| 236 | string.digits, 'ELB', StartNumber, 'NUMBER_1') |
| 237 | self.state.add_transition_list( |
| 238 | string.digits, 'NUMBER_1', BuildNumber, 'NUMBER_1') |
| 239 | self.state.add_transition('D', 'NUMBER_1', DoBack, 'INIT') |
| 240 | self.state.add_transition('B', 'NUMBER_1', DoDown, 'INIT') |
| 241 | self.state.add_transition('C', 'NUMBER_1', DoForward, 'INIT') |
| 242 | self.state.add_transition('A', 'NUMBER_1', DoUp, 'INIT') |
| 243 | self.state.add_transition('J', 'NUMBER_1', DoErase, 'INIT') |
| 244 | self.state.add_transition('K', 'NUMBER_1', DoEraseLine, 'INIT') |
| 245 | self.state.add_transition('l', 'NUMBER_1', DoMode, 'INIT') |
| 246 | # It gets worse... the 'm' code can have infinite number of |
| 247 | # number;number;number before it. I've never seen more than two, |
| 248 | # but the specs say it's allowed. crap! |
| 249 | self.state.add_transition('m', 'NUMBER_1', None, 'INIT') |
| 250 | # LED control. Same problem as 'm' code. |
| 251 | self.state.add_transition('q', 'NUMBER_1', None, 'INIT') |
| 252 | |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 253 | # \E[?47h appears to be "switch to alternate screen" |
| 254 | # \E[?47l restores alternate screen... I think. |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 255 | self.state.add_transition_list( |
| 256 | string.digits, 'MODECRAP', StartNumber, 'MODECRAP_NUM') |
| 257 | self.state.add_transition_list( |
| 258 | string.digits, |
| 259 | 'MODECRAP_NUM', |
| 260 | BuildNumber, |
| 261 | 'MODECRAP_NUM') |
| 262 | self.state.add_transition('l', 'MODECRAP_NUM', None, 'INIT') |
| 263 | self.state.add_transition('h', 'MODECRAP_NUM', None, 'INIT') |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 264 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 265 | # RM Reset Mode Esc [ Ps l none |
| 266 | self.state.add_transition(';', 'NUMBER_1', None, 'SEMICOLON') |
| 267 | self.state.add_transition_any('SEMICOLON', Log, 'INIT') |
| 268 | self.state.add_transition_list( |
| 269 | string.digits, 'SEMICOLON', StartNumber, 'NUMBER_2') |
| 270 | self.state.add_transition_list( |
| 271 | string.digits, 'NUMBER_2', BuildNumber, 'NUMBER_2') |
| 272 | self.state.add_transition_any('NUMBER_2', Log, 'INIT') |
| 273 | self.state.add_transition('H', 'NUMBER_2', DoHome, 'INIT') |
| 274 | self.state.add_transition('f', 'NUMBER_2', DoHome, 'INIT') |
| 275 | self.state.add_transition('r', 'NUMBER_2', DoScrollRegion, 'INIT') |
| 276 | # It gets worse... the 'm' code can have infinite number of |
| 277 | # number;number;number before it. I've never seen more than two, |
| 278 | # but the specs say it's allowed. crap! |
| 279 | self.state.add_transition('m', 'NUMBER_2', None, 'INIT') |
| 280 | # LED control. Same problem as 'm' code. |
| 281 | self.state.add_transition('q', 'NUMBER_2', None, 'INIT') |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 282 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 283 | def process(self, c): |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 284 | |
| 285 | self.state.process(c) |
| 286 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 287 | def process_list(self, l): |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 288 | |
| 289 | self.write(l) |
| 290 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 291 | def write(self, s): |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 292 | |
| 293 | for c in s: |
| 294 | self.process(c) |
| 295 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 296 | def flush(self): |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 297 | |
| 298 | pass |
| 299 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 300 | def write_ch(self, ch): |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 301 | """This puts a character at the current cursor position. cursor |
| 302 | position if moved forward with wrap-around, but no scrolling is done if |
| 303 | the cursor hits the lower-right corner of the screen. """ |
| 304 | |
| 305 | #\r and \n both produce a call to crlf(). |
| 306 | ch = ch[0] |
| 307 | |
| 308 | if ch == '\r': |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 309 | # self.crlf() |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 310 | return |
| 311 | if ch == '\n': |
| 312 | self.crlf() |
| 313 | return |
| 314 | if ch == chr(screen.BS): |
| 315 | self.cursor_back() |
| 316 | self.put_abs(self.cur_r, self.cur_c, ' ') |
| 317 | return |
| 318 | |
| 319 | if ch not in string.printable: |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 320 | fout = open('log', 'a') |
| 321 | fout.write('Nonprint: ' + str(ord(ch)) + '\n') |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 322 | fout.close() |
| 323 | return |
| 324 | self.put_abs(self.cur_r, self.cur_c, ch) |
| 325 | old_r = self.cur_r |
| 326 | old_c = self.cur_c |
| 327 | self.cursor_forward() |
| 328 | if old_c == self.cur_c: |
| 329 | self.cursor_down() |
| 330 | if old_r != self.cur_r: |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 331 | self.cursor_home(self.cur_r, 1) |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 332 | else: |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 333 | self.scroll_up() |
| 334 | self.cursor_home(self.cur_r, 1) |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 335 | self.erase_line() |
| 336 | |
| 337 | # def test (self): |
| 338 | # |
| 339 | # import sys |
| 340 | # write_text = 'I\'ve got a ferret sticking up my nose.\n' + \ |
| 341 | # '(He\'s got a ferret sticking up his nose.)\n' + \ |
| 342 | # 'How it got there I can\'t tell\n' + \ |
| 343 | # 'But now it\'s there it hurts like hell\n' + \ |
| 344 | # 'And what is more it radically affects my sense of smell.\n' + \ |
| 345 | # '(His sense of smell.)\n' + \ |
| 346 | # 'I can see a bare-bottomed mandril.\n' + \ |
| 347 | # '(Slyly eyeing his other nostril.)\n' + \ |
| 348 | # 'If it jumps inside there too I really don\'t know what to do\n' + \ |
| 349 | # 'I\'ll be the proud posessor of a kind of nasal zoo.\n' + \ |
| 350 | # '(A nasal zoo.)\n' + \ |
| 351 | # 'I\'ve got a ferret sticking up my nose.\n' + \ |
| 352 | # '(And what is worst of all it constantly explodes.)\n' + \ |
| 353 | # '"Ferrets don\'t explode," you say\n' + \ |
| 354 | # 'But it happened nine times yesterday\n' + \ |
| 355 | # 'And I should know for each time I was standing in the way.\n' + \ |
| 356 | # 'I\'ve got a ferret sticking up my nose.\n' + \ |
| 357 | # '(He\'s got a ferret sticking up his nose.)\n' + \ |
| 358 | # 'How it got there I can\'t tell\n' + \ |
| 359 | # 'But now it\'s there it hurts like hell\n' + \ |
| 360 | # 'And what is more it radically affects my sense of smell.\n' + \ |
| 361 | # '(His sense of smell.)' |
| 362 | # self.fill('.') |
| 363 | # self.cursor_home() |
| 364 | # for c in write_text: |
| 365 | # self.write_ch (c) |
| 366 | # print str(self) |
| 367 | # |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 368 | # if __name__ == '__main__': |
Johnny Chen | b7cfba4 | 2011-03-11 20:13:06 +0000 | [diff] [blame] | 369 | # t = ANSI(6,65) |
| 370 | # t.test() |