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.
Relevant replacement documents include:
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-01-14