{ This file is part of the Free Pascal run time library. A file in Amiga system run time library. Copyright (c) 1998-2003 by Nils Sjoholm member of the Amiga RTL development team. 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. **********************************************************************} unit consoleio; { History: First version of ConsoleIO. This is an translation of consoleio from PCQ Pascal. Just AttachConsole to a window and you have your own console. 12 Sep 2000. Added the define use_amiga_smartlink. 13 Jan 2003. Changed integer > smallint. 10 Feb 2003. nils.sjoholm@mailbox.swipnet.se } {$I useamigasmartlink.inc} {$ifdef use_amiga_smartlink} {$smartlink on} {$endif use_amiga_smartlink} interface uses exec, intuition, console, amigalib, conunit; TYPE tConsoleSet = record WritePort, ReadPort : pMsgPort; WriteRequest, ReadRequest : pIOStdReq; Window : pWindow; { not yet used } Buffer : Char; end; pConsoleSet = ^tConsoleSet; { ConsoleIO.p This file implements all the normal console.device stuff for dealing with windows. They are pulled from the ROM Kernel Manual. See ConsoleTest.p for an example of using these routines. } Procedure ConPutChar(Request : pIOStdReq; Character : Char); Procedure ConWrite(Request : pIOStdReq; Str : pchar; length : longint); Procedure ConPutStr(Request : pIOStdReq; Str : pchar); Procedure QueueRead(Request : pIOStdReq; Where : pchar); Function ConGetChar(consolePort : pMsgPort; Request : pIOStdReq; WhereTo : pchar) : Char; Procedure CleanSet(con : pConsoleSet); Function AttachConsole(w : pWindow) : pConsoleSet; Function ReadKey(con : pConsoleSet) : Char; Function KeyPressed(con : pConsoleSet) : Boolean; Procedure WriteString(con : pConsoleSet; Str : Pchar); Procedure WriteString(con : pConsoleSet; Str : string); Function MaxX(con : pConsoleSet) : smallint; Function MaxY(con : pConsoleSet) : smallint; Function WhereX(con : pConsoleSet) : smallint; Function WhereY(con : pConsoleSet) : smallint; Procedure TextColor(con : pConsoleSet; pen : Byte); Procedure TextBackground(con : pConsoleSet; pen : Byte); Procedure DetachConsole(con : pConsoleSet); Procedure ClrEOL(con : pConsoleSet); Procedure ClrScr(con : pConsoleSet); Procedure CursOff(con : pConsoleSet); Procedure CursOn(con : pConsoleSet); Procedure DelLine(con : pConsoleSet); Function LongToStr (I : smallint) : String; Procedure GotoXY(con : pConsoleSet; x,y : smallint); Procedure InsLine(con : pConsoleSet); Procedure OpenConsoleDevice; Procedure CloseConsoleDevice; implementation Procedure ConPutChar(Request : pIOStdReq; Character : Char); var Error : longint; begin Request^.io_Command := CMD_WRITE; Request^.io_Data := Addr(Character); Request^.io_Length := 1; Error := DoIO(pIORequest(Request)); end; Procedure ConWrite(Request : pIOStdReq; Str : pchar; length : longint); var Error : longint; begin Request^.io_Command := CMD_WRITE; Request^.io_Data := Str; Request^.io_Length := Length; Error := DoIO(pIORequest(Request)); end; Procedure ConPutStr(Request : pIOStdReq; Str : pchar); var Error : longint; begin Request^.io_Command := CMD_WRITE; Request^.io_Data := Str; Request^.io_Length := -1; Error := DoIO(pIORequest(Request)); end; Procedure QueueRead(Request : pIOStdReq; Where : pchar); begin Request^.io_Command := CMD_READ; Request^.io_Data := Where; Request^.io_Length := 1; SendIO(pIORequest(Request)); end; Function ConGetChar(consolePort : pMsgPort; Request : pIOStdReq; WhereTo : pchar) : Char; var Temp : Char; TempMsg : pMessage; begin if GetMsg(consolePort) = Nil then begin TempMsg := WaitPort(consolePort); TempMsg := GetMsg(consolePort); end; Temp := WhereTo^; QueueRead(Request, WhereTo); ConGetChar := Temp; end; Procedure CleanSet(con : pConsoleSet); begin with con^ do begin if ReadRequest <> Nil then DeleteStdIO(ReadRequest); if WriteRequest <> Nil then DeleteStdIO(WriteRequest); if ReadPort <> Nil then DeletePort(ReadPort); if WritePort <> Nil then DeletePort(WritePort); end; end; Function AttachConsole(w : pWindow) : pConsoleSet; var con : pConsoleSet; Error : Boolean; begin New(con); if con = Nil then AttachConsole := Nil; with Con^ do begin WritePort := CreatePort(Nil, 0); Error := WritePort = Nil; ReadPort := CreatePort(Nil, 0); Error := Error or (ReadPort = Nil); if not Error then begin WriteRequest := CreateStdIO(WritePort); Error := Error or (WriteRequest = Nil); ReadRequest := CreateStdIO(ReadPort); Error := Error or (ReadRequest = Nil); end; if Error then begin CleanSet(con); Dispose(con); AttachConsole := Nil; end; Window := w; end; with con^.WriteRequest^ do begin io_Data := pointer(w); io_Length := SizeOf(tWindow); end; Error := OpenDevice('console.device', 0, pIORequest(con^.WriteRequest), 0) <> 0; if Error then begin CleanSet(con); Dispose(con); AttachConsole := Nil; end; with con^ do begin ReadRequest^.io_Device := WriteRequest^.io_Device; ReadRequest^.io_Unit := WriteRequest^.io_Unit; end; QueueRead(con^.ReadRequest, Addr(con^.Buffer)); AttachConsole := Con; end; Function ReadKey(con : pConsoleSet) : Char; begin with con^ do ReadKey := ConGetChar(ReadPort, ReadRequest, Addr(Buffer)); end; Function KeyPressed(con : pConsoleSet) : Boolean; begin with con^ do KeyPressed := CheckIO(pIORequest(ReadRequest)) <> Nil; end; Procedure WriteString(con : pConsoleSet; Str : Pchar); begin ConPutStr(con^.WriteRequest, Str); end; Procedure WriteString(con : pConsoleSet; Str : string); var temp : string; begin temp := Str; temp := temp + #0; ConPutStr(con^.WriteRequest, @temp[1]); end; Function MaxX(con : pConsoleSet) : smallint; var CU : pConUnit; begin CU := pConUnit(con^.WriteRequest^.io_Unit); MaxX := CU^.cu_XMax; end; Function MaxY(con : pConsoleSet) : smallint; var CU : pConUnit; begin CU := pConUnit(con^.WriteRequest^.io_Unit); MaxY := CU^.cu_YMax; end; Function WhereX(con : pConsoleSet) : smallint; var CU : pConUnit; begin CU := pConUnit(con^.WriteRequest^.io_Unit); WhereX := CU^.cu_XCP; end; Function WhereY(con : pConsoleSet) : smallint; var CU : pConUnit; begin CU := pConUnit(con^.WriteRequest^.io_Unit); WhereY := CU^.cu_YCP; end; Procedure TextColor(con : pConsoleSet; pen : Byte); var CU : pConUnit; begin CU := pConUnit(con^.WriteRequest^.io_Unit); CU^.cu_FgPen := pen; end; Procedure TextBackground(con : pConsoleSet; pen : Byte); var CU : pConUnit; begin CU := pConUnit(con^.WriteRequest^.io_Unit); CU^.cu_BgPen := pen; end; Procedure DetachConsole(con : pConsoleSet); var TempMsg : pMessage; begin with con^ do begin Forbid; if CheckIO(pIORequest(ReadRequest)) = Nil then begin AbortIO(pIORequest(ReadRequest)); Permit; TempMsg := WaitPort(ReadPort); TempMsg := GetMsg(ReadPort); end else Permit; CloseDevice(pIORequest(WriteRequest)); end; CleanSet(con); Dispose(con); end; const CSI = #27 + '['; Procedure ClrEOL(con : pConsoleSet); { Clear to the end of the line } begin WriteString(con, CSI + 'K'); end; Procedure ClrScr(con : pConsoleSet); { Clear the text area of the window } begin WriteString(con, CSI + '1;1H\cJ'); end; Procedure CursOff(con : pConsoleSet); { Turn the console device's text cursor off } begin WriteString(con, CSI + '0 p'); end; Procedure CursOn(con : pConsoleSet); { Turn the text cursor on } begin WriteString(con, CSI + ' p'); end; { Delete the current line, moving all the lines below it } { up one. The bottom line is cleared. } Procedure DelLine(con : pConsoleSet); begin WriteString(con, CSI + 'M'); end; Function LongToStr (I : smallint) : String; Var S : String; begin Str (I,S); LongToStr:=S; end; Procedure GotoXY(con : pConsoleSet; x,y : smallint); { Move the text cursor to the x,y position. This routine uses the ANSI CUP command. } var XRep : string[7]; YRep : string[7]; begin XRep := LongToStr(x); YRep := LongToStr(y); WriteString(con,CSI); WriteString(con,(YRep)); WriteString(con,string(';')); WriteString(con,(XRep)); WriteString(con,string('H')); end; { Insert a line at the current text position. The current line and } { all those below it are moved down one. } Procedure InsLine(con : pConsoleSet); begin WriteString(con, CSI + 'L'); end; { These routines just open and close the Console device without attaching it to any window. They update ConsoleBase, and are thus required for RawKeyConvert and DeadKeyConvert. } var ConsoleRequest : tIOStdReq; Procedure OpenConsoleDevice; { This procedure initializes ConsoleDevice, which is required for CDInputHandler and RawKeyConvert. } var Error : longint; begin Error := OpenDevice('console.device', -1, Addr(ConsoleRequest), 0); ConsoleDevice := ConsoleRequest.io_Device; end; Procedure CloseConsoleDevice; begin CloseDevice(Addr(ConsoleRequest)); end; end.