WindowsXP-SP1/enduser/netmeeting/ui/msconfwb/user.cpp
2020-09-30 16:53:49 +02:00

859 lines
20 KiB
C++

//
// USER.CPP
// User Class Members
//
// Copyright Microsoft 1998-
//
// PRECOMP
#include "precomp.h"
//
// Local macros
//
#define ASSERT_LOCAL_USER() ASSERT(IsLocalUser() == TRUE);
//
// Init()
// This could fail...
//
BOOL WbUser::Init(POM_OBJECT hUser)
{
ASSERT(hUser != NULL);
m_hPageCurrent = WB_PAGE_HANDLE_NULL;
m_zoomed = FALSE;
m_hUser = hUser;
m_pRemotePointer = new DCWbGraphicPointer(this);
if (!m_pRemotePointer)
{
ERROR_OUT(("WbUser::Init - failed to create m_pRemotePointer"));
return(FALSE);
}
Refresh();
return(TRUE);
}
//
//
// Function: ~WbUser
//
// Purpose: Destructor
//
//
WbUser::~WbUser(void)
{
// don't leave any loose ends
if ((g_pMain != NULL) && (g_pMain->GetLockOwner() == this))
{
g_pMain->SetLockOwner(NULL);
g_pMain->UpdateWindowTitle();
}
// Free the remote pointer
if (m_pRemotePointer != NULL)
{
delete m_pRemotePointer;
m_pRemotePointer = NULL;
}
}
//
//
// Function: Refresh
//
// Purpose: Read the user details and copy them to member variables.
//
//
void WbUser::Refresh(void)
{
MLZ_EntryOut(ZONE_FUNCTION, "WbUser::Refresh");
ASSERT(m_pRemotePointer);
// Set the flag indicating whether this is the local user
POM_OBJECT hLocalUser;
g_pwbCore->WBP_PersonHandleLocal(&hLocalUser);
m_bLocalUser = (m_hUser == hLocalUser);
// Read the external data
WB_PERSON userDetails;
UINT uiReturn = g_pwbCore->WBP_GetPersonData(m_hUser, &userDetails);
if (uiReturn != 0)
{
DefaultExceptionHandler(WBFE_RC_WB, uiReturn);
return;
}
// Get the user name
lstrcpy(m_strName, userDetails.personName);
// Get the sync flag
m_bSynced = (userDetails.synced != FALSE);
// Get the current page
m_hPageCurrent = userDetails.currentPage;
// Get the current position in the page
m_rectVisible.left = userDetails.visibleRect.left;
m_rectVisible.right = userDetails.visibleRect.right;
m_rectVisible.top = userDetails.visibleRect.top;
m_rectVisible.bottom = userDetails.visibleRect.bottom;
// Get the pointer active flag. We go directly to the member variable
// here since the SetActive member of the pointer class would re-write
// the user information.
m_pRemotePointer->m_bActive = (userDetails.pointerActive != 0);
// Get the pointer page
m_pRemotePointer->SetPage(userDetails.pointerPage);
// Get the pointer position
m_pRemotePointer->MoveTo(userDetails.pointerPos.x, userDetails.pointerPos.y);
// Get the color
m_color = g_ColorTable[userDetails.colorId % NUM_COLOR_ENTRIES];
// Set the pointer color
m_pRemotePointer->SetColor(m_color);
}
//
// Function: Update
//
// Purpose: Update the external copy of the user information
//
void WbUser::Update()
{
MLZ_EntryOut(ZONE_FUNCTION, "WbUser::Update");
// Can only update if we are the local user
ASSERT_LOCAL_USER();
ASSERT(m_pRemotePointer);
// Get the local user details
WB_PERSON userDetails;
UINT uiReturn;
uiReturn = g_pwbCore->WBP_GetPersonData(m_hUser, &userDetails);
if (uiReturn != 0)
{
DefaultExceptionHandler(WBFE_RC_WB, uiReturn);
return;
}
// Don't update the name
// Set the sync flag
userDetails.synced = (m_bSynced != FALSE);
// Set the pointer active flag
userDetails.pointerActive = (m_pRemotePointer->IsActive() != FALSE);
// Set the page handle for the current page
userDetails.currentPage = m_hPageCurrent;
// Set the current position in the page
userDetails.visibleRect.left = (short)m_rectVisible.left;
userDetails.visibleRect.right = (short)m_rectVisible.right;
userDetails.visibleRect.top = (short)m_rectVisible.top;
userDetails.visibleRect.bottom = (short)m_rectVisible.bottom;
// Set the pointer page
userDetails.pointerPage = m_pRemotePointer->Page();
// Set the pointer position within the page
POINT pointerPos;
m_pRemotePointer->GetPosition(&pointerPos);
userDetails.pointerPos.x = (short)pointerPos.x;
userDetails.pointerPos.y = (short)pointerPos.y;
// Don't update the color
// Write the user details back to the core
uiReturn = g_pwbCore->WBP_SetLocalPersonData(&userDetails);
if (uiReturn != 0)
{
// Throw exception
DefaultExceptionHandler(WBFE_RC_WB, uiReturn);
return;
}
}
//
//
// Function: PutSyncPosition
//
// Purpose: Write the sync position from the current position of this
// user.
//
//
void WbUser::PutSyncPosition(void)
{
MLZ_EntryOut(ZONE_FUNCTION, "WbUser::PutSyncPosition");
// Set up a sync object
WB_SYNC sync;
sync.length = sizeof(WB_SYNC);
sync.currentPage = m_hPageCurrent;
sync.visibleRect.top = (short)m_rectVisible.top;
sync.visibleRect.left = (short)m_rectVisible.left;
sync.visibleRect.bottom = (short)m_rectVisible.bottom;
sync.visibleRect.right = (short)m_rectVisible.right;
sync.zoomed = (TSHR_UINT16)m_zoomed;
sync.dataOffset = (TSHR_UINT16)((BYTE *)&(sync.currentPage) - (BYTE *)&sync);
UINT uiReturn = g_pwbCore->WBP_SyncPositionUpdate(&sync);
if (uiReturn != 0)
{
// Throw an exception
DefaultExceptionHandler(WBFE_RC_WB, uiReturn);
return;
}
}
//
//
// Function: GetSyncPosition
//
// Purpose: Get the position at which this user should be to
// account for the current sync information. This function
// assumes that there is a valid sync position available.
//
//
void WbUser::GetSyncPosition(void)
{
MLZ_EntryOut(ZONE_FUNCTION, "WbUser::GetSyncPosition");
// Get the current sync position
WB_SYNC sync;
UINT uiReturn = g_pwbCore->WBP_SyncPositionGet(&sync);
if (uiReturn != 0)
{
// Throw an exception
DefaultExceptionHandler(WBFE_RC_WB, uiReturn);
return;
}
TRACE_DEBUG(("Sync page handle = %d", sync.currentPage));
// If the sync page is not valid, do nothing
if (sync.currentPage != WB_PAGE_HANDLE_NULL)
{
// Get the current sync position
m_hPageCurrent = sync.currentPage;
// Now calculate the new visible rectangle
RECT rectSyncUser;
rectSyncUser.left = sync.visibleRect.left;
rectSyncUser.top = sync.visibleRect.top;
rectSyncUser.right = sync.visibleRect.right;
rectSyncUser.bottom = sync.visibleRect.bottom;
// Check the y position of the visible rectangles
if ((rectSyncUser.bottom - rectSyncUser.top) <= (m_rectVisible.bottom - m_rectVisible.top))
{
// The sync rectangle's height is smaller than our visible rectangle's
if (rectSyncUser.top < m_rectVisible.top)
{
::OffsetRect(&m_rectVisible, 0, rectSyncUser.top - m_rectVisible.top);
}
else if (rectSyncUser.bottom > m_rectVisible.bottom)
{
::OffsetRect(&m_rectVisible, 0, rectSyncUser.bottom - m_rectVisible.bottom);
}
}
else
{
// The sync rectangle is bigger than ours
if (rectSyncUser.top > m_rectVisible.top)
{
::OffsetRect(&m_rectVisible, 0, rectSyncUser.top - m_rectVisible.top);
}
else if (rectSyncUser.bottom < m_rectVisible.bottom)
{
::OffsetRect(&m_rectVisible, 0, rectSyncUser.bottom - m_rectVisible.bottom);
}
}
if ((rectSyncUser.right - rectSyncUser.left) <= (m_rectVisible.right - m_rectVisible.left))
{
// The sync rectangle's width is smaller than our visible rectangle's
if (rectSyncUser.left < m_rectVisible.left)
{
::OffsetRect(&m_rectVisible, rectSyncUser.left - m_rectVisible.left, 0);
}
else if (rectSyncUser.right > m_rectVisible.right)
{
::OffsetRect(&m_rectVisible, rectSyncUser.right - m_rectVisible.right, 0);
}
}
else
{
// The sync rectangle is bigger than ours
if (rectSyncUser.left > m_rectVisible.left)
{
::OffsetRect(&m_rectVisible, rectSyncUser.left - m_rectVisible.left, 0);
}
else if (rectSyncUser.right < m_rectVisible.right)
{
::OffsetRect(&m_rectVisible, rectSyncUser.right - m_rectVisible.right, 0);
}
}
m_zoomed = sync.zoomed;
}
}
//
//
// Function: Sync
//
// Purpose: Sync the local user. The page and point passed as parameters
// are used as the current sync position only if there is no
// current sync position determined by another user.
//
//
void WbUser::Sync(void)
{
MLZ_EntryOut(ZONE_FUNCTION, "WbUser::Sync");
ASSERT_LOCAL_USER();
ASSERT(m_pRemotePointer);
// Determine whether any other users are currently synced
WbUser* pUser = WB_GetFirstUser();
while (pUser != NULL)
{
// If this user is synced, we are done
if (pUser->IsSynced())
{
break;
}
// Try the next user
pUser = WB_GetNextUser(pUser);
}
// If we found a synced user, and we don't have the contents lock
if ( (pUser != NULL)
&& (!WB_GotContentsLock()))
{
// Get the sync position from the core
GetSyncPosition();
}
else
{
// Set the sync position from our own position
PutSyncPosition();
}
// Update the synced member flag
m_bSynced = TRUE;
// Write the user details back to the core
Update();
}
//
//
// Function: Unsync
//
// Purpose: Unsynchronize the users page from other synced users
//
//
void WbUser::Unsync(void)
{
MLZ_EntryOut(ZONE_FUNCTION, "WbUser::Unsync");
ASSERT_LOCAL_USER();
// Update the local member
m_bSynced = FALSE;
// Update the external details
Update();
}
//
//
// Function: PutPointer
//
// Purpose: Turn on the user's remote pointer
//
//
void WbUser::PutPointer(WB_PAGE_HANDLE hPage, POINT point)
{
MLZ_EntryOut(ZONE_FUNCTION, "WbUser::PutPointer");
// Check that we are the local user (we cannot do the update if we are not)
ASSERT_LOCAL_USER();
ASSERT(m_pRemotePointer);
m_pRemotePointer->SetActive(hPage, point);
}
//
//
// Function: RemovePointer
//
// Purpose: Turn off the user's remote pointer
//
//
void WbUser::RemovePointer(void)
{
MLZ_EntryOut(ZONE_FUNCTION, "WbUser::RemovePointer");
// Check that we are the local user (we cannot do the update if we are not)
ASSERT_LOCAL_USER();
// Update the remote pointer members
ASSERT(m_pRemotePointer);
m_pRemotePointer->m_bActive = FALSE;
m_pRemotePointer->m_hPage = WB_PAGE_HANDLE_NULL;
// Update the external user information
Update();
}
//
// Function: IsUsingPointer()
//
BOOL WbUser::IsUsingPointer(void) const
{
ASSERT(m_pRemotePointer);
return(m_pRemotePointer->IsActive());
}
//
// Function: PointerPage()
//
WB_PAGE_HANDLE WbUser::PointerPage(void) const
{
ASSERT(m_pRemotePointer);
return(m_pRemotePointer->Page());
}
//
// Function: GetPointerPosition()
//
void WbUser::GetPointerPosition(LPPOINT lpptPos)
{
ASSERT(m_pRemotePointer);
m_pRemotePointer->GetPosition(lpptPos);
}
//
//
// Function: SetPage
//
// Purpose: Set the user's current page
//
//
void WbUser::SetPage(WB_PAGE_HANDLE hPage)
{
MLZ_EntryOut(ZONE_FUNCTION, "WbUser::Page");
// Check that we are the local user (we cannot do the update if we are not)
ASSERT_LOCAL_USER();
// Only make the update if it is a change
if (m_hPageCurrent != hPage)
{
// Update the local member
m_hPageCurrent = hPage;
// Update the external information
Update();
}
}
//
//
// Function: CurrentPosition
//
// Purpose: Set the user's current position
//
//
void WbUser::SetVisibleRect(LPCRECT lprcVisible)
{
MLZ_EntryOut(ZONE_FUNCTION, "WbUser::SetVisibleRect");
// Check that we are the local user (we cannot do the update if we are not)
ASSERT_LOCAL_USER();
// Only make the update if it is a change
if (!::EqualRect(&m_rectVisible, lprcVisible))
{
// Update the local member
m_rectVisible = *lprcVisible;
// Update the external information
Update();
}
}
//
//
// Function: operator==
//
// Purpose: Return TRUE if the specified user is the same as this user
//
//
BOOL WbUser::operator==(const WbUser& user) const
{
return (m_hUser == user.m_hUser);
}
//
//
// Function: operator!=
//
// Purpose: Return FALSE if the specified user is the same as this user
//
//
BOOL WbUser::operator!=(const WbUser& user) const
{
return (!((*this) == user));
}
//
//
// Function: operator=
//
// Purpose: Copy the specified user to this one
//
//
WbUser& WbUser::operator=(const WbUser& user)
{
// Save the new handles
m_hUser = user.m_hUser;
// Read the details
Refresh();
return (*this);
}
//
//
// Function: HasContentsLock
//
// Purpose: Check whether this user has the whiteboard contents lock
//
//
BOOL WbUser::HasContentsLock(void) const
{
// call the core to find out if we have the lock
return (WB_LockUser() == this);
}
//
//
// Function: WbUserList::Clear
//
// Purpose: Clear the user handle map, removing all user objects
//
//
void WbUserList::Clear(void)
{
// Delete all the user objects in the user map
WbUser* pUser;
POM_OBJECT hUser;
ASSERT(g_pUsers);
POSITION position = g_pUsers->GetHeadPosition();
while (position)
{
POSITION posSav = position;
pUser = (WbUser*)g_pUsers->GetNext(position);
if (pUser != NULL)
{
delete pUser;
}
g_pUsers->RemoveAt(posSav);
}
// Remove all the map entries
EmptyList();
}
//
//
// Function: ~WbUserList
//
// Purpose: Destructor
//
//
WbUserList::~WbUserList(void)
{
// Delete all the user objects in the user map
Clear();
}
//
//
// Function: LockUser
//
// Purpose: Return a user object showing who has the lock
//
//
WbUser* WB_LockUser(void)
{
MLZ_EntryOut(ZONE_FUNCTION, "WB_LockUser");
// Get the lock status from the core (cannot fail)
POM_OBJECT hLockUser;
WB_LOCK_TYPE lockType;
lockType = g_pwbCore->WBP_LockStatus(&hLockUser);
// Build a result
WbUser* pUserResult = NULL;
if (lockType != WB_LOCK_TYPE_NONE)
{
pUserResult = WB_GetUser(hLockUser);
}
return pUserResult;
}
//
//
// Function: Locked
//
// Purpose: Return TRUE if another user has a lock (contents or page).
// NOTE that the page order lock implies the contents are
// locked.
//
//
BOOL WB_Locked(void)
{
POM_OBJECT pLockUser;
return ( (g_pwbCore->WBP_LockStatus(&pLockUser) != WB_LOCK_TYPE_NONE)
&& (WB_LocalUser() != WB_LockUser()));
}
//
//
// Function: ContentsLocked
//
// Purpose: Return TRUE if another user has the contents lock
//
//
BOOL WB_ContentsLocked(void)
{
POM_OBJECT pLockUser;
return ( (g_pwbCore->WBP_LockStatus(&pLockUser) == WB_LOCK_TYPE_CONTENTS)
&& (WB_LocalUser() != WB_LockUser()));
}
//
//
// Function: GotLock
//
// Purpose: Return TRUE if the local user has a lock
//
//
BOOL WB_GotLock(void)
{
POM_OBJECT pLockUser;
return ( (g_pwbCore->WBP_LockStatus(&pLockUser) != WB_LOCK_TYPE_NONE)
&& (WB_LocalUser() == WB_LockUser()));
}
//
//
// Function: GotContentsLock
//
// Purpose: Return TRUE if the local user has the contents lock
//
//
BOOL WB_GotContentsLock(void)
{
POM_OBJECT pLockUser;
return ( (g_pwbCore->WBP_LockStatus(&pLockUser) == WB_LOCK_TYPE_CONTENTS)
&& (WB_LocalUser() == WB_LockUser()));
}
//
//
// Function: PresentationMode
//
// Purpose: Return TRUE if the whiteboard is in presentation mode, i.e.
// another user has the contents lock, and is synced.
//
//
BOOL WB_PresentationMode(void)
{
return ( (WB_ContentsLocked())
&& (WB_LockUser() != NULL)
&& (WB_LockUser()->IsSynced()));
}
//
//
// Function: GetUser
//
// Purpose: Return a pointer to a user object from a user handle
//
//
WbUser* WB_GetUser(POM_OBJECT hUser)
{
MLZ_EntryOut(ZONE_FUNCTION, "WB_GetFirstUser");
// Set up a return value
WbUser* pUserResult = NULL;
// if the user handle is null, we return a null object pointer
if (hUser != NULL)
{
// Look the user up in the internal map
ASSERT(g_pUsers);
POSITION position = g_pUsers->GetHeadPosition();
BOOL bFound = FALSE;
while (position)
{
pUserResult = (WbUser*)g_pUsers->GetNext(position);
if (hUser == pUserResult->Handle())
{
return pUserResult;
}
}
// The user is not yet in our map
pUserResult = new WbUser();
if (!pUserResult)
{
ERROR_OUT(("Couldn't allocate user object for 0x%08x", hUser));
}
else
{
if (!pUserResult->Init(hUser))
{
ERROR_OUT(("Couldn't init user object for 0x%08x", hUser));
delete pUserResult;
pUserResult = NULL;
}
else
{
// Add the new user to the internal map
g_pUsers->AddTail(pUserResult);
}
}
}
return pUserResult;
}
//
//
// Function: GetFirstUser
//
// Purpose: Return the first user in the call
//
//
WbUser* WB_GetFirstUser(void)
{
MLZ_EntryOut(ZONE_FUNCTION, "WB_GetFirstUser");
// Get the handle of the first user (cannot fail)
POM_OBJECT hUser;
g_pwbCore->WBP_PersonHandleFirst(&hUser);
// Get a pointer to the user object for this handle
WbUser* pUser = WB_GetUser(hUser);
return pUser;
}
//
//
// Function: GetNextUser
//
// Purpose: Return the next user in the call
//
//
WbUser* WB_GetNextUser(const WbUser* pUser)
{
MLZ_EntryOut(ZONE_FUNCTION, "WB_GetNextUser");
ASSERT(pUser != NULL);
// Get the handle of the next user
POM_OBJECT hNextUser;
UINT uiReturn = g_pwbCore->WBP_PersonHandleNext(pUser->Handle(),
&hNextUser);
WbUser* pUserResult = NULL;
if (uiReturn == 0)
{
pUserResult = WB_GetUser(hNextUser);
}
return pUserResult;
}
//
//
// Function: LocalUser
//
// Purpose: Return an object representing the local user
//
//
WbUser* WB_LocalUser(void)
{
MLZ_EntryOut(ZONE_FUNCTION, "WB_LocalUser");
// Get the local user handle (cannot fail)
POM_OBJECT hUser;
g_pwbCore->WBP_PersonHandleLocal(&hUser);
return WB_GetUser(hUser);
}