home *** CD-ROM | disk | FTP | other *** search
/ Jason Aller Floppy Collection / 276.img / FORUM21S.ZIP / SUBS2.PAS < prev    next >
Pascal/Delphi Source File  |  1988-02-13  |  24KB  |  1,058 lines

  1. {$R-,S-,I-,D-,T-,F-,V-,B-,N-,L+ }
  2. {$M 65500,0,0 }
  3.  
  4. unit subs2;
  5.  
  6. { $define testingdevices}   (* Activate this define for test mode *)
  7.  
  8. interface
  9.  
  10. uses printer,dos,crt,gentypes,configrt,gensubs,subs1,windows,modem,statret,chatstuf,
  11.      flags;
  12.  
  13. procedure beepbeep;
  14. procedure summonbeep;
  15. procedure abortttfile (er:integer);
  16. procedure openttfile;
  17. procedure writecon (k:char);
  18. procedure toggleavail;
  19. function charready:boolean;
  20. function readchar:char;
  21. function waitforchar:char;
  22. procedure clearchain;
  23. function charpressed (k:char):boolean;  { TRUE if K is in typeahead }
  24. procedure addtochain (l:lstr);
  25. procedure directoutchar (k:char);
  26. procedure handleincoming;
  27. procedure writechar (k:char);
  28. {$F+}
  29.       function opendevice (var t:textrec):integer;
  30.       function closedevice (var t:textrec):integer;
  31.       function cleardevice (var t:textrec):integer;
  32.       function ignorecommand (var t:textrec):integer;
  33.       function directoutchars (var t:textrec):integer;
  34.       function writechars (var t:textrec):integer;
  35.       function directinchars (var t:textrec):integer;
  36.       function readcharfunc (var t:textrec):integer;
  37. {$F-}
  38. function getinputchar:char;
  39. procedure getstr;
  40. procedure writestr (s:anystr);
  41. procedure cls;
  42. procedure writehdr (q:anystr);
  43. function issysop:boolean;
  44. procedure reqlevel (l:integer);
  45. procedure printfile (fn:lstr);
  46. procedure printtexttopoint (var tf:text);
  47. procedure skiptopoint (var tf:text);
  48. function minstr (blocks:integer):sstr;
  49. procedure parserange (numents:integer; var f,l:integer);
  50. function menu (mname:mstr; mfn:sstr; choices:anystr):integer;
  51. function checkpassword (var u:userrec):boolean;
  52. function getpassword:boolean;
  53. procedure getacflag (var ac:accesstype; var tex:mstr);
  54.  
  55. implementation
  56.  
  57. procedure beepbeep;
  58. begin
  59.   nosound;
  60.   sound (200);
  61.   delay (10);
  62.   nosound
  63. end;
  64.  
  65. procedure summonbeep;
  66. var cnt:integer;
  67. begin
  68.   nosound;
  69.   cnt:=1330;
  70.   repeat
  71.     sound (cnt);
  72.     delay (10);
  73.     cnt:=cnt+200;
  74.   until cnt>4300;
  75.   nosound
  76. end;
  77.  
  78. procedure abortttfile (er:integer);
  79. var n:integer;
  80. begin
  81.   specialmsg ('<Texttrap error '+strr(er)+'>');
  82.   texttrap:=false;
  83.   textclose (ttfile);
  84.   n:=ioresult
  85. end;
  86.  
  87. procedure openttfile;
  88. var n:integer;
  89. begin
  90.   appendfile ('Texttrap',ttfile);
  91.   n:=ioresult;
  92.   if n=0
  93.     then texttrap:=true
  94.     else abortttfile (n)
  95. end;
  96.  
  97. procedure writecon (k:char);
  98. var r:registers;
  99. begin
  100.   if k=^J
  101.     then write (usr,k)
  102.     else
  103.       begin
  104.         r.dl:=ord(k);
  105.         r.ah:=2;
  106.         intr($21,r)
  107.       end
  108. end;
  109.  
  110. procedure toggleavail;
  111. begin
  112.   if sysopavail=notavailable
  113.     then sysopavail:=available
  114.     else sysopavail:=succ(sysopavail)
  115. end;
  116.  
  117. function charready:boolean;
  118. var k:char;
  119. begin
  120.   if modeminlock then while numchars>0 do k:=getchar;
  121.   if hungupon or keyhit
  122.     then charready:=true
  123.     else if online
  124.       then charready:=(not modeminlock) and (numchars>0)
  125.       else charready:=false
  126. end;
  127.  
  128. function readchar:char;
  129.  
  130.   procedure toggletempsysop;
  131.   begin
  132.     if tempsysop
  133.       then ulvl:=regularlevel
  134.       else
  135.         begin
  136.           regularlevel:=ulvl;
  137.           ulvl:=sysoplevel
  138.         end;
  139.     tempsysop:=not tempsysop
  140.   end;
  141.  
  142.   procedure togviewstats;
  143.   begin
  144.     if splitmode
  145.       then unsplit
  146.       else
  147.         begin
  148.           splitscreen (7);
  149.           top;
  150.           clrscr;
  151.           write (usr,'File Level:     ',urec.udlevel,
  152.                  ^M^J'File Points:    ',urec.udpoints,
  153.                  ^M^J'XMODEM uploads: ',urec.uploads,
  154.                  ^M^J'XMODEM dnloads: ',urec.downloads);
  155.           window (40,1,80,5);
  156.           gotoxy (1,1);
  157.           write (usr,'Posts:      ',urec.nbu,
  158.                  ^M^J'Uploads:    ',urec.nup,
  159.                  ^M^J'Downloads:  ',urec.ndn,
  160.                  ^M^J'Total Time: ',urec.totaltime:0:0,
  161.                  ^M^J'Num. calls: ',urec.numon);
  162.           window (1,1,80,5);
  163.           bottom
  164.         end;
  165.   end;
  166.  
  167.   procedure showhelp;
  168.   begin
  169.     if splitmode
  170.       then unsplit
  171.       else begin
  172.         splitscreen (10);
  173.         top;
  174.         clrscr;
  175.         write (usr,
  176. 'Chat with user: F1               Sysop commands: F2'^M^J,
  177. 'Sysop gets the system next: F7   Lock the timer: F8'^M^J,
  178. 'Lock out all modem input: F9     Lock all modem output: F10'^M^J,
  179. 'Chat availabily toggle: Alt-A    Grant temporary sysop powers: Alt-T'^M^J,
  180. 'Grant user more time: Alt-M      Take away user''s time: Alt-L'^M^J,
  181. 'Take away ALL time: Alt-K        Refresh the bottom line: Alt-B'^M^J,
  182. 'Toggle printer echo: Ctrl-PrtSc  Toggle text trap: Alt-E'^M^J,
  183. 'View user''s status: Alt-V');
  184.     end;
  185.   end;
  186.  
  187.   procedure toggletexttrap;
  188.   var n:integer;
  189.   begin
  190.     if texttrap
  191.       then
  192.         begin
  193.           textclose (ttfile);
  194.           n:=ioresult;
  195.           if n<>0 then abortttfile (n);
  196.           texttrap:=false
  197.         end
  198.       else openttfile
  199.   end;
  200.  
  201. var k:char;
  202.     ret:char;
  203.     dorefresh:boolean;
  204. begin
  205.   requestchat:=false;
  206.   requestcom:=false;
  207.   reqspecial:=false;
  208.   if keyhit
  209.     then
  210.       begin
  211.         k:=bioskey;
  212.         ret:=k;
  213.         if ord(k)>127 then begin
  214.           ret:=#0;
  215.           dorefresh:=ingetstr;
  216.           case ord(k)-128 of
  217.             availtogglechar:
  218.               begin
  219.                 toggleavail;
  220.                 chatmode:=false;
  221.                 dorefresh:=true
  222.               end;
  223.             sysopcomchar:
  224.               begin
  225.                 requestcom:=true;
  226.                 requestchat:=true
  227.               end;
  228.             breakoutchar:halt(e_controlbreak);
  229.             lesstimechar:urec.timetoday:=urec.timetoday-1;
  230.             moretimechar:urec.timetoday:=urec.timetoday+1;
  231.             notimechar:settimeleft (-1);
  232.             chatchar:requestchat:=true;
  233.             sysnextchar:sysnext:=not sysnext;
  234.             timelockchar:if timelock then timelock:=false else begin
  235.                            timelock:=true;
  236.                            lockedtime:=timeleft
  237.                          end;
  238.             inlockchar:modeminlock:=not modeminlock;
  239.             outlockchar:setoutlock (not modemoutlock);
  240.             tempsysopchar:toggletempsysop;
  241.             bottomchar:bottomline;
  242.             viewstatchar:togviewstats;
  243.             sysophelpchar:if dorefresh then showhelp;
  244.             texttrapchar:toggletexttrap;
  245.             printerechochar:printerecho:=not printerecho;
  246.             72:ret:=^E;
  247.             75:ret:=^S;
  248.             77:ret:=^D;
  249.             80:ret:=^X;
  250.             115:ret:=^A;
  251.             116:ret:=^F;
  252.             73:ret:=^R;
  253.             81:ret:=^C;
  254.             71:ret:=^Q;
  255.             79:ret:=^W;
  256.             83:ret:=^G;
  257.             82:ret:=^V;
  258.             117:ret:=^P;
  259.           end;
  260.           if dorefresh then bottomline
  261.         end
  262.       end
  263.     else
  264.       begin
  265.         k:=getchar;
  266.         if modeminlock
  267.           then ret:=#0
  268.           else ret:=k
  269.       end;
  270.   if ret='+' then write (' '^H);
  271.   readchar:=ret
  272. end;
  273.  
  274. function waitforchar:char;
  275. var t:integer;
  276.     k:char;
  277. begin
  278.   t:=timer+mintimeout;
  279.   if t>=1440 then t:=t-1440;
  280.   repeat
  281.     if timer=t then forcehangup:=true
  282.   until charready;
  283.   waitforchar:=readchar
  284. end;
  285.  
  286. procedure clearchain;
  287. begin
  288.   chainstr[0]:=#0
  289. end;
  290.  
  291. function charpressed (k:char):boolean;  { TRUE if K is in typeahead }
  292. begin
  293.   charpressed:=pos(k,chainstr)>0
  294. end;
  295.  
  296. procedure addtochain (l:lstr);
  297. begin
  298.   if length(chainstr)<>0 then chainstr:=chainstr+',';
  299.   chainstr:=chainstr+l
  300. end;
  301.  
  302. procedure directoutchar (k:char);
  303. var n:integer;
  304. begin
  305.   if inuse<>1
  306.     then writecon (k)
  307.     else begin
  308.       bottom;
  309.       writecon (k);
  310.       top
  311.     end;
  312.   if wherey>lasty then gotoxy (wherex,lasty);
  313.   if online and (not modemoutlock) and ((k<>#10) or uselinefeeds)
  314.     then sendchar(k);
  315.   if texttrap then begin
  316.     write (ttfile,k);
  317.     n:=ioresult;
  318.     if n<>0 then abortttfile (n)
  319.   end;
  320.   if printerecho then write (lst,k)
  321. end;
  322.  
  323. procedure handleincoming;
  324. var k:char;
  325. begin
  326.   k:=readchar;
  327.   case upcase(k) of
  328.     'X',^X,^K,^C,#27,' ':begin
  329.       writeln (direct);
  330.       break:=true;
  331.       linecount:=0;
  332.       xpressed:=(upcase(k)='X') or (k=^X);
  333.       if xpressed then clearchain
  334.     end;
  335.     ^S:k:=waitforchar;
  336.     else if length(chainstr)<255 then chainstr:=chainstr+k
  337.   end
  338. end;
  339.  
  340. procedure writechar (k:char);
  341.  
  342.   procedure endofline;
  343.  
  344.     procedure write13 (k:char);
  345.     var n:integer;
  346.     begin
  347.       for n:=1 to 13 do directoutchar (k)
  348.     end;
  349.  
  350.   var b:boolean;
  351.   begin
  352.     writeln (direct);
  353.     if timelock then settimeleft (lockedtime);
  354.     if curattrib=urec.statcolor then ansicolor (urec.regularcolor);
  355.     linecount:=linecount+1;
  356.     if (linecount>=urec.displaylen-1) and (not dontstop)
  357.           and (moreprompts in urec.config) then begin
  358.       linecount:=1;
  359.       write (direct,'More (Y/N/C)?');
  360.       repeat
  361.         k:=upcase(waitforchar)
  362.       until (k in [^M,' ','C','N','Y']) or hungupon;
  363.       write13 (^H);
  364.       write13 (' ');
  365.       write13 (^H);
  366.       if k='N' then break:=true else if k='C' then dontstop:=true
  367.     end
  368.   end;
  369.  
  370. begin
  371.   if hungupon then exit;
  372.   if k<=^Z then
  373.     case k of
  374.       ^J,#0:exit;
  375.       ^Q:k:=^H;
  376.       ^B:begin
  377.            clearbreak;
  378.            exit
  379.          end
  380.     end;
  381.   if break then exit;
  382.   if k<=^Z then begin
  383.     case k of
  384.       ^G:beepbeep;
  385.       ^L:cls;
  386.       ^N,^R:ansireset;
  387.       ^S:ansicolor (urec.statcolor);
  388.       ^P:ansicolor (urec.promptcolor);
  389.       ^U:ansicolor (urec.inputcolor);
  390.       ^H:directoutchar (k);
  391.       ^M:endofline
  392.     end;
  393.     exit
  394.   end;
  395.   if usecapsonly then k:=upcase(k);
  396.   directoutchar (k);
  397.   if (keyhit or ((not modemoutlock) and online and (numchars>0)))
  398.      and (not nobreak) then handleincoming
  399. end;
  400.  
  401. function getinputchar:char;
  402. var k:char;
  403. begin
  404.   if length(chainstr)=0 then begin
  405.     getinputchar:=waitforchar;
  406.     exit
  407.   end;
  408.   k:=chainstr[1];
  409.   delete (chainstr,1,1);
  410.   if (k=',') and (not nochain) then k:=#13;
  411.   getinputchar:=k
  412. end;
  413.  
  414. {$ifdef testingdevices}
  415.  
  416. procedure devicedone (var t:textrec; m:mstr);
  417. var r:registers;
  418.     cnt:integer;
  419. begin
  420.   write (usr,'Device ');
  421.   cnt:=0;
  422.   while t.name[cnt]<>#0 do begin
  423.     write (usr,t.name[cnt]);
  424.     cnt:=cnt+1
  425.   end;
  426.   writeln (usr,' ',m,'... press any key');
  427.   r.ax:=0;
  428.   intr ($16,r);
  429.   if r.al=3 then halt
  430. end;
  431.  
  432. {$endif}
  433.  
  434. {$F+}
  435.  
  436. function opendevice;
  437. begin
  438.   {$ifdef testingdevices}  devicedone (t,'opened');  {$endif}
  439.   t.handle:=1;
  440.   t.mode:=fminout;
  441.   t.bufend:=0;
  442.   t.bufpos:=0;
  443.   opendevice:=0
  444. end;
  445.  
  446. function closedevice;
  447. begin
  448.   {$ifdef testingdevices}  devicedone (t,'closed');  {$endif}
  449.   t.handle:=0;
  450.   t.mode:=fmclosed;
  451.   t.bufend:=0;
  452.   t.bufpos:=0;
  453.   closedevice:=0
  454. end;
  455.  
  456. function cleardevice;
  457. begin
  458.   {$ifdef testingdevices}  devicedone (t,'cleared');  {$endif}
  459.   t.bufend:=0;
  460.   t.bufpos:=0;
  461.   cleardevice:=0
  462. end;
  463.  
  464. function ignorecommand;
  465. begin
  466.   {$ifdef testingdevices}  devicedone (t,'ignored');  {$endif}
  467.   ignorecommand:=0
  468. end;
  469.  
  470. function directoutchars;
  471. var cnt:integer;
  472. begin
  473.   for cnt:=t.bufend to t.bufpos-1 do
  474.     directoutchar (t.bufptr^[cnt]);
  475.   t.bufend:=0;
  476.   t.bufpos:=0;
  477.   directoutchars:=0
  478. end;
  479.  
  480. function writechars;
  481. var cnt:integer;
  482. begin
  483.   for cnt:=t.bufend to t.bufpos-1 do
  484.     writechar (t.bufptr^[cnt]);
  485.   t.bufend:=0;
  486.   t.bufpos:=0;
  487.   writechars:=0
  488. end;
  489.  
  490. function directinchars;
  491. begin
  492.   with t do begin
  493.     bufptr^[0]:=waitforchar;
  494.     t.bufpos:=0;
  495.     t.bufend:=1
  496.   end;
  497.   directinchars:=0
  498. end;
  499.  
  500. function readcharfunc;
  501. begin
  502.   with t do begin
  503.     bufptr^[0]:=getinputchar;
  504.     t.bufpos:=0;
  505.     t.bufend:=1
  506.   end;
  507.   readcharfunc:=0
  508. end;
  509.  
  510. {$F-}
  511.  
  512. procedure getstr;
  513. var marker,cnt:integer;
  514.     p:byte absolute input;
  515.     k:char;
  516.     oldinput:anystr;
  517.     done,wrapped:boolean;
  518.     wordtowrap:lstr;
  519.  
  520.   procedure bkspace;
  521.  
  522.     procedure bkwrite (q:sstr);
  523.     begin
  524.       write (q);
  525.       if splitmode and dots then write (usr,q)
  526.     end;
  527.  
  528.   begin
  529.     if p<>0
  530.       then
  531.         begin
  532.           if input[p]=^Q
  533.             then bkwrite (' ')
  534.             else bkwrite (k+' '+k);
  535.           p:=p-1
  536.         end
  537.       else if wordwrap
  538.         then
  539.           begin
  540.             input:=k;
  541.             done:=true
  542.           end
  543.   end;
  544.  
  545.   procedure sendit (k:char; n:integer);
  546.   var temp:anystr;
  547.   begin
  548.     temp[0]:=chr(n);
  549.     fillchar (temp[1],n,k);
  550.     nobreak:=true;
  551.     write (temp)
  552.   end;
  553.  
  554.   procedure superbackspace (r1:integer);
  555.   var cnt,n:integer;
  556.   begin
  557.     n:=0;
  558.     for cnt:=r1 to p do
  559.       if input[cnt]=^Q
  560.         then n:=n-1
  561.         else n:=n+1;
  562.     if n<0 then sendit (' ',-n) else begin
  563.       sendit (^H,n);
  564.       sendit (' ',n);
  565.       sendit (^H,n)
  566.     end;
  567.     p:=r1-1
  568.   end;
  569.  
  570.   procedure cancelent;
  571.   begin
  572.     superbackspace (1)
  573.   end;
  574.  
  575.   function findspace:integer;
  576.   var s:integer;
  577.   begin
  578.     s:=p;
  579.     while (input[s]<>' ') and (s>0) do s:=s-1;
  580.     findspace:=s
  581.   end;
  582.  
  583.   procedure wrapaword (q:char);
  584.   var s:integer;
  585.   begin
  586.     done:=true;
  587.     if q=' ' then exit;
  588.     s:=findspace;
  589.     if s=0 then exit;
  590.     wrapped:=true;
  591.     wordtowrap:=copy(input,s+1,255)+q;
  592.     superbackspace (s)
  593.   end;
  594.  
  595.   procedure deleteword;
  596.   var s,n:integer;
  597.   begin
  598.     if p=0 then exit;
  599.     s:=findspace;
  600.     if s<>0 then s:=s-1;
  601.     n:=p-s;
  602.     p:=s;
  603.     sendit (^H,n);
  604.     sendit (' ',n);
  605.     sendit (^H,n)
  606.   end;
  607.  
  608.   procedure addchar (k:char);
  609.   begin
  610.     if p<buflen
  611.       then if (k<>' ') or (p>0) or wordwrap or beginwithspacesok
  612.         then
  613.           begin
  614.             p:=p+1;
  615.             input[p]:=k;
  616.             if dots
  617.               then
  618.                 begin
  619.                   writechar (dotchar);
  620.                   if splitmode then write (usr,k)
  621.                 end
  622.               else writechar (k)
  623.           end
  624.         else
  625.       else if wordwrap then wrapaword (k)
  626.   end;
  627.  
  628.   procedure repeatent;
  629.   var cnt:integer;
  630.   begin
  631.     for cnt:=1 to length(oldinput) do addchar (oldinput[cnt])
  632.   end;
  633.  
  634.   procedure tab;
  635.   var n,c:integer;
  636.   begin
  637.     n:=(p+8) and 248;
  638.     if n>buflen then n:=buflen;
  639.     for c:=1 to n-p do addchar (' ')
  640.   end;
  641.  
  642.   procedure getinput;
  643.   begin
  644.     oldinput:=input;
  645.     ingetstr:=true;
  646.     done:=false;
  647.     bottomline;
  648.     if splitmode and dots then top;
  649.     p:=0;
  650.     repeat
  651.       clearbreak;
  652.       nobreak:=true;
  653.       k:=getinputchar;
  654.       if hungupon then begin
  655.         input:='';
  656.         k:=#13;
  657.         done:=true
  658.       end;
  659.       case k of
  660.         ^I:tab;
  661.         ^H:bkspace;
  662.         ^M:done:=true;
  663.         ^R:repeatent;
  664.         ^X,#27:cancelent;
  665.         ^W:deleteword;
  666.         ' '..'~':addchar (k);
  667.         ^Q:if wordwrap and bkspinmsgs then addchar (k)
  668.       end;
  669.       if requestchat then begin
  670.         p:=0;
  671.         writeln (^B^N^M^M^B);
  672.         chat (requestcom);
  673.         write (^B^M^M^P,lastprompt);
  674.         requestchat:=false
  675.       end
  676.     until done;
  677.     writeln;
  678.     if splitmode and dots then begin
  679.       writeln (usr);
  680.       bottom
  681.     end;
  682.     ingetstr:=false;
  683.     ansireset
  684.   end;
  685.  
  686.   procedure divideinput;
  687.   var p:integer;
  688.   begin
  689.     p:=pos(',',input);
  690.     if p=0 then exit;
  691.     addtochain (copy(input,p+1,255)+#13);
  692.     input[0]:=chr(p-1)
  693.   end;
  694.  
  695. begin
  696.   che;
  697.   clearbreak;
  698.   linecount:=1;
  699.   wrapped:=false;
  700.   nochain:=nochain or wordwrap;
  701.   ansicolor (urec.inputcolor);
  702.   getinput;
  703.   if not nochain then divideinput;
  704.   while input[length(input)]=' ' do input[0]:=pred(input[0]);
  705.   if not wordwrap then
  706.     while (length(input)>0) and (input[1]=' ') do delete (input,1,1);
  707.   if wrapped then chainstr:=wordtowrap;
  708.   wordwrap:=false;
  709.   nochain:=false;
  710.   beginwithspacesok:=false;
  711.   dots:=false;
  712.   buflen:=80;
  713.   linecount:=1
  714. end;
  715.  
  716. procedure writestr (s:anystr);
  717. var k:char;
  718.     ex:boolean;
  719. begin
  720.   che;
  721.   clearbreak;
  722.   ansireset;
  723.   uselinefeeds:=linefeeds in urec.config;
  724.   usecapsonly:=not (lowercase in urec.config);
  725.   k:=s[length(s)];
  726.   s:=copy(s,1,length(s)-1);
  727.   case k of
  728.     ':':begin
  729.           write (^P,s,': ');
  730.           lastprompt:=s+': ';
  731.           getstr
  732.         end;
  733.     ';':write (s);
  734.     '*':begin
  735.           write (^P,s);
  736.           lastprompt:=s;
  737.           getstr
  738.         end;
  739.     '&':begin
  740.           nochain:=true;
  741.           write (^P,s);
  742.           lastprompt:=s;
  743.           getstr
  744.         end
  745.     else writeln (s,k)
  746.   end;
  747.   clearbreak
  748. end;
  749.  
  750. procedure cls;
  751. begin
  752.   bottom;
  753.   clrscr;
  754.   bottomline
  755. end;
  756.  
  757. procedure writehdr (q:anystr);
  758. var cnt:integer;
  759. begin
  760.   writeln (^B^M);
  761.   for cnt:=1 to (40-length(q)) div 2 do write (' ');
  762.   write (q,^M^M^B)
  763. end;
  764.  
  765. function issysop:boolean;
  766. begin
  767.   issysop:=(ulvl>=sysoplevel) or (cursection in urec.config)
  768. end;
  769.  
  770. procedure reqlevel (l:integer);
  771. begin
  772.   writeln (^B'Nice try, but level ',l,' is required.')
  773. end;
  774.  
  775. procedure printfile (fn:lstr);
  776.  
  777.   procedure getextension (var fname:lstr);
  778.  
  779.     procedure tryfiles (a,b,c,d:integer);
  780.     var q:boolean;
  781.  
  782.       function tryfile (n:integer):boolean;
  783.       const exts:array [1..4] of string[3]=('','ANS','ASC','40');
  784.       begin
  785.         if not exist (fname+'.'+exts[n]) then tryfile:=false else begin
  786.           tryfile:=true;
  787.           fname:=fname+'.'+exts[n]
  788.         end
  789.       end;
  790.  
  791.     begin
  792.       if tryfile (a) then exit;
  793.       if tryfile (b) then exit;
  794.       if tryfile (c) then exit;
  795.       q:=tryfile (d)
  796.     end;
  797.  
  798.   begin
  799.     if pos ('.',fname)<>0 then exit;
  800.     if ansigraphics in urec.config  then tryfiles (2,3,1,4) else
  801.     if asciigraphics in urec.config then tryfiles (3,1,4,2) else
  802.     if eightycols in urec.config    then tryfiles (1,4,3,2) else
  803.                                          tryfiles (4,1,3,2)
  804.   end;
  805.  
  806. var tf:text;
  807.     k:char;
  808. begin
  809.   clearbreak;
  810.   writeln;
  811.   getextension (fn);
  812.   assign (tf,fn);
  813.   reset (tf);
  814.   iocode:=ioresult;
  815.   if iocode<>0 then begin
  816.     fileerror ('Printfile',fn);
  817.     exit
  818.   end;
  819.   clearbreak;
  820.   while not (eof(tf) or break or hungupon) do
  821.     begin
  822.       read (tf,k);
  823.       write (k)
  824.     end;
  825.   if break then writeln (^B);
  826.   writeln;
  827.   textclose (tf);
  828.   curattrib:=0;
  829.   ansireset
  830. end;
  831.  
  832. procedure printtexttopoint (var tf:text);
  833. var l:lstr;
  834. begin
  835.   l:='';
  836.   clearbreak;
  837.   while not (eof(tf) or hungupon) and (l<>'.') do begin
  838.     if not break then writeln (l);
  839.     readln (tf,l)
  840.   end
  841. end;
  842.  
  843. procedure skiptopoint (var tf:text);
  844. var l:lstr;
  845. begin
  846.   l:='';
  847.   while not eof(tf) and (l<>'.') do
  848.     readln (tf,l)
  849. end;
  850.  
  851. function minstr (blocks:integer):sstr;
  852. var min,sec:integer;
  853.     rsec:real;
  854.     ss:sstr;
  855. begin
  856.   rsec:=1.38 * blocks * (1200/baudrate);
  857.   min:=trunc (rsec/60.0);
  858.   sec:=trunc (rsec-(min*60.0));
  859.   ss:=strr(sec);
  860.   if length(ss)<2 then ss:='0'+ss;
  861.   minstr:=strr(min)+':'+ss
  862. end;
  863.  
  864. procedure parserange (numents:integer; var f,l:integer);
  865. var rf,rl:mstr;
  866.     p,v1,v2:integer;
  867. begin
  868.   f:=0;
  869.   l:=0;
  870.   if numents<1 then exit;
  871.   repeat
  872.     writestr ('Range [1-'+strr(numents)+', CR=all, ?=help]:');
  873.     if input='?' then printfile (textfiledir+'Rangehlp');
  874.     if (length(input)>0) and (upcase(input[1])='Q') then exit
  875.   until (input<>'?') or hungupon;
  876.   if hungupon then exit;
  877.   if length(input)=0 then begin
  878.     f:=1;
  879.     l:=numents
  880.   end else begin
  881.     p:=pos('-',input);
  882.     v1:=valu(copy(input,1,p-1));
  883.     v2:=valu(copy(input,p+1,255));
  884.     if p=0 then begin
  885.       f:=v2;
  886.       l:=v2
  887.     end else if p=1 then begin
  888.       f:=1;
  889.       l:=v2
  890.     end else if p=length(input) then begin
  891.       f:=v1;
  892.       l:=numents
  893.     end else begin
  894.       f:=v1;
  895.       l:=v2
  896.     end
  897.   end;
  898.   if (f<1) or (l>numents) or (f>l) then begin
  899.     f:=0;
  900.     l:=0;
  901.     writestr ('Invalid range!')
  902.   end;
  903.   writeln (^B)
  904. end;
  905.  
  906. function menu (mname:mstr; mfn:sstr; choices:anystr):integer;
  907. var k:char;
  908.     sysmenu,percent,needsys:boolean;
  909.     n,p,i:integer;
  910.     prompt:lstr;
  911. begin
  912.   sysmenu:=false;
  913.   percent:=false;
  914.   for p:=1 to length(choices)-1 do
  915.     if choices[p]='%'
  916.       then if choices[p+1]='@'
  917.         then percent:=true
  918.         else
  919.       else if choices[p+1]='@'
  920.         then sysmenu:=true;
  921.   writeln (^B);
  922.   repeat
  923.     if chatmode
  924.       then for n:=1 to 3 do summonbeep;
  925.     if (timeleft<1) or (timetillevent<=3) then begin
  926.       printfile (textfiledir+'Timesup');
  927.       forcehangup:=true;
  928.       menu:=0;
  929.       exit
  930.     end;
  931.     if showtime in urec.config
  932.       then prompt:='('+strr(timeleft)+' left) '
  933.       else prompt:='';
  934.     prompt:=prompt+mname+' menu [?=help';
  935.     if percent and issysop then prompt:=prompt+', %=sysop';
  936.     prompt:=prompt+']:';
  937.     writestr (prompt);
  938.     n:=0;
  939.     if length(input)=0
  940.       then k:='_'
  941.       else
  942.         begin
  943.           if match(input,'/OFF') then begin
  944.             forcehangup:=true;
  945.             menu:=0;
  946.             exit
  947.           end;
  948.           n:=valu(input);
  949.           if n>0
  950.             then k:='#'
  951.             else k:=upcase(input[1])
  952.         end;
  953.     p:=1;
  954.     i:=1;
  955.     if k='?'
  956.       then
  957.         begin
  958.           printfile (textfiledir+mfn+'M');
  959.           if sysmenu and issysop then printfile (textfiledir+mfn+'S')
  960.         end
  961.       else
  962.         while p<=length(choices) do begin
  963.           needsys:=false;
  964.           if p<length(choices)
  965.             then if choices[p+1]='@'
  966.               then needsys:=true;
  967.           if upcase(choices[p])=k
  968.             then if needsys and (not issysop)
  969.               then
  970.                 begin
  971.                   reqlevel (sysoplevel);
  972.                   p:=255;
  973.                   needsys:=false
  974.                 end
  975.               else p:=256
  976.             else
  977.               begin
  978.                 p:=p+1;
  979.                 if needsys then p:=p+1;
  980.                 i:=i+1
  981.               end
  982.         end
  983.   until (p=256) or hungupon;
  984.   writeln (^B^M);
  985.   if hungupon
  986.     then menu:=0
  987.     else
  988.       if k='#' then menu:=-n else menu:=i
  989. end;
  990.  
  991. function getpassword:boolean;
  992. var t:sstr;
  993. begin
  994.   getpassword:=false;
  995.   dots:=true;
  996.   buflen:=15;
  997.   getstr;
  998.   if input=''
  999.     then exit
  1000.     else begin
  1001.       t:=input;
  1002.       dots:=true;
  1003.       writestr ('Re-enter for verification:');
  1004.       if not match(t,input) then begin
  1005.         writeln ('They don''t match!');
  1006.         getpassword:=hungupon;
  1007.         exit
  1008.       end;
  1009.       urec.password:=t;
  1010.       getpassword:=true
  1011.     end
  1012. end;
  1013.  
  1014. function checkpassword (var u:userrec):boolean;
  1015. var tries:integer;
  1016. begin
  1017.   tries:=0;
  1018.   checkpassword:=true;
  1019.   repeat
  1020.     splitscreen (5);
  1021.     top;
  1022.     writeln (usr,'Password Entry');
  1023.     writeln (usr,'User name: ',u.handle);
  1024.     writeln (usr,'Password: ',u.password);
  1025.     write (usr,'Has entered so far: ');
  1026.     bottom;
  1027.     dots:=true;
  1028.     writestr (^M'Password please:');
  1029.     unsplit;
  1030.     if hungupon then begin
  1031.       checkpassword:=false;
  1032.       exit
  1033.     end;
  1034.     if match(input,u.password)
  1035.       then exit
  1036.       else tries:=tries+1
  1037.   until tries>3;
  1038.   checkpassword:=false
  1039. end;
  1040.  
  1041. procedure getacflag (var ac:accesstype; var tex:mstr);
  1042. begin
  1043.   writestr ('[K]ick off, [B]y level, [L]et in:');
  1044.   ac:=invalid;
  1045.   if length(input)=0 then exit;
  1046.   case upcase(input[1]) of
  1047.     'B':ac:=bylevel;
  1048.     'L':ac:=letin;
  1049.     'K':ac:=keepout
  1050.   end;
  1051.   tex:=accessstr[ac]
  1052. end;
  1053.  
  1054. begin
  1055. end.
  1056.  
  1057.  
  1058.