void gimp_text_tool_editor_button_press (GimpTextTool *text_tool, gdouble x, gdouble y, GimpButtonPressType press_type) { GtkTextBuffer *buffer = GTK_TEXT_BUFFER (text_tool->buffer); GtkTextIter cursor; GtkTextIter selection; gimp_text_tool_xy_to_iter (text_tool, x, y, &cursor); selection = cursor; text_tool->select_start_iter = cursor; text_tool->select_words = FALSE; text_tool->select_lines = FALSE; switch (press_type) { case GIMP_BUTTON_PRESS_NORMAL: gtk_text_buffer_place_cursor (buffer, &cursor); break; case GIMP_BUTTON_PRESS_DOUBLE: text_tool->select_words = TRUE; if (! gtk_text_iter_starts_word (&cursor)) gtk_text_iter_backward_visible_word_starts (&cursor, 1); if (! gtk_text_iter_ends_word (&selection) && ! gtk_text_iter_forward_visible_word_ends (&selection, 1)) gtk_text_iter_forward_to_line_end (&selection); gtk_text_buffer_select_range (buffer, &cursor, &selection); break; case GIMP_BUTTON_PRESS_TRIPLE: text_tool->select_lines = TRUE; gtk_text_iter_set_line_offset (&cursor, 0); gtk_text_iter_forward_to_line_end (&selection); gtk_text_buffer_select_range (buffer, &cursor, &selection); break; } }
static void gimp_text_tool_delete_from_cursor (GimpTextTool *text_tool, GtkDeleteType type, gint count) { GtkTextBuffer *buffer = GTK_TEXT_BUFFER (text_tool->buffer); GtkTextIter cursor; GtkTextIter end; GIMP_LOG (TEXT_EDITING, "%s count = %d", g_enum_get_value (g_type_class_ref (GTK_TYPE_DELETE_TYPE), type)->value_name, count); gimp_text_tool_reset_im_context (text_tool); gtk_text_buffer_get_iter_at_mark (buffer, &cursor, gtk_text_buffer_get_insert (buffer)); end = cursor; switch (type) { case GTK_DELETE_CHARS: if (gtk_text_buffer_get_has_selection (buffer)) { gtk_text_buffer_delete_selection (buffer, TRUE, TRUE); return; } else { gtk_text_iter_forward_cursor_positions (&end, count); } break; case GTK_DELETE_WORD_ENDS: if (count < 0) { if (! gtk_text_iter_starts_word (&cursor)) gtk_text_iter_backward_visible_word_starts (&cursor, 1); } else if (count > 0) { if (! gtk_text_iter_ends_word (&end) && ! gtk_text_iter_forward_visible_word_ends (&end, 1)) gtk_text_iter_forward_to_line_end (&end); } break; case GTK_DELETE_WORDS: if (! gtk_text_iter_starts_word (&cursor)) gtk_text_iter_backward_visible_word_starts (&cursor, 1); if (! gtk_text_iter_ends_word (&end) && ! gtk_text_iter_forward_visible_word_ends (&end, 1)) gtk_text_iter_forward_to_line_end (&end); break; case GTK_DELETE_DISPLAY_LINES: break; case GTK_DELETE_DISPLAY_LINE_ENDS: break; case GTK_DELETE_PARAGRAPH_ENDS: if (count < 0) { gtk_text_iter_set_line_offset (&cursor, 0); } else if (count > 0) { if (! gtk_text_iter_ends_line (&end)) gtk_text_iter_forward_to_line_end (&end); else gtk_text_iter_forward_cursor_positions (&end, 1); } break; case GTK_DELETE_PARAGRAPHS: break; case GTK_DELETE_WHITESPACE: find_whitepace_region (&cursor, &cursor, &end); break; } if (! gtk_text_iter_equal (&cursor, &end)) { gtk_text_buffer_delete_interactive (buffer, &cursor, &end, TRUE); } }
static void gimp_text_tool_move_cursor (GimpTextTool *text_tool, GtkMovementStep step, gint count, gboolean extend_selection) { GtkTextBuffer *buffer = GTK_TEXT_BUFFER (text_tool->buffer); GtkTextIter cursor; GtkTextIter selection; GtkTextIter *sel_start; gboolean cancel_selection = FALSE; gint x_pos = -1; GIMP_LOG (TEXT_EDITING, "%s count = %d, select = %s", g_enum_get_value (g_type_class_ref (GTK_TYPE_MOVEMENT_STEP), step)->value_name, count, extend_selection ? "TRUE" : "FALSE"); gtk_text_buffer_get_iter_at_mark (buffer, &cursor, gtk_text_buffer_get_insert (buffer)); gtk_text_buffer_get_iter_at_mark (buffer, &selection, gtk_text_buffer_get_selection_bound (buffer)); if (extend_selection) { sel_start = &selection; } else { /* when there is a selection, moving the cursor without * extending it should move the cursor to the end of the * selection that is in moving direction */ if (count > 0) gtk_text_iter_order (&selection, &cursor); else gtk_text_iter_order (&cursor, &selection); sel_start = &cursor; /* if we actually have a selection, just move *to* the beginning/end * of the selection and not *from* there on LOGICAL_POSITIONS * and VISUAL_POSITIONS movement */ if (! gtk_text_iter_equal (&cursor, &selection)) cancel_selection = TRUE; } switch (step) { case GTK_MOVEMENT_LOGICAL_POSITIONS: if (! cancel_selection) gtk_text_iter_forward_visible_cursor_positions (&cursor, count); break; case GTK_MOVEMENT_VISUAL_POSITIONS: if (! cancel_selection) { PangoLayout *layout; const gchar *text; if (! gimp_text_tool_ensure_layout (text_tool)) break; layout = gimp_text_layout_get_pango_layout (text_tool->layout); text = pango_layout_get_text (layout); while (count != 0) { const gunichar word_joiner = 8288; /*g_utf8_get_char(WORD_JOINER);*/ gint index; gint trailing = 0; gint new_index; index = gimp_text_buffer_get_iter_index (text_tool->buffer, &cursor, TRUE); if (count > 0) { if (g_utf8_get_char (text + index) == word_joiner) pango_layout_move_cursor_visually (layout, TRUE, index, 0, 1, &new_index, &trailing); else new_index = index; pango_layout_move_cursor_visually (layout, TRUE, new_index, trailing, 1, &new_index, &trailing); count--; } else { pango_layout_move_cursor_visually (layout, TRUE, index, 0, -1, &new_index, &trailing); if (new_index != -1 && new_index != G_MAXINT && g_utf8_get_char (text + new_index) == word_joiner) { pango_layout_move_cursor_visually (layout, TRUE, new_index, trailing, -1, &new_index, &trailing); } count++; } if (new_index != G_MAXINT && new_index != -1) index = new_index; else break; gimp_text_buffer_get_iter_at_index (text_tool->buffer, &cursor, index, TRUE); gtk_text_iter_forward_chars (&cursor, trailing); } } break; case GTK_MOVEMENT_WORDS: if (count < 0) { gtk_text_iter_backward_visible_word_starts (&cursor, -count); } else if (count > 0) { if (! gtk_text_iter_forward_visible_word_ends (&cursor, count)) gtk_text_iter_forward_to_line_end (&cursor); } break; case GTK_MOVEMENT_DISPLAY_LINES: { GtkTextIter start; GtkTextIter end; gint cursor_index; PangoLayout *layout; PangoLayoutLine *layout_line; PangoLayoutIter *layout_iter; PangoRectangle logical; gint line; gint trailing; gint i; gtk_text_buffer_get_bounds (buffer, &start, &end); cursor_index = gimp_text_buffer_get_iter_index (text_tool->buffer, &cursor, TRUE); if (! gimp_text_tool_ensure_layout (text_tool)) break; layout = gimp_text_layout_get_pango_layout (text_tool->layout); pango_layout_index_to_line_x (layout, cursor_index, FALSE, &line, &x_pos); layout_iter = pango_layout_get_iter (layout); for (i = 0; i < line; i++) pango_layout_iter_next_line (layout_iter); pango_layout_iter_get_line_extents (layout_iter, NULL, &logical); x_pos += logical.x; pango_layout_iter_free (layout_iter); /* try to go to the remembered x_pos if it exists *and* we are at * the beginning or at the end of the current line */ if (text_tool->x_pos != -1 && (x_pos <= logical.x || x_pos >= logical.x + logical.width)) x_pos = text_tool->x_pos; line += count; if (line < 0) { cursor = start; break; } else if (line >= pango_layout_get_line_count (layout)) { cursor = end; break; } layout_iter = pango_layout_get_iter (layout); for (i = 0; i < line; i++) pango_layout_iter_next_line (layout_iter); layout_line = pango_layout_iter_get_line_readonly (layout_iter); pango_layout_iter_get_line_extents (layout_iter, NULL, &logical); pango_layout_iter_free (layout_iter); pango_layout_line_x_to_index (layout_line, x_pos - logical.x, &cursor_index, &trailing); gimp_text_buffer_get_iter_at_index (text_tool->buffer, &cursor, cursor_index, TRUE); while (trailing--) gtk_text_iter_forward_char (&cursor); } break; case GTK_MOVEMENT_PAGES: /* well... */ case GTK_MOVEMENT_BUFFER_ENDS: if (count < 0) { gtk_text_buffer_get_start_iter (buffer, &cursor); } else if (count > 0) { gtk_text_buffer_get_end_iter (buffer, &cursor); } break; case GTK_MOVEMENT_PARAGRAPH_ENDS: if (count < 0) { gtk_text_iter_set_line_offset (&cursor, 0); } else if (count > 0) { if (! gtk_text_iter_ends_line (&cursor)) gtk_text_iter_forward_to_line_end (&cursor); } break; case GTK_MOVEMENT_DISPLAY_LINE_ENDS: if (count < 0) { gtk_text_iter_set_line_offset (&cursor, 0); } else if (count > 0) { if (! gtk_text_iter_ends_line (&cursor)) gtk_text_iter_forward_to_line_end (&cursor); } break; default: return; } text_tool->x_pos = x_pos; gimp_draw_tool_pause (GIMP_DRAW_TOOL (text_tool)); gimp_text_tool_reset_im_context (text_tool); gtk_text_buffer_select_range (buffer, &cursor, sel_start); gimp_draw_tool_resume (GIMP_DRAW_TOOL (text_tool)); }
void gimp_text_tool_editor_motion (GimpTextTool *text_tool, gdouble x, gdouble y) { GtkTextBuffer *buffer = GTK_TEXT_BUFFER (text_tool->buffer); GtkTextIter old_cursor; GtkTextIter old_selection; GtkTextIter cursor; GtkTextIter selection; gtk_text_buffer_get_iter_at_mark (buffer, &old_cursor, gtk_text_buffer_get_insert (buffer)); gtk_text_buffer_get_iter_at_mark (buffer, &old_selection, gtk_text_buffer_get_selection_bound (buffer)); gimp_text_tool_xy_to_iter (text_tool, x, y, &cursor); selection = text_tool->select_start_iter; if (text_tool->select_words || text_tool->select_lines) { GtkTextIter start; GtkTextIter end; if (gtk_text_iter_compare (&cursor, &selection) < 0) { start = cursor; end = selection; } else { start = selection; end = cursor; } if (text_tool->select_words) { if (! gtk_text_iter_starts_word (&start)) gtk_text_iter_backward_visible_word_starts (&start, 1); if (! gtk_text_iter_ends_word (&end) && ! gtk_text_iter_forward_visible_word_ends (&end, 1)) gtk_text_iter_forward_to_line_end (&end); } else if (text_tool->select_lines) { gtk_text_iter_set_line_offset (&start, 0); gtk_text_iter_forward_to_line_end (&end); } if (gtk_text_iter_compare (&cursor, &selection) < 0) { cursor = start; selection = end; } else { selection = start; cursor = end; } } if (! gtk_text_iter_equal (&cursor, &old_cursor) || ! gtk_text_iter_equal (&selection, &old_selection)) { gimp_draw_tool_pause (GIMP_DRAW_TOOL (text_tool)); gtk_text_buffer_select_range (buffer, &cursor, &selection); gimp_draw_tool_resume (GIMP_DRAW_TOOL (text_tool)); } }
void _ide_source_view_apply_movement (IdeSourceView *self, IdeSourceViewMovement movement, gboolean extend_selection, gboolean exclusive, guint count, gunichar command, gunichar modifier, gunichar search_char, gint *target_offset) { Movement mv = { 0 }; GtkTextBuffer *buffer; GtkTextMark *insert; gsize i; g_return_if_fail (IDE_IS_SOURCE_VIEW (self)); #ifdef IDE_ENABLE_TRACE { GEnumValue *enum_value; GEnumClass *enum_class; enum_class = g_type_class_ref (IDE_TYPE_SOURCE_VIEW_MOVEMENT); enum_value = g_enum_get_value (enum_class, movement); IDE_TRACE_MSG ("movement(%s, extend_selection=%s, exclusive=%s, count=%u)", enum_value->value_nick, extend_selection ? "YES" : "NO", exclusive ? "YES" : "NO", count); g_type_class_unref (enum_class); } #endif buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (self)); insert = gtk_text_buffer_get_insert (buffer); mv.self = self; mv.target_offset = target_offset; mv.type = movement; mv.extend_selection = extend_selection; mv.exclusive = exclusive; mv.count = count; mv.ignore_select = FALSE; mv.ignore_target_offset = FALSE; mv.command = command; mv.modifier = modifier; ide_source_view_movements_get_selection (&mv); switch (movement) { case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_OFFSET: gtk_text_iter_backward_chars (&mv.insert, MAX (1, mv.count)); break; case IDE_SOURCE_VIEW_MOVEMENT_NEXT_OFFSET: gtk_text_iter_forward_chars (&mv.insert, MAX (1, mv.count)); break; case IDE_SOURCE_VIEW_MOVEMENT_NTH_CHAR: ide_source_view_movements_nth_char (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_CHAR: ide_source_view_movements_previous_char (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_NEXT_CHAR: ide_source_view_movements_next_char (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_FIRST_CHAR: ide_source_view_movements_first_char (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_FIRST_NONSPACE_CHAR: ide_source_view_movements_first_nonspace_char (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_MIDDLE_CHAR: ide_source_view_movements_middle_char (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_LAST_CHAR: ide_source_view_movements_last_char (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_FULL_WORD_START: for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_previous_full_word_start (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_NEXT_FULL_WORD_START: for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_next_full_word_start (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_FULL_WORD_END: for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_previous_full_word_end (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_NEXT_FULL_WORD_END: for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_next_full_word_end (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_SUB_WORD_START: gtk_text_iter_backward_visible_word_starts (&mv.insert, MAX (1, mv.count)); break; case IDE_SOURCE_VIEW_MOVEMENT_NEXT_SUB_WORD_START: if (!gtk_text_iter_forward_visible_word_ends (&mv.insert, MAX (1, mv.count))) gtk_text_iter_forward_to_line_end (&mv.insert); break; case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_WORD_START: for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_previous_word_start (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_NEXT_WORD_START: for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_next_word_start (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_WORD_END: for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_previous_word_end (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_NEXT_WORD_END: for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_next_word_end (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_SENTENCE_START: for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_sentence_start (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_SENTENCE_END: for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_sentence_end (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_PARAGRAPH_START: for (i = MAX (1, mv.count); i > 0; i--) { mv.exclusive = exclusive && i == 1; ide_source_view_movements_paragraph_start (&mv); } break; case IDE_SOURCE_VIEW_MOVEMENT_PARAGRAPH_END: for (i = MAX (1, mv.count); i > 0; i--) { mv.exclusive = exclusive && i == 1; ide_source_view_movements_paragraph_end (&mv); } break; case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_LINE: mv.ignore_target_offset = TRUE; mv.ignore_select = TRUE; for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_previous_line (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_NEXT_LINE: mv.ignore_target_offset = TRUE; mv.ignore_select = TRUE; for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_next_line (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_FIRST_LINE: ide_source_view_movements_first_line (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_NTH_LINE: ide_source_view_movements_nth_line (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_LAST_LINE: ide_source_view_movements_last_line (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_LINE_PERCENTAGE: ide_source_view_movements_line_percentage (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_LINE_CHARS: ide_source_view_movements_line_chars (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_LINE_END: ide_source_view_movements_line_end (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_HALF_PAGE_UP: case IDE_SOURCE_VIEW_MOVEMENT_HALF_PAGE_DOWN: case IDE_SOURCE_VIEW_MOVEMENT_PAGE_UP: case IDE_SOURCE_VIEW_MOVEMENT_PAGE_DOWN: for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_move_page (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_SCREEN_DOWN: case IDE_SOURCE_VIEW_MOVEMENT_SCREEN_UP: for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_scroll (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_SCREEN_TOP: ide_source_view_movements_screen_top (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_SCREEN_MIDDLE: ide_source_view_movements_screen_middle (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_SCREEN_BOTTOM: ide_source_view_movements_screen_bottom (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_MATCH_SPECIAL: ide_source_view_movements_match_special (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_SCROLL_SCREEN_TOP: case IDE_SOURCE_VIEW_MOVEMENT_SCROLL_SCREEN_CENTER: case IDE_SOURCE_VIEW_MOVEMENT_SCROLL_SCREEN_BOTTOM: ide_source_view_movements_scroll_center (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_UNMATCHED_BRACE: for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_previous_unmatched (&mv, '{', '}'); break; case IDE_SOURCE_VIEW_MOVEMENT_NEXT_UNMATCHED_BRACE: for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_next_unmatched (&mv, '}', '{'); break; case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_UNMATCHED_PAREN: for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_previous_unmatched (&mv, '(', ')'); break; case IDE_SOURCE_VIEW_MOVEMENT_NEXT_UNMATCHED_PAREN: for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_next_unmatched (&mv, ')', '('); break; case IDE_SOURCE_VIEW_MOVEMENT_NEXT_MATCH_MODIFIER: for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_next_match_modifier (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_MATCH_MODIFIER: for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_previous_match_modifier (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_MATCH_SEARCH_CHAR: mv.modifier = search_char; for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movement_match_search_char (&mv, FALSE); break; case IDE_SOURCE_VIEW_MOVEMENT_NEXT_MATCH_SEARCH_CHAR: mv.modifier = search_char; for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movement_match_search_char (&mv, TRUE); break; default: g_return_if_reached (); } if (!mv.ignore_select) ide_source_view_movements_select_range (&mv); if (!mv.ignore_target_offset) *target_offset = gtk_text_iter_get_line_offset (&mv.insert); if (!mv.ignore_scroll_to_insert) ide_source_view_scroll_mark_onscreen (self, insert, TRUE, 0.5, 0.5); }