home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / ECO30603.ZIP / ECO30603.LZH / ECOLIBBS / ECO_DOOR.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1993-03-08  |  30.9 KB  |  1,147 lines

  1. {$R-}
  2. {$M 5000, 0, 262144}
  3. unit eco_door;
  4. interface
  5. uses
  6.   dos, crt,
  7.   eco_ansi;
  8.  
  9. const
  10.   processextended: boolean = true;
  11.  
  12. type
  13.   charset = set of char;
  14.   userrec = record
  15.     name       :       string[35];   { name of the user online     }
  16.     city       :       string[25];   { city where user lives       }
  17.     timeleft   :             word;   { time user has left          }
  18.     timeout    :             byte;   { inactivity time for user    }
  19.     ansi       :          boolean;   { does the user support ansi  }
  20.     chatreason :       string[60];   { chat reason incase he yells }
  21.   end;
  22.  
  23.  
  24. var
  25.   port       :    byte;   {                                    comm port 0-3 }
  26.   baud       :    word;   {                            current connect speed }
  27.   online     : boolean;   {                whether it's a local/remote login }
  28.   mstatus    :    word;   {                               modem status, word }
  29.   foreground :    byte;   { foreground color, so you can check and change... }
  30.   background :    byte;   {  background color so you can check and change... }
  31.   stop       : boolean;   {          variable used for some stop procedures. }
  32.  
  33.   modemonly  : boolean;   {         if true then output will only be sent to }
  34.                           {       the modem! this boolean is used by several }
  35.                           {                                       procedures }
  36.  
  37.   sysopname  :  string;   {                      name of the system operator }
  38.  
  39.   showstatwin: boolean;   {                should the status window be shown }
  40.   user       : userrec;
  41.  
  42.   statevent,              {                       booleans to control events }
  43.                           {              if statevent = true then the window }
  44.                           {                                will be refreshed }
  45.   timeoutwarn: boolean;   {              if timeoutwarn = true then the user }
  46.                           {                  will be warned that his time is }
  47.                           {                                    running short }
  48.   localkey   : boolean;   {             this boolean will be true when a key }
  49.                           {                is pressed and it happend to be a }
  50.                           {               local key, this makes it easier to }
  51.                           {               support special sysop keys without }
  52.                           {             having to rebuild several procedures }
  53.  
  54. function softinitfossil: boolean; { will initialize the fossil, true if }
  55.                                   {                           sucessful }
  56. procedure inittimes;              {is automatically run when the program }
  57.                                   {starts.                               }
  58. procedure send(s: string);        {modem equivalent of write}
  59. procedure sendln(s: string);      {modem equivalent of writeln}
  60.                                   {read a string with max length = len}
  61. procedure readstr(var s: string; len: byte);
  62.                                   {read a word with max number of chars = len}
  63. procedure readint(var int: word; len: byte);
  64. procedure editstr(var s  : string; len: byte);
  65.                                    {edit a string with max length = len,
  66.                                    if the string s has a length > len then
  67.                                    len := length(s) !! }
  68. procedure portcolor(f: byte);     {modem equivalent of textcolor}
  69. procedure portbackground(b: byte);{modem equivalent of textbackground}
  70. procedure clrportscr;             {modem equivalent of clrscr}
  71. procedure clrporteol;             {modem equivalent of clreol}
  72. procedure autoansidetect;         {detect if remote has user.ansi support}
  73. procedure purgeinbuffer;          {purge input buffer}
  74. procedure portxy(x,y: byte);      {modem equivalent of gotoxy}
  75. procedure displayfile(
  76.   fname: string;
  77.   stopkeys: charset;
  78.   pausekeys: charset;
  79.   var ch   : char
  80. );
  81.                                   {display a file with hotkeys in set hotkeys}
  82. function  waitchar(cset: charset): char;
  83.                                   {waits till a key has been pressed in
  84.                                    cset and returns that key}
  85.  
  86. function  portx: byte;            {modem equivalent of wherex}
  87. function  porty: byte;            {modem equivalent of wherey}
  88. function  readchar: char;         {modem equivalent of readch}
  89. function  getstatus: word;        {returns modem status}
  90. function  portkeypressed: boolean;{modem equivalent of keypressed}
  91.  
  92. procedure resetcounter(num: byte;col: byte);
  93.                                   {reset line counter to num lines
  94.                                    and with prompt color = col}
  95. procedure stopcounter;            {stop the line counter.}
  96. procedure hangup;                 {hang up the modem!}
  97.  
  98. {other helpfull functions and procedures}
  99.  
  100. function  ms(l: longint): string;  {convert a word to a string fast}
  101. function  rep(ch: char;b: byte): string;
  102.                                    {return a string with filled with ch and }
  103.                                    {with length b                           }
  104. function  uprcase(s: string): string;
  105.                                   {convert a string to uprcase}
  106. procedure trim(var s: string);    {trim all leading and trailing #0 and #32}
  107. function  byte_set(b,bit: byte): boolean;
  108.                                   {checks to see if bit is set in b}
  109. function  lz(w: word): string;    {aka leading zero, adds a 0 before one digit }
  110.                                   {numbers, handy for dates!                   }
  111. procedure chat(full,direct: boolean); {inline fullscreen chatter. if full is   }
  112.                                   {False, then it will go into normal mode, If
  113.                                   {Direct is true, then it will not display the}
  114.                                   {Chat reason (since there won't be one)      }
  115. Procedure DisplayStat;            {show sysop status window}
  116.                                   {This option isn't really finished yet, but
  117.                                    the part that is done works...}
  118. Procedure Delay(Num: byte);       {A replacement for the Delay in the CRT
  119.                                    unit. This Delay works with seconds, and
  120.                                    it works in and outside of dv}
  121.  
  122.  
  123.                                    
  124.                                    
  125. implementation
  126.  
  127.  
  128.  
  129.  
  130.  
  131.  
  132.  
  133. const
  134.   esc = #27;
  135.   fore: array[0..15] of string[5] = (
  136.     '[0;30', '[0;34', '[0;32', '[0;36', '[0;31', '[0;35', '[0;33', '[0;37',
  137.     '[1;30', '[1;34', '[1;32', '[1;36', '[1;31', '[1;35', '[1;33', '[1;37'
  138.   );
  139.   back: array[0..7]  of string[4] = (
  140.     ';40m', ';44m', ';42m', ';46m', ';41m', ';45m', ';43m', ';47m'
  141.   );
  142.  
  143. var
  144.   _countline  : boolean;
  145.   _linecount  :    byte;
  146.   _pausecount :    byte;
  147.   _checktime  : boolean;
  148.  
  149.   promptcolor :    byte;
  150.   timeoutmin,
  151.   lastmin     :    byte;
  152.  
  153.  
  154.   
  155.   procedure delay(num: byte);
  156.   var
  157.     stoptime,
  158.     curtime : longint;
  159.     regs    : registers;
  160.  
  161.   begin
  162.     regs.ah := $00;
  163.     intr($1a,regs);
  164.     stoptime := regs.cx*65536 + regs.dx + (num * 18);
  165.     if stoptime > $1800b0 then stoptime := stoptime - $1800b0;
  166.     repeat
  167.       regs.ah := $00;
  168.       intr($1a,regs);
  169.       curtime := regs.cx*65536 + regs.dx;
  170.     until curtime >= stoptime;
  171.   end;
  172.  
  173.  
  174.   
  175.   procedure displaystat;
  176.   var x,y: byte;
  177.   begin
  178.     if statevent then begin
  179.       x := wherex;
  180.       y := wherey;
  181.       window(1,24,80,25);
  182.       textcolor(yellow);
  183.       textbackground(7);
  184.       gotoxy(1,1);
  185.       write(user.name,', From ',user.city);
  186.       write(rep(' ',64-wherex));
  187.       write('Baud: ',baud);
  188.       clrporteol;
  189.       gotoxy(1,2);
  190.       write('Time left: ',user.timeleft);
  191.       clrporteol;
  192.       window(1,1,80,23);
  193.       textattr := 7;
  194.       gotoxy(x,y);
  195.       statevent := false;
  196.     end;
  197.   end;
  198.  
  199.  
  200.   
  201.   procedure checkwarnflags;
  202.   var oldfore,oldback: byte;
  203.   begin
  204.     if timeoutwarn then begin
  205.       oldfore := foreground;
  206.       oldback := background;
  207.       portcolor(12);
  208.       portbackground(0);
  209.       sendln('Hello ?? Are you still there ??');
  210.       portcolor(oldfore);
  211.       portbackground(oldback);
  212.     end;
  213.   end;
  214.  
  215.  
  216.   
  217.   function lz(w: word): string;
  218.   var s: string;
  219.   begin
  220.     str(w,s);
  221.     if length(s) < 2 then s := '0'+s;
  222.     lz := s;
  223.   end;
  224.  
  225.  
  226.   
  227.   function byte_set(b,bit: byte): boolean;
  228.   var v: byte;
  229.   begin
  230.     v := 1 shl bit;
  231.     byte_set := v = v and b;
  232.   end;
  233.  
  234.  
  235.   
  236.   procedure inittimes;
  237.   var hour,min,sec,hund: word;
  238.   begin
  239.     gettime(hour,min,sec,hund);
  240.     lastmin    := min;
  241.     timeoutmin := min;
  242.   end;
  243.  
  244.  
  245.   
  246.   function ms(l: longint): string;
  247.   var s: string;
  248.   begin
  249.     str(l,s);
  250.     ms := s;
  251.   end;
  252.  
  253.  
  254.   
  255.   function rep(ch: char;b: byte): string;
  256.   var s: string;
  257.   begin
  258.     fillchar(s,sizeof(s),ch);
  259.     s[0] := chr(b);
  260.     rep := s;
  261.   end;
  262.  
  263.  
  264.   
  265.   function uprcase(s: string): string;
  266.   var j: byte;
  267.   begin
  268.     for j := 1 to length(s) do s[j] := upcase(s[j]);
  269.     uprcase := s;
  270.   end;
  271.  
  272.  
  273.   
  274.   function getstatus: word;
  275.   var regs: registers;
  276.   begin
  277.     fillchar(regs,sizeof(regs),$00);
  278.     regs.ah := $03;
  279.     intr($14,regs);
  280.     getstatus := regs.ah*256+regs.al;
  281.     writeln(regs.ah);
  282.   end;
  283.  
  284.  
  285.   
  286.   procedure trim(var s: string);
  287.   begin
  288.     while (s[1] in [' ',#0]) do delete(s,1,1);
  289.     while (s[length(s)] in [' ',#0]) do delete(s,length(s),1);
  290.   end;
  291.  
  292.  
  293.   
  294.   procedure carrierlost;
  295.   begin
  296.     writeln('Carrier lost, returning to board...');
  297.     halt;
  298.   end;
  299.  
  300.  
  301.   
  302.   procedure checkcarrier;
  303.   var regs: registers;
  304.   begin
  305.     fillchar(regs,sizeof(regs),$0);
  306.     regs.ah := $03;
  307.     regs.dx := port;
  308.     intr($14,regs);
  309.     if not byte_set(regs.al, 7) then carrierlost;
  310.   end;
  311.  
  312.  
  313.   
  314.   procedure resetcounter(num: byte;col: byte);
  315.   begin
  316.     promptcolor := col;
  317.     stop := false;
  318.     _pausecount := num;
  319.     _countline  := true;
  320.     _linecount  := 0;
  321.   end;
  322.  
  323.  
  324.   
  325.   procedure stopcounter;
  326.   begin
  327.     _countline := false;
  328.     stop       := false;
  329.   end;
  330.  
  331.  
  332.   
  333.   procedure promptcontinue;
  334.   var
  335.     cnt: byte;
  336.     s  : string;
  337.     ch : char;
  338.     oldf: byte;
  339.     oldb: byte;
  340.  
  341.   begin
  342.     oldf := foreground;
  343.     oldb := background;
  344.     portcolor(promptcolor);
  345.     portbackground(0);
  346.     send('More [Y/n]');
  347.     ch := #255;
  348.     repeat
  349.       if portkeypressed then ch := readchar;
  350.       ch := upcase(ch);
  351.     until ch in [#13,'Y','N'];
  352.     stop := ch = 'N';
  353.     _linecount := 0;
  354.     send(rep(#08,10)+rep(#32,10)+rep(#08,10));
  355.     portcolor(oldf);
  356.     portbackground(oldb);
  357.   end;
  358.  
  359.  
  360.   
  361.   procedure clickcounter;
  362.   begin
  363.     inc(_linecount);
  364.     if _linecount = _pausecount then promptcontinue;
  365.   end;
  366.  
  367.  
  368.   
  369.   procedure sendchar(ch: char);
  370.   var regs: registers;
  371.   begin
  372.     if online then begin
  373.       checkcarrier;
  374.       fillchar(regs,sizeof(regs),$00);
  375.       regs.ah := $01;
  376.       regs.al := ord(ch);
  377.       regs.dx := port;
  378.       intr($14,regs);
  379.     end;
  380.     if not modemonly then write(ch);
  381.   end;
  382.  
  383.  
  384.   
  385.   procedure send(s: string);
  386.   var cnt: byte;
  387.   begin
  388.     for cnt := 1 to length(s) do sendchar(s[cnt]);
  389.   end;
  390.  
  391.  
  392.   
  393.   procedure sendln(s: string);
  394.   var cnt: byte;
  395.   begin
  396.     for cnt := 1 to length(s) do sendchar(s[cnt]);
  397.     sendchar(#13);
  398.     sendchar(#10);
  399.     if _countline then clickcounter;
  400.   end;
  401.  
  402.  
  403.   
  404.   procedure purgeinbuffer;
  405.   var regs: registers;
  406.   begin
  407.     fillchar(regs,sizeof(regs),$00);
  408.     regs.ah := $0a;
  409.     regs.dx := port;
  410.     intr($14,regs);
  411.   end;
  412.  
  413.  
  414.   
  415.   function portpressed: boolean;
  416.   var regs: registers;
  417.   begin
  418.     portpressed := false;
  419.     fillchar(regs,sizeof(regs),$00);
  420.     if online then begin
  421.       regs.ah := $03;
  422.       regs.dx := port;
  423.       intr($14,regs);
  424.       portpressed := byte_set(regs.ah,0);
  425.       if not byte_set(regs.al,7) then carrierlost;
  426.     end;
  427.   end;
  428.  
  429.  
  430.   
  431.   function portkeypressed: boolean;
  432.   var ok: boolean;
  433.  
  434.     procedure checktimer(ok: boolean);
  435.     var hour,min,sec,hund: word;
  436.     begin
  437.       gettime(hour,min,sec,hund);
  438.       if min <> lastmin then begin
  439.         lastmin   := min;
  440.         statevent := true;
  441.         dec(user.timeleft);
  442.       end;
  443.       if ok then timeoutmin := min else begin
  444.         if min > timeoutmin + 2 then timeoutwarn := true;
  445.         if min > timeoutmin + 3 then hangup;
  446.       end;
  447.     end;
  448.  
  449.  
  450.     
  451.   begin
  452.     ok := keypressed or portpressed;
  453.     portkeypressed := ok;
  454.     checktimer(ok);
  455.     displaystat;
  456.     checkwarnflags;
  457.   end;
  458.  
  459.  
  460.   
  461.   
  462.   procedure jumptodos;
  463.   var y: byte;
  464.   begin
  465.     portcolor(15); portbackground(0); sendln(''); y := wherey;
  466.     sendln('Sysop is jumping to DOS, please wait...');
  467.     textattr := 7; clrscr; swapvectors;
  468.     exec(getenv('COMSPEC'),''); swapvectors; statevent := true;
  469.     displaystat; portxy(1,y); portcolor(15); portbackground(0);
  470.     sendln('Sysop has returned, thank you for waiting.');
  471.   end;
  472.  
  473.  
  474.  
  475.  
  476.   
  477.   function readchar: char;
  478.   var
  479.     regs: registers;
  480.     ch  : char;
  481.  
  482.   begin
  483.     if online and portpressed then begin
  484.       checkcarrier;
  485.       fillchar(regs,sizeof(regs),$00);
  486.       regs.ah := $02;
  487.       regs.dx := port;
  488.       intr($14,regs);
  489.       readchar := chr(regs.al);
  490.       localkey := false;
  491.     end else if keypressed then begin
  492.       ch := readkey;
  493.       if (ch = #0) and processextended then begin
  494.         ch := readkey;
  495.         case ch of
  496.           #46: chat(true,true);
  497.           #35: hangup;
  498.           #36: jumptodos;
  499.         end;
  500.         readchar := #255;
  501.       end else readchar := ch;
  502.       localkey := true;
  503.     end;
  504.   end;
  505.  
  506.  
  507.   
  508.   procedure readstr(var s: string; len: byte);
  509.   var ch: char;
  510.   begin
  511.     s := '';
  512.     ch := #0;
  513.     repeat
  514.       if portkeypressed then begin
  515.         ch := readchar;
  516.         if (ch = #08) and (length(s) > 0) then begin
  517.           delete(s,length(s),1);
  518.           send(#08#32#08);
  519.         end;
  520.         if (ch = #0) then begin
  521.           ch := readkey;
  522.           ch := #255;
  523.         end;
  524.         if (
  525.           (ch <> #08) and (ch <> #13) and (length(s) < len) and
  526.           (ch > #31) and (ch < #127)
  527.         ) then begin
  528.           s := s + ch;
  529.           sendchar(ch);
  530.         end;
  531.       end;
  532.     until (length(s) >= len) or (ch = #13);
  533.   end;
  534.  
  535.  
  536.   
  537.   procedure readint(var int: word; len: byte);
  538.   var
  539.     ch   :    char;
  540.     s    :  string;
  541.     code : integer;
  542.  
  543.   begin
  544.     s := '';
  545.     ch := #0;
  546.     repeat
  547.       if portkeypressed then begin
  548.         ch := readchar;
  549.         if (ch = #08) and (length(s) > 0) then begin
  550.           delete(s,length(s),1);
  551.           send(#08#32#08);
  552.         end;
  553.         if (
  554.           (ch <> #08) and (ch <> #13) and (length(s) < len) and
  555.           (ch > #47) and (ch < #58)
  556.         ) then begin
  557.           s := s + ch;
  558.           send(ch);
  559.         end;
  560.       end;
  561.     until (length(s) > len) or (ch = #13);
  562.     val(s,int,code);
  563.   end;
  564.  
  565.  
  566.   
  567.   procedure editstr(var s  : string; len: byte);
  568.   var ch: char;
  569.   begin
  570.     ch := #0;
  571.     send(s);
  572.     if len < length(s) then len := length(s);
  573.     repeat
  574.       if portkeypressed then begin
  575.         ch := readchar;
  576.         if (ch = #08) and (length(s) > 0) then begin
  577.           delete(s,length(s),1);
  578.           send(#08#32#08);
  579.         end;
  580.         if (
  581.           (ch <> #08) and (ch <> #13) and (length(s) < len) and
  582.           (ch > #31) and (ch < #127)
  583.         ) then begin
  584.           s := s + ch;
  585.           send(ch);
  586.         end;
  587.       end;
  588.     until (length(s) > len) or (ch = #13);
  589.   end;
  590.  
  591.  
  592.   
  593.   procedure portcolor(f: byte);
  594.   begin
  595.     if (f < 16) and user.ansi then begin
  596.       textcolor(f);
  597.       foreground := f;
  598.       modemonly := true;
  599.       if f < 8 then send(esc+'[0m');
  600.       send(esc+fore[foreground]+back[background]);
  601.       modemonly := false;
  602.     end;
  603.   end;
  604.  
  605.  
  606.   
  607.   procedure portbackground(b: byte);
  608.   begin
  609.     if (b < 8) and user.ansi then begin
  610.       textbackground(b);
  611.       background := b;
  612.       modemonly := true;
  613.       send(esc+'[0m');
  614.       send(esc+fore[foreground]+back[background]);
  615.       modemonly := false;
  616.     end;
  617.   end;
  618.  
  619.  
  620.   
  621.   procedure clrportscr;
  622.   begin
  623.     clrscr;
  624.     modemonly := true;
  625.     send(esc+'[2J');
  626.     modemonly := false;
  627.   end;
  628.  
  629.  
  630.   
  631.   procedure clrporteol;
  632.   begin
  633.     clreol;
  634.     modemonly := true;
  635.     if user.ansi then send(esc+'[K');
  636.     modemonly := false;
  637.   end;
  638.  
  639.  
  640.   
  641.   procedure autoansidetect;
  642.   var
  643.     ch :    char;
  644.     j  : longint;
  645.  
  646.   begin
  647.     purgeinbuffer;
  648.     user.ansi := false;
  649.     if online then begin
  650.       modemonly := true;
  651.       send(esc+'[6n');
  652.       send(rep(#08,4));
  653.       modemonly := false;
  654.       delay(1);
  655.       if portpressed then begin
  656.         ch := readchar;
  657.         user.ansi := ch = 'R';
  658.       end;
  659.     end else user.ansi := true;
  660.   end;
  661.  
  662.  
  663.   
  664.   procedure portxy(x,y: byte);
  665.   begin
  666.     if not online then gotoxy(x,y) else if user.ansi then begin
  667.       gotoxy(x,y);
  668.       modemonly := true;
  669.       send(esc+'['+ms(y)+';'+ms(x)+'H');
  670.       modemonly := false;
  671.     end else begin
  672.       if y > wherey then send(rep(#10,wherey-y));
  673.       if x > wherex then send(rep(#32,wherex-x));
  674.       if x < wherex then send(rep(#08,x-wherex));
  675.     end;
  676.   end;
  677.  
  678.  
  679.   
  680.   procedure displayfile(
  681.     fname     :  string;
  682.     stopkeys  : charset;
  683.     pausekeys : charset;
  684.     var ch    :    char
  685.   );
  686.  
  687.   var 
  688.     s  : string[80];
  689.     f  : file;
  690.     j  : byte;
  691.     nr : word;
  692.     io : byte;
  693.  
  694.     function hotkeypressed: boolean;
  695.     var ch2: char;
  696.     begin
  697.       hotkeypressed := false;
  698.       if stopkeys <> [] then if portkeypressed then begin
  699.         ch2 := upcase(readchar);
  700.         if ch2 in stopkeys then begin
  701.           hotkeypressed := true;
  702.           ch := ch2;
  703.         end else if ch2 in pausekeys then begin
  704.           repeat until portkeypressed;
  705.           ch2 := readchar;
  706.         end;
  707.         modemonly := true;
  708.       end;
  709.     end;
  710.  
  711.   begin
  712.     if fname <> '' then begin
  713.       if pos('.',fname) > 0 then delete(fname,pos('.',fname),4);
  714.       if user.ansi then fname := fname + '.ANS' else fname := fname + '.ASC';
  715.       assign(f,fname);
  716.       {$I-} reset(f,1); {$I+}
  717.       io := ioresult;
  718.       if (io <> 0) and user.ansi then begin
  719.         if user.ansi then fname := copy(fname,1,pos('.',fname))+'ASC';
  720.         assign(f,fname);
  721.         {$I-} reset(f,1); {$I+}
  722.         io := ioresult;
  723.       end;
  724.       if io = 0 then begin
  725.         modemonly := true;
  726.         repeat
  727.           s := '';
  728.           blockread(f,s[1],80,nr);
  729.           s[0] := chr(nr);
  730.           send(s);
  731.           ansiwrite(s);
  732.         until (nr = 0) or hotkeypressed;
  733.         modemonly := false;
  734.         close(f);
  735.       end else writeln('Error: ',fname, ' not found');
  736.     end;
  737.   end;
  738.  
  739.  
  740.   
  741.   function portx: byte;
  742.   begin
  743.     portx := wherex;
  744.   end;
  745.  
  746.  
  747.   
  748.   function porty: byte;
  749.   begin
  750.     porty := wherey;
  751.   end;
  752.  
  753.  
  754.   
  755.   function waitchar(cset: charset): char;
  756.   var ch: char;
  757.   begin
  758.     ch := #255;
  759.     repeat
  760.       if portkeypressed then ch := readchar;
  761.       ch := upcase(ch);
  762.     until ch in cset;
  763.     waitchar := ch;
  764.   end;
  765.  
  766.  
  767.   
  768.   procedure hangup;
  769.   var regs: registers;
  770.   begin
  771.     with regs do begin
  772.       ah := $06; dx := port; al := $00; intr($14,regs);
  773.     end;
  774.     halt;
  775.   end;
  776.  
  777.  
  778.   
  779.   procedure chat(full,direct: boolean);
  780.   const
  781.     infocolor = 14;
  782.     dsz    : string[4] = #24'B00';
  783.     dszcnt : byte = 1;
  784.  
  785.   var
  786.     sysopscreen   : array[2..11] of string[80];
  787.     userscreen    : array[13..22] of string[80];
  788.     normalline    : string[80];
  789.     sysopx,sysopy :       byte;
  790.     userx,usery   :       byte;
  791.     ch            :       char;
  792.     sysopchat     :       byte;
  793.     userchat      :       byte;
  794.     starttime     :    longint;
  795.     endtime       :    longint;
  796.     hour, min,
  797.     sec, hund     :       word;
  798.     chatlog       :       text;
  799.  
  800.  
  801.     
  802.     procedure scrollsysopscreen;
  803.     var cnt: byte;
  804.     begin
  805.       for cnt := 2 to 6 do sysopscreen[cnt] := sysopscreen[cnt+5];
  806.       for cnt := 7 to 11 do fillchar(
  807.         sysopscreen[cnt], sizeof(sysopscreen[cnt]), 0
  808.       );
  809.       for cnt := 11 downto 2 do begin
  810.         portxy(1,cnt);
  811.         clrporteol;
  812.         if cnt < 7 then sendln(sysopscreen[cnt]);
  813.       end;
  814.       sysopy := 7;
  815.     end;
  816.  
  817.  
  818.     procedure wrapsysopscreen;
  819.     var cnt: byte;
  820.     begin
  821.       cnt := 81;
  822.       repeat
  823.         dec(cnt);
  824.       until (sysopscreen[sysopy-1][cnt] = #32) or (cnt = 1);
  825.       if cnt > 1 then begin
  826.         sysopscreen[sysopy] := copy(sysopscreen[sysopy-1],cnt+1,80-cnt);
  827.         delete(sysopscreen[sysopy-1],cnt,80-cnt);
  828.         portxy(cnt,sysopy-1);
  829.         send(rep(#32,81-cnt));
  830.         portxy(1,sysopy);
  831.         send(sysopscreen[sysopy]);
  832.       end;
  833.     end;
  834.  
  835.  
  836.  
  837.     procedure scrolluserscreen;
  838.     var cnt: byte;
  839.     begin
  840.       for cnt := 13 to 17 do userscreen[cnt] := userscreen[cnt+5];
  841.       for cnt := 18 to 22 do fillchar(
  842.         userscreen[cnt], sizeof(userscreen[cnt]), 0
  843.       );
  844.       for cnt := 22 downto 13 do begin
  845.         portxy(1,cnt);
  846.         clrporteol;
  847.         if cnt < 18 then sendln(userscreen[cnt]);
  848.       end;
  849.       usery := 18;
  850.     end;
  851.  
  852.     
  853.     
  854.     procedure clearsysopscreen;
  855.     var cnt : byte;
  856.     begin
  857.       for cnt := 2 to 11 do fillchar(
  858.         sysopscreen[cnt], sizeof(sysopscreen[cnt]), 0
  859.       );
  860.       for cnt := 11 downto 2 do begin
  861.         portxy(1,cnt);
  862.         clrporteol;
  863.       end;
  864.       sysopy := 2;
  865.     end;
  866.  
  867.  
  868.  
  869.     procedure clearuserscreen;
  870.     var cnt : byte;
  871.     begin
  872.       for cnt := 13 to 22 do fillchar(
  873.         userscreen[cnt], sizeof(userscreen[cnt]), 0
  874.       );
  875.       for cnt := 22 downto 13 do begin
  876.         portxy(1,cnt);
  877.         clrporteol;
  878.       end;
  879.       usery := 13;
  880.     end;
  881.  
  882.  
  883.  
  884.     procedure wrapuserscreen;
  885.     var cnt: byte;
  886.     begin
  887.       cnt := 81;
  888.       repeat
  889.         dec(cnt);
  890.       until (userscreen[usery-1][cnt] = #32) or (cnt = 1);
  891.       if cnt > 1 then begin
  892.         userscreen[usery] := copy(userscreen[usery-1],cnt+1,80-cnt);
  893.         delete(userscreen[usery-1],cnt,80-cnt);
  894.         portxy(cnt,usery-1);
  895.         send(rep(#32,81-cnt));
  896.         portxy(1,usery);
  897.         send(userscreen[usery]);
  898.       end;
  899.     end;
  900.  
  901.  
  902.  
  903.     procedure wordwrapnormal;
  904.     var cnt: byte;
  905.     begin
  906.       cnt := 81;
  907.       repeat
  908.         dec(cnt);
  909.       until (normalline[cnt] = #32) or (cnt = 1);
  910.       if cnt > 1 then begin
  911.         normalline := copy(normalline,cnt+1,80-cnt);
  912.         portxy(cnt,porty);
  913.         send(rep(#32,81-cnt));
  914.         send(normalline);
  915.       end;
  916.     end;
  917.  
  918.     procedure redrawscreen(sysop: boolean);
  919.     var cnt: byte;
  920.     begin
  921.       if sysop then begin
  922.         modemonly := true; clrscr; textcolor(15); textbackground(1);
  923.         clreol; write(#32+sysopname); gotoxy(1,12); clreol;
  924.         write(#32+user.name); gotoxy(1,23); clreol; textcolor(14);
  925.         write(
  926.           'Press Ctrl + R to re-draw screen and Ctrl + W to clear your screen'
  927.         );
  928.         textbackground(0); gotoxy(1,2); textcolor(14); gotoxy(1,2);
  929.         for cnt := 2 to sysopy do writeln(sysopscreen[cnt]);
  930.         textcolor(3); gotoxy(1,13);
  931.         for cnt := 13 to usery do writeln(userscreen[cnt]);
  932.       end else begin
  933.         clrportscr; portcolor(15); portbackground(1); clrporteol;
  934.         send(#32+sysopname); portxy(1,12); clrporteol; send(#32+user.name);
  935.         portxy(1,23); clrporteol; portcolor(14);
  936.         send(
  937.           'Press Ctrl + R to re-draw screen and Ctrl + W to clear your screen'
  938.         );
  939.         portbackground(0); portxy(1,2); portcolor(14); portxy(1,2);
  940.         for cnt := 2 to sysopy do sendln(sysopscreen[cnt]);
  941.         portcolor(3); portxy(1,13);
  942.         for cnt := 13 to usery do sendln(userscreen[cnt]);
  943.       end;
  944.       if sysop then portxy(length(sysopscreen[sysopy])+1,sysopy) else
  945.         portxy(length(userscreen[usery])+1,usery);
  946.      end;
  947.  
  948.   begin
  949.     gettime(hour,min,sec,hund); starttime := hour*60+min; statevent := true;
  950.     displaystat; sysopchat := 14; userchat  := 3;
  951.     ch := #255; portcolor(infocolor); portbackground(0); sendln(''); sendln('');
  952.     sendln('SysOp entering chat mode...');
  953.     if user.ansi and full then begin
  954.       portbackground(0); clrportscr; portcolor(15); portbackground(1);
  955.       clrporteol; send(#32+sysopname); portxy(1,12); clrporteol;
  956.       send(#32+user.name); portxy(1,23); clrporteol; portcolor(14);
  957.       send(
  958.         'Press Ctrl + R to re-draw screen and Ctrl + W to clear your screen'
  959.       );
  960.       portbackground(0); portxy(1,2); sysopy := 2; usery  := 13;
  961.       fillchar(sysopscreen,sizeof(sysopscreen),0);
  962.       fillchar(userscreen ,sizeof(userscreen) ,0);
  963.       processextended := false;
  964.       repeat
  965.         if portkeypressed then begin
  966.           ch := readchar;
  967.           if localkey then begin
  968.             if ch = #0 then begin
  969.               ch := readkey;
  970.               case ch of
  971.                 #35: hangup;
  972.                 #36: begin
  973.                   jumptodos;
  974.                   redrawscreen(true);
  975.                 end;
  976.               end;
  977.             end else begin
  978.               displaystat;
  979.               if foreground <> sysopchat then portcolor(sysopchat);
  980.               if (
  981.                 (wherex <> length(sysopscreen[sysopy])+1) or
  982.                 (wherey <> sysopy)
  983.               ) then portxy(length(sysopscreen[sysopy])+1,sysopy);
  984.               if (ch = #08) then begin
  985.                 if (
  986.                   (length(sysopscreen[sysopy]) = 0) and (sysopy > 2)
  987.                 ) then begin
  988.                   dec(sysopy);
  989.                   if length(sysopscreen[sysopy]) = 80 then begin
  990.                     portxy(80,sysopy);
  991.                     send(#32);
  992.                     portxy(80,sysopy);
  993.                   end else begin
  994.                     portxy(length(sysopscreen[sysopy])+1,sysopy);
  995.                     delete(sysopscreen[sysopy],length(sysopscreen[sysopy]),1);
  996.                     send(#08#32#08);
  997.                   end;
  998.                 end else if length(sysopscreen[sysopy]) > 0 then begin
  999.                   delete(sysopscreen[sysopy],length(sysopscreen[sysopy]),1);
  1000.                   send(#08#32#08);
  1001.                 end;
  1002.               end;
  1003.               if (ch > #27) and (ch <> #255) then begin
  1004.                 sysopscreen[sysopy] := sysopscreen[sysopy] + ch; send(ch);
  1005.                 if length(sysopscreen[sysopy]) = 80 then begin
  1006.                   if sysopy = 11 then scrollsysopscreen else inc(sysopy);
  1007.                   if sysopscreen[sysopy-1][80] > #32 then wrapsysopscreen;
  1008.                 end;
  1009.               end;
  1010.               if ch = #23 then clearsysopscreen;
  1011.               if ch = #18 then redrawscreen(true);
  1012.               if ch = #25 then begin
  1013.                 sysopscreen[sysopy] := '';
  1014.                 portxy(1,sysopy);
  1015.                 clrporteol;
  1016.               end;
  1017.               if ch = #13 then begin
  1018.                 if sysopy = 11 then scrollsysopscreen else inc(sysopy);
  1019.                 portxy(1,sysopy);
  1020.               end;
  1021.             end;
  1022.           end else begin
  1023.             if foreground <> userchat then portcolor(userchat);
  1024.             if (
  1025.               (portx <> length(userscreen[usery])+1) or
  1026.               (porty <> usery)
  1027.             ) then portxy(length(userscreen[usery])+1,usery);
  1028.             if (ch = #08) then begin
  1029.               if (length(userscreen[usery]) = 0) and (usery > 13) then begin
  1030.                 dec(usery);
  1031.                 if length(userscreen[usery]) = 80 then begin
  1032.                   portxy(80,usery);
  1033.                   send(#32);
  1034.                   portxy(80,usery);
  1035.                 end else begin
  1036.                   portxy(length(userscreen[usery])+1,usery);
  1037.                   delete(userscreen[usery],length(userscreen[usery]),1);
  1038.                   send(#08#32#08);
  1039.                 end;
  1040.               end else if length(userscreen[usery]) > 0 then begin
  1041.                 delete(userscreen[usery],length(userscreen[usery]),1);
  1042.                 send(#08#32#08);
  1043.               end;
  1044.             end;
  1045.             if (ch = #0) then begin
  1046.               ch := readkey;
  1047.               ch := #255;
  1048.             end;
  1049.             if (
  1050.               (ch <> #08) and (ch <> #13) and (ch > #27) and (ch <> #255)
  1051.             ) then begin
  1052.               userscreen[usery] := userscreen[usery] + ch;
  1053.               send(ch);
  1054.               if length(userscreen[usery]) = 80 then begin
  1055.                 if usery = 22 then scrolluserscreen else inc(usery);
  1056.                 if userscreen[usery-1][80] > #32 then wrapuserscreen;
  1057.               end;
  1058.             end;
  1059.             if ch = #13 then begin
  1060.               if usery = 22 then scrolluserscreen else inc(usery);
  1061.               portxy(1,usery);
  1062.             end;
  1063.             if ch = #18 then redrawscreen(false);
  1064.             if ch = #23 then clearuserscreen;
  1065.             if ch = #25 then begin
  1066.               userscreen[usery] := '';
  1067.               portxy(1,usery);
  1068.               clrporteol;
  1069.             end;
  1070.             if ch = #27 then ch := #255;
  1071.           end;
  1072.         end;
  1073.       until (ch = #27);
  1074.     end else begin
  1075.       sendln('Hi there, '+user.name+' this is your Sysop.');
  1076.       normalline := '';
  1077.       repeat
  1078.         if portkeypressed then begin
  1079.           ch := readchar;
  1080.           if localkey then if (
  1081.             foreground <> sysopchat
  1082.           ) then portcolor(sysopchat) else if (
  1083.             foreground <> userchat
  1084.           ) then portcolor(userchat);
  1085.           if (ch = #08) and (length(normalline) > 0) then begin
  1086.             delete(normalline,length(normalline),1);
  1087.             send(#08#32#08);
  1088.           end;
  1089.           if (
  1090.             (ch <> #08) and (ch <> #13) and (length(normalline) < 80) and
  1091.             (ch > #31) and (ch < #127)
  1092.           ) then begin
  1093.             normalline := normalline + ch;
  1094.             if length(normalline) = 80 then wordwrapnormal;
  1095.             send(ch);
  1096.           end;
  1097.           if (ch = #13) then begin
  1098.             sendln('');
  1099.             normalline := '';
  1100.           end;
  1101.         end;
  1102.       until (ch = #27) and (localkey);
  1103.       processextended := true;
  1104.     end;
  1105.  
  1106.     portbackground(0); clrportscr; portcolor(infocolor);
  1107.     sendln('Chat mode ended.'); sendln('');
  1108.     gettime(hour,min,sec,hund); endtime := hour*60+sec;
  1109.     if direct then begin
  1110.       if (
  1111.         endtime < starttime
  1112.       ) then user.timeleft := user.timeleft+endtime-starttime else
  1113.         user.timeleft := user.timeleft+starttime-endtime;
  1114.     end;
  1115.   end;
  1116.  
  1117.  
  1118.   
  1119.   function softinitfossil: boolean;
  1120.   var regs: registers;
  1121.   begin
  1122.     softinitfossil := false;
  1123.     with regs do begin
  1124.       ah := $04; dx := port; intr($14,regs);
  1125.       if ax = $1954 then softinitfossil := true;
  1126.     end;
  1127.   end;
  1128.  
  1129. begin
  1130.   user.ansi   := false;
  1131.   port        :=     1;
  1132.   foreground  :=     7;
  1133.   background  :=     0;
  1134.   modemonly   := false;
  1135.   _countline  := false;
  1136.   _linecount  :=     0;
  1137.   _pausecount :=     0;
  1138.   stop        := false;
  1139.   _checktime  := false;
  1140.   statevent   :=  true;
  1141.   timeoutwarn := false;
  1142.   timeoutmin  :=    61;
  1143.   fillchar(user,sizeof(user),0);
  1144.   fillchar(sysopname,sizeof(sysopname),0);
  1145.   inittimes;
  1146. end.
  1147.