turn on italics in TextView

classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

turn on italics in TextView

Doug McCasland
Hi,

I am trying GTK3 TextView, in C. I know how to apply tags, such as italics,
bold, etc., to a region of text.

But how do I "turn on" a style (italics, bold, etc) while typing in the
buffer? For example, suppose I am typing text and there are no styles set.
Then I want to type in italics. I want to apply the italic tag to the
insert point, after which whatever I typed would be in italics.

I notice that when you place the insert cursor to the right of any existing
styled text, the tags of the previous character are inherited, but only if
the style is in effect before and after the insert point. Interestingly,
the trailing newline can be stylized (invisibly), so when the insert point
is at the end of a line and the last visible character has a style, then
that style is inherited.

I've looked at some methods that use a key-press signal and then apply a
text tag to the region of the untagged character just typed, but that is
slow and looks odd on screen -- the plain char is displayed and then
replaced by the tagged char.

I've also tried:

gtk_text_buffer_insert_markup(buf, &iter, "<i>", -1);

but that gets a Warning: Invalid markup string: ... Element 'markup' was
closed, but the currently open element is 'i' and has no effect on the
displayed text. Using <i></i> gets no warning but also has no effect. I
finally resorted to:

gtk_text_buffer_insert_markup(buf, &iter, "<i> </i>", -1); // 2 spaces

gtk_text_iter_backward_char (&iter);

gtk_text_buffer_place_cursor(buf, &iter);

which lets me start typing in italics between 2 new (tagged) spaces --
that's not so bad.

But clicking an "I" button to start typing in italics -- that is a basic
editing function that has been around for decades. It must be possible in
GTK somehow?

thanks
_______________________________________________
gtk-app-devel-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: turn on italics in TextView

Gtk+ - Apps Dev mailing list

 
Hi Doug,

You can try using the "insert-text" callback to set your italics on the inserted text. This is what I came up with to test. The signal is connected after so that the update occurs first. Careful about not changing the location iter also since there is a warning in the documentation about doing so. Might not need to worry about it here but something to be aware of.

https://developer.gnome.org/gtk3/stable/GtkTextBuffer.html#GtkTextBuffer-insert-text

Eric


/*
  gcc -Wall textview2.c -o textview2 `pkg-config --cflags --libs gtk+-3.0`
  Tested on GTK3.18 and Ubuntu16.04
*/

#include<gtk/gtk.h>

static gboolean italic=FALSE;

static void toggle_italic(GtkToggleButton *toggle1, gpointer data)
  {
    GtkWidget *label=gtk_bin_get_child(GTK_BIN(toggle1));
    if(gtk_toggle_button_get_active(toggle1))
      {
        gtk_label_set_markup(GTK_LABEL(label), "<span style='italic'>Italics</span>");
        italic=TRUE;
      }
    else
      {
        gtk_label_set_text(GTK_LABEL(label), "Italics");
        italic=FALSE;
      }
    gtk_widget_grab_focus(GTK_WIDGET(data));
  }
static void new_text(GtkTextBuffer *textbuffer, GtkTextIter *location, gchar *text, gint len, gpointer user_data)
  {
    if(italic)
      {
        GtkTextIter *start=gtk_text_iter_copy(location);
        GtkTextIter *end=gtk_text_iter_copy(location);
        gtk_text_iter_backward_chars(start, len);
        gtk_text_buffer_apply_tag_by_name(textbuffer, "tag1", start, end);
        gtk_text_iter_free(start);
        gtk_text_iter_free(end);
      }
  }
