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