windows-nt/Source/XPSP1/NT/enduser/netmeeting/ui/wb/t126obj.cpp
2020-09-26 16:20:57 +08:00

712 lines
14 KiB
C++

//
// T126OBJ.CPP
// T126 objects: point, openpolyline, closepolyline, ellipse, bitmaps, workspaces
//
// Copyright Microsoft 1998-
//
#include "precomp.h"
#include "NMWbObj.h"
void T126Obj::AddToWorkspace()
{
ULONG gccHandle;
UINT neededHandles = 1;
if(GetType() == workspaceCreatePDU_chosen)
{
neededHandles = 2;
}
if(g_GCCPreallocHandles[g_iGCCHandleIndex].GccHandleCount >= neededHandles)
{
gccHandle = g_GCCPreallocHandles[g_iGCCHandleIndex].InitialGCCHandle + g_GCCPreallocHandles[g_iGCCHandleIndex].GccHandleCount - neededHandles;
g_GCCPreallocHandles[g_iGCCHandleIndex].GccHandleCount = g_GCCPreallocHandles[g_iGCCHandleIndex].GccHandleCount - neededHandles;
//
// We got a handle no need to ask for another one
//
GotGCCHandle(gccHandle);
TimeToGetGCCHandles(PREALLOC_GCC_HANDLES);
return;
}
else
{
TRACE_MSG(("GCC Tank %d has not enough handles, we needed %d and we have %d",
g_iGCCHandleIndex, neededHandles, g_GCCPreallocHandles[g_iGCCHandleIndex].GccHandleCount));
//
// Not enough handles
//
g_GCCPreallocHandles[g_iGCCHandleIndex].GccHandleCount = 0;
TRACE_MSG(("GCC Tank %d is now empty, switching to other GCC tank", g_iGCCHandleIndex));
//
// Switch gcc handles
//
g_iGCCHandleIndex = g_iGCCHandleIndex ? 0 : 1;
//
// Try again
//
if(g_GCCPreallocHandles[g_iGCCHandleIndex].GccHandleCount >= neededHandles)
{
gccHandle = g_GCCPreallocHandles[g_iGCCHandleIndex].InitialGCCHandle + g_GCCPreallocHandles[g_iGCCHandleIndex].GccHandleCount - neededHandles;
g_GCCPreallocHandles[g_iGCCHandleIndex].GccHandleCount = g_GCCPreallocHandles[g_iGCCHandleIndex].GccHandleCount - neededHandles;
//
// We got a handle no need to ask for another one
//
GotGCCHandle(gccHandle);
TimeToGetGCCHandles(PREALLOC_GCC_HANDLES);
return;
}
}
//
// Save this object in our list of DrawingObjects
//
g_pListOfObjectsThatRequestedHandles->AddHead(this);
//
// Ask GCC to give us an unique handle
//
T120Error rc = g_pNMWBOBJ->AllocateHandles(neededHandles);
//
// If we are not in a conference RegistryAllocateHandle will not work,
// so we need to create a fake confirm to remove the object from the list
//
if (T120_NO_ERROR != rc)
{
//
// Fake a GCCAllocateHandleConfim
//
T126_GCCAllocateHandleConfirm(AllocateFakeGCCHandle(),neededHandles);
}
}
//
//
// Function: T126Obj::NormalizeRect
//
// Purpose: Normalize a rectangle ensuring that the top left is above
// and to the left of the bottom right.
//
//
void NormalizeRect(LPRECT lprc)
{
int tmp;
if (lprc->right < lprc->left)
{
tmp = lprc->left;
lprc->left = lprc->right;
lprc->right = tmp;
}
if (lprc->bottom < lprc->top)
{
tmp = lprc->top;
lprc->top = lprc->bottom;
lprc->bottom = tmp;
}
}
void T126Obj::SetRect(LPCRECT lprc)
{
m_rect.top = lprc->top;
m_rect.bottom = lprc->bottom;
m_rect.left = lprc->left;
m_rect.right = lprc->right;
}
void T126Obj::SetBoundsRect(LPCRECT lprc)
{
m_boundsRect.top = lprc->top;
m_boundsRect.bottom = lprc->bottom;
m_boundsRect.left = lprc->left;
m_boundsRect.right = lprc->right;
}
void T126Obj::SetRectPts(POINT point1, POINT point2)
{
RECT rc;
rc.left = point1.x;
rc.top = point1.y;
rc.right = point2.x;
rc.bottom = point2.y;
SetRect(&rc);
}
void T126Obj::SetBoundRectPts(POINT point1, POINT point2)
{
RECT rc;
rc.left = point1.x;
rc.top = point1.y;
rc.right = point2.x;
rc.bottom = point2.y;
SetBoundsRect(&rc);
}
void T126Obj::GetRect(LPRECT lprc)
{
lprc->top = m_rect.top;
lprc->bottom = m_rect.bottom;
lprc->left = m_rect.left;
lprc->right = m_rect.right;
}
void T126Obj::GetBoundsRect(LPRECT lprc)
{
if(GraphicTool() == TOOLTYPE_HIGHLIGHT || GraphicTool() == TOOLTYPE_PEN)
{
lprc->top = m_boundsRect.top;
lprc->bottom = m_boundsRect.bottom;
lprc->left = m_boundsRect.left;
lprc->right = m_boundsRect.right;
}
else
{
GetRect(lprc);
::InflateRect(lprc, m_penThickness/2, m_penThickness/2);
}
NormalizeRect(lprc);
}
BOOL T126Obj::PointInBounds(POINT point)
{
RECT rect;
GetBoundsRect(&rect);
return ::PtInRect(&rect, point);
}
void T126Obj::MoveBy(int cx, int cy)
{
// Move the bounding rectangle
::OffsetRect(&m_rect, cx, cy);
}
void T126Obj::MoveTo(int x, int y)
{
// Calculate the offset needed to translate the object from its current
// position to the required position.
x -= m_rect.left;
y -= m_rect.top;
MoveBy(x, y);
}
//
// Select a drawing and add the rectangle sizes to the selector size rectangle
//
void T126Obj::SelectDrawingObject(void)
{
if(GraphicTool() == TOOLTYPE_REMOTEPOINTER && GetOwnerID() != GET_NODE_ID_FROM_MEMBER_ID(g_MyMemberID))
{
return;
}
//
// Mark it as selected locally
//
SelectedLocally();
//
// Calculate the size of the rectangle to be invalidated.
//
CalculateInvalidationRect();
//
// Draw the selection rectangle
//
DrawRect();
}
void T126Obj::UnselectDrawingObject(void)
{
//
// Erase selection rect
//
DrawRect();
if(GraphicTool() == TOOLTYPE_REMOTEPOINTER && GetOwnerID() != GET_NODE_ID_FROM_MEMBER_ID(g_MyMemberID))
{
return;
}
ClearSelectionFlags();
//
// Don't even bother sending selection changes if we were deleted
// or if this was a remote that unselected us.
//
if(WasDeletedLocally() || WasSelectedRemotely())
{
return;
}
ResetAttrib();
SetViewState(unselected_chosen);
//
// We are going to send a new view state, mark it as edited locally
//
EditedLocally();
//
// Sends the change in the view state to the other nodes
//
OnObjectEdit();
ClearEditionFlags();
}
void T126Obj::DrawRect(void)
{
if(GraphicTool() == TOOLTYPE_REMOTEPOINTER)
{
return;
}
RECT rect;
GetBoundsRect(&rect);
::DrawFocusRect(g_pDraw->m_hDCCached,&rect);
}
void T126Obj::SelectedLocally(void)
{
m_bSelectedLocally = TRUE;
m_bSelectedRemotely = FALSE;
SetViewState(selected_chosen);
//
// We are going to send a new view state, mark it as edited locally
//
EditedLocally();
ResetAttrib();
ChangedViewState();
//
// Sends the change in the view state to the other nodes
//
OnObjectEdit();
}
void T126Obj::SelectedRemotely(void)
{
m_bSelectedLocally = FALSE;
m_bSelectedRemotely = TRUE;
SetViewState(selected_chosen);
}
void T126Obj::MoveBy(LONG x , LONG y)
{
//
// Erase the old one
//
if(GraphicTool() == TOOLTYPE_REMOTEPOINTER)
{
UnDraw();
}
DrawRect();
RECT rect;
if(GraphicTool() == TOOLTYPE_PEN || GraphicTool() == TOOLTYPE_HIGHLIGHT)
{
GetBoundsRect(&rect);
}
else
{
GetRect(&rect);
}
::OffsetRect(&rect, x, y);
if(GraphicTool() == TOOLTYPE_PEN || GraphicTool() == TOOLTYPE_HIGHLIGHT)
{
SetBoundsRect(&rect);
}
else
{
SetRect(&rect);
}
POINT anchorPoint;
GetAnchorPoint(&anchorPoint);
SetAnchorPoint(anchorPoint.x + x ,anchorPoint.y + y);
//
// Draw the new one
//
if(GraphicTool() == TOOLTYPE_REMOTEPOINTER)
{
Draw();
}
DrawRect();
CalculateInvalidationRect();
}
void T126Obj::CalculateInvalidationRect(void)
{
RECT rect;
UINT penThickness = GetPenThickness();
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 ));
GetBoundsRect(&rect);
::UnionRect(&g_pDraw->m_selectorRect,&g_pDraw->m_selectorRect,&rect);
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 ));
}
//
// Checks object for an actual overlap with pRectHit. This
// function assumes that the boundingRect has already been
// compared with pRectHit.
//
BOOL T126Obj::RectangleHit(BOOL borderHit, LPCRECT pRectHit)
{
RECT rectEdge;
RECT rectHit;
RECT rect;
//
// If we are filled do the simple thing
//
if(!borderHit)
{
POINT point;
point.x = (pRectHit->left + pRectHit->right) / 2;
point.y = (pRectHit->top + pRectHit->bottom) / 2;
if(PointInBounds(point))
{
return TRUE;
}
}
GetRect(&rect);
NormalizeRect(&rect);
// check left edge
rectEdge.left = rect.left - GetPenThickness()/2;
rectEdge.top = rect.top - GetPenThickness()/2;
rectEdge.right = rect.left + GetPenThickness()/2 ;
rectEdge.bottom = rect.bottom + GetPenThickness()/2;
if (::IntersectRect(&rectHit, &rectEdge, pRectHit))
return( TRUE );
// check right edge
rectEdge.left = rect.right - GetPenThickness()/2;
rectEdge.right = rect.right + GetPenThickness()/2;
if (::IntersectRect(&rectHit, &rectEdge, pRectHit))
return( TRUE );
// check top edge
rectEdge.left = rect.left;
rectEdge.right = rect.right;
rectEdge.top = rect.top - GetPenThickness()/2;
rectEdge.bottom = rect.top + GetPenThickness()/2;
if (::IntersectRect(&rectHit, &rectEdge, pRectHit))
return( TRUE );
// check bottom edge
rectEdge.top = rect.bottom - GetPenThickness()/2;
rectEdge.bottom = rect.bottom + GetPenThickness()/2;
if (::IntersectRect(&rectHit, &rectEdge, pRectHit))
return( TRUE );
return( FALSE );
}
void T126Obj::SetAnchorPoint(LONG x, LONG y)
{
if(m_anchorPoint.x != x || m_anchorPoint.y != y)
{
ChangedAnchorPoint();
m_anchorPoint.x = x;
m_anchorPoint.y = y;
}
}
void T126Obj::SetZOrder(ZOrder zorder)
{
m_zOrder = zorder;
ChangedZOrder();
}
#define ARRAY_INCREMENT 0x200
DCDWordArray::DCDWordArray()
{
MLZ_EntryOut(ZONE_FUNCTION, "DCDWordArray::DCDWordArray");
m_Size = 0;
m_MaxSize = ARRAY_INCREMENT;
DBG_SAVE_FILE_LINE
m_pData = new POINT[ARRAY_INCREMENT];
ASSERT(m_pData);
}
DCDWordArray::~DCDWordArray()
{
MLZ_EntryOut(ZONE_FUNCTION, "DCDWordArray::~DCDWordArray");
delete[] m_pData;
}
//
// We need to increase the size of the array
//
BOOL DCDWordArray::ReallocateArray(void)
{
POINT *pOldArray = m_pData;
DBG_SAVE_FILE_LINE
m_pData = new POINT[m_MaxSize];
ASSERT(m_pData);
if(m_pData)
{
TRACE_DEBUG((">>>>>Increasing size of array to hold %d points", m_MaxSize));
// copy new data from old
memcpy( m_pData, pOldArray, (m_Size) * sizeof(POINT));
TRACE_DEBUG(("Deleting array of points %x", pOldArray));
delete[] pOldArray;
return TRUE;
}
else
{
m_pData = pOldArray;
return FALSE;
}
}
//
// Add a new point to the array
//
void DCDWordArray::Add(POINT point)
{
MLZ_EntryOut(ZONE_FUNCTION, "DCDWordArray::Add");
TRACE_DEBUG(("Adding point(%d,%d) at %d", point.x, point.y, m_Size));
TRACE_DEBUG(("Adding point at %x", &m_pData[m_Size]));
if(m_pData == NULL)
{
return;
}
m_pData[m_Size].x = point.x;
m_pData[m_Size].y = point.y;
m_Size++;
//
// if we want more points, we need to re allocate the array
//
if(m_Size == m_MaxSize)
{
m_MaxSize +=ARRAY_INCREMENT;
if(ReallocateArray() == FALSE)
{
m_Size--;
}
}
}
//
// Return the number of points in the array
//
UINT DCDWordArray::GetSize(void)
{
return m_Size;
}
//
// Sets the size of the array
//
void DCDWordArray::SetSize(UINT size)
{
int newSize;
//
// if we want more points, we need to re allocate the array
//
if (size > m_MaxSize)
{
m_MaxSize= ((size/ARRAY_INCREMENT)+1)*ARRAY_INCREMENT;
if(ReallocateArray() == FALSE)
{
return;
}
}
m_Size = size;
}
void T126Obj::SetPenThickness(UINT penThickness)
{
m_penThickness = penThickness;
ChangedPenThickness();
}
void T126Obj::GotGCCHandle(ULONG gccHandle)
{
//
// Save this objects handle
//
SetThisObjectHandle(gccHandle);
//
// It was created locally
//
CreatedLocally();
switch(GetType())
{
//
// New drawing requested a unique handle
//
case(bitmapCreatePDU_chosen):
case(drawingCreatePDU_chosen):
{
WorkspaceObj * pWorkspace = GetWorkspace(GetWorkspaceHandle());
if(pWorkspace && !pWorkspace->IsObjectInWorkspace(this))
{
//
// Add a this drawing to the correct workspace
//
if(!AddT126ObjectToWorkspace(this))
{
return;
}
}
break;
}
//
// New workspace requested a unique handle
//
case(workspaceCreatePDU_chosen):
{
//
// Save this objects handle
//
SetViewHandle(gccHandle + 1);
SetWorkspaceHandle(gccHandle);
if(!IsWorkspaceListed(this))
{
AddNewWorkspace((WorkspaceObj*) this);
}
break;
}
}
//
// Send it to T126 apps
//
SendNewObjectToT126Apps();
}
//
// Create the nonstandard pdu header
//
void CreateNonStandardPDU(NonStandardParameter * sipdu, LPSTR NonStandardString)
{
PT126_VENDORINFO vendorInfo;
sipdu->nonStandardIdentifier.choice = h221nonStandard_chosen;
vendorInfo = (PT126_VENDORINFO) &sipdu->nonStandardIdentifier.u.h221nonStandard.value;
vendorInfo->bCountryCode = USA_H221_COUNTRY_CODE;
vendorInfo->bExtension = USA_H221_COUNTRY_EXTENSION;
vendorInfo->wManufacturerCode = MICROSOFT_H_221_MFG_CODE;
lstrcpy((LPSTR)&vendorInfo->nonstandardString,NonStandardString);
sipdu->nonStandardIdentifier.u.h221nonStandard.length = sizeof(T126_VENDORINFO) -sizeof(vendorInfo->nonstandardString) + lstrlen(NonStandardString);
sipdu->data.value = NULL;
}
void TimeToGetGCCHandles(ULONG numberOfGccHandles)
{
TRACE_MSG(("Using GCC Tank %d ", g_iGCCHandleIndex));
TRACE_MSG(("GCC Tank 0 has %d GCC handles ", g_GCCPreallocHandles[0].GccHandleCount));
TRACE_MSG(("GCC Tank 1 has %d GCC handles ", g_GCCPreallocHandles[1].GccHandleCount));
//
// If we have half a tank of GCC handles, it is time to fill up the spare tank
//
if(g_GCCPreallocHandles[g_iGCCHandleIndex].GccHandleCount <= PREALLOC_GCC_HANDLES / 2 &&
g_GCCPreallocHandles[g_iGCCHandleIndex ? 0 : 1].GccHandleCount == 0 &&
!g_WaitingForGCCHandles)
{
TRACE_MSG(("GCC Tank %d is half full, time to get more GCC handles", g_iGCCHandleIndex));
g_pNMWBOBJ->AllocateHandles(numberOfGccHandles);
g_WaitingForGCCHandles = TRUE;
}
//
// If we ran out of handles, it is time to switch tanks
//
if(g_GCCPreallocHandles[g_iGCCHandleIndex].GccHandleCount == 0)
{
TRACE_MSG(("GCC Tank %d is empty, switching to other GCC tank", g_iGCCHandleIndex));
g_iGCCHandleIndex = g_iGCCHandleIndex ? 0 : 1;
}
}