123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438 |
- {
- 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.
- **********************************************************************}
- var
- ScanCode: byte;
- SpecialKey: boolean;
- procedure GotoXY (X: tcrtcoord; Y: tcrtcoord);
- begin
- GotoXY32 (X, Y);
- end;
- procedure Window (X1, Y1, X2, Y2: byte);
- begin
- Window32 (X1, Y1, X2, Y2);
- end;
- function WhereX: tcrtcoord;
- var
- X1: dword;
- begin
- X1 := WhereX32;
- if X1 > 255 then
- WhereX := 255
- else
- WhereX := X1;
- end;
- function WhereY: tcrtcoord;
- 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;
- threadvar
- 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}
- var
- PrevCtrlBreakHandler: TCtrlBreakHandler;
- function CrtCtrlBreakHandler (CtrlBreak: boolean): boolean;
- begin
- (* Earlier registered handlers (e.g. FreeVision) have priority. *)
- if Assigned (PrevCtrlBreakHandler) then
- if PrevCtrlBreakHandler (CtrlBreak) then
- begin
- CrtCtrlBreakHandler := true;
- Exit;
- end;
- (* If Ctrl-Break was pressed, either ignore it or allow default processing. *)
- if CtrlBreak then
- CrtCtrlBreakHandler := not (CheckBreak)
- else (* Ctrl-C pressed *)
- begin
- if not (SpecialKey) and (ScanCode = 0) then
- ScanCode := 3;
- CrtCtrlBreakHandler := true;
- end;
- end;
- 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);
- ScanCode := 0;
- SpecialKey := false;
- AssignCrt (Input);
- Reset (Input);
- AssignCrt (Output);
- Rewrite (Output);
- PrevCtrlBreakHandler := SysSetCtrlBreakHandler (@CrtCtrlBreakHandler);
- if PrevCtrlBreakHandler = TCtrlBreakHandler (pointer (-1)) then
- PrevCtrlBreakHandler := nil;
- CheckBreak := true;
- end;
|