Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

709 lines
19 KiB

/**************************************************************************\
*
* Copyright (c) 1998 Microsoft Corporation
*
* Module Name:
*
* stringFormat.hpp
*
* Abstract:
*
* String and text format definition
*
* Revision History:
*
* 08/05/1999 dbrown
* Created it.
*
\**************************************************************************/
#ifndef _STRINGFORMAT_HPP
#define _STRINGFORMAT_HPP
const REAL DefaultMargin = REAL(1.0/6.0);
const REAL DefaultTracking = REAL(1.03);
const REAL DefaultBottomMargin = REAL(1.0/8.0);
const INT DefaultFormatFlags = 0;
const StringTrimming DefaultTrimming = StringTrimmingCharacter;
// Private StringFormatFlags
const INT StringFormatFlagsPrivateNoGDI = 0x80000000;
const INT StringFormatFlagsPrivateAlwaysUseFullImager = 0x40000000;
const INT StringFormatFlagsPrivateUseNominalAdvance = 0x20000000;
const INT StringFormatFlagsPrivateFormatPersisted = 0x10000000;
class StringFormatRecordData : public ObjectData
{
public:
INT32 Flags;
LANGID Language;
GpStringAlignment StringAlign;
GpStringAlignment LineAlign;
GpStringDigitSubstitute DigitSubstitute;
LANGID DigitLanguage;
REAL FirstTabOffset;
INT32 HotkeyPrefix;
REAL LeadingMargin;
REAL TrailingMargin;
REAL Tracking;
StringTrimming Trimming;
INT32 CountTabStops;
INT32 RangeCount;
};
//
// Represent a string format object
//
class GpStringFormat : public GpObject
{
protected:
VOID SetValid(BOOL valid)
{
GpObject::SetValid(valid ? ObjectTagStringFormat : ObjectTagInvalid);
}
public:
GpStringFormat() :
Flags (DefaultFormatFlags),
Language (LANG_NEUTRAL),
StringAlign (StringAlignmentNear),
LineAlign (StringAlignmentNear),
DigitSubstitute (StringDigitSubstituteUser),
DigitLanguage (LANG_NEUTRAL),
FirstTabOffset (0.0),
TabStops (NULL),
CountTabStops (0),
HotkeyPrefix (HotkeyPrefixNone),
LeadingMargin (DefaultMargin),
TrailingMargin (DefaultMargin),
Tracking (DefaultTracking),
Trimming (StringTrimmingCharacter),
Ranges (NULL),
RangeCount (0),
Permanent (FALSE)
{
SetValid(TRUE); // default is valid
}
GpStringFormat(INT flags, LANGID language) :
Flags (flags),
Language (language),
StringAlign (StringAlignmentNear),
LineAlign (StringAlignmentNear),
DigitSubstitute (StringDigitSubstituteUser),
DigitLanguage (LANG_NEUTRAL),
FirstTabOffset (0.0),
TabStops (NULL),
CountTabStops (0),
HotkeyPrefix (HotkeyPrefixNone),
LeadingMargin (DefaultMargin),
TrailingMargin (DefaultMargin),
Tracking (DefaultTracking),
Trimming (StringTrimmingCharacter),
Ranges (NULL),
RangeCount (0),
Permanent (FALSE)
{
SetValid(TRUE); // default is valid
}
~GpStringFormat()
{
if (TabStops)
delete [] TabStops;
if (Ranges)
delete [] Ranges;
}
static GpStringFormat *GenericDefault();
static GpStringFormat *GenericTypographic();
static void DestroyStaticObjects()
{
// these objects are created as a static but constructed in the
// GenericDefault() and GenericTypographic(). we need to destruct
// it just in case the user called SetTapStop which allocate memory
// inside this object and by this way we prevent any memory leak.
if (GenericDefaultPointer != NULL)
{
GenericDefaultPointer->~GpStringFormat();
// Zero the memory - this is risky code, so we want the memory
// to match what it was when GDI+ started up.
memset(GenericDefaultPointer, 0, sizeof(GpStringFormat));
GenericDefaultPointer = NULL;
}
if (GenericTypographicPointer != NULL)
{
GenericTypographicPointer->~GpStringFormat();
// Zero the memory - this is risky code, so we want the memory
// to match what it was when GDI+ started up.
memset(GenericTypographicPointer, 0, sizeof(GpStringFormat));
GenericTypographicPointer = NULL;
}
return;
}
GpStringFormat *Clone() const;
GpStatus SetFormatFlags(INT flags)
{
if (Flags != flags)
{
Flags = flags;
UpdateUid();
}
return Ok;
}
INT GetFormatFlags() const
{
return Flags;
}
GpStatus SetAlign(GpStringAlignment align)
{
if (StringAlign != align)
{
StringAlign = align;
UpdateUid();
}
return Ok;
}
GpStatus GetAlign(GpStringAlignment *align) const
{
*align = StringAlign;
return Ok;
}
GpStringAlignment GetPhysicalAlignment() const
{
if ( !(Flags & StringFormatFlagsDirectionRightToLeft)
|| StringAlign == StringAlignmentCenter
|| Flags & StringFormatFlagsDirectionVertical)
{
return StringAlign;
}
else if (StringAlign == StringAlignmentNear)
{
return StringAlignmentFar; // RTL near = right
}
else
{
return StringAlignmentNear; // RTL far = left
}
}
GpStringAlignment GetAlign() const
{
return StringAlign;
}
GpStatus SetLineAlign(GpStringAlignment align)
{
if (LineAlign != align)
{
LineAlign = align;
UpdateUid();
}
return Ok;
}
GpStatus GetLineAlign(GpStringAlignment *align) const
{
*align = LineAlign;
return Ok;
}
GpStringAlignment GetLineAlign() const
{
return LineAlign;
}
GpStatus SetHotkeyPrefix (INT hotkeyPrefix)
{
if (HotkeyPrefix != hotkeyPrefix)
{
HotkeyPrefix = hotkeyPrefix;
UpdateUid();
}
return Ok;
}
GpStatus GetHotkeyPrefix (INT *hotkeyPrefix) const
{
if (!hotkeyPrefix)
return InvalidParameter;
*hotkeyPrefix = HotkeyPrefix;
return Ok;
}
INT GetHotkeyPrefix () const
{
return HotkeyPrefix;
}
GpStatus SetTabStops (
REAL firstTabOffset,
INT countTabStops,
const REAL *tabStops
)
{
if (countTabStops > 0)
{
// We do not support negative tabulation (tab position
// advances in the opposite direction of reading order)
if (firstTabOffset < 0)
{
return NotImplemented;
}
for (INT i = 0; i < countTabStops; i++)
{
if (tabStops[i] < 0)
{
return NotImplemented;
}
}
REAL *newTabStops = new REAL [countTabStops];
if (!newTabStops)
{
return OutOfMemory;
}
if (TabStops)
{
delete [] TabStops;
}
TabStops = newTabStops;
GpMemcpy (TabStops, tabStops, sizeof(REAL) * countTabStops);
CountTabStops = countTabStops;
FirstTabOffset = firstTabOffset;
UpdateUid();
}
return Ok;
}
GpStatus GetTabStopCount (
INT *countTabStops
) const
{
if (!countTabStops)
{
return InvalidParameter;
}
*countTabStops = CountTabStops;
return Ok;
}
GpStatus GetTabStops (
REAL *firstTabOffset,
INT countTabStops,
REAL *tabStops
) const
{
if ( !firstTabOffset
|| !tabStops)
{
return InvalidParameter;
}
INT count;
if (countTabStops <= CountTabStops)
count = countTabStops;
else
count = CountTabStops;
GpMemcpy(tabStops, TabStops, sizeof(REAL) * count);
*firstTabOffset = FirstTabOffset;
return Ok;
}
INT GetTabStops (
REAL *firstTabOffset,
REAL **tabStops
) const
{
*firstTabOffset = FirstTabOffset;
*tabStops = TabStops;
return CountTabStops;
}
GpStatus SetMeasurableCharacterRanges(
INT rangeCount,
const CharacterRange *ranges
);
INT GetMeasurableCharacterRanges(
CharacterRange **ranges = NULL
) const
{
if (ranges)
{
*ranges = Ranges;
}
return RangeCount;
}
GpStatus SetDigitSubstitution(
LANGID language,
StringDigitSubstitute substitute = StringDigitSubstituteNational
)
{
if (DigitSubstitute != substitute || DigitLanguage != language)
{
DigitSubstitute = substitute;
DigitLanguage = language;
UpdateUid();
}
return Ok;
}
GpStatus GetDigitSubstitution(
LANGID *language,
StringDigitSubstitute *substitute
) const
{
if(substitute)
{
*substitute = DigitSubstitute;
}
if(language)
{
*language = DigitLanguage;
}
return Ok;
}
GpStatus SetLeadingMargin(REAL margin)
{
if (LeadingMargin != margin)
{
LeadingMargin = margin;
UpdateUid();
}
return Ok;
}
REAL GetLeadingMargin() const
{
return LeadingMargin;
}
GpStatus SetTrailingMargin(REAL margin)
{
if (TrailingMargin != margin)
{
TrailingMargin = margin;
UpdateUid();
}
return Ok;
}
REAL GetTrailingMargin() const
{
return TrailingMargin;
}
GpStatus SetTracking(REAL tracking)
{
if (Tracking != tracking)
{
Tracking = tracking;
UpdateUid();
}
return Ok;
}
REAL GetTracking() const
{
return Tracking;
}
GpStatus SetTrimming(StringTrimming trimming)
{
if (Trimming != trimming)
{
Trimming = trimming;
UpdateUid();
}
return Ok;
}
GpStatus GetTrimming(StringTrimming *trimming) const
{
ASSERT(trimming != NULL);
if (trimming == NULL)
{
return InvalidParameter;
}
*trimming = Trimming;
return Ok;
}
virtual BOOL IsValid() const
{
// If the string format came from a different version of GDI+, its tag
// will not match, and it won't be considered valid.
return GpObject::IsValid(ObjectTagStringFormat);
}
virtual ObjectType GetObjectType() const { return ObjectTypeStringFormat; }
virtual GpStatus GetData(IStream * stream) const
{
ASSERT (stream);
StringFormatRecordData stringFormatData;
stringFormatData.Flags = Flags;
stringFormatData.Language = Language;
stringFormatData.StringAlign = StringAlign;
stringFormatData.LineAlign = LineAlign;
stringFormatData.DigitSubstitute = DigitSubstitute;
stringFormatData.DigitLanguage = DigitLanguage;
stringFormatData.FirstTabOffset = FirstTabOffset;
stringFormatData.LineAlign = LineAlign;
stringFormatData.CountTabStops = CountTabStops;
stringFormatData.HotkeyPrefix = HotkeyPrefix;
stringFormatData.LeadingMargin = LeadingMargin;
stringFormatData.TrailingMargin = TrailingMargin;
stringFormatData.Tracking = Tracking;
stringFormatData.Trimming = Trimming;
stringFormatData.CountTabStops = CountTabStops;
stringFormatData.RangeCount = RangeCount;
stream->Write(
&stringFormatData,
sizeof(stringFormatData),
NULL
);
stream->Write(
TabStops,
CountTabStops * sizeof(TabStops[0]),
NULL
);
stream->Write(
Ranges,
RangeCount * sizeof(Ranges[0]),
NULL
);
return Ok;
}
virtual UINT GetDataSize() const
{
UINT size = sizeof(StringFormatRecordData);
size += (CountTabStops * sizeof(TabStops[0]));
size += (RangeCount * sizeof(Ranges[0]));
return size;
}
virtual GpStatus SetData(const BYTE * dataBuffer, UINT size)
{
if ((dataBuffer == NULL) || (size < (sizeof(StringFormatRecordData) - sizeof(REAL))))
{
WARNING(("dataBuffer too small"));
return InvalidParameter;
}
const StringFormatRecordData *stringFormatData =
(const StringFormatRecordData *)dataBuffer;
if (!stringFormatData->MajorVersionMatches())
{
WARNING(("Version number mismatch"));
return InvalidParameter;
}
Flags = stringFormatData->Flags | StringFormatFlagsPrivateFormatPersisted;
Language = stringFormatData->Language;
StringAlign = stringFormatData->StringAlign;
LineAlign = stringFormatData->LineAlign;
DigitSubstitute = stringFormatData->DigitSubstitute;
DigitLanguage = stringFormatData->DigitLanguage;
FirstTabOffset = stringFormatData->FirstTabOffset;
LineAlign = stringFormatData->LineAlign;
CountTabStops = stringFormatData->CountTabStops;
HotkeyPrefix = stringFormatData->HotkeyPrefix;
LeadingMargin = stringFormatData->LeadingMargin;
TrailingMargin = stringFormatData->TrailingMargin;
Tracking = stringFormatData->Tracking;
Trimming = stringFormatData->Trimming;
CountTabStops = stringFormatData->CountTabStops;
RangeCount = stringFormatData->RangeCount;
if (size <
( sizeof(StringFormatRecordData)
+ sizeof(TabStops[0]) * CountTabStops
+ sizeof(Ranges[0]) * RangeCount))
{
return InvalidParameter;
}
// Propagate tab stops
if (TabStops)
{
delete [] TabStops;
}
TabStops = new REAL [CountTabStops];
if (TabStops == NULL)
{
return OutOfMemory;
}
REAL *tabStops = (REAL *)(&stringFormatData[1]);
for (INT i = 0; i < CountTabStops; i++)
{
TabStops[i] = tabStops[i];
}
// Propagate ranges
if (Ranges)
{
delete [] Ranges;
}
Ranges = new CharacterRange [RangeCount];
if (Ranges == NULL)
{
if (TabStops)
{
delete [] TabStops;
}
return OutOfMemory;
}
CharacterRange *ranges = (CharacterRange *)(&tabStops[CountTabStops]);
for (INT i = 0; i < RangeCount; i++)
{
Ranges[i] = ranges[i];
}
UpdateUid();
return Ok;
}
BOOL IsPermanent() const
{
return Permanent;
}
// we override the new operator for this class just to use it for object
// placement. we didn't make the new placemenet global because it will
// conflict with office because they link with GdiPlus statically.
// we didn't override the delete operator because it is fine to use the
// global one in \engine\runtime\Mem.h
void* operator new(size_t size)
{
return GpMalloc(size);
}
void* operator new(size_t size, void* p)
{
return p;
}
// Digit Substitution
const ItemScript GetDigitScript() const
{
return GetDigitSubstitutionsScript(DigitSubstitute, DigitLanguage);
}
private:
INT Flags;
LANGID Language;
GpStringAlignment StringAlign;
GpStringAlignment LineAlign;
GpStringDigitSubstitute DigitSubstitute;
LANGID DigitLanguage;
REAL FirstTabOffset;
REAL *TabStops; // absolute tab stops in world unit
INT CountTabStops;
INT HotkeyPrefix;
REAL LeadingMargin; // relative to body font em size
REAL TrailingMargin; // relative to body font em size
REAL Tracking; // scale factor
GpStringTrimming Trimming;
CharacterRange *Ranges; // character ranges
INT RangeCount; // number of ranges
BOOL Permanent;
GpStringFormat(const GpStringFormat &format)
{
// This should never get called! Use Clone instead!
ASSERT(FALSE);
}
// The following static variables support the generic StringFormats
// Pointers (initialised at load time to null)
static GpStringFormat *GenericDefaultPointer;
static GpStringFormat *GenericTypographicPointer;
// Memory allocation for generic structures. Note that we must allocate
// load time memory as BYTE arrays to avoid creating a dependency on
// the CRT for class construction.
// The definitions (which specify the size) are in StringFormat.cpp.
static BYTE GenericDefaultStaticBuffer[];
static BYTE GenericTypographicStaticBuffer[];
};
#endif // !_STRINGFORMAT_HPP