Suivez-nous sur X

|
|
|
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 : C - Console.device, réception de caractères et affichage via la graphics.library
(Article écrit par Max et extrait d'Amiga News Tech - avril 1991)
|
|
Après avoir vu comment le console.device pouvait servir à
l'entrée et à la sortie de caractères dans une fenêtre Intuition, il nous reste à voir
comment il peut permettre, simplement et sans fatigue, de tout bonnement recevoir des caractères
en entrée et les afficher à l'aide de la graphics.library.
On peut d'emblée se demander quel peut bien être l'avantage de sortir nous-même les
caractères reçus, alors qu'une tâche bienveillante peut s'en occuper pour nous. D'autant
plus que la gestion du curseur est automatique, de même que le "clipping" (ou devrais-je dire
"wrapping" ?), le style et toutes ces sortes de choses.
Oui, mais... Avez-vous déjà essayé de positionner le curseur à une position déterminée dans
la fenêtre ? Il faut envoyer une suite de codes ANSI par l'intermédiaire de DoIO(), ce
qui utilise autant de mémoire. Idem pour passer en gras, italique ou souligné. Quant à changer
de police de caractères ou simplement de taille des caractères, n'en parlons même pas.
La méthode que nous allons voir maintenant est beaucoup plus simple à mettre en oeuvre, même
si elle peut sembler plus longue. En tout cas, un de ses gros avantages est de permettre de
se passer d'un MessagePort supplémentaire, toujours ennuyeux à gérer avec ses signaux particuliers.
Mais lisez plutôt.
Petit détour par la graphics.library
Pour résumer la méthode, je dirais simplement qu'elle consiste à ouvrir une fenêtre
Intuition de manière tout à fait normale, en spécifiant "RAWKEY" comme drapeau
IDCMP. Il est évidemment possible d'en utiliser d'autres, comme MENUPICK ou INTUITICKS.
Il faut simplement faire attention à bien utiliser le drapeau RAWKEY et non VANILLAKEY,
qui, s'il traduit bien les codes clavier en caractères ASCII, occulte complètement au
passage les touches spéciales (touches de fonction, curseur et Help).
Par la suite, à chaque message de type RAWKEY reçu, on appelle la fonction RawKeyConvert()
du console.device, qui se charge de la traduction désirée, en accord avec le KeyMap
spécifié. Ce qui signifie que si vous désirez que votre programme parle le suédois,
le javanais ou l'espéranto, rien n'est plus facile.
Tertio, les caractères sont affichés à l'aide de la graphics.library, via la fonction
Text(). Dans le programme d'exemple qui illustre cet article, le curseur est dessiné par
nos soins et par la fonction RectFill(). Cela suppose bien entendu que l'on gère soi-même sa
position, mais c'est enfantin. De plus, cela permet à ceux qui aiment bien se faire remarquer,
d'en modifier la taille ou carrément l'apparence. Ce n'est qu'une question d'imagination - et de goût.
RawKeyConvert()
En citant tout à l'heure RawKeyConvert(), j'ai parlé de fonction, et non de commande.
Qu'est-ce à dire ? Eh bien tout simplement qu'il s'agit d'une fonction et non d'une commande.
Si. C'est là une particularité que le console.device partage avec le serial.device et le
trackdisk.device : offrir des fonctions, tout comme une bibliothèque standard, en plus
des commandes (CMD_WRITE et consoeurs). Il est d'ailleurs à regretter que cette fonction ne
fasse pas partie de l'intuition.library, qui d'ailleurs l'utilise à outrance, mais bon...
Cela nous oblige tout de même à utiliser une structure IOStdReq, à ouvrir le périphérique logique, à
récupérer un pointeur sur son adresse de base (j'en profiter pour rappeler au passage qu'un périphérique logique
a la même structure de base qu'une bibliothèque "classique").
Enfin, cela ne prend que quelques lignes de code et peu de mémoire. L'ouverture du périphérique logique
se fait maintenant de manière un peu différence à celle vue le mois dernier : en mettant le
numéro d'unité à "-1" lors de l'appel à OpenDevice(), on n'a pas besoin de se créer de
MessagePort, et une seule structure IOStdReq suffit. Le pointeur sur l'adresse de base du
périphérique logique est ensuite récupérée dans cette structure, de la manière suivante :
Ce qui donne en assembleur :
Comme vous le voyez, c'est loin d'être compliqué. Notez au passage que le nom de variable
ConsoleDevice est obligatoire, du moins en C, pour que l'éditeur de liens y retrouve ses
billes lors de l'édition de liens avec l'Amiga.lib. Elle doit être de type (struct ConsoleDevice *).
Bien. Voyons maintenant l'utilisation de RawKeyConvert(). Son synopsys est le suivant :
nombre = RawKeyConvert(event, buffer, buflen, keymap);
d0 a0 a1 d1 a2
|
Avec :
- event : pointeur sur une structure InputEvent.
- buffer : pointeur sur le tampon mémoire recevant le(s) caractère(s).
- buflen : taille de ce tampon mémoire.
- keymap : pointeur sur un keymap particulier ou NULL.
- nombre : nombre de caractères "traduits" ou -1 si le tampon mémoire était trop petit.
On voit ici que "event" pointe sur une structure de type InputEvent, alors qu'Intuition ne
nous envoie que des IntuiMessages. Conclusion : il va falloir se fabriquer une structure
InputEvent et la remplir nous-même, en recopiant tout simplement les champs de l'IntuiMessage.
Cet extrait de la fonction doKeys du listing montre comme faire :
C'était pas bien difficile. Je laisse aux 68000eurs le soin de transcrire cette routine dans
leur langage préféré.
Au retour de RawKeyConvert(), on obtient le nombre de caractères "traduits" dans le tampon mémoire,
ou -1 si celui-ci était trop petit. Normalement, ce nombre devrait être égal à un, du moins
tant qu'à la touche concernée, correspond un code ASCII affichage. Dans le cas des touches
"spéciales" (F1 à F10, curseur, Help), le tampon mémoire contient la transcription ANSI de
ces touches, à savoir (tous les codes sont en hexadécimal) :
Cela oblige à écrire une routine (plutôt complexe) qui interprète ces codes ANSI afin de
réagir convenablement suivant la touche enfoncée... Il y a évidemment plus simple : oublier
alors RawKeyConvert() et utiliser l'IntuiMessage. C'est exactement de cette façon qu'agit
la fonction DoSpecialKeys() dans le listing. A noter que les touches comme Ctrl/C
ou Ctrl/Y sont "traduites" en leur vraie valeur ASCII (3, 25. etc.).
Mise à jour d'août 2020 : une version en texte et adaptée à
vbcc a été réalisée par Yann-Gaël Guéhéneuc et est disponible sur
obligement.free.fr/files/antconsoledevice2.lha.
Petite digression
Notre étude du console.device étant maintenant terminée, j'en profite qu'il me reste un peu de
place pour parler de la gestion du curseur au travers de la graphics.library.
Bien que le listing proposé dans cet article n'agisse pas de cette manière (la honte soit sur
moi et ma famille jusqu'à la cinquante deuxième génération), il est recommandé, pour le
positionnement et la taille du curseur, de connaître les largeur, hauteur et ligne de base de
la police en cours. J'ai utilisé des #define pour la police Topaz taille 8, mais il y a
évidemment des moyens beaucoup plus officiels de procéder. Voici une fonction C qui réalise ceci
(en supposant que la diskfont.library ait été correctement ouverte) :
Avec ces trois variables, on positionne le curseur où l'on veut :
En utilisant cette fonction, veillez à ce que le curseur soit d'au moins un pixel
moins large et moins haut que la police en cours, sinon il "mordra" sur le caractère voisin.
Voilà qui vous donne tous les éléments pour créer un éditeur de texte ultra-rapide. C'est
comme ça que fonctionne GenAm2, l'éditeur du Devpac, ou même MEmacs, l'éditeur fourni sur
la disquette Extras du Workbench. Ed quant à lui, utilise le console.device pour la
sortie des caractères... voyez la différence. Vous trouverez de plus dans le listing les
routines appropriées pour éditer une ligne (BackSpace et Del sont gérées), à vous de
l'adapter à plusieurs lignes, puis à un texte entier, cela est beaucoup moins difficile que
ça n'en a l'air.
|