1 /*
2  * xed-commands-edit.c
3  * This file is part of xed
4  *
5  * Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence
6  * Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi
7  * Copyright (C) 2002-2005 Paolo Maggi
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor,
22  * Boston, MA 02110-1301, USA.
23  */
24 
25 /*
26  * Modified by the xed Team, 1998-2005. See the AUTHORS file for a
27  * list of people on the xed Team.
28  * See the ChangeLog files for a list of changes.
29  *
30  * $Id$
31  */
32 
33 #include <config.h>
34 #include <gtk/gtk.h>
35 
36 #include "xed-commands.h"
37 #include "xed-window.h"
38 #include "xed-debug.h"
39 #include "xed-view.h"
40 #include "xed-preferences-dialog.h"
41 
42 void
_xed_cmd_edit_undo(GtkAction * action,XedWindow * window)43 _xed_cmd_edit_undo (GtkAction   *action,
44 		     XedWindow *window)
45 {
46 	XedView *active_view;
47 	GtkSourceBuffer *active_document;
48 
49 	xed_debug (DEBUG_COMMANDS);
50 
51 	active_view = xed_window_get_active_view (window);
52 	g_return_if_fail (active_view);
53 
54 	active_document = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (active_view)));
55 
56 	gtk_source_buffer_undo (active_document);
57 
58 	xed_view_scroll_to_cursor (active_view);
59 
60 	gtk_widget_grab_focus (GTK_WIDGET (active_view));
61 }
62 
63 void
_xed_cmd_edit_redo(GtkAction * action,XedWindow * window)64 _xed_cmd_edit_redo (GtkAction   *action,
65 		     XedWindow *window)
66 {
67 	XedView *active_view;
68 	GtkSourceBuffer *active_document;
69 
70 	xed_debug (DEBUG_COMMANDS);
71 
72 	active_view = xed_window_get_active_view (window);
73 	g_return_if_fail (active_view);
74 
75 	active_document = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (active_view)));
76 
77 	gtk_source_buffer_redo (active_document);
78 
79 	xed_view_scroll_to_cursor (active_view);
80 
81 	gtk_widget_grab_focus (GTK_WIDGET (active_view));
82 }
83 
84 void
_xed_cmd_edit_cut(GtkAction * action,XedWindow * window)85 _xed_cmd_edit_cut (GtkAction   *action,
86 		    XedWindow *window)
87 {
88 	XedView *active_view;
89 
90 	xed_debug (DEBUG_COMMANDS);
91 
92 	active_view = xed_window_get_active_view (window);
93 	g_return_if_fail (active_view);
94 
95 	xed_view_cut_clipboard (active_view);
96 
97 	gtk_widget_grab_focus (GTK_WIDGET (active_view));
98 }
99 
100 void
_xed_cmd_edit_copy(GtkAction * action,XedWindow * window)101 _xed_cmd_edit_copy (GtkAction   *action,
102 		     XedWindow *window)
103 {
104 	XedView *active_view;
105 
106 	xed_debug (DEBUG_COMMANDS);
107 
108 	active_view = xed_window_get_active_view (window);
109 	g_return_if_fail (active_view);
110 
111 	xed_view_copy_clipboard (active_view);
112 
113 	gtk_widget_grab_focus (GTK_WIDGET (active_view));
114 }
115 
116 void
_xed_cmd_edit_paste(GtkAction * action,XedWindow * window)117 _xed_cmd_edit_paste (GtkAction   *action,
118 		      XedWindow *window)
119 {
120 	XedView *active_view;
121 
122 	xed_debug (DEBUG_COMMANDS);
123 
124 	active_view = xed_window_get_active_view (window);
125 	g_return_if_fail (active_view);
126 
127 	xed_view_paste_clipboard (active_view);
128 
129 	gtk_widget_grab_focus (GTK_WIDGET (active_view));
130 }
131 
132 void
_xed_cmd_edit_delete(GtkAction * action,XedWindow * window)133 _xed_cmd_edit_delete (GtkAction   *action,
134 		       XedWindow *window)
135 {
136 	XedView *active_view;
137 
138 	xed_debug (DEBUG_COMMANDS);
139 
140 	active_view = xed_window_get_active_view (window);
141 	g_return_if_fail (active_view);
142 
143 	xed_view_delete_selection (active_view);
144 
145 	gtk_widget_grab_focus (GTK_WIDGET (active_view));
146 }
147 
148 void
_xed_cmd_edit_select_all(GtkAction * action,XedWindow * window)149 _xed_cmd_edit_select_all (GtkAction   *action,
150 			   XedWindow *window)
151 {
152 	XedView *active_view;
153 
154 	xed_debug (DEBUG_COMMANDS);
155 
156 	active_view = xed_window_get_active_view (window);
157 	g_return_if_fail (active_view);
158 
159 	xed_view_select_all (active_view);
160 
161 	gtk_widget_grab_focus (GTK_WIDGET (active_view));
162 }
163 
164 void
_xed_cmd_edit_preferences(GtkAction * action,XedWindow * window)165 _xed_cmd_edit_preferences (GtkAction   *action,
166 			    XedWindow *window)
167 {
168 	xed_debug (DEBUG_COMMANDS);
169 
170 	xed_show_preferences_dialog (window);
171 }
172 
173 void
_xed_cmd_edit_toggle_comment(GtkAction * action,XedWindow * window)174 _xed_cmd_edit_toggle_comment (GtkAction *action,
175                               XedWindow *window)
176 {
177     XedView *active_view;
178     GtkSourceBuffer *active_document;
179     GtkSourceLanguage *language;
180     const gchar *comment_text;
181     gint start_line;
182     gint end_line;
183     gint i;
184     gboolean is_comment = FALSE;
185     GtkTextIter start_iter;
186     GtkTextIter end_iter;
187 
188     xed_debug (DEBUG_COMMANDS);
189 
190     active_view = xed_window_get_active_view (window);
191 
192     if (active_view == NULL)
193     {
194         return;
195     }
196 
197     active_document = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (active_view)));
198     language = gtk_source_buffer_get_language (active_document);
199 
200     if (language == NULL)
201     {
202         return;
203     }
204 
205     comment_text = gtk_source_language_get_metadata (language, "line-comment-start");
206 
207     if (comment_text == NULL)
208     {
209         return;
210     }
211 
212     gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (active_document), &start_iter, &end_iter);
213     start_line = gtk_text_iter_get_line (&start_iter);
214     end_line = gtk_text_iter_get_line (&end_iter);
215 
216     gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER (active_document)); // begin
217 
218     // if some lines are already commented, consider the whole block commented and uncomment them
219     for (i = start_line; i <= end_line; i++)
220     {
221         GtkTextIter start_line_iter;
222         GtkTextIter end_line_iter;
223         const gchar *line_text;
224 
225         gtk_text_buffer_get_iter_at_line (GTK_TEXT_BUFFER (active_document), &start_line_iter, i);
226         end_line_iter = start_line_iter;
227         gtk_text_iter_forward_to_line_end (&end_line_iter);
228 
229         line_text = gtk_text_buffer_get_slice (GTK_TEXT_BUFFER (active_document), &start_line_iter, &end_line_iter, TRUE);
230         if (g_str_has_prefix (line_text, comment_text))
231         {
232             is_comment = TRUE;
233             end_line_iter = start_line_iter;
234             gtk_text_iter_forward_chars (&end_line_iter, strlen(comment_text));
235             gtk_text_buffer_delete (GTK_TEXT_BUFFER (active_document), &start_line_iter, &end_line_iter);
236         }
237     }
238 
239     // only comment if nothing was commented to begin with
240     if (!is_comment)
241     {
242         for (i = start_line; i <= end_line; i++)
243         {
244             GtkTextIter insert_iter;
245 
246             gtk_text_buffer_get_iter_at_line (GTK_TEXT_BUFFER (active_document), &insert_iter, i);
247             gtk_text_buffer_insert (GTK_TEXT_BUFFER (active_document), &insert_iter, comment_text, -1);
248         }
249     }
250 
251     gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (active_document)); // end
252 }
253 
254 void
_xed_cmd_edit_toggle_comment_block(GtkAction * action,XedWindow * window)255 _xed_cmd_edit_toggle_comment_block (GtkAction *action,
256                                     XedWindow *window)
257 {
258     XedView *active_view;
259     GtkSourceBuffer *active_document;
260     GtkSourceLanguage *language;
261     const gchar *start_text;
262     const gchar *end_text;
263     GtkTextIter start_iter;
264     GtkTextIter end_iter;
265     gchar *selected_text;
266     gchar *insert_text;
267 
268     xed_debug (DEBUG_COMMANDS);
269 
270     active_view = xed_window_get_active_view (window);
271 
272     if (active_view == NULL)
273     {
274         return;
275     }
276 
277     active_document = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (active_view)));
278     language = gtk_source_buffer_get_language (active_document);
279 
280     if (language == NULL)
281     {
282         return;
283     }
284 
285     start_text = gtk_source_language_get_metadata (language, "block-comment-start");
286     end_text = gtk_source_language_get_metadata (language, "block-comment-end");
287 
288     if (start_text == NULL || end_text == NULL)
289     {
290         return;
291     }
292 
293     gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (active_document), &start_iter, &end_iter);
294 
295     selected_text = gtk_text_buffer_get_slice (GTK_TEXT_BUFFER (active_document), &start_iter, &end_iter, TRUE);
296 
297     if (g_str_has_prefix (selected_text, start_text) && g_str_has_suffix (selected_text, end_text))
298     {
299         gint start = strlen (start_text);
300         gint end = strlen (end_text);
301         const gchar *tmp = selected_text + start;
302         insert_text = g_strndup (tmp , strlen(selected_text) - start - end);
303     }
304     else
305     {
306         insert_text = g_strconcat (start_text, selected_text, end_text, NULL);
307     }
308 
309     gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER (active_document)); // begin
310 
311     // replace the selected text with the commented/uncommented version
312     gtk_text_buffer_delete (GTK_TEXT_BUFFER (active_document), &start_iter, &end_iter);
313     gtk_text_buffer_insert (GTK_TEXT_BUFFER (active_document), &end_iter, insert_text, -1);
314 
315     // move selection back where it was
316     gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (active_document), &start_iter,
317                                         gtk_text_iter_get_offset (&end_iter) - strlen (insert_text));
318     gtk_text_buffer_select_range (GTK_TEXT_BUFFER (active_document), &start_iter, &end_iter);
319 
320     gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (active_document)); // end
321 
322     g_free (selected_text);
323     g_free (insert_text);
324 }
325