Browse Source

+ basis for common platform independent implementation of Crt

Tomas Hajny 20 years ago
parent
commit
cdccf904cd
1 changed files with 417 additions and 0 deletions
  1. 417 0
      rtl/inc/crt.inc

+ 417 - 0
rtl/inc/crt.inc

@@ -0,0 +1,417 @@
+{
+    $Id$
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 1998 - 2005 by the Free Pascal development team.
+
+    This file implements platform independent routines for Crt.
+    It should be modified later to use routines from Keyboard and
+    Video instead of code in platform-specific crt.pas.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+procedure GotoXY (X: byte; Y: byte);
+begin
+ GotoXY32 (X, Y);
+end;
+
+procedure Window (X1, Y1, X2, Y2: byte);
+begin
+ Window32 (X1, Y1, X2, Y2);
+end;
+
+function WhereX: byte;
+var
+ X1: dword;
+begin
+ X1 := WhereX32;
+ if X1 > 255 then
+  WhereX := 255
+ else
+  WhereX := X1;
+end;
+
+function WhereY: byte;
+var
+ Y1: dword;
+begin
+ Y1 := WhereY32;
+ if Y1 > 255 then
+  WhereY := 255
+ else
+  WhereY := Y1;
+end;
+
+
+procedure ClrScr;
+{Clears the current window.}
+begin
+ RemoveLines (0, Succ (WindMaxY - WindMinY));
+ GotoXY32 (1, 1);
+end;
+
+
+procedure GotoXY32 (X, Y: dword);
+(* Positions cursor on (X, Y) (1-based) relative to window origin; for TP/BP
+   compatibility call completely ignored in case of incorrect parameters.    *)
+begin
+ if (X > 0) and (Y > 0) then
+  begin
+   Dec (X);
+   Dec (Y);
+   if (X <= WindMaxX - WindMinX) and (Y <= WindMaxY - WindMinY) then
+    SetScreenCursor (X + WindMinX, Y + WindMinY);
+  end;
+end;
+
+
+function WhereX32: dword;
+(* Returns the X position of the cursor (1-based). *)
+var
+ X, Y: dword;
+begin
+ GetScreenCursor (X, Y);
+ WhereX32 := Succ (X - WindMinX);
+end;
+
+
+function WhereY32: dword;
+(* Returns the Y position of the cursor (1-based). *)
+var
+ X, Y: dword;
+begin
+ GetScreenCursor (X, Y);
+ WhereY32 := Succ (Y - WindMinY);
+end;
+
+
+procedure ClrEol;
+(* Clears the line where cursor is located from current position up to end. *)
+var
+ X, Y: dword;
+begin
+ GetScreenCursor (X, Y);
+ ClearCells (X, Y, Succ (WindMaxX - X));
+end;
+
+
+procedure DelLine;
+(* Deletes the line at cursor. *)
+begin
+ RemoveLines (Pred (WhereY32), 1);
+end;
+
+
+procedure TextMode (Mode: word);
+{ Use this procedure to set-up a specific text-mode.}
+begin
+ TextAttr := $07;
+ LastMode := Mode;
+ SetScreenMode (Mode);
+ WindMin := 0;
+ WindMaxX := Pred (ScreenWidth);
+ WindMaxY := Pred (ScreenHeight);
+ if WindMaxX >= 255 then
+  WindMax := 255
+ else
+  WindMax := WindMaxX;
+ if WindMaxY >= 255 then
+  WindMax := WindMax or $FF00
+ else
+  WindMax := WindMax or (WindMaxY shl 8);
+ ClrScr;
+end;
+
+
+procedure TextColor (Color: byte);
+{All text written after calling this will have Color as foreground colour.}
+begin
+ TextAttr := (TextAttr and $70) or (Color and $f);
+ if Color > 15 then
+  TextAttr := TextAttr or 128;
+end;
+
+
+procedure TextBackground (Color: byte);
+{All text written after calling this will have Color as background colour.}
+begin
+ TextAttr := (TextAttr and $8F) or ((Color and $7) shl 4);
+end;
+
+
+procedure NormVideo;
+{Changes the text-background to black and the foreground to white.}
+begin
+ TextAttr := $7;
+end;
+
+
+procedure LowVideo;
+{All text written after this will have low intensity.}
+begin
+ TextAttr := TextAttr and $F7;
+end;
+
+
+procedure HighVideo;
+{All text written after this will have high intensity.}
+begin
+ TextAttr := TextAttr or $8;
+end;
+
+
+procedure Window32 (X1, Y1, X2, Y2: dword);
+{Change the write window to the given coordinates.}
+begin
+ if (X1 > 0) and (Y1 > 0) and (X2 <= ScreenWidth) and (Y2 <= ScreenHeight)
+                                             and (X1 <= X2) and (Y1 <= Y2) then
+  begin
+   WindMinX := Pred (X1);
+   WindMinY := Pred (Y1);
+   if WindMinX >= 255 then
+    WindMin := 255
+   else
+    WindMin := WindMinX;
+   if WindMinY >= 255 then
+    WindMin := WindMin or $FF00
+   else
+    WindMin := WindMin or (WindMinY shl 8);
+   WindMaxX := Pred (X2);
+   WindMaxY := Pred (Y2);
+   if WindMaxX >= 255 then
+    WindMax := 255
+   else
+    WindMax := WindMaxX;
+   if WindMaxY >= 255 then
+    WindMax := WindMax or $FF00
+   else
+    WindMax := WindMaxX or (WindMaxY shl 8);
+   GotoXY32 (1, 1);
+  end;
+end;
+
+
+{$ifdef HASTHREADVAR}
+threadvar
+{$else HASTHREADVAR}
+var
+{$endif HASTHREADVAR}
+ CurrX, CurrY: dword;
+
+
+procedure WriteChar (C: char);
+begin
+ case C of
+  #7: WriteBell;
+  #8: if CurrX >= WindMinX then
+       Dec (CurrX);
+{      #9: x:=(x-lo(windmin)) and $fff8+8+lo(windmin);}
+  #10: Inc (CurrY);
+  #13: CurrX := WindMinX;
+  else
+   begin
+    WriteNormal (C, CurrX, CurrY);
+    Inc (CurrX);
+   end;
+ end;
+ if CurrX > WindMaxX then
+  begin
+   CurrX := WindMinX;
+   Inc (CurrY);
+  end;
+ if CurrY > WindMaxY then
+  begin
+   RemoveLines (0, 1);
+   CurrY := WindMaxY;
+  end;
+end;
+
+
+function CrtWrite (var F: TextRec): integer;
+var
+ I: dword;
+{Write a series of characters to the console.}
+begin
+ if F.BufPos > 0 then
+  begin
+   GetScreenCursor (CurrX, CurrY);
+   for I := 0 to Pred (F.BufPos) do
+    WriteChar ((PChar (F.BufPtr) + I)^);
+   SetScreenCursor (CurrX, CurrY);
+   F.BufPos := 0;
+  end;
+ CrtWrite := 0;
+end;
+
+
+function CrtRead (var F: TextRec): integer;
+{Read a series of characters from the console.}
+var
+ C: char;
+begin
+ GetScreenCursor (CurrX, CurrY);
+ F.BufPos := 0;
+ F.BufEnd := 0;
+ repeat
+  if F.BufPos > F.BufEnd then
+   F.BufEnd := F.BufPos;
+  SetScreenCursor (CurrX, CurrY);
+  C := ReadKey;
+  case C of
+   #0: ReadKey;
+(* The following code to support input editing is incomplete anyway
+   - no handling of line breaks, no possibility to insert characters
+   or delete characters inside the string, etc.
+
+   #0 : case readkey of
+          #71 : while f.bufpos>0 do
+                 begin
+                   dec(f.bufpos);
+                   WriteChar(#8);
+                 end;
+          #75 : if f.bufpos>0 then
+                 begin
+                   dec(f.bufpos);
+                   WriteChar(#8);
+                 end;
+          #77 : if f.bufpos<f.bufend then
+                 begin
+                   WriteChar(f.bufptr^[f.bufpos]);
+                   inc(f.bufpos);
+                 end;
+          #79 : while f.bufpos<f.bufend do
+                 begin
+                   WriteChar(f.bufptr^[f.bufpos]);
+                   inc(f.bufpos);
+                 end;
+         end;
+*)
+
+   #8: if (F.BufPos > 0) and (F.BufPos = F.BufEnd) then
+        begin
+{$WARNING CrtRead doesn't handle line breaks correctly (same bug as TP/BP)!}
+         WriteChar (#8);
+         WriteChar (' ');
+         WriteChar (#8);
+         Dec (F.BufPos);
+         Dec (F.BufEnd);
+        end;
+   #13: begin
+         WriteChar(#13);
+         WriteChar(#10);
+         F.BufPtr^ [F.BufEnd] := #13;
+         Inc (F.BufEnd);
+         F.BufPtr^ [F.BufEnd] := #10;
+         Inc (F.BufEnd);
+         break;
+        end;
+   #26: if CheckEOF then
+         begin
+          F.BufPtr^ [F.BufEnd] := #26;
+          Inc (F.BufEnd);
+          break;
+         end;
+   #32..#255: if F.BufPos < F.BufSize - 2 then
+               begin
+                F.BufPtr^ [F.BufPos] := C;
+                Inc (F.BufPos);
+                WriteChar (C);
+               end;
+  end
+ until false;
+ CrtRead := 0;
+end;
+
+
+function CrtReturn (var F: TextRec): integer;
+begin
+ CrtReturn:=0;
+end;
+
+
+function CrtClose (var F: TextRec): integer;
+begin
+ F.Mode := fmClosed;
+ CrtClose := 0;
+end;
+
+
+function CrtOpen (var F: TextRec): integer;
+begin
+ if F.Mode = fmOutput then
+  begin
+   TextRec(F).InOutFunc := @CrtWrite;
+   TextRec(F).FlushFunc := @CrtWrite;
+  end
+ else
+  begin
+   F.Mode := fmInput;
+   TextRec(F).InOutFunc := @CrtRead;
+   TextRec(F).FlushFunc := @CrtReturn;
+  end;
+ TextRec(F).CloseFunc := @CrtClose;
+ CrtOpen := 0;
+end;
+
+
+procedure AssignCrt (var F: text);
+{Assigns a file to the crt console.}
+begin
+ Assign (F, '');
+ TextRec (F).OpenFunc := @CrtOpen;
+end;
+
+
+{$IFNDEF HAS_SOUND}
+procedure Sound (Hz: word);
+(* Dummy Sound implementation - for platforms requiring both frequence
+   and duration at the beginning instead of start and stop procedures. *)
+begin
+end;
+{$ENDIF HAS_SOUND}
+
+
+{$IFNDEF HAS_NOSOUND}
+procedure NoSound;
+(* Dummy NoSound implementation - for platforms requiring both frequence
+   and duration at the beginning instead of start and stop procedures.   *)
+begin
+end;
+{$ENDIF HAS_NOSOUND}
+
+
+procedure CrtInit;
+(* Common part of unit initialization. *)
+begin
+ TextAttr := LightGray;
+ WindMin := 0;
+ WindMaxX := Pred (ScreenWidth);
+ WindMaxY := Pred (ScreenHeight);
+ if WindMaxX >= 255 then
+  WindMax := 255
+ else
+  WindMax := WindMaxX;
+ if WindMaxY >= 255 then
+  WindMax := WindMax or $FF00
+ else
+  WindMax := WindMax or (WindMaxY shl 8);
+ ExtKeyCode := #0;
+ AssignCrt (Input);
+ Reset (Input);
+ AssignCrt (Output);
+ Rewrite (Output);
+end;
+
+{
+  $Log$
+  Revision 1.1  2005-05-14 14:32:55  hajny
+    + basis for common platform independent implementation of Crt
+
+
+}