[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 14:06:39
Message-ID: 200402111506.39744.yez () home ! nl
[Download RAW message or body]

7bit

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

? kmail/.kmcomposewin.cpp.swp
? 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 13:40:13 -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 13:40:29 -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,21 @@
         && ( !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 +      delete tmpDwPart;
 
       // add Attachments
       // create additional bodyparts for the attachments (if any)
@@ -2577,8 +2774,9 @@
               }
             }
             msg->addBodyPart( &newAttachPart );
-          } else
+          } else {
             msg->addBodyPart( attachPart );
+            }
 
 kdDebug(5006) << "                                 added " << idx << ". attachment \
to this Multipart/Mixed" << endl;  } else {
@@ -2588,40 +2786,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 +3196,7 @@
   QString text;
   QCString cText;
 
-  if (mDisableBreaking)
+  if (mDisableBreaking || mEditor->textFormat() == Qt::RichText)
       text = mEditor->text();
   else
       text = mEditor->brokenText();
@@ -3022,7 +3224,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 +3233,7 @@
                                                i18n("Send"), i18n("Change Encoding") \
) == KMessageBox::Yes);  if (!anyway)
       {
-        mEditor->setText(oldText);
+        setBody(oldText);
         return QCString();
       }
     }
@@ -4721,6 +4923,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 +4989,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 +5302,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 +5502,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 +5538,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 +5644,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 +6119,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 +6206,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 +6227,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 +6422,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 +6490,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 +6517,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 +6560,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 +6606,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 +6639,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 13:40:32 -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 13:40:43 -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