;*
;
; ### Gadgets by JM v1.0 ###
;
; - Created 910906 by JM -
;
; Edited:
;
; - 910913 by JM -> v1.0	- lopullinen kommentoitu versio.
;
;

; Include-tiedostot, joissa on määritelty käyttöjärjestelmään liittyviä
; struktuureja ja vakioita.

		include "exec/types.i"
		include "exec/nodes.i"
		include "exec/lists.i"
		include "exec/memory.i"
		include	"graphics/gfx.i"
		include	"graphics/gfxbase.i"
		include	"graphics/text.i"
		include	"intuition/intuition.i"
		include	"intuition/screens.i"


; Makrot, joiden avulla käyttöjärjestelmän rutiineja on helpompi kutsua.
; Makrot määrittelevät automaattisesti kaikki kutsutut rutiinit linkkeriä
; varten ja lataavat kirjaston perusosoitteen a6:een ennen rutiinin kut-
; sumista.
; Esimerkiksi "lib intui,OpenWindow" purkautuu käskyiksi
;   xref   _LVOOpenWindow
;   move.l intuibase(a4),a6
;   jsr    _LVOOpenWindow(a6)
;
; flib vastaa lib-makroa, mutta ei lataa automaattisesti kirjaston perus-
; osoitetta a6:een.  Tästä on hyötyä kutsuttaessa useita samassa kirjas-
; tossa olevia rutiineja peräkkäin (a6:n arvo säilyy kutsujen aikana).

lib		macro			; käyttö: lib kirjasto,rutiini
		xref	_LVO\2		; määrittelee offsetin
		move.l	\1base(a4),a6	; ottaa kirjaston perusosoitteen
		jsr	_LVO\2(a6)	; kutsuu rutiinia _LVOxxx(a6)
		endm

flib		macro			; käyttö: flib kirjasto,rutiini
		xref	_LVO\2		; määrittelee offsetin
		jsr	_LVO\2(a6)	; kutsuu rutiinia _LVOxxx(a6)
		endm

exec		macro			; käyttö: exec rutiini
		xref	_LVO\1		; maarittelee offsetin
		move.l	$4,a6		; ottaa execin perusosoitteen
		jsr	_LVO\1(a6)	; kutsuu rutiinia _LVOxxx(a6)
		endm


; Ikkunan liput, jotka määräävät ikkunan ominaisuudet.  Erikoinen
; määrittelytapa johtuu siitä, että liput eivät mahdu yhdelle riville.
;
WFLAGS		set	SIMPLE_REFRESH!NOCAREREFRESH!WINDOWDEPTH
WFLAGS		set	WFLAGS!WINDOWDRAG!WINDOWSIZING!WINDOWCLOSE

; IDCMP-liput, jotka kertovat, mistä tapahtumista Intuitionin on
; lähetettävä ohjelmalle viestejä.  Tässä ohjelmassa odotetaan
; vain gadgettien vapauttamiseen ja ikkunan sulkemiseen liittyviä viestejä.
;
IDCMPFLAGS	set	CLOSEWINDOW!GADGETUP	; IDCMP

; Määritellään offsetit pinossa oleviin muuttujiin.  Muuttujatila varataan
; ohjelman alussa link-käskyllä.
;
intuibase	equ	-4	; tila Intuition-kirjaston osoittimelle
gfxbase		equ	-8	; tila Graphics-kirjaston osoittimelle
window		equ	-12	; tila Window-osoittimelle
rp		equ	-16	; tila RastPort-osoittimelle
quit		equ	-20	; lippu: pitää poistua


; Pääohjelma.  Alussa nollataan pinomuuttujat ja avataan tarvittavat
; kirjastot (Intuition ja Graphics).
;
main	link	a4,#-24			; varataan muuttujatilaa
	clr.l	intuibase(a4)		; nollataan muuttujat
	clr.l	gfxbase(a4)
	clr.l	window(a4)
	clr.w	quit(a4)		; nolla: ei poistuta

	lea	gfx(pc),a1		; grafiikkakirjaston nimi
	moveq	#0,d0			; kirjastoversio (mikä tahansa)
	exec	OpenLibrary		; kutsutaan OpenLibrary()ä
	move.l	d0,gfxbase(a4)		; talletetaan gfx:n perusosoite
	beq	cleanup			; jos kirjastoa ei ole, pois!

	lea	intui(pc),a1		; Intuition-kirjaston nimi
	moveq	#0,d0			; kirjastoversio (mikä tahansa)
	exec	OpenLibrary		; kutsutaan OpenLibrary()ä
	move.l	d0,intuibase(a4)	; talletetaan I:n perusosoite
	beq	cleanup			; jos kirjastoa ei ole, pois!

; Avataan ikkuna.  Intuition liittää gadgetit automaattisesti ikkunaan,
; koska niiden osoitin on asetettu NewWindow-struktuuriin.

	lea	Newwindow,a0		; NewWindow-struktuurin osoite
	lib	intui,OpenWindow	; kutsutaan OpenWindow()ia
	move.l	d0,window(a4)		; talletetaan Window:n osoite
	beq	cleanup			; jos ei auennut, pois!
	move.l	d0,a0
	move.l	wd_RPort(a0),rp(a4)	; otetaan RastPortin osoite
	move.l	wd_UserPort(a0),a5	; ikkunan viestiportti a5:een

;----------------------------------------------------------------------------
;
; Silmukka, jossa odotetaan IDCMP-viestejä ja käsitellään niiden komennot.
; Odottaminen tapahtuu Execin Wait-rutiinilla.
; Kun ohjelma saa CLOSEWINDOW-viestin, asetetaan lippu merkiksi siitä, että
; ohjelman pitäisi poistua.  Sitten luetaan muut mahdolliset IDCMP-viestit,
; minkä jälkeen ohjelma päättyy.
; Kun käyttäjä vapauttaa jomman kumman gadgetin, ohjelma saa GADGETUP-viestin
; ja lukee ao. gadgetin UserData-kentästä kutsuttavan aliohjelman osoitteen.

loop	tst.w	quit(a4)		; pitääkö poistua?
	bne	cleanup			; joop -> voe tokkiisa

w_idcmp	moveq	#0,d0			; bittimaski = 0
	move.b	MP_SIGBIT(a5),d1	; signaalibitin numero
	bset	d1,d0			; muunnetaan bittimaskiksi
	exec	Wait			; odotetaan IDCMP-viestiä

nextmsg	move.l	a5,a0			; viestiportti
	exec	GetMsg			; otetaan saapunut viesti
	tst.l	d0
	beq.s	loop			; häh? ei viestiä? odotetaan lisää!

	move.l	d0,a1			; saadun viestin osoite a1:een
	move.l	im_Class(a1),d2		; viestin tyyppi d2:een
	move.w	im_Code(a1),d3		; koodi (esim. näppäimen numero)
	move.l	im_IAddress(a1),a2	; gadgetin tms. osoite

	exec	ReplyMsg		; vastataan viestiin

	cmp.l	#CLOSEWINDOW,d2		; painettiinko sulkunappulaa?
	bne.s	10$			; ei -> hyppää
	move.w	#1,quit(a4)		; kyllä: asetetaan lippu
	bra.s	nextmsg			; luetaan loput viestit

10$	cmp.l	#GADGETUP,d2		; gadget-viesti?
	bne	nextmsg			; ei -> luetaan seuraava viesti
	move.l	gg_UserData(a2),a0	; kyllä: otetaan UserData-kenttä
	jsr	(a0)			; kutsutaan aliohjelmaa
	bra	nextmsg			; tarkistetaan, onko muita viestejä

; cleanup sulkee kaiken, mikä oli avoinna.  Ennen sulkemista testataan,
; että suljettava olio oli avautunut - esimerkiksi ikkunaa ei voi sulkea,
; ellei se ole auki (guru).  Jos olion osoitin on nolla, se merkitsee,
; ettei kyseinen olio ole auki.

cleanup	move.l	window(a4),d0		; onko ikkuna auki?
	beq.s	101$			; ei -> hypätään
	move.l	d0,a0
	lib	intui,CloseWindow	; suljetaan ikkuna

101$	move.l	gfxbase(a4),d0		; graphics auki?
	beq.s	201$			; ei -> loikataan
	move.l	d0,a1
	exec	CloseLibrary		; suljetaan graphics-kirjasto

201$	move.l	intuibase(a4),d0	; intuition auki?
	beq.s	202$			; ei -> harpataan
	move.l	d0,a1
	exec	CloseLibrary		; suljetaan intuition

202$	unlk	a4			; vapautetaan pinoalue
	moveq	#0,d0			; ei virhettä
	rts				; poistutaan


;----------------------------------------------------------------------------
;
; Gadget-aliohjelmat, jotka ajetaan ao. gadgetin vapauttamisen (GADGETUP-
; viestin) jälkeen.
; String-gadgetin rutiini asettaa näppäillyn merkkijonon ikkunan otsikko-
; palkkiin, boolean-gadget puolestaan tyhjentää string-gadgetin puskurimuis-
; tin nollaamalla puskurin ensimmäisen paikan.
;
StrRtn	move.l	gg_SpecialInfo(a2),a1	; StringInfo
	move.l	si_Buffer(a1),a1	; gadgetin tekstipuskuri a1:een
	move.l	window(a4),a0		; ikkuna
	moveq	#-1,d0			; -1 d0:aan
	move.l	d0,a2			; ei muuteta näytön otsikkotekstiä
	lib	intui,SetWindowTitles	; asetetaan ikkunan otsikkoteksti
	rts

BoolRtn	lea.l	StringGadget,a0		; string-gadget
	move.l	gg_SpecialInfo(a0),a1	; StringInfo
	move.l	si_Buffer(a1),a1	; gadgetin tekstipuskuri
	clr.b	(a1)			; 'tyhjennetään' puskuri
	move.l	window(a4),a1		; ikkunan osoitin
	sub.l	a2,a2			; ei requester
	moveq	#1,d0			; päivitetään vain yksi gadget
	lib	intui,RefreshGList
	rts


;----------------------------------------------------------------------------
;
gfx	dc.b	"graphics.library",0	; kirjastojen nimet
intui	dc.b	"intuition.library",0
	ds.w	0			; varmistetaan osoite parilliseksi
;----------------------------------------------------------------------------
;
; Muuttuvat struktuurit, jotka on sijoitettu erilliseen data-tyyppiseen
; lohkoon, jolloin itse ohjelman koodi pysyy muuttumattomana suositusten
; mukaisesti.

		section	struct,DATA

; Ikkunoiden avaamisessa tarvittava NewWindow-struktuuri, joka sisältää
; tiedot ikkunan koosta, paikasta, väreistä ja niin edelleen.
;
Newwindow	dc.w	10,100		; ikkunan koordinaatit (x,y)
		dc.w	300,60		; ikkunan koko (x,y)
		dc.b	0,1		; kynien värit
		dc.l	IDCMPFLAGS	; vahdi sulkunappulaa yms
		dc.l	WFLAGS		; liput
		dc.l	StringGadget	; ensimmäinen gadget
		dc.l	0		; ei omaa checkmarkkia
		dc.l	WTitle		; ikkunan otsikkopalkin teksti
		dc.l	0		; näytön osoitin, ei tarvita tässä
		dc.l	0		; ei BitMap-osoitinta
		dc.w	100,100		; ikkunan minimikoko
		dc.w	500,200		; ikkunan maksimikoko
		dc.w	WBENCHSCREEN	; näytön tyyppi = WORKBENCH


;----------------------------------------------------------------------------
;
; Gadget-struktuurit ja niihin liittyvät apustruktuurit.  Tässä esimerkissä
; struktuureihin on suoraan asetettu osoittimet muihin struktuureihin, mikä
; helpottaa ohjelmointia.  Absoluuttiset viittaukset kuitenkin pidentävät
; ohjelman ajettavaa versiota, koska jokaisesta viittauksesta syntyy myös
; tieto siitä, miten kyseinen viittaus on käsiteltävä ohjelmaa ladattaessa.
; Parempi tapa olisi varata struktuureille muistia ohjelman ajon aikana ja
; luoda kaikki tarvittavat struktuurit ohjelmallisesti ja asettaa samalla
; osoittimet toisiin struktuureihin.
:
StringGadget	dc.l	BoolGadget	; osoitin seuraavaan gadgettiin
		dc.w	10,20		; x- ja y-paikka
		dc.w	200,10		; x- ja y-koko
		dc.w	GADGHCOMP	; liput
		dc.w	RELVERIFY	; toiminto vasta vapautettaessa
		dc.w	STRGADGET	; tyyppi = string
		dc.l	StringBorder	; kehys gadgetin ympärille ->
		dc.l	0		; aktivoidessa ei uutta kuviota
		dc.l	0		; ei tekstiä
		dc.l	0		; mutual exclude, ei käytössä
		dc.l	StringSInfo	; special info -> StringInfo
		dc.w	0		; gadget ID
		dc.l	StrRtn		; userdata

StringSInfo	dc.l	buffer		; puskuri gadgetin tekstille
		dc.l	undo_buffer	; undo-puskuri
		dc.w	0		; paikka, jossa ollaan editoimassa
		dc.w	32		; maksimi merkkien määrä
		dc.w	0		; ensimmäinen näytöllä näkyvä merkki
		dc.w	0,0,0,0,0	; Intuitionin sisäisiä muuttujia
		dc.l	0		; ei käytössä 1.3:ssa
		dc.l	0		; longint (ei käytössä tässä)
		dc.l	0		; vaihtoehtoinen näppäinkartta

; struktuuri, joka määrittelee gadgetin ympärille piirrettävän kehyksen
StringBorder	dc.w	-2,-2		; suhteellinen paikka
		dc.b	1,2		; piirtovärit
		dc.b	RP_JAM1		; piirtomoodi
		dc.b	5		; koordinaattiparien määrä
		dc.l	StringVectors	; koordinaattiparitaulukko ->
		dc.l	0		; ei useampia Border-struktuureja

StringVectors	dc.w	0,0,203,0,203,11,0,11,0,0 ; viivojen koordinaattiparit


BoolGadget	dc.l	0		; ei enempää gadgetteja
		dc.w	220,19		; x- ja y-paikka
		dc.w	56,10		; x- ja y-koko
		dc.w	GADGHCOMP	; liput
		dc.w	RELVERIFY	; toiminto vasta vapautettaessa
		dc.w	BOOLGADGET	; tyyppi = boolean
		dc.l	BoolBorder	; kehys gadgetin ympärille ->
		dc.l	0		; aktivoidessa ei uutta kuviota
		dc.l	BoolText	; teksti ->
		dc.l	0		; mutual exclude, ei käytössä
		dc.l	0		; special info (ei tarpeen)
		dc.w	0		; gadget ID
		dc.l	BoolRtn		; userdata

; struktuuri, joka määrittelee gadgetin ympärille piirrettävän kehyksen
BoolBorder	dc.w	-1,-1		; suhteellinen paikka
		dc.b	1,2		; piirtovärit
		dc.b	RP_JAM1		; piirtomoodi
		dc.b	5		; koordinaattiparien määrä
		dc.l	BoolVectors	; koordinaattiparit ->
		dc.l	0		; ei useampia Border-struktuureja

BoolVectors	dc.w	0,0,57,0,57,11,0,11,0,0 ; viivojen koordinaattiparit

; IntuiText-struktuuri boolean-gadgetin tekstiä varten
BoolText	dc.b	1,2		; piirtovärit
		dc.b	RP_JAM1		; piirtomoodi
		dc.b	0		; (ei käytössä)
		dc.w	8,1		; suhteellinen paikka
		dc.l	0		; fontti = oletusfontti
		dc.l	Bool_Text	; teksti
		dc.l	0		; ei lisätekstiä

;----------------------------------------------------------------------------
;
; Tarvittavaa fontia ei ole asetettu, vaan ohjelma käyttää systeemin oletus-
; fonttia.  Gadgettien koot on laskettu 8 pisteen fontille ja esimerkiksi
; Kickstart 2.0:n alla käytettävät suuremmat fontit tai tavallinen Topaz 9
; sotkevat ohjelman ulkonäön.  Kickstart 1.3:ssa ei kuitenkaan ole mahdol-
; lista asettaa fonttia string-gadgettiin muutoin kuin avaamalla oman näytön
; (screen) ja asettamalla siihen haluamansa fontin.  Gadgetit käyttävät aina
; näytön oletusfonttia.
;
;----------------------------------------------------------------------------
;
; Tekstit:
;
WTitle		dc.b	"SimpleRefresh-ikkuna",0
Bool_Text	dc.b	"PAINA",0
		ds.w	0

;----------------------------------------------------------------------------
;
; String-gadgetin puskurit on sijoitettu omaan BSS-hunkkiinsa, jolloin ne
; eivät vie tilaa ohjelman käännetystä versiosta, mutta niille varataan
; automaattisesti tilaa ohjelmaa ladattaessa.  Haittapuolena on, että
; puskureihin ei voi viitata lyhyemmällä ja nopeammalla suhteellisella
; osoituksella, vaan on aina käytettävä absoluuttista osoitusmuotoa (koska
; BSS-hunkki voi sijoittua muistissa minne tahansa, ei kiinteään paikkaan
; muuhun ohjelmaan nähden).  Toinen haitta on, ettei ohjelmaa voi ladata
; residentiksi, koska kaikki samaan aikaan ajettavat ohjelmakopiot käyttäi-
; sivät samaa puskuria.  Toisaalta puskureissa olisi uusilla ajokerroilla
; entistä tietoa nollatavujen sijasta, koska BSS-hunkki nollataan vain
; kerran ohjelmaa ladattaessa.  Menetelmän etuna taas on, ettei muistia
; tarvitse erikseen varata.

		section	puskurit,bss

buffer		ds.b	34
undo_buffer	ds.b	34

		end

