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 4 : void * ImplCreateIso2022CnToUnicodeContext()
72 : {
73 : ImplIso2022CnToUnicodeContext * pContext =
74 4 : new ImplIso2022CnToUnicodeContext;
75 4 : pContext->m_eState = IMPL_ISO_2022_CN_TO_UNICODE_STATE_ASCII;
76 4 : pContext->m_bSo = false;
77 4 : pContext->m_b116431 = false;
78 4 : 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 4 : void ImplDestroyIso2022CnToUnicodeContext(void * pContext)
93 : {
94 4 : delete static_cast< ImplIso2022CnToUnicodeContext * >(pContext);
95 4 : }
96 :
97 74 : 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 74 : m_pGb2312ToUnicodeData;
110 : sal_uInt16 const * pCns116431992Data
111 : = static_cast< ImplIso2022CnConverterData const * >(pData)->
112 74 : m_pCns116431992ToUnicodeData;
113 : sal_Int32 const * pCns116431992RowOffsets
114 : = static_cast< ImplIso2022CnConverterData const * >(pData)->
115 74 : m_pCns116431992ToUnicodeRowOffsets;
116 : sal_Int32 const * pCns116431992PlaneOffsets
117 : = static_cast< ImplIso2022CnConverterData const * >(pData)->
118 74 : m_pCns116431992ToUnicodePlaneOffsets;
119 : ImplIso2022CnToUnicodeState eState
120 74 : = IMPL_ISO_2022_CN_TO_UNICODE_STATE_ASCII;
121 74 : sal_uInt32 nRow = 0;
122 74 : bool bSo = false;
123 74 : bool b116431 = false;
124 74 : sal_uInt32 nInfo = 0;
125 74 : sal_Size nConverted = 0;
126 74 : sal_Unicode * pDestBufPtr = pDestBuf;
127 74 : sal_Unicode * pDestBufEnd = pDestBuf + nDestChars;
128 :
129 74 : if (pContext)
130 : {
131 74 : eState = static_cast< ImplIso2022CnToUnicodeContext * >(pContext)->m_eState;
132 74 : nRow = static_cast< ImplIso2022CnToUnicodeContext * >(pContext)->m_nRow;
133 74 : bSo = static_cast< ImplIso2022CnToUnicodeContext * >(pContext)->m_bSo;
134 74 : b116431 = static_cast< ImplIso2022CnToUnicodeContext * >(pContext)->m_b116431;
135 : }
136 :
137 214 : for (; nConverted < nSrcBytes; ++nConverted)
138 : {
139 140 : bool bUndefined = true;
140 140 : sal_uInt32 nChar = *(sal_uChar const *) pSrcBuf++;
141 : sal_uInt32 nPlane;
142 140 : switch (eState)
143 : {
144 : case IMPL_ISO_2022_CN_TO_UNICODE_STATE_ASCII:
145 52 : if (nChar == 0x0E) // SO
146 : {
147 8 : bSo = true;
148 8 : eState = IMPL_ISO_2022_CN_TO_UNICODE_STATE_SO;
149 : }
150 44 : else if (nChar == 0x1B) // ESC
151 8 : eState = IMPL_ISO_2022_CN_TO_UNICODE_STATE_ESC;
152 36 : else if (nChar < 0x80)
153 36 : if (pDestBufPtr != pDestBufEnd)
154 36 : *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 52 : break;
163 :
164 : case IMPL_ISO_2022_CN_TO_UNICODE_STATE_SO:
165 28 : if (nChar == 0x0F) // SI
166 : {
167 8 : bSo = false;
168 8 : eState = IMPL_ISO_2022_CN_TO_UNICODE_STATE_ASCII;
169 : }
170 20 : else if (nChar == 0x1B) // ESC
171 8 : eState = IMPL_ISO_2022_CN_TO_UNICODE_STATE_ESC;
172 12 : else if (nChar >= 0x21 && nChar <= 0x7E)
173 : {
174 12 : nRow = nChar;
175 12 : 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 28 : break;
183 :
184 : case IMPL_ISO_2022_CN_TO_UNICODE_STATE_SO_2:
185 12 : if (nChar >= 0x21 && nChar <= 0x7E)
186 12 : if (b116431)
187 : {
188 4 : nPlane = 0;
189 4 : goto transform;
190 : }
191 : else
192 : {
193 8 : sal_uInt16 nUnicode = 0;
194 : sal_uInt32 nFirst;
195 8 : nRow += 0x80;
196 8 : nChar += 0x80;
197 8 : nFirst = pGb2312Data[nRow].mnTrailStart;
198 16 : if (nChar >= nFirst
199 8 : && nChar <= pGb2312Data[nRow].mnTrailEnd)
200 8 : nUnicode = pGb2312Data[nRow].
201 8 : mpToUniTrailTab[nChar - nFirst];
202 8 : if (nUnicode != 0)
203 8 : if (pDestBufPtr != pDestBufEnd)
204 : {
205 8 : *pDestBufPtr++ = (sal_Unicode) nUnicode;
206 8 : 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 8 : }
213 : else
214 : {
215 0 : bUndefined = false;
216 0 : goto bad_input;
217 : }
218 8 : break;
219 :
220 : case IMPL_ISO_2022_CN_TO_UNICODE_STATE_116432:
221 4 : if (nChar >= 0x21 && nChar <= 0x7E)
222 : {
223 4 : nRow = nChar;
224 4 : 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 4 : break;
232 :
233 : case IMPL_ISO_2022_CN_TO_UNICODE_STATE_116432_2:
234 4 : if (nChar >= 0x21 && nChar <= 0x7E)
235 : {
236 4 : nPlane = 1;
237 4 : 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 16 : if (nChar == 0x24) // $
248 12 : eState = IMPL_ISO_2022_CN_TO_UNICODE_STATE_ESC_DOLLAR;
249 4 : else if (nChar == 0x4E) // N
250 4 : eState = IMPL_ISO_2022_CN_TO_UNICODE_STATE_116432;
251 : else
252 : {
253 0 : bUndefined = false;
254 0 : goto bad_input;
255 : }
256 16 : break;
257 :
258 : case IMPL_ISO_2022_CN_TO_UNICODE_STATE_ESC_DOLLAR:
259 12 : if (nChar == 0x29) // )
260 8 : eState = IMPL_ISO_2022_CN_TO_UNICODE_STATE_ESC_DOLLAR_RPAREN;
261 4 : else if (nChar == 0x2A) // *
262 : eState
263 4 : = IMPL_ISO_2022_CN_TO_UNICODE_STATE_ESC_DOLLAR_ASTERISK;
264 : else
265 : {
266 0 : bUndefined = false;
267 0 : goto bad_input;
268 : }
269 12 : break;
270 :
271 : case IMPL_ISO_2022_CN_TO_UNICODE_STATE_ESC_DOLLAR_RPAREN:
272 8 : if (nChar == 0x41) // A
273 : {
274 6 : b116431 = false;
275 : eState = bSo ? IMPL_ISO_2022_CN_TO_UNICODE_STATE_SO :
276 6 : IMPL_ISO_2022_CN_TO_UNICODE_STATE_ASCII;
277 : }
278 2 : else if (nChar == 0x47) // G
279 : {
280 2 : b116431 = true;
281 : eState = bSo ? IMPL_ISO_2022_CN_TO_UNICODE_STATE_SO :
282 2 : IMPL_ISO_2022_CN_TO_UNICODE_STATE_ASCII;
283 : }
284 : else
285 : {
286 0 : bUndefined = false;
287 0 : goto bad_input;
288 : }
289 8 : break;
290 :
291 : case IMPL_ISO_2022_CN_TO_UNICODE_STATE_ESC_DOLLAR_ASTERISK:
292 4 : if (nChar == 0x48) // H
293 : eState = bSo ? IMPL_ISO_2022_CN_TO_UNICODE_STATE_SO :
294 4 : IMPL_ISO_2022_CN_TO_UNICODE_STATE_ASCII;
295 : else
296 : {
297 0 : bUndefined = false;
298 0 : goto bad_input;
299 : }
300 4 : break;
301 : }
302 132 : continue;
303 :
304 : transform:
305 : {
306 8 : sal_Int32 nPlaneOffset = pCns116431992PlaneOffsets[nPlane];
307 8 : if (nPlaneOffset == -1)
308 0 : goto bad_input;
309 : else
310 : {
311 : sal_Int32 nOffset
312 8 : = pCns116431992RowOffsets[nPlaneOffset + (nRow - 0x21)];
313 8 : if (nOffset == -1)
314 0 : goto bad_input;
315 : else
316 : {
317 8 : sal_uInt32 nFirstLast = pCns116431992Data[nOffset++];
318 8 : sal_uInt32 nFirst = nFirstLast & 0xFF;
319 8 : sal_uInt32 nLast = nFirstLast >> 8;
320 8 : nChar -= 0x20;
321 8 : if (nChar >= nFirst && nChar <= nLast)
322 : {
323 : sal_uInt32 nUnicode
324 8 : = pCns116431992Data[nOffset + (nChar - nFirst)];
325 8 : if (nUnicode == 0xFFFF)
326 0 : goto bad_input;
327 8 : 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 8 : if (pDestBufPtr != pDestBufEnd)
342 8 : *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 8 : IMPL_ISO_2022_CN_TO_UNICODE_STATE_ASCII;
350 : }
351 : }
352 8 : 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 74 : if (eState > IMPL_ISO_2022_CN_TO_UNICODE_STATE_SO
382 : && (nInfo & (RTL_TEXTTOUNICODE_INFO_ERROR
383 : | RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL))
384 : == 0)
385 : {
386 30 : if ((nFlags & RTL_TEXTTOUNICODE_FLAGS_FLUSH) == 0)
387 30 : 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 74 : if (pContext)
406 : {
407 74 : static_cast< ImplIso2022CnToUnicodeContext * >(pContext)->m_eState = eState;
408 74 : static_cast< ImplIso2022CnToUnicodeContext * >(pContext)->m_nRow = nRow;
409 74 : static_cast< ImplIso2022CnToUnicodeContext * >(pContext)->m_bSo = bSo;
410 74 : static_cast< ImplIso2022CnToUnicodeContext * >(pContext)->m_b116431 = b116431;
411 : }
412 74 : if (pInfo)
413 74 : *pInfo = nInfo;
414 74 : if (pSrcCvtBytes)
415 74 : *pSrcCvtBytes = nConverted;
416 :
417 74 : return pDestBufPtr - pDestBuf;
418 : }
419 :
420 1 : void * ImplCreateUnicodeToIso2022CnContext(void)
421 : {
422 : ImplUnicodeToIso2022CnContext * pContext =
423 1 : new ImplUnicodeToIso2022CnContext;
424 1 : pContext->m_nHighSurrogate = 0;
425 1 : pContext->m_eSoDesignator = IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_NONE;
426 1 : pContext->m_b116432Designator = false;
427 1 : pContext->m_bSo = false;
428 1 : 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 1 : void ImplDestroyUnicodeToIso2022CnContext(void * pContext)
445 : {
446 1 : delete static_cast< ImplUnicodeToIso2022CnContext * >(pContext);
447 1 : }
448 :
449 4 : static sal_uInt32 ImplIso2022CnTranslateTo2312(ImplUniToDBCSHighTab const *
450 : pGb2312Data,
451 : sal_uInt32 nChar)
452 : {
453 4 : sal_uInt32 nIndex1 = nChar >> 8;
454 4 : if (nIndex1 < 0x100)
455 : {
456 4 : sal_uInt32 nIndex2 = nChar & 0xFF;
457 4 : sal_uInt32 nFirst = pGb2312Data[nIndex1].mnLowStart;
458 4 : if (nIndex2 >= nFirst && nIndex2 <= pGb2312Data[nIndex1].mnLowEnd)
459 4 : return pGb2312Data[nIndex1].mpToUniTrailTab[nIndex2 - nFirst]
460 4 : & 0x7F7F;
461 : }
462 0 : return 0;
463 : }
464 :
465 : static sal_uInt32
466 1 : ImplIso2022CnTranslateTo116431(sal_uInt8 const * pCns116431992Data,
467 : sal_Int32 const * pCns116431992PageOffsets,
468 : sal_Int32 const * pCns116431992PlaneOffsets,
469 : sal_uInt32 nChar)
470 : {
471 1 : sal_Int32 nOffset = pCns116431992PlaneOffsets[nChar >> 16];
472 : sal_uInt32 nFirst;
473 : sal_uInt32 nLast;
474 : sal_uInt32 nPlane;
475 1 : if (nOffset == -1)
476 0 : return 0;
477 1 : nOffset = pCns116431992PageOffsets[nOffset + ((nChar & 0xFF00) >> 8)];
478 1 : if (nOffset == -1)
479 0 : return 0;
480 1 : nFirst = pCns116431992Data[nOffset++];
481 1 : nLast = pCns116431992Data[nOffset++];
482 1 : nChar &= 0xFF;
483 1 : if (nChar < nFirst || nChar > nLast)
484 0 : return 0;
485 1 : nOffset += 3 * (nChar - nFirst);
486 1 : nPlane = pCns116431992Data[nOffset++];
487 1 : if (nPlane != 1)
488 1 : return 0;
489 0 : return (0x20 + pCns116431992Data[nOffset]) << 8
490 0 : | (0x20 + pCns116431992Data[nOffset + 1]);
491 : }
492 :
493 1 : 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 1 : m_pUnicodeToGb2312Data;
506 : sal_uInt8 const * pCns116431992Data
507 : = static_cast< ImplIso2022CnConverterData const * >(pData)->
508 1 : m_pUnicodeToCns116431992Data;
509 : sal_Int32 const * pCns116431992PageOffsets
510 : = static_cast< ImplIso2022CnConverterData const * >(pData)->
511 1 : m_pUnicodeToCns116431992PageOffsets;
512 : sal_Int32 const * pCns116431992PlaneOffsets
513 : = static_cast< ImplIso2022CnConverterData const * >(pData)->
514 1 : m_pUnicodeToCns116431992PlaneOffsets;
515 1 : sal_Unicode nHighSurrogate = 0;
516 : ImplUnicodeToIso2022CnDesignator eSoDesignator
517 1 : = IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_NONE;
518 1 : bool b116432Designator = false;
519 1 : bool bSo = false;
520 1 : sal_uInt32 nInfo = 0;
521 1 : sal_Size nConverted = 0;
522 1 : char * pDestBufPtr = pDestBuf;
523 1 : char * pDestBufEnd = pDestBuf + nDestBytes;
524 : bool bWritten;
525 :
526 1 : if (pContext)
527 : {
528 : nHighSurrogate
529 1 : = static_cast< ImplUnicodeToIso2022CnContext * >(pContext)->m_nHighSurrogate;
530 : eSoDesignator
531 1 : = static_cast< ImplUnicodeToIso2022CnContext * >(pContext)->m_eSoDesignator;
532 : b116432Designator = static_cast< ImplUnicodeToIso2022CnContext * >(pContext)->
533 1 : m_b116432Designator;
534 1 : bSo = static_cast< ImplUnicodeToIso2022CnContext * >(pContext)->m_bSo;
535 : }
536 :
537 15 : for (; nConverted < nSrcChars; ++nConverted)
538 : {
539 14 : bool bUndefined = true;
540 14 : sal_uInt32 nChar = *pSrcBuf++;
541 14 : if (nHighSurrogate == 0)
542 : {
543 14 : 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 14 : if (ImplIsLowSurrogate(nChar) || ImplIsNoncharacter(nChar))
558 : {
559 0 : bUndefined = false;
560 0 : goto bad_input;
561 : }
562 :
563 14 : if (nChar == 0x0A || nChar == 0x0D) // LF, CR
564 : {
565 2 : if (bSo)
566 : {
567 1 : if (pDestBufPtr != pDestBufEnd)
568 : {
569 1 : *pDestBufPtr++ = 0x0F; // SI
570 1 : bSo = false;
571 : eSoDesignator
572 1 : = IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_NONE;
573 1 : b116432Designator = false;
574 : }
575 : else
576 0 : goto no_output;
577 : }
578 4 : if (pDestBufPtr != pDestBufEnd)
579 2 : *pDestBufPtr++ = static_cast< char >(nChar);
580 : else
581 0 : goto no_output;
582 : }
583 12 : else if (nChar == 0x0E || nChar == 0x0F || nChar == 0x1B)
584 : goto bad_input;
585 12 : else if (nChar < 0x80)
586 : {
587 8 : 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 8 : if (pDestBufPtr != pDestBufEnd)
598 8 : *pDestBufPtr++ = static_cast< char >(nChar);
599 : else
600 0 : goto no_output;
601 : }
602 : else
603 : {
604 4 : sal_uInt32 nBytes = 0;
605 : ImplUnicodeToIso2022CnDesignator eNewDesignator =
606 4 : IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_NONE;
607 4 : switch (eSoDesignator)
608 : {
609 : case IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_NONE:
610 2 : nBytes = ImplIso2022CnTranslateTo2312(pGb2312Data, nChar);
611 2 : if (nBytes != 0)
612 : {
613 : eNewDesignator
614 2 : = IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_2312;
615 2 : 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 2 : nBytes = ImplIso2022CnTranslateTo2312(pGb2312Data, nChar);
632 2 : if (nBytes != 0)
633 : {
634 : eNewDesignator
635 1 : = IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_NONE;
636 1 : break;
637 : }
638 : nBytes = ImplIso2022CnTranslateTo116431(
639 : pCns116431992Data,
640 : pCns116431992PageOffsets,
641 : pCns116431992PlaneOffsets,
642 1 : nChar);
643 1 : if (nBytes != 0)
644 : {
645 : eNewDesignator
646 0 : = IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_116431;
647 0 : break;
648 : }
649 1 : 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 4 : if (nBytes != 0)
673 : {
674 3 : if (eNewDesignator
675 : != IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_NONE)
676 : {
677 2 : 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 2 : if (pDestBufEnd - pDestBufPtr >= 4)
688 : {
689 2 : *pDestBufPtr++ = 0x1B; // ESC
690 2 : *pDestBufPtr++ = 0x24; // $
691 2 : *pDestBufPtr++ = 0x29; // )
692 : *pDestBufPtr++
693 : = eNewDesignator
694 : == IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_2312 ?
695 2 : 0x41 : 0x47; // A, G
696 2 : eSoDesignator = eNewDesignator;
697 : }
698 : else
699 0 : goto no_output;
700 : }
701 3 : if (!bSo)
702 : {
703 2 : if (pDestBufPtr != pDestBufEnd)
704 : {
705 2 : *pDestBufPtr++ = 0x0E; // SO
706 2 : bSo = true;
707 : }
708 : else
709 0 : goto no_output;
710 : }
711 3 : if (pDestBufEnd - pDestBufPtr >= 4)
712 : {
713 3 : *pDestBufPtr++ = static_cast< char >(nBytes >> 8);
714 3 : *pDestBufPtr++ = static_cast< char >(nBytes & 0xFF);
715 : }
716 : else
717 0 : goto no_output;
718 : }
719 : else
720 : {
721 1 : sal_Int32 nOffset = pCns116431992PlaneOffsets[nChar >> 16];
722 : sal_uInt32 nFirst;
723 : sal_uInt32 nLast;
724 : sal_uInt32 nPlane;
725 1 : if (nOffset == -1)
726 0 : goto bad_input;
727 : nOffset
728 : = pCns116431992PageOffsets[nOffset
729 1 : + ((nChar & 0xFF00) >> 8)];
730 1 : if (nOffset == -1)
731 0 : goto bad_input;
732 1 : nFirst = pCns116431992Data[nOffset++];
733 1 : nLast = pCns116431992Data[nOffset++];
734 1 : nChar &= 0xFF;
735 1 : if (nChar < nFirst || nChar > nLast)
736 : goto bad_input;
737 1 : nOffset += 3 * (nChar - nFirst);
738 1 : nPlane = pCns116431992Data[nOffset++];
739 1 : if (nPlane != 2)
740 0 : goto bad_input;
741 1 : if (!b116432Designator)
742 : {
743 1 : if (pDestBufEnd - pDestBufPtr >= 4)
744 : {
745 1 : *pDestBufPtr++ = 0x1B; // ESC
746 1 : *pDestBufPtr++ = 0x24; // $
747 1 : *pDestBufPtr++ = 0x2A; // *
748 1 : *pDestBufPtr++ = 0x48; // H
749 1 : b116432Designator = true;
750 : }
751 : else
752 0 : goto no_output;
753 : }
754 1 : if (pDestBufEnd - pDestBufPtr >= 4)
755 : {
756 1 : *pDestBufPtr++ = 0x1B; // ESC
757 1 : *pDestBufPtr++ = 0x4E; // N
758 : *pDestBufPtr++
759 1 : = static_cast< char >(0x20 + pCns116431992Data[nOffset++]);
760 : *pDestBufPtr++
761 1 : = static_cast< char >(0x20 + pCns116431992Data[nOffset]);
762 : }
763 : else
764 0 : goto no_output;
765 : }
766 : }
767 14 : nHighSurrogate = 0;
768 14 : 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 1 : if ((nInfo & (RTL_UNICODETOTEXT_INFO_ERROR
797 : | RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL))
798 : == 0)
799 : {
800 1 : bool bFlush = true;
801 1 : 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 1 : if (bFlush && bSo && (nFlags & RTL_UNICODETOTEXT_FLAGS_FLUSH) != 0)
827 : {
828 1 : if (pDestBufPtr != pDestBufEnd)
829 : {
830 1 : *pDestBufPtr++ = 0x0F; // SI
831 1 : bSo = false;
832 : }
833 : else
834 0 : nInfo |= RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL;
835 : }
836 : }
837 :
838 1 : if (pContext)
839 : {
840 : static_cast< ImplUnicodeToIso2022CnContext * >(pContext)->m_nHighSurrogate
841 1 : = nHighSurrogate;
842 : static_cast< ImplUnicodeToIso2022CnContext * >(pContext)->m_eSoDesignator
843 1 : = eSoDesignator;
844 : static_cast< ImplUnicodeToIso2022CnContext * >(pContext)->m_b116432Designator
845 1 : = b116432Designator;
846 1 : static_cast< ImplUnicodeToIso2022CnContext * >(pContext)->m_bSo = bSo;
847 : }
848 1 : if (pInfo)
849 1 : *pInfo = nInfo;
850 1 : if (pSrcCvtChars)
851 1 : *pSrcCvtChars = nConverted;
852 :
853 1 : return pDestBufPtr - pDestBuf;
854 : }
855 :
856 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|