Obligement - L'Amiga au maximum

Jeudi 25 avril 2024 - 10:15  

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 - Requête flexible de gadgets de chaîne de caractères utilisant l'allocation dynamique de mémoire
(Article écrit par Randy Finch et extrait du Randy Finch's Web Site - février 1990)


J'ai travaillé sur un programme en C (sur AmigaOS 1.3) qui nécessite plusieurs requêtes contenant uniquement des gadgets de type chaîne de caractères et deux gadgets booléens ("OK" et "Cancel"). Le problème que j'ai rencontré est que chaque requête a besoin d'un nombre différent de gadgets de type chaîne. Ne voulant pas écrire une fonction différente pour chaque requête, j'ai décidé d'écrire une fonction capable de générer toutes les requêtes dont j'avais besoin. Pour accomplir cette tâche, l'allocation dynamique de la mémoire a été utilisée.

Allocation dynamique de la mémoire sur l'Amiga

Après avoir étudié les différentes méthodes d'allocation de la mémoire sur Amiga, j'ai décidé qu'utiliser la fonction AllocRemember fournie par la bibliothèque Intuition serait la méthode la plus simple. Cette fonction crée une liste liée de blocs mémoire en utilisant une structure Remember (définie dans intuition.h). Une structure Remember a la forme suivante :

struct Remember {
		struct Remember *NextRemember;
		ULONG  RememberSize;
		UBYTE *Memory;
	}

Cette structure contient un pointeur vers une autre structure Remember, un entier long non signé contenant la taille du bloc mémoire, et un pointeur vers le bloc mémoire alloué. Le pointeur NextRemember rend possible la liste liée de blocs mémoire.

Afin de créer une liste liée, un pointeur vers une structure Remember doit être déclaré et initialisé à NULL comme suit :

	struct Remember *MyMemBlocks = NULL ;

Supposons que deux blocs mémoire, l'un de 100 octets et l'autre de 200 octets, soient nécessaires au programme. La fonction AllocRemember est appelée comme suit :

	mem_pointer1 = AllocRemember(&MyMemBlocks,100,MEMF_CLEAR) ;

Le premier argument est l'adresse du pointeur de la structure Remember. Il est important de garder à l'esprit que ce n'est pas un pointeur vers une structure Remember, mais un pointeur vers ce pointeur. Ceci est illustré dans la figure 1.

C

Le deuxième argument est la quantité mémoire à allouer, dans ce cas 100 octets. Le troisième argument contient des drapeaux (définis dans memory.h) ; MEMF_CLEAR signifie remplir le bloc mémoire avec des zéros après l'allocation. Les autres drapeaux incluent :

MEMF_FAST		Allocate fast (external) memory
	MEMF_CHIP		Allocate chip (internal 512K) memory
	MEMF_PUBLIC		Allocate memory for different tasks or interrupt code
				   such as task control blocks, messages, ports, etc.

Si aucun des drapeaux ci-dessus n'est activé, MEMF_FAST est supposé être le premier. Si aucune mémoire Fast n'est disponible, la mémoire Chip est utilisée.

La fonction AllocRemember renvoie un pointeur vers le bloc mémoire alloué si elle est réussie ou NULL si elle échoue. AllocRemember effectue en fait deux allocations de mémoire, une pour la structure Remember et une pour le bloc mémoire demandé. Il remplit également la structure Remember et définit la variable MyMemBlocks pour qu'elle pointe sur la structure. Ceci est représenté graphiquement dans les Figures 2a et 2b.

C

Afin d'allouer le bloc mémoire de 200 octets, la fonction AllocRemember est à nouveau appelée de la même manière que précédemment.

	mem_pointer2 = AllocRemember(&MyMemBlocks,200,MEMF_CLEAR) ;

Ici, la fonction crée une autre structure Remember et définit l'élément NextRemember de la structure Remember précédente pour qu'il pointe vers cette nouvelle structure. De plus, un bloc mémoire de 200 octets est alloué (voir figure 2c).

En raison de la manière dont la fonction AllocRemember est appelée, il est très facile d'allouer plusieurs blocs mémoire de taille égale. Par exemple, pour créer 10 blocs mémoire qui contiendront chacun une structure IntuiText, la méthode présentée dans le listing 1 peut être utilisée.

Listing 1

           Fragment de code C illustrant comment allouer
      Dix blocs de mémoire à utiliser pour les structures IntuiText

     UBYTE *pointer;
     ULONG i;
     struct Remember *IntuiTextBlocks = NULL;
     ...
     ...
     for( i = 0 ; i < 10 ; ++i)  {
          pointer = AllocRemember(&IntuiTextBlocks,
                      sizeof(struct IntuiText), MEMF_CLEAR);

            /* Exit if allocation fails */

          if (pointer = NULL) ExitRoutine();
     }
     ...
     ...

Après l'exécution de ce code, IntuiTextBlocks pointera vers la première des 10 structures Remember qui sont liées entre elles par les pointeurs NextRemember. Chaque bloc mémoire est accessible via l'élément Memory de la structure Remember correspondante. Ces pointeurs peuvent être convertis en "pointeur vers une structure IntuiText", puis les blocs mémoire peuvent être remplis de données, comme le montre le listing 2.

Listing 2

	   Fragment de code C illustrant la manière de remplir
           dix blocs de mémoire avec des informations IntuiText

  UBYTE  i;
  STRPTR Titles[10];
  struct Remember  *ITextPointer;
  struct Remember  *IntuiTextBlocks;
  struct IntuiText *CurITextPointer;
  ...
  ...

  /*  Assign temporary pointer to Remember structures  */

  ITextPointer = IntuiTextBlocks;

  for (i = 0; i < 10; ++i) {

     /*  Cast a memory block pointer to IntuiText structure
         pointer  */

     CurITextPointer = (struct IntuiText *) ITextPointer->Memory;

     CurITextPointer->FrontPen  = 0;
     CurITextPointer->BackPen   = 1;
     CurITextPointer->DrawMode  = JAM2;
     CurITextPointer->LeftEdge  = 80;
     CurITextPointer->TopEdge   = 0;
     CurITextPointer->ITextFont = NULL;
     CurITextPointer->IText     = Titles[i];
     CurITextPointer->NextText  = NULL;

     /*  Get next memory block in the linked list  */

     ITextPointer = ITextPointer->NextRemember;

  }

  ...
  ...

Lorsque les blocs mémoire ne sont plus nécessaires, la fonction FreeRemember peut être appelée.

	FreeRemember(&IntuiTextBlocks, TRUE);

Cette fonction va désallouer tous les blocs mémoire de la liste ainsi que la mémoire utilisée par les structures Remember. Si le deuxième argument est "FALSE" (FAUX), toutes les structures Remember seront effacées mais les blocs mémoire resteront intacts.

La méthode qui vient d'être décrite a été utilisée pour allouer dynamiquement de la mémoire pour diverses structures et tampons mémoire dans une fonction qui peut créer une requête contenant un nombre variable de gadgets de chaîne. Cette fonction est intitulée "StringsRequest" et fait partie du programme intitulé "StrReq.c" présenté dans le listing 3.

La fonction StringsRequest

Six listes liées distinctes de blocs mémoire sont utilisées dans la fonction StringsRequest. Quatre de ces listes liées contiennent chacune des structures Remember NumEntrys, où "NumEntrys" est le nombre de gadgets de chaîne de caractères requis dans la requête. Ces structures Remember pointent vers des blocs mémoire contenant toutes les structures Gadget et leurs structures IntuiText et StringInfo associées, ainsi que la mémoire tampon pour les chaînes de gadgets. Les cinquième et sixième listes liées ne contiennent en fait qu'une seule structure Remember chacune. L'une pointe vers un bloc mémoire contenant une structure Requester tandis que l'autre pointe vers un tampon d'annulation.

Les structures IntuiText fournissent des informations sur le texte lié à chaque gadget. Ce texte apparaît à gauche de chaque gadget de chaîne et peut être utilisé pour identifier le type d'information que l'utilisateur doit fournir dans le gadget. Les structures StringInfo fournissent des informations sur les chaînes de caractères qui apparaissent réellement dans les gadgets. L'une des informations de cette structure est un pointeur vers un tampon où le texte réel est stocké. Il existe un tampon distinct pour chaque gadget. La structure contient également un pointeur vers un tampon d'annulation. Ce tampon mémoire est rempli avec une copie d'un tampon mémoire de gadget de chaîne de caractères lorsque le gadget est sélectionné pour la première fois. Une fois les modifications apportées à la chaîne de caractères dans le gadget, l'utilisateur peut revenir au contenu original du gadget en appuyant sur les touches "Amiga droite+Q". Un seul tampon d'annulation est suffisant pour tous les gadgets, car un seul gadget peut être actif à la fois. La structure de requête relie toutes les informations ci-dessus.

Utilisation de la fonction StringsRequest

La fonction StringsRequest est de type "Bool" ; elle renvoie "TRUE" (VRAI) si la requête est ouverte et fermée avec succès, sinon elle renvoie "FASLE" (FAUX). Les huit paramètres passés à la fonction sont décrits dans le tableau ci-dessous.

Tableau 1 : description des huit paramètres à passer à la fonction StringsRequest
  • HeaderText : pointeur vers une chaîne de caractères à terminaison nulle contenant le texte à centrer en haut de la page de la requête.
  • NumEntrys : nombre de gadgets de chaîne devant apparaître dans la requête.
  • BoxWidth : tableau de nombres entiers courts contenant la largeur, en caractères, des cases devant contenir les chaînes de caractères dans les gadgets. Ce tableau doit comporter au moins "NumEntrys" éléments.
  • Titles : ttableau de pointeurs vers des chaînes à terminaison nulle contenant le texte devant apparaître à la gauche de chaque gadget de chaîne. Ce texte permet d'identifier le type d'information que contient chaque gadget de chaîne. Ce tableau doit comporter au moins "NumEntrys" éléments.
  • DefText : tableau de pointeurs vers des chaînes de caractères à terminaison nulle contenant le texte initial devant apparaître à l'intérieur de chaque gadget de chaîne. Assurez-vous que les tampons mémoire contenant les chaînes sont suffisamment longs pour contenir leurs longueurs de chaîne maximale respective. Ce tableau doit comporter au moins "NumEntrys" éléments.
  • MaxLenDefText : tableau de petits nombres entiers contenant la longueur maximale des chaînes de caractères dans chaque gadget de chaîne. Cette longueur inclut le terminateur nul. Ce tableau doit comporter au moins "NumEntrys" éléments.
  • TypeDefText : tableau d'entiers courts contenant soit un zéro, soit un LONGINT (défini dans intuition.h). Un zéro indique que le gadget correspondant est un gadget standard de type chaîne de caractères standard. LONGINT indique que le gadget ne doit accepter que des entiers longs. Ce tableau doit comporter au moins "NumEntrys" éléments.
  • Window : pointeur vers la structure Window de la fenêtre dans laquelle la requête apparaîtra.
Intuition ne permet pas à un gadget de chaîne de caractères d'être plus large que la longueur maximale de la chaîne qu'il contient. Par conséquent, si un élément du tableau MaxLenDefText est plus petit que l'élément correspondant du tableau BoxWidth, la largeur du gadget sera égale à MaxLenDefText plutôt qu'à BoxWidth. La fonction StringsRequest en tient compte lorsqu'elle détermine la taille de la requête.

Si un élément du tableau TypeDefText est égal à LONGINT, Intuition n'autorisera la saisie que d'entiers longs dans le gadget de chaîne. Ceci est utile si l'information requise est un nombre. La valeur initiale dans l'élément correspondant du tableau DefText doit toujours être une chaîne de caractères ; il est donc nécessaire de convertir le long entier en une chaîne ASCII avant d'appeler StringsRequest. Une fois que la fonction renvoie le contrôle à la routine d'appel, la chaîne ASCII doit être reconvertie en un nombre entier.

La fonction StringsRequest utilise les informations fournies par ses paramètres pour déterminer la largeur et la hauteur nécessaires de la requête afin qu'elle puisse contenir les gadgets de chaîne et le texte associé. Elle commence par allouer la quantité de mémoire requise, remplit cette mémoire avec toutes les structures de données nécessaires, puis affiche la requête. La figure 3 montre un exemple de requête contenant cinq gadgets de type chaîne.

C

Comme les gadgets sont affichés en colonnes, la requête est limitée à 10 gadgets de chaîne dans une fenêtre plein écran en mode non entrelacé ou à 20 gadgets en mode entrelacé.

La requête contient également deux gadgets booléens, l'un affichant "OK" et l'autre affichant "Cancel" (Annuler). Après avoir modifié le texte dans les gadgets de chaîne, le gadget "OK" peut être sélectionné pour affecter les nouvelles entrées aux chaînes de caractères pointées par le tableau DefText. Si vous sélectionnez "Cancel", le texte qui se trouvait dans les gadgets au moment de l'affichage de la requête reste intact. Après avoir choisi "OK" ou "Cancel", la requête disparaît, la mémoire allouée aux différentes structures de données retourne dans le pool de mémoire libre et le contrôle revient au programme appelant.

Le programme court intitulé TestSR présenté dans le listing 4 peut être compilé et lié à StrReq.c. Il démontre le fonctionnement de la fonction StringsRequest. Le programme demande à l'utilisateur à l'écran des informations sur les gadgets de chaîne à afficher dans la requête. Alternativement, un fichier texte contenant toutes ces informations peut être créé et le programme peut être exécuté avec l'entrée redirigée vers ce fichier. TestSR lira les informations, ouvrira une fenêtre et affichera la requête. Une fois les modifications effectuées et le gadget "OK" ou "Cancel" choisi, la fenêtre se fermera et le texte actuel de chaque gadget sera affiché.

J'espère que cette fonction et les techniques de programmation qu'elle utilise vous seront utiles.


[Retour en haut] / [Retour aux articles]