Re: Problem with Gtext.iter in menuitem callback

Maxence Guesdon <[email protected]> Fri, 21 May 2010 13:19:36 +0200
Newsgroups gmane.comp.lang.ocaml.lib.gtk
Message-ID <[email protected]>
Le Thu, 20 May 2010 17:24:11 +0200,
Alain Mebsout <[email protected]> a écrit :

> Hi lablgtk,
>

Hello,

> I'm trying to insert some text in a source_buffer when clicking on a 
> menu item (in a popup menu, which shows on right clicking a certain
> tag).
> 
> Here is a simplified version of my callback function :
> 
> let triggers_callback (buffer:GSourceView.source_buffer) ~origin:y z
> i = let ni = new GText.iter i in
>    match GdkEvent.get_type z with
>      | `BUTTON_PRESS ->
> buffer#insert ~iter:ni " | new trigger"; (* THIS WORKS FINE *)
>          let z = GdkEvent.Button.cast z in
>          if GdkEvent.Button.button z = 3 then
>            let menu = GMenu.menu () in
>            let image = GMisc.image ~stock:`ADD () in
>            let menuitem = GMenu.image_menu_item
>                  ~image ~label:"Add trigger(s) ..."
> ~packing:menu#append () in
>            ignore(menuitem#connect#activate
>                      ~callback:(fun () ->
> buffer#insert ~iter:ni " | new trigger")
>                      (* GTK ERROR *)
>              );
>            menu#popup ~button:3 ~time:(GdkEvent.Button.time z);
>            true
>          else
>            false
>      | _ -> false
> 
> The first call to buffer#insert does what it's expected to do but the 
> second one which is connected to the menu item raises a gtk error
> (and sometimes a segfault if I try to access the iter e.g. with 
> iter#forward_char). It looks like the iter does not exists anymore. I 
> would be grateful if anybody could give me a hint on whether I'm
> missing something here or if there's strange magic happening in menu
> items.
> 
> Here is the gtk error triggered by the second call to buffer#insert :
> 
> Gtk-WARNING **: Invalid text buffer iterator: either the iterator is 
> uninitialized, or the characters/pixbufs/widgets in the buffer have
> been modified since the iterator was created.
> You must use marks, character numbers, or line numbers to preserve a 
> position across buffer modifications.
> You can apply tags and insert marks without invalidating your
> iterators, but any mutation that affects 'indexable' buffer contents
> (contents that can be referred to by character offset)
> will invalidate all outstanding iterators
> 
> Gtk-CRITICAL **: gtk_text_buffer_insert: assertion 
> `gtk_text_iter_get_buffer (iter) == buffer' failed

As the warning says, you're using a deprecated iter. As soon as you
change the contents of the buffer, your iter is deprecated and you
must create a new one, for example from an absolute position.
You may try something like this:

after "let ni = new GText.iter in", add
"let offset = ni#offset in"

Then, where you used "ni", you can now create a new iter from the
abolute offset:
let ni = buffer#get_iter (`OFFSET offset) in

then use this new anv valid iter:
buffer#insert ~iter: ni ...

(this is not tested but is the general way of working with iters)

Regards,

Maxence