static gboolean item_grid_button_released (GocItem *item, int button, G_GNUC_UNUSED double x_, G_GNUC_UNUSED double y_) { GnmItemGrid *ig = GNM_ITEM_GRID (item); GnmPane *pane = GNM_PANE (item->canvas); SheetControlGUI *scg = ig->scg; Sheet *sheet = scg_sheet (scg); ItemGridSelectionType selecting = ig->selecting; GdkEvent *event = goc_canvas_get_cur_event (item->canvas); if (button != 1 && button != 2) return FALSE; gnm_pane_slide_stop (pane); switch (selecting) { case GNM_ITEM_GRID_NO_SELECTION: return TRUE; case GNM_ITEM_GRID_SELECTING_FORMULA_RANGE : /* Removal of this code (2 lines) */ /* should fix http://bugzilla.gnome.org/show_bug.cgi?id=63485 */ /* sheet_make_cell_visible (sheet, */ /* sheet->edit_pos.col, sheet->edit_pos.row, FALSE); */ /* Fall through */ case GNM_ITEM_GRID_SELECTING_CELL_RANGE : sv_selection_simplify (scg_view (scg)); wb_view_selection_desc ( wb_control_view (scg_wbc (scg)), TRUE, NULL); break; default: g_assert_not_reached (); } ig->selecting = GNM_ITEM_GRID_NO_SELECTION; gnm_simple_canvas_ungrab (item, gdk_event_get_time (event)); if (selecting == GNM_ITEM_GRID_SELECTING_FORMULA_RANGE) gnm_expr_entry_signal_update ( wbcg_get_entry_logical (scg_wbcg (scg)), TRUE); if (selecting == GNM_ITEM_GRID_SELECTING_CELL_RANGE && button == 1) { GnmCellPos const *pos = sv_is_singleton_selected (scg_view (scg)); if (pos != NULL) { GnmHLink *link; /* check for hyper links */ link = sheet_hlink_find (sheet, pos); if (link != NULL) gnm_hlink_activate (link, scg_wbcg (scg)); } } return TRUE; }
static void gnm_so_path_user_config (SheetObject *so, SheetControl *sc) { GnmSOPath *sop = GNM_SO_PATH (so); dialog_so_styled (scg_wbcg (GNM_SCG (sc)), G_OBJECT (sop), sop_default_style (), _("Filled Object Properties"), SO_STYLED_TEXT); }
static gboolean ccombo_activate (GtkTreeView *list, gboolean button) { SheetObjectView *sov = g_object_get_data (G_OBJECT (list), SOV_ID); GocItem *view = GOC_ITEM (sov); GnmPane *pane = GNM_PANE (view->canvas); GnmCComboViewClass *klass = GNM_CCOMBO_VIEW_GET_CLASS (sov); if ((klass->activate) (sheet_object_view_get_so (sov), list, scg_wbcg (pane->simple.scg), button)) { ccombo_popup_destroy (GTK_WIDGET (list)); return TRUE; } return FALSE; }
static void soi_cb_save_as (SheetObject *so, SheetControl *sc) { WBCGtk *wbcg; char *uri; GsfOutput *output; GSList *l = NULL; GOImageFormat sel_fmt; GOImageFormatInfo const *format_info; GdkPixbuf *pixbuf = NULL; GError *err = NULL; SheetObjectImage *soi = SHEET_OBJECT_IMAGE (so); g_return_if_fail (soi != NULL); sel_fmt = go_image_get_format_from_name (soi->type); if ((pixbuf = go_image_get_pixbuf (soi->image)) != NULL) l = go_image_get_formats_with_pixbuf_saver (); /* Move original format first in menu */ if (sel_fmt != GO_IMAGE_FORMAT_UNKNOWN) { l = g_slist_remove (l, GUINT_TO_POINTER (sel_fmt)); l = g_slist_prepend (l, GUINT_TO_POINTER (sel_fmt)); } wbcg = scg_wbcg (SHEET_CONTROL_GUI (sc)); uri = go_gui_get_image_save_info (wbcg_toplevel (wbcg), l, &sel_fmt, NULL); if (!uri) goto out; output = go_file_create (uri, &err); if (!output) goto out; format_info = go_image_get_format_info (sel_fmt); sheet_object_write_image (so, (format_info? format_info->name: NULL), -1.0, output, &err); gsf_output_close (output); g_object_unref (output); if (err != NULL) go_cmd_context_error (GO_CMD_CONTEXT (wbcg), err); out: if (pixbuf) g_object_unref (pixbuf); g_free (uri); g_slist_free (l); }
/** * gnm_cell_combo_view_popdown: * @sov: #SheetObjectView * @activate_time: event time * * Open the popup window associated with @sov **/ void gnm_cell_combo_view_popdown (SheetObjectView *sov, guint32 activate_time) { GocItem *view = GOC_ITEM (sov); GnmPane *pane = GNM_PANE (view->canvas); SheetControlGUI *scg = pane->simple.scg; SheetObject *so = sheet_object_view_get_so (sov); Sheet const *sheet = sheet_object_get_sheet (so); GtkWidget *frame, *popup, *list, *container; int root_x, root_y; gboolean make_buttons = FALSE; GtkTreePath *clip = NULL, *select = NULL; GtkWindow *toplevel = wbcg_toplevel (scg_wbcg (scg)); GdkWindow *popup_window; GdkDevice *device; GnmRange const *merge; popup = gtk_window_new (GTK_WINDOW_POPUP); gtk_window_set_type_hint (GTK_WINDOW (popup), GDK_WINDOW_TYPE_HINT_COMBO); gtk_window_group_add_window (gtk_window_get_group (toplevel), GTK_WINDOW (popup)); go_gtk_window_set_transient (toplevel, GTK_WINDOW (popup)); gtk_window_set_resizable (GTK_WINDOW (popup), FALSE); gtk_window_set_decorated (GTK_WINDOW (popup), FALSE); gtk_window_set_screen (GTK_WINDOW (popup), gtk_widget_get_screen (GTK_WIDGET (toplevel))); list = ccombo_create_list (GNM_CCOMBO_VIEW (sov), so, &clip, &select, &make_buttons); gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (list), FALSE); g_object_set_data (G_OBJECT (list), SOV_ID, sov); frame = gtk_frame_new (NULL); gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT); #if 0 range_dump (&so->anchor.cell_bound, ""); g_printerr (" : so = %p, view = %p\n", so, view); #endif if (clip != NULL) { GtkWidget *sw = gtk_scrolled_window_new ( gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (list)), gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (list))); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); g_object_set_data_full (G_OBJECT (list), "clip", clip, (GDestroyNotify)gtk_tree_path_free); gtk_container_add (GTK_CONTAINER (sw), list); /* * Do the sizing in a realize handler as newer versions of * gtk+ give us zero sizes until then. */ g_signal_connect_after (list, "realize", G_CALLBACK (cb_realize_treeview), sw); container = sw; } else container = list; if (make_buttons) { GtkWidget *vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); GtkWidget *hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); GtkWidget *button; button = gtk_button_new_from_stock (GTK_STOCK_CANCEL); g_signal_connect_swapped (button, "clicked", G_CALLBACK (cb_ccombo_cancel_button), list); gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 6); button = gtk_button_new_from_stock (GTK_STOCK_OK); g_signal_connect_swapped (button, "clicked", G_CALLBACK (cb_ccombo_ok_button), list); gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 6); gtk_box_pack_start (GTK_BOX (vbox), container, FALSE, TRUE, 6); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 6); container = vbox; } gtk_container_add (GTK_CONTAINER (frame), container); /* do the popup */ gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (pane)), &root_x, &root_y); if (sheet->text_is_rtl) { GtkAllocation pa; gtk_widget_get_allocation (GTK_WIDGET (pane), &pa); root_x += pa.width; root_x -= scg_colrow_distance_get (scg, TRUE, pane->first.col, so->anchor.cell_bound.start.col + 1); } else root_x += scg_colrow_distance_get (scg, TRUE, pane->first.col, so->anchor.cell_bound.start.col); merge = gnm_sheet_merge_is_corner (sheet, &(so->anchor.cell_bound.start)); gtk_window_move (GTK_WINDOW (popup), root_x, root_y + scg_colrow_distance_get (scg, FALSE, pane->first.row, so->anchor.cell_bound.start.row + ((merge == NULL) ? 1 : range_height (merge)))); gtk_container_add (GTK_CONTAINER (popup), frame); g_signal_connect (popup, "key_press_event", G_CALLBACK (cb_ccombo_key_press), list); g_signal_connect (popup, "button_press_event", G_CALLBACK (cb_ccombo_button_press), list); g_signal_connect_after (popup, "button_release_event", G_CALLBACK (cb_ccombo_button_release), list); g_signal_connect (list, "motion_notify_event", G_CALLBACK (cb_ccombo_list_motion), list); g_signal_connect (list, "button_press_event", G_CALLBACK (cb_ccombo_list_button_press), popup); gtk_widget_show_all (popup); /* after we show the window setup the selection (showing the list * clears the selection) */ if (select != NULL) { gtk_tree_selection_select_path ( gtk_tree_view_get_selection (GTK_TREE_VIEW (list)), select); gtk_tree_view_set_cursor (GTK_TREE_VIEW (list), select, NULL, FALSE); gtk_tree_path_free (select); } gtk_widget_grab_focus (popup); gtk_widget_grab_focus (GTK_WIDGET (list)); ccombo_focus_change (GTK_WIDGET (list), TRUE); popup_window = gtk_widget_get_window (popup); device = gtk_get_current_event_device (); if (0 == gdk_device_grab (device, popup_window, GDK_OWNERSHIP_APPLICATION, TRUE, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK, NULL, activate_time)) { if (0 == gdk_device_grab (gdk_device_get_associated_device (device), popup_window, GDK_OWNERSHIP_APPLICATION, TRUE, GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK, NULL, activate_time)) gtk_grab_add (popup); else gdk_device_ungrab (device, activate_time); } }
static int item_grid_button_pressed (GocItem *item, int button, double x_, double y_) { GnmItemGrid *ig = GNM_ITEM_GRID (item); GocCanvas *canvas = item->canvas; GnmPane *pane = GNM_PANE (canvas); SheetControlGUI *scg = ig->scg; WBCGtk *wbcg = scg_wbcg (scg); SheetControl *sc = (SheetControl *)scg; SheetView *sv = sc_view (sc); Sheet *sheet = sv_sheet (sv); GnmCellPos pos; gboolean edit_showed_dialog; gboolean already_selected; GdkEvent *event = goc_canvas_get_cur_event (item->canvas); gint64 x = x_ * canvas->pixels_per_unit, y = y_ * canvas->pixels_per_unit; gnm_pane_slide_stop (pane); pos.col = gnm_pane_find_col (pane, x, NULL); pos.row = gnm_pane_find_row (pane, y, NULL); /* GnmRange check first */ if (pos.col >= gnm_sheet_get_max_cols (sheet)) return TRUE; if (pos.row >= gnm_sheet_get_max_rows (sheet)) return TRUE; /* A new object is ready to be realized and inserted */ if (wbcg->new_object != NULL) return ig_obj_create_begin (ig, button, x, y); /* If we are not configuring an object then clicking on the sheet * ends the edit. */ if (scg->selected_objects == NULL) wbcg_focus_cur_scg (wbcg); else if (wbc_gtk_get_guru (wbcg) == NULL) scg_mode_edit (scg); /* If we were already selecting a range of cells for a formula, * reset the location to a new place, or extend the selection. */ if (button == 1 && scg->rangesel.active) { ig->selecting = GNM_ITEM_GRID_SELECTING_FORMULA_RANGE; if (event->button.state & GDK_SHIFT_MASK) scg_rangesel_extend_to (scg, pos.col, pos.row); else scg_rangesel_bound (scg, pos.col, pos.row, pos.col, pos.row); gnm_pane_slide_init (pane); gnm_simple_canvas_grab (item, GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, NULL, gdk_event_get_time (event)); return TRUE; } /* If the user is editing a formula (wbcg_rangesel_possible) then we * enable the dynamic cell selection mode. */ if (button == 1 && wbcg_rangesel_possible (wbcg)) { scg_rangesel_start (scg, pos.col, pos.row, pos.col, pos.row); ig->selecting = GNM_ITEM_GRID_SELECTING_FORMULA_RANGE; gnm_pane_slide_init (pane); gnm_simple_canvas_grab (item, GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, NULL, gdk_event_get_time (event)); return TRUE; } /* While a guru is up ignore clicks */ if (wbc_gtk_get_guru (wbcg) != NULL) return TRUE; /* This was a regular click on a cell on the spreadsheet. Select it. * but only if the entered expression is valid */ if (!wbcg_edit_finish (wbcg, WBC_EDIT_ACCEPT, &edit_showed_dialog)) return TRUE; if (button == 1 && !sheet_selection_is_allowed (sheet, &pos)) return TRUE; /* Button == 1 is used to trigger hyperlinks (and possibly similar */ /* special cases. Otherwise button == 2 should behave exactly like */ /* button == 1. See bug #700792 */ /* buttons 1 and 2 will always change the selection, the other buttons will * only effect things if the target is not already selected. */ already_selected = sv_is_pos_selected (sv, pos.col, pos.row); if (button == 1 || button == 2 || !already_selected) { if (!(event->button.state & (GDK_CONTROL_MASK|GDK_SHIFT_MASK))) sv_selection_reset (sv); if ((event->button.button != 1 && event->button.button != 2) || !(event->button.state & GDK_SHIFT_MASK) || sv->selections == NULL) { sv_selection_add_pos (sv, pos.col, pos.row, (already_selected && (event->button.state & GDK_CONTROL_MASK)) ? GNM_SELECTION_MODE_REMOVE : GNM_SELECTION_MODE_ADD); sv_make_cell_visible (sv, pos.col, pos.row, FALSE); } else sv_selection_extend_to (sv, pos.col, pos.row); sheet_update (sheet); } if (edit_showed_dialog) return TRUE; /* we already ignored the button release */ switch (button) { case 1: case 2: { guint32 double_click_time; /* * If the second click is on a different cell than the * first one this cannot be a double-click */ if (already_selected) { g_object_get (gtk_widget_get_settings (GTK_WIDGET (canvas)), "gtk-double-click-time", &double_click_time, NULL); if ((ig->last_click_time + double_click_time) > gdk_event_get_time (event) && wbcg_edit_start (wbcg, FALSE, FALSE)) { break; } } ig->last_click_time = gdk_event_get_time (event); ig->selecting = GNM_ITEM_GRID_SELECTING_CELL_RANGE; gnm_pane_slide_init (pane); gnm_simple_canvas_grab (item, GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, NULL, gdk_event_get_time (event)); break; } case 3: scg_context_menu (scg, event, FALSE, FALSE); break; default : break; } return TRUE; }
static gboolean item_grid_draw_region (GocItem const *item, cairo_t *cr, double x_0, double y_0, double x_1, double y_1) { GocCanvas *canvas = item->canvas; double scale = canvas->pixels_per_unit; gint64 x0 = x_0 * scale, y0 = y_0 * scale, x1 = x_1 * scale, y1 = y_1 * scale; gint width = x1 - x0; gint height = y1 - y0; GnmPane *pane = GNM_PANE (canvas); Sheet const *sheet = scg_sheet (pane->simple.scg); WBCGtk *wbcg = scg_wbcg (pane->simple.scg); GnmCell const * const edit_cell = wbcg->editing_cell; GnmItemGrid *ig = GNM_ITEM_GRID (item); ColRowInfo const *ri = NULL, *next_ri = NULL; int const dir = sheet->text_is_rtl ? -1 : 1; SheetView const *sv = scg_view (ig->scg); WorkbookView *wbv = sv_wbv (sv); gboolean show_function_cell_markers = wbv->show_function_cell_markers; gboolean show_extension_markers = wbv->show_extension_markers; /* we use the selected background color from an entry for selected cells */ GtkWidget *entry = gtk_entry_new (); GtkStyleContext *ctxt = gtk_widget_get_style_context (entry); /* To ensure that far and near borders get drawn we pretend to draw +-2 * pixels around the target area which would include the surrounding * borders if necessary */ /* TODO : there is an opportunity to speed up the redraw loop by only * painting the borders of the edges and not the content. * However, that feels like more hassle that it is worth. Look into this someday. */ int x; gint64 y, start_x, offset; int col, row, n, start_col, end_col; int start_row = gnm_pane_find_row (pane, y0-2, &y); int end_row = gnm_pane_find_row (pane, y1+2, NULL); gint64 const start_y = y - canvas->scroll_y1 * scale; GnmStyleRow sr, next_sr; GnmStyle const **styles; GnmBorder const **borders, **prev_vert; GnmBorder const *none = sheet->hide_grid ? NULL : gnm_style_border_none (); GnmRange view; GSList *merged_active, *merged_active_seen, *merged_used, *merged_unused, *ptr, **lag; int *colwidths = NULL; gboolean const draw_selection = ig->scg->selected_objects == NULL && wbcg->new_object == NULL; start_col = gnm_pane_find_col (pane, x0-2, &start_x); end_col = gnm_pane_find_col (pane, x1+2, NULL); g_return_val_if_fail (start_col <= end_col, TRUE); #if 0 g_printerr ("%s:", cell_coord_name (start_col, start_row)); g_printerr ("%s <= %ld vs ???", cell_coord_name(end_col, end_row), (long)y); g_printerr (" [%s]\n", cell_coord_name (ig->bound.end.col, ig->bound.end.row)); #endif /* clip to bounds */ if (end_col > ig->bound.end.col) end_col = ig->bound.end.col; if (end_row > ig->bound.end.row) end_row = ig->bound.end.row; /* Skip any hidden cols/rows at the start */ for (; start_col <= end_col ; ++start_col) { ri = sheet_col_get_info (sheet, start_col); if (ri->visible) break; } for (; start_row <= end_row ; ++start_row) { ri = sheet_row_get_info (sheet, start_row); if (ri->visible) break; } /* if everything is hidden no need to draw */ if (end_col < ig->bound.start.col || start_col > ig->bound.end.col || end_row < ig->bound.start.row || start_row > ig->bound.end.row) return TRUE; /* Respan all rows that need it. */ for (row = start_row; row <= end_row; row++) { ColRowInfo const *ri = sheet_row_get_info (sheet, row); if (ri->visible && ri->needs_respan) row_calc_spans ((ColRowInfo *)ri, row, sheet); } sheet_style_update_grid_color (sheet); /* Fill entire region with default background (even past far edge) */ cairo_save (cr); if (canvas->direction == GOC_DIRECTION_LTR) gtk_render_background (goc_item_get_style_context (item), cr, x0 - canvas->scroll_x1 * scale, y0 - canvas->scroll_y1 * scale, width, height); else gtk_render_background (goc_item_get_style_context (item), cr, canvas->width - x0 + canvas->scroll_x1 * scale - width, y0 - canvas->scroll_y1 * scale, width, height); cairo_restore (cr); /* Get ordered list of merged regions */ merged_active = merged_active_seen = merged_used = NULL; merged_unused = gnm_sheet_merge_get_overlap (sheet, range_init (&view, start_col, start_row, end_col, end_row)); /* * allocate a single blob of memory for all 8 arrays of pointers. * - 6 arrays of n GnmBorder const * * - 2 arrays of n GnmStyle const * * * then alias the arrays for easy access so that array [col] is valid * for all elements start_col-1 .. end_col+1 inclusive. * Note that this means that in some cases array [-1] is legal. */ n = end_col - start_col + 3; /* 1 before, 1 after, 1 fencepost */ style_row_init (&prev_vert, &sr, &next_sr, start_col, end_col, g_alloca (n * 8 * sizeof (gpointer)), sheet->hide_grid); /* load up the styles for the first row */ next_sr.row = sr.row = row = start_row; sheet_style_get_row (sheet, &sr); /* Collect the column widths */ colwidths = g_alloca (n * sizeof (int)); colwidths -= start_col; for (col = start_col; col <= end_col; col++) { ColRowInfo const *ci = sheet_col_get_info (sheet, col); colwidths[col] = ci->visible ? ci->size_pixels : -1; } goc_canvas_c2w (canvas, start_x / scale, 0, &x, NULL); start_x = x; for (y = start_y; row <= end_row; row = sr.row = next_sr.row, ri = next_ri) { /* Restore the set of ranges seen, but still active. * Reinverting list to maintain the original order */ g_return_val_if_fail (merged_active == NULL, TRUE); #if DEBUG_SELECTION_PAINT g_printerr ("row = %d (startcol = %d)\n", row, start_col); #endif while (merged_active_seen != NULL) { GSList *tmp = merged_active_seen->next; merged_active_seen->next = merged_active; merged_active = merged_active_seen; merged_active_seen = tmp; MERGE_DEBUG (merged_active->data, " : seen -> active\n"); } /* find the next visible row */ while (1) { ++next_sr.row; if (next_sr.row <= end_row) { next_ri = sheet_row_get_info (sheet, next_sr.row); if (next_ri->visible) { sheet_style_get_row (sheet, &next_sr); break; } } else { for (col = start_col ; col <= end_col; ++col) next_sr.vertical [col] = next_sr.bottom [col] = none; break; } } /* look for merges that start on this row, on the first painted row * also check for merges that start above. */ view.start.row = row; lag = &merged_unused; for (ptr = merged_unused; ptr != NULL; ) { GnmRange * const r = ptr->data; if (r->start.row <= row) { GSList *tmp = ptr; ptr = *lag = tmp->next; if (r->end.row < row) { tmp->next = merged_used; merged_used = tmp; MERGE_DEBUG (r, " : unused -> used\n"); } else { ColRowInfo const *ci = sheet_col_get_info (sheet, r->start.col); g_slist_free_1 (tmp); merged_active = g_slist_insert_sorted (merged_active, r, (GCompareFunc)merged_col_cmp); MERGE_DEBUG (r, " : unused -> active\n"); if (ci->visible) item_grid_draw_merged_range (cr, ig, start_x, y, &view, r, draw_selection, ctxt); } } else { lag = &(ptr->next); ptr = ptr->next; } } for (col = start_col, x = start_x; col <= end_col ; col++) { GnmStyle const *style; CellSpanInfo const *span; ColRowInfo const *ci = sheet_col_get_info (sheet, col); #if DEBUG_SELECTION_PAINT g_printerr ("col [%d] = %d\n", col, x); #endif if (!ci->visible) { if (merged_active != NULL) { GnmRange const *r = merged_active->data; if (r->end.col == col) { ptr = merged_active; merged_active = merged_active->next; if (r->end.row <= row) { ptr->next = merged_used; merged_used = ptr; MERGE_DEBUG (r, " : active2 -> used\n"); } else { ptr->next = merged_active_seen; merged_active_seen = ptr; MERGE_DEBUG (r, " : active2 -> seen\n"); } } } continue; } /* Skip any merged regions */ if (merged_active != NULL) { GnmRange const *r = merged_active->data; if (r->start.col <= col) { gboolean clear_top, clear_bottom = FALSE; int i, first = r->start.col; int last = r->end.col; ptr = merged_active; merged_active = merged_active->next; if (r->end.row <= row) { ptr->next = merged_used; merged_used = ptr; MERGE_DEBUG (r, " : active -> used\n"); /* in case something managed the bottom of a merge */ if (r->end.row < row) goto plain_draw; } else { ptr->next = merged_active_seen; merged_active_seen = ptr; MERGE_DEBUG (r, " : active -> seen\n"); if (next_sr.row <= r->end.row) clear_bottom = TRUE; } x += dir * scg_colrow_distance_get ( pane->simple.scg, TRUE, col, last+1); col = last; if (first < start_col) { first = start_col; sr.vertical [first] = NULL; } if (last > end_col) { last = end_col; sr.vertical [last+1] = NULL; } clear_top = (r->start.row != row); /* Clear the borders */ for (i = first ; i <= last ; i++) { if (clear_top) sr.top [i] = NULL; if (clear_bottom) sr.bottom [i] = NULL; if (i > first) sr.vertical [i] = NULL; } continue; } } plain_draw : /* a quick hack to deal with 142267 */ if (dir < 0) x -= ci->size_pixels; style = sr.styles [col]; item_grid_draw_background (cr, ig, style, col, row, x, y, ci->size_pixels, ri->size_pixels, draw_selection, ctxt); /* Is this part of a span? * 1) There are cells allocated in the row * (indicated by ri->spans != NULL) * 2) Look in the rows hash table to see if * there is a span descriptor. */ if (NULL == ri->spans || NULL == (span = row_span_get (ri, col))) { /* If it is being edited pretend it is empty to * avoid problems with long cells' * contents extending past the edge of the edit * box. Ignore blanks too. */ GnmCell const *cell = sheet_cell_get (sheet, col, row); if (!gnm_cell_is_empty (cell) && cell != edit_cell) { if (show_function_cell_markers) draw_function_marker (ig, cell, cr, x, y, ci->size_pixels, ri->size_pixels, dir); cell_draw (cell, cr, x, y, ci->size_pixels, ri->size_pixels, -1, show_extension_markers); } /* Only draw spaning cells after all the backgrounds * that we are going to draw have been drawn. No need * to draw the edit cell, or blanks. */ } else if (edit_cell != span->cell && (col == span->right || col == end_col)) { GnmCell const *cell = span->cell; int const start_span_col = span->left; int const end_span_col = span->right; int real_x = x; ColRowInfo const *cell_col = sheet_col_get_info (sheet, cell->pos.col); int center_offset = cell_col->size_pixels/2; int tmp_width = ci->size_pixels; if (col != cell->pos.col) style = sheet_style_get (sheet, cell->pos.col, row); /* x, y are relative to this cell origin, but the cell * might be using columns to the left (if it is set to right * justify or center justify) compute the pixel difference */ if (dir > 0 && start_span_col != cell->pos.col) center_offset += scg_colrow_distance_get ( pane->simple.scg, TRUE, start_span_col, cell->pos.col); else if (dir < 0 && end_span_col != cell->pos.col) center_offset += scg_colrow_distance_get ( pane->simple.scg, TRUE, cell->pos.col, end_span_col); if (start_span_col != col) { offset = scg_colrow_distance_get ( pane->simple.scg, TRUE, start_span_col, col); tmp_width += offset; if (dir > 0) real_x -= offset; sr.vertical [col] = NULL; } if (end_span_col != col) { offset = scg_colrow_distance_get ( pane->simple.scg, TRUE, col+1, end_span_col + 1); tmp_width += offset; if (dir < 0) real_x -= offset; } if (show_function_cell_markers) draw_function_marker (ig, cell, cr, real_x, y, tmp_width, ri->size_pixels, dir); cell_draw (cell, cr, real_x, y, tmp_width, ri->size_pixels, center_offset, show_extension_markers); } else if (col != span->left) sr.vertical [col] = NULL; if (dir > 0) x += ci->size_pixels; } gnm_style_borders_row_draw (prev_vert, &sr, cr, start_x, y, y+ri->size_pixels, colwidths, TRUE, dir); /* In case there were hidden merges that trailed off the end */ while (merged_active != NULL) { GnmRange const *r = merged_active->data; ptr = merged_active; merged_active = merged_active->next; if (r->end.row <= row) { ptr->next = merged_used; merged_used = ptr; MERGE_DEBUG (r, " : active3 -> used\n"); } else { ptr->next = merged_active_seen; merged_active_seen = ptr; MERGE_DEBUG (r, " : active3 -> seen\n"); } } /* roll the pointers */ borders = prev_vert; prev_vert = sr.vertical; sr.vertical = next_sr.vertical; next_sr.vertical = borders; borders = sr.top; sr.top = sr.bottom; sr.bottom = next_sr.top = next_sr.bottom; next_sr.bottom = borders; styles = sr.styles; sr.styles = next_sr.styles; next_sr.styles = styles; y += ri->size_pixels; } if (ig->bound.start.row > 0 && start_y < 1) ig_cairo_draw_bound (ig, cr, start_x, 1, x, 1); if (ig->bound.start.col > 0) { if (canvas->direction == GOC_DIRECTION_RTL && start_x >= goc_canvas_get_width (canvas)) { x = goc_canvas_get_width (canvas); ig_cairo_draw_bound (ig, cr, x, start_y, x, y); } else if (canvas->direction == GOC_DIRECTION_LTR && start_x < 1) ig_cairo_draw_bound (ig, cr, 1, start_y, 1, y); } g_object_ref_sink (entry); g_object_unref (entry); g_slist_free (merged_used); /* merges with bottom in view */ g_slist_free (merged_active_seen); /* merges with bottom the view */ g_slist_free (merged_unused); /* merges in hidden rows */ g_return_val_if_fail (merged_active == NULL, TRUE); return TRUE; }