PageRenderTime 51ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/widget/os2/nsClipboard.cpp

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