Source code of Windows XP (NT5)
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.

952 lines
24 KiB

  1. #include "precomp.h"
  2. //
  3. // USR.CPP
  4. // Update Sender/Receiver
  5. //
  6. // Copyright(c) Microsoft 1997-
  7. //
  8. #define MLZ_FILE_ZONE ZONE_NET
  9. //
  10. // USR strategy when network packets cannot be allocated.
  11. //
  12. // The USR sends three different types of packets:
  13. //
  14. // - font negotiation packets
  15. // - order packets
  16. // - screen data packets
  17. //
  18. // Font negotiation packets are sent by the USR_Periodic function. If the
  19. // packet cannot be sent first time then the USR will retry (on each call
  20. // to the USR_Periodic function) until it has succesfully sent the packet.
  21. // The only dependency on font packets is that until the systems in a share
  22. // have been able to exchange font negotiation packets they will not be
  23. // able to send text output as orders - they will simply send text as
  24. // screen data.
  25. //
  26. // The USR function UP_SendUpdates sends all update packets (both order
  27. // packets and screen data packets). Order packets must be sent first and
  28. // screen data packets are only sent if all the orders have been
  29. // succesfully sent. When sending screen data packets they are only sent
  30. // if the corresponding palette packets have been sent - otherwise they are
  31. // re-absorbed into the screen data to be transmitted later.
  32. //
  33. //
  34. //
  35. // USR_ShareStarting()
  36. // Creates share resources
  37. //
  38. BOOL ASShare::USR_ShareStarting(void)
  39. {
  40. BOOL rc = FALSE;
  41. BITMAPINFOHEADER bitmapInfo;
  42. HDC hdcDesktop = NULL;
  43. DebugEntry(ASShare::USR_ShareStarting);
  44. //
  45. // Set the black bitmap data and hatch bitmap data flags which can be
  46. // used as an aid for debugging. These are false unless there is an
  47. // entry in the ini file to override them.
  48. //
  49. COM_ReadProfInt(DBG_INI_SECTION_NAME, USR_INI_HATCHSCREENDATA, FALSE,
  50. &m_usrHatchScreenData);
  51. COM_ReadProfInt(DBG_INI_SECTION_NAME, USR_INI_HATCHBMPORDERS, FALSE,
  52. &m_usrHatchBitmaps);
  53. //
  54. // Double-check the order packet sizes are OK
  55. //
  56. ASSERT(SMALL_ORDER_PACKET_SIZE < LARGE_ORDER_PACKET_SIZE);
  57. ASSERT(LARGE_ORDER_PACKET_SIZE <= TSHR_MAX_SEND_PKT);
  58. //
  59. // Allocate a chunk of memory big enough to contain the largest packet
  60. // an application can receive from the network. This is required to
  61. // store uncompressed bitmaps and repeated general use by the USR.
  62. //
  63. m_usrPBitmapBuffer = new BYTE[TSHR_MAX_SEND_PKT];
  64. if (!m_usrPBitmapBuffer)
  65. {
  66. ERROR_OUT(("USR_ShareStarted: failed to alloc memory m_usrPBitmapBuffer"));
  67. //
  68. // To continue the share would cause a GP fault as soon as anything
  69. // tries to use this buffer so delete this person from the share.
  70. // The reason is lack of resources.
  71. //
  72. DC_QUIT;
  73. }
  74. //
  75. // Create the transfer bitmaps for screen data and bitmap orders
  76. //
  77. USR_InitDIBitmapHeader(&bitmapInfo, g_usrScreenBPP);
  78. //
  79. // Create the transfer bitmaps. These are used for both outgoing and
  80. // incoming data.
  81. //
  82. // To avoid having to recreate the bitmaps whenever the parties in the
  83. // share change, (and hence the various bpp may change) from r2.0 we
  84. // now use a fixed vertical size and if necessary can handle incoming
  85. // bitmaps in multiple bands.
  86. //
  87. // These are the resulting heights for 256 pixel wide segments.
  88. //
  89. // TSHR_MAX_SEND_PKT - sizeof(DATAPACKETHEADER) / bytes per scan line
  90. //
  91. // 4bpp --> (32000 - 4) / 128 = 249
  92. // 8bpp --> (32000 - 4) / 256 = 124
  93. // 24bpp --> (32000 - 4) / 768 = 41
  94. //
  95. //
  96. //
  97. // NOTE:
  98. // The VGA driver has a problem when the bitmap ends exactly on a 4K
  99. // (page) boundary. So we create the bitmaps one pixel taller.
  100. //
  101. // BOGUS BUGBUG LAURABU
  102. // Is this really true anymore? If not, save some memory and make these
  103. // the right size.
  104. //
  105. hdcDesktop = GetDC(NULL);
  106. if (!hdcDesktop)
  107. {
  108. ERROR_OUT(("USR_ShareStarting: can't get screen DC"));
  109. DC_QUIT;
  110. }
  111. // The large bitmap is short. The rest are medium height.
  112. bitmapInfo.biWidth = 1024;
  113. bitmapInfo.biHeight = MaxBitmapHeight(MEGA_WIDE_X_SIZE, 8) + 1;
  114. m_usrBmp1024 = CreateDIBitmap(hdcDesktop, &bitmapInfo, 0, NULL, NULL,
  115. DIB_RGB_COLORS);
  116. if (!m_usrBmp1024)
  117. {
  118. ERROR_OUT(("USR_ShareStarting: failed to reate m_usrBmp1024"));
  119. DC_QUIT;
  120. }
  121. bitmapInfo.biHeight = MaxBitmapHeight(MEGA_X_SIZE, 8) + 1;
  122. bitmapInfo.biWidth = 256;
  123. m_usrBmp256 = CreateDIBitmap(hdcDesktop, &bitmapInfo, 0, NULL, NULL,
  124. DIB_RGB_COLORS);
  125. if (!m_usrBmp256)
  126. {
  127. ERROR_OUT(("USR_ShareStarting: failed to create m_usrBmp256"));
  128. DC_QUIT;
  129. }
  130. bitmapInfo.biWidth = 128;
  131. m_usrBmp128 = CreateDIBitmap(hdcDesktop, &bitmapInfo, 0, NULL, NULL,
  132. DIB_RGB_COLORS);
  133. if (!m_usrBmp128)
  134. {
  135. ERROR_OUT(("USR_ShareStarting: failed to create m_usrBmp128"));
  136. DC_QUIT;
  137. }
  138. bitmapInfo.biWidth = 112;
  139. m_usrBmp112 = CreateDIBitmap(hdcDesktop, &bitmapInfo, 0, NULL, NULL,
  140. DIB_RGB_COLORS);
  141. if (!m_usrBmp112)
  142. {
  143. ERROR_OUT(("USR_ShareStarting: failed to create m_usrBmp112"));
  144. DC_QUIT;
  145. }
  146. bitmapInfo.biWidth = 96;
  147. m_usrBmp96 = CreateDIBitmap(hdcDesktop, &bitmapInfo, 0, NULL, NULL,
  148. DIB_RGB_COLORS);
  149. if (!m_usrBmp96)
  150. {
  151. ERROR_OUT(("USR_ShareStarting: failed to create m_usrBmp96"));
  152. DC_QUIT;
  153. }
  154. bitmapInfo.biWidth = 80;
  155. m_usrBmp80 = CreateDIBitmap(hdcDesktop, &bitmapInfo, 0, NULL, NULL,
  156. DIB_RGB_COLORS);
  157. if (!m_usrBmp80)
  158. {
  159. ERROR_OUT(("USR_ShareStarting: failed to create m_usrBmp80"));
  160. DC_QUIT;
  161. }
  162. bitmapInfo.biWidth = 64;
  163. m_usrBmp64 = CreateDIBitmap(hdcDesktop, &bitmapInfo, 0, NULL, NULL,
  164. DIB_RGB_COLORS);
  165. if (!m_usrBmp64)
  166. {
  167. ERROR_OUT(("USR_ShareStarting: failed to create m_usrBmp64"));
  168. DC_QUIT;
  169. }
  170. bitmapInfo.biWidth = 48;
  171. m_usrBmp48 = CreateDIBitmap(hdcDesktop, &bitmapInfo, 0, NULL, NULL,
  172. DIB_RGB_COLORS);
  173. if (!m_usrBmp48)
  174. {
  175. ERROR_OUT(("USR_ShareStarting: failed to create m_usrBmp48"));
  176. DC_QUIT;
  177. }
  178. bitmapInfo.biWidth = 32;
  179. m_usrBmp32 = CreateDIBitmap(hdcDesktop, &bitmapInfo, 0, NULL, NULL,
  180. DIB_RGB_COLORS);
  181. if (!m_usrBmp32)
  182. {
  183. ERROR_OUT(("USR_ShareStarting: failed to create m_usrBmp32"));
  184. DC_QUIT;
  185. }
  186. bitmapInfo.biWidth = 16;
  187. m_usrBmp16 = CreateDIBitmap(hdcDesktop, &bitmapInfo, 0, NULL, NULL,
  188. DIB_RGB_COLORS);
  189. if (!m_usrBmp16)
  190. {
  191. ERROR_OUT(("USR_ShareStarting: failed to create m_usrBmp16"));
  192. DC_QUIT;
  193. }
  194. rc = TRUE;
  195. DC_EXIT_POINT:
  196. if (hdcDesktop)
  197. {
  198. ReleaseDC(NULL, hdcDesktop);
  199. }
  200. DebugExitBOOL(ASShare::USR_ShareStarting, rc);
  201. return(rc);
  202. }
  203. //
  204. // USR_ShareEnded()
  205. // Cleans up share resources
  206. //
  207. void ASShare::USR_ShareEnded(void)
  208. {
  209. DebugEntry(ASShare::USR_ShareEnded);
  210. //
  211. // Delete Transfer Bitmaps.
  212. //
  213. if (m_usrBmp1024)
  214. {
  215. DeleteBitmap(m_usrBmp1024);
  216. m_usrBmp1024= NULL;
  217. }
  218. if (m_usrBmp256)
  219. {
  220. DeleteBitmap(m_usrBmp256);
  221. m_usrBmp256 = NULL;
  222. }
  223. if (m_usrBmp128)
  224. {
  225. DeleteBitmap(m_usrBmp128);
  226. m_usrBmp128 = NULL;
  227. }
  228. if (m_usrBmp112)
  229. {
  230. DeleteBitmap(m_usrBmp112);
  231. m_usrBmp112 = NULL;
  232. }
  233. if (m_usrBmp96)
  234. {
  235. DeleteBitmap(m_usrBmp96);
  236. m_usrBmp96 = NULL;
  237. }
  238. if (m_usrBmp80)
  239. {
  240. DeleteBitmap(m_usrBmp80);
  241. m_usrBmp80 = NULL;
  242. }
  243. if (m_usrBmp64)
  244. {
  245. DeleteBitmap(m_usrBmp64);
  246. m_usrBmp64 = NULL;
  247. }
  248. if (m_usrBmp48)
  249. {
  250. DeleteBitmap(m_usrBmp48);
  251. m_usrBmp48 = NULL;
  252. }
  253. if (m_usrBmp32)
  254. {
  255. DeleteBitmap(m_usrBmp32);
  256. m_usrBmp32 = NULL;
  257. }
  258. if (m_usrBmp16)
  259. {
  260. DeleteBitmap(m_usrBmp16);
  261. m_usrBmp16 = NULL;
  262. }
  263. //
  264. // Free Bitmap Buffer.
  265. //
  266. if (m_usrPBitmapBuffer != NULL)
  267. {
  268. delete[] m_usrPBitmapBuffer;
  269. m_usrPBitmapBuffer = NULL;
  270. }
  271. DebugExitVOID(ASShare::USR_ShareEnded);
  272. }
  273. //
  274. // USR_RecalcCaps()
  275. //
  276. // DESCRIPTION:
  277. //
  278. // Enumerates the bitmap capabilities of all parties currently in the
  279. // share, and determines the common capabilities.
  280. //
  281. // PARAMETERS: None.
  282. //
  283. // RETURNS: TRUE if there are good common caps, or false on failure (which
  284. // has the effect of rejecting a new party from joining the share).
  285. //
  286. //
  287. void ASShare::USR_RecalcCaps(BOOL fJoiner)
  288. {
  289. ASPerson * pasT;
  290. UINT capsMaxBPP;
  291. UINT capsMinBPP;
  292. UINT capsSupports4BPP;
  293. UINT capsSupports8BPP;
  294. UINT capsSupports24BPP;
  295. UINT capsOldBPP;
  296. DebugEntry(ASShare::USR_RecalcCaps);
  297. if (!m_pHost)
  298. {
  299. // Nothing to do
  300. DC_QUIT;
  301. }
  302. ValidatePerson(m_pasLocal);
  303. capsOldBPP = m_pHost->m_usrSendingBPP;
  304. //
  305. // Init the caps
  306. //
  307. capsSupports4BPP = m_pasLocal->cpcCaps.screen.capsSupports4BPP;
  308. capsSupports8BPP = m_pasLocal->cpcCaps.screen.capsSupports8BPP;
  309. capsSupports24BPP = m_pasLocal->cpcCaps.screen.capsSupports24BPP;
  310. capsMaxBPP = 0;
  311. capsMinBPP = 0xFFFFFFFF;
  312. for (pasT = m_pasLocal->pasNext; pasT != NULL; pasT = pasT->pasNext)
  313. {
  314. //
  315. // Check the bpps supported.
  316. //
  317. if (pasT->cpcCaps.screen.capsSupports4BPP != CAPS_SUPPORTED)
  318. {
  319. capsSupports4BPP = CAPS_UNSUPPORTED;
  320. }
  321. if (pasT->cpcCaps.screen.capsSupports8BPP != CAPS_SUPPORTED)
  322. {
  323. capsSupports8BPP = CAPS_UNSUPPORTED;
  324. }
  325. if (pasT->cpcCaps.screen.capsSupports24BPP != CAPS_SUPPORTED)
  326. {
  327. capsSupports24BPP = CAPS_UNSUPPORTED;
  328. }
  329. //
  330. // Set the combined bpp to the maximum so far found.
  331. // (If we send data at this bpp then one of the remote systems can
  332. // usefully process this number of colors).
  333. //
  334. capsMaxBPP = max(capsMaxBPP, pasT->cpcCaps.screen.capsBPP);
  335. capsMinBPP = min(capsMinBPP, pasT->cpcCaps.screen.capsBPP);
  336. }
  337. //
  338. // Now figure out what BPP we will transmit at.
  339. //
  340. //
  341. // Limit the combined caps bpp (which is currently the maximum bpp that
  342. // any system in the share wants) to the local bpp, since there is no
  343. // point sending at higher bpp than the local machine has.
  344. //
  345. capsMaxBPP = min(capsMaxBPP, g_usrScreenBPP);
  346. if (!capsMaxBPP)
  347. capsMaxBPP = g_usrScreenBPP;
  348. capsMinBPP = min(capsMinBPP, g_usrScreenBPP);
  349. //
  350. // m_usrSendingBPP is most often going to be 8. So it's easier to assume
  351. // it, then check for cases where it won't be.
  352. //
  353. m_pHost->m_usrSendingBPP = 8;
  354. if ((capsMaxBPP <= 4) && (capsSupports4BPP == CAPS_SUPPORTED))
  355. {
  356. m_pHost->m_usrSendingBPP = 4;
  357. }
  358. else if ((capsMinBPP >= 24) &&
  359. (g_asSettings & SHP_SETTING_TRUECOLOR) &&
  360. (capsSupports24BPP == CAPS_SUPPORTED))
  361. {
  362. m_pHost->m_usrSendingBPP = 24;
  363. }
  364. if (capsOldBPP != m_pHost->m_usrSendingBPP)
  365. {
  366. //
  367. // If switching to/from palettized, we need to update the
  368. // "need to send palette" flag. Note that 4bpp is also a
  369. // palettized color depth.
  370. //
  371. if ((capsOldBPP <= 8) && (m_pHost->m_usrSendingBPP > 8))
  372. m_pHost->m_pmMustSendPalette = FALSE;
  373. else if ((capsOldBPP > 8) && (m_pHost->m_usrSendingBPP <= 8))
  374. m_pHost->m_pmMustSendPalette = TRUE;
  375. #ifdef _DEBUG
  376. if (capsOldBPP == 24)
  377. {
  378. WARNING_OUT(("TRUE COLOR SHARING is now FINISHED"));
  379. }
  380. else if (m_pHost->m_usrSendingBPP == 24)
  381. {
  382. WARNING_OUT(("TRUE COLOR SHARING is now STARTING"));
  383. }
  384. #endif
  385. if (!fJoiner)
  386. {
  387. //
  388. // Sending BPP changed. Repaint all shared stuff.
  389. // NOTE:
  390. // We recalc the sendBPP at three points:
  391. // * When we start to share
  392. // * When a person joins
  393. // * When a person leaves
  394. //
  395. // In the first two cases, shared stuff is repainted,
  396. // so everybody gets the new sendBPP data. Only in the
  397. // leave case do we need to force this.
  398. //
  399. m_pHost->HET_RepaintAll();
  400. }
  401. }
  402. DC_EXIT_POINT:
  403. DebugExitVOID(ASShare::USR_RecalcCaps);
  404. }
  405. //
  406. // USR_HostStarting()
  407. //
  408. BOOL ASHost::USR_HostStarting(void)
  409. {
  410. BOOL rc = FALSE;
  411. HDC hdc;
  412. DebugEntry(ASHost::USR_HostStarting);
  413. //
  414. // Create scratch DC
  415. //
  416. hdc = GetDC(NULL);
  417. if (!hdc)
  418. {
  419. ERROR_OUT(("USR_HostStarting: can't get screen DC"));
  420. DC_QUIT;
  421. }
  422. m_usrWorkDC = CreateCompatibleDC(hdc);
  423. ReleaseDC(NULL, hdc);
  424. if (!m_usrWorkDC)
  425. {
  426. ERROR_OUT(("USR_HostStarting: can't create m_usrWorkDC"));
  427. DC_QUIT;
  428. }
  429. m_pShare->USR_RecalcCaps(TRUE);
  430. rc = TRUE;
  431. DC_EXIT_POINT:
  432. DebugExitBOOL(ASHost::USR_HostStarting, rc);
  433. return(rc);
  434. }
  435. //
  436. // USR_HostEnded()
  437. //
  438. void ASHost::USR_HostEnded(void)
  439. {
  440. DebugEntry(ASHost::USR_HostEnded);
  441. if (m_usrWorkDC != NULL)
  442. {
  443. DeleteDC(m_usrWorkDC);
  444. m_usrWorkDC = NULL;
  445. }
  446. DebugExitVOID(ASHost::USR_HostEnded);
  447. }
  448. //
  449. // USR_ScrollDesktop
  450. //
  451. void ASShare::USR_ScrollDesktop
  452. (
  453. ASPerson * pasPerson,
  454. int xNew,
  455. int yNew
  456. )
  457. {
  458. int xOld;
  459. int yOld;
  460. DebugEntry(ASShare::USR_ScrollDesktop);
  461. ValidateView(pasPerson);
  462. //
  463. // If the origin has changed then do the update.
  464. //
  465. xOld = pasPerson->m_pView->m_dsScreenOrigin.x;
  466. yOld = pasPerson->m_pView->m_dsScreenOrigin.y;
  467. if ((xOld != xNew) || (yOld != yNew))
  468. {
  469. pasPerson->m_pView->m_dsScreenOrigin.x = xNew;
  470. pasPerson->m_pView->m_dsScreenOrigin.y = yNew;
  471. //
  472. // We must ensure that data written to the ScreenBitmap is not
  473. // clipped
  474. //
  475. OD_ResetRectRegion(pasPerson);
  476. //
  477. // Offset the existing bitmap by the change in desktop origins.
  478. //
  479. BitBlt(pasPerson->m_pView->m_usrDC,
  480. 0,
  481. 0,
  482. pasPerson->cpcCaps.screen.capsScreenWidth,
  483. pasPerson->cpcCaps.screen.capsScreenHeight,
  484. pasPerson->m_pView->m_usrDC,
  485. xNew - xOld,
  486. yNew - yOld,
  487. SRCCOPY);
  488. //
  489. // Offset the shadow cursor pos -- same place on remote screen
  490. // but now different place in VD
  491. //
  492. pasPerson->cmPos.x += xNew - xOld;
  493. pasPerson->cmPos.y += yNew - yOld;
  494. //
  495. // Repaint the view
  496. //
  497. VIEW_InvalidateRgn(pasPerson, NULL);
  498. }
  499. DebugExitVOID(ASShare::USR_ScrollDesktop);
  500. }
  501. //
  502. // FUNCTION: USR_InitDIBitmapHeader
  503. //
  504. // DESCRIPTION:
  505. //
  506. // Initialises a Device Independent bitmap header to be the given bits per
  507. // pel.
  508. //
  509. // PARAMETERS:
  510. //
  511. // pbh - pointer to the bitmap header to be initialised.
  512. // bpp - bpp to be used for the bitmap
  513. //
  514. // RETURNS: VOID
  515. //
  516. //
  517. void ASShare::USR_InitDIBitmapHeader
  518. (
  519. BITMAPINFOHEADER * pbh,
  520. UINT bpp
  521. )
  522. {
  523. DebugEntry(ASShare::USR_InitDIBitmapHeader);
  524. pbh->biSize = sizeof(BITMAPINFOHEADER);
  525. pbh->biPlanes = 1;
  526. pbh->biBitCount = (WORD)bpp;
  527. pbh->biCompression = BI_RGB;
  528. pbh->biSizeImage = 0;
  529. pbh->biXPelsPerMeter = 10000;
  530. pbh->biYPelsPerMeter = 10000;
  531. pbh->biClrUsed = 0;
  532. pbh->biClrImportant = 0;
  533. DebugExitVOID(ASShare::USR_InitDIBitmapHeader);
  534. }
  535. //
  536. // USR_ViewStarting()
  537. //
  538. // Called when someone we're viewing starts to host. We create the desktop
  539. // bitmap for them plus scratch objects
  540. //
  541. BOOL ASShare::USR_ViewStarting(ASPerson * pasPerson)
  542. {
  543. BOOL rc;
  544. DebugEntry(ASShare::USR_ViewStarting);
  545. ValidateView(pasPerson);
  546. //
  547. // Create a bitmap for this new party
  548. //
  549. rc = USRCreateRemoteDesktop(pasPerson);
  550. DebugExitBOOL(ASShare::USR_ViewStarting, rc);
  551. return(rc);
  552. }
  553. //
  554. // FUNCTION: USRCreateRemoteDesktop
  555. //
  556. // DESCRIPTION:
  557. //
  558. // Creates the shadow bitmap for a remote party.
  559. //
  560. // PARAMETERS:
  561. //
  562. // personID - person to create the shadow bitmap for.
  563. //
  564. // RETURNS: TRUE if successful, FALSE otherwise.
  565. //
  566. //
  567. BOOL ASShare::USRCreateRemoteDesktop(ASPerson * pasPerson)
  568. {
  569. BOOL rc = FALSE;
  570. HDC hdcDesktop = NULL;
  571. RECT desktopRect;
  572. DebugEntry(ASShare::USRCreateRemoteDesktop);
  573. ValidateView(pasPerson);
  574. ASSERT(pasPerson->m_pView->m_usrDC == NULL);
  575. ASSERT(pasPerson->m_pView->m_usrBitmap == NULL);
  576. ASSERT(pasPerson->m_pView->m_usrOldBitmap == NULL);
  577. hdcDesktop = GetDC(NULL);
  578. //
  579. // Create the scratch DC
  580. //
  581. pasPerson->m_pView->m_usrWorkDC = CreateCompatibleDC(hdcDesktop);
  582. if (!pasPerson->m_pView->m_usrWorkDC)
  583. {
  584. ERROR_OUT(("Couldn't create workDC for person [%d]", pasPerson->mcsID));
  585. DC_QUIT;
  586. }
  587. //
  588. // Create the DC that keeps the screen bitmap for this party
  589. //
  590. pasPerson->m_pView->m_usrDC = CreateCompatibleDC(hdcDesktop);
  591. if (!pasPerson->m_pView->m_usrDC)
  592. {
  593. ERROR_OUT(("Couldn't create usrDC for person [%d]", pasPerson->mcsID));
  594. DC_QUIT;
  595. }
  596. //
  597. // We can't use this person's usrDC, since that currently has a MONO
  598. // bitmap selected into it.
  599. //
  600. pasPerson->m_pView->m_usrBitmap = CreateCompatibleBitmap(hdcDesktop, pasPerson->cpcCaps.screen.capsScreenWidth, pasPerson->cpcCaps.screen.capsScreenHeight);
  601. if (pasPerson->m_pView->m_usrBitmap == NULL)
  602. {
  603. ERROR_OUT(("Couldn't create screen bitmap for [%d]", pasPerson->mcsID));
  604. DC_QUIT;
  605. }
  606. //
  607. // Select the screen bitmap into the person's DC, and save the previous
  608. // 1x1 bitmap away, so we can deselect it when done.
  609. //
  610. pasPerson->m_pView->m_usrOldBitmap = SelectBitmap(pasPerson->m_pView->m_usrDC, pasPerson->m_pView->m_usrBitmap);
  611. //
  612. // Fill the Screen Bitmap with grey.
  613. //
  614. // In practice the Shadow Window Presenter(SWP) should never display
  615. // any area of the Screen Bitmap that has not been updated with data
  616. // from a remote system.
  617. //
  618. // Therefore this operation is just "insurance" in case the SWP goes
  619. // wrong and momentarily displays a non-updated area - a flash of grey
  620. // is better than a flash of garbage.
  621. //
  622. desktopRect.left = 0;
  623. desktopRect.top = 0;
  624. desktopRect.right = pasPerson->cpcCaps.screen.capsScreenWidth;
  625. desktopRect.bottom = pasPerson->cpcCaps.screen.capsScreenHeight;
  626. FillRect(pasPerson->m_pView->m_usrDC, &desktopRect, GetSysColorBrush(COLOR_APPWORKSPACE));
  627. rc = TRUE;
  628. DC_EXIT_POINT:
  629. if (hdcDesktop != NULL)
  630. {
  631. ReleaseDC(NULL, hdcDesktop);
  632. }
  633. DebugExitBOOL(ASShare::USRCreateRemoteDesktop, rc);
  634. return(rc);
  635. }
  636. //
  637. // USR_ViewEnded()
  638. //
  639. // Called when person we're viewing stops hosting. We get rid of their
  640. // desktop bitmap.
  641. //
  642. void ASShare::USR_ViewEnded(ASPerson * pasPerson)
  643. {
  644. ValidateView(pasPerson);
  645. //
  646. // Delete the desktop bitmap for the party that has left
  647. //
  648. USRDeleteRemoteDesktop(pasPerson);
  649. }
  650. //
  651. // FUNCTION: USRDeleteRemoteDesktop
  652. //
  653. // DESCRIPTION:
  654. //
  655. // Deletes a remote party's shadow bitmap.
  656. //
  657. // PARAMETERS:
  658. //
  659. // personID - party whose shadow bitmap is to be deleted.
  660. //
  661. // RETURNS: Nothing.
  662. //
  663. //
  664. void ASShare::USRDeleteRemoteDesktop(ASPerson * pasPerson)
  665. {
  666. DebugEntry(ASShare::USRDeleteRemoteDesktop);
  667. ValidateView(pasPerson);
  668. if (pasPerson->m_pView->m_usrOldBitmap != NULL)
  669. {
  670. // Deselect screen bitmap
  671. SelectBitmap(pasPerson->m_pView->m_usrDC, pasPerson->m_pView->m_usrOldBitmap);
  672. pasPerson->m_pView->m_usrOldBitmap = NULL;
  673. }
  674. if (pasPerson->m_pView->m_usrBitmap != NULL)
  675. {
  676. // Delete the screen bitmap
  677. DeleteBitmap(pasPerson->m_pView->m_usrBitmap);
  678. pasPerson->m_pView->m_usrBitmap = NULL;
  679. }
  680. if (pasPerson->m_pView->m_usrDC != NULL)
  681. {
  682. //
  683. // Delete the screen DC. Created objects should have
  684. // been selected out of it before now.
  685. //
  686. DeleteDC(pasPerson->m_pView->m_usrDC);
  687. pasPerson->m_pView->m_usrDC = NULL;
  688. }
  689. if (pasPerson->m_pView->m_usrWorkDC != NULL)
  690. {
  691. DeleteDC(pasPerson->m_pView->m_usrWorkDC);
  692. pasPerson->m_pView->m_usrWorkDC = NULL;
  693. }
  694. DebugExitVOID(ASShare::USRDeleteRemoteDesktop);
  695. }
  696. //
  697. // This function is a mess! First because it ought to be an FH API
  698. // function, and secondly because it mixes portable code and Windows API
  699. // calls. The details of what is to be done with it are deferred until the
  700. // UNIX port of FH is designed, though. STOPPRESS! Function replaced by new
  701. // FH_CreateAndSelectFont, which combines old USR_UseFont and
  702. // FH_CreateAndSelectFont - you have to write an NT version.
  703. //
  704. //
  705. // USR_UseFont()
  706. //
  707. BOOL ASShare::USR_UseFont
  708. (
  709. HDC surface,
  710. HFONT* pHFont,
  711. TEXTMETRIC* pFontMetrics,
  712. LPSTR pName,
  713. UINT codePage,
  714. UINT MaxHeight,
  715. UINT Height,
  716. UINT Width,
  717. UINT Weight,
  718. UINT flags
  719. )
  720. {
  721. BOOL rc = FALSE;
  722. HFONT hNewFont;
  723. HFONT hOldFont;
  724. DebugEntry(ASShare::USR_UseFont);
  725. rc = FH_CreateAndSelectFont(surface,
  726. &hNewFont,
  727. &hOldFont,
  728. pName,
  729. codePage,
  730. MaxHeight,
  731. Height,
  732. Width,
  733. Weight,
  734. flags);
  735. if (rc == FALSE)
  736. {
  737. //
  738. // Failed to create or select the font.
  739. //
  740. DC_QUIT;
  741. }
  742. //
  743. // Select in the new font which ensures that the old one is deselected.
  744. //
  745. // NB. We do not delete the font we are deselecting, rather the old
  746. // one that was passed to us. This is beacuse multiple components use
  747. // "surface", and so the deselected font may not be the current
  748. // component's last font at all - the important thing is that by
  749. // selecting in the new font we are ensuring that the old font is not
  750. // the selected one.
  751. //
  752. SelectFont(surface, hNewFont);
  753. if (*pHFont)
  754. {
  755. DeleteFont(*pHFont);
  756. }
  757. //
  758. // If a pointer to font metrics was passed in then we need to query
  759. // the metrics now.
  760. //
  761. if (pFontMetrics)
  762. GetTextMetrics(surface, pFontMetrics);
  763. //
  764. // Update the record of the last font we selected.
  765. //
  766. *pHFont = hNewFont;
  767. rc = TRUE;
  768. DC_EXIT_POINT:
  769. DebugExitDWORD(ASShare::USR_UseFont, rc);
  770. return(rc);
  771. }
  772. //
  773. // USR_ScreenChanged()
  774. //
  775. void ASShare::USR_ScreenChanged(ASPerson * pasPerson)
  776. {
  777. DebugEntry(ASShare::USR_ScreenChanged);
  778. ValidatePerson(pasPerson);
  779. pasPerson->cpcCaps.screen.capsScreenWidth = pasPerson->cpcCaps.screen.capsScreenWidth;
  780. pasPerson->cpcCaps.screen.capsScreenHeight = pasPerson->cpcCaps.screen.capsScreenHeight;
  781. if (pasPerson->m_pView)
  782. {
  783. //
  784. // Recreate screen bitmap
  785. //
  786. //
  787. // Discard the remote users current shadow bitmap
  788. //
  789. USRDeleteRemoteDesktop(pasPerson);
  790. //
  791. // Create a new shadow bitmap for remote user that is of the new size
  792. //
  793. USRCreateRemoteDesktop(pasPerson);
  794. }
  795. VIEW_ScreenChanged(pasPerson);
  796. DebugExitVOID(ASShare::USR_ScreenChanged);
  797. }
  798.