[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kmail-devel
Subject:    Re: [PATCH] composing html messages
From:       Edwin Schepers <yez () home ! nl>
Date:       2004-02-11 15:51:27
Message-ID: 200402111651.27806.yez () home ! nl
[Download RAW message or body]

On Tuesday 10 February 2004 07:01, Don Sanders wrote:
> On Sunday 08 February 2004 21:22, Edwin Schepers wrote:
> > Hi,
> > Finally it looks I have something workable.
> > It's not final: indentation, deleting some kDebug's and naming has
> > to be changed.
> > Could you (someone) review ?
> > If this is the way to go, and when it looks quite stable, can I
> > commit (after the changes to make it final)?
> 
> Great! The basic functionality of creating multipart/alternative 
> messages is working well now.
> 
> I think just some relatively minor clean ups and the patch can go in. 
> Specifically removing the DEBUG define and commented out code, 
> disabling the html toolbar by default and if possible resolving the 
> too large line spacing issue and the patch should be ok.
Hi Don,
This is a new patch.
- #define DEBUG deleted
- messagebox when trying to sign/encrypt HTML messages
- code cleanup
- html toolbar off by default


Issues to be solved :
- line spacing when opening and closing from Drafts
- signing/encryption of HTML messages
- opening HTML messages from Drafts does not always show a correct message 
(it's including the HTML code). This has to do with the fact that the 
bodyParts are not always the same. It seems that it differs depending of 
whether another message is clicked before.

I hope these issues won't stop my patch going into cvs.

Regards,
Edwin

["htmlmail.diff" (text/x-diff)]

? kmail/htmlmail.diff
Index: kmail/kmcomposerui.rc
===================================================================
RCS file: /home/kde/kdepim/kmail/kmcomposerui.rc,v
retrieving revision 1.28
diff -u -r1.28 kmcomposerui.rc
--- kmail/kmcomposerui.rc	11 Nov 2003 01:23:52 -0000	1.28
+++ kmail/kmcomposerui.rc	11 Feb 2004 15:40:50 -0000
@@ -1,4 +1,4 @@
-<!DOCTYPE kpartgui ><kpartgui version="18" name="kmcomposer" >
+<!DOCTYPE kpartgui ><kpartgui version="19" name="kmcomposer" >
  <MenuBar>
   <Menu noMerge="1" name="file" >
    <text>&amp;Message</text>
@@ -32,6 +32,7 @@
    <Action name="encrypt_message" />
    <Separator/>
    <Action name="options_select_crypto" />
+   <Action name="html"/>
    <Action name="charsets" />
    <Action name="wordwrap" />
    <Action name="options_auto_spellchecking" />
@@ -74,6 +75,7 @@
    <Action name="setup_spellchecker" append="save_merge"/>
   </Menu>
  </MenuBar>
+
  <ToolBar noMerge="1" name="mainToolBar" fullWidth="true" ><text>Main Toolbar</text>
   <Action name="send_default" />
   <Action name="send_alternative" />
@@ -88,4 +90,18 @@
   <Action name="encrypt_message" />
   <Action name="options_select_crypto" />
  </ToolBar>
+ <ToolBar noMerge="1" name="htmlToolBar" ><text>Html Toolbar</text>
+  <Action name="text_list" />
+  <Action name="text_font" />
+  <Action name="text_size" />
+  <Action name="text_bold" />
+  <Action name="text_italic" />
+  <Action name="text_under" />
+  <Action name="format_color" />
+  <Action name="align_left" />
+  <Action name="align_right" />
+  <Action name="align_center" />
+  <Action name="align_justify" />
+ </ToolBar>
+
 </kpartgui>
Index: kmail/kmcomposewin.cpp
===================================================================
RCS file: /home/kde/kdepim/kmail/kmcomposewin.cpp,v
retrieving revision 1.782
diff -u -r1.782 kmcomposewin.cpp
--- kmail/kmcomposewin.cpp	7 Feb 2004 16:52:47 -0000	1.782
+++ kmail/kmcomposewin.cpp	11 Feb 2004 15:41:13 -0000
@@ -77,6 +77,7 @@
 #include <kspelldlg.h>
 #include <spellingfilter.h>
 #include <ksyntaxhighlighter.h>
+#include <kcolordialog.h>
 
 #include <qtabdialog.h>
 #include <qregexp.h>
@@ -215,11 +216,31 @@
            SLOT( slotUpdateAttachActions() ) );
   mAttachMenu = 0;
 
+  useHTMLEditor = false;
   readConfig();
   setupStatusBar();
   setupEditor();
   setupActions();
+
+  // configuration is read now
+  if (useHTMLEditor)
+    toggleMarkup(true);
+  else {
+    if ( aMsg ) {
+      if ( aMsg->typeStr()=="multipart" && aMsg->subtypeStr()=="alternative") {
+        toggleMarkup(true);
+      }
+      else {
+        toggleMarkup(false);
+      }
+    }
+    else
+      toggleMarkup(false);
+  }
+
   applyMainWindowSettings(KMKernel::config(), "Composer");
+  // html-toolbar always default off
+  toolBar("htmlToolBar")->hide();
 
   connect(mEdtSubject,SIGNAL(textChanged(const QString&)),
           SLOT(slotUpdWinTitle(const QString&)));
@@ -290,6 +311,7 @@
     kdDebug(5006) << "KMAIL_DEBUG_COMPOSER_CRYPTO = FALSE" << endl;
   }
   mDone = true;
+
 }
 
 
@@ -962,9 +984,9 @@
     composerConfig.readBoolEntry( "autoSpellChecking", true );
   mAutoSpellCheckingAction->setEnabled( !mUseExtEditor );
   mAutoSpellCheckingAction->setChecked( !mUseExtEditor && spellChecking );
-  mEditor->slotAutoSpellCheckingToggled( !mUseExtEditor && spellChecking );
+  slotAutoSpellCheckingToggled( !mUseExtEditor && spellChecking );
   connect( mAutoSpellCheckingAction, SIGNAL( toggled( bool ) ),
-           mEditor, SLOT( slotAutoSpellCheckingToggled( bool ) ) );
+           this, SLOT( slotAutoSpellCheckingToggled( bool ) ) );
 
   QStringList encodings = KMMsgBase::supportedEncodings(TRUE);
   encodings.prepend( i18n("Auto-Detect"));
@@ -972,6 +994,10 @@
   mEncodingAction->setCurrentItem( -1 );
 
   //these are checkable!!!
