GTK+ Forums

Discussion forum for GTK+ and Programming. Ask questions, troubleshoot problems, view and post example code, or express your opinions.
It is currently Fri Nov 21, 2014 2:21 am

All times are UTC




Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: problem with key-press-event
PostPosted: Wed Dec 21, 2011 7:48 pm 
Offline
GTK+ Geek

Joined: Sun Apr 03, 2011 11:12 am
Posts: 63
Hello, everyone, I am trying to create an IDE for Python. For, that I want to modify key-press-event. Here's the code for modifying key-press-event. Here, I had modified key-press-event for Enter Key. This will provide indentation in two case, if the line contains ':' or if it has some brackets opened (i.e. open brackets not having their close brackets). Whenever I uncomment the code for second case (which present here under comments "Problem with this code" and "/************/") and press Enter, I get the result as if I had pressed Enter twiced. I mean, if I press enter once, I will had two new lines created. Please, tell me where's the error.
Here's the code:
Code:
static gboolean txtinput_key_press_event(GtkWidget *widget,GdkEventKey *event)
{
    GtkTextBuffer *buffer;
    buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(txtinput[gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook))]));
    GtkTextIter current_iter;
    gtk_text_buffer_get_iter_at_mark(buffer,&current_iter,gtk_text_buffer_get_insert(buffer));
    int line=0,col=0,chars=0;
    chars = gtk_text_iter_get_offset(&current_iter);
    line = gtk_text_iter_get_line(&current_iter);
    col = gtk_text_iter_get_line_offset(&current_iter);
   
    gtk_statusbar_pop(GTK_STATUSBAR(statusbar),0);
    gchar *msg;
    msg = g_strdup_printf("Char %d Line %d Col %d", chars +1,line +1, col +1);
    gtk_statusbar_push(GTK_STATUSBAR(statusbar),0,msg);
    if (gtk_source_view_get_auto_indent(GTK_SOURCE_VIEW(txtinput[gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook))])) == TRUE)
    {
        gint indent_width;
        indent_width = 4;/*gtk_source_view_get_indent_width(GTK_SOURCE_VIEW(txtinput[gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook))]));*/
        GtkTextIter line_iter,next_line_iter;
        int next_line,offset_end_of_line;
        switch (event->keyval)
        {
            case GDK_Return:
                gtk_text_buffer_get_iter_at_line(buffer,&line_iter,line);
                char *line_text;
                line_text = gtk_text_buffer_get_text(buffer,&line_iter,&current_iter,TRUE);
                int spaces=0,count=0,i;
                for (i=0; i<strlen(line_text);i++)
                {
                    if(line_text[i] == ' ')
                    spaces++;
                    else
                    break;
                    }
                for (i=0;i<strlen(line_text);i++)
                {
                    if (line_text[i]==':')
                    count++;
                    }
                int count_open=0,count_close=0;
                for(i=0;i<strlen(line_text);i++)
                {
                    if(line_text[i]=='(')
                    count_open++;
                    if(line_text[i]==')')
                    count_close++;
                    }               
                gtk_text_buffer_insert(buffer,&current_iter,"\n",-1);
                if (count==1)
                {                     
                    int i,j;
                    for (j=0;j<spaces/indent_width + 1;j++)
                    {
                        for (i=0;i<indent_width;i++)
                        {
                            /*gtk_text_buffer_get_iter_at_mark(buffer,&current_iter,gtk_text_buffer_get_insert(buffer));*/                           
                            gtk_text_buffer_insert(buffer,&current_iter," ",-1);
                             }
                        }
                    }   
                else
                {
                    int i,j;
                    for (j=0;j<spaces/indent_width;j++)
                    {
                        for (i=0;i<indent_width;i++)
                        {
                            /*gtk_text_buffer_get_iter_at_mark(buffer,&current_iter,gtk_text_buffer_get_insert(buffer));*/
                            gtk_text_buffer_insert(buffer,&current_iter," ",-1);
                            }                                                     
                        }
                    }
                /*Problem with this code, this will produce two new lines for single Enter*/
                if(count_open>count_close)
                {
                    int k;
                    for(k=0;k<count_open-count_close;k++)
                    {
                        for (j=0;j<spaces/indent_width + 1;j++)
                        {
                            for (i=0;i<indent_width;i++)
                            gtk_text_buffer_insert(buffer,&current_iter," ",-1);
                            }
                        }
                    }
                /******************************************************/
               
                break;
           
            default:
                return FALSE;
            }
        }
    else
    return FALSE;
    }


Top
 Profile  
 
 Post subject: Re: problem with key-press-event
PostPosted: Thu Dec 22, 2011 9:43 am 
Offline
Never Seen the Sunlight

Joined: Mon Apr 28, 2008 5:52 am
Posts: 776
Location: UK
Hi,

Your code contains many errors, not just the one that you have observed. You have a very serious memory leak, which is leak a small amount of memory on every key press of at least 20 bytes if not more. It is possible that control will leave the function with out returning a value, so the retuned value will be undefined.

I was also unable to compile the code sample due to the number of errors and warnings, so it you attend to these problems first you may find that you have the solution to your first problem.

_________________
E.


