static gchar * get_word (GtkSourceCompletionProvider *provider, GtkTextIter *iter) { GtkTextIter *end; gboolean moved = FALSE; gunichar c; gchar *word; end = gtk_text_iter_copy(iter); do { if (!gtk_text_iter_backward_char(iter)) { break; } c = gtk_text_iter_get_char(iter); moved = TRUE; } while (!is_stop_char(c)); if (moved && !gtk_text_iter_is_start(iter)) { gtk_text_iter_forward_char(iter); } word = g_strstrip(gtk_text_iter_get_text(iter, end)); gtk_text_iter_free(end); return word; }
/* Symmetric of iter_forward_full_word_end(). */ void _gtk_source_iter_backward_full_word_start (GtkTextIter *iter) { GtkTextIter pos; GtkTextIter prev; gboolean non_blank_found = FALSE; pos = *iter; while (!gtk_text_iter_is_start (&pos)) { prev = pos; gtk_text_iter_backward_visible_cursor_position (&prev); if (!g_unichar_isspace (gtk_text_iter_get_char (&prev))) { break; } pos = prev; } while (!gtk_text_iter_is_start (&pos)) { prev = pos; gtk_text_iter_backward_visible_cursor_position (&prev); if (g_unichar_isspace (gtk_text_iter_get_char (&prev))) { break; } non_blank_found = TRUE; pos = prev; } if (non_blank_found) { *iter = pos; } }
static gchar * smie_gtk_source_buffer_backward_token (gpointer data) { smie_gtk_source_buffer_context_t *context = data; GtkTextIter iter, start_iter; if (gtk_text_iter_is_start (&context->iter)) return NULL; /* Skip comments and whitespaces. */ gtk_text_iter_backward_char (&context->iter); while (!gtk_text_iter_is_start (&context->iter) && (gtk_source_buffer_iter_has_context_class (context->buffer, &context->iter, "comment") || g_unichar_isspace (gtk_text_iter_get_char (&context->iter)))) gtk_text_iter_backward_char (&context->iter); gtk_text_iter_assign (&iter, &context->iter); if (gtk_source_buffer_iter_has_context_class (context->buffer, &context->iter, "string")) { /* Read a string literal. */ while (!gtk_text_iter_is_start (&context->iter) && gtk_source_buffer_iter_has_context_class (context->buffer, &context->iter, "string")) gtk_text_iter_backward_char (&context->iter); } else if (g_unichar_ispunct (gtk_text_iter_get_char (&context->iter))) { /* Read a punctuation. */ while (!gtk_text_iter_is_start (&context->iter) && g_unichar_ispunct (gtk_text_iter_get_char (&context->iter))) gtk_text_iter_backward_char (&context->iter); } else { /* Read a normal token. */ while (!gtk_text_iter_is_start (&context->iter) && !(gtk_source_buffer_iter_has_context_class (context->buffer, &context->iter, "comment") || gtk_source_buffer_iter_has_context_class (context->buffer, &context->iter, "string") || g_unichar_ispunct (gtk_text_iter_get_char (&context->iter)) || g_unichar_isspace (gtk_text_iter_get_char (&context->iter)))) gtk_text_iter_backward_char (&context->iter); } gtk_text_iter_assign (&start_iter, &context->iter); if (!gtk_text_iter_is_start (&start_iter)) gtk_text_iter_forward_char (&start_iter); gtk_text_iter_forward_char (&iter); return gtk_text_iter_get_slice (&start_iter, &iter); }
/* Symmetric of iter_forward_extra_natural_word_end(). */ void _gtk_source_iter_backward_extra_natural_word_start (GtkTextIter *iter) { GtkTextIter prev_word_start = *iter; GtkTextIter prev_underscore_start = *iter; GtkTextIter *limit = NULL; gboolean found; if (gtk_text_iter_backward_visible_word_start (&prev_word_start)) { limit = &prev_word_start; } found = gtk_text_iter_backward_search (iter, "_", GTK_TEXT_SEARCH_VISIBLE_ONLY | GTK_TEXT_SEARCH_TEXT_ONLY, &prev_underscore_start, NULL, limit); if (found) { *iter = prev_underscore_start; } else { *iter = prev_word_start; } while (!gtk_text_iter_is_start (iter)) { GtkTextIter prev = *iter; gtk_text_iter_backward_visible_cursor_position (&prev); if (gtk_text_iter_get_char (&prev) == '_') { *iter = prev; } else if (gtk_text_iter_ends_word (iter)) { gtk_text_iter_backward_visible_word_start (iter); } else { break; } } }
static gboolean smie_gtk_source_buffer_backward_comment (gpointer data) { smie_gtk_source_buffer_context_t *context = data; GtkTextIter end_iter; gtk_text_iter_assign (&end_iter, &context->iter); while (!gtk_text_iter_is_start (&context->iter) && (gtk_source_buffer_iter_has_context_class (context->buffer, &context->iter, "comment") || g_unichar_isspace (gtk_text_iter_get_char (&context->iter))) && gtk_text_iter_backward_char (&context->iter)) ; return !gtk_text_iter_equal (&context->iter, &end_iter); }
static gboolean smie_gtk_source_buffer_is_start (gpointer data) { smie_gtk_source_buffer_context_t *context = data; return gtk_text_iter_is_start (&context->iter); }
static gssize xedit_document_input_stream_read (GInputStream *stream, void *buffer, gsize count, GCancellable *cancellable, GError **error) { XeditDocumentInputStream *dstream; GtkTextIter iter; gssize space_left, read, n; dstream = XEDIT_DOCUMENT_INPUT_STREAM (stream); if (count < 6) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NO_SPACE, "Not enougth space in destination"); return -1; } if (g_cancellable_set_error_if_cancelled (cancellable, error)) return -1; /* Initialize the mark to the first char in the text buffer */ if (!dstream->priv->is_initialized) { gtk_text_buffer_get_start_iter (dstream->priv->buffer, &iter); dstream->priv->pos = gtk_text_buffer_create_mark (dstream->priv->buffer, NULL, &iter, FALSE); dstream->priv->is_initialized = TRUE; } space_left = count; read = 0; do { n = read_line (dstream, buffer + read, space_left); read += n; space_left -= n; } while (space_left > 0 && n != 0 && dstream->priv->bytes_partial == 0); /* Make sure that non-empty files are always terminated with \n (see bug #95676). * Note that we strip the trailing \n when loading the file */ gtk_text_buffer_get_iter_at_mark (dstream->priv->buffer, &iter, dstream->priv->pos); if (gtk_text_iter_is_end (&iter) && !gtk_text_iter_is_start (&iter)) { gssize newline_size; newline_size = get_new_line_size (dstream); if (space_left >= newline_size && !dstream->priv->newline_added) { const gchar *newline; newline = get_new_line (dstream); memcpy (buffer + read, newline, newline_size); read += newline_size; dstream->priv->newline_added = TRUE; } } return read; }
/** * gail_text_util_get_text: * @textutil: A #GailTextUtil * @layout: A gpointer which is a PangoLayout, a GtkTreeView of NULL * @function: An enumeration specifying whether to return the text before, at, or * after the offset. * @boundary_type: The boundary type. * @offset: The offset of the text in the GailTextUtil * @start_offset: Address of location in which the start offset is returned * @end_offset: Address of location in which the end offset is returned * * This function gets the requested substring from the text in the GtkTextUtil. * The layout is used only for getting the text on a line. The value is NULL * for a GtkTextView which is not wrapped, is a GtkTextView for a GtkTextView * which is wrapped and is a PangoLayout otherwise. * * Returns: the substring requested **/ gchar* gail_text_util_get_text (GailTextUtil *textutil, gpointer layout, GailOffsetType function, AtkTextBoundary boundary_type, gint offset, gint *start_offset, gint *end_offset) { GtkTextIter start, end; gint line_number; GtkTextBuffer *buffer; g_return_val_if_fail (GAIL_IS_TEXT_UTIL (textutil), NULL); buffer = textutil->buffer; if (buffer == NULL) { *start_offset = 0; *end_offset = 0; return NULL; } if (!gtk_text_buffer_get_char_count (buffer)) { *start_offset = 0; *end_offset = 0; return g_strdup (""); } gtk_text_buffer_get_iter_at_offset (buffer, &start, offset); end = start; switch (function) { case GAIL_BEFORE_OFFSET: switch (boundary_type) { case ATK_TEXT_BOUNDARY_CHAR: gtk_text_iter_backward_char(&start); break; case ATK_TEXT_BOUNDARY_WORD_START: if (!gtk_text_iter_starts_word (&start)) gtk_text_iter_backward_word_start (&start); end = start; gtk_text_iter_backward_word_start(&start); break; case ATK_TEXT_BOUNDARY_WORD_END: if (gtk_text_iter_inside_word (&start) && !gtk_text_iter_starts_word (&start)) gtk_text_iter_backward_word_start (&start); while (!gtk_text_iter_ends_word (&start)) { if (!gtk_text_iter_backward_char (&start)) break; } end = start; gtk_text_iter_backward_word_start(&start); while (!gtk_text_iter_ends_word (&start)) { if (!gtk_text_iter_backward_char (&start)) break; } break; case ATK_TEXT_BOUNDARY_SENTENCE_START: if (!gtk_text_iter_starts_sentence (&start)) gtk_text_iter_backward_sentence_start (&start); end = start; gtk_text_iter_backward_sentence_start (&start); break; case ATK_TEXT_BOUNDARY_SENTENCE_END: if (gtk_text_iter_inside_sentence (&start) && !gtk_text_iter_starts_sentence (&start)) gtk_text_iter_backward_sentence_start (&start); while (!gtk_text_iter_ends_sentence (&start)) { if (!gtk_text_iter_backward_char (&start)) break; } end = start; gtk_text_iter_backward_sentence_start (&start); while (!gtk_text_iter_ends_sentence (&start)) { if (!gtk_text_iter_backward_char (&start)) break; } break; case ATK_TEXT_BOUNDARY_LINE_START: if (layout == NULL) { line_number = gtk_text_iter_get_line (&start); if (line_number == 0) { gtk_text_buffer_get_iter_at_offset (buffer, &start, 0); } else { gtk_text_iter_backward_line (&start); gtk_text_iter_forward_line (&start); } end = start; gtk_text_iter_backward_line (&start); } else if GTK_IS_TEXT_VIEW (layout) { GtkTextView *view = GTK_TEXT_VIEW (layout); gtk_text_view_backward_display_line_start (view, &start); end = start; gtk_text_view_backward_display_line (view, &start); } else if (PANGO_IS_LAYOUT (layout)) get_pango_text_offsets (PANGO_LAYOUT (layout), buffer, function, boundary_type, offset, start_offset, end_offset, &start, &end); break; case ATK_TEXT_BOUNDARY_LINE_END: if (layout == NULL) { line_number = gtk_text_iter_get_line (&start); if (line_number == 0) { gtk_text_buffer_get_iter_at_offset (buffer, &start, 0); end = start; } else { gtk_text_iter_backward_line (&start); end = start; while (!gtk_text_iter_ends_line (&start)) { if (!gtk_text_iter_backward_char (&start)) break; } gtk_text_iter_forward_to_line_end (&end); } } else if GTK_IS_TEXT_VIEW (layout) { GtkTextView *view = GTK_TEXT_VIEW (layout); gtk_text_view_backward_display_line_start (view, &start); if (!gtk_text_iter_is_start (&start)) { gtk_text_view_backward_display_line (view, &start); end = start; if (!gtk_text_iter_is_start (&start)) { gtk_text_view_backward_display_line (view, &start); gtk_text_view_forward_display_line_end (view, &start); } gtk_text_view_forward_display_line_end (view, &end); } else { end = start; } } else if (PANGO_IS_LAYOUT (layout)) get_pango_text_offsets (PANGO_LAYOUT (layout), buffer, function, boundary_type, offset, start_offset, end_offset, &start, &end); break; }
static gboolean editor_application_window_key_press_event (GtkWidget *widget, GdkEventKey *event) { EditorApplicationWindow *window = EDITOR_APPLICATION_WINDOW (widget); if (event->keyval == GDK_KEY_KP_Tab || event->keyval == GDK_KEY_Tab) { GtkTextMark *mark; smie_gtk_source_buffer_context_t context; gint indent, current_indent; GtkTextIter iter, start_iter, end_iter; memset (&context, 0, sizeof (smie_gtk_source_buffer_context_t)); context.buffer = window->buffer; mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (window->buffer)); gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (window->buffer), &iter, mark); gtk_text_iter_assign (&context.iter, &iter); indent = smie_indenter_calculate (window->indenter, &context); if (indent < 0) { g_printf ("indent: undetermined\n"); return TRUE; } else g_printf ("indent: %d\n", indent); /* Point START_ITER to the beginning of the line. */ gtk_text_iter_assign (&start_iter, &iter); while (!gtk_text_iter_is_start (&start_iter) && !gtk_text_iter_starts_line (&start_iter) && gtk_text_iter_backward_char (&start_iter)) ; /* Point END_ITER to the end of the indent and count the offset. */ gtk_text_iter_assign (&end_iter, &start_iter); current_indent = 0; while (!gtk_text_iter_is_end (&end_iter) && !gtk_text_iter_ends_line (&end_iter) && g_unichar_isspace (gtk_text_iter_get_char (&end_iter)) && gtk_text_iter_forward_char (&end_iter)) current_indent++; /* Replace the current indent if it doesn't match the computed one. */ if (indent < current_indent) { gtk_text_iter_forward_chars (&start_iter, indent); gtk_text_buffer_delete (GTK_TEXT_BUFFER (window->buffer), &start_iter, &end_iter); } else if (indent > current_indent) { gchar *text = g_new0 (gchar, indent - current_indent); memset (text, ' ', indent * sizeof (gchar)); gtk_text_buffer_insert (GTK_TEXT_BUFFER (window->buffer), &start_iter, text, indent - current_indent); g_free (text); } return TRUE; } return GTK_WIDGET_CLASS (editor_application_window_parent_class)->key_press_event (widget, event); }
gdouble get_selection_font_size(GtkTextBuffer *text_buffer, GtkTextView *text_view) { // Local variables GtkTextIter end_iter; gfloat font_size; // Used for calculating the font size of a character gint font_size_int; // Used for retrieving the size of a character in a text layer gfloat iter_size; // The size of the present character GtkTextAttributes *text_attributes; // Pointer to the attributes for a text layer character GtkTextIter first_iter; // Retrieve the selection start and end iters gtk_text_buffer_get_selection_bounds(GTK_TEXT_BUFFER(text_buffer), &first_iter, &end_iter); // If the start iter is not at the start of the text buffer, we move it back one character to get an accurate value if (FALSE == gtk_text_iter_is_start(&first_iter)) { gtk_text_iter_backward_char(&first_iter); } // Unless the start and end iters are at the same place, move the end iter back one so we // get an accurate value if (FALSE == gtk_text_iter_equal(&first_iter, &end_iter)) { gtk_text_iter_backward_char(&end_iter); } // Determine the font size at the selection start iter text_attributes = gtk_text_view_get_default_attributes(GTK_TEXT_VIEW(text_view)); gtk_text_iter_get_attributes(&first_iter, text_attributes); font_size_int = pango_font_description_get_size(text_attributes->font); font_size_int *= 10; font_size = roundf(((gfloat) font_size_int) / PANGO_SCALE); font_size /= 10; // Step through the text buffer character by character, // checking if the font size has changed while (FALSE == gtk_text_iter_equal(&first_iter, &end_iter)) { // Move forward one iter gtk_text_iter_forward_char(&first_iter); // Get the font size at this new iter text_attributes = gtk_text_view_get_default_attributes(GTK_TEXT_VIEW(text_view)); gtk_text_iter_get_attributes(&first_iter, text_attributes); font_size_int = pango_font_description_get_size(text_attributes->font); font_size_int *= 10; iter_size = roundf(((gfloat) font_size_int) / PANGO_SCALE); iter_size /= 10; // If the font size value is different to the original size, // then we short circuit the loop and return -1.0 if (font_size != iter_size) { return -1.0; } } // We've reached the end of the selection, and the selection font size // has been the same the whole way. We return that font size. return font_size; }