rtoss - Blame information for rev 124

Subversion Repositories:
Rev:
Rev Author Line No. Line
89 roytam 1 #include "stdafx.h"
2 #include "app.h"
3 #include "textfile.h"
4 #include "ktlarray.h"
5 using namespace ki;
6  
7  
8  
9 //=========================================================================
10 // テキストファイル読み出し共通インタ[フェイス
11 //=========================================================================
12  
13 struct ki::TextFileRPimpl : public Object
14 {
15         inline TextFileRPimpl()
16                 : state(EOL) {}
17  
18         virtual size_t ReadLine( unicode* buf, ulong siz )
19                 = 0;
20  
21         enum { EOF=0, EOL=1, EOB=2 } state;
22 };
23  
24  
25  
26 //-------------------------------------------------------------------------
27 // Unicode系用のベ[スクラス
28 //      UTF-8以外はそんなに出会わないだろうから遅くてもよしとする。
29 //-------------------------------------------------------------------------
30  
31 struct rBasicUTF : public ki::TextFileRPimpl
32 {
33         virtual unicode PeekC() = 0;
34         virtual unicode GetC() {unicode ch=PeekC(); Skip(); return ch;}
35         virtual void Skip() = 0;
36         virtual bool Eof() = 0;
37  
38         size_t ReadLine( unicode* buf, ulong siz )
39         {
40                 state = EOF;
41  
42                 // 改行が出るまで読む
43                 unicode *w=buf, *e=buf+siz;
44                 while( !Eof() )
45                 {
46                         *w = GetC();
47                         if( *w==L'\r' || *w==L'\n' )
48                         {
49                                 state = EOL;
50                                 break;
51                         }
52                         else if( *w!=0xfeff && ++w==e )
53                         {
54                                 state = EOB;
55                                 break;
56                         }
57                 }
58  
59                 // 改行コ[ドスキップ処理
60                 if( state == EOL )
61                         if( *w==L'\r' && !Eof() && PeekC()==L'\n' )
62                                 Skip();
63  
64                 // 読んだ文字数
65                 return w-buf;
66         }
67 };
68  
69  
70  
71 //-------------------------------------------------------------------------
72 // UCS2ベタ/UCS4ベタ。それぞれUTF16, UTF32の代わりとして使う。
73 // ついでに同じtemplateで、ISO-8859-1も処理してしまう。^^;
74 //-------------------------------------------------------------------------
75  
76 template<typename T>
77 struct rUCS : public rBasicUTF
78 {
79         rUCS( const uchar* b, ulong s, bool bigendian )
80                 : fb( reinterpret_cast<const T*>(b) )
81                 , fe( reinterpret_cast<const T*>(b+(s/sizeof(T))*sizeof(T)) )
82                 , be( bigendian ) {}
83  
84         const T *fb, *fe;
85         const bool be;
86  
87         // エンディアン変換
88         inline  byte swap(  byte val ) { return val; }
89         inline dbyte swap( dbyte val ) { return (val<<8) |(val>>8); }
90         inline qbyte swap( qbyte val ) { return ((val>>24)&0xff |
91                                                  (val>>8)&0xff00 |
92                                                                                          (val<<8)&0xff0000|
93                                                                                          (val<<24)); }
94  
95         virtual void Skip() { ++fb; }
96         virtual bool Eof() { return fb==fe; }
97         virtual unicode PeekC() { return (unicode)(be ? swap(*fb) : *fb); }
98 };
99  
100 typedef rUCS< byte> rWest;
101 typedef rUCS<dbyte> rUtf16;
102  
103 // UTF-32読み込み
104 struct rUtf32 : public rUCS<qbyte>
105 {
106         rUtf32( const uchar* b, ulong s, bool bigendian )
107                 : rUCS<qbyte>(b,s,bigendian)
108                 , state(0) {}
109  
110         int state;
111         qbyte curChar() { return be ? swap(*fb) : *fb; }
112         bool inBMP(qbyte c) { return c<0x10000; }
113  
114         virtual unicode PeekC()
115         {
116                 qbyte c = curChar();
117                 if( inBMP(c) )
118                         return (unicode)c;
119                 return (unicode)(state==0 ? 0xD800 + (((c-0x10000) >> 10)&0x3ff)
120                                               : 0xDC00 + ( (c-0x10000)       &0x3ff));
121         }
122  
123         virtual void Skip()
124         {
125                 if( inBMP(curChar()) )
126                         ++fb;
127                 else if( state==0 )
128                         state=1;
129                 else
130                         ++fb, state=0;
131         }
132 };
133  
134  
90 roytam 135 //-------------------------------------------------------------------------
136 // UTF-1
137 //-------------------------------------------------------------------------
138 struct rUtf1 : public rBasicUTF
139 {
140         rUtf1( const uchar* b, ulong s )
141                 : fb( b )
142                 , fe( b+s ) {}
89 roytam 143  
90 roytam 144         const uchar *fb, *fe;
145  
146         inline byte conv( uchar x )
147         {
148                 if( x<=0x20 )      return x + 0xBE;
149                 else if( x<=0x7E ) return x - 0x21;
150                 else if( x<=0x9F ) return x + 0x60;
151                 else               return x - 0x42;
152         }
153  
154         bool Eof() { return fb==fe; }
155         void Skip()
156         {
157                 if( *fb >= 0xFC && *fb <= 0xFF )      { fb+=5; }
158                 else if( *fb >= 0xF6 && *fb <= 0xFB ) { fb+=3; }
159                 else if( *fb >= 0xA0 && *fb <= 0xF5 ) { fb+=2; }
160                 else /*if( *fb <= 0x9F )*/            {  ++fb; }
161         }
162         unicode PeekC()
163         {
164                 if( *fb <= 0x9F )                         { return (unicode)(*fb); }
165                 else if( *fb == 0xA0 )                    { return (unicode)(*(fb+1)); }
166                 else if( *fb >= 0xA1 && *fb <= 0xF5 )     { return (unicode)((*fb-0xA1) * 0xBE + conv(*(fb+1)) + 0x100); }
167                 else if( *fb >= 0xF6 && *fb <= 0xFB )     { return (unicode)((*fb-0xF6) * 0x8D04 + conv(*(fb+1)) * 0xBE + conv(*(fb+2)) + 0x4016); }
168                 else /*if( *fb >= 0xFC && *fb <= 0xFF )*/ { return (unicode)((*fb-0xFC) * 0x4DAD6810 + conv(*(fb+1)) * 0x68A8F8 + conv(*(fb+2)) * 0x8D04 + conv(*(fb+3)) * 0xBE + conv(*(fb+4)) + 0x38E2E); }
169         }
170 };
171  
89 roytam 172 //-------------------------------------------------------------------------
92 roytam 173 // UTF-9 (draft-abela-utf9-00)
174 //-------------------------------------------------------------------------
175 struct rUtf9 : public rBasicUTF
176 {
177         rUtf9( const uchar* b, ulong s )
178                 : fb( b )
179                 , fe( b+s ) {}
180  
181         const uchar *fb, *fe;
182  
183         bool Eof() { return fb==fe; }
184         void Skip()
185         {
186                 if( *fb >= 0x98 && *fb <= 0x9F )      { fb+=5; }
187                 else if( *fb >= 0x94 && *fb <= 0x97 ) { fb+=4; }
188                 else if( *fb >= 0x90 && *fb <= 0x93 ) { fb+=3; }
189                 else if( *fb >= 0x80 && *fb <= 0x8F ) { fb+=2; }
190                 else /* 0~0x7F,0xA0~0xFF */           {  ++fb; }
191         }
192         unicode PeekC()
193         {
194                 if( *fb >= 0x98 && *fb <= 0x9F )      { return (unicode)(((*fb & 0x07) << 28) + ((*(fb+1) & 0x7F) << 21) + ((*(fb+2) & 0x7F) << 14) + ((*(fb+3) & 0x7F) << 7) + (*(fb+4) & 0x7F)); }
195                 else if( *fb >= 0x94 && *fb <= 0x97 ) { return (unicode)(((*fb & 0x03) << 21) + ((*(fb+1) & 0x7F) << 14) + ((*(fb+2) & 0x7F) << 7) + (*(fb+3) & 0x7F)); }
196                 else if( *fb >= 0x90 && *fb <= 0x93 ) { return (unicode)(((*fb & 0x03) << 14) + ((*(fb+1) & 0x7F) << 7) + (*(fb+2) & 0x7F)); }
197                 else if( *fb >= 0x80 && *fb <= 0x8F ) { return (unicode)(((*fb & 0x7F) << 7) + (*(fb+1) & 0x7F)); }
198                 else /* 0~0x7F,0xA0~0xFF */           { return (unicode)(*fb); }
199         }
200 };
201  
202 //-------------------------------------------------------------------------
89 roytam 203 // UTF-5
204 //     0-  F : 1bbbb
205 //    10- FF : 1bbbb 0bbbb
206 //   100-FFF : 1bbbb 0bbbb 0bbbb
207 // というように、16進での一桁を一文字で表していくフォ[マット。
208 // 各 0bbbb は '0', '1', ... '9', 'A', ... 'F'
209 // 各 1bbbb は 'G', 'H', ... 'P', 'Q', ... 'V' の字で表現。
210 //-------------------------------------------------------------------------
211  
212 struct rUtf5 : public rBasicUTF
213 {
214         rUtf5( const uchar* b, ulong s )
215                 : fb( b )
216                 , fe( b+s ) {}
217  
218         const uchar *fb, *fe;
219  
220         // 16進文字から整数値へ変換
221         inline byte conv( uchar x )
222         {
223                 if( '0'<=x && x<='9' ) return x-'0';
224                 else                   return x-'A'+0x0A;
225         }
226  
227         void Skip() { do ++fb; while( fb<fe && *fb<'G' ); }
228         bool Eof() { return fb==fe; }
229         unicode PeekC()
230         {
231                 unicode ch = (*fb-'G');
232                 for( const uchar* p=fb+1; p<fe && *p<'G'; ++p )
233                         ch = (ch<<4)|conv(*p);
234                 return ch;
235         }
236 };
237  
238  
239  
240 //-------------------------------------------------------------------------
241 // UTF-7
242 //   ASCII範囲の字はそのまま。それ以外はUTF-16の値をbase64エンコ[ド
243 //   して出力。エンコ[ドされた部分は + と - で挟まれる。また '+' と
244 //   いう字自体を表現するために "+-" という形式を用いる。
245 //-------------------------------------------------------------------------
246  
247 namespace
248 {
249         static const uchar u7c[128]={
250         0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
251         0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
252         0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3e,0xff,0xff,0xff,0x3f,
253         0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0xff,0xff,0xff,0xff,0xff,0xff,
254         0xff,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
255         0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0xff,0xff,0xff,0xff,0xff,
256         0xff,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,
257         0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0xff,0xff,0xff,0xff,0xff };
258 }
259  
260 struct rUtf7 : public rBasicUTF
261 {
262         rUtf7( const uchar* b, ulong s )
263                 : fb( b )
264                 , fe( b+s )
265                 , rest( -1 ) { fillbuf(); }
266  
267         const uchar *fb, *fe;
268         unicode buf[3]; // b64を8文字毎に読んでバッファに溜めておく
269         int rest;       // バッファの空き
270         bool inB64;     // base64エリア内ならtrue
271  
272         void Skip() { if(--rest==0) fillbuf(); }
273         bool Eof() { return fb==fe && rest==0; }
274         unicode PeekC() { return buf[rest-1]; }
275  
276         void fillbuf()
277         {
278                 if( fb<fe )
279                         if( !inB64 )
280                                 if( *fb=='+' )
281                                         if( fb+1<fe && fb[1]=='-' )
282                                                 rest=1, buf[0]=L'+', fb+=2;  // +-
283                                         else
284                                                 ++fb, inB64=true, fillbuf(); // 単独 +
285                                 else
286                                         rest=1, buf[0]=*fb++;            // 普通の字
287                         else
288                         {
289                                 // 何文字デコ[ドできるか数える
290                                 int N=0, E=Max(int(fb-fe),8);
291                                 while( N<E && fb[N]<0x80 && u7c[fb[N]]!=0xff )
292                                         ++N;
293  
294                                 // デコ[ド
295                                 buf[0]=buf[1]=buf[2]=0;
296                                 switch( N )
297                                 {
298                                 case 8: buf[2]|= u7c[fb[7]];
299                                 case 7: buf[2]|=(u7c[fb[6]]<< 6);
300                                 case 6: buf[2]|=(u7c[fb[5]]<<12), buf[1]|=(u7c[fb[5]]>>4);
301                                 case 5: buf[1]|=(u7c[fb[4]]<< 2);
302                                 case 4: buf[1]|=(u7c[fb[3]]<< 8);
303                                 case 3: buf[1]|=(u7c[fb[2]]<<14), buf[0]|=(u7c[fb[2]]>>2);
304                                 case 2: buf[0]|=(u7c[fb[1]]<< 4);
305                                 case 1: buf[0]|=(u7c[fb[0]]<<10);
306                                         unicode t;
307                                         rest = 1;
308                                         if( N==8 )
309                                                 rest=3, t=buf[0], buf[0]=buf[2], buf[2]=t;
310                                         else if( N>=6 )
311                                                 rest=2, t=buf[0], buf[0]=buf[1], buf[1]=t;
312                                 }
313  
314                                 // 使った分進む
315                                 if( N<E )
316                                 {
317                                         inB64=false;
318                                         if( fb[N]=='-' )
319                                                 ++fb;
320                                 }
321                                 fb += N;
322                                 if( N==0 )
323                                         fillbuf();
324                         }
325         }
326 };
327  
328  
329  
330 //-------------------------------------------------------------------------
331 // UTF8/MBCS
332 //  CR,LFが1バイト文字としてきちんと出てくるので、
333 //  切り分けが簡単な形式をここでまとめて扱う。UTF8以外の変換は
334 //  Windowsに全て任せている。
335 //-------------------------------------------------------------------------
336  
337 namespace
338 {
339         typedef char* (WINAPI * uNextFunc)(WORD,const char*,DWORD);
340  
341         static const byte mask[] = { 0, 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01 };
342         static inline int GetMaskIndex(uchar n)
343         {
344                 if( uchar(n+2) < 0xc2 ) return 1; // 00〜10111111, fe, ff
345                 if( n          < 0xe0 ) return 2; // 110xxxxx
346                 if( n          < 0xf0 ) return 3; // 1110xxxx
347                 if( n          < 0xf8 ) return 4; // 11110xxx
348                 if( n          < 0xfc ) return 5; // 111110xx
349                                         return 6; // 1111110x
350         }
351  
352         static char* WINAPI CharNextUtf8( WORD, const char* p, DWORD )
353         {
354                 return const_cast<char*>( p+GetMaskIndex(uchar(*p)) );
355         }
356  
357         // Win95対策。
358         //   http://support.microsoft.com/default.aspx?scid=%2Fisapi%2Fgomscom%2Easp%3Ftarget%3D%2Fjapan%2Fsupport%2Fkb%2Farticles%2Fjp175%2F3%2F92%2Easp&LN=JA
359         // MSDNにはWin95以降でサポ[トと書いてあるのにCP_UTF8は
360         // 使えないらしいので、自前の変換関数で。
361         typedef int (WINAPI * uConvFunc)(UINT,DWORD,const char*,int,wchar_t*,int);
362         static int WINAPI Utf8ToWideChar( UINT, DWORD, const char* sb, int ss, wchar_t* wb, int ws )
363         {
364                 const uchar *p = reinterpret_cast<const uchar*>(sb);
365                 const uchar *e = reinterpret_cast<const uchar*>(sb+ss);
366                 wchar_t     *w = wb; // バッファサイズチェック無し(仕様)
367  
368                 for( int t; p<e; ++w )
369                 {
370                         t  = GetMaskIndex(*p);
371                         qbyte qch = (*p++ & mask[t]);
372                         while( p<e && --t )
373                                 qch<<=6, qch|=(*p++)&0x3f;
374                         if(qch<0x10000)
375                                 *w = (wchar_t)qch;
376                         else
377                                 *w++ = (wchar_t)(0xD800 + (((qch-0x10000)>>10)&0x3ff)),
378                                 *w   = (wchar_t)(0xDC00 + (((qch-0x10000)    )&0x3ff));
379                 }
380                 return int(w-wb);
381         }
382 }
383  
384 struct rMBCS : public TextFileRPimpl
385 {
386         // ファイルポインタ&コ[ドペ[ジ
387         const char* fb;
388         const char* fe;
389         const int   cp;
390         uNextFunc next;
391         uConvFunc conv;
392  
393         // 初期設定
394         rMBCS( const uchar* b, ulong s, int c )
395                 : fb( reinterpret_cast<const char*>(b) )
396                 , fe( reinterpret_cast<const char*>(b+s) )
397                 , cp( c==UTF8 ? UTF8N : c )
124 roytam 398 #if !defined(TARGET_VER) || (defined(TARGET_VER) && TARGET_VER>310)
89 roytam 399                 , next( cp==UTF8N ?   CharNextUtf8 : CharNextExA )
124 roytam 400 #endif
121 roytam 401                 , conv( cp==UTF8N && (app().isWin95()||!app().isNewShell())
89 roytam 402                                   ? Utf8ToWideChar : MultiByteToWideChar )
403         {
404                 if( cp==UTF8N && fe-fb>=3
405                  && b[0]==0xef && b[1]==0xbb && b[2]==0xbf )
406                         fb += 3; // BOMスキップ
407         }
408  
409         size_t ReadLine( unicode* buf, ulong siz )
410         {
411                 // バッファの終[か、ファイルの終[の近い方まで読み込む
412                 const char *p, *end = Min( fb+siz/2, fe );
413                 state = (end==fe ? EOF : EOB);
414  
415                 // 改行が出るまで進む
416                 for( p=fb; p<end; )
417                         if( *p=='\r' || *p=='\n' )
418                         {
419                                 state = EOL;
420                                 break;
421                         }
124 roytam 422 #if !defined(TARGET_VER) || (defined(TARGET_VER) && TARGET_VER>350)
96 roytam 423                         else if( (*p) & 0x80 && p+1<end )
89 roytam 424                         {
425                                 p = next(cp,p,0);
426                         }
123 roytam 427 #endif
89 roytam 428                         else
429                         {
430                                 ++p;
431                         }
432  
433                 // Unicodeへ変換
121 roytam 434                 ulong len;
89 roytam 435 #ifndef _UNICODE
121 roytam 436                 len = conv( cp, 0, fb, p-fb, buf, siz );
89 roytam 437 #else
121 roytam 438                 if(!app().isNewShell())
439                 {
440                         len = conv( cp, 0, fb, p-fb, buf, siz );
441                 }
442                 else
443                 {
444                         len = ::MultiByteToWideChar( cp, 0, fb, int(p-fb), buf, siz );
445                 }
89 roytam 446 #endif
447                 // 改行コ[ドスキップ処理
448                 if( state == EOL )
449                         if( *(p++)=='\r' && p<fe && *p=='\n' )
450                                 ++p;
451                 fb = p;
452  
453                 // 終了
454                 return len;
455         }
456 };
457  
458  
459  
460 //-------------------------------------------------------------------------
461 // ISO-2022 の適当な実装
462 //
463 //      コ[ドペ[ジとして、G0, G1, G2, G3 の四面を持つ。
464 //      それぞれ決まったエスケ[プシ[ケンスによって、
465 //      さまざまな文字集合を各面に呼び出すことが出来る。
466 //      とりあえず現在のバ[ジョンで対応しているふりなのは
467 //      次の通り。()内に、そのいい加減っぷりを示す。
468 //
469 //              <<いつでも>>
470 //              1B 28 42    : G0へ ASCII
471 //              1B 28 4A    : G0へ JIS X 0201 ロ[マ字 (のかわりにASCII)
472 //              1B 29 4A    : G1へ JIS X 0201 ロ[マ字 (のかわりにASCII)
473 //              1B 2A 4A    : G2へ JIS X 0201 ロ[マ字 (のかわりにASCII)
474 //              1B 3B 4A    : G3へ JIS X 0201 ロ[マ字 (のかわりにASCII)
475 //              1B 2E 41    : G2へ ISO-8859-1
476 //              <<CP932が有効な場合>>
477 //              1B 28 49    : G0へ JIS X 0201 カナ
478 //              1B 29 49    : G1へ JIS X 0201 カナ
479 //              1B 2A 49    : G2へ JIS X 0201 カナ
480 //              1B 2B 49    : G3へ JIS X 0201 カナ
481 //              1B 24 40    : G0へ JIS X 0208(1978)
482 //              1B 24 42    : G0へ JIS X 0208(1983)    (年度は区別しない)
483 //              <<CP936が有効な場合>>
484 //              1B 24 41    : G0へ GB 2312
485 //              1B 24 29 41 : G1へ GB 2312
486 //              1B 24 2A 41 : G2へ GB 2312
487 //              1B 24 2B 41 : G3へ GB 2312
488 //              <<CP949が有効な場合>>
489 //              1B 24 28 43 : G0へ KS X 1001
490 //              1B 24 29 43 : G1へ KS X 1001
491 //              1B 24 2A 43 : G2へ KS X 1001
492 //              1B 24 2B 43 : G3へ KS X 1001
493 //
494 //      各面に呼び出した文字集合は、
495 //              GL (0x21〜0xfe) GR (0xa0〜0xff)
496 //      のどちらかへマップすることで、実際のバイト値となる。
497 //      マップ命令となるバイト列は、次の通り
498 //
499 //              0F    : GL        へG0を呼び出し
500 //              0E    : GL        へG1を呼び出し
501 //              1B 7E : GR        へG1を呼び出し
502 //              8E    : GL/GR両方 へG2を一瞬だけ呼び出し。1B 4E も同義
503 //              8F    : GL/GR両方 へG3を一瞬だけ呼び出し。1B 4F も同義
504 //
505 //-------------------------------------------------------------------------
506  
507 enum CodeSet { ASCII, LATIN, KANA, JIS, KSX, GB };
508  
509 struct rIso2022 : public TextFileRPimpl
510 {
511         // Helper: JIS X 0208 => SJIS
512         void jis2sjis( uchar k, uchar t, char* s )
513         {
514                 if(k>=0x3f)     s[0] = (char)(((k+1)>>1)+0xc0);
515                 else            s[0] = (char)(((k+1)>>1)+0x80);
516                 if( k&1 )       s[1] = (char)((t>>6) ? t+0x40 : t+0x3f);
517                 else            s[1] = (char)(t+0x9e);
518         }
519  
520         // ファイルポインタ
521         const uchar* fb;
522         const uchar* fe;
523         bool      fixed; // ESCによる切り替えを行わないならtrue
524         bool    mode_hz; // HZの場合。
525  
526         // 作業変数
527         CodeSet *GL, *GR, G[4];
528         int gWhat; // 次の字は 1:GL/GR 2:G2 3:G3 で出力
529         ulong len;
530  
531         // 初期化
532         rIso2022( const uchar* b, ulong s, bool f, bool hz,
533                 CodeSet g0, CodeSet g1, CodeSet g2=ASCII, CodeSet g3=ASCII )
534                 : fb( b )
535                 , fe( b+s )
536                 , fixed( f )
537                 , mode_hz( hz )
538                 , GL( &G[0] )
539                 , GR( &G[1] )
540                 , gWhat( 1 )
541         {
542                 G[0]=g0, G[1]=g1, G[2]=g2, G[3]=g3;
543         }
544  
545         void DoSwitching( const uchar*& p )
546         {
547                 if( fixed )
548                 {
549                         if( p[0]==0x24 && p[1]!=0x40 && p[1]!=0x41 && p[1]!=0x42
550                          && p+2 < fe && (p[2]==0x41 || p[2]==0x43) )
551                                 ++p;
552                 }
553                 else
554                 {
555                         if( p[1]==0x4A )
556                                 G[ (p[0]-0x28)%4 ] = ASCII;         // 1B [28-2B] 4A
557                         else if( p[1]==0x49 )
558                                 G[ (p[0]-0x28)%4 ] = KANA;          // 1B [28-2B] 49
559                         else if( *reinterpret_cast<const dbyte*>(p)==0x4228 )
560                                 G[ 0 ] = ASCII;                     // 1B 28 42
561                         else if( *reinterpret_cast<const dbyte*>(p)==0x412E )
562                                 G[ 2 ] = LATIN;                     // 1B 2E 41
563                         else if( p[0]==0x24 )
564                                 if( p[1]==0x40 || p[1]==0x42 )
565                                         G[ 0 ] = JIS;                   // 1B 24 [40|42]
566                                 else if( p[1]==0x41 )
567                                         G[ 0 ] = GB;                    // 1B 24 41
568                                 else if( p+2 < fe )
569                                         if( p[2]==0x41 )
570                                                 G[ ((*++p)-0x28)%4 ] = GB;  // 1B 24 [28-2B] 41
571                                         else if( p[2]==0x43 )
572                                                 G[ ((*++p)-0x28)%4 ] = KSX; // 1B 24 [28-2B] 43
573                 }
574                 ++p;
575         }
576  
577         void DoOutput( unicode*& buf, const uchar*& p )
578         {
579                 // 文字集合取り出し
580                 CodeSet cs =
581                         (gWhat==2 ? G[2] :
582                         (gWhat==3 ? G[3] :
583                         (*p&0x80  ? *GR  : *GL)));
584  
585                 char c[2];
586                 ulong wt=1;
587                 switch( cs )
588                 {
589                 case ASCII:
590                         *buf = (*p)&0x7f;
591                         break;
592                 case LATIN:
593                         *buf = (*p)|0x80;
594                         break;
595                 case KANA:
596                         c[0] = (*p)|0x80;
597                         wt = ::MultiByteToWideChar(
598                                 932, MB_PRECOMPOSED, c, 1, buf, 2 );
599                         break;
600                 case GB:
601                 case KSX:
602                         c[0] = (*  p)|0x80;
603                         c[1] = (*++p)|0x80;
604                         wt = ::MultiByteToWideChar(
605                                 (cs==GB?936:949), MB_PRECOMPOSED, c, 2, buf, 2 );
606                         break;
607                 case JIS:
608                         jis2sjis( (p[0]&0x7f)-0x20, (p[1]&0x7f)-0x20, c );
609                         ++p;
610                         wt = ::MultiByteToWideChar(
611                                 932, MB_PRECOMPOSED, c, 2, buf, 2 );
612                         break;
613                 }
614                 buf+=wt;
615                 len+=wt;
616         }
617  
618         size_t ReadLine( unicode* buf, ulong siz )
619         {
620                 len=0;
621  
622                 // バッファの終[か、ファイルの終[の近い方まで読み込む
623                 const uchar *p, *end = Min( fb+siz/2, fe );
624                 state = (end==fe ? EOF : EOB);
625  
626                 // 改行が出るまで進む
627                 for( p=fb; p<end; ++p )
628                         switch( *p )
629                         {
630                         case '\r':
631                         case '\n': state =   EOL; goto outofloop;
632                         case 0x0F:    GL = &G[0]; break;
633                         case 0x0E:    GL = &G[1]; break;
634                         case 0x8E: gWhat =     2; break;
635                         case 0x8F: gWhat =     3; break;
636                         case 0x1B:
637                                 if( p+1<fe ) {
638                                         ++p; if( *p==0x7E )    GR = &G[1];
639                                         else if( *p==0x4E ) gWhat =  2;
640                                         else if( *p==0x4F ) gWhat =  3;
641                                         else if( p+1<fe )   DoSwitching(p);
642                                 }break;
643                         case 0x7E: if( mode_hz && p+1<fe ) {
644                                         ++p; if( *p==0x7D ){ GL = &G[0]; break; }
645                                         else if( *p==0x7B ){ GL = &G[1]; break; }
646                                 } // fall through...
96 roytam 647                         default:
648                                 if( p+1>=end ) goto outofloop;
649                                 DoOutput( buf, p ); gWhat=1; break;
89 roytam 650                         }
651                 outofloop:
652  
653                 // 改行コ[ドスキップ処理
654                 if( state == EOL )
655                         if( *(p++)=='\r' && p<fe && *p=='\n' )
656                                 ++p;
657                 fb = p;
658  
659                 // 終了
660                 return len;
661         }
662 };
663  
664  
665  
666 //-------------------------------------------------------------------------
667 // 自動判定などなど
668 //-------------------------------------------------------------------------
669  
670 TextFileR::TextFileR( int charset )
671         : cs_( charset )
672         , nolbFound_(true)
673 {
674 }
675  
676 TextFileR::~TextFileR()
677 {
678         Close();
679 }
680  
681 size_t TextFileR::ReadLine( unicode* buf, ulong siz )
682 {
683         return impl_->ReadLine( buf, siz );
684 }
685  
686 int TextFileR::state() const
687 {
688         return impl_->state;
689 }
690  
691 void TextFileR::Close()
692 {
693         fp_.Close();
694 }
695  
696 bool TextFileR::Open( const TCHAR* fname )
697 {
698         // ファイルを開く
699         if( !fp_.Open(fname) )
700                 return false;
701         const uchar* buf = fp_.base();
702         const ulong  siz = fp_.size();
703  
704         // 必要なら自動判定
705         cs_ = AutoDetection( cs_, buf, Min<ulong>(siz,16<<10) ); // 先頭16KB
706  
707         // 対応するデコ[ダを作成
708         switch( cs_ )
709         {
710         case Western: impl_ = new rWest(buf,siz,true); break;
711         case UTF16b:
712         case UTF16BE: impl_ = new rUtf16(buf,siz,true); break;
713         case UTF16l:
714         case UTF16LE: impl_ = new rUtf16(buf,siz,false); break;
715         case UTF32b:
716         case UTF32BE: impl_ = new rUtf32(buf,siz,true); break;
717         case UTF32l:
718         case UTF32LE: impl_ = new rUtf32(buf,siz,false); break;
90 roytam 719         case UTF1:    impl_ = new rUtf1(buf,siz); break;
89 roytam 720         case UTF5:    impl_ = new rUtf5(buf,siz); break;
721         case UTF7:    impl_ = new rUtf7(buf,siz); break;
92 roytam 722         case UTF9:    impl_ = new rUtf9(buf,siz); break;
89 roytam 723         case EucJP:   impl_ = new rIso2022(buf,siz,true,false,ASCII,JIS,KANA); break;
724         case IsoJP:   impl_ = new rIso2022(buf,siz,false,false,ASCII,KANA); break;
725         case IsoKR:   impl_ = new rIso2022(buf,siz,true,false,ASCII,KSX); break;
726         case IsoCN:   impl_ = new rIso2022(buf,siz,true,false,ASCII,GB); break;
727         case HZ:      impl_ = new rIso2022(buf,siz,true,true, ASCII,GB); break;
728         default:      impl_ = new rMBCS(buf,siz,cs_); break;
729         }
730  
731         return true;
732 }
733  
734 int TextFileR::AutoDetection( int cs, const uchar* ptr, ulong siz )
735 {
736 //-- まず、文字の出現回数の統計を取る
737  
738         int  freq[256];
739         bool bit8 = false;
740         mem00( freq, sizeof(freq) );
741         for( ulong i=0; i<siz; ++i )
742         {
743                 if( ptr[i] >= 0x80 )
744                         bit8 = true;
745                 ++freq[ ptr[i] ];
746         }
747  
748 //-- 改行コ[ド決定 (UTF16/32/7のとき問題あり。UTF5に至っては判定不可…)
749  
750              if( freq['\r'] > freq['\n']*2 ) lb_ = CR;
751         else if( freq['\n'] > freq['\r']*2 ) lb_ = LF;
752         else                                 lb_ = CRLF;
753         nolbFound_ = freq['\r']==0 && freq['\n']==0;
754  
755 //-- デフォルトコ[ド
756  
757         int defCs = ::GetACP();
758  
759 //-- 小さすぎる場合はここで終了
760  
761         if( siz <= 4 )
762                 return cs==AutoDetect ? defCs : cs;
763  
764 //-- 明示指定がある場合はここで終了
765  
766         ulong bom4 = (ptr[0]<<24) + (ptr[1]<<16) + (ptr[2]<<8) + (ptr[3]);
767         ulong bom2 = (ptr[0]<<8)  + (ptr[1]);
768  
769         if( cs==UTF8 || cs==UTF8N )
770                 cs = (bom4>>8==0xefbbbf ? UTF8 : UTF8N);
771         else if( cs==UTF32b || cs==UTF32BE )
772                 cs = (bom4==0x0000feff ? UTF32b : UTF32BE);
773         else if( cs==UTF32l || cs==UTF32LE )
774                 cs = (bom4==0xfffe0000 ? UTF32l : UTF32LE);
775         else if( cs==UTF16b || cs==UTF16BE )
776                 cs = (bom2==0xfeff ? UTF16b : UTF16BE);
777         else if( cs==UTF16l || cs==UTF16LE )
778                 cs = (bom2==0xfffe ? UTF16l : UTF16LE);
779  
780         if( cs != AutoDetect )
781                 return cs;
782  
783 //-- BOMチェック・7bitチェック
784  
785         bool Jp = ::IsValidCodePage(932)!=FALSE;
786  
787         if( (bom4>>8) == 0xefbbbf )   cs = UTF8;
788         else if( bom4 == 0x0000feff ) cs = UTF32b;
789         else if( bom4 == 0xfffe0000 ) cs = UTF32l;
790         else if( bom2 == 0xfeff )     cs = UTF16b;
791         else if( bom2 == 0xfffe )     cs = UTF16l;
792         else if( bom4 == 0x1b242943 && ::IsValidCodePage(949) ) cs = IsoKR;
793         else if( bom4 == 0x1b242941 && ::IsValidCodePage(936) ) cs = IsoCN;
794         else if( Jp && !bit8 && freq[0x1b]>0 )                  cs = IsoJP;
795  
796         if( cs != AutoDetect )
797                 return cs;
798  
799 //-- UTF-5 チェック
800  
801         ulong u5sum = 0;
802         for( uchar c='0'; c<='9'; ++c ) u5sum += freq[c];
803         for( uchar c='A'; c<='V'; ++c ) u5sum += freq[c];
804         if( siz == u5sum )
805                 return UTF5;
806  
807 //-- 暫定版 UTF-8 / 日本語EUC チェック
808  
809         cs = defCs;
810  
811         // 改行コ[ドがLFか、ある程度の大きさか、でないと
812         // 無条件で ANSI-CP と見なしてしまう。
813         if( bit8 && (siz>4096 || lb_==1
814          || freq[0xfd]>0 || freq[0xfe]>0 || freq[0xff]>0 || freq[0x80]>0) )
815         {
816                 // UHCやGBKはEUC-JPと非常に混同しやすいので、そっちがデフォルトの場合は
817                 // EUC-JP自動判定を切る
818                 if( Jp && ::GetACP()!=UHC && ::GetACP()!=GBK && ::GetACP()!=Big5 )
819                 {
820                         // EUCとしておかしい値が無いかチェック
821                         bool be=true;
822                         for( int k=0x90; k<=0xa0; ++k )if( freq[k]>0 ){be=false;break;}
823                         for( int k=0x7f; k<=0x8d; ++k )if( freq[k]>0 ){be=false;break;}
824                         if( be )
825                                 return EucJP;
826                 }
827                 {
828                         // UTF8として読めるかどうかチェック
829                         bool b8=true;
830                         int mi=1;
831                         for( ulong i=0; i<siz && b8; ++i )
832                                 if( --mi )
833                                 {
834                                         if( ptr[i]<0x80 || ptr[i]>=0xc0 )
835                                                 b8 = false;
836                                 }
837                                 else
838                                 {
839                                         mi = 1;
840                                         if( ptr[i] > 0x7f )
841                                         {
842                                                 mi = GetMaskIndex( ptr[i] );
843                                                 if( mi == 1 )//ptr[i] >= 0xfe )
844                                                         b8 = false;
845                                         }
846                                 }
847                         if( b8 )
848                                 return UTF8N;
849                 }
850         }
851  
99 roytam 852  
124 roytam 853 #if !defined(TARGET_VER) || (defined(TARGET_VER) && TARGET_VER>310)
100 roytam 854 #ifndef NO_MLANG
99 roytam 855         app().InitModule( App::OLE );
856         IMultiLanguage2 *lang = NULL;
857         if( S_OK == ::CoCreateInstance(CLSID_CMultiLanguage, NULL, CLSCTX_ALL, IID_IMultiLanguage2, (LPVOID*)&lang ) )
858         {
107 roytam 859                 int detectEncCount = 5;
860                 DetectEncodingInfo detectEnc[5];
861                 lang->DetectInputCodepage(MLDETECTCP_DBCS, 0, (char *)(ptr), (INT *)(&siz), detectEnc, &detectEncCount); // 2 ugly C-cast here
99 roytam 862  
107 roytam 863                 // MLang fine tunes
108 roytam 864                 if ( detectEncCount > 1 && detectEnc[0].nCodePage == 1252 ) // sometimes it gives multiple results with 1252 in the first
107 roytam 865                 {
866                         if ( detectEncCount == 2 && detectEnc[1].nCodePage == 850 ) // seems to be wrongly detected
867                         {
868                                 cs = defCs;
869                         }
870                         else
871                         {
872                                 cs =  detectEnc[detectEncCount-1].nCodePage; // always use last one
873                         }
874                 }
875                 else if ( detectEncCount > 1 && detectEnc[0].nCodePage > 950 ) // non asian codepage in first
876                 {
877                         int highestConfidence = 0;
878                         for(int x=0;x<detectEncCount;x++)
879                         {
880                                 if(highestConfidence < detectEnc[x].nConfidence)
881                                 {
882                                         highestConfidence = detectEnc[x].nConfidence; // use codepage with highest Confidence
883                                         cs = detectEnc[x].nCodePage;
884                                 }
885                         }
886                 }
887                 else
888                 {
889                         cs =  detectEnc[0].nCodePage;
890                 }
891  
100 roytam 892 # ifdef MLANG_DEBUG
102 roytam 893                 TCHAR tmp[10];
104 roytam 894                 ::wsprintf(tmp,TEXT("%d"),cs);
101 roytam 895                 ::MessageBox(NULL,tmp,TEXT("MLangDetect"),0);
100 roytam 896 # endif
897  
99 roytam 898                 if (cs == 20127 || !cs) cs = defCs; // 20127 == ASCII, 0 = unknown
899  
900                 if (lang)
901                         lang->Release();
100 roytam 902         }
124 roytam 903 #endif //NO_MLANG
904 #endif //TARGET_VER
99 roytam 905  
89 roytam 906 //-- 判定結果
907  
908         return cs;
909 }
910  
911  
912  
913 //=========================================================================
914 // テキストファイル出力共通インタ[フェイス
915 //=========================================================================
916  
917 struct ki::TextFileWPimpl : public Object
918 {
919         virtual void WriteLine( const unicode* buf, ulong siz )
920                 { while( siz-- ) WriteChar( *buf++ ); }
921  
922         virtual void WriteLB( const unicode* buf, ulong siz )
923                 { WriteLine( buf, siz ); }
924  
925         virtual void WriteChar( unicode ch )
926                 {}
927  
928         ~TextFileWPimpl()
929                 { delete [] buf_; }
930  
931 protected:
932  
933         TextFileWPimpl( FileW& w )
934                 : fp_   (w)
935                 , bsiz_ (65536)
936                 , buf_  (new char[bsiz_]) {}
937  
938         void ReserveMoreBuffer()
939                 {
940                         char* nBuf = new char[bsiz_<<=1];
941                         delete [] buf_;
942                         buf_ = nBuf;
943                 }
944  
945         FileW& fp_;
946         ulong  bsiz_;
947         char*  buf_;
948 };
949  
950  
951  
952 //-------------------------------------------------------------------------
953 // Unicodeテキスト
954 //-------------------------------------------------------------------------
955  
956 struct wUtf16LE : public TextFileWPimpl
957 {
958         wUtf16LE( FileW& w, bool bom ) : TextFileWPimpl(w)
959                 { if(bom){ unicode ch=0xfeff; fp_.Write(&ch,2); } }
960         void WriteLine( const unicode* buf, ulong siz ) {fp_.Write(buf,siz*2);}
961 };
962  
963 struct wUtf16BE : public TextFileWPimpl
964 {
965         wUtf16BE( FileW& w, bool bom ) : TextFileWPimpl(w)
966                 { if(bom) WriteChar(0xfeff); }
967         void WriteChar( unicode ch ) { fp_.WriteC(ch>>8), fp_.WriteC(ch&0xff); }
968 };
969  
970 struct wUtf32LE : public TextFileWPimpl
971 {
972         wUtf32LE( FileW& w, bool bom ) : TextFileWPimpl(w)
973                 { if(bom) {unicode c=0xfeff; WriteLine(&c,1);} }
974 //      void WriteChar( unicode ch )
975 //              { fp_.WriteC(ch&0xff), fp_.WriteC(ch>>8), fp_.WriteC(0), fp_.WriteC(0); }
976         virtual void WriteLine( const unicode* buf, ulong siz )
977         {
978                 while( siz-- )
979                 {
980                         unicode c = *buf++;
981                         qbyte  cc = c;
982                         if( (0xD800<=c && c<=0xDBFF) && siz>0 ) // trail char が正しいかどうかはチェックする気がない
983                         {
984                                 unicode c2 = *buf++; siz--;
985                                 cc = 0x10000 + (((c-0xD800)&0x3ff)<<10) + ((c2-0xDC00)&0x3ff);
986                         }
987                         for(int i=0; i<=3; ++i)
988                                 fp_.WriteC( (uchar)(cc>>(8*i)) );
989                 }
990         }
991 };
992  
993 struct wUtf32BE : public TextFileWPimpl
994 {
995         wUtf32BE( FileW& w, bool bom ) : TextFileWPimpl(w)
996                 { if(bom) {unicode c=0xfeff; WriteLine(&c,1);} }
997 //      void WriteChar( unicode ch )
998 //              { fp_.WriteC(0), fp_.WriteC(0), fp_.WriteC(ch>>8), fp_.WriteC(ch&0xff); }
999         virtual void WriteLine( const unicode* buf, ulong siz )
1000         {
1001                 while( siz-- )
1002                 {
1003                         unicode c = *buf++;
1004                         qbyte  cc = c;
1005                         if( (0xD800<=c && c<=0xDBFF) && siz>0 ) // trail char が正しいかどうかはチェックする気がない
1006                         {
1007                                 unicode c2 = *buf++; siz--;
1008                                 cc = 0x10000 + (((c-0xD800)&0x3ff)<<10) + ((c2-0xDC00)&0x3ff);
1009                         }
1010                         for(int i=3; i>=0; --i)
1011                                 fp_.WriteC( (uchar)(cc>>(8*i)) );
1012                 }
1013         }
1014 };
1015  
1016 struct wWest : public TextFileWPimpl
1017 {
1018         wWest( FileW& w ) : TextFileWPimpl(w) {}
1019         void WriteChar( unicode ch ) { fp_.WriteC(ch>0xff ? '?' : (uchar)ch); }
1020 };
1021  
90 roytam 1022 struct wUtf1 : public TextFileWPimpl
1023 {
1024         wUtf1( FileW& w ) : TextFileWPimpl(w) {}
1025         inline qbyte conv ( qbyte x )
1026         {
1027                 if( x<=0x5D )      return x + 0x21;
1028                 else if( x<=0xBD ) return x + 0x42;
1029                 else if( x<=0xDE ) return x - 0xBE;
1030                 else               return x - 0x60;
1031         }
1032         void WriteChar( unicode ch )
1033         {
1034                 if( ch <= 0x9f )
1035                         fp_.WriteC( static_cast<uchar>(ch) );
1036                 else if( ch <= 0xff )
1037                         fp_.WriteC( 0xA0 ),
1038                         fp_.WriteC( static_cast<uchar>(ch) );
1039                 else if( ch <= 0x4015 )
1040                         fp_.WriteC( static_cast<uchar>(0xA1 + (ch - 0x100) / 0xBE) ),
1041                         fp_.WriteC( static_cast<uchar>(conv((ch - 0x100) % 0xBE)) );
1042                 else if( ch <= 0x38E2D )
1043                         fp_.WriteC( static_cast<uchar>(0xF6 + (ch - 0x4016) / (0xBE*0xBE))  ),
1044                         fp_.WriteC( static_cast<uchar>(conv((ch - 0x4016) / 0xBE % 0xBE)) ),
1045                         fp_.WriteC( static_cast<uchar>(conv((ch - 0x4016) % 0xBE)) );
1046                 else
1047                         fp_.WriteC( static_cast<uchar>(0xFC + (ch - 0x38E2E) / (0xBE*0xBE*0xBE*0xBE))  ),
1048                         fp_.WriteC( static_cast<uchar>(conv((ch - 0x38E2E) / (0xBE*0xBE*0xBE) % 0xBE)) ),
1049                         fp_.WriteC( static_cast<uchar>(conv((ch - 0x38E2E) / (0xBE*0xBE) % 0xBE)) ),
1050                         fp_.WriteC( static_cast<uchar>(conv((ch - 0x38E2E) / 0xBE % 0xBE)) ),
1051                         fp_.WriteC( static_cast<uchar>(conv((ch - 0x38E2E) % 0xBE)) );
1052         }
1053 };
1054  
92 roytam 1055 struct wUtf9 : public TextFileWPimpl
1056 {
1057         wUtf9( FileW& w ) : TextFileWPimpl(w) {}
1058         void WriteChar( unicode ch )
1059         {
1060                 if( ch <= 0x7F || (ch >= 0xA0 && ch <= 0xFF ))
1061                         fp_.WriteC( static_cast<uchar>(ch) );
1062                 else if( ch <= 0x07FF )
1063                         fp_.WriteC( static_cast<uchar>(0x80 | (ch >> 7)) ),
1064                         fp_.WriteC( static_cast<uchar>(0x80 | (ch & 0x7F)) );
1065                 else if( ch <= 0xFFFF )
1066                         fp_.WriteC( static_cast<uchar>(0x90 | (ch >> 14)) ),
1067                         fp_.WriteC( static_cast<uchar>(0x80 | (ch >> 7) & 0x7F) ),
1068                         fp_.WriteC( static_cast<uchar>(0x80 | (ch & 0x7F)) );
1069                 else if( ch <= 0x7FFFFF )
1070                         fp_.WriteC( static_cast<uchar>(0x94 | (ch >> 21)) ),
1071                         fp_.WriteC( static_cast<uchar>(0x80 | (ch >> 14) & 0x7F) ),
1072                         fp_.WriteC( static_cast<uchar>(0x80 | (ch >> 7) & 0x7F) ),
1073                         fp_.WriteC( static_cast<uchar>(0x80 | (ch & 0x7F)) );
1074                 else
1075                         fp_.WriteC( static_cast<uchar>(0x98 | (ch >> 28) & 0x07) ),
1076                         fp_.WriteC( static_cast<uchar>(0x80 | (ch >> 21) & 0x7F) ),
1077                         fp_.WriteC( static_cast<uchar>(0x80 | (ch >> 14) & 0x7F) ),
1078                         fp_.WriteC( static_cast<uchar>(0x80 | (ch >> 7) & 0x7F) ),
1079                         fp_.WriteC( static_cast<uchar>(0x80 | (ch & 0x7F)) );
1080         }
1081 };
1082  
89 roytam 1083 struct wUtf5 : public TextFileWPimpl
1084 {
1085         wUtf5( FileW& w ) : TextFileWPimpl(w) {}
1086         void WriteChar( unicode ch )
1087         {
1088                 static const char conv[] = {
1089                         '0','1','2','3','4','5','6','7',
1090                                 '8','9','A','B','C','D','E','F' };
1091                 if(ch<0x10)
1092                 {
1093                         fp_.WriteC(ch+'G');
1094                 }
1095                 else if(ch<0x100)
1096                 {
1097                         fp_.WriteC((ch>>4)+'G');
1098                         fp_.WriteC(conv[ch&0xf]);
1099                 }
1100                 else if(ch<0x1000)
1101                 {
1102                         fp_.WriteC((ch>>8)+'G');
1103                         fp_.WriteC(conv[(ch>>4)&0xf]);
1104                         fp_.WriteC(conv[ch&0xf]);
1105                 }
1106                 else
1107                 {
1108                         fp_.WriteC((ch>>12)+'G');
1109                         fp_.WriteC(conv[(ch>>8)&0xf]);
1110                         fp_.WriteC(conv[(ch>>4)&0xf]);
1111                         fp_.WriteC(conv[ch&0xf]);
1112                 }
1113         }
1114 };
1115  
1116  
1117  
1118 //-------------------------------------------------------------------------
1119 // Win95対策の自前UTF8/UTF7処理
1120 //-------------------------------------------------------------------------
121 roytam 1121 //#ifndef _UNICODE
89 roytam 1122  
1123 struct wUTF8 : public TextFileWPimpl
1124 {
1125         wUTF8( FileW& w, int cp )
1126                 : TextFileWPimpl(w)
1127         {
1128                 if( cp == UTF8 ) // BOM書き込み
1129                         fp_.Write( "\xEF\xBB\xBF", 3 );
1130         }
1131  
1132         void WriteLine( const unicode* str, ulong len )
1133         {
1134                 //        0000-0000-0xxx-xxxx | 0xxxxxxx
1135                 //        0000-0xxx-xxyy-yyyy | 110xxxxx 10yyyyyy
1136                 //        xxxx-yyyy-yyzz-zzzz | 1110xxxx 10yyyyyy 10zzzzzz
1137                 // x-xxyy-yyyy-zzzz-zzww-wwww | 11110xxx 10yyyyyy 10zzzzzz 10wwwwww
1138                 // ...
1139                 while( len-- )
1140                 {
1141                         qbyte ch = *str;
1142                         if( (0xD800<=ch&&ch<=0xDBFF) && len )
1143                                 ch = 0x10000 + (((ch-0xD800)&0x3ff)<<10) + ((*++str-0xDC00)&0x3ff), len--;
1144  
1145                         if( ch <= 0x7f )
1146                                 fp_.WriteC( static_cast<uchar>(ch) );
1147                         else if( ch <= 0x7ff )
1148                                 fp_.WriteC( 0xc0 | static_cast<uchar>(ch>>6) ),
1149                                 fp_.WriteC( 0x80 | static_cast<uchar>(ch&0x3f) );
1150                         else if( ch<= 0xffff )
1151                                 fp_.WriteC( 0xe0 | static_cast<uchar>(ch>>12) ),
1152                                 fp_.WriteC( 0x80 | static_cast<uchar>((ch>>6)&0x3f) ),
1153                                 fp_.WriteC( 0x80 | static_cast<uchar>(ch&0x3f) );
1154                         else if( ch<= 0x1fffff )
1155                                 fp_.WriteC( 0xf0 | static_cast<uchar>(ch>>18) ),
1156                                 fp_.WriteC( 0x80 | static_cast<uchar>((ch>>12)&0x3f) ),
1157                                 fp_.WriteC( 0x80 | static_cast<uchar>((ch>>6)&0x3f) ),
1158                                 fp_.WriteC( 0x80 | static_cast<uchar>(ch&0x3f) );
1159                         else if( ch<= 0x3ffffff )
1160                                 fp_.WriteC( 0xf8 | static_cast<uchar>(ch>>24) ),
1161                                 fp_.WriteC( 0x80 | static_cast<uchar>((ch>>18)&0x3f) ),
1162                                 fp_.WriteC( 0x80 | static_cast<uchar>((ch>>12)&0x3f) ),
1163                                 fp_.WriteC( 0x80 | static_cast<uchar>((ch>>6)&0x3f) ),
1164                                 fp_.WriteC( 0x80 | static_cast<uchar>(ch&0x3f) );
1165                         else
1166                                 fp_.WriteC( 0xfc | static_cast<uchar>(ch>>30) ),
1167                                 fp_.WriteC( 0x80 | static_cast<uchar>((ch>>24)&0x3f) ),
1168                                 fp_.WriteC( 0x80 | static_cast<uchar>((ch>>18)&0x3f) ),
1169                                 fp_.WriteC( 0x80 | static_cast<uchar>((ch>>12)&0x3f) ),
1170                                 fp_.WriteC( 0x80 | static_cast<uchar>((ch>>6)&0x3f) ),
1171                                 fp_.WriteC( 0x80 | static_cast<uchar>(ch&0x3f) );
1172                         ++str;
1173                 }
1174         }
1175 };
1176  
1177  
1178  
1179 struct wUTF7 : public TextFileWPimpl
1180 {
1181         wUTF7( FileW& w ) : TextFileWPimpl(w) {}
1182  
1183         void WriteLine( const unicode* str, ulong len )
1184         {
1185                 static const uchar mime[64] = {
1186                 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
1187                 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
1188                 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
1189                 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'};
1190  
1191                 // XxxxxxYyyyyyZzzz | zzWwwwwwUuuuuuVv | vvvvTtttttSsssss
1192                 bool mode_m = false;
1193                 while( len )
1194                 {
1195                         if( *str <= 0x7f )
1196                         {
1197                                 fp_.WriteC( static_cast<uchar>(*str) );
1198                                 if( *str == L'+' )
1199                                         fp_.WriteC( '-' );
1200                                 ++str, --len;
1201                         }
1202                         else
1203                         {
1204                                 if(!mode_m) fp_.WriteC( '+' ), mode_m=true;
1205                                 unicode tx[3] = {0,0,0};
1206                                 int n=0;
1207                                 tx[0] = *str, ++str, --len, ++n;
1208                                 if( len && *str>0x7f )
1209                                 {
1210                                         tx[1] = *str, ++str, --len, ++n;
1211                                         if( len && *str>0x7f )
1212                                                 tx[2] = *str, ++str, --len, ++n;
1213                                 }
1214                                 {
1215                                         fp_.WriteC( mime[ tx[0]>>10 ] );
1216                                         fp_.WriteC( mime[ (tx[0]>>4)&0x3f ] );
1217                                         fp_.WriteC( mime[ (tx[0]<<2|tx[1]>>14)&0x3f ] );
1218                                         if( n>=2 )
1219                                         {
1220                                                 fp_.WriteC( mime[ (tx[1]>>8)&0x3f ] );
1221                                                 fp_.WriteC( mime[ (tx[1]>>2)&0x3f ] );
1222                                                 fp_.WriteC( mime[ (tx[1]<<4|tx[2]>>12)&0x3f ] );
1223                                                 if( n>=3 )
1224                                                 {
1225                                                         fp_.WriteC( mime[ (tx[2]>>6)&0x3f ] );
1226                                                         fp_.WriteC( mime[ tx[2]&0x3f ] );
1227                                                 }
1228                                         }
1229                                 }
1230                                 if( len && *str<=0x7f )
1231                                         fp_.WriteC( '-' ), mode_m = false;
1232                         }
1233                 }
1234         }
1235 };
1236  
1237  
1238  
121 roytam 1239 //#endif
89 roytam 1240 //-------------------------------------------------------------------------
1241 // Windows頼りの変換
1242 //-------------------------------------------------------------------------
1243  
1244 struct wMBCS : public TextFileWPimpl
1245 {
1246         wMBCS( FileW& w, int cp )
1247                 : TextFileWPimpl(w), cp_(cp)
1248         {
1249                 if( cp == UTF8 )
1250                 {
1251                         // BOM書き込み
1252                         cp_ = UTF8N;
1253                         fp_.Write( "\xEF\xBB\xBF", 3 );
1254                 }
1255         }
1256  
1257         void WriteLine( const unicode* str, ulong len )
1258         {
1259                 // WideCharToMultiByte API を利用した変換
1260                 int r;
1261                 while(
1262                         0==(r=::WideCharToMultiByte(cp_,0,str,len,buf_,bsiz_,NULL,NULL))
1263                  && ::GetLastError()==ERROR_INSUFFICIENT_BUFFER )
1264                         ReserveMoreBuffer();
1265  
1266                 // ファイルへ書き込み
1267                 fp_.Write( buf_, r );
1268         }
1269  
1270         int cp_;
1271 };
1272  
1273  
1274  
1275 //-------------------------------------------------------------------------
1276 // ISO-2022 サブセットその1。
1277 // ASCIIともう一つしか文字集合を使わないもの
1278 //-------------------------------------------------------------------------
1279  
1280 struct wIso2022 : public TextFileWPimpl
1281 {
1282         wIso2022( FileW& w, int cp )
1283                 : TextFileWPimpl(w), hz_(cp==HZ)
1284         {
1285                 switch( cp )
1286                 {
1287                 case IsoKR:
1288                         fp_.Write( "\x1B\x24\x29\x43", 4 );
1289                         cp_ = UHC;
1290                         break;
1291  
1292                 case IsoCN:
1293                         fp_.Write( "\x1B\x24\x29\x41", 4 );
1294                         // fall through...
1295                 default:
1296                         cp_ = GBK;
1297                         break;
1298                 }
1299         }
1300  
1301         void WriteLine( const unicode* str, ulong len )
1302         {
1303                 // まず WideCharToMultiByte API を利用して変換
1304                 int r;
1305                 while(
1306                         0==(r=::WideCharToMultiByte(cp_,0,str,len,buf_,bsiz_,NULL,NULL))
1307                  && ::GetLastError()==ERROR_INSUFFICIENT_BUFFER )
1308                         ReserveMoreBuffer();
1309  
1310                 bool ascii = true;
1311                 for( int i=0; i<r; ++i )
1312                         if( buf_[i] & 0x80 )
1313                         {
1314                                 // 非ASCII部分は最上位ビットを落としてから出力
1315                                 if( ascii )
1316                                 {
1317                                         if( hz_ )
1318                                                 fp_.WriteC( 0x7E ), fp_.WriteC( 0x7B );
1319                                         else
1320                                                 fp_.WriteC( 0x0E );
1321                                         ascii = false;
1322                                 }
1323                                 fp_.WriteC( buf_[i++] & 0x7F );
1324                                 fp_.WriteC( buf_[i]   & 0x7F );
1325                         }
1326                         else
1327                         {
1328                                 // ASCII部分はそのまま出力
1329                                 if( !ascii )
1330                                 {
1331                                         if( hz_ )
1332                                                 fp_.WriteC( 0x7E ), fp_.WriteC( 0x7D );
1333                                         else
1334                                                 fp_.WriteC( 0x0F );
1335                                         ascii = true;
1336                                 }
1337                                 fp_.WriteC( buf_[i] );
1338  
1339                                 // ただしHZの場合、0x7E は 0x7E 0x7E と表す
1340                                 if( hz_ && buf_[i]==0x7E )
1341                                         fp_.WriteC( 0x7E );
1342                         }
1343  
1344                 // 最後は確実にASCIIに戻す
1345                 if( !ascii )
1346                         if( hz_ )
1347                                 fp_.WriteC( 0x7E ), fp_.WriteC( 0x7D );
1348                         else
1349                                 fp_.WriteC( 0x0F );
1350         }
1351  
1352         int  cp_;
1353         bool hz_;
1354 };
1355  
1356  
1357  
1358  
1359 //-------------------------------------------------------------------------
1360 // ISO-2022 サブセットその2。日本語EUC
1361 //-------------------------------------------------------------------------
1362  
1363 // Helper: SJIS ==> JIS X 0208
1364 static void sjis2jis( uchar s1, uchar s2, char* k )
1365 {
1366         if( ((s1==0xfa || s1==0xfb) && s2>=0x40) || (s1==0xfc && (s2&0xf0)==0x40) )
1367         {
1368                 // IBM外字のマッピング
1369 static const WORD IBM_sjis2kuten[] = {
1370 /*fa40*/0x5c51,0x5c52,0x5c53,0x5c54,0x5c55,0x5c56,0x5c57,0x5c58,0x5c59,0x5c5a,0x0d15,0x0d16,0x0d17,0x0d18,0x0d19,0x0d1a,
1371 /*fa50*/0x0d1b,0x0d1c,0x0d1d,0x0d1e,0x022c,0x5c5c,0x5c5d,0x5c5e,0x0d4a,0x0d42,0x0d44,0x0248,0x5901,0x5902,0x5903,0x5904,
1372 /*fa60*/0x5905,0x5906,0x5907,0x5908,0x5909,0x590a,0x590b,0x590c,0x590d,0x590e,0x590f,0x5910,0x5911,0x5912,0x5913,0x5914,
1373 /*fa70*/0x5915,0x5916,0x5917,0x5918,0x5919,0x591a,0x591b,0x591c,0x591d,0x591e,0x591f,0x5920,0x5921,0x5922,0x5923,/**/0x0109,
1374 /*fa80*/0x5924,0x5925,0x5926,0x5927,0x5928,0x5929,0x592a,0x592b,0x592c,0x592d,0x592e,0x592f,0x5930,0x5931,0x5932,0x5933,
1375 /*fa90*/0x5934,0x5935,0x5936,0x5937,0x5938,0x5939,0x593a,0x593b,0x593c,0x593d,0x593e,0x593f,0x5940,0x5941,0x5942,0x5943,
1376 /*faa0*/0x5944,0x5945,0x5946,0x5947,0x5948,0x5949,0x594a,0x594b,0x594c,0x594d,0x594e,0x594f,0x5950,0x5951,0x5952,0x5953,
1377 /*fab0*/0x5954,0x5955,0x5956,0x5957,0x5958,0x5959,0x595a,0x595b,0x595c,0x595d,0x595e,0x5a01,0x5a02,0x5a03,0x5a04,0x5a05,
1378 /*fac0*/0x5a06,0x5a07,0x5a08,0x5a09,0x5a0a,0x5a0b,0x5a0c,0x5a0d,0x5a0e,0x5a0f,0x5a10,0x5a11,0x5a12,0x5a13,0x5a14,0x5a15,
1379 /*fad0*/0x5a16,0x5a17,0x5a18,0x5a19,0x5a1a,0x5a1b,0x5a1c,0x5a1d,0x5a1e,0x5a1f,0x5a20,0x5a21,0x5a22,0x5a23,0x5a24,0x5a25,
1380 /*fae0*/0x5a26,0x5a27,0x5a28,0x5a29,0x5a2a,0x5a2b,0x5a2c,0x5a2d,0x5a2e,0x5a2f,0x5a30,0x5a31,0x5a32,0x5a33,0x5a34,0x5a35,
1381 /*faf0*/0x5a36,0x5a37,0x5a38,0x5a39,0x5a3a,0x5a3b,0x5a3c,0x5a3d,0x5a3e,0x5a3f,0x5a40,0x5a41,0x5a42,/**/0x0109,0x0109,0x0109,
1382 /*fb40*/0x5a43,0x5a44,0x5a45,0x5a46,0x5a47,0x5a48,0x5a49,0x5a4a,0x5a4b,0x5a4c,0x5a4d,0x5a4e,0x5a4f,0x5a50,0x5a51,0x5a52,
1383 /*fb50*/0x5a53,0x5a54,0x5a55,0x5a56,0x5a57,0x5a58,0x5a59,0x5a5a,0x5a5b,0x5a5c,0x5a5d,0x5a5e,0x5b01,0x5b02,0x5b03,0x5b04,
1384 /*fb60*/0x5b05,0x5b06,0x5b07,0x5b08,0x5b09,0x5b0a,0x5b0b,0x5b0c,0x5b0d,0x5b0e,0x5b0f,0x5b10,0x5b11,0x5b12,0x5b13,0x5b14,
1385 /*fb70*/0x5b15,0x5b16,0x5b17,0x5b18,0x5b19,0x5b1a,0x5b1b,0x5b1c,0x5b1d,0x5b1e,0x5b1f,0x5b20,0x5b21,0x5b22,0x5b23,/**/0x0109,
1386 /*fb80*/0x5b24,0x5b25,0x5b26,0x5b27,0x5b28,0x5b29,0x5b2a,0x5b2b,0x5b2c,0x5b2d,0x5b2e,0x5b2f,0x5b30,0x5b31,0x5b32,0x5b33,
1387 /*fb90*/0x5b34,0x5b35,0x5b36,0x5b37,0x5b38,0x5b39,0x5b3a,0x5b3b,0x5b3c,0x5b3d,0x5b3e,0x5b3f,0x5b40,0x5b41,0x5b42,0x5b43,
1388 /*fba0*/0x5b44,0x5b45,0x5b46,0x5b47,0x5b48,0x5b49,0x5b4a,0x5b4b,0x5b4c,0x5b4d,0x5b4e,0x5b4f,0x5b50,0x5b51,0x5b52,0x5b53,
1389 /*fbb0*/0x5b54,0x5b55,0x5b56,0x5b57,0x5b58,0x5b59,0x5b5a,0x5b5b,0x5b5c,0x5b5d,0x5b5e,0x5c01,0x5c02,0x5c03,0x5c04,0x5c05,
1390 /*fbc0*/0x5c06,0x5c07,0x5c08,0x5c09,0x5c0a,0x5c0b,0x5c0c,0x5c0d,0x5c0e,0x5c0f,0x5c10,0x5c11,0x5c12,0x5c13,0x5c14,0x5c15,
1391 /*fbd0*/0x5c16,0x5c17,0x5c18,0x5c19,0x5c1a,0x5c1b,0x5c1c,0x5c1d,0x5c1e,0x5c1f,0x5c20,0x5c21,0x5c22,0x5c23,0x5c24,0x5c25,
1392 /*fbe0*/0x5c26,0x5c27,0x5c28,0x5c29,0x5c2a,0x5c2b,0x5c2c,0x5c2d,0x5c2e,0x5c2f,0x5c30,0x5c31,0x5c32,0x5c33,0x5c34,0x5c35,
1393 /*fbf0*/0x5c36,0x5c37,0x5c38,0x5c39,0x5c3a,0x5c3b,0x5c3c,0x5c3d,0x5c3e,0x5c3f,0x5c40,0x5c41,0x5c42,/**/0x0109,0x0109,0x0109,
1394 /*fc40*/0x5c43,0x5c44,0x5c45,0x5c46,0x5c47,0x5c48,0x5c49,0x5c4a,0x5c4b,0x5c4c,0x5c4d,0x5c4e,/**/0x0109,0x0109,0x0109,0x0109,
1395 };
1396                 k[0] = IBM_sjis2kuten[ (s1-0xfa)*12*16 + (s2-0x40) ]>>8;
1397                 k[1] = IBM_sjis2kuten[ (s1-0xfa)*12*16 + (s2-0x40) ]&0xff;
1398         }
1399         else
1400         {
1401                 // その他
1402                 if( s2>=0x9f )
1403                 {
1404                         if( s1>=0xe0 ) k[0] = ((s1-0xc0)<<1);
1405                         else           k[0] = ((s1-0x80)<<1);
1406                         k[1] = s2-0x9e;
1407                 }
1408                 else
1409                 {
1410                         if( s1>=0xe0 ) k[0] = ((s1-0xc0)<<1)-1;
1411                         else           k[0] = ((s1-0x80)<<1)-1;
1412  
1413                         if( s2 & 0x80 ) k[1] = s2-0x40;
1414                         else                    k[1] = s2-0x3f;
1415                 }
1416         }
1417  
1418         k[0] += 0x20;
1419         k[1] += 0x20;
1420 }
1421  
1422 struct wEucJp : public TextFileWPimpl
1423 {
1424         wEucJp( FileW& w )
1425                 : TextFileWPimpl(w) {}
1426  
1427         void WriteLine( const unicode* str, ulong len )
1428         {
1429                 // まず WideCharToMultiByte API を利用して変換
1430                 int r;
1431                 while(
1432                         0==(r=::WideCharToMultiByte(932,0,str,len,buf_,bsiz_,NULL,NULL))
1433                  && ::GetLastError()==ERROR_INSUFFICIENT_BUFFER )
1434                         ReserveMoreBuffer();
1435  
1436                 for( int i=0; i<r; ++i )
1437                         if( buf_[i] & 0x80 )
1438                         {
1439                                 if( 0xA1<=(uchar)buf_[i] && (uchar)buf_[i]<=0xDF )
1440                                 {
1441                                         // カナ
1442                                         fp_.WriteC( 0x8E );
1443                                         fp_.WriteC( buf_[i] );
1444                                 }
1445                                 else
1446                                 {
1447                                         // JIS X 0208
1448                                         sjis2jis( buf_[i], buf_[i+1], buf_+i );
1449                                         fp_.WriteC( buf_[i++] | 0x80 );
1450                                         fp_.WriteC( buf_[i]   | 0x80 );
1451                                 }
1452                         }
1453                         else
1454                         {
1455                                 // ASCII部分はそのまま出力
1456                                 fp_.WriteC( buf_[i] );
1457                         }
1458         }
1459 };
1460  
1461  
1462  
1463 //-------------------------------------------------------------------------
1464 // ISO-2022 サブセットその3。ISO-2022-JP
1465 //-------------------------------------------------------------------------
1466  
1467 struct wIsoJp : public TextFileWPimpl
1468 {
1469         wIsoJp( FileW& w )
1470                 : TextFileWPimpl(w)
1471         {
1472                 fp_.Write( "\x1b\x28\x42", 3 );
1473         }
1474  
1475         void WriteLine( const unicode* str, ulong len )
1476         {
1477                 // まず WideCharToMultiByte API を利用して変換
1478                 int r;
1479                 while(
1480                         0==(r=::WideCharToMultiByte(932,0,str,len,buf_,bsiz_,NULL,NULL))
1481                  && ::GetLastError()==ERROR_INSUFFICIENT_BUFFER )
1482                         ReserveMoreBuffer();
1483  
1484                 enum { ROMA, KANJI, KANA } state = ROMA;
1485                 for( int i=0; i<r; ++i )
1486                         if( buf_[i] & 0x80 )
1487                         {
1488                                 if( 0xA1<=(uchar)buf_[i] && (uchar)buf_[i]<=0xDF )
1489                                 {
1490                                         // カナ
1491                                         if( state != KANA )
1492                                                 fp_.Write( "\x1b\x28\x49", 3 ), state = KANA;
1493                                         fp_.WriteC( buf_[i] & 0x7f );
1494                                 }
1495                                 else
1496                                 {
1497                                         // JIS X 0208
1498                                         if( state != KANJI )
1499                                                 fp_.Write( "\x1b\x24\x42", 3 ), state = KANJI;
1500                                         sjis2jis( buf_[i], buf_[i+1], buf_+i );
1501                                         fp_.WriteC( buf_[i++] );
1502                                         fp_.WriteC( buf_[i]   );
1503                                 }
1504                         }
1505                         else
1506                         {
1507                                 // ASCII部分はそのまま出力
1508                                 if( state != ROMA )
1509                                         fp_.Write( "\x1b\x28\x42", 3 ), state = ROMA;
1510                                 fp_.WriteC( buf_[i] );
1511                         }
1512  
1513                 if( state != ROMA )
1514                         fp_.Write( "\x1b\x28\x42", 3 ), state = ROMA;
1515         }
1516 };
1517  
1518  
1519  
1520  
1521 //-------------------------------------------------------------------------
1522 // 書き込みル[チンの準備等々
1523 //-------------------------------------------------------------------------
1524  
1525 TextFileW::TextFileW( int charset, int linebreak )
1526         : cs_( charset ), lb_(linebreak)
1527 {
1528 }
1529  
1530 TextFileW::~TextFileW()
1531 {
1532         Close();
1533 }
1534  
1535 void TextFileW::Close()
1536 {
1537         impl_ = NULL;
1538         fp_.Close();
1539 }
1540  
1541 void TextFileW::WriteLine( const unicode* buf, ulong siz, bool lastline )
1542 {
1543         impl_->WriteLine( buf, siz );
1544         if( !lastline )
1545         {
1546                 static const ulong lbLst[] = {0x0D, 0x0A, 0x000A000D};
1547                 static const ulong lbLen[] = {   1,    1,          2};
1548                 impl_->WriteLB(
1549                         reinterpret_cast<const unicode*>(&lbLst[lb_]), lbLen[lb_] );
1550         }
1551 }
1552  
1553 bool TextFileW::Open( const TCHAR* fname )
1554 {
1555         if( !fp_.Open( fname, true ) )
1556                 return false;
1557  
1558         switch( cs_ )
1559         {
1560         case Western: impl_ = new wWest( fp_ ); break;
90 roytam 1561         case UTF1:    impl_ = new wUtf1( fp_ ); break;
89 roytam 1562         case UTF5:    impl_ = new wUtf5( fp_ ); break;
92 roytam 1563         case UTF9:    impl_ = new wUtf9( fp_ ); break;
89 roytam 1564         case UTF16l:
1565         case UTF16LE: impl_ = new wUtf16LE( fp_, cs_==UTF16l ); break;
1566         case UTF16b:
1567         case UTF16BE: impl_ = new wUtf16BE( fp_, cs_==UTF16b ); break;
1568         case UTF32l:
1569         case UTF32LE: impl_ = new wUtf32LE( fp_, cs_==UTF32l ); break;
1570         case UTF32b:
1571         case UTF32BE: impl_ = new wUtf32BE( fp_, cs_==UTF32b ); break;
1572         case EucJP:   impl_ = new wEucJp( fp_ ); break;
1573         case IsoJP:   impl_ = new wIsoJp( fp_ ); break;
1574         case IsoKR:   impl_ = new wIso2022( fp_, cs_ ); break;
1575         case IsoCN:   impl_ = new wIso2022( fp_, cs_ ); break;
1576         case HZ:      impl_ = new wIso2022( fp_, cs_ ); break;
1577         case UTF8:
1578         case UTF8N:
1579         default:
1580 #ifndef _UNICODE
124 roytam 1581                 if( /*app().isWin95() &&*/ (cs_==UTF8 || cs_==UTF8N) )
89 roytam 1582                         impl_ = new wUTF8( fp_, cs_ );
124 roytam 1583                 else if( /*app().isWin95() &&*/ cs_==UTF7 )
89 roytam 1584                         impl_ = new wUTF7( fp_ );
1585                 else
121 roytam 1586 #else
1587                 if( !app().isNewShell() && (cs_==UTF8 || cs_==UTF8N) )
1588                         impl_ = new wUTF8( fp_, cs_ );
1589                 else if( !app().isNewShell() && cs_==UTF7 )
1590                         impl_ = new wUTF7( fp_ );
1591                 else
89 roytam 1592 #endif
1593                 impl_ = new wMBCS( fp_, cs_ );
1594                 break;
1595         }
1596         return true;
1597 }