Update of /cvsroot/mahogany/M/src/classes
In directory sc8-pr-cvs1:/tmp/cvs-serv26487/src/classes

Modified Files:
        ComposeTemplate.cpp 
Log Message:
added QuoteText()

Index: ComposeTemplate.cpp
===================================================================
RCS file: /cvsroot/mahogany/M/src/classes/ComposeTemplate.cpp,v
retrieving revision 1.55
retrieving revision 1.56
diff -b -u -2 -r1.55 -r1.56
--- ComposeTemplate.cpp 4 Oct 2003 14:52:37 -0000       1.55
+++ ComposeTemplate.cpp 6 Oct 2003 00:36:25 -0000       1.56
@@ -346,29 +346,8 @@
    String GetSignature() const;
 
-   // return the reply prefix to use for message quoting when replying
-   String GetReplyPrefix() const;
-
-   // put the text quoted according to our current quoting options with the
-   // given reply prefix into value
-   enum
-   {
-      NoDetectSig = 0,
-      DetectSig = 1
-   };
-   void ExpandOriginalText(const String& text,
-                           const String& prefix,
-                           String *value,
-                           int flags = DetectSig) const;
-
 private:
    // helper used by GetCategory and GetVariable
    static int FindStringInArray(const wxChar *strs[], int max, const String& s);
 
-   // helper used by ExpandOriginal(): return the personal name part of the
-   // first address of the given type
-   //
-   // FIXME: this function is bad as it completely ignores the other addresses
-   void GetNameForAddress(String *value, MessageAddressType type) const;
-
    // the sink we use when expanding pseudo variables
    ExpansionSink& m_sink;
@@ -489,4 +468,267 @@
 
 // ----------------------------------------------------------------------------