+  markupAction = new KToggleAction (i18n("HTML"), 0, this, SLOT(slotToggleMarkup()),
+                      actionCollection(), "html");
+  markupAction->setChecked(useHTMLEditor);
+
   mAllFieldsAction = new KToggleAction (i18n("&All Fields"), 0, this,
                                        SLOT(slotView()),
                                        actionCollection(), "show_all_fields");
@@ -1110,6 +1136,56 @@
     mCryptoModuleAction->setCurrentItem( idx );
   }
 
+  QStringList styleItems;
+  styleItems << i18n( "Standard" );
+  styleItems << i18n( "Bullet List (Disc)" );
+  styleItems << i18n( "Bullet List (Circle)" );
+  styleItems << i18n( "Bullet List (Square)" );
+  styleItems << i18n( "Ordered List (Decimal)" );
+  styleItems << i18n( "Ordered List (Alpha lower)" );
+  styleItems << i18n( "Ordered List (Alpha upper)" );
+
+  listAction = new KSelectAction( i18n( "Select Style" ), 0, actionCollection(),
+				  "text_list" );
+  listAction->setItems( styleItems );
+  connect( listAction, SIGNAL( activated( const QString& ) ),
+           SLOT( slotListAction( const QString& ) ) );
+  fontAction = new KFontAction( "Select Font", 0, actionCollection(), 
+				"text_font" );
+  connect( fontAction, SIGNAL( activated( const QString& ) ),
+           SLOT( slotFontAction( const QString& ) ) );
+  fontSizeAction = new KFontSizeAction( "Select Size", 0, actionCollection(), 
+					"text_size" );
+  connect( fontSizeAction, SIGNAL( fontSizeChanged( int ) ),
+           SLOT( slotSizeAction( int ) ) );
+
+  alignLeftAction = new KToggleAction (i18n("Align Left"), "text_left", 0,
+                      this, SLOT(slotAlignLeft()), actionCollection(), 
+                      "align_left");
+  alignLeftAction->setChecked( TRUE );
+  alignRightAction = new KToggleAction (i18n("Align Right"), "text_right", 0, 
+                      this, SLOT(slotAlignRight()), actionCollection(), 
+                      "align_right");
+  alignCenterAction = new KToggleAction (i18n("Align Center"), "text_center", 0,
+                       this, SLOT(slotAlignCenter()), actionCollection(), 
+                       "align_center");
+  alignJustifyAction = new KToggleAction (i18n("Align Justify"), "kmtextjustify", 0, \
 +                        this, SLOT(slotAlignJustify()),
+                        actionCollection(),
+                        "align_justify");
+  textBoldAction = new KToggleAction (i18n("&Bold"), "text_bold", 0,
+				      this, SLOT(slotTextBold()),
+				      actionCollection(), "text_bold");
+  textItalicAction = new KToggleAction (i18n("&Italic"), "text_italic", 0, 
+					this, SLOT(slotTextItalic()),
+					actionCollection(), "text_italic");
+  textUnderAction = new KToggleAction (i18n("&Under"), "text_under", 0,
+				       this, SLOT(slotTextUnder()),
+				       actionCollection(), "text_under");
+  actionFormatColor = new KAction( i18n( "Text Color..." ), "colorize", 0,
+                                     this, SLOT( slotTextColor() ),
+                                     actionCollection(), "format_color");
+
   createGUI("kmcomposerui.rc");
 }
 
@@ -1183,6 +1259,10 @@
   */
   updateCursorPosition();
   connect(mEditor,SIGNAL(CursorPositionChanged()),SLOT(updateCursorPosition()));
+  connect( mEditor, SIGNAL( currentFontChanged( const QFont & ) ),
+	   this, SLOT( fontChanged( const QFont & ) ) );
+  connect( mEditor, SIGNAL( currentAlignmentChanged( int ) ),
+	   this, SLOT( alignmentChanged( int ) ) );
 }
 
 
