gtk+ text editor vim type modes (insert / command)

440 views Asked by At

I'm trying to incorporate vim like functionality in a text editor I am creating in gtk+ 2.0 and gtksourceview 2.0. I have it working except when I press "i" to enter insert mode it enters this mode properly, but then it types an "i" in the text buffer. Here is my keypress function which is setup to enter command mode (leave insert mode) when the esc key is hit, and as I said before enter insert mode when the i key is pressed:

gboolean on_key_press_win_main (GtkWidget *widget, GdkEventKey *event, gpointer user_data)
{

  switch (event->keyval)
  {

    case GDK_i:
      if (event->state & GDK_CONTROL_MASK)
      {
        printf("key pressed: %s\n", "ctrl + i");
      }
      else
      {
        GtkTextBuffer *tbuffer;
                GtkTextView *text_view;
                int page = 0;
        gchar *msg;
        gint row, col;
        GtkTextIter iter;

              page = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
                text_view = GTK_TEXT_VIEW(txtinput[notebookPages[page]]);
                tbuffer = gtk_text_view_get_buffer (text_view);

        if (insert_mode == 0)
        {
            insert_mode = 1;
            command_mode = 0;

            /* update statusbar */
            gtk_statusbar_pop(GTK_STATUSBAR(statusbar), 0); 

            gtk_text_buffer_get_iter_at_mark(tbuffer, &iter, gtk_text_buffer_get_insert(tbuffer));

            row = gtk_text_iter_get_line(&iter);
            col = gtk_text_iter_get_line_offset(&iter);

            msg = g_strdup_printf("INSERT\t\t Col %d Ln %d", col+1, row+1);
            gtk_statusbar_push(GTK_STATUSBAR(statusbar), 0, msg);

            gtk_text_view_set_editable (text_view, TRUE);

        }

      }

      break;

        /* esc key */
        case 65307:
    {
        GtkTextBuffer *tbuffer;
          GtkTextView *text_view;
          int page = 0;
      gchar *msg;
      gint row, col;
      GtkTextIter iter;

        page = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
          text_view = GTK_TEXT_VIEW(txtinput[notebookPages[page]]);
          tbuffer = gtk_text_view_get_buffer (text_view);

      insert_mode = 0;
      command_mode = 1;
      gtk_text_view_set_editable (text_view, FALSE);

      /* update statusbar */
      gtk_statusbar_pop(GTK_STATUSBAR(statusbar), 0); 

      gtk_text_buffer_get_iter_at_mark(tbuffer, &iter, gtk_text_buffer_get_insert(tbuffer));

      row = gtk_text_iter_get_line(&iter);
      col = gtk_text_iter_get_line_offset(&iter);

      msg = g_strdup_printf("Col %d Ln %d", col+1, row+1);
      gtk_statusbar_push(GTK_STATUSBAR(statusbar), 0, msg);

    }

    break;

    default:
      return FALSE; 
  }

  return FALSE; 
}

As you can see gtk_text_view_set_editable (text_view, FALSE) is set when entering command mode, and gtk_text_view_set_editable (text_view, TRUE) is set when entering insert mode. However, when entering insert mode the text_view is set editable before the keystroke registers in the buffer even if it is the last command in the keypress case. How can I keep the i from being placed in the text buffer when entering insert mode?

2

There are 2 answers

0
ptomato On BEST ANSWER

Return TRUE from the event handler instead of FALSE to block any further processing of the event. Event handlers work like a filter, you filter out the keystrokes that you don't want to pass on to the textview.

PS. Don't use constants like 65307, use GDK_KEY_Escape or whatever it is.

0
nomadicME On

Wouldn't you know it, as soon as I finished writing this question a viable option pops into my head. This is probably why the key_release_event was created. Worked like a charm.