| Index: third_party/twisted_8_1/twisted/conch/insults/window.py
 | 
| diff --git a/third_party/twisted_8_1/twisted/conch/insults/window.py b/third_party/twisted_8_1/twisted/conch/insults/window.py
 | 
| deleted file mode 100644
 | 
| index 51487f80d93ece6677621456a87c61e1b5d67d02..0000000000000000000000000000000000000000
 | 
| --- a/third_party/twisted_8_1/twisted/conch/insults/window.py
 | 
| +++ /dev/null
 | 
| @@ -1,864 +0,0 @@
 | 
| -# -*- test-case-name: twisted.conch.test.test_window -*-
 | 
| -
 | 
| -"""
 | 
| -Simple insults-based widget library
 | 
| -
 | 
| -@author: U{Jp Calderone<mailto:exarkun@twistedmatrix.com>}
 | 
| -"""
 | 
| -
 | 
| -import array
 | 
| -
 | 
| -from twisted.conch.insults import insults, helper
 | 
| -from twisted.python import text as tptext
 | 
| -
 | 
| -class YieldFocus(Exception):
 | 
| -    """Input focus manipulation exception
 | 
| -    """
 | 
| -
 | 
| -class BoundedTerminalWrapper(object):
 | 
| -    def __init__(self, terminal, width, height, xoff, yoff):
 | 
| -        self.width = width
 | 
| -        self.height = height
 | 
| -        self.xoff = xoff
 | 
| -        self.yoff = yoff
 | 
| -        self.terminal = terminal
 | 
| -        self.cursorForward = terminal.cursorForward
 | 
| -        self.selectCharacterSet = terminal.selectCharacterSet
 | 
| -        self.selectGraphicRendition = terminal.selectGraphicRendition
 | 
| -        self.saveCursor = terminal.saveCursor
 | 
| -        self.restoreCursor = terminal.restoreCursor
 | 
| -
 | 
| -    def cursorPosition(self, x, y):
 | 
| -        return self.terminal.cursorPosition(
 | 
| -            self.xoff + min(self.width, x),
 | 
| -            self.yoff + min(self.height, y)
 | 
| -            )
 | 
| -
 | 
| -    def cursorHome(self):
 | 
| -        return self.terminal.cursorPosition(
 | 
| -            self.xoff, self.yoff)
 | 
| -
 | 
| -    def write(self, bytes):
 | 
| -        return self.terminal.write(bytes)
 | 
| -
 | 
| -class Widget(object):
 | 
| -    focused = False
 | 
| -    parent = None
 | 
| -    dirty = False
 | 
| -    width = height = None
 | 
| -
 | 
| -    def repaint(self):
 | 
| -        if not self.dirty:
 | 
| -            self.dirty = True
 | 
| -        if self.parent is not None and not self.parent.dirty:
 | 
| -            self.parent.repaint()
 | 
| -
 | 
| -    def filthy(self):
 | 
| -        self.dirty = True
 | 
| -
 | 
| -    def redraw(self, width, height, terminal):
 | 
| -        self.filthy()
 | 
| -        self.draw(width, height, terminal)
 | 
| -
 | 
| -    def draw(self, width, height, terminal):
 | 
| -        if width != self.width or height != self.height or self.dirty:
 | 
| -            self.width = width
 | 
| -            self.height = height
 | 
| -            self.dirty = False
 | 
| -            self.render(width, height, terminal)
 | 
| -
 | 
| -    def render(self, width, height, terminal):
 | 
| -        pass
 | 
| -
 | 
| -    def sizeHint(self):
 | 
| -        return None
 | 
| -
 | 
| -    def keystrokeReceived(self, keyID, modifier):
 | 
| -        if keyID == '\t':
 | 
| -            self.tabReceived(modifier)
 | 
| -        elif keyID == '\x7f':
 | 
| -            self.backspaceReceived()
 | 
| -        elif keyID in insults.FUNCTION_KEYS:
 | 
| -            self.functionKeyReceived(keyID, modifier)
 | 
| -        else:
 | 
| -            self.characterReceived(keyID, modifier)
 | 
| -
 | 
| -    def tabReceived(self, modifier):
 | 
| -        # XXX TODO - Handle shift+tab
 | 
| -        raise YieldFocus()
 | 
| -
 | 
| -    def focusReceived(self):
 | 
| -        """Called when focus is being given to this widget.
 | 
| -
 | 
| -        May raise YieldFocus is this widget does not want focus.
 | 
| -        """
 | 
| -        self.focused = True
 | 
| -        self.repaint()
 | 
| -
 | 
| -    def focusLost(self):
 | 
| -        self.focused = False
 | 
| -        self.repaint()
 | 
| -
 | 
| -    def backspaceReceived(self):
 | 
| -        pass
 | 
| -
 | 
