--- sav/fhandler_clipboard.cc 2012-07-08 02:36:47.000000000 +0200 +++ ./fhandler_clipboard.cc 2012-08-14 18:25:14.903255600 +0200 @@ -222,6 +222,7 @@ fhandler_dev_clipboard::read (void *ptr, UINT formatlist[2]; int format; LPVOID cb_data; + int rach; if (!OpenClipboard (NULL)) { @@ -243,12 +244,18 @@ fhandler_dev_clipboard::read (void *ptr, cygcb_t *clipbuf = (cygcb_t *) cb_data; if (pos < clipbuf->len) - { + { ret = ((len > (clipbuf->len - pos)) ? (clipbuf->len - pos) : len); memcpy (ptr, clipbuf->data + pos , ret); pos += ret; } } + else if ((rach = get_readahead ()) >= 0) + { + /* Deliver from read-ahead buffer. */ + * (char *) ptr = rach; + ret = 1; + } else { wchar_t *buf = (wchar_t *) cb_data; @@ -256,25 +263,46 @@ fhandler_dev_clipboard::read (void *ptr, size_t glen = GlobalSize (hglb) / sizeof (WCHAR) - 1; if (pos < glen) { + /* If caller's buffer is too small to hold at least one + max-size character, redirect algorithm to local + read-ahead buffer, finally fill class read-ahead buffer + with result and feed caller from there. */ + char * _ptr = (char *) ptr; + size_t _len = len; + char cprabuf [8 + 1]; /* need this length for surrogates */ + if (len < 8) + { + _ptr = cprabuf; + _len = 8; + } + /* Comparing apples and oranges here, but the below loop could become extremly slow otherwise. We rather return a few bytes less than possible instead of being even more slow than usual... */ - if (glen > pos + len) - glen = pos + len; + if (glen > pos + _len) + glen = pos + _len; /* This loop is necessary because the number of bytes returned by sys_wcstombs does not indicate the number of wide chars used for it, so we could potentially drop wide chars. */ while ((ret = sys_wcstombs (NULL, 0, buf + pos, glen - pos)) != (size_t) -1 - && ret > len) + && ret > _len) --glen; if (ret == (size_t) -1) ret = 0; else { - ret = sys_wcstombs ((char *) ptr, (size_t) -1, + ret = sys_wcstombs ((char *) _ptr, (size_t) -1, buf + pos, glen - pos); pos = glen; + /* If using read-ahead buffer, copy to class read-ahead buffer + and deliver first byte. */ + if (_ptr == cprabuf) + { + puts_readahead (cprabuf, ret); + * (char *) ptr = get_readahead (); + ret = 1; + } } } }