Forum Programmation.c Affichage de caractères grecques UTF-8 dans Xorg

Posté par .
Tags :
3
10
nov.
2011

Bonjour,

Je travaille sur Debian Squeeze et je cherche a faire une application multilingue, Français et Grec.

Pour les caractères Grecs, on peut utiliser la norme iso8859-7.
C'est la table des caractères Grec moderne sur 8 bits (255 caractères).

On peut utiliser aussi la norme UTF-8 rassemble tout les caractères internationnaux dans 4*8bits.

J'ai fais un premier programme en C encodé en UTF-8, et je le lance à partir d'une console SSH avec PuTTY configuré en UTF-8 :

printf("test FR : bonjour\n");
printf("test GR : ΤΕΣΤΠΛΔΦΩΖ\n");

Les caractères grecs sont bien affichés dans la console PuTTY.

Ensuite j'ai fait un programme qui affiche ces textes dans Xorg avec Xlib :

#include <X11/Xlib.h>
#include <stdio.h>

int main(void) {
 Display *d;
 Window w;
 XEvent e;

 char *msg="ΟΑΣΔΦΖΧΨΩΒzeΒ";
 d = XOpenDisplay(NULL);
 if (d == NULL) {
  fprintf(stderr, "Cannot open display\n");
  exit(1);
 }

 int s;
 s = DefaultScreen(d);

 w = XCreateSimpleWindow(d, RootWindow(d, s), 10, 10, 200, 200, 1, BlackPixel(d, s), WhitePixel(d, s));

 XMapWindow(d, w);

 XSelectInput(d, w, ExposureMask);

 while (1) {
  XNextEvent(d, &e);
  if (e.type == Expose) {
   XDrawString(d, w, DefaultGC(d, s), 10, 20, msg, strlen(msg));
  }
 }

 XCloseDisplay(d);
 return 0;

}

Quand je le lance, Xorg n'affiche pas correctement les caractères grecs.

J'ai fait le même test avec la librairie Qt et j'ai le même résultat.

Je pense que ça vient des polices utilisées par Xorg.

Mais même en utilisant la police Unifont l'affichage n'est pas correct.
GNU Unifont : tous les codes de caractères imprimables d'« Unicode 5.1 Basic Multilingual Plane (BMP) » (Plan de base multilingue Unicode 5.1)

J'ai essayé aussi une police en version iso8859-7 :

-misc-fixed-medium-r-normal--8-80-75-75-c-50-iso8859-7

