Esempio n. 1
0
 def get_text():
     formats = get_clipboard_formats()
     matching = []
     for u in (utf8, not utf8):
         if u:
             fmts = [win32con.CF_UNICODETEXT]
         else:
             fmts = [win32con.CF_TEXT, win32con.CF_OEMTEXT]
         matching += [fmt for fmt in formats if fmt in fmts]
     log("supported formats: %s (prefer utf8: %s)",
         csv(format_names(matching)), utf8)
     if not matching:
         log("no supported formats, only: %s",
             csv(format_names(formats)))
         errback()
         return True
     data_handle = None
     fmt = None
     for fmt in matching:
         data_handle = GetClipboardData(fmt)
         log("GetClipboardData(%s)=%#x", format_name(fmt), data_handle
             or 0)
         if data_handle:
             break
     if not data_handle:
         log("no valid data handle using %s (may try again)",
             csv(format_names(matching)))
         return False
     data = GlobalLock(data_handle)
     if not data:
         log("failed to lock data handle %#x (may try again)",
             data_handle)
         return False
     log("got data handle lock %#x for format '%s'", data,
         format_name(fmt))
     try:
         if fmt == win32con.CF_UNICODETEXT:
             try:
                 v = w_to_utf8(data)
             except Exception as e:
                 log("w_to_utf8(..)", exc_info=True)
                 errback(str(e))
                 return True
             callback(v)
             return True
         #CF_TEXT or CF_OEMTEXT:
         astr = cast(data, LPCSTR)
         s = astr.value.decode("latin1")
         if CONVERT_LINE_ENDINGS:
             s = s.replace("\r\n", "\n")
         b = s.encode("latin1")
         ulen = len(b)
         if ulen > MAX_CLIPBOARD_PACKET_SIZE:
             errback("text data is too large: %i characters" % ulen)
             return True
         log("got %i bytes of TEXT data: %s", len(b), ellipsizer(b))
         callback(b)
         return True
     finally:
         GlobalUnlock(data)
Esempio n. 2
0
 def get_text():
     data_handle = GetClipboardData(win32con.CF_UNICODETEXT)
     if not data_handle:
         errback("no data handle")
         return
     data = GlobalLock(data_handle)
     if not data:
         errback("failed to lock handle")
         return
     try:
         wstr = cast(data, LPCWSTR)
         ulen = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, None, 0, None, None)
         if ulen>MAX_CLIPBOARD_PACKET_SIZE:
             errback("too much data")
             return
         buf = create_string_buffer(ulen)
         l = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, byref(buf), ulen, None, None)
         if l>0:
             if buf.raw[l-1:l]==b"\0":
                 s = buf.raw[:l-1]
             else:
                 s = buf.raw[:l]
             log("got %i bytes of data: %s", len(s), repr_ellipsized(str(s)))
             callback(strtobytes(s))
         else:
             errback("failed to convert to UTF8: %s" % FormatError(get_last_error()))
     finally:
         GlobalUnlock(data)
