

; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­                                                                 ­­
; ­­                        CLIwindow V1.00                          ­­
; ­­                                                                 ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­                                                                 ­­
; ­­         Copyright 12/1990 by    Roger Fischlin                  ­­
; ­­                                 Steigerwaldweg 6                ­­
; ­­                                 6450 Hanau 7                    ­­
; ­­                                 Germany                         ­­
; ­­                                                                 ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­                                                                 ­­
; ­­ This program may be freely  distributed if you don't  gain  any ­­
; ­­ profit by using and/or distributing it.                         ­­
; ­­                                                                 ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­    This program is pc relative and 100% PURE (set P flag)       ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­


	incdir	"ram:include/"

	include	"exec/exec_lib.i"
	include	"exec/memory.i"
	include	"intuition/intuition_Lib.i"
	include	"intuition/intuition.i"
	include	"libraries/dos.i"
	include	"libraries/dos_lib.i"
	include	"libraries/dosextens.i"


; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­                              Macros                             ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­


DOS	macro			; die alten Macros müssen ersetzt
	move.l	Var_DOS(a5),a6		; werden, da ja die Library-Bases
	jsr	_LVO\1(a6)		; an anderer Stelle vermerkt werden.
	endm

INT	macro
	move.l	Var_INT(a5),a6
	jsr	_LVO\1(a6)
	endm
	


; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­                          Variablen                              ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­

	rsreset
Var_DOS	rs.l	1		; DOSBase
Var_INT	rs.l	1		; IntuitionBase
Var_Parameter	rs.l	1		; Zeiger auf Paramterstring
Var_X	rs.w	1		; X-Ordinate
Var_Y	rs.w	1		; Y-Ordinate
Var_Width	rs.w	1		; Breite
Var_Height	rs.w	1		; Höhe
Var_Window	rs.l	1		; Zeiger aufs Window

Var_SIZEOF	rs.b	0


; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­                 Variablenspeicherplatz belegen                  ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­ Diese Routine belegt den Speicherplatz für die zuvor  bestimmte ­­
; ­­ Variablenliste. Bei einem Fehler wird  das anschließende Haupt- ­­
; ­­ programm nicht gestartet.                                       ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­


_main	clr.b	-1(a0,d0)		; Paramterstring mit $00 terminieren
	move.l	a0,a4
	moveq.l	#Var_SIZEOF,d0		; Variablenspeicher
	move.l	#MEMF_CLEAR+MEMF_PUBLIC,d1	; belegen
	CALLEXEC	AllocMem
	tst.l	d0
	beq.s	.Fehler		; Fehler !
	move.l	d0,a5
	move.l	a4,Var_Parameter(a5)
	bsr	.Programm		: ins Hauptprogramm
.Label1	move.l	d0,-(sp)
	move.l	a5,a1
	moveq.l	#Var_SIZEOF,d0
	CALLEXEC	FreeMem		; Variablenspeicher freigeben
	move.l	(sp)+,d0
	rts
.Fehler	moveq.l	#20,d0		; fataler Fehler !
	bra.s	.Label1
.Programm

; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­                       Hauptprogramm                             ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­

MAIN	bsr	GetLibs		; DOS- und Intuition-Library öffnen
	tst.l	d0		; Fehler
	beq	.Fehler
	bsr	CLIWindow		; Zeiger auf CLI-Window
	lea.l	.Text1(pc),a0
	tst.l	d0
	beq	.PrintText
	move.l	d0,Var_Window(a5)	; Zeiger merken

	move.l	d0,a0
	move.w	wd_LeftEdge(a0),Var_X(a5)	; aktuelle Windowerte als Voreinstellung
	move.w	wd_TopEdge(a0),Var_Y(a5)	; kopieren
	move.w	wd_Width(a0),Var_Width(a5)
	move.w	wd_Height(a0),Var_Height(a5)


	move.l	Var_Parameter(a5),a0	; X-Ordinate holen
	move.l	a0,a1
	cmp.b	#"?",(a0)
	beq	.INFO		; Info-String ausgeben
	cmp.b	#"*",(a1)+		; aktuellen Wert übernehmen ?
	beq.s	.Label1
	subq.l	#1,a1		; A0 wieder um eins vermindern
	bsr	GetLong
	move.l	a0,a1		; Zeiger auf nächstes Argument
	lea.l	.Text2(pc),a0
	tst.l	d1		; Fehler ?
	bne	.PrintText		; Fehlermeldung ausgeben
	move.w	d0,Var_X(a5)
