IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

GTK+ avec C & C++ Discussion :

coloration syntaxique en temps réel


Sujet :

GTK+ avec C & C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Inscrit en
    Janvier 2007
    Messages
    293
    Détails du profil
    Informations forums :
    Inscription : Janvier 2007
    Messages : 293
    Par défaut coloration syntaxique en temps réel
    Bonjour,

    Dans le cadre d'un mini-projet en théorie des langages et programmation je suis amené à faire un éditeur d'algortihme capable de colorier le texte.

    Le projet est presque fini, si j'ouvre un fichier ma fonction qui colorie le texte fonctionne correctement (cette fonction contient un appel à un lexer qui reconnait les mots clés) renvoie une structure qui contient le mot et si il est mot cle ou pas (color = TRUE or FALSE)

    mon problème est le suivant, je veux arriver à colorier au fur et à mesure que l'utilisateur tape son texte au clavier, pour celà j'utilise une méthode pour le moins inélégante qui est la suivante.

    à chaque fois que l'utilisateur tape un caractère, je relis tout le GtkTextBuffer, l'envoi en traitement à ma fonction colorier, où le lexer fait sa cuisine, ensuite insere le texte tagger. (le lexer renvoie une liste chainee donc chauqe noeud est défini comme suit

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    struct mot
    {
    	int color;	/* si c'est un mot cle color = TRUE sinon color = FALSE */
    	char *mot_cle;	/* le mot cle a afficher */
    	struct mot *p_suivant; /* pointeur sur le noeud suivant */
    };
    problème : je fais l'appel à la fonction colorier dans le cb_modifier de ma zone texte

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    /* Creation de la zone de texte  */
       {
    	   GtkTextBuffer *p_tampon_zone_texte = NULL;
          GtkWidget *p_fenetre_defilement = NULL;
     
          p_zone_texte = gtk_text_view_new ();
     
          gtk_text_view_set_indent (GTK_TEXT_VIEW (p_zone_texte), 2);
     
    	   /* On cree la fenetre avec barre de defilement */
          p_fenetre_defilement = gtk_scrolled_window_new (NULL, NULL);
     
          /* On masque les barre de defilement si on en a pas besoin */
          gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (p_fenetre_defilement),
                                          GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
     
          /* On ajoute la fenetre barre de defilementa la boite principale */
          gtk_box_pack_start (GTK_BOX (p_boite_principale), p_fenetre_defilement, TRUE, TRUE, 0);
     
    	   /* La zone texte doit apparaitre grisee */
    	   gtk_widget_set_sensitive  (p_zone_texte, FALSE);
     
    	   /* On associe la zone texte à son tampon */
      	   p_tampon_zone_texte = gtk_text_view_get_buffer (GTK_TEXT_VIEW (p_zone_texte));
     
      	   /* Si on a modifie la zone texte, on doit mettre la variable docs.p_document->modifie
      	      a FALSE */
    	   g_signal_connect (G_OBJECT (p_tampon_zone_texte), "changed", G_CALLBACK (cb_modifie), NULL);
     
    	   /* On ajoute la zone texte a la fenetre de defilement */
          gtk_container_add (GTK_CONTAINER (p_fenetre_defilement), p_zone_texte);
     
           /* creation du tag gras */
          gtk_text_buffer_create_tag (p_tampon_zone_texte, "bold", "weight", 551, NULL);
     
          /* creation du tag couleur bleue et gras */
          gtk_text_buffer_create_tag (p_tampon_zone_texte, "mot_cle", "weight", 551, "foreground", "blue", NULL);
     
       }
    voilà le cb_modifier

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    void cb_modifie (GtkWidget *p_widget, gpointer donnees_utilisateur)
    {
       if (docs.p_document_actif != NULL)
       {
          /* Si le document existe */
     
          /* On met que le document a ete modifie */
          docs.p_document_actif->modifie = FALSE;
     
          /* on va colorier le texte qu'on a taper, toute la chaine de caractere
             dans le tampon est réanalysee, recoloriee et affichee apres effacement
             de la zone texte precedente */
     
          GtkTextIter debut;
          GtkTextIter fin;
          GtkTextBuffer *p_tampon_zone_texte;
     
          /* on selectionne le tampon de la zone texte a l'aide des 2 iterateurs */
          p_tampon_zone_texte = gtk_text_view_get_buffer (docs.p_document_actif->p_zone_texte);
          gtk_text_buffer_get_bounds (p_tampon_zone_texte, &debut, &fin);
     
          /* on recupere la chaine a colorie */
          gchar *chaine = gtk_text_buffer_get_text (p_tampon_zone_texte, &debut, &fin, FALSE);
     
          /* on colorie */
          printf ("%s\n", chaine);
          colorier_chaine (chaine, docs.p_document_actif->p_zone_texte);
     
       }
     
       (void)p_widget;
       (void)donnees_utilisateur;
    }
    ainsi que m'a fonction colorié

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    static void colorier_chaine (gchar *chaine, GtkTextView *p_zone_texte)
    {
       struct mot *p_liste = NULL;
       GtkTextBuffer *p_tampon_zone_texte = NULL;
       GtkTextMark *cursor;
       GtkTextIter position_curseur ;
     
       /* On recupere le tampon d'affichage de la zone texte */
       p_tampon_zone_texte = gtk_text_view_get_buffer (p_zone_texte);
     
       /* On efface le tampon de la zone de texte */
          GtkTextIter debut;
          GtkTextIter fin;
     
       /* on selectionne le tampon de la zone texte a l'aide des 2 iterateurs */
          p_tampon_zone_texte = gtk_text_view_get_buffer (docs.p_document_actif->p_zone_texte);
          gtk_text_buffer_get_bounds (p_tampon_zone_texte, &debut, &fin);
     
       /* et on supprime */
       gtk_text_buffer_delete (p_tampon_zone_texte, &debut, &fin);
     
       /* appelle au lexer qui traite les informations de la chaine */
       p_liste = lexer (chaine);
     
       if (p_liste != NULL)
       {
          /* le traitement a reussi */
     
          p_liste = p_liste->p_suivant;
     
          /* on affiche chaque mot de la liste */
          while (p_liste != NULL)
          {
             if (p_liste->color == TRUE)
             {
                /* c'est un mot cle, on tag */
     
                /* Get the mark at cursor. */
                cursor = gtk_text_buffer_get_mark (p_tampon_zone_texte, "insert");
                /* Get the iter at cursor. */
                gtk_text_buffer_get_iter_at_mark (p_tampon_zone_texte, &position_curseur, cursor);
     
                gtk_text_buffer_insert_with_tags_by_name
                (p_tampon_zone_texte, &position_curseur, p_liste->mot_cle, -1, "mot_cle", NULL);
             }
             else
             {
                /* Ce n'est pas un mot cle on touche a rien */
                gtk_text_buffer_insert_at_cursor (p_tampon_zone_texte, p_liste->mot_cle, -1);
             }
     
             p_liste = p_liste->p_suivant;
          }
     
          /* on libere la liste chainee */
          p_liste = liberer_liste (p_liste);
       }
    }
    le problème est le suivant,

    j'arrive bien à lire le GtkTextBuffer à chaque modification (j'ai testé avec des printf, ça marche), le souci c'est quand je fais cet appel

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    colorier_chaine (chaine, docs.p_document_actif->p_zone_texte);
    dans cb_modifier, j'ai une boucle infinie, plus rien n'est affiché, et au final l'application plante (j'imagine que j'ai du mal libérer de la mémoire quelque part).

    En faite si je comprends bien mon problème est le suivant, quand je lis le GtkTextBuffer dans cb_modifier y'a pas de souci, quand j'envoie le texte lu à traiter dans colorier, cette fonction colorie et écrit dans le GtkTextBuffer, le problème c'est que à ce moment là, le GtkTextBuffer est modifié et donc je relis directement la même chaine de caractères tapé, la retraite, remodifie et c'est le cycle infernal. Et là je sais pas comment faire pour aficher ma chaine coloriée sans que cb_modifier soit appellé et que ce cycle ce perpétue.

    Merci

  2. #2
    Rédacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2004
    Messages
    5 840
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 42
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Par défaut
    Bonjour,

    ça tombe bien, je suis en train de faire un éditeur WYSIWYG, voici ce que j'ai fait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    static void insert_text (GtkTextBuffer *buffer, GtkTextIter *location,
                             gchar *text, gint len, gpointer user_data)
    {
      GList *tmp = NULL;
      GtkTextIter start;
     
      start = *location;
      gtk_text_iter_backward_chars (&start, len);
      for (tmp = g_list_first (active_tags); tmp != NULL; tmp = g_list_next (tmp))
      {
        gtk_text_buffer_apply_tag_by_name (buffer, (gchar *)tmp->data, &start,
                                           location);
      }
    }
     
    static void gtk_wysiwyg_init (GtkWysiwyg *this)
    {
      GtkTextBuffer *buffer = NULL;
     
      g_return_if_fail (this != NULL);
     
      buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (this));
      g_signal_connect (buffer, "insert-text", G_CALLBACK (insert_text), this);
    }
    Le code complet (enfin, le début...) : GtkWysiwyg

  3. #3
    Membre éclairé
    Inscrit en
    Janvier 2007
    Messages
    293
    Détails du profil
    Informations forums :
    Inscription : Janvier 2007
    Messages : 293
    Par défaut
    Bonjour,

    en faite pour implémenter ce que je veux faire avec ta méthode j'aurais besoin d'un temps et de connaissances dont je ne dispose malheureusement pas pour l'instant

    N'y a t'il pas un moyen pour faire comprendre à cette instruction

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    g_signal_connect (G_OBJECT (p_tampon_zone_texte), "changed", G_CALLBACK (cb_modifie), NULL);

    que quand mon lexer insere du texte dans le GtkTextBuffer ce n'est pas un signal qui doit faire appel à cb_modifie. En faite l'appel à cb_modifie ne doit ce faire quand quand l'utilisateur tape du texte dans la zone de texte.

  4. #4
    Membre éclairé
    Inscrit en
    Janvier 2007
    Messages
    293
    Détails du profil
    Informations forums :
    Inscription : Janvier 2007
    Messages : 293
    Par défaut
    Bon résolu avec l'aide de 2 variables globales (on fait cqu'on peut)

    Merci

  5. #5
    Membre Expert
    Homme Profil pro
    Inscrit en
    Janvier 2005
    Messages
    1 259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 1 259
    Par défaut
    Tu peux déconnecter temporairement ton callback aussi avec g_signal_handlers_disconnect_by_func

  6. #6
    Membre éclairé
    Inscrit en
    Janvier 2007
    Messages
    293
    Détails du profil
    Informations forums :
    Inscription : Janvier 2007
    Messages : 293
    Par défaut
    Citation Envoyé par teuf13 Voir le message
    Tu peux déconnecter temporairement ton callback aussi avec g_signal_handlers_disconnect_by_func
    Bonsoir,

    je pense que c'est bien ce que je cherchais, jvais essayer de trouver des examples sur google.

    Merci

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Voir requête éxécuté en temps réel ?
    Par [DreaMs] dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 08/01/2004, 14h52
  2. Coloration syntaxique
    Par _-Sky-_ dans le forum Composants
    Réponses: 4
    Dernier message: 03/01/2004, 21h58
  3. cubes temps réel en ROLAP
    Par Guizz dans le forum MS SQL Server
    Réponses: 4
    Dernier message: 09/07/2003, 16h36
  4. Durée d'un traitement temps réel
    Par Almex dans le forum C
    Réponses: 5
    Dernier message: 29/03/2003, 14h15
  5. Coloration syntaxique ASM dans un RichEdit
    Par Crick dans le forum Composants VCL
    Réponses: 5
    Dernier message: 20/12/2002, 01h53

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo