[pan2: 13/23] Teach text-massager about format=flowed.



commit d0b4dba36ecd2358458f81616aec4c43fce123d7
Author: K. Haley <haleykd users sf net>
Date:   Wed Apr 7 15:02:40 2010 -0600

    Teach text-massager about format=flowed.

 pan/gui/body-pane.cc                   |    4 +-
 pan/usenet-utils/text-massager-test.cc |    6 ++
 pan/usenet-utils/text-massager.cc      |  147 +++++++++++++++++++++-----------
 pan/usenet-utils/text-massager.h       |    2 +-
 4 files changed, 108 insertions(+), 51 deletions(-)
---
diff --git a/pan/gui/body-pane.cc b/pan/gui/body-pane.cc
index 42070a6..f4eb451 100644
--- a/pan/gui/body-pane.cc
+++ b/pan/gui/body-pane.cc
@@ -940,10 +940,12 @@ BodyPane :: append_part (GMimeObject * obj, GtkAllocation * widget_size)
   else if (g_mime_content_type_is_type (type, "text", "*"))
   {
     const char * fallback_charset (_charset.c_str());
+    const char * p_flowed (g_mime_object_get_content_type_parameter(obj,"format"));
+    const bool flowed (g_strcmp0 (p_flowed, "flowed") == 0);
     std::string str = mime_part_to_utf8 (part, fallback_charset);
 
     if (!str.empty() && _prefs.get_flag ("wrap-article-body", false))
-      str = _tm.fill (str);
+      str = _tm.fill (str, flowed);
 
     const bool do_mute (_prefs.get_flag ("mute-quoted-text", false));
     const bool do_smilies (_prefs.get_flag ("show-smilies-as-graphics", true));
diff --git a/pan/usenet-utils/text-massager-test.cc b/pan/usenet-utils/text-massager-test.cc
index 796ecf9..3013e95 100644
--- a/pan/usenet-utils/text-massager-test.cc
+++ b/pan/usenet-utils/text-massager-test.cc
@@ -34,6 +34,12 @@ int main (void)
    expected_out = "> a\n> b\n> c";
    check (out == expected_out);
 
+   /* flowed test */
+   in = "This is \na test of \nflowed text.\n\nA\n";
+   out = tm.fill (in, true);
+   expected_out = "This is a test of flowed text.\n\nA";
+   check (out == expected_out);
+
    /* wrap real-world 1 */
    in = 
 "Cybe R. Wizard wrote:\n"
diff --git a/pan/usenet-utils/text-massager.cc b/pan/usenet-utils/text-massager.cc
index cee9d2e..d34d808 100644
--- a/pan/usenet-utils/text-massager.cc
+++ b/pan/usenet-utils/text-massager.cc
@@ -108,8 +108,99 @@ namespace
    typedef std::vector<Paragraph> paragraphs_t;
    typedef paragraphs_t::iterator p_it;
 
+   void merge_fixed (paragraphs_t &paragraphs, lines_t &lines, int wrap_col)
+   {
+     int prev_content_len = 0;
+     StringView cur_leader;
+     std::string cur_content;
+
+     for (lines_cit it=lines.begin(), end=lines.end(); it!=end; ++it)
+     {
+        const Line& line (*it);
+        bool paragraph_end = true;
+        bool hard_break = false;
+
+        if (cur_content.empty() || line.leader==cur_leader)
+           paragraph_end = false;
+
+        if (line.content.empty()) {
+           hard_break = prev_content_len!=0;
+           paragraph_end = true;
+        }
+
+        // we usually don't want to wrap really short lines
+        if (prev_content_len && prev_content_len<(wrap_col/2))
+           paragraph_end = true;
+
+        if (paragraph_end) // the new line is a new paragraph, so save old
+        {
+           paragraphs.push_back (Paragraph (
+              cur_leader.str, cur_leader.len,
+              cur_content.c_str(), cur_content.size()));
+           cur_leader = line.leader;
+           cur_content = line.content.to_string();
+           if (hard_break) {
+              paragraphs.push_back (Paragraph (
+                 cur_leader.str, cur_leader.len, "", 0));
+            }
+        }
+        else // append to the content
+        {
+           if (!cur_content.empty())
+              cur_content += ' ';
+           cur_leader = line.leader;
+           cur_content.insert (cur_content.end(),
+                               line.content.begin(),
+                               line.content.end());
+        }
+
+        prev_content_len = line.content.len;
+     }
+   }
+
+  void merge_flowed (paragraphs_t &paragraphs, lines_t &lines)
+  {
+    StringView cur_leader;
+    std::string cur_content;
+    bool prev_flowed=true;
+
+    for (lines_cit it=lines.begin(), end=lines.end(); it!=end; ++it)
+    {
+      const Line& line (*it);
+
+      if (line.leader != cur_leader)
+        prev_flowed = false;
+
+      if (!prev_flowed) // the new line is a new paragraph, so save old
+      {
+         paragraphs.push_back (Paragraph (
+            cur_leader.str, cur_leader.len,
+            cur_content.c_str(), cur_content.size()));
+         cur_leader = line.leader;
+         cur_content = line.content.to_string();
+      }
+      else // append to the content
+      {
+         if (!cur_content.empty())
+            cur_content += ' ';
+         cur_leader = line.leader;
+         cur_content.insert (cur_content.end(),
+                             line.content.begin(),
+                             line.content.end());
+      }
+      // flowed text ends with a space
+      if (line.content.len && line.content.str[line.content.len] == ' ')
+         prev_flowed = true;
+      else
+        prev_flowed = false;
+    }
+    //add final content
+    paragraphs.push_back (Paragraph (cur_leader.str, cur_leader.len,
+                            cur_content.c_str(), cur_content.size()));
+ }
+
    std::vector<Paragraph>
-   get_paragraphs (const TextMassager& tm, const StringView& body)
+   get_paragraphs (const TextMassager& tm, const StringView& body, bool flowed)
    {
       StringView mybody (body);
       StringView line;
@@ -141,52 +232,10 @@ namespace
       std::vector<Paragraph> paragraphs;
       if (!lines.empty())
       {
-         int prev_content_len = 0;
-         StringView cur_leader;
-         std::string cur_content;
-
-         for (lines_cit it=lines.begin(), end=lines.end(); it!=end; ++it)
-         {
-            const Line& line (*it);
-            bool paragraph_end = true;
-            bool hard_break = false;
-
-            if (cur_content.empty() || line.leader==cur_leader)
-               paragraph_end = false;
-
-            if (line.content.empty()) {
-               hard_break = prev_content_len!=0;
-               paragraph_end = true;
-            }
-
-            // we usually don't want to wrap really short lines
-            if (prev_content_len && prev_content_len<(tm.get_wrap_column()/2))
-               paragraph_end = true;
-
-            if (paragraph_end) // the new line is a new paragraph, so save old
-            {
-               paragraphs.push_back (Paragraph (
-                  cur_leader.str, cur_leader.len,
-                  cur_content.c_str(), cur_content.size()));
-               cur_leader = line.leader;
-               cur_content = line.content.to_string();
-               if (hard_break) {
-                  paragraphs.push_back (Paragraph (
-                     cur_leader.str, cur_leader.len, "", 0));
-                }
-            }
-            else // append to the content
-            {
-               if (!cur_content.empty())
-                  cur_content += ' ';
-               cur_leader = line.leader;
-               cur_content.insert (cur_content.end(),
-                                   line.content.begin(),
-                                   line.content.end());
-            }
-
-            prev_content_len = line.content.len;
-         }
+        if (flowed)
+          merge_flowed(paragraphs, lines);
+        else
+          merge_fixed(paragraphs, lines, tm.get_wrap_column());
 
         // Remember that empty line we added back up at the top?
         // We remove it now
@@ -271,7 +320,7 @@ namespace
 }
 
 std::string
-TextMassager :: fill (const StringView& body) const
+TextMassager :: fill (const StringView& body, bool flowed) const
 {
    std::string retval;
 
@@ -291,7 +340,7 @@ TextMassager :: fill (const StringView& body) const
    typedef std::vector<std::string> strings_t;
    typedef strings_t::const_iterator strings_cit;
    strings_t lines;
-   paragraphs_t paragraphs (get_paragraphs (*this, tmp_body));
+   paragraphs_t paragraphs (get_paragraphs (*this, tmp_body, flowed));
    for (p_it it=paragraphs.begin(), end=paragraphs.end(); it!=end; ++it)
       fill_paragraph (*this, *it, lines);
 
diff --git a/pan/usenet-utils/text-massager.h b/pan/usenet-utils/text-massager.h
index 47e4977..68251db 100644
--- a/pan/usenet-utils/text-massager.h
+++ b/pan/usenet-utils/text-massager.h
@@ -44,7 +44,7 @@ namespace pan
     public:
       static char* rot13_inplace (char * text);
       std::string mute_quotes (const StringView& text) const;
-      std::string fill (const StringView& text) const;
+      std::string fill (const StringView& text, bool flowed = false) const;
       int get_wrap_column () const { return _wrap_column; }
       bool is_quote_character (unsigned int unichar) const;
       std::set<char> get_quote_characters () const;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]