225 lines
6.6 KiB
C
225 lines
6.6 KiB
C
/*
|
|
* L3afpad - GTK+ based simple text editor
|
|
* Copyright (C) 2004-2005 Tarot Osuji
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include <gtk/gtk.h>
|
|
//#include <gdk/gdkkeysyms.h>
|
|
#include <undo.h>
|
|
#include "indent.h"
|
|
|
|
static gboolean auto_indent = FALSE;
|
|
static gint default_tab_width = 8;
|
|
static gint current_tab_width = 8;
|
|
|
|
gint get_current_tab_width(void)
|
|
{
|
|
return current_tab_width;
|
|
}
|
|
|
|
void indent_set_state(gboolean state)
|
|
{
|
|
auto_indent = state;
|
|
}
|
|
|
|
gboolean indent_get_state(void)
|
|
{
|
|
return auto_indent;
|
|
}
|
|
|
|
static gchar *compute_indentation(GtkTextBuffer *buffer, GtkTextIter *iter, gint line)
|
|
{
|
|
GtkTextIter start_iter, end_iter;
|
|
gunichar ch;
|
|
|
|
gtk_text_buffer_get_iter_at_line(buffer, &start_iter, line);
|
|
end_iter = start_iter;
|
|
ch = gtk_text_iter_get_char(&end_iter);
|
|
while (g_unichar_isspace(ch) && ch != '\n') {
|
|
if (!gtk_text_iter_forward_char(&end_iter))
|
|
break;
|
|
ch = gtk_text_iter_get_char(&end_iter);
|
|
}
|
|
if (gtk_text_iter_equal(&start_iter, &end_iter))
|
|
return NULL;
|
|
|
|
if (iter && gtk_text_iter_compare(iter, &end_iter) < 0)
|
|
return gtk_text_iter_get_text(&start_iter, iter);
|
|
return gtk_text_iter_get_text(&start_iter, &end_iter);
|
|
}
|
|
|
|
void indent_real(GtkWidget *text_view)
|
|
{
|
|
GtkTextIter iter;
|
|
gchar *ind, *str;
|
|
|
|
GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
|
|
|
|
g_signal_emit_by_name(G_OBJECT(buffer), "begin-user-action");
|
|
gtk_text_buffer_delete_selection(buffer, TRUE, TRUE);
|
|
gtk_text_buffer_get_iter_at_mark(buffer, &iter, gtk_text_buffer_get_insert(buffer));
|
|
ind = compute_indentation(buffer, &iter, gtk_text_iter_get_line(&iter));
|
|
str = g_strconcat("\n", ind, NULL);
|
|
gtk_text_buffer_insert(buffer, &iter, str, -1);
|
|
g_signal_emit_by_name(G_OBJECT(buffer), "end-user-action");
|
|
g_free(str);
|
|
g_free(ind);
|
|
|
|
gtk_text_view_scroll_mark_onscreen(
|
|
GTK_TEXT_VIEW(text_view),
|
|
gtk_text_buffer_get_insert(buffer));
|
|
}
|
|
|
|
static gint calculate_real_tab_width(GtkWidget *text_view, guint tab_size) //from gtksourceview
|
|
{
|
|
PangoLayout *layout;
|
|
gchar *tab_string;
|
|
gint tab_width = 0;
|
|
|
|
if (tab_size == 0)
|
|
return -1;
|
|
|
|
tab_string = g_strnfill(tab_size, 0x20);
|
|
layout = gtk_widget_create_pango_layout(text_view, tab_string);
|
|
g_free (tab_string);
|
|
|
|
if (layout != NULL) {
|
|
pango_layout_get_pixel_size(layout, &tab_width, NULL);
|
|
g_object_unref(G_OBJECT(layout));
|
|
} else
|
|
tab_width = -1;
|
|
|
|
return tab_width;
|
|
}
|
|
|
|
void indent_refresh_tab_width(GtkWidget *text_view)
|
|
{
|
|
PangoTabArray *tab_array;
|
|
|
|
tab_array = pango_tab_array_new(1, TRUE);
|
|
pango_tab_array_set_tab(tab_array, 0, PANGO_TAB_LEFT,
|
|
calculate_real_tab_width(text_view, current_tab_width));
|
|
gtk_text_view_set_tabs(GTK_TEXT_VIEW(text_view), tab_array);
|
|
pango_tab_array_free(tab_array);
|
|
}
|
|
|
|
void indent_toggle_tab_width(GtkWidget *text_view)
|
|
{
|
|
if (current_tab_width == default_tab_width)
|
|
if (default_tab_width == 8)
|
|
current_tab_width = 4;
|
|
else
|
|
current_tab_width = 8;
|
|
else
|
|
current_tab_width = default_tab_width;
|
|
indent_refresh_tab_width(text_view);
|
|
}
|
|
|
|
void indent_set_default_tab_width(gint width)
|
|
{
|
|
default_tab_width = width;
|
|
current_tab_width = default_tab_width;
|
|
}
|
|
|
|
void indent_multi_line_indent(GtkTextBuffer *buffer)
|
|
{
|
|
GtkTextIter start_iter, end_iter, iter;
|
|
gint start_line, end_line, i;
|
|
gboolean pos;
|
|
|
|
gtk_text_buffer_get_selection_bounds(buffer, &start_iter, &end_iter);
|
|
start_line = gtk_text_iter_get_line(&start_iter);
|
|
end_line = gtk_text_iter_get_line(&end_iter);
|
|
gtk_text_buffer_get_iter_at_mark(buffer, &iter, gtk_text_buffer_get_insert(buffer));
|
|
pos = gtk_text_iter_equal(&iter, &start_iter);
|
|
for (i = start_line; i < end_line; i++) {
|
|
gtk_text_buffer_get_iter_at_line(buffer, &iter, i);
|
|
gtk_text_buffer_place_cursor(buffer, &iter);
|
|
g_signal_emit_by_name(G_OBJECT(buffer), "begin-user-action");
|
|
gtk_text_buffer_insert(buffer, &iter, "\t", 1);
|
|
g_signal_emit_by_name(G_OBJECT(buffer), "end-user-action");
|
|
undo_set_sequency(TRUE);
|
|
}
|
|
undo_set_sequency(FALSE);
|
|
|
|
gtk_text_buffer_get_iter_at_line(buffer, &start_iter, start_line);
|
|
gtk_text_buffer_get_iter_at_line(buffer, &end_iter, end_line);
|
|
if (pos) {
|
|
gtk_text_buffer_place_cursor(buffer, &end_iter);
|
|
gtk_text_buffer_move_mark_by_name(buffer, "insert", &start_iter);
|
|
} else {
|
|
gtk_text_buffer_place_cursor(buffer, &start_iter);
|
|
gtk_text_buffer_move_mark_by_name(buffer, "insert", &end_iter);
|
|
}
|
|
}
|
|
|
|
static gint compute_indent_offset_length(const gchar *ind)
|
|
{
|
|
guint8 c = *ind;
|
|
gint len = 1;
|
|
|
|
if (c == 0x20)
|
|
while ((len < current_tab_width) && (c = *++ind) == 0x20)
|
|
len++;
|
|
|
|
return len;
|
|
}
|
|
|
|
void indent_multi_line_unindent(GtkTextBuffer *buffer)
|
|
{
|
|
GtkTextIter start_iter, end_iter, iter;
|
|
gint start_line, end_line, i, len;
|
|
gboolean pos;
|
|
gchar *ind;
|
|
|
|
gtk_text_buffer_get_selection_bounds(buffer, &start_iter, &end_iter);
|
|
start_line = gtk_text_iter_get_line(&start_iter);
|
|
end_line = gtk_text_iter_get_line(&end_iter);
|
|
gtk_text_buffer_get_iter_at_mark(buffer, &iter, gtk_text_buffer_get_insert(buffer));
|
|
pos = gtk_text_iter_equal(&iter, &start_iter);
|
|
i = start_line;
|
|
do {
|
|
ind = compute_indentation(buffer, NULL, i);
|
|
if (ind && strlen(ind)) {
|
|
len = compute_indent_offset_length(ind);
|
|
gtk_text_buffer_get_iter_at_line(buffer, &start_iter, i);
|
|
gtk_text_buffer_place_cursor(buffer, &start_iter);
|
|
end_iter = start_iter;
|
|
gtk_text_iter_forward_chars(&end_iter, len);
|
|
gtk_text_buffer_move_mark_by_name(buffer, "insert", &end_iter);
|
|
g_signal_emit_by_name(G_OBJECT(buffer), "begin-user-action");
|
|
gtk_text_buffer_delete(buffer, &start_iter, &end_iter);
|
|
g_signal_emit_by_name(G_OBJECT(buffer), "end-user-action");
|
|
undo_set_sequency(TRUE);
|
|
g_free(ind);
|
|
}
|
|
i++;
|
|
} while (i < end_line);
|
|
undo_set_sequency(FALSE);
|
|
|
|
gtk_text_buffer_get_iter_at_line(buffer, &start_iter, start_line);
|
|
gtk_text_buffer_get_iter_at_line(buffer, &end_iter, end_line);
|
|
if (pos) {
|
|
gtk_text_buffer_place_cursor(buffer, &end_iter);
|
|
gtk_text_buffer_move_mark_by_name(buffer, "insert", &start_iter);
|
|
} else {
|
|
gtk_text_buffer_place_cursor(buffer, &start_iter);
|
|
gtk_text_buffer_move_mark_by_name(buffer, "insert", &end_iter);
|
|
}
|
|
}
|