18a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen"""This implements an ANSI terminal emulator as a subclass of screen.
28a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
38a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen$Id: ANSI.py 491 2007-12-16 20:04:57Z noah $
48a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen"""
58a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen# references:
68a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#     http://www.retards.org/terminals/vt102.html
78a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#     http://vt100.net/docs/vt102-ug/contents.html
88a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#     http://vt100.net/docs/vt220-rm/
98a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#     http://www.termsys.demon.co.uk/vtansi.htm
108a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
118a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chenimport screen
128a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chenimport FSM
138a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chenimport copy
148a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chenimport string
158a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
168a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chendef Emit (fsm):
178a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
188a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen = fsm.memory[0]
198a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen.write_ch(fsm.input_symbol)
208a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
218a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chendef StartNumber (fsm):
228a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
238a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    fsm.memory.append (fsm.input_symbol)
248a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
258a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chendef BuildNumber (fsm):
268a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
278a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    ns = fsm.memory.pop()
288a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    ns = ns + fsm.input_symbol
298a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    fsm.memory.append (ns)
308a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
318a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chendef DoBackOne (fsm):
328a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
338a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen = fsm.memory[0]
348a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen.cursor_back ()
358a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
368a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chendef DoBack (fsm):
378a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
388a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    count = int(fsm.memory.pop())
398a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen = fsm.memory[0]
408a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen.cursor_back (count)
418a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
428a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chendef DoDownOne (fsm):
438a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
448a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen = fsm.memory[0]
458a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen.cursor_down ()
468a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
478a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chendef DoDown (fsm):
488a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
498a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    count = int(fsm.memory.pop())
508a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen = fsm.memory[0]
518a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen.cursor_down (count)
528a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
538a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chendef DoForwardOne (fsm):
548a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
558a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen = fsm.memory[0]
568a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen.cursor_forward ()
578a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
588a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chendef DoForward (fsm):
598a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
608a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    count = int(fsm.memory.pop())
618a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen = fsm.memory[0]
628a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen.cursor_forward (count)
638a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
648a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chendef DoUpReverse (fsm):
658a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
668a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen = fsm.memory[0]
678a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen.cursor_up_reverse()
688a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
698a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chendef DoUpOne (fsm):
708a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
718a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen = fsm.memory[0]
728a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen.cursor_up ()
738a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
748a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chendef DoUp (fsm):
758a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
768a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    count = int(fsm.memory.pop())
778a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen = fsm.memory[0]
788a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen.cursor_up (count)
798a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
808a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chendef DoHome (fsm):
818a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
828a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    c = int(fsm.memory.pop())
838a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    r = int(fsm.memory.pop())
848a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen = fsm.memory[0]
858a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen.cursor_home (r,c)
868a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
878a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chendef DoHomeOrigin (fsm):
888a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
898a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    c = 1
908a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    r = 1
918a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen = fsm.memory[0]
928a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen.cursor_home (r,c)
938a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
948a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chendef DoEraseDown (fsm):
958a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
968a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen = fsm.memory[0]
978a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen.erase_down()
988a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
998a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chendef DoErase (fsm):
1008a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
1018a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    arg = int(fsm.memory.pop())
1028a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen = fsm.memory[0]
1038a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    if arg == 0:
1048a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        screen.erase_down()
1058a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    elif arg == 1:
1068a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        screen.erase_up()
1078a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    elif arg == 2:
1088a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        screen.erase_screen()
1098a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
1108a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chendef DoEraseEndOfLine (fsm):
1118a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
1128a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen = fsm.memory[0]
1138a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen.erase_end_of_line()
1148a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
1158a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chendef DoEraseLine (fsm):
1168a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
1178a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen = fsm.memory[0]
1188a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    if arg == 0:
1198a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        screen.end_of_line()
1208a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    elif arg == 1:
1218a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        screen.start_of_line()
1228a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    elif arg == 2:
1238a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        screen.erase_line()
1248a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
1258a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chendef DoEnableScroll (fsm):
1268a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
1278a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen = fsm.memory[0]
1288a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen.scroll_screen()
1298a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
1308a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chendef DoCursorSave (fsm):
1318a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
1328a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen = fsm.memory[0]
1338a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen.cursor_save_attrs()
1348a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
1358a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chendef DoCursorRestore (fsm):
1368a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
1378a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen = fsm.memory[0]
1388a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen.cursor_restore_attrs()
1398a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
1408a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chendef DoScrollRegion (fsm):
1418a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
1428a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen = fsm.memory[0]
1438a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    r2 = int(fsm.memory.pop())
1448a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    r1 = int(fsm.memory.pop())
1458a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen.scroll_screen_rows (r1,r2)
1468a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
1478a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chendef DoMode (fsm):
1488a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
1498a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen = fsm.memory[0]
1508a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    mode = fsm.memory.pop() # Should be 4
1518a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    # screen.setReplaceMode ()
1528a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
1538a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chendef Log (fsm):
1548a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
1558a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    screen = fsm.memory[0]
1568a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    fsm.memory = [screen]
1578a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    fout = open ('log', 'a')
1588a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    fout.write (fsm.input_symbol + ',' + fsm.current_state + '\n')
1598a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    fout.close()
1608a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
1618a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chenclass term (screen.screen):
1628a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    """This is a placeholder.
1638a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    In theory I might want to add other terminal types.
1648a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    """
1658a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    def __init__ (self, r=24, c=80):
1668a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        screen.screen.__init__(self, r,c)
1678a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
1688a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chenclass ANSI (term):
1698a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
1708a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    """This class encapsulates a generic terminal. It filters a stream and
1718a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    maintains the state of a screen object. """
1728a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
1738a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    def __init__ (self, r=24,c=80):
1748a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
1758a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        term.__init__(self,r,c)
1768a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
1778a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        #self.screen = screen (24,80)
1788a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state = FSM.FSM ('INIT',[self])
1798a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.set_default_transition (Log, 'INIT')
1808a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition_any ('INIT', Emit, 'INIT')
1818a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition ('\x1b', 'INIT', None, 'ESC')
1828a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition_any ('ESC', Log, 'INIT')
1838a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition ('(', 'ESC', None, 'G0SCS')
1848a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition (')', 'ESC', None, 'G1SCS')
1858a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition_list ('AB012', 'G0SCS', None, 'INIT')
1868a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition_list ('AB012', 'G1SCS', None, 'INIT')
1878a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition ('7', 'ESC', DoCursorSave, 'INIT')
1888a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition ('8', 'ESC', DoCursorRestore, 'INIT')
1898a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition ('M', 'ESC', DoUpReverse, 'INIT')
1908a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition ('>', 'ESC', DoUpReverse, 'INIT')
1918a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition ('<', 'ESC', DoUpReverse, 'INIT')
1928a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition ('=', 'ESC', None, 'INIT') # Selects application keypad.
1938a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition ('#', 'ESC', None, 'GRAPHICS_POUND')
1948a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition_any ('GRAPHICS_POUND', None, 'INIT')
1958a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition ('[', 'ESC', None, 'ELB')
1968a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        # ELB means Escape Left Bracket. That is ^[[
1978a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition ('H', 'ELB', DoHomeOrigin, 'INIT')
1988a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition ('D', 'ELB', DoBackOne, 'INIT')
1998a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition ('B', 'ELB', DoDownOne, 'INIT')
2008a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition ('C', 'ELB', DoForwardOne, 'INIT')
2018a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition ('A', 'ELB', DoUpOne, 'INIT')
2028a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition ('J', 'ELB', DoEraseDown, 'INIT')
2038a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition ('K', 'ELB', DoEraseEndOfLine, 'INIT')
2048a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition ('r', 'ELB', DoEnableScroll, 'INIT')
2058a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition ('m', 'ELB', None, 'INIT')
2068a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition ('?', 'ELB', None, 'MODECRAP')
2078a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition_list (string.digits, 'ELB', StartNumber, 'NUMBER_1')
2088a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition_list (string.digits, 'NUMBER_1', BuildNumber, 'NUMBER_1')
2098a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition ('D', 'NUMBER_1', DoBack, 'INIT')
2108a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition ('B', 'NUMBER_1', DoDown, 'INIT')
2118a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition ('C', 'NUMBER_1', DoForward, 'INIT')
2128a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition ('A', 'NUMBER_1', DoUp, 'INIT')
2138a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition ('J', 'NUMBER_1', DoErase, 'INIT')
2148a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition ('K', 'NUMBER_1', DoEraseLine, 'INIT')
2158a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition ('l', 'NUMBER_1', DoMode, 'INIT')
2168a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        ### It gets worse... the 'm' code can have infinite number of
2178a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        ### number;number;number before it. I've never seen more than two,
2188a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        ### but the specs say it's allowed. crap!
2198a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition ('m', 'NUMBER_1', None, 'INIT')
2208a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        ### LED control. Same problem as 'm' code.
2218a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition ('q', 'NUMBER_1', None, 'INIT')
2228a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
2238a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        # \E[?47h appears to be "switch to alternate screen"
2248a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        # \E[?47l restores alternate screen... I think.
2258a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition_list (string.digits, 'MODECRAP', StartNumber, 'MODECRAP_NUM')
2268a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition_list (string.digits, 'MODECRAP_NUM', BuildNumber, 'MODECRAP_NUM')
2278a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition ('l', 'MODECRAP_NUM', None, 'INIT')
2288a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition ('h', 'MODECRAP_NUM', None, 'INIT')
2298a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
2308a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#RM   Reset Mode                Esc [ Ps l                   none
2318a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition (';', 'NUMBER_1', None, 'SEMICOLON')
2328a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition_any ('SEMICOLON', Log, 'INIT')
2338a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition_list (string.digits, 'SEMICOLON', StartNumber, 'NUMBER_2')
2348a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition_list (string.digits, 'NUMBER_2', BuildNumber, 'NUMBER_2')
2358a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition_any ('NUMBER_2', Log, 'INIT')
2368a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition ('H', 'NUMBER_2', DoHome, 'INIT')
2378a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition ('f', 'NUMBER_2', DoHome, 'INIT')
2388a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition ('r', 'NUMBER_2', DoScrollRegion, 'INIT')
2398a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        ### It gets worse... the 'm' code can have infinite number of
2408a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        ### number;number;number before it. I've never seen more than two,
2418a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        ### but the specs say it's allowed. crap!
2428a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition ('m', 'NUMBER_2', None, 'INIT')
2438a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        ### LED control. Same problem as 'm' code.
2448a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.add_transition ('q', 'NUMBER_2', None, 'INIT')
2458a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
2468a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    def process (self, c):
2478a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
2488a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.state.process(c)
2498a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
2508a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    def process_list (self, l):
2518a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
2528a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.write(l)
2538a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
2548a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    def write (self, s):
2558a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
2568a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        for c in s:
2578a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            self.process(c)
2588a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
2598a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    def flush (self):
2608a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
2618a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        pass
2628a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
2638a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen    def write_ch (self, ch):
2648a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
2658a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        """This puts a character at the current cursor position. cursor
2668a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        position if moved forward with wrap-around, but no scrolling is done if
2678a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        the cursor hits the lower-right corner of the screen. """
2688a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
2698a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        #\r and \n both produce a call to crlf().
2708a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        ch = ch[0]
2718a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
2728a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        if ch == '\r':
2738a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        #    self.crlf()
2748a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            return
2758a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        if ch == '\n':
2768a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            self.crlf()
2778a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            return
2788a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        if ch == chr(screen.BS):
2798a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            self.cursor_back()
2808a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            self.put_abs(self.cur_r, self.cur_c, ' ')
2818a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            return
2828a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
2838a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        if ch not in string.printable:
2848a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            fout = open ('log', 'a')
2858a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            fout.write ('Nonprint: ' + str(ord(ch)) + '\n')
2868a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            fout.close()
2878a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            return
2888a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.put_abs(self.cur_r, self.cur_c, ch)
2898a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        old_r = self.cur_r
2908a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        old_c = self.cur_c
2918a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        self.cursor_forward()
2928a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen        if old_c == self.cur_c:
2938a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            self.cursor_down()
2948a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            if old_r != self.cur_r:
2958a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen                self.cursor_home (self.cur_r, 1)
2968a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen            else:
2978a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen                self.scroll_up ()
2988a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen                self.cursor_home (self.cur_r, 1)
2998a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen                self.erase_line()
3008a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen
3018a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#    def test (self):
3028a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#
3038a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#        import sys
3048a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#        write_text = 'I\'ve got a ferret sticking up my nose.\n' + \
3058a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#        '(He\'s got a ferret sticking up his nose.)\n' + \
3068a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#        'How it got there I can\'t tell\n' + \
3078a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#        'But now it\'s there it hurts like hell\n' + \
3088a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#        'And what is more it radically affects my sense of smell.\n' + \
3098a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#        '(His sense of smell.)\n' + \
3108a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#        'I can see a bare-bottomed mandril.\n' + \
3118a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#        '(Slyly eyeing his other nostril.)\n' + \
3128a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#        'If it jumps inside there too I really don\'t know what to do\n' + \
3138a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#        'I\'ll be the proud posessor of a kind of nasal zoo.\n' + \
3148a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#        '(A nasal zoo.)\n' + \
3158a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#        'I\'ve got a ferret sticking up my nose.\n' + \
3168a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#        '(And what is worst of all it constantly explodes.)\n' + \
3178a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#        '"Ferrets don\'t explode," you say\n' + \
3188a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#        'But it happened nine times yesterday\n' + \
3198a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#        'And I should know for each time I was standing in the way.\n' + \
3208a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#        'I\'ve got a ferret sticking up my nose.\n' + \
3218a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#        '(He\'s got a ferret sticking up his nose.)\n' + \
3228a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#        'How it got there I can\'t tell\n' + \
3238a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#        'But now it\'s there it hurts like hell\n' + \
3248a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#        'And what is more it radically affects my sense of smell.\n' + \
3258a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#        '(His sense of smell.)'
3268a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#        self.fill('.')
3278a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#        self.cursor_home()
3288a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#        for c in write_text:
3298a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#            self.write_ch (c)
3308a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#        print str(self)
3318a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#
3328a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#if __name__ == '__main__':
3338a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#    t = ANSI(6,65)
3348a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#    t.test()
335