8

L'internationalisation des textes

 

                   Nous développons dans ce chapitre les notions introduites par la Release 5 permettant l'internationali­sation des textes. Les programmeurs possédant une version antérieure à la Release 5 peuvent ignorer entièrement ce chapitre.

 

 

8.1. Les localités

                  Une application doit pouvoir s'adapter aux différentes langues internationales sans qu'il soit nécessaire de la recompiler. Tel est le but de l’internationalisation des applications. Cependant, il ne peut être du ressort des applications de prévoir toutes les configurations locales. C'est pourquoi X a prévu de fonder l'internationalisation des applications sur les concepts de localité (locale) et de méthode d'entrée (input method).

                  Dans la Release 5, les localités peuvent affecter les processus de codage et décodage de textes à différents niveaux :

                  • au niveau de la lecture des entrées

                  • au niveau des dessins de textes

                  • au niveau des fichiers de ressources

                  • au niveau de la communication entre clients

 

                  Ainsi, une localité fixée affecte la lecture des chaînes avec XmbLookupText et XwcLookupText, le dessin de chaînes avec XmbDrawText et XwcDrawText ainsi que  les demandes d'étendues avec XmbTextExtents, XwcTextExtents ou XExtentsOfFontSet. Dans toutes ces requêtes, les chaînes sont interprétées selon la coutume locale induite par la localité.

 

      Une localité modifie aussi l'interprétation des chaînes lors des accès aux ressources effectués avec XrmGetFileDatabase, XrmGetStringDatabase et XrmPutFileDatabase. Elle affecte aussi l'interprétation des textes de messages d'erreurs récupérés par XGetErrorsDatabaseText et XGetErrorText ainsi que certaines fonctions affectant les propriétés standards, comme XmbSetWMProperties, XwcSetWMProperties ou XmbTextPropertyToTextList.

                  On modifiera le comportement des programmes dans l'environnement local en affectant la localité elle‑même (avec XSetLocaleModifiers) et en sélectionnant des styles de méthodes d'entrée par l'intermédiaire de contextes d'entrée.

 

 

Déclaration de la localité

 

                  X permet d'utiliser une et parfois plusieurs localités[1]. Ces localités sont définies par diverses données du système hôte et déterminent le comportement local du programme à l'exécution. Dans les implantations conformes à la librairie ANSI C, la méthode de déclaration de la localité (ou locale) est setlocale. Cette fonction configure les opérations locales à la fois dans la librairie C de l'hôte[2] et dans la Xlib. Une opération locale de la Xlib est gouvernée par la catégorie LC_CTYPE, appelée localité courante. Dans les systèmes qui ne se conforment pas à ANSI C, le mécanisme d'instanciation de la localité dépendra des implantations. Dans tous les cas, les implantations sont libres d'ajouter d'autres mécanismes pour annoncer la localité courante à la Xlib.

                  Avant d'utiliser une localité, les clients doivent appeler la fonction de configuration de la localité de l'hôte (en général setlocale) puis déclarer cette localité à la Xlib avec XSetLocaleModifiers;. La fonction XSupportsLocale permet ensuite de vérifier que la valeur courante qui a été attribuée à la localité est bien supportée par X, car le serveur n'est pas tenu de supporter toutes les localités supportées par l'hôte.

 

Bool  XSupportsLocale ()

char * XSetLocaleModifiers (modifiers_list)

char *               modifiers_list;

 

                  La requête XSetLocaleModifiers permet d'initialiser la localité courante pour la librairie et d'affecter des modifieurs. La sémantique de certaines capacités spéciales liées à l'internationalisation peut également être configurée en affectant des modifieurs. Les noms des modifieurs ou des catégories utilisées dépendent des implantations. La liste modifiers_list est la concaténation d'un ou de plusieurs éléments de la forme "@categorie=valeur" où categorie est un nom[3] et valeur est une valeur affectée à cette catégorie. Si la valeur est vide, elle ne modifie pas le défaut de l'implantation. Sur les systèmes satisfaisant les conventions POSIX[4], la variable d'environnement de l'hôte XMODIFIERS sera de toute manière concaténée à la liste pour fournir des valeurs de défaut.

 

                   La seule capacité standard qui soit reconnue de manière internationale est la sélection d'un ou plusieurs styles de méthodes de lecture des entrées. Cette sélection sera effectuée par l'affectation de la catégorie "im" pour input method. Les valeurs possibles dépendent des implantations locales et il faut consulter la documentation locale pour savoir comment annoncer la ou les méthodes de lecture des entrées.

 

                  Si la fonction retourne NULL, c'est qu'une erreur a été commise dans la spécification des catégories et aucune modification ne sera effectuée. Sinon, la chaîne retournée permet, en rappelant ultérieurement la fonction avec cette chaîne, de restaurer les anciens liens.         

 

Il faut qu'un appel à XSetLocaleModifiers avec une chaîne non vide soit exécuté avec succès pour que les fonctions de la Xlib qui utilisent la localité puissent être invoquées sans provoquer d'erreur.

 

 

8.2. Les ensembles de fontes locales

                  Pour dessiner dans une localité, on a besoin d'un certain nombre de jeux de caractères. En effet, chaque localité privilégie une langue et requiert un ou plusieurs jeux de caractères pour écrire les textes dans cette langue. Pour créer un ensemble de fontes acceptable par la localité courante, on utilisera la fonction

XFontSet XCreateFontSet (dpy, base_font_name_list,

                                                                                &missing_charset_list_return,

                                                                                &missing_charset_count_return,

                                                                                &def_string_return)

 

char *               base_font_name_list ;

char **             missing_charset_list_return ;

int                      missing_charset_count_return ;

char *               def_string_return ;

 

                  La fonction XCreateFontSet tente d'instancier un ensemble de fontes, acceptable pour la localité, qui satisfasse en outre les spécifications indiquées par le client dans base_font_name_list. L'ensemble de fontes créé, éventuellement restreint à un seul élément, sera lié à la localité courante.

 

                  La liste base_font_name_list indiquée par l'utilisateur est fournie sous la forme d'une chaîne dont les noms sont séparés par des virgules, et qui finit par zéro. (Les virgules peuvent être séparées par des blancs qui seront ignorés). L'utilisation de noms de fontes satisfaisant aux conventions XLFD[5] permet à la Xlib d'effectuer des généralisations, et un seul nom (un patron) peut en réalité spécifier toute une famille de fontes utilisables par la localité. Si l'utilisateur veut spécifier entièrement l'ensemble des fontes, il peut toujours spécifier entièrement les noms de l'ensemble requis.

 

                  Pour instancier un ensemble de fontes, XCreateFontSet parcourt la liste de base et choisit, dans chaque jeu de caractères requis[6] par la localité, la première fonte disponible satisfaisante dans la famille des fontes spécifiées par ce nom[7]. Par exemple, si une localité requiert l'ensemble des jeux de caractères suivants

                  ISO8859-1

                  JISX0208.1983

                  JISX0201.1976

                  GB2312-1980.0

 

l'utilisateur peut directement fournir une liste de noms complets qui spécifieront entièrement les fontes dans chacun des jeux de caractères requis

 

                  "JIS-Fixed-Medium-R-Normal--26-180-100-100-C-240-JISX0208.1983-0,\

                  JIS-Fixed-Medium-R-Normal--26-180-100-100-C-120-JISX0201.1976-0,\

                  GB-Fixed-Medium-R-Normal--26-180-100-100-C-240-GB2312-1980.0,\

                  Adobe-Courier_Bold-R-Normal--25-180-100-100-M-150-ISO8859-1"

 

ou bien il peut fournir une liste spécifiant partiellement les jeux de caractères comme

 

                  "JIS-Fixed-Medium-R-Normal--26-180-100-100-C-240,\

                  JIS-Fixed-Medium-R-Normal--26-180-100-100-C-120,\

                  GB-Fixed-Medium-R-Normal--26-180-100-100-C-240,\

                  Adobe-Courier_Bold-R-Normal--25-180-100-100-M-150"

