Suivez-nous sur Mastodon

|
|
|
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
|
|
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
|
|
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
|
|
A propos d'Obligement
|
|
David Brunet
|
|
|
|
Programmation : Assembleur - exploitation des types d'outils
(Article écrit par Frédéric Delacroix et extrait d'Amiga News - juin 1994)
|
|
Je vous propose ce mois-ci une méthode, assez optimisée, pour exploiter les arguments
passés à une commande. Nous ne nous attarderons pas cette fois-ci sur l'utilisation du
CLI et de la puissante fonction ReadArgs(), mais plutôt à l'utilisation - plus rare sans doute -
des types d'outils (tooltypes), aussi bien à partir du Worbench que du CLI (ou Shell, c'est pareil).
Les fichiers icônes
C'est bien connu maintenant, pour afficher une icône associée à un fichier,
le Workbench a besoin d'un fichier ".info" correspondant, contenant des informations
sur l'objet à afficher. Ce n'est plus vrai à partir du Kickstart 2.0 grâce à l'option
"Show all files", mais c'est un cas particulier que nous laissons de côté.
Nous laissons également de côté les fichiers nommés ".info" tout court que l'on
pouvait rencontrer jadis, au temps du Kickstart 1.3, qui semblaient contenir le
listing du répertoire concerné, et qui ont depuis disparu de nos contrées.
Voyons donc le contenu d'un fichier icône. Il s'agit en réalité principalement d'une
structure DiskObject, définie dans le fichier d'inclusion "workbench/workbench.[hi]" :
struct DiskObject {
UWORD do_Magic; /* indication d'une icône */
UWORD do_Version;
struct Gadget do_Gadget; /* définit l'icône même */
UBYTE do_Type; /* projet, outil, etc */
char * do_DefaultTool; /* outil des projets */
char ** do_ToolTypes;
LONG do_CurrentX; /* position de l'icône */
LONG do_CurrentY;
struct DrawerData * do_DrawerData; /* la fenêtre des tiroirs */
char * do_ToolWindow; /* pas réellement utilisé */
LONG do_StackSize; /* taille de la pile */
};
|
La manière dont ces informations sont réellement stockées dans le fichier n'est pas
documentée et risque de changer dans des versions ultérieures du système. En conséquence,
l'accès aux fichiers icônes doit toujours se faire par l'intermédiaire de l'icon.library.
Cette bibliothèque possède par ailleurs quelques fonctions comme FindToolType()
ou FreeFreeList() qui sont très utiles dans certains cas.
Le cas qui nous intéresse
Nous voulons savoir si tel ou tel type d'outils
a été spécifié par l'utilisateur. Pour cela, il faut évidemment d'abord obtenir
la structure DiskObject. Pour ce faire, l'icon.library (sur disque jusqu'au Kickstart 1.3,
en ROM depuis), propose la fonction GetDiskObject(), à laquelle on fournit en
A0 le nom de l'icône à charger (sans le suffixe ".info"). On obtient en retour
la structure DiskObject correspondante. ou "0" s'il n'en existe pas, ou si une erreur
est survenue pendant le chargement (dans ce cas IoErr() en donne la cause).
Le premier problème se pose : comment savoir quelle icône charger ?
Cela dépend surtout de ce que l'on veut faire. En général, il suffit de charger
l'icône du programme lui-même, mais il peut s'avérer nécessaire par exemple pour
un programme lancé à partir du Workbench par une sélection multiple, d'examiner
toutes les icônes sélectionnées. Là, c'est le programmeur qui décide.
En général, un programme lancé à partir du Workbench examine le premier ou le
deuxième argument donné par la structure WBStartup reçue en début d'exécution à
son port de message. En général, il vaut mieux s'intéresser au second, étant donné
que cela signifie que l'utilisateur a soit fait une sélection multiple (grâce à la
touche "Shift") ou cliqué sur une icône projet dont l'outil par défaut était le
programme en cours d'exécution. Dans le premier cas, les arguments sont envoyés au
programme dans l'ordre de la sélection : dans le second, c'est l'icône de l'outil
par défaut en premier, puis l'icône projet qui a été cliquée.
Un programme lancé à partir du CLI a la tâche plus difficile, surtout si on n'utilise
pas le Kickstart 2.0. Il s'agit pour lui de trouver d'où il vient, c'est-à-dire son
répertoire (à priori, ce n'est pas le même que le répertoire courant) et l'exécutable.
Le Kickstart 2.0 rend les choses assez simples grâce aux fonctions GetProgramDir()
et GetProgramName() de la dos.library, évitant ainsi quelques migraines à se plonger dans
les pointeurs BCPL. Il suffit alors d'aller chercher l'icône grâce à l'icon.library.
A noter qu'il peut être judicieux de prévoir également le passage d'arguments par le
CLI, ces arguments surpassant alors ceux donnés en type d'outils. Il suffit alors d'examiner
l'icône de la façon la plus classique, à grand renfort de FindToolType() et MatchToolValue().
Un exemple !
Le programme que je vous propose ce mois-ci affiche tous les types d'outils d'une
icône dans la fenêtre du CLI, ou dans une fenêtre CON: si invoqué à partir du Workbench.
A partir du CLI, il se contente d'afficher les types d'outils de son icône à lui,
et à partir du Workbench affiche ses types d'outils, ou ceux du second argument s'il y en
a un. Il y a deux façons de donner un deuxième argument : soit cliquer sur l'icône du
programme puis "Shift-double-cliquer" sur l'icône à examiner, soit utiliser une icône
de type projet dont l'outil par défaut est le programme dont le listing suit.
J'oubliais : ce programme ne marche que sur Kickstart 2.04 et supérieur.
En guise de conclusion
Une dernière chose : lorsqu'un de vos programmes crée une icône projet,
il est de bon aloi de régler le bon outil par défaut. Ceci se fait, si on
vient du CLI, en réservant deux espaces contigus sur la pile (ou ailleurs,
mais la pile c'est bien pratique). Dans l'un on met le chemin du programme grâce
à GetProgramDir() et NameFromLock(), dans l'autre on y met le nom du programme
obtenu par GetProgramName(), et on réunit le tout dans le premier tampon mémoire
grâce à AddPart(). Il reste alors à mettre dans le champ do_DefaultTool de la
structure DiskObject le pointeur sur le tampon mémoire et à sauvegarder l'icône.
include exec/execbase.i
include exec/exec.i
include exec/exec_lib.i
include dos/dos.i
include dos/dos_lib.i
include dos/dosextens.i
include workbench/workbench.i
include workbench/startup.i
include workbench/icon_lib.i
move.l 4.w,a6 ; ExecBase
move.l ThisTask(a6),a4 ; notre tâche
tst.l pr_CLI(a4) ; vient-elle du CLI?
bne.s FromCLI
lea pr_MsgPort(a4),a0 ; non: va checher
jsr _LVOWaitPort(a6) ; le message du
lea pr_MsgPort(a4),a0 ; workbench
jsr _LVOGetMsg(a6)
move.l d0,WB.Startup
; On ouvre d'abord la bibliothèque dos.library
FromCLI lea DOSName(pc),a1
moveq #37,d0 ; Kickstart 2.04+
jsr _LVOOpenLibrary(a6)
move.l d0,DOSBase
beq exit
; puis la bibliothèque icon.library
lea IconName(pc),a1
moveq #37,d0
jsr _LVOOpenLibrary(a6)
move.l d0,IconBase
beq FermeDOS
tst.l WB.Startup
beq.s FenCLI
; pour le workbench, on ouvre une fenêtre
move.l #WBFenetre,d1
move.l #MODE_OLDFILE,d2
move.l DOSBase(pc),a6
jsr _LVOOpen(a6)
move.l d0,Fenetre
beq.s FermeIcon
; s'il y a au moins 2 arguments, on prend le deuxième,
; sinon on se contente du premier
move.l WB.Startup(pc),a2
tst.l sm_NumArgs(a2)
beq.s FermeFenetre
move.l sm_ArgList(a2),a3 ; liste de structures
cmp.l #2,sm_NumArgs(a2) ; WBArg (lock+nom)
blt.s UnArg
addq.l #wa_SIZEOF,a3
UnArg move.l wa_Lock(a3),d3
move.l wa_Name(a3),d4
bsr.s GetIcon ; charge l'icône en mémoire
bsr Affiche ; affiche les tooltypes
bsr FreeIcon ; libère l'icône
bra.s FermeFenetre
FenCLI move.l DOSBase(pc),a6 ; le CLI a déjà une fenêtre
jsr _LVOOutput(a6)
move.l d0,Fenetre
jsr _LVOGetProgramDir(a6) ; verrou sur le répertoire
move.l d0,d3 ; du programme (accessible aussi par
beq.s FermeIcon ; le pseudo-assign PROGDIR:
lea -108(sp),sp ; on se réserve un tampon sur la pile
move.l sp,d1 ; (108 octets sont suffisants pour un nom de
moveq #108,d2 ; fichier)
jsr _LVOGetProgramName(a6) ; on y copie le nom du programme
move.l sp,d4
bsr.s GetIcon ; on charge l'icône
lea 108(sp),sp ; plus besoin du nom, on libère l'espace
bsr.s Affiche ; affichage des types d'outils
bsr FreeIcon ; libération de l'icône
bra.s FermeIcon
FermeFenetre
move.l Fenetre(pc),d1
move.l DOSBase(pc),a6
jsr _LVOClose(a6)
FermeIcon
move.l IconBase(pc),a1
move.l 4.w,a6
jsr _LVOCloseLibrary(a6)
FermeDOS
move.l DOSBase(pc),a1
jsr _LVOCloseLibrary(a6)
exit move.l WB.Startup(pc),d0
beq.s CLIExit
move.l d0,a1 ; il faut toujours faire un Forbid() avant
jsr _LVOForbid(a6) ; de répondre au Workbench !
jsr _LVOReplyMsg(a6)
CLIExit moveq #0,d0
rts
; la routine suivante charge l'icône en mémoire
GetIcon ; (D6)DiskObject=GetIcon(directory,Nom)(D3,D4)
move.l d3,d1 ; on se place dans le bon directory
move.l DOSBase(pc),a6 (D3 est un Lock)
jsr _LVOCurrentDir(a6)
move.l d0,d5 ; on sauve l'ancien
move.l d4,a0 ; on charge l'icône (D4
move.l IconBase(pc),a6 ; pointe sur son nom)
jsr _LVOGetDiskObjectNew(a6)
move.l d0,d6
move.l d5,d1 ; on remet l'ancien dir
move.l DOSBase(pc),a6
jsr _LVOCurrentDir(a6)
rts
; la routine suivante affiche les types d'outils
; (do_ToolTypes pointe sur un tableau de pointeurs sur des
; chaînes de caractères, terminée par un pointeur nul).
Affiche ; Affiche(DiskObject)(D6)
move.l d6,a4
move.l a4,d6
beq.s .Fin
cmp.b #WBPROJECT,do_Type(a4) ; bonus: si l'icône
bne.s .PasProjet ; est un projet, on affiche
lea do_DefaultTool(a4),a1 ; l'icône par défaut
lea DefTool.MSG(pc),a0
bsr.s PrintF
.PasProjet
move.l #ToolTypes.MSG,d0
bsr.s Print
move.l do_ToolTypes(a4),a2
.Loop move.l (a2)+,d0
beq.s .Fin
bsr.s Print
bra.s .Loop
.Fin rts
; cette routine libère la mémoire associée à la structure
; DiskObject.
FreeIcon ; FreeIcon(DiskObject)(D6)
move.l d6,a0
move.l a0,d6
beq.s .Rien
move.l IconBase(pc),a6
jsr _LVOFreeDiskObject(a6)
.Rien rts
Print ; Print(Message)(d0)
move.l d0,d2
move.l Fenetre(pc),d1
move.l DOSBase(pc),a6
jsr _LVOFPuts(a6)
move.l Fenetre(pc),d1
moveq #10,d2
jsr _LVOFPutC(a6)
rts
PrintF ; PrintF(Format,Args)(A0,A1)
move.l a0,d2
move.l a1,d3
move.l Fenetre(pc),d1
move.l DOSBase(pc),a6
jsr _LVOVFPrintf(a6)
move.l Fenetre(pc),d1
moveq #10,d2
jsr _LVOFPutC(a6)
rts
WB.Startup dc.l 0
DOSBase dc.l 0
IconBase dc.l 0
Fenetre dc.l 0
DOSName dc.b "dos.library",0
IconName dc.b "icon.library",0
WBFenetre dc.b "CON:////ToolTypes/AUTO/CLOSE/WAIT/SCREEN*",0
DefTool.MSG dc.b "Outil par défaut de ce projet: %s",10,0
ToolTypes.MSG dc.b "Types d'outils de l''icône:",0
|
|