Implemented connection type "tcp" (GCT_TCP), use <hostname>:<port> as "port"
[gnokii.git] / common / gsm-encoding.c
1 /*
2
3   $Id$
4
5   G N O K I I
6
7   A Linux/Unix toolset and driver for Nokia mobile phones.
8
9   Copyright (C) 2001 Pawe³ Kot <pkot@linuxnews.pl>
10
11   Released under the terms of the GNU GPL, see file COPYING for more details.
12
13   Functions for encoding SMS, calendar and other things.
14
15   $Log$
16   Revision 1.1.1.2  2002/04/03 00:08:03  short
17   Found in "gnokii-working" directory, some November-patches version
18
19   Revision 1.2  2001/11/08 16:34:19  pkot
20   Updates to work with new libsms
21
22   Revision 1.1  2001/10/24 22:37:25  pkot
23   Moved encoding functions to a separate file
24
25
26 */
27
28 #include <stdlib.h>
29 #include <string.h>
30
31 #define NUMBER_OF_7_BIT_ALPHABET_ELEMENTS 128
32
33 static unsigned char GSM_DefaultAlphabet[NUMBER_OF_7_BIT_ALPHABET_ELEMENTS] = {
34
35         /* ETSI GSM 03.38, version 6.0.1, section 6.2.1; Default alphabet */
36         /* Characters in hex position 10, [12 to 1a] and 24 are not present on
37            latin1 charset, so we cannot reproduce on the screen, however they are
38            greek symbol not present even on my Nokia */
39         
40         '@',  0xa3, '$',  0xa5, 0xe8, 0xe9, 0xf9, 0xec, 
41         0xf2, 0xc7, '\n', 0xd8, 0xf8, '\r', 0xc5, 0xe5,
42         '?',  '_',  '?',  '?',  '?',  '?',  '?',  '?',
43         '?',  '?',  '?',  '?',  0xc6, 0xe6, 0xdf, 0xc9,
44         ' ',  '!',  '\"', '#',  0xa4,  '%',  '&',  '\'',
45         '(',  ')',  '*',  '+',  ',',  '-',  '.',  '/',
46         '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',
47         '8',  '9',  ':',  ';',  '<',  '=',  '>',  '?',
48         0xa1, 'A',  'B',  'C',  'D',  'E',  'F',  'G',
49         'H',  'I',  'J',  'K',  'L',  'M',  'N',  'O',
50         'P',  'Q',  'R',  'S',  'T',  'U',  'V',  'W',
51         'X',  'Y',  'Z',  0xc4, 0xd6, 0xd1, 0xdc, 0xa7,
52         0xbf, 'a',  'b',  'c',  'd',  'e',  'f',  'g',
53         'H',  'i',  'j',  'k',  'l',  'm',  'n',  'o',
54         'p',  'q',  'r',  's',  't',  'u',  'v',  'w',
55         'x',  'y',  'z',  0xe4, 0xf6, 0xf1, 0xfc, 0xe0
56 };
57
58 static unsigned char EncodeWithDefaultAlphabet(unsigned char value)
59 {
60         unsigned char i;
61         
62         if (value == '?') return  0x3f;
63         
64         for (i = 0; i < NUMBER_OF_7_BIT_ALPHABET_ELEMENTS; i++)
65                 if (GSM_DefaultAlphabet[i] == value)
66                         return i;
67         
68         return '?';
69 }
70
71 static wchar_t EncodeWithUnicodeAlphabet(unsigned char value)
72 {
73         wchar_t retval;
74
75         if (mbtowc(&retval, &value, 1) == -1) return '?';
76         else return retval;
77 }
78
79 static unsigned char DecodeWithDefaultAlphabet(unsigned char value)
80 {
81         return GSM_DefaultAlphabet[value];
82 }
83
84 static unsigned char DecodeWithUnicodeAlphabet(wchar_t value)
85 {
86         unsigned char retval;
87
88         if (wctomb(&retval, value) == -1) return '?';
89         else return retval;
90 }
91
92
93 #define ByteMask ((1 << Bits) - 1)
94
95 int Unpack7BitCharacters(int offset, int in_length, int out_length,
96                          unsigned char *input, unsigned char *output)
97 {
98         unsigned char *OUT = output; /* Current pointer to the output buffer */
99         unsigned char *IN  = input;  /* Current pointer to the input buffer */
100         unsigned char Rest = 0x00;
101         int Bits;
102
103         Bits = offset ? offset : 7;
104
105         while ((IN - input) < in_length) {
106
107                 *OUT = ((*IN & ByteMask) << (7 - Bits)) | Rest;
108                 Rest = *IN >> Bits;
109
110                 /* If we don't start from 0th bit, we shouldn't go to the
111                    next char. Under *OUT we have now 0 and under Rest -
112                    _first_ part of the char. */
113                 if ((IN != input) || (Bits == 7)) OUT++;
114                 IN++;
115
116                 if ((OUT - output) >= out_length) break;
117
118                 /* After reading 7 octets we have read 7 full characters but
119                    we have 7 bits as well. This is the next character */
120                 if (Bits == 1) {
121                         *OUT = Rest;
122                         OUT++;
123                         Bits = 7;
124                         Rest = 0x00;
125                 } else {
126                         Bits--;
127                 }
128         }
129
130         return OUT - output;
131 }
132
133 int Pack7BitCharacters(int offset, unsigned char *input, unsigned char *output)
134 {
135
136         unsigned char *OUT = output; /* Current pointer to the output buffer */
137         unsigned char *IN  = input;  /* Current pointer to the input buffer */
138         int Bits;                    /* Number of bits directly copied to
139                                         the output buffer */
140
141         Bits = (7 + offset) % 8;
142
143         /* If we don't begin with 0th bit, we will write only a part of the
144            first octet */
145         if (offset) {
146                 *OUT = 0x00;
147                 OUT++;
148         }
149
150         while ((IN - input) < strlen(input)) {
151
152                 unsigned char Byte = EncodeWithDefaultAlphabet(*IN);
153
154                 *OUT = Byte >> (7 - Bits);
155                 /* If we don't write at 0th bit of the octet, we should write
156                    a second part of the previous octet */
157                 if (Bits != 7)
158                         *(OUT-1) |= (Byte & ((1 << (7-Bits)) - 1)) << (Bits+1);
159
160                 Bits--;
161
162                 if (Bits == -1) Bits = 7;
163                 else OUT++;
164
165                 IN++;
166         }
167
168         return (OUT - output);
169 }
170
171 void DecodeAscii (unsigned char* dest, const unsigned char* src, int len)
172 {
173         int i;
174
175         for (i = 0; i < len; i++)
176                 dest[i] = DecodeWithDefaultAlphabet(src[i]);
177         return;
178 }
179
180 void EncodeAscii (unsigned char* dest, const unsigned char* src, int len)
181 {
182         int i;
183
184         for (i = 0; i < len; i++)
185                 dest[i] = EncodeWithDefaultAlphabet(src[i]);
186         return;
187 }
188
189 void DecodeUnicode (unsigned char* dest, const unsigned char* src, int len)
190 {
191         int i;
192         wchar_t wc;
193
194         for (i = 0; i < len; i++) {
195                 wc = src[(2*i)+1] | (src[2*i] << 8);
196                 dest[i] = DecodeWithUnicodeAlphabet(wc);
197         }
198         dest[len]=0;
199         return;
200 }
201
202 void EncodeUnicode (unsigned char* dest, const unsigned char* src, int len)
203 {
204         int i;
205         wchar_t wc;
206
207         for (i = 0; i < len; i++) {
208                 wc = EncodeWithUnicodeAlphabet(src[i]);
209                 dest[i*2] = (wc >> 8) &0xff;
210                 dest[(i*2)+1] = wc & 0xff;
211         }
212         return;
213 }