.Label1	cmp.b	#"/",(a1)+		; "/"-Zeichen ?
	bne	.PrintText

	move.l	a1,a0		; Y-Ordinate holen
	cmp.b	#"*",(a1)+		; aktuellen Wert übernehmen ?
	beq.s	.Label2
	subq.l	#1,a1		; A0 wieder um eins vermindern
	bsr	GetLong
	move.l	a0,a1		; Zeiger auf nächstes Argument
	lea.l	.Text2(pc),a0
	tst.l	d1		; Fehler ?
	bne	.PrintText		; Fehlermeldung ausgeben
	move.w	d0,Var_Y(a5)
.Label2	cmp.b	#"/",(a1)+		; "/"-Zeichen ?
	bne	.PrintText

	move.l	a1,a0		; Breite holen
	cmp.b	#"*",(a1)+		; aktuellen Wert übernehmen ?
	beq.s	.Label3
	subq.l	#1,a1		; A0 wieder um eins vermindern
	bsr	GetLong
	move.l	a0,a1		; Zeiger auf nächstes Argument
	lea.l	.Text2(pc),a0
	tst.l	d1		; Fehler ?
	bne	.PrintText		; Fehlermeldung ausgeben
	move.w	d0,Var_Width(a5)
.Label3	cmp.b	#"/",(a1)+		; "/"-Zeichen ?
	bne	.PrintText

	move.l	a1,a0		; Höhe holen
	cmp.b	#"*",(a1)+		; aktuellen Wert übernehmen ?
	beq.s	.Label12
	subq.l	#1,a1		; A0 wieder um eins vermindern
	bsr	GetLong
	move.l	a0,a1		; Zeiger auf nächstes Argument
	lea.l	.Text2(pc),a0
	tst.l	d1		; Fehler ?
	bne	.PrintText		; Fehlermeldung ausgeben
	move.w	d0,Var_Height(a5)


.Label12	CALLEXEC	Forbid		; kein anderer Task darf das Window jetzt verschieben !
	move.l	Var_Window(a5),a0	; Window-Zeiger
	move.l	wd_WScreen(a0),a1	; Screen-Zeiger

	move.w	Var_Width(a5),d0
	cmp.w	#0,d0		; Ist die Breite >0 ?
	bgt.s	.Label10		; wenn ja, verzweige
	add.w	sc_Width(a1),d0	; sonst : echte Breite = Breite + Screen_Breite - Window_X
	sub.w	Var_X(a5),d0
	move.w	d0,Var_Width(a5)
.Label10	move.w	Var_Height(a5),d0
	cmp.w	#0,d0		; Ist die Höhe >0 ?
	bgt.s	.Label11		; wenn ja, verzweige
	add.w	sc_Height(a1),d0	; sonst : echte Höhe = Höhe + Screen_Höhe - Window_Y
	sub.w	Var_Y(a5),d0
	move.w	d0,Var_Height(a5)
.Label11

	move.w	Var_Width(a5),d0
	cmp.w	wd_MaxWidth(a0),d0	; Gewünschte Breite größer als erlaubte ?
	bls.s	.Label6
	move.w	wd_MaxWidth(a0),d0	; erlaubte Breite
.Label6	cmp.w	wd_MinWidth(a0),d0	; Gewünschte Breite kleiner als erlaubte ?
	bhi.s	.Label7
	move.w	wd_MinWidth(a0),d0	; erlaubte Breite
.Label7	move.w	d0,Var_Width(a5)


	move.w	Var_Height(a5),d0
	cmp.w	wd_MaxHeight(a0),d0	; Gewünschte Höhe größer als erlaubte ?
	bls.s	.Label8
	move.w	wd_MaxHeight(a0),d0
