Esempio n. 1
0
def calc_line_pos( text, line_layout, pref_col ):
    """
    Calculate the closest linear position to pref_col given a
    line layout structure.  Returns None if no position found.
    """
    closest_sc = None
    closest_pos = None
    current_sc = 0

    if pref_col == 'left':
        for seg in line_layout:
            s = LayoutSegment(seg)
            if s.offs is not None:
                return s.offs
        return
    elif pref_col == 'right':
        for seg in line_layout:
            s = LayoutSegment(seg)
            if s.offs is not None:
                closest_pos = s
        s = closest_pos
        if s is None:
            return
        if s.end is None:
            return s.offs
        return calc_text_pos( text, s.offs, s.end, s.sc-1)[0]

    for seg in line_layout:
        s = LayoutSegment(seg)
        if s.offs is not None:
            if s.end is not None:
                if (current_sc <= pref_col and 
                    pref_col < current_sc + s.sc):
                    # exact match within this segment
                    return calc_text_pos( text, 
                        s.offs, s.end,
                        pref_col - current_sc )[0]
                elif current_sc <= pref_col:
                    closest_sc = current_sc + s.sc - 1
                    closest_pos = s
                    
            if closest_sc is None or ( abs(pref_col-current_sc)
                    < abs(pref_col-closest_sc) ):
                # this screen column is closer
                closest_sc = current_sc
                closest_pos = s.offs
            if current_sc > closest_sc:
                # we're moving past
                break
        current_sc += s.sc
    
    if closest_pos is None or type(closest_pos) == type(0):
        return closest_pos

    # return the last positions in the segment "closest_pos"
    s = closest_pos
    return calc_text_pos( text, s.offs, s.end, s.sc-1)[0]
Esempio n. 2
0
def html_span(s, aspec, cursor=-1):
    fg_r, fg_g, fg_b, bg_r, bg_g, bg_b = aspec.get_rgb_values()
    # use real colours instead of default fg/bg
    if fg_r is None:
        fg_r, fg_g, fg_b = _d_fg_r, _d_fg_g, _d_fg_b
    if bg_r is None:
        bg_r, bg_g, bg_b = _d_bg_r, _d_bg_g, _d_bg_b
    html_fg = "#%02x%02x%02x" % (fg_r, fg_g, fg_b)
    html_bg = "#%02x%02x%02x" % (bg_r, bg_g, bg_b)
    if aspec.standout:
        html_fg, html_bg = html_bg, html_fg
    extra = (";text-decoration:underline" * aspec.underline +
             ";font-weight:bold" * aspec.bold)

    def html_span(fg, bg, s):
        if not s: return ""
        return ('<span style="color:%s;'
                'background:%s%s">%s</span>' % (fg, bg, extra, html_escape(s)))

    if cursor >= 0:
        c_off, _ign = util.calc_text_pos(s, 0, len(s), cursor)
        c2_off = util.move_next_char(s, c_off, len(s))
        return (html_span(html_fg, html_bg, s[:c_off]) +
                html_span(html_bg, html_fg, s[c_off:c2_off]) +
                html_span(html_fg, html_bg, s[c2_off:]))
    else:
        return html_span(html_fg, html_bg, s)
Esempio n. 3
0
def html_span(s, aspec, cursor = -1):
    fg_r, fg_g, fg_b, bg_r, bg_g, bg_b = aspec.get_rgb_values()
    # use real colours instead of default fg/bg
    if fg_r is None:
        fg_r, fg_g, fg_b = _d_fg_r, _d_fg_g, _d_fg_b
    if bg_r is None:
        bg_r, bg_g, bg_b = _d_bg_r, _d_bg_g, _d_bg_b
    html_fg = "#%02x%02x%02x" % (fg_r, fg_g, fg_b)
    html_bg = "#%02x%02x%02x" % (bg_r, bg_g, bg_b)
    if aspec.standout:
        html_fg, html_bg = html_bg, html_fg
    extra = (";text-decoration:underline" * aspec.underline +
        ";font-weight:bold" * aspec.bold)
    def html_span(fg, bg, s):
        if not s: return ""
        return ('<span style="color:%s;'
            'background:%s%s">%s</span>' % 
            (fg, bg, extra, html_escape(s)))
    
    if cursor >= 0:
        c_off, _ign = util.calc_text_pos(s, 0, len(s), cursor)
        c2_off = util.move_next_char(s, c_off, len(s))
        return (html_span(html_fg, html_bg, s[:c_off]) +
            html_span(html_bg, html_fg, s[c_off:c2_off]) +
            html_span(html_fg, html_bg, s[c2_off:]))
    else:
        return html_span(html_fg, html_bg, s)