@@ -1243,11 +1323,14 @@
 {
   KMMessagePart bodyPart, *msgPart;
   int i, num;
+#ifdef DEBUG
+      kdDebug(5006) << "entering KMComposeWin::setMsg()" << endl;
+#endif
 
   //assert(newMsg!=0);
   if(!newMsg)
     {
-      kdDebug(5006) << "KMComposeWin::setMsg() : newMsg == 0!\n" << endl;
+      kdDebug(5006) << "KMComposeWin::setMsg() : newMsg == 0!" << endl;
       return;
     }
   mMsg = newMsg;
@@ -1360,15 +1443,41 @@
 
   mDictionaryCombo->setCurrentByDictionary( ident.dictionary() );
 
+  //kdDebug(5006) << "KMComposeWin::setMsg() mMsg=" << mMsg->asString() << endl;
   num = mMsg->numBodyParts();
+  //kdDebug(5006) << "KMComposeWin::setMsg() mMsg->numBodyParts=" << \
mMsg->numBodyParts() << endl;  
   if (num > 0)
   {
     QCString bodyDecoded;
-    mMsg->bodyPart(0, &bodyPart);
+    int firstAttachment=0;
 
-    int firstAttachment = (bodyPart.typeStr().lower() == "text") ? 1 : 0;
-    if (firstAttachment)
+//eschepers : this part has to be refined. It looks like mMsg->bodyPart() is giving \
different results in some situations +    mMsg->bodyPart(1, &bodyPart);
+    if (bodyPart.typeStr().lower() == "text" && bodyPart.subtypeStr().lower() == \
"html" ) { +      // we have a mp/al header with a text and an html body
+      kdDebug(5006) << "KMComposeWin::setMsg() : text/html found" << endl;
+      firstAttachment = 2;
+      toggleMarkup(true);
+    } else {
+      mMsg->bodyPart(0, &bodyPart);
+      if (bodyPart.typeStr().lower() == "multipart" && bodyPart.subtypeStr().lower() \
== "alternative" ) { +	// we have a mp/mx header with a mp/al, text and an html body
+        kdDebug(5006) << "KMComposeWin::setMsg() : text/html found" << endl;
+        firstAttachment = 1;
+        toggleMarkup(true);
+      }
+      else {
+        mMsg->bodyPart(0, &bodyPart);
+        if (bodyPart.typeStr().lower() == "text" ) {
+          // we have a mp/mx body with a text body
+          kdDebug(5006) << "KMComposeWin::setMsg() : text/ found" << endl;
+          firstAttachment = 1;
+        }
+      }
+     }
+
+    if (firstAttachment != 0) // there's text to show
     {
       mCharset = bodyPart.charset();
       if ( mCharset.isEmpty() || mCharset == "default" )
@@ -1387,11 +1496,12 @@
 
       const QTextCodec *codec = KMMsgBase::codecForName(mCharset);
       if (codec)
-        mEditor->setText(codec->toUnicode(bodyDecoded));
+        setBody(codec->toUnicode(bodyDecoded));
       else
-        mEditor->setText(QString::fromLocal8Bit(bodyDecoded));
+        setBody(QString::fromLocal8Bit(bodyDecoded));
       mEditor->insertLine("\n", -1);
-    } else mEditor->setText("");
+    } else setBody("");
+
     for(i=firstAttachment; i<num; i++)
     {
       msgPart = new KMMessagePart;
@@ -1416,9 +1526,9 @@
 
     const QTextCodec *codec = KMMsgBase::codecForName(mCharset);
     if (codec) {
-      mEditor->setText(codec->toUnicode(bodyDecoded));
+      setBody(codec->toUnicode(bodyDecoded));
     } else
-      mEditor->setText(QString::fromLocal8Bit(bodyDecoded));
+      setBody(QString::fromLocal8Bit(bodyDecoded));
   }
 
   setCharset(mCharset);
@@ -1553,6 +1663,10 @@
 //-----------------------------------------------------------------------------
 bool KMComposeWin::applyChanges( bool backgroundMode )
 {
+#ifdef DEBUG
+  kdDebug(5006) << "entering KMComposeWin::applyChanges" << endl;
+#endif
+
   if(!mMsg) {
     kdDebug(5006) << "KMComposeWin::applyChanges() : mMsg == 0!\n" << endl;
     return FALSE;
@@ -1917,6 +2031,12 @@
                                            bool ignoreBcc,
                                            QCString& signCertFingerprint )
 {
+#ifdef DEBUG
+  kdDebug(5006) << "entering KMComposeWin::composeMessage" << endl;
+  doSign?kdDebug(5006) <<"doSign=true"<<endl:kdDebug(5006) <<"doSign=false"<<endl;
+  doEncrypt?kdDebug(5006) <<"doEncrypt=true"<<endl:kdDebug(5006) \
<<"doEncrypt=false"<<endl; +#endif
+
   Kpgp::Result result = Kpgp::Ok;
   // create informative header for those that have no mime-capable
   // email client
@@ -1984,14 +2104,72 @@
   }
 
   KMMessagePart oldBodyPart;
-  oldBodyPart.setTypeStr(   earlyAddAttachments ? "multipart" : "text" );
-  oldBodyPart.setSubtypeStr(earlyAddAttachments ? "mixed"     : "plain");
+  // if an html message is to be generated, make a text/plain and text/html part
+  if ( useHTMLEditor ) {
+    oldBodyPart.setTypeStr(   "multipart");
+    oldBodyPart.setSubtypeStr(earlyAddAttachments ? "mixed"     : "alternative");
+  }
+  else {
+    oldBodyPart.setTypeStr(   earlyAddAttachments ? "multipart" : "text" );
+    oldBodyPart.setSubtypeStr(earlyAddAttachments ? "mixed"     : "plain");
+  }
   oldBodyPart.setContentDisposition( "inline" );
 
-  QCString boundaryCStr;
-
   bool isQP = kmkernel->msgSender()->sendQuotedPrintable();
 
+  if (useHTMLEditor) { // create a multipart body
+    // calculate a boundary string
+    QCString boundaryCStr;  // storing boundary string data
+    QCString newbody="";
+    DwMediaType tmpCT;
+    tmpCT.CreateBoundary( 0 );
+    boundaryCStr = tmpCT.Boundary().c_str();
+    QValueList<int> allowedCTEs;
+
+    KMMessagePart textBodyPart;
+    textBodyPart.setTypeStr("text");
+    textBodyPart.setSubtypeStr("plain");
+    mEditor->setTextFormat(Qt::PlainText);
+    QCString textbody = breakLinesAndApplyCodec();
+    mEditor->setTextFormat(Qt::RichText);
+    textBodyPart.setBodyAndGuessCte(textbody, allowedCTEs, !isQP && !doSign,
+                                     doSign);
+    DwBodyPart* textDwPart = theMessage.createDWBodyPart( &textBodyPart );
+    textDwPart->Assemble();
+    newbody += "--";
+    newbody +=     boundaryCStr;
+    newbody +=                 "\n";
+    newbody += textDwPart->AsString().c_str();
+    delete textDwPart;
+    textDwPart = 0;
+
+    KMMessagePart htmlBodyPart;
+    htmlBodyPart.setTypeStr("text");
+    htmlBodyPart.setSubtypeStr("html");
+    // the signed body must not be 8bit encoded
+    QCString htmlbody = breakLinesAndApplyCodec();
+    htmlBodyPart.setBodyAndGuessCte(htmlbody, allowedCTEs, !isQP && !doSign,
+                                     doSign);
+    DwBodyPart* htmlDwPart = theMessage.createDWBodyPart( &htmlBodyPart );
+    htmlDwPart->Assemble();
+    newbody += "\n--";
+    newbody +=     boundaryCStr;
+    newbody +=                 "\n";
+    newbody += htmlDwPart->AsString().c_str();
+    delete htmlDwPart;
+    htmlDwPart = 0;
+
+    newbody += "--";
+    newbody +=     boundaryCStr;
+    newbody +=                 "--\n";
+    body = newbody;
+    oldBodyPart.setBodyEncoded( newbody );
+
+    // this is ugly, but I don't know another way right now. anyone?
+    mSaveBoundary = tmpCT.Boundary();
+  }
+  QCString boundaryCStr;
+
   if( earlyAddAttachments ) {
     // calculate a boundary string
     ++previousBoundaryLevel;
@@ -2000,15 +2178,21 @@
     boundaryCStr = tmpCT.Boundary().c_str();
     // add the normal body text
     KMMessagePart innerBodyPart;
-    innerBodyPart.setTypeStr(   "text" );
-    innerBodyPart.setSubtypeStr("plain");
+    if ( useHTMLEditor ) {
+      innerBodyPart.setTypeStr(   "text" );
+      innerBodyPart.setSubtypeStr("html");
+    }
+    else {
+      innerBodyPart.setTypeStr(   "text" );
+      innerBodyPart.setSubtypeStr("plain");
+    }
     innerBodyPart.setContentDisposition( "inline" );
     QValueList<int> allowedCTEs;
     // the signed body must not be 8bit encoded
     innerBodyPart.setBodyAndGuessCte(body, allowedCTEs, !isQP && !doSign,
                                      doSign);
     innerBodyPart.setCharset(mCharset);
-    innerBodyPart.setBodyEncoded( body );
+    innerBodyPart.setBodyEncoded( body ); // do we need this, since \
                setBodyAndGuessCte does this already?
     DwBodyPart* innerDwPart = theMessage.createDWBodyPart( &innerBodyPart );
     innerDwPart->Assemble();
     body  = "--";
@@ -2058,7 +2242,7 @@
     body +=       boundaryCStr;
     body +=                   "--\n";
   }
-  else
+  else // !earlyAddAttachments
   {
     QValueList<int> allowedCTEs;
     // the signed body must not be 8bit encoded
@@ -2213,7 +2397,7 @@
                             newBodyPart,
                                signCertFingerprint );
     }
-    //        kdDebug(5006) << "###AFTER ENCRYPTION\"" << theMessage.asString() << \
"\""<<endl; +    //kdDebug(5006) << "###AFTER ENCRYPTION : \"" << \
theMessage.asString() << "\""<<endl;  }
   return result;
 }
