[Xfce4-commits] <mousepad:master> * mousepad/mousepad-view.c: Implement transpose: - Selection on one line: Inverse selected text. - Multiple lines selected: Invert seleted lines. - Cursor is inside a word: Swap chars on each side of the cursor. - Cursor is outside a word: Swap word left and right of the cursor. - Cursor at the start of a line: Swap line with the line above. - Cursor at the end of a line: Swap line with the line below. Will add support for multi- and column-selections later. Thanks to Textmate for this great idea.

Nick Schermer noreply at xfce.org
Sat May 5 21:30:57 CEST 2012


Updating branch refs/heads/master
         to 03cd4c266c5d539c85dbe22f505d1d54c1b011b4 (commit)
       from ec4cae752aa01e235b870df476b0c3008cb24f4d (commit)

commit 03cd4c266c5d539c85dbe22f505d1d54c1b011b4
Author: Nick Schermer <nick at xfce.org>
Date:   Fri Oct 26 15:02:40 2007 +0000

    	* mousepad/mousepad-view.c: Implement transpose:
    	   - Selection on one line: Inverse selected text.
    	   - Multiple lines selected: Invert seleted lines.
    	   - Cursor is inside a word: Swap chars on each side of the cursor.
    	   - Cursor is outside a word: Swap word left and right of the cursor.
    	   - Cursor at the start of a line: Swap line with the line above.
    	   - Cursor at the end of a line: Swap line with the line below.
    	Will add support for multi- and column-selections later. Thanks to
    	Textmate for this great idea.
    
    (Old svn revision: 26200)

 ChangeLog                       |   12 ++
 mousepad/mousepad-view.c        |  250 ++++++++++++++++++++++++++++++++++++++-
 mousepad/mousepad-view.h        |    2 +
 mousepad/mousepad-window-ui.xml |    2 +
 mousepad/mousepad-window.c      |   38 ++++--
 5 files changed, 288 insertions(+), 16 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index e64012a..2d87175 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,16 @@
 2007-10-26	Nick Schermer <nick at xfce.org>
+	* mousepad/mousepad-view.c: Implement transpose:
+	   - Selection on one line: Inverse selected text.
+	   - Multiple lines selected: Invert seleted lines.
+	   - Cursor is inside a word: Swap chars on each side of the cursor.
+	   - Cursor is outside a word: Swap word left and right of the cursor.
+	   - Cursor at the start of a line: Swap line with the line above.
+	   - Cursor at the end of a line: Swap line with the line below.
+	Will add support for multi- and column-selections later. Thanks to
+	Textmate for this great idea.
+
+
+2007-10-26	Nick Schermer <nick at xfce.org>
 	* MousepadHelp.in, mousepad/mousepad-{dialogs,window}.{c,h}:
 	  Add support for the help file.
 	* Mousepad.spec.in: Add spec file.
