Obligement - L'Amiga au maximum

Vendredi 17 mai 2024 - 11:49  

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 : C - Spy, espion de la mémoire
(Article écrit par Max et extrait d'Amiga News Tech - septembre 1991)


Quand j'étais à l'école, la maîtresse disait toujours au petit surdoué que j'étais déjà, que le meilleur moyen d'apprendre quelque chose est d'observer d'autres personnes le faire. Ce vieil adage m'est depuis resté, et je ne manque jamais une occasion de le mettre en pratique.

Pour ce qui nous concerne ici, nous allons nous fabriquer un outil capable de naviguer dans la mémoire de l'Amiga à la recherche de ses structures si particulières, que nous afficherons en clair - parfois en foncé - de telle sorte que l'utilisateur n'aie plus qu'à cliquer sur l'un des champs de cette structure pour en visualiser le contenu. Ainsi, il (l'utilisateur) sera en mesure de se balader de fenêtre en fenêtre, de menu en menu, de gadget en gadget, de train en train et de port en port et pourra y observer tous les paramètres mis en place par d'autres programmeurs plus chevronnés que lui. En anglais, on appelle ce type d'outils un "browser", ce qui, si ma mémoire ne me fait pas trop défaut, doit signifier quelque chose comme "baladeur" ou "scruteur".

En aucun cas il ne sera permis de modifier les valeurs trouvées, sinon cela devient un éditeur, ce qui est hors de propos aujourd'hui. Sans parler des conséquences désastreuses que peut avoir la moindre modification de données inconnues.

Comment ça marche ?

Le principe est très simple : pour chaque structure connue du programme, on écrit une fonction chargée de l'afficher correctement. Histoire de ne pas trop se surcharger de travail, on lui associe également un bloc d'informations décrivant le nom de chacun des membres de la structure, ainsi que son type. De cette manière, l'affichage à proprement parler de toutes les structures pourra être effectué par une seule et même fonction, ne laissant plus que les réactions de l'utilisateur à gérer. Rien de bien extraordinaire d'ailleurs, puisque cela consiste à repérer quel champ à été cliqué, et à appeler la routine d'affichage correspondante. Notez à ce sujet qu'une même fonction peut s'appeler elle-même. Par exemple, la fonction prWindow() (qui affiche donc une structure Window) s'appelle elle-même lorsque l'un des champs NextWindow, Parent ou Descendant à été cliqué. En C, cela ne pose aucun problème, il faut juste faire attention à ce que la pile ne déborde point, suite à de trop nombreux appels récursifs.

La version publiée de notre espion ne connaît que les structures IntuitionBase, Screen, Window, Gadget et Menu - la place manquait pour en ajouter d'autres. La version présente sur la disquette accompagnant ce numéro connaît en plus les structures Menultem, Gadget, IntuiText, Border, Image, RastPort, ViewPort, TextAttr et TextFont.

Si vous désirez ajouter des structures supplémentaires, il vous suffit d'écrire autant de nouvelles fonctions, en vous basant sur le principe de celles déjà en place, qu'il vous faudra tout de même modifier un tout petit peu, afin qu'elles se rendent compte du changement.

Pour clarifier le principe, imaginons que nous voulions ajouter la structure BoolInfo. On commence donc par écrire une fonction prBoolInfo() qui ressemblera à ça :

C
C

Le tableau StructureInfo décrit tous les champs de la structure BoolInfo :
  • D'abord son type en ASCII ("ULONG", "UWORD *", etc.).
  • Puis son nom en ASCII aussi ("Flags", "Mask", etc.).
  • Son type codé, à choisir dans le tableau ci-dessous.
  • Enfin, sa longueur en octets.
Les types de champs possibles sont définis dans Spy.h. Ce sont :
  • ALIEN : le champ est d'un type inconnu du programme.
  • STRUC : structure à l'intérieur de la structure.
  • OCTET : valeur sur 1 octet.
  • CARAC : idem, mais affichée en ASCII.
  • MOT16 : valeur sur 16 bits.
  • MOT32 : valeur sur 32 bits.
  • CHAIN : pointeur sur une chaîne de caractères.
  • S_PTR : pointeur.
  • TABLO : tableau de valeurs.
Une fois ceci fait, il vous faudra modifier la fonction prGadget() afin qu'elle prenne en compte votre nouvelle fonction prBoolInfo(). Il faudra pour cela changer le code du champ SpecialInfo d'ALIEN en S_PTR, et ajouter dans le switch :

C
Et c'est tout.

Tel quel, ce programme ne présente pas vraiment d'astuces de programmation éclatantes. J'espère toutefois qu'il vous sera utile dans la mise au point de vos propres applications - c'est en tout cas son but.

Listing 1 (makefile pour Spy.c)

EXE=Spy
OBJ=Spy.o SpyGadgets.o
LIB=LIB:amiga.lib LIB:lc.lib
ARG=-d5 -mas -v -cfsuwt -N
LNK=SC SD DEFINE __main=__tinymain NOICONS NODEBUG

Spy:           $(OBJ)
               BLink LIB:c.o $(OBJ) TO $(EXE) LIB $(LIB) $(LNK)

Spy.o:         Spy.c Spy.h
               Lc $(ARG) Spy.c

SpyGadgets.o:  SpyGadgets.c Spy.h
               Lc $(ARG) SpyGadgets.c

