Annotation of kernel/bsd/hfs/hfscommon/Unicode/UnicodeWrappers.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
        !             7:  * Reserved.  This file contains Original Code and/or Modifications of
        !             8:  * Original Code as defined in and that are subject to the Apple Public
        !             9:  * Source License Version 1.1 (the "License").  You may not use this file
        !            10:  * except in compliance with the License.  Please obtain a copy of the
        !            11:  * License at http://www.apple.com/publicsource and read it before using
        !            12:  * this file.
        !            13:  * 
        !            14:  * The Original Code and all software distributed under the License are
        !            15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            19:  * License for the specific language governing rights and limitations
        !            20:  * under the License.
        !            21:  * 
        !            22:  * @APPLE_LICENSE_HEADER_END@
        !            23:  */
        !            24: 
        !            25: /*
        !            26:        File:           UnicodeWrappers.c
        !            27: 
        !            28:        Contains:       Wrapper routines for Unicode conversion and comparison.
        !            29: 
        !            30:        Version:        HFS Plus 1.0
        !            31: 
        !            32:        Written by:     Mark Day
        !            33: 
        !            34:        Copyright:      � 1996-1999 by Apple Computer, Inc., all rights reserved.
        !            35: 
        !            36:        File Ownership:
        !            37: 
        !            38:                DRI:                            Mark Day
        !            39: 
        !            40:                Other Contact:          Don Brady
        !            41: 
        !            42:                Technology:                     xxx put technology here xxx
        !            43: 
        !            44:        Writers:
        !            45: 
        !            46:                (DSH)   Deric Horn
        !            47:                (msd)   Mark Day
        !            48:                (djb)   Don Brady
        !            49: 
        !            50:        Change History (most recent first):
        !            51:       <Rhap>    2/09/99        djb             Fix UnicodeToMacRoman to handle a terminating decomposed char.
        !            52:       <Rhap>    1/22/99        djb             Add more TARGET_OS_MAC conditionals to remove orphaned code.
        !            53:       <Rhap>     7/6/98        djb             Handle hi-bit Mac Roman characters in basic latin conversions (radar #2247519).
        !            54:       <Rhap>    6/11/98        PPD             Added a few special-case ASCII/Unicode mappings to cover installer's needs.
        !            55:          <Rhap>         3/31/98        djb             Sync up with final HFSVolumes.h header file.
        !            56: 
        !            57:          <CS41>         1/28/98        msd             Bug 2207446: When mangling a name, check to see if the Unicode
        !            58:                                                                        Converter is installed before we call it.
        !            59:          <CS40>         1/21/98        msd             Bug 2206836: If a name contains a colon, change it to question
        !            60:                                                                        mark and mangle the name.
        !            61:          <CS39>        12/11/97        msd             For Metrowerks and test tools, call the Get_xxx routines to get
        !            62:                                                                        the Unicode table addresses.
        !            63:          <CS38>        12/10/97        djb             Radar #2005461, don't use fallback chars when converting to
        !            64:                                                                        Unicode, instead let the client (Catalog) retry with MacRoman.
        !            65:          <CS37>         12/2/97        DSH             Conditionalize out some unicode related routines for DFA
        !            66:          <CS36>        11/26/97        djb             Radar #2005461,2005688 don't swallow kTECPartialCharErr errors!
        !            67:          <CS35>        11/17/97        djb             Name mangling was broken with decomposed Unicode.
        !            68:          <CS34>        11/16/97        djb             Radar #2001928 - use kUnicodeCanonicalDecompVariant variant.
        !            69:          <CS33>        11/11/97        DSH             Use Get_gLowerCaseTable for DiskFirstAid builds to avoid loading
        !            70:                                                                        in a branch to the table.
        !            71:          <CS32>         11/7/97        msd             Replace FastSimpleCompareStrings with FastUnicodeCompare (which
        !            72:                                                                        handles ignorable Unicode characters). Remove the wrapper
        !            73:                                                                        routine, CompareUnicodeNames, and have its callers call
        !            74:                                                                        FastUnicodeCompare directly.
        !            75:          <CS31>        10/17/97        djb             Change kUnicodeUseHFSPlusMapping to kUnicodeUseLatestMapping.
        !            76:          <CS30>        10/17/97        msd             Fix some type casts for char pointers.
        !            77:          <CS29>        10/13/97        djb             Add new SPIs for Finder View font (radar #1679073).
        !            78:          <CS28>         10/1/97        djb             Preserve current heap zone in InitializeEncodingContext routine
        !            79:                                                                        (radar #1682686).
        !            80:          <CS27>         9/17/97        djb             Handle kTECPartialCharErr errors in ConvertHFSNameToUnicode.
        !            81:          <CS26>         9/16/97        msd             In MockConvertFromPStringToUnicode, use pragma unused instead of
        !            82:                                                                        commenting out unused parameter (so SC will compile it).
        !            83:          <CS25>         9/15/97        djb             Fix MockConverters to do either 7-bit ascii or else mangle the
        !            84:                                                                        name (radar #1672388). Use 'p2u#' resource for bootstrapping
        !            85:                                                                        Unicode. Make sure InitializeEncodingContext uses System heap.
        !            86:          <CS24>         9/10/97        msd             Make InitializeEncodingContext public.
        !            87:          <CS23>          9/7/97        djb             Handle '�' char in BasicLatinUnicode converter.
        !            88:          <CS22>          9/4/97        djb             Add logging to BasicLatinUnicodeToPascal.
        !            89:          <CS21>         8/26/97        djb             Make FastSimpleCompareStrings faster. Add
        !            90:                                                                        BasicLatinUnicodeToPascal to make 7-bit ascii conversions
        !            91:                                                                        faster.
        !            92:          <CS20>         8/14/97        djb             Add FastRelString here (to be next to the data tables).
        !            93:          <CS19>         7/21/97        djb             LogEndTime now takes an error code.
        !            94:          <CS18>         7/18/97        msd             Include LowMemPriv.h, Gestalt.h, TextUtils.h.
        !            95:          <CS17>         7/16/97        DSH             FilesInternal.i renamed FileMgrInternal.i to avoid name
        !            96:                                                                        collision
        !            97:          <CS16>          7/8/97        DSH             Loading PrecompiledHeaders from define passed in on C line
        !            98:          <CS15>          7/8/97        DSH             InitializeUnicode changed its API
        !            99:          <CS14>          7/1/97        DSH             SC, DFA complier, requires parameters in functions. #pragma'd
        !           100:                                                                        them out to eliminate C warnings.
        !           101:          <CS13>         6/30/97        msd             Remove unused parameter warnings in FallbackProc by commenting
        !           102:                                                                        out unused parameter names.
        !           103:          <CS12>         6/26/97        DSH             FallbackProc declare variables before useage for SC,
        !           104:                                                                        MockConverters no longer static for DFA.
        !           105:          <CS11>         6/25/97        msd             In function InitStaticUnicodeConverter, the variable fsVars was
        !           106:                                                                        being used before being initialized.
        !           107:          <CS10>         6/24/97        DSH             Runtime checks to call through CFM or static linked routines.
        !           108:           <CS9>         6/20/97        msd             Re-introduce fix from <CS7>. Fix another missing cast. Remove a
        !           109:                                                                        spurious semicolon.
        !           110:           <CS8>         6/18/97        djb             Add more ConversionContexts routines. Improved file mangling.
        !           111:           <CS7>         6/16/97        msd             Add a missing cast in GetFileIDString.
        !           112:           <CS6>         6/13/97        djb             Added support for long filenames. Switched to
        !           113:                                                                        ConvertUnicodeToHFSName, ConvertHFSNameToUnicode, and
        !           114:                                                                        CompareUnicodeNames.
        !           115:           <CS5>          6/4/97        djb             Use system script instead of macRoman.
        !           116:           <CS4>         5/19/97        djb             Add call to LockMappingTable so tables won't move!
        !           117:           <CS3>          5/9/97        djb             Include HFSInstrumentation.h
        !           118:           <CS2>          5/7/97        djb             Add summary traces. Add FastSimpleCompareStrings routine.
        !           119:           <CS1>         4/24/97        djb             first checked in
        !           120:          <HFS5>         3/27/97        djb             Add calls to real Unicode conversion routines.
        !           121:          <HFS4>          2/6/97        msd             Add conditional code to use real Unicode comparison routines
        !           122:                                                                        (default to off).
        !           123:          <HFS3>          1/6/97        djb             Fix HFSUnicodeCompare - the final comparison of length1 and
        !           124:                                                                        length2 was backwards.
        !           125:          <HFS2>        12/12/96        msd             Use precompiled headers.
        !           126:          <HFS1>        12/12/96        msd             first checked in
        !           127: 
        !           128: */
        !           129: 
        !           130: #if ( PRAGMA_LOAD_SUPPORTED )
        !           131:         #pragma        load    PrecompiledHeaders
        !           132: #else
        !           133:         #if TARGET_OS_MAC
        !           134:         #include       <CodeFragments.h>
        !           135:         #include       <Errors.h>
        !           136:         #include       <MixedModePriv.h>
        !           137:         #include       <Script.h>
        !           138:         #include       <UnicodeConverter.h>
        !           139:         #include       <LowMemPriv.h>
        !           140:         #include       <Gestalt.h>
        !           141:         #include       <TextUtils.h>
        !           142:         #else
        !           143:         #include "../headers/system/MacOSStubs.h"
        !           144:         #endif         /* TARGET_OS_MAC */
        !           145: #endif /* PRAGMA_LOAD_SUPPORTED */
        !           146: 
        !           147: #if TARGET_OS_MAC
        !           148: #include       <IntlResources.h>
        !           149: #include       <TextCommonPriv.h>
        !           150: #include       <UnicodeConverterPriv.h>
        !           151: #include       <FileMgrResources.h>
        !           152: #endif         /* TARGET_OS_MAC */
        !           153: 
        !           154: #if TARGET_OS_RHAPSODY
        !           155: #include "UCStringCompareData.h"
        !           156: #endif /* TARGET_OS_RHAPSODY */
        !           157: 
        !           158: #include "../headers/FileMgrInternal.h"
        !           159: #include "../headers/system/HFSUnicodeWrappers.h"
        !           160: #include "../headers/system/HFSInstrumentation.h"
        !           161: 
        !           162: #include "ConvertUTF.h"
        !           163: 
        !           164: #ifdef __MWERKS__
        !           165: #define USE_TABLE_ACCESSORS    1
        !           166: #endif
        !           167: 
        !           168: #ifndef USE_TABLE_ACCESSORS
        !           169: #define USE_TABLE_ACCESSORS    0
        !           170: #endif
        !           171: 
        !           172: 
        !           173: #if TARGET_OS_MAC
        !           174: enum {
        !           175:        uupCreateTextToUnicodeInfoProcInfo =
        !           176:                kPascalStackBased
        !           177:                | RESULT_SIZE(SIZE_CODE(sizeof(OSStatus)))
        !           178:                | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(ConstUnicodeMappingPtr)))
        !           179:                | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(TextToUnicodeInfo*))),
        !           180: 
        !           181: 
        !           182:        uppCreateUnicodeToTextInfoProcInfo =
        !           183:                kPascalStackBased
        !           184:                | RESULT_SIZE(SIZE_CODE(sizeof(OSStatus)))
        !           185:                | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(ConstUnicodeMappingPtr)))
        !           186:                | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(UnicodeToTextInfo*))),
        !           187: 
        !           188: 
        !           189:        uppConvertFromTextToUnicodeProcInfo =
        !           190:                kPascalStackBased
        !           191:                | RESULT_SIZE(SIZE_CODE(sizeof(OSStatus)))
        !           192:                | STACK_ROUTINE_PARAMETER(1,  SIZE_CODE(sizeof(TextToUnicodeInfo)))
        !           193:                | STACK_ROUTINE_PARAMETER(2,  SIZE_CODE(sizeof(ByteCount)))
        !           194:                | STACK_ROUTINE_PARAMETER(3,  SIZE_CODE(sizeof(ConstLogicalAddress)))
        !           195:                | STACK_ROUTINE_PARAMETER(4,  SIZE_CODE(sizeof(OptionBits)))
        !           196:                | STACK_ROUTINE_PARAMETER(5,  SIZE_CODE(sizeof(ItemCount)))
        !           197:                | STACK_ROUTINE_PARAMETER(6,  SIZE_CODE(sizeof(ByteOffset*)))
        !           198:                | STACK_ROUTINE_PARAMETER(7,  SIZE_CODE(sizeof(ItemCount*)))
        !           199:                | STACK_ROUTINE_PARAMETER(8,  SIZE_CODE(sizeof(ByteOffset*)))
        !           200:                | STACK_ROUTINE_PARAMETER(9,  SIZE_CODE(sizeof(ByteCount)))
        !           201:                | STACK_ROUTINE_PARAMETER(10, SIZE_CODE(sizeof(ByteCount*)))
        !           202:                | STACK_ROUTINE_PARAMETER(11, SIZE_CODE(sizeof(ByteCount*)))
        !           203:                | STACK_ROUTINE_PARAMETER(12, SIZE_CODE(sizeof(UniCharArrayPtr))),
        !           204: 
        !           205:         
        !           206:        uppConvertFromUnicodeToTextProcInfo =
        !           207:                kPascalStackBased
        !           208:                | RESULT_SIZE(SIZE_CODE(sizeof(OSStatus)))
        !           209:                | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(UnicodeToTextInfo)))
        !           210:                | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(ByteCount)))
        !           211:                | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(ConstUniCharArrayPtr)))
        !           212:                | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(OptionBits)))
        !           213:                | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(ItemCount)))
        !           214:                | STACK_ROUTINE_PARAMETER(6, SIZE_CODE(sizeof(ByteOffset*)))
        !           215:                | STACK_ROUTINE_PARAMETER(7, SIZE_CODE(sizeof(ItemCount*)))
        !           216:                | STACK_ROUTINE_PARAMETER(8, SIZE_CODE(sizeof(ByteOffset*)))
        !           217:                | STACK_ROUTINE_PARAMETER(9, SIZE_CODE(sizeof(ByteCount)))
        !           218:                | STACK_ROUTINE_PARAMETER(10, SIZE_CODE(sizeof(ByteCount*)))
        !           219:                | STACK_ROUTINE_PARAMETER(11, SIZE_CODE(sizeof(ByteCount*)))
        !           220:                | STACK_ROUTINE_PARAMETER(12, SIZE_CODE(sizeof(LogicalAddress))),
        !           221: 
        !           222: 
        !           223:        uppUpgradeScriptInfoToTextEncodingProcInfo =
        !           224:                kPascalStackBased
        !           225:                | RESULT_SIZE(SIZE_CODE(sizeof(OSStatus)))
        !           226:                | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(ScriptCode)))
        !           227:                | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(LangCode)))
        !           228:                | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(RegionCode)))
        !           229:                | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(ConstStr255Param)))
        !           230:                | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(TextEncoding*))),
        !           231: 
        !           232: 
        !           233:        uppRevertTextEncodingToScriptInfoProcInfo =
        !           234:                kPascalStackBased
        !           235:                | RESULT_SIZE(SIZE_CODE(sizeof(OSStatus)))
        !           236:                | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(TextEncoding)))
        !           237:                | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(ScriptCode*)))
        !           238:                | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(LangCode*)))
        !           239:                | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(StringPtr))),
        !           240: 
        !           241: 
        !           242: // NOTE: this one uses "C" calling conventions...
        !           243:        uppLockMappingTableProcInfo =
        !           244:                kCStackBased
        !           245:                | RESULT_SIZE(SIZE_CODE(sizeof(OSStatus)))
        !           246:                | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(UnicodeMapping*)))
        !           247:                | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Boolean)))
        !           248: };
        !           249: #endif         /* TARGET_OS_MAC */
        !           250: 
        !           251: 
        !           252: enum {
        !           253:        smLargestScript = 32,
        !           254:        
        !           255:        kMinFileExtensionChars = 1,             // does not include dot
        !           256:        kMaxFileExtensionChars = 5              // does not include dot
        !           257: };
        !           258: 
        !           259: #define kASCIIPiSymbol                         0xB9
        !           260: #define kASCIIMicroSign                                0xB5
        !           261: #define kASCIIGreekDelta                       0xC6
        !           262: 
        !           263: 
        !           264: #define Is7BitASCII(c)                         ( (c) >= 0x20 && (c) <= 0x7F )
        !           265: 
        !           266: #define        IsSpecialASCIIChar(c)           ( (c) == (UInt8) kASCIIMicroSign || (c) == (UInt8) kASCIIPiSymbol || (c) == (UInt8) kASCIIGreekDelta )
        !           267: 
        !           268: // Note:       '�' has two Unicode representations 0x00B5 (micro sign) and 0x03BC (greek)
        !           269: //                     '�' has two Unicode representations 0x2206 (increment) and 0x0394 (greek)
        !           270: #define        IsSpecialUnicodeChar(c)         ( (c) == 0x00B5 || (c) == 0x03BC || (c) == 0x03C0 || (c) == 0x2206 || (c) == 0x0394 )
        !           271: 
        !           272: #define IsHexDigit(c)                          ( ((c) >= (UInt8) '0' && (c) <= (UInt8) '9') || ((c) >= (UInt8) 'A' && (c) <= (UInt8) 'F') )
        !           273: 
        !           274: //
        !           275: // PToUTable and PToUEntry describe the 'p2u#' resource
        !           276: // This resource is used to map pascal to Unicode before
        !           277: // the real Unicode converter is initialize.
        !           278: //
        !           279: struct PToUEntry {
        !           280:        Str31           pascalString;                   // pascal representation
        !           281:        UInt16          unicodeChars;                   // unicode char count
        !           282:        UniChar         unicodeString[63];              // unicode representation
        !           283: };
        !           284: typedef struct PToUEntry PToUEntry;
        !           285: 
        !           286: 
        !           287: struct PToUTable {
        !           288:        UInt16          entries;                // number of entries
        !           289:        PToUEntry       entry[1];
        !           290: };
        !           291: typedef struct PToUTable PToUTable;
        !           292: 
        !           293: 
        !           294: extern UniChar *       Get_gLowerCaseTable(void);
        !           295: 
        !           296: //     Unicode Glue routines
        !           297: // WARNING:  These Glue APIs must match the APIs in UnicodeConverter.h (the glue assumes they are the same)
        !           298: //                      for example CreateTextToUnicodeInfo_Glue and CreateTextToUnicodeInfo must have identical parameters and calling conventions
        !           299: 
        !           300: extern pascal OSStatus CreateTextToUnicodeInfo_Glue(ConstUnicodeMappingPtr iUnicodeMapping, TextToUnicodeInfo *oTextToUnicodeInfo);
        !           301: extern pascal OSStatus CreateUnicodeToTextInfo_Glue(ConstUnicodeMappingPtr iUnicodeMapping, UnicodeToTextInfo *oUnicodeToTextInfo);
        !           302: extern pascal OSStatus ConvertFromTextToUnicode_Glue(TextToUnicodeInfo iTextToUnicodeInfo, ByteCount iSourceLen, ConstLogicalAddress iSourceStr, OptionBits iControlFlags, ItemCount iOffsetCount, ByteOffset iOffsetArray[], ItemCount *oOffsetCount, ByteOffset oOffsetArray[], ByteCount iBufLen, ByteCount *oSourceRead, ByteCount *oUnicodeLen, UniCharArrayPtr oUnicodeStr);
        !           303: extern pascal OSStatus ConvertFromUnicodeToText_Glue(UnicodeToTextInfo iUnicodeToTextInfo, ByteCount iUnicodeLen, ConstUniCharArrayPtr iUnicodeStr, OptionBits iControlFlags, ItemCount iOffsetCount, ByteOffset iOffsetArray[], ItemCount *oOffsetCount, ByteOffset oOffsetArray[], ByteCount iBufLen, ByteCount *oInputRead, ByteCount *oOutputLen, LogicalAddress oOutputStr);
        !           304: extern pascal OSStatus UpgradeScriptInfoToTextEncoding_Glue(ScriptCode textScriptID, LangCode textLanguageID, RegionCode regionID, ConstStr255Param textFontname, TextEncoding *encoding);
        !           305: extern pascal OSStatus RevertTextEncodingToScriptInfo_Glue(TextEncoding encoding, ScriptCode *textScriptID, LangCode *textLanguageID, Str255 textFontname);
        !           306: 
        !           307: // EXCEPTION:  this one uses "C" calling conventions (why?)
        !           308: extern OSStatus LockMappingTable_Glue(UnicodeMapping *unicodeMappingPtr, Boolean lockIt);
        !           309: 
        !           310: #if TARGET_OS_MAC
        !           311: static OSErr InitStaticUnicodeConverter(void);
        !           312: static OSErr InitDynamicUnicodeConverter( Boolean forBootVolume );
        !           313: #endif /* TARGET_OS_MAC */
        !           314: 
        !           315: 
        !           316: #if TARGET_OS_MAC
        !           317: static OSErr InstallConversionContexts( FSVarsRec *fsVars );
        !           318: 
        !           319: static OSErr   InstallLibraryVector( CFragConnectionID connectionID, ConstStr255Param symbolName,
        !           320:                                                                          ProcInfoType procInfo, UniversalProcPtr *vector );
        !           321: 
        !           322: static OSErr   InstallSystemConversionContext( FSVarsRec *fsVars, Boolean forBootVolume );
        !           323: #endif /* TARGET_OS_MAC */
        !           324: 
        !           325: static void    GetFilenameExtension( ItemCount length, ConstUniCharArrayPtr unicodeStr, Str15 extStr );
        !           326: 
        !           327: static void    GetFileIDString( HFSCatalogNodeID fileID, Str15 fileIDStr );
        !           328: 
        !           329: static void AppendPascalString( ConstStr15Param src, Str31 dst );
        !           330: 
        !           331: static UInt32 HexStringToInteger( UInt32 length, const UInt8 *hexStr );
        !           332: 
        !           333: 
        !           334: pascal OSStatus FallbackProc( UniChar *srcUniStr, ByteCount srcUniStrLen, ByteCount *srcConvLen,
        !           335:                                                          TextPtr destStr, ByteCount destStrLen, ByteCount *destConvLen,
        !           336:                                                          LogicalAddress contextPtr, ConstUnicodeMappingPtr unicodeMappingPtr );
        !           337: 
        !           338: 
        !           339: static OSErr MacRomanToUnicode (ConstStr255Param pascalString, ItemCount *unicodeChars, UniCharArrayPtr unicodeString);
        !           340: static OSErr UnicodeToMacRoman (ItemCount unicodeChars, ConstUniCharArrayPtr unicodeString, Str31 pascalString);
        !           341: 
        !           342: 
        !           343: /*
        !           344:        Get the base encoding used by the File System
        !           345:        
        !           346:        If no HFS Plus volumes have been mounted yet then
        !           347:        the default encoding could be kTextEncodingUndefined
        !           348: */
        !           349: #if TARGET_OS_MAC
        !           350: TextEncoding
        !           351: GetDefaultTextEncoding(void)
        !           352: {
        !           353:        FSVarsRec       *fsVars;        
        !           354: 
        !           355:        fsVars = (FSVarsRec*) LMGetFSMVars();
        !           356: 
        !           357:        return fsVars->gDefaultBaseEncoding;
        !           358: }
        !           359: #endif
        !           360: 
        !           361: 
        !           362: /*
        !           363:        Set the base encoding used by the File System
        !           364: */
        !           365: #if TARGET_OS_MAC
        !           366: OSErr
        !           367: SetDefaultTextEncoding(TextEncoding encoding)
        !           368: {
        !           369:        FSVarsRec       *fsVars;
        !           370:        OSErr           result;
        !           371: 
        !           372: 
        !           373:        fsVars = (FSVarsRec*) LMGetFSMVars();
        !           374: 
        !           375: 
        !           376:        // undefined only makes sense when Unicode Library is not installed
        !           377:        if ( encoding == kTextEncodingUndefined )
        !           378:        {
        !           379:                if ( fsVars->gIsUnicodeInstalled == false )
        !           380:                        fsVars->gDefaultBaseEncoding = encoding;
        !           381:                        
        !           382:                return noErr;
        !           383:        }
        !           384: 
        !           385:        encoding = GetTextEncodingBasePriv(encoding);
        !           386:  
        !           387:        if ( !ValidMacEncoding(encoding) )
        !           388:                return paramErr;        // we only support Mac encodings!
        !           389: 
        !           390:        // if Unicode Library is installed then setup context for this encoding
        !           391:        // otherwise it will occur when the first HFS Plus volume gets mounted
        !           392:        if ( fsVars->gIsUnicodeInstalled )
        !           393:        {
        !           394:                result = InitializeEncodingContext( encoding, fsVars );
        !           395:                if ( result != noErr )
        !           396:                        return result;
        !           397:        }       
        !           398: 
        !           399:        // make it the default...
        !           400:        fsVars->gDefaultBaseEncoding = encoding;
        !           401: 
        !           402:        return noErr;
        !           403: }
        !           404: #endif /* TARGET_OS_MAC */
        !           405: 
        !           406: /*
        !           407:        Get the encoding that matches font
        !           408: */
        !           409: 
        !           410: #if TARGET_OS_MAC
        !           411: OSErr
        !           412: GetTextEncodingForFont( ConstStr255Param fontName, UInt32 * textEncoding )
        !           413: {
        !           414:        FSVarsRec *             fsVars;
        !           415:        OSErr                   result;
        !           416: 
        !           417: 
        !           418:        fsVars = (FSVarsRec*) LMGetFSMVars();
        !           419: 
        !           420:        // if Unicode Library is installed then we can get the encoding...
        !           421:        if ( fsVars->gIsUnicodeInstalled )
        !           422:        {
        !           423:                result = UpgradeScriptInfoToTextEncoding_Glue ( kTextScriptDontCare,
        !           424:                                                                                                                kTextLanguageDontCare,
        !           425:                                                                                                                kTextRegionDontCare,
        !           426:                                                                                                                fontName,
        !           427:                                                                                                                textEncoding );
        !           428:        }
        !           429:        else // Unicode Library not installed so save font name for later...
        !           430:        {
        !           431:                StringPtr       savedFontName;
        !           432:                UInt16          stringByteSize;
        !           433:                
        !           434:                stringByteSize = fontName[0] + 1;
        !           435:                savedFontName = fsVars->gTextEncodingFontName;
        !           436: 
        !           437:                // if we already had one then get rid of it
        !           438:                if ( savedFontName != NULL )
        !           439:                        DisposePtr( (Ptr) savedFontName );
        !           440: 
        !           441:                savedFontName = (StringPtr) NewPtrSys( stringByteSize );
        !           442:                
        !           443:                if ( savedFontName != NULL )
        !           444:                        BlockMoveData(fontName, savedFontName, stringByteSize);
        !           445:                
        !           446:                fsVars->gTextEncodingFontName = savedFontName;
        !           447:                
        !           448:                *textEncoding = kTextEncodingUndefined;
        !           449:                result = noErr;
        !           450:        }
        !           451: 
        !           452:        return result;
        !           453: }
        !           454: #endif /* TARGET_OS_MAC */
        !           455: 
        !           456: /*
        !           457:        Count the number of encodings installed by the File System
        !           458: */
        !           459: #if TARGET_OS_MAC
        !           460: ItemCount
        !           461: CountInstalledEncodings(void)
        !           462: {
        !           463:        FSVarsRec       *fsVars;        
        !           464: 
        !           465:        fsVars = (FSVarsRec*) LMGetFSMVars();
        !           466: 
        !           467:        return fsVars->gInstalledEncodings;
        !           468: }
        !           469: #endif
        !           470: 
        !           471: /*
        !           472:        Convert a Unicode string to a Pascal string (Str31) for use in an HFS file/folder name.
        !           473: */
        !           474: #if 0
        !           475: OSErr
        !           476: ConvertUnicodeToHFSName( ConstHFSUniStr255Param unicodeName, TextEncoding encoding, HFSCatalogNodeID cnid, Str31 hfsName )
        !           477: {
        !           478:        ByteCount               unicodeByteLength;
        !           479:        ByteCount               pascalSizeLimit;
        !           480:        OSErr                   result;
        !           481:        
        !           482:        hfsName[0] = 0;         // in case we get errors, make sure output is valid
        !           483:        unicodeByteLength = unicodeName->length * sizeof(UniChar);
        !           484: 
        !           485:        if ( unicodeByteLength == 0 )
        !           486:                return noErr;
        !           487: 
        !           488:        if ( cnid == kHFSRootFolderID )
        !           489:                pascalSizeLimit = kHFSMaxVolumeNameChars;       // an HFS volume name
        !           490:        else
        !           491:                pascalSizeLimit = kHFSMaxFileNameChars;         // an HFS file name
        !           492: 
        !           493:        result = MockConvertFromUnicodeToPString( unicodeByteLength, unicodeName->unicode, hfsName );
        !           494: 
        !           495:        // Check if name was too long or some characters were unrepresentable...
        !           496:        // if so we need to mangle the name so that the file can be found by
        !           497:        // name later
        !           498: 
        !           499:        if ( result == kTECOutputBufferFullStatus || result == kTECUsedFallbacksStatus )
        !           500:        {
        !           501:                Str15           fileIDStr;                              // file ID as a pascal string
        !           502:                Str15           extStr;                                 // dot extension as a pascal string
        !           503: 
        !           504:                GetFileIDString(cnid, fileIDStr);
        !           505:                
        !           506:                //      Get a filename extension only if it is a file.
        !           507:                if ( pascalSizeLimit == kHFSMaxFileNameChars)
        !           508:                        GetFilenameExtension(unicodeName->length, unicodeName->unicode, extStr);
        !           509:                else
        !           510:                        extStr[0] = (UInt8) 0;  // volumes don't have extensions
        !           511:        
        !           512:                // calculate free space for filename prefix
        !           513:                pascalSizeLimit -= StrLength(extStr) + StrLength(fileIDStr);
        !           514:                
        !           515:                //      Generate the prefix part of the name (before extension or File ID string).
        !           516:                //      Since the Unicode converter wasn't installed, use the PString we already have,
        !           517:                //      shortening it if needed.
        !           518:                if (hfsName[0] > pascalSizeLimit)
        !           519:                        hfsName[0] = pascalSizeLimit;
        !           520:                else
        !           521:                        hfsName[0] -= StrLength(extStr);        // remove extension chars (if any) from source
        !           522:                
        !           523:                strcat(hfsName, fileIDStr);
        !           524:                strcat(hfsName, extStr);
        !           525:                
        !           526:                result = noErr;
        !           527:        }
        !           528: 
        !           529:        return result;
        !           530: 
        !           531: } // end ConvertUnicodeToHFSName
        !           532: #endif
        !           533: 
        !           534: /*
        !           535:        Convert a Pascal string (Str31, such as a file/folder name) to Unicode.
        !           536: */
        !           537: #if TARGET_OS_MAC
        !           538: OSErr
        !           539: ConvertHFSNameToUnicode( ConstStr31Param hfsName, TextEncoding encoding, HFSUniStr255 *unicodeName )
        !           540: {
        !           541:        ByteCount       unicodeByteLength;
        !           542:        OSErr           result;
        !           543:        
        !           544: 
        !           545:        result = MockConvertFromPStringToUnicode( hfsName, sizeof(unicodeName->unicode), &unicodeByteLength, unicodeName->unicode );
        !           546:        
        !           547:        unicodeName->length = unicodeByteLength / sizeof(UniChar);      // Note: from byte count to char count
        !           548: 
        !           549:        return result;
        !           550: 
        !           551: } // end ConvertHFSNameToUnicode
        !           552: #endif
        !           553: 
        !           554: 
        !           555: /*
        !           556:        MockConvertFromUnicodeToPString
        !           557:  */
        !           558: #if TARGET_OS_MAC
        !           559: OSErr
        !           560: MockConvertFromUnicodeToPString( ByteCount unicodeLength, ConstUniCharArrayPtr unicodeStr, Str31 pascalStr )
        !           561: {
        !           562:        return UnicodeToMacRoman(unicodeLength / sizeof(UniChar), unicodeStr, pascalStr);
        !           563: }
        !           564: #endif
        !           565: 
        !           566: /*
        !           567:        MockConvertFromPStringToUnicode
        !           568:  */
        !           569: #if TARGET_OS_MAC
        !           570: OSErr
        !           571: MockConvertFromPStringToUnicode(ConstStr31Param pascalStr, ByteCount maxUnicodeLen, ByteCount *actualUnicodeLen, UniCharArrayPtr unicodeStr)
        !           572: {
        !           573: #pragma unused(maxUnicodeLen)
        !           574: 
        !           575:        UInt32  unicodeChars;
        !           576:        OSErr   result;
        !           577: 
        !           578:        result = MacRomanToUnicode (pascalStr, &unicodeChars, unicodeStr);
        !           579: 
        !           580:        *actualUnicodeLen = unicodeChars * sizeof(UniChar);             // return length in bytes
        !           581: 
        !           582:        return result;
        !           583: }
        !           584: #endif
        !           585: 
        !           586: /*
        !           587:        Initialize the Unicode Converter library
        !           588:        
        !           589:        If the library cannot be initialized the wrapper code will default to using 7-bit ASCII or mangled names.
        !           590:        
        !           591:        WARNING: This cannot be called from within a file system call (since it calls the file system)!
        !           592: */
        !           593: #if TARGET_OS_MAC
        !           594: OSErr InitUnicodeConverter(Boolean forBootVolume)
        !           595: {
        !           596:        FSVarsRec                       *fsVars;        
        !           597:        Handle                          resourceHandle;
        !           598:        long                            response;
        !           599:        OSErr                           err;
        !           600: 
        !           601:        
        !           602:        fsVars = (FSVarsRec*) LMGetFSMVars();
        !           603: 
        !           604:        if ( fsVars->gIsUnicodeInstalled == true )                                      //      Has Unicode already been installed
        !           605:                return ( noErr );
        !           606:        
        !           607:        err = Gestalt( gestaltSysArchitecture, &response );                     //�� Runtime check to load static or dynamic libraries
        !           608:        if ( (response == gestaltPowerPC) && (err == noErr) )
        !           609:        {
        !           610:                SInt32  savedOffsetToUTC;
        !           611: 
        !           612:                if (forBootVolume)
        !           613:                {
        !           614:                        savedOffsetToUTC = fsVars->offsetToUTC;         // save offset from GMT to local time
        !           615:                        fsVars->offsetToUTC = 0;                                        // trick CFM into caching an older mod date for the extensions folder
        !           616: 
        !           617:                        // For bootstrap PascalToUnicode conversions we need to load the p2u table
        !           618:                        resourceHandle = GetResource ('p2u#', 0);       // get our special mapping table
        !           619:                        if (resourceHandle != NULL)
        !           620:                        {
        !           621:                                HLock(resourceHandle);
        !           622:                                fsVars->gBootPToUTable = *resourceHandle;
        !           623:                        }
        !           624:                }
        !           625: 
        !           626: 
        !           627:                err = InitDynamicUnicodeConverter( forBootVolume );
        !           628: 
        !           629: 
        !           630:                if (forBootVolume)
        !           631:                {
        !           632:                        fsVars->offsetToUTC = savedOffsetToUTC;         // restore offset from GMT to local time
        !           633: 
        !           634:                        // The real converters should be online now so we can jettison the table
        !           635:                        if (resourceHandle != NULL)
        !           636:                        {
        !           637:                                HUnlock(resourceHandle);
        !           638:                                fsVars->gBootPToUTable = NULL;
        !           639:                                ReleaseResource(resourceHandle);                        // we no longer need this table
        !           640:                        }
        !           641:                }
        !           642:        }
        !           643:        
        !           644:        if ( (err != noErr) || (response != gestaltPowerPC) )           //      If we got an error or on a 68K mac
        !           645:        {
        !           646:                err = InitStaticUnicodeConverter();                                             //      Init the 68K static version of the converters
        !           647:        }
        !           648: 
        !           649:        
        !           650:        return ( err );
        !           651: }
        !           652: #endif /* TARGET_OS_MAC */     
        !           653: 
        !           654: 
        !           655: /*
        !           656:        Initialize the Staticly linked 68K Unicode Converter library
        !           657: 
        !           658:        If the library cannot be initialized the wrapper code will default to using 7-bit ASCII or mangled names.
        !           659:        WARNING: This cannot be called from within a file system call (since it calls the file system)!
        !           660: */
        !           661: #if TARGET_OS_MAC
        !           662: static OSErr
        !           663: InitStaticUnicodeConverter(void)
        !           664: {
        !           665:        FSVarsRec                       *fsVars;        
        !           666:        THz                                     savedHeapZone;
        !           667:        OSErr                           err;
        !           668:        Str31                           textEncodingConverterName;
        !           669: 
        !           670:        // use the system context
        !           671:        savedHeapZone = GetZone();
        !           672:        SetZone( SystemZone() );
        !           673: 
        !           674:        GetIndString( textEncodingConverterName, kBaseHFSPlusResourceID, rTextEncodingConverterName );  //���need real string!!
        !           675:        err = InitializeUnicode( textEncodingConverterName );
        !           676:        ExitOnError( err );
        !           677: 
        !           678:        fsVars = (FSVarsRec*) LMGetFSMVars();
        !           679:        fsVars->gUseDynamicUnicodeConverters = false;
        !           680: 
        !           681:        err = InstallSystemConversionContext( fsVars, false );
        !           682:        ExitOnError( err );
        !           683:        
        !           684:        fsVars = (FSVarsRec*) LMGetFSMVars();
        !           685:        fsVars->gIsUnicodeInstalled = true;
        !           686: 
        !           687: 
        !           688: ErrorExit:
        !           689:        
        !           690:        SetZone( savedHeapZone );
        !           691:        
        !           692:        return( err );
        !           693: }
        !           694: #endif /* TARGET_OS_MAC */     
        !           695: 
        !           696: 
        !           697: 
        !           698: /*
        !           699:        Initialize the PPC CFM dynamically linked 68K Unicode Converter library
        !           700:        If the library cannot be initialized the wrapper code will default to
        !           701:        using the 68K staticly linked library.
        !           702: */
        !           703: #if TARGET_OS_MAC
        !           704: static OSErr
        !           705: InitDynamicUnicodeConverter( Boolean forBootVolume )
        !           706: {
        !           707:        CFragConnectionID       unicodeLib = 0;
        !           708:        CFragConnectionID       textLib = 0;
        !           709:        Ptr                                     tempMainAddr;
        !           710:        Str255                          errMessage;
        !           711:        FSVarsRec                       *fsVars;        
        !           712:        THz                                     savedHeapZone;
        !           713:        OSErr                           result;
        !           714: 
        !           715: 
        !           716:        fsVars = (FSVarsRec*) LMGetFSMVars();
        !           717:        
        !           718:        // use the system context
        !           719:        savedHeapZone = GetZone();
        !           720:        SetZone( SystemZone() );
        !           721:        #if 0
        !           722:          (void) BeginSystemMode();
        !           723:        #endif
        !           724: 
        !           725:        result = GetSharedLibrary("\pUnicodeConverter", kPowerPCCFragArch, kPrivateCFragCopy, &unicodeLib, &tempMainAddr, errMessage);
        !           726:        ExitOnError( result );
        !           727: 
        !           728:        result = GetSharedLibrary("\pTextCommon", kPowerPCCFragArch, kPrivateCFragCopy, &textLib, &tempMainAddr, errMessage);
        !           729:        ExitOnError( result );
        !           730: 
        !           731: 
        !           732:        fsVars->gUseDynamicUnicodeConverters    = true;
        !           733: 
        !           734:        result = InstallLibraryVector( unicodeLib,
        !           735:                                                                   "\pCreateTextToUnicodeInfo",
        !           736:                                                                   uupCreateTextToUnicodeInfoProcInfo,
        !           737:                                                                   &fsVars->uppCreateTextToUnicodeInfo );
        !           738:        ExitOnError( result );
        !           739: 
        !           740: 
        !           741:        result = InstallLibraryVector( unicodeLib,
        !           742:                                                                   "\pCreateUnicodeToTextInfo",
        !           743:                                                                   uppCreateUnicodeToTextInfoProcInfo,
        !           744:                                                                   &fsVars->uppCreateUnicodeToTextInfo );
        !           745:        ExitOnError( result );
        !           746: 
        !           747: 
        !           748:        result = InstallLibraryVector( unicodeLib,
        !           749:                                                                   "\pConvertFromTextToUnicode",
        !           750:                                                                   uppConvertFromTextToUnicodeProcInfo,
        !           751:                                                                   &fsVars->uppConvertFromTextToUnicode );      // don't set vector yet
        !           752:        ExitOnError( result );
        !           753: 
        !           754: 
        !           755:        result = InstallLibraryVector( unicodeLib,
        !           756:                                                                   "\pConvertFromUnicodeToText",
        !           757:                                                                   uppConvertFromUnicodeToTextProcInfo,
        !           758:                                                                   &fsVars->uppConvertFromUnicodeToText );      // don't set vector yet
        !           759:        ExitOnError( result );
        !           760: 
        !           761: 
        !           762:        result = InstallLibraryVector( unicodeLib,
        !           763:                                                                   "\pLockMappingTable",
        !           764:                                                                   uppLockMappingTableProcInfo,
        !           765:                                                                   &fsVars->uppLockMappingTable );
        !           766:        ExitOnError( result );
        !           767: 
        !           768: 
        !           769:        result = InstallLibraryVector( textLib,
        !           770:                                                                   "\pUpgradeScriptInfoToTextEncoding",
        !           771:                                                                   uppUpgradeScriptInfoToTextEncodingProcInfo,
        !           772:                                                                   &fsVars->uppUpgradeScriptInfoToTextEncoding );
        !           773:        ExitOnError( result );
        !           774: 
        !           775:   #if 0
        !           776:        result = InstallLibraryVector( textLib,
        !           777:                                                                   "\pRevertTextEncodingToScriptInfo",
        !           778:                                                                   uppRevertTextEncodingToScriptInfoProcInfo,
        !           779:                                                                   &fsVars->uppRevertTextEncodingToScriptInfo );
        !           780:        ExitOnError( result );
        !           781:   #endif
        !           782:  
        !           783:        // NOTE:  Real Unicode filename conversion is not enabled yet but that's OK.
        !           784:        // We can still call the converter library since it finds it's data files by
        !           785:        // matching file type and creator (not by name).
        !           786: 
        !           787:        result = InstallSystemConversionContext(fsVars, forBootVolume);
        !           788:        ExitOnError( result );
        !           789: 
        !           790:        fsVars->gIsUnicodeInstalled = true;             //      Unicode binding and setup succesful, and now enabled
        !           791: 
        !           792:        // restore previous context
        !           793:        #if 0
        !           794:          (void) EndSystemMode();
        !           795:        #endif
        !           796:        SetZone( savedHeapZone );
        !           797: 
        !           798:        return noErr;
        !           799: 
        !           800: ErrorExit:
        !           801: 
        !           802:        fsVars->uppCreateTextToUnicodeInfo = NULL;
        !           803:        fsVars->uppCreateUnicodeToTextInfo = NULL;
        !           804:        fsVars->uppConvertFromTextToUnicode = NULL;
        !           805:        fsVars->uppConvertFromUnicodeToText = NULL;
        !           806:        fsVars->uppLockMappingTable = NULL;
        !           807:        
        !           808:        if ( unicodeLib )
        !           809:                (void) CloseConnection( &unicodeLib );
        !           810: 
        !           811:        if ( textLib )
        !           812:                (void) CloseConnection( &textLib );
        !           813: 
        !           814:        #if 0
        !           815:          (void) EndSystemMode();
        !           816:        #endif
        !           817:        SetZone( savedHeapZone );
        !           818:        
        !           819:        return result;
        !           820: 
        !           821: } // end InitDynamicUnicodeConverter
        !           822: #endif /* TARGET_OS_MAC */     
        !           823: 
        !           824: 
        !           825: 
        !           826: //
        !           827: // Install a conversion context for the system script (call early in boot)
        !           828: //
        !           829: #if TARGET_OS_MAC
        !           830: static OSErr
        !           831: InstallSystemConversionContext( FSVarsRec *fsVars, Boolean forBootVolume )
        !           832: {
        !           833:        TextEncoding            defaultEncoding;
        !           834:        ScriptCode                      script;
        !           835:        RegionCode                      region;
        !           836:        OSErr                           result;
        !           837: 
        !           838:        // The Script Manager does not setup the region until later in boot
        !           839:        // so if we're booting from HFS Plus we need to "manually" determine
        !           840:        // the system script and region using the 'itlc' resource.
        !           841: 
        !           842:        if ( forBootVolume )
        !           843:        {
        !           844:                Handle           configResource;
        !           845:                ItlcRecord      *itlConfig;
        !           846:                
        !           847:                configResource = GetResource( 'itlc', 0 );
        !           848:                
        !           849:                if ( configResource != NULL )
        !           850:                {
        !           851:                        itlConfig = (ItlcRecord*) *configResource;
        !           852:                        
        !           853:                        script = itlConfig->itlcSystem;
        !           854:                        region = itlConfig->itlcRegionCode;
        !           855:        
        !           856:                        ReleaseResource( configResource );
        !           857:                }
        !           858:                else
        !           859:                {
        !           860:                        script = GetScriptManagerVariable(smSysScript);
        !           861:                        region = kTextRegionDontCare;
        !           862:                }               
        !           863:        }
        !           864:        else
        !           865:        {
        !           866:                script = GetScriptManagerVariable(smSysScript);
        !           867:                region = GetScriptManagerVariable(smRegionCode);
        !           868:        }
        !           869: 
        !           870:        result = UpgradeScriptInfoToTextEncoding_Glue( script,
        !           871:                                                                                                   kTextLanguageDontCare,
        !           872:                                                                                                   region,
        !           873:                                                                                                   NULL,
        !           874:                                                                                                   &defaultEncoding );
        !           875:        if ( result == paramErr )
        !           876:        {
        !           877:                // ok, last ditch effort to get an encoding...
        !           878:                result = UpgradeScriptInfoToTextEncoding_Glue( script,
        !           879:                                                                                                           kTextLanguageDontCare,
        !           880:                                                                                                           kTextRegionDontCare,
        !           881:                                                                                                           NULL,
        !           882:                                                                                                           &defaultEncoding );
        !           883:        }
        !           884:        ReturnIfError(result);
        !           885:        
        !           886:        defaultEncoding = GetTextEncodingBasePriv(defaultEncoding);
        !           887:        
        !           888:        result = InitializeEncodingContext( defaultEncoding, fsVars );
        !           889:        ReturnIfError(result);
        !           890:        
        !           891:        if ( defaultEncoding != kTextEncodingMacRoman )
        !           892:        {
        !           893:                result = InitializeEncodingContext( kTextEncodingMacRoman, fsVars );    // always install Roman
        !           894:                ReturnIfError(result);
        !           895:        }
        !           896: 
        !           897:        // Since a call to set the default text encoding can occur
        !           898:        // before any HFS Plus volumes are mounted we need to check
        !           899:        // gDefaultBaseEncoding and gTextEncodingFontName to see if
        !           900:        // the default encoding needs to change...
        !           901:        if ( !forBootVolume )
        !           902:        {
        !           903:                TextEncoding    requestedEncoding;
        !           904: 
        !           905:                requestedEncoding = fsVars->gDefaultBaseEncoding;
        !           906: 
        !           907:                if ( requestedEncoding == kTextEncodingUndefined  &&  fsVars->gTextEncodingFontName != NULL )
        !           908:                {
        !           909:                        result = UpgradeScriptInfoToTextEncoding_Glue ( kTextScriptDontCare,
        !           910:                                                                                                                        kTextLanguageDontCare,
        !           911:                                                                                                                        kTextRegionDontCare,
        !           912:                                                                                                                        fsVars->gTextEncodingFontName,
        !           913:                                                                                                                        &requestedEncoding );
        !           914:                        if ( result != noErr )
        !           915:                                requestedEncoding = kTextEncodingUndefined;
        !           916: 
        !           917:                        DisposePtr((Ptr) fsVars->gTextEncodingFontName);        // we no longer need font name
        !           918:                        fsVars->gTextEncodingFontName = NULL;
        !           919:                }
        !           920: 
        !           921:                if ( requestedEncoding != kTextEncodingUndefined  &&  requestedEncoding != defaultEncoding )
        !           922:                {
        !           923:                        result = InitializeEncodingContext( requestedEncoding, fsVars );
        !           924:                        if ( result == noErr )
        !           925:                                defaultEncoding = requestedEncoding;
        !           926:                }
        !           927:        }
        !           928: 
        !           929:        
        !           930:        // remember the default text encoding...
        !           931:        fsVars->gDefaultBaseEncoding = defaultEncoding;
        !           932: 
        !           933:        return noErr;
        !           934: 
        !           935: } // end InstallSystemConversionContext
        !           936: #endif /* TARGET_OS_MAC */     
        !           937: 
        !           938: 
        !           939: 
        !           940: //
        !           941: // Install any addition scripts that were installed by the system (call late in boot)
        !           942: //
        !           943: #if TARGET_OS_MAC
        !           944: OSErr
        !           945: InstallConversionContextsForInstalledScripts( void )
        !           946: {
        !           947:        FSVarsRec*              fsVars;
        !           948:        TextEncoding    encoding;
        !           949:        UInt32                  scriptCount;
        !           950:        ScriptCode              systemScript;
        !           951:        ScriptCode              script;
        !           952:        OSErr                   result;
        !           953: 
        !           954: 
        !           955:        fsVars = (FSVarsRec*) LMGetFSMVars();
        !           956: 
        !           957:        scriptCount = GetScriptManagerVariable(smEnabled);
        !           958:        systemScript = GetScriptManagerVariable(smSysScript);
        !           959: 
        !           960:        script = 0;
        !           961: 
        !           962:        while ( (scriptCount > 0) && (script <= smLargestScript) )
        !           963:        {
        !           964:                if ( GetScriptVariable(script, smScriptEnabled) != 0 )  // is this script enabled?
        !           965:                {               
        !           966:                        --scriptCount;
        !           967: 
        !           968:                        if ( script != systemScript )   // we already did systemScript
        !           969:                        {
        !           970:                                LangCode        language;
        !           971: 
        !           972:                                language = GetScriptVariable( script, smScriptLang );
        !           973:                        
        !           974:                                result = UpgradeScriptInfoToTextEncoding_Glue( script, language, kTextRegionDontCare, NULL, &encoding );
        !           975:                                if ( result == noErr )
        !           976:                                        (void) InitializeEncodingContext( encoding, fsVars );
        !           977:                        }
        !           978:                }
        !           979: 
        !           980:                ++script;       // on to the next one
        !           981:        }
        !           982: 
        !           983:        return noErr;
        !           984: 
        !           985: } // end InstallConversionContextsForInstalledScripts
        !           986: #endif /* TARGET_OS_MAC */     
        !           987: 
        !           988: 
        !           989: 
        !           990: //
        !           991: // Install any addition scripts that were used by an HFS Plus volume (called at volume mount time)
        !           992: //
        !           993: #if TARGET_OS_MAC
        !           994: OSErr
        !           995: InstallVolumeConversionContexts( UInt64 encodingsBitmap )
        !           996: {
        !           997:        FSVarsRec *     fsVars;
        !           998:        UInt32          encodingMask;
        !           999:        UInt32          index;
        !          1000:        UInt32          encoding;
        !          1001:        OSErr           result;
        !          1002: 
        !          1003: 
        !          1004:        fsVars = (FSVarsRec*) LMGetFSMVars();
        !          1005: 
        !          1006:        index = 0;
        !          1007:        encodingMask = 1;
        !          1008: 
        !          1009:        while ( encodingMask != 0 )
        !          1010:        {
        !          1011:                if ( encodingMask & encodingsBitmap.lo )                                                        // encodings 0 - 31
        !          1012:                {
        !          1013:                        encoding = MapIndexToEncoding(index);
        !          1014:                        result = InitializeEncodingContext( encoding, fsVars );
        !          1015:                }
        !          1016: 
        !          1017:                if      ( encodingMask & encodingsBitmap.hi )                                                   // encodings 32 - 64
        !          1018:                {
        !          1019:                        encoding = MapIndexToEncoding(index + 32);
        !          1020:                        result = InitializeEncodingContext( encoding, fsVars );
        !          1021:                }
        !          1022: 
        !          1023:                encodingMask = encodingMask << 1;
        !          1024:                ++index;
        !          1025:        }
        !          1026: 
        !          1027:        return noErr;
        !          1028: 
        !          1029: } // end InstallVolumeConversionContexts
        !          1030: #endif /* TARGET_OS_MAC */     
        !          1031: 
        !          1032: 
        !          1033: //
        !          1034: // Initialze a conversion context for a single encoding (if not already installed)
        !          1035: //
        !          1036: #if TARGET_OS_MAC
        !          1037: OSErr InitializeEncodingContext( TextEncoding encoding, FSVarsRec *fsVars )
        !          1038: {
        !          1039:        UInt32                  index;
        !          1040:        UnicodeMapping  unicodeMapping;
        !          1041:        THz                             savedHeapZone;
        !          1042:        OSStatus                result;
        !          1043: 
        !          1044: 
        !          1045:        encoding = GetTextEncodingBasePriv( encoding );
        !          1046:        index = MapEncodingToIndex(encoding);
        !          1047: 
        !          1048:        if ( fsVars->gConversionContext[index].toUnicode != 0 )
        !          1049:                return noErr;   // this one is already installed!
        !          1050: 
        !          1051:        savedHeapZone = GetZone();
        !          1052:        SetZone( SystemZone() );        // always use the system heap since Conversion Contexts are global
        !          1053: 
        !          1054: 
        !          1055:        // Note: by default kTextEncodingUnicodeV2_0 allows corporate use characters
        !          1056:        unicodeMapping.unicodeEncoding = CreateTextEncodingPriv( kTextEncodingUnicodeV2_0, kUnicodeCanonicalDecompVariant, 0 );
        !          1057:        unicodeMapping.otherEncoding = encoding;
        !          1058:        unicodeMapping.mappingVersion = kUnicodeUseHFSPlusMapping;
        !          1059: 
        !          1060: 
        !          1061:        if ( fsVars->gUseDynamicUnicodeConverters == false )
        !          1062:                result = LockMappingTable( &unicodeMapping, true );
        !          1063:        else
        !          1064:                result = LockMappingTable_Glue( &unicodeMapping, true );
        !          1065:        ExitOnError( result );
        !          1066:        
        !          1067:        result = CreateTextToUnicodeInfo_Glue( &unicodeMapping, &fsVars->gConversionContext[index].toUnicode );
        !          1068:        ExitOnError( result );
        !          1069: 
        !          1070:        result = CreateUnicodeToTextInfo_Glue( &unicodeMapping, &fsVars->gConversionContext[index].fromUnicode );
        !          1071:        ExitOnError( result );
        !          1072: 
        !          1073:        ++(fsVars->gInstalledEncodings);        // keep track of how many we've installed
        !          1074: 
        !          1075: #if 0  
        !          1076:        result = SetFallbackUnicodeToText( fsVars->gConversionContext[index].fromUnicode,
        !          1077:                                                                           NewUnicodeToTextFallbackProc(FallbackProc),  // since we are compiled 68K no routine descriptor is needed
        !          1078:                                                                           kUnicodeFallbackCustomOnly,
        !          1079:                                                                           NULL );
        !          1080: 
        !          1081: #endif
        !          1082: 
        !          1083: ErrorExit:
        !          1084: 
        !          1085:        SetZone( savedHeapZone );
        !          1086: 
        !          1087:        return result;
        !          1088: 
        !          1089: } // end InitializeEncodingContext
        !          1090: #endif /* TARGET_OS_MAC */     
        !          1091: 
        !          1092: 
        !          1093: #if TARGET_OS_MAC
        !          1094: pascal OSStatus
        !          1095: FallbackProc( UniChar * srcUniStr, ByteCount srcUniStrLen, ByteCount *srcConvLen,
        !          1096:                          TextPtr destStr, ByteCount destStrLen, ByteCount *destConvLen,
        !          1097:                          LogicalAddress contextPtr, ConstUnicodeMappingPtr unicodeMappingPtr)
        !          1098: {
        !          1099:        #pragma unused (srcUniStr, destStrLen, contextPtr, unicodeMappingPtr)
        !          1100:        *srcConvLen = srcUniStrLen;
        !          1101:        *destStr = '_';
        !          1102:        *destConvLen = sizeof(unsigned char);
        !          1103: 
        !          1104:        return noErr;
        !          1105: }
        !          1106: #endif
        !          1107: 
        !          1108: #if TARGET_OS_MAC
        !          1109: static OSErr
        !          1110: InstallLibraryVector ( CFragConnectionID connectionID, ConstStr255Param symbolName, ProcInfoType procInfo, UniversalProcPtr *vector)
        !          1111: {
        !          1112:        UniversalProcPtr        routineDescriptor;
        !          1113:        CFragSymbolClass        symClass;
        !          1114:        ProcPtr                         tVector;
        !          1115:        OSErr                           result;
        !          1116:        
        !          1117: 
        !          1118:        result = FindSymbol(connectionID, symbolName, (Ptr *) &tVector, &symClass);
        !          1119:        ReturnIfError( result );
        !          1120: 
        !          1121:        routineDescriptor = NewRoutineDescriptorTrap(tVector, procInfo, kPowerPCISA);
        !          1122:        
        !          1123:        if ( routineDescriptor != NULL )
        !          1124:                *vector = routineDescriptor;
        !          1125:        else
        !          1126:                result = memFullErr;
        !          1127:                
        !          1128:        return result;
        !          1129: }
        !          1130: #endif
        !          1131: 
        !          1132: 
        !          1133: //
        !          1134: // Get filename extension (if any) as a pascal string
        !          1135: //
        !          1136: #if TARGET_OS_MAC
        !          1137: static void
        !          1138: GetFilenameExtension( ItemCount length, ConstUniCharArrayPtr unicodeStr, Str15 extStr )
        !          1139: {
        !          1140:        UInt32  i;
        !          1141:        UniChar c;
        !          1142:        UInt16  extChars;                       // number of extension characters (excluding the dot)
        !          1143:        UInt16  maxExtChars;
        !          1144:        Boolean foundExtension;
        !          1145: 
        !          1146: 
        !          1147:        extStr[0] = (UInt8) 0;          // assume there's no extension
        !          1148: 
        !          1149:        if ( length < 3 )
        !          1150:                return;                                 // sorry, "x.y" is smallest possible extension  
        !          1151:        
        !          1152:        if ( length < (kMaxFileExtensionChars + 2) )
        !          1153:                maxExtChars = length - 2;       // we need at least one prefix character and dot
        !          1154:        else
        !          1155:                maxExtChars = kMaxFileExtensionChars;
        !          1156: 
        !          1157:        i = length;
        !          1158:        extChars = 0;
        !          1159:        foundExtension = false;
        !          1160: 
        !          1161:        while ( extChars <= maxExtChars )
        !          1162:        {
        !          1163:                c = unicodeStr[--i];
        !          1164: 
        !          1165:                if ( c == (UniChar) '.' )               // look for leading dot
        !          1166:                {
        !          1167:                        if ( extChars > 0 )                     // cannot end with a dot
        !          1168:                                foundExtension = true;
        !          1169:                        break;
        !          1170:                }
        !          1171: 
        !          1172:                if ( Is7BitASCII(c) || IsSpecialUnicodeChar(c) )
        !          1173:                        ++extChars;
        !          1174:                else
        !          1175:                        break;
        !          1176:        }
        !          1177:        
        !          1178:        // if we found one then copy it
        !          1179:        if ( foundExtension )
        !          1180:        {
        !          1181:                UInt8 *extStrPtr = extStr;
        !          1182:                const UniChar *unicodeStrPtr = &unicodeStr[i];  // point to dot char
        !          1183:                
        !          1184:                *(extStrPtr++) = extChars + 1;          // set length to extension chars plus dot
        !          1185: 
        !          1186:                for ( i = 0; i <= extChars; ++i )
        !          1187:                {
        !          1188:                        c = *(unicodeStrPtr++);
        !          1189:                        
        !          1190:                        // map any special characters
        !          1191:                        switch (c)
        !          1192:                        {
        !          1193:                                case 0x00B5:                    // micro sign
        !          1194:                                case 0x03BC:                    // greek mu
        !          1195:                                        c = (UniChar) '�';
        !          1196:                                        break;
        !          1197: 
        !          1198:                                case 0x03C0:                    // greek pi
        !          1199:                                        c = (UniChar) '�';
        !          1200:                                        break;
        !          1201: 
        !          1202:                                case 0x2206:                    // increment sign
        !          1203:                                case 0x0394:                    // greek capital delta
        !          1204:                                        c = (UniChar) '�';
        !          1205:                                        break;
        !          1206:                        }
        !          1207: 
        !          1208:                        *(extStrPtr++) = (UInt8) c;             // copy/convert to ascii
        !          1209:                }
        !          1210:        }
        !          1211: 
        !          1212: } // end GetFilenameExtension
        !          1213: #endif /* TARGET_OS_MAC */
        !          1214: 
        !          1215: 
        !          1216: //
        !          1217: // Count filename extension characters (if any)
        !          1218: //
        !          1219: static UInt32
        !          1220: CountFilenameExtensionChars( const unsigned char * filename )
        !          1221: {
        !          1222:        UInt32  i;
        !          1223:        UniChar c;
        !          1224:        UInt32  extChars;                       // number of extension characters (excluding the dot)
        !          1225:        UInt32  length;
        !          1226:        UInt16  maxExtChars;
        !          1227:        Boolean foundExtension;
        !          1228: 
        !          1229: 
        !          1230:        length = strlen(filename);
        !          1231: 
        !          1232:        if ( length < 3 )
        !          1233:                return 0;                                       // sorry, "x.y" is smallest possible extension  
        !          1234:        
        !          1235:        if ( length < (kMaxFileExtensionChars + 2) )
        !          1236:                maxExtChars = length - 2;       // we need at least on prefix character and dot
        !          1237:        else
        !          1238:                maxExtChars = kMaxFileExtensionChars;
        !          1239: 
        !          1240:        extChars = 0;                           // assume there's no extension
        !          1241:        i = length - 1;                         // index to last ascii character
        !          1242:        foundExtension = false;
        !          1243: 
        !          1244:        while ( extChars <= maxExtChars )
        !          1245:        {
        !          1246:                c = filename[i--];
        !          1247: 
        !          1248:                if ( c == (UInt8) '.' )         // look for leading dot
        !          1249:                {
        !          1250:                        if ( extChars > 0 )                     // cannot end with a dot
        !          1251:                                return (extChars);
        !          1252: 
        !          1253:                        break;
        !          1254:                }
        !          1255: 
        !          1256:                if ( Is7BitASCII(c) || IsSpecialASCIIChar(c) )
        !          1257:                        ++extChars;
        !          1258:                else
        !          1259:                        break;
        !          1260:        }
        !          1261:        
        !          1262:        return 0;
        !          1263: 
        !          1264: } // end CountFilenameExtensionChars
        !          1265: 
        !          1266: 
        !          1267: //
        !          1268: // Convert file ID into a hexidecimal string with no leading zeros
        !          1269: //
        !          1270: #if TARGET_OS_MAC
        !          1271: static void
        !          1272: GetFileIDString( HFSCatalogNodeID fileID, Str15 fileIDStr )
        !          1273: {
        !          1274:        SInt32  i, b;
        !          1275:        static UInt8 *translate = (UInt8 *) "0123456789ABCDEF";
        !          1276:        UInt8   c;
        !          1277:        
        !          1278:        fileIDStr[1] = '#';
        !          1279: 
        !          1280:        for ( i = 1, b = 28; b >= 0; b -= 4 )
        !          1281:        {
        !          1282:                c = *(translate + ((fileID >> b) & 0x0000000F));
        !          1283:                
        !          1284:                // if its not a leading zero add it to our string
        !          1285:                if ( (c != (UInt8) '0') || (i > 1) || (b == 0) )
        !          1286:                        fileIDStr[++i] = c;
        !          1287:        }
        !          1288: 
        !          1289:        fileIDStr[0] = (UInt8) i;
        !          1290: 
        !          1291: } // end GetFileIDString
        !          1292: #endif /* TARGET_OS_MAC */
        !          1293: 
        !          1294: 
        !          1295: //
        !          1296: // Append a suffix to a pascal string
        !          1297: //
        !          1298: #if TARGET_OS_MAC
        !          1299: static void
        !          1300: AppendPascalString( ConstStr15Param src, Str31 dst )
        !          1301: {
        !          1302:        UInt32  i, j;
        !          1303:        UInt32  srcLen;
        !          1304:        
        !          1305:        srcLen = StrLength(src);
        !          1306:        
        !          1307:        if ( (srcLen + StrLength(dst)) > 31 )   // safety net
        !          1308:                return;
        !          1309:        
        !          1310:        i = dst[0] + 1;         // get end of dst
        !          1311:        
        !          1312:        for (j = 1; j <= srcLen; ++j)
        !          1313:                dst[i++] = src[j];
        !          1314:                
        !          1315:        dst[0] += srcLen;
        !          1316: 
        !          1317: } // end AppendPascalString
        !          1318: #endif /* TARGET_OS_MAC */
        !          1319: 
        !          1320: 
        !          1321: HFSCatalogNodeID
        !          1322: GetEmbeddedFileID(const unsigned char * filename, UInt32 *prefixLength)
        !          1323: {
        !          1324:        short   length;
        !          1325:        short   extChars;
        !          1326:        short   i;
        !          1327:        UInt8   c;                      // current character in filename
        !          1328: 
        !          1329:        *prefixLength = 0;
        !          1330: 
        !          1331:        if ( filename == NULL )
        !          1332:                return 0;
        !          1333: 
        !          1334:        length = strlen(filename);
        !          1335: 
        !          1336:        if ( length < 4 )
        !          1337:                return 0;               // too small to have a file ID
        !          1338: 
        !          1339:        if ( length >= 6 )      // big enough for a file ID (#10) and an extension (.x) ?
        !          1340:                extChars = CountFilenameExtensionChars(filename);
        !          1341:        else
        !          1342:                extChars = 0;
        !          1343:        
        !          1344:        if ( extChars > 0 )
        !          1345:                length -= (extChars + 1);       // skip dot plus extension characters
        !          1346: 
        !          1347:        // scan for file id digits...
        !          1348:        for ( i = length - 1; i >= 0; --i)
        !          1349:        {
        !          1350:                c = filename[i];
        !          1351: 
        !          1352:                if ( c == '#' )         // look for file ID marker
        !          1353:                {
        !          1354:                        if ( (length - i) < 3 )
        !          1355:                                break;          // too small to be a file ID
        !          1356: 
        !          1357:                        *prefixLength = i;
        !          1358:                        return HexStringToInteger(length - i - 1, &filename[i+1]);
        !          1359:                }
        !          1360: 
        !          1361:                if ( !IsHexDigit(c) )
        !          1362:                        break;                  // file ID string must have hex digits  
        !          1363:        }
        !          1364: 
        !          1365:        return 0;
        !          1366: 
        !          1367: } // end GetEmbeddedFileID
        !          1368: 
        !          1369: 
        !          1370: //_______________________________________________________________________
        !          1371: 
        !          1372: static UInt32
        !          1373: HexStringToInteger (UInt32 length, const UInt8 *hexStr)
        !          1374: {
        !          1375:        UInt32          value;  // decimal value represented by the string
        !          1376:        short           i;
        !          1377:        UInt8           c;              // next character in buffer
        !          1378:        const UInt8     *p;             // pointer to character string
        !          1379: 
        !          1380:        value = 0;
        !          1381:        p = hexStr;
        !          1382: 
        !          1383:        for ( i = 0; i < length; ++i )
        !          1384:        {
        !          1385:                c = *p++;
        !          1386: 
        !          1387:                if (c >= '0' && c <= '9')
        !          1388:                {
        !          1389:                        value = value << 4;
        !          1390:                        value += (UInt32) c - (UInt32) '0';
        !          1391:                }
        !          1392:                else if (c >= 'A' && c <= 'F')
        !          1393:                {
        !          1394:                        value = value << 4;
        !          1395:                        value += 10 + ((unsigned int) c - (unsigned int) 'A');
        !          1396:                }
        !          1397:                else
        !          1398:                {
        !          1399:                        return 0;       // oops, how did this character get in here?
        !          1400:                }
        !          1401:        }
        !          1402: 
        !          1403:        return value;
        !          1404: 
        !          1405: } // end HexStringToInteger
        !          1406: 
        !          1407: 
        !          1408: //_______________________________________________________________________
        !          1409: //
        !          1410: //     Routine:        FastRelString
        !          1411: //
        !          1412: //     Output:         returns -1 if str1 < str2
        !          1413: //                             returns  1 if str1 > str2
        !          1414: //                             return   0 if equal
        !          1415: //
        !          1416: //_______________________________________________________________________
        !          1417: 
        !          1418: #if USE_TABLE_ACCESSORS
        !          1419:        UInt16 *Get_gCompareTable(void);
        !          1420: #else
        !          1421:        extern unsigned short gCompareTable[];
        !          1422: #endif
        !          1423: 
        !          1424: SInt32 FastRelString( ConstStr255Param str1, ConstStr255Param str2 )
        !          1425: {
        !          1426:        UInt16*                 compareTable;
        !          1427:        SInt32                  bestGuess;
        !          1428:        UInt8                   length, length2;
        !          1429: 
        !          1430:        
        !          1431:        length = *(str1++);
        !          1432:        length2 = *(str2++);
        !          1433: 
        !          1434:        if (length == length2)
        !          1435:                bestGuess = 0;
        !          1436:        else if (length < length2)
        !          1437:                bestGuess = -1;
        !          1438:        else
        !          1439:        {
        !          1440:                bestGuess = 1;
        !          1441:                length = length2;
        !          1442:        }
        !          1443: 
        !          1444: #if USE_TABLE_ACCESSORS
        !          1445:        compareTable = Get_gCompareTable();
        !          1446: #else
        !          1447:        compareTable = (UInt16*) gCompareTable;
        !          1448: #endif
        !          1449: 
        !          1450:        while (length--)
        !          1451:        {
        !          1452:                UInt8   aChar, bChar;
        !          1453: 
        !          1454:                aChar = *(str1++);
        !          1455:                bChar = *(str2++);
        !          1456:                
        !          1457:                if (aChar != bChar)             //      If they don't match exacly, do case conversion
        !          1458:                {       
        !          1459:                        UInt16  aSortWord, bSortWord;
        !          1460: 
        !          1461:                        aSortWord = compareTable[aChar];
        !          1462:                        bSortWord = compareTable[bChar];
        !          1463: 
        !          1464:                        if (aSortWord > bSortWord)
        !          1465:                                return 1;
        !          1466: 
        !          1467:                        if (aSortWord < bSortWord)
        !          1468:                                return -1;
        !          1469:                }
        !          1470:                
        !          1471:                //      If characters match exactly, then go on to next character immediately without
        !          1472:                //      doing any extra work.
        !          1473:        }
        !          1474:        
        !          1475:        //      if you got to here, then return bestGuess
        !          1476:        return bestGuess;
        !          1477: }      
        !          1478: 
        !          1479: 
        !          1480: 
        !          1481: /* 0x00A0 - 0x00FF = Latin 1 Supplement (30 total) */
        !          1482: UInt8 gLatin1Table[] =
        !          1483: {                 /*  0     1     2     3     4     5     6     7     8     9     A     B     C     D     E     F  */
        !          1484:        /* 0x00A0 */    0xCA, 0xC1, 0xA2, 0xA3, 0xDB, 0xB4,  '?', 0xA4, 0xAC, 0xA9, 0xBB, 0xC7, 0xC2,  '?', 0xA8, 0xF8,
        !          1485:        /* 0x00B0 */    0xA1, 0XB1,  '?',  '?', 0xAB, 0xB5, 0xA6, 0xe1, 0xFC,  '?', 0xBC, 0xC8,  '?',  '?',  '?', 0xC0,
        !          1486:        /* 0x00C0 */     '?',  '?',  '?',  '?',  '?',  '?', 0xAE,  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',
        !          1487:        /* 0x00D0 */     '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?', 0xAF,  '?',  '?',  '?',  '?',  '?',  '?', 0xA7,
        !          1488:        /* 0x00E0 */     '?',  '?',  '?',  '?',  '?',  '?', 0xBE,  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',
        !          1489:        /* 0x00F0 */     '?',  '?',  '?',  '?',  '?',  '?',  '?', 0xD6, 0xBF,  '?',  '?',  '?',  '?',  '?',  '?',  '?'
        !          1490: };
        !          1491: 
        !          1492: 
        !          1493: /* 0x02C0 - 0x02DF = Spacing Modifiers (8 total) */
        !          1494: UInt8 gSpaceModsTable[] =
        !          1495: {                 /*  0     1     2     3     4     5     6     7     8     9     A     B     C     D     E     F  */
        !          1496:        /* 0x02C0 */     '?',  '?',  '?',  '?',  '?',  '?', 0xF6, 0xFF,  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',
        !          1497:        /* 0x02D0 */     '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?', 0xF9, 0xFA, 0xFB, 0xFE, 0xF7, 0xFD,  '?',  '?'
        !          1498: };
        !          1499: 
        !          1500: 
        !          1501: /* 0x20xx = General Punctuation (16 total) */
        !          1502: UInt8 gPunctTable[] =
        !          1503: {                 /*  0     1     2     3     4     5     6     7     8     9     A     B     C     D     E     F  */
        !          1504:        /* 0x2000 */     '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',
        !          1505:        /* 0x2010 */     '?',  '?',  '?', 0xd0, 0xd1,  '?',  '?',  '?', 0xd4, 0xd5, 0xe2,  '?', 0xd2, 0xd3, 0xe3,  '?',
        !          1506:        /* 0x2020 */    0xa0, 0xe0, 0xa5,  '?',  '?',  '?', 0xc9,  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',
        !          1507:        /* 0x2030 */    0xe4,  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?', 0xdc, 0xdd,  '?',  '?',  '?',  '?',  '?',
        !          1508:        /* 0x2040 */     '?',  '?',  '?',  '?', 0xda,  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?'
        !          1509: };
        !          1510: 
        !          1511: 
        !          1512: /* 0x2200 = Mathematical Operators (11 total) */
        !          1513: UInt8 gMathTable[] =
        !          1514: {                 /*  0     1     2     3     4     5     6     7     8     9     A     B     C     D     E     F  */
        !          1515:        /* 0x2200 */     '?',  '?', 0xb6,  '?',  '?',  '?', 0xc6,  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?', 0xb8,
        !          1516:        /* 0x2210 */     '?', 0xb7,  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?', 0xc3,  '?',  '?',  '?', 0xb0,  '?',
        !          1517:        /* 0x2220 */     '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?', 0xba,  '?',  '?',  '?',  '?',
        !          1518:        /* 0x2230 */     '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',
        !          1519:        /* 0x2240 */     '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?', 0xc5,  '?',  '?',  '?',  '?',  '?',  '?',  '?',
        !          1520:        /* 0x2250 */     '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',
        !          1521:        /* 0x2260 */    0xad,  '?',  '?',  '?', 0xb2, 0xb3,  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?'
        !          1522: };
        !          1523: 
        !          1524: 
        !          1525: /* */
        !          1526: UInt8 gReverseCombTable[] =
        !          1527: {                 /*  0     1     2     3     4     5     6     7     8     9     A     B     C     D     E     F  */
        !          1528:        /* 0x40 */              0xDA, 0x40, 0xDA, 0xDA, 0xDA, 0x56, 0xDA, 0xDA, 0xDA, 0x6C, 0xDA, 0xDA, 0xDA, 0xDA, 0x82, 0x98,
        !          1529:        /* 0x50 */              0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xAE, 0xDA, 0xDA, 0xDA, 0xC4, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA,
        !          1530:        /* 0x60 */              0xDA, 0x4B, 0xDA, 0xDA, 0xDA, 0x61, 0xDA, 0xDA, 0xDA, 0x77, 0xDA, 0xDA, 0xDA, 0xDA, 0x8D, 0xA3,
        !          1531:        /* 0x70 */              0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xB9, 0xDA, 0xDA, 0xDA, 0xCF, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA,
        !          1532: 
        !          1533:        /* Combining Diacritical Marks (0x0300 - 0x030A) */
        !          1534: 
        !          1535:        /*                0     1     2     3     4     5     6     7     8     9     A  */
        !          1536:        /*  'A'   */
        !          1537:        /* 0x0300 */    0xCB, 0xE7, 0xE5, 0xCC,  '?',  '?',  '?',  '?', 0x80,  '?', 0x81,
        !          1538: 
        !          1539:        /*  'a'   */
        !          1540:        /* 0x0300 */    0x88, 0x87, 0x89, 0x8B,  '?',  '?',  '?',  '?', 0x8A,  '?', 0x8C,
        !          1541: 
        !          1542:        /*  'E'   */
        !          1543:        /* 0x0300 */    0xE9, 0x83, 0xE6,  '?',  '?',  '?',  '?',  '?', 0xE8,  '?',  '?',
        !          1544: 
        !          1545:        /*  'e'   */
        !          1546:        /* 0x0300 */    0x8F, 0x8E, 0x90,  '?',  '?',  '?',  '?',  '?', 0x91,  '?',  '?',
        !          1547: 
        !          1548:        /*  'I'   */
        !          1549:        /* 0x0300 */    0xED, 0xEA, 0xEB,  '?',  '?',  '?',  '?',  '?', 0xEC,  '?',  '?',
        !          1550: 
        !          1551:        /*  'i'   */
        !          1552:        /* 0x0300 */    0x93, 0x92, 0x94,  '?',  '?',  '?',  '?',  '?', 0x95,  '?',  '?',
        !          1553: 
        !          1554:        /*  'N'   */
        !          1555:        /* 0x0300 */     '?',  '?',  '?', 0x84,  '?',  '?',  '?',  '?',  '?',  '?',  '?',
        !          1556: 
        !          1557:        /*  'n'   */
        !          1558:        /* 0x0300 */     '?',  '?',  '?', 0x96,  '?',  '?',  '?',  '?',  '?',  '?',  '?',
        !          1559: 
        !          1560:        /*  'O'   */
        !          1561:        /* 0x0300 */    0xF1, 0xEE, 0xEF, 0xCD,  '?',  '?',  '?',  '?', 0x85,  '?',  '?',
        !          1562: 
        !          1563:        /*  'o'   */
        !          1564:        /* 0x0300 */    0x98, 0x97, 0x99, 0x9B,  '?',  '?',  '?',  '?', 0x9A,  '?',  '?',
        !          1565: 
        !          1566:        /*  'U'   */
        !          1567:        /* 0x0300 */    0xF4, 0xF2, 0xF3,  '?',  '?',  '?',  '?',  '?', 0x86,  '?',  '?',
        !          1568:        
        !          1569:        /*  'u'   */
        !          1570:        /* 0x0300 */    0x9D, 0x9C, 0x9E,  '?',  '?',  '?',  '?',  '?', 0x9F,  '?',  '?',
        !          1571: 
        !          1572:        /*  'Y'   */
        !          1573:        /* 0x0300 */     '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?', 0xD9,  '?',  '?',
        !          1574: 
        !          1575:        /*  'y'   */
        !          1576:        /* 0x0300 */     '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?', 0xD8,  '?',  '?',
        !          1577: 
        !          1578:        /*  else  */
        !          1579:        /* 0x0300 */     '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?',  '?'
        !          1580: };
        !          1581: 
        !          1582: 
        !          1583: static OSErr UnicodeToMacRoman (ItemCount unicodeChars, ConstUniCharArrayPtr unicodeString, Str31 pascalString)
        !          1584: {
        !          1585:        UInt8                   *p;
        !          1586:        const UniChar   *u;
        !          1587:        UniChar                 c;
        !          1588:        UniChar                 mask;
        !          1589:        UInt16                  inputChars;
        !          1590:        UInt16                  pascalChars;
        !          1591:        OSErr                   result = noErr;
        !          1592:        UInt8                   lsb;
        !          1593:        UInt8                   prevChar;
        !          1594:        UInt8                   mc;
        !          1595: 
        !          1596: 
        !          1597:        mask = (UniChar) 0xFF80;
        !          1598:        p = &pascalString[1];
        !          1599:        u = unicodeString;
        !          1600:        inputChars = unicodeChars;
        !          1601:        pascalChars = prevChar = 0;
        !          1602:        
        !          1603:        while (inputChars) {
        !          1604:                c = *(u++);
        !          1605:                lsb = (UInt8) c;
        !          1606: 
        !          1607:                /*
        !          1608:                 * If its not 7-bit ascii, then we need to map it
        !          1609:                 */
        !          1610:                if ( c & mask ) {
        !          1611:                        mc = '?';
        !          1612:                        switch (c & 0xFF00) {
        !          1613:                                case 0x0000:
        !          1614:                                        if (lsb >= 0xA0)
        !          1615:                                                mc = gLatin1Table[lsb - 0xA0];
        !          1616:                                        break;
        !          1617: 
        !          1618:                                case 0x0200:
        !          1619:                                        if (lsb >= 0xC0 && lsb <= 0xDF)
        !          1620:                                                mc = gSpaceModsTable[lsb - 0xC0];
        !          1621:                                        break;
        !          1622: 
        !          1623:                                case 0x2000:
        !          1624:                                        if (lsb <= 0x4F)
        !          1625:                                                mc = gPunctTable[lsb];
        !          1626:                                        break;
        !          1627: 
        !          1628:                                case 0x2200:
        !          1629:                                        if (lsb <= 0x6F)
        !          1630:                                                mc = gMathTable[lsb];
        !          1631:                                        break;
        !          1632: 
        !          1633:                                case 0x0300:
        !          1634:                                        if (c <= 0x030A) {
        !          1635:                                                if (prevChar >= 'A' && prevChar < 'z') {
        !          1636:                                                        mc = gReverseCombTable[gReverseCombTable[prevChar - 0x40] + lsb];
        !          1637:                                                        --p;    /* backup over base char */
        !          1638:                                                        --pascalChars;
        !          1639:                                                }
        !          1640:                                        }
        !          1641:                                        else {
        !          1642:                                                switch (c) {
        !          1643:                                                        case 0x0327:    /* combining cedilla */
        !          1644:                                                                if (prevChar == 'C')
        !          1645:                                                                        mc = 0x82;
        !          1646:                                                                else if (prevChar == 'c')
        !          1647:                                                                        mc = 0x8D;
        !          1648:                                                                else
        !          1649:                                                                        break;
        !          1650:                                                                --p;    /* backup over base char */
        !          1651:                                                                --pascalChars;
        !          1652:                                                                break;
        !          1653: 
        !          1654:                                                        case 0x03A9: mc = 0xBD; break;  /* omega */
        !          1655: 
        !          1656:                                                        case 0x03C0: mc = 0xB9; break;  /* pi */
        !          1657:                                                }
        !          1658:                                        }
        !          1659:                                        break;
        !          1660:                                        
        !          1661:                                default:
        !          1662:                                        switch (c) {
        !          1663:                                                case 0x0131: mc = 0xf5; break;  /* dotless i */
        !          1664: 
        !          1665:                                                case 0x0152: mc = 0xce; break;  /* OE */
        !          1666: 
        !          1667:                                                case 0x0153: mc = 0xcf; break;  /* oe */
        !          1668: 
        !          1669:                                                case 0x0192: mc = 0xc4; break;  /* � */
        !          1670: 
        !          1671:                                                case 0x2122: mc = 0xaa; break;  /* TM */
        !          1672: 
        !          1673:                                                case 0x25ca: mc = 0xd7; break;  /* diamond */
        !          1674: 
        !          1675:                                                case 0xf8ff: mc = 0xf0; break;  /* apple logo */
        !          1676: 
        !          1677:                                                case 0xfb01: mc = 0xde; break;  /* fi */
        !          1678: 
        !          1679:                                                case 0xfb02: mc = 0xdf; break;  /* fl */
        !          1680:                                        }
        !          1681:                        } /* end switch (c & 0xFF00) */
        !          1682:                        
        !          1683:                        /*
        !          1684:                         * If we have an unmapped character then we need to mangle the name...
        !          1685:                         */
        !          1686:                        if (mc == '?')
        !          1687:                                result = kTECUsedFallbacksStatus;
        !          1688:                        
        !          1689:                        prevChar = 0;
        !          1690:                        lsb = mc;
        !          1691: 
        !          1692:                } /* end if (c & mask) */
        !          1693:                else {
        !          1694:                        prevChar = lsb;
        !          1695:                }
        !          1696: 
        !          1697:                if (pascalChars >= 31)
        !          1698:                        break;
        !          1699: 
        !          1700:                *(p++) = lsb;
        !          1701:                ++pascalChars;
        !          1702:                --inputChars;
        !          1703: 
        !          1704:        } /* end while */
        !          1705:        
        !          1706:        pascalString[0] = pascalChars;
        !          1707:        
        !          1708:        if (inputChars > 0)
        !          1709:                result = kTECOutputBufferFullStatus;    /* ran out of room! */
        !          1710: 
        !          1711:        return result;
        !          1712: }
        !          1713: 
        !          1714: 
        !          1715: UniChar        gHiBitBaseUnicode[128] =
        !          1716: {
        !          1717:        /* 0x80 */      0x0041, 0x0041, 0x0043, 0x0045, 0x004e, 0x004f, 0x0055, 0x0061, 
        !          1718:        /* 0x88 */      0x0061, 0x0061, 0x0061, 0x0061, 0x0061, 0x0063, 0x0065, 0x0065, 
        !          1719:        /* 0x90 */      0x0065, 0x0065, 0x0069, 0x0069, 0x0069, 0x0069, 0x006e, 0x006f, 
        !          1720:        /* 0x98 */      0x006f, 0x006f, 0x006f, 0x006f, 0x0075, 0x0075, 0x0075, 0x0075, 
        !          1721:        /* 0xa0 */      0x2020, 0x00b0, 0x00a2, 0x00a3, 0x00a7, 0x2022, 0x00b6, 0x00df, 
        !          1722:        /* 0xa8 */      0x00ae, 0x00a9, 0x2122, 0x00b4, 0x00a8, 0x2260, 0x00c6, 0x00d8, 
        !          1723:        /* 0xb0 */      0x221e, 0x00b1, 0x2264, 0x2265, 0x00a5, 0x00b5, 0x2202, 0x2211, 
        !          1724:        /* 0xb8 */      0x220f, 0x03c0, 0x222b, 0x00aa, 0x00ba, 0x03a9, 0x00e6, 0x00f8, 
        !          1725:        /* 0xc0 */      0x00bf, 0x00a1, 0x00ac, 0x221a, 0x0192, 0x2248, 0x2206, 0x00ab, 
        !          1726:        /* 0xc8 */      0x00bb, 0x2026, 0x00a0, 0x0041, 0x0041, 0x004f, 0x0152, 0x0153, 
        !          1727:        /* 0xd0 */      0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0x00f7, 0x25ca, 
        !          1728:        /* 0xd8 */      0x0079, 0x0059, 0x2044, 0x00a4, 0x2039, 0x203a, 0xfb01, 0xfb02, 
        !          1729:        /* 0xe0 */      0x2021, 0x00b7, 0x201a, 0x201e, 0x2030, 0x0041, 0x0045, 0x0041, 
        !          1730:        /* 0xe8 */      0x0045, 0x0045, 0x0049, 0x0049, 0x0049, 0x0049, 0x004f, 0x004f, 
        !          1731:        /* 0xf0 */      0xf8ff, 0x004f, 0x0055, 0x0055, 0x0055, 0x0131, 0x02c6, 0x02dc, 
        !          1732:        /* 0xf8 */      0x00af, 0x02d8, 0x02d9, 0x02da, 0x00b8, 0x02dd, 0x02db, 0x02c7
        !          1733: };
        !          1734: 
        !          1735: UniChar        gHiBitCombUnicode[128] =
        !          1736: {
        !          1737:        /* 0x80 */      0x0308, 0x030a, 0x0327, 0x0301, 0x0303, 0x0308, 0x0308, 0x0301, 
        !          1738:        /* 0x88 */      0x0300, 0x0302, 0x0308, 0x0303, 0x030a, 0x0327, 0x0301, 0x0300, 
        !          1739:        /* 0x90 */      0x0302, 0x0308, 0x0301, 0x0300, 0x0302, 0x0308, 0x0303, 0x0301, 
        !          1740:        /* 0x98 */      0x0300, 0x0302, 0x0308, 0x0303, 0x0301, 0x0300, 0x0302, 0x0308, 
        !          1741:        /* 0xa0 */      0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        !          1742:        /* 0xa8 */      0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
        !          1743:        /* 0xb0 */      0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
        !          1744:        /* 0xb8 */      0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
        !          1745:        /* 0xc0 */      0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
        !          1746:        /* 0xc8 */      0x0000, 0x0000, 0x0000, 0x0300, 0x0303, 0x0303, 0x0000, 0x0000, 
        !          1747:        /* 0xd0 */      0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
        !          1748:        /* 0xd8 */      0x0308, 0x0308, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
        !          1749:        /* 0xe0 */      0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0302, 0x0302, 0x0301, 
        !          1750:        /* 0xe8 */      0x0308, 0x0300, 0x0301, 0x0302, 0x0308, 0x0300, 0x0301, 0x0302, 
        !          1751:        /* 0xf0 */      0x0000, 0x0300, 0x0301, 0x0302, 0x0300, 0x0000, 0x0000, 0x0000, 
        !          1752:        /* 0xf8 */      0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
        !          1753: };
        !          1754: 
        !          1755: 
        !          1756: static OSErr MacRomanToUnicode (ConstStr255Param pascalString, ItemCount *unicodeChars, UniCharArrayPtr unicodeString)
        !          1757: {
        !          1758:        const UInt8             *p;
        !          1759:        UniChar                 *u;
        !          1760:        UInt16                  pascalChars;
        !          1761:        UInt8                   c;
        !          1762: 
        !          1763: 
        !          1764:        p = pascalString;
        !          1765:        u = unicodeString;
        !          1766: 
        !          1767:        *unicodeChars = pascalChars = *(p++);   // pick up length byte
        !          1768: 
        !          1769:        while (pascalChars--) {
        !          1770:                c = *(p++);
        !          1771: 
        !          1772:                if ( (SInt8) c >= 0 ) {         // make sure its seven bit ascii
        !          1773:                        *(u++) = (UniChar) c;           //  pad high byte with zero
        !          1774:                }
        !          1775:                else {  /* its a hi bit character */
        !          1776:                        UniChar uc;
        !          1777: 
        !          1778:                        c &= 0x7F;
        !          1779:                        *(u++) = uc = gHiBitBaseUnicode[c];
        !          1780:                        
        !          1781:                        /*
        !          1782:                         * if the unicode character (uc) is an alpha char
        !          1783:                         * then we have an additional combining character
        !          1784:                         */
        !          1785:                        if ((uc <= (UniChar) 'z') && (uc >= (UniChar) 'A')) {
        !          1786:                                *(u++) = gHiBitCombUnicode[c];
        !          1787:                                ++(*unicodeChars);
        !          1788:                        }
        !          1789:                }
        !          1790:        }
        !          1791:        
        !          1792:        return noErr;
        !          1793: }
        !          1794: 
        !          1795: 
        !          1796: 
        !          1797: //
        !          1798: //     FastUnicodeCompare - Compare two Unicode strings; produce a relative ordering
        !          1799: //
        !          1800: //         IF                          RESULT
        !          1801: //     --------------------------
        !          1802: //     str1 < str2             =>      -1
        !          1803: //     str1 = str2             =>       0
        !          1804: //     str1 > str2             =>      +1
        !          1805: //
        !          1806: //     The lower case table starts with 256 entries (one for each of the upper bytes
        !          1807: //     of the original Unicode char).  If that entry is zero, then all characters with
        !          1808: //     that upper byte are already case folded.  If the entry is non-zero, then it is
        !          1809: //     the _index_ (not byte offset) of the start of the sub-table for the characters
        !          1810: //     with that upper byte.  All ignorable characters are folded to the value zero.
        !          1811: //
        !          1812: //     In pseudocode:
        !          1813: //
        !          1814: //             Let c = source Unicode character
        !          1815: //             Let table[] = lower case table
        !          1816: //
        !          1817: //             lower = table[highbyte(c)]
        !          1818: //             if (lower == 0)
        !          1819: //                     lower = c
        !          1820: //             else
        !          1821: //                     lower = table[lower+lowbyte(c)]
        !          1822: //
        !          1823: //             if (lower == 0)
        !          1824: //                     ignore this character
        !          1825: //
        !          1826: //     To handle ignorable characters, we now need a loop to find the next valid character.
        !          1827: //     Also, we can't pre-compute the number of characters to compare; the string length might
        !          1828: //     be larger than the number of non-ignorable characters.  Further, we must be able to handle
        !          1829: //     ignorable characters at any point in the string, including as the first or last characters.
        !          1830: //     We use a zero value as a sentinel to detect both end-of-string and ignorable characters.
        !          1831: //     Since the File Manager doesn't prevent the NUL character (value zero) as part of a filename,
        !          1832: //     the case mapping table is assumed to map u+0000 to some non-zero value (like 0xFFFF, which is
        !          1833: //     an invalid Unicode character).
        !          1834: //
        !          1835: //     Pseudocode:
        !          1836: //
        !          1837: //             while (1) {
        !          1838: //                     c1 = GetNextValidChar(str1)                     //      returns zero if at end of string
        !          1839: //                     c2 = GetNextValidChar(str2)
        !          1840: //
        !          1841: //                     if (c1 != c2) break                                     //      found a difference
        !          1842: //
        !          1843: //                     if (c1 == 0)                                            //      reached end of string on both strings at once?
        !          1844: //                             return 0;                                               //      yes, so strings are equal
        !          1845: //             }
        !          1846: //
        !          1847: //             // When we get here, c1 != c2.  So, we just need to determine which one is less.
        !          1848: //             if (c1 < c2)
        !          1849: //                     return -1;
        !          1850: //             else
        !          1851: //                     return 1;
        !          1852: //
        !          1853: 
        !          1854: #if TARGET_OS_MAC
        !          1855: extern void gLowerCaseTable(void);             //      Really an exported data symbol, a table
        !          1856: #else
        !          1857: extern UInt16 gLowerCaseTable[];
        !          1858: #endif
        !          1859: 
        !          1860: SInt32 FastUnicodeCompare ( register ConstUniCharArrayPtr str1, register ItemCount length1,
        !          1861:                                                        register ConstUniCharArrayPtr str2, register ItemCount length2)
        !          1862: {
        !          1863:        register UInt16         c1,c2;
        !          1864:        register UInt16         temp;
        !          1865:        register UInt16*        lowerCaseTable;
        !          1866: 
        !          1867: #if ( FORDISKFIRSTAID || USE_TABLE_ACCESSORS)  
        !          1868:        lowerCaseTable = Get_gLowerCaseTable();
        !          1869: #else
        !          1870:        lowerCaseTable = (UInt16*) gLowerCaseTable;
        !          1871: #endif
        !          1872: 
        !          1873:        while (1) {
        !          1874:                //      Set default values for c1, c2 in case there are no more valid chars
        !          1875:                c1 = 0;
        !          1876:                c2 = 0;
        !          1877:                
        !          1878:                //      Find next non-ignorable char from str1, or zero if no more
        !          1879:                while (length1 && c1 == 0) {
        !          1880:                        c1 = *(str1++);
        !          1881:                        --length1;
        !          1882:                        if ((temp = lowerCaseTable[c1>>8]) != 0)                //      is there a subtable for this upper byte?
        !          1883:                                c1 = lowerCaseTable[temp + (c1 & 0x00FF)];      //      yes, so fold the char
        !          1884:                }
        !          1885:                
        !          1886:                
        !          1887:                //      Find next non-ignorable char from str2, or zero if no more
        !          1888:                while (length2 && c2 == 0) {
        !          1889:                        c2 = *(str2++);
        !          1890:                        --length2;
        !          1891:                        if ((temp = lowerCaseTable[c2>>8]) != 0)                //      is there a subtable for this upper byte?
        !          1892:                                c2 = lowerCaseTable[temp + (c2 & 0x00FF)];      //      yes, so fold the char
        !          1893:                }
        !          1894:                
        !          1895:                if (c1 != c2)           //      found a difference, so stop looping
        !          1896:                        break;
        !          1897:                
        !          1898:                if (c1 == 0)            //      did we reach the end of both strings at the same time?
        !          1899:                        return 0;               //      yes, so strings are equal
        !          1900:        }
        !          1901:        
        !          1902:        if (c1 < c2)
        !          1903:                return -1;
        !          1904:        else
        !          1905:                return 1;
        !          1906: }
        !          1907: 
        !          1908: 
        !          1909: OSErr
        !          1910: ConvertUTF8ToUnicode(ByteCount srcLen, const unsigned char* srcStr, ByteCount maxDstLen,
        !          1911:                                         ByteCount *actualDstLen, UniCharArrayPtr dstStr)
        !          1912: {
        !          1913:        ConversionResult result;
        !          1914:        UTF8* sourceStart;
        !          1915:        UTF8* sourceEnd;
        !          1916:        UTF16* targetStart;
        !          1917:        UTF16* targetEnd;
        !          1918: 
        !          1919:        sourceStart = (UTF8*) srcStr;
        !          1920:        sourceEnd = sourceStart + srcLen;
        !          1921:        targetStart = (UTF16*) dstStr;
        !          1922:        targetEnd = targetStart + maxDstLen/2;
        !          1923: 
        !          1924:        result = ConvertUTF8toUTF16 (&sourceStart, sourceEnd, &targetStart, targetEnd);
        !          1925:        
        !          1926:        *actualDstLen = (targetStart - dstStr) * sizeof(UniChar);
        !          1927:        
        !          1928:        if (result == targetExhausted)
        !          1929:                return kTECOutputBufferFullStatus;
        !          1930:        else if (result == sourceExhausted)
        !          1931:                return kTextMalformedInputErr;
        !          1932: 
        !          1933:        return noErr;
        !          1934: }
        !          1935: 
        !          1936: 
        !          1937: OSErr
        !          1938: ConvertUnicodeToUTF8(ByteCount srcLen, ConstUniCharArrayPtr srcStr, ByteCount maxDstLen,
        !          1939:                                         ByteCount *actualDstLen, unsigned char* dstStr)
        !          1940: {
        !          1941:        ConversionResult result;
        !          1942:        UTF16* sourceStart;
        !          1943:        UTF16* sourceEnd;
        !          1944:        UTF8* targetStart;
        !          1945:        UTF8* targetEnd;
        !          1946:        ByteCount outputLength;
        !          1947: 
        !          1948:        sourceStart = (UTF16*) srcStr;
        !          1949:        sourceEnd = (UTF16*) ((char*) srcStr + srcLen);
        !          1950:        targetStart = (UTF8*) dstStr;
        !          1951:        targetEnd = targetStart + maxDstLen;
        !          1952:        
        !          1953:        result = ConvertUTF16toUTF8 (&sourceStart, sourceEnd, &targetStart, targetEnd);
        !          1954:        
        !          1955:        *actualDstLen = outputLength = targetStart - dstStr;
        !          1956: 
        !          1957:        if (result == targetExhausted)
        !          1958:                return kTECOutputBufferFullStatus;
        !          1959:        else if (result == sourceExhausted)
        !          1960:                return kTECPartialCharErr;
        !          1961: 
        !          1962:        if (outputLength >= maxDstLen)
        !          1963:                return kTECOutputBufferFullStatus;
        !          1964:                
        !          1965:        dstStr[outputLength] = 0;       /* also add null termination */
        !          1966: 
        !          1967:        return noErr;
        !          1968: }
        !          1969: 
        !          1970: 
        !          1971: OSErr
        !          1972: ConvertUTF8ToMacRoman(ByteCount srcLen, const unsigned char* srcStr, Str31 dstStr)
        !          1973: {
        !          1974:        UniChar uniStr[64];
        !          1975:        ByteCount uniLen;
        !          1976:        OSErr result;
        !          1977: 
        !          1978:     result = ConvertUTF8ToUnicode(srcLen, srcStr, sizeof(uniStr), &uniLen, uniStr);
        !          1979:        if (result == 0)
        !          1980:                result = UnicodeToMacRoman(uniLen / sizeof(UniChar), uniStr, dstStr);
        !          1981: 
        !          1982:        return result;
        !          1983: }
        !          1984: 
        !          1985: 
        !          1986: OSErr
        !          1987: ConvertMacRomanToUTF8(Str31 srcStr, ByteCount maxDstLen, ByteCount *actualDstLen,
        !          1988:                                          unsigned char* dstStr)
        !          1989: {
        !          1990:        UniChar uniStr[64];
        !          1991:        ItemCount unicodeChars;
        !          1992:        OSErr result;
        !          1993: 
        !          1994:        result = MacRomanToUnicode(srcStr, &unicodeChars, uniStr);
        !          1995: 
        !          1996:        if (result == 0)
        !          1997:                result = ConvertUnicodeToUTF8(unicodeChars * sizeof(UniChar), uniStr,
        !          1998:                                                                          maxDstLen, actualDstLen, dstStr);
        !          1999:        return result;
        !          2000: }
        !          2001: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.