Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1004 lines
38 KiB

  1. /****************************************************************************/
  2. // wcmint.c
  3. //
  4. // Cursor Manager internal functions
  5. //
  6. // Copyright (C) 1997-1999 Microsoft Corporation
  7. /****************************************************************************/
  8. #include <adcg.h>
  9. extern "C" {
  10. #define TRC_GROUP TRC_GROUP_CORE
  11. #define TRC_FILE "wcmint"
  12. #include <atrcapi.h>
  13. }
  14. #define TSC_HR_FILEID TSC_HR_WCMINT_CPP
  15. #include "autil.h"
  16. #include "wui.h"
  17. #include "cm.h"
  18. #include "uh.h"
  19. #define ROUND_UP( x, to ) (((x) + (to-1)) & ~(to-1))
  20. #define BMP_LENGTH_CALC( BPP, WIDTH, HEIGHT, BITSPADDING ) \
  21. (ROUND_UP( (BPP) * (WIDTH), (BITSPADDING)) / 8 * HEIGHT)
  22. /****************************************************************************/
  23. /* Name: CMCreateMonoCursor */
  24. /* */
  25. /* Purpose: Create a monochrome cursor from the MonoPointerAttributes */
  26. /* */
  27. /* Returns: Cursor handle (NULL if failed) */
  28. /****************************************************************************/
  29. HRESULT DCINTERNAL CCM::CMCreateMonoCursor(
  30. TS_MONOPOINTERATTRIBUTE UNALIGNED FAR *pMono,
  31. DCUINT dataLen, HCURSOR *phcursor)
  32. {
  33. HRESULT hr = S_OK;
  34. HCURSOR rc = CM_DEFAULT_ARROW_CURSOR_HANDLE;
  35. unsigned xorLen;
  36. DC_BEGIN_FN("CMCreateMonoCursor");
  37. *phcursor = NULL;
  38. // SECURITY 555587: CMCreate<XXX>Cursor must validate input
  39. if (pMono->lengthPointerData +
  40. FIELDOFFSET(TS_MONOPOINTERATTRIBUTE, monoPointerData) > dataLen) {
  41. TRC_ERR(( TB, _T("Invalid mono cursor data length; size %u"), dataLen));
  42. hr = E_TSC_CORE_LENGTH;
  43. DC_QUIT;
  44. }
  45. TRC_ASSERT(pMono->width <= 32 && pMono->height <= 32,
  46. (TB, _T("Invalid mono cursor; height %d width %d"), pMono->height,
  47. pMono->width));
  48. // Data contains XOR followed by AND mask.
  49. xorLen = ((pMono->width + 15) & 0xFFF0) * pMono->height;
  50. TRC_DATA_DBG("AND mask", pMono->monoPointerData + xorLen, xorLen);
  51. TRC_DATA_DBG("XOR bitmap", pMono->monoPointerData, xorLen);
  52. // SECURITY 555587: CMCreate<XXX>Cursor must validate input
  53. if (2 * xorLen != pMono->lengthPointerData)
  54. {
  55. TRC_ERR(( TB, _T("Invalid mono cursor data lengths")));
  56. hr = E_TSC_CORE_LENGTH;
  57. DC_QUIT;
  58. }
  59. #ifndef OS_WINCE
  60. rc = CreateCursor(_pUi->UI_GetInstanceHandle(),
  61. pMono->hotSpot.x,
  62. pMono->hotSpot.y,
  63. pMono->width,
  64. pMono->height,
  65. pMono->monoPointerData + xorLen,
  66. pMono->monoPointerData);
  67. #else
  68. /******************************************************************/
  69. /* In Windows CE environments, we're not guaranteed that */
  70. /* CreateCursor is part of the OS, so we do a GetProcAddress on */
  71. /* it so we can be sure. If it's not there, this usually means */
  72. /* we're on a touch screen device where these cursor doesn't */
  73. /* matter anyway. */
  74. /******************************************************************/
  75. if (g_pCreateCursor)
  76. {
  77. rc = g_pCreateCursor(_pUi->UI_GetInstanceHandle(),
  78. pMono->hotSpot.x,
  79. pMono->hotSpot.y,
  80. pMono->width,
  81. pMono->height,
  82. pMono->monoPointerData + xorLen,
  83. pMono->monoPointerData);
  84. }
  85. else
  86. {
  87. rc = CM_DEFAULT_ARROW_CURSOR_HANDLE;
  88. }
  89. #endif
  90. *phcursor = rc;
  91. DC_EXIT_POINT:
  92. DC_END_FN();
  93. return hr;
  94. }
  95. /****************************************************************************/
  96. /* Name: CMCreateColorCursor */
  97. /* */
  98. /* Purpose: Create a color cursor from the ColorPointerAttributes */
  99. /* */
  100. /* Returns: handle of cursor (NULL if failed) */
  101. /* */
  102. /* Params: IN pColorData - pointer to pointer data in PointerPDU */
  103. /* */
  104. /* Operation: Use CreateIconIndirect to create a color icon */
  105. /* Win16: not supported */
  106. /* Windows CE: not supported, according to SDK */
  107. /****************************************************************************/
  108. HRESULT DCINTERNAL CCM::CMCreateColorCursor(
  109. unsigned bpp,
  110. TS_COLORPOINTERATTRIBUTE UNALIGNED FAR *pColor,
  111. DCUINT dataLen, HCURSOR *phcursor)
  112. {
  113. HRESULT hr = E_FAIL;
  114. HCURSOR rc = NULL;
  115. HDC hdcMem = NULL;
  116. HBITMAP hbmANDMask = NULL;
  117. HWND hwndDesktop = NULL;
  118. HBITMAP hbmXORBitmap = NULL;
  119. PBYTE maskData = NULL;
  120. *phcursor = NULL;
  121. /************************************************************************/
  122. /* Static buffer to hold the (temporary) bitmap info. */
  123. /* */
  124. /* We need a BITMAPINFO structure plus 255 additional RGBQUADs */
  125. /* (remember that there is one included within the BITMAPINFO). The */
  126. /* number of these we use depends on the bitmap we're passed: */
  127. /* */
  128. /* - XOR bitmap at 24bpp needs no color table */
  129. /* - XOR bitmap at 8bpp needs a 256 entry color table */
  130. /* - 1bpp AND mask requires only 2 colors */
  131. /************************************************************************/
  132. static char bmi[sizeof(BITMAPINFO) + (sizeof(RGBQUAD) * 255)];
  133. LPBITMAPINFO pbmi = (LPBITMAPINFO)bmi;
  134. #ifdef OS_WINCE
  135. void *pv;
  136. #endif // OS_WINCE
  137. DC_BEGIN_FN("CMCreateColorCursor");
  138. TRC_NRM((TB, _T("bpp(%d) xhs(%u) yhs(%u) cx(%u) cy(%u) cbXOR(%u) cbAND(%u)"),
  139. bpp,
  140. pColor->hotSpot.x,
  141. pColor->hotSpot.y,
  142. pColor->width,
  143. pColor->height,
  144. pColor->lengthXORMask,
  145. pColor->lengthANDMask));
  146. TRC_DATA_DBG("AND mask",
  147. pColor->colorPointerData + pColor->lengthXORMask,
  148. pColor->lengthANDMask);
  149. TRC_DATA_DBG("XOR bitmap",
  150. pColor->colorPointerData,
  151. pColor->lengthXORMask);
  152. if (pColor->lengthANDMask + pColor->lengthXORMask +
  153. FIELDOFFSET(TS_COLORPOINTERATTRIBUTE,colorPointerData) >
  154. dataLen) {
  155. TRC_ERR(( TB, _T("Invalid Color Cursor data; expected %u have %u"),
  156. pColor->lengthANDMask + pColor->lengthXORMask +
  157. FIELDOFFSET(TS_COLORPOINTERATTRIBUTE,colorPointerData),
  158. dataLen));
  159. hr = E_TSC_CORE_LENGTH;
  160. DC_QUIT;
  161. }
  162. TRC_ASSERT(pColor->width <= 32 && pColor->height <= 32,
  163. ( TB, _T("Invalid color cursor; height %d width %d"), pColor->height,
  164. pColor->width));
  165. // SECURITY 555587: must validate sizes read from packet
  166. // Color pointer: XOR mask should be WORD aligned
  167. if (BMP_LENGTH_CALC( (WORD)bpp, pColor->width, pColor->height, 16) != pColor->lengthXORMask ) {
  168. TRC_ABORT((TB,_T("xor mask is not of proper length; bpp %d got %u expected %u"),
  169. (WORD)bpp, pColor->lengthXORMask,
  170. BMP_LENGTH_CALC((WORD)bpp, pColor->width, pColor->height, 16)));
  171. hr = E_TSC_CORE_LENGTH;
  172. DC_QUIT;
  173. }
  174. // Color pointer: AND mask should be DWORD aligned
  175. TRC_ASSERT(
  176. (BMP_LENGTH_CALC( 1, pColor->width, pColor->height, 16) ==
  177. pColor->lengthANDMask) ||
  178. (BMP_LENGTH_CALC( 1, pColor->width, pColor->height, 32) ==
  179. pColor->lengthANDMask ),
  180. (TB,_T("and mask is not of proper length; got %u expected %u or %u"),
  181. pColor->lengthANDMask,
  182. BMP_LENGTH_CALC( 1, pColor->width, pColor->height, 16),
  183. BMP_LENGTH_CALC( 1, pColor->width, pColor->height, 32)));
  184. /************************************************************************/
  185. /* Initialize the bitmap header for the XOR data. */
  186. /************************************************************************/
  187. pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  188. pbmi->bmiHeader.biWidth = pColor->width;
  189. pbmi->bmiHeader.biHeight = pColor->height;
  190. pbmi->bmiHeader.biPlanes = 1;
  191. pbmi->bmiHeader.biBitCount = (WORD)bpp;
  192. pbmi->bmiHeader.biCompression = BI_RGB;
  193. pbmi->bmiHeader.biSizeImage = pColor->lengthXORMask;
  194. pbmi->bmiHeader.biXPelsPerMeter = 0;
  195. pbmi->bmiHeader.biYPelsPerMeter = 0;
  196. pbmi->bmiHeader.biClrUsed = 0;
  197. pbmi->bmiHeader.biClrImportant = 0;
  198. /************************************************************************/
  199. /* Get a device dependent bitmap containing the XOR data. */
  200. /************************************************************************/
  201. hbmXORBitmap = CMCreateXORBitmap(pbmi, pColor);
  202. if (hbmXORBitmap == NULL)
  203. {
  204. TRC_ERR((TB, _T("Failed to create XOR bitmap")));
  205. DC_QUIT;
  206. }
  207. /************************************************************************/
  208. /* For the mono bitmap, use CreateCompatibleDC - this makes no */
  209. /* difference on NT, but allows this code to work on Windows 95. */
  210. /************************************************************************/
  211. hdcMem = CreateCompatibleDC(NULL);
  212. if (hdcMem == NULL)
  213. {
  214. TRC_ALT((TB, _T("Failed to create DC")));
  215. DC_QUIT;
  216. }
  217. /************************************************************************/
  218. /* Create AND Mask (1bpp) - set the RGB colors to black and white. */
  219. /************************************************************************/
  220. pbmi->bmiHeader.biBitCount = 1;
  221. pbmi->bmiHeader.biClrUsed = 2;
  222. pbmi->bmiHeader.biSizeImage = pColor->lengthANDMask;
  223. pbmi->bmiColors[0].rgbRed = 0x00;
  224. pbmi->bmiColors[0].rgbGreen = 0x00;
  225. pbmi->bmiColors[0].rgbBlue = 0x00;
  226. pbmi->bmiColors[0].rgbReserved = 0x00;
  227. pbmi->bmiColors[1].rgbRed = 0xFF;
  228. pbmi->bmiColors[1].rgbGreen = 0xFF;
  229. pbmi->bmiColors[1].rgbBlue = 0xFF;
  230. pbmi->bmiColors[1].rgbReserved = 0x00;
  231. #ifdef OS_WINCE
  232. hbmANDMask = CreateDIBSection(hdcMem, pbmi,
  233. DIB_RGB_COLORS, &pv, NULL, 0);
  234. if (hbmANDMask != NULL)
  235. DC_MEMCPY(pv, pColor->colorPointerData + pColor->lengthXORMask,
  236. pColor->lengthANDMask);
  237. #else // !OS_WINCE
  238. if (!(pColor->width & 3)) {
  239. maskData = pColor->colorPointerData + pColor->lengthXORMask;
  240. } else {
  241. PBYTE sourceData;
  242. PBYTE destData;
  243. DWORD widthBytes;
  244. unsigned i;
  245. sourceData = pColor->colorPointerData + pColor->lengthXORMask;
  246. widthBytes = ((pColor->width + 15) & ~15) / 8;
  247. pbmi->bmiHeader.biSizeImage = ((widthBytes + 3) & ~3) * pColor->height;
  248. maskData = (PBYTE) UT_Malloc(_pUt, ((DCUINT)pbmi->bmiHeader.biSizeImage));
  249. if (maskData) {
  250. destData = maskData;
  251. for (i = 0; i < pColor->height; i++) {
  252. memcpy(destData, sourceData, widthBytes);
  253. sourceData += (widthBytes + 1) & ~1;
  254. destData += (widthBytes + 3) & ~3;
  255. }
  256. } else {
  257. // We failed to allocate, so we'll just use the wire format
  258. // color bitmap data. The cursor would be wrong, but
  259. // it's better than no cursor
  260. maskData = pColor->colorPointerData + pColor->lengthXORMask;
  261. }
  262. }
  263. hbmANDMask = CreateDIBitmap(hdcMem,
  264. (LPBITMAPINFOHEADER)pbmi,
  265. CBM_INIT,
  266. maskData,
  267. pbmi,
  268. DIB_RGB_COLORS);
  269. #endif // OS_WINCE
  270. /************************************************************************/
  271. /* Free the DC. */
  272. /************************************************************************/
  273. DeleteDC(hdcMem);
  274. if (hbmANDMask == NULL)
  275. {
  276. TRC_ALT((TB, _T("Failed to create AND mask")));
  277. DC_QUIT;
  278. }
  279. // /****************************************************************************/
  280. // /* Testing... */
  281. // /****************************************************************************/
  282. // {
  283. // HWND hwndDesktop = GetDesktopWindow();
  284. // HDC hdcScreen = GetWindowDC(hwndDesktop);
  285. // HDC hdcMemory = CreateCompatibleDC(hdcScreen);
  286. // HBITMAP hbmOld;
  287. //
  288. // hbmOld = SelectBitmap(hdcMemory, hbmANDMask);
  289. // BitBlt(hdcScreen, 1000, 800, 1031, 831, hdcMemory, 0, 0, SRCCOPY);
  290. //
  291. // SelectBitmap(hdcMemory, hbmXORBitmap);
  292. // BitBlt(hdcScreen, 1032, 800, 1063, 831, hdcMemory, 0, 0, SRCCOPY);
  293. //
  294. // SelectBitmap(hdcMemory, hbmOld);
  295. // DeleteDC(hdcMemory);
  296. // ReleaseDC(hwndDesktop, hdcScreen);
  297. // }
  298. /************************************************************************/
  299. /* Create the cursor. */
  300. /************************************************************************/
  301. rc = CMCreatePlatformCursor(pColor, hbmXORBitmap, hbmANDMask);
  302. TRC_NRM((TB, _T("CreateCursor(%p) cx(%u)cy(%u)"),
  303. rc, pColor->width, pColor->height));
  304. *phcursor = rc;
  305. hr = S_OK;
  306. DC_EXIT_POINT:
  307. #ifndef OS_WINCE
  308. if (hbmXORBitmap != NULL)
  309. {
  310. DeleteBitmap(hbmXORBitmap);
  311. }
  312. if (hbmANDMask != NULL)
  313. {
  314. DeleteBitmap(hbmANDMask);
  315. }
  316. #else // OS_WINCE
  317. if (hbmXORBitmap != NULL)
  318. {
  319. DeleteObject((HGDIOBJ)hbmXORBitmap);
  320. }
  321. if (hbmANDMask != NULL)
  322. {
  323. DeleteObject((HGDIOBJ)hbmANDMask);
  324. }
  325. #endif // OS_WINCE
  326. if (maskData != NULL &&
  327. maskData != (pColor->colorPointerData + pColor->lengthXORMask)) {
  328. UT_Free(_pUt, maskData);
  329. }
  330. /************************************************************************/
  331. /* Check that we have successfully managed to create the cursor. If */
  332. /* not then substitute the default cursor. */
  333. /************************************************************************/
  334. if (*phcursor == NULL)
  335. {
  336. /********************************************************************/
  337. /* Substitute the default arrow cursor. */
  338. /********************************************************************/
  339. *phcursor = CM_DEFAULT_ARROW_CURSOR_HANDLE;
  340. TRC_ERR((TB, _T("Could not create cursor - substituting default arrow")));
  341. }
  342. DC_END_FN();
  343. return hr;
  344. } /* CMCreateColorCursor */
  345. #if defined(OS_WINCE)
  346. /****************************************************************************/
  347. /* Name: CMMakeMonoDIB */
  348. /* */
  349. /* Purpose: Create a mono DIB from the supplied color DIB */
  350. /* */
  351. /* Returns: Nothing */
  352. /* */
  353. /* Params: IN hdc - device context applying to the DIB */
  354. /* IN/OUT pbmi - pointer to bitmap info for source/target */
  355. /* IN pColorDIB - pointer to source bits */
  356. /* OUT pMonoDIB - address of buffer to receive mono bits */
  357. /* */
  358. /* Operation: Currently supports 32x32xNbpp source. The bitmap header */
  359. /* passed in (source) is updated to match the target. */
  360. /****************************************************************************/
  361. DCVOID DCINTERNAL CCM::CMMakeMonoDIB(HDC hdc,
  362. LPBITMAPINFO pbmi,
  363. PDCUINT8 pColorDIB,
  364. PDCUINT8 pMonoDIB)
  365. {
  366. COLORREF dcBackColor;
  367. LONG i;
  368. RGBTRIPLE bkCol;
  369. DCUINT8 monoMask;
  370. DCUINT8 monoByte;
  371. PDCUINT32 pBMIColor;
  372. PBYTE colorData = NULL;
  373. BYTE swap;
  374. DC_BEGIN_FN("CMMakeMonoDIB");
  375. // Find out the background color for this DC.
  376. dcBackColor = GetBkColor(hdc);
  377. bkCol.rgbtRed = (BYTE)(dcBackColor);
  378. bkCol.rgbtGreen = (BYTE)(((DCUINT16)dcBackColor) >> 8);
  379. bkCol.rgbtBlue = (BYTE)(dcBackColor >> 16);
  380. // The color pointer data width is WORD aligned on the wire.
  381. // We need to pass the DWORD aligned raw bitmap data to CreateDIBitmap
  382. // to create the actual cursor bitmap.
  383. // Also, we pad the cursor bitmap to 32x32 if it is not
  384. if (pbmi->bmiHeader.biWidth == CM_CURSOR_WIDTH &&
  385. pbmi->bmiHeader.biHeight == CM_CURSOR_HEIGHT) {
  386. colorData = pColorDIB;
  387. } else {
  388. PBYTE sourceData;
  389. PBYTE destData;
  390. DWORD WidthBytes;
  391. sourceData = pColorDIB;
  392. WidthBytes = pbmi->bmiHeader.biWidth *
  393. pbmi->bmiHeader.biBitCount / 8;
  394. colorData = (PBYTE) UT_Malloc( _pUt, CM_CURSOR_WIDTH * CM_CURSOR_HEIGHT *
  395. pbmi->bmiHeader.biBitCount / 8);
  396. if (colorData) {
  397. memset(colorData, 0, pbmi->bmiHeader.biSizeImage);
  398. destData = colorData;
  399. for (i = 0; i < pbmi->bmiHeader.biHeight; i++) {
  400. memcpy(destData, sourceData, WidthBytes);
  401. sourceData += (WidthBytes + 1) & ~1;
  402. destData += CM_CURSOR_WIDTH * pbmi->bmiHeader.biBitCount / 8;
  403. }
  404. } else {
  405. DC_QUIT;
  406. }
  407. }
  408. // Convert the bitmap. Any pixels which match the DC's background
  409. // color map to 1 (white) in the mono DIB; all other pixels map to 0
  410. // (black).
  411. TRC_NRM((TB, _T("bitmap color depth %u"), pbmi->bmiHeader.biBitCount));
  412. if (pbmi->bmiHeader.biBitCount == 24) {
  413. for (i = 0; i < ((CM_CURSOR_WIDTH * CM_CURSOR_HEIGHT) / 8); i++) {
  414. // Initialise the next target byte to all 0 pixels.
  415. monoByte = 0;
  416. // Get the next 8 pixels ie, one target byte's worth.
  417. for (monoMask = 0x80; monoMask != 0; monoMask >>= 1) {
  418. /************************************************************/
  419. /* Determine if the next Pel in the source matches the DC */
  420. /* background color. If not, it is unnecessary to */
  421. /* explicitly write a zero as each target byte is zeroed */
  422. /* before writing any data, ie each pixel is zero by */
  423. /* default. */
  424. /* 24bpp gives 3 bytes per pel */
  425. /************************************************************/
  426. if ( (colorData[0] == bkCol.rgbtBlue) &&
  427. (colorData[1] == bkCol.rgbtGreen) &&
  428. (colorData[2] == bkCol.rgbtRed) )
  429. {
  430. // Background color match - write a 1 to the mono DIB.
  431. monoByte |= monoMask;
  432. }
  433. // Advance the source pointer to the next pel.
  434. colorData += 3;
  435. }
  436. // Save the target value in the target buffer.
  437. *pMonoDIB = monoByte;
  438. // Advance the target pointer to the next byte.
  439. pMonoDIB++;
  440. }
  441. }
  442. #ifdef DC_HICOLOR
  443. else if ((pbmi->bmiHeader.biBitCount == 16) ||
  444. (pbmi->bmiHeader.biBitCount == 15))
  445. {
  446. BYTE red, green, blue;
  447. DCUINT16 redMask, greenMask, blueMask;
  448. if (pbmi->bmiHeader.biBitCount == 16)
  449. {
  450. redMask = TS_RED_MASK_16BPP;
  451. greenMask = TS_GREEN_MASK_16BPP;
  452. blueMask = TS_BLUE_MASK_16BPP;
  453. }
  454. else
  455. {
  456. redMask = TS_RED_MASK_15BPP;
  457. greenMask = TS_GREEN_MASK_15BPP;
  458. blueMask = TS_BLUE_MASK_15BPP;
  459. }
  460. for ( i = 0; i < ((CM_CURSOR_WIDTH * CM_CURSOR_HEIGHT) / 8); i++ )
  461. {
  462. /****************************************************************/
  463. /* Initialise the next target byte to all 0 pixels. */
  464. /****************************************************************/
  465. monoByte = 0;
  466. /****************************************************************/
  467. /* Get the next 8 pixels ie, one target byte's worth. */
  468. /****************************************************************/
  469. for ( monoMask = 0x80; monoMask != 0; monoMask >>= 1 )
  470. {
  471. /************************************************************/
  472. /* Determine if the next Pel in the source matches the DC */
  473. /* background color. If not, it is unnecessary to */
  474. /* explicitly write a zero as each target byte is zeroed */
  475. /* before writing any data, ie each pixel is zero by */
  476. /* default. */
  477. /* */
  478. /* 15 and 16bpp give 2 bytes per pel */
  479. /************************************************************/
  480. #if defined (OS_WINCE) && defined (DC_NO_UNALIGNED)
  481. blue = ((*((DCUINT16 UNALIGNED *)pColorDIB)) & blueMask) << 3;
  482. green = ((*((DCUINT16 UNALIGNED *)pColorDIB)) & greenMask) >> 3;
  483. red = ((*((DCUINT16 UNALIGNED *)pColorDIB)) & redMask) >> 8;
  484. #else
  485. blue = ((*((PDCUINT16)pColorDIB)) & blueMask) << 3;
  486. green = ((*((PDCUINT16)pColorDIB)) & greenMask) >> 3;
  487. red = ((*((PDCUINT16)pColorDIB)) & redMask) >> 8;
  488. #endif
  489. #ifndef OS_WINCE
  490. if ( (blue == bkCol.rgbtBlue) &&
  491. (green == bkCol.rgbtGreen) &&
  492. (red == bkCol.rgbtRed) )
  493. #else
  494. if (dcBackColor == GetNearestColor(hdc, RGB(red, green, blue)))
  495. #endif
  496. {
  497. /********************************************************/
  498. /* Background color match - write a 1 to the mono DIB. */
  499. /********************************************************/
  500. monoByte |= monoMask;
  501. }
  502. /************************************************************/
  503. /* Advance the source pointer to the next pel. */
  504. /************************************************************/
  505. pColorDIB += 2;
  506. }
  507. /****************************************************************/
  508. /* Save the target value in the target buffer. */
  509. /****************************************************************/
  510. *pMonoDIB = monoByte;
  511. /****************************************************************/
  512. /* Advance the target pointer to the next byte. */
  513. /****************************************************************/
  514. pMonoDIB++;
  515. }
  516. }
  517. #endif
  518. else if (pbmi->bmiHeader.biBitCount == 8)
  519. {
  520. // we need to set up a color table to go with the bmp
  521. //
  522. pbmi->bmiHeader.biClrUsed = 1 << pbmi->bmiHeader.biBitCount;
  523. TRC_NRM((TB, _T("XOR clr used %d"), pbmi->bmiHeader.biClrUsed));
  524. GetPaletteEntries( _pUh->UH_GetCurrentPalette(),
  525. 0,
  526. (UINT)pbmi->bmiHeader.biClrUsed,
  527. (LPPALETTEENTRY)pbmi->bmiColors);
  528. /********************************************************************/
  529. /* now we have to flip the red and blue components - paletteentries */
  530. /* go R-G-B-flags, while the RGBQUADs required for color tables go */
  531. /* B-G-R-reserved */
  532. /********************************************************************/
  533. for (i = 0; i < pbmi->bmiHeader.biClrUsed; i++)
  534. {
  535. swap = pbmi->bmiColors[i].rgbRed;
  536. pbmi->bmiColors[i].rgbRed = pbmi->bmiColors[i].rgbBlue;
  537. pbmi->bmiColors[i].rgbBlue = swap;
  538. }
  539. for ( i = 0; i < ((CM_CURSOR_WIDTH * CM_CURSOR_HEIGHT) / 8); i++ ) {
  540. // Initialise the next target byte to all 0 pixels.
  541. monoByte = 0;
  542. // Get the next 8 pixels ie, one target byte's worth.
  543. for ( monoMask = 0x80; monoMask != 0; monoMask >>= 1 ) {
  544. /************************************************************/
  545. /* Determine if the next Pel in the source matches the DC */
  546. /* background color. If not, it is unnecessary to */
  547. /* explicitly write a zero as each target byte is zeroed */
  548. /* before writing any data, ie each pixel is zero by */
  549. /* default. */
  550. /* */
  551. /* 8bpp gives one byte per pel, and each byte is an index */
  552. /* into the supplied color table rather than an RGB value */
  553. /************************************************************/
  554. if (
  555. (pbmi->bmiColors[*colorData].rgbBlue == bkCol.rgbtBlue) &&
  556. (pbmi->bmiColors[*colorData].rgbGreen == bkCol.rgbtGreen) &&
  557. (pbmi->bmiColors[*colorData].rgbRed == bkCol.rgbtRed)) {
  558. // Background color match - write a 1 to the mono DIB.
  559. monoByte |= monoMask;
  560. }
  561. // Advance the source pointer to the next pel.
  562. colorData ++;
  563. }
  564. // Save the target value in the target buffer.
  565. *pMonoDIB = monoByte;
  566. // Advance the target pointer to the next byte.
  567. pMonoDIB++;
  568. }
  569. }
  570. else {
  571. TRC_ERR((TB, _T("Unsupported BPP %d"), pbmi->bmiHeader.biBitCount));
  572. }
  573. DC_EXIT_POINT:
  574. // Update the bitmap header to reflect the mono DIB.
  575. #ifdef OS_WINCE
  576. if (!(pbmi->bmiHeader.biWidth == CM_CURSOR_WIDTH &&
  577. pbmi->bmiHeader.biHeight == CM_CURSOR_HEIGHT)) {
  578. #else
  579. if (colorData != pColorDIB) {
  580. #endif
  581. UT_Free( _pUt, colorData);
  582. }
  583. pbmi->bmiHeader.biBitCount = 1;
  584. pbmi->bmiHeader.biClrUsed = 2;
  585. pBMIColor = (PDCUINT32)pbmi->bmiColors;
  586. pBMIColor[0] = RGB(0, 0, 0);
  587. pBMIColor[1] = RGB(0xff, 0xff, 0xff);
  588. DC_END_FN();
  589. }
  590. #endif
  591. #ifdef OS_WINCE
  592. /****************************************************************************/
  593. // CMCreateXORBitmap
  594. //
  595. // Windows CE version.
  596. /****************************************************************************/
  597. HBITMAP CCM::CMCreateXORBitmap(
  598. LPBITMAPINFO pbmi,
  599. TS_COLORPOINTERATTRIBUTE UNALIGNED FAR *pColor)
  600. {
  601. struct {
  602. BITMAPINFO bmi;
  603. RGBQUAD bmiColors2;
  604. } bigbmi;
  605. PDCUINT32 pBMIColor;
  606. HDC hdcMem;
  607. HBITMAP hbmXORBitmap;
  608. void *pv;
  609. DC_BEGIN_FN("CMCreateXORBitmap");
  610. // Create a copy of the bitmapinfo
  611. DC_MEMCPY(&bigbmi, pbmi, sizeof(bigbmi));
  612. // Make it a mono DIB
  613. bigbmi.bmi.bmiHeader.biBitCount = 1;
  614. bigbmi.bmi.bmiHeader.biSizeImage = 0;
  615. pBMIColor = (PDCUINT32)bigbmi.bmi.bmiColors;
  616. pBMIColor[0] = RGB(0, 0, 0);
  617. pBMIColor[1] = RGB(0xff, 0xff, 0xff);
  618. hdcMem = CreateCompatibleDC(NULL);
  619. if (hdcMem != 0) {
  620. // Create a 1bpp compatible bitmap.
  621. hbmXORBitmap = CreateDIBSection(hdcMem, &bigbmi.bmi, DIB_PAL_COLORS,
  622. &pv, NULL, 0);
  623. if (hbmXORBitmap != NULL) {
  624. // Convert the XOR bitmap into 1bpp format. Avoid using
  625. // Windows for this as display drivers are unreliable for DIB
  626. // conversions.
  627. CMMakeMonoDIB(hdcMem, pbmi, pColor->colorPointerData, (PDCUINT8)pv);
  628. }
  629. // Free the DC.
  630. DeleteDC(hdcMem);
  631. }
  632. else {
  633. // DC creation failure.
  634. TRC_ERR((TB, _T("Failed to create memory DC")));
  635. hbmXORBitmap = 0;
  636. }
  637. DC_END_FN();
  638. return hbmXORBitmap;
  639. }
  640. HCURSOR CCM::CMCreatePlatformCursor(
  641. TS_COLORPOINTERATTRIBUTE UNALIGNED FAR *pColor,
  642. HBITMAP hbmXORBitmap,
  643. HBITMAP hbmANDMask)
  644. {
  645. // Set this to use the cursor workaround. Note that we would fix this
  646. // differently were we going to ship this code, but since this should
  647. // be fixed in the OS, this will do in the mean time.
  648. #define WINCE_CURSOR_BUG
  649. HCURSOR hCursor = NULL;
  650. ICONINFO ii;
  651. #ifdef WINCE_CURSOR_BUG
  652. HBITMAP hbmDst;
  653. HDC hdcSrc, hdcDst;
  654. HGDIOBJ gdiOldSrc, gdiOldDst;
  655. struct {
  656. BITMAPINFO bmi;
  657. RGBQUAD bmiColors2;
  658. } bigbmi;
  659. PDCUINT32 pBMIColor;
  660. void *pv;
  661. #endif // WINCE_CURSOR_BUG
  662. DC_BEGIN_FN("CMCreatePlatformCursor");
  663. #ifdef WINCE_CURSOR_BUG
  664. hdcSrc = CreateCompatibleDC(NULL);
  665. if (hdcSrc != NULL) {
  666. hdcDst = CreateCompatibleDC(NULL);
  667. if (hdcDst != NULL) {
  668. bigbmi.bmi.bmiHeader.biSize = sizeof(bigbmi.bmi);
  669. bigbmi.bmi.bmiHeader.biWidth = pColor->width;
  670. bigbmi.bmi.bmiHeader.biHeight = pColor->height * 2;
  671. bigbmi.bmi.bmiHeader.biPlanes = 1;
  672. bigbmi.bmi.bmiHeader.biBitCount = 1;
  673. bigbmi.bmi.bmiHeader.biCompression = BI_RGB;
  674. bigbmi.bmi.bmiHeader.biSizeImage = 0;
  675. bigbmi.bmi.bmiHeader.biXPelsPerMeter = 0;
  676. bigbmi.bmi.bmiHeader.biXPelsPerMeter = 0;
  677. bigbmi.bmi.bmiHeader.biClrUsed = 0;
  678. bigbmi.bmi.bmiHeader.biClrImportant = 0;
  679. pBMIColor = (PDCUINT32)bigbmi.bmi.bmiColors;
  680. pBMIColor[0] = RGB(0, 0, 0);
  681. pBMIColor[1] = RGB(0xff, 0xff, 0xff);
  682. hbmDst = CreateDIBSection(hdcDst, &bigbmi.bmi, DIB_PAL_COLORS, &pv,
  683. NULL, 0);
  684. if (NULL != hbmDst) {
  685. gdiOldSrc = SelectObject(hdcSrc, (HGDIOBJ) hbmANDMask);
  686. gdiOldDst = SelectObject(hdcDst, (HGDIOBJ) hbmDst);
  687. BitBlt(hdcDst, 0, 0, pColor->width, pColor->height, hdcSrc,
  688. 0, 0, SRCCOPY);
  689. SelectObject(hdcSrc, (HGDIOBJ) hbmXORBitmap);
  690. BitBlt(hdcDst, 0, pColor->height, pColor->width,
  691. pColor->height, hdcSrc, 0, 0, SRCCOPY);
  692. SelectObject(hdcSrc, gdiOldSrc);
  693. SelectObject(hdcDst, gdiOldDst);
  694. ii.fIcon = FALSE;
  695. ii.xHotspot = pColor->hotSpot.x;
  696. ii.yHotspot = pColor->hotSpot.y;
  697. ii.hbmMask = hbmDst;
  698. ii.hbmColor = hbmDst;
  699. hCursor = CreateIconIndirect(&ii);
  700. DeleteObject(hbmDst);
  701. }
  702. else {
  703. TRC_SYSTEM_ERROR("CreateDIBSection");
  704. }
  705. DeleteDC(hdcDst);
  706. }
  707. else {
  708. TRC_SYSTEM_ERROR("CreateCompatibleDC (2)");
  709. }
  710. DeleteDC(hdcSrc);
  711. }
  712. else {
  713. TRC_SYSTEM_ERROR("CreateCompatibleDC (1)");
  714. }
  715. #else // WINCE_CURSOR_BUG
  716. ii.fIcon = FALSE;
  717. ii.xHotspot = pColor->hotSpot.x;
  718. ii.yHotspot = pColor->hotSpot.y;
  719. ii.hbmMask = hbmANDMask;
  720. ii.hbmColor = hbmXORBitmap;
  721. hCursor = CreateIconIndirect(&ii);
  722. #endif // WINCE_CURSOR_BUG
  723. DC_END_FN();
  724. return hCursor;
  725. }
  726. #else // OS_WINCE
  727. HBITMAP CCM::CMCreateXORBitmap(
  728. LPBITMAPINFO pbmi,
  729. TS_COLORPOINTERATTRIBUTE UNALIGNED FAR *pColor)
  730. {
  731. HWND hwndDesktop;
  732. HDC hdcScreen;
  733. HBITMAP hbmXORBitmap;
  734. PBYTE colorData = NULL;
  735. unsigned fUsage;
  736. unsigned i;
  737. BYTE swap;
  738. DC_BEGIN_FN("CMCreateXORBitmap");
  739. // Get a screen DC that we can pass to CreateDIBitmap. We do not use
  740. // CreateCompatibleDC(NULL) here because that results in Windows
  741. // creating a mono bitmap (since the DC generated has a stock mono
  742. // bitmap selected into it and CreateDIBitmap generates a bitmap of the
  743. // same format as that already selected in the DC).
  744. hwndDesktop = GetDesktopWindow();
  745. hdcScreen = GetWindowDC(hwndDesktop);
  746. if (hdcScreen != 0) {
  747. // Set up the usage flag
  748. #ifdef DC_HICOLOR
  749. if (pbmi->bmiHeader.biBitCount > 8) {
  750. TRC_NRM((TB, _T("Hi color so usage is DIB_RGB_COLORS")));
  751. /****************************************************************/
  752. /* The bitmap contains RGBS so there's no color table */
  753. /****************************************************************/
  754. fUsage = DIB_RGB_COLORS;
  755. }
  756. #else
  757. if (pbmi->bmiHeader.biBitCount == 24) {
  758. TRC_NRM((TB, _T("24 bpp so usage is DIB_RGB_COLORS")));
  759. // The bitmap contains RGBS so there's no color table.
  760. fUsage = DIB_RGB_COLORS;
  761. }
  762. #endif
  763. else {
  764. TRC_DBG((TB, _T("%d bpp, usage DIB_RGB_COLORS"),
  765. pbmi->bmiHeader.biBitCount));
  766. // The bitmap has a color table containing RGB colors.
  767. fUsage = DIB_RGB_COLORS;
  768. pbmi->bmiHeader.biClrUsed = 1 << pbmi->bmiHeader.biBitCount;
  769. TRC_NRM((TB, _T("XOR clr used %d"), pbmi->bmiHeader.biClrUsed));
  770. i = GetPaletteEntries(_pUh->UH_GetCurrentPalette(),
  771. 0,
  772. pbmi->bmiHeader.biClrUsed,
  773. (LPPALETTEENTRY)pbmi->bmiColors);
  774. TRC_NRM((TB, _T("Entries returned %d"), i));
  775. if (i != pbmi->bmiHeader.biClrUsed) {
  776. TRC_SYSTEM_ERROR("GetPaletteEntries");
  777. }
  778. // Now we have to flip the red and blue components -
  779. // paletteentries go R-G-B-flags, while the RGBQUADs required
  780. // for color tables go B-G-R-reserved.
  781. for (i = 0; i < pbmi->bmiHeader.biClrUsed; i++) {
  782. swap = pbmi->bmiColors[i].rgbRed;
  783. pbmi->bmiColors[i].rgbRed = pbmi->bmiColors[i].rgbBlue;
  784. pbmi->bmiColors[i].rgbBlue = swap;
  785. }
  786. }
  787. // The color pointer XOR data width is WORD aligned on the wire.
  788. // We need to pass the DWORD aligned raw bitmap data to CreateDIBitmap
  789. // to create the actual cursor bitmap
  790. if (!(pColor->width & 3)) {
  791. colorData = pColor->colorPointerData;
  792. } else {
  793. PBYTE sourceData;
  794. PBYTE destData;
  795. DWORD widthBytes;
  796. unsigned i;
  797. sourceData = pColor->colorPointerData;
  798. widthBytes = pColor->width * pbmi->bmiHeader.biBitCount / 8;
  799. pbmi->bmiHeader.biSizeImage = ((pColor->width + 3) & ~3) * pColor->height *
  800. pbmi->bmiHeader.biBitCount / 8;
  801. colorData = (PBYTE) UT_Malloc(_pUt, ((DCUINT)pbmi->bmiHeader.biSizeImage));
  802. if (colorData) {
  803. destData = colorData;
  804. for (i = 0; i < pColor->height; i++) {
  805. memcpy(destData, sourceData, widthBytes);
  806. sourceData += (widthBytes + 1) & ~1;
  807. destData += (widthBytes + 3) & ~3;
  808. }
  809. } else {
  810. // We failed to allocate, so we'll just use the wire format
  811. // color bitmap data. The cursor would be wrong, but
  812. // it's better than no cursor
  813. colorData = pColor->colorPointerData;
  814. }
  815. }
  816. // Create XOR Bitmap.
  817. hbmXORBitmap = CreateDIBitmap(hdcScreen,
  818. (LPBITMAPINFOHEADER)pbmi,
  819. CBM_INIT,
  820. colorData,
  821. pbmi,
  822. fUsage);
  823. // Release the DC.
  824. ReleaseDC(hwndDesktop, hdcScreen);
  825. }
  826. else {
  827. // Error getting the screen DC.
  828. TRC_ERR((TB, _T("Failed to create screen DC")));
  829. hbmXORBitmap = 0;
  830. }
  831. DC_END_FN();
  832. if (colorData != pColor->colorPointerData) {
  833. UT_Free(_pUt, colorData);
  834. }
  835. return hbmXORBitmap;
  836. }
  837. HCURSOR CCM::CMCreatePlatformCursor(
  838. TS_COLORPOINTERATTRIBUTE UNALIGNED FAR *pColor,
  839. HBITMAP hbmXORBitmap,
  840. HBITMAP hbmANDMask)
  841. {
  842. ICONINFO iconInfo;
  843. DC_BEGIN_FN("CMCreatePlatformCursor");
  844. // Create a color cursor using the mask and color bitmaps.
  845. iconInfo.fIcon = FALSE;
  846. iconInfo.xHotspot = pColor->hotSpot.x;
  847. iconInfo.yHotspot = pColor->hotSpot.y;
  848. iconInfo.hbmMask = hbmANDMask;
  849. iconInfo.hbmColor = hbmXORBitmap;
  850. TRC_DBG((TB,_T("Create icon with hs x %d y %d"),
  851. iconInfo.xHotspot, iconInfo.yHotspot));
  852. DC_END_FN();
  853. return CreateIconIndirect(&iconInfo);
  854. }
  855. #endif // OS_WINCE