Esempio n. 3
0
    def set_clipboard_image(self, img_format, img_data):
        image_formats = {}
        if COMPRESSED_IMAGES:
            #first save it as binary compressed data:
            fmt_name = LPCSTR(img_format.upper().encode("latin1")+b"\0")   #ie: "PNG"
            fmt = RegisterClipboardFormatA(fmt_name)
            if fmt:
                buf = create_string_buffer(img_data)
                pbuf = cast(byref(buf), c_void_p)
                l = len(img_data)
                data_handle = GlobalAlloc(GMEM_MOVEABLE, l)
                if not data_handle:
                    log.error("Error: failed to allocate %i bytes of global memory", l)
                    return True
                data = GlobalLock(data_handle)
                if not data:
                    log("failed to lock data handle %#x (may try again)", data_handle)
                    return False
                log("got data handle lock %#x for %i bytes of '%s' data", data, l, img_format)
                try:
                    memmove(data, pbuf, l)
                finally:
                    GlobalUnlock(data)
                image_formats[fmt] = data_handle

        #also convert it to a bitmap:
        from PIL import Image
        buf = BytesIO(img_data)
        img = Image.open(buf)
        if img.mode!="RGBA":
            img = img.convert("RGBA")
        rgb_data = img.tobytes("raw", "BGRA")
        w, h = img.size
        log("set_clipboard_image(%s, %s) image size=%s, BGR buffer=%i bytes",
            img_format, ellipsizer(data), img.size, len(rgb_data))
        header = BITMAPINFOHEADER()
        memset(byref(header), 0, sizeof(BITMAPINFOHEADER ))
        header.biSize       = sizeof(BITMAPINFOHEADER)
        header.biWidth      = w
        header.biHeight     = -h
        header.biPlanes     = 1
        header.biBitCount   = 32
        header.biCompression    = BI_RGB
        header.biSizeImage      = 0
        header.biXPelsPerMeter  = 10
        header.biYPelsPerMeter  = 10
        bitmapinfo = BITMAPINFO()
        bitmapinfo.bmiColors = 0
        memmove(byref(bitmapinfo.bmiHeader), byref(header), sizeof(BITMAPINFOHEADER))
        rgb_buf = create_string_buffer(rgb_data)
        pbuf = cast(byref(rgb_buf), c_void_p)
        hdc = GetDC(None)
        CBM_INIT = 4
        bitmap = CreateDIBitmap(hdc, byref(header), CBM_INIT, pbuf, byref(bitmapinfo), win32con.DIB_RGB_COLORS)
        ReleaseDC(None, hdc)
        image_formats[win32con.CF_BITMAP] = bitmap

        self.do_set_clipboard_image(image_formats)
Esempio n. 4
0
 def set_clipboard_text(self, text):
     #convert to wide char
     #get the length in wide chars:
     if CONVERT_LINE_ENDINGS:
         text = text.decode("utf8").replace("\n", "\r\n").encode("utf8")
     wlen = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, text, len(text), None, 0)
     if not wlen:
         self.set_err("failed to prepare to convert to wide char")
         return True
     log("MultiByteToWideChar wlen=%i", wlen)
     #allocate some memory for it:
     l = (wlen+1)*2
     buf = GlobalAlloc(GMEM_MOVEABLE, l)
     if not buf:
         self.set_err("failed to allocate %i bytes of global memory" % l)
         return True
     log("GlobalAlloc buf=%#x", buf)
     locked = GlobalLock(buf)
     if not locked:
         self.set_err("failed to lock buffer %#x" % buf)
         GlobalFree(buf)
         return True
     try:
         locked_buf = cast(locked, LPWSTR)
         r = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, text, len(text), locked_buf, wlen)
         if not r:
             self.set_err("failed to convert to wide char")
             GlobalFree(buf)
             return True
     finally:
         GlobalUnlock(locked)
     #we're going to alter the clipboard ourselves,
     #ignore messages until we're done:
     self._block_owner_change = True
     def cleanup():
         GLib.idle_add(self.remove_block)
     def set_clipboard_data():
         r = EmptyClipboard()
         log("EmptyClipboard()=%s", r)
         if not r:
             self.set_err("failed to empty the clipboard")
             return False
         r = SetClipboardData(win32con.CF_UNICODETEXT, buf)
         if not r:
             e = WinError(GetLastError())
             log("SetClipboardData(CF_UNICODETEXT, %i chars)=%s (%s)", wlen, r, e)
             return False
         log("SetClipboardData(CF_UNICODETEXT, %i chars)=%s", wlen, r)
         cleanup()
         return True
     def set_clipboard_error(error_text=""):
         log("set_clipboard_error(%s)", error_text)
         if error_text:
             log.warn("Warning: failed to set clipboard data")
             log.warn(" %s", error_text)
         cleanup()
     self.with_clipboard_lock(set_clipboard_data, set_clipboard_error)
