B
    't\                 @   s   d Z ddlmZ ddlmZ ddlmZ ddlmZ ddl	m
Z
 dd	lmZ dd
lmZ ddlmZmZ ddlmZmZmZ ddlZdddgZdZdZG dd deZefddZdd ZdS )z
Win32 event loop.
    )unicode_literals   )SECURITY_ATTRIBUTES   )	EventLoop)wrap_in_current_context)Future)InputHookContext)ThreadWithFuture)windllpointer)DWORDBOOLHANDLENWin32EventLoopwait_for_handlescreate_win32_eventi  c                   s   e Zd ZdZd fdd	Zd ddZdd	 Zd
d ZefddZ	dd Z
d!ddZd"ddZdd Zdd Zdd Zdd Zdd Z  ZS )#r   z
    Event loop for Windows systems.

    :param recognize_paste: When True, try to discover paste actions and turn
        the event into a BracketedPaste.
    Tc                s8   t t|   t | _g | _d| _d| _i | _d | _	d S )NF)
superr   __init__r   _event_calls_from_executorclosed_running	_read_fds_inputhook_context)selfZrecognize_paste)	__class__ =lib/python3.7/site-packages/prompt_toolkit/eventloop/win32.pyr   #   s    zWin32EventLoop.__init__Nc             C   s~   t |tst|dks"t|s"t| jr0td| jr>tdz2d| _x| s\| | qHW | j	rn| | W dd| _X dS )z
        Keep running the event loop until `future` has been set.

        :param future: :class:`prompt_toolkit.eventloop.future.Future` object.
        NzEvent loop is already runningzEvent loop already closed.TF)

isinstancer   AssertionErrorcallabler   	Exceptionr   Zdone	_run_oncer   )r   future	inputhookr   r   r   run_until_complete2   s    
z!Win32EventLoop.run_until_completec                s~   |r0 j d krt  _  fdd} j ||  t}| jkr\tj j  	  n| j
krz j
| } | d S )Nc                s   t  | rtndS )zF True when there is input ready. The inputhook should return control. r   )bool_ready_for_readingINFINITE)wait)r   r   r   readyT   s    z'Win32EventLoop._run_once.<locals>.ready)r   r	   Zcall_inputhookr)   r*   r   r   kernel32Z
ResetEvent#_process_queued_calls_from_executorr   	_run_task)r   r&   r,   handlecallbackr   )r   r   r$   M   s    





zWin32EventLoop._run_oncec          
   C   s@   y
|  W n0 t k
r: } z| d|i W d d }~X Y nX d S )NZ	exception)BaseExceptionZcall_exception_handler)r   ter   r   r   r/   e   s
    
zWin32EventLoop._run_taskc             C   s"   | j g}|| j  t||S )zS
        Return the handle that is ready for reading or `None` on timeout.
        )r   extendr   keysr   )r   timeouthandlesr   r   r   r)   m   s    z!Win32EventLoop._ready_for_readingc             C   s(   d| _ tj| j | jr$| j  d S )NT)r   r   r-   ZCloseHandler   r   close)r   r   r   r   r9   u   s    zWin32EventLoop.closeFc             C   s   t ||d}| |j |jS )z
        Run a long running function in a background thread.
        (This is recommended for code that could block the event loop.)
        Similar to Twisted's ``deferToThread``.
        )Zdaemon)r
   call_from_executorstartr%   )r   r1   Z_daemonZthr   r   r   run_in_executor~   s    zWin32EventLoop.run_in_executorc             C   s&   t |}| j| tj| j dS )zm
        Call this function in the main event loop.
        Similar to Twisted's ``callFromThread``.
        N)r   r   appendr   r-   ZSetEventr   )r   r1   Z_max_postpone_untilr   r   r   r:      s    z!Win32EventLoop.call_from_executorc             C   s6   | j d d  }| j d d = x|D ]}| | q W d S )N)r   r/   )r   Zcalls_from_executorcr   r   r   r.      s    
z2Win32EventLoop._process_queued_calls_from_executorc             C   s"   t |}t|}| || dS )z; Start watching the file descriptor for read availability. N)r   msvcrtget_osfhandleadd_win32_handle)r   fdr1   hr   r   r   
add_reader   s    
zWin32EventLoop.add_readerc             C   s   t |}| | dS )z: Stop watching the file descriptor for read availability. N)r?   r@   remove_win32_handle)r   rB   rC   r   r   r   remove_reader   s    
zWin32EventLoop.remove_readerc             C   s   t |}|| j|< dS )z' Add a Win32 handle to the event loop. N)r   r   )r   r0   r1   r   r   r   rA      s    zWin32EventLoop.add_win32_handlec             C   s   || j kr| j |= dS )z, Remove a Win32 handle from the event loop. N)r   )r   r0   r   r   r   rE      s    
z"Win32EventLoop.remove_win32_handle)T)N)F)N)__name__
__module____qualname____doc__r   r'   r$   r/   r*   r)   r9   r<   r:   r.   rD   rF   rA   rE   __classcell__r   r   )r   r   r      s   
	

c             C   sj   t | tstt |tsttt|  }||  }tjt||t	dt
|}|tkrZdS || }|S dS )z
    Waits for multiple handles. (Similar to 'select') Returns the handle which is ready.
    Returns `None` on timeout.

    http://msdn.microsoft.com/en-us/library/windows/desktop/ms687025(v=vs.85).aspx
    FN)r    listr!   intr   lenr   r-   ZWaitForMultipleObjectsr   r   WAIT_TIMEOUT)r8   r7   ZarrtypeZhandle_arrayZretrC   r   r   r   r      s    c               C   s    t jtt tdtddS )z}
    Creates a Win32 unnamed Event .

    http://msdn.microsoft.com/en-us/library/windows/desktop/ms682396(v=vs.85).aspx
    TFN)r   r-   ZCreateEventAr   r   r   r   r   r   r   r      s
    )rJ   Z
__future__r   Zwin32_typesr   baser   contextr   r%   r   r&   r	   Zutilsr
   Zctypesr   r   Zctypes.wintypesr   r   r   r?   __all__rO   r*   r   r   r   r   r   r   r   <module>   s&    