word-chars setting

This commit is contained in:
Yevgen Muntyan 2008-01-06 12:50:09 -06:00
parent cb4d7d756a
commit eb3a5b1509
7 changed files with 137 additions and 51 deletions

View File

@ -65,6 +65,7 @@ enum {
MOO_EDIT_SETTING_WRAP_MODE, MOO_EDIT_SETTING_WRAP_MODE,
MOO_EDIT_SETTING_SHOW_LINE_NUMBERS, MOO_EDIT_SETTING_SHOW_LINE_NUMBERS,
MOO_EDIT_SETTING_TAB_WIDTH, MOO_EDIT_SETTING_TAB_WIDTH,
MOO_EDIT_SETTING_WORD_CHARS,
MOO_EDIT_LAST_SETTING MOO_EDIT_LAST_SETTING
}; };

View File

@ -1002,6 +1002,7 @@ moo_edit_apply_config (MooEdit *edit)
GtkWrapMode wrap_mode; GtkWrapMode wrap_mode;
gboolean line_numbers; gboolean line_numbers;
guint tab_width; guint tab_width;
char *word_chars;
moo_edit_apply_lang_config (edit); moo_edit_apply_lang_config (edit);
@ -1009,11 +1010,13 @@ moo_edit_apply_config (MooEdit *edit)
"wrap-mode", &wrap_mode, "wrap-mode", &wrap_mode,
"show-line-numbers", &line_numbers, "show-line-numbers", &line_numbers,
"tab-width", &tab_width, "tab-width", &tab_width,
"word-chars", &word_chars,
NULL); NULL);
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (edit), wrap_mode); gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (edit), wrap_mode);
moo_text_view_set_show_line_numbers (MOO_TEXT_VIEW (edit), line_numbers); moo_text_view_set_show_line_numbers (MOO_TEXT_VIEW (edit), line_numbers);
moo_text_view_set_tab_width (MOO_TEXT_VIEW (edit), tab_width); moo_text_view_set_tab_width (MOO_TEXT_VIEW (edit), tab_width);
moo_text_view_set_word_chars (MOO_TEXT_VIEW (edit), word_chars);
} }

View File

