home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / EXTRAS / UUCODE / UUCP / RSNU106A.ZIP / src / rusnmain.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1994-04-12  |  50.1 KB  |  1,980 lines

  1. unit rusnmain;
  2.  
  3. {
  4.  
  5. rusnmain.pas - rusnews main (to keep from recompiling huge rusnews.pas)
  6.  
  7. }
  8.  
  9. {$I rusn-def.pas}
  10.  
  11. interface
  12.  
  13. uses dos,crt,rusngenf,rusnfunc,rusnglob,rusnselb,rusntime,rusnio,
  14.   rusnproc,rusnkill
  15.  
  16. {$ifdef mouse}
  17.  
  18. ,mouse   {the mouse unit I have is from Turbo Technix}
  19.  
  20. {$endif}
  21.  
  22. ;
  23.  
  24.  
  25. procedure shutdown(exitcode: integer);
  26. procedure usage;
  27. procedure defaultlppcols;
  28.  
  29. {$ifdef mouse}
  30. procedure handler     { Mouse event handler called by device driver }
  31.    (flags, cs, ip, ax, bx, cx, dx, si, di, ds, es, bp: word);
  32. interrupt;
  33. {$endif}
  34.  
  35. procedure fixuplppcols;
  36. procedure sethash(var h: hashedt; s: string);
  37. procedure backupjoin;
  38. procedure swapi(var i,j: integer);
  39. procedure swapart(a,b: integer);
  40. procedure sortitall;
  41. procedure readinarts;
  42. procedure groupinit;
  43. procedure findhighest;
  44. procedure initialize;
  45.  
  46. implementation
  47.  
  48. procedure shutdown;
  49.  
  50. begin
  51.   if joinfn<>'' then
  52.     close(joinf);
  53.   if haskillfile then
  54.     close(killf);
  55.   if hasantikillfile then
  56.     close(antikillf);
  57.  
  58. {$ifdef mouse}
  59.  
  60.   if hasmouse then
  61.     begin
  62.       mhide;
  63.       mreset(themouse);
  64.     end;
  65.  
  66. {$endif}
  67.  
  68.   xgotoxy(1,lpp);
  69.   xwriteln;
  70.   if console then
  71.     begin
  72.       textattr := oldtextattr;
  73.       xwriteln;
  74.     end;
  75.   halt(exitcode);
  76. end;
  77.  
  78. procedure usage;
  79.  
  80. begin
  81.   xwritelnsss('usage: ',newsreadername,' [options]');
  82.   xwritelns('  -u --user %A');
  83.   xwritelns('  -n --newsgroup c.b.w (jumps directly to that newsgroup)');
  84.   xwritelns('  -p --port 0 (uses that fossil port - 0=COM1, 1=COM2)');
  85.   xwritelns('  -f --fullname Full_Name (underscores will become spaces)');
  86.   xwritelns('  -e --editor d:/path/editor.exe (uses this editor)');
  87.   xwritelns('  -o --editor-options !_w:\user\%A (editor non-filename options)');
  88.   xwritelns('  -s --forum-set-list local_usenet (uses these forum sets only)');
  89.   xwritelns('  -t --trusted (allows dialin users to edit articles)');
  90.   xwritelns('  -v --waffle-version %V (specifies waffle version)');
  91.   xwritelns('  -m --minutes %O (specifies minutes online time)');
  92.   xwritelns('  -d --shadow 1 (shadows all COMx output to console)');
  93.   xwritelns('  -r --rcfile w:/waffle/lib/rusnews.opt (reads in options)');
  94.   xwriteln;
  95.   xwritelns('see documentation for other configuration options');
  96.   xwriteln;
  97.   xwritelns('russell@alpha3.ersys.edmonton.ab.ca (931208)');
  98.   shutdown(1);
  99. end;
  100.  
  101. {$ifdef mouse}
  102.  
  103. procedure handler;
  104.  
  105. begin
  106.   mousevent.event     := ax;
  107.   mousevent.btnstatus := bx;
  108.   mousevent.horiz     := cx;
  109.   mousevent.vert      := dx;
  110.   inline (        { Exit processing for far return to device driver }
  111.        $8B/$E5/            { MOV  SP, BP }
  112.        $5D/                { POP  BP }
  113.        $07/                { POP  ES }
  114.        $1F/                { POP  DS }
  115.        $5F/                { POP  DI }
  116.        $5E/                { POP  SI }
  117.        $5A/                { POP  DX }
  118.        $59/                { POP  CX }
  119.        $5B/                { POP  BX }
  120.        $58/                { POP  AX }
  121.        $CB );              { RETF    }
  122. end;
  123.  
  124. {$endif}
  125.  
  126. procedure defaultlppcols;
  127.  
  128. begin
  129.   if console then
  130.     begin
  131.       if detectvideo then
  132.         begin
  133.           lpp := mem[$40:$84]+1;
  134.           cols := mem[$40:$4a];
  135.         end
  136.       else
  137.         begin
  138.           lpp := 25;
  139.           cols := 80
  140.         end;
  141.     end
  142.   else
  143.     begin
  144.       lpp := 24;
  145.       cols := 80;
  146.     end;
  147.  
  148. end;
  149.  
  150. procedure fixuplppcols;
  151.  
  152. begin
  153.   lpp := max(minlpp,min(lpp,maxlpp));
  154.   cols := max(mincols,min(cols,maxcols));
  155.  
  156. {26 letters+10 digits for toggles}
  157.  
  158.   sellpp := min(lpp-selheaderlines-4,36);
  159. end;
  160.  
  161. procedure sethash;
  162.  
  163. var
  164.   i: integer;
  165.   atat: integer;
  166. {$ifdef oldhash}
  167.   ls,rs: integer;
  168. {$endif}
  169.   leng: integer;
  170.   l: integer;
  171.   startaft: integer;
  172.  
  173. begin
  174. {$ifdef oldhash}
  175.   for i := 1 to 6 do
  176.     h[i] := 0;
  177.   atat := pos('@',s);
  178.   if atat=0 then
  179.     begin
  180. {leave malformed ones alone}
  181.     end
  182.   else
  183.     begin
  184. {assume all message-ids are at least 6 chars long - a@b.cd is}
  185.       ls := atat-6;
  186.       rs := atat+1;
  187. {handle these specially - the last bunch of stuff is always the same!}
  188.       if pos(newsreadername,s)>0 then
  189.         ls := 10;
  190.       if ls<1 then
  191.         ls := 1;
  192.       if atat>length(s)-5 then
  193.         rs := length(s)-5;
  194.       for i := 1 to 3 do
  195.         h[i] := 16*( (ord(s[ls+i*2-1])) and 15)+( (ord(s[ls+i*2])) and 15);
  196.       for i := 1 to 3 do
  197.         h[i+3] := 16*( (ord(s[rs+i*2-1])) and 15)+( (ord(s[rs+i*2])) and 15);
  198.     end;
  199. {$endif}
  200.  
  201.   h[1] := 0;
  202.   h[2] := 0;
  203.   atat := pos('@',s);
  204.   if atat=0 then
  205.     begin
  206. {leave malformed ones alone}
  207.     end
  208.   else
  209.     begin
  210.       leng := length(s);
  211.       l := min(16,leng);
  212.       for i := 1 to l do
  213.         if odd(ord(s[i])) then
  214.           h[1] := (h[1] shl 1)+1
  215.         else
  216.           h[1] := h[1] shl 1;
  217.       l := min(16,leng);
  218.       startaft := leng-l;
  219.       if startaft>atat then
  220.         startaft := atat;
  221.       for i := 1 to l do
  222.         if odd(ord(s[startaft+i])) then
  223.           h[2] := (h[2] shl 1)+1
  224.         else
  225.           h[2] := h[2] shl 1;
  226.     end;
  227.  
  228. {$ifdef testhash}
  229.  
  230. {
  231. writeln('hashed "',s,'" to ',h[1]:5,' ',h[2]:5);
  232. }
  233.  
  234. {$endif}
  235.  
  236. end;
  237.  
  238. procedure backupjoin;
  239.  
  240. var
  241.   s: string;
  242.   tempf: text;
  243.   createjoined: boolean;
  244.  
  245. begin
  246.   xwritelns('Backing up join file...');
  247.   createjoined := (numjoined=0);
  248.   assign(tempf,home+'\join.bak');
  249.   reset(joinf);
  250.   rewrite(tempf);
  251.   while not eof(joinf) do
  252.     begin
  253.       readln(joinf,s);
  254.       writeln(tempf,s);
  255.       if createjoined and (numjoined<maxjoined) then
  256.         begin
  257.           inc(numjoined);
  258.           joinedgroups[numjoined] := getfirstw(s);
  259.         end;
  260.     end;
  261.   close(tempf);
  262.   reset(joinf);
  263. end;
  264.  
  265. procedure swapi;
  266.  
  267. var
  268.   t: integer;
  269.  
  270. begin
  271.   t := i;
  272.   i := j;
  273.   j := t;
  274. end;
  275.  
  276. procedure swapart;
  277.  
  278. var
  279.   tempsubj: subjstringt;
  280.   tempfilename: fnstringt;
  281.   tempdate: datet;
  282.   tempindents: byte;
  283.   tempsizeink: byte;
  284.   tempfrom: fromstringt;
  285.  
  286. {don't need to worry about hashing stuff - by this time, not needed}
  287.  
  288. begin
  289.   tempsubj := basesubjs[a];
  290.   tempfilename := filenamesp^[a];
  291.   tempdate := datesp^[a];
  292.   tempindents := indents[a];
  293.   tempsizeink := sizeink[a];
  294.   tempfrom := fromsp^[a];
  295.  
  296.   basesubjs[a] := basesubjs[b];
  297.   filenamesp^[a] := filenamesp^[b];
  298.   datesp^[a] := datesp^[b];
  299.   indents[a] := indents[b];
  300.   sizeink[a] := sizeink[b];
  301.   fromsp^[a] := fromsp^[b];
  302.  
  303.   basesubjs[b] := tempsubj;
  304.   filenamesp^[b] := tempfilename;
  305.   datesp^[b] := tempdate;
  306.   indents[b] := tempindents;
  307.   sizeink[b] := tempsizeink;
  308.   fromsp^[b] := tempfrom;
  309. end;
  310.  
  311. procedure sortitall;
  312.  
  313. var
  314.   i,j: integer;
  315.   dateptrs,subjptrs,finalptrs,revfinalptrs: array[1..maxarts] of integer;
  316.   dateptrsdone: integer;
  317.   finalptrsdone: integer;
  318.   finalstart: integer;
  319.   currsubjptr: integer;
  320.   foundnewsubj: boolean;
  321.   currsubj: subjstringt;
  322.  
  323. begin
  324.  
  325. {first sort by date, then for each oldest article, take the rest of the}
  326. {articles in that thread together, sorting within the thread only}
  327.  
  328.   for i := 1 to numarts do
  329.     dateptrs[i] := i;
  330.  
  331. {the dates equal but subjects not test is for comp.sources.* etc. v29i033}
  332. {hopefully will help part 1/6 posts too (eg alt.sources)}
  333.  
  334.   for i := 1 to numarts-1 do
  335.     for j := i+1 to numarts do
  336.       if (datesp^[dateptrs[i]]>datesp^[dateptrs[j]]) then
  337.         swapi(dateptrs[i],dateptrs[j])
  338.       else if ( (datesp^[dateptrs[i]]=datesp^[dateptrs[j]]) and
  339.        firstsubjg(basesubjs[dateptrs[i]],basesubjs[dateptrs[j]]) ) then
  340.         swapi(dateptrs[i],dateptrs[j]);
  341.  
  342.   for i := 1 to numarts do
  343.     subjptrs[i] := i;
  344.  
  345.   for i := 1 to numarts-1 do
  346.     for j := i+1 to numarts do
  347.       if firstsubjg(basesubjs[subjptrs[i]],basesubjs[subjptrs[j]]) then
  348.         swapi(subjptrs[i],subjptrs[j]);
  349.  
  350. {sort via finalptrs indirection to prevent extra swapping}
  351.  
  352.   dateptrsdone := 0;
  353.   finalptrsdone := 0;
  354.   while finalptrsdone<numarts do
  355.     begin
  356.       inc(dateptrsdone);
  357.  
  358.       if dateptrs[dateptrsdone]>0 then
  359.         begin
  360.  
  361.           currsubj := basesubjs[dateptrs[dateptrsdone]];
  362.  
  363.           currsubjptr := 1;
  364.           while firstsubjg(currsubj,basesubjs[subjptrs[currsubjptr]]) do
  365.             inc(currsubjptr);
  366.  
  367.           finalstart := finalptrsdone+1;
  368.           foundnewsubj := false;
  369.           while (finalptrsdone<numarts) and not foundnewsubj do
  370.             begin
  371.               if subjseq(currsubj,basesubjs[subjptrs[currsubjptr]]) then
  372.                 begin
  373.                   inc(finalptrsdone);
  374.                   finalptrs[finalptrsdone] := subjptrs[currsubjptr];
  375.                   inc(currsubjptr);
  376.                 end
  377.               else
  378.                 foundnewsubj := true;
  379.             end;
  380.  
  381. {$ifdef testsort}
  382. write('now have: ');
  383. for i := finalstart to finalptrsdone do
  384.   write(finalptrs[i],' ');
  385. writeln;
  386. xwrites('pausing...');
  387. xwritelns(xreadkey);
  388. {$endif}
  389.  
  390.           for i := finalstart to finalptrsdone-1 do
  391.             for j := i+1 to finalptrsdone do
  392.               if not firstartfirst(finalptrs[i],finalptrs[j]) then
  393.                 swapi(finalptrs[i],finalptrs[j]);
  394.  
  395.           for i := 1 to numarts do
  396.             if subjseq(basesubjs[dateptrs[i]],currsubj) then
  397.               dateptrs[i] := -dateptrs[i];
  398.  
  399.         end;
  400.     end;
  401.  
  402.   for i := 1 to numarts do
  403.     revfinalptrs[finalptrs[i]] := i;
  404.  
  405.   for i := 1 to numarts-1 do
  406.     if finalptrs[i]<>i then
  407.       begin
  408.         swapart(i,finalptrs[i]);
  409.         finalptrs[revfinalptrs[i]] := finalptrs[i];
  410.         revfinalptrs[finalptrs[i]] := revfinalptrs[i];
  411.         finalptrs[i] := i;
  412.         revfinalptrs[i] := i;
  413.       end;
  414.  
  415. end;
  416.  
  417. procedure readinarts;
  418.  
  419. var
  420.   sawanyclose: boolean;
  421.   wroteanything: boolean;
  422.   lowfilenum: word;
  423.   fileinfo: searchrec;
  424.   doserr: integer;
  425.   subject: string;
  426.   from: string;
  427.   newsgroups: string;
  428.   messageid: string;
  429.   references: string;
  430.   inreplyto: string;
  431.   filename: string;
  432.   filenum: word;
  433.   datestr: string;
  434.   bufferedkey: char;
  435.   i: integer;
  436.   workwithit: boolean;
  437.   readnomore: boolean;
  438.   highestfile: word;
  439.   mangledsubject: string;
  440.   mailgroup: boolean;
  441.   waskilled: boolean;
  442.   possgroup: string;
  443.  
  444. begin
  445.   sawanyclose := false;
  446.   wroteanything := false;
  447.   if readallarts then
  448.     lowfilenum := 0
  449.   else if readpagesback<>0 then
  450.     lowfilenum := max(alreadyread-readpagesback*sellpp,0)
  451.   else
  452.     lowfilenum := alreadyread;
  453.   readallarts := false;
  454.   readpagesback := 0;
  455.   nextwhilereading := false;
  456.   readnomore := false;
  457.   highestart := 0;
  458.   highestfile := 0;
  459.  
  460.   bufferedkey := ' ';
  461.  
  462.   findfirst(basedir+'*.*',archive,fileinfo);
  463.   doserr := doserror;
  464.   if doserr<>0 then
  465.     sawanyclose := true;  {if there's no files at ALL, that's close enough}
  466.  
  467.   while (doserr=0) and (numarts<maxarts) and not nextwhilereading and
  468.    not readnomore do
  469.     begin
  470.       if xkeypressed then
  471.         begin
  472.           bufferedkey := xreadkey;
  473.           if bufferedkey='N' then
  474.             nextwhilereading := true
  475.           else if bufferedkey='O' then
  476.             readnomore := true
  477.           else if (bufferedkey='!') and trusted then
  478.             begin
  479.               shellout;
  480.             end
  481.           else if bufferedkey='Q' then
  482.             begin
  483. {}{} {should it use confirmquit here?}
  484.               nextwhilereading := true;
  485.               alreadyingroup := true;
  486.               currgroup := '';
  487.             end;
  488.         end;
  489.  
  490.       filenum := atow(fileinfo.name);
  491.  
  492.       if (filenum>=lowfilenum) and
  493.        (fileinfo.name[1]>='0') and (fileinfo.name[1]<='9') then
  494.         sawanyclose := true;
  495.  
  496.       if not nextwhilereading and not readnomore and
  497.        (filenum>lowfilenum) and
  498.        (fileinfo.name[1]>='0') and (fileinfo.name[1]<='9') then
  499.         begin
  500.  
  501. {some people put tabs in the Subject: line!  ick!}
  502.  
  503.           filename := basedir+fileinfo.name;
  504.           subject := expand(getheaderline(filename,'subject:'));
  505.  
  506.           from := getheaderline(filename,'from:');
  507.           newsgroups := getheaderline(filename,'newsgroups:');
  508.  
  509.           if justdots then
  510.             xwrites('.')
  511.           else
  512.             xwrites(fileinfo.name);
  513.  
  514.           wroteanything := true;
  515.  
  516. {if there's from and newsgroups, but no subject, let it pass}
  517.  
  518.           if (subject='') and (from<>'') and (newsgroups<>'') then
  519.             subject := '(No subject - please provide one)';
  520.  
  521.           mailgroup := ismailgroup(currgroup);
  522.  
  523.           if mailgroup and (subject='') then
  524.             subject := '(No subject)';
  525.  
  526.           if (subject='') and missingsubjectisok then
  527.             subject := '(No subject - please provide one)';
  528.  
  529.           waskilled := false;
  530.           workwithit := true;
  531.  
  532.           if not mailgroup then
  533.             begin
  534.               if subject='' then
  535.                 begin
  536.                   workwithit := false;
  537.                   xwrites('e');
  538.                 end
  539.               else if alreadyseen(newsgroups) then
  540.                 begin
  541.                   workwithit := false;
  542.                   xwrites('s');
  543.                 end
  544.               else
  545.                 begin
  546.                   workwithit := not subjkilled(subject);
  547.                   if workwithit then
  548.                     workwithit := not fromkilled(from);
  549.                   waskilled := not workwithit;
  550.                   if waskilled then
  551.                     xwrites('k');
  552.                   if antikillevenkilled then
  553.                     workwithit := true;
  554.                 end;
  555.             end;
  556.  
  557.           if workwithit then
  558.             begin
  559.               inc(numarts);
  560.               filenamesp^[numarts] := fileinfo.name;
  561.  
  562. { use mangledsubject instead of basesubjs[numarts] to prevent accidental }
  563. { thread separation when Re: makes it go beyond subjstringt length }
  564.  
  565. { changed 'Re: ' to 'Re:' - a LOT of broken systems out there! }
  566.  
  567.               mangledsubject := subject;
  568.               indents[numarts] := 0;
  569.               while upper(copy(mangledsubject,1,3))='RE:' do
  570.                 begin
  571.                   inc(indents[numarts]);
  572.                   mangledsubject := ltrim(copy(mangledsubject,4,255));
  573.                 end;
  574.               basesubjs[numarts] := mangledsubject;
  575.  
  576.               fromsp^[numarts] := trim(ltrim(getfromname(from)));
  577.               if fromsp^[numarts]='' then
  578.                 fromsp^[numarts] := getfromaddr(from);
  579.  
  580.               if fileinfo.size>255*1024 then
  581.                 sizeink[numarts] := 255
  582.               else
  583.                 sizeink[numarts] :=
  584.                  longint(fileinfo.size+1023) div longint(1024);
  585.  
  586.               datestr := getheaderline(filename,'date:');
  587.               datesp^[numarts] := stringtodate(datestr);
  588.  
  589.               messageid := getheaderline(filename,'message-id:');
  590.               sethash(hmessageidsp^[numarts],messageid);
  591.  
  592.               references := getheaderline(filename,'references:');
  593.  
  594. { Andrew system non-compliance, looks like }
  595.  
  596.               inreplyto := getheaderline(filename,'in-reply-to:');
  597.  
  598. { needs to only grab up to the next > char}
  599.  
  600.               if length(references)+length(inreplyto)<250 then
  601.                 if copy(inreplyto,1,1)='<' then
  602.                   references := references+' '+inreplyto;
  603.  
  604. { don't wipe out data with a 0 just because there's nothing in the header }
  605.               if numoccur('<',references)>0 then
  606.                 indents[numarts] := numoccur('<',references);
  607.  
  608.               if not mailgroup then
  609.                 begin
  610.  
  611. {for use with auto-select key - start of antikill}
  612.                   if antikillreferences then
  613.                     if pos(node,references)<>0 then
  614.                       indents[numarts] := indents[numarts] or 128;
  615.  
  616. {for author's use to make sure everything's working}
  617.                   if antikillthisnewsreader then
  618.                     if pos(newsreadername,messageid)<>0 then
  619.                       indents[numarts] := indents[numarts] or 128;
  620.  
  621.                   if indents[numarts]<128 then
  622.                     if subjantikilled(subject) then
  623.                       indents[numarts] := indents[numarts] or 128
  624.                     else if fromantikilled(from) then
  625.                       indents[numarts] := indents[numarts] or 128;
  626.  
  627.                   if (indents[numarts] and 128)<>0 then
  628.                     xwrites('a');
  629.  
  630.                 end;
  631.  
  632.               if (indents[numarts]<128) and waskilled then
  633.                 begin
  634. {if was killed, only antikilling can bring it back}
  635.                   dec(numarts);
  636.                 end
  637.               else
  638.                 begin
  639.                   while numoccur('>',references)>4 do
  640.                     messageid := chopfirstw(references);
  641.  
  642.                   sethash(hreferencesp[1]^[numarts],chopfirstw(references));
  643.                   sethash(hreferencesp[2]^[numarts],chopfirstw(references));
  644.                   sethash(hreferencesp[3]^[numarts],chopfirstw(references));
  645.                   sethash(hreferencesp[4]^[numarts],chopfirstw(references));
  646.  
  647.                   if filenum>highestart then
  648.                     highestart := filenum;
  649.                 end
  650.  
  651.             end;
  652.  
  653.           if not justdots then
  654.             if wanderingnumbers then
  655.               xwrites(' ')
  656.             else
  657.               xwritess('     ',^M);
  658.  
  659.           if not readnomore then
  660.             if filenum>highestfile then
  661.               highestfile := filenum;
  662.         end;
  663.       findnext(fileinfo);
  664.       doserr := doserror;
  665.     end;
  666.  
  667.   if numarts=0 then
  668.     begin
  669.       if wroteanything then
  670.         xwriteln;
  671.       xwritelns('no new articles');
  672.     end
  673.   else if wanderingnumbers then
  674.     xwriteln;
  675.  
  676.   if not sawanyclose and not nextwhilereading and not readnomore then
  677.     warn3(
  678.      'there ARE articles for this group on disk, but none close',
  679.      'to the entry in your join file.  you may want to check for',
  680.      're-sequenced or missing news files');
  681.  
  682. {if all were read but filtered, show them as read to avoid scanning next time}
  683.  
  684.   if (numarts=0) and not nextwhilereading and not readnomore then
  685.     updatejoin(highestfile);
  686.  
  687.   if (doserr=0) and (numarts=maxarts) then
  688.     begin
  689.       warn('not all articles read in!');
  690.     end;
  691.  
  692. {handle 'G'oto while scanning already-read groups where O doesn't work}
  693.  
  694.   if xkeypressed then
  695.     bufferedkey := xreadkey;
  696.  
  697.   if bufferedkey='G' then
  698.     begin
  699.       possgroup := '';
  700.       pickagroup(possgroup);
  701.       xclreolxy(1,lpp);
  702.       if possgroup<>'' then
  703.         begin
  704.           nextwhilereading := true;
  705.           currgroup := possgroup;
  706.           alreadyingroup := true;
  707.         end;
  708.     end;
  709.  
  710. end;
  711.  
  712. procedure groupinit;
  713.  
  714. procedure groupinitkills;
  715.  
  716. var
  717.   s: string;
  718.   killgroup: string;
  719.   inglobals: boolean;
  720.   killline: integer;
  721.   sizewarned: boolean;
  722.  
  723. function killeof: boolean;
  724.  
  725. begin
  726.   if killfileinmem then
  727.     killeof := (killline>=numkills)
  728.   else
  729.     killeof := eof(killf);
  730. end;
  731.  
  732. function nextkillline: killstringt;
  733.  
  734. var
  735.   s: string;
  736.  
  737. begin
  738.   if killfileinmem then
  739.     begin
  740.       inc(killline);
  741.       nextkillline := killtextp^[killline];
  742.     end
  743.   else
  744.     begin
  745.       readln(killf,s);
  746.       nextkillline := s;
  747.     end;
  748. end;
  749.  
  750. begin
  751.  
  752. {read in kill file for this group}
  753.  
  754.   numsubjks := 0;
  755.   numfromks := 0;
  756.   nonglobalkills := false;
  757.  
  758.   killline := 0;
  759.   inglobals := true;
  760.  
  761.   sizewarned := false;
  762.  
  763.   if haskillfile then
  764.     begin
  765.       if not killfileinmem then
  766.         begin
  767.           if not quiet then
  768.             xwritelns('reading in kill file...');
  769.           reset(killf);
  770.         end;
  771.  
  772. {allow defaults to come before the first Newsgroups line}
  773.  
  774.       killgroup := currgroup;
  775.       while not killeof do
  776.         begin
  777.           s := nextkillline;
  778.  
  779. {if it's a new Newsgroups: selection, then check it - otherwise, process}
  780.  
  781.           if parseheadername(s)='Newsgroups' then
  782.             begin
  783.               killgroup := parseheadervalue(s);
  784.               inglobals := false;
  785.             end
  786.           else if killgroup=currgroup then
  787.             begin
  788.  
  789.               if showsubjectkills and showfromkills then
  790.                 xwritelnss('kill: ',s)
  791.               else
  792.                 begin
  793.                   if showsubjectkills then
  794.                     if parseheadername(s)='Subject' then
  795.                       xwritelnss('kill: ',s);
  796.                   if showfromkills then
  797.                     if parseheadername(s)='From' then
  798.                       xwritelnss('kill: ',s);
  799.                 end;
  800.  
  801.               if parseheadername(s)='Subject' then
  802.                 begin
  803.                   if numsubjks<maxkills then
  804.                     begin
  805.                       inc(numsubjks);
  806.                       killsubjsp^[numsubjks] := parseheadervalue(s);
  807.                       if not inglobals then
  808.                         nonglobalkills := true;
  809.                     end
  810.                   else
  811.                     begin
  812. {}{} {too many subject kills - ignore}
  813. {}{} {should discard the oldest one}
  814.                       if not sizewarned then
  815.                         warn('kill file is larger than memory allows');
  816.                       sizewarned := true;
  817.                     end;
  818.                 end
  819.               else if parseheadername(s)='From' then
  820.                 begin
  821.                   if numfromks<maxkills then
  822.                     begin
  823.                       inc(numfromks);
  824.                       killfromsp^[numfromks] := parseheadervalue(s);
  825.                       if not inglobals then
  826.                         nonglobalkills := true;
  827.                     end
  828.                   else
  829.                     begin
  830. {}{} {too many from kills - ignore}
  831. {}{} {should discard the oldest one}
  832.                       if not sizewarned then
  833.                         warn('kill file is larger than memory allows');
  834.                       sizewarned := true;
  835.                     end;
  836.                 end
  837.               else
  838.                 begin
  839. {}{} {invalid entry in kill file}
  840.                   warn('unrecognizable entry in kill file');
  841.                   warn(copy(s,1,40));
  842.                 end;
  843.             end;
  844.         end;
  845.     end;
  846. end;
  847.  
  848. procedure groupinitantikills;
  849.  
  850. var
  851.   s: string;
  852.   antikillgroup: string;
  853.   inglobals: boolean;
  854.   antikillline: integer;
  855.   sizewarned: boolean;
  856.  
  857. function antikilleof: boolean;
  858.  
  859. begin
  860.   if antikillfileinmem then
  861.     antikilleof := (antikillline>=numantikills)
  862.   else
  863.     antikilleof := eof(antikillf);
  864. end;
  865.  
  866. function nextantikillline: killstringt;
  867.  
  868. var
  869.   s: string;
  870.  
  871. begin
  872.   if antikillfileinmem then
  873.     begin
  874.       inc(antikillline);
  875.       nextantikillline := antikilltextp^[antikillline];
  876.     end
  877.   else
  878.     begin
  879.       readln(antikillf,s);
  880.       nextantikillline := s;
  881.     end;
  882. end;
  883.  
  884. begin
  885.  
  886. {read in antikill file for this group}
  887.  
  888.   numsubjaks := 0;
  889.   numfromaks := 0;
  890.   nonglobalantikills := false;
  891.  
  892.   antikillline := 0;
  893.   inglobals := true;
  894.  
  895.   sizewarned := false;
  896.  
  897.   if hasantikillfile then
  898.     begin
  899.       if not antikillfileinmem then
  900.         begin
  901.           if not quiet then
  902.             xwritelns('reading in antikill file...');
  903.           reset(antikillf);
  904.         end;
  905.  
  906. {allow defaults to come before the first Newsgroups line}
  907.  
  908.       antikillgroup := currgroup;
  909.       while not antikilleof do
  910.         begin
  911.           s := nextantikillline;
  912.  
  913. {if it's a new Newsgroups: selection, then check it - otherwise, process}
  914.  
  915.           if parseheadername(s)='Newsgroups' then
  916.             begin
  917.               antikillgroup := parseheadervalue(s);
  918.               inglobals := false;
  919.             end
  920.           else if antikillgroup=currgroup then
  921.             begin
  922.  
  923.               if showsubjectantikills and showfromantikills then
  924.                 xwritelnss('antikill: ',s)
  925.               else
  926.                 begin
  927.                   if showsubjectantikills then
  928.                     if parseheadername(s)='Subject' then
  929.                       xwritelnss('antikill: ',s);
  930.                   if showfromantikills then
  931.                     if parseheadername(s)='From' then
  932.                       xwritelnss('antikill: ',s);
  933.                 end;
  934.  
  935.               if parseheadername(s)='Subject' then
  936.                 begin
  937.                   if numsubjaks<maxkills then
  938.                     begin
  939.                       inc(numsubjaks);
  940.                       antikillsubjsp^[numsubjaks] := parseheadervalue(s);
  941.                       if not inglobals then
  942.                         nonglobalantikills := true;
  943.                     end
  944.                   else
  945.                     begin
  946. {}{} {too many subject antikills - ignore}
  947. {}{} {should discard the oldest one}
  948.                       if not sizewarned then
  949.                         warn('antikill file is larger than memory allows');
  950.                       sizewarned := true;
  951.                     end;
  952.                 end
  953.               else if parseheadername(s)='From' then
  954.                 begin
  955.                   if numfromaks<maxkills then
  956.                     begin
  957.                       inc(numfromaks);
  958.                       antikillfromsp^[numfromaks] := parseheadervalue(s);
  959.                       if not inglobals then
  960.                         nonglobalantikills := true;
  961.                     end
  962.                   else
  963.                     begin
  964. {}{} {too many from antikills - ignore}
  965. {}{} {should discard the oldest one}
  966.                       if not sizewarned then
  967.                         warn('antikill file is larger than memory allows');
  968.                       sizewarned := true;
  969.                     end;
  970.                 end
  971.               else
  972.                 begin
  973. {}{} {invalid entry in antikill file}
  974.                   warn('unrecognizable entry in antikill file');
  975.                   warn(copy(s,1,40));
  976.                 end;
  977.             end;
  978.         end;
  979.     end;
  980. end;
  981.  
  982. begin
  983.   numarts := 0;
  984.   headerinmem := '';
  985.   highestread := 0;
  986.  
  987.   basedir := getbasedir(currgroup);
  988.   if basedir='' then
  989.     begin
  990.       if haltonunknowngroups then
  991.         begin
  992.           xwritelns('could not find /dir= entry for this group - location of');
  993.           xwritelns('  news unknown.  make sure you are using the new DEFAULT');
  994.           xwritelns('  lines instead of the old (v1.63 and lower) FORUM lines');
  995.           xwriteln;
  996.           xwritelns('also make sure you have not missed any forum sets if you');
  997.           xwritelns('  used the -s or --forum-set-list options');
  998.           shutdown(1);
  999.         end
  1000.       else
  1001.         begin
  1002.           xwritelns('could not find directory for this group... continuing');
  1003.         end;
  1004.     end
  1005.   else
  1006.     begin
  1007.       if not quiet then
  1008.         xwritelnss('news directory=',basedir);
  1009.  
  1010.       groupinitkills;
  1011.       groupinitantikills;
  1012.     end;
  1013. end;
  1014.  
  1015. procedure findhighest;
  1016.  
  1017. const
  1018.   impossiblealreadyread=65535;
  1019.     {note: a word variable, needs to change to maxlongint}
  1020.  
  1021. var
  1022.   s: string;
  1023.  
  1024. begin
  1025.   reset(joinf);
  1026.   alreadyread := impossiblealreadyread;
  1027.   while (alreadyread=impossiblealreadyread) and not eof(joinf) do
  1028.     begin
  1029.       readln(joinf,s);
  1030.       if getfirstw(s)=currgroup then
  1031.         alreadyread := getalreadyread(s);
  1032.     end;
  1033.  
  1034. { only needed for initial single-group stuff }
  1035.  
  1036.   if alreadyread=impossiblealreadyread then
  1037.     begin
  1038.       xwritelnss('not joined to ',currgroup);
  1039.       shutdown(1);
  1040.     end;
  1041.  
  1042. { end of only needed part }
  1043.  
  1044. end;
  1045.  
  1046. procedure initialize;
  1047.  
  1048. var
  1049.   currparmi: integer;
  1050.   currparm: string;
  1051.   nextparm: string;
  1052.   colors: string;
  1053.   optf: text;
  1054.   opttag: string;
  1055.   optval: string;
  1056.   gotogroup: boolean;
  1057.   ch: char;
  1058.  
  1059. function handleoption(tag, value: string): boolean;
  1060.  
  1061. var
  1062.   usedarg: boolean;
  1063.  
  1064. procedure handlemap(cmdline: string);
  1065.  
  1066. var
  1067.   where: string;
  1068.   oldkey,newkey: char;
  1069.   newcmdline: string;
  1070.  
  1071. function whatch: char;
  1072.  
  1073. var
  1074.   result: char;
  1075.   donescan: boolean;
  1076.  
  1077. begin
  1078.   result := chr(0);
  1079.   if length(newcmdline)>0 then
  1080.     begin
  1081.       if (newcmdline[1]='\') and (length(newcmdline)>1) then
  1082.         begin
  1083.           result := newcmdline[2];
  1084.           newcmdline := chop(newcmdline,2);  {get rid of it and the backslash}
  1085.         end
  1086.       else if (newcmdline[1]='=') and (length(newcmdline)>1) then
  1087.         begin
  1088.           newcmdline := chop(newcmdline,1);  {get rid of the equals}
  1089.           donescan := false;
  1090.           while not donescan do
  1091.             begin
  1092.               if length(newcmdline)=0 then
  1093.                 donescan := true     {no more to see}
  1094.               else if (newcmdline[1]<'0') or (newcmdline[1]>'9') then
  1095.                 donescan := true     {no more digits, anyway}
  1096.               else
  1097.                 begin
  1098.                   result := chr(10*ord(result)+ord(newcmdline[1])-ord('0'));
  1099.                   newcmdline := chop(newcmdline,1);   {get rid of digit}
  1100.                 end;
  1101.             end;
  1102.         end
  1103.       else
  1104.         begin
  1105.           result := newcmdline[1];
  1106.           newcmdline := chop(newcmdline,1);
  1107.         end;
  1108.     end;
  1109.   whatch := result;
  1110. end;
  1111.  
  1112. begin
  1113.   newcmdline := cmdline;
  1114.   newkey := chr(0);
  1115.   oldkey := chr(0);
  1116.   where := chopfirstw(newcmdline);
  1117.   newcmdline := ltrim(newcmdline);
  1118.   oldkey := whatch;
  1119.   newcmdline := ltrim(newcmdline);
  1120.   newkey := whatch;
  1121.  
  1122.   if (oldkey<>chr(0)) and (newkey<>chr(0)) then
  1123.     begin
  1124.       if where='browse' then
  1125.         begin
  1126.           browsemap[oldkey] := newkey;
  1127.         end
  1128.       else if where='select' then
  1129.         begin
  1130.           selmap[oldkey] := newkey;
  1131.         end
  1132.       else if where='both' then
  1133.         begin
  1134.           browsemap[oldkey] := newkey;
  1135.           selmap[oldkey] := newkey;
  1136.         end
  1137.       else if where='main' then
  1138.         begin
  1139.           mainmap[oldkey] := newkey;
  1140.         end
  1141.       else
  1142.         begin
  1143.           warn('weird use of map - ignored');
  1144.         end;
  1145.     end
  1146.   else
  1147.     begin
  1148.       warn('weird use of map - ignored');
  1149.     end;
  1150. end;
  1151.  
  1152. begin
  1153.   usedarg := false;
  1154.   if tag='--map' then
  1155.     begin
  1156.       handlemap(value);
  1157.     end
  1158.   else if (tag='-u') or (tag='--user') then
  1159.     begin
  1160.       userid := value;
  1161.       usedarg := true;
  1162.     end
  1163.   else if (tag='-n') or (tag='--newsgroup') then
  1164.     begin
  1165.       currgroup := value;
  1166.       if currgroup<>'' then
  1167.         alreadyingroup := true;
  1168.       usedarg := true;
  1169.     end
  1170.   else if (tag='-g') or (tag='--goto') then
  1171.     begin
  1172.       gotogroup := true;
  1173.       if copy(value,1,1)<>'-' then
  1174.         begin
  1175.           currgroup := value;
  1176.           usedarg := true;
  1177.         end;
  1178.     end
  1179.   else if (tag='-p') or (tag='--port') then
  1180.     begin
  1181.       console := false;
  1182.       port := atoi(value);
  1183.       trusted := false;
  1184.       usedarg := true;
  1185.     end
  1186.   else if tag='--console' then
  1187.     begin
  1188.       console := true;
  1189.       port := -1;
  1190.       trusted := true;
  1191.       minutes := maxint;
  1192.     end
  1193.   else if (tag='-l') or (tag='--lines') then
  1194.     begin
  1195.       lpp := atoi(value);
  1196.     end
  1197.   else if (tag='-c') or (tag='--columns') then
  1198.     begin
  1199.       cols := atoi(value);
  1200.     end
  1201.   else if (tag='-f') or (tag='--fullname') then
  1202.     begin
  1203.       fullname := trim(ununderscore(value));
  1204.       usedarg := true;
  1205.     end
  1206.   else if (tag='-e') or (tag='--editor') then
  1207.     begin
  1208.       editor := value;
  1209.       usedarg := true;
  1210.     end
  1211.   else if (tag='-o') or (tag='--editor-options') then
  1212.     begin
  1213.       editoroptions := ununderscore(value);
  1214.       usedarg := true;
  1215.     end
  1216.   else if (tag='-s') or (tag='--forum-set-list') then
  1217.     begin
  1218.       forumsetl := ununderscore(value);
  1219.       usedarg := true;
  1220.     end
  1221.   else if (tag='-t') or (tag='--trusted') then
  1222.     begin
  1223.       trusted := true;
  1224.     end
  1225.   else if (tag='-v') or (tag='--waffle-version') then
  1226.     begin
  1227.       waffleversion := value;
  1228.       usedarg := true;
  1229.     end
  1230.   else if (tag='-m') or (tag='--minutes') then
  1231.     begin
  1232.       minutes := atoi(value);
  1233.       usedarg := true;
  1234.     end
  1235.   else if (tag='-d') or (tag='--shadow') then
  1236.     begin
  1237.       shadow := atoi(value);
  1238.       usedarg := true;
  1239.     end
  1240.   else if (tag='-r') or (tag='--rcfile') then
  1241.     begin
  1242.       optfn := unslash(value);
  1243.       usedarg := true;
  1244.     end
  1245.   else if tag='--vspeller' then
  1246.     begin
  1247.       vspeller := unslash(value);
  1248.       usedarg := true;
  1249.     end
  1250.   else if tag='--vspeller-options' then
  1251.     begin
  1252.       vspelleroptions := ununderscore(value);
  1253.       usedarg := true;
  1254.     end
  1255.   else if tag='--subjects-case-insensitive' then
  1256.     begin
  1257.       subjectscaseinsensitive := true;
  1258.     end
  1259.   else if tag='--subject-length' then
  1260.     begin
  1261.       if atoi(value)>0 then
  1262.         subjectlength := atoi(value);
  1263.       usedarg := true;
  1264.     end
  1265.   else if tag='--make-space-like-x' then
  1266.     begin
  1267.       makespacelikex := true;
  1268.     end
  1269.   else if tag='--make-return-like-asterisk' then
  1270.     begin
  1271.       handlemap('select =13 *');
  1272.     end
  1273.   else if tag='--hide-these-headers' then
  1274.     begin
  1275.       hideheaders := upper(value);
  1276.       usedarg := true;
  1277.     end
  1278.   else if tag='--show-only-these-headers' then
  1279.     begin
  1280.       showheaders := upper(value);
  1281.       usedarg := true;
  1282.     end
  1283.   else if tag='--highlight-these-headers' then
  1284.     begin
  1285.       highlightheaders := upper(value);
  1286.       usedarg := true;
  1287.     end
  1288.   else if tag='--wandering-numbers' then
  1289.     begin
  1290.       wanderingnumbers := true;
  1291.     end
  1292.   else if tag='--antikill-references' then
  1293.     begin
  1294.       antikillreferences := true;
  1295.     end
  1296.   else if tag='--show-subject-kills' then
  1297.     begin
  1298.       showsubjectkills := true;
  1299.     end
  1300.   else if tag='--show-from-kills' then
  1301.     begin
  1302.       showfromkills := true;
  1303.     end
  1304.   else if tag='--show-subject-antikills' then
  1305.     begin
  1306.       showsubjectantikills := true;
  1307.     end
  1308.   else if tag='--show-from-antikills' then
  1309.     begin
  1310.       showfromantikills := true;
  1311.     end
  1312.   else if tag='--auto-antikill' then
  1313.     begin
  1314.       autoantikill := true;
  1315.     end
  1316.   else if tag='--warn-auto-antikill' then
  1317.     begin
  1318.       warnautoantikill := true;
  1319.     end
  1320.   else if tag='--edit-after-vspell' then
  1321.     begin
  1322.       editaftervspell := true;
  1323.     end
  1324.   else if tag='--case-insensitive-kill' then
  1325.     begin
  1326.       caseinsensitivekill := true;
  1327.     end
  1328.   else if tag='--case-insensitive-antikill' then
  1329.     begin
  1330.       caseinsensitiveantikill := true;
  1331.     end
  1332.   else if tag='--substring-subject-kill' then
  1333.     begin
  1334.       substringsubjectkill := true;
  1335.     end
  1336.   else if tag='--substring-from-kill' then
  1337.     begin
  1338.       substringfromkill := true;
  1339.     end
  1340.   else if tag='--substring-subject-antikill' then
  1341.     begin
  1342.       substringsubjectantikill := true;
  1343.     end
  1344.   else if tag='--substring-from-antikill' then
  1345.     begin
  1346.       substringfromantikill := true;
  1347.     end
  1348.   else if tag='--quiet' then
  1349.     begin
  1350.       quiet := true;
  1351.     end
  1352.   else if tag='--ignore-environment' then
  1353.     begin
  1354.       ignoreenvironment := true;
  1355.     end
  1356.   else if tag='--confirm-next' then
  1357.     begin
  1358.       confirmnext := true;
  1359.     end
  1360.   else if tag='--confirm-quit' then
  1361.     begin
  1362.       confirmquit := true;
  1363.     end
  1364.   else if tag='--missing-subject-is-ok' then
  1365.     begin
  1366.       missingsubjectisok := true;
  1367.     end
  1368.   else if tag='--tilde-home' then
  1369.     begin
  1370.       tildehome := true;
  1371.     end
  1372.   else if tag='--antikill-this-newsreader' then
  1373.     begin
  1374.       antikillthisnewsreader := true;
  1375.     end
  1376.   else if tag='--clear-screen-between-groups' then
  1377.     begin
  1378.       clearscreenbetweengroups := true;
  1379.     end
  1380.   else if tag='--detect-video' then
  1381.     begin
  1382.       detectvideo := true;
  1383.       defaultlppcols;
  1384.     end
  1385.   else if tag='--antikill-even-killed' then
  1386.     begin
  1387.       antikillevenkilled := true;
  1388.     end
  1389.   else if tag='--mail-prefix' then
  1390.     begin
  1391.       mailprefix := value;
  1392.       usedarg := true;
  1393.     end
  1394.   else if tag='--ignore-mouse' then
  1395.     begin
  1396.       ignoremouse := true;
  1397.     end
  1398.   else if tag='--use-bios-for-screen' then
  1399.     begin
  1400.       usebiosforscreen := true;
  1401.     end
  1402.   else if tag='--hide-form-feeds' then
  1403.     begin
  1404.       hideformfeeds := true;
  1405.     end
  1406.   else if tag='--path-userid' then
  1407.     begin
  1408.       pathuserid := value;
  1409.       usedarg := true;
  1410.     end
  1411.   else if tag='--custom-static' then
  1412.     begin
  1413.       customstatic := value;
  1414.       usedarg := true;
  1415.     end
  1416.   else if tag='--halt-on-unknown-groups' then
  1417.     begin
  1418.       haltonunknowngroups := true;
  1419.     end
  1420.   else if tag='--mouse-chars-header' then
  1421.     begin
  1422.       mousecharsheader := value;
  1423.       usedarg := true;
  1424.     end
  1425.   else if tag='--just-dots' then
  1426.     begin
  1427.       justdots := true;
  1428.     end
  1429.   else if tag='--no-filemode' then
  1430.     begin
  1431.       nofilemode := true;
  1432.     end
  1433. {$ifdef uupc}
  1434.   else if tag='--uupc-mode' then
  1435.     begin
  1436.       uupcmode := true;
  1437.     end
  1438. {$endif}
  1439.   else
  1440.     begin
  1441.  
  1442.  
  1443. {$ifdef ignoreoldoptions}
  1444.  
  1445. { compatability switch with earlier releases - now obsolete }
  1446.  
  1447. {try to make sure any error messages are going to be visible!}
  1448.  
  1449.       console := true;
  1450.       xwritesss(newsreadername,' ',newsreaderversion);
  1451.       xwritelnss(': unknown option: ',tag);
  1452.       usage;  {usage shuts down}
  1453.  
  1454. {$else}
  1455.  
  1456.       userid := tag;
  1457.       xwritelns('warning: obsolete usage of userid on the command line');
  1458.       xwritelns('use -u/--user instead');
  1459.  
  1460. {$endif}
  1461.  
  1462.     end;
  1463.  
  1464.   handleoption := usedarg;
  1465.  
  1466. end;
  1467.  
  1468. begin
  1469.   randomize;
  1470.   new(filenamesp);
  1471.   new(fromsp);
  1472.   new(datesp);
  1473.   new(killsubjsp);
  1474.   new(killfromsp);
  1475.   new(killtextp);
  1476.   new(antikillsubjsp);
  1477.   new(antikillfromsp);
  1478.   new(antikilltextp);
  1479.   new(hmessageidsp);
  1480.   new(hreferencesp[1]);
  1481.   new(hreferencesp[2]);
  1482.   new(hreferencesp[3]);
  1483.   new(hreferencesp[4]);
  1484.   userid := '';
  1485.   currgroup := '';
  1486.   forumsetl := '';
  1487.   waffleversion := '';
  1488.  
  1489. {set up things for clean shutdowns}
  1490.  
  1491.   haskillfile := false;
  1492.   hasantikillfile := false;
  1493.   killfileinmem := false;
  1494.   antikillfileinmem := false;
  1495.   joinfn := '';
  1496.   if console then
  1497.     oldtextattr := textattr;
  1498.  
  1499. {$ifdef tiny}
  1500.   console := false;
  1501.   port := 0;
  1502.   trusted := false;
  1503.   minutes := 60;
  1504. {$else}
  1505.   console := true;
  1506.   port := -1;
  1507.   trusted := true;
  1508.   minutes := maxint;
  1509. {$endif}
  1510.  
  1511.   fullname := '';
  1512.   editor := '';
  1513.   editoroptions := '';
  1514.   vspeller := '';
  1515.   vspelleroptions := '';
  1516.   shadow := 0;
  1517.   optfn := '';
  1518.  
  1519.   subjectscaseinsensitive := false;
  1520.   subjectlength := 50;
  1521.   makespacelikex := false;
  1522.   hideheaders := '';
  1523.   showheaders := '';
  1524.   highlightheaders := upper(':Subject:From:Date:');
  1525.   wanderingnumbers := false;
  1526.   antikillreferences := false;
  1527.   showsubjectkills := false;
  1528.   showfromkills := false;
  1529.   showsubjectantikills := false;
  1530.   showfromantikills := false;
  1531.   autoantikill := false;
  1532.   warnautoantikill := false;
  1533.   editaftervspell := false;
  1534.   caseinsensitivekill := false;
  1535.   caseinsensitiveantikill := false;
  1536.   substringsubjectkill := false;
  1537.   substringfromkill := false;
  1538.   substringsubjectantikill := false;
  1539.   substringfromantikill := false;
  1540.   quiet := false;
  1541.   ignoreenvironment := false;
  1542.   confirmnext := false;
  1543.   confirmquit := false;
  1544.   missingsubjectisok := false;
  1545.   tildehome := false;
  1546.   antikillthisnewsreader := false;
  1547.   clearscreenbetweengroups := false;
  1548.   detectvideo := false;
  1549.   antikillevenkilled := false;
  1550.   mailprefix := '';
  1551.   ignoremouse := false;
  1552.   usebiosforscreen := false;
  1553.   hideformfeeds := false;
  1554.   pathuserid := '';
  1555.   customstatic := '';
  1556.   haltonunknowngroups := false;
  1557.   mousecharsheader := '< > ^ $ * - + Q N @ ~ Z G ''';
  1558.   justdots := false;
  1559.   nofilemode := false;
  1560. {$ifdef uupc}
  1561.   uupcmode := false;
  1562. {$endif}
  1563.  
  1564.   alreadyingroup := false;
  1565.   readallarts := false;
  1566.   readpagesback := 0;
  1567.  
  1568.   gotogroup := false;
  1569.  
  1570.   lastfilen := '';
  1571.  
  1572.   defaultlppcols;
  1573.  
  1574.   for ch := chr(0) to chr(255) do
  1575.     begin
  1576.       browsemap[ch] := ch;
  1577.       selmap[ch] := ch;
  1578.       mainmap[ch] := ch;
  1579.     end;
  1580.  
  1581.   currparmi := 1;
  1582.   while currparmi<=paramcount do
  1583.     begin
  1584.       currparm := paramstr(currparmi);
  1585.       if currparmi<paramcount then
  1586.         nextparm := paramstr(currparmi+1)
  1587.       else
  1588.         nextparm := '';
  1589.  
  1590.       if handleoption(currparm,nextparm) then
  1591.         inc(currparmi);
  1592.  
  1593.       inc(currparmi);
  1594.  
  1595.     end;
  1596.  
  1597.   if optfn<>'' then
  1598.     begin
  1599.  
  1600. {waste of time - tpascal doesn't use filemode on text files!}
  1601.  
  1602.       oldfilemode := filemode;
  1603.       if not nofilemode then
  1604.         filemode := $40;   {read only, deny none}
  1605.  
  1606.       assign(optf,optfn);
  1607.       {$I-}
  1608.       reset(optf);
  1609.       {$I+}
  1610.       if ioresult<>0 then
  1611.         begin
  1612.           console := true;
  1613.           xwritelnss('could not open option file ',optfn);
  1614.           shutdown(1);
  1615.         end;
  1616.       optfn := '';
  1617.       while not eof(optf) do
  1618.         begin
  1619.           readln(optf,optval);
  1620.           opttag := chopfirstw(optval);
  1621.           if length(opttag)>0 then
  1622.             if opttag[1]<>'#' then
  1623.               begin
  1624.                 if opttag[1]<>'-' then
  1625.                   opttag := '--'+opttag;
  1626.                 if handleoption(opttag,optval) then
  1627.                   ;
  1628.               end;
  1629.         end;
  1630.       close(optf);
  1631.  
  1632.       filemode := oldfilemode;
  1633.  
  1634.       if optfn<>'' then
  1635.         xwritelns('cannot use -r/--rcfile inside an rcfile, sorry');
  1636.     end;
  1637.  
  1638.   if usebiosforscreen then
  1639.     directvideo := false;
  1640.  
  1641. {try to make sure any error messages are going to be visible!}
  1642.  
  1643.   if not console and (port<>0) and (port<>1) and (port<>2) and (port<>3) then
  1644.     begin
  1645.       console := true;
  1646.       xwritelns('error: -p/--port specified without valid port number');
  1647.       xwritelns('  valid numbers are 0 (COM1) and 1 (COM2)   (2=COM3 and');
  1648.       xwritelns('  3=COM4 allowed, your fossil may not support them)');
  1649.       shutdown(1);
  1650.     end;
  1651.  
  1652. {$ifdef debug}
  1653.   xwritelns('parameters:');
  1654.   for currparmi := 1 to paramcount do
  1655.     xwritelns(paramstr(currparmi));
  1656. {$endif}
  1657.  
  1658.   xwritelnsss(newsreadername,' ',newsreaderversion);
  1659.  
  1660.   if (userid='') and not ignoreenvironment then
  1661.     userid := lower(getenv('NET_NAME'));
  1662.   if (userid='') and not ignoreenvironment then
  1663.     userid := lower(getenv('USER'));
  1664.  
  1665.   if userid='' then
  1666.     usage;
  1667.  
  1668.   xwritelnss('user: ',userid);
  1669.  
  1670.   if pathuserid='' then
  1671.     pathuserid := userid;
  1672.  
  1673.   wafenv := getenv('WAFFLE');
  1674.   if wafenv='' then
  1675.     begin
  1676. {$ifdef nowaffle}
  1677.       xwritelns('no WAFFLE environment variable - using `./static''.');
  1678.       wafenv := './static';
  1679. {$else}
  1680.       xwritelns('must set WAFFLE environment variable');
  1681.       shutdown(1);
  1682. {$endif}
  1683.     end;
  1684.  
  1685.   wafenv := unslash(wafenv);
  1686.  
  1687.   if (waffleversion='') and not ignoreenvironment then
  1688.     waffleversion := getenv('WAFFLEVERSION');
  1689.   if waffleversion='' then
  1690.     waffleversion := getstaticvalue('version');
  1691.   if waffleversion='' then
  1692.     waffleversion := '1.64';
  1693.   if (length(waffleversion)<>4) or (copy(waffleversion,2,1)<>'.') or
  1694.    (numoccur('.',waffleversion)<>1) then
  1695.     begin
  1696.       xwritelns('WAFFLEVERSION environment variable, or static file version:');
  1697.       xwritelns('setting, or -v/--waffle-version argument in wrong format');
  1698.       xwritelns('should be similar to `1.64'' (without the quotes)');
  1699.       xwritelnsss('it is currently set to: `',waffleversion,'''');
  1700.       shutdown(1);
  1701.     end;
  1702.  
  1703.   if not quiet then
  1704.     xwritelnss('waffle version: ',waffleversion);
  1705.  
  1706.   temporarydir := getstaticvalue('temporary');
  1707.   if not ignoreenvironment then
  1708.     begin
  1709.       temporarydir := default(getenv('TMP'),temporarydir);
  1710.       temporarydir := default(getenv('TEMP'),temporarydir);
  1711.     end;
  1712.   temporarydir := default('.',temporarydir);
  1713.   temporarydir := unslash(temporarydir);
  1714.  
  1715.   waffledir := getstaticvalue('waffle');
  1716.   if waffledir='' then
  1717.     waffledir := copy(wafenv,1,rposc(wafenv,'\')-1);
  1718.   waffledir := unslash(waffledir);
  1719.  
  1720.   spooldir := unslash(default(waffledir+'/spool',getstaticvalue('spool')));
  1721.   userdir := unslash(default(waffledir+'/user',getstaticvalue('user')));
  1722.   outboxdir := unslash(default(spooldir+'/outbox',getstaticvalue('outbox')));
  1723.  
  1724.   if fullname='' then
  1725.     begin
  1726.       if waffleversion='1.64' then
  1727.         fullname := trim(getpwinfo164(5))
  1728.       else if waffleversion>='1.65' then
  1729.         fullname := trim(getpwinfo165(3))
  1730.       else
  1731.         xwritelns(
  1732.         'only Waffle 1.64 and 1.65 (and beyond) password file formats known');
  1733.     end;
  1734.   if (fullname='') and not ignoreenvironment then
  1735.     fullname := trim(ununderscore(getenv('FULLNAME')));
  1736.   if fullname='' then
  1737.     begin
  1738.       xwritelnsss('user ',userid,' has no name in the password file');
  1739.       xwritelns('  that can be found, and environment variable FULLNAME');
  1740.       xwritelns('  not set, and option -f/--fullname not used');
  1741.       shutdown(1);
  1742.     end;
  1743.  
  1744.   if not quiet then
  1745.     xwritelnss('full name: ',fullname);
  1746.  
  1747. {}{} {needs to get editor entry from password and extern/_editors files}
  1748.  
  1749.   if (editor='') and not ignoreenvironment then
  1750.     editor := getenv('VISUAL');
  1751.   if (editor='') and not ignoreenvironment then
  1752.     editor := getenv('EDITOR');
  1753.   if editor='' then
  1754.     editor := 'vi.exe';
  1755.  
  1756.   if not quiet then
  1757.     xwritelnss('editor: ',editor);
  1758.  
  1759.   if (vspeller='') and not ignoreenvironment then
  1760.     vspeller := getenv('VSPELL');
  1761.   if (vspeller='') and not ignoreenvironment then
  1762.     vspeller := getenv('SPELL');
  1763.   if vspeller='' then
  1764.     vspeller := 'vspell.exe';
  1765.  
  1766.   if not quiet then
  1767.     xwritelnss('vspeller: ',vspeller);
  1768.  
  1769.   if not quiet then
  1770.     xwritelnsi('minutes left: ',minutes);
  1771.  
  1772.   uucpname := getstaticvalue('uucpname');
  1773.   node := getstaticvalue('node');
  1774.   smarthost := getstaticvalue('smarthost');
  1775.   organ := getstaticvalue('organ');
  1776.   netmail := getstaticvalue('netmail');
  1777.   netnews := getstaticvalue('netnews');
  1778.   replyto := getstaticvalue('replyto');
  1779.   newsname := default(uucpname,getstaticvalue('newsname'));
  1780.  
  1781.   if (uucpname='') or (smarthost='') or (organ='') then
  1782.     begin
  1783.       xwritelns('invalid uucpname, smarthost, or organ static variable');
  1784.       xwritelns('  none of these can be empty');
  1785.       xwritelns('  current values:');
  1786.       xwritelnss('  uucpname:  ',uucpname);
  1787.       xwritelnss('  smarthost: ',smarthost);
  1788.       xwritelnss('  organ:     ',organ);
  1789.       shutdown(1);
  1790.     end;
  1791.  
  1792.   if mailprefix='' then
  1793.     mailprefix := uucpname+'.mail';
  1794.  
  1795. {make life easier later - redefine mailprefix to include userid}
  1796.  
  1797.   mailprefix := mailprefix+'.'+userid;
  1798.  
  1799.   if not quiet then
  1800.     xwritelnss('mail groups begin with ',mailprefix);
  1801.  
  1802.   if netmail='' then
  1803.     netmail := '%A@%n (%W)';
  1804.   if netnews='' then
  1805.     netnews := netmail;
  1806.  
  1807.   mailfrom := wafexpand(netmail);
  1808.   newsfrom := wafexpand(netnews);
  1809.   if replyto<>'' then
  1810.     replyto := wafexpand(replyto);
  1811.  
  1812.   if (numoccur('.',node)=0) or (numoccur('@',newsfrom)<>1) or
  1813.    (numoccur('@',mailfrom)>1) or (numoccur('@',replyto)>1) or
  1814.    ( (numoccur('@',mailfrom)=0) and (numoccur('!',mailfrom)=0) ) then
  1815.     begin
  1816.       xwritelns('invalid node: or netmail:/netnews:/replyto: static entry');
  1817.       xwritelns('  the node entry needs at least one "."');
  1818.       xwritelns('  the netmail entry needs one "@" and/or at least one "!"');
  1819.       xwritelns('  the netnews entry needs one "@"');
  1820.       xwritelns('  the replyto entry (if any) can have at most one "@"');
  1821.       xwriteln;
  1822.       xwritelns('current settings:');
  1823.       xwritelnss('  node:     ',node);
  1824.       xwritelnss('  newsfrom: ',newsfrom);
  1825.       xwritelnss('  mailfrom: ',mailfrom);
  1826.       xwritelnss('  replyto:  ',replyto);
  1827.       shutdown(1);
  1828.     end;
  1829.  
  1830.   if not quiet then
  1831.     xwritelnss('mail from: ',mailfrom);
  1832.   if mailfrom<>newsfrom then
  1833.     if not quiet then
  1834.       xwritelnss('news from: ',newsfrom);
  1835.   if replyto<>'' then
  1836.     if not quiet then
  1837.       if replyto=mailfrom then
  1838.         xwritelnss('reply-to: ','(same as mail)')
  1839.       else if replyto=newsfrom then
  1840.         xwritelnss('reply-to: ','(same as news)')
  1841.       else
  1842.         xwritelnss('reply-to: ',replyto);
  1843.  
  1844.   if forumsetl='' then
  1845.     forumsetl := getstaticvalue('forums');
  1846.  
  1847.   forumsetl := ltrim(trim(forumsetl));
  1848.  
  1849.   if forumsetl='' then
  1850.     begin
  1851.       xwritelns('empty forum set list');
  1852.       shutdown(1);
  1853.     end;
  1854.  
  1855.   if not quiet then
  1856.     xwritelnss('forum set list: ',forumsetl);
  1857.  
  1858.   if not ignoreenvironment then
  1859.     timezone := getenv('TZ');
  1860.  
  1861.   if timezone='' then
  1862.     timezone := getstaticvalue('timezone');
  1863.   if timezone='' then
  1864.     timezone := 'MST';
  1865.   if pos(' ',timezone)>1 then
  1866.     timezone := copy(timezone,1,pos(' ',timezone)-1)
  1867.   else if (timezone[1]<>'+') and (timezone[1]<>'-') then
  1868.     timezone := copy(timezone,1,3);
  1869. { handles TZ=GMT0BST and TZ=+1100 and TZ=BST-1 cases }
  1870.  
  1871.   if not quiet then
  1872.     xwritelnss('timezone: ',timezone);
  1873.  
  1874. {once joinfn is assigned to a nonempty string, it's open}
  1875.  
  1876.   home := userdir+'\'+userid;
  1877.   joinfn := home+'\join';
  1878.   assign(joinf,joinfn);
  1879.   {$I-}
  1880.   reset(joinf);
  1881.   {$I+}
  1882.   if ioresult<>0 then
  1883.     begin
  1884.       xwritelnsss('join file ',joinfn,' not found.');
  1885.       joinfn := '';
  1886.       shutdown(1);
  1887.     end;
  1888.  
  1889.   numjoined := 0;
  1890.   backupjoin;
  1891.  
  1892.   readinkill(true);
  1893.   readinantikill(true);
  1894.  
  1895.   if currgroup<>'' then
  1896.     if not joinedtogroup(currgroup) then
  1897.       begin
  1898.         xwritelnsss('not joined to ',currgroup,
  1899.          ' - starting at top of join file');
  1900.         currgroup := '';
  1901.         alreadyingroup := false;
  1902.       end;
  1903.  
  1904.   minstart := mitoday;
  1905.  
  1906.   fixuplppcols;
  1907.  
  1908.   if not quiet then
  1909.     begin
  1910.       xwritelnsi('lines per page: ',lpp);
  1911.       xwritelnsi('sel lines per page: ',sellpp);
  1912.       xwritelnsi('columns: ',cols);
  1913.       if usebiosforscreen then
  1914.         xwritelns('(using bios for screen writes)');
  1915.       if hideformfeeds then
  1916.         xwritelns('(hiding form feeds)');
  1917.     end;
  1918.  
  1919. {$ifdef mouse}
  1920.  
  1921.   hasmouse := false;
  1922.  
  1923. {$endif}
  1924.  
  1925.   if console then
  1926.     begin
  1927.  
  1928.       oldtextattr := textattr;
  1929.       lowcolor := 7;
  1930.       highcolor := 15;
  1931.       colors := getstaticvalue('colors');
  1932.       if colors='' then
  1933.         colors := getstaticvalue('colours');
  1934.       if colors<>'' then
  1935.         begin
  1936.           lowcolor := atoi(chopfirstw(colors));
  1937.           highcolor := atoi(getfirstw(colors));
  1938.         end;
  1939.       if (lowcolor mod 16)=(highcolor mod 16) then
  1940.         if (lowcolor mod 16)=7 then
  1941.           highcolor := 15
  1942.         else
  1943.           lowcolor := 7;
  1944.       xlowvideo;
  1945.  
  1946. {$ifdef mouse}
  1947.  
  1948.       if not ignoremouse then
  1949.         begin
  1950.           mreset(themouse);
  1951.           hasmouse := themouse.exists;
  1952.         end;
  1953.  
  1954.       if hasmouse then
  1955.         begin
  1956.  
  1957.           minsttask($14,seg(handler),ofs(handler));
  1958.           mousevent.event := 0;
  1959.           mshow;
  1960.         end;
  1961.  
  1962. {$endif}
  1963.  
  1964.     end;
  1965.  
  1966.   if gotogroup then
  1967.     begin
  1968.  
  1969. { make sure last line had no valuable information }
  1970.       xgotoxy(1,lpp);
  1971.       xwriteln;
  1972.  
  1973.       pickagroup(currgroup);
  1974.       if currgroup<>'' then
  1975.         alreadyingroup := true;
  1976.     end;
  1977. end;
  1978.  
  1979. end.
  1980.