Top
 Profile  
 
 Post subject: Re: problem with key-press-event
PostPosted: Thu Dec 22, 2011 2:11 pm 
Offline
GTK+ Geek

Joined: Sun Apr 03, 2011 11:12 am
Posts: 63
could you please tell me where are those memory leaks??


Top
 Profile  
 
 Post subject: Re: problem with key-press-event
PostPosted: Thu Dec 22, 2011 2:22 pm 
Offline
GTK+ Geek

Joined: Sun Apr 03, 2011 11:12 am
Posts: 63
one memory leak, I could identify is that of char *line_text. By using g_free(line_text), I was able to correct the code. Can please tell me other memory leaks. Also, besides pointers to char, which other pointers should be freed??


Top
 Profile  
 
 Post subject: Re: problem with key-press-event
PostPosted: Sat Dec 24, 2011 4:44 pm 
Offline
Never Seen the Sunlight

Joined: Mon Apr 28, 2008 5:52 am
Posts: 776
Location: UK
Hi you did find one of the memory leaks. I have re-worked your code to correct for the other memory leak and other problems, I have also done some changes which might improve performance for you.

- Used g_free on the string allocated by g_strdup_printf() when it is no longer needed. (the other memory leak)
- Replaced the use of GDK_Return (now deprecated) with GDK_KEY_Return.
- Reworked the code so that the return value is well defined and return TRUE for the handling of the return key. As we hand done handling all the work necessary.
- Reworked the code so that the line scanning is a bit quicker (scan once instead of three times)
- Reworked code to use a GString to build the return character and indenting string instead of doing multiple calls to gtk_text_buffer_insert(). Note each call to gtk_text_buffer_insert() will emit a "insert-text" signal

Code:
static const char indent_spaces[] = "                    ";

static gboolean txtinput_key_press_event(GtkWidget *widget, GdkEventKey *event)
{
    GtkTextBuffer *buffer;
    buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(txtinput[gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook))]));
    GtkTextIter current_iter;
    gtk_text_buffer_get_iter_at_mark(buffer,&current_iter,gtk_text_buffer_get_insert(buffer));
    int line, col, chars;
    chars = gtk_text_iter_get_offset(&current_iter);
    line = gtk_text_iter_get_line(&current_iter);
    col = gtk_text_iter_get_line_offset(&current_iter);

    gchar *msg;
    msg = g_strdup_printf("Char %d Line %d Col %d", chars +1, line +1, col +1);
    gtk_statusbar_pop(GTK_STATUSBAR(statusbar), 0);
    gtk_statusbar_push(GTK_STATUSBAR(statusbar), 0, msg);
    g_free(msg);

    if (gtk_source_view_get_auto_indent(GTK_SOURCE_VIEW(txtinput[gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook))])) == TRUE) {
        gint indent_width;
        indent_width = 4;/*gtk_source_view_get_indent_width(GTK_SOURCE_VIEW(txtinput[gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook))]));*/
        GtkTextIter line_iter,next_line_iter;
        int next_line,offset_end_of_line;

        switch (event->keyval) {
        case GDK_KEY_Return:
            gtk_text_buffer_get_iter_at_line(buffer,&line_iter,line);
            char *line_text;
            line_text = gtk_text_buffer_get_text(buffer,&line_iter,&current_iter,TRUE);
            int spaces=0, count=0, i;
            int count_open = 0, count_close = 0;
            size_t line_text_len = strlen(line_text);
            for (i=0; i < line_text_len; i++) {
                if(line_text[i] == ' ')
                    spaces++;
                else
                    break;
            }
            for ( ; i < line_text_len; i++) {
                if (line_text[i]==':')
                    count++;
                if(line_text[i]=='(')
                    count_open++;
                if(line_text[i]==')')
                    count_close++;
            }

            GString * ispaces = g_string_new("\n");

            if (count==1) {
                int j;
                for (j=0; j<spaces/indent_width + 1; j++) {
                    g_string_append_len(ispaces, indent_spaces, indent_width);
                }
            } else {
                int j;
                for (j=0; j<spaces/indent_width; j++) {
                    g_string_append_len(ispaces, indent_spaces, indent_width);
                }
            }
            /*Problem with this code, check for line wrap as this can add great length to the line*/
            if(count_open>count_close) {
                int k,j;
                for(k=0; k<count_open-count_close; k++) {
                    for (j=0; j<spaces/indent_width + 1; j++) {
                        g_string_append_len(ispaces, indent_spaces, indent_width);
                    }
                }
            }
            /******************************************************/

            gtk_text_buffer_insert(buffer, &current_iter, ispaces->str, ispaces->len);
            g_string_free(ispaces, TRUE);
            g_free(line_text);

            return TRUE;

        default:
            return FALSE;
        }
    }

    return FALSE;
}


Hope this helps and that by using GLib features it can make code easier to read.

_________________
E.


Top
 Profile  
 
 Post subject: Re: problem with key-press-event
PostPosted: Mon Dec 26, 2011 5:46 pm 
Offline
GTK+ Geek

Joined: Sun Apr 03, 2011 11:12 am
Posts: 63
thank you man!! :)


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC


Who is online

Users browsing this forum: Google [Bot], Yahoo [Bot] and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group