Obligement - L'Amiga au maximum

Vendredi 06 juin 2025 - 12:57  

Translate

En De Nl Nl
Es Pt It Nl


Rubriques

Actualité (récente)
Actualité (archive)
Comparatifs
Dossiers
Entrevues
Matériel (tests)
Matériel (bidouilles)
Points de vue
En pratique
Programmation
Reportages
Quizz
Tests de jeux
Tests de logiciels
Tests de compilations
Trucs et astuces
Articles divers

Articles in English


Réseaux sociaux

Suivez-nous sur X




Liste des jeux Amiga

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z,
ALL


Trucs et astuces

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Glossaire

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Galeries

Menu des galeries

BD d'Amiga Spécial
Caricatures Dudai
Caricatures Jet d'ail
Diagrammes de Jay Miner
Images insolites
Fin de jeux (de A à E)
Fin de Jeux (de F à O)
Fin de jeux (de P à Z)
Galerie de Mike Dafunk
Logos d'Obligement
Pubs pour matériels
Systèmes d'exploitation
Trombinoscope Alchimie 7
Vidéos


Téléchargement

Documents
Jeux
Logiciels
Magazines
Divers


Liens

Associations
Jeux
Logiciels
Matériel
Magazines et médias
Pages personnelles
Réparateurs
Revendeurs
Scène démo
Sites de téléchargement
Divers


Partenaires

Annuaire Amiga

Amedia Computer

Relec


A Propos

A propos d'Obligement

A Propos


Contact

David Brunet

Courriel

 


Programmation : Assembleur - PublicMenus (première partie)
(Article écrit par Max et extrait d'Amiga News Tech - juin 1992)


Ha ha ! Après trois longs mois de dur labeur, l'Utilitaire du mois revient dans l'ANT. Mesdames, mesdemoiselles, messieurs et les autres, je suis fier de vous présenter (roulements de tambour)... PublicMenus version 1.0.

De quoi est-ce que s'agit-il donc au juste ? Disons pour simplifier et pour entretenir le suspens, que les PublicMenus sont aux menus ce que les PublicScreens du système 2.0 sont aux écrans... Plus précisément, il s'agit d'un menu déroulant dans le plus pur style "pop-up" que plusieurs applications, totalement indépendantes les unes des autres, peuvent se partager à loisir. Ce menu n'est de plus pas attaché à une fenêtre particulière, comme le sont ceux d'Intuition, mais est toujours déroulé dans l'écran le plus "en avant".

Menus partagés

Pour être partagé, le menu se doit d'être partageable (cet article a été écrit en étroite collaboration avec M. de la Palisse). Et qu'est-ce qui est le plus partageable sur Amiga, sinon les bibliothèques de fonctions (libraries) ? En conséquence, notre utilitaire du mois est une bibliothèque (publicmenus.library pour ne pas la nommer), donc qu'il faudra ouvrir, utiliser à loisir puis bien sûr refermer. Il s'agit donc d'un utilitaire destiné plus spécialement (on peut même dire : exclusivement) aux programmeurs et qui ne pourra pas être utilisé tel quel par le commun des mortels.

Mais, me direz-vous (car je vous connais) : quel est donc l'intérêt d'une telle bibliothèque ? A ceci je répondrai que chacun y trouvera l'intérêt qu'il souhaite. Par exemple, moi, je me suis concocté quelques petits programmes tournant en tâche de fond (c'est-à-dire sans ouvrir d'écran ni de fenêtre) qui utilisent le menu publique pour donner accès à quelques options de configuration : une alarme, un économiseur d'écran, une version améliorée du ScreenSaver et du ScreenRoller (voir cet article), un exécuteur de programmes à la MyMenu... D'autres pourraient l'utiliser dans le cas de programmes s'iconifiant eux-mêmes (par exemple PowerPacker, via l'option "Sleep") pour permettre un réveil sur commande sans encombrer l'écran du Workbench d'une inutile fenêtre... Bref, c'est à chacun de voir.

Distribution

Avant d'aller plus loin, il me faut préciser qu'une version 1.1 de la bibliothèque a été envoyée à Fred Fish dans le fol espoir de la voir un jour diffusée sur l'une des disquettes de la célèbre collection. Cette distribution contient non seulement l'exécutable mais aussi une volumineuse documentation (en anglais et en français), les fichiers Include C et assembleur indispensables à tout programmeur désirant l'utiliser, ainsi que plusieurs exemples d'utilisation, également en C et en assembleur (bien sûr, les abonnés avec disquette y auront aussi droit). Seuls les fichiers sources ne sont pas fournis, afin d'éviter que trop de versions différentes ne circulent. Je vous recommande donc vivement de surveiller le catalogue Fish et de vous procurer la version 1.1 dès qu'elle sera disponible (NDLR : la version 1.1 est également disponible sur la disquette ANT 34).

Comment ça marche ?

Une fois la bibliothèque installée et au moins un menu publique déclaré, rien ne se passe... En fait, la bibliothèque attend que l'utilisateur appuie sur le bouton droit de la souris en conjonction avec la touche Amiga gauche. A ce moment-là, le menu est affiché et tout se passe exactement de la même manière qu'avec Intuition. Les items peuvent être des textes ou des images et tous les modes de sélection standards d'Intuition (HIGHNONE, HIGHCOMP, HIGHBOX et HIGHIMAGE) sont gérés. Un menu peut être désactivé soit totalement, soit partiellement, puis réactivé. Enfin, même les raccourcis clavier sont gérés avec la touche Amiga gauche). Je vous l'ai dit, c'est tout comme Intuition, mais sans Intuition.

Qui fait quoi ?

Chaque application désirant utiliser le menu public devra au préalable ouvrir la bibliothèque, en utilisant tout à fait normalement la fonction OpenLibrary() d'Exec. Lors de la première ouverture, une tâche est créée, destinée à gérer à la fois l'affichage du menu et les mouvements et clics de la souris. Cette tâche installe un Input-Handler d'une priorité supérieure à celle d'Intuition, afin que celle-ci ne s'aperçoive de rien. Évidemment, lorsqu'Exec décide qu'il est temps de retirer la bibliothèque du système, l'Input-Handler et la tâche sont tous deux supprimés.

On peut donc résumer la situation ainsi : c'est une tâche (au sens Exec du terme) qui est le coeur du système, la bibliothèque ne faisant qu'office de lien entre les applications l'utilisant et la tâche.

Les fonctions

Comme toute bibliothèque digne de ce nom, la publicmenus.library offre quelques fonctions qu'il convient de connaître. Les premières seront vues rapidement, car elles ont leur équivalent soit dans la bibliothèque C standard, soit dans amiga.lib ou Exec 2.0 (le mystère disparaîtra totalement quand je vous aurai dit qu'elles ont été judicieusement baptisées StringLen(), NewMsgPort(), FreeMsgPort(), NewIORequest() et FreeIORequest(), afin que le nom ne rentre pas en conflit avec CreateMsgPort() et compagnie). Ces fonctions ont été incluses en pensant aux programmeurs en assembleur utilisateurs de la version 1.3 d'AmigaDOS (et de toute façon, j'en avais besoin).

