(*--------------------------------------------------------------------------- :Program. Terminal.mod :Author. ??? backtranslated Bernd Preusing :Address. Gerhardstr. 16 D-2200 Elmshorn :Phone. 04121/22486 :Shortcut. [bep] :Version. :Date. :Copyright. PD :Language. Modula-II :Translator. M2Amiga :Imports. XDos (special dos.library) :UpDate. :Contents. M2Amiga Terminal.mod :Remark. ---------------------------------------------------------------------------*) IMPLEMENTATION MODULE Terminal; FROM SYSTEM IMPORT CAST, SHIFT, INLINE, SETREG, ADDRESS, LONGSET, ADR; FROM Arts IMPORT startupMsg, wbStarted, Assert, TermProcedure; FROM ASCII IMPORT eol, eof, cr, lf, bs, can; FROM Assembler IMPORT D0, RTS; IMPORT Dos; FROM Exec IMPORT UByte, Byte, MsgPort, MsgPortPtr, FindTask, Wait; FROM XDos IMPORT XDos1, XDos2, XDos3; (* Wer hat das Dos geknackt?? *) FROM Intuition IMPORT NewWindow, WindowFlags, WindowFlagSet, ScreenFlags, ScreenFlagSet, IDCMPFlags, IDCMPFlagSet, Window, WindowPtr, OpenWindow, CloseWindow; FROM Workbench IMPORT WBStartupPtr, WBArg, WBArgumentsPtr, WBStartup; CONST msgFehler = 'Fehler beim Eröffnen des Terminals'; TYPE ProcessPtr = POINTER TO Dos.Process; (* Penner! *) LongPtr = POINTER TO LONGINT; CharPtr = POINTER TO CHAR; VAR InHandle, OutHandle: Dos.FileHandlePtr; MyWindow: WindowPtr; LoadedDevice: MsgPortPtr; MyStartup: WBStartupPtr; MyTask: ProcessPtr; OldSigBit: Byte; (* besser: UByte spart Code *) ReadPos,ActPos: INTEGER; InputBuffer: ARRAY[0..255] OF CHAR; StarName: CARDINAL; (* Ich weiß nicht, was hier getrickst wird, auf jeden Fall kostet das jedesmal 48 Bytes Speicher! *) PROCEDURE MakeWindow(name:ADDRESS); VAR nw:NewWindow; dev:ADDRESS; dev2: LongPtr; CONName:ARRAY[0..3] OF CHAR; BEGIN WITH nw DO leftEdge:=0; topEdge:=50; width:=640; height:=100; detailPen:=0; blockPen:=1; idcmpFlags:=IDCMPFlagSet{closeWindow}; flags:=WindowFlagSet{windowSizing, windowDrag, windowDepth, windowClose, activate}; firstGadget:=NIL; checkMark:=NIL; title:=name; screen:=NIL; bitMap:=NIL; minWidth:=100; minHeight:=40; maxWidth:=-1; maxHeight:=-1; type:=ScreenFlagSet{wbenchScreen} END; MyWindow:=OpenWindow(nw); Assert(MyWindow#NIL,ADR(msgFehler)); CONName:=' CON'; CONName[0]:=03C; (* Länge *) (* liefert wohl BPTR auf DeviceList *) dev:=XDos1(7CH,SHIFT(ADR(CONName),-2)); Assert(dev#NIL,ADR('finddevice failed')); dev2:=CAST(LongPtr,SHIFT(dev,2)); (* worauf zeigt das Ding ??? *) dev2:=CAST(LongPtr,CAST(LONGINT,dev2)+28); (* wäre dann DevList.startup ? *) dev2^:=-1; (* hänge CON an Window *) LoadedDevice:=CAST(MsgPortPtr,XDos2(70H,dev,MyWindow)); Assert(LoadedDevice#NIL,ADR('loaddevice failed')); dev2^:=0; MyTask^.consoleTask:=LoadedDevice; MyTask^.windowPtr:=MyWindow; OldSigBit:=MyWindow^.userPort^.sigBit; (* CloseGadget ergibt Ctrl-C *) MyWindow^.userPort^.sigBit:=Dos.ctrlC (* 12 *) END MakeWindow; PROCEDURE KillWindow(); BEGIN MyWindow^.userPort^.sigBit:=OldSigBit; IF waitCloseGadget THEN SETREG(D0,Wait(LONGSET{OldSigBit})); END; MyTask^.consoleTask:=NIL; MyTask^.windowPtr:=NIL; SETREG(D0,XDos3(30H,0,LoadedDevice,03EFH (* =1007 *) )); LoadedDevice:=NIL; MyWindow:=NIL; (* Kommt CloseWindow von XDos3 ??? *) END KillWindow; PROCEDURE DosWrite(ch:CHAR); BEGIN SETREG(D0,Dos.Write(OutHandle,ADR(ch),1)); (* SETREG: Resultat ignoriert *) END DosWrite; PROCEDURE ReadLine(); VAR ch0,ch:CHAR; unused, i, MyPos: INTEGER; BEGIN IF ActPos=255 THEN RETURN END; MyPos:=ActPos; LOOP IF Dos.Read(InHandle,ADR(ch),1)#1 THEN InputBuffer[ActPos]:=eof; INC(ActPos); EXIT END; IF (ch>=03C) AND (ch<=06C) THEN (* ctrlC..ctrlF *) EXIT ELSIF (ch=cr) AND (ActPos<255) THEN InputBuffer[ActPos]:=lf; DosWrite(lf); INC(ActPos); EXIT ELSIF ch=bs THEN IF ActPos>MyPos THEN DosWrite(bs); DosWrite(' '); DosWrite(bs); DEC(ActPos) END; IF ActPos=MyPos THEN EXIT END; ELSIF ch=can (* Ctrl-X *) THEN FOR i:=MyPos+1 TO ActPos DO DosWrite(bs); DosWrite(' '); DosWrite(bs) END; ActPos:=MyPos; EXIT ELSIF ActPos<255 THEN InputBuffer[ActPos]:=ch; DosWrite(ch); INC(ActPos); END; END; (* LOOP *) InputBuffer[ActPos]:=0C END ReadLine; PROCEDURE Read(VAR ch: CHAR); BEGIN IF wbStarted THEN WHILE ReadPos=ActPos DO ReadPos:=0; ActPos:=0; ReadLine END; ch:=InputBuffer[ReadPos]; INC(ReadPos) ELSE IF Dos.Read(InHandle,ADR(ch),1)#1 THEN ch:=eof END END END Read; PROCEDURE ReadLn(VAR st: ARRAY OF CHAR; VAR len: INTEGER); VAR a:CharPtr; ch1:CHAR; BEGIN len:=0; a:=CAST(CharPtr,ADR(st)); LOOP Read(ch1); IF (ch1=eol) OR (ch1=eof) THEN EXIT ELSIF len<=HIGH(st) THEN a^:=ch1; INC(len); INC(a) END; END; IF len<=HIGH(st) THEN a^:=0C END; END ReadLn; PROCEDURE Write(ch: CHAR); BEGIN IF wbStarted AND (Dos.WaitForChar(InHandle,1)#0) THEN ReadLine (* warte, bis Zeile fertig eingegeben *) END; SETREG(D0,Dos.Write(OutHandle,ADR(ch),1)) END Write; PROCEDURE WriteString(string: ARRAY OF CHAR); VAR length: INTEGER; BEGIN IF wbStarted AND (Dos.WaitForChar(InHandle,1)#0) THEN ReadLine END; length:=0; WHILE (length<=HIGH(string)) AND (string[length]#0C) DO INC(length) END; SETREG(D0,Dos.Write(OutHandle,ADR(string),length)) END WriteString; (* $E- *) (* Schöner Trick, geht aber nur ohne Parameter und Lokalvariablen! *) PROCEDURE WriteLn; BEGIN Write(eol); INLINE(RTS) END WriteLn; PROCEDURE Term(); BEGIN IF wbStarted AND (LoadedDevice#NIL) THEN KillWindow; OutHandle:=NIL END; IF MyWindow#NIL THEN CloseWindow(MyWindow) END END Term; BEGIN LoadedDevice:=NIL; MyWindow:=NIL; MyTask:=CAST(ProcessPtr,FindTask(NIL)); MyStartup:=startupMsg; waitCloseGadget:=TRUE; TermProcedure(Term); IF wbStarted THEN MakeWindow(MyStartup^.argList^[0].name); StarName:=2A00H; (* '*',0C = aktives Window *) OutHandle:=Dos.Open(ADR(StarName),Dos.oldFile); Assert(OutHandle#NIL,ADR(msgFehler)); InHandle:=OutHandle; ActPos:=0; ReadPos:=0; InputBuffer[ReadPos]:=0C ELSE OutHandle:=Dos.Output(); InHandle:=Dos.Input() END END Terminal.mod