1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /*
3  * Pan - A Newsreader for Gtk+
4  * Copyright (C) 2002-2006  Charles Kerr <charles@rebelbase.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, see <http://www.gnu.org/licenses/>.
17  *
18  */
19 
20 #include <config.h>
21 #include <cassert>
22 #include <algorithm>
23 #include <glib.h>
24 #include <pan/general/debug.h>
25 #include <pan/general/macros.h>
26 #include <pan/general/string-view.h>
27 #include "article.h"
28 
29 using namespace pan;
30 
31 Article :: PartState
get_part_state() const32 Article :: get_part_state () const
33 {
34   PartState part_state (SINGLE);
35 
36   // not a multipart
37   if (!is_binary)
38     part_state = SINGLE;
39 
40   // someone's posted a followup to a multipart
41   else if (!is_line_count_ge(250) && has_reply_leader(subject.to_view()))
42     part_state = SINGLE;
43 
44   else  {
45     const Parts::number_t total = parts.get_total_part_count ();
46     const Parts::number_t found = parts.get_found_part_count ();
47     if (!found) // someone's posted a "000/124" info message
48       part_state = SINGLE;
49     else // a multipart..
50       part_state = total==found ? COMPLETE : INCOMPLETE;
51   }
52 
53   return part_state;
54 }
55 
56 unsigned int
get_crosspost_count() const57 Article :: get_crosspost_count () const
58 {
59   quarks_t groups;
60   foreach_const (Xref, xref,  xit)
61     groups.insert (xit->group);
62   return (int) groups.size ();
63 }
64 
65 bool
has_reply_leader(const StringView & s)66 Article :: has_reply_leader (const StringView& s)
67 {
68   return !s.empty()
69     && s.len>4 \
70     && (s.str[0]=='R' || s.str[0]=='r')
71     && (s.str[1]=='E' || s.str[1]=='e')
72     && s.str[2]==':'
73     && s.str[3]==' ';
74 }
75 
76 unsigned long
get_byte_count() const77 Article :: get_byte_count () const
78 {
79   unsigned long bytes = 0;
80   for (part_iterator it(pbegin()), end(pend()); it!=end; ++it)
81     bytes += it.bytes();
82   return bytes;
83 }
84 
85 bool
is_byte_count_ge(unsigned long test) const86 Article :: is_byte_count_ge (unsigned long test) const
87 {
88   unsigned long bytes = 0;
89   for (part_iterator it(pbegin()), end(pend()); it!=end; ++it)
90     if (((bytes += it.bytes())) >= test)
91       return true;
92   return false;
93 }
94 
95 Article :: mid_sequence_t
get_part_mids() const96 Article :: get_part_mids () const
97 {
98   mid_sequence_t mids;
99   for (part_iterator it(pbegin()), end(pend()); it!=end; ++it)
100   {
101     mids.push_back (it.mid());
102   }
103   return mids;
104 }
105 
106 //const Quark&
107 //Article :: get_attachment () const
108 //{
109 //  for (part_iterator it(pbegin()), end(pend()); it!=end; ++it)
110 //    if (it.mid() == search)
111 //}
112 
113 void
clear()114 Article :: clear ()
115 {
116   message_id.clear ();
117   author.clear ();
118   subject.clear ();
119   time_posted = 0;
120   xref.clear ();
121   score = 0;
122   parts.clear ();
123   is_binary = false;
124 }
125