@ -32,11 +32,17 @@ parent_class (void)
static gboolean static gboolean
is_word_char (const GtkTextIter *iter) iter_is_word_char (const GtkTextIter *iter,
MooTextView *view)
{ {
guint i;
gunichar c = gtk_text_iter_get_char (iter); gunichar c = gtk_text_iter_get_char (iter);
g_return_val_if_fail (c != 0, FALSE);
return g_unichar_isalnum (c) || c == '_'; for (i = 0; i < view->priv->n_word_chars; ++i)
if (c == view->priv->word_chars[i])
return TRUE;
return c == '_' || g_unichar_isalnum (c);
} }
/* Glib docs say: "(Note: don't use this to do word breaking; you have /* Glib docs say: "(Note: don't use this to do word breaking; you have
@ -44,58 +50,72 @@ is_word_char (const GtkTextIter *iter)
* is fairly complex.)" * is fairly complex.)"
*/ */
static gboolean static gboolean
is_space (const GtkTextIter *iter) iter_is_space (const GtkTextIter *iter)
{ {
gunichar c = gtk_text_iter_get_char (iter); gunichar c = gtk_text_iter_get_char (iter);
g_return_val_if_fail (c != 0, FALSE);
return g_unichar_isspace (c); return g_unichar_isspace (c);
} }
static gboolean static gboolean
is_word_start (const GtkTextIter *iter) iter_is_word_start (const GtkTextIter *iter,
MooTextView *view)
{ {
GtkTextIter i; GtkTextIter i;
if (!is_word_char (iter)) return FALSE;
if (!iter_is_word_char (iter, view))
return FALSE;
i = *iter; i = *iter;
if (!gtk_text_iter_backward_char (&i)) return TRUE;
return !is_word_char (&i); return !gtk_text_iter_backward_char (&i) ||
!iter_is_word_char (&i, view);
} }
static gboolean static gboolean
text_iter_forward_word_start (GtkTextIter *iter) text_iter_forward_word_start (GtkTextIter *iter,
MooTextView *view)
{ {
gboolean moved = FALSE; gboolean moved = FALSE;
if (gtk_text_iter_is_end (iter)) return FALSE;
/* if iter points to word char, then go to the first non-space char after the word if (gtk_text_iter_is_end (iter))
* otherwise, go to the next word char return FALSE;
/* if iter points to a word char then go to the first non-space char after the word;
* otherwise, go to the next word char;
* stop at end of line * stop at end of line
*/ */
if (is_word_char (iter)) { if (iter_is_word_char (iter, view))
while (!gtk_text_iter_is_end (iter) && is_word_char (iter)) {
while (!gtk_text_iter_is_end (iter) && iter_is_word_char (iter, view))
{ {
gtk_text_iter_forward_cursor_position (iter); gtk_text_iter_forward_cursor_position (iter);
moved = TRUE; moved = TRUE;
} }
if (gtk_text_iter_is_end (iter)) return FALSE;
if (gtk_text_iter_is_end (iter))
return FALSE;
while (!gtk_text_iter_is_end (iter) && while (!gtk_text_iter_is_end (iter) &&
is_space (iter) && iter_is_space (iter) &&
!gtk_text_iter_ends_line (iter)) !gtk_text_iter_ends_line (iter))
{ {
gtk_text_iter_forward_cursor_position (iter); gtk_text_iter_forward_cursor_position (iter);
moved = TRUE; moved = TRUE;
} }
} }
else { else
if (gtk_text_iter_ends_line (iter)) { {
if (gtk_text_iter_ends_line (iter))
{
gtk_text_iter_forward_cursor_position (iter); gtk_text_iter_forward_cursor_position (iter);
moved = TRUE; moved = TRUE;
} }
else { else
{
while (!gtk_text_iter_is_end (iter) && while (!gtk_text_iter_is_end (iter) &&
!is_word_char (iter) && !iter_is_word_char (iter, view) &&
!gtk_text_iter_ends_line (iter)) !gtk_text_iter_ends_line (iter))
{ {
gtk_text_iter_forward_cursor_position (iter); gtk_text_iter_forward_cursor_position (iter);
@ -103,52 +123,70 @@ text_iter_forward_word_start (GtkTextIter *iter)
} }
} }
} }
return moved && !gtk_text_iter_is_end (iter); return moved && !gtk_text_iter_is_end (iter);
} }
static gboolean static gboolean
text_iter_forward_word_start_n (GtkTextIter *iter, guint count) text_iter_forward_word_start_n (GtkTextIter *iter,
guint count,
MooTextView *view)
{ {
if (!count) return FALSE; if (!count)
while (count) { return FALSE;
if (!text_iter_forward_word_start (iter)) {
while (count)
{
if (!text_iter_forward_word_start (iter, view))
{
gtk_text_iter_forward_to_end (iter); gtk_text_iter_forward_to_end (iter);
return FALSE; return FALSE;
} }
else
--count; --count;
} }
return TRUE; return TRUE;
} }
static gboolean static gboolean
text_iter_backward_word_start (GtkTextIter *iter) text_iter_backward_word_start (GtkTextIter *iter,
MooTextView *view)
{ {
gboolean moved = FALSE; gboolean moved = FALSE;
if (gtk_text_iter_starts_line (iter)) {
if (gtk_text_iter_starts_line (iter))
{
moved = gtk_text_iter_backward_cursor_position (iter); moved = gtk_text_iter_backward_cursor_position (iter);
/* it may point now to \n in \r\n combination, fixed in gtk-2.10 */ /* it may point now to \n in \r\n combination, fixed in gtk-2.10 */
if (moved && !gtk_text_iter_ends_line (iter)) if (moved && !gtk_text_iter_ends_line (iter))
gtk_text_iter_backward_char (iter); gtk_text_iter_backward_char (iter);
} }
else { else
{
while (gtk_text_iter_backward_cursor_position (iter) && while (gtk_text_iter_backward_cursor_position (iter) &&
!is_word_start (iter) && !iter_is_word_start (iter, view) &&
!gtk_text_iter_starts_line (iter)) !gtk_text_iter_starts_line (iter))
moved = TRUE; moved = TRUE;
} }
return moved; return moved;
} }
static gboolean static gboolean
text_iter_backward_word_start_n (GtkTextIter *iter, guint count) text_iter_backward_word_start_n (GtkTextIter *iter,
guint count,
MooTextView *view)
{ {
gboolean moved = FALSE; gboolean moved = FALSE;
while (count && text_iter_backward_word_start (iter)) {
while (count && text_iter_backward_word_start (iter, view))
{
moved = TRUE; moved = TRUE;
--count; --count;
} }
return moved; return moved;
} }
@ -187,14 +225,14 @@ move_cursor_to (GtkTextView *text_view,
static void static void
moo_text_view_move_cursor_words (G_GNUC_UNUSED MooTextView *view, moo_text_view_move_cursor_words (MooTextView *view,
GtkTextIter *iter, GtkTextIter *iter,
gint count) gint count)
{ {
if (count < 0) if (count < 0)
text_iter_backward_word_start_n (iter, -count); text_iter_backward_word_start_n (iter, -count, view);
else if (count > 0) else if (count > 0)
text_iter_forward_word_start_n (iter, count); text_iter_forward_word_start_n (iter, count, view);
} }
@ -214,7 +252,7 @@ moo_text_view_home_end (MooTextView *view,
while (!gtk_text_iter_ends_line (&first)) while (!gtk_text_iter_ends_line (&first))
{ {
if (is_space (&first)) if (iter_is_space (&first))
gtk_text_iter_forward_cursor_position (&first); gtk_text_iter_forward_cursor_position (&first);
else else
break; break;
@ -235,7 +273,7 @@ moo_text_view_home_end (MooTextView *view,
{ {
gtk_text_iter_backward_cursor_position (&last); gtk_text_iter_backward_cursor_position (&last);
if (!is_space (&last)) if (!iter_is_space (&last))
{ {
gtk_text_iter_forward_cursor_position (&last); gtk_text_iter_forward_cursor_position (&last);
break; break;
@ -347,6 +385,7 @@ _moo_text_view_delete_from_cursor (GtkTextView *text_view,
GtkTextBuffer *buf; GtkTextBuffer *buf;
GtkTextMark *insert_mark; GtkTextMark *insert_mark;
GtkTextIter insert, start, end; GtkTextIter insert, start, end;
MooTextView *view = MOO_TEXT_VIEW (text_view);
if (type != GTK_DELETE_WORD_ENDS) if (type != GTK_DELETE_WORD_ENDS)
{ {
@ -372,9 +411,9 @@ _moo_text_view_delete_from_cursor (GtkTextView *text_view,
end = insert; end = insert;
if (count > 0) if (count > 0)
text_iter_forward_word_start_n (&end, count); text_iter_forward_word_start_n (&end, count, view);
else if (count < 0) else if (count < 0)
text_iter_backward_word_start_n (&start, -count); text_iter_backward_word_start_n (&start, -count, view);
if (!gtk_text_iter_equal (&start, &end)) if (!gtk_text_iter_equal (&start, &end))
{ {
@ -921,12 +960,19 @@ text_view_start_selection_dnd (GtkTextView *text_view,
static int static int
char_class (const GtkTextIter *iter) iter_get_char_class (const GtkTextIter *iter,
MooTextView *view)
{ {
if (gtk_text_iter_ends_line (iter)) return -1; if (gtk_text_iter_ends_line (iter))
else if (is_space (iter)) return 0; return -1;
else if (is_word_char (iter)) return 1;
else return 2; if (iter_is_space (iter))
return 0;
if (iter_is_word_char (iter, view))
return 1;
return 2;
} }
#define FIND_BRACKET_LIMIT 2000 #define FIND_BRACKET_LIMIT 2000
@ -984,23 +1030,23 @@ _moo_text_view_extend_selection (MooTextView *view,
start = end; end = tmp; start = end; end = tmp;
} }
ch_class = char_class (end); ch_class = iter_get_char_class (end, view);
while (!gtk_text_iter_ends_line (end) && while (!gtk_text_iter_ends_line (end) &&
char_class (end) == ch_class) iter_get_char_class (end, view) == ch_class)
{ {
gtk_text_iter_forward_cursor_position (end); gtk_text_iter_forward_cursor_position (end);
} }
ch_class = char_class (start); ch_class = iter_get_char_class (start, view);
while (!gtk_text_iter_starts_line (start) && while (!gtk_text_iter_starts_line (start) &&
char_class (start) == ch_class) iter_get_char_class (start, view) == ch_class)
{ {
gtk_text_iter_backward_cursor_position (start); gtk_text_iter_backward_cursor_position (start);
} }
if (char_class (start) != ch_class) if (iter_get_char_class (start, view) != ch_class)
gtk_text_iter_forward_cursor_position (start); gtk_text_iter_forward_cursor_position (start);
return gtk_text_iter_compare (start, end); return gtk_text_iter_compare (start, end);

View File

@ -67,6 +67,9 @@ _moo_edit_init_config (void)
moo_edit_config_install_setting (g_param_spec_uint ("tab-width", "tab-width", "tab-width", moo_edit_config_install_setting (g_param_spec_uint ("tab-width", "tab-width", "tab-width",
1, G_MAXUINT, 8, 1, G_MAXUINT, 8,
G_PARAM_READWRITE)); G_PARAM_READWRITE));
_moo_edit_settings[MOO_EDIT_SETTING_WORD_CHARS] =
moo_edit_config_install_setting (g_param_spec_string ("word-chars", "word-chars", "word-chars",
NULL, G_PARAM_READWRITE));
} }

View File

@ -159,6 +159,9 @@ struct _MooTextViewPrivate {
gunichar char_inserted; gunichar char_inserted;
int char_inserted_offset; int char_inserted_offset;
gunichar *word_chars;
guint n_word_chars;
/***********************************************************************/ /***********************************************************************/
/* Selection and drag /* Selection and drag
*/ */

View File

@ -262,7 +262,6 @@ static void moo_text_view_class_init (MooTextViewClass *klass)
gobject_class->constructor = moo_text_view_constructor; gobject_class->constructor = moo_text_view_constructor;
gobject_class->finalize = moo_text_view_finalize; gobject_class->finalize = moo_text_view_finalize;
widget_class->button_press_event = _moo_text_view_button_press_event; widget_class->button_press_event = _moo_text_view_button_press_event;
widget_class->button_release_event = _moo_text_view_button_release_event; widget_class->button_release_event = _moo_text_view_button_release_event;
widget_class->motion_notify_event = _moo_text_view_motion_event; widget_class->motion_notify_event = _moo_text_view_motion_event;
@ -663,6 +662,9 @@ moo_text_view_init (MooTextView *view)
view->priv->colors[MOO_TEXT_VIEW_COLOR_RIGHT_MARGIN] = g_strdup (LIGHT_BLUE); view->priv->colors[MOO_TEXT_VIEW_COLOR_RIGHT_MARGIN] = g_strdup (LIGHT_BLUE);
view->priv->right_margin_offset = 80; view->priv->right_margin_offset = 80;
view->priv->word_chars = NULL;
view->priv->n_word_chars = 0;
view->priv->dnd.button = GDK_BUTTON_RELEASE; view->priv->dnd.button = GDK_BUTTON_RELEASE;
view->priv->dnd.type = MOO_TEXT_VIEW_DRAG_NONE; view->priv->dnd.type = MOO_TEXT_VIEW_DRAG_NONE;
view->priv->dnd.start_x = -1; view->priv->dnd.start_x = -1;
@ -794,6 +796,7 @@ moo_text_view_finalize (GObject *object)
g_object_unref (mark); g_object_unref (mark);
} }
g_free (view->priv->word_chars);
g_slist_free (view->priv->line_marks); g_slist_free (view->priv->line_marks);
G_OBJECT_CLASS (moo_text_view_parent_class)->finalize (object); G_OBJECT_CLASS (moo_text_view_parent_class)->finalize (object);
@ -1343,6 +1346,30 @@ moo_text_view_char_inserted (MooTextView *view,
} }
void
moo_text_view_set_word_chars (MooTextView *view,
const char *word_chars)
{
guint i;
g_return_if_fail (MOO_IS_TEXT_VIEW (view));
g_return_if_fail (!word_chars || g_utf8_validate (word_chars, -1, NULL));
g_free (view->priv->word_chars);
view->priv->word_chars = NULL;
view->priv->n_word_chars = 0;
if (!word_chars || !word_chars[0])
return;
view->priv->n_word_chars = g_utf8_strlen (word_chars, -1);
view->priv->word_chars = g_new0 (gunichar, view->priv->n_word_chars);
for (i = 0; *word_chars; i++, word_chars = g_utf8_next_char (word_chars))
view->priv->word_chars[i] = g_utf8_get_char (word_chars);
}
static void static void
cursor_moved (MooTextView *view, cursor_moved (MooTextView *view,
GtkTextIter *where) GtkTextIter *where)

View File

@ -148,6 +148,9 @@ void moo_text_view_set_lang (MooTextView *view,
void moo_text_view_set_lang_by_id (MooTextView *view, void moo_text_view_set_lang_by_id (MooTextView *view,
const char *id); const char *id);
void moo_text_view_set_word_chars (MooTextView *view,
const char *word_chars);
void moo_text_view_strip_whitespace (MooTextView *view); void moo_text_view_strip_whitespace (MooTextView *view);
void moo_text_view_add_child_in_border (MooTextView *view, void moo_text_view_add_child_in_border (MooTextView *view,