- Timestamp:
- May 29, 2013 10:46:54 AM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/GuestHost/SharedClipboard/x11-clipboard.cpp
r46301 r46307 62 62 TARGETS, 63 63 TEXT, /* Treat this as Utf8, but it may really be ascii */ 64 CTEXT,65 64 UTF8, 66 65 BMP … … 89 88 { "TEXT", TEXT, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT }, 90 89 { "text/plain", TEXT, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT }, 91 { "COMPOUND_TEXT", CTEXT, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT },92 90 { "image/bmp", BMP, VBOX_SHARED_CLIPBOARD_FMT_BITMAP }, 93 91 { "image/x-bmp", BMP, VBOX_SHARED_CLIPBOARD_FMT_BITMAP }, … … 341 339 * Go through an array of X11 clipboard targets to see if they contain a text 342 340 * format we can support, and if so choose the ones we prefer (e.g. we like 343 * Utf8 better than compoundtext).341 * Utf8 better than plain text). 344 342 * @param pCtx the clipboard backend context structure 345 343 * @param pTargets the list of targets … … 376 374 { 377 375 bool success = true; 378 Atom targets[ 3];376 Atom targets[2]; 379 377 CLIPX11FORMAT x11Format; 380 targets[0] = clipGetAtom(NULL, "COMPOUND_TEXT"); 381 targets[1] = clipGetAtom(NULL, "text/plain"); 382 targets[2] = clipGetAtom(NULL, "TARGETS"); 378 targets[0] = clipGetAtom(NULL, "text/plain"); 379 targets[1] = clipGetAtom(NULL, "TARGETS"); 383 380 x11Format = clipGetTextFormatFromTargets(pCtx, targets, 3); 384 if (clipRealFormatForX11Format(x11Format) != CTEXT)381 if (clipRealFormatForX11Format(x11Format) != TEXT) 385 382 success = false; 386 383 targets[0] = clipGetAtom(NULL, "UTF8_STRING"); 387 384 targets[1] = clipGetAtom(NULL, "text/plain"); 388 targets[2] = clipGetAtom(NULL, "COMPOUND_TEXT");389 385 x11Format = clipGetTextFormatFromTargets(pCtx, targets, 3); 390 386 if (clipRealFormatForX11Format(x11Format) != UTF8) … … 431 427 * Go through an array of X11 clipboard targets to see if we can support any 432 428 * of them and if relevant to choose the ones we prefer (e.g. we like Utf8 433 * better than compoundtext).429 * better than plain text). 434 430 * @param pCtx the clipboard backend context structure 435 431 * @param pTargets the list of targets … … 1080 1076 1081 1077 /** 1082 * Satisfy a request from X11 to convert the clipboard text to1083 * COMPOUND_TEXT. We return null-terminated text, but can cope with non-null-1084 * terminated input.1085 *1086 * @returns iprt status code1087 * @param pDisplay an X11 display structure, needed for conversions1088 * performed by Xlib1089 * @param pv the text to be converted (UCS-2 with Windows EOLs)1090 * @param cb the length of the text in @cb in bytes1091 * @param atomTypeReturn where to store the atom for the type of the data1092 * we are returning1093 * @param pValReturn where to store the pointer to the data we are1094 * returning. This should be to memory allocated by1095 * XtMalloc, which will be freed by the Xt toolkit1096 * later.1097 * @param pcLenReturn where to store the length of the data we are1098 * returning1099 * @param piFormatReturn where to store the bit width (8, 16, 32) of the1100 * data we are returning1101 */1102 static int clipWinTxtToCTextForX11CB(Display *pDisplay, PRTUTF16 pwszSrc,1103 size_t cbSrc, Atom *atomTypeReturn,1104 XtPointer *pValReturn,1105 unsigned long *pcLenReturn,1106 int *piFormatReturn)1107 {1108 char *pszTmp = NULL, *pszTmp2 = NULL;1109 size_t cbTmp = 0, cbActual = 0;1110 XTextProperty property;1111 int rc = VINF_SUCCESS, xrc = 0;1112 1113 LogRelFlowFunc(("pwszSrc=%.*ls, cbSrc=%u\n", cbSrc / 2, pwszSrc, cbSrc));1114 AssertPtrReturn(pDisplay, false);1115 AssertPtrReturn(pwszSrc, false);1116 rc = clipWinTxtBufSizeForUtf8(pwszSrc, cbSrc / 2, &cbTmp);1117 if (RT_SUCCESS(rc))1118 {1119 pszTmp = (char *)RTMemAlloc(cbTmp);1120 if (!pszTmp)1121 rc = VERR_NO_MEMORY;1122 }1123 if (RT_SUCCESS(rc))1124 rc = clipWinTxtToUtf8(pwszSrc, cbSrc, pszTmp, cbTmp + 1,1125 &cbActual);1126 /* Convert the Utf8 text to the current encoding (usually a noop). */1127 if (RT_SUCCESS(rc))1128 rc = RTStrUtf8ToCurrentCP(&pszTmp2, pszTmp);1129 /* And finally (!) convert the resulting text to compound text. */1130 if (RT_SUCCESS(rc))1131 xrc = XmbTextListToTextProperty(pDisplay, &pszTmp2, 1,1132 XCompoundTextStyle, &property);1133 if (RT_SUCCESS(rc) && xrc < 0)1134 rc = ( xrc == XNoMemory ? VERR_NO_MEMORY1135 : xrc == XLocaleNotSupported ? VERR_NOT_SUPPORTED1136 : xrc == XConverterNotFound ? VERR_NOT_SUPPORTED1137 : VERR_UNRESOLVED_ERROR);1138 RTMemFree(pszTmp);1139 RTStrFree(pszTmp2);1140 *atomTypeReturn = property.encoding;1141 *pValReturn = reinterpret_cast<XtPointer>(property.value);1142 *pcLenReturn = property.nitems + 1;1143 *piFormatReturn = property.format;1144 LogRelFlowFunc(("returning %Rrc\n", rc));1145 if (RT_SUCCESS(rc))1146 LogRelFlowFunc (("converted string is %s\n", property.value));1147 return rc;1148 }1149 1150 /**1151 1078 * Does this atom correspond to one of the two selection types we support? 1152 1079 * @param widget a valid Xt widget … … 1171 1098 AssertPtrReturnVoid(pText); 1172 1099 AssertPtrReturnVoid(pcText); 1173 AssertReturnVoid((format == UTF8) || (format == CTEXT) || (format ==TEXT));1100 AssertReturnVoid((format == UTF8) || (format == TEXT)); 1174 1101 if (((char *)pText)[*pcText - 1] == '\0') 1175 1102 --(*pcText); … … 1186 1113 *atomTarget); 1187 1114 CLIPFORMAT format = clipRealFormatForX11Format(x11Format); 1188 if ( ((format == UTF8) || (format == CTEXT) || (format ==TEXT))1115 if ( ((format == UTF8) || (format == TEXT)) 1189 1116 && (pCtx->vboxFormats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)) 1190 1117 { … … 1201 1128 atomTypeReturn, pValReturn, 1202 1129 pcLenReturn, piFormatReturn); 1203 else if (RT_SUCCESS(rc) && (format == CTEXT))1204 rc = clipWinTxtToCTextForX11CB(XtDisplay(pCtx->widget),1205 (PRTUTF16)pv, cb,1206 atomTypeReturn, pValReturn,1207 pcLenReturn, piFormatReturn);1208 1130 if (RT_SUCCESS(rc)) 1209 1131 clipTrimTrailingNul(*(XtPointer *)pValReturn, pcLenReturn, format); … … 1442 1364 1443 1365 /** 1444 * Convert COMPOUND TEXT with CR end-of-lines into Utf-16 as Windows expects1445 * it and return the result in a RTMemAlloc allocated buffer.1446 * @returns IPRT status code1447 * @param widget An Xt widget, necessary because we use Xt/Xlib for the1448 * conversion1449 * @param pcSrc The source text1450 * @param cbSrc The size of the source in bytes, not counting the1451 * terminating zero1452 * @param ppwszDest Where to store the buffer address1453 * @param pcbDest On success, where to store the number of bytes written.1454 * Undefined otherwise. Optional1455 */1456 static int clipCTextToWinTxt(Widget widget, unsigned char *pcSrc,1457 unsigned cbSrc, PRTUTF16 *ppwszDest,1458 uint32_t *pcbDest)1459 {1460 LogRelFlowFunc(("widget=%p, pcSrc=%p, cbSrc=%u, ppwszDest=%p\n", widget,1461 pcSrc, cbSrc, ppwszDest));1462 AssertReturn(widget, VERR_INVALID_PARAMETER);1463 AssertPtrReturn(pcSrc, VERR_INVALID_POINTER);1464 AssertPtrReturn(ppwszDest, VERR_INVALID_POINTER);1465 if (pcbDest)1466 *pcbDest = 0;1467 1468 /* Special case as X*TextProperty* can't seem to handle empty strings. */1469 if (cbSrc == 0)1470 {1471 *ppwszDest = (PRTUTF16) RTMemAlloc(2);1472 if (!*ppwszDest)1473 return VERR_NO_MEMORY;1474 **ppwszDest = 0;1475 if (pcbDest)1476 *pcbDest = 2;1477 return VINF_SUCCESS;1478 }1479 1480 if (pcbDest)1481 *pcbDest = 0;1482 /* Intermediate conversion to Utf8 */1483 int rc = VINF_SUCCESS;1484 XTextProperty property;1485 char **ppcTmp = NULL, *pszTmp = NULL;1486 int cProps;1487 1488 property.value = pcSrc;1489 property.encoding = clipGetAtom(widget, "COMPOUND_TEXT");1490 property.format = 8;1491 property.nitems = cbSrc;1492 int xrc = XmbTextPropertyToTextList(XtDisplay(widget), &property,1493 &ppcTmp, &cProps);1494 if (xrc < 0)1495 rc = ( xrc == XNoMemory ? VERR_NO_MEMORY1496 : xrc == XLocaleNotSupported ? VERR_NOT_SUPPORTED1497 : xrc == XConverterNotFound ? VERR_NOT_SUPPORTED1498 : VERR_UNRESOLVED_ERROR);1499 /* Convert the text returned to UTF8 */1500 if (RT_SUCCESS(rc))1501 rc = RTStrCurrentCPToUtf8(&pszTmp, *ppcTmp);1502 /* Now convert the UTF8 to UTF16 */1503 if (RT_SUCCESS(rc))1504 rc = clipUtf8ToWinTxt(pszTmp, strlen(pszTmp), ppwszDest, pcbDest);1505 if (ppcTmp != NULL)1506 XFreeStringList(ppcTmp);1507 RTStrFree(pszTmp);1508 LogRelFlowFunc(("Returning %Rrc\n", rc));1509 if (pcbDest)1510 LogRelFlowFunc(("*pcbDest=%u\n", *pcbDest));1511 return rc;1512 }1513 1514 /**1515 1366 * Convert Latin-1 text with CR end-of-lines into Utf-16 as Windows expects 1516 1367 * it and return the result in a RTMemAlloc allocated buffer. … … 1630 1481 switch (clipRealFormatForX11Format(pReq->mTextFormat)) 1631 1482 { 1632 case CTEXT:1633 rc = clipCTextToWinTxt(widget, (unsigned char *)pvSrc, cbSrc,1634 (PRTUTF16 *) &pvDest, &cbDest);1635 break;1636 1483 case UTF8: 1637 1484 case TEXT: … … 1872 1719 Display *XtDisplay(Widget w) 1873 1720 { return (Display *) 0xffff; } 1874 1875 int XmbTextListToTextProperty(Display *display, char **list, int count,1876 XICCEncodingStyle style,1877 XTextProperty *text_prop_return)1878 {1879 /* We don't fully reimplement this API for obvious reasons. */1880 AssertReturn(count == 1, XLocaleNotSupported);1881 AssertReturn(style == XCompoundTextStyle, XLocaleNotSupported);1882 /* We simplify the conversion by only accepting ASCII. */1883 for (unsigned i = 0; (*list)[i] != 0; ++i)1884 AssertReturn(((*list)[i] & 0x80) == 0, XLocaleNotSupported);1885 text_prop_return->value =1886 (unsigned char*)RTMemDup(*list, strlen(*list) + 1);1887 text_prop_return->encoding = clipGetAtom(NULL, "COMPOUND_TEXT");1888 text_prop_return->format = 8;1889 text_prop_return->nitems = strlen(*list);1890 return 0;1891 }1892 1893 int Xutf8TextListToTextProperty(Display *display, char **list, int count,1894 XICCEncodingStyle style,1895 XTextProperty *text_prop_return)1896 {1897 return XmbTextListToTextProperty(display, list, count, style,1898 text_prop_return);1899 }1900 1901 int XmbTextPropertyToTextList(Display *display,1902 const XTextProperty *text_prop,1903 char ***list_return, int *count_return)1904 {1905 int rc = 0;1906 if (text_prop->nitems == 0)1907 {1908 *list_return = NULL;1909 *count_return = 0;1910 return 0;1911 }1912 /* Only accept simple ASCII properties */1913 for (unsigned i = 0; i < text_prop->nitems; ++i)1914 AssertReturn(!(text_prop->value[i] & 0x80), XConverterNotFound);1915 char **ppList = (char **)RTMemAlloc(sizeof(char *));1916 char *pValue = (char *)RTMemAlloc(text_prop->nitems + 1);1917 if (pValue)1918 {1919 memcpy(pValue, text_prop->value, text_prop->nitems);1920 pValue[text_prop->nitems] = 0;1921 }1922 if (ppList)1923 *ppList = pValue;1924 if (!ppList || !pValue)1925 {1926 RTMemFree(ppList);1927 RTMemFree(pValue);1928 rc = XNoMemory;1929 }1930 else1931 {1932 /* NULL-terminate the string */1933 pValue[text_prop->nitems] = '\0';1934 *count_return = 1;1935 *list_return = ppList;1936 }1937 return rc;1938 }1939 1940 int Xutf8TextPropertyToTextList(Display *display,1941 const XTextProperty *text_prop,1942 char ***list_return, int *count_return)1943 {1944 return XmbTextPropertyToTextList(display, text_prop, list_return,1945 count_return);1946 }1947 1721 1948 1722 void XtAppSetExitFlag(XtAppContext app_context) {} … … 2490 2264 testStringFromX11(hTest, pCtx, "hello world", VINF_SUCCESS); 2491 2265 2492 /*** COMPOUND TEXT from X11 ***/2493 RTTestSub(hTest, "reading compound text from X11");2494 /* Simple test */2495 clipSetSelectionValues("COMPOUND_TEXT", XA_STRING, "hello world",2496 sizeof("hello world"), 8);2497 testStringFromX11(hTest, pCtx, "hello world", VINF_SUCCESS);2498 /* With an embedded carriage return */2499 clipSetSelectionValues("COMPOUND_TEXT", XA_STRING, "hello\nworld",2500 sizeof("hello\nworld"), 8);2501 testStringFromX11(hTest, pCtx, "hello\r\nworld", VINF_SUCCESS);2502 /* With an embedded CRLF */2503 clipSetSelectionValues("COMPOUND_TEXT", XA_STRING, "hello\r\nworld",2504 sizeof("hello\r\nworld"), 8);2505 testStringFromX11(hTest, pCtx, "hello\r\r\nworld", VINF_SUCCESS);2506 /* With an embedded LFCR */2507 clipSetSelectionValues("COMPOUND_TEXT", XA_STRING, "hello\n\rworld",2508 sizeof("hello\n\rworld"), 8);2509 testStringFromX11(hTest, pCtx, "hello\r\n\rworld", VINF_SUCCESS);2510 /* An empty string */2511 clipSetSelectionValues("COMPOUND_TEXT", XA_STRING, "",2512 sizeof(""), 8);2513 testStringFromX11(hTest, pCtx, "", VINF_SUCCESS);2514 /* A non-zero-terminated string */2515 clipSetSelectionValues("COMPOUND_TEXT", XA_STRING,2516 "hello world", sizeof("hello world") - 1, 8);2517 testStringFromX11(hTest, pCtx, "hello world", VINF_SUCCESS);2518 2519 2266 /*** Latin1 from X11 ***/ 2520 2267 RTTestSub(hTest, "reading Latin1 from X11"); … … 2647 2394 "hello world"); 2648 2395 2649 /*** COMPOUND TEXT from VBox ***/2650 RTTestSub(hTest, "reading COMPOUND TEXT from VBox");2651 /* Simple test */2652 clipSetVBoxUtf16(pCtx, VINF_SUCCESS, "hello world",2653 sizeof("hello world") * 2);2654 testStringFromVBox(hTest, pCtx, "COMPOUND_TEXT",2655 clipGetAtom(NULL, "COMPOUND_TEXT"), "hello world");2656 /* With an embedded carriage return */2657 clipSetVBoxUtf16(pCtx, VINF_SUCCESS, "hello\r\nworld",2658 sizeof("hello\r\nworld") * 2);2659 testStringFromVBox(hTest, pCtx, "COMPOUND_TEXT",2660 clipGetAtom(NULL, "COMPOUND_TEXT"), "hello\nworld");2661 /* With an embedded CRCRLF */2662 clipSetVBoxUtf16(pCtx, VINF_SUCCESS, "hello\r\r\nworld",2663 sizeof("hello\r\r\nworld") * 2);2664 testStringFromVBox(hTest, pCtx, "COMPOUND_TEXT",2665 clipGetAtom(NULL, "COMPOUND_TEXT"), "hello\r\nworld");2666 /* With an embedded CRLFCR */2667 clipSetVBoxUtf16(pCtx, VINF_SUCCESS, "hello\r\n\rworld",2668 sizeof("hello\r\n\rworld") * 2);2669 testStringFromVBox(hTest, pCtx, "COMPOUND_TEXT",2670 clipGetAtom(NULL, "COMPOUND_TEXT"), "hello\n\rworld");2671 /* An empty string */2672 clipSetVBoxUtf16(pCtx, VINF_SUCCESS, "", 2);2673 testStringFromVBox(hTest, pCtx, "COMPOUND_TEXT",2674 clipGetAtom(NULL, "COMPOUND_TEXT"), "");2675 /* A non-zero-terminated string */2676 clipSetVBoxUtf16(pCtx, VINF_SUCCESS, "hello world",2677 sizeof("hello world") * 2 - 2);2678 testStringFromVBox(hTest, pCtx, "COMPOUND_TEXT",2679 clipGetAtom(NULL, "COMPOUND_TEXT"), "hello world");2680 2681 2396 /*** Timeout from VBox ***/ 2682 2397 RTTestSub(hTest, "reading from VBox with timeout");
Note:
See TracChangeset
for help on using the changeset viewer.