home *** CD-ROM | disk | FTP | other *** search
/ Between Heaven & Hell 2 / BetweenHeavenHell.cdr / 500 / 433 / pyserial.inc < prev    next >
Text File  |  1986-12-23  |  20KB  |  808 lines

  1. FUNCTION GotCarrier : BOOLEAN;
  2. BEGIN
  3.   IF NOT Comm
  4.   THEN GotCarrier := FALSE
  5.   ELSE
  6.   BEGIN
  7.     IF (PORT[ModemStatus] AND $80) > 0
  8.     THEN GotCarrier := TRUE
  9.     ELSE GotCarrier := FALSE;
  10.   END;
  11. END;
  12.  
  13. PROCEDURE SetBaud(BaudRate : INTEGER);
  14. BEGIN
  15.   IF Comm THEN
  16.   BEGIN
  17.     PORT[IntReg]      := 0;
  18.     PORT[LineContrl]  := $80;
  19.     PORT[LowBaud]     := LO(TRUNC(BaudConst / BaudRate));
  20.     PORT[HighBaud]    := HI(TRUNC(BaudConst / BaudRate));
  21.     PORT[LineContrl]  := 3;
  22.     PORT[ModemContrl] := 3;
  23.   END;
  24. END;
  25.  
  26. FUNCTION GotComChar : BOOLEAN;
  27. BEGIN
  28.   GotComChar := FALSE;
  29.   IF Comm THEN IF ((PORT[StatusPort] AND RReady) > 0)
  30.   THEN GotComChar := TRUE;
  31. END;
  32.  
  33. FUNCTION TransmitReady : BOOLEAN;
  34. BEGIN
  35.   TransmitReady := FALSE;
  36.   IF Comm THEN IF ((PORT[StatusPort] AND TReady) <> 0)
  37.   THEN TransmitReady := TRUE;
  38. END;
  39.  
  40. FUNCTION AnyKeyPressed : BOOLEAN;
  41. BEGIN
  42.   AnyKeyPressed := FALSE;
  43.   IF GotComChar THEN AnyKeyPressed := TRUE;
  44.   IF KEYPRESSED THEN AnyKeyPressed := TRUE;
  45. END;
  46.  
  47. FUNCTION LostCarrier : BOOLEAN;
  48. BEGIN
  49.   LostCarrier := FALSE;
  50.   IF Comm THEN IF HadCarrier <> GotCarrier THEN LostCarrier := TRUE;
  51. END;
  52.  
  53. FUNCTION SerialIn : CHAR;
  54. VAR
  55.   CHARIn    : CHAR;
  56.   CmdChar   : CHAR;
  57.   GotEvent  : BOOLEAN;
  58.   TimeInner : INTEGER;
  59.   TimeOut   : BOOLEAN;
  60.   TimeOuter : INTEGER;
  61. BEGIN
  62.   {----- Loop until something other than a FnKey request -----}
  63.   REPEAT
  64.     TimeInner := 0;
  65.     TimeOut   := FALSE;
  66.     TimeOuter := 0;
  67.     GotEvent  := FALSE;
  68.     {--- Wait for a char or event from somewhere ---}
  69.     REPEAT
  70.       TimeInner := TimeInner + 1;
  71.       IF TimeInner = 3000 THEN
  72.       BEGIN
  73.         TimeInner := 0;
  74.         TimeOuter := TimeOuter + 1;
  75.         IF TimeOuter = TimeOutSecs THEN TimeOut := TRUE;
  76.       END;
  77.       IF AnyKeyPressed OR LostCarrier OR TimeOut OR SysFail  THEN GotEvent := TRUE;
  78.     UNTIL GotEvent;
  79.     {--- Process the event ---}
  80.     IF LostCarrier OR TimeOut OR SysFail THEN
  81.     BEGIN
  82.       IF LostCarrier OR (TimeOutCntr > 3) THEN Logoff := TRUE;
  83.       IF TimeOut THEN TimeOutCntr := TimeOutCntr + 1;
  84.       CHARIn := ^M;
  85.     END
  86.     ELSE
  87.     BEGIN
  88.       TimeOutCntr := 0;
  89.       IF KEYPRESSED
  90.       THEN
  91.       BEGIN
  92.         READ(KBD,CHARIn);
  93.         IF CHARIn = #27 THEN DoFnKeys;
  94.       END
  95.       ELSE CHARIn := CHR(PORT[DataPort]);
  96.       CHARIn := CHR(BYTE(CHARIn) AND $7F);
  97.     END;
  98.     IF ((CHARIn < #27) AND (NOT (CHARIn IN [^B,^H,^M,^S,^X])))
  99.     OR (CHarin > #126) THEN CHARIn := '.';
  100.   UNTIL (CHARIn <> #27) OR ExFnKey;
  101.   Last2Char := LastChar;
  102.   LastChar  := CHARIn;
  103.   SerialIn  := CHARIn;
  104. END;
  105.  
  106. PROCEDURE AwaitSend;
  107. BEGIN
  108.   REPEAT UNTIL TransmitReady OR LostCarrier;
  109. END;
  110.  
  111. PROCEDURE SerialOut(OutChar : CHAR);
  112. VAR
  113.   SLCntr   : INTEGER;
  114. BEGIN
  115.   {----- Send char to modem when ready -----}
  116.   IF GotCarrier THEN
  117.   BEGIN
  118.     AwaitSend;
  119.     {--- Defuse attempt to send ATTN code to modem from remote ---}
  120.     IF (LastChar = Attn[2]) THEN
  121.     BEGIN
  122.       IF (Last2Char = Attn[1]) THEN
  123.       BEGIN
  124.         PORT[DataPort] := 20;
  125.         AwaitSend;
  126.         PORT[DataPort] := 08;
  127.         AwaitSend;
  128.       END;
  129.     END;
  130.     PORT[DataPort] := ORD(OutChar);
  131.   END;
  132.   {----- Check for character during output -----}
  133.   IF AnyKeyPressed AND (NOT Inputting) THEN
  134.   BEGIN
  135.     CharDuringO := TRUE;
  136.     DuringOChar := SerialIn;
  137.     IF ExFnKey
  138.     THEN
  139.     BEGIN
  140.       ExFnKey := FALSE;
  141.       CharDuringO := FALSE;
  142.     END
  143.     ELSE
  144.     BEGIN
  145.       IF  (DuringOChar IN [^S, 'P', 'p']) THEN
  146.       BEGIN
  147.         CharDuringO := FALSE;
  148.         REPEAT UNTIL AnyKeyPressed OR LostCarrier;
  149.         DuringOChar := SerialIn;
  150.       END;  { Pausing }
  151.     END;  { Not after FnKey }
  152.   END;  { Char during output }
  153.   {----- Update the console -----}
  154.   IF (OutChar <> ^Q) AND (OutChar <> ^G) THEN WRITE(OutChar);
  155.   IF OutChar = ^J THEN
  156.   BEGIN
  157.     GetDate;
  158.     IF SaveTime <> Mint THEN StatusLine;
  159.   END;
  160. END;
  161.  
  162. PROCEDURE XLF;
  163. BEGIN
  164.   IF NOT SuppressOut THEN
  165.   BEGIN
  166.     SerialOut(^M);
  167.     SerialOut(^J);
  168.   END
  169. END;
  170.  
  171. PROCEDURE SendLine(OutLine : Line);
  172. VAR
  173.   CHARPosn  : BYTE;
  174.   XInChar   : CHAR;
  175.   XLen      : INTEGER;
  176. BEGIN
  177.   IF NOT SuppressOut THEN
  178.   BEGIN
  179.     XLen := LENGTH(OutLine);
  180.     IF XLen <> 0 THEN
  181.     BEGIN
  182.       CHARPosn := 0;
  183.       REPEAT
  184.         IF AnyKeyPressed AND (Adding OR Contacting) AND Wrapping
  185.         THEN
  186.         BEGIN
  187.           XInChar := SerialIn;
  188.           IF XInChar > #27 THEN
  189.           BEGIN
  190.             InputLen := InputLen + 1;
  191.             IF InputLen > 100 THEN InputLen := 100;
  192.             InputLine[InputLen] := XInChar;
  193.           END;
  194.         END
  195.         ELSE
  196.         BEGIN
  197.           {----- Spaced out a file transmit? -----}
  198.           IF OutFiling AND CharDuringO AND (DuringOChar = ' ')
  199.           THEN
  200.           BEGIN
  201.             XLen := CHARPosn;
  202.             XLF;
  203.           END
  204.           ELSE
  205.           BEGIN
  206.             CHARPosn := CHARPosn + 1;
  207.             SerialOut(OutLine[CHARPosn]);
  208.             IF CHARPosn > 1 THEN
  209.             BEGIN
  210.               IF (OutLine[CHARPosn-1] = ^H) THEN
  211.               BEGIN
  212.                 IF OutLine[CHARPosn] <> ^H
  213.                 THEN
  214.                 IF ((BaudRate > 500) OR LocalUser)
  215.                 THEN DELAY(75)
  216.                 ELSE DELAY(15);
  217.               END;  { Imbedded backspace }
  218.             END; { Worth checking for backspace }
  219.           END;  { Output of file not interrupted }
  220.         END;  { Not taking another character during wrap }
  221.       UNTIL (CHARPosn = XLen);
  222.     END;  { Output longer than 0 }
  223.   END;  { Output not suppressed }
  224. END;  { X }
  225.  
  226. PROCEDURE X(WorkLine : Line);
  227. VAR
  228.   BSCntr     : INTEGER;
  229.   FoundWrap  : BOOLEAN;
  230.   WorkLen    : INTEGER;
  231.   WorkPtr    : INTEGER;
  232.   WorkWidth  : INTEGER;
  233.   XLen       : INTEGER;
  234. BEGIN
  235.   WorkWidth := Width - 1;
  236.   {----- Step through the fragments -----}
  237.   REPEAT
  238.     WorkPtr := 999;
  239.     XLen := LENGTH(WorkLine);
  240.     IF XLen > WorkWidth THEN
  241.     BEGIN
  242.       {--- Find the maximum allowable ---}
  243.       FoundWrap := FALSE;
  244.       WorkPtr := 0;
  245.       BSCntr  := 0;
  246.       REPEAT
  247.         WorkPtr := WorkPtr + 1;
  248.         IF WorkLine[WorkPtr] = ^H THEN BSCntr := BSCntr + 2;
  249.         IF WorkPtr - BSCntr = WorkWidth THEN FoundWrap := TRUE;
  250.       UNTIL FoundWrap;
  251.       {--- Step backwards to a wrap point ---}
  252.       FoundWrap := FALSE;
  253.       WorkPtr := WorkPtr + 1;
  254.       REPEAT
  255.         WorkPtr := WorkPtr - 1;
  256.         IF POS(WorkLine[WorkPtr],' .,?!:;)]%-+') > 0
  257.         THEN FoundWrap := TRUE;
  258.         {--- Is it a hopeless case? ---}
  259.         IF WorkPtr + BSCntr < BreakPoint THEN
  260.         BEGIN
  261.           WorkPtr := WorkWidth;
  262.           FoundWrap := TRUE;
  263.         END;
  264.       UNTIL FoundWrap;
  265.     END;  { Needs wrapping }
  266.     {--- Send line, remove sent text, do linefeed if wrapping ---}
  267.     IF WorkPtr > XLen THEN WorkPtr := XLen;
  268.     SendLine(COPY(WorkLine,1,WorkPtr));
  269.     DELETE(WorkLine,1,WorkPtr);
  270.     IF LENGTH(WorkLine) > 0 THEN XLF;  { Get ready for another piece }
  271.   UNTIL (LENGTH(WorkLine) = 0) OR (CharDuringO AND (DuringOChar = ' '));
  272. END;
  273.  
  274. PROCEDURE XLn(OutLine : Line);
  275. VAR   CHARPosn : BYTE;   BEGIN   X(OutLine);  XLF;  END;
  276.  
  277. PROCEDURE XLnI(OutLine : Line);  { Skippable Informatory Messages }
  278. BEGIN                            { It's up to you to reset CharDuringO }
  279.   IF NOT (CharDuringO AND (DuringOChar = ' ')) THEN XLn(OutLine);
  280. END;  { XLnI }
  281.  
  282. PROCEDURE SlowX(SXLine : Line);
  283. VAR
  284.   SXCntr : INTEGER;
  285. BEGIN
  286.   FOR SXCntr := 1 TO LENGTH(SXLine) DO
  287.   BEGIN
  288.     SerialOut(SXLine[SXCntr]);
  289.     IF GotCarrier THEN DELAY(80);
  290.   END;
  291. END;
  292.  
  293. PROCEDURE PySerialInit;
  294. BEGIN
  295.   CharDuringO := FALSE;
  296.   Inputting := FALSE;
  297.   TimeOutCntr := 0;
  298.   TimeOutSecs := 10;
  299. END;
  300.  
  301. PROCEDURE BackSpace;
  302. BEGIN
  303.   IF InputLen > 0 THEN
  304.   BEGIN
  305.     BSCntr := BSCntr + 1;
  306.     InputLen := InputLen - 1;
  307.     SerialOut(^H);  SerialOut(' ');  SerialOut(^H);
  308.   END;
  309. END;
  310.  
  311. PROCEDURE WrapWith(WWChar : CHAR);  { New for Version 3.01 }
  312. VAR
  313.   IWCChar : CHAR;
  314. BEGIN
  315.   X(WWChar);
  316.   IF AnyKeyPressed AND (CmdLen < 100) THEN
  317.   BEGIN
  318.     IF KEYPRESSED
  319.     THEN READ(KBD,IWCChar)
  320.     ELSE IWCChar := CHR(PORT[DataPort]);
  321.     IF IWCChar < #27 THEN
  322.     BEGIN
  323.       CmdLen := CmdLen + 1;
  324.       CmdParm[CmdLen] := IWCChar;
  325.     END;
  326.   END;
  327. END;
  328.  
  329. FUNCTION GetInput : Line;
  330. VAR
  331.   BackCntr  : INTEGER;  { Renamed for Version 3.01 -- use FIND for others }
  332.   EndTime   : REAL;
  333.   GIChar    : CHAR;
  334.   GotInput  : BOOLEAN;
  335.   StartTime : REAL;
  336.   WrapCntr  : INTEGER;
  337.   WrapPtr   : INTEGER;
  338. BEGIN
  339.   GotInput := FALSE;
  340.   Inputting := TRUE;
  341.   InputLen := 0;
  342.   BSCntr := 0;
  343.   IF LENGTH(CmdParm) > 0 THEN
  344.   BEGIN
  345.     InputLine := CmdParm;
  346.     CmdParm := '';
  347.     IF NOT ((Adding OR Contacting) AND Wrapping) THEN GotInput:= TRUE;
  348.     WrapCntr := 0;
  349.     REPEAT
  350.       WrapCntr := WrapCntr + 1;
  351.       X(InputLine[WrapCntr]);
  352.     UNTIL (WrapCntr = InputLen);   { Can be extended by X function }
  353.   END;
  354.   IF NOT GotInput THEN
  355.   BEGIN
  356.     SerialOut(^Q);
  357.     BackCntr := 0;
  358.     GetDate;
  359.     StartTime := Mint * 60 + Secs;
  360.     REPEAT
  361.       GIChar := SerialIn;
  362.       IF Contacting THEN
  363.       BEGIN
  364.         IF GIChar = ^M
  365.         THEN
  366.         BEGIN
  367.           SOUND(700);
  368.           DELAY(5);
  369.         END
  370.         ELSE
  371.         BEGIN
  372.           SOUND(1000+ORD(GIChar));
  373.           DELAY(1);
  374.         END;
  375.         NOSOUND;
  376.       END;
  377.       CASE GIChar OF
  378.         #27 : BEGIN END;
  379.         ^M  : GotInput := TRUE;
  380.         ^X  : WHILE InputLen > 0 DO BackSpace;
  381.         ^H  : BackSpace;
  382.       ELSE
  383.         IF GIChar = ^B THEN
  384.         BEGIN
  385.           GIChar := ^H;  { Allow imbedded backspaces }
  386.           BackCntr := BackCntr + 2;  { Removes two from screen }
  387.         END;
  388.         IF (InputLen - BackCntr < 76) AND (InputLen < 100) THEN
  389.         BEGIN
  390.           InputLen := InputLen + 1;
  391.           IF UpCaseInput THEN GIChar := UPCASE(GIChar);
  392.           InputLine[InputLen] := GIChar;
  393.           SerialOut(GIChar);
  394.         END;
  395.         IF (InputLen - BackCntr >= 76) AND Wrapping THEN
  396.         BEGIN
  397.           WrapPtr := InputLen + 1;
  398.           REPEAT
  399.             WrapPtr := WrapPtr - 1
  400.           UNTIL (InputLine[WrapPtr] = ' ') OR (WrapPtr < 55);
  401.           IF WrapPtr >= 55
  402.           THEN
  403.           BEGIN
  404.             IF WrapPtr <> InputLen
  405.             THEN
  406.             BEGIN
  407.               { Next few lines changed for Version 3.01 to fix word-wrap }
  408.               CmdParm := COPY(InputLine, WrapPtr + 1, InputLen - WrapPtr);
  409.               FOR WrapCntr := (WrapPtr + 1) TO InputLen DO WrapWith(^H);
  410.               FOR WrapCntr := (WrapPtr + 1) TO InputLen DO WrapWith(' ');
  411.             END;
  412.             InputLen := WrapPtr - 1;
  413.             GotInput := TRUE;
  414.           END;
  415.         END;
  416.       END; { Not BS, CR, ESC or CTL-X }
  417.     UNTIL GotInput;
  418.     GetDate;
  419.     EndTime := Mint * 60 + Secs;
  420.     IF StartTime > EndTime { i.e. midnight-wrap } THEN
  421.     EndTime := EndTime + 86400.0;
  422.     InputTime := EndTime - StartTime;
  423.   END; { No CmdParm }
  424.   Inputting := FALSE;
  425.   GetInput := InputLine;
  426. END;
  427.  
  428. FUNCTION GetInputLn : Line;
  429. BEGIN
  430.   GetInputLn := GetInput;
  431.   X(^M+^J);
  432. END;
  433.  
  434. FUNCTION GetInt(GIPrompt : Line) : INTEGER;
  435. VAR
  436.   GotInt   : BOOLEAN;
  437.   IntChar  : CHAR;
  438.   TestNum  : INTEGER;
  439.   VALxxx   : INTEGER;
  440. BEGIN
  441.   GotInt := FALSE;
  442.   IF (LENGTH(CmdParm) > 0)
  443.   THEN
  444.   BEGIN
  445.     VAL(CmdParm,TestNum,VALRetCode);
  446.     IF VALRetCode = 0 THEN
  447.     BEGIN
  448.       CmdParm := '';
  449.       GotInt := TRUE;
  450.     END
  451.     ELSE
  452.     BEGIN
  453.       IF VALRetCode = 1
  454.       THEN GotInt := FALSE
  455.       ELSE
  456.       BEGIN
  457.         VAL(COPY(CmdParm,1,VALRetCode - 1),TestNum,VALxxx);
  458.         GotInt := TRUE;
  459.         DELETE(CmdParm,1,VALRetCode);
  460.       END;
  461.     END;
  462.     IF GotInt THEN XLn(GIPrompt+IntToStr(TestNum));
  463.   END;  { Had a stacked value }
  464.   IF NOT GotInt THEN
  465.   BEGIN
  466.     InputLine := '';
  467.     X(GIPrompt+^Q);
  468.     Inputting := TRUE;
  469.     REPEAT
  470.       IntChar := SerialIn;
  471.       IF IntChar IN ['0'..'9',^H,^M,^X]
  472.       THEN
  473.       BEGIN
  474.         CASE IntChar OF
  475.           #27 : BEGIN END;
  476.           ^H  : BackSpace;
  477.           ^M  : GotInt := TRUE;
  478.           ^X  : While InputLen > 0 DO BackSpace;
  479.         ELSE
  480.           InputLen := InputLen + 1;
  481.           IF InputLen > 5 THEN
  482.           BEGIN
  483.             InputLine := '32767';
  484.             GotInt := TRUE;
  485.           END
  486.           ELSE InputLine[InputLen] := IntChar;
  487.           SerialOut(IntChar);
  488.         END;
  489.       END;
  490.       IF Logoff THEN
  491.       BEGIN
  492.         GotInt := TRUE;
  493.         InputLine := '';
  494.       END;
  495.     UNTIL GotInt;
  496.     IF LENGTH(InputLine) = 0 THEN
  497.     BEGIN
  498.       InputLine := '0';
  499.       SerialOut('0');
  500.     END;
  501.     XLF;
  502.     Inputting := FALSE;
  503.     VAL(InputLine,TestNum,VALRetCode);
  504.   END; { No valid cmdparm }
  505.   IF TestNum < 0 THEN TestNum := 0;
  506.   GetInt := TestNum;
  507. END;
  508.  
  509. PROCEDURE GetTestPass;
  510. VAR
  511.   GTPChar : CHAR;
  512. BEGIN
  513.   XLF;
  514.   X('<(*)> '+^Q);
  515.   TestPass := '';
  516.   Inputting := TRUE;
  517.   REPEAT
  518.     GTPChar := SerialIn;
  519.     IF GTPChar <> ^M THEN
  520.     BEGIN
  521.       IF GTPChar = ^H
  522.       THEN
  523.       BEGIN
  524.         IF LENGTH(TestPass) > 0 THEN
  525.         BEGIN
  526.           X(^H+' '+^H);
  527.           TestPass := COPY(TestPass,1,LENGTH(TestPass)-1);
  528.         END;
  529.       END
  530.       ELSE
  531.       BEGIN
  532.         TestPass := TestPass + UPCASE(GTPChar);
  533.         X('*');
  534.       END;
  535.     END;
  536.   UNTIL (GTPChar = ^M) OR (LENGTH(TestPass) = 10);
  537.   Inputting := FALSE;
  538. END;
  539.  
  540. {======= Modem-Control Routines =======}
  541.  
  542. FUNCTION LocalSerialIn : CHAR;
  543. VAR
  544.   LSChar    : CHAR;
  545.   LSTimeOut : INTEGER;
  546. BEGIN
  547.   LSTimeOut := 0;
  548.   REPEAT
  549.     LSTimeOut := LSTimeOut + 1;
  550.   UNTIL GotComChar OR (LSTimeOut = 5000);
  551.   IF LSTimeOut = 5000
  552.   THEN LSChar := '/'
  553.   ELSE LSChar := CHR(PORT[DataPort]);
  554.   LocalSerialIn := LSChar;
  555. END;
  556.  
  557. PROCEDURE LocalSerialOut(LSOChar : CHAR);
  558. BEGIN
  559.   REPEAT UNTIL ((PORT[StatusPort] AND TReady) > 0) OR KEYPRESSED;
  560.   PORT[DataPort] := ORD(LSOChar);
  561. END;
  562.  
  563. PROCEDURE ModemShow(MSChar : TenType);
  564. BEGIN
  565.   CASE MSChar OF
  566.     ^J : BEGIN END;
  567.     ^M : BEGIN END;
  568.     ELSE IF NOT SuppressOut THEN WRITE(MSChar);
  569.   END;
  570. END;
  571.  
  572. FUNCTION ModemResponse : ComLine;
  573. VAR
  574.   MRChar    : CHAR;
  575.   MRLine    : ComLine;
  576.   MRLen     : BYTE ABSOLUTE MRLine;
  577.   TimeNow   : INTEGER;
  578.   TimeStart : INTEGER;
  579. BEGIN
  580.   {----- Give the modem some time to wake up -----}
  581.   GetDate;
  582.   TimeStart := Secs;
  583.   REPEAT
  584.     GetDate;
  585.     TimeNow := Secs;
  586.     IF TimeNow < TimeStart THEN TimeNow := TimeNow + 60;  { Min. wrap }
  587.   UNTIL GotComChar OR (TimeNow - TimeStart > 3);
  588.   {----- Get the response, if any -----}
  589.   IF NOT GotComChar
  590.   THEN MRLine := '<TIME-OUT>'
  591.   ELSE
  592.   BEGIN
  593.     {----- Get the response -----}
  594.     MRLine := '';
  595.     MRLen  := 0;
  596.     TimeStart := GetHSecs;
  597.     REPEAT
  598.       IF GotComChar THEN
  599.       BEGIN
  600.         TimeStart := GetHSecs;
  601.         MRChar := UPCASE(CHR(PORT[DataPort]));
  602.         ModemShow(MRChar);
  603.         IF MRLen = 40 THEN MRLen := 0;
  604.         MRLen := MRLen + 1;
  605.         MRLine[MRLen] := MRChar;
  606.       END;
  607.       TimeNow := GetHSecs;
  608.       IF TimeNow < TimeStart THEN TimeNow := TimeNow + 100;  { Sec. wrap }
  609.     UNTIL TimeNow - TimeStart > 50;
  610.   END;
  611.   {----- Forward the response -----}
  612.   ModemResponse := MRLine;
  613.   IF NOT SuppressOut THEN WRITELN;
  614. END;
  615.  
  616. FUNCTION WaitForOkay : ComLine;
  617. VAR
  618.   FromModem : ComLine;
  619.   Response  : ComLine;
  620. BEGIN
  621.   GOTOXY(45,WHEREY);
  622.   WRITE('Response: ');
  623.   FromModem := ModemResponse;
  624.   IF POS(ModemOkay,FromModem) > 0
  625.   THEN WaitForOkay := ModemOkay
  626.   ELSE WaitForOkay := '<TIME-OUT>';
  627. END;
  628.  
  629. PROCEDURE ModemCtrl(MCLine : ComLine);
  630. VAR
  631.   MCCntr   : INTEGER;
  632.   MCToss   : CHAR;
  633.   MCTry    : INTEGER;
  634. BEGIN
  635.   IF
  636.   (
  637.   (NOT GotCarrier) OR ((MCLine = ModemHangUp) AND (DisconMethod = 'ATTN'))
  638.   )
  639.   AND Comm
  640.   THEN
  641.   BEGIN
  642.     MCTry := 0;
  643.     REPEAT
  644.       MCTry := MCTry + 1;
  645.       {=== Send the command ===}
  646.       WRITE(#17#16,' Modem: ');
  647.       FOR MCCntr := 1 TO LENGTH(MCLine) DO
  648.       BEGIN
  649.         IF MCLine[MCCntr] = '^'
  650.         THEN DELAY(100)
  651.         ELSE
  652.         BEGIN
  653.           LocalSerialOut(MCLine[MCCntr]);
  654.           ModemShow(LocalSerialIn);
  655.         END;
  656.       END;
  657.       {=== Catch up ===}
  658.       DELAY(100);
  659.       IF GotComChar THEN
  660.       BEGIN
  661.         ModemShow(LocalSerialIn);
  662.         DELAY(100);
  663.       END;
  664.       {=== Execute the command ===}
  665.       LocalSerialOut(^M);
  666.     UNTIL (WaitForOkay <> '<TIME-OUT>') OR (MCTry = 3);
  667.   END;
  668. END;
  669.  
  670. PROCEDURE DropReady;
  671. VAR
  672.   DREat  : ComLine;
  673.   DRLoop : INTEGER;
  674. BEGIN
  675.   IF HadCarrier THEN    { Changed for 3.01 }
  676.   BEGIN
  677.     SetBaud(BaudRate);  { New line for 3.01 }
  678.     SerialOut(^M);      { New line for 3.01 }
  679.     SerialOut(^M);      { New line for 3.01 }
  680.     IF DisconMethod = 'DTR'
  681.     THEN
  682.     BEGIN
  683.       PORT[ModemContrl] := 0;
  684.       DELAY(DisconDelay);
  685.       SetBaud(300);
  686.       WRITELN;
  687.     END
  688.     ELSE
  689.     BEGIN
  690.       WRITELN;
  691.       WRITE(#17#16+' Modem: ');
  692.       DELAY(DisconDelay);
  693.       FOR DRLoop := 1 TO LENGTH(Attn) DO
  694.       BEGIN
  695.         IF Attn[DRLoop] = '^'
  696.         THEN DELAY(10)
  697.         ELSE
  698.         BEGIN
  699.           DELAY(150);
  700.           LocalSerialOut(Attn[DRLoop]);
  701.           WRITE(Attn[DRLoop]);
  702.         END;
  703.       END;
  704.       DELAY(DisconDelay DIV 3);
  705.       DREat := WaitForOkay;
  706.       ModemCtrl(ModemHangUp);
  707.     END;
  708.   END;
  709. END;
  710.  
  711. PROCEDURE DropCarrier;
  712. VAR
  713.   DCNoise : ComLine;
  714.   DCCnt   : INTEGER;
  715. BEGIN
  716.   XLF; XLF;
  717.   FOR DCCnt := 1 TO 7 DO
  718.   BEGIN
  719.     SOUND(1000 - DCCnt * 25); DELAY(4); NOSOUND; DELAY(9);
  720.   END;
  721.   IF GotCarrier THEN
  722.   BEGIN
  723.     WRITE(#17#16+' Disconnecting...');
  724.     DropReady;
  725.     SuppressOut := TRUE;
  726.     DCNoise := ModemResponse;    { NO CARRIER message or noise, etc. }
  727.     SuppressOut := FALSE;
  728.   END;
  729. END;
  730.  
  731. PROCEDURE ResetAnswer;
  732. BEGIN
  733.   IF LocalUser THEN ModemCtrl(ModemHangUp);
  734.   IF SysFail OR ShutDown
  735.   THEN
  736.   BEGIN
  737.     ModemCtrl(ModemNoAnswer);
  738.     ModemCtrl(ModemReset);
  739.   END
  740.   ELSE ModemCtrl(ModemDoAnswer);
  741. END;
  742.  
  743. PROCEDURE ModemInit;
  744. BEGIN
  745.   IF Comm THEN
  746.   BEGIN
  747.     SetBaud(300);
  748.     ModemCtrl(ModemAttn);
  749.     ModemCtrl(ModemConfig);
  750.     ModemCtrl(ModemHangUp);
  751.     ModemCtrl(ModemDoAnswer);
  752.   END;
  753. END;
  754.  
  755. PROCEDURE AwaitUser;
  756. VAR
  757.   AUChar    : CHAR;
  758.   AULine    : Line;
  759.   GotUser   : BOOLEAN;
  760.   Response  : ComLine;
  761. BEGIN
  762.   WRITELN;
  763.   WRITELN(#17#16+' Awaiting visitor...');
  764.   WRITELN;
  765.   GotUser   := FALSE;
  766.   LastChar  := ' ';
  767.   Last2Char := ' ';
  768.   LocalUser := FALSE;
  769.   Response  := '';
  770.   REPEAT
  771.     {--- Detect console user ---}
  772.     IF KEYPRESSED THEN
  773.     BEGIN
  774.       READ(KBD,AUChar);
  775.       IF AUChar = #27
  776.       THEN DoFnKeys
  777.       ELSE
  778.       BEGIN
  779.         ModemCtrl(ModemPickUp);
  780.         GotUser    := TRUE;
  781.         HadCarrier := FALSE;
  782.         LocalUser  := TRUE;
  783.       END;
  784.     END;
  785.     IF GotComChar THEN
  786.     BEGIN
  787.       AULine := ModemResponse;
  788.       {--- See if it's a valid response ---}
  789.       IF POS(Modem300 ,AULine) > 0 THEN Response := Modem300;
  790.       IF POS(Modem1200,AULine) > 0 THEN Response := Modem1200;
  791.       IF POS(Modem2400,AULine) > 0 THEN Response := Modem2400;
  792.       IF LENGTH(Response) > 0 THEN
  793.       BEGIN
  794.         WRITELN;
  795.         GotUser    := TRUE;
  796.         HadCarrier := TRUE;
  797.         IF Response = Modem300 THEN
  798.         BEGIN BaudRate   := 300;  SetBaud(BaudRate); END;
  799.         IF Response = Modem1200 THEN
  800.         BEGIN BaudRate   := 1200; SetBaud(BaudRate); END;
  801.         IF Response = Modem2400 THEN
  802.         BEGIN BaudRate   := 2400; SetBaud(BaudRate); END;
  803.       END;  { Got a recognizable modem response }
  804.     END;  { Got a char at the modem }
  805.   UNTIL GotUser;
  806.   WRITELN; WRITELN(#17#16+' Connected.');
  807. END;
  808.