int main (int argc, char *argv[])
  {
    gtk_init(&argc, &argv);

    GtkWidget *window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window), "Textview");
    gtk_window_set_default_size(GTK_WINDOW(window), 300, 200);
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);

    GtkWidget *text_view1=gtk_text_view_new();
    gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text_view1), GTK_WRAP_CHAR);
    gtk_widget_set_vexpand(text_view1, TRUE);
    gtk_widget_set_hexpand(text_view1, TRUE);

    GtkTextBuffer *buffer=gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view1));
    gtk_text_buffer_create_tag(buffer, "tag1", "style", PANGO_STYLE_ITALIC, NULL);
    g_signal_connect_after(buffer, "insert-text", G_CALLBACK(new_text), NULL);

    GtkWidget *toggle1=gtk_toggle_button_new_with_label("Italics");
    g_signal_connect(toggle1, "toggled", G_CALLBACK(toggle_italic), text_view1);

    GtkWidget *grid=gtk_grid_new();
    gtk_container_set_border_width(GTK_CONTAINER(grid), 8);
    gtk_grid_set_row_spacing(GTK_GRID(grid), 12);
    gtk_grid_attach(GTK_GRID(grid), text_view1, 0, 0, 1, 1);
    gtk_grid_attach(GTK_GRID(grid), toggle1, 0, 1, 1, 1);
   
    gtk_container_add(GTK_CONTAINER(window), grid);

    gtk_widget_show_all(window);

    gtk_main();

    return 0;
  }


 


_______________________________________________
gtk-app-devel-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: turn on italics in TextView

Gtk+ - Apps Dev mailing list

 
Here are a few things that might improve the above code a little. Use

gtk_button_set_focus_on_click(GTK_BUTTON(toggle1), FALSE);

instead of a grab. Also the global gboolean can be eliminated if you pass the toggle button pointer to the "insert-text" callback. Then you can just use

if(gtk_toggle_button_get_active(user_data))
 
For the sequence of events it is my understanding that the text changes will be made during the event cycle before the window gets re-painted.

https://developer.gnome.org/gtk3/stable/chap-drawing-model.html

Eric
 

 

 

-----Original Message-----
From: Doug McCasland <[hidden email]>
To: cecashon <[hidden email]>
Sent: Tue, Jun 13, 2017 4:09 pm
Subject: Re: turn on italics in TextView


cecashon, thanks so much for your great reply!


I had tried all those calls, but I hadn't put them together as you did, nor did I apply the tag in the way your code does.  And I didn't think of having one signal/function for the button-down and another for the apply_tag_by_name.  Cool!  


So your code gets a signal after the character(s) is entered. Then the style is applied to that char, without moving the insert point.  Do you know if the un-tagged char is visibly displayed first, and then altered?  Or is all the processing somehow finished before the display changes, and then only the tagged char is put on the screen.






_______________________________________________
gtk-app-devel-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: turn on italics in TextView

Doug McCasland
​Thanks again.  That works, but ​the state is lost when the cursor is
moved.  Here is some code to discover multiple styles after the cursor is
moved.  The pointers to the style tags are saved in globals, then in the
callback for the cursor move, we look for those pointers in the linked-list
returned by gtk_text_iter_get_tag().  I tried to use some of the other
link-list functions/macros, such as g_slist_position, but could only
get gtk_text_iter_get_tag() to work.  Maybe there's a more efficient way to
do this.

// globals
GSList *gtk_text_iter_get_tags (const GtkTextIter *iter);
GtkTextTag *italp, *boldp, *ulinep;

// call back after cursor is moved
  void
get_style(GtkTextView *tv, GtkMovementStep step,
        gint count, gboolean extend, gpointer *user_data)  {
GSList *tlist;
GtkTextIter start;
GtkTextMark *mark;
GtkTextBuffer *buf;

buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(tv));

mark = gtk_text_buffer_get_insert(buf);
gtk_text_buffer_get_iter_at_mark (buf, &start, mark);

tlist = gtk_text_iter_get_tags(&start);

// look for each style -- could used to set bits in a bitfield
if (g_slist_find(tlist, italp))
    g_printerr("got match for ital\n");
if (g_slist_find(tlist, boldp))
    g_printerr("got match for bold\n");
if (g_slist_find(tlist, ulinep))
    g_printerr("got match for uline\n");

}

. . .
main(...)
 . . .
italp = gtk_text_buffer_create_tag(buffer, "ital", "style",
PANGO_STYLE_ITALIC, NULL);
boldp =gtk_text_buffer_create_tag(buffer, "bold", "weight",
PANGO_WEIGHT_BOLD, NULL);
ulinep = gtk_text_buffer_create_tag(buffer, "uline", "underline",
PANGO_UNDERLINE_SINGLE, NULL);

