12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)"""This implements an ANSI (VT100) terminal emulator as a subclass of screen.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)PEXPECT LICENSE
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    This license is approved by the OSI and FSF as GPL-compatible.
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        http://opensource.org/licenses/isc-license.txt
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Copyright (c) 2012, Noah Spurrier <noah@noah.org>
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# references:
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#     http://en.wikipedia.org/wiki/ANSI_escape_code
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#     http://www.retards.org/terminals/vt102.html
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#     http://vt100.net/docs/vt102-ug/contents.html
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#     http://vt100.net/docs/vt220-rm/
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#     http://www.termsys.demon.co.uk/vtansi.htm
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import screen
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import FSM
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import copy
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import string
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# The 'Do.*' functions are helper functions for the ANSI class.
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def DoEmit (fsm):
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen = fsm.memory[0]
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen.write_ch(fsm.input_symbol)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def DoStartNumber (fsm):
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fsm.memory.append (fsm.input_symbol)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def DoBuildNumber (fsm):
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ns = fsm.memory.pop()
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ns = ns + fsm.input_symbol
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fsm.memory.append (ns)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def DoBackOne (fsm):
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen = fsm.memory[0]
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen.cursor_back ()
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def DoBack (fsm):
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    count = int(fsm.memory.pop())
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen = fsm.memory[0]
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen.cursor_back (count)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def DoDownOne (fsm):
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen = fsm.memory[0]
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen.cursor_down ()
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def DoDown (fsm):
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    count = int(fsm.memory.pop())
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen = fsm.memory[0]
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen.cursor_down (count)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def DoForwardOne (fsm):
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen = fsm.memory[0]
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen.cursor_forward ()
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def DoForward (fsm):
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    count = int(fsm.memory.pop())
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen = fsm.memory[0]
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen.cursor_forward (count)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def DoUpReverse (fsm):
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen = fsm.memory[0]
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen.cursor_up_reverse()
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def DoUpOne (fsm):
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen = fsm.memory[0]
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen.cursor_up ()
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def DoUp (fsm):
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    count = int(fsm.memory.pop())
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen = fsm.memory[0]
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen.cursor_up (count)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def DoHome (fsm):
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c = int(fsm.memory.pop())
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    r = int(fsm.memory.pop())
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen = fsm.memory[0]
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen.cursor_home (r,c)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def DoHomeOrigin (fsm):
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c = 1
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    r = 1
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen = fsm.memory[0]
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen.cursor_home (r,c)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def DoEraseDown (fsm):
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen = fsm.memory[0]
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen.erase_down()
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def DoErase (fsm):
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    arg = int(fsm.memory.pop())
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen = fsm.memory[0]
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if arg == 0:
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        screen.erase_down()
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elif arg == 1:
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        screen.erase_up()
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elif arg == 2:
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        screen.erase_screen()
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def DoEraseEndOfLine (fsm):
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen = fsm.memory[0]
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen.erase_end_of_line()
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def DoEraseLine (fsm):
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    arg = int(fsm.memory.pop())
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen = fsm.memory[0]
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if arg == 0:
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        screen.erase_end_of_line()
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elif arg == 1:
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        screen.erase_start_of_line()
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elif arg == 2:
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        screen.erase_line()
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def DoEnableScroll (fsm):
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen = fsm.memory[0]
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen.scroll_screen()
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def DoCursorSave (fsm):
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen = fsm.memory[0]
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen.cursor_save_attrs()
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def DoCursorRestore (fsm):
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen = fsm.memory[0]
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen.cursor_restore_attrs()
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def DoScrollRegion (fsm):
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen = fsm.memory[0]
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    r2 = int(fsm.memory.pop())
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    r1 = int(fsm.memory.pop())
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen.scroll_screen_rows (r1,r2)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def DoMode (fsm):
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen = fsm.memory[0]
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mode = fsm.memory.pop() # Should be 4
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # screen.setReplaceMode ()
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def DoLog (fsm):
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    screen = fsm.memory[0]
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fsm.memory = [screen]
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fout = open ('log', 'a')
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fout.write (fsm.input_symbol + ',' + fsm.current_state + '\n')
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fout.close()
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class term (screen.screen):
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """This class is an abstract, generic terminal.
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    This does nothing. This is a placeholder that
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    provides a common base class for other terminals
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    such as an ANSI terminal. """
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def __init__ (self, r=24, c=80):
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        screen.screen.__init__(self, r,c)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ANSI (term):
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """This class implements an ANSI (VT100) terminal.
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    It is a stream filter that recognizes ANSI terminal
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    escape sequences and maintains the state of a screen object. """
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def __init__ (self, r=24,c=80):
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        term.__init__(self,r,c)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        #self.screen = screen (24,80)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state = FSM.FSM ('INIT',[self])
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.state.set_default_transition (DoLog, 'INIT')
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.state.add_transition_any ('INIT', DoEmit, 'INIT')
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition ('\x1b', 'INIT', None, 'ESC')
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.state.add_transition_any ('ESC', DoLog, 'INIT')
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition ('(', 'ESC', None, 'G0SCS')
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition (')', 'ESC', None, 'G1SCS')
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition_list ('AB012', 'G0SCS', None, 'INIT')
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition_list ('AB012', 'G1SCS', None, 'INIT')
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition ('7', 'ESC', DoCursorSave, 'INIT')
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition ('8', 'ESC', DoCursorRestore, 'INIT')
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition ('M', 'ESC', DoUpReverse, 'INIT')
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition ('>', 'ESC', DoUpReverse, 'INIT')
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition ('<', 'ESC', DoUpReverse, 'INIT')
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition ('=', 'ESC', None, 'INIT') # Selects application keypad.
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition ('#', 'ESC', None, 'GRAPHICS_POUND')
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition_any ('GRAPHICS_POUND', None, 'INIT')
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition ('[', 'ESC', None, 'ELB')
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # ELB means Escape Left Bracket. That is ^[[
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition ('H', 'ELB', DoHomeOrigin, 'INIT')
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition ('D', 'ELB', DoBackOne, 'INIT')
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition ('B', 'ELB', DoDownOne, 'INIT')
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition ('C', 'ELB', DoForwardOne, 'INIT')
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition ('A', 'ELB', DoUpOne, 'INIT')
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition ('J', 'ELB', DoEraseDown, 'INIT')
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition ('K', 'ELB', DoEraseEndOfLine, 'INIT')
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition ('r', 'ELB', DoEnableScroll, 'INIT')
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition ('m', 'ELB', None, 'INIT')
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition ('?', 'ELB', None, 'MODECRAP')
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.state.add_transition_list (string.digits, 'ELB', DoStartNumber, 'NUMBER_1')
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.state.add_transition_list (string.digits, 'NUMBER_1', DoBuildNumber, 'NUMBER_1')
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition ('D', 'NUMBER_1', DoBack, 'INIT')
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition ('B', 'NUMBER_1', DoDown, 'INIT')
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition ('C', 'NUMBER_1', DoForward, 'INIT')
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition ('A', 'NUMBER_1', DoUp, 'INIT')
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition ('J', 'NUMBER_1', DoErase, 'INIT')
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition ('K', 'NUMBER_1', DoEraseLine, 'INIT')
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition ('l', 'NUMBER_1', DoMode, 'INIT')
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ### It gets worse... the 'm' code can have infinite number of
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ### number;number;number before it. I've never seen more than two,
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ### but the specs say it's allowed. crap!
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition ('m', 'NUMBER_1', None, 'INIT')
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ### LED control. Same implementation problem as 'm' code.
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.state.add_transition ('q', 'NUMBER_1', None, 'INIT')
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        # \E[?47h switch to alternate screen
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        # \E[?47l restores to normal screen from alternate screen.
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.state.add_transition_list (string.digits, 'MODECRAP', DoStartNumber, 'MODECRAP_NUM')
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.state.add_transition_list (string.digits, 'MODECRAP_NUM', DoBuildNumber, 'MODECRAP_NUM')
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition ('l', 'MODECRAP_NUM', None, 'INIT')
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition ('h', 'MODECRAP_NUM', None, 'INIT')
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#RM   Reset Mode                Esc [ Ps l                   none
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition (';', 'NUMBER_1', None, 'SEMICOLON')
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.state.add_transition_any ('SEMICOLON', DoLog, 'INIT')
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.state.add_transition_list (string.digits, 'SEMICOLON', DoStartNumber, 'NUMBER_2')
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.state.add_transition_list (string.digits, 'NUMBER_2', DoBuildNumber, 'NUMBER_2')
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.state.add_transition_any ('NUMBER_2', DoLog, 'INIT')
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition ('H', 'NUMBER_2', DoHome, 'INIT')
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition ('f', 'NUMBER_2', DoHome, 'INIT')
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition ('r', 'NUMBER_2', DoScrollRegion, 'INIT')
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ### It gets worse... the 'm' code can have infinite number of
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ### number;number;number before it. I've never seen more than two,
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ### but the specs say it's allowed. crap!
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.add_transition ('m', 'NUMBER_2', None, 'INIT')
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ### LED control. Same problem as 'm' code.
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.state.add_transition ('q', 'NUMBER_2', None, 'INIT')
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.state.add_transition (';', 'NUMBER_2', None, 'SEMICOLON_X')
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        # Create a state for 'q' and 'm' which allows an infinite number of ignored numbers
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.state.add_transition_any ('SEMICOLON_X', DoLog, 'INIT')
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.state.add_transition_list (string.digits, 'SEMICOLON_X', None, 'NUMBER_X')
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.state.add_transition_any ('NUMBER_X', DoLog, 'INIT')
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.state.add_transition ('m', 'NUMBER_X', None, 'INIT')
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.state.add_transition ('q', 'NUMBER_X', None, 'INIT')
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.state.add_transition (';', 'NUMBER_2', None, 'SEMICOLON_X')
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def process (self, c):
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.state.process(c)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def process_list (self, l):
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.write(l)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def write (self, s):
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for c in s:
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.process(c)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def flush (self):
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pass
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def write_ch (self, ch):
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """This puts a character at the current cursor position. The cursor
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        position is moved forward with wrap-around, but no scrolling is done if
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        the cursor hits the lower-right corner of the screen. """
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        #\r and \n both produce a call to cr() and lf(), respectively.
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ch = ch[0]
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if ch == '\r':
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            self.cr()
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if ch == '\n':
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.crlf()
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if ch == chr(screen.BS):
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.cursor_back()
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if ch not in string.printable:
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            fout = open ('log', 'a')
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            fout.write ('Nonprint: ' + str(ord(ch)) + '\n')
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            fout.close()
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.put_abs(self.cur_r, self.cur_c, ch)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        old_r = self.cur_r
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        old_c = self.cur_c
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.cursor_forward()
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if old_c == self.cur_c:
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.cursor_down()
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if old_r != self.cur_r:
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.cursor_home (self.cur_r, 1)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else:
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.scroll_up ()
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.cursor_home (self.cur_r, 1)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.erase_line()
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#    def test (self):
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#        import sys
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#        write_text = 'I\'ve got a ferret sticking up my nose.\n' + \
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#        '(He\'s got a ferret sticking up his nose.)\n' + \
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#        'How it got there I can\'t tell\n' + \
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#        'But now it\'s there it hurts like hell\n' + \
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#        'And what is more it radically affects my sense of smell.\n' + \
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#        '(His sense of smell.)\n' + \
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#        'I can see a bare-bottomed mandril.\n' + \
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#        '(Slyly eyeing his other nostril.)\n' + \
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#        'If it jumps inside there too I really don\'t know what to do\n' + \
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#        'I\'ll be the proud posessor of a kind of nasal zoo.\n' + \
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#        '(A nasal zoo.)\n' + \
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#        'I\'ve got a ferret sticking up my nose.\n' + \
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#        '(And what is worst of all it constantly explodes.)\n' + \
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#        '"Ferrets don\'t explode," you say\n' + \
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#        'But it happened nine times yesterday\n' + \
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#        'And I should know for each time I was standing in the way.\n' + \
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#        'I\'ve got a ferret sticking up my nose.\n' + \
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#        '(He\'s got a ferret sticking up his nose.)\n' + \
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#        'How it got there I can\'t tell\n' + \
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#        'But now it\'s there it hurts like hell\n' + \
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#        'And what is more it radically affects my sense of smell.\n' + \
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#        '(His sense of smell.)'
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#        self.fill('.')
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#        self.cursor_home()
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#        for c in write_text:
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#            self.write_ch (c)
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#        print str(self)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if __name__ == '__main__':
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#    t = ANSI(6,65)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#    t.test()
369