home *** CD-ROM | disk | FTP | other *** search
/ Between Heaven & Hell 2 / BetweenHeavenHell.cdr / 500 / 433 / pyfiles.inc < prev    next >
Text File  |  1986-10-17  |  31KB  |  924 lines

  1. FUNCTION Compress(CLine : Line) : Line;
  2. VAR
  3.   CompLen    : INTEGER;
  4.   CompPtr    : INTEGER;
  5.   OutComp    : Line;
  6.   OutCompLen : BYTE ABSOLUTE OutComp;
  7. BEGIN
  8.   CompLen := LENGTH(Cline);
  9.   CompPtr := 0;
  10.   OutComp := '';
  11.   IF LENGTH(CLine) > 0 THEN
  12.   BEGIN
  13.     REPEAT
  14.       CompPtr := CompPtr + 1;
  15.       OutCompLen := OutCompLen + 1;
  16.       IF (CLine[CompPtr] <> ' ') OR (CompPtr = CompLen)
  17.       THEN OutComp[OutCompLen] := CLine[CompPtr]
  18.       ELSE
  19.       BEGIN
  20.         OutComp[OutCompLen] := CHR(ORD(CLine[CompPtr + 1]) + 128);
  21.         CompPtr := CompPtr + 1;
  22.       END;
  23.     UNTIL CompPtr = CompLen;
  24.   END;
  25.   Compress := OutComp;
  26. END;
  27.  
  28. FUNCTION DeCompress(CLine : Line) : Line;
  29. VAR
  30.   CompLen    : INTEGER;
  31.   CompPtr    : INTEGER;
  32.   OutComp    : Line;
  33.   OutCompLen : BYTE ABSOLUTE OutComp;
  34. BEGIN
  35.   OutComp := '';
  36.   IF LENGTH(CLine) > 0 THEN
  37.   BEGIN
  38.     FOR CompPtr := 1 TO LENGTH(CLine) DO
  39.     BEGIN
  40.       OutCompLen := OutCompLen + 1;
  41.       IF ORD(CLine[CompPtr]) < 129
  42.       THEN OutComp[OutCompLen] := CLine[CompPtr]
  43.       ELSE
  44.       BEGIN
  45.         OutComp[OutCompLen] := ' ';
  46.         OutCompLen := OutCompLen + 1;
  47.         OutComp[OutCompLen] := CHR(ORD(CLine[CompPtr]) - 128);
  48.       END;
  49.     END;
  50.   END;
  51.   DeCompress := OutComp;
  52. END;
  53.  
  54. PROCEDURE OpenFail(OFFile : FNType);
  55. BEGIN
  56.   WRITELN(#17#16+' Fatal error!  Can''t open '+OFFile);
  57.   WRITELN(#17#16+' IORESULT = '+IntToStr(IORESULT));
  58.   WRITELN(#17#16+' Check:  Installed wrong?  Wrong diskettes?');
  59.   SysFail := TRUE;
  60. END;
  61.  
  62. FUNCTION OpenFailed : BOOLEAN;
  63. BEGIN
  64.   IF IORESULT > 0
  65.   THEN
  66.   BEGIN
  67.     OpenFailed := TRUE;
  68.     XLn('* File Error; IORESULT = '+IntToStr(IOResult));
  69.   END
  70.   ELSE OpenFailed := FALSE;
  71. END;
  72.  
  73. FUNCTION OpenFile(FileName : FNType) : BOOLEAN;
  74. VAR
  75.   OFX, OFY, OFY2 : INTEGER;
  76. BEGIN
  77.   FileName := Upper(FileName);
  78.   IF POS(MFLocation,FileName) = 0 THEN FileName := DFLocation + FileName;
  79.   ASSIGN(TxtFile,FileName);
  80.   {$I-}
  81.   RESET(TxtFile);
  82.   {$I+}
  83.   IF IOresult > 0
  84.   THEN
  85.   BEGIN
  86.     OpenFile := FALSE;
  87.     SysLog('W','Open Error on '+FileName);
  88.   END
  89.   ELSE
  90.   BEGIN
  91.     OpenFile := TRUE;
  92.     OFX  := WHEREX;
  93.     OFY  := WHEREY;
  94.     IF OFY > 3
  95.     THEN OFY2 := OFY - 3
  96.     ELSE OFY2 := OFY;
  97.     GOTOXY(76 - LENGTH(FileName),OFY2);
  98.     WRITE(#17#16+' '+FileName);
  99.     GOTOXY(OFX,OFY);
  100.   END;
  101. END;
  102.  
  103. FUNCTION MsgNumAfter(IMPNum : INTEGER) : INTEGER;
  104. BEGIN
  105.   IF IMPNum = MaxMsgs THEN IMPNum := 0;
  106.   MsgNumAfter := IMPNum + 1;
  107. END;
  108.  
  109. FUNCTION MsgNumBefore(IMPNum : INTEGER) : INTEGER;
  110. BEGIN
  111.   IF IMPNum = 1 THEN IMPNum := MaxMsgs + 1;
  112.   MsgNumBefore := IMPNum - 1;
  113. END;
  114.  
  115. FUNCTION XFile(FName : FNType) : SFType;
  116. VAR
  117.   CharPos     : INTEGER;
  118.   Excluding   : BOOLEAN;
  119.   InList      : BOOLEAN;
  120.   InterCmd    : CHAR;
  121.   Private     : BOOLEAN;
  122.   SFLine      : Line;
  123.   SFStat      : SFType;
  124.   XNames      : Line;
  125. BEGIN
  126.   OutFiling := TRUE;
  127.   Private := FALSE;
  128.   IF (NOT OpenFile(FName))
  129.   THEN SFStat := OpenError
  130.   ELSE
  131.   BEGIN
  132.     ExplainKeys;
  133.     InterCmd := '*';
  134.     REPEAT
  135.       {----- Get the line to print -----}
  136.       {$I-} READLN(TxtFile,SFLine); {$I+}
  137.       IF IORESULT > 0 THEN
  138.       BEGIN
  139.         XLn('File-read problem -- sorry.');
  140.         SysLog('W','File-read error '+IntToStr(IORESULT)+' on '+FName);
  141.         InterCmd := 'S';
  142.       END;
  143.       SFLine := DeCompress(SFLine);
  144.       {----- Check for private or exclusive -----}
  145.       IF (LENGTH(SFLine) > 2)
  146.       THEN
  147.       BEGIN
  148.         IF (SFLine[1] IN ['>','<']) AND (SFLine[2] ='<') THEN
  149.         BEGIN
  150.           IF SFLine[1] = '>'
  151.           THEN Excluding := TRUE
  152.           ELSE Excluding := FALSE;
  153.           {----- Find the >> or >< end-delimiter -----}
  154.           CharPos := POS('>>',SFLine);
  155.           IF CharPos = 0 THEN CharPos := LastPos('><',SFLine);
  156.           IF CHARPos >= 4 THEN
  157.           BEGIN
  158.             IF Private THEN XLF;  { In case of previous one }
  159.             XNames := Upper(COPY(SFLine,2,CHARPos-1));
  160.             IF (POS('<'+UserName+'>',XNames) > 0)
  161.             THEN InList := TRUE
  162.             ELSE InList := FALSE;
  163.             IF (    Excluding    AND    InList    AND (NOT WizOp) )
  164.             OR ( (NOT Excluding) AND (NOT InList) AND (NOT WizOp) )
  165.             THEN Private := TRUE
  166.             ELSE Private := FALSE;
  167.             IF Private THEN
  168.             BEGIN
  169.               X(COPY(SFLine,1,CHARPos+1));
  170.               IF CHARPos + 22 > Width
  171.               THEN XLF
  172.               ELSE X('  ');
  173.               IF Excluding
  174.               THEN XLn('(Exclusive Message)')
  175.               ELSE XLn('(Private Message)');
  176.             END;  {  Valid reader }
  177.           END;  { End delimiter is acceptable }
  178.         END;   { Could be exclusive or private }
  179.       END;  { Line is long enough to check }
  180.       {----- Send line and check for interrupted output -----}
  181.       IF NOT Private THEN
  182.       BEGIN
  183.         IF LENGTH(TuneString) > 0 THEN
  184.         BEGIN
  185.           IF POS(TuneString,Upper(SFLine)) > 0 THEN TuneMatch := TRUE;
  186.         END;
  187.         XLn(SFLine);
  188.       END;
  189.       IF CharDuringO THEN
  190.       BEGIN
  191.         OutFiling   := FALSE;
  192.         CharDuringO := FALSE;
  193.         IF DuringOChar = ' '
  194.         THEN InterCmd := 'S'
  195.         ELSE
  196.         BEGIN
  197.           IF SuppressOut THEN
  198.           BEGIN
  199.             SuppressOut := FALSE;
  200.             XLF;
  201.           END;
  202.           REPEAT
  203.             IF Multiple
  204.             THEN
  205.             BEGIN
  206.               XLn(CR+LF+'Continue, Skip, Quit, Back-up, Re-read?');
  207.               X('(C/S/Q/B/R)  '+XON)
  208.             END
  209.             ELSE X(CR+LF+'Continue or Quit? (C/Q)  '+XON);
  210.             InterCmd := UPCASE(SerialIn);
  211.             IF LostCarrier THEN InterCmd := 'Q';
  212.             {----- Back-up and Re-read processing -----}
  213.             IF Multiple THEN
  214.             BEGIN
  215.               IF InterCmd IN ['B','R'] THEN
  216.               BEGIN
  217.                 IF InterCmd = 'B' THEN
  218.                 REPEAT
  219.                   MsgPtr := MsgNumBefore(MsgPtr);
  220.                 UNTIL (MsgBands[MsgPtr] = ReadBand) OR (ReadBand = '*');
  221.                 MsgPtr := MsgNumBefore(MsgPtr);  { Make it "next message" }
  222.               END;
  223.             END;
  224.           UNTIL InterCmd IN ['C','S','Q','B','R'];
  225.           XLn(InterCmd);
  226.           IF InterCmd IN ['B','R'] THEN InterCmd := 'S';
  227.         END;  { Not a space }
  228.         OutFiling := TRUE;
  229.       END;  { CharDuringO }
  230.     UNTIL EOF(TxtFile)                  { End of file }
  231.     OR    (InterCmd IN ['S','Q'])       { User-interruption }
  232.     OR    (TuneMatch AND SuppressOut);  { Tune-scanning successful }
  233.     {----- Clean up -----}
  234.     CLOSE(TxtFile);
  235.     IF InterCmd = 'Q'
  236.     THEN SFStat := Quit
  237.     ELSE SFStat := Okay;
  238.   END;  { File opened okay }
  239.   OutFiling := FALSE;
  240.   XFile := SFStat;
  241. END;
  242.  
  243. FUNCTION FindUserRecPtr(FURPName : UNameType) : BOOLEAN;
  244. VAR
  245.   GotHim   : BOOLEAN;
  246.   FURPTest : UNameType;
  247. BEGIN
  248.   GotHim := FALSE;
  249.   UserRecPtr := 0;
  250.   FURPTest := Upper(FURPName);
  251.   REPEAT
  252.     UserRecPtr := UserRecPtr + 1;
  253.     IF Upper(UserNames[UserRecPtr]) = FURPTest THEN GotHim := TRUE;
  254.   UNTIL GotHim OR (UserRecPtr = MaxUsers);
  255.   IF NOT GotHim
  256.   THEN FindUserRecPtr := FALSE
  257.   ELSE
  258.   BEGIN
  259.     UserRecPtr := UserRecPtr - 1; { First Component is at 0 }
  260.     FindUserRecPtr := TRUE;
  261.   END;
  262. END;
  263.  
  264. PROCEDURE GetReadDate(GRDChar : CHAR);
  265. BEGIN
  266.   IF Date_Warp > -1 THEN
  267.   BEGIN
  268.     ReadDate := Date_Warp;  ReadMint := Mint_Warp;  { Yummy }
  269.   END
  270.   ELSE
  271.   BEGIN
  272.     WITH UsersRec DO
  273.     BEGIN
  274.       CASE GRDChar OF
  275.         '0' : BEGIN
  276.                 ReadDate := Date_X; ReadMint := Mint_X; Read_X := TRUE;
  277.               END;
  278.         'A' : BEGIN
  279.                 ReadDate := Date_A; ReadMint := Mint_A; Read_A := TRUE;
  280.               END;
  281.         'B' : BEGIN
  282.                 ReadDate := Date_B; ReadMint := Mint_B; Read_B := TRUE;
  283.               END;
  284.         'C' : BEGIN
  285.                 ReadDate := Date_C; ReadMint := Mint_C; Read_C := TRUE;
  286.               END;
  287.         'D' : BEGIN
  288.                 ReadDate := Date_D; ReadMint := Mint_D; Read_D := TRUE;
  289.               END;
  290.         'P' : BEGIN
  291.                 ReadDate := Date_P; ReadMint := Mint_P; Read_P := TRUE;
  292.               END;
  293.         'S' : BEGIN
  294.                 ReadDate := Date_S; ReadMint := Mint_S; Read_S := TRUE;
  295.               END;
  296.         'G' : BEGIN
  297.                 ReadDate := Date_Last; ReadMint := Mint_Last;
  298.               END;
  299.         '*' : BEGIN
  300.                 ReadDate := Date_Last; ReadMint := Mint_Last;
  301.               END;
  302.       END; { Case }
  303.     END; { With }
  304.   END; { Not warped }
  305. END;
  306.  
  307. FUNCTION MsgFile(MFNum : INTEGER) : FNType;
  308. VAR
  309.   StrNum   : STRING[7];
  310.   MFPad    : STRING[14];
  311. BEGIN
  312.   STR(MFNum,StrNum);
  313.   MFPad := '0000000' + StrNum;
  314.   StrNum := COPY( MFPad, LENGTH(MFPad)-6, 7 );
  315.   MsgFile := MFLocation + 'B' + StrNum;
  316. END;
  317.  
  318. FUNCTION OpenQuestFile : BOOLEAN;
  319. BEGIN
  320.   QuestFileName := DFLocation + File_Queries;
  321.   ASSIGN(QuestFile,QuestFileName);
  322.   {$I-}  RESET(QuestFile);  {$I+}
  323.   OpenQuestFile := TRUE;  IF IOResult > 0 THEN OpenQuestFile := FALSE;
  324. END;
  325.  
  326. FUNCTION AskMsgTimesPtr : INTEGER;
  327. VAR
  328.   MFCntr : INTEGER;
  329.   MFDate : INTEGER;
  330.   MFMint : INTEGER;
  331.   MFGot  : BOOLEAN;
  332. BEGIN
  333.   MFDate := GetInt('What day was the message sent?  ');
  334.   MFMint := GetInt('And what  minute  of that day?  '); XLF;
  335.   IF (MFMint = 0) AND (MFDate = 1) THEN MFMint := 1;
  336.   MFCntr := 0;
  337.   MFGot := FALSE;
  338.   REPEAT
  339.     MFCntr := MFCntr + 1;
  340.     IF (MsgDates[MFCntr] = MFDate) AND (MsgMints[MFCntr] = MFMint)
  341.     THEN MFGot := TRUE;
  342.   UNTIL MFGot OR (MFCntr = MaxMsgs);
  343.   IF MFGot
  344.   THEN AskMsgTimesPtr := MFCntr - 1
  345.   ELSE AskMsgTimesPtr := MaxMsgs;  { Beyond EOF }
  346. END;
  347.  
  348. FUNCTION Editor(EType : CHAR) : CHAR;
  349. TYPE
  350.   AddType  = (NoAdd, YesAdd, Doing);
  351. VAR
  352.   AddAgain : AddType;
  353.   AddDone  : BOOLEAN;
  354.   Added    : BOOLEAN;
  355.   AvgBS    : REAL;
  356.   AvgIT    : REAL;
  357.   BlCntr   : INTEGER;
  358.   ChAuto   : CHAR;
  359.   ChCmd    : CHAR;
  360.   ChDone   : BOOLEAN;
  361.   ChFound  : BOOLEAN;
  362.   ChExp    : INTEGER;
  363.   ChFrom   : Line;
  364.   ChLine   : Line;
  365.   ChSpot   : INTEGER;
  366.   ChTo     : Line;
  367.   HighIT   : REAL;
  368.   LowIT    : REAL;
  369.   SpdRng   : REAL;
  370.   TempBS   : REAL;
  371.   TempIT   : REAL;
  372.   TrackBS  : ARRAY[1..MaxMsgLen] OF REAL;
  373.   TrackIT  : ARRAY[1..MaxMsgLen] OF REAL;
  374. BEGIN
  375.   AddAgain := NoAdd;
  376.   AddDone  := TRUE;
  377.   Added    := FALSE;
  378.   ChDone   := FALSE;
  379.   Communicative := TRUE;
  380.   FOR ChPtr := 1 TO MaxMsgLen DO
  381.   BEGIN
  382.     TrackBS[ChPtr] := 0;
  383.     TrackIT[ChPtr] := 0;
  384.   END;
  385.   IF EType = 'C' THEN ChAuto := '%';
  386.   IF EType = 'S' THEN ChAuto := 'A';
  387.   REPEAT
  388.     CharDuringO := FALSE;
  389.     IF ChAuto <> ' '
  390.     THEN
  391.     BEGIN
  392.       ChCmd := ChAuto;
  393.       IF AddAgain = YesAdd
  394.       THEN
  395.       BEGIN
  396.         ChAuto := 'A';
  397.         AddAgain := Doing;
  398.       END
  399.       ELSE ChAuto := ' ';
  400.     END
  401.     ELSE
  402.     BEGIN
  403.       X(LF+'OPTION?  '+XON);
  404.       ChCmd := UPCASE(SerialIn);
  405.       IF ChCmd = CR THEN ChCmd := 'S';
  406.       XLn(ChCmd);
  407.       XLF;
  408.       CharDuringO := FALSE;
  409.     END;
  410.     CASE ChCmd OF
  411.       '?' : BEGIN
  412.               XLn('> Single-letter commands');
  413.               XLF;
  414.               IF AddAgain = Doing
  415.               THEN X('E - Edit mode       ')
  416.               ELSE X('A - Add more text   ');
  417.               XLn('L - List the text');
  418.               XLn('F - Find a word     C - Change a line');
  419.               XLn('D - Delete a line   I - Insert a line');
  420.               XLn('S - Save the text   Q - Quit, no save');
  421.               IF Wrapping
  422.               THEN XLn('W - Word-wrap off')
  423.               ELSE XLn('W - Word-wrap on');
  424.               XLF;
  425.               XLn('While typing anywhere on this system:');
  426.               XLn('Hold down  CTRL-X  to delete a  line.');
  427.               XLn('Hold down  CTRL-H  to erase a letter.');
  428.             END;
  429.       'A' : BEGIN
  430.               IF ChSize >= MaxMsgLen
  431.               THEN
  432.               BEGIN
  433.                 XLn('Message is full');
  434.                 AddAgain := NoAdd;
  435.               END
  436.               ELSE
  437.               BEGIN
  438.                 IF AddAgain = NoAdd
  439.                 THEN XLn(LF+'For help:  enter  ?  on an empty line.')
  440.                 ELSE XLn(LF+'Continue entering text...');
  441.                 AddAgain := YesAdd;
  442.                 AddDone  := FALSE;
  443.                 Added    := TRUE;
  444.                 XLF;
  445.                 REPEAT
  446.                   Adding := TRUE;
  447.                   ChLine := GetInputLn;
  448.                   Adding := FALSE;
  449.                   IF Logoff THEN ChLine := 'S';
  450.                   IF (LENGTH(ChLine) = 1) AND (ChLine <> ' ') THEN
  451.                   BEGIN
  452.                     ChAuto := UPCASE(ChLine[1]);
  453.                     IF ChAuto IN ['E','L','C','D','I'] THEN
  454.                     BEGIN
  455.                       XLF;
  456.                       X('Message contains '+IntToStr(ChSize)+' line');
  457.                       IF ChSize <> 1 THEN X('s');
  458.                       XLn('.');
  459.                     END;
  460.                     XLF;
  461.                     IF ChAuto = 'E' THEN AddAgain := NoAdd;
  462.                     AddDone := TRUE;
  463.                   END
  464.                   ELSE
  465.                   BEGIN
  466.                     ChSize := ChSize + 1;
  467.                     EditBuffer[ChSize] := ChLine;
  468.                     TrackBS[ChSize]    := BSCntr;
  469.                     TrackIT[ChSize]    := InputTime;
  470.                     LenCnt := LenCnt + LENGTH(ChLine);
  471.                     IF ChSize = (MaxMsgLen - 5) THEN XLn('"FIVE LINES LEFT"');
  472.                   END;
  473.                   IF ChSize = MaxMsgLen THEN AddDone := TRUE;
  474.                 UNTIL AddDone;
  475.               END; { Msg not full }
  476.             END; { 'A' }
  477.       'C' : BEGIN
  478.               ChPtr := GetInt('Change which line?  ');
  479.               IF (ChPtr > 0) AND (ChPtr <= ChSize) THEN
  480.               BEGIN
  481.                 X('Change what? ');
  482.                 ChFrom := GetInputLn;
  483.                 IF LENGTH(ChFrom) <> 0 THEN
  484.                 BEGIN
  485.                   ChSpot := POS(ChFrom,EditBuffer[ChPtr]);
  486.                   IF ChSpot = 0
  487.                   THEN XLn('Not found.')
  488.                   ELSE
  489.                   BEGIN
  490.                     X('Change it to what? ');
  491.                     ChTo := GetInputLn;
  492.                     DELETE(EditBuffer[ChPtr],ChSpot,LENGTH(ChFrom));
  493.                     INSERT(ChTo,EditBuffer[ChPtr],ChSpot);
  494.                   END; { Found from }
  495.                 END; { Valid from }
  496.               END; { Valid line }
  497.             END; { C proc }
  498.       'D' : BEGIN
  499.               ChPtr := GetInt('Delete which line?  ');
  500.               IF (ChPtr > 0) AND (ChPtr <= ChSize) THEN
  501.               BEGIN
  502.                 WHILE ChPtr < ChSize DO
  503.                 BEGIN
  504.                   EditBuffer[ChPtr] := EditBuffer[ChPtr + 1];
  505.                   TrackBS[ChPtr]    := TrackBS[ChPtr + 1];
  506.                   TrackIT[ChPtr]    := TrackIT[ChPtr + 1];
  507.                   ChPtr := ChPtr + 1;
  508.                 END;
  509.                 ChSize := ChSize - 1;
  510.               END
  511.               ELSE XLn('Line '+IntToStr(ChPtr)+' not found.');
  512.             END;
  513.       'E' : ChAuto := '%';
  514.       'F' : BEGIN
  515.               ChFound := FALSE;
  516.               X('Find what?  ');
  517.               ChFrom := GetInputLn; XLF;
  518.               IF LENGTH(ChFrom) <> 0 THEN
  519.               BEGIN
  520.                 ChPtr := 1;
  521.                 REPEAT
  522.                   IF POS(ChFrom,EditBuffer[ChPtr]) > 0
  523.                   THEN
  524.                   BEGIN
  525.                     ChFound := TRUE;
  526.                     XLn(Fmt(IntToStr(ChPtr),Left,3)+EditBuffer[ChPtr]);
  527.                   END;
  528.                   ChPtr := ChPtr + 1;
  529.                 UNTIL CharDuringO OR (ChPtr > ChSize);
  530.                 IF NOT ChFound THEN XLn('Can''t find that.');
  531.               END;
  532.             END;
  533.       'I' : BEGIN
  534.               IF ChSize < MaxMsgLen THEN
  535.               BEGIN
  536.                 ChPtr := GetInt('Insert after which line?  '); XLF;
  537.                 IF (ChPtr > -1) AND (ChPtr <= ChSize) THEN
  538.                 IF ChPtr < ChSize THEN
  539.                 BEGIN
  540.                   FOR ChExp := ChSize DOWNTO ChPtr + 1 DO
  541.                   BEGIN
  542.                     EditBuffer[ChExp+1] := EditBuffer[ChExp];
  543.                     TrackBS[ChExp+1]    := TrackBS[ChExp];
  544.                     TrackIT[ChExp+1]    := TrackIT[ChExp];
  545.                   END;
  546.                 END;
  547.                 ChSize := ChSize + 1;
  548.                 XLn('Enter the text of your new line...');
  549.                 EditBuffer[ChPtr + 1] := GetInputLn;
  550.               END
  551.               ELSE XLn('Message is full -- can''t insert.');
  552.             END;
  553.       'L' : BEGIN
  554.               ChPtr := GetInt('List from which line number?  '); XLF;
  555.               IF ChPtr =  0 THEN ChPtr := 1;
  556.               IF ChSize = 0
  557.               THEN XLn('Nothing to list.')
  558.               ELSE
  559.               BEGIN
  560.                 IF ChPtr > ChSize THEN ChPtr := ChSize;
  561.                 CharDuringO := FALSE;
  562.                 REPEAT
  563.                   X(Fmt(IntToStr(ChPtr),Right,2)+' ');
  564.                   XLn(EditBuffer[ChPtr]);
  565.                   ChPtr := ChPtr + 1;
  566.                 UNTIL CharDuringO OR (ChPtr > ChSize);
  567.               END;
  568.             END;
  569.       'S' : BEGIN
  570.               IF ChSize = 0
  571.               THEN XLn('Nothing to send.')
  572.               ELSE
  573.               BEGIN
  574.                 IF EditBuffer[1] = '(SUMMARY LINE)' THEN
  575.                 BEGIN
  576.                   XLn('Summarize your message (1 line):');
  577.                   X('> ');
  578.                   EditBuffer[1] := GetInputLn;
  579.                   TrackBS[1]    := BSCntr;
  580.                   TrackIT[1]    := InputTime;
  581.                   XLF;
  582.                   IF (LENGTH(EditBuffer[1]) < 10) AND (ChSize > 5)
  583.                   THEN XLn('Not much of a summary...'+LF);
  584.                 END;
  585.                 ChDone := TRUE;
  586.                 Editor := 'S';
  587.                 {----- Analyze typing -----}
  588.                 IF (ChSize > 0) AND Added THEN
  589.                 BEGIN
  590.                   AvgBS  := 0;
  591.                   AvgIT  := 0;
  592.                   BlCntr := 0;
  593.                   HighIT := 0.0;
  594.                   LowIT  := 10000.0;
  595.                   FOR ChSpot := 1 TO ChSize DO
  596.                   BEGIN
  597.                     IF (LENGTH(EditBuffer[ChSpot]) < 5)
  598.                     OR (TrackIT[ChSpot] < 1)
  599.                     THEN BlCntr := BlCntr + 1
  600.                     ELSE
  601.                     BEGIN
  602.                       {----- Calc backspacing -----}
  603.                       TempBS := TrackBS[ChSpot] / (LENGTH(EditBuffer[ChSpot]));
  604.                       AvgBS := AvgBS + TempBS;
  605.                       {---- Calc CPS for this line -----}
  606.                       TempIT := LENGTH(EditBuffer[ChSpot]) / TrackIT[ChSpot];
  607.                       AvgIT := AvgIT + TempIT;
  608.                       IF HighIT < TempIT THEN HighIT := TempIT;
  609.                       IF LowIT  > TempIT THEN LowIT  := TempIT;
  610.                     END;
  611.                   END;
  612.                   IF BlCntr < ChSize THEN
  613.                   BEGIN
  614.                     AvgBS  := AvgBS / (ChSize-BlCntr) * 100;
  615.                     AvgIT  := AvgIT / (ChSize-BlCntr) * 12;
  616.                     HighIT := HighIT * 12;
  617.                     LowIT  := LowIT  * 12;
  618.                     SpdRng := HighIT - LowIT;
  619.                     WRITELN(#17#16+' ╓──Low WPM──╥─High  WPM─╥──Avg WPM──╥─Spd Range─╥─BS Factor─╖');
  620.                     WRITE(#17#16+' ╙──',LowIT:5:0,' ───╨──',HighIT:5:0,' ───╨──',AvgIT:5:0);
  621.                     WRITELN(' ───╨──',SpdRng:5:0,' ───╨──',AvgBS:5:0,' ───╜');
  622.                     WRITELN;
  623.                   END;  { Enough to analyze }
  624.                 END;  { Worth analyzing }
  625.                 {----- Save the message -----}
  626.                 X('Concentrate...');
  627.                 REWRITE(TxtFile); X('.');
  628.                 {$I-}
  629.                 ChPtr := 0;
  630.                 REPEAT
  631.                   ChPtr := ChPtr + 1;
  632.                   WRITELN(TxtFile,Compress(EditBuffer[ChPtr]));
  633.                   IF ((ChPtr DIV 3) * 3) = ChPtr THEN X('.');
  634.                 UNTIL (ChPtr = ChSize) OR (IORESULT <> 0);
  635.                 IF IORESULT <> 0 THEN
  636.                 BEGIN
  637.                   SysLog('W','Message disk error, IORESULT = '+IntToStr(IORESULT));
  638.                   XLn('Disk space overflow!');
  639.                   SysFail := TRUE;
  640.                 END;
  641.                 {$I+}
  642.               END;
  643.               CLOSE(TxtFile);
  644.               IF EType = 'C' THEN XLF;
  645.             END;
  646.       'Q' : BEGIN
  647.               IF EType = 'C'
  648.               THEN XLn('Cancel all changes?')
  649.               ELSE XLn('Cancel this message?');
  650.               IF Yes THEN
  651.               BEGIN
  652.                 ChDone := TRUE;
  653.                 Editor := 'Q';
  654.                 CLOSE(TxtFile);
  655.               END;
  656.             END;
  657.       'W' : BEGIN
  658.               Wrapping := NOT Wrapping;
  659.               X('Word-wrapping text-entry ');
  660.               IF Wrapping
  661.               THEN XLn('turned on.')
  662.               ELSE XLn('turned off.');
  663.             END;
  664.             ELSE XLn('Type  ?  for help.');
  665.     END;  { Of CASE }
  666.   UNTIL ChDone;
  667. END;
  668.  
  669. FUNCTION XMsg : SFType;
  670. VAR
  671.   NiceLine : STRING[12];
  672.   XMTime   : STRING[12];
  673.   ScanCode : SFType;
  674. BEGIN
  675.   TuneMatch := TRUE;
  676.   ScanCode  := Okay;
  677.   {----- If we're tuned, check if this file is to print -----}
  678.   IF LENGTH(TuneString) > 0 THEN
  679.   BEGIN
  680.     TuneMatch := FALSE;
  681.     SuppressOut := TRUE;
  682.     ScanCode := XFile(MsgFile(MsgPtr));
  683.     SuppressOut := FALSE;
  684.     IF TuneMatch
  685.     THEN XLF
  686.     ELSE
  687.     BEGIN
  688.       X(ShowDate(MsgDates[MsgPtr],MsgMints[MsgPtr])+' ');
  689.       IF WHEREX + 11 > Width THEN XLF;
  690.     END;
  691.   END;
  692.   {----- Print the header, then the file -----}
  693.   IF TuneMatch AND (ScanCode <> Quit) THEN
  694.   BEGIN
  695.     NiceLine := '------------';
  696.     CharDuringO := FALSE;
  697.     XMTime := ShowDate(MsgDates[MsgPtr],MsgMints[MsgPtr]);
  698.     XLF;
  699.     XLn(COPY(NiceLine,1,LENGTH(XMTime)));
  700.     XLn(XMTime + '  '+Upper(MsgPosters[MsgPtr]));
  701.     X(COPY(NiceLine,1,LENGTH(XMTime)));
  702.     IF ReadBand <> '*'
  703.     THEN XLF
  704.     ELSE XLn('  '+XlateBoard(MsgBands[MsgPtr]));
  705.     XLF;
  706.     XMsg := XFile(MsgFile(MsgPtr));
  707.   END;
  708. END;
  709.  
  710. FUNCTION ReadBoard(RBChar : CHAR) : BOOLEAN;
  711. VAR
  712.   RBStat   : SFType;
  713.   GotMsgs  : BOOLEAN;
  714. BEGIN
  715.   ReadBand := RBChar;
  716.   GotMsgs  := FALSE;
  717.   GetReadDate(ReadBand);
  718.   MsgPtr  := NextMsg;
  719.   RBStat  := Okay;
  720.   IF ReadBand <> '*' THEN
  721.   BEGIN
  722.     REPEAT
  723.       IF Before(ReadDate, ReadMint, MsgDates[MsgPtr], MsgMints[MsgPtr])
  724.       AND (MsgBands[MsgPtr] = ReadBand)
  725.       AND (InFocus(MsgPosters[MsgPtr]))
  726.       THEN GotMsgs := TRUE
  727.       ELSE MsgPtr := MsgNumAfter(MsgPtr);
  728.     UNTIL GotMsgs OR (MsgPtr = NextMsg);
  729.   END
  730.   ELSE GotMsgs := TRUE;
  731.   IF NOT GotMsgs
  732.   THEN ReadBoard := FALSE
  733.   ELSE
  734.   BEGIN
  735.     Multiple := TRUE;
  736.     IF ReadBand <> '*' THEN
  737.     BEGIN
  738.       Explained := FALSE;
  739.       ExplainKeys;
  740.       XLn('Tuning in the telepathic band used by');
  741.       XLn('the ' + XlateBoard(ReadBand) + '.');
  742.     END;
  743.     REPEAT
  744.       IF Before(ReadDate, ReadMint, MsgDates[MsgPtr], MsgMints[MsgPtr])
  745.       AND ( (MsgBands[MsgPtr] = ReadBand) OR (ReadBand = '*') )
  746.       AND (InFocus(MsgPosters[MsgPtr]))
  747.       THEN RBStat := XMsg;
  748.       MsgPtr := MsgNumAfter(MsgPtr);
  749.     UNTIL (MsgPtr = NextMsg) OR (RBStat = Quit);
  750.     IF (RBStat = Quit) AND (RBChar = 'G')
  751.     THEN Postings := Postings - RANDOM(2);
  752.     ReadBoard := TRUE;
  753.     Multiple  := FALSE;
  754.     IF (NOT TuneMatch) AND (LENGTH(TuneString) > 0) THEN XLF;
  755.   END;
  756. END;
  757.  
  758. PROCEDURE WriteBoard(WBChar : CHAR);
  759. VAR
  760.   AnCase   : INTEGER;
  761.   AnComma  : INTEGER;
  762.   AnCont   : INTEGER;
  763.   AnOther  : INTEGER;
  764.   AnPeriod : INTEGER;
  765.   AnSpace  : INTEGER;
  766.   Private  : BOOLEAN;
  767.   Score    : INTEGER;
  768.   WBCnt    : INTEGER;
  769.   WBFile   : FNType;
  770.   WBLine   : Line;
  771.   WBPos    : INTEGER;
  772.   WBStat   : CHAR;
  773. BEGIN
  774.   Private := FALSE;
  775.   LenCnt := 0;
  776.   XLn('Sending on the telepathic band used by');
  777.   XLn('the ' + XlateBoard(WBChar)+'.');
  778.   EditBuffer[1] := '(SUMMARY LINE)';
  779.   EditBuffer[2] := '';
  780.   ChSize := 2;
  781.   WBFile := MsgFile(NextMsg);
  782.   ASSIGN(TxtFile,WBFile);
  783.   WBStat := Editor('S');
  784.   IF (ChSize <= 2) OR (WBStat = 'Q')
  785.   THEN XLn('Nothing sent.')
  786.   ELSE
  787.   BEGIN
  788.     MsgBands[NextMsg]   := WBChar;     MsgTimesRec.MsgBand    := WBChar;
  789.     MsgDates[NextMsg]   := Date;       MsgTimesRec.Date_Added := Date;
  790.     MsgMints[NextMsg]   := Mint;       MsgTimesRec.Mint_Added := Mint;
  791.     MsgPosters[NextMsg] := UserName;   MsgTimesRec.Poster     := UserName;
  792.     X('.');  SEEK(MsgTimesFile,NextMsg-1);  { First Component is 0 }
  793.     X('.');  WRITE(MsgTimesFile,MsgTimesRec);
  794.     NextMsg := MsgNumAfter(NextMsg);
  795.     X('.');  RESET(NextMsgFile);
  796.     X('.');  WRITE(NextMsgFile,NextMsg);
  797.     XLn(' ['+ShowDate(Date,Mint)+']');
  798.     XLF;
  799.     {--- Analyze message for content ---}
  800.     IF Level = 0
  801.     THEN Postings := Postings + 1
  802.     ELSE
  803.     BEGIN
  804.       AnCase   := 0;
  805.       AnComma  := 0;
  806.       AnCont   := 0;
  807.       AnOther  := 0;
  808.       AnPeriod := 0;
  809.       AnSpace  := 0;
  810.       X('"HMM');
  811.       FOR WBCnt := 1 TO ChSize DO
  812.       BEGIN
  813.         IF WBCnt DIV 6 * 6 = WBCnt THEN X('M');
  814.         WBLine := Upper(EditBuffer[WBCnt]);
  815.         {----- High-content indicators -----}
  816.         IF POS( ' BUT ',WBLine) > 0 THEN AnCont   := AnCont + 2; { but }
  817.         IF POS( 'N''T', WBLine) > 0 THEN AnCont   := AnCont + 1; { can't etc. }
  818.         IF POS( 'OULD', WBLine) > 0 THEN AnCont   := AnCont + 2; { would could should }
  819.         IF POS( 'IF Y', WBLine) > 0 THEN AnCont   := AnCont + 2; { if you }
  820.         IF POS(' NOT ', WBLine) > 0 THEN AnCont   := AnCont + 2; { assertive }
  821.         IF POS( '''S',  WBLine) > 0 THEN AnOther  := AnOther + 1;
  822.         IF POS( '?',    WBLine) > 0 THEN AnOther  := AnOther + 1;
  823.         IF POS( '(',    WBLine) > 0 THEN AnOther  := AnOther + 2;
  824.         IF POS( '"',    WBLine) > 0 THEN AnOther  := AnOther + 2;
  825.         {----- Garbage detectors -----}
  826.         IF POS( '   ',  WBLine) > 0 THEN AnSpace  := AnSpace + 1;
  827.         IF POS( '---',  WBLine) > 0 THEN AnOther  := AnOther - 2;
  828.         {----- Punctuation -----}
  829.         IF POS( ', ',   WBLine) > 0 THEN AnComma  := AnComma + 2;
  830.         IF POS( '. ',   WBLine) > 0 THEN AnPeriod := AnPeriod + 1;
  831.         IF POS( '.  ',  WBLine) > 0 THEN AnPeriod := AnPeriod + 2;
  832.         IF POS( '-',    WBLine) > 0 THEN AnOther  := AnOther + 1;
  833.         IF POS( ': ',   WBLine) > 0 THEN AnOther  := AnOther + 1;
  834.         IF POS( '; ',   WBLine) > 0 THEN AnOther  := AnOther + 3;
  835.         {----- "Noisey" indicators -----}
  836.         IF LENGTH(WBLine) > 20
  837.         THEN IF POS(' ',WBLine) = 0 THEN AnOther := AnOther - 1;
  838.         IF AnCase = 0 THEN IF POS('e',EditBuffer[WBCnt]) > 0 THEN AnCase := 1;
  839.         {----- Early-message downhills -----}
  840.         IF WBCnt = 1 THEN
  841.         BEGIN
  842.           IF (POS('JUST ',WBLine) < 10)   { this is just }
  843.           OR (POS('ONLY ',WBLine) < 10)   { this is only }
  844.           THEN AnOther := AnOther - 1;
  845.         END;
  846.         IF WBCnt < 7 THEN
  847.         BEGIN
  848.           IF COPY(WBLine,1,2) = '<<' THEN Private  := TRUE;
  849.           WBPos := POS('ESTEEM',WBLine) - POS('FOR',WBLine);
  850.           IF (WBPos > 0) AND (WBPos <= 9) THEN AnOther := AnOther - 2;
  851.           IF (POS('CK',WBLine) - 2) = POS('FU',WBLine) { Decorum, eh? }
  852.           THEN AnCont  := AnCont - 1;
  853.         END;
  854.       END;
  855.       {--- Reduce Content Scores ---}
  856.       AnComma  := AnComma  DIV 2;
  857.       AnCont   := AnCont   DIV 2;
  858.       AnPeriod := AnPeriod DIV 3;
  859.       {----- Restrict Content Scores -----}
  860.       IF AnComma  > 2 THEN AnComma  := 2;
  861.       IF AnCont   > 4 THEN AnCont   := 4;
  862.       IF AnOther  > 8 THEN AnOther  := 8;
  863.       IF AnPeriod > 2 THEN AnPeriod := 2;
  864.       {----- Calculate Total Score -----}
  865.       IF AnCase = 0 THEN AnCase := -1;
  866.       Score := (LenCnt DIV 1200) + AnCase + AnComma + AnOther + AnPeriod + AnCont;
  867.       IF LENGTH(EditBuffer[1]) < ChSize THEN Score := Score - 2;
  868.       IF AnSpace > ChSize DIV 3 THEN Score := Score - 2;
  869.       IF (LenCnt DIV ChSize) < 15 THEN Score := 0;
  870.       IF Private THEN Score := Score - 3;
  871.       {----- Deal with blabbermouths -----}
  872.       NumSends := NumSends + 1;
  873.       { Number of Sends    1  2  3  4  5  6 }
  874.       { Score Adjustment   0  0  2  4  6  8 }
  875.       IF NumSends > 2 THEN Score := Score - ((NumSends - 2) * 2);
  876.       {--- Tell him about it ---}
  877.       IF Score < 0 THEN Score := 0;
  878.       XLn('."'+LF);
  879.       CASE Score OF
  880.         0..1 : BEGIN
  881.                  XLn('TSOTL is annoyed by that message.');
  882.                  IF NOT WizOp THEN
  883.                  BEGIN
  884.                    IF Level > 2 THEN
  885.                    BEGIN
  886.                      SetAltitude(Level - 2);
  887.                      Level := Altitude;
  888.                      XLN(LF+'"THIS IS YOUR NEW LEVEL!"');
  889.                    END;
  890.                    Postings := Postings - 1;
  891.                    AscCnt := AscCnt + 3;
  892.                    Pleaseable := FALSE;
  893.                  END;
  894.                END;
  895.         2   : BEGIN
  896.                  XLn('TSOTL is NOT impressed by that message.');
  897.                  Postings := Postings - 1;
  898.                 AscCnt := AscCnt + 2;
  899.                END;
  900.         3   :  XLn('TSOTL says, "A LITTLE DISAPPOINTING."');
  901.         4   :  XLn('TSOTL says, "NEARLY WORTH READING."');
  902.         5   :  XLn('TSOTL found that almost interesting.');
  903.         6..9 : BEGIN
  904.                  XLn('TSOTL found that mildly interesting.');
  905.                  Postings := Postings + 1;
  906.                END;
  907.         10..12:BEGIN
  908.                  XLn('TSOTL thought that was quite good.');
  909.                  Postings := Postings + 2;
  910.                  AscCnt := AscCnt - 1;
  911.                END;
  912.         13..15:BEGIN
  913.                  XLn('TSOTL liked that one.');
  914.                  Postings := Postings + 3;
  915.                  AscCnt := AscCnt - 2;
  916.                END;
  917.                ELSE
  918.                  XLn('TSOTL liked that one very much.');
  919.                  Postings := Postings + 3;
  920.                  AscCnt := AscCnt - 3;
  921.       END; { of CASE }
  922.     END; { of > Alt 0 }
  923.   END; { of something-sent }
  924. END;