+// helper functions
+// ----------------------------------------------------------------------------
+
+// return the personal name part of the first address of the given type
+//
+// FIXME: this function is bad as it completely ignores the other addresses
+static String GetNameForAddress(Message *msg, MessageAddressType type)
+{
+   String value;
+
+   AddressList_obj addrList(msg->GetAddressList(type));
+   if ( addrList )
+   {
+      Address *addr = addrList->GetFirst();
+      if ( addr )
+         value = addr->GetName();
+   }
+
+   return value;
+}
+
+// return the reply prefix to use for message quoting when replying
+static String GetReplyPrefix(Message *msg, Profile *profile)
+{
+   String prefix;
+
+   // X-Attribution header value overrides everything else if it exists
+   if ( msg && READ_CONFIG_BOOL(profile, MP_REPLY_MSGPREFIX_FROM_XATTR) )
+   {
+      msg->GetHeaderLine("X-Attribution", prefix);
+   }
+
+   // prepend the senders initials to the reply prefix (this
+   // will make reply prefix like "VZ>")
+   if ( prefix.empty() &&
+            READ_CONFIG(profile, MP_REPLY_MSGPREFIX_FROM_SENDER) )
+   {
+      // take from address, not reply-to which can be set to
+      // reply to a mailing list, for example
+      String name = GetNameForAddress(msg, MAT_FROM);
+      if ( name.empty() )
+      {
+         // no from address? try to find anything else
+         name = GetNameForAddress(msg, MAT_REPLYTO);
+      }
+
+      name = MailFolder::DecodeHeader(name);
+
+      // it's (quite) common to have quotes around the personal
+      // part of the address, remove them if so
+
+      // remove spaces
+      name.Trim(TRUE);
+      name.Trim(FALSE);
+      if ( !name.empty() )
+      {
+         if ( name[0u] == '"' && name.Last() == '"' )
+         {
+            name = name.Mid(1, name.length() - 2);
+         }
+
+         // take the first letter of each word
+         wxStringTokenizer tk(name);
+         while ( tk.HasMoreTokens() )
+         {
+            char chInitial = tk.GetNextToken()[0u];
+
+            if ( chInitial == '<' )
+            {
+               // this must be the start of embedded "<...>"
+               // address, skip it completely
+               break;
+            }
+
+            // only take letters as initials
+            if ( isalpha(chInitial) )
+            {
+               prefix += chInitial;
+            }
+         }
+      }
+   }
+
+   // and then the standard reply prefix too
+   prefix += READ_CONFIG(profile, MP_REPLY_MSGPREFIX);
+
+   return prefix;
+}
+
+// flags for ExpandOriginalText()
+enum
+{
+   NoDetectSig = 0,
+   DetectSig = 1
+};
+
+// put the text quoted according to our current quoting options with the given
+// reply prefix into value
+static String
+ExpandOriginalText(const String& text,
+                   const String& prefix,
+                   Profile *profile,
+                   int flags = DetectSig)
+{
+   String value;
+
+   // should we quote the empty lines?
+   //
+   // this option is ignored when we're inserting text verbatim (hence without
+   // reply prefix) and not quoting it
+   bool quoteEmpty = !prefix.empty() &&
+                        READ_CONFIG(profile, MP_REPLY_QUOTE_EMPTY);
+
+   // where to break lines (if at all)?
+   size_t wrapMargin;
+   if ( READ_CONFIG(profile, MP_WRAP_QUOTED) )
+   {
+      wrapMargin = READ_CONFIG(profile, MP_WRAPMARGIN);
+      if ( wrapMargin <= prefix.length() )
+      {
+         wxLogError(_("The configured automatic wrap margin (%u) is too "
+                      "small, please increase it.\n"
+                      "\n"
+                      "Disabling automatic wrapping for now."), wrapMargin);
+
+         profile->writeEntry(MP_WRAP_QUOTED, false);
+         wrapMargin = 0;
+      }
+   }
+   else
+   {
+      // don't wrap
+      wrapMargin = 0;
+   }
+
+   // should we detect the signature and discard it?
+   bool detectSig = (flags & DetectSig) &&
+                        READ_CONFIG_BOOL(profile, MP_REPLY_DETECT_SIG);
+
+   DetectSignature signature;
+   if( detectSig )
+   {
+      if( !signature.Initialize(profile) )
+      {
+         profile->writeEntry(MP_REPLY_DETECT_SIG, false);
+         detectSig = false;
+      }
+   }
+
+   // if != 0, then we're at the end of the current line
+   size_t lenEOL = 0;
+
+   // the current line
+   String lineCur;
+
+   // the last detected signature start
+   int posSig = -1;
+
+   for ( const wxChar *cptr = text.c_str(); ; cptr++ )
+   {
+      // start of [real] new line?
+      if ( lineCur.empty() )
+      {
+         if ( detectSig )
+         {
+            if ( signature.StartsHere(cptr) )
+            {
+               // remember that the sig apparently starts here
+               posSig = value.length();
+            }
+         }
+
+         if ( !quoteEmpty && (lenEOL = IsEndOfLine(cptr)) != 0 )
+         {
+            // this line is empty, skip it entirely (i.e. don't output the
+            // prefix for it)
+            cptr += lenEOL - 1;
+
+            value += '\n';
+
+            continue;
+         }
+
+         lineCur += prefix;
+      }
+
+      if ( !*cptr || (lenEOL = IsEndOfLine(cptr)) != 0 )
+      {
+         // sanity test
+         ASSERT_MSG( !wrapMargin || lineCur.length() <= wrapMargin,
+                     _T("logic error in auto wrap code") );
+
+         value += lineCur;
+
+         if ( !*cptr )
+         {
+            // end of text
+            break;
+         }
+
+         // put just '\n' in output, we don't need "\r\n"
+         value += '\n';
+
+         lineCur.clear();
+
+         // -1 to compensate for ++ in the loop
+         cptr += lenEOL - 1;
+      }
+      else // !EOL
+      {
+         lineCur += *cptr;
+
+         // we don't need to wrap a line if it is its last character anyhow
+         if ( wrapMargin && lineCur.length() >= wrapMargin
+               && !IsEndOfLine(cptr + 1) )
+         {
+            // break the line before the last word
+            size_t n = wrapMargin - 1;
+            while ( n > prefix.length() )
+            {
+               if ( isspace(lineCur[n]) )
+                  break;
+
+               n--;
+            }
+
+            if ( n == prefix.length() )
+            {
+               // no space found in the line or it is in prefix which
+               // we don't want to wrap - so just cut the line right here
+               n = wrapMargin;
+            }
+
+            value.append(lineCur, n);
+            value += '\n';
+
+            // we don't need to start the new line with spaces so remove them
+            // from the tail
+            while ( n < lineCur.length() && isspace(lineCur[n]) )
+            {
+               n++;
+            }
+
+            lineCur.erase(0, n);
+            lineCur.Prepend(prefix);
+         }
+      }
+   }
+
+   // if we had a sig, truncate it now: we have to do it like this because
+   // otherwise we risk discarding a too big part of the message, e.g. if it
+   // contains a quoted message with a sig inside it so we want to discard
+   // everything after the last sig detected
+   if ( posSig != -1 )
+   {
+      value.erase(posSig);
+   }
+
+   return value;
+}
+
+
+// ----------------------------------------------------------------------------
 // ExpansionSink - the sink used with wxComposeView
 // ----------------------------------------------------------------------------