g_signal_connect_after(text_view, "move-cursor", G_CALLBACK(get_style),
NULL);
. . .



On Wed, Jun 14, 2017 at 10:48 AM, <[hidden email]> wrote:

>
> Here are a few things that might improve the above code a little. Use
>
> gtk_button_set_focus_on_click(GTK_BUTTON(toggle1), FALSE);
>
> instead of a grab. Also the global gboolean can be eliminated if you pass
> the toggle button pointer to the "insert-text" callback. Then you can just
> use
>
> if(gtk_toggle_button_get_active(user_data))
>
> For the sequence of events it is my understanding that the text changes
> will be made during the event cycle before the window gets re-painted.
>
> https://developer.gnome.org/gtk3/stable/chap-drawing-model.html
>
> Eric
>
>
>
> -----Original Message-----
> From: Doug McCasland <[hidden email]>
> To: cecashon <[hidden email]>
> Sent: Tue, Jun 13, 2017 4:09 pm
> Subject: Re: turn on italics in TextView
>
> cecashon, thanks so much for your great reply!
>
> I had tried all those calls, but I hadn't put them together as you did,
> nor did I apply the tag in the way your code does.  And I didn't think of
> having one signal/function for the button-down and another for the
> apply_tag_by_name.  Cool!
>
> So your code gets a signal after the character(s) is entered. Then the
> style is applied to that char, without moving the insert point.  Do you
> know if the un-tagged char is visibly displayed first, and then altered?
> Or is all the processing somehow finished before the display changes, and
> then only the tagged char is put on the screen.
>
>
>
>


--
Doug McCasland   <[hidden email]>
_______________________________________________
gtk-app-devel-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: turn on italics in TextView

Gtk+ - Apps Dev mailing list

 
Another option is to look at the properties of the tags to get the information that you need. This might work better than saving globals and matching pointers.

Eric

...
    GSList *tlist=NULL;
    GSList *next=NULL;
    tlist=gtk_text_iter_get_tags(&start);
    if(tlist!=NULL)
      {
        do
          {
            next=tlist->next;
            gchar *string=NULL;
            g_object_get(G_OBJECT(tlist->data), "name", &string, NULL);
            g_print("%s\n", string);
            g_free(string);
            tlist=g_slist_next(tlist);
          }while(next!=NULL);
       }
    else g_print("No Tags\n");

    if(tlist!=NULL) g_slist_free(tlist);
...

 



_______________________________________________
gtk-app-devel-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: turn on italics in TextView

Gtk+ - Apps Dev mailing list

 
On that last post, I think that I have some bad pointer arithmetic. Moving a pointer past the end and freeing a moved pointer. Not so good.

Eric

...
    GSList *tlist=NULL;
    GSList *p=NULL;
    GSList *next=NULL;
    tlist=gtk_text_iter_get_tags(&start);
    p=tlist;
    if(tlist!=NULL)
      {
        do
          {
            next=p->next;
            gchar *string=NULL;
            g_object_get(G_OBJECT(p->data), "name", &string, NULL);
            g_print("%s\n", string);
            g_free(string);
            if(next!=NULL)p=g_slist_next(p);
          }while(next!=NULL);
       }
    else g_print("No Tag\n");

    if(tlist!=NULL) g_slist_free(tlist);
...

 

 

-----Original Message-----
From: Eric Cashon via gtk-app-devel-list <[hidden email]>
To: dougm <[hidden email]>
Cc: gtk-app-devel-list <[hidden email]>
Sent: Tue, Jun 20, 2017 4:48 pm
Subject: Re: turn on italics in TextView


 
Another option is to look at the properties of the tags to get the information that you need. This might work better than saving globals and matching pointers.

Eric

...
    GSList *tlist=NULL;
    GSList *next=NULL;
    tlist=gtk_text_iter_get_tags(&start);
    if(tlist!=NULL)
    {
        do
          {
            next=tlist->next;
            gchar *string=NULL;
            g_object_get(G_OBJECT(tlist->data), "name", &string, NULL);
            g_print("%s\n", string);
            g_free(string);
      tlist=g_slist_next(tlist);
          }while(next!=NULL);
       }
    else g_print("No Tags\n");

    if(tlist!=NULL) g_slist_free(tlist);