@@ -2319,6 +2503,10 @@
                                    KMMessagePart newBodyPart,
                                    QCString& signCertFingerprint )
 {
+#ifdef DEBUG
+  kdDebug(5006) << "entering KMComposeWin::encryptMessage" << endl;
+#endif
+
   Kpgp::Result result = Kpgp::Ok;
   if(!msg)
   {
@@ -2450,12 +2638,20 @@
         && ( !earlyAddAttachments || !allAttachmentsAreInBody ) ) {
       // set the content type header
       msg->headers().ContentType().FromString( "Multipart/Mixed" );
-kdDebug(5006) << "KMComposeWin::encryptMessage() : set top level Content-Type to \
                Multipart/Mixed" << endl;
-//      msg->setBody( "This message is in MIME format.\n"
-//                    "Since your mail reader does not understand this format,\n"
-//                    "some or all parts of this message may not be legible." );
+      kdDebug(5006) << "KMComposeWin::encryptMessage() : set top level Content-Type \
to Multipart/Mixed" << endl; +      //msg->setBody( "This message is in MIME \
format.\n" +      //              "Since your mail reader does not understand this \
format,\n" +      //              "some or all parts of this message may not be \
legible." );  // add our Body Part
-      msg->addBodyPart( &ourFineBodyPart );
+      DwBodyPart* tmpDwPart = msg->createDWBodyPart( &ourFineBodyPart );
+      DwHeaders& headers = tmpDwPart->Headers();
+      DwMediaType& ct = headers.ContentType();
+      ct.SetBoundary(mSaveBoundary);
+      tmpDwPart->Assemble();
+
+      KMMessagePart newPart;
+      newPart.setBody(tmpDwPart->AsString().c_str());
+      msg->addDwBodyPart(tmpDwPart); // only this method doesn't add it as \
text/plain  
       // add Attachments
       // create additional bodyparts for the attachments (if any)
@@ -2577,8 +2773,9 @@
               }
             }
             msg->addBodyPart( &newAttachPart );
-          } else
+          } else {
             msg->addBodyPart( attachPart );
+            }
 
 kdDebug(5006) << "                                 added " << idx << ". attachment \
to this Multipart/Mixed" << endl;  } else {
@@ -2588,40 +2785,44 @@
     } else {
       if( ourFineBodyPart.originalContentTypeStr() ) {
         //msg->headers().Assemble();
-        //kdDebug(5006) << "\n\n\nKMComposeWin::composeMessage():\n      A.:\n\n" << \
msg->headerAsString() << "|||\n\n\n\n\n" << endl; +        //kdDebug(5006) << \
"\n\n\nKMComposeWin::encryptMessage():\n      A.:\n\n" << msg->headerAsString() << \
                "|||\n\n\n\n\n" << endl;
         msg->headers().ContentType().FromString( \
ourFineBodyPart.originalContentTypeStr() );  //msg->headers().Assemble();
-        //kdDebug(5006) << "\n\n\nKMComposeWin::composeMessage():\n      B.:\n\n" << \
msg->headerAsString() << "|||\n\n\n\n\n" << endl; +        //kdDebug(5006) << \
"\n\n\nKMComposeWin::encryptMessage():\n      B.:\n\n" << msg->headerAsString() << \
"|||\n\n\n\n\n" << endl;  msg->headers().ContentType().Parse();
         //msg->headers().Assemble();
-        //kdDebug(5006) << "\n\n\nKMComposeWin::composeMessage():\n      C.:\n\n" << \
                msg->headerAsString() << "|||\n\n\n\n\n" << endl;
-kdDebug(5006) << "KMComposeWin::encryptMessage() : set top level Content-Type from \
originalContentTypeStr()" << endl; +        //kdDebug(5006) << \
"\n\n\nKMComposeWin::encryptMessage():\n      C.:\n\n" << msg->headerAsString() << \
"|||\n\n\n\n\n" << endl; +        //kdDebug(5006) << "KMComposeWin::encryptMessage() \
: set top level Content-Type from originalContentTypeStr()" << endl;  } else {
         msg->headers().ContentType().FromString( ourFineBodyPart.typeStr() + "/" + \
                ourFineBodyPart.subtypeStr() );
-kdDebug(5006) << "KMComposeWin::encryptMessage() : set top level Content-Type from \
                typeStr()/subtypeStr()" << endl;
-      }
+        kdDebug(5006) << "KMComposeWin::encryptMessage() : set top level \
Content-Type from typeStr()/subtypeStr()" << endl; +        }
       //msg->headers().Assemble();
-      //kdDebug(5006) << "\n\n\nKMComposeWin::composeMessage():\n      D.:\n\n" << \
msg->headerAsString() << "|||\n\n\n\n\n" << endl; +      //kdDebug(5006) << \
"KMComposeWin::encryptMessage():\n      D.:\n\n" << msg->headerAsString() << \
"|||\n\n\n\n\n" << endl;  msg->setCharset( ourFineBodyPart.charset() );
       //msg->headers().Assemble();
-      //kdDebug(5006) << "\n\n\nKMComposeWin::composeMessage():\n      E.:\n\n" << \
msg->headerAsString() << "|||\n\n\n\n\n" << endl; +      //kdDebug(5006) << \
"\n\n\nKMComposeWin::encryptMessage():\n      E.:\n\n" << msg->headerAsString() << \
"|||\n\n\n\n\n" << endl;  msg->setHeaderField( "Content-Transfer-Encoding",
                             ourFineBodyPart.contentTransferEncodingStr() );
       //msg->headers().Assemble();
