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() const32Article :: 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() const57Article :: 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)66Article :: 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() const77Article :: 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) const86Article :: 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() const96Article :: 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()114Article :: 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