| -    def functionKeyReceived(self, keyID, modifier):
 | 
| -        func = getattr(self, 'func_' + keyID.name, None)
 | 
| -        if func is not None:
 | 
| -            func(modifier)
 | 
| -
 | 
| -    def characterReceived(self, keyID, modifier):
 | 
| -        pass
 | 
| -
 | 
| -class ContainerWidget(Widget):
 | 
| -    """
 | 
| -    @ivar focusedChild: The contained widget which currently has
 | 
| -    focus, or None.
 | 
| -    """
 | 
| -    focusedChild = None
 | 
| -    focused = False
 | 
| -
 | 
| -    def __init__(self):
 | 
| -        Widget.__init__(self)
 | 
| -        self.children = []
 | 
| -
 | 
| -    def addChild(self, child):
 | 
| -        assert child.parent is None
 | 
| -        child.parent = self
 | 
| -        self.children.append(child)
 | 
| -        if self.focusedChild is None and self.focused:
 | 
| -            try:
 | 
| -                child.focusReceived()
 | 
| -            except YieldFocus:
 | 
| -                pass
 | 
| -            else:
 | 
| -                self.focusedChild = child
 | 
| -        self.repaint()
 | 
| -
 | 
| -    def remChild(self, child):
 | 
| -        assert child.parent is self
 | 
| -        child.parent = None
 | 
| -        self.children.remove(child)
 | 
| -        self.repaint()
 | 
| -
 | 
| -    def filthy(self):
 | 
| -        for ch in self.children:
 | 
| -            ch.filthy()
 | 
| -        Widget.filthy(self)
 | 
| -
 | 
| -    def render(self, width, height, terminal):
 | 
| -        for ch in self.children:
 | 
| -            ch.draw(width, height, terminal)
 | 
| -
 | 
| -    def changeFocus(self):
 | 
| -        self.repaint()
 | 
| -
 | 
| -        if self.focusedChild is not None:
 | 
| -            self.focusedChild.focusLost()
 | 
| -            focusedChild = self.focusedChild
 | 
| -            self.focusedChild = None
 | 
| -            try:
 | 
| -                curFocus = self.children.index(focusedChild) + 1
 | 
| -            except ValueError:
 | 
| -                raise YieldFocus()
 | 
| -        else:
 | 
| -            curFocus = 0
 | 
| -        while curFocus < len(self.children):
 | 
| -            try:
 | 
| -                self.children[curFocus].focusReceived()
 | 
| -            except YieldFocus:
 | 
| -                curFocus += 1
 | 
| -            else:
 | 
| -                self.focusedChild = self.children[curFocus]
 | 
| -                return
 | 
| -        # None of our children wanted focus
 | 
| -        raise YieldFocus()
 | 
| -
 | 
| -
 | 
| -    def focusReceived(self):
 | 
| -        self.changeFocus()
 | 
| -        self.focused = True
 | 
| -
 | 
| -
 | 
| -    def keystrokeReceived(self, keyID, modifier):
 | 
| -        if self.focusedChild is not None:
 | 
| -            try:
 | 
| -                self.focusedChild.keystrokeReceived(keyID, modifier)
 | 
| -            except YieldFocus:
 | 
| -                self.changeFocus()
 | 
| -                self.repaint()
 | 
| -        else:
 | 
| -            Widget.keystrokeReceived(self, keyID, modifier)
 | 
| -
 | 
| -
 | 
| -class TopWindow(ContainerWidget):
 | 
| -    """
 | 
| -    A top-level container object which provides focus wrap-around and paint
 | 
| -    scheduling.
 | 
| -
 | 
| -    @ivar painter: A no-argument callable which will be invoked when this
 | 
| -    widget needs to be redrawn.
 | 
| -
 | 
| -    @ivar scheduler: A one-argument callable which will be invoked with a
 | 
| -    no-argument callable and should arrange for it to invoked at some point in
 | 
| -    the near future.  The no-argument callable will cause this widget and all
 | 
| -    its children to be redrawn.  It is typically beneficial for the no-argument
 | 
| -    callable to be invoked at the end of handling for whatever event is
 | 
| -    currently active; for example, it might make sense to call it at the end of
 | 
| -    L{twisted.conch.insults.insults.ITerminalProtocol.keystrokeReceived}.
 | 
| -    Note, however, that since calls to this may also be made in response to no
 | 
| -    apparent event, arrangements should be made for the function to be called
 | 
| -    even if an event handler such as C{keystrokeReceived} is not on the call
 | 
| -    stack (eg, using C{reactor.callLater} with a short timeout).
 | 
| -    """
 | 
| -    focused = True
 | 
| -
 | 
| -    def __init__(self, painter, scheduler):
 | 
| -        ContainerWidget.__init__(self)
 | 
| -        self.painter = painter
 | 
| -        self.scheduler = scheduler
 | 