Suivent AddPMenu(), RemPMenu(), OffPMenu(), OnPMenu() et PItemAddress(). Les deux premières permettent respectivement d'ajouter et d'enlever un menu public et les trois suivantes agissent comme leur équivalent Intuitionnesque. Reportez-vous à la description ci-jointe pour plus de détails sur leur fonctionnement et leurs paramètres respectifs.

Assemblage

La bibliothèque entière a été écrite en assembleur avec le Devpac 2 (puis le Devpac 3, mais aucune de ses particularités n'a été utilisée). Utilisez le petit script listé ci-dessous pour assembler les deux fichiers sources et relier les deux fichiers objets en un seul exécutable nommé libs:publicmenus.library.

Notez qu'il y a de quoi taper : entre la bibliothèque elle-même, les includes (C et assembleur) et le fichier FD (Cf. LibTool), nous n'aurons pas trop de deux mois pour achever complètement notre oeuvre.

Assembleur
Assembleur
Assembleur
Assembleur

Listing 1 : include:libraries/publicmenus.h

#ifndef	LIBRARIES_PUBLICMENUS_H
#define	LIBRARIES_PUBLICMENUS_H
/*
**	PublicMenus v1.1 - © 1992, RingarSoft
**
**	publicmenus.h -structures et constantes
**
*/

#ifndef	EXEC_PORTS_H
#include "exec/ports.h"
#endif	/* EXEC_PORTS_H */

#ifndef	INTUITION_INTUITION_H
#include "intuition/intuition.h"
#endif	/* INTUITION_INTUITION_H */

/****** PublicMenu ******/
struct PublicMenu {
	struct	Menu IntuiMenu;		/* Menu  Intuition standard */
	struct	MsgPort *OwnerPort;	/* Votre MessagePort        */
};

#define PublicItem MenuItem
#define PublicSubItem MenuItem

/****** Quelques re-définitions *************************************/
#define	PMENUENABLED	MENUENABLED
#define	PITEMENABLED	ITEMENABLED
#define	PITEMTEXT	ITEMTEXT
#define	PMENUTOGGLE	MENUTOGGLE

/****** PublicMessage ***********************************************/
struct PublicMessage {
	struct	Message ExecMessage;	/* Message Exec standard    */
	UWORD	MenuPick;		/* Valeur du MenuPick       */
	UWORD	Qualifiers;		/* Qualificateurs           */
	ULONG	Seconds, Micros;	/* Heure Système            */
};

/****** Divers ******************************************************/
#define	NOPMENU	0x001F
#define	NOPITEM	0x003F
#define	NOPSUB	0x001F
#define	PMENUNULL 0xFFFF

#define	PMENUNUM(n) (n & 0x1F)
#define	PITEMNUM(n) ((n >> 5) & 0x003F)
#define	PSUBNUM(n) ((n >> 11) & 0x001F)

#define	SHIFTPMENU(n) (n & 0x1F)
#define	SHIFTPITEM(n) ((n & 0x3F) << 5)
#define	SHIFTPSUB(n) ((n & 0x1F) << 11)

#define	MAKEPNUM(i,s)	(SHIFTPSUB(s)|SHIFTPITEM(i)|NOPMENU)

#define	PCHECKWIDTH	CHECKWIDTH
#define	PCOMMWIDTH	COMMWIDTH
#define	LOWPCHECKWIDTH	LOWCHECKWIDTH
#define	LOWPCOMMWIDTH	LOWCOMMWIDTH

/****** Nom de la Librairie *****************************************/
#define	PUBLICMENUSNAME	"publicmenus.library"

#endif	/* LIBRARIES_PUBLICMENUS_H */

Listing 2 : include:libraries/publicmenusbase.h

#ifndef	LIBRARIES_PUBLICMENUSBASE_H
#define	LIBRARIES_PUBLICMENUSBASE_H
/*
**	PublicMenus v1.1 - © 1992, RingarSoft
**
**	publicmenusbase.h - structure de base
**
*/

#ifndef	EXEC_TYPES_H
#include "exec/types.h"
#endif	/* EXEC_TYPES_H */

#ifndef	EXEC_LIBRARIES_H
#include "exec/libraries.h"
#endif	/* EXEC_LIBRARIES_H */

#ifndef	EXEC_SEMAPHORES_H
#include "exec/semaphores.h"
#endif	/* EXEC_SEMAPHORES_H */

/****** Library base structure ***************************************/
struct PublicMenusBase {
	struct	Library pmb_Lib;	/* Librarie standard         */
	UBYTE	pmb_Flags, pmb_Pad;
	ULONG	pmb_SegList;

	struct	PublicMenu *pmb_PMenuStrip;  /* Le PublicMenuStrip   */
	UWORD	pmb_PMenuCount;	      /* Nombre de PMenus            */
	struct	SignalSemaphore pmb_Semaphore;	/* Pour accès unique */
	struct	Task *pmb_PMenusTask;		/* PMenus.task       */
};

#endif	/* PMENUSBASE_H */

Listing 3 : include:proto/publicmenus.h

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

extern struct PublicMenusBase *PMenusBase;
SHORT StringLen(char *);
struct MsgPort *NewMsgPort(char *, LONG);
void FreeMsgPort(struct MsgPort *);
struct IORequest *NewIORequest(struct MsgPort *, LONG);
void FreeIORequest(struct IORequest *);
void LockPMenus(void);
void UnlockPMenus(void);
BOOL AddPMenu(struct PublicMenu *);
void RemPMenu(struct PublicMenu *);
void OffPMenu(struct PublicMenu *, USHORT);
void OnPMenu(struct PublicMenu *, USHORT);
struct PublicItem *PItemAddress(struct PublicMenu *, USHORT);

#ifndef NO_PRAGMAS
/* pragmas pour le SAS/C 5.10. Désolé, je ne connais pas le Manx ! ------*/
#pragma libcall PMenusBase StringLen 1E 801
#pragma libcall PMenusBase NewMsgPort 2A 802
#pragma libcall PMenusBase FreeMsgPort 30 801
#pragma libcall PMenusBase NewIORequest 36 802
#pragma libcall PMenusBase FreeIORequest 3C 901
#pragma libcall PMenusBase LockPMenus 42 0
#pragma libcall PMenusBase UnlockPMenus 48 0
#pragma libcall PMenusBase AddPMenu 4E 801
#pragma libcall PMenusBase RemPMenu 54 801
#pragma libcall PMenusBase OffPMenu 5A 802
#pragma libcall PMenusBase OnPMenu 60 802
#pragma libcall PMenusBase PItemAddress 66 802
#endif

Listing 4 : include:libraries/publicmenus.i

	IFND	LIBRARIES_PUBLICMENUS_I
LIBRARIES_PUBLICMENUS_I	SET	1
**
**	PublicMenus v1.1 - © 1992, RingarSoft
**
**	publicmenus.i - structures et constantes
**
**

	IFND	EXEC_PORTS_I
	INCLUDE	"exec/ports.i"
	ENDC	; EXEC_PORTS_I

	IFND	INTUITION_INTUITION_I
	INCLUDE	"intuition/intuition.i"
	ENDC	; INTUITION_INTUITION_I

******* PublicMenu ***************************************************
	STRUCTURE PublicMenu,0
 		STRUCT	pmu_IntuiMenu,mu_SIZEOF	; Menu Intuition standard
 		APTR	pmu_OwnerPort		; Votre MessagePort
 		LABEL	pmu_SIZEOF

******* PublicItem ***************************************************
	STRUCTURE PublicItem,mi_SIZEOF		; Identique à MenuItem
		LABEL	pmi_SIZEOF

******* The PublicSubItem structure **********************************
	STRUCTURE PublicSubItem,mi_SIZEOF	; Itendique à MenuItem
		LABEL	pms_SIZEOF

******* Quelques re-définitions **************************************
PMENUENABLED	EQU	MENUENABLED
PITEMENABLED	EQU	ITEMENABLED
PITEMTEXT	EQU	ITEMTEXT
PMENUTOGGLE	EQU	MENUTOGGLE

******* PublicMessage ************************************************
	STRUCTURE PublicMessage,0
 		STRUCT	pmn_ExecMessage,MN_SIZE	; Message Exec standard
 		UWORD	pmn_MenuPick		; Valeur du MenuPick
 		UWORD	pmn_Qualifiers		; Qualificateurs
 		ULONG	pmn_Seconds		; Heure Système
 		ULONG	pmn_Micros		;    ''   ''
 		LABEL	pmn_SIZEOF

******* Divers *******************************************************
;#define PMENUNUM(n) (n & 0x1F)
;#define PITEMNUM(n) ((n >> 5) & 0x003F)
;#define PSUBNUM(n) ((n >> 11) & 0x001F)
;
;#define SHIFTPMENU(n) (n & 0x1F)
;#define SHIFTPITEM(n) ((n & 0x3F) << 5)
;#define SHIFTPSUB(n) ((n & 0x1F) << 11)

NOPMENU	EQU	$001F
NOPITEM	EQU	$003F
NOPSUB	EQU	$001F
PMENUNULL EQU	$FFFF

PCHECKWIDTH	EQU	CHECKWIDTH
PCOMMWIDTH	EQU	COMMWIDTH
LOWPCHECKWIDTH	EQU	LOWCHECKWIDTH
LOWPCOMMWIDTH	EQU	LOWCOMMWIDTH

******* Nom de la librairie ******************************************
PUBLICMENUSNAME	MACRO
		dc.b	"publicmenus.library",0
		ds.w	0
		ENDM

	ENDC	; LIBRARIES_PUBLICMENUS_I

Listing 5 : include:libraries/publicmenusbase.i

	IFND	LIBRARIES_PUBLICMENUSBASE_I
LIBRARIES_PUBLICMENUSBASE_I	SET	1
**
**	PublicMenus v1.1 - © 1992, RingarSoft
**
**	publicmenusbase.i - structure de base
**
**

	IFND	EXEC_TYPES_I
	INCLUDE	"exec/types.i"
	ENDC	; EXEC_TYPES_I

	IFND	EXEC_LIBRARIES_I
	INCLUDE	"exec/libraries.i"
	ENDC	; EXEC_LIBRARIES_I

	IFND	EXEC_SEMAPHORES_I
	INCLUDE	"exec/semaphores.i"
	ENDC	; EXEC_SEMAPHORES_I

******* Library base structure ***************************************
    STRUCTURE	PublicMenusBase,0
    	STRUCT	pmb_Lib,LIB_SIZE	; Librairie standard
	UBYTE	pmb_Flags
	UBYTE	pmb_Pad
	ULONG	pmb_SegList

	APTR	pmb_PMenuStrip		; Le PublicMenuStrip
	UWORD	pmb_PMenuCount		; Nombre de PMenus
	STRUCT	pmb_Semaphore,SS_SIZE	; Pour accès unique
	APTR	pmb_PMenusTask		; PMenus.task

	LABEL	PublicMenusBase_SIZEOF

	ENDC	; LIBRARIES_PUBLICMENUSBASE_I

Listing 6 : include:libraries/publicmenus_lib.i

_LVOStringLen	EQU	-30
;_LVOReserved	EQU	-36
_LVONewMsgPort	EQU	-42
_LVOFreeMsgPort	EQU	-48
_LVONewIORequest	EQU	-54
_LVOFreeIORequest	EQU	-60
_LVOLockPMenus	EQU	-66
_LVOUnlockPMenus	EQU	-72
_LVOAddPMenu	EQU	-78
_LVORemPMenu	EQU	-84
_LVOOffPMenu	EQU	-90
_LVOOnPMenu	EQU	-96
_LVOPItemAddress	EQU	-102

Listing 7 : PTask.i

;
; PTask.i - Définition des variables de la tâche principale
;
	IFND	INTUITION_INTUITION_I
	INCLUDE	"intuition/intuition.i"
	ENDC
	IFND	GRAPHICS_RASTPORT_I
	INCLUDE	"graphics/rastport.i"
	ENDC
	IFND	EXEC_INTERRUPTS_I
	INCLUDE	"exec/interrupts.i"
	ENDC
	IFND	LIBRARIES_DOS_I
	INCLUDE	"libraries/dos.i"
	ENDC

		; Utilisation particulière du Menu
pmu_MenuPick	EQU	mu_JazzX	; Valeur MenuPick
pmu_LastSelNum	EQU	mu_JazzY	; Dernière sélection (numéro)
pmu_LastSelect	EQU	mu_BeatX	; Dernière sélection (adresse)

		; Description d'un signal
		rsreset
SignalData	rs.b	0
sgd_SigBit	rs.l	1		; N° du bit de signal
sgd_SigMask	rs.l	1		; Masque du signal
sgd_SIZEOF	rs.w	0

		; Structure d'une "boîte" (dessin des menus)
		rsreset
Box		rs.b	0
bx_LeftEdge	rs.w	1		; Coordonnée X1
bx_TopEdge	rs.w	1		; Coordonnée Y1
bx_Width	rs.w	1		; Largeur
bx_Height	rs.w	1		; Hauteur
bx_RightEdge	rs.w	1		; Coordonnée X2
bx_BottomEdge	rs.w	1		; Coordonnée Y2
bx_LeftOffset	rs.w	1		; Décalage X
bx_TopOffset	rs.w	1		; Décalage Y
bx_ItemList	rs.l	1		; Premier Item
bx_BitMap	rs.b	bm_SIZEOF	; BitMap
bx_Flags	rs.w	1		; Flags (cf. ci-dessous)
bx_SIZEOF	rs.w	0

		; Flags (numéros de bits)
BX_PARENT_OFF	EQU	0	; Item ou Menu père désactivé
BX_DRAWN	EQU	1	; Boîte dessinée (rasters alloués)

		; Les variables proprement dites
		rsreset
PmuBase		rs.l	1	; Base de la library
pMainTask	rs.l	1	; Adresse de la tâche (pour le Handler)
IntBase		rs.l	1	; IntuitionBase
GfxBase		rs.l	1	; GfxBase
LayBase		rs.l	1	; LayersBase
pMainPort	rs.l	1	; MsgPort pour les envoyer les messages
pMainSignal	rs.l	1	; Signal pour le port (masque)
pInputPort	rs.l	1	; MsgPort pour l'input.device
pInputIO	rs.l	1	; IORequest pour l'input.device
pConsoleIO	rs.l	1	; IORequest pour le console.device
ConBase		rs.l	1	; ConsoleBase
pHostScreen	rs.l	1	; Screen utilisé pour dessiner les menus
pHostFont	rs.l	1	; Fonte utilisée
pAKeyImage	rs.l	1	; Image du CheckMark
pCheckImage	rs.l	1	; Image de la Command Key (Amiga gauche)
pQualifiers	rs.w	1	; Qualificateurs (mis par le Handler)
pCode		rs.w	1	; MenuPick (mis par le Handler)
pExit1		rs.b	1	; Flag de fin (boucle principale)
pExit2		rs.b	1	; Flag de fin (boucle Menus)
pMenues		rs.b	1	; TRUE si les menus sont dessinés
pPAD		rs.b	1
pMenuNum	rs.w	1	; Menu courant (numéro)
pCurrentMenu	rs.l	1	; Menu courant (adresse)
pCurrentItem	rs.l	1	; Item courant
pCurrentSub	rs.l	1	; Sub  courant
pTempItem	rs.l	1	; Stockage temporaire

pSIGNALS	rs.b	0
pMoveSignal	rs.b	sgd_SIZEOF	; Signal pour la souris
pLDownSignal	rs.b	sgd_SIZEOF	; Signal bouton gauche appuyé
pLUpSignal	rs.b	sgd_SIZEOF	; Signal bouton gauche relâché
pRDownSignal	rs.b	sgd_SIZEOF	; Signal bouton droit appuyé
pRUpSignal	rs.b	sgd_SIZEOF	; Signal bouton droit relâché
pKeySignal	rs.b	sgd_SIZEOF	; Signal touche COMMSEQ appuyée
PMB_NB_SIGNALS	EQU	6
pSigMasks	rs.l	1		; Masque de tous les signaux

pRastPort	rs.b	rp_SIZEOF	; RastPort pour le dessin
pMenuBox	rs.b	bx_SIZEOF	; Boîte des Menus
pItemBox	rs.b	bx_SIZEOF	; Boîte des Items
pSubBox		rs.b	bx_SIZEOF	; Boîte des SubItems

pInterrupt	rs.b	IS_SIZE		; Pour l'input.device
pConsoleBuff	rs.l	1		; Pour le console.device
VARSIZE		rs.w	0		; Taille des variables

; ************************************
		; Constantes
HANDLER_PRI	EQU	65

BORDER		EQU	2
OVERLAP		EQU	2

AKEYWIDTH_H	EQU	27
AKEYWIDTH_L	EQU	16

CHECKWIDTH_H	EQU	19
CHECKWIDTH_L	EQU	13

INIT_OK		EQU	SIGBREAKF_CTRL_C
INIT_FAILED	EQU	SIGBREAKF_CTRL_D
QUIT_SIGNAL	EQU	SIGBREAKF_CTRL_E|SIGBREAKF_CTRL_F

; ************************************
CALLSYS	MACRO
	jsr	_LVO\1(a6)
	ENDM

EXEC	MACRO
	movea.l	$4.w,a6
	CALLSYS	\1
	ENDM

INT	MACRO
	movea.l	IntBase(a5),a6
	CALLSYS	\1
	ENDM

GRAF	MACRO
	movea.l	GfxBase(a5),a6
	CALLSYS	\1
	ENDM

LAY	MACRO
	movea.l	LayBase(a5),a6
	CALLSYS	\1
	ENDM

PMENUS	MACRO
	movea.l	PmuBase(a5),a6
	jsr	_LVO\1(a6)
	ENDM

DEFSTR	MACRO
	dc.b	\1,0
	even
	ENDM

Listing 8 : PLib.s

;
; PublicMenus - © 1992, RingarSoft pour ANT
;
; PLib.s - Fonctions de la Library
; Assemblé avecDevpac Amiga 3.02
;
	OPT	o+,ow+,ow2-
	OPT	l+

	INCDIR	"Include:"	; A changer au besoin
	INCLUDE	"exec/types.i"
	INCLUDE	"exec/libraries.i"
	INCLUDE	"exec/initializers.i"
	INCLUDE	"exec/resident.i"
	INCLUDE	"exec/ports.i"
	INCLUDE	"exec/memory.i"
	INCLUDE	"exec/execbase.i"

	INCLUDE	"libraries/publicmenus.i"
	INCLUDE	"libraries/publicmenusbase.i"
	INCLUDE	"libraries/publicmenus_lib.i"

	INCLUDE	"PTask.i"

VERSION		EQU	1		; Version de la library
REVISION	EQU	1		; Numéro de révision

STACKSIZE	EQU	4000		; Pile de la tâche
TASKPRI		EQU	3		; Priorité de la tâche

	; Labels à exporter
	XDEF	StringLen,NewMsgPort,FreeMsgPort
	XDEF	NewIORequest,FreeIORequest

	; Lables à importer
	XREF	MainTask,InitTask,EndTask

; ************************************
RunLib	moveq	#0,d0
	rts

; ************************************
RomTag	dc.w	RTC_MATCHWORD		; RT_MATCHWORD
	dc.l	RomTag			; RT_MATCHTAG
	dc.l	EndTag			; RT_ENDSKIP
	dc.b	RTF_AUTOINIT		; RT_FLAGS
	dc.b	VERSION			; RT_VERSION
	dc.b	NT_LIBRARY		; RT_TYPE
	dc.b	0			; RT_PRI
	dc.l	PMenusName		; RT_NAME
	dc.l	PMenusID		; RT_IDSTRING
	dc.l	Init			; RT_INIT
EndTag	EQU	*

; ************************************
Init	dc.l	PublicMenusBase_SIZEOF	; Taille de LibBase
	dc.l	FuncTable		; Init. fonctions
	dc.l	DataTable		; Init. données
	dc.l	InitRoutine		; Init. routine

FuncTable:
	dc.l	Open,Close		; Fonctions système
	dc.l	Expunge,Reserved

	dc.l	StringLen,Reserved	; Fonctions spécifiques
	dc.l	NewMsgPort,FreeMsgPort,NewIORequest,FreeIORequest
	dc.l	LockPMenus,UnlockPMenus
	dc.l	AddPMenu,RemPMenu,OffPMenu,OnPMenu
	dc.l	PItemAddress
	dc.l	-1			; Fin de la table

DataTable:
	INITBYTE LN_TYPE,NT_LIBRARY
	INITLONG LN_NAME,PMenusName
	INITBYTE LIB_FLAGS,LIBF_SUMUSED!LIBF_CHANGED
	INITWORD LIB_VERSION,VERSION
	INITWORD LIB_REVISION,REVISION
	INITLONG LIB_IDSTRING,PMenusID
	dc.l	0

; ************************************
; Cette routine est appelée après que la library ait été
; chargée. La base est dans D0, la liste des segments dans A0.
; Si elle retourne NULL, OpenLibrary() échouera.
InitRoutine:
	movem.l	d2-d3/a2-a5,-(sp)
	movea.l	d0,a5
	move.l	a0,pmb_SegList(a5)

	clr.l	pmb_PMenuStrip(a5)	; Initialise les variables
	clr.w	pmb_PMenuCount(a5)	; importantes...
	lea	pmb_Semaphore(a5),a0
	CALLSYS	InitSemaphore

	lea	TaskMemList(pc),a0	; Alloue d'un coup toute la
	CALLSYS	AllocEntry		; mémoire nécessaire à la
	bclr	#31,d0			; tâche (variables, pile...)
	bne.s	.InitFailed

	movea.l	d0,a2				 ; a2 = MemList
	movea.l	ML_ME+(ME_SIZE*0)+ME_ADDR(a2),a4 ; a4 = Task
	movea.l	ML_ME+(ME_SIZE*1)+ME_ADDR(a2),a3 ; a3 = VARS
	movea.l	ML_ME+(ME_SIZE*2)+ME_ADDR(a2),a1 ; a1 = Stack
	move.l	a4,pmb_PMenusTask(a5)

	move.l	a5,PmuBase(a3)		; La tâche en aura besoin...
	move.l	a4,pMainTask(a3)

	move.b	#NT_TASK,LN_TYPE(a4)	; Initialise la structure Task
	move.b	#TASKPRI,LN_PRI(a4)
	move.l	#TaskName,LN_NAME(a4)

	move.l	a1,TC_SPLOWER(a4)
	lea	STACKSIZE(a1),a1
	move.l	a1,TC_SPUPPER(a4)

	; Astuce : l'adresse des variables est poussée sur la pile
	; de la tâche ; elle n'aura qu'à se servir !
	move.l	ThisTask(a6),-(a1)
	move.l	a3,-(a1)
	move.l	a1,TC_SPREG(a4)

	; Autre astuce : on ajoute la MemList allouée ci-dessus au
	; champ TC_MEMENTRY de la structure Task. Ainsi, la mémoire
	; sera automatiquement libérée par Exec lorsque la tâche
	; se terminera.
	lea	TC_MEMENTRY(a4),a0
	NEWLIST	a0
	movea.l	a2,a1
	CALLSYS	AddHead

	movea.l	a4,a1			; Ajoute la tâche...
	lea	StartTask(pc),a2	; (InitPC)
	suba.l	a3,a3			; (FinalPC)
	CALLSYS	AddTask

	; Attend que la tâche ait fini son initialisation
	move.l	#INIT_FAILED,d3
	move.l	#INIT_OK,d0
	or.l	d3,d0
	CALLSYS	Wait

	and.l	d3,d0			; Si l'initiation a échoué,
	bne.s	.InitFailed		; retourne NULL (la tâche
	move.l	a5,d0			; se terminera d'elle-même)
	bra.s	.InitOk
.InitFailed:
	moveq	#0,d0
.InitOk	movem.l	(sp)+,d2-d3/a2-a5
	rts

TaskMemList:
	dcb.b	LN_SIZE
	dc.w	3				; Nombre d'entrées
	dc.l	MEMF_CLEAR|MEMF_PUBLIC,TC_SIZE	; Structure Task
	dc.l	MEMF_CLEAR,VARSIZE		; Variables
	dc.l	MEMF_CLEAR,STACKSIZE		; Pile

; ************************************
; La nouvelle Tâche commence réellement ici...
StartTask:
	movea.l	4(sp),a5	; Récupère l'adresse des variables
	movea.l	8(sp),a4	; Tâche qui a appelé OpenLibrary()

	bsr	InitTask	; Initialisation (cf. PTask.s)
	beq.s	.TaskFailed	; Manqué !

	move.l	#INIT_OK,d0	; Tout va bien !
	movea.l	a4,a1
	EXEC	Signal		; On le signale à la Library
	bsr	MainTask	; Et on saute à la bloucle principale
	bsr	EndTask
	bra.s	.Ret

.TaskFailed:
	move.l	#INIT_FAILED,d0
	movea.l	a4,a1
	EXEC	Signal
.Ret	suba.l	a1,a1		; Suicide !!
	EXEC	RemTask
	rts

; ************************************
PMenusName	PUBLICMENUSNAME
PMenusID	dc.b	"PublicMenus ",VERSION+48,".",REVISION+48
		dc.b	" (24 April 1992)",13,10,0
		even
TaskName	DEFSTR	<"PMenus.task">

; ************************************
Open	addq.w	#1,LIB_OPENCNT(a6)
	bclr	#LIBB_DELEXP,pmb_Flags(a6)
	move.l	a6,d0
	rts

; ************************************
Close	moveq	#0,d0
	subq.w	#1,LIB_OPENCNT(a6)
	bne.s	.1
	btst	#LIBB_DELEXP,pmb_Flags(a6)
	bne.s	Expunge
.1	rts

; ************************************
; La fonction Expunge() retire la library de la liste des
; library, libère toute la mémoire allouée et ferme tout
; ce qui a pu être ouvert.
; Expunge() peut être appelée à deux occasions : lors d'une
; allocation mémoire (si Exec en manque) ou par Close() ci-dessus
; lorsque le dernier utilisateur a refermé la library.
; Elle doit retourner la liste des segments (transmise à InitRoutine)
; pour que le DOS l'UnloadSeg() ou NULL sinon.
Expunge	movem.l	d2/a5/a6,-(sp)

	movea.l	a6,a5
	movea.l	$4.w,a6

	tst.w	LIB_OPENCNT(a5)		; Library encore utilisée ?
	beq.s	.1
	bset	#LIBB_DELEXP,pmb_Flags(a6)
	moveq	#0,d0
	bra.s	.Ret
.1	move.l	pmb_SegList(a5),d2	; Prépare la seglist...

	movea.l	a5,a1			; Retire la library de la
	CALLSYS	Remove			; liste ExecBase->LibList

	movea.l	pmb_PMenusTask(a5),a1	; Prévient la tâche principale
	move.l	#QUIT_SIGNAL,d0		; qu'il est temps de mourir...
	CALLSYS	Signal

	moveq	#0,d0			; Libère la mémoire allouée
	movea.l	a5,a1			; par Exec pour PublicMenusBase
	move.w	LIB_NEGSIZE(a5),d0
	suba.l	d0,a1
	add.w	LIB_POSSIZE(a5),d0
	CALLSYS	FreeMem
	move.l	d2,d0
.Ret	movem.l	(sp)+,d2/a5/a6
	rts

; ************************************
Reserved:
	moveq	#0,d0
	rts

; **************************************
; * Fonctions spécifiques à la library *
; **************************************
; Len = StringLen(String)
; D0    -30       A0
StringLen:
	moveq	#-1,d0	* String (A0)
.count	tst.b	(a0)+
	dbeq	d0,.count
	adda.w	d0,a0
	not.l	d0
	rts

; ************************************
; NewPort = NewMsgPort(Name,Pri)
; D0        -36        A0   D0
NewMsgPort:
	movem.l	d2-d3/a2-a3/a6,-(sp)
	movea.l	a0,a2
	move.l	d0,d2
	suba.l	a3,a3
	moveq	#-1,d0
	EXEC	AllocSignal
	move.b	d0,d3
	bmi.s	.Ret
.SigOk	moveq	#MP_SIZE,d0
	move.l	#MEMF_CLEAR|MEMF_PUBLIC,d1
	CALLSYS	AllocMem
	tst.l	d0
	bne.s	.PortOk
	move.b	d3,d0
	CALLSYS	FreeSignal
	bra.s	.Ret
.PortOk	movea.l	d0,a3
	move.b	d2,MP+LN_PRI(a3)
	move.b	#NT_MSGPORT,MP+LN_TYPE(a3)
	move.b	#PA_SIGNAL,MP_FLAGS(a3)
	move.b	d3,MP_SIGBIT(a3)
	move.l	ThisTask(a6),MP_SIGTASK(a3)
	move.l	a2,MP+LN_NAME(a3)
	beq.s	.List
	movea.l	a3,a1
	CALLSYS	AddPort
	bra.s	.Ret
.List	lea	MP_MSGLIST(a3),a0
	NEWLIST	a0
.Ret	move.l	a3,d0
	movem.l	(sp)+,d2-d3/a2-a3/a6
	rts

; ************************************
; VOID FreeMsgPort(Port)
;      -42         A0
FreeMsgPort:
	movem.l	a2/a6,-(sp)
	movea.l	a0,a2
	movea.l	$4.w,a6
	move.l	MP+LN_NAME(a2),d0
	beq.s	.NoName
	move.l	a2,a1
	CALLSYS	RemPort
.NoName	moveq	#0,d0
	move.b	MP_SIGBIT(a2),d0
	CALLSYS	FreeSignal
	movea.l	a2,a1
	moveq	#MP_SIZE,d0
	CALLSYS	FreeMem
	movem.l	(sp)+,a2/a6
	rts

; ************************************
; NewIO = NewIORequest(Port,Size)
; D0      -48          A0   D0
NewIORequest:
	movem.l	d2/a2-a3/a6,-(sp)
	move.l	d0,d2
	movea.l	a0,a2
	move.l	#MEMF_CLEAR|MEMF_PUBLIC,d1
	EXEC	AllocMem
	tst.l	d0
	beq.s	.Ret
	movea.l	d0,a3
	move.b	#NT_MESSAGE,IO+MP+LN_TYPE(a3)
	move.w	d2,IO+MP+MN_LENGTH(a3)
	move.l	a2,IO+MP+MN_REPLYPORT(a3)
.Ret	movem.l	(sp)+,d2/a2-a3/a6
	rts

; ************************************
; VOID FreeIORequest(IORequest)
;      -54           A1
FreeIORequest:
	move.l	a6,-(sp)
	moveq	#0,d0
	move.w	IO+MP+MN_LENGTH(a1),d0
	EXEC	FreeMem
	movea.l	(sp)+,a6
	rts

; ************************************
; VOID LockPMenus(VOID)
;      -60
LockPMenus:
	movem.l	d0-d1/a0-a1/a6,-(sp)
	lea	pmb_Semaphore(a6),a0
	EXEC	ObtainSemaphore
	movem.l	(sp)+,d0-d1/a0-a1/a6
	rts

; ************************************
; VOID UnlockPMenus(VOID)
;      -66
UnlockPMenus:
	movem.l	d0-d1/a0-a1/a6,-(sp)
	lea	pmb_Semaphore(a6),a0
	EXEC	ReleaseSemaphore
	movem.l	(sp)+,d0-d1/a0-a1/a6
	rts

; ************************************
; BOOL AddPMenu(PMenu)
; D0   -72      A0
AddPMenu:
	bsr.s	LockPMenus
	move.l	pmb_PMenuStrip(a6),d0
	beq.s	.First
.Last	movea.l	d0,a1
	move.l	mu_NextMenu(a1),d0
	bne.s	.Last
	move.l	a0,mu_NextMenu(a1)
	bra.s	.Add
.First	move.l	a0,pmb_PMenuStrip(a6)
.Add	addq.w	#1,pmb_PMenuCount(a6)
	clr.l	mu_NextMenu(a0)
	bsr.s	UnlockPMenus
	moveq	#-1,d0
	rts

; ************************************
; VOID RemPMenu(PMenu)
;      -78      A0
RemPMenu:
	bsr.s	LockPMenus
	move.l	pmb_PMenuStrip(a6),d0
	beq.s	.ret
	cmpa.l	d0,a0
	beq.s	.First
.loop	movea.l	d0,a1
	move.l	mu_NextMenu(a1),d0
	beq.s	.rem
	cmpa.l	d0,a0
	bne.s	.loop
.rem	move.l	mu_NextMenu(a0),mu_NextMenu(a1)
	bra.s	.1
.First	move.l	mu_NextMenu(a0),pmb_PMenuStrip(a6)
.1	subq.w	#1,pmb_PMenuCount(a6)
	bne.s	.ret
	clr.l	pmb_PMenuStrip(a6)
.ret	bsr.s	UnlockPMenus
	rts

; ************************************
; VOID OffPMenu(PMenu,PMenuNumber)
;      -84      A0    D0
OffPMenu:
	bsr.s	LockPMenus
	bsr.s	PItemAddress
	tst.l	d0
	beq.s	.Menu
.Item	movea.l	d0,a0
	bclr	#4,mi_Flags+1(a0)
	bra.s	UnlockPMenus
.Menu	bclr	#0,mu_Flags+1(a0)
	bra.s	UnlockPMenus

; ************************************
; VOID OnPMenu(PMenu,PMenuNumber)
;      -90     A0    D0
OnPMenu:
	bsr	LockPMenus
	bsr.s	PItemAddress
	tst.l	d0
	beq.s	.Menu
.Item	movea.l	d0,a0
	bset	#4,mi_Flags+1(a0)
	bra	UnlockPMenus
.Menu	bset	#0,mu_Flags+1(a0)
	bra	UnlockPMenus

; ************************************
; Item = PItemAddress(PMenu,PMenuNumber)
; D0     -96          A0    D0
PItemAddress:
	movem.l	d2/a2,-(sp)
	bsr	LockPMenus
	suba.l	a2,a2
	moveq	#-1,d1		; PMenuNumber == MENUNULL ?
	cmp.w	d1,d0
	beq.s	.ret
	lsr.w	#5,d0		; ITEMNUM(PMenuNumber) == NOITEM ?
	moveq	#NOITEM,d2
	and.w	d0,d2
	cmpi.w	#NOITEM,d2
	beq.s	.ret
	move.l	mu_FirstItem(a0),d1
	bra.s	.1
.loop1	movea.l	d1,a0
	move.l	mi_NextItem(a0),d1
.1	dbeq	d2,.loop1
	beq.s	.ret
	movea.l	d1,a2
	lsr.w	#6,d0		; SUBNUM(PMenuNumber) == NOSUB ?
	moveq	#NOSUB,d2
	and.w	d0,d2
	cmpi.w	#NOSUB,d2
	beq.s	.ret
	move.l	mi_SubItem(a2),d1
	bra.s	.2
.loop2	movea.l	d1,a0
	move.l	mi_NextItem(a0),d1
.2	dbeq	d2,.loop2
	beq.s	.ret
	movea.l	d1,a2
.ret	bsr	UnlockPMenus
	move.l	a2,d0
	movem.l	(sp)+,d2/a2
	rts

; ************************************
	END


[Retour en haut] / [Retour aux articles] [Article suivant]