.Label8	cmp.w	wd_MinHeight(a0),d0	; Gewünschte Höhe kleiner als erlaubte ?
	bhi.s	.Label9
	move.w	wd_MinHeight(a0),d0	; erlaubte Höhe
.Label9	move.w	d0,Var_Height(a5)


	move.l	wd_WScreen(a0),a0	; Zeiger auf zugehörigen Screen

	move.w	Var_X(a5),d0		; X2 bestimmen
	add.w	Var_Width(a5),d0
	move.w	Var_Y(a5),d1		; Y2 bestimmen
	add.w	Var_Height(a5),d1

	cmp.w	sc_Width(a0),d0	; X2> Windowbreite ?
	bls.s	.Label4
	CALLEXEC	Permit		; Fehler !
	lea.l	.Text3(pc),a0
	bra	.PrintText
.Label4	cmp.w	sc_Height(a0),d1	; Y2> Windowhöhe ?
	bls.s	.Label5
	CALLEXEC	Permit		; Fehler !
	lea.l	.Text3(pc),a0
	bra	.PrintText


.Label5	move.l	Var_Window(a5),a0	; zunächst Window-Position verändern
	move.w	Var_X(a5),d0		; DeltaX = neue_X_Ordinate - X_Ordinate_Window
	move.w	Var_Y(a5),d1		; DeltaY = neue_Y_Ordinate - Y_Ordinate_Window
	sub.w	wd_LeftEdge(a0),d0
	sub.w	wd_TopEdge(a0),d1
	INT	MoveWindow

	move.l	Var_Window(a5),a0	; jetzt die Window-Größe verändern
	move.w	Var_Width(a5),d0	; DeltaX = neue_Breite - alte_Breite
	move.w	Var_Height(a5),d1	; DeltaY = neue_Höhe   - alte_Höhe
	sub.w	wd_Width(a0),d0
	sub.w	wd_Height(a0),d1
	INT	SizeWindow

	CALLEXEC	Permit		; das war's !
	lea.l	.NewSize(pc),a0	; das CLI/die SHELL soll die neuen Ausmaße übernehmen !
	bsr	CLIText


	bsr	CloseLibs		; zuvor geöffnete Libraries schließen
	moveq.l	#0,d0		; kein Fehler !
	rts

.Fehler	bsr	CloseLibs		; zuvor geöffnete Libraries schließen
	moveq.l	#20,d0		; fataler Fehler !
	rts

.PrintText	bsr	CLIText		; Fehlermeldung ausgeben
	bsr	CloseLibs		; zuvor geöffnete Libraries schließen
	moveq.l	#0,d0
	rts

.INFO	lea.l	.InfoString(pc),a0	; "?"-Funktion
	bra.s	.PrintText

.Text1	dc.b	"Can't get window pointer !",10,0
	even
.Text2	dc.b	"Sytax error !",10,0
	even
.Text3	dc.b	"Check screen size !",10,0
	even
.NewSize	dc.b	$9b,"t",$9b,"u",0
	even
.InfoString	dc.b	10," ",$9b,"4m"
	dc.b	"            CLIwindow V1.00    © 12/1990 Roger Fischlin            "
	dc.b	$9b,"0m",10,10
	dc.b	" CLIwindow may be freely  distributed  if you  don't gain  an profit",10
	dc.b	" by using and/or distributing it.CLIwindow will move this CLI window",10
	dc.b	" and change its size.",10,10
	dc.b	" Usage : CLIwindow x/y/width/height",10,10
	dc.b	" use '*' for current data. CLIwindow will check MinWidth & MinHeight",10
	dc.b	" and MaxWidth & MaxHeight. It also takes  care of the  screen  size.",10
	dc.b	" You may use hexadecimal numbers, too. If Width od Height are bellow",10
	dc.b	" 1 then they are taken as X2 oder Y2  relative to the  screen size .",10
	dc.b	" For example 'CLIwindow 0/0/0/0' will use  the  whole screen size or",10
	dc.b	" 'CLIwindow 0/0/-10/0' will leave ten rows free.",10
	dc.b	10,0

; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­                           GetLibs                               ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­ GetLibs öffnet  die  DOS-  und  die  Intuition-Library ab Kick- ­­
; ­­ start 1.2 . Tritt ein Fehler auf, so enthält D0 0.              ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­

GetLibs	lea.l	IntName(pc),a1		; Intuition-Library
	moveq.l	#33,d0		; ab Kickstart 1.2
	CALLEXEC	OpenLibrary		; öffnen
	move.l	d0,Var_INT(a5)
	beq.s	.Error
	lea.l	DosName(pc),a1		; DOS-Library
	moveq.l	#33,d0		; ab Kickstart 1.2
	CALLEXEC	OpenLibrary		; öffnen
	move.l	d0,Var_DOS(a5)
.Error	rts

IntName	INTNAME			; Library-Namen
DosName	DOSNAME

; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­                          CloseLibs                              ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­ CloseLibs schließt die von OpenLibs geöffneten Libraries, nicht ­­
; ­­ geöffnete Libraries werden abgefangen.                          ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­

CloseLibs	move.l	d2,-(sp)		; D2 retten
	moveq.l	#0,d2		; D2 als $0000000-Vergleich
	move.l	Var_INT(a5),a1		; Intuition-Library schließen
	cmp.l	a0,d2		; Wurde sie überhaupt geöffnet ?
	beq.s	.Skip1
	CALLEXEC	CloseLibrary
.Skip1	move.l	Var_DOS(a5),a1		; DOS-Library schließen
	cmp.l	a0,d2		; Wurde sie überhaupt geöffnet ?
	beq.s	.Skip2
	CALLEXEC	CloseLibrary
.Skip2	move.l	(sp)+,d2
	rts

; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­                           CLIWindow                             ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­ CLIWindow ermittelt den Zeiger auf das Fenster  des CLIs, bzw.  ­­
; ­­ liefet 0 bei einem Fehler.                                      ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­


CLIWindow	movem.l	a2-a5,-(sp)		; Register retten
	sub.l	a1,a1
	CALLEXEC	FindTask		; Zeiger auf eigenen Task
	move.l	d0,a0
	move.l	pr_ConsoleTask(a0),a2	; ID der zugehörigen Console

	sub.l	a0,a0		; Reply-Port erzeugen
	moveq.l	#0,d0
	bsr	CreatePort
	tst.l	d0		; Fehler ?
	beq	.Label1
	move.l	d0,a3		; Zeiger auf Reply-Port retten

	bsr	CreatePacket		; StandardPacket erzeugen
	tst.l	d0		; Fehler ?
	beq.s	.Label2
	move.l	d0,a4
	move.l	a3,sp_Pkt+dp_Port(a4)	; Reply-Port eintragen

	moveq.l	#id_SIZEOF,d0		; Speicher für InfoData reservieren
	move.l	#MEMF_PUBLIC!MEMF_CLEAR,d1
	CALLEXEC	AllocMem
	tst.l	d0
	beq.s	.Label3
	move.l	d0,a5

	lsr.l	#2,d0		; id-Zeiger in BCPL-Zeiger umwandeln
	move.l	d0,sp_Pkt+dp_Arg1(a4)	; und ins DosPacket eintragen
	move.l	#ACTION_DISK_INFO,sp_Pkt+dp_Type(a4)	

	move.l	a4,a1		; Zeiger auf Packet
	move.l	a2,a0		; Zeiger auf Port
	CALLEXEC	PutMsg

.Label5	move.l	a3,a0		; auf Reply warten
	CALLEXEC	WaitPort	

	move.l	a3,a0		; Reply-Message holen
	CALLEXEC	GetMsg
	tst.l	d0		; doch keine Message ?
	beq.s	.Label5
	
	move.l	id_VolumeNode(a5),d0	; WindowPointer !

.Label4	move.l	d0,-(sp)
	move.l	a5,a1		; Speicher für InfoData 
	moveq.l	#id_SIZEOF,d0		; freigeben
	CALLEXEC	FreeMem
	move.l	(sp)+,d0

.Label3	move.l	d0,-(sp)
	move.l	a4,a0
	bsr	DeletePacket		; Standard-Packet löschen
	move.l	(sp)+,d0

