472 lines
11 KiB
C++
472 lines
11 KiB
C++
|
#include "precomp.h"
|
||
|
|
||
|
|
||
|
//
|
||
|
// OE.CPP
|
||
|
// Order Encoding
|
||
|
//
|
||
|
// Copyright(c) Microsoft 1997-
|
||
|
//
|
||
|
|
||
|
#define MLZ_FILE_ZONE ZONE_ORDER
|
||
|
|
||
|
|
||
|
//
|
||
|
// OE_PartyLeftShare()
|
||
|
//
|
||
|
void ASShare::OE_PartyLeftShare(ASPerson * pasPerson)
|
||
|
{
|
||
|
DebugEntry(ASShare::OE_PartyLeftShare);
|
||
|
|
||
|
ValidatePerson(pasPerson);
|
||
|
|
||
|
//
|
||
|
// Free any font info for this person.
|
||
|
//
|
||
|
if (pasPerson->poeFontInfo)
|
||
|
{
|
||
|
TRACE_OUT(("FREED FONT DATA"));
|
||
|
delete[] pasPerson->poeFontInfo;
|
||
|
pasPerson->poeFontInfo = NULL;
|
||
|
pasPerson->oecFonts = 0;
|
||
|
}
|
||
|
|
||
|
DebugExitVOID(ASShare::OE_PartyLeftShare);
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// OE_RecalcCaps()
|
||
|
//
|
||
|
// Recalculates orders and fonts when somebody joins or leaves the share.
|
||
|
// Unlike the other components, this happens even when we ourselves are not
|
||
|
// hosting, we need this info to interpret data from remote hosts.
|
||
|
//
|
||
|
void ASShare::OE_RecalcCaps(BOOL fJoiner)
|
||
|
{
|
||
|
UINT iOrder;
|
||
|
ASPerson * pasT;
|
||
|
|
||
|
DebugEntry(ASShare::OE_RecalcCaps);
|
||
|
|
||
|
ValidatePerson(m_pasLocal);
|
||
|
|
||
|
//
|
||
|
// Set the initial support to the local support.
|
||
|
//
|
||
|
memcpy(m_aoeOrderSupported, m_pasLocal->cpcCaps.orders.capsOrders,
|
||
|
sizeof(m_pasLocal->cpcCaps.orders.capsOrders));
|
||
|
|
||
|
//
|
||
|
// m_aoeOrderSupported contains more entries than the CAPS_MAX_NUM_ORDERS
|
||
|
// entries in the g_cpcLocalCaps.orders entry. Set the additional values
|
||
|
// to FALSE.
|
||
|
//
|
||
|
for (iOrder = CAPS_MAX_NUM_ORDERS;
|
||
|
iOrder < ORD_NUM_INTERNAL_ORDERS; iOrder++)
|
||
|
{
|
||
|
m_aoeOrderSupported[iOrder] = FALSE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// The combined support for the r1.1 font protocol is initially
|
||
|
// whatever the local support is.
|
||
|
//
|
||
|
m_oeCombinedOrderCaps.capsfFonts = m_pasLocal->cpcCaps.orders.capsfFonts;
|
||
|
|
||
|
//
|
||
|
// The combined support for encoding is initially the local values
|
||
|
//
|
||
|
m_oefOE2Negotiable = ((m_pasLocal->cpcCaps.orders.capsEncodingLevel &
|
||
|
CAPS_ENCODING_OE2_NEGOTIABLE) != 0);
|
||
|
|
||
|
m_oefOE2EncodingOn = !((m_pasLocal->cpcCaps.orders.capsEncodingLevel &
|
||
|
CAPS_ENCODING_OE2_DISABLED) != 0);
|
||
|
m_oeOE2Flag = OE2_FLAG_UNKNOWN;
|
||
|
|
||
|
if (m_oefOE2EncodingOn)
|
||
|
{
|
||
|
m_oeOE2Flag |= OE2_FLAG_SUPPORTED;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_oeOE2Flag |= OE2_FLAG_NOT_SUPPORTED;
|
||
|
}
|
||
|
|
||
|
m_oefBaseOE = ((m_pasLocal->cpcCaps.orders.capsEncodingLevel &
|
||
|
CAPS_ENCODING_BASE_OE) != 0);
|
||
|
|
||
|
m_oefAlignedOE = ((m_pasLocal->cpcCaps.orders.capsEncodingLevel &
|
||
|
CAPS_ENCODING_ALIGNED_OE) != 0);
|
||
|
|
||
|
//
|
||
|
// Loop through the people in the share and examine their order caps
|
||
|
//
|
||
|
for (pasT = m_pasLocal->pasNext; pasT != NULL; pasT = pasT->pasNext)
|
||
|
{
|
||
|
ValidatePerson(pasT);
|
||
|
|
||
|
//
|
||
|
// Check the orders in the orders capabilities.
|
||
|
//
|
||
|
for (iOrder = 0; iOrder < CAPS_MAX_NUM_ORDERS; iOrder++)
|
||
|
{
|
||
|
if (pasT->cpcCaps.orders.capsOrders[iOrder] < ORD_LEVEL_1_ORDERS)
|
||
|
{
|
||
|
//
|
||
|
// The order is not supported at the level we want to send out
|
||
|
// (currently ORD_LEVEL_1_ORDERS) so set the combined caps to
|
||
|
// say not supported.
|
||
|
//
|
||
|
m_aoeOrderSupported[iOrder] = FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_oeCombinedOrderCaps.capsfFonts &=
|
||
|
(pasT->cpcCaps.orders.capsfFonts | ~CAPS_FONT_AND_FLAGS);
|
||
|
|
||
|
m_oeCombinedOrderCaps.capsfFonts |=
|
||
|
(pasT->cpcCaps.orders.capsfFonts & CAPS_FONT_OR_FLAGS);
|
||
|
|
||
|
//
|
||
|
// Check Order encoding support
|
||
|
//
|
||
|
if (!(pasT->cpcCaps.orders.capsEncodingLevel & CAPS_ENCODING_OE2_NEGOTIABLE))
|
||
|
{
|
||
|
m_oefOE2Negotiable = FALSE;
|
||
|
TRACE_OUT(("OE2 negotiation switched off by person [%d]", pasT->mcsID));
|
||
|
}
|
||
|
|
||
|
if (pasT->cpcCaps.orders.capsEncodingLevel & CAPS_ENCODING_OE2_DISABLED)
|
||
|
{
|
||
|
m_oefOE2EncodingOn = FALSE;
|
||
|
m_oeOE2Flag |= OE2_FLAG_NOT_SUPPORTED;
|
||
|
TRACE_OUT(("OE2 switched off by person [%d]", pasT->mcsID));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_oeOE2Flag |= OE2_FLAG_SUPPORTED;
|
||
|
TRACE_OUT(("OE2 supported by person [%d]", pasT->mcsID));
|
||
|
}
|
||
|
|
||
|
if (!(pasT->cpcCaps.orders.capsEncodingLevel & CAPS_ENCODING_BASE_OE))
|
||
|
{
|
||
|
m_oefBaseOE = FALSE;
|
||
|
TRACE_OUT(("Base OE switched off by person [%d]", pasT->mcsID));
|
||
|
}
|
||
|
|
||
|
if (!(pasT->cpcCaps.orders.capsEncodingLevel & CAPS_ENCODING_ALIGNED_OE))
|
||
|
{
|
||
|
m_oefAlignedOE = FALSE;
|
||
|
TRACE_OUT(("Aligned OE switched off by [%d]", pasT->mcsID));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// At 2.x, the DESKSCROLL order support is implied by the SCRBLT
|
||
|
// support.
|
||
|
//
|
||
|
m_aoeOrderSupported[HIWORD(ORD_DESKSCROLL)] = m_aoeOrderSupported[HIWORD(ORD_SCRBLT)];
|
||
|
|
||
|
//
|
||
|
// Turn on the order support now that the table is set up.
|
||
|
//
|
||
|
m_oefSendOrders = TRUE;
|
||
|
|
||
|
//
|
||
|
// Check for incompatible capabilities:
|
||
|
// - OE2 not negotiable but parties don't agree on OE2
|
||
|
// - OE2 not supported but parties don't agree on OE.
|
||
|
// If incompatabilites exist, switch off all order support.
|
||
|
//
|
||
|
if ((!m_oefOE2Negotiable) && (m_oeOE2Flag == OE2_FLAG_MIXED))
|
||
|
{
|
||
|
ERROR_OUT(("OE2 not negotiable but parties don't agree"));
|
||
|
m_oefSendOrders = FALSE;
|
||
|
}
|
||
|
|
||
|
if (!m_oefOE2EncodingOn && !m_oefBaseOE && !m_oefAlignedOE)
|
||
|
{
|
||
|
ERROR_OUT(("None of OE, OE' or OE2 supported"));
|
||
|
m_oefSendOrders = FALSE;
|
||
|
}
|
||
|
|
||
|
FH_DetermineFontSupport();
|
||
|
|
||
|
OECapabilitiesChanged();
|
||
|
|
||
|
DebugExitVOID(ASShare::OE_RecalcCaps);
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// OE_SyncOutgoing()
|
||
|
// Called when share is created or someone new joins the share. Disables
|
||
|
// text orders until we get fonts from all remotes. Broadcasts our local
|
||
|
// supported font list.
|
||
|
//
|
||
|
void ASShare::OE_SyncOutgoing(void)
|
||
|
{
|
||
|
DebugEntry(OE_SyncOutgoing);
|
||
|
|
||
|
//
|
||
|
// Stop sending text orders until the font negotiation is complete.
|
||
|
//
|
||
|
OE_EnableText(FALSE);
|
||
|
|
||
|
//
|
||
|
// Resend font info
|
||
|
//
|
||
|
m_fhLocalInfoSent = FALSE;
|
||
|
|
||
|
DebugExitVOID(ASShare::OE_SyncOutgoing);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// OE_Periodic - see oe.h
|
||
|
//
|
||
|
void ASShare::OE_Periodic(void)
|
||
|
{
|
||
|
DebugEntry(ASShare::OE_Periodic);
|
||
|
|
||
|
//
|
||
|
// If our local font information has not been sent, then send it now.
|
||
|
//
|
||
|
if (!m_fhLocalInfoSent)
|
||
|
{
|
||
|
FH_SendLocalFontInfo();
|
||
|
}
|
||
|
|
||
|
DebugExitVOID(ASShare::OE_Periodic);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// OE_EnableText
|
||
|
//
|
||
|
void ASShare::OE_EnableText(BOOL enable)
|
||
|
{
|
||
|
DebugEntry(ASShare::OE_EnableText);
|
||
|
|
||
|
m_oefTextEnabled = (enable != FALSE);
|
||
|
|
||
|
OECapabilitiesChanged();
|
||
|
|
||
|
DebugExitVOID(ASShare::OE_EnableText);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// OE_RectIntersectsSDA()
|
||
|
//
|
||
|
BOOL ASHost::OE_RectIntersectsSDA(LPRECT pRect)
|
||
|
{
|
||
|
RECT rectVD;
|
||
|
BOOL fIntersection = FALSE;
|
||
|
UINT i;
|
||
|
|
||
|
DebugEntry(ASHost::OE_RectIntersectsSDA);
|
||
|
|
||
|
//
|
||
|
// Copy the supplied rectangle, converting to inclusive Virtual
|
||
|
// Desktop coords.
|
||
|
//
|
||
|
rectVD.left = pRect->left;
|
||
|
rectVD.top = pRect->top;
|
||
|
rectVD.right = pRect->right - 1;
|
||
|
rectVD.bottom = pRect->bottom - 1;
|
||
|
|
||
|
//
|
||
|
// Loop through each of the bounding rectangles checking for
|
||
|
// an intersection with the supplied rectangle.
|
||
|
//
|
||
|
for (i = 0; i < m_baNumRects; i++)
|
||
|
{
|
||
|
if ( (m_abaRects[i].left <= rectVD.right) &&
|
||
|
(m_abaRects[i].top <= rectVD.bottom) &&
|
||
|
(m_abaRects[i].right >= rectVD.left) &&
|
||
|
(m_abaRects[i].bottom >= rectVD.top) )
|
||
|
{
|
||
|
TRACE_OUT(("Rect {%d, %d, %d, %d} intersects SDA {%d, %d, %d, %d}",
|
||
|
rectVD.left, rectVD.top, rectVD.right, rectVD.bottom,
|
||
|
m_abaRects[i].left, m_abaRects[i].top,
|
||
|
m_abaRects[i].right, m_abaRects[i].bottom));
|
||
|
fIntersection = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
DebugExitBOOL(ASHost::OE_RectIntersectsSDA, fIntersection);
|
||
|
return(fIntersection);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// OE_SendAsOrder()
|
||
|
//
|
||
|
BOOL ASShare::OE_SendAsOrder(DWORD order)
|
||
|
{
|
||
|
BOOL rc = FALSE;
|
||
|
|
||
|
DebugEntry(ASShare::OE_SendAsOrder);
|
||
|
|
||
|
//
|
||
|
// Only check the order if we are allowed to send orders in the first
|
||
|
// place!
|
||
|
//
|
||
|
if (m_oefSendOrders)
|
||
|
{
|
||
|
TRACE_OUT(("Orders enabled"));
|
||
|
|
||
|
//
|
||
|
// We are sending some orders, so check individual flags.
|
||
|
//
|
||
|
rc = (m_aoeOrderSupported[HIWORD(order)] != 0);
|
||
|
TRACE_OUT(("Send order 0x%08x HIWORD %hu", order, HIWORD(order)));
|
||
|
}
|
||
|
|
||
|
DebugExitBOOL(ASShare::OE_SendAsOrder, rc);
|
||
|
return(rc);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// OE_GetStringExtent(..)
|
||
|
//
|
||
|
int OE_GetStringExtent
|
||
|
(
|
||
|
HDC hdc,
|
||
|
PTEXTMETRIC pMetric,
|
||
|
LPSTR lpszString,
|
||
|
UINT cbString,
|
||
|
LPRECT pRect
|
||
|
)
|
||
|
{
|
||
|
SIZE textExtent;
|
||
|
UINT i;
|
||
|
ABC abcSpace;
|
||
|
PTEXTMETRIC pTextMetrics;
|
||
|
int overhang = 0;
|
||
|
TEXTMETRIC metricT;
|
||
|
|
||
|
|
||
|
DebugEntry(OE_GetStringExtent);
|
||
|
|
||
|
//
|
||
|
// If no text metrics supplied, then use the global text metrics.
|
||
|
//
|
||
|
pTextMetrics = (pMetric != (PTEXTMETRIC)NULL)
|
||
|
? pMetric
|
||
|
: &metricT;
|
||
|
|
||
|
//
|
||
|
// If there are no characters then return a NULL rectangle.
|
||
|
//
|
||
|
pRect->left = 1;
|
||
|
pRect->top = 0;
|
||
|
pRect->right = 0;
|
||
|
pRect->bottom = 0;
|
||
|
|
||
|
if (cbString == 0)
|
||
|
{
|
||
|
TRACE_OUT(( "Zero length string"));
|
||
|
DC_QUIT;
|
||
|
}
|
||
|
|
||
|
if (!GetTextExtentPoint32(hdc, (LPCTSTR)lpszString, cbString, &textExtent))
|
||
|
{
|
||
|
ERROR_OUT(( "Failed to get text extent, rc = %lu",
|
||
|
GetLastError()));
|
||
|
DC_QUIT;
|
||
|
}
|
||
|
|
||
|
pRect->left = 0;
|
||
|
pRect->top = 0;
|
||
|
pRect->right = textExtent.cx;
|
||
|
pRect->bottom = textExtent.cy;
|
||
|
|
||
|
//
|
||
|
// We have the Windows text extent, which is the advance distance
|
||
|
// for the string. However, some fonts (eg TrueType with C spacing
|
||
|
// or italic) may extend beyond this. Add in this extra value here
|
||
|
// if necessary.
|
||
|
//
|
||
|
if (pTextMetrics->tmPitchAndFamily & TMPF_TRUETYPE)
|
||
|
{
|
||
|
//
|
||
|
// Get the ABC spacing of the last character in the string.
|
||
|
//
|
||
|
GetCharABCWidths(hdc, lpszString[cbString-1], lpszString[cbString-1],
|
||
|
&abcSpace );
|
||
|
|
||
|
//
|
||
|
// SFR 2916: Add in (not subtract) the C space of the last
|
||
|
// character from the string extent.
|
||
|
//
|
||
|
overhang = abcSpace.abcC;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// The font is not TrueType. Add any global font overhang onto
|
||
|
// the string extent.
|
||
|
//
|
||
|
overhang = pTextMetrics->tmOverhang;
|
||
|
}
|
||
|
|
||
|
pRect->right += overhang;
|
||
|
|
||
|
DC_EXIT_POINT:
|
||
|
DebugExitDWORD(OE_GetStringExtent, overhang);
|
||
|
return(overhang);
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
//
|
||
|
// Name: OECapabilitiesChanged
|
||
|
//
|
||
|
// Purpose: Called when the OE capabilities have been renegotiated.
|
||
|
//
|
||
|
// Returns: Nothing
|
||
|
//
|
||
|
// Params: None
|
||
|
//
|
||
|
//
|
||
|
void ASShare::OECapabilitiesChanged(void)
|
||
|
{
|
||
|
DebugEntry(ASShare::OECapabilitiesChanged);
|
||
|
|
||
|
if (g_asCanHost)
|
||
|
{
|
||
|
OE_NEW_CAPABILITIES newCapabilities;
|
||
|
|
||
|
newCapabilities.sendOrders = (m_oefSendOrders != FALSE);
|
||
|
|
||
|
newCapabilities.textEnabled = (m_oefTextEnabled != FALSE);
|
||
|
|
||
|
newCapabilities.baselineTextEnabled =
|
||
|
(m_oeCombinedOrderCaps.capsfFonts & CAPS_FONT_ALLOW_BASELINE) != 0;
|
||
|
|
||
|
newCapabilities.orderSupported = m_aoeOrderSupported;
|
||
|
|
||
|
OSI_FunctionRequest(OE_ESC_NEW_CAPABILITIES, (LPOSI_ESCAPE_HEADER)&newCapabilities,
|
||
|
sizeof(newCapabilities));
|
||
|
}
|
||
|
|
||
|
DebugExitVOID(ASShare::OECapabilitiesChanged);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|