...

 



_______________________________________________
gtk-app-devel-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list

_______________________________________________
gtk-app-devel-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: turn on italics in TextView

Doug McCasland
Eric, thanks again.

I ended up using g_signal_connect() on "key-press-event" (instead of
"insert-text").  This makes it easier IMO to handle specific cases, since
the callback fn can return TRUE if it did anything or FALSE to get GTK
default behavior, unlike void insert-text fn.  Plus if you paste 20000
chars, the insert-text callback will process every one of them, whereas
key-press-event will get none of them.

I think I tried to do my own version of the move-cursor and change
italic/bold state buttons, but abandoned it, don't remember why.  But I
took the advice to "store" the italic/bold states in the toolbar button
states.  It's a little quirky since the text cursor can move away from an
italic/bold region and still the i/b tutton, if already pressed, stays that
way and so typing at the new cursor location is i/b.

Anyway, with Italic button pressed, for example, I get the char via
key-press-event.  (If style tool button not pressed, then return FALSE).
The characters are just keycodes at this point, so need to kick back most
of them to default:

    switch (event->keyval)  {
        case GDK_KEY_Return:
        case GDK_KEY_Delete:
        case GDK_KEY_Shift_L:
        case GDK_KEY_Shift_R:
        case GDK_KEY_Alt_L:
        case GDK_KEY_Alt_R:
        case GDK_KEY_Control_L:
        case GDK_KEY_Up:
        case GDK_KEY_Down:
        case GDK_KEY_Left:
        case GDK_KEY_Right:
        case GDK_KEY_End:
        case GDK_KEY_Home:
        // case GDK_KEY_BackSpace:
        return FALSE;
    }

or you get the first letter after "GDK_KEY_".  Still haven't fixed up the
backspace case.  Then call

text = gdk_keyval_name(event->keyval);

If strlen(text) > 1, then go through this exercise:

            switch (event->keyval)  {
                case GDK_KEY_exclam: text = "!"; break;
                case GDK_KEY_quotedbl: text = "\""; break;
                case GDK_KEY_numbersign: text = "#"; break;
                case GDK_KEY_dollar: text = "$"; break;
                case GDK_KEY_percent: text = "%"; break;
                case GDK_KEY_ampersand: text = "&"; break;
                case GDK_KEY_apostrophe: text = "'"; break;
                case GDK_KEY_parenleft: text = "("; break;
                case GDK_KEY_parenright: text = ")"; break;
                case GDK_KEY_asterisk: text = "*"; break;
                case GDK_KEY_plus: text = "+"; break;
                case GDK_KEY_colon: text = ":"; break;
                case GDK_KEY_less: text = "<"; break;
                case GDK_KEY_greater: text = ">"; break;
                case GDK_KEY_question: text = "?"; break;
                case GDK_KEY_at: text = "@"; break;
                case GDK_KEY_underscore: text = "_"; break;
                case GDK_KEY_braceleft: text = "{"; break;
                case GDK_KEY_bar: text = "|"; break;
                case GDK_KEY_braceright: text = "}"; break;
                case GDK_KEY_asciitilde: text = "~"; break;
            }

Then after all that malarkey, simply insert the char, get the iters around
it, and apply the style to it.  Then return TRUE.

So this works pretty good (good enough :-) ).

Even though I didn't use your suggested code

    GSList *tlist=NULL;
    GSList *next=NULL;
    tlist=gtk_text_iter_get_tags(&start);
    if(tlist!=NULL)
      {
        do
          {
            next=tlist->next;
            gchar *string=NULL;
            g_object_get(G_OBJECT(tlist->data), "name", &string, NULL);
            g_print("%s\n", string);
            g_free(string);
            tlist=g_slist_next(tlist);
          }while(next!=NULL);
       }
    else g_print("No Tags\n");

    if(tlist!=NULL) g_slist_free(tlist);

