GtkTextLineSegment* gtk_text_line_segment_split (const GtkTextIter *iter) { GtkTextLineSegment *prev, *seg; GtkTextBTree *tree; GtkTextLine *line; int count; line = _gtk_text_iter_get_text_line (iter); tree = _gtk_text_iter_get_btree (iter); count = gtk_text_iter_get_line_index (iter); if (gtk_debug_flags & GTK_DEBUG_TEXT) _gtk_text_iter_check (iter); prev = NULL; seg = line->segments; while (seg != NULL) { if (seg->byte_count > count) { if (count == 0) { return prev; } else { g_assert (count != seg->byte_count); g_assert (seg->byte_count > 0); _gtk_text_btree_segments_changed (tree); seg = (*seg->type->splitFunc)(seg, count); if (prev == NULL) line->segments = seg; else prev->next = seg; return seg; } } else if ((seg->byte_count == 0) && (count == 0) && !seg->type->leftGravity) { return prev; } count -= seg->byte_count; prev = seg; seg = seg->next; } g_error ("split_segment reached end of line!"); return NULL; }
Gobby::OperationSave::OperationSave(Operations& operations, TextSessionView& view, const Glib::RefPtr<Gio::File>& file, const std::string& encoding, DocumentInfoStorage::EolStyle eol_style): Operation(operations), m_file(file), m_view(&view), m_start_time(std::time(NULL)), m_current_line_index(0), m_encoding(encoding), m_eol_style(eol_style), m_storage_key(view.get_info_storage_key()), m_iconv(encoding.c_str(), "UTF-8"), m_buffer_size(0), m_buffer_index(0) { const Folder& folder = get_folder_manager().get_text_folder(); folder.signal_document_removed().connect( sigc::mem_fun(*this, &OperationSave::on_document_removed)); // Load content so that the session can go on while saving GtkTextBuffer* buffer = GTK_TEXT_BUFFER(view.get_text_buffer()); GtkTextIter prev; GtkTextIter pos; GtkTextIter old_pos; gtk_text_buffer_get_start_iter(buffer, &prev); pos = prev; if(!gtk_text_iter_ends_line(&pos)) gtk_text_iter_forward_to_line_end(&pos); do { Line line; line.first = gtk_text_buffer_get_text(buffer, &prev, &pos, TRUE); line.second = gtk_text_iter_get_line_index(&pos); m_lines.push_back(line); //if(gtk_text_iter_is_end(&prev)) // break; old_pos = pos; gtk_text_iter_forward_line(&prev); gtk_text_iter_forward_to_line_end(&pos); } while(!gtk_text_iter_equal(&pos, &old_pos)); m_current_line = m_lines.begin(); }
/********** 'set_chord_position' function ************************************/ gint set_chord_position(GtkWidget *t_view, GtkTextBuffer *buffer) { GtkTextTag *tag; GtkTextMark *end_chord, *start_chord; GtkTextIter ch, chord_S, chord_E, match_end, match_start, start_of_line; GtkClipboard *clipboard; gint line_num_1, line_num_2, line_count_V, line_offset_1, line_offset_2; line_count_V = gtk_text_buffer_get_line_count(buffer); clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); gtk_text_buffer_get_start_iter(buffer, &start_of_line); if(gtk_text_iter_forward_search(&start_of_line, "[", 1, &match_start, &match_end, NULL)) { gtk_text_buffer_create_mark(buffer, "start_chord", &match_start, FALSE); start_chord = gtk_text_buffer_get_mark(buffer, "start_chord"); } else { return -1; } if(gtk_text_iter_forward_search(&start_of_line, "]", 1, &match_start, &match_end, NULL)) { gtk_text_buffer_create_mark(buffer, "end_chord", &match_end, FALSE); end_chord = gtk_text_buffer_get_mark(buffer, "end_chord"); } else { return -1; } // Initializes iters at mark. gtk_text_buffer_get_iter_at_mark(buffer, &chord_S, start_chord); gtk_text_buffer_get_iter_at_mark(buffer, &chord_E, end_chord); // Get line and line offset of iter. If we just obtain the offset // within buffer then chord_S will not format as desired. line_num_1 = gtk_text_iter_get_line(&chord_S); line_offset_1 = gtk_text_iter_get_line_index(&chord_S); line_num_2 = gtk_text_iter_get_line(&chord_E); line_offset_2 = gtk_text_iter_get_line_index(&chord_E); // This returns with error if end bracket does not have a // matching start bracket. if(line_offset_1 > line_offset_2) { return -1; } //g_print("Lineoffset of start:end bracket:\n%d\n%d\n", line_offset_1, line_offset_2); // If chord found is found more than two lines down // refresh global values of 'line_count_C' and 'line_num_C'. if(line_num_1 > (line_num_C + 1)) { line_num_C = line_num_1; line_count_C = line_count_V; } // Copy, cut, and add tags to the section between the marks. gtk_text_buffer_select_range(buffer, &chord_S, &chord_E); tag = gtk_text_buffer_create_tag(buffer, NULL, "background", "gold", "weight", "500", "foreground-gdk", "black3", NULL); gtk_text_buffer_apply_tag(buffer, tag, &chord_S, &chord_E); gtk_text_buffer_cut_clipboard(buffer, clipboard, TRUE); // This finds first chord of line. if(line_count_V == line_count_C) { gtk_text_buffer_get_iter_at_line(buffer, &start_of_line, line_num_1); gtk_text_buffer_insert(buffer, &start_of_line, "\n", -1); } // This finds the rest of the chord_S on the same line as the first. if(line_num_1 == (line_num_C + 1)) { line_num_1 = line_num_1 - 1; line_num_2 = line_num_2 - 1; } gtk_text_buffer_get_iter_at_line(buffer, &ch, line_num_1); // Insert 110 blank spaces so we can insert chord_S at higher offsets than 0. // GtkTextBuffer does not allow us to insert past a newline character // so we move it with spaces to allow us to place chord_S at offsets // past a newline character. if(gtk_text_iter_get_char(&ch) == '\n') { gtk_text_buffer_insert(buffer, &ch, " ", -1); } // Place iter at the same offset one line above. gtk_text_buffer_get_iter_at_line_index(buffer, &ch, line_num_1, line_offset_1); //g_print("Position after cut: %d\n", line_offset_1); gtk_text_buffer_paste_clipboard(buffer, clipboard, &ch, TRUE); gtk_text_buffer_get_iter_at_line_offset(buffer, &ch, line_num_1, line_offset_2); // Deletes the end bracket. gtk_text_buffer_backspace(buffer, &ch, FALSE, TRUE); gtk_text_buffer_get_iter_at_line_offset(buffer, &ch, line_num_1, line_offset_1 +1); // Deletes the start bracket. gtk_text_buffer_backspace(buffer, &ch, FALSE, TRUE); gtk_text_buffer_delete_mark_by_name(buffer, "start_chord"); gtk_text_buffer_delete_mark_by_name(buffer, "end_chord"); return 0; }
static gint console_key_handler (GtkWidget *cview, GdkEventKey *event, gpointer p) { guint keyval = event->keyval; guint upkey = gdk_keyval_to_upper(keyval); GtkTextIter ins, end; GtkTextBuffer *buf; GtkTextMark *mark; gint ctrl = 0; #ifdef MAC_NATIVE if (cmd_key(event)) { if (upkey == GDK_C || upkey == GDK_X) { /* allow regular copy/cut behavior */ return FALSE; } } #endif if (event->state & GDK_CONTROL_MASK) { if (keyval == GDK_Control_L || keyval == GDK_Control_R) { return FALSE; } else if (upkey == GDK_C || upkey == GDK_X) { /* allow regular copy/cut behavior */ return FALSE; } else { ctrl = 1; } } buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(cview)); /* first find out where the insertion point and end are */ mark = gtk_text_buffer_get_insert(buf); gtk_text_buffer_get_iter_at_mark(buf, &ins, mark); gtk_text_buffer_get_end_iter(buf, &end); /* if the insertion point is not on the last line, move it */ if (gtk_text_iter_get_line(&ins) != gtk_text_iter_get_line(&end)) { gtk_text_buffer_place_cursor(buf, &end); gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(cview), TRUE); gtk_text_buffer_get_end_iter(buf, &ins); } if (keyval == GDK_Home && (event->state & GDK_SHIFT_MASK)) { /* "select to start of line" */ GtkTextIter start = ins; gtk_text_iter_set_line_index(&start, 2); gtk_text_buffer_select_range(buf, &start, &ins); return TRUE; } if (IS_BACKKEY(keyval)) { /* if we're at the start of the input line, block backspacing */ if (gtk_text_iter_get_line_index(&ins) < 3) { return TRUE; } } else if (keyval == GDK_Home || (ctrl && upkey == GDK_A)) { /* go to start of typing area */ gtk_text_iter_set_line_index(&ins, 2); gtk_text_buffer_place_cursor(buf, &ins); return TRUE; } /* At this point 'ins' indicates the insertion point and 'end' points to the end of the current line of input, These may or may not be the same thing. */ if (keyval == GDK_Return) { /* execute the command, unless backslash-continuation is happening */ ExecState *state; gchar *thisline; int contd = 0, err = 0; state = g_object_get_data(G_OBJECT(cview), "ExecState"); thisline = console_get_current_line(buf, &ins); if (thisline != NULL) { g_strstrip(thisline); contd = command_continues(state->line, thisline, &err); g_free(thisline); } if (err) { gui_errmsg(err); } else if (contd) { console_insert_prompt(buf, &end, "\n> "); console_scroll_to_end(cview, buf, &end); } else { /* request execution of the completed command */ command_entered = 1; } event->keyval = GDK_End; return FALSE; } if (keyval == GDK_Up || keyval == GDK_Down) { /* up/down arrows: navigate the command history */ GtkTextIter start = ins; const char *histline; if (hpos == hlines && keyval == GDK_Up) { g_free(hist0); hist0 = console_get_current_line(buf, &ins); } histline = fetch_history_line(keyval); if (histline != NULL || keyval == GDK_Down) { gtk_text_iter_set_line_index(&start, 2); gtk_text_buffer_delete(buf, &start, &end); if (histline != NULL) { gtk_text_buffer_insert(buf, &start, histline, -1); } else if (hpos == hlines && hist0 != NULL) { gtk_text_buffer_insert(buf, &start, hist0, -1); } } return TRUE; } if (keyval == GDK_Tab) { /* tab completion for gretl commands, variable names */ return console_complete_word(buf, &ins); } return FALSE; }
void gtk_text_layout_draw (GtkTextLayout *layout, GtkWidget *widget, GdkDrawable *drawable, GdkGC *cursor_gc, /* Location of the drawable in layout coordinates */ gint x_offset, gint y_offset, /* Region of the layout to render */ gint x, gint y, gint width, gint height, /* widgets to expose */ GList **widgets) { GdkRectangle clip; gint current_y; GSList *cursor_list; GtkTextRenderState *render_state; GtkTextIter selection_start, selection_end; gboolean have_selection = FALSE; GSList *line_list; GSList *tmp_list; g_return_if_fail (GTK_IS_TEXT_LAYOUT (layout)); g_return_if_fail (layout->default_style != NULL); g_return_if_fail (layout->buffer != NULL); g_return_if_fail (drawable != NULL); g_return_if_fail (width >= 0); g_return_if_fail (height >= 0); if (width == 0 || height == 0) return; line_list = gtk_text_layout_get_lines (layout, y + y_offset, y + y_offset + height, ¤t_y); current_y -= y_offset; if (line_list == NULL) return; /* nothing on the screen */ clip.x = x; clip.y = y; clip.width = width; clip.height = height; render_state = gtk_text_render_state_new (widget, drawable, &clip); gdk_gc_set_clip_rectangle (render_state->fg_gc, &clip); gdk_gc_set_clip_rectangle (render_state->bg_gc, &clip); gtk_text_layout_wrap_loop_start (layout); if (gtk_text_buffer_get_selection_bounds (layout->buffer, &selection_start, &selection_end)) have_selection = TRUE; tmp_list = line_list; while (tmp_list != NULL) { GtkTextLineDisplay *line_display; gint selection_start_index = -1; gint selection_end_index = -1; gboolean have_strong; gboolean have_weak; GtkTextLine *line = tmp_list->data; line_display = gtk_text_layout_get_line_display (layout, line, FALSE); if (line_display->height > 0) { g_assert (line_display->layout != NULL); if (have_selection) { GtkTextIter line_start, line_end; gint byte_count; gtk_text_layout_get_iter_at_line (layout, &line_start, line, 0); line_end = line_start; if (!gtk_text_iter_ends_line (&line_end)) gtk_text_iter_forward_to_line_end (&line_end); byte_count = gtk_text_iter_get_line_index (&line_end); if (gtk_text_iter_compare (&selection_start, &line_end) <= 0 && gtk_text_iter_compare (&selection_end, &line_start) >= 0) { if (gtk_text_iter_compare (&selection_start, &line_start) >= 0) selection_start_index = gtk_text_iter_get_line_index (&selection_start); else selection_start_index = -1; if (gtk_text_iter_compare (&selection_end, &line_end) <= 0) selection_end_index = gtk_text_iter_get_line_index (&selection_end); else selection_end_index = MAX(byte_count, 1); } } render_para (drawable, render_state, line_display, - x_offset, current_y, selection_start_index, selection_end_index, widgets); /* We paint the cursors last, because they overlap another chunk and need to appear on top. */ have_strong = FALSE; have_weak = FALSE; cursor_list = line_display->cursors; while (cursor_list) { GtkTextCursorDisplay *cursor = cursor_list->data; if (cursor->is_strong) have_strong = TRUE; else have_weak = TRUE; cursor_list = cursor_list->next; } cursor_list = line_display->cursors; while (cursor_list) { GtkTextCursorDisplay *cursor = cursor_list->data; GtkTextDirection dir; GdkRectangle cursor_location; GdkGC *gc; dir = line_display->direction; if (have_strong && have_weak) { if (!cursor->is_strong) dir = (dir == GTK_TEXT_DIR_RTL) ? GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL; } cursor_location.x = line_display->x_offset + cursor->x - x_offset; cursor_location.y = current_y + line_display->top_margin + cursor->y; cursor_location.width = 0; cursor_location.height = cursor->height; gc = _gtk_get_insertion_cursor_gc (widget, cursor->is_strong); gdk_gc_set_clip_rectangle(gc, &clip); _gtk_draw_insertion_cursor (widget, drawable, gc, &cursor_location, dir, have_strong && have_weak); gdk_gc_set_clip_rectangle (gc, NULL); g_object_unref (gc); cursor_list = cursor_list->next; } } /* line_display->height > 0 */ current_y += line_display->height; gtk_text_layout_free_line_display (layout, line_display); render_state->last_appearance = NULL; render_state->last_bg_appearance = NULL; tmp_list = g_slist_next (tmp_list); } gtk_text_layout_wrap_loop_end (layout); gtk_text_render_state_destroy (render_state); g_slist_free (line_list); }