@@ -1033,13 +1275,4 @@
 }
 
-void
-VarExpander::GetNameForAddress(String *value, MessageAddressType type) const
-{
-   AddressList_obj addrList(m_msg->GetAddressList(type));
-   Address *addr = addrList ? addrList->GetFirst() : NULL;
-   if ( addr )
-      *value = addr->GetName();
-}
-
 bool
 VarExpander::ExpandOriginal(const String& Name, String *value) const
@@ -1075,5 +1308,5 @@
 
          case OriginalHeader_ReplyTo:
-            GetNameForAddress(value, MAT_REPLYTO);
+            *value = GetNameForAddress(m_msg, MAT_REPLYTO);
             break;
 
@@ -1087,14 +1320,14 @@
 
          case OriginalHeader_PersonalName:
-            GetNameForAddress(value, MAT_FROM);
+            *value = GetNameForAddress(m_msg, MAT_FROM);
             break;
 
          case OriginalHeader_FirstName:
-            GetNameForAddress(value, MAT_FROM);
+            *value = GetNameForAddress(m_msg, MAT_FROM);
             *value = Message::GetFirstNameFromAddress(*value);
             break;
 
          case OriginalHeader_LastName:
-            GetNameForAddress(value, MAT_FROM);
+            *value = GetNameForAddress(m_msg, MAT_FROM);
             *value = Message::GetLastNameFromAddress(*value);
             break;
@@ -1306,5 +1539,7 @@
    {
       case MimeType::TEXT:
-         ExpandOriginalText(mimePart->GetTextContent(), prefix, value);
+         *value = ExpandOriginalText(mimePart->GetTextContent(),
+                                     prefix,
+                                     m_profile);
 
          quoted = true;
@@ -1352,5 +1587,5 @@
    if ( isQuote )
    {
-      prefix = GetReplyPrefix();
+      prefix = GetReplyPrefix(m_msg, m_profile);
    }
    //else: template "text", so no reply prefix at all
@@ -1380,5 +1615,5 @@
       {
          // include the selection only in the template expansion
-         ExpandOriginalText(selection, prefix, value, NoDetectSig);
+         *value = ExpandOriginalText(selection, prefix, m_profile, NoDetectSig);
       }
    }
@@ -1649,4 +1884,15 @@
 
    return true;
+}
+
+extern String QuoteText(const String& text,
+                        Profile *profile,
+                        Message *msgOriginal)
+{
+   CHECK( profile && msgOriginal, _T(""), _T("NULL parameters in QuoteText") );
+
+   const String prefix = GetReplyPrefix(msgOriginal, profile);
+
+   return ExpandOriginalText(text, prefix, profile, NoDetectSig);
 }
 



-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf
_______________________________________________
Mahogany-cvsupdates mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/mahogany-cvsupdates

Reply via email to