def __init__(self, text=None, attr=None, cs=None, cursor=None, maxcol=None, check_width=True): """ text -- list of strings, one for each line attr -- list of run length encoded attributes for text cs -- list of run length encoded character set for text cursor -- (x,y) of cursor or None maxcol -- screen columns taken by this canvas check_width -- check and fix width of all lines in text """ Canvas.__init__(self) if text == None: text = [] if check_width: widths = [] for t in text: if type(t) != type(""): raise CanvasError("Canvas text must be plain strings encoded in the screen's encoding", `text`) widths.append( calc_width( t, 0, len(t)) ) else: assert type(maxcol) == type(0) widths = [maxcol] * len(text) if maxcol is None: if widths: # find maxcol ourselves maxcol = max(widths) else: maxcol = 0 if attr == None: attr = [[] for x in range(len(text))] if cs == None: cs = [[] for x in range(len(text))] # pad text and attr to maxcol for i in range(len(text)): w = widths[i] if w > maxcol: raise CanvasError("Canvas text is wider than the maxcol specified \n%s\n%s\n%s"%(`maxcol`,`widths`,`text`)) if w < maxcol: text[i] = text[i] + " "*(maxcol-w) a_gap = len(text[i]) - rle_len( attr[i] ) if a_gap < 0: raise CanvasError("Attribute extends beyond text \n%s\n%s" % (`text[i]`,`attr[i]`) ) if a_gap: rle_append_modify( attr[i], (None, a_gap)) cs_gap = len(text[i]) - rle_len( cs[i] ) if cs_gap < 0: raise CanvasError("Character Set extends beyond text \n%s\n%s" % (`text[i]`,`cs[i]`) ) if cs_gap: rle_append_modify( cs[i], (None, cs_gap)) self._attr = attr self._cs = cs self.cursor = cursor self._text = text self._maxcol = maxcol
def attrrange( start_offs, end_offs, destw ): """ Add attributes based on attributes between start_offs and end_offs. """ if start_offs == end_offs: [(at,run)] = arange(start_offs,end_offs) rle_append_modify( linea, ( at, destw )) return if destw == end_offs-start_offs: for at, run in arange(start_offs,end_offs): rle_append_modify( linea, ( at, run )) return # encoded version has different width o = start_offs for at, run in arange(start_offs, end_offs): if o+run == end_offs: rle_append_modify( linea, ( at, destw )) return tseg = text[o:o+run] tseg, cs = apply_target_encoding( tseg ) segw = rle_len(cs) rle_append_modify( linea, ( at, segw )) o += run destw -= segw
def apply_text_layout(text, attr, ls, maxcol): t = [] a = [] c = [] class AttrWalk: pass aw = AttrWalk aw.k = 0 # counter for moving through elements of a aw.off = 0 # current offset into text of attr[ak] def arange( start_offs, end_offs ): """Return an attribute list for the range of text specified.""" if start_offs < aw.off: aw.k = 0 aw.off = 0 o = [] while aw.off < end_offs: if len(attr)<=aw.k: # run out of attributes o.append((None,end_offs-max(start_offs,aw.off))) break at,run = attr[aw.k] if aw.off+run <= start_offs: # move forward through attr to find start_offs aw.k += 1 aw.off += run continue if end_offs <= aw.off+run: o.append((at, end_offs-max(start_offs,aw.off))) break o.append((at, aw.off+run-max(start_offs, aw.off))) aw.k += 1 aw.off += run return o for line_layout in ls: # trim the line to fit within maxcol line_layout = trim_line( line_layout, text, 0, maxcol ) line = [] linea = [] linec = [] def attrrange( start_offs, end_offs, destw ): """ Add attributes based on attributes between start_offs and end_offs. """ if start_offs == end_offs: [(at,run)] = arange(start_offs,end_offs) rle_append_modify( linea, ( at, destw )) return if destw == end_offs-start_offs: for at, run in arange(start_offs,end_offs): rle_append_modify( linea, ( at, run )) return # encoded version has different width o = start_offs for at, run in arange(start_offs, end_offs): if o+run == end_offs: rle_append_modify( linea, ( at, destw )) return tseg = text[o:o+run] tseg, cs = apply_target_encoding( tseg ) segw = rle_len(cs) rle_append_modify( linea, ( at, segw )) o += run destw -= segw for seg in line_layout: #if seg is None: assert 0, ls s = LayoutSegment(seg) if s.end: tseg, cs = apply_target_encoding( text[s.offs:s.end]) line.append(tseg) attrrange(s.offs, s.end, rle_len(cs)) rle_join_modify( linec, cs ) elif s.text: tseg, cs = apply_target_encoding( s.text ) line.append(tseg) attrrange( s.offs, s.offs, len(tseg) ) rle_join_modify( linec, cs ) elif s.offs: if s.sc: line.append(" "*s.sc) attrrange( s.offs, s.offs, s.sc ) else: line.append(" "*s.sc) linea.append((None, s.sc)) linec.append((None, s.sc)) t.append("".join(line)) a.append(linea) c.append(linec) return TextCanvas(t, a, c, maxcol=maxcol)