[EN] [IT]
[INFO] [ACQUÉRIR] [PLAN] [RESSOURCES]
CHAPITRE
APPRENDRE À PROGRAMMER AVEC FUTUREBASIC
NOTES

Organisation du code

Section programme principal
Section des fonctions
Section d'en-tête

Leçon 16 : L'organisation des programmes

Pour chaque problème donné, il y a toujours diverses solutions qui peuvent être mises en œuvre. Ces solutions dépendront de votre connaissance du langage d'une part, mais aussi de votre façon de raisonner et de poser les problèmes. Ces deux aspects se nourrissent mutuellement et évoluent au fur et à mesure que vous progressez dans l'une ou l'autre de ces voies.

Le BASIC, de manière générale, est assez laxiste dans sa forme. Ceci permet à l'apprenti programmeur de ne pas se décourager par l'accumulation de frustrations. Il n'en reste pas moins que si vous commencez par employer de bonnes méthodes, même si elles vous paraissent parfois contraignantes, vous rendrez cette expérience plus fructueuse et finalement vous progresserez plus régulièrement et plus longtemps.

On débute souvent par l'écriture de petits programmes qui peuvent aisément tenir dans un seul document de code source, mais déjà, à ce niveau, il est bon d'organiser son programme de manière cohérente. L'écriture de plus gros programmes ne se fera que par l'extension naturelle de cette organisation.

N'hésitez pas à découper vos programmes en sections que vous délimiterez par des signets, notez que les signets de FutureBASIC vous aideront à naviguer dans votre code source par l'intermédiaire d'un menu local qui liste tous les signets présents dans le document, ce qui vous évitera des défilements intempestifs à la recherche d'instructions particulières.

