|
|
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.