home *** CD-ROM | disk | FTP | other *** search
/ Clickx 115 / Clickx 115.iso / software / tools / windows / tails-i386-0.16.iso / live / filesystem.squashfs / usr / share / pyshared / ANSI.py next >
Encoding:
Python Source  |  2007-12-16  |  10.6 KB  |  335 lines

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