// // 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); }