summaryrefslogtreecommitdiffabout
path: root/gammu/emb/common/service/sms/gsmems.c
Side-by-side diff
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 @@
+/* (c) 2002-2004 by Marcin Wiacek */
+
+#include <ctype.h>
+#include <string.h>
+#include <time.h>
+
+#include "../../gsmcomon.h"
+#include "../../misc/coding/coding.h"
+#include "../gsmcal.h"
+#include "../gsmpbk.h"
+#include "../gsmlogo.h"
+#include "../gsmring.h"
+#include "../gsmdata.h"
+#include "../gsmnet.h"
+#include "gsmsms.h"
+#include "gsmmulti.h"
+
+/* EMS Developers' Guidelines from www.sonyericsson.com
+ * docs from Alcatel
+ */
+GSM_Error GSM_EncodeEMSMultiPartSMS(GSM_MultiPartSMSInfo *Info,
+ GSM_MultiSMSMessage *SMS,
+ GSM_UDH UDHType)
+{
+ unsigned char Buffer[GSM_MAX_SMS_LENGTH*2*MAX_MULTI_SMS];
+ int i,UsedText,j,Length,Width,Height,z,x,y;
+ unsigned int Len;
+ int Used,FreeText,FreeBytes,Width2,CopiedText,CopiedSMSText;
+ unsigned char UDHID;
+ GSM_Bitmap Bitmap,Bitmap2;
+ GSM_Ringtone Ring;
+ GSM_Coding_Type Coding = SMS_Coding_Default;
+ GSM_Phone_Bitmap_Types BitmapType;
+ MultiPartSMSEntry *Entry;
+ bool start;
+ GSM_DateTime Date;
+
+#ifdef DEBUG
+ if (UDHType != UDH_NoUDH) dbgprintf("linked EMS\n");
+#endif
+
+ if (Info->UnicodeCoding) Coding = SMS_Coding_Unicode;
+
+ /* Cleaning on the start */
+ for (i=0;i<MAX_MULTI_SMS;i++) {
+ GSM_SetDefaultSMSData(&SMS->SMS[i]);
+ SMS->SMS[i].UDH.Type = UDHType;
+ GSM_EncodeUDHHeader(&SMS->SMS[i].UDH);
+ SMS->SMS[i].Coding = Coding;
+ }
+
+ /* Packing */
+ for (i=0;i<Info->EntriesNum;i++) {
+ Entry = &Info->Entries[i];
+
+ switch (Entry->ID) {
+ case SMS_ConcatenatedTextLong:
+ case SMS_ConcatenatedTextLong16bit:
+ Len = 0;
+ while(1) {
+ if (Entry->Left || Entry->Right ||
+ Entry->Center || Entry->Large ||
+ Entry->Small || Entry->Bold ||
+ Entry->Italic || Entry->Underlined ||
+ Entry->Strikethrough) {
+ Buffer[0] = 0x0A; /* ID for text format */
+ Buffer[1] = 0x03; /* length of rest */
+ Buffer[2] = 0x00; /* Position in EMS msg */
+ Buffer[3] = 0x00; /* how many chars */
+ Buffer[4] = 0x00; /* formatting bits */
+ if (Entry->Left) {
+ } else if (Entry->Right) { Buffer[4] |= 1;
+ } else if (Entry->Center) { Buffer[4] |= 2;
+ } else Buffer[4] |= 3;
+ if (Entry->Large) { Buffer[4] |= 4;
+ } else if (Entry->Small) { Buffer[4] |= 8;}
+ if (Entry->Bold) Buffer[4] |= 16;
+ if (Entry->Italic) Buffer[4] |= 32;
+ if (Entry->Underlined) Buffer[4] |= 64;
+ if (Entry->Strikethrough) Buffer[4] |= 128;
+ GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,5,true,&UsedText,&CopiedText,&CopiedSMSText);
+ GSM_Find_Free_Used_SMS2(Coding,SMS->SMS[SMS->Number], &UsedText, &FreeText, &FreeBytes);
+ if (FreeText == 0) continue;
+ }
+ GSM_AddSMS_Text_UDH(SMS,Coding,Entry->Buffer+Len*2,UnicodeLength(Entry->Buffer) - Len,false,&UsedText,&CopiedText,&CopiedSMSText);
+ if (Entry->Left || Entry->Right ||
+ Entry->Center || Entry->Large ||
+ Entry->Small || Entry->Bold ||
+ Entry->Italic || Entry->Underlined ||
+ Entry->Strikethrough) {
+ SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-3] = UsedText;
+ SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-2] = CopiedSMSText;
+ }
+ Len += CopiedText;
+ if (Len == UnicodeLength(Entry->Buffer)) break;
+ dbgprintf("%i %i\n",Len,UnicodeLength(Entry->Buffer));
+ }
+ break;
+ case SMS_EMSPredefinedSound:
+ case SMS_EMSPredefinedAnimation:
+ if (Entry->ID == SMS_EMSPredefinedSound) {
+ Buffer[0] = 0x0B; /* ID for def.sound */
+ } else {
+ Buffer[0] = 0x0D; /* ID for def.animation */
+ }
+ Buffer[1] = 0x02; /* Length of rest */
+ Buffer[2] = 0x00; /* Position in EMS msg */
+ Buffer[3] = Entry->Number; /* Number of anim. */
+ GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,4,true,&UsedText,&CopiedText,&CopiedSMSText);
+ SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-2] = UsedText;
+ break;
+ case SMS_EMSSonyEricssonSound:
+ case SMS_EMSSound10:
+ case SMS_EMSSound12:
+ if (Entry->Protected) {
+ Buffer[0] = 0x17; /* ID for ODI */
+ Buffer[1] = 2; /* Length of rest */
+ Buffer[2] = 1; /* Number of protected objects */
+ Buffer[3] = 1; /* 1=Protected,0=Not protected */
+ GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,4,true,&UsedText,&CopiedText,&CopiedSMSText);
+ }
+
+ Length = 128; /* 128 bytes is maximal length from specs */
+ switch (Entry->ID) {
+ case SMS_EMSSound10:
+ Entry->RingtoneNotes = GSM_EncodeEMSSound(*Entry->Ringtone, Buffer+3, &Length, 1.0, true);
+ break;
+ case SMS_EMSSound12:
+ Entry->RingtoneNotes = GSM_EncodeEMSSound(*Entry->Ringtone, Buffer+3, &Length, 1.2, true);
+ break;
+ case SMS_EMSSonyEricssonSound:
+ Entry->RingtoneNotes = GSM_EncodeEMSSound(*Entry->Ringtone, Buffer+3, &Length, 0, true);
+ break;
+ default:
+ break;
+ }
+
+ Buffer[0] = 0x0C; /* ID for EMS sound */
+ Buffer[1] = Length+1; /* Length of rest */
+ Buffer[2] = 0x00; /* Position in EMS msg */
+ GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,Length+3,true,&UsedText,&CopiedText,&CopiedSMSText);
+ SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-Length-1] = UsedText;
+ break;
+ case SMS_EMSSonyEricssonSoundLong:
+ case SMS_EMSSound10Long:
+ case SMS_EMSSound12Long:
+ Ring = *Entry->Ringtone;
+
+ /* First check if we can use classic format */
+ Length = 128; /* 128 bytes is maximal length from specs */
+ switch (Entry->ID) {
+ case SMS_EMSSound10Long:
+ Entry->RingtoneNotes = GSM_EncodeEMSSound(Ring, Buffer+3, &Length, 1.0, true);
+ break;
+ case SMS_EMSSound12Long:
+ Entry->RingtoneNotes = GSM_EncodeEMSSound(Ring, Buffer+3, &Length, 1.2, true);
+ break;
+ case SMS_EMSSonyEricssonSoundLong:
+ Entry->RingtoneNotes = GSM_EncodeEMSSound(Ring, Buffer+3, &Length, 0, true);
+ break;
+ default:
+ break;
+ }
+ if (Entry->RingtoneNotes == Ring.NoteTone.NrCommands) {
+ if (Entry->Protected) {
+ Buffer[0] = 0x17; /* ID for ODI */
+ Buffer[1] = 2; /* Length of rest */
+ Buffer[2] = 1; /* Number of protected objects */
+ Buffer[3] = 1; /* 1=Protected,0=Not protected */
+ GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,4,true,&UsedText,&CopiedText,&CopiedSMSText);
+ }
+
+ Buffer[0] = 0x0C; /* ID for EMS sound */
+ Buffer[1] = Length+1; /* Length of rest */
+ Buffer[2] = 0x00; /* Position in EMS msg */
+ GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,Length+3,true,&UsedText,&CopiedText,&CopiedSMSText);
+ SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-Length-1] = UsedText;
+ break;
+ }
+
+ /* Find free place in first SMS */
+ GSM_Find_Free_Used_SMS2(Coding,SMS->SMS[SMS->Number], &UsedText, &FreeText, &FreeBytes);
+ Length = FreeBytes - 3;
+ if (Entry->Protected) Length = Length - 4;
+ if (Length < 0) Length = 128;
+ if (Length > 128) Length = 128;
+
+ Ring = *Entry->Ringtone;
+
+ /* Checking number of SMS */
+ Used = 0;
+ FreeBytes = 0;
+ start = true;
+ while (1) {
+ if (FreeBytes != 0) {
+ z = 0;
+ for (j=FreeBytes;j<Ring.NoteTone.NrCommands;j++) {
+ Ring.NoteTone.Commands[z] = Ring.NoteTone.Commands[j];
+ z++;
+ }
+ Ring.NoteTone.NrCommands -= FreeBytes;
+ if (Ring.NoteTone.NrCommands == 0) break;
+ Length = 128; /* 128 bytes is maximal length from specs */
+ }
+ switch (Entry->ID) {
+ case SMS_EMSSound10Long:
+ FreeBytes = GSM_EncodeEMSSound(Ring, Buffer+3, &Length, 1.0, start);
+ break;
+ case SMS_EMSSound12Long:
+ FreeBytes = GSM_EncodeEMSSound(Ring, Buffer+3, &Length, 1.2, start);
+ break;
+ case SMS_EMSSonyEricssonSoundLong:
+ FreeBytes = GSM_EncodeEMSSound(Ring, Buffer+3, &Length, 0, start);
+ break;
+ default:
+ break;
+ }
+ start = false;
+ Used++;
+ }
+ dbgprintf("Used SMS: %i\n",Used);
+
+ if (Entry->Protected) {
+ Buffer[0] = 0x17; /* ID for ODI */
+ Buffer[1] = 2; /* Length of rest */
+ Buffer[2] = Used+1; /* Number of protected objects */
+ Buffer[3] = 1; /* 1=Protected,0=Not protected */
+ GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,4,true,&UsedText,&CopiedText,&CopiedSMSText);
+ }
+
+ /* Save UPI UDH */
+ Buffer[0] = 0x13; /* ID for UPI */
+ Buffer[1] = 1; /* Length of rest */
+ Buffer[2] = Used; /* Number of used parts */
+ GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,3,true,&UsedText,&CopiedText,&CopiedSMSText);
+
+ /* Find free place in first SMS */
+ GSM_Find_Free_Used_SMS2(Coding,SMS->SMS[SMS->Number], &UsedText, &FreeText, &FreeBytes);
+ Length = FreeBytes - 3;
+ if (Length < 0) Length = 128;
+ if (Length > 128) Length = 128;
+
+ Ring = *Entry->Ringtone;
+
+ /* Saving */
+ FreeBytes = 0;
+ start = true;
+ while (1) {
+ if (FreeBytes != 0) {
+ z = 0;
+ for (j=FreeBytes;j<Ring.NoteTone.NrCommands;j++) {
+ Ring.NoteTone.Commands[z] = Ring.NoteTone.Commands[j];
+ z++;
+ }
+ Ring.NoteTone.NrCommands -= FreeBytes;
+ if (Ring.NoteTone.NrCommands == 0) break;
+ Length = 128; /* 128 bytes is maximal length from specs */
+ }
+ switch (Entry->ID) {
+ case SMS_EMSSound10Long:
+ FreeBytes = GSM_EncodeEMSSound(Ring, Buffer+3, &Length, 1.0, start);
+ break;
+ case SMS_EMSSound12Long:
+ FreeBytes = GSM_EncodeEMSSound(Ring, Buffer+3, &Length, 1.2, start);
+ break;
+ case SMS_EMSSonyEricssonSoundLong:
+ FreeBytes = GSM_EncodeEMSSound(Ring, Buffer+3, &Length, 0, start);
+ break;
+ default:
+ break;
+ }
+ Buffer[0] = 0x0C; /* ID for EMS sound */
+ Buffer[1] = Length+1; /* Length of rest */
+ Buffer[2] = 0x00; /* Position in EMS msg */
+ GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,Length+3,true,&UsedText,&CopiedText,&CopiedSMSText);
+ SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-Length-1] = UsedText;
+ start = false;
+ }
+
+ Entry->RingtoneNotes = Entry->Ringtone->NoteTone.NrCommands;
+
+ break;
+ case SMS_EMSAnimation:
+ if (Entry->Protected) {
+ Buffer[0] = 0x17; /* ID for ODI */
+ Buffer[1] = 2; /* Length of rest */
+ Buffer[2] = 1; /* Number of protected objects */
+ Buffer[3] = 1; /* 1=Protected,0=Not protected */
+ GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,4,true,&UsedText,&CopiedText,&CopiedSMSText);
+ }
+
+ if (Entry->Bitmap->Bitmap[0].BitmapWidth > 8 || Entry->Bitmap->Bitmap[0].BitmapHeight > 8) {
+ BitmapType = GSM_EMSMediumPicture; /* Bitmap 16x16 */
+ Buffer[0] = 0x0E; /* ID for 16x16 animation */
+ } else {
+ BitmapType = GSM_EMSSmallPicture; /* Bitmap 8x8 */
+ Buffer[0] = 0x0F; /* ID for 8x8 animation */
+ }
+ Length = PHONE_GetBitmapSize(BitmapType,0,0);
+
+ Buffer[1] = Length*Entry->Bitmap->Number + 1; /* Length of rest */
+ Buffer[2] = 0x00; /* Position in EMS msg */
+ for (j=0;j<Entry->Bitmap->Number;j++) {
+ PHONE_EncodeBitmap(BitmapType, Buffer+3+j*Length, &Entry->Bitmap->Bitmap[j]);
+ }
+ GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,3+Length*Entry->Bitmap->Number,true,&UsedText,&CopiedText,&CopiedSMSText);
+ SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-1-Length*Entry->Bitmap->Number] = UsedText;
+ break;
+ case SMS_EMSFixedBitmap:
+ if (Entry->Protected) {
+ Buffer[0] = 0x17; /* ID for ODI */
+ Buffer[1] = 2; /* Length of rest */
+ Buffer[2] = 1; /* Number of protected objects */
+ Buffer[3] = 1; /* 1=Protected,0=Not protected */
+ GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,4,true,&UsedText,&CopiedText,&CopiedSMSText);
+ }
+
+ if (Entry->Bitmap->Bitmap[0].BitmapWidth > 16 || Entry->Bitmap->Bitmap[0].BitmapHeight > 16) {
+ BitmapType = GSM_EMSBigPicture; /* Bitmap 32x32 */
+ Buffer[0] = 0x10; /* ID for EMS bitmap */
+ } else {
+ BitmapType = GSM_EMSMediumPicture; /* Bitmap 16x16 */
+ Buffer[0] = 0x11; /* ID for EMS bitmap */
+ }
+ Length = PHONE_GetBitmapSize(BitmapType,0,0);
+ PHONE_GetBitmapWidthHeight(BitmapType, &Width, &Height);
+
+ Buffer[1] = Length + 1; /* Length of rest */
+ Buffer[2] = 0x00; /* Position in EMS msg */
+ PHONE_EncodeBitmap(BitmapType,Buffer+3, &Entry->Bitmap->Bitmap[0]);
+ GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,3+Length,true,&UsedText,&CopiedText,&CopiedSMSText);
+ SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-1-Length] = UsedText;
+ break;
+ case SMS_EMSVariableBitmapLong:
+ BitmapType = GSM_EMSVariablePicture;
+ Width = Entry->Bitmap->Bitmap[0].BitmapWidth;
+ Height = Entry->Bitmap->Bitmap[0].BitmapHeight;
+ Bitmap = Entry->Bitmap->Bitmap[0];
+
+ /* First check if we can use classical format */
+ while (1) {
+ /* Width should be multiply of 8 */
+ while (Width % 8 != 0) Width--;
+
+ /* specs */
+ if (Width <= 96 && Height <= 128) break;
+
+ Height--;
+ }
+ Length = PHONE_GetBitmapSize(BitmapType,Width,Height);
+ if (Length <= 128) {
+ if (Entry->Protected) {
+ Buffer[0] = 0x17; /* ID for ODI */
+ Buffer[1] = 2; /* Length of rest */
+ Buffer[2] = 1; /* Number of protected objects */
+ Buffer[3] = 1; /* 1=Protected,0=Not protected */
+ GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,4,true,&UsedText,&CopiedText,&CopiedSMSText);
+ }
+
+ Buffer[0] = 0x12; /* ID for EMS bitmap */
+ Buffer[1] = Length + 3; /* Length of rest */
+ Buffer[2] = 0x00; /* Position in EMS msg */
+ Buffer[3] = Width/8; /* Bitmap width/8 */
+ Buffer[4] = Height; /* Bitmap height */
+
+ GSM_ResizeBitmap(&Bitmap, &Entry->Bitmap->Bitmap[0], Width, Height);
+#ifdef DEBUG
+ if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,&Bitmap);
+#endif
+ PHONE_EncodeBitmap(BitmapType,Buffer+5, &Bitmap);
+ GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,5+Length,true,&UsedText,&CopiedText,&CopiedSMSText);
+ SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-3-Length] = UsedText;
+ break;
+ }
+
+ /* Find free place in first SMS */
+ GSM_Find_Free_Used_SMS2(Coding,SMS->SMS[SMS->Number], &UsedText, &FreeText, &FreeBytes);
+ Used = 0;
+ Length = FreeBytes - 3;
+ if (Entry->Protected) Length = Length - 4;
+ if (Length < 0) Length = 128;
+ if (Length > 128) Length = 128;
+
+ /* Checking number of SMS */
+ FreeBytes = 0;
+ while (FreeBytes != Width) {
+ Width2 = 8;
+ while (FreeBytes + Width2 != Width) {
+ if (PHONE_GetBitmapSize(BitmapType,Width2+8,Height) > Length) break;
+
+ Width2 = Width2 + 8;
+ }
+ FreeBytes = FreeBytes + Width2;
+ Length = 128;
+ Used ++;
+ }
+ dbgprintf("Used SMS: %i\n",Used);
+
+ if (Entry->Protected) {
+ Buffer[0] = 0x17; /* ID for ODI */
+ Buffer[1] = 2; /* Length of rest */
+ Buffer[2] = Used+1; /* Number of protected objects */
+ Buffer[3] = 1; /* 1=Protected,0=Not protected */
+ GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,4,true,&UsedText,&CopiedText,&CopiedSMSText);
+ }
+
+ /* Save UPI UDH */
+ Buffer[0] = 0x13; /* ID for UPI */
+ Buffer[1] = 1; /* Length of rest */
+ Buffer[2] = Used; /* Number of used parts */
+
+ /* Find free place in first SMS */
+ GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,3,true,&UsedText,&CopiedText,&CopiedSMSText);
+ GSM_Find_Free_Used_SMS2(Coding,SMS->SMS[SMS->Number], &UsedText, &FreeText, &FreeBytes);
+ Length = FreeBytes - 3;
+ if (Length < 0) Length = 128;
+ if (Length > 128) Length = 128;
+
+#ifdef DEBUG
+ if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,&Bitmap);
+#endif
+
+ /* Saving SMS */
+ FreeBytes = 0;
+ while (FreeBytes != Width) {
+ Width2 = 8;
+ while (FreeBytes + Width2 != Width) {
+ if (PHONE_GetBitmapSize(BitmapType,Width2+8,Height) > Length) break;
+
+ Width2 = Width2 + 8;
+ }
+
+ /* Copying part of bitmap to new structure */
+ Bitmap2.BitmapWidth = Width2;
+ Bitmap2.BitmapHeight = Height;
+ GSM_ClearBitmap(&Bitmap2);
+ for (x=0;x<Width2;x++) {
+ for (y=0;y<Height;y++) {
+ if (GSM_IsPointBitmap(&Bitmap,x+FreeBytes,y)) {
+ GSM_SetPointBitmap(&Bitmap2, x, y);
+ }
+ }
+ }
+#ifdef DEBUG
+ if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,&Bitmap2);
+#endif
+
+ /* Adding new bitmap to SMS */
+ Length = PHONE_GetBitmapSize(BitmapType,Width2,Height);
+ Buffer[0] = 0x12; /* ID for EMS bitmap */
+ Buffer[1] = Length + 3; /* Length of rest */
+ Buffer[2] = 0x00; /* Position in EMS msg */
+ Buffer[3] = Width2/8; /* Bitmap width/8 */
+ Buffer[4] = Height; /* Bitmap height */
+ PHONE_EncodeBitmap(BitmapType,Buffer+5, &Bitmap2);
+ GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,5+Length,true,&UsedText,&CopiedText,&CopiedSMSText);
+ SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-3-Length] = UsedText;
+
+ FreeBytes = FreeBytes + Width2;
+ Length = 128;
+ }
+ break;
+ case SMS_EMSVariableBitmap:
+ if (Entry->Protected) {
+ Buffer[0] = 0x17; /* ID for ODI */
+ Buffer[1] = 2; /* Length of rest */
+ Buffer[2] = 1; /* Number of protected objects */
+ Buffer[3] = 1; /* 1=Protected,0=Not protected */
+ GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,4,true,&UsedText,&CopiedText,&CopiedSMSText);
+ }
+
+ BitmapType = GSM_EMSVariablePicture;
+ Width = Entry->Bitmap->Bitmap[0].BitmapWidth;
+ Height = Entry->Bitmap->Bitmap[0].BitmapHeight;
+
+ while (1) {
+ /* Width should be multiply of 8 */
+ while (Width % 8 != 0) Width--;
+
+ /* specs */
+ if (PHONE_GetBitmapSize(BitmapType,Width,Height) <= 128) break;
+
+ Height--;
+ }
+
+ Length = PHONE_GetBitmapSize(BitmapType,Width,Height);
+
+ Buffer[0] = 0x12; /* ID for EMS bitmap */
+ Buffer[1] = Length + 3; /* Length of rest */
+ Buffer[2] = 0x00; /* Position in EMS msg */
+ Buffer[3] = Width/8; /* Bitmap width/8 */
+ Buffer[4] = Height; /* Bitmap height */
+
+ GSM_ResizeBitmap(&Bitmap, &Entry->Bitmap->Bitmap[0], Width, Height);
+#ifdef DEBUG
+ if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,&Bitmap);
+#endif
+ PHONE_EncodeBitmap(BitmapType,Buffer+5, &Bitmap);
+ GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,5+Length,true,&UsedText,&CopiedText,&CopiedSMSText);
+ SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-3-Length] = UsedText;
+ break;
+ default:
+ break;
+ }
+ }
+
+ SMS->Number++;
+
+ if (UDHType == UDH_ConcatenatedMessages) {
+ UDHID = GSM_MakeSMSIDFromTime();
+ for (i=0;i<SMS->Number;i++) {
+ SMS->SMS[i].UDH.Text[2+1] = UDHID;
+ SMS->SMS[i].UDH.Text[3+1] = SMS->Number;
+ SMS->SMS[i].UDH.Text[4+1] = i+1;
+ }
+ }
+ if (UDHType == UDH_ConcatenatedMessages16bit) {
+ UDHID = GSM_MakeSMSIDFromTime();
+ GSM_GetCurrentDateTime (&Date);
+ for (i=0;i<SMS->Number;i++) {
+ SMS->SMS[i].UDH.Text[2+1] = Date.Hour;
+ SMS->SMS[i].UDH.Text[3+1] = UDHID;
+ SMS->SMS[i].UDH.Text[4+1] = SMS->Number;
+ SMS->SMS[i].UDH.Text[5+1] = i+1;
+ }
+ }
+
+#ifdef DEBUG
+ dbgprintf("SMS number is %i\n",SMS->Number);
+ for (i=0;i<SMS->Number;i++) {
+ dbgprintf("UDH length %i\n",SMS->SMS[i].UDH.Length);
+ DumpMessage(di.df, di.dl, SMS->SMS[i].UDH.Text, SMS->SMS[i].UDH.Length);
+ dbgprintf("SMS length %i\n",UnicodeLength(SMS->SMS[i].Text)*2);
+ DumpMessage(di.df, di.dl, SMS->SMS[i].Text, UnicodeLength(SMS->SMS[i].Text)*2);
+ }
+#endif
+ return ERR_NONE;
+}
+
+static bool AddEMSText(GSM_SMSMessage *SMS, GSM_MultiPartSMSInfo *Info, int *Pos, int Len)
+{
+ int BufferLen;
+
+ if (Len==0) return true;
+
+ if (Info->Entries[Info->EntriesNum].ID!=SMS_ConcatenatedTextLong &&
+ Info->Entries[Info->EntriesNum].ID!=0) {
+ (Info->EntriesNum)++;
+ }
+ BufferLen = UnicodeLength(Info->Entries[Info->EntriesNum].Buffer)*2;
+ switch (SMS->Coding) {
+ case SMS_Coding_8bit:
+// memcpy(Info->Entries[Info->EntriesNum].Buffer+BufferLen,SMS->Text+(*Pos),Len);
+// BufferLen+=Len;
+// (*Pos)+=Len;
+ break;
+ case SMS_Coding_Unicode:
+ case SMS_Coding_Default:
+ Info->Entries[Info->EntriesNum].Buffer = realloc(Info->Entries[Info->EntriesNum].Buffer, BufferLen + (Len * 2) + 2);
+ if (Info->Entries[Info->EntriesNum].Buffer == NULL) return false;
+ memcpy(Info->Entries[Info->EntriesNum].Buffer + BufferLen, SMS->Text + (*Pos) *2, Len * 2);
+ BufferLen += Len * 2;
+ break;
+ }
+ (*Pos)+=Len;
+ Info->Entries[Info->EntriesNum].Buffer[BufferLen] = 0;
+ Info->Entries[Info->EntriesNum].Buffer[BufferLen+1] = 0;
+ Info->Entries[Info->EntriesNum].ID = SMS_ConcatenatedTextLong;
+ return true;
+}
+
+bool GSM_DecodeEMSMultiPartSMS(GSM_MultiPartSMSInfo *Info,
+ GSM_MultiSMSMessage *SMS)
+{
+ int i, w, Pos, z, UPI = 1, width, height;
+ bool RetVal = false, NewPicture = true;
+ GSM_Phone_Bitmap_Types BitmapType;
+ GSM_Bitmap Bitmap,Bitmap2;
+
+ for (i=0;i<MAX_MULTI_SMS;i++) {
+ Info->Entries[i].ID = 0;
+ }
+
+ for (i=0;i<SMS->Number;i++) {
+ Pos = 0;
+ w = 1;
+ while (w < SMS->SMS[i].UDH.Length) {
+ if (Info->EntriesNum + 1 == MAX_MULTI_SMS) {
+ dbgprintf("Couldn't parse SMS, contains too many EMS parts!\n");
+ return false;
+ }
+ switch(SMS->SMS[i].UDH.Text[w]) {
+ case 0x00:
+ dbgprintf("UDH part - linked SMS with 8 bit ID\n");
+ break;
+ case 0x08:
+ dbgprintf("UDH part - linked SMS with 16 bit ID\n");
+ break;
+// case 0x0A:
+// dbgprintf("UDH part - EMS text formatting\n");
+// break;
+ case 0x0B:
+ dbgprintf("UDH part - default EMS sound\n");
+ if (SMS->SMS[i].UDH.Text[w+2] > Pos) {
+ z = Pos;
+ if (!AddEMSText(&SMS->SMS[i], Info, &Pos, SMS->SMS[i].UDH.Text[w+2]-z)) return false;
+ }
+ if (Info->Entries[Info->EntriesNum].ID != 0) (Info->EntriesNum)++;
+ Info->Entries[Info->EntriesNum].Number = SMS->SMS[i].UDH.Text[w+3];
+ Info->Entries[Info->EntriesNum].ID = SMS_EMSPredefinedSound;
+ RetVal = true;
+ break;
+// case 0x0C:
+// dbgprintf("UDH part - EMS sound\n");
+// break;
+ case 0x0D:
+ dbgprintf("UDH part - default EMS animation\n");
+ if (SMS->SMS[i].UDH.Text[w+2] > Pos) {
+ z = Pos;
+ if (!AddEMSText(&SMS->SMS[i], Info, &Pos, SMS->SMS[i].UDH.Text[w+2]-z)) return false;
+ }
+ if (Info->Entries[Info->EntriesNum].ID != 0) (Info->EntriesNum)++;
+ Info->Entries[Info->EntriesNum].Number = SMS->SMS[i].UDH.Text[w+3];
+ Info->Entries[Info->EntriesNum].ID = SMS_EMSPredefinedAnimation;
+ RetVal = true;
+ break;
+ case 0x0E:
+ case 0x0F:
+ if (SMS->SMS[i].UDH.Text[w] == 0x0E) {
+ dbgprintf("UDH part - EMS 16x16 animation\n");
+ BitmapType = GSM_EMSMediumPicture;
+ } else {
+ dbgprintf("UDH part - EMS 8x8 animation\n");
+ BitmapType = GSM_EMSSmallPicture;
+ }
+ dbgprintf("Position - %i\n",SMS->SMS[i].UDH.Text[w+2]);
+ if (SMS->SMS[i].UDH.Text[w+2] > Pos) {
+ z = Pos;
+ if (!AddEMSText(&SMS->SMS[i], Info, &Pos, SMS->SMS[i].UDH.Text[w+2]-z)) return false;
+ }
+ (Info->EntriesNum)++;
+ Info->Entries[Info->EntriesNum].ID = SMS_EMSAnimation;
+ Info->Entries[Info->EntriesNum].Bitmap = (GSM_MultiBitmap *)malloc(sizeof(GSM_MultiBitmap));
+ if (Info->Entries[Info->EntriesNum].Bitmap == NULL) return false;
+ Info->Entries[Info->EntriesNum].Bitmap->Number = 0;
+ for (z=0;z<((SMS->SMS[i].UDH.Text[w+1]-1)/PHONE_GetBitmapSize(BitmapType,0,0));z++) {
+ Info->Entries[Info->EntriesNum].Bitmap->Bitmap[z].Type = GSM_PictureImage;
+ PHONE_DecodeBitmap(BitmapType,
+ SMS->SMS[i].UDH.Text + w + 3 + PHONE_GetBitmapSize(BitmapType,0,0) * z,
+ &Info->Entries[Info->EntriesNum].Bitmap->Bitmap[z]);
+ Info->Entries[Info->EntriesNum].Bitmap->Number++;
+ }
+ RetVal = true;
+ break;
+ case 0x10:
+ case 0x11:
+ if (SMS->SMS[i].UDH.Text[w] == 0x10) {
+ dbgprintf("UDH part - EMS 32x32 picture\n");
+ BitmapType = GSM_EMSBigPicture;
+ } else {
+ dbgprintf("UDH part - EMS 16x16 picture\n");
+ BitmapType = GSM_EMSMediumPicture;
+ }
+ dbgprintf("Position - %i\n",SMS->SMS[i].UDH.Text[w+2]);
+ if (SMS->SMS[i].UDH.Text[w+2] > Pos) {
+ z = Pos;
+ if (!AddEMSText(&SMS->SMS[i], Info, &Pos, SMS->SMS[i].UDH.Text[w+2]-z)) return false;
+ }
+ if (Info->Entries[Info->EntriesNum].ID != 0) (Info->EntriesNum)++;
+ Info->Entries[Info->EntriesNum].Bitmap = (GSM_MultiBitmap *)malloc(sizeof(GSM_MultiBitmap));
+ if (Info->Entries[Info->EntriesNum].Bitmap == NULL) return false;
+ PHONE_DecodeBitmap(BitmapType,
+ SMS->SMS[i].UDH.Text + w + 3,
+ &Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0]);
+ Info->Entries[Info->EntriesNum].Bitmap->Number = 1;
+ Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].Text[0] = 0;
+ Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].Text[1] = 0;
+ Info->Entries[Info->EntriesNum].ID = SMS_EMSFixedBitmap;
+ RetVal = true;
+ break;
+ case 0x12:
+ dbgprintf("UDH part - EMS variable width bitmap\n");
+ if (SMS->SMS[i].UDH.Text[w+2] > Pos) {
+ z = Pos;
+ if (!AddEMSText(&SMS->SMS[i], Info, &Pos, SMS->SMS[i].UDH.Text[w+2]-z)) return false;
+ }
+ if (NewPicture) {
+ (Info->EntriesNum)++;
+ Info->Entries[Info->EntriesNum].Bitmap->Number = 0;
+ Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].BitmapWidth = 0;
+ Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].BitmapHeight = 0;
+ }
+ Bitmap.BitmapWidth = SMS->SMS[i].UDH.Text[w+3]*8;
+ Bitmap.BitmapHeight = SMS->SMS[i].UDH.Text[w+4];
+ Info->Entries[Info->EntriesNum].Bitmap = (GSM_MultiBitmap *)malloc(sizeof(GSM_MultiBitmap));
+ if (Info->Entries[Info->EntriesNum].Bitmap == NULL) return false;
+ if (NewPicture) {
+ Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].BitmapWidth = Bitmap.BitmapWidth;
+ Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].BitmapHeight = Bitmap.BitmapHeight;
+ PHONE_DecodeBitmap(GSM_EMSVariablePicture,
+ SMS->SMS[i].UDH.Text + w + 5,
+ &Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0]);
+ } else {
+ PHONE_DecodeBitmap(GSM_EMSVariablePicture,
+ SMS->SMS[i].UDH.Text + w + 5,
+ &Bitmap);
+ Bitmap2 = Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0];
+ Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].BitmapWidth = Bitmap.BitmapWidth+Bitmap2.BitmapWidth;
+ Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].BitmapHeight = Bitmap2.BitmapHeight;
+ for (width=0;width<Bitmap2.BitmapWidth;width++) {
+ for (height=0;height<Bitmap2.BitmapHeight;height++) {
+ if (GSM_IsPointBitmap(&Bitmap2, width, height)) {
+ GSM_SetPointBitmap(&Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0],width,height);
+ } else {
+ GSM_ClearPointBitmap(&Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0],width,height);
+ }
+ }
+ }
+ for (width=0;width<Bitmap.BitmapWidth;width++) {
+ for (height=0;height<Bitmap2.BitmapHeight;height++) {
+ if (GSM_IsPointBitmap(&Bitmap, width, height)) {
+ GSM_SetPointBitmap(&Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0],width+Bitmap2.BitmapWidth,height);
+ } else {
+ GSM_ClearPointBitmap(&Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0],width+Bitmap2.BitmapWidth,height);
+ }
+ }
+ }
+ }
+ if (UPI == 1) {
+ Info->Entries[Info->EntriesNum].Bitmap->Number = 1;
+ Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].Text[0] = 0;
+ Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].Text[1] = 0;
+ Info->Entries[Info->EntriesNum].ID = SMS_EMSVariableBitmap;
+ RetVal = true;
+ NewPicture = true;
+ dbgprintf("New variable picture\n");
+ } else {
+ NewPicture = false;
+ UPI--;
+ }
+ break;
+ case 0x13:
+ dbgprintf("UDH part - UPI\n");
+ dbgprintf("Value %i\n",SMS->SMS[i].UDH.Text[w+2]);
+ UPI = SMS->SMS[i].UDH.Text[w+2];
+ break;
+ case 0x17:
+ dbgprintf("UDH part - Object Distribution Indicator (Media Rights Protecting) ignored now\n");
+ break;
+ default:
+ dbgprintf("UDH part - block %02x\n",SMS->SMS[i].UDH.Text[w]);
+ Info->Unknown = true;
+ } /* switch */
+ w=w+SMS->SMS[i].UDH.Text[w+1]+2;
+ } /* while */
+ if (!AddEMSText(&SMS->SMS[i], Info, &Pos, SMS->SMS[i].Length-Pos)) return false;
+ RetVal = true;
+ }
+ if (RetVal) (Info->EntriesNum)++;
+ return RetVal;
+}
+
+/* How should editor hadle tabs in this file? Add editor commands here.
+ * vim: noexpandtab sw=8 ts=8 sts=8:
+ */