~ubuntu-branches/ubuntu/gutsy/lv/gutsy

« back to all changes in this revision

Viewing changes to src/big5.c

  • Committer: Bazaar Package Importer
  • Author(s): GOTO Masanori
  • Date: 2003-11-16 01:21:59 UTC
  • Revision ID: james.westby@ubuntu.com-20031116012159-wpu27qhoxzskmjy0
Tags: upstream-4.50
ImportĀ upstreamĀ versionĀ 4.50

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * big5.c
 
3
 *
 
4
 * All rights reserved. Copyright (C) 1996 by NARITA Tomio.
 
5
 * $Id: big5.c,v 1.5 2003/11/13 03:08:19 nrt Exp $
 
6
 */
 
7
/*
 
8
 * This program is free software; you can redistribute it and/or modify
 
9
 * it under the terms of the GNU General Public License as published by
 
10
 * the Free Software Foundation; either version 2 of the License, or
 
11
 * (at your option) any later version.
 
12
 *
 
13
 * This program is distributed in the hope that it will be useful,
 
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
 * GNU General Public License for more details.
 
17
 *
 
18
 * You should have received a copy of the GNU General Public License
 
19
 * along with this program; if not, write to the Free Software
 
20
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
21
 */
 
22
 
 
23
#include <import.h>
 
24
#include <decode.h>
 
25
#include <escape.h>
 
26
#include <encode.h>
 
27
#include <uty.h>
 
28
#include <unimap.h>
 
29
#include <begin.h>
 
30
#include <big5.h>
 
31
 
 
32
#include <big5cns.map>
 
33
 
 
34
private ic_t BinarySearchRange( codes_t *array, int high, ic_t code )
 
35
{
 
36
  int low, mid, distance, tmp;
 
37
 
 
38
  low = 0;
 
39
  mid = high >> 1;
 
40
 
 
41
  for( ; low <= high ; mid = ( low + high ) >> 1 ){
 
42
    if( ( array[ mid ].code <= code ) && ( array[ mid + 1 ].code > code ) ){
 
43
      if( 0 == array[ mid ].peer )
 
44
        return 0;
 
45
      if( code >= 0xa140U ){
 
46
        /* big5 to cns */
 
47
        tmp = ( ( code & 0xff00 ) - ( array[ mid ].code & 0xff00 ) ) >> 8;
 
48
        high = code & 0x00ff;
 
49
        low = array[ mid ].code & 0x00ff;
 
50
        /*
 
51
         * NOTE: big5 high_byte: 0xa1-0xfe, low_byte: 0x40-0x7e, 0xa1-0xfe
 
52
         *                                 (radicals: 0x00-0x3e, 0x3f-0x9c)
 
53
         *  big5 radix is 0x9d.                     [region_low, region_high]
 
54
         *  We should remember big5 has two different regions (above).
 
55
         *  There is a bias for the distance between these regions.
 
56
         *    0xa1 - 0x7e + bias = 1 (Distance between 0xa1 and 0x7e is 1.)
 
57
         *                  bias = - 0x22.
 
58
         */
 
59
        distance = tmp * 0x9d + high - low +
 
60
          ( high >= 0xa1 ? ( low >= 0xa1 ? 0 : - 0x22 )
 
61
           : ( low >= 0xa1 ? + 0x22 : 0 ) );
 
62
        /*
 
63
         * NOTE: we have to convert the distance into a code point.
 
64
         *       The code point's low_byte is 0x21 plus mod_0x5e.
 
65
         *       In the first, we extract the mod_0x5e of the starting
 
66
         *       code point, subtracting 0x21, and add distance to it.
 
67
         *       Then we calculate again mod_0x5e of them, and restore
 
68
         *       the final codepoint, adding 0x21.
 
69
         */
 
70
        tmp = ( array[ mid ].peer & 0x00ff ) + distance - 0x21;
 
71
        tmp = ( array[ mid ].peer & 0xff00 ) + ( ( tmp / 0x5e ) << 8 )
 
72
          + 0x21 + tmp % 0x5e;
 
73
        return tmp;
 
74
      } else {
 
75
        /* cns to big5 */
 
76
        tmp = ( ( code & 0xff00 ) - ( array[ mid ].code & 0xff00 ) ) >> 8;
 
77
        /*
 
78
         * NOTE: ISO charsets ranges between 0x21-0xfe (94charset).
 
79
         *       Its radix is 0x5e. But there is no distance bias like big5.
 
80
         */
 
81
        distance = tmp * 0x5e
 
82
          + ( (int)( code & 0x00ff ) - (int)( array[ mid ].code & 0x00ff ) );
 
83
        /*
 
84
         * NOTE: Similar to big5 to cns conversion, we extract mod_0x9d and
 
85
         *       restore mod_0x9d into a code point.
 
86
         */
 
87
        low = array[ mid ].peer & 0x00ff;
 
88
        tmp = low + distance - ( low >= 0xa1 ? 0x62 : 0x40 );
 
89
        low = tmp % 0x9d;
 
90
        tmp = ( array[ mid ].peer & 0xff00 ) + ( ( tmp / 0x9d ) << 8 )
 
91
          + ( low > 0x3e ? 0x62 : 0x40 ) + low;
 
92
        return tmp;
 
93
      }
 
94
    } else if( array[ mid ].code > code ){
 
95
      high = mid - 1;
 
96
    } else {
 
97
      low = mid + 1;
 
98
    }
 
99
  }
 
100
 
 
101
  return 0;
 
102
}
 
