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