-      //kdDebug(5006) << "\n\n\nKMComposeWin::composeMessage():\n      F.:\n\n" << \
msg->headerAsString() << "|||\n\n\n\n\n" << endl; +      //kdDebug(5006) << \
"\n\n\nKMComposeWin::encryptMessage():\n      F.:\n\n" << msg->headerAsString() << \
"|||\n\n\n\n\n" << endl;  msg->setHeaderField( "Content-Description",
                             ourFineBodyPart.contentDescription() );
       msg->setHeaderField( "Content-Disposition",
                             ourFineBodyPart.contentDisposition() );
 
-kdDebug(5006) << "KMComposeWin::encryptMessage() : top level headers and body \
adjusted" << endl; +      kdDebug(5006) << "KMComposeWin::encryptMessage() : top \
level headers and body adjusted" << endl;  
       // set body content
-      // msg->setBody( ourFineBodyPart.body() );
-      msg->setMultiPartBody( ourFineBodyPart.body() );
-      //kdDebug(5006) << "\n\n\n\n\n\n\nKMComposeWin::composeMessage():\n      \
99.:\n\n\n\n|||" << msg->asString() << "|||\n\n\n\n\n\n" << endl; +      if ( \
useHTMLEditor) { // add the boundary to the header +        DwMediaType & contentType \
= msg->dwContentType(); +        contentType.SetBoundary(mSaveBoundary);
+      }
+      msg->setBody(ourFineBodyPart.body() );
+      //kdDebug(5006) << "\n\n\n\n\n\n\nKMComposeWin::encryptMessage():\n      \
99.:\n|||" << msg->asString() << "|||\n\n\n\n\n\n" << endl;  \
                //msg->headers().Assemble();
-      //kdDebug(5006) << "\n\n\nKMComposeWin::composeMessage():\n      Z.:\n\n" << \
msg->headerAsString() << "|||\n\n\n\n\n" << endl; +      //kdDebug(5006) << \
"\n\n\n\n\n\n\nKMComposeWin::encryptMessage():\n      100.:\n\n\n\n|||" << \
msg->asString() << "|||\n\n\n\n\n\n" << endl; +      //kdDebug(5006) << \
"\n\n\nKMComposeWin::encryptMessage():\n      Z.:\n\n" << msg->headerAsString() << \
"|||\n\n\n\n\n" << endl;  }
 
   }
@@ -2994,7 +3195,7 @@
   QString text;
   QCString cText;
 
-  if (mDisableBreaking)
+  if (mDisableBreaking || mEditor->textFormat() == Qt::RichText)
       text = mEditor->text();
   else
       text = mEditor->brokenText();
@@ -3022,7 +3223,7 @@
     if (!text.isEmpty() && (newText != text))
     {
       QString oldText = mEditor->text();
-      mEditor->setText(newText);
+      setBody(newText);
       KCursorSaver idle(KBusyPtr::idle());
       bool anyway = (KMessageBox::warningYesNo(this,
                                                i18n("<qt>Not all characters fit into \
the chosen" @@ -3031,7 +3232,7 @@
                                                i18n("Send"), i18n("Change Encoding") \
) == KMessageBox::Yes);  if (!anyway)
       {
-        mEditor->setText(oldText);
+        setBody(oldText);
         return QCString();
       }
     }
@@ -4721,6 +4922,19 @@
 //-----------------------------------------------------------------------------
 void KMComposeWin::slotEncryptToggled(bool on)
 {
+  if ( useHTMLEditor && on ) {
+    int ret = KMessageBox::warningYesNoCancel(this,
+                                      i18n("<qt><p>Encrypting HTML messages is not \
yet supported." +                                           "<p>Do you want to delete \
your markup and turn on encryption ?</p></qt>"), +                                    \
i18n("Encrypt Message?"), +                                           KGuiItem( \
i18n("&Encrypt") ), +                                           KGuiItem( \
i18n("&Don't Encrypt") ) ); +    if ( KMessageBox::Cancel == ret || KMessageBox::No \
== ret ) { +      mEncryptAction->setChecked(false);
+      return;
+    }
+    toggleMarkup(false);
+  }
   setEncryption( on, true /* set by the user */ );
 }
 
@@ -4774,6 +4988,19 @@
 //-----------------------------------------------------------------------------
 void KMComposeWin::slotSignToggled(bool on)
 {
+  if ( useHTMLEditor && on ) {
+    int ret = KMessageBox::warningYesNoCancel(this,
+                                      i18n("<qt><p>Signing HTML messages is not yet \
supported." +                                           "<p>Do you want to delete \
your markup and turn on signing ?</p></qt>"), +                                       \
i18n("Sign Message?"), +                                           KGuiItem( \
i18n("&Sign") ), +                                           KGuiItem( i18n("&Don't \
Sign") ) ); +    if ( KMessageBox::Cancel == ret || KMessageBox::No == ret ) {
+      mSignAction->setChecked(false);
+      return;
+    }
+    toggleMarkup(false);
+  }
   setSigning( on, true /* set by the user */ );
 }
 
@@ -5074,6 +5301,68 @@
   mEditor->cleanWhiteSpace();
 }
 
+//-----------------------------------------------------------------------------
+void KMComposeWin::slotToggleMarkup()
+{
+ if ( markupAction->isChecked() ) {
+   toggleMarkup(true);
+ }
+ else
+   toggleMarkup(false);
+
+}
+//-----------------------------------------------------------------------------
+void KMComposeWin::toggleMarkup(bool markup)
+{
+  if ( markup ) {
+    if (!useHTMLEditor) {
+      if ( mSignAction->isChecked() || mEncryptAction->isChecked() ) {
+        const int rc = KMessageBox::warningYesNoCancel(this,
+                            i18n("<p>Markup messages is not yet supported on signed \
or encrypted " +                                 "messages</p><p>Turn \
signing/encryption off ?</p>"), +                            i18n("Not supported"),
+               i18n("Yes"),
+               i18n("&No") );
+        if (rc == KMessageBox::Cancel)
+          return ;
+        else if (rc == KMessageBox::Yes) {
+               mSignAction->setChecked(false);
+               mEncryptAction->setChecked(false);
+             }
+      }
+    kdDebug(5006) << "setting RichText editor" << endl;
+    useHTMLEditor = true; // set it directly to true. setColor hits another \
toggleMarkup +
+    // set all highlighted text caused by spelling back to black
+    int paraFrom, indexFrom, paraTo, indexTo;
+    mEditor->getSelection ( &paraFrom, &indexFrom, &paraTo, &indexTo);
+    mEditor->selectAll();
+    mEditor->setColor(QColor(0,0,0));
+    mEditor->setSelection ( paraFrom, indexFrom, paraTo, indexTo);
+
+    mEditor->setTextFormat(Qt::RichText);
+    mEditor->setModified(true);
+    toolBar("htmlToolBar")->show();
+    markupAction->setChecked(true);
+    mEditor->deleteAutoSpellChecking();
+    mAutoSpellCheckingAction->setChecked(false);
+    slotAutoSpellCheckingToggled(false);
+   }
+  }
+  else {
+    kdDebug(5006) << "setting PlainText editor" << endl;
+    useHTMLEditor = false;
+    mEditor->setTextFormat(Qt::PlainText);
+    QString text = mEditor->text();
+    mEditor->setText(text); // otherwise the text still looks formatted
+    mEditor->setModified(true);
+    toolBar("htmlToolBar")->hide();
+    mEditor->initializeAutoSpellChecking( mDictionaryCombo->spellConfig());
+    slotAutoSpellCheckingToggled(true);
+  }
+
+}
+
 
 //-----------------------------------------------------------------------------
 void KMComposeWin::slotSpellcheck()
