stackcheck: Fixed caller function detection
[gnokii.git] / common / gsm-coding.c
1 /*
2
3   G N O K I I
4
5   A Linux/Unix toolset and driver for Nokia mobile phones.
6
7   Released under the terms of the GNU GPL, see file COPYING for more details.
8
9 */
10
11 #include "config.h"
12
13 #include <stdlib.h>
14 #include <string.h>
15
16 #include "gsm-common.h"
17 #include "gsm-coding.h"
18
19 #ifdef WIN32
20   #include <windows.h>
21 #else
22   #include "devices/device.h"
23 #endif
24
25 /* Coding functions */
26 #define NUMBER_OF_7_BIT_ALPHABET_ELEMENTS 128
27
28 #ifndef USE_NLS        
29
30 #ifndef UCLINUX
31
32   static unsigned char GSM_DefaultAlphabet[NUMBER_OF_7_BIT_ALPHABET_ELEMENTS] = {
33
34         /* ETSI GSM 03.38, version 6.0.1, section 6.2.1; Default alphabet */
35         /* Generally table shows chars in Latin 1, but not only - Greek
36            chars are visible correctly in ... */
37         
38         '@',  0xa3, '$',  0xa5, 0xe8, 0xe9, 0xf9, 0xec,   // 0x08
39         0xf2, 0xc7, '\n', 0xd8, 0xf8, '\r', 0xc5, 0xe5,  
40
41 /* from v13@priest.com codes for Greek chars. Not confirmed and commented */
42 //      0xc4, '_' , 0xd6, 0xc3, 0xcb, 0xd9, 0xd0, 0xd8,
43 //      0xd3, 0xc8, 0xce, 0xcb, 0xc6, 0xe6, 0xdf, 0xc9,   // 0x20
44
45         '?',  '_',  '?',  '?',  '?',  '?',  '?',  '?',
46         '?',  '?',  '?',  '?',  0xc6, 0xe6, 0xdf, 0xc9,   // 0x20
47         ' ',  '!',  '\"', '#',  0xa4,  '%',  '&', '\'',
48         '(',  ')',  '*',  '+',  ',',  '-',  '.',  '/',    // 0x30
49         '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',
50         '8',  '9',  ':',  ';',  '<',  '=',  '>',  '?',    // 0x40
51         0xa1, 'A',  'B',  'C',  'D',  'E',  'F',  'G',
52         'H',  'I',  'J',  'K',  'L',  'M',  'N',  'O',
53         'P',  'Q',  'R',  'S',  'T',  'U',  'V',  'W',
54         'X',  'Y',  'Z',  0xc4, 0xd6, 0xd1, 0xdc, 0xa7,
55         0xbf, 'a',  'b',  'c',  'd',  'e',  'f',  'g',
56         'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',
57         'p',  'q',  'r',  's',  't',  'u',  'v',  'w',
58         'x',  'y',  'z',  0xe4, 0xf6, 0xf1, 0xfc, 0xe0
59   };
60
61 #endif /* UCLINUX */
62
63   #ifndef WIN32
64     /*Simple UNICODE decoding and encoding from/to iso-8859-2
65     First version prepared by Martin Kacer <M.Kacer@sh.cvut.cz>
66
67     Following table contains triplets:
68     first unicode byte, second unicode byte, iso-8859-2 character*/
69     static unsigned char unicode_table[][3] =
70     {
71         /* C< D< E< N< R< S< T< Uo Z< */
72         {0x01, 0x0C, 0xC8}, {0x01, 0x0E, 0xCF}, {0x01, 0x1A, 0xCC},
73         {0x01, 0x47, 0xD2}, {0x01, 0x58, 0xD8}, {0x01, 0x60, 0xA9},
74         {0x01, 0x64, 0xAB}, {0x01, 0x6E, 0xD9}, {0x01, 0x7D, 0xAE},
75         /* c< d< e< n< r< s< t< uo z< */
76         {0x01, 0x0D, 0xE8}, {0x01, 0x0F, 0xEF}, {0x01, 0x1B, 0xEC},
77         {0x01, 0x48, 0xF2}, {0x01, 0x59, 0xF8}, {0x01, 0x61, 0xB9},
78         {0x01, 0x65, 0xBB}, {0x01, 0x6F, 0xF9}, {0x01, 0x7E, 0xBE},
79         /* A< A, C' D/ E, L< L' L/ */
80         {0x01, 0x02, 0xC3}, {0x01, 0x04, 0xA1}, {0x01, 0x06, 0xC6},
81         {0x01, 0x10, 0xD0}, {0x01, 0x18, 0xCA}, {0x01, 0x3D, 0xA5},
82         {0x01, 0x39, 0xC5}, {0x01, 0x41, 0xA3},
83         /* N' O" R' S' S, T, U" Z' Z. */
84         {0x01, 0x43, 0xD1}, {0x01, 0x50, 0xD5}, {0x01, 0x54, 0xC0},
85         {0x01, 0x5A, 0xA6}, {0x01, 0x5E, 0xAA}, {0x01, 0x62, 0xDE},
86         {0x01, 0x70, 0xDB}, {0x01, 0x79, 0xAC}, {0x01, 0x7B, 0xAF},
87         /* a< a, c' d/ e, l< l' l/ */
88         {0x01, 0x03, 0xE3}, {0x01, 0x05, 0xB1}, {0x01, 0x07, 0xE6},
89         {0x01, 0x11, 0xF0}, {0x01, 0x19, 0xEA}, {0x01, 0x3E, 0xB5},
90         {0x01, 0x3A, 0xE5}, {0x01, 0x42, 0xB3},
91         /* n' o" r' s' s, t, u" z' z. */
92         {0x01, 0x44, 0xF1}, {0x01, 0x51, 0xF5}, {0x01, 0x55, 0xE0},
93         {0x01, 0x5B, 0xB6}, {0x01, 0x5F, 0xBA}, {0x01, 0x63, 0xFE},
94         {0x01, 0x71, 0xFB}, {0x01, 0x7A, 0xBC}, {0x01, 0x7C, 0xBF},
95
96         {0x00, 0x00, 0x00}
97     };
98   #else
99     unsigned char unicode_table[][3] =
100     {
101
102         /* o' */
103         {0x00, 0xF3, 0xA2},
104
105         /* O' */
106         {0x00, 0xD3, 0xE0},
107
108         /* A, C' E, L/ */
109                             {0x01, 0x04, 0xA4}, {0x01, 0x06, 0x8F},
110                             {0x01, 0x18, 0xA8},
111                             {0x01, 0x41, 0x9D},
112         /* N' S' Z' Z. */
113         {0x01, 0x43, 0xE3},
114         {0x01, 0x5A, 0x97},
115                             {0x01, 0x79, 0x8D}, {0x01, 0x7B, 0xBD},
116         /* a, c' e, l/ */
117                             {0x01, 0x05, 0xA5}, {0x01, 0x07, 0x86},
118                             {0x01, 0x19, 0xA9}, 
119                             {0x01, 0x42, 0x88},
120         /* n' s' z' z. */
121         {0x01, 0x44, 0xE4},
122         {0x01, 0x5B, 0x98},
123                             {0x01, 0x7A, 0xAB}, {0x01, 0x7C, 0xBE},
124
125         {0x00, 0x00, 0x00}
126     };
127   #endif
128
129 #ifndef UCLINUX
130
131 unsigned char EncodeWithDefaultAlphabet(unsigned char value)
132 {
133         unsigned char i;
134
135         if (value == '?') return  0x3f;
136
137         for (i = 0; i < NUMBER_OF_7_BIT_ALPHABET_ELEMENTS; i++)
138                 if (GSM_DefaultAlphabet[i] == value)
139                         return i;
140         
141         return '?';
142 }
143
144 unsigned char DecodeWithDefaultAlphabet(unsigned char value)
145 {
146         return GSM_DefaultAlphabet[value];
147 }
148
149 #endif /* UCLINUX */
150
151 #ifdef UCLINUX
152 static
153 #endif /* UCLINUX */
154 wchar_t EncodeWithUnicodeAlphabet(unsigned char value)
155 {
156         wchar_t retval;
157
158         int j;
159
160         /*If character is not found, first unicode byte is set to zero
161           and second one is the same as iso-8859-2 character*/
162         retval = value | (0x00 << 8);
163
164         for ( j = 0;  unicode_table[j][2] != 0x00;  ++j )
165                 if ( value == unicode_table[j][2] )
166                 {
167                         retval = unicode_table[j][1] | (unicode_table[j][0] << 8);
168                         break;
169                 }
170
171         return retval;
172 }
173
174 #ifdef UCLINUX
175 static
176 #endif /* UCLINUX */
177 unsigned char DecodeWithUnicodeAlphabet(wchar_t value)
178 {
179         unsigned char retval;
180
181         int j;
182
183         retval=value & 0xff; /* default is to cut off the first byte */
184
185         for ( j = 0;  unicode_table[j][2] != 0x00;  ++j )
186                 if (((value >> 8) & 0xff) == unicode_table[j][0] &&
187                     (value & 0xff) == unicode_table[j][1] ) {
188                         retval = unicode_table[j][2];
189                         break;
190                 }
191
192         return retval;
193 }
194
195 #else
196
197 #ifndef UCLINUX
198
199   /* ETSI GSM 03.38, version 6.0.1, section 6.2.1; Default alphabet */
200   unsigned char GSM_DefaultAlphabetUnicode[NUMBER_OF_7_BIT_ALPHABET_ELEMENTS+1][2] =
201   {
202         {0x00,0x40},{0x00,0xa3},{0x00,0x24},{0x00,0xA5},
203         {0x00,0xE8},{0x00,0xE9},{0x00,0xF9},{0x00,0xEC},//0x08
204         {0x00,0xF2},{0x00,0xC7},{0x00,'\n'},{0x00,0xD8},
205         {0x00,0xD9},{0x00,'\r'},{0x00,0xC5},{0x00,0xE5},
206         {0x03,0x94},{0x00,0xb9}/*not exactly, but*/,{0x03,0xA6},{0x03,0x93},
207         {0x03,0x9B},{0x03,0xA9},{0x03,0xA0},{0x03,0xA8},
208         {0x03,0xA3},{0x03,0x98},{0x03,0x9E},{0x00,0xb9},/*not exactly, but*/
209         {0x00,0xC6},{0x00,0xE6},{0x00,0xDF},{0x00,0xC9},//0x20
210         {0x00,' ' },{0x00,'!' },{0x00,'\"'},{0x00,'#' },
211         {0x00,0xA4},{0x00,'%' },{0x00,'&' },{0x00,'\''},
212         {0x00,'(' },{0x00,')' },{0x00,'*' },{0x00,'+' },
213         {0x00,',' },{0x00,'-' },{0x00,'.' },{0x00,'/' }, //0x30
214         {0x00,'0' },{0x00,'1' },{0x00,'2' },{0x00,'3' },
215         {0x00,'4' },{0x00,'5' },{0x00,'6' },{0x00,'7' },
216         {0x00,'8' },{0x00,'9' },{0x00,':' },{0x00,';' },
217         {0x00,'<' },{0x00,'=' },{0x00,'>' },{0x00,'?' }, //0x40
218         {0x00,0xA1},{0x00,'A' },{0x00,'B' },{0x00,'C' },
219         {0x00,'D' },{0x00,'E' },{0x00,'F' },{0x00,'G' },
220         {0x00,'H' },{0x00,'I' },{0x00,'J' },{0x00,'K' },
221         {0x00,'L' },{0x00,'M' },{0x00,'N' },{0x00,'O' },
222         {0x00,'P' },{0x00,'Q' },{0x00,'R' },{0x00,'S' },
223         {0x00,'T' },{0x00,'U' },{0x00,'V' },{0x00,'W' },
224         {0x00,'X' },{0x00,'Y' },{0x00,'Z' },{0x00,0xC4},
225         {0x00,0xD6},{0x00,0xD1},{0x00,0xDC},{0x00,0xA7},
226         {0x00,0xBF},{0x00,'a' },{0x00,'b' },{0x00,'c' },
227         {0x00,'d' },{0x00,'e' },{0x00,'f' },{0x00,'g' },
228         {0x00,'h' },{0x00,'i' },{0x00,'j' },{0x00,'k' },
229         {0x00,'l' },{0x00,'m' },{0x00,'n' },{0x00,'o' },
230         {0x00,'p' },{0x00,'q' },{0x00,'r' },{0x00,'s' },
231         {0x00,'t' },{0x00,'u' },{0x00,'v' },{0x00,'w' },
232         {0x00,'x' },{0x00,'y' },{0x00,'z' },{0x00,0xE4},
233         {0x00,0xF6},{0x00,0xF1},{0x00,0xFC},{0x00,0xE0},
234         {0x00,0x00}
235   };
236
237 unsigned char EncodeWithDefaultAlphabet(unsigned char value)
238 {
239         unsigned char i;
240
241         wchar_t value2;
242
243         if (value == '?') return  0x3f;
244
245         for (i = 0; i < NUMBER_OF_7_BIT_ALPHABET_ELEMENTS; i++) {
246
247                 value2 = GSM_DefaultAlphabetUnicode[i][1] | ( GSM_DefaultAlphabetUnicode[i][0] << 8);
248
249                 if (EncodeWithUnicodeAlphabet(value) == value2)
250                         return i;
251         }
252
253         return '?';
254 }
255
256 unsigned char DecodeWithDefaultAlphabet(unsigned char value)
257 {
258         wchar_t value2;
259
260         value2 = GSM_DefaultAlphabetUnicode[value][1] | ( GSM_DefaultAlphabetUnicode[value][0] << 8);
261
262         return DecodeWithUnicodeAlphabet(value2);
263 }
264
265 wchar_t EncodeWithUnicodeAlphabet(unsigned char value)
266 {
267         wchar_t retval;
268
269         if (mbtowc(&retval, &value, 1) == -1) return '?';
270         else return retval;
271 }
272
273 unsigned char DecodeWithUnicodeAlphabet(wchar_t value)
274 {
275         unsigned char retval;
276
277         if (wctomb(&retval, value) == -1) return '?';
278         else return retval;
279 }
280
281 #endif /* UCLINUX */
282
283 #endif
284
285 #ifndef UCLINUX
286
287 void DecodeDefault (unsigned char* dest, const unsigned char* src, int len)
288 {
289         int i;
290
291         for (i = 0; i < len; i++)
292                 dest[i] = DecodeWithDefaultAlphabet(src[i]);
293         dest[len]=0;
294 }
295
296 void EncodeDefault (unsigned char* dest, const unsigned char* src, int len)
297 {
298         int i;
299
300         for (i = 0; i < len; i++)
301                 dest[i] = EncodeWithDefaultAlphabet(src[i]);
302         return;
303 }
304
305 #endif /* UCLINUX */
306
307 void DecodeUnicode (unsigned char* dest, const unsigned char* src, int len)
308 {
309         int i;
310         wchar_t wc;
311
312         for (i = 0; i < len; i++) {
313           wc = src[(2*i)+1] | (src[2*i] << 8);
314           dest[i] = DecodeWithUnicodeAlphabet(wc);
315         }
316         dest[len]=0;
317         return;
318 }
319
320 void EncodeUnicode (unsigned char* dest, const unsigned char* src, int len)
321 {
322         int i;
323         wchar_t wc;
324
325         for (i = 0; i < len; i++) {
326                 wc = EncodeWithUnicodeAlphabet(src[i]);
327                 dest[i*2] = (wc >> 8) &0xff;
328                 dest[(i*2)+1] = wc & 0xff;
329         }
330 }
331
332 #ifdef UCLINUX
333 static
334 #endif /* UCLINUX */
335 bool EncodeWithUTF8Alphabet(u8 mychar, u8 *ret1, u8 *ret2)
336 {
337       u8 mychar1,mychar2,mychar3,mychar4;
338       int j=0;
339       
340       mychar1=((EncodeWithUnicodeAlphabet(mychar)>>8)&0xff);
341       mychar2=EncodeWithUnicodeAlphabet(mychar)&0xff;
342       if (mychar1>0x00 || mychar2>128) {
343         mychar3=0x00;
344         mychar4=128;
345         while (true) {
346           if (mychar3==mychar1) {
347             if (mychar4+64>=mychar2) {
348                *ret1=j+0xc2;
349                *ret2=0x80+(mychar2-mychar4);
350                return true;
351             }
352           }
353           if (mychar4==192) {
354               mychar3++;
355               mychar4=0;
356           } else {
357               mychar4=mychar4+64;
358           }
359           j++;
360         }
361       }
362       return false;
363 }
364
365 #ifndef UCLINUX
366
367 void DecodeWithUTF8Alphabet(u8 mychar3, u8 mychar4, u8 *ret)
368 {
369     u8 mychar1, mychar2;
370     int j;
371     wchar_t wc;    
372         
373     mychar1=0x00;
374     mychar2=128;
375     for(j=0;j<mychar3-0xc2;j++) {
376         if (mychar2==192) {
377             mychar1++;
378             mychar2=0;
379         } else {
380             mychar2=mychar2+64;
381         }
382     }
383     mychar2=mychar2+(mychar4-0x80);
384     wc = mychar2 | (mychar1 << 8);
385     *ret=DecodeWithUnicodeAlphabet(wc);
386     j=-1;
387 }
388
389 #endif /* UCLINUX */
390
391 void EncodeUTF8 (unsigned char* dest, const unsigned char* src, int len)
392 {
393         int i,j=0,z;
394         u8 mychar1, mychar2;
395         u8 buf[7];
396         
397         for (i = 0; i < len; i++) {         
398             if (EncodeWithUTF8Alphabet(src[i],&mychar1,&mychar2)) {
399                 sprintf(buf, "=%02X=%02X",mychar1,mychar2);
400                 for (z=0;z<6;z++) dest[j++]=buf[z];
401             } else {
402                 dest[j++]=src[i];
403             }
404         }
405         dest[j++]=0;
406 }
407
408 #ifndef UCLINUX
409
410 void DecodeUTF8 (unsigned char* dest, const unsigned char* src, int len)
411 {
412         int i=0,j=0;
413         u8 mychar1, mychar2,ret;
414         
415         while (i<=len) {
416             if (len-6>=i) {
417                 /* Need to have correct chars */
418                 if (src[i]  =='=' && DecodeWithHexBinAlphabet(src[i+1])!=-1
419                                   && DecodeWithHexBinAlphabet(src[i+2])!=-1 &&
420                     src[i+3]=='=' && DecodeWithHexBinAlphabet(src[i+4])!=-1 &&
421                                      DecodeWithHexBinAlphabet(src[i+5])!=-1) {
422                     mychar1=16*DecodeWithHexBinAlphabet(src[i+1])+DecodeWithHexBinAlphabet(src[i+2]);
423                     mychar2=16*DecodeWithHexBinAlphabet(src[i+4])+DecodeWithHexBinAlphabet(src[i+5]);
424                     DecodeWithUTF8Alphabet(mychar1,mychar2,&ret);
425                     i=i+5;
426                     dest[j++]=ret;
427                 } else {
428                     dest[j++]=src[i];
429                 }   
430             } else {
431                 dest[j++]=src[i];
432             }
433             i++;
434         }
435         dest[j++]=0;
436 }
437
438 int DecodeWithHexBinAlphabet (unsigned char mychar) {
439     if (mychar>='A' && mychar<='F') return mychar-'A'+10;
440     if (mychar>='a' && mychar<='f') return mychar-'a'+10;
441     if (mychar>='0' && mychar<='9') return mychar-'0';
442     return -1;
443 }
444
445 unsigned char EncodeWithHexBinAlphabet (int digit) {
446   if (digit >= 0 && digit <= 9) return '0'+(digit);
447   if (digit >=10 && digit <=15) return 'A'+(digit-10);
448   return 0;
449 }
450
451 void DecodeHexBin (unsigned char* dest, const unsigned char* src, int len)
452 {
453         int i,current=0;
454
455         for (i = 0; i < len/2 ; i++) {
456           dest[current++]=DecodeWithHexBinAlphabet(src[i*2])*16+
457                           DecodeWithHexBinAlphabet(src[i*2+1]);
458         }
459         dest[current++]=0;
460 }
461
462 void EncodeHexBin (unsigned char* dest, const unsigned char* src, int len)
463 {
464         int i,current=0;
465
466         for (i = 0; i < len; i++) {
467            dest[current++]=EncodeWithHexBinAlphabet(src[i] >> 0x04);
468            dest[current++]=EncodeWithHexBinAlphabet(src[i] & 0x0f);
469         }
470 }
471
472 void DecodeBCD (unsigned char* dest, const unsigned char* src, int len)
473 {
474         int i,current=0,digit;
475
476         for (i = 0; i < len; i++) {
477                 digit=src[i] & 0x0f;
478                 if (digit<10) dest[current++]=digit + '0';
479                 digit=src[i] >> 4;
480                 if (digit<10) dest[current++]=digit + '0';
481         }
482         dest[current++]=0;
483 }
484
485 void EncodeBCD (unsigned char* dest, const unsigned char* src, int len, bool fill)
486 {
487         int i,current=0;
488
489         for (i = 0; i < len; i++) {
490            if (i & 0x01) {
491              dest[current]=dest[current] | ((src[i]-'0') << 4);
492              current++;
493            } else {
494              dest[current]=src[i]-'0';
495            }
496         }
497
498         /* When fill is set: we fill in the most significant bits of the
499            last byte with 0x0f (1111 binary) if the number is represented
500            with odd number of digits. */
501         if (fill && (len & 0x01)) {
502              dest[current]=dest[current] | 0xf0;
503         }
504 }
505
506 unsigned char EncodeWithBCDAlphabet(int value)
507 {
508   return ((value%10) << 4) | ((value/10) & 0xf);
509 }
510
511 int DecodeWithBCDAlphabet(unsigned char value)
512 {
513         return 10*(value & 0x0f)+(value >> 4);
514 }
515
516 #endif /* UCLINUX */