after cursor motion, I did deploy that elsewhere to find format tags (for
example in exporting to HTML, for which I have a crude version).  Once
again thanks for that do-while tlist loop -- I *never* would've figured out
how to write that!

--Doug


On Tue, Jun 20, 2017 at 10:47 PM, <[hidden email]> wrote:

>
> On that last post, I think that I have some bad pointer arithmetic. Moving
> a pointer past the end and freeing a moved pointer. Not so good.
>
> Eric
>
> ...
>     GSList *tlist=NULL;
>     GSList *p=NULL;
>     GSList *next=NULL;
>     tlist=gtk_text_iter_get_tags(&start);
>     p=tlist;
>     if(tlist!=NULL)
>       {
>         do
>           {
>             next=p->next;
>             gchar *string=NULL;
>             g_object_get(G_OBJECT(p->data), "name", &string, NULL);
>             g_print("%s\n", string);
>             g_free(string);
>             if(next!=NULL)p=g_slist_next(p);
>           }while(next!=NULL);
>        }
>     else g_print("No Tag\n");
>
>     if(tlist!=NULL) g_slist_free(tlist);
> ...
>
>
> -----Original Message-----
> From: Eric Cashon via gtk-app-devel-list <[hidden email]>
> To: dougm <[hidden email]>
> Cc: gtk-app-devel-list <[hidden email]>
> Sent: Tue, Jun 20, 2017 4:48 pm
> Subject: Re: turn on italics in TextView
>
>
>
> Another option is to look at the properties of the tags to get the
> information that you need. This might work better than saving globals and
> matching pointers.
>
> Eric
>
> ...
> GSList *tlist=NULL;
> GSList *next=NULL;
> tlist=gtk_text_iter_get_tags(&start);
> if(tlist!=NULL)
> {
> do
> {
> next=tlist->next;
> gchar *string=NULL;
> g_object_get(G_OBJECT(tlist->data), "name", &string, NULL);
> g_print("%s\n", string);
> g_free(string);
> tlist=g_slist_next(tlist);
> }while(next!=NULL);
> }
> else g_print("No Tags\n");
>
> if(tlist!=NULL) g_slist_free(tlist);
> ...
>
>
>
>
>
> _______________________________________________
> gtk-app-devel-list mailing list
> [hidden email]
> https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
>
_______________________________________________
gtk-app-devel-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: turn on italics in TextView

Gtk+ - Apps Dev mailing list

 


Hi Doug,

I made a bit of a pointer mess there. Not the best of answers or way to go about iterating through a list. Looking at some GTK code, this is better done with a for loop. As usual, you don't want to move the pointer you get from gtk_text_iter_get_tags() and then free it. This will cause you grief later on along with buggy code that may not be so easy to debug.

Very glad you got things working well even with a less than good answer. Need to be careful of the pointers myself.

Eric


    GSList *tlist=NULL;
    GSList *p=NULL;
    tlist=gtk_text_iter_get_tags(&start);
    g_print("List %p p %p\n", tlist, p);
    for(p=tlist;p;p=p->next)
      {
        gchar *string=NULL;
        g_object_get(G_OBJECT(p->data), "name", &string, NULL);
        g_print("p %p %s\n", p, string);
        g_free(string);
      }

    g_print("List %p\n", tlist);
    if(tlist!=NULL) g_slist_free(tlist);
_______________________________________________
gtk-app-devel-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: turn on italics in TextView

Doug McCasland
Heh-heh, yes that for loop does look better :-)  I'll use that.

Textview is awesome and will save me thousands of lines of code, but not
being able to apply a tag to an iter -- that has been a big drawback for
me.  You can discover a tag at an iter, but only apply/remove it to a
range.  It would be great to be able to apply a style tag at an iter
(including in a blank line) and then have text inserted their use that tag.

One more suggestion for GTK Textview -- this is about the margin and indent
tags.  I found that you can apply those tags anywhere in a line and even
multiple times.  So in a 100-char line, you can have chars 33-45 with an
indent of 100px, and chars 63-88 with an indent of -50px, etc.  And in
addition various left-margins.  When you move the cursor through such a
line, the cursor bounces around like crazy and the line is reformatted back
and forth.  I cannot imagine why anyone would want this.  Such tags should
only apply to whole lines, and only one indent or left-margin tag per
line.  As it is, the applied indent and margin tags are hard to manage and
cause too much trouble.


