LDFLAGS -> LDLIBS
[gnokii.git] / common / gsm-bitmaps.c
1 /*
2
3   G N O K I I
4
5   A Linux/Unix toolset and driver for Nokia mobile phones.
6
7   Copyright (C) 1999, 2000 Hugh Blemings & Pavel Janík ml. 
8
9   Released under the terms of the GNU GPL, see file COPYING for more details.
10         
11   Functions for common bitmap operations.
12  
13   Last modified: Sat 18 Nov 2000 by Chris Kemp
14
15 */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <ctype.h>
21 #include <sys/stat.h>
22
23 #include "gsm-common.h"
24 #include "gsm-bitmaps.h"
25 #include "gsm-api.h"
26
27 /* A few useful functions for bitmaps */
28
29 void GSM_SetPointBitmap(GSM_Bitmap *bmp, int x, int y)
30 {
31         if (bmp->type == GSM_StartupLogo) bmp->bitmap[((y/8)*bmp->width)+x] |= 1 << (y%8);
32         if (bmp->type == GSM_OperatorLogo || bmp->type == GSM_CallerLogo) bmp->bitmap[(y*bmp->width+x)/8] |= 1 << (7-((y*bmp->width+x)%8));
33
34         /* Testing only! */
35         if (bmp->type == GSM_PictureImage) bmp->bitmap[9*y + (x/8)] |= 1 << (7-(x%8));
36 }
37
38 void GSM_ClearPointBitmap(GSM_Bitmap *bmp, int x, int y)
39 {
40         if (bmp->type == GSM_StartupLogo) bmp->bitmap[((y/8)*bmp->width)+x] &= 255 - (1 << (y%8));
41         if (bmp->type == GSM_OperatorLogo || bmp->type == GSM_CallerLogo) bmp->bitmap[(y*bmp->width+x)/8] &= 255 - (1 << (7-((y*bmp->width+x)%8)));
42
43         /* Testing only ! */
44         if (bmp->type == GSM_PictureImage) bmp->bitmap[9*y + (x/8)] &= 255 - (1 << (7-(x%8)));
45 }
46
47 bool GSM_IsPointBitmap(GSM_Bitmap *bmp, int x, int y)
48 {
49         int i = 0;
50
51         if (bmp->type == GSM_StartupLogo) i = (bmp->bitmap[((y/8)*bmp->width) + x] & 1<<((y%8)));
52         if (bmp->type == GSM_OperatorLogo || bmp->type == GSM_CallerLogo)
53                 i = (bmp->bitmap[(y*bmp->width+x)/8] & 1 << (7-((y*bmp->width+x)%8)));
54         /* Testing only ! */
55         if (bmp->type == GSM_PictureImage) i = (bmp->bitmap[9*y + (x/8)] & 1<<(7-(x%8)));
56  
57         if (i) return true;
58         else return false;
59 }
60
61 void GSM_ClearBitmap(GSM_Bitmap *bmp)
62 {
63         int i;
64
65         for (i = 0; i < bmp->size; i++) bmp->bitmap[i] = 0;
66 }
67
68
69 void GSM_ResizeBitmap(GSM_Bitmap *bitmap, GSM_Bitmap_Types target, GSM_Information *info)
70 {
71         GSM_Bitmap backup;
72         int x,y,copywidth,copyheight;
73
74         /* Copy into the backup */
75         memcpy(&backup,bitmap,sizeof(GSM_Bitmap));
76       
77         if (target==GSM_StartupLogo) {
78                 bitmap->width=info->StartupLogoW;
79                 bitmap->height=info->StartupLogoH;
80                 bitmap->size=((bitmap->height/8)+(bitmap->height%8>0))*bitmap->width;
81         }
82         if (target==GSM_OperatorLogo) {
83                 bitmap->width=info->OpLogoW;
84                 bitmap->height=info->OpLogoH;
85                 x=bitmap->width*bitmap->height;
86                 bitmap->size=(x/8)+(x%8>0);
87         }
88         if (target==GSM_CallerLogo) {
89                 bitmap->width=info->CallerLogoW;
90                 bitmap->height=info->CallerLogoH;
91                 x=bitmap->width*bitmap->height;
92                 bitmap->size=(x/8)+(x%8>0);
93         }
94         if (target==GSM_PictureImage) {
95                 bitmap->width=72;
96                 bitmap->height=28;
97                 bitmap->size=bitmap->width*bitmap->height/8;
98         }
99         bitmap->type=target;
100
101         if (backup.width>bitmap->width) {
102                 copywidth=bitmap->width;
103 #ifdef DEBUG
104                 fprintf(stdout,_("We lost some part of image - it's cut (width from %i to %i) !\n"),backup.width,bitmap->width);
105 #endif /* DEBUG */
106         } else copywidth=backup.width;
107
108         if (backup.height>bitmap->height) {
109                 copyheight=bitmap->height;
110 #ifdef DEBUG
111                 fprintf(stdout,_("We lost some part of image - it's cut (height from %i to %i) !\n"),backup.height,bitmap->height);
112 #endif /* DEBUG */
113         } else copyheight=backup.height;
114   
115
116         GSM_ClearBitmap(bitmap);
117   
118         for (y=0;y<copyheight;y++) {
119                 for (x=0;x<copywidth;x++)
120                         if (GSM_IsPointBitmap(&backup,x,y)) GSM_SetPointBitmap(bitmap,x,y);
121         }
122 }
123
124 void GSM_PrintBitmap(GSM_Bitmap *bitmap)
125 {
126         int x, y;
127
128         for (y = 0; y < bitmap->height; y++) {
129                 for (x = 0; x < bitmap->width; x++) {
130                         if (GSM_IsPointBitmap(bitmap, x, y)) {
131                                 fprintf(stdout, "#");
132                         } else {
133                                 fprintf(stdout, " ");
134                         }
135                 }
136                 fprintf(stdout, "\n");
137         }
138 }
139
140
141 GSM_Error GSM_ReadSMSBitmap(int type, char *message, char *code, GSM_Bitmap *bitmap)
142 {
143         int offset = 0;
144
145         switch (type) {
146         case SMS_OpLogo:
147                 if (!code) return GE_UNKNOWN;
148
149                 bitmap->type = SMS_OpLogo;
150
151                 bitmap->netcode[0] = '0' + (message[0] & 0x0f);
152                 bitmap->netcode[1] = '0' + (message[0] >> 4);
153                 bitmap->netcode[2] = '0' + (message[1] & 0x0f);
154                 bitmap->netcode[3] = ' ';
155                 bitmap->netcode[4] = '0' + (message[2] & 0x0f);
156                 bitmap->netcode[5] = '0' + (message[2] >> 4);
157                 bitmap->netcode[6] = 0;
158
159                 break;
160         case SMS_CallerIDLogo:
161                 bitmap->type = SMS_CallerIDLogo;
162                 break;
163         case SMS_Picture:
164                 offset = 2;
165                 bitmap->type = GSM_PictureImage;
166                 break;
167         default: /* error */
168                 return GE_UNKNOWN;
169                 break;
170         }
171         bitmap->width = message[0];
172         bitmap->height = message[1];
173   
174         bitmap->size = (bitmap->width * bitmap->height) / 8;
175         memcpy(bitmap->bitmap, message + offset + 2, bitmap->size);
176
177         dprintf("Bitmap from SMS: width %i, height %i\n", bitmap->width, bitmap->height);
178
179         return GE_NONE;
180 }
181
182
183 /* Returns message length */
184
185 int GSM_SaveSMSBitmap(GSM_SMSMessage *message, GSM_Bitmap *bitmap)
186 {
187         int current=0;
188   
189         char UserDataHeader[7] = {      0x06, /* UDH Length */
190                                         0x05, /* IEI: application port addressing scheme, 16 bit address */
191                                         0x04, /* IEI length */
192                                         0x15, /* destination address: high byte */
193                                         0x00, /* destination address: low byte */
194                                         0x00, /* originator address */
195                                         0x00};
196
197         char Data[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
198   
199         /* Default settings for SMS message:
200            - no delivery report
201            - Class Message 1
202            - no compression
203            - 8 bit data
204            - SMSC no. 1
205            - validity 3 days
206            - set UserDataHeaderIndicator
207         */
208
209         message->Status = SMS_Sent;
210         /* Data Coding Scheme */
211         message->DCS.Type = SMS_GeneralDataCoding;
212         message->DCS.u.General.Class = 2;
213         message->DCS.u.General.Compressed = false;
214         message->DCS.u.General.Alphabet = SMS_8bit;
215
216
217         message->MessageCenter.No = 1;
218         message->Validity.VPF = SMS_RelativeFormat;
219         message->Validity.u.Relative = 4320; /* 4320 minutes == 72 hours */
220         message->ReplyViaSameSMSC = false;
221
222         switch (bitmap->type) {
223         case GSM_OperatorLogo:
224                 message->UDH[0].Type = SMS_OpLogo;
225                 UserDataHeader[4] = 0x82; /* NBS port 0x1582 */
226       
227                 /* Set the network code */
228                 Data[current++] = ((bitmap->netcode[1] & 0x0f) << 4) | (bitmap->netcode[0] & 0xf);
229                 Data[current++] = 0xf0 | (bitmap->netcode[2] & 0x0f);
230                 Data[current++] = ((bitmap->netcode[5] & 0x0f) << 4) | (bitmap->netcode[4] & 0xf);
231
232                 break;
233         case GSM_CallerLogo:
234                 message->UDH[0].Type = SMS_CallerIDLogo;
235                 UserDataHeader[4] = 0x83; /* NBS port 0x1583 */
236                 break;
237         default: /* error */
238                 break;
239         }
240         
241         /* Set the logo size */
242         current++;
243         Data[current++] = bitmap->width;
244         Data[current++] = bitmap->height;
245
246         Data[current++] = 0x01;
247
248         memcpy(message->MessageText, UserDataHeader, 7);
249         memcpy(message->MessageText, Data, current);
250         memcpy(message->MessageText+current, bitmap->bitmap, bitmap->size);
251
252         return current;
253 }