windows-nt/Source/XPSP1/NT/termsrv/remdsk/rds/as/cpi32/oe2.cpp
2020-09-26 16:20:57 +08:00

1326 lines
44 KiB
C++
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "precomp.h"
//
// OE2.CPP
// Order Encoding Second Level
//
// Copyright(c) Microsoft 1997-
//
#define MLZ_FILE_ZONE ZONE_ORDER
//
// OE2_HostStarting()
//
BOOL ASHost::OE2_HostStarting(void)
{
DebugEntry(ASHost::OE2_HostStarting);
//
// Set up the pointers for 2nd level encoding
//
m_oe2Tx.LastOrder[OE2_DSTBLT_ORDER ] = &m_oe2Tx.LastDstblt;
m_oe2Tx.LastOrder[OE2_PATBLT_ORDER ] = &m_oe2Tx.LastPatblt;
m_oe2Tx.LastOrder[OE2_SCRBLT_ORDER ] = &m_oe2Tx.LastScrblt;
m_oe2Tx.LastOrder[OE2_MEMBLT_ORDER ] = &m_oe2Tx.LastMemblt;
m_oe2Tx.LastOrder[OE2_MEM3BLT_ORDER ] = &m_oe2Tx.LastMem3blt;
m_oe2Tx.LastOrder[OE2_TEXTOUT_ORDER ] = &m_oe2Tx.LastTextOut;
m_oe2Tx.LastOrder[OE2_EXTTEXTOUT_ORDER] = &m_oe2Tx.LastExtTextOut;
m_oe2Tx.LastOrder[OE2_RECTANGLE_ORDER ] = &m_oe2Tx.LastRectangle;
m_oe2Tx.LastOrder[OE2_LINETO_ORDER ] = &m_oe2Tx.LastLineTo;
m_oe2Tx.LastOrder[OE2_OPAQUERECT_ORDER] = &m_oe2Tx.LastOpaqueRect;
m_oe2Tx.LastOrder[OE2_SAVEBITMAP_ORDER] = &m_oe2Tx.LastSaveBitmap;
m_oe2Tx.LastOrder[OE2_DESKSCROLL_ORDER] = &m_oe2Tx.LastDeskScroll;
m_oe2Tx.LastOrder[OE2_MEMBLT_R2_ORDER ] = &m_oe2Tx.LastMembltR2;
m_oe2Tx.LastOrder[OE2_MEM3BLT_R2_ORDER] = &m_oe2Tx.LastMem3bltR2;
m_oe2Tx.LastOrder[OE2_POLYGON_ORDER ] = &m_oe2Tx.LastPolygon;
m_oe2Tx.LastOrder[OE2_PIE_ORDER ] = &m_oe2Tx.LastPie;
m_oe2Tx.LastOrder[OE2_ELLIPSE_ORDER ] = &m_oe2Tx.LastEllipse;
m_oe2Tx.LastOrder[OE2_ARC_ORDER ] = &m_oe2Tx.LastArc;
m_oe2Tx.LastOrder[OE2_CHORD_ORDER ] = &m_oe2Tx.LastChord;
m_oe2Tx.LastOrder[OE2_POLYBEZIER_ORDER] = &m_oe2Tx.LastPolyBezier;
m_oe2Tx.LastOrder[OE2_ROUNDRECT_ORDER ] = &m_oe2Tx.LastRoundRect;
//
// Set up the last order values to a known value.
//
m_oe2Tx.LastOrderType = OE2_PATBLT_ORDER;
m_oe2Tx.pLastOrder = (LPCOM_ORDER)m_oe2Tx.LastOrder[m_oe2Tx.LastOrderType];
DebugExitBOOL(ASHost::OE2_HostStarting, TRUE);
return(TRUE);
}
//
// OE2_HostEnded()
//
void ASHost::OE2_HostEnded(void)
{
DebugEntry(ASHost::OE2_HostEnded);
//
// For OUTGOING order encoding, free the last font we cached.
//
if (m_oe2Tx.LastHFONT != NULL)
{
ASSERT(m_pShare);
ASSERT(m_usrWorkDC);
SelectFont(m_usrWorkDC, (HFONT)GetStockObject(SYSTEM_FONT));
DeleteFont(m_oe2Tx.LastHFONT);
m_oe2Tx.LastHFONT = NULL;
}
DebugExitVOID(ASHost::OE2_HostEnded);
}
//
// OE2_SyncOutgoing()
// Called when NEW dude starts to host, a share is created, or somebody new
// joins the share.
// Resets the OUTGOING 2nd level order encoding data.
//
void ASHost::OE2_SyncOutgoing(void)
{
DebugEntry(ASHost::OE2_SyncOutgoing);
//
// Set up the last order values to a known value.
//
m_oe2Tx.LastOrderType = OE2_PATBLT_ORDER;
m_oe2Tx.pLastOrder = (LPCOM_ORDER)m_oe2Tx.LastOrder[m_oe2Tx.LastOrderType];
//
// Clear out all the last orders.
//
ZeroMemory(&m_oe2Tx.LastDstblt, sizeof(m_oe2Tx.LastDstblt));
((PATBLT_ORDER*)&m_oe2Tx.LastDstblt)->type = ORD_DSTBLT_TYPE;
ZeroMemory(&m_oe2Tx.LastPatblt, sizeof(m_oe2Tx.LastPatblt));
((PATBLT_ORDER*)&m_oe2Tx.LastPatblt)->type = ORD_PATBLT_TYPE;
ZeroMemory(&m_oe2Tx.LastScrblt, sizeof(m_oe2Tx.LastScrblt));
((PATBLT_ORDER*)&m_oe2Tx.LastScrblt)->type = ORD_SCRBLT_TYPE;
ZeroMemory(&m_oe2Tx.LastMemblt, sizeof(m_oe2Tx.LastMemblt));
((PATBLT_ORDER*)&m_oe2Tx.LastMemblt)->type = ORD_MEMBLT_TYPE;
ZeroMemory(&m_oe2Tx.LastMem3blt,sizeof(m_oe2Tx.LastMem3blt));
((PATBLT_ORDER*)&m_oe2Tx.LastMem3blt)->type = ORD_MEM3BLT_TYPE;
ZeroMemory(&m_oe2Tx.LastTextOut, sizeof(m_oe2Tx.LastTextOut));
((PATBLT_ORDER*)&m_oe2Tx.LastTextOut)->type = ORD_TEXTOUT_TYPE;
ZeroMemory(&m_oe2Tx.LastExtTextOut, sizeof(m_oe2Tx.LastExtTextOut));
((PATBLT_ORDER*)&m_oe2Tx.LastExtTextOut)->type = ORD_EXTTEXTOUT_TYPE;
ZeroMemory(&m_oe2Tx.LastRectangle, sizeof(m_oe2Tx.LastRectangle));
((PATBLT_ORDER*)&m_oe2Tx.LastRectangle)->type = ORD_RECTANGLE_TYPE;
ZeroMemory(&m_oe2Tx.LastPolygon, sizeof(m_oe2Tx.LastPolygon));
((POLYGON_ORDER*)&m_oe2Tx.LastPolygon)->type = ORD_POLYGON_TYPE;
ZeroMemory(&m_oe2Tx.LastPie, sizeof(m_oe2Tx.LastPie));
((PIE_ORDER*)&m_oe2Tx.LastPie)->type = ORD_PIE_TYPE;
ZeroMemory(&m_oe2Tx.LastEllipse, sizeof(m_oe2Tx.LastEllipse));
((ELLIPSE_ORDER*)&m_oe2Tx.LastEllipse)->type = ORD_ELLIPSE_TYPE;
ZeroMemory(&m_oe2Tx.LastArc, sizeof(m_oe2Tx.LastArc));
((ARC_ORDER*)&m_oe2Tx.LastArc)->type = ORD_ARC_TYPE;
ZeroMemory(&m_oe2Tx.LastChord, sizeof(m_oe2Tx.LastChord));
((CHORD_ORDER*)&m_oe2Tx.LastChord)->type = ORD_CHORD_TYPE;
ZeroMemory(&m_oe2Tx.LastPolyBezier, sizeof(m_oe2Tx.LastPolyBezier));
((POLYBEZIER_ORDER*)&m_oe2Tx.LastPolyBezier)->type = ORD_POLYBEZIER_TYPE;
ZeroMemory(&m_oe2Tx.LastRoundRect, sizeof(m_oe2Tx.LastRoundRect));
((ROUNDRECT_ORDER*)&m_oe2Tx.LastRoundRect)->type = ORD_ROUNDRECT_TYPE;
ZeroMemory(&m_oe2Tx.LastLineTo, sizeof(m_oe2Tx.LastLineTo));
((PATBLT_ORDER*)&m_oe2Tx.LastLineTo)->type = ORD_LINETO_TYPE;
ZeroMemory(&m_oe2Tx.LastOpaqueRect, sizeof(m_oe2Tx.LastOpaqueRect));
((PATBLT_ORDER*)&m_oe2Tx.LastOpaqueRect)->type = ORD_OPAQUERECT_TYPE;
ZeroMemory(&m_oe2Tx.LastSaveBitmap, sizeof(m_oe2Tx.LastSaveBitmap));
((PATBLT_ORDER*)&m_oe2Tx.LastSaveBitmap)->type = ORD_SAVEBITMAP_TYPE;
ZeroMemory(&m_oe2Tx.LastDeskScroll, sizeof(m_oe2Tx.LastDeskScroll));
((PATBLT_ORDER*)&m_oe2Tx.LastDeskScroll)->type = ORD_DESKSCROLL_TYPE;
ZeroMemory(&m_oe2Tx.LastMembltR2, sizeof(m_oe2Tx.LastMembltR2));
((PATBLT_ORDER*)&m_oe2Tx.LastMembltR2)->type = ORD_MEMBLT_R2_TYPE;
ZeroMemory(&m_oe2Tx.LastMem3bltR2, sizeof(m_oe2Tx.LastMem3bltR2));
((PATBLT_ORDER*)&m_oe2Tx.LastMem3bltR2)->type = ORD_MEM3BLT_R2_TYPE;
ZeroMemory(&m_oe2Tx.LastBounds, sizeof(m_oe2Tx.LastBounds));
DebugExitVOID(ASHost::OE2_SyncOutgoing);
}
//
// OE2_EncodeOrder()
//
TSHR_UINT16 ASHost::OE2_EncodeOrder
(
LPINT_ORDER pIntOrder,
void * pBuffer,
TSHR_UINT16 cbBufferSize
)
{
POE2ETFIELD pTableEntry;
LPSTR pNextFreeSpace;
UINT thisFlag = 0;
RECT Rect;
TSHR_RECT16 Rect16;
UINT cbEncodedOrderSize;
UINT cbMaxEncodedOrderSize;
LPBYTE pControlFlags;
LPTSHR_UINT32_UA pEncodingFlags;
LPSTR pEncodedOrder;
UINT numEncodingFlagBytes;
LPSTR pVariableField;
BOOL useDeltaCoords;
UINT i;
LPCOM_ORDER pComOrder;
UINT fieldLength;
UINT numReps;
DebugEntry(ASHost::OE2_EncodeOrder);
#ifdef ORDER_TRACE
if (OE2_DebugOrderTrace)
{
TrcUnencodedOrder(pIntOrder);
}
#endif // ORDER_TRACE
//
// Set up a pointer to the Common Order.
//
pComOrder = (LPCOM_ORDER)&(pIntOrder->OrderHeader.Common);
//
// Calculate the maximum bytes required to encode this order.
//
if (pComOrder->OrderHeader.fOrderFlags & OF_PRIVATE)
{
//
// Private order.
//
cbMaxEncodedOrderSize = OE2_CONTROL_FLAGS_FIELD_SIZE +
COM_ORDER_SIZE(pComOrder);
}
else
{
//
// Normal (not Private) order.
//
cbMaxEncodedOrderSize = OE2_CONTROL_FLAGS_FIELD_SIZE +
OE2_TYPE_FIELD_SIZE +
OE2_MAX_FIELD_FLAG_BYTES +
OE2_MAX_ADDITIONAL_BOUNDS_BYTES +
COM_ORDER_SIZE(pComOrder);
}
//
// If we are not absolutely certain that the supplied buffer is big
// enough to hold this order (encoded) then return immediately.
//
if (cbMaxEncodedOrderSize > cbBufferSize)
{
cbEncodedOrderSize = 0;
goto encode_order_exit;
}
//
// Set up some local variables to access the encoding buffer in various
// ways.
//
pControlFlags = &((PDCEO2ORDER)pBuffer)->ControlFlags;
pEncodedOrder = (LPSTR)&((PDCEO2ORDER)pBuffer)->EncodedOrder[0];
pEncodingFlags = (LPTSHR_UINT32_UA)&pEncodedOrder[0];
//
// Initialise the control flags field to indicate this is a standard
// encoding (ie the rest of the control flags have the meaning defined
// by the rest of the OE2_CF_XXX definitions).
//
*pControlFlags = OE2_CF_STANDARD_ENC;
//
// If the private flag is set then we must return the encoded order
// as it is (ie without doing any further encoding).
//
if (pComOrder->OrderHeader.fOrderFlags & OF_PRIVATE)
{
*pControlFlags |= OE2_CF_UNENCODED;
cbEncodedOrderSize = SBC_CopyPrivateOrderData(
(LPBYTE)pEncodedOrder,
pComOrder,
cbMaxEncodedOrderSize -
FIELD_OFFSET(DCEO2ORDER, EncodedOrder) );
cbEncodedOrderSize += FIELD_OFFSET(DCEO2ORDER, EncodedOrder);
TRACE_OUT(( "PRIVATE order size %u", cbEncodedOrderSize));
goto encode_order_exit;
}
//
// If the type of this order is different to the last order encoded,
// get a pointer to the last order of this type encoded and remember
// what type of order it is. We must also tell the decoding end that
// this type is different from the last one, so set the new type flag
// and copy type into buffer
//
// The "type" field come before the encoding flags so that the number
// of flags we have can vary depending on the order. Set up a pointer
// to these flags here depending on whether or not we have to encode
// the order type.
//
if (TEXTFIELD(pComOrder)->type != ((PATBLT_ORDER*)m_oe2Tx.pLastOrder)->type)
{
TRACE_OUT(( "change type from %04X to %04X",
LOWORD(((PATBLT_ORDER*)m_oe2Tx.pLastOrder)->type),
LOWORD(TEXTFIELD(pComOrder)->type)));
m_oe2Tx.LastOrderType = OE2GetOrderType(pComOrder);
m_oe2Tx.pLastOrder = (LPCOM_ORDER)m_oe2Tx.LastOrder[m_oe2Tx.LastOrderType];
*(LPBYTE)pEncodedOrder = m_oe2Tx.LastOrderType;
*pControlFlags |= OE2_CF_TYPE_CHANGE;
pEncodingFlags = (LPTSHR_UINT32_UA)&pEncodedOrder[1];
}
else
{
pEncodingFlags = (LPTSHR_UINT32_UA)&pEncodedOrder[0];
}
//
// Work out how many bytes we will need to store the encoding flags in.
// (We have a flag for each field in the order structure). This code
// we have written will cope with up to a DWORD of encoding flags.
//
numEncodingFlagBytes= (s_etable.NumFields[m_oe2Tx.LastOrderType]+7)/8;
if (numEncodingFlagBytes > OE2_MAX_FIELD_FLAG_BYTES)
{
ERROR_OUT(( "Too many flag bytes (%d) for this code", numEncodingFlagBytes));
}
//
// Now we know how many bytes make up the flags we can get a pointer
// to the position at which to start encoding the orders fields into.
//
pNextFreeSpace = ((LPSTR)pEncodingFlags) + numEncodingFlagBytes;
//
// Calculate the bounds. If these are the same as those already in the
// order header then there is no need to send any bounds because we can
// recalculate them at the receiver.
//
m_pShare->OD2_CalculateBounds(pComOrder, &Rect, FALSE, m_pShare->m_pasLocal);
TSHR_RECT16_FROM_RECT(&Rect16, Rect);
if (memcmp(&(pComOrder->OrderHeader.rcsDst), &Rect16, sizeof(Rect16)))
{
TRACE_OUT(( "copy bounding rect"));
OE2EncodeBounds((LPBYTE*)&pNextFreeSpace,
&pComOrder->OrderHeader.rcsDst);
*pControlFlags |= OE2_CF_BOUNDS;
}
//
// Before we do the field encoding (using s_etable) check all the field
// entries flagged as coordinates to see if we can switch to
// OE2_CF_DELTACOORDS mode.
//
pTableEntry = s_etable.pFields[m_oe2Tx.LastOrderType];
useDeltaCoords = TRUE;
//
// Loop through each fixed field in this order structure...
//
while ( useDeltaCoords
&& (pTableEntry->FieldPos != 0)
&& ((pTableEntry->FieldType & OE2_ETF_FIXED) != 0) )
{
//
// If this field entry is a coordinate then compare it to the
// previous coordinate we sent for this field to determine whether
// we can send it as a delta
//
if (pTableEntry->FieldType & OE2_ETF_COORDINATES)
{
useDeltaCoords =
OE2CanUseDeltaCoords(((LPSTR)pComOrder->abOrderData)
+ pTableEntry->FieldPos,
((LPSTR)m_oe2Tx.pLastOrder)
+ pTableEntry->FieldPos,
pTableEntry->FieldUnencodedLen,
pTableEntry->FieldSigned,
1);
}
pTableEntry++;
}
//
// Loop through each of the variable fields...
//
pVariableField = ((LPSTR)(pComOrder->abOrderData))
+ pTableEntry->FieldPos;
while (useDeltaCoords && (pTableEntry->FieldPos != 0))
{
//
// The length of the field (in bytes) is given in the first
// TSHR_UINT32 of the variable sized field structure.
//
fieldLength = *(TSHR_UINT32 FAR *)pVariableField;
pVariableField += sizeof(TSHR_UINT32);
//
// If this field entry is a coordinate then compare it to the
// previous coordinate we sent for this field to determine whether
// we can send it as a delta
//
if (pTableEntry->FieldType & OE2_ETF_COORDINATES)
{
//
// The number of coordinates is given by the number of bytes in
// the field divided by the size of each entry
//
numReps = fieldLength / pTableEntry->FieldUnencodedLen;
useDeltaCoords =
OE2CanUseDeltaCoords(pVariableField,
((LPSTR)m_oe2Tx.pLastOrder)
+ pTableEntry->FieldPos,
pTableEntry->FieldUnencodedLen,
pTableEntry->FieldSigned,
numReps);
}
//
// Move on to the next field in the order structure. Note that
// variable sized fields are packed on the send side. (ie
// increment pVariableField by fieldLength not by
// pTableEntry->FieldLen).
//
pVariableField += fieldLength;
pTableEntry++;
}
if (useDeltaCoords)
{
*pControlFlags |= OE2_CF_DELTACOORDS;
}
//
// Now do the encoding...
//
pTableEntry = s_etable.pFields[m_oe2Tx.LastOrderType];
//
// Clear the encoding flag bytes.
//
for (i = 0; i < numEncodingFlagBytes; i++)
{
((LPBYTE)pEncodingFlags)[i] = 0;
}
thisFlag = 0x00000001;
//
// First process all the fixed size fields in the order structure...
// (These come before the variable sized fields).
//
while ( (pTableEntry->FieldPos != 0)
&& (pTableEntry->FieldType & OE2_ETF_FIXED) )
{
//
// If the field has changed since it was previously transmitted then
// we need to send it again.
//
if (memcmp(
((LPBYTE)(pComOrder->abOrderData)) + pTableEntry->FieldPos,
((LPBYTE)m_oe2Tx.pLastOrder) + pTableEntry->FieldPos,
pTableEntry->FieldUnencodedLen))
{
//
// Update the encoding flags
//
*pEncodingFlags |= thisFlag;
//
// If we are encoding in delta coordinate mode and this field
// is a coordinate...
//
if (useDeltaCoords &&
((pTableEntry->FieldType & OE2_ETF_COORDINATES) != 0) )
{
OE2CopyToDeltaCoords((LPTSHR_INT8*)&pNextFreeSpace,
(((LPSTR)pComOrder->abOrderData)
+ pTableEntry->FieldPos),
(((LPSTR)m_oe2Tx.pLastOrder)
+ pTableEntry->FieldPos),
pTableEntry->FieldUnencodedLen,
pTableEntry->FieldSigned,
1);
}
else
{
//
// Update the data to be sent
//
OE2EncodeField(((LPBYTE)(pComOrder->abOrderData)) +
pTableEntry->FieldPos,
(LPBYTE*)&pNextFreeSpace,
pTableEntry->FieldUnencodedLen,
pTableEntry->FieldEncodedLen,
pTableEntry->FieldSigned,
1);
}
//
// Save the current value for comparison next time.
//
memcpy(((LPBYTE)m_oe2Tx.pLastOrder) + pTableEntry->FieldPos,
((LPBYTE)(pComOrder->abOrderData)) + pTableEntry->FieldPos,
pTableEntry->FieldUnencodedLen);
}
//
// Move on to the next field in the structure.
//
thisFlag = thisFlag << 1;
pTableEntry++;
}
//
// Now process the variable sized entries...
//
pVariableField = ((LPSTR)(pComOrder->abOrderData))
+ pTableEntry->FieldPos;
while (pTableEntry->FieldPos != 0)
{
//
// The length of the field is given in the first UINT of the
// variable sized field structure.
//
fieldLength = *(TSHR_UINT32 FAR *)pVariableField;
//
// If the field has changed (either in size or in contents) then we
// need to copy it across.
//
if (memcmp(pVariableField, ((LPBYTE)m_oe2Tx.pLastOrder) +
pTableEntry->FieldPos, fieldLength + sizeof(TSHR_UINT32)))
{
//
// Update the encoding flags
//
*pEncodingFlags |= thisFlag;
//
// Work out how many elements we are encoding for this field.
//
numReps = fieldLength / pTableEntry->FieldUnencodedLen;
//
// Fill in the length of the field into the encoded buffer
// (this is always encoded in a single byte), then increment
// the pointer ready to encode the actual field.
//
// Note that the length must always be set to the length
// required for regular second level encoding of the field,
// regardless of whether regular encoding or delta encoding is
// used.
//
ASSERT(numReps * pTableEntry->FieldEncodedLen < 256);
*pNextFreeSpace =
(BYTE)(numReps * pTableEntry->FieldEncodedLen);
pNextFreeSpace++;
//
// If we are encoding in delta coordinate mode and this field
// is a coordinate...
//
if (useDeltaCoords &&
((pTableEntry->FieldType & OE2_ETF_COORDINATES) != 0) )
{
//
// Encode using delta coordinate encoding
//
OE2CopyToDeltaCoords((LPTSHR_INT8*)&pNextFreeSpace,
pVariableField + sizeof(TSHR_UINT32),
((LPSTR)m_oe2Tx.pLastOrder)
+ pTableEntry->FieldPos
+ sizeof(TSHR_UINT32),
pTableEntry->FieldUnencodedLen,
pTableEntry->FieldSigned,
numReps);
}
else
{
//
// Use regular encoding
//
OE2EncodeField((LPBYTE)(pVariableField + sizeof(TSHR_UINT32)),
(LPBYTE*)&pNextFreeSpace,
pTableEntry->FieldUnencodedLen,
pTableEntry->FieldEncodedLen,
pTableEntry->FieldSigned,
numReps);
}
//
// Keep data for comparison next time.
//
// Note that the variable fields of pLastOrder are not packed
// (unlike the order which we are encoding), so we can use
// pTableEntry->FieldPos to get the start of the field.
//
memcpy(((LPSTR)m_oe2Tx.pLastOrder) + pTableEntry->FieldPos,
pVariableField,
fieldLength + sizeof(TSHR_UINT32));
}
//
// Move on to the next field in the order structure, remembering to
// step. Note that past the size field. variable sized fields are
// packed on the send side. (ie increment pVariableField by
// fieldLength not by pTableEntry->FieldLen).
//
pVariableField += fieldLength + sizeof(TSHR_UINT32);
//
// Make sure that we are at the next 4-byte boundary
//
if ((((UINT_PTR)pVariableField) % 4) != 0)
{
pVariableField += 4 - (((UINT_PTR)pVariableField) % 4);
}
thisFlag = thisFlag << 1;
pTableEntry++;
}
//
// record some stats:
// Increment the count of order bytes of this type
// Set the flags on for the fields which have been encoded
//
cbEncodedOrderSize = (UINT)(pNextFreeSpace - (LPSTR)pBuffer);
TRACE_OUT(( "return %u flags %x,%x", cbEncodedOrderSize,
(UINT)*pControlFlags, *pEncodingFlags));
encode_order_exit:
//
// "Insurance" check that we have not overwritten the end of the buffer.
//
if (cbEncodedOrderSize > cbBufferSize)
{
//
// Oh dear!
// We should never take this path - if we do, the code has gone
// seriously wrong.
//
ERROR_OUT(( "End of buffer overwritten! enc(%d) buff(%d) type(%d)",
cbEncodedOrderSize,
cbBufferSize,
m_oe2Tx.LastOrderType));
}
//
// Return the length of the encoded order
//
DebugExitDWORD(ASShare::OE2_EncodeOrder, cbEncodedOrderSize);
return((TSHR_UINT16)cbEncodedOrderSize);
}
//
//
// OE2GetOrderType() - see oe2.h
//
//
BYTE OE2GetOrderType(LPCOM_ORDER pOrder)
{
BYTE type = 0xff;
DebugEntry(OE2GetOrderType);
TRACE_OUT(( "order type = %hx", TEXTFIELD(pOrder)->type));
switch ( TEXTFIELD(pOrder)->type )
{
case ORD_DSTBLT_TYPE:
type = OE2_DSTBLT_ORDER;
break;
case ORD_PATBLT_TYPE:
type = OE2_PATBLT_ORDER;
break;
case ORD_SCRBLT_TYPE:
type = OE2_SCRBLT_ORDER;
break;
case ORD_MEMBLT_TYPE:
type = OE2_MEMBLT_ORDER;
break;
case ORD_MEM3BLT_TYPE:
type = OE2_MEM3BLT_ORDER;
break;
case ORD_MEMBLT_R2_TYPE:
type = OE2_MEMBLT_R2_ORDER;
break;
case ORD_MEM3BLT_R2_TYPE:
type = OE2_MEM3BLT_R2_ORDER;
break;
case ORD_TEXTOUT_TYPE:
type = OE2_TEXTOUT_ORDER;
break;
case ORD_EXTTEXTOUT_TYPE:
type = OE2_EXTTEXTOUT_ORDER;
break;
case ORD_RECTANGLE_TYPE:
type = OE2_RECTANGLE_ORDER;
break;
case ORD_LINETO_TYPE:
type = OE2_LINETO_ORDER;
break;
case ORD_OPAQUERECT_TYPE:
type = OE2_OPAQUERECT_ORDER;
break;
case ORD_SAVEBITMAP_TYPE:
type = OE2_SAVEBITMAP_ORDER;
break;
case ORD_DESKSCROLL_TYPE:
type = OE2_DESKSCROLL_ORDER;
break;
case ORD_POLYGON_TYPE:
type = OE2_POLYGON_ORDER;
break;
case ORD_PIE_TYPE:
type = OE2_PIE_ORDER;
break;
case ORD_ELLIPSE_TYPE:
type = OE2_ELLIPSE_ORDER;
break;
case ORD_ARC_TYPE:
type = OE2_ARC_ORDER;
break;
case ORD_CHORD_TYPE:
type = OE2_CHORD_ORDER;
break;
case ORD_POLYBEZIER_TYPE:
type = OE2_POLYBEZIER_ORDER;
break;
case ORD_ROUNDRECT_TYPE:
type = OE2_ROUNDRECT_ORDER;
break;
default:
ERROR_OUT(( "Unknown order type %x",
TEXTFIELD(pOrder)->type));
}
DebugExitDWORD(OE2GetOrderType, type);
return(type);
}
//
// Given a pointer to 2 arrays, work out if the difference between every
// element at corresponding indices in the arrays can be represented by a
// delta (1 byte integer).
//
// ARRAY1 - The first array
// ARRAY2 - The second array
// NUMELEMENTS - The number of elements in the arrays
// DELTASPOSSIBLE - The "return value". Set to TRUE if all differences
// can be represented by deltas, FALSE if not.
//
#define CHECK_DELTA_ARRAY(ARRAY1, ARRAY2, NUMELEMENTS, DELTASPOSSIBLE) \
{ \
UINT index; \
int delta; \
(DELTASPOSSIBLE) = TRUE; \
for (index=0 ; index<(NUMELEMENTS) ; index++) \
{ \
delta = (ARRAY1)[index] - (ARRAY2)[index]; \
if (delta != (int)(TSHR_INT8)delta) \
{ \
(DELTASPOSSIBLE) = FALSE; \
break; \
} \
} \
}
//
//
// Name: OE2CanUseDeltaCoords
//
// Purpose: This function compares two arrays containing a number of
// coordinate values. If the difference between each
// coordinate pair can be expressed as a byte sized delta
// quantity then the function returns TRUE otherwise it returns
// FALSE.
//
// Returns: TRUE if delta coords can be used, FALSE otherwise
//
// Params: IN pNewCoords - Pointer to the new array
// IN pOldCoords - Pointer to the existing array
// IN fieldLength - The size (in bytes) of each element in the
// array.
// IN signedValue - TRUE of the elements in the arrays are
// signed values, FALSE otherwise.
// IN numElements - The number of elements in the arrays.
//
//
BOOL OE2CanUseDeltaCoords(void * pNewCoords,
void * pOldCoords,
UINT fieldLength,
BOOL signedValue,
UINT numElements)
{
LPTSHR_INT16 pNew16Signed = (LPTSHR_INT16)pNewCoords;
LPTSHR_INT32 pNew32Signed = (LPTSHR_INT32)pNewCoords;
LPTSHR_UINT16 pNew16Unsigned = (LPTSHR_UINT16)pNewCoords;
LPUINT pNew32Unsigned = (LPUINT)pNewCoords;
LPTSHR_INT16 pOld16Signed = (LPTSHR_INT16)pOldCoords;
LPTSHR_INT32 pOld32Signed = (LPTSHR_INT32)pOldCoords;
LPTSHR_UINT16 pOld16Unsigned = (LPTSHR_UINT16)pOldCoords;
LPUINT pOld32Unsigned = (LPUINT)pOldCoords;
BOOL useDeltaCoords;
DebugEntry(OE2CanUseDeltaCoords);
switch (fieldLength)
{
case 2:
{
if (signedValue)
{
CHECK_DELTA_ARRAY(pNew16Signed,
pOld16Signed,
numElements,
useDeltaCoords);
}
else
{
CHECK_DELTA_ARRAY(pNew16Unsigned,
pOld16Unsigned,
numElements,
useDeltaCoords);
}
}
break;
case 4:
{
if (signedValue)
{
CHECK_DELTA_ARRAY(pNew32Signed,
pOld32Signed,
numElements,
useDeltaCoords);
}
else
{
CHECK_DELTA_ARRAY(pNew32Unsigned,
pOld32Unsigned,
numElements,
useDeltaCoords);
}
}
break;
default:
{
ERROR_OUT(( "Bad field length %d", fieldLength));
useDeltaCoords = FALSE;
}
break;
}
DebugExitDWORD(OE2CanUseDeltaCoords, useDeltaCoords);
return(useDeltaCoords);
}
//
// Given two arrays, fill in a delta array with each element holding
// ARRAY1[i] - ARRAY2[i]
//
// DESTARRAY - The delta array. This is an array of TSHR_INT8s
// ARRAY1 - The first array
// ARRAY2 - The second array
// NUMELEMENTS - The number of elements in the arrays
//
//
#define COPY_TO_DELTA_ARRAY(DESTARRAY, ARRAY1, ARRAY2, NUMELEMENTS) \
{ \
UINT index; \
for (index=0 ; index<(NUMELEMENTS) ; index++) \
{ \
(DESTARRAY)[index] = (TSHR_INT8)((ARRAY1)[index] - (ARRAY2)[index]); \
} \
}
//
//
// Name: OE2CopyToDeltaCoords
//
// Purpose: Copies an array of coordinate values to an array of delta
// (byte sized) coordinate values relative to a reference array
// of coordinate values.
//
// Returns: Nothing
//
// Params: IN/OUT ppDestination - Pointer to the start of the
// destination delta array. This is
// updated to point to the byte following
// the last delta on exit.
// IN pNewCoords - Pointer to the new array
// IN pOldCoords - Pointer to the reference array
// IN fieldLength - The size (in bytes) of each element in
// New/OldCoords arrays.
// IN signedValue - TRUE of the elements in the coords
// arrays are signed values, FALSE
// otherwise.
// IN numElements - The number of elements in the arrays.
//
// Operation: The caller should call OE2CanUseDeltaCoords() before calling
// this function to ensure that the differences can be
// encoded using delta coordingates.
//
//
void OE2CopyToDeltaCoords(LPTSHR_INT8* ppDestination,
void * pNewCoords,
void * pOldCoords,
UINT fieldLength,
BOOL signedValue,
UINT numElements)
{
LPTSHR_INT16 pNew16Signed = (LPTSHR_INT16)pNewCoords;
LPTSHR_INT32 pNew32Signed = (LPTSHR_INT32)pNewCoords;
LPTSHR_UINT16 pNew16Unsigned = (LPTSHR_UINT16)pNewCoords;
LPUINT pNew32Unsigned = (LPUINT)pNewCoords;
LPTSHR_INT16 pOld16Signed = (LPTSHR_INT16)pOldCoords;
LPTSHR_INT32 pOld32Signed = (LPTSHR_INT32)pOldCoords;
LPTSHR_UINT16 pOld16Unsigned = (LPTSHR_UINT16)pOldCoords;
LPUINT pOld32Unsigned = (LPUINT)pOldCoords;
DebugEntry(OE2CopyToDeltaCoords);
switch (fieldLength)
{
case 2:
{
if (signedValue)
{
COPY_TO_DELTA_ARRAY(*ppDestination,
pNew16Signed,
pOld16Signed,
numElements);
}
else
{
COPY_TO_DELTA_ARRAY(*ppDestination,
pNew16Unsigned,
pOld16Unsigned,
numElements);
}
}
break;
case 4:
{
if (signedValue)
{
COPY_TO_DELTA_ARRAY(*ppDestination,
pNew32Signed,
pOld32Signed,
numElements);
}
else
{
COPY_TO_DELTA_ARRAY(*ppDestination,
pNew32Unsigned,
pOld32Unsigned,
numElements);
}
}
break;
default:
{
ERROR_OUT(( "Bad field length %d", fieldLength));
}
break;
}
//
// Update the next free position in the destination buffer
//
*ppDestination += numElements;
DebugExitVOID(OE2CopyToDeltaCoords);
}
//
// OE2EncodeBounds()
//
void ASHost::OE2EncodeBounds
(
LPBYTE * ppNextFreeSpace,
LPTSHR_RECT16 pRect
)
{
LPBYTE pFlags;
DebugEntry(ASHost::OE2EncodeBounds);
//
// The encoding used is a byte of flags followed by a variable number
// of 16bit coordinate values and 8bit delta coordinate values (which
// may be interleaved).
//
//
// The first byte of the encoding will contain the flags that represent
// how the coordinates of the rectangle were encoded.
//
pFlags = *ppNextFreeSpace;
*pFlags = 0;
(*ppNextFreeSpace)++;
//
// For each of the four coordinate values in the rectangle: If the
// coordinate has not changed then the encoding is null. If the
// coordinate can be encoded as a delta then do so and set the
// appropriate flag. Otherwise copy the coordinate as a 16bit value
// and set the appropriate flag.
//
if (m_oe2Tx.LastBounds.left != pRect->left)
{
if (OE2CanUseDeltaCoords(&pRect->left,
&m_oe2Tx.LastBounds.left,
sizeof(pRect->left),
TRUE, // signed value
1))
{
OE2CopyToDeltaCoords((LPTSHR_INT8*)ppNextFreeSpace,
&pRect->left,
&m_oe2Tx.LastBounds.left,
sizeof(pRect->left),
TRUE, // signed value
1);
*pFlags |= OE2_BCF_DELTA_LEFT;
}
else
{
*((LPTSHR_UINT16)(*ppNextFreeSpace)) = pRect->left;
*pFlags |= OE2_BCF_LEFT;
(*ppNextFreeSpace) = (*ppNextFreeSpace) + sizeof(TSHR_UINT16);
}
}
if (m_oe2Tx.LastBounds.top != pRect->top)
{
if (OE2CanUseDeltaCoords(&pRect->top,
&m_oe2Tx.LastBounds.top,
sizeof(pRect->top),
TRUE, // signed value
1))
{
OE2CopyToDeltaCoords((LPTSHR_INT8*)ppNextFreeSpace,
&pRect->top,
&m_oe2Tx.LastBounds.top,
sizeof(pRect->top),
TRUE, // signed value
1);
*pFlags |= OE2_BCF_DELTA_TOP;
}
else
{
*((LPTSHR_UINT16)(*ppNextFreeSpace)) = pRect->top;
*pFlags |= OE2_BCF_TOP;
(*ppNextFreeSpace) = (*ppNextFreeSpace) + sizeof(TSHR_UINT16);
}
}
if (m_oe2Tx.LastBounds.right != pRect->right)
{
if (OE2CanUseDeltaCoords(&pRect->right,
&m_oe2Tx.LastBounds.right,
sizeof(pRect->right),
TRUE, // signed value
1))
{
OE2CopyToDeltaCoords((LPTSHR_INT8*)ppNextFreeSpace,
&pRect->right,
&m_oe2Tx.LastBounds.right,
sizeof(pRect->right),
TRUE, // signed value
1);
*pFlags |= OE2_BCF_DELTA_RIGHT;
}
else
{
*((LPTSHR_UINT16)(*ppNextFreeSpace)) = pRect->right;
*pFlags |= OE2_BCF_RIGHT;
(*ppNextFreeSpace) = (*ppNextFreeSpace) + sizeof(TSHR_UINT16);
}
}
if (m_oe2Tx.LastBounds.bottom != pRect->bottom)
{
if (OE2CanUseDeltaCoords(&pRect->bottom,
&m_oe2Tx.LastBounds.bottom,
sizeof(pRect->bottom),
TRUE, // signed value
1))
{
OE2CopyToDeltaCoords((LPTSHR_INT8*)ppNextFreeSpace,
&pRect->bottom,
&m_oe2Tx.LastBounds.bottom,
sizeof(pRect->bottom),
TRUE, // signed value
1);
*pFlags |= OE2_BCF_DELTA_BOTTOM;
}
else
{
*((LPTSHR_UINT16)(*ppNextFreeSpace)) = pRect->bottom;
*pFlags |= OE2_BCF_BOTTOM;
(*ppNextFreeSpace) = (*ppNextFreeSpace) + sizeof(TSHR_UINT16);
}
}
//
// Copy the rectangle for reference with the next encoding.
//
m_oe2Tx.LastBounds = *pRect;
DebugExitVOID(ASHost::OE2EncodeBounds);
}
//
// OE2_UseFont()
//
BOOL ASHost::OE2_UseFont
(
LPSTR pName,
TSHR_UINT16 facelength,
TSHR_UINT16 CodePage,
TSHR_UINT16 MaxHeight,
TSHR_UINT16 Height,
TSHR_UINT16 Width,
TSHR_UINT16 Weight,
TSHR_UINT16 flags
)
{
BOOL rc = TRUE;
DebugEntry(ASHost::OE2_UseFont);
if ((!m_oe2Tx.LastHFONT) ||
(m_oe2Tx.LastFontFaceLen != facelength) ||
(memcmp(m_oe2Tx.LastFaceName, pName, facelength)) ||
(m_oe2Tx.LastCodePage != CodePage) ||
(m_oe2Tx.LastFontHeight != Height ) ||
(m_oe2Tx.LastFontWidth != Width ) ||
(m_oe2Tx.LastFontWeight != Weight ) ||
(m_oe2Tx.LastFontFlags != flags ))
{
memcpy(m_oe2Tx.LastFaceName, pName, facelength);
m_oe2Tx.LastFaceName[facelength] = '\0';
m_oe2Tx.LastFontFaceLen = facelength;
m_oe2Tx.LastCodePage = CodePage;
m_oe2Tx.LastFontHeight = Height;
m_oe2Tx.LastFontWidth = Width;
m_oe2Tx.LastFontWeight = Weight;
m_oe2Tx.LastFontFlags = flags;
rc = m_pShare->USR_UseFont(m_usrWorkDC,
&m_oe2Tx.LastHFONT,
&m_oe2Tx.LastFontMetrics,
(LPSTR)m_oe2Tx.LastFaceName,
CodePage,
MaxHeight,
Height,
Width,
Weight,
flags);
}
DebugExitBOOL(ASHost::OE2_UseFont, rc);
return(rc);
}
//
// Copy an array of source elements to an array of destination elements,
// converting the types as the copy takes place.
//
// DESTARRAY - The destination array
// SRCARRAY - The source array
// DESTTYPE - The type of the elements in the destination array
// NUMELEMENTS - The number of elements in the array
//
//
#define CONVERT_ARRAY(DESTARRAY, SRCARRAY, DESTTYPE, NUMELEMENTS) \
{ \
UINT index; \
for (index=0 ; index<(NUMELEMENTS) ; index++) \
{ \
(DESTARRAY)[index] = (DESTTYPE)(SRCARRAY)[index]; \
} \
}
//
// OE2EncodeField - see oe2.h
//
void OE2EncodeField(void * pSrc,
LPBYTE* ppDest,
UINT srcFieldLength,
UINT destFieldLength,
BOOL signedValue,
UINT numElements)
{
LPTSHR_UINT8 pSrc8 = (LPTSHR_UINT8)pSrc;
LPTSHR_INT16 pSrc16Signed = (LPTSHR_INT16)pSrc;
LPTSHR_INT32 pSrc32Signed = (LPTSHR_INT32)pSrc;
LPTSHR_INT8 pDest8Signed = (LPTSHR_INT8)*ppDest;
LPTSHR_INT16_UA pDest16Signed = (LPTSHR_INT16_UA)*ppDest;
//
// Note that the source fields may not be aligned correctly, so we use
// unaligned pointers. The destination is aligned correctly.
//
DebugEntry(OE2EncodeField);
//
// We can ignore signed values since we only ever truncate the data.
// Consider the case where we have a 16 bit integer that we want to
// convert to 8 bits. We know our values are permissable within the
// lower integer size (ie. we know the unsigned value will be less
// than 256 of that a signed value will be -128 >= value >= 127), so we
// just need to make sure that we have the right high bit set.
//
// But this must be the case for a 16-bit equivalent of an 8-bit
// number. No problems - just take the truncated integer.
//
//
// Make sure that the destination field length is larger or equal to
// the source field length. If it isn't, something has gone wrong.
//
if (srcFieldLength < destFieldLength)
{
ERROR_OUT(( "Source field length %d is smaller than destination %d",
srcFieldLength,
destFieldLength));
DC_QUIT;
}
//
// If the source and destination field lengths are the same, we can
// just do a copy (no type conversion required).
//
if (srcFieldLength == destFieldLength)
{
memcpy(*ppDest, pSrc, destFieldLength * numElements);
}
else
{
//
// We know that srcFieldLength must be greater than destFieldLength
// because of our checks above. So there are only three
// conversions to consider:
//
// 16 bit -> 8 bit
// 32 bit -> 8 bit
// 32 bit -> 16 bit
//
// We can ignore the sign as all we are ever doing is truncating
// the integer.
//
if ((srcFieldLength == 4) && (destFieldLength == 1))
{
CONVERT_ARRAY(pDest8Signed,
pSrc32Signed,
TSHR_INT8,
numElements);
}
else if ((srcFieldLength == 4) && (destFieldLength == 2))
{
CONVERT_ARRAY(pDest16Signed,
pSrc32Signed,
TSHR_INT16,
numElements);
}
else if ((srcFieldLength == 2) && (destFieldLength == 1))
{
CONVERT_ARRAY(pDest8Signed,
pSrc16Signed,
TSHR_INT8,
numElements);
}
else
{
ERROR_OUT(( "Bad conversion, dest length = %d, src length = %d",
destFieldLength,
srcFieldLength));
}
}
DC_EXIT_POINT:
*ppDest += destFieldLength * numElements;
DebugExitVOID(OE2EncodeField);
}