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); }
static void entry_changed_cb(GtkTextBuffer *buffer, void *data) { char *xmlstr, *str; GtkTextIter iter; int wrapped_lines; int lines; GdkRectangle oneline; int height; int pad_top, pad_inside, pad_bottom; GtkTextIter start, end; xmlnode *node; wrapped_lines = 1; gtk_text_buffer_get_start_iter(buffer, &iter); gtk_text_view_get_iter_location(GTK_TEXT_VIEW(console->entry), &iter, &oneline); while (gtk_text_view_forward_display_line(GTK_TEXT_VIEW(console->entry), &iter)) wrapped_lines++; lines = gtk_text_buffer_get_line_count(buffer); /* Show a maximum of 64 lines */ lines = MIN(lines, 6); wrapped_lines = MIN(wrapped_lines, 6); pad_top = gtk_text_view_get_pixels_above_lines(GTK_TEXT_VIEW(console->entry)); pad_bottom = gtk_text_view_get_pixels_below_lines(GTK_TEXT_VIEW(console->entry)); pad_inside = gtk_text_view_get_pixels_inside_wrap(GTK_TEXT_VIEW(console->entry)); height = (oneline.height + pad_top + pad_bottom) * lines; height += (oneline.height + pad_inside) * (wrapped_lines - lines); gtk_widget_set_size_request(console->sw, -1, height + 6); gtk_text_buffer_get_start_iter(buffer, &start); gtk_text_buffer_get_end_iter(buffer, &end); str = gtk_text_buffer_get_text(buffer, &start, &end, FALSE); if (!str) return; xmlstr = g_strdup_printf("<xml>%s</xml>", str); node = xmlnode_from_str(xmlstr, -1); if (node) { gtk_imhtml_clear_formatting(GTK_IMHTML(console->entry)); } else { gtk_imhtml_toggle_background(GTK_IMHTML(console->entry), "#ffcece"); } g_free(str); g_free(xmlstr); if (node) xmlnode_free(node); }
static VALUE textview_forward_display_line(VALUE self, VALUE iter) { return CBOOL2RVAL(gtk_text_view_forward_display_line(_SELF(self), RVAL2ITR(iter))); }
/* * 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 bg_gtk_textview_update(bg_gtk_textview_t * t, const char * text) { const char * next_tab; const char * pos; const char * end_pos; int line; int tab_pos; int line_width; int i; PangoTabArray * tab_array; GtkTextIter start_iter; GtkTextIter end_iter; GdkRectangle start_rect; GdkRectangle end_rect; pos = text; next_tab = strchr(pos, '\t'); /* No tabs here, just copy the text */ if(!next_tab) { gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(t->textview), GTK_WRAP_WORD); gtk_text_buffer_set_text(t->buffer, text, -1); } else /* This is the complicated version */ { line = 0; tab_pos = 0; while(1) { next_tab = strchr(pos, '\t'); end_pos = strchr(pos, '\n'); if(!end_pos) end_pos = pos + strlen(pos); if(next_tab > end_pos) next_tab = NULL; /* Insert everything before the tab and calculate width */ gtk_text_buffer_get_end_iter(t->buffer, &end_iter); if(!next_tab) { gtk_text_buffer_insert(t->buffer, &end_iter, pos, (int)(end_pos - pos)); } else { gtk_text_buffer_insert(t->buffer, &end_iter, pos, (int)(next_tab - pos)); } gtk_text_buffer_get_bounds(t->buffer, &start_iter, &end_iter); for(i = 0; i < line; i++) { gtk_text_view_forward_display_line(GTK_TEXT_VIEW(t->textview), &start_iter); } gtk_text_view_get_iter_location(GTK_TEXT_VIEW(t->textview), &start_iter, &start_rect); gtk_text_view_get_iter_location(GTK_TEXT_VIEW(t->textview), &end_iter, &end_rect); line_width = end_rect.x + end_rect.width; if(tab_pos < line_width) tab_pos = line_width; /* Insert everything after the tab */ if(next_tab) { gtk_text_buffer_get_end_iter(t->buffer, &end_iter); gtk_text_buffer_insert(t->buffer, &end_iter, next_tab, (int)(end_pos - next_tab)); } pos = end_pos; line++; if(*pos == '\0') break; else { while(*pos == '\n') { gtk_text_buffer_get_end_iter(t->buffer, &end_iter); gtk_text_buffer_insert(t->buffer, &end_iter, pos, 1); pos++; } } } /* Set the tab positions */ tab_array = pango_tab_array_new_with_positions(1, /* gint size, */ 1, /* gboolean positions_in_pixels, */ PANGO_TAB_LEFT, /* PangoTabAlign first_alignment, */ tab_pos+10 /* gint first_position, */ ); gtk_text_view_set_tabs(GTK_TEXT_VIEW(t->textview), tab_array); pango_tab_array_free(tab_array); } gtk_text_buffer_get_bounds(t->buffer, &start_iter, &end_iter); gtk_text_buffer_apply_tag(t->buffer, text_tag, &start_iter, &end_iter); };
/* Internal function: write a Latin-1 buffer with length to a stream. */ static void write_buffer_to_stream(strid_t str, gchar *buf, glui32 len) { switch(str->type) { case STREAM_TYPE_WINDOW: /* Each window type has a different way of printing to it */ switch(str->window->type) { /* Printing to these windows' streams does nothing */ case wintype_Blank: case wintype_Pair: case wintype_Graphics: str->write_count += len; break; /* Text grid/buffer windows */ case wintype_TextGrid: { gchar *utf8 = convert_latin1_to_utf8(buf, len); if(utf8 != NULL) { /* Deal with newlines */ int i; gchar *line = utf8; for(i=0; i<len; i++) { if(utf8[i] == '\n') { utf8[i] = '\0'; write_utf8_to_window_buffer(str->window, line); flush_window_buffer(str->window); /* Move cursor position forward to the next line */ gdk_threads_enter(); GtkTextIter cursor_pos; GtkTextView *textview = GTK_TEXT_VIEW(str->window->widget); GtkTextBuffer *buffer = gtk_text_view_get_buffer(textview); GtkTextMark *cursor_mark = gtk_text_buffer_get_mark(buffer, "cursor_position"); gtk_text_buffer_get_iter_at_mark( buffer, &cursor_pos, cursor_mark); gtk_text_view_forward_display_line(textview, &cursor_pos); gtk_text_view_backward_display_line_start(textview, &cursor_pos); gtk_text_buffer_move_mark(buffer, cursor_mark, &cursor_pos); gdk_threads_leave(); line = utf8 + (i < len-1 ? (i+1):(len-1)); } } /* No more newlines left. */ write_utf8_to_window_buffer(str->window, line); g_free(utf8); } str->write_count += len; } break; case wintype_TextBuffer: { gchar *utf8 = convert_latin1_to_utf8(buf, len); if(utf8 != NULL) { write_utf8_to_window_buffer(str->window, utf8); g_free(utf8); } } str->write_count += len; break; default: ILLEGAL_PARAM("Unknown window type: %u", str->window->type); } /* Now write the same buffer to the window's echo stream */ if(str->window->echo_stream != NULL) write_buffer_to_stream(str->window->echo_stream, buf, len); break; case STREAM_TYPE_MEMORY: if(str->unicode && str->ubuffer) { int foo = 0; while(str->mark < str->buflen && foo < len) str->ubuffer[str->mark++] = (unsigned char)buf[foo++]; } if(!str->unicode && str->buffer) { int copycount = MIN(len, str->buflen - str->mark); memmove(str->buffer + str->mark, buf, copycount); str->mark += copycount; } /* Move the EOF marker if we wrote past it */ if(str->mark > str->endmark) str->endmark = str->mark; str->write_count += len; break; case STREAM_TYPE_FILE: if(str->binary) { if(str->unicode) { gchar *writebuffer = convert_latin1_to_ucs4be_string(buf, len); ensure_file_operation(str, filemode_Write); fwrite(writebuffer, sizeof(gchar), len * 4, str->file_pointer); g_free(writebuffer); } else /* Regular file */ { ensure_file_operation(str, filemode_Write); fwrite(buf, sizeof(gchar), len, str->file_pointer); } } else /* Text mode is the same for Unicode and regular files */ { gchar *utf8 = convert_latin1_to_utf8(buf, len); if(utf8 != NULL) { ensure_file_operation(str, filemode_Write); g_fprintf(str->file_pointer, "%s", utf8); g_free(utf8); } } str->write_count += len; break; case STREAM_TYPE_RESOURCE: ILLEGAL(_("Writing to a resource stream is illegal.")); break; default: ILLEGAL_PARAM("Unknown stream type: %u", str->type); } }