1 //  This may look like C code, but it is really -*- C++ -*-
2 
3 //  ------------------------------------------------------------------
4 //  The Goldware Library
5 //  Copyright (C) 1990-1999 Odinn Sorensen
6 //  ------------------------------------------------------------------
7 //  This library is free software; you can redistribute it and/or
8 //  modify it under the terms of the GNU Library General Public
9 //  License as published by the Free Software Foundation; either
10 //  version 2 of the License, or (at your option) any later version.
11 //
12 //  This library is distributed in the hope that it will be useful,
13 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 //  Library General Public License for more details.
16 //
17 //  You should have received a copy of the GNU Library General Public
18 //  License along with this program; if not, write to the Free
19 //  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20 //  MA 02111-1307, USA
21 //  ------------------------------------------------------------------
22 //  $Id: gmowcat2.cpp,v 1.5 2006/05/14 11:45:05 ssianky Exp $
23 //  ------------------------------------------------------------------
24 //  WildCat! 4.x messagebase engine.
25 //  ------------------------------------------------------------------
26 
27 #include <gdbgerr.h>
28 #include <gmemdbg.h>
29 #include <gdbgtrk.h>
30 #include <gmowcat.h>
31 
32 
33 //  ------------------------------------------------------------------
34 
refresh()35 void WCatArea::refresh() {
36 
37   GFTRK("WCatRefresh");
38 
39   // Create new base record or read the existing one
40   if(data->fhix != -1) {
41     if(filelength(data->fhix) < sizeof(WCatBase)) {
42       data->base.recsize = sizeof(WCatIdx);
43       data->base.active = 0;
44       data->base.nextmsgno = 1;
45       lseekset(data->fhix, 0);
46       write(data->fhix, &data->base, sizeof(WCatBase));
47     }
48     else {
49       lseekset(data->fhix, 0);
50       read(data->fhix, &data->base, sizeof(WCatBase));
51     }
52   }
53 
54   int32_t ixnum = (filelength(data->fhix)-sizeof(WCatBase)) / sizeof(WCatIdx);
55 
56   // Are there any msgs?
57   if(ixnum) {
58 
59     // Read the index file
60     data->idx = (WCatIdx*)throw_realloc(data->idx, (uint)(ixnum*sizeof(WCatIdx)));
61     lseekset(data->fhix, sizeof(WCatBase));
62     read(data->fhix, data->idx, (uint)(ixnum*sizeof(WCatIdx)));
63   }
64 
65   GFTRK(0);
66 }
67 
68 
69 //  ------------------------------------------------------------------
70 
raw_scan(int __keep_index,int __scanpm)71 void WCatArea::raw_scan(int __keep_index, int __scanpm) {
72 
73   GFTRK("WCatRawScan");
74 
75   WCatData* _was_data = data;
76   if(_was_data == NULL) {
77     data = wcatdata;
78     wide = wcatwide;
79   }
80 
81   int _wasopen = isopen;
82   if(not _wasopen) {
83     if(ispacked()) {
84       const char* newpath = Unpack(path());
85       if(newpath == NULL)
86         packed(false);
87       set_real_path(newpath ? newpath : path());
88     }
89     isopen++;
90   }
91 
92   // Load the lastread
93   dword _lastread = 0;
94   int _fh = ::sopen(AddPath(real_path(), ".lrd"), O_RDONLY|O_BINARY, WideSharemode, S_STDRD);
95   if(_fh != -1) {
96     lseekset(_fh, wide->userno, sizeof(dword));
97     read(_fh, &_lastread, sizeof(dword));
98     ::close(_fh);
99   }
100 
101   // Open WildCat! files for scanning unless they are already open
102   if(not _wasopen) {
103 
104     data->idx = NULL;
105     data->base.recsize = 0;
106     data->base.active = 0;
107     data->base.nextmsgno = 0;
108 
109     // Open index file
110     data->fhix = ::sopen(AddPath(real_path(), ".ix"), O_RDONLY|O_BINARY, WideSharemode, S_STDRD);
111     if(data->fhix != -1) {
112 
113       // Allocate index buffer and read from file
114       refresh();
115 
116       // Close index file
117       ::close(data->fhix);
118       data->fhix = -1;
119     }
120     if(ispacked()) {
121       CleanUnpacked(real_path());
122     }
123     isopen--;
124   }
125 
126   uint _active = 0;
127   uint _lastread_reln = 0;
128   uint _lastreadfound = 0;
129 
130   if(data->base.active) {
131 
132     // (Re)allocate message index
133     if(__keep_index)
134       Msgn->Resize((uint)data->base.active);
135 
136     // Variables for the loop
137     uint _msgno;
138     uint32_t* _msgndxptr = Msgn->tag;
139     WCatIdx* _ixptr = data->idx;
140     uint  _totalmsgs = data->base.active;
141     uint _firstmsgno = _totalmsgs ? _ixptr->msgno : 0;
142     uint _lastmsgno = 0;
143 
144     // Fill message index
145     while(_active < _totalmsgs) {
146 
147       _active++;
148       _msgno = (_ixptr++)->msgno;
149       if(not _firstmsgno)
150         _firstmsgno = _msgno;
151       if(__keep_index)
152         *_msgndxptr++ = _msgno;
153 
154       // Get the lastread
155       if((_msgno >= _lastread) and (_lastread_reln == 0)) {
156         _lastreadfound = _msgno;
157         _lastread_reln = (uint)(_active - (_msgno != _lastread ? 1 : 0));
158       }
159 
160       // Store last message number
161       _lastmsgno = _msgno;
162     }
163 
164     // If the exact lastread was not found
165     if(_active and (_lastreadfound != _lastread)) {
166 
167       // Higher than highest or lower than lowest?
168       if(_lastread > _lastmsgno)
169         _lastread_reln = _active;
170       else if(_lastread < _firstmsgno)
171         _lastread_reln = 0;
172     }
173   }
174 
175   // Update area data
176   Msgn->SetCount(_active);
177   lastread = _lastread_reln;
178   lastreadentry = _lastreadfound;
179 
180   // Scan for personal mail
181   if(__scanpm) {
182     // Not implemented yet
183   }
184 
185   // Free index buffer if just counting
186   if(not __keep_index or __scanpm)
187     throw_release(data->idx);
188 
189   if(_was_data == NULL) {
190     data = NULL;
191     wide = NULL;
192   }
193 
194   GFTRK(0);
195 }
196 
197 
198 //  ------------------------------------------------------------------
199 
scan()200 void WCatArea::scan() {
201 
202   GFTRK("WCatScan");
203 
204   raw_scan(true);
205 
206   GFTRK(0);
207 }
208 
209 
210 //  ------------------------------------------------------------------
211 
scan_area()212 void WCatArea::scan_area() {
213 
214   GFTRK("WCatScanArea");
215 
216   raw_scan(false);
217 
218   GFTRK(0);
219 }
220 
221 
222 //  ------------------------------------------------------------------
223 
scan_area_pm()224 void WCatArea::scan_area_pm() {
225 
226   GFTRK("WCatScanArea*M");
227 
228   raw_scan(true, true);
229   Msgn->Reset();
230 
231   GFTRK(0);
232 }
233 
234 
235 //  ------------------------------------------------------------------
236