/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/NPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): */ #include "unicpriv.h" /*================================================================================= =================================================================================*/ typedef PRBool (*uSubGeneratorFunc) (PRUint16 in, unsigned char* out); /*================================================================================= =================================================================================*/ typedef PRBool (*uGeneratorFunc) ( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ); MODULE_PRIVATE PRBool uGenerate( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ); #define uSubGennerator(sub,in,out) (* m_subgenerator[sub])((in),(out)) PRIVATE PRBool uCheckAndGenAlways1Byte( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ); PRIVATE PRBool uCheckAndGenAlways2Byte( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ); PRIVATE PRBool uCheckAndGenAlways2ByteShiftGR( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ); PRIVATE PRBool uCheckAndGenByTable( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ); PRIVATE PRBool uCheckAndGen2ByteGRPrefix8F( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ); PRIVATE PRBool uCheckAndGen2ByteGRPrefix8EA2( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ); PRIVATE PRBool uCheckAndGenAlways2ByteSwap( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ); PRIVATE PRBool uCheckAndGenAlways4Byte( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ); PRIVATE PRBool uCheckAndGenAlways4ByteSwap( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ); PRIVATE PRBool uCheckAndGen2ByteGRPrefix8EA3( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ); PRIVATE PRBool uCheckAndGen2ByteGRPrefix8EA4( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ); PRIVATE PRBool uCheckAndGen2ByteGRPrefix8EA5( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ); PRIVATE PRBool uCheckAndGen2ByteGRPrefix8EA6( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ); PRIVATE PRBool uCheckAndGen2ByteGRPrefix8EA7( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ); PRIVATE PRBool uCheckAndGenAlways1ByteShiftGL( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ); PRIVATE PRBool uCnGAlways8BytesComposedHangul( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ); PRIVATE PRBool uCnGAlways8BytesGLComposedHangul( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ); PRIVATE PRBool uGenComposedHangulCommon( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen, PRUint8 mask ); PRIVATE PRBool uGenAlways2Byte( PRUint16 in, unsigned char* out ); PRIVATE PRBool uGenAlways2ByteShiftGR( PRUint16 in, unsigned char* out ); PRIVATE PRBool uGenAlways1Byte( PRUint16 in, unsigned char* out ); PRIVATE PRBool uGenAlways1BytePrefix8E( PRUint16 in, unsigned char* out ); PRIVATE PRBool uGenAlways2ByteUTF8( PRUint16 in, unsigned char* out ); PRIVATE PRBool uGenAlways3ByteUTF8( PRUint16 in, unsigned char* out ); /*================================================================================= =================================================================================*/ PRIVATE uGeneratorFunc m_generator[uNumOfCharsetType] = { uCheckAndGenAlways1Byte, uCheckAndGenAlways2Byte, uCheckAndGenByTable, uCheckAndGenAlways2ByteShiftGR, uCheckAndGen2ByteGRPrefix8F, uCheckAndGen2ByteGRPrefix8EA2, uCheckAndGenAlways2ByteSwap, uCheckAndGenAlways4Byte, uCheckAndGenAlways4ByteSwap, uCheckAndGen2ByteGRPrefix8EA3, uCheckAndGen2ByteGRPrefix8EA4, uCheckAndGen2ByteGRPrefix8EA5, uCheckAndGen2ByteGRPrefix8EA6, uCheckAndGen2ByteGRPrefix8EA7, uCheckAndGenAlways1ByteShiftGL, uCnGAlways8BytesComposedHangul, uCnGAlways8BytesGLComposedHangul }; /*================================================================================= =================================================================================*/ PRIVATE uSubGeneratorFunc m_subgenerator[uNumOfCharType] = { uGenAlways1Byte, uGenAlways2Byte, uGenAlways2ByteShiftGR, uGenAlways1BytePrefix8E, uGenAlways2ByteUTF8, uGenAlways3ByteUTF8 }; /*================================================================================= =================================================================================*/ MODULE_PRIVATE PRBool uGenerate( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ) { return (* m_generator[shift->classID]) (shift,state,in,out,outbuflen,outlen); } /*================================================================================= =================================================================================*/ PRIVATE PRBool uGenAlways1Byte( PRUint16 in, unsigned char* out ) { out[0] = (unsigned char)in; return PR_TRUE; } /*================================================================================= =================================================================================*/ PRIVATE PRBool uGenAlways2Byte( PRUint16 in, unsigned char* out ) { out[0] = (unsigned char)((in >> 8) & 0xff); out[1] = (unsigned char)(in & 0xff); return PR_TRUE; } /*================================================================================= =================================================================================*/ PRIVATE PRBool uGenAlways2ByteShiftGR( PRUint16 in, unsigned char* out ) { out[0] = (unsigned char)(((in >> 8) & 0xff) | 0x80); out[1] = (unsigned char)((in & 0xff) | 0x80); return PR_TRUE; } /*================================================================================= =================================================================================*/ PRIVATE PRBool uGenAlways1BytePrefix8E( PRUint16 in, unsigned char* out ) { out[0] = 0x8E; out[1] = (unsigned char)(in & 0xff); return PR_TRUE; } /*================================================================================= =================================================================================*/ PRIVATE PRBool uGenAlways2ByteUTF8( PRUint16 in, unsigned char* out ) { out[0] = (unsigned char)(0xC0 | (( in >> 6 ) & 0x1F)); out[1] = (unsigned char)(0x80 | (( in ) & 0x3F)); return PR_TRUE; } /*================================================================================= =================================================================================*/ PRIVATE PRBool uGenAlways3ByteUTF8( PRUint16 in, unsigned char* out ) { out[0] = (unsigned char)(0xE0 | (( in >> 12 ) & 0x0F)); out[1] = (unsigned char)(0x80 | (( in >> 6 ) & 0x3F)); out[2] = (unsigned char)(0x80 | (( in ) & 0x3F)); return PR_TRUE; } /*================================================================================= =================================================================================*/ PRIVATE PRBool uCheckAndGenAlways1Byte( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ) { /* Don't check inlen. The caller should ensure it is larger than 0 */ /* Oops, I don't agree. Code changed to check every time. [CATA] */ if(outbuflen < 1) return PR_FALSE; else { *outlen = 1; out[0] = in & 0xff; return PR_TRUE; } } /*================================================================================= =================================================================================*/ PRIVATE PRBool uCheckAndGenAlways2Byte( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ) { if(outbuflen < 2) return PR_FALSE; else { *outlen = 2; out[0] = ((in >> 8 ) & 0xff); out[1] = in & 0xff; return PR_TRUE; } } /*================================================================================= =================================================================================*/ PRIVATE PRBool uCheckAndGenAlways2ByteShiftGR( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ) { if(outbuflen < 2) return PR_FALSE; else { *outlen = 2; out[0] = ((in >> 8 ) & 0xff) | 0x80; out[1] = (in & 0xff) | 0x80; return PR_TRUE; } } /*================================================================================= =================================================================================*/ PRIVATE PRBool uCheckAndGenByTable( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ) { PRInt16 i; uShiftCell* cell = &(shift->shiftcell[0]); PRInt16 itemnum = shift->numOfItem; unsigned char inH, inL; inH = (in >> 8) & 0xff; inL = (in & 0xff ); for(i=0;i= cell[i].shiftout.MinLB) && ( inL <= cell[i].shiftout.MaxLB) && ( inH >= cell[i].shiftout.MinHB) && ( inH <= cell[i].shiftout.MaxHB) ) { if(outbuflen < cell[i].reserveLen) return PR_FALSE; else { *outlen = cell[i].reserveLen; return (uSubGennerator(cell[i].classID,in,out)); } } } return PR_FALSE; } /*================================================================================= =================================================================================*/ PRIVATE PRBool uCheckAndGen2ByteGRPrefix8F( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ) { if(outbuflen < 3) return PR_FALSE; else { *outlen = 3; out[0] = 0x8F; out[1] = ((in >> 8 ) & 0xff) | 0x80; out[2] = (in & 0xff) | 0x80; return PR_TRUE; } } /*================================================================================= =================================================================================*/ PRIVATE PRBool uCheckAndGen2ByteGRPrefix8EA2( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ) { if(outbuflen < 4) return PR_FALSE; else { *outlen = 4; out[0] = 0x8E; out[1] = 0xA2; out[2] = ((in >> 8 ) & 0xff) | 0x80; out[3] = (in & 0xff) | 0x80; return PR_TRUE; } } /*================================================================================= =================================================================================*/ PRIVATE PRBool uCheckAndGenAlways2ByteSwap( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ) { if(outbuflen < 2) return PR_FALSE; else { *outlen = 2; out[0] = in & 0xff; out[1] = ((in >> 8 ) & 0xff); return PR_TRUE; } } /*================================================================================= =================================================================================*/ PRIVATE PRBool uCheckAndGenAlways4Byte( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ) { if(outbuflen < 4) return PR_FALSE; else { *outlen = 4; out[0] = out[1] = 0x00; out[2] = ((in >> 8 ) & 0xff); out[3] = in & 0xff; return PR_TRUE; } } /*================================================================================= =================================================================================*/ PRIVATE PRBool uCheckAndGenAlways4ByteSwap( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ) { if(outbuflen < 4) return PR_FALSE; else { *outlen = 4; out[0] = ((in >> 8 ) & 0xff); out[1] = in & 0xff; out[2] = out[3] = 0x00; return PR_TRUE; } } /*================================================================================= =================================================================================*/ PRIVATE PRBool uCheckAndGen2ByteGRPrefix8EA3( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ) { if(outbuflen < 4) return PR_FALSE; else { *outlen = 4; out[0] = 0x8E; out[1] = 0xA3; out[2] = ((in >> 8 ) & 0xff) | 0x80; out[3] = (in & 0xff) | 0x80; return PR_TRUE; } } /*================================================================================= =================================================================================*/ PRIVATE PRBool uCheckAndGen2ByteGRPrefix8EA4( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ) { if(outbuflen < 4) return PR_FALSE; else { *outlen = 4; out[0] = 0x8E; out[1] = 0xA4; out[2] = ((in >> 8 ) & 0xff) | 0x80; out[3] = (in & 0xff) | 0x80; return PR_TRUE; } } /*================================================================================= =================================================================================*/ PRIVATE PRBool uCheckAndGen2ByteGRPrefix8EA5( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ) { if(outbuflen < 4) return PR_FALSE; else { *outlen = 4; out[0] = 0x8E; out[1] = 0xA5; out[2] = ((in >> 8 ) & 0xff) | 0x80; out[3] = (in & 0xff) | 0x80; return PR_TRUE; } } /*================================================================================= =================================================================================*/ PRIVATE PRBool uCheckAndGen2ByteGRPrefix8EA6( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ) { if(outbuflen < 4) return PR_FALSE; else { *outlen = 4; out[0] = 0x8E; out[1] = 0xA6; out[2] = ((in >> 8 ) & 0xff) | 0x80; out[3] = (in & 0xff) | 0x80; return PR_TRUE; } } /*================================================================================= =================================================================================*/ PRIVATE PRBool uCheckAndGen2ByteGRPrefix8EA7( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ) { if(outbuflen < 4) return PR_FALSE; else { *outlen = 4; out[0] = 0x8E; out[1] = 0xA7; out[2] = ((in >> 8 ) & 0xff) | 0x80; out[3] = (in & 0xff) | 0x80; return PR_TRUE; } } /*================================================================================= =================================================================================*/ PRIVATE PRBool uCheckAndGenAlways1ByteShiftGL( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ) { /* Don't check inlen. The caller should ensure it is larger than 0 */ /* Oops, I don't agree. Code changed to check every time. [CATA] */ if(outbuflen < 1) return PR_FALSE; else { *outlen = 1; out[0] = in & 0x7f; return PR_TRUE; } } #define SBase 0xAC00 #define LCount 19 #define VCount 21 #define TCount 28 #define NCount (VCount * TCount) /*================================================================================= =================================================================================*/ PRIVATE PRBool uGenComposedHangulCommon( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen, PRUint8 mask ) { if(outbuflen < 8) return PR_FALSE; else { static PRUint8 lMap[LCount] = { 0xa1, 0xa2, 0xa4, 0xa7, 0xa8, 0xa9, 0xb1, 0xb2, 0xb3, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe }; static PRUint8 tMap[TCount] = { 0xd4, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xba, 0xbb, 0xbc, 0xbd, 0xbe }; PRUint16 SIndex, LIndex, VIndex, TIndex; /* the following line are copy from Unicode 2.0 page 3-13 */ /* item 1 of Hangul Syllabel Decomposition */ SIndex = in - SBase; /* the following lines are copy from Unicode 2.0 page 3-14 */ /* item 2 of Hangul Syllabel Decomposition w/ modification */ LIndex = SIndex / NCount; VIndex = (SIndex % NCount) / TCount; TIndex = SIndex % TCount; *outlen = 8; out[0] = out[2] = out[4] = out[6] = (0xa4 & mask); out[1] = 0xd4 & mask; out[3] = lMap[LIndex] & mask; out[5] = (VIndex + 0xbf) & mask; out[7] = tMap[TIndex] & mask; return PR_TRUE; } } PRIVATE PRBool uCnGAlways8BytesComposedHangul( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ) { return uGenComposedHangulCommon(shift,state,in,out,outbuflen,outlen,0xff); } PRIVATE PRBool uCnGAlways8BytesGLComposedHangul( uShiftTable *shift, PRInt32* state, PRUint16 in, unsigned char* out, PRUint32 outbuflen, PRUint32* outlen ) { return uGenComposedHangulCommon(shift,state,in,out,outbuflen,outlen,0x7f); }