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