windows-nt/Source/XPSP1/NT/enduser/netmeeting/as/cpi32/oe.cpp
2020-09-26 16:20:57 +08:00

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