| -
 | 
| -    _paintCall = None
 | 
| -    def repaint(self):
 | 
| -        if self._paintCall is None:
 | 
| -            self._paintCall = object()
 | 
| -            self.scheduler(self._paint)
 | 
| -        ContainerWidget.repaint(self)
 | 
| -
 | 
| -    def _paint(self):
 | 
| -        self._paintCall = None
 | 
| -        self.painter()
 | 
| -
 | 
| -    def changeFocus(self):
 | 
| -        try:
 | 
| -            ContainerWidget.changeFocus(self)
 | 
| -        except YieldFocus:
 | 
| -            try:
 | 
| -                ContainerWidget.changeFocus(self)
 | 
| -            except YieldFocus:
 | 
| -                pass
 | 
| -
 | 
| -    def keystrokeReceived(self, keyID, modifier):
 | 
| -        try:
 | 
| -            ContainerWidget.keystrokeReceived(self, keyID, modifier)
 | 
| -        except YieldFocus:
 | 
| -            self.changeFocus()
 | 
| -
 | 
| -
 | 
| -class AbsoluteBox(ContainerWidget):
 | 
| -    def moveChild(self, child, x, y):
 | 
| -        for n in range(len(self.children)):
 | 
| -            if self.children[n][0] is child:
 | 
| -                self.children[n] = (child, x, y)
 | 
| -                break
 | 
| -        else:
 | 
| -            raise ValueError("No such child", child)
 | 
| -
 | 
| -    def render(self, width, height, terminal):
 | 
| -        for (ch, x, y) in self.children:
 | 
| -            wrap = BoundedTerminalWrapper(terminal, width - x, height - y, x, y)
 | 
| -            ch.draw(width, height, wrap)
 | 
| -
 | 
| -
 | 
| -class _Box(ContainerWidget):
 | 
| -    TOP, CENTER, BOTTOM = range(3)
 | 
| -
 | 
| -    def __init__(self, gravity=CENTER):
 | 
| -        ContainerWidget.__init__(self)
 | 
| -        self.gravity = gravity
 | 
| -
 | 
| -    def sizeHint(self):
 | 
| -        height = 0
 | 
| -        width = 0
 | 
| -        for ch in self.children:
 | 
| -            hint = ch.sizeHint()
 | 
| -            if hint is None:
 | 
| -                hint = (None, None)
 | 
| -
 | 
| -            if self.variableDimension == 0:
 | 
| -                if hint[0] is None:
 | 
| -                    width = None
 | 
| -                elif width is not None:
 | 
| -                    width += hint[0]
 | 
| -                if hint[1] is None:
 | 
| -                    height = None
 | 
| -                elif height is not None:
 | 
| -                    height = max(height, hint[1])
 | 
| -            else:
 | 
| -                if hint[0] is None:
 | 
| -                    width = None
 | 
| -                elif width is not None:
 | 
| -                    width = max(width, hint[0])
 | 
| -                if hint[1] is None:
 | 
| -                    height = None
 | 
| -                elif height is not None:
 | 
| -                    height += hint[1]
 | 
| -
 | 
| -        return width, height
 | 
| -
 | 
| -
 | 
| -    def render(self, width, height, terminal):
 | 
| -        if not self.children:
 | 
| -            return
 | 
| -
 | 
| -        greedy = 0
 | 
| -        wants = []
 | 
| -        for ch in self.children:
 | 
| -            hint = ch.sizeHint()
 | 
| -            if hint is None:
 | 
| -                hint = (None, None)
 | 
| -            if hint[self.variableDimension] is None:
 | 
| -                greedy += 1
 | 
| -            wants.append(hint[self.variableDimension])
 | 
| -
 | 
| -        length = (width, height)[self.variableDimension]
 | 
| -        totalWant = sum([w for w in wants if w is not None])
 | 
| -        if greedy:
 | 
| -            leftForGreedy = int((length - totalWant) / greedy)
 | 
| -
 | 
| -        widthOffset = heightOffset = 0
 | 
| -
 | 
| -        for want, ch in zip(wants, self.children):
 | 
| -            if want is None:
 | 
| -                want = leftForGreedy
 | 
| -
 | 
| -            subWidth, subHeight = width, height
 | 
| -            if self.variableDimension == 0:
 | 
| -                subWidth = want
 | 
| -            else:
 | 
| -                subHeight = want
 | 
| -
 | 
| -            wrap = BoundedTerminalWrapper(
 | 
| -                terminal,
 | 
| -                subWidth,
 | 
| -                subHeight,
 | 
| -                widthOffset,
 | 
| -                heightOffset,
 | 
| -                )
 | 
| -            ch.draw(subWidth, subHeight, wrap)
 | 
| -            if self.variableDimension == 0:
 | 
| -                widthOffset += want
 | 
| -            else:
 | 