On Tue, Aug 15, 2017 at 11:34 AM, <[hidden email]> wrote:

>
>
> Hi Doug,
>
> I made a bit of a pointer mess there. Not the best of answers or way to go
> about iterating through a list. Looking at some GTK code, this is better
> done with a for loop. As usual, you don't want to move the pointer you get
> from gtk_text_iter_get_tags() and then free it. This will cause you grief
> later on along with buggy code that may not be so easy to debug.
>
> Very glad you got things working well even with a less than good answer.
> Need to be careful of the pointers myself.
>
> Eric
>
>
>     GSList *tlist=NULL;
>     GSList *p=NULL;
>     tlist=gtk_text_iter_get_tags(&start);
>     g_print("List %p p %p\n", tlist, p);
>     for(p=tlist;p;p=p->next)
>       {
>         gchar *string=NULL;
>         g_object_get(G_OBJECT(p->data), "name", &string, NULL);
>         g_print("p %p %s\n", p, string);
>         g_free(string);
>       }
>
>     g_print("List %p\n", tlist);
>     if(tlist!=NULL) g_slist_free(tlist);
>



--
Doug McCasland   <[hidden email]>
_______________________________________________
gtk-app-devel-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: turn on italics in TextView

Gtk+ - Apps Dev mailing list

Have you tried gtk_text_buffer_insert_with_tags_by_name() to insert text with a tag at an iter?

What tag combo do you use to get the cursor to bounce around? If I test having two indent tags on the same line, the first one applied wins out. This is what I tested with.

Eric


/*
  gcc -Wall move_cursor1.c -o move_cursor1 `pkg-config --cflags --libs gtk+-3.0`
  Tested on GTK3.18 and Ubuntu16.04
*/

#include<gtk/gtk.h>

static void get_style(GtkTextView *tv, GtkMovementStep step, gint count, gboolean extend, gpointer *user_data)
  {
    static int i=1;
    GtkTextIter start;
    GtkTextMark *mark;
    GtkTextBuffer *buf;

    buf=gtk_text_view_get_buffer(GTK_TEXT_VIEW(tv));

    mark=gtk_text_buffer_get_insert(buf);
    gtk_text_buffer_get_iter_at_mark (buf, &start, mark);
    g_print("Iter %i\n", gtk_text_iter_get_offset(&start));

    GSList *tlist=NULL;
    GSList *p=NULL;
    tlist=gtk_text_iter_get_tags(&start);
    g_print("%i. List %p p %p\n", i, tlist, p);
    i++;
    for(p=tlist;p;p=p->next)
      {
        gchar *string=NULL;
        g_object_get(G_OBJECT(p->data), "name", &string, NULL);
        g_print("p %p %s\n", p, string);
        g_free(string);
      }

    g_print("List %p\n", tlist);
    if(tlist!=NULL) g_slist_free(tlist);
  }
