messagingappbase/smartmessaging/gmsmodel/src/GmsModel.cpp
changeset 0 72b543305e3a
equal deleted inserted replaced
-1:000000000000 0:72b543305e3a
       
     1 /*
       
     2 * Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  
       
    15 *     Picture Message model and converter.
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 
       
    21 // INCLUDE FILES
       
    22 #include "gmsModel.h"
       
    23 
       
    24 #include <txtrich.h>                //for CRichText
       
    25 #include <s32file.h>
       
    26 
       
    27 // LOCAL CONSTANTS AND MACROS
       
    28 
       
    29 // size constants
       
    30 const TInt KGmsVersionLength          = 1;
       
    31 const TInt KGmsItemLengthFieldLength  = 2;
       
    32 const TInt KGmsItemHeaderLength       = 3;
       
    33 
       
    34 // tokens
       
    35 const TUint8 KGmsVersionAsciiZero     = 48; // "0"
       
    36 const TUint8 KGmsItemTypeLatin1       = 0;  // "0"
       
    37 const TUint8 KGmsItemTypeUnicode      = 1;  // "1"
       
    38 const TUint8 KGmsItemTypeOTABitmap    = 2;  // "2"
       
    39 
       
    40 const TUint8 KGmsLF = 10;
       
    41 _LIT(KGmsModelDll,"GmsModel.dll");
       
    42 
       
    43 //  MEMBER FUNCTIONS
       
    44 
       
    45 
       
    46 EXPORT_C CGmsModel* CGmsModel::NewL(RFs& aFs, TInt aLeaveCodeForCorrupt)
       
    47     {
       
    48     CGmsModel* self = new (ELeave) CGmsModel(aFs, aLeaveCodeForCorrupt);
       
    49     CleanupStack::PushL(self);
       
    50     self->ConstructL();
       
    51     CleanupStack::Pop(self);
       
    52     return self;
       
    53     }
       
    54 
       
    55 void CGmsModel::ConstructL()
       
    56     {
       
    57     }
       
    58 
       
    59 EXPORT_C CGmsModel::~CGmsModel()
       
    60     {
       
    61     delete iText;
       
    62     delete iOTABitmap;
       
    63     }
       
    64 
       
    65 EXPORT_C void CGmsModel::ImportGMSL(const TDesC8& aInput)
       
    66     {
       
    67     Reset();
       
    68     TInt index = 0;
       
    69     CheckVersionL(aInput, index); //this leaves if version is invalid
       
    70 
       
    71     TInt length = aInput.Length();
       
    72     while (index < length)
       
    73         {
       
    74         //either text, a picture or something unsupported
       
    75         ExtractGMSSubItemL(aInput, index);
       
    76         }
       
    77     __ASSERT_ALWAYS(HasPicture(), User::Leave(iLeaveCorrupt));
       
    78     }
       
    79 
       
    80 EXPORT_C void CGmsModel::ImportGMSL(const CRichText& aRichText)
       
    81     {
       
    82     Reset();
       
    83 
       
    84     // Create a temporary HBufC16 for extracting from CRichText.
       
    85     // (CRichText has no interface for extracting to 8 bit descriptor)
       
    86     TInt docLength = aRichText.DocumentLength();
       
    87     HBufC16* buf = HBufC16::NewLC(docLength);
       
    88     TPtr16 ptr16(buf->Des());
       
    89     aRichText.Extract(ptr16, 0, docLength);
       
    90 
       
    91     //Create a temporary HBufC8 for importing to converter.
       
    92     HBufC8* buf8 = HBufC8::NewLC(docLength);
       
    93     TPtr8 ptr8 = buf8->Des();
       
    94 
       
    95     //Copy from 16 to 8 bit descriptor.
       
    96     ptr8.Copy(ptr16);
       
    97 
       
    98     ImportGMSL(*buf8);
       
    99     CleanupStack::PopAndDestroy(2); //buf8 buf16
       
   100     }
       
   101 
       
   102 EXPORT_C HBufC8* CGmsModel::ExportGMS8LC()
       
   103     {
       
   104     // There has to be at least picture data.
       
   105     __ASSERT_ALWAYS(HasPicture(), Panic(EGmsMPanicNoPicData1));
       
   106 
       
   107     HBufC8* buf = NULL;
       
   108     buf = HBufC8::NewLC(TotalSize());
       
   109     TPtr8 gms(buf->Des());
       
   110     AppendVersionL(gms);        // <version>
       
   111     AppendTextSubItemL(gms);    // <item>
       
   112     AppendPictureSubItemL(gms); // <item>
       
   113     return buf;
       
   114     }
       
   115 
       
   116 EXPORT_C HBufC16* CGmsModel::ExportGMS16LC()
       
   117     {
       
   118     HBufC16* buf16 = HBufC16::NewLC(TotalSize());
       
   119     TPtr ptr16(buf16->Des());
       
   120     HBufC8* buf8 = ExportGMS8LC();
       
   121     TPtr8 ptr8(buf8->Des());
       
   122     ptr16.Copy(ptr8);
       
   123     CleanupStack::PopAndDestroy(); //buf8
       
   124     return buf16;
       
   125     }
       
   126 
       
   127 EXPORT_C HBufC* CGmsModel::TextAsHBufC16LC() const
       
   128     {
       
   129     if (iText)
       
   130         {
       
   131         return iText->AllocLC();
       
   132         }
       
   133     return KNullDesC().AllocLC();
       
   134     }
       
   135 
       
   136 EXPORT_C void CGmsModel::SetTextL(const TDesC& aSource)
       
   137     {
       
   138     if (ContainsUnicodeL(aSource))
       
   139         {
       
   140         SetTextUnicodeL(aSource);
       
   141         }
       
   142     else
       
   143         {
       
   144         SetTextLatinL(aSource);
       
   145         }
       
   146     }
       
   147 
       
   148 EXPORT_C void CGmsModel::SetTextLatinL(const TDesC& aSource)
       
   149     {
       
   150     HBufC* text = aSource.AllocL();
       
   151     delete iText;
       
   152     iText  = text;
       
   153     iMode = EGmsModeLatin;
       
   154     }
       
   155 
       
   156 EXPORT_C void CGmsModel::SetTextUnicodeL(const TDesC& aSource)
       
   157     {
       
   158     HBufC* text = aSource.AllocL();
       
   159     delete iText;
       
   160     iText  = text;
       
   161     iMode = EGmsModeUnicode;
       
   162     }
       
   163 
       
   164 TBool CGmsModel::ContainsUnicodeL(const TDesC& aInputString) const
       
   165     {
       
   166     TInt length = aInputString.Length();
       
   167     const TUint KGmsHighestLatin1 = 255;
       
   168     for (TInt n = 0; n < length; n++)
       
   169         {
       
   170         TUint16 ch = aInputString[n];
       
   171         // Latin-1 occupies dec. values 0 to 255 of Unicode. (U+0000..U+00FF)
       
   172         if (ch > KGmsHighestLatin1 && ch != CEditableText::EParagraphDelimiter)
       
   173             {        
       
   174             return ETrue;
       
   175             }
       
   176         }
       
   177     return EFalse;
       
   178     }
       
   179 
       
   180 EXPORT_C void CGmsModel::ExportOTABitmapL(RWriteStream& aOutStream)
       
   181     {
       
   182     __ASSERT_ALWAYS(HasPicture(), Panic(EGmsMPanicNoPictureToExport));
       
   183     aOutStream.WriteL(*iOTABitmap);
       
   184     }
       
   185 
       
   186 /// Assumes an 8 bit data stream
       
   187 EXPORT_C void CGmsModel::ImportOTABitmapL(RReadStream& aReadStream)
       
   188     {
       
   189     MStreamBuf* streamBuf = NULL;
       
   190     streamBuf = aReadStream.Source();
       
   191     User::LeaveIfNull(streamBuf);
       
   192     TInt size = streamBuf->SizeL();
       
   193     __ASSERT_ALWAYS(size > 0,
       
   194         Panic(EGmsMPanicStreamIsEmpty));
       
   195     HBufC8* bitmap = HBufC8::NewLC(size);
       
   196     TPtr8 bitmapPtr(bitmap->Des());
       
   197     aReadStream.ReadL(bitmapPtr, size);
       
   198     // This leaves with iLeaveCorrupt if the bitmap is bad.
       
   199     HBufC8* buf8 = CheckedAndFixedOtaBitmapL(*bitmap);
       
   200     CleanupStack::PopAndDestroy(bitmap);
       
   201     delete iOTABitmap;
       
   202     iOTABitmap = buf8;
       
   203     }
       
   204 
       
   205 EXPORT_C TInt CGmsModel::SizeOfCompleteMsgExcludingTextAndPic() const
       
   206     {
       
   207     return (KGmsVersionLength + KGmsItemHeaderLength*2);
       
   208     }
       
   209 
       
   210 EXPORT_C TBool CGmsModel::HasText() const
       
   211     {
       
   212     if (!iText || iText->Length() <= 0)
       
   213         {
       
   214         return EFalse;
       
   215         }
       
   216     // length > 0
       
   217     return ETrue;
       
   218     }
       
   219 
       
   220 // This does not verify that the data is valid
       
   221 EXPORT_C TBool CGmsModel::HasPicture() const
       
   222     {
       
   223     if (!iOTABitmap || iOTABitmap->Length() <= 0)
       
   224         {
       
   225         return EFalse;
       
   226         }
       
   227     // length > 0
       
   228     return ETrue;
       
   229     }
       
   230 
       
   231 EXPORT_C TBool CGmsModel::IsTextLatin() const
       
   232     {
       
   233     return (iMode == EGmsModeLatin);
       
   234     }
       
   235 
       
   236 EXPORT_C TInt CGmsModel::TotalSizeExcludingText() const
       
   237     {
       
   238     TInt bitmapSize = 0;
       
   239     if (iOTABitmap)
       
   240         {
       
   241         bitmapSize = iOTABitmap->Size();
       
   242         }
       
   243     return bitmapSize + SizeOfCompleteMsgExcludingTextAndPic();
       
   244     }
       
   245 
       
   246 EXPORT_C TInt CGmsModel::TotalSize() const
       
   247     {
       
   248     TInt textSize(0);
       
   249     
       
   250     textSize = Textlength();
       
   251     if (iMode == EGmsModeUnicode)
       
   252         {
       
   253         textSize *= 2; // (two bytes per char)
       
   254         }
       
   255 
       
   256     return TotalSizeExcludingText() + textSize;
       
   257     }
       
   258 
       
   259 EXPORT_C TInt CGmsModel::Textlength() const
       
   260     {
       
   261     if (iText)
       
   262         {
       
   263         return iText->Length();
       
   264         }
       
   265     return 0;
       
   266     }
       
   267 
       
   268 EXPORT_C TInt CGmsModel::PictureSize() const
       
   269     {
       
   270     if (iOTABitmap)
       
   271         {
       
   272         return iOTABitmap->Size();
       
   273         }
       
   274     return 0;
       
   275     }
       
   276 
       
   277 EXPORT_C void CGmsModel::Reset()
       
   278     {
       
   279     delete iText;
       
   280     iText = NULL;
       
   281     delete iOTABitmap;
       
   282     iOTABitmap = NULL;
       
   283     }
       
   284 
       
   285 EXPORT_C TInt CGmsModel::_TestingL(TInt /*aCode1*/, TInt& /*aCode2*/, const TDesC8& /*aDes1*/, const TDesC16& /*aDes2*/)
       
   286     {
       
   287     // Nothing here.
       
   288     return 0;
       
   289     }
       
   290 
       
   291 // Deprecated. Do not use.
       
   292 //
       
   293 EXPORT_C HBufC* CGmsModel::ExtractTextFromMsgLC(const TDesC& /*aMsg*/, TInt /*aAmount*/)
       
   294     {
       
   295     return NULL; // for compiler
       
   296     }
       
   297 
       
   298 EXPORT_C TBool CGmsModel::IsPictureValidL()
       
   299     {
       
   300     // Deprecated
       
   301     return ETrue;
       
   302     }
       
   303 
       
   304 TBool CGmsModel::ImportOtaBitmapL(const TDesC& aFileName)
       
   305     {
       
   306     RFileReadStream readStream;
       
   307     User::LeaveIfError(readStream.Open(
       
   308         iFs,
       
   309         aFileName,
       
   310         EFileStream));
       
   311     readStream.PushL();
       
   312     MStreamBuf* buf = readStream.Source();
       
   313     User::LeaveIfNull(buf);
       
   314     TInt size = buf->SizeL();
       
   315     __ASSERT_ALWAYS(size > 0,
       
   316         Panic(EGmsNull1));
       
   317     HBufC8* data = HBufC8::NewLC(size);
       
   318     TPtr8 dataPtr(data->Des());
       
   319     readStream.ReadL(dataPtr, size);
       
   320     TBool success;
       
   321     HBufC8* buf8 = NULL;
       
   322     buf8 = CheckedAndFixedOtaBitmapL(*data, success);
       
   323     CleanupStack::PopAndDestroy(data);
       
   324     CleanupStack::PopAndDestroy(); //(closes readStream)
       
   325     if (success)
       
   326         {
       
   327         delete iOTABitmap;
       
   328         iOTABitmap = buf8;
       
   329         return ETrue;
       
   330         }
       
   331     else
       
   332         {
       
   333         __ASSERT_DEBUG(!buf8, Panic(EGmsProblem1));
       
   334         return EFalse;
       
   335         }
       
   336     }
       
   337 
       
   338 // Call this as the first extraction method.
       
   339 void CGmsModel::CheckVersionL(const TDesC8& aInput, TInt& aIndex)
       
   340     {
       
   341     __ASSERT_ALWAYS(aInput.Length() >= KGmsVersionLength,
       
   342         User::Leave(iLeaveCorrupt));
       
   343     // To be a valid msg, its version identifier must be zero
       
   344     if (aInput[0] != KGmsVersionAsciiZero)
       
   345         {
       
   346         User::Leave(iLeaveCorrupt);
       
   347         }
       
   348     aIndex++;
       
   349     }
       
   350 
       
   351 void CGmsModel::ExtractGMSSubItemL(const TDesC8& aInput, TInt& aIndex)
       
   352     {
       
   353     ExtractGMSSubItemL(aInput, aIndex, EFalse);
       
   354     }
       
   355 
       
   356 void CGmsModel::ExtractGMSSubItemL(const TDesC8& aInput, TInt& aIndex,
       
   357     TBool aSkipBitmap)
       
   358     {
       
   359     __ASSERT_ALWAYS(aInput.Length() >= aIndex + KGmsItemHeaderLength,
       
   360         User::Leave(iLeaveCorrupt));
       
   361 
       
   362     //Get GMS item type. It should be one of the following:
       
   363     //  "00" <GMS-item-length> <ISO-8859-1-char>*     = LATIN TEXT ITEM
       
   364     //  "01" <GMS-item-length> <UNICODE-char>*        = UNICODE TEXT ITEM
       
   365     //  "02" <GMS-item-length> <OTA-bitmap>           = PICTURE ITEM
       
   366 
       
   367     TBuf8<1> msgItemType;
       
   368     msgItemType = aInput.Mid(aIndex, 1); //pos, length
       
   369     aIndex += 1;
       
   370 
       
   371     if (KGmsItemTypeLatin1 == msgItemType[0])       // "00"
       
   372         {
       
   373         ExtractLatin1L(aInput, aIndex);
       
   374         }
       
   375     else if (KGmsItemTypeUnicode == msgItemType[0]) // "01"
       
   376         {
       
   377         ExtractUnicodeL(aInput, aIndex);
       
   378         }
       
   379     else if (KGmsItemTypeOTABitmap == msgItemType[0]) // "02"
       
   380         {
       
   381         if (aSkipBitmap)
       
   382             {
       
   383             ExtractUnknownL(aInput, aIndex); //just skips over it
       
   384             }
       
   385         else
       
   386             {
       
   387             ExtractOTABitmapL(aInput, aIndex);
       
   388             }
       
   389         }
       
   390     else
       
   391         {
       
   392         ExtractUnknownL(aInput, aIndex); //just skips over the part
       
   393         }
       
   394     }
       
   395 
       
   396 void CGmsModel::ExtractLatin1L(const TDesC8& aInput, TInt& aIndex)
       
   397     {
       
   398     TInt length = ExtractLengthL(aInput, aIndex);
       
   399 
       
   400     __ASSERT_ALWAYS(aInput.Length() >= aIndex + length,
       
   401         User::Leave(iLeaveCorrupt));
       
   402 
       
   403     delete iText;
       
   404     iText = NULL;
       
   405     iText = HBufC::NewL(length);
       
   406     iText->Des().Copy(aInput.Mid(aIndex, length));
       
   407     aIndex += length;
       
   408     iMode = EGmsModeLatin;
       
   409     }
       
   410 
       
   411 void CGmsModel::ExtractUnicodeL(const TDesC8& aInput, TInt& aIndex)
       
   412     {
       
   413     TInt length = ExtractLengthL(aInput, aIndex);
       
   414     __ASSERT_ALWAYS(aInput.Length() >= aIndex + length,
       
   415         User::Leave(iLeaveCorrupt));
       
   416     __ASSERT_ALWAYS((length % 2) == 0, User::Leave(iLeaveCorrupt));//even nr.
       
   417     delete iText;
       
   418     iText = NULL;
       
   419     iText = HBufC::NewL(length / 2);
       
   420 
       
   421     //
       
   422     // The data has to be reassembled from UCS-2 to 16 bit Unicode.
       
   423     //
       
   424     TPtr ptr(iText->Des());
       
   425     for (TInt n = aIndex; n < aIndex + length; n += 2)
       
   426         {
       
   427         TUint16 lower = aInput[n + 1];
       
   428         TUint16 upper = aInput[n];
       
   429         upper = TUint16(upper << 8);
       
   430         TUint16 ch = 0;
       
   431         ch = TUint16(upper | lower);
       
   432         ptr.Append(ch);
       
   433         }
       
   434     aIndex += length;
       
   435     iMode = EGmsModeUnicode;
       
   436     }
       
   437 
       
   438 void CGmsModel::ExtractOTABitmapL(const TDesC8& aInput, TInt& aIndex)
       
   439     {
       
   440     TInt length = ExtractLengthL(aInput, aIndex);
       
   441     __ASSERT_ALWAYS(aInput.Length() >= aIndex + length,
       
   442         User::Leave(iLeaveCorrupt));
       
   443     delete iOTABitmap;
       
   444     iOTABitmap = NULL;
       
   445     // This leaves with iLeaveCorrupt if the bitmap is bad.
       
   446     iOTABitmap = CheckedAndFixedOtaBitmapL(aInput.Mid(aIndex, length));
       
   447     aIndex += length;
       
   448     }
       
   449 
       
   450 void CGmsModel::ExtractUnknownL(const TDesC8& aInput, TInt& aIndex)
       
   451     {
       
   452     TInt length = ExtractLengthL(aInput, aIndex);
       
   453     __ASSERT_ALWAYS(aInput.Length() >= aIndex + length,
       
   454         User::Leave(iLeaveCorrupt));
       
   455     aIndex += length; // Skip the unknown item.
       
   456     }
       
   457 
       
   458 TInt CGmsModel::ExtractLengthL(const TDesC8& aInput, TInt& aIndex)
       
   459     {
       
   460     __ASSERT_ALWAYS(aInput.Length() >= aIndex + KGmsItemLengthFieldLength,
       
   461         User::Leave(iLeaveCorrupt));
       
   462 
       
   463     // (KGmsItemLengthFieldLength = 2)
       
   464     TBuf8<KGmsItemLengthFieldLength> itemLength;
       
   465     itemLength.Copy(aInput.Mid(aIndex, KGmsItemLengthFieldLength));
       
   466     aIndex += KGmsItemLengthFieldLength;
       
   467     TUint16 length = 0;
       
   468     length = TUint16 ((itemLength[0]&0x000000FF));
       
   469     length = TUint16 (length<<8);
       
   470     length |= TUint16 ((itemLength[1]&0x000000FF));
       
   471     return length;
       
   472     }
       
   473 
       
   474 CGmsModel::CGmsModel(RFs& aFs, TInt aLeaveCodeForCorrupt) :
       
   475     iFs(aFs),
       
   476     iLeaveCorrupt(aLeaveCodeForCorrupt)
       
   477     {
       
   478     }
       
   479 
       
   480 void CGmsModel::AppendVersionL(TDes8& aGms)
       
   481     {
       
   482     TBuf8<1> gmsVersion;
       
   483     _LIT(KEmpty1, "0");
       
   484     gmsVersion.Copy(KEmpty1);
       
   485     gmsVersion[0] = KGmsVersionAsciiZero;
       
   486     aGms.Append(gmsVersion);
       
   487     }
       
   488 
       
   489 void CGmsModel::AppendTextSubItemL(TDes8& aGms)
       
   490     {
       
   491     TBuf8<3> itemHeader;
       
   492     _LIT(KEmpty3, "000");
       
   493     itemHeader.Copy(KEmpty3);
       
   494 
       
   495     if (iMode == EGmsModeLatin)
       
   496         {
       
   497         itemHeader[0] = KGmsItemTypeLatin1; // entity type identifier.
       
   498         }
       
   499     else
       
   500         {
       
   501         // Unicode
       
   502         itemHeader[0] = KGmsItemTypeUnicode; // entity type identifier.
       
   503         }
       
   504 
       
   505     TInt sizeT = 0;
       
   506     if (iText)
       
   507         {
       
   508         sizeT = iText->Length();
       
   509         if (iMode == EGmsModeUnicode)
       
   510             {
       
   511             sizeT *= 2;
       
   512             }
       
   513         }
       
   514 
       
   515     // The text header is added even if there is no text.
       
   516     TInt lowerT = sizeT;
       
   517     lowerT &= TInt(0x000000FF);
       
   518 
       
   519     TUint upperT = sizeT;
       
   520     upperT = TInt(upperT >> 8);
       
   521     upperT &= TInt(0x000000FF);
       
   522 
       
   523     itemHeader[1] = TInt8(upperT); //First byte of <Item-length>
       
   524     itemHeader[2] = TInt8(lowerT); //Second byte of <Item-length>
       
   525 
       
   526     aGms.Append(itemHeader);
       
   527     if (iText)
       
   528         {
       
   529         if (iMode == EGmsModeLatin)
       
   530             {
       
   531             AppendLatin1TextL(aGms, *iText);
       
   532             }
       
   533         else
       
   534             {
       
   535             // Have to encode Unicode text to UCS2.
       
   536             AppendUCS2TextL(aGms, *iText);
       
   537             }
       
   538         }
       
   539     }
       
   540 
       
   541 void CGmsModel::AppendPictureSubItemL(TDes8& aGms)
       
   542     {
       
   543     __ASSERT_DEBUG(HasPicture(), Panic(EGmsMPanicNoPicData2));
       
   544 
       
   545     TBuf8<3> itemHeader;
       
   546     _LIT(KEmpty3, "000");
       
   547     itemHeader.Copy(KEmpty3);
       
   548 
       
   549     itemHeader[0] = KGmsItemTypeOTABitmap; // entity type identifier.
       
   550 
       
   551     TInt sizeB = iOTABitmap->Size();
       
   552     TInt lowerB = sizeB;
       
   553     lowerB &= TInt(0x000000FF);
       
   554 
       
   555     TUint upperB = sizeB;
       
   556     upperB = TInt(upperB >> 8);
       
   557     upperB &= TInt(0x000000FF);
       
   558 
       
   559     itemHeader[1] = TInt8(upperB); //First byte of <Item-length>
       
   560     itemHeader[2] = TInt8(lowerB); //Second byte of <Item-length>
       
   561 
       
   562     aGms.Append(itemHeader);
       
   563     aGms.Append(*iOTABitmap);
       
   564     }
       
   565 
       
   566 void CGmsModel::AppendUCS2TextL(TDes8& aGms, const TDesC& aText)
       
   567     {
       
   568     TInt length = aText.Length();
       
   569     for (TInt n = 0; n < length; n++)
       
   570         {
       
   571         TUint16 i = aText[n];
       
   572 
       
   573         TUint16 lower = i;
       
   574         lower &= TUint16(0x000000FF);
       
   575 
       
   576         TUint16 upper = i;
       
   577         upper = TUint16(upper >> 8);
       
   578         upper &= TUint16(0x000000FF);
       
   579         TChar ch = upper;
       
   580         aGms.Append(ch);
       
   581         ch = lower;
       
   582         aGms.Append(ch);
       
   583         }
       
   584     }
       
   585 
       
   586 void CGmsModel::AppendLatin1TextL(TDes8& aGms, const TDesC& aText)
       
   587     {
       
   588     TInt length = aText.Length();
       
   589     for (TInt n = 0; n < length; n++)
       
   590         {
       
   591         TUint16 ch = aText[n];
       
   592         if (ch == CEditableText::EParagraphDelimiter)
       
   593             {
       
   594             aGms.Append(KGmsLF);
       
   595             }
       
   596         else
       
   597             {
       
   598             aGms.Append(ch);
       
   599             }
       
   600         }
       
   601     }
       
   602 
       
   603 HBufC8* CGmsModel::CheckedAndFixedOtaBitmapL(const TDesC8& aOta) const
       
   604     {
       
   605     TBool success;
       
   606     HBufC8* buf = CheckedAndFixedOtaBitmapL(aOta, success);
       
   607     if (success)
       
   608         {
       
   609         return buf;
       
   610         }
       
   611     else
       
   612         {
       
   613         __ASSERT_DEBUG(!buf, Panic(EGmsProblem2));
       
   614         User::Leave(iLeaveCorrupt);
       
   615         return NULL; //for compiler
       
   616         }
       
   617     }
       
   618 
       
   619 HBufC8* CGmsModel::CheckedAndFixedOtaBitmapL(const TDesC8& aOta, TBool& aSuccess) const
       
   620     {
       
   621     // From Smart Messaging Specification 3.0.0:
       
   622     // <ota-bitmap> ::= <header> <image- data> [<palette>]
       
   623     // <header> ::= <infofield> [<extfield>]* <width><height><depth>
       
   624 
       
   625     __ASSERT_DEBUG(aOta.Length(), Panic(EGmsNoPic1));
       
   626     TInt length = aOta.Length();
       
   627 
       
   628     // <header> should be four bytes
       
   629     const TInt KHeaderBytes = 4;
       
   630     if (length < KHeaderBytes)
       
   631         {
       
   632         aSuccess = EFalse;
       
   633         return NULL;
       
   634         }
       
   635 
       
   636     // <infofield> byte should be zero, because the following should hold:
       
   637     // Concatenation flag = 0 (no)
       
   638     // Compression = 0        (no)
       
   639     // External palette = 0   (not used)
       
   640     // Icon max size fld len. = 0 (8 bit)
       
   641     // Number of animated icons = 0
       
   642     if (aOta[0] != 0)
       
   643         {
       
   644         aSuccess = EFalse;
       
   645         return NULL;
       
   646         }
       
   647 
       
   648     // <extfield> not allowed, and it was ruled out by requiring 0 for
       
   649     // the concatenation flag of <infofield>.
       
   650 
       
   651     TInt width = aOta[1];
       
   652     TInt height = aOta[2];
       
   653     TInt depth = aOta[3];
       
   654     if (!Rng(KGmsMinPictureWidthPixels, width, KGmsMaxPictureWidthPixels)
       
   655         || !Rng(KGmsMinPictureHeightPixels, height,KGmsMaxPictureHeightPixels)
       
   656         || depth != 1)
       
   657         {
       
   658         aSuccess = EFalse;
       
   659         return NULL;
       
   660         }
       
   661 
       
   662     // Check that there is the right amount of picture data.
       
   663     TInt pixels = width * height;
       
   664     TInt bytesNeededForPicData = pixels / 8 + (pixels%8 == 0 ? 0 : 1);
       
   665     TInt bytesNeeded = bytesNeededForPicData + KHeaderBytes;
       
   666     TInt tooManyBytes = length - bytesNeeded;
       
   667     if (tooManyBytes == 0)
       
   668         {
       
   669         aSuccess = ETrue;
       
   670         return aOta.AllocL();
       
   671         }
       
   672     else if (tooManyBytes < 0)
       
   673         {
       
   674         // not enough bytes
       
   675         aSuccess = EFalse;
       
   676         return NULL;
       
   677         }
       
   678     else
       
   679         {
       
   680         // tooManyBytes > 0
       
   681         // Discard the excess bytes.
       
   682         aSuccess = ETrue;
       
   683         return aOta.Left(bytesNeeded).AllocL();
       
   684         }
       
   685     }
       
   686 
       
   687 void CGmsModel::Panic(TGmsModelPanic aCode)
       
   688     {
       
   689     User::Panic(KGmsModelDll, aCode);
       
   690     }
       
   691 
       
   692 //end of file