Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "sal/config.h"
21 :
22 : #include "rtl/textcvt.h"
23 : #include "sal/types.h"
24 :
25 : #include "context.hxx"
26 : #include "converter.hxx"
27 : #include "convertiso2022cn.hxx"
28 : #include "tenchelp.hxx"
29 : #include "unichars.hxx"
30 :
31 : namespace {
32 :
33 : enum ImplIso2022CnToUnicodeState // order is important:
34 : {
35 : IMPL_ISO_2022_CN_TO_UNICODE_STATE_ASCII,
36 : IMPL_ISO_2022_CN_TO_UNICODE_STATE_SO,
37 : IMPL_ISO_2022_CN_TO_UNICODE_STATE_SO_2,
38 : IMPL_ISO_2022_CN_TO_UNICODE_STATE_116432,
39 : IMPL_ISO_2022_CN_TO_UNICODE_STATE_116432_2,
40 : IMPL_ISO_2022_CN_TO_UNICODE_STATE_ESC,
41 : IMPL_ISO_2022_CN_TO_UNICODE_STATE_ESC_DOLLAR,
42 : IMPL_ISO_2022_CN_TO_UNICODE_STATE_ESC_DOLLAR_RPAREN,
43 : IMPL_ISO_2022_CN_TO_UNICODE_STATE_ESC_DOLLAR_ASTERISK
44 : };
45 :
46 : struct ImplIso2022CnToUnicodeContext
47 : {
48 : ImplIso2022CnToUnicodeState m_eState;
49 : sal_uInt32 m_nRow;
50 : bool m_bSo;
51 : bool m_b116431;
52 : };
53 :
54 : enum ImplUnicodeToIso2022CnDesignator
55 : {
56 : IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_NONE,
57 : IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_2312,
58 : IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_116431
59 : };
60 :
61 : struct ImplUnicodeToIso2022CnContext
62 : {
63 : sal_Unicode m_nHighSurrogate;
64 : ImplUnicodeToIso2022CnDesignator m_eSoDesignator;
65 : bool m_b116432Designator;
66 : bool m_bSo;
67 : };
68 :
69 : }
70 :
71 8 : void * ImplCreateIso2022CnToUnicodeContext()
72 : {
73 : ImplIso2022CnToUnicodeContext * pContext =
74 8 : new ImplIso2022CnToUnicodeContext;
75 8 : pContext->m_eState = IMPL_ISO_2022_CN_TO_UNICODE_STATE_ASCII;
76 8 : pContext->m_bSo = false;
77 8 : pContext->m_b116431 = false;
78 8 : return pContext;
79 : }
80 :
81 0 : void ImplResetIso2022CnToUnicodeContext(void * pContext)
82 : {
83 0 : if (pContext)
84 : {
85 : static_cast< ImplIso2022CnToUnicodeContext * >(pContext)->m_eState
86 0 : = IMPL_ISO_2022_CN_TO_UNICODE_STATE_ASCII;
87 0 : static_cast< ImplIso2022CnToUnicodeContext * >(pContext)->m_bSo = false;
88 0 : static_cast< ImplIso2022CnToUnicodeContext * >(pContext)->m_b116431 = false;
89 : }
90 0 : }
91 :
92 8 : void ImplDestroyIso2022CnToUnicodeContext(void * pContext)
93 : {
94 8 : delete static_cast< ImplIso2022CnToUnicodeContext * >(pContext);
95 8 : }
96 :
97 148 : sal_Size ImplConvertIso2022CnToUnicode(void const * pData,
98 : void * pContext,
99 : char const * pSrcBuf,
100 : sal_Size nSrcBytes,
101 : sal_Unicode * pDestBuf,
102 : sal_Size nDestChars,
103 : sal_uInt32 nFlags,
104 : sal_uInt32 * pInfo,
105 : sal_Size * pSrcCvtBytes)
106 : {
107 : ImplDBCSToUniLeadTab const * pGb2312Data
108 : = static_cast< ImplIso2022CnConverterData const * >(pData)->
109 148 : m_pGb2312ToUnicodeData;
110 : sal_uInt16 const * pCns116431992Data
111 : = static_cast< ImplIso2022CnConverterData const * >(pData)->
112 148 : m_pCns116431992ToUnicodeData;
113 : sal_Int32 const * pCns116431992RowOffsets
114 : = static_cast< ImplIso2022CnConverterData const * >(pData)->
115 148 : m_pCns116431992ToUnicodeRowOffsets;
116 : sal_Int32 const * pCns116431992PlaneOffsets
117 : = static_cast< ImplIso2022CnConverterData const * >(pData)->
118 148 : m_pCns116431992ToUnicodePlaneOffsets;
119 : ImplIso2022CnToUnicodeState eState
120 148 : = IMPL_ISO_2022_CN_TO_UNICODE_STATE_ASCII;
121 148 : sal_uInt32 nRow = 0;
122 148 : bool bSo = false;
123 148 : bool b116431 = false;
124 148 : sal_uInt32 nInfo = 0;
125 148 : sal_Size nConverted = 0;
126 148 : sal_Unicode * pDestBufPtr = pDestBuf;
127 148 : sal_Unicode * pDestBufEnd = pDestBuf + nDestChars;
128 :
129 148 : if (pContext)
130 : {
131 148 : eState = static_cast< ImplIso2022CnToUnicodeContext * >(pContext)->m_eState;
132 148 : nRow = static_cast< ImplIso2022CnToUnicodeContext * >(pContext)->m_nRow;
133 148 : bSo = static_cast< ImplIso2022CnToUnicodeContext * >(pContext)->m_bSo;
134 148 : b116431 = static_cast< ImplIso2022CnToUnicodeContext * >(pContext)->m_b116431;
135 : }
136 :
137 428 : for (; nConverted < nSrcBytes; ++nConverted)
138 : {
139 280 : bool bUndefined = true;
140 280 : sal_uInt32 nChar = *(unsigned char const *) pSrcBuf++;
141 : sal_uInt32 nPlane;
142 280 : switch (eState)
143 : {
144 : case IMPL_ISO_2022_CN_TO_UNICODE_STATE_ASCII:
145 104 : if (nChar == 0x0E) // SO
146 : {
147 16 : bSo = true;
148 16 : eState = IMPL_ISO_2022_CN_TO_UNICODE_STATE_SO;
149 : }
150 88 : else if (nChar == 0x1B) // ESC
151 16 : eState = IMPL_ISO_2022_CN_TO_UNICODE_STATE_ESC;
152 72 : else if (nChar < 0x80)
153 72 : if (pDestBufPtr != pDestBufEnd)
154 72 : *pDestBufPtr++ = (sal_Unicode) nChar;
155 : else
156 0 : goto no_output;
157 : else
158 : {
159 0 : bUndefined = false;
160 0 : goto bad_input;
161 : }
162 104 : break;
163 :
164 : case IMPL_ISO_2022_CN_TO_UNICODE_STATE_SO:
165 56 : if (nChar == 0x0F) // SI
166 : {
167 16 : bSo = false;
168 16 : eState = IMPL_ISO_2022_CN_TO_UNICODE_STATE_ASCII;
169 : }
170 40 : else if (nChar == 0x1B) // ESC
171 16 : eState = IMPL_ISO_2022_CN_TO_UNICODE_STATE_ESC;
172 24 : else if (nChar >= 0x21 && nChar <= 0x7E)
173 : {
174 24 : nRow = nChar;
175 24 : eState = IMPL_ISO_2022_CN_TO_UNICODE_STATE_SO_2;
176 : }
177 : else
178 : {
179 0 : bUndefined = false;
180 0 : goto bad_input;
181 : }
182 56 : break;
183 :
184 : case IMPL_ISO_2022_CN_TO_UNICODE_STATE_SO_2:
185 24 : if (nChar >= 0x21 && nChar <= 0x7E)
186 24 : if (b116431)
187 : {
188 8 : nPlane = 0;
189 8 : goto transform;
190 : }
191 : else
192 : {
193 16 : sal_uInt16 nUnicode = 0;
194 : sal_uInt32 nFirst;
195 16 : nRow += 0x80;
196 16 : nChar += 0x80;
197 16 : nFirst = pGb2312Data[nRow].mnTrailStart;
198 16 : if (nChar >= nFirst
199 16 : && nChar <= pGb2312Data[nRow].mnTrailEnd)
200 16 : nUnicode = pGb2312Data[nRow].
201 16 : mpToUniTrailTab[nChar - nFirst];
202 16 : if (nUnicode != 0)
203 16 : if (pDestBufPtr != pDestBufEnd)
204 : {
205 16 : *pDestBufPtr++ = (sal_Unicode) nUnicode;
206 16 : eState = IMPL_ISO_2022_CN_TO_UNICODE_STATE_SO;
207 : }
208 : else
209 0 : goto no_output;
210 : else
211 0 : goto bad_input;
212 16 : }
213 : else
214 : {
215 0 : bUndefined = false;
216 0 : goto bad_input;
217 : }
218 16 : break;
219 :
220 : case IMPL_ISO_2022_CN_TO_UNICODE_STATE_116432:
221 8 : if (nChar >= 0x21 && nChar <= 0x7E)
222 : {
223 8 : nRow = nChar;
224 8 : eState = IMPL_ISO_2022_CN_TO_UNICODE_STATE_116432_2;
225 : }
226 : else
227 : {
228 0 : bUndefined = false;
229 0 : goto bad_input;
230 : }
231 8 : break;
232 :
233 : case IMPL_ISO_2022_CN_TO_UNICODE_STATE_116432_2:
234 8 : if (nChar >= 0x21 && nChar <= 0x7E)
235 : {
236 8 : nPlane = 1;
237 8 : goto transform;
238 : }
239 : else
240 : {
241 0 : bUndefined = false;
242 0 : goto bad_input;
243 : }
244 : break;
245 :
246 : case IMPL_ISO_2022_CN_TO_UNICODE_STATE_ESC:
247 32 : if (nChar == 0x24) // $
248 24 : eState = IMPL_ISO_2022_CN_TO_UNICODE_STATE_ESC_DOLLAR;
249 8 : else if (nChar == 0x4E) // N
250 8 : eState = IMPL_ISO_2022_CN_TO_UNICODE_STATE_116432;
251 : else
252 : {
253 0 : bUndefined = false;
254 0 : goto bad_input;
255 : }
256 32 : break;
257 :
258 : case IMPL_ISO_2022_CN_TO_UNICODE_STATE_ESC_DOLLAR:
259 24 : if (nChar == 0x29) // )
260 16 : eState = IMPL_ISO_2022_CN_TO_UNICODE_STATE_ESC_DOLLAR_RPAREN;
261 8 : else if (nChar == 0x2A) // *
262 : eState
263 8 : = IMPL_ISO_2022_CN_TO_UNICODE_STATE_ESC_DOLLAR_ASTERISK;
264 : else
265 : {
266 0 : bUndefined = false;
267 0 : goto bad_input;
268 : }
269 24 : break;
270 :
271 : case IMPL_ISO_2022_CN_TO_UNICODE_STATE_ESC_DOLLAR_RPAREN:
272 16 : if (nChar == 0x41) // A
273 : {
274 12 : b116431 = false;
275 : eState = bSo ? IMPL_ISO_2022_CN_TO_UNICODE_STATE_SO :
276 12 : IMPL_ISO_2022_CN_TO_UNICODE_STATE_ASCII;
277 : }
278 4 : else if (nChar == 0x47) // G
279 : {
280 4 : b116431 = true;
281 : eState = bSo ? IMPL_ISO_2022_CN_TO_UNICODE_STATE_SO :
282 4 : IMPL_ISO_2022_CN_TO_UNICODE_STATE_ASCII;
283 : }
284 : else
285 : {
286 0 : bUndefined = false;
287 0 : goto bad_input;
288 : }
289 16 : break;
290 :
291 : case IMPL_ISO_2022_CN_TO_UNICODE_STATE_ESC_DOLLAR_ASTERISK:
292 8 : if (nChar == 0x48) // H
293 : eState = bSo ? IMPL_ISO_2022_CN_TO_UNICODE_STATE_SO :
294 8 : IMPL_ISO_2022_CN_TO_UNICODE_STATE_ASCII;
295 : else
296 : {
297 0 : bUndefined = false;
298 0 : goto bad_input;
299 : }
300 8 : break;
301 : }
302 264 : continue;
303 :
304 : transform:
305 : {
306 16 : sal_Int32 nPlaneOffset = pCns116431992PlaneOffsets[nPlane];
307 16 : if (nPlaneOffset == -1)
308 0 : goto bad_input;
309 : else
310 : {
311 : sal_Int32 nOffset
312 16 : = pCns116431992RowOffsets[nPlaneOffset + (nRow - 0x21)];
313 16 : if (nOffset == -1)
314 0 : goto bad_input;
315 : else
316 : {
317 16 : sal_uInt32 nFirstLast = pCns116431992Data[nOffset++];
318 16 : sal_uInt32 nFirst = nFirstLast & 0xFF;
319 16 : sal_uInt32 nLast = nFirstLast >> 8;
320 16 : nChar -= 0x20;
321 16 : if (nChar >= nFirst && nChar <= nLast)
322 : {
323 : sal_uInt32 nUnicode
324 16 : = pCns116431992Data[nOffset + (nChar - nFirst)];
325 16 : if (nUnicode == 0xFFFF)
326 0 : goto bad_input;
327 16 : else if (ImplIsHighSurrogate(nUnicode))
328 0 : if (pDestBufEnd - pDestBufPtr >= 2)
329 : {
330 0 : nOffset += nLast - nFirst + 1;
331 0 : nFirst = pCns116431992Data[nOffset++];
332 0 : *pDestBufPtr++ = (sal_Unicode) nUnicode;
333 : *pDestBufPtr++
334 : = (sal_Unicode)
335 : pCns116431992Data[
336 0 : nOffset + (nChar - nFirst)];
337 : }
338 : else
339 0 : goto no_output;
340 : else
341 16 : if (pDestBufPtr != pDestBufEnd)
342 16 : *pDestBufPtr++ = (sal_Unicode) nUnicode;
343 : else
344 0 : goto no_output;
345 : }
346 : else
347 : goto bad_input;
348 : eState = bSo ? IMPL_ISO_2022_CN_TO_UNICODE_STATE_SO :
349 16 : IMPL_ISO_2022_CN_TO_UNICODE_STATE_ASCII;
350 : }
351 : }
352 16 : continue;
353 : }
354 :
355 : bad_input:
356 0 : switch (sal::detail::textenc::handleBadInputTextToUnicodeConversion(
357 : bUndefined, true, 0, nFlags, &pDestBufPtr, pDestBufEnd,
358 0 : &nInfo))
359 : {
360 : case sal::detail::textenc::BAD_INPUT_STOP:
361 0 : eState = IMPL_ISO_2022_CN_TO_UNICODE_STATE_ASCII;
362 0 : b116431 = false;
363 0 : break;
364 :
365 : case sal::detail::textenc::BAD_INPUT_CONTINUE:
366 0 : eState = IMPL_ISO_2022_CN_TO_UNICODE_STATE_ASCII;
367 0 : b116431 = false;
368 0 : continue;
369 :
370 : case sal::detail::textenc::BAD_INPUT_NO_OUTPUT:
371 0 : goto no_output;
372 : }
373 0 : break;
374 :
375 : no_output:
376 0 : --pSrcBuf;
377 0 : nInfo |= RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL;
378 0 : break;
379 : }
380 :
381 148 : if (eState > IMPL_ISO_2022_CN_TO_UNICODE_STATE_SO
382 60 : && (nInfo & (RTL_TEXTTOUNICODE_INFO_ERROR
383 : | RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL))
384 : == 0)
385 : {
386 60 : if ((nFlags & RTL_TEXTTOUNICODE_FLAGS_FLUSH) == 0)
387 60 : nInfo |= RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL;
388 : else
389 0 : switch (sal::detail::textenc::handleBadInputTextToUnicodeConversion(
390 : false, true, 0, nFlags, &pDestBufPtr, pDestBufEnd,
391 0 : &nInfo))
392 : {
393 : case sal::detail::textenc::BAD_INPUT_STOP:
394 : case sal::detail::textenc::BAD_INPUT_CONTINUE:
395 0 : eState = IMPL_ISO_2022_CN_TO_UNICODE_STATE_ASCII;
396 0 : b116431 = false;
397 0 : break;
398 :
399 : case sal::detail::textenc::BAD_INPUT_NO_OUTPUT:
400 0 : nInfo |= RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL;
401 0 : break;
402 : }
403 : }
404 :
405 148 : if (pContext)
406 : {
407 148 : static_cast< ImplIso2022CnToUnicodeContext * >(pContext)->m_eState = eState;
408 148 : static_cast< ImplIso2022CnToUnicodeContext * >(pContext)->m_nRow = nRow;
409 148 : static_cast< ImplIso2022CnToUnicodeContext * >(pContext)->m_bSo = bSo;
410 148 : static_cast< ImplIso2022CnToUnicodeContext * >(pContext)->m_b116431 = b116431;
411 : }
412 148 : if (pInfo)
413 148 : *pInfo = nInfo;
414 148 : if (pSrcCvtBytes)
415 148 : *pSrcCvtBytes = nConverted;
416 :
417 148 : return pDestBufPtr - pDestBuf;
418 : }
419 :
420 2 : void * ImplCreateUnicodeToIso2022CnContext(void)
421 : {
422 : ImplUnicodeToIso2022CnContext * pContext =
423 2 : new ImplUnicodeToIso2022CnContext;
424 2 : pContext->m_nHighSurrogate = 0;
425 2 : pContext->m_eSoDesignator = IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_NONE;
426 2 : pContext->m_b116432Designator = false;
427 2 : pContext->m_bSo = false;
428 2 : return pContext;
429 : }
430 :
431 0 : void ImplResetUnicodeToIso2022CnContext(void * pContext)
432 : {
433 0 : if (pContext)
434 : {
435 0 : static_cast< ImplUnicodeToIso2022CnContext * >(pContext)->m_nHighSurrogate = 0;
436 : static_cast< ImplUnicodeToIso2022CnContext * >(pContext)->m_eSoDesignator
437 0 : = IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_NONE;
438 : static_cast< ImplUnicodeToIso2022CnContext * >(pContext)->m_b116432Designator
439 0 : = false;
440 0 : static_cast< ImplUnicodeToIso2022CnContext * >(pContext)->m_bSo = false;
441 : }
442 0 : }
443 :
444 2 : void ImplDestroyUnicodeToIso2022CnContext(void * pContext)
445 : {
446 2 : delete static_cast< ImplUnicodeToIso2022CnContext * >(pContext);
447 2 : }
448 :
449 8 : static sal_uInt32 ImplIso2022CnTranslateTo2312(ImplUniToDBCSHighTab const *
450 : pGb2312Data,
451 : sal_uInt32 nChar)
452 : {
453 8 : sal_uInt32 nIndex1 = nChar >> 8;
454 8 : if (nIndex1 < 0x100)
455 : {
456 8 : sal_uInt32 nIndex2 = nChar & 0xFF;
457 8 : sal_uInt32 nFirst = pGb2312Data[nIndex1].mnLowStart;
458 8 : if (nIndex2 >= nFirst && nIndex2 <= pGb2312Data[nIndex1].mnLowEnd)
459 8 : return pGb2312Data[nIndex1].mpToUniTrailTab[nIndex2 - nFirst]
460 8 : & 0x7F7F;
461 : }
462 0 : return 0;
463 : }
464 :
465 : static sal_uInt32
466 2 : ImplIso2022CnTranslateTo116431(sal_uInt8 const * pCns116431992Data,
467 : sal_Int32 const * pCns116431992PageOffsets,
468 : sal_Int32 const * pCns116431992PlaneOffsets,
469 : sal_uInt32 nChar)
470 : {
471 2 : sal_Int32 nOffset = pCns116431992PlaneOffsets[nChar >> 16];
472 : sal_uInt32 nFirst;
473 : sal_uInt32 nLast;
474 : sal_uInt32 nPlane;
475 2 : if (nOffset == -1)
476 0 : return 0;
477 2 : nOffset = pCns116431992PageOffsets[nOffset + ((nChar & 0xFF00) >> 8)];
478 2 : if (nOffset == -1)
479 0 : return 0;
480 2 : nFirst = pCns116431992Data[nOffset++];
481 2 : nLast = pCns116431992Data[nOffset++];
482 2 : nChar &= 0xFF;
483 2 : if (nChar < nFirst || nChar > nLast)
484 0 : return 0;
485 2 : nOffset += 3 * (nChar - nFirst);
486 2 : nPlane = pCns116431992Data[nOffset++];
487 2 : if (nPlane != 1)
488 2 : return 0;
489 0 : return (0x20 + pCns116431992Data[nOffset]) << 8
490 0 : | (0x20 + pCns116431992Data[nOffset + 1]);
491 : }
492 :
493 2 : sal_Size ImplConvertUnicodeToIso2022Cn(void const * pData,
494 : void * pContext,
495 : sal_Unicode const * pSrcBuf,
496 : sal_Size nSrcChars,
497 : char * pDestBuf,
498 : sal_Size nDestBytes,
499 : sal_uInt32 nFlags,
500 : sal_uInt32 * pInfo,
501 : sal_Size * pSrcCvtChars)
502 : {
503 : ImplUniToDBCSHighTab const * pGb2312Data
504 : = static_cast< ImplIso2022CnConverterData const * >(pData)->
505 2 : m_pUnicodeToGb2312Data;
506 : sal_uInt8 const * pCns116431992Data
507 : = static_cast< ImplIso2022CnConverterData const * >(pData)->
508 2 : m_pUnicodeToCns116431992Data;
509 : sal_Int32 const * pCns116431992PageOffsets
510 : = static_cast< ImplIso2022CnConverterData const * >(pData)->
511 2 : m_pUnicodeToCns116431992PageOffsets;
512 : sal_Int32 const * pCns116431992PlaneOffsets
513 : = static_cast< ImplIso2022CnConverterData const * >(pData)->
514 2 : m_pUnicodeToCns116431992PlaneOffsets;
515 2 : sal_Unicode nHighSurrogate = 0;
516 : ImplUnicodeToIso2022CnDesignator eSoDesignator
517 2 : = IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_NONE;
518 2 : bool b116432Designator = false;
519 2 : bool bSo = false;
520 2 : sal_uInt32 nInfo = 0;
521 2 : sal_Size nConverted = 0;
522 2 : char * pDestBufPtr = pDestBuf;
523 2 : char * pDestBufEnd = pDestBuf + nDestBytes;
524 : bool bWritten;
525 :
526 2 : if (pContext)
527 : {
528 : nHighSurrogate
529 2 : = static_cast< ImplUnicodeToIso2022CnContext * >(pContext)->m_nHighSurrogate;
530 : eSoDesignator
531 2 : = static_cast< ImplUnicodeToIso2022CnContext * >(pContext)->m_eSoDesignator;
532 : b116432Designator = static_cast< ImplUnicodeToIso2022CnContext * >(pContext)->
533 2 : m_b116432Designator;
534 2 : bSo = static_cast< ImplUnicodeToIso2022CnContext * >(pContext)->m_bSo;
535 : }
536 :
537 30 : for (; nConverted < nSrcChars; ++nConverted)
538 : {
539 28 : bool bUndefined = true;
540 28 : sal_uInt32 nChar = *pSrcBuf++;
541 28 : if (nHighSurrogate == 0)
542 : {
543 28 : if (ImplIsHighSurrogate(nChar))
544 : {
545 0 : nHighSurrogate = (sal_Unicode) nChar;
546 0 : continue;
547 : }
548 : }
549 0 : else if (ImplIsLowSurrogate(nChar))
550 0 : nChar = ImplCombineSurrogates(nHighSurrogate, nChar);
551 : else
552 : {
553 0 : bUndefined = false;
554 0 : goto bad_input;
555 : }
556 :
557 28 : if (ImplIsLowSurrogate(nChar) || ImplIsNoncharacter(nChar))
558 : {
559 0 : bUndefined = false;
560 0 : goto bad_input;
561 : }
562 :
563 28 : if (nChar == 0x0A || nChar == 0x0D) // LF, CR
564 : {
565 4 : if (bSo)
566 : {
567 2 : if (pDestBufPtr != pDestBufEnd)
568 : {
569 2 : *pDestBufPtr++ = 0x0F; // SI
570 2 : bSo = false;
571 : eSoDesignator
572 2 : = IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_NONE;
573 2 : b116432Designator = false;
574 : }
575 : else
576 0 : goto no_output;
577 : }
578 8 : if (pDestBufPtr != pDestBufEnd)
579 4 : *pDestBufPtr++ = static_cast< char >(nChar);
580 : else
581 0 : goto no_output;
582 : }
583 24 : else if (nChar == 0x0E || nChar == 0x0F || nChar == 0x1B)
584 : goto bad_input;
585 24 : else if (nChar < 0x80)
586 : {
587 16 : if (bSo)
588 : {
589 0 : if (pDestBufPtr != pDestBufEnd)
590 : {
591 0 : *pDestBufPtr++ = 0x0F; // SI
592 0 : bSo = false;
593 : }
594 : else
595 0 : goto no_output;
596 : }
597 16 : if (pDestBufPtr != pDestBufEnd)
598 16 : *pDestBufPtr++ = static_cast< char >(nChar);
599 : else
600 0 : goto no_output;
601 : }
602 : else
603 : {
604 8 : sal_uInt32 nBytes = 0;
605 : ImplUnicodeToIso2022CnDesignator eNewDesignator =
606 8 : IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_NONE;
607 8 : switch (eSoDesignator)
608 : {
609 : case IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_NONE:
610 4 : nBytes = ImplIso2022CnTranslateTo2312(pGb2312Data, nChar);
611 4 : if (nBytes != 0)
612 : {
613 : eNewDesignator
614 4 : = IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_2312;
615 4 : break;
616 : }
617 : nBytes = ImplIso2022CnTranslateTo116431(
618 : pCns116431992Data,
619 : pCns116431992PageOffsets,
620 : pCns116431992PlaneOffsets,
621 0 : nChar);
622 0 : if (nBytes != 0)
623 : {
624 : eNewDesignator
625 0 : = IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_116431;
626 0 : break;
627 : }
628 0 : break;
629 :
630 : case IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_2312:
631 4 : nBytes = ImplIso2022CnTranslateTo2312(pGb2312Data, nChar);
632 4 : if (nBytes != 0)
633 : {
634 : eNewDesignator
635 2 : = IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_NONE;
636 2 : break;
637 : }
638 : nBytes = ImplIso2022CnTranslateTo116431(
639 : pCns116431992Data,
640 : pCns116431992PageOffsets,
641 : pCns116431992PlaneOffsets,
642 2 : nChar);
643 2 : if (nBytes != 0)
644 : {
645 : eNewDesignator
646 0 : = IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_116431;
647 0 : break;
648 : }
649 2 : break;
650 :
651 : case IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_116431:
652 : nBytes = ImplIso2022CnTranslateTo116431(
653 : pCns116431992Data,
654 : pCns116431992PageOffsets,
655 : pCns116431992PlaneOffsets,
656 0 : nChar);
657 0 : if (nBytes != 0)
658 : {
659 : eNewDesignator
660 0 : = IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_NONE;
661 0 : break;
662 : }
663 0 : nBytes = ImplIso2022CnTranslateTo2312(pGb2312Data, nChar);
664 0 : if (nBytes != 0)
665 : {
666 : eNewDesignator
667 0 : = IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_2312;
668 0 : break;
669 : }
670 0 : break;
671 : }
672 8 : if (nBytes != 0)
673 : {
674 6 : if (eNewDesignator
675 : != IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_NONE)
676 : {
677 4 : if (bSo)
678 : {
679 0 : if (pDestBufPtr != pDestBufEnd)
680 : {
681 0 : *pDestBufPtr++ = 0x0F; // SI
682 0 : bSo = false;
683 : }
684 : else
685 0 : goto no_output;
686 : }
687 4 : if (pDestBufEnd - pDestBufPtr >= 4)
688 : {
689 4 : *pDestBufPtr++ = 0x1B; // ESC
690 4 : *pDestBufPtr++ = 0x24; // $
691 4 : *pDestBufPtr++ = 0x29; // )
692 : *pDestBufPtr++
693 : = eNewDesignator
694 : == IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_2312 ?
695 4 : 0x41 : 0x47; // A, G
696 4 : eSoDesignator = eNewDesignator;
697 : }
698 : else
699 0 : goto no_output;
700 : }
701 6 : if (!bSo)
702 : {
703 4 : if (pDestBufPtr != pDestBufEnd)
704 : {
705 4 : *pDestBufPtr++ = 0x0E; // SO
706 4 : bSo = true;
707 : }
708 : else
709 0 : goto no_output;
710 : }
711 6 : if (pDestBufEnd - pDestBufPtr >= 4)
712 : {
713 6 : *pDestBufPtr++ = static_cast< char >(nBytes >> 8);
714 6 : *pDestBufPtr++ = static_cast< char >(nBytes & 0xFF);
715 : }
716 : else
717 0 : goto no_output;
718 : }
719 : else
720 : {
721 2 : sal_Int32 nOffset = pCns116431992PlaneOffsets[nChar >> 16];
722 : sal_uInt32 nFirst;
723 : sal_uInt32 nLast;
724 : sal_uInt32 nPlane;
725 2 : if (nOffset == -1)
726 0 : goto bad_input;
727 : nOffset
728 : = pCns116431992PageOffsets[nOffset
729 2 : + ((nChar & 0xFF00) >> 8)];
730 2 : if (nOffset == -1)
731 0 : goto bad_input;
732 2 : nFirst = pCns116431992Data[nOffset++];
733 2 : nLast = pCns116431992Data[nOffset++];
734 2 : nChar &= 0xFF;
735 2 : if (nChar < nFirst || nChar > nLast)
736 : goto bad_input;
737 2 : nOffset += 3 * (nChar - nFirst);
738 2 : nPlane = pCns116431992Data[nOffset++];
739 2 : if (nPlane != 2)
740 0 : goto bad_input;
741 2 : if (!b116432Designator)
742 : {
743 2 : if (pDestBufEnd - pDestBufPtr >= 4)
744 : {
745 2 : *pDestBufPtr++ = 0x1B; // ESC
746 2 : *pDestBufPtr++ = 0x24; // $
747 2 : *pDestBufPtr++ = 0x2A; // *
748 2 : *pDestBufPtr++ = 0x48; // H
749 2 : b116432Designator = true;
750 : }
751 : else
752 0 : goto no_output;
753 : }
754 2 : if (pDestBufEnd - pDestBufPtr >= 4)
755 : {
756 2 : *pDestBufPtr++ = 0x1B; // ESC
757 2 : *pDestBufPtr++ = 0x4E; // N
758 : *pDestBufPtr++
759 2 : = static_cast< char >(0x20 + pCns116431992Data[nOffset++]);
760 : *pDestBufPtr++
761 2 : = static_cast< char >(0x20 + pCns116431992Data[nOffset]);
762 : }
763 : else
764 0 : goto no_output;
765 : }
766 : }
767 28 : nHighSurrogate = 0;
768 28 : continue;
769 :
770 : bad_input:
771 0 : switch (sal::detail::textenc::handleBadInputUnicodeToTextConversion(
772 : bUndefined, nChar, nFlags, &pDestBufPtr, pDestBufEnd,
773 0 : &nInfo, "\x0F" /* SI */, bSo ? 1 : 0, &bWritten))
774 : {
775 : case sal::detail::textenc::BAD_INPUT_STOP:
776 0 : nHighSurrogate = 0;
777 0 : break;
778 :
779 : case sal::detail::textenc::BAD_INPUT_CONTINUE:
780 0 : if (bWritten)
781 0 : bSo = false;
782 0 : nHighSurrogate = 0;
783 0 : continue;
784 :
785 : case sal::detail::textenc::BAD_INPUT_NO_OUTPUT:
786 0 : goto no_output;
787 : }
788 0 : break;
789 :
790 : no_output:
791 0 : --pSrcBuf;
792 0 : nInfo |= RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL;
793 0 : break;
794 : }
795 :
796 2 : if ((nInfo & (RTL_UNICODETOTEXT_INFO_ERROR
797 : | RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL))
798 : == 0)
799 : {
800 2 : bool bFlush = true;
801 2 : if (nHighSurrogate != 0)
802 : {
803 0 : if ((nFlags & RTL_UNICODETOTEXT_FLAGS_FLUSH) != 0)
804 0 : nInfo |= RTL_UNICODETOTEXT_INFO_SRCBUFFERTOSMALL;
805 : else
806 0 : switch (sal::detail::textenc::handleBadInputUnicodeToTextConversion(
807 : false, 0, nFlags, &pDestBufPtr, pDestBufEnd, &nInfo,
808 0 : "\x0F" /* SI */, bSo ? 1 : 0, &bWritten))
809 : {
810 : case sal::detail::textenc::BAD_INPUT_STOP:
811 0 : nHighSurrogate = 0;
812 0 : bFlush = false;
813 0 : break;
814 :
815 : case sal::detail::textenc::BAD_INPUT_CONTINUE:
816 0 : if (bWritten)
817 0 : bSo = false;
818 0 : nHighSurrogate = 0;
819 0 : break;
820 :
821 : case sal::detail::textenc::BAD_INPUT_NO_OUTPUT:
822 0 : nInfo |= RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL;
823 0 : break;
824 : }
825 : }
826 2 : if (bFlush && bSo && (nFlags & RTL_UNICODETOTEXT_FLAGS_FLUSH) != 0)
827 : {
828 2 : if (pDestBufPtr != pDestBufEnd)
829 : {
830 2 : *pDestBufPtr++ = 0x0F; // SI
831 2 : bSo = false;
832 : }
833 : else
834 0 : nInfo |= RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL;
835 : }
836 : }
837 :
838 2 : if (pContext)
839 : {
840 : static_cast< ImplUnicodeToIso2022CnContext * >(pContext)->m_nHighSurrogate
841 2 : = nHighSurrogate;
842 : static_cast< ImplUnicodeToIso2022CnContext * >(pContext)->m_eSoDesignator
843 2 : = eSoDesignator;
844 : static_cast< ImplUnicodeToIso2022CnContext * >(pContext)->m_b116432Designator
845 2 : = b116432Designator;
846 2 : static_cast< ImplUnicodeToIso2022CnContext * >(pContext)->m_bSo = bSo;
847 : }
848 2 : if (pInfo)
849 2 : *pInfo = nInfo;
850 2 : if (pSrcCvtChars)
851 2 : *pSrcCvtChars = nConverted;
852 :
853 2 : return pDestBufPtr - pDestBuf;
854 : }
855 :
856 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|