int main (int argc, char *argv[])
  {
    gtk_init(&argc, &argv);

    GtkWidget *window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window), "Move Cursor");
    gtk_window_set_default_size(GTK_WINDOW(window), 300, 200);
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);

    GtkWidget *textview=gtk_text_view_new();
    gtk_widget_set_vexpand(textview, TRUE);
    gtk_widget_set_hexpand(textview, TRUE);
    g_signal_connect(textview, "move-cursor", G_CALLBACK(get_style), NULL);

    GtkTextBuffer *buffer=gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview));
    gtk_text_buffer_create_tag(buffer, "ital", "style", PANGO_STYLE_ITALIC, NULL);
    gtk_text_buffer_create_tag(buffer, "bold", "weight", PANGO_WEIGHT_BOLD, NULL);
    gtk_text_buffer_create_tag(buffer, "uline", "underline", PANGO_UNDERLINE_SINGLE, NULL);
    gtk_text_buffer_create_tag(buffer, "indent", "indent", 20, NULL);
    gtk_text_buffer_create_tag(buffer, "indent2", "indent", 40, NULL);
    gtk_text_buffer_create_tag(buffer, "left-margin", "left-margin", 20, NULL);
    gtk_text_buffer_create_tag(buffer, "left-margin2", "left-margin", 40, NULL);    

    GtkTextIter iter;
    gtk_text_buffer_get_start_iter(buffer, &iter);
    gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, "ital ", -1, "ital", NULL);
    gtk_text_buffer_get_end_iter(buffer, &iter);
    gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, "bold ", -1, "bold", NULL);
    gtk_text_buffer_get_end_iter(buffer, &iter);
    //Check a newline for a tag.
    gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, "uline \n", -1, "uline", NULL);
    gtk_text_buffer_get_end_iter(buffer, &iter);
    gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, "all\n", -1, "ital", "bold", "uline", NULL);
    //Check indents in the same line.
    gtk_text_buffer_get_end_iter(buffer, &iter);
    gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, "indent ", -1, "indent", NULL);
    gtk_text_buffer_get_end_iter(buffer, &iter);
    gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, "indent2\n", -1, "indent2", NULL);
    gtk_text_buffer_get_end_iter(buffer, &iter);
    gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, "indent2\n", -1, "indent2", NULL);
    //Check left-margin in the same line.
    gtk_text_buffer_get_end_iter(buffer, &iter);
    gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, "left-margin ", -1, "left-margin", NULL);
    gtk_text_buffer_get_end_iter(buffer, &iter);
    gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, "left-margin2\n", -1, "left-margin2", NULL);
    gtk_text_buffer_get_end_iter(buffer, &iter);
    gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, "left-margin2", -1, "left-margin2", NULL);

    GtkWidget *grid=gtk_grid_new();
    gtk_container_set_border_width(GTK_CONTAINER(grid), 8);
    gtk_grid_attach(GTK_GRID(grid), textview, 0, 0, 1, 1);
   
    gtk_container_add(GTK_CONTAINER(window), grid);

    gtk_widget_show_all(window);

    gtk_main();

    return 0;
  }
_______________________________________________
gtk-app-devel-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: turn on italics in TextView

Doug McCasland
Indeed, gtk_text_buffer_insert_with_tags_by_name() does what it says.  What
I was talking about was (in some future Textview) applying the tag to an
iter, then whenever the insert point was on that iter, it would inherit the
tag properties set there.  So typing at that point gets the formatting.

I don't have my code in front of me, but as I recall the jumpy-cursor thing
happened with this:

   1. Insert some text in a line.
   2. Apply indent 50px to whole line.  The line will be indented on the
   screen.
   3. Start typing at the beginning of line, which will not inherit the
   indent tag.  The indent will disappear on the screen.
   4. Move the cursor to the region with the applied indent -- the indent
   comes back.



On Tue, Aug 15, 2017 at 2:27 PM, <[hidden email]> wrote:

>
> Have you tried gtk_text_buffer_insert_with_tags_by_name() to insert text
> with a tag at an iter?
>
> What tag combo do you use to get the cursor to bounce around? If I test
> having two indent tags on the same line, the first one applied wins out.
> This is what I tested with.
>
> Eric
>
>
> /*
>   gcc -Wall move_cursor1.c -o move_cursor1 `pkg-config --cflags --libs
> gtk+-3.0`
>   Tested on GTK3.18 and Ubuntu16.04
> */
>
> #include<gtk/gtk.h>
>
> static void get_style(GtkTextView *tv, GtkMovementStep step, gint count,
> gboolean extend, gpointer *user_data)
>   {
>     static int i=1;
>     GtkTextIter start;
>     GtkTextMark *mark;
>     GtkTextBuffer *buf;
>
>     buf=gtk_text_view_get_buffer(GTK_TEXT_VIEW(tv));
>
>     mark=gtk_text_buffer_get_insert(buf);
>     gtk_text_buffer_get_iter_at_mark (buf, &start, mark);
>     g_print("Iter %i\n", gtk_text_iter_get_offset(&start));
>
>     GSList *tlist=NULL;
>     GSList *p=NULL;
>     tlist=gtk_text_iter_get_tags(&start);
>     g_print("%i. List %p p %p\n", i, tlist, p);
>     i++;
>     for(p=tlist;p;p=p->next)
>       {
>         gchar *string=NULL;
>         g_object_get(G_OBJECT(p->data), "name", &string, NULL);
>         g_print("p %p %s\n", p, string);
>         g_free(string);
>       }
>
>     g_print("List %p\n", tlist);
>     if(tlist!=NULL) g_slist_free(tlist);
>   }
> int main (int argc, char *argv[])
>   {
>     gtk_init(&argc, &argv);
>
>     GtkWidget *window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
>     gtk_window_set_title(GTK_WINDOW(window), "Move Cursor");
>     gtk_window_set_default_size(GTK_WINDOW(window), 300, 200);
>     gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
>     g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
>
>     GtkWidget *textview=gtk_text_view_new();
>     gtk_widget_set_vexpand(textview, TRUE);
>     gtk_widget_set_hexpand(textview, TRUE);
>     g_signal_connect(textview, "move-cursor", G_CALLBACK(get_style), NULL);
>
>     GtkTextBuffer *buffer=gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview)
> );
>     gtk_text_buffer_create_tag(buffer, "ital", "style",
> PANGO_STYLE_ITALIC, NULL);
>     gtk_text_buffer_create_tag(buffer, "bold", "weight",
> PANGO_WEIGHT_BOLD, NULL);
>     gtk_text_buffer_create_tag(buffer, "uline", "underline",
> PANGO_UNDERLINE_SINGLE, NULL);
>     gtk_text_buffer_create_tag(buffer, "indent", "indent", 20, NULL);
>     gtk_text_buffer_create_tag(buffer, "indent2", "indent", 40, NULL);
>     gtk_text_buffer_create_tag(buffer, "left-margin", "left-margin", 20,
> NULL);
>     gtk_text_buffer_create_tag(buffer, "left-margin2", "left-margin", 40,
> NULL);
>
>     GtkTextIter iter;
>     gtk_text_buffer_get_start_iter(buffer, &iter);
>     gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, "ital ", -1,
> "ital", NULL);
>     gtk_text_buffer_get_end_iter(buffer, &iter);
>     gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, "bold ", -1,
> "bold", NULL);
>     gtk_text_buffer_get_end_iter(buffer, &iter);
>     //Check a newline for a tag.
>     gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, "uline \n",
> -1, "uline", NULL);
>     gtk_text_buffer_get_end_iter(buffer, &iter);
>     gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, "all\n", -1,
> "ital", "bold", "uline", NULL);
>     //Check indents in the same line.
>     gtk_text_buffer_get_end_iter(buffer, &iter);
>     gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, "indent ",
> -1, "indent", NULL);
>     gtk_text_buffer_get_end_iter(buffer, &iter);
>     gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, "indent2\n",
> -1, "indent2", NULL);
>     gtk_text_buffer_get_end_iter(buffer, &iter);
>     gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, "indent2\n",
> -1, "indent2", NULL);
>     //Check left-margin in the same line.
>     gtk_text_buffer_get_end_iter(buffer, &iter);
>     gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, "left-margin
> ", -1, "left-margin", NULL);
>     gtk_text_buffer_get_end_iter(buffer, &iter);
>     gtk_text_buffer_insert_with_tags_by_name(buffer, &iter,
> "left-margin2\n", -1, "left-margin2", NULL);
>     gtk_text_buffer_get_end_iter(buffer, &iter);
>     gtk_text_buffer_insert_with_tags_by_name(buffer, &iter,
> "left-margin2", -1, "left-margin2", NULL);
>
>     GtkWidget *grid=gtk_grid_new();
>     gtk_container_set_border_width(GTK_CONTAINER(grid), 8);
>     gtk_grid_attach(GTK_GRID(grid), textview, 0, 0, 1, 1);
>
>     gtk_container_add(GTK_CONTAINER(window), grid);
>
>     gtk_widget_show_all(window);
>
>     gtk_main();
>
>     return 0;
>   }




--
Doug McCasland   <[hidden email]>
_______________________________________________
gtk-app-devel-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Loading...