1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39
40 // Most of the code here was originally written by Serika Kurusugawa
41 // a.k.a. Junji Takagi, and is included in Qt with the author's permission,
42 // and the grateful thanks of the Qt team.
43
44 /*! \class QSjisCodec
45 \inmodule QtCore
46 \reentrant
47 \internal
48 */
49
50 #include "qsjiscodec_p.h"
51 #include "qlist.h"
52
53 QT_BEGIN_NAMESPACE
54
55 enum {
56 Esc = 0x1b
57 };
58
59 #define IsKana(c) (((c) >= 0xa1) && ((c) <= 0xdf))
60 #define IsSjisChar1(c) ((((c) >= 0x81) && ((c) <= 0x9f)) || \
61 (((c) >= 0xe0) && ((c) <= 0xfc)))
62 #define IsSjisChar2(c) (((c) >= 0x40) && ((c) != 0x7f) && ((c) <= 0xfc))
63 #define IsUserDefinedChar1(c) (((c) >= 0xf0) && ((c) <= 0xfc))
64
65 #define QValidChar(u) ((u) ? QChar((ushort)(u)) : QChar(QChar::ReplacementCharacter))
66
67 /*!
68 Creates a Shift-JIS codec. Note that this is done automatically by
69 the QApplication, you do not need construct your own.
70 */
QSjisCodec()71 QSjisCodec::QSjisCodec() : conv(QJpUnicodeConv::newConverter(QJpUnicodeConv::Default))
72 {
73 }
74
75
76 /*!
77 Destroys the Shift-JIS codec.
78 */
~QSjisCodec()79 QSjisCodec::~QSjisCodec()
80 {
81 delete (const QJpUnicodeConv*)conv;
82 conv = 0;
83 }
84
85
convertFromUnicode(const QChar * uc,int len,ConverterState * state) const86 QByteArray QSjisCodec::convertFromUnicode(const QChar *uc, int len, ConverterState *state) const
87 {
88 char replacement = '?';
89 if (state) {
90 if (state->flags & ConvertInvalidToNull)
91 replacement = 0;
92 }
93 int invalid = 0;
94
95 int rlen = 2*len + 1;
96 QByteArray rstr;
97 rstr.resize(rlen);
98 uchar* cursor = (uchar*)rstr.data();
99 for (int i = 0; i < len; i++) {
100 QChar ch = uc[i];
101 uint j;
102 if (ch.row() == 0x00 && ch.cell() < 0x80) {
103 // ASCII
104 *cursor++ = ch.cell();
105 } else if ((j = conv->unicodeToJisx0201(ch.row(), ch.cell())) != 0) {
106 // JIS X 0201 Latin or JIS X 0201 Kana
107 *cursor++ = j;
108 } else if ((j = conv->unicodeToSjis(ch.row(), ch.cell())) != 0) {
109 // JIS X 0208
110 *cursor++ = (j >> 8);
111 *cursor++ = (j & 0xff);
112 } else if ((j = conv->unicodeToSjisibmvdc(ch.row(), ch.cell())) != 0) {
113 // JIS X 0208 IBM VDC
114 *cursor++ = (j >> 8);
115 *cursor++ = (j & 0xff);
116 } else if ((j = conv->unicodeToCp932(ch.row(), ch.cell())) != 0) {
117 // CP932 (for lead bytes 87, ee & ed)
118 *cursor++ = (j >> 8);
119 *cursor++ = (j & 0xff);
120 } else if ((j = conv->unicodeToJisx0212(ch.row(), ch.cell())) != 0) {
121 // JIS X 0212 (can't be encoded in ShiftJIS !)
122 *cursor++ = 0x81; // white square
123 *cursor++ = 0xa0; // white square
124 } else {
125 // Error
126 *cursor++ = replacement;
127 ++invalid;
128 }
129 }
130 rstr.resize(cursor - (const uchar*)rstr.constData());
131
132 if (state) {
133 state->invalidChars += invalid;
134 }
135 return rstr;
136 }
137
convertToUnicode(const char * chars,int len,ConverterState * state) const138 QString QSjisCodec::convertToUnicode(const char* chars, int len, ConverterState *state) const
139 {
140 uchar buf[1] = {0};
141 int nbuf = 0;
142 QChar replacement = QChar::ReplacementCharacter;
143 if (state) {
144 if (state->flags & ConvertInvalidToNull)
145 replacement = QChar::Null;
146 nbuf = state->remainingChars;
147 buf[0] = state->state_data[0];
148 }
149 int invalid = 0;
150 uint u= 0;
151 QString result;
152 for (int i=0; i<len; i++) {
153 uchar ch = chars[i];
154 switch (nbuf) {
155 case 0:
156 if (ch < 0x80) {
157 result += QValidChar(ch);
158 } else if (IsKana(ch)) {
159 // JIS X 0201 Latin or JIS X 0201 Kana
160 u = conv->jisx0201ToUnicode(ch);
161 result += QValidChar(u);
162 } else if (IsSjisChar1(ch)) {
163 // JIS X 0208
164 buf[0] = ch;
165 nbuf = 1;
166 } else {
167 // Invalid
168 result += replacement;
169 ++invalid;
170 }
171 break;
172 case 1:
173 // JIS X 0208
174 if (IsSjisChar2(ch)) {
175 if ((u = conv->sjisibmvdcToUnicode(buf[0], ch))) {
176 result += QValidChar(u);
177 } else if ((u = conv->cp932ToUnicode(buf[0], ch))) {
178 result += QValidChar(u);
179 }
180 else if (IsUserDefinedChar1(buf[0])) {
181 result += QChar::ReplacementCharacter;
182 } else {
183 u = conv->sjisToUnicode(buf[0], ch);
184 result += QValidChar(u);
185 }
186 } else {
187 // Invalid
188 result += replacement;
189 ++invalid;
190 }
191 nbuf = 0;
192 break;
193 }
194 }
195
196 if (state) {
197 state->remainingChars = nbuf;
198 state->state_data[0] = buf[0];
199 state->invalidChars += invalid;
200 }
201 return result;
202 }
203
204
_mibEnum()205 int QSjisCodec::_mibEnum()
206 {
207 return 17;
208 }
209
_name()210 QByteArray QSjisCodec::_name()
211 {
212 return "Shift_JIS";
213 }
214
215 /*!
216 Returns the codec's mime name.
217 */
_aliases()218 QList<QByteArray> QSjisCodec::_aliases()
219 {
220 QList<QByteArray> list;
221 list << "SJIS" // Qt 3 compat
222 << "MS_Kanji";
223 return list;
224 }
225
226 QT_END_NAMESPACE
227