@@ -5212,7 +5501,7 @@
   {
     if( !mOldSigText.isEmpty() && mAutoSign )
       edtText.append( mOldSigText );
-    mEditor->setText( edtText );
+    setBody( edtText );
   }
 
   // disable certain actions if there is no PGP user identity set
@@ -5248,6 +5537,12 @@
 }
 
 //-----------------------------------------------------------------------------
+void KMComposeWin::slotAutoSpellCheckingToggled( bool on )
+{
+  if (mEditor->AutoSpellChecking(on) == -1 )
+    mAutoSpellCheckingAction->setChecked(false); // set it to false again
+}
+//-----------------------------------------------------------------------------
 void KMComposeWin::slotSpellcheckConfig()
 {
   KWin kwin;
@@ -5348,6 +5643,111 @@
     mAlwaysSend = bAlways;
 }
 
+void KMComposeWin::slotListAction( const QString& style )
+{
+    if ( style == i18n( "Standard" ) )
+	mEditor->setParagType( QStyleSheetItem::DisplayBlock, QStyleSheetItem::ListDisc );
+    else if ( style == i18n( "Bullet List (Disc)" ) )
+	mEditor->setParagType( QStyleSheetItem::DisplayListItem, QStyleSheetItem::ListDisc \
); +    else if ( style == i18n( "Bullet List (Circle)" ) )
+	mEditor->setParagType( QStyleSheetItem::DisplayListItem, \
QStyleSheetItem::ListCircle ); +    else if ( style == i18n( "Bullet List (Square)" ) \
) +	mEditor->setParagType( QStyleSheetItem::DisplayListItem, \
QStyleSheetItem::ListSquare ); +    else if ( style == i18n( "Ordered List (Decimal)" \
)) +	mEditor->setParagType( QStyleSheetItem::DisplayListItem, \
QStyleSheetItem::ListDecimal ); +    else if ( style == i18n( "Ordered List (Alpha \
lower)" ) ) +	mEditor->setParagType( QStyleSheetItem::DisplayListItem, \
QStyleSheetItem::ListLowerAlpha ); +    else if ( style == i18n( "Ordered List (Alpha \
upper)" ) ) +	mEditor->setParagType( QStyleSheetItem::DisplayListItem, \
QStyleSheetItem::ListUpperAlpha ); +    mEditor->viewport()->setFocus();
+}
+
+void KMComposeWin::slotFontAction( const QString& font)
+{
+    toggleMarkup(true);
+    mEditor->QTextEdit::setFamily( font );
+    mEditor->viewport()->setFocus();
+    qDebug( "font %s", font.latin1() );
+}
+
+void KMComposeWin::slotSizeAction( int size )
+{
+    toggleMarkup(true);
+    mEditor->setPointSize( size );
+    mEditor->viewport()->setFocus();
+    qDebug( "font size %d", size );
+}
+
+void KMComposeWin::slotAlignLeft()
+{
+    toggleMarkup(true);
+    mEditor->QTextEdit::setAlignment( AlignLeft );
+}
+
+void KMComposeWin::slotAlignCenter()
+{
+    toggleMarkup(true);
+    mEditor->QTextEdit::setAlignment( AlignHCenter );
+}
+
+void KMComposeWin::slotAlignRight()
+{
+    toggleMarkup(true);
+    mEditor->QTextEdit::setAlignment( AlignRight );
+}
+
+void KMComposeWin::slotAlignJustify()
+{
+    toggleMarkup(true);
+    mEditor->QTextEdit::setAlignment( AlignJustify );
+}
+
+void KMComposeWin::slotTextBold()
+{
+    toggleMarkup(true);
+    mEditor->QTextEdit::setBold( textBoldAction->isChecked() );
+}
+
+void KMComposeWin::slotTextItalic()
+{
+    toggleMarkup(true);
+    mEditor->QTextEdit::setItalic( textItalicAction->isChecked() );
+}
+
+void KMComposeWin::slotTextUnder()
+{
+    toggleMarkup(true);
+    mEditor->QTextEdit::setUnderline( textUnderAction->isChecked() );
+}
+
+void KMComposeWin::slotTextColor()
+{
+  QColor color = mEditor->color();
+  if ( KColorDialog::getColor( color ) ) {
+    toggleMarkup(true);
+    mEditor->setColor( color );
+  }
+}
+
+void KMComposeWin::fontChanged( const QFont &f )
+{
+    fontAction->setFont( f.family() );
+    fontSizeAction->setFontSize( f.pointSize() );
+    textBoldAction->setChecked( f.bold() );
+    textItalicAction->setChecked( f.italic() );
+    textUnderAction->setChecked( f.underline() );
+    //}
+}
+
+void KMComposeWin::alignmentChanged( int a )
+{
+    //toggleMarkup();
+    alignLeftAction->setChecked( ( a == AlignAuto ) || ( a & AlignLeft ) );
+    alignCenterAction->setChecked( ( a & AlignHCenter ) );
+    alignRightAction->setChecked( ( a & AlignRight ) );
+    alignJustifyAction->setChecked( ( a & AlignJustify ) );
+}
+
 void KMEdit::contentsDragEnterEvent(QDragEnterEvent *e)
 {
     if (e->provides(MailListDrag::format()))
@@ -5718,7 +6118,7 @@
         newText.replace( QRegExp("\\s*\\(at\\)\\s*"), "@" );
     }
     contents = contents.left(pos)+newText+contents.mid(pos);
-    setText(contents);
+    setBody(contents);
     setEdited( true );
     setCursorPosition(pos+newText.length());
 }
