home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / READSTR.ZIP / READ.MOD < prev    next >
Encoding:
Text File  |  1986-08-27  |  44.9 KB  |  1,440 lines

  1. Procedure ReadString(Option:char;
  2.                      AutoClear,InsertStatusLine,SetCposTo1onEntry,
  3.                      Floater,DeadColorsOnExit:Boolean;
  4.                      HelpLine,HelpNum,X,Y:Byte;
  5.                      ScanExitSet:ByteSetType;
  6.                      Var Scan:Byte;
  7.                      AsciiExitSet:CharSetType;
  8.                      Var Ascii:char;
  9.                      Var CPos:Byte;
  10.                      Var Z:String80;
  11.                      Mask:String80);
  12. Const
  13.  EndTag=#7;
  14.  LocalExitSet:ByteSetType=[ArrowLfKey,ArrowRtKey,HomeKey,EndKey,BkSpKey,
  15.                            DelKey,CtrlBkSpKey,CtrlDelKey];
  16. Var
  17.  OverBuff:String[80];
  18.  I,MaxLen,MPos:Byte;
  19.  MaskLen:Byte absolute Mask;
  20.  ZLen:Byte absolute Z;
  21.  OLen:Byte absolute OverBuff;
  22.  Activity:Boolean;
  23.  
  24.    Procedure GotoCpos;
  25.    Var Zpos:Byte;
  26.    Begin
  27.     MPos:=0; ZPos:=0;
  28.     While ZPos<Cpos Do
  29.       Begin
  30.        MPos:=Succ(MPos);
  31.        If mask[MPos] in ValidMaskTokenSet then ZPos:=Succ(ZPos);
  32.       End;
  33.     GotoXY(X+Pred(MPos),Y);
  34.    End;
  35.  
  36.    Procedure ZWrite(Floater:Boolean);
  37.    Var OldZLen,MaskPos,ZPos:Byte;
  38.    Begin
  39.     While (OLen>0) and (MaxLen>ZLen) Do
  40.       Begin
  41.        Z:=Z+OverBuff[1];
  42.        Delete(OverBuff,1,1);
  43.       End;
  44.     OldZLen:=ZLen;
  45.     If (MaxLen-ZLen>0) and Floater then Z:=Z+EndTag;
  46.     If MaxLen-ZLen>0 then Z:=Z+Spaces(MaxLen-ZLen);
  47.     ZPos:=0;
  48.     For MaskPos:=1 to MaskLen do
  49.        Case mask[MaskPos] of
  50.           '!','#','&','*'..'+','/','<'..'@','['..'^','{'..'~':
  51.              Begin
  52.               BInc(ZPos);
  53.               QWrite(Z[ZPos],X+pred(MaskPos),Y,0,0);
  54.              End;
  55.           Else QWrite(Mask[MaskPos],X+pred(MaskPos),Y,0,0);
  56.        End; {case}
  57.     ZLen:=OldZLen;
  58.     If option<>'W' then GotoCpos;
  59.    End;
  60.  
  61.    Procedure FunctionKey;
  62.    Begin
  63.     Case Scan of
  64.         ArrowRtKey:If (Cpos<Succ(Zlen)) and (Cpos<MaxLen) then
  65.                      Begin
  66.                       Cpos:=Succ(Cpos); GotoCpos;
  67.                       Scan:=0;
  68.                      End;
  69.        ArrowLfKey:If Cpos<>1 then
  70.                     Begin
  71.                      If (Cpos=Succ(ZLen)) and (Z[ZLen]=' ') then
  72.                        Begin
  73.                         Delete(Z,Zlen,1);
  74.                         Cpos:=Pred(Cpos);
  75.                         ZWrite(Floater);
  76.                        End
  77.                      Else
  78.                        Begin
  79.                         Cpos:=Pred(Cpos);
  80.                         GotoCpos;
  81.                        End;
  82.                      Scan:=0;
  83.                     End;
  84.        HomeKey:If Cpos>1 then
  85.                  Begin
  86.                   Cpos:=1; GotoCpos;
  87.                   If Z[ZLen]=' ' then
  88.                     Begin
  89.                      Z:=RSpaceWhack(Z);
  90.                      ZWrite(Floater);
  91.                     End;
  92.                   Scan:=0;
  93.                  End;
  94.        EndKey:If ((Cpos<succ(ZLen)) and (ZLen<MaxLen)) or (Cpos<ZLen) or (Z[ZLen]=' ') then
  95.                 Begin
  96.                  If Z[ZLen]=' ' Then
  97.                    Begin
  98.                     Z:=RSpaceWhack(Z);
  99.                     ZWrite(Floater);
  100.                    End;
  101.                  If ZLen<MaxLen then Cpos:=Succ(ZLen)
  102.                  Else Cpos:=ZLen;
  103.                  GotoCpos;
  104.                  Scan:=0;
  105.                 End;
  106.        BkSpKey:If Cpos>1 then
  107.                  Begin
  108.                   Cpos:=Pred(Cpos); Delete(Z,Cpos,1);
  109.                   ZWrite(Floater);
  110.                   Scan:=0;
  111.                  End;
  112.        DelKey:If Cpos<=ZLen then
  113.                 Begin
  114.                  Delete(Z,Cpos,1); ZWrite(Floater);
  115.                  Scan:=0;
  116.                 End;
  117.        CtrlBkSpKey:If Cpos>1 then
  118.                      Begin
  119.                       Delete(Z,1,Pred(Cpos));
  120.                       Cpos:=1; ZWrite(Floater);
  121.                       Scan:=0;
  122.                      End;
  123.        CtrlDelKey:If Cpos<=ZLen then
  124.                     Begin
  125.                      Delete(Z,Cpos,ZLen-Pred(Cpos));
  126.                      OLen:=0; ZWrite(Floater);
  127.                      Scan:=0;
  128.                     End;
  129.     End; {case}
  130.    End;
  131.  
  132.    Procedure TypeChar;
  133.    Begin
  134.     If Ascii in AsciiExitSet then exit;
  135.     If not activity then
  136.       Begin
  137.        activity:=True;
  138.        if AutoClear and (Cpos=1) then
  139.          Begin
  140.           ZLen:=0;
  141.           CPos:=1;
  142.          End;
  143.       End;
  144.     If (Cpos=MaxLen) and (Ascii=' ') and (ZLen=Pred(MaxLen)) then
  145.       Begin
  146.        Scan:=FullStringExit;
  147.        Exit;
  148.       End;
  149.     If BitCheck(7,OldKBStatus) then
  150.       Begin
  151.        Insert(Ascii,Z,Cpos);
  152.        If ZLen>MaxLen then
  153.          Begin
  154.           Insert(Z[ZLen],OverBuff,1);
  155.           Delete(Z,ZLen,1);
  156.          End;
  157.       End
  158.     Else
  159.       Begin
  160.        Z[CPos]:=Ascii;
  161.        If Cpos>Zlen then Zlen:=Cpos;
  162.       End;
  163.     Cpos:=Succ(Cpos);
  164.     If cpos>MaxLen then
  165.       Begin
  166.        Scan:=FullStringExit;
  167.        Cpos:=Pred(Cpos);
  168.       End;
  169.     ZWrite(Floater);
  170.    End;
  171.  
  172. Begin
  173.  OLen:=0;
  174.  MaxLen:=0;
  175.  If SetCposto1onEntry then cpos:=1;
  176.  If cpos>ZLen then cpos:=succ(ZLen);
  177.  If option='W' then
  178.    Begin
  179.     For I:=1 to MaskLen do
  180.        Case mask[I] of
  181.           '!','#','&','*'..'+','/','<'..'@','['..'^','{'..'~':BInc(MaxLen);
  182.        End; {case}
  183.     If Cpos>MaxLen then Cpos:=MaxLen;
  184.    End
  185.  Else
  186.    Begin
  187.     For I:=1 to MaskLen do
  188.       Begin
  189.        If Mask[I] in ValidMaskTokenSet then
  190.          Begin
  191.           BInc(MaxLen);
  192.           QWriteAtt(1,X+Pred(I),Y,LFCC,0);
  193.          End
  194.        Else QWriteAtt(1,X+Pred(I),Y,NFCC,0);
  195.       End;
  196.     If Cpos>MaxLen then Cpos:=MaxLen;
  197.     ZWrite(Floater);
  198.     Activity:=False;
  199.     SetHelp(HelpLine,HelpNum);
  200.     Cursor(on);
  201.     Repeat
  202.        ReadKey(InsertStatusLine,ScanExitSet+LocalExitSet,AsciiExitSet,
  203.                Mask[Mpos],Scan,Ascii);
  204.        If Ascii=#0 then FunctionKey Else TypeChar;
  205.     Until (Scan in ScanExitSet) or (Ascii in AsciiExitSet);
  206.     Cursor(off);
  207.     If Z[ZLen]=' ' then Z:=RSpaceWhack(Z);
  208.    End;
  209.  If DeadColorsOnExit or (option='W') then QWriteAtt(MaskLen,x,y,DFCC,0);
  210.  ZWrite(off);
  211. End;
  212.  
  213. Procedure ReadChar(option:char;
  214.                    DeadColorsOnExit:Boolean;
  215.                    HelpLine,HelpNum,X,Y:Byte;
  216.                    ScanExitSet:ByteSetType;
  217.                    Var Scan:Byte;
  218.                    AsciiExitSet:CharSetType;
  219.                    Var Ascii:Char;
  220.                    MaskSet:CharSetType;
  221.                    Var Z:Char);
  222. Begin
  223.  QWrite(Z,x,y,0,1);
  224.  If option<>'W' then
  225.    Begin
  226.     SetHelp(HelpLine,HelpNum);
  227.     Cursor(on);
  228.     Repeat
  229.        QWriteAtt(1,x,y,LFCC,0);
  230.        ReadKey(Off,ScanExitSet,AsciiExitSet+MaskSet,#0,Scan,Ascii);
  231.        If Ascii in MaskSet then
  232.          Begin
  233.           Z:=Ascii; QWrite(Z,x,y,0,0);
  234.           Ascii:=#0; Scan:=FullStringExit;
  235.          End;
  236.     Until (Scan in ScanExitSet) or (Ascii in AsciiExitSet);
  237.     Cursor(off);
  238.    End;
  239.  If DeadColorsOnExit or (option='W') then QWriteAtt(1,x,y,DFCC,0);
  240. End;
  241.  
  242. Procedure ReadReal(option:char;
  243.                    AutoClear,InsertStatusLine,SetCposTo1onEntry,
  244.                    NegativeNumbers,DeadColorsOnExit:Boolean;
  245.                    HelpLine,HelpNum,X,Y:Byte;
  246.                    ScanExitSet:ByteSetType;
  247.                    Var Scan:Byte;
  248.                    AsciiExitSet:CharSetType;
  249.                    Var Ascii:char;
  250.                    IntFLen,ManFLen:Byte; {Integral & Mantissa Field Lengths}
  251.                    Var Cpos:Byte;
  252.                    Var Z:Real);
  253. Var
  254.    IntStr,ManStr,ManMask:String[30];
  255.    IntLen:Byte absolute IntStr;
  256.    MaxLen,ManPos1,IntPos1,NegPos2:Byte;
  257.    FourDigitLeader,Negative,Activity,IntegralSection:Boolean;
  258.    AsciiMoveRightSet,NegAsciiExitSet:CharSetType;
  259.    ScanMoveRightSet,ScanMoveLeftSet,IntScanExitSet:ByteSetType;
  260.  
  261.    Procedure WriteNegative;
  262.    Var LNegChar,RNegChar:char;
  263.    Begin
  264.     If Negative then
  265.       Begin
  266.        LNegChar:='<';
  267.        RNegChar:='>';
  268.       End
  269.     Else
  270.       Begin
  271.        LNegChar:=' ';
  272.        RNegChar:=' ';
  273.       End;
  274.     QWrite(LNegChar,x,y,0,0);
  275.     QWrite(RNegChar,NegPos2,y,0,0);
  276.    End;
  277.  
  278.    Function Fpos(IntPos:Byte):Byte;
  279.    Begin
  280.     If (FourDigitLeader and (IntPos+4>MaxLen)) then Fpos:=MaxLen-IntPos
  281.     Else Fpos:=IntFLen-(IntPos+(pred(IntPos) div 3));
  282.    End;
  283.  
  284.    Procedure GotoCpos;
  285.    Begin
  286.     GotoXY(IntPos1+Fpos(succ(IntLen-Cpos)),Y);
  287.     If (Cpos=0) and ((IntLen mod 3)=0) and not(FourDigitLeader and (MaxLen-(IntLen-cpos)<5)) then
  288.        QWrite(' ',0,0,0,2);
  289.    End;
  290.  
  291.    Procedure IntWrite;
  292.    Var I:Byte;
  293.    Begin
  294.     Activity:=True;
  295.     While (IntLen>1) and (IntStr[1]='0') and (cpos>0) Do
  296.       Begin
  297.        Delete(IntStr,1,1);
  298.        Cpos:=Pred(Cpos);
  299.       End;
  300.     If IntLen=0 then
  301.       Begin
  302.        IntStr:='0';
  303.        Cpos:=1;
  304.       End;
  305.     If (IntStr='0') and negativeNumbers then
  306.        If ManStr=StringOf(ManFLen,'0') then
  307.          Begin
  308.           Negative:=False;
  309.           WriteNegative;
  310.          End;
  311.     GotoXY(IntPos1,y);
  312.     If MaxLen-IntLen>0 then QWrite(Spaces(Fpos(IntLen)),0,0,LFCC,2);
  313.     For I:=1 to IntLen Do
  314.       Begin
  315.        QWrite(IntStr[I],0,0,LFCC,2);
  316.        If (((IntLen-I) mod 3)=0) and (I<>IntLen) and not(FourDigitLeader and (MaxLen-IntLen=0) and (I=1)) then
  317.           QWrite(',',0,0,NFCC,2);
  318.       End;
  319.     GotoCpos;
  320.    End;
  321.  
  322.    Procedure GetRealStr;
  323.  
  324.       Procedure NegativeAdjust;
  325.       Begin
  326.        If Ascii='-' then Negative:=True Else Negative:=False;
  327.        WriteNegative;
  328.        Ascii:=#0;
  329.        If IntegralSection then GotoCpos;
  330.       End;
  331.  
  332.       Procedure GetIntStr;
  333.  
  334.          Procedure ClearMantissa;
  335.          Begin
  336.           If ManFLen>0 then
  337.             Begin
  338.              ManStr:=StringOf(ManFLen,'0');
  339.              QWrite(ManStr,ManPos1,y,0,0);
  340.             End;
  341.          End;
  342.  
  343.          Procedure FunctionKey;
  344.          Begin
  345.           Case Scan of
  346.               ArrowRtKey:If Cpos<Intlen then
  347.                            Begin
  348.                             Cpos:=Succ(Cpos);
  349.                             GotoCpos;
  350.                             Scan:=0;
  351.                            End;
  352.              ArrowLfKey:If (Cpos>1) or ((Cpos=1)and (IntLen<MaxLen)) then
  353.                           Begin
  354.                            Cpos:=pred(Cpos);
  355.                            GotoCpos;
  356.                            Scan:=0;
  357.                           End;
  358.              HomeKey:If (Cpos>1) or ((Cpos=1) and (IntLen<MaxLen)) then
  359.                        Begin
  360.                         If IntLen=MaxLen then Cpos:=1 Else Cpos:=0;
  361.                         GotoCpos;
  362.                         Scan:=0;
  363.                        End;
  364.              EndKey:If Cpos<IntLen then
  365.                       Begin
  366.                        Cpos:=IntLen;
  367.                        GotoCpos;
  368.                        Scan:=0;
  369.                       End;
  370.              BkSpKey:If Cpos>0 then
  371.                        Begin
  372.                         Delete(IntStr,Cpos,1);
  373.                         Cpos:=Pred(Cpos);
  374.                         IntWrite;
  375.                         Scan:=0;
  376.                        End;
  377.              DelKey:If IntLen>0 then
  378.                       Begin
  379.                        If Cpos=IntLen then Cpos:=Pred(Cpos);
  380.                        Delete(IntStr,Succ(Cpos),1);
  381.                        IntWrite;
  382.                        Scan:=0;
  383.                       End;
  384.              CtrlBkSpKey:If Cpos>0 then
  385.                            Begin
  386.                             Delete(IntStr,1,Cpos);
  387.                             Cpos:=0;
  388.                             IntWrite;
  389.                             Scan:=0;
  390.                            End;
  391.              CtrlDelKey:If (Cpos<IntLen) or ((ManFLen>0) and (ManStr<>StringOf(ManFLen,'0'))) then
  392.                           Begin
  393.                            ClearMantissa;
  394.                            If Cpos<IntLen then
  395.                              Begin
  396.                               IntLen:=Cpos;
  397.                               IntWrite;
  398.                              End;
  399.                            Scan:=0;
  400.                           End;
  401.           End; {case}
  402.           If (Cpos>0) and (IntStr[1]='0') and (IntLen>1) then IntWrite;
  403.          End;
  404.  
  405.          Procedure TypeChar;
  406.          Begin
  407.           If Ascii in AsciiMoveRightSet+AsciiExitSet then Exit;
  408.           If not activity and AutoClear and (Cpos=IntLen) then
  409.             Begin
  410.              IntLen:=0;
  411.              CPos:=0;
  412.              ClearMantissa;
  413.             End;
  414.           If (IntLen<MaxLen) and (BitCheck(7,OldKBStatus) or (Cpos=IntLen)) then
  415.             Begin
  416.              Cpos:=succ(Cpos);
  417.              Insert(Ascii,IntStr,Cpos);
  418.              If Cpos=MaxLen then scan:=FullStringExit;
  419.             End
  420.           Else
  421.             Begin
  422.              If cpos=0 then
  423.                Begin
  424.                 Insert(Ascii,IntStr,1);
  425.                 Cpos:=2;
  426.                End
  427.              Else
  428.                Begin
  429.                 IntStr[CPos]:=Ascii;
  430.                 If Cpos=MaxLen then scan:=FullStringExit
  431.                 Else Cpos:=Succ(Cpos);
  432.                End;
  433.             End;
  434.           Ascii:=#0;
  435.           IntWrite;
  436.          End;
  437.  
  438.       Begin {procedure GetIntStr}
  439.        GotoCpos;
  440.        Repeat
  441.           ReadKey(InsertStatusLine,ScanExitSet+IntScanExitSet+ScanMoveRightSet,
  442.                   AsciiExitSet+AsciiMoveRightSet+NegAsciiExitSet,'&',
  443.                   Scan,Ascii);
  444.           If Ascii in NegAsciiExitSet then NegativeAdjust;
  445.           If Ascii=#0 then FunctionKey Else TypeChar;
  446.        Until (Scan in ScanExitSet+ScanMoveRightSet) or (Ascii in AsciiExitSet+AsciiMoveRightSet);
  447.       End; {procedure GetIntStr}
  448.  
  449.       Procedure GetManStr;
  450.       Var ManLen:Byte absolute ManStr;
  451.       Begin
  452.        Repeat
  453.           ReadString('R',Off,InsertStatusLine,off,off,off,0,0,
  454.                      ManPos1,y,ScanExitSet+ScanMoveLeftSet,Scan,
  455.                      AsciiExitSet+NegAsciiExitSet,Ascii,Cpos,ManStr,ManMask);
  456.           If Ascii in NegAsciiExitSet then NegativeAdjust;
  457.        Until (Scan in ScanExitSet+ScanMoveLeftSet) or (Ascii in AsciiExitSet);
  458.        If ManLen<ManFLen then
  459.          Begin
  460.           ManStr:=ManStr+StringOf(ManFLen-ManLen,'0');
  461.           QWrite(ManStr,ManPos1,y,0,0);
  462.          End;
  463.       End;
  464.  
  465.       Procedure Flip;
  466.       Begin
  467.        IntegralSection:=Not IntegralSection;
  468.        Scan:=0; Ascii:=#0;
  469.       End;
  470.  
  471.       Procedure SetSectionAndCpos;
  472.       Begin
  473.        If Cpos=1 then
  474.           If IntFLen>0 then
  475.             Begin
  476.              IntegralSection:=True;
  477.              Cpos:=IntLen;
  478.             End
  479.           Else
  480.              IntegralSection:=False
  481.        Else
  482.           If Cpos>Succ(ManFLen) then
  483.             Begin
  484.              Cpos:=pred(Cpos-ManFLen);
  485.              IntegralSection:=True;
  486.             End
  487.           Else
  488.             Begin
  489.              Cpos:=Pred(Cpos);
  490.              IntegralSection:=False;
  491.             End;
  492.       End;
  493.  
  494.    Var Dummy:Integer;
  495.    Begin {procedure GetRealStr}
  496.     Activity:=False;
  497.     SetHelp(HelpLine,HelpNum); Cursor(on);
  498.     IntScanExitSet:=[ArrowLfKey,ArrowRtKey,HomeKey,EndKey,BkSpKey,DelKey,
  499.                      CtrlBkSpKey,CtrlDelKey];
  500.     SetSectionAndCpos;
  501.     Repeat
  502.        If IntegralSection then
  503.          Begin
  504.           GetIntStr;
  505.           If ((Scan in [ArrowRtKey,EndKey,FullStringExit]) or (Ascii='.')) and (ManFLen>0) then
  506.             Begin
  507.              If Scan=EndKey then Cpos:=ManFLen Else Cpos:=1;
  508.              Flip;
  509.             End;
  510.          End
  511.        Else
  512.          Begin
  513.           GetManStr;
  514.           If (Scan in [ArrowLfKey,HomeKey]) and (IntFLen>0) then
  515.             Begin
  516.              If Scan=HomeKey then
  517.                 If IntLen<MaxLen then Cpos:=0 Else Cpos:=1
  518.              Else Cpos:=IntLen;
  519.              Flip;
  520.             End;
  521.          End;
  522.     Until (Scan in ScanExitSet) or (Ascii in AsciiExitSet);
  523.     Cursor(off);
  524.     Val(IntStr+'.'+ManStr,Z,dummy);
  525.     If NegativeNumbers and Negative then Z:=-Z;
  526.     If IntegralSection then
  527.        If Cpos=IntLen then Cpos:=1 Else Cpos:=succ(Cpos+ManFLen)
  528.     Else
  529.        Cpos:=Succ(cpos);
  530.    End; {procedure GetRealStr}
  531.  
  532.    Procedure Initialize;
  533.    Begin
  534.     IntPos1:=x;
  535.     ManPos1:=succ(x+IntFLen);
  536.     If ManFLen=0 then ManPos1:=pred(ManPos1);
  537.     If IntFLen=0 then ManPos1:=succ(ManPos1);
  538.     If NegativeNumbers then
  539.       Begin
  540.        IntPos1:=succ(IntPos1);
  541.        ManPos1:=succ(ManPos1);
  542.        NegPos2:=ManPos1+ManFLen;
  543.        NegAsciiExitSet:=['-','+'];
  544.        If Z<0 then
  545.          Begin
  546.           Negative:=True;
  547.           Z:=-Z;
  548.          End
  549.        Else Negative:=False;
  550.        WriteNegative;
  551.        If option<>'W' then
  552.          Begin
  553.           QWriteAtt(1,x,y,NFCC,0);
  554.           QWriteAtt(1,NegPos2,y,NFCC,0);
  555.          End;
  556.       End
  557.     Else
  558.       Begin
  559.        NegPos2:=pred(ManPos1+ManFLen);
  560.        NegAsciiExitSet:=[];
  561.       End;
  562.     If SetCposTo1onEntry or (Option='W') then Cpos:=1;
  563.     If IntFLen>0 then
  564.       Begin
  565.        ScanMoveLeftSet:=[ArrowLfKey,HomeKey];
  566.        MaxLen:=IntFLen-(IntFLen div 4);
  567.        IntStr:=LSpaceWhack(form(StringOf(20,'#'),Int(Z)));
  568.        FourDigitLeader:=((IntFLen mod 4)=0);
  569.        If FourDigitLeader then MaxLen:=succ(MaxLen);
  570.        IntWrite;
  571.       End
  572.     Else
  573.       Begin
  574.        ScanMoveLeftSet:=[];
  575.        MaxLen:=0;
  576.        IntStr:='';
  577.        QWrite('0',IntPos1,y,NFCC,1);
  578.       End;
  579.     If ManFLen>0 then
  580.       Begin
  581.        ScanMoveRightSet:=[ArrowRtKey,EndKey,FullStringExit];
  582.        AsciiMoveRightSet:=['.'];
  583.        ManStr:=form(StringOf(18,'#')+'.'+StringOf(ManFLen,'#'),Z);
  584.        Delete(ManStr,1,19);
  585.        QWrite('.',pred(ManPos1),y,NFCC,2);
  586.        QWrite(ManStr,0,0,LFCC,0);
  587.        ManMask:=StringOf(ManFLen,'&');
  588.       End
  589.     Else
  590.       Begin
  591.        ScanMoveRightSet:=[];
  592.        AsciiMoveRightSet:=[];
  593.        ManMask:='';
  594.        ManStr:='';
  595.       End;
  596.    End;
  597.  
  598.    Procedure Finalize;
  599.    Begin
  600.     If (Option='W') or DeadColorsOnExit then
  601.        QWriteAtt(succ(NegPos2-x),x,y,DFCC,0);
  602.    End;
  603.  
  604. Begin {procedure ReadReal}
  605.  Initialize;
  606.  If option<>'W' then GetRealStr;
  607.  Finalize;
  608. End; {procedure ReadReal}
  609.  
  610. Procedure ReadInt(Option:char;
  611.                   AutoClear,InsertStatusLine,SetCposTo1onEntry,
  612.                   NegativeNumbers,DeadColorsOnExit:Boolean;
  613.                   HelpLine,HelpNum,X,Y:Byte;
  614.                   ScanExitSet:ByteSetType;
  615.                   Var Scan:Byte;
  616.                   AsciiExitSet:CharSetType;
  617.                   Var Ascii:Char;
  618.                   FieldLength:Byte;
  619.                   Var Cpos:Byte;
  620.                   Var Z:Integer);
  621. Var
  622.  TempReal:Real;
  623.  DummyKey:Char;
  624. Begin
  625.  Repeat
  626.     TempReal:=Z;
  627.     ReadReal(Option,AutoClear,InsertStatusLine,SetCposTo1onEntry,
  628.              NegativeNumbers,DeadColorsOnExit,HelpLine,HelpNum,X,Y,
  629.              ScanExitSet,Scan,AsciiExitSet,Ascii,FieldLength,0,
  630.              Cpos,TempReal);
  631.     If scan=EscKey then TempReal:=Z;
  632.     If Not((TempReal<32767) and (TempReal>-32767)) then
  633.       Begin
  634.        PopUpArray[1]:='You must use a smaller number.';
  635.        PopUpArray[2]:=ToContinue;
  636.        PopNote(1,1,DummyKey);
  637.       End;
  638.  Until (TempReal<32767) and (TempReal>-32767);
  639.  Z:=Round(TempReal);
  640. End;
  641.  
  642. Procedure ReadByte(Option:char;
  643.                    AutoClear,InsertStatusLine,SetCposTo1onEntry,
  644.                    DeadColorsOnExit:Boolean;
  645.                    HelpLine,HelpNum,X,Y:Byte;
  646.                    ScanExitSet:ByteSetType;
  647.                    Var Scan:Byte;
  648.                    AsciiExitSet:CharSetType;
  649.                    Var Ascii:Char;
  650.                    FieldLength:Byte;
  651.                    Var Cpos:Byte;
  652.                    Var Z:Byte);
  653. Var
  654.  TempInt:Integer;
  655.  DummyKey:Char;
  656. Begin
  657.  Repeat
  658.     TempInt:=Z;
  659.     ReadInt(Option,AutoClear,InsertStatusLine,SetCposTo1onEntry,
  660.              Off,DeadColorsOnExit,HelpLine,HelpNum,X,Y,
  661.              ScanExitSet,Scan,AsciiExitSet,Ascii,FieldLength,
  662.              Cpos,TempInt);
  663.     If scan=EscKey then TempInt:=Z;
  664.     If Not(TempInt in [0..255]) then
  665.       Begin
  666.        PopUpArray[1]:='You must use a smaller number.';
  667.        PopUpArray[2]:=ToContinue;
  668.        PopNote(1,1,DummyKey);
  669.       End;
  670.  Until TempInt in [0..255];
  671.  Z:=TempInt;
  672. End;
  673.  
  674. Procedure ReadDate(Option:char;
  675.                    SetCposTo1onEntry:Boolean;
  676.                    HelpLine,HelpNum,
  677.                    x,y:byte;
  678.                    ScanExitSet:ByteSetType;
  679.                    Var Scan:Byte;
  680.                    AsciiExitSet:CharSetType;
  681.                    Var Ascii:char;
  682.                    Var CPos:Byte;
  683.                    Var Jul:JulType;
  684.                    OtherMode:Byte;  {1=day of week, 2=TFN, 3=both, 0=None}
  685.                    RoundYear:Char);      { RoundYear : 'F'=Forward  }
  686.                                          {             'B'=Backward }
  687.                                          {             'N'=Nearest  }
  688. Const
  689.  DateScanExitSet:ByteSetType=[ArrowRtKey,ArrowLfKey,BkSpKey,EscKey];
  690.  NextSectionAsciiSet:CharSetType=['/','-','+','\','.',','];
  691.  StartOver=255;
  692. Var
  693.  Greg,OldGreg:GregType;
  694.  dummy:Integer;
  695.  Section:Byte;
  696.  key1,PKey:char;
  697.  TFN,MTWTFSS,NoDate:Boolean;
  698.  DateAsciiExitSet,AsciiOtherSet:CharSetType;
  699.  
  700.    Function DateString(Month,Day:Byte;Year:Integer):String10;
  701.    Begin
  702.     Case Year of
  703.        0:DateString:='TFN      ';
  704.        1..7:DateString:=LeftText(DayName[Year],9);
  705.        Else DateString:=form('@@',Month)+'-'+form('@@',Day)+'-'+form('@@',(Year mod 100));
  706.     End; {case}
  707.    End;
  708.  
  709.    Procedure WriteDate;
  710.    Begin
  711.     QWrite(DateString(Greg.Month,Greg.Day,Greg.Year),x,y,0,0);
  712.    End;
  713.  
  714.    Procedure SetNormalColorMode;
  715.    Begin
  716.     QWriteAtt(8,x,y,LFCC,0);
  717.     QWriteAtt(1,x+2,y,NFCC,0);
  718.     QWriteAtt(1,x+5,y,NFCC,0);
  719.     QWrite(' ',x+8,y,7,0);
  720.    End;
  721.  
  722.    Procedure GetOther_StageTwo;
  723.    Var
  724.     AsciiWeekSet:CharSetType;
  725.     FirstChar:Char;
  726.  
  727.       Procedure FinishUp;
  728.       Begin
  729.        Greg.Day:=OldGreg.Day;
  730.        Greg.Month:=OldGreg.Month;
  731.        WriteDate;
  732.        Ascii:=#0; Scan:=FullStringExit;
  733.       End;
  734.  
  735.       Procedure GetOther_StageThree;
  736.       Var NumericSet:CharSetType;
  737.       Begin
  738.        QWrite(Ascii+' ',x,y,LFCC,0);
  739.        QWrite(Spaces(6),x+2,y,NFCC,0);
  740.        QWrite(' ',x+8,y,7,0);
  741.        GotoXY(succ(x),y);
  742.        If Ascii='T' then
  743.           If TFN then AsciiWeekSet:=['U','H','F']
  744.           Else AsciiWeekSet:=['U','H']
  745.        Else AsciiWeekSet:=['A','U'];
  746.        If NoDate then NumericSet:=[] Else NumericSet:=['0'..'9'];
  747.        FirstChar:=Ascii;
  748.        ReadKey(off,ScanExitSet+[ArrowLfKey,BkSpKey],
  749.                AsciiExitSet+AsciiWeekSet+NumericSet,#0,scan,Ascii);
  750.        If Ascii in AsciiWeekSet then
  751.          Begin
  752.           Case Ascii of
  753.              'H':Greg.Year:=4;
  754.              'F':Greg.Year:=0;
  755.              'A':Greg.Year:=6;
  756.              'U':If FirstChar='T' then Greg.Year:=2
  757.                  Else Greg.Year:=7;
  758.           End; {case}
  759.           FinishUp;
  760.          End
  761.        Else
  762.          Begin
  763.           If Scan in [ArrowLfKey,BkSpKey] then Scan:=StartOver;
  764.           Greg:=OldGreg;
  765.           WriteDate;
  766.          End;
  767.       End;
  768.  
  769.    Begin {procedure GetOther_StageTwo}
  770.     If Not MTWTFSS then
  771.       Begin
  772.        Greg.Year:=0;
  773.        FinishUp;
  774.       End
  775.     Else
  776.       Begin
  777.        If Ascii in ['M','W','F'] then
  778.          Begin
  779.           Case Ascii of
  780.              'M':Greg.Year:=1;
  781.              'W':Greg.Year:=3;
  782.              'F':Greg.Year:=5;
  783.           End; {case}
  784.           FinishUp;
  785.          End
  786.        Else
  787.           GetOther_StageThree;
  788.       End;
  789.    End;
  790.  
  791.    Procedure GetDate;
  792.  
  793.       Procedure CheckDate;
  794.       Begin
  795.        If (Greg.Month in [4,6,9,11]) and (Greg.Day=31) then
  796.          Begin
  797.           PopUpArray[1]:=MonthName[Greg.Month]+' has only 30 days in it.';
  798.           PopUpArray[2]:=ToTryAgain;
  799.           PopUpArray[3]:=ToChangeTo+DateString(Greg.Month,30,Greg.Year)+'.';
  800.           PopUpArray[4]:=ToChangeTo+DateString(succ(Greg.Month),1,Greg.Year)+'.';
  801.           PopUpArray[5]:=ToChangeTo+DateString(OldGreg.Month,OldGreg.Day,OldGreg.Year)+' (default).';
  802.           PopUpKey[2]:='A';
  803.           PopUpKey[3]:='B';
  804.           PopUpKey[4]:='C';
  805.           PopNote(1,4,PKey);
  806.           Case PKey of
  807.              #0:Begin
  808.                   section:=0;
  809.                   scan:=0;
  810.                  End;
  811.              'A':Begin
  812.                   Greg.Day:=30;
  813.                   WriteDate;
  814.                  End;
  815.              'B':Begin
  816.                   Greg.Day:=1;
  817.                   Greg.Month:=succ(Greg.Month);
  818.                   WriteDate;
  819.                  End;
  820.              'C':Begin
  821.                   Greg:=OldGreg;
  822.                   WriteDate;
  823.                  End;
  824.           End; {case}
  825.          End;
  826.        If (Greg.Month=2) and ((Greg.Day>29) or ((Greg.Day=29) and ((Greg.Year mod 4)<>0))) then
  827.          Begin
  828.           If (Greg.Year mod 4)>0 then
  829.             Begin
  830.              PopUpArray[1]:='There are only 28 days';
  831.              PopUpArray[2]:='in February this year.';
  832.              PopUpArray[3]:=ToTryAgain;
  833.              PopUpArray[4]:=ToChangeTo+DateString(3,Greg.Day-28,Greg.Year)+'.';
  834.              PopUpArray[5]:=ToChangeTo+DateString(2,28,Greg.Year)+'.';
  835.              PopUpArray[6]:=ToChangeTo+DateString(OldGreg.Month,OldGreg.Day,OldGreg.Year)+' (default).';
  836.              PopUpKey[2]:='A';
  837.              PopUpKey[3]:='B';
  838.              PopUpKey[4]:='C';
  839.              PopNote(2,4,PKey);
  840.              Case PKey of
  841.                 #0:Begin
  842.                     section:=0;
  843.                     scan:=0;
  844.                    End;
  845.                 'A':Begin
  846.                      Greg.Month:=3;
  847.                      Greg.Day:=Greg.Day-28;
  848.                      WriteDate;
  849.                     End;
  850.                 'B':Begin
  851.                      Greg.Day:=28;
  852.                      WriteDate;
  853.                     End;
  854.                 'C':Begin
  855.                      Greg:=OldGreg;
  856.                      WriteDate;
  857.                     End;
  858.              End; {case}
  859.             End
  860.           Else
  861.             Begin
  862.              PopUpArray[1]:='There are never more than';
  863.              PopUpArray[2]:='29 days in February.';
  864.              PopUpArray[3]:=ToTryAgain;
  865.              PopUpArray[4]:=ToChangeTo+DateString(3,Greg.Day-29,Greg.Year)+'.';
  866.              PopUpArray[5]:=ToChangeTo+DateString(2,29,Greg.Year)+'.';
  867.              PopUpArray[6]:=ToChangeTo+DateString(OldGreg.Month,OldGreg.Day,OldGreg.Year)+' (default).';
  868.              PopUpKey[2]:='A';
  869.              PopUpKey[3]:='B';
  870.              PopUpKey[4]:='C';
  871.              PopNote(2,4,PKey);
  872.              Case PKey of
  873.                 #0:Begin
  874.                     section:=0;
  875.                     scan:=0;
  876.                    End;
  877.                 'A':Begin
  878.                      Greg.Month:=3;
  879.                      Greg.Day:=Greg.Day-29;
  880.                      WriteDate;
  881.                     End;
  882.                 'B':Begin
  883.                      Greg.Day:=29;
  884.                      WriteDate;
  885.                     End;
  886.                 'C':Begin
  887.                      Greg:=OldGreg;
  888.                      WriteDate;
  889.                     End;
  890.              End; {case}
  891.             End; {else}
  892.          End; {if}
  893.       End; {procedure}
  894.  
  895.       Procedure CheckMonth(GivenMonth:String2);
  896.       Begin
  897.        Greg.Month:=ByteVal(GivenMonth);
  898.        If not(Greg.Month in [1..12]) then
  899.          Begin
  900.           WriteDate;
  901.           PopUpArray[1]:='The number '+form('@@',Greg.Month)+' is not recognized as a';
  902.           PopUpArray[2]:='valid month.  You must enter a number in';
  903.           PopUpArray[3]:='the range of 1 (Jan) through 12 (Dec).';
  904.           PopUpArray[4]:=ToContinue;
  905.           PopNote(3,1,PKey);
  906.           section:=0;
  907.           scan:=0;
  908.           Greg.Month:=OldGreg.Month;
  909.          End;
  910.        WriteDate;
  911.       End;
  912.  
  913.       Procedure CheckDay(GivenDay:String2);
  914.       Begin
  915.        Greg.Day:=ByteVal(GivenDay);
  916.        If not(greg.Day in [1..31]) then
  917.          Begin
  918.           WriteDate;
  919.           PopUpArray[1]:='There cannot be '+form('@@',Greg.Day)+' days';
  920.           PopUpArray[2]:='in any month.';
  921.           PopUpArray[3]:=ToContinue;
  922.           PopNote(2,1,PKey);
  923.           section:=3;
  924.           scan:=0;
  925.           Greg.Day:=OldGreg.Day;
  926.          End;
  927.        WriteDate;
  928.       End;
  929.  
  930.       Procedure CheckYear(GivenYear:String2);
  931.       var Dif:Integer;
  932.       Begin
  933.        val(GivenYear,Greg.Year,dummy);
  934.        If RoundYear='F' then
  935.          Begin
  936.           if length(givenYear)=1 then
  937.             Begin
  938.              Greg.Year:=Greg.Year+(OldGreg.Year div 10)*10-20;
  939.              While Greg.Year<OldGreg.Year Do Greg.Year:=Greg.Year+10;
  940.             End
  941.           Else
  942.             Begin
  943.              Greg.Year:=Greg.Year+(OldGreg.Year div 100)*100-200;
  944.              While Greg.Year<OldGreg.Year Do Greg.Year:=Greg.Year+100;
  945.             End;
  946.          End; {If}
  947.        If RoundYear='B' then
  948.          Begin
  949.           if Length(GivenYear)=1 then
  950.            Begin
  951.             Greg.Year:=Greg.Year+(OldGreg.Year div 10)*10+20;
  952.             While Greg.Year>OldGreg.Year Do Greg.Year:=Greg.Year-10;
  953.            End
  954.           Else
  955.             Begin
  956.              Greg.Year:=Greg.Year+(OldGreg.Year div 100)*100+200;
  957.              While Greg.Year>OldGreg.Year Do Greg.Year:=Greg.Year-100;
  958.             End;
  959.          End;
  960.        If RoundYear='N' then
  961.          Begin
  962.           If Length(GivenYear)=1 then
  963.             Begin
  964.              Dif:=Greg.Year-(OldGreg.Year mod 10);
  965.              If Dif=0 then Greg.Year:=OldGreg.Year;
  966.              If Abs(Dif) in [1..4] then Greg.Year:=OldGreg.Year+Dif;
  967.              If Dif in [6..9] then Greg.Year:=OldGreg.Year-10+Dif;
  968.              If -Dif in [6..9] then Greg.Year:=OldGreg.Year+10+Dif;
  969.              If Abs(Dif)=5 then
  970.                Begin
  971.                 PopUpArray[1]:='The correct year cannot be determined';
  972.                 PopUpArray[2]:='with the information given.  Both the';
  973.                 PopUpArray[3]:='future and previous years ending in '+form('#',Greg.Year);
  974.                 PopUpArray[4]:='are exactly five years from the default';
  975.                 PopUpArray[5]:='year given.';
  976.                 PopUpArray[6]:=ToTryAgain;
  977.                 PopUpArray[7]:=ToChangeTo+form('####',OldGreg.Year+5)+' (future).';
  978.                 PopUpArray[8]:=ToChangeTo+form('####',OldGreg.Year-5)+' (previous).';
  979.                 PopUpArray[9]:=ToChangeTo+form('####',OldGreg.Year)+' (default).';
  980.                 PopUpKey[2]:='F';
  981.                 PopUpKey[3]:='P';
  982.                 PopUpKey[4]:='D';
  983.                 PopNote(5,4,PKey);
  984.                 Case PKey of
  985.                    #0:Begin
  986.                        Greg.Year:=OldGreg.Year;
  987.                        Section:=6;
  988.                        scan:=0;
  989.                       End;
  990.                    'F':Greg.Year:=OldGreg.Year+5;
  991.                    'P':Greg.Year:=OldGreg.Year-5;
  992.                    'D':Greg.Year:=OldGreg.Year;
  993.                 End; {case}
  994.                End;
  995.             End
  996.            Else
  997.             Begin
  998.              Dif:=Greg.Year-(OldGreg.Year mod 100);
  999.              If Dif=0 then Greg.Year:=OldGreg.Year;
  1000.              If Abs(Dif) in [1..49] then Greg.Year:=OldGreg.Year+Dif;
  1001.              If Dif in [51..99] then Greg.Year:=OldGreg.Year-100+Dif;
  1002.              If -Dif in [51..99] then Greg.Year:=OldGreg.Year+100+Dif;
  1003.              If Abs(Dif)=50 then
  1004.                Begin
  1005.                 QWrite(GivenYear,x+6,y,0,0);
  1006.                 PopUpArray[1]:='The correct year cannot be determined';
  1007.                 PopUpArray[2]:='with the information given.  Both the';
  1008.                 PopUpArray[3]:='future and previous years ending in '+form('##',Greg.Year);
  1009.                 PopUpArray[4]:='are exactly fifty years from the default';
  1010.                 PopUpArray[5]:='year given.';
  1011.                 PopUpArray[6]:=ToTryAgain;
  1012.                 PopUpArray[7]:=ToChangeTo+form('####',OldGreg.Year+50)+' (future).';
  1013.                 PopUpArray[8]:=ToChangeTo+form('####',OldGreg.Year-50)+' (previous).';
  1014.                 PopUpArray[9]:=ToChangeTo+form('####',OldGreg.Year)+' (default).';
  1015.                 PopUpKey[2]:='F';
  1016.                 PopUpKey[3]:='P';
  1017.                 PopUpKey[4]:='D';
  1018.                 PopNote(5,4,PKey);
  1019.                 Case PKey of
  1020.                    #0:Begin
  1021.                        Greg.Year:=OldGreg.Year;
  1022.                        Section:=6;
  1023.                        scan:=0;
  1024.                       End;
  1025.                    'F':Greg.Year:=OldGreg.Year+50;
  1026.                    'P':Greg.Year:=OldGreg.Year-50;
  1027.                    'D':Greg.Year:=OldGreg.Year;
  1028.                 End; {case}
  1029.                End;
  1030.             End
  1031.          End;
  1032.        WriteDate;
  1033.       End; {function CheckYear}
  1034.  
  1035.       Procedure NextSection;
  1036.       Begin
  1037.        if section in [6,7] then
  1038.          Begin
  1039.           If section=7 then checkyear(key1);
  1040.           Exit;
  1041.          End;
  1042.        scan:=0;
  1043.        if (section=1) and (key1<>'0') then Greg.Month:=ByteVal(key1);
  1044.        if (section=4) and (key1<>'0') then Greg.Day:=ByteVal(key1);
  1045.        WriteDate;
  1046.        if section in [0,1] then section:=3 else section:=6;
  1047.       End;
  1048.  
  1049.       Procedure PrevSection;
  1050.       Begin
  1051.        If section in [0,1] then
  1052.          Begin
  1053.           If section=1 then checkmonth(key1);
  1054.           Exit;
  1055.          End;
  1056.        scan:=0;
  1057.        if section=4 then Greg.Day:=ByteVal(key1);
  1058.        If section=7 then
  1059.          Begin
  1060.           checkyear(key1);
  1061.           If Section=6 then Exit;
  1062.          End;
  1063.        WriteDate;
  1064.        if section in [6,7] then section:=3 else section:=0;
  1065.       End;
  1066.  
  1067.    Begin  {procedure GetDate}
  1068.     SetNormalColorMode;
  1069.     Repeat
  1070.        GotoXY(x+section,y);
  1071.        ReadKey(off,DateScanExitSet+ScanExitSet,
  1072.                AsciiExitSet+DateAsciiExitSet,'&',scan,Ascii);
  1073.        If scan=EscKey then Greg:=OldGreg;
  1074.        If Ascii in AsciiOtherSet then
  1075.          Begin
  1076.           GetOther_StageTwo;
  1077.           If (Ascii in ['0'..'9']) or (Scan=StartOver) then
  1078.             Begin
  1079.              Ascii:=#0;
  1080.              Scan:=0;
  1081.              SetNormalColorMode;
  1082.             End;
  1083.          End
  1084.        Else
  1085.          Begin
  1086.           If (Ascii=' ') and (section in [0,3]) then Ascii:='0';
  1087.           If Ascii in ['0'..'9'] then
  1088.             Begin
  1089.              scan:=0;
  1090.              Case section of
  1091.                 0,3,6:Begin
  1092.                        key1:=Ascii;
  1093.                        section:=succ(section);
  1094.                        QWrite(Key1+' ',0,0,LFCC,2);
  1095.                       End;
  1096.                 1:Begin
  1097.                    Section:=3;
  1098.                    CheckMonth(key1+Ascii);
  1099.                   End;
  1100.                 4:Begin
  1101.                    Section:=6;
  1102.                    CheckDay(key1+Ascii);
  1103.                   End;
  1104.                 7:Begin
  1105.                    scan:=FullStringExit;
  1106.                    CheckYear(key1+Ascii);
  1107.                   End;
  1108.              End; {case}
  1109.             End {if}
  1110.           Else
  1111.             Begin
  1112.              Case scan of
  1113.                 arrowrtkey:NextSection;
  1114.                 arrowlfKey,
  1115.                 BkSpKey:Case section of
  1116.                            1,4,7:Begin
  1117.                                   Case section of
  1118.                                      1:Greg.Month:=OldGreg.Month;
  1119.                                      4:Greg.Day:=OldGreg.Day;
  1120.                                      7:Greg.Year:=OldGreg.Year;
  1121.                                   End; {case}
  1122.                                   scan:=0;
  1123.                                   Section:=Pred(Section);
  1124.                                   QWrite(' ',x+section,y,0,0);
  1125.                                  End;
  1126.                              3,6:PrevSection;
  1127.                         End; {case}
  1128.                 Else If scan in ScanExitSet then
  1129.                         Case section of
  1130.                            1:checkmonth(key1);
  1131.                            4:checkday(key1);
  1132.                            7:checkYear(key1);
  1133.                         End; {case}
  1134.              End; {case}
  1135.              If ((Ascii in NextSectionAsciiSet) and (section<6)) or
  1136.                 ((Ascii=' ') and (section in [1,4])) then
  1137.                Begin
  1138.                 Ascii:=#0;
  1139.                 NextSection;
  1140.                End;
  1141.              If (Ascii=' ') and (section=7) then
  1142.                Begin
  1143.                 Ascii:=#0;
  1144.                 scan:=FullStringExit;
  1145.                 NextSection;
  1146.                End;
  1147.             End; {else}
  1148.           If (scan in ScanExitSet) or (Ascii in AsciiExitSet) then CheckDate;
  1149.          End;
  1150.     Until (scan in ScanExitSet) or (Ascii in AsciiExitSet);
  1151.     WriteDate;
  1152.    End;
  1153.  
  1154.    Procedure GetOther;
  1155.    Begin
  1156.     Repeat
  1157.        QWriteAtt(1,x,y,LFCC,0);
  1158.        If Greg.Year=3 then QWriteAtt(8,succ(x),y,NFCC,0)
  1159.        Else QWriteAtt(7,succ(x),y,NFCC,0);
  1160.        GotoXY(x,y);
  1161.        ReadKey(off,ScanExitSet,AsciiExitSet+AsciiOtherSet,'&',scan,Ascii);
  1162.        If Ascii in AsciiOtherSet then GetOther_StageTwo;
  1163.     Until (Scan in ScanExitSet) or (Ascii in AsciiExitSet) or
  1164.           ((Ascii in ['0'..'9']) and Not NoDate);
  1165.     If Ascii in ['0'..'9'] then
  1166.       Begin
  1167.        RawDate(Greg);
  1168.        OldGreg:=Greg;
  1169.        WriteDate;
  1170.        QWrite(' ',x+8,y,7,0);
  1171.        GetDate;
  1172.       End;
  1173.    End;
  1174.  
  1175. Begin  {procedure ReadDate}
  1176.  JulToGreg(Jul,Greg);
  1177.  WriteDate;
  1178.  If option<>'W' then
  1179.    Begin
  1180.     SetHelp(HelpLine,HelpNum); cursor(on);
  1181.     OldGreg:=Greg;
  1182.     MTWTFSS:=Bitcheck(0,OtherMode);
  1183.     TFN:=BitCheck(1,OtherMode);
  1184.     NoDate:=Bitcheck(2,OtherMode);
  1185.     AsciiOtherSet:=[];
  1186.     If TFN then AsciiOtherSet:=['T'];
  1187.     If MTWTFSS then AsciiOtherSet:=['M','T','W','F','S'];
  1188.     DateAsciiExitSet:=AsciiOtherSet+NextSectionAsciiSet;
  1189.     If SetCposto1onEntry then Cpos:=1;
  1190.     Section:=Pred(Cpos);
  1191.     If Greg.Year>10 then GetDate Else GetOther;
  1192.     Cpos:=Succ(Section);
  1193.     GregToJul(Greg,Jul); cursor(off);
  1194.    End; {else}
  1195.  If Greg.Year=3 then QWriteAtt(9,x,y,DFCC,0)
  1196.  Else
  1197.    Begin
  1198.     QWriteAtt(8,x,y,DFCC,0);
  1199.     QWrite(' ',x+8,y,7,0);
  1200.    End;
  1201. End; {procedure ReadDate}
  1202.  
  1203. Procedure ReadTime(Option:char;
  1204.                    SetCposTo1onEntry,MilitaryTime:Boolean;
  1205.                    Omissions, { bit 0 = hours, bit 2 = seconds }
  1206.                    HelpLine,HelpNum,X,Y:Byte;
  1207.                    ScanExitSet:ByteSetType;
  1208.                    Var Scan:Byte;
  1209.                    AsciiExitSet:CharSetType;
  1210.                    Var Ascii:Char;
  1211.                    Var Cpos:Byte;
  1212.                    Var DayPart:Integer);
  1213. Const
  1214.  AsciiMeridiemSet:CharSetType=['A','P'];
  1215.  AsciiMoveRightSet:CharSetType=[':','.',',','-','/'];
  1216.  ScanMoveRightSet:ByteSetType=[ArrowRtKey,EndKey,FullStringExit];
  1217.  ScanMoveLeftSet:ByteSetType=[ArrowLfKey,HomeKey];
  1218. Var
  1219.  HourStr,MinuteStr,SecondStr:String[2];
  1220.  Clock:ClockType;
  1221.  Section,MeridiemPos:Byte;
  1222.  PM,Seconds,Hours:Boolean;
  1223.  
  1224.    Procedure WriteTime;
  1225.    Var TempString:String[10];
  1226.    Begin
  1227.     TempString:=TimeString(Clock,MilitaryTime);
  1228.     If Not Seconds then Delete(TempString,6,3);
  1229.     If hours then
  1230.       Begin
  1231.        If TempString[1]=' ' then TempString[1]:='0';
  1232.        HourStr:=TempString;
  1233.       End
  1234.     Else Delete(TempString,1,3);
  1235.     QWrite(TempString,x,y,0,0);
  1236.    End;
  1237.  
  1238.    Procedure GetTime;
  1239.    Var dummykey:char;
  1240.  
  1241.       Procedure AMPM;
  1242.  
  1243.          Procedure AdjustHour;
  1244.          Begin
  1245.           WriteTime;
  1246.           Ascii:=#0;
  1247.          End;
  1248.  
  1249.       Begin
  1250.        If (Ascii='P') and (Clock.Hour in [0..11]) then
  1251.          Begin
  1252.           Clock.Hour:=Clock.Hour+12;
  1253.           PM:=True;
  1254.           AdjustHour;
  1255.          End;
  1256.        If (Ascii='A') and (Clock.Hour in [12..23]) then
  1257.          Begin
  1258.           Clock.Hour:=Clock.Hour-12;
  1259.           PM:=False;
  1260.           AdjustHour;
  1261.          End;
  1262.       End;
  1263.  
  1264.       Procedure GetHour;
  1265.       Var OldHourStr:String[2];
  1266.       Begin
  1267.        OldHourStr:=HourStr;
  1268.        Repeat
  1269.           ReadString('R',On,Off,Off,Off,Off,0,0,x,y,ScanExitSet+ScanMoveRightSet,
  1270.                    Scan,AsciiExitSet+AsciiMeridiemSet+AsciiMoveRightSet,Ascii,
  1271.                    Cpos,HourStr,'&&');
  1272.           If (HourStr='') or (Scan=EscKey) then HourStr:=OldHourStr;
  1273.           Clock.Hour:=ByteVal(HourStr);
  1274.           If Clock.Hour>23 then
  1275.             Begin
  1276.              PopUpArray[1]:='There are only 24 hours in a day';
  1277.              If MilitaryTime then PopUpArray[2]:='(0 through 23).'
  1278.              Else PopUpArray[2]:='(12am through 11pm).';
  1279.              PopUpArray[3]:=ToContinue;
  1280.              PopNote(2,1,dummykey);
  1281.              HourStr:=OldHourStr;
  1282.              cpos:=1;
  1283.             End;
  1284.        Until Clock.Hour<24;
  1285.        If (not MilitaryTime) and PM and (Clock.Hour<12) then
  1286.           Clock.Hour:=Clock.Hour+12;
  1287.        If (Clock.Hour=12) and (not PM) and (not MilitaryTime) then
  1288.           clock.Hour:=0;
  1289.        If Clock.Hour in [12..23] then PM:=True Else PM:=False;
  1290.        WriteTime;
  1291.       End;
  1292.  
  1293.       Procedure GetMinute;
  1294.       Var
  1295.        TScanMoveRightSet,TScanMoveLeftSet:ByteSetType;
  1296.        OldMinuteStr:String[2];
  1297.        Xofs:Byte;
  1298.       Begin
  1299.        OldMinuteStr:=MinuteStr;
  1300.        If seconds then TScanMoveRightSet:=ScanMoveRightSet
  1301.        Else TScanMoveRightSet:=[];
  1302.        If hours then
  1303.          Begin
  1304.           TScanMoveLeftSet:=ScanMoveLeftSet;
  1305.           Xofs:=3;
  1306.          End
  1307.        Else
  1308.          Begin
  1309.           TScanMoveLeftSet:=[];
  1310.           Xofs:=0;
  1311.          End;
  1312.        Repeat
  1313.           ReadString('R',On,Off,Off,Off,Off,0,0,x+Xofs,y,
  1314.                      ScanExitSet+TScanMoveLeftSet+TScanMoveRightSet,Scan,
  1315.                      AsciiExitSet+AsciiMeridiemSet+AsciiMoveRightSet,Ascii,
  1316.                      Cpos,MinuteStr,'&&');
  1317.           If (MinuteStr='') or (Scan=EscKey) then MinuteStr:=OldMinuteStr;
  1318.           Clock.Minute:=ByteVal(MinuteStr);
  1319.           If Clock.Minute>59 then
  1320.             Begin
  1321.              PopUpArray[1]:='There are only 60 minutes';
  1322.              PopUpArray[2]:='in an hour (0 through 59).';
  1323.              PopUpArray[3]:=ToContinue;
  1324.              PopNote(2,1,dummykey);
  1325.              MinuteStr:=OldMinuteStr;
  1326.              cpos:=1;
  1327.             End;
  1328.        Until Clock.Minute<60;
  1329.        MinuteStr:=form('@@',Clock.Minute);
  1330.        WriteTime;
  1331.       End;
  1332.  
  1333.       Procedure GetSecond;
  1334.       Var
  1335.        OldSecondStr:String[2];
  1336.        Xofs:Byte;
  1337.       Begin
  1338.        OldSecondStr:=SecondStr;
  1339.        If hours then Xofs:=6 Else Xofs:=3;
  1340.        Repeat
  1341.           ReadString('R',On,Off,Off,Off,Off,0,0,x+Xofs,y,ScanExitSet+ScanMoveLeftSet,
  1342.                      Scan,AsciiExitSet+AsciiMeridiemSet,Ascii,Cpos,SecondStr,'&&');
  1343.           If (SecondStr='') or (Scan=EscKey) then SecondStr:=OldSecondStr;
  1344.           Clock.Second:=ByteVal(SecondStr);
  1345.           If Clock.Second>59 then
  1346.             Begin
  1347.              PopUpArray[1]:='There are only 60 seconds';
  1348.              PopUpArray[2]:='in a minute (0 through 59).';
  1349.              PopUpArray[3]:=ToContinue;
  1350.              PopNote(2,1,dummykey);
  1351.              SecondStr:=OldSecondStr;
  1352.              cpos:=1;
  1353.             End;
  1354.        Until Clock.Second<60;
  1355.        If (clock.Second mod 5)<>0 then
  1356.          Begin
  1357.           Clock.Second:=((Clock.Second+2) div 5)*5;
  1358.           If Clock.Second=60 then Clock.Second:=55;
  1359.           Beep;
  1360.          End;
  1361.        SecondStr:=form('@@',Clock.Second);
  1362.        WriteTime;
  1363.       End;
  1364.  
  1365.    Begin
  1366.     SetHelp(HelpLine,HelpNum);
  1367.     QWriteAtt(5,x,y,LFCC,0);
  1368.     QWriteAtt(1,x+2,y,NFCC,0);
  1369.     If seconds and hours then
  1370.       Begin
  1371.        QWriteAtt(1,x+5,y,NFCC,0);
  1372.        QWriteAtt(2,x+6,y,LFCC,0);
  1373.       End;
  1374.     If Not MilitaryTime then
  1375.       Begin
  1376.        QWriteAtt(2,x+MeridiemPos,y,NFCC,0);
  1377.        If Clock.Hour>11 then PM:=True Else PM:=False;
  1378.       End;
  1379.     MinuteStr:=form('@@',Clock.Minute);
  1380.     SecondStr:=form('@@',Clock.Second);
  1381.     If SetCposTo1onEntry then
  1382.       Begin
  1383.        Cpos:=1;
  1384.        If Hours then Section:=1 Else Section:=2;
  1385.       End
  1386.     Else
  1387.       Begin
  1388.        section:=succ(Cpos) div 2;
  1389.        If not hours then BInc(section);
  1390.        If odd(Cpos) then Cpos:=1 Else Cpos:=2;
  1391.       End;
  1392.     Repeat
  1393.        Case section of
  1394.           1:GetHour;
  1395.           2:GetMinute;
  1396.           3:GetSecond;
  1397.        End; {case}
  1398.        If Ascii in (AsciiMeridiemSet) then AMPM;
  1399.        If ((Ascii in AsciiMoveRightSet) or (Scan in ScanMoveRightSet)) and
  1400.           ((Seconds and (section=2)) or (section=1)) then
  1401.          Begin
  1402.           Section:=succ(section);
  1403.           Ascii:=#0;
  1404.           Scan:=0;
  1405.           Cpos:=1;
  1406.          End;
  1407.        If (Scan in ScanMoveLeftSet) and
  1408.           (((section=2) and hours) or (section=3)) then
  1409.          Begin
  1410.           Section:=pred(section);
  1411.           Scan:=0;
  1412.           Cpos:=1;
  1413.          End;
  1414.     Until (Scan in ScanExitSet) or (Ascii in AsciiExitSet);
  1415.     Cpos:=(pred(section)*2)+Cpos;
  1416.     If not hours then
  1417.       Begin
  1418.        Cpos:=Cpos-2;
  1419.        Clock.Hour:=0;
  1420.       End;
  1421.     If not seconds then Clock.second:=0;
  1422.     ClockToDayPart(Clock,DayPart);
  1423.    End;
  1424.  
  1425. Begin
  1426.  DayPartToClock(DayPart,Clock);
  1427.  Hours:=not BitCheck(0,Omissions); Seconds:=not BitCheck(2,Omissions);
  1428.  If not hours then
  1429.    Begin
  1430.     MilitaryTime:=True;
  1431.     Seconds:=True;
  1432.    End;
  1433.  If seconds and hours then MeridiemPos:=8 Else MeridiemPos:=5;
  1434.  WriteTime;
  1435.  If option<>'W' then GetTime;
  1436.  QWriteAtt(MeridiemPos,x,y,DFCC,0);
  1437.  If Not MilitaryTime then QWriteAtt(2,x+MeridiemPos,y,DFCC,0);
  1438. End;
  1439.  
  1440.