Updating branch refs/heads/master to 03cd4c266c5d539c85dbe22f505d1d54c1b011b4 (commit) from ec4cae752aa01e235b870df476b0c3008cb24f4d (commit)
commit 03cd4c266c5d539c85dbe22f505d1d54c1b011b4 Author: Nick Schermer <n...@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 <n...@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 <n...@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, ¤t_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, ¤t_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); } _______________________________________________ Xfce4-commits mailing list Xfce4-commits@xfce.org https://mail.xfce.org/mailman/listinfo/xfce4-commits