| -                heightOffset += want
 | 
| -
 | 
| -
 | 
| -class HBox(_Box):
 | 
| -    variableDimension = 0
 | 
| -
 | 
| -class VBox(_Box):
 | 
| -    variableDimension = 1
 | 
| -
 | 
| -
 | 
| -class Packer(ContainerWidget):
 | 
| -    def render(self, width, height, terminal):
 | 
| -        if not self.children:
 | 
| -            return
 | 
| -
 | 
| -        root = int(len(self.children) ** 0.5 + 0.5)
 | 
| -        boxes = [VBox() for n in range(root)]
 | 
| -        for n, ch in enumerate(self.children):
 | 
| -            boxes[n % len(boxes)].addChild(ch)
 | 
| -        h = HBox()
 | 
| -        map(h.addChild, boxes)
 | 
| -        h.render(width, height, terminal)
 | 
| -
 | 
| -
 | 
| -class Canvas(Widget):
 | 
| -    focused = False
 | 
| -
 | 
| -    contents = None
 | 
| -
 | 
| -    def __init__(self):
 | 
| -        Widget.__init__(self)
 | 
| -        self.resize(1, 1)
 | 
| -
 | 
| -    def resize(self, width, height):
 | 
| -        contents = array.array('c', ' ' * width * height)
 | 
| -        if self.contents is not None:
 | 
| -            for x in range(min(width, self._width)):
 | 
| -                for y in range(min(height, self._height)):
 | 
| -                    contents[width * y + x] = self[x, y]
 | 
| -        self.contents = contents
 | 
| -        self._width = width
 | 
| -        self._height = height
 | 
| -        if self.x >= width:
 | 
| -            self.x = width - 1
 | 
| -        if self.y >= height:
 | 
| -            self.y = height - 1
 | 
| -
 | 
| -    def __getitem__(self, (x, y)):
 | 
| -        return self.contents[(self._width * y) + x]
 | 
| -
 | 
| -    def __setitem__(self, (x, y), value):
 | 
| -        self.contents[(self._width * y) + x] = value
 | 
| -
 | 
| -    def clear(self):
 | 
| -        self.contents = array.array('c', ' ' * len(self.contents))
 | 
| -
 | 
| -    def render(self, width, height, terminal):
 | 
| -        if not width or not height:
 | 
| -            return
 | 
| -
 | 
| -        if width != self._width or height != self._height:
 | 
| -            self.resize(width, height)
 | 
| -        for i in range(height):
 | 
| -            terminal.cursorPosition(0, i)
 | 
| -            terminal.write(''.join(self.contents[self._width * i:self._width * i + self._width])[:width])
 | 
| -
 | 
| -
 | 
| -def horizontalLine(terminal, y, left, right):
 | 
| -    terminal.selectCharacterSet(insults.CS_DRAWING, insults.G0)
 | 
| -    terminal.cursorPosition(left, y)
 | 
| -    terminal.write(chr(0161) * (right - left))
 | 
| -    terminal.selectCharacterSet(insults.CS_US, insults.G0)
 | 
| -
 | 
| -def verticalLine(terminal, x, top, bottom):
 | 
| -    terminal.selectCharacterSet(insults.CS_DRAWING, insults.G0)
 | 
| -    for n in xrange(top, bottom):
 | 
| -        terminal.cursorPosition(x, n)
 | 
| -        terminal.write(chr(0170))
 | 
| -    terminal.selectCharacterSet(insults.CS_US, insults.G0)
 | 
| -
 | 
| -
 | 
| -def rectangle(terminal, (top, left), (width, height)):
 | 
| -    terminal.selectCharacterSet(insults.CS_DRAWING, insults.G0)
 | 
| -
 | 
| -    terminal.cursorPosition(top, left)
 | 
| -    terminal.write(chr(0154))
 | 
| -    terminal.write(chr(0161) * (width - 2))
 | 
| -    terminal.write(chr(0153))
 | 
| -    for n in range(height - 2):
 | 
| -        terminal.cursorPosition(left, top + n + 1)
 | 
| -        terminal.write(chr(0170))
 | 
| -        terminal.cursorForward(width - 2)
 | 
| -        terminal.write(chr(0170))
 | 
| -    terminal.cursorPosition(0, top + height - 1)
 | 
| -    terminal.write(chr(0155))
 | 
| -    terminal.write(chr(0161) * (width - 2))
 | 
| -    terminal.write(chr(0152))
 | 
| -
 | 
| -    terminal.selectCharacterSet(insults.CS_US, insults.G0)
 | 
| -
 | 
| -class Border(Widget):
 | 
| -    def __init__(self, containee):
 | 
| -        Widget.__init__(self)
 | 
| -        self.containee = containee
 | 
| -        self.containee.parent = self
 | 
| -
 | 
| -    def focusReceived(self):
 | 
| -        return self.containee.focusReceived()
 | 
| -
 | 
| -    def focusLost(self):
 | 
| -        return self.containee.focusLost()
 | 
| -
 | 
| -    def keystrokeReceived(self, keyID, modifier):
 | 
| -        return self.containee.keystrokeReceived(keyID, modifier)
 | 
| -
 | 
| -    def sizeHint(self):
 | 
| -        hint = self.containee.sizeHint()
 | 
| -        if hint is None:
 | 
| -            hint = (None, None)
 | 
| -        if hint[0] is None:
 | 
| -            x = None
 | 
| -        else:
 | 
| -            x = hint[0] + 2
 | 
| -        if hint[1] is None:
 | 
| -            y = None
 | 
| -        else:
 | 
| -            y = hint[1] + 2
 | 
| -        return x, y
 | 
| -
 | 
| -    def filthy(self):
 | 
| -        self.containee.filthy()
 | 
| -        Widget.filthy(self)
 | 
| -
 | 
| -    def render(self, width, height, terminal):
 | 
| -        if self.containee.focused:
 | 
| -            terminal.write('\x1b[31m')
 | 
| -        rectangle(terminal, (0, 0), (width, height))
 | 
| -        terminal.write('\x1b[0m')
 | 
| -        wrap = BoundedTerminalWrapper(terminal, width - 2, height - 2, 1, 1)
 | 
| -        self.containee.draw(width - 2, height - 2, wrap)
 | 
| -
 | 
| -
 | 
| -class Button(Widget):
 | 
| -    def __init__(self, label, onPress):
 | 
| -        Widget.__init__(self)
 | 
| -        self.label = label
 | 
| -        self.onPress = onPress
 | 
| -
 | 
| -    def sizeHint(self):
 | 
| -        return len(self.label), 1
 | 
| -
 | 
| -    def characterReceived(self, keyID, modifier):
 | 
| -        if keyID == '\r':
 | 
| -            self.onPress()
 | 
| -
 | 
| -    def render(self, width, height, terminal):
 | 
| -        terminal.cursorPosition(0, 0)
 | 
| -        if self.focused:
 | 
| -            terminal.write('\x1b[1m' + self.label + '\x1b[0m')
 | 
| -        else:
 | 
| -            terminal.write(self.label)
 | 
| -
 | 
| -class TextInput(Widget):
 | 
| -    def __init__(self, maxwidth, onSubmit):
 | 
| -        Widget.__init__(self)
 | 
| -        self.onSubmit = onSubmit
 | 
| -        self.maxwidth = maxwidth
 | 
| -        self.buffer = ''
 | 
| -        self.cursor = 0
 | 
| -
 | 
| -    def setText(self, text):
 | 
| -        self.buffer = text[:self.maxwidth]
 | 
| -        self.cursor = len(self.buffer)
 | 
| -        self.repaint()
 | 
| -
 | 
| -    def func_LEFT_ARROW(self, modifier):
 | 
| -        if self.cursor > 0:
 | 
| -            self.cursor -= 1
 | 
| -            self.repaint()
 | 
| -
 | 
| -    def func_RIGHT_ARROW(self, modifier):
 | 
| -        if self.cursor < len(self.buffer):
 | 
| -            self.cursor += 1
 | 
| -            self.repaint()
 | 
| -
 | 
| -    def backspaceReceived(self):
 | 
| -        if self.cursor > 0:
 | 
| -            self.buffer = self.buffer[:self.cursor - 1] + self.buffer[self.cursor:]
 | 
| -            self.cursor -= 1
 | 
| -            self.repaint()
 | 
| -
 | 
| -    def characterReceived(self, keyID, modifier):
 | 
| -        if keyID == '\r':
 | 
| -            self.onSubmit(self.buffer)
 | 
| -        else:
 | 
| -            if len(self.buffer) < self.maxwidth:
 | 
| -                self.buffer = self.buffer[:self.cursor] + keyID + self.buffer[self.cursor:]
 | 
| -                self.cursor += 1
 | 
| -                self.repaint()
 | 
| -
 | 
| -    def sizeHint(self):
 | 
| -        return self.maxwidth + 1, 1
 | 
| -
 | 
| -    def render(self, width, height, terminal):
 | 
| -        currentText = self._renderText()
 | 
| -        terminal.cursorPosition(0, 0)
 | 
| -        if self.focused:
 | 
| -            terminal.write(currentText[:self.cursor])
 | 
| -            cursor(terminal, currentText[self.cursor:self.cursor+1] or ' ')
 | 
| -            terminal.write(currentText[self.cursor+1:])
 | 
| -            terminal.write(' ' * (self.maxwidth - len(currentText) + 1))
 | 
| -        else:
 | 
| -            more = self.maxwidth - len(currentText)
 | 
| -            terminal.write(currentText + '_' * more)
 | 
| -
 | 
| -    def _renderText(self):
 | 
| -        return self.buffer
 | 
| -
 | 
| -class PasswordInput(TextInput):
 | 
| -    def _renderText(self):
 | 
| -        return '*' * len(self.buffer)
 | 
| -
 | 
| -class TextOutput(Widget):
 | 
| -    text = ''
 | 
| -
 | 
| -    def __init__(self, size=None):
 | 
| -        Widget.__init__(self)
 | 
| -        self.size = size
 | 
| -
 | 
| -    def sizeHint(self):
 | 
| -        return self.size
 | 
| -
 | 
| -    def render(self, width, height, terminal):
 | 
| -        terminal.cursorPosition(0, 0)
 | 
| -        text = self.text[:width]
 | 
| -        terminal.write(text + ' ' * (width - len(text)))
 | 
| -
 | 
| -    def setText(self, text):
 | 
| -        self.text = text
 | 
| -        self.repaint()
 | 
| -
 | 
| -    def focusReceived(self):
 | 
| -        raise YieldFocus()
 | 
| -
 | 
| -class TextOutputArea(TextOutput):
 | 
| -    WRAP, TRUNCATE = range(2)
 | 
| -
 | 
| -    def __init__(self, size=None, longLines=WRAP):
 | 
| -        TextOutput.__init__(self, size)
 | 
| -        self.longLines = longLines
 | 
| -
 | 
| -    def render(self, width, height, terminal):
 | 
| -        n = 0
 | 
| -        inputLines = self.text.splitlines()
 | 
| -        outputLines = []
 | 
| -        while inputLines:
 | 
| -            if self.longLines == self.WRAP:
 | 
| -                wrappedLines = tptext.greedyWrap(inputLines.pop(0), width)
 | 
| -                outputLines.extend(wrappedLines or [''])
 | 
| -            else:
 | 
| -                outputLines.append(inputLines.pop(0)[:width])
 | 
| -            if len(outputLines) >= height:
 | 
| -                break
 | 
| -        for n, L in enumerate(outputLines[:height]):
 | 
| -            terminal.cursorPosition(0, n)
 | 
| -            terminal.write(L)
 | 
| -
 | 
| -class Viewport(Widget):
 | 
| -    _xOffset = 0
 | 
| -    _yOffset = 0
 | 
| -
 | 
| -    def xOffset():
 | 
| -        def get(self):
 | 
| -            return self._xOffset
 | 
| -        def set(self, value):
 | 
| -            if self._xOffset != value:
 | 
| -                self._xOffset = value
 | 
| -                self.repaint()
 | 
| -        return get, set
 | 
| -    xOffset = property(*xOffset())
 | 
| -
 | 
| -    def yOffset():
 | 
| -        def get(self):
 | 
| -            return self._yOffset
 | 
| -        def set(self, value):
 | 
| -            if self._yOffset != value:
 | 
| -                self._yOffset = value
 | 
| -                self.repaint()
 | 
| -        return get, set
 | 
| -    yOffset = property(*yOffset())
 | 
| -
 | 
| -    _width = 160
 | 
| -    _height = 24
 | 
| -
 | 
| -    def __init__(self, containee):
 | 
| -        Widget.__init__(self)
 | 
| -        self.containee = containee
 | 
| -        self.containee.parent = self
 | 
| -
 | 
| -        self._buf = helper.TerminalBuffer()
 | 
| -        self._buf.width = self._width
 | 
| -        self._buf.height = self._height
 | 
| -        self._buf.connectionMade()
 | 
| -
 | 
| -    def filthy(self):
 | 
| -        self.containee.filthy()
 | 
| -        Widget.filthy(self)
 | 
| -
 | 
| -    def render(self, width, height, terminal):
 | 
| -        self.containee.draw(self._width, self._height, self._buf)
 | 
| -
 | 
| -        # XXX /Lame/
 | 
| -        for y, line in enumerate(self._buf.lines[self._yOffset:self._yOffset + height]):
 | 
| -            terminal.cursorPosition(0, y)
 | 
| -            n = 0
 | 
| -            for n, (ch, attr) in enumerate(line[self._xOffset:self._xOffset + width]):
 | 
| -                if ch is self._buf.void:
 | 
| -                    ch = ' '
 | 
| -                terminal.write(ch)
 | 
| -            if n < width:
 | 
| -                terminal.write(' ' * (width - n - 1))
 | 
| -
 | 
| -
 | 
| -class _Scrollbar(Widget):
 | 
| -    def __init__(self, onScroll):
 | 
| -        Widget.__init__(self)
 | 
| -        self.onScroll = onScroll
 | 
| -        self.percent = 0.0
 | 
| -
 | 
| -    def smaller(self):
 | 
| -        self.percent = min(1.0, max(0.0, self.onScroll(-1)))
 | 
