| 1 |
""" |
|---|
| 2 |
You don't really want to use this module. Try insults.py instead. |
|---|
| 3 |
""" |
|---|
| 4 |
|
|---|
| 5 |
from twisted.internet import protocol |
|---|
| 6 |
|
|---|
| 7 |
class InsultsClient(protocol.Protocol): |
|---|
| 8 |
|
|---|
| 9 |
escapeTimeout = 0.2 |
|---|
| 10 |
|
|---|
| 11 |
def __init__(self): |
|---|
| 12 |
self.width = self.height = None |
|---|
| 13 |
self.xpos = self.ypos = 0 |
|---|
| 14 |
self.commandQueue = [] |
|---|
| 15 |
self.inEscape = '' |
|---|
| 16 |
|
|---|
| 17 |
def setSize(self, width, height): |
|---|
| 18 |
call = 0 |
|---|
| 19 |
if self.width: |
|---|
| 20 |
call = 1 |
|---|
| 21 |
self.width = width |
|---|
| 22 |
self.height = height |
|---|
| 23 |
if call: |
|---|
| 24 |
self.windowSizeChanged() |
|---|
| 25 |
|
|---|
| 26 |
def dataReceived(self, data): |
|---|
| 27 |
from twisted.internet import reactor |
|---|
| 28 |
for ch in data: |
|---|
| 29 |
if ch == '\x1b': |
|---|
| 30 |
if self.inEscape: |
|---|
| 31 |
self.keyReceived(ch) |
|---|
| 32 |
self.inEscape = '' |
|---|
| 33 |
else: |
|---|
| 34 |
self.inEscape = ch |
|---|
| 35 |
self.escapeCall = reactor.callLater(self.escapeTimeout, |
|---|
| 36 |
self.endEscape) |
|---|
| 37 |
elif ch in 'ABCD' and self.inEscape: |
|---|
| 38 |
self.inEscape = '' |
|---|
| 39 |
self.escapeCall.cancel() |
|---|
| 40 |
if ch == 'A': |
|---|
| 41 |
self.keyReceived('<Up>') |
|---|
| 42 |
elif ch == 'B': |
|---|
| 43 |
self.keyReceived('<Down>') |
|---|
| 44 |
elif ch == 'C': |
|---|
| 45 |
self.keyReceived('<Right>') |
|---|
| 46 |
elif ch == 'D': |
|---|
| 47 |
self.keyReceived('<Left>') |
|---|
| 48 |
elif self.inEscape: |
|---|
| 49 |
self.inEscape += ch |
|---|
| 50 |
else: |
|---|
| 51 |
self.keyReceived(ch) |
|---|
| 52 |
|
|---|
| 53 |
def endEscape(self): |
|---|
| 54 |
ch = self.inEscape |
|---|
| 55 |
self.inEscape = '' |
|---|
| 56 |
self.keyReceived(ch) |
|---|
| 57 |
|
|---|
| 58 |
def initScreen(self): |
|---|
| 59 |
self.transport.write('\x1b=\x1b[?1h') |
|---|
| 60 |
|
|---|
| 61 |
def gotoXY(self, x, y): |
|---|
| 62 |
"""Go to a position on the screen. |
|---|
| 63 |
""" |
|---|
| 64 |
self.xpos = x |
|---|
| 65 |
self.ypos = y |
|---|
| 66 |
self.commandQueue.append(('gotoxy', x, y)) |
|---|
| 67 |
|
|---|
| 68 |
def writeCh(self, ch): |
|---|
| 69 |
"""Write a character to the screen. If we're at the end of the row, |
|---|
| 70 |
ignore the write. |
|---|
| 71 |
""" |
|---|
| 72 |
if self.xpos < self.width - 1: |
|---|
| 73 |
self.commandQueue.append(('write', ch)) |
|---|
| 74 |
self.xpos += 1 |
|---|
| 75 |
|
|---|
| 76 |
def writeStr(self, s): |
|---|
| 77 |
"""Write a string to the screen. This does not wrap a the edge of the |
|---|
| 78 |
screen, and stops at \\r and \\n. |
|---|
| 79 |
""" |
|---|
| 80 |
s = s[:self.width-self.xpos] |
|---|
| 81 |
if '\n' in s: |
|---|
| 82 |
s=s[:s.find('\n')] |
|---|
| 83 |
if '\r' in s: |
|---|
| 84 |
s=s[:s.find('\r')] |
|---|
| 85 |
self.commandQueue.append(('write', s)) |
|---|
| 86 |
self.xpos += len(s) |
|---|
| 87 |
|
|---|
| 88 |
def eraseToLine(self): |
|---|
| 89 |
"""Erase from the current position to the end of the line. |
|---|
| 90 |
""" |
|---|
| 91 |
self.commandQueue.append(('eraseeol',)) |
|---|
| 92 |
|
|---|
| 93 |
def eraseToScreen(self): |
|---|
| 94 |
"""Erase from the current position to the end of the screen. |
|---|
| 95 |
""" |
|---|
| 96 |
self.commandQueue.append(('eraseeos',)) |
|---|
| 97 |
|
|---|
| 98 |
def clearScreen(self): |
|---|
| 99 |
"""Clear the screen, and return the cursor to 0, 0. |
|---|
| 100 |
""" |
|---|
| 101 |
self.commandQueue = [('cls',)] |
|---|
| 102 |
self.xpos = self.ypos = 0 |
|---|
| 103 |
|
|---|
| 104 |
def setAttributes(self, *attrs): |
|---|
| 105 |
"""Set the attributes for drawing on the screen. |
|---|
| 106 |
""" |
|---|
| 107 |
self.commandQueue.append(('attributes', attrs)) |
|---|
| 108 |
|
|---|
| 109 |
def refresh(self): |
|---|
| 110 |
"""Redraw the screen. |
|---|
| 111 |
""" |
|---|
| 112 |
redraw = '' |
|---|
| 113 |
for command in self.commandQueue: |
|---|
| 114 |
if command[0] == 'gotoxy': |
|---|
| 115 |
redraw += '\x1b[%i;%iH' % (command[2]+1, command[1]+1) |
|---|
| 116 |
elif command[0] == 'write': |
|---|
| 117 |
redraw += command[1] |
|---|
| 118 |
elif command[0] == 'eraseeol': |
|---|
| 119 |
redraw += '\x1b[0K' |
|---|
| 120 |
elif command[0] == 'eraseeos': |
|---|
| 121 |
redraw += '\x1b[OJ' |
|---|
| 122 |
elif command[0] == 'cls': |
|---|
| 123 |
redraw += '\x1b[H\x1b[J' |
|---|
| 124 |
elif command[0] == 'attributes': |
|---|
| 125 |
redraw += '\x1b[%sm' % ';'.join(map(str, command[1])) |
|---|
| 126 |
else: |
|---|
| 127 |
print command |
|---|
| 128 |
self.commandQueue = [] |
|---|
| 129 |
self.transport.write(redraw) |
|---|
| 130 |
|
|---|
| 131 |
def windowSizeChanged(self): |
|---|
| 132 |
"""Called when the size of the window changes. |
|---|
| 133 |
Might want to redraw the screen here, or something. |
|---|
| 134 |
""" |
|---|
| 135 |
|
|---|
| 136 |
def keyReceived(self, key): |
|---|
| 137 |
"""Called when the user hits a key. |
|---|
| 138 |
""" |
|---|