1
/* shiftcolumn.c - a Geany plugin
3
* Copyright 2009 Andrew L Janke <a.janke@gmail.com>
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
31
#include "sciwrappers.h"
33
#include "keybindings.h"
34
#include "plugindata.h"
35
#include "geanyfunctions.h"
38
#include <glib/gprintf.h>
39
#include <gdk/gdkkeysyms.h>
41
GeanyPlugin *geany_plugin;
42
GeanyData *geany_data;
43
GeanyFunctions *geany_functions;
45
PLUGIN_VERSION_CHECK(130);
46
PLUGIN_SET_INFO(_("Shift Column"),
47
_("Shift a selection left and right"),
48
VERSION, "Andrew L Janke <a.janke@gmail.com>");
51
static GtkWidget *menu_item_shift_left = NULL;
52
static GtkWidget *menu_item_shift_right = NULL;
60
PLUGIN_KEY_GROUP(shiftcolumn, KB_COUNT)
63
static void shift_left_cb(G_GNUC_UNUSED GtkMenuItem *menuitem,
64
G_GNUC_UNUSED gpointer gdata){
89
/* get a pointer to the scintilla object */
90
sci = document_get_current()->editor->sci;
92
if (sci_has_selection(sci)){
94
startpos = sci_get_selection_start(sci);
95
endpos = sci_get_selection_end(sci);
97
/* sanity check -- we dont care which way the block was selected */
98
if(startpos > endpos){
104
startline = sci_get_line_from_position(sci, startpos);
105
endline = sci_get_line_from_position(sci, endpos);
108
// if(sci_get_selection_mode(sci) == 1){
109
if(startline == endline){
111
/* get the text in question */
112
txt_len = endpos - startpos;
113
txt_i = g_malloc(txt_len + 1);
114
txt = g_malloc(txt_len + 2);
115
sci_get_selected_text(sci, txt_i);
117
char_before = sci_get_char_at(sci, startpos - 1);
119
/* set up new text buf */
120
(void) g_sprintf(txt, "%s%c", txt_i, char_before);
123
sci_start_undo_action(sci);
125
/* put the new text in */
126
sci_set_selection_start(sci, startpos - 1);
127
sci_replace_sel(sci, txt);
129
/* select the right bit again */
130
sci_set_selection_start(sci, startpos - 1);
131
sci_set_selection_end(sci, endpos - 1);
134
sci_end_undo_action(sci);
140
/* rectangle mode (we hope!) */
142
startcol = sci_get_col_from_position(sci, startpos);
143
endcol = sci_get_col_from_position(sci, endpos);
145
/* return early for the trivial case */
146
if(startcol == 0 || startcol == endcol){
151
sci_start_undo_action(sci);
153
for(line_iter = startline; line_iter <= endline; line_iter++){
154
linepos = sci_get_position_from_line(sci, line_iter);
155
linelen = sci_get_line_length(sci, line_iter);
157
/* do we need to do something */
158
if(linelen >= startcol - 1 ){
160
/* if between the two columns */
161
/* pad to the end first */
162
if(linelen <= endcol){
164
/* bung in some spaces -- sorry, I dont like tabs */
165
n_spaces = endcol - linelen + 1;
166
spaces = g_malloc(sizeof(gchar) * (n_spaces + 1));
167
for(i = 0; i < n_spaces; i++){
172
sci_insert_text(sci, linepos + linelen - 1, spaces);
176
/* now move the text itself */
177
sci_set_selection_mode(sci, 0);
178
sci_set_selection_start(sci, linepos + startcol);
179
sci_set_selection_end(sci, linepos + endcol);
181
txt_len = sci_get_selected_text_length(sci);
182
txt_i = g_malloc(txt_len + 1);
183
txt = g_malloc(txt_len + 2);
185
sci_get_selected_text(sci, txt_i);
186
char_before = sci_get_char_at(sci, linepos + startcol - 1);
188
/* set up new text buf */
189
(void) g_sprintf(txt, "%s%c", txt_i, char_before);
191
/* put the new text in */
192
sci_set_selection_start(sci, linepos + startcol - 1);
193
sci_replace_sel(sci, txt);
200
/* put the selection box back */
201
/* here we rely upon the last result of linepos */
202
sci_set_selection_mode(sci, 1);
203
sci_set_selection_start(sci, startpos - 1);
204
sci_set_selection_end(sci, linepos + endcol - 1);
206
/* end undo action */
207
sci_end_undo_action(sci);
213
static void shift_right_cb(G_GNUC_UNUSED GtkMenuItem *menuitem,
214
G_GNUC_UNUSED gpointer gdata){
234
ScintillaObject *sci;
236
/* get a pointer to the scintilla object */
237
sci = document_get_current()->editor->sci;
239
if (sci_has_selection(sci)){
241
startpos = sci_get_selection_start(sci);
242
endpos = sci_get_selection_end(sci);
244
/* sanity check -- we dont care which way the block was selected */
245
if(startpos > endpos){
251
startline = sci_get_line_from_position(sci, startpos);
252
endline = sci_get_line_from_position(sci, endpos);
255
if(startline == endline){
257
/* get the text in question */
258
txt_len = endpos - startpos;
259
txt_i = g_malloc(txt_len + 1);
260
txt = g_malloc(txt_len + 2);
261
sci_get_selected_text(sci, txt_i);
263
char_after = sci_get_char_at(sci, endpos);
265
/* set up new text buf */
266
(void) g_sprintf(txt, "%c%s", char_after, txt_i);
269
sci_start_undo_action(sci);
271
/* put the new text in */
272
sci_set_selection_end(sci, endpos + 1);
273
sci_replace_sel(sci, txt);
275
/* select the right bit again */
276
sci_set_selection_start(sci, startpos + 1);
277
sci_set_selection_end(sci, endpos + 1);
280
sci_end_undo_action(sci);
286
/* rectangle mode (we hope!) */
288
startcol = sci_get_col_from_position(sci, startpos);
289
endcol = sci_get_col_from_position(sci, endpos);
292
sci_start_undo_action(sci);
294
for(line_iter = startline; line_iter <= endline; line_iter++){
295
linepos = sci_get_position_from_line(sci, line_iter);
296
linelen = sci_get_line_length(sci, line_iter);
298
/* do we need to do something */
299
if(linelen >= startcol - 1 ){
301
/* if between the two columns or at the end */
303
if(linelen <= endcol || linelen - 1 == endcol){
304
txt = g_malloc(sizeof(gchar) * 2);
307
sci_insert_text(sci, linepos + startcol, txt);
312
/* move the text itself */
313
sci_set_selection_mode(sci, 0);
314
sci_set_selection_start(sci, linepos + startcol);
315
sci_set_selection_end(sci, linepos + endcol);
317
txt_len = sci_get_selected_text_length(sci);
318
txt_i = g_malloc(txt_len + 1);
319
txt = g_malloc(txt_len + 2);
321
sci_get_selected_text(sci, txt_i);
322
char_after = sci_get_char_at(sci, linepos + endcol);
324
/* set up new text buf */
325
(void) g_sprintf(txt, "%c%s", char_after, txt_i);
327
/* put the new text in */
328
sci_set_selection_end(sci, linepos + endcol + 1);
329
sci_replace_sel(sci, txt);
337
/* put the selection box back */
338
/* here we rely upon the last result of linepos */
339
sci_set_selection_mode(sci, 1);
340
sci_set_selection_start(sci, startpos + 1);
341
sci_set_selection_end(sci, linepos + endcol + 1);
343
/* end undo action */
344
sci_end_undo_action(sci);
350
static void kb_shift_left(G_GNUC_UNUSED guint key_id){
353
if (document_get_current() == NULL){
357
shift_left_cb(NULL, NULL);
360
static void kb_shift_right(G_GNUC_UNUSED guint key_id){
363
if (document_get_current() == NULL){
367
shift_right_cb(NULL, NULL);
370
void plugin_init(G_GNUC_UNUSED GeanyData *data){
372
/* init gettext and friends */
373
main_locale_init(LOCALEDIR, GETTEXT_PACKAGE);
375
menu_item_shift_left = gtk_menu_item_new_with_mnemonic(_("Shift Left"));
376
gtk_widget_show(menu_item_shift_left);
377
gtk_container_add(GTK_CONTAINER(geany->main_widgets->tools_menu),
378
menu_item_shift_left);
379
g_signal_connect(menu_item_shift_left, "activate",
380
G_CALLBACK(shift_left_cb), NULL);
382
menu_item_shift_right = gtk_menu_item_new_with_mnemonic(_("Shift Right"));
383
gtk_widget_show(menu_item_shift_right);
384
gtk_container_add(GTK_CONTAINER(geany->main_widgets->tools_menu),
385
menu_item_shift_right);
386
g_signal_connect(menu_item_shift_right, "activate",
387
G_CALLBACK(shift_right_cb), NULL);
389
/* make sure our menu items aren't called when there is no doc open */
390
ui_add_document_sensitive(menu_item_shift_right);
391
ui_add_document_sensitive(menu_item_shift_left);
393
/* setup keybindings */
394
keybindings_set_item(plugin_key_group, KB_SHIFT_LEFT, kb_shift_left,
395
GDK_9, GDK_CONTROL_MASK, "shift_left", _("Shift Left"), menu_item_shift_left);
396
keybindings_set_item(plugin_key_group, KB_SHIFT_RIGHT, kb_shift_right,
397
GDK_0, GDK_CONTROL_MASK, "shift_right", _("Shift Right"), menu_item_shift_right);
400
void plugin_cleanup(void){
401
gtk_widget_destroy(menu_item_shift_left);
402
gtk_widget_destroy(menu_item_shift_right);