Dans la plupart des programmes simples, on peut déterminer trois sections principales :
  • Une section d'en-tête
  • Une section pour les fonctions
  • Une section pour le programme principal

    Programme principal
    Au moment de l'exécution ou de la construction de l'application, le Compilateur parcourt ces sections dans cet ordre. Commencer par le début et terminer par la fin vous paraît sans nul doute évident, toutefois, nous verrons que ce détail proche d'une lapalissade pourra avoir son importance ultérieurement. On a d'ailleurs déjà vu que le Compilateur se plaindra si vous tentez d'appeler une fonction dont il n'a pas encore rencontré la déclaration dans votre code.

    Maintenant, lorsque votre programme est lancé, la première instruction exécutée sera la première commande exécutable qu'il rencontrera généralement dans votre section réservée au programme principal.

    Habituellement dans cette section, on commence par initialiser un certain nombre de variables en testant l'environnement dans lequel le programme est exécuté. Votre application peut avoir besoin par exemple de connaître la taille du moniteur principal, ou de savoir si QuickTime est présent sur le système. On peut appeler ici une ou plusieurs fonctions qui se chargeront de retrouver les informations nécessaires.

    C'est aussi, au tout début du programme que l'on initialise les managers du Macintosh qui demandent une initialisation. Après quoi, avec FutureBASIC, on installe les vecteurs d'événements dont l'application aura besoin. Cette vectorisation désigne les fonctions qui devront être appelées par le runtime pour tel ou tel type d'événement. Finalement, le programme s'installe dans une boucle dite infinie, dont le rôle essentiel est d'intercepter les événements qui surviennent en provenance de l'utilisateur ou du système. La commande HANDLEEVENTS autorise l'interception de tels événements. Lorsqu'un événement d'un type donné survient, non seulement le runtime aura déchiffré et reformaté, dans une forme plus digeste pour nous, l'événement dont il s'agit mais, pour peu que l'on ait défini (ou vectorisé) une fonction pour gérer ce type d'événement, il appellera automatiquement notre gestionnaire personnalisé.

    De manière schématique, la section du programme principal, peut se présenter ainsi :

    FN Initialiser

    ON MENU   FN
    GererMenu
    ON DIALOG FN GererDialogue
    ON MOUSE  FN GererSouris

    DO
      HANDLEEVENTS
    UNTIL
    (1 = 2 )


    On peut faire ici un certain nombre de remarques concernant la vectorisation des événements :

  • Il est tout à fait possible de déclarer vos vecteurs dans une fonction locale, ce que vous pourriez très bien faire dans la fonction Initialiser ci-dessus.

  • Vous n'êtes pas obligé de déclarer tous les vecteurs disponibles avec FutureBASIC, vous n'installerez que ceux dont votre application a besoin.

  • Vous pouvez vous passer de la presque totalité des vecteurs de FutureBASIC en utilisant le vecteur ON EVENT dans lequel il vous faudra décoder l'événement brut pour en extraire les valeurs et réagir en conséquence. Un tel gestionnaire d'événement brut ressemblera beaucoup à ce qu'on peut trouver dans un langage comme le C. Pour empêcher le runtime de traiter l'événement que vous avez intercepté et peut-être géré vous pouvez le transformer en événement nul à la sortie de la routine gestionnaire d'événement brut. Décoder les événements bruts n'est pas toujours très simple, il est donc préférable de laisser le runtime se charger de ce travail pour nous. On utilisera donc plus volontiers le vecteur ON EVENT dans certaines occasions très spéciales.

    Le plus souvent vous rencontrerez une boucle événementielle telle que la suivante :

    DO
      HANDLEEVENTS
    UNTIL
    gFini


    gFini est une variable globale booléenne qui, lorsqu'elle passe à VRAI (valeur non nulle), indique au programme de sortir de la boucle infinie qui piège les événements. Cette variable peut être mise à VRAI par diverses parties du programme pour terminer l'exécution de l'application. Certains programmeurs ont pris l'habitude d'appeler une fonction au sortir de la boucle événementielle pour faire du nettoyage de la mémoire afin de libérer les blocs que l'application aurait pu réserver pour ses besoins.

    Vous noterez que l'instruction END est facultative pour terminer l'exécution, toutefois vous la trouverez encore dans certains exemples, car les programmeurs peuvent utiliser la fin de leur section principale pour y inclure non seulement des listes de données avec l'instruction DATA ou encore des procédures de rappel (callback procedures) utilisées par d'autres sections du programme.

    Si le cas des instructions DATA ne pose pas de problèmes du fait que la commande n'est pas exécutable (il s'agit de déclarations), il n'en va pas de même des procédures de rappel qui contiennent des commandes immédiatement exécutables lorsque le flux du programme entre dans ces fonctions un peu spéciales. Les procédures de rappel doivent avoir un format particulier et elles sont définies dans des blocs ENTERPROC/EXITPROC. Gardez bien en mémoire qu'à la différence des blocs LOCAL FN/END FN qui ne sont exécutés que lorsque la fonction est appelée depuis d'autres parties de votre programme, les blocs de procédure sont exécutés sur le champ, ce qui peut avoir des conséquences désastreuses pour votre application. Un autre inconvénient à noter est qu'il n'est plus possible d'utiliser le Débogueur lorsque ces procédures sont exécutées. C'est la raison pour laquelle vous serez peut-être amené à rencontrer des morceaux de code qui se présentent schématiquement comme ceci :

    #IF DEF _useFBdbugger
      TROFF
    #ENDIF
    GOTO
    "sauter cette procédure"
    "ma procédure"
    ENTERPROC (param1, param2 )
    // instructions ici
    EXITPROC
    "sauter cette procédure"
    #IF DEF _useFBdbugger
      TRON
    #ENDIF


    La première instruction ci-dessus est une structure de compilation conditionnelle qui teste si le Débogueur a été activé au moment de la compilation, auquel cas, elle le désactive pour éviter tout problème, puis l'instruction GOTO branche le flux du programme de manière à ne pas entrer dans la procédure. Enfin, si le Débogueur était actif lors de la compilation, il est réactivé après le détournement du flux.

    Généralement, les procédures de rappel ne sont pas abordées avec les débutants, parce qu'on peut très bien programmer sans en utiliser aucune et qu'elles adressent, en principe, des besoins particuliers. Il est toutefois intéressant de mentionner leur existence pour montrer l'étendue des possibilités offertes par FutureBASIC.

    Sans doute, vous vous demandez dans quelles circonstances ces procédures trouvent une utilité. Nous avons vu que FutureBASIC mettait à notre disposition non seulement un ensemble versatile de mots-clés BASIC, mais également qu'il nous permettait un accès aisé à une quantité industrielle de fonctions et de procédures de la Toolbox du Macintosh. Malgré la pléthore de commandes disponibles, il est certain que tous les besoins des programmeurs ne peuvent pas être couverts. Dans de nombreuses fonctions et procédures de la Toolbox, Apple a introduit un mécanisme qui permet un échange d'informations entre la Toolbox et votre code, de telle sorte que le programmeur a la possibilité d'exercer un certain contrôle durant l'exécution du code que lui-même n'a pas écrit. C'est, d'une certaine manière, une façon d'étendre les possibilités de la Toolbox. Ce mécanisme est implémenté au moyen de procédures de rappel. Le programmeur passera en paramètre à la fonction de la Toolbox qu'il souhaite invoquer l'adresse d'une routine qui sera à son tour invoquée par la Toolbox.

    De manière générale, les fonctions de la Toolbox qui peuvent accepter une procédure de rappel, communiquent des informations (des paramètres) au moment où elles invoquent à leur tour vos routines. Il est bien entendu indispensable de connaître le nombre et le format des paramètres que la Toolbox va vous renvoyer. Il est également indispensable de savoir si la Toolbox s'attend à recevoir un résultat de votre routine et dans quel format. Il faut donc consulter la documentation d'Apple qui détaille ce type d'information pour chaque procédure de rappel possible.

    Nous avons mentionné ici les procédures de rappel parce que beaucoup de programmeurs les placent dans la section réservée au programme principal après la commande END, comme le suggère le Manuel de Référence de FutureBASIC, ce qui empêchera le flux du programme dʼentrer dans ces procédures de manière inopinée. Mais cet emplacement n'est pas une obligation, ces procédures pourraient très bien se trouver ailleurs dans votre code source, pour peu que vous preniez soin de détourner le flux du programme pour les contourner.

    Le programme le plus rudimentaire utilisant une boucle événementielle que l'on peut produire avec FutureBASIC est le suivant, qui consiste en une simple boucle événementielle :

    DO
      HANDLEEVENTS
    UNTIL
    0


    Vous pouvez compiler ce bout de code qui ne fait rien si ce n'est attendre que l'utilisateur choisisse l'article de menu Quitter qui a été installé automatiquement par le runtime.

    Il est très possible d'appeler des fonctions depuis la boucle événementielle si vous le souhaitez. Ces fonctions seront donc exécutées très souvent, c'est-à-dire chaque fois que le programme n'a rien de particulier à faire, ni d'événements à gérer. Il est toutefois recommandé d'avoir une boucle peu encombrée de manière à ce que la commande HANDLEEVENTS soit exécutée le plus souvent possible, votre application n'en paraîtra que plus fluide aux yeux de l'utilisateur final.

    Ne perdez pas de vue que lorsqu'une fonction quelconque est appelée, votre programme exécute les commandes qu'elle contient et que le flux du programme ne reviendra dans la boucle principale que lorsque la fonction aura pris fin. Comme une fonction peut elle-même invoquer d'autres fonctions qui en appellent d'autres à leur tour et ainsi de suite, le flux du programme peut mettre un certain temps avant de revenir à la boucle événementielle. Pendant, ce temps de latence, l'utilisateur est contraint d'attendre avant de pouvoir déclencher une autre opération. Il est donc relativement important de soigner la vitesse d'exécution de vos fonctions. Dans ce domaine, FutureBASIC est bien armé. Le code exécutable généré par le Compilateur est très rapide à la base, mais sachez que certaines constructions logiques ou certaines formes syntaxiques produisent un code plus rapide et cela quelquefois de manière très sensible. Dans certains cas de figure, il n'est pas possible d'accélérer suffisamment le code pour que l'application semble fluide à l'utilisateur, d'autre part n'oubliez pas que la rapidité d'exécution dépend aussi et en grande partie de la puissance de l'ordinateur sur lequel l'application est exécutée. Votre programme peut néanmoins se comporter correctement vis à vis de l'utilisateur en affichant un curseur animé en forme de montre par exemple, si le processus ne prend que quelques secondes avant de lui redonner la main. Au-delà, il est recommandé d'afficher une boîte de dialogue présentant un message et une barre de progression qui indiquent clairement à l'utilisateur qu'il doit patienter. D'autres retours visuels sont envisageables, mais quel que soit le choix que vous ferez, il faut éviter que l'utilisateur ne se pose des questions sur ce qui est en train de se passer dans votre application. En fait, cette simple mesure de politesse peut revêtir une autre importance. Le feed back donné à l'utilisateur le rassure, il constate que le programme travaille et répond à ses demandes - on ne doit pas négliger de donner un sentiment de confort à l'utilisateur - et par ailleurs il lui permet de constater si l'ordinateur pour une raison quelconque a cessé d'être opérationnel, la barre de progression n'avancera plus, ou bien la montre cessera d'être animée. Avant OS X, ce genre de mésaventure n'était pas rare, elle pouvait être due à une erreur de programmation dans votre application ou bien à une autre application tournant en tâche de fond ayant gelé le système.

    Il y a d'autres techniques plus difficiles à mettre en œuvre qui permettent de faire revenir le flux du programme très rapidement dans la boucle événementielle. Ces techniques emploient des threads et demandent un plus gros effort de conception. Les threads sont des processus indépendants qui s'exécutent parallèlement au programme principal. Bien qu'indépendants dans leur exécution, les threads ont l'avantage de "voir" les variables globales du programme dans lequel ils s'exécutent au même titre que les fonctions locales ordinaires. Plusieurs threads peuvent être en activité au même moment, de plus, la même fonction peut servir deux threads ou plus simultanément. Chaque thread devra libérer du temps pour que les autres threads puissent progresser.

    Dans ce cas de figure, le programme principal est considéré comme un thread; il est d'ailleurs appelé le thread principal. A l'exception notoire du thread principal, les autres threads ne possèdent pas de boucle événementielle.

    Notez que la Release 7 a introduit deux nouveaux mots-clés facilitant à l'extrême l'installation de threads dans vos programmes. Avec la commande THREADBEGIN, vous désignez la fonction de votre code source qui devra être exécutée dans un thread, tandis que la fonction THREADSTATUS non seulement libérera du temps pour les autres processus, mais aussi vous retournera une valeur indiquant si le thread doit être avorté pour une raison quelconque. THREADSTATUS doit être appelée très régulièrement pendant l'exécution du thread, à la manière de la commande HANDLEEVENTS sinon vous perdrez la fluidité que vous essayez de gagner.

    Programmer avec des threads n'est pas toujours une simple affaire comme ces deux commandes pourraient le laisser supposer. Encore une fois, cela demande une réflexion plus poussée sur le mode opératoire de votre programme, ce qui a nécessairement une incidence sur sa conception, mais il y a aussi un second inconvénient dans cette technique et c'est tout simplement que le Débogueur intégré à FutureBASIC ne peut pas être utilisé pour pister vos fonctions et vos variables. Rien ne vous empêche toutefois d'écrire des fonctions spécifiques utilisées pendant la phase de déverminage qui se chargeront d'enregistrer dans un fichier texte les informations que vous avez besoin de tracer.

    Tout comme les procédures de rappel, la technique des threads n'est généralement pas abordée avec les débutants. En dépit de cela, ce livre se veut légèrement différent en ce qu'il entend donner une vision plus globale de la programmation sur Macintosh avec FutureBASIC, c'est pourquoi nous mentionnons ces techniques, mais aussi nous les mettrons en œuvre dans la section pratique de l'ouvrage.

    La section réservée aux fonctions.
    C'est en fait ici la partie la plus simple bien que la plus volumineuse aussi. Toutes les fonctions utilisées par votre programme seront localisées dans cette section médiane. Un très gros programme peut avoir des milliers de fonctions. Cette section aura tendance à augmenter au fur et à mesure des nouveautés que vous introduirez dans votre application. En réalité, elle n'est qu'une suite de déclarations. Vous devez vous souvenir que l'ordre dans lequel vos fonctions sont déclarées a une relative importance. Une fonction dont le Compilateur n'aura pas encore "vu" la déclaration, ne pourra pas être invoquée dans le corps d'une autre fonction, à moins que vous ne l'ayez prototypée avec la commande DEF FN, comme nous l'avons déjà évoqué. Exemple :

    LOCAL FN fonction1
      FN fonction2
    END FN

    LOCAL FN
    fonction2
    END FN

    Ci-dessus, le Compilateur s'arrêtera au moment de générer le code exécutable pour la fonction locale fonction1, du fait qu'il n'aura jamais entendu parler de ma fonction2 qui est invoquée et ne saura pas à quoi elle fait référence. Le code qui suit règle le problème. DEF FN indique au Compilateur le nom de la fonction et les paramètres qu'elle accepte. Cela suffit à contenter le Compilateur.

    DEF FN fonction2

    LOCAL FN
    fonction1
      FN fonction2
    END FN

    LOCAL FN
    fonction2
    END FN

    Certains programmeurs prototypent toutes leurs fonctions au début de leur code source ou bien dans un fichier externe qu'ils incluent avec la commande INCLUDE. Ils n'ont plus alors à se soucier de l'ordre dans lequel les fonctions sont déclarées et toutes les fonctions locales peuvent s'appeler entre elles sans susciter de problèmes. La seule objection que je vois dans cette méthode est qu'elle n'aide pas à acquérir une certaine rigueur dans l'organisation du code source.

    De toutes les manières, il est souhaitable d'organiser les fonctions locales selon leur domaine d'activité, vous naviguerez alors plus aisément dans le code. Pour vous aider davantage, vous pouvez insérer aux emplacements stratégiques des signets aux noms révélateurs.

    Votre programme peut à certain moment prendre un tel embonpoint qu'il vous deviendra pénible malgré tout de faire des va-et-vient incessants à différentes parties du code source.

    Si vous avez pris soin de regrouper vos fonctions par thème, il vous sera alors facile de les couper, puis les coller dans un nouveau document de code source, d'enregistrer ce document sur le disque dur en lui donnant un nom pertinent, puis d'insérer une commande INCLUDE, en lieu et place des fonctions qui auront été coupées. Si vous êtes amené à morceler votre code de cette manière c'est qu'il est sans doute temps pour vous d'utiliser le Gestionnaire de Projets intégré à l'Editeur. Le Gestionnaire de Projets vous permet d'avoir une organisation rationnelle de votre code source. En réalité, un projet FutureBASIC peut être vu comme un fichier de code source unique qui aurait été découpé en chapitres.

    Il y a peu de choses à ajouter concernant la section réservée aux fonctions, si ce n'est que les fonctions doivent porter un nom unique qui les identifie et les différencie de toutes les autres fonctions déclarées dans votre programme. La seule exception à cette règle ne peut se produire qu'avec des structures de compilation conditionnelle. Exemple :

    COMPILE LONG IF CarbonLib
      LOCAL FN maFonction
      END FN
    COMPILE XELSE
      LOCAL FN
    maFonction
      END FN
    COMPILE END IF


    Ci-dessus la fonction maFonction est déclarée deux fois, seulement le Compilateur génèrera du code différent selon la cible de la compilation. La cible de la compilation est définie par la sélection appropriée d'un article du menu Commande. Les choix offerts étant mutuellement exclusifs, le Compilateur ne génèrera du code que pour la version de la fonction appropriée à la cible. Notez toutefois que pour la compilation d'applications dites FAT (qui peuvent s'exécuter sur des machines 68000 et PPC), FutureBASIC compilera une première fois votre code en version PPC, puis une seconde fois en version 68K. Il n'y aura donc pas plus de conflits dans ce cas-là si vous utilisez des structures de compilation conditionnelle.

    La section d'en-tête
    La section d'en-tête que nous voyons ici en dernier est la première à être examinée par le Compilateur. Elle consiste en une série de déclarations ou de directives à l'intention du Compilateur.

    Le contenu de cette section varie considérablement d'un programme à l'autre. Il se peut même que cette section soit entièrement vide.

    On a déjà vu que certains programmeurs y plaçaient les prototypes des fonctions utilisées partout ailleurs dans le programme. De même, on pourrait y trouver des déclarations pour des fonctions et des procédures de la Toolbox que FutureBASIC ne reconnaît pas d'office.

    C'est aussi là une grande et appréciable particularité de l'environnement. Les fichiers headers de FutureBASIC contiennent des milliers de définitions d'appel à la Toolbox, pourtant toutes les fonctions n'y ont pas été déclarées. Il peut arriver, qu'un appel particulier vienne à manquer. Vous ne serez pas bloqué pour autant à attendre que les concepteurs du logiciel daignent enfin déclarer les fonctions qui vous manquent si vous avez sous la main les Headers Universels d'Apple (ces headers sont disponibles en téléchargement libre sur le site web d'Apple). Dans la majorité des cas, la conversion des déclarations d'Apple vers FutureBASIC est réalisée très simplement, cependant elle demande une bonne connaissance quelquefois du Macintosh et de la programmation en général.

    À titre d'exemple, voici la déclaration trouvée dans les Headers Universels d'Apple pour la procédure SetRect qui permet d'attribuer en une seule commande les coordonnées d'une variable de type RECT.

    EXTERN_API( void )
    SetRect(
    Rect * r,
    short left,
    short top,
    short right,
    short bottom) ONEWORDINLINE(0xA8A7);


    La conversion pour FutureBASIC pourrait donner ceci :

    TOOLBOX SetRect( ¬
    RECT * r,    ¬
    SHORT left,  ¬
    SHORT top,   ¬
    SHORT right, ¬
    SHORT bottom ) `0xA8A7


    La traduction, comme on le voit ci-dessus, est presque du mot à mot. Il faut noter que la casse des caractères dans le nom de l'appel Toolbox doit être scrupuleusement respectée sous peine de crash. C'est la seule occasion dans FutureBASIC où ce genre de contrainte s'applique. Lorsque vous appellerez cette procédure dans votre code, la casse des caractères n'aura plus cette importance.

    La partie terminale en hexadécimale est seulement utile pour la compilation d'applications 68K. Si vous n'entendez pas supporter les machines 68000, vous pouvez supprimer ces quelques instructions sans danger.

    Les fonctions de la Toolbox, par opposition aux procédures, qui elles ne retournent pas de résultat, suivent à de très légères différences la même syntaxe. La fonction PtInRect accepte deux paramètres : un point et un rectangle et elle retourne une valeur booléenne _true si le point est à l'intérieur du rectangle, sinon _false.

    EXTERN_API( Boolean )
    PtInRect(
    Point pt,
    const Rect * r) ONEWORDINLINE(0xA8AD);

    TOOLBOX FN PtInRect( POINT pt, const RECT * r ) = BOOLEAN `0xA8AD


    Notez le mot-clé FN devant le nom de la fonction Toolbox ainsi que la position et le type de la variable retournée par la fonction.

    Il y a une quantité importante de headers produits par Apple, et chaque header regroupe les fonctions de la Toolbox d'un manager particulier. Il faut savoir que tous ces headers n'ont pas forcément été traduits pour FutureBASIC^3, il faut savoir aussi que FutureBASIC ne calque pas l'organisation de ses propres headers sur celle définie par Apple.

    Si pour l'immense majorité des utilisateurs l'organisation choisie par Staz Software ne posera aucun problème, elle peut toutefois gêner les programmeurs expérimentés qui souhaitent remplacer les headers de FutureBASIC existants ou ajouter leur propres headers intégralement convertis. Ils pourront alors être confrontés à des déclarations dupliquées qu'il devront nettoyer dans leurs headers convertis.

    Le choix fait par Staz Software de ne pas implémenter l'ensemble des headers d'Apple permet à FutureBASIC d'accélérer le processus de compilation, mais aussi de produire des applications très légèrement moins volumineuses. En principe, vous ne devriez pas être confronté au type de problème évoqué ici avant longtemps.

    En revanche, il faut savoir que le runtime ne compile pas l'ensemble de ses headers lorsque vous choisissez d'exécuter ou de construire une application, mais il compile seulement un sous-ensemble que l'on pourrait qualifier de standard. Pour certains besoins particuliers, il vous faudra alors inclure manuellement les headers appropriés avec une commande INCLUDE que l'on place généralement dans la section d'en-tête du programme.

    Vous pouvez examiner le manuel Aide Toolbox qui liste la pléthore d'appels Toolbox disponibles avec FutureBASIC et indique aussi le fichier header dans lequel un appel particulier est déclaré. Si vous souhaitez utiliser un appel Toolbox et que le Compilateur vous signale qu'il n'est pas défini, il vous suffira alors d'inclure le fichier header dans lequel il est déclaré. Par exemple, la fonction SpeakString qui permet d'utiliser le synthétiseur vocal du Macintosh n'est pas disponible en compilation Standard. Pour pouvoir utiliser cette fonction, vous écrirez l'instruction suivante au début de votre programme :

    INCLUDE "Tlbx SpeechSynthesis.Incl"

    Bien entendu, toutes les autres fonctions définies dans ce fichier d'en-tête seront aussi disponibles pour votre application.

    Les fichiers headers ne contiennent pas seulement des définitions de fonctions et de procédures de la Toolbox. Vous y trouverez aussi des déclarations de constantes et de structures (records) définies par Apple.

    Il est très possible de mémoriser à la longue tous les mots-clés du langage FutureBASIC, il n'y en a pas tant que ça après tout, en revanche vous devez abandonner tout espoir de mémoriser les milliers de fonctions, de constantes et de structures qui pullulent dans la Toolbox. Un débutant a largement de quoi être intimidé. Un des avantages de FutureBASIC est qu'il permet au novice d'absorber à son propre rythme toutes les subtilités de la Toolbox du Macintosh. Il peut percevoir alors la Toolbox comme une immense caverne d'Ali Baba regorgeant de perles qu'il pourra glaner au fil de ses pérégrinations. Il découvrira parfois qu'un simple appel à l'une de ses fonctions pourra résoudre des difficultés de programmation et qu'une commande pourra à elle seule faire le travail de plusieurs lignes de code.

    Il est tout à fait envisageable de produire des applications dignes de ce nom en n'utilisant que le "BASIC Standard" proposé par FutureBASIC, mais il est certain que FutureBASIC ne serait pas un environnement susceptible d'intéresser les programmeurs professionnels s'il ne donnait pas un accès aussi aisé à la Toolbox du Macintosh. Historiquement d'ailleurs, c'est à cette particularité que FutureBASIC doit sa renommée, pendant longtemps, il a été le seul BASIC sur Mac à proposer cette fonctionnalité.

    Maintenant, il faut être honnête, on sait que le BASIC Standard est un langage qui n'est pas né d'hier, d'ailleurs beaucoup le considèrent depuis longtemps comme dépassé, voire complètement obsolète. Sur le Macintosh, FutureBASIC démontre qu'il n'en est rien par son élégante implémentation de ce langage procédural. Toutefois, malgré l'évolution du langage qui accepte des mots-clés comme BUTTON, WINDOW ou MOUSE pour tenir compte des avancées technologiques (les interfaces graphiques n'existaient pas à l'origine du BASIC), certaines fonctionnalités des programmes modernes ne peuvent être implémentées qu'en ayant recours à la Toolbox. La technique aujourd'hui très répandue du glisser-déposer en est un bon exemple. En réalité, de nombreuses technologies présentes dans le système d'Apple nécessitent les bons services de la Toolbox pour pouvoir les mettre en œuvre dans vos applications. Il faut l'admettre, ce n'est pas toujours aisé, mais la bonne nouvelle c'est que rien n'est impossible avec FutureBASIC.

    Bien que cela ne soit pas une obligation, il est coutumier de placer dans la section d'en-tête des commandes non exécutables à l'intention du compilateur. Ces commandes ont une incidence sur l'application qui sera compilée.

    Par exemple, DIM SYSTEM indiquera le nombre d'octets supplémentaires que l'on souhaite allouer à la partition mémoire dans laquelle évoluera l'application. Sur Macintosh (avant le système X) l'utilisateur a la possibilité de modifier cette partition mémoire au moyen de la commande Lire les informations dans le Finder. Si votre application nécessite une plus grande quantité de mémoire que celle attribuée automatiquement par le Compilateur, vous pouvez forcer une plus grande valeur grâce à cette commande. La valeur estimée par le Compilateur est le plus souvent suffisante pour faire fonctionner votre application, mais il ne peut pas toujours évaluer vos réels besoins en mémoire. DIM SYSTEM vous permet donc de prérégler à votre convenance l'allocation nécessaire.

    La commande OUTPUT FILE attribuera un nom de fichier à l'application compilée. FutureBASIC attribue un nom par défaut à l'application au moment où il l'écrira sur le disque.

    On trouve quelquefois dans lʼen-tête, la commande DEF OPEN qui indique au compilateur le type et le créateur des fichiers que votre application peut créer. Sur Macintosh, tous les fichiers possèdent un type et une signature de créateur tous deux représentés par une séquence de 4 caractères. Les applications ont le type générique APPL et une signature qui les identifie de manière unique. Cette signature est attribuée arbitrairement par le concepteur du logiciel, mais elle ne doit pas entrer en conflit avec d'autres signatures existantes. Cette signature peut être enregistrée auprès d'Apple qui maintient une base de données de toutes les signatures que les programmeurs ont bien voulu référencer. FutureBASIC attribue par défaut la signature ???? à votre application. Vous pourrez, bien entendu, changer à votre gré cette signature. Un fichier-document possède aussi un type et une signature de créateur. En général, la signature du créateur est identique à la signature de l'application qui a servi à créer le fichier. Notez qu'une application peut produire et utiliser différents types de fichiers. Ces fichiers auront alors la même signature de créateur, mais se distingueront par un type différent. La commande DEF OPEN vous permet de définir le type et la signature que FutureBASIC attribuera au fichier créé lors de la prochaine opération de création de fichier dans votre application. Vous pouvez utiliser la commande DEF OPEN autant de fois que vous le souhaitez dans votre programme. Le Finder utilise ces informations pour afficher l'icône appropriée. Il est fortement conseillé de soigner le design des icônes qui seront affichées de manière à donner visuellement un air de famille aux fichiers générés par la même application.

    Notez que certains types de fichiers sont préétablis, le type TEXT indique que le fichier contient du texte pur, le type PICT indique que le fichier contient une image au format propre au système d'Apple.

    Cʼest aussi, le plus souvent, dans lʼen-tête que nous trouverons la commande RESOURCES qui indique au compilateur un fichier de ressources à inclure dans lʼapplication compilée et qui permet également dʼassigner une signature de créateur.

    RESOURCES "Mes Ressources","CREA"

    Avec cette commande, on pénètre dans un vaste domaine qui a aussi contribué au succès du Macintosh. Le concept de ressources était essentiel jusquʼà lʼarrivée du système OS X.

    Aussi surprenant que cela puisse vous paraître si vous êtes novice sur la plate-forme Macintosh, la plupart des fichiers sont en fait la combinaison de deux fichiers distincts. Cette dualité est cachée aux yeux de lʼutilisateur qui aura la certitude de manipuler un fichier unique, par exemple en glissant son icône dʼun disque à un autre pour en faire une copie. Le système dissimule en fait ce qui se passe réellement. En tant que programmeurs cela revêt tout de même une grande importance pour nous.

    On parlera plus volontiers de la partie données (data fork) dʼun fichier et de sa partie ressources (resource fork). Une application qui crée des documents utilisera le plus souvent la partie données du fichier quʼelle créera pour stocker les informations concernant ce document, mais ceci nʼest pas une obligation, car elle peut aussi stocker des informations dans la partie réservée aux ressources. Bien quʼil nʼy ait rien de systématique en cela, certains fichiers (le plus souvent des documents) ont une partie ressources vide, et dʼautres une partie données vide (le plus souvent, il sʼagit dʼapplications).

    Mais que contient au juste cette partie ressources ?

    Si je vous réponds des données, vous allez commencer à devenir nerveux, aussi, je vous répondrai quʼil sʼagit de données enregistrées sous un certain format. Lʼobjet de la partie ressources est de contenir des données qui ne sont pas susceptibles dʼêtre modifiées par le programme lors de son exécution, on y trouvera là beaucoup dʼéléments constituant lʼinterface utilisateur mais pas uniquement.

    Ces données dʼun genre particulier sont classées par type. Bien que rien ne vous empêche de définir vos propres types, il faut savoir quʼun très grand nombre dʼentre eux ont déjà été prédéfinis par Apple. À l'instar de la signature des fichiers, les types sont également représentés par 4 caractères. Les données stockées sous un type spécifique doivent répondre à la structure attendue pour le type de ressource concernée. Par exemple, une chaîne Pascal pourrait être stockée sous la forme dʼune ressource de type ‟STR ‟ (notez lʼespace final).

    Une ressource particulière est identifiée par son type, mais aussi par un numéro identifiant en principe unique qui la distingue des autres ressources du même type. Ces numéros identifiants sont représentées sur des entiers courts dans l'intervalle [-37000, + 37000]. Les identifiants négatifs sont en principe réservés par Apple, ce qui nous laisse une bonne quantité dʼidentificateurs disponibles tout de même.

    Pour avoir un aperçu des types de ressources les plus répandus, consultez le tableau ci-dessous, il vous indiquera également ce que représente chacun des types.



    [Precédent] [Table des Matières] [Suivant]
  • {Note}
    © 2000 Pix&Mix
    Tous droits réservés

    FutureBASIC est une marque déposée appartenant à Staz Software, Inc et utilisée avec permission.