1326 lines
44 KiB
C++
1326 lines
44 KiB
C++
|
#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);
|
|||
|
}
|
|||
|
|
|||
|
|