diff --git a/mousepad/mousepad-view.c b/mousepad/mousepad-view.c
index dec3071..2fed762 100644
--- a/mousepad/mousepad-view.c
+++ b/mousepad/mousepad-view.c
@@ -77,6 +77,15 @@ static gchar    *mousepad_view_indent_string                 (GtkTextBuffer
 static gint      mousepad_view_calculate_layout_width        (GtkWidget          *widget,
                                                               gsize               length,
                                                               gchar               fill_char);
+static void      mousepad_view_transpose_range               (GtkTextBuffer       *buffer,
+                                                              GtkTextIter         *start_iter,
+                                                              GtkTextIter         *end_iter);
+static void      mousepad_view_transpose_lines               (GtkTextBuffer       *buffer,
+                                                              GtkTextIter         *start_iter,
+                                                              GtkTextIter         *end_iter);
+static void      mousepad_view_transpose_words               (GtkTextBuffer       *buffer,
+                                                              GtkTextIter         *iter);
+
 
 
 enum _MousepadViewFlags
@@ -1232,8 +1241,8 @@ mousepad_view_selection_clipboard (MousepadView *view,
 
   _mousepad_return_if_fail (view->marks == NULL || g_slist_length (view->marks) % 2 == 0);
 
-  /* create string with some size so we don't have to realloc a zillon times */
-  string = g_string_sized_new (1024);
+  /* create new string */
+  string = g_string_new (NULL);
 
   /* get the buffer */
   buffer = mousepad_view_get_buffer (view);
@@ -1495,6 +1504,243 @@ mousepad_view_put_cursor_on_screen (MousepadView *view)
 
 
 
+static void
+mousepad_view_transpose_range (GtkTextBuffer *buffer,
+                               GtkTextIter   *start_iter,
+                               GtkTextIter   *end_iter)
+{
+  gchar *string, *reversed;
+  gint   offset;
+
+  /* store start iter line offset */
+  offset = gtk_text_iter_get_offset (start_iter);
+
+  /* get selected text */
+  string = gtk_text_buffer_get_slice (buffer, start_iter, end_iter, FALSE);
+
+  /* reverse the string */
+  reversed = g_utf8_strreverse (string, -1);
+
+  /* cleanup */
+  g_free (string);
+
+  /* delete the text between the iters */
+  gtk_text_buffer_delete (buffer, start_iter, end_iter);
+
+  /* insert the reversed string */
+  gtk_text_buffer_insert (buffer, end_iter, reversed, -1);
+
+  /* cleanup */
+  g_free (reversed);
+
+  /* restore start iter */
+  gtk_text_buffer_get_iter_at_offset (buffer, start_iter, offset);
+}
+
+
+
+static void
+mousepad_view_transpose_lines (GtkTextBuffer *buffer,
+                               GtkTextIter   *start_iter,
+                               GtkTextIter   *end_iter)
+{
+  GString *string;
+  gint     start_line, end_line;
+  gint     i;
+  gchar   *slice;
+
+  /* make sure the order is ok */
+  gtk_text_iter_order (start_iter, end_iter);
+
+  /* get the line numbers */
+  start_line = gtk_text_iter_get_line (start_iter);
+  end_line = gtk_text_iter_get_line (end_iter);
+
+  /* new string */
+  string = g_string_new (NULL);
+
+  /* add the lines in reversed order to the string */
+  for (i = start_line; i <= end_line; i++)
+    {
+      /* get start iter */
+      gtk_text_buffer_get_iter_at_line (buffer, start_iter, i);
+
+      /* set end iter */
+      *end_iter = *start_iter;
+
+      /* only prepend when the iters won't be equal */
+      if (!gtk_text_iter_ends_line (end_iter))
+        {
+          /* move the iter to the end of this line */
+          gtk_text_iter_forward_to_line_end (end_iter);
+
+          /* prepend line */
+          slice = gtk_text_buffer_get_slice (buffer, start_iter, end_iter, FALSE);
+          string = g_string_prepend (string, slice);
+          g_free (slice);
+        }
+
+      /* prepend new line */
+      if (i < end_line)
+        string = g_string_prepend_c (string, '\n');
+    }
+
+  /* get start iter again */
+  gtk_text_buffer_get_iter_at_line (buffer, start_iter, start_line);
+
+  /* delete selection */
+  gtk_text_buffer_delete (buffer, start_iter, end_iter);
+
+  /* insert reversed lines */
+  gtk_text_buffer_insert (buffer, end_iter, string->str, string->len);
+
+  /* cleanup */
+  g_string_free (string, TRUE);
+
+  /* restore start iter */
+  gtk_text_buffer_get_iter_at_line (buffer, start_iter, start_line);
+}
+
+
+
+static void
+mousepad_view_transpose_words (GtkTextBuffer *buffer,
+                               GtkTextIter   *iter)
+{
+  GtkTextIter  start_one, end_one, end_two;
+  gchar       *word_left, *word_right, *word_space;
+
+  /* move the iter to the start of first word */
+  gtk_text_iter_backward_word_start (iter);
+  start_one = *iter;
+  if (!gtk_text_iter_starts_word (iter))
+    return;
+
+  /* move to end of first word */
+  gtk_text_iter_forward_word_end (iter);
+  end_one = *iter;
+  if (!gtk_text_iter_ends_word (iter))
+    return;
+
+  /* move to end of second word */
+  gtk_text_iter_forward_word_end (iter);
+  end_two = *iter;
+  if (!gtk_text_iter_ends_word (iter))
+    return;
+
+  /* move to start of second word */
+  gtk_text_iter_backward_word_start (iter);
+  if (!gtk_text_iter_starts_word (iter))
+    return;
+
+  /* only do this on the same line */
+  if (gtk_text_iter_get_line (&start_one) != gtk_text_iter_get_line (&end_two))
+    return;
+
+  /* get the three parts */
+  word_left = gtk_text_buffer_get_slice (buffer, &start_one, &end_one, FALSE);
+  word_space = gtk_text_buffer_get_slice (buffer, &end_one, iter, FALSE);
+  word_right = gtk_text_buffer_get_slice (buffer, iter, &end_two, FALSE);
+
+  /* build string */
+  gtk_text_buffer_delete (buffer, &start_one, &end_two);
+  *iter = end_two;
+
+  /* insert right word */
+  gtk_text_buffer_insert (buffer, iter, word_right, -1);
+  g_free (word_right);
+
+  /* insert space */
+  gtk_text_buffer_insert (buffer, iter, word_space, -1);
+  g_free (word_space);
+
+  /* insert left word */
+  gtk_text_buffer_insert (buffer, iter, word_left, -1);
+  g_free (word_left);
+
+  /* return valid iter */
+  gtk_text_iter_backward_word_start (iter);
+
+  /* place cursor */
+  gtk_text_buffer_place_cursor (buffer, iter);
+}
+
+
+
+void
+mousepad_view_transpose (MousepadView *view)
+{
+  GtkTextBuffer *buffer;
+  GtkTextIter    sel_start, sel_end;
+
+  _mousepad_return_if_fail (MOUSEPAD_IS_VIEW (view));
+
+  /* get buffer */
+  buffer = mousepad_view_get_buffer (view);
+
+  /* begin user action */
+  gtk_text_buffer_begin_user_action (buffer);
+
+  if (view->flags != 0)
+    {
+
+    }
+  else if (gtk_text_buffer_get_selection_bounds (buffer, &sel_start, &sel_end))
+    {
+      /* if the selection is not on the same line, include the whole lines */
+      if (gtk_text_iter_get_line (&sel_start) == gtk_text_iter_get_line (&sel_end))
+        {
+          /* reverse selection */
+          mousepad_view_transpose_range (buffer, &sel_start, &sel_end);
+        }
+      else
+        {
+          /* reverse lines */
+          mousepad_view_transpose_lines (buffer, &sel_start, &sel_end);
+        }
+
+      /* restore selection */
+      gtk_text_buffer_select_range (buffer, &sel_start, &sel_end);
+    }
+  else
+    {
+      /* get cursor iter */
+      gtk_text_buffer_get_iter_at_mark (buffer, &sel_start, gtk_text_buffer_get_insert (buffer));
+
+      /* set end iter */
+      sel_end = sel_start;
+
+      if (gtk_text_iter_starts_line (&sel_start))
+        {
+          /* swap this line with the line above */
+          if (gtk_text_iter_backward_line (&sel_end))
+            mousepad_view_transpose_lines (buffer, &sel_start, &sel_end);
+        }
+      else if (gtk_text_iter_ends_line (&sel_start))
+        {
+          /* swap this line with the line below */
+          if (gtk_text_iter_forward_line (&sel_end))
+            mousepad_view_transpose_lines (buffer, &sel_start, &sel_end);
+        }
+      else if (gtk_text_iter_inside_word (&sel_start) && !gtk_text_iter_starts_word (&sel_start))
+        {
+          /* reverse the characters before and after the cursor */
+          if (gtk_text_iter_backward_char (&sel_start) && gtk_text_iter_forward_char (&sel_end))
+            mousepad_view_transpose_range (buffer, &sel_start, &sel_end);
+        }
+      else
+        {
+          /* swap the words left and right of the cursor */
+          mousepad_view_transpose_words (buffer, &sel_start);
+        }
+    }
+
+  /* end user action */
+  gtk_text_buffer_end_user_action (buffer);
+}
+
+
+
 void
 mousepad_view_clipboard_cut (MousepadView *view)
 {
diff --git a/mousepad/mousepad-view.h b/mousepad/mousepad-view.h
index f29a671..8a1933f 100644
--- a/mousepad/mousepad-view.h
+++ b/mousepad/mousepad-view.h
@@ -35,6 +35,8 @@ GType           mousepad_view_get_type                  (void) G_GNUC_CONST;
 
 void            mousepad_view_put_cursor_on_screen      (MousepadView      *view);
 
+void            mousepad_view_transpose                 (MousepadView      *view);
+
 void            mousepad_view_clipboard_cut             (MousepadView      *view);
 
 void            mousepad_view_clipboard_copy            (MousepadView      *view);
diff --git a/mousepad/mousepad-window-ui.xml b/mousepad/mousepad-window-ui.xml
index efbf935..6c5baaa 100644
--- a/mousepad/mousepad-window-ui.xml
+++ b/mousepad/mousepad-window-ui.xml
@@ -56,6 +56,8 @@
       <menuitem action="delete" />
       <separator />
       <menuitem action="select-all" />
+      <separator />
+      <menuitem action="transpose" />
     </menu>
 
     <menu action="search-menu">
diff --git a/mousepad/mousepad-window.c b/mousepad/mousepad-window.c
index f46cc83..e68914c 100644
--- a/mousepad/mousepad-window.c
+++ b/mousepad/mousepad-window.c
@@ -232,6 +232,8 @@ static void              mousepad_window_action_delete                (GtkAction
                                                                        MousepadWindow         *window);
 static void              mousepad_window_action_select_all            (GtkAction              *action,
                                                                        MousepadWindow         *window);
+static void              mousepad_window_action_transpose             (GtkAction              *action,
+                                                                       MousepadWindow         *window);
 static void              mousepad_window_action_find                  (GtkAction              *action,
                                                                        MousepadWindow         *window);
 static void              mousepad_window_action_find_next             (GtkAction              *action,
@@ -350,6 +352,7 @@ static const GtkActionEntry action_entries[] =
     { "paste-column", GTK_STOCK_PASTE, N_("Paste _Column"), "<control><shift>V", N_("Paste the clipboard text in a clumn"), G_CALLBACK (mousepad_window_action_paste_column), },
     { "delete", GTK_STOCK_DELETE, NULL, NULL, N_("Delete the selected text"), G_CALLBACK (mousepad_window_action_delete), },
     { "select-all", GTK_STOCK_SELECT_ALL, NULL, NULL, N_("Select the entire document"), G_CALLBACK (mousepad_window_action_select_all), },
+    { "transpose", NULL, N_("_Transpose"), NULL, N_("Reverse the order of something"), G_CALLBACK (mousepad_window_action_transpose), },
 
   { "search-menu", NULL, N_("_Search"), NULL, NULL, NULL, },
     { "find", GTK_STOCK_FIND, NULL, NULL, N_("Search for text"), G_CALLBACK (mousepad_window_action_find), },
@@ -2914,11 +2917,20 @@ static void
 mousepad_window_action_select_all (GtkAction      *action,
                                    MousepadWindow *window)
 {
-  MousepadDocument *document = window->active;
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
 
-  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+  mousepad_view_select_all (window->active->textview);
+}
+
+
+
+static void
+mousepad_window_action_transpose (GtkAction      *action,
+                                  MousepadWindow *window)
+{
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
 
-  mousepad_view_select_all (document->textview);
+  mousepad_view_transpose (window->active->textview);
 }
 
 
@@ -3298,20 +3310,18 @@ static void
 mousepad_window_action_go_to_line (GtkAction      *action,
                                    MousepadWindow *window)
 {
-  MousepadDocument *document = window->active;
-  gint              current_line, last_line, line;
+  gint current_line, last_line, line;
 
-  if (G_LIKELY (document))
-    {
-      /* get the current and last line number */
-      mousepad_document_line_numbers (document, &current_line, &last_line);
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
 
-      /* run the jump to dialog and wait for the response */
-      line = mousepad_dialogs_go_to_line (GTK_WINDOW (window), current_line, last_line);
+  /* get the current and last line number */
+  mousepad_document_line_numbers (window->active, &current_line, &last_line);
 
-      if (G_LIKELY (line > 0))
-        mousepad_document_go_to_line (document, line);
-    }
+  /* run the jump to dialog and wait for the response */
+  line = mousepad_dialogs_go_to_line (GTK_WINDOW (window), current_line, last_line);
+
+  if (G_LIKELY (line > 0))
+    mousepad_document_go_to_line (window->active, line);
 }
 
 


More information about the Xfce4-commits mailing list