mirror of
https://github.com/clinton-hall/nzbToMedia.git
synced 2025-07-31 12:00:04 -07:00
190 lines
4.7 KiB
Python
190 lines
4.7 KiB
Python
from __future__ import with_statement, print_function
|
|
|
|
import sys
|
|
import re
|
|
import itertools
|
|
from contextlib import contextmanager
|
|
import io
|
|
|
|
import six
|
|
import ctypes
|
|
from ctypes import windll
|
|
|
|
from jaraco.windows.api import clipboard, memory
|
|
from jaraco.windows.error import handle_nonzero_success, WindowsError
|
|
from jaraco.windows.memory import LockedMemory
|
|
|
|
__all__ = (
|
|
'CF_TEXT', 'GetClipboardData', 'CloseClipboard',
|
|
'SetClipboardData', 'OpenClipboard',
|
|
)
|
|
|
|
def OpenClipboard(owner=None):
|
|
"""
|
|
Open the clipboard.
|
|
|
|
owner
|
|
[in] Handle to the window to be associated with the open clipboard.
|
|
If this parameter is None, the open clipboard is associated with the
|
|
current task.
|
|
"""
|
|
handle_nonzero_success(windll.user32.OpenClipboard(owner))
|
|
|
|
CloseClipboard = lambda: handle_nonzero_success(windll.user32.CloseClipboard())
|
|
|
|
data_handlers = dict()
|
|
def handles(*formats):
|
|
def register(func):
|
|
for format in formats:
|
|
data_handlers[format] = func
|
|
return func
|
|
return register
|
|
|
|
def nts(s):
|
|
"""
|
|
Null Terminated String
|
|
Get the portion of s up to a null character.
|
|
"""
|
|
result, null, rest = s.partition('\x00')
|
|
return result
|
|
|
|
@handles(clipboard.CF_DIBV5, clipboard.CF_DIB)
|
|
def raw_data(handle):
|
|
return LockedMemory(handle).data
|
|
|
|
@handles(clipboard.CF_TEXT)
|
|
def text_string(handle):
|
|
return nts(raw_data(handle))
|
|
|
|
@handles(clipboard.CF_UNICODETEXT)
|
|
def unicode_string(handle):
|
|
return nts(raw_data(handle).decode('utf-16'))
|
|
|
|
@handles(clipboard.CF_BITMAP)
|
|
def as_bitmap(handle):
|
|
# handle is HBITMAP
|
|
raise NotImplementedError("Can't convert to DIB")
|
|
# todo: use GetDIBits http://msdn.microsoft.com/en-us/library/dd144879%28v=VS.85%29.aspx
|
|
|
|
@handles(clipboard.CF_HTML)
|
|
class HTMLSnippet(object):
|
|
def __init__(self, handle):
|
|
self.data = text_string(handle)
|
|
self.headers = self.parse_headers(self.data)
|
|
|
|
@property
|
|
def html(self):
|
|
return self.data[self.headers['StartHTML']:]
|
|
|
|
@staticmethod
|
|
def parse_headers(data):
|
|
d = io.StringIO(data)
|
|
def header_line(line):
|
|
return re.match('(\w+):(.*)', line)
|
|
headers = itertools.imap(header_line, d)
|
|
# grab headers until they no longer match
|
|
headers = itertools.takewhile(bool, headers)
|
|
def best_type(value):
|
|
try:
|
|
return int(value)
|
|
except ValueError:
|
|
pass
|
|
try:
|
|
return float(value)
|
|
except ValueError:
|
|
pass
|
|
return value
|
|
pairs = (
|
|
(header.group(1), best_type(header.group(2)))
|
|
for header
|
|
in headers
|
|
)
|
|
return dict(pairs)
|
|
|
|
def GetClipboardData(type=clipboard.CF_UNICODETEXT):
|
|
if not type in data_handlers:
|
|
raise NotImplementedError("No support for data of type %d" % type)
|
|
handle = clipboard.GetClipboardData(type)
|
|
if handle is None:
|
|
raise TypeError("No clipboard data of type %d" % type)
|
|
return data_handlers[type](handle)
|
|
|
|
EmptyClipboard = lambda: handle_nonzero_success(windll.user32.EmptyClipboard())
|
|
|
|
def SetClipboardData(type, content):
|
|
"""
|
|
Modeled after http://msdn.microsoft.com/en-us/library/ms649016%28VS.85%29.aspx#_win32_Copying_Information_to_the_Clipboard
|
|
"""
|
|
allocators = {
|
|
clipboard.CF_TEXT: ctypes.create_string_buffer,
|
|
clipboard.CF_UNICODETEXT: ctypes.create_unicode_buffer,
|
|
}
|
|
if not type in allocators:
|
|
raise NotImplementedError("Only text types are supported at this time")
|
|
# allocate the memory for the data
|
|
content = allocators[type](content)
|
|
flags = memory.GMEM_MOVEABLE
|
|
size = ctypes.sizeof(content)
|
|
handle_to_copy = windll.kernel32.GlobalAlloc(flags, size)
|
|
with LockedMemory(handle_to_copy) as lm:
|
|
ctypes.memmove(lm.data_ptr, content, size)
|
|
result = clipboard.SetClipboardData(type, handle_to_copy)
|
|
if result is None:
|
|
raise WindowsError()
|
|
|
|
def set_text(source):
|
|
with context():
|
|
EmptyClipboard()
|
|
SetClipboardData(clipboard.CF_TEXT, source)
|
|
|
|
def get_text():
|
|
with context():
|
|
result = GetClipboardData(clipboard.CF_TEXT)
|
|
return result
|
|
|
|
def set_unicode_text(source):
|
|
with context():
|
|
EmptyClipboard()
|
|
SetClipboardData(clipboard.CF_UNICODETEXT, source)
|
|
|
|
def get_unicode_text():
|
|
with context():
|
|
return GetClipboardData()
|
|
|
|
def get_html():
|
|
with context():
|
|
result = GetClipboardData(clipboard.CF_HTML)
|
|
return result
|
|
|
|
def set_html(source):
|
|
with context():
|
|
EmptyClipboard()
|
|
SetClipboardData(clipboard.CF_UNICODETEXT, source)
|
|
|
|
def get_image():
|
|
with context():
|
|
return GetClipboardData(clipboard.CF_DIB)
|
|
|
|
def paste_stdout():
|
|
getter = get_unicode_text if six.PY3 else get_text
|
|
sys.stdout.write(getter())
|
|
|
|
def stdin_copy():
|
|
setter = set_unicode_text if six.PY3 else set_text
|
|
setter(sys.stdin.read())
|
|
|
|
@contextmanager
|
|
def context():
|
|
OpenClipboard()
|
|
try:
|
|
yield
|
|
finally:
|
|
CloseClipboard()
|
|
|
|
def get_formats():
|
|
with context():
|
|
format_index = 0
|
|
while True:
|
|
format_index = clipboard.EnumClipboardFormats(format_index)
|
|
if format_index == 0: break
|
|
yield format_index
|