103
 
 
104
public ic_t BIG5toCNS( ic_t big5, byte *cset )
 
105
{
 
106
  ic_t cns = 0;
 
107
 
 
108
  if( big5 < 0xc940U ){
 
109
    /* level 1 */
 
110
    if( 0 < (cns = BinarySearchRange( big5Level1ToCnsPlane1, 23, big5 )) )
 
111
      *cset = CNS_1;
 
112
  } else if( big5 == 0xc94aU ){
 
113
    /* level 2 */
 
114
    *cset = CNS_1;
 
115
    cns = 0x4442;
 
116
  } else {
 
117
    /* level 2 */
 
118
    if( 0 < (cns = BinarySearchRange( big5Level2ToCnsPlane2, 46, big5 )) )
 
119
      *cset = CNS_2;
 
120
  }
 
121
 
 
122
  if( 0 == cns ){
 
123
    *cset = ASCII;
 
124
    return (ic_t)'?';
 
125
  }
 
126
 
 
127
  return cns;
 
128
}
 
129
 
 
130
public ic_t CNStoBIG5( ic_t cns, byte *cset )
 
131
{
 
132
  unsigned int big5 = 0;
 
133
 
 
134
  switch( *cset ){
 
135
  case CNS_1:
 
136
    big5 = BinarySearchRange( cnsPlane1ToBig5Level1, 24, cns );
 
137
    break;
 
138
  case CNS_2:
 
139
    big5 = BinarySearchRange( cnsPlane2ToBig5Level2, 47, cns );
 
140
    break;
 
141
  }
 
142
 
 
143
  if( 0 == big5 ){
 
144
    *cset = ASCII;
 
145
    return (ic_t)'?';
 
146
  }
 
147
 
 
148
  *cset = BIG5;
 
149
 
 
150
  return big5;
 
151
}
 
152
 
 
153
public void ConvertCNStoBIG5( i_str_t *istr )
 
154
{
 
155
  int i;
 
156
  byte cset;
 
157
 
 
158
  for( i = 0 ; NOSET != istr[ i ].charset ; i++ ){
 
159
    if( CNS_1 == istr[ i ].charset || CNS_2 == istr[ i ].charset ){
 
160
      cset = istr[ i ].charset;
 
161
      istr[ i ].c = CNStoBIG5( istr[ i ].c, &cset );
 
162
      istr[ i ].charset = cset;
 
163
    }
 
164
  }
 
165
}
 
166
 
 
167
public void ConvertBIG5toCNS( i_str_t *istr )
 
168
{
 
169
  int i;
 
170
  byte cset;
 
171
 
 
172
  for( i = 0 ; NOSET != istr[ i ].charset ; i++ ){
 
173
    if( BIG5 == istr[ i ].charset ){
 
174
      cset = istr[ i ].charset;
 
175
      istr[ i ].c = BIG5toCNS( istr[ i ].c, &cset );
 
176
      istr[ i ].charset = cset;
 
177
    }
 
178
  }
 
179
}
 
