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