***************************************************
***						***
*** Tips zu OS2.0:				***
*** --------------				***
***  + ListView-Gadget incl. Listenverwaltung	***
***  + CheckBox-Gadget				***
***  + BitMapScale()				***
***  + Screen & Windows				***
***  + Menüs					***
***						***
***	Markus Adamski				***
***	Tannenweg 7				***
***	4100 Duisburg 18			***
***						***
***	Assembler: Devpac 2.14D			***
***						***
***************************************************

		opt	c+,ow+,o1+,o3+,o4+,o5+,s-

		incdir	"DEVPAC:Includes/"
		include	"exec/exec.i"
		include	"graphics/displayinfo.i"
		include	"graphics/scale.i"
		include	"intuition/screens.i"
		include	"libraries/gadtools.i"
		include	"lvo.i"

		STRUCTURE Internal,0
		APTR	_IntBase	; Libraries-Basis-Adressen
		APTR	_GadBase
		APTR	_GfxBase
		APTR	ScrHandle	; -> Screen-Struktur
		APTR	WinHandle	; -> Windows-Struktur
		APTR	WinRPort	; -> Rastport des Windows
		APTR	LV_Gad		; -> ListView-Gadget
		APTR	GetVisual	; Ergebnis von GetVisualInfoA()
		APTR	MenuAddr	; Ergebnis von CreateMenusA()
		APTR	GadgetList	; -> Gadget-Liste
		UBYTE	Flags
		LABEL	Int_SIZEOF

CALL		MACRO
		IFEQ	NARG-2		; 2 Werte übergeben ?
		 IFND	\2		;  Ja -> 2. Wert definiert ?
		  move.l 4.W,a6		;   Nein -> ExecBase nach a6
		 ELSEIF
		  move.l \2(a5),a6	;   Sonst Basis auslesen
		 ENDC			; Bei Übergabe nur eines Wertes
		ENDC			;  wird a6 nicht verändert !
		jsr	_LVO\1(a6)	; Aufruf
		ENDM

OPENLIB		MACRO
		lea	\1(pc),a1
		moveq	#\2,d0
		CALL	OpenLibrary,EXEC
		move.l	d0,\3(a5)
		ENDM

MENU		MACRO
		dc.b	\1,0
		dc.l	\2,0
		dc.w	\3
		dc.l	0,0
		ENDM

TRUE	=	-1
FALSE	=	0

FirstEntry	= 0


		lea	StrucPtr(pc),a5		; Zeiger auf eigene Struktur

;*** Libraries öffnen
		OPENLIB	IntName,37,_IntBase	; Libraries öffnen
		beq	WrongOS
		OPENLIB	GadName,37,_GadBase
		beq	WrongOS
		OPENLIB	GfxName,37,_GfxBase
		beq	WrongOS

;*** Leere Liste erzeugen
		lea	ListStruktur(pc),a0	; Leere Liste erzeugen
		move.l	a0,LH_TAILPRED(a0)	; LH_TAILPRED -> LH_HEAD
		move.l	a0,LH_HEAD(a0)		; LH_HEAD -> LH_TAIL
		addq.l	#4,LH_HEAD(a0)
		clr.l	LH_TAIL(a0)		; LH_TAIL = 0

;*** Screen öffnen
		lea	ScrTags(pc),a1		; Screen öffnen
		sub.l	a0,a0
		CALL	OpenScreenTagList,_IntBase
		move.l	d0,ScrHandle(a5)	; Handle merken
		beq	NoScreen

;*** Window öffnen
		lea	WinTags(pc),a1		; Window öffnen
		move.l	d0,ti_Data(a1)		; Zeiger auf Screen eintragen
		sub.l	a0,a0
		CALL	OpenWindowTagList
		move.l	d0,WinHandle(a5)	; Handle merken
		beq	NoWin
		move.l	d0,a0			; Rastport-Adresse holen
		move.l	wd_RPort(a0),a0
		move.l	a0,WinRPort(a5)		;  und merken

;*** VisualInfo-Struktur erzeugen
		move.l	ScrHandle(a5),a0	; VisualInfo-Struktur
		lea	VInfo_Tag(pc),a1	;  erzeugen
		CALL	GetVisualInfoA,_GadBase
		move.l	d0,GetVisual(a5)

;*** Vorbereitung für NewGadgets
		lea	GadgetList(a5),a0	; Datenbereich reservieren
		CALL	CreateContext		; d0 = Zeiger

;*** ListView-Gadget erzeugen
		lea	List_Gad_Tag(pc),a2	; ListView-Gadget generieren
		lea	ListViewStruc(pc),a1
		move.l	GetVisual(a5),gng_VisualInfo(a1)
		move.l	d0,a0			; Erg. von CreateContext()
		moveq	#LISTVIEW_KIND,d0
		CALL	CreateGadgetA
		move.l	d0,LV_Gad(a5)		; Zeiger auf Gadget merken

;*** CheckBoxGadget erzeugen
		lea	Check_Gad_Tag(pc),a2	; CheckBox-Gadget erzeugen
		lea	CheckGadStruc(pc),a1
		move.l	GetVisual(a5),gng_VisualInfo(a1)
		move.l	d0,a0			; Erg. von CreateGadgetA()
		moveq	#CHECKBOX_KIND,d0
		CALL	CreateGadgetA

;*** Menü erstellen und an Window übergeben
		lea	MenuStruct(pc),a0	; Menü erstellen
		lea	MenuTag(pc),a1
		CALL	CreateMenusA
		move.l	d0,MenuAddr(a5)		; Menü-Adresse merken
		move.l	d0,a0
		move.l	GetVisual(a5),a1
		lea	LayoutTag(pc),a2
		CALL	LayoutMenusA
		move.l	WinHandle(a5),a0	; Menü einhängen
		move.l	MenuAddr(a5),a1
		CALL	SetMenuStrip,_IntBase

;*** Gadgets zeichnen
		move.l	WinHandle(a5),a0	; Gadget in Window-
		move.l	GadgetList(a5),a1	;  Struktur eintragen
		moveq	#-1,d0
		moveq	#-1,d1
		sub.l	a2,a2
		CALL	AddGList
		move.l	GadgetList(a5),a0	; Gadgets zeichnen
		move.l	WinHandle(a5),a1
		sub.l	a2,a2
		moveq	#-1,d0
		CALL	RefreshGList
		move.l	WinHandle(a5),a0
		sub.l	a1,a1
		CALL	GT_RefreshWindow,_GadBase

; *** Liste mit Einträgen erzeugen
; *** AB HIER DARF A0 NICHT ANDERWEITIG VERÄNDERT WERDEN !!!

		lea	ListStruktur(pc),a0	; Listenkopf initialisieren
		move.l	a0,LH_HEAD(a0)
		add.l	#LH_SIZE,(a0)		; LH_HEAD -> 1. Node
		clr.l	LH_TAIL(a0)
		clr.l	LH_TAILPRED(a0)
		clr.w	LH_TYPE(a0)
		lea	LH_SIZE(a0),a0
		bset	#FirstEntry,Flags(a5)	; Erster Eintrag !

		lea	MenuTxt_1(pc),a1	; Namen in Liste eintragen
		bsr	AddList
		lea	MenuTxt_2(pc),a1
		bsr	AddList

		lea	ListStruktur(pc),a1	; Leeren Eintrag an Listenende
		move.l	a1,LN_SUCC(a0)		; LN_SUCC -> LH_TAIL
		addq.l	#LH_TAIL,(a0)
		move.l	a0,LH_TAILPRED(a1)	; LH_TAILPRED -> Node
		move.l	a0,LN_PRED(a0)		; LN_PRED -> LN_SUCC (!)
		sub.l	#LN_SIZE+4,4(a0)
		clr.l	LN_NAME(a0)

	; *** BIS HIERHIN DARF A0 NICHT ANDERWEITIG VERÄNDERT WERDEN !!!

;*** ListView-Gadget neu zeichnen
		move.l	LV_Gad(a5),a0		; List an ListView-
		move.l	WinHandle(a5),a1	;  Gadget übergeben
		sub.l	a2,a2
		lea	List_Gad_Tag(pc),a3
		CALL	GT_SetGadgetAttrsA

;*** BitMap-Bereich vergrößern
		move.l	ScrHandle(a5),a1	; Struktur initialisieren,
		lea	sc_BitMap(a1),a1	;  in der die Werte zur
		lea	ScaleArgs(pc),a0	;  Vergrößerung eines
		move.l	a1,bsa_SrcBitMap(a0)	;  BitPlane-Bereichen
		move.l	a1,bsa_DestBitMap(a0)	;  benötigt
		move.w	#240,bsa_SrcX(a0)	; Quell-Bereich links/oben
		move.w	#20,bsa_SrcY(a0)
		move.w	#180,bsa_SrcWidth(a0)	; Quell-Ausdehnung
		move.w	#100,bsa_SrcHeight(a0)
		move.w	#10,bsa_DestX(a0)	; Ziel-Bereich links oben
		move.w	#130,bsa_DestY(a0)
		move.w	#180,bsa_XSrcFactor(a0)	 ; Die Vergrößerung ist als
		move.w	#67,bsa_YSrcFactor(a0)	 ;  Bruch darstellbar:
		move.w	#600,bsa_XDestFactor(a0) ;  Der Zähler wird als Ziel-,
		move.w	#60,bsa_YDestFactor(a0)	 ;  der Nenner als Quell-Faktor
		move.w	#600,bsa_DestWidth(a0)	 ;  eingetragen !!!
		move.w	#89,bsa_DestHeight(a0)	 ; X: 600/180 = 3.33
		CALL	BitMapScale,_GfxBase	 ; Y: 60/67   = 0.89

;*** Eingabe aus UserMsgPort des Windows lesen
Eingabe_holen:	move.l	WinHandle(a5),a3	; UserPort-Adresse des
		move.l	wd_UserPort(a3),a3	;  Windows holen

Message_holen:	move.l	a3,a0			; Message abholen
		CALL	GT_GetIMsg,_GadBase
		tst.l	d0			; War eine da ?
		bne.s	Auswerten		; Ja -> auswerten

		moveq	#-1,d0			; Nein -> Signalbit holen
		CALL	AllocSignal,EXEC
		tst.b	d0			; War eins frei ?
		bmi.s	Message_holen		; Nein -> Message holen

		move.b	d0,MP_SIGBIT(a3)	; Bit in MessagePort schreiben
		move.l	ThisTask(a6),MP_SIGTASK(a3) ; Task-Adresse eintragen
		clr.b	MP_FLAGS(a3)		; Keine Flags
		move.l	a3,a0			; Auf Signal warten
		CALL	WaitPort
		move.b	#PA_IGNORE,MP_FLAGS(a3)	; Nicht reagieren
		move.b	MP_SIGBIT(a3),d0	; Signalbit holen,
		CALL	FreeSignal		;  freigeben,
		bra.s	Message_holen		;  und Nachricht holen

Auswerten:	move.l	d0,a1
		CALL	GT_ReplyIMsg,_GadBase	; Beantwortem

;*** Gadgets entfernen
		move.l	GetVisual(a5),a0	; Gadgets entfernen
		CALL	FreeVisualInfo,_GadBase
		move.l	GadgetList(a5),a0
		CALL	FreeGadgets

;*** Menüs entfernen
		move.l	MenuAddr(a5),a0		; Menüs freigeben
		CALL	FreeMenus,_GadBase
		move.l	WinHandle(a5),a0	; Menü entfernen
		CALL	ClearMenuStrip,_IntBase

;*** Fenster schließen
		move.l	WinHandle(a5),a0	; Fenster schließen
		CALL	CloseWindow

;*** Screen schließen
NoWin:		move.l	ScrHandle(a5),a0
		CALL	CloseScreen		; Screen schließen

;*** Libraries schließen
NoScreen:	move.l	_IntBase(a5),a1		; Libraries schließen
		CALL	CloseLibrary,EXEC
		move.l	_GadBase(a5),a1
		CALL	CloseLibrary
		move.l	_GfxBase(a5),a1
		CALL	CloseLibrary

WrongOS:	moveq	#0,d0			; ENDE
		rts

*******************************
*** Name in Liste einhängen ***
*******************************
*** a0 = Zeiger auf freien Eintrag
*** a1 = Zeiger auf String
AddList:	btst	#FirstEntry,Flags(a5)	; 1. Eintrag ?
		bne.s	1$			; Ja -> Spezialfall
		move.l	a0,LN_SUCC(a0)
		add.l	#LN_SIZE,(a0)		; LN_SUCC -> Nächste Node
		move.l	a0,LN_PRED(a0)		; LN_PRED -> LN_SUCC (!)
		sub.l	#LN_SIZE+4,LN_PRED(a0)	; Zeiger um Länge einer
		clr.w	LN_TYPE(a0)		;  Node auf den Vorgänger
		move.l	a1,LN_NAME(a0)		;  verkürzen !!!
		lea	LN_SIZE(a0),a0
		rts

1$:		bclr	#FirstEntry,Flags(a5)
		move.l	a0,LN_SUCC(a0)
		add.l	#LN_SIZE,(a0)		; LN_SUCC -> Nächste Node
		move.l	a0,LN_PRED(a0)		; LN_PRED -> LH_HEAD (!)
		sub.l	#LH_SIZE+4,LN_PRED(a0)	; Zeiger um Länge eines
		clr.w	LN_TYPE(a0)		;  List-Kopfes auf den
		move.l	a1,LN_NAME(a0)		;  Vorgänger verkürzen !!!
		lea	LN_SIZE(a0),a0
		rts

StrucPtr:	dcb.w	(Int_SIZEOF+1)/2,0

IntName:	dc.b	"intuition.library",0
GadName:	dc.b	"gadtools.library",0
GfxName:	dc.b	"graphics.library",0

ScrTitle:	dc.b	"Testfenster",0

MenuTxt_1:	dc.b	"Menü-Titel",0
MenuTxt_2:	dc.b	"Item",0
MenuTxt_3:	dc.b	"1. Sub-Item",0
MenuTxt_4:	dc.b	"2. Sub-Item",0
		even

WinTags:	dc.l	WA_CustomScreen,0
		dc.l	WA_Left,0
		dc.l	WA_Top,0
		dc.l	WA_Width,640
		dc.l	WA_Height,256
		dc.l	WA_Backdrop,TRUE
		dc.l	WA_Borderless,TRUE
		dc.l	WA_IDCMP,IDCMP_VANILLAKEY
		dc.l	TAG_DONE

ScrTags:	dc.l	SA_Title,ScrTitle
		dc.l	SA_Colors,ColorTab
		dc.l	SA_Pens,Pens_3D_Struct
		dc.l	SA_DisplayID,PAL_MONITOR_ID|HIRES_KEY
		dc.l	SA_Width,640
		dc.l	SA_Height,256
		dc.l	SA_Depth,3
		dc.l	SA_Type,CUSTOMSCREEN
		dc.l	SA_DetailPen,7
		dc.l	SA_BlockPen,3
		dc.l	TAG_DONE

Pens_3D_Struct:	dc.w	0,0,1,7,1,3,1,-1

ColorTab:	dc.w	0,10,10,10
		dc.w	1,0,0,1
		dc.w	2,15,15,15
		dc.w	3,6,8,11
		dc.w	4,15,15,15
		dc.w	5,0,0,1
		dc.w	6,0,0,0
		dc.w	7,14,14,14
		dc.w	-1

ListViewStruc:	dc.w	240,20,180,100		; x, y, Breite, Höhe
		dc.l	0,Font			; Label, TextAttr
		dc.w	10			; GadgetID
		dc.l	PLACETEXT_IN,0,0
List_Gad_Tag:	dc.l	GTLV_Labels,ListStruktur ; Tag für ListView
		dc.l	GA_Disabled,FALSE
		dc.l	GTLV_ReadOnly,FALSE
		dc.l	TAG_DONE
ListStruktur:	dcb.b	LH_SIZE+LN_SIZE*17,0	; Liste für ListView

CheckGadStruc:	dc.w	20,20,140,20		; CheckBox-Gadget
		dc.l	0,Font
		dc.w	11
		dc.l	PLACETEXT_IN,0,0
Check_Gad_Tag:	dc.l	GTCB_Checked,TRUE
		dc.l	TAG_DONE

MenuStruct:	MENU	NM_TITLE,MenuTxt_1,ITEMTEXT
		MENU	NM_ITEM,MenuTxt_2,ITEMTEXT
		MENU	NM_SUB,MenuTxt_3,CHECKED!CHECKIT!MENUTOGGLE
		MENU	NM_SUB,MenuTxt_4,CHECKED!CHECKIT!MENUTOGGLE
		MENU	NM_END,0,0
MenuTag:	dc.l	GTMN_FrontPen,2		; Tags für Menüs
		dc.l	GTMN_FullMenu,TRUE
		dc.l	TAG_DONE
LayoutTag:	dc.l	GTMN_TextAttr,Font
		dc.l	TAG_DONE

VInfo_Tag:	dc.l	TAG_DONE		; Tag für GetVisualInfoA()

Font:		dc.l	FontName		; TextAttr-Struktur
		dc.w	9,0
FontName:	dc.b	"topaz.font",0
		even

ScaleArgs:	dcb.w	12,0
		dcb.l	6,0
