1 /* gEDA - GPL Electronic Design Automation
2 * gschem - gEDA Schematic Capture
3 * Copyright (C) 1998-2007 Ales Hvezda
4 * Copyright (C) 1998-2007 gEDA Contributors (see ChangeLog for details)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
33 #ifdef HAVE_LIBDMALLOC
37 static int undo_file_index
=0;
38 static int prog_pid
=0;
40 static char* tmp_path
= NULL
;
42 /* this is additional number of levels (or history) at which point the */
43 /* undo stack will be trimmed, it's used a safety to prevent running out */
44 /* of entries to free */
45 #define UNDO_PADDING 5
47 /*! \todo Finish function documentation!!!
49 * \par Function Description
52 void o_undo_init(void)
56 tmp_path
= g_strdup (getenv("TMP"));
57 if (tmp_path
== NULL
) {
58 tmp_path
= g_strdup ("/tmp");
61 printf("%s\n", tmp_path
);
65 /*! \todo Finish function documentation!!!
67 * \par Function Description
70 * <B>flag</B> can be one of the following values:
72 * <DT>*</DT><DD>UNDO_ALL
73 * <DT>*</DT><DD>UNDO_VIEWPORT_ONLY
76 void o_undo_savestate(GSCHEM_TOPLEVEL
*w_current
, int flag
)
78 TOPLEVEL
*toplevel
= w_current
->toplevel
;
79 PAGE
*page
= toplevel
->page_current
;
80 char *filename
= NULL
;
81 OBJECT
*object_head
= NULL
;
84 /* save autosave backups if necessary */
85 o_autosave_backups(w_current
);
87 if (w_current
->undo_control
== FALSE
) {
91 if (w_current
->undo_type
== UNDO_DISK
&& flag
== UNDO_ALL
) {
92 /* Increment the number of operations since last backup if
93 auto-save is enabled */
94 if (toplevel
->auto_save_interval
!= 0) {
95 page
->ops_since_last_backup
++;
98 filename
= g_strdup_printf("%s%cgschem.save%d_%d.sch",
99 tmp_path
, G_DIR_SEPARATOR
,
100 prog_pid
, undo_file_index
++);
102 /* Changed from f_save to o_save when adding backup copy creation. */
103 /* f_save manages the creation of backup copies.
104 This way, f_save is called only when saving a file, and not when
105 saving an undo backup copy */
106 o_save(toplevel
, page
, filename
);
107 } else if (w_current
->undo_type
== UNDO_MEMORY
&& flag
== UNDO_ALL
) {
108 /* Increment the number of operations since last backup if
109 auto-save is enabled */
110 if (toplevel
->auto_save_interval
!= 0) {
111 page
->ops_since_last_backup
++;
114 object_head
= s_toplevel_new_object(toplevel
, OBJ_HEAD
, "undo_head");
116 o_list_copy_all(toplevel
, page
->object_head
->next
,
117 object_head
, NORMAL_FLAG
);
120 s_undo_add(toplevel
, page
, flag
, filename
, object_head
,
121 page
->left
, page
->top
, page
->right
, page
->bottom
,
122 page
->page_control
, page
->up_page
);
125 printf("\n\n---Undo----\n");
126 s_undo_print_all(page
);
132 /* Now go through and see if we need to free/remove some undo levels */
133 /* so we stay within the limits */
135 /* only check history every 10 undo savestates */
136 if (undo_file_index
% 10) {
141 levels
= s_undo_levels(page
);
143 printf("levels: %d\n", levels
);
146 s_undo_trim(toplevel
, page
,
147 w_current
->undo_levels
+ UNDO_PADDING
);
150 printf("\n\n---Undo----\n");
151 s_undo_print_all(page
);
156 /*! \todo Finish function documentation!!!
158 * \par Function Description
160 * <B>type</B> can be one of the following values:
162 * <DT>*</DT><DD>UNDO_ACTION
163 * <DT>*</DT><DD>REDO_ACTION
166 void o_undo_callback(GSCHEM_TOPLEVEL
*w_current
, int type
)
168 TOPLEVEL
*toplevel
= w_current
->toplevel
;
169 PAGE
*page
= toplevel
->page_current
;
171 GList
*old_state
, *new_state
;
176 int find_prev_data
=FALSE
;
181 if (w_current
->undo_control
== FALSE
) {
182 s_log_message(_("Undo/Redo disabled in rc file\n"));
186 if (page
->undo_current
== NULL
) {
192 new_state
= page
->undo_current
->next
;
195 new_state
= page
->undo_current
->prev
;
201 old_state
= page
->undo_current
;
203 if (new_state
== NULL
) {
204 /* There is no state to undo/redo to. */
208 u_new
= new_state
->data
;
209 u_old
= old_state
->data
;
211 switch (w_current
->undo_type
) {
213 if (u_new
->filename
== NULL
) {
214 s_log_message(_("File-based undo requested with no file\n"));
219 if (u_new
->object_head
== NULL
) {
220 s_log_message(_("In-memory undo requested with no object list\n"));
225 s_log_message(_("Unknown undo type\n"));
229 if (u_old
->type
== UNDO_ALL
&& u_new
->type
== UNDO_VIEWPORT_ONLY
) {
231 printf("Type: %d\n", u_new
->type
);
232 printf("Current is an undo all, next is viewport only!\n");
234 find_prev_data
= TRUE
;
236 o_undo_copy_prev_memento(new_state
, w_current
->undo_type
);
240 save_filename
= g_strdup (page
->page_filename
);
242 /* save structure so it's not nuked */
243 save_newest
= page
->undo_newest
;
244 page
->undo_newest
= NULL
;
245 page
->undo_current
= NULL
;
247 switch (w_current
->undo_type
) {
249 p_new
= s_page_new(toplevel
, u_new
->filename
);
252 p_new
= s_page_new (toplevel
, save_filename
);
255 /* We handled the default case gracefully earlier. */
258 p_new
->width
= w_current
->win_width
;
259 p_new
->height
= w_current
->win_height
;
260 s_toplevel_goto_page(toplevel
, p_new
);
261 set_window(toplevel
, p_new
,
262 toplevel
->init_left
, toplevel
->init_right
,
263 toplevel
->init_top
, toplevel
->init_bottom
);
265 s_hierarchy_replace_page(toplevel
, page
, p_new
);
267 /* Finally delete the page now that the new page is linked. */
268 s_page_delete (toplevel
, page
);
270 /* temporarily disable logging */
271 save_logging
= do_logging
;
272 prev_status
= toplevel
->DONT_REDRAW
;
273 toplevel
->DONT_REDRAW
= 1;
276 if (w_current
->undo_type
== UNDO_DISK
&& u_new
->filename
) {
277 f_open(toplevel
, p_new
, u_new
->filename
, NULL
);
279 x_manual_resize(w_current
);
280 p_new
->page_control
= u_new
->page_control
;
281 p_new
->up_page
= u_new
->up_page
;
283 } else if (w_current
->undo_type
== UNDO_MEMORY
&& u_new
->object_head
) {
284 s_delete_list_fromstart(toplevel
, p_new
->object_head
);
286 p_new
->object_head
= s_toplevel_new_object(toplevel
, OBJ_HEAD
, "object_head");
288 o_list_copy_all(toplevel
, u_new
->object_head
->next
,
292 p_new
->object_tail
= return_tail(p_new
->object_head
);
293 x_manual_resize(w_current
);
294 p_new
->page_control
= u_new
->page_control
;
295 p_new
->up_page
= u_new
->up_page
;
300 set_window(toplevel
, p_new
,
301 u_new
->left
, u_new
->right
,
302 u_new
->top
, u_new
->bottom
);
303 x_hscrollbar_update(w_current
);
304 x_vscrollbar_update(w_current
);
306 /* restore logging */
307 do_logging
= save_logging
;
309 /* set filename right */
310 g_free(p_new
->page_filename
);
311 p_new
->page_filename
= save_filename
;
314 x_pagesel_update (w_current
);
315 x_multiattrib_update(w_current
, p_new
->selection_list
);
317 /* Let the caller to decide if redraw or not */
318 /* toplevel->DONT_REDRAW = 0; */
319 toplevel
->DONT_REDRAW
= prev_status
;
321 if (!toplevel
->DONT_REDRAW
) {
322 o_redraw_all(w_current
);
324 i_update_menus(w_current
);
326 /* restore saved undo structures */
327 p_new
->undo_newest
= save_newest
;
329 p_new
->undo_current
= new_state
;
331 /* don't have to free data here since filename, object_head are */
332 /* just pointers to the real data (lower in the stack) */
333 if (find_prev_data
) {
334 u_new
->filename
= NULL
;
335 u_new
->object_head
= NULL
;
339 printf("\n\n---Undo----\n");
340 s_undo_print_all(p_new
);
345 /*! \todo Finish function documentation!!!
347 * \par Function Description
350 void o_undo_cleanup(void)
355 for (i
= 0 ; i
< undo_file_index
; i
++) {
356 filename
= g_strdup_printf("%s%cgschem.save%d_%d.sch", tmp_path
,
357 G_DIR_SEPARATOR
, prog_pid
, i
);
366 /*! \todo Finish function documentation!!!
368 * \par Function Description
371 void o_undo_remove_last_undo(GSCHEM_TOPLEVEL
*w_current
)
373 TOPLEVEL
*toplevel
= w_current
->toplevel
;
374 if (toplevel
->page_current
->undo_current
== NULL
) {
378 toplevel
->page_current
->undo_current
=
379 toplevel
->page_current
->undo_current
->next
;