Add CF_UNICODETEXT as primary text clipboard format.

Use [x11drv].TextCP for interchange with X.
This commit is contained in:
Dmitry Timoshkov 2000-12-11 01:09:56 +00:00 committed by Alexandre Julliard
parent 93dd2d694f
commit 1df0d36592
6 changed files with 271 additions and 131 deletions

View File

@ -7,9 +7,9 @@
struct tagWND; struct tagWND;
typedef struct tagWINE_CLIPFORMAT { typedef struct tagWINE_CLIPFORMAT {
WORD wFormatID; UINT wFormatID;
WORD wRefCount; UINT wRefCount;
WORD wDataPresent; BOOL wDataPresent;
LPSTR Name; LPSTR Name;
HANDLE16 hData16; HANDLE16 hData16;
HANDLE hDataSrc32; HANDLE hDataSrc32;

View File

@ -58,7 +58,7 @@ static WORD LastRegFormat = CF_REGFORMATBASE;
* WARNING: This data ordering is dependendent on the WINE_CLIPFORMAT structure * WARNING: This data ordering is dependendent on the WINE_CLIPFORMAT structure
* declared in clipboard.h * declared in clipboard.h
*/ */
WINE_CLIPFORMAT ClipFormats[17] = { WINE_CLIPFORMAT ClipFormats[] = {
{ CF_TEXT, 1, 0, "Text", 0, 0, 0, 0, NULL, &ClipFormats[1]}, { CF_TEXT, 1, 0, "Text", 0, 0, 0, 0, NULL, &ClipFormats[1]},
{ CF_BITMAP, 1, 0, "Bitmap", 0, 0, 0, 0, &ClipFormats[0], &ClipFormats[2]}, { CF_BITMAP, 1, 0, "Bitmap", 0, 0, 0, 0, &ClipFormats[0], &ClipFormats[2]},
{ CF_METAFILEPICT, 1, 0, "MetaFile Picture", 0, 0, 0, 0, &ClipFormats[1], &ClipFormats[3]}, { CF_METAFILEPICT, 1, 0, "MetaFile Picture", 0, 0, 0, 0, &ClipFormats[1], &ClipFormats[3]},
@ -71,11 +71,12 @@ WINE_CLIPFORMAT ClipFormats[17] = {
{ CF_PENDATA, 1, 0, "PenData", 0, 0, 0, 0, &ClipFormats[8], &ClipFormats[10]}, { CF_PENDATA, 1, 0, "PenData", 0, 0, 0, 0, &ClipFormats[8], &ClipFormats[10]},
{ CF_RIFF, 1, 0, "RIFF", 0, 0, 0, 0, &ClipFormats[9], &ClipFormats[11]}, { CF_RIFF, 1, 0, "RIFF", 0, 0, 0, 0, &ClipFormats[9], &ClipFormats[11]},
{ CF_WAVE, 1, 0, "Wave", 0, 0, 0, 0, &ClipFormats[10], &ClipFormats[12]}, { CF_WAVE, 1, 0, "Wave", 0, 0, 0, 0, &ClipFormats[10], &ClipFormats[12]},
{ CF_OWNERDISPLAY, 1, 0, "Owner Display", 0, 0, 0, 0, &ClipFormats[11], &ClipFormats[13]}, { CF_UNICODETEXT, 1, 0, "Unicode Text", 0, 0, 0, 0, &ClipFormats[11], &ClipFormats[13]},
{ CF_DSPTEXT, 1, 0, "DSPText", 0, 0, 0, 0, &ClipFormats[12], &ClipFormats[14]}, { CF_OWNERDISPLAY, 1, 0, "Owner Display", 0, 0, 0, 0, &ClipFormats[12], &ClipFormats[14]},
{ CF_DSPMETAFILEPICT, 1, 0, "DSPMetaFile Picture", 0, 0, 0, 0, &ClipFormats[13], &ClipFormats[15]}, { CF_DSPTEXT, 1, 0, "DSPText", 0, 0, 0, 0, &ClipFormats[13], &ClipFormats[15]},
{ CF_DSPBITMAP, 1, 0, "DSPBitmap", 0, 0, 0, 0, &ClipFormats[14], &ClipFormats[16]}, { CF_DSPMETAFILEPICT, 1, 0, "DSPMetaFile Picture", 0, 0, 0, 0, &ClipFormats[14], &ClipFormats[16]},
{ CF_HDROP, 1, 0, "HDROP", 0, 0, 0, 0, &ClipFormats[15], NULL} { CF_DSPBITMAP, 1, 0, "DSPBitmap", 0, 0, 0, 0, &ClipFormats[15], &ClipFormats[17]},
{ CF_HDROP, 1, 0, "HDROP", 0, 0, 0, 0, &ClipFormats[16], NULL}
}; };
@ -276,9 +277,10 @@ BOOL CLIPBOARD_IsPresent(WORD wFormat)
{ {
/* special case */ /* special case */
if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT ) if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT || wFormat == CF_UNICODETEXT )
return ClipFormats[CF_TEXT-1].wDataPresent || return ClipFormats[CF_TEXT-1].wDataPresent ||
ClipFormats[CF_OEMTEXT-1].wDataPresent; ClipFormats[CF_OEMTEXT-1].wDataPresent ||
ClipFormats[CF_UNICODETEXT-1].wDataPresent;
else else
{ {
LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat ); LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
@ -422,6 +424,58 @@ static BOOL CLIPBOARD_RenderFormat(LPWINE_CLIPFORMAT lpFormat)
return (lpFormat->hData16 || lpFormat->hData32) ? TRUE : FALSE; return (lpFormat->hData16 || lpFormat->hData32) ? TRUE : FALSE;
} }
/**************************************************************************
* CLIPBOARD_ConvertText
* Returns number of required/converted characters - not bytes!
*/
static INT CLIPBOARD_ConvertText(WORD src_fmt, void const *src, INT src_size,
WORD dst_fmt, void *dst, INT dst_size)
{
UINT cp;
if(src_fmt == CF_UNICODETEXT)
{
switch(dst_fmt)
{
case CF_TEXT:
cp = CP_ACP;
break;
case CF_OEMTEXT:
cp = CP_OEMCP;
break;
default:
return 0;
}
return WideCharToMultiByte(cp, 0, src, src_size, dst, dst_size, NULL, NULL);
}
if(dst_fmt == CF_UNICODETEXT)
{
switch(src_fmt)
{
case CF_TEXT:
cp = CP_ACP;
break;
case CF_OEMTEXT:
cp = CP_OEMCP;
break;
default:
return 0;
}
return MultiByteToWideChar(cp, 0, src, src_size, dst, dst_size);
}
if(!dst_size) return src_size;
if(dst_size > src_size) dst_size = src_size;
if(src_fmt == CF_TEXT )
CharToOemBuffA(src, dst, dst_size);
else
OemToCharBuffA(src, dst, dst_size);
return dst_size;
}
/************************************************************************** /**************************************************************************
* CLIPBOARD_RenderText * CLIPBOARD_RenderText
@ -438,8 +492,19 @@ static LPWINE_CLIPFORMAT CLIPBOARD_RenderText( UINT wFormat )
LPWINE_CLIPFORMAT lpSource = ClipFormats; LPWINE_CLIPFORMAT lpSource = ClipFormats;
LPWINE_CLIPFORMAT lpTarget; LPWINE_CLIPFORMAT lpTarget;
/* Asked for CF_TEXT and not available - always attempt to convert from CF_OEM_TEXT */ /* Asked for CF_TEXT but not available - always attempt to convert
from CF_UNICODETEXT or CF_OEMTEXT */
if( wFormat == CF_TEXT && !ClipFormats[CF_TEXT-1].wDataPresent ) if( wFormat == CF_TEXT && !ClipFormats[CF_TEXT-1].wDataPresent )
{
if(ClipFormats[CF_UNICODETEXT-1].wDataPresent)
{
/* Convert UNICODETEXT -> TEXT */
lpSource = &ClipFormats[CF_UNICODETEXT-1];
lpTarget = &ClipFormats[CF_TEXT-1];
TRACE("\tUNICODETEXT -> TEXT\n");
}
else if(ClipFormats[CF_OEMTEXT-1].wDataPresent)
{ {
/* Convert OEMTEXT -> TEXT */ /* Convert OEMTEXT -> TEXT */
lpSource = &ClipFormats[CF_OEMTEXT-1]; lpSource = &ClipFormats[CF_OEMTEXT-1];
@ -447,9 +512,22 @@ static LPWINE_CLIPFORMAT CLIPBOARD_RenderText( UINT wFormat )
TRACE("\tOEMTEXT -> TEXT\n"); TRACE("\tOEMTEXT -> TEXT\n");
} }
/* Asked for CF_OEM_TEXT, and CF_TEXT available */ else
else if( wFormat == CF_OEMTEXT && !ClipFormats[CF_OEMTEXT-1].wDataPresent lpSource = NULL; /* Conversion format is not available */
&& ClipFormats[CF_TEXT-1].wDataPresent ) }
/* Asked for CF_OEMTEXT but not available - always attempt to convert
from CF_UNICODETEXT or CF_TEXT */
else if( wFormat == CF_OEMTEXT && !ClipFormats[CF_OEMTEXT-1].wDataPresent )
{
if(ClipFormats[CF_UNICODETEXT-1].wDataPresent)
{
/* Convert UNICODETEXT -> OEMTEXT */
lpSource = &ClipFormats[CF_UNICODETEXT-1];
lpTarget = &ClipFormats[CF_OEMTEXT-1];
TRACE("\tUNICODETEXT -> OEMTEXT\n");
}
else if(ClipFormats[CF_TEXT-1].wDataPresent)
{ {
/* Convert TEXT -> OEMTEXT */ /* Convert TEXT -> OEMTEXT */
lpSource = &ClipFormats[CF_TEXT-1]; lpSource = &ClipFormats[CF_TEXT-1];
@ -457,6 +535,32 @@ static LPWINE_CLIPFORMAT CLIPBOARD_RenderText( UINT wFormat )
TRACE("\tTEXT -> OEMTEXT\n"); TRACE("\tTEXT -> OEMTEXT\n");
} }
else
lpSource = NULL; /* Conversion format is not available */
}
/* Asked for CF_UNICODETEXT but not available - always attempt to convert
from CF_TEXT or CF_OEMTEXT */
else if( wFormat == CF_UNICODETEXT && !ClipFormats[CF_UNICODETEXT-1].wDataPresent )
{
if(ClipFormats[CF_TEXT-1].wDataPresent)
{
/* Convert TEXT -> UNICODETEXT */
lpSource = &ClipFormats[CF_TEXT-1];
lpTarget = &ClipFormats[CF_UNICODETEXT-1];
TRACE("\tTEXT -> UNICODETEXT\n");
}
else if(ClipFormats[CF_OEMTEXT-1].wDataPresent)
{
/* Convert OEMTEXT -> UNICODETEXT */
lpSource = &ClipFormats[CF_OEMTEXT-1];
lpTarget = &ClipFormats[CF_UNICODETEXT-1];
TRACE("\tOEMTEXT -> UNICODETEXT\n");
}
else
lpSource = NULL; /* Conversion format is not available */
}
/* Text format requested is available - no conversion necessary */ /* Text format requested is available - no conversion necessary */
else else
{ {
@ -470,35 +574,48 @@ static LPWINE_CLIPFORMAT CLIPBOARD_RenderText( UINT wFormat )
/* Convert to the desired target text format, if necessary */ /* Convert to the desired target text format, if necessary */
if( lpTarget != lpSource && !lpTarget->hData16 && !lpTarget->hData32 ) if( lpTarget != lpSource && !lpTarget->hData16 && !lpTarget->hData32 )
{ {
UINT16 size; INT src_chars, dst_chars, alloc_size;
LPCSTR lpstrS; LPCSTR lpstrS;
LPSTR lpstrT; LPSTR lpstrT;
if (lpSource->hData32) if (lpSource->hData32)
{ {
size = GlobalSize( lpSource->hData32 );
lpstrS = (LPSTR)GlobalLock(lpSource->hData32); lpstrS = (LPSTR)GlobalLock(lpSource->hData32);
} }
else else
{ {
size = GlobalSize16( lpSource->hData16 );
lpstrS = (LPSTR)GlobalLock16(lpSource->hData16); lpstrS = (LPSTR)GlobalLock16(lpSource->hData16);
} }
if( !lpstrS ) return NULL; if( !lpstrS ) return NULL;
TRACE("\tconverting from '%s' to '%s', %i chars\n",
lpSource->Name, lpTarget->Name, size);
lpTarget->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, size); /* Text always NULL terminated */
if(lpSource->wFormatID == CF_UNICODETEXT)
src_chars = strlenW((LPCWSTR)lpstrS);
else
src_chars = strlen(lpstrS);
/* Calculate number of characters in the destination buffer */
dst_chars = CLIPBOARD_ConvertText(lpSource->wFormatID, lpstrS, src_chars,
lpTarget->wFormatID, NULL, 0);
if(!dst_chars) return NULL;
TRACE("\tconverting from '%s' to '%s', %i chars\n",
lpSource->Name, lpTarget->Name, src_chars);
/* Convert characters to bytes */
if(lpTarget->wFormatID == CF_UNICODETEXT)
alloc_size = dst_chars * sizeof(WCHAR);
else
alloc_size = dst_chars;
lpTarget->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, alloc_size);
lpstrT = (LPSTR)GlobalLock(lpTarget->hData32); lpstrT = (LPSTR)GlobalLock(lpTarget->hData32);
if( lpstrT ) if( lpstrT )
{ {
if( lpSource->wFormatID == CF_TEXT ) CLIPBOARD_ConvertText(lpSource->wFormatID, lpstrS, src_chars,
CharToOemBuffA(lpstrS, lpstrT, size); lpTarget->wFormatID, lpstrT, dst_chars);
else
OemToCharBuffA(lpstrS, lpstrT, size);
TRACE("\tgot %s\n", lpstrT);
GlobalUnlock(lpTarget->hData32); GlobalUnlock(lpTarget->hData32);
} }
else else
@ -678,18 +795,22 @@ HANDLE16 WINAPI SetClipboardData16( UINT16 wFormat, HANDLE16 hData )
{ {
CLIPBOARD_DeleteRecord(lpFormat, TRUE); CLIPBOARD_DeleteRecord(lpFormat, TRUE);
/* delete existing CF_TEXT/CF_OEMTEXT aliases */ /* delete existing CF_UNICODETEXT/CF_TEXT/CF_OEMTEXT aliases */
if(wFormat == CF_UNICODETEXT)
if( wFormat == CF_TEXT {
&& ( ClipFormats[CF_OEMTEXT-1].hData16
|| ClipFormats[CF_OEMTEXT-1].hData32 )
&& !ClipFormats[CF_OEMTEXT-1].wDataPresent )
CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
if( wFormat == CF_OEMTEXT
&& ( ClipFormats[CF_OEMTEXT-1].hData16
|| ClipFormats[CF_OEMTEXT-1].hData32 )
&& !ClipFormats[CF_TEXT-1].wDataPresent )
CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE); CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
}
else if(wFormat == CF_TEXT)
{
CLIPBOARD_DeleteRecord(&ClipFormats[CF_UNICODETEXT-1], TRUE);
CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
}
else if(wFormat == CF_OEMTEXT)
{
CLIPBOARD_DeleteRecord(&ClipFormats[CF_UNICODETEXT-1], TRUE);
CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
}
} }
bCBHasChanged = TRUE; bCBHasChanged = TRUE;
@ -732,18 +853,22 @@ HANDLE WINAPI SetClipboardData( UINT wFormat, HANDLE hData )
{ {
CLIPBOARD_DeleteRecord(lpFormat, TRUE); CLIPBOARD_DeleteRecord(lpFormat, TRUE);
/* delete existing CF_TEXT/CF_OEMTEXT aliases */ /* delete existing CF_UNICODETEXT/CF_TEXT/CF_OEMTEXT aliases */
if(wFormat == CF_UNICODETEXT)
if( wFormat == CF_TEXT {
&& ( ClipFormats[CF_OEMTEXT-1].hData16
|| ClipFormats[CF_OEMTEXT-1].hData32 )
&& !ClipFormats[CF_OEMTEXT-1].wDataPresent )
CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
if( wFormat == CF_OEMTEXT
&& ( ClipFormats[CF_OEMTEXT-1].hData16
|| ClipFormats[CF_OEMTEXT-1].hData32 )
&& !ClipFormats[CF_TEXT-1].wDataPresent )
CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE); CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
}
else if(wFormat == CF_TEXT)
{
CLIPBOARD_DeleteRecord(&ClipFormats[CF_UNICODETEXT-1], TRUE);
CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
}
else if(wFormat == CF_OEMTEXT)
{
CLIPBOARD_DeleteRecord(&ClipFormats[CF_UNICODETEXT-1], TRUE);
CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
}
} }
bCBHasChanged = TRUE; bCBHasChanged = TRUE;
@ -780,7 +905,7 @@ HANDLE16 WINAPI GetClipboardData16( UINT16 wFormat )
return 0; return 0;
} }
if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT ) if( wFormat == CF_UNICODETEXT || wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
{ {
lpRender = CLIPBOARD_RenderText(wFormat); lpRender = CLIPBOARD_RenderText(wFormat);
if ( !lpRender ) return 0; if ( !lpRender ) return 0;
@ -847,7 +972,7 @@ HANDLE WINAPI GetClipboardData( UINT wFormat )
return 0; return 0;
} }
if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT ) if( wFormat == CF_UNICODETEXT || wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
{ {
lpRender = CLIPBOARD_RenderText(wFormat); lpRender = CLIPBOARD_RenderText(wFormat);
if ( !lpRender ) return 0; if ( !lpRender ) return 0;
@ -938,10 +1063,10 @@ INT WINAPI CountClipboardFormats(void)
lpFormat = lpFormat->NextFormat; lpFormat = lpFormat->NextFormat;
} }
/* these two are equivalent, adjust the total */ /* these are equivalent, adjust the total */
FormatCount += (ClipFormats[CF_UNICODETEXT-1].wDataPresent ||
FormatCount += abs(ClipFormats[CF_TEXT-1].wDataPresent - ClipFormats[CF_TEXT-1].wDataPresent ||
ClipFormats[CF_OEMTEXT-1].wDataPresent); ClipFormats[CF_OEMTEXT-1].wDataPresent) ? 1 : 0;
TRACE("\ttotal %d\n", FormatCount); TRACE("\ttotal %d\n", FormatCount);
return FormatCount; return FormatCount;
@ -988,25 +1113,35 @@ UINT WINAPI EnumClipboardFormats( UINT wFormat )
{ {
if (lpFormat == NULL) return 0; if (lpFormat == NULL) return 0;
/* Synthesize CF_TEXT from CF_OEMTEXT and vice versa */ if(CLIPBOARD_IsPresent(lpFormat->wFormatID))
bFormatPresent = (lpFormat->wDataPresent || break;
(lpFormat->wFormatID == CF_OEMTEXT && ClipFormats[CF_TEXT-1].wDataPresent) ||
(lpFormat->wFormatID == CF_TEXT && ClipFormats[CF_OEMTEXT-1].wDataPresent) );
/* Query the driver if not yet in the cache */ /* Query the driver if not yet in the cache */
if (!bFormatPresent && !USER_Driver.pIsSelectionOwner()) if (!USER_Driver.pIsSelectionOwner())
{ {
bFormatPresent = if(lpFormat->wFormatID == CF_UNICODETEXT ||
USER_Driver.pIsClipboardFormatAvailable( (lpFormat->wFormatID == CF_TEXT) ? lpFormat->wFormatID == CF_TEXT ||
CF_OEMTEXT : lpFormat->wFormatID ); lpFormat->wFormatID == CF_OEMTEXT)
{
if(USER_Driver.pIsClipboardFormatAvailable(CF_UNICODETEXT) ||
USER_Driver.pIsClipboardFormatAvailable(CF_TEXT) ||
USER_Driver.pIsClipboardFormatAvailable(CF_OEMTEXT))
bFormatPresent = TRUE;
else
bFormatPresent = FALSE;
} }
else
bFormatPresent = USER_Driver.pIsClipboardFormatAvailable(lpFormat->wFormatID);
if(bFormatPresent) if(bFormatPresent)
break; break;
}
lpFormat = lpFormat->NextFormat; lpFormat = lpFormat->NextFormat;
} }
TRACE("Next available format %d\n", lpFormat->wFormatID);
return lpFormat->wFormatID; return lpFormat->wFormatID;
} }
@ -1230,14 +1365,8 @@ BOOL WINAPI IsClipboardFormatAvailable( UINT wFormat )
if (wFormat == 0) /* Reject this case quickly */ if (wFormat == 0) /* Reject this case quickly */
bRet = FALSE; bRet = FALSE;
/* If WINE is not the clipboard selection owner ask the clipboard driver */
else if ( !USER_Driver.pIsSelectionOwner() )
bRet = USER_Driver.pIsClipboardFormatAvailable( (wFormat == CF_TEXT) ?
CF_OEMTEXT : wFormat );
/* Check if the format is in the local cache */
else else
bRet = CLIPBOARD_IsPresent(wFormat); bRet = EnumClipboardFormats(wFormat - 1) == wFormat;
TRACE("(%04X)- ret(%d)\n", wFormat, bRet); TRACE("(%04X)- ret(%d)\n", wFormat, bRet);
return bRet; return bRet;

View File

@ -14,7 +14,6 @@
#include "queue.h" #include "queue.h"
#include "task.h" #include "task.h"
#include "win.h" #include "win.h"
#include "clipboard.h"
#include "hook.h" #include "hook.h"
#include "heap.h" #include "heap.h"
#include "thread.h" #include "thread.h"

View File

@ -15,7 +15,6 @@
#include "task.h" #include "task.h"
#include "queue.h" #include "queue.h"
#include "win.h" #include "win.h"
#include "clipboard.h"
#include "controls.h" #include "controls.h"
#include "cursoricon.h" #include "cursoricon.h"
#include "hook.h" #include "hook.h"

View File

@ -107,7 +107,7 @@ UINT X11DRV_CLIPBOARD_MapPropertyToFormat(char *itemFmtName)
else if ( 0 == strncmp(itemFmtName, FMT_PREFIX, strlen(FMT_PREFIX)) ) else if ( 0 == strncmp(itemFmtName, FMT_PREFIX, strlen(FMT_PREFIX)) )
return RegisterClipboardFormatA(itemFmtName + strlen(FMT_PREFIX)); return RegisterClipboardFormatA(itemFmtName + strlen(FMT_PREFIX));
else if ( 0 == strcmp(itemFmtName, "STRING") ) else if ( 0 == strcmp(itemFmtName, "STRING") )
return CF_OEMTEXT; return CF_UNICODETEXT;
else if ( 0 == strcmp(itemFmtName, "PIXMAP") else if ( 0 == strcmp(itemFmtName, "PIXMAP")
|| 0 == strcmp(itemFmtName, "BITMAP") ) || 0 == strcmp(itemFmtName, "BITMAP") )
{ {
@ -139,8 +139,12 @@ Atom X11DRV_CLIPBOARD_MapFormatToProperty(UINT wFormat)
switch (wFormat) switch (wFormat)
{ {
/* We support only CF_UNICODETEXT, other formats are synthesized */
case CF_OEMTEXT: case CF_OEMTEXT:
case CF_TEXT: case CF_TEXT:
return None;
case CF_UNICODETEXT:
prop = XA_STRING; prop = XA_STRING;
break; break;
@ -516,9 +520,9 @@ static BOOL X11DRV_CLIPBOARD_ReadSelection(UINT wFormat, Window w, Atom prop, At
* format, if possible. * format, if possible.
*/ */
if ( (reqType == XA_STRING) if ( (reqType == XA_STRING)
&& (atype == XA_STRING) && (aformat == 8) ) /* treat Unix text as CF_OEMTEXT */ && (atype == XA_STRING) && (aformat == 8) )
/* convert Unix text to CF_UNICODETEXT */
{ {
HANDLE16 hText = 0;
int i,inlcount = 0; int i,inlcount = 0;
char* lpstr; char* lpstr;
@ -527,38 +531,33 @@ static BOOL X11DRV_CLIPBOARD_ReadSelection(UINT wFormat, Window w, Atom prop, At
for(i=0; i <= nitems; i++) for(i=0; i <= nitems; i++)
if( val[i] == '\n' ) inlcount++; if( val[i] == '\n' ) inlcount++;
hText=GlobalAlloc16(GMEM_MOVEABLE, nitems + inlcount + 1); if( (lpstr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nitems + inlcount + 1)) )
if( (lpstr = (char*)GlobalLock16(hText)) )
{ {
ZeroMemory(lpstr, nitems + inlcount + 1); static UINT text_cp = (UINT)-1;
UINT count;
HANDLE hUnicodeText;
for(i=0,inlcount=0; i <= nitems; i++) for(i=0,inlcount=0; i <= nitems; i++)
{ {
if( val[i] == '\n' ) lpstr[inlcount++]='\r'; if( val[i] == '\n' ) lpstr[inlcount++]='\r';
lpstr[inlcount++]=val[i]; lpstr[inlcount++]=val[i];
} }
GlobalUnlock16(hText);
}
else
hText = 0;
if( hText ) if(text_cp == (UINT)-1)
text_cp = PROFILE_GetWineIniInt("x11drv", "TextCP", CP_ACP);
count = MultiByteToWideChar(text_cp, 0, lpstr, -1, NULL, 0);
hUnicodeText = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, count * sizeof(WCHAR));
if(hUnicodeText)
{ {
/* delete previous CF_TEXT and CF_OEMTEXT data */ WCHAR *textW = GlobalLock(hUnicodeText);
lpFormat = CLIPBOARD_LookupFormat(CF_TEXT); MultiByteToWideChar(text_cp, 0, lpstr, -1, textW, count);
if (lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32) GlobalUnlock(hUnicodeText);
CLIPBOARD_DeleteRecord(lpFormat, !(hWndClipWindow)); SetClipboardData(CF_UNICODETEXT, hUnicodeText);
lpFormat = CLIPBOARD_LookupFormat(CF_OEMTEXT);
if (lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32)
CLIPBOARD_DeleteRecord(lpFormat, !(hWndClipWindow));
/* Update the CF_OEMTEXT record */
lpFormat->wDataPresent = 1;
lpFormat->hData32 = 0;
lpFormat->hData16 = hText;
bRet = TRUE; bRet = TRUE;
} }
HeapFree(GetProcessHeap(), 0, lpstr);
}
} }
else if ( reqType == XA_PIXMAP || reqType == XA_BITMAP ) /* treat PIXMAP as CF_DIB or CF_BITMAP */ else if ( reqType == XA_PIXMAP || reqType == XA_BITMAP ) /* treat PIXMAP as CF_DIB or CF_BITMAP */
{ {
@ -891,6 +890,8 @@ BOOL X11DRV_IsClipboardFormatAvailable(UINT wFormat)
Window ownerPrimary = TSXGetSelectionOwner(display,XA_PRIMARY); Window ownerPrimary = TSXGetSelectionOwner(display,XA_PRIMARY);
Window ownerClipboard = TSXGetSelectionOwner(display,xaClipboard); Window ownerClipboard = TSXGetSelectionOwner(display,xaClipboard);
TRACE("%d\n", wFormat);
/* /*
* If the selection has not been previously cached, or the selection has changed, * If the selection has not been previously cached, or the selection has changed,
* try and cache the list of available selection targets from the current selection. * try and cache the list of available selection targets from the current selection.
@ -913,14 +914,10 @@ BOOL X11DRV_IsClipboardFormatAvailable(UINT wFormat)
/* Exit if there is no selection */ /* Exit if there is no selection */
if ( !ownerClipboard && !ownerPrimary ) if ( !ownerClipboard && !ownerPrimary )
{
TRACE("There is no selection\n");
return FALSE; return FALSE;
}
if ( wFormat == CF_TEXT )
wFormat = CF_OEMTEXT;
/* Check if the format is available in the clipboard cache */
if ( CLIPBOARD_IsPresent(wFormat) )
return TRUE;
/* /*
* Many X client apps (such as XTerminal) don't support being queried * Many X client apps (such as XTerminal) don't support being queried
@ -930,6 +927,7 @@ BOOL X11DRV_IsClipboardFormatAvailable(UINT wFormat)
if ( !cSelectionTargets ) if ( !cSelectionTargets )
return X11DRV_GetClipboardData( wFormat ); return X11DRV_GetClipboardData( wFormat );
TRACE("There is no selection\n");
return FALSE; return FALSE;
} }
@ -987,8 +985,7 @@ void X11DRV_SetClipboardData(UINT wFormat)
* *
* This method is invoked only when we DO NOT own the X selection * This method is invoked only when we DO NOT own the X selection
* *
* NOTE: Clipboard driver doesn't get requests for CF_TEXT data, only * NOTE: Clipboard driver get requests only for CF_UNICODETEXT data.
* for CF_OEMTEXT.
* We always get the data from the selection client each time, * We always get the data from the selection client each time,
* since we have no way of determining if the data in our cache is stale. * since we have no way of determining if the data in our cache is stale.
*/ */
@ -1000,6 +997,8 @@ BOOL X11DRV_GetClipboardData(UINT wFormat)
WND* wnd = NULL; WND* wnd = NULL;
LPWINE_CLIPFORMAT lpFormat; LPWINE_CLIPFORMAT lpFormat;
TRACE("%d\n", wFormat);
if( !selectionAcquired && (wnd = WIN_FindWndPtr(hWnd)) ) if( !selectionAcquired && (wnd = WIN_FindWndPtr(hWnd)) )
{ {
XEvent xe; XEvent xe;
@ -1055,6 +1054,8 @@ BOOL X11DRV_GetClipboardData(UINT wFormat)
TRACE("\tpresent %s = %i\n", CLIPBOARD_GetFormatName(wFormat), bRet ); TRACE("\tpresent %s = %i\n", CLIPBOARD_GetFormatName(wFormat), bRet );
} }
TRACE("Returning %d\n", bRet);
return bRet; return bRet;
} }

View File

@ -1071,29 +1071,40 @@ static Atom EVENT_SelectionRequest_TARGETS( Window requestor, Atom target, Atom
*/ */
static Atom EVENT_SelectionRequest_STRING( Window requestor, Atom target, Atom rprop ) static Atom EVENT_SelectionRequest_STRING( Window requestor, Atom target, Atom rprop )
{ {
HANDLE16 hText; static UINT text_cp = (UINT)-1;
HANDLE hUnicodeText;
LPWSTR uni_text;
LPSTR text; LPSTR text;
int size,i,j; int size,i,j;
char* lpstr = 0; char* lpstr = 0;
char *itemFmtName; char *itemFmtName;
int xRc; int xRc;
if(text_cp == (UINT)-1)
text_cp = PROFILE_GetWineIniInt("x11drv", "TextCP", CP_ACP);
/* /*
* Map the requested X selection property type atom name to a * Map the requested X selection property type atom name to a
* windows clipboard format ID. * windows clipboard format ID.
*/ */
itemFmtName = TSXGetAtomName(display, target); itemFmtName = TSXGetAtomName(display, target);
TRACE("Request for %s (wFormat=%x %s)\n", TRACE("Request for %s (wFormat=%x %s)\n",
itemFmtName, CF_TEXT, CLIPBOARD_GetFormatName(CF_TEXT)); itemFmtName, CF_UNICODETEXT, CLIPBOARD_GetFormatName(CF_UNICODETEXT));
TSXFree(itemFmtName); TSXFree(itemFmtName);
hText = GetClipboardData16(CF_TEXT); hUnicodeText = GetClipboardData(CF_UNICODETEXT);
if ( !hText ) if(!hUnicodeText)
return None; return None;
text = GlobalLock16(hText); uni_text = GlobalLock(hUnicodeText);
if(!uni_text)
return None;
size = WideCharToMultiByte(text_cp, 0, uni_text, -1, NULL, 0, NULL, NULL);
text = HeapAlloc(GetProcessHeap(), 0, size);
if (!text) if (!text)
return None; return None;
size = GlobalSize16(hText); WideCharToMultiByte(text_cp, 0, uni_text, -1, text, size, NULL, NULL);
/* remove carriage returns */ /* remove carriage returns */
lpstr = (char*)HeapAlloc( GetProcessHeap(), 0, size-- ); lpstr = (char*)HeapAlloc( GetProcessHeap(), 0, size-- );
@ -1113,7 +1124,8 @@ static Atom EVENT_SelectionRequest_STRING( Window requestor, Atom target, Atom r
lpstr, j); lpstr, j);
TRACE("(Rc=%d)\n", xRc); TRACE("(Rc=%d)\n", xRc);
GlobalUnlock16(hText); GlobalUnlock(hUnicodeText);
HeapFree(GetProcessHeap(), 0, text);
HeapFree( GetProcessHeap(), 0, lpstr ); HeapFree( GetProcessHeap(), 0, lpstr );
return rprop; return rprop;