? src/workbook-control-gui.c.mine ? src/dialogs/dialog-sheet-order.c.mine Index: ChangeLog =================================================================== RCS file: /cvs/gnome/gnumeric/ChangeLog,v retrieving revision 1.2738 diff -u -3 -p -r1.2738 ChangeLog --- ChangeLog 28 Feb 2003 21:14:40 -0000 1.2738 +++ ChangeLog 2 Mar 2003 22:49:18 -0000 @@ -1,3 +1,18 @@ +2003-03-02 Lutz Mueller + + * src/commands.[c,h] (cmd_delete_sheet, cmd_insert_sheet): New. + * src/sheet.[c,h] (sheet_dup): Additional parameter to make it + possible to duplicate a sheet in another workbook. + * workbook.c: (workbook_sheet_attach) If sheet should be attached + after NULL, _pre_pend it. Otherwise, you can't prepend any sheets. + (workbook_sheet_detach): Don't destroy the sheet. Perhaps the + caller still needs it. + * src/stf.c: Call sheet_destroy after workbook_sheet_detach. + Update to reflect changes in workbook_sheet_attach. + * src/xml-io.c: Update to reflect changes in workbook_sheet_attach. + * src/workbook-control-gui.c: Enable drag & drop of sheets between + workbooks. + 2003-02-28 Morten Welinder * src/mathfunc.c (random_01): Get larger chunks of randomness. Index: src/commands.c =================================================================== RCS file: /cvs/gnome/gnumeric/src/commands.c,v retrieving revision 1.323 diff -u -3 -p -r1.323 commands.c --- src/commands.c 23 Feb 2003 23:26:14 -0000 1.323 +++ src/commands.c 2 Mar 2003 22:49:20 -0000 @@ -755,6 +755,7 @@ command_undo_sheet_delete (Sheet* sheet) } sheet_deps_destroy (sheet); workbook_sheet_detach (wb, sheet); + sheet_destroy (sheet); return (TRUE); } @@ -4572,6 +4573,156 @@ cmd_rename_sheet (WorkbookControl *wbc, return cmd_reorganize_sheets (wbc, NULL, NULL, changed_names, new_names, NULL, NULL, NULL, NULL, NULL, NULL); +} + +/******************************************************************/ + +#define CMD_DELETE_SHEET_TYPE (cmd_delete_sheet_get_type ()) +#define CMD_DELETE_SHEET(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_DELETE_SHEET_TYPE, CmdDeleteSheet)) + +typedef struct +{ + GnumericCommand cmd; + + Workbook *wb; + Sheet *sheet; + Sheet *after; + +} CmdDeleteSheet; + +GNUMERIC_MAKE_COMMAND (CmdDeleteSheet, cmd_delete_sheet); + +static gboolean +cmd_delete_sheet_undo (GnumericCommand *cmd, G_GNUC_UNUSED WorkbookControl *wbc) +{ + CmdDeleteSheet *me = CMD_DELETE_SHEET (cmd); + + workbook_sheet_attach (me->wb, me->sheet, me->after); + + return FALSE; +} + +static gboolean +cmd_delete_sheet_redo (GnumericCommand *cmd, G_GNUC_UNUSED WorkbookControl *wbc) +{ + CmdDeleteSheet *me = CMD_DELETE_SHEET (cmd); + + workbook_sheet_detach (me->wb, me->sheet); + + return FALSE; +} + +static void +cmd_delete_sheet_finalize (GObject *cmd) +{ + CmdDeleteSheet *me = CMD_DELETE_SHEET (cmd); + int i; + + /* Destroy the sheet only if it is in no workbook. */ + for (i = workbook_sheet_count (me->wb); i > 0; i--) + if (me->sheet == workbook_sheet_by_index (me->wb, i - 1)) + break; + if (!i) + sheet_destroy (me->sheet); + + gnumeric_command_finalize (cmd); +} + +gboolean +cmd_delete_sheet (WorkbookControl *wbc, Sheet *sheet) +{ + GObject *obj; + CmdDeleteSheet *me; + int i; + + obj = g_object_new (CMD_DELETE_SHEET_TYPE, NULL); + me = CMD_DELETE_SHEET (obj); + + me->wb = wb_control_workbook (wbc); + me->sheet = sheet; + for (i = workbook_sheet_count (me->wb); i > 0; i--) + if (sheet == workbook_sheet_by_index (me->wb, i - 1)) + break; + me->after = (i > 1 ? workbook_sheet_by_index (me->wb, i - 2) : NULL); + + me->cmd.sheet = sheet; + me->cmd.size = 1; + me->cmd.cmd_descriptor = g_strdup_printf (_("Delete sheet")); + + return command_push_undo (wbc, obj); +} + +/******************************************************************/ + +#define CMD_INSERT_SHEET_TYPE (cmd_insert_sheet_get_type ()) +#define CMD_INSERT_SHEET(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_INSERT_SHEET_TYPE, CmdInsertSheet)) + +typedef struct +{ + GnumericCommand cmd; + + Workbook *wb; + Sheet *sheet; + Sheet *after; + +} CmdInsertSheet; + +GNUMERIC_MAKE_COMMAND (CmdInsertSheet, cmd_insert_sheet); + +static gboolean +cmd_insert_sheet_undo (GnumericCommand *cmd, G_GNUC_UNUSED WorkbookControl *wbc) +{ + CmdInsertSheet *me = CMD_INSERT_SHEET (cmd); + + workbook_sheet_detach (me->wb, me->sheet); + + return FALSE; +} + +static gboolean +cmd_insert_sheet_redo (GnumericCommand *cmd, G_GNUC_UNUSED WorkbookControl *wbc) +{ + CmdInsertSheet *me = CMD_INSERT_SHEET (cmd); + + workbook_sheet_attach (me->wb, me->sheet, me->after); + + return FALSE; +} + +static void +cmd_insert_sheet_finalize (GObject *cmd) +{ + CmdInsertSheet *me = CMD_INSERT_SHEET (cmd); + int i; + + /* Destroy the sheet only if it is in no workbook. */ + for (i = workbook_sheet_count (me->wb); i > 0; i--) + if (me->sheet == workbook_sheet_by_index (me->wb, i - 1)) + break; + if (!i) + sheet_destroy (me->sheet); + + gnumeric_command_finalize (cmd); +} + +gboolean +cmd_insert_sheet (WorkbookControl *wbc, Sheet *sheet, Sheet *after) +{ + GObject *obj; + CmdInsertSheet *me; + + obj = g_object_new (CMD_INSERT_SHEET_TYPE, NULL); + me = CMD_INSERT_SHEET (obj); + + me->wb = wb_control_workbook (wbc); + me->sheet = sheet; + me->after = after; + + me->cmd.sheet = sheet; + me->cmd.size = 1; + me->cmd.cmd_descriptor = g_strdup_printf (_("Insert sheet")); + + return command_push_undo (wbc, obj); } /******************************************************************/ Index: src/commands.h =================================================================== RCS file: /cvs/gnome/gnumeric/src/commands.h,v retrieving revision 1.75 diff -u -3 -p -r1.75 commands.h --- src/commands.h 21 Nov 2002 17:54:41 -0000 1.75 +++ src/commands.h 2 Mar 2003 22:49:21 -0000 @@ -97,6 +97,8 @@ gboolean cmd_reorganize_sheets (Workbook GSList *protection_changed, GSList *new_locks); gboolean cmd_rename_sheet (WorkbookControl *wbc, Sheet *sheet, char const *old_name, char const *new_name); +gboolean cmd_delete_sheet (WorkbookControl *wbc, Sheet *s); +gboolean cmd_insert_sheet (WorkbookControl *wbc, Sheet *s, Sheet *after); gboolean cmd_set_comment (WorkbookControl *wbc, Sheet *sheet, CellPos const *pos, const char *new_text); Index: src/sheet.c =================================================================== RCS file: /cvs/gnome/gnumeric/src/sheet.c,v retrieving revision 1.662 diff -u -3 -p -r1.662 sheet.c --- src/sheet.c 23 Feb 2003 23:26:14 -0000 1.662 +++ src/sheet.c 2 Mar 2003 22:49:22 -0000 @@ -3916,18 +3916,19 @@ sheet_clone_cells (Sheet const *src, She /** * sheet_dup : * @src : + * @wb : */ Sheet * -sheet_dup (Sheet const *src) +sheet_dup (Sheet const *src, Workbook *wb) { - Workbook *wb; Sheet *dst; char *name; g_return_val_if_fail (IS_SHEET (src), NULL); g_return_val_if_fail (src->workbook !=NULL, NULL); - wb = src->workbook; + if (!wb) + wb = src->workbook; name = workbook_sheet_get_free_name (wb, src->name_unquoted, TRUE, TRUE); dst = sheet_new (wb, name); Index: src/sheet.h =================================================================== RCS file: /cvs/gnome/gnumeric/src/sheet.h,v retrieving revision 1.328 diff -u -3 -p -r1.328 sheet.h --- src/sheet.h 28 Jan 2003 15:56:41 -0000 1.328 +++ src/sheet.h 2 Mar 2003 22:49:22 -0000 @@ -73,7 +73,8 @@ struct _Sheet { #define IS_SHEET(x) (((x) != NULL) && ((x)->signature == SHEET_SIGNATURE)) Sheet *sheet_new (Workbook *wb, char const *name); -Sheet *sheet_dup (Sheet const *source_sheet); +Sheet *sheet_dup (Sheet const *source_sheet, + Workbook *dest_workbook); void sheet_destroy (Sheet *sheet); void sheet_destroy_contents (Sheet *sheet); void sheet_rename (Sheet *sheet, char const *new_name); Index: src/stf.c =================================================================== RCS file: /cvs/gnome/gnumeric/src/stf.c,v retrieving revision 1.63 diff -u -3 -p -r1.63 stf.c --- src/stf.c 4 Feb 2003 05:19:01 -0000 1.63 +++ src/stf.c 2 Mar 2003 22:49:23 -0000 @@ -202,6 +202,7 @@ stf_read_workbook (GnmFileOpener const * char *data; Sheet *sheet; Workbook *book; + int count; data = stf_preparse (COMMAND_CONTEXT (context), input); if (!data) @@ -215,15 +216,19 @@ stf_read_workbook (GnmFileOpener const * name = g_path_get_basename (gsf_input_name (input)); book = wb_view_workbook (wbv); sheet = sheet_new (book, name); - workbook_sheet_attach (book, sheet, NULL); + count = workbook_sheet_count (book); + workbook_sheet_attach (book, sheet, + count ? workbook_sheet_by_index (book, count - 1) : NULL); g_free (name); dialogresult = stf_dialog (WORKBOOK_CONTROL_GUI (context->impl), name, data); if (dialogresult != NULL && stf_store_results (dialogresult, sheet, 0, 0)) { workbook_recalc (book); sheet_queue_respan (sheet, 0, SHEET_MAX_ROWS-1); - } else + } else { workbook_sheet_detach (book, sheet); + sheet_destroy (sheet); + } g_free (data); if (dialogresult != NULL) @@ -343,7 +348,7 @@ stf_read_workbook_auto_csvtab (GnmFileOp StfParseOptions_t *po; char *pos; unsigned int comma = 0, tab = 0, lines = 0; - int i; + int i, count; book = wb_view_workbook (wbv); data = stf_preparse (COMMAND_CONTEXT (context), input); @@ -361,7 +366,9 @@ stf_read_workbook_auto_csvtab (GnmFileOp name = g_path_get_basename (gsf_input_name (input)); sheet = sheet_new (book, name); - workbook_sheet_attach (book, sheet, NULL); + count = workbook_sheet_count (book); + workbook_sheet_attach (book, sheet, + count ? workbook_sheet_by_index (book, count - 1) : NULL); po = stf_parse_options_new (); @@ -381,6 +388,7 @@ stf_read_workbook_auto_csvtab (GnmFileOp if (!stf_parse_sheet (po, data, sheet, 0, 0)) { workbook_sheet_detach (book, sheet); + sheet_destroy (sheet); g_free (data); stf_parse_options_free (po); gnumeric_error_read (COMMAND_CONTEXT (context), Index: src/workbook-control-gui.c =================================================================== RCS file: /cvs/gnome/gnumeric/src/workbook-control-gui.c,v retrieving revision 1.389 diff -u -3 -p -r1.389 workbook-control-gui.c --- src/workbook-control-gui.c 28 Jan 2003 15:56:41 -0000 1.389 +++ src/workbook-control-gui.c 2 Mar 2003 22:49:25 -0000 @@ -577,7 +577,7 @@ static void sheet_action_clone_sheet (GtkWidget *widget, SheetControlGUI *scg) { SheetControl *sc = (SheetControl *) scg; - Sheet *new_sheet = sheet_dup (sc->sheet); + Sheet *new_sheet = sheet_dup (sc->sheet, NULL); workbook_sheet_attach (sc->sheet->workbook, new_sheet, sc->sheet); sheet_set_dirty (new_sheet, TRUE); @@ -710,60 +710,89 @@ cb_sheet_label_drag_data_get (GtkWidget n_source = gtk_notebook_page_num_by_label (wbcg->notebook, widget); p_source = gtk_notebook_get_nth_page (wbcg->notebook, n_source); scg = g_object_get_data (G_OBJECT (p_source), SHEET_CONTROL_KEY); + g_return_if_fail (IS_SHEET_CONTROL_GUI (scg)); gtk_selection_data_set (selection_data, selection_data->target, - 8, (void *) scg, sizeof (scg)); + 8, (void *) scg, sizeof (scg)); } static void -cb_sheet_label_drag_data_received (GtkWidget *widget, GdkDragContext *context, +cb_sheet_label_drag_data_received (GtkWidget *w_dest, GdkDragContext *context, gint x, gint y, GtkSelectionData *data, guint info, guint time, - WorkbookControlGUI *wbcg) + WorkbookControlGUI *wbcg_dest) { - GtkWidget *w_source; - gint n_source, n_dest; - Sheet *sheet; - GSList *old_order= NULL, *new_order; - Workbook *wb; + GtkWidget *w_src, *window; + gint n_src, n_dest; + Sheet *sheet, *s_src, *s_dest; + GSList *old_order = NULL, *new_order; + Workbook *wb_dest, *wb_src; + WorkbookControlGUI *wbcg_src; + SheetControlGUI *scg_src; guint n, i; - g_return_if_fail (IS_WORKBOOK_CONTROL_GUI (wbcg)); - g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (IS_WORKBOOK_CONTROL_GUI (wbcg_dest)); - w_source = gtk_drag_get_source_widget (context); - n_source = gtk_notebook_page_num_by_label (wbcg->notebook, w_source); + /* Source */ + w_src = gtk_drag_get_source_widget (context); + scg_src = g_object_get_data (G_OBJECT (w_src), SHEET_CONTROL_KEY); + wbcg_src = scg_get_wbcg (scg_src); + n_src = gtk_notebook_page_num_by_label (wbcg_src->notebook, w_src); + s_src = sc_sheet (SHEET_CONTROL (scg_src)); + wb_src = wb_control_workbook (WORKBOOK_CONTROL (wbcg_src)); + + /* Destination */ + n_dest = gtk_notebook_page_num_by_label (wbcg_dest->notebook, w_dest); + wb_dest = wb_control_workbook (WORKBOOK_CONTROL (wbcg_dest)); /* * Is this a sheet of our workbook? If yes, we just reorder * the sheets. */ - if (n_source >= 0) { + if (wbcg_src == wbcg_dest) { /* Make a list of the current order. */ - wb = wb_control_workbook (WORKBOOK_CONTROL (wbcg)); - n = workbook_sheet_count (wb); + n = workbook_sheet_count (wb_src); for (i = 0; i < n; i++) { - sheet = workbook_sheet_by_index (wb, i); + sheet = workbook_sheet_by_index (wb_src, i); old_order = g_slist_append (old_order, sheet); } /* Make a list of the new order. */ new_order = g_slist_copy (old_order); - sheet = g_slist_nth_data (new_order, n_source); + sheet = g_slist_nth_data (new_order, n_src); new_order = g_slist_remove (new_order, sheet); - n_dest = gtk_notebook_page_num_by_label (wbcg->notebook, - widget); - new_order = g_slist_insert (new_order, sheet, n_dest); + new_order = g_slist_insert (new_order, sheet, + n_dest + ((x > w_dest->allocation.width / 2) ? 1 : 0)); /* Reorder the sheets! */ - cmd_reorganize_sheets (WORKBOOK_CONTROL (wbcg), old_order, + cmd_reorganize_sheets (WORKBOOK_CONTROL (wbcg_src), old_order, new_order, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); } else { - g_return_if_fail (IS_SHEET_CONTROL_GUI (data->data)); - - g_warning ("Not yet implemented!"); + /* + * Create a copy of the sheet and insert it at the + * right position. Then delete the original sheet. + */ + s_dest = sheet_dup (s_src, wb_dest); + for (i = workbook_sheet_count (wb_dest); i > 0; i--) { + sheet = workbook_sheet_by_index (wb_dest, i - 1); + if (!strcmp (sheet->name_unquoted, + s_src->name_unquoted)) + break; + } + if (!i) + sheet_rename (s_dest, s_src->name_unquoted); + if (!n_dest) { + if (x < w_dest->allocation.width / 2) + sheet = NULL; + else + sheet = workbook_sheet_by_index (wb_dest, 0); + } else + sheet = workbook_sheet_by_index (wb_dest, n_dest - + ((x > w_dest->allocation.width / 2) ? 0 : 1)); + cmd_insert_sheet (WORKBOOK_CONTROL (wbcg_dest), s_dest, sheet); + cmd_delete_sheet (WORKBOOK_CONTROL (wbcg_src), s_src); } } @@ -840,32 +869,39 @@ cb_sheet_label_drag_leave (GtkWidget *wi } static gboolean -cb_sheet_label_drag_motion (GtkWidget *widget, GdkDragContext *context, - gint x, gint y, guint time, WorkbookControlGUI *wbcg) +cb_sheet_label_drag_motion (GtkWidget *w_dest, GdkDragContext *context, + gint x, gint y, guint time, WorkbookControlGUI *wbcg_dest) { - GtkWidget *w_source, *arrow, *window; - gint n_source, n_dest, root_x, root_y, pos_x, pos_y; + GtkWidget *w_src, *arrow, *window; + gint n_src, n_dest, root_x, root_y, pos_x, pos_y; + SheetControlGUI *scg_src; + WorkbookControlGUI *wbcg_src; + + g_return_val_if_fail (IS_WORKBOOK_CONTROL_GUI (wbcg_dest), FALSE); + + /* Source */ + w_src = gtk_drag_get_source_widget (context); + scg_src = g_object_get_data (G_OBJECT (w_src), SHEET_CONTROL_KEY); + wbcg_src = scg_get_wbcg (scg_src); + n_src = gtk_notebook_page_num_by_label (wbcg_src->notebook, w_src); - g_return_val_if_fail (IS_WORKBOOK_CONTROL_GUI (wbcg), FALSE); - g_return_val_if_fail (IS_WORKBOOK_CONTROL_GUI (wbcg), FALSE); + /* Destination */ + n_dest = gtk_notebook_page_num_by_label (wbcg_dest->notebook, w_dest); /* Make sure we are really hovering over another label. */ - w_source = gtk_drag_get_source_widget (context); - n_source = gtk_notebook_page_num_by_label (wbcg->notebook, w_source); - n_dest = gtk_notebook_page_num_by_label (wbcg->notebook, widget); - arrow = g_object_get_data (G_OBJECT (w_source), "arrow"); - if (n_source == n_dest) { + arrow = g_object_get_data (G_OBJECT (w_src), "arrow"); + if ((wbcg_src == wbcg_dest) && (n_src == n_dest)) { gtk_widget_hide (arrow); return (FALSE); } /* Move the arrow to the correct position and show it. */ - window = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW); + window = gtk_widget_get_ancestor (w_dest, GTK_TYPE_WINDOW); gtk_window_get_position (GTK_WINDOW (window), &root_x, &root_y); - pos_x = root_x + widget->allocation.x; - pos_y = root_y + widget->allocation.y; - if (n_source < n_dest) - pos_x += widget->allocation.width; + pos_x = root_x + w_dest->allocation.x; + pos_y = root_y + w_dest->allocation.y; + if (x > w_dest->allocation.width / 2) + pos_x += w_dest->allocation.width; gtk_window_move (GTK_WINDOW (arrow), pos_x, pos_y); gtk_widget_show (arrow); @@ -908,6 +944,7 @@ wbcg_sheet_add (WorkbookControl *wbc, Sh scg->label = editable_label_new (sheet->name_unquoted, sheet->tab_color ? &sheet->tab_color->color : NULL, sheet->tab_text_color ? &sheet->tab_text_color->color : NULL); + g_object_set_data (G_OBJECT (scg->label), SHEET_CONTROL_KEY, scg); g_signal_connect_after (GTK_OBJECT (scg->label), "edit_finished", G_CALLBACK (cb_sheet_label_edit_finished), wbcg); @@ -2094,7 +2131,7 @@ cb_edit_duplicate_sheet (GtkWidget *widg { WorkbookControl *wbc = WORKBOOK_CONTROL (wbcg); Sheet *old_sheet = wb_control_cur_sheet (wbc); - Sheet *new_sheet = sheet_dup (old_sheet); + Sheet *new_sheet = sheet_dup (old_sheet, NULL); workbook_sheet_attach (wb_control_workbook (wbc), new_sheet, Index: src/workbook.c =================================================================== RCS file: /cvs/gnome/gnumeric/src/workbook.c,v retrieving revision 1.583 diff -u -3 -p -r1.583 workbook.c --- src/workbook.c 15 Jan 2003 17:02:02 -0000 1.583 +++ src/workbook.c 2 Mar 2003 22:49:26 -0000 @@ -172,6 +172,7 @@ workbook_finalize (GObject *wb_object) Sheet *sheet = ptr->data; workbook_sheet_detach (wb, sheet); + sheet_destroy (sheet); } g_list_free (sheets); @@ -924,7 +925,7 @@ workbook_sheet_by_name (Workbook const * * @new_sheet : * @insert_after : optional position. * - * Add @new_sheet to @wb, either placing it after @insert_after, or appending. + * Add @new_sheet to @wb, either placing it after @insert_after, or prepending. */ void workbook_sheet_attach (Workbook *wb, Sheet *new_sheet, @@ -941,7 +942,11 @@ workbook_sheet_attach (Workbook *wb, She workbook_sheet_index_update (wb, pos); } else { g_ptr_array_add (wb->sheets, new_sheet); - workbook_sheet_index_update (wb, workbook_sheet_count (wb) - 1); + memmove (wb->sheets->pdata + sizeof (gpointer), + wb->sheets->pdata, + sizeof (gpointer) * (wb->sheets->len - 1)); + g_ptr_array_index (wb->sheets, 0) = new_sheet; + workbook_sheet_index_update (wb, 0); } g_hash_table_insert (wb->sheet_hash_private, @@ -1026,7 +1031,6 @@ workbook_sheet_detach (Workbook *wb, She workbook_sheet_index_update (wb, sheet_index); sheet->index_in_wb = -1; g_hash_table_remove (wb->sheet_hash_private, sheet->name_case_insensitive); - sheet_destroy (sheet); post_sheet_index_change (wb); if (focus != NULL) @@ -1115,6 +1119,7 @@ workbook_sheet_delete (Sheet *sheet) /* All is fine, remove the sheet */ workbook_sheet_detach (wb, sheet); + sheet_destroy (sheet); g_signal_emit (G_OBJECT (wb), signals [SHEET_DELETED], 0); } Index: src/xml-io.c =================================================================== RCS file: /cvs/gnome/gnumeric/src/xml-io.c,v retrieving revision 1.386 diff -u -3 -p -r1.386 xml-io.c --- src/xml-io.c 24 Feb 2003 17:49:10 -0000 1.386 +++ src/xml-io.c 2 Mar 2003 22:49:35 -0000 @@ -3328,6 +3328,7 @@ xml_sheet_create (XmlParseContext *ctxt, "xml_sheet_create: invalid element type %s, 'Sheet' expected\n", node->name); } else { + int count; xmlChar *name = xml_node_get_cstr ( e_xml_get_child_by_name (node, CC2XML ("Name")), NULL); @@ -3340,9 +3341,11 @@ xml_sheet_create (XmlParseContext *ctxt, g_return_if_fail (name != NULL); + count = workbook_sheet_count (ctxt->wb); workbook_sheet_attach (ctxt->wb, - sheet_new (ctxt->wb, CXML2C (name)), - NULL); + sheet_new (ctxt->wb, CXML2C (name)), + count ? workbook_sheet_by_index (ctxt->wb, + count - 1) : NULL); xmlFree (name); } }