]> git.tdb.fi Git - libs/core.git/blob - source/iso2022jp.cpp
Initial upload
[libs/core.git] / source / iso2022jp.cpp
1 #include "ascii.h"
2 #include "iso2022jp.h"
3 #include "jisx0201.h"
4 #include "jisx0208.h"
5
6 using namespace std;
7
8 namespace Msp {
9
10 void Iso2022Jp::Encoder::encode_char(wchar_t c)
11 {
12         if(c>=0 && c<=0x7F && c!=0x5C && c!=0x7E)
13         {
14                 if(mode!=ASCII && mode!=JISX0201)
15                         switch_mode(ASCII);
16                 append(c);
17         }
18         else if(c==0x5C || c==0x7E)
19         {
20                 if(mode!=ASCII)
21                         switch_mode(ASCII);
22                 append(c);
23         }
24         else if(c==0xA5 || c==0x203E)
25         {
26                 if(mode!=JISX0201)
27                         switch_mode(JISX0201);
28                 if(c==0xA5)
29                         append(0x5C);
30                 else if(c==0x203E)
31                         append(0x7E);
32         }
33         else
34         {
35                 unsigned short jis=ucs_to_jisx0208(c);
36                 if(!jis)
37                         throw CodecError("Can't express character in ISO-2022-JP");
38                 if(mode!=JISX0208)
39                         switch_mode(JISX0208);
40         }
41 }
42
43 void Iso2022Jp::Encoder::switch_mode(Mode m)
44 {
45         mode=m;
46         switch(mode)
47         {
48         case ASCII:    append("\033(B", 3); break;
49         case JISX0201: append("\033(J", 3); break;
50         case JISX0208: append("\033$B", 3); break;
51         }
52 }
53
54 Iso2022Jp::Decoder::Decoder():
55         mode(ASCII),
56         dec(new Ascii::Decoder),
57         escape(0)
58 { }
59
60 void Iso2022Jp::Decoder::decode_char(const string &str, string::const_iterator &i)
61 {
62         while(i!=str.end())
63         {
64                 if(escape)
65                 {
66                         escape=escape<<8 | (unsigned char)*i;
67                         if(*i>='@' && *i<='Z')
68                         {
69                                 switch(escape)
70                                 {
71                                 case 0x1B2842: switch_mode(ASCII); break;    // ESC ( B
72                                 case 0x1B284A: switch_mode(JISX0201); break; // ESC ( J
73                                 case 0x1B2440:                               // ESC $ @
74                                 case 0x1B2442: switch_mode(JISX0208); break; // ESC $ B
75                                 default: throw CodecError("Invalid ISO-2022-JP escape sequence");
76                                 }
77                                 escape=0;
78                         }
79                         ++i;
80                 }
81                 else if(*i==0x1B)
82                 {
83                         escape=0x1B;
84                         ++i;
85                 }
86                 else
87                 {
88                         dec->decode_char(str, i);
89                         break;
90                 }
91         }
92 }
93
94 void Iso2022Jp::Decoder::sync()
95 {
96         if(escape)
97                 throw CodecError("Sync in middle of ISO-2022-JP escape sequence");
98         if(mode!=ASCII)
99                 throw CodecError("Sync while not in ASCII mode");
100         append(dec->get());
101         dec->flush();
102 }
103
104 void Iso2022Jp::Decoder::switch_mode(Mode m)
105 {
106         append(dec->get());
107         delete dec;
108
109         mode=m;
110         switch(mode)
111         {
112         case ASCII: dec=new Ascii::Decoder; break;
113         case JISX0201: dec=new JisX0201::Decoder; break;
114         case JISX0208: dec=new JisX0208::Decoder; break;
115         }
116 }
117
118 } // namespace Msp