diff options
Diffstat (limited to 'widgets/table/e-cell-text.c')
-rw-r--r-- | widgets/table/e-cell-text.c | 1312 |
1 files changed, 443 insertions, 869 deletions
diff --git a/widgets/table/e-cell-text.c b/widgets/table/e-cell-text.c index edbea905e7..c72e5248b4 100644 --- a/widgets/table/e-cell-text.c +++ b/widgets/table/e-cell-text.c @@ -5,7 +5,7 @@ * * Authors: * Miguel de Icaza <miguel@ximian.com> - * Chris Lahey <clahey@ximian.com> + * Chris Lahey <clahey@ximian.com> * * A lot of code taken from: * @@ -40,15 +40,10 @@ #include <math.h> #include <string.h> #include <gdk/gdkx.h> /* for BlackPixel */ -#include <gtk/gtkenums.h> -#include <gtk/gtkentry.h> -#include <gtk/gtkwindow.h> -#include <gtk/gtkinvisible.h> -#include <gtk/gtksignal.h> #include <gdk/gdkkeysyms.h> -#include <gtk/gtkwidget.h> -#include <libgnomeui/gnome-canvas.h> -#include <libgnomeui/gnome-canvas-rect-ellipse.h> +#include <gtk/gtk.h> +#include <libgnomecanvas/gnome-canvas.h> +#include <libgnomecanvas/gnome-canvas-rect-ellipse.h> #include "e-cell-text.h" #include "gal/util/e-util.h" #include "gal/widgets/e-canvas.h" @@ -58,9 +53,11 @@ #include "gal/util/e-text-event-processor.h" #include "gal/e-text/e-text.h" #include "gal/util/e-text-event-processor-emacs-like.h" +#include "gal/util/e-i18n.h" #include "e-table-tooltip.h" #define d(x) +#define DO_SELECTION 1 #if d(!)0 #define e_table_item_leave_edit_(x) (e_table_item_leave_edit((x)), g_print ("%s: e_table_item_leave_edit\n", __FUNCTION__)) @@ -68,7 +65,7 @@ #define e_table_item_leave_edit_(x) (e_table_item_leave_edit((x))) #endif -#define ECT_CLASS(c) (E_CELL_TEXT_CLASS(GTK_OBJECT((c))->klass)) +#define ECT_CLASS(c) (E_CELL_TEXT_CLASS(GTK_OBJECT_GET_CLASS ((c)))) /* This defines a line of text */ struct line { @@ -132,19 +129,16 @@ typedef struct { } ECellTextView; -typedef struct _CurrentCell{ +struct _CellEdit { + ECellTextView *text_view; - int width; - char *text; - int model_col, view_col, row; - ECellTextLineBreaks *breaks; - EFontStyle style; -} CurrentCell; -#define CURRENT_CELL(x) ((CurrentCell *)(x)) + int model_col, view_col, row; + int cell_width; -struct _CellEdit { - CurrentCell cell; + PangoLayout *layout; + + char *text; char *old_text; @@ -193,33 +187,11 @@ static void e_cell_text_view_command (ETextEventProcessor *tep, ETextEventProces static void e_cell_text_view_get_selection (CellEdit *edit, GdkAtom selection, guint32 time); static void e_cell_text_view_supply_selection (CellEdit *edit, guint time, GdkAtom selection, char *data, gint length); -static GtkWidget *e_cell_text_view_get_invisible (CellEdit *edit); -static void _selection_clear_event (GtkInvisible *invisible, - GdkEventSelection *event, - CellEdit *edit); -static void _selection_get (GtkInvisible *invisible, - GtkSelectionData *selection_data, - guint info, - guint time_stamp, - CellEdit *edit); -static void _selection_received (GtkInvisible *invisible, - GtkSelectionData *selection_data, - guint time, - CellEdit *edit); -static int number_of_lines (char *text); -static void split_into_lines (CurrentCell *cell); -static void unref_lines (CurrentCell *cell); -static void calc_line_widths (CurrentCell *cell); -static int get_line_ypos (CurrentCell *cell, struct line *line); -static int get_line_xpos (CurrentCell *cell, struct line *line); static void _get_tep (CellEdit *edit); -static gint _get_position_from_xy (CurrentCell *cell, gint x, gint y); -static void _get_xy_from_position (CurrentCell *cell, gint position, gint *xp, gint *yp); +static gint get_position_from_xy (CellEdit *edit, gint x, gint y); static gboolean _blink_scroll_timeout (gpointer data); -static void build_current_cell (CurrentCell *cell, ECellTextView *text_view, int model_col, int view_col, int row); -static void unbuild_current_cell (CurrentCell *cell); static void calc_ellipsis (ECellTextView *text_view); static void ect_free_color (gchar *color_spec, GdkColor *color, GdkColormap *colormap); static GdkColor* e_cell_text_get_color (ECellTextView *cell_view, gchar *color_spec); @@ -280,6 +252,14 @@ ect_queue_redraw (ECellTextView *text_view, int view_col, int view_row) view_col, view_row, view_col, view_row); } +static void +invisible_finalize (gpointer data, + GObject *invisible) +{ + CellEdit *edit = data; + edit->invisible = NULL; +} + /* * Shuts down the editing process */ @@ -289,19 +269,19 @@ ect_stop_editing (ECellTextView *text_view, gboolean commit) CellEdit *edit = text_view->edit; int row, view_col, model_col; char *old_text, *text; - CurrentCell *cell = (CurrentCell *) text_view->edit; if (!edit) return; - row = cell->row; - view_col = cell->view_col; - model_col = cell->model_col; + row = edit->row; + view_col = edit->view_col; + model_col = edit->model_col; old_text = edit->old_text; - text = cell->text; - if (edit->invisible) - gtk_widget_unref (edit->invisible); + text = edit->text; + if (edit->invisible) { + g_object_weak_unref (G_OBJECT (edit->invisible), invisible_finalize, edit); + } if (edit->tep) gtk_object_unref (GTK_OBJECT(edit->tep)); if (edit->primary_selection) @@ -322,6 +302,9 @@ ect_stop_editing (ECellTextView *text_view, gboolean commit) edit->timer = NULL; } + if (edit->layout) + g_object_unref (edit->layout); + g_free (edit); text_view->edit = NULL; @@ -402,7 +385,8 @@ ect_realize (ECellView *ecell_view) text_view->font = e_font_from_gdk_name (ect->font_name); } if (!text_view->font){ - text_view->font = e_font_from_gdk_font (GTK_WIDGET (text_view->canvas)->style->font); + gdk_font_ref (gtk_style_get_font (GTK_WIDGET (text_view->canvas)->style)); + text_view->font = e_font_from_gdk_font (gtk_style_get_font (GTK_WIDGET (text_view->canvas)->style)); } calc_ellipsis (text_view); @@ -452,29 +436,133 @@ ect_unrealize (ECellView *ecv) static void ect_free_color (gchar *color_spec, GdkColor *color, GdkColormap *colormap) { - g_free (color_spec); /* This frees the color. Note we don't free it if it is the special value. */ if (color != (GdkColor*) 1) { - gdk_colors_free (colormap, &color->pixel, 1, 0); + gulong pix = color->pixel; + + gdk_colors_free (colormap, &pix, 1, 0); /* This frees the memory for the GdkColor. */ gdk_color_free (color); } } -static void -set_style(ECellView *ecell_view, CurrentCell *cell, int row) +static PangoLayout * +build_layout (ECellTextView *text_view, int row, const char *text) { - EFontStyle style = E_FONT_PLAIN; + ECellView *ecell_view = (ECellView *) text_view; ECellText *ect = E_CELL_TEXT (ecell_view->ecell); + PangoLayout *layout; + gboolean bold, strikeout; + + layout = gtk_widget_create_pango_layout (GTK_WIDGET (((GnomeCanvasItem *)ecell_view->e_table_item_view)->canvas), text); + + bold = ect->bold_column >= 0 && + row >= 0 && + e_table_model_value_at(ecell_view->e_table_model, ect->bold_column, row); + strikeout = ect->strikeout_column >= 0 && e_table_model_value_at(ecell_view->e_table_model, ect->strikeout_column, row); + + if (bold || strikeout) { + PangoAttrList *attrs; + int length = strlen (text); + attrs = pango_attr_list_new (); + if (bold) { + PangoAttribute *attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD); + attr->start_index = 0; + attr->end_index = length; + + pango_attr_list_insert_before (attrs, attr); + } + if (strikeout) { + PangoAttribute *attr = pango_attr_strikethrough_new (TRUE); + attr->start_index = 0; + attr->end_index = length; - if (ect->bold_column >= 0 && e_table_model_value_at(ecell_view->e_table_model, ect->bold_column, row)) - style = E_FONT_BOLD; + pango_attr_list_insert_before (attrs, attr); + } + pango_layout_set_attributes (layout, attrs); + pango_attr_list_unref (attrs); + } - cell->style = style; + return layout; +} + +static PangoLayout * +generate_layout (ECellTextView *text_view, int model_col, int view_col, int row) +{ + ECellView *ecell_view = (ECellView *) text_view; + ECellText *ect = E_CELL_TEXT (ecell_view->ecell); + PangoLayout *layout; + CellEdit *edit = text_view->edit; + + if (edit && edit->model_col == model_col && edit->row == row) { + g_object_ref (edit->layout); + return edit->layout; + } + + if (row >= 0) { + char *temp = e_cell_text_get_text(ect, ecell_view->e_table_model, model_col, row); + layout = build_layout (text_view, row, temp); + e_cell_text_free_text(ect, temp); + } else + layout = build_layout (text_view, row, "Mumbo Jumbo"); + + return layout; +} + +static void +draw_pango_rectangle (GdkDrawable *drawable, GdkGC *gc, int x1, int y1, PangoRectangle rect) +{ + int width = rect.width / PANGO_SCALE; + int height = rect.height / PANGO_SCALE; + if (width <= 0) + width = 1; + if (height <= 0) + height = 1; + gdk_draw_rectangle (drawable, gc, TRUE, + x1 + rect.x / PANGO_SCALE, y1 + rect.y / PANGO_SCALE, width, height); +} + +static gboolean +show_pango_rectangle (CellEdit *edit, PangoRectangle rect) +{ + int x1 = rect.x / PANGO_SCALE; + int x2 = (rect.x + rect.width) / PANGO_SCALE; +#if 0 + int y1 = rect.y / PANGO_SCALE; + int y2 = (rect.y + rect.height) / PANGO_SCALE; +#endif + + int new_xofs_edit = edit->xofs_edit; + int new_yofs_edit = edit->yofs_edit; + + if (x1 < new_xofs_edit) + new_xofs_edit = x1; + if (2 + x2 - edit->cell_width > new_xofs_edit) + new_xofs_edit = 2 + x2 - edit->cell_width; + if (new_xofs_edit < 0) + new_xofs_edit = 0; + +#if 0 + if (y1 < new_yofs_edit) + new_yofs_edit = y1; + if (2 + y2 - edit->cell_height > new_yofs_edit) + new_yofs_edit = 2 + y2 - edit->cell_height; + if (new_yofs_edit < 0) + new_yofs_edit = 0; +#endif + + if (new_xofs_edit != edit->xofs_edit || + new_yofs_edit != edit->yofs_edit) { + edit->xofs_edit = new_xofs_edit; + edit->yofs_edit = new_yofs_edit; + return TRUE; + } + + return FALSE; } /* @@ -485,70 +573,39 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable, int model_col, int view_col, int row, ECellFlags flags, int x1, int y1, int x2, int y2) { - /* New ECellText */ - ECellText *ect = E_CELL_TEXT (ecell_view->ecell); + PangoLayout *layout; ECellTextView *text_view = (ECellTextView *) ecell_view; - GtkWidget *canvas = GTK_WIDGET (text_view->canvas); - GdkRectangle rect, *clip_rect; - struct line *lines; - int i; - int xpos, ypos; - int start_char, end_char; - int sel_start, sel_end; - GdkRectangle sel_rect; - GdkGC *fg_gc; - EFont *font = text_view->font; - const int height = e_font_height (text_view->font); + ECellText *ect = E_CELL_TEXT (ecell_view->ecell); CellEdit *edit = text_view->edit; - gboolean edit_display = FALSE; - ECellTextLineBreaks *linebreaks; - GdkColor *foreground, *cell_foreground, *cursor_color; - gchar *color_spec; gboolean selected; - EFontStyle style = E_FONT_PLAIN; + GdkColor *foreground, *cursor_color; + GtkWidget *canvas = GTK_WIDGET (text_view->canvas); + GdkRectangle clip_rect; + int x_origin, y_origin; selected = flags & E_CELL_SELECTED; - if (edit){ - if ((edit->cell.view_col == view_col) && (edit->cell.row == row)) { - edit_display = TRUE; - fg_gc = canvas->style->fg_gc[edit->has_selection ? GTK_STATE_SELECTED : GTK_STATE_ACTIVE]; - } else - fg_gc = canvas->style->fg_gc[GTK_STATE_ACTIVE]; - } else { - fg_gc = canvas->style->fg_gc[GTK_STATE_ACTIVE]; - } - - /* - * Be a nice citizen: clip to the region we are supposed to draw on - */ - rect.x = x1; - rect.y = y1; - rect.width = x2 - x1; - rect.height = y2 - y1; - - gdk_gc_set_clip_rectangle (text_view->gc, &rect); - gdk_gc_set_clip_rectangle (fg_gc, &rect); - clip_rect = ▭ - - if (selected){ + if (selected) { if (flags & E_CELL_FOCUSED) - foreground = &canvas->style->text [GTK_STATE_SELECTED]; + foreground = &canvas->style->fg [GTK_STATE_SELECTED]; else - foreground = &canvas->style->text [GTK_STATE_ACTIVE]; + foreground = &canvas->style->fg [GTK_STATE_ACTIVE]; + cursor_color = foreground; } else { foreground = &canvas->style->text [GTK_STATE_NORMAL]; - } - - cursor_color = foreground; - - if (ect->color_column != -1 && ! selected) { - color_spec = e_table_model_value_at (ecell_view->e_table_model, - ect->color_column, row); - cell_foreground = e_cell_text_get_color (text_view, - color_spec); - if (cell_foreground) - foreground = cell_foreground; + cursor_color = foreground; + + if (ect->color_column != -1) { + char *color_spec; + GdkColor *cell_foreground; + + color_spec = e_table_model_value_at (ecell_view->e_table_model, + ect->color_column, row); + cell_foreground = e_cell_text_get_color (text_view, + color_spec); + if (cell_foreground) + foreground = cell_foreground; + } } gdk_gc_set_foreground (text_view->gc, foreground); @@ -558,179 +615,98 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable, x2 -= 4; y2 -= 1; - rect.x = x1; - rect.y = y1; - rect.width = x2 - x1; - rect.height = y2 - y1; - - gdk_gc_set_clip_rectangle (text_view->gc, &rect); - gdk_gc_set_clip_rectangle (fg_gc, &rect); - clip_rect = ▭ + x_origin = x1 + ect->x + text_view->xofs - (edit ? edit->xofs_edit : 0); + y_origin = y1 + ect->y + text_view->yofs - (edit ? edit->yofs_edit : 0); + + clip_rect.x = x1; + clip_rect.y = y1; + clip_rect.width = x2 - x1; + clip_rect.height = y2 - y1; + + gdk_gc_set_clip_rectangle (text_view->gc, &clip_rect); + /* clip_rect = ▭*/ + + layout = generate_layout (text_view, model_col, view_col, row); + + gdk_draw_layout (drawable, text_view->gc, + x_origin, y_origin, + layout); + + if (edit && edit->view_col == view_col && edit->row == row) { + if (edit->selection_start != edit->selection_end) { + int start_index, end_index; + PangoLayoutLine *line; + gint *ranges; + gint n_ranges, i; + PangoRectangle logical_rect; + GdkRegion *clip_region = gdk_region_new (); + GdkRegion *rect_region; + GdkGC *selection_gc; + GdkGC *text_gc; + + start_index = MIN (edit->selection_start, edit->selection_end); + end_index = edit->selection_start ^ edit->selection_end ^ start_index; + + if (edit->has_selection) { + selection_gc = canvas->style->base_gc [GTK_STATE_SELECTED]; + text_gc = canvas->style->text_gc[GTK_STATE_SELECTED]; + } else { + selection_gc = canvas->style->base_gc [GTK_STATE_ACTIVE]; + text_gc = canvas->style->text_gc[GTK_STATE_ACTIVE]; + } - if (edit_display){ - CellEdit *edit = text_view->edit; - CurrentCell *cell = CURRENT_CELL(edit); + gdk_gc_set_clip_rectangle (selection_gc, &clip_rect); - set_style(ecell_view, cell, row); + line = pango_layout_get_lines (layout)->data; - style = cell->style; + pango_layout_line_get_x_ranges (line, start_index, end_index, &ranges, &n_ranges); - cell->width = x2 - x1; - - split_into_lines (cell); + pango_layout_get_extents (layout, NULL, &logical_rect); - linebreaks = cell->breaks; - - lines = linebreaks->lines; - ypos = get_line_ypos (cell, lines); - ypos += e_font_ascent (text_view->font); - ypos -= edit->yofs_edit; + for (i=0; i < n_ranges; i++) { + GdkRectangle sel_rect; - for (i = 0; i < linebreaks->num_lines; i++) { - xpos = get_line_xpos (cell, lines); - xpos -= edit->xofs_edit; + sel_rect.x = x_origin + ranges[2*i] / PANGO_SCALE; + sel_rect.y = y_origin; + sel_rect.width = (ranges[2*i + 1] - ranges[2*i]) / PANGO_SCALE; + sel_rect.height = logical_rect.height / PANGO_SCALE; - /* start_char, end_char, sel_start and sel_end are IN BYTES */ + gdk_draw_rectangle (drawable, selection_gc, TRUE, + sel_rect.x, sel_rect.y, sel_rect.width, sel_rect.height); - start_char = lines->text - cell->text; - end_char = start_char + lines->length; - - sel_start = edit->selection_start; - sel_end = edit->selection_end; - - if (sel_start > sel_end){ - sel_start ^= sel_end; - sel_end ^= sel_start; - sel_start ^= sel_end; - } - if (sel_start < start_char) - sel_start = start_char; - if (sel_end > end_char) - sel_end = end_char; - - if (sel_start < sel_end){ - sel_rect.x = xpos + x1 + e_font_utf8_text_width (font, style, lines->text, sel_start - start_char); - sel_rect.y = ypos + y1 - e_font_ascent (font); - sel_rect.width = e_font_utf8_text_width (font, style, - lines->text + sel_start - start_char, - sel_end - sel_start); - sel_rect.height = height; - gtk_paint_flat_box (canvas->style, - drawable, - - edit->has_selection ? GTK_STATE_SELECTED : GTK_STATE_ACTIVE, - GTK_SHADOW_NONE, - clip_rect, - canvas, - "text", - sel_rect.x, - sel_rect.y, - sel_rect.width, - sel_rect.height); - - e_font_draw_utf8_text (drawable, font, style, text_view->gc, xpos + x1, ypos + y1, - lines->text, - sel_start - start_char); - e_font_draw_utf8_text (drawable, font, style, fg_gc, - xpos + x1 + e_font_utf8_text_width (font, style, lines->text, sel_start - start_char), - ypos + y1, - lines->text + sel_start - start_char, - sel_end - sel_start); - e_font_draw_utf8_text (drawable, font, style, text_view->gc, - xpos + x1 + e_font_utf8_text_width (font, style, lines->text, sel_end - start_char), - ypos + y1, - lines->text + sel_end - start_char, - end_char - sel_end); - } else { - e_font_draw_utf8_text (drawable, font, style, text_view->gc, - xpos + x1, ypos + y1, - lines->text, - lines->length); - } - if (edit->selection_start == edit->selection_end && - edit->selection_start >= start_char && - edit->selection_start <= end_char && - edit->show_cursor) { - gdk_gc_set_foreground (text_view->gc, cursor_color); - gdk_draw_rectangle (drawable, - text_view->gc, - TRUE, - xpos + x1 + e_font_utf8_text_width (font, style, lines->text, sel_start - start_char), - ypos + y1 - e_font_ascent (font), - 1, - height); + gdk_region_union_with_rect (clip_region, &sel_rect); } - if (ect->strikeout_column >= 0 && e_table_model_value_at(ecell_view->e_table_model, ect->strikeout_column, row)) { - gdk_draw_rectangle (drawable, - text_view->gc, - TRUE, - x1, ypos + y1 - (e_font_ascent (font) / 2), - x2 - x1, - 1); - } - ypos += height; - lines ++; - } - unref_lines (cell); - } else { - - ECellTextLineBreaks *linebreaks; - CurrentCell cell; - build_current_cell (&cell, text_view, model_col, view_col, row); - - set_style(ecell_view, &cell, row); - style = cell.style; + rect_region = gdk_region_rectangle (&clip_rect); + gdk_region_intersect (clip_region, rect_region); + gdk_region_destroy (rect_region); - cell.width = x2 - x1; - - split_into_lines (&cell); - - linebreaks = cell.breaks; - lines = linebreaks->lines; - ypos = get_line_ypos (&cell, lines); - ypos += e_font_ascent (text_view->font); - - - for (i = 0; i < linebreaks->num_lines; i++) { - xpos = get_line_xpos (&cell, lines); - if (ect->use_ellipsis && lines->ellipsis_length < lines->length) { - e_font_draw_utf8_text (drawable, font, style, text_view->gc, - xpos + x1, ypos + y1, - lines->text, - lines->ellipsis_length); - e_font_draw_utf8_text (drawable, font, style, text_view->gc, - xpos + x1 + lines->width - text_view->ellipsis_width[style], - ypos + y1, - ect->ellipsis ? ect->ellipsis : "...", - ect->ellipsis ? strlen (ect->ellipsis) : 3); - } else { - e_font_draw_utf8_text (drawable, font, style, text_view->gc, - xpos + x1, - ypos + y1, - lines->text, - lines->length); - } - if (ect->strikeout_column >= 0 && e_table_model_value_at(ecell_view->e_table_model, ect->strikeout_column, row)) { - gdk_draw_rectangle (drawable, - text_view->gc, - TRUE, - x1, ypos + y1 - (e_font_ascent (font) / 2), - x2 - x1, - 1); + gdk_gc_set_clip_region (text_gc, clip_region); + gdk_draw_layout (drawable, text_gc, + x_origin, y_origin, + layout); + gdk_gc_set_clip_region (text_gc, NULL); + gdk_gc_set_clip_region (selection_gc, NULL); + + gdk_region_destroy (clip_region); + g_free (ranges); + } else { + if (edit->show_cursor) { + PangoRectangle strong_pos, weak_pos; + pango_layout_get_cursor_pos (layout, edit->selection_start, &strong_pos, &weak_pos); + draw_pango_rectangle (drawable, text_view->gc, x_origin, y_origin, strong_pos); + if (strong_pos.x != weak_pos.x || + strong_pos.y != weak_pos.y || + strong_pos.width != weak_pos.width || + strong_pos.height != weak_pos.height) + draw_pango_rectangle (drawable, text_view->gc, x_origin, y_origin, weak_pos); } - ypos += height; - lines++; } - unref_lines (&cell); - unbuild_current_cell (&cell); } - gdk_gc_set_clip_rectangle (text_view->gc, NULL); - gdk_gc_set_clip_rectangle (fg_gc, NULL); + g_object_unref (G_OBJECT (layout)); } - /* * Get the background color */ @@ -750,20 +726,6 @@ ect_get_bg_color(ECellView *ecell_view, int row) } -static void -ect_style_set(ECellView *ecell_view, GtkStyle *old_style) -{ - ECellTextView *text_view = (ECellTextView *) ecell_view; - ECellText *ect = (ECellText *) ecell_view->ecell; - - if (!ect->font_name) { - e_font_unref (text_view->font); - text_view->font = e_font_from_gdk_font (GTK_WIDGET (text_view->canvas)->style->font); - } -} - - - /* * Selects the entire string */ @@ -773,7 +735,7 @@ ect_edit_select_all (ECellTextView *text_view) g_assert (text_view->edit); text_view->edit->selection_start = 0; - text_view->edit->selection_end = strlen (text_view->edit->cell.text); + text_view->edit->selection_end = strlen (text_view->edit->text); } static gboolean @@ -797,28 +759,15 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, CellEdit *edit = text_view->edit; GtkWidget *canvas = GTK_WIDGET (text_view->canvas); gint return_val = 0; - CurrentCell cell, *cellptr; d(gboolean press = FALSE); if (!(flags & E_CELL_EDITING)) return 0; - build_current_cell (&cell, text_view, model_col, view_col, row); - - - if (edit){ - if ((edit->cell.view_col == view_col) && (edit->cell.row == row)) { - edit_display = TRUE; - cellptr = CURRENT_CELL(edit); - } else { - cellptr = &cell; - } - } else { - cellptr = &cell; + if (edit && edit->view_col == view_col && edit->row == row) { + edit_display = TRUE; } - set_style(ecell_view, cellptr, row); - e_tep_event.type = event->type; switch (event->type) { case GDK_FOCUS_CHANGE: @@ -837,7 +786,6 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, e_table_item_enter_edit (text_view->cell_view.e_table_item_view, view_col, row); ect_edit_select_all (text_view); edit = text_view->edit; - cellptr = CURRENT_CELL(edit); edit_display = TRUE; } if (edit_display) { @@ -886,14 +834,13 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, e_table_item_enter_edit (text_view->cell_view.e_table_item_view, view_col, row); edit = text_view->edit; - cellptr = CURRENT_CELL(edit); edit_display = TRUE; e_tep_event.button.type = GDK_BUTTON_PRESS; e_tep_event.button.time = button.time; e_tep_event.button.state = button.state; e_tep_event.button.button = button.button; - e_tep_event.button.position = _get_position_from_xy (cellptr, button.x, button.y); + e_tep_event.button.position = get_position_from_xy (edit, event->button.x, event->button.y); _get_tep (edit); edit->actions = 0; return_val = e_text_event_processor_handle_event (edit->tep, @@ -910,13 +857,13 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, edit->last_state = button.state; e_tep_event.button.type = GDK_BUTTON_RELEASE; - } + } if (edit_display) { GdkEventButton button = event->button; e_tep_event.button.time = button.time; e_tep_event.button.state = button.state; e_tep_event.button.button = button.button; - e_tep_event.button.position = _get_position_from_xy (cellptr, button.x, button.y); + e_tep_event.button.position = get_position_from_xy (edit, event->button.x, event->button.y); _get_tep (edit); edit->actions = 0; return_val = e_text_event_processor_handle_event (edit->tep, @@ -940,7 +887,7 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, GdkEventMotion motion = event->motion; e_tep_event.motion.time = motion.time; e_tep_event.motion.state = motion.state; - e_tep_event.motion.position = _get_position_from_xy (cellptr, motion.x, motion.y); + e_tep_event.motion.position = get_position_from_xy (edit, event->motion.x, event->motion.y); _get_tep (edit); edit->actions = 0; return_val = e_text_event_processor_handle_event (edit->tep, @@ -977,7 +924,6 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, break; } - unbuild_current_cell (&cell); if (return_val) return return_val; #if 0 @@ -996,22 +942,13 @@ static int ect_height (ECellView *ecell_view, int model_col, int view_col, int row) { ECellTextView *text_view = (ECellTextView *) ecell_view; - EFont *font; - ECellText *ect = E_CELL_TEXT(ecell_view->ecell); - gchar *string; - gint value; - - font = text_view->font; + gint height; + PangoLayout *layout; - if (row == -1) { - value = e_font_height (font) + TEXT_PAD; - } else { - string = e_cell_text_get_text(ect, ecell_view->e_table_model, model_col, row); - value = e_font_height (font) * number_of_lines(string) + TEXT_PAD; - e_cell_text_free_text(ect, string); - } - - return value; + layout = generate_layout (text_view, model_col, view_col, row); + pango_layout_get_pixel_size (layout, NULL, &height); + g_object_unref (layout); + return height + 2; } /* @@ -1028,9 +965,19 @@ ect_enter_edit (ECellView *ecell_view, int model_col, int view_col, int row) edit = g_new (CellEdit, 1); text_view->edit = edit; - build_current_cell (CURRENT_CELL(edit), text_view, model_col, view_col, row); + edit->view_col = -1; + edit->model_col = -1; + edit->row = -1; + + edit->layout = generate_layout (text_view, model_col, view_col, row); - set_style(ecell_view, CURRENT_CELL(edit), row); + edit->text_view = text_view; + edit->model_col = model_col; + edit->view_col = view_col; + edit->row = row; + edit->cell_width = e_table_header_get_column ( + ((ETableItem *)ecell_view->e_table_item_view)->header, + view_col)->width - 8; edit->xofs_edit = 0.0; edit->yofs_edit = 0.0; @@ -1068,7 +1015,7 @@ ect_enter_edit (ECellView *ecell_view, int model_col, int view_col, int row) temp = e_cell_text_get_text(ect, ecell_view->e_table_model, model_col, row); edit->old_text = g_strdup (temp); e_cell_text_free_text(ect, temp); - edit->cell.text = g_strdup (edit->old_text); + edit->text = g_strdup (edit->old_text); #if 0 if (edit->pointer_in){ @@ -1095,9 +1042,6 @@ ect_leave_edit (ECellView *ecell_view, int model_col, int view_col, int row, voi if (edit){ ect_stop_editing (text_view, TRUE); - /* FIXME: edit is freed in ect_stop_editing() so I've - commented this out - Damon. */ - /*unbuild_current_cell (CURRENT_CELL(edit));*/ } else { /* * We did invoke this leave edit internally @@ -1132,7 +1076,7 @@ ect_load_state (ECellView *ecell_view, int model_col, int view_col, int row, voi int length; int *selection = save_state; - length = strlen (edit->cell.text); + length = strlen (edit->text); edit->selection_start = MIN (selection[0], length); edit->selection_end = MIN (selection[1], length); @@ -1154,7 +1098,7 @@ ect_print (ECellView *ecell_view, GnomePrintContext *context, int model_col, int view_col, int row, double width, double height) { - GnomeFont *font = gnome_font_new ("Helvetica", 12); + GnomeFont *font = gnome_font_find ("Helvetica", 12); char *string; ECellText *ect = E_CELL_TEXT(ecell_view->ecell); string = e_cell_text_get_text(ect, ecell_view->e_table_model, model_col, row); @@ -1193,32 +1137,23 @@ ect_max_width (ECellView *ecell_view, { /* New ECellText */ ECellTextView *text_view = (ECellTextView *) ecell_view; - EFont *font; int row; int number_of_rows; int max_width = 0; - font = text_view->font; number_of_rows = e_table_model_row_count (ecell_view->e_table_model); for (row = 0; row < number_of_rows; row++) { - CurrentCell cell; - struct line *line; + PangoLayout *layout = generate_layout (text_view, model_col, view_col, row); int width; - build_current_cell (&cell, text_view, model_col, view_col, row); - split_into_lines (&cell); - calc_line_widths (&cell); - - line = (struct line *)cell.breaks->lines; - width = e_font_utf8_text_width (font, cell.style, - line->text, line->length); + pango_layout_get_pixel_size (layout, &width, NULL); + max_width = MAX (max_width, width); - unref_lines (&cell); - unbuild_current_cell (&cell); + g_object_unref (layout); } - return max_width; + return max_width + 8; } static int @@ -1229,24 +1164,17 @@ ect_max_width_by_row (ECellView *ecell_view, { /* New ECellText */ ECellTextView *text_view = (ECellTextView *) ecell_view; - CurrentCell cell; - struct line *line; int width; + PangoLayout *layout; if (row >= e_table_model_row_count (ecell_view->e_table_model)) return 0; - build_current_cell (&cell, text_view, model_col, view_col, row); - split_into_lines (&cell); - calc_line_widths (&cell); - - line = (struct line *)cell.breaks->lines; - width = e_font_utf8_text_width (text_view->font, cell.style, - line->text, line->length); - unref_lines (&cell); - unbuild_current_cell (&cell); + layout = generate_layout (text_view, model_col, view_col, row); + pango_layout_get_pixel_size (layout, &width, NULL); + g_object_unref (layout); - return width; + return width + 8; } static gint @@ -1298,12 +1226,7 @@ ect_show_tooltip (ECellView *ecell_view, ETableTooltip *tooltip) { ECellTextView *text_view = (ECellTextView *) ecell_view; - CurrentCell cell; - struct line *lines; GtkWidget *canvas; - int i; - gdouble max_width; - gboolean cut_off; double i2c[6]; ArtPoint origin = {0, 0}; ArtPoint pixel_origin; @@ -1314,33 +1237,17 @@ ect_show_tooltip (ECellView *ecell_view, double tooltip_x; double tooltip_y; GnomeCanvasItem *rect; - double text_height; ECellText *ect = E_CELL_TEXT(ecell_view->ecell); GtkWidget *window; + PangoLayout *layout; + int width, height; tooltip->timer = 0; - build_current_cell (&cell, text_view, model_col, view_col, row); - - set_style(ecell_view, &cell, row); - - cell.width = col_width - 8; - split_into_lines (&cell); - calc_line_widths (&cell); - - cut_off = FALSE; - for (lines = cell.breaks->lines, i = 0; i < cell.breaks->num_lines; - lines++, i++) { - if (lines->length > lines->ellipsis_length) { - cut_off = TRUE; - break; - } - } + layout = generate_layout (text_view, model_col, view_col, row); - if (!cut_off) { - tooltip->timer = 0; - unref_lines (&cell); - unbuild_current_cell (&cell); + pango_layout_get_pixel_size (layout, &width, &height); + if (width < col_width - 8) { return; } @@ -1362,24 +1269,12 @@ ect_show_tooltip (ECellView *ecell_view, GTK_WIDGET_UNSET_FLAGS (canvas, GTK_CAN_FOCUS); GTK_WIDGET_UNSET_FLAGS (window, GTK_CAN_FOCUS); - max_width = 0.0; - for (lines = cell.breaks->lines, i = 0; i < cell.breaks->num_lines; - lines++, i++) { - gdouble line_width; - - line_width = e_font_utf8_text_width (text_view->font, - cell.style, lines->text, - lines->length); - max_width = MAX (max_width, line_width); - } - - text_height = e_font_height (text_view->font) * cell.breaks->num_lines + 4; rect = gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (canvas)), gnome_canvas_rect_get_type (), "x1", (double) 0.0, "y1", (double) 0.0, - "x2", (double) max_width + 4, - "y2", (double) text_height, + "x2", (double) width + 4, + "y2", (double) height, "fill_color_gdk", tooltip->background, NULL); @@ -1390,18 +1285,18 @@ ect_show_tooltip (ECellView *ecell_view, "bold", (gboolean) ect->bold_column >= 0 && e_table_model_value_at(ecell_view->e_table_model, ect->bold_column, row), "strikeout", (gboolean) ect->strikeout_column >= 0 && e_table_model_value_at(ecell_view->e_table_model, ect->strikeout_column, row), "fill_color_gdk", tooltip->foreground, - "text", cell.text, + "text", pango_layout_get_text (layout), "editable", FALSE, - "clip_width", max_width, - "clip_height", (double) text_height, + "clip_width", (double) width, + "clip_height", (double) height, "clip", TRUE, "line_wrap", FALSE, "justification", E_CELL_TEXT (text_view->cell_view.ecell)->justify, "draw_background", FALSE, NULL); - tooltip_width = max_width; - tooltip_height = text_height; + tooltip_width = width; + tooltip_height = height; tooltip_y = tooltip->y; switch (E_CELL_TEXT (text_view->cell_view.ecell)->justify) { @@ -1435,9 +1330,6 @@ ect_show_tooltip (ECellView *ecell_view, e_canvas_popup_tooltip (E_CANVAS(text_view->canvas), window, pixel_origin.x + tooltip->x, pixel_origin.y + tooltip->y - 1); - unref_lines (&cell); - unbuild_current_cell (&cell); - return; } @@ -1445,13 +1337,13 @@ ect_show_tooltip (ECellView *ecell_view, * GtkObject::destroy method */ static void -ect_destroy (GtkObject *object) +ect_finalize (GObject *object) { ECellText *ect = E_CELL_TEXT (object); g_free (ect->font_name); - GTK_OBJECT_CLASS (parent_class)->destroy (object); + G_OBJECT_CLASS (parent_class)->finalize (object); } /* Set_arg handler for the text item */ static void @@ -1532,7 +1424,7 @@ e_cell_text_class_init (GtkObjectClass *object_class) ECellTextClass *ectc = (ECellTextClass *) object_class; char *ellipsis_env; - object_class->destroy = ect_destroy; + G_OBJECT_CLASS (object_class)->finalize = ect_finalize; ecc->new_view = ect_new_view; ecc->kill_view = ect_kill_view; @@ -1552,7 +1444,6 @@ e_cell_text_class_init (GtkObjectClass *object_class) ecc->max_width_by_row = ect_max_width_by_row; ecc->show_tooltip = ect_show_tooltip; ecc->get_bg_color = ect_get_bg_color; - ecc->style_set = ect_style_set; ectc->get_text = ect_real_get_text; ectc->free_text = ect_real_free_text; @@ -1654,163 +1545,28 @@ e_cell_text_new (const char *fontname, GtkJustification justify) return (ECell *) ect; } -/* Calculates the x position of the specified line of text, based on the text's justification */ -static int -get_line_xpos (CurrentCell *cell, struct line *line) -{ - int x; - - ECellTextView *text_view = cell->text_view; - ECellText *ect = E_CELL_TEXT (((ECellView *)cell->text_view)->ecell); - - x = text_view->xofs + ect->x; - - switch (ect->justify) { - case GTK_JUSTIFY_RIGHT: - x += cell->width - line->width; - break; - - case GTK_JUSTIFY_CENTER: - x += (cell->width - line->width) / 2; - break; - - default: - /* For GTK_JUSTIFY_LEFT, we don't have to do anything. We do not support - * GTK_JUSTIFY_FILL, yet. - */ - break; - } - - return x; -} - -/* Calculates the x position of the specified line of text, based on the text's justification */ -static int -get_line_ypos (CurrentCell *cell, struct line *line) -{ - int y; - - ECellTextView *text_view = cell->text_view; - ECellText *ect = E_CELL_TEXT (((ECellView *)cell->text_view)->ecell); - ECellTextLineBreaks *linebreaks = cell->breaks; - - struct line *lines = linebreaks->lines; - - EFont *font; - - font = text_view->font; - - y = text_view->yofs + ect->y; - y += (line - lines) * e_font_height (font); - - return y; -} /* fixme: Handle Font attributes */ /* position is in BYTES */ -static void -_get_xy_from_position (CurrentCell *cell, gint position, gint *xp, gint *yp) -{ - if (xp || yp) { - struct line *lines; - int x, y; - int j; - ECellTextView *text_view = cell->text_view; - ECellTextLineBreaks *linebreaks; - EFont *font; - - font = text_view->font; - - split_into_lines (cell); - - linebreaks = cell->breaks; - lines = linebreaks->lines; - - x = get_line_xpos (cell, lines); - y = get_line_ypos (cell, lines); - for (j = 0, lines = linebreaks->lines; j < linebreaks->num_lines; lines++, j++) { - if (lines->text > cell->text + position) - break; - y += e_font_height (font); - } - lines --; - y -= e_font_descent (font); - - x += e_font_utf8_text_width (font, cell->style, - lines->text, - position - (lines->text - cell->text)); - if ((CellEdit *) cell == cell->text_view->edit){ - x -= ((CellEdit *)cell)->xofs_edit; - y -= ((CellEdit *)cell)->yofs_edit; - } - if (xp) - *xp = x; - if (yp) - *yp = y; - unref_lines (cell); - } -} - static gint -_get_position_from_xy (CurrentCell *cell, gint x, gint y) +get_position_from_xy (CellEdit *edit, gint x, gint y) { - int i, j; - int xpos, ypos; - struct line *lines; - int return_val; - gchar *p; - - ECellTextView *text_view = cell->text_view; - ECellTextLineBreaks *linebreaks; - EFont *font; - - font = text_view->font; - - split_into_lines (cell); - - linebreaks = cell->breaks; - - lines = linebreaks->lines; - - if ((CellEdit *) cell == cell->text_view->edit){ - x += ((CellEdit *)cell)->xofs_edit; - y += ((CellEdit *)cell)->yofs_edit; - } - - ypos = get_line_ypos (cell, linebreaks->lines); - j = 0; - while (y > ypos) { - ypos += e_font_height (font); - j ++; - } - j--; - if (j >= linebreaks->num_lines) - j = linebreaks->num_lines - 1; - if (j < 0) - j = 0; - i = 0; + int index; + int trailing; + const char *text; + PangoLayout *layout = edit->layout; + ECellTextView *text_view = edit->text_view; + ECellText *ect = (ECellText *) ((ECellView *)text_view)->ecell; - lines += j; - xpos = get_line_xpos (cell, lines); + x -= (ect->x + text_view->xofs - edit->xofs_edit); + y -= (ect->y + text_view->yofs - edit->yofs_edit); - for (p = lines->text; p < lines->text + lines->length && g_unichar_validate (g_utf8_get_char (p)); p = g_utf8_next_char (p)) { - gint charwidth; + pango_layout_xy_to_index (layout, x * PANGO_SCALE, y * PANGO_SCALE, &index, &trailing); - charwidth = e_font_utf8_char_width (font, cell->style, p); + text = pango_layout_get_text (layout); - xpos += charwidth / 2; - if (xpos > x) { - break; - } - xpos += (charwidth + 1) / 2; - } - - return_val = p - cell->text; - - unref_lines (cell); - - return return_val; + return g_utf8_offset_to_pointer (text + index, trailing) - text; } #define SCROLL_WAIT_TIME 30000 @@ -1821,11 +1577,11 @@ _blink_scroll_timeout (gpointer data) ECellTextView *text_view = (ECellTextView *) data; ECellText *ect = E_CELL_TEXT (((ECellView *)text_view)->ecell); CellEdit *edit = text_view->edit; - CurrentCell *cell = CURRENT_CELL(edit); gulong current_time; gboolean scroll = FALSE; gboolean redraw = FALSE; + int width, height; g_timer_elapsed (edit->timer, ¤t_time); @@ -1838,19 +1594,18 @@ _blink_scroll_timeout (gpointer data) current_time < edit->scroll_start) scroll = TRUE; } + + pango_layout_get_pixel_size (edit->layout, &width, &height); + if (scroll && edit->button_down) { /* FIXME: Copy this for y. */ - if (edit->lastx - ect->x > cell->width) { - ECellTextLineBreaks *linebreaks; - split_into_lines (cell); - linebreaks = cell->breaks; - if (edit->xofs_edit < linebreaks->max_width - cell->width) { + if (edit->lastx - ect->x > edit->cell_width) { + if (edit->xofs_edit < width - edit->cell_width) { edit->xofs_edit += 4; - if (edit->xofs_edit > linebreaks->max_width - cell->width + 1) - edit->xofs_edit = linebreaks->max_width - cell->width + 1; + if (edit->xofs_edit > width - edit->cell_width + 1) + edit->xofs_edit = width - edit->cell_width + 1; redraw = TRUE; } - unref_lines (cell); } if (edit->lastx - ect->x < 0 && edit->xofs_edit > 0) { @@ -1864,7 +1619,7 @@ _blink_scroll_timeout (gpointer data) e_tep_event.type = GDK_MOTION_NOTIFY; e_tep_event.motion.state = edit->last_state; e_tep_event.motion.time = 0; - e_tep_event.motion.position = _get_position_from_xy (cell, edit->lastx, edit->lasty); + e_tep_event.motion.position = get_position_from_xy (edit, edit->lastx, edit->lasty); _get_tep (edit); e_text_event_processor_handle_event (edit->tep, &e_tep_event); @@ -1882,7 +1637,7 @@ _blink_scroll_timeout (gpointer data) edit->show_cursor = FALSE; } if (redraw){ - ect_queue_redraw (text_view, edit->cell.view_col, edit->cell.row); + ect_queue_redraw (text_view, edit->view_col, edit->row); } return TRUE; } @@ -1890,36 +1645,35 @@ _blink_scroll_timeout (gpointer data) static int next_word (CellEdit *edit, int start) { - CurrentCell *cell = CURRENT_CELL(edit); char *p; int length; - length = strlen (cell->text); + length = strlen (edit->text); if (start >= length) return length; - p = g_utf8_next_char (cell->text + start); + p = g_utf8_next_char (edit->text + start); while (*p && g_unichar_validate (g_utf8_get_char (p))) { gunichar unival = g_utf8_get_char (p); if (g_unichar_isspace (unival)) - return p - cell->text; + return p - edit->text; p = g_utf8_next_char (p); } - return p - cell->text; + return p - edit->text; } static int _get_position (ECellTextView *text_view, ETextEventProcessorCommand *command) { int length; - int x, y; CellEdit *edit = text_view->edit; - CurrentCell *cell = CURRENT_CELL(edit); EFont *font; gchar *p; int unival; + int index; + int trailing; font = text_view->font; @@ -1937,57 +1691,57 @@ _get_position (ECellTextView *text_view, ETextEventProcessorCommand *command) /* fixme: this probably confuses TEP */ case E_TEP_END_OF_BUFFER: - return strlen (cell->text); + return strlen (edit->text); case E_TEP_START_OF_LINE: if (edit->selection_end < 1) return 0; - p = g_utf8_find_prev_char (cell->text, cell->text + edit->selection_end); + p = g_utf8_find_prev_char (edit->text, edit->text + edit->selection_end); - if (p == cell->text) return 0; + if (p == edit->text) return 0; - p = g_utf8_find_prev_char (cell->text, p); + p = g_utf8_find_prev_char (edit->text, p); - while (p && p > cell->text) { - if (*p == '\n') return p - cell->text + 1; - p = g_utf8_find_prev_char (cell->text, p); + while (p && p > edit->text) { + if (*p == '\n') return p - edit->text + 1; + p = g_utf8_find_prev_char (edit->text, p); } return 0; case E_TEP_END_OF_LINE: - length = strlen (cell->text); + length = strlen (edit->text); if (edit->selection_end >= length) return length; - p = g_utf8_next_char (cell->text + edit->selection_end); + p = g_utf8_next_char (edit->text + edit->selection_end); while (*p && g_unichar_validate (g_utf8_get_char (p))) { - if (*p == '\n') return p - cell->text; + if (*p == '\n') return p - edit->text; p = g_utf8_next_char (p); } - return p - cell->text; + return p - edit->text; case E_TEP_FORWARD_CHARACTER: - length = strlen (cell->text); + length = strlen (edit->text); if (edit->selection_end >= length) return length; - p = g_utf8_next_char (cell->text + edit->selection_end); + p = g_utf8_next_char (edit->text + edit->selection_end); - return p - cell->text; + return p - edit->text; case E_TEP_BACKWARD_CHARACTER: if (edit->selection_end < 1) return 0; - p = g_utf8_find_prev_char (cell->text, cell->text + edit->selection_end); + p = g_utf8_find_prev_char (edit->text, edit->text + edit->selection_end); if (p == NULL) return 0; - return p - cell->text; + return p - edit->text; case E_TEP_FORWARD_WORD: return next_word (edit, edit->selection_end); @@ -1996,31 +1750,53 @@ _get_position (ECellTextView *text_view, ETextEventProcessorCommand *command) if (edit->selection_end < 1) return 0; - p = g_utf8_find_prev_char (cell->text, cell->text + edit->selection_end); + p = g_utf8_find_prev_char (edit->text, edit->text + edit->selection_end); - if (p == cell->text) return 0; + if (p == edit->text) return 0; - p = g_utf8_find_prev_char (cell->text, p); + p = g_utf8_find_prev_char (edit->text, p); - while (p && p > cell->text && g_unichar_validate (g_utf8_get_char (p))) { + while (p && p > edit->text && g_unichar_validate (g_utf8_get_char (p))) { unival = g_utf8_get_char (p); if (g_unichar_isspace (unival)) { - return (g_utf8_next_char (p) - cell->text); + return (g_utf8_next_char (p) - edit->text); } - p = g_utf8_find_prev_char (cell->text, p); + p = g_utf8_find_prev_char (edit->text, p); } return 0; case E_TEP_FORWARD_LINE: - _get_xy_from_position (cell, edit->selection_end, &x, &y); - y += e_font_height (font); - return _get_position_from_xy (cell, x, y); + pango_layout_move_cursor_visually (edit->layout, + TRUE, + edit->selection_end, + 0, + TRUE, + &index, + &trailing); + index = g_utf8_offset_to_pointer (edit->text + index, trailing) - edit->text; + if (index < 0) + return 0; + length = strlen (edit->text); + if (index >= length) + return length; + return index; case E_TEP_BACKWARD_LINE: - _get_xy_from_position (cell, edit->selection_end, &x, &y); - y -= e_font_height (font); - return _get_position_from_xy (cell, x, y); - + pango_layout_move_cursor_visually (edit->layout, + TRUE, + edit->selection_end, + 0, + TRUE, + &index, + &trailing); + + index = g_utf8_offset_to_pointer (edit->text + index, trailing) - edit->text; + if (index < 0) + return 0; + length = strlen (edit->text); + if (index >= length) + return length; + return index; case E_TEP_FORWARD_PARAGRAPH: case E_TEP_BACKWARD_PARAGRAPH: @@ -2038,7 +1814,6 @@ static void _delete_selection (ECellTextView *text_view) { CellEdit *edit = text_view->edit; - CurrentCell *cell = CURRENT_CELL(edit); gint length; gchar *sp, *ep; @@ -2050,8 +1825,8 @@ _delete_selection (ECellTextView *text_view) edit->selection_end ^= edit->selection_start; } - sp = cell->text + edit->selection_start; - ep = cell->text + edit->selection_end; + sp = edit->text + edit->selection_start; + ep = edit->text + edit->selection_end; length = strlen (ep) + 1; memmove (sp, ep, length); @@ -2066,20 +1841,19 @@ static void _insert (ECellTextView *text_view, char *string, int value) { CellEdit *edit = text_view->edit; - CurrentCell *cell = CURRENT_CELL(edit); char *temp; if (value <= 0) return; - temp = g_new (gchar, strlen (cell->text) + value + 1); + temp = g_new (gchar, strlen (edit->text) + value + 1); - strncpy (temp, cell->text, edit->selection_start); + strncpy (temp, edit->text, edit->selection_start); strncpy (temp + edit->selection_start, string, value); - strcpy (temp + edit->selection_start + value, cell->text + edit->selection_end); + strcpy (temp + edit->selection_start + value, edit->text + edit->selection_end); - g_free (cell->text); + g_free (edit->text); - cell->text = temp; + edit->text = temp; edit->selection_start += value; edit->selection_end = edit->selection_start; @@ -2088,13 +1862,12 @@ _insert (ECellTextView *text_view, char *string, int value) static void capitalize (CellEdit *edit, int start, int end, ETextEventProcessorCaps type) { - CurrentCell *cell = CURRENT_CELL(edit); - ECellTextView *text_view = cell->text_view; + ECellTextView *text_view = edit->text_view; gboolean first = TRUE; - int character_length = g_utf8_strlen (cell->text + start, start - end); - const char *p = cell->text + start; - const char *text_end = cell->text + end; + int character_length = g_utf8_strlen (edit->text + start, start - end); + const char *p = edit->text + start; + const char *text_end = edit->text + end; char *new_text = g_new0 (char, character_length * 6 + 1); char *output = new_text; @@ -2141,8 +1914,7 @@ static void e_cell_text_view_command (ETextEventProcessor *tep, ETextEventProcessorCommand *command, gpointer data) { CellEdit *edit = (CellEdit *) data; - CurrentCell *cell = CURRENT_CELL(edit); - ECellTextView *text_view = cell->text_view; + ECellTextView *text_view = edit->text_view; ECellText *ect = E_CELL_TEXT (text_view->cell_view.ecell); gboolean change = FALSE; @@ -2176,7 +1948,7 @@ e_cell_text_view_command (ETextEventProcessor *tep, ETextEventProcessorCommand * sel_end = MAX(edit->selection_start, edit->selection_end); if (sel_start != sel_end) { e_cell_text_view_supply_selection (edit, command->time, GDK_SELECTION_PRIMARY, - cell->text + sel_start, + edit->text + sel_start, sel_end - sel_start); } else if (edit->timer) { g_timer_reset (edit->timer); @@ -2211,7 +1983,7 @@ e_cell_text_view_command (ETextEventProcessor *tep, ETextEventProcessorCommand * sel_end = MAX(edit->selection_start, edit->selection_end); if (sel_start != sel_end) { e_cell_text_view_supply_selection (edit, command->time, clipboard_atom, - cell->text + sel_start, + edit->text + sel_start, sel_end - sel_start); } if (edit->timer) { @@ -2259,88 +2031,33 @@ e_cell_text_view_command (ETextEventProcessor *tep, ETextEventProcessorCommand * break; } - if (!edit->button_down) { - int x; - int i; - struct line *lines; - ECellTextLineBreaks *linebreaks; - - split_into_lines (cell); - - linebreaks = cell->breaks; - - for (lines = linebreaks->lines, i = 0; i < linebreaks->num_lines ; i++, lines ++) { - if ((lines->text - cell->text) > edit->selection_end) { - break; - } - } - lines --; - x = e_font_utf8_text_width (font, cell->style, - lines->text, - edit->selection_end - (lines->text - cell->text)); - + if (change) { + if (edit->layout) + g_object_unref (edit->layout); + edit->layout = build_layout (text_view, edit->row, edit->text); + } - if (x < edit->xofs_edit) { - edit->xofs_edit = x; - redraw = TRUE; + if (!edit->button_down) { + PangoRectangle strong_pos, weak_pos; + pango_layout_get_cursor_pos (edit->layout, edit->selection_end, &strong_pos, &weak_pos); + if (strong_pos.x != weak_pos.x || + strong_pos.y != weak_pos.y || + strong_pos.width != weak_pos.width || + strong_pos.height != weak_pos.height) { + if (show_pango_rectangle (edit, weak_pos)) + redraw = TRUE; } - - if (2 + x - cell->width > edit->xofs_edit) { - edit->xofs_edit = 2 + x - cell->width; + if (show_pango_rectangle (edit, strong_pos)) { redraw = TRUE; } - unref_lines (cell); } if (redraw){ - ect_queue_redraw (text_view, edit->cell.view_col, edit->cell.row); - } -#if 0 - gnome_canvas_item_request_update (GNOME_CANVAS_ITEM(text)); -#endif -} - -static void _invisible_destroy (GtkInvisible *invisible, - CellEdit *edit) -{ - edit->invisible = NULL; -} - -static GtkWidget *e_cell_text_view_get_invisible (CellEdit *edit) -{ - GtkWidget *invisible; - if (edit->invisible) { - invisible = edit->invisible; - } else { - invisible = gtk_invisible_new (); - edit->invisible = invisible; - - gtk_selection_add_target (invisible, - GDK_SELECTION_PRIMARY, - GDK_SELECTION_TYPE_STRING, - E_SELECTION_PRIMARY); - gtk_selection_add_target (invisible, - clipboard_atom, - GDK_SELECTION_TYPE_STRING, - E_SELECTION_CLIPBOARD); - - gtk_signal_connect (GTK_OBJECT(invisible), "selection_get", - GTK_SIGNAL_FUNC (_selection_get), - edit); - gtk_signal_connect (GTK_OBJECT(invisible), "selection_clear_event", - GTK_SIGNAL_FUNC (_selection_clear_event), - edit); - gtk_signal_connect (GTK_OBJECT(invisible), "selection_received", - GTK_SIGNAL_FUNC (_selection_received), - edit); - - gtk_signal_connect (GTK_OBJECT(invisible), "destroy", - GTK_SIGNAL_FUNC (_invisible_destroy), - edit); + ect_queue_redraw (text_view, edit->view_col, edit->row); } - return invisible; } +#ifdef DO_SELECTION static void _selection_clear_event (GtkInvisible *invisible, GdkEventSelection *event, @@ -2403,9 +2120,41 @@ _selection_received (GtkInvisible *invisible, } } +static GtkWidget *e_cell_text_view_get_invisible (CellEdit *edit) +{ + if (edit->invisible == NULL) { + GtkWidget *invisible = gtk_invisible_new (); + edit->invisible = invisible; + + gtk_selection_add_target (invisible, + GDK_SELECTION_PRIMARY, + GDK_SELECTION_TYPE_STRING, + E_SELECTION_PRIMARY); + gtk_selection_add_target (invisible, + clipboard_atom, + GDK_SELECTION_TYPE_STRING, + E_SELECTION_CLIPBOARD); + + gtk_signal_connect (GTK_OBJECT(invisible), "selection_get", + GTK_SIGNAL_FUNC (_selection_get), + edit); + gtk_signal_connect (GTK_OBJECT(invisible), "selection_clear_event", + GTK_SIGNAL_FUNC (_selection_clear_event), + edit); + gtk_signal_connect (GTK_OBJECT(invisible), "selection_received", + GTK_SIGNAL_FUNC (_selection_received), + edit); + + g_object_weak_ref (G_OBJECT (invisible), invisible_finalize, edit); + } + return edit->invisible; +} +#endif + static void e_cell_text_view_supply_selection (CellEdit *edit, guint time, GdkAtom selection, char *data, gint length) { +#if DO_SELECTION gboolean successful; GtkWidget *invisible; @@ -2431,17 +2180,20 @@ e_cell_text_view_supply_selection (CellEdit *edit, guint time, GdkAtom selection if (selection == GDK_SELECTION_PRIMARY) edit->has_selection = successful; +#endif } static void e_cell_text_view_get_selection (CellEdit *edit, GdkAtom selection, guint32 time) { +#if DO_SELECTION GtkWidget *invisible; invisible = e_cell_text_view_get_invisible (edit); gtk_selection_convert (invisible, selection, GDK_SELECTION_TYPE_STRING, time); +#endif } static void @@ -2458,89 +2210,6 @@ _get_tep (CellEdit *edit) } } -static int -number_of_lines (char *text) -{ - int num_lines = 0; - gchar *p; - - if (!text) return 0; - - for (p = text; *p && g_unichar_validate (g_utf8_get_char (p)); p = g_utf8_next_char (p)) { - if (*p == '\n') num_lines++; - } - - num_lines++; - return num_lines; -} - -/* Splits the text of the text item into lines */ -static void -split_into_lines (CurrentCell *cell) -{ - char *p; - struct line *lines; - gint len; - - char *text = cell->text; - ECellTextLineBreaks *linebreaks; - - if (! cell->breaks) { - cell->breaks = g_new (ECellTextLineBreaks, 1); - cell->breaks->ref_count = 1; - } else { - cell->breaks->ref_count ++; - return; - } - linebreaks = cell->breaks; - - /* Check if already split. */ - linebreaks->lines = NULL; - linebreaks->num_lines = 0; - - if (!text) - return; - - /* First, count the number of lines */ - - linebreaks->num_lines = number_of_lines(cell->text); - - /* Allocate array of lines and calculate split positions */ - - linebreaks->lines = lines = g_new0 (struct line, linebreaks->num_lines); - - len = 0; - for (p = text; *p && g_unichar_validate (g_utf8_get_char (p)); p = g_utf8_next_char (p)) { - if (len == 0) lines->text = p; - if (*p == '\n') { - lines->length = p - lines->text; - lines++; - len = 0; - } else - len++; - } - - if (len == 0) - lines->text = p; - lines->length = p - lines->text; - - calc_line_widths (cell); -} - -/* Free lines structure. */ -static void -unref_lines (CurrentCell *cell) -{ - if (cell->breaks){ - cell->breaks->ref_count --; - if (cell->breaks->ref_count <= 0){ - g_free (cell->breaks->lines); - g_free (cell->breaks); - cell->breaks = NULL; - } - } -} - static void calc_ellipsis (ECellTextView *text_view) { @@ -2560,101 +2229,6 @@ calc_ellipsis (ECellTextView *text_view) } } -/* Calculates the line widths (in pixels) of the text's splitted lines */ -static void -calc_line_widths (CurrentCell *cell) -{ - ECellTextView *text_view = cell->text_view; - ECellText *ect = E_CELL_TEXT (((ECellView *)text_view)->ecell); - ECellTextLineBreaks *linebreaks = cell->breaks; - struct line *lines; - int i; - int j; - EFont *font; - - font = text_view->font; - - lines = linebreaks->lines; - linebreaks->max_width = 0; - - if (!lines) return; - - for (i = 0; i < linebreaks->num_lines; i++) { - if (lines->length != 0) { - if (font) { - lines->width = e_font_utf8_text_width (font, cell->style, - lines->text, lines->length); - lines->ellipsis_length = 0; - } else { - lines->width = 0; - } - - if (ect->use_ellipsis && - (!(text_view->edit && - cell->row == text_view->edit->cell.row && - cell->view_col == text_view->edit->cell.view_col)) && - lines->width > cell->width) { - if (font) { - lines->ellipsis_length = 0; - for (j = 0; j < lines->length; j++){ - if (e_font_utf8_text_width (font, cell->style, lines->text, j) + - text_view->ellipsis_width[cell->style] < cell->width) { - lines->ellipsis_length = j; - } - else - break; - } - } - else - lines->ellipsis_length = 0; - lines->width = e_font_utf8_text_width (font, cell->style, lines->text, lines->ellipsis_length) + - text_view->ellipsis_width[cell->style]; - } - else - lines->ellipsis_length = lines->length; - - if (lines->width > linebreaks->max_width) - linebreaks->max_width = lines->width; - } else { - lines->width = 0; - lines->ellipsis_length = 0; - } - - lines++; - } -} - -static void -build_current_cell (CurrentCell *cell, ECellTextView *text_view, int model_col, int view_col, int row) -{ - ECellView *ecell_view = (ECellView *) text_view; - ECellText *ect = E_CELL_TEXT (ecell_view->ecell); - char *temp; - - cell->text_view = text_view; - cell->model_col = model_col; - cell->view_col = view_col; - cell->row = row; - cell->breaks = NULL; - - temp = e_cell_text_get_text(ect, ecell_view->e_table_model, model_col, row); - cell->text = g_strdup(temp); - e_cell_text_free_text(ect, temp); - - cell->width = e_table_header_get_column ( - ((ETableItem *)ecell_view->e_table_item_view)->header, - view_col)->width - 8; - cell->style = 0; -} - -static void -unbuild_current_cell (CurrentCell *cell) -{ - g_free(cell->text); - cell->text = NULL; -} - - static GdkColor* e_cell_text_get_color (ECellTextView *cell_view, gchar *color_spec) { |