void gglk_text_update_scrollmark(GglkText *tb) { GtkTextIter olditer, pastiter, iter; gtk_text_buffer_get_iter_at_mark(tb->buffer, &olditer, tb->scrollmark); gtk_text_buffer_get_end_iter(tb->buffer, &iter); gtk_text_buffer_move_mark(tb->buffer, tb->scrollmark, &iter); gtk_text_view_move_mark_onscreen(GTK_TEXT_VIEW(tb), tb->scrollmark); gtk_text_buffer_get_iter_at_mark(tb->buffer, &pastiter, tb->scrollmark); iter = pastiter; gtk_text_view_backward_display_line(GTK_TEXT_VIEW(tb), &iter); /* If we're trying to scroll down, but the backward_display_line made us fail, undo that. */ if(gtk_text_iter_compare(&pastiter, &olditer) >= 0 && gtk_text_iter_compare(&iter, &olditer) <= 0) { iter = pastiter; gtk_text_view_forward_display_line(GTK_TEXT_VIEW(tb), &iter); } gtk_text_buffer_move_mark(tb->buffer, tb->scrollmark, &iter); }
void hybrid_chat_textview_notify(GtkWidget *textview, const gchar *text, gint type) { GtkTextBuffer *recv_tb; GtkTextIter end_iter; GtkTextIter stop_iter; GtkTextIter start_iter; GtkTextMark *mark; recv_tb = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview)); gtk_text_buffer_get_end_iter(recv_tb, &end_iter); gtk_text_view_backward_display_line(GTK_TEXT_VIEW(textview), &end_iter); gtk_text_buffer_get_end_iter(recv_tb, &stop_iter); gtk_text_buffer_get_start_iter(recv_tb, &start_iter); /* first line */ if (gtk_text_iter_equal(&end_iter, &stop_iter)) { gtk_text_buffer_delete(recv_tb, &start_iter, &stop_iter); } else { gtk_text_buffer_delete(recv_tb, &end_iter, &stop_iter); if (!gtk_text_iter_equal(&start_iter, &end_iter)) { gtk_text_buffer_insert(recv_tb, &end_iter, "\n", -1); } } gtk_text_buffer_get_end_iter(recv_tb, &end_iter); if (type == MSG_NOTIFICATION_INPUT) { gtk_text_buffer_insert_with_tags_by_name(recv_tb, &end_iter, text, strlen(text), "grey", "small", "wrap", NULL); } mark = gtk_text_buffer_get_mark(recv_tb, "scroll"); gtk_text_buffer_move_mark(recv_tb, mark, &end_iter); gtk_text_view_scroll_mark_onscreen(GTK_TEXT_VIEW(textview), mark); }
static VALUE textview_backward_display_line(VALUE self, VALUE iter) { return CBOOL2RVAL(gtk_text_view_backward_display_line(_SELF(self), RVAL2ITR(iter))); }
/** * 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; }
/* * Links can be activated by pressing Enter. */ static gboolean key_press_event (GtkWidget *text_view, GdkEventKey *event, GdauiCloud *cloud) { GtkTextIter iter; GtkTextBuffer *buffer; switch (event->keyval) { case GDK_KEY_Return: case GDK_KEY_space: case GDK_KEY_KP_Enter: buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view)); gtk_text_buffer_get_iter_at_mark (buffer, &iter, gtk_text_buffer_get_insert (buffer)); follow_if_link (text_view, &iter, cloud); return TRUE; case GDK_KEY_Up: case GDK_KEY_Down: case GDK_KEY_Left: case GDK_KEY_Right: if ((cloud->priv->selection_mode == GTK_SELECTION_SINGLE) || (cloud->priv->selection_mode == GTK_SELECTION_BROWSE)) { GtkTextIter iter; if (cloud->priv->selected_tags) { GtkTextMark *mark; mark = gtk_text_buffer_get_insert (cloud->priv->tbuffer); gtk_text_buffer_get_iter_at_mark (cloud->priv->tbuffer, &iter, mark); } else if ((event->keyval == GDK_KEY_Right) || (event->keyval == GDK_KEY_Down)) gtk_text_buffer_get_start_iter (cloud->priv->tbuffer, &iter); else gtk_text_buffer_get_end_iter (cloud->priv->tbuffer, &iter); gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (cloud->priv->tview), TRUE); while (1) { /* loop to move the cursor enough positions to change the selected item */ gboolean done = FALSE; GtkMovementStep mvt_type; gint mvt_amount; switch (event->keyval) { case GDK_KEY_Up: done = ! gtk_text_view_backward_display_line ((GtkTextView*)cloud->priv->tview, &iter); mvt_type = GTK_MOVEMENT_DISPLAY_LINES; mvt_amount = -1; break; case GDK_KEY_Down: done = ! gtk_text_view_forward_display_line ((GtkTextView*)cloud->priv->tview, &iter); mvt_type = GTK_MOVEMENT_DISPLAY_LINES; mvt_amount = 1; break; case GDK_KEY_Left: done = ! gtk_text_iter_backward_char (&iter); mvt_type = GTK_MOVEMENT_VISUAL_POSITIONS; mvt_amount = -1; break; default: case GDK_KEY_Right: done = ! gtk_text_iter_forward_char (&iter); mvt_type = GTK_MOVEMENT_VISUAL_POSITIONS; mvt_amount = 1; break; } if (done) break; /* end of treatment as no movement possible */ g_signal_emit_by_name (cloud->priv->tview, "move-cursor", mvt_type, mvt_amount, FALSE); GtkTextMark *mark; mark = gtk_text_buffer_get_insert (cloud->priv->tbuffer); gtk_text_buffer_get_iter_at_mark (cloud->priv->tbuffer, &iter, mark); GSList *tags, *tagp; done = FALSE; tags = gtk_text_iter_get_tags (&iter); for (tagp = tags; tagp; tagp = tagp->next) { GtkTextTag *tag = (GtkTextTag*) tagp->data; gint row; row = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (tag), "row")) - 1; if (row >= 0) { if ((cloud->priv->selected_tags && (tag != cloud->priv->selected_tags->data)) || !cloud->priv->selected_tags) { row_clicked (cloud, row, tag); done = TRUE; break; } } } if (tags) g_slist_free (tags); if (done) { GtkTextMark *mark; mark = gtk_text_buffer_get_insert (cloud->priv->tbuffer); gtk_text_view_scroll_mark_onscreen ((GtkTextView*)cloud->priv->tview, mark); break; } } gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (cloud->priv->tview), FALSE); return TRUE; } default: break; } return FALSE; }
void hybrid_chat_textview_append(GtkWidget *textview, HybridAccount *account, HybridBuddy *buddy, const gchar *message, time_t msg_time) { GtkTextBuffer *recv_tb; GtkTextIter end_iter; GtkTextIter stop_iter; GtkTextIter start_iter; GtkTextMark *mark; gchar *names; const gchar *color; const gchar *name; struct tm *tm_time; gchar time[128]; g_return_if_fail(textview != NULL); g_return_if_fail(message != NULL); tm_time = localtime(&msg_time); strftime(time, sizeof(time) - 1, _("%H:%M:%S"), tm_time); recv_tb = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview)); gtk_text_buffer_get_end_iter(recv_tb, &end_iter); gtk_text_view_backward_display_line(GTK_TEXT_VIEW(textview), &end_iter); gtk_text_buffer_get_end_iter(recv_tb, &stop_iter); gtk_text_buffer_get_start_iter(recv_tb, &start_iter); /* first line */ if (gtk_text_iter_equal(&end_iter, &stop_iter)) { gtk_text_buffer_delete(recv_tb, &start_iter, &stop_iter); } else { gtk_text_buffer_delete(recv_tb, &end_iter, &stop_iter); if (!gtk_text_iter_equal(&start_iter, &end_iter)) { gtk_text_buffer_insert(recv_tb, &end_iter, "\n", -1); } } gtk_text_buffer_get_end_iter(recv_tb, &end_iter); if (!buddy) { color = "blue"; name = account->nickname && *account->nickname ? account->nickname : account->username; } else { color = "green"; name = buddy->name && *buddy->name ? buddy->name : buddy->id; } names = g_strdup_printf(" (%s) ", time); gtk_text_buffer_insert_with_tags_by_name(recv_tb, &end_iter, names, strlen(names), color, "wrap", NULL); g_free(names); gtk_text_buffer_insert_with_tags_by_name(recv_tb, &end_iter, name, strlen(name), color, "bold", "wrap", NULL); names = _(" said:"); gtk_text_buffer_insert_with_tags_by_name(recv_tb, &end_iter, names, strlen(names), color, "wrap", NULL); gtk_text_buffer_insert(recv_tb, &end_iter, "\n", -1); gtk_text_buffer_insert_with_tags_by_name(recv_tb, &end_iter, message, strlen(message), "lm10", "wrap", NULL); gtk_text_buffer_insert(recv_tb, &end_iter, "\n", -1); gtk_text_iter_set_line_offset(&end_iter, 0); mark = gtk_text_buffer_get_mark(recv_tb, "scroll"); gtk_text_buffer_move_mark(recv_tb, mark, &end_iter); gtk_text_view_scroll_mark_onscreen(GTK_TEXT_VIEW(textview), mark); }