@@ -5805,6 +6205,7 @@
   QColor defaultColor2( 0x00, 0x70, 0x00 );
   QColor defaultColor3( 0x00, 0x60, 0x00 );
   QColor defaultForeground( kapp->palette().active().text() );
+
   QColor col1 = readerConfig.readColorEntry( "ForegroundColor", &defaultForeground \
);  QColor col2 = readerConfig.readColorEntry( "QuotedText3", &defaultColor3 );
   QColor col3 = readerConfig.readColorEntry( "QuotedText2", &defaultColor2 );
@@ -5825,18 +6226,34 @@
 }
 
 //-----------------------------------------------------------------------------
+void KMEdit::deleteAutoSpellChecking()
+{ // because the highlighter doesn't support RichText, delete its instance.
+  delete mSpellChecker;
+}
+//-----------------------------------------------------------------------------
 void KMEdit::addSuggestion(const QString& text, const QStringList& lst, unsigned int \
)  {
   mReplacements[text] = lst;
 }
 
+
+void KMEdit::setSpellCheckingActive(bool spellCheckingActive)
+{
+  if (textFormat() != Qt::RichText) {
+    mSpellChecker->setActive(spellCheckingActive);
+  }
+}
+
+
 //-----------------------------------------------------------------------------
 KMEdit::~KMEdit()
 {
   removeEventFilter(this);
 
   delete mKSpell;
-  delete mSpellChecker;
+  if (textFormat() != Qt::RichText) {
+    delete mSpellChecker;
+  }
 }
 
 
@@ -6004,11 +6421,17 @@
 
 
 //-----------------------------------------------------------------------------
-void KMEdit::slotAutoSpellCheckingToggled( bool on )
+int KMEdit::AutoSpellChecking( bool on )
 {
+  if (textFormat() == Qt::RichText ) {
+     // syntax highlighter doesn't support extended text properties
+     if (on) KMessageBox::sorry(this, i18n("Automatic spellchecking is not possible \
on text with markup.")); +     return -1;
+  }
   // don't autoEnable spell checking if the user turned spell checking off
   mSpellChecker->setAutomatic( on );
   mSpellChecker->setActive( on );
+  return 1;
 }
 
 
@@ -6066,8 +6489,16 @@
     return;
   mWasModifiedBeforeSpellCheck = isModified();
   mSpellLineEdit = !mSpellLineEdit;
-  mKSpell = new KSpell(this, i18n("Spellcheck - KMail"), this,
-                       SLOT(slotSpellcheck2(KSpell*)));
+//  maybe for later, for now plaintext is given to KSpell
+//  if (textFormat() == Qt::RichText ) {
+//    kdDebug(5006) << "KMEdit::spellcheck, spellchecking for RichText" << endl;
+//    mKSpell = new KSpell(this, i18n("Spellcheck - KMail"), this,
+//		       SLOT(slotSpellcheck2(KSpell*)),0,true,false,KSpell::HTML);
+//  }
+//  else {
+    mKSpell = new KSpell(this, i18n("Spellcheck - KMail"), this,
+		       SLOT(slotSpellcheck2(KSpell*)));
+//  }
   QStringList l = KSpellingHighlighter::personalWords();
   for ( QStringList::Iterator it = l.begin(); it != l.end(); ++it ) {
       mKSpell->addPersonal( *it );
@@ -6085,20 +6516,26 @@
 #if KDE_IS_VERSION( 3, 1, 92 )
 void KMEdit::cut()
 {
-    KEdit::cut();
+  KEdit::cut();
+  if (textFormat() != Qt::RichText) {
     mSpellChecker->restartBackgroundSpellCheck();
+  }
 }
 
 void KMEdit::clear()
 {
-    KEdit::clear();
+  KEdit::clear();
+  if (textFormat() != Qt::RichText) {
     mSpellChecker->restartBackgroundSpellCheck();
+  }
 }
 
 void KMEdit::del()
 {
-    KEdit::del();
+  KEdit::del();
+  if (textFormat() != Qt::RichText) {
     mSpellChecker->restartBackgroundSpellCheck();
+  }
 }
 #else
 // can't #ifdef slots :-(
@@ -6122,8 +6559,28 @@
     kdDebug()<<"slotCorrected (const QString &oldWord, const QString &newWord, \
unsigned int pos) : "<<oldWord<<endl;  if( mSpellLineEdit )
         mComposer->sujectLineWidget()->spellCheckerCorrected( oldWord, newWord, \
                pos);
-     else
-         corrected(oldWord, newWord, pos);
+    else {
+        unsigned int l = 0;
+        unsigned int cnt = 0;
+        bool _bold,_underline,_italic;
+        QColor _color;
+        QFont _font;
+        posToRowCol (pos, l, cnt);
+        setCursorPosition(l, cnt+1); // the new word will get the same markup now as \
the first character of the word +        _bold = bold();
+        _underline = underline();
+        _italic = italic();
+        _color = color();
+        _font = currentFont();
+        corrected(oldWord, newWord, pos);
+        setSelection (l, cnt, l, cnt+newWord.length());
+        setBold(_bold);
+        setItalic(_italic);
+        setUnderline(_underline);
+        setColor(_color);
+        setCurrentFont(_font);
+    }
+
 }
 
 //-----------------------------------------------------------------------------
@@ -6148,7 +6605,10 @@
         }
 
         kdDebug(5006) << "spelling: new SpellingFilter with prefix=\"" << \
                quotePrefix << "\"" << endl;
-        mSpellingFilter = new SpellingFilter(text(), quotePrefix, \
SpellingFilter::FilterUrls, +        QTextEdit plaintext;
+        plaintext.setText(text());
+        plaintext.setTextFormat(Qt::PlainText);
+        mSpellingFilter = new SpellingFilter(plaintext.text(), quotePrefix, \
                SpellingFilter::FilterUrls,
                                              SpellingFilter::FilterEmailAddresses);
 
         mKSpell->check(mSpellingFilter->filteredText());
@@ -6178,8 +6638,9 @@
       }
       else
       {
-          kdDebug(5006) << "spelling: canceled - restoring text from SpellingFilter" \
                << endl;
-          setText(mSpellingFilter->originalText());
+          // don't restore, why undo all explicit replacements?
+          //kdDebug(5006) << "spelling: canceled - restoring text from \
SpellingFilter" << endl; +          //setText(mSpellingFilter->originalText());
           setModified(mWasModifiedBeforeSpellCheck);
       }
   }
