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