180
 
 
181
public void DecodeBig5( state_t *state, byte codingSystem )
 
182
{
 
183
  byte charset, ch;
 
184
  byte c[ ICHAR_WIDTH ];
 
185
 
 
186
  for( ; ; ){
 
187
    GetChar( ch );
 
188
    if( ch < SP ){
 
189
      if( ESC == ch ){
 
190
        if( FALSE == DecodeEscape( state ) )
 
191
          break;
 
192
      } else if( HT == ch )
 
193
        DecodeAddTab( state->attr );
 
194
      else if( SO == ch )       /* LS1 for 8bit */
 
195
        state->gset[ GL ] = G1;
 
196
      else if( SI == ch )       /* LS0 for 8bit */
 
197
        state->gset[ GL ] = G0;
 
198
      else if( BS == ch )
 
199
        DecodeAddBs();
 
200
      else
 
201
        DecodeAddControl( ch );
 
202
    } else {
 
203
      if( NULL != state->sset ){
 
204
        if( FALSE == DecodeAddShifted( state, ch ) )
 
205
          break;
 
206
        else
 
207
          continue;
 
208
      } else if( IsBig5Byte1( ch ) ){
 
209
        /*
 
210
         * Big5
 
211
         */
 
212
        charset = BIG5;
 
213
        c[ 0 ] = ch;
 
214
        GetChar( ch );
 
215
        if( !IsBig5Byte2( ch ) ){
 
216
          DecodeAddControl( c[ 0 ] );
 
217
          DecodeAddControl( ch );
 
218
          continue;
 
219
        }
 
220
        c[ 1 ] = ch;
 
221
      } else {
 
222
        /*
 
223
         * iso-2022
 
224
         */
 
225
        charset = CSET( G0 );
 
226
        if( !IsGraphicChar( charset, ch ) ){
 
227
          if( SP == ch ){
 
228
            DecodeAddSpace( state->attr );
 
229
          } else {
 
230
            DecodeAddControl( ch );
 
231
          }
 
232
          continue;
 
233
        }
 
234
        c[ 0 ] = ch;
 
235
        if( TRUE == iTable[ (int)charset ].multi ){
 
236
          GetChar( ch );
 
237
          ch &= 0x7f;
 
238
          if( !IsGraphicChar( charset, ch ) )
 
239
            continue;
 
240
          c[ 1 ] = ch;
 
241
        }
 
242
      }
 
243
      DecodeAddChar( charset, c, state->attr );
 
244
    }
 
245
  }
 
246
}
 
247
 
 
248
public void EncodeBig5( i_str_t *istr, int head, int tail,
 
249
                       byte codingSystem, boolean_t binary )
 
250
{
 
251
  int idx, attr;
 
252
  ic_t ic;
 
253
  byte cset;
 
254
 
 
255
  for( idx = head ; idx < tail ; idx++ ){
 
256
    cset = istr[ idx ].charset;
 
257
    ic = istr[ idx ].c;
 
258
    attr = (int)istr[ idx ].attr << 8;
 
259
    if( CNS_1 == cset || CNS_2 == cset )
 
260
      ic = CNStoBIG5( ic, &cset );
 
261
#ifndef MSDOS /* IF NOT DEFINED */
 
262
    else if( UNICODE == cset )
 
263
      ic = UNItoBIG5( ic, &cset );
 
264
#endif /* MSDOS */
 
265
    if( cset < PSEUDO ){
 
266
      if( ASCII == cset ){
 
267
        EncodeAddChar( attr, ic );
 
268
      } else if( BIG5 == cset ){
 
269
        EncodeAddChar( attr, MakeByte1( ic ) );
 
270
        EncodeAddChar( attr, MakeByte2( ic ) );
 
271
      } else {
 
272
        if( FALSE == EncodeAddInvalid( attr, ic, cset ) )
 
273
          break;
 
274
      }
 
275
    } else if( FALSE == EncodeAddPseudo( attr, ic, cset, binary ) ){
 
276
      break;
 
277
    }
 
278
  }
 
279
}