
    ;OOf                        d dl mZmZ d dlmZ d dlmZmZ d dlm	Z	m
Z
mZmZmZmZ d dlmZmZmZ d dlmZ d dlmZ d dlmZmZmZmZ d d	lmZmZmZmZm Z m!Z!m"Z" d d
l#m$Z$m%Z%m&Z& dZ'dZ(dZ)dZ*dZ+dZ,dZ-dZ.dZ/dZ0dZ1dZ2dZ3dZ4dZ5dZ6e6dfZ7dZ8 G d de	ejr                        Z: G d d e;      Z<d! Z=d" Z>d# Z?d$ Z@d% ZAd& ZB G d' d( ee:eC            ZD G d) d*eD      ZE G d+ d,eD      ZFd- ZG G d. d/eD      ZH G d0 d1eD      ZI G d2 d3eF      ZJ G d4 d5e;      ZK G d6 d7eD      ZL G d8 d9eK      ZM G d: d;eL      ZN G d< d=eN      ZOd> ZP G d? d@e;      ZQ G dA dB ePdC      eD      ZRdD ZSeTdEk(  r eS        yFyF)G    )divisionprint_function)
attrgetter)	text_typewith_metaclass)	MetaSuperdecompose_tagmarkup
calc_widthis_wide_charmove_prev_charmove_next_char)calc_poscalc_coords
shift_line)signals)text_layout)CanvasCacheCompositeCanvasSolidCanvasapply_text_layout)command_mapCURSOR_LEFTCURSOR_RIGHT	CURSOR_UPCURSOR_DOWNCURSOR_MAX_LEFTCURSOR_MAX_RIGHT)
split_reprremove_defaultspython3_reprflowboxfixedleftrightcentertopmiddlebottomspaceanyclipellipsispackgivenrelatived   weightc                   "     e Zd ZdZ fdZ xZS )
WidgetMetaa  
    Bases: :class:`MetaSuper`, :class:`MetaSignals`

    Automatic caching of render and rows methods.

    Class variable *no_cache* is a list of names of methods to not cache
    automatically.  Valid method names for *no_cache* are ``'render'`` and
    ``'rows'``.

    Class variable *ignore_focus* if defined and set to ``True`` indicates
    that the canvas this widget renders is not affected by the focus
    parameter, so it may be ignored when caching.
    c                     |j                  dg       }t        t        |   |||       d|v r"d|vrt	        |       }nt        |       }|| _        d|v rd|vrt        |       | _        d|v r| `	d|v r| `
y y )Nno_cacherenderrowsignore_focus)getsuperr4   __init__cache_widget_rendernocache_widget_renderr7   cache_widget_rowsr8   r6   r9   )clsnamebasesdr6   	render_fn	__class__s         M/var/www/premiumrankchecker/venv/lib/python3.12/site-packages/urwid/widget.pyr<   zWidgetMeta.__init__V   s    55R(j#'eQ7q=x'/4	1#6	"CJQ;61(-CH?Q      )__name__
__module____qualname____doc__r<   __classcell__)rE   s   @rF   r4   r4   H   s    ! !rG   r4   c                       e Zd Zy)WidgetErrorNrH   rI   rJ    rG   rF   rN   rN   i       rG   rN   c                     |r|dd dk7  r|d   |j                         k7  s$t        |      dkD  rE|d   |j                         k7  r.t        d| |j                         |j                         |fz        yy)zA
    Raise a WidgetError if a canv does not match size size.
       N)r   r   z8Widget %r rendered (%d x %d) canvas when passed size %r!)colslenr8   rN   )widgetsizecanvs      rF   validate_sizerY   l   sz     	abT!d1g&<	T1aDIIK/ $'-tyy{IIK'   	  0rG   c                     	 |j                   | _         | j                  j                  |j                         |j                  | _        |j                  | _        y# t
        $ r Y yw xY w)zN
    Copy as much of the function detail from fn to new_fn
    as we can.
    N)rH   __dict__updaterK   rI   	TypeError)new_fnfns     rF   update_wrapperr`   v   sQ    
++r{{+MM s   AA 	A'&A'c                      t        t         dd             j                  d fd	}|_        t	        |       |S )zt
    Return a function that wraps the cls.render() method
    and fetches and stores canvases with CanvasCache.
    r9   Fc                     |xr  }t        j                  | ||      }|r|S  | ||      }t        | ||       |j                  rt	        |      }|j                  | ||       t        j                  |       |S N)focus)r   fetchrY   widget_infor   finalizestoreselfrW   rd   rX   r@   r_   r9   s       rF   cached_renderz*cache_widget_render.<locals>.cached_render   s    *l*  sD%8K$E*dD$'"4(DdD%(#t$rG   F)boolgetattrr7   original_fnr`   )r@   rk   r_   r9   s   ` @@rF   r=   r=      s@    
 ^U;<L	B !#M="%rG   c                     | j                   t        d      rj                  dfd	}|_        t        |       |S )zl
    Return a function that wraps the cls.render() method
    and finalizes the canvas that it returns.
    ro   c                      | ||      }|j                   rt        |      }t        | ||       |j                  | ||       |S rc   )rf   r   rY   rg   )rj   rW   rd   rX   r_   s       rF   finalize_renderz.nocache_widget_render.<locals>.finalize_render   sE    $E*"4(DdD$'dD%(rG   rl   )r7   hasattrro   r`   )r@   rr   r_   s     @rF   r>   r>      s@    
 
Br=!^^ #%O?B'rG   c                 j      j                   j                  d fd	}|_        t        |       |S )z
    Return a function that wraps the cls.render() method
    and finalizes the canvas that it returns, but does not
    cache the canvas.
    c                 r     | |      }|j                   rt        |      }|j                  | |       |S rc   )rf   r   rg   )rW   rd   rX   r_   rj   s      rF   rr   z7nocache_widget_render_instance.<locals>.finalize_render   s9    $E*"4(DdD%(rG   rl   )r7   ro   r`   )rj   rr   r_   s   ` @rF   nocache_widget_render_instancerv      s3     
	 	 B #%O?B'rG   c                 x     t        t         dd             j                  d fd	}t        |       |S )zt
    Return a function that wraps the cls.rows() method
    and returns rows from the CanvasCache if available.
    r9   Fc                 z    |xr  }t        j                  | ||      }|r|j                         S  | ||      S N)r   re   r8   ri   s       rF   cached_rowsz&cache_widget_rows.<locals>.cached_rows   sD    *l*  sD%899;$e$$rG   rl   )rm   rn   r8   r`   )r@   rz   r_   r9   s   ` @@rF   r?   r?      s8    
 ^U;<L	B% ;#rG   c                       e Zd ZdZdZ eeeeg      Z	e
Zd Zd Zd Zd ZddZ ed d	
      Z ed d
      ZddZ eeed
      Zd Zd Zd Zy)WidgetaL#  
    Widget base class

    .. attribute:: _selectable
       :annotation: = False

       The default :meth:`.selectable` method returns this
       value.

    .. attribute:: _sizing
       :annotation: = frozenset(['flow', 'box', 'fixed'])

       The default :meth:`.sizing` method returns this value.

    .. attribute:: _command_map
       :annotation: = urwid.command_map

       A shared :class:`CommandMap` instance. May be redefined
       in subclasses or widget instances.

    .. method:: render(size, focus=False)

       .. note::

          This method is not implemented in :class:`.Widget` but
          must be implemented by any concrete subclass

       :param size: One of the following,
                    *maxcol* and *maxrow* are integers > 0:

                    (*maxcol*, *maxrow*)
                      for box sizing -- the parent chooses the exact
                      size of this widget

                    (*maxcol*,)
                      for flow sizing -- the parent chooses only the
                      number of columns for this widget

                    ()
                      for fixed sizing -- this widget is a fixed size
                      which can't be adjusted by the parent
       :type size: widget size
       :param focus: set to ``True`` if this widget or one of its children
                     is in focus
       :type focus: bool

       :returns: A :class:`Canvas` subclass instance containing the
                 rendered content of this widget

       :class:`Text` widgets return a :class:`TextCanvas` (arbitrary text and
       display attributes), :class:`SolidFill` widgets return a
       :class:`SolidCanvas` (a single character repeated across
       the whole surface) and container widgets return a
       :class:`CompositeCanvas` (one or more other canvases
       arranged arbitrarily).

       If *focus* is ``False``, the returned canvas may not have a cursor
       position set.

       There is some metaclass magic defined in the :class:`Widget`
       metaclass :class:`WidgetMeta` that causes the
       result of this method to be cached by :class:`CanvasCache`.
       Later calls will automatically look up the value in the cache first.

       As a small optimization the class variable :attr:`ignore_focus`
       may be defined and set to ``True`` if this widget renders the same
       canvas regardless of the value of the *focus* parameter.

       Any time the content of a widget changes it should call
       :meth:`_invalidate` to remove any cached canvases, or the widget
       may render the cached canvas instead of creating a new one.


    .. method:: rows(size, focus=False)

       .. note::

          This method is not implemented in :class:`.Widget` but
          must be implemented by any flow widget.  See :meth:`.sizing`.

       See :meth:`Widget.render` for parameter details.

       :returns: The number of rows required for this widget given a number
                 of columns in *size*

       This is the method flow widgets use to communicate their size to other
       widgets without having to render a canvas. This should be a quick
       calculation as this function may be called a number of times in normal
       operation. If your implementation may take a long time you should add
       your own caching here.

       There is some metaclass magic defined in the :class:`Widget`
       metaclass :class:`WidgetMeta` that causes the
       result of this function to be retrieved from any
       canvas cached by :class:`CanvasCache`, so if your widget
       has been rendered you may not receive calls to this function. The class
       variable :attr:`ignore_focus` may be defined and set to ``True`` if this
       widget renders the same size regardless of the value of the *focus*
       parameter.


    .. method:: keypress(size, key)

       .. note::

          This method is not implemented in :class:`.Widget` but
          must be implemented by any selectable widget.
          See :meth:`.selectable`.

       :param size: See :meth:`Widget.render` for details
       :type size: widget size
       :param key: a single keystroke value; see :ref:`keyboard-input`
       :type key: bytes or unicode

       :returns: ``None`` if *key* was handled by this widget or
                 *key* (the same value passed) if *key* was not handled
                 by this widget

       Container widgets will typically call the :meth:`keypress` method on
       whichever of their children is set as the focus.

       The standard widgets use :attr:`_command_map` to
       determine what action should be performed for a given *key*. You may
       modify these values to your liking globally, at some level in the
       widget hierarchy or on individual widgets. See :class:`CommandMap`
       for the defaults.

       In your own widgets you may use whatever logic you like: filtering or
       translating keys, selectively passing along events etc.



    .. method:: mouse_event(size, event, button, col, row, focus)

       .. note::

          This method is not implemented in :class:`.Widget` but
          may be implemented by a subclass.  Not implementing this
          method is equivalent to having a method that always returns
          ``False``.

       :param size: See :meth:`Widget.render` for details.
       :type size: widget size
       :param event: Values such as ``'mouse press'``, ``'ctrl mouse press'``,
                     ``'mouse release'``, ``'meta mouse release'``,
                     ``'mouse drag'``; see :ref:`mouse-input`
       :type event: mouse event
       :param button: 1 through 5 for press events, often 0 for release events
                      (which button was released is often not known)
       :type button: int
       :param col: Column of the event, 0 is the left edge of this widget
       :type col: int
       :param row: Row of the event, 0 it the top row of this widget
       :type row: int
       :param focus: Set to ``True`` if this widget or one of its children
                     is in focus
       :type focus: bool

       :returns: ``True`` if the event was handled by this widget, ``False``
                 otherwise

       Container widgets will typically call the :meth:`mouse_event` method on
       whichever of their children is at the position (*col*, *row*).


    .. method:: get_cursor_coords(size)

       .. note::

          This method is not implemented in :class:`.Widget` but
          must be implemented by any widget that may return cursor
          coordinates as part of the canvas that :meth:`render` returns.

       :param size: See :meth:`Widget.render` for details.
       :type size: widget size

       :returns: (*col*, *row*) if this widget has a cursor, ``None`` otherwise

       Return the cursor coordinates (*col*, *row*) of a cursor that will appear
       as part of the canvas rendered by this widget when in focus, or ``None``
       if no cursor is displayed.

       The :class:`ListBox` widget
       uses this method to make sure a cursor in the focus widget is not
       scrolled out of view.  It is a separate method to avoid having to render
       the whole widget while calculating layout.

       Container widgets will typically call the :meth:`.get_cursor_coords`
       method on their focus widget.


    .. method:: get_pref_col(size)

       .. note::

          This method is not implemented in :class:`.Widget` but
          may be implemented by a subclass.

       :param size: See :meth:`Widget.render` for details.
       :type size: widget size

       :returns: a column number or ``'left'`` for the leftmost available
                 column or ``'right'`` for the rightmost available column

       Return the preferred column for the cursor to be displayed in this
       widget. This value might not be the same as the column returned from
       :meth:`get_cursor_coords`.

       The :class:`ListBox` and :class:`Pile`
       widgets call this method on a widget losing focus and use the value
       returned to call :meth:`.move_cursor_to_coords` on the widget becoming
       the focus. This allows the focus to move up and down through widgets
       while keeping the cursor in approximately the same column on screen.


    .. method:: move_cursor_to_coords(size, col, row)

       .. note::

          This method is not implemented in :class:`.Widget` but
          may be implemented by a subclass.  Not implementing this
          method is equivalent to having a method that always returns
          ``False``.

       :param size: See :meth:`Widget.render` for details.
       :type size: widget size
       :param col: new column for the cursor, 0 is the left edge of this widget
       :type col: int
       :param row: new row for the cursor, 0 it the top row of this widget
       :type row: int

       :returns: ``True`` if the position was set successfully anywhere on
                 *row*, ``False`` otherwise
    Fc                 .    t        j                  |        y)zt
        Mark cached canvases rendered by this widget as dirty so that
        they will not be used again.
        N)r   
invalidaterj   s    rF   _invalidatezWidget._invalidate  s    
 	t$rG   c                 4    t        j                  | || g|  y)z[
        Convenience function to emit signals with self as first
        argument.
        N)r   emit_signal)rj   rA   argss      rF   _emitzWidget._emit  s    
 	D$4t4rG   c                     | j                   S )ao  
        :returns: ``True`` if this is a widget that is designed to take the
                  focus, i.e. it contains something the user might want to
                  interact with, ``False`` otherwise,

        This default implementation returns :attr:`._selectable`.
        Subclasses may leave these is if the are not selectable,
        or if they are always selectable they may
        set the :attr:`_selectable` class variable to ``True``.

        If this method returns ``True`` then the :meth:`.keypress` method
        must be implemented.

        Returning ``False`` does not guarantee that this widget will never be in
        focus, only that this widget will usually be skipped over when changing
        focus. It is still possible for non selectable widgets to have the focus
        (typically when there are no other selectable widgets visible).
        )_selectabler   s    rF   
