home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / FORUM25C.ZIP / BULLETIN.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1989-02-07  |  30.5 KB  |  1,217 lines

  1. {$R-,S-,V-,B-,L- }
  2. {$O+}
  3.  
  4. UNIT Bulletin;
  5.  
  6.  
  7. {/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\}
  8.  
  9. INTERFACE
  10.  
  11. USES CRT,
  12.      Gentypes,
  13.      Configrt,
  14.      Statret,
  15.      Gensubs,
  16.      Subs1,
  17.      Subs2,
  18.      Userret,
  19.      Textret,
  20.      Mainr1,
  21.      Mainr2,
  22.      Overret1,
  23.      TopPost,       {    Keeps track of top ten posters  }
  24.      Flags;
  25.  
  26.  
  27. {/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\}
  28.  
  29. Procedure Bulletinmenu;
  30.  
  31. {/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\}
  32.  
  33. IMPLEMENTATION
  34.  
  35. {/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\}
  36.  
  37.  
  38. {=============================================================================}
  39.  
  40. TYPE Newscan_modes = (Express,Extended);
  41.  
  42. VAR Scan_mode : Newscan_modes;
  43.     Newscan_sub : BOOLEAN;
  44.  
  45. {=============================================================================}
  46.  
  47. Procedure bulletinmenu;
  48. VAR q,
  49.     Cur_bul,
  50.     lastreadnum : INTEGER;
  51.     Post        : Bulrec;
  52.     Last_msg    : INTEGER;
  53.  
  54. {=============================================================================}
  55.  
  56.   Procedure makeboard; forward;
  57.   Procedure setfirstboard; forward;
  58.  
  59. {=============================================================================}
  60.  
  61.   Function Sponsor_on : BOOLEAN;
  62.   Begin
  63.     Sponsor_on := Match(Curboard.Sponsor,Unam)
  64.   End;
  65.  
  66. {=============================================================================}
  67.  
  68.   Procedure Clear_order(VAR bo : boardorder);
  69.   VAR c1 : BYTE;
  70.   Begin
  71.     For c1 := 0 TO 255 DO bo[c1] := c1
  72.   End;
  73.  
  74. {=============================================================================}
  75.  
  76.   Procedure carryout (VAR bo:boardorder);
  77.   VAR u:userrec;
  78.       cnt,un:integer;
  79.  
  80.     Procedure doone;
  81.     VAR cnt,q:integer;
  82.         ns,a1,a2:set of byte;
  83.     begin
  84.       fillchar (ns,32,0);
  85.       fillchar (a1,32,0);
  86.       fillchar (a2,32,0);
  87.       for cnt:=0 to 255 do begin
  88.         q:=bo[cnt];
  89.         if q in u.newscanconfig then ns:=ns+[cnt];
  90.         if q in u.access1 then a1:=a1+[cnt];
  91.         if q in u.access2 then a2:=a2+[cnt]
  92.       end;
  93.       u.newscanconfig:=ns;
  94.       u.access1:=a1;
  95.       u.access2:=a2;
  96.       seek (ufile,un);
  97.       write (ufile,u)
  98.     end;
  99.  
  100.   begin
  101.     writeln (^B'Adjusting user access flags...');
  102.     seek (ufile,1);
  103.     for un:=1 to numusers do begin
  104.       if (un mod 10)=0 then write (' ',un);
  105.       read (ufile,u);
  106.       if length(u.handle)>0 then doone
  107.     end
  108.   end;
  109.  
  110. {=============================================================================}
  111.  
  112.   Procedure switchboards (bnum1,bnum2:integer; VAR bo:boardorder);
  113.   VAR bd1,bd2:boardrec;
  114.       n1:integer;
  115.   begin
  116.     seekbdfile (bnum1);
  117.     read (bdfile,bd1);
  118.     seekbdfile (bnum2);
  119.     read (bdfile,bd2);
  120.     seekbdfile (bnum1);
  121.     writebdfile (bd2);
  122.     seekbdfile (bnum2);
  123.     writebdfile (bd1);
  124.     n1:=bo[bnum1];
  125.     bo[bnum1]:=bo[bnum2];
  126.     bo[bnum2]:=n1
  127.   end;
  128.  
  129. {=============================================================================}
  130.  
  131.   Procedure seekffile (n:integer);
  132.   begin
  133.     seek (ffile,n-1)
  134.   end;
  135.  
  136. {=============================================================================}
  137.  
  138.   Function numfiles:integer;
  139.   begin
  140.     numfiles:=filesize (ffile)
  141.   end;
  142.  
  143. {=============================================================================}
  144.  
  145.   Procedure assignffile;
  146.   begin
  147.     assign (ffile,boarddir+curboardname+'.FIL')
  148.   end;
  149.  
  150. {=============================================================================}
  151.  
  152.   Procedure formatffile;
  153.   begin
  154.     close (ffile);
  155.     assignffile;
  156.     rewrite (ffile)
  157.   end;
  158.  
  159. {=============================================================================}
  160.  
  161.   Procedure openffile;
  162.   VAR f:filerec;
  163.       i:integer;
  164.   begin
  165.     close (ffile);
  166.     assignffile;
  167.     reset (ffile);
  168.     i:=ioresult;
  169.     if i<>0 then formatffile
  170.   end;
  171.  
  172. {=============================================================================}
  173.  
  174.   Procedure addfile (f:filerec);
  175.   begin
  176.     seekffile (numfiles+1);
  177.     write (ffile,f)
  178.   end;
  179.  
  180. {=============================================================================}
  181.  
  182.   Procedure delfile (fn:integer);
  183.   VAR f:filerec;
  184.       cnt:integer;
  185.   begin
  186.     for cnt:=fn to numfiles-1 do begin
  187.       seekffile (cnt+1);
  188.       read (ffile,f);
  189.       seekffile (cnt);
  190.       write (ffile,f)
  191.     end;
  192.     seekffile (numfiles);
  193.     truncate (ffile)
  194.   end;
  195.  
  196. {=============================================================================}
  197.  
  198.   Procedure seekbfile (n:integer);
  199.   begin
  200.     seek (bfile,n-1); che
  201.   end;
  202.  
  203. {=============================================================================}
  204.  
  205.   Function numbuls:integer;
  206.   begin
  207.     numbuls:=filesize(bfile)
  208.   end;
  209.  
  210. {=============================================================================}
  211.  
  212.   Procedure getlastreadnum;
  213.   VAR oldb:boolean;
  214.       Post:bulrec;
  215.       lr:word;
  216.   begin
  217.     lastreadnum:=numbuls;
  218.     oldb:=false;
  219.     lr:=urec.lastread[curboardnum];
  220.     while (lastreadnum>0) and (not oldb) do begin
  221.       seekbfile (lastreadnum);
  222.       read (bfile,Post);
  223.       oldb:=Post.id=lr;
  224.       if not oldb then lastreadnum:=lastreadnum-1
  225.     end
  226.   end;
  227.  
  228. {=============================================================================}
  229.  
  230.   Procedure assignbfile;
  231.   begin
  232.     assign (bfile,boarddir+curboardname+'.BUL')
  233.   end;
  234.  
  235. {=============================================================================}
  236.  
  237.   Procedure formatbfile;
  238.   begin
  239.     assignbfile;
  240.     rewrite (bfile);
  241.     curboardnum:=searchboard(curboardname);
  242.     if curboardnum=-1 then begin
  243.       curboardnum:=filesize(bdfile);
  244.       fillchar (curboard,sizeof(curboard),0);
  245.       writecurboard
  246.     end
  247.   end;
  248.  
  249. {=============================================================================}
  250.  
  251.   Procedure openbfile;
  252.   VAR Post:bulrec;
  253.       i:integer;
  254.   begin
  255.     curboardnum:=searchboard (curboardname);
  256.     if curboardnum=-1 then begin
  257.       makeboard;
  258.       exit
  259.     end;
  260.     close (bfile);
  261.     assignbfile;
  262.     reset (bfile);
  263.     i:=ioresult;
  264.     if ioresult<>0 then formatbfile;
  265.     getlastreadnum;
  266.     seekbdfile (curboardnum);
  267.     read (bdfile,curboard);
  268.     openffile
  269.   end;
  270.  
  271. {=============================================================================}
  272.  
  273.   Function boardexist(n:sstr):boolean;
  274.   begin
  275.     boardexist:=not (searchboard(n)=-1)
  276.   end;
  277.  
  278. {=============================================================================}
  279.  
  280.   Procedure addbul (VAR Post:bulrec);
  281.   VAR b2:bulrec;
  282.   begin
  283.     if numbuls=0 then Post.id:=0 else begin
  284.       seekbfile (numbuls);
  285.       read (bfile,b2);
  286.       Post.id:=b2.id+1
  287.     end;
  288.     seekbfile (numbuls+1);
  289.     write (bfile,Post)
  290.   end;
  291.  
  292. {=============================================================================}
  293.  
  294.   Function checkcurbul:boolean;
  295.   begin
  296.     if (cur_bul<1) or (cur_bul>numbuls) then begin
  297.       checkcurbul:=false;
  298.       Cur_bul:=0
  299.     end else checkcurbul:=true
  300.   end;
  301.  
  302. {=============================================================================}
  303.  
  304.   Procedure getbrec;
  305.   begin
  306.     if checkcurbul then begin
  307.       seekbfile (Cur_bul);
  308.       read (bfile,Post); che
  309.     end
  310.   end;
  311.  
  312. {=============================================================================}
  313.  
  314.   Procedure delbul (bn:integer; deltext:boolean);
  315.   VAR c,un:integer;
  316.       Post:bulrec;
  317.       u:userrec;
  318.   begin
  319.     if (bn<1) or (bn>numbuls) then exit;
  320.     seekbfile (bn);
  321.     read (bfile,Post);
  322.     if deltext then deletetext (Post.line);
  323.     for c:=bn to numbuls-1 do begin
  324.       seekbfile (c+1);
  325.       read (bfile,Post);
  326.       seekbfile (c);
  327.       write (bfile,Post)
  328.     end;
  329.     seekbfile (numbuls);
  330.     truncate (bfile);
  331.     getlastreadnum
  332.   end;
  333.  
  334. {=============================================================================}
  335.  
  336.   Procedure delboard (bdn:integer);
  337.   VAR bd1:boardrec;
  338.       cnt,nbds:integer;
  339.       bo:boardorder;
  340.   begin
  341.     Clear_order(bo);
  342.     nbds:=filesize(bdfile)-1;
  343.     if nbds=0 then begin
  344.       close (bdfile);
  345.       rewrite (bdfile);
  346.       exit
  347.     end;
  348.     for cnt:=bdn to nbds-1 do begin
  349.       seekbdfile (cnt+1);
  350.       read (bdfile,bd1);
  351.       seekbdfile (cnt);
  352.       writebdfile (bd1);
  353.       bo[cnt]:=cnt+1
  354.     end;
  355.     seek (bdfile,nbds);
  356.     truncate (bdfile);
  357.     seek (bifile,nbds);
  358.     truncate (bifile);
  359.     carryout (bo)
  360.   end;
  361.  
  362. {=============================================================================}
  363.  
  364. {$I UdAscii.Sub}
  365.  
  366. {=============================================================================}
  367.  
  368.   Procedure readcurbul;
  369.   VAR q:anystr;
  370.       t:sstr;
  371.       cnt:integer;
  372.   begin
  373.     if checkcurbul then
  374.       begin
  375.         getbrec;
  376.         If EightyCols in Urec.Config THEN
  377.           Begin
  378.             Tab(^B'[Sub board ] : '^S+Curboard.BoardName,45);
  379.             Writeln(^B'[Number   ] : '^S,Cur_bul,' of ',numbuls);
  380.             Tab(^B'[Title     ] : '^S+Copy(Post.title,1,28),45);
  381.             if issysop or (not Post.anon) then
  382.                writeln('[When     ] : '^S,datestr(Post.when),' at ',timestr(Post.when));
  383.             q:='[Left by   ] : '^S;
  384.             if Post.anon then
  385.              begin
  386.                q:=q+anonymousstr;
  387.                if issysop then q:=q+' ('+Post.leftby+')'
  388.              end
  389.             else
  390.              begin
  391.               if Post.plevel=-1 then
  392.                 t:='unknown'
  393.               else
  394.                 t:=strr(Post.plevel);
  395.               q:=q+Post.leftby+' (Level '+t+')'
  396.              end;
  397.             Writeln(q);
  398.           End
  399.         ELSE
  400.           Begin
  401.             Writeln(^B'[Sub board ] : '^S+Curboard.BoardName,45);
  402.             Writeln(^B'[Number    ] : '^S,Cur_bul,' of ',numbuls);
  403.             writeln(^B'[Title     ] : '^S,Post.title);
  404.             q:='[Left by  ] : '^S;
  405.             if Post.anon then
  406.              begin
  407.                q:=q+anonymousstr;
  408.                if issysop then q:=q+' ('+Post.leftby+')'
  409.              end
  410.             else
  411.              begin
  412.               if Post.plevel=-1 then
  413.                 t:='unknown'
  414.               else
  415.                 t:=strr(Post.plevel);
  416.               q:=q+Post.leftby+' (Level '+t+')'
  417.              end;
  418.             if issysop or (not Post.anon)
  419.                then writeln ('[When     ] : '^S,datestr(Post.when),' at ',timestr(Post.when));
  420.             writeln (q);
  421.             if break then exit;
  422.           End;
  423.       printtext (Post.line)
  424.     end;
  425.     if Cur_bul>lastreadnum then begin
  426.       lastreadnum:=Cur_bul;
  427.       urec.lastread[curboardnum]:=Post.id
  428.     end
  429.   end;
  430.  
  431. {=============================================================================}
  432.  
  433.   Function queryaccess:accesstype;
  434.   begin
  435.     queryaccess:=getuseraccflag (urec,curboardnum)
  436.   end;
  437.  
  438. {=============================================================================}
  439.  
  440.   Procedure autodelete;
  441.   VAR cnt:integer;
  442.   begin
  443.     writeln ('Erasing first five posts...');
  444.     for cnt:=6 downto 2 do delbul (cnt,true)
  445.   end;
  446.  
  447. {=============================================================================}
  448.  
  449.   Procedure postbul(Post_title : AnyStr);
  450.   VAR l:integer;
  451.       m:message;
  452.       Post:bulrec;
  453.   begin
  454.     if ulvl<postlevel then begin
  455.       reqlevel(postlevel);
  456.       exit
  457.     end;
  458.     l:=editor(m,(Post_Title = ''));
  459.     if l>=0 then
  460.       begin
  461.         Inc(urec.nbu);
  462.         writeurec;
  463.         Add_name(Unam,urec.nbu);
  464.         Save_top_posters;
  465.         Post.anon:=m.anon;
  466.         If Post_Title = '' THEN
  467.           Post.title:=m.title
  468.         ELSE
  469.           Post.Title := Post_Title;
  470.         Post.when:=now;
  471.         Post.leftby:=unam;
  472.         Post.line:=l;
  473.         Post.plevel:=ulvl;
  474.         addbul (Post);
  475.         newposts:=newposts+1;
  476.         with curboard do
  477.           if autodel<=numbuls then autodelete
  478.       end
  479.   end;
  480.  
  481. {=============================================================================}
  482.  
  483.   Procedure getbnum (txt:mstr);
  484.   VAR q:boolean;
  485.   begin
  486.     if length(input)>1
  487.       then Cur_bul:=valu(copy(input,2,255))
  488.       else begin
  489.         writestr (^M'Bulletin to '+txt+':');
  490.         Cur_bul:=valu(input)
  491.       end;
  492.     q:=checkcurbul
  493.   end;
  494.  
  495. {=============================================================================}
  496.  
  497.   Procedure readbul;
  498.   begin
  499.     getbnum ('read');
  500.     readcurbul
  501.   end;
  502.  
  503. {=============================================================================}
  504.  
  505.   Procedure readnextbul;
  506.   VAR t:integer;
  507.   begin
  508.     t:=Cur_bul;
  509.     Cur_bul:=Cur_bul+1;
  510.     readcurbul;
  511.     if Cur_bul=0 then Cur_bul:=t
  512.   end;
  513.  
  514. {=============================================================================}
  515.  
  516.   Procedure readnum (n:integer);
  517.   begin
  518.     Cur_bul:=n;
  519.     readcurbul
  520.   end;
  521.  
  522. {=============================================================================}
  523.  
  524.   Function haveaccess (n:integer):boolean;
  525.   VAR a:accesstype;
  526.   begin
  527.     curboardnum:=n;
  528.     seekbdfile (n);
  529.     read (bdfile,curboard);
  530.     a:=queryaccess;
  531.     if a=bylevel
  532.       then haveaccess:=ulvl>=curboard.level
  533.       else haveaccess:=a=letin
  534.   end;
  535.  
  536. {=============================================================================}
  537.  
  538.   Procedure makeboard;
  539.   begin
  540.     formatbfile;
  541.     formatffile;
  542.     with curboard do begin
  543.       shortname:=curboardname;
  544.       buflen:=30;
  545.       writestr (^M'Board name: &');
  546.       boardname:=input;
  547.       buflen:=30;
  548.       writestr ('Sponsor (C/R for '+unam+'):');
  549.       if input='' then input:=unam;
  550.       sponsor:=input;
  551.       writestr ('Minimum level for entry:');
  552.       level:=valu(input);
  553.       writestr ('Autodelete after:');
  554.       autodel:=valu(input);
  555.       if autodel<10 then begin
  556.         writeln ('Must be at least 10!');
  557.         autodel:=10
  558.       end;
  559.       setallflags (curboardnum,bylevel);
  560.       writecurboard;
  561.       writeln ('Board created.');
  562.       writelog (4,4,boardname+' ['+shortname+']')
  563.     end
  564.   end;
  565.  
  566. {=============================================================================}
  567.  
  568.   Procedure setactive (nn:sstr);
  569.  
  570.     Procedure doswitch;
  571.     begin
  572.       openbfile;
  573.       Cur_bul:=0;
  574.       with curboard do
  575.         writeln (^M'[Sub-board ] : '^S,boardname,
  576.                  ^M'[Sponsor   ] : '^S,sponsor,
  577.                  ^M'[Bulletins ] : '^S,numbuls,
  578.                  ^M'[Last read ] : '^S,lastreadnum,
  579.                  ^M'[Files     ] : '^S,numfiles,^M)
  580.     end;
  581.  
  582.     Procedure tryswitch;
  583.     VAR n,s:integer;
  584.  
  585.       Procedure denyaccess;
  586.       VAR Post:bulrec;
  587.       begin
  588.         reqlevel (curboard.level);
  589.         setfirstboard
  590.       end;
  591.  
  592.     begin
  593.       curboardname:=nn;
  594.       curboardnum:=searchboard(nn);
  595.       if haveaccess(curboardnum)
  596.         then doswitch
  597.         else denyaccess
  598.     end;
  599.  
  600.   VAR Post:bulrec;
  601.   begin
  602.     Cur_bul:=0;
  603.     close (bfile);
  604.     close (ffile);
  605.     curboardname:=nn;
  606.     if boardexist(nn) then tryswitch else begin
  607.       writeln ('No such board: ',curboardname,'!');
  608.       if issysop
  609.         then
  610.           begin
  611.             writestr (^M'Create one (Y/N)? *');
  612.             if yes
  613.               then
  614.                 begin
  615.                   makeboard;
  616.                   setactive (curboardname)
  617.                 end
  618.               else setfirstboard
  619.           end
  620.         else setfirstboard
  621.     end
  622.   end;
  623.  
  624. {=============================================================================}
  625.  
  626.   Function validbname (n:sstr):boolean;
  627.   VAR cnt:integer;
  628.   begin
  629.     validbname:=false;
  630.     if (length(n)=0) or (length(n)>8) then exit;
  631.     for cnt:=1 to length(n) do
  632.       if not (upcase(n[cnt]) in ['0'..'9','A'..'Z']) then exit;
  633.     validbname:=true
  634.   end;
  635.  
  636. {=============================================================================}
  637.  
  638.   Procedure listboards;
  639.   VAR cnt,oldcurboard:integer;
  640.       printed:boolean;
  641.   begin
  642.     oldcurboard:=curboardnum;
  643.     writeln (^M'Number   Name                      Level'^M);
  644.     if break then exit;
  645.     for cnt:=0 to filesize(bdfile)-1 do
  646.       if haveaccess(cnt) then
  647.         with curboard do begin
  648.           tab (shortname,9);
  649.           tab (boardname,26);
  650.           writeln (level);
  651.           if break then exit
  652.         end;
  653.     curboardnum:=oldcurboard;
  654.     seekbdfile (curboardnum);
  655.     read (bdfile,curboard)
  656.   end;
  657.  
  658. {=============================================================================}
  659.  
  660.   Procedure activeboard;
  661.   begin
  662.     if length(input)>1
  663.       then input:=copy(input,2,255)
  664.       else
  665.         repeat
  666.           writestr (^M^M'Board number [?=List]:');
  667.           if input='?' then listboards
  668.         until (input<>'?') or hungupon;
  669.     if hungupon or (length(input)=0) then exit;
  670.     if input[1]='*' then input:=copy(input,2,255);
  671.     if validbname(input)
  672.       then setactive (input)
  673.       else
  674.         begin
  675.           writeln (^M'Invalid board name!');
  676.           setfirstboard
  677.         end
  678.   end;
  679.  
  680. {=============================================================================}
  681.  
  682.   Procedure setfirstboard;
  683.   Begin
  684.     if filesize(bdfile)=0 then exit;
  685.     if not haveaccess(0)
  686.       then error ('User can''t access first board','','');
  687.     seek (bdfile,0);
  688.     read (bdfile,curboard);
  689.     curboardname := curboard.shortname;
  690.     curboardnum := 0;
  691.     Cur_bul := 0;
  692.     openbfile
  693.   End;
  694.  
  695. {=============================================================================}
  696.  
  697.   Procedure listbuls;
  698.   VAR cnt,bn:integer;
  699.       q:boolean;
  700.   begin
  701.     if length(input)>1 then begin
  702.       Cur_bul:=valu(copy(input,2,255));
  703.       q:=checkcurbul
  704.     end;
  705.     if Cur_bul=0
  706.       then
  707.         begin
  708.           writestr (^M'List titles starting at #*');
  709.           Cur_bul:=valu(input)
  710.         end
  711.       else
  712.         if length(input)>1
  713.           then Cur_bul:=valu(input)
  714.           else Cur_bul:=Cur_bul+10;
  715.     if not checkcurbul then Cur_bul:=1;
  716.     writeln ('Titles:'^M);
  717.     for cnt:=0 to 9 do
  718.       begin
  719.         bn:=Cur_bul+cnt;
  720.         if (bn>0) and (bn<=numbuls) then
  721.           begin
  722.             seekbfile (bn);
  723.             read (bfile,Post);
  724.             write (bn,'. ',Post.title,' by ');
  725.             if Post.anon
  726.               then writeln (anonymousstr)
  727.               else writeln (Post.leftby);
  728.             if break then exit
  729.           end
  730.       end
  731.   end;
  732.  
  733. {=============================================================================}
  734.  
  735.   Procedure killbul;
  736.   VAR un:integer;
  737.       u:userrec;
  738.   begin
  739.     writehdr ('Bulletin Deletion');
  740.     getbnum ('delete');
  741.     if not checkcurbul then exit;
  742.     getbrec;
  743.     if (not match(Post.leftby,unam)) and (not issysop) and (not Sponsor_on)
  744.       then begin
  745.         writeln ('You didn''t post that!');
  746.         exit
  747.       end;
  748.     writeln ('Title:   ',Post.title,
  749.              ^M'Left by: ',Post.leftby,^M^M);
  750.     writestr ('Delete this? *');
  751.     if not yes then exit;
  752.     un:=lookupuser (Post.leftby);
  753.     if un<>0 then begin
  754.       writeurec;
  755.       seek (ufile,un);
  756.       read (ufile,u);
  757.       u.nbu:=u.nbu-1;
  758.       seek (ufile,un);
  759.       write (ufile,u);
  760.       readurec;
  761.       Delete_one_post(Post.Leftby,u.nbu);
  762.       Save_top_posters;
  763.     end;
  764.     delbul (Cur_bul,true);
  765.     writeln ('Bulletin deleted.');
  766.     writelog (4,5,Post.title)
  767.   end;
  768.  
  769. {=============================================================================}
  770.  
  771.   Procedure editbul;
  772.   VAR me:message;
  773.   begin
  774.     getbnum ('edit');
  775.     if not checkcurbul then exit;
  776.     getbrec;
  777.     if (not match(Post.leftby,unam)) and (not issysop) and (not Sponsor_on)
  778.       then begin
  779.         writeln ('You didn''t post that!');
  780.         exit
  781.       end;
  782.     reloadtext (Post.line,me);
  783.     me.title:=Post.title;
  784.     me.anon:=Post.anon;
  785.     if reedit (me,true) then begin
  786.       writelog (4,6,Post.title);
  787.       deletetext (Post.line);
  788.       Post.line:=maketext (me);
  789.       if Post.line<0 then begin
  790.         writestr (^M'Deleting bulletin...');
  791.         delbul (Cur_bul,false)
  792.       end else begin
  793.         seekbfile (Cur_bul);
  794.         write (bfile,Post)
  795.       end
  796.     end
  797.   end;
  798.  
  799. {=============================================================================}
  800.  
  801.   Procedure sendbreply;
  802.   begin
  803.     if checkcurbul then begin
  804.       getbrec;
  805.       sendmailto (LookUpUser(Post.leftby),Post.anon)
  806.     end else begin
  807.       getbnum ('reply to');
  808.       if checkcurbul then sendbreply
  809.     end
  810.   end;
  811.  
  812. {=============================================================================}
  813.  
  814.   Procedure listfiles;
  815.   VAR cnt,r1,r2,nfiles:integer;
  816.       f:filerec;
  817.   begin
  818.     nfiles:=numfiles;
  819.     thereare (nfiles,'file','files');
  820.     if nfiles=0 then exit;
  821.     parserange (nfiles,r1,r2);
  822.     if r1=0 then exit;
  823.     for cnt:=r1 to r2 do begin
  824.       seekffile (cnt);
  825.       read (ffile,f); che;
  826.       writeln (cnt,'. ',f.descrip);
  827.       if break then exit
  828.     end
  829.   end;
  830.  
  831. {=============================================================================}
  832.  
  833.   Function getfilenumber (txt:lstr):integer;
  834.   VAR fn:integer;
  835.       gotten:boolean;
  836.   begin
  837.     getfilenumber:=0;
  838.     input:=copy(input,2,255);
  839.     if length(input)=0 then
  840.       repeat
  841.         gotten:=true;
  842.         writestr (^M'File number to '+txt+' [?=List]:');
  843.         if input='?' then
  844.           begin
  845.             writeln;
  846.             listfiles;
  847.             writeln;
  848.             gotten:=false
  849.           end
  850.       until gotten;
  851.     fn:=valu(input);
  852.     if (fn<1) or (fn>numfiles) then fn:=0;
  853.     getfilenumber:=fn
  854.   end;
  855.  
  856. {=============================================================================}
  857.  
  858.   Procedure downloadfile;
  859.   VAR fn:integer;
  860.   begin
  861.     fn:=getfilenumber ('download');
  862.     if fn<>0 then
  863.       begin
  864.         sendfile (fn);
  865.         urec.ndn:=urec.ndn+1
  866.       end;
  867.   end;
  868.  
  869. {=============================================================================}
  870.  
  871.   Procedure uploadfile;
  872.   VAR f:filerec;
  873.   begin
  874.     writestr ('Describe the file'+^M+'=> *');
  875.     if length(input)<>0 then begin
  876.       f.descrip:=input;
  877.       receivefile (f);
  878.       urec.nup:=urec.nup+1
  879.     end
  880.   end;
  881.  
  882. {=============================================================================}
  883.  
  884. {$I BSponsr.pas}
  885.  
  886. {=============================================================================}
  887.  
  888.   VAR beenaborted:boolean;
  889.  
  890.   Function aborted:boolean;
  891.   begin
  892.     if beenaborted then begin
  893.       aborted:=true;
  894.       exit
  895.     end;
  896.     aborted:=xpressed or hungupon;
  897.     if xpressed then begin
  898.       beenaborted:=true;
  899.       writeln (^B'Newscan aborted!')
  900.     end
  901.   end;
  902.  
  903. {=============================================================================}
  904.  
  905. Function Num_new_Bulletins(B_name : SStr) : INTEGER;
  906. VAR Current : WORD;
  907.     Tally   : WORD;
  908. Begin
  909.   CurBoardName := B_name;
  910.   OpenBFile;
  911.   Cur_bul := LastReadNum+1;
  912.   Tally := 0;
  913.   While (Cur_bul <= numbuls) DO
  914.    Begin
  915.      GetBrec;
  916.      IF Post.when > laston THEN
  917.        Begin
  918.          Inc(Tally);
  919.        End;
  920.       Inc(Cur_bul);
  921.     End;
  922.   Num_new_bulletins := Tally;
  923. End;
  924.  
  925. {=============================================================================}
  926.  
  927. VAR newmsgs : boolean;
  928.     NewFIles : BOOLEAN;
  929.  
  930.   Procedure newscanboard;
  931.   VAR Advance_board : BOOLEAN;
  932.  
  933.     Procedure shownewfiles;
  934.     VAR cnt,first,numf:integer;
  935.         f:filerec;
  936.         nf:boolean;
  937.     begin
  938.       NewFiles := FALSE;
  939.       numf:=numfiles;
  940.       cnt:=numf;
  941.       nf:=true;
  942.       while (cnt>0) and nf do begin
  943.         seekffile (cnt);
  944.         read (ffile,f);
  945.         nf:=f.when>laston;
  946.         if nf then cnt:=cnt-1
  947.       end;
  948.       first:=cnt+1;
  949.       if first>numf then exit;
  950.       writehdr ('New files');
  951.       NewFiles := TRUE;
  952.       if aborted or break then exit;
  953.       for cnt:=first to numf do begin
  954.         seekffile (cnt);
  955.         read (ffile,f);
  956.         writeln (cnt,'. ',f.descrip);
  957.         if aborted or break then exit
  958.       end
  959.     end;
  960.  
  961. {-----------------------------------------------------------------------------}
  962.  
  963. Procedure Execute_options;
  964. VAR Command_char : CHAR;
  965.     q : INTEGER;
  966. Begin
  967.    q := Menu('['+strr(Cur_Bul)+'/'+Strr(NumBuls)+']-Newscan',
  968.              'BNEWS','REFQNP_#');
  969.    Case q OF
  970.     1 : Begin
  971.             Writeln;
  972.             WriteStr('Posting a reply to #'+Strr(Cur_bul));
  973.             Writeln(Post.Title,' by ',Post.LeftBy);
  974.             If Copy(Post.Title,1,3) <> 'RE:' THEN
  975.                PostBul('RE: '+Post.Title)
  976.             ELSE
  977.                Postbul(Post.Title);
  978.           End;
  979.     6 : PostBul('');
  980.     2 : Sendmailto(LookUpUser(Post.leftby),Post.anon);
  981.     3 : Sendmailto(LookUpUser(Curboard.sponsor),FALSE);
  982.     4 : Begin
  983.            BeenAborted := TRUE;
  984.            Writeln;
  985.            Writeln('Newscan aborted');
  986.           End;
  987.     5 : Advance_board := TRUE;
  988.    ELSE
  989.      Begin
  990.        If (-q <= Numbuls) AND (-q > 0) THEN Cur_bul := (-q)-1;
  991.        Newscan_sub := FALSE;
  992.      End;
  993.   End;
  994. End;
  995.  
  996. {-----------------------------------------------------------------------------}
  997.  
  998.   VAR oldb    : boolean;
  999.   begin
  1000.     Advance_board := FALSE;
  1001.     beenaborted := FALSE;
  1002.     Newmsgs := FALSE;
  1003.     NewFiles := FALSE;
  1004.     Cur_bul := lastreadnum+1;
  1005.     Last_msg := numbuls;
  1006.     while Cur_bul <= numbuls do begin
  1007.       getbrec;
  1008.       IF (Post.when > laston) OR (NOT Newscan_sub) THEN
  1009.        Begin
  1010.         If (Scan_Mode = Extended) AND
  1011.            (ExtClrScr in Urec.Config) THEN Writeln(^L);
  1012.         Writeln;
  1013.         Writeln;
  1014.         readnum(Cur_bul);
  1015.         If Scan_mode = Extended THEN
  1016.           Begin
  1017.             Execute_options;
  1018.           End;
  1019.         newmsgs := true
  1020.        End;
  1021.       Cur_bul:=Cur_bul+1;
  1022.       IF (aborted) OR (Advance_board) THEN Exit
  1023.     end;
  1024.     shownewfiles;
  1025.     if (postprompts in urec.config) and
  1026.         (newmsgs) and (ulvl>=postlevel) AND
  1027.         (Scan_mode = Express ) THEN
  1028.          Begin
  1029.            writestr (^M'Post now? *');
  1030.            writeln;
  1031.            if yes then postbul('');
  1032.          End
  1033.   End;
  1034.  
  1035. {=============================================================================}
  1036.  
  1037.   Procedure newscanall;
  1038.   VAR cb       : integer;
  1039.       Scan_str : Mstr;
  1040.       c1       : BYTE;
  1041.       New_pst  : BYTE;
  1042.   Begin
  1043.     Writeln;
  1044.     Writeln('-%-  Newscan all subboards -%-'^M);
  1045.     WriteStr('Newscan mode: [E]xpress, or e[X]tended? *');
  1046.     If NOT (UpCase(Input[1]) IN ['E','X']) THEN Exit;
  1047.     Case UpCase(Input[1]) OF
  1048.       'E' : Scan_mode := Express;
  1049.       'X' : Scan_mode := Extended;
  1050.     End;
  1051.     BeenAborted:=false;
  1052.     Writehdr('New-scanning. [X] to abort.');
  1053.     IF aborted THEN exit;
  1054.     Case Scan_mode OF
  1055.       Express  : Scan_str := 'Express';
  1056.       Extended : Scan_str := 'Extended';
  1057.     End;
  1058.  
  1059.     For cb := 0 to FileSize(Bdfile)-1 DO
  1060.       Begin
  1061.         if aborted then exit;
  1062.         if haveaccess(cb) and (not (cb in urec.newscanconfig)) THEN
  1063.          Begin
  1064.           Curboardname:=curboard.shortname;
  1065.           Openbfile;
  1066.           IF aborted then EXIT;
  1067.           Writeln(^B,Scan_str+' scanning: [',curboard.boardname,']');
  1068.           if aborted then exit;
  1069.  
  1070.           NewMsgs := FALSE;
  1071.           NewFiles := FALSE;
  1072.           Newscan_sub := TRUE;
  1073.  
  1074.           newscanboard;
  1075.  
  1076.         End
  1077.       ELSE
  1078.         If haveaccess(cb) THEN
  1079.             Writeln(^B,'Skipping ',curboard.boardname,'.');
  1080.     End;
  1081.  
  1082.     Writeln(^B^M'Newscan complete!'^G);
  1083.     Setfirstboard
  1084.   End;
  1085.  
  1086. {=============================================================================}
  1087.  
  1088.   Procedure noboards;
  1089.   begin
  1090.     writeln ('No sub-boards exist!');
  1091.     if not issysop then exit;
  1092.     writestr ('Create the first sub-board now? *');
  1093.     if not yes then exit;
  1094.     writestr ('Enter its access name/number:');
  1095.     if not validbname(input) then writeln (^B'Invalid board name!') else begin
  1096.       curboardname:=input;
  1097.       makeboard
  1098.     end
  1099.   end;
  1100.  
  1101. {=============================================================================}
  1102.  
  1103.   Procedure togglenewscan;
  1104.   begin
  1105.     write ('Newscan this board: ');
  1106.     if curboardnum in urec.newscanconfig
  1107.       then
  1108.         begin
  1109.           writeln ('Yes');
  1110.           urec.newscanconfig:=urec.newscanconfig-[curboardnum]
  1111.         end
  1112.       else
  1113.         begin
  1114.           writeln ('No');
  1115.           urec.newscanconfig:=urec.newscanconfig+[curboardnum]
  1116.         end
  1117.   end;
  1118.  
  1119. {=============================================================================}
  1120.  
  1121.   Procedure nextsubboard;
  1122.   VAR cb:integer;
  1123.       obn:sstr;
  1124.   begin
  1125.     obn:=curboardname;
  1126.     cb:=curboardnum;
  1127.     while cb<filesize(bdfile)-1 do begin
  1128.       cb:=cb+1;
  1129.       if haveaccess (cb) then begin
  1130.         seek (bifile,cb);
  1131.         read (bifile,obn);
  1132.         setactive (obn);
  1133.         exit
  1134.       end
  1135.     end;
  1136.     writestr ('This is the last sub-board!');
  1137.     setactive (obn)
  1138.   end;
  1139.  
  1140. {=============================================================================}
  1141.  
  1142. VAR boo:boolean;
  1143. label exit;
  1144. begin
  1145.   cursection:=bulletinsysop;
  1146.   openbdfile;
  1147.   if filesize(bdfile)=0 then begin
  1148.     noboards;
  1149.     if filesize(bdfile)=0 then begin
  1150.       closebdfile;
  1151.       goto exit
  1152.     end
  1153.   end;
  1154.   if not haveaccess(0)
  1155.     then
  1156.       begin
  1157.         writeln (^B'You do not have access to the first sub-board!');
  1158.         closebdfile;
  1159.         goto exit
  1160.       end;
  1161.   Show_top_posters;
  1162.   setfirstboard;
  1163.   repeat
  1164.     boo := checkcurbul;
  1165.     with curboard do
  1166.       writeln (^M,boardname,' [',shortname,']: ',Cur_bul,' of ',numbuls);
  1167.     if Sponsor_on OR issysop THEN
  1168.       Writeln('%: Board sponsor commands');
  1169.     q := menu ('Bulletin','BULLET','PRDFUKT*MQ#_%LNBAVCHES+WO');
  1170.     case q of
  1171.       1  : postbul('');
  1172.       2  : readbul;
  1173.       3  : downloadfile;
  1174.       4,
  1175.       22 : sendmailto (LookUpUser(curboard.sponsor),false);
  1176.       5  : uploadfile;
  1177.       6  : killbul;
  1178.       8,
  1179.       16,
  1180.       17 : activeboard;
  1181.       7  : listbuls;
  1182.       9  : sendbreply;
  1183.       12 : if not hungupon then readnextbul;
  1184.       13 : boardsponsor;
  1185.       14 : listfiles;
  1186.       15 : newscanall;
  1187.       18 : Begin
  1188.              Scan_mode := Express;
  1189.              newscanboard;
  1190.            End;
  1191.       19 : togglenewscan;
  1192.       20 : help ('Bulletin.hlp');
  1193.       21 : editbul;
  1194.       23 : nextsubboard;
  1195.       24 : readnum (lastreadnum+1);
  1196.       25 : Show_top_posters;
  1197.       else if q<0 then readnum (-q)
  1198.     end
  1199.   until (q=10) or hungupon or (filesize(bdfile)=0);
  1200.   exit:
  1201.   close (bfile);
  1202.   close (ffile);
  1203.   closebdfile
  1204. End;
  1205.  
  1206. {=============================================================================}
  1207.  
  1208. {/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\}
  1209.  
  1210. {initialization}
  1211.  
  1212. {/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\}
  1213.  
  1214. Begin
  1215.   FillChar(Post_array,SizeOf(Top_poster_Type),0);
  1216. End.
  1217.