Esempio n. 4
0
 def __init__(self, fill_char, cols, rows):
     Canvas.__init__(self)
     end, col = calc_text_pos(fill_char, 0, len(fill_char), 1)
     assert col == 1, "Invalid fill_char: %r" % fill_char
     self._text, cs = apply_target_encoding(fill_char[:end])
     self._cs = cs[0][0]
     self.size = cols, rows
     self.cursor = None
Esempio n. 5
0
 def _last_row(self, row):
     """On the last row we need to slide the bottom right character
     into place. Calculate the new line, attr and an insert sequence
     to do that.
     
     eg. last row:
     XXXXXXXXXXXXXXXXXXXXYZ
     
     Y will be drawn after Z, shifting Z into position.
     """
     
     new_row = row[:-1]
     z_attr, z_cs, last_text = row[-1]
     last_cols = util.calc_width(last_text, 0, len(last_text))
     last_offs, z_col = util.calc_text_pos(last_text, 0, 
         len(last_text), last_cols-1)
     if last_offs == 0:
         z_text = last_text
         del new_row[-1]
         # we need another segment
         y_attr, y_cs, nlast_text = row[-2]
         nlast_cols = util.calc_width(nlast_text, 0, 
             len(nlast_text))
         z_col += nlast_cols
         nlast_offs, y_col = util.calc_text_pos(nlast_text, 0,
             len(nlast_text), nlast_cols-1)
         y_text = nlast_text[nlast_offs:]
         if nlast_offs:
             new_row.append((y_attr, y_cs, 
                 nlast_text[:nlast_offs]))
     else:
         z_text = last_text[last_offs:]
         y_attr, y_cs = z_attr, z_cs
         nlast_cols = util.calc_width(last_text, 0,
             last_offs)
         nlast_offs, y_col = util.calc_text_pos(last_text, 0,
             last_offs, nlast_cols-1)
         y_text = last_text[nlast_offs:last_offs]
         if nlast_offs:
             new_row.append((y_attr, y_cs,
                 last_text[:nlast_offs]))
     
     new_row.append((z_attr, z_cs, z_text))
     return new_row, z_col-y_col, (y_attr, y_cs, y_text)
Esempio n. 6
0
def code_span(s, fg, bg, cursor=-1):
    code_fg = _code_colours[fg]
    code_bg = _code_colours[bg]

    if cursor >= 0:
        c_off, _ign = util.calc_text_pos(s, 0, len(s), cursor)
        c2_off = util.move_next_char(s, c_off, len(s))

        return (code_fg + code_bg + s[:c_off] + "\n" + code_bg + code_fg +
                s[c_off:c2_off] + "\n" + code_fg + code_bg + s[c2_off:] + "\n")
    else:
        return code_fg + code_bg + s + "\n"
Esempio n. 7
0
def code_span( s, fg, bg, cursor = -1):
    code_fg = _code_colours[ fg ]
    code_bg = _code_colours[ bg ]
    
    if cursor >= 0:
        c_off, _ign = util.calc_text_pos(s, 0, len(s), cursor)
        c2_off = util.move_next_char(s, c_off, len(s))

        return ( code_fg + code_bg + s[:c_off] + "\n" +
             code_bg + code_fg + s[c_off:c2_off] + "\n" +
             code_fg + code_bg + s[c2_off:] + "\n")
    else:
        return code_fg + code_bg + s + "\n"
Esempio n. 8
0
def html_span( s, fg, bg, cursor = -1):
	html_fg = _html_colours[ fg ]
	html_bg = _html_colours[ bg ]
	def html_span(fg, bg, s):
		if not s: return ""
		return '<span style="color:%s;background:%s">%s</span>' % \
			(fg, bg, html_escape(s))
	
	if cursor >= 0:
		c_off, _ign = util.calc_text_pos(s, 0, len(s), cursor)
		c2_off = util.move_next_char(s, c_off, len(s))
		return (html_span(html_fg, html_bg, s[:c_off]) +
			html_span(html_bg, html_fg, s[c_off:c2_off]) +
			html_span(html_fg, html_bg, s[c2_off:]))
	else:
		return html_span(html_fg, html_bg, s)
