194663Sscottl/*
294663Sscottl * Various routines from the OSTA 2.01 specs.  Copyrights are included with
394663Sscottl * each code segment.  Slight whitespace modifications have been made for
494663Sscottl * formatting purposes.  Typos/bugs have been fixed.
594663Sscottl *
694663Sscottl * $FreeBSD$
794663Sscottl */
894663Sscottl
994663Sscottl#include <fs/udf/osta.h>
1094663Sscottl
1194663Sscottl/*****************************************************************************/
12139776Simp/*-
13139776Simp **********************************************************************
1494663Sscottl * OSTA compliant Unicode compression, uncompression routines.
1594663Sscottl * Copyright 1995 Micro Design International, Inc.
1694663Sscottl * Written by Jason M. Rinn.
1794663Sscottl * Micro Design International gives permission for the free use of the
1894663Sscottl * following source code.
1994663Sscottl */
2094663Sscottl
2194663Sscottl/***********************************************************************
2294663Sscottl * Takes an OSTA CS0 compressed unicode name, and converts
2394663Sscottl * it to Unicode.
2494663Sscottl * The Unicode output will be in the byte order
2594663Sscottl * that the local compiler uses for 16-bit values.
2694663Sscottl * NOTE: This routine only performs error checking on the compID.
2794663Sscottl * It is up to the user to ensure that the unicode buffer is large
2894663Sscottl * enough, and that the compressed unicode name is correct.
2994663Sscottl *
3094663Sscottl * RETURN VALUE
3194663Sscottl *
3294663Sscottl * The number of unicode characters which were uncompressed.
3394663Sscottl * A -1 is returned if the compression ID is invalid.
3494663Sscottl */
3594663Sscottlint
3694663Sscottludf_UncompressUnicode(
3794663Sscottl	int numberOfBytes,	/* (Input) number of bytes read from media. */
3894663Sscottl	byte *UDFCompressed,	/* (Input) bytes read from media. */
3994663Sscottl	unicode_t *unicode)	/* (Output) uncompressed unicode characters. */
4094663Sscottl{
4194663Sscottl	unsigned int compID;
4294663Sscottl	int returnValue, unicodeIndex, byteIndex;
4394663Sscottl
4494663Sscottl	/* Use UDFCompressed to store current byte being read. */
4594663Sscottl	compID = UDFCompressed[0];
4694663Sscottl
4794663Sscottl	/* First check for valid compID. */
4894663Sscottl	if (compID != 8 && compID != 16) {
4994663Sscottl		returnValue = -1;
5094663Sscottl	} else {
5194663Sscottl		unicodeIndex = 0;
5294663Sscottl		byteIndex = 1;
5394663Sscottl
5494663Sscottl		/* Loop through all the bytes. */
5594663Sscottl		while (byteIndex < numberOfBytes) {
5694663Sscottl			if (compID == 16) {
5794663Sscottl				/* Move the first byte to the high bits of the
5894663Sscottl				 * unicode char.
5994663Sscottl				 */
6094663Sscottl				unicode[unicodeIndex] =
6194663Sscottl				    UDFCompressed[byteIndex++] << 8;
6294663Sscottl			} else {
6394663Sscottl				unicode[unicodeIndex] = 0;
6494663Sscottl			}
6594663Sscottl			if (byteIndex < numberOfBytes) {
6694663Sscottl				/*Then the next byte to the low bits. */
6794663Sscottl				unicode[unicodeIndex] |=
6894663Sscottl				    UDFCompressed[byteIndex++];
6994663Sscottl			}
7094663Sscottl			unicodeIndex++;
7194663Sscottl		}
7294663Sscottl		returnValue = unicodeIndex;
7394663Sscottl	}
7494663Sscottl	return(returnValue);
7594663Sscottl}
7694663Sscottl
77122101Sscottl/*
78122101Sscottl * Almost same as udf_UncompressUnicode(). The difference is that
79122101Sscottl * it keeps byte order of unicode string.
80122101Sscottl */
81122101Sscottlint
82122101Sscottludf_UncompressUnicodeByte(
83122101Sscottl	int numberOfBytes,	/* (Input) number of bytes read from media. */
84122101Sscottl	byte *UDFCompressed,	/* (Input) bytes read from media. */
85122101Sscottl	byte *unicode)		/* (Output) uncompressed unicode characters. */
86122101Sscottl{
87122101Sscottl	unsigned int compID;
88122101Sscottl	int returnValue, unicodeIndex, byteIndex;
89122101Sscottl
90122101Sscottl	/* Use UDFCompressed to store current byte being read. */
91122101Sscottl	compID = UDFCompressed[0];
92122101Sscottl
93122101Sscottl	/* First check for valid compID. */
94122101Sscottl	if (compID != 8 && compID != 16) {
95122101Sscottl		returnValue = -1;
96122101Sscottl	} else {
97122101Sscottl		unicodeIndex = 0;
98122101Sscottl		byteIndex = 1;
99122101Sscottl
100122101Sscottl		/* Loop through all the bytes. */
101122101Sscottl		while (byteIndex < numberOfBytes) {
102122101Sscottl			if (compID == 16) {
103122101Sscottl				/* Move the first byte to the high bits of the
104122101Sscottl				 * unicode char.
105122101Sscottl				 */
106122101Sscottl				unicode[unicodeIndex++] =
107122101Sscottl				    UDFCompressed[byteIndex++];
108122101Sscottl			} else {
109122101Sscottl				unicode[unicodeIndex++] = 0;
110122101Sscottl			}
111122101Sscottl			if (byteIndex < numberOfBytes) {
112122101Sscottl				/*Then the next byte to the low bits. */
113122101Sscottl				unicode[unicodeIndex++] =
114122101Sscottl				    UDFCompressed[byteIndex++];
115122101Sscottl			}
116122101Sscottl		}
117122101Sscottl		returnValue = unicodeIndex;
118122101Sscottl	}
119122101Sscottl	return(returnValue);
120122101Sscottl}
121122101Sscottl
12294663Sscottl/***********************************************************************
12394663Sscottl * DESCRIPTION:
12494663Sscottl * Takes a string of unicode wide characters and returns an OSTA CS0
12594663Sscottl * compressed unicode string. The unicode MUST be in the byte order of
12694663Sscottl * the compiler in order to obtain correct results. Returns an error
12794663Sscottl * if the compression ID is invalid.
12894663Sscottl *
12994663Sscottl * NOTE: This routine assumes the implementation already knows, by
13094663Sscottl * the local environment, how many bits are appropriate and
13194663Sscottl * therefore does no checking to test if the input characters fit
13294663Sscottl * into that number of bits or not.
13394663Sscottl *
13494663Sscottl * RETURN VALUE
13594663Sscottl *
13694663Sscottl * The total number of bytes in the compressed OSTA CS0 string,
13794663Sscottl * including the compression ID.
13894663Sscottl * A -1 is returned if the compression ID is invalid.
13994663Sscottl */
14094663Sscottlint
14194663Sscottludf_CompressUnicode(
14294663Sscottl	int numberOfChars,	/* (Input) number of unicode characters. */
14394663Sscottl	int compID,		/* (Input) compression ID to be used. */
14494663Sscottl	unicode_t *unicode,	/* (Input) unicode characters to compress. */
14594663Sscottl	byte *UDFCompressed)	/* (Output) compressed string, as bytes. */
14694663Sscottl{
14794663Sscottl	int byteIndex, unicodeIndex;
14894663Sscottl
14994663Sscottl	if (compID != 8 && compID != 16) {
15094663Sscottl		byteIndex = -1; /* Unsupported compression ID ! */
15194663Sscottl	} else {
15294663Sscottl		/* Place compression code in first byte. */
15394663Sscottl		UDFCompressed[0] = compID;
15494663Sscottl
15594663Sscottl		byteIndex = 1;
15694663Sscottl		unicodeIndex = 0;
15794663Sscottl		while (unicodeIndex < numberOfChars) {
15894663Sscottl			if (compID == 16) {
15994663Sscottl				/* First, place the high bits of the char
16094663Sscottl				 * into the byte stream.
16194663Sscottl				 */
16294663Sscottl				UDFCompressed[byteIndex++] =
16394663Sscottl				    (unicode[unicodeIndex] & 0xFF00) >> 8;
16494663Sscottl			}
16594663Sscottl			/*Then place the low bits into the stream. */
16694663Sscottl			UDFCompressed[byteIndex++] =
16794663Sscottl			    unicode[unicodeIndex] & 0x00FF;
16894663Sscottl			unicodeIndex++;
16994663Sscottl		}
17094663Sscottl	}
17194663Sscottl	return(byteIndex);
17294663Sscottl}
17394663Sscottl
17494663Sscottl/*****************************************************************************/
17594663Sscottl/*
17694663Sscottl * CRC 010041
17794663Sscottl */
17894663Sscottlstatic unsigned short crc_table[256] = {
17994663Sscottl	0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
18094663Sscottl	0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
18194663Sscottl	0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
18294663Sscottl	0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
18394663Sscottl	0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
18494663Sscottl	0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
18594663Sscottl	0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
18694663Sscottl	0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
18794663Sscottl	0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
18894663Sscottl	0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
18994663Sscottl	0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
19094663Sscottl	0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
19194663Sscottl	0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
19294663Sscottl	0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
19394663Sscottl	0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
19494663Sscottl	0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
19594663Sscottl	0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
19694663Sscottl	0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
19794663Sscottl	0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
19894663Sscottl	0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
19994663Sscottl	0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
20094663Sscottl	0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
20194663Sscottl	0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
20294663Sscottl	0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
20394663Sscottl	0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
20494663Sscottl	0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
20594663Sscottl	0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
20694663Sscottl	0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
20794663Sscottl	0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
20894663Sscottl	0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
20994663Sscottl	0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
21094663Sscottl	0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
21194663Sscottl};
21294663Sscottl
21394663Sscottlunsigned short
21494663Sscottludf_cksum(s, n)
21594663Sscottl	unsigned char *s;
21694663Sscottl	int n;
21794663Sscottl{
21894663Sscottl	unsigned short crc=0;
21994663Sscottl
22094663Sscottl	while (n-- > 0)
22194663Sscottl		crc = crc_table[(crc>>8 ^ *s++) & 0xff] ^ (crc<<8);
22294663Sscottl	return crc;
22394663Sscottl}
22494663Sscottl
22594663Sscottl/* UNICODE Checksum */
22694663Sscottlunsigned short
22794663Sscottludf_unicode_cksum(s, n)
22894663Sscottl	unsigned short *s;
22994663Sscottl	int n;
23094663Sscottl{
23194663Sscottl	unsigned short crc=0;
23294663Sscottl
23394663Sscottl	while (n-- > 0) {
23494663Sscottl		/* Take high order byte first--corresponds to a big endian
23594663Sscottl		 * byte stream.
23694663Sscottl		 */
23794663Sscottl		crc = crc_table[(crc>>8 ^ (*s>>8)) & 0xff] ^ (crc<<8);
23894663Sscottl		crc = crc_table[(crc>>8 ^ (*s++ & 0xff)) & 0xff] ^ (crc<<8);
23994663Sscottl	}
24094663Sscottl	return crc;
24194663Sscottl}
24294663Sscottl
24394663Sscottl#ifdef MAIN
24494663Sscottlunsigned char bytes[] = { 0x70, 0x6A, 0x77 };
24594663Sscottl
24694663Sscottlmain()
24794663Sscottl{
24894663Sscottl	unsigned short x;
24994663Sscottl	x = cksum(bytes, sizeof bytes);
25094663Sscottl	printf("checksum: calculated=%4.4x, correct=%4.4x\en", x, 0x3299);
25194663Sscottl	exit(0);
25294663Sscottl}
25394663Sscottl#endif
25494663Sscottl
25594663Sscottl/*****************************************************************************/
25694663Sscottl#ifdef NEEDS_ISPRINT
257139776Simp/*-
258139776Simp **********************************************************************
25994663Sscottl * OSTA UDF compliant file name translation routine for OS/2,
26094663Sscottl * Windows 95, Windows NT, Macintosh and UNIX.
26194663Sscottl * Copyright 1995 Micro Design International, Inc.
26294663Sscottl * Written by Jason M. Rinn.
26394663Sscottl * Micro Design International gives permission for the free use of the
26494663Sscottl * following source code.
26594663Sscottl */
26694663Sscottl
26794663Sscottl/***********************************************************************
26894663Sscottl * To use these routines with different operating systems.
26994663Sscottl *
27094663Sscottl * OS/2
27194663Sscottl * Define OS2
27294663Sscottl * Define MAXLEN = 254
27394663Sscottl *
27494663Sscottl * Windows 95
27594663Sscottl * Define WIN_95
27694663Sscottl * Define MAXLEN = 255
27794663Sscottl *
27894663Sscottl * Windows NT
27994663Sscottl * Define WIN_NT
28094663Sscottl * Define MAXLEN = 255
28194663Sscottl *
28294663Sscottl * Macintosh:
283193571Srwatson * Define APPLE_MAC.
28494663Sscottl * Define MAXLEN = 31.
28594663Sscottl *
28694663Sscottl * UNIX
28794663Sscottl * Define UNIX.
28894663Sscottl * Define MAXLEN as specified by unix version.
28994663Sscottl */
29094663Sscottl
29194663Sscottl#define	ILLEGAL_CHAR_MARK	0x005F
29294663Sscottl#define	CRC_MARK	0x0023
29394663Sscottl#define	EXT_SIZE	5
29494663Sscottl#define	TRUE	1
29594663Sscottl#define	FALSE	0
29694663Sscottl#define	PERIOD	0x002E
29794663Sscottl#define	SPACE	0x0020
29894663Sscottl
29994663Sscottl/*** PROTOTYPES ***/
30094663Sscottlint IsIllegal(unicode_t ch);
30194663Sscottl
30294663Sscottl/* Define a function or macro which determines if a Unicode character is
30394663Sscottl * printable under your implementation.
30494663Sscottl */
30594663Sscottlint UnicodeIsPrint(unicode_t);
30694663Sscottl
30794663Sscottl/***********************************************************************
30894663Sscottl * Translates a long file name to one using a MAXLEN and an illegal
30994663Sscottl * char set in accord with the OSTA requirements. Assumes the name has
31094663Sscottl * already been translated to Unicode.
31194663Sscottl *
31294663Sscottl * RETURN VALUE
31394663Sscottl *
31494663Sscottl * Number of unicode characters in translated name.
31594663Sscottl */
31694663Sscottlint UDFTransName(
31794663Sscottl	unicode_t *newName,	/* (Output)Translated name. Must be of length
31894663Sscottl				 * MAXLEN */
31994663Sscottl	unicode_t *udfName,	/* (Input) Name from UDF volume.*/
32094663Sscottl	int udfLen)		/* (Input) Length of UDF Name. */
32194663Sscottl{
32294663Sscottl	int index, newIndex = 0, needsCRC = FALSE;
32394663Sscottl	int extIndex = 0, newExtIndex = 0, hasExt = FALSE;
32494663Sscottl#if defined OS2 || defined WIN_95 || defined WIN_NT
32594663Sscottl	int trailIndex = 0;
32694663Sscottl#endif
32794663Sscottl	unsigned short valueCRC;
32894663Sscottl	unicode_t current;
32994663Sscottl	const char hexChar[] = "0123456789ABCDEF";
33094663Sscottl
33194663Sscottl	for (index = 0; index < udfLen; index++) {
33294663Sscottl		current = udfName[index];
33394663Sscottl
33494663Sscottl		if (IsIllegal(current) || !UnicodeIsPrint(current)) {
33594663Sscottl			needsCRC = TRUE;
33694663Sscottl			/* Replace Illegal and non-displayable chars with
33794663Sscottl			 * underscore.
33894663Sscottl			 */
33994663Sscottl			current = ILLEGAL_CHAR_MARK;
34094663Sscottl			/* Skip any other illegal or non-displayable
34194663Sscottl			 * characters.
34294663Sscottl			 */
34394663Sscottl			while(index+1 < udfLen && (IsIllegal(udfName[index+1])
34494663Sscottl			    || !UnicodeIsPrint(udfName[index+1]))) {
34594663Sscottl				index++;
34694663Sscottl			}
34794663Sscottl		}
34894663Sscottl
34994663Sscottl		/* Record position of extension, if one is found. */
35094663Sscottl		if (current == PERIOD && (udfLen - index -1) <= EXT_SIZE) {
35194663Sscottl			if (udfLen == index + 1) {
35294663Sscottl				/* A trailing period is NOT an extension. */
35394663Sscottl				hasExt = FALSE;
35494663Sscottl			} else {
35594663Sscottl				hasExt = TRUE;
35694663Sscottl				extIndex = index;
35794663Sscottl				newExtIndex = newIndex;
35894663Sscottl			}
35994663Sscottl		}
36094663Sscottl
36194663Sscottl#if defined OS2 || defined WIN_95 || defined WIN_NT
36294663Sscottl		/* Record position of last char which is NOT period or space. */
36394663Sscottl		else if (current != PERIOD && current != SPACE) {
36494663Sscottl			trailIndex = newIndex;
36594663Sscottl		}
36694663Sscottl#endif
36794663Sscottl
36894663Sscottl		if (newIndex < MAXLEN) {
36994663Sscottl			newName[newIndex++] = current;
37094663Sscottl		} else {
37194663Sscottl			needsCRC = TRUE;
37294663Sscottl		}
37394663Sscottl	}
37494663Sscottl
37594663Sscottl#if defined OS2 || defined WIN_95 || defined WIN_NT
37694663Sscottl	/* For OS2, 95 & NT, truncate any trailing periods and\or spaces. */
37794663Sscottl	if (trailIndex != newIndex - 1) {
37894663Sscottl		newIndex = trailIndex + 1;
37994663Sscottl		needsCRC = TRUE;
38094663Sscottl		hasExt = FALSE; /* Trailing period does not make an
38194663Sscottl				 * extension. */
38294663Sscottl	}
38394663Sscottl#endif
38494663Sscottl
38594663Sscottl	if (needsCRC) {
38694663Sscottl		unicode_t ext[EXT_SIZE];
38794663Sscottl		int localExtIndex = 0;
38894663Sscottl		if (hasExt) {
38994663Sscottl			int maxFilenameLen;
39094663Sscottl			/* Translate extension, and store it in ext. */
39194663Sscottl			for(index = 0; index<EXT_SIZE &&
39294663Sscottl			    extIndex + index +1 < udfLen; index++ ) {
39394663Sscottl				current = udfName[extIndex + index + 1];
39494663Sscottl				if (IsIllegal(current) ||
39594663Sscottl				    !UnicodeIsPrint(current)) {
39694663Sscottl					needsCRC = 1;
39794663Sscottl					/* Replace Illegal and non-displayable
39894663Sscottl					 * chars with underscore.
39994663Sscottl					 */
40094663Sscottl					current = ILLEGAL_CHAR_MARK;
40194663Sscottl					/* Skip any other illegal or
40294663Sscottl					 * non-displayable characters.
40394663Sscottl					 */
40494663Sscottl					while(index + 1 < EXT_SIZE
40594663Sscottl					    && (IsIllegal(udfName[extIndex +
40694663Sscottl					    index + 2]) ||
40794663Sscottl					    !isprint(udfName[extIndex +
40894663Sscottl					    index + 2]))) {
40994663Sscottl						index++;
41094663Sscottl					}
41194663Sscottl				}
41294663Sscottl				ext[localExtIndex++] = current;
41394663Sscottl			}
41494663Sscottl
41594663Sscottl			/* Truncate filename to leave room for extension and
41694663Sscottl			 * CRC.
41794663Sscottl			 */
41894663Sscottl			maxFilenameLen = ((MAXLEN - 5) - localExtIndex - 1);
41994663Sscottl			if (newIndex > maxFilenameLen) {
42094663Sscottl				newIndex = maxFilenameLen;
42194663Sscottl			} else {
42294663Sscottl				newIndex = newExtIndex;
42394663Sscottl			}
42494663Sscottl		} else if (newIndex > MAXLEN - 5) {
42594663Sscottl			/*If no extension, make sure to leave room for CRC. */
42694663Sscottl			newIndex = MAXLEN - 5;
42794663Sscottl		}
42894663Sscottl		newName[newIndex++] = CRC_MARK; /* Add mark for CRC. */
42994663Sscottl
43094663Sscottl		/*Calculate CRC from original filename from FileIdentifier. */
43194663Sscottl		valueCRC = udf_unicode_cksum(udfName, udfLen);
43294663Sscottl		/* Convert 16-bits of CRC to hex characters. */
43394663Sscottl		newName[newIndex++] = hexChar[(valueCRC & 0xf000) >> 12];
43494663Sscottl		newName[newIndex++] = hexChar[(valueCRC & 0x0f00) >> 8];
43594663Sscottl		newName[newIndex++] = hexChar[(valueCRC & 0x00f0) >> 4];
43694663Sscottl		newName[newIndex++] = hexChar[(valueCRC & 0x000f)];
43794663Sscottl
43894663Sscottl		/* Place a translated extension at end, if found. */
43994663Sscottl		if (hasExt) {
44094663Sscottl			newName[newIndex++] = PERIOD;
44194663Sscottl			for (index = 0;index < localExtIndex ;index++ ) {
44294663Sscottl				newName[newIndex++] = ext[index];
44394663Sscottl			}
44494663Sscottl		}
44594663Sscottl	}
44694663Sscottl	return(newIndex);
44794663Sscottl}
44894663Sscottl
44994663Sscottl#if defined OS2 || defined WIN_95 || defined WIN_NT
45094663Sscottl/***********************************************************************
45194663Sscottl * Decides if a Unicode character matches one of a list
45294663Sscottl * of ASCII characters.
45394663Sscottl * Used by OS2 version of IsIllegal for readability, since all of the
45494663Sscottl * illegal characters above 0x0020 are in the ASCII subset of Unicode.
45594663Sscottl * Works very similarly to the standard C function strchr().
45694663Sscottl *
45794663Sscottl * RETURN VALUE
45894663Sscottl *
45994663Sscottl * Non-zero if the Unicode character is in the given ASCII string.
46094663Sscottl */
46194663Sscottlint UnicodeInString(
46294663Sscottl	unsigned char *string,	/* (Input) String to search through. */
46394663Sscottl	unicode_t ch)		/* (Input) Unicode char to search for. */
46494663Sscottl{
46594663Sscottl	int found = FALSE;
46694663Sscottl	while (*string != '\0' && found == FALSE) {
46794663Sscottl		/* These types should compare, since both are unsigned
46894663Sscottl		 * numbers. */
46994663Sscottl		if (*string == ch) {
47094663Sscottl			found = TRUE;
47194663Sscottl		}
47294663Sscottl		string++;
47394663Sscottl	}
47494663Sscottl	return(found);
47594663Sscottl}
47694663Sscottl#endif /* OS2 */
47794663Sscottl
47894663Sscottl/***********************************************************************
47994663Sscottl * Decides whether the given character is illegal for a given OS.
48094663Sscottl *
48194663Sscottl * RETURN VALUE
48294663Sscottl *
48394663Sscottl * Non-zero if char is illegal.
48494663Sscottl */
48594663Sscottlint IsIllegal(unicode_t ch)
48694663Sscottl{
487193571Srwatson#ifdef APPLE_MAC
48894663Sscottl	/* Only illegal character on the MAC is the colon. */
48994663Sscottl	if (ch == 0x003A) {
49094663Sscottl		return(1);
49194663Sscottl	} else {
49294663Sscottl		return(0);
49394663Sscottl	}
49494663Sscottl
49594663Sscottl#elif defined UNIX
49694663Sscottl	/* Illegal UNIX characters are NULL and slash. */
49794663Sscottl	if (ch == 0x0000 || ch == 0x002F) {
49894663Sscottl		return(1);
49994663Sscottl	} else {
50094663Sscottl		return(0);
50194663Sscottl	}
50294663Sscottl
50394663Sscottl#elif defined OS2 || defined WIN_95 || defined WIN_NT
50494663Sscottl	/* Illegal char's for OS/2 according to WARP toolkit. */
50594663Sscottl	if (ch < 0x0020 || UnicodeInString("\\/:*?\"<>|", ch)) {
50694663Sscottl		return(1);
50794663Sscottl	} else {
50894663Sscottl		return(0);
50994663Sscottl	}
51094663Sscottl#endif
51194663Sscottl}
51294663Sscottl#endif
513