Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | ##---------------------------------------------------------------------------## |
2 | ## File: | |
3 | ## $Id: mhthread.pl,v 2.10 2002/06/27 04:56:41 ehood Exp $ | |
4 | ## Author: | |
5 | ## Earl Hood mhonarc@mhonarc.org | |
6 | ## Description: | |
7 | ## Thread routines for MHonArc | |
8 | ##---------------------------------------------------------------------------## | |
9 | ## MHonArc -- Internet mail-to-HTML converter | |
10 | ## Copyright (C) 1995-2001 Earl Hood, mhonarc@mhonarc.org | |
11 | ## | |
12 | ## This program is free software; you can redistribute it and/or modify | |
13 | ## it under the terms of the GNU General Public License as published by | |
14 | ## the Free Software Foundation; either version 2 of the License, or | |
15 | ## (at your option) any later version. | |
16 | ## | |
17 | ## This program is distributed in the hope that it will be useful, | |
18 | ## but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 | ## GNU General Public License for more details. | |
21 | ## | |
22 | ## You should have received a copy of the GNU General Public License | |
23 | ## along with this program; if not, write to the Free Software | |
24 | ## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | |
25 | ## 02111-1307, USA | |
26 | ##---------------------------------------------------------------------------## | |
27 | ||
28 | package mhonarc; | |
29 | ||
30 | ##--------------------------------------------------------------------------- | |
31 | ## write_thread_index outputs the thread index | |
32 | ## | |
33 | sub write_thread_index { | |
34 | local($onlypg) = shift; | |
35 | local($tmpl, $handle); | |
36 | local($index) = (""); | |
37 | local(*a); | |
38 | local($PageNum, $PageSize, $totalpgs, %Printed); | |
39 | local($lastlevel, $tlevel, $iscont, $i, $offstart, $offend); | |
40 | ||
41 | local($level) = 0; ## !!!Used in print_thread!!! | |
42 | local($last0index) = ''; | |
43 | ||
44 | ## Make sure list orders are set | |
45 | if (!scalar(@TListOrder)) { | |
46 | &compute_threads(); | |
47 | } | |
48 | if (!scalar(@MListOrder)) { # need for resource variable expansions | |
49 | @MListOrder = &sort_messages(); | |
50 | %Index2MLoc = (); | |
51 | @Index2MLoc{@MListOrder} = (0 .. $#MListOrder); | |
52 | } | |
53 | ||
54 | &compute_page_total(); | |
55 | @ThreadList = @TListOrder; | |
56 | $PageNum = $onlypg || 1; | |
57 | $totalpgs = $onlypg || $NumOfPages; | |
58 | ||
59 | for ( ; $PageNum <= $totalpgs; ++$PageNum) { | |
60 | next if $PageNum < $TIdxMinPg; | |
61 | ||
62 | if ($MULTIIDX) { | |
63 | $offstart = ($PageNum-1) * $IDXSIZE; | |
64 | $offend = $offstart + $IDXSIZE-1; | |
65 | $offend = $#TListOrder if $#TListOrder < $offend; | |
66 | @a = @TListOrder[$offstart..$offend]; | |
67 | ||
68 | if ($PageNum > 1) { | |
69 | $TIDXPATHNAME = join("", $OUTDIR, $DIRSEP, | |
70 | $TIDXPREFIX, $PageNum, ".", $HtmlExt); | |
71 | } else { | |
72 | $TIDXPATHNAME = join($DIRSEP, $OUTDIR, $TIDXNAME); | |
73 | } | |
74 | ||
75 | } else { | |
76 | $TIDXPATHNAME = join($DIRSEP, $OUTDIR, $TIDXNAME); | |
77 | if ($IDXSIZE && (($i = ($#ThreadList+1) - $IDXSIZE) > 0)) { | |
78 | if ($TREVERSE) { | |
79 | @NotIdxThreadList = splice(@ThreadList, $IDXSIZE); | |
80 | } else { | |
81 | @NotIdxThreadList = splice(@ThreadList, 0, $i); | |
82 | } | |
83 | } | |
84 | *a = *ThreadList; | |
85 | } | |
86 | $PageSize = scalar(@a); | |
87 | ||
88 | if ($IDXONLY) { | |
89 | $handle = 'STDOUT'; | |
90 | } else { | |
91 | ($handle = &file_create($TIDXPATHNAME, $GzipFiles)) || | |
92 | die("ERROR: Unable to create $TIDXPATHNAME\n"); | |
93 | } | |
94 | print STDOUT "Writing $TIDXPATHNAME ...\n" unless $QUIET; | |
95 | ||
96 | $tmpl = ($TIDXPGSSMARKUP ne '') ? $TIDXPGSSMARKUP : $SSMARKUP; | |
97 | if ($tmpl ne '') { | |
98 | $tmpl =~ s/$VarExp/&replace_li_var($1,'')/geo; | |
99 | print $handle $tmpl; | |
100 | } | |
101 | ||
102 | print $handle "<!-- ", &commentize("MHonArc v$VERSION"), " -->\n"; | |
103 | ||
104 | ($tmpl = $TIDXPGBEG) =~ s/$VarExp/&replace_li_var($1,'')/geo; | |
105 | print $handle $tmpl; | |
106 | ||
107 | ($tmpl = $THEAD) =~ s/$VarExp/&replace_li_var($1,'')/geo; | |
108 | print $handle $tmpl; | |
109 | ||
110 | ## Flag visible messages for use in printing thread index page | |
111 | foreach $index (@a) { $TVisible{$index} = 1; } | |
112 | ||
113 | ## Print index. Print unless message has been printed, or | |
114 | ## unless it has reference that is visible. | |
115 | $level = 0; # !!!Used in print_thread!!! | |
116 | $lastlevel = $ThreadLevel{$a[0]}; | |
117 | ||
118 | # check if continuing a thread | |
119 | if ($lastlevel > 0) { | |
120 | ($tmpl = $TCONTBEG) =~ s/$VarExp/&replace_li_var($1,$a[0])/geo; | |
121 | print $handle $tmpl; | |
122 | } | |
123 | # perform any indenting | |
124 | for ($i=0; $i < $lastlevel; ++$i) { | |
125 | ++$level; | |
126 | if ($level <= $TLEVELS) { | |
127 | ($tmpl = $TINDENTBEG) =~ s/$VarExp/&replace_li_var($1,'')/geo; | |
128 | print $handle $tmpl; | |
129 | } | |
130 | } | |
131 | # print index listing | |
132 | foreach $index (@a) { | |
133 | $tlevel = $ThreadLevel{$index}; | |
134 | if (($lastlevel > 0) && ($tlevel < $lastlevel)) { | |
135 | for ($i=$tlevel; $i < $lastlevel; ++$i) { | |
136 | if ($level <= $TLEVELS) { | |
137 | ($tmpl = $TINDENTEND) =~ | |
138 | s/$VarExp/&replace_li_var($1,'')/geo; | |
139 | print $handle $tmpl; | |
140 | } | |
141 | --$level; | |
142 | } | |
143 | $lastlevel = $tlevel; | |
144 | if ($lastlevel < 1) { # Check if continuation done | |
145 | ($tmpl = $TCONTEND) =~ | |
146 | s/$VarExp/&replace_li_var($1,'')/geo; | |
147 | print $handle $tmpl; | |
148 | } | |
149 | } | |
150 | unless ($Printed{$index} || | |
151 | ($HasRef{$index} && $TVisible{$HasRef{$index}})) { | |
152 | &print_thread($handle, $index, | |
153 | ($lastlevel > 0) ? 0 : 1); | |
154 | } | |
155 | } | |
156 | # unindent if required | |
157 | for ($i=0; $i < $lastlevel; ++$i) { | |
158 | if ($level <= $TLEVELS) { | |
159 | ($tmpl = $TINDENTEND) =~ s/$VarExp/&replace_li_var($1,'')/geo; | |
160 | print $handle $tmpl; | |
161 | } | |
162 | --$level; | |
163 | } | |
164 | # close continuation if required | |
165 | if ($lastlevel > 0) { | |
166 | ($tmpl = $TCONTEND) =~ s/$VarExp/&replace_li_var($1,'')/geo; | |
167 | print $handle $tmpl; | |
168 | } | |
169 | ||
170 | ## Reset visibility flags | |
171 | foreach $index (@a) { $TVisible{$index} = 0; } | |
172 | ||
173 | ($tmpl = $TFOOT) =~ s/$VarExp/&replace_li_var($1,'')/geo; | |
174 | print $handle $tmpl; | |
175 | ||
176 | &output_doclink($handle); | |
177 | ||
178 | ($tmpl = $TIDXPGEND) =~ s/$VarExp/&replace_li_var($1,'')/geo; | |
179 | print $handle $tmpl; | |
180 | ||
181 | print $handle "<!-- ", &commentize("MHonArc v$VERSION"), " -->\n"; | |
182 | ||
183 | close($handle) unless $IDXONLY; | |
184 | } | |
185 | } | |
186 | ||
187 | ##--------------------------------------------------------------------------- | |
188 | ## Routine to compute the order messages are listed by thread. | |
189 | ## Main use is to provide the ability to correctly define | |
190 | ## values for resource variables related to next/prev thread | |
191 | ## message. | |
192 | ## | |
193 | ## NOTE: Thread order is determined by all the messages in an | |
194 | ## archive, and not by what is visible in the thread index page. | |
195 | ## Hence, if the thread index page size is less than number of | |
196 | ## messages, the next/prev messages of thread (accessible via | |
197 | ## resource variables) will not necessarily correspond to the | |
198 | ## actual physical next/prev message listed in the thread index. | |
199 | ## | |
200 | ## The call to do_thread() defines the TListOrder array for use | |
201 | ## in expanding thread related resource variables. | |
202 | ## | |
203 | sub compute_threads { | |
204 | local(%FirstSub2Index) = (); | |
205 | local(%Counted) = (); | |
206 | local(%stripsub) = (); | |
207 | local(@refs); | |
208 | local($index, $msgid, $refindex, $depth, $tmp); | |
209 | ||
210 | ## Reset key data structures | |
211 | @TListOrder = (); | |
212 | %Index2TLoc = (); | |
213 | %ThreadLevel = (); | |
214 | %HasRef = (); | |
215 | %HasRefDepth = (); | |
216 | %Replies = (); | |
217 | %SReplies = (); | |
218 | ||
219 | ## Sort by date first for subject based threads | |
220 | @ThreadList = sort_messages(0,0,0,0); | |
221 | ||
222 | ## Find first occurrances of subjects | |
223 | if (!$NoSubjectThreads) { | |
224 | foreach $index (@ThreadList) { | |
225 | $tmp = lc $Subject{$index}; | |
226 | 1 while (($tmp =~ s/^$SubReplyRxp//io) || | |
227 | ($tmp =~ s/\s*-\s*re(ply|sponse)\s*$//io)); | |
228 | ||
229 | $stripsub{$index} = $tmp; | |
230 | next unless $tmp =~ /\S/; | |
231 | $FirstSub2Index{$tmp} = $index | |
232 | unless defined($FirstSub2Index{$tmp}) || | |
233 | (defined($Refs{$index}) && | |
234 | grep($MsgId{$_}, @{$Refs{$index}})); | |
235 | } | |
236 | } | |
237 | ||
238 | ## Compute thread data | |
239 | TCOMP: foreach $index (@ThreadList) { | |
240 | next unless defined($Refs{$index}); | |
241 | ||
242 | # Check for explicit threading | |
243 | if (@refs = @{$Refs{$index}}) { | |
244 | $depth = 0; | |
245 | while ($msgid = pop(@refs)) { | |
246 | if (($refindex = $MsgId{$msgid})) { | |
247 | ||
248 | $HasRef{$index} = $refindex; | |
249 | $HasRefDepth{$index} = $depth; | |
250 | if ($Replies{$refindex}) { | |
251 | push(@{$Replies{$refindex}}, $index); | |
252 | } else { | |
253 | $Replies{$refindex} = [ $index ]; | |
254 | } | |
255 | next TCOMP; | |
256 | } | |
257 | ++$depth; | |
258 | } | |
259 | } | |
260 | ||
261 | } continue { | |
262 | # Check for subject-based threading | |
263 | if (!$NoSubjectThreads && !$HasRef{$index}) { | |
264 | $refindex = $FirstSub2Index{$stripsub{$index}}; | |
265 | if ($refindex && ($refindex ne $index)) { | |
266 | ||
267 | $HasRef{$index} = $refindex; | |
268 | $HasRefDepth{$index} = 0; | |
269 | if ($SReplies{$refindex}) { | |
270 | push(@{$SReplies{$refindex}}, $index); | |
271 | } else { | |
272 | $SReplies{$refindex} = [ $index ]; | |
273 | } | |
274 | } | |
275 | } | |
276 | } | |
277 | ||
278 | ## Calculate thread listing order | |
279 | @ThreadList = sort_messages($TNOSORT, $TSUBSORT, 0, $TREVERSE); | |
280 | foreach $index (@ThreadList) { | |
281 | unless ($Counted{$index} || $HasRef{$index}) { | |
282 | &do_thread($index, 0); | |
283 | } | |
284 | } | |
285 | } | |
286 | ||
287 | ##--------------------------------------------------------------------------- | |
288 | ## do_thread() computes the order messages are listed by thread. | |
289 | ## Uses %Counted defined locally in compute_thread_from_list(). | |
290 | ## do_thread() main purpose is to set the TListOrder array and | |
291 | ## Index2TLoc assoc array. | |
292 | ## | |
293 | sub do_thread { | |
294 | local($idx, $level) = ($_[0], $_[1]); | |
295 | local(@repls, @srepls) = (); | |
296 | ||
297 | ## Get replies | |
298 | @repls = sort increase_index @{$Replies{$idx}} | |
299 | if defined($Replies{$idx}); | |
300 | @srepls = sort increase_index @{$SReplies{$idx}} | |
301 | if defined($SReplies{$idx}); | |
302 | ||
303 | ## Add index to printed order list (IMPORTANT SIDE-EFFECT) | |
304 | push(@TListOrder, $idx); | |
305 | $Index2TLoc{$idx} = $#TListOrder; | |
306 | ||
307 | ## Mark message | |
308 | $Counted{$idx} = 1; | |
309 | $ThreadLevel{$idx} = $level; | |
310 | ||
311 | if (@repls) { | |
312 | foreach (@repls) { | |
313 | &do_thread($_, $level + 1 + $HasRefDepth{$_}); | |
314 | } | |
315 | } | |
316 | if (@srepls) { | |
317 | foreach (@srepls) { | |
318 | &do_thread($_, $level + 1 + $HasRefDepth{$_}); | |
319 | } | |
320 | } | |
321 | } | |
322 | ||
323 | ##--------------------------------------------------------------------------- | |
324 | ## Routine to print thread. | |
325 | ## Uses %Printed defined by caller. | |
326 | ## | |
327 | sub print_thread { | |
328 | local($handle, $idx, $top) = ($_[0], $_[1], $_[2]); | |
329 | my(@repls, @srepls) = (); | |
330 | my($attop, $haverepls, $hvnirepls, $single, $depth, $i); | |
331 | my $didtliend = 0; | |
332 | ||
333 | ## Get replies | |
334 | @repls = sort increase_index @{$Replies{$idx}} | |
335 | if defined($Replies{$idx}); | |
336 | @srepls = sort increase_index @{$SReplies{$idx}} | |
337 | if defined($SReplies{$idx}); | |
338 | $depth = $HasRefDepth{$idx}; | |
339 | $hvnirepls = (@repls || @srepls); | |
340 | ||
341 | @repls = grep($TVisible{$_}, @repls); | |
342 | @srepls = grep($TVisible{$_}, @srepls); | |
343 | $haverepls = (@repls || @srepls); | |
344 | ||
345 | ## $hvnirepls is a flag if the message has replies, but they are | |
346 | ## not visible. $haverepls is a flag if the message has visible | |
347 | ## replies. $hvnirepls is used to determine the $attop and | |
348 | ## $single flags. $haverepls is used for determine recursive | |
349 | ## calls and level. | |
350 | ||
351 | ## Print entry | |
352 | #$attop = ($top && $haverepls); | |
353 | #$single = ($top && !$haverepls); | |
354 | $attop = ($top && $hvnirepls); | |
355 | $single = ($top && !$hvnirepls); | |
356 | ||
357 | if ($attop) { | |
358 | &print_thread_var($handle, $idx, \$TTOPBEG); | |
359 | } elsif ($single) { | |
360 | &print_thread_var($handle, $idx, \$TSINGLETXT); | |
361 | } else { | |
362 | ## Check for missing messages | |
363 | if ($DoMissingMsgs) { | |
364 | for ($i=$depth; $i > 0; --$i) { | |
365 | ++$level; | |
366 | &print_thread_var($handle, $idx, \$TLINONE); | |
367 | &print_thread_var($handle, $idx, \$TSUBLISTBEG) | |
368 | if $level <= $TLEVELS; | |
369 | } | |
370 | } | |
371 | &print_thread_var($handle, $idx, \$TLITXT); | |
372 | } | |
373 | ||
374 | ## Increment level count if their are replies | |
375 | ++$level if ($haverepls); | |
376 | ||
377 | ## Print list item close if hit max depth | |
378 | if (!$attop && !$single && ($level > $TLEVELS)) { | |
379 | &print_thread_var($handle, $idx, \$TLIEND); | |
380 | $didtliend = 1; | |
381 | } | |
382 | ||
383 | ## Mark message printed | |
384 | $Printed{$idx} = 1; | |
385 | ||
386 | ## Print sub-threads | |
387 | if (scalar(@repls) || scalar(@srepls)) { | |
388 | &print_thread_var($handle, $idx, \$TSUBLISTBEG) if $level <= $TLEVELS; | |
389 | foreach (@repls) { | |
390 | &print_thread($handle, $_); | |
391 | } | |
392 | if (@srepls) { | |
393 | &print_thread_var($handle, $idx, \$TSUBJECTBEG); | |
394 | foreach (@srepls) { | |
395 | &print_thread($handle, $_); | |
396 | } | |
397 | &print_thread_var($handle, $idx, \$TSUBJECTEND); | |
398 | } | |
399 | &print_thread_var($handle, $idx, \$TSUBLISTEND) if $level <= $TLEVELS; | |
400 | } | |
401 | ||
402 | ## Decrement level count if their were replies | |
403 | --$level if ($haverepls); | |
404 | ||
405 | ## Check for missing messages | |
406 | if ($DoMissingMsgs && !($attop || $single)) { | |
407 | for ($i=$depth; $i > 0; --$i) { | |
408 | &print_thread_var($handle, $idx, \$TLINONEEND); | |
409 | &print_thread_var($handle, $idx, \$TSUBLISTEND) | |
410 | if $level <= $TLEVELS; | |
411 | --$level; | |
412 | } | |
413 | } | |
414 | ||
415 | ## Close entry text | |
416 | if ($attop) { | |
417 | &print_thread_var($handle, $idx, \$TTOPEND); | |
418 | } elsif (!$single && !$didtliend) { | |
419 | &print_thread_var($handle, $idx, \$TLIEND); | |
420 | } | |
421 | } | |
422 | ||
423 | ##--------------------------------------------------------------------------- | |
424 | ## Print out text based upon resource variable referenced by $tvar. | |
425 | ## | |
426 | sub print_thread_var { | |
427 | my($handle, $index, $tvar) = @_; | |
428 | my($tmpl); | |
429 | ($tmpl = $$tvar) =~ s/$VarExp/&replace_li_var($1,$index)/geo; | |
430 | print $handle $tmpl; | |
431 | } | |
432 | ||
433 | ##--------------------------------------------------------------------------- | |
434 | ## make_thread_slice generates a slice of the thread listing. | |
435 | ## Arguments are: | |
436 | ## | |
437 | ## $refindex : Reference message index that slice is based | |
438 | ## $bcnt : Number of messages before $refindex to list | |
439 | ## $acnt : Number of messages after $refindex to list | |
440 | ## | |
441 | ## Returns string containing thread slice text. | |
442 | ## | |
443 | sub make_thread_slice { | |
444 | my($refindex, $bcnt, $acnt, $inclusive) = @_; | |
445 | my($slicetxt) = ""; | |
446 | ||
447 | my($pos) = $Index2TLoc{$refindex}; | |
448 | my($start) = $pos - $bcnt; | |
449 | my($end) = $pos + $acnt; | |
450 | $start = 0 if $start < 0; | |
451 | $end = $#TListOrder if $end > $#TListOrder; | |
452 | if ($inclusive) { | |
453 | # adjust before count | |
454 | if ($bcnt == 0 || $ThreadLevel{$TListOrder[$pos]} <= 0) { | |
455 | $start = $pos; | |
456 | } else { | |
457 | for ($i=$pos-1; ($i > $start) && ($i > 0); --$i) { | |
458 | last if ($ThreadLevel{$TListOrder[$i]} <= 0); | |
459 | } | |
460 | $start = $i; | |
461 | } | |
462 | # adjust after count | |
463 | if ($acnt != 0) { | |
464 | for ($i=$pos+1; ($i <= $end) && ($i <= $#TListOrder); ++$i) { | |
465 | last if ($ThreadLevel{$TListOrder[$i]} <= 0); | |
466 | } | |
467 | $end = $i-1; | |
468 | } | |
469 | ||
470 | } | |
471 | my(@a) = @TListOrder[$start..$end]; | |
472 | my($lastlevel) = $ThreadLevel{$a[0]}; | |
473 | my($tmpl, $index, $tlevel, $iscont, $i); | |
474 | ||
475 | local($level) = 0; ## XXX: Used in make_thread!!! | |
476 | local(%Printed) = (); ## XXX: Used in make_thread!!! | |
477 | ||
478 | ($tmpl = $TSLICEBEG) =~ s/$VarExp/&replace_li_var($1,'')/geo; | |
479 | $slicetxt .= $tmpl; | |
480 | ||
481 | ## Flag visible messages for use in printing thread | |
482 | foreach $index (@a) { $TVisible{$index} = 1; } | |
483 | ||
484 | # check if continuing a thread | |
485 | if ($lastlevel > 0) { | |
486 | ($tmpl = $TSLICECONTBEG) =~ s/$VarExp/&replace_li_var($1,$a[0])/geo; | |
487 | $slicetxt .= $tmpl; | |
488 | } | |
489 | # perform any indenting | |
490 | for ($i=0; $i < $lastlevel; ++$i) { | |
491 | ++$level; | |
492 | if ($level <= $TSLICELEVELS) { | |
493 | ($tmpl = $TSLICEINDENTBEG) =~ s/$VarExp/&replace_li_var($1,'')/geo; | |
494 | $slicetxt .= $tmpl; | |
495 | } | |
496 | } | |
497 | # print index listing | |
498 | foreach $index (@a) { | |
499 | $tlevel = $ThreadLevel{$index}; | |
500 | if (($lastlevel > 0) && ($tlevel < $lastlevel)) { | |
501 | for ($i=$tlevel; $i < $lastlevel; ++$i) { | |
502 | if ($level <= $TSLICELEVELS) { | |
503 | ($tmpl = $TSLICEINDENTEND) =~ | |
504 | s/$VarExp/&replace_li_var($1,'')/geo; | |
505 | $slicetxt .= $tmpl; | |
506 | } | |
507 | --$level; | |
508 | } | |
509 | $lastlevel = $tlevel; | |
510 | if ($lastlevel < 1) { # Check if continuation done | |
511 | ($tmpl = $TSLICECONTEND) =~ | |
512 | s/$VarExp/&replace_li_var($1,'')/geo; | |
513 | $slicetxt .= $tmpl; | |
514 | } | |
515 | } | |
516 | unless ($Printed{$index} || | |
517 | ($HasRef{$index} && $TVisible{$HasRef{$index}})) { | |
518 | $slicetxt .= &make_thread($index, | |
519 | (($lastlevel > 0) ? 0 : 1), $refindex); | |
520 | } | |
521 | } | |
522 | # unindent if required | |
523 | for ($i=0; $i < $lastlevel; ++$i) { | |
524 | if ($level <= $TSLICELEVELS) { | |
525 | ($tmpl = $TSLICEINDENTEND) =~ s/$VarExp/&replace_li_var($1,'')/geo; | |
526 | $slicetxt .= $tmpl; | |
527 | } | |
528 | --$level; | |
529 | } | |
530 | # close continuation if required | |
531 | if ($lastlevel > 0) { | |
532 | ($tmpl = $TSLICECONTEND) =~ s/$VarExp/&replace_li_var($1,'')/geo; | |
533 | $slicetxt .= $tmpl; | |
534 | } | |
535 | ||
536 | ## Reset visibility flags | |
537 | foreach $index (@a) { $TVisible{$index} = 0; } | |
538 | ||
539 | ($tmpl = $TSLICEEND) =~ s/$VarExp/&replace_li_var($1,'')/geo; | |
540 | $slicetxt .= $tmpl; | |
541 | ||
542 | $slicetxt; | |
543 | } | |
544 | ||
545 | ##--------------------------------------------------------------------------- | |
546 | ## Routine to generate text representing a thread. | |
547 | ## Used by make_thread_slice(). | |
548 | ## Uses %Printed and $level defined by caller. | |
549 | ## | |
550 | sub make_thread { | |
551 | my($idx, $top, $refidx) = @_; | |
552 | my($attop, $haverepls, $hvnirepls, $single, $depth, $i); | |
553 | my(@repls, @srepls) = ( ); | |
554 | my($ret) = ""; | |
555 | ||
556 | ## Get replies | |
557 | @repls = sort increase_index @{$Replies{$idx}} | |
558 | if defined($Replies{$idx}); | |
559 | @srepls = sort increase_index @{$SReplies{$idx}} | |
560 | if defined($SReplies{$idx}); | |
561 | $depth = $HasRefDepth{$idx}; | |
562 | $hvnirepls = (@repls || @srepls); | |
563 | ||
564 | @repls = grep($TVisible{$_}, @repls); | |
565 | @srepls = grep($TVisible{$_}, @srepls); | |
566 | $haverepls = (@repls || @srepls); | |
567 | ||
568 | ## $hvnirepls is a flag if the message has replies, but they are | |
569 | ## not visible. $haverepls is a flag if the message has visible | |
570 | ## replies. $hvnirepls is used to determine the $attop and | |
571 | ## $single flags. $haverepls is used for determine recursive | |
572 | ## calls and level. | |
573 | ||
574 | ## Print entry | |
575 | $attop = ($top && $hvnirepls); | |
576 | $single = ($top && !$hvnirepls); | |
577 | ||
578 | if ($attop) { | |
579 | $ret .= &expand_thread_var($idx, | |
580 | ($idx eq $refidx) ? \$TSLICETOPBEGCUR : \$TSLICETOPBEG); | |
581 | } elsif ($single) { | |
582 | $ret .= &expand_thread_var($idx, | |
583 | ($idx eq $refidx) ? \$TSLICESINGLETXTCUR: \$TSLICESINGLETXT); | |
584 | } else { | |
585 | ## Check for missing messages | |
586 | if ($DoMissingMsgs) { | |
587 | for ($i = $depth; $i > 0; $i--) { | |
588 | $level++; | |
589 | $ret .= &expand_thread_var($idx, \$TSLICELINONE); | |
590 | $ret .= &expand_thread_var($idx, \$TSLICESUBLISTBEG) | |
591 | if $level <= $TSLICELEVELS; | |
592 | } | |
593 | } | |
594 | $ret .= &expand_thread_var($idx, | |
595 | ($idx eq $refidx) ? \$TSLICELITXTCUR : \$TSLICELITXT); | |
596 | } | |
597 | ||
598 | ## Increment level count if their are replies | |
599 | if ($haverepls) { | |
600 | $level++; | |
601 | } | |
602 | ||
603 | ## Mark message printed | |
604 | $Printed{$idx} = 1; | |
605 | ||
606 | ## Print sub-threads | |
607 | if (@repls) { | |
608 | $ret .= &expand_thread_var($idx, \$TSLICESUBLISTBEG) | |
609 | if $level <= $TSLICELEVELS; | |
610 | foreach (@repls) { | |
611 | $ret .= &make_thread($_, 0, $refidx); | |
612 | } | |
613 | $ret .= &expand_thread_var($idx, \$TSLICESUBLISTEND) | |
614 | if $level <= $TSLICELEVELS; | |
615 | } | |
616 | if (@srepls) { | |
617 | $ret .= &expand_thread_var($idx, \$TSLICESUBLISTBEG) | |
618 | if $level <= $TSLICELEVELS; | |
619 | $ret .= &expand_thread_var($idx, \$TSLICESUBJECTBEG); | |
620 | foreach (@srepls) { | |
621 | $ret .= &make_thread($_, 0, $refidx); | |
622 | } | |
623 | $ret .= &expand_thread_var($idx, \$TSLICESUBJECTEND); | |
624 | $ret .= &expand_thread_var($idx, \$TSLICESUBLISTEND) | |
625 | if $level <= $TSLICELEVELS; | |
626 | } | |
627 | ||
628 | ## Decrement level count if their were replies | |
629 | if ($haverepls) { | |
630 | $level--; | |
631 | } | |
632 | ## Check for missing messages | |
633 | if ($DoMissingMsgs && !($attop || $single)) { | |
634 | for ($i = $depth; $i > 0; $i--) { | |
635 | $ret .= &expand_thread_var($idx, \$TSLICELINONEEND); | |
636 | $ret .= &expand_thread_var($idx, \$TSLICESUBLISTEND) | |
637 | if $level <= $TSLICELEVELS; | |
638 | $level--; | |
639 | } | |
640 | } | |
641 | ||
642 | ## Close entry text | |
643 | if ($attop) { | |
644 | $ret .= &expand_thread_var($idx, | |
645 | ($idx eq $refidx) ? \$TSLICETOPENDCUR : \$TSLICETOPEND); | |
646 | } elsif (!$single) { | |
647 | $ret .= &expand_thread_var($idx, | |
648 | ($idx eq $refidx) ? \$TSLICELIENDCUR : \$TSLICELIEND); | |
649 | } | |
650 | ||
651 | $ret; | |
652 | } | |
653 | ||
654 | ##--------------------------------------------------------------------------- | |
655 | ## Expand text based upon resource variable referenced by $tvar. | |
656 | ## | |
657 | sub expand_thread_var { | |
658 | my($index, $tvar) = @_; | |
659 | my($expstr); | |
660 | ($expstr = $$tvar) =~ s/$VarExp/&replace_li_var($1,$index)/geo; | |
661 | $expstr; | |
662 | } | |
663 | ||
664 | ##--------------------------------------------------------------------------- | |
665 | 1; |