/* shiftcolumn.c - a Geany plugin * * Copyright 2009 Andrew L Janke * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #ifdef HAVE_LOCALE_H # include #endif #include #include #include GeanyPlugin *geany_plugin; GeanyData *geany_data; PLUGIN_VERSION_CHECK(224) PLUGIN_SET_TRANSLATABLE_INFO(LOCALEDIR, GETTEXT_PACKAGE, _("Shift Column"), _("Shift a selection left and right." "\nThis plugin currently has no maintainer. Would you like to help " "by contributing to this plugin?"), VERSION, "Andrew L Janke ") static GtkWidget *menu_item_shift_left = NULL; static GtkWidget *menu_item_shift_right = NULL; /* Keybinding(s) */ enum{ KB_SHIFT_LEFT, KB_SHIFT_RIGHT, KB_COUNT }; static void shift_left_cb(G_GNUC_UNUSED GtkMenuItem *menuitem, G_GNUC_UNUSED gpointer gdata){ gchar *txt; gchar *txt_i; gchar char_before; gint startpos; gint endpos; gint startline; gint endline; gint line_iter; gint linepos; gint linelen; gint startcol; gint endcol; gint i; gint n_spaces; gchar *spaces; ScintillaObject *sci; /* get a pointer to the scintilla object */ sci = document_get_current()->editor->sci; if (sci_has_selection(sci)){ startpos = sci_get_selection_start(sci); endpos = sci_get_selection_end(sci); /* sanity check -- we dont care which way the block was selected */ if(startpos > endpos){ i = endpos; endpos = startpos; startpos = i; } startline = sci_get_line_from_position(sci, startpos); /* Setting also start point for 1st line */ linepos = sci_get_position_from_line(sci, startline); endline = sci_get_line_from_position(sci, endpos); /* normal mode */ if(startline == endline){ /* get the text in question */ txt_i = sci_get_selection_contents(sci); char_before = sci_get_char_at(sci, startpos - 1); /* set up new text buf */ txt = g_strdup_printf("%s%c", txt_i, char_before); /* start undo */ sci_start_undo_action(sci); /* put the new text in */ sci_set_selection_start(sci, startpos - 1); sci_set_selection_end(sci, endpos); sci_replace_sel(sci, txt); /* select the right bit again */ sci_set_selection_start(sci, startpos - 1); sci_set_selection_end(sci, endpos - 1); /* end undo */ sci_end_undo_action(sci); g_free(txt); g_free(txt_i); } /* rectangle mode (we hope!) */ else{ startcol = sci_get_col_from_position(sci, startpos); endcol = sci_get_col_from_position(sci, endpos); /* return early for the trivial case */ if(startcol == 0 || startcol == endcol){ return; } /* start undo */ sci_start_undo_action(sci); for(line_iter = startline; line_iter <= endline; line_iter++){ linepos = sci_get_position_from_line(sci, line_iter); linelen = sci_get_line_length(sci, line_iter); /* do we need to do something */ if(linelen >= startcol - 1 ){ /* if between the two columns */ /* pad to the end first */ if(linelen <= endcol){ /* bung in some spaces -- sorry, I dont like tabs */ n_spaces = endcol - linelen + 1; spaces = g_malloc(sizeof(gchar) * (n_spaces + 1)); for(i = 0; i < n_spaces; i++){ spaces[i] = ' '; } spaces[i] = '\0'; sci_insert_text(sci, linepos + linelen - 1, spaces); g_free(spaces); } /* now move the text itself */ sci_set_selection_mode(sci, 0); sci_set_selection_start(sci, linepos + startcol); sci_set_selection_end(sci, linepos + endcol); txt_i = sci_get_selection_contents(sci); char_before = sci_get_char_at(sci, linepos + startcol - 1); /* set up new text buf */ txt = g_strdup_printf("%s%c", txt_i, char_before); /* put the new text in */ sci_set_selection_start(sci, linepos + startcol - 1); sci_replace_sel(sci, txt); g_free(txt); g_free(txt_i); } } /* put the selection box back */ /* here we rely upon the last result of linepos */ sci_set_selection_mode(sci, 1); sci_set_selection_start(sci, startpos - 1); sci_set_selection_end(sci, linepos + endcol - 1); /* end undo action */ sci_end_undo_action(sci); } } } static void shift_right_cb(G_GNUC_UNUSED GtkMenuItem *menuitem, G_GNUC_UNUSED gpointer gdata){ gchar *txt; gchar *txt_i; gchar char_after; gint startpos; gint endpos; gint startline; gint endline; gint line_iter; gint linepos; gint linelen; gint startcol; gint endcol; gint i; ScintillaObject *sci; /* get a pointer to the scintilla object */ sci = document_get_current()->editor->sci; if (sci_has_selection(sci)){ startpos = sci_get_selection_start(sci); endpos = sci_get_selection_end(sci); /* sanity check -- we dont care which way the block was selected */ if(startpos > endpos){ i = endpos; endpos = startpos; startpos = i; } startline = sci_get_line_from_position(sci, startpos); linepos = sci_get_position_from_line(sci, startline); endline = sci_get_line_from_position(sci, endpos); /* normal mode */ if(startline == endline){ /* get the text in question */ txt_i = sci_get_selection_contents(sci); char_after = sci_get_char_at(sci, endpos); /* set up new text buf */ txt = g_strdup_printf("%c%s", char_after, txt_i); /* start undo */ sci_start_undo_action(sci); /* put the new text in */ sci_set_selection_start(sci, startpos); sci_set_selection_end(sci, endpos + 1); sci_replace_sel(sci, txt); /* select the right bit again */ sci_set_selection_start(sci, startpos + 1); sci_set_selection_end(sci, endpos + 1); /* end undo */ sci_end_undo_action(sci); g_free(txt); g_free(txt_i); } /* rectangle mode (we hope!) */ else{ startcol = sci_get_col_from_position(sci, startpos); endcol = sci_get_col_from_position(sci, endpos); /* start undo */ sci_start_undo_action(sci); for(line_iter = startline; line_iter <= endline; line_iter++){ linepos = sci_get_position_from_line(sci, line_iter); linelen = sci_get_line_length(sci, line_iter); /* do we need to do something */ if(linelen >= startcol - 1 ){ /* if between the two columns or at the end */ /* add in a space */ if(linelen <= endcol || linelen - 1 == endcol){ txt = g_malloc(sizeof(gchar) * 2); sprintf(txt, " "); sci_insert_text(sci, linepos + startcol, txt); g_free(txt); } else{ /* move the text itself */ sci_set_selection_mode(sci, 0); sci_set_selection_start(sci, linepos + startcol); sci_set_selection_end(sci, linepos + endcol); txt_i = sci_get_selection_contents(sci); char_after = sci_get_char_at(sci, linepos + endcol); /* set up new text buf */ txt = g_strdup_printf("%c%s", char_after, txt_i); /* put the new text in */ sci_set_selection_end(sci, linepos + endcol + 1); sci_replace_sel(sci, txt); g_free(txt); g_free(txt_i); } } } /* put the selection box back */ /* here we rely upon the last result of linepos */ sci_set_selection_mode(sci, 1); sci_set_selection_start(sci, startpos + 1); sci_set_selection_end(sci, linepos + endcol + 1); /* end undo action */ sci_end_undo_action(sci); } } } static void kb_shift_left(G_GNUC_UNUSED guint key_id){ /* sanity check */ if (document_get_current() == NULL){ return; } shift_left_cb(NULL, NULL); } static void kb_shift_right(G_GNUC_UNUSED guint key_id){ /* sanity check */ if (document_get_current() == NULL){ return; } shift_right_cb(NULL, NULL); } void plugin_init(G_GNUC_UNUSED GeanyData *data){ GeanyKeyGroup *key_group; menu_item_shift_left = gtk_menu_item_new_with_mnemonic(_("Shift Left")); gtk_widget_show(menu_item_shift_left); gtk_container_add(GTK_CONTAINER(geany->main_widgets->tools_menu), menu_item_shift_left); g_signal_connect(menu_item_shift_left, "activate", G_CALLBACK(shift_left_cb), NULL); menu_item_shift_right = gtk_menu_item_new_with_mnemonic(_("Shift Right")); gtk_widget_show(menu_item_shift_right); gtk_container_add(GTK_CONTAINER(geany->main_widgets->tools_menu), menu_item_shift_right); g_signal_connect(menu_item_shift_right, "activate", G_CALLBACK(shift_right_cb), NULL); /* make sure our menu items aren't called when there is no doc open */ ui_add_document_sensitive(menu_item_shift_right); ui_add_document_sensitive(menu_item_shift_left); /* setup keybindings */ key_group = plugin_set_key_group(geany_plugin, "shiftcolumn", KB_COUNT, NULL); keybindings_set_item(key_group, KB_SHIFT_LEFT, kb_shift_left, 0, GDK_CONTROL_MASK, "shift_left", _("Shift Left"), menu_item_shift_left); keybindings_set_item(key_group, KB_SHIFT_RIGHT, kb_shift_right, 0, GDK_CONTROL_MASK, "shift_right", _("Shift Right"), menu_item_shift_right); } void plugin_cleanup(void){ gtk_widget_destroy(menu_item_shift_left); gtk_widget_destroy(menu_item_shift_right); }