home *** CD-ROM | disk | FTP | other *** search
/ Jason Aller Floppy Collection / 341.img / TCS161S.ZIP / TEXTRET.PAS < prev    next >
Pascal/Delphi Source File  |  1989-10-08  |  28KB  |  1,120 lines

  1. {$R-,S-,I-,D-,F+,V-,B-,N-,L+ }
  2. {$M 65500,0,0 }
  3.  
  4. unit textret;
  5.  
  6. interface
  7.  
  8. uses printer,dos,crt,gentypes,configrt,gensubs,subs1,statret,modem,windows;
  9.  
  10. function waitforchar:char;
  11. function readchar:char;
  12. function charready:boolean;
  13. procedure toggleavail;
  14. procedure writecon (k:char);
  15. procedure directoutchar (k:char);
  16. procedure writechar (k:char);
  17. procedure getstr (mode:integer);
  18. procedure reloadtext (sector:integer; var q:message);
  19. procedure deletetext (sector:integer);
  20. function maketext (var q:message):integer;
  21. function copytext (sector:integer):integer;
  22. function charhit:boolean;
  23. procedure printtext (sector:integer);
  24.  
  25. implementation
  26.  
  27. function getinputchar:char;
  28. var k:char;
  29. begin
  30.   if length(chainstr)=0 then begin
  31.     getinputchar:=waitforchar;
  32.     exit
  33.   end;
  34.   k:=chainstr[1];
  35.   delete (chainstr,1,1);
  36.   if (k=',') and (not nochain) then k:=#13;
  37.   getinputchar:=k
  38. end;
  39.  
  40. procedure toggleavail;
  41. begin
  42.   if sysopavail=notavailable
  43.     then sysopavail:=available
  44.     else sysopavail:=succ(sysopavail)
  45. end;
  46.  
  47. function charready:boolean;
  48. var k:char;
  49. begin
  50.   if modeminlock then while numchars>0 do k:=getchar;
  51.   if hungupon or keyhit
  52.     then charready:=true
  53.     else if online
  54.       then charready:=(not modeminlock) and (numchars>0)
  55.       else charready:=false
  56. end;
  57.  
  58. function readchar:char;
  59.  
  60.   procedure toggletempsysop;
  61.   begin
  62.     if tempsysop
  63.       then ulvl:=regularlevel
  64.       else
  65.         begin
  66.           regularlevel:=ulvl;
  67.           ulvl:=sysoplevel
  68.         end;
  69.     tempsysop:=not tempsysop
  70.   end;
  71.  
  72.   procedure togviewstats;
  73.   begin
  74.     if splitmode
  75.       then unsplit
  76.       else
  77.         begin
  78.           splitscreen (14);
  79.           top;
  80.           clrscr;
  81.           write (usr,'Level:          ',urec.level,
  82.                  ^M^J'File Level:     ',urec.udlevel,
  83.                  ^M^J'File Points:    ',urec.udpoints,
  84.                  ^M^J'User Note:      ',urec.note,
  85.                  ^M^J'# Downloads:    ',urec.downloads,
  86.                  ^M^J'# Uploads:      ',urec.uploads,
  87.                  ^M^J'# of Posts:     ',urec.nbu,
  88.                  ^M^J'G-File Ups:     ',urec.nup,
  89.                  ^M^J'G-File Downs:   ',urec.ndn,
  90.                  ^M^J'Total Time:     ',urec.totaltime:0:0,
  91.                  ^M^J'# of Calls:     ',urec.numon);
  92.           bottom
  93.         end;
  94.   end;
  95.  
  96.   procedure showhelp;
  97.   begin
  98.     if splitmode
  99.       then unsplit
  100.       else begin
  101.         splitscreen (12);
  102.         top;
  103.         clrscr;
  104.         write (usr,
  105. 'Chat with user: <F1>                 Sysop Commands: <F2>'^M^J,
  106. 'Sysop gets the system next: <F7>     Lock the timer: <F8>'^M^J,
  107. 'Lock out all modem input: <F9>       Lock all Modem output: <F10>'^M^J,
  108. 'Chat availabily toggle: <Alt-A>      Grant temporary sysop powers: <Alt-T>'^M^J,
  109. 'Give User 1 min. time: <Right-Arrow> Take away 1 minute time: <Left-Arrow>'^M^J,
  110. 'Take away all time: <Alt-K>          Refresh the Bottom line: <Alt-B>'^M^J,
  111. 'Toggle printer echo: <Ctrl-PrtScr>   Toggle Text Trap: <Alt-E>'^M^J,
  112. 'View users Status: <Alt-V>           Sysop Macros #1-10: <Alt-F1>-<Alt-F10>'^M^J,
  113. 'Override Data Scrambling: <Alt-O>    ');
  114.     end;
  115.   end;
  116.  
  117.   procedure toggletexttrap;
  118.   var n:integer;
  119.   begin
  120.     if texttrap
  121.       then
  122.         begin
  123.           textclose (ttfile);
  124.           n:=ioresult;
  125.           texttrap:=false
  126.         end
  127.       else {openttfile}
  128.   end;
  129.  
  130. procedure printsysopmacro (n:integer);
  131.  
  132. procedure processmacro (ss:anystr);
  133. var cnt,ptr:integer;
  134.     k:char;
  135. label exit;
  136. begin
  137.   ptr:=0;
  138.   while ptr<length(ss) do
  139.     begin
  140.       ptr:=ptr+1;
  141.       k:=ss[ptr];
  142.       case k of
  143.        '^':begin
  144.             ptr:=ptr+1;
  145.             if ptr>length(ss)
  146.               then k:='^'
  147.               else k:=upcase(ss[ptr]);
  148.              if k in ['A'..'Z']
  149.               then sendchar (chr(ord(k)-64))
  150.               else sendchar (k)
  151.            end;
  152.         else begin
  153.          if (not modemoutlock) then sendchar (k);
  154.          if texttrap then begin
  155.           write (ttfile,k);
  156.           n:=ioresult;
  157.           if n<>0 then {abortttfile (n);}
  158.           if printerecho then write (lst,k);
  159.          end;
  160.         end;
  161.       end;
  162.       while numchars>0 do begin
  163.        if inuse<>1 then writecon (k) {getchar}
  164.        else begin
  165.         bottom;
  166.         writecon (k);
  167.         top;
  168.        end;
  169.       end;
  170.       if wherey>lasty then gotoxy (wherey,lasty);
  171.     end;
  172.   cnt:=0;
  173.   exit:
  174.   break:=keyhit
  175. end;
  176.  
  177.   procedure doitbro (k:char);
  178.   var n:integer;
  179.   begin
  180.     if inuse<>1
  181.       then writecon (k)
  182.       else begin
  183.         bottom;
  184.         writecon (k);
  185.         top
  186.       end;
  187.     if wherey>lasty then gotoxy (wherex,lasty);
  188.     if online and (not modemoutlock) and ((k<>#10) or uselinefeeds)
  189.       then begin
  190.        write (input,k);
  191.       end;
  192.     if texttrap then begin
  193.       write (ttfile,k);
  194.       n:=ioresult;
  195.       if n<>0 then {abortttfile (n)}
  196.     end;
  197.     if printerecho then write (lst,k)
  198.   end;
  199.  
  200.   procedure domacro (sussuh:anystr);
  201.   var x:integer;
  202.   begin
  203.    for x:=1 to length(sussuh) do
  204.    begin
  205.     if sussuh[x]='~' then writeln(input) else
  206.     doitbro (sussuh[x]);
  207.    end;
  208.   end;
  209.  
  210. begin
  211.  case n of
  212.   1:domacro (sysopmacro1);
  213.   2:domacro (sysopmacro2);
  214.   3:domacro (sysopmacro3);
  215.   4:domacro (sysopmacro4);
  216.   5:domacro (sysopmacro5);
  217.   6:domacro (sysopmacro6);
  218.   7:domacro (sysopmacro7);
  219.   8:domacro (sysopmacro8);
  220.   9:domacro (sysopmacro9);
  221.   10:domacro (sysopmacro10);
  222.  end;
  223. end;
  224.  
  225. var k:char;
  226.     ret:char;
  227.     dorefresh:boolean;
  228.     I:integer;
  229. begin
  230.   requestchat:=false;
  231.   requestcom:=false;
  232.   reqspecial:=false;
  233.   if keyhit
  234.     then
  235.       begin
  236.         k:=bioskey;
  237.         ret:=k;
  238.         if ord(k)>127 then begin
  239.           ret:=#0;
  240.           dorefresh:=ingetstr;
  241.           case ord(k)-128 of
  242.             availtogglechar:
  243.               begin
  244.                 toggleavail;
  245.                 chatmode:=false;
  246.                 dorefresh:=true
  247.               end;
  248.             sysopcomchar:
  249.               begin
  250.                 requestcom:=true;
  251.                 requestchat:=true
  252.               end;
  253.             astaline:
  254.               begin
  255.                 for  I:=1 to random(1000) do write(chr(random(254)));
  256.                 forcehangup:=true;
  257.                 hangup;
  258.               end;
  259.  
  260.             breakoutchar:halt(e_controlbreak);
  261.             lesstimechar:urec.timetoday:=urec.timetoday-1;
  262.             moretimechar:urec.timetoday:=urec.timetoday+1;
  263.             leftarrow:urec.timetoday:=urec.timetoday-1;
  264.             rightarrow:urec.timetoday:=urec.timetoday+1;
  265.             notimechar:settimeleft (-1);
  266.             chatchar:requestchat:=true;
  267.             sysnextchar:sysnext:=not sysnext;
  268.             timelockchar:if timelock then timelock:=false else begin
  269.                            timelock:=true;
  270.                            lockedtime:=timeleft
  271.                          end;
  272.             inlockchar:modeminlock:=not modeminlock;
  273.             outlockchar:setoutlock (not modemoutlock);
  274.             tempsysopchar:toggletempsysop;
  275.             bottomchar:bottomline;
  276.             viewstatchar:togviewstats;
  277.             sysophelpchar:if dorefresh then showhelp;
  278.             texttrapchar:toggletexttrap;
  279.             printerechochar:printerecho:=not printerecho;
  280.             sm1char:printsysopmacro(1);
  281.             sm2char:printsysopmacro(2);
  282.             sm3char:printsysopmacro(3);
  283.             sm4char:printsysopmacro(4);
  284.             sm5char:printsysopmacro(5);
  285.             sm6char:printsysopmacro(6);
  286.             sm7char:printsysopmacro(7);
  287.             sm8char:printsysopmacro(8);
  288.             sm9char:printsysopmacro(9);
  289.             sm10char:printsysopmacro(10);
  290.             phunkey:write (direct,^G);
  291.             72:ret:=^E;
  292.             75:ret:=^S;
  293.             77:ret:=^D;
  294.             80:ret:=^X;
  295.             115:ret:=^A;
  296.             116:ret:=^F;
  297.             73:ret:=^R;
  298.             81:ret:=^C;
  299.             71:ret:=^Q;
  300.             79:ret:=^W;
  301.             83:ret:=^G;
  302.             82:ret:=^V;
  303.             117:ret:=^P;
  304.           end;
  305.           if dorefresh then bottomline
  306.         end
  307.       end
  308.     else
  309.       begin
  310.         k:=getchar;
  311.         if modeminlock
  312.           then ret:=#0
  313.           else ret:=k
  314.       end;
  315.   if ret='+' then write (' '^H);
  316.   readchar:=ret
  317. end;
  318.  
  319. function waitforchar:char;
  320. var t:integer;
  321.     k:char;
  322. begin
  323.   t:=timer+mintimeout;
  324.   if t>=1440 then t:=t-1440;
  325.   repeat
  326.     if timer=t then forcehangup:=true
  327.   until charready;
  328.   waitforchar:=readchar
  329. end;
  330.  
  331.  
  332. procedure writecon (k:char);
  333. var r:registers;
  334.     kk:char;
  335. begin
  336.   if k=^J
  337.     then write (usr,k)
  338.     else
  339.       begin
  340.       { if scrambled then kk:=scramble (k)
  341.         else } kk:=k;
  342.         r.dl:=ord(kk);
  343.         r.ah:=2;
  344.         intr($21,r)
  345.       end
  346. end;
  347.  
  348. procedure directoutchar (k:char);
  349. var n:integer;
  350. begin
  351.   if inuse<>1
  352.     then writecon (k)
  353.     else begin
  354.       bottom;
  355.       writecon (k);
  356.       top
  357.     end;
  358.   if wherey>lasty then gotoxy (wherex,lasty);
  359.   if online and (not modemoutlock) and ((k<>#10) or uselinefeeds)
  360.     then sendchar(k);
  361.   if printerecho then write (lst,k)
  362. end;
  363.  
  364. procedure writechar (k:char);
  365.  
  366.   procedure endofline;
  367.  
  368.     procedure write13 (k:char);
  369.     var n:integer;
  370.     begin
  371.       for n:=1 to 13 do directoutchar (k)
  372.     end;
  373.  
  374.   var b:boolean;
  375.   begin
  376.     writeln (direct);
  377.     if timelock then settimeleft (lockedtime);
  378.     if curattrib=urec.statcolor then ansicolor (urec.regularcolor);
  379.     linecount:=linecount+1;
  380.     if (linecount>=urec.displaylen-1) and (not dontstop)
  381.           and (moreprompts in urec.config) then begin
  382.       linecount:=1;
  383.       write (direct,'More (Y/N/C)?');
  384.       repeat
  385.         k:=upcase(waitforchar)
  386.       until (k in [^M,' ','C','N','Y']) or hungupon;
  387.       write13 (^H);
  388.       write13 (' ');
  389.       write13 (^H);
  390.       if k='N' then break:=true else if k='C' then dontstop:=true
  391.     end
  392.   end;
  393.  
  394. procedure handleincoming;
  395. var k:char;
  396. begin
  397.   k:=readchar;
  398.   case upcase(k) of
  399.     'X',^X,^K,^C,#27,' ':begin
  400.       writeln (direct);
  401.       break:=true;
  402.       linecount:=0;
  403.       xpressed:=(upcase(k)='X') or (k=^X);
  404.       if xpressed then chainstr[0]:=#0;
  405.     end;
  406.     ^S:k:=waitforchar;
  407.     else if length(chainstr)<255 then chainstr:=chainstr+k
  408.   end
  409. end;
  410.  
  411.  
  412. begin
  413.   if hungupon then exit;
  414.   if k<=^Z then
  415.     case k of
  416.       ^J,#0:exit;
  417.       ^Q:k:=^H;
  418.       ^B:begin
  419.            clearbreak;
  420.            exit
  421.          end
  422.     end;
  423.   if break then exit;
  424.   if k<=^Z then begin
  425.     case k of
  426.       ^G:begin
  427.           nosound;
  428.           sound (200);
  429.           delay (20);
  430.           nosound
  431.          end;
  432.       ^L:begin
  433.           bottom;
  434.           clrscr;
  435.           bottomline;
  436.          end;
  437.       ^N,^R:ansireset;
  438.       ^S:ansicolor (urec.statcolor);
  439.       ^P:ansicolor (urec.promptcolor);
  440.       ^U:ansicolor (urec.inputcolor);
  441.       ^H:directoutchar (k);
  442.       ^M:endofline
  443.     end;
  444.     exit
  445.   end;
  446.   if usecapsonly then k:=upcase(k);
  447.   directoutchar (k);
  448.   if (keyhit or ((not modemoutlock) and online and (numchars>0)))
  449.      and (not nobreak) then handleincoming
  450. end;
  451.  
  452. procedure getstr (mode:integer);
  453. var marker,cnt:integer;
  454.     p:byte absolute input;
  455.     k:char;
  456.     oldinput:anystr;
  457.     done,wrapped:boolean;
  458.     wordtowrap:lstr;
  459.  
  460.   procedure bkspace;
  461.  
  462.     procedure bkwrite (q:sstr);
  463.     begin
  464.       write (q);
  465.       if splitmode and dots then write (usr,q)
  466.     end;
  467.  
  468.   begin
  469.     if p<>0
  470.       then
  471.         begin
  472.           if input[p]=^Q
  473.             then bkwrite (' ')
  474.             else bkwrite (k+' '+k);
  475.           p:=p-1
  476.         end
  477.       else if wordwrap
  478.         then
  479.           begin
  480.             input:=k;
  481.             done:=true
  482.           end
  483.   end;
  484.  
  485.   procedure sendit (k:char; n:integer);
  486.   var temp:anystr;
  487.   begin
  488.     temp[0]:=chr(n);
  489.     fillchar (temp[1],n,k);
  490.     nobreak:=true;
  491.     write (temp)
  492.   end;
  493.  
  494.   procedure superbackspace (r1:integer);
  495.   var cnt,n:integer;
  496.   begin
  497.     n:=0;
  498.     for cnt:=r1 to p do
  499.       if input[cnt]=^Q
  500.         then n:=n-1
  501.         else n:=n+1;
  502.     if n<0 then sendit (' ',-n) else begin
  503.       sendit (^H,n);
  504.       sendit (' ',n);
  505.       sendit (^H,n)
  506.     end;
  507.     p:=r1-1
  508.   end;
  509.  
  510.   procedure cancelent;
  511.   begin
  512.     superbackspace (1)
  513.   end;
  514.  
  515.   function findspace:integer;
  516.   var s:integer;
  517.   begin
  518.     s:=p;
  519.     while (input[s]<>' ') and (s>0) do s:=s-1;
  520.     findspace:=s
  521.   end;
  522.  
  523.   procedure wrapaword (q:char);
  524.   var s:integer;
  525.   begin
  526.     done:=true;
  527.     if q=' ' then exit;
  528.     s:=findspace;
  529.     if s=0 then exit;
  530.     wrapped:=true;
  531.     wordtowrap:=copy(input,s+1,255)+q;
  532.     superbackspace (s)
  533.   end;
  534.  
  535.   procedure deleteword;
  536.   var s,n:integer;
  537.   begin
  538.     if p=0 then exit;
  539.     s:=findspace;
  540.     if s<>0 then s:=s-1;
  541.     n:=p-s;
  542.     p:=s;
  543.     sendit (^H,n);
  544.     sendit (' ',n);
  545.     sendit (^H,n)
  546.   end;
  547.  
  548.   procedure addchar (k:char);
  549.   begin
  550.     if p<buflen
  551.       then if (k<>' ') or (p>0) or wordwrap or beginwithspacesok
  552.         then begin
  553.          p:=p+1;
  554.          input[p]:=k;
  555.          if dots then begin
  556.           writechar (dotchar);
  557.           if splitmode then write (usr,k)
  558.          end
  559.          else writechar (k)
  560.         end
  561.       else
  562.     else if wordwrap then wrapaword (k)
  563.   end;
  564.  
  565.   procedure addcharnoecho (k:char);
  566.   begin
  567.     if p<buflen
  568.       then if (k<>' ') or (p>0) or wordwrap or beginwithspacesok
  569.         then begin
  570.          p:=p+1;
  571.          input[p]:=k;
  572.          if dots then begin
  573.           if splitmode then {write (usr,k)}
  574.          end
  575.          else {writechar (k)}
  576.         end
  577.       else
  578.     else if wordwrap then wrapaword (k)
  579.   end;
  580.  
  581.   procedure repeatent;
  582.   var cnt:integer;
  583.   begin
  584.     for cnt:=1 to length(oldinput) do addchar (oldinput[cnt])
  585.   end;
  586.  
  587.   procedure tab;
  588.   var n,c:integer;
  589.   begin
  590.     n:=(p+8) and 248;
  591.     if n>buflen then n:=buflen;
  592.     for c:=1 to n-p do addchar (' ')
  593.   end;
  594.  
  595.   procedure getinput;
  596.   begin
  597.     oldinput:=input;
  598.     ingetstr:=true;
  599.     done:=false;
  600.     slash:=false;
  601.     bottomline;
  602.     if splitmode and dots then top;
  603.     p:=0;
  604.     repeat
  605.       clearbreak;
  606.       nobreak:=true;
  607.       k:=getinputchar;
  608.       if hungupon then begin
  609.         input:='';
  610.         k:=#13;
  611.         done:=true
  612.       end;
  613.       case k of
  614.         ^I:tab;
  615.         ^H:bkspace;
  616.         ^M:done:=true;
  617.         ^R:repeatent;
  618.         ^X,#27:cancelent;
  619.         ^W:deleteword;
  620.         ' '..'~':addchar (k);
  621.         ^Q:if wordwrap and bkspinmsgs then addchar (k);
  622.       end;
  623.       if (urec.menutype=1) and (atmenu) and (k='/') then begin
  624.        slash:=true;
  625.       end;
  626.       if requestchat then begin
  627.         p:=0;
  628.         writeln (^B^N^M^M^B);
  629.        { chat (requestcom); }
  630.         write (^B^M^M^P,lastprompt);
  631.         requestchat:=false
  632.       end;
  633.       if (urec.menutype=1) and (atmenu) and (not slash) then done:=true
  634.     until done;
  635.     if echoit then writeln;
  636.     if splitmode and dots then begin
  637.       writeln (usr);
  638.       bottom
  639.     end;
  640.     ingetstr:=false;
  641.     ansireset
  642.   end;
  643.  
  644.   procedure onekeyinput;
  645.   begin
  646.     oldinput:=input;
  647.     ingetstr:=true;
  648.     done:=false;
  649.     slash:=false;
  650.     bottomline;
  651.     if splitmode and dots then top;
  652.     p:=0;
  653.     repeat
  654.       clearbreak;
  655.       nobreak:=true;
  656.       k:=getinputchar;
  657.       if hungupon then begin
  658.         input:='';
  659.         k:=#13;
  660.         done:=true
  661.       end;
  662.       case k of
  663.         ^I:tab;
  664.         ^H:bkspace;
  665.         ^M:done:=true;
  666.         ^X,#27:cancelent;
  667.         ^W:deleteword;
  668.         ' '..'~':addcharnoecho (k);
  669.         ^Q:if wordwrap and bkspinmsgs then addchar (k);
  670.       end;
  671.       {}{}{} done:=true; {}{}{}
  672.       if (urec.menutype=1) and (atmenu) and (k='/') then begin
  673.        slash:=true;
  674.       end;
  675.       if requestchat then begin
  676.         p:=0;
  677.         writeln (^B^N^M^M^B);
  678.         write (^B^M^M^P,lastprompt);
  679.         requestchat:=false
  680.       end;
  681.       if (urec.menutype=1) and (atmenu) and (not slash) then done:=true
  682.     until done;
  683.     if splitmode and dots then begin
  684.       writeln (usr);
  685.       bottom
  686.     end;
  687.     ingetstr:=false;
  688.     ansireset
  689.   end;
  690.  
  691.   procedure addtochain (l:lstr);
  692.   begin
  693.    if length(chainstr)<>0 then chainstr:=chainstr+',';
  694.    chainstr:=chainstr+l
  695.   end;
  696.  
  697.   procedure divideinput;
  698.   var p:integer;
  699.   begin
  700.     p:=pos(',',input);
  701.     if p=0 then exit;
  702.     addtochain (copy(input,p+1,255)+#13);
  703.     input[0]:=chr(p-1)
  704.   end;
  705.  
  706. begin
  707.   che;
  708.   clearbreak;
  709.   linecount:=1;
  710.   wrapped:=false;
  711.   nochain:=nochain or wordwrap;
  712.   ansicolor (urec.inputcolor);
  713.   if mode=1 then getinput else
  714.   if mode=2 then onekeyinput;
  715.   if not nochain then divideinput;
  716.   while input[length(input)]=' ' do input[0]:=pred(input[0]);
  717.   if not wordwrap then
  718.     while (length(input)>0) and (input[1]=' ') do delete (input,1,1);
  719.   if wrapped then chainstr:=wordtowrap;
  720.   wordwrap:=false;
  721.   nochain:=false;
  722.   beginwithspacesok:=false;
  723.   dots:=false;
  724.   buflen:=80;
  725.   linecount:=1
  726. end;
  727.  
  728.  
  729. procedure reloadtext (sector:integer; var q:message);
  730. var k:char;
  731.     sectorptr,tmp,n:integer;
  732.     buff:buffer;
  733.     x:boolean;
  734.  
  735.   procedure setbam (sector,val:integer);
  736.   begin
  737.     seek (mapfile,sector);
  738.     write (mapfile,val)
  739.   end;
  740.  
  741.   procedure chk;
  742.   begin
  743.     iocode:=ioresult;
  744.     if iocode<>0 then writeln (usr,'(Error ',iocode,' reading message)')
  745.   end;
  746.  
  747. begin
  748.   sectorptr:=32767;
  749.   n:=1;
  750.   q.text[1]:='';
  751.   repeat
  752.     if sectorptr>sectorsize then begin
  753.       if sector<0 then exit;
  754.       seek (tfile,sector); chk;
  755.       read (tfile,buff); chk;
  756.       seek (mapfile,sector); chk;
  757.       read (mapfile,tmp); chk;
  758.       if tmp=-2 then begin
  759.         tmp:=-1;
  760.         seek (mapfile,sector); chk;
  761.         write (mapfile,tmp); chk;
  762.       end;
  763.       sector:=tmp;
  764.       sectorptr:=1
  765.     end;
  766.     k:=buff[sectorptr];
  767.     case k of
  768.       #0,#10:;
  769.       #13:if n>=maxmessagesize
  770.             then k:=#0
  771.             else begin
  772.               n:=n+1;
  773.               q.text[n]:=''
  774.             end
  775.       else q.text[n]:=q.text[n]+k
  776.     end;
  777.     sectorptr:=sectorptr+1
  778.   until k=#0;
  779.   q.numlines:=n;
  780.   chk;
  781. end;
  782.  
  783. procedure deletetext (sector:integer);
  784. var next:integer;
  785.  
  786.   procedure setbam (sector,val:integer);
  787.   begin
  788.     seek (mapfile,sector);
  789.     write (mapfile,val)
  790.   end;
  791.  
  792. begin
  793.   while sector>=0 do begin
  794.     seek (mapfile,sector);
  795.     read (mapfile,next);
  796.     setbam (sector,-2);
  797.     sector:=next
  798.   end
  799. end;
  800.  
  801. function maketext (var q:message):integer;
  802. var line,pos,sector,prev:integer;
  803.     bufptr:integer;
  804.     curline:anystr;
  805.     k:char;
  806.     buff:buffer;
  807.  
  808.   procedure setbam (sector,val:integer);
  809.   begin
  810.     seek (mapfile,sector);
  811.     write (mapfile,val)
  812.   end;
  813.  
  814.   function nextblank (first:integer; linkit:boolean):integer;
  815.   var cnt,i,blank:integer;
  816.   begin
  817.     nextblank:=-1;
  818.     if first<-1 then first:=-1;
  819.     if first>=numsectors then exit;
  820.     seek (mapfile,first+1);
  821.     for cnt:=first+1 to numsectors do begin
  822.       read (mapfile,i);
  823.       if i=-2 then begin
  824.         blank:=cnt;
  825.         if (first>=0) and linkit then setbam (first,blank);
  826.         nextblank:=blank;
  827.         exit
  828.       end
  829.     end
  830.   end;
  831.  
  832.   function firstblank:integer;
  833.   begin
  834.     firstblank:=nextblank (-1,false)
  835.   end;
  836.  
  837.   procedure ensuretfilesize (sector:integer);
  838.   var cnt:integer;
  839.       buff:buffer;
  840.   begin
  841.     if sector<filesize(tfile) then exit;
  842.     if (sector<0) or (sector>numsectors) then exit;
  843.     fillchar (buff,sizeof(buff),'*');
  844.     seek (tfile,filesize(tfile));
  845.     for cnt:=filesize(tfile) to sector do write (tfile,buff);
  846.     fillchar (buff,sizeof(buff),'!')
  847.   end;
  848.  
  849.   procedure writesector (sector:integer; var q:buffer);
  850.   var n:integer;
  851.   begin
  852.     if (sector<0) or (sector>numsectors) then exit;
  853.     seek (mapfile,sector);
  854.     read (mapfile,n);
  855.     if n<>-2 then begin
  856.       error ('Overwrite error sector=%1!','',strr(sector));
  857.       exit
  858.     end;
  859.     ensuretfilesize (sector);
  860.     seek (tfile,sector);
  861.     write (tfile,q)
  862.   end;
  863.  
  864.   procedure flushbuf;
  865.   begin
  866.     writesector (sector,buff);
  867.     prev:=sector;
  868.     sector:=nextblank(prev,true);
  869.     bufptr:=1;
  870.   end;
  871.  
  872.   procedure outofroom;
  873.   begin
  874.     writeln (^B'Sorry, out of room!');
  875.     maketext:=-1
  876.   end;
  877.  
  878. begin
  879.   if q.numlines=0 then begin
  880.     writeln (^B'Message blank!');
  881.     maketext:=-1;
  882.     exit
  883.   end;
  884.   if firstfree>=0 then begin
  885.     sector:=firstfree;
  886.     seek (mapfile,sector);
  887.     read (mapfile,prev)
  888.   end else prev:=-1;
  889.   if prev<>-2 then begin
  890.     firstfree:=firstblank;
  891.     sector:=firstfree
  892.   end;
  893.   maketext:=sector;
  894.   if sector=-1 then begin
  895.     outofroom;
  896.     exit
  897.   end;
  898.   bufptr:=1;
  899.   for line:=1 to q.numlines do begin
  900.     curline:=q.text[line]+^M;
  901.     if line=q.numlines then curline:=curline+chr(0);
  902.     for pos:=1 to length(curline) do begin
  903.       k:=curline[pos];
  904.       buff[bufptr]:=k;
  905.       bufptr:=bufptr+1;
  906.       if bufptr>sectorsize then begin
  907.         flushbuf;
  908.         if sector=-1 then begin
  909.           outofroom;
  910.           exit
  911.         end
  912.       end
  913.     end
  914.   end;
  915.   if bufptr>1 then flushbuf;
  916.   setbam (prev,-1);
  917.   firstfree:=nextblank(firstfree,false);
  918.   if firstfree=-1 then firstfree:=firstblank
  919. end;
  920.  
  921. function copytext (sector:integer):integer;
  922. var me:message;
  923. begin
  924.   reloadtext (sector,me);
  925.   copytext:=maketext (me)
  926. end;
  927.  
  928. function charhit:boolean;
  929. var k:char;
  930. begin
  931.   if modeminlock then while numchars>0 do k:=getchar;
  932.   if hungupon or keyhit
  933.     then charhit:=true
  934.     else if online
  935.       then charhit:=(not modeminlock) and (numchars>0)
  936.       else charhit:=false
  937. end;
  938.  
  939. procedure printtext (sector:integer);
  940. var q:message;
  941.     x,bub,done:boolean;
  942.     n,m,t,w,b,y,mm,i,apexiscool,e:integer;
  943.     p:byte;
  944.     s,a,cornerstone,sunbane:string;
  945.     cs,css,keithmillerisafag:char;
  946.     kay,thegog:char;
  947. begin
  948.   reloadtext (sector,q);
  949.   writeln (^B);
  950.   n:=1;
  951.   repeat
  952.    mm:=0;
  953.    repeat
  954.     if length(q.text[n])>0 then begin
  955.     p:=0;
  956.     mm:=mm+1;
  957.     s:=copy(q.text[n],mm,1);
  958.     if s='|' then p:=mm
  959.      else p:=0;
  960.     if p>0 then begin
  961.      cornerstone:=copy(q.text[n],p+1,1);
  962.      sunbane:=copy(q.text[n],p+2,1);
  963.      a:=(upcase(cornerstone[1]))+(upcase(sunbane[1]));
  964.      if
  965.       (a='00') or (a='01') or (a='02') or (a='03') or (a='04') or (a='05') or
  966.       (a='06') or (a='07') or (a='08') or (a='09') or (a='10') or (a='11') or
  967.       (a='12') or (a='13') or (a='14') or (a='15') or (a='16') or (a='17') or
  968.       (a='18') or (a='19') or (a='20') or (a='21') or (a='22') or (a='23') or
  969.       (a='KE') or (a='UN') or (a='CL') or (a='TI') or (a='DA'){ or (a='B0') or
  970.       (a='B1') or (a='B2') or (a='B3') or (a='B4') or (a='B5') or (a='B6') or
  971.       (a='B7')} or ((a[1]='P') and (valu(a[2])>0))
  972.       then begin
  973.       if
  974.       (a='00') or (a='01') or (a='02') or (a='03') or (a='04') or (a='05') or
  975.       (a='06') or (a='07') or (a='08') or (a='09') or (a='10') or (a='11') or
  976.       (a='12') or (a='13') or (a='14') or (a='15') or (a='16') or (a='17') or
  977.       (a='18') or (a='19') or (a='20') or (a='21') or (a='22') or (a='23') then
  978.      begin
  979.       delete (q.text[n],p+1,2);
  980.       b:=valu(a);
  981.       case b of
  982.        16:case curattrib of
  983.            0..15:b:=curattrib;
  984.            16..31:b:=curattrib-16;
  985.            32..47:b:=curattrib-32;
  986.            48..63:b:=curattrib-48;
  987.            64..79:b:=curattrib-64;
  988.            80..95:b:=curattrib-80;
  989.            96..111:b:=curattrib-96;
  990.            112..127:b:=curattrib-111;
  991.           end;
  992.        17:case curattrib of
  993.            0..15:b:=curattrib+16;
  994.            16..31:b:=curattrib;
  995.            32..47:b:=curattrib-16;
  996.            48..63:b:=curattrib-32;
  997.            64..79:b:=curattrib-48;
  998.            80..95:b:=curattrib-64;
  999.            96..111:b:=curattrib-80;
  1000.            112..127:b:=curattrib-96;
  1001.           end;
  1002.        18:case curattrib of
  1003.            0..15:b:=curattrib+32;
  1004.            16..31:b:=curattrib+16;
  1005.            32..47:b:=curattrib;
  1006.            48..63:b:=curattrib-16;
  1007.            64..79:b:=curattrib-32;
  1008.            80..95:b:=curattrib-48;
  1009.            96..111:b:=curattrib-64;
  1010.            112..127:b:=curattrib-80;
  1011.           end;
  1012.        19:case curattrib of
  1013.            0..15:b:=curattrib+48;
  1014.            16..31:b:=curattrib+32;
  1015.            32..47:b:=curattrib+16;
  1016.            48..63:b:=curattrib;
  1017.            64..79:b:=curattrib-16;
  1018.            80..95:b:=curattrib-32;
  1019.            96..111:b:=curattrib-48;
  1020.            112..127:b:=curattrib-64;
  1021.           end;
  1022.        20:case curattrib of
  1023.            0..15:b:=curattrib+64;
  1024.            16..31:b:=curattrib+48;
  1025.            32..47:b:=curattrib+32;
  1026.            48..63:b:=curattrib+16;
  1027.            64..79:b:=curattrib;
  1028.            80..95:b:=curattrib-16;
  1029.            96..111:b:=curattrib-32;
  1030.            112..127:b:=curattrib-48;
  1031.           end;
  1032.        21:case curattrib of
  1033.            0..15:b:=curattrib+80;
  1034.            16..31:b:=curattrib+64;
  1035.            32..47:b:=curattrib+48;
  1036.            48..63:b:=curattrib+32;
  1037.            64..79:b:=curattrib+16;
  1038.            80..95:b:=curattrib;
  1039.            96..111:b:=curattrib-16;
  1040.            112..127:b:=curattrib-32;
  1041.           end;
  1042.        22:case curattrib of
  1043.            0..15:b:=curattrib+96;
  1044.            16..31:b:=curattrib+80;
  1045.            32..47:b:=curattrib+64;
  1046.            48..63:b:=curattrib+48;
  1047.            64..79:b:=curattrib+32;
  1048.            80..95:b:=curattrib+16;
  1049.            96..111:b:=curattrib;
  1050.            112..127:b:=curattrib-16;
  1051.           end;
  1052.        23:case curattrib of
  1053.            0..15:b:=curattrib+111;
  1054.            16..31:b:=curattrib+96;
  1055.            32..47:b:=curattrib+80;
  1056.            48..63:b:=curattrib+64;
  1057.            64..79:b:=curattrib+48;
  1058.            80..95:b:=curattrib+32;
  1059.            96..111:b:=curattrib+16;
  1060.            112..127:b:=curattrib;
  1061.           end;
  1062.         end;
  1063.       if b=0 then ansicolor (0);
  1064.       if (b<>0) then ansicolor (b);
  1065.      end;
  1066.      end;
  1067.      if a='KE' then
  1068.      begin
  1069.       delete (q.text[n],p+1,1);
  1070.       delete (q.text[n],p+1,1);
  1071.       write ('*');
  1072.       getstr (2);
  1073.      end;
  1074.      if a='UN' then
  1075.      begin
  1076.       delete (q.text[n],p+1,1);
  1077.       delete (q.text[n],p+1,1);
  1078.       write (urec.handle);
  1079.      end;
  1080.      if a='TI' then
  1081.      begin
  1082.       delete (q.text[n],p+1,1);
  1083.       delete (q.text[n],p+1,1);
  1084.       write (timestr(now));
  1085.      end;
  1086.      if a='DA' then
  1087.      begin
  1088.       delete (q.text[n],p+1,1);
  1089.       delete (q.text[n],p+1,1);
  1090.       write (datestr(now));
  1091.      end;
  1092.      if a='CL' then
  1093.      begin
  1094.       delete (q.text[n],p+1,1);
  1095.       delete (q.text[n],p+1,1);
  1096.       if (ansigraphics in urec.config) then write (#27+'[2J') else
  1097.        write (^L);
  1098.      end;
  1099.      if ((a[1]='P') and (valu(a[2])>0)) then
  1100.      begin
  1101.       delete (q.text[n],p+1,1);
  1102.       delete (q.text[n],p+1,1);
  1103.       apexiscool:=valu(a[2]);
  1104.       delay (apexiscool*1000);
  1105.      end;
  1106.    end else write (s);
  1107.   end;
  1108.   until mm=length(q.text[n]);
  1109.    writeln;
  1110.    n:=n+1;
  1111.   until break or (n>q.numlines) or hungupon;
  1112.   x:=xpressed; bub:=break;
  1113.   writeln (^B^M);
  1114.   xpressed:=x; break:=bub;
  1115.   ansicolor (urec.regularcolor)
  1116. end;
  1117.  
  1118. begin
  1119. end.
  1120.