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