word-chars setting

master
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_SHOW_LINE_NUMBERS,
MOO_EDIT_SETTING_TAB_WIDTH,
MOO_EDIT_SETTING_WORD_CHARS,
MOO_EDIT_LAST_SETTING
};

View File

@ -1002,6 +1002,7 @@ moo_edit_apply_config (MooEdit *edit)
GtkWrapMode wrap_mode;
gboolean line_numbers;
guint tab_width;
char *word_chars;
moo_edit_apply_lang_config (edit);
@ -1009,11 +1010,13 @@ moo_edit_apply_config (MooEdit *edit)
"wrap-mode", &wrap_mode,
"show-line-numbers", &line_numbers,
"tab-width", &tab_width,
"word-chars", &word_chars,
NULL);
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_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
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);
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
@ -44,58 +50,72 @@ is_word_char (const GtkTextIter *iter)
* is fairly complex.)"
*/
static gboolean
is_space (const GtkTextIter *iter)
iter_is_space (const GtkTextIter *iter)
{
gunichar c = gtk_text_iter_get_char (iter);
g_return_val_if_fail (c != 0, FALSE);
return g_unichar_isspace (c);
}
static gboolean
is_word_start (const GtkTextIter *iter)
iter_is_word_start (const GtkTextIter *iter,
MooTextView *view)
{
GtkTextIter i;
if (!is_word_char (iter)) return FALSE;
if (!iter_is_word_char (iter, view))
return FALSE;
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
text_iter_forward_word_start (GtkTextIter *iter)
text_iter_forward_word_start (GtkTextIter *iter,
MooTextView *view)
{
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
* otherwise, go to the next word char
if (gtk_text_iter_is_end (iter))
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
*/
if (is_word_char (iter)) {
while (!gtk_text_iter_is_end (iter) && is_word_char (iter))
if (iter_is_word_char (iter, view))
{
while (!gtk_text_iter_is_end (iter) && iter_is_word_char (iter, view))
{
gtk_text_iter_forward_cursor_position (iter);
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) &&
is_space (iter) &&
iter_is_space (iter) &&
!gtk_text_iter_ends_line (iter))
{
gtk_text_iter_forward_cursor_position (iter);
moved = TRUE;
}
}
else {
if (gtk_text_iter_ends_line (iter)) {
else
{
if (gtk_text_iter_ends_line (iter))
{
gtk_text_iter_forward_cursor_position (iter);
moved = TRUE;
}
else {
else
{
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_forward_cursor_position (iter);
@ -103,52 +123,70 @@ text_iter_forward_word_start (GtkTextIter *iter)
}
}
}
return moved && !gtk_text_iter_is_end (iter);
}
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;
while (count) {
if (!text_iter_forward_word_start (iter)) {
if (!count)
return FALSE;
while (count)
{
if (!text_iter_forward_word_start (iter, view))
{
gtk_text_iter_forward_to_end (iter);
return FALSE;
}
else
--count;
--count;
}
return TRUE;
}
static gboolean
text_iter_backward_word_start (GtkTextIter *iter)
text_iter_backward_word_start (GtkTextIter *iter,
MooTextView *view)
{
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);
/* it may point now to \n in \r\n combination, fixed in gtk-2.10 */
if (moved && !gtk_text_iter_ends_line (iter))
gtk_text_iter_backward_char (iter);
}
else {
else
{
while (gtk_text_iter_backward_cursor_position (iter) &&
!is_word_start (iter) &&
!iter_is_word_start (iter, view) &&
!gtk_text_iter_starts_line (iter))
moved = TRUE;
}
return moved;
}
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;
while (count && text_iter_backward_word_start (iter)) {
while (count && text_iter_backward_word_start (iter, view))
{
moved = TRUE;
--count;
}
return moved;
}
@ -187,14 +225,14 @@ move_cursor_to (GtkTextView *text_view,
static void
moo_text_view_move_cursor_words (G_GNUC_UNUSED MooTextView *view,
moo_text_view_move_cursor_words (MooTextView *view,
GtkTextIter *iter,
gint count)
{
if (count < 0)
text_iter_backward_word_start_n (iter, -count);
text_iter_backward_word_start_n (iter, -count, view);
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))
{
if (is_space (&first))
if (iter_is_space (&first))
gtk_text_iter_forward_cursor_position (&first);
else
break;
@ -235,7 +273,7 @@ moo_text_view_home_end (MooTextView *view,
{
gtk_text_iter_backward_cursor_position (&last);
if (!is_space (&last))
if (!iter_is_space (&last))
{
gtk_text_iter_forward_cursor_position (&last);
break;
@ -347,6 +385,7 @@ _moo_text_view_delete_from_cursor (GtkTextView *text_view,
GtkTextBuffer *buf;
GtkTextMark *insert_mark;
GtkTextIter insert, start, end;
MooTextView *view = MOO_TEXT_VIEW (text_view);
if (type != GTK_DELETE_WORD_ENDS)
{
@ -372,9 +411,9 @@ _moo_text_view_delete_from_cursor (GtkTextView *text_view,
end = insert;
if (count > 0)
text_iter_forward_word_start_n (&end, count);
text_iter_forward_word_start_n (&end, count, view);
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))
{
@ -921,12 +960,19 @@ text_view_start_selection_dnd (GtkTextView *text_view,
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;
else if (is_space (iter)) return 0;
else if (is_word_char (iter)) return 1;
else return 2;
if (gtk_text_iter_ends_line (iter))
return -1;
if (iter_is_space (iter))
return 0;
if (iter_is_word_char (iter, view))
return 1;
return 2;
}
#define FIND_BRACKET_LIMIT 2000
@ -984,23 +1030,23 @@ _moo_text_view_extend_selection (MooTextView *view,
start = end; end = tmp;
}
ch_class = char_class (end);
ch_class = iter_get_char_class (end, view);
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);
}
ch_class = char_class (start);
ch_class = iter_get_char_class (start, view);
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);
}
if (char_class (start) != ch_class)
if (iter_get_char_class (start, view) != ch_class)
gtk_text_iter_forward_cursor_position (start);
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",
1, G_MAXUINT, 8,
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;
int char_inserted_offset;
gunichar *word_chars;
guint n_word_chars;
/***********************************************************************/
/* 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->finalize = moo_text_view_finalize;
widget_class->button_press_event = _moo_text_view_button_press_event;
widget_class->button_release_event = _moo_text_view_button_release_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->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.type = MOO_TEXT_VIEW_DRAG_NONE;
view->priv->dnd.start_x = -1;
@ -794,6 +796,7 @@ moo_text_view_finalize (GObject *object)
g_object_unref (mark);
}
g_free (view->priv->word_chars);
g_slist_free (view->priv->line_marks);
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
cursor_moved (MooTextView *view,
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,
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_add_child_in_border (MooTextView *view,