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.

711 lines
14 KiB

  1. //
  2. // T126OBJ.CPP
  3. // T126 objects: point, openpolyline, closepolyline, ellipse, bitmaps, workspaces
  4. //
  5. // Copyright Microsoft 1998-
  6. //
  7. #include "precomp.h"
  8. #include "NMWbObj.h"
  9. void T126Obj::AddToWorkspace()
  10. {
  11. ULONG gccHandle;
  12. UINT neededHandles = 1;
  13. if(GetType() == workspaceCreatePDU_chosen)
  14. {
  15. neededHandles = 2;
  16. }
  17. if(g_GCCPreallocHandles[g_iGCCHandleIndex].GccHandleCount >= neededHandles)
  18. {
  19. gccHandle = g_GCCPreallocHandles[g_iGCCHandleIndex].InitialGCCHandle + g_GCCPreallocHandles[g_iGCCHandleIndex].GccHandleCount - neededHandles;
  20. g_GCCPreallocHandles[g_iGCCHandleIndex].GccHandleCount = g_GCCPreallocHandles[g_iGCCHandleIndex].GccHandleCount - neededHandles;
  21. //
  22. // We got a handle no need to ask for another one
  23. //
  24. GotGCCHandle(gccHandle);
  25. TimeToGetGCCHandles(PREALLOC_GCC_HANDLES);
  26. return;
  27. }
  28. else
  29. {
  30. TRACE_MSG(("GCC Tank %d has not enough handles, we needed %d and we have %d",
  31. g_iGCCHandleIndex, neededHandles, g_GCCPreallocHandles[g_iGCCHandleIndex].GccHandleCount));
  32. //
  33. // Not enough handles
  34. //
  35. g_GCCPreallocHandles[g_iGCCHandleIndex].GccHandleCount = 0;
  36. TRACE_MSG(("GCC Tank %d is now empty, switching to other GCC tank", g_iGCCHandleIndex));
  37. //
  38. // Switch gcc handles
  39. //
  40. g_iGCCHandleIndex = g_iGCCHandleIndex ? 0 : 1;
  41. //
  42. // Try again
  43. //
  44. if(g_GCCPreallocHandles[g_iGCCHandleIndex].GccHandleCount >= neededHandles)
  45. {
  46. gccHandle = g_GCCPreallocHandles[g_iGCCHandleIndex].InitialGCCHandle + g_GCCPreallocHandles[g_iGCCHandleIndex].GccHandleCount - neededHandles;
  47. g_GCCPreallocHandles[g_iGCCHandleIndex].GccHandleCount = g_GCCPreallocHandles[g_iGCCHandleIndex].GccHandleCount - neededHandles;
  48. //
  49. // We got a handle no need to ask for another one
  50. //
  51. GotGCCHandle(gccHandle);
  52. TimeToGetGCCHandles(PREALLOC_GCC_HANDLES);
  53. return;
  54. }
  55. }
  56. //
  57. // Save this object in our list of DrawingObjects
  58. //
  59. g_pListOfObjectsThatRequestedHandles->AddHead(this);
  60. //
  61. // Ask GCC to give us an unique handle
  62. //
  63. T120Error rc = g_pNMWBOBJ->AllocateHandles(neededHandles);
  64. //
  65. // If we are not in a conference RegistryAllocateHandle will not work,
  66. // so we need to create a fake confirm to remove the object from the list
  67. //
  68. if (T120_NO_ERROR != rc)
  69. {
  70. //
  71. // Fake a GCCAllocateHandleConfim
  72. //
  73. T126_GCCAllocateHandleConfirm(AllocateFakeGCCHandle(),neededHandles);
  74. }
  75. }
  76. //
  77. //
  78. // Function: T126Obj::NormalizeRect
  79. //
  80. // Purpose: Normalize a rectangle ensuring that the top left is above
  81. // and to the left of the bottom right.
  82. //
  83. //
  84. void NormalizeRect(LPRECT lprc)
  85. {
  86. int tmp;
  87. if (lprc->right < lprc->left)
  88. {
  89. tmp = lprc->left;
  90. lprc->left = lprc->right;
  91. lprc->right = tmp;
  92. }
  93. if (lprc->bottom < lprc->top)
  94. {
  95. tmp = lprc->top;
  96. lprc->top = lprc->bottom;
  97. lprc->bottom = tmp;
  98. }
  99. }
  100. void T126Obj::SetRect(LPCRECT lprc)
  101. {
  102. m_rect.top = lprc->top;
  103. m_rect.bottom = lprc->bottom;
  104. m_rect.left = lprc->left;
  105. m_rect.right = lprc->right;
  106. }
  107. void T126Obj::SetBoundsRect(LPCRECT lprc)
  108. {
  109. m_boundsRect.top = lprc->top;
  110. m_boundsRect.bottom = lprc->bottom;
  111. m_boundsRect.left = lprc->left;
  112. m_boundsRect.right = lprc->right;
  113. }
  114. void T126Obj::SetRectPts(POINT point1, POINT point2)
  115. {
  116. RECT rc;
  117. rc.left = point1.x;
  118. rc.top = point1.y;
  119. rc.right = point2.x;
  120. rc.bottom = point2.y;
  121. SetRect(&rc);
  122. }
  123. void T126Obj::SetBoundRectPts(POINT point1, POINT point2)
  124. {
  125. RECT rc;
  126. rc.left = point1.x;
  127. rc.top = point1.y;
  128. rc.right = point2.x;
  129. rc.bottom = point2.y;
  130. SetBoundsRect(&rc);
  131. }
  132. void T126Obj::GetRect(LPRECT lprc)
  133. {
  134. lprc->top = m_rect.top;
  135. lprc->bottom = m_rect.bottom;
  136. lprc->left = m_rect.left;
  137. lprc->right = m_rect.right;
  138. }
  139. void T126Obj::GetBoundsRect(LPRECT lprc)
  140. {
  141. if(GraphicTool() == TOOLTYPE_HIGHLIGHT || GraphicTool() == TOOLTYPE_PEN)
  142. {
  143. lprc->top = m_boundsRect.top;
  144. lprc->bottom = m_boundsRect.bottom;
  145. lprc->left = m_boundsRect.left;
  146. lprc->right = m_boundsRect.right;
  147. }
  148. else
  149. {
  150. GetRect(lprc);
  151. ::InflateRect(lprc, m_penThickness/2, m_penThickness/2);
  152. }
  153. NormalizeRect(lprc);
  154. }
  155. BOOL T126Obj::PointInBounds(POINT point)
  156. {
  157. RECT rect;
  158. GetBoundsRect(&rect);
  159. return ::PtInRect(&rect, point);
  160. }
  161. void T126Obj::MoveBy(int cx, int cy)
  162. {
  163. // Move the bounding rectangle
  164. ::OffsetRect(&m_rect, cx, cy);
  165. }
  166. void T126Obj::MoveTo(int x, int y)
  167. {
  168. // Calculate the offset needed to translate the object from its current
  169. // position to the required position.
  170. x -= m_rect.left;
  171. y -= m_rect.top;
  172. MoveBy(x, y);
  173. }
  174. //
  175. // Select a drawing and add the rectangle sizes to the selector size rectangle
  176. //
  177. void T126Obj::SelectDrawingObject(void)
  178. {
  179. if(GraphicTool() == TOOLTYPE_REMOTEPOINTER && GetOwnerID() != GET_NODE_ID_FROM_MEMBER_ID(g_MyMemberID))
  180. {
  181. return;
  182. }
  183. //
  184. // Mark it as selected locally
  185. //
  186. SelectedLocally();
  187. //
  188. // Calculate the size of the rectangle to be invalidated.
  189. //
  190. CalculateInvalidationRect();
  191. //
  192. // Draw the selection rectangle
  193. //
  194. DrawRect();
  195. }
  196. void T126Obj::UnselectDrawingObject(void)
  197. {
  198. //
  199. // Erase selection rect
  200. //
  201. DrawRect();
  202. if(GraphicTool() == TOOLTYPE_REMOTEPOINTER && GetOwnerID() != GET_NODE_ID_FROM_MEMBER_ID(g_MyMemberID))
  203. {
  204. return;
  205. }
  206. ClearSelectionFlags();
  207. //
  208. // Don't even bother sending selection changes if we were deleted
  209. // or if this was a remote that unselected us.
  210. //
  211. if(WasDeletedLocally() || WasSelectedRemotely())
  212. {
  213. return;
  214. }
  215. ResetAttrib();
  216. SetViewState(unselected_chosen);
  217. //
  218. // We are going to send a new view state, mark it as edited locally
  219. //
  220. EditedLocally();
  221. //
  222. // Sends the change in the view state to the other nodes
  223. //
  224. OnObjectEdit();
  225. ClearEditionFlags();
  226. }
  227. void T126Obj::DrawRect(void)
  228. {
  229. if(GraphicTool() == TOOLTYPE_REMOTEPOINTER)
  230. {
  231. return;
  232. }
  233. RECT rect;
  234. GetBoundsRect(&rect);
  235. ::DrawFocusRect(g_pDraw->m_hDCCached,&rect);
  236. }
  237. void T126Obj::SelectedLocally(void)
  238. {
  239. m_bSelectedLocally = TRUE;
  240. m_bSelectedRemotely = FALSE;
  241. SetViewState(selected_chosen);
  242. //
  243. // We are going to send a new view state, mark it as edited locally
  244. //
  245. EditedLocally();
  246. ResetAttrib();
  247. ChangedViewState();
  248. //
  249. // Sends the change in the view state to the other nodes
  250. //
  251. OnObjectEdit();
  252. }
  253. void T126Obj::SelectedRemotely(void)
  254. {
  255. m_bSelectedLocally = FALSE;
  256. m_bSelectedRemotely = TRUE;
  257. SetViewState(selected_chosen);
  258. }
  259. void T126Obj::MoveBy(LONG x , LONG y)
  260. {
  261. //
  262. // Erase the old one
  263. //
  264. if(GraphicTool() == TOOLTYPE_REMOTEPOINTER)
  265. {
  266. UnDraw();
  267. }
  268. DrawRect();
  269. RECT rect;
  270. if(GraphicTool() == TOOLTYPE_PEN || GraphicTool() == TOOLTYPE_HIGHLIGHT)
  271. {
  272. GetBoundsRect(&rect);
  273. }
  274. else
  275. {
  276. GetRect(&rect);
  277. }
  278. ::OffsetRect(&rect, x, y);
  279. if(GraphicTool() == TOOLTYPE_PEN || GraphicTool() == TOOLTYPE_HIGHLIGHT)
  280. {
  281. SetBoundsRect(&rect);
  282. }
  283. else
  284. {
  285. SetRect(&rect);
  286. }
  287. POINT anchorPoint;
  288. GetAnchorPoint(&anchorPoint);
  289. SetAnchorPoint(anchorPoint.x + x ,anchorPoint.y + y);
  290. //
  291. // Draw the new one
  292. //
  293. if(GraphicTool() == TOOLTYPE_REMOTEPOINTER)
  294. {
  295. Draw();
  296. }
  297. DrawRect();
  298. CalculateInvalidationRect();
  299. }
  300. void T126Obj::CalculateInvalidationRect(void)
  301. {
  302. RECT rect;
  303. UINT penThickness = GetPenThickness();
  304. TRACE_DEBUG(("Invalidation Rect (%d,%d) (%d,%d)", g_pDraw->m_selectorRect.left,g_pDraw->m_selectorRect.top, g_pDraw->m_selectorRect.right, g_pDraw->m_selectorRect.bottom ));
  305. GetBoundsRect(&rect);
  306. ::UnionRect(&g_pDraw->m_selectorRect,&g_pDraw->m_selectorRect,&rect);
  307. TRACE_DEBUG(("Invalidation Rect (%d,%d) (%d,%d)", g_pDraw->m_selectorRect.left,g_pDraw->m_selectorRect.top, g_pDraw->m_selectorRect.right, g_pDraw->m_selectorRect.bottom ));
  308. }
  309. //
  310. // Checks object for an actual overlap with pRectHit. This
  311. // function assumes that the boundingRect has already been
  312. // compared with pRectHit.
  313. //
  314. BOOL T126Obj::RectangleHit(BOOL borderHit, LPCRECT pRectHit)
  315. {
  316. RECT rectEdge;
  317. RECT rectHit;
  318. RECT rect;
  319. //
  320. // If we are filled do the simple thing
  321. //
  322. if(!borderHit)
  323. {
  324. POINT point;
  325. point.x = (pRectHit->left + pRectHit->right) / 2;
  326. point.y = (pRectHit->top + pRectHit->bottom) / 2;
  327. if(PointInBounds(point))
  328. {
  329. return TRUE;
  330. }
  331. }
  332. GetRect(&rect);
  333. NormalizeRect(&rect);
  334. // check left edge
  335. rectEdge.left = rect.left - GetPenThickness()/2;
  336. rectEdge.top = rect.top - GetPenThickness()/2;
  337. rectEdge.right = rect.left + GetPenThickness()/2 ;
  338. rectEdge.bottom = rect.bottom + GetPenThickness()/2;
  339. if (::IntersectRect(&rectHit, &rectEdge, pRectHit))
  340. return( TRUE );
  341. // check right edge
  342. rectEdge.left = rect.right - GetPenThickness()/2;
  343. rectEdge.right = rect.right + GetPenThickness()/2;
  344. if (::IntersectRect(&rectHit, &rectEdge, pRectHit))
  345. return( TRUE );
  346. // check top edge
  347. rectEdge.left = rect.left;
  348. rectEdge.right = rect.right;
  349. rectEdge.top = rect.top - GetPenThickness()/2;
  350. rectEdge.bottom = rect.top + GetPenThickness()/2;
  351. if (::IntersectRect(&rectHit, &rectEdge, pRectHit))
  352. return( TRUE );
  353. // check bottom edge
  354. rectEdge.top = rect.bottom - GetPenThickness()/2;
  355. rectEdge.bottom = rect.bottom + GetPenThickness()/2;
  356. if (::IntersectRect(&rectHit, &rectEdge, pRectHit))
  357. return( TRUE );
  358. return( FALSE );
  359. }
  360. void T126Obj::SetAnchorPoint(LONG x, LONG y)
  361. {
  362. if(m_anchorPoint.x != x || m_anchorPoint.y != y)
  363. {
  364. ChangedAnchorPoint();
  365. m_anchorPoint.x = x;
  366. m_anchorPoint.y = y;
  367. }
  368. }
  369. void T126Obj::SetZOrder(ZOrder zorder)
  370. {
  371. m_zOrder = zorder;
  372. ChangedZOrder();
  373. }
  374. #define ARRAY_INCREMENT 0x200
  375. DCDWordArray::DCDWordArray()
  376. {
  377. MLZ_EntryOut(ZONE_FUNCTION, "DCDWordArray::DCDWordArray");
  378. m_Size = 0;
  379. m_MaxSize = ARRAY_INCREMENT;
  380. DBG_SAVE_FILE_LINE
  381. m_pData = new POINT[ARRAY_INCREMENT];
  382. ASSERT(m_pData);
  383. }
  384. DCDWordArray::~DCDWordArray()
  385. {
  386. MLZ_EntryOut(ZONE_FUNCTION, "DCDWordArray::~DCDWordArray");
  387. delete[] m_pData;
  388. }
  389. //
  390. // We need to increase the size of the array
  391. //
  392. BOOL DCDWordArray::ReallocateArray(void)
  393. {
  394. POINT *pOldArray = m_pData;
  395. DBG_SAVE_FILE_LINE
  396. m_pData = new POINT[m_MaxSize];
  397. ASSERT(m_pData);
  398. if(m_pData)
  399. {
  400. TRACE_DEBUG((">>>>>Increasing size of array to hold %d points", m_MaxSize));
  401. // copy new data from old
  402. memcpy( m_pData, pOldArray, (m_Size) * sizeof(POINT));
  403. TRACE_DEBUG(("Deleting array of points %x", pOldArray));
  404. delete[] pOldArray;
  405. return TRUE;
  406. }
  407. else
  408. {
  409. m_pData = pOldArray;
  410. return FALSE;
  411. }
  412. }
  413. //
  414. // Add a new point to the array
  415. //
  416. void DCDWordArray::Add(POINT point)
  417. {
  418. MLZ_EntryOut(ZONE_FUNCTION, "DCDWordArray::Add");
  419. TRACE_DEBUG(("Adding point(%d,%d) at %d", point.x, point.y, m_Size));
  420. TRACE_DEBUG(("Adding point at %x", &m_pData[m_Size]));
  421. if(m_pData == NULL)
  422. {
  423. return;
  424. }
  425. m_pData[m_Size].x = point.x;
  426. m_pData[m_Size].y = point.y;
  427. m_Size++;
  428. //
  429. // if we want more points, we need to re allocate the array
  430. //
  431. if(m_Size == m_MaxSize)
  432. {
  433. m_MaxSize +=ARRAY_INCREMENT;
  434. if(ReallocateArray() == FALSE)
  435. {
  436. m_Size--;
  437. }
  438. }
  439. }
  440. //
  441. // Return the number of points in the array
  442. //
  443. UINT DCDWordArray::GetSize(void)
  444. {
  445. return m_Size;
  446. }
  447. //
  448. // Sets the size of the array
  449. //
  450. void DCDWordArray::SetSize(UINT size)
  451. {
  452. int newSize;
  453. //
  454. // if we want more points, we need to re allocate the array
  455. //
  456. if (size > m_MaxSize)
  457. {
  458. m_MaxSize= ((size/ARRAY_INCREMENT)+1)*ARRAY_INCREMENT;
  459. if(ReallocateArray() == FALSE)
  460. {
  461. return;
  462. }
  463. }
  464. m_Size = size;
  465. }
  466. void T126Obj::SetPenThickness(UINT penThickness)
  467. {
  468. m_penThickness = penThickness;
  469. ChangedPenThickness();
  470. }
  471. void T126Obj::GotGCCHandle(ULONG gccHandle)
  472. {
  473. //
  474. // Save this objects handle
  475. //
  476. SetThisObjectHandle(gccHandle);
  477. //
  478. // It was created locally
  479. //
  480. CreatedLocally();
  481. switch(GetType())
  482. {
  483. //
  484. // New drawing requested a unique handle
  485. //
  486. case(bitmapCreatePDU_chosen):
  487. case(drawingCreatePDU_chosen):
  488. {
  489. WorkspaceObj * pWorkspace = GetWorkspace(GetWorkspaceHandle());
  490. if(pWorkspace && !pWorkspace->IsObjectInWorkspace(this))
  491. {
  492. //
  493. // Add a this drawing to the correct workspace
  494. //
  495. if(!AddT126ObjectToWorkspace(this))
  496. {
  497. return;
  498. }
  499. }
  500. break;
  501. }
  502. //
  503. // New workspace requested a unique handle
  504. //
  505. case(workspaceCreatePDU_chosen):
  506. {
  507. //
  508. // Save this objects handle
  509. //
  510. SetViewHandle(gccHandle + 1);
  511. SetWorkspaceHandle(gccHandle);
  512. if(!IsWorkspaceListed(this))
  513. {
  514. AddNewWorkspace((WorkspaceObj*) this);
  515. }
  516. break;
  517. }
  518. }
  519. //
  520. // Send it to T126 apps
  521. //
  522. SendNewObjectToT126Apps();
  523. }
  524. //
  525. // Create the nonstandard pdu header
  526. //
  527. void CreateNonStandardPDU(NonStandardParameter * sipdu, LPSTR NonStandardString)
  528. {
  529. PT126_VENDORINFO vendorInfo;
  530. sipdu->nonStandardIdentifier.choice = h221nonStandard_chosen;
  531. vendorInfo = (PT126_VENDORINFO) &sipdu->nonStandardIdentifier.u.h221nonStandard.value;
  532. vendorInfo->bCountryCode = USA_H221_COUNTRY_CODE;
  533. vendorInfo->bExtension = USA_H221_COUNTRY_EXTENSION;
  534. vendorInfo->wManufacturerCode = MICROSOFT_H_221_MFG_CODE;
  535. lstrcpy((LPSTR)&vendorInfo->nonstandardString,NonStandardString);
  536. sipdu->nonStandardIdentifier.u.h221nonStandard.length = sizeof(T126_VENDORINFO) -sizeof(vendorInfo->nonstandardString) + lstrlen(NonStandardString);
  537. sipdu->data.value = NULL;
  538. }
  539. void TimeToGetGCCHandles(ULONG numberOfGccHandles)
  540. {
  541. TRACE_MSG(("Using GCC Tank %d ", g_iGCCHandleIndex));
  542. TRACE_MSG(("GCC Tank 0 has %d GCC handles ", g_GCCPreallocHandles[0].GccHandleCount));
  543. TRACE_MSG(("GCC Tank 1 has %d GCC handles ", g_GCCPreallocHandles[1].GccHandleCount));
  544. //
  545. // If we have half a tank of GCC handles, it is time to fill up the spare tank
  546. //
  547. if(g_GCCPreallocHandles[g_iGCCHandleIndex].GccHandleCount <= PREALLOC_GCC_HANDLES / 2 &&
  548. g_GCCPreallocHandles[g_iGCCHandleIndex ? 0 : 1].GccHandleCount == 0 &&
  549. !g_WaitingForGCCHandles)
  550. {
  551. TRACE_MSG(("GCC Tank %d is half full, time to get more GCC handles", g_iGCCHandleIndex));
  552. g_pNMWBOBJ->AllocateHandles(numberOfGccHandles);
  553. g_WaitingForGCCHandles = TRUE;
  554. }
  555. //
  556. // If we ran out of handles, it is time to switch tanks
  557. //
  558. if(g_GCCPreallocHandles[g_iGCCHandleIndex].GccHandleCount == 0)
  559. {
  560. TRACE_MSG(("GCC Tank %d is empty, switching to other GCC tank", g_iGCCHandleIndex));
  561. g_iGCCHandleIndex = g_iGCCHandleIndex ? 0 : 1;
  562. }
  563. }