Listing 2 (fichier d'entête à Spy.c et SpyGadgets.c)

#define SZ(x) sizeof(struct x)

#define BYTESIZE	sizeof(BYTE)
#define WORDSIZE	sizeof(WORD)
#define LONGSIZE	sizeof(LONG)
#define PTRSIZE 	sizeof(APTR)

#define ALIEN	0x0000	/* type inconnnu - non sélectionnable */
#define STRUC	0x0001	/* structure                          */
#define OCTET	0x0002	/* octet                              */
#define CARAC	0x0003	/* caractère alphanumérique           */
#define MOT16	0x0004	/* mot                                */
#define MOT32	0x0005	/* long                               */
#define CHAIN	0x0006	/* chaine de caractères               */
#define S_PTR	0x0007	/* pointeur sur une structure         */
#define TABLO	0x0008	/* tableau de valeurs quelconques     */

#define MAX_BUFFERS	64
#define MAX_LINES	15

#define GGID_CHOIX	0
#define GGID_RETOUR	0x1000
#define GGID_SLIDER	0x1001

#define TOP_LINE	25

#define SI_SIZE		(sizeof(si) / sizeof(struct StructureInfo))

struct StructureInfo
{	UBYTE *MemberType;
	UBYTE *MemberName;
	WORD   MemberFlag;
	WORD   MemberSize;
};

struct Depart
{	struct IntuitionBase *IntuitionBase;
	struct GfxBase       *GfxBase;
	/* On pourrait continuer avec d'autres libraries */
};

Listing 3 (Spy.c)

 * Spy v1.0 - L'Espion des structures en mémoire...               *
 * Par Max pour ANT                                               *
 *                                                                *
 * Ecrit pour le SAS/Lattice C 5.10                               *
 * (voir le makefile ci-joint pour les détails de compilation)    *
 *                                                                *
 * NOTE : Pour des raisons de mise en page, la version publiée    *
 *        est plus petite que celle sur la disquette...           *
 *****************************************************************/

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/ports.h>
#include <intuition/intuition.h>
#include <intuition/screens.h>
#include <intuition/intuitionbase.h>
#include <libraries/dos.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <clib/macros.h>
#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/graphics.h>

#include "spy.h"

/***** Variables globales ****************************************/
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Window *win;
struct RastPort *rp;

SHORT Overlap, visibleLines,
      totalLines, topLine, hidden;

/***** Données globales et externes ******************************/
extern struct NewWindow nw;
extern struct Gadget ChoixGadget[];
extern struct Gadget RetourGadget, SliderGadget;
extern struct PropInfo SliderInfo;

struct IntuiText iText =
{	1, 0, JAM2, 15, (TOP_LINE + 1), NULL, NULL, NULL
};

UBYTE buffers[MAX_BUFFERS][80], buftype[MAX_BUFFERS];

struct Depart Debut;

/***** Prototypes ************************************************/
void main(void);
void cleanexit(LONG code);

void ClearWindow(void);
void MakeBuffers(struct StructureInfo *sinfo,WORD num,UBYTE *mem);
void PrepareGadgets(void);
void SetSlider(void);
void GetSlider(void);
void SetGadgets(void);
SHORT GetChoice(void);

void HexDump(UBYTE *base, WORD nb, WORD size);
void Dump08(UBYTE *base, UBYTE *buf, SHORT nb);
void Dump16(UBYTE *base, UBYTE *buf, SHORT nb);
void Dump32(UBYTE *base, UBYTE *buf, SHORT nb);

void prDepart(struct Depart *deb);
void prIntuitionBase(struct IntuitionBase *ib);
void prScreen(struct Screen *scr);
void prWindow(struct Window *win);
void prTextAttr(struct TextAttr *ta);
void prTextFont(struct TextFont *tf);
void prViewPort(struct ViewPort *vp);
void prRastPort(struct RastPort *rp);
void prBitMap(struct BitMap *bm);
void prGadget(struct Gadget *gg);
void prMenu(struct Menu *mnu);
void prMenuItem(struct MenuItem *itm);
void prIntuiText(struct IntuiText *it);
void prImage(struct Image *img);
void prBorder(struct Border *brd);

/***** main() - Initialisation et affiche la structure de départ **/
void main(void)
{
	if (!(IntuitionBase = (struct IntuitionBase *)
		OpenLibrary("intuition.library", 33L)))
	cleanexit(RETURN_FAIL);

	if (!(GfxBase = (struct GfxBase *)
		OpenLibrary("graphics.library", 33L)))
	cleanexit(RETURN_FAIL);

	Debut.IntuitionBase = IntuitionBase;
	Debut.GfxBase       = GfxBase;

	if (!(win = OpenWindow(&nw)))
		cleanexit(RETURN_FAIL);
	rp = win->RPort;

	PrepareGadgets();

	for (;;)	/* FOREVER */
	{	prDepart(&Debut);
	}
}

/***** cleanexit() - Ferme tout et retourne au WB/CLI ************/
void cleanexit(LONG code)
{
	if (win)
		CloseWindow(win);
	if (GfxBase)
		CloseLibrary((struct Library *)GfxBase);
	if (IntuitionBase)
		CloseLibrary((struct Library *)IntuitionBase);
	exit(code);
}

/***** ClearWindow() - Efface la fenêtre et ses gadgets **********/
void ClearWindow(void)
{
	if (SliderGadget.NextGadget)
		RemoveGList(win, SliderGadget.NextGadget, -1L);

	SetAPen(rp, 0);
	RectFill(rp, win->BorderLeft, win->BorderTop,
	         win->Width  - win->BorderRight  - 2,
	         win->Height - win->BorderBottom - 2);
}

/***** MakeBuffers() - Prépare les textes des gadgets ************/
void MakeBuffers(struct StructureInfo *sinfo, WORD num, UBYTE *mem)
{
LONG offset;
register SHORT i, coul;
UBYTE b[40];

	ClearWindow();

	Overlap = 1;
	visibleLines = MAX_LINES;
	totalLines = topLine = hidden = 0;

	if (num > MAX_BUFFERS) num = MAX_BUFFERS;

	for (i = offset = 0; i < num; i++)
	{	register struct StructureInfo *si = &sinfo[i];
		register WORD type = si->MemberFlag;
		register UBYTE *buf = buffers[i];
		register APTR ptr;

		sprintf(buf,"%-.24s%-.16s",si->MemberType,si->MemberName);

		coul = 2;

		switch(type)
		{	case STRUC:
			case TABLO:
				coul = 1;
			case ALIEN:
				b[0] = ';';
				b[1] = '\0';
				break;
			case OCTET:	/* écrit un octet en hexa */
				sprintf(b, " = 0x%02lx;", *(UBYTE *)(mem + offset));
				break;
			case CARAC:	/* écrit un octet en ASCII */
				sprintf(b, " = '%lc';", *(UBYTE *)(mem + offset));
				break;
			case MOT16:	/* écrit un mot en hexa */
				sprintf(b, " = 0x%04lx;", *(UWORD *)(mem + offset));
				break;
			case MOT32:	/* écrit un long en hexa */
				sprintf(b, " = 0x%08lx;", *(ULONG *)(mem + offset));
				break;
			case CHAIN:	/* écrit une chaine en ASCII */
				if (!(ptr = (APTR)*(ULONG *)(mem + offset)))
					strcpy(b, " = NULL;");
				else
				{	coul = 3;
					sprintf(b, " = '%.38s';", ptr);
				}
				break;
			case S_PTR:	/* écrit un pointeur */
				if (!(ptr = (APTR)*(ULONG *)(mem + offset)))
					strcpy(b, " = NULL;");
				else
				{	coul = 1;
					sprintf(b, " = 0x%08lx;", ptr);
				}
				break;

		}	/* switch */

		strcat(buf, b);
		buftype[i] = coul;

		if (i < MAX_LINES)
		{	iText.FrontPen = coul;
			iText.IText    = buf;
			PrintIText(rp, &iText, 15, i * 10);
		}
		++totalLines;
		offset += (LONG)si->MemberSize;
	}	/* for */
	SetGadgets();
	SetSlider();
}

/***** SetGadgets() - Met en place les gadgets de choix **********/
void SetGadgets(void)
{
register SHORT i;

	for (i = 0; (i < MAX_LINES) && (i < totalLines); i++)
	{	if (buftype[topLine + i] == 1)
		{	ChoixGadget[i].GadgetID = topLine + i;
			AddGadget(win, &ChoixGadget[i], -1L);
		}
	}
}

/****** SetSlider() - Règle la taille et la position du slider ***/
void SetSlider(void)
{
register UWORD VertBody, VertPot;

	hidden = MAX(totalLines - visibleLines, 0);

	if (topLine < 0)
		topLine = 0;
	else if (topLine > hidden)
		topLine = hidden;

	if (hidden > 0 && totalLines > Overlap)
		VertBody = (UWORD)(((ULONG)(visibleLines - Overlap)
		           * MAXBODY) / (totalLines - Overlap));
	else
		VertBody = MAXBODY;

	if (hidden > 0)
		VertPot  = (UWORD)(((ULONG)topLine * MAXPOT) / hidden);
	else
		VertPot  = 0;

	NewModifyProp(&SliderGadget, win, NULL, FREEVERT|AUTOKNOB,
	              MAXPOT, VertPot, MAXBODY, VertBody, 1L);
}

/****** GetSlider() - Lit la nouvelle position du slider *********/
void GetSlider(void)
{
register SHORT i;

	topLine = ((((ULONG)hidden * SliderInfo.VertPot) +
	          (MAXPOT / 2)) / MAXPOT);

	ClearWindow();
	for (i = 0; (i < MAX_LINES) && (i < totalLines); i++)
	{	iText.FrontPen = buftype[topLine + i];
		iText.IText    = buffers[topLine + i];
		PrintIText(rp, &iText, 15, i * 10);
	}
	SetGadgets();
}

/***** GetChoix() - Gère les gadgets (choix, retour et slider) ***/
SHORT GetChoix(void)
{
struct IntuiMessage *im;
struct Gadget *g;
ULONG class;
USHORT code;

	for (;;)	/* FOREVER */
	{	WaitPort(win->UserPort);
		while (im = (struct IntuiMessage *)GetMsg(win->UserPort))
		{	class = im->Class;
			code  = im->Code;
			g     = (struct Gadget *)im->IAddress;
			ReplyMsg((struct Message *)im);

			switch(class)
			{	case RAWKEY:
					if (code == CURSORUP)
						--topLine;
					else if (code == CURSORDOWN)
						++topLine;

					SetSlider();
					GetSlider();
					break;

				case GADGETUP:
					if (g->GadgetID == GGID_SLIDER)
						GetSlider();
					else
						return((SHORT)g->GadgetID);
					break;

				case CLOSEWINDOW:
					cleanexit(RETURN_OK);
					break;
			}
		}
	}
	return(0);	/* Evite un Warning à la compilation */
}

/***** HexDump() - Affiche un dump hexa d'une zone mémoire *******/
void HexDump(UBYTE *base, SHORT nb, SHORT size)
{
UBYTE *mem = base;
SHORT offset;

	ClearWindow();
	totalLines = topLine = hidden = 0;

	while (nb)
	{	if (totalLines < MAX_BUFFERS)
		{	register UBYTE *buf;

			buf = buffers[totalLines];
			*buf = '\0';

			buftype[totalLines] = 3;

			switch(size)
			{	case OCTET:
					offset = MIN(nb, 16);
					Dump08(mem, buf, offset);
					mem += (LONG)offset;
					break;
				case MOT16:
					offset = MIN(nb, 8);
					Dump16(mem, buf, offset);
					mem += (LONG)(offset * 2);
					break;
				case MOT32:
					offset = MIN(nb, 4);
					Dump32(mem, buf, offset);
					mem += (LONG)(offset * 4);
					break;
			}
			if (totalLines < MAX_LINES)
			{	iText.FrontPen = 3;
				iText.IText    = buf;
				PrintIText(rp, &iText, 15, totalLines * 10);
			}
			++totalLines;
			nb -= offset;
		}
		else
			nb = 0;	/* pour sortir du while(nb) */
	}
	SetGadgets();
	SetSlider();
	GetChoix();	/* Juste pour attendre 'CLOSE' ou 'Retour' */
}

void Dump08(UBYTE *base, UBYTE *buf, SHORT nb)	/* Dump octets */
{
register SHORT i;
UBYTE b[4];
register UBYTE *m = base;

	for (i = 0; i < nb; i++)
	{	sprintf(b, "%02lx ", *(m++));
		strcat(buf, b);
	}
}

void Dump16(UBYTE *base, UBYTE *buf, SHORT nb)	/* Dump mots */
{
register SHORT i;
UBYTE b[6];
register UWORD *m = (UWORD *)base;

	for (i = 0; i < nb; i++)
	{	sprintf(b, "%04lx ", *(m++));
		strcat(buf, b);
	}
}

void Dump32(UBYTE *base, UBYTE *buf, SHORT nb)	/* Dump longs */
{
register SHORT i;
UBYTE b[10];
register ULONG *m = (ULONG *)base;

	for (i = 0; i < nb; i++)
	{	sprintf(b, "%08lx ", *(m++));
		strcat(buf, b);
	}
}

/******************************************************************
 * Voici maintenant toutes les routines d'affichages des          *
 * différentes structures du système. Elles sont toutes basées    *
 * sur le même squelette... Avec un bon éditeur et quelques coups *
 * de copier/coller bien placés, ce ne sera pas trop dur à taper. *
 *****************************************************************/

/***** Structure de départ ***************************************/
void prDepart(struct Depart *deb)
{
static struct StructureInfo si[] =
{	{	"struct IntuitionBase *", "IntuitionBase", S_PTR, PTRSIZE },
	{	"struct GfxBase *",       "GfxBase",       ALIEN, PTRSIZE }
};
SHORT choix = 0;
	while (choix != GGID_RETOUR)
	{	MakeBuffers(si, SI_SIZE, (UBYTE *)&Debut);
		switch(choix = GetChoix())
		{	case GGID_CHOIX + 0:
				prIntuitionBase(Debut.IntuitionBase);
				break;
		}
	}
}

/***** IntuitionBase (champs publics seulement) ******************/
void prIntuitionBase(struct IntuitionBase *ib)
{
static struct StructureInfo si[] =
{	{	"struct Library ",  "LibNode",      ALIEN, SZ(Library) },
	{	"struct View ",     "ViewLord",     ALIEN, SZ(View),   },
	{	"struct Window *",  "ActiveWindow", S_PTR, PTRSIZE,    },
	{	"struct Screen *",  "ActiveScreen", S_PTR, PTRSIZE,    },
	{	"struct Screen *",  "FirstScreen",  S_PTR, PTRSIZE,    },
	{	"ULONG ",           "Flags",        MOT32, LONGSIZE,   },
	{	"WORD ",            "MouseY",       MOT16, WORDSIZE,   },
	{	"WORD ",            "MouseX",       MOT16, WORDSIZE,   },
	{	"ULONG ",           "Seconds",      MOT32, LONGSIZE,   },
	{	"ULONG ",           "Micros",       MOT32, LONGSIZE,   }
};
SHORT choix = 0;
	while (choix != GGID_RETOUR)
	{	MakeBuffers(si, SI_SIZE, (UBYTE *)IntuitionBase);
		switch (choix = GetChoix())
		{	case GGID_CHOIX + 2:
				prWindow(IntuitionBase->ActiveWindow);
				break;
			case GGID_CHOIX + 3:
				prScreen(IntuitionBase->ActiveScreen);
				break;
			case GGID_CHOIX + 4:
				prScreen(IntuitionBase->FirstScreen);
				break;
		}
	}
}

/***** Screen ****************************************************/
void prScreen(struct Screen *scr)
{
static struct StructureInfo si[] =
{	{	"struct Screen *",    "NextScreen",   S_PTR, PTRSIZE     },
	{	"struct Window *",    "FirstWindow",  S_PTR, PTRSIZE     },
	{	"SHORT ",             "LeftEdge",     MOT16, WORDSIZE    },
	{	"SHORT ",             "TopEdge",      MOT16, WORDSIZE    },
	{	"SHORT ",             "Width",        MOT16, WORDSIZE    },
	{	"SHORT ",             "Height",       MOT16, WORDSIZE    },
	{	"SHORT",              "MouseY",       MOT16, WORDSIZE    },
	{	"SHORT",              "MouseX",       MOT16, WORDSIZE    },
	{	"USHORT ",            "Flags",        MOT16, WORDSIZE    },
	{	"UBYTE *",            "Title",        CHAIN, PTRSIZE     },
	{	"UBYTE *",            "DefaultTitle", CHAIN, PTRSIZE     },
	{	"BYTE ",              "BarHeight",    OCTET, BYTESIZE    },
	{	"BYTE ",              "BarVBorder",   OCTET, BYTESIZE    },
	{	"BYTE ",              "BarHBorder",   OCTET, BYTESIZE    },
	{	"BYTE ",              "MenuVBorder",  OCTET, BYTESIZE    },
	{	"BYTE ",              "MenuHBorder",  OCTET, BYTESIZE    },
	{	"BYTE ",              "WBorTop",      OCTET, BYTESIZE    },
	{	"BYTE ",              "WBorLeft",     OCTET, BYTESIZE    },
	{	"BYTE ",              "WBorRight",    OCTET, BYTESIZE    },
	{	"BYTE ",              "WBorBottom",   OCTET, WORDSIZE    },
	{	"struct TextAttr *",  "Font",         S_PTR, PTRSIZE     },
	{	"struct ViewPort ",   "ViewPort",  STRUC, SZ(ViewPort)   },
	{	"struct RastPort ",   "RastPort",  STRUC, SZ(RastPort)   },
	{	"struct BitMap ",     "BitMap",    STRUC, SZ(BitMap)     },
	{	"struct Layer_Info ", "LayerInfo", ALIEN, SZ(Layer_Info) },
	{	"struct Gadget *",    "FirstGadget",  S_PTR, PTRSIZE     },
	{	"UBYTE ",             "DetailPen",    OCTET, BYTESIZE    },
	{	"UBYTE ",             "BlockPen",     OCTET, BYTESIZE    },
	{	"USHORT ",            "SaveColor0",   MOT16, WORDSIZE    },
	{	"struct Layer *",     "BarLayer",     ALIEN, PTRSIZE     },
	{	"UBYTE *",            "ExtData",      ALIEN, PTRSIZE     },
	{	"UBYTE *",            "UserData",     ALIEN, PTRSIZE     }
};
SHORT choix = 0;
	while (choix != GGID_RETOUR)
	{	MakeBuffers(si, SI_SIZE, (UBYTE *)scr);
		switch (choix = GetChoix())
		{	case GGID_CHOIX + 0:
				prScreen(scr->NextScreen);
				break;
			case GGID_CHOIX + 1:
				prWindow(scr->FirstWindow);
				break;
			case GGID_CHOIX + 20:
				prTextAttr(scr->Font);
				break;
			case GGID_CHOIX + 21:
				prViewPort(&scr->ViewPort);
				break;
			case GGID_CHOIX + 22:
				prRastPort(&scr->RastPort);
				break;
			case GGID_CHOIX + 23:
				prBitMap(&scr->BitMap);
				break;
			case GGID_CHOIX + 25:
				prGadget(scr->FirstGadget);
				break;
		}
	}
}

/***** Window ****************************************************/
void prWindow(struct Window *win)
{
static struct StructureInfo si[] =
{	{	"struct Window *",       "NextWindow",   S_PTR, PTRSIZE  },
	{	"SHORT ",                "LeftEdge",     MOT16, WORDSIZE },
	{	"SHORT ",                "TopEdge",      MOT16, WORDSIZE },
	{	"SHORT ",                "Width",        MOT16, WORDSIZE },
	{	"SHORT ",                "Height",       MOT16, WORDSIZE },
	{	"SHORT ",                "MouseY",       MOT16, WORDSIZE },
	{	"SHORT ",                "MouseX",       MOT16, WORDSIZE },
	{	"SHORT ",                "MinWidth",     MOT16, WORDSIZE },
	{	"SHORT ",                "MinHeight",    MOT16, WORDSIZE },
	{	"USHORT ",               "MaxWidth",     MOT16, WORDSIZE },
	{	"USHORT ",               "MaxHeight",    MOT16, WORDSIZE },
	{	"ULONG ",                "Flags",        MOT32, LONGSIZE },
	{	"struct Menu *",         "MenuStrip",    S_PTR, PTRSIZE  },
	{	"UBYTE *",               "Title",        CHAIN, PTRSIZE  },
	{	"struct Requester *",    "FirstRequest", ALIEN, PTRSIZE  },
	{	"struct Requester *",    "DMRequest",    ALIEN, PTRSIZE  },
	{	"SHORT ",                "ReqCount",     MOT16, WORDSIZE },
	{	"struct Screen *",       "WScreen",      S_PTR, PTRSIZE  },
	{	"struct RastPort *",     "RPort",        S_PTR, PTRSIZE  },
	{	"BYTE ",                 "BorderLeft",   OCTET, BYTESIZE },
	{	"BYTE ",                 "BorderTop",    OCTET, BYTESIZE },
	{	"BYTE ",                 "BorderRight",  OCTET, BYTESIZE },
	{	"BYTE ",                 "BorderBottom", OCTET, BYTESIZE },
	{	"struct RastPort *",     "BorderRPort",  S_PTR, PTRSIZE  },
	{	"struct Gadget *",       "FirstGadget",  S_PTR, PTRSIZE  },
	{	"struct Window *",       "Parent",       S_PTR, PTRSIZE  },
	{	"struct Window *",       "Descendant",   S_PTR, PTRSIZE  },
	{	"USHORT *",              "Pointer",      ALIEN, PTRSIZE  },
	{	"BYTE ",                 "PtrHeight",    OCTET, BYTESIZE },
	{	"BYTE ",                 "PtrWidth",     OCTET, BYTESIZE },
	{	"BYTE ",                 "XOffset",      OCTET, BYTESIZE },
	{	"BYTE ",                 "YOffset",      OCTET, BYTESIZE },
	{	"ULONG ",                "IDCMPFlags",   MOT32, LONGSIZE },
	{	"struct MsgPort *",      "UserPort",     ALIEN, PTRSIZE  },
	{	"struct MsgPort *",      "WindowPort",   ALIEN, PTRSIZE  },
	{	"struct IntuiMessage *", "MessageKey",   ALIEN, PTRSIZE  },
	{	"UBYTE ",                "DetailPen",    OCTET, BYTESIZE },
	{	"UBYTE ",                "BlockPen",     OCTET, BYTESIZE },
	{	"struct Image *",        "CheckMark",    S_PTR, PTRSIZE  },
	{	"UBYTE *",               "ScreenTitle",  CHAIN, PTRSIZE  },
	{	"SHORT ",                "GZZMouseX",    MOT16, WORDSIZE },
	{	"SHORT ",                "GZZMouseY",    MOT16, WORDSIZE },
	{	"SHORT ",                "GZZWidth",     MOT16, WORDSIZE },
	{	"SHORT ",                "GZZHeight",    MOT16, WORDSIZE },
	{	"UBYTE *",               "ExtData",      ALIEN, PTRSIZE  },
	{	"BYTE *",                "UserData",     ALIEN, PTRSIZE  },
	{	"struct Layer *",        "WLayer",       ALIEN, PTRSIZE  },
	{   "struct TextFont *",     "IFont",        S_PTR, PTRSIZE  }
};
SHORT choix = 0;
	while (choix != GGID_RETOUR)
	{	MakeBuffers(si, SI_SIZE, (UBYTE *)win);
		switch (choix = GetChoix())
		{	case GGID_CHOIX + 0:
				prWindow(win->NextWindow);
				break;
			case GGID_CHOIX + 12:
				prMenu(win->MenuStrip);
				break;
			case GGID_CHOIX + 17:
				prScreen(win->WScreen);
				break;
			case GGID_CHOIX + 18:
				prRastPort(win->RPort);
				break;
			case GGID_CHOIX + 23:
				prRastPort(win->BorderRPort);
				break;
			case GGID_CHOIX + 24:
				prGadget(win->FirstGadget);
				break;
			case GGID_CHOIX + 25:
				prWindow(win->Parent);
				break;
			case GGID_CHOIX + 26:
				prWindow(win->Descendant);
				break;
			case GGID_CHOIX + 38:
				prImage(win->CheckMark);
				break;
			case GGID_CHOIX + 47:
				prTextFont(win->IFont);
				break;
		}
	}
}

/***** TextAttr **************************************************/
void prTextAttr(struct TextAttr *ta)
{
static struct StructureInfo si[] =
{	{	"STRPTR ", "ta_Name",  CHAIN, PTRSIZE  },
	{	"UWORD ",  "ta_YSize", MOT16, WORDSIZE },
	{	"UBYTE ",  "ta_Style", OCTET, BYTESIZE },
	{	"UBYTE ",  "ta_Flags", OCTET, BYTESIZE }
};
SHORT choix = 0;
	while (choix != GGID_RETOUR)
	{	MakeBuffers(si, SI_SIZE, (UBYTE *)ta);
		choix = GetChoix();
	}
}

/***** TextFont **************************************************/
void prTextFont(struct TextFont *tf)
{
static struct StructureInfo si[] =
{	{	"struct Message *", "tf_Message",   ALIEN, PTRSIZE  },
	{	"UWORD ",           "tf_YSize",     MOT16, WORDSIZE },
	{	"UBYTE ",           "tf_Style",     OCTET, BYTESIZE },
	{	"UBYTE ",           "tf_Flags",     OCTET, BYTESIZE },
	{	"UWORD ",           "tf_XSize",     MOT16, WORDSIZE },
	{	"UWORD ",           "tf_Baseline",  MOT16, WORDSIZE },
	{	"UWORD ",           "tf_BoldSmear", MOT16, WORDSIZE },
	{	"UWORD ",           "tf_Accessors", MOT16, WORDSIZE },
	{	"UBYTE ",           "tf_LoChar",    OCTET, BYTESIZE },
	{	"UBYTE ",           "tf_HiChar",    OCTET, BYTESIZE },
	{	"APTR ",            "tf_CharData",  ALIEN, PTRSIZE  },
	{	"UWORD ",           "tf_Modulo",    MOT16, WORDSIZE },
	{	"APTR ",            "tf_CharLoc",   ALIEN, PTRSIZE  },
	{	"APTR ",            "tf_CharSpace", ALIEN, PTRSIZE  },
	{	"APTR ",            "tf_CharKern",  ALIEN, PTRSIZE  }
};
SHORT choix = 0;
	while (choix != GGID_RETOUR)
	{	MakeBuffers(si, SI_SIZE, (UBYTE *)tf);
		choix = GetChoix();
	}
}

/***** ViewPort **************************************************/
void prViewPort(struct ViewPort *vp)
{
static struct StructureInfo si[] =
{	{	"struct ViewPort *", "Next",     S_PTR, PTRSIZE  },
	{	"struct ColorMap *", "ColorMap", ALIEN, PTRSIZE  },
	{	"struct CopList *",  "DspIns",   ALIEN, PTRSIZE  },
	{	"struct CopList *",  "SprIns",   ALIEN, PTRSIZE  },
	{	"struct CopList *",  "ClrIns",   ALIEN, PTRSIZE  },
	{	"struct UCopList *", "UCopIns",  ALIEN, PTRSIZE  },
	{	"SHORT ",            "DWidth",   MOT16, WORDSIZE },
	{	"SHORT ",            "Dheight",  MOT16, WORDSIZE },
	{	"SHORT ",            "DxOffset", MOT16, WORDSIZE },
	{	"SHORT ",            "DyOffset", MOT16, WORDSIZE },
	{	"USHORT ",           "Modes",    MOT16, WORDSIZE },
	{	"UBYTE ",    "SpritePriorities", OCTET, BYTESIZE },
	{	"UBYTE ",            "reserved", OCTET, BYTESIZE },
	{	"struct RasInfo *",  "RasInfo",  ALIEN, PTRSIZE  }
};
SHORT choix = 0;
	while (choix != GGID_RETOUR)
	{	MakeBuffers(si, SI_SIZE, (UBYTE *)vp);
		switch(choix = GetChoix())
		{	case GGID_CHOIX + 0:
				prViewPort(vp->Next);
				break;
		}
	}
}

/***** RastPort **************************************************/
void prRastPort(struct RastPort *rp)
{
static struct StructureInfo si[] =
{	{	"struct Layer *",    "Layer",       ALIEN, PTRSIZE  },
	{	"struct BitMap *",   "BitMap",      S_PTR, PTRSIZE  },
	{	"USHORT *",          "AreaPtrn",    ALIEN, PTRSIZE  },
	{	"struct TmpRas *",   "TmpRas",      ALIEN, PTRSIZE  },
	{	"struct AreaInfo *", "AreaInfo",    ALIEN, PTRSIZE  },
	{	"struct GelsInfo *", "GelsInfo",    ALIEN, PTRSIZE  },
	{	"UBYTE ",            "Mask",        OCTET, BYTESIZE },
	{	"BYTE ",             "FgPen",       OCTET, BYTESIZE },
	{	"BYTE ",             "BgPen",       OCTET, BYTESIZE },
	{	"BYTE ",             "AOlPen",      OCTET, BYTESIZE },
	{	"BYTE ",             "DrawMode",    OCTET, BYTESIZE },
	{	"BYTE ",             "AreaPtSz",    OCTET, BYTESIZE },
	{	"BYTE ",             "linpatcnt",   OCTET, BYTESIZE },
	{	"BYTE ",             "dummy",       OCTET, BYTESIZE },
	{	"USHORT ",           "Flags",       MOT16, WORDSIZE },
	{	"USHORT ",           "LinePtrn",    MOT16, WORDSIZE },
	{	"SHORT ",            "cp_x",        MOT16, WORDSIZE },
	{	"SHORT ",            "cp_y",        MOT16, WORDSIZE },
	{	"UBYTE ",            "minterms[8]", TABLO, BYTESIZE * 8 },
	{	"SHORT ",            "PenWidth",    MOT16, WORDSIZE },
	{	"SHORT ",            "PenHeight",   MOT16, WORDSIZE },
	{	"struct TextFont *", "Font",        S_PTR, PTRSIZE  },
	{	"UBYTE ",            "AlgoStyle",   OCTET, BYTESIZE },
	{	"UYBTE ",            "TxFlags",     OCTET, BYTESIZE },
	{	"UWORD ",            "TxHeight",    MOT16, WORDSIZE },
	{	"UWORD ",            "TxWidth",     MOT16, WORDSIZE },
	{	"UWORD ",            "TxBaseline",  MOT16, WORDSIZE },
	{	"WORD ",             "TxSpacing",   MOT16, WORDSIZE },
	{	"APTR *",            "RP_User",     ALIEN, PTRSIZE  },
	{	"ULONG ",       "longreserved[2]",  TABLO, LONGSIZE * 2 },
	{	"UWORD ",       "wordreserved[7]",  TABLO, WORDSIZE * 7 },
	{	"UBYTE ",            "reserved[8]", TABLO, BYTESIZE * 8 }
};
SHORT choix = 0;

	while (choix != GGID_RETOUR)
	{	MakeBuffers(si, SI_SIZE, (UBYTE *)rp);
		switch(choix = GetChoix())
		{	case GGID_CHOIX + 1:
				prBitMap(rp->BitMap);
				break;
			case GGID_CHOIX + 18:
				HexDump((UBYTE *)&rp->minterms, 8, OCTET);
				break;
			case GGID_CHOIX + 21:
				prTextFont(rp->Font);
				break;
			case GGID_CHOIX + 29:
				HexDump((UBYTE *)&rp->longreserved, 2, MOT32);
				break;
			case GGID_CHOIX + 30:
				HexDump((UBYTE *)&rp->wordreserved, 7, MOT16);
				break;
			case GGID_CHOIX + 31:
				HexDump((UBYTE *)&rp->reserved, 8, OCTET);
				break;
		}
	}
}

/***** BitMap ****************************************************/
void prBitMap(struct BitMap *bm)
{
static struct StructureInfo si[] =
{	{	"UWORD ",    "BytesPerRow", MOT16, WORDSIZE },
	{	"UWORD ",    "Rows",        MOT16, WORDSIZE },
	{	"UBYTE ",    "Flags",       OCTET, BYTESIZE },
	{	"UBYTE ",    "Depth",       OCTET, BYTESIZE },
	{	"UWORD ",    "Pad",         MOT16, WORDSIZE },
	{	"PLANEPTR ", "Planes[8]",   TABLO, LONGSIZE * 8 }
};
SHORT choix = 0;
	while (choix != GGID_RETOUR)
	{	MakeBuffers(si, SI_SIZE, (UBYTE *)bm);
		switch(choix = GetChoix())
		{	case GGID_CHOIX + 5 : 
				HexDump((UBYTE *)&bm->Planes, 8, MOT32);
				break;
		}
	}
}

/***** Gadget ****************************************************/
void prGadget(struct Gadget *gg)
{
static struct StructureInfo si[] =
{	{	"struct Gadget *",    "NextGadget",    S_PTR, PTRSIZE  },
	{	"SHORT ",             "LeftEdge",      MOT16, WORDSIZE },
	{	"SHORT ",             "TopEdge",       MOT16, WORDSIZE },
	{	"SHORT ",             "Width",         MOT16, WORDSIZE },
	{	"SHORT ",             "Height",        MOT16, WORDSIZE },
	{	"USHORT ",            "Flags",         MOT16, WORDSIZE },
	{	"USHORT ",            "Activation",    MOT16, WORDSIZE },
	{	"USHORT ",            "GadgetType",    MOT16, WORDSIZE },
	{	"APTR ",              "GadgetRender",  S_PTR, PTRSIZE  },
	{	"APTR ",              "SelectRender",  S_PTR, PTRSIZE  },
	{	"struct IntuiText *", "GadgetText",    S_PTR, PTRSIZE  },
	{	"LONG ",              "MutualExclude", MOT32, LONGSIZE },
	{	"APTR ",              "SpecialInfo",   ALIEN, PTRSIZE  },
	{	"USHORT ",            "GadgetID",      MOT16, WORDSIZE },
	{	"APTR ",              "UserData",      ALIEN, PTRSIZE  }
};
SHORT choix = 0;
	while (choix != GGID_RETOUR)
	{	MakeBuffers(si, SI_SIZE, (UBYTE *)gg);
		switch(choix = GetChoix())
		{	case GGID_CHOIX + 0:
				prGadget(gg->NextGadget);
				break;
			case GGID_CHOIX + 8:
				if (gg->Flags & GADGIMAGE)
					prImage((struct Image *)gg->GadgetRender);
				else
					prBorder((struct Border *)gg->GadgetRender);
				break;
			case GGID_CHOIX + 9:
				if (gg->Flags & GADGHIMAGE)
					prImage((struct Image *)gg->SelectRender);
				else
					prBorder((struct Border *)gg->SelectRender);
				break;
			case GGID_CHOIX + 10:
				prIntuiText(gg->GadgetText);
				break;
		}
	}
}

/***** Menu ******************************************************/
void prMenu(struct Menu *mnu)
{
static struct StructureInfo si[] =
{	{	"struct Menu *",     "NextMenu",  S_PTR, PTRSIZE  },
	{	"SHORT ",            "LeftEdge",  MOT16, WORDSIZE },
	{	"SHORT ",            "TopEdge",   MOT16, WORDSIZE },
	{	"SHORT ",            "Width",     MOT16, WORDSIZE },
	{	"SHORT ",            "Height",    MOT16, WORDSIZE },
	{	"USHORT ",           "Flags",     MOT16, WORDSIZE },
	{	"UBYTE *",           "MenuName",  CHAIN, PTRSIZE  },
	{	"struct MenuItem *", "FirstItem", S_PTR, PTRSIZE  },
	{	"SHORT ",            "JazzX",     MOT16, WORDSIZE },
	{	"SHORT ",            "JazzY",     MOT16, WORDSIZE },
	{	"SHORT ",            "BeatX",     MOT16, WORDSIZE },
	{	"SHORT ",            "BeatY",     MOT16, WORDSIZE }
};
SHORT choix = 0;
	while (choix != GGID_RETOUR)
	{	MakeBuffers(si, SI_SIZE, (UBYTE *)mnu);
		switch(choix = GetChoix())
		{	case GGID_CHOIX + 0:
				prMenu(mnu->NextMenu);
				break;
			case GGID_CHOIX + 7:
				prMenuItem(mnu->FirstItem);
				break;
		}
	}
}

/***** MenuItem **************************************************/
void prMenuItem(struct MenuItem *itm)
{
static struct StructureInfo si[] =
{	{	"struct MenuItem *", "NextItem",      S_PTR, PTRSIZE  },
	{	"SHORT ",            "LeftEdge",      MOT16, WORDSIZE },
	{	"SHORT ",            "TopEdge",       MOT16, WORDSIZE },
	{	"SHORT ",            "Width",         MOT16, WORDSIZE },
	{	"SHORT ",            "Height",        MOT16, WORDSIZE },
	{	"USHORT ",           "Flags",         MOT16, WORDSIZE },
	{	"LONG ",             "MutualExclude", MOT32, LONGSIZE },
	{	"APTR ",             "ItemFill",      S_PTR, PTRSIZE  },
	{	"APTR ",             "SelectFill",    S_PTR, PTRSIZE  },
	{	"BYTE ",             "Command",       CARAC, WORDSIZE },
	{	"struct MenuItem *", "SubItem",       S_PTR, PTRSIZE  },
	{	"USHORT ",           "NextSelect",    MOT16, WORDSIZE }
};
SHORT choix = 0;
	while (choix != GGID_RETOUR)
	{	MakeBuffers(si, SI_SIZE, (UBYTE *)itm);
		switch(choix = GetChoix())
		{	case GGID_CHOIX + 0:
				prMenuItem(itm->NextItem);
				break;
			case GGID_CHOIX + 7:
				if (itm->Flags & ITEMTEXT)
					prIntuiText((struct IntuiText *)itm->ItemFill);
				else
					prImage((struct Image *)itm->ItemFill);
				break;
			case GGID_CHOIX + 8:
				if (itm->Flags & ITEMTEXT)
					prIntuiText((struct IntuiText *)itm->SelectFill);
				else
					prImage((struct Image *)itm->SelectFill);
				break;
			case GGID_CHOIX + 10:
				prMenuItem(itm->SubItem);
				break;
		}
	}
}

/***** Image *****************************************************/
void prImage(struct Image *img)
{
static struct StructureInfo si[] =
{	{	"SHORT ",         "LeftEdge",   MOT16, WORDSIZE },
	{	"SHORT ",         "TopEdge",    MOT16, WORDSIZE },
	{	"SHORT ",         "Width",      MOT16, WORDSIZE },
	{	"SHORT ",         "Height",     MOT16, WORDSIZE },
	{	"SHORT ",         "Depth",      MOT16, WORDSIZE },
	{	"USHORT *",       "ImageData",  ALIEN, PTRSIZE  },
	{	"UBYTE ",         "PlanePick",  OCTET, BYTESIZE },
	{	"UBYTE ",         "PlaneOnOff", OCTET, BYTESIZE },
	{	"struct Image *", "NextImage",  S_PTR, PTRSIZE  }
};
SHORT choix = 0;
	while (choix != GGID_RETOUR)
	{	MakeBuffers(si, SI_SIZE, (UBYTE *)img);
		switch(choix = GetChoix())
		{	case GGID_CHOIX + 8:
				prImage(img->NextImage);
				break;
		}
	}
}

/***** IntuiText *************************************************/
void prIntuiText(struct IntuiText *it)
{
static struct StructureInfo si[] =
{	{	"UBYTE ",             "FrontPen",  OCTET, BYTESIZE },
	{	"UBYTE ",             "BackPen",   OCTET, BYTESIZE },
	{	"UBYTE ",             "DrawMode",  OCTET, WORDSIZE },
	{	"SHORT ",             "LeftEdge",  MOT16, WORDSIZE },
	{	"SHORT ",             "TopEdge",   MOT16, WORDSIZE },
	{	"struct TextAttr *",  "ITextFont", S_PTR, PTRSIZE  },
	{	"UBYTE *",            "IText",     CHAIN, PTRSIZE  },
	{	"struct IntuiText *", "NextText",  S_PTR, PTRSIZE  }
};
SHORT choix = 0;
	while (choix != GGID_RETOUR)
	{	MakeBuffers(si, SI_SIZE, (UBYTE *)it);
		switch(choix = GetChoix())
		{	case GGID_CHOIX + 5:
				prTextAttr(it->ITextFont);
				break;
			case GGID_CHOIX + 7:
				prIntuiText(it->NextText);
				break;
		}
	}
}

/***** Border ****************************************************/
void prBorder(struct Border *brd)
{
static struct StructureInfo si[] =
{	{	"SHORT ",          "LeftEdge",   MOT16, WORDSIZE },
	{	"SHORT ",          "TopEdge",    MOT16, WORDSIZE },
	{	"UBYTE ",          "FrontPen",   OCTET, BYTESIZE },
	{	"UBYTE ",          "BackPen",    OCTET, BYTESIZE },
	{	"UBYTE ",          "DrawMode",   OCTET, BYTESIZE },
	{	"BYTE ",           "Count",      OCTET, BYTESIZE },
	{	"SHORT *",         "XY",         TABLO, PTRSIZE  },
	{	"struct Border *", "NextBorder", S_PTR, PTRSIZE  }
};
SHORT choix = 0;
	while (choix != GGID_RETOUR)
	{	MakeBuffers(si, SI_SIZE, (UBYTE *)brd);
		switch(choix = GetChoix())
		{	case GGID_CHOIX + 6:
				HexDump((UBYTE *)brd->XY, brd->Count * 2, MOT16);
				break;
			case GGID_CHOIX + 7:
				prBorder(brd->NextBorder);
				break;
		}
	}
}

Listing 4 (SpyGadgets.c)

#include <intuition/intuition.h>

#include "Spy.h"

/******************************************************************
 * Gadgets de choix des structures à visionner                    *
 *****************************************************************/
struct Gadget ChoixGadget[MAX_LINES];

/******************************************************************
 * Gadget Slider                                                  *
 *****************************************************************/
struct PropInfo SliderInfo =
{	AUTOKNOB|FREEVERT, MAXPOT, MAXPOT, MAXBODY, MAXBODY
};

struct Image SliderImage =
{	0, 0, 8, 154, 0, NULL, 0x00,0x01, NULL
};

struct Gadget SliderGadget =
{	NULL,
	-15, 10, 16, -10,
	GADGIMAGE|GRELRIGHT|GRELHEIGHT,
	RELVERIFY|GADGIMMEDIATE|RIGHTBORDER,
	PROPGADGET,
	(APTR)&SliderImage,
	NULL, NULL, NULL, (APTR)&SliderInfo, GGID_SLIDER, NULL
};

/******************************************************************
 * Gadget "Retour"                                                *
 *****************************************************************/
SHORT RetourVectors[] =
{	0, 0, 101, 0, 101, 11, 0, 11, 0, 0
};

struct Border RetourBorder =
{	-1, -1, 3, 0, JAM1, 5, RetourVectors, NULL
};

struct IntuiText RetourText =
{	1, 0, JAM2, 26, 1, NULL, "Retour", NULL
};

struct Gadget RetourGadget =
{	&SliderGadget,
	15, -15, 100, 10,
	GRELBOTTOM,
	RELVERIFY|BOTTOMBORDER,
	BOOLGADGET,
	(APTR)&RetourBorder,
	NULL,
	&RetourText, NULL, NULL, GGID_RETOUR, NULL
};

/******************************************************************
 * Fenêtre                                                        *
 *****************************************************************/
struct NewWindow nw =
{	0, 11, 640, 194,
	-1, -1,
	CLOSEWINDOW|GADGETUP|RAWKEY,
	WINDOWCLOSE|WINDOWDRAG|WINDOWDEPTH|ACTIVATE,
	&RetourGadget,
	NULL,
	"Spy - par Max pour ANT",
	NULL, NULL,
	0, 0, 0, 0,
	WBENCHSCREEN
};

/******************************************************************
 * PrepareGadgets() - Initialise les gadgets de choix             *
 *****************************************************************/
void PrepareGadgets(void)
{
register WORD i;

	for (i = 0; i < MAX_LINES; i++)
	{	register struct Gadget *g = &ChoixGadget[i];

		g->NextGadget    = NULL;
		g->LeftEdge      = 10;
		g->TopEdge       = (i * 10) + TOP_LINE;
		g->Width         = -36;
		g->Height        = 10;
		g->Flags         = GADGHCOMP|GRELWIDTH;
		g->Activation    = RELVERIFY;
		g->GadgetType    = BOOLGADGET;
		g->GadgetRender  = NULL;
		g->SelectRender  = NULL;
		g->MutualExclude = NULL;
		g->SpecialInfo   = NULL;
		g->GadgetID      = GGID_CHOIX;
		g->UserData      = NULL;
	}
}



[Retour en haut] / [Retour aux articles]