selectablezWidget.selectable  s    & rG   c                     | j                   S )a3  
        :returns: A frozenset including one or more of ``'box'``, ``'flow'`` and
                  ``'fixed'``.  Default implementation returns the value of
                  :attr:`._sizing`, which for this class includes all three.

        The sizing modes returned indicate the modes that may be
        supported by this widget, but is not sufficient to know
        that using that sizing mode will work.  Subclasses should
        make an effort to remove sizing modes they know will not
        work given the state of the widget, but many do not yet
        do this.

        If a sizing mode is missing from the set then the widget
        should fail when used in that mode.

        If ``'flow'`` is among the values returned then the other
        methods in this widget must be able to accept a
        single-element tuple (*maxcol*,) to their ``size``
        parameter, and the :meth:`rows` method must be defined.

        If ``'box'`` is among the values returned then the other
        methods must be able to accept a two-element tuple
        (*maxcol*, *maxrow*) to their size parameter.

        If ``'fixed'`` is among the values returned then the other
        methods must be able to accept an empty tuple () to
        their size parameter, and the :meth:`pack` method must
        be defined.
        )_sizingr   s    rF   sizingzWidget.sizing  s    < ||rG   c                    |s8t         | j                         v rt        d      t        dt	        |       z        t        |      dk(  rCt        | j                         v r|| j                  ||      fz   S t        dt	        |       z        |S )ad  
        See :meth:`Widget.render` for parameter details.

        :returns: A "packed" size (*maxcol*, *maxrow*) for this widget

        Calculate and return a minimum
        size where all content could still be displayed. Fixed widgets must
        implement this method and return their size when ``()`` is passed as the
        *size* parameter.

        This default implementation returns the *size* passed, or the *maxcol*
        passed and the value of :meth:`rows` as the *maxrow* when (*maxcol*,)
        is passed as the *size* parameter.

        .. note::

           This is a new method that hasn't been fully implemented across the
           standard widget types. In particular it has not yet been
           implemented for container widgets.

        :class:`Text` widgets have implemented this method.
        You can use :meth:`Text.pack` to calculate the minimum
        columns and rows required to display a text widget without wrapping,
        or call it iteratively to calculate the minimum number of columns
        required to display the text wrapped into a target number of rows.
        z)Fixed widgets must override Widget.pack()z3Cannot pack () size, this is not a fixed widget: %srS   z9Cannot pack (maxcol,) size, this is not a flow widget: %s)FIXEDr   NotImplementedErrorrN   reprrU   FLOWr8   rj   rW   rd   s      rF   r.   zWidget.pack  s    6 %) +% & &  $T
+ , ,Y!^t{{}$tyyu5777 #%)$Z0 1 1rG   c                     | S ry   rP   r   s    rF   <lambda>zWidget.<lambda>,  s    t rG   z
        Read-only property that steps through decoration widgets
        and returns the one at the base.  This default implementation
        returns self.
        docc                      y ry   rP   r   s    rF   r   zWidget.<lambda>2  s    rG   z
        Read-only property returning the child widget in focus for
        container widgets.  This default implementation
        always returns ``None``, indicating that this widget has no children.
        Nc                     t        d| z        )Nz/No focus_position, %r is not a container widget)
IndexErrorrj   vals     rF   _not_a_containerzWidget._not_a_container8  s    =DF 	FrG   a  
        Property for reading and setting the focus position for
        container widgets. This default implementation raises
        :exc:`IndexError`, making normal widgets fail the same way
        accessing :attr:`.focus_position` on an empty container widget would.
        c                     t        |       S )z
        A friendly __repr__ for widgets, designed to be extended
        by subclasses with _repr_words and _repr_attr methods.
        )r   r   s    rF   __repr__zWidget.__repr__B  s    
 $rG   c                 F   g }| j                         rdg|z   }| j                         rt| j                         t        t        t        t
        g      k7  rIt        | j                               }|j                          |j                  dj                  |             |dgz   S )Nr   /rV   )
r   r   	frozensetr   BOXr   listsortappendjoin)rj   wordssizing_modess      rF   _repr_wordszWidget._repr_wordsI  s}    ??!NU*E;;=T[[]isE8J.KK.LLL,/0z!!rG   c                     i S ry   rP   r   s    rF   _repr_attrszWidget._repr_attrsS  s    	rG   rl   ry   )rH   rI   rJ   rK   r   r   r   r   r   r   r   _command_mapr   r   r   r   r.   propertybase_widgetrd   r   focus_positionr   r   r   rP   rG   rF   r|   r|      s    iT KsE*+GL%5 *@&P + 2 K % , EF .0@ G N "rG   r|   c                   2    e Zd ZdZ eeg      ZddZddZy)
FlowWidgetz
    Deprecated.  Inherit from Widget and add:

        _sizing = frozenset(['flow'])

    at the top of your class definition instead.

    Base class of widgets that determine their rows from the number of
    columns available.
    c                     t               )z@
        All flow widgets must implement this function.
        r   r   s      rF   r8   zFlowWidget.rowsd       "##rG   c                     t               z;
        All widgets must implement this function.
        r   r   s      rF   r7   zFlowWidget.renderj  r   rG   Nrl   )	rH   rI   rJ   rK   r   r   r   r8   r7   rP   rG   rF   r   r   W  s    	 G$$rG   r   c                   .    e Zd ZdZdZ eeg      ZddZy)	BoxWidgeta  
    Deprecated.  Inherit from Widget and add:

        _sizing = frozenset(['box'])
        _selectable = True

    at the top of your class definition instead.

    Base class of width and height constrained widgets such as
    the top level widget attached to the display object
    Tc                     t               r   r   r   s      rF   r7   zBoxWidget.render  r   rG   Nrl   )	rH   rI   rJ   rK   r   r   r   r   r7   rP   rG   rF   r   r   q  s    
 KG$rG   r   c                 *    | dk7  rt        d|       y)z[
    raise ValueError if size != ().

    Used by FixedWidgets to test size parameter.
    rP   z+FixedWidget takes only () for size.passed: N)
ValueError)rW   s    rF   
fixed_sizer     s%     rz # $ 	$ rG   c                   2    e Zd ZdZ eeg      ZddZddZy)FixedWidgetz
    Deprecated.  Inherit from Widget and add:

        _sizing = frozenset(['fixed'])

    at the top of your class definition instead.

    Base class of widgets that know their width and height and
    cannot be resized
    c                     t               r   r   r   s      rF   r7   zFixedWidget.render  r   rG   Nc                     t               )zA
        All fixed widgets must implement this function.
        r   r   s      rF   r.   zFixedWidget.pack  r   rG   rl   NF)	rH   rI   rJ   rK   r   r   r   r7   r.   rP   rG   rF   r   r     s    	  G$$rG   r   c                   J    e Zd ZdZ eeg      ZdZd	dZd Z	d Z
d
dZd
dZy)Dividerz#
    Horizontal divider widget
    Tc                 b    | j                   j                          || _        || _        || _        y)a  
        :param div_char: character to repeat across line
        :type div_char: bytes or unicode

        :param top: number of blank lines above
        :type top: int

        :param bottom: number of blank lines below
        :type bottom: int

        >>> Divider()
        <Divider flow widget>
        >>> Divider(u'-')
        <Divider flow widget '-'>
        >>> Divider(u'x', 1, 2)
        <Divider flow widget 'x' bottom=2 top=1>
        N)_Divider__superr<   div_charr'   r)   )rj   r   r'   r)   s       rF   r<   zDivider.__init__  s)    $ 	 rG   c                     | j                   j                         t        | j                        g| j                  dk7  z  z   S )N )r   r   r    r   r   s    rF   r   zDivider._repr_words  sA    ||'')'-),0MMT,A-C C 	CrG   c                     t        | j                  j                               }| j                  r| j                  |d<   | j                  r| j                  |d<   |S )Nr'   r)   )dictr   r   r'   r)   rj   attrss     rF   r   zDivider._repr_attrs  sD    T\\--/088DHHU5\;;$++hrG   c                 B    |\  }| j                   dz   | j                  z   S )z
        Return the number of lines that will be rendered.

        >>> Divider().rows((10,))
        1
        >>> Divider(u'x', 1, 2).rows((10,))
        4
        rS   )r'   r)   rj   rW   rd   maxcols       rF   r8   zDivider.rows  s"     	xx!|dkk))rG   c                     |\  }t        | j                  |d      }t        |      }| j                  s| j                  r&|j                  | j                  | j                         |S )a[  
        Render the divider as a canvas and return it.

        >>> Divider().render((10,)).text # ... = b in Python 3
        [...'          ']
        >>> Divider(u'-', top=1).render((10,)).text
        [...'          ', ...'----------']
        >>> Divider(u'x', bottom=2).render((5,)).text
        [...'xxxxx', ...'     ', ...'     ']
        rS   )r   r   r   r'   r)   pad_trim_top_bottomrj   rW   rd   r   rX   s        rF   r7   zDivider.render  sQ     	4==&!4t$88t{{$$TXXt{{;rG   N)r   r   r   rl   )rH   rI   rJ   rK   r   r   r   r9   r<   r   r   r8   r7   rP   rG   rF   r   r     s4     GL.C