Esempio n. 9
0
def html_span(s, fg, bg, cursor=-1):
    html_fg = _html_colours[fg]
    html_bg = _html_colours[bg]

    def html_span(fg, bg, s):
        if not s: return ""
        return '<span style="color:%s;background:%s">%s</span>' % \
         (fg, bg, html_escape(s))

    if cursor >= 0:
        c_off, _ign = util.calc_text_pos(s, 0, len(s), cursor)
        c2_off = util.move_next_char(s, c_off, len(s))
        return (html_span(html_fg, html_bg, s[:c_off]) +
                html_span(html_bg, html_fg, s[c_off:c2_off]) +
                html_span(html_fg, html_bg, s[c2_off:]))
    else:
        return html_span(html_fg, html_bg, s)
Esempio n. 10
0
    def calculate_text_segments( self, text, width, wrap ):
        """
        Calculate the segments of text to display given width screen 
        columns to display them.  
        
        text - text to display
        width - number of available screen columns
        wrap - wrapping mode used
        
        Returns a layout structure without aligmnent applied.
        """
        b = []
        p = 0
        if wrap == 'clip':
            # no wrapping to calculate, so it's easy.
            while p<=len(text):
                n_cr = text.find("\n", p)
                if n_cr == -1: 
                    n_cr = len(text)
                sc = calc_width(text, p, n_cr)
                l = [(0,n_cr)]
                if p!=n_cr:
                    l = [(sc, p, n_cr)] + l
                b.append(l)
                p = n_cr+1
            return b

        
        while p<=len(text):
            # look for next eligible line break
            n_cr = text.find("\n", p)
            if n_cr == -1: 
                n_cr = len(text)
            sc = calc_width(text, p, n_cr)
            if sc == 0:
                # removed character hint
                b.append([(0,n_cr)])
                p = n_cr+1
                continue
            if sc <= width:
                # this segment fits
                b.append([(sc,p,n_cr),
                    # removed character hint
                    (0,n_cr)])
                
                p = n_cr+1
                continue
            pos, sc = calc_text_pos( text, p, n_cr, width )
            # FIXME: handle pathological width=1 double-byte case
            if wrap == 'any':
                b.append([(sc,p,pos)])
                p = pos
                continue
            assert wrap == 'space'
            if text[pos] == " ":
                # perfect space wrap
                b.append([(sc,p,pos),
                    # removed character hint
                    (0,pos)])
                p = pos+1
                continue
            if is_wide_char(text, pos):
                # perfect next wide
                b.append([(sc,p,pos)])
                p = pos
                continue
            prev = pos    
            while prev > p:
                prev = move_prev_char(text, p, prev)
                if text[prev] == " ":
                    sc = calc_width(text,p,prev)
                    l = [(0,prev)]
                    if p!=prev:
                        l = [(sc,p,prev)] + l
                    b.append(l)
                    p = prev+1 
                    break
                if is_wide_char(text,prev):
                    # wrap after wide char
                    next = move_next_char(text, prev, pos)
                    sc = calc_width(text,p,next)
                    b.append([(sc,p,next)])
                    p = next
                    break
            else:
                # unwrap previous line space if possible to
                # fit more text (we're breaking a word anyway)
                if b and (len(b[-1]) == 2 or ( len(b[-1])==1 
                        and len(b[-1][0])==2 )):
                    # look for removed space above
                    if len(b[-1]) == 1:
                        [(h_sc, h_off)] = b[-1]
                        p_sc = 0
                        p_off = p_end = h_off
                    else:
                        [(p_sc, p_off, p_end),
                               (h_sc, h_off)] = b[-1]
                    if (p_sc < width and h_sc==0 and
                        text[h_off] == " "):
                        # combine with previous line
                        del b[-1]
                        p = p_off
                        pos, sc = calc_text_pos( 
                            text, p, n_cr, width )
                        b.append([(sc,p,pos)])
                        # check for trailing " " or "\n"
                        p = pos
                        if p < len(text) and (
                            text[p] in (" ","\n")):
                            # removed character hint
                            b[-1].append((0,p))
                            p += 1
                        continue
                        
                        
                # force any char wrap
                b.append([(sc,p,pos)])
                p = pos
        return b