home *** CD-ROM | disk | FTP | other *** search
/ Jason Aller Floppy Collection / 189.img / TCS120S.ZIP / MAINMENU.PAS < prev    next >
Pascal/Delphi Source File  |  1989-04-01  |  42KB  |  1,704 lines

  1. {$R-,S-,I-,D-,F+,V-,B-,N-,L+ }
  2. {$M 65500,0,0 }
  3.  
  4. unit mainmenu;
  5.  
  6. interface
  7.  
  8. uses crt,dos,
  9.      gentypes,configrt,statret,textret,userret,mailret,
  10.      gensubs,subs1,subs2,windows,chatstuf,mainr1,mainr2,overret1;
  11.  
  12. var userqr,userlistqr:integer;
  13.     u,uu:userrec;
  14.     totalused,totalidle,totalup,totaldown,totalmins,callsday,
  15.     totaldisk,totalfree,filesizes,x,y,z:real;
  16.     a,b,c:integer;
  17.     totalfiles:integer;
  18.     dofiles:boolean;
  19.  
  20. procedure calcuserqr;
  21. procedure calcuserlistqr;
  22. procedure editusers;
  23. procedure zapspecifiedusers;
  24. procedure summonsysop;
  25. procedure offtcs;
  26. procedure listusers;
  27. procedure transfername;
  28. procedure editnews;
  29. procedure yourstatus;
  30. procedure delerrlog;
  31. procedure feedback;
  32. procedure settime;
  33. procedure changepwd;
  34. procedure requestraise;
  35. procedure makeuser;
  36. procedure infoformhunt;
  37. procedure donations;
  38. procedure viewsyslog;
  39. procedure viewsyslog2;
  40. procedure delsyslog;
  41. procedure showsystemstatus;
  42. procedure showallforms;
  43. procedure showallsysops;
  44. procedure mainhelp;
  45. procedure bbslist;
  46. procedure readerrlog;
  47. procedure showad;
  48. procedure setlastcall;
  49. procedure removeallforms;
  50. procedure readfeedback;
  51.  
  52. implementation
  53.  
  54. procedure calcuserqr;
  55. begin
  56.  with u do begin
  57.   userqr := qrmultifactor*(u.uploads+u.nbu)-u.downloads;
  58.  end;
  59. end;
  60.  
  61. procedure calcuserlistqr;
  62. begin
  63.  with uu do begin
  64.   userlistqr := qrmultifactor*(uu.uploads+uu.nbu)-uu.downloads;
  65.  end;
  66. end;
  67.  
  68. procedure editusers;
  69. var eunum:integer;
  70.     matched:boolean;
  71.  
  72.   procedure elistusers (getspecs:boolean);
  73.   var cnt,f,l:integer;
  74.       us:userspecsrec;
  75.  
  76.     procedure listuser;
  77.     begin
  78.       write (cnt:4,' ');
  79.       tab (u.handle,31);
  80.       write (u.level:6,' ');
  81.       if useqr then begin
  82.        calcuserqr;
  83.        tab (strr(userqr),8);
  84.       end;
  85.       writeln (u.nbu:6,u.numon:6,postcallratio(u):7:2)
  86.     end;
  87.  
  88.   begin
  89.     if getspecs
  90.       then if selectspecs(us)
  91.         then exit
  92.         else
  93.           begin
  94.             f:=1;
  95.             l:=numusers
  96.           end
  97.       else parserange (numusers,f,l);
  98.     seek (ufile,f);
  99.     matched:=false;
  100.     write (^B^M^M' ID# Name                            Level ');
  101.     if useqr then write ('QR         ');
  102.     writeln ('Posts Calls PCR');
  103.     for cnt:=f to l do begin
  104.       read (ufile,u);
  105.       if (not getspecs) or fitsspecs(u,us) then begin
  106.         listuser;
  107.         matched:=true
  108.       end;
  109.       handleincoming;
  110.       if break then exit
  111.     end;
  112.     if not matched then
  113.       if getspecs
  114.         then writeln (^B^M'No users match specifications!')
  115.         else writeln (^B^M'No users found in that range!')
  116.   end;
  117.  
  118. begin
  119.   repeat
  120.     writestr (^M'User to Edit [?,??=List]:');
  121.     if (length(input)=0) or (match(input,'Q')) then exit;
  122.     if input[1]='?'
  123.       then elistusers (input='??')
  124.       else begin
  125.         eunum:=lookupuser (input);
  126.         if eunum=0
  127.           then writestr ('User not found!')
  128.           else edituser (eunum)
  129.       end
  130.   until hungupon
  131. end;
  132.  
  133. procedure zapspecifiedusers;
  134. var us:userspecsrec;
  135.     confirm:boolean;
  136.     u:userrec;
  137.     cnt:integer;
  138.     done:boolean;
  139. begin
  140.   if selectspecs (us) then exit;
  141.   writestr ('Confirm each deletion individually? *');
  142.   if length(input)=0 then exit;
  143.   confirm:=yes;
  144.   if not confirm then begin
  145.     writestr (^M'Are you SURE you want to mass delete without confirmation? *');
  146.     if not yes then exit
  147.   end;
  148.   for cnt:=1 to numusers do begin
  149.     seek (ufile,cnt);
  150.     read (ufile,u);
  151.     if (length(u.handle)>0) and fitsspecs (u,us) then begin
  152.       if confirm
  153.         then
  154.           begin
  155.             done:=false;
  156.             repeat
  157.               writestr ('Delete '+u.handle+' (Y/N/X/E):');
  158.               if length(input)>0 then case upcase(input[1]) of
  159.                 'Y':begin
  160.                       done:=true;
  161.                       writeln ('Deleting '+u.handle+'...');
  162.                       deleteuser (cnt)
  163.                     end;
  164.                 'N':done:=true;
  165.                 'X':exit;
  166.                 'E':begin
  167.                       edituser(cnt);
  168.                       writeln;
  169.                       writeln
  170.                     end
  171.               end
  172.             until done
  173.           end
  174.         else
  175.           begin
  176.             writeln ('Deleting '+u.handle+'...');
  177.             if break then begin
  178.               writestr ('Aborted!!');
  179.               exit
  180.             end;
  181.             deleteuser (cnt)
  182.           end
  183.     end
  184.   end
  185. end;
  186.  
  187. procedure summonsysop;
  188. var tf:text;
  189.     k:char;
  190. begin
  191.   chatmode:=not chatmode;
  192.   bottomline;
  193.   if chatmode
  194.     then
  195.       if sysopisavail
  196.         then
  197.           begin
  198.             writestr ('Enter a reason to chat: &');
  199.             chatreason:=input;
  200.             if length(input)=0 then begin
  201.               chatmode:=false;
  202.               exit
  203.             end;
  204.             writelog (1,3,chatreason);
  205.             splitscreen (4);
  206.             top;
  207.             clrscr;
  208.             writeln (usr,unam,' wants to chat!  His reason:');
  209.             write (usr,chatreason);
  210.             bottom;
  211.             assign (tf,textfiledir+'Summon');
  212.             reset (tf);
  213.             if ioresult=0 then begin
  214.               while (not (eof(tf) or hungupon)) and chatmode do
  215.                 begin
  216.                   read (tf,k);
  217.                   nobreak:=true;
  218.                   if ord(k)=7 then summonbeep else writechar (k);
  219.                   if keyhit then begin
  220.                     k:=bioskey;
  221.                     clearbreak;
  222.                     chat (false)
  223.                   end
  224.                 end;
  225.               textclose (tf)
  226.             end;
  227.             if chatmode
  228.               then writestr (^M'Use [C] again to turn off page.')
  229.               else unsplit
  230.           end
  231.         else
  232.           begin
  233.             if length(notavailstr)=0 then
  234.             writestr ('Sorry, '+sysopname+
  235.                       ' isn''t available right now!') else
  236.             writeln (notavailstr);
  237.             chatmode:=false;
  238.             writelog (1,2,'')
  239.           end
  240.     else writestr ('Page off.  Use [C] to turn it back on.');
  241.   clearbreak
  242. end;
  243.  
  244. procedure offtcs;
  245. var q,n:integer;
  246.     tn:file of integer;
  247.     m:message;
  248. begin
  249.   writestr ('Logoff now? *');
  250.   if yes then begin
  251.     if ulvl<msgnextlvl then begin
  252.       printfile (textfiledir+'GoodBye');
  253.      disconnect;
  254.      end;
  255.     writestr ('Change Auto-Message? *');
  256.     if yes then begin
  257.       titlestr:='Auto-Message';
  258.       sendstr:='Next User';
  259.       q:=editor(m,false,'Auto-Message');
  260.       sendstr:='';
  261.       if q>=0 then begin
  262.         if tonext>=0 then deletetext (tonext);
  263.         tonext:=q;
  264.         writestatus
  265.       end
  266.     end;
  267.     printfile (textfiledir+'Goodbye');
  268.     disconnect
  269.   end
  270. end;
  271.  
  272. procedure listusers;
  273. var cnt,u1,u2:integer;
  274. begin
  275.   if ulvl<listuserlvl then reqlevel (listuserlvl);
  276.   writehdr ('List Users');
  277.   parserange (numusers,u1,u2);
  278.   if u1=0 then exit;
  279.   write (^B'['^S'Name'^R']                           ['^S'Level'^R'] ['^S'Note'^R']');
  280.   if useqr then writeln (^R'                          ['^S'QR'^R']  ')
  281.   else writeln;
  282.   if break then exit;
  283.   if (asciigraphics in urec.config) then
  284.    write (^B'───────────────────────────────────────────────') else
  285.    write (^B'-----------------------------------------------');
  286.   if (useqr) then begin
  287.    if (asciigraphics in urec.config) then
  288.     write (^B'────────────────────────────────') else
  289.     write (^B'--------------------------------');
  290.   end;
  291.   writeln;
  292.   if break then exit;
  293.   for cnt:=u1 to u2 do
  294.     begin
  295.       seek (ufile,cnt);
  296.       read (ufile,uu);
  297.       che;
  298.       if length(uu.handle)>0 then begin
  299.         periods:=true;
  300.         write (^R'['^S);
  301.         tab (uu.handle,30);
  302.         if break then exit;
  303.         write (^R']-['^S);
  304.         periods:=true;
  305.         tab (strr(uu.level),5);
  306.         if break then exit;
  307.         write (^R']-['^S);
  308.         periods:=true;
  309.         tab (uu.note,29);
  310.         write (^R']');
  311.         if break then exit;
  312.         if useqr then begin
  313.          calcuserlistqr;
  314.          write ('-['^S);
  315.          tab (strr(userlistqr),4);
  316.          write (^R']');
  317.          if break then exit;
  318.         end;
  319.        writeln;
  320.       end
  321.     end
  322. end;
  323.  
  324. procedure transfername;
  325. var un,nlvl,ntime,tmp:integer;
  326.     u:userrec;
  327.     qaz:lstr;
  328. begin
  329.   if tempsysop then begin
  330.     writestr ('Disabling temporary sysop powers...');
  331.     ulvl:=regularlevel;
  332.     tempsysop:=false
  333.   end;
  334.   writestr ('Transfer to user name:');
  335.   if length(input)=0 then exit;
  336.   un:=lookupuser(input);
  337.   if unum=un then begin
  338.     writestr ('Dumbass!! You can''t transfer to yourself!');
  339.      end;
  340.   if un=0 then begin
  341.     writestr ('No such user.');
  342.     exit
  343.   end;
  344.   seek (ufile,un);
  345.   read (ufile,u);
  346.   if ulvl<sysoplevel then if not checkpassword(u) then begin
  347.     writelog (1,5,u.handle);
  348.     exit
  349.   end;
  350.   writelog (1,4,u.handle);
  351.   updateuserstats (false);
  352.   ntime:=0;
  353.   if datepart(u.laston)<>datepart(now) then begin
  354.     tmp:=ulvl;
  355.     if tmp<1 then tmp:=1;
  356.     if tmp>100 then tmp:=100;
  357.     ntime:=usertime[tmp]
  358.   end;
  359.   if u.timetoday<10
  360.     then if issysop or (u.level>=sysoplevel)
  361.       then
  362.         begin
  363.           writestr ('The user has '+strr(u.timetoday)+' min(s) left!');
  364.           writestr ('New time left:');
  365.           ntime:=valu(input)
  366.         end
  367.       else
  368.         if u.timetoday>0
  369.           then writeln ('Warning: You have ',u.timetoday,' minutes left!')
  370.           else
  371.             begin
  372.               writestr ('Sorry, that user doesn''t have any time left!');
  373.               exit
  374.             end;
  375.   unum:=un;
  376.   readurec;
  377.   if ntime<>0 then begin
  378.     urec.timetoday:=ntime;
  379.     writeurec
  380.   end;
  381. end;
  382.  
  383. procedure editnews;
  384. var nn,numnews:integer;
  385.     nf:file of integer;
  386.  
  387.   procedure getnn (txt:mstr);
  388.   begin
  389.     writestr ('News number to '+txt+':');
  390.     nn:=valu(input);
  391.     if (nn<1) or (nn>numnews) then nn:=0
  392.   end;
  393.  
  394.   procedure delnews;
  395.   var cnt:integer;
  396.       r:integer;
  397.   begin
  398.     if nn=0 then getnn ('delete');
  399.     if nn<>0 then begin
  400.       seek (nf,nn-1);
  401.       read (nf,r); che;
  402.       deletetext (r);
  403.       numnews:=filesize(nf)-1;
  404.       for cnt:=nn to numnews do
  405.         begin
  406.           seek (nf,cnt);
  407.           read (nf,r);
  408.           seek (nf,cnt-1);
  409.           write (nf,r)
  410.         end;
  411.       seek (nf,numnews);
  412.       truncate (nf)
  413.     end
  414.   end;
  415.  
  416.   procedure listnews;
  417.   var cnt:integer;
  418.       r,sector:integer;
  419.       q:buffer;
  420.       l:anystr;
  421.       k:char;
  422.   begin
  423.     clearbreak;
  424.     for cnt:=1 to numnews do begin
  425.       seek (nf,cnt-1);
  426.       read (nf,r);
  427.       seek (tfile,r);
  428.       read (tfile,q);
  429.       write (strr(cnt)+'. ');
  430.       r:=1;
  431.       k:=' ';
  432.       l:='';
  433.       while (ord(k)<>13) and not hungupon do begin
  434.         k:=q[r];
  435.         r:=r+1;
  436.         if (k=#0) or (r>sectorsize) then k:=chr(13);
  437.         l:=l+k
  438.       end;
  439.       writeln (l);
  440.       if break then exit
  441.     end;
  442.     writeln
  443.   end;
  444.  
  445.   procedure viewnews;
  446.   var r:integer;
  447.   begin
  448.     if nn=0 then getnn ('view');
  449.     if nn<>0 then begin
  450.       seek (nf,nn-1);
  451.       read (nf,r); che;
  452.       printtext (r)
  453.     end
  454.   end;
  455.  
  456.   procedure adddnews;
  457.   begin
  458.     close (nf);
  459.     addnews;
  460.     assign (nf,'News');
  461.     reset (nf)
  462.   end;
  463.  
  464. var q:integer;
  465. begin
  466.   assign (nf,'News');
  467.   reset (nf);
  468.   if ioresult<>0 then writestr ('No news!  Use [A] to add some!') else begin
  469.     repeat
  470.       numnews:=filesize(nf);
  471.       write (^B^M'News entries: ',numnews);
  472.       q:=menu ('News Edit','NEWS','ADLVQ');
  473.       nn:=valu(copy(input,2,255));
  474.       if (nn<1) or (nn>numnews) then nn:=0;
  475.       case q of
  476.         1:adddnews;
  477.         2:delnews;
  478.         3:listnews;
  479.         4:viewnews
  480.       end;
  481.       if numnews=0 then begin
  482.         close (nf);
  483.         erase (nf);
  484.         writestr ('No more news!  Use [A] to add some.');
  485.         q:=5
  486.       end
  487.     until (q=5) or hungupon
  488.   end;
  489.   close (nf)
  490. end;
  491.  
  492. procedure yourstatus;
  493. begin
  494.   if ansi then write (#27+'[2J') else write (^L);
  495.   if (asciigraphics in urec.config) then
  496.   writeln (^P'────────────────────') else
  497.   writeln (^P'--------------------');
  498.   writeln (^P'[ Your User Status ]');
  499.   if (asciigraphics in urec.config) then
  500.   writeln (^P'────────────────────') else
  501.   writeln (^P'--------------------');
  502.   writeln (^R'Name:   '^S,unam,^R' [Level '^S,ulvl,^R']');
  503.   writeln (^R'Calls:  '^S,urec.numon);
  504.   writeln (^R'Note:   '^S,urec.note);
  505.   writeln (^P'Message Section');
  506.   writeln (^R' Posts:        '^S,urec.nbu);
  507.   writeln (^R' Text Ups:     '^S,urec.nup);
  508.   writeln (^R' Text Downs:   '^S,urec.ndn);
  509.   writeln (^P'File Transfer');
  510.   writeln (^R' File Level:   '^S,urec.udlevel);
  511.   writeln (^R' File Points:  '^S,urec.udpoints);
  512.   write   (^R' Uploaded:     '^S,urec.uploads,^R' time');
  513.   if urec.uploads<>1 then write ('s');
  514.   writeln (^R', '^S,streal(urec.upk),^R' bytes');
  515.   write   (^R' Downloaded:   '^S,urec.downloads,^R' time');
  516.   if urec.downloads<>1 then write ('s');
  517.   writeln (^R', '^S,streal(urec.downk),^R' bytes');
  518.   writeln (^P'G-Files');
  519.   writeln (^R' G-File Level: '^S,urec.gflevel);
  520.   writeln (^R' Uploads:      '^S,urec.gfuploads);
  521.   writeln (^R' Downloads:    '^S,urec.gfdownloads);
  522.   writeln (^R'Total time on: '^S,urec.totaltime:0:0);
  523.   writeln (^R'Time left:     '^S,timeleft);
  524.   if (useqr) then begin
  525.    calcqr;
  526.    writeln('Quality Rating:'^S,qr);
  527.   end
  528. end;
  529.  
  530. procedure delerrlog;
  531. var e:text;
  532.     i:integer;
  533. begin
  534.   writestr ('Delete Error Log [y/n]:');
  535.   if not yes then exit;
  536.   assign (e,'errlog');
  537.   reset (e);
  538.   i:=ioresult;
  539.   if ioresult=1
  540.     then writeln (^M'No error log!')
  541.     else begin
  542.       textclose (e);
  543.       erase (e);
  544.       writestr ('Error log deleted.');
  545.       if ioresult>1
  546.         then writeln ('I/O error ',i,' deleting error log!');
  547.       writelog (2,2,'')
  548.     end
  549. end;
  550.  
  551. procedure feedback;
  552. var m:mailrec;
  553.     me:message;
  554. begin
  555.   writestr ('Leave Feedback to '+sysopname+' [y/n]? *');
  556.   if not yes then exit;
  557.   m.line:=editor(me,true,'Feedback');
  558.   if m.line<0 then exit;
  559.   m.title:=me.title;
  560.   m.sentby:=unam;
  561.   m.anon:=false;
  562.   m.when:=now;
  563.   addfeedback (m);
  564.   writestr ('Feedback sent.')
  565. end;
  566.  
  567. procedure settime;
  568. var t:integer;
  569.     n:longint;
  570.     r:registers;
  571.     d:datetime;
  572. begin
  573.   writestr ('Current Time: '+timestr(now));
  574.   writestr ('Current Date: '+datestr(now));
  575.   writestr ('Enter new time:');
  576.   if length(input)<>0
  577.     then begin
  578.       t:=timeleft;
  579.       unpacktime (timeval(input),d);
  580.       r.ch:=d.hour;
  581.       r.cl:=d.min;
  582.       r.dh:=0;
  583.       r.dl:=0;
  584.       r.ah:=$2d;
  585.       intr ($21,r);
  586.       if r.al=$ff then writestr ('Invalid time!');
  587.       settimeleft (t)
  588.     end;
  589.   writestr ('Enter new date:');
  590.   if length(input)<>0
  591.     then begin
  592.       unpacktime (dateval(input),d);
  593.       r.dl:=d.day;
  594.       r.dh:=d.month;
  595.       r.cx:=d.year;
  596.       r.ah:=$2b;
  597.       intr ($21,r);
  598.       if r.al=$ff then writestr ('Invalid date!')
  599.     end;
  600.   writelog (2,4,'')
  601. end;
  602.  
  603. procedure changepwd;
  604. var t:sstr;
  605. begin
  606.   writehdr ('Password Change');
  607.   dots:=true;
  608.   buflen:=15;
  609.   writeln ('Enter new Password, or ');
  610.   writeln ('Press [Return] to have one generated.');
  611.   write ('-> ');
  612.   if getpassword
  613.     then begin
  614.       writeurec;
  615.       writestr ('Password changed.');
  616.       writelog (1,1,'')
  617.     end else
  618.       writestr ('Not changed.')
  619. end;
  620.  
  621. procedure requestraise;
  622. var t:text;
  623.     q:lstr;
  624.     p,l1,l2:integer;
  625.     s1,s2:sstr;
  626.     me:message;
  627.     m:mailrec;
  628. label nope,found;
  629. begin
  630.   assign (t,textfiledir+'Raisereq');
  631.   reset (t);
  632.   if ioresult<>0 then goto nope;
  633.   printtexttopoint (t);
  634.   while not eof(t) do begin
  635.     readln (t,q);
  636.     p:=pos('-',q);
  637.     if p>0
  638.       then
  639.         begin
  640.           s1:=copy(q,1,p-1);
  641.           s2:=copy(q,p+1,255)
  642.         end
  643.       else
  644.         begin
  645.           s1:=copy(q,1,15);
  646.           s2:=s1
  647.         end;
  648.     val (s1,l1,p);
  649.     if p=0 then val (s2,l2,p);
  650.     if p<>0 then begin
  651.       textclose (t);
  652.       error ('Invalid range in RAISEREQ: %1','',q);
  653.       exit
  654.     end;
  655.     if (ulvl>=l1) and (ulvl<=l2) then goto found;
  656.     skiptopoint (t)
  657.   end;
  658.   nope:
  659.   error ('No text for level %1','',strr(ulvl));
  660.   textclose (t);
  661.   p:=ioresult;
  662.   exit;
  663.   found:
  664.   printtexttopoint (t);
  665.   textclose (t);
  666.   if hungupon then exit;
  667.   titlestr:='Raise Request';
  668.   sendstr:='Sysop';
  669.   writestr ('Press [Return] to enter the a message concerning your request:');
  670.   m.line:=editor (me,false,'Raise Request');
  671.   sendstr:='';
  672.   if m.line<0 then exit;
  673.   m.anon:=false;
  674.   m.title:='Raise Request (Now Level '+strr(ulvl)+')';
  675.   m.sentby:=unam;
  676.   m.when:=now;
  677.   addfeedback (m);
  678. end;
  679.  
  680. procedure makeuser;
  681. var u:userrec;
  682.     un,ln:integer;
  683. begin
  684.   writehdr ('Add a User');
  685.   writestr ('Name:');
  686.   if length(input)=0 then exit;
  687.   if lookupuser(input)<>0 then begin
  688.     writestr ('Sorry!  Already exists!');
  689.     exit
  690.   end;
  691.   u.handle:=input;
  692.   writestr ('Password:');
  693.   u.password:=input;
  694.   writestr ('Level:');
  695.   if length(input)=0 then exit;
  696.   u.level:=valu(input);
  697.   u.note:=newusernote;
  698.   un:=adduser(u);
  699.   if un=-1 then begin
  700.     writestr ('Sorry, no room for new users!');
  701.     exit
  702.   end;
  703.   ln:=u.level;
  704.   if ln<1 then ln:=1;
  705.   if ln>100 then ln:=100;
  706.   u.timetoday:=usertime[ln];
  707.   writeufile (u,un);
  708.   writestr ('User added as #'+strr(un)+'.');
  709.   writelog (2,8,u.handle)
  710. end;
  711.  
  712. procedure infoformhunt;
  713. begin
  714.   writestr ('User to search for [CR/All users]:');
  715.   writeln (^M);
  716.   showinfoforms (input)
  717. end;
  718.  
  719. procedure donations;
  720. var fn:lstr;
  721. begin
  722.   fn:=textfiledir+'Donation';
  723.   if exist (fn)
  724.     then printfile (fn)
  725.     else begin
  726.       writestr ('I''m sorry, no information is currently available.');
  727.       if issysop
  728.         then writestr (
  729. 'Sysop:  To create donation information text, make a file called '+fn)
  730.     end
  731. end;
  732.  
  733. procedure viewsyslog;
  734. var n:integer;
  735.     l:logrec;
  736.  
  737.   function lookupsyslogdat (m,s:integer):integer;
  738.   var cnt:integer;
  739.   begin
  740.     for cnt:=1 to numsyslogdat do with syslogdat[cnt] do
  741.       if (menu=m) and (subcommand=s) then begin
  742.         lookupsyslogdat:=cnt;
  743.         exit
  744.       end;
  745.     lookupsyslogdat:=0
  746.   end;
  747.  
  748.   function firstentry:boolean;
  749.   begin
  750.     firstentry:=(l.menu=0) and (l.subcommand in [1..2])
  751.   end;
  752.  
  753.   procedure backup;
  754.   begin
  755.     while n<>0 do begin
  756.       n:=n-1;
  757.       seek (logfile,n);
  758.       read (logfile,l);
  759.       if firstentry then exit
  760.     end;
  761.     n:=-1
  762.   end;
  763.  
  764.   procedure showentry (includedate:boolean);
  765.   var q:lstr;
  766.       p:integer;
  767.   begin
  768.     q:=syslogdat[lookupsyslogdat(l.menu,l.subcommand)].text;
  769.     p:=pos('%',q);
  770.     if p<>0 then q:=copy(q,1,p-1)+l.param+copy(q,p+1,255);
  771.     if includedate then q:=q+' on '+datestr(l.when);
  772.     q:=q+' at '+timestr(l.when);
  773.     writeln (q)
  774.   end;
  775.  
  776. var b:boolean;
  777. begin
  778.   writehdr ('View System Log');
  779.   writeln ('Press [Space] to advance to the previous caller, [X] to abort.');
  780.   writeln;
  781.   writelog (2,6,'');
  782.   n:=filesize(logfile);
  783.   repeat
  784.     clearbreak;
  785.     writeln (^M);
  786.     backup;
  787.     if n=-1 then exit;
  788.     seek (logfile,n);
  789.     read (logfile,l);
  790.     showentry (true);
  791.     b:=false;
  792.     while not (eof(logfile) or break or xpressed or b) do begin
  793.       read (logfile,l);
  794.       b:=firstentry;
  795.       if not b then showentry (false);
  796.     end
  797.   until xpressed
  798. end;
  799.  
  800. procedure viewsyslog2;
  801. var n:integer;
  802.     l:logrec;
  803.     kwit:boolean;
  804.  
  805.   function lookupsyslogdat (m,s:integer):integer;
  806.   var cnt:integer;
  807.   begin
  808.     for cnt:=1 to numsyslogdat do with syslogdat[cnt] do
  809.       if (menu=m) and (subcommand=s) then begin
  810.         lookupsyslogdat:=cnt;
  811.         exit
  812.       end;
  813.     lookupsyslogdat:=0
  814.   end;
  815.  
  816.   function firstentry:boolean;
  817.   begin
  818.     firstentry:=(l.menu=0) and (l.subcommand in [1..2])
  819.   end;
  820.  
  821.   procedure backup;
  822.   begin
  823.     while n<>0 do begin
  824.       n:=n-1;
  825.       seek (logfile,n);
  826.       read (logfile,l);
  827.       if firstentry then exit
  828.     end;
  829.     n:=-1
  830.   end;
  831.  
  832.   procedure showentry (includedate:boolean);
  833.   var q:lstr;
  834.       p:integer;
  835.   begin
  836.     q:=syslogdat[lookupsyslogdat(l.menu,l.subcommand)].text;
  837.     p:=pos('%',q);
  838.     if p<>0 then q:=copy(q,1,p-1)+l.param+copy(q,p+1,255);
  839.     if includedate then q:=q+' on '+datestr(l.when);
  840.     q:=q+' at '+timestr(l.when);
  841.     if wherey>=23 then begin
  842.      input:='';
  843.      writestr ('[Enter] to Continue or [Q]uit: *');
  844.      if (upcase(input[1])='Q') then kwit:=true;
  845.      clrscr;
  846.     end;
  847.     writeln (q)
  848.   end;
  849.  
  850. var b:boolean;
  851. begin
  852.   kwit:=false;
  853.   writehdr ('View System Log');
  854.   writeln ('Press [Space] to advance to the previous caller, [X] to abort.');
  855.   writeln;
  856.   writelog (2,6,'');
  857.   n:=filesize(logfile);
  858.   repeat
  859.     clearbreak;
  860.     writeln (^M);
  861.     backup;
  862.     if n=-1 then exit;
  863.     seek (logfile,n);
  864.     read (logfile,l);
  865.     showentry (true);
  866.     if kwit then exit;
  867.     b:=false;
  868.   { if wherey>=23 then begin
  869.      writestr ('[Enter] to continue or [Q]uit:');
  870.      if upcase(input[1])='Q' then exit;
  871.      clrscr;
  872.      gotoxy (1,1);
  873.     end; }
  874.     while not (eof(logfile) or break or xpressed or b) do begin
  875.       read (logfile,l);
  876.       b:=firstentry;
  877.       if not b then showentry (false);
  878.     end
  879.   until xpressed
  880. end;
  881.  
  882. procedure delsyslog;
  883. begin
  884.   writestr ('Delete System Log [y/n]:');
  885.   if not yes then exit;
  886.   close (logfile);
  887.   rewrite (logfile);
  888.   writeln (^M'System log deleted.');
  889.   writelog (2,7,unam)
  890. end;
  891.  
  892. procedure showsystemstatus;
  893. var totalused,totalidle,totalup,totaldown,totalmins,callsday:real;
  894.     yiyiyi:integer;
  895.     drv:array [1..15] of boolean;
  896.  
  897.   procedure diskcalcs;
  898.   var cnt,cnt2,curarea:integer;
  899.       ar,area:arearec;
  900.       ud:udrec;
  901.       inscan,showit,fast:boolean;
  902.  
  903.   procedure assignud;
  904.   begin
  905.     close (udfile);
  906.     assign (udfile,'AREA'+strr(curarea))
  907.   end;
  908.  
  909.   const beenaborted:boolean=false;
  910.  
  911.   function aborted:boolean;
  912.   begin
  913.     if beenaborted then begin
  914.       aborted:=true;
  915.       exit
  916.     end;
  917.     aborted:=xpressed or hungupon;
  918.     if xpressed then begin
  919.       beenaborted:=true;
  920.       writeln (^B'Aborted!')
  921.     end
  922.   end;
  923.  
  924.   procedure setarea (n:integer);
  925.   begin
  926.     curarea:=n;
  927.     seek (afile,n-1);
  928.     read (afile,area);
  929.     assignud;
  930.     close (udfile);
  931.     reset (udfile);
  932.     if ioresult<>0 then rewrite (udfile);
  933.   end;
  934.  
  935.   procedure checkdrive (dv:char);
  936.   var n:byte;
  937.       tempdisk,tempfree:real;
  938.  
  939.     procedure writefreespace (dr:byte);
  940.     var r:registers;
  941.         csize:real;
  942.  
  943.       function unsigned (i:integer):real;
  944.       begin
  945.         if i>=0 then unsigned:=i else unsigned:=65536.0+i
  946.       end;
  947.  
  948.     begin
  949.       r.ah:=$36;
  950.       r.dl:=dr;
  951.       intr ($21,r);
  952.       if r.ax=-1 then exit;
  953.       csize:=unsigned(r.ax)*unsigned(r.cx);
  954.       tempfree:=(csize*unsigned(r.bx))/1000;
  955.       tempdisk:=(csize*unsigned(r.dx))/1000;
  956.     end;
  957.  
  958.   begin
  959.     if (ord(dv)<65) or (ord(dv)>79) then exit;
  960.     n:=ord(dv)-64;
  961.     writefreespace(n);
  962.     if not drv[n] then begin
  963.       drv[n]:=true;
  964.       totaldisk:=totaldisk+tempdisk;
  965.       totalfree:=totalfree+tempfree;
  966.     end;
  967.   end;
  968.  
  969.   function getfname (path:lstr; name:mstr):lstr;
  970.   var l:lstr;
  971.   begin
  972.     l:=path;
  973.     if length(l)<>0 then if not (upcase(l[length(l)]) in [':','\'])
  974.       then l:=l+'\';
  975.     l:=l+name;
  976.     getfname:=l
  977.   end;
  978.  
  979.   begin
  980.     totalfiles:=0;
  981.     filesizes:=0;
  982.     totaldisk:=0;
  983.     totalFree:=0;
  984.     for cnt:=1 to 15 do drv[cnt]:=false;
  985.     assign (afile,'Areadir');
  986.     if exist ('Areadir') then begin
  987.      reset (afile);
  988.      if filesize (afile)<0 then exit
  989.     end
  990.     else rewrite (afile);
  991.     cnt:=1;
  992.     while (cnt<=filesize(afile)) do begin
  993.       seek (afile,cnt-1);
  994.       read (afile,ar);
  995.       checkdrive (upcase(ar.xmodemdir[1]));
  996.       setarea (cnt);
  997.       for cnt2:=filesize (udfile) downto 1 do begin
  998.         seek (udfile,cnt2-1);
  999.         read (udfile,ud);
  1000.         checkdrive (upcase(ud.path[1]));
  1001.         if aborted then begin
  1002.           totalfiles:=0;
  1003.           filesizes:=0;
  1004.           totaldisk:=0;
  1005.           totalfree:=0;
  1006.           exit;
  1007.         end;
  1008.         if exist (getfname(ud.path,ud.filename)) then begin
  1009.           totalfiles:=totalfiles+1;
  1010.           filesizes:=filesizes+ud.filesize;
  1011.         end;
  1012.       end;
  1013.       cnt:=cnt+1;
  1014.     end;
  1015.     filesizes:=filesizes/1000;
  1016.   end;
  1017.  
  1018.   procedure percent (prompt:mstr; top,bot:real);
  1019.   var p:real;
  1020.   begin
  1021.     write (prompt);
  1022.     if bot<1 then begin
  1023.       writeln ('N/A');
  1024.       exit
  1025.     end;
  1026.     p:=round(1000*top/bot)/10;
  1027.     writeln (p:0:1,'%')
  1028.   end;
  1029.  
  1030. var ozzy,anarky:anystr;
  1031.     metallica:integer;
  1032. begin
  1033.   writehdr ('System Status');
  1034.   dofiles:=false;
  1035.   totalused:=numminsused.total+elapsedtime(numminsused);
  1036.   totalidle:=numminsidle.total;
  1037.   totalup:=totalidle+numminsused.total;
  1038.   totalmins:=1440.0*(numdaysup-1.0)+timer;
  1039.   totaldown:=totalmins-totalup;
  1040.   callsday:=round(10*numcallers/numdaysup)/10;
  1041.   writestr ('Calculate Disk Storages & File Area Stats [y/n]? *');
  1042.   writeln;
  1043.   if yes then begin
  1044.    writeln ('Calculating...');
  1045.    dofiles:=true;
  1046.    diskcalcs;
  1047.   end;
  1048.   ozzy:=ver+' - '+parsedate(date);
  1049.   {
  1050.   write (^R'╒═══════════════════════════════════╤═══════════════════════════════════╕');
  1051.   writeln;
  1052.   write (^R'│ TCS Version: '^S);
  1053.   tab (ozzy,21);
  1054.   write (^R'│ ');
  1055.   write ('Time & Date: '^S);
  1056.   tab(timestr(now)+', '+datestr(now),21);
  1057.   writeln (^R'│');
  1058.   write (^R'│ Calls Today: '^S);
  1059.   tab (strr(callstoday),21);
  1060.   write (^R'│ ');
  1061.   write ('Total Callers: '^S);
  1062.   tab (streal(numcallers),19);
  1063.   writeln (^R'│');
  1064.   write ('│ Total Days up: '^S);
  1065.   tab (strr(numdaysup),19);
  1066.   write (^R'│ ');
  1067.   write ('Calls per day: '^S);
  1068.   tab (streal(callsday),19);
  1069.   writeln (^R'│');
  1070.   write ('│ Total mins in use: '^S);
  1071.   tab (streal(numminsused.total),15);
  1072.   write (^R'│ ');
  1073.   write ('Total mins idle: '^S);
  1074.   tab (streal(totalidle),17);
  1075.   writeln (^R'│');
  1076.   write ('│ Mins File Xfer: '^S);
  1077.   tab (streal(numminsxfer.total),18);
  1078.   write (^R'│ ');
  1079.   write ('Total mins Up: '^S);
  1080.   tab (streal(totalup),19);
  1081.   writeln (^R'│');
  1082.   write ('Total mins Down: '^S);
  1083.   tab (streal(totaldown),19);
  1084.   write (^R'│ '); }
  1085.   writeln ('TCS Version:       '^S,ozzy);
  1086.   writeln ('Time & Date:       '^S,timestr(now),', ',datestr(now));
  1087.   writeln ('Calls today:       '^S,callstoday);
  1088.   writeln ('Total callers:     '^S,numcallers:0:0);
  1089.   writeln ('Total days up:     '^S,numdaysup);
  1090.   writeln ('Calls per day:     '^S,callsday:0:1);
  1091.   writeln ('Total mins in use: '^S,numminsused.total:0:0);
  1092.   writeln ('Total mins idle:   '^S,totalidle:0:0);
  1093.   writeln ('Mins file xfer:    '^S,numminsxfer.total:0:0);
  1094.   writeln ('Total mins up:     '^S,totalup:0:0);
  1095.   writeln ('Total mins down:   '^S,totaldown:0:0);
  1096.   percent ('% BBS is in use:   '^S,totalused,totalmins);
  1097.   percent ('% BBS is idle:     '^S,totalidle,totalmins);
  1098.   percent ('% BBS is up:       '^S,totalup,totalmins);
  1099.   percent ('% BBS is down:     '^S,totaldown,totalmins);
  1100.   if dofiles then begin
  1101.   percent ('% Space Unused:    '^S,totalfree,totaldisk);
  1102.   percent ('% Space Used:      '^S,(totaldisk-totalfree),totaldisk);
  1103.   percent ('% Storage Online:  '^S,filesizes,totaldisk);
  1104.   writeln ('Files Online:      '^S,totalfiles);
  1105.   writeln ('Files Storage:     '^S,streal (filesizes/1000),' Megabytes');
  1106.   writeln ('Total Storage:     '^S,streal (totaldisk/1000),' Megabytes');
  1107.   writeln ('Upload Space:      '^S,streal (totalfree/1000),' Megabytes');
  1108.   write   ('Drives Online:     '^S);
  1109.   for yiyiyi:=1 to 15 do
  1110.    if drv[yiyiyi] then write (chr(yiyiyi+64),': ');
  1111.   end;
  1112.   writeln (^R);
  1113. end;
  1114.  
  1115. procedure showallforms;
  1116. begin
  1117.   showinfoforms ('')
  1118. end;
  1119.  
  1120. procedure showallsysops;
  1121. var n:integer;
  1122.     u:userrec;
  1123.     q:set of configtype;
  1124.     s:configtype;
  1125.  
  1126.   procedure showuser;
  1127.   const sectionnames:array [udsysop..databasesysop] of string[20]=
  1128.          ('File transfer','Bulletin section','Voting booths',
  1129.           'E-mail section','Doors','Main Menu','Databases');
  1130.   var s:configtype;
  1131.   begin
  1132.     writeln (^B^M'Name:  '^S,u.handle,
  1133.                ^M'Level: '^S,u.level,^M);
  1134.     for s:=udsysop to databasesysop do
  1135.       if s in u.config then
  1136.         writeln ('Sysop of the ',sectionnames[s]);
  1137.     writestr (^M'Edit user? *');
  1138.     if yes then edituser (n)
  1139.   end;
  1140.  
  1141. begin
  1142.   q:=[];
  1143.   for s:=udsysop to databasesysop do q:=q+[s];
  1144.   for n:=1 to numusers do begin
  1145.     seek (ufile,n);
  1146.     read (ufile,u);
  1147.     if (u.level>=sysoplevel) or (q*u.config<>[]) then showuser
  1148.   end
  1149. end;
  1150.  
  1151. procedure mainhelp;
  1152. begin
  1153.   help ('Mainmenu.Hlp')
  1154. end;
  1155.  
  1156. procedure bbslist;
  1157. var card,ugbot,p:lstr;
  1158.     b:bbsrec;
  1159.  
  1160.    function numbbses:integer;
  1161.    begin
  1162.      numbbses:=filesize(blfile)
  1163.    end;
  1164.  
  1165.    procedure seekblfile (n:integer);
  1166.    begin
  1167.      seek (blfile,n-1);
  1168.    end;
  1169.  
  1170.    function numbbs:integer;
  1171.    begin
  1172.     numbbs:=filesize (blfile);
  1173.    end;
  1174.  
  1175.    procedure getstring (t:lstr; var m; buf:integer);
  1176.    var q:lstr absolute m;
  1177.        mm:lstr;
  1178.    begin
  1179.      writeln (^R'Old ',t,': '^S,q,^R);
  1180.      buflen:=buf;
  1181.      writestr ('Enter new '+t+' [CR/no change]:');
  1182.      mm:=input;
  1183.      if length(mm)<>0 then q:=mm;
  1184.      writeln
  1185.    end;
  1186.  
  1187.     procedure listbbs;
  1188.     var cnt,b1,b2:integer;
  1189.         showedz:boolean;
  1190.     begin
  1191.      writehdr ('BBS List');
  1192.      reset (blfile);
  1193.      if ioresult<>0 then begin
  1194.       writeln ('There are no BBS''s in the list.  Add one!');
  1195.       exit;
  1196.      end
  1197.      else begin
  1198.      parserange (numbbs,b1,b2);
  1199.      writestr ('Show Extended BBS Descriptions [Y/n]? *');
  1200.      writeln;
  1201.      showedz:=true;
  1202.      if upcase(input[1])='N' then showedz:=false;
  1203.      if b1>0 then
  1204.      for cnt := b1 to b2 do
  1205.      begin
  1206.       seekblfile (cnt);
  1207.       read (blfile,b);
  1208.       write (^R'['^S);
  1209.       tab (b.number,12);
  1210.       write (^R'] ['^P);
  1211.       tab (b.name,48);
  1212.       write (^R'] ['^U);
  1213.       tab (b.maxbaud,4);
  1214.       write (^R'] ['^P);
  1215.       tab (b.ware,4);
  1216.       writeln (^R']');
  1217.       if showedz then
  1218.       begin
  1219.        write (^R' ['^U);
  1220.        tab (b.extdesc,76);
  1221.        writeln (^R']');
  1222.       end;
  1223.      end;
  1224.     end;
  1225.     end;
  1226.  
  1227.     procedure addbbs;
  1228.     begin
  1229.      writehdr ('Add a BBS');
  1230.      writeln (^R'Phone Number [12 Characters Max]');
  1231.      writeln (^R'  [------------]');
  1232.      buflen:=12;
  1233.      writestr ('-> &');
  1234.      b.number:=input;
  1235.      writeln;
  1236.      writeln (^R'Enter BBS Name [48 Characters Max]');
  1237.      writeln (^R'  [------------------------------------------------]');
  1238.      buflen:=48;
  1239.      writestr ('-> &');
  1240.      b.name:=input;
  1241.      writeln;
  1242.      writeln (^R'Maximum Baud [4 Digits] (ie 2400,9600,19.2)');
  1243.      writeln (^R'  [----]');
  1244.      buflen:=4;
  1245.      writestr ('-> &');
  1246.      b.maxbaud:=input;
  1247.      if valu(b.maxbaud)<=300 then
  1248.      writeln (^R^M'Man, your board must really suck!');
  1249.      writeln;
  1250.      writeln (^R'BBS Software [4 Characters Max] (ie TCS,EM/2,WWIV)');
  1251.      writeln (^R'  [----]');
  1252.      buflen:=4;
  1253.      writestr ('-> &');
  1254.      b.ware:=input;
  1255.      writeln;
  1256.      writeln (^R'Extended BBS Description [77 Characters Max - CR for none]');
  1257.      writeln (^R'  [-------------------------------------------------------------------------]');
  1258.      buflen:=77;
  1259.      writestr ('-> &');
  1260.      b.extdesc:=input;
  1261.      b.leftby:=unam;
  1262.      if (length(b.number)>0) and (length(b.name)>0) and (length(b.maxbaud)>0)
  1263.      and (length(b.ware)>0) then begin
  1264.       if not exist ('BBSList.Dat') then rewrite (blfile);
  1265.       seekblfile (numbbses+1);
  1266.       write (blfile,b);
  1267.       writeln (^M^S'BBS Added!'^R^M);
  1268.      end else
  1269.      writeln (^M^S'Entry incomplete!'^R^M);
  1270.      end;
  1271.  
  1272.   procedure changebbs;
  1273.   var q,spock:integer;
  1274.       doodzdomain:char;
  1275.  
  1276.    procedure showbbs (b:bbsrec);
  1277.    begin
  1278.    writeln (^M^R'[1] BBS Name:     '^S,b.name,
  1279.             ^M^R'[2] BBS Number:   '^S,b.number,
  1280.             ^M^R'[3] Max Baud:     '^S,b.maxbaud,
  1281.             ^M^R'[4] BBS Software: '^S,b.ware,
  1282.             ^M^R'[5] Extended BBS Description:',
  1283.             ^M^R'> '^S,b.extdesc,
  1284.             ^M^R'[Q] Quit');
  1285.    end;
  1286.  
  1287.    begin
  1288.        writehdr ('Change an Entry');
  1289.        writestr (^M'Entry to Change [?/List]: &');
  1290.        if input[1]='?' then listbbs;
  1291.        spock:=valu(input);
  1292.        if spock<1 then exit;
  1293.        if spock>numbbs then exit;
  1294.        seekblfile (spock);
  1295.        read (blfile,b);
  1296.        if not (match (b.leftby,unam)) then begin
  1297.         writeln (^M'You didn''t post that entry!'^M);
  1298.         exit;
  1299.        end;
  1300.        repeat
  1301.        showbbs (b);
  1302.        writestr ('[Edit BBS List Command]: *');
  1303.        doodzdomain:=upcase(input[1]);
  1304.        case doodzdomain of
  1305.         '1':getstring ('BBS Name',b.name,48);
  1306.         '2':getstring ('BBS Number',b.number,12);
  1307.         '3':getstring ('Maximum Baud',b.maxbaud,4);
  1308.         '4':getstring ('BBS Software',b.ware,4);
  1309.         '5':begin
  1310.              writeln ('Old Extended BBS Description:');
  1311.              writeln ('> ',b.extdesc);
  1312.              writeln ('Enter new Extended BBS Description [CR/no change]:');
  1313.              buflen:=77;
  1314.              writestr ('> &');
  1315.              if length(input)<>0 then b.extdesc:=input;
  1316.              writeln
  1317.             end;
  1318.         'Q':;
  1319.        end;
  1320.        until doodzdomain='Q';
  1321.        write (blfile,b);
  1322.        close (blfile);
  1323.       end;
  1324.  
  1325.   procedure deletebbs;
  1326.   begin
  1327.    writehdr ('Delete an Entry');
  1328.   end;
  1329.  
  1330.   procedure bbslistsysop;
  1331.   begin
  1332.      writeln;
  1333.      repeat
  1334.       ugbot:=' ';
  1335.       writeln  (^R'['^S'D'^R']elete an Entry');
  1336.       writeln  (^R'['^S'C'^R']hange an Entry');
  1337.       writeln  (^R'['^S'S'^R']ort Entries');
  1338.     { writeln  (^R'['^S'T'^R']Textfile'); }
  1339.       writeln  (^R'['^S'Q'^R']uit');
  1340.       writestr ('[BBS List Sysop Command]:');
  1341.       ugbot:=upstring(input);
  1342.       case ugbot[1] of
  1343.        'D':deletebbs;
  1344.        'C':changebbs;
  1345.        'S':begin
  1346.            end;
  1347.        'T':begin
  1348.            end;
  1349.        'Q':;
  1350.       end;
  1351.      until (ugbot[1]='Q');
  1352.     end;
  1353.  
  1354. label exit;
  1355. var q:integer;
  1356. begin
  1357.     assign (blfile,'BBSList.Dat');
  1358.     repeat
  1359.      q:=menu ('BBS List Menu','BBSLIST','LADC%Q');
  1360.      writeln;
  1361.      case q of
  1362.       1:listbbs;
  1363.       2:addbbs;
  1364.       3:deletebbs;
  1365.       4:changebbs;
  1366.       5:bbslistsysop;
  1367.       6:goto exit;
  1368.      end;
  1369.      until (hungupon) or (q=6);
  1370.     exit:
  1371.     close (blfile);
  1372. end;
  1373.  
  1374. procedure readerrlog;
  1375. begin
  1376.   if exist ('Errlog')
  1377.     then printfile ('Errlog')
  1378.     else writestr ('No error file!')
  1379. end;
  1380.  
  1381. procedure showad;
  1382. var fn:lstr;
  1383. begin
  1384.   fn:=textfiledir+'TCS.Ad';
  1385.   if exist (fn) then printfile (fn) else begin
  1386.   writeln (^M'No Advertisement.'^M);
  1387.   writeln (usr,'Sysop: To make one, create a file called TCS.AD in your Menus Directory.'^M);
  1388.   end;
  1389. end;
  1390.  
  1391. procedure setlastcall;
  1392.  
  1393.   function digit (k:char):boolean;
  1394.   begin
  1395.     digit:=ord(k) in [48..57]
  1396.   end;
  1397.  
  1398.   function validtime (inp:sstr):boolean;
  1399.   var c,s,l:integer;
  1400.       d1,d2,d3,d4:char;
  1401.       ap,m:char;
  1402.   begin
  1403.     validtime:=false;
  1404.     l:=length(inp);
  1405.     if (l<7) or (l>8) then exit;
  1406.     c:=pos(':',inp);
  1407.     if c<>l-5 then exit;
  1408.     s:=pos(' ',inp);
  1409.     if s<>l-2 then exit;
  1410.     d2:=inp[c-1];
  1411.     if l=7
  1412.       then d1:='0'
  1413.       else d1:=inp[1];
  1414.     d3:=inp[c+1];
  1415.     d4:=inp[c+2];
  1416.     ap:=upcase(inp[s+1]);
  1417.     m:=upcase(inp[s+2]);
  1418.     if d1='1' then if d2>'2' then d2:='!';
  1419.     if (d1>='0') and (d1<='1') and digit(d2) and (d3>='0') and (d3<='5')
  1420.        and digit(d4) and ((ap='A') or (ap='P')) and (m='M')
  1421.          then validtime:=true
  1422.   end;
  1423.  
  1424.   function validdate (inp:sstr):boolean;
  1425.   var k,l:char;
  1426.  
  1427.     function gchar:char;
  1428.     begin
  1429.       if length(inp)=0 then begin
  1430.         gchar:='?';
  1431.         exit
  1432.       end;
  1433.       gchar:=inp[1];
  1434.       delete (inp,1,1)
  1435.     end;
  1436.  
  1437.   begin
  1438.     validdate:=false;
  1439.     k:=gchar;
  1440.     l:=gchar;
  1441.     if not digit(k) then exit;
  1442.     if l='/'
  1443.       then if k='0'
  1444.         then exit
  1445.         else
  1446.       else begin
  1447.         if k>'1' then exit;
  1448.         if not digit(l) then exit;
  1449.         if (l>'2') and (k='1') then exit;
  1450.         l:=gchar;
  1451.         if l<>'/' then exit
  1452.       end;
  1453.     k:=gchar;
  1454.     l:=gchar;
  1455.     if l='/'
  1456.       then if k='0'
  1457.         then exit
  1458.         else
  1459.       else begin
  1460.         if k>'3' then exit;
  1461.         if not digit(l) then exit;
  1462.         if (k='3') and (l>'1') then exit;
  1463.         l:=gchar;
  1464.         if l<>'/' then exit
  1465.       end;
  1466.     if digit(gchar) and digit(gchar) then validdate:=true
  1467.   end;
  1468.  
  1469. begin
  1470.   writeln (^M'Your last call was: '^S,datestr(laston),' at ',timestr(laston));
  1471.   writestr (^M'Enter new date (mm/dd/yy):');
  1472.   if length(input)>0
  1473.     then if validdate (input)
  1474.       then laston:=dateval(input)+timepart(laston)
  1475.       else writestr ('Invalid date!');
  1476.   writestr (^M'Enter new time (hh:mm am/pm):');
  1477.   if length(input)>0
  1478.     then if validtime(input)
  1479.       then laston:=timeval(input)+datepart(laston)
  1480.       else writestr ('Invalid time!')
  1481. end;
  1482.  
  1483. procedure removeallforms;
  1484. var cnt,ndel:integer;
  1485.     u:userrec;
  1486. begin
  1487.   writestr ('Erase ALL of which Info-Form [#1-5]? *');
  1488.   if (valu(input)<1) or (valu(input)>5) then exit;
  1489.   writestr ('Erase ALL # '+strr(valu(input))+' Info-Forms -- Are you sure [y/n]? *');
  1490.   if not yes then exit;
  1491.   writeurec;
  1492.   writestr (^M'Erasing... please stand by...');
  1493.   ndel:=0;
  1494.   for cnt:=1 to numusers do begin
  1495.     if (cnt mod 10)=0 then write (cnt,', ');
  1496.     seek (ufile,cnt);
  1497.     read (ufile,u);
  1498.     if (valu(input)=1) then begin
  1499.     if u.infoform1>=0 then begin
  1500.       deletetext (u.infoform1);
  1501.       u.infoform1:=-1;
  1502.       seek (ufile,cnt);
  1503.       write (ufile,u);
  1504.       ndel:=ndel+1
  1505.     end
  1506.    end else
  1507.    if (valu(input)=2) then begin
  1508.     if u.infoform2>=0 then begin
  1509.       deletetext (u.infoform2);
  1510.       u.infoform2:=-1;
  1511.       seek (ufile,cnt);
  1512.       write (ufile,u);
  1513.       ndel:=ndel+1
  1514.     end
  1515.    end else
  1516.    if (valu(input)=3) then begin
  1517.     if u.infoform3>=0 then begin
  1518.       deletetext (u.infoform3);
  1519.       u.infoform3:=-1;
  1520.       seek (ufile,cnt);
  1521.       write (ufile,u);
  1522.       ndel:=ndel+1
  1523.     end
  1524.    end else
  1525.    if (valu(input)=4) then begin
  1526.     if u.infoform4>=0 then begin
  1527.       deletetext (u.infoform4);
  1528.       u.infoform4:=-1;
  1529.       seek (ufile,cnt);
  1530.       write (ufile,u);
  1531.       ndel:=ndel+1
  1532.     end
  1533.    end else
  1534.    if (valu(input)=5) then begin
  1535.     if u.infoform5>=0 then begin
  1536.       deletetext (u.infoform5);
  1537.       u.infoform5:=-1;
  1538.       seek (ufile,cnt);
  1539.       write (ufile,u);
  1540.       ndel:=ndel+1
  1541.     end
  1542.    end;
  1543.   end;
  1544.   writeln ('Done.');
  1545.   writestr (^M'All '+strr(ndel)+' Info-forms #'+strr(valu(input))+' erased.');
  1546.   readurec
  1547. end;
  1548.  
  1549. procedure readfeedback;
  1550. var ffile:file of mailrec;
  1551.     m:mailrec;
  1552.     me:message;
  1553.     cur:integer;
  1554.  
  1555.   function nummessages:integer;
  1556.   begin
  1557.     nummessages:=filesize(ffile)
  1558.   end;
  1559.  
  1560.   function checkcur:boolean;
  1561.   begin
  1562.     if length(input)>1 then cur:=valu(copy(input,2,255));
  1563.     if (cur<1) or (cur>nummessages) then begin
  1564.       writestr (^M'Message out of range!');
  1565.       cur:=0;
  1566.       checkcur:=true
  1567.     end else begin
  1568.       checkcur:=false;
  1569.       seek (ffile,cur-1);
  1570.       read (ffile,m)
  1571.     end
  1572.   end;
  1573.  
  1574.   procedure readnum (n:integer);
  1575.   begin
  1576.     cur:=n;
  1577.     input:='';
  1578.     if checkcur then exit;
  1579.     writeln (^B^M'Message: '^S,cur,
  1580.                ^M'Title:   '^S,m.title,
  1581.                ^M'Sent by: '^S,m.sentby,
  1582.                ^M'Sent on: '^S,datestr(m.when),' at ',timestr(m.when),^M);
  1583.     if break then exit;
  1584.     printtext (m.line)
  1585.   end;
  1586.  
  1587.   procedure writecurmsg;
  1588.   begin
  1589.     if (cur<1) or (cur>nummessages) then cur:=0;
  1590.     write (^B^M'Current msg: '^S);
  1591.     if cur=0 then write ('None') else begin
  1592.       seek (ffile,cur-1);
  1593.       read (ffile,m);
  1594.       write (m.title,' by ',m.sentby)
  1595.     end
  1596.   end;
  1597.  
  1598.   procedure delfeedback;
  1599.   var cnt:integer;
  1600.   begin
  1601.     if checkcur then exit;
  1602.     deletetext (m.line);
  1603.     for cnt:=cur to nummessages-1 do begin
  1604.       seek (ffile,cnt);
  1605.       read (ffile,m);
  1606.       seek (ffile,cnt-1);
  1607.       write (ffile,m)
  1608.     end;
  1609.     seek (ffile,nummessages-1);
  1610.     truncate (ffile);
  1611.     cur:=cur-1
  1612.   end;
  1613.  
  1614.   procedure editusr;
  1615.   var n:integer;
  1616.   begin
  1617.     if checkcur then exit;
  1618.     n:=lookupuser (m.sentby);
  1619.     if n=0
  1620.       then writestr ('User disappeared!')
  1621.       else edituser (n)
  1622.   end;
  1623.  
  1624.   procedure infoform;
  1625.   begin
  1626.     if checkcur then exit;
  1627.     showinfoforms (m.sentby)
  1628.   end;
  1629.  
  1630.   procedure nextfeedback;
  1631.   begin
  1632.     cur:=cur+1;
  1633.     if cur>nummessages then begin
  1634.       writestr (^M'Sorry, no more feedback!');
  1635.       cur:=0;
  1636.       exit
  1637.     end;
  1638.     readnum (cur)
  1639.   end;
  1640.  
  1641.   procedure readagain;
  1642.   begin
  1643.     if checkcur then exit;
  1644.     readnum (cur)
  1645.   end;
  1646.  
  1647.   procedure replyfeedback;
  1648.   begin
  1649.     if checkcur then exit;
  1650.     sendmailto (m.sentby,false)
  1651.   end;
  1652.  
  1653.   procedure listfeedback;
  1654.   var cnt:integer;
  1655.   begin
  1656.     if nummessages=0 then exit;
  1657.     thereare (nummessages,'piece of feedback','pieces of feedback');
  1658.     if break then exit;
  1659.     writeln (^M'Num Title                          Left by'^M);
  1660.     seek (ffile,0);
  1661.     for cnt:=1 to nummessages do begin
  1662.       read (ffile,m);
  1663.       tab (strr(cnt),4);
  1664.       if break then exit;
  1665.       tab (m.title,31);
  1666.       writeln (m.sentby);
  1667.       if break then exit
  1668.     end
  1669.   end;
  1670.  
  1671.  
  1672. var q:integer;
  1673. label exit;
  1674. begin
  1675.   assign (ffile,'Feedback');
  1676.   reset (ffile);
  1677.   if ioresult<>0 then rewrite (ffile);
  1678.   cur:=0;
  1679.   repeat
  1680.     if nummessages=0 then begin
  1681.       writestr ('Sorry, no feedback!');
  1682.       goto exit
  1683.     end;
  1684.     writecurmsg;
  1685.     q:=menu ('Feedback Menu','FEED','Q#DEIR_AL');
  1686.     if q<0
  1687.       then readnum (-q)
  1688.       else case q of
  1689.         3:delfeedback;
  1690.         4:editusr;
  1691.         5:infoform;
  1692.         6:replyfeedback;
  1693.         7:nextfeedback;
  1694.         8:readagain;
  1695.         9:listfeedback;
  1696.       end
  1697.   until (q=1) or hungupon;
  1698.   exit:
  1699.   close (ffile)
  1700. end;
  1701.  
  1702. begin
  1703. end.
  1704.