Toujours le même problème.

  • # Manque d'infos

    Posté par . Évalué à 1.

    1. fait nous des captures d'écrans.

    2. dans quelle locale lances-tu le programme sous X11 ?
      lance le à partir d'un xterm après avoir lancer la commande "locale"

    3. Tu peux aussi essayer efont.

    • [^] # Re: Manque d'infos

      Posté par . Évalué à 1.

      J'ai essayé avec deux locales :

      fr_FR.UTF-8
      el_GR.UTF-8

      en faisant :

      LANG=el_GR.UTF-8 Xorg
      DISPLAY=:0 LANG=el_GR.UTF-8 ./a.out

      Les 2 locales me donnent le même résultat

      dans xterm, printenv me donne :

      SHELL=/bin/bash
      TERM=xterm
      SSH_CLIENT=192.168.56.1 1891 22
      WINDOWID=2097165
      SSH_TTY=/dev/pts/1
      XTERM_SHELL=/bin/bash
      USER=root
      PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
      MAIL=/var/mail/root
      PWD=/root/test/xlib_2
      LANG=el_GR.UTF-8
      XTERM_LOCALE=el_GR.UTF-8
      XTERM_VERSION=XTerm(261)
      HOME=/root
      SHLVL=2
      LOGNAME=root
      SSH_CONNECTION=192.168.56.1 1891 192.168.56.21 22
      DISPLAY=:0.0
      _=/usr/bin/printenv

      Pour la capture d'écran :

      http://imageshack.us/photo/my-images/411/unledige.png/

      Sachant que je demande d'afficher le texte " ΟΑΣΔΦΖΧΨΩΒzeΒ"
      avec les polices :

      "-gnu-unifont-medium-r-normal--0-0-75-75-c-0-iso10646-1" et
      "-misc-fixed-bold-r-normal--0-0-100-100-c-0-iso8859-7"

      • [^] # Re: Manque d'infos

        Posté par . Évalué à 1.

        La capture d'écran semble suggérer que tu affiches plutôt du iso8859-7 que de l'UTF-8 mais avec une font unicode, ou l'inverse !

        Un autre point :
        pour moi, il faut définir LC_ALL et non pas LANG.
        Quand je lance :

        LANG=C localc
        
        

        Je continue d'avoir libreoffice en français;
        alors que quand je lance :
        LC_ALL=C  localc
        
        

        libreoffice est alors en anglais.

        Pourquoi ne pas essayer avec el_GR tout court pour comparer le résultat.

        • [^] # Re: Manque d'infos

          Posté par . Évalué à 0.

          J'ai essayé aussi avec LC_ALL.

          Il semble que LC_ALL et LANG aient le même rôle, après les programmes utilisent l'un ou l'autre.

  • # XDrawString -> Xutf8DrawString

    Posté par (page perso) . Évalué à 2.

    Si le code source est en UTF-8, les constantes chaînes de caractères le seront aussi. Dans ce cas, il vaudrait mieux utiliser Xutf8DrawString(), en passant comme XFontSet la valeur renvoyée par XCreateFontSet(d, "*", ...).

  • # Solution Qt

    Posté par . Évalué à 2.

    J'ai trouvée une solution avec Qt qui fonctionne :

    Ajouter après QApplication :

    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));

    D'après la doc :

    void QTextCodec::setCodecForCStrings ( QTextCodec * codec ) [static]

    Sets the codec used by QString to convert to and from const char * and QByteArrays. If the codec is 0 (the default), QString assumes Latin-1.

    Par contre j'ai toujours le problème avec xlib, XCreateFontSet semble complexe à utiliser.

    • [^] # Re: Solution Qt

      Posté par (page perso) . Évalué à 1.

      La doc de Xlib laisse à désirer, en effet, mais ce n'est pas aussi compliqué que ça en a l'air.
      J'ai modifié ton programme comme suit, en ajoutant pas mal de code de diagnostic, et ça a l'air de marcher. (À compiler avec -std=c99)

      #include <X11/Xlib.h>
      #include <stdio.h>
      #include <stdlib.h>
      #include <string.h>
      #include <locale.h>
      
      int main(void) {
       printf("setlocale() -> %s\n", setlocale(LC_ALL, ""));
      
       Display *d = XOpenDisplay(NULL);
       if (d == NULL) {
        fprintf(stderr, "Cannot open display\n");
        exit(1);
       }
      
       char **missing_charset_list = NULL;
       int missing_charset_count = 0;
       char *def_string = NULL;
       XFontSet fs = XCreateFontSet(d, "*", &missing_charset_list, &missing_charset_count, &def_string);
       printf("fs = %p, def_string = %s\n", fs, def_string);
       for (int i = 0; i < missing_charset_count; ++i)
        printf("missing_charset_list[%d] = %s\n", i, missing_charset_list[i]);
       XFreeStringList(missing_charset_list);
       if (fs == NULL)
        exit(1);
      
       int s = DefaultScreen(d);
      
       char msg[] = "ΟΑΣΔΦΖΧΨΩΒzeΒ";
       Window w = XCreateSimpleWindow(d, RootWindow(d, s), 10, 10, 200, 200, 1, BlackPixel(d, s), WhitePixel(d, s));
      
       XMapWindow(d, w);
      
       XSelectInput(d, w, ExposureMask);
      
       while (1) {
        XEvent e;
        XNextEvent(d, &e);
        if (e.type == Expose) {
         XmbDrawString(d, w, fs, DefaultGC(d, s), 10, 20, msg, strlen(msg));
        }
       }
      
       XFreeFontSet(d, fs);
      
       XCloseDisplay(d);
       return 0;
      
      }
      
      
      • [^] # Re: Solution Qt

        Posté par . Évalué à 1.

        En effet ça marche.

        Il faut modifier :

        XMapWindow(d, w);

        XSelectInput(d, w, ExposureMask);

        par :

        XSelectInput(d, w, ExposureMask);

        XMapWindow(d, w);

        pour avoir l'affichage.

        Merci

  • # wchar_t?

    Posté par (page perso) . Évalué à 1.

    je sais pas mais avec des wchar_t ça marcherais pas mieux ?

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.