[dia] Interface changes to pass modifiers to text_key_event()



commit df82abaefa74182b8233d208392bf36a867dc53f
Author: Hans Breuer <hans breuer org>
Date:   Sun May 31 11:00:09 2009 +0200

    Interface changes to pass modifiers to text_key_event()
    
    In preparation for bug #581301 - Deletion of whole words instead
    of characters - an extra parameter 'keystate' is passed though
    to text_key_evnet().
    Currently it is only used to make ctrl-arrow-(left|right) jump
    to the previous/next word.
---
 app/commands.c       |    4 +-
 app/disp_callbacks.c |   11 ++++----
 app/display.c        |    2 +-
 lib/focus.h          |    2 +-
 lib/text.c           |   64 ++++++++++++++++++++++++++++++++++++++++++++++---
 5 files changed, 70 insertions(+), 13 deletions(-)

diff --git a/app/commands.c b/app/commands.c
index 8686900..40b7dc1 100644
--- a/app/commands.c
+++ b/app/commands.c
@@ -181,10 +181,10 @@ insert_text(DDisplay *ddisp, Focus *focus, const gchar *text)
     gchar *next_line = g_utf8_strchr(text, -1, '\n');
     if (next_line != text) {
       gint len = g_utf8_strlen(text, (next_line-text));
-      modified = (*focus->key_event)(focus, GDK_A, text, len, &change);
+      modified = (*focus->key_event)(focus, 0, GDK_A, text, len, &change);
     }
     if (next_line != NULL) {
-      modified = (*focus->key_event)(focus, GDK_Return, "\n", 1, &change);
+      modified = (*focus->key_event)(focus, 0, GDK_Return, "\n", 1, &change);
       text = g_utf8_next_char(next_line);
     } else {
       text = NULL;
diff --git a/app/disp_callbacks.c b/app/disp_callbacks.c
index 71c8dc7..51e09cc 100644
--- a/app/disp_callbacks.c
+++ b/app/disp_callbacks.c
@@ -371,7 +371,8 @@ ddisplay_popup_menu(DDisplay *ddisp, GdkEventButton *event)
 		 event->button, event->time);
 }
 static void 