Index: kmail/kmcomposewin.h
===================================================================
RCS file: /home/kde/kdepim/kmail/kmcomposewin.h,v
retrieving revision 1.230
diff -u -r1.230 kmcomposewin.h
--- kmail/kmcomposewin.h	3 Feb 2004 23:11:25 -0000	1.230
+++ kmail/kmcomposewin.h	11 Feb 2004 15:41:13 -0000
@@ -31,6 +31,7 @@
 
 #include "cryptplugwrapper.h"
 #include <kabc/addresslineedit.h>
+#include <mimelib/mediatyp.h>
 
 class _StringPair {
  public:
@@ -55,6 +56,9 @@
 class KProcess;
 class KDirWatch;
 class KSelectAction;
+class KFontAction;
+class KFontSizeAction;
+class KSelectAction;
 class KSpell;
 class KSpellConfig;
 class KDictSpellingHighlighter;
@@ -64,6 +68,7 @@
 class KTempFile;
 class KToolBar;
 class KToggleAction;
+class KSelectColorAction;
 class KURL;
 class IdentityCombo;
 class SpellingFilter;
@@ -98,6 +103,11 @@
   QString brokenText();
 
   /**
+   * Toggle automatic spellchecking
+   */
+  int AutoSpellChecking( bool );
+
+  /**
    * For the external editor
    */
   void setUseExternalEditor( bool use ) { mUseExtEditor = use; }
@@ -112,15 +122,18 @@
   bool checkExternalEditorFinished();
 
 
+  void setSpellCheckingActive(bool spellCheckingActive);
+
   /** Drag and drop methods */
   void contentsDragEnterEvent(QDragEnterEvent *e);
   void contentsDragMoveEvent(QDragMoveEvent *e);
   void contentsDropEvent(QDropEvent *e);
 
+  void initializeAutoSpellChecking( KSpellConfig* autoSpellConfig );
+  void deleteAutoSpellChecking();
 signals:
   void spellcheck_done(int result);
 public slots:
-  void slotAutoSpellCheckingToggled( bool );
   void slotSpellcheck2(KSpell*);
   void slotSpellResult(const QString&);
   void slotSpellDone();
@@ -145,7 +158,6 @@
 
 private:
   void killExternalEditor();
-  void initializeAutoSpellChecking( KSpellConfig* autoSpellConfig );
 
 private:
   KSpell *mKSpell;
@@ -511,6 +523,9 @@
 
   void slotCleanSpace();
 
+  void slotToggleMarkup();
+  void toggleMarkup(bool markup);
+
 
 //  void slotSpellConfigure();
   void slotSpellcheckDone(int result);
@@ -548,6 +563,20 @@
    */
    void addAttach(const KMMessagePart* msgPart);
 
+   void slotListAction(const QString &);
+   void slotFontAction(const QString &);
+   void slotSizeAction(int);
+   void slotAlignLeft();
+   void slotAlignCenter();
+   void slotAlignRight();
+   void slotAlignJustify();
+   void slotTextBold();
+   void slotTextItalic();
+   void slotTextUnder();
+   void slotTextColor();
+   void fontChanged( const QFont & );
+   void alignmentChanged( int );
+
 signals:
   /**
    * A message has been queued or saved in the drafts folder
@@ -692,10 +721,10 @@
    * called via pgpSignedMsg() (or pgpEncryptedMsg(), resp.).
    *
    * NOTE: The c string representation of the MIME object (or the
-   *       flat text, resp.) is returned in resultingData, so just
+   *       flat text, resp.) is returned in resultingPart, so just
    *       use this string as body text of the surrounding MIME object.
    *       This string *is* encoded according to contentTEncClear
-   *       and thus should be ready for neing sended via SMTP.
+   *       and thus should be ready for being sent via SMTP.
    */
   bool processStructuringInfo( const QString   bugURL,
                                uint            boundaryLevel,
@@ -790,6 +819,7 @@
   KMFolder *mFolder;
   long mShowHeaders;
   QString mExtEditor;
+  bool useHTMLEditor;
   bool mUseExtEditor;
   QPtrList<_StringPair> mCustHeaders;
   bool mConfirmSend;
@@ -821,6 +851,16 @@
   KToggleAction *mWordWrapAction, *mFixedFontAction, *mAutoSpellCheckingAction;
   KToggleAction *mDictionaryAction;
 
+  KSelectAction *listAction;
+  KFontAction *fontAction;
+  KFontSizeAction *fontSizeAction;
+  KToggleAction *alignLeftAction, *alignCenterAction, *alignRightAction,
+      *alignJustifyAction;
+  KToggleAction *textBoldAction, *textItalicAction, *textUnderAction;
+  KToggleAction *plainTextAction, *markupAction;
+  KAction *actionFormatColor;
+  KAction *mHtmlToolbar;
+
   KSelectAction *mEncodingAction;
   KSelectAction *mCryptoModuleAction;
 
@@ -838,7 +878,14 @@
   void slotCompletionModeChanged( KGlobalSettings::Completion );
   void slotConfigChanged();
 
+  /**
+   *  toggle automatic spellchecking
+   */
+  void slotAutoSpellCheckingToggled(bool);
+
+
 private:
+  DwString  mSaveBoundary;
   QColor mForeColor,mBackColor;
   struct atmLoadData
   {
Index: kmail/kmmessage.h
===================================================================
RCS file: /home/kde/kdepim/kmail/kmmessage.h,v
retrieving revision 1.159
diff -u -r1.159 kmmessage.h
--- kmail/kmmessage.h	20 Jan 2004 12:28:09 -0000	1.159
+++ kmail/kmmessage.h	11 Feb 2004 15:41:27 -0000
@@ -196,7 +196,7 @@
   KMMessage* createDeliveryReceipt() const;
 
   /** Create a new message that is a MDN for this message, filling all
-      required felds with proper values. Th ereturned message is not
+      required fields with proper values. The returned message is not
       stored in any folder.
 
       @param a Use AutomaticAction for filtering and ManualAction for
@@ -589,7 +589,7 @@
   DwBodyPart * getFirstDwBodyPart() const;
 
   /** Fill the KMMessagePart structure for a given DwBodyPart.
-      Iff withBody is false the body of the KMMessagePart will be left
+      If withBody is false the body of the KMMessagePart will be left
       empty and only the headers of the part will be filled in*/
   static void bodyPart(DwBodyPart* aDwBodyPart, KMMessagePart* aPart,
 		       bool withBody = true );



_______________________________________________
KMail developers mailing list
KMail-devel@kde.org
https://mail.kde.org/mailman/listinfo/kmail-devel


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic