serio:ty06pr00id00ex00
  "   li~e8Yn2oh      13:0
  :   lm_JJh Ȯ2oyai~e8Z.6ژo ?     """SS1 -- a spreadsheet."""

import os
import re
import sys
import cgi
import rexec
from xml.parsers import expat

LEFT, CENTER, RIGHT = "LEFT", "CENTER", "RIGHT"

def ljust(x, n):
    return x.ljust(n)
def center(x, n):
    return x.center(n)
def rjust(x, n):
    return x.rjust(n)
align2action = {LEFT: ljust, CENTER: center, RIGHT: rjust}

align2xml = {LEFT: "left", CENTER: "center", RIGHT: "right"}
xml2align = {"left": LEFT, "center": CENTER, "right": RIGHT}

align2anchor = {LEFT: "w", CENTER: "center", RIGHT: "e"}

def sum(seq):
    total = 0
    for x in seq:
        if x is not None:
            total += x
    return total

class Sheet:

    def __init__(self):
        self.cells = {} # {(x, y): cell, ...}
        self.rexec = rexec.RExec()
        m = self.rexec.add_module('__main__')
        m.cell = self.cellvalue
        m.cells = self.multicellvalue
        m.sum = sum

    def cellvalue(self, x, y):
        cell = self.getcell(x, y)
        if hasattr(cell, 'recalc'):
            return cell.recalc(self.rexec)
        else:
            return cell

    def multicellvalue(self, x1, y1, x2, y2):
        if x1 > x2:
            x1, x2 = x2, x1
        if y1 > y2:
            y1, y2 = y2, y1
        seq = []
        for y in range(y1, y2+1):
            for x in range(x1, x2+1):
                seq.append(self.cellvalue(x, y))
        return seq

    def getcell(self, x, y):
        return self.cells.get((x, y))

    def setcell(self, x, y, cell):
        assert x > 0 and y > 0
        assert isinstance(cell, BaseCell)
        self.cells[x, y] = cell

    def clearcell(self, x, y):
        try:
            del self.cells[x, y]
        except KeyError:
            pass

    def clearcells(self, x1, y1, x2, y2):
        for xy in self.selectcells(x1, y1, x2, y2):
            del self.cells[xy]

    def clearrows(self, y1, y2):
        self.clearcells(0, y1, sys.maxint, y2)

    def clearcolumns(self, x1, x2):
        self.clearcells(x1, 0, x2, sys.maxint)

    def selectcells(self, x1, y1, x2, y2):
        if x1 > x2:
            x1, x2 = x2, x1
        if y1 > y2:
            y1, y2 = y2, y1
        return [(x, y) for x, y in self.cells
                if x1 <= x <= x2 and y1 <= y <= y2]

    def movecells(self, x1, y1, x2, y2, dx, dy):
        if dx == 0 and dy == 0:
            return
        if x1 > x2:
            x1, x2 = x2, x1
        if y1 > y2:
            y1, y2 = y2, y1
        assert x1+dx > 0 and y1+dy > 0
        new = {}
        for x, y in self.cells:
            cell = self.cells[x, y]
            if hasattr(cell, 'renumber'):
                cell = cell.renumber(x1, y1, x2, y2, dx, dy)
            if x1 <= x <= x2 and y1 <= y <= y2:
                x += dx
                y += dy
            new[x, y] = cell
        self.cells = new

    def insertrows(self, y, n):
        assert n > 0
        self.movecells(0, y, sys.maxint, sys.maxint, 0, n)

    def deleterows(self, y1, y2):
        if y1 > y2:
            y1, y2 = y2, y1
        self.clearrows(y1, y2)
        self.movecells(0, y2+1, sys.maxint, sys.maxint, 0, y1-y2-1)

    def insertcolumns(self, x, n):
        assert n > 0
        self.movecells(x, 0, sys.maxint, sys.maxint, n, 0)

    def deletecolumns(self, x1, x2):
        if x1 > x2:
            x1, x2 = x2, x1
        self.clearcells(x1, x2)
        self.movecells(x2+1, 0, sys.maxint, sys.maxint, x1-x2-1, 0)

    def getsize(self):
        maxx = maxy = 0
        for x, y in self.cells:
            maxx = max(maxx, x)
            maxy = max(maxy, y)
        return maxx, maxy

    def reset(self):
        for cell in self.cells.itervalues():
            if hasattr(cell, 'reset'):
                cell.reset()

    def recalc(self):
        self.reset()
        for cell in self.cells.itervalues():
            if hasattr(cell, 'recalc'):
                cell.recalc(self.rexec)

    def display(self):
        maxx, maxy = self.getsize()
  