ou encore, fournir un motif permettant l'appariement avec n'importe quel jeu de caractères, comme par exemple "-*-*-*-R-Normal--*-180-100-100-*-*" .

                  Si une fonte peut être instanciée dans chacun des jeux caractères requis par la localité, XCreateFontSet retourne un ensemble de fontes de type XFontSet et missing_charset_count_return vaut zéro.

 

                  Si la fonction échoue, par exemple s'il n'y a pas assez de place mémoire ou si la localité courante n'est pas supportée par X, elle retourne le pointeur NULL et missing_charset_count_return vaut zéro. Elle peut aussi n'échouer que partiellement et dans ce cas missing_charset_count_return n'est pas nul. Ce nombre indique alors le nombre de jeux de caractères requis qui n'ont pu être instanciés. Les ensembles de caractères manquants sont retournés dans missing_charset_list_return. On notera que l'on peut ainsi se servir de XCreateFontSet pour récupérer l'ensemble des jeux de caractères requis par la localité. Cette liste pourra ensuite être libérée par XFreeStringList. L'utilisateur peut alors réitérer sa demande pour instancier correctement l'ensemble de fontes. Sinon, quand une fonction de dessin ou une requête d'extension est utilisée avec cet ensemble incomplet de fontes, les caractères manquants y seront remplacés par la chaîne retournée dans def_string_return[8].

                 

                  Un ensemble de fontes ayant été ainsi créé, on pourra dessiner avec lui des chaînes qui seront interprétées par la localité (cf. section 8.3), ou bien l'associer à un contexte de lecture des entrées qui effectuera lui-même l'affichage des entrées avec cet ensemble de fontes (cf. section  8.4. et suivantes).

                  Pour récupérer les noms et les structures XFontStruct associés aux fontes d'un ensemble de fontes, on utilisera la fonction

 

int XFontsOfFontSet (font_set, &font_struct_list_return,

                                                                &font_name_list_return)

XFontSet                          font_set ;

XFontStruct**                font_struc_list_return;

char **                              font_name_list_return ;

 

                  Les chaînes de caractères et les structures retournées par cette fonction appartiennent à la Xlib et ne doivent pas être libérées ni modifiées par le client. En outre il n'est pas certain que X ait chargé les fontes à la création de l'ensemble de fontes. La Xlib peut en effet implanter des caches et ne charger les fontes que lorsqu'un dessin ou un calcul de dimension est demandé. En conséquence, l'existence de dimension dans le champ per_char des structures XFontStruct retournées est en fait aléatoire.

 

                  Signalons également XBaseFontNameListOfFontSet qui permet de récupérer la liste des noms fournie par le client à la création d'un ensemble de fontes, et XLocaleOfFontSet qui fournit le nom de la localité qui est associée à un ensemble de fontes.

 

char * XBaseFontNameListOfFontSet (font_set)

char *  XLocaleOfFontSet (font_set)

XFontSet                          font_set ;

 

                  Pour libérer un ensemble de fontes, on utilisera la requête

 

void XFreeFontSet (dpy, font_set).

 

 

8.3. Le dessin des textes

                  La Release 5 distingue les fonctions de dessin des textes selon qu'elles utilisent des chaînes de caractères 8-bits (appelées aussi chaînes multi-byte) ou des chaînes de caractères étendus (wide characters). Dans le premier cas, une chaîne de plusieurs caractères a le type char * et finit par le caractère nul. Dans le deuxième cas, elle a le type wchar_t *, où wchar_t est la forme des caractères étendus supportée par l'environnement de l'hôte. Les fonctions opérant sur des chaînes de caractères codés sur 8 bits sont préfixées par Xmb (pour multi-byte) et celles opérant sur des caractères étendus sont préfixées par Xwc (pour wide character).

                  Le dessin d'une chaîne de caractères se fait à partir de l'origine passée à la requête. Si la direction implantée est de gauche à droite, les caractères sont normalement disposés sur une horizontale, de gauche à droite. Cependant, dans une localité donnée, une primitive de dessin de texte peut modifier localement l'ordre des caractères, en réponse à une analyse lexicale de la chaîne.

 

Etendues des chaînes

 

                  On définit deux types d'étendues géométriques des caractères : l'encrage d'un caractère (ink extent) et son étendue logique (logical extent). L'encrage détermine le plus petit rectangle englobant tous les caractères du dessin pour ce qui est de la couleur de l’encre (attribut foreground du GC). Mais les dimensions de l'encrage n'incluent pas les espaces nécessaires à un bon interlignage. L'étendue logique, à l'inverse, prévoit un espacement logique minimal. Aucun dessin supplémentaire, comme par exemple un souligné dessiné par le client, ne devrait intersecter le rectangle de l'étendue logique.

                  Les fonctions fournissant des étendues de chaînes utiliseront des structures de type XFontSetExtents (fig. 8.1.) :

 

typedef struct {

   XRectangle max_ink_extent ;                          /* sur tous les caract. */

   XRectangle max_logical_extent ;              /* sur tous les caract. */

} XFontSetExtents ;

 

 fig. 8.1. La structure XFontSetExtents

 

 

                  Pour obtenir les étendues maximales des caractères sur un ensemble de fontes, on dispose de

 

XFontSetExtents *  XExtentsOfFontSet (font_set)

 

et pour obtenir la longueur en pixel d'une chaîne de caractères, on utilisera

 

int XmbTextEscapement (font_set, string, num_bytes)

int XwcTextEscapement (font_set, wstring, num_wchar)

wchar_t *       wstring ;

 

                  Pour obtenir la plus petite boîte englobant une chaîne de caractères, on utilisera les fonctions

 

int XmbTextExtents (font_set, string, num_bytes, &overall_ink_return,

                                                               &overall_logical_return)

int XwcTextExtents (font_set, wstring, num_wchar, &overall_ink_return,

                                                               &overall_logical_return)

XFontSet        font_set ;

char *               string ;

wchar_t *       wstring ;

XRectangle    overall_ink_return, overall_logical_return ;

 

                  Cependant, le dessin de deux caractères avec deux ordres successifs peut fournir un rendu différent du dessin constitué par un ordre unique (avec une chaîne de deux caractères). Les primitives de dessin de chaînes dans une localité sont en effet libres d'implanter des rendus dépendant du contexte. Pour déterminer s'il existe des phénomènes de dépendances contextuelles, on pourra utiliser la fonction booléenne

 Bool XContextDependentDrawing (font_set)

 

                   De même, il est possible que deux caractères successifs soient en réalité imprimés l'un par dessus l'autre. Pour déterminer la position exacte d'un caractère dans une chaîne, on utilisera les fonctions XmbTextPerCharExtents ou XwcTextPerCharExtents.

 

XmbTextPerCharExtents (font_set, string, num_bytes, ink_array_return,

                                                                                logical_array_return, array_size,

                                                                                &num_chars_return, &overall_ink_return,

                                                                                &overall_logical_return)

XwcTextPerCharExtents (font_set, wstring, num_wchar, ink_array_return,

                                                                                logical_array_return, array_size,

                                                                                &num_chars_return, &overall_ink_return,

                                                                                &overall_logical_return)

XRectangle    ink_array_return [], logical_array_return [];

int                      array_size, num_chars_return ;

XRectangle    overall_ink_return,

                            overall_logical_return ;

                  Ces fonctions retournent les étendues géométriques de chacun des caractères de la chaîne dans des tableaux ainsi que les étendues de l'ensemble de tous les caractères de la chaîne (arguments overall_ink_return et overall_logical_return).

 

 

Le dessin des caractères dans la localité

 

                  Une fois calculées les dimensions et emplacements des lignes, on utilisera les fonctions de dessins suivantes :

void XmbDrawString (dpy, draw, font_set, gc, x, y, string, num_bytes)

void XwcDrawString (dpy, draw, font_set, gc, x, y, wstring, num_wchars)

 

void XmbDrawImageString (dpy, draw, font_set, gc, x, y, string, num_bytes)

void XwcDrawImageString (dpy, draw, font_set, gc, x, y, wstring,

                                                                                num_wchars)

 

void XmbDrawText (dpy, draw, gc, x, y, items, nitems)

