Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
MoreTextUtils/MoreTextUtils.cp
/* |
File: MoreTextUtils.cp |
Contains: |
Written by: Pete Gontier |
Copyright: Copyright (c) 1998 Apple Computer, Inc., All Rights Reserved. |
You may incorporate this Apple sample source code into your program(s) without |
restriction. This Apple sample source code has been provided "AS IS" and the |
responsibility for its operation is yours. You are not permitted to redistribute |
this Apple sample source code as "Apple sample source code" after having made |
changes. If you're going to re-distribute the source, we require that you make |
it clear in the source that the code was descended from Apple sample source |
code, but that you've made changes. |
Change History (most recent first): |
<6> 20/3/00 Quinn Added MoreReplaceText and its support routines. Added |
MoreStrLen. Tidied up a little. |
<5> 1/3/00 Quinn Minor Carbonation changes. |
<4> 21/4/99 Quinn Added ValidStringListHandle. |
<3> 2/15/99 PCG InlineGetHandleSize loses the Inline |
<2> 11/11/98 PCG fix header |
<1> 11/10/98 PCG first big re-org at behest of Quinn |
Old Change History (most recent first): |
<2> 10/23/98 PCG add GetStringFromLongDouble |
<1> 6/16/98 PCG initial checkin |
*/ |
///////////////////////////////////////////////////////////////// |
// MoreIsBetter Setup |
#include "MoreSetup.h" |
// Our Prototypes |
#include "MoreTextUtils.h" |
// Mac OS Interfaces |
#include <Resources.h> |
#include <PLStringFuncs.h> |
#include <Fonts.h> |
// MIB Prototypes |
#include "MoreMemory.h" |
#include "MoreQuickDraw.h" |
///////////////////////////////////////////////////////////////// |
pascal OSErr NewStringPtr (ConstStr255Param init, UInt8 maxSize, StringPtr *result) |
{ |
OSErr err = noErr; |
if (!MoreAssert (result && (!init || (*init <= maxSize)))) |
err = paramErr; |
else |
{ |
*result = StringPtr (NewPtr (1 + (maxSize ? maxSize : (init ? *init : 255)))); |
if (!*result) |
err = MemError ( ); |
else if (init && *init) |
PLstrcpy (*result,init); |
else |
**result = 0; |
} |
return err; |
} |
pascal OSErr NewStringListHandle (Handle *h) |
{ |
DebugStr ("\pThis routine has never been traced."); |
if (!MoreAssert (h)) |
return nilHandleErr; |
*h = NewHandleClear (sizeof (UInt16)); |
if (!*h) |
return MemError ( ); |
return noErr; |
} |
pascal OSErr AppendStringToListHandle (ConstStr255Param str, Handle h) |
{ |
DebugStr ("\pThis routine has never been traced."); |
OSErr err = noErr; |
if (!MoreAssert (h && *h)) |
err = nilHandleErr; |
else |
{ |
UInt8 dummyZero; |
if (!str) |
{ |
dummyZero = 0; |
str = &dummyZero; |
} |
if (!(err = PtrAndHand (str, h, *str + 1))) |
(** (UInt16 **) h) += 1; |
} |
return err; |
} |
pascal OSErr GetNewStringList (short resID, tStringListP *newStringList) |
{ |
OSErr err = noErr; |
Handle h = GetResource ('STR#',resID); |
if (!h) |
{ |
err = ResError ( ); |
if (!err) err = resNotFound; |
} |
else |
{ |
Size handleSize = GetHandleSize (h); |
(void) MoreAssert (MemError ( ) == noErr); |
if (handleSize < 2) |
err = paramErr; |
else |
{ |
UInt16 stringCount = ** (UInt16 **) h; |
Size stringListSize = sizeof (**newStringList) + (handleSize - 2) + |
(stringCount * sizeof (StringPtr)); |
*newStringList = (tStringListP) NewPtr (stringListSize); |
if (!*newStringList) |
err = MemError ( ); |
else |
{ |
(*newStringList)->count = stringCount; |
if (stringCount) |
{ |
UInt16 index = 0; |
StringPtr stringScan = (StringPtr) ((*newStringList)->list + stringCount); |
BlockMoveData (2 + *h, stringScan, handleSize - 2); |
do |
{ |
(*newStringList)->list [index] = stringScan; |
stringScan += *stringScan + 1; |
} |
while (++index < stringCount); |
} |
} |
} |
ReleaseResource (h); |
(void) MoreAssert (ResError ( ) == noErr); |
} |
return err; |
} |
pascal Boolean ValidStringListHandle(Handle stringList) |
// See comment in interface part. |
{ |
Boolean result; |
UInt16 stringCount; |
UInt16 stringIndex; |
UInt8* cursor; |
UInt8* bound; |
ByteCount stringListLength; |
result = true; |
if (stringList == NULL || *stringList == NULL || GetHandleSize(stringList) < sizeof(UInt16) ) { |
result = false; |
} |
if (result) { |
stringCount = *((UInt16 *) *stringList); |
stringListLength = GetHandleSize(stringList); |
// From here down we have to make sure we do nothing to move |
// or purge until we're done with cursor and bound. |
cursor = ((UInt8 *)*stringList) + sizeof(UInt16); |
bound = ((UInt8 *)*stringList) + stringListLength; |
for (stringIndex = 0; stringIndex < stringCount; stringIndex++) { |
if ( cursor < bound ) { |
cursor += *cursor + 1; |
} else { |
result = false; |
break; |
} |
} |
if (result) { |
if ( cursor != bound ) { |
result = false; |
} |
} |
} |
return result; |
} |
pascal OSErr GetPascalStringFromLongDouble (long double d, SInt8 precision, StringPtr buf) |
{ |
OSErr err = noErr; |
*buf = 0; |
// If client requests more precision than is available, bitch. |
if (!MoreAssert (precision < SIGDIGLEN)) |
err = paramErr; |
else |
{ |
// If precision is less than 0, client is requesting |
// as much precision as is available. |
if (precision < 0) |
precision = SIGDIGLEN; |
// Try normal notation, and if that overflows, |
// fall back to scientific notation (bleah!). |
decimal dec; |
decform df = { 1, 0, precision }; |
num2dec (&df,d,&dec); |
if (dec.sig.text [0] == '?') |
{ |
df.style = 0; |
df.digits = SIGDIGLEN; |
num2dec (&df,d,&dec); |
} |
if (*(dec.sig.text) == '0') |
PLstrcpy (buf,"\p0"); |
else if (*(dec.sig.text) == 'I') |
PLstrcpy (buf,"\p[INF]"); |
else if (*(dec.sig.text) == 'N') |
PLstrcpy (buf,"\p[NaN]"); |
else |
{ |
// Finally, convert it to a pascal string... |
dec2str (&df,&dec,(Ptr)buf); |
CopyCStringToPascal( (char *) buf, buf ); |
// ...and trim trailing zeroes. |
// if (df.style == 1 && dec.exp < 0) |
// while (buf [*buf] == '0') |
// *buf -= 1; |
} |
} |
return err; |
} |
// gDummyPort is a pointer to a dummy GrafPort whose font is always |
// the system font. By setting thePort to this port, we can then safely |
// call Script Manager that get script information from the current port. |
static GrafPtr gDummyPort; |
extern pascal OSStatus InitMoreTextUtils(void) |
// See comment in header. |
{ |
OSStatus err; |
GrafPtr oldPort; |
// Preserve the current port. |
GetPort(&oldPort); |
// Create gDummyPort. |
gDummyPort = (GrafPtr) CreateNewPort(); |
err = MoreMemError(gDummyPort); |
if (err == noErr) { |
// CreateNewPort, if it follows the semantics of the old |
// OpenPort routine, should set thePort to the new port. |
// This assert ensures that behaviour, because the following |
// call to TextFont relies on it. |
#if MORE_DEBUG |
{ |
GrafPtr junkPort; |
GetPort(&junkPort); |
MoreAssertQ(junkPort == gDummyPort); |
} |
#endif |
// Set the dummy portÕs font to the system font. |
TextFont(systemFont); |
} |
SetPort(oldPort); |
return err; |
} |
extern pascal void TermMoreTextUtils(void) |
// See comment in header. |
{ |
if (gDummyPort != nil) { |
DisposePort( (CGrafPtr) gDummyPort); |
gDummyPort = nil; |
} |
} |
extern pascal void MoreReplaceText(Str255 baseText, ConstStr255Param substitutionText, ConstStr15Param key) |
// See comment in header. |
{ |
OSStatus err; |
GrafPtr oldPort; |
Handle baseTextH; |
Handle substitutionTextH; |
Size newLength; |
UInt8 *tmpKey; |
MoreAssertQ(baseText != nil); |
MoreAssertQ(substitutionText != nil); |
MoreAssertQ(key != nil); |
MoreAssertQ(key[0] <= 15); |
GetPort(&oldPort); |
baseTextH = nil; |
substitutionTextH = nil; |
// Copy the strings into handles, call ReplaceText, then |
// copy the result back into baseText (making sure that |
// there is at most 255 bytes in the resulting string). |
err = noErr; |
if (gDummyPort == nil) { |
err = InitMoreTextUtils(); |
} |
if (err == noErr) { |
SetPort(gDummyPort); |
err = PtrToHand(&baseText[1], &baseTextH, baseText[0]); |
} |
if (err == noErr) { |
err = PtrToHand(&substitutionText[1], &substitutionTextH, substitutionText[0]); |
} |
if (err == noErr) { |
tmpKey = (UInt8 *) key; |
err = ReplaceText(baseTextH, substitutionTextH, tmpKey); |
if (err >= 0) { |
newLength = GetHandleSize(baseTextH); |
if (newLength > 255) { |
newLength = 255; |
} |
baseText[0] = newLength; |
BlockMoveData(*baseTextH, &baseText[1], newLength); |
err = noErr; |
} |
} |
// Clean up. |
if (baseTextH != nil) { |
DisposeHandle(baseTextH); |
MoreAssertQ(MemError() == noErr); |
} |
if (substitutionTextH != nil) { |
DisposeHandle(substitutionTextH); |
MoreAssertQ(MemError() == noErr); |
} |
SetPort(oldPort); |
MoreAssert(err == noErr); |
} |
extern pascal ByteCount MoreStrLen(const char *str) |
// See comment in header. |
{ |
ByteCount result; |
result = 0; |
while ( *str != 0 ) { |
result += 1; |
str += 1; |
} |
return result; |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-07-22