-handle_key_event(DDisplay *ddisp, Focus *focus, guint keysym,
+handle_key_event(DDisplay *ddisp, Focus *focus, 
+		 guint keystate, guint keysym,
                  const gchar *str, int strlen) 
 {
   DiaObject *obj = focus_get_object(focus);
@@ -381,7 +382,7 @@ handle_key_event(DDisplay *ddisp, Focus *focus, guint keysym,
 
   object_add_updates(obj, ddisp->diagram);
   
-  modified = (focus->key_event)(focus, keysym, str, strlen,
+  modified = (focus->key_event)(focus, keystate, keysym, str, strlen,
 				&obj_change);
 
       /* Make sure object updates its data and its connected: */
@@ -419,7 +420,7 @@ ddisplay_im_context_commit(GtkIMContext *context, const gchar  *str,
   ddisplay_im_context_preedit_reset(ddisp, focus);
   
   if (focus != NULL)
-    handle_key_event(ddisp, focus, 0, str, g_utf8_strlen(str,-1));
+    handle_key_event(ddisp, focus, 0, 0, str, g_utf8_strlen(str,-1));
 }
 
 void 
@@ -435,7 +436,7 @@ ddisplay_im_context_preedit_changed(GtkIMContext *context,
                                     &ddisp->preedit_attrs, &cursor_pos);
   if (ddisp->preedit_string != NULL) {
     if (focus != NULL) {
-      handle_key_event(ddisp, focus, 0, ddisp->preedit_string,
+      handle_key_event(ddisp, focus, 0, 0, ddisp->preedit_string,
                        g_utf8_strlen(ddisp->preedit_string,-1));
     } else {
       ddisplay_im_context_preedit_reset(ddisp, focus);
@@ -804,7 +805,7 @@ ddisplay_canvas_events (GtkWidget *canvas,
 		    break;
 		  default:
 		    /*! key event not swallowed by the input method ? */
-		    handle_key_event(ddisp, focus, kevent->keyval,
+		    handle_key_event(ddisp, focus, kevent->state, kevent->keyval,
 				     kevent->string, kevent->length);
 		    
 		    diagram_flush(ddisp->diagram);
diff --git a/app/display.c b/app/display.c
index bafd3a9..6aca06a 100644
--- a/app/display.c
+++ b/app/display.c
@@ -1542,7 +1542,7 @@ ddisplay_im_context_preedit_reset(DDisplay *ddisp, Focus *focus)
       ObjectChange *change;
       
       for (i = 0; i < g_utf8_strlen(ddisp->preedit_string, -1); i++) {
-        (focus->key_event)(focus, GDK_BackSpace, NULL, 0, &change);
+        (focus->key_event)(focus, 0, GDK_BackSpace, NULL, 0, &change);
       }
     }
     
diff --git a/lib/focus.h b/lib/focus.h
index 505aff8..59fb140 100644
--- a/lib/focus.h
+++ b/lib/focus.h
@@ -28,7 +28,7 @@ struct _Focus {
 
   /* return TRUE if modified object.
      Set change if object is changed. */
-  int (*key_event)(Focus *focus, guint keysym, const gchar *str, int strlen,
+  int (*key_event)(Focus *focus, guint keystate, guint keysym, const gchar *str, int strlen,
                    ObjectChange **change);
 };
 
diff --git a/lib/text.c b/lib/text.c
index 90266c0..2fa0896 100644
--- a/lib/text.c
+++ b/lib/text.c
@@ -33,7 +33,8 @@
 #include "objchange.h"
 #include "textline.h"
 
-static int text_key_event(Focus *focus, guint keysym,
+static int text_key_event(Focus *focus, 
+			  guint keystate, guint keysym,
 			  const gchar *str, int strlen,
 			  ObjectChange **change);
 
@@ -573,6 +574,53 @@ text_set_cursor_at_end( Text* text )
   text->cursor_pos = text_get_line_strlen(text, text->cursor_row) ;
 }
 
+typedef enum {
+  WORD_START = 1,
+  WORD_END
+} CursorMovement;
+
+static void
+text_move_cursor(Text *text, CursorMovement mv)
+{
+  gchar *str = text_line_get_string(text->lines[text->cursor_row]);
+  gchar *p = str;
+  int curmax = text_get_line_strlen(text, text->cursor_row);
+  if (text->cursor_pos > 0 && text->cursor_pos <= curmax) {
+    int i;
+    for (i = 0; i < text->cursor_pos; ++i)
+      p = g_utf8_next_char (p);
+  } 
+  if (WORD_START == mv && text->cursor_pos < 1) {
+    if (text->cursor_row) {
+      text->cursor_row--;
+      text->cursor_pos = text_get_line_strlen(text, text->cursor_row);
+    }
+    return;
+  } else if (WORD_END == mv && text->cursor_pos == curmax) {
+    if (text->cursor_row < text->numlines - 1) {
+      text->cursor_row++;
+      text->cursor_pos = 0;
+    }
+    return;
+  }
+  while (!g_unichar_isalnum (g_utf8_get_char (p))) {
+    p = (WORD_START == mv ? g_utf8_find_prev_char (str, p) : g_utf8_next_char (p));
+    if (p) text->cursor_pos += (WORD_START == mv ? -1 : 1);
+    if (!p || !*p)
+      return;
+    if (!text->cursor_pos || text->cursor_pos == curmax)
+      return;
+  }
+  while (g_unichar_isalnum (g_utf8_get_char (p))) {
+    p = (WORD_START == mv ? g_utf8_find_prev_char (str, p) : g_utf8_next_char (p));
+    if (p) text->cursor_pos += (WORD_START == mv ? -1 : 1);
+    if (!p || !*p)
+      return;
+    if (!text->cursor_pos || text->cursor_pos == curmax)
+      return;
+  }
+}
+
 /* The renderer is only used to determine where the click is, so is not
  * required when no point is given. */
 void
@@ -826,7 +874,9 @@ text_delete_key_handler(Focus *focus, ObjectChange ** change)
 }
 
 static int
-text_key_event(Focus *focus, guint keyval, const gchar *str, int strlen,
+text_key_event(Focus *focus, 
+	       guint keystate, guint keyval, 
+	       const gchar *str, int strlen,
                ObjectChange **change)
 {
   Text *text;
@@ -859,12 +909,18 @@ text_key_event(Focus *focus, guint keyval, const gchar *str, int strlen,
     
         break;
       case GDK_Left:
-        text->cursor_pos--;
+        if (keystate & GDK_CONTROL_MASK)
+	  text_move_cursor(text, WORD_START);
+	else
+          text->cursor_pos--;
         if (text->cursor_pos<0)
           text->cursor_pos = 0;
         break;
       case GDK_Right:
-        text->cursor_pos++;
+        if (keystate & GDK_CONTROL_MASK)
+	  text_move_cursor(text, WORD_END);
+	else
+          text->cursor_pos++;
         if (text->cursor_pos > text_get_line_strlen(text, text->cursor_row))
           text->cursor_pos = text_get_line_strlen(text, text->cursor_row);
         break;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]