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.

796 lines
19 KiB

  1. // File: roomlist.cpp
  2. #include "precomp.h"
  3. #include "resource.h"
  4. #include "ConfRoom.h"
  5. #include "RoomList.h"
  6. #include "RToolbar.h"
  7. #include "VidView.h"
  8. #include "RostInfo.h"
  9. #include "particip.h"
  10. static const int RL_NUM_ICON_COLUMNS = 0;
  11. /* C R O O M L I S T V I E W */
  12. /*-------------------------------------------------------------------------
  13. %%Function: CRoomListView
  14. -------------------------------------------------------------------------*/
  15. CRoomListView::CRoomListView():
  16. // m_iSortColumn (0),
  17. m_lUserData(0),
  18. m_fSortAscending (TRUE)
  19. {
  20. DbgMsg(iZONE_OBJECTS, "Obj: %08X created CRoomListView", this);
  21. }
  22. CRoomListView::~CRoomListView()
  23. {
  24. ListView_DeleteAllItems(m_hWnd);
  25. if(IsWindow())
  26. {
  27. DestroyWindow();
  28. }
  29. DbgMsg(iZONE_OBJECTS, "Obj: %08X destroyed CRoomListView", this);
  30. }
  31. CParticipant * CRoomListView::GetParticipant(void)
  32. {
  33. LPARAM lParam = GetSelectedLParam();
  34. return (CParticipant *) lParam;
  35. }
  36. //////////////////////////////////////////////////////////////////////////
  37. // CRoomListView::CView
  38. VOID CRoomListView::Show(BOOL fVisible)
  39. {
  40. if (NULL != m_hWnd)
  41. {
  42. ::ShowWindow(m_hWnd, fVisible ? SW_SHOW : SW_HIDE);
  43. }
  44. }
  45. VOID CRoomListView::ShiftFocus(HWND hwndCur, BOOL fForward)
  46. {
  47. if ((NULL == hwndCur) && (NULL != m_hWnd))
  48. {
  49. ::SetFocus(m_hWnd);
  50. }
  51. }
  52. VOID CRoomListView::Redraw(void)
  53. {
  54. if (NULL == m_hWnd)
  55. return;
  56. // Invalidate entire client area and force erase:
  57. ::InvalidateRect(m_hWnd, NULL, TRUE);
  58. // Force an immediate repaint:
  59. ::UpdateWindow(m_hWnd);
  60. }
  61. VOID CRoomListView::ForwardSysChangeMsg(UINT uMsg, WPARAM wParam, LPARAM lParam)
  62. {
  63. // Pass all messages to the list view window:
  64. if (NULL != m_hWnd)
  65. {
  66. ::SendMessage(m_hWnd, uMsg, wParam, lParam);
  67. }
  68. }
  69. BOOL CRoomListView::Create(HWND hwndParent)
  70. {
  71. DBGENTRY(CRoomListView::FCreate);
  72. RECT rcPos;
  73. SetRect( &rcPos, 0, 0, 0, 0 );
  74. DWORD dwStyle = WS_CHILD | WS_TABSTOP | LVS_REPORT | LVS_SINGLESEL | LVS_AUTOARRANGE | LVS_SHAREIMAGELISTS;
  75. DWORD dwExStyle = WS_EX_CLIENTEDGE;
  76. CWindowImpl<CRoomListView>::Create( hwndParent, rcPos, g_szEmpty, dwStyle, dwExStyle, ID_LISTVIEW );
  77. if (NULL == m_hWnd)
  78. return FALSE;
  79. // initialize the list view window
  80. // Associate the image list with the list view
  81. ListView_SetImageList(m_hWnd, g_himlIconSmall, LVSIL_SMALL);
  82. // Now initialize the columns we will need
  83. // Initialize the LV_COLUMN structure
  84. // the mask specifies that the .fmt, .ex, width, and .subitem members
  85. // of the structure are valid,
  86. LV_COLUMN lvC; // List View Column structure
  87. ClearStruct(&lvC);
  88. TCHAR pszText[256]; // place to store some text
  89. lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
  90. lvC.fmt = LVCFMT_LEFT;
  91. SIZE size;
  92. GetDesiredSize(&size);
  93. int iWidth = size.cx;
  94. // default width of the non-icon columns (-1 to prevent creating a scrollbar)
  95. int iIconColWidth = ::GetSystemMetrics(SM_CXSMICON) + 7; // 7 additional pixels
  96. int iTextColWidth = ((iWidth - (RL_NUM_ICON_COLUMNS * iIconColWidth))
  97. / (NUM_COLUMNS - RL_NUM_ICON_COLUMNS)) - 1;
  98. lvC.pszText = pszText;
  99. // Add the columns.
  100. for (int index = 0; index < NUM_COLUMNS; index++)
  101. {
  102. HD_ITEM hdi;
  103. hdi.mask = HDI_IMAGE | HDI_FORMAT;
  104. hdi.fmt = HDF_IMAGE;
  105. lvC.iSubItem = index;
  106. switch (index)
  107. {
  108. case COLUMN_INDEX_NAME:
  109. default:
  110. {
  111. // These are text or text&icon columns
  112. hdi.iImage = -1;
  113. lvC.cx = iTextColWidth;
  114. break;
  115. }
  116. }
  117. LoadString(::GetInstanceHandle(),
  118. IDS_COLUMN_NAME + index,
  119. pszText,
  120. CCHMAX(pszText));
  121. if (-1 != ListView_InsertColumn(m_hWnd, index, &lvC))
  122. {
  123. if (-1 != hdi.iImage)
  124. {
  125. ASSERT(ListView_GetHeader(m_hWnd));
  126. Header_SetItem(ListView_GetHeader(m_hWnd), index, &hdi);
  127. }
  128. }
  129. else
  130. {
  131. WARNING_OUT(("Could not insert column %d in list view", index));
  132. }
  133. }
  134. ASSERT(ListView_GetHeader(m_hWnd));
  135. Header_SetImageList(ListView_GetHeader(m_hWnd), g_himlIconSmall);
  136. // set the style to do drag and drop headers and full row select
  137. dwExStyle = ListView_GetExtendedListViewStyle(m_hWnd);
  138. dwExStyle |= (LVS_EX_SUBITEMIMAGES | LVS_EX_HEADERDRAGDROP);
  139. ListView_SetExtendedListViewStyle(m_hWnd, dwExStyle);
  140. return TRUE;
  141. }
  142. LRESULT CRoomListView::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  143. {
  144. int cx = LOWORD(lParam);
  145. HWND hwndHeader = ListView_GetHeader(m_hWnd);
  146. if (NULL != hwndHeader)
  147. {
  148. // This check is to avoid a RIP in debug windows
  149. ListView_SetColumnWidth(m_hWnd, 0, cx);
  150. }
  151. bHandled = FALSE;
  152. return(0);
  153. }
  154. /****************************************************************************
  155. *
  156. * CLASS: CRoomListView
  157. *
  158. * MEMBER: Add(int iPosition, LPARAM lParam)
  159. *
  160. * PURPOSE: Adds a item to the list view
  161. *
  162. ****************************************************************************/
  163. BOOL CRoomListView::Add(int iPosition, CParticipant * pPart)
  164. {
  165. DebugEntry(CRoomListView::Add);
  166. BOOL bRet = FALSE;
  167. int nPrevCount = ListView_GetItemCount(m_hWnd);
  168. LV_ITEM lvI; // List view item structure
  169. // Fill in the LV_ITEM structure
  170. // The mask specifies the the .pszText, .iImage, .lParam and .state
  171. // members of the LV_ITEM structure are valid.
  172. lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
  173. lvI.state = (0 == nPrevCount) ? LVIS_FOCUSED : 0;
  174. lvI.stateMask = LVIS_FOCUSED;
  175. lvI.iItem = iPosition;
  176. lvI.iSubItem = 0;
  177. // The parent window is responsible for storing the text. The List view
  178. // window will send a LVN_GETDISPINFO when it needs the text to display
  179. lvI.pszText = LPSTR_TEXTCALLBACK;
  180. lvI.cchTextMax = MAX_ITEMLEN;
  181. lvI.iImage = I_IMAGECALLBACK;
  182. lvI.lParam = (LPARAM) pPart;
  183. if (-1 != ListView_InsertItem(m_hWnd, &lvI))
  184. {
  185. pPart->AddRef(); // the ListView keeps a reference on this
  186. // set the text for each of the columns for report view
  187. for (int iSubItem = 1; iSubItem < NUM_COLUMNS; iSubItem++)
  188. {
  189. ListView_SetItemText( m_hWnd,
  190. iPosition,
  191. iSubItem,
  192. LPSTR_TEXTCALLBACK);
  193. }
  194. ListView_SortItems( m_hWnd,
  195. CRoomListView::RoomListViewCompareProc,
  196. (LPARAM)(this));
  197. }
  198. DebugExitBOOL(CRoomListView::Add, bRet);
  199. return bRet;
  200. }
  201. /****************************************************************************
  202. *
  203. * CLASS: CRoomListView
  204. *
  205. * MEMBER: LParamToPos(LPARAM lParam)
  206. *
  207. * PURPOSE: Returns the position index associated with the lParam value
  208. *
  209. ****************************************************************************/
  210. int CRoomListView::LParamToPos(LPARAM lParam)
  211. {
  212. // Note: retuns -1 on failure
  213. LV_FINDINFO lvF;
  214. lvF.flags = LVFI_PARAM;
  215. lvF.lParam = lParam;
  216. return ListView_FindItem(m_hWnd, -1, &lvF);
  217. }
  218. /****************************************************************************
  219. *
  220. * CLASS: CRoomListView
  221. *
  222. * MEMBER: GetSelectedLParam()
  223. *
  224. * PURPOSE: Returns the lParam of the selected item or NULL (no sel.)
  225. *
  226. ****************************************************************************/
  227. LPARAM CRoomListView::GetSelectedLParam()
  228. {
  229. LPARAM lRet = NULL;
  230. if (::GetFocus() == m_hWnd)
  231. {
  232. // The list view has the focus, so find the selected item (if any)
  233. int iItem = ListView_GetNextItem(m_hWnd, -1, LVNI_ALL | LVNI_SELECTED);
  234. if (-1 != iItem)
  235. {
  236. LV_ITEM lvi;
  237. lvi.iItem = iItem;
  238. lvi.iSubItem = 0;
  239. lvi.mask = LVIF_PARAM;
  240. if (ListView_GetItem(m_hWnd, &lvi))
  241. {
  242. lRet = lvi.lParam;
  243. }
  244. }
  245. }
  246. return lRet;
  247. }
  248. /* R E M O V E */
  249. /*-------------------------------------------------------------------------
  250. %%Function: Remove
  251. Removes an item from the list view
  252. -------------------------------------------------------------------------*/
  253. VOID CRoomListView::Remove(LPARAM lParam)
  254. {
  255. DBGENTRY(CRoomListView::Remove);
  256. int iPosition = LParamToPos(lParam);
  257. if (-1 == iPosition)
  258. return;
  259. ListView_DeleteItem(m_hWnd, iPosition);
  260. }
  261. /* O N C H A N G E P A R T I C I P A N T */
  262. /*-------------------------------------------------------------------------
  263. %%Function: OnChangeParticipant
  264. Updates the user's status information
  265. -------------------------------------------------------------------------*/
  266. VOID CRoomListView::OnChangeParticipant(CParticipant * pPart, NM_MEMBER_NOTIFY uNotify)
  267. {
  268. DBGENTRY(CRoomListView::OnChangeParticipant);
  269. switch (uNotify)
  270. {
  271. case NM_MEMBER_ADDED:
  272. {
  273. // Add the new member to the start of the list
  274. Add(0, pPart);
  275. break;
  276. }
  277. case NM_MEMBER_REMOVED:
  278. {
  279. // Remove the member from the list
  280. Remove((LPARAM) pPart);
  281. break;
  282. }
  283. case NM_MEMBER_UPDATED:
  284. {
  285. int iPos = LParamToPos((LPARAM) pPart);
  286. if (-1 == iPos)
  287. return;
  288. ListView_RedrawItems(m_hWnd, iPos, iPos);
  289. ListView_SortItems(m_hWnd, CRoomListView::RoomListViewCompareProc, (LPARAM)(this));
  290. break;
  291. }
  292. default:
  293. break;
  294. }
  295. }
  296. /****************************************************************************
  297. *
  298. * CLASS: CRoomListView
  299. *
  300. * MEMBER: OnNotify(WPARAM, LPARAM)
  301. *
  302. * PURPOSE: Handles WM_NOTIFY messages sent to the list view
  303. *
  304. ****************************************************************************/
  305. LRESULT CRoomListView::OnNotify(WPARAM wParam, LPARAM lParam)
  306. {
  307. LRESULT lRet = 0L;
  308. LV_DISPINFO *pLvdi = (LV_DISPINFO *)lParam;
  309. ASSERT(pLvdi);
  310. if (ID_LISTVIEW == wParam)
  311. {
  312. switch(pLvdi->hdr.code)
  313. {
  314. case NM_DBLCLK:
  315. case NM_RETURN:
  316. {
  317. if (0x8000 & ::GetKeyState(VK_MENU))
  318. {
  319. ::PostMessage(::GetMainWindow(), WM_COMMAND, IDM_POPUP_PROPERTIES, 0);
  320. }
  321. break;
  322. }
  323. case NM_CLICK:
  324. case NM_RCLICK:
  325. {
  326. LV_HITTESTINFO lvhi;
  327. ::GetCursorPos(&(lvhi.pt));
  328. ::MapWindowPoints(NULL, m_hWnd, &(lvhi.pt), 1);
  329. ListView_SubItemHitTest(m_hWnd, &lvhi);
  330. if (LVHT_ONITEMICON | lvhi.flags)
  331. {
  332. lRet = OnClick(&lvhi, (NM_CLICK == pLvdi->hdr.code));
  333. }
  334. break;
  335. }
  336. case LVN_DELETEITEM:
  337. {
  338. NM_LISTVIEW * pnmv = (NM_LISTVIEW *) lParam;
  339. CParticipant * pPart = (CParticipant *) pnmv->lParam;
  340. ASSERT(pPart);
  341. if (pPart)
  342. {
  343. pPart->Release();
  344. }
  345. break;
  346. }
  347. case LVN_GETDISPINFO:
  348. {
  349. GetDispInfo(pLvdi);
  350. break;
  351. }
  352. case LVN_COLUMNCLICK:
  353. {
  354. // The user clicked on one of the column headings - sort by
  355. // this column.
  356. TRACE_OUT(("CRoomListView::OnNotify called (NM_COLUMNCLICK)"));
  357. NM_LISTVIEW *pNm = (NM_LISTVIEW *)lParam;
  358. ASSERT(pNm);
  359. if (pNm->iSubItem == m_iSortColumn)
  360. {
  361. m_fSortAscending = !m_fSortAscending;
  362. }
  363. else
  364. {
  365. m_fSortAscending = TRUE;
  366. }
  367. // m_iSortColumn = pNm->iSubItem;
  368. ListView_SortItems( pNm->hdr.hwndFrom,
  369. CRoomListView::RoomListViewCompareProc,
  370. (LPARAM)(this));
  371. break;
  372. }
  373. default:
  374. break;
  375. }
  376. }
  377. return lRet;
  378. }
  379. /* G E T D I S P I N F O */
  380. /*-------------------------------------------------------------------------
  381. %%Function: GetDispInfo
  382. Get the display information for a participant
  383. -------------------------------------------------------------------------*/
  384. VOID CRoomListView::GetDispInfo(LV_DISPINFO * pLvdi)
  385. {
  386. CParticipant * pPart = (CParticipant *) (pLvdi->item.lParam);
  387. if (NULL == pPart)
  388. return;
  389. // Get the text
  390. if (pLvdi->item.mask & LVIF_TEXT)
  391. {
  392. switch (pLvdi->item.iSubItem)
  393. {
  394. case COLUMN_INDEX_NAME:
  395. {
  396. lstrcpyn(pLvdi->item.pszText, pPart->GetPszName(), pLvdi->item.cchTextMax);
  397. break;
  398. }
  399. default:
  400. break;
  401. }
  402. }
  403. // Get the Image
  404. if (pLvdi->item.mask & LVIF_IMAGE)
  405. {
  406. switch (pLvdi->item.iSubItem)
  407. {
  408. case COLUMN_INDEX_NAME:
  409. {
  410. pLvdi->item.iImage = II_USER;
  411. break;
  412. }
  413. default:
  414. break;
  415. }
  416. }
  417. }
  418. /****************************************************************************
  419. *
  420. * CLASS: CRoomListView
  421. *
  422. * MEMBER: LoadColumnInfo(RegEntry* pre)
  423. *
  424. * PURPOSE: Loads the column position info in the registry
  425. *
  426. ****************************************************************************/
  427. BOOL CRoomListView::LoadSettings(RegEntry* pre)
  428. {
  429. DebugEntry(CRoomListView::LoadColumnInfo);
  430. // BUGBUG georgep: Using a fixed initial width for now; should take a max
  431. // of longest name and the window width
  432. ListView_SetColumnWidth(m_hWnd, 0, 300);
  433. DebugExitBOOL(CRoomListView::LoadColumnInfo, TRUE);
  434. return TRUE;
  435. }
  436. /****************************************************************************
  437. *
  438. * CLASS: CRoomListView
  439. *
  440. * MEMBER: OnClick(LV_HITTESTINFO*, BOOL)
  441. *
  442. * PURPOSE: Handles creating a popup menu when clicking on some icons
  443. *
  444. ****************************************************************************/
  445. /* O N C L I C K */
  446. /*-------------------------------------------------------------------------
  447. %%Function: OnClick
  448. Handles creating a popup menu when clicking on some icons
  449. -------------------------------------------------------------------------*/
  450. LRESULT CRoomListView::OnClick(LV_HITTESTINFO* plvhi, BOOL fLeftClick)
  451. {
  452. ASSERT(NULL != plvhi);
  453. // Select the item:
  454. ListView_SetItemState(m_hWnd, plvhi->iItem,
  455. LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
  456. switch (plvhi->iSubItem)
  457. {
  458. case COLUMN_INDEX_NAME:
  459. {
  460. if (fLeftClick)
  461. return 0; // selection
  462. break;
  463. }
  464. default:
  465. return 0;
  466. }
  467. // convert back to screen coords
  468. ::MapWindowPoints(m_hWnd, NULL, &(plvhi->pt), 1);
  469. OnPopup(plvhi->pt);
  470. return 1;
  471. }
  472. /****************************************************************************
  473. *
  474. * CLASS: CRoomListView
  475. *
  476. * MEMBER: OnPopup(POINT)
  477. *
  478. * PURPOSE: Handles popup menu
  479. *
  480. ****************************************************************************/
  481. BOOL CRoomListView::OnPopup(POINT pt)
  482. {
  483. CParticipant * pPart = GetParticipant();
  484. if (NULL == pPart)
  485. return FALSE;
  486. // Get the menu for the popup from the resource file.
  487. HMENU hMenu = LoadMenu(::GetInstanceHandle(), MAKEINTRESOURCE(IDR_USER_POPUP));
  488. if (NULL == hMenu)
  489. return FALSE;
  490. // Get the first menu in it which we will use for the call to
  491. // TrackPopup(). This could also have been created on the fly using
  492. // CreatePopupMenu and then we could have used InsertMenu() or
  493. // AppendMenu.
  494. HMENU hMenuTrackPopup = GetSubMenu(hMenu, 0);
  495. ASSERT(NULL != hMenuTrackPopup);
  496. ::EnableMenuItem(hMenuTrackPopup, IDM_POPUP_SPEEDDIAL,
  497. pPart->FEnableCmdCreateSpeedDial() ? MF_ENABLED : MF_GRAYED);
  498. ::EnableMenuItem(hMenuTrackPopup, IDM_POPUP_ADDRESSBOOK,
  499. pPart->FEnableCmdCreateWabEntry() ? MF_ENABLED : MF_GRAYED);
  500. ::EnableMenuItem(hMenuTrackPopup, IDM_POPUP_EJECT,
  501. pPart->FEnableCmdEject() ? MF_ENABLED : MF_GRAYED);
  502. // GiveControl/CancelGiveControl()
  503. pPart->CalcControlCmd(hMenuTrackPopup);
  504. BOOL fShowMenu = TRUE;
  505. // Check to see if we have "special" coordinates that signify
  506. // that we entered here as a result of a keyboard click
  507. // instead of a mouse click - and if so, get some default coords
  508. if ((0xFFFF == pt.x) && (0xFFFF == pt.y))
  509. {
  510. int iPos = LParamToPos((LPARAM)pPart);
  511. RECT rctIcon;
  512. if ((-1 == iPos) ||
  513. (FALSE == ListView_GetItemRect( m_hWnd,
  514. iPos,
  515. &rctIcon,
  516. LVIR_ICON)))
  517. {
  518. fShowMenu = FALSE;
  519. }
  520. else
  521. {
  522. // Convert from client coords to screen coords
  523. ::MapWindowPoints(m_hWnd, NULL, (LPPOINT)&rctIcon, 2);
  524. pt.x = rctIcon.left + ((rctIcon.right - rctIcon.left) / 2);
  525. pt.y = rctIcon.top + ((rctIcon.bottom - rctIcon.top) / 2);
  526. }
  527. }
  528. if (fShowMenu)
  529. {
  530. HWND hwnd = ::GetMainWindow();
  531. // Draw and track the "floating" popup
  532. int cmd = TrackPopupMenu( hMenuTrackPopup,
  533. TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
  534. pt.x,
  535. pt.y,
  536. 0,
  537. hwnd,
  538. NULL);
  539. // Get this again since we just ended a message loop
  540. pPart = GetParticipant();
  541. if (0 != cmd && NULL != pPart)
  542. {
  543. pPart->OnCommand(hwnd, (WORD)cmd);
  544. }
  545. }
  546. // We are finished with the menu now, so destroy it
  547. DestroyMenu(hMenu);
  548. return TRUE;
  549. }
  550. /****************************************************************************
  551. *
  552. * CLASS: CRoomListView
  553. *
  554. * MEMBER: Callback used for sorting the list view
  555. *
  556. ****************************************************************************/
  557. int CALLBACK CRoomListView::RoomListViewCompareProc(LPARAM lParam1,
  558. LPARAM lParam2,
  559. LPARAM lParamSort)
  560. {
  561. DebugEntry(RoomListViewCompareProc);
  562. CParticipant * pPart1 = (CParticipant *)lParam1;
  563. CParticipant * pPart2 = (CParticipant *)lParam2;
  564. CRoomListView* prlv = (CRoomListView*) lParamSort;
  565. ASSERT(prlv);
  566. int iResult = 0;
  567. if (pPart1 && pPart2)
  568. {
  569. switch (prlv->m_iSortColumn)
  570. {
  571. case COLUMN_INDEX_NAME:
  572. {
  573. LPTSTR lpStr1 = pPart1->GetPszName();
  574. LPTSTR lpStr2 = pPart2->GetPszName();
  575. iResult = lstrcmpi(lpStr1, lpStr2);
  576. break;
  577. }
  578. default:
  579. {
  580. ERROR_OUT(("Sorting by unknown label"));
  581. break;
  582. }
  583. }
  584. }
  585. if (!prlv->m_fSortAscending)
  586. {
  587. iResult = -iResult;
  588. }
  589. DebugExitINT(RoomListViewCompareProc, iResult);
  590. return iResult;
  591. }
  592. VOID TileBltWatermark(UINT x, UINT y, UINT cx, UINT cy, UINT xOff, UINT yOff, HDC hdcDst, HDC hdcSrc,
  593. UINT cxWatermark, UINT cyWatermark)
  594. {
  595. DBGENTRY(CRoomListView::TileBltWatermark)
  596. int cxPart, cyPart;
  597. BOOL fxTile, fyTile;
  598. ReCheck:
  599. fxTile = ((xOff + cx) > cxWatermark);
  600. fyTile = ((yOff + cy) > cyWatermark);
  601. if (!fxTile && !fyTile)
  602. {
  603. // no tiling needed -- blt and leave
  604. BitBlt(hdcDst, x, y, cx, cy, hdcSrc, xOff, yOff, SRCCOPY);
  605. DBGEXIT(CRoomListView::TileBltWatermark)
  606. return;
  607. }
  608. if (!fxTile)
  609. {
  610. // vertically tile
  611. cyPart = cyWatermark - yOff;
  612. BitBlt(hdcDst, x, y, cx, cyPart, hdcSrc, xOff, yOff, SRCCOPY);
  613. y += cyPart;
  614. cy -= cyPart;
  615. yOff = 0;
  616. goto ReCheck;
  617. }
  618. if (!fyTile)
  619. {
  620. // horizontally tile
  621. cxPart = cxWatermark - xOff;
  622. BitBlt(hdcDst, x, y, cxPart, cy, hdcSrc, xOff, yOff, SRCCOPY);
  623. x += cxPart;
  624. cx -= cxPart;
  625. xOff = 0;
  626. goto ReCheck;
  627. }
  628. // tile both ways
  629. cyPart = cyWatermark - yOff;
  630. TileBltWatermark(x, y, cx, cyPart, xOff, yOff, hdcDst, hdcSrc, cxWatermark, cyWatermark);
  631. y += cyPart;
  632. cy -= cyPart;
  633. yOff = 0;
  634. goto ReCheck;
  635. }
  636. void CRoomListView::GetDesiredSize(SIZE *ppt)
  637. {
  638. // BUGBUG georgep: faking these numbers; should use something dependent on the font size
  639. ppt->cx = 200;
  640. ppt->cy = 100;
  641. }
  642. // a quick but simple function to convert the "unicode" characters
  643. // from the H.245 roster info struct to ascii
  644. int Unicode4ToAsciiOEM009(char *szIn, char *szOut)
  645. {
  646. while (*szIn)
  647. {
  648. *szOut = (*szIn) - 4;
  649. szIn++;
  650. szOut++;
  651. }
  652. *szOut = '\0';
  653. return 0;
  654. }
  655.