1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsXPCOM.h"
#include "nsISupportsPrimitives.h"
#include "nsCOMPtr.h"
#include "nsPrimitiveHelpers.h"
#include "nsXPIDLString.h"
#include "nsOS2Uni.h"
#include "nsClipboard.h"
#define INCL_DOSERRORS
#define INCL_WIN
#include <os2.h>
inline uint32_t RegisterClipboardFormat(PCSZ pcszFormat)
{
ATOM atom = WinFindAtom(WinQuerySystemAtomTable(), pcszFormat);
if (!atom) {
atom = WinAddAtom(WinQuerySystemAtomTable(), pcszFormat);
}
return atom;
}
nsClipboard::nsClipboard() : nsBaseClipboard()
{
RegisterClipboardFormat(kTextMime);
RegisterClipboardFormat(kUnicodeMime);
RegisterClipboardFormat(kHTMLMime);
RegisterClipboardFormat(kAOLMailMime);
RegisterClipboardFormat(kPNGImageMime);
RegisterClipboardFormat(kJPEGImageMime);
RegisterClipboardFormat(kJPGImageMime);
RegisterClipboardFormat(kGIFImageMime);
RegisterClipboardFormat(kFileMime);
RegisterClipboardFormat(kURLMime);
RegisterClipboardFormat(kNativeImageMime);
RegisterClipboardFormat(kNativeHTMLMime);
}
nsClipboard::~nsClipboard()
{}
nsresult nsClipboard::SetNativeClipboardData(int32_t aWhichClipboard)
{
if (aWhichClipboard != kGlobalClipboard)
return NS_ERROR_FAILURE;
return DoClipboardAction(Write);
}
nsresult nsClipboard::GetNativeClipboardData(nsITransferable *aTransferable, int32_t aWhichClipboard)
{
// make sure we have a good transferable
if (!aTransferable || aWhichClipboard != kGlobalClipboard)
return NS_ERROR_FAILURE;
nsITransferable *tmp = mTransferable;
mTransferable = aTransferable;
nsresult rc = DoClipboardAction(Read);
mTransferable = tmp;
return rc;
}
// Get some data from the clipboard
bool nsClipboard::GetClipboardData(const char *aFlavor)
{
uint32_t ulFormatID = GetFormatID(aFlavor);
bool found = GetClipboardDataByID( ulFormatID, aFlavor );
if (!found)
{
if (!strcmp( aFlavor, kUnicodeMime ))
{
found = GetClipboardDataByID( CF_TEXT, aFlavor );
}
else if (strstr( aFlavor, "image/" ))
{
found = GetClipboardDataByID( CF_BITMAP, aFlavor );
}
}
return found;
}
bool nsClipboard::GetClipboardDataByID(uint32_t aFormatID, const char *aFlavor)
{
PVOID pDataMem;
uint32_t NumOfBytes;
bool TempBufAllocated = false;
PVOID pClipboardData = reinterpret_cast<PVOID>(WinQueryClipbrdData(0, aFormatID));
if (!pClipboardData)
return false;
if (strstr( aFlavor, "text/" )) // All text/.. flavors are null-terminated
{
pDataMem = pClipboardData;
if (aFormatID == CF_TEXT) // CF_TEXT is one byte character set
{
uint32_t NumOfChars = strlen( static_cast<char*>(pDataMem) );
NumOfBytes = NumOfChars;
if (!strcmp( aFlavor, kUnicodeMime )) // Asked for unicode, but only plain text available. Convert it!
{
nsAutoChar16Buffer buffer;
int32_t bufLength;
MultiByteToWideChar(0, static_cast<char*>(pDataMem), NumOfChars,
buffer, bufLength);
pDataMem = ToNewUnicode(nsDependentString(buffer.Elements()));
TempBufAllocated = true;
NumOfBytes = bufLength * sizeof(UniChar);
}
}
else // All other text/.. flavors are in unicode
{
uint32_t NumOfChars = UniStrlen( static_cast<UniChar*>(pDataMem) );
NumOfBytes = NumOfChars * sizeof(UniChar);
PVOID pTempBuf = nsMemory::Alloc(NumOfBytes);
memcpy(pTempBuf, pDataMem, NumOfBytes);
pDataMem = pTempBuf;
TempBufAllocated = true;
}
// DOM wants LF only, so convert from CRLF
nsLinebreakHelpers::ConvertPlatformToDOMLinebreaks( aFlavor, &pDataMem, // pDataMem could be reallocated !!
reinterpret_cast<int32_t*>(&NumOfBytes) ); // yuck
}
else // Assume rest of flavors are binary data
{
if (aFormatID == CF_BITMAP)
{
if (!strcmp( aFlavor, kJPEGImageMime ) || !strcmp( aFlavor, kJPGImageMime ))
{
// OS2TODO Convert bitmap to jpg
#ifdef DEBUG
printf( "nsClipboard:: No JPG found on clipboard; need to convert BMP\n");
#endif
}
else if (!strcmp( aFlavor, kGIFImageMime ))
{
// OS2TODO Convert bitmap to gif
#ifdef DEBUG
printf( "nsClipboard:: No GIF found on clipboard; need to convert BMP\n");
#endif
}
else if (!strcmp( aFlavor, kPNGImageMime ))
{
// OS2TODO Convert bitmap to png
#ifdef DEBUG
printf( "nsClipboard:: No PNG found on clipboard; need to convert BMP\n");
#endif
}
}
else
{
pDataMem = static_cast<PBYTE>(pClipboardData) + sizeof(uint32_t);
NumOfBytes = *(static_cast<uint32_t*>(pClipboardData));
}
}
nsCOMPtr<nsISupports> genericDataWrapper;
nsPrimitiveHelpers::CreatePrimitiveForData( aFlavor, pDataMem, NumOfBytes, getter_AddRefs(genericDataWrapper) );
#ifdef DEBUG
nsresult errCode =
#endif
mTransferable->SetTransferData( aFlavor, genericDataWrapper, NumOfBytes );
#ifdef DEBUG
if (errCode != NS_OK)
printf( "nsClipboard:: Error setting data into transferable\n" );
#endif
if (TempBufAllocated)
nsMemory::Free(pDataMem);
return true;
}
// Set some data onto the clipboard
void nsClipboard::SetClipboardData(const char *aFlavor)
{
void *pMozData = nullptr;
uint32_t NumOfBytes = 0;
// Get the data from the transferable
nsCOMPtr<nsISupports> genericDataWrapper;
#ifdef DEBUG
nsresult errCode =
#endif
mTransferable->GetTransferData( aFlavor, getter_AddRefs(genericDataWrapper), &NumOfBytes );
#ifdef DEBUG
if (NS_FAILED(errCode)) printf( "nsClipboard:: Error getting data from transferable\n" );
#endif
if (NumOfBytes == 0) return;
nsPrimitiveHelpers::CreateDataFromPrimitive( aFlavor, genericDataWrapper, &pMozData, NumOfBytes );
/* If creating the data failed, just return */
if (!pMozData) {
return;
}
uint32_t ulFormatID = GetFormatID(aFlavor);
if (strstr( aFlavor, "text/" )) // All text/.. flavors are null-terminated
{
if (ulFormatID == CF_TEXT) // CF_TEXT is one byte character set
{
char* pByteMem = nullptr;
if (DosAllocSharedMem( reinterpret_cast<PPVOID>(&pByteMem), nullptr, NumOfBytes + sizeof(char),
PAG_WRITE | PAG_COMMIT | OBJ_GIVEABLE ) == NO_ERROR)
{
memcpy( pByteMem, pMozData, NumOfBytes ); // Copy text string
pByteMem[NumOfBytes] = '\0'; // Append terminator
// With Warp4 copying more than 64K to the clipboard works well, but
// legacy apps cannot always handle it. So output an alarm to alert the
// user that there might be a problem.
if (strlen(pByteMem) > 0xFFFF) {
WinAlarm(HWND_DESKTOP, WA_ERROR);
}
WinSetClipbrdData(0, reinterpret_cast<ULONG>(pByteMem), ulFormatID, CFI_POINTER);
}
}
else // All other text/.. flavors are in unicode
{
UniChar* pUnicodeMem = nullptr;
uint32_t NumOfChars = NumOfBytes / sizeof(UniChar);
if (DosAllocSharedMem( reinterpret_cast<PPVOID>(&pUnicodeMem), nullptr, NumOfBytes + sizeof(UniChar),
PAG_WRITE | PAG_COMMIT | OBJ_GIVEABLE ) == NO_ERROR)
{
memcpy( pUnicodeMem, pMozData, NumOfBytes ); // Copy text string
pUnicodeMem[NumOfChars] = L'\0'; // Append terminator
WinSetClipbrdData( 0, reinterpret_cast<ULONG>(pUnicodeMem), ulFormatID, CFI_POINTER );
}
// If the flavor is unicode, we also put it on the clipboard as CF_TEXT
// after conversion to locale charset.
if (!strcmp( aFlavor, kUnicodeMime ))
{
char* pByteMem = nullptr;
if (DosAllocSharedMem(reinterpret_cast<PPVOID>(&pByteMem), nullptr,
NumOfBytes + 1,
PAG_WRITE | PAG_COMMIT | OBJ_GIVEABLE ) == NO_ERROR)
{
PRUnichar* uchtemp = (PRUnichar*)pMozData;
for (uint32_t i=0;i<NumOfChars;i++) {
switch (uchtemp[i]) {
case 0x2018:
case 0x2019:
uchtemp[i] = 0x0027;
break;
case 0x201C:
case 0x201D:
uchtemp[i] = 0x0022;
break;
case 0x2014:
uchtemp[i] = 0x002D;
break;
}
}
nsAutoCharBuffer buffer;
int32_t bufLength;
WideCharToMultiByte(0, static_cast<PRUnichar*>(pMozData),
NumOfBytes, buffer, bufLength);
memcpy(pByteMem, buffer.Elements(), NumOfBytes);
// With Warp4 copying more than 64K to the clipboard works well, but
// legacy apps cannot always handle it. So output an alarm to alert the
// user that there might be a problem.
if (strlen(pByteMem) > 0xFFFF) {
WinAlarm(HWND_DESKTOP, WA_ERROR);
}
WinSetClipbrdData(0, reinterpret_cast<ULONG>(pByteMem), CF_TEXT, CFI_POINTER);
}
}
}
}
else // Assume rest of flavors are binary data
{
PBYTE pBinaryMem = nullptr;
if (DosAllocSharedMem( reinterpret_cast<PPVOID>(&pBinaryMem), nullptr, NumOfBytes + sizeof(uint32_t),
PAG_WRITE | PAG_COMMIT | OBJ_GIVEABLE ) == NO_ERROR)
{
*(reinterpret_cast<uint32_t*>(pBinaryMem)) = NumOfBytes; // First DWORD contains data length
memcpy( pBinaryMem + sizeof(uint32_t), pMozData, NumOfBytes ); // Copy binary data
WinSetClipbrdData( 0, reinterpret_cast<ULONG>(pBinaryMem), ulFormatID, CFI_POINTER );
}
// If the flavor is image, we also put it on clipboard as CF_BITMAP
// after conversion to OS2 bitmap
if (strstr (aFlavor, "image/"))
{
// XXX OS2TODO Convert jpg, gif, png to bitmap
#ifdef DEBUG
printf( "nsClipboard:: Putting image on clipboard; should also convert to BMP\n" );
#endif
}
}
nsMemory::Free(pMozData);
}
// Go through the flavors in the transferable and either get or set them
nsresult nsClipboard::DoClipboardAction(ClipboardAction aAction)
{
nsresult rc = NS_ERROR_FAILURE;
if (WinOpenClipbrd(0/*hab*/)) {
if (aAction == Write)
WinEmptyClipbrd(0/*hab*/);
// Get the list of formats the transferable can handle
nsCOMPtr<nsISupportsArray> pFormats;
if(aAction == Read)
rc = mTransferable->FlavorsTransferableCanImport(getter_AddRefs(pFormats));
else
rc = mTransferable->FlavorsTransferableCanExport(getter_AddRefs(pFormats));
if (NS_FAILED(rc))
return NS_ERROR_FAILURE;
uint32_t cFormats = 0;
pFormats->Count(&cFormats);
for (uint32_t i = 0; i < cFormats; i++) {
nsCOMPtr<nsISupports> genericFlavor;
pFormats->GetElementAt(i, getter_AddRefs(genericFlavor));
nsCOMPtr<nsISupportsCString> currentFlavor(do_QueryInterface(genericFlavor));
if (currentFlavor) {
nsXPIDLCString flavorStr;
currentFlavor->ToString(getter_Copies(flavorStr));
if (aAction == Read) {
if (GetClipboardData(flavorStr))
break;
}
else
SetClipboardData(flavorStr);
}
}
WinCloseClipbrd(0/*hab*/);
rc = NS_OK;
}
return rc;
}
// get the format ID for a given mimetype
uint32_t nsClipboard::GetFormatID(const char *aMimeStr)
{
if (strcmp(aMimeStr, kTextMime) == 0)
return CF_TEXT;
return RegisterClipboardFormat(aMimeStr);
}
NS_IMETHODIMP nsClipboard::HasDataMatchingFlavors(const char** aFlavorList,
uint32_t aLength,
int32_t aWhichClipboard,
bool *_retval)
{
*_retval = false;
if (aWhichClipboard != kGlobalClipboard || !aFlavorList)
return NS_OK;
for (uint32_t i = 0; i < aLength; ++i) {
ULONG fmtInfo = 0;
uint32_t format = GetFormatID(aFlavorList[i]);
if (WinQueryClipbrdFmtInfo(0/*hab*/, format, &fmtInfo)) {
*_retval = true;
break;
}
// if the client asked for unicode and it wasn't present, check if we have CF_TEXT.
if (!strcmp(aFlavorList[i], kUnicodeMime)) {
if (WinQueryClipbrdFmtInfo(0/*hab*/, CF_TEXT, &fmtInfo)) {
*_retval = true;
break;
}
}
// OS2TODO - Support for Images
// if the client asked for image/.. and it wasn't present, check if we have CF_BITMAP.
if (strstr(aFlavorList[i], "image/")) {
if (WinQueryClipbrdFmtInfo (0, CF_BITMAP, &fmtInfo)) {
#ifdef DEBUG
printf("nsClipboard:: Image present on clipboard; need to add BMP conversion!\n");
#endif
// *_retval = true;
// break;
}
}
}
return NS_OK;
}
|