*rG   r   c                   .    e Zd ZdZdZdZddZd Zd	dZy)
	SolidFillzA
    A box widget that fills an area with a single character
    FTc                 F    | j                   j                          || _        y)z
        :param fill_char: character to fill area with
        :type fill_char: bytes or unicode

        >>> SolidFill(u'8')
        <SolidFill box widget '8'>
        N)_SolidFill__superr<   	fill_char)rj   r   s     rF   r<   zSolidFill.__init__  s     	"rG   c                 d    | j                   j                         t        | j                        gz   S ry   )r   r   r    r   r   s    rF   r   zSolidFill._repr_words  s&    ||'')\$..-I,JJJrG   c                 :    |\  }}t        | j                  ||      S )z
        Render the Fill as a canvas and return it.

        >>> SolidFill().render((4,2)).text # ... = b in Python 3
        [...'    ', ...'    ']
        >>> SolidFill('#').render((5,3)).text
        [...'#####', ...'#####', ...'#####']
        )r   r   )rj   rW   rd   r   maxrows        rF   r7   zSolidFill.render  s      4>>66::rG   N)r   rl   )	rH   rI   rJ   rK   r   r9   r<   r   r7   rP   rG   rF   r   r     s#     KL	#K
;rG   r   c                       e Zd Zy)	TextErrorNrO   rP   rG   rF   r   r     rQ   rG   r   c                       e Zd ZdZ eeg      ZdZdZe	e
dfdZd Zd Zd Zd	 Zd
 Z ed d      Z ed d      Zd Zd ZddZ ed e      Z ed e      Z ed       ZddZddZddZd ZddZy)Textz/
    a horizontally resizeable text widget
    T   Nc                     | j                   j                          d| _        | j                  |       | j	                  |||       y)a[  
        :param markup: content of text widget, one of:

            bytes or unicode
              text to be displayed

            (*display attribute*, *text markup*)
              *text markup* with *display attribute* applied to all parts
              of *text markup* with no display attribute already applied

            [*text markup*, *text markup*, ... ]
              all *text markup* in the list joined together

        :type markup: :ref:`text-markup`
        :param align: typically ``'left'``, ``'center'`` or ``'right'``
        :type align: text alignment mode
        :param wrap: typically ``'space'``, ``'any'``, ``'clip'`` or ``'ellipsis'``
        :type wrap: text wrapping mode
        :param layout: defaults to a shared :class:`StandardTextLayout` instance
        :type layout: text layout instance

        >>> Text(u"Hello")
        <Text flow widget 'Hello'>
        >>> t = Text(('bold', u"stuff"), 'right', 'any')
        >>> t
        <Text flow widget 'stuff' align='right' wrap='any'>
        >>> print(t.text)
        stuff
        >>> t.attrib
        [('bold', 5)]
        N)_Text__superr<   _cache_maxcolset_text
set_layout)rj   markupalignwraplayouts        rF   r<   zText.__init__   s9    @ 	!ftV,rG   c                    | j                   j                         }| j                         d   }t        |      }t	        |      | j
                  kD  r/|d| j
                  dz  dz  dz
   dz   || j
                   dz  d z   }||gz   S )z
        Show the text in the repr in python3 format (b prefix for byte
        strings) and truncate if it's too long
        r   N      z...)r   r   get_textr    rU   _repr_content_length_max)rj   firsttextrests       rF   r   zText._repr_wordsE  s    
 ((*}}q!D!t9t444D$77!;q@1DEd;;;q@ABCDv~rG   c                     t        | j                  j                         | j                  | j                        }t        |t        j                        S )N)r   r   )r   r   r   _align_mode
_wrap_moder   r   r<   r   s     rF   r   zText._repr_attrsR  s>    T\\--/""" udmm44rG   c                 F    d | _         | j                  j                          y ry   )r   r   r   r   s    rF   r   zText._invalidateX  s    !  "rG   c                 T    t        |      \  | _        | _        | j                          y)a  
        Set content of text widget.

        :param markup: see :class:`Text` for description.
        :type markup: text markup

        >>> t = Text(u"foo")
        >>> print(t.text)
        foo
        >>> t.set_text(u"bar")
        >>> print(t.text)
        bar
        >>> t.text = u"baz"  # not supported because text stores text but set_text() takes markup
        Traceback (most recent call last):
        AttributeError: can't set attribute
        N)r	   _text_attribr   rj   r   s     rF   r   zText.set_text\  s#    " $7v#> 
DLrG   c                 2    | j                   | j                  fS )aV  
        :returns: (*text*, *display attributes*)

            *text*
              complete bytes/unicode content of text widget

            *display attributes*
              run length encoded display attributes for *text*, eg.
              ``[('attr1', 10), ('attr2', 5)]``

        >>> Text(u"Hello").get_text() # ... = u in Python 2
        (...'Hello', [])
        >>> Text(('bright', u"Headline")).get_text()
        (...'Headline', [('bright', 8)])
        >>> Text([('a', u"one"), u"two", ('b', u"three")]).get_text()
        (...'onetwothree', [('a', 3), (None, 3), ('b', 5)])
        )r   r   r   s    rF   r   zText.get_textp  s    $ zz4<<''rG   c                 (    | j                         d   S Nr   r   r   s    rF   r   zText.<lambda>  s     2 rG   zh
        Read-only property returning the complete bytes/unicode content
        of this widget
        r   c                 (    | j                         d   S )NrS   r   r   s    rF   r   zText.<lambda>  s    $--/!"4 rG   zo
        Read-only property returning the run-length encoded display
        attributes of this widget
        c                     | j                   j                  |      st        d|d      || _        | j	                          y)a  
        Set text alignment mode. Supported modes depend on text layout
        object in use but defaults to a :class:`StandardTextLayout` instance

        :param mode: typically ``'left'``, ``'center'`` or ``'right'``
        :type mode: text alignment mode

        >>> t = Text(u"word")
        >>> t.set_align_mode('right')
        >>> t.align
        'right'
        >>> t.render((10,)).text # ... = b in Python 3
        [...'      word']
        >>> t.align = 'center'
        >>> t.render((10,)).text
        [...'   word   ']
        >>> t.align = 'somewhere'
        Traceback (most recent call last):
        TextError: Alignment mode 'somewhere' not supported.
        zAlignment mode  not supported.N)r   supports_align_moder   r   r   rj   modes     rF   set_align_modezText.set_align_mode  s?    * {{..t4  rG   c                     | j                   j                  |      st        d|d      || _        | j	                          y)a  
        Set text wrapping mode. Supported modes depend on text layout
        object in use but defaults to a :class:`StandardTextLayout` instance

        :param mode: typically ``'space'``, ``'any'``, ``'clip'`` or ``'ellipsis'``
        :type mode: text wrapping mode

        >>> t = Text(u"some words")
        >>> t.render((6,)).text # ... = b in Python 3
        [...'some  ', ...'words ']
        >>> t.set_wrap_mode('clip')
        >>> t.wrap
        'clip'
        >>> t.render((6,)).text
        [...'some w']
        >>> t.wrap = 'any'  # Urwid 0.9.9 or later
        >>> t.render((6,)).text
        [...'some w', ...'ords  ']
        >>> t.wrap = 'somehow'
        Traceback (most recent call last):
        TextError: Wrap mode 'somehow' not supported.
        z
Wrap mode r   N)r   supports_wrap_moder   r   r   r   s     rF   set_wrap_modezText.set_wrap_mode  s7    . {{--d34ABBrG   c                 z    |t         j                  }|| _        | j                  |       | j	                  |       y)a  
        Set the text layout object, alignment and wrapping modes at
        the same time.

        :type align: text alignment mode
        :param wrap: typically 'space', 'any', 'clip' or 'ellipsis'
        :type wrap: text wrapping mode
        :param layout: defaults to a shared :class:`StandardTextLayout` instance
        :type layout: text layout instance

        >>> t = Text(u"hi")
        >>> t.set_layout('right', 'clip')
        >>> t
        <Text flow widget 'hi' align='right' wrap='clip'>
        N)r   default_layout_layoutr  r  )rj   r   r   r   s       rF   r   zText.set_layout  s7      > //FE"4 rG   c                     | j                   S ry   )r   r   s    rF   r   zText.<lambda>  s    !1!1 rG   c                     | j                   S ry   )r   r   s    rF   r   zText.<lambda>  s
     rG   c                     | j                   S ry   )r  r   s    rF   r   zText.<lambda>  s
    $,, rG   c                 t    |\  }| j                         \  }}| j                  |||f      }t        ||||      S )a`  
        Render contents with wrapping and alignment.  Return canvas.

        See :meth:`Widget.render` for parameter details.

        >>> Text(u"important things").render((18,)).text # ... = b in Python 3
        [...'important things  ']
        >>> Text(u"important things").render((11,)).text
        [...'important  ', ...'things     ']
        )r   get_line_translationr   )rj   rW   rd   r   r   attrtranss          rF   r7   zText.render  sA     	]]_
d))6D;@ tUF;;rG   c                 >    |\  }t        | j                  |            S )z
        Return the number of rows the rendered text requires.

        See :meth:`Widget.rows` for parameter details.

        >>> Text(u"important things").rows((18,))
        1
        >>> Text(u"important things").rows((11,))
        2
        )rU   r  r   s       rF   r8   z	Text.rows  s!     	4,,V455rG   c                 t    | j                   r| j                   |k7  r| j                  ||       | j                  S )a  
        Return layout structure used to map self.text to a canvas.
        This method is used internally, but may be useful for
        debugging custom layout classes.

        :param maxcol: columns available for display
        :type maxcol: int
        :param ta: ``None`` or the (*text*, *display attributes*) tuple
                   returned from :meth:`.get_text`
        :type ta: text and display attributes
        )r   _update_cache_translation_cache_translation)rj   r   tas      rF   r  zText.get_line_translation  s6     !!T%7%76%A**626&&&rG   c                     |r|\  }}n| j                         \  }}|| _        | j                  j                  ||| j                  | j                        | _        y ry   )r   r   r   r   r   r  )rj   r   r  r   r  s        rF   r  zText._update_cache_translation  sO    JD$JD$#"&++"4"4&$**DOO#=rG   c                    | j                         \  }}|Y|\  }t        | j                  d      s|S | j                  |||f      }| j                  j	                  ||      }|t        |      fS d}d}|t        |      k  rJ|j                  d|      }	|	dk(  rt        |      }	t        |||	      }
|
|kD  r|
}|	dz   }|t        |      k  rJ||j                  d      dz   fS )a  
        Return the number of screen columns and rows required for
        this Text widget to be displayed without wrapping or
        clipping, as a single element tuple.

        :param size: ``None`` for unlimited screen columns or (*maxcol*,) to
                     specify a maximum column size
        :type size: widget size

        >>> Text(u"important things").pack()
        (16, 1)
        >>> Text(u"important things").pack((15,))
        (9, 2)
        >>> Text(u"important things").pack((8,))
        (8, 2)
        r.   r   
rS   )	r   rs   r   r  r.   rU   findr
   count)rj   rW   rd   r   r  r   r  rT   ijcs              rF   r.   z	Text.pack  s    " ]]_
dIV4;;/--vT{CE;;##VU4D#e*%%#d)m		$"ABwI4A&Av!A #d)m djj&*++rG   ry   rl   r   )rH   rI   rJ   rK   r   r   r   r9   r   LEFTSPACEr<   r   r   r   r   r   r   r   attribr  r  r   r   r   r   r7   r8   r  r  r.   rP   rG   rF   r   r     s     GL"%)d #-J5#((( 2 9 D 4 ; F
68!, 1>BE/?D./F<"6' =%,rG   r   c                       e Zd Zy)	EditErrorNrO   rP   rG   rF   r!  r!  >  rQ   rG   r!  c            	          e Zd ZdZdZdZddgZd Zdddee	ddddf	d	Z
d
 Zd Zd Zd Zd Zd Zd Z ed d      Zd Z ed ed      Zd Zd Zd Z eeed      Zd Zd Zd Zd Zd Zd  Zd! Z d&d"Z!d'd#Z"d$ Z#d% Z$y)(Edita   
    Text editing widget implements cursor movement, text insertion and
    deletion.  A caption may prefix the editing area.  Uses text class
    for text layout.

    Users of this class may listen for ``"change"`` or ``"postchange"``
    events.  See :func:``connect_signal``.

    * ``"change"`` is sent just before the value of edit_text changes.
      It receives the new text as an argument.  Note that ``"change"`` cannot
      change the text in question as edit_text changes the text afterwards.
    * ``"postchange"`` is sent after the value of edit_text changes.
      It receives the old value of the text as an argument and thus is
      appropriate for changing the text.  It is possible for a ``"postchange"``
      event handler to get into a loop of changing the text and then being
      called when the event is re-emitted.  It is up to the event
      handler to guard against this case (for instance, by not changing the
      text if it is signaled for for text that it has already changed once).
    TFchange
postchangec                 Z    t        |d      xs t        |      dk(  xr t        |      dk\  S )z
        Filter for text that may be entered into this widget by the user

        :param ch: character to be inserted
        :type ch: bytes or unicode

        This implementation returns True for all printable characters.
        r   rS       )r   rU   ordrj   chs     rF   
valid_charzEdit.valid_char[  s+     Bq!Cc"gqj&BSW]CrG    Nc
                 (   | j                   j                  d|||       || _        || _        d| _        | j                  |       d| _        | j                  |       |t        |      }| j                  |       | j                  |	       d| _        y)a  
        :param caption: markup for caption preceding edit_text, see
                        :class:`Text` for description of text markup.
        :type caption: text markup
        :param edit_text: initial text for editing, type (bytes or unicode)
                          must match the text in the caption
        :type edit_text: bytes or unicode
        :param multiline: True: 'enter' inserts newline  False: return it
        :type multiline: bool
        :param align: typically 'left', 'center' or 'right'
        :type align: text alignment mode
        :param wrap: typically 'space', 'any' or 'clip'
        :type wrap: text wrapping mode
        :param allow_tab: True: 'tab' inserts 1-8 spaces  False: return it
        :type allow_tab: bool
        :param edit_pos: initial position for cursor, None:end of edit_text
        :type edit_pos: int
        :param layout: defaults to a shared :class:`StandardTextLayout` instance
        :type layout: text layout instance
        :param mask: hide text entered with this character, None:disable mask
        :type mask: bytes or unicode

        >>> Edit()
        <Edit selectable flow widget '' edit_pos=0>
        >>> Edit(u"Y/n? ", u"yes")
        <Edit selectable flow widget 'yes' caption='Y/n? ' edit_pos=3>
        >>> Edit(u"Name ", u"Smith", edit_pos=1)
        <Edit selectable flow widget 'Smith' caption='Name ' edit_pos=1>
        >>> Edit(u"", u"3.14", align='right')
        <Edit selectable flow widget '3.14' align='right' edit_pos=4>
        r,  r   NF)_Edit__superr<   	multiline	allow_tab	_edit_posset_caption
_edit_textset_edit_textrU   set_edit_posset_mask_shift_view_to_cursor)
rj   caption	edit_textr/  r   r   r0  edit_posr   masks
             rF   r<   zEdit.__init__f  s    F 	b%v6""!9%9~H(#d%*"rG   c                     | j                   j                         d d t        | j                        gz   dt        | j                        z   gt        | j                        z  z   dg| j                  du z  z   S )Nr  zcaption=r/  T)r.  r   r    r3  _captionrm   r/  r   s    rF   r   zEdit._repr_words  s    ||'')#2.)2+ +dmm44.68<T]]8K.LL O NNd2O44 	4rG   c                     t        | j                  j                         | j                        }t	        |t
        j                        S )N)r:  )r   r.  r   r1  r   r#  r<   r   s     rF   r   zEdit._repr_attrs  s3    T\\--/^^%udmm44rG   c                     | j                   %| j                  | j                  z   | j                  fS | j                  | j                   t	        | j                        z  z   | j                  fS )a  
        Returns ``(text, display attributes)``. See :meth:`Text.get_text`
        for details.

        Text returned includes the caption and edit_text, possibly masked.

        >>> Edit(u"What? ","oh, nothing.").get_text() # ... = u in Python 2
        (...'What? oh, nothing.', [])
        >>> Edit(('bright',u"user@host:~$ "),"ls").get_text()
        (...'user@host:~$ ls', [('bright', 13)])
        >>> Edit(u"password:", u"seekrit", mask=u"*").get_text()
        (...'password:*******', [])
        )_maskr=  r3  r   rU   r   s    rF   r   zEdit.get_text  sT     ::==4??2DLL@@==DJJT__1E$EFTTrG   c                 J    t        | d      s|dk(  rd| _        yt        d      )z
        Not supported by Edit widget.

        >>> Edit().set_text("test")
        Traceback (most recent call last):
        EditError: set_text() not supported.  Use set_caption() or set_edit_text() instead.
        r   r,  NzHset_text() not supported.  Use set_caption() or set_edit_text() instead.)rs   r   r!  r   s     rF   r   zEdit.set_text  s0     tW%&B,DJ + , 	,rG   c                 `    |\  }| j                   \  }}||k7  r| j                  |f      d   S |S )a  
        Return the preferred column for the cursor, or the
        current cursor x value.  May also return ``'left'`` or ``'right'``
        to indicate the leftmost or rightmost column available.

        This method is used internally and by other widgets when
        moving the cursor up or down between widgets so that the
        column selected is one that the user would expect.

        >>> size = (10,)
        >>> Edit().get_pref_col(size)
        0
        >>> e = Edit(u"", u"word")
        >>> e.get_pref_col(size)
        4
        >>> e.keypress(size, 'left')
        >>> e.get_pref_col(size)
        3
        >>> e.keypress(size, 'end')
        >>> e.get_pref_col(size)
        'right'
        >>> e = Edit(u"", u"2\nwords")
        >>> e.keypress(size, 'left')
        >>> e.keypress(size, 'up')
        >>> e.get_pref_col(size)
        4
        >>> e.keypress(size, 'left')
        >>> e.get_pref_col(size)
        0
        r   )pref_col_maxcolget_cursor_coords)rj   rW   r   pref_colthen_maxcols        rF   get_pref_colzEdit.get_pref_col  s@    > 	 $ 4 4+& ))6)4Q77OrG   c                     t        d      )z
        No longer supported.

        >>> Edit().update_text()
        Traceback (most recent call last):
        EditError: update_text() has been removed.  Use set_caption() or set_edit_text() instead.
        zNupdate_text() has been removed.  Use set_caption() or set_edit_text() instead.)r!  r   s    rF   update_textzEdit.update_text  s      8 9 	9rG   c                 T    t        |      \  | _        | _        | j                          y)au  
        Set the caption markup for this widget.

        :param caption: markup for caption preceding edit_text, see
                        :meth:`Text.__init__` for description of text markup.

        >>> e = Edit("")
        >>> e.set_caption("cap1")
        >>> print(e.caption)
        cap1
        >>> e.set_caption(('bold', "cap2"))
        >>> print(e.caption)
        cap2
        >>> e.attrib
        [('bold', 4)]
        >>> e.caption = "cap3"  # not supported because caption stores text but set_caption() takes markup
        Traceback (most recent call last):
        AttributeError: can't set attribute
        N)r	   r=  r   r   )rj   r8  s     rF   r2  zEdit.set_caption  s#    ( ':'&B#t|rG   c                     | j                   S ry   )r=  r   s    rF   r   zEdit.<lambda>  s
    4== rG   zK
        Read-only property returning the caption for this widget.
        r   c                     |dk  rd}|t        | j                        kD  rt        | j                        }d| _        d| _        || _        | j                          y)a  
        Set the cursor position with a self.edit_text offset.
        Clips pos to [0, len(edit_text)].

        :param pos: cursor position
        :type pos: int

        >>> e = Edit(u"", u"word")
        >>> e.edit_pos
        4
        >>> e.set_edit_pos(2)
        >>> e.edit_pos
        2
        >>> e.edit_pos = -1  # Urwid 0.9.9 or later
        >>> e.edit_pos
        0
        >>> e.edit_pos = 20
        >>> e.edit_pos
        4
        r   NNN)rU   r3  	highlightrC  r1  r   )rj   poss     rF   r5  zEdit.set_edit_pos  sQ    * 7CT__%%doo&C)rG   c                     | j                   S ry   )r1  r   s    rF   r   zEdit.<lambda>2  s
    DNN rG   zI
        Property controlling the edit position for this widget.
        c                 2    || _         | j                          y)z
        Set the character for masking text away.

        :param mask: hide text entered with this character, None:disable mask
        :type mask: bytes or unicode
        N)r@  r   )rj   r;  s     rF   r6  zEdit.set_mask6  s     
rG   c                    | j                  |      }d| _        | j                  d|       | j                  }|| _        | j                  t        |      kD  rt        |      | _        | j                  d|       | j                          y)a  
        Set the edit text for this widget.

        :param text: text for editing, type (bytes or unicode)
                     must match the text in the caption
        :type text: bytes or unicode

        >>> e = Edit()
        >>> e.set_edit_text(u"yes")
        >>> print(e.edit_text)
        yes
        >>> e
        <Edit selectable flow widget 'yes' edit_pos=0>
        >>> e.edit_text = u"no"  # Urwid 0.9.9 or later
        >>> print(e.edit_text)
        no
        Nr$  r%  )_normalize_to_captionrN  r   r3  r:  rU   r   )rj   r   old_texts      rF   r4  zEdit.set_edit_textA  sn    $ ))$/

8T"??==3t9$IDM

<*rG   c                     | j                   S )z
        Return the edit text for this widget.

        >>> e = Edit(u"What? ", u"oh, nothing.")
        >>> print(e.get_edit_text())
        oh, nothing.
        >>> print(e.edit_text)
        oh, nothing.
        )r3  r   s    rF   get_edit_textzEdit.get_edit_text]  s     rG   zE
        Property controlling the edit text for this widget.
        c                     | j                  |      }| j                  |      \  }}| j                  |       | j                  |       d| _        y)aM  
        Insert text at the cursor position and update cursor.
        This method is used by the keypress() method when inserting
        one or more characters into edit_text.

        :param text: text for inserting, type (bytes or unicode)
                     must match the text in the caption
        :type text: bytes or unicode

        >>> e = Edit(u"", u"42")
        >>> e.insert_text(u".5")
        >>> e
        <Edit selectable flow widget '42.5' edit_pos=4>
        >>> e.set_edit_pos(2)
        >>> e.insert_text(u"a")
        >>> print(e.edit_text)
        42a.5
        N)rS  insert_text_resultr4  r5  rN  )rj   r   result_text
result_poss       rF   insert_textzEdit.insert_textm  sL    & ))$/"&"9"9$"?Z;'*%rG   c                     t        |t              }t        | j                  t              }||k(  r|S |r|j                  d      S |j	                  d      S )zc
        Return text converted to the same type as self.caption
        (bytes or unicode)
        ascii)
isinstancer   r=  encodedecode)rj   r   tucus       rF   rS  zEdit._normalize_to_caption  sM    
 i(y18K;;w''{{7##rG   c                 \   | j                  |      }| j                  r5| j                  \  }}| j                  d| | j                  |d }}||z   }|}n| j                  }| j                  }	 |d| |z   ||d z   }|t        |      z  }||fS #  J t	        | j                  ||f             xY w)a!  
        Return result of insert_text(text) without actually performing the
        insertion.  Handy for pre-validation.

        :param text: text for inserting, type (bytes or unicode)
                     must match the text in the caption
        :type text: bytes or unicode
        N)rS  rN  r9  r:  r   rU   )rj   r   startstopbtextetextrY  rZ  s           rF   rX  zEdit.insert_text_result  s     ))$/>>..KE4>>&514>>$%3H5E 5=KJ..KJ	@&{
3d:JK()K 	c$i
Z((	@?dDNNK>??1s   ,B B+c                 T   |\  }| j                   }| j                  |      rMt        |t              r+t        | j                  t              s|j                  d      }| j                  |       y|dk(  r3| j                  r'dd| j                   dz  z
  z  }| j                  |       y|dk(  r | j                  rd}| j                  |       y| j                  |   t        k(  r0|dk(  r|S t        | j                  d|      }| j                  |       y| j                  |   t        k(  rV|t        | j                        k\  r|S t!        | j                  |t        | j                              }| j                  |       y| j                  |   t"        t$        fv rjd| _        | j)                  |f      \  }}| j+                  |f      }|J | j                  |   t"        k(  r|d	z  }n|d	z  }| j-                  |f||      s|S y|d
k(  rd| _        | j1                         sh|dk(  r|S t        | j                  d|      }| j3                  | j                  d| | j                  | j                   d z          | j                  |       yy|dk(  rd| _        | j1                         s}|t        | j                        k\  r|S t!        | j                  |t        | j                              }| j3                  | j                  d| j                    | j                  |d z          yy| j                  |   t4        t6        fv rkd| _        d| _        | j)                  |f      \  }}| j                  |   t4        k(  r| j-                  |ft8        |       y| j-                  |ft:        |       y|S )a  
        Handle editing keystrokes, return others.

        >>> e, size = Edit(), (20,)
        >>> e.keypress(size, 'x')
        >>> e.keypress(size, 'left')
        >>> e.keypress(size, '1')
        >>> print(e.edit_text)
        1x
        >>> e.keypress(size, 'backspace')
        >>> e.keypress(size, 'end')
        >>> e.keypress(size, '2')
        >>> print(e.edit_text)
        x2
        >>> e.keypress(size, 'shift f1')
        'shift f1'
        zutf-8tabr      enterr  r   NrS   	backspacerM  delete)r:  r+  r^  r   r=  r_  r[  r0  r/  r   r   r   r9  r5  r   rU   r   r   r   rN  rD  rG  move_cursor_to_coordsrC  _delete_highlightedr4  r   r   r  RIGHT)rj   rW   keyr   pxyrE  s           rF   keypresszEdit.keypress  s`   $ 	MM??33	*t}}i8 jj)S!%ZDNNq$--/*+CS!'\dnnCS!s#{2!tCZt~~a2Aa s#|3C''t~~aDNN0CDAa s#	;'??!DN((&3CAa((&3H'''   %2AFAq&!--viC
 D +#-D ++-6#:"4>>!A6""DNN2A$6NN4==>2%3 5!!1& . (]#-D ++-DNN++J"4>>!C4GH""DNN>DMM$BNN12&%' )	 . s#9I'JJ!DN#-D ((&3CAa  %8**F9dA>  **F9eQ? JrG   c                    |\  }| j                  |      }| j                  |d      \  }}||k  s|t        |      k\  ryt        | j	                         d   |||      }|t        | j
                        z
  }	|	dk  rd}	|	t        | j                        kD  rt        | j                        }	|	| _        ||f| _        | j                          y)a  
        Set the cursor position with (x,y) coordinates.
        Returns True if move succeeded, False otherwise.

        >>> size = (10,)
        >>> e = Edit("","edit\ntext")
        >>> e.move_cursor_to_coords(size, 5, 0)
        True
        >>> e.edit_pos
        4
        >>> e.move_cursor_to_coords(size, 5, 3)
        False
        >>> e.move_cursor_to_coords(size, 0, 1)
        True
        >>> e.edit_pos
        5
        r   FT)
r  position_coordsrU   r   r   r8  r9  r:  rC  r   )
rj   rW   rs  rt  r   r  top_xtop_yrO  e_poss
             rF   rn  zEdit.move_cursor_to_coords  s    $ 	))&1++FA6uu9SZ*E1a9c$,,''19ae3t~~&&DNN0C &yrG   c                 >    |\  }|dk(  r| j                  |f||      S y)z
        Move the cursor to the location clicked for button 1.

        >>> size = (20,)
        >>> e = Edit("","words here")
        >>> e.mouse_event(size, 'mouse press', 1, 2, 0, True)
        True
        >>> e.edit_pos
        2
        rS   Nrn  )rj   rW   eventbuttonrs  rt  rd   r   s           rF   mouse_eventzEdit.mouse_event2  s.     	19--y!Q@@ rG   c                     | j                   sy| j                   \  }}| j                  d| | j                  |d }}| j                  ||z          || _        d| _         y)zm
        Delete all highlighted text and update cursor position, if any
        text is highlighted.
        NT)rN  r9  r4  r:  )rj   rd  re  rf  rg  s        rF   ro  zEdit._delete_highlightedB  s\    
 ~~vnnt~~fu-t~~de/DuEEM+rG   c                     |\  }t        |      | _        t        j                  | |f      }|r"t	        |      }| j                  |f      |_        |S )a  
        Render edit widget and return canvas.  Include cursor when in
        focus.

        >>> c = Edit("? ","yes").render((10,), focus=True)
        >>> c.text # ... = b in Python 3
        [...'? yes     ']
        >>> c.cursor
        (5, 0)
        )rm   r7  r   r7   r   rD  cursorr   s        rF   r7   zEdit.renderP  sQ     	%)%["{{4	*"4(D00&;DK rG   c                 v   t         j                  | ||      }| j                  s|S | j                         \  }}t	        ||| j
                  t        | j                        z         \  }}|dk  r |d | t        ||   |       gz   ||dz   d  z   S ||k\  r&|d | t        ||   ||z
  dz          gz   ||dz   d  z   S |S )Nr   rS   )	r   r  r7  r   r   r:  rU   r8  r   )rj   r   r  r  r   ignorers  rt  s           rF   r  zEdit.get_line_translationj  s    ))$;))L}}f4MMC--0!q52AYeAhr*+,!+   &[2AYeAh6!}567!+   rG   c                 P    |\  }d| _         | j                  || j                        S )z
        Return the (*x*, *y*) coordinates of cursor within widget.

        >>> Edit("? ","yes").get_cursor_coords((10,))
        (5, 0)
        T)r7  rw  r:  )rj   rW   r   s      rF   rD  zEdit.get_cursor_coords}  s*     	%)"##F4==99rG   c                     |t        | j                        z   }| j                  |      }t        | j	                         d   ||      \  }}||fS )zR
        Return (*x*, *y*) coordinates for an offset into self.edit_text.
        r   )rU   r8  r  r   r   )rj   r   rO  rr  r  rs  rt  s          rF   rw  zEdit.position_coords  sM    
 #dll##))&1$--/!,eA6!s
rG   rl   ry   )%rH   rI   rJ   rK   r   r9   r   r+  r  r  r<   r   r   r   r   rG  rI  r2  r   r8  r5  r:  r6  r4  rV  r9  r[  rS  rX  ru  rn  r  ro  r7   r  rD  rw  rP   rG   rF   r#  r#  B  s    & KL&G	D  #cUUe$T.+`45
U(,&$L	9. 0 7 G< 2L G H	8
  < I2$):_BBA 4&
:rG   r#  c                   *    e Zd ZdZd ZddZd Zd Zy)IntEditzEdit widget for integer valuesc                 *    t        |      dk(  xr |dv S )z1
        Return true for decimal digits.
        rS   
0123456789)rU   r)  s     rF   r+  zIntEdit.valid_char  s     2wz0bL00rG   Nc                 \    |t        |      }nd}| j                  j                  ||       y)z
        caption -- caption markup
        default -- default edit value

        >>> IntEdit(u"", 42)
        <IntEdit selectable flow widget '42' edit_pos=2>
        Nr,  )str_IntEdit__superr<   )rj   r8  defaultr   s       rF   r<   zIntEdit.__init__  s+     c'lcgc*rG   c                 @   |\  }t         j                  | |f|      }|s| j                  dkD  rp| j                  dd dk(  r^| j	                  | j                  dz
         | j                  | j                  dd        | j                  dkD  r| j                  dd dk(  r^|S )a8  
        Handle editing keystrokes.  Remove leading zeros.

        >>> e, size = IntEdit(u"", 5002), (10,)
        >>> e.keypress(size, 'home')
        >>> e.keypress(size, 'delete')
        >>> print(e.edit_text)
        002
        >>> e.keypress(size, 'end')
        >>> print(e.edit_text)
        2
        r   NrS   0)r#  ru  r:  r9  r5  r4  )rj   rW   rq  r   	unhandleds        rF   ru  zIntEdit.keypress  s     	MM$y5	--!#r(:c(A!!4==1#45""4>>!"#56 --!#r(:c(A rG   c                 F    | j                   rt        | j                         S y)z
        Return the numeric value of self.edit_text.

        >>> e, size = IntEdit(), (10,)
        >>> e.keypress(size, '5')
        >>> e.keypress(size, '1')
        >>> e.value() == 51
        True
        r   )r9  intr   s    rF   valuezIntEdit.value  s     >>t~~&&rG   )r,  N)rH   rI   rJ   rK   r+  r<   ru  r  rP   rG   rF   r  r    s    (1
+0rG   r  c                 @    t        |        G fddt              }|S )z
    Return a mixin class that delegates all standard widget methods
    to an attribute given by attribute_name.

    This mixin is designed to be used as a superclass of another widget.
    c                       e Zd ZdgZd fd	Z e fd      Z e fd      Z e fd      Z e fd      Z	 e fd      Z
 e fd      Z e fd	      Z e fd
      Z e fd      Zy)7delegate_to_widget_mixin.<locals>.DelegateToWidgetMixinr8   c                 L     |       j                  ||      }t        |      S rc   )r7   r   )rj   rW   rd   rX   get_delegates       rF   r7   z>delegate_to_widget_mixin.<locals>.DelegateToWidgetMixin.render  s(    %,,T,?D"4((rG   c                 (     |       j                   S ry   )r   rj   r  s    rF   r   z@delegate_to_widget_mixin.<locals>.DelegateToWidgetMixin.<lambda>  s    ,t*<*G*G rG   c                 (     |       j                   S ry   )rD  r  s    rF   r   z@delegate_to_widget_mixin.<locals>.DelegateToWidgetMixin.<lambda>  s    T*<< rG   c                 (     |       j                   S ry   )rG  r  s    rF   r   z@delegate_to_widget_mixin.<locals>.DelegateToWidgetMixin.<lambda>  s    L,>,K,K rG   c                 (     |       j                   S ry   )ru  r  s    rF   r   z@delegate_to_widget_mixin.<locals>.DelegateToWidgetMixin.<lambda>  s    T(:(C(C rG   c                 (     |       j                   S ry   r|  r  s    rF   r   z@delegate_to_widget_mixin.<locals>.DelegateToWidgetMixin.<lambda>  s    T*@@ rG   c                 (     |       j                   S ry   )r8   r  s    rF   r   z@delegate_to_widget_mixin.<locals>.DelegateToWidgetMixin.<lambda>      L$6$;$; rG   c                 (     |       j                   S ry   )r  r  s    rF   r   z@delegate_to_widget_mixin.<locals>.DelegateToWidgetMixin.<lambda>  s    <+=+I+I rG   c                 (     |       j                   S ry   )r   r  s    rF   r   z@delegate_to_widget_mixin.<locals>.DelegateToWidgetMixin.<lambda>  s    l4&8&?&? rG   c                 (     |       j                   S ry   )r.   r  s    rF   r   z@delegate_to_widget_mixin.<locals>.DelegateToWidgetMixin.<lambda>  r  rG   Nrl   )rH   rI   rJ   r6   r7   r   r   rD  rG  ru  rn  r8   r  r   r.   )r  s   rF   DelegateToWidgetMixinr    s{    8	) GH
$<> KLCD (@!B;<IJ?@;<rG   r  )r   r|   )attribute_namer  r  s     @rF   delegate_to_widget_mixinr    s#     n-L= =$ ! rG   c                       e Zd Zy)WidgetWrapErrorNrO   rP   rG   rF   r  r    rQ   rG   r  c                   F    e Zd Zd Zd Z ed e      ZddZ eee      Zy)
WidgetWrapc                     || _         y)a9  
        w -- widget to wrap, stored as self._w

        This object will pass the functions defined in Widget interface
        definition to self._w.

        The purpose of this widget is to provide a base class for
        widgets that compose other widgets for their display and
        behaviour.  The details of that composition should not affect
        users of the subclass.  The subclass may decide to expose some
        of the wrapped widgets by behaving like a ContainerWidget or
        WidgetDecoration, or it may hide them from outside access.
        N_wrapped_widgetrj   ws     rF   r<   zWidgetWrap.__init__  s      !rG   c                 2    || _         | j                          y)a  
        Change the wrapped widget.  This is meant to be called
        only by subclasses.

        >>> size = (10,)
        >>> ww = WidgetWrap(Edit("hello? ","hi"))
        >>> ww.render(size).text # ... = b in Python 3
        [...'hello? hi ']
        >>> ww.selectable()
        True
        >>> ww._w = Text("goodbye") # calls _set_w()
        >>> ww.render(size).text
        [...'goodbye   ']
        >>> ww.selectable()
        False
        N)r  r   r  s     rF   _set_wzWidgetWrap._set_w  s    "  !rG   c                     | j                   S ry   r  r   s    rF   r   zWidgetWrap.<lambda>  s    d22 rG   Nc                     t        d      )NzThe WidgetWrap.w member variable has been renamed to WidgetWrap._w (not intended for use outside the class and its subclasses).  Please update your code to use self._w instead of self.w.)r  r   s     rF   _raise_old_name_errorz WidgetWrap._raise_old_name_error  s     ! " 	"rG   ry   )	rH   rI   rJ   r<   r  r   _wr  r  rP   rG   rF   r  r    s0    ! & 
2F	;B" 	&(=>ArG   r  r  c                  ,    dd l } | j                          y r   )doctesttestmod)r  s    rF   _testr  &  s    OOrG   __main__N)U
__future__r   r   operatorr   urwid.compatr   r   
urwid.utilr   r	   r
   r   r   r   urwid.text_layoutr   r   r   urwidr   r   urwid.canvasr   r   r   r   urwid.command_mapr   r   r   r   r   r   r   urwid.split_reprr   r   r    r   r   r   r  rp  CENTERTOPMIDDLEBOTTOMr  ANYCLIPELLIPSISPACKGIVENRELATIVERELATIVE_100WEIGHTMetaSignalsr4   	ExceptionrN   rY   r`   r=   r>   rv   r?   objectr|   r   r   r   r   r   r   r   r   r!  r#  r  r  r  r  r  rH   rP   rG   rF   <module>r     s  , 0  22 2 ? ?   ? ? ? F F  	 		 	 #	!G// !B	) 	 0&"$B^J/ BJ$ $4$ $,$$& $4Ef EP;	 ;B		 	d,6 d,N			 	P	4 P	f:d :z!B	i 	,?)*;<f ,?` Z	G rG   