.Label2	move.l	d0,-(sp)
	move.l	a3,a0
	bsr	DeletePort		; Reply-Port löschen
	move.l	(sp)+,d0

.Label1	movem.l	(sp)+,a2-a5
	rts


; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­                           CreatePacket                          ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­ CreatePacket erzeugt ein StandardPacket,Message- und DosPacket- ­­
; ­­ Teil werden verbunden. In d0/a0 wird er Zeiger zurückgeben,bzw. ­­
; ­­ 0 bei einen Fehler.                                             ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­


CreatePacket	moveq.l	#sp_SIZEOF,d0		; Speicher für StandardPacket reservieren
	move.l	#MEMF_PUBLIC!MEMF_CLEAR,d1
	CALLEXEC	AllocMem
	tst.l	d0
	beq.s	.Label1
	move.l	d0,a0	
	lea.l	sp_Pkt(a0),a1		; Zeiger auf Packet-Teil
	move.l	a1,sp_Msg+LN_NAME(a0)	; Node-Namen muß auf Packet-Teil zeigen
	move.l	a0,sp_Pkt+dp_Link(a0)	; DosPacket-Link muß auf Message-Teil zeigen
.Label1	rts	

; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­                           DeletePacket                          ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­ DeletePacket  löscht ein   zuvor   mit  CreatePacket  erzeugtes ­­
; ­­ StandardPacket. Als Parameter  wird  in A0 der  Zeiger auf  das ­­
; ­­ StandardPacket erwartet.                                        ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­

DeletePacket	moveq.l	#0,d0
	cmp.l	d0,a0		; 0-Zeiger abfangen !
	beq.s	.NIL
	move.l	a0,a1
	moveq.l	#sp_SIZEOF,d0		; Speicher freigeben
	CALLEXEC	FreeMem
.NIL	rts


; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­                          CreatePort                             ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­ CreatePort erzeugt einen  funktionsfähigen   Msg-Port  des Typs ­­
; ­­ PA_SIGNAL mit der Priorität von D0.A0 zeigt auf den Port-Namen, ­­
; ­­ der nicht kopiert  wird. Falls A0 0  ist, wird er nicht in  die ­­
; ­­ Liste öffentlicher  Ports   aufgenommen.  Als SigTask wird  der ­­
; ­­ eigene eingetragen. Der Funktionswert in D0 ist  der Zeiger auf ­­
; ­­ auf den Port oder bei einem Fehler 0 .                          ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­


CreatePort	move.l	a2,-(sp)
	movem.l	d0/a0,-(sp)		; retten
	moveq.l	#MP_SIZE,d0		; Speicher für Port reservieren
	move.l	#MEMF_PUBLIC!MEMF_CLEAR,d1
	CALLEXEC	AllocMem
	tst.l	d0
	beq.s	.NoMem
	move.l	d0,a2
	moveq.l	#-1,d0		; Signal belegen
	CALLEXEC	AllocSignal
	move.b	d0,MP_SIGBIT(a2)
	bmi.s	.FreeMem		; kein Signal 
	movem.l	(sp)+,d0/a0
	move.b	d0,MP+LN_PRI(a2)	; Priorität eintragen
	move.b	#NT_MSGPORT,LN_TYPE(a2)
	move.l	a0,MP+LN_NAME(a2)	; Name
	sub.l	a1,a1
	CALLEXEC	FindTask
	move.l	d0,MP_SIGTASK(a2)	; eigener Task als Signal-Empfänger
	lea.l	MP_MSGLIST(a2),a0
	move.b	#NT_MESSAGE,LH_TYPE(a0)	; Messages werden verwaltet
	bsr	NewList
	tst.l	MP+LN_NAME(a2)		; öffentlicher Port ?
	beq.s	.Private
	move.l	a2,a1
	CALLEXEC	AddPort		; Port in allgemeine Liste eintragen
.Private	move.l	a2,d0
	move.l	(sp)+,a2
	rts

.FreeMem	move.l	a2,a1
	moveq.l	#MP_SIZE,d0		; Speicher freigeben
	CALLEXEC	FreeMem
.NoMem	addq.l	#8,sp
	move.l	(sp)+,a2
	moveq.l	#0,d0		; Fehler !
	rts

; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­                            NewList                              ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­ NewList initialisiert eine LIST-Struktur, A0 muß auf die LIST-  ­­
; ­­ Struktur zeigen.                                                ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­

NewList	move.l	a0,LH_HEAD(a0)		; LH_HEAD muß auf LH_TAIL zeigen
	addq.l	#LH_TAIL,(a0)
	clr.l	LH_TAIL(a0)		; LH_TAIL muß auf  0 zeigen
	move.l	a0,LH_TAILPRED(a0)
	rts

; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­                         DeletePort                              ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­ DeletePort löscht einen zuvor mit CreatePort erzeugten MsgPort. ­­
; ­­ Als Parameter wird in A0 der Zeiger auf den Port erwartet.Noch  ­­
; ­­ ausstehende Messages werden zuvor reply-t.                      ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­

DeletePort	move.l	a2,-(sp)
	move.l	a0,a2		; Zeiger retten
	CALLEXEC	Forbid		; Multitasking unterbinden
.Loop	move.l	a2,a0
	CALLEXEC	GetMsg		; Msg holen
	tst.l	d0		; keine (weitere) Message mehr
	beq.s	.AllReplied
	move.l	d0,a1
	CALLEXEC	ReplyMsg		; Message reply-en
	bra.s	.Loop
.AllReplied	move.l	MP+LN_NAME(a2),d0	; öffentlicher Port ?
	beq.s	.Private
	move.l	a2,a1
	CALLEXEC	RemPort		; entfernen
.Private	move.b	MP_SIGBIT(a2),d0
	CALLEXEC	FreeSignal		; Signal freigeben
	move.l	a2,a1		; Speicher freigeben
	moveq.l	#MP_SIZE,d0
	CALLEXEC	FreeMem
	CALLEXEC	Permit		; Multitasking wieder erlauben
	move.l	(sp)+,a2
	rts

; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­                           CLIText                               ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­ CLIText gibt den mit einem $00-Byte  abgeschlossen Text (Zeiger ­­
; ­­ in A0) im CLI-Window aus.                                       ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­

CLIText	movem.l	d2/d3,-(sp)		; Register retten
	move.l	a0,d2		; Zeiger nach D2
	moveq.l	#-1,d3		; Länge ermitteln
.Label	addq.l	#1,d3
	tst.b	(a0)+
	bne.s	.Label
	DOS	Output		; Handle fürs CLI-Fenster
	move.l	d0,d1
	DOS	Write		; Text ausgeben
	movem.l	(sp)+,d2/d3
	rts

; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­                          GetLong                                ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­ GetLong übersetzt den ASCII-String (Zeiger in A0)  in ein Long- ­­
; ­­ Word, welches in D0 zurückgeben wird. Anschließend zeigt A0 auf ­­                                                      ­­
; ­­ das erste Zeichen nach der Zalh im String.  Enthält D1  0, trat ­­
; ­­ kein Fehler auf. 1 signalisiert einen Überlauf, -1 zeigt  einen ­­
; ­­ Fehler im Aufbau  an. Unterstützt werden  das  dezimale und das ­­
; ­­ hexadezimale ("$")  Zahlensystem.                               ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­

GetLong	movem.l	d3-d3/a1-a3,-(sp)	; Register retten
	bsr.s	.Main
	movem.l	(sp)+,d3-d3/a1-a3
	rts

.Main	moveq.l	#0,d0		; Register löschen
	moveq.l	#0,d1
	moveq.l	#0,d2
.Label1	move.b	(a0)+,d3		; Spaces und Tabs überlesen
	cmp.b	#" ",d3
	beq.s	.Label1
	cmp.b	#9,d3
	beq.s	.Label1

	cmp.b	#"$",d3		; hexadezimal ?
	beq	.Hex
	cmp.b	#"-",d3		; negativ ?
	beq.s	.Negativ
	cmp.b	#"9",d3		; Ziffer ?
	bhi	.Fehler
	cmp.b	#"0"-1,d3
	bhi	.Dezimal

.Fehler	subq.l	#1,a0		; ^Fehler
	moveq.l	#-1,d1		; Fehlercode
	rts

