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.
 
 
 
 
 
 

953 lines
24 KiB

#include "precomp.h"
//
// USR.CPP
// Update Sender/Receiver
//
// Copyright(c) Microsoft 1997-
//
#define MLZ_FILE_ZONE ZONE_NET
//
// USR strategy when network packets cannot be allocated.
//
// The USR sends three different types of packets:
//
// - font negotiation packets
// - order packets
// - screen data packets
//
// Font negotiation packets are sent by the USR_Periodic function. If the
// packet cannot be sent first time then the USR will retry (on each call
// to the USR_Periodic function) until it has succesfully sent the packet.
// The only dependency on font packets is that until the systems in a share
// have been able to exchange font negotiation packets they will not be
// able to send text output as orders - they will simply send text as
// screen data.
//
// The USR function UP_SendUpdates sends all update packets (both order
// packets and screen data packets). Order packets must be sent first and
// screen data packets are only sent if all the orders have been
// succesfully sent. When sending screen data packets they are only sent
// if the corresponding palette packets have been sent - otherwise they are
// re-absorbed into the screen data to be transmitted later.
//
//
//
// USR_ShareStarting()
// Creates share resources
//
BOOL ASShare::USR_ShareStarting(void)
{
BOOL rc = FALSE;
BITMAPINFOHEADER bitmapInfo;
HDC hdcDesktop = NULL;
DebugEntry(ASShare::USR_ShareStarting);
//
// Set the black bitmap data and hatch bitmap data flags which can be
// used as an aid for debugging. These are false unless there is an
// entry in the ini file to override them.
//
COM_ReadProfInt(DBG_INI_SECTION_NAME, USR_INI_HATCHSCREENDATA, FALSE,
&m_usrHatchScreenData);
COM_ReadProfInt(DBG_INI_SECTION_NAME, USR_INI_HATCHBMPORDERS, FALSE,
&m_usrHatchBitmaps);
//
// Double-check the order packet sizes are OK
//
ASSERT(SMALL_ORDER_PACKET_SIZE < LARGE_ORDER_PACKET_SIZE);
ASSERT(LARGE_ORDER_PACKET_SIZE <= TSHR_MAX_SEND_PKT);
//
// Allocate a chunk of memory big enough to contain the largest packet
// an application can receive from the network. This is required to
// store uncompressed bitmaps and repeated general use by the USR.
//
m_usrPBitmapBuffer = new BYTE[TSHR_MAX_SEND_PKT];
if (!m_usrPBitmapBuffer)
{
ERROR_OUT(("USR_ShareStarted: failed to alloc memory m_usrPBitmapBuffer"));
//
// To continue the share would cause a GP fault as soon as anything
// tries to use this buffer so delete this person from the share.
// The reason is lack of resources.
//
DC_QUIT;
}
//
// Create the transfer bitmaps for screen data and bitmap orders
//
USR_InitDIBitmapHeader(&bitmapInfo, g_usrScreenBPP);
//
// Create the transfer bitmaps. These are used for both outgoing and
// incoming data.
//
// To avoid having to recreate the bitmaps whenever the parties in the
// share change, (and hence the various bpp may change) from r2.0 we
// now use a fixed vertical size and if necessary can handle incoming
// bitmaps in multiple bands.
//
// These are the resulting heights for 256 pixel wide segments.
//
// TSHR_MAX_SEND_PKT - sizeof(DATAPACKETHEADER) / bytes per scan line
//
// 4bpp --> (32000 - 4) / 128 = 249
// 8bpp --> (32000 - 4) / 256 = 124
// 24bpp --> (32000 - 4) / 768 = 41
//
//
//
// NOTE:
// The VGA driver has a problem when the bitmap ends exactly on a 4K
// (page) boundary. So we create the bitmaps one pixel taller.
//
// BOGUS BUGBUG LAURABU
// Is this really true anymore? If not, save some memory and make these
// the right size.
//
hdcDesktop = GetDC(NULL);
if (!hdcDesktop)
{
ERROR_OUT(("USR_ShareStarting: can't get screen DC"));
DC_QUIT;
}
// The large bitmap is short. The rest are medium height.
bitmapInfo.biWidth = 1024;
bitmapInfo.biHeight = MaxBitmapHeight(MEGA_WIDE_X_SIZE, 8) + 1;
m_usrBmp1024 = CreateDIBitmap(hdcDesktop, &bitmapInfo, 0, NULL, NULL,
DIB_RGB_COLORS);
if (!m_usrBmp1024)
{
ERROR_OUT(("USR_ShareStarting: failed to reate m_usrBmp1024"));
DC_QUIT;
}
bitmapInfo.biHeight = MaxBitmapHeight(MEGA_X_SIZE, 8) + 1;
bitmapInfo.biWidth = 256;
m_usrBmp256 = CreateDIBitmap(hdcDesktop, &bitmapInfo, 0, NULL, NULL,
DIB_RGB_COLORS);
if (!m_usrBmp256)
{
ERROR_OUT(("USR_ShareStarting: failed to create m_usrBmp256"));
DC_QUIT;
}
bitmapInfo.biWidth = 128;
m_usrBmp128 = CreateDIBitmap(hdcDesktop, &bitmapInfo, 0, NULL, NULL,
DIB_RGB_COLORS);
if (!m_usrBmp128)
{
ERROR_OUT(("USR_ShareStarting: failed to create m_usrBmp128"));
DC_QUIT;
}
bitmapInfo.biWidth = 112;
m_usrBmp112 = CreateDIBitmap(hdcDesktop, &bitmapInfo, 0, NULL, NULL,
DIB_RGB_COLORS);
if (!m_usrBmp112)
{
ERROR_OUT(("USR_ShareStarting: failed to create m_usrBmp112"));
DC_QUIT;
}
bitmapInfo.biWidth = 96;
m_usrBmp96 = CreateDIBitmap(hdcDesktop, &bitmapInfo, 0, NULL, NULL,
DIB_RGB_COLORS);
if (!m_usrBmp96)
{
ERROR_OUT(("USR_ShareStarting: failed to create m_usrBmp96"));
DC_QUIT;
}
bitmapInfo.biWidth = 80;
m_usrBmp80 = CreateDIBitmap(hdcDesktop, &bitmapInfo, 0, NULL, NULL,
DIB_RGB_COLORS);
if (!m_usrBmp80)
{
ERROR_OUT(("USR_ShareStarting: failed to create m_usrBmp80"));
DC_QUIT;
}
bitmapInfo.biWidth = 64;
m_usrBmp64 = CreateDIBitmap(hdcDesktop, &bitmapInfo, 0, NULL, NULL,
DIB_RGB_COLORS);
if (!m_usrBmp64)
{
ERROR_OUT(("USR_ShareStarting: failed to create m_usrBmp64"));
DC_QUIT;
}
bitmapInfo.biWidth = 48;
m_usrBmp48 = CreateDIBitmap(hdcDesktop, &bitmapInfo, 0, NULL, NULL,
DIB_RGB_COLORS);
if (!m_usrBmp48)
{
ERROR_OUT(("USR_ShareStarting: failed to create m_usrBmp48"));
DC_QUIT;
}
bitmapInfo.biWidth = 32;
m_usrBmp32 = CreateDIBitmap(hdcDesktop, &bitmapInfo, 0, NULL, NULL,
DIB_RGB_COLORS);
if (!m_usrBmp32)
{
ERROR_OUT(("USR_ShareStarting: failed to create m_usrBmp32"));
DC_QUIT;
}
bitmapInfo.biWidth = 16;
m_usrBmp16 = CreateDIBitmap(hdcDesktop, &bitmapInfo, 0, NULL, NULL,
DIB_RGB_COLORS);
if (!m_usrBmp16)
{
ERROR_OUT(("USR_ShareStarting: failed to create m_usrBmp16"));
DC_QUIT;
}
rc = TRUE;
DC_EXIT_POINT:
if (hdcDesktop)
{
ReleaseDC(NULL, hdcDesktop);
}
DebugExitBOOL(ASShare::USR_ShareStarting, rc);
return(rc);
}
//
// USR_ShareEnded()
// Cleans up share resources
//
void ASShare::USR_ShareEnded(void)
{
DebugEntry(ASShare::USR_ShareEnded);
//
// Delete Transfer Bitmaps.
//
if (m_usrBmp1024)
{
DeleteBitmap(m_usrBmp1024);
m_usrBmp1024= NULL;
}
if (m_usrBmp256)
{
DeleteBitmap(m_usrBmp256);
m_usrBmp256 = NULL;
}
if (m_usrBmp128)
{
DeleteBitmap(m_usrBmp128);
m_usrBmp128 = NULL;
}
if (m_usrBmp112)
{
DeleteBitmap(m_usrBmp112);
m_usrBmp112 = NULL;
}
if (m_usrBmp96)
{
DeleteBitmap(m_usrBmp96);
m_usrBmp96 = NULL;
}
if (m_usrBmp80)
{
DeleteBitmap(m_usrBmp80);
m_usrBmp80 = NULL;
}
if (m_usrBmp64)
{
DeleteBitmap(m_usrBmp64);
m_usrBmp64 = NULL;
}
if (m_usrBmp48)
{
DeleteBitmap(m_usrBmp48);
m_usrBmp48 = NULL;
}
if (m_usrBmp32)
{
DeleteBitmap(m_usrBmp32);
m_usrBmp32 = NULL;
}
if (m_usrBmp16)
{
DeleteBitmap(m_usrBmp16);
m_usrBmp16 = NULL;
}
//
// Free Bitmap Buffer.
//
if (m_usrPBitmapBuffer != NULL)
{
delete[] m_usrPBitmapBuffer;
m_usrPBitmapBuffer = NULL;
}
DebugExitVOID(ASShare::USR_ShareEnded);
}
//
// USR_RecalcCaps()
//
// DESCRIPTION:
//
// Enumerates the bitmap capabilities of all parties currently in the
// share, and determines the common capabilities.
//
// PARAMETERS: None.
//
// RETURNS: TRUE if there are good common caps, or false on failure (which
// has the effect of rejecting a new party from joining the share).
//
//
void ASShare::USR_RecalcCaps(BOOL fJoiner)
{
ASPerson * pasT;
UINT capsMaxBPP;
UINT capsMinBPP;
UINT capsSupports4BPP;
UINT capsSupports8BPP;
UINT capsSupports24BPP;
UINT capsOldBPP;
DebugEntry(ASShare::USR_RecalcCaps);
if (!m_pHost)
{
// Nothing to do
DC_QUIT;
}
ValidatePerson(m_pasLocal);
capsOldBPP = m_pHost->m_usrSendingBPP;
//
// Init the caps
//
capsSupports4BPP = m_pasLocal->cpcCaps.screen.capsSupports4BPP;
capsSupports8BPP = m_pasLocal->cpcCaps.screen.capsSupports8BPP;
capsSupports24BPP = m_pasLocal->cpcCaps.screen.capsSupports24BPP;
capsMaxBPP = 0;
capsMinBPP = 0xFFFFFFFF;
for (pasT = m_pasLocal->pasNext; pasT != NULL; pasT = pasT->pasNext)
{
//
// Check the bpps supported.
//
if (pasT->cpcCaps.screen.capsSupports4BPP != CAPS_SUPPORTED)
{
capsSupports4BPP = CAPS_UNSUPPORTED;
}
if (pasT->cpcCaps.screen.capsSupports8BPP != CAPS_SUPPORTED)
{
capsSupports8BPP = CAPS_UNSUPPORTED;
}
if (pasT->cpcCaps.screen.capsSupports24BPP != CAPS_SUPPORTED)
{
capsSupports24BPP = CAPS_UNSUPPORTED;
}
//
// Set the combined bpp to the maximum so far found.
// (If we send data at this bpp then one of the remote systems can
// usefully process this number of colors).
//
capsMaxBPP = max(capsMaxBPP, pasT->cpcCaps.screen.capsBPP);
capsMinBPP = min(capsMinBPP, pasT->cpcCaps.screen.capsBPP);
}
//
// Now figure out what BPP we will transmit at.
//
//
// Limit the combined caps bpp (which is currently the maximum bpp that
// any system in the share wants) to the local bpp, since there is no
// point sending at higher bpp than the local machine has.
//
capsMaxBPP = min(capsMaxBPP, g_usrScreenBPP);
if (!capsMaxBPP)
capsMaxBPP = g_usrScreenBPP;
capsMinBPP = min(capsMinBPP, g_usrScreenBPP);
//
// m_usrSendingBPP is most often going to be 8. So it's easier to assume
// it, then check for cases where it won't be.
//
m_pHost->m_usrSendingBPP = 8;
if ((capsMaxBPP <= 4) && (capsSupports4BPP == CAPS_SUPPORTED))
{
m_pHost->m_usrSendingBPP = 4;
}
else if ((capsMinBPP >= 24) &&
(g_asSettings & SHP_SETTING_TRUECOLOR) &&
(capsSupports24BPP == CAPS_SUPPORTED))
{
m_pHost->m_usrSendingBPP = 24;
}
if (capsOldBPP != m_pHost->m_usrSendingBPP)
{
//
// If switching to/from palettized, we need to update the
// "need to send palette" flag. Note that 4bpp is also a
// palettized color depth.
//
if ((capsOldBPP <= 8) && (m_pHost->m_usrSendingBPP > 8))
m_pHost->m_pmMustSendPalette = FALSE;
else if ((capsOldBPP > 8) && (m_pHost->m_usrSendingBPP <= 8))
m_pHost->m_pmMustSendPalette = TRUE;
#ifdef _DEBUG
if (capsOldBPP == 24)
{
WARNING_OUT(("TRUE COLOR SHARING is now FINISHED"));
}
else if (m_pHost->m_usrSendingBPP == 24)
{
WARNING_OUT(("TRUE COLOR SHARING is now STARTING"));
}
#endif
if (!fJoiner)
{
//
// Sending BPP changed. Repaint all shared stuff.
// NOTE:
// We recalc the sendBPP at three points:
// * When we start to share
// * When a person joins
// * When a person leaves
//
// In the first two cases, shared stuff is repainted,
// so everybody gets the new sendBPP data. Only in the
// leave case do we need to force this.
//
m_pHost->HET_RepaintAll();
}
}
DC_EXIT_POINT:
DebugExitVOID(ASShare::USR_RecalcCaps);
}
//
// USR_HostStarting()
//
BOOL ASHost::USR_HostStarting(void)
{
BOOL rc = FALSE;
HDC hdc;
DebugEntry(ASHost::USR_HostStarting);
//
// Create scratch DC
//
hdc = GetDC(NULL);
if (!hdc)
{
ERROR_OUT(("USR_HostStarting: can't get screen DC"));
DC_QUIT;
}
m_usrWorkDC = CreateCompatibleDC(hdc);
ReleaseDC(NULL, hdc);
if (!m_usrWorkDC)
{
ERROR_OUT(("USR_HostStarting: can't create m_usrWorkDC"));
DC_QUIT;
}
m_pShare->USR_RecalcCaps(TRUE);
rc = TRUE;
DC_EXIT_POINT:
DebugExitBOOL(ASHost::USR_HostStarting, rc);
return(rc);
}
//
// USR_HostEnded()
//
void ASHost::USR_HostEnded(void)
{
DebugEntry(ASHost::USR_HostEnded);
if (m_usrWorkDC != NULL)
{
DeleteDC(m_usrWorkDC);
m_usrWorkDC = NULL;
}
DebugExitVOID(ASHost::USR_HostEnded);
}
//
// USR_ScrollDesktop
//
void ASShare::USR_ScrollDesktop
(
ASPerson * pasPerson,
int xNew,
int yNew
)
{
int xOld;
int yOld;
DebugEntry(ASShare::USR_ScrollDesktop);
ValidateView(pasPerson);
//
// If the origin has changed then do the update.
//
xOld = pasPerson->m_pView->m_dsScreenOrigin.x;
yOld = pasPerson->m_pView->m_dsScreenOrigin.y;
if ((xOld != xNew) || (yOld != yNew))
{
pasPerson->m_pView->m_dsScreenOrigin.x = xNew;
pasPerson->m_pView->m_dsScreenOrigin.y = yNew;
//
// We must ensure that data written to the ScreenBitmap is not
// clipped
//
OD_ResetRectRegion(pasPerson);
//
// Offset the existing bitmap by the change in desktop origins.
//
BitBlt(pasPerson->m_pView->m_usrDC,
0,
0,
pasPerson->cpcCaps.screen.capsScreenWidth,
pasPerson->cpcCaps.screen.capsScreenHeight,
pasPerson->m_pView->m_usrDC,
xNew - xOld,
yNew - yOld,
SRCCOPY);
//
// Offset the shadow cursor pos -- same place on remote screen
// but now different place in VD
//
pasPerson->cmPos.x += xNew - xOld;
pasPerson->cmPos.y += yNew - yOld;
//
// Repaint the view
//
VIEW_InvalidateRgn(pasPerson, NULL);
}
DebugExitVOID(ASShare::USR_ScrollDesktop);
}
//
// FUNCTION: USR_InitDIBitmapHeader
//
// DESCRIPTION:
//
// Initialises a Device Independent bitmap header to be the given bits per
// pel.
//
// PARAMETERS:
//
// pbh - pointer to the bitmap header to be initialised.
// bpp - bpp to be used for the bitmap
//
// RETURNS: VOID
//
//
void ASShare::USR_InitDIBitmapHeader
(
BITMAPINFOHEADER * pbh,
UINT bpp
)
{
DebugEntry(ASShare::USR_InitDIBitmapHeader);
pbh->biSize = sizeof(BITMAPINFOHEADER);
pbh->biPlanes = 1;
pbh->biBitCount = (WORD)bpp;
pbh->biCompression = BI_RGB;
pbh->biSizeImage = 0;
pbh->biXPelsPerMeter = 10000;
pbh->biYPelsPerMeter = 10000;
pbh->biClrUsed = 0;
pbh->biClrImportant = 0;
DebugExitVOID(ASShare::USR_InitDIBitmapHeader);
}
//
// USR_ViewStarting()
//
// Called when someone we're viewing starts to host. We create the desktop
// bitmap for them plus scratch objects
//
BOOL ASShare::USR_ViewStarting(ASPerson * pasPerson)
{
BOOL rc;
DebugEntry(ASShare::USR_ViewStarting);
ValidateView(pasPerson);
//
// Create a bitmap for this new party
//
rc = USRCreateRemoteDesktop(pasPerson);
DebugExitBOOL(ASShare::USR_ViewStarting, rc);
return(rc);
}
//
// FUNCTION: USRCreateRemoteDesktop
//
// DESCRIPTION:
//
// Creates the shadow bitmap for a remote party.
//
// PARAMETERS:
//
// personID - person to create the shadow bitmap for.
//
// RETURNS: TRUE if successful, FALSE otherwise.
//
//
BOOL ASShare::USRCreateRemoteDesktop(ASPerson * pasPerson)
{
BOOL rc = FALSE;
HDC hdcDesktop = NULL;
RECT desktopRect;
DebugEntry(ASShare::USRCreateRemoteDesktop);
ValidateView(pasPerson);
ASSERT(pasPerson->m_pView->m_usrDC == NULL);
ASSERT(pasPerson->m_pView->m_usrBitmap == NULL);
ASSERT(pasPerson->m_pView->m_usrOldBitmap == NULL);
hdcDesktop = GetDC(NULL);
//
// Create the scratch DC
//
pasPerson->m_pView->m_usrWorkDC = CreateCompatibleDC(hdcDesktop);
if (!pasPerson->m_pView->m_usrWorkDC)
{
ERROR_OUT(("Couldn't create workDC for person [%d]", pasPerson->mcsID));
DC_QUIT;
}
//
// Create the DC that keeps the screen bitmap for this party
//
pasPerson->m_pView->m_usrDC = CreateCompatibleDC(hdcDesktop);
if (!pasPerson->m_pView->m_usrDC)
{
ERROR_OUT(("Couldn't create usrDC for person [%d]", pasPerson->mcsID));
DC_QUIT;
}
//
// We can't use this person's usrDC, since that currently has a MONO
// bitmap selected into it.
//
pasPerson->m_pView->m_usrBitmap = CreateCompatibleBitmap(hdcDesktop, pasPerson->cpcCaps.screen.capsScreenWidth, pasPerson->cpcCaps.screen.capsScreenHeight);
if (pasPerson->m_pView->m_usrBitmap == NULL)
{
ERROR_OUT(("Couldn't create screen bitmap for [%d]", pasPerson->mcsID));
DC_QUIT;
}
//
// Select the screen bitmap into the person's DC, and save the previous
// 1x1 bitmap away, so we can deselect it when done.
//
pasPerson->m_pView->m_usrOldBitmap = SelectBitmap(pasPerson->m_pView->m_usrDC, pasPerson->m_pView->m_usrBitmap);
//
// Fill the Screen Bitmap with grey.
//
// In practice the Shadow Window Presenter(SWP) should never display
// any area of the Screen Bitmap that has not been updated with data
// from a remote system.
//
// Therefore this operation is just "insurance" in case the SWP goes
// wrong and momentarily displays a non-updated area - a flash of grey
// is better than a flash of garbage.
//
desktopRect.left = 0;
desktopRect.top = 0;
desktopRect.right = pasPerson->cpcCaps.screen.capsScreenWidth;
desktopRect.bottom = pasPerson->cpcCaps.screen.capsScreenHeight;
FillRect(pasPerson->m_pView->m_usrDC, &desktopRect, GetSysColorBrush(COLOR_APPWORKSPACE));
rc = TRUE;
DC_EXIT_POINT:
if (hdcDesktop != NULL)
{
ReleaseDC(NULL, hdcDesktop);
}
DebugExitBOOL(ASShare::USRCreateRemoteDesktop, rc);
return(rc);
}
//
// USR_ViewEnded()
//
// Called when person we're viewing stops hosting. We get rid of their
// desktop bitmap.
//
void ASShare::USR_ViewEnded(ASPerson * pasPerson)
{
ValidateView(pasPerson);
//
// Delete the desktop bitmap for the party that has left
//
USRDeleteRemoteDesktop(pasPerson);
}
//
// FUNCTION: USRDeleteRemoteDesktop
//
// DESCRIPTION:
//
// Deletes a remote party's shadow bitmap.
//
// PARAMETERS:
//
// personID - party whose shadow bitmap is to be deleted.
//
// RETURNS: Nothing.
//
//
void ASShare::USRDeleteRemoteDesktop(ASPerson * pasPerson)
{
DebugEntry(ASShare::USRDeleteRemoteDesktop);
ValidateView(pasPerson);
if (pasPerson->m_pView->m_usrOldBitmap != NULL)
{
// Deselect screen bitmap
SelectBitmap(pasPerson->m_pView->m_usrDC, pasPerson->m_pView->m_usrOldBitmap);
pasPerson->m_pView->m_usrOldBitmap = NULL;
}
if (pasPerson->m_pView->m_usrBitmap != NULL)
{
// Delete the screen bitmap
DeleteBitmap(pasPerson->m_pView->m_usrBitmap);
pasPerson->m_pView->m_usrBitmap = NULL;
}
if (pasPerson->m_pView->m_usrDC != NULL)
{
//
// Delete the screen DC. Created objects should have
// been selected out of it before now.
//
DeleteDC(pasPerson->m_pView->m_usrDC);
pasPerson->m_pView->m_usrDC = NULL;
}
if (pasPerson->m_pView->m_usrWorkDC != NULL)
{
DeleteDC(pasPerson->m_pView->m_usrWorkDC);
pasPerson->m_pView->m_usrWorkDC = NULL;
}
DebugExitVOID(ASShare::USRDeleteRemoteDesktop);
}
//
// This function is a mess! First because it ought to be an FH API
// function, and secondly because it mixes portable code and Windows API
// calls. The details of what is to be done with it are deferred until the
// UNIX port of FH is designed, though. STOPPRESS! Function replaced by new
// FH_CreateAndSelectFont, which combines old USR_UseFont and
// FH_CreateAndSelectFont - you have to write an NT version.
//
//
// USR_UseFont()
//
BOOL ASShare::USR_UseFont
(
HDC surface,
HFONT* pHFont,
TEXTMETRIC* pFontMetrics,
LPSTR pName,
UINT codePage,
UINT MaxHeight,
UINT Height,
UINT Width,
UINT Weight,
UINT flags
)
{
BOOL rc = FALSE;
HFONT hNewFont;
HFONT hOldFont;
DebugEntry(ASShare::USR_UseFont);
rc = FH_CreateAndSelectFont(surface,
&hNewFont,
&hOldFont,
pName,
codePage,
MaxHeight,
Height,
Width,
Weight,
flags);
if (rc == FALSE)
{
//
// Failed to create or select the font.
//
DC_QUIT;
}
//
// Select in the new font which ensures that the old one is deselected.
//
// NB. We do not delete the font we are deselecting, rather the old
// one that was passed to us. This is beacuse multiple components use
// "surface", and so the deselected font may not be the current
// component's last font at all - the important thing is that by
// selecting in the new font we are ensuring that the old font is not
// the selected one.
//
SelectFont(surface, hNewFont);
if (*pHFont)
{
DeleteFont(*pHFont);
}
//
// If a pointer to font metrics was passed in then we need to query
// the metrics now.
//
if (pFontMetrics)
GetTextMetrics(surface, pFontMetrics);
//
// Update the record of the last font we selected.
//
*pHFont = hNewFont;
rc = TRUE;
DC_EXIT_POINT:
DebugExitDWORD(ASShare::USR_UseFont, rc);
return(rc);
}
//
// USR_ScreenChanged()
//
void ASShare::USR_ScreenChanged(ASPerson * pasPerson)
{
DebugEntry(ASShare::USR_ScreenChanged);
ValidatePerson(pasPerson);
pasPerson->cpcCaps.screen.capsScreenWidth = pasPerson->cpcCaps.screen.capsScreenWidth;
pasPerson->cpcCaps.screen.capsScreenHeight = pasPerson->cpcCaps.screen.capsScreenHeight;
if (pasPerson->m_pView)
{
//
// Recreate screen bitmap
//
//
// Discard the remote users current shadow bitmap
//
USRDeleteRemoteDesktop(pasPerson);
//
// Create a new shadow bitmap for remote user that is of the new size
//
USRCreateRemoteDesktop(pasPerson);
}
VIEW_ScreenChanged(pasPerson);
DebugExitVOID(ASShare::USR_ScreenChanged);
}