Esempio n. 5
0
 def do_set_clipboard_text(self, text):
     #convert to wide char
     #get the length in wide chars:
     wlen = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, text, len(text), None, 0)
     if not wlen:
         self.set_err("failed to prepare to convert to wide char")
         return False
     log("MultiByteToWideChar wlen=%i", wlen)
     #allocate some memory for it:
     l = (wlen+1)*2
     buf = GlobalAlloc(GMEM_MOVEABLE, l)
     if not buf:
         self.set_err("failed to allocate %i bytes of global memory" % l)
         return False
     log("GlobalAlloc buf=%#x", buf)
     locked = GlobalLock(buf)
     if not locked:
         self.set_err("failed to lock buffer %#x" % buf)
         GlobalFree(buf)
         return False
     try:
         locked_buf = cast(locked, LPWSTR)
         r = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, text, len(text), locked_buf, wlen)
         if not r:
             self.set_err("failed to convert to wide char")
             return False
     finally:
         GlobalUnlock(locked)
     #we're going to alter the clipboard ourselves,
     #ignore messages until we're done:
     self._block_owner_change = True
     #def empty_error():
     #    self.set_err("failed to empty the clipboard")
     #self.with_clipboard_lock(EmptyClipboard, empty_error)
     def cleanup():
         GlobalFree(buf)
         glib.idle_add(self.remove_block)
     ret = [False]
     def do_set_data():
         if not EmptyClipboard():
             self.set_err("failed to empty the clipboard")
         if not SetClipboardData(win32con.CF_UNICODETEXT, buf):
             #no need to warn here
             #set_clipboard_text() will try again
             return
         log("SetClipboardData(..) done")
         cleanup()
         ret[0] = True
     def set_error(error_text=""):
         log.error("Error: failed to set clipboard data")
         if error_text:
             log.error(" %s", error_text)
         cleanup()
     self.with_clipboard_lock(do_set_data, set_error)
     return ret[0]
Esempio n. 6
0
 def get_text():
     formats = []
     fmt = 0
     while True:
         fmt = EnumClipboardFormats(fmt)
         if fmt:
             formats.append(fmt)
         else:
             break
     log("clipboard formats: %s", csv(format_name(x) for x in formats))
     matching = []
     for u in (utf8, not utf8):
         if u:
             fmts = [win32con.CF_UNICODETEXT]
         else:
             fmts = [win32con.CF_TEXT, win32con.CF_OEMTEXT]
         matching += [fmt for fmt in formats if fmt in fmts]
     log("supported formats: %s (prefer utf8: %s)",
         csv(format_name(x) for x in matching), utf8)
     if not matching:
         log("no supported formats, only: %s",
             csv(format_name(x) for x in formats))
         errback()
         return True
     data_handle = None
     for fmt in matching:
         data_handle = GetClipboardData(fmt)
         log("GetClipboardData(%s)=%#x", format_name(fmt), data_handle
             or 0)
         if data_handle:
             break
     if not data_handle:
         log("no valid data handle using %s (may try again)",
             csv(format_name(x) for x in matching))
         return False
     data = GlobalLock(data_handle)
     if not data:
         log("failed to lock data handle %#x (may try again)",
             data_handle)
         return False
     log("got data handle lock %#x for format '%s'", data,
         format_name(fmt))
     try:
         if fmt == win32con.CF_UNICODETEXT:
             wstr = cast(data, LPCWSTR)
             ulen = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, None, 0,
                                        None, None)
             if ulen > MAX_CLIPBOARD_PACKET_SIZE:
                 errback("unicode data is too large: %i bytes" % ulen)
                 return True
             buf = create_string_buffer(ulen)
             l = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, byref(buf),
                                     ulen, None, None)
             if l == 0:
                 errback("failed to convert to UTF8: %s" %
                         FormatError(get_last_error()))
                 return True
             if buf.raw[l - 1:l] == b"\0":
                 s = buf.raw[:l - 1]
             else:
                 s = buf.raw[:l]
             log("got %i bytes of UNICODE data: %s", len(s),
                 ellipsizer(s))
             if CONVERT_LINE_ENDINGS:
                 v = s.decode("utf8").replace("\r\n",
                                              "\n").encode("utf8")
             else:
                 v = strtobytes(s)
             callback(v)
             return True
         #CF_TEXT or CF_OEMTEXT:
         astr = cast(data, LPCSTR)
         s = astr.value.decode("latin1")
         if CONVERT_LINE_ENDINGS:
             s = s.replace("\r\n", "\n")
         b = s.encode("latin1")
         ulen = len(b)
         if ulen > MAX_CLIPBOARD_PACKET_SIZE:
             errback("text data is too large: %i characters" % ulen)
             return True
         log("got %i bytes of TEXT data: %s", len(b), ellipsizer(b))
         callback(b)
         return True
     finally:
         GlobalUnlock(data)
Esempio n. 7
0
        def got_clipboard_lock():
            if COMPRESSED_IMAGES:
                fmt_name = LPCSTR(img_format.upper().encode("latin1") +
                                  b"\0")  #ie: "PNG"
                fmt = RegisterClipboardFormatA(fmt_name)
                if fmt:
                    data_handle = GetClipboardData(fmt)
                    if data_handle:
                        size = GlobalSize(data_handle)
                        data = GlobalLock(data_handle)
                        log("GetClipboardData(%s)=%#x size=%s, data=%#x",
                            img_format.upper(), data_handle, size, data)
                        if data and size:
                            try:
                                cdata = (c_char * size).from_address(data)
                            finally:
                                GlobalUnlock(data)
                            got_image(bytes(cdata), False)
                            return True

            data_handle = GetClipboardData(win32con.CF_DIBV5)
            log("CF_BITMAP=%s", data_handle)
            data = GlobalLock(data_handle)
            if not data:
                log("failed to lock data handle %#x (may try again)",
                    data_handle)
                return False
            try:
                header = cast(data, PBITMAPV5HEADER).contents
                offset = header.bV5Size + header.bV5ClrUsed * 4
                w, h = header.bV5Width, abs(header.bV5Height)
                bits = header.bV5BitCount
                log(
                    "offset=%s, width=%i, height=%i, compression=%s", offset,
                    w, h,
                    BI_FORMATS.get(header.bV5Compression,
                                   header.bV5Compression))
                log("planes=%i, bitcount=%i", header.bV5Planes, bits)
                log("colorspace=%s",
                    COLOR_PROFILES.get(header.bV5CSType, header.bV5CSType))
                #if header.bV5Compression in (BI_JPEG, BI_PNG):
                #    pass
                if header.bV5Compression != BI_RGB:
                    errback(
                        "cannot handle %s compression yet" % BI_FORMATS.get(
                            header.bV5Compression, header.bV5Compression))
                    return True
                if bits == 24:
                    save_format = "RGB"
                    rgb_format = "BGR"
                    stride = roundup(w * 3, 4)
                elif bits == 32:
                    save_format = "RGBA"
                    rgb_format = "BGRA"
                    stride = w * 4
                else:
                    errback(
                        "cannot handle image data with %i bits per pixel yet" %
                        bits)
                    return True
                img_size = stride * h
                rgb_data = (c_char * img_size).from_address(data + offset)
                from PIL import Image, ImageOps
                img = Image.frombytes(save_format, (w, h), rgb_data, "raw",
                                      rgb_format, stride, 1)
                if header.bV5Height > 0:
                    img = ImageOps.flip(img)
                buf = BytesIO()
                img.save(buf, format=save_format)
                data = buf.getvalue()
                buf.close()
                got_image(data, True)
                return True
            finally:
                GlobalUnlock(data)