home *** CD-ROM | disk | FTP | other *** search
/ Best Objectech Shareware Selections / UNTITLED.iso / boss / util / misc / 018 / mufusion.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1993-03-04  |  33.6 KB  |  1,317 lines

  1. {$B-}    {Boolean complete evaluation off}
  2. {$S-}    {Stack checking off}
  3. {$I-}    {I/O checking off}
  4. {$R-}    {Range checking off}
  5. {$M 4096,8192,8192}
  6.  
  7. program mufusion;
  8.  
  9. {  This terminal package by was written by Peter Summers, using code
  10.    released to the public domain program by Jim Nutt.  It now emulates a
  11.    Microfusion MF30 terminal.  The program (including source) may be
  12.    distributed freely, but copyright is retained by the Cardiology
  13.    Department at Royal Melbourne Hospital.    }
  14.  
  15. Uses
  16.   Dos,
  17.   Crt,
  18.   {$IFDEF INT14}
  19.   Mufint14;
  20.   {$ELSE}
  21.   Mufasync;
  22.   {$ENDIF}
  23.  
  24. const
  25.   default     = -1;
  26.   space       = $20;
  27.   bufsize     = 720;        {number of lines of backpage buffer.  This can be reduced
  28.                  to increase the amount of memory available when shelled to DOS.}
  29.   prbufsize   = 3072;       {size of the printer buffer}
  30.   fklen       = 80;         {maximum length of function key definition}
  31.  
  32. {initialised variables}
  33.   portnum     : integer = 1;                {communications port number}
  34.   baudrate    : word    = 9600;             {line speed}
  35.   fcolor      : integer = 2;                {foreground color}
  36.   bcolor      : integer = 0;                {background color}
  37.   pcolor      : integer = 3;                {protected color}
  38.   defprinter  : string[40] = 'LPT1';        {default printer}
  39.   end_now     : boolean = false;            {true if we're about to exit}
  40.   capture_on  : boolean = false;            {true if capturing}
  41.   printer_on  : boolean = false;            {true if printing}
  42.   new_line    : boolean = false;            {true if a line feed is pending}
  43.   gen_cr      : boolean = false;            {true if a carriage return may be generated}
  44.   endprbuf    : integer = 0;                {points to end of print buffer}
  45.   numprints   : integer = 1;                {number of copies when using esc-F-C}
  46.   debug_off   : boolean = true;             {true if debugging is off}
  47.   lastkb_stat : byte    = $FF;              {previous status of shift/control/alt keys}
  48.   fk_defined  : boolean = false;            {true if the function keys have been defined}
  49.   auto_echo   : boolean = false;            {true if characters echoed locally}
  50.   sendbreak   : boolean = false;            {true if a break signal should be sent}
  51.   printscrn   : boolean = false;            {true if a print screen is pending}
  52.   prism          : boolean = false;        {true if we're trying to look like a prism}
  53.   screenptr   : integer = 0;                {pointer to current screen within backpage buffer}
  54.  
  55. var
  56.   screenbuf   : array[1..80,0..bufsize-1] of byte;      {backpage buffer}
  57.   fkey        : array[1..20] of string[fklen];          {function key definitions}
  58.   protmode    : boolean;                                {true = protected text on}
  59.   capture     : text;                                   {file for capturing}
  60.   printer     : text;                                   {file for printing}
  61.   printbuf    : array[1..prbufsize] of char;            {Buffer for output to the printer.}
  62.   start_mode  : integer;                                {Text mode when mufusion was called}
  63.   num_lines   : integer;                                {Number of rows on terminal screen}
  64.   thiskb_stat : byte;                                   {Status of shift/control/alt keys}
  65.   lastposx    : integer;                                {Used for restoring cursor position (with on of the ecs F functions)}
  66.   lastposy    : integer;
  67.   saveint05   : pointer;                                {The original print screen vector}
  68.   reg         : registers;                              {Used for called to interrupt routines}
  69.  
  70.  
  71.  
  72. function kb_stat: byte;
  73.  
  74. { Returns the shift/control/alt function key status of the keyboard}
  75.  
  76. begin
  77.   reg.AH := $02;
  78.   intr($16, Reg);
  79.   kb_stat := reg.AL;
  80. end;
  81.  
  82.  
  83.  
  84. procedure stat_write(tstr:string; wait:word);
  85.  
  86. { Write a string to the status line}
  87.  
  88. var
  89.   oldtextattr : byte;
  90.   x,y         : integer;
  91.  
  92. begin
  93.   x := wherex;
  94.   y := wherey;
  95.   oldtextattr:=textattr;
  96.   textattr:=$70;
  97.   window(1,num_lines+1,80,num_lines+1);
  98.   clreol;
  99.   gotoxy(2,1);
  100.   write(tstr);
  101.   lastkb_stat:=$FF;             {ensures the status line gets restored}
  102.   if wait>0 then
  103.     begin
  104.       sound(50);
  105.       delay(wait);
  106.       nosound;
  107.     end;
  108.   window(1,1,80,num_lines);
  109.   textattr:=oldtextattr;
  110.   gotoxy(x,y);
  111. end;
  112.  
  113.  
  114.  
  115. function stat_read(pstr : string) : string;
  116.  
  117. { Prompt for an input string on the status line}
  118.  
  119. var
  120.   oldtextattr : byte;
  121.   tstr        : string[80];
  122.   x,y         : integer;
  123.  
  124. begin
  125.  
  126.   x := wherex;
  127.   y := wherey;
  128.   oldtextattr:=textattr;
  129.   textattr:=$70;
  130.   window(1,num_lines+1,80,num_lines+1);
  131.   clreol;
  132.   gotoxy(2,1);
  133.   write(pstr);
  134.   lastkb_stat:=$FF;             {ensures the status line gets restored}
  135.   gotoxy(length(pstr) + 3,1);
  136.   {$IFDEF INT14}
  137.   if not paused then int14_pause;
  138.   {$ENDIF}
  139.   readln(tstr);
  140.   stat_read := tstr;
  141.   window(1,1,80,num_lines);
  142.   textattr:=oldtextattr;
  143.   gotoxy(x,y);
  144. end;
  145.  
  146.  
  147.  
  148. function open(var file_to_open : text; filename : string): boolean;
  149.  
  150. var
  151.   attributes   : word;
  152.   keystroke    : char;
  153.  
  154. begin
  155.   if filename='' then open:=false else
  156.     begin
  157.       assign(file_to_open,filename);
  158.       getfattr(file_to_open,attributes);
  159.       keystroke:=' ';
  160.       if attributes=0 then
  161.     rewrite(file_to_open)
  162.       else
  163.     repeat
  164.       stat_write('File exists, (A)ppend, (O)verlay, or (Q)uit ? ..',500);
  165.       keystroke:=readkey;
  166.       case keystroke of
  167.         'A','a' : append(file_to_open);
  168.         'O','o' : rewrite(file_to_open);
  169.       end;
  170.     until keystroke in ['O','o','A','a','Q','q'];
  171.       if keystroke in ['Q','q'] then
  172.         open:=false
  173.       else
  174.         begin
  175.           if (IOresult=0) then
  176.             open:=true
  177.           else
  178.             begin
  179.               open:=false;
  180.               stat_write('Can''t write to file '+filename+'...',1000);
  181.             end;
  182.         end;
  183.     end;
  184. end;
  185.  
  186.  
  187.  
  188. procedure display_statline;
  189.  
  190. { Display the current status line, dependant on keyboard shift/alt key
  191.   status and definition of function keys }
  192.  
  193. var
  194.   oldtextattr : byte;
  195.   startkey    : integer;
  196.   i,j,x,y     : integer;
  197.  
  198. begin
  199.   if thiskb_stat = 8 then
  200.     stat_write('Capture  Dial  dEbug  Feed  Hangup  Image  Lines  dOs  Print  Run  Setpr  eXit',0)
  201.   else
  202.     begin
  203.       if fk_defined and (thiskb_stat<4) then
  204.     begin
  205.       x := wherex;
  206.       y := wherey;
  207.       oldtextattr:=textattr;
  208.       window(1,num_lines+1,80,num_lines+1);
  209.       gotoxy(1,1);
  210.       clreol;
  211.       textattr:=$70;
  212.       if thiskb_stat=0 then
  213.         startkey:=1
  214.       else
  215.         startkey:=11;
  216.       for i:= 0 to 9 do
  217.         begin
  218.           gotoxy(7*i+2*(i div 4)+1,1);
  219.           for j:= 1 to 6 do
  220.         if (j <= length(fkey[startkey+i]))
  221.           and (ord(fkey[startkey+i,j]) in [32..126])
  222.             then write(fkey[startkey+i,j]) else write(' ');
  223.         end;
  224.       gotoxy(75,1);
  225.       if prism then textattr:=4 else textattr:=1;
  226.       if printer_on then textattr:=textattr or 8;
  227.       if capture_on then textattr:=textattr or $80;
  228.       write('µ3.9n');
  229.       window(1,1,80,num_lines);
  230.       textattr:=oldtextattr;
  231.       gotoxy(x,y);
  232.     end
  233.       else
  234.     stat_write('µfusion v3.9n by Peter Summers                           (C) Cardiology at RMH',0);
  235.     end;
  236. end;
  237.  
  238.  
  239.  
  240. procedure flushprintbuf(numcopies:integer);
  241.  
  242. { Flush the printer buffer }
  243.  
  244. var
  245.   i,copy : integer;
  246.   retry  : char;
  247.  
  248. begin
  249.   if (endprbuf=0) or not printer_on then exit;
  250.   stat_write('Writing to the printer...',0);
  251.   {$IFDEF INT14}
  252.   if not paused then int14_pause;
  253.   {$ENDIF}
  254.   for copy:=1 to numcopies do
  255.     for i:=1 to endprbuf do
  256.       begin
  257.       write(printer,printbuf[i]);
  258.         while IOresult<>0 do
  259.       begin
  260.         stat_write('Can''t write to the printer, Retry (Y/N) ?',1000);
  261.             if readkey in ['N','n'] then
  262.               begin
  263.             endprbuf:=0;
  264.             printer_on:=false;
  265.             close(printer);
  266.                 if IOresult<>0 then
  267.                   stat_write('Error closing printer...',1000);
  268.                exit;
  269.               end;
  270.             write(printer,printbuf[i]);
  271.           end;
  272.       end;
  273.   endprbuf:=0;
  274. end;
  275.  
  276.  
  277.  
  278. procedure print(rcvd:integer);
  279.   begin
  280.     if printer_on and (rcvd>=0) then
  281.       begin
  282.         endprbuf:=endprbuf+1;
  283.         printbuf[endprbuf]:=chr(rcvd);
  284.         if endprbuf=prbufsize then flushprintbuf(1);
  285.       end;
  286.   end;
  287.  
  288.  
  289.  
  290. procedure turn_printer_on;
  291.  
  292. var attributes : word;
  293.  
  294. begin
  295.   if printer_on then exit;
  296.   getfattr(printer,attributes);
  297.   if attributes=0 then
  298.     rewrite(printer)
  299.   else
  300.     append(printer);
  301.   if IOresult=0 then
  302.     printer_on:=true
  303.   else
  304.     stat_write('Can''t access printer...',1000);
  305.   lastkb_stat:=$FF;             {ensures the status line gets restored}
  306. end;
  307.  
  308.  
  309.  
  310. procedure turn_printer_off;
  311.  
  312. begin
  313.   if not printer_on then exit;
  314.   flushprintbuf(1);
  315.   if not printer_on then exit;
  316.   close(printer);
  317.   if IOresult<>0 then stat_write('Error closing printer...',1000);
  318.   printer_on:=false;
  319.   lastkb_stat:=$FF;             {ensures the status line gets restored}
  320. end;
  321.  
  322.  
  323.  
  324. procedure hangup;
  325.  
  326. { Hang up the modem }
  327.  
  328. begin
  329.   stat_write('Hanging up the modem...',0);
  330.   {$IFDEF INT14}
  331.   if not paused then int14_pause;
  332.   {$ENDIF}
  333.   Async_Close(true);
  334.   delay(1100);
  335.   if not(Async_Open(portnum,baudrate,'N',8,1)) then halt(1);
  336.   if Async_Carrier_Detect then
  337.     begin
  338.       Async_Send_String_With_Delays('+++',10,10);
  339.       delay(1100);
  340.       Async_Send_String_With_Delays(^M+'ATH'+^M,10,10);
  341.     end;
  342.   if Async_Carrier_Detect then
  343.     stat_write('The modem won''t hang up...',0)
  344.   else
  345.     stat_write('The modem has hung up...',0);
  346.   delay(1000);
  347.  end;
  348.  
  349.  
  350.  
  351. procedure dial;
  352.  
  353. { Dial with a Hayes compatible modem }
  354.  
  355. var
  356.   number : string[40];
  357.  
  358. begin
  359.   number := stat_read('Number to dial ...');
  360.   if number<>'' then
  361.     begin
  362.       if Async_Carrier_Detect then hangup;
  363.       Async_Send_String_With_Delays(^M + 'ATD' + number + ^M,10,10);
  364.     end;
  365. end;
  366.  
  367.  
  368.  
  369. procedure master_clear;
  370.  
  371. { Clear the current screen }
  372.  
  373. var
  374.   i,j : integer;
  375.  
  376. begin
  377.   textattr:=(bcolor shl 4) or 8 or pcolor;
  378.   clrscr;
  379.   protmode:=true;
  380.   new_line:=false;
  381.   gen_cr:=false;
  382.   screenptr:=(screenptr+num_lines) mod bufsize;
  383.   for i:=1 to 80 do
  384.     for j:=1 to num_lines do
  385.       screenbuf[i,(j+screenptr) mod bufsize]:=space;
  386. end;
  387.  
  388.  
  389.  
  390. procedure display_screen;
  391.  
  392. { Display the section of the backpage buffer pointed to by screenptr }
  393.  
  394. var
  395.   i,j,k       : integer;
  396.   oldtextattr : byte;
  397.  
  398. begin
  399.   oldtextattr:=textattr;
  400.   gotoxy(1,1);
  401.   for j:=1 to num_lines do
  402.     if screenbuf[1,(j+screenptr) mod bufsize]<>0 then
  403.       for i:=1 to 80 do
  404.     begin
  405.       if not ((i=80) and (j=num_lines)) then
  406.         begin
  407.           k:=screenbuf[i,(j+screenptr) mod bufsize];
  408.           if (k and $80)=0 then
  409.         textattr:=(bcolor shl 4) or 8 or fcolor
  410.           else
  411.         textattr:=(bcolor shl 4) or 8 or pcolor;
  412.           write(chr(k and $7F));
  413.         end
  414.     end
  415.     else
  416.       begin
  417.     clreol;
  418.     write(^M^J);
  419.       end;
  420.   textattr:=oldtextattr;
  421. end;
  422.  
  423.  
  424.  
  425. procedure control_break(flags,cs,ip,ax,bx,cx,dx,si,di,ds,es,bp:word);
  426.  
  427. { Interrupt routine to catch the control-break key }
  428.  
  429. interrupt;
  430.  
  431. begin
  432.   sendbreak:=true;
  433. end;
  434.  
  435.  
  436.  
  437. procedure print_screen(flags,cs,ip,ax,bx,cx,dx,si,di,ds,es,bp:word);
  438.  
  439. { Interrupt routine to catch the print-screen key }
  440.  
  441. interrupt;
  442.  
  443. begin
  444.   printscrn:=true;
  445. end;
  446.  
  447.  
  448.  
  449. procedure screen_dump;
  450.  
  451. { Print the section of the backpage buffer pointed to by screenptr (normally
  452.   the current screen) to the nominated print device }
  453.  
  454. var
  455.   i,j,k,last : integer;
  456.   was_printing : boolean;
  457.  
  458. begin
  459.   was_printing:=printer_on;
  460.   turn_printer_on;
  461.   for j:=1 to num_lines do
  462.     if screenbuf[1,(j+screenptr) mod bufsize]<>0 then
  463.       begin
  464.     last:=80;
  465.     while ((screenbuf[last,(j+screenptr) mod bufsize] and $7F) = $20)
  466.       and (last>0) do last:=last-1;
  467.         for i:=1 to last do
  468.           print(screenbuf[i,(j+screenptr) mod bufsize] and $7F);
  469.         print(13);
  470.         print(10);
  471.       end;
  472.   if was_printing then flushprintbuf(1) else turn_printer_off;
  473. end;
  474.  
  475.  
  476.  
  477. procedure feed_printer;
  478.  
  479. { Send a formfeed to the printer }
  480.  
  481. var
  482.   was_printing : boolean;
  483.  
  484. begin
  485.   was_printing:=printer_on;
  486.   turn_printer_on;
  487.   print(12);
  488.   if was_printing then flushprintbuf(1) else turn_printer_off;
  489. end;
  490.  
  491.  
  492.  
  493. procedure dump_image_file;
  494.  
  495. { Create a screen image file. }
  496.  
  497. var
  498.   i,j,last     : integer;
  499.   image        : text;
  500.  
  501. label end_of_loop;
  502.  
  503. begin
  504.   if open(image,stat_read('Image file name ...')) then
  505.     begin
  506.       for j:=1 to num_lines do
  507.     if screenbuf[1,(j+screenptr) mod bufsize]<>0 then
  508.        begin
  509.              last:=80;
  510.              while ((screenbuf[last,(j+screenptr) mod bufsize] and $7F)
  511.            = $20) and (last>0) do last:=last-1;
  512.              for i:=1 to last+1 do
  513.                begin
  514.          if (i<=last) then
  515.            write(image,chr(screenbuf[i,(j+screenptr) mod bufsize] and $7F))
  516.          else
  517.            write(image,^M+^J);
  518.                  if IOresult<>0 then
  519.            begin
  520.                      stat_write('Can''t write to image file...',1000);
  521.                      goto end_of_loop;
  522.                    end;
  523.                end;
  524.            end;
  525.     end_of_loop:
  526.       close(image);
  527.       if IOresult<>0 then
  528.         stat_write('Error closing image file...',1000);
  529.   end;
  530. end;
  531.  
  532.  
  533.  
  534. procedure run_command(cmndline:string);
  535.  
  536. { Shell to DOS }
  537.  
  538. var
  539.   x,y         : integer;
  540.   oldscrnmode : word;
  541.   oldtextattr : byte;
  542.  
  543. begin
  544.   x:=wherex;
  545.   y:=wherey;
  546.   oldtextattr:=textattr;
  547.   oldscrnmode:=lastmode;
  548.   textmode(start_mode);
  549.   textattr:=$07;
  550.   if cmndline='' then
  551.     begin
  552.       write('Shelling to DOS, type EXIT to return...');
  553.       {$IFDEF INT14}
  554.       if not paused then int14_pause;
  555.       {$ENDIF}
  556.     end;
  557.   setintvec($05,saveint05);
  558.   swapvectors;
  559.   exec(getenv('COMSPEC'),cmndline);
  560.   swapvectors;
  561.   textmode(oldscrnmode);
  562.   textattr:=oldtextattr;
  563.   clrscr;
  564.   if debug_off then
  565.     begin
  566.       setintvec($05,@print_screen);
  567.       display_screen;
  568.       gotoxy(x,y);
  569.     end;
  570.   async_clear_errors;
  571.   lastkb_stat:=$FF;             {ensures the status line gets restored}
  572. end;
  573.  
  574.  
  575.  
  576. procedure backpage(offset:integer);
  577.  
  578. { Do backpaging }
  579.  
  580. var
  581.   x,y          : integer;
  582.   oldtextattr  : byte;
  583.   oldscreenptr : integer;
  584.   keystroke    : integer;
  585.   tempstring   : string[4];
  586.  
  587. begin
  588.   x:=wherex;
  589.   y:=wherey;
  590.   oldtextattr:=textattr;
  591.   oldscreenptr:=screenptr;
  592.   screenptr:=(screenptr+bufsize-offset) mod bufsize;
  593.   {$IFDEF INT14}
  594.   if not paused then int14_pause;
  595.   {$ENDIF}
  596.   repeat
  597.     str((oldscreenptr+bufsize-screenptr) mod bufsize, tempstring);
  598.     stat_write(tempstring+' lines back, PgUp, PgDn, Home, End move, press the Space Bar to quit...',0);
  599.     display_screen;
  600.     keystroke:=ord(readkey);
  601.     if keystroke=0 then
  602.       case ord(readkey) of
  603.     19 : run_command('/c '+stat_read('Command ...'));      {Alt-R}
  604.     23 : dump_image_file;                                  {Alt-I}
  605.     24 : run_command('');                                  {Alt-O}
  606.     45 : end_now := true;                                  {Alt-X}
  607.     73,110: if (((screenptr+bufsize-oldscreenptr) mod bufsize)>=2*num_lines)
  608.           and (screenbuf[1,(screenptr+1) mod bufsize] <> 0) then
  609.           screenptr:=(screenptr+bufsize-num_lines) mod bufsize;
  610.     71:     if (((screenptr+bufsize-oldscreenptr) mod bufsize) > num_lines) and
  611.           (screenbuf[1,(screenptr+1) mod bufsize] <> 0) then
  612.           screenptr:=(screenptr+bufsize-1) mod bufsize;
  613.     81,111: screenptr:=(screenptr+num_lines) mod bufsize;
  614.     79:     screenptr:=(screenptr+1) mod bufsize;
  615.       end;
  616.     if printscrn then
  617.       begin
  618.     screen_dump;
  619.     printscrn:=false;
  620.       end;
  621.   until end_now or (keystroke<>0) or
  622.     ((screenptr+bufsize-oldscreenptr) mod bufsize<num_lines);
  623.   screenptr:=oldscreenptr;
  624.   display_screen;
  625.   gotoxy(x,y);
  626.   textattr:=oldtextattr;
  627. end;
  628.  
  629.  
  630.  
  631. procedure toggle_lines;
  632.  
  633. { Toggle in and out of 25 line mode }
  634.  
  635. var
  636.   oldx,oldy,oldlines : byte;
  637.   i,j : word;
  638.  
  639. begin
  640.   oldx:=wherex;
  641.   oldy:=wherey;
  642.   oldlines:=num_lines;
  643.   textmode(Font8x8 xor lastmode);
  644.   num_lines:=hi(windmax);
  645.   if protmode then textattr:=(bcolor shl 4) or 8 or pcolor
  646.     else textattr:=(bcolor shl 4) or 8 or fcolor;
  647.   if num_lines>oldlines then
  648.     for i:=1 to 80 do
  649.       for j:=oldlines+1 to num_lines do
  650.     screenbuf[i,(j+screenptr) mod bufsize]:=space;
  651.   if debug_off then
  652.     begin
  653.       if oldy>num_lines then
  654.     begin
  655.       screenptr:=screenptr+oldy-num_lines;
  656.       oldy:=num_lines;
  657.     end;
  658.       display_screen;
  659.       gotoxy(oldx,oldy);
  660.     end;
  661. end;
  662.  
  663.  
  664.  
  665. procedure toggle_debug;
  666.  
  667. { Toggle debugging }
  668.  
  669. begin
  670.   if debug_off then
  671.     setintvec($05,saveint05)
  672.   else
  673.     setintvec($05,@print_screen);
  674.   debug_off := not debug_off;
  675.   if debug_off then clrscr
  676.     else master_clear;
  677. end;
  678.  
  679.  
  680.  
  681. procedure toggle_capture;
  682.  
  683. { Toggle the capture file status }
  684.  
  685. begin
  686.   if capture_on then
  687.     begin
  688.       stat_write('Closing capture file...',0);
  689.       close(capture);
  690.       delay(1000);
  691.       if IOresult<>0 then
  692.         stat_write('Error closing capture file...',1000);
  693.       capture_on:=false;
  694.     end
  695.   else
  696.     capture_on:=open(capture,stat_read('Capture file name ...'));
  697. end;
  698.  
  699.  
  700.  
  701. procedure set_printer;
  702.  
  703. { Get a new destination for printing }
  704.  
  705. var
  706.   was_printing : boolean;
  707.  
  708. begin
  709.   was_printing:=printer_on;
  710.   turn_printer_off;
  711.   printer_on:=open(printer,stat_read('Set printer to ['+defprinter+'] ...'));
  712.   if not printer_on then assign(printer,defprinter);
  713.   if was_printing then turn_printer_on else turn_printer_off;
  714. end;
  715.  
  716.  
  717.  
  718. procedure findunprot;
  719.  
  720. { Find the next unprotected section of the screen }
  721.  
  722. var
  723.   i,j  : integer;
  724.  
  725. begin
  726.   i := wherex;
  727.   j := wherey;
  728.   repeat
  729.     i:=i+1;
  730.     if i=81 then
  731.       begin
  732.     i:=1;
  733.     j:=j+1;
  734.       end;
  735.   until ((i=80) and (j=num_lines)) or
  736.     ((screenbuf[i,(j+screenptr) mod bufsize] and $80)=0);
  737.   gotoxy(i,j);
  738. end;
  739.  
  740.  
  741.  
  742. procedure setup;
  743.  
  744. { Initialise the program }
  745.  
  746. var
  747.   code : integer;
  748.   i,j  : integer;
  749.   junk : char;
  750.  
  751. begin
  752.   checkbreak:=false;
  753.  
  754.   if paramcount>0 then
  755.     begin
  756.       val(paramstr(1),portnum,code);
  757.       if (code<>0) or (portnum<1) or (portnum>4) then
  758.     begin
  759.       writeln(^M+^J+'Microfusion MF30 terminal emulator.'+^M+^J);
  760.       writeln('MUFUSION [port [speed [unprotected [background [protected [printer]]]]]]'+^M+^J);
  761.       writeln('eg. MUFUSION 2                 -  use COM2.');
  762.       writeln('    MUFUSION 1 19200           -  use COM1 at 19200 bps.');
  763.       writeln('    MUFUSION 1 9600 6 1 7      -  use COM1 at 9600, yellow unprotected text,');
  764.       writeln('                                  blue background, white protected text.');
  765.       writeln('    MUFUSION 1 9600 2 0 3 COM2 -  print to COM2.'+^M+^J);
  766.       writeln('Defaults are COM1, 9600 bps, green, black, cyan, LPT1.');
  767.       halt(1);
  768.     end;
  769.     end;
  770.  
  771.   Async_Init(default,default,default,default,default);
  772.   Async_Setup_Port(portnum,default,default,default);
  773.  
  774.   if paramcount>1 then val(paramstr(2),baudrate,code);
  775.  
  776.   if not(Async_Open(portnum,baudrate,'N',8,1)) then
  777.     begin
  778.       write('Can''t find port number ',portnum,'.');
  779.       while keypressed do junk:=readkey;
  780.       halt(1);
  781.     end;
  782.  
  783.   if lo(start_mode)=mono then
  784.     begin
  785.       fcolor:=7;
  786.       bcolor:=0;
  787.       pcolor:=7;
  788.     end
  789.   else
  790.     begin
  791.       if paramcount>2 then val(paramstr(3),fcolor,code);
  792.       fcolor:=fcolor and 7;
  793.       if paramcount>3 then val(paramstr(4),bcolor,code);
  794.       bcolor:=bcolor and 7;
  795.       if paramcount>4 then val(paramstr(5),pcolor,code);
  796.       pcolor:=pcolor and 7;
  797.     end;
  798.  
  799.   Async_Clear_Errors;
  800.  
  801.   start_mode:=lastmode;
  802.   textmode(lo(start_mode));
  803.   num_lines:=hi(windmax);
  804.  
  805.   for i := 1 to 20 do fkey[i]:='';
  806.   for j:=0 to bufsize-1 do
  807.     screenbuf[1,j]:=0;
  808.  
  809.   master_clear;
  810.  
  811.   if paramcount>5 then defprinter:=paramstr(6);
  812.   assign(printer,defprinter);
  813.   turn_printer_on;
  814.   if printer_on then turn_printer_off else
  815.     stat_write('Printer '+defprinter+' is not available...',2000);
  816.  
  817.   getintvec($05,saveint05);
  818.   setintvec($05,@print_screen);
  819.   setintvec($1B,@control_break);
  820.  
  821. end;
  822.  
  823.  
  824.  
  825. function cgetc(TimeLimit : integer) : integer;
  826.  
  827. { Get a character from the COM port, and send it to the printer and capture
  828.   file as required, or return -1 if no character was found }
  829.  
  830. const
  831.   TIMED_OUT = -1;
  832. var
  833.   char_rcvd : char;
  834.  
  835. begin
  836.   {$IFDEF INT14}
  837.   if paused then int14_unpause;
  838.   {$ENDIF}
  839.  
  840.   if TimeLimit>0 then
  841.     begin
  842.       TimeLimit := 1000*TimeLimit;
  843.       repeat
  844.     delay(1);
  845.     TimeLimit:=TimeLimit-1;
  846.       until Async_Buffer_Check or (TimeLimit=0);
  847.     end;
  848.  
  849.   if (Async_Receive(char_rcvd)) then
  850.     begin
  851.       cgetc := ord(char_rcvd);
  852.       if capture_on then
  853.     begin
  854.       write(capture,char_rcvd);
  855.       if IOresult<>0 then
  856.         begin
  857.           stat_write('Can''t write to capture file...',1000);
  858.               toggle_capture;
  859.         end;
  860.     end;
  861.     end
  862.   else
  863.     cgetc := TIMED_OUT;
  864. end;
  865.  
  866.  
  867.  
  868. procedure printonly;
  869.  
  870. var
  871.   rcvd : integer;
  872.  
  873. label end_of_loop;
  874.  
  875. begin
  876.   turn_printer_on;
  877.   display_statline;
  878.   repeat
  879.     rcvd:=cgetc(0);
  880.     case rcvd of
  881.       -1,0 : {do nothing};
  882.          3 : goto end_of_loop;
  883.         27 : begin
  884.                rcvd:=cgetc(5);
  885.                case rcvd of
  886.                  0,3,27 : print(rcvd);
  887.                      70 : if cgetc(5)=66 then goto end_of_loop;
  888.                else
  889.                  print(27);
  890.                  print(rcvd);
  891.                end;
  892.              end;
  893.     else
  894.       print(rcvd);
  895.     end;
  896.   until (kb_stat and 8) <> 0;         {until Alt key pressed}
  897. end_of_loop:
  898.   flushprintbuf(numprints);
  899.   turn_printer_off;
  900. end;
  901.  
  902.  
  903.  
  904. procedure facilities;
  905.  
  906. { Implement the esc-F facilities }
  907.  
  908. var
  909.   i,k : integer;
  910.  
  911. begin
  912.   case (cgetc(5) and $7F) of
  913.     58 : endprbuf:=0;
  914.     59 : numprints:=cgetc(5);
  915.     65 : turn_printer_on;
  916.     66 : turn_printer_off;
  917.     67 : printonly;
  918.     69 : auto_echo:=true;
  919.     70 : auto_echo:=false;
  920.     77 : begin
  921.        gotoxy(lastposx,lastposy);
  922.        lastposx:=wherex;
  923.        lastposy:=wherey;
  924.      end;
  925.     87 : begin
  926.        for i:=1 to 20 do fkey[i]:='';
  927.        i:=1;
  928.        repeat
  929.          k:=cgetc(5) and $7F;
  930.          case k of
  931.            2 : if i>1 then i:=i-1;
  932.            3 : i:=i+1;
  933.            4 : {do nothing};
  934.            6 : i:=i+1;
  935.          else
  936.            if i<=20 then fkey[i]:=fkey[i]+chr(k);
  937.          end;
  938.        until k=4;
  939.        fk_defined:=true;
  940.        lastkb_stat:=$FF;             {ensures the status line gets restored}
  941.  
  942.      end;
  943.   end;
  944. end;
  945.  
  946.  
  947.  
  948. procedure escape;
  949.  
  950. { Implement the escape sequences }
  951.  
  952. var
  953.   rcvd : integer;
  954.   ch   : char;
  955.   x,y  : integer;
  956.   i,j  : integer;
  957.  
  958. begin
  959.   rcvd := cgetc(5) and $7F;
  960.   if rcvd > 0
  961.     then
  962.       begin
  963.     case rcvd of
  964.       32    : write(^H+' '+^H);           {back space destructive}
  965.       33    : begin
  966.             sound(50);
  967.             repeat until keypressed;
  968.             nosound;
  969.           end;
  970.       38    : begin
  971.             protmode:=FALSE;          {protected mode OFF}
  972.             textattr:=textattr and $F8 or fcolor
  973.           end;
  974.       39    : begin
  975.             protmode:=TRUE;           {protected mode ON}
  976.             textattr:=textattr and $F8 or pcolor
  977.           end;
  978.       40    : textattr:=textattr or 8;    {high intensity}
  979.       41    : textattr:=textattr and $F7; {low intensity}
  980.       42    : gotoxy(1,wherey+1);         {new line}
  981.       43    : master_clear;               {master clear}
  982.       44,74,89,107,111
  983.         : begin                       {clear to end of page}
  984.             i := wherex;
  985.             j := wherey;
  986.             x := wherex;
  987.             y := wherey;
  988.             repeat
  989.               if ((screenbuf[x,(y+screenptr) mod bufsize] and $80)=0)
  990.             or (protmode and (rcvd<>111)) then
  991.               begin
  992.                 screenbuf[x,(y+screenptr) mod bufsize]:=space;
  993.                 gotoxy(x,y);
  994.                 write(' ');
  995.               end;
  996.               x:=x+1;
  997.               if x=81 then
  998.             begin
  999.               x:=1;
  1000.               y:=y+1;
  1001.             end;
  1002.             until (x=80) and (y=num_lines);
  1003.             gotoxy(i,j);
  1004.           end;
  1005.       45,75,84 : if prism and printer_on and (rcvd=84) then turn_printer_off
  1006.         else
  1007.           begin                    {clear to end of line}
  1008.             i := wherex;
  1009.             j := wherey;
  1010.             x := wherex;
  1011.             y := wherey;
  1012.             repeat
  1013.               if ((screenbuf[x,(y+screenptr) mod bufsize] and $80)=0)
  1014.             or protmode then
  1015.             begin
  1016.               screenbuf[x,(y+screenptr) mod bufsize]:=space;
  1017.               gotoxy(x,y);
  1018.               write(' ');
  1019.             end;
  1020.               x:=x+1;
  1021.             until (x=81) or ((x=80) and (y=num_lines));
  1022.             gotoxy(i,j);
  1023.           end;
  1024.       49    : if protmode then            {non-reverse text}
  1025.             textattr:=(textattr and $88) or pcolor or (bcolor shl 4)
  1026.           else
  1027.             textattr:=(textattr and $88) or fcolor or (bcolor shl 4);
  1028.       50    : if protmode then            {reverse text}
  1029.             textattr:=(textattr and $88) or bcolor or (pcolor shl 4)
  1030.           else
  1031.             textattr:=(textattr and $88) or bcolor or (fcolor shl 4);
  1032.       53    : begin                       {bell}
  1033.             sound(220);
  1034.             delay(200);
  1035.             nosound;
  1036.           end;
  1037.       60    : if (wherex>1) then gotoxy(wherex-1,wherey);  {cursor left}
  1038.       61    : begin                       {goto y,x}
  1039.             y:=cgetc(5)-31;
  1040.             x:=cgetc(5)-31;
  1041.             if x>80 then x:=wherex;
  1042.             if y>num_lines then y:=wherey;
  1043.             lastposx:=wherex;
  1044.             lastposy:=wherey;
  1045.             gotoxy(x,y);
  1046.             new_line:=false;
  1047.           end;
  1048.       62    :  if wherex<80 then gotoxy(wherex+1,wherey)
  1049.              else write(^M+^J);       {cursor right}
  1050.       64    : Async_Send(^M);             {clear prism junk}
  1051.       69    : begin
  1052.             insline;                  {insert line}
  1053.             for j:=num_lines downto wherey+1 do
  1054.               for i:= 1 to 80 do
  1055.             screenbuf[i,(j+screenptr) mod bufsize]:=
  1056.               screenbuf[i,(j-1+screenptr) mod bufsize];
  1057.             for i:= 1 to 80 do
  1058.               screenbuf[i,(wherey+screenptr) mod bufsize]:=space;
  1059.           end;
  1060.       70    : facilities;                 {extended facilities}
  1061.       76    : begin
  1062.             write(^J);                {cursor down}
  1063.             if (wherey=num_lines) then
  1064.               begin
  1065.             screenptr:=(screenptr+1) mod bufsize;
  1066.             for i:=1 to 80 do
  1067.               screenbuf[i,(num_lines+screenptr) mod bufsize]:=space;
  1068.               end;
  1069.           end;
  1070.       77    : if wherey>1 then gotoxy(wherex,wherey-1);    {cursor up}
  1071.       78    : textattr:=textattr or $80;                   {blinking}
  1072.       79    : textattr:=textattr and $7F;                  {non-blinking}
  1073.       80    : screen_dump;
  1074.       82    : if prism then turn_printer_on
  1075.           else
  1076.             begin
  1077.               delline;                  {delete line}
  1078.               for j:=wherey to num_lines-1 do
  1079.             for i:= 1 to 80 do
  1080.               screenbuf[i,(j+screenptr) mod bufsize]:=
  1081.                 screenbuf[i,(j-1+screenptr) mod bufsize];
  1082.               for i:= 1 to 80 do
  1083.             screenbuf[i,(num_lines+screenptr) mod bufsize]:=space;
  1084.             end;
  1085.       90    : begin
  1086.             gotoxy(1,1);              {cursor home}
  1087.             if ((screenbuf[wherex,(wherey+screenptr) mod bufsize]
  1088.               and $80)<>0) and not protmode then
  1089.               findunprot;
  1090.           end;
  1091.       91    : begin                       {behave like a prism}
  1092.             prism:=true;
  1093.                     lastkb_stat:=$FF;         {ensures the status line}
  1094.           end;                        {gets restored}
  1095.       98    : write(^M+^J);               {go to start of next line}
  1096.       101   : begin                       {write a character n times}
  1097.             j:=cgetc(5);
  1098.             ch:=chr(cgetc(5) and $7F);
  1099.             for i:=1 to j do
  1100.               Async_Stuff(ch);
  1101.           end;
  1102.       112   : begin                       {clear field}
  1103.             x := wherex;
  1104.             y := wherey;
  1105.             while not (((screenbuf[wherex,(wherey+screenptr) mod bufsize]
  1106.               and $80)<>0) or ((wherex=80)and(wherey=num_lines))) do
  1107.             begin
  1108.               screenbuf[wherex,(wherey+screenptr) mod bufsize]
  1109.                 :=space;
  1110.               write(' ');
  1111.             end;
  1112.             gotoxy(x,y);
  1113.           end;
  1114.     end;
  1115.       end;
  1116. end;
  1117.  
  1118.  
  1119.  
  1120. var
  1121.   keystroke : char;
  1122.   rcvd      : integer;
  1123.   k         : integer;
  1124.  
  1125. begin {mufusion}
  1126.   setup;
  1127.   repeat
  1128.     if keypressed then
  1129.       begin
  1130.     keystroke:=readkey;
  1131.     if (keystroke = chr(0)) and keypressed then
  1132.       begin
  1133.         keystroke:=readkey;
  1134.         case ord(keystroke) of
  1135.           18 : toggle_debug;                                     {Alt-E}
  1136.           19 : run_command('/c '+stat_read('Command ...'));      {Alt-R}
  1137.           23 : if debug_off then dump_image_file;                {Alt-I}
  1138.           24 : run_command('');                                  {Alt-O}
  1139.           25 : if printer_on then turn_printer_off
  1140.                      else turn_printer_on;                           {Alt-P}
  1141.           31 : set_printer;                                      {Alt-S}
  1142.           32 : dial;                                             {Alt-D}
  1143.           33 : feed_printer;                                     {Alt-F}
  1144.           35 : hangup;
  1145.           38 : toggle_lines;
  1146.           45 : end_now := true;
  1147.           46 : toggle_capture;
  1148.           59..68 : Async_Send_String_With_Delays(fkey[ord(keystroke)-58],10,10);   {F1-10}
  1149.           71     : if debug_off then backpage(1);                {Home}
  1150.           72     : Async_Send(chr(24));                          {Up Arrow}
  1151.           73,110 : if debug_off then backpage(num_lines);        {PgUp,alt-F7}
  1152.           75,115 : Async_Send(chr(20));                          {Left Arrow}
  1153.           77,116 : Async_Send(chr(22));                          {Right Arrow}
  1154.           80     : Async_Send(chr(18));                          {Down Arrow}
  1155.           82     : Async_Send(chr(16));                          {Ins}
  1156.           83     : Async_Send(chr(14));                          {Del}
  1157.           84..93 : Async_Send_String_With_Delays(fkey[ord(keystroke)-73],10,10);   {shift F1-10}
  1158.           104 : Async_Send(chr(27));                             {alt-F1}
  1159.           105 : Async_Send(chr(28));                             {alt-F2}
  1160.           106 : Async_Send(chr(30));                             {alt-F3}
  1161.           107 : Async_Send(chr(29));                             {alt-F4}
  1162.           108,109 : Async_Send(chr(0));                          {alt-F5,alt-F6}
  1163.           112 : master_clear;                                    {alt-F9}
  1164.           119 : Async_Send(chr(23));                             {ctrl Home}
  1165.           117 : Async_Send(chr(17));                             {ctrl End}
  1166.           132 : Async_Send(chr(25));                             {ctrl PgUp}
  1167.           118 : Async_Send(chr(19));                             {ctrl PgDn}
  1168.         end;
  1169.       end
  1170.     else
  1171.       begin
  1172.         gen_cr:=true;
  1173.         Async_Send(keystroke);
  1174.         if auto_echo then Async_Stuff(keystroke);
  1175.       end;
  1176.       end;
  1177.  
  1178.     if not end_now
  1179.       then
  1180.     begin
  1181.  
  1182.       if sendbreak then
  1183.         begin
  1184.           Async_Send_Break;
  1185.           sendbreak:=false;
  1186.         end;
  1187.  
  1188.       if printscrn then
  1189.         begin
  1190.           screen_dump;
  1191.           printscrn:=false;
  1192.         end;
  1193.  
  1194.       rcvd := cgetc(0);
  1195.  
  1196.       if rcvd >= 0 then
  1197.         begin
  1198.           if debug_off then
  1199.         begin
  1200.                   rcvd := rcvd and $7F;
  1201.           if new_line then
  1202.             begin
  1203.               if (rcvd in [10,32..126]) then
  1204.             begin
  1205.               write(^J);
  1206.               screenptr:=(screenptr+1) mod bufsize;
  1207.               for k:=1 to 80 do
  1208.                 screenbuf[k,(num_lines+screenptr) mod bufsize]:=space;
  1209.             end;
  1210.               if not (rcvd in [0,7,10,13,16,27]) then new_line:=false;
  1211.             end;
  1212.  
  1213.           case rcvd of
  1214.  
  1215.           32..126 : begin
  1216.                   if protmode then
  1217.                 screenbuf[wherex,(wherey+screenptr) mod
  1218.                   bufsize]:=ord(rcvd)+$80
  1219.                   else
  1220.                 begin
  1221.                   if ((screenbuf[wherex,(wherey+screenptr)
  1222.                     mod bufsize] and $80)<>0) then findunprot;
  1223.                   screenbuf[wherex,(wherey+screenptr) mod
  1224.                     bufsize]:=ord(rcvd);
  1225.                 end;
  1226.                   if (wherex=80) and (wherey=num_lines) then
  1227.                 begin
  1228.                   if protmode then
  1229.                     begin
  1230.                       screenptr:=(screenptr+1) mod bufsize;
  1231.                       for k:=1 to 80 do
  1232.                     screenbuf[k,(num_lines+screenptr)
  1233.                       mod bufsize]:=space;
  1234.                     end
  1235.                   else
  1236.                     gotoxy(1,wherey);
  1237.                 end;
  1238.                   write(chr(rcvd));
  1239.                   if gen_cr and (not protmode) and
  1240.                 ((screenbuf[wherex,(wherey+screenptr)
  1241.                 mod bufsize] and $80)<>0) then
  1242.                   Async_Send(chr(13));
  1243.                 end;
  1244.            3      : turn_printer_off;
  1245.            7      : begin                              {bell}
  1246.                   sound(220);
  1247.                   delay(200);
  1248.                   nosound;
  1249.                 end;
  1250.            8      : begin
  1251.                   if wherex>1 then                   {backspace}
  1252.                 write(^H+' '+^H)
  1253.                   else if wherey>1 then
  1254.                 begin
  1255.                   gotoxy(80,wherey-1);
  1256.                   write(' ');
  1257.                   gotoxy(80,wherey-1);
  1258.                 end
  1259.                   else write(' ');
  1260.                   screenbuf[wherex,(wherey+screenptr)
  1261.                 mod bufsize]:=space;
  1262.                 end;
  1263.           10      : if wherey<num_lines then            {line feed}
  1264.                   write(^J)
  1265.                 else
  1266.                   new_line:=protmode;
  1267.           11      : begin                  {vertical address lead-in}
  1268.                   k:=cgetc(5);
  1269.                   lastposx:=wherex;
  1270.                   lastposy:=wherey;
  1271.                   if k>0 then gotoxy(wherex,(k mod 32)+1);
  1272.                 end;
  1273.           12,26   : master_clear;                      {master clear}
  1274.           13      : gotoxy(1,wherey);       {carriage return}
  1275.           16      : begin                   {horiz. address lead-in}
  1276.                   k:=cgetc(5);
  1277.                   lastposx:=wherex;
  1278.                   lastposy:=wherey;
  1279.                   gotoxy((k mod 16+10*(k div 16) mod 80)+1,wherey);
  1280.                 end;
  1281.           27      : escape;                            {escape}
  1282.  
  1283.           end;
  1284.           if (not protmode) and (rcvd<>13) and ((screenbuf[wherex,
  1285.             (wherey+screenptr) mod bufsize] and $80)<>0)
  1286.               then findunprot;
  1287.           gen_cr:=false;
  1288.                   if printer_on and (rcvd in [10,12,13,32..126]) then
  1289.                     print(rcvd);
  1290.         end
  1291.           else                                             {debug on}
  1292.         begin
  1293.           case rcvd of
  1294.             32..126 : write(chr(rcvd));                  {printable}
  1295.               11,16 : write('<',rcvd,'><',cgetc(1),'>'); {address leadin}
  1296.           else
  1297.             write('<',rcvd,'>');                       {unprintable}
  1298.           end;
  1299.         end;
  1300.             end;
  1301.     end;
  1302.  
  1303.     thiskb_stat:=kb_stat and $0F;
  1304.     if thiskb_stat<>lastkb_stat then display_statline;
  1305.     lastkb_stat:=thiskb_stat;
  1306.  
  1307.   until end_now;
  1308.  
  1309.   turn_printer_off;
  1310.   if capture_on then toggle_capture;
  1311.   setintvec($05,saveint05);
  1312.   Async_Close(false);
  1313.   textbackground(0);
  1314.   textcolor(7);
  1315.   textmode(start_mode);
  1316. end.
  1317.