home *** CD-ROM | disk | FTP | other *** search
/ ftp.update.uu.se / ftp.update.uu.se.2014.03.zip / ftp.update.uu.se / pub / rainbow / msdos / misc2 / dialv23.lzh / DIAL.PAS < prev    next >
Pascal/Delphi Source File  |  1985-09-05  |  28KB  |  921 lines

  1. Program Dial;
  2. {
  3. This program is a screen oriented Hayes SmartModem dialer for the DEC  Rainbow.
  4. It  is  written in Turbo Pascal 3.0 for DOS.  All operation has been done under
  5. DOS 2.11.  See DIAL.DOC for more details.
  6.  
  7. To Recompile this program you MUST change the Minimum and Maximum dynamic memory
  8. in the Turbo Pascal compiler.  To do this follow this sequence of commands:
  9.  
  10.         >O        ; compiler options
  11.         >C        ; select .COM file
  12.         >I        ; change minimum dynamic memory
  13.         :50       ; set it to 50
  14.         >A        ; change maximum dynamic memory
  15.         :100      ; set it to 100
  16.         >Q        ; quit
  17.         >C        ; compile a file
  18.         :DIAL     ; the name of this program
  19.  
  20. I owe much to the authors of several packages I used to  build  this:    mostly
  21. made possible by B.  Eiben of DEC, whose efforts in managing public accounts on
  22. DEC's MARKET system brought together all the tools I needed.  This  program  is
  23. placed  in the public domain and any are welcome to copy it and/or modify it as
  24. long as it is not used for any commercial purpose.
  25.  
  26. Written by Ted Weirich in July 1985.
  27. Last modified August 3, 1985.
  28.   Broken into smaller pieces.
  29.   Added environment variable support to find command.com and dial file.
  30.   Added push capability off the interrupt key.
  31.   Improve coding some.
  32.  
  33. Modified Sept. 5 1985 By David Horowitz
  34.   Added 2400 Baud support
  35.   Added Support for USRobotics 2400 Courier
  36.  
  37.  
  38.   Note: The source is now set for the USR 2400.  To set it for a hayes
  39.         modem you must change the Modem_Type Constant back to 1.
  40. }
  41.  
  42. {********************************* Type Declarations *************************}
  43.  
  44. Type
  45.   str61        = String[61];
  46.   str80        = String[80];
  47.   str127       = String[127]; {CCP command string}
  48.   str133       = String[133];
  49.   stringlong   = String[150];
  50.   str255       = String[255];
  51.   register_set = Record case Integer of
  52.                    1: (AX,BX,CX,DX,BP,SI,DI,DS,ES,Flags : INTEGER);
  53.                    2: (AL,AH,BL,BH,CL,CH,DL,DH : Byte);
  54.                  End;
  55.   dir_rec      = Record                      {Internal directory format}
  56.                    Num     : String[15];     {Phone number}
  57.                    Desc    : String[16];     {Destination description}
  58.                    DosCmd  : String[34];     {DOS cmd when party answers}
  59.                  End;
  60.  
  61.   {The following are various options you may use with Fast Video:}
  62.   fv_subfunction_type = (Char_Attrib,Attrib_Only,Char_Only);
  63.  
  64.   {This is used when changing comm port parameters}
  65.   __CommCtrlBlock = RECORD
  66.                       ModemCtrl      : Byte;
  67.                       StopBits       : Byte;
  68.                       DataBits       : Byte;
  69.                       Parity         : Byte;
  70.                       RCVBaud        : Byte;
  71.                       XMTBaud        : Byte;
  72.                       XONChar        : Byte;
  73.                       XOFFChar       : Byte;
  74.                       RCVXON         : Byte;
  75.                       XMTXON         : Byte;
  76.                       AltBufSize     : Integer;
  77.                       BuffAddrOffset : Integer;
  78.                       BuffAddrSeg    : Integer;
  79.                     End;
  80.                       
  81.   {This is used for all comm port I/O}
  82.    __IOCTLPacketType = RECORD
  83.                          Fnction   : Byte;
  84.                          Func_retC : Byte;
  85.                          Character : Char;
  86.                          Char_Stat : Byte;
  87.                          Buffer    : Byte;    {either CCB or 0}
  88.                        end;
  89.  
  90.   CommInType = RECORD           {With each character read in, there's}
  91.                  Char  : Char;  {the character itself, and a byte    }
  92.                  Error : Byte;  {indicating any data errors          }
  93.                end;
  94.                    
  95.   {These are the extended communications functions}
  96.    __SubFunction = ( ProgramDev, ProgramDefault, SetDefBuf,
  97.                      ReadDevSetup, EnableRecvIntr, DisableRecvIntr,
  98.                      ReadInStat, ReadChar, GetChar, ReadOutStat,
  99.                      WriteChar, PutChar, XMTImmed, ReadModem,
  100.                      SetModem, XMTBreak, StopBreak, SetRecvIntr,
  101.                      ResetRecvIntr, EmptyBufIntr, ResetEmptyBufIntr,
  102.                      SetIntrRoutine, ResetDevIntr );
  103.  
  104.   ParityType = ( NoChange, Even, Odd, None );  {Possible parity values}
  105.   DataBitsType = (DBNoChange, DB5, DB6, DB7, DB8, DB7S, DB7M );
  106.  
  107. {*************************** Constant Declarations *************************}
  108.  
  109. Const
  110.  
  111.   version_string  = 'Turbo DIAL V2.3 for DOS and the DEC Rainbow, 3-Aug-1985';
  112.   Modem_Type             = 2;         {Hayes    = 1}
  113.                                       {USR 2400 = 2}
  114.   Dial_File              = 'dialnum.txt';
  115.   Successful             = 255;
  116.   Unsuccessful           = 0;
  117.   max_dir_entries        = 100;       {Max # of phone numbers in dir table}
  118.   fsl                    = 4;         {first line written on screen}
  119.   lsl                    = 22;        {last line written on screen}
  120.   nls                    = 19;        {Number of lines on the screen}
  121.   hayes_delay            = 50;        {ms we wait between sending chars to}
  122.                                       {the Hayes SmartModem}
  123.   USR2400_delay          = 50;
  124.   msg_delay              = 1000;      {time we wait while user reads the}
  125.                                       {warning or fatal message}
  126.   autobaud_char          = 13;        {send this char nauto_times for good con}
  127.   nauto_times            = 3;         {send autobaud_char this many times}
  128.  
  129.   {$I FVCONST.INC }
  130.  
  131.   {codes returned on a level 1 keyboard input call - hex}
  132.  
  133.   {$I KEYDFNS.INC }
  134.  
  135.  
  136. {**************************** Variable Declarations *************************}
  137.  
  138. Var
  139.   mcode             : integer;
  140.   dirfil            : Text;
  141.   commandline       : Str255;
  142.   dir_entry         : Array[1..Max_Dir_Entries] of Dir_Rec;
  143.   max_dir_ent       : integer;
  144.   cur_dir_ent       : integer;
  145.   top_dir_ent       : integer;
  146.   bot_dir_ent       : integer;
  147.   keepgoing         : Boolean;
  148.   TextToPrint       : Str133;
  149.   lv1_fnc           : boolean;
  150.   lv1_shft          : boolean;
  151.   lv1_ctrl          : boolean;
  152.   lv1_caps          : boolean;
  153.   dummylogical      : boolean;
  154.   Regs              : Register_Set;
  155.   i                 : integer;
  156.  
  157.   {Storage for the comm port stuff}
  158.  
  159.   __Buffer1             : String[255];        {The next 2 lines set up comm}
  160.   __Buffer2             : String[255];        {data buffer of 512 bytes    }
  161.   DefaultBaud           : Integer;
  162.   DefaultDataBits       : DataBitsType;
  163.   DefaultParity         : ParityType;
  164.   DefaultStopBits       : Real;
  165.   CommIn                : CommInType;
  166.   __SetSerialIO         : __IOCTLPacketType;  {These two variables must be}
  167.   __CCB                 : __CommCtrlBlock;    {defined contiguously.      }
  168.   __IOCTLPacket         : __IOCTLPacketType;
  169.  
  170.  
  171. {******************************* Misc or Global Functions *******************}
  172.  
  173. {$I FINDENV.INC }
  174.  
  175.  
  176. Procedure Execute_Command ( command_line : Str255 ) ; Forward;
  177.  
  178.  
  179. Function IMIN( x : Integer; y : Integer) : Integer;
  180. {
  181. Return the maximum of two integers.
  182. }
  183. Begin
  184.   If x <= y Then IMIN := x Else IMIN := y;
  185. End;
  186.  
  187.  
  188. Function IMAX( x : Integer; y : Integer) : Integer;
  189. {
  190. Return the minimum of two integers
  191. }
  192. Begin
  193.   If x >= y Then IMAX := x Else IMAX := y;
  194. End;
  195.  
  196.  
  197. {$V-}
  198. Function StrMatch( S1 : Str255; S2 : Str255 ) : Boolean;
  199. {
  200. Use this function to compare two strings of perhaps unequal length without
  201. regard for case.  Note, anything matches the null string.
  202. }
  203. Var
  204.   i      : Integer;
  205.   result : Boolean;
  206. Begin
  207.   i := 1;
  208.   result := true;
  209.   While (i <= Length(S1)) and (i <= Length(S2)) and result Do
  210.     Begin
  211.       result := (UpCase(S1[i]) = UpCase(S2[i]));
  212.       i := i + 1;
  213.     End;
  214.   StrMatch := result;
  215. End;
  216. {$V+}
  217.  
  218.  
  219. {******************************* Comm Port Routines *************************}
  220. {
  221. The following routines were taken from COMLIB.INC as found in the TC package
  222. (Rainbow VT220 emulator) on MARKET.  Thanks.
  223. }
  224.  
  225. {$I COMMLIB.INC }
  226.  
  227. {*************************** Keyboard Input Routines *************************}
  228. {
  229. Antique LCTERM sources, FUNKEY.PAS, and other examples form the basis for
  230. the following routines for level 1 and 2 keyboard input.  Thanks.
  231. }
  232.  
  233. {$I KEYBOARD.INC }
  234.  
  235. {*************************** Fast Video Routines *****************************}
  236. {
  237. The example FASTVID.PAS from MARKET is the basis for the following routine.
  238. }
  239.  
  240.  
  241. Procedure FastVideo (VAR Text : Str133; Attrib : BYTE;
  242.                          Subfunc : FV_Subfunction_type;
  243.                          TextLength, TRow, TCol : INTEGER);
  244. {
  245. This procedure sends a line to the screen via the high  speed  video  firmware.
  246.  
  247. Sample Call:
  248.  
  249.   TextToPrint := 'aBcDeFgHiJkLmNoPqRsTuVwXyZAbCdEfGhIjKlMnOpQrStUvWxYz';
  250.   Attributes := FUnder;
  251.   FV_Subfunction := Char_Attrib;
  252.   TextToPrintLength := LENGTH(TextToPrint);
  253.   FastVideo(TextToPrint, Attributes, FV_Subfunction,TextToPrintLength,Row,Col);
  254.  
  255. In order to write to (1,1), you must disable the cursor.
  256.  
  257. The routine to turn off the cursor is:    Result.DI := 8;
  258.                                           Intr(24,Result);
  259. To reenable the cursor:                   Result.DI := 10;
  260.                                           Intr(24,Result);
  261. }
  262.  
  263. Const
  264.   FastVidDI : INTEGER = 20;   {Subfunction in DI to call Fast Video function}
  265. Var
  266.   TextString, AttributeString : Str133; {Need to set up these locals}
  267.                                         {so they are in the same}
  268.                                         {data segment area.}
  269.   Result : Register_Set;  {Data registers used for MSDOS interrupts}
  270.   J  : Integer;
  271. Begin
  272.   {Fill up attribute string with codes. One extra byte to fill it out}
  273.   For J := 1 to Textlength+1 do AttributeString[j] := chr(Attrib);
  274.   AttributeString[0] := chr(Textlength+1);
  275.   TextString := Text;
  276.   With Result Do Begin  {Load up the necessary registers.}
  277.     AX := Ord(Subfunc); {Put the Subfunction selection into the AX Reg}
  278.     {Put the row and col # into lower BX and upper BX respectively}
  279.     Mem[Seg(BX) : Ofs(BX)] := TRow;
  280.     Mem[Seg(BX) : Ofs(BX) + 1] := TCol;
  281.     {Put the length of the string (or its attributes) in CX}
  282.     CX := TextLength;
  283.     {Stuff the offsets of the text & attribute strings in SI & DX}
  284.     {Add 1 to them to get past the length byte in [0]}
  285.     DX := Ofs(AttributeString) + 1;
  286.     SI := Ofs(TextString) + 1;
  287.     {Make sure the Base Pointer shows the Segment of the strings. These}
  288.     {MUST be in the same segment,  This is why we set up the local variables.}
  289.     BP := SEG(TextString);
  290.     DI := FastVidDI;   {Put the proper value into the DI Reg for Fast Video.}
  291.   End;
  292.   INTR(24,Result);
  293. End; {Procedure FastVideo}
  294.  
  295.  
  296. Procedure ClearVidLine( l : integer);
  297. {
  298. Use this instead of TURBO's CLREOL for erasing a line on the screen.
  299. }
  300. Var
  301.   tt : Str133;
  302. Begin
  303.   If (l >= 1) and (l <= 24) Then
  304.     Begin
  305.       If l = 1 Then
  306.         Begin
  307.           Regs.DI := 8;       {Turn cursor off}
  308.           Intr(24,Regs);
  309.         End;
  310.       FillChar(tt,81,' ');
  311.       tt[0] := char(80);
  312.       FastVideo(tt, FNormal, Char_Attrib, 80, l, 1);
  313.       If l = 1 Then
  314.         Begin
  315.           Regs.DI := 10;      {Turn cursor back on}
  316.           Intr(24,Regs);
  317.         End;
  318.     End;
  319. End;
  320.  
  321.  
  322. {$V-}
  323. Procedure MsgLine(t:str133;Atr:Byte);
  324. {
  325. Use this procedure to write info on line 24, text centered.  Position 
  326. the cursor just after the text.
  327. }
  328. Var
  329.   x,y : Integer;
  330.   tt  : Str133;
  331. Begin
  332.   ClearVidLine(24);
  333.   x  := length(t);
  334.   y  := (80-x) div 2;
  335.   tt := t;
  336.   FastVideo(tt, atr, char_Attrib, x, 24, y);
  337.   GotoXY(x+y+1,24);
  338.   Delay(msg_delay);
  339. End;
  340. {$V+}
  341.  
  342.  
  343. Procedure ReverseLine(line:integer);
  344. {
  345. Use this procedure to set an existing line with data on it to reverse video
  346. This line is assumed to be a phone entry line, and we don't overwrite the
  347. "static" information written by DrawBox.
  348. }
  349. Var
  350.   x  : integer;
  351.   tt : Str133;
  352. Begin
  353.   x := cur_dir_ent - top_dir_ent + fsl;
  354.   FillChar(tt,75,' ');
  355.   tt[0] := char(75);
  356.   FastVideo(tt, FReverse, Attrib_Only, 75, x, 5);
  357. End;
  358.  
  359.  
  360. Procedure NormalLine(line:integer);
  361. {
  362. Use this procedure to set an existing line with data on it to normal video
  363. See ReverseLine for more information.
  364. }
  365. Var
  366.   x  : integer;
  367.   tt : Str133;
  368. Begin
  369.   x := cur_dir_ent - top_dir_ent + fsl;
  370.   FillChar(tt,75,' ');
  371.   tt[0] := char(75);
  372.   FastVideo(tt, FNormal, Attrib_Only, 75, x, 5);
  373. End;
  374.  
  375.  
  376. Procedure DrawBox;
  377. {
  378. Draw a border around the screen and put titles in it, ready for directory data.
  379. }
  380. Var
  381.   j  : Integer;
  382.   fc : Char;
  383.   tt : Str133;
  384. Begin
  385.   Regs.DI := 8;        {Disable cursor so we can write at (1,1)}
  386.   Intr(24,Regs);
  387.   Clrscr;
  388.  
  389.   fc := chr(fm_horz);  {Write top side of box}
  390.   FillChar(tt,80,fc);
  391.   tt[0] := chr(80);
  392.   tt[1] := chr(fm_ulc);
  393.   tt[80] := chr(fm_urc);
  394.   FastVideo(tt, FNormal,Char_Attrib, 80, 1, 1);
  395.  
  396.   FillChar(tt,80,' ');
  397.   tt[0] := chr(80);
  398.   tt[1] := chr(fm_vert);
  399.   tt[80] := chr(fm_vert);
  400.   FastVideo(tt, FNormal, Char_Attrib, 80, 2,1);
  401.  
  402.   tt := '   Telephone         Description               Dos Command';
  403.   tt := tt + '                    ';
  404.   tt[0] := chr(78);
  405.   FastVideo(tt, FReverse, Char_Attrib, 78, 2,2);
  406.  
  407.   fc := chr(fm_horz);
  408.   FillChar(tt,80,fc);
  409.   tt[0] := chr(80);
  410.   tt[1] := chr(fm_ltee); {Write line under titles, line 3}
  411.   tt[3] := chr(fm_ttee);
  412.   tt[80] := chr(fm_rtee);
  413.   FastVideo(tt, FNormal,Char_Attrib, 80, 3, 1);
  414.  
  415.   tt := '    ';
  416.   tt[1] := chr(fm_vert); {Write sides of box}
  417.   tt[3] := chr(fm_vert);
  418.   for j := fsl to lsl do begin
  419.     tt[2] := chr(j-fsl+65);
  420.     FastVideo(tt, FNormal, Char_Attrib, 4, j,  1);
  421.     FastVideo(tt, FNormal, Char_Attrib, 1, j, 80);
  422.   end;
  423.  
  424.   fc := chr(fm_horz);
  425.   FillChar(tt,80,fc);
  426.   tt[1] := chr(fm_llc);  {Write bottom side of box}
  427.   tt[3] := chr(fm_btee);
  428.   tt[80] := chr(fm_lrc);
  429.   tt[0] := chr(80);
  430.   FastVideo(tt, FNormal,Char_Attrib, 80, 23, 1);
  431.  
  432.   Regs.DI := 10;    {Re-enable cursor}
  433.   Intr(24,Regs);
  434. End; {Procedure DrawBox}
  435.  
  436.  
  437. Procedure PaintScreen(top:integer;cur:integer);
  438. {
  439. Fill the box with directory data.  We starting writing with entry top and when
  440. done, reverse video the entry cur.
  441. }
  442. Var
  443.   i, j, ndx, l, ttp  : integer;
  444.   tt                 : Str133;
  445. Begin
  446.   DrawBox;
  447.   ndx := top;
  448.   top_dir_ent := top;
  449.   For i := 1 to nls do begin
  450.     If i > max_dir_ent Then l := 0 Else l := length(dir_entry[ndx].num);
  451.     If l > 0 Then
  452.       Begin
  453.         tt := dir_entry[ndx].num;
  454.         FastVideo(tt, FNormal, Char_Attrib, Length(tt), i+fsl-1, 5);
  455.         tt := dir_entry[ndx].desc;
  456.         FastVideo(tt, FNormal, Char_Attrib, Length(tt), i+fsl-1, 20);
  457.         tt := dir_entry[ndx].doscmd;
  458.         FastVideo(tt, FNormal, Char_Attrib, Length(tt), i+fsl-1, 40);
  459.         bot_dir_ent := ndx;
  460.       End
  461.     Else
  462.       Begin
  463.         FillChar(tt,80,' ');
  464.         tt[0] := chr(75);
  465.         FastVideo(tt, FNormal,Char_Attrib, 75, i+fsl-1, 5);
  466.       End;
  467.     ndx := ndx + 1;
  468.   End;
  469.   ReverseLine(cur);
  470. End;
  471.  
  472.  
  473. {***************************** Phone Directory Routines **********************}
  474.  
  475. Function ReadDirectory : Boolean;
  476. {
  477. Read the disk file and remember all the entries in the in-core data structure
  478. Return true if we read the file and had no major problems, false if the caller
  479. shouldn't proceed.
  480. }
  481. Var
  482.   i             : Integer;
  483.   typ_char      : char;
  484.   sep_char      : char;
  485.   rec_data      : string[70];
  486.   file_name     : str255;
  487.   result        : Boolean;
  488. Begin
  489.   result := true;
  490.   For i := 1 to max_dir_entries do
  491.     with dir_entry[i] do begin
  492.       num    := '';
  493.       desc   := '';
  494.       doscmd := '';
  495.     end;
  496.   file_name := 'DIAL';
  497.   file_name := find_env(file_name) + dial_file;
  498.   Assign(dirfil,file_name);
  499.     {$I-}  Reset(dirfil);  {$I+}
  500.   i := IOResult;
  501.   If i <> 0 Then 
  502.     Begin
  503.       Str(i,rec_data);
  504.       MsgLine(('?? Error opening directory file = '+rec_data+ ' ??'),FBoldBlink);
  505.       result := false;
  506.     End
  507.   Else
  508.     Begin
  509.       i := 0;
  510.       Repeat
  511.         Begin
  512.           Readln(dirfil,rec_data);
  513.           typ_char := UpCase(rec_data[1]);
  514.           rec_data := Copy(rec_data,3,Length(rec_data));
  515.           Case typ_char of
  516.             ';' : Begin    {comment line, do nothing}
  517.                   End;
  518.             '!' : Begin    {comment line, do nothing}
  519.                   End;
  520.             ' ' : Begin
  521.                   End;
  522.             'N' : Begin    {phone number.  bump index and remember #}
  523.                     i := i + 1;
  524.                     dir_entry[i].num := rec_data;
  525.                   End;
  526.             'D' : Begin    {description of destination/number}
  527.                     dir_entry[i].desc := rec_data;
  528.                   End;
  529.             'C' : Begin    {command passed to DOS upon successful dialing}
  530.                     dir_entry[i].doscmd := rec_data;
  531.                   End;
  532.             Else  Begin    {i don't know what to do with this}
  533.                     Str(i,rec_data);
  534.                     MsgLine(('?? Bad record type char ('+typ_char+') at rec '+rec_data+' ??'),FBoldBlink);
  535.                   End;
  536.           End;
  537.         End;
  538.       Until ((Eof(dirfil)) or (i > max_dir_entries));
  539.       Close(dirfil);
  540.       cur_dir_ent := 1;
  541.       If i > max_dir_entries then
  542.         Begin
  543.           MsgLine('%% Phone dir truncated - increase max_dir_entries. %%',FBoldBlink);
  544.           max_dir_ent := i - 1;
  545.         End
  546.       Else max_dir_ent := i;
  547.     End;
  548.   ReadDirectory := result;
  549. End; {Function Read_Directory}
  550.  
  551.  
  552. Function PickDefault : Integer;
  553. {
  554. This function sees if there is a command tail.  If so, see if we can find it in
  555. the descriptions field of the phone directory.  If a match, then use that as
  556. the default entry.  If not, or no command tail, set default entry to 1.
  557. }
  558. Var
  559.   n  : integer;
  560.   s  : string[16];
  561. Begin
  562.   PickDefault := 1;
  563.   n := Paramcount;
  564.   If n > 0 Then
  565.     Begin
  566.       s := ParamStr(1);
  567.       For n := 1 to max_dir_ent Do
  568.         If StrMatch(s,dir_entry[n].desc) Then PickDefault := n;
  569.     End;
  570. End;
  571.  
  572.  
  573. {*************************** Help Routines *******************************}
  574. {
  575. There is a doc file also, but these should help refresh someone's memory.
  576. }
  577.  
  578. {$I HELP.INC }
  579.  
  580.  
  581. {******************** User Entry Selection Routines **************************}
  582.  
  583. Procedure WriteSelection(num:integer);
  584. {
  585. Write the user's current selection where it's supposed to be.  We don't use the
  586. MsgLine routine here because we don't want the delay.
  587. }
  588. Var
  589.   x,y : Integer;
  590.   tt  : Str133;
  591. Begin
  592.   ClearVidLine(24);
  593.   tt := 'Enter your selection: ' + chr(cur_dir_ent-top_dir_ent+65);
  594.   x  := length(tt);
  595.   y  := (80-x) div 2;
  596.   FastVideo(tt, FBold, Char_Attrib, x, 24, y);
  597.   GotoXY(x+y+1,24);
  598. End;
  599.  
  600.  
  601. Procedure Do_PrevLine;
  602. {
  603. Called by getsel to highlight the previous entry line.
  604. }
  605. Var
  606.   j : integer;
  607. Begin
  608.   j := cur_dir_ent - 1;
  609.   If j < top_dir_ent Then
  610.     Begin
  611.       If j >= 1 Then
  612.         Begin
  613.           cur_dir_ent := j;
  614.           J := IMAX((cur_dir_ent-nls+1),1);
  615.           PaintScreen(j,cur_dir_ent);
  616.           WriteSelection(cur_dir_ent);
  617.         End;
  618.     End
  619.   Else
  620.     Begin
  621.       NormalLine(cur_dir_ent);
  622.       cur_dir_ent := j;
  623.       ReverseLine(cur_dir_ent);
  624.       WriteSelection(cur_dir_ent);
  625.     End;
  626. End;
  627.  
  628.  
  629. Procedure Do_PrevScreen;
  630. {
  631. Called by getsel to paint the previous screen of entries.
  632. }
  633. Begin
  634.   If lv1_shft Then
  635.     Begin
  636.       cur_dir_ent := 1;
  637.       PaintScreen(cur_dir_ent,cur_dir_ent);
  638.       WriteSelection(cur_dir_ent);
  639.     End
  640.   Else
  641.     Begin
  642.       cur_dir_ent := IMAX((cur_dir_ent-nls),1);
  643.       top_dir_ent := IMAX((top_dir_ent-nls),1);
  644.       PaintScreen(top_dir_ent,cur_dir_ent);
  645.       WriteSelection(cur_dir_ent);
  646.     End;
  647. End;
  648.  
  649.  
  650. Procedure Do_NextLine;
  651. {
  652. Called by getsel to highlight the next entry line.
  653. }
  654. Var
  655.   j : integer;
  656. Begin
  657.   j := cur_dir_ent + 1;
  658.   If j > bot_dir_ent Then
  659.     Begin
  660.       If j <= max_dir_ent Then
  661.         Begin
  662.           cur_dir_ent := j;
  663.           PaintScreen(cur_dir_ent,cur_dir_ent);
  664.           WriteSelection(cur_dir_ent);
  665.         End;
  666.     End
  667.   Else
  668.     Begin
  669.       NormalLine(cur_dir_ent);
  670.       cur_dir_ent := j;
  671.       ReverseLine(cur_dir_ent);
  672.       WriteSelection(cur_dir_ent);
  673.     End;
  674. End;
  675.  
  676.  
  677. Procedure Do_NextScreen;
  678. {
  679. Called by getsel to paint the next screen of entries.
  680. }
  681. Begin
  682.   If lv1_shft Then
  683.     Begin
  684.       top_dir_ent := max_dir_ent - nls + 1;
  685.       If (cur_dir_ent+nls <= max_dir_ent) And
  686.          (cur_dir_ent+nls > top_dir_ent)
  687.          Then cur_dir_ent := cur_dir_ent + nls
  688.            Else cur_dir_ent := top_dir_ent;
  689.       PaintScreen(cur_dir_ent,cur_dir_ent);
  690.       WriteSelection(cur_dir_ent);
  691.     End
  692.   Else
  693.     Begin
  694.       cur_dir_ent := IMIN((cur_dir_ent+nls),max_dir_ent-nls+1);
  695.       top_dir_ent := IMIN((top_dir_ent+nls),max_dir_ent-nls+1);
  696.       PaintScreen(top_dir_ent,cur_dir_ent);
  697.       WriteSelection(cur_dir_ent);
  698.     End;
  699. End;
  700.  
  701.  
  702. Procedure Push;
  703. {
  704. Here bacause the user used the interrupt key to get a lower shell to type DOS
  705. commands to.
  706. }
  707. Begin
  708.   ClrScr;
  709.   MsgLine('Pushing to lower shell, type EXIT to return',FNormal);
  710.   Execute_Command('');
  711.   PaintScreen(cur_dir_ent,cur_dir_ent);
  712.   WriteSelection(cur_dir_ent);
  713. End;
  714.  
  715.  
  716. Function GetSel : Char;
  717. {
  718. Get the user's entry selection.
  719.  
  720.         Uparrow                 highlight previous entry
  721.         Downarrow               highlight next entry
  722.         Previous screen         back up one screen of entries
  723.         Shift previous screen   Go to top of entry list
  724.         Next screen             Advance one screen of entries
  725.         Shift next screen       Go to end of list of entries
  726.         Do                      Use selected entry
  727.         Return                  Use selected entry
  728.         Interrupt               Push to lower shell
  729.         Cancel                  Hangup the modem
  730.         Help                    Help the user a little
  731.         Space                   Exit
  732.         Exit                    Exit
  733. }
  734. Var
  735.   x               : Integer;
  736.   rc              : Integer;
  737.   ch              : Char;
  738.   result          : Boolean;
  739.   valid_selection : Boolean;
  740. Begin
  741.   WriteSelection(cur_dir_ent);
  742.   Repeat
  743.     Begin
  744.       valid_selection := false;
  745.       rc := level1key;
  746.       ch := UpCase(chr(rc));
  747.       case rc of
  748.         key_help:       Begin
  749.                           help_user;
  750.                           DrawBox;
  751.                           PaintScreen(cur_dir_ent,cur_dir_ent);
  752.                           WriteSelection(cur_dir_ent);
  753.                         End;
  754.         key_exit:       Begin
  755.                           ch := ' ';
  756.                           rc := ord(ch);
  757.                           valid_selection := true;
  758.                         End;
  759.         key_prevscreen: Do_PrevScreen;
  760.         Key_nextscreen: Do_NextScreen;
  761.         key_downarrow:  Do_NextLine;
  762.         key_uparrow:    Do_PrevLine;
  763.         65..83,97..115: Begin
  764.                           x := bot_dir_ent - top_dir_ent + 65;
  765.                           If ch <= chr(x) Then
  766.                             Begin
  767.                               NormalLine(cur_dir_ent);
  768.                               cur_dir_ent := ord(ch) - 65 + top_dir_ent;
  769.                               WriteSelection(cur_dir_ent);
  770.                               ReverseLine(cur_dir_ent);
  771.                             End;
  772.                         End;
  773.         Key_Do, 13, 32: valid_selection := true;
  774.         Key_Cancel:     Result := DisconnectModem;
  775.         Key_Interrupt:  Push;
  776.         Else            Write(chr(7));
  777.       End;
  778.     End;
  779.   Until valid_selection;
  780.   Getsel := ch;
  781. End;
  782.  
  783.  
  784. {******************** Common Modem Service Routines ***************************}
  785.  
  786. Procedure WrtModemRsp( mrc : integer );
  787. {
  788. Write the modem's response on the information line.  This is really modem
  789. independent but is places here for commonality sake for all to use.  When you
  790. add your own modem type, please have its return response code routine return
  791. one of the following.
  792. }
  793. Var
  794.   rspstr : String[10];
  795. Begin
  796.   Str(mrc,rspstr);
  797.   ClearVidLine(24);
  798.   Case mrc of
  799.     -1 : MsgLine('Modem response timeout',FBlink);
  800.     0  : MsgLine('Modem responded OK',FBlink);
  801.     1  : MsgLine('300 baud Connection',FBlink);
  802.     2  : MsgLine('Ring detected',FBlink);
  803.     3  : MsgLine('No Connection',FBlink);
  804.     4  : MsgLine('Error in Command',FBlink);
  805.     5  : MsgLine('1200 baud Connection',FBlink);
  806.     6  : MsgLine('2400 baud Connection',FBlink);
  807.     Else MsgLine(('Unknown modem response - '+rspstr),FBlink);
  808.   End;
  809. End; {Procedure WrtModemRsp}
  810.  
  811.  
  812. {************************** Hayes Specific Modem Routines *********************}
  813.  
  814. {$I HAYES.INC }
  815.  
  816. {************************** USR Specific Modem Routines ***********************}
  817.  
  818. {$I USR2400.INC }
  819.  
  820. {**************************** Modem Indpendent Routines *********************}
  821. {
  822. These are the programs interfact to modem specific routines.  The actual work
  823. is done in the Hayes group for instance, but they are not called directly.
  824. }
  825.  
  826. Function GetModemRsp( secs : Integer ) : Integer;
  827. {
  828. Use this function to get the modem's response for any given command.  Response
  829. is returned as an integer value 0 through 5.  Call with the maximum number of
  830. seconds you wish to wait.
  831. }
  832. Begin
  833.   Case Modem_Type of
  834.     1 : GetModemRsp := GetHayesRsp(secs);
  835.     2 : GetModemRsp := GetUSR2400rsp(secs);
  836.   End;
  837. End;
  838.  
  839.  
  840. Function InitModem : Boolean;
  841. {
  842. Initialize the modem.  Return false if this failed so top level can abort.
  843. }
  844. Begin
  845.   Case Modem_Type of
  846.     1 : InitModem := InitHayes;
  847.     2 : InitModem := InitUSR2400;
  848.   End;
  849. End;
  850.  
  851.  
  852. Procedure DialModem;
  853. {
  854. Dial the modem with the user selected string.
  855. }
  856. Begin
  857.   Case Modem_Type of
  858.     1 : DialHayes;
  859.     2 : DialUSR2400;
  860.   End;
  861. End;
  862.  
  863.  
  864. {****************************** Execute DOS Command Routines ****************}
  865.  
  866. {$I EXECUTE.INC }
  867.  
  868.  
  869. {**************************** Main Program **********************************}
  870.  
  871. Begin
  872.   CrtInit;
  873.   ClrScr;
  874.  
  875.   {Introduce ourselves}
  876.  
  877.   texttoprint := version_string;
  878.   FastVideo(texttoprint, FBold, Char_Attrib, length(texttoprint), 1, 11);
  879.   MsgLine('Use the HELP key for assistence',FBlink);
  880.  
  881.  
  882.   keepgoing := ReadDirectory;
  883.   cur_dir_ent := pickdefault;
  884.   top_dir_ent := IMAX((cur_dir_ent-(nls div 2 + 1)),1);
  885.   While keepgoing Do
  886.     Begin
  887.       PaintScreen(top_dir_ent,cur_dir_ent);
  888.       If Getsel = ' ' THEN keepgoing := false;
  889.       If keepgoing Then
  890.         Begin
  891.           If InitModem Then
  892.             Begin
  893.               DialModem;
  894.               mcode := GetModemRsp(60);
  895.               WrtModemRsp(mcode);
  896.               If ((mcode = 1) or (mcode = 5) or (mcode = 6)) THEN
  897.                 Begin
  898.                   ClrScr;
  899.                   For i := 1 to nauto_times Do
  900.                     dummylogical := WriteCommChar(Chr(autobaud_char));
  901.                   Case mcode of
  902.                     6: dummylogical := SetSerial(3,2400,1,DB7S,none,Chr(0));
  903.                     5: dummylogical := SetSerial(3,1200,1,DB7S,none,Chr(0));
  904.                     1: dummylogical := SetSerial(3,0300,1,DB7S,none,Chr(0));
  905.                   end;
  906.                   commandline := dir_entry[cur_dir_ent].doscmd;
  907.                   Execute_Command(commandline);
  908.                 End;
  909.             End
  910.           Else
  911.             Begin
  912.               MsgLine('?? Could not initialize your modem ??',FBoldBlink);
  913.               keepgoing := false;
  914.             End;
  915.         End;
  916.     End;
  917.   Dummylogical := ReplaceDefault;
  918.   ClrScr;
  919.   CrtExit;
  920. End.
  921.