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.

3897 lines
101 KiB

  1. #include "precomp.h"
  2. //
  3. // CM.CPP
  4. // Cursor Manager
  5. //
  6. // Copyright(c) Microsoft 1997-
  7. //
  8. #define MLZ_FILE_ZONE ZONE_CORE
  9. //
  10. // CM_ShareStarting()
  11. // Creates resources used by the share
  12. //
  13. BOOL ASShare::CM_ShareStarting(void)
  14. {
  15. BOOL rc = FALSE;
  16. HBITMAP hbmpT;
  17. ICONINFO cursorInfo;
  18. char szTmp[MAX_CURSOR_TAG_FONT_NAME_LENGTH];
  19. DebugEntry(ASShare::CM_ShareStarting);
  20. //
  21. // Create the hatching brush we will use to make shadow cursors
  22. // distinguishable from real cursors.
  23. //
  24. hbmpT = LoadBitmap(g_asInstance, MAKEINTRESOURCE(IDB_HATCH32X32) );
  25. m_cmHatchBrush = CreatePatternBrush(hbmpT);
  26. DeleteBitmap(hbmpT);
  27. if (!m_cmHatchBrush)
  28. {
  29. ERROR_OUT(("CM_ShareStarting: Failed to created hatched brush"));
  30. DC_QUIT;
  31. }
  32. m_cmArrowCursor = LoadCursor(NULL, IDC_ARROW);
  33. if (!m_cmArrowCursor)
  34. {
  35. ERROR_OUT(("CM_ShareStarting: Failed to load cursors"));
  36. DC_QUIT;
  37. }
  38. // Get the arrow hotspot
  39. GetIconInfo(m_cmArrowCursor, &cursorInfo);
  40. m_cmArrowCursorHotSpot.x = cursorInfo.xHotspot;
  41. m_cmArrowCursorHotSpot.y = cursorInfo.yHotspot;
  42. DeleteBitmap(cursorInfo.hbmMask);
  43. if (cursorInfo.hbmColor)
  44. DeleteBitmap(cursorInfo.hbmColor);
  45. //
  46. // Get the size of the cursor on this system. (Cursor bitmaps are word
  47. // padded 1bpp).
  48. //
  49. m_cmCursorWidth = GetSystemMetrics(SM_CXCURSOR);
  50. m_cmCursorHeight = GetSystemMetrics(SM_CYCURSOR);
  51. //
  52. // Load the name of the font which will be used for creating cursor
  53. // tags. It makes sense to have this in a resource, so it can be
  54. // localized.
  55. //
  56. LoadString(g_asInstance, IDS_FONT_CURSORTAG, szTmp, sizeof(szTmp));
  57. m_cmCursorTagFont = CreateFont(CURSOR_TAG_FONT_HEIGHT, 0, 0, 0, FW_NORMAL,
  58. FALSE, FALSE, FALSE, DEFAULT_CHARSET,
  59. OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS,
  60. DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE,
  61. szTmp);
  62. if (!m_cmCursorTagFont)
  63. {
  64. ERROR_OUT(("CM_ShareStarting: couldn't create cursor tag font"));
  65. DC_QUIT;
  66. }
  67. rc = TRUE;
  68. DC_EXIT_POINT:
  69. DebugExitBOOL(ASShare::CM_ShareStarting, rc);
  70. return(rc);
  71. }
  72. //
  73. // CM_ShareEnded()
  74. // Frees resources used by the share
  75. //
  76. void ASShare::CM_ShareEnded(void)
  77. {
  78. DebugEntry(ASShare::CM_ShareEnded);
  79. //
  80. // Free cursor tag font
  81. //
  82. if (m_cmCursorTagFont != NULL)
  83. {
  84. DeleteFont(m_cmCursorTagFont);
  85. m_cmCursorTagFont = NULL;
  86. }
  87. //
  88. // Free shadow cursor dither brush
  89. //
  90. if (m_cmHatchBrush != NULL)
  91. {
  92. DeleteBrush(m_cmHatchBrush);
  93. m_cmHatchBrush = NULL;
  94. }
  95. DebugExitVOID(ASShare::CM_ShareEnded);
  96. }
  97. //
  98. // CM_PartyJoiningShare()
  99. //
  100. BOOL ASShare::CM_PartyJoiningShare(ASPerson * pasPerson)
  101. {
  102. BOOL rc = FALSE;
  103. DebugEntry(ASShare::CM_PartyJoiningShare);
  104. ValidatePerson(pasPerson);
  105. //
  106. // For 2.x nodes, create cursor cache now
  107. // For 3.0 nodes, create it when they start to host
  108. //
  109. if (pasPerson->cpcCaps.general.version < CAPS_VERSION_30)
  110. {
  111. if (!CMCreateIncoming(pasPerson))
  112. {
  113. ERROR_OUT(("CM_PartyJoiningShare: can't create cursor cache"));
  114. DC_QUIT;
  115. }
  116. }
  117. pasPerson->cmhRemoteCursor = m_cmArrowCursor;
  118. pasPerson->cmHotSpot = m_cmArrowCursorHotSpot;
  119. ASSERT(pasPerson->cmPos.x == 0);
  120. ASSERT(pasPerson->cmPos.y == 0);
  121. rc = TRUE;
  122. DC_EXIT_POINT:
  123. DebugExitBOOL(ASShare::CM_PartyJoiningShare, rc);
  124. return(rc);
  125. }
  126. //
  127. // CM_PartyLeftShare()
  128. //
  129. // See cm.h for description.
  130. //
  131. void ASShare::CM_PartyLeftShare(ASPerson * pasPerson)
  132. {
  133. DebugEntry(ASShare::CM_PartyLeftShare);
  134. ValidatePerson(pasPerson);
  135. //
  136. // Clear the incoming (receive) cursor cache info
  137. //
  138. if (pasPerson->cpcCaps.general.version < CAPS_VERSION_30)
  139. {
  140. TRACE_OUT(("CM_PartyLeftShare: freeing 2.x cursor cache for [%d]",
  141. pasPerson->mcsID));
  142. CMFreeIncoming(pasPerson);
  143. }
  144. else
  145. {
  146. ASSERT(!pasPerson->ccmRxCache);
  147. ASSERT(!pasPerson->acmRxCache);
  148. }
  149. DebugExitVOID(ASShare::CM_PartyLeftShare);
  150. }
  151. //
  152. // CM_HostStarting()
  153. //
  154. // Called when we start to host. Creates the outgoing cursor cache
  155. //
  156. BOOL ASHost::CM_HostStarting(void)
  157. {
  158. BOOL rc = FALSE;
  159. DebugEntry(ASHost::CM_HostStarting);
  160. //
  161. // Calculate actual size of cache we will use -- if 3.0 share, it's
  162. // what we advertise in our caps, but if 2.x share, it's <= to that
  163. // amount, being the min of everybody in the share.
  164. //
  165. // We however create the cache the size we want, knowing that in a 2.x
  166. // share we'll use some subset of it. That's cool.
  167. //
  168. m_pShare->CM_RecalcCaps(TRUE);
  169. if (!CH_CreateCache(&m_cmTxCacheHandle, TSHR_CM_CACHE_ENTRIES,
  170. 1, 0, NULL))
  171. {
  172. ERROR_OUT(("Could not create CM cache"));
  173. DC_QUIT;
  174. }
  175. rc = TRUE;
  176. DC_EXIT_POINT:
  177. DebugExitBOOL(ASHost::CM_HostStarting, rc);
  178. return(rc);
  179. }
  180. //
  181. // CM_HostEnded()
  182. //
  183. // Called when we stop hosting, so we can free cursor data
  184. //
  185. void ASHost::CM_HostEnded(void)
  186. {
  187. DebugEntry(ASHost::CM_HostEnded);
  188. //
  189. // Destroy the outgoing cursor cache
  190. //
  191. if (m_cmTxCacheHandle)
  192. {
  193. CH_DestroyCache(m_cmTxCacheHandle);
  194. m_cmTxCacheHandle = 0;
  195. m_cmNumTxCacheEntries = 0;
  196. }
  197. DebugExitVOID(ASHost::CM_HostEnded);
  198. }
  199. //
  200. // CM_ViewStarting()
  201. //
  202. // Called when somebody we're viewing starts to host. We create
  203. // the incoming cursor cache (well, we create it if they are 3.0; 2.x
  204. // nodes populated it even when not hosting).
  205. //
  206. BOOL ASShare::CM_ViewStarting(ASPerson * pasPerson)
  207. {
  208. BOOL rc = FALSE;
  209. DebugEntry(ASShare::CM_ViewStarting);
  210. ValidatePerson(pasPerson);
  211. if (pasPerson->cpcCaps.general.version < CAPS_VERSION_30)
  212. {
  213. // Reuse created cache
  214. ASSERT(pasPerson->acmRxCache);
  215. TRACE_OUT(("CM_ViewStarting: reusing cursor cache for 2.x node [%d]",
  216. pasPerson->mcsID));
  217. }
  218. else
  219. {
  220. if (!CMCreateIncoming(pasPerson))
  221. {
  222. ERROR_OUT(("CM_ViewStarting: can't create cursor cache for [%d]",
  223. pasPerson->mcsID));
  224. DC_QUIT;
  225. }
  226. }
  227. rc = TRUE;
  228. DC_EXIT_POINT:
  229. DebugExitBOOL(ASShare::CM_ViewStarting, rc);
  230. return(rc);
  231. }
  232. //
  233. // CM_ViewEnded()
  234. //
  235. // Called when somebody we are viewing has stopped hosting. We free up
  236. // cursor data needed to handle what they send us (well, for 3.0 dudes we
  237. // do; for 2.x dudes we keep it as long as they are in a share).
  238. //
  239. void ASShare::CM_ViewEnded(ASPerson * pasPerson)
  240. {
  241. DebugEntry(ASShare::CM_ViewEnded);
  242. ValidatePerson(pasPerson);
  243. if (pasPerson->cpcCaps.general.version >= CAPS_VERSION_30)
  244. {
  245. // Free cursor cache
  246. CMFreeIncoming(pasPerson);
  247. }
  248. else
  249. {
  250. TRACE_OUT(("CM_ViewEnded: keeping cursor cache for 2.x node [%d]",
  251. pasPerson->mcsID));
  252. }
  253. DebugExitVOID(ASShare::CM_ViewEnded);
  254. }
  255. //
  256. // CMCreateIncoming()
  257. // Creates cursor cache for person.
  258. // If 3.0 node, we create it when they start to host
  259. // If 2.x node, we create it when they join the share
  260. //
  261. BOOL ASShare::CMCreateIncoming(ASPerson * pasPerson)
  262. {
  263. BOOL rc = FALSE;
  264. DebugEntry(ASShare::CMCreateIncoming);
  265. if (!pasPerson->cpcCaps.cursor.capsCursorCacheSize)
  266. {
  267. //
  268. // This person has no cursor cache; don't create one.
  269. //
  270. WARNING_OUT(("CMCreateIncoming: person [%d] has no cursor cache size", pasPerson->mcsID));
  271. rc = TRUE;
  272. DC_QUIT;
  273. }
  274. pasPerson->ccmRxCache = pasPerson->cpcCaps.cursor.capsCursorCacheSize;
  275. pasPerson->acmRxCache = new CACHEDCURSOR[pasPerson->ccmRxCache];
  276. if (!pasPerson->acmRxCache)
  277. {
  278. ERROR_OUT(("CMCreateIncoming: can't create cursor cache for node [%d]", pasPerson->mcsID));
  279. DC_QUIT;
  280. }
  281. ZeroMemory(pasPerson->acmRxCache, sizeof(CACHEDCURSOR) * pasPerson->ccmRxCache);
  282. rc = TRUE;
  283. DC_EXIT_POINT:
  284. DebugExitBOOL(ASShare::CMCreateIncoming, rc);
  285. return(rc);
  286. }
  287. //
  288. // CMFreeIncoming()
  289. // Frees cursor cache for person.
  290. // If 3.0 node, we free it when they stop hosting
  291. // If 2.x node, we free it when they leave the share
  292. //
  293. void ASShare::CMFreeIncoming(ASPerson * pasPerson)
  294. {
  295. UINT irx;
  296. POINT cursorPos;
  297. HWND hwnd;
  298. HCURSOR hCurCursor;
  299. DebugEntry(ASShare::CMFreeIncoming);
  300. hCurCursor = ::GetCursor();
  301. if (pasPerson->acmRxCache)
  302. {
  303. for (irx = 0; irx < pasPerson->ccmRxCache; irx++)
  304. {
  305. if (pasPerson->acmRxCache[irx].hCursor != NULL)
  306. {
  307. if (pasPerson->acmRxCache[irx].hCursor == hCurCursor)
  308. {
  309. //
  310. // We're about to destroy the current cursor. Reset it.
  311. // Note that this can only happen when there's an active
  312. // frame for this host. And that frame must be about
  313. // to go away, in which case USER will jiggle the cursor
  314. // anyway. So we don't need to do more than this.
  315. //
  316. ::SetCursor(m_cmArrowCursor);
  317. }
  318. if (pasPerson->acmRxCache[irx].hCursor == pasPerson->cmhRemoteCursor)
  319. {
  320. pasPerson->cmhRemoteCursor = NULL;
  321. }
  322. ::DestroyCursor(pasPerson->acmRxCache[irx].hCursor);
  323. pasPerson->acmRxCache[irx].hCursor = NULL;
  324. }
  325. }
  326. pasPerson->ccmRxCache = 0;
  327. delete[] pasPerson->acmRxCache;
  328. pasPerson->acmRxCache = NULL;
  329. }
  330. DebugExitVOID(ASShare::CMFreeIncoming);
  331. }
  332. //
  333. // CM_Periodic()
  334. //
  335. void ASHost::CM_Periodic(void)
  336. {
  337. HWND hwnd;
  338. DebugEntry(ASHost::CM_Periodic);
  339. CM_MaybeSendCursorMovedPacket();
  340. //
  341. // Find out which window is currently controlling the cursor
  342. // appearance.
  343. //
  344. hwnd = CMGetControllingWindow();
  345. if (hwnd)
  346. {
  347. UINT cursorType;
  348. CURSORDESCRIPTION desiredCursor;
  349. UINT idDelta;
  350. //
  351. // Send a cursor shape update for the controlling window if necessary
  352. //
  353. if (m_pShare->HET_WindowIsHosted(hwnd))
  354. cursorType = CM_CT_DISPLAYEDCURSOR;
  355. else
  356. cursorType = CM_CT_DEFAULTCURSOR;
  357. switch (cursorType)
  358. {
  359. case CM_CT_DEFAULTCURSOR:
  360. if ((m_cmLastCursorShape.type == CM_CD_SYSTEMCURSOR) &&
  361. (m_cmLastCursorShape.id == CM_IDC_ARROW) )
  362. {
  363. //
  364. // No change.
  365. //
  366. DC_QUIT;
  367. }
  368. desiredCursor.type = CM_CD_SYSTEMCURSOR;
  369. desiredCursor.id = CM_IDC_ARROW;
  370. break;
  371. case CM_CT_DISPLAYEDCURSOR:
  372. CMGetCurrentCursor(&desiredCursor);
  373. if (desiredCursor.type == m_cmLastCursorShape.type)
  374. {
  375. switch (desiredCursor.type)
  376. {
  377. case CM_CD_SYSTEMCURSOR:
  378. if (desiredCursor.id == m_cmLastCursorShape.id)
  379. {
  380. //
  381. // Same cursor as last time.
  382. //
  383. DC_QUIT;
  384. }
  385. break;
  386. case CM_CD_BITMAPCURSOR:
  387. //
  388. // If the cursor has already been used, ignore it.
  389. // Check if stamp is less than or equal to the last
  390. // one - assume any sufficiently large difference
  391. // is due to overflow.
  392. //
  393. idDelta = (UINT)
  394. (desiredCursor.id - m_cmLastCursorShape.id);
  395. if (((idDelta == 0) || (idDelta > 0x10000000)) &&
  396. ((g_asSharedMemory->cmCursorHidden != FALSE) == (m_cmfCursorHidden != FALSE)))
  397. {
  398. TRACE_OUT(( "No change in cursor"));
  399. DC_QUIT;
  400. }
  401. break;
  402. default:
  403. ERROR_OUT(("Invalid cursor definition"));
  404. break;
  405. }
  406. }
  407. break;
  408. default:
  409. ERROR_OUT(("cursorType invalid"));
  410. DC_QUIT;
  411. }
  412. if (desiredCursor.type == CM_CD_SYSTEMCURSOR)
  413. {
  414. if (!CMSendSystemCursor(desiredCursor.id))
  415. {
  416. //
  417. // We failed to send the system cursor, so we just exit without
  418. // updating m_cmLastCursorShape. We will attempt to send it again
  419. // on the next call to CM_Periodic.
  420. //
  421. DC_QUIT;
  422. }
  423. m_cmLastCursorShape.type = desiredCursor.type;
  424. m_cmLastCursorShape.id = desiredCursor.id;
  425. }
  426. else
  427. {
  428. //
  429. // Save the 'hidden' state.
  430. //
  431. m_cmfCursorHidden = (g_asSharedMemory->cmCursorHidden != FALSE);
  432. if (!CMSendBitmapCursor())
  433. {
  434. //
  435. // We failed to send the bitmap cursor, so we just exit without
  436. // updating m_cmLastCursorShape. We will attempt to send it again
  437. // on the next call to CM_Periodic.
  438. //
  439. DC_QUIT;
  440. }
  441. m_cmLastCursorShape.type = desiredCursor.type;
  442. m_cmLastCursorShape.id = desiredCursor.id;
  443. }
  444. }
  445. DC_EXIT_POINT:
  446. DebugExitVOID(ASHost::CM_Periodic);
  447. }
  448. //
  449. // CM_SyncOutgoing()
  450. // Forces a send of the current cursor shape/pos when we start to host or
  451. // somebody new joins the conference
  452. //
  453. void ASHost::CM_SyncOutgoing(void)
  454. {
  455. DebugEntry(ASHost::CM_SyncOutgoing);
  456. //
  457. // Mark the last cursor as unknown. On next timer tick we'll send the
  458. // current one.
  459. //
  460. m_cmLastCursorShape.type = CM_CD_UNKNOWN;
  461. m_cmLastCursorPos.x = -1;
  462. m_cmLastCursorPos.y = -1;
  463. //
  464. // Clear the cursor cache.
  465. //
  466. if (m_cmTxCacheHandle != 0)
  467. {
  468. CH_ClearCache(m_cmTxCacheHandle);
  469. }
  470. DebugExitVOID(ASHost::CM_SyncOutgoing);
  471. }
  472. //
  473. // CM_DrawShadowCursor(..)
  474. //
  475. void ASShare::CM_DrawShadowCursor(ASPerson * pasHost, HDC hdc)
  476. {
  477. HBRUSH hbrOld;
  478. HDC hdcMem;
  479. HBITMAP hbmp;
  480. HBITMAP hbmpOld;
  481. HPALETTE hpalScreen = NULL;
  482. HPALETTE hpalOldDIB = NULL;
  483. POINT ptFrame;
  484. DebugEntry(ASShare::CM_DrawShadowCursor);
  485. ValidateView(pasHost);
  486. //
  487. // Draw the shadow cursor if there is one.
  488. //
  489. if (pasHost->cmShadowOff || !pasHost->cmhRemoteCursor)
  490. {
  491. TRACE_OUT(("CM_DrawShadowCursor: no cursor to draw"));
  492. DC_QUIT;
  493. }
  494. //
  495. // The cursor position is always kept in the host's screen coordinates.
  496. // When we paint our view frame, we adjust the DC so that painting
  497. // in host coordinates works right, even though the view frame may
  498. // be scrolled over.
  499. //
  500. ptFrame.x = pasHost->cmPos.x - pasHost->cmHotSpot.x - pasHost->m_pView->m_viewPos.x;
  501. ptFrame.y = pasHost->cmPos.y - pasHost->cmHotSpot.y - pasHost->m_pView->m_viewPos.y;
  502. //
  503. // We draw a greyed cursor using the following steps.
  504. // - copy the destination window rectangle to a memory bitmap.
  505. // - draw the cursor into the memory bitmap
  506. //
  507. // [the memory bitmap now contains the window background + a non-greyed
  508. // cursor]
  509. //
  510. // - blt the window bitmap back to the memory using a 3-way ROP and a
  511. // hatched pattern bitmap. The ROP is chosen such that the 0s and 1s
  512. // in the pattern bitmap select either a bitmap pel or a destination
  513. // pel for the final result. The pattern bitmap is such that most
  514. // of the bitmap pels are copied, but a few destination pels are
  515. // left unchanged, giving a greying effect.
  516. //
  517. // - copy the resulting bitmap back into the window.
  518. //
  519. // The last two steps are done so that the cursor does not appear to
  520. // change shape as it is moved. If the 3 way blt is done back to the
  521. // screen at stage 3, the pattern stays relative to the screen coords
  522. // and hence as the cursor moves, it will lose different pels each
  523. // time and appear to deform.
  524. //
  525. // The ROP is calculated to copy the source pel where the pattern is 1
  526. // and to leave the destination pel unchanged where the pattern is 0:
  527. //
  528. // P S D R
  529. //
  530. // 0 0 0 0
  531. // 0 0 1 1
  532. // 0 1 0 0
  533. // 0 1 1 1
  534. // 1 0 0 0
  535. // 1 0 1 0
  536. // 1 1 0 1
  537. // 1 1 1 1
  538. //
  539. // ^
  540. // Read upwards -> 0xCA
  541. //
  542. // From the table in the SDK, this gives a full ROP value of 0x00CA0749
  543. //
  544. //
  545. #define GREY_ROP 0x00CA0749
  546. if (NULL == (hdcMem = CreateCompatibleDC(hdc)))
  547. {
  548. WARNING_OUT(( "Failed to create memory DC"));
  549. DC_QUIT;
  550. }
  551. if (NULL == (hbmp = CreateCompatibleBitmap(hdc, CM_MAX_CURSOR_WIDTH, CM_MAX_CURSOR_HEIGHT)))
  552. {
  553. WARNING_OUT(( "Failed to create bitmap"));
  554. DeleteDC(hdcMem);
  555. DC_QUIT;
  556. }
  557. if (NULL == (hbmpOld = SelectBitmap(hdcMem, hbmp)))
  558. {
  559. WARNING_OUT(( "Failed to select bitmap"));
  560. DeleteBitmap(hbmp);
  561. DeleteDC(hdcMem);
  562. DC_QUIT;
  563. }
  564. hbrOld = SelectBrush(hdcMem, m_cmHatchBrush);
  565. //
  566. //
  567. // We need to make sure that we have the same logical palette selected
  568. // into both DCs otherwise we will corrupt the background color info
  569. // when we do the blitting.
  570. //
  571. //
  572. hpalScreen = SelectPalette(hdc,
  573. (HPALETTE)GetStockObject(DEFAULT_PALETTE),
  574. FALSE );
  575. SelectPalette( hdc, hpalScreen, FALSE );
  576. hpalOldDIB = SelectPalette( hdcMem, hpalScreen, FALSE );
  577. RealizePalette(hdcMem);
  578. BitBlt( hdcMem,
  579. 0,
  580. 0,
  581. CM_MAX_CURSOR_WIDTH,
  582. CM_MAX_CURSOR_HEIGHT,
  583. hdc,
  584. ptFrame.x,
  585. ptFrame.y,
  586. SRCCOPY );
  587. DrawIcon(hdcMem, 0, 0, pasHost->cmhRemoteCursor);
  588. CMDrawCursorTag(pasHost, hdcMem);
  589. BitBlt( hdcMem,
  590. 0,
  591. 0,
  592. CM_MAX_CURSOR_WIDTH,
  593. CM_MAX_CURSOR_HEIGHT,
  594. hdc,
  595. ptFrame.x,
  596. ptFrame.y,
  597. GREY_ROP );
  598. BitBlt( hdc,
  599. ptFrame.x,
  600. ptFrame.y,
  601. CM_MAX_CURSOR_WIDTH,
  602. CM_MAX_CURSOR_HEIGHT,
  603. hdcMem,
  604. 0,
  605. 0,
  606. SRCCOPY );
  607. SelectBrush(hdcMem, hbrOld);
  608. SelectBitmap(hdcMem, hbmpOld);
  609. DeleteBitmap(hbmp);
  610. if (hpalOldDIB != NULL)
  611. {
  612. SelectPalette(hdcMem, hpalOldDIB, FALSE);
  613. }
  614. DeleteDC(hdcMem);
  615. DC_EXIT_POINT:
  616. DebugExitVOID(ASShare::CM_DrawShadowCursor);
  617. }
  618. //
  619. // CM_ReceivedPacket(..)
  620. //
  621. void ASShare::CM_ReceivedPacket
  622. (
  623. ASPerson * pasPerson,
  624. PS20DATAPACKET pPacket
  625. )
  626. {
  627. PCMPACKETHEADER pCMPacket;
  628. DebugEntry(ASShare::CM_ReceivedPacket);
  629. ValidatePerson(pasPerson);
  630. pCMPacket = (PCMPACKETHEADER)pPacket;
  631. //
  632. // Switch on the packet type
  633. //
  634. switch (pCMPacket->type)
  635. {
  636. case CM_CURSOR_ID:
  637. case CM_CURSOR_MONO_BITMAP:
  638. case CM_CURSOR_COLOR_BITMAP:
  639. case CM_CURSOR_COLOR_CACHE:
  640. CMReceivedCursorShapePacket(pasPerson, pCMPacket);
  641. break;
  642. case CM_CURSOR_MOVE:
  643. CMReceivedCursorMovedPacket(pasPerson, pCMPacket);
  644. break;
  645. default:
  646. ERROR_OUT(("Invalid CM data packet from [%d] of type %d",
  647. pasPerson->mcsID, pCMPacket->type));
  648. break;
  649. }
  650. DebugExitVOID(ASShare::CM_ReceivedPacket);
  651. }
  652. //
  653. // CM_ApplicationMovedCursor(..)
  654. //
  655. void ASHost::CM_ApplicationMovedCursor(void)
  656. {
  657. DebugEntry(ASHost::CM_ApplicationMovedCursor);
  658. WARNING_OUT(("CM host: cursor moved by app, tell viewers"));
  659. m_cmfSyncPos = TRUE;
  660. CM_MaybeSendCursorMovedPacket();
  661. DebugExitVOID(ASHost::CM_ApplicationMovedCursor);
  662. }
  663. //
  664. // CM_RecalcCaps()
  665. //
  666. // This calculates the CM hosting caps when
  667. // * we start to host
  668. // * we're hosting and somebody joins the share
  669. // * we're hosting and somebody leaves the share
  670. //
  671. // This can GO AWAY WHEN 2.x COMPAT IS GONE -- no more min() of cache size
  672. //
  673. void ASShare::CM_RecalcCaps(BOOL fJoiner)
  674. {
  675. ASPerson * pasT;
  676. DebugEntry(ASShare::CM_RecalcCaps);
  677. if (!m_pHost || !fJoiner)
  678. {
  679. //
  680. // Nothing to do if we're not hosting. And also, if somebody has
  681. // left, no recalculation -- 2.x didn't.
  682. //
  683. DC_QUIT;
  684. }
  685. ValidatePerson(m_pasLocal);
  686. m_pHost->m_cmNumTxCacheEntries = m_pasLocal->cpcCaps.cursor.capsCursorCacheSize;
  687. m_pHost->m_cmfUseColorCursorProtocol =
  688. (m_pasLocal->cpcCaps.cursor.capsSupportsColorCursors == CAPS_SUPPORTED);
  689. //
  690. // Now with 3.0, viewers just create caches which are the size
  691. // of the host's send caps. No more min, no more receive caps
  692. //
  693. if (m_scShareVersion < CAPS_VERSION_30)
  694. {
  695. TRACE_OUT(("In share with 2.x nodes, must recalc CM caps"));
  696. for (pasT = m_pasLocal->pasNext; pasT != NULL; pasT = pasT->pasNext)
  697. {
  698. m_pHost->m_cmNumTxCacheEntries = min(m_pHost->m_cmNumTxCacheEntries,
  699. pasT->cpcCaps.cursor.capsCursorCacheSize);
  700. if (pasT->cpcCaps.cursor.capsSupportsColorCursors != CAPS_SUPPORTED)
  701. {
  702. m_pHost->m_cmfUseColorCursorProtocol = FALSE;
  703. }
  704. }
  705. TRACE_OUT(("Recalced CM caps: Tx Cache size %d, color cursors %d",
  706. m_pHost->m_cmNumTxCacheEntries,
  707. (m_pHost->m_cmfUseColorCursorProtocol != FALSE)));
  708. }
  709. DC_EXIT_POINT:
  710. DebugExitVOID(ASShare::CM_RecalcCaps);
  711. }
  712. //
  713. // FUNCTION: CMReceivedCursorShapePacket
  714. //
  715. // DESCRIPTION:
  716. //
  717. // Processes a received cursor shape packet.
  718. //
  719. // PARAMETERS:
  720. //
  721. // personID - ID of the packet sender
  722. //
  723. // pCMPacket - pointer to the received cursor shape packet
  724. //
  725. // RETURNS: Nothing
  726. //
  727. //
  728. void ASShare::CMReceivedCursorShapePacket
  729. (
  730. ASPerson * pasPerson,
  731. PCMPACKETHEADER pCMPacket
  732. )
  733. {
  734. BOOL fSetCursorToNULL = FALSE;
  735. HCURSOR hNewCursor;
  736. HCURSOR hOldCursor = NULL;
  737. POINT newHotSpot;
  738. UINT cacheID;
  739. DebugEntry(ASShare::CMReceivedCursorShapePacket);
  740. ValidatePerson(pasPerson);
  741. //
  742. // Now create or load the new cursor.
  743. //
  744. switch (pCMPacket->type)
  745. {
  746. case CM_CURSOR_ID:
  747. CMProcessCursorIDPacket((PCMPACKETID)pCMPacket,
  748. &hNewCursor, &newHotSpot);
  749. break;
  750. case CM_CURSOR_MONO_BITMAP:
  751. case CM_CURSOR_COLOR_BITMAP:
  752. if (pCMPacket->type == CM_CURSOR_MONO_BITMAP)
  753. {
  754. cacheID = CMProcessMonoCursorPacket((PCMPACKETMONOBITMAP)pCMPacket,
  755. &hNewCursor, &newHotSpot);
  756. }
  757. else
  758. {
  759. cacheID = CMProcessColorCursorPacket((PCMPACKETCOLORBITMAP)pCMPacket,
  760. &hNewCursor, &newHotSpot );
  761. }
  762. ASSERT(pasPerson->acmRxCache);
  763. ASSERT(cacheID < pasPerson->ccmRxCache);
  764. hOldCursor = pasPerson->acmRxCache[cacheID].hCursor;
  765. if (hNewCursor != NULL)
  766. {
  767. TRACE_OUT(("Cursor using cache %u", cacheID));
  768. pasPerson->acmRxCache[cacheID].hCursor = hNewCursor;
  769. pasPerson->acmRxCache[cacheID].hotSpot = newHotSpot;
  770. }
  771. else
  772. {
  773. //
  774. // use default cursor.
  775. //
  776. TRACE_OUT(( "color cursor failed so use arrow"));
  777. pasPerson->acmRxCache[cacheID].hCursor = NULL;
  778. pasPerson->acmRxCache[cacheID].hotSpot.x = 0;
  779. pasPerson->acmRxCache[cacheID].hotSpot.y = 0;
  780. hNewCursor = m_cmArrowCursor;
  781. newHotSpot = m_cmArrowCursorHotSpot;
  782. }
  783. break;
  784. case CM_CURSOR_COLOR_CACHE:
  785. cacheID = ((PCMPACKETCOLORCACHE)pCMPacket)->cacheIndex;
  786. ASSERT(pasPerson->acmRxCache);
  787. ASSERT(cacheID < pasPerson->ccmRxCache);
  788. //
  789. // If the caching failed last time then use the default arrow
  790. // cursor.
  791. //
  792. if (pasPerson->acmRxCache[cacheID].hCursor == NULL)
  793. {
  794. TRACE_OUT(( "cache empty so use arrow"));
  795. hNewCursor = m_cmArrowCursor;
  796. newHotSpot = m_cmArrowCursorHotSpot;
  797. }
  798. else
  799. {
  800. hNewCursor = pasPerson->acmRxCache[cacheID].hCursor;
  801. newHotSpot = pasPerson->acmRxCache[cacheID].hotSpot;
  802. }
  803. break;
  804. default:
  805. WARNING_OUT(( "Unknown cursor type: %u", pCMPacket->type));
  806. DC_QUIT;
  807. }
  808. //
  809. // Destroy the old cursor. Note that for bitmap cursor packets,
  810. // we will set the cursor to the new image twice.
  811. //
  812. if (hOldCursor)
  813. {
  814. if (hOldCursor == ::GetCursor())
  815. {
  816. ::SetCursor(hNewCursor);
  817. }
  818. ::DestroyCursor(hOldCursor);
  819. }
  820. pasPerson->cmhRemoteCursor = hNewCursor;
  821. //
  822. // Decide what to do with the new cursor...
  823. //
  824. if (!pasPerson->cmShadowOff)
  825. {
  826. //
  827. // The shadow cursor is enabled so update it. It won't change state
  828. // or move, it will just repaint with the new image and/or hotspot.
  829. //
  830. TRACE_OUT(("Update shadow cursor"));
  831. CM_UpdateShadowCursor(pasPerson, pasPerson->cmShadowOff,
  832. pasPerson->cmPos.x, pasPerson->cmPos.y,
  833. newHotSpot.x, newHotSpot.y);
  834. }
  835. else
  836. {
  837. HWND hwnd;
  838. // Update the hotspot.
  839. pasPerson->cmHotSpot = newHotSpot;
  840. // Refresh if no old cursor
  841. ASSERT(pasPerson->m_pView);
  842. hwnd = CMGetControllingWindow();
  843. if (hwnd == pasPerson->m_pView->m_viewClient)
  844. {
  845. SendMessage(hwnd, WM_SETCURSOR, (WPARAM)hwnd, MAKELONG(HTCLIENT, 0));
  846. }
  847. }
  848. DC_EXIT_POINT:
  849. DebugExitVOID(ASShare::CMReceivedCursorShapePacket);
  850. }
  851. //
  852. // FUNCTION: CMProcessMonoCursorPacket
  853. //
  854. // DESCRIPTION:
  855. //
  856. // Processes a received mono cursor packet.
  857. //
  858. // PARAMETERS:
  859. //
  860. // pCMPacket - pointer to the received cursor ID packet
  861. //
  862. // phNewCursor - pointer to a HCURSOR variable that receives the handle
  863. // of a cursor that corresponds to the received packet
  864. //
  865. // pNewHotSpot - pointer to a POINT variable that receives the hot-spot
  866. // of the new cursor
  867. //
  868. // RETURNS: Nothing
  869. //
  870. //
  871. UINT ASShare::CMProcessMonoCursorPacket
  872. (
  873. PCMPACKETMONOBITMAP pCMPacket,
  874. HCURSOR* phNewCursor,
  875. LPPOINT pNewHotSpot
  876. )
  877. {
  878. UINT cbReceivedMaskBytes;
  879. LPBYTE pANDMask;
  880. LPBYTE pXORMask;
  881. DebugEntry(ASShare::CMProcessMonoCursorPacket);
  882. //
  883. // Work out the size (in bytes) of the two bitmap masks we have just
  884. // received. (Cursor bitmaps are 1bpp and word padded).
  885. //
  886. cbReceivedMaskBytes = pCMPacket->height * CM_BYTES_FROM_WIDTH(pCMPacket->width);
  887. //
  888. // NOTE: Compressed cursors are an R.11 remnant. NM 1.0 and 2.0 never
  889. // sent them specially compressed. Therefore the code to handle
  890. // decompression should be unnecessary. Let's find out!
  891. //
  892. ASSERT(pCMPacket->header.type == CM_CURSOR_MONO_BITMAP);
  893. //
  894. // Get the XOR and AND masks
  895. //
  896. pXORMask = pCMPacket->aBits;
  897. pANDMask = pXORMask + cbReceivedMaskBytes;
  898. //
  899. // Create a cursor from the definition supplied in the packet.
  900. //
  901. *phNewCursor = CMCreateMonoCursor(pCMPacket->xHotSpot,
  902. pCMPacket->yHotSpot, pCMPacket->width, pCMPacket->height,
  903. pANDMask, pXORMask);
  904. if (*phNewCursor == NULL)
  905. {
  906. WARNING_OUT(( "Failed to create hRemoteCursor"));
  907. DC_QUIT;
  908. }
  909. //
  910. // Return the hot spot.
  911. //
  912. pNewHotSpot->x = pCMPacket->xHotSpot;
  913. pNewHotSpot->y = pCMPacket->yHotSpot;
  914. DC_EXIT_POINT:
  915. DebugExitDWORD(ASShare::CMProcessMonoCursorPacket, 0);
  916. return(0);
  917. }
  918. //
  919. // FUNCTION: CMProcessColorCursorPacket
  920. //
  921. // DESCRIPTION:
  922. //
  923. // Processes a received color cursor packet.
  924. //
  925. // PARAMETERS:
  926. //
  927. // pCMPacket - pointer to the received cursor ID packet
  928. //
  929. // phNewCursor - pointer to a HCURSOR variable that receives the handle
  930. // of a cursor that corresponds to the received packet
  931. //
  932. // pNewHotSpot - pointer to a POINT variable that receives the hot-spot
  933. // of the new cursor
  934. //
  935. // RETURNS: Nothing
  936. //
  937. //
  938. UINT ASShare::CMProcessColorCursorPacket
  939. (
  940. PCMPACKETCOLORBITMAP pCMPacket,
  941. HCURSOR* phNewCursor,
  942. LPPOINT pNewHotSpot
  943. )
  944. {
  945. LPBYTE pXORBitmap;
  946. LPBYTE pANDMask;
  947. DebugEntry(ASShare::CMProcessColorCursorPacket);
  948. //
  949. // Calculate the pointers to the XOR bitmap and the AND mask within the
  950. // color cursor data.
  951. //
  952. pXORBitmap = pCMPacket->aBits;
  953. pANDMask = pXORBitmap + pCMPacket->cbXORBitmap;
  954. //
  955. // Create a cursor from the definition supplied in the packet.
  956. //
  957. *phNewCursor = CMCreateColorCursor(pCMPacket->xHotSpot, pCMPacket->yHotSpot,
  958. pCMPacket->cxWidth, pCMPacket->cyHeight, pANDMask, pXORBitmap,
  959. pCMPacket->cbANDMask, pCMPacket->cbXORBitmap);
  960. if (*phNewCursor == NULL)
  961. {
  962. WARNING_OUT(( "Failed to create color cursor"));
  963. DC_QUIT;
  964. }
  965. //
  966. // Return the hot spot.
  967. //
  968. pNewHotSpot->x = pCMPacket->xHotSpot;
  969. pNewHotSpot->y = pCMPacket->yHotSpot;
  970. DC_EXIT_POINT:
  971. DebugExitDWORD(ASShare::CMProcessColorCursorPacket, pCMPacket->cacheIndex);
  972. return(pCMPacket->cacheIndex);
  973. }
  974. //
  975. // FUNCTION: CMReceivedCursorMovedPacket
  976. //
  977. // DESCRIPTION:
  978. //
  979. // Processes a received cursor movement packet.
  980. //
  981. // PARAMETERS:
  982. //
  983. // personID - ID of the sender of this packet
  984. //
  985. // pCMPacket - pointer to the received cursor movement packet
  986. //
  987. // RETURNS: Nothing
  988. //
  989. //
  990. void ASShare::CMReceivedCursorMovedPacket
  991. (
  992. ASPerson * pasFrom,
  993. PCMPACKETHEADER pCMHeader
  994. )
  995. {
  996. ASPerson * pasControlling;
  997. PCMPACKETMOVE pCMPacket = (PCMPACKETMOVE)pCMHeader;
  998. DebugEntry(ASShare::CMReceivedCursorMovedPacket);
  999. //
  1000. // Handle an incoming cursor moved packet.
  1001. //
  1002. ValidatePerson(pasFrom);
  1003. TRACE_OUT(("Received cursor move packet from [%d] to pos (%d,%d)",
  1004. pasFrom->mcsID, pCMPacket->xPos, pCMPacket->yPos));
  1005. CM_UpdateShadowCursor(pasFrom, pasFrom->cmShadowOff,
  1006. pCMPacket->xPos, pCMPacket->yPos,
  1007. pasFrom->cmHotSpot.x, pasFrom->cmHotSpot.y);
  1008. //
  1009. // If we're in control of this person and it's a sync, we need to
  1010. // move our cursor too, to reflect where the app really stuck it.
  1011. //
  1012. if ((pasFrom->m_caControlledBy == m_pasLocal) &&
  1013. !pasFrom->m_caControlPaused &&
  1014. (pCMPacket->header.flags & CM_SYNC_CURSORPOS))
  1015. {
  1016. //
  1017. // If our mouse is over this host's client area,
  1018. // autoscroll to pos or move our cursor
  1019. //
  1020. WARNING_OUT(("CM SYNC pos to {%04d, %04d}", pCMPacket->xPos,
  1021. pCMPacket->yPos));
  1022. VIEW_SyncCursorPos(pasFrom, pCMPacket->xPos, pCMPacket->yPos);
  1023. }
  1024. DebugExitVOID(ASShare::CMReceivedCursorMovedPacket);
  1025. }
  1026. //
  1027. // CM_UpdateShadowCursor()
  1028. //
  1029. // This repaints the host's shadow cursor in the view frame we have for him.
  1030. // It is used when
  1031. // * the cursor image has changed
  1032. // * the cursor tag has changed (due to control changes)
  1033. // * the cursor hotspot has changed
  1034. // * the cursor state is changing between on and off
  1035. // * the cursor has moved
  1036. //
  1037. void ASShare::CM_UpdateShadowCursor
  1038. (
  1039. ASPerson * pasPerson,
  1040. BOOL cmShadowOff,
  1041. int xNewPos,
  1042. int yNewPos,
  1043. int xNewHot,
  1044. int yNewHot
  1045. )
  1046. {
  1047. RECT rcInval;
  1048. DebugEntry(ASShare::CM_UpdateShadowCursor);
  1049. //
  1050. // Is the remote cursor currently on?
  1051. //
  1052. if (!pasPerson->cmShadowOff)
  1053. {
  1054. if (pasPerson->m_pView)
  1055. {
  1056. //
  1057. // We need to invalidate the old rectangle where the cursor
  1058. // was. We need to adjust for the hotspot. Also, adjust for
  1059. // any scrolling we may have done in the view frame.
  1060. //
  1061. rcInval.left = pasPerson->cmPos.x - pasPerson->cmHotSpot.x;
  1062. rcInval.top = pasPerson->cmPos.y - pasPerson->cmHotSpot.y;
  1063. rcInval.right = rcInval.left + m_cmCursorWidth;
  1064. rcInval.bottom = rcInval.top + m_cmCursorHeight;
  1065. VIEW_InvalidateRect(pasPerson, &rcInval);
  1066. }
  1067. }
  1068. // Update the state, position, and hotspot
  1069. pasPerson->cmShadowOff = cmShadowOff;
  1070. pasPerson->cmPos.x = xNewPos;
  1071. pasPerson->cmPos.y = yNewPos;
  1072. pasPerson->cmHotSpot.x = xNewHot;
  1073. pasPerson->cmHotSpot.y = yNewHot;
  1074. if (!pasPerson->cmShadowOff)
  1075. {
  1076. if (pasPerson->m_pView)
  1077. {
  1078. //
  1079. // We need to invalidate the new rectangle where the cursor is
  1080. // moving to. Again, we need to adjust for the hotspot, and any
  1081. // scrolling done in the view frame.
  1082. //
  1083. rcInval.left = pasPerson->cmPos.x - pasPerson->cmHotSpot.x;
  1084. rcInval.top = pasPerson->cmPos.y - pasPerson->cmHotSpot.y;
  1085. rcInval.right = rcInval.left + m_cmCursorWidth;
  1086. rcInval.bottom = rcInval.top + m_cmCursorHeight;
  1087. VIEW_InvalidateRect(pasPerson, &rcInval);
  1088. }
  1089. }
  1090. DebugExitVOID(ASShare::CM_UpdateShadowCursor);
  1091. }
  1092. void ASHost::CM_MaybeSendCursorMovedPacket(void)
  1093. {
  1094. PCMPACKETMOVE pCMPacket;
  1095. POINT cursorPos;
  1096. #ifdef _DEBUG
  1097. UINT sentSize;
  1098. #endif
  1099. DebugEntry(ASHost::CM_MaybeSendCursorMovedPacket);
  1100. //
  1101. // Get the cursor position.
  1102. //
  1103. if(!GetCursorPos(&cursorPos))
  1104. {
  1105. WARNING_OUT(("Unable to get cursor position. Error=%d", GetLastError()));
  1106. goto DC_EXIT_POINT;
  1107. }
  1108. //
  1109. // Has it changed?
  1110. //
  1111. if (m_cmfSyncPos ||
  1112. (cursorPos.x != m_cmLastCursorPos.x) ||
  1113. (cursorPos.y != m_cmLastCursorPos.y))
  1114. {
  1115. //
  1116. // Try to allocate a packet.
  1117. //
  1118. pCMPacket = (PCMPACKETMOVE)m_pShare->SC_AllocPkt(PROT_STR_MISC, g_s20BroadcastID,
  1119. sizeof(*pCMPacket));
  1120. if (!pCMPacket)
  1121. {
  1122. WARNING_OUT(("Failed to alloc CM move packet"));
  1123. DC_QUIT;
  1124. }
  1125. TRACE_OUT(("Sending cursor moved packet to pos (%d, %d)",
  1126. cursorPos.x, cursorPos.y));
  1127. //
  1128. // Fill in the fields
  1129. //
  1130. pCMPacket->header.header.data.dataType = DT_CM;
  1131. pCMPacket->header.type = CM_CURSOR_MOVE;
  1132. pCMPacket->header.flags = 0;
  1133. if (m_cmfSyncPos)
  1134. {
  1135. pCMPacket->header.flags |= CM_SYNC_CURSORPOS;
  1136. }
  1137. pCMPacket->xPos = (TSHR_UINT16)cursorPos.x;
  1138. pCMPacket->yPos = (TSHR_UINT16)cursorPos.y;
  1139. //
  1140. // Compress and send the packet.
  1141. //
  1142. if (m_pShare->m_scfViewSelf)
  1143. m_pShare->CM_ReceivedPacket(m_pShare->m_pasLocal, &(pCMPacket->header.header));
  1144. #ifdef _DEBUG
  1145. sentSize =
  1146. #endif // _DEBUG
  1147. m_pShare->DCS_CompressAndSendPacket(PROT_STR_MISC, g_s20BroadcastID,
  1148. &(pCMPacket->header.header), sizeof(*pCMPacket));
  1149. TRACE_OUT(("CM MOVE packet size: %08d, sent %08d", sizeof(*pCMPacket), sentSize));
  1150. m_cmfSyncPos = FALSE;
  1151. m_cmLastCursorPos = cursorPos;
  1152. }
  1153. DC_EXIT_POINT:
  1154. DebugExitVOID(ASHost::CM_MaybeSendCursorMovedPacket);
  1155. }
  1156. //
  1157. // FUNCTION: CMSendCursorShape
  1158. //
  1159. // DESCRIPTION:
  1160. //
  1161. // Sends a packet containing the given cursor shape (bitmap). If the
  1162. // same shape is located in the cache then a cached cursor packet is sent.
  1163. //
  1164. // PARAMETERS:
  1165. //
  1166. // pCursorShape - pointer to the cursor shape
  1167. //
  1168. // cbCursorDataSize - pointer to the cursor data size
  1169. //
  1170. // RETURNS: TRUE if successful, FALSE otherwise.
  1171. //
  1172. //
  1173. BOOL ASHost::CMSendCursorShape
  1174. (
  1175. LPCM_SHAPE pCursorShape,
  1176. UINT cbCursorDataSize
  1177. )
  1178. {
  1179. BOOL rc = FALSE;
  1180. BOOL fInCache;
  1181. LPCM_SHAPE pCacheData;
  1182. UINT iCacheEntry;
  1183. DebugEntry(ASHost::CMSendCursorShape);
  1184. fInCache = CH_SearchCache(m_cmTxCacheHandle,
  1185. (LPBYTE)pCursorShape,
  1186. cbCursorDataSize,
  1187. 0,
  1188. &iCacheEntry );
  1189. if (!fInCache)
  1190. {
  1191. pCacheData = (LPCM_SHAPE)new BYTE[cbCursorDataSize];
  1192. if (pCacheData == NULL)
  1193. {
  1194. WARNING_OUT(("Failed to alloc CM_SHAPE data"));
  1195. DC_QUIT;
  1196. }
  1197. memcpy(pCacheData, pCursorShape, cbCursorDataSize);
  1198. iCacheEntry = CH_CacheData(m_cmTxCacheHandle,
  1199. (LPBYTE)pCacheData,
  1200. cbCursorDataSize,
  1201. 0);
  1202. TRACE_OUT(( "Cache new cursor: pShape 0x%p, iEntry %u",
  1203. pCursorShape, iCacheEntry));
  1204. if (!CMSendColorBitmapCursor(pCacheData, iCacheEntry ))
  1205. {
  1206. CH_RemoveCacheEntry(m_cmTxCacheHandle, iCacheEntry);
  1207. DC_QUIT;
  1208. }
  1209. }
  1210. else
  1211. {
  1212. TRACE_OUT(("Cursor in cache: pShape 0x%p, iEntry %u",
  1213. pCursorShape, iCacheEntry));
  1214. if (!CMSendCachedCursor(iCacheEntry))
  1215. {
  1216. DC_QUIT;
  1217. }
  1218. }
  1219. //
  1220. // Return success.
  1221. //
  1222. rc = TRUE;
  1223. DC_EXIT_POINT:
  1224. DebugExitDWORD(ASHost::CMSendCursorShape, rc);
  1225. return(rc);
  1226. }
  1227. //
  1228. // FUNCTION: CMCopy1bppTo1bpp
  1229. //
  1230. // DESCRIPTION:
  1231. //
  1232. // Color conversion utility function to copy 1bpp cursor data to 1bpp (no
  1233. // conversion required).
  1234. //
  1235. // Data is assumed to be padded to word boundaries, and that the
  1236. // destination buffer is big enough to receive the 1bpp cursor data.
  1237. //
  1238. // PARAMETERS:
  1239. //
  1240. // pSrc - pointer to source data
  1241. //
  1242. // pDst - pointer to destination buffer
  1243. //
  1244. // cx - width of cursor in pixels
  1245. //
  1246. // cy - height of cursor in pixels
  1247. //
  1248. // RETURNS: Nothing
  1249. //
  1250. //
  1251. void CMCopy1bppTo1bpp( LPBYTE pSrc,
  1252. LPBYTE pDst,
  1253. UINT cx,
  1254. UINT cy )
  1255. {
  1256. UINT cbRowWidth;
  1257. DebugEntry(CMCopy1bppTo1bpp);
  1258. cbRowWidth = ((cx + 15)/16) * 2;
  1259. memcpy(pDst, pSrc, (cbRowWidth * cy));
  1260. DebugExitVOID(CMCopy1bppTo1bpp);
  1261. }
  1262. //
  1263. // FUNCTION: CMCopy4bppTo1bpp
  1264. //
  1265. // DESCRIPTION:
  1266. //
  1267. // Color conversion utility function to copy 4bpp cursor data to 1bpp.
  1268. //
  1269. // Data is assumed to be padded to word boundaries, and that the
  1270. // destination buffer is big enough to receive the 1bpp cursor data.
  1271. //
  1272. // PARAMETERS:
  1273. //
  1274. // pSrc - pointer to source data
  1275. //
  1276. // pDst - pointer to destination buffer
  1277. //
  1278. // cx - width of cursor in pixels
  1279. //
  1280. // cy - height of cursor in pixels
  1281. //
  1282. // RETURNS: Nothing
  1283. //
  1284. //
  1285. void CMCopy4bppTo1bpp( LPBYTE pSrc,
  1286. LPBYTE pDst,
  1287. UINT cx,
  1288. UINT cy )
  1289. {
  1290. UINT x;
  1291. UINT y;
  1292. UINT cbDstRowWidth;
  1293. UINT cbSrcRowWidth;
  1294. UINT cbUnpaddedDstRowWidth;
  1295. BOOL fPadByteNeeded;
  1296. BYTE Mask;
  1297. DebugEntry(CMCopy4bppTo1bpp);
  1298. cbDstRowWidth = ((cx + 15)/16) * 2;
  1299. cbUnpaddedDstRowWidth = (cx + 7) / 8;
  1300. cbSrcRowWidth = (cx + 1) / 2;
  1301. fPadByteNeeded = ((cbDstRowWidth - cbUnpaddedDstRowWidth) > 0);
  1302. for (y = 0; y < cy; y++)
  1303. {
  1304. *pDst = 0;
  1305. Mask = 0x80;
  1306. for (x = 0; x < cbSrcRowWidth; x++)
  1307. {
  1308. if (Mask == 0)
  1309. {
  1310. Mask = 0x80;
  1311. pDst++;
  1312. *pDst = 0;
  1313. }
  1314. if ((*pSrc & 0xF0) != 0)
  1315. {
  1316. *pDst |= Mask;
  1317. }
  1318. if ((*pSrc & 0x0F) != 0)
  1319. {
  1320. *pDst |= (Mask >> 1);
  1321. }
  1322. Mask >>= 2;
  1323. pSrc++;
  1324. }
  1325. if (fPadByteNeeded)
  1326. {
  1327. pDst++;
  1328. *pDst = 0;
  1329. }
  1330. pDst++;
  1331. }
  1332. DebugExitVOID(CMCopy4bppTo1bpp);
  1333. }
  1334. //
  1335. // FUNCTION: CMCopy8bppTo1bpp
  1336. //
  1337. // DESCRIPTION:
  1338. //
  1339. // Color conversion utility function to copy 8bpp cursor data to 1bpp.
  1340. //
  1341. // Data is assumed to be padded to word boundaries, and that the
  1342. // destination buffer is big enough to receive the 1bpp cursor data.
  1343. //
  1344. // PARAMETERS:
  1345. //
  1346. // pSrc - pointer to source data
  1347. //
  1348. // pDst - pointer to destination buffer
  1349. //
  1350. // cx - width of cursor in pixels
  1351. //
  1352. // cy - height of cursor in pixels
  1353. //
  1354. // RETURNS: Nothing
  1355. //
  1356. //
  1357. void CMCopy8bppTo1bpp( LPBYTE pSrc,
  1358. LPBYTE pDst,
  1359. UINT cx,
  1360. UINT cy )
  1361. {
  1362. UINT x;
  1363. UINT y;
  1364. UINT cbDstRowWidth;
  1365. UINT cbSrcRowWidth;
  1366. UINT cbUnpaddedDstRowWidth;
  1367. BOOL fPadByteNeeded;
  1368. BYTE Mask;
  1369. DebugEntry(CMCopy8bppTo1bpp);
  1370. cbDstRowWidth = ((cx + 15)/16) * 2;
  1371. cbUnpaddedDstRowWidth = (cx + 7) / 8;
  1372. cbSrcRowWidth = cx;
  1373. fPadByteNeeded = ((cbDstRowWidth - cbUnpaddedDstRowWidth) > 0);
  1374. for (y = 0; y < cy; y++)
  1375. {
  1376. *pDst = 0;
  1377. Mask = 0x80;
  1378. for (x = 0; x < cbSrcRowWidth; x++)
  1379. {
  1380. if (Mask == 0x00)
  1381. {
  1382. Mask = 0x80;
  1383. pDst++;
  1384. *pDst = 0;
  1385. }
  1386. if (*pSrc != 0)
  1387. {
  1388. *pDst |= Mask;
  1389. }
  1390. Mask >>= 1;
  1391. pSrc++;
  1392. }
  1393. if (fPadByteNeeded)
  1394. {
  1395. pDst++;
  1396. *pDst = 0;
  1397. }
  1398. pDst++;
  1399. }
  1400. DebugExitVOID(CMCopy8bppTo1bpp);
  1401. }
  1402. //
  1403. // FUNCTION: CMCopy16bppTo1bpp
  1404. //
  1405. // DESCRIPTION:
  1406. //
  1407. // Color conversion utility function to copy 16bpp cursor data to 1bpp.
  1408. //
  1409. // Data is assumed to be padded to word boundaries, and that the
  1410. // destination buffer is big enough to receive the 1bpp cursor data.
  1411. //
  1412. // PARAMETERS:
  1413. //
  1414. // pSrc - pointer to source data
  1415. //
  1416. // pDst - pointer to destination buffer
  1417. //
  1418. // cx - width of cursor in pixels
  1419. //
  1420. // cy - height of cursor in pixels
  1421. //
  1422. // RETURNS: Nothing
  1423. //
  1424. //
  1425. void CMCopy16bppTo1bpp( LPBYTE pSrc,
  1426. LPBYTE pDst,
  1427. UINT cx,
  1428. UINT cy )
  1429. {
  1430. UINT x;
  1431. UINT y;
  1432. UINT cbDstRowWidth;
  1433. UINT cbUnpaddedDstRowWidth;
  1434. BOOL fPadByteNeeded;
  1435. BYTE Mask;
  1436. DebugEntry(CMCopy16bppTo1bpp);
  1437. cbDstRowWidth = ((cx + 15)/16) * 2;
  1438. cbUnpaddedDstRowWidth = (cx + 7) / 8;
  1439. fPadByteNeeded = ((cbDstRowWidth - cbUnpaddedDstRowWidth) > 0);
  1440. for (y = 0; y < cy; y++)
  1441. {
  1442. *pDst = 0;
  1443. Mask = 0x80;
  1444. for (x = 0; x < cx; x++)
  1445. {
  1446. if (Mask == 0)
  1447. {
  1448. Mask = 0x80;
  1449. pDst++;
  1450. *pDst = 0;
  1451. }
  1452. if (*(LPTSHR_UINT16)pSrc != 0)
  1453. {
  1454. *pDst |= Mask;
  1455. }
  1456. Mask >>= 1;
  1457. pSrc += 2;
  1458. }
  1459. if (fPadByteNeeded)
  1460. {
  1461. pDst++;
  1462. *pDst = 0;
  1463. }
  1464. pDst++;
  1465. }
  1466. DebugExitVOID(CMCopy16bppTo1bpp);
  1467. }
  1468. //
  1469. // FUNCTION: CMCopy24bppTo1bpp
  1470. //
  1471. // DESCRIPTION:
  1472. //
  1473. // Color conversion utility function to copy 24bpp cursor data to 1bpp.
  1474. //
  1475. // Data is assumed to be padded to word boundaries, and that the
  1476. // destination buffer is big enough to receive the 1bpp cursor data.
  1477. //
  1478. // PARAMETERS:
  1479. //
  1480. // pSrc - pointer to source data
  1481. //
  1482. // pDst - pointer to destination buffer
  1483. //
  1484. // cx - width of cursor in pixels
  1485. //
  1486. // cy - height of cursor in pixels
  1487. //
  1488. // RETURNS: Nothing
  1489. //
  1490. //
  1491. void CMCopy24bppTo1bpp( LPBYTE pSrc,
  1492. LPBYTE pDst,
  1493. UINT cx,
  1494. UINT cy )
  1495. {
  1496. UINT x;
  1497. UINT y;
  1498. UINT cbDstRowWidth;
  1499. UINT cbUnpaddedDstRowWidth;
  1500. BOOL fPadByteNeeded;
  1501. BYTE Mask;
  1502. UINT intensity;
  1503. DebugEntry(CMCopy24bppTo1bpp);
  1504. cbDstRowWidth = ((cx + 15)/16) * 2;
  1505. cbUnpaddedDstRowWidth = (cx + 7) / 8;
  1506. fPadByteNeeded = ((cbDstRowWidth - cbUnpaddedDstRowWidth) > 0);
  1507. for (y = 0; y < cy; y++)
  1508. {
  1509. *pDst = 0;
  1510. Mask = 0x80;
  1511. for (x = 0; x < cx; x++)
  1512. {
  1513. if (Mask == 0)
  1514. {
  1515. Mask = 0x80;
  1516. pDst++;
  1517. *pDst = 0;
  1518. }
  1519. //
  1520. // Work out the intensity of the RGB value. There are three
  1521. // possible results
  1522. // 1) intensity <=CM_BLACK_THRESHOLD
  1523. // -- we leave the dest as blck
  1524. // 2) intensity > CM_WHITE_THRESHOLD
  1525. // -- we definitely map to white
  1526. // 3) otherwise
  1527. // -- we map to white in a grid hatching fashion
  1528. //
  1529. intensity = ((UINT)pSrc[0]*(UINT)pSrc[0]) +
  1530. ((UINT)pSrc[1]*(UINT)pSrc[1]) +
  1531. ((UINT)pSrc[2]*(UINT)pSrc[2]);
  1532. if ( (intensity > CM_WHITE_THRESHOLD) ||
  1533. ((intensity > CM_BLACK_THRESHOLD) && (((x ^ y) & 1) == 1)))
  1534. {
  1535. *pDst |= Mask;
  1536. }
  1537. Mask >>= 1;
  1538. pSrc += 3;
  1539. }
  1540. if (fPadByteNeeded)
  1541. {
  1542. pDst++;
  1543. *pDst = 0;
  1544. }
  1545. pDst++;
  1546. }
  1547. DebugExitVOID(CMCopy24bppTo1bpp);
  1548. }
  1549. //
  1550. // FUNCTION: CMSendCachedCursor
  1551. //
  1552. // DESCRIPTION:
  1553. //
  1554. // Sends a packet containing the given cache entry id.
  1555. //
  1556. // PARAMETERS:
  1557. //
  1558. // iCacheEntry - cache index
  1559. //
  1560. // RETURNS: TRUE if packet sent, FALSE otherwise.
  1561. //
  1562. //
  1563. BOOL ASHost::CMSendCachedCursor(UINT iCacheEntry)
  1564. {
  1565. BOOL rc = FALSE;
  1566. PCMPACKETCOLORCACHE pCMPacket;
  1567. #ifdef _DEBUG
  1568. UINT sentSize;
  1569. #endif // _DEBUG
  1570. DebugEntry(ASHost::CMSendCachedCursor);
  1571. TRACE_OUT(( "Send cached cursor(%u)", iCacheEntry));
  1572. pCMPacket = (PCMPACKETCOLORCACHE)m_pShare->SC_AllocPkt(PROT_STR_MISC, g_s20BroadcastID,
  1573. sizeof(*pCMPacket));
  1574. if (!pCMPacket)
  1575. {
  1576. WARNING_OUT(("Failed to alloc CM cached image packet"));
  1577. DC_QUIT;
  1578. }
  1579. //
  1580. // Fill in the packet.
  1581. //
  1582. pCMPacket->header.header.data.dataType = DT_CM;
  1583. pCMPacket->header.type = CM_CURSOR_COLOR_CACHE;
  1584. pCMPacket->cacheIndex = (TSHR_UINT16)iCacheEntry;
  1585. //
  1586. // Send it
  1587. //
  1588. if (m_pShare->m_scfViewSelf)
  1589. m_pShare->CM_ReceivedPacket(m_pShare->m_pasLocal, &(pCMPacket->header.header));
  1590. #ifdef _DEBUG
  1591. sentSize =
  1592. #endif // _DEBUG
  1593. m_pShare->DCS_CompressAndSendPacket(PROT_STR_MISC, g_s20BroadcastID,
  1594. &(pCMPacket->header.header), sizeof(*pCMPacket));
  1595. TRACE_OUT(("CM COLOR CACHE packet size: %08d, sent %08d", sizeof(*pCMPacket),
  1596. sentSize));
  1597. rc = TRUE;
  1598. DC_EXIT_POINT:
  1599. DebugExitBOOL(ASHost::CMSendCachedCursor, rc);
  1600. return(rc);
  1601. }
  1602. //
  1603. // FUNCTION: CMGetControllingWindow
  1604. //
  1605. // DESCRIPTION:
  1606. //
  1607. // Determines the window that is controlling the cursor's current shape.
  1608. //
  1609. // PARAMETERS: None
  1610. //
  1611. // RETURNS: the window that is controlling the cursor's current shape.
  1612. //
  1613. //
  1614. HWND CMGetControllingWindow(void)
  1615. {
  1616. POINT cursorPos;
  1617. HWND hwnd;
  1618. DebugEntry(CMGetControllingWindow);
  1619. //
  1620. // If a SysErrPopup Window (which is always System Modal) is present
  1621. // then WindowFromPoint enters a infinite recursion loop, trashing the
  1622. // stack and crashing the whole system.
  1623. // If there is a SysModal window Window ensure WindowFromPoint is not
  1624. // executed.
  1625. //
  1626. // The window controlling the cursor appearance is:
  1627. //
  1628. // - the local window that has the mouse capture (if any)
  1629. // - the window that is under the current mouse position
  1630. //
  1631. //
  1632. hwnd = GetCapture();
  1633. if (!hwnd)
  1634. {
  1635. //
  1636. // Get the current mouse position.
  1637. //
  1638. GetCursorPos(&cursorPos);
  1639. hwnd = WindowFromPoint(cursorPos);
  1640. }
  1641. DebugExitDWORD(CMGetControllingWindow, HandleToUlong(hwnd));
  1642. return(hwnd);
  1643. }
  1644. //
  1645. // FUNCTION: CMGetCurrentCursor
  1646. //
  1647. // DESCRIPTION:
  1648. //
  1649. // Returns a description of the current cursor
  1650. //
  1651. // PARAMETERS:
  1652. //
  1653. // pCursor - pointer to a CURSORDESCRIPTION variable that receives details
  1654. // of the current cursor
  1655. //
  1656. // RETURNS: Nothing
  1657. //
  1658. //
  1659. void CMGetCurrentCursor(LPCURSORDESCRIPTION pCursor)
  1660. {
  1661. LPCM_FAST_DATA lpcmShared;
  1662. DebugEntry(CMGetCurrentCursor);
  1663. lpcmShared = CM_SHM_START_READING;
  1664. pCursor->type = CM_CD_BITMAPCURSOR;
  1665. pCursor->id = lpcmShared->cmCursorStamp;
  1666. CM_SHM_STOP_READING;
  1667. DebugExitVOID(CMGetCurrentCursor);
  1668. }
  1669. //
  1670. // FUNCTION: CMSendSystemCursor
  1671. //
  1672. // DESCRIPTION:
  1673. //
  1674. // Sends a packet containing the given system cursor IDC.
  1675. //
  1676. // PARAMETERS:
  1677. //
  1678. // cursorIDC - the IDC of the system cursor to send
  1679. //
  1680. // RETURNS: TRUE if successful, FALSE otherwise.
  1681. //
  1682. //
  1683. BOOL ASHost::CMSendSystemCursor(UINT cursorIDC)
  1684. {
  1685. BOOL rc = FALSE;
  1686. PCMPACKETID pCMPacket;
  1687. #ifdef _DEBUG
  1688. UINT sentSize;
  1689. #endif // _DEBUG
  1690. DebugEntry(ASHost::CMSendSystemCursor);
  1691. ASSERT((cursorIDC == CM_IDC_NULL) || (cursorIDC == CM_IDC_ARROW));
  1692. //
  1693. // The cursor is one of the system cursors - create a PROTCURSOR packet
  1694. //
  1695. pCMPacket = (PCMPACKETID)m_pShare->SC_AllocPkt(PROT_STR_MISC, g_s20BroadcastID,
  1696. sizeof(*pCMPacket));
  1697. if (!pCMPacket)
  1698. {
  1699. WARNING_OUT(("Failed to alloc CM system image packet"));
  1700. DC_QUIT;
  1701. }
  1702. //
  1703. // Fill in the packet.
  1704. //
  1705. pCMPacket->header.header.data.dataType = DT_CM;
  1706. pCMPacket->header.type = CM_CURSOR_ID;
  1707. pCMPacket->idc = cursorIDC;
  1708. TRACE_OUT(( "Send CMCURSORID %ld", cursorIDC));
  1709. //
  1710. // Send it
  1711. //
  1712. if (m_pShare->m_scfViewSelf)
  1713. m_pShare->CM_ReceivedPacket(m_pShare->m_pasLocal, &(pCMPacket->header.header));
  1714. #ifdef _DEBUG
  1715. sentSize =
  1716. #endif // _DEBUG
  1717. m_pShare->DCS_CompressAndSendPacket(PROT_STR_MISC, g_s20BroadcastID,
  1718. &(pCMPacket->header.header), sizeof(*pCMPacket));
  1719. TRACE_OUT(("CM ID packet size: %08d, sent %08d", sizeof(*pCMPacket),
  1720. sentSize));
  1721. //
  1722. // Indicate that we successfully sent a packet.
  1723. //
  1724. rc = TRUE;
  1725. DC_EXIT_POINT:
  1726. DebugExitBOOL(ASHost::CMSendSystemCursor, rc);
  1727. return(rc);
  1728. }
  1729. //
  1730. // FUNCTION: CMSendBitmapCursor
  1731. //
  1732. // DESCRIPTION:
  1733. //
  1734. // Sends the current cursor as a bitmap.
  1735. //
  1736. // PARAMETERS: None
  1737. //
  1738. // RETURNS: TRUE if successful, FALSE otherwise.
  1739. //
  1740. //
  1741. BOOL ASHost::CMSendBitmapCursor(void)
  1742. {
  1743. BOOL rc = FALSE;
  1744. LPCM_SHAPE pCursor;
  1745. UINT cbCursorDataSize;
  1746. DebugEntry(ASHost::CMSendBitmapCursor);
  1747. //
  1748. // If cursor is hidden, send Null cursor
  1749. //
  1750. if (m_cmfCursorHidden)
  1751. {
  1752. TRACE_OUT(( "Send Null cursor (cursor hidden)"));
  1753. CMSendSystemCursor(CM_IDC_NULL);
  1754. DC_QUIT;
  1755. }
  1756. //
  1757. // Get a pointer to the current cursor shape.
  1758. //
  1759. if (!CMGetCursorShape(&pCursor, &cbCursorDataSize))
  1760. {
  1761. DC_QUIT;
  1762. }
  1763. //
  1764. // If this is a Null pointer, send the relevant packet.
  1765. //
  1766. if (CM_CURSOR_IS_NULL(pCursor))
  1767. {
  1768. TRACE_OUT(( "Send Null cursor"));
  1769. CMSendSystemCursor(CM_IDC_NULL);
  1770. DC_QUIT;
  1771. }
  1772. //
  1773. // If all of the parties in the call support the color cursor protocol
  1774. // then we try to send the cursor using that protocol, otherwise we
  1775. // send a mono cursor.
  1776. //
  1777. if (m_cmfUseColorCursorProtocol)
  1778. {
  1779. if (!CMSendCursorShape(pCursor, cbCursorDataSize))
  1780. {
  1781. DC_QUIT;
  1782. }
  1783. }
  1784. else
  1785. {
  1786. //
  1787. // We cannot send cursors that are not 32x32 using the mono
  1788. // protocol.
  1789. //
  1790. if ((pCursor->hdr.cx != 32) || (pCursor->hdr.cy != 32))
  1791. {
  1792. //
  1793. // Maybe copy and alter the cursor definition so that it is
  1794. // 32x32 ?
  1795. //
  1796. WARNING_OUT(( "Non-standard cursor (%d x %d)", pCursor->hdr.cx,
  1797. pCursor->hdr.cy ));
  1798. DC_QUIT;
  1799. }
  1800. if (!CMSendMonoBitmapCursor(pCursor))
  1801. {
  1802. DC_QUIT;
  1803. }
  1804. }
  1805. //
  1806. // Return success.
  1807. //
  1808. rc = TRUE;
  1809. DC_EXIT_POINT:
  1810. DebugExitDWORD(ASHost::CMSendBitmapCursor, rc);
  1811. return(rc);
  1812. }
  1813. //
  1814. // FUNCTION: CMCalculateColorCursorSize
  1815. //
  1816. // DESCRIPTION:
  1817. //
  1818. // Calculates the size in bytes of a given color cursor.
  1819. //
  1820. // PARAMETERS:
  1821. //
  1822. // pCursor - pointer to the cursor shape
  1823. //
  1824. // pcbANDMaskSize - pointer to a UINT variable that receives the AND mask
  1825. // size in bytes
  1826. //
  1827. // pcbXORBitmapSize - pointer to a UINT variable that receives the XOR
  1828. // bitmap size in bytes
  1829. //
  1830. // RETURNS: Nothing
  1831. //
  1832. //
  1833. void CMCalculateColorCursorSize( LPCM_SHAPE pCursor,
  1834. LPUINT pcbANDMaskSize,
  1835. LPUINT pcbXORBitmapSize)
  1836. {
  1837. DebugEntry(CMCalculcateColorCursorSize);
  1838. *pcbANDMaskSize = CURSOR_AND_MASK_SIZE(pCursor);
  1839. *pcbXORBitmapSize = CURSOR_DIB_BITS_SIZE( pCursor->hdr.cx,
  1840. pCursor->hdr.cy,
  1841. 24 );
  1842. DebugExitVOID(CMCalculateColorCursorSize);
  1843. }
  1844. //
  1845. // FUNCTION: CMSendColorBitmapCursor
  1846. //
  1847. // DESCRIPTION:
  1848. //
  1849. // Sends a given cursor as a color bitmap.
  1850. //
  1851. // PARAMETERS:
  1852. //
  1853. // pCursor - pointer to the cursor shape
  1854. //
  1855. // iCacheEntry - cache index to store in the transmitted packet
  1856. //
  1857. // RETURNS: TRUE if packet sent, FALSE otherwise
  1858. //
  1859. //
  1860. BOOL ASHost::CMSendColorBitmapCursor(LPCM_SHAPE pCursor, UINT iCacheEntry)
  1861. {
  1862. UINT cbPacketSize;
  1863. PCMPACKETCOLORBITMAP pCMPacket;
  1864. BOOL rc = FALSE;
  1865. UINT cbANDMaskSize;
  1866. UINT cbXORBitmapSize;
  1867. UINT cbColorCursorSize;
  1868. #ifdef _DEBUG
  1869. UINT sentSize;
  1870. #endif // _DEBUG
  1871. DebugEntry(ASHost::CMSendColorBitmapCursor);
  1872. CMCalculateColorCursorSize(pCursor, &cbANDMaskSize, &cbXORBitmapSize );
  1873. cbColorCursorSize = cbANDMaskSize + cbXORBitmapSize;
  1874. //
  1875. // Allocate a packet.
  1876. //
  1877. cbPacketSize = sizeof(CMPACKETCOLORBITMAP) + (cbColorCursorSize - 1);
  1878. pCMPacket = (PCMPACKETCOLORBITMAP)m_pShare->SC_AllocPkt(PROT_STR_MISC,
  1879. g_s20BroadcastID, cbPacketSize);
  1880. if (!pCMPacket)
  1881. {
  1882. WARNING_OUT(("Failed to alloc CM color image packet, size %u", cbPacketSize));
  1883. DC_QUIT;
  1884. }
  1885. //
  1886. // Fill in the packet.
  1887. //
  1888. pCMPacket->header.header.data.dataType = DT_CM;
  1889. //
  1890. // Fill in fields.
  1891. //
  1892. pCMPacket->header.type = CM_CURSOR_COLOR_BITMAP;
  1893. pCMPacket->cacheIndex = (TSHR_UINT16)iCacheEntry;
  1894. if (!CMGetColorCursorDetails(pCursor,
  1895. &(pCMPacket->cxWidth), &(pCMPacket->cyHeight),
  1896. &(pCMPacket->xHotSpot), &(pCMPacket->yHotSpot),
  1897. pCMPacket->aBits + cbXORBitmapSize,
  1898. &(pCMPacket->cbANDMask),
  1899. pCMPacket->aBits,
  1900. &(pCMPacket->cbXORBitmap )))
  1901. {
  1902. //
  1903. // Failed to get a cursor details. Must free up SNI packet
  1904. //
  1905. S20_FreeDataPkt(&(pCMPacket->header.header));
  1906. DC_QUIT;
  1907. }
  1908. ASSERT((pCMPacket->cbANDMask == cbANDMaskSize));
  1909. ASSERT((pCMPacket->cbXORBitmap == cbXORBitmapSize));
  1910. //
  1911. // Send it
  1912. //
  1913. if (m_pShare->m_scfViewSelf)
  1914. m_pShare->CM_ReceivedPacket(m_pShare->m_pasLocal, &(pCMPacket->header.header));
  1915. #ifdef _DEBUG
  1916. sentSize =
  1917. #endif // _DEBUG
  1918. m_pShare->DCS_CompressAndSendPacket(PROT_STR_MISC, g_s20BroadcastID,
  1919. &(pCMPacket->header.header), sizeof(*pCMPacket));
  1920. TRACE_OUT(("CM COLOR BITMAP packet size: %08d, sent %08d", sizeof(*pCMPacket),
  1921. sentSize));
  1922. //
  1923. // Indicate that we successfully sent a packet.
  1924. //
  1925. rc = TRUE;
  1926. DC_EXIT_POINT:
  1927. DebugExitBOOL(ASHost::CMSendColorBitmapCursor, rc);
  1928. return(rc);
  1929. }
  1930. //
  1931. // FUNCTION: CMSendMonoBitmapCursor
  1932. //
  1933. // DESCRIPTION:
  1934. //
  1935. // Sends a given cursor as a mono bitmap
  1936. //
  1937. // PARAMETERS:
  1938. //
  1939. // pCursor - pointer to the cursor shape
  1940. //
  1941. // RETURNS: TRUE if packet sent, FALSE otherwise
  1942. //
  1943. //
  1944. BOOL ASHost::CMSendMonoBitmapCursor(LPCM_SHAPE pCursor)
  1945. {
  1946. UINT cbPacketSize;
  1947. PCMPACKETMONOBITMAP pCMPacket;
  1948. BOOL rc = FALSE;
  1949. TSHR_UINT16 cbANDMaskSize;
  1950. TSHR_UINT16 cbXORBitmapSize;
  1951. #ifdef _DEBUG
  1952. UINT sentSize;
  1953. #endif // _DEBUG
  1954. DebugEntry(AShare::CMSendMonoBitmapCursor);
  1955. //
  1956. // Calculate the sizes of the converted (1bpp) AND and XOR bitmaps.
  1957. //
  1958. cbANDMaskSize = (TSHR_UINT16)CURSOR_AND_MASK_SIZE(pCursor);
  1959. cbXORBitmapSize = cbANDMaskSize;
  1960. //
  1961. // Allocate a packet.
  1962. //
  1963. cbPacketSize = sizeof(CMPACKETMONOBITMAP) +
  1964. (cbANDMaskSize + cbXORBitmapSize - 1);
  1965. pCMPacket = (PCMPACKETMONOBITMAP)m_pShare->SC_AllocPkt(PROT_STR_MISC,
  1966. g_s20BroadcastID, cbPacketSize);
  1967. if (!pCMPacket)
  1968. {
  1969. WARNING_OUT(("Failed to alloc CM mono image packet, size %u", cbPacketSize));
  1970. DC_QUIT;
  1971. }
  1972. //
  1973. // Fill FF in to initialize the XOR and AND bits
  1974. //
  1975. FillMemory((LPBYTE)(pCMPacket+1)-1, cbANDMaskSize + cbXORBitmapSize, 0xFF);
  1976. //
  1977. // Fill in the packet.
  1978. //
  1979. pCMPacket->header.header.data.dataType = DT_CM;
  1980. //
  1981. // Fill in fields.
  1982. //
  1983. pCMPacket->header.type = CM_CURSOR_MONO_BITMAP;
  1984. CMGetMonoCursorDetails(pCursor,
  1985. &(pCMPacket->width),
  1986. &(pCMPacket->height),
  1987. &(pCMPacket->xHotSpot),
  1988. &(pCMPacket->yHotSpot),
  1989. pCMPacket->aBits + cbXORBitmapSize,
  1990. &cbANDMaskSize,
  1991. pCMPacket->aBits,
  1992. &cbXORBitmapSize );
  1993. pCMPacket->cbBits = (TSHR_UINT16) (cbANDMaskSize + cbXORBitmapSize);
  1994. TRACE_OUT(( "Mono cursor cx:%u cy:%u xhs:%u yhs:%u cbAND:%u cbXOR:%u",
  1995. pCMPacket->width, pCMPacket->height,
  1996. pCMPacket->xHotSpot, pCMPacket->yHotSpot,
  1997. cbANDMaskSize, cbXORBitmapSize));
  1998. //
  1999. // Send it
  2000. //
  2001. if (m_pShare->m_scfViewSelf)
  2002. m_pShare->CM_ReceivedPacket(m_pShare->m_pasLocal, &(pCMPacket->header.header));
  2003. #ifdef _DEBUG
  2004. sentSize =
  2005. #endif // _DEBUG
  2006. m_pShare->DCS_CompressAndSendPacket(PROT_STR_MISC, g_s20BroadcastID,
  2007. &(pCMPacket->header.header), sizeof(*pCMPacket));
  2008. TRACE_OUT(("CM MONO BITMAP packet size: %08d, sent %08d", sizeof(*pCMPacket),
  2009. sentSize));
  2010. //
  2011. // Indicate that we successfully sent a packet.
  2012. //
  2013. rc = TRUE;
  2014. DC_EXIT_POINT:
  2015. DebugExitDWORD(ASHost::CMSendMonoBitmapCursor, rc);
  2016. return(rc);
  2017. }
  2018. //
  2019. // FUNCTION: CMCreateMonoCursor
  2020. //
  2021. // DESCRIPTION: Creates a mono cursor
  2022. //
  2023. // PARAMETERS:
  2024. //
  2025. // xHotSpot - x position of the hotspot
  2026. //
  2027. // yHotSpot - y position of the hotspot
  2028. //
  2029. // cxWidth - width of the cursor
  2030. //
  2031. // cyHeight - height of the cursor
  2032. //
  2033. // pANDMask - pointer to a 1bpp, word-padded AND mask
  2034. //
  2035. // pXORBitmap - pointer to a 1bpp, word-padded XOR bitmap
  2036. //
  2037. // RETURNS: a valid cursor id, or NULL if the function fails
  2038. //
  2039. //
  2040. HCURSOR ASShare::CMCreateMonoCursor(UINT xHotSpot,
  2041. UINT yHotSpot,
  2042. UINT cxWidth,
  2043. UINT cyHeight,
  2044. LPBYTE pANDMask,
  2045. LPBYTE pXORBitmap)
  2046. {
  2047. HCURSOR rc;
  2048. DebugEntry(ASShare::CMCreateMonoCursor);
  2049. //
  2050. // Attempt to create the mono cursor.
  2051. //
  2052. rc = CreateCursor(g_asInstance, xHotSpot, yHotSpot, cxWidth, cyHeight,
  2053. pANDMask, pXORBitmap);
  2054. //
  2055. // Check that the cursor handle is not null.
  2056. //
  2057. if (NULL == rc)
  2058. {
  2059. //
  2060. // Substitute the default arrow cursor.
  2061. //
  2062. rc = m_cmArrowCursor;
  2063. WARNING_OUT(( "Could not create cursor - substituting default arrow"));
  2064. }
  2065. //
  2066. // Return the cursor
  2067. //
  2068. DebugExitDWORD(ASShare::CMCreateMonoCursor, HandleToUlong(rc));
  2069. return(rc);
  2070. }
  2071. //
  2072. // FUNCTION: CMCreateColorCursor
  2073. //
  2074. // DESCRIPTION:
  2075. //
  2076. // Creates a color cursor.
  2077. //
  2078. // PARAMETERS:
  2079. //
  2080. // xHotSpot - x position of the hotspot
  2081. //
  2082. // yHotSpot - y position of the hotspot
  2083. //
  2084. // cxWidth - width of the cursor
  2085. //
  2086. // cyHeight - height of the cursor
  2087. //
  2088. // pANDMask - pointer to a 1bpp, word-padded AND mask
  2089. //
  2090. // pXORBitmap - pointer to a 24bpp, word-padded XOR bitmap
  2091. //
  2092. // cbANDMask - the size in bytes of the AND mask
  2093. //
  2094. // cbXORBitmap - the size in bytes of the XOR bitmap
  2095. //
  2096. // RETURNS: a valid cursor id, or NULL if the function fails
  2097. //
  2098. //
  2099. HCURSOR ASShare::CMCreateColorCursor
  2100. (
  2101. UINT xHotSpot,
  2102. UINT yHotSpot,
  2103. UINT cxWidth,
  2104. UINT cyHeight,
  2105. LPBYTE pANDMask,
  2106. LPBYTE pXORBitmap,
  2107. UINT cbANDMask,
  2108. UINT cbXORBitmap
  2109. )
  2110. {
  2111. HCURSOR rc = 0;
  2112. UINT cbAllocSize;
  2113. LPBITMAPINFO pbmi = NULL;
  2114. HDC hdc = NULL;
  2115. ICONINFO iconInfo;
  2116. HBITMAP hbmXORBitmap = NULL;
  2117. HBITMAP hbmANDMask = NULL;
  2118. HWND hwndDesktop = NULL;
  2119. DebugEntry(ASShare::CMCreateColorCursor);
  2120. TRACE_OUT(("xhs(%u) yhs(%u) cx(%u) cy(%u) cbXOR(%u) cbAND(%u)",
  2121. xHotSpot,
  2122. yHotSpot,
  2123. cxWidth,
  2124. cyHeight,
  2125. cbXORBitmap,
  2126. cbANDMask ));
  2127. //
  2128. // We need a BITMAPINFO structure plus one additional RGBQUAD (there is
  2129. // one included within the BITMAPINFO). We use this to pass the 24bpp
  2130. // XOR bitmap (which has no color table) and the 1bpp AND mask (which
  2131. // requires 2 colors).
  2132. //
  2133. cbAllocSize = sizeof(*pbmi) + sizeof(RGBQUAD);
  2134. pbmi = (LPBITMAPINFO)new BYTE[cbAllocSize];
  2135. if (pbmi == NULL)
  2136. {
  2137. WARNING_OUT(( "Failed to alloc bmi(%x)", cbAllocSize));
  2138. DC_QUIT;
  2139. }
  2140. //
  2141. // Get a screen DC that we can pass to CreateDIBitmap. We do not use
  2142. // CreateCompatibleDC(NULL) here because that results in Windows
  2143. // creating a mono bitmap.
  2144. //
  2145. hwndDesktop = GetDesktopWindow();
  2146. hdc = GetWindowDC(hwndDesktop);
  2147. if (hdc == NULL)
  2148. {
  2149. WARNING_OUT(( "Failed to create DC"));
  2150. DC_QUIT;
  2151. }
  2152. pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  2153. pbmi->bmiHeader.biWidth = cxWidth;
  2154. pbmi->bmiHeader.biHeight = cyHeight;
  2155. pbmi->bmiHeader.biPlanes = 1;
  2156. pbmi->bmiHeader.biBitCount = 24;
  2157. pbmi->bmiHeader.biCompression = 0;
  2158. pbmi->bmiHeader.biSizeImage = cbXORBitmap;
  2159. pbmi->bmiHeader.biXPelsPerMeter = 0;
  2160. pbmi->bmiHeader.biYPelsPerMeter = 0;
  2161. pbmi->bmiHeader.biClrUsed = 0;
  2162. pbmi->bmiHeader.biClrImportant = 0;
  2163. hbmXORBitmap = CreateDIBitmap( hdc,
  2164. (LPBITMAPINFOHEADER)pbmi,
  2165. CBM_INIT,
  2166. pXORBitmap,
  2167. pbmi,
  2168. DIB_RGB_COLORS );
  2169. ReleaseDC(hwndDesktop, hdc);
  2170. if (hbmXORBitmap == NULL)
  2171. {
  2172. WARNING_OUT(( "Failed to create XOR bitmap"));
  2173. DC_QUIT;
  2174. }
  2175. //
  2176. // Create MONOCHROME mask bitmap. This works on both Win95 and NT.
  2177. // COLOR masks don't work on Win95, just NT.
  2178. //
  2179. hdc = CreateCompatibleDC(NULL);
  2180. if (!hdc)
  2181. {
  2182. WARNING_OUT(("Failed to get screen dc"));
  2183. DC_QUIT;
  2184. }
  2185. pbmi->bmiHeader.biBitCount = 1;
  2186. pbmi->bmiHeader.biCompression = 0;
  2187. pbmi->bmiHeader.biSizeImage = cbANDMask;
  2188. // Black
  2189. pbmi->bmiColors[0].rgbRed = 0x00;
  2190. pbmi->bmiColors[0].rgbGreen = 0x00;
  2191. pbmi->bmiColors[0].rgbBlue = 0x00;
  2192. pbmi->bmiColors[0].rgbReserved = 0x00;
  2193. // White
  2194. pbmi->bmiColors[1].rgbRed = 0xFF;
  2195. pbmi->bmiColors[1].rgbGreen = 0xFF;
  2196. pbmi->bmiColors[1].rgbBlue = 0xFF;
  2197. pbmi->bmiColors[1].rgbReserved = 0x00;
  2198. hbmANDMask = CreateDIBitmap( hdc,
  2199. (LPBITMAPINFOHEADER)pbmi,
  2200. CBM_INIT,
  2201. pANDMask,
  2202. pbmi,
  2203. DIB_RGB_COLORS );
  2204. DeleteDC(hdc);
  2205. if (hbmANDMask == NULL)
  2206. {
  2207. WARNING_OUT(( "Failed to create AND mask"));
  2208. DC_QUIT;
  2209. }
  2210. #ifdef _DEBUG
  2211. //
  2212. // Make sure the AND mask is monochrome
  2213. //
  2214. {
  2215. BITMAP bmp;
  2216. GetObject(hbmANDMask, sizeof(BITMAP), &bmp);
  2217. ASSERT(bmp.bmPlanes == 1);
  2218. ASSERT(bmp.bmBitsPixel == 1);
  2219. }
  2220. #endif
  2221. iconInfo.fIcon = FALSE;
  2222. iconInfo.xHotspot = xHotSpot;
  2223. iconInfo.yHotspot = yHotSpot;
  2224. iconInfo.hbmMask = hbmANDMask;
  2225. iconInfo.hbmColor = hbmXORBitmap;
  2226. rc = CreateIconIndirect(&iconInfo);
  2227. TRACE_OUT(( "CreateCursor(%x) cx(%u)cy(%u)", rc, cxWidth, cyHeight));
  2228. DC_EXIT_POINT:
  2229. if (hbmXORBitmap != NULL)
  2230. {
  2231. DeleteBitmap(hbmXORBitmap);
  2232. }
  2233. if (hbmANDMask != NULL)
  2234. {
  2235. DeleteBitmap(hbmANDMask);
  2236. }
  2237. if (pbmi != NULL)
  2238. {
  2239. delete[] pbmi;
  2240. }
  2241. //
  2242. // Check that we have successfully managed to create the cursor. If
  2243. // not then substitute the default cursor.
  2244. //
  2245. if (rc == 0)
  2246. {
  2247. //
  2248. // Substitute the default arrow cursor.
  2249. //
  2250. rc = m_cmArrowCursor;
  2251. WARNING_OUT(( "Could not create cursor - substituting default arrow"));
  2252. }
  2253. DebugExitDWORD(ASShare::CMCreateColorCursor, HandleToUlong(rc));
  2254. return(rc);
  2255. }
  2256. //
  2257. // FUNCTION: CMCreateAbbreviatedName
  2258. //
  2259. // DESCRIPTION:
  2260. //
  2261. // This function attempts to take a name, and create an abbreviation from
  2262. // the first characters of the first and last name.
  2263. //
  2264. // PARAMETERS:
  2265. //
  2266. // szTagName - a pointer to a string containing the name to abbreviate.
  2267. // szBuf - a pointer to a buffer into which the abbreviation will
  2268. // be created.
  2269. // cbBuf - size of buffer pointed to by szBuf.
  2270. //
  2271. // RETURNS:
  2272. //
  2273. // TRUE: Success. szBuf filled in.
  2274. // FALSE: Failure. szBuf is not filled in.
  2275. //
  2276. //
  2277. BOOL CMCreateAbbreviatedName(LPCSTR szTagName, LPSTR szBuf,
  2278. UINT cbBuf)
  2279. {
  2280. BOOL rc = FALSE;
  2281. LPSTR p;
  2282. LPSTR q;
  2283. DebugEntry(CMCreateAbbreviatedName);
  2284. //
  2285. // This function isn't DBCS safe, so we don't abbreviate in DBCS
  2286. // character sets.
  2287. //
  2288. if (TRUE == GetSystemMetrics(SM_DBCSENABLED))
  2289. {
  2290. DC_QUIT;
  2291. }
  2292. //
  2293. // Try to create initials. If that doesn't work, fail the call.
  2294. //
  2295. if ((NULL != (p = (LPSTR)_StrChr(szTagName, ' '))) && ('\0' != *(p+1)))
  2296. {
  2297. //
  2298. // Is there enough room for initials?
  2299. //
  2300. if (cbBuf < NTRUNCLETTERS)
  2301. {
  2302. DC_QUIT;
  2303. }
  2304. q = szBuf;
  2305. *q++ = *szTagName;
  2306. *q++ = '.';
  2307. *q++ = *(p+1);
  2308. *q++ = '.';
  2309. *q = '\0';
  2310. AnsiUpper(szBuf);
  2311. rc = TRUE;
  2312. }
  2313. DC_EXIT_POINT:
  2314. DebugExitBOOL(CMCreateAbbreviatedName, rc);
  2315. return rc;
  2316. }
  2317. //
  2318. // FUNCTION: CMDrawCursorTag
  2319. //
  2320. // DESCRIPTION:
  2321. //
  2322. // PARAMETERS:
  2323. //
  2324. // hdcWindow - DC handle of the window to be drawn to
  2325. //
  2326. // cursorID - handle of cursor to drawn
  2327. //
  2328. // RETURNS: Nothing.
  2329. //
  2330. //
  2331. void ASShare::CMDrawCursorTag
  2332. (
  2333. ASPerson * pasHost,
  2334. HDC hdc
  2335. )
  2336. {
  2337. ASPerson * pasPerson;
  2338. char ShortName[TSHR_MAX_PERSON_NAME_LEN];
  2339. HFONT hOldFont = NULL;
  2340. RECT rect;
  2341. UINT cCharsFit;
  2342. LPSTR p;
  2343. DebugEntry(ASShare::CMDrawCursorTag);
  2344. pasPerson = pasHost->m_caControlledBy;
  2345. if (!pasPerson)
  2346. {
  2347. // Nothing to do
  2348. DC_QUIT;
  2349. }
  2350. ValidatePerson(pasPerson);
  2351. //
  2352. // Try to abbreviate the person's name, so it will fit into the tag.
  2353. // If the abbreviation fails, just copy the entire name for now.
  2354. //
  2355. if (!(CMCreateAbbreviatedName(pasPerson->scName, ShortName, sizeof(ShortName))))
  2356. {
  2357. lstrcpyn(ShortName, pasPerson->scName, sizeof(ShortName));
  2358. }
  2359. //
  2360. // Select the cursor tag font into the DC.
  2361. //
  2362. hOldFont = SelectFont(hdc, m_cmCursorTagFont);
  2363. if (hOldFont == NULL)
  2364. {
  2365. WARNING_OUT(("CMDrawCursorTag failed"));
  2366. DC_QUIT;
  2367. }
  2368. //
  2369. // Create the tag background...
  2370. //
  2371. PatBlt(hdc, TAGXOFF, TAGYOFF, TAGXSIZ, TAGYSIZ, WHITENESS);
  2372. //
  2373. // See how many characters of the name or abbreviation we can fit into
  2374. // the tag. First assume the whole thing fits.
  2375. //
  2376. cCharsFit = lstrlen(ShortName);
  2377. //
  2378. // Determine how many characters actually fit.
  2379. //
  2380. rect.left = rect.top = rect.right = rect.bottom = 0;
  2381. for (p = AnsiNext(ShortName); ; p = AnsiNext(p))
  2382. {
  2383. if (DrawText(hdc, ShortName, (int)(p - ShortName), &rect,
  2384. DT_CALCRECT | DT_SINGLELINE | DT_NOPREFIX))
  2385. {
  2386. if (rect.right > TAGXSIZ)
  2387. {
  2388. //
  2389. // This number of characters does not fit into the tag. Try
  2390. // the next smaller number.
  2391. //
  2392. cCharsFit = (UINT)(AnsiPrev(ShortName, p) - ShortName);
  2393. break;
  2394. }
  2395. }
  2396. if ( '\0' == *p)
  2397. break;
  2398. }
  2399. //
  2400. // Now draw the text. Note that DrawText does not return a documented
  2401. // error code, so we don't check.
  2402. //
  2403. rect.left = TAGXOFF;
  2404. rect.top = TAGYOFF;
  2405. rect.right = TAGXOFF + TAGXSIZ;
  2406. rect.bottom = TAGYOFF + TAGYSIZ;
  2407. DrawText(hdc, ShortName, cCharsFit, &rect,
  2408. DT_CENTER | DT_SINGLELINE | DT_NOPREFIX);
  2409. DC_EXIT_POINT:
  2410. //
  2411. // Perform necessary cleanup.
  2412. //
  2413. if (hOldFont)
  2414. {
  2415. SelectFont(hdc, hOldFont);
  2416. }
  2417. DebugExitVOID(ASShare::CMDrawCursorTag);
  2418. }
  2419. //
  2420. // FUNCTION: CMGetCursorShape
  2421. //
  2422. // DESCRIPTION:
  2423. //
  2424. // Returns a pointer to a DCCURSORSHAPE structure that defines the bit
  2425. // definition of the currently displayed cursor.
  2426. //
  2427. // A DCCURSORSHAPE structure is OS-specific. The higher level code does
  2428. // not look at any individual fields in this structure - it just compares
  2429. // the whole data block with others in the cursor cache. If two
  2430. // DCCURSORSHAPE structures contain the same the data, then the
  2431. // corresponding cursors are assumed to be the same.
  2432. //
  2433. // The LPCM_SHAPE returned here is passed back into
  2434. // CMGetColorCursorDetails or CMGetMonoCursorDetails to retrieve the
  2435. // specific details.
  2436. //
  2437. // PARAMETERS:
  2438. //
  2439. // ppCursorShape - pointer to a LPCM_SHAPE variable that receives the
  2440. // pointer to the DCCURSORSHAPE structure
  2441. //
  2442. // pcbCursorDataSize - pointer to a UINT variable that receives the size
  2443. // in bytes of the DCCURSORSHAPE structure
  2444. //
  2445. // RETURNS: Success TRUE/FALSE
  2446. //
  2447. //
  2448. BOOL CMGetCursorShape(LPCM_SHAPE * ppCursorShape,
  2449. LPUINT pcbCursorDataSize )
  2450. {
  2451. LPCM_FAST_DATA lpcmShared;
  2452. BOOL rc = FALSE;
  2453. DebugEntry(CMGetCursorShape);
  2454. lpcmShared = CM_SHM_START_READING;
  2455. //
  2456. // Check that a cursor has been written to shared memory - may happen
  2457. // on start-up before the display driver has written a cursor - or if
  2458. // the display driver is not working.
  2459. //
  2460. if (lpcmShared->cmCursorShapeData.hdr.cBitsPerPel == 0)
  2461. {
  2462. TRACE_OUT(( "No cursor in shared memory"));
  2463. DC_QUIT;
  2464. }
  2465. *ppCursorShape = (LPCM_SHAPE)&lpcmShared->cmCursorShapeData;
  2466. *pcbCursorDataSize = CURSORSHAPE_SIZE(&lpcmShared->cmCursorShapeData);
  2467. rc = TRUE;
  2468. DC_EXIT_POINT:
  2469. CM_SHM_STOP_READING;
  2470. DebugExitDWORD(CMGetCursorShape, rc);
  2471. return(rc);
  2472. }
  2473. //
  2474. // FUNCTION: CMGetColorCursorDetails
  2475. //
  2476. // DESCRIPTION:
  2477. //
  2478. // Returns details of a cursor at 24bpp, given a DCCURSORSHAPE structure.
  2479. //
  2480. // PARAMETERS:
  2481. //
  2482. // pCursor - pointer to a DCCURSORSHAPE structure from which this function
  2483. // extracts the details
  2484. //
  2485. // pcxWidth - pointer to a TSHR_UINT16 variable that receives the cursor width
  2486. // in pixels
  2487. //
  2488. // pcyHeight - pointer to a TSHR_UINT16 variable that receives the cursor
  2489. // height in pixels
  2490. //
  2491. // pxHotSpot - pointer to a TSHR_UINT16 variable that receives the cursor
  2492. // hotspot x coordinate
  2493. //
  2494. // pyHotSpot - pointer to a TSHR_UINT16 variable that receives the cursor
  2495. // hotspot y coordinate
  2496. //
  2497. // pANDMask - pointer to a buffer that receives the cursor AND mask
  2498. //
  2499. // pcbANDMask - pointer to a TSHR_UINT16 variable that receives the size in
  2500. // bytes of the cursor AND mask
  2501. //
  2502. // pXORBitmap - pointer to a buffer that receives the cursor XOR bitmap at
  2503. // 24bpp
  2504. //
  2505. // pcbXORBitmap - pointer to a TSHR_UINT16 variable that receives the size in
  2506. // bytes of the cursor XOR bitmap
  2507. //
  2508. //
  2509. BOOL ASHost::CMGetColorCursorDetails
  2510. (
  2511. LPCM_SHAPE pCursor,
  2512. LPTSHR_UINT16 pcxWidth,
  2513. LPTSHR_UINT16 pcyHeight,
  2514. LPTSHR_UINT16 pxHotSpot,
  2515. LPTSHR_UINT16 pyHotSpot,
  2516. LPBYTE pANDMask,
  2517. LPTSHR_UINT16 pcbANDMask,
  2518. LPBYTE pXORBitmap,
  2519. LPTSHR_UINT16 pcbXORBitmap
  2520. )
  2521. {
  2522. BOOL rc = FALSE;
  2523. LPCM_SHAPE_HEADER pCursorHdr;
  2524. HDC hdcScreen = NULL;
  2525. HBITMAP hbmp = NULL;
  2526. UINT cbANDMaskSize;
  2527. UINT cbXORBitmapSize;
  2528. HDC hdcTmp = NULL;
  2529. UINT cbANDMaskRowWidth;
  2530. UINT cbSrcRowOffset;
  2531. UINT cbDstRowOffset;
  2532. UINT y;
  2533. LPUINT pDestBitmasks;
  2534. BITMAPINFO_ours bmi;
  2535. BITMAPINFO_ours srcbmi;
  2536. HBITMAP oldBitmap;
  2537. void * pBmBits = NULL;
  2538. int numColors;
  2539. int ii;
  2540. LPCM_FAST_DATA lpcmShared;
  2541. DebugEntry(ASHost::CMGetColorCursorDetails);
  2542. if (pCursor == NULL)
  2543. {
  2544. DC_QUIT;
  2545. }
  2546. pCursorHdr = &(pCursor->hdr);
  2547. //
  2548. // Copy the cursor size and hotspot coords.
  2549. //
  2550. *pcxWidth = pCursorHdr->cx;
  2551. *pcyHeight = pCursorHdr->cy;
  2552. *pxHotSpot = (TSHR_UINT16)pCursorHdr->ptHotSpot.x;
  2553. *pyHotSpot = (TSHR_UINT16)pCursorHdr->ptHotSpot.y;
  2554. TRACE_OUT(( "cx(%u) cy(%u) cbWidth %d planes(%u) bpp(%u)",
  2555. pCursorHdr->cx,
  2556. pCursorHdr->cy,
  2557. pCursorHdr->cbRowWidth,
  2558. pCursorHdr->cPlanes,
  2559. pCursorHdr->cBitsPerPel ));
  2560. cbANDMaskSize = CURSOR_AND_MASK_SIZE(pCursor);
  2561. cbXORBitmapSize = CURSOR_XOR_BITMAP_SIZE(pCursor);
  2562. //
  2563. // Copy the AND mask - this is always mono.
  2564. //
  2565. // The AND mask is currently in top-down format (the top row of the
  2566. // bitmap comes first).
  2567. //
  2568. // The protocol sends bitmaps in Device Independent format, which is
  2569. // bottom-up. We therefore have to flip the rows as we copy the mask.
  2570. //
  2571. cbANDMaskRowWidth = pCursorHdr->cbRowWidth;
  2572. cbSrcRowOffset = 0;
  2573. cbDstRowOffset = cbANDMaskRowWidth * (pCursorHdr->cy-1);
  2574. for (y = 0; y < pCursorHdr->cy; y++)
  2575. {
  2576. memcpy( pANDMask + cbDstRowOffset,
  2577. pCursor->Masks + cbSrcRowOffset,
  2578. cbANDMaskRowWidth );
  2579. cbSrcRowOffset += cbANDMaskRowWidth;
  2580. cbDstRowOffset -= cbANDMaskRowWidth;
  2581. }
  2582. //
  2583. // The XOR mask is color and is in DIB format - at 1bpp for mono
  2584. // cursors, or the display driver bpp.
  2585. //
  2586. // We create a bitmap of the same size, set the bits into it and then
  2587. // get the bits out in 24bpp DIB format.
  2588. //
  2589. hdcTmp = CreateCompatibleDC(NULL);
  2590. if (hdcTmp == NULL)
  2591. {
  2592. ERROR_OUT(( "failed to create DC"));
  2593. DC_QUIT;
  2594. }
  2595. //
  2596. // Setup source bitmap information.
  2597. //
  2598. m_pShare->USR_InitDIBitmapHeader((BITMAPINFOHEADER *)&srcbmi, pCursorHdr->cBitsPerPel);
  2599. srcbmi.bmiHeader.biWidth = pCursorHdr->cx;
  2600. srcbmi.bmiHeader.biHeight = pCursorHdr->cy;
  2601. numColors = COLORS_FOR_BPP(pCursorHdr->cBitsPerPel);
  2602. //
  2603. // Setup source palette info.
  2604. //
  2605. if (pCursorHdr->cBitsPerPel > 8)
  2606. {
  2607. //
  2608. // If the device bpp is > 8, we have to set up the DIB section to
  2609. // use the same bitmasks as the device. This means setting the
  2610. // compression type to BI_BITFIELDS and setting the first 3 DWORDS
  2611. // of the bitmap info color table to be the bitmasks for R, G and B
  2612. // respectively.
  2613. // But not for 24bpp. No bitmask or palette are used - it is
  2614. // always 8,8,8 RGB.
  2615. //
  2616. if (pCursorHdr->cBitsPerPel != 24)
  2617. {
  2618. TRACE_OUT(( "Copy bitfields"));
  2619. srcbmi.bmiHeader.biCompression = BI_BITFIELDS;
  2620. lpcmShared = CM_SHM_START_READING;
  2621. pDestBitmasks = (LPUINT)(srcbmi.bmiColors);
  2622. pDestBitmasks[0] = lpcmShared->bitmasks[0];
  2623. pDestBitmasks[1] = lpcmShared->bitmasks[1];
  2624. pDestBitmasks[2] = lpcmShared->bitmasks[2];
  2625. CM_SHM_STOP_READING;
  2626. }
  2627. else
  2628. {
  2629. TRACE_OUT(( "24bpp cursor: no bitmasks"));
  2630. }
  2631. }
  2632. else
  2633. {
  2634. TRACE_OUT(( "Get palette %d", numColors));
  2635. lpcmShared = CM_SHM_START_READING;
  2636. //
  2637. // Flip the palette - its RGB in the kernel, and needs to be BGR
  2638. // here.
  2639. //
  2640. for (ii = 0; ii < numColors; ii++)
  2641. {
  2642. srcbmi.bmiColors[ii].rgbRed = lpcmShared->colorTable[ii].peRed;
  2643. srcbmi.bmiColors[ii].rgbGreen = lpcmShared->colorTable[ii].peGreen;
  2644. srcbmi.bmiColors[ii].rgbBlue = lpcmShared->colorTable[ii].peBlue;
  2645. }
  2646. CM_SHM_STOP_READING;
  2647. }
  2648. //
  2649. // Create source bitmap and write in the bitmap bits.
  2650. //
  2651. hbmp = CreateDIBSection(hdcTmp,
  2652. (BITMAPINFO *)&srcbmi,
  2653. DIB_RGB_COLORS,
  2654. &pBmBits,
  2655. NULL,
  2656. 0);
  2657. if (hbmp == NULL)
  2658. {
  2659. ERROR_OUT(( "Failed to create bitmap"));
  2660. DC_QUIT;
  2661. }
  2662. TRACE_OUT(( "Copy %d bytes of data into bitmap 0x%08x",
  2663. cbXORBitmapSize, pBmBits));
  2664. memcpy(pBmBits, pCursor->Masks + cbANDMaskSize, cbXORBitmapSize);
  2665. //
  2666. // Set up the structure required by GetDIBits - 24bpp. Set the height
  2667. // -ve to allow for top-down ordering of the bitmap.
  2668. //
  2669. m_pShare->USR_InitDIBitmapHeader((BITMAPINFOHEADER *)&bmi, 24);
  2670. bmi.bmiHeader.biWidth = pCursorHdr->cx;
  2671. bmi.bmiHeader.biHeight = -pCursorHdr->cy;
  2672. if (GetDIBits(hdcTmp,
  2673. hbmp,
  2674. 0,
  2675. pCursorHdr->cy,
  2676. pXORBitmap,
  2677. (LPBITMAPINFO)&bmi,
  2678. DIB_RGB_COLORS) == 0)
  2679. {
  2680. ERROR_OUT(( "GetDIBits failed hdc(%x) hbmp(%x) cy(%d)",
  2681. (TSHR_UINT16)hdcTmp,
  2682. (TSHR_UINT16)hbmp,
  2683. pCursorHdr->cy ));
  2684. DC_QUIT;
  2685. }
  2686. *pcbANDMask = (TSHR_UINT16) CURSOR_AND_MASK_SIZE(pCursor);
  2687. *pcbXORBitmap = (TSHR_UINT16) CURSOR_DIB_BITS_SIZE(pCursor->hdr.cx,
  2688. pCursor->hdr.cy,
  2689. 24);
  2690. //
  2691. // Return success.
  2692. //
  2693. rc = TRUE;
  2694. DC_EXIT_POINT:
  2695. //
  2696. // Clean up before exit.
  2697. //
  2698. if (hdcTmp)
  2699. {
  2700. DeleteDC(hdcTmp);
  2701. }
  2702. if (hbmp != NULL)
  2703. {
  2704. DeleteBitmap(hbmp);
  2705. }
  2706. DebugExitBOOL(ASHost::CMGetColorCursorDetails, rc);
  2707. return(rc);
  2708. }
  2709. //
  2710. // FUNCTION: CMGetMonoCursorDetails
  2711. //
  2712. // DESCRIPTION:
  2713. //
  2714. // Returns details of a cursor at 1bpp, given a DCCURSORSHAPE structure.
  2715. //
  2716. // PARAMETERS:
  2717. //
  2718. // pCursor - pointer to a DCCURSORSHAPE structure from which this function
  2719. // extracts the details
  2720. //
  2721. // pcxWidth - pointer to a TSHR_UINT16 variable that receives the cursor width
  2722. // in pixels
  2723. //
  2724. // pcyHeight - pointer to a TSHR_UINT16 variable that receives the cursor
  2725. // height in pixels
  2726. //
  2727. // pxHotSpot - pointer to a TSHR_UINT16 variable that receives the cursor
  2728. // hotspot x coordinate
  2729. //
  2730. // pyHotSpot - pointer to a TSHR_UINT16 variable that receives the cursor
  2731. // hotspot y coordinate
  2732. //
  2733. // pANDMask - pointer to a buffer that receives the cursor AND mask
  2734. //
  2735. // pcbANDMask - pointer to a TSHR_UINT16 variable that receives the size in
  2736. // bytes of the cursor AND mask
  2737. //
  2738. // pXORBitmap - pointer to a buffer that receives the cursor XOR bitmap at
  2739. // 1bpp
  2740. //
  2741. // pcbXORBitmap - pointer to a TSHR_UINT16 variable that receives the size in
  2742. // bytes of the cursor XOR bitmap
  2743. //
  2744. //
  2745. BOOL CMGetMonoCursorDetails(LPCM_SHAPE pCursor,
  2746. LPTSHR_UINT16 pcxWidth,
  2747. LPTSHR_UINT16 pcyHeight,
  2748. LPTSHR_UINT16 pxHotSpot,
  2749. LPTSHR_UINT16 pyHotSpot,
  2750. LPBYTE pANDMask,
  2751. LPTSHR_UINT16 pcbANDMask,
  2752. LPBYTE pXORBitmap,
  2753. LPTSHR_UINT16 pcbXORBitmap)
  2754. {
  2755. BOOL rc = FALSE;
  2756. LPCM_SHAPE_HEADER pCursorHdr;
  2757. UINT x;
  2758. UINT y;
  2759. LPBYTE pSrcRow;
  2760. UINT cbDstRowWidth;
  2761. LPBYTE pDstData;
  2762. UINT cbSrcANDMaskSize;
  2763. LPBYTE pSrcXORMask;
  2764. PFNCMCOPYTOMONO pfnCopyToMono;
  2765. DebugEntry(CMGetMonoCursor);
  2766. pCursorHdr = &(pCursor->hdr);
  2767. TRACE_OUT(( "cx(%u) cy(%u) cbWidth %d planes(%u) bpp(%u)",
  2768. pCursorHdr->cx,
  2769. pCursorHdr->cy,
  2770. pCursorHdr->cbRowWidth,
  2771. pCursorHdr->cPlanes,
  2772. pCursorHdr->cBitsPerPel ));
  2773. //
  2774. // Copy the cursor size and hotspot coords.
  2775. //
  2776. *pcxWidth = pCursorHdr->cx;
  2777. *pcyHeight = pCursorHdr->cy;
  2778. *pxHotSpot = (TSHR_UINT16)pCursorHdr->ptHotSpot.x;
  2779. *pyHotSpot = (TSHR_UINT16)pCursorHdr->ptHotSpot.y;
  2780. //
  2781. // Copy the AND mask - this is always mono...
  2782. // The rows are padded to word (16-bit) boundaries.
  2783. //
  2784. pDstData = pANDMask;
  2785. pSrcRow = pCursor->Masks;
  2786. cbDstRowWidth = ((pCursorHdr->cx + 15)/16) * 2;
  2787. for (y = 0; y < pCursorHdr->cy; y++)
  2788. {
  2789. for (x = 0; x < cbDstRowWidth; x++)
  2790. {
  2791. if (x < pCursorHdr->cbRowWidth)
  2792. {
  2793. //
  2794. // Copy data from the cursor definition.
  2795. //
  2796. *pDstData++ = pSrcRow[x];
  2797. }
  2798. else
  2799. {
  2800. //
  2801. // Padding required.
  2802. //
  2803. *pDstData++ = 0xFF;
  2804. }
  2805. }
  2806. pSrcRow += pCursorHdr->cbRowWidth;
  2807. }
  2808. //
  2809. // Copy the XOR mask - this may be color. We convert to mono by:
  2810. //
  2811. // - turning all zero values into a binary 0
  2812. // - turning all non-zero value into a binary 1
  2813. //
  2814. //
  2815. switch (pCursorHdr->cBitsPerPel)
  2816. {
  2817. case 1:
  2818. TRACE_OUT(( "1bpp"));
  2819. pfnCopyToMono = CMCopy1bppTo1bpp;
  2820. break;
  2821. case 4:
  2822. TRACE_OUT(( "4bpp"));
  2823. pfnCopyToMono = CMCopy4bppTo1bpp;
  2824. break;
  2825. case 8:
  2826. TRACE_OUT(( "8bpp"));
  2827. pfnCopyToMono = CMCopy8bppTo1bpp;
  2828. break;
  2829. case 16:
  2830. TRACE_OUT(( "16bpp"));
  2831. pfnCopyToMono = CMCopy16bppTo1bpp;
  2832. break;
  2833. case 24:
  2834. TRACE_OUT(( "24bpp"));
  2835. pfnCopyToMono = CMCopy24bppTo1bpp;
  2836. break;
  2837. default:
  2838. ERROR_OUT(( "Unexpected bpp: %d", pCursorHdr->cBitsPerPel));
  2839. DC_QUIT;
  2840. }
  2841. cbSrcANDMaskSize = pCursorHdr->cbRowWidth * pCursorHdr->cy;
  2842. pSrcXORMask = pCursor->Masks + cbSrcANDMaskSize;
  2843. (*pfnCopyToMono)( pSrcXORMask,
  2844. pXORBitmap,
  2845. pCursorHdr->cx,
  2846. pCursorHdr->cy );
  2847. *pcbANDMask = (TSHR_UINT16) (cbDstRowWidth * pCursorHdr->cy);
  2848. *pcbXORBitmap = (TSHR_UINT16) *pcbANDMask;
  2849. //
  2850. // Return success.
  2851. //
  2852. rc = TRUE;
  2853. DC_EXIT_POINT:
  2854. DebugExitDWORD(CMGetMonoCursor, rc);
  2855. return(rc);
  2856. }
  2857. //
  2858. // FUNCTION: CMSetCursorTransform
  2859. //
  2860. // DESCRIPTION:
  2861. //
  2862. // This function is responsible for setting cursor transforms.
  2863. //
  2864. // PARAMETERS:
  2865. //
  2866. // cWidth - the width in pels of the AND mask and the XOR DIB
  2867. // cHeight - the height in pels of the AND mask and the XOR DIB
  2868. // pOrigANDMask - a pointer to the bits of a WORD padded AND mask (the
  2869. // bits are top-down)
  2870. // pOrigXORDIB - a pointer to a DIB of the size given by cWidth and
  2871. // cHeight.
  2872. //
  2873. //
  2874. BOOL ASHost::CMSetCursorTransform
  2875. (
  2876. LPBYTE pOrigANDMask,
  2877. LPBITMAPINFO pOrigXORDIB
  2878. )
  2879. {
  2880. BOOL rc = FALSE;
  2881. LPBYTE pBits = NULL;
  2882. UINT cbSize;
  2883. CM_DRV_XFORM_INFO drvXformInfo;
  2884. UINT srcRowLength;
  2885. DebugEntry(ASHost::CMSetCursorTransform);
  2886. //
  2887. // The transform should be monochrome
  2888. //
  2889. ASSERT(pOrigXORDIB->bmiHeader.biBitCount == 1);
  2890. //
  2891. // For mono tags, create a single 1bpp DIB with AND followed by XOR
  2892. // data. Since both the AND mask and the XOR bitmap are word
  2893. // aligned we need to know the word aligned row length for
  2894. // allocating memory.
  2895. //
  2896. //
  2897. // Calculate the source and destination row lengths (in bytes).
  2898. //
  2899. srcRowLength = ((m_pShare->m_cmCursorWidth + 15)/16) * 2;
  2900. cbSize = srcRowLength * m_pShare->m_cmCursorHeight;
  2901. pBits = new BYTE[cbSize * 2];
  2902. if (!pBits)
  2903. {
  2904. ERROR_OUT(( "Alloc %lu bytes failed", cbSize * 2));
  2905. DC_QUIT;
  2906. }
  2907. //
  2908. // Copy the packed 1bpp AND and XOR bits to the buffer
  2909. //
  2910. TRACE_OUT(( "Copy %d bytes from 0x%08x", cbSize, pOrigANDMask));
  2911. //
  2912. // Copy the AND and XOR 1bpp masks.
  2913. //
  2914. memcpy(pBits, pOrigANDMask, cbSize);
  2915. memcpy(pBits + cbSize, POINTER_TO_DIB_BITS(pOrigXORDIB), cbSize);
  2916. //
  2917. // Call the display driver to set the pointer transform.
  2918. //
  2919. drvXformInfo.width = m_pShare->m_cmCursorWidth;
  2920. drvXformInfo.height = m_pShare->m_cmCursorHeight;
  2921. drvXformInfo.pANDMask = pBits;
  2922. drvXformInfo.result = FALSE;
  2923. if (!OSI_FunctionRequest(CM_ESC_XFORM, (LPOSI_ESCAPE_HEADER)&drvXformInfo,
  2924. sizeof(drvXformInfo)) ||
  2925. !drvXformInfo.result)
  2926. {
  2927. ERROR_OUT(("CM_ESC_XFORM failed"));
  2928. DC_QUIT;
  2929. }
  2930. //
  2931. // Set flag inidicating that transform is applied.
  2932. //
  2933. m_cmfCursorTransformApplied = TRUE;
  2934. rc = TRUE;
  2935. DC_EXIT_POINT:
  2936. //
  2937. // Release allocated memory, bitmaps, DCs.
  2938. //
  2939. if (pBits)
  2940. {
  2941. delete[] pBits;
  2942. }
  2943. DebugExitBOOL(ASHost::CMSetCursorTransform, rc);
  2944. return(rc);
  2945. }
  2946. //
  2947. // FUNCTION: CMRemoveCursorTransform
  2948. //
  2949. // DESCRIPTION:
  2950. // This function is responsible for removing cursor transforms.
  2951. //
  2952. // PARAMETERS: None.
  2953. //
  2954. void ASHost::CMRemoveCursorTransform(void)
  2955. {
  2956. DebugEntry(ASHost::CMRemoveCursorTransform);
  2957. //
  2958. // Check to see if there is currently a transform applied.
  2959. //
  2960. if (m_cmfCursorTransformApplied)
  2961. {
  2962. CM_DRV_XFORM_INFO drvXformInfo;
  2963. //
  2964. // Call down to the display driver to remove the pointer tag.
  2965. //
  2966. drvXformInfo.pANDMask = NULL;
  2967. drvXformInfo.result = FALSE;
  2968. OSI_FunctionRequest(CM_ESC_XFORM, (LPOSI_ESCAPE_HEADER)&drvXformInfo,
  2969. sizeof(drvXformInfo));
  2970. m_cmfCursorTransformApplied = FALSE;
  2971. }
  2972. DebugExitVOID(ASHost::CMRemoveCursorTransform);
  2973. }
  2974. //
  2975. // FUNCTION: CMProcessCursorIDPacket
  2976. //
  2977. // DESCRIPTION:
  2978. //
  2979. // Processes a received cursor ID packet.
  2980. //
  2981. // PARAMETERS:
  2982. //
  2983. // pCMPacket - pointer to the received cursor ID packet
  2984. //
  2985. // phNewCursor - pointer to a HCURSOR variable that receives the handle
  2986. // of a cursor that corresponds to the received packet
  2987. //
  2988. // pNewHotSpot - pointer to a POINT variable that receives the hot-spot
  2989. // of the new cursor
  2990. //
  2991. // RETURNS: Nothing
  2992. //
  2993. //
  2994. void ASShare::CMProcessCursorIDPacket
  2995. (
  2996. PCMPACKETID pCMPacket,
  2997. HCURSOR* phNewCursor,
  2998. LPPOINT pNewHotSpot
  2999. )
  3000. {
  3001. DebugEntry(ASShare::CMProcessCursorIDPacket);
  3002. //
  3003. // We only support NULL and ARROW
  3004. //
  3005. //
  3006. // If the IDC is not NULL then load the cursor.
  3007. //
  3008. if (pCMPacket->idc != CM_IDC_NULL)
  3009. {
  3010. if (pCMPacket->idc != CM_IDC_ARROW)
  3011. {
  3012. WARNING_OUT(("ProcessCursorIDPacket: unrecognized ID, using arrow"));
  3013. }
  3014. *phNewCursor = m_cmArrowCursor;
  3015. *pNewHotSpot = m_cmArrowCursorHotSpot;
  3016. }
  3017. else
  3018. {
  3019. // NULL is used for hidden cursors
  3020. *phNewCursor = NULL;
  3021. pNewHotSpot->x = 0;
  3022. pNewHotSpot->y = 0;
  3023. }
  3024. DebugExitVOID(ASShare::CMProcessCursorIDPacket);
  3025. }
  3026. //
  3027. // CM_Controlled()
  3028. //
  3029. // Called when we start/stop being controlled.
  3030. //
  3031. extern CURTAGINFO g_cti;
  3032. void ASHost::CM_Controlled(ASPerson * pasController)
  3033. {
  3034. char szAbbreviatedName[128];
  3035. DebugEntry(ASHost::CM_Controlled);
  3036. //
  3037. // If we are not being controlled, turn off the cursor tag. Note that
  3038. // being detached means we aren't controlled.
  3039. //
  3040. if (!pasController)
  3041. {
  3042. // We're not being controlled by a remote. No cursor xform
  3043. CMRemoveCursorTransform();
  3044. }
  3045. else
  3046. {
  3047. BOOL fAbbreviated = CMCreateAbbreviatedName(pasController->scName,
  3048. szAbbreviatedName, sizeof(szAbbreviatedName));
  3049. if ( !fAbbreviated )
  3050. {
  3051. lstrcpyn(szAbbreviatedName, pasController->scName,
  3052. ARRAY_ELEMENTS(szAbbreviatedName));
  3053. }
  3054. if (!CMGetCursorTagInfo(szAbbreviatedName))
  3055. {
  3056. ERROR_OUT(("GetCurTagInfo failed, not setting cursor tag"));
  3057. }
  3058. else
  3059. {
  3060. CMSetCursorTransform(&g_cti.aAndBits[0], &g_cti.bmInfo);
  3061. }
  3062. }
  3063. DebugExitVOID(ASHost::CM_Controlled);
  3064. }
  3065. // This initializes our single, volatile data for
  3066. // creating cursor tags.
  3067. CURTAGINFO g_cti = {
  3068. 32, // height of masks
  3069. 32, // width of masks
  3070. // bits describing the AND mask, this is a 12x24 rectangle in lower right
  3071. // if the tag size is changed, the mask will have to be edited, the
  3072. // following helps draw attention to this
  3073. #if ( TAGXOFF != 8 || TAGYOFF != 20 || TAGXSIZ != 24 || TAGYSIZ != 12 )
  3074. #error "Bitmap mask may be incorrect"
  3075. #endif
  3076. { 0xff, 0xff, 0xff, 0xff, // line 1
  3077. 0xff, 0xff, 0xff, 0xff, // line 2
  3078. 0xff, 0xff, 0xff, 0xff, // line 3
  3079. 0xff, 0xff, 0xff, 0xff, // line 4
  3080. 0xff, 0xff, 0xff, 0xff, // line 5
  3081. 0xff, 0xff, 0xff, 0xff, // line 6
  3082. 0xff, 0xff, 0xff, 0xff, // line 7
  3083. 0xff, 0xff, 0xff, 0xff, // line 8
  3084. 0xff, 0xff, 0xff, 0xff, // line 9
  3085. 0xff, 0xff, 0xff, 0xff, // line 10
  3086. 0xff, 0xff, 0xff, 0xff, // line 11
  3087. 0xff, 0xff, 0xff, 0xff, // line 12
  3088. 0xff, 0xff, 0xff, 0xff, // line 13
  3089. 0xff, 0xff, 0xff, 0xff, // line 14
  3090. 0xff, 0xff, 0xff, 0xff, // line 15
  3091. 0xff, 0xff, 0xff, 0xff, // line 16
  3092. 0xff, 0xff, 0xff, 0xff, // line 17
  3093. 0xff, 0xff, 0xff, 0xff, // line 18
  3094. 0xff, 0xff, 0xff, 0xff, // line 19
  3095. 0xff, 0xff, 0xff, 0xff, // line 20
  3096. 0xff, 0x00, 0x00, 0x00, // line 21
  3097. 0xff, 0x00, 0x00, 0x00, // line 22
  3098. 0xff, 0x00, 0x00, 0x00, // line 23
  3099. 0xff, 0x00, 0x00, 0x00, // line 24
  3100. 0xff, 0x00, 0x00, 0x00, // line 25
  3101. 0xff, 0x00, 0x00, 0x00, // line 26
  3102. 0xff, 0x00, 0x00, 0x00, // line 27
  3103. 0xff, 0x00, 0x00, 0x00, // line 28
  3104. 0xff, 0x00, 0x00, 0x00, // line 29
  3105. 0xff, 0x00, 0x00, 0x00, // line 30
  3106. 0xff, 0x00, 0x00, 0x00, // line 31
  3107. 0xff, 0x00, 0x00, 0x00 // line 32
  3108. },
  3109. // Initialize the BITMAPINFO structure:
  3110. {
  3111. // Initialize the BITMAPINFOHEADER structure:
  3112. {
  3113. sizeof(BITMAPINFOHEADER),
  3114. 32, // width
  3115. -32, // height (top down bitmap)
  3116. 1, // planes
  3117. 1, // bits per pixel
  3118. BI_RGB, // compression format (none)
  3119. 0, // not used for uncompressed bitmaps
  3120. 0, // xpels per meter, not set
  3121. 0, // ypels per meter, not set
  3122. 0, // biClrsUsed, indicates 2 color entries follow this struct
  3123. 0 // biClrsImportant (all)
  3124. },
  3125. // Initialize the foreground color (part of BITMAPINFO struct)
  3126. // This is BLACK
  3127. { 0x0, 0x0, 0x0, 0x0 },
  3128. },
  3129. // Initialize the background color (part of single RGBQUAD struct following
  3130. // BITMAPINFO STRUCTURE
  3131. { 0xff, 0xff, 0xff, 0x00 },
  3132. // Because this is a packed bitmap, the bitmap bits follow:
  3133. // These will be written into dynamically to create the tag
  3134. { 0, }
  3135. };
  3136. //
  3137. // This function isn't DBCS safe, so we don't abbreviate in
  3138. // DBCS character sets
  3139. //
  3140. BOOL ASShare::CMCreateAbbreviatedName
  3141. (
  3142. LPCSTR szTagName,
  3143. LPSTR szBuf,
  3144. UINT cbBuf
  3145. )
  3146. {
  3147. BOOL rc = FALSE;
  3148. DebugEntry(ASShare::CMCreateAbbreviatedName);
  3149. if (GetSystemMetrics(SM_DBCSENABLED))
  3150. {
  3151. TRACE_OUT(("Do not attempt to abbreviate on DBCS system"));
  3152. DC_QUIT;
  3153. }
  3154. // We will try to create initials first
  3155. LPSTR p;
  3156. if ( NULL != (p = (LPSTR) _StrChr ( szTagName, ' ' )))
  3157. {
  3158. // Enough room for initials?
  3159. if (cbBuf < NTRUNCLETTERS)
  3160. {
  3161. TRACE_OUT(("CMCreateAbbreviatedName: not enough room for initials"));
  3162. DC_QUIT;
  3163. }
  3164. char * q = szBuf;
  3165. *q++ = *szTagName;
  3166. *q++ = '.';
  3167. *q++ = *(p+1);
  3168. *q++ = '.';
  3169. *q = '\0';
  3170. CharUpper ( q );
  3171. rc = TRUE;
  3172. }
  3173. DC_EXIT_POINT:
  3174. DebugExitBOOL(ASShare::CMCreateAbbreviatedName, rc);
  3175. return(rc);
  3176. }
  3177. // This function will create the appropriate data in the
  3178. // volatile global and return a pointer to it.
  3179. BOOL ASHost::CMGetCursorTagInfo(LPCSTR szTagName)
  3180. {
  3181. HDC hdc = NULL;
  3182. HDC hdcScratch = NULL;
  3183. HBITMAP hBmpOld = NULL;
  3184. HBITMAP hBitmap = NULL;
  3185. PCURTAGINFO pctiRet = NULL;
  3186. RECT rect;
  3187. HFONT hOldFont;
  3188. BOOL rc = FALSE;
  3189. DebugEntry(ASHost::CMGetCursorTagInfo);
  3190. hdcScratch = CreateCompatibleDC(NULL);
  3191. if (!hdcScratch)
  3192. {
  3193. ERROR_OUT(("CMGetCursorTagInfo: couldn't get scratch DC"));
  3194. DC_QUIT;
  3195. }
  3196. hBitmap = CreateDIBitmap(hdcScratch,
  3197. &(g_cti.bmInfo.bmiHeader),
  3198. 0, // don't initialize bits
  3199. NULL, // don't initialize bits
  3200. &(g_cti.bmInfo),
  3201. DIB_RGB_COLORS );
  3202. if (!hBitmap)
  3203. {
  3204. ERROR_OUT(("CMGetCursorTagInfo: failed to create bitmap"));
  3205. DC_QUIT;
  3206. }
  3207. hBmpOld = SelectBitmap(hdcScratch, hBitmap);
  3208. hOldFont = SelectFont(hdcScratch, m_pShare->m_cmCursorTagFont);
  3209. // Create the tag background...
  3210. PatBlt ( hdcScratch, 0, 0, 32, 32, BLACKNESS );
  3211. PatBlt ( hdcScratch, TAGXOFF, TAGYOFF, TAGXSIZ, TAGYSIZ, WHITENESS );
  3212. // Now see how many characters of the name or abbreviation
  3213. // we can fit into the tag
  3214. int cCharsFit;
  3215. SIZE size;
  3216. LPSTR p;
  3217. // First assume the whole thing fits
  3218. cCharsFit = lstrlen(szTagName);
  3219. // Now try to find out how big a part actually fits
  3220. rect.left = rect.top = rect.right = rect.bottom = 0;
  3221. for ( p = CharNext(szTagName); ; p = CharNext(p) )
  3222. {
  3223. if ( DrawText(hdcScratch, szTagName, (int)(p - szTagName), &rect,
  3224. DT_CALCRECT | DT_SINGLELINE | DT_NOPREFIX ) )
  3225. {
  3226. if ( rect.right > TAGXSIZ )
  3227. {
  3228. // This number of characters no longer fits into the
  3229. // tag. Take the next smaller number and leave the loop
  3230. cCharsFit = (int)(CharPrev(szTagName, p) - szTagName);
  3231. break;
  3232. }
  3233. }
  3234. if ( NULL == *p )
  3235. break;
  3236. }
  3237. TRACE_OUT(("Tag: [%s], showing %d chars", szTagName, cCharsFit ));
  3238. // Now draw the text...
  3239. // DrawText doesn't return a documented error...
  3240. rect.top = TAGYOFF;
  3241. rect.left = TAGXOFF;
  3242. rect.bottom = TAGYOFF + TAGYSIZ;
  3243. rect.right = TAGXOFF + TAGXSIZ;
  3244. DrawText ( hdcScratch, szTagName, cCharsFit, &rect,
  3245. DT_CENTER | DT_SINGLELINE | DT_NOPREFIX );
  3246. SelectFont (hdcScratch, hOldFont);
  3247. // Now get the bitmap bits into the global volatile data area
  3248. // Make sure the number of scan lines requested is returned
  3249. if ( 32 != GetDIBits ( hdcScratch,
  3250. hBitmap,
  3251. 0,
  3252. 32,
  3253. g_cti.aXorBits,
  3254. &(g_cti.bmInfo),
  3255. DIB_RGB_COLORS ))
  3256. {
  3257. ERROR_OUT(("CMGetCursorTagInfo: GetDIBits failed"));
  3258. DC_QUIT;
  3259. }
  3260. // Reset the foreground and background colors to black
  3261. // and white respectively no matter what GetDIBits has filled in.
  3262. // REVIEW: how do we get GetDIBits to fill in the expected (B&W) color
  3263. // table?
  3264. g_cti.bmInfo.bmiColors[0].rgbBlue = 0x0;
  3265. g_cti.bmInfo.bmiColors[0].rgbGreen = 0x0;
  3266. g_cti.bmInfo.bmiColors[0].rgbRed = 0x0;
  3267. g_cti.bmInfo.bmiColors[0].rgbReserved = 0;
  3268. g_cti.rgbBackground[0].rgbBlue = 0xff;
  3269. g_cti.rgbBackground[0].rgbGreen = 0xff;
  3270. g_cti.rgbBackground[0].rgbRed = 0xff;
  3271. g_cti.rgbBackground[0].rgbReserved = 0;
  3272. // Finally, we are happy
  3273. rc = TRUE;
  3274. DC_EXIT_POINT:
  3275. // Perform necessary cleanup
  3276. if (hBmpOld)
  3277. SelectBitmap ( hdcScratch, hBmpOld);
  3278. if ( hBitmap )
  3279. DeleteBitmap ( hBitmap );
  3280. if ( hdcScratch )
  3281. DeleteDC ( hdcScratch );
  3282. DebugExitBOOL(ASHost::CMGetCursorTagInfo, rc);
  3283. return(rc);
  3284. }