summaryrefslogtreecommitdiffabout
path: root/gammu/emb/common/service/sms/gsmems.c
Unidiff
Diffstat (limited to 'gammu/emb/common/service/sms/gsmems.c') (more/less context) (ignore whitespace changes)
-rw-r--r--gammu/emb/common/service/sms/gsmems.c765
1 files changed, 765 insertions, 0 deletions
diff --git a/gammu/emb/common/service/sms/gsmems.c b/gammu/emb/common/service/sms/gsmems.c
new file mode 100644
index 0000000..a7e20f4
--- a/dev/null
+++ b/gammu/emb/common/service/sms/gsmems.c
@@ -0,0 +1,765 @@
1/* (c) 2002-2004 by Marcin Wiacek */
2
3#include <ctype.h>
4#include <string.h>
5#include <time.h>
6
7#include "../../gsmcomon.h"
8#include "../../misc/coding/coding.h"
9#include "../gsmcal.h"
10#include "../gsmpbk.h"
11#include "../gsmlogo.h"
12#include "../gsmring.h"
13#include "../gsmdata.h"
14#include "../gsmnet.h"
15#include "gsmsms.h"
16#include "gsmmulti.h"
17
18/* EMS Developers' Guidelines from www.sonyericsson.com
19 * docs from Alcatel
20 */
21 GSM_Error GSM_EncodeEMSMultiPartSMS(GSM_MultiPartSMSInfo *Info,
22 GSM_MultiSMSMessage *SMS,
23 GSM_UDH UDHType)
24{
25 unsigned char Buffer[GSM_MAX_SMS_LENGTH*2*MAX_MULTI_SMS];
26 int i,UsedText,j,Length,Width,Height,z,x,y;
27 unsigned int Len;
28 int Used,FreeText,FreeBytes,Width2,CopiedText,CopiedSMSText;
29 unsigned char UDHID;
30 GSM_Bitmap Bitmap,Bitmap2;
31 GSM_Ringtone Ring;
32 GSM_Coding_Type Coding = SMS_Coding_Default;
33 GSM_Phone_Bitmap_TypesBitmapType;
34 MultiPartSMSEntry *Entry;
35 bool start;
36 GSM_DateTime Date;
37
38#ifdef DEBUG
39 if (UDHType != UDH_NoUDH) dbgprintf("linked EMS\n");
40#endif
41
42 if (Info->UnicodeCoding) Coding = SMS_Coding_Unicode;
43
44 /* Cleaning on the start */
45 for (i=0;i<MAX_MULTI_SMS;i++) {
46 GSM_SetDefaultSMSData(&SMS->SMS[i]);
47 SMS->SMS[i].UDH.Type = UDHType;
48 GSM_EncodeUDHHeader(&SMS->SMS[i].UDH);
49 SMS->SMS[i].Coding = Coding;
50 }
51
52 /* Packing */
53 for (i=0;i<Info->EntriesNum;i++) {
54 Entry = &Info->Entries[i];
55
56 switch (Entry->ID) {
57 case SMS_ConcatenatedTextLong:
58 case SMS_ConcatenatedTextLong16bit:
59 Len = 0;
60 while(1) {
61 if (Entry->Left || Entry->Right ||
62 Entry->Center || Entry->Large ||
63 Entry->Small || Entry->Bold ||
64 Entry->Italic || Entry->Underlined ||
65 Entry->Strikethrough) {
66 Buffer[0] = 0x0A;/* ID for text format */
67 Buffer[1] = 0x03; /* length of rest*/
68 Buffer[2] = 0x00; /* Position in EMS msg*/
69 Buffer[3] = 0x00; /* how many chars */
70 Buffer[4] = 0x00; /* formatting bits*/
71 if (Entry->Left) {
72 } else if (Entry->Right) {Buffer[4] |= 1;
73 } else if (Entry->Center) {Buffer[4] |= 2;
74 } else Buffer[4] |= 3;
75 if (Entry->Large) { Buffer[4] |= 4;
76 } else if (Entry->Small) {Buffer[4] |= 8;}
77 if (Entry->Bold) Buffer[4] |= 16;
78 if (Entry->Italic) Buffer[4] |= 32;
79 if (Entry->Underlined) Buffer[4] |= 64;
80 if (Entry->Strikethrough) Buffer[4] |= 128;
81 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,5,true,&UsedText,&CopiedText,&CopiedSMSText);
82 GSM_Find_Free_Used_SMS2(Coding,SMS->SMS[SMS->Number], &UsedText, &FreeText, &FreeBytes);
83 if (FreeText == 0) continue;
84 }
85 GSM_AddSMS_Text_UDH(SMS,Coding,Entry->Buffer+Len*2,UnicodeLength(Entry->Buffer) - Len,false,&UsedText,&CopiedText,&CopiedSMSText);
86 if (Entry->Left || Entry->Right ||
87 Entry->Center || Entry->Large ||
88 Entry->Small || Entry->Bold ||
89 Entry->Italic || Entry->Underlined ||
90 Entry->Strikethrough) {
91 SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-3] = UsedText;
92 SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-2] = CopiedSMSText;
93 }
94 Len += CopiedText;
95 if (Len == UnicodeLength(Entry->Buffer)) break;
96 dbgprintf("%i %i\n",Len,UnicodeLength(Entry->Buffer));
97 }
98 break;
99 case SMS_EMSPredefinedSound:
100 case SMS_EMSPredefinedAnimation:
101 if (Entry->ID == SMS_EMSPredefinedSound) {
102 Buffer[0] = 0x0B; /* ID for def.sound*/
103 } else {
104 Buffer[0] = 0x0D; /* ID for def.animation*/
105 }
106 Buffer[1] = 0x02; /* Length of rest */
107 Buffer[2] = 0x00; /* Position in EMS msg*/
108 Buffer[3] = Entry->Number; /* Number of anim.*/
109 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,4,true,&UsedText,&CopiedText,&CopiedSMSText);
110 SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-2] = UsedText;
111 break;
112 case SMS_EMSSonyEricssonSound:
113 case SMS_EMSSound10:
114 case SMS_EMSSound12:
115 if (Entry->Protected) {
116 Buffer[0] = 0x17; /* ID for ODI */
117 Buffer[1] = 2; /* Length of rest */
118 Buffer[2] = 1; /* Number of protected objects */
119 Buffer[3] = 1; /* 1=Protected,0=Not protected */
120 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,4,true,&UsedText,&CopiedText,&CopiedSMSText);
121 }
122
123 Length = 128; /* 128 bytes is maximal length from specs */
124 switch (Entry->ID) {
125 case SMS_EMSSound10:
126 Entry->RingtoneNotes = GSM_EncodeEMSSound(*Entry->Ringtone, Buffer+3, &Length, 1.0, true);
127 break;
128 case SMS_EMSSound12:
129 Entry->RingtoneNotes = GSM_EncodeEMSSound(*Entry->Ringtone, Buffer+3, &Length, 1.2, true);
130 break;
131 case SMS_EMSSonyEricssonSound:
132 Entry->RingtoneNotes = GSM_EncodeEMSSound(*Entry->Ringtone, Buffer+3, &Length, 0, true);
133 break;
134 default:
135 break;
136 }
137
138 Buffer[0] = 0x0C; /* ID for EMS sound */
139 Buffer[1] = Length+1; /* Length of rest */
140 Buffer[2] = 0x00; /* Position in EMS msg */
141 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,Length+3,true,&UsedText,&CopiedText,&CopiedSMSText);
142 SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-Length-1] = UsedText;
143 break;
144 case SMS_EMSSonyEricssonSoundLong:
145 case SMS_EMSSound10Long:
146 case SMS_EMSSound12Long:
147 Ring = *Entry->Ringtone;
148
149 /* First check if we can use classic format */
150 Length = 128; /* 128 bytes is maximal length from specs */
151 switch (Entry->ID) {
152 case SMS_EMSSound10Long:
153 Entry->RingtoneNotes = GSM_EncodeEMSSound(Ring, Buffer+3, &Length, 1.0, true);
154 break;
155 case SMS_EMSSound12Long:
156 Entry->RingtoneNotes = GSM_EncodeEMSSound(Ring, Buffer+3, &Length, 1.2, true);
157 break;
158 case SMS_EMSSonyEricssonSoundLong:
159 Entry->RingtoneNotes = GSM_EncodeEMSSound(Ring, Buffer+3, &Length, 0, true);
160 break;
161 default:
162 break;
163 }
164 if (Entry->RingtoneNotes == Ring.NoteTone.NrCommands) {
165 if (Entry->Protected) {
166 Buffer[0] = 0x17; /* ID for ODI */
167 Buffer[1] = 2; /* Length of rest */
168 Buffer[2] = 1; /* Number of protected objects */
169 Buffer[3] = 1; /* 1=Protected,0=Not protected */
170 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,4,true,&UsedText,&CopiedText,&CopiedSMSText);
171 }
172
173 Buffer[0] = 0x0C; /* ID for EMS sound */
174 Buffer[1] = Length+1; /* Length of rest */
175 Buffer[2] = 0x00; /* Position in EMS msg */
176 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,Length+3,true,&UsedText,&CopiedText,&CopiedSMSText);
177 SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-Length-1] = UsedText;
178 break;
179 }
180
181 /* Find free place in first SMS */
182 GSM_Find_Free_Used_SMS2(Coding,SMS->SMS[SMS->Number], &UsedText, &FreeText, &FreeBytes);
183 Length = FreeBytes - 3;
184 if (Entry->Protected) Length = Length - 4;
185 if (Length < 0) Length = 128;
186 if (Length > 128) Length = 128;
187
188 Ring = *Entry->Ringtone;
189
190 /* Checking number of SMS */
191 Used = 0;
192 FreeBytes = 0;
193 start = true;
194 while (1) {
195 if (FreeBytes != 0) {
196 z = 0;
197 for (j=FreeBytes;j<Ring.NoteTone.NrCommands;j++) {
198 Ring.NoteTone.Commands[z] = Ring.NoteTone.Commands[j];
199 z++;
200 }
201 Ring.NoteTone.NrCommands -= FreeBytes;
202 if (Ring.NoteTone.NrCommands == 0) break;
203 Length = 128; /* 128 bytes is maximal length from specs */
204 }
205 switch (Entry->ID) {
206 case SMS_EMSSound10Long:
207 FreeBytes = GSM_EncodeEMSSound(Ring, Buffer+3, &Length, 1.0, start);
208 break;
209 case SMS_EMSSound12Long:
210 FreeBytes = GSM_EncodeEMSSound(Ring, Buffer+3, &Length, 1.2, start);
211 break;
212 case SMS_EMSSonyEricssonSoundLong:
213 FreeBytes = GSM_EncodeEMSSound(Ring, Buffer+3, &Length, 0, start);
214 break;
215 default:
216 break;
217 }
218 start = false;
219 Used++;
220 }
221 dbgprintf("Used SMS: %i\n",Used);
222
223 if (Entry->Protected) {
224 Buffer[0] = 0x17; /* ID for ODI */
225 Buffer[1] = 2; /* Length of rest */
226 Buffer[2] = Used+1; /* Number of protected objects */
227 Buffer[3] = 1; /* 1=Protected,0=Not protected */
228 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,4,true,&UsedText,&CopiedText,&CopiedSMSText);
229 }
230
231 /* Save UPI UDH */
232 Buffer[0] = 0x13; /* ID for UPI */
233 Buffer[1] = 1; /* Length of rest */
234 Buffer[2] = Used; /* Number of used parts*/
235 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,3,true,&UsedText,&CopiedText,&CopiedSMSText);
236
237 /* Find free place in first SMS */
238 GSM_Find_Free_Used_SMS2(Coding,SMS->SMS[SMS->Number], &UsedText, &FreeText, &FreeBytes);
239 Length = FreeBytes - 3;
240 if (Length < 0) Length = 128;
241 if (Length > 128) Length = 128;
242
243 Ring = *Entry->Ringtone;
244
245 /* Saving */
246 FreeBytes = 0;
247 start = true;
248 while (1) {
249 if (FreeBytes != 0) {
250 z = 0;
251 for (j=FreeBytes;j<Ring.NoteTone.NrCommands;j++) {
252 Ring.NoteTone.Commands[z] = Ring.NoteTone.Commands[j];
253 z++;
254 }
255 Ring.NoteTone.NrCommands -= FreeBytes;
256 if (Ring.NoteTone.NrCommands == 0) break;
257 Length = 128; /* 128 bytes is maximal length from specs */
258 }
259 switch (Entry->ID) {
260 case SMS_EMSSound10Long:
261 FreeBytes = GSM_EncodeEMSSound(Ring, Buffer+3, &Length, 1.0, start);
262 break;
263 case SMS_EMSSound12Long:
264 FreeBytes = GSM_EncodeEMSSound(Ring, Buffer+3, &Length, 1.2, start);
265 break;
266 case SMS_EMSSonyEricssonSoundLong:
267 FreeBytes = GSM_EncodeEMSSound(Ring, Buffer+3, &Length, 0, start);
268 break;
269 default:
270 break;
271 }
272 Buffer[0] = 0x0C; /* ID for EMS sound */
273 Buffer[1] = Length+1; /* Length of rest */
274 Buffer[2] = 0x00; /* Position in EMS msg */
275 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,Length+3,true,&UsedText,&CopiedText,&CopiedSMSText);
276 SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-Length-1] = UsedText;
277 start = false;
278 }
279
280 Entry->RingtoneNotes = Entry->Ringtone->NoteTone.NrCommands;
281
282 break;
283 case SMS_EMSAnimation:
284 if (Entry->Protected) {
285 Buffer[0] = 0x17; /* ID for ODI */
286 Buffer[1] = 2; /* Length of rest */
287 Buffer[2] = 1; /* Number of protected objects */
288 Buffer[3] = 1; /* 1=Protected,0=Not protected */
289 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,4,true,&UsedText,&CopiedText,&CopiedSMSText);
290 }
291
292 if (Entry->Bitmap->Bitmap[0].BitmapWidth > 8 || Entry->Bitmap->Bitmap[0].BitmapHeight > 8) {
293 BitmapType = GSM_EMSMediumPicture;/* Bitmap 16x16 */
294 Buffer[0] = 0x0E; /* ID for 16x16 animation */
295 } else {
296 BitmapType = GSM_EMSSmallPicture;/* Bitmap 8x8 */
297 Buffer[0] = 0x0F; /* ID for 8x8 animation */
298 }
299 Length = PHONE_GetBitmapSize(BitmapType,0,0);
300
301 Buffer[1] = Length*Entry->Bitmap->Number + 1; /* Length of rest */
302 Buffer[2] = 0x00; /* Position in EMS msg */
303 for (j=0;j<Entry->Bitmap->Number;j++) {
304 PHONE_EncodeBitmap(BitmapType, Buffer+3+j*Length, &Entry->Bitmap->Bitmap[j]);
305 }
306 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,3+Length*Entry->Bitmap->Number,true,&UsedText,&CopiedText,&CopiedSMSText);
307 SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-1-Length*Entry->Bitmap->Number] = UsedText;
308 break;
309 case SMS_EMSFixedBitmap:
310 if (Entry->Protected) {
311 Buffer[0] = 0x17; /* ID for ODI */
312 Buffer[1] = 2; /* Length of rest */
313 Buffer[2] = 1; /* Number of protected objects */
314 Buffer[3] = 1; /* 1=Protected,0=Not protected */
315 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,4,true,&UsedText,&CopiedText,&CopiedSMSText);
316 }
317
318 if (Entry->Bitmap->Bitmap[0].BitmapWidth > 16 || Entry->Bitmap->Bitmap[0].BitmapHeight > 16) {
319 BitmapType = GSM_EMSBigPicture; /* Bitmap 32x32 */
320 Buffer[0] = 0x10; /* ID for EMS bitmap*/
321 } else {
322 BitmapType = GSM_EMSMediumPicture; /* Bitmap 16x16 */
323 Buffer[0] = 0x11; /* ID for EMS bitmap*/
324 }
325 Length = PHONE_GetBitmapSize(BitmapType,0,0);
326 PHONE_GetBitmapWidthHeight(BitmapType, &Width, &Height);
327
328 Buffer[1] = Length + 1; /* Length of rest */
329 Buffer[2] = 0x00; /* Position in EMS msg*/
330 PHONE_EncodeBitmap(BitmapType,Buffer+3, &Entry->Bitmap->Bitmap[0]);
331 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,3+Length,true,&UsedText,&CopiedText,&CopiedSMSText);
332 SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-1-Length] = UsedText;
333 break;
334 case SMS_EMSVariableBitmapLong:
335 BitmapType = GSM_EMSVariablePicture;
336 Width = Entry->Bitmap->Bitmap[0].BitmapWidth;
337 Height = Entry->Bitmap->Bitmap[0].BitmapHeight;
338 Bitmap = Entry->Bitmap->Bitmap[0];
339
340 /* First check if we can use classical format */
341 while (1) {
342 /* Width should be multiply of 8 */
343 while (Width % 8 != 0) Width--;
344
345 /* specs */
346 if (Width <= 96 && Height <= 128) break;
347
348 Height--;
349 }
350 Length = PHONE_GetBitmapSize(BitmapType,Width,Height);
351 if (Length <= 128) {
352 if (Entry->Protected) {
353 Buffer[0] = 0x17; /* ID for ODI */
354 Buffer[1] = 2; /* Length of rest */
355 Buffer[2] = 1; /* Number of protected objects */
356 Buffer[3] = 1; /* 1=Protected,0=Not protected */
357 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,4,true,&UsedText,&CopiedText,&CopiedSMSText);
358 }
359
360 Buffer[0] = 0x12; /* ID for EMS bitmap*/
361 Buffer[1] = Length + 3; /* Length of rest */
362 Buffer[2] = 0x00; /* Position in EMS msg*/
363 Buffer[3] = Width/8; /* Bitmap width/8 */
364 Buffer[4] = Height; /* Bitmap height */
365
366 GSM_ResizeBitmap(&Bitmap, &Entry->Bitmap->Bitmap[0], Width, Height);
367#ifdef DEBUG
368 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,&Bitmap);
369#endif
370 PHONE_EncodeBitmap(BitmapType,Buffer+5, &Bitmap);
371 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,5+Length,true,&UsedText,&CopiedText,&CopiedSMSText);
372 SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-3-Length] = UsedText;
373 break;
374 }
375
376 /* Find free place in first SMS */
377 GSM_Find_Free_Used_SMS2(Coding,SMS->SMS[SMS->Number], &UsedText, &FreeText, &FreeBytes);
378 Used = 0;
379 Length = FreeBytes - 3;
380 if (Entry->Protected)Length = Length - 4;
381 if (Length < 0) Length = 128;
382 if (Length > 128) Length = 128;
383
384 /* Checking number of SMS */
385 FreeBytes = 0;
386 while (FreeBytes != Width) {
387 Width2 = 8;
388 while (FreeBytes + Width2 != Width) {
389 if (PHONE_GetBitmapSize(BitmapType,Width2+8,Height) > Length) break;
390
391 Width2 = Width2 + 8;
392 }
393 FreeBytes = FreeBytes + Width2;
394 Length = 128;
395 Used ++;
396 }
397 dbgprintf("Used SMS: %i\n",Used);
398
399 if (Entry->Protected) {
400 Buffer[0] = 0x17; /* ID for ODI */
401 Buffer[1] = 2; /* Length of rest */
402 Buffer[2] = Used+1; /* Number of protected objects */
403 Buffer[3] = 1; /* 1=Protected,0=Not protected */
404 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,4,true,&UsedText,&CopiedText,&CopiedSMSText);
405 }
406
407 /* Save UPI UDH */
408 Buffer[0] = 0x13; /* ID for UPI */
409 Buffer[1] = 1; /* Length of rest */
410 Buffer[2] = Used; /* Number of used parts*/
411
412 /* Find free place in first SMS */
413 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,3,true,&UsedText,&CopiedText,&CopiedSMSText);
414 GSM_Find_Free_Used_SMS2(Coding,SMS->SMS[SMS->Number], &UsedText, &FreeText, &FreeBytes);
415 Length = FreeBytes - 3;
416 if (Length < 0) Length = 128;
417 if (Length > 128) Length = 128;
418
419#ifdef DEBUG
420 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,&Bitmap);
421#endif
422
423 /* Saving SMS */
424 FreeBytes = 0;
425 while (FreeBytes != Width) {
426 Width2 = 8;
427 while (FreeBytes + Width2 != Width) {
428 if (PHONE_GetBitmapSize(BitmapType,Width2+8,Height) > Length) break;
429
430 Width2 = Width2 + 8;
431 }
432
433 /* Copying part of bitmap to new structure */
434 Bitmap2.BitmapWidth = Width2;
435 Bitmap2.BitmapHeight = Height;
436 GSM_ClearBitmap(&Bitmap2);
437 for (x=0;x<Width2;x++) {
438 for (y=0;y<Height;y++) {
439 if (GSM_IsPointBitmap(&Bitmap,x+FreeBytes,y)) {
440 GSM_SetPointBitmap(&Bitmap2, x, y);
441 }
442 }
443 }
444#ifdef DEBUG
445 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,&Bitmap2);
446#endif
447
448 /* Adding new bitmap to SMS */
449 Length = PHONE_GetBitmapSize(BitmapType,Width2,Height);
450 Buffer[0] = 0x12; /* ID for EMS bitmap*/
451 Buffer[1] = Length + 3; /* Length of rest */
452 Buffer[2] = 0x00; /* Position in EMS msg*/
453 Buffer[3] = Width2/8; /* Bitmap width/8 */
454 Buffer[4] = Height; /* Bitmap height */
455 PHONE_EncodeBitmap(BitmapType,Buffer+5, &Bitmap2);
456 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,5+Length,true,&UsedText,&CopiedText,&CopiedSMSText);
457 SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-3-Length] = UsedText;
458
459 FreeBytes = FreeBytes + Width2;
460 Length = 128;
461 }
462 break;
463 case SMS_EMSVariableBitmap:
464 if (Entry->Protected) {
465 Buffer[0] = 0x17; /* ID for ODI */
466 Buffer[1] = 2; /* Length of rest */
467 Buffer[2] = 1; /* Number of protected objects */
468 Buffer[3] = 1; /* 1=Protected,0=Not protected */
469 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,4,true,&UsedText,&CopiedText,&CopiedSMSText);
470 }
471
472 BitmapType = GSM_EMSVariablePicture;
473 Width = Entry->Bitmap->Bitmap[0].BitmapWidth;
474 Height = Entry->Bitmap->Bitmap[0].BitmapHeight;
475
476 while (1) {
477 /* Width should be multiply of 8 */
478 while (Width % 8 != 0) Width--;
479
480 /* specs */
481 if (PHONE_GetBitmapSize(BitmapType,Width,Height) <= 128) break;
482
483 Height--;
484 }
485
486 Length = PHONE_GetBitmapSize(BitmapType,Width,Height);
487
488 Buffer[0] = 0x12; /* ID for EMS bitmap*/
489 Buffer[1] = Length + 3; /* Length of rest */
490 Buffer[2] = 0x00; /* Position in EMS msg*/
491 Buffer[3] = Width/8; /* Bitmap width/8 */
492 Buffer[4] = Height; /* Bitmap height */
493
494 GSM_ResizeBitmap(&Bitmap, &Entry->Bitmap->Bitmap[0], Width, Height);
495#ifdef DEBUG
496 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,&Bitmap);
497#endif
498 PHONE_EncodeBitmap(BitmapType,Buffer+5, &Bitmap);
499 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,5+Length,true,&UsedText,&CopiedText,&CopiedSMSText);
500 SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-3-Length] = UsedText;
501 break;
502 default:
503 break;
504 }
505 }
506
507 SMS->Number++;
508
509 if (UDHType == UDH_ConcatenatedMessages) {
510 UDHID = GSM_MakeSMSIDFromTime();
511 for (i=0;i<SMS->Number;i++) {
512 SMS->SMS[i].UDH.Text[2+1] = UDHID;
513 SMS->SMS[i].UDH.Text[3+1] = SMS->Number;
514 SMS->SMS[i].UDH.Text[4+1] = i+1;
515 }
516 }
517 if (UDHType == UDH_ConcatenatedMessages16bit) {
518 UDHID = GSM_MakeSMSIDFromTime();
519 GSM_GetCurrentDateTime (&Date);
520 for (i=0;i<SMS->Number;i++) {
521 SMS->SMS[i].UDH.Text[2+1] = Date.Hour;
522 SMS->SMS[i].UDH.Text[3+1] = UDHID;
523 SMS->SMS[i].UDH.Text[4+1] = SMS->Number;
524 SMS->SMS[i].UDH.Text[5+1] = i+1;
525 }
526 }
527
528#ifdef DEBUG
529 dbgprintf("SMS number is %i\n",SMS->Number);
530 for (i=0;i<SMS->Number;i++) {
531 dbgprintf("UDH length %i\n",SMS->SMS[i].UDH.Length);
532 DumpMessage(di.df, di.dl, SMS->SMS[i].UDH.Text, SMS->SMS[i].UDH.Length);
533 dbgprintf("SMS length %i\n",UnicodeLength(SMS->SMS[i].Text)*2);
534 DumpMessage(di.df, di.dl, SMS->SMS[i].Text, UnicodeLength(SMS->SMS[i].Text)*2);
535 }
536#endif
537 return ERR_NONE;
538}
539
540static bool AddEMSText(GSM_SMSMessage *SMS, GSM_MultiPartSMSInfo *Info, int *Pos, int Len)
541{
542 int BufferLen;
543
544 if (Len==0) return true;
545
546 if (Info->Entries[Info->EntriesNum].ID!=SMS_ConcatenatedTextLong &&
547 Info->Entries[Info->EntriesNum].ID!=0) {
548 (Info->EntriesNum)++;
549 }
550 BufferLen = UnicodeLength(Info->Entries[Info->EntriesNum].Buffer)*2;
551 switch (SMS->Coding) {
552 case SMS_Coding_8bit:
553 // memcpy(Info->Entries[Info->EntriesNum].Buffer+BufferLen,SMS->Text+(*Pos),Len);
554 // BufferLen+=Len;
555 // (*Pos)+=Len;
556 break;
557 case SMS_Coding_Unicode:
558 case SMS_Coding_Default:
559 Info->Entries[Info->EntriesNum].Buffer = realloc(Info->Entries[Info->EntriesNum].Buffer, BufferLen + (Len * 2) + 2);
560 if (Info->Entries[Info->EntriesNum].Buffer == NULL) return false;
561 memcpy(Info->Entries[Info->EntriesNum].Buffer + BufferLen, SMS->Text + (*Pos) *2, Len * 2);
562 BufferLen += Len * 2;
563 break;
564 }
565 (*Pos)+=Len;
566 Info->Entries[Info->EntriesNum].Buffer[BufferLen]= 0;
567 Info->Entries[Info->EntriesNum].Buffer[BufferLen+1]= 0;
568 Info->Entries[Info->EntriesNum].ID = SMS_ConcatenatedTextLong;
569 return true;
570}
571
572 bool GSM_DecodeEMSMultiPartSMS(GSM_MultiPartSMSInfo *Info,
573 GSM_MultiSMSMessage *SMS)
574{
575 int i, w, Pos, z, UPI = 1, width, height;
576 bool RetVal = false, NewPicture = true;
577 GSM_Phone_Bitmap_Types BitmapType;
578 GSM_Bitmap Bitmap,Bitmap2;
579
580 for (i=0;i<MAX_MULTI_SMS;i++) {
581 Info->Entries[i].ID = 0;
582 }
583
584 for (i=0;i<SMS->Number;i++) {
585 Pos = 0;
586 w= 1;
587 while (w < SMS->SMS[i].UDH.Length) {
588 if (Info->EntriesNum + 1 == MAX_MULTI_SMS) {
589 dbgprintf("Couldn't parse SMS, contains too many EMS parts!\n");
590 return false;
591 }
592 switch(SMS->SMS[i].UDH.Text[w]) {
593 case 0x00:
594 dbgprintf("UDH part - linked SMS with 8 bit ID\n");
595 break;
596 case 0x08:
597 dbgprintf("UDH part - linked SMS with 16 bit ID\n");
598 break;
599 // case 0x0A:
600 // dbgprintf("UDH part - EMS text formatting\n");
601 // break;
602 case 0x0B:
603 dbgprintf("UDH part - default EMS sound\n");
604 if (SMS->SMS[i].UDH.Text[w+2] > Pos) {
605 z = Pos;
606 if (!AddEMSText(&SMS->SMS[i], Info, &Pos, SMS->SMS[i].UDH.Text[w+2]-z)) return false;
607 }
608 if (Info->Entries[Info->EntriesNum].ID != 0) (Info->EntriesNum)++;
609 Info->Entries[Info->EntriesNum].Number = SMS->SMS[i].UDH.Text[w+3];
610 Info->Entries[Info->EntriesNum].ID = SMS_EMSPredefinedSound;
611 RetVal = true;
612 break;
613 // case 0x0C:
614 // dbgprintf("UDH part - EMS sound\n");
615 // break;
616 case 0x0D:
617 dbgprintf("UDH part - default EMS animation\n");
618 if (SMS->SMS[i].UDH.Text[w+2] > Pos) {
619 z = Pos;
620 if (!AddEMSText(&SMS->SMS[i], Info, &Pos, SMS->SMS[i].UDH.Text[w+2]-z)) return false;
621 }
622 if (Info->Entries[Info->EntriesNum].ID != 0) (Info->EntriesNum)++;
623 Info->Entries[Info->EntriesNum].Number = SMS->SMS[i].UDH.Text[w+3];
624 Info->Entries[Info->EntriesNum].ID = SMS_EMSPredefinedAnimation;
625 RetVal = true;
626 break;
627 case 0x0E:
628 case 0x0F:
629 if (SMS->SMS[i].UDH.Text[w] == 0x0E) {
630 dbgprintf("UDH part - EMS 16x16 animation\n");
631 BitmapType = GSM_EMSMediumPicture;
632 } else {
633 dbgprintf("UDH part - EMS 8x8 animation\n");
634 BitmapType = GSM_EMSSmallPicture;
635 }
636 dbgprintf("Position - %i\n",SMS->SMS[i].UDH.Text[w+2]);
637 if (SMS->SMS[i].UDH.Text[w+2] > Pos) {
638 z = Pos;
639 if (!AddEMSText(&SMS->SMS[i], Info, &Pos, SMS->SMS[i].UDH.Text[w+2]-z)) return false;
640 }
641 (Info->EntriesNum)++;
642 Info->Entries[Info->EntriesNum].ID = SMS_EMSAnimation;
643 Info->Entries[Info->EntriesNum].Bitmap = (GSM_MultiBitmap *)malloc(sizeof(GSM_MultiBitmap));
644 if (Info->Entries[Info->EntriesNum].Bitmap == NULL) return false;
645 Info->Entries[Info->EntriesNum].Bitmap->Number = 0;
646 for (z=0;z<((SMS->SMS[i].UDH.Text[w+1]-1)/PHONE_GetBitmapSize(BitmapType,0,0));z++) {
647 Info->Entries[Info->EntriesNum].Bitmap->Bitmap[z].Type = GSM_PictureImage;
648 PHONE_DecodeBitmap(BitmapType,
649 SMS->SMS[i].UDH.Text + w + 3 + PHONE_GetBitmapSize(BitmapType,0,0) * z,
650 &Info->Entries[Info->EntriesNum].Bitmap->Bitmap[z]);
651 Info->Entries[Info->EntriesNum].Bitmap->Number++;
652 }
653 RetVal = true;
654 break;
655 case 0x10:
656 case 0x11:
657 if (SMS->SMS[i].UDH.Text[w] == 0x10) {
658 dbgprintf("UDH part - EMS 32x32 picture\n");
659 BitmapType = GSM_EMSBigPicture;
660 } else {
661 dbgprintf("UDH part - EMS 16x16 picture\n");
662 BitmapType = GSM_EMSMediumPicture;
663 }
664 dbgprintf("Position - %i\n",SMS->SMS[i].UDH.Text[w+2]);
665 if (SMS->SMS[i].UDH.Text[w+2] > Pos) {
666 z = Pos;
667 if (!AddEMSText(&SMS->SMS[i], Info, &Pos, SMS->SMS[i].UDH.Text[w+2]-z)) return false;
668 }
669 if (Info->Entries[Info->EntriesNum].ID != 0) (Info->EntriesNum)++;
670 Info->Entries[Info->EntriesNum].Bitmap = (GSM_MultiBitmap *)malloc(sizeof(GSM_MultiBitmap));
671 if (Info->Entries[Info->EntriesNum].Bitmap == NULL) return false;
672 PHONE_DecodeBitmap(BitmapType,
673 SMS->SMS[i].UDH.Text + w + 3,
674 &Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0]);
675 Info->Entries[Info->EntriesNum].Bitmap->Number = 1;
676 Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].Text[0] = 0;
677 Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].Text[1] = 0;
678 Info->Entries[Info->EntriesNum].ID = SMS_EMSFixedBitmap;
679 RetVal = true;
680 break;
681 case 0x12:
682 dbgprintf("UDH part - EMS variable width bitmap\n");
683 if (SMS->SMS[i].UDH.Text[w+2] > Pos) {
684 z = Pos;
685 if (!AddEMSText(&SMS->SMS[i], Info, &Pos, SMS->SMS[i].UDH.Text[w+2]-z)) return false;
686 }
687 if (NewPicture) {
688 (Info->EntriesNum)++;
689 Info->Entries[Info->EntriesNum].Bitmap->Number = 0;
690 Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].BitmapWidth = 0;
691 Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].BitmapHeight = 0;
692 }
693 Bitmap.BitmapWidth = SMS->SMS[i].UDH.Text[w+3]*8;
694 Bitmap.BitmapHeight = SMS->SMS[i].UDH.Text[w+4];
695 Info->Entries[Info->EntriesNum].Bitmap = (GSM_MultiBitmap *)malloc(sizeof(GSM_MultiBitmap));
696 if (Info->Entries[Info->EntriesNum].Bitmap == NULL) return false;
697 if (NewPicture) {
698 Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].BitmapWidth = Bitmap.BitmapWidth;
699 Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].BitmapHeight = Bitmap.BitmapHeight;
700 PHONE_DecodeBitmap(GSM_EMSVariablePicture,
701 SMS->SMS[i].UDH.Text + w + 5,
702 &Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0]);
703 } else {
704 PHONE_DecodeBitmap(GSM_EMSVariablePicture,
705 SMS->SMS[i].UDH.Text + w + 5,
706 &Bitmap);
707 Bitmap2 = Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0];
708 Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].BitmapWidth = Bitmap.BitmapWidth+Bitmap2.BitmapWidth;
709 Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].BitmapHeight = Bitmap2.BitmapHeight;
710 for (width=0;width<Bitmap2.BitmapWidth;width++) {
711 for (height=0;height<Bitmap2.BitmapHeight;height++) {
712 if (GSM_IsPointBitmap(&Bitmap2, width, height)) {
713 GSM_SetPointBitmap(&Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0],width,height);
714 } else {
715 GSM_ClearPointBitmap(&Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0],width,height);
716 }
717 }
718 }
719 for (width=0;width<Bitmap.BitmapWidth;width++) {
720 for (height=0;height<Bitmap2.BitmapHeight;height++) {
721 if (GSM_IsPointBitmap(&Bitmap, width, height)) {
722 GSM_SetPointBitmap(&Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0],width+Bitmap2.BitmapWidth,height);
723 } else {
724 GSM_ClearPointBitmap(&Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0],width+Bitmap2.BitmapWidth,height);
725 }
726 }
727 }
728 }
729 if (UPI == 1) {
730 Info->Entries[Info->EntriesNum].Bitmap->Number = 1;
731 Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].Text[0] = 0;
732 Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].Text[1] = 0;
733 Info->Entries[Info->EntriesNum].ID = SMS_EMSVariableBitmap;
734 RetVal = true;
735 NewPicture = true;
736 dbgprintf("New variable picture\n");
737 } else {
738 NewPicture = false;
739 UPI--;
740 }
741 break;
742 case 0x13:
743 dbgprintf("UDH part - UPI\n");
744 dbgprintf("Value %i\n",SMS->SMS[i].UDH.Text[w+2]);
745 UPI = SMS->SMS[i].UDH.Text[w+2];
746 break;
747 case 0x17:
748 dbgprintf("UDH part - Object Distribution Indicator (Media Rights Protecting) ignored now\n");
749 break;
750 default:
751 dbgprintf("UDH part - block %02x\n",SMS->SMS[i].UDH.Text[w]);
752 Info->Unknown = true;
753 } /* switch */
754 w=w+SMS->SMS[i].UDH.Text[w+1]+2;
755 } /* while */
756 if (!AddEMSText(&SMS->SMS[i], Info, &Pos, SMS->SMS[i].Length-Pos)) return false;
757 RetVal = true;
758 }
759 if (RetVal) (Info->EntriesNum)++;
760 return RetVal;
761}
762
763/* How should editor hadle tabs in this file? Add editor commands here.
764 * vim: noexpandtab sw=8 ts=8 sts=8:
765 */