void XwcDrawText (dpy, draw, gc, x, y, items, nitems)

 

      Ces fonctions sont les homologues des fonctions XDrawText, XDrawString et XDrawImageString introduites dans le chapitre précédent.

                  XmbDrawString et XwcDrawString dessinent simplement la chaîne indiquée dans la couleur d'avant‑plan du contexte graphique avec les fontes spécifiées par l'ensemble de fontes, indépendamment de celle spécifiée dans le contexte graphique. De même XmbDrawImageString et XwcDrawImageString ne consultent le contexte graphique que pour déterminer le style de remplissage et les couleurs produites.

                  XmbDrawText et XwcDrawText permettent de dessiner sur une même ligne des items dans des ensembles de fontes différents (pour avoir par exemple du gras ou de l'italique sur un mot isolé dans la ligne). Ces fonctions utilisent respectivement des structures XmbTextItem et XwcTextItem qui sont analogues aux structures XTextItem utilisées par XDrawText (cf. section 8.4.), excepté que la fonte est spécifiée ici par un ensemble de fontes lié à la localité.

 

 

 

8.4. Les méthodes d'entrée

                  De nombreuses langues utilisent un alphabet de lettres pour former des mots. Mais parfois, certaines lettres manquent au clavier et les utilisateurs doivent enfoncer plusieurs touches pour introduire un seul caractère. C'est le cas par exemple du français et en général des langues européennes lorsqu'elles sont tapées sur un clavier QWERTY. Des méthodes de compensation ont été développées et portent le nom de méthodes d'entrée européennes ou de méthodes d'entrée par composition.

 

                  Le japonais et le coréen fournissent des exemples de langues basées sur un alphabet phonétique. Le nombre des symboles utilisés est alors réduit, mais l'affichage des entrées peut varier chaque fois qu'un nouveau symbole est introduit. Il devient alors nécessaire de distinguer le caractère tapé au clavier du résultat produit par la combinaison de ce caractère avec les précédents. Des méthodes d'entrée standards utilisant de larges dictionnaires ont été développées pour ces deux langues. D'autres langues orientales comme le chinois présentent de nombreux systèmes d'entrée dont certains sont basés sur des décompositions idéographiques. Dans les systèmes idéographiques, l'utilisateur peut choisir dans différents menus des signes qui lui permettent de former progressivement un idéogramme. Il existe aujourd'hui environ 16 méthodes d'entrée standards du chinois (phonétiques et idéographiques).

 

                  Des méthodes d'entrée (input methods) ont donc été définies pour uniformiser l'architecture des programmes X et permettre l'internationalisation des programmes. Ces méthodes nécessitent généralement une ou plusieurs zones d'affichage permettant de donner un retour satisfaisant à l'utilisateur. Les zones définies par la librairie sont les suivantes :

                  • La zone de préédition (Preedit area). Quelque soit la langue, l'utilisateur peut parfois taper plusieurs touches pour composer un caractère. Le processus de composition de touches pour former des caractères est appelé préédition (preediting). Cette zone permettra de représenter les résultats intermédiaires tapés par le client.

                  • La zone de statut (Status area).  C'est la zone qui permet d'afficher les entrées qui ont été effectivement interprétées par la méthode d'entrée au point où en est l'utilisateur. Cette zone peut consister en des données textuelles ou bitmap, ou en une combinaison des deux.

 

                  Il existe également des zones auxiliaires qui sont utilisées pour présenter des menus et adapter des dialogues avec l'utilisateur. Mais les zones auxiliaires sont totalement indépendantes des applications et entièrement maintenues par la méthode d'entrée.

 Styles d'interaction

 

                  Différents styles d'interaction ont été identifiés par X pour l'affichage de la zone de préédition :

                  • On-the-spot input method. Les données de préédition sont affichées immédiatement dans la fenêtre de l'application et directement au point d'insertion. Ce sont les applications qui autorisent l'affichage des données au point d'insertion.

                  • Over-the-spot preediting. Cette fois les données sont affichées dans une fenêtre de préédition par dessus le point d'insertion.

                  • Off-the-spot preediting. Les données sont affichées dans une fenêtre de préédition positionnée à l'intérieur de la fenêtre de l'application, mais pas au point d'insertion. En général, cette fenêtre se trouve placée en bas de la fenêtre de l'application.

                  • Root-window preediting. Cette fois les données sont affichées dans une fenêtre spéciale, fille de la racine.

 

                  Plus généralement, les styles d'entrée d'une méthode d'entrée contiendront les indications des styles d'interaction utilisés pour l'affichage des zones de préédition et de statut.

 

 

Architecture d'implantation des méthodes d'entrée

 

                  L'édition et la préédition peuvent nécessiter de grands volumes de ressources mémoire ou calcul. Pour cette raison, les méthodes d'entrée sont souvent implantées comme processus séparé (un serveur d'entrée) et nécessitent une connexion spéciale à l'application.

 

                  De manière générale, la connexion à une méthode d'entrée dépend de la localité. Les méthodes d'entrée pourront être implantées comme librairie locale ou comme serveur autonome. L'implantation d'un serveur d'entrée implique un coût supplémentaire de communication mais les applications peuvent alors migrer sans recompilation de liens.

 

                  Les méthodes d'entrée peuvent être basées sur deux types d'architectures par rapport à la connexion du client au serveur X. Elles peuvent intervenir en amont de manière indépendante et servir en quelque sorte de filtre pour n'envoyer au client que des clés déjà recomposées (front-end architecture). Deux connexions indépendantes sont alors ouvertes au serveur X : la connexion ouverte par le client et celle ouverte par la méthode d'entrée. Les événements sur les touches sont dirigés systématiquement vers la méthode d'entrée et les autres événements vers le client. Il est alors nécessaire de synchroniser le client et la méthode d'entrée pour que le client sache quand il peut lire des entrées et éviter les blocages. Le mécanisme introduit permet également au client de récupérer les envois de touches autres que les caractères (comme les touches fonctions).

                  L'architecture peut également se situer après la connexion au serveur (back-end architecture). Dans ce cas, une seule connexion au serveur X est utilisée et un mécanisme de filtrage doit décider de ce qui revient à la méthode d'entrée et de ce qui revient à l’application. Quand la méthode d'entrée est un processus séparé, cette architecture doit prévoir un protocole de communication avec le serveur d'entrée.

 

                  Les deux types d'architecture ont leurs avantages et leurs inconvénients. Les architectures “avant” introduisent des problèmes de synchronisation et de filtrage. Les architectures “arrière” impliquent souvent un coût supplémentaire de communication et un plus grand nombre de commutations entre processus[9]. Quoi qu'il en soit, la communication avec une méthode d'entrée se fera au niveau de la Xlib par l'intermédiaire de structures opaques, représentées par les types XIM (pour X Input Method) et XIC (pour X Input Context), dont nous allons maintenant détailler l'usage.

 

 

 

8.5. Les contextes d'entrée

                  Pour permettre au client d'avoir éventuellement plusieurs zones de lecture d'entrée, la librairie a introduit la notion de contexte d'entrée (input context). Les contextes d'entrée (type XIC) permettent d'identifier une zone ayant le focus des entrées et fixent les paramètres caractérisant l'affichage et la communication entre le client et la méthode d'entrée.

 

                  Un contexte d'entrée est une combinaison entre une méthode d'entrée, une localité, une fenêtre du client, des informations sur un état interne du contexte (initial ou en cours d'interprétation), et de nombreux paramètres spécifiant les zones d'affichage et la communication avec le client. Nous allons donner d'abord un aperçu général des principes de communication entre la méthode d’entrée et le client pour simplifier l'exposé des sections suivantes.

 

 

Style d'entrée

 

                  La communication avec une méthode d'entrée s'effectue grâce à des fonctions et à différents paramètres du contexte d'entrée. Ces paramètres varient selon le style d'entrée qui a été choisi à la création du contexte. Tous les attributs ne sont donc pas toujours présents. En particulier, les attributs de préédition et les attributs de status n'existent pas toujours.

 

 

Focus d'un contexte d'entrée

 

                  Un contexte d'entrée est attaché à une unique méthode d'entrée, mais plusieurs contextes d'entrée peuvent être attachés à la même méthode, éventuellement dans une même fenêtre de l'application.             

 

                  Pour permettre la lecture à partir d'un contexte d'entrée particulier, il faudra que l'application lui donne le focus. Il ne s'agit pas tout à fait du focus de l'application puisque plusieurs contextes d'entrée peuvent être associés à une même fenêtre de l'application ; l'application peut attribuer le focus de la méthode d'entrée à un contexte particulier et le lui retirer (ou l'attribuer à un autre contexte) en fonction de changements internes à l'application. Ces changements ne correspondent pas nécessairement à des changements de focus rapportés par le serveur, ni même à des changements de fenêtres ; ils permettent simplement d'indiquer à la méthode d'entrée le contexte dans lequel elle va saisir et afficher les résultats obtenus. Cette opération d'attribution de focus sera effectuée avec la fonction XSetICFocus. Normalement, le client appellera XSetICFocus pour avertir la méthode d'entrée que la fenêtre de focus d'un contexte d'entrée a récupéré le focus du clavier. Cela permet à la méthode d'entrée d'effectuer en retour la mise en relief attendue par l'utilisateur.

 

                  Les contextes d'entrée jouent un rôle un peu analogue aux contextes graphiques en ceci qu'ils modifient les requêtes de lecture comme les contextes graphiques modifient les requêtes de dessin. C'est à l'application de décider si elle préfère créer plusieurs contextes pour passer d'une zone de lecture à l'autre (elle précisera alors à la méthode d'entrée quel est le contexte qui a le focus), ou si elle préfère n'associer qu'un seul contexte à sa fenêtre principale, et le modifier chaque fois que cela est nécessaire.

 

Lecture des entrées

 

                  Pour récupérer les entrées dans l'application le client devra appeler XmbLookupString ou XwcLookupString avec le contexte d'entrée. Les chaînes retournées par ces fonctions seront codées dans la localité présente à l'état initial. Le client appellera généralement ces fonctions sur réception des événements de type KeyPress. Si une synchronisation entre le client et la méthode d'entrée est nécessaire, la méthode d'entrée peut envoyer à l'application des événements de type KeyPress de champ keycode à zéro pour lui demander de faire appel à ces fonctions.

 

 

 

Filtrage des événements

 

                  Inversement, pour permettre à une méthode d'entrée de récupérer les événements se produisant dans des fenêtres de l'application, un mécanisme de filtrage a été prévu. En effet, la méthode d'entrée peut avoir besoin de traiter certains événements (comme par exemple les Expose se produisant sur la fenêtre de préédition). L'argument XNFilterEvents d'un contexte d'entrée permettra au client de récupérer le masque des événement nécessaires à la méthode d'entrée ; le client pourra alors l'ajouter à sa propre liste d'événements sélectionnés sur la fenêtre. Ensuite, il appellera la fonction XFilterEvent chaque fois qu'il recevra un événement, cet appel permettant à la méthode d'entrée de récupérer et de traiter éventuellement l'événement.

 

 

Callbacks

 

                  Pour permettre la communication avec la méthode d'entrée, des paramètres de type fonction sont également requis par certains styles de lecture. Ces fonctions sont définies par le client mais peuvent être appelées par la méthode d'entrée pour accomplir une certaine tâche. Par exemple, si c'est le client qui est responsable de l'édition des chaînes de préédition et qu'il appelle XmbLookupString, il doit parfois être averti des caractères intermédiaires à afficher avant le retour de la fonction, car sinon, certaines informations seraient perdues. Il est donc nécessaire que la méthode d'entrée lui rende la main pour qu'il accomplisse les affichages intermédiaires et cela, avant qu'elle ne termine. Ce type de paradoxe est résolu par l'utilisation de fonctions de callback. Les fonctions de rappel (ou callbacks) sont des fonctions dont la sémantique est prédéfinie, qui sont écrites par le client et données en argument au contexte d'entrée. Elles permettent de synchroniser les tâches de la méthode d'entrée avec celles du client. Il existe des callbacks permettant d'afficher des informations dans la zone de statut et des callbacks permettant d'afficher dans la zone de préédition. Ces fonctions interviendront dans des styles d'entrée bien précis (les styles StatusCallback et PreeditCallback).

 

 

Négociation géométrique des fenêtres d'entrée

 

                  Pour l'implantation des différents styles, une contribution du client est toujours nécessaire. Mais en dehors des styles nécessitant des callbacks, la répartition des responsabilités est très simple : la méthode d'entrée est responsable du contenu de la fenêtre d'entrée alors que le client est responsable de sa géométrie (taille, position). Les échanges d'information entre le client et la méthode d'entrée pour déterminer la géométrie des fenêtres d'affichage portent le nom de négociation géométrique.

 

                  Il faut en général que le client essaie de satisfaire les demandes du contexte d'entrée pour la géométrie des zones d'affichage. Pour cela, il doit consulter (de sa propre initiative[10]) le paramètre XNAreaNeeded (figurant dans les attributs XNStatusAttributes ou XNPreeditAttributes); ce paramètre indiquera les souhaits de la méthode d'entrée en ce qui concerne la zone considérée. Une méthode d'entrée peut ainsi suggérer une taille pour la zone de préédition ou la zone de statut. Mais c'est le client qui sera chargé en dernière instance d'informer la méthode d'entrée de la géométrie effective qu'il aura choisie, via l'attribut XNArea correspondant à la zone considérée.

 

8.6. La création de contextes d'entrée

                  On peut ouvrir une connexion à une méthode d'entrée avec la fonction

 

XIM   XOpenIM (dpy, db, res_name, res_class)

XrmDataBase                 db ;                           /* pointeur sur une base de ressources */

char *                                 res_name ;             /* nom de l'application */

char *                                 res_class ;              /* nom de la classe de l'application */

 

Cette méthode d'entrée et tous les contextes créés  à partir d'elle sont liés à la localité courante et à la spécification courante des modifieurs au moment de la création. Ces liaisons ne peuvent pas être changées dynamiquement. (On pourra cependant modifier la méthode d'entrée par défaut de la localité juste avant un appel à XOpenIM avec XSetLocaleModifiers).

 

                  L'argument db est une base de ressources dans laquelle la méthode d'entrée ira chercher les ressources privées dont elle a besoin. Les arguments res_name et res_class indiquent le nom et la classe des ressources permettant de trouver les valeurs de défaut de l'application pour les contextes d'entrée. Il est préférable de ne pas passer la valeur NULL. Ces ressources ne sont pas censées exister avant l'appel et ne dureront que l'espace de temps de vie de la méthode d'entrée. Si la fonction échoue, elle retournera NULL.

 

                  Signalons également quelques fonctions utiles sur les méthodes d’entrée :

 

Status XCloseIM (im)

Display * XDisplayOfIM (im)

char * XLocaleOfIM (im)

XIM                  im;

 

      Pour fermer une connexion à une méthode d'entrée, on utilisera la fonction XCloseIM. La fonction XDisplayOfIM  permet de récupérer le dispositif d’afichage auquel la méthode d’entrée se trouve reliée et XLocaleOfIM permet de récupérer le nom de la localité courante.

 

 

Liste d'arguments de longueur variable

 

                  Plusieurs requêtes sur les méthodes d'entrée utilisent une liste d'arguments variable. Dans la suite, trois points de suspension en argument dénotent une telle liste. Une liste d'arguments de longueur variable est constituée d'alternances de nom et valeur, les noms étant des chaînes de caractères et les valeurs ayant toujours le type XPointer. La fin de la liste est indiquée par l'argument (de nom) NULL.

 

                  Une liste d'arguments de longueur variable peut aussi contenir une liste de longueur variable. Dans ce cas, le nom XVaNestedList sera utilisé à la place du nom de l'argument et la valeur qui suit est interprétée comme une liste de longueur variable introduite à cet endroit. La fin de la liste imbriquée est elle aussi indiquée par la chaîne NULL. Pour allouer dynamiquement une liste de longueur variable, on utilisera la fonction

 

          XVaNestedList XVaCreateNestedList (bidon, ...)

          int bidon ;               /* inutilisé, mais requis par ANSI C */

 

Cette liste pourra être libérée par XFree.

 

 

Les styles d'entrée d'une méthode d'entrée

 

                  Une méthode d'entrée peut être interrogée avec la requête XGetIMValues, pour connaître les styles d'entrée qu'elle supporte, et ses besoins en matière de zones d'affichage. Cette requête se présente avec une liste d'arguments de longueur variable :

 

char *  XGetIMValues (im, ...)

                  Le seul nom d'argument standard défini par la librairie Xlib est XNQueryInputStyle. Dans la Xlib, tous les symboles commençant par XN décrivent des chaînes de caractères prédéfinies[11]. La valeur associée à ce nom est une structure de type XIMStyles dont on récupérera ici l'adresse dans le pointeur passé en argument (celui qui suivra immédiatement XNQueryInputStyle). La structure de type XIMStyles récupérée pourra être libérée ensuite par XFree. Cette structure est définie figure 8.2. Elle permet de récupérer les styles supportés par la méthode d'entrée. La liste des styles supportés est une liste de combinaisons de masques. On combine différents masques car on combine en réalité différents styles d'interaction pour les zones de préédition et les zones de statut. Chaque élément de la liste indique une combinaison acceptable et toutes les combinaisons possibles figurent dans la liste.

 

          typedef unsigned long XIMStyle;   /* masques */

 

          typedef struct {

                            unsigned short      count_styles;

                            XIMStyle *           supported_styles;

          } XIMStyles

 

fig. 8.2. La structure XIMStyles définissant les styles d'entrée

 

                  Chaque masque indique au client s'il y a des valeurs nécessaires au fonctionnement du style donné. Les différents masques et leur signification sont énumérés ci-après. Concernant les styles d'interaction pour la zone d'affichage de préédition, on aura les styles :

 

XIMPreeditArea              Le client doit fournir une zone de préédition, i.e. une valeur à XNArea dans les attributs de préédition XNPreeditAttributes (cette valeur pourra être négociée en consultant la valeur de XNAreaNeeded).

 

XIMPreeditCallbacks Le client doit fournir toutes les callbacks de préédition : XNPreeditStartCallback, XNPreeditDoneCallback, XNPreeditDrawCallback  et XNPreeditCaretCallback.

 

XIMPreeditPosition Le client doit fournir des valeurs de positions de préédition (XNSpotLocation et XNFocusWindow).

 

XIMPreeditNothing     La méthode d'entrée fonctionne seule, sans valeur d'attributs de préédition.

 

XIMPreeditNone              La méthode d'entrée ne fournit pas de retour de préédition et toutes les valeurs de préédition sont ignorées.

 

Les possibilités de styles de la zone de statut sont les suivantes :

XIMStatusArea                 Le client doit fournir une valeur de zone XNArea pour l'affichage du statut. Cet attribut sera donné dans la liste des attributs de statut XNStatusAtrtributes (et sa valeur sera négociée à partir de celle de XNAreaNeeded).

 

XIMStatusCallbacks Le client doit définir des callbacks pour l'affichage du statut courant : XNStatusStartCallback, XNStatusDoneCallback  et XNStatusDrawCallback.

 

XIMStatusNothing        La méthode d'entrée affiche seule les résultats, sans consulter de valeurs de statut.

 

XIMStatusNone                 La méthode d'entrée ne propose aucune édition de statut et les toutes les valeurs de statut sont ignorées.

 

                  Par exemple, une méthode d'entrée pourra supporter les deux styles XIMPreeditNone | XIMStatusCallbacks et XIMPreeditPosition | XIMStatusArea. Avec la première combinaison, la méthode d'entrée n'affiche aucun résultat de préédition mais affiche les entrées de touches déjà interprétées à l'aide des fonctions de callback fournies par le client. Dans le second style, elle affiche les données de préédition directement au point d'insertion indiqué par le client, et les données de statut dans la zone indiquée par le client.

 

                  Le client choisit donc un style parmi les différentes combinaisons qui lui sont proposées par la méthode d'entrée et crée un contexte d'entrée lié à ce style. La fonction qui permet de créer un contexte d'entrée est XCreateIC.

 

XIC   XCreateIC (im, ...)

XIM                  im;

 

                  La liste d'arguments variable permet ici d'affecter des valeurs aux paramètres du contexte d'entrée. Certaines valeurs doivent impérativement figurer dès la création. Il s'agit du style d'entrée (l'argument XNInputStyle), qui doit être sélectionné parmi les styles supportés par la méthode d'entrée dans la localité courante (liste retournée par XGetIMValues), et de l'ensemble des fonctions de callback, si ces dernières sont requises par le style sélectionné. Toutes les autres valeurs pourront être affectées plus tard avec la fonction XSetICValues. Si XCreateIC échoue[12], elle retourne le pointeur NULL.

 

 

Affectation et récupération de valeurs

 

                  Les opérations de consultation et d’affectation sont effectuées grâce aux requêtes XSetICValues et XGetICValues :

 

char *  XGetICValues (ic, ...)

char *  XSetICValues (ic, ...)

XIC                   ic ;

 

                  Ces fonctions retournent NULL si aucune erreur n'est survenue. Sinon, elles retournent le nom du premier argument qui n'a pu être respectivement lu ou affecté. Une erreur peut provenir du fait qu'un nom d'argument n'est pas reconnu, ou qu'un argument qui est affecté n'est en réalité disponible qu'en lecture.

 

                  Les valeurs utilisées par un contexte d'entrée sont relatives au style choisi par l'utilisateur. Les tables qui suivent décrivent comment ces valeurs peuvent être affectées (cf. figures 8.3. et 8.4.).  Le client doit parfois négocier la géométrie de la zone d'affichage. Dans cette négociation, il doit en général d'abord consulter les valeurs du contexte suggérées par la méthode d'entrée, puis affecter les arguments requis par le style qu'il aura retenu. La première colonne (Gestion géométrique) indique si ces valeurs affectent la géométrie et si elles nécessitent une négociation avec la méthode d'entrée. Les colonnes suivantes indiquent comment une valeur doit être affectée relativement à un style donné.

 

 

                   Styles

Paramètres

Gestion Géométrique

Preedit Callback

Preedit Position

Preedit Area

Preedit Nothing

Preedit None

InputStyle

 

C-G

C-G

C-G

C-G

C-G

ClientWindow

 

O-G

O-G

O-G

---

---

FocusWindow

GN

D-S-G

D-S-G

D-S-G

D-S-G

---

RessourceName

 

---

D-S-G

D-S-G

D-S-G

---

RessourceClass

 

---

D-S-G

D-S-G

D-S-G

---

GeometryCallback

 

---

---

D-S-G

---

---

FilterEvents

 

G

G

G

G

---

PreeditAttributes

 

 

 

 

 

 

Area

GS

---

D-S-G

D-S-G

---

---

AreaNeeded

GN-GR

---

---

S-G

---

---

SpotLocation

 

---

C-S-G

---

---

---

Colormap

 

---

D-S-G

D-S-G

D-S-G

---

Foregroung

 

---

D-S-G

D-S-G

D-S-G

---

Background

 

---

D-S-G

D-S-G

D-S-G

---

BackgroundPixmap

 

---

D-S-G

D-S-G

D-S-G

---

FontSet

GN

---

C-S-G

C-S-G

D-S-G

---

LineSpacing

GN

---

D-S-G

D-S-G

D-S-G

---

Cursor

 

---

D-S-G

D-S-G

D-S-G

---

PreeditCallbacks

 

C-S-G

---

---

---

---

 

fig. 8.3. Accès aux valeurs des attributs selon le style de préédition

 

 

                   Styles

Paramètres

Gestion Géométrique

Status Callback

Status

Area

Status Nothing

Status None

InputStyle

 

C-G

C-G

C-G

C-G

ClientWindow

 

O-G

O-G

O-G

---

FocusWindow

GN

D-S-G

D-S-G

D-S-G

---

RessourceName

 

---

D-S-G

D-S-G

---

RessourceClass

 

---

D-S-G

D-S-G

---

GeometryCallback

 

---

D-S-G

---

---

FilterEvents

 

G

G

G

G

StatusAttributes

 

 

 

 

 

Area

GS

---

D-S-G

---

---

AreaNeeded

GN-GR

---

S-G

---

---

Colormap

 

---

D-S-G

D-S-G

---

Foregroung

 

---

D-S-G

D-S-G

---

Background

 

---

D-S-G

D-S-G

---

BackgroundPixmap

 

---

D-S-G

D-S-G

---

FontSet

GN

---

C-S-G

D-S-G

---

LineSpacing

GN

---

D-S-G

D-S-G

---

Cursor

 

---

D-S-G

D-S-G

---

StatusCallbacks

 

C-S-G

---

---

---

 

fig. 8.4. Accès aux valeurs des attributs selon le style de statut

 

                   Les lettres utilisées par ces tables ont la signification suivante :

 

C                               La valeur doit être affectée à la création avec XCreateIC.

D                               La valeur doit être affectée à la création par XCreateIC ou bien une valeur de défaut sera fournie.

G                               La valeur peut être récupérée avec XGetICValues.

S                                Cette valeur sera affectée par XSetICValues.

GN                            Cette valeur peut donner lieu à une négociation géométrique quand elle est affectée par XCreateIC ou XSetICValues.

GR                            Cette valeur sera la réponse de la méthode d'entrée quand une valeur de négociation (type GN) est affectée.

GS                            Cette valeur fixera la géométrie de la fenêtre de la méthode d'entrée.

O                               Cette valeur doit être affectée une fois et une seule.

---                              La valeur est ignorée dans ce style.

8.7. Les paramètres du contexte d'entrée

                  Voici une brève description des paramètres d’un contexte d’entrée :

 

Style d'entrée

 

XNInputStyle                    Le style d'interaction utilisé. Sa valeur détermine l’ensemble des attributs nécessaires. Cet argument doit être fixé à la création du contexte et ne peut ensuite être modifié.

 

                  Les valeurs possibles sont à choisir parmi les différentes combinaisons proposées par la méthode d’entrée. Pour déterminer un style d’édition, il faut d’abord faire un appel à XGetIMValues (pour récupérer les différentes combinaison possibles) en interrogeant la méthode sur la valeur de l’argument XNQueryInputStyle. Le style choisi détermine alors les contraintes sur les affectations des autres attributs (cf. dans la section précédente, Les styles d’entrées, et Affectation et récupération de valeurs).

 

 

Fenêtres d'affichage et de lecture des entrées

 

XNClientWindow              Cet argument a le type Window. Il indique à la méthode d'entrée la fenêtre du client qui pourra être utilisée pour afficher les entrées ou pour y créer des sous-fenêtres.

 

                   Cette valeur ne peut être affectée qu'une seule fois. La négociation géométrique de la zone d'affichage sera effectuée relativement à cette fenêtre. Il n'est normalement pas prévu de changement dynamique.

 

XNFocusWindow                 Cet argument permet de spécifier la fenêtre qui recevra les entrées du clavier.

 

La méthode d'entrée peut modifier cette fenêtre en y sélectionnant des événements, en lui envoyant des événements, et en modifiant ses propriétés ; elle peut aussi y saisir le clavier. Si la fenêtre de focus n'est pas affectée, elle sera par défaut égale à la fenêtre du client spécifiée dans XNClientWindow. Le client devra appeler XSetICFocus et XUnsetICFocus pour avertir la méthode d'entrée des changements de focus concernant la fenêtre de focus du contexte d'entrée (cf. section 8.9. Mise en œuvre).

Paramètres de communication

 

XNResourceName

XNResourceClass

 

Ces chaînes spécifient les noms complets utilisés par le client pour indiquer les ressources de la fenêtre d’affichage. Ils seront utilisés par la méthode d'entrée pour accéder aux ressources.

 

XNGeometryCallback Cet argument est de type XIMCallback (cf. figure 8.5.). Il spécifie la fonction qui sera appelée par la méthode d'entrée pour demander elle-même une négociation de la géométrie de la zone d'affichage.

 

     typedef void (*XIMProc)();

  typedef struct {

             XPointer    client_data ;

             XIMProc     callback;

  } XIMCallback ;

 

fig. 8.5. Le type XIMCallback

 

                   Cette callback n'est jamais nécessaire pour un fonctionnement correct de la méthode d'entrée ni du client. Elle peut cependant être utilisée quand les méthodes d'entrée autorisent des changements géométriques dynamiques. Elle permet à la méthode d'entrée d'initier elle-même une demande de négociation géométrique.

 

                  Chaque callback a sa sémantique particulière et comprend des données particulières. Cependant, toutes les callbacks satisfont au prototype :

 

void CallbackPrototype (ic, client_data, call_data)

XIC  ic ;                             /* spécifie le contexte d'entrée */

XPointer         client_data ;           /* données additionnelles */

UnType           call_data ;              /* type specifique a chaque callback */

 

                  Dans le cas de la GeometryCallback, l'argument de type call_data a le type XPointer et sera toujours NULL.

 

XNFilterEvents              Cet argument ne peut qu'être lu. Il retourne le masque d'événements que la méthode d'entrée souhaite traiter sur la fenêtre du client.

                  Le client doit effectuer ensuite la sélection souhaitée par la méthode d’entrée en rajoutant ce masque au sien propre sur la fenêtre XNClientWindow, et utiliser ensuite la fonction XFilterEvent sur chaque événement reçu par cette fenêtre pour permettre à la méthode d'entrée de filtrer les événements qui l'intéressent (cf. section 8.8).

 

 

Paramètres de préédition et de statut

 

XNPreeditAttributes

XNStatusAttributes

 

Ces deux arguments spécifient les attributs qui doivent être utilisés pour les zones de préédition et de statut si elles existent. Les valeurs de ces attributs seront affectés avec XSetICValues et récupérés avec XGetICValues sous la forme d'une liste d'arguments de longueur variable dont les noms sont décrits ci-après (section 8.8.).

 

                  On se conformera aux indications des tables données par les figures 8.3. et 8.4. pour l'affectation et la récupération des valeurs de ces attributs. Le détail des valeurs des arguments de ces listes est donné dans la section suivante.

 

 

8.8. Attributs de préédition et de statut

                  Les valeurs qui sont décrites dans cette section correspondent aux valeurs des attributs affectables dans les listes associées aux paramètres XNPreeditAttributes et XNStatusAttributes d'un contexte d'entrée. Ces valeurs peuvent donc figurer comme valeurs de préédition ou de statut.

 

XNArea                                      Cet argument est un pointeur sur un XRectangle. Son interprétation dépend du style de la méthode d'entrée (voir ci-après). S'il n'est pas spécifié, le défaut sera fourni par la géométrie de la fenêtre indiquée par XNFocusWindow. S'il est NULL, le résultat est imprévisible.

 

                  Si le style est XIMPreeditPosition, XNArea spécifie la zone de clipping dans laquelle se fera l'affichage de la préédition. Si une fenêtre de focus a été indiquée, les composantes sont relatives à cette fenêtre ; sinon, elles sont relatives à la fenêtre du client. Si aucune des fenêtres n'est spécifiée, le résultat est indéfini.

                  Si le style est XIMPreeditArea ou XIMStatusArea, XNArea spécifie la géométrie fournie par le client. La méthode d'entrée peut utiliser cette zone (en préédition ou en statut selon les attributs affectés) pour afficher ses entrées. La méthode d'entrée peut créer une sous-fenêtre de la fenêtre du client aux dimensions indiquées par la zone. Les composantes sont relatives à la fenêtre du client.

 

XNAreaNeeded                    Cet argument permet au client de suggérer une géométrie pour la zone XNArea et d'en récupérer la valeur attendue par la méthode d'entrée (négociation géométrique). Comme XNArea, sa valeur est un pointeur sur un XRectangle et son interprétation dépend du style de la méthode d'entrée. Il n'est valide que si le style est XIMPreeditArea ou XIMStatusArea et n'est utilisé que dans la négociation géométrique avec le client. (Il n'a pas d'autre effet sur la méthode d'entrée.)

 

                  Dans la négociation géométrique, le client suit les étapes suivantes : Il suggère (éventuellement) des valeurs en affectant XNAreaNeeded. Ensuite, il récupère la valeur de XNAreaNeeded avec XGetICValues. La méthode d'entrée a dû faire de son mieux pour maintenir la valeur proposée par le client mais suggère elle aussi une taille. Ensuite, il affecte cette valeur (ou une autre) à XNArea pour indiquer à la méthode d'entrée son choix final. La méthode d'entrée ne peut de toute manière qu'accepter la géométrie qu'il aura choisie, mais il est recommandé au client de tenir compte des souhaits émis par la méthode d'entrée dans XNAreaNeeded.

 

                  Le client doit en outre tenir compte du fait que d'autres affectations de valeurs (XNFontSet, XNLineSpacing) peuvent modifier les besoins géométriques de la méthode d'entrée. C'est la responsabilité du client de renégocier la géométrie chaque fois qu'il modifiera dans le contexte d'entrée des valeurs qui en dépendent.

 

XNSpotLocation              Cet argument a le type pointeur sur un XPoint. Il donne les composantes du point d'entrée dans le style XIMPreeditPosition et n’est pas utilisé par ailleurs.

 

                  La position en x indique la position du prochain caractère à insérer. La position en y fournit la ligne de base dans la fenêtre ayant le focus. Les composantes x et y sont relatives à XNFocusWindow si elle a été affectée, sinon elles sont relatives à la fenêtre du client. Si aucune des fenêtres n'est affectée, le résultat est aléatoire.

XNColormap

XNStdColormap

 

XNColormap permet d'identifier une table de couleurs (Colormap) et XNStdColormap permet d'indiquer une table standard en fournissant un Atom. Ces tables seront utilisées par la méthode d'entrée pour y allouer les couleurs.

 

XNForeground

XNBackground

 

Ces attributs indiquent les couleurs d'avant-plan et d'arrière‑plan utilisables par la méthode d'entrée. Ces pixels doivent être valides dans la table utilisée par la méthode d'entrée.

 

XNBackgroundPixmap Cet argument indique un Pixmap de pavage pour le fond de la fenêtre utilisée par la méthode d'entrée.

 

XNFontSet                             Cet argument indique quel ensemble de fontes la méthode d'entrée doit utiliser pour afficher les chaînes. Sa valeur peut intervenir dans la négociation géométrique.

 

XNLineSpacing                 Cet argument (type int) sera utilisé si la méthode d'entrée affiche des textes sur plusieurs lignes. Sa valeur peut intervenir dans la négociation géométrique.

 

XNCursor                                Cet argument (type Cursor) permet de spécifier le curseur qui apparaîtra dans la fenêtre de la méthode.

 

 

                  De nombreuses callbacks sont requises par les styles XIMPreeditCallbacks et XIMStatusCallbacks. Un client qui souhaite utiliser le style XIMPreeditCallbacks doit fournir l'ensemble des callbacks de préédition XNPreeditStartCallback, XNPreeditDoneCallback, XNPreeditDrawCallback et XNPreeditCaretCallback dans la liste des attributs de préédition. Un client qui souhaite utiliser le style XIMStatusCallbacks doit fournir (dans la liste des attributs de statut) l'ensemble des callbacks XNStatusStartCallback, XNStatusDoneCallback et XNStatusDrawCallback.  Toutes les fonctions de callback sont données sous la forme d'un pointeur sur une structure XIMCallback (cf. figure 8.5. page 199) et doivent être fournies dès la création du contexte d'entrée.

 

                   La plupart du temps, les programmes utilisent des toolkits pour interagir avec la méthode d'entrée, et seuls les programmeurs de toolkits ont besoin de se pencher sur la sémantique particulière des callbacks. Voici cependant à titre d'exemple, le prototypage des callbacks intervenant dans le style  XIMStatusCallbacks.

void StatusStartCallback (ic, client_data, call_data)

XIC  ic ;                             /* spécifie le contexte d'entrée */

XPointer         client_data ;           /* données additionnelles */

XPointer          call_data ;              /* toujours NULL pour cette callback */

 

                  Cette fonction sera appelée pour que les données nécessaires à l'affichage de la zone de statut soient préparées. On peut s'attendre ensuite à recevoir plusieurs appels à StatusDrawCallback, puis à un appel à StatusDoneCallback qui clora la séquence d'entrée avant qu'un nouvel appel à StatusStartCallback ne soit exécuté.

 

void StatusDoneCallback (ic, client_data, call_data)

XIC  ic ;                             /* spécifie le contexte d'entrée */

XPointer         client_data ;           /* données additionnelles */

XPointer          call_data ;              /* toujours NULL pour cette callback */

 

                  Quand un contexte d'entrée est détruit ou qu'il perd le focus, la méthode d'entrée appelle StatusDoneCallback.

 

 

typedef enum {

   XIMTextType,

   XIMBitmapType,

} XIMStatusDataType ;

 

typedef struct _XIMStatusDrawCallbackStruct {

   XIMStatusDataType type ;

   union {

               XIMText  *text;

               Pixmap      bitmap;

   } data ;

} XIMStatusDrawCallbackStruct ;

 

fig. 8.6. Le type XIMStatusDrawCallbackStruct

 

 

void StatusDrawCallback (ic, client_data, call_data)

XIC  ic ;                             /* spécifie le contexte d'entrée */

XPointer         client_data ;           /* données additionnelles */

XIMStatusDrawCallbackStruct* call_data ;         

 

                  StatusDrawCallback doit mettre à jour la zone de statut des entrées soit en dessinant une chaîne de caractères, soit en dessinant un bitmap. La structure XIMStatusDrawCallbackStruct  est définie de sorte à préciser de quel type de dessin il est question (figure 8.6. page précédente).

 

                  Pour le prototypage des quatre callbacks intervenant dans le style XIMPreeditCallbacks nous renvoyons le lecteur à la documentation technique.

 

8.9. Mise en œuvre

                  Si l'on récapitule les sections précédentes, le client a dû en début de programme effectuer les opérations suivantes pour créer un contexte d'entrée :

                  • Affecter la localité courante (en général avec setlocale, XSupportsLocale et XSetLocaleModifiers).

                  • Récupérer la méthode d'entrée courante avec XOpenIM.

                  • Choisir un style d'entrée à partir de XGetIMValues.

                  • Créer un contexte d'entrée avec XCreateIC.

A ce stade, on distingue deux grands cas : les styles fonctionnant avec des callbacks et les autres. Dans les styles fonctionnant avec des fonctions de callback, ces dernières auront dû être fournies dès la création du contexte d'entrée. Pour les autres, quand le style requiert une négociation géométrique, on créera d'abord un ensemble de fontes avec XCreateFontSet et on affectera les paramètres XNFontSet et XNLineSpacing avant de procéder à la négociation.

 

                  Une fois les valeurs nécessaires au bon fonctionnement d'un style d'entrée affectées, le client est invité à récupérer la valeur de XNFilterEvents. Il sélectionnera alors les événements correspondant à ce masque sur la fenêtre du client et utilisera la fonction XFilterEvent pour filtrer les événements après chaque appel à XNextEvent :

 

Bool XFilterEvent (&event, win)

XEvent            event ;

Window          win ;       

                  Cette fonction permet à la méthode d'entrée de récupérer les événements qui la concernent. Elle indique en outre par sa valeur de retour si l'événement a été filtré par une méthode d'entrée. Si l'argument win est à None, XFilterEvent applique le filtrage à la fenêtre qui a reçu l'événement. (L'argument win est fourni pour que les niveaux créés par-dessus la librairie Xlib qui font de la redirection puissent indiquer vers quelle fenêtre un événement a été redirigé.)

                  Si XFilterEvent retourne True, c'est qu'une méthode de lecture des entrées a filtré l'événement, et le client doit normalement ignorer cet événement. (Cependant, si une saisie du clavier a été déclenchée par le client et que cette fonction retourne True, le client doit abandonner la saisie.) Si XFilterEvent retourne False, le client peut traiter normalement l'événement.        

 

Un client doit également s'attendre à recevoir des événements de type KeyPress avec un keycode à zéro. De tels événements peuvent être envoyés par une méthode d'entrée qui a des entrées composées à faire lire au client. Cet événement sert conventionnellement de signal pour avertir le client qu'il peut appeler XmbLookupString ou XwcLookupString. Il ne sera jamais être utilisé à d'autres fins.

                  Les fonctions qui permettront de lire les entrées composées à partir d'une méthode d'entrée sont XmbLookupString ou XwcLookupString. Bien que la méthode d'entrée se charge parfois de l'affichage des entrées pour l'utilisateur, le client doit tout de même récupérer ces données pour pouvoir en disposer dans le programme. Le client appellera ces fonctions sur la réception des événements de type KeyPress :

int XmbLookupString (ic, &ev, buffer_return, bytes_buffer, &keysym_return,

                                                                &status_return)

int XwcLookupString (ic, &ev, wbuffer_return, wchars_buffer,

                                                                &keysym_return, &status_return)

XIC  ic ;

XEvent            ev ;                            /* nécessairement de type XKeyPressedEvent */

char*                 buffer_return ;

wchar_t *        wbuffer_return ;

int                      bytes_buffer, wchars_buffer ;

KeySym          keysym_return ;

Status                status_return ;

 

      Ces fonctions sont analogues à la fonction XLookupString que nous avons introduite dans la section 5.7. XmbLookupString retourne la longueur de la chaîne retournée dans buffer_return en bytes et XwcLookupString retourne la longueur de la chaîne en caractères. Ces fonctions prennent toutes deux en argument un contexte d'entrée qui n'a cependant pas besoin d'avoir le focus au moment de l'appel. L'événement spécifié doit par contre nécessairement avoir le type KeyPress. Le tampon de réponse est alloué par le client et sa taille maximale est annoncée par bytes_buffer ou wchars_buffer. Le codage symbolique n'est retourné dans keysym_return que si cet argument n'est pas NULL et status_return retourne une valeur qui indique la nature des données retournées. Les valeurs de retour possibles sont les suivantes :

XBufferOverflow           La chaîne retournée est trop large pour être copiée dans le buffer proposé. La taille requise est retournée comme valeur de la fonction. Le client doit rappeler la fonction avec le même événement et un buffer de taille adéquate.

 

XLookupNone                       Rien de consistant n'a été lu jusqu'à présent. La fonction retourne zéro.

 

XLookupChars                    Des caractères ont été composés à partir des entrées. Ils sont placés dans l'argument buffer_return et la longueur de la chaîne est retournée comme valeur de la fonction. La chaîne est codée dans la localité liée au contexte d'entrée. L'argument keysym_return n'est pas modifié.

 

XLookupKeysym                 Un code symbolique est retourné au lieu d'une chaîne. Le contenu de buffer_return n'est pas modifié et la fonction retourne zéro.

 

XLookupBoth                       Un code symbolique et une chaîne ont été retournés. Ce cas conjoint XLookupKeysym et XLookupChars.

 

                  Pour gérer les contextes d'entrée, le client dispose des fonctions suivantes :

void XSetICFocus (ic)

void XUnsetICFocus (ic)

 

                  XSetICFocus et XUnsetICFocus sont des fonctions permettant au client d'informer la méthode d'entrée des changements de focus concernant la fenêtre de focus du contexte d'entrée. XSetICFocus informe la méthode d'entrée de ce que la fenêtre de focus attachée au contexte d'entrée a reçu le focus et doit donc s'attendre à récupérer des clés. XUnsetICFocus a l'effet inverse. Affecter le focus à un contexte a pour effet de le supprimer aux autres contextes. Après un appel à ces fonctions, la méthode d'entrée peut effectuer les affichages de retour attendus par l'utilisateur.

 

                  D'autres fonctions permettent de ramener un contexte d'entrée dans son état initial :

char * XmbResetIC (ic)

wchar_t * XwcResetIC (ic)

XIC  ic ;

 

      Les valeurs retournées par ces fonctions sont les chaînes courantes prééditées (dans le format spécifié par le nom de la fonction). Les clients doivent libérer ces chaînes par XFree si elles ne sont pas nulles. Toutes les entrées qui étaient précédemment attachées à ce contexte sont supprimées par un appel à ces fonctions et la méthode d'entrée doit effacer les zones d'affichage dont elle a la charge. L'appel à ses fonctions ne change pas le focus de la méthode sur un contexte.

                 

                  Signalons pour clore ce chapitre deux fonctions liées aux contextes d'entrée :

XIM XIMOfIC (ic)

void XDestroy (ic)

XIC  ic ;

 

                  XIMOfIC retourne la méthode d'entrée à laquelle un contexte d'entrée est associée et XDestroy détruit le contexte d'entrée passé en argument.

 

 


 

 

       Les fonctions importantes

 

          setlocale

          Bool  XSupportsLocale ()

          char * XSetLocaleModifiers (modifiers_list)

 

          XFontSet XCreateFontSet (dpy, base_font_name_list,

                                                                                &missing_charset_list_return,

                                                                                &missing_charset_count_return,

                                                                                &def_string_return)

 

          int XmbTextExtents (font_set, string, num_bytes, &overall_ink_return,

                                                               &overall_logical_return)

          void XmbDrawString (dpy, draw, font_set, gc, x, y, string, num_bytes)

          void XmbDrawImageString (dpy, draw, font_set, gc, x, y, string, n_bytes)

          void XmbDrawText (dpy, draw, gc, x, y, items, nitems)

 

          int XwcTextExtents (font_set, wstring, num_wchar, &overall_ink_return,

                                                               &overall_logical_return)

          void XwcDrawString (dpy, draw, font_set, gc, x, y, wstring, num_wchars)

          void XwcDrawImageString (dpy, draw, font_set, gc, x, y, wstring,

                                                                                num_wchars)

          void XwcDrawText (dpy, draw, gc, x, y, items, nitems)

 

 

          XIM   XOpenIM (dpy, db, res_name, res_class)

          char *  XGetIMValues (im, ...)

          XIC   XCreateIC (im, ...)

          char *  XGetICValues (ic, ...)

          char *  XSetICValues (ic, ...)

 

          Bool XFilterEvent (&event, win)

          int XmbLookupString (ic, &ev, buffer_return, bytes_buffer,

                                                                                &keysym_return, &status_return)

          void XSetICFocus (ic)

          void XUnsetICFocus (ic)

          char * XmbResetIC (ic)

          wchar_t * XwcResetIC (ic)

 



[1] Cependant, la plupart des paramètres concernant la lecture des entrées sont instanciés à la création des contextes d'entrée et ne pourront ensuite être modifiés.

[2] Par exemple, en ANSI C, on aura des fonctions de lecture locale comme mblen, mbtowc, wctomb et strtok.

[3] Restreint à l'ensemble des caractères de nom de fichiers portables. Il s'agit des 65 caractères que l'on peut utiliser pour nommer des fichiers. Cet ensemble est le suivant : a..z A..Z 0..9 ._-

[4] POSIX = Portable Operating System Interface ISO/IEC 9945-1 (IEEE Std 1003.1).

[5] Cf. section 7.1. Les noms de fontes .

[6] Comme on va le voir, l'ensemble des jeux de caractères requis peut être récupéré avec cette même fonction.

[7]  Grossièrement, le premier nom de fonte de la liste indiquant directement un ensemble requis par l'environnement local sera sélectionné; sinon la première fonte XLFD à spécifier un sur‑ensemble des caractères requis fera l'affaire, ou bien l'algorithme recherchera une fonte XLFD comportant des propriétés analogues et permettant, moyennant quelques modifications de liens, de récupérer l'ensemble (ou un sur‑ensemble) des caractères requis.

[8] Cette chaîne n'est pas nécessairement constituée de caractères valides dans la localité, ni même de caractères de l'ensemble de fonte dans laquelle est effectué la requête. Mais le client pourra ainsi connaître la taille des caractères imprimés comme caractères de défaut.

[9] Par exemple, dans le cas de trois processus séparés (le serveur X, le serveur d'entrée et le client), il y a deux commutations de processus par entrée de clé en architecture arrière, alors qu'il n'y en a qu'une si le filtrage a été réalisé en amont.

[10] Il existe cependant une fonction de callback permettant à la méthode d'entrée d'initier une négociation concernant la géométrie de la fenêtre.

[11] Ces chaînes peuvent être obtenues en supprimant le préfixe XN et en mettant en minuscule la majuscule d'origine. Ainsi par exemple XNQueryInputStyle est en fait définie par la chaîne "queryInputStyle", de même XNFocusWindow représente la chaîne "focusWindow". Ces définitions figurent dans le fichier <X11/Xlib.h>.

[12] Cette fonction peut échouer si une valeur requise n'est pas fournie, ou si l'on tente d'affecter une valeur qui ne peut qu'être lue comme XNFilterEvents, ou encore si certains arguments sont inconnus.