| -        self.repaint()
 | 
| -
 | 
| -    def bigger(self):
 | 
| -        self.percent = min(1.0, max(0.0, self.onScroll(+1)))
 | 
| -        self.repaint()
 | 
| -
 | 
| -
 | 
| -class HorizontalScrollbar(_Scrollbar):
 | 
| -    def sizeHint(self):
 | 
| -        return (None, 1)
 | 
| -
 | 
| -    def func_LEFT_ARROW(self, modifier):
 | 
| -        self.smaller()
 | 
| -
 | 
| -    def func_RIGHT_ARROW(self, modifier):
 | 
| -        self.bigger()
 | 
| -
 | 
| -    _left = u'\N{BLACK LEFT-POINTING TRIANGLE}'
 | 
| -    _right = u'\N{BLACK RIGHT-POINTING TRIANGLE}'
 | 
| -    _bar = u'\N{LIGHT SHADE}'
 | 
| -    _slider = u'\N{DARK SHADE}'
 | 
| -    def render(self, width, height, terminal):
 | 
| -        terminal.cursorPosition(0, 0)
 | 
| -        n = width - 3
 | 
| -        before = int(n * self.percent)
 | 
| -        after = n - before
 | 
| -        me = self._left + (self._bar * before) + self._slider + (self._bar * after) + self._right
 | 
| -        terminal.write(me.encode('utf-8'))
 | 
| -
 | 
| -
 | 
| -class VerticalScrollbar(_Scrollbar):
 | 
| -    def sizeHint(self):
 | 
| -        return (1, None)
 | 
| -
 | 
| -    def func_UP_ARROW(self, modifier):
 | 
| -        self.smaller()
 | 
| -
 | 
| -    def func_DOWN_ARROW(self, modifier):
 | 
| -        self.bigger()
 | 
| -
 | 
| -    _up = u'\N{BLACK UP-POINTING TRIANGLE}'
 | 
| -    _down = u'\N{BLACK DOWN-POINTING TRIANGLE}'
 | 
| -    _bar = u'\N{LIGHT SHADE}'
 | 
| -    _slider = u'\N{DARK SHADE}'
 | 
| -    def render(self, width, height, terminal):
 | 
| -        terminal.cursorPosition(0, 0)
 | 
| -        knob = int(self.percent * (height - 2))
 | 
| -        terminal.write(self._up.encode('utf-8'))
 | 
| -        for i in xrange(1, height - 1):
 | 
| -            terminal.cursorPosition(0, i)
 | 
| -            if i != (knob + 1):
 | 
| -                terminal.write(self._bar.encode('utf-8'))
 | 
| -            else:
 | 
| -                terminal.write(self._slider.encode('utf-8'))
 | 
| -        terminal.cursorPosition(0, height - 1)
 | 
| -        terminal.write(self._down.encode('utf-8'))
 | 
| -
 | 
| -
 | 
| -class ScrolledArea(Widget):
 | 
| -    def __init__(self, containee):
 | 
| -        Widget.__init__(self, containee)
 | 
| -        self._viewport = Viewport(containee)
 | 
| -        self._horiz = HorizontalScrollbar(self._horizScroll)
 | 
| -        self._vert = VerticalScrollbar(self._vertScroll)
 | 
| -
 | 
| -        for w in self._viewport, self._horiz, self._vert:
 | 
| -            w.parent = self
 | 
| -
 | 
| -    def _horizScroll(self, n):
 | 
| -        self._viewport.xOffset += n
 | 
| -        self._viewport.xOffset = max(0, self._viewport.xOffset)
 | 
| -        return self._viewport.xOffset / 25.0
 | 
| -
 | 
| -    def _vertScroll(self, n):
 | 
| -        self._viewport.yOffset += n
 | 
| -        self._viewport.yOffset = max(0, self._viewport.yOffset)
 | 
| -        return self._viewport.yOffset / 25.0
 | 
| -
 | 
| -    def func_UP_ARROW(self, modifier):
 | 
| -        self._vert.smaller()
 | 
| -
 | 
| -    def func_DOWN_ARROW(self, modifier):
 | 
| -        self._vert.bigger()
 | 
| -
 | 
| -    def func_LEFT_ARROW(self, modifier):
 | 
| -        self._horiz.smaller()
 | 
| -
 | 
| -    def func_RIGHT_ARROW(self, modifier):
 | 
| -        self._horiz.bigger()
 | 
| -
 | 
| -    def filthy(self):
 | 
| -        self._viewport.filthy()
 | 
| -        self._horiz.filthy()
 | 
| -        self._vert.filthy()
 | 
| -        Widget.filthy(self)
 | 
| -
 | 
| -    def render(self, width, height, terminal):
 | 
| -        wrapper = BoundedTerminalWrapper(terminal, width - 2, height - 2, 1, 1)
 | 