.Negativ	tst.b	d2		; teste,ob bereits ein "-"
	bne.s	.Fehler
	moveq.l	#1,d2		; Flag für negativ seten
	bra	.Label1




.Dezimal	subq.l	#1,a0		; A0 auf erste Ziffer setzen
	move.l	a0,a1		; A1 ^erstes Ziffer
.Label_D2	move.b	(a0)+,d3		; nächste Zeiffer holen 
	cmp.b	#"9",d3		; wiederhole, bis Zahlenende
	bhi.s	.Label_D3		; erreicht wird.
	cmp.b	#"0"-1,d3
	bhi.s	.Label_D2

.Label_D3	lea.l	.Data10(pc),a2		; Zeiger auf 10'er-Potenzen
	subq.l	#1,a0		; A0 ^letzte Ziffer+1
	move.l	a0,a3		; A3 ^letzte Ziffer+1 

.Label_D5	move.l	(a2)+,d4		; Stellenzahl holen
	beq.s	.Overflow		; Longwordgrenze überschritten ?
	moveq.l	#0,d3		; D3 löschen
	move.b	-(a3),d3		; vorherige Ziffer holen
	sub.b	#"0"+1,d3		; und in Zahl umwandeln (1 abziehen wegen DBRA-Schleife)
	bmi.s	.D_Zero		; Ziffer "0" abfangen
.Label_D4	add.l	d4,d0		; Stellenzahl so oft wie Ziffer addieren
	dbra	d3,.Label_D4
.D_Zero	cmp.l	a3,a1		; Zahlenanfang erreicht ?
	bne.s	.Label_D5

.Vorzeichen	tst.b	d2		; negatives Vorzeichen ?
	beq.s	.NotNegative
	tst.l	d0		; Ist die Zahl größer als ein Longint ?
	bmi	.Overflow
	neg.l	d0		; negativieren
.NotNegative	moveq.l	#0,d1		; keine Fehler
	rts

.Data10	dc.l	1
	dc.l	10
	dc.l	100
	dc.l	1000
	dc.l	10000
	dc.l	100000
	dc.l	1000000
	dc.l	10000000
	dc.l	100000000
	dc.l	1000000000
	dc.l	0

.Overflow	moveq.l	#1,d1		; Überfluß (Zahl zu groß !)
	rts
		




.Hex	move.b	(a0)+,d3		; erste Stelle OK ?
	bsr.s	.Nibble
	bmi	.Fehler		; Fehler !


	lea.l	-1(a0),a1		; A1 ^ erste Ziffer
.Label_H2	move.b	(a0)+,d3
	bsr.s	.Nibble		; in Hexa-Ziffer übersetzen 
	bpl.s	.Label_H2
	subq.l	#1,a0		; A0 ^letzte Ziffer+1
	move.l	a0,a2		; A2 ^letzte Ziffer+1
	moveq.l	#0,d1
.Label_H3	move.b	-(a2),d3		; vorherige Ziffer
	bsr	.Nibble
	lsl.l	d1,d4		; Nibble an richtige Position schieben
	add.l	d4,d0		; zum Ergebnis addieren
	addq.l	#4,d1
	cmp.b	#32,d1		; 32. Bit erreicht ?
	bhi	.Overflow		; wenn ja, Overflow !
	cmp.l	a2,a1		; Zahlenanfang erreicht ?
	bne.s	.Label_H3
	bra	.Vorzeichen

.Nibble	moveq.l	#0,d4
	cmp.b	#"a"-1,d3		; Ziffer d3 -> Zahl d4
	bls.s	.N1		; Upcase
	cmp.b	#"f",d3
	bhi.s	.N_Error
	sub.b	#"a"-"A",d3
.N1	sub.b	#"0",d3
	cmp.b	#9,d3		; Ziffer ?
	bls.s	.Ziffer
	sub.b	#"@"-"9",d3		; Buchstabe
	cmp.b	#$f,d3
	bhi.s	.N_Error
.Ziffer	move.b	d3,d4
	rts
.N_Error	moveq.l	#-1,d4		; Fehler !
	rts
	


