Annotation of kernel/bsd/hfs/hfscommon/Unicode/UnicodeWrappers.c, revision 1.1.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.