home *** CD-ROM | disk | FTP | other *** search
/ World of Shareware - Software Farm 2 / wosw_2.zip / wosw_2 / PASCAL / PSSTR102.ZIP / STRINGS.PAS < prev   
Pascal/Delphi Source File  |  1993-01-01  |  18KB  |  831 lines

  1. {
  2.  
  3.                                                       ╔══════════════════╗
  4.                                                       ║ String, Variable ║
  5.                                                       ║   and Keyboard   ║
  6.                                                       ║    Utilities     ║
  7.                                                       ║    Rev. 1.02     ║
  8.                                                       ╚══════════════════╝
  9.  
  10. }
  11.  
  12. {$F-} {$O-} {$A+} {$G-}
  13. {$V-} {$B-} {$X-} {$N+} {$E+}
  14.  
  15. {$I FINAL.PAS}
  16.  
  17. {$IFDEF FINAL}
  18.   {$I-} {$R-}
  19.   {$D-} {$L-} {$S-}
  20. {$ENDIF}
  21.  
  22. Unit Strings;
  23.  
  24. Interface
  25.  
  26. Uses CRT,DOS;
  27.  
  28. Const
  29.   MaxXYSaves        =    5;                  {Max Number of Cursor Saves}
  30.   LeftText          =    0;
  31.   CentreText        =    1;
  32.   RightText         =    2;
  33.   OutSideText       =    3;
  34.  
  35. Type
  36.   TextFormats       = LeftText..RightText;
  37.   JustifyFormats    = LeftText..OutSideText;
  38.   XYType            = (CursorX,CursorY);
  39.   XYPosData         = Array[1..MaxXYSaves] of
  40.                         Array [XYType] of Byte;
  41.   KeyBufferFunction = (Clear,Save,Restore);
  42.  
  43.  
  44. Procedure SpacesToZeros (StIn:String;Var StOut:String);
  45. Function  PosFrom       (SubS:String;StIn:String;FarIn:Byte):Byte;
  46. Function  RevPosFrom    (SubS:String;StIn:String;FarIn:Byte):Byte;
  47. Procedure UpperCase     (StIn:String;Var StOut:String);
  48. Procedure PadVar        (StIn:String;Var StOut:String;Count:Byte);
  49. Procedure PadVarWith    (StIn:String;Var StOut:String;Count:Byte;
  50.                                                       WithMe:Char);
  51. Procedure FormatVar     (StIn:String;Var StOut:String;
  52.                          Size:Byte;Format:TextFormats);
  53. Procedure UnPadVar      (StIn:String;Var StOut:String);
  54. Procedure UnPadVarRight (StIn:String;Var StOut:String);
  55. Procedure UnPadVarLeft  (StIn:String;Var StOut:String);
  56. Procedure RightJustify  (StIn:String;Var StOut:String;
  57.                          Margin:Byte;JType:JustifyFormats);
  58. Procedure PadFileName   (StIn:String;Var StOut:String);
  59.  
  60. Function  AdjustMeter   (StartMeter1,EndMeter1,ValueMeter1,
  61.                          StartMeter2,EndMeter2:LongInt):LongInt;
  62.  
  63. Function  MemoryCount   (P:Pointer):LongInt;
  64. Procedure GetLowestOfs  (P:Pointer;Var S,O:Word);
  65. Procedure AdjustPtr     (Var P:Pointer;Amount:LongInt);
  66.  
  67. Procedure SaveCursorSize(Var Data:Word);
  68. Procedure RestCursorSize(Data:Word);
  69. Procedure SaveXYPos     (Var Position:XYPosData);
  70. Procedure RestXYPos     (Var Position:XYPosData);
  71. Procedure CursorSize    (UpLim,DownLim:Byte);
  72.  
  73. Procedure PushCursorSize;
  74. Procedure PopCursorSize;
  75. Procedure PushXYPos;
  76. Procedure PopXYPos;
  77. Procedure PushTextColor;
  78. Procedure PopTextColor;
  79.  
  80. Procedure KeyBuffer     (Option:KeyBufferFunction);
  81.  
  82. Procedure SwapBytes     (Var A,B:Byte);
  83. Procedure SwapIntegers  (Var A,B:Integer);
  84. Procedure SwapWords     (Var A,B:Word);
  85. Procedure SwapLongInts  (Var A,B:LongInt);
  86. Procedure SwapReals     (Var A,B:Real);
  87. Procedure SwapSingles   (Var A,B:Single);
  88. Procedure SwapDoubles   (Var A,B:Double);
  89. Procedure SwapExtendeds (Var A,B:Extended);
  90. Procedure SwapStrings   (Var A,B:String);
  91.  
  92. Implementation
  93.  
  94. Var
  95.   PushPopCursorSize:Array[1..MaxXYSaves] of Word;
  96.   PushPopTextColor :Array[1..MaxXYSaves] of Word;
  97.   PushPopCursorPos :XYPosData;
  98.  
  99. Procedure SpacesToZeros(StIn:String;Var StOut:String); Assembler;
  100.  
  101. Asm
  102.   push  ds
  103.   cld
  104.   lds   si,StIn
  105.   les   di,StOut
  106.   lodsb
  107.   stosb
  108.   xor   ah,ah
  109.   xchg  ax,cx
  110.   jcxz  @Section3
  111.  
  112. @Section1:
  113.  
  114.   lodsb
  115.   cmp   al,' '
  116.   jne   @Section2
  117.   mov   al,'0'
  118.  
  119. @Section2:
  120.  
  121.   stosb
  122.   loop  @Section1
  123.  
  124. @Section3:
  125.  
  126.   pop   ds
  127.  
  128. End;
  129.  
  130. Function PosFrom(SubS:String;StIn:String;FarIn:Byte):Byte;
  131.  
  132. Var
  133.   NewPos:Byte;
  134.  
  135. Begin
  136.   Delete(StIn,1,FarIn-1);
  137.   NewPos:=Pos(SubS,StIn);
  138.   If NewPos=0 Then
  139.     PosFrom:=0
  140.   Else
  141.     PosFrom:=NewPos+FarIn-1;
  142. End;
  143.  
  144. Function RevPosFrom(SubS:String;StIn:String;FarIn:Byte):Byte;
  145.  
  146. Var
  147.   Mark  :Byte;
  148.   Temp  :Byte;
  149.   Chk   :String;
  150.  
  151. Begin
  152.   If Length(SubS)>Length(StIn) Then
  153.   Begin
  154.     RevPosFrom:=0;
  155.     Exit;
  156.   End;
  157.  
  158.   Mark:=Length(StIn)-Length(SubS)+1;
  159.   If Mark>FarIn Then Mark:=FarIn;
  160.   Temp:=0;
  161.  
  162.   While (Mark>=1) And (Temp=0) do
  163.   Begin
  164.     Chk:=Copy(StIn,Mark,Length(SubS));
  165.     If Chk=SubS Then
  166.       Temp:=Mark
  167.     Else
  168.       Dec(Mark);
  169.   End;
  170.   RevPosFrom:=Temp;
  171. End;
  172.  
  173. Procedure UpperCase(StIn:String;Var StOut:String); Assembler;
  174.  
  175. Asm
  176.   push  ds
  177.   cld
  178.   lds   si,StIn
  179.   les   di,StOut
  180.   lodsb
  181.   stosb
  182.   xor   ah,ah
  183.   xchg  ax,cx
  184.   jcxz  @Section3
  185.  
  186. @Section1:
  187.  
  188.   lodsb
  189.   cmp   al,'a'
  190.   jb    @Section2
  191.   cmp   al,'z'
  192.   ja    @Section2
  193.   sub   al,20h
  194.  
  195. @Section2:
  196.  
  197.   stosb
  198.   loop  @Section1
  199.  
  200. @Section3:
  201.  
  202.   pop   ds
  203.  
  204. End;
  205.  
  206. Procedure PadVar(StIn:String;Var StOut:String;Count:Byte);
  207.  
  208. Var
  209.    J:Byte;
  210.  
  211. Begin
  212.   StOut:=StIn;
  213.   For J:=1 to Count do
  214.     StOut:=StOut+' ';
  215. End;
  216.  
  217. Procedure PadVarWith(StIn:String;Var StOut:String;Count:Byte;WithMe:Char);
  218.  
  219. Var
  220.    J:Byte;
  221.  
  222. Begin
  223.   StOut:=StIn;
  224.   For J:=1 to Count do
  225.     StOut:=StOut+WithMe;
  226. End;
  227.  
  228. Procedure FormatVar(StIn:String;Var StOut:String;
  229.                     Size:Byte;Format:TextFormats);
  230. Begin
  231.   StOut:=StIn;
  232.  
  233.   If Format=LeftText Then
  234.     While Length(StOut)<Size do
  235.       StOut:=StOut+' '
  236.   Else
  237.     If Format=CentreText Then
  238.     Begin
  239.       While Length(StOut)<Size-1 do
  240.         StOut:=' '+StOut+' ';
  241.       Format:=RightText;
  242.     End;
  243.  
  244.   If Format=RightText Then
  245.     While Length(StOut)<Size do
  246.       StOut:=' '+StOut;
  247. End;
  248.  
  249. Procedure UnPadVar(StIn:String;Var StOut:String);
  250. Begin
  251.   StOut:=StIn;
  252.   While (Length(StOut)>0) And (StOut[1]=' ') do
  253.     Delete(StOut,1,1);
  254.   While (Length(StOut)>0) And (StOut[Length(StOut)]=' ') do
  255.     Delete(StOut,Length(StOut),1);
  256. End;
  257.  
  258. Procedure UnPadVarRight(StIn:String;Var StOut:String);
  259. Begin
  260.   StOut:=StIn;
  261.   While (Length(StOut)>0) And (StOut[Length(StOut)]=' ') do
  262.     Delete(StOut,Length(StOut),1);
  263. End;
  264.  
  265. Procedure UnPadVarLeft(StIn:String;Var StOut:String);
  266. Begin
  267.   StOut:=StIn;
  268.   While (Length(StOut)>0) And (StOut[1]=' ') do
  269.     Delete(StOut,1,1);
  270. End;
  271.  
  272. Procedure RightJustify(StIn:String;Var StOut:String;
  273.                        Margin:Byte;JType:JustifyFormats);
  274.  
  275.   Procedure RightJustifyLeft;
  276.  
  277.   Var
  278.     EndLoop  :Boolean;
  279.     Marker,
  280.     SpPos    :Byte;
  281.  
  282.   Begin
  283.     EndLoop:=False;
  284.     While (Length(StOut)<Margin) And (Not EndLoop) do
  285.     Begin
  286.       Marker:=1;
  287.       Repeat
  288.         SpPos:=PosFrom(' ',StOut,Marker);
  289.         If (SpPos=0) Or (SpPos=Length(StOut)) Then
  290.         Begin
  291.           If Marker=1 Then EndLoop:=True;
  292.           Marker:=255
  293.         End
  294.         Else
  295.         Begin
  296.           Insert(' ',StOut,SpPos);
  297.           Marker:=SpPos+2;
  298.           While (StOut[Marker]=' ') And (Marker<Margin) do
  299.             Inc(Marker);
  300.         End;
  301.       Until (Length(StOut)>=Margin) Or (Marker>Length(StOut)) Or EndLoop;
  302.     End;
  303.   End;
  304.  
  305.   Procedure RightJustifyRight;
  306.  
  307.   Var
  308.     EndLoop  :Boolean;
  309.     Marker,
  310.     SpPos    :Byte;
  311.  
  312.   Begin
  313.     EndLoop:=False;
  314.     While (Length(StOut)<Margin) And (Not EndLoop) do
  315.     Begin
  316.       Marker:=Length(StOut);
  317.       Repeat
  318.         SpPos:=RevPosFrom(' ',StOut,Marker);
  319.         If (SpPos=0) Or (SpPos=1) Then
  320.         Begin
  321.           If Marker=Length(StOut) Then EndLoop:=True;
  322.           Marker:=0;
  323.         End
  324.         Else
  325.         Begin
  326.           Insert(' ',StOut,SpPos);
  327.           Marker:=SpPos-1;
  328.           While (StOut[Marker]=' ') And (Marker>1) do
  329.             Dec(Marker);
  330.         End;
  331.       Until (Length(StOut)>=Margin) Or (Marker=0) Or EndLoop;
  332.     End;
  333.   End;
  334.  
  335.   Procedure RightJustifyCentre;
  336.  
  337.   Var
  338.     EndLoop1,
  339.     EndLoop2 :Boolean;
  340.     Marker1,
  341.     Marker2,
  342.     SpPos    :Byte;
  343.  
  344.   Begin
  345.     EndLoop1:=False;
  346.     EndLoop2:=False;
  347.  
  348.     While (Length(StOut)<Margin) And (Not EndLoop1) And (Not EndLoop2) do
  349.     Begin
  350.       Marker1:=Length(StOut) Div 2;
  351.       Marker2:=Marker1;
  352.       If StOut[Marker1]=' ' Then Inc(Marker1);
  353.  
  354.       Repeat
  355.         If Not ((Length(StOut)>=Margin) Or (Marker1>Length(StOut)) Or EndLoop1) Then
  356.         Begin
  357.           SpPos:=PosFrom(' ',StOut,Marker1);
  358.           If (SpPos=0) Or (SpPos=Length(StOut)) Then
  359.           Begin
  360.             If Marker1=Length(StOut) Div 2 Then EndLoop1:=True;
  361.             Marker1:=255
  362.           End
  363.           Else
  364.           Begin
  365.             Insert(' ',StOut,SpPos);
  366.             Marker1:=SpPos+2;
  367.             While (StOut[Marker1]=' ') And (Marker1<Margin) do
  368.               Inc(Marker1);
  369.           End;
  370.         End;
  371.  
  372.         If Not ((Length(StOut)>=Margin) Or (Marker2=0) Or EndLoop2) Then
  373.         Begin
  374.           SpPos:=RevPosFrom(' ',StOut,Marker2);
  375.           If (SpPos<=1) Then
  376.           Begin
  377.             If Marker2=Length(StOut) Div 2 Then EndLoop2:=True;
  378.             Marker2:=0;
  379.           End
  380.           Else
  381.           Begin
  382.             Insert(' ',StOut,SpPos);
  383.             If Marker1 <> 255 Then
  384.               Inc(Marker1);               {Pushes Marker 1 Up 1 Space}
  385.             Marker2:=SpPos-1;
  386.             While (StOut[Marker2]=' ') And (Marker2>1) do
  387.               Dec(Marker2);
  388.           End;
  389.         End;
  390.       Until ((Length(StOut)>=Margin) Or (Marker1>Length(StOut)) Or EndLoop1) And
  391.             ((Length(StOut)>=Margin) Or (Marker2=0) Or EndLoop2);
  392.     End;
  393.   End;
  394.  
  395.   Procedure RightJustifyOutSide;
  396.  
  397.   Var
  398.     EndLoop1,
  399.     EndLoop2 :Boolean;
  400.     Marker1,
  401.     Marker2,
  402.     SpPos    :Byte;
  403.  
  404.   Begin
  405.     EndLoop1:=False;
  406.     EndLoop2:=False;
  407.  
  408.     While (Length(StOut)<Margin) And (Not EndLoop1) And (Not EndLoop2) do
  409.     Begin
  410.       Marker1:=1;
  411.       Marker2:=Length(StOut);
  412.  
  413.       Repeat
  414.         If Not ((Length(StOut)>=Margin) Or (Marker1>Length(StOut) Div 2) Or EndLoop1) Then
  415.         Begin
  416.           SpPos:=PosFrom(' ',StOut,Marker1);
  417.           If (SpPos=0) Or (SpPos>Length(StOut) Div 2) Then
  418.           Begin
  419.             If Marker1=1 Then EndLoop1:=True;
  420.             Marker1:=255
  421.           End
  422.           Else
  423.           Begin
  424.             Insert(' ',StOut,SpPos);
  425.             Marker1:=SpPos+2;
  426.             While (StOut[Marker1]=' ') And (Marker1<Length(StOut) Div 2) do
  427.               Inc(Marker1);
  428.           End;
  429.         End;
  430.  
  431.         If Not ((Length(StOut)>=Margin) Or (Marker2<Length(StOut) Div 2) Or EndLoop2) Then
  432.         Begin
  433.           SpPos:=RevPosFrom(' ',StOut,Marker2);
  434.           If (SpPos<=1) Then
  435.           Begin
  436.             If Marker2<=Length(StOut) Div 2 Then EndLoop2:=True;
  437.             Marker2:=0;
  438.           End
  439.           Else
  440.           Begin
  441.             Insert(' ',StOut,SpPos);
  442.             If Marker1 <> 255 Then
  443.               Inc(Marker1);               {Pushes Marker 1 Up 1 Space}
  444.             Marker2:=SpPos-1;
  445.             While (StOut[Marker2]=' ') And (Marker2>=Length(StOut) Div 2) do
  446.               Dec(Marker2);
  447.           End;
  448.         End;
  449.       Until ((Length(StOut)>=Margin) Or (Marker1>Length(StOut) Div 2) Or EndLoop1) And
  450.             ((Length(StOut)>=Margin) Or (Marker2<=Length(StOut) Div 2) Or EndLoop2);
  451.     End;
  452.   End;
  453.  
  454. Begin
  455.   StOut:=StIn;
  456.   Case JType Of
  457.     LeftText    :RightJustifyLeft;
  458.     RightText   :RightJustifyRight;
  459.     CentreText  :RightJustifyCentre;
  460.     OutSideText :RightJustifyOutSide;
  461.   End;
  462. End;
  463.  
  464. Procedure PadFileName(StIn:String;Var StOut:String);
  465.  
  466. { ╔════════════════════════════════════════════════════════════════════════╗ }
  467. { ║  Pads the file name to 12 characters.                                  ║ }
  468. { ╚════════════════════════════════════════════════════════════════════════╝ }
  469.  
  470. Var
  471.   T1 :DirStr;
  472.   T2 :NameStr;
  473.   T3 :ExtStr;
  474.   Dot:Char;
  475.  
  476. Begin
  477.   If StIn='.' Then
  478.   Begin
  479.     PadVar(StIn,StOut,11);
  480.     Exit;
  481.   End;
  482.  
  483.   If StIn='..' Then
  484.   Begin
  485.     PadVar(StIn,StOut,10);
  486.     Exit;
  487.   End;
  488.  
  489.   FSplit(StIn,T1,T2,T3);
  490.   PadVar(T2,T2,8-Length(T2));
  491.   Delete(T3,1,1);
  492.   PadVar(T3,T3,3-Length(T3));
  493.   If T3='   ' Then Dot:=' ' Else Dot:='.';
  494.   StOut:=T1+T2+Dot+T3;
  495. End;
  496.  
  497. Function AdjustMeter(StartMeter1,EndMeter1,ValueMeter1,
  498.                      StartMeter2,EndMeter2:LongInt):LongInt;
  499. Begin
  500.   AdjustMeter:=(((EndMeter2-StartMeter2)*(ValueMeter1-StartMeter1)) Div
  501.                (EndMeter1-StartMeter1))+StartMeter2;
  502. End;
  503.  
  504. Function MemoryCount(P:Pointer):LongInt;
  505. Begin
  506.   MemoryCount:=LongInt(Seg(P^)) * 16 + Ofs(P^);
  507. End;
  508.  
  509. Procedure GetLowestOfs(P:Pointer;Var S,O:Word);
  510. Begin
  511.   O:=Ofs(P^);
  512.   S:=Seg(P^);
  513.   If O<16 Then Exit;
  514.   Inc(S,O Div 16);
  515.   O:=O Mod 16;
  516. End;
  517.  
  518. Procedure AdjustPtr(Var P:Pointer;Amount:LongInt);
  519.  
  520. Var
  521.   X,
  522.   Segt,
  523.   Ofst  :Word;
  524.  
  525. Begin
  526.   Segt:=Seg(P^);
  527.   Ofst:=Ofs(P^);
  528.   If Amount<0 Then
  529.   Begin
  530.     X:=$FFFF-Ofst;      {Want to Make Ofst as Big as Possible}
  531.     X:=X - (X Mod 16);  {Round It to the Nearest 16}
  532.     Dec(Segt,X Div 16); {Take it from the Segment}
  533.     Inc(Ofst,X);        {Add it to the Offset}
  534.   End
  535.   Else
  536.   Begin
  537.     X:=Ofst - (Ofst Mod 16);    {Want to make Ofst as Small as Possible}
  538.     Inc(Segt,X Div 16);         {Add it to the Segment}
  539.     Dec(Ofst,X);                {Take it from the Offset}
  540.   End;
  541.   P:=Ptr(Segt,Ofst+Amount);
  542. End;
  543.  
  544. Procedure SaveCursorSize(Var Data:Word); Assembler;
  545. Asm
  546.   mov  ah,3
  547.   int  10h
  548.   les  di,Data
  549.   mov  es:[di],cx
  550. End;
  551.  
  552. Procedure RestCursorSize(Data:Word); Assembler;
  553. Asm
  554.   mov  ah,1
  555.   mov  cx,Data
  556.   int  10h
  557. End;
  558.  
  559. Procedure SaveXYPos(Var Position:XYPosData);
  560. {This saves the current cursor position and can store up to the last five}
  561. {cursor positions}
  562. {Number 'MaxXYSaves' is the lastest save}
  563.  
  564. Var
  565.   X:Byte;   {Loop}
  566.  
  567. Begin
  568.   For X:=1 to MaxXYSaves-1 do                    {Shift Cursor Saves up}
  569.   Begin
  570.       Position[X,CursorX]:=Position[X+1,CursorX];
  571.       Position[X,CursorY]:=Position[X+1,CursorY];
  572.   End;   {For X Loop}
  573.   Position[5,CursorX]:=WhereX;      {Insert New Cursor Save Position}
  574.   Position[5,CursorY]:=WhereY;
  575. End;  {SaveXYPos}
  576.  
  577. Procedure RestXYPos(Var Position:XYPosData);
  578. {This will restore up to five previously saved cursor positions}
  579. {Number 'MaxXYSaves' is the position to be restored}
  580.  
  581. Var
  582.   X:Byte;       {Loop}
  583.  
  584. Begin
  585.   GotoXY(Position[MaxXYSaves,CursorX],Position[MaxXYSaves,CursorY]); {Goto Old Position}
  586.   For X:=MaxXYSaves downto 2 do    {Shift up the cursor positions for the next restore}
  587.   Begin
  588.       Position[X,CursorX]:=Position[X-1,CursorX];
  589.       Position[X,CursorY]:=Position[X-1,CursorY];
  590.   End;  {For X Loop}
  591. End;  {RestXYPos}
  592.  
  593. Procedure CursorSize(UpLim,DownLim:Byte); Assembler;
  594. {Set the cursor size.  Send $20,$20 for no cursor}
  595. Asm
  596.   mov  ah,1
  597.   mov  ch,UpLim
  598.   mov  cl,DownLim
  599.   int  10h
  600. End;
  601.  
  602. Procedure PushCursorSize;
  603.  
  604. Var
  605.   X:Word;
  606.  
  607. Begin
  608.   For X:=1 to MaxXYSaves-1 do
  609.     PushPopCursorSize[X]:=PushPopCursorSize[X+1];
  610.  
  611.   Asm
  612.     mov  ah,3
  613.     int  10h
  614.     mov  X,cx
  615.   End;
  616.  
  617.   PushPopCursorSize[MaxXYSaves]:=X;
  618. End;
  619.  
  620. Procedure PopCursorSize;
  621.  
  622. Var
  623.   X:Word;
  624.  
  625. Begin
  626.   X:=PushPopCursorSize[MaxXYSaves];
  627.  
  628.   Asm
  629.     mov  ah,1
  630.     mov  cx,X
  631.     int  10h
  632.   End;
  633.  
  634.   For X:=MaxXYSaves DownTo 2 do
  635.     PushPopCursorSize[X]:=PushPopCursorSize[X-1];
  636. End;
  637.  
  638. Procedure PushXYPos;
  639.  
  640. Var
  641.   X:Byte;
  642.  
  643. Begin
  644.   For X:=1 to MaxXYSaves-1 do
  645.     PushPopCursorPos[X]:=PushPopCursorPos[X+1];
  646.  
  647.   PushPopCursorPos[MaxXYSaves,CursorX]:=WhereX;
  648.   PushPopCursorPos[MaxXYSaves,CursorY]:=WhereY;
  649. End;
  650.  
  651. Procedure PopXYPos;
  652.  
  653. Var
  654.   X:Byte;
  655.  
  656. Begin
  657.   GotoXY(PushPopCursorPos[MaxXYSaves,CursorX],
  658.          PushPopCursorPos[MaxXYSaves,CursorY]);
  659.  
  660.   For X:=MaxXYSaves DownTo 2 do
  661.     PushPopCursorPos[X]:=PushPopCursorPos[X-1];
  662. End;
  663.  
  664. Procedure PushTextColor;
  665.  
  666. Var
  667.   X:Byte;
  668.  
  669. Begin
  670.   For X:=1 to MaxXYSaves-1 do
  671.     PushPopTextColor[X]:=PushPopTextColor[X+1];
  672.  
  673.   PushPopTextColor[MaxXYSaves]:=TextAttr;
  674. End;
  675.  
  676. Procedure PopTextColor;
  677.  
  678. Var
  679.   X:Word;
  680.  
  681. Begin
  682.   TextAttr:=PushPopTextColor[MaxXYSaves];
  683.  
  684.   For X:=MaxXYSaves DownTo 2 do
  685.     PushPopTextColor[X]:=PushPopTextColor[X-1];
  686. End;
  687.  
  688. Procedure KeyBuffer(Option:KeyBufferFunction);
  689.  
  690. Type
  691.   KeyBufType=Record
  692.                Head:Word;
  693.                Tail:Word;
  694.                Data:Array[1..16] Of Word;
  695.              End;
  696.  
  697. Const
  698.   KeyBuf:KeyBufType=(Head:0;Tail:0;Data:(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0));
  699.   P     :Pointer   =Ptr(0,$41A);
  700.  
  701. Begin
  702.   Case Option Of
  703.     Clear   :MemW[0:$41A]:=MemW[0:$41C];
  704.     Save    :Move(P^,KeyBuf,SizeOf(KeyBuf));
  705.     Restore :Move(KeyBuf,P^,SizeOf(KeyBuf));
  706.   End;
  707. End;
  708.  
  709. Procedure SwapBytes(Var A,B:Byte); Assembler;
  710. Asm
  711.   push  ds
  712.   les   di,A
  713.   lds   si,B
  714.   mov   al,es:[di]
  715.   mov   bl,al             {A into BX}
  716.   mov   al,ds:[si]        {B into AX}
  717.   mov   es:[di],al
  718.   mov   al,bl
  719.   mov   ds:[si],al
  720.   pop   ds
  721. End;
  722.  
  723. Procedure SwapIntegers(Var A,B:Integer); Assembler;
  724. Asm
  725.   push  ds
  726.   les   di,A
  727.   lds   si,B
  728.   mov   ax,es:[di]
  729.   mov   bx,ax             {A into BX}
  730.   mov   ax,ds:[si]        {B into AX}
  731.   mov   es:[di],ax
  732.   mov   ax,bx
  733.   mov   ds:[si],ax
  734.   pop   ds
  735. End;
  736.  
  737. Procedure SwapWords(Var A,B:Word); Assembler;
  738. Asm
  739.   push  ds
  740.   les   di,A
  741.   lds   si,B
  742.   mov   ax,es:[di]
  743.   mov   bx,ax             {A into BX}
  744.   mov   ax,ds:[si]        {B into AX}
  745.   mov   es:[di],ax
  746.   mov   ax,bx
  747.   mov   ds:[si],ax
  748.   pop   ds
  749. End;
  750.  
  751. Procedure SwapLongInts(Var A,B:LongInt);
  752.  
  753. Var
  754.   C:LongInt;
  755.  
  756. Begin
  757.   C:=A;
  758.   A:=B;
  759.   B:=C;
  760. End;
  761.  
  762. Procedure SwapReals(Var A,B:Real);
  763.  
  764. Var
  765.   C:Real;
  766.  
  767. Begin
  768.   C:=A;
  769.   A:=B;
  770.   B:=C;
  771. End;
  772.  
  773. Procedure SwapSingles(Var A,B:Single);
  774.  
  775. Var
  776.   C:Single;
  777.  
  778. Begin
  779.   C:=A;
  780.   A:=B;
  781.   B:=C;
  782. End;
  783.  
  784. Procedure SwapDoubles(Var A,B:Double);
  785.  
  786. Var
  787.   C:Double;
  788.  
  789. Begin
  790.   C:=A;
  791.   A:=B;
  792.   B:=C;
  793. End;
  794.  
  795. Procedure SwapExtendeds(Var A,B:Extended);
  796.  
  797. Var
  798.   C:Extended;
  799.  
  800. Begin
  801.   C:=A;
  802.   A:=B;
  803.   B:=C;
  804. End;
  805.  
  806. Procedure SwapComps(Var A,B:Comp);
  807.  
  808. Var
  809.   C:Comp;
  810.  
  811. Begin
  812.   C:=A;
  813.   A:=B;
  814.   B:=C;
  815. End;
  816.  
  817. Procedure SwapStrings(Var A,B:String);
  818.  
  819. Var
  820.   C:String;
  821.  
  822. Begin
  823.   C:=A;
  824.   A:=B;
  825.   B:=C;
  826. End;
  827.  
  828. End.
  829.  
  830. { Copyright 1993, Michael Gallias }
  831.