1 /* Dia -- a diagram creation/manipulation program
2  * Copyright (C) 1998 Alexander Larsson
3  *
4  * sheets_dialog_callbacks.c : a sheets and objects dialog
5  * Copyright (C) 2002 M.C. Nelson
6                       Steffen Macke
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21  *
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 #  include <config.h>
26 #endif
27 
28 #include <errno.h>
29 #include <string.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #ifdef HAVE_UNISTD_H
33 #include <unistd.h>
34 #endif
35 #include <time.h>
36 #ifdef HAVE_UTIME_H
37 #include <utime.h>
38 #else
39 /* isn't this placement common ? */
40 #include <sys/utime.h>
41 #ifdef G_OS_WIN32
42 #  define utime(n,b) _utime(n,b)
43 #  define utim_buf _utimbuf
44 #endif
45 #endif
46 
47 #include <glib/gstdio.h>
48 #include <gmodule.h>
49 
50 #undef GTK_DISABLE_DEPRECATED /* GtkOptionMenu */
51 #ifdef GNOME
52 #include <gnome.h>
53 #else
54 #include <gtk/gtk.h>
55 #endif
56 
57 #include <libxml/tree.h>
58 #include <libxml/parser.h>
59 #include <libxml/xmlmemory.h>
60 
61 #include "gtkwrapbox.h"
62 
63 #include "dia_dirs.h"
64 #include "dia_xml_libxml.h"
65 #include "plug-ins.h"
66 #include "object.h"
67 
68 #include "interface.h"
69 #include "message.h"
70 #include "sheets.h"
71 #include "sheets_dialog_callbacks.h"
72 #include "sheets_dialog.h"
73 
74 #include "pixmaps/line_break.xpm"
75 #include "intl.h"
76 
77 static GSList *radio_group = NULL;
78 
79 static void
sheets_dialog_hide(void)80 sheets_dialog_hide(void)
81 {
82   gtk_widget_hide(sheets_dialog);
83 }
84 
85 gboolean
on_sheets_main_dialog_delete_event(GtkWidget * widget,GdkEvent * event,gpointer user_data)86 on_sheets_main_dialog_delete_event     (GtkWidget       *widget,
87                                         GdkEvent        *event,
88                                         gpointer         user_data)
89 {
90   sheets_dialog_hide();
91   return TRUE;
92 }
93 
94 
95 static void
sheets_dialog_up_down_set_sensitive(GList * wrapbox_button_list,GtkToggleButton * togglebutton)96 sheets_dialog_up_down_set_sensitive(GList *wrapbox_button_list,
97                                     GtkToggleButton *togglebutton)
98 {
99   GtkWidget *button;
100 
101   button = lookup_widget(sheets_dialog, "button_move_up");
102 
103   /* If the active button is the 1st in the wrapbox, OR
104      if the active button is a linebreak AND is 2nd in the wrapbox
105      THEN set the 'Up' button to insensitive */
106 
107   if (!wrapbox_button_list
108       || GTK_TOGGLE_BUTTON(g_list_first(wrapbox_button_list)->data) == togglebutton
109       || (!gtk_object_get_data(GTK_OBJECT(togglebutton), "sheet_object_mod")
110           && g_list_nth(wrapbox_button_list, 1)
111           && GTK_TOGGLE_BUTTON(g_list_nth(wrapbox_button_list, 1)->data)
112              == togglebutton))
113     gtk_widget_set_sensitive(button, FALSE);
114   else
115     gtk_widget_set_sensitive(button, TRUE);
116 
117   button = lookup_widget(sheets_dialog, "button_move_down");
118   if (!wrapbox_button_list
119       || GTK_TOGGLE_BUTTON(g_list_last(wrapbox_button_list)->data) == togglebutton
120       || (!gtk_object_get_data(GTK_OBJECT(togglebutton), "sheet_object_mod")
121           && g_list_previous(g_list_last(wrapbox_button_list))
122           && GTK_TOGGLE_BUTTON(g_list_previous(g_list_last(wrapbox_button_list))
123                               ->data)
124              == togglebutton))
125     gtk_widget_set_sensitive(button, FALSE);
126   else
127     gtk_widget_set_sensitive(button, TRUE);
128 }
129 
130 static void
on_sheets_dialog_object_button_toggled(GtkToggleButton * togglebutton,gpointer ud_wrapbox)131 on_sheets_dialog_object_button_toggled(GtkToggleButton *togglebutton,
132                                        gpointer ud_wrapbox)
133 {
134   GList *wrapbox_button_list;
135   GtkWidget *button;
136   GtkWidget *table_sheets;
137   GtkWidget *optionmenu_left;
138   GtkWidget *optionmenu_right;
139   gchar *sheet_left;
140   gchar *sheet_right;
141 
142   if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(togglebutton)) == FALSE)
143     return;
144 
145   /* We remember the active button so we don't have to search for it later */
146 
147   gtk_object_set_data(GTK_OBJECT(ud_wrapbox), "active_button", togglebutton);
148 
149   /* Same with the active wrapbox */
150 
151   table_sheets = lookup_widget(sheets_dialog, "table_sheets");
152   gtk_object_set_data(GTK_OBJECT(table_sheets), "active_wrapbox", ud_wrapbox);
153 
154   optionmenu_left = lookup_widget(sheets_dialog, "optionmenu_left");
155   sheet_left = gtk_object_get_data(GTK_OBJECT(optionmenu_left),
156                                    "active_sheet_name");
157 
158   optionmenu_right = lookup_widget(sheets_dialog, "optionmenu_right");
159   sheet_right = gtk_object_get_data(GTK_OBJECT(optionmenu_right),
160                                     "active_sheet_name");
161 
162   if ((gboolean)gtk_object_get_data(GTK_OBJECT(ud_wrapbox), "is_left") ==TRUE)
163   {
164     gtk_object_set_data(GTK_OBJECT(table_sheets), "active_optionmenu",
165                         optionmenu_left);
166     button = lookup_widget(sheets_dialog, "button_copy");
167     gtk_object_set(GTK_OBJECT(button), "label", _("Copy ->"), NULL);
168     button = lookup_widget(sheets_dialog, "button_copy_all");
169     gtk_object_set(GTK_OBJECT(button), "label", _("Copy All ->"), NULL);
170     button = lookup_widget(sheets_dialog, "button_move");
171     gtk_object_set(GTK_OBJECT(button), "label", _("Move ->"), NULL);
172     button = lookup_widget(sheets_dialog, "button_move_all");
173     gtk_object_set(GTK_OBJECT(button), "label", _("Move All ->"), NULL);
174   }
175   else
176   {
177     gtk_object_set_data(GTK_OBJECT(table_sheets), "active_optionmenu",
178                         optionmenu_right);
179     button = lookup_widget(sheets_dialog, "button_copy");
180     gtk_object_set(GTK_OBJECT(button), "label", _("<- Copy"), NULL);
181     button = lookup_widget(sheets_dialog, "button_copy_all");
182     gtk_object_set(GTK_OBJECT(button), "label", _("<- Copy All"), NULL);
183     button = lookup_widget(sheets_dialog, "button_move");
184     gtk_object_set(GTK_OBJECT(button), "label", _("<- Move"), NULL);
185     button = lookup_widget(sheets_dialog, "button_move_all");
186     gtk_object_set(GTK_OBJECT(button), "label", _("<- Move All"), NULL);
187   }
188 
189   sheet_left = sheet_left ? sheet_left : "";  /* initial value can be NULL */
190 
191   if (!strcmp(sheet_left, sheet_right)
192       || gtk_object_get_data(GTK_OBJECT(togglebutton), "is_hidden_button")
193       || !gtk_object_get_data(GTK_OBJECT(togglebutton), "sheet_object_mod"))
194   {
195     button = lookup_widget(sheets_dialog, "button_copy");
196     gtk_widget_set_sensitive(button, FALSE);
197     button = lookup_widget(sheets_dialog, "button_copy_all");
198     gtk_widget_set_sensitive(button, FALSE);
199     button = lookup_widget(sheets_dialog, "button_move");
200     gtk_widget_set_sensitive(button, FALSE);
201     button = lookup_widget(sheets_dialog, "button_move_all");
202     gtk_widget_set_sensitive(button, FALSE);
203   }
204   else
205   {
206     button = lookup_widget(sheets_dialog, "button_copy");
207     gtk_widget_set_sensitive(button, TRUE);
208     button = lookup_widget(sheets_dialog, "button_copy_all");
209     gtk_widget_set_sensitive(button, TRUE);
210     button = lookup_widget(sheets_dialog, "button_move");
211     gtk_widget_set_sensitive(button, TRUE);
212     button = lookup_widget(sheets_dialog, "button_move_all");
213     gtk_widget_set_sensitive(button, TRUE);
214   }
215 
216   wrapbox_button_list = gtk_container_children(GTK_CONTAINER(ud_wrapbox));
217 
218   if (g_list_length(wrapbox_button_list))
219   {
220     SheetMod *sm;
221 
222     sheets_dialog_up_down_set_sensitive(wrapbox_button_list, togglebutton);
223 
224     sm = gtk_object_get_data(GTK_OBJECT(togglebutton), "sheet_mod");
225 
226     button = lookup_widget(sheets_dialog, "button_edit");
227     if (!gtk_object_get_data(GTK_OBJECT(togglebutton), "sheet_object_mod")
228         && sm->sheet.scope == SHEET_SCOPE_SYSTEM)
229       gtk_widget_set_sensitive(button, FALSE);
230     else
231       gtk_widget_set_sensitive(button, TRUE);
232 
233     button = lookup_widget(sheets_dialog, "button_remove");
234     if (gtk_object_get_data(GTK_OBJECT(togglebutton), "is_hidden_button")
235         && sm->sheet.shadowing == NULL
236         && sm->sheet.scope == SHEET_SCOPE_SYSTEM)
237       gtk_widget_set_sensitive(button, FALSE);
238     else
239       gtk_widget_set_sensitive(button, TRUE);
240   }
241   else
242   {
243     button = lookup_widget(sheets_dialog, "button_move_up");
244     gtk_widget_set_sensitive(button, FALSE);
245     button = lookup_widget(sheets_dialog, "button_move_down");
246     gtk_widget_set_sensitive(button, FALSE);
247     button = lookup_widget(sheets_dialog, "button_edit");
248     gtk_widget_set_sensitive(button, FALSE);
249     button = lookup_widget(sheets_dialog, "button_remove");
250     gtk_widget_set_sensitive(button, FALSE);
251   }
252   g_list_free(wrapbox_button_list);
253 }
254 
255 static void
sheets_dialog_wrapbox_add_line_break(GtkWidget * wrapbox)256 sheets_dialog_wrapbox_add_line_break(GtkWidget *wrapbox)
257 {
258   SheetMod *sm;
259   GtkWidget *button;
260   GtkStyle *style;
261   GdkPixmap *pixmap, *mask;
262   GtkWidget *gtkpixmap;
263 
264   sm = gtk_object_get_data(GTK_OBJECT(wrapbox), "sheet_mod");
265   g_assert(sm);
266 
267   button = gtk_radio_button_new(radio_group);
268   gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
269 
270   gtk_object_set_data(GTK_OBJECT(button), "sheet_mod", sm);
271 
272   radio_group = gtk_radio_button_group(GTK_RADIO_BUTTON(button));
273 
274   gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(button), FALSE);
275   gtk_container_set_border_width(GTK_CONTAINER(button), 0);
276 
277   style = gtk_widget_get_style(wrapbox);
278   pixmap =
279     gdk_pixmap_colormap_create_from_xpm_d(NULL,
280                                           gtk_widget_get_colormap(wrapbox),
281                                           &mask,
282                                           &style->bg[GTK_STATE_NORMAL],
283                                           line_break_xpm);
284 
285   gtkpixmap = gtk_pixmap_new(pixmap, mask);
286   gtk_container_add(GTK_CONTAINER(button), gtkpixmap);
287   gtk_widget_show(gtkpixmap);
288 
289   gtk_wrap_box_pack(GTK_WRAP_BOX(wrapbox), button, FALSE, TRUE, FALSE, TRUE);
290   gtk_widget_show(button);
291 
292   gtk_tooltips_set_tip(sheets_dialog_tooltips, button, _("Line Break"), NULL);
293 
294   g_signal_connect(GTK_OBJECT(button), "toggled",
295 		   G_CALLBACK(on_sheets_dialog_object_button_toggled),
296                      wrapbox);
297 }
298 
299 static void
sheets_dialog_object_set_tooltip(SheetObjectMod * som,GtkWidget * button)300 sheets_dialog_object_set_tooltip(SheetObjectMod *som, GtkWidget *button)
301 {
302   gchar *tip;
303 
304    switch (som->type){
305    case OBJECT_TYPE_SVG:
306     tip = g_strdup_printf(_("%s\nShape"), som->sheet_object.description);
307     break;
308    case OBJECT_TYPE_PROGRAMMED:
309     tip = g_strdup_printf(_("%s\nObject"), som->sheet_object.description);
310     break;
311    default:
312     tip = g_strdup_printf(_("%s\nUnassigned type"), som->sheet_object.description);
313     break;
314   }
315 
316   gtk_tooltips_set_tip(sheets_dialog_tooltips, button, tip, NULL);
317   g_free(tip);
318 }
319 
320 static GtkWidget *
sheets_dialog_create_object_button(SheetObjectMod * som,SheetMod * sm,GtkWidget * wrapbox)321 sheets_dialog_create_object_button(SheetObjectMod *som, SheetMod *sm,
322                                    GtkWidget *wrapbox)
323 {
324   GtkWidget *button;
325   GdkPixmap *pixmap, *mask;
326   GtkWidget *gtkpixmap;
327 
328   button = gtk_radio_button_new(radio_group);
329   radio_group = gtk_radio_button_group(GTK_RADIO_BUTTON(button));
330 
331   gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(button), FALSE);
332   gtk_container_set_border_width(GTK_CONTAINER(button), 0);
333 
334   create_object_pixmap(&som->sheet_object, wrapbox, &pixmap, &mask);
335   gtkpixmap = gtk_pixmap_new(pixmap, mask);
336   gtk_container_add(GTK_CONTAINER(button), gtkpixmap);
337   gtk_widget_show(gtkpixmap);
338 
339   sheets_dialog_object_set_tooltip(som, button);
340 
341   gtk_object_set_data(GTK_OBJECT(button), "sheet_mod", sm);
342   gtk_object_set_data(GTK_OBJECT(button), "sheet_object_mod", som);
343 
344   g_signal_connect(GTK_OBJECT(button), "toggled",
345 		   G_CALLBACK(on_sheets_dialog_object_button_toggled),
346                      wrapbox);
347   return button;
348 }
349 
350 gboolean optionmenu_activate_first_pass = TRUE;
351 
352 void
on_sheets_dialog_optionmenu_activate(GtkMenuItem * menuitem,gpointer user_data)353 on_sheets_dialog_optionmenu_activate   (GtkMenuItem     *menuitem,
354                                         gpointer         user_data)
355 {
356   GtkWidget *wrapbox;
357   Sheet *sheet;
358   GtkWidget *optionmenu;
359   GSList *object_mod_list;
360   GtkWidget *hidden_button;
361   GList *button_list;
362 
363   sheet = &(((SheetMod *)(user_data))->sheet);
364 
365   wrapbox = gtk_object_get_data(GTK_OBJECT(menuitem), "wrapbox");
366   g_assert(wrapbox);
367 
368   /* The hidden button is necessary to keep track of radio_group
369      when there are no objects and to force 'toggled' events    */
370 
371   if (optionmenu_activate_first_pass)
372   {
373     hidden_button = gtk_radio_button_new(NULL);
374     optionmenu_activate_first_pass = FALSE;
375   }
376   else
377   {
378     hidden_button = gtk_radio_button_new(radio_group);
379     radio_group = gtk_radio_button_group(GTK_RADIO_BUTTON(hidden_button));
380   }
381 
382   g_signal_connect(GTK_OBJECT(hidden_button), "toggled",
383 		   G_CALLBACK(on_sheets_dialog_object_button_toggled),
384                      wrapbox);
385   gtk_object_set_data(GTK_OBJECT(hidden_button), "is_hidden_button",
386                       (gpointer)TRUE);
387   gtk_object_set_data(GTK_OBJECT(wrapbox), "hidden_button", hidden_button);
388   gtk_object_set_data(GTK_OBJECT(hidden_button), "sheet_mod", user_data);
389 
390   if (gtk_object_get_data(GTK_OBJECT(wrapbox), "is_left"))
391     optionmenu = lookup_widget(sheets_dialog, "optionmenu_left");
392   else
393     optionmenu = lookup_widget(sheets_dialog, "optionmenu_right");
394   gtk_object_set_data(GTK_OBJECT(optionmenu), "active_sheet_name", sheet->name);
395 
396   gtk_container_foreach(GTK_CONTAINER(wrapbox),
397                         (GtkCallback)gtk_widget_destroy, NULL);
398 
399   radio_group = gtk_radio_button_group(GTK_RADIO_BUTTON(hidden_button));
400 
401   gtk_wrap_box_set_aspect_ratio(GTK_WRAP_BOX(wrapbox), 4 * 1.0 / 9);
402                                                 /* MCNFIXME: calculate this */
403 #ifdef CHANGE_COLOUR_OF_MODIFIED_SHEETS
404   {
405     GtkRcStyle *style;
406 
407     style->fg[0].red = style->bg[0].red = 56000;
408     style->fg[1].red = style->bg[1].red = 56000;
409     style->fg[2].red = style->bg[2].red = 56000;
410     style->fg[3].red = style->bg[3].red = 56000;
411     style->fg[4].red = style->bg[4].red = 56000;
412     style->color_flags[0] |= 0x0f;
413     style->color_flags[1] |= 0x0f;
414     style->color_flags[2] |= 0x0f;
415     style->color_flags[3] |= 0x0f;
416     style->color_flags[4] |= 0x0f;
417 
418     sw = lookup_widget(sheets_dialog, "scrolledwindow_right");
419     gtk_widget_modify_style(wrapbox, style);
420   }
421 #endif
422 
423   gtk_object_set_data(GTK_OBJECT(wrapbox), "sheet_mod", user_data);
424 
425   for (object_mod_list = sheet->objects; object_mod_list;
426        object_mod_list = g_slist_next(object_mod_list))
427   {
428     GtkWidget *button;
429     SheetObjectMod *som;
430 
431     som = object_mod_list->data;
432     if (som->mod == SHEET_OBJECT_MOD_DELETED)
433       continue;
434 
435     if (som->sheet_object.line_break == TRUE)
436       sheets_dialog_wrapbox_add_line_break(wrapbox);
437 
438     button = sheets_dialog_create_object_button(som, user_data, wrapbox);
439 
440     gtk_wrap_box_pack_wrapped(GTK_WRAP_BOX(wrapbox), button,
441 		      FALSE, TRUE, FALSE, TRUE, som->sheet_object.line_break);
442 
443     gtk_widget_show(button);
444   }
445 
446   button_list = gtk_container_children(GTK_CONTAINER(wrapbox));
447 
448   if (g_list_length(button_list))
449   {
450     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(hidden_button), TRUE);
451     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button_list->data), TRUE);
452   }
453   else
454     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(hidden_button), TRUE);
455 
456   g_list_free(button_list);
457 }
458 
459 static void
sheets_dialog_apply_revert_set_sensitive(gboolean is_sensitive)460 sheets_dialog_apply_revert_set_sensitive(gboolean is_sensitive)
461 {
462   GtkWidget *button;
463 
464   button = lookup_widget(sheets_dialog, "button_apply");
465   gtk_widget_set_sensitive(button, is_sensitive);
466 
467   button = lookup_widget(sheets_dialog, "button_revert");
468   gtk_widget_set_sensitive(button, is_sensitive);
469 }
470 
471 typedef enum
472 {
473   SHEETS_DIALOG_MOVE_UP   = -1,
474   SHEETS_DIALOG_MOVE_DOWN = +1
475 }
476 SheetsDialogMoveDir;
477 #define \
478   SHEETS_DIALOG_MOVE_NONE   SHEETS_DIALOG_MOVE_UP
479 
480 static void
_gtk_wrap_box_set_child_forced_break(GtkWrapBox * box,GtkWidget * child,gboolean wrapped)481 _gtk_wrap_box_set_child_forced_break (GtkWrapBox* box, GtkWidget* child,
482                                       gboolean wrapped)
483 {
484   gboolean hexpand, hfill, vexpand, vfill, dummy;
485 
486   gtk_wrap_box_query_child_packing (box, child, &hexpand, &hfill,
487                                     &vexpand, &vfill, &dummy);
488   gtk_wrap_box_set_child_packing (box, child, hexpand, hfill,
489                                   vexpand, vfill, wrapped);
490 }
491 static void
sheets_dialog_normalize_line_breaks(GtkWidget * wrapbox,SheetsDialogMoveDir dir)492 sheets_dialog_normalize_line_breaks(GtkWidget *wrapbox, SheetsDialogMoveDir dir)
493 {
494   GList *button_list;
495   GList *iter_list;
496   gboolean is_line_break;
497 
498   button_list = gtk_container_children(GTK_CONTAINER(wrapbox));
499 
500   is_line_break = FALSE;
501   for (iter_list = button_list; iter_list; iter_list = g_list_next(iter_list))
502   {
503     SheetMod *sm;
504     SheetObjectMod *som;
505 
506     sm = gtk_object_get_data(GTK_OBJECT(iter_list->data), "sheet_mod");
507     som = gtk_object_get_data(GTK_OBJECT(iter_list->data), "sheet_object_mod");
508     if (som)
509     {
510       if (is_line_break)
511       {
512         if (som->sheet_object.line_break == FALSE)
513         {
514           if (sm->mod == SHEETMOD_MOD_NONE)
515             sm->mod = SHEETMOD_MOD_CHANGED;
516 
517           som->mod = SHEET_OBJECT_MOD_CHANGED;
518         }
519 
520         som->sheet_object.line_break = TRUE;
521         _gtk_wrap_box_set_child_forced_break(GTK_WRAP_BOX(wrapbox),
522                                              GTK_WIDGET(iter_list->data), TRUE);
523       }
524       else
525       {
526         if (som->sheet_object.line_break == TRUE)
527         {
528           if (sm->mod == SHEETMOD_MOD_NONE)
529             sm->mod = SHEETMOD_MOD_CHANGED;
530           som->mod = SHEET_OBJECT_MOD_CHANGED;
531         }
532 
533         som->sheet_object.line_break = FALSE;
534         _gtk_wrap_box_set_child_forced_break(GTK_WRAP_BOX(wrapbox),
535                                             GTK_WIDGET(iter_list->data), FALSE);
536       }
537       is_line_break = FALSE;
538     }
539     else
540     {
541       if (is_line_break)
542       {
543         if (dir == SHEETS_DIALOG_MOVE_UP)
544         {
545           iter_list = g_list_previous(iter_list);
546           gtk_widget_destroy(GTK_WIDGET(iter_list->data));
547           iter_list = g_list_next(iter_list);
548           radio_group = gtk_radio_button_group(GTK_RADIO_BUTTON(iter_list
549                                                                        ->data));
550         }
551         else
552         {
553           GList *tmp_list;
554 
555           tmp_list = g_list_previous(iter_list);
556           gtk_widget_destroy(GTK_WIDGET(iter_list->data));
557           radio_group = gtk_radio_button_group(GTK_RADIO_BUTTON(tmp_list
558                                                                        ->data));
559         }
560       }
561       else
562         is_line_break = TRUE;
563     }
564   }
565 
566   /* We delete a trailing linebreak button in the wrapbox */
567 
568   iter_list = g_list_last(button_list);
569   if (iter_list && !gtk_object_get_data(GTK_OBJECT(iter_list->data),
570                                         "sheet_object_mod"))
571   {
572     gtk_widget_destroy(GTK_WIDGET(iter_list->data));
573     if (g_list_previous(iter_list))
574     {
575       gtk_toggle_button_set_active(g_list_previous(iter_list)->data, TRUE);
576       radio_group = gtk_radio_button_group(GTK_RADIO_BUTTON(
577                                              g_list_previous(iter_list)->data));
578     }
579   }
580 
581   g_list_free(button_list);
582 }
583 
584 GtkWidget *
sheets_dialog_get_active_button(GtkWidget ** wrapbox,GList ** button_list)585 sheets_dialog_get_active_button(GtkWidget **wrapbox, GList **button_list)
586 {
587   GtkWidget *table_sheets;
588 
589   table_sheets = lookup_widget(sheets_dialog, "table_sheets");
590   *wrapbox = gtk_object_get_data(GTK_OBJECT(table_sheets), "active_wrapbox");
591   *button_list = gtk_container_children(GTK_CONTAINER(*wrapbox));
592   return gtk_object_get_data(GTK_OBJECT(*wrapbox), "active_button");
593 }
594 
595 
596 static void
sheets_dialog_move_up_or_down(SheetsDialogMoveDir dir)597 sheets_dialog_move_up_or_down(SheetsDialogMoveDir dir)
598 {
599   GtkWidget *table_sheets;
600   GtkWidget *wrapbox;
601   GList *button_list;
602   GtkWidget *active_button;
603   gint button_pos;
604   SheetObjectMod *som;
605   SheetObjectMod *som_next;
606   GList *next_button_list;
607 
608   table_sheets = lookup_widget(sheets_dialog, "table_sheets");
609   wrapbox = gtk_object_get_data(GTK_OBJECT(table_sheets), "active_wrapbox");
610 
611   button_list = gtk_container_children(GTK_CONTAINER(wrapbox));
612   active_button = gtk_object_get_data(GTK_OBJECT(wrapbox), "active_button");
613 
614   button_pos = g_list_index(button_list, active_button);
615   gtk_wrap_box_reorder_child(GTK_WRAP_BOX(wrapbox),
616                              GTK_WIDGET(active_button), button_pos + dir);
617   g_list_free(button_list);
618 
619   sheets_dialog_normalize_line_breaks(wrapbox, dir);
620 
621   /* And then reorder the backing store if necessary */
622 
623   button_list = gtk_container_children(GTK_CONTAINER(wrapbox));
624   active_button = gtk_object_get_data(GTK_OBJECT(wrapbox), "active_button");
625 
626   som = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_object_mod");
627 
628   next_button_list = g_list_next(g_list_find(button_list, active_button));
629   if (next_button_list)
630     som_next = gtk_object_get_data(GTK_OBJECT(next_button_list->data),
631                                    "sheet_object_mod");
632   else
633     som_next = NULL; /* either 1) no button after 'active_button'
634                             or 2) button after 'active_button' is line break */
635 
636   /* This is all a little hairy, but the idea is that we don't need
637      to reorder the backing store if the button was moved to the other
638      side of a line break button since a line break button doesn't
639      exist in the backing store.  Starting to look a little like lisp... */
640 
641   if (som && (((dir == SHEETS_DIALOG_MOVE_DOWN)
642                  && (som->sheet_object.line_break == FALSE))
643           || (((dir == SHEETS_DIALOG_MOVE_UP)
644                  && som_next))))
645   {
646     SheetMod *sm;
647     GSList *object_list;
648     gint object_pos;
649 
650     som->mod = SHEET_OBJECT_MOD_CHANGED;
651 
652     sm = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_mod");
653     if (sm->mod == SHEETMOD_MOD_NONE)
654       sm->mod = SHEETMOD_MOD_CHANGED;
655 
656     object_list = g_slist_find(sm->sheet.objects, som);
657     g_assert(object_list);
658 
659     object_pos = g_slist_position(sm->sheet.objects, object_list);
660     sm->sheet.objects = g_slist_remove_link(sm->sheet.objects, object_list);
661     sm->sheet.objects = g_slist_insert(sm->sheet.objects, object_list->data,
662                                        object_pos + dir);
663   }
664 
665   sheets_dialog_apply_revert_set_sensitive(TRUE);
666 
667   sheets_dialog_up_down_set_sensitive(button_list,
668                                       GTK_TOGGLE_BUTTON(active_button));
669   g_list_free(button_list);
670 }
671 
672 void
on_sheets_dialog_button_move_up_clicked(GtkButton * button,gpointer user_data)673 on_sheets_dialog_button_move_up_clicked(GtkButton *button, gpointer user_data)
674 {
675   sheets_dialog_move_up_or_down(SHEETS_DIALOG_MOVE_UP);
676 }
677 
678 void
on_sheets_dialog_button_move_down_clicked(GtkButton * button,gpointer user_data)679 on_sheets_dialog_button_move_down_clicked(GtkButton *button, gpointer user_data)
680 {
681   sheets_dialog_move_up_or_down(SHEETS_DIALOG_MOVE_DOWN);
682 }
683 
684 void
on_sheets_dialog_button_close_clicked(GtkButton * button,gpointer user_data)685 on_sheets_dialog_button_close_clicked  (GtkButton       *button,
686                                         gpointer         user_data)
687 {
688   sheets_dialog_hide();
689 }
690 
691 static GtkWidget *sheets_new_dialog;
692 
693 typedef enum
694 {
695   SHEETS_NEW_DIALOG_TYPE_SVG_SHAPE = 1,   /* allows g_assert() */
696   SHEETS_NEW_DIALOG_TYPE_LINE_BREAK,
697   SHEETS_NEW_DIALOG_TYPE_SHEET
698 }
699 SheetsNewDialogType;
700 
701 GList *sheets_new_dialog_combo_list = NULL;
702 
703 void
on_sheets_dialog_button_new_clicked(GtkButton * button,gpointer user_data)704 on_sheets_dialog_button_new_clicked    (GtkButton       *button,
705                                         gpointer         user_data)
706 {
707   GtkWidget *combo;
708   GtkWidget *wrapbox;
709   GList *button_list;
710   GtkWidget *active_button;
711   gboolean is_line_break_sensitive;
712 
713   sheets_new_dialog = create_sheets_new_dialog();
714 
715   if (sheets_new_dialog_combo_list)
716   {
717     combo = lookup_widget(sheets_new_dialog, "combo_from_file");
718     gtk_combo_set_popdown_strings(GTK_COMBO(combo),
719                                   sheets_new_dialog_combo_list);
720   }
721 
722   /* Deterine if a line break button can be put after the active button */
723 
724   active_button = sheets_dialog_get_active_button(&wrapbox, &button_list);
725   is_line_break_sensitive = TRUE;
726   if (gtk_object_get_data(GTK_OBJECT(active_button), "sheet_mod"))
727   {
728     button_list = g_list_next(g_list_find(button_list, active_button));
729     if (!button_list || !gtk_object_get_data(GTK_OBJECT(button_list->data),
730                                            "sheet_mod"))
731       is_line_break_sensitive = FALSE;
732     g_list_free(button_list);
733   }
734   else
735     is_line_break_sensitive = FALSE;
736 
737   active_button = lookup_widget(sheets_new_dialog, "radiobutton_line_break");
738   gtk_widget_set_sensitive(active_button, is_line_break_sensitive);
739 
740   /* Use the 'ok' button to hold the current 'type' selection */
741 
742   active_button = lookup_widget(sheets_new_dialog, "button_ok");
743   gtk_object_set_data(GTK_OBJECT(active_button), "active_type",
744                       (gpointer)SHEETS_NEW_DIALOG_TYPE_SVG_SHAPE);
745 
746   gtk_widget_show(sheets_new_dialog);
747 }
748 
749 void
on_sheets_new_dialog_button_cancel_clicked(GtkButton * button,gpointer user_data)750 on_sheets_new_dialog_button_cancel_clicked
751                                         (GtkButton       *button,
752                                         gpointer         user_data)
753 {
754   gtk_widget_destroy(sheets_new_dialog);
755   sheets_new_dialog = NULL;
756 }
757 
758 void
on_sheets_new_dialog_button_ok_clicked(GtkButton * button,gpointer user_data)759 on_sheets_new_dialog_button_ok_clicked (GtkButton       *button,
760                                         gpointer         user_data)
761 {
762   SheetsNewDialogType active_type;
763   GtkWidget *table_sheets;
764   GtkWidget *wrapbox;
765   GList *button_list;
766   GtkWidget *active_button;
767 
768   table_sheets = lookup_widget(sheets_dialog, "table_sheets");
769   wrapbox = gtk_object_get_data(GTK_OBJECT(table_sheets), "active_wrapbox");
770 
771   active_type = (SheetsNewDialogType)gtk_object_get_data(GTK_OBJECT(button),
772                                                          "active_type");
773   g_assert(active_type);
774 
775   switch (active_type)
776   {
777     GtkWidget *entry;
778     gchar *file_name;
779     gchar *p;
780     struct stat stat_buf;
781     GList *plugin_list;
782     DiaObjectType *ot;
783     typedef gboolean (*CustomObjectLoadFunc) (gchar*, DiaObjectType **);
784     CustomObjectLoadFunc custom_object_load_fn;
785     gint pos;
786     GtkWidget *active_button;
787     GList *button_list;
788     SheetObjectMod *som;
789     SheetMod *sm;
790     SheetObject *sheet_obj;
791     Sheet *sheet;
792     GtkWidget *optionmenu;
793 
794   case SHEETS_NEW_DIALOG_TYPE_SVG_SHAPE:
795 
796     entry = lookup_widget(sheets_new_dialog, "combo_entry_from_file");
797     /* Since this is a file name, no utf8 translation is needed */
798     file_name = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
799 
800     p = file_name + strlen(file_name) - 6;
801     if (strcmp(p, ".shape"))
802     {
803       message_error(_("Filename must end with '%s': '%s'"),
804                     ".shape", dia_message_filename(file_name));
805       g_free(file_name);
806       return;
807     }
808 
809     if (g_stat(file_name, &stat_buf) == -1)
810     {
811       message_error(_("Error examining %s: %s"),
812 		    dia_message_filename(file_name), strerror(errno));
813       g_free(file_name);
814       return;
815     }
816 
817     custom_object_load_fn = NULL;
818     for (plugin_list = dia_list_plugins(); plugin_list != NULL;
819          plugin_list = g_list_next(plugin_list))
820     {
821        PluginInfo *info = plugin_list->data;
822 
823        custom_object_load_fn =
824          (CustomObjectLoadFunc)dia_plugin_get_symbol (info, "custom_object_load");
825        if (custom_object_load_fn)
826          break;
827     }
828     g_assert(custom_object_load_fn);
829 
830     if (!(*custom_object_load_fn)(file_name, &ot))
831     {
832     	xmlDoc *doc = NULL;
833 	xmlNode *root_element = NULL;
834 
835 	/* See if the user tries to open a diagram as a shape */
836 	doc = xmlReadFile(file_name, NULL, 0);
837 	if(doc != NULL)
838 	{
839 		root_element = xmlDocGetRootElement(doc);
840 		if(0 == g_strncasecmp((gchar *)root_element->name, "dia", 3))
841 			message_error(
842 				_("Please export the diagram as a shape."));
843 		xmlFreeDoc(doc);
844 	}
845 	message_error(_("Could not interpret shape file: '%s'"),
846 		    dia_message_filename(file_name));
847 	xmlCleanupParser();
848       g_free(file_name);
849       return;
850     }
851     object_register_type(ot);
852 
853     entry = lookup_widget(sheets_new_dialog, "entry_svg_description");
854     sheet_obj = g_new0(SheetObject, 1);
855     sheet_obj->object_type = g_strdup(ot->name);
856     {
857       sheet_obj->description =
858 	gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
859     }
860     sheet_obj->pixmap = ot->pixmap;
861     sheet_obj->user_data = ot->default_user_data;
862     sheet_obj->user_data_type = USER_DATA_IS_OTHER;
863     sheet_obj->line_break = FALSE;
864     sheet_obj->pixmap_file = g_strdup(ot->pixmap_file);
865     sheet_obj->has_icon_on_sheet = FALSE;
866 
867     sm = gtk_object_get_data(GTK_OBJECT(wrapbox), "sheet_mod");
868     som = sheets_append_sheet_object_mod(sheet_obj, sm);
869     som->mod = SHEET_OBJECT_MOD_NEW;
870     som->svg_filename = g_strdup(file_name);
871     if (sm->mod == SHEETMOD_MOD_NONE)
872       sm->mod = SHEETMOD_MOD_CHANGED;
873 
874     active_button = sheets_dialog_create_object_button(som, sm, wrapbox);
875     gtk_wrap_box_pack(GTK_WRAP_BOX(wrapbox), active_button,
876                       FALSE, TRUE, FALSE, TRUE);
877     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(active_button), TRUE);
878     gtk_widget_show(active_button);
879 
880     sheets_new_dialog_combo_list = g_list_append(sheets_new_dialog_combo_list,
881                                                  file_name);
882     break;
883 
884   case SHEETS_NEW_DIALOG_TYPE_LINE_BREAK:
885 
886     sheets_dialog_wrapbox_add_line_break(wrapbox);
887 
888     button_list = gtk_container_children(GTK_CONTAINER(wrapbox));
889     active_button = gtk_object_get_data(GTK_OBJECT(wrapbox), "active_button");
890     pos = g_list_index(button_list, active_button);
891     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_list_last(button_list)
892                                                                  ->data), TRUE);
893     gtk_wrap_box_reorder_child(GTK_WRAP_BOX(wrapbox),
894                                g_list_last(button_list)->data, pos + 1);
895 
896     sheets_dialog_normalize_line_breaks(wrapbox, SHEETS_DIALOG_MOVE_NONE);
897 
898     sm = gtk_object_get_data(GTK_OBJECT(wrapbox), "sheet_mod");
899     if (sm->mod == SHEETMOD_MOD_NONE)
900       sm->mod = SHEETMOD_MOD_CHANGED;
901 
902     g_list_free(button_list);
903     break;
904 
905   case SHEETS_NEW_DIALOG_TYPE_SHEET:
906     {
907       gchar *sheet_name;
908       gchar *sheet_descrip;
909 
910       entry = lookup_widget(sheets_new_dialog, "entry_sheet_name");
911       sheet_name = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
912 
913       sheet_name = g_strchug(g_strchomp(sheet_name));
914       if (!*sheet_name)
915       {
916         message_error(_("Sheet must have a Name"));
917         return;
918       }
919 
920       entry = lookup_widget(sheets_new_dialog, "entry_sheet_description");
921       sheet_descrip = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
922 
923       sheet = g_new0(Sheet, 1);
924       sheet->name = sheet_name;
925       sheet->filename = "";
926       sheet->description = sheet_descrip;
927       sheet->scope = SHEET_SCOPE_USER;
928       sheet->shadowing = NULL;
929       sheet->objects = NULL;
930 
931       sm = sheets_append_sheet_mods(sheet);
932       sm->mod = SHEETMOD_MOD_NEW;
933 
934       table_sheets = lookup_widget(sheets_dialog, "table_sheets");
935       optionmenu = gtk_object_get_data(GTK_OBJECT(table_sheets),
936                                        "active_optionmenu");
937       g_assert(optionmenu);
938       sheets_optionmenu_create(optionmenu, wrapbox, sheet_name);
939     }
940     break;
941 
942   default:
943     g_assert_not_reached();
944   }
945 
946   sheets_dialog_apply_revert_set_sensitive(TRUE);
947 
948   button_list = gtk_container_children(GTK_CONTAINER(wrapbox));
949   active_button = gtk_object_get_data(GTK_OBJECT(wrapbox), "active_button");
950   sheets_dialog_up_down_set_sensitive(button_list,
951                                       GTK_TOGGLE_BUTTON(active_button));
952   g_list_free(button_list);
953 
954   gtk_widget_destroy(sheets_new_dialog);
955   sheets_new_dialog = NULL;
956 }
957 
958 static GtkWidget *sheets_shapeselection_dialog;
959 
960 void
on_sheets_new_dialog_button_browse_clicked(GtkButton * button,gpointer user_data)961 on_sheets_new_dialog_button_browse_clicked
962                                         (GtkButton       *button,
963                                         gpointer         user_data)
964 {
965   sheets_shapeselection_dialog = create_sheets_shapeselection_dialog();
966   gtk_widget_show(sheets_shapeselection_dialog);
967 }
968 
969 void
on_sheets_shapeselection_dialog_button_cancel_clicked(GtkButton * button,gpointer user_data)970 on_sheets_shapeselection_dialog_button_cancel_clicked
971                                         (GtkButton       *button,
972                                         gpointer         user_data)
973 {
974   gtk_widget_destroy(sheets_shapeselection_dialog);
975   sheets_shapeselection_dialog = NULL;
976 }
977 
978 void
on_sheets_shapeselection_dialog_button_ok_clicked(GtkButton * button,gpointer user_data)979 on_sheets_shapeselection_dialog_button_ok_clicked
980                                         (GtkButton       *button,
981                                         gpointer         user_data)
982 {
983   const gchar *filename;
984   GtkWidget *entry;
985 
986   filename =
987       gtk_file_selection_get_filename(
988           GTK_FILE_SELECTION(sheets_shapeselection_dialog));
989 
990   entry = lookup_widget(sheets_new_dialog, "combo_entry_from_file");
991   /* Since this is a filename entry from the dialog, no utf is needed */
992   gtk_entry_set_text(GTK_ENTRY(entry), filename);
993 
994   gtk_widget_destroy(sheets_shapeselection_dialog);
995   sheets_shapeselection_dialog = NULL;
996 }
997 
998 static GtkWidget *sheets_edit_dialog;
999 
1000 void
on_sheets_dialog_button_edit_clicked(GtkButton * button,gpointer user_data)1001 on_sheets_dialog_button_edit_clicked   (GtkButton       *button,
1002                                         gpointer         user_data)
1003 {
1004   GtkWidget *wrapbox;
1005   GList *button_list;
1006   GtkWidget *active_button;
1007   SheetObjectMod *som;
1008   gchar *descrip = "";
1009   gchar *type = "";
1010   GtkWidget *entry;
1011   SheetMod *sm;
1012   gchar *name = "";
1013 
1014   if (sheets_edit_dialog == NULL)
1015     sheets_edit_dialog = create_sheets_edit_dialog();
1016 
1017   active_button = sheets_dialog_get_active_button(&wrapbox, &button_list);
1018   som = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_object_mod");
1019   if (som)
1020   {
1021     descrip = som->sheet_object.description;
1022     type = sheet_object_mod_get_type_string(som);
1023   }
1024 
1025   entry = lookup_widget(sheets_edit_dialog, "entry_object_description");
1026   if (som)
1027     gtk_entry_set_text(GTK_ENTRY(entry), descrip);
1028   else
1029     gtk_widget_set_sensitive(entry, FALSE);
1030 
1031   entry = lookup_widget(sheets_edit_dialog, "entry_object_type");
1032   if (som)
1033     gtk_entry_set_text(GTK_ENTRY(entry), type);
1034   else
1035     gtk_widget_set_sensitive(entry, FALSE);
1036 
1037   sm = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_mod");
1038   if (sm)
1039   {
1040     name = sm->sheet.name;
1041     descrip = sm->sheet.description;
1042   }
1043 
1044   entry = lookup_widget(sheets_edit_dialog, "entry_sheet_name");
1045   gtk_entry_set_text(GTK_ENTRY(entry), name);
1046 #if CAN_EDIT_SHEET_NAME
1047   if (sm->sheet.scope == SHEET_SCOPE_SYSTEM)
1048 #endif
1049     gtk_widget_set_sensitive(entry, FALSE);
1050 
1051   entry = lookup_widget(sheets_edit_dialog, "entry_sheet_description");
1052   gtk_entry_set_text(GTK_ENTRY(entry), descrip);
1053 
1054   gtk_widget_show(sheets_edit_dialog);
1055 }
1056 
1057 void
on_sheets_edit_dialog_button_cancel_clicked(GtkButton * button,gpointer user_data)1058 on_sheets_edit_dialog_button_cancel_clicked
1059                                         (GtkButton       *button,
1060                                         gpointer         user_data)
1061 {
1062   gtk_widget_destroy(sheets_edit_dialog);
1063   sheets_edit_dialog = NULL;
1064 }
1065 
1066 static GtkWidget *sheets_remove_dialog;
1067 
1068 typedef enum
1069 {
1070   SHEETS_REMOVE_DIALOG_TYPE_OBJECT = 1,
1071   SHEETS_REMOVE_DIALOG_TYPE_SHEET
1072 }
1073 SheetsRemoveDialogType;
1074 
1075 void
on_sheets_dialog_button_remove_clicked(GtkButton * button,gpointer user_data)1076 on_sheets_dialog_button_remove_clicked (GtkButton       *button,
1077                                         gpointer         user_data)
1078 {
1079   GtkWidget *wrapbox;
1080   GList *button_list;
1081   GtkWidget *active_button;
1082   SheetMod *sm;
1083   GtkWidget *entry;
1084   GtkWidget *radio_button;
1085 
1086   sheets_remove_dialog = create_sheets_remove_dialog();
1087 
1088   active_button = sheets_dialog_get_active_button(&wrapbox, &button_list);
1089   g_assert(active_button);
1090 
1091   /* Force a change in state in the radio button for set sensitive */
1092 
1093   radio_button = lookup_widget(sheets_remove_dialog, "radiobutton_sheet");
1094   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio_button), TRUE);
1095 
1096   entry = lookup_widget(sheets_remove_dialog, "entry_object");
1097   if (gtk_object_get_data(GTK_OBJECT(active_button), "is_hidden_button"))
1098   {
1099     radio_button = lookup_widget(sheets_remove_dialog, "radiobutton_object");
1100     gtk_widget_set_sensitive(radio_button, FALSE);
1101     gtk_widget_set_sensitive(entry, FALSE);
1102   }
1103   else
1104   {
1105     SheetObjectMod *som;
1106 
1107     som = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_object_mod");
1108     if (!som)
1109       gtk_entry_set_text(GTK_ENTRY(entry), _("Line Break"));
1110     else
1111       gtk_entry_set_text(GTK_ENTRY(entry), som->sheet_object.description);
1112 
1113     radio_button = lookup_widget(sheets_remove_dialog, "radiobutton_object");
1114     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio_button), TRUE);
1115   }
1116 
1117   entry = lookup_widget(sheets_remove_dialog, "entry_sheet");
1118   sm = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_mod");
1119 
1120   /* Note:  It is currently impossible to remove a user sheet that has
1121             been shadowed by a more recent system sheet--the logic is just
1122             too hairy.  Once the user sheet has been updated, or the [copy of
1123             system] sheet has been removed, then they can remove the user
1124             sheet just fine (in the next invocation of dia).  This would
1125             be rare, to say the least... */
1126 
1127   if (sm->sheet.shadowing == NULL && sm->sheet.scope == SHEET_SCOPE_SYSTEM)
1128   {
1129     GtkWidget *radio_button;
1130 
1131     radio_button = lookup_widget(sheets_remove_dialog, "radiobutton_sheet");
1132     gtk_widget_set_sensitive(radio_button, FALSE);
1133     gtk_widget_set_sensitive(entry, FALSE);
1134   }
1135   gtk_entry_set_text(GTK_ENTRY(entry), sm->sheet.name);
1136 
1137   gtk_widget_show(sheets_remove_dialog);
1138 }
1139 
1140 void
on_sheets_remove_dialog_button_cancel_clicked(GtkButton * button,gpointer user_data)1141 on_sheets_remove_dialog_button_cancel_clicked
1142                                         (GtkButton       *button,
1143                                         gpointer         user_data)
1144 {
1145   gtk_widget_destroy(sheets_remove_dialog);
1146   sheets_remove_dialog = NULL;
1147 }
1148 
1149 static void
sheets_dialog_togglebutton_set_sensitive(GtkToggleButton * togglebutton,GtkWidget * dialog,gchar * widget_names[],gint type)1150 sheets_dialog_togglebutton_set_sensitive(GtkToggleButton *togglebutton,
1151                                          GtkWidget *dialog,
1152                                          gchar *widget_names[], gint type)
1153 {
1154   gboolean is_sensitive;
1155   guint i;
1156   GtkWidget *tmp;
1157 
1158   is_sensitive = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(togglebutton));
1159   if (is_sensitive)
1160   {
1161     tmp = lookup_widget(dialog, "button_ok");
1162     gtk_object_set_data(GTK_OBJECT(tmp), "active_type", (gpointer)type);
1163   }
1164 
1165   for (i = 0; widget_names[i]; i++)
1166   {
1167     tmp = lookup_widget(dialog, widget_names[i]);
1168     gtk_widget_set_sensitive(tmp, is_sensitive);
1169   }
1170 }
1171 
1172 void
on_sheets_new_dialog_radiobutton_svg_shape_toggled(GtkToggleButton * togglebutton,gpointer user_data)1173 on_sheets_new_dialog_radiobutton_svg_shape_toggled
1174                                         (GtkToggleButton *togglebutton,
1175                                         gpointer         user_data)
1176 {
1177   static gchar *widget_names[] =
1178   {
1179     "combo_from_file",
1180     "button_browse",
1181     "label_svg_description",
1182     "entry_svg_description",
1183     NULL
1184   };
1185 
1186   sheets_dialog_togglebutton_set_sensitive(togglebutton, sheets_new_dialog,
1187                                            widget_names,
1188                                            SHEETS_NEW_DIALOG_TYPE_SVG_SHAPE);
1189 }
1190 
1191 void
on_sheets_new_dialog_radiobutton_sheet_toggled(GtkToggleButton * togglebutton,gpointer user_data)1192 on_sheets_new_dialog_radiobutton_sheet_toggled
1193                                         (GtkToggleButton *togglebutton,
1194                                         gpointer         user_data)
1195 {
1196   static gchar *widget_names[] =
1197   {
1198     "entry_sheet_name",
1199     "entry_sheet_description",
1200     "label_description",
1201     NULL
1202   };
1203 
1204   sheets_dialog_togglebutton_set_sensitive(togglebutton, sheets_new_dialog,
1205                                            widget_names,
1206                                            SHEETS_NEW_DIALOG_TYPE_SHEET);
1207 }
1208 
1209 void
on_sheets_new_dialog_radiobutton_line_break_toggled(GtkToggleButton * togglebutton,gpointer user_data)1210 on_sheets_new_dialog_radiobutton_line_break_toggled
1211                                         (GtkToggleButton *togglebutton,
1212                                         gpointer         user_data)
1213 {
1214   static gchar *widget_names[] =
1215   {
1216     NULL
1217   };
1218 
1219   sheets_dialog_togglebutton_set_sensitive(togglebutton, sheets_new_dialog,
1220                                            widget_names,
1221                                            SHEETS_NEW_DIALOG_TYPE_LINE_BREAK);
1222 }
1223 
1224 void
on_sheets_remove_dialog_radiobutton_object_toggled(GtkToggleButton * togglebutton,gpointer user_data)1225 on_sheets_remove_dialog_radiobutton_object_toggled
1226                                         (GtkToggleButton *togglebutton,
1227                                         gpointer         user_data)
1228 {
1229   gchar *widget_names[] =
1230   {
1231     "pixmap_object",
1232     "entry_object",
1233     NULL
1234   };
1235 
1236   sheets_dialog_togglebutton_set_sensitive(togglebutton, sheets_remove_dialog,
1237                                            widget_names,
1238                                            SHEETS_REMOVE_DIALOG_TYPE_OBJECT);
1239 }
1240 
1241 void
on_sheets_remove_dialog_radiobutton_sheet_toggled(GtkToggleButton * togglebutton,gpointer user_data)1242 on_sheets_remove_dialog_radiobutton_sheet_toggled
1243                                         (GtkToggleButton *togglebutton,
1244                                         gpointer         user_data)
1245 {
1246   gchar *widget_names[] =
1247   {
1248     "entry_sheet",
1249     NULL
1250   };
1251 
1252   sheets_dialog_togglebutton_set_sensitive(togglebutton, sheets_remove_dialog,
1253                                            widget_names,
1254                                            SHEETS_REMOVE_DIALOG_TYPE_SHEET);
1255 }
1256 
1257 static GtkWidget *
sheets_dialog_set_new_active_button(void)1258 sheets_dialog_set_new_active_button(void)
1259 {
1260   GtkWidget *active_button;
1261   GtkWidget *wrapbox;
1262   GList *button_list;
1263   GList *active_button_list;
1264   GtkWidget *new_active_button;
1265 
1266   active_button = sheets_dialog_get_active_button(&wrapbox, &button_list);
1267 
1268   active_button_list = g_list_find(button_list, active_button);
1269   g_assert(active_button_list);
1270   if (g_list_next(active_button_list))
1271     new_active_button = g_list_next(active_button_list)->data;
1272   else
1273   {
1274     if (g_list_previous(active_button_list))
1275       new_active_button = g_list_previous(active_button_list)->data;
1276     else
1277       new_active_button = gtk_object_get_data(GTK_OBJECT(wrapbox),
1278                                               "hidden_button");
1279   }
1280   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(new_active_button), TRUE);
1281 
1282   return new_active_button;
1283 }
1284 
1285 void
on_sheets_remove_dialog_button_ok_clicked(GtkButton * button,gpointer user_data)1286 on_sheets_remove_dialog_button_ok_clicked
1287                                         (GtkButton       *button,
1288                                         gpointer         user_data)
1289 {
1290   SheetsRemoveDialogType type;
1291   GtkWidget *wrapbox;
1292   GList *button_list;
1293   GtkWidget *active_button;
1294 
1295   type = (SheetsRemoveDialogType)gtk_object_get_data(GTK_OBJECT(button),
1296                                                      "active_type");
1297 
1298   active_button = sheets_dialog_get_active_button(&wrapbox, &button_list);
1299 
1300   switch (type)
1301   {
1302     SheetObjectMod *som;
1303     GtkWidget *new_active_button;
1304     SheetMod *sm;
1305     GtkWidget *table_sheets;
1306     GtkWidget *optionmenu;
1307 
1308   case SHEETS_REMOVE_DIALOG_TYPE_OBJECT:
1309 
1310     som = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_object_mod");
1311     if (som)
1312     {
1313       sm = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_mod");
1314       sm->mod = SHEETMOD_MOD_CHANGED;
1315       som->mod = SHEET_OBJECT_MOD_DELETED;
1316     }
1317     new_active_button = sheets_dialog_set_new_active_button();
1318 
1319     gtk_widget_destroy(active_button);
1320     radio_group = gtk_radio_button_group(GTK_RADIO_BUTTON(new_active_button));
1321 
1322     sheets_dialog_normalize_line_breaks(wrapbox, SHEETS_DIALOG_MOVE_NONE);
1323     break;
1324 
1325   case SHEETS_REMOVE_DIALOG_TYPE_SHEET:
1326 
1327     sm = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_mod");
1328     sm->mod = SHEETMOD_MOD_DELETED;
1329 
1330     if (sm->sheet.shadowing && sm->sheet.scope == SHEET_SCOPE_USER)
1331       sheets_append_sheet_mods(sm->sheet.shadowing);
1332 
1333     table_sheets = lookup_widget(sheets_dialog, "table_sheets");
1334     optionmenu = gtk_object_get_data(GTK_OBJECT(table_sheets),
1335                                      "active_optionmenu");
1336     g_assert(optionmenu);
1337     sheets_optionmenu_create(optionmenu, wrapbox, NULL);
1338 
1339     break;
1340 
1341   default:
1342     g_assert_not_reached();
1343   }
1344 
1345   g_list_free(button_list);
1346 
1347   sheets_dialog_apply_revert_set_sensitive(TRUE);
1348   gtk_widget_destroy(sheets_remove_dialog);
1349   sheets_remove_dialog = NULL;
1350 }
1351 
1352 void
on_sheets_edit_dialog_button_ok_clicked(GtkButton * button,gpointer user_data)1353 on_sheets_edit_dialog_button_ok_clicked
1354                                         (GtkButton       *button,
1355                                         gpointer         user_data)
1356 {
1357   GtkWidget *active_button;
1358   GtkWidget *wrapbox;
1359   GList *button_list;
1360   GtkWidget *entry;
1361   gboolean something_changed = FALSE;
1362 
1363   active_button = sheets_dialog_get_active_button(&wrapbox, &button_list);
1364   g_assert(active_button);
1365 
1366   entry = lookup_widget(sheets_edit_dialog, "entry_object_description");
1367   if ((gboolean)gtk_object_get_data(GTK_OBJECT(entry), "changed") == TRUE)
1368   {
1369     SheetMod *sm;
1370     SheetObjectMod *som;
1371 
1372     som = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_object_mod");
1373     som->sheet_object.description =
1374       gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
1375     sheets_dialog_object_set_tooltip(som, active_button);
1376 
1377     som->mod = SHEET_OBJECT_MOD_CHANGED;
1378 
1379     sm = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_mod");
1380     if (sm->mod == SHEETMOD_MOD_NONE)
1381       sm->mod = SHEETMOD_MOD_CHANGED;
1382 
1383     something_changed = TRUE;
1384   }
1385 
1386   entry = lookup_widget(sheets_edit_dialog, "entry_sheet_description");
1387   if ((gboolean)gtk_object_get_data(GTK_OBJECT(entry), "changed") == TRUE)
1388   {
1389     SheetMod *sm;
1390 
1391     sm = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_mod");
1392     sm->sheet.description =
1393       gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
1394 
1395     if (sm->mod == SHEETMOD_MOD_NONE)
1396       sm->mod = SHEETMOD_MOD_CHANGED;
1397     something_changed = TRUE;
1398   }
1399 
1400 #ifdef CAN_EDIT_SHEET_NAME
1401   /* This must be last because we reload the sheets if changed */
1402 
1403   entry = lookup_widget(sheets_edit_dialog, "entry_sheet_name");
1404   if ((gboolean)gtk_object_get_data(GTK_OBJECT(entry), "changed") == TRUE)
1405   {
1406     SheetMod *sm;
1407     GtkWidget *table_sheets;
1408     GtkWidget *optionmenu;
1409 
1410     sm = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_mod");
1411     sm->sheet.name = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
1412     if (sm->mod == SHEETMOD_MOD_NONE)
1413       sm->mod = SHEETMOD_MOD_CHANGED;
1414 
1415     table_sheets = lookup_widget(sheets_dialog, "table_sheets");
1416     optionmenu = gtk_object_get_data(GTK_OBJECT(table_sheets),
1417                                      "active_optionmenu");
1418     sheets_optionmenu_create(optionmenu, wrapbox, NULL);
1419 
1420     something_changed = TRUE;
1421   }
1422 #endif
1423   if (something_changed == TRUE)
1424     sheets_dialog_apply_revert_set_sensitive(TRUE);
1425 
1426   gtk_widget_destroy(sheets_edit_dialog);
1427   sheets_edit_dialog = NULL;
1428 }
1429 
1430 void
on_sheets_edit_dialog_entry_object_description_changed(GtkEditable * editable,gpointer user_data)1431 on_sheets_edit_dialog_entry_object_description_changed
1432                                         (GtkEditable     *editable,
1433                                         gpointer         user_data)
1434 {
1435   gtk_object_set_data(GTK_OBJECT(editable), "changed", (gpointer)TRUE);
1436 }
1437 
1438 
1439 void
on_sheets_edit_dialog_entry_sheet_description_changed(GtkEditable * editable,gpointer user_data)1440 on_sheets_edit_dialog_entry_sheet_description_changed
1441                                         (GtkEditable     *editable,
1442                                         gpointer         user_data)
1443 {
1444   gtk_object_set_data(GTK_OBJECT(editable), "changed", (gpointer)TRUE);
1445 }
1446 
1447 void
on_sheets_edit_dialog_entry_sheet_name_changed(GtkEditable * editable,gpointer user_data)1448 on_sheets_edit_dialog_entry_sheet_name_changed
1449                                         (GtkEditable     *editable,
1450                                         gpointer         user_data)
1451 {
1452   gtk_object_set_data(GTK_OBJECT(editable), "changed", (gpointer)TRUE);
1453 }
1454 
1455 static GtkWidget *
sheets_dialog_get_target_wrapbox(GtkWidget * wrapbox)1456 sheets_dialog_get_target_wrapbox(GtkWidget *wrapbox)
1457 {
1458   if (gtk_object_get_data(GTK_OBJECT(wrapbox), "is_left"))
1459     return gtk_object_get_data(GTK_OBJECT(sheets_dialog), "wrapbox_right");
1460   else
1461     return gtk_object_get_data(GTK_OBJECT(sheets_dialog), "wrapbox_left");
1462 }
1463 
1464 static void
sheets_dialog_copy_object(GtkWidget * active_button,GtkWidget * target_wrapbox)1465 sheets_dialog_copy_object(GtkWidget *active_button, GtkWidget *target_wrapbox)
1466 {
1467   GtkWidget *button;
1468   SheetMod *sm;
1469   SheetObjectMod *som;
1470   SheetObjectMod *som_new;
1471 
1472   sm = gtk_object_get_data(GTK_OBJECT(target_wrapbox), "sheet_mod");
1473   som = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_object_mod");
1474 
1475   if (!som)
1476     return;
1477 
1478 
1479   som_new = g_new0(SheetObjectMod, 1);
1480   {
1481     SheetObject *so = &som_new->sheet_object;
1482 
1483     so->object_type = g_strdup(som->sheet_object.object_type);
1484     so->description = g_strdup(som->sheet_object.description);
1485     so->pixmap = som->sheet_object.pixmap;
1486     so->user_data = som->sheet_object.user_data;
1487     so->user_data_type = som->sheet_object.user_data_type;
1488     so->line_break = FALSE;          /* must be false--we don't copy linebreaks */
1489     so->pixmap_file = g_strdup(som->sheet_object.pixmap_file);
1490     so->has_icon_on_sheet = som->sheet_object.has_icon_on_sheet;
1491   }
1492 
1493   som_new->type = som->type;
1494   som_new->mod = SHEET_OBJECT_MOD_NONE;
1495 
1496   sm->sheet.objects = g_slist_append(sm->sheet.objects, som_new);
1497   if (sm->mod == SHEETMOD_MOD_NONE)
1498     sm->mod = SHEETMOD_MOD_CHANGED;
1499 
1500   button = sheets_dialog_create_object_button(som_new, sm, target_wrapbox);
1501   gtk_wrap_box_pack(GTK_WRAP_BOX(target_wrapbox), button,
1502                     FALSE, TRUE, FALSE, TRUE);
1503   gtk_widget_show(button);
1504 
1505   sheets_dialog_apply_revert_set_sensitive(TRUE);
1506 }
1507 
1508 void
on_sheets_dialog_button_copy_clicked(GtkButton * button,gpointer user_data)1509 on_sheets_dialog_button_copy_clicked   (GtkButton       *button,
1510                                         gpointer         user_data)
1511 {
1512   GtkWidget *active_button;
1513   GtkWidget *wrapbox;
1514   GList *button_list;
1515   GtkWidget *target_wrapbox;
1516 
1517   active_button = sheets_dialog_get_active_button(&wrapbox, &button_list);
1518 
1519   target_wrapbox = sheets_dialog_get_target_wrapbox(wrapbox);
1520 
1521   sheets_dialog_copy_object(active_button, target_wrapbox);
1522 }
1523 
1524 void
on_sheets_dialog_button_copy_all_clicked(GtkButton * button,gpointer user_data)1525 on_sheets_dialog_button_copy_all_clicked
1526                                         (GtkButton       *button,
1527                                         gpointer         user_data)
1528 {
1529   GtkWidget *active_button;
1530   GtkWidget *wrapbox;
1531   GList *button_list, *iter_list;
1532   GtkWidget *target_wrapbox;
1533 
1534   active_button = sheets_dialog_get_active_button(&wrapbox, &button_list);
1535 
1536   target_wrapbox = sheets_dialog_get_target_wrapbox(wrapbox);
1537 
1538   for (iter_list = button_list; iter_list; iter_list = g_list_next(iter_list))
1539     sheets_dialog_copy_object(iter_list->data, target_wrapbox);
1540 }
1541 
1542 void
on_sheets_dialog_button_move_clicked(GtkButton * button,gpointer user_data)1543 on_sheets_dialog_button_move_clicked   (GtkButton       *button,
1544                                         gpointer         user_data)
1545 {
1546   GtkWidget *active_button;
1547   GtkWidget *wrapbox;
1548   GList *button_list;
1549   GtkWidget *target_wrapbox;
1550   SheetObjectMod *som;
1551   GtkWidget *new_active_button;
1552 
1553   active_button = sheets_dialog_get_active_button(&wrapbox, &button_list);
1554 
1555   target_wrapbox = sheets_dialog_get_target_wrapbox(wrapbox);
1556 
1557   sheets_dialog_copy_object(active_button, target_wrapbox);
1558 
1559   som = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_object_mod");
1560   if (som) {
1561     SheetMod *sm;
1562 
1563     som->mod = SHEET_OBJECT_MOD_DELETED;
1564     /* also mark the source sheet as changed */
1565     sm = gtk_object_get_data(GTK_OBJECT(active_button), "sheet_mod");
1566     sm->mod = SHEETMOD_MOD_CHANGED;
1567   }
1568 
1569   new_active_button = sheets_dialog_set_new_active_button();
1570 
1571   gtk_widget_destroy(active_button);
1572   radio_group = gtk_radio_button_group(GTK_RADIO_BUTTON(new_active_button));
1573 
1574   sheets_dialog_normalize_line_breaks(wrapbox, SHEETS_DIALOG_MOVE_NONE);
1575 }
1576 
1577 void
on_sheets_dialog_button_move_all_clicked(GtkButton * button,gpointer user_data)1578 on_sheets_dialog_button_move_all_clicked
1579                                         (GtkButton       *button,
1580                                         gpointer         user_data)
1581 {
1582   GtkWidget *active_button;
1583   GtkWidget *wrapbox;
1584   GList *button_list;
1585   GList *iter_list;
1586   GtkWidget *target_wrapbox;
1587   SheetObjectMod *som;
1588 
1589   active_button = sheets_dialog_get_active_button(&wrapbox, &button_list);
1590 
1591   target_wrapbox = sheets_dialog_get_target_wrapbox(wrapbox);
1592 
1593   for (iter_list = button_list; iter_list; iter_list = g_list_next(iter_list))
1594   {
1595     sheets_dialog_copy_object(iter_list->data, target_wrapbox);
1596 
1597     som = gtk_object_get_data(GTK_OBJECT(iter_list->data), "sheet_object_mod");
1598     if (som)
1599       som->mod = SHEET_OBJECT_MOD_DELETED;
1600 
1601     gtk_widget_destroy(iter_list->data);
1602 
1603     /* MCNFIXME:  do we have to resanitize the radio_group? */
1604   }
1605 
1606   /* Force the 1st button in the target wrapbox to be active after moving */
1607 
1608   button_list = gtk_container_children(GTK_CONTAINER(target_wrapbox));
1609   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button_list->data), TRUE);
1610 }
1611 
1612 static gboolean
copy_file(gchar * src,gchar * dst)1613 copy_file(gchar *src, gchar *dst)
1614 {
1615   FILE *fp_src;
1616   FILE *fp_dst;
1617   int c;
1618 
1619   if ((fp_src = g_fopen(src, "rb")) == NULL)
1620   {
1621     message_error(_("Couldn't open '%s': %s"),
1622 		  dia_message_filename(src), strerror(errno));
1623     return FALSE;
1624   }
1625 
1626   if ((fp_dst = g_fopen(dst, "wb")) == NULL)
1627   {
1628     message_error(_("Couldn't open '%s': %s"),
1629 		  dia_message_filename(dst), strerror(errno));
1630     return FALSE;
1631   }
1632 
1633   while ((c = fgetc(fp_src)) != EOF)
1634     fputc(c, fp_dst);
1635 
1636   fclose(fp_src);
1637   fclose(fp_dst);
1638 
1639   return TRUE;
1640 }
1641 
1642 /* write a sheet to ~/.dia/sheets */
1643 static gboolean
write_user_sheet(Sheet * sheet)1644 write_user_sheet(Sheet *sheet)
1645 {
1646   FILE *file;
1647   xmlDocPtr doc;
1648   xmlNodePtr root;
1649   xmlNodePtr node;
1650   xmlNodePtr object_node;
1651   xmlNodePtr desc_node;
1652   xmlNodePtr icon_node;
1653   gchar buf[512];
1654   time_t time_now;
1655   const char *username;
1656   gchar *dir_user_sheets;
1657   gchar *filename;
1658   SheetObject *sheetobject;
1659   GSList *sheet_objects;
1660 
1661   dir_user_sheets = dia_config_filename("sheets");
1662   if (!*(sheet->filename))
1663   {
1664     gchar *basename;
1665 
1666     basename = g_strdup(sheet->name);
1667     basename = g_strdelimit(basename, G_STR_DELIMITERS G_DIR_SEPARATOR_S, '_');
1668     filename = g_strdup_printf("%s%s%s.sheet", dir_user_sheets,
1669                                G_DIR_SEPARATOR_S, basename);
1670     g_free(basename);
1671   }
1672   else
1673     filename = g_strdup_printf("%s%s%s", dir_user_sheets,
1674                                G_DIR_SEPARATOR_S, g_basename(sheet->filename));
1675 
1676   file = g_fopen(filename, "w");
1677 
1678   if (file==NULL)
1679   {
1680     message_error(_("Couldn't open: '%s' for writing"),
1681 		  dia_message_filename(filename));
1682     g_free(filename);
1683     return FALSE;
1684   }
1685   fclose(file);
1686 
1687   time_now = time(NULL);
1688   username = g_get_user_name();
1689   if (username==NULL)
1690     username = _("a user");
1691 
1692   doc = xmlNewDoc((const xmlChar *)"1.0");
1693   doc->encoding = xmlStrdup((const xmlChar *)"UTF-8");
1694   doc->standalone = FALSE;
1695   root = xmlNewDocNode(doc, NULL, (const xmlChar *)"sheet", NULL);
1696   doc->xmlRootNode = root;
1697   xmlSetProp(root, (const xmlChar *)"xmlns", (const xmlChar *) DIA_XML_NAME_SPACE_BASE "dia-sheet-ns");
1698 
1699   /* comments */
1700   xmlAddChild(root, xmlNewText((const xmlChar *)"\n"));
1701   xmlAddChild(root, xmlNewComment((const xmlChar *)"Dia-Version: "VERSION));
1702   xmlAddChild(root, xmlNewText((const xmlChar *)"\n"));
1703   g_snprintf(buf, sizeof(buf), _("File: %s"), filename);
1704   xmlAddChild(root, xmlNewComment((xmlChar *)buf));
1705   xmlAddChild(root, xmlNewText((const xmlChar *)"\n"));
1706   g_snprintf(buf, sizeof(buf), _("Date: %s"), ctime(&time_now));
1707   buf[strlen(buf)-1] = '\0'; /* remove the trailing new line */
1708   xmlAddChild(root, xmlNewComment((xmlChar *)buf));
1709   xmlAddChild(root, xmlNewText((const xmlChar *)"\n"));
1710   g_snprintf(buf, sizeof(buf), _("For: %s"), username);
1711   xmlAddChild(root, xmlNewComment((xmlChar *)buf));
1712   xmlAddChild(root, xmlNewText((const xmlChar *)"\n\n"));
1713 
1714   /* sheet name */
1715   node = xmlNewChild(root, NULL, (const xmlChar *)"name", NULL);
1716   xmlAddChild(node, xmlNewText((xmlChar *)sheet->name));
1717   xmlAddChild(root, xmlNewText((const xmlChar *)"\n"));
1718 
1719   /* sheet description */
1720   node = xmlNewChild(root, NULL, (const xmlChar *)"description", NULL);
1721   xmlAddChild(node, xmlNewText((xmlChar *)sheet->description));
1722   xmlAddChild(root, xmlNewText((const xmlChar *)"\n"));
1723 
1724   /* content */
1725   node = xmlNewChild(root, NULL, (const xmlChar *)"contents", NULL);
1726   xmlAddChild(node, xmlNewText((const xmlChar *)"\n"));
1727   xmlAddChild(node, xmlNewComment((const xmlChar *) _("add shapes here")));
1728   xmlAddChild(node, xmlNewText((const xmlChar *)"\n"));
1729 
1730   /* objects */
1731   for (sheet_objects = sheet->objects; sheet_objects;
1732        sheet_objects = g_slist_next(sheet_objects))
1733   {
1734     SheetObjectMod *som;
1735 
1736     som = sheet_objects->data;
1737 
1738     if (som->mod == SHEET_OBJECT_MOD_DELETED)
1739       continue;
1740 
1741     /* If its a new shape, then copy the .shape and .xpm files from
1742        their current location to ~/.dia/shapes/ */
1743 
1744     if (som->mod == SHEET_OBJECT_MOD_NEW)
1745     {
1746       gchar *dia_user_shapes;
1747       gchar *dest;
1748 
1749       dia_user_shapes = dia_config_filename("shapes");
1750 
1751       dest = g_strdup_printf("%s%s%s", dia_user_shapes, G_DIR_SEPARATOR_S,
1752                              g_basename(som->svg_filename));
1753       copy_file(som->svg_filename, dest);
1754       g_free(dest);
1755 
1756       dest = g_strdup_printf("%s%s%s", dia_user_shapes, G_DIR_SEPARATOR_S,
1757                              g_basename(som->sheet_object.pixmap_file));
1758       copy_file(som->sheet_object.pixmap_file, dest);
1759       g_free(dest);
1760     }
1761 
1762     sheetobject = &som->sheet_object;
1763     object_node = xmlNewChild(node, NULL, (const xmlChar *)"object", NULL);
1764 
1765     xmlSetProp(object_node, (const xmlChar *)"name", (xmlChar *)sheetobject->object_type);
1766 
1767     if (sheetobject->user_data_type == USER_DATA_IS_INTDATA)
1768     {
1769       gchar *user_data;
1770 
1771       user_data = g_strdup_printf("%u", (guint)(sheetobject->user_data));
1772       xmlSetProp(object_node, (const xmlChar *)"intdata", (xmlChar *) user_data);
1773       g_free(user_data);
1774     }
1775 
1776     xmlAddChild(object_node, xmlNewText((const xmlChar *)"\n"));
1777     desc_node = xmlNewChild(object_node, NULL, (const xmlChar *)"description", NULL);
1778     xmlAddChild(desc_node, xmlNewText((xmlChar *) sheetobject->description));
1779     /*    xmlAddChild(object_node, xmlNewText((const xmlChar *)"\n")); */
1780 
1781     if (sheetobject->has_icon_on_sheet == TRUE)
1782     {
1783       gchar *canonical_icon;
1784       gchar *canonical_user_sheets;
1785       gchar *canonical_sheets;
1786       gchar *icon;
1787 
1788       xmlAddChild(object_node, xmlNewText((const xmlChar *)"\n"));
1789       icon_node = xmlNewChild(object_node, NULL, (const xmlChar *)"icon", NULL);
1790       canonical_icon = dia_get_canonical_path(sheetobject->pixmap_file);
1791       icon = canonical_icon;
1792       canonical_user_sheets = dia_get_canonical_path(dir_user_sheets);
1793       canonical_sheets = dia_get_canonical_path(dia_get_data_directory("sheets"));
1794       if(g_str_has_prefix(icon, canonical_user_sheets))
1795         icon += strlen(canonical_user_sheets) + 1;
1796       if(g_str_has_prefix(icon, canonical_sheets))
1797         icon += strlen(canonical_sheets) + 1;
1798       xmlAddChild(icon_node, xmlNewText((xmlChar *) icon));
1799       xmlAddChild(object_node, xmlNewText((const xmlChar *)"\n"));
1800       g_free(canonical_icon);
1801       g_free(canonical_user_sheets);
1802       g_free(canonical_sheets);
1803     }
1804   }
1805   xmlSetDocCompressMode(doc, 0);
1806   xmlDiaSaveFile(filename, doc);
1807   xmlFreeDoc(doc);
1808   return TRUE;
1809 }
1810 
1811 static void
touch_file(gchar * filename)1812 touch_file(gchar *filename)
1813 {
1814   struct stat stat_buf;
1815   struct utimbuf utim_buf;
1816 
1817   g_stat(filename, &stat_buf);
1818   utim_buf.actime = stat_buf.st_atime;
1819   utim_buf.modtime = time(NULL);
1820   utime(filename, &utim_buf);
1821 }
1822 
1823 static gint
sheets_find_sheet(gconstpointer a,gconstpointer b)1824 sheets_find_sheet(gconstpointer a, gconstpointer b)
1825 {
1826   if (!strcmp(((Sheet *)a)->name, ((Sheet *)b)->name))
1827     return 0;
1828   else
1829     return 1;
1830 }
1831 
1832 extern GSList *sheets_mods_list;
1833 
1834 void
on_sheets_dialog_button_apply_clicked(GtkButton * button,gpointer user_data)1835 on_sheets_dialog_button_apply_clicked  (GtkButton       *button,
1836                                         gpointer         user_data)
1837 {
1838   GSList *iter_list;
1839 
1840   for (iter_list = sheets_mods_list; iter_list;
1841        iter_list = g_slist_next(iter_list))
1842   {
1843     SheetMod *sm;
1844     GSList *sheets_list;
1845     GSList *find_list;
1846 
1847     sm = iter_list->data;
1848     switch (sm->mod)
1849     {
1850       GSList *sheet_object_mods_list;
1851       GSList *list;
1852       Sheet *new_sheet = NULL;
1853 
1854     case SHEETMOD_MOD_NEW:
1855       write_user_sheet(&sm->sheet);
1856 
1857       sheet_object_mods_list = sm->sheet.objects;
1858       sm->sheet.objects = NULL;
1859       /* we have to transfer 'permanent' memory */
1860       new_sheet = g_new0 (Sheet, 1);
1861       *new_sheet = sm->sheet;
1862       register_sheet(new_sheet);
1863 
1864       for (list = sheet_object_mods_list; list; list = g_slist_next(list))
1865       {
1866         SheetObjectMod *som;
1867 	SheetObject *new_object;
1868 
1869         som = list->data;
1870         if (som->mod == SHEET_OBJECT_MOD_DELETED)
1871           continue;
1872 
1873 	new_object = g_new0(SheetObject, 1);
1874 	*new_object = som->sheet_object;
1875         sheet_append_sheet_obj(new_sheet, new_object);
1876       }
1877 
1878       dia_sort_sheets();
1879       fill_sheet_menu();
1880       break;
1881 
1882     case SHEETMOD_MOD_CHANGED:
1883       write_user_sheet(&sm->sheet);
1884 
1885       sheet_object_mods_list = sm->sheet.objects;
1886       sheets_list = get_sheets_list();
1887 
1888       sheets_list = g_slist_find_custom(sheets_list, &sm->sheet,
1889                                         sheets_find_sheet);
1890       g_assert(sheets_list);
1891       ((Sheet *)(sheets_list->data))->objects = NULL;
1892 
1893       for (list = sheet_object_mods_list; list; list = g_slist_next(list))
1894       {
1895         SheetObjectMod *som;
1896 	SheetObject *new_object;
1897 
1898         som = list->data;
1899         if (som->mod == SHEET_OBJECT_MOD_DELETED)
1900           continue;
1901 
1902 	new_object = g_new0(SheetObject, 1);
1903 	*new_object = som->sheet_object;
1904         sheet_append_sheet_obj(sheets_list->data, new_object);
1905       }
1906       fill_sheet_menu();
1907       break;
1908 
1909     case SHEETMOD_MOD_DELETED:
1910       if (sm->sheet.scope == SHEET_SCOPE_SYSTEM)
1911         touch_file(sm->sheet.shadowing->filename);
1912       else
1913         g_unlink(sm->sheet.filename);
1914 
1915       sheets_list = get_sheets_list();
1916       find_list = g_slist_find_custom(sheets_list, &sm->sheet,
1917                                         sheets_find_sheet);
1918       g_assert(sheets_list);
1919       if (!g_slist_remove_link(sheets_list, find_list))
1920 	g_warning ("No sheets left?");
1921 
1922       dia_sort_sheets();
1923       fill_sheet_menu();
1924       break;
1925 
1926     case SHEETMOD_MOD_NONE:
1927       break;
1928 
1929     default:
1930       g_assert_not_reached();
1931     }
1932   }
1933   {
1934     optionmenu_activate_first_pass = TRUE;
1935 
1936     sheets_dialog_apply_revert_set_sensitive(FALSE);
1937     sheets_dialog_create();
1938   }
1939 }
1940 
1941 void
on_sheets_dialog_button_revert_clicked(GtkButton * button,gpointer user_data)1942 on_sheets_dialog_button_revert_clicked (GtkButton       *button,
1943                                         gpointer         user_data)
1944 {
1945   optionmenu_activate_first_pass = TRUE;
1946 
1947   sheets_dialog_apply_revert_set_sensitive(FALSE);
1948   sheets_dialog_create();
1949 }
1950 
1951