| -        self._viewport.draw(width - 2, height - 2, wrapper)
 | 
| -        if self.focused:
 | 
| -            terminal.write('\x1b[31m')
 | 
| -        horizontalLine(terminal, 0, 1, width - 1)
 | 
| -        verticalLine(terminal, 0, 1, height - 1)
 | 
| -        self._vert.draw(1, height - 1, BoundedTerminalWrapper(terminal, 1, height - 1, width - 1, 0))
 | 
| -        self._horiz.draw(width, 1, BoundedTerminalWrapper(terminal, width, 1, 0, height - 1))
 | 
| -        terminal.write('\x1b[0m')
 | 
| -
 | 
| -def cursor(terminal, ch):
 | 
| -    terminal.saveCursor()
 | 
| -    terminal.selectGraphicRendition(str(insults.REVERSE_VIDEO))
 | 
| -    terminal.write(ch)
 | 
| -    terminal.restoreCursor()
 | 
| -    terminal.cursorForward()
 | 
| -
 | 
| -class Selection(Widget):
 | 
| -    # Index into the sequence
 | 
| -    focusedIndex = 0
 | 
| -
 | 
| -    # Offset into the displayed subset of the sequence
 | 
| -    renderOffset = 0
 | 
| -
 | 
| -    def __init__(self, sequence, onSelect, minVisible=None):
 | 
| -        Widget.__init__(self)
 | 
| -        self.sequence = sequence
 | 
| -        self.onSelect = onSelect
 | 
| -        self.minVisible = minVisible
 | 
| -        if minVisible is not None:
 | 
| -            self._width = max(map(len, self.sequence))
 | 
| -
 | 
| -    def sizeHint(self):
 | 
| -        if self.minVisible is not None:
 | 
| -            return self._width, self.minVisible
 | 
| -
 | 
| -    def func_UP_ARROW(self, modifier):
 | 
| -        if self.focusedIndex > 0:
 | 
| -            self.focusedIndex -= 1
 | 
| -            if self.renderOffset > 0:
 | 
| -                self.renderOffset -= 1
 | 
| -            self.repaint()
 | 
| -
 | 
| -    def func_PGUP(self, modifier):
 | 
| -        if self.renderOffset != 0:
 | 
| -            self.focusedIndex -= self.renderOffset
 | 
| -            self.renderOffset = 0
 | 
| -        else:
 | 
| -            self.focusedIndex = max(0, self.focusedIndex - self.height)
 | 
| -        self.repaint()
 | 
| -
 | 
| -    def func_DOWN_ARROW(self, modifier):
 | 
| -        if self.focusedIndex < len(self.sequence) - 1:
 | 
| -            self.focusedIndex += 1
 | 
| -            if self.renderOffset < self.height - 1:
 | 
| -                self.renderOffset += 1
 | 
| -            self.repaint()
 | 
| -
 | 
| -
 | 
| -    def func_PGDN(self, modifier):
 | 
| -        if self.renderOffset != self.height - 1:
 | 
| -            change = self.height - self.renderOffset - 1
 | 
| -            if change + self.focusedIndex >= len(self.sequence):
 | 
| -                change = len(self.sequence) - self.focusedIndex - 1
 | 
| -            self.focusedIndex += change
 | 
| -            self.renderOffset = self.height - 1
 | 
| -        else:
 | 
| -            self.focusedIndex = min(len(self.sequence) - 1, self.focusedIndex + self.height)
 | 
| -        self.repaint()
 | 
| -
 | 
| -    def characterReceived(self, keyID, modifier):
 | 
| -        if keyID == '\r':
 | 
| -            self.onSelect(self.sequence[self.focusedIndex])
 | 
| -
 | 
| -    def render(self, width, height, terminal):
 | 
| -        self.height = height
 | 
| -        start = self.focusedIndex - self.renderOffset
 | 
| -        if start > len(self.sequence) - height:
 | 
| -            start = max(0, len(self.sequence) - height)
 | 
| -
 | 
| -        elements = self.sequence[start:start+height]
 | 
| -
 | 
| -        for n, ele in enumerate(elements):
 | 
| -            terminal.cursorPosition(0, n)
 | 
| -            if n == self.renderOffset:
 | 
| -                terminal.saveCursor()
 | 
| -                if self.focused:
 | 
| -                    modes = str(insults.REVERSE_VIDEO), str(insults.BOLD)
 | 
| -                else:
 | 
| -                    modes = str(insults.REVERSE_VIDEO),
 | 
| -                terminal.selectGraphicRendition(*modes)
 | 
| -            text = ele[:width]
 | 
| -            terminal.write(text + (' ' * (width - len(text))))
 | 
| -            if n == self.renderOffset:
 | 
| -                terminal.restoreCursor()
 | 
| 
 |