|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * "Portions Copyright (c) 2000 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.0 (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: #include <sys/param.h> ! 26: #include <sys/systm.h> ! 27: #include <sys/kernel.h> ! 28: #include <sys/lock.h> ! 29: #include <sys/malloc.h> ! 30: #include <sys/queue.h> ! 31: ! 32: #include "hfs.h" ! 33: ! 34: ! 35: /* hfs encoding converter list */ ! 36: SLIST_HEAD(encodinglst, hfs_encoding) hfs_encoding_list = {0}; ! 37: decl_simple_lock_data(,hfs_encoding_list_slock); ! 38: ! 39: ! 40: /* hfs encoding converter entry */ ! 41: struct hfs_encoding { ! 42: SLIST_ENTRY(hfs_encoding) link; ! 43: int refcount; ! 44: int kmod_id; ! 45: UInt32 encoding; ! 46: hfs_to_unicode_func_t get_unicode_func; ! 47: unicode_to_hfs_func_t get_hfsname_func; ! 48: }; ! 49: ! 50: /* XXX We should use an "official" interface! */ ! 51: extern kern_return_t kmod_destroy(host_t host, kmod_t id); ! 52: extern struct host realhost; ! 53: ! 54: #define MAX_HFS_UNICODE_CHARS (15*5) ! 55: ! 56: static int mac_roman_to_unicode(Str31 hfs_str, UniChar *uni_str, UInt32 maxCharLen, UInt32 *usedCharLen); ! 57: ! 58: static int unicode_to_mac_roman(UniChar *uni_str, UInt32 unicodeChars, Str31 hfs_str); ! 59: ! 60: ! 61: void ! 62: hfs_converterinit(void) ! 63: { ! 64: SLIST_INIT(&hfs_encoding_list); ! 65: simple_lock_init(&hfs_encoding_list_slock); ! 66: ! 67: /* ! 68: * add resident MacRoman converter and take a reference ! 69: * since its always "loaded". ! 70: */ ! 71: hfs_addconverter(0, kTextEncodingMacRoman, mac_roman_to_unicode, unicode_to_mac_roman); ! 72: SLIST_FIRST(&hfs_encoding_list)->refcount++; ! 73: } ! 74: ! 75: ! 76: /* ! 77: * hfs_addconverter - add an HFS encoding converter ! 78: * ! 79: * This is called exclusivly by kernel loadable modules ! 80: * (like HFS_Japanese.kmod) to register hfs encoding ! 81: * conversion routines. ! 82: * ! 83: */ ! 84: int ! 85: hfs_addconverter(int id, UInt32 encoding, hfs_to_unicode_func_t get_unicode, unicode_to_hfs_func_t get_hfsname) ! 86: { ! 87: struct hfs_encoding *encp; ! 88: ! 89: MALLOC(encp, struct hfs_encoding *, sizeof(struct hfs_encoding), M_TEMP, M_WAITOK); ! 90: ! 91: simple_lock(&hfs_encoding_list_slock); ! 92: ! 93: encp->link.sle_next = NULL; ! 94: encp->refcount = 0; ! 95: encp->encoding = encoding; ! 96: encp->get_unicode_func = get_unicode; ! 97: encp->get_hfsname_func = get_hfsname; ! 98: encp->kmod_id = id; ! 99: SLIST_INSERT_HEAD(&hfs_encoding_list, encp, link); ! 100: ! 101: simple_unlock(&hfs_encoding_list_slock); ! 102: return (0); ! 103: } ! 104: ! 105: ! 106: /* ! 107: * hfs_remconverter - remove an HFS encoding converter ! 108: * ! 109: * Can be called by a kernel loadable module's finalize ! 110: * routine to remove an encoding converter so that the ! 111: * module (i.e. the code) can be unloaded. ! 112: * ! 113: * However, in the normal case, the removing and unloading ! 114: * of these converters is done in hfs_relconverter. ! 115: * The call is initiated from within the kernel during the unmounting of an hfs voulume. ! 116: */ ! 117: int ! 118: hfs_remconverter(int id, UInt32 encoding) ! 119: { ! 120: struct hfs_encoding *encp; ! 121: int busy = 0; ! 122: ! 123: simple_lock(&hfs_encoding_list_slock); ! 124: SLIST_FOREACH(encp, &hfs_encoding_list, link) { ! 125: if (encp->encoding == encoding && encp->kmod_id == id) { ! 126: encp->refcount--; ! 127: ! 128: /* if converter is no longer in use, release it */ ! 129: if (encp->refcount <= 0 && encp->kmod_id != 0) { ! 130: SLIST_REMOVE(&hfs_encoding_list, encp, hfs_encoding, link); ! 131: FREE(encp, M_TEMP); ! 132: } else { ! 133: busy = 1; ! 134: } ! 135: break; ! 136: } ! 137: } ! 138: simple_unlock(&hfs_encoding_list_slock); ! 139: ! 140: return (busy); ! 141: } ! 142: ! 143: ! 144: /* ! 145: * hfs_getconverter - get HFS encoding converters ! 146: * ! 147: * Normally called during the mounting of an hfs voulume. ! 148: */ ! 149: int ! 150: hfs_getconverter(UInt32 encoding, hfs_to_unicode_func_t *get_unicode, unicode_to_hfs_func_t *get_hfsname) ! 151: { ! 152: struct hfs_encoding *encp; ! 153: int found = 0; ! 154: ! 155: simple_lock(&hfs_encoding_list_slock); ! 156: SLIST_FOREACH(encp, &hfs_encoding_list, link) { ! 157: if (encp->encoding == encoding) { ! 158: found = 1; ! 159: *get_unicode = encp->get_unicode_func; ! 160: *get_hfsname = encp->get_hfsname_func; ! 161: ++encp->refcount; ! 162: break; ! 163: } ! 164: } ! 165: simple_unlock(&hfs_encoding_list_slock); ! 166: ! 167: if (!found) { ! 168: *get_unicode = NULL; ! 169: *get_hfsname = NULL; ! 170: return (EINVAL); ! 171: } ! 172: ! 173: return (0); ! 174: } ! 175: ! 176: ! 177: /* ! 178: * hfs_relconverter - release interest in an HFS encoding converter ! 179: * ! 180: * Normally called during the unmounting of an hfs voulume. ! 181: */ ! 182: int ! 183: hfs_relconverter(UInt32 encoding) ! 184: { ! 185: struct hfs_encoding *encp; ! 186: int found = 0; ! 187: ! 188: simple_lock(&hfs_encoding_list_slock); ! 189: SLIST_FOREACH(encp, &hfs_encoding_list, link) { ! 190: if (encp->encoding == encoding) { ! 191: found = 1; ! 192: encp->refcount--; ! 193: ! 194: /* if converter is no longer in use, release it */ ! 195: if (encp->refcount <= 0 && encp->kmod_id != 0) { ! 196: int id = encp->kmod_id; ! 197: ! 198: SLIST_REMOVE(&hfs_encoding_list, encp, hfs_encoding, link); ! 199: FREE(encp, M_TEMP); ! 200: encp = NULL; ! 201: ! 202: simple_unlock(&hfs_encoding_list_slock); ! 203: kmod_destroy(&realhost, id); ! 204: simple_lock(&hfs_encoding_list_slock); ! 205: } ! 206: break; ! 207: } ! 208: } ! 209: simple_unlock(&hfs_encoding_list_slock); ! 210: ! 211: return (found ? 0 : EINVAL); ! 212: } ! 213: ! 214: ! 215: /* ! 216: * Convert HFS encoded string into UTF-8 ! 217: * ! 218: * Unicode output is fully decomposed ! 219: * '/' chars are converted to ':' ! 220: */ ! 221: int ! 222: hfs_to_utf8(ExtendedVCB *vcb, Str31 hfs_str, ByteCount maxDstLen, ByteCount *actualDstLen, unsigned char* dstStr) ! 223: { ! 224: int error; ! 225: UniChar uniStr[MAX_HFS_UNICODE_CHARS]; ! 226: ItemCount uniCount; ! 227: hfs_to_unicode_func_t hfs_get_unicode = VCBTOHFS(vcb)->hfs_get_unicode; ! 228: ! 229: error = hfs_get_unicode(hfs_str, uniStr, MAX_HFS_UNICODE_CHARS, &uniCount); ! 230: ! 231: if (error == 0) ! 232: error = ConvertUnicodeToUTF8(uniCount * sizeof(UniChar), uniStr, maxDstLen, actualDstLen, dstStr); ! 233: ! 234: return error; ! 235: } ! 236: ! 237: ! 238: /* ! 239: * Convert UTF-8 string into HFS encoding ! 240: * ! 241: * ':' chars are converted to '/' ! 242: * Assumes input represents fully decomposed Unicode ! 243: */ ! 244: int ! 245: utf8_to_hfs(ExtendedVCB *vcb, ByteCount srcLen, const unsigned char* srcStr, Str31 dstStr) ! 246: { ! 247: int error; ! 248: UniChar uniStr[MAX_HFS_UNICODE_CHARS]; ! 249: ItemCount uniCount; ! 250: unicode_to_hfs_func_t hfs_get_hfsname = VCBTOHFS(vcb)->hfs_get_hfsname; ! 251: ! 252: error = ConvertUTF8ToUnicode(srcLen, srcStr, sizeof(uniStr), &uniCount, uniStr); ! 253: if (error == 0) ! 254: error = hfs_get_hfsname(uniStr, uniCount/sizeof(UniChar), dstStr); ! 255: ! 256: return error; ! 257: } ! 258: ! 259: ! 260: ! 261: /* ! 262: * HFS MacRoman to/from Unicode conversions are built into the kernel ! 263: * All others hfs encodings are loadable. ! 264: */ ! 265: ! 266: /* 0x00A0 - 0x00FF = Latin 1 Supplement (30 total) */ ! 267: static UInt8 gLatin1Table[] = { ! 268: /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ ! 269: /* 0x00A0 */ 0xCA, 0xC1, 0xA2, 0xA3, 0xDB, 0xB4, '?', 0xA4, 0xAC, 0xA9, 0xBB, 0xC7, 0xC2, '?', 0xA8, 0xF8, ! 270: /* 0x00B0 */ 0xA1, 0XB1, '?', '?', 0xAB, 0xB5, 0xA6, 0xe1, 0xFC, '?', 0xBC, 0xC8, '?', '?', '?', 0xC0, ! 271: /* 0x00C0 */ '?', '?', '?', '?', '?', '?', 0xAE, '?', '?', '?', '?', '?', '?', '?', '?', '?', ! 272: /* 0x00D0 */ '?', '?', '?', '?', '?', '?', '?', '?', 0xAF, '?', '?', '?', '?', '?', '?', 0xA7, ! 273: /* 0x00E0 */ '?', '?', '?', '?', '?', '?', 0xBE, '?', '?', '?', '?', '?', '?', '?', '?', '?', ! 274: /* 0x00F0 */ '?', '?', '?', '?', '?', '?', '?', 0xD6, 0xBF, '?', '?', '?', '?', '?', '?', '?' ! 275: }; ! 276: ! 277: /* 0x02C0 - 0x02DF = Spacing Modifiers (8 total) */ ! 278: static UInt8 gSpaceModsTable[] = { ! 279: /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ ! 280: /* 0x02C0 */ '?', '?', '?', '?', '?', '?', 0xF6, 0xFF, '?', '?', '?', '?', '?', '?', '?', '?', ! 281: /* 0x02D0 */ '?', '?', '?', '?', '?', '?', '?', '?', 0xF9, 0xFA, 0xFB, 0xFE, 0xF7, 0xFD, '?', '?' ! 282: }; ! 283: ! 284: /* 0x2010 - 0x20AF = General Punctuation (17 total) */ ! 285: static UInt8 gPunctTable[] = { ! 286: /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ ! 287: /* 0x2010 */ '?', '?', '?', 0xd0, 0xd1, '?', '?', '?', 0xd4, 0xd5, 0xe2, '?', 0xd2, 0xd3, 0xe3, '?', ! 288: /* 0x2020 */ 0xa0, 0xe0, 0xa5, '?', '?', '?', 0xc9, '?', '?', '?', '?', '?', '?', '?', '?', '?', ! 289: /* 0x2030 */ 0xe4, '?', '?', '?', '?', '?', '?', '?', '?', 0xdc, 0xdd, '?', '?', '?', '?', '?', ! 290: /* 0x2040 */ '?', '?', '?', '?', 0xda, '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', ! 291: /* 0x2050 */ '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', ! 292: /* 0x2060 */ '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', ! 293: /* 0x2070 */ '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', ! 294: /* 0x2080 */ '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', ! 295: /* 0x2090 */ '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', ! 296: /* 0x20A0 */ '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', 0xdb, '?', '?', '?' ! 297: }; ! 298: ! 299: /* 0x22xx = Mathematical Operators (11 total) */ ! 300: static UInt8 gMathTable[] = { ! 301: /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ ! 302: /* 0x2200 */ '?', '?', 0xb6, '?', '?', '?', 0xc6, '?', '?', '?', '?', '?', '?', '?', '?', 0xb8, ! 303: /* 0x2210 */ '?', 0xb7, '?', '?', '?', '?', '?', '?', '?', '?', 0xc3, '?', '?', '?', 0xb0, '?', ! 304: /* 0x2220 */ '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', 0xba, '?', '?', '?', '?', ! 305: /* 0x2230 */ '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', ! 306: /* 0x2240 */ '?', '?', '?', '?', '?', '?', '?', '?', 0xc5, '?', '?', '?', '?', '?', '?', '?', ! 307: /* 0x2250 */ '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', ! 308: /* 0x2260 */ 0xad, '?', '?', '?', 0xb2, 0xb3, '?', '?' ! 309: }; ! 310: ! 311: /* */ ! 312: static UInt8 gReverseCombTable[] = { ! 313: /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ ! 314: /* 0x40 */ 0xDA, 0x40, 0xDA, 0xDA, 0xDA, 0x56, 0xDA, 0xDA, 0xDA, 0x6C, 0xDA, 0xDA, 0xDA, 0xDA, 0x82, 0x98, ! 315: /* 0x50 */ 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xAE, 0xDA, 0xDA, 0xDA, 0xC4, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, ! 316: /* 0x60 */ 0xDA, 0x4B, 0xDA, 0xDA, 0xDA, 0x61, 0xDA, 0xDA, 0xDA, 0x77, 0xDA, 0xDA, 0xDA, 0xDA, 0x8D, 0xA3, ! 317: /* 0x70 */ 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xB9, 0xDA, 0xDA, 0xDA, 0xCF, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, ! 318: ! 319: /* Combining Diacritical Marks (0x0300 - 0x030A) */ ! 320: /* 0 1 2 3 4 5 6 7 8 9 A */ ! 321: /* 'A' */ ! 322: /* 0x0300 */ 0xCB, 0xE7, 0xE5, 0xCC, '?', '?', '?', '?', 0x80, '?', 0x81, ! 323: ! 324: /* 'a' */ ! 325: /* 0x0300 */ 0x88, 0x87, 0x89, 0x8B, '?', '?', '?', '?', 0x8A, '?', 0x8C, ! 326: ! 327: /* 'E' */ ! 328: /* 0x0300 */ 0xE9, 0x83, 0xE6, '?', '?', '?', '?', '?', 0xE8, '?', '?', ! 329: ! 330: /* 'e' */ ! 331: /* 0x0300 */ 0x8F, 0x8E, 0x90, '?', '?', '?', '?', '?', 0x91, '?', '?', ! 332: ! 333: /* 'I' */ ! 334: /* 0x0300 */ 0xED, 0xEA, 0xEB, '?', '?', '?', '?', '?', 0xEC, '?', '?', ! 335: ! 336: /* 'i' */ ! 337: /* 0x0300 */ 0x93, 0x92, 0x94, '?', '?', '?', '?', '?', 0x95, '?', '?', ! 338: ! 339: /* 'N' */ ! 340: /* 0x0300 */ '?', '?', '?', 0x84, '?', '?', '?', '?', '?', '?', '?', ! 341: ! 342: /* 'n' */ ! 343: /* 0x0300 */ '?', '?', '?', 0x96, '?', '?', '?', '?', '?', '?', '?', ! 344: ! 345: /* 'O' */ ! 346: /* 0x0300 */ 0xF1, 0xEE, 0xEF, 0xCD, '?', '?', '?', '?', 0x85, '?', '?', ! 347: ! 348: /* 'o' */ ! 349: /* 0x0300 */ 0x98, 0x97, 0x99, 0x9B, '?', '?', '?', '?', 0x9A, '?', '?', ! 350: ! 351: /* 'U' */ ! 352: /* 0x0300 */ 0xF4, 0xF2, 0xF3, '?', '?', '?', '?', '?', 0x86, '?', '?', ! 353: ! 354: /* 'u' */ ! 355: /* 0x0300 */ 0x9D, 0x9C, 0x9E, '?', '?', '?', '?', '?', 0x9F, '?', '?', ! 356: ! 357: /* 'Y' */ ! 358: /* 0x0300 */ '?', '?', '?', '?', '?', '?', '?', '?', 0xD9, '?', '?', ! 359: ! 360: /* 'y' */ ! 361: /* 0x0300 */ '?', '?', '?', '?', '?', '?', '?', '?', 0xD8, '?', '?', ! 362: ! 363: /* else */ ! 364: /* 0x0300 */ '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?' ! 365: }; ! 366: ! 367: ! 368: /* ! 369: * Convert Unicode string into HFS MacRoman encoding ! 370: * ! 371: * Assumes Unicode input is fully decomposed ! 372: */ ! 373: static int unicode_to_mac_roman(UniChar *uni_str, UInt32 unicodeChars, Str31 hfs_str) ! 374: { ! 375: UInt8 *p; ! 376: const UniChar *u; ! 377: UniChar c; ! 378: UniChar mask; ! 379: UInt16 inputChars; ! 380: UInt16 pascalChars; ! 381: OSErr result = noErr; ! 382: UInt8 lsb; ! 383: UInt8 prevChar; ! 384: UInt8 mc; ! 385: ! 386: mask = (UniChar) 0xFF80; ! 387: p = &hfs_str[1]; ! 388: u = uni_str; ! 389: inputChars = unicodeChars; ! 390: pascalChars = prevChar = 0; ! 391: ! 392: while (inputChars) { ! 393: c = *(u++); ! 394: lsb = (UInt8) c; ! 395: ! 396: /* ! 397: * If its not 7-bit ascii, then we need to map it ! 398: */ ! 399: if ( c & mask ) { ! 400: mc = '?'; ! 401: switch (c & 0xFF00) { ! 402: case 0x0000: ! 403: if (lsb >= 0xA0) ! 404: mc = gLatin1Table[lsb - 0xA0]; ! 405: break; ! 406: ! 407: case 0x0200: ! 408: if (lsb >= 0xC0 && lsb <= 0xDF) ! 409: mc = gSpaceModsTable[lsb - 0xC0]; ! 410: break; ! 411: ! 412: case 0x2000: ! 413: if (lsb >= 0x10 && lsb <= 0xAF) ! 414: mc = gPunctTable[lsb- 0x10]; ! 415: break; ! 416: ! 417: case 0x2200: ! 418: if (lsb <= 0x68) ! 419: mc = gMathTable[lsb]; ! 420: break; ! 421: ! 422: case 0x0300: ! 423: if (c <= 0x030A) { ! 424: if (prevChar >= 'A' && prevChar < 'z') { ! 425: mc = gReverseCombTable[gReverseCombTable[prevChar - 0x40] + lsb]; ! 426: --p; /* backup over base char */ ! 427: --pascalChars; ! 428: } ! 429: } else { ! 430: switch (c) { ! 431: case 0x0327: /* combining cedilla */ ! 432: if (prevChar == 'C') ! 433: mc = 0x82; ! 434: else if (prevChar == 'c') ! 435: mc = 0x8D; ! 436: else ! 437: break; ! 438: --p; /* backup over base char */ ! 439: --pascalChars; ! 440: break; ! 441: ! 442: case 0x03A9: mc = 0xBD; break; /* omega */ ! 443: ! 444: case 0x03C0: mc = 0xB9; break; /* pi */ ! 445: } ! 446: } ! 447: break; ! 448: ! 449: default: ! 450: switch (c) { ! 451: case 0x0131: mc = 0xf5; break; /* dotless i */ ! 452: ! 453: case 0x0152: mc = 0xce; break; /* OE */ ! 454: ! 455: case 0x0153: mc = 0xcf; break; /* oe */ ! 456: ! 457: case 0x0192: mc = 0xc4; break; /* � */ ! 458: ! 459: case 0x2122: mc = 0xaa; break; /* TM */ ! 460: ! 461: case 0x25ca: mc = 0xd7; break; /* diamond */ ! 462: ! 463: case 0xf8ff: mc = 0xf0; break; /* apple logo */ ! 464: ! 465: case 0xfb01: mc = 0xde; break; /* fi */ ! 466: ! 467: case 0xfb02: mc = 0xdf; break; /* fl */ ! 468: } ! 469: } /* end switch (c & 0xFF00) */ ! 470: ! 471: /* ! 472: * If we have an unmapped character then we need to mangle the name... ! 473: */ ! 474: if (mc == '?') ! 475: result = kTECUsedFallbacksStatus; ! 476: ! 477: prevChar = 0; ! 478: lsb = mc; ! 479: ! 480: } else { ! 481: prevChar = lsb; ! 482: } ! 483: ! 484: if (pascalChars >= 31) ! 485: break; ! 486: ! 487: *(p++) = lsb; ! 488: ++pascalChars; ! 489: --inputChars; ! 490: ! 491: } /* end while */ ! 492: ! 493: hfs_str[0] = pascalChars; ! 494: ! 495: if (inputChars > 0) ! 496: result = kTECOutputBufferFullStatus; /* ran out of room! */ ! 497: ! 498: return result; ! 499: } ! 500: ! 501: ! 502: static UniChar gHiBitBaseUnicode[128] = { ! 503: /* 0x80 */ 0x0041, 0x0041, 0x0043, 0x0045, 0x004e, 0x004f, 0x0055, 0x0061, ! 504: /* 0x88 */ 0x0061, 0x0061, 0x0061, 0x0061, 0x0061, 0x0063, 0x0065, 0x0065, ! 505: /* 0x90 */ 0x0065, 0x0065, 0x0069, 0x0069, 0x0069, 0x0069, 0x006e, 0x006f, ! 506: /* 0x98 */ 0x006f, 0x006f, 0x006f, 0x006f, 0x0075, 0x0075, 0x0075, 0x0075, ! 507: /* 0xa0 */ 0x2020, 0x00b0, 0x00a2, 0x00a3, 0x00a7, 0x2022, 0x00b6, 0x00df, ! 508: /* 0xa8 */ 0x00ae, 0x00a9, 0x2122, 0x00b4, 0x00a8, 0x2260, 0x00c6, 0x00d8, ! 509: /* 0xb0 */ 0x221e, 0x00b1, 0x2264, 0x2265, 0x00a5, 0x00b5, 0x2202, 0x2211, ! 510: /* 0xb8 */ 0x220f, 0x03c0, 0x222b, 0x00aa, 0x00ba, 0x03a9, 0x00e6, 0x00f8, ! 511: /* 0xc0 */ 0x00bf, 0x00a1, 0x00ac, 0x221a, 0x0192, 0x2248, 0x2206, 0x00ab, ! 512: /* 0xc8 */ 0x00bb, 0x2026, 0x00a0, 0x0041, 0x0041, 0x004f, 0x0152, 0x0153, ! 513: /* 0xd0 */ 0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0x00f7, 0x25ca, ! 514: /* 0xd8 */ 0x0079, 0x0059, 0x2044, 0x20ac, 0x2039, 0x203a, 0xfb01, 0xfb02, ! 515: /* 0xe0 */ 0x2021, 0x00b7, 0x201a, 0x201e, 0x2030, 0x0041, 0x0045, 0x0041, ! 516: /* 0xe8 */ 0x0045, 0x0045, 0x0049, 0x0049, 0x0049, 0x0049, 0x004f, 0x004f, ! 517: /* 0xf0 */ 0xf8ff, 0x004f, 0x0055, 0x0055, 0x0055, 0x0131, 0x02c6, 0x02dc, ! 518: /* 0xf8 */ 0x00af, 0x02d8, 0x02d9, 0x02da, 0x00b8, 0x02dd, 0x02db, 0x02c7 ! 519: }; ! 520: ! 521: static UniChar gHiBitCombUnicode[128] = { ! 522: /* 0x80 */ 0x0308, 0x030a, 0x0327, 0x0301, 0x0303, 0x0308, 0x0308, 0x0301, ! 523: /* 0x88 */ 0x0300, 0x0302, 0x0308, 0x0303, 0x030a, 0x0327, 0x0301, 0x0300, ! 524: /* 0x90 */ 0x0302, 0x0308, 0x0301, 0x0300, 0x0302, 0x0308, 0x0303, 0x0301, ! 525: /* 0x98 */ 0x0300, 0x0302, 0x0308, 0x0303, 0x0301, 0x0300, 0x0302, 0x0308, ! 526: /* 0xa0 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, ! 527: /* 0xa8 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, ! 528: /* 0xb0 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, ! 529: /* 0xb8 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, ! 530: /* 0xc0 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, ! 531: /* 0xc8 */ 0x0000, 0x0000, 0x0000, 0x0300, 0x0303, 0x0303, 0x0000, 0x0000, ! 532: /* 0xd0 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, ! 533: /* 0xd8 */ 0x0308, 0x0308, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, ! 534: /* 0xe0 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0302, 0x0302, 0x0301, ! 535: /* 0xe8 */ 0x0308, 0x0300, 0x0301, 0x0302, 0x0308, 0x0300, 0x0301, 0x0302, ! 536: /* 0xf0 */ 0x0000, 0x0300, 0x0301, 0x0302, 0x0300, 0x0000, 0x0000, 0x0000, ! 537: /* 0xf8 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 ! 538: }; ! 539: ! 540: ! 541: /* ! 542: * Convert HFS MacRoman encoded string into Unicode ! 543: * ! 544: * Unicode output is fully decomposed ! 545: */ ! 546: static int mac_roman_to_unicode(Str31 hfs_str, UniChar *uni_str, ! 547: UInt32 maxCharLen, UInt32 *unicodeChars) ! 548: { ! 549: const UInt8 *p; ! 550: UniChar *u; ! 551: UInt16 pascalChars; ! 552: UInt8 c; ! 553: ! 554: p = hfs_str; ! 555: u = uni_str; ! 556: ! 557: *unicodeChars = pascalChars = *(p++); /* pick up length byte */ ! 558: ! 559: while (pascalChars--) { ! 560: c = *(p++); ! 561: ! 562: if ( (SInt8) c >= 0 ) { /* check if seven bit ascii */ ! 563: *(u++) = (UniChar) c; /* just pad high byte with zero */ ! 564: } else { /* its a hi bit character */ ! 565: UniChar uc; ! 566: ! 567: c &= 0x7F; ! 568: *(u++) = uc = gHiBitBaseUnicode[c]; ! 569: ! 570: /* ! 571: * if the unicode character we get back is an alpha char ! 572: * then we must have an additional combining character ! 573: */ ! 574: if ((uc <= (UniChar) 'z') && (uc >= (UniChar) 'A')) { ! 575: *(u++) = gHiBitCombUnicode[c]; ! 576: ++(*unicodeChars); ! 577: } ! 578: } ! 579: } ! 580: ! 581: return noErr; ! 582: } ! 583:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.