VirtualBox

Ignore:
Timestamp:
Jun 27, 2007 5:36:14 PM (18 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
22446
Message:

Linux host clipboard fixes and added compound text to the Linux guest clipboard

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/linux/xclient/clipboard.cpp

    r3287 r3321  
    2525#define USE_UTF16
    2626#define USE_UTF8
     27#define USE_CTEXT
    2728#define USE_LATIN1
    2829
     
    8182    TARGETS,
    8283    LATIN1,
     84    CTEXT,
    8385    UTF8,
    8486    UTF16
     
    359361
    360362/**
    361  * Convert a Utf16 text with Linux EOLs to Utf16-LE with Windows EOLs, allocating memory
    362  * for the converted text.  Does no checking for validity.
     363 * Convert a Utf16 text with Linux EOLs to zero-terminated Utf16-LE with Windows EOLs, allocating
     364 * memory for the converted text.  Does no checking for validity.
    363365 *
    364366 * @returns VBox status code
     
    385387        return VINF_SUCCESS;
    386388    }
    387     AssertReturn(pu16Src != 0, VERR_INVALID_PARAMETER);
     389    AssertReturn(VALID_PTR(pu16Src), VERR_INVALID_PARAMETER);
    388390    cwDest = 0;
    389391    for (i = 0; i < cwSrc; ++i, ++cwDest)
     
    393395            ++cwDest;
    394396        }
    395     }
    396     /* Leave space for a trailing null in any case */
     397        if (pu16Src[i] == 0)
     398        {
     399            break;
     400        }
     401    }
     402    /* Leave space for a trailing null */
    397403    ++cwDest;
    398404    pu16Dest = reinterpret_cast<PRTUTF16>(RTMemAlloc(cwDest * 2));
     
    408414            pu16Dest[j] = CARRIAGERETURN;
    409415            ++j;
     416        }
     417        if (pu16Src[i] == 0)
     418        {
     419            break;
    410420        }
    411421        pu16Dest[j] = pu16Src[i];
     
    496506
    497507/**
     508 * Convert the compound text returned from the guest X11 clipboard to UTF-16LE with Windows EOLs
     509 * and send it to the host.
     510 *
     511 * @param pValue      Source compound text
     512 * @param cbSourceLen Length in 8-bit bytes of the source text
     513 */
     514static void vboxClipboardGetCText(XtPointer pValue, size_t cbSourceLen)
     515{
     516    size_t cwSourceLen, cwDestLen;
     517    char **ppu8SourceText = 0;
     518    PRTUTF16 pu16SourceText = 0, pu16DestText;
     519    XTextProperty property;
     520    int rc, cProps;
     521
     522    LogFlowFunc(("\n"));
     523    Log2 (("vboxClipboardGetCText: converting compound text to Utf-16LE. Original is %.*s\n",
     524           cbSourceLen, pValue));
     525    /* First convert the compound text to Utf8 */
     526    property.value = reinterpret_cast<unsigned char *>(pValue);
     527    property.encoding = g_ctx.atomCText;
     528    property.format = 8;
     529    property.nitems = cbSourceLen;
     530    rc = Xutf8TextPropertyToTextList(XtDisplay(g_ctx.widget), &property, &ppu8SourceText, &cProps);
     531    XtFree(reinterpret_cast<char *>(pValue));
     532    if (rc < 0)
     533    {
     534        char *pcReason;
     535        switch(rc)
     536        {
     537        case XNoMemory:
     538            pcReason = "out of memory";
     539            break;
     540        case XLocaleNotSupported:
     541            pcReason = "locale (Utf8) not supported";
     542            break;
     543        case XConverterNotFound:
     544            pcReason = "converter not found";
     545            break;
     546        default:
     547            pcReason = "unknown error";
     548        }
     549        XFreeStringList(ppu8SourceText);
     550        LogRel(("vboxClipboardGetCText: Xutf8TextPropertyToTextList failed.  Reason: %s\n",
     551                pcReason));
     552        vboxClipboardSendData (0, 0, 0);
     553        LogFlowFunc(("sending empty data and returning\n"));
     554        return;
     555    }
     556    /* Next convert the UTF8 to UTF16 */
     557    rc = RTStrToUtf16Ex(*ppu8SourceText, cbSourceLen, &pu16SourceText, 0, &cwSourceLen);
     558    XFreeStringList(ppu8SourceText);
     559    if (rc != VINF_SUCCESS)
     560    {
     561        vboxClipboardSendData (0, 0, 0);
     562        LogFlowFunc(("sending empty data and returning\n"));
     563        return;
     564    }
     565    rc = vboxClipboardUtf16LinToWin(pu16SourceText, cwSourceLen, &pu16DestText, &cwDestLen);
     566    RTMemFree(reinterpret_cast<void *>(pu16SourceText));
     567    if (rc != VINF_SUCCESS)
     568    {
     569        vboxClipboardSendData (0, 0, 0);
     570        LogFlowFunc(("sending empty data and returning\n"));
     571        return;
     572    }
     573    Log2 (("vboxClipboardGetCText: converted string is %.*ls\n", cwDestLen, pu16DestText));
     574    vboxClipboardSendData (VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
     575                            reinterpret_cast<void *>(pu16DestText), cwDestLen * 2);
     576    RTMemFree(reinterpret_cast<void *>(pu16DestText));
     577    LogFlowFunc(("returning\n"));
     578}
     579
     580/**
    498581 * Convert the Latin1 text returned from the guest X11 clipboard to UTF-16LE with Windows EOLs
    499582 * and send it to the host.
     
    572655    case UTF16:
    573656        vboxClipboardGetUtf16(pValue, cTextLen / 2);
     657        break;
     658    case CTEXT:
     659        vboxClipboardGetCText(pValue, cTextLen);
    574660        break;
    575661    case UTF8:
     
    788874
    789875/**
    790  * Get the size of the buffer needed to hold a Utf16 string with Linux EOLs converted from
    791  * a Utf16 string with Windows EOLs.
     876 * Get the size of the buffer needed to hold a zero-terminated Utf16 string with Linux EOLs
     877 * converted from a Utf16 string with Windows EOLs.
    792878 *
    793879 * @returns The size of the buffer needed in bytes
     
    801887    size_t cwDest;
    802888
    803     LogFlowFunc(("pu16Src=%.*ls, cwSrc=%u", cwSrc, pu16Src, cwSrc));
     889    LogFlowFunc(("pu16Src=%.*ls, cwSrc=%u\n", cwSrc, pu16Src, cwSrc));
    804890    AssertReturn(pu16Src != 0, VERR_INVALID_PARAMETER);
    805891    /* We only take little endian Utf16 */
     
    824910        if (pu16Src[i] == 0)
    825911        {
    826             /* The terminating zero is included in the size */
    827             ++cwDest;
    828912            break;
    829913        }
    830914    }
     915    /* The terminating null */
     916    ++cwDest;
    831917    LogFlowFunc(("returning %d\n", cwDest * 2));
    832918    return cwDest * 2;
     
    851937
    852938    LogFlowFunc(("pu16Src=%.*ls, cwSrc=%u, pu16Dest=%p, cwDest=%u\n",
    853                  cwSrc, pu16Src, cwSrc, pu16Dest, cwDest));
     939                  cwSrc, pu16Src, cwSrc, pu16Dest, cwDest));
    854940    /* A buffer of size 0 may not be an error, but it is not a good idea either. */
    855941    Assert(cwDest > 0);
    856     AssertReturn(pu16Src != 0, VERR_INVALID_PARAMETER);
     942    AssertReturn(VALID_PTR(pu16Src), VERR_INVALID_PARAMETER);
    857943    /* We only take little endian Utf16 */
    858944    AssertReturn(pu16Src[0] != 0xfffe, VERR_INVALID_PARAMETER);
     
    898984        }
    899985    }
    900     LogFlowFunc(("set string %.*ls.  Returning\n", cwDestPos, pu16Dest));
     986    if (cwDestPos == cwDest)
     987    {
     988        LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
     989        return VERR_BUFFER_OVERFLOW;
     990    }
     991    pu16Dest[cwDestPos] = 0;
     992    LogFlowFunc(("set string %ls.  Returning\n", pu16Dest + 1));
    901993    return VINF_SUCCESS;
    902994}
     
    9921084    }
    9931085    cwHostText = cbHostText / 2;
     1086    Log2 (("vboxClipboardConvertUtf8: original text is %.*ls\n", cwHostText, pu16HostText));
    9941087    cwGuestText = vboxClipboardUtf16GetLinSize(pu16HostText, cwHostText);
    9951088    pu16GuestText = reinterpret_cast<PRTUTF16>(RTMemAlloc(cwGuestText * 2));
     
    10011094    }
    10021095    rc = vboxClipboardUtf16WinToLin(pu16HostText, cwHostText, pu16GuestText, cwGuestText);
     1096    RTMemFree(reinterpret_cast<char *>(pu16HostText));
    10031097    if (rc != VINF_SUCCESS)
    10041098    {
    10051099        Log2(("vboxClipboardConvertUtf16: vboxClipboardUtf16WinToLin returned %Vrc\n", rc));
    1006         RTMemFree(reinterpret_cast<char *>(pu16HostText));
    10071100        RTMemFree(reinterpret_cast<char *>(pu16GuestText));
    10081101        LogFlowFunc(("rc = false\n"));
     
    10111104    /* Now convert the Utf16 Linux text to Utf8 */
    10121105    cbGuestText = cwGuestText * 3;  /* Should always be enough. */
    1013     if (rc != VINF_SUCCESS)
    1014     {
    1015         RTMemFree(reinterpret_cast<char *>(pu16HostText));
     1106    pcGuestText = XtMalloc(cbGuestText);
     1107    if (pcGuestText == 0)
     1108    {
    10161109        RTMemFree(reinterpret_cast<char *>(pu16GuestText));
    10171110        LogFlowFunc(("rc = false\n"));
    10181111        return false;
    10191112    }
    1020     pcGuestText = XtMalloc(cbGuestText);
    10211113    /* Our runtime can't cope with endian markers. */
    10221114    rc = RTUtf16ToUtf8Ex(pu16GuestText + 1, cwGuestText - 1, &pcGuestText, cbGuestText, 0);
     1115    RTMemFree(reinterpret_cast<char *>(pu16GuestText));
    10231116    if (rc != VINF_SUCCESS)
    10241117    {
    1025         RTMemFree(reinterpret_cast<char *>(pu16HostText));
    1026         RTMemFree(reinterpret_cast<char *>(pu16GuestText));
    10271118        XtFree(pcGuestText);
    10281119        LogFlowFunc(("rc = false\n"));
    10291120        return false;
    10301121    }
    1031     Log2 (("vboxClipboardConvertUtf8: returning Utf-8, original text is %.*ls\n", cwHostText,
    1032            pu16HostText));
    10331122    Log2 (("vboxClipboardConvertUtf8: converted text is %.*s\n", cbGuestText, pcGuestText));
    1034     RTMemFree(reinterpret_cast<char *>(pu16HostText));
    1035     RTMemFree(reinterpret_cast<char *>(pu16GuestText));
    10361123    *atomTypeReturn = g_ctx.atomUtf8;
    10371124    *pValReturn = reinterpret_cast<XtPointer>(pcGuestText);
    10381125    *pcLenReturn = cbGuestText;
    10391126    *piFormatReturn = 8;
     1127    LogFlowFunc(("rc = true\n"));
     1128    return true;
     1129}
     1130
     1131/**
     1132 * Satisfy a request from the guest to convert the clipboard text to compound text.
     1133 *
     1134 * @returns true if we successfully convert the data to the format requested, false otherwise.
     1135 *
     1136 * @param atomTypeReturn The type of the data we are returning
     1137 * @param pValReturn     A pointer to the data we are returning.  This should be to memory
     1138 *                       allocated by XtMalloc, which will be freed by the toolkit later
     1139 * @param pcLenReturn    The length of the data we are returning
     1140 * @param piFormatReturn The format (8bit, 16bit, 32bit) of the data we are returning
     1141 */
     1142static Boolean vboxClipboardConvertCText(Atom *atomTypeReturn, XtPointer *pValReturn,
     1143                                         unsigned long *pcLenReturn, int *piFormatReturn)
     1144{
     1145    PRTUTF16 pu16GuestText, pu16HostText;
     1146    char *pcUtf8Text;
     1147    unsigned cbHostText, cwHostText, cwGuestText, cbUtf8Text;
     1148    XTextProperty property;
     1149    int rc;
     1150
     1151    LogFlowFunc(("\n"));
     1152    /* Get the host Utf16 data and convert it to Linux Utf16. */
     1153    rc = vboxClipboardReadHostData(VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
     1154                                   reinterpret_cast<void **>(&pu16HostText), &cbHostText);
     1155    if ((rc != VINF_SUCCESS) || cbHostText == 0)
     1156    {
     1157        Log (("vboxClipboardConvertCText: vboxClipboardReadHostData returned %Vrc, %d bytes of data\n", rc, cbHostText));
     1158        g_ctx.hostFormats = 0;
     1159        LogFlowFunc(("rc = false\n"));
     1160        return false;
     1161    }
     1162    Log2 (("vboxClipboardConvertCText: original text is %.*ls\n", cwHostText, pu16HostText));
     1163    cwHostText = cbHostText / 2;
     1164    cwGuestText = vboxClipboardUtf16GetLinSize(pu16HostText, cwHostText);
     1165    pu16GuestText = reinterpret_cast<PRTUTF16>(RTMemAlloc(cwGuestText * 2));
     1166    if (pu16GuestText == 0)
     1167    {
     1168        Log(("vboxClipboardConvertCText: out of memory\n"));
     1169        RTMemFree(reinterpret_cast<char *>(pu16HostText));
     1170        LogFlowFunc(("rc = false\n"));
     1171        return false;
     1172    }
     1173    rc = vboxClipboardUtf16WinToLin(pu16HostText, cwHostText, pu16GuestText, cwGuestText);
     1174    RTMemFree(reinterpret_cast<char *>(pu16HostText));
     1175    if (rc != VINF_SUCCESS)
     1176    {
     1177        Log2(("vboxClipboardConvertUtf16: vboxClipboardUtf16WinToLin returned %Vrc\n", rc));
     1178        RTMemFree(reinterpret_cast<char *>(pu16GuestText));
     1179        LogFlowFunc(("rc = false\n"));
     1180        return false;
     1181    }
     1182    /* Now convert the Utf16 Linux text to Utf8 */
     1183    cbUtf8Text = cwGuestText * 3;  /* Should always be enough. */
     1184    pcUtf8Text = reinterpret_cast<char *>(RTMemAlloc(cbUtf8Text));
     1185    if (pcUtf8Text == 0)
     1186    {
     1187        Log(("vboxClipboardConvertCText: out of memory\n"));
     1188        RTMemFree(reinterpret_cast<char *>(pu16GuestText));
     1189        LogFlowFunc(("rc = false\n"));
     1190        return false;
     1191    }
     1192    /* Our runtime can't cope with endian markers. */
     1193    rc = RTUtf16ToUtf8Ex(pu16GuestText + 1, cwGuestText - 1, &pcUtf8Text, cbUtf8Text, 0);
     1194    RTMemFree(reinterpret_cast<char *>(pu16GuestText));
     1195    if (rc != VINF_SUCCESS)
     1196    {
     1197        Log(("vboxClipboardConvertCText: RTUtf16ToUtf8Ex failed: rc=%Vrc\n", rc));
     1198        XtFree(pcUtf8Text);
     1199        LogFlowFunc(("rc = false\n"));
     1200        return false;
     1201    }
     1202    /* And finally (!) convert the Utf8 text to compound text. */
     1203    rc = Xutf8TextListToTextProperty(XtDisplay(g_ctx.widget), &pcUtf8Text, 1,
     1204                                     XCompoundTextStyle, &property);
     1205    RTMemFree(pcUtf8Text);
     1206    if (rc < 0)
     1207    {
     1208        char *pcReason;
     1209        switch(rc)
     1210        {
     1211        case XNoMemory:
     1212            pcReason = "out of memory";
     1213            break;
     1214        case XLocaleNotSupported:
     1215            pcReason = "locale (Utf8) not supported";
     1216            break;
     1217        case XConverterNotFound:
     1218            pcReason = "converter not found";
     1219            break;
     1220        default:
     1221            pcReason = "unknown error";
     1222        }
     1223        LogRel(("vboxClipboardConvertCText: Xutf8TextListToTextProperty failed.  Reason: %s\n",
     1224                pcReason));
     1225        XFree(property.value);
     1226        LogFlowFunc(("rc = false\n"));
     1227        return false;
     1228    }
     1229    Log2 (("vboxClipboardConvertCText: converted text is %s\n", property.value));
     1230    *atomTypeReturn = property.encoding;
     1231    *pValReturn = reinterpret_cast<XtPointer>(property.value);
     1232    *pcLenReturn = property.nitems;
     1233    *piFormatReturn = property.format;
    10401234    LogFlowFunc(("rc = true\n"));
    10411235    return true;
     
    11601354        }
    11611355    }
    1162     if (*atomTarget == g_ctx.atomCText)
    1163     {
    1164         /* We do not support compound text conversion.  However, as we are required to do so by
    1165            the X11 standards, we return Latin-1 if we are asked to do so anyway. */
    1166         LogRel(("An application on your guest system has asked for clipboard data in COMPOUND_TEXT format.  Since VirtualBox does not support this format, international characters will get lost.  Please set up your guest applications to use Unicode!\n"));
    1167         eFormat = LATIN1;
    1168     }
    11691356    switch (eFormat)
    11701357    {
     
    11791366    case UTF8:
    11801367        rc = vboxClipboardConvertUtf8(atomTypeReturn, pValReturn, pcLenReturn, piFormatReturn);
     1368        LogFlowFunc(("rc=%d\n", rc));
     1369        return rc;
     1370    case CTEXT:
     1371        rc = vboxClipboardConvertCText(atomTypeReturn, pValReturn, pcLenReturn, piFormatReturn);
    11811372        LogFlowFunc(("rc=%d\n", rc));
    11821373        return rc;
     
    15201711                           VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT);
    15211712#endif
     1713#ifdef USE_CTEXT
     1714    vboxClipboardAddFormat("COMPOUND_TEXT", CTEXT,
     1715                           VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT);
     1716#endif
    15221717#ifdef USE_LATIN1
    15231718    vboxClipboardAddFormat("STRING", LATIN1,
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette