/*! \todo Finish function documentation!!! * \brief * \par Function Description * * * <B>flag</B> can be one of the following values: * <DL> * <DT>*</DT><DD>UNDO_ALL * <DT>*</DT><DD>UNDO_VIEWPORT_ONLY * </DL> */ void o_undo_savestate (GschemToplevel *w_current, PAGE *page, int flag) { TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current); char *filename = NULL; GList *object_list = NULL; int levels; UNDO *u_current; UNDO *u_current_next; GschemPageView *view = gschem_toplevel_get_current_page_view (w_current); g_return_if_fail (view != NULL); g_return_if_fail (page != NULL); GschemPageGeometry *geometry = gschem_page_view_get_page_geometry (view); /* save autosave backups if necessary */ o_autosave_backups(w_current); if (w_current->undo_control == FALSE) { return; } if (flag == UNDO_ALL) { /* Increment the number of operations since last backup if auto-save is enabled */ if (toplevel->auto_save_interval != 0) { page->ops_since_last_backup++; } /* HACK */ /* Before we save the undo state, consolidate nets as necessary */ /* This is where the net consolidation call would have been * triggered before it was removed from o_save_buffer(). */ if (toplevel->net_consolidate == TRUE) geda_net_object_consolidate (toplevel, page); } if (w_current->undo_type == UNDO_DISK && flag == UNDO_ALL) { filename = g_strdup_printf("%s%cgschem.save%d_%d.sch", tmp_path, G_DIR_SEPARATOR, prog_pid, undo_file_index++); /* Changed from f_save to o_save when adding backup copy creation. */ /* f_save manages the creaton of backup copies. This way, f_save is called only when saving a file, and not when saving an undo backup copy */ o_save (toplevel, s_page_objects (page), filename, NULL); } else if (w_current->undo_type == UNDO_MEMORY && flag == UNDO_ALL) { object_list = o_glist_copy_all (toplevel, s_page_objects (page), object_list); } /* Clear Anything above current */ if (page->undo_current) { s_undo_remove_rest(toplevel, page->undo_current->next); page->undo_current->next = NULL; } else { /* undo current is NULL */ s_undo_remove_rest(toplevel, page->undo_bottom); page->undo_bottom = NULL; } page->undo_tos = page->undo_current; if (geometry != NULL) { page->undo_tos = s_undo_add(page->undo_tos, flag, filename, object_list, (geometry->viewport_left + geometry->viewport_right) / 2, (geometry->viewport_top + geometry->viewport_bottom) / 2, /* scale */ max (((double) abs (geometry->viewport_right - geometry->viewport_left) / geometry->screen_width), ((double) abs (geometry->viewport_top - geometry->viewport_bottom) / geometry->screen_height)), page->page_control, page->up); } else { page->undo_tos = s_undo_add(page->undo_tos, flag, filename, object_list, 0, /* center x */ 0, /* center y */ 0, /* scale */ page->page_control, page->up); } page->undo_current = page->undo_tos; if (page->undo_bottom == NULL) { page->undo_bottom = page->undo_tos; } #if DEBUG printf("\n\n---Undo----\n"); s_undo_print_all(page->undo_bottom); printf("BOTTOM: %s\n", page->undo_bottom->filename); printf("TOS: %s\n", page->undo_tos->filename); printf("CURRENT: %s\n", page->undo_current->filename); printf("----\n"); #endif g_free(filename); /* Now go through and see if we need to free/remove some undo levels */ /* so we stay within the limits */ /* only check history every 10 undo savestates */ if (undo_file_index % 10) { return; } levels = s_undo_levels(page->undo_bottom); #if DEBUG printf("levels: %d\n", levels); #endif if (levels >= w_current->undo_levels + UNDO_PADDING) { levels = levels - w_current->undo_levels; #if DEBUG printf("Trimming: %d levels\n", levels); #endif u_current = page->undo_bottom; while (levels > 0) { /* Because we use a pad you are always guaranteed to never */ /* exhaust the list */ g_assert (u_current != NULL); u_current_next = u_current->next; if (u_current->filename) { #if DEBUG printf("Freeing: %s\n", u_current->filename); #endif unlink(u_current->filename); g_free(u_current->filename); } if (u_current->object_list) { geda_object_list_delete (toplevel, u_current->object_list); u_current->object_list = NULL; } u_current->next = NULL; u_current->prev = NULL; g_free(u_current); u_current = u_current_next; levels--; } g_assert (u_current != NULL); u_current->prev = NULL; page->undo_bottom = u_current; #if DEBUG printf("New current is: %s\n", u_current->filename); #endif } #if DEBUG printf("\n\n---Undo----\n"); s_undo_print_all(page->undo_bottom); printf("BOTTOM: %s\n", page->undo_bottom->filename); printf("TOS: %s\n", page->undo_tos->filename); printf("CURRENT: %s\n", page->undo_current->filename); printf("----\n"); #endif }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * * * <B>flag</B> can be one of the following values: * <DL> * <DT>*</DT><DD>UNDO_ALL * <DT>*</DT><DD>UNDO_VIEWPORT_ONLY * </DL> */ void o_undo_savestate(GSCHEM_TOPLEVEL *w_current, int flag) { TOPLEVEL *toplevel = w_current->toplevel; char *filename = NULL; GList *object_list = NULL; int levels; UNDO *u_current; UNDO *u_current_next; /* save autosave backups if necessary */ o_autosave_backups(w_current); if (w_current->undo_control == FALSE) { return; } if (flag == UNDO_ALL) { /* Increment the number of operations since last backup if auto-save is enabled */ if (toplevel->auto_save_interval != 0) { toplevel->page_current->ops_since_last_backup++; } /* HACK */ /* Before we save the undo state, consolidate nets as necessary */ /* This is where the net consolidation call would have been * triggered before it was removed from o_save_buffer(). */ if (toplevel->net_consolidate == TRUE) o_net_consolidate (toplevel, toplevel->page_current); } if (w_current->undo_type == UNDO_DISK && flag == UNDO_ALL) { filename = g_strdup_printf("%s%cgschem.save%d_%d.sch", tmp_path, G_DIR_SEPARATOR, prog_pid, undo_file_index++); /* Changed from f_save to o_save when adding backup copy creation. */ /* f_save manages the creaton of backup copies. This way, f_save is called only when saving a file, and not when saving an undo backup copy */ o_save (toplevel, s_page_objects (toplevel->page_current), filename, NULL); } else if (w_current->undo_type == UNDO_MEMORY && flag == UNDO_ALL) { object_list = o_glist_copy_all (toplevel, s_page_objects (toplevel->page_current), object_list); } /* Clear Anything above current */ if (toplevel->page_current->undo_current) { s_undo_remove_rest(toplevel, toplevel->page_current->undo_current->next); toplevel->page_current->undo_current->next = NULL; } else { /* undo current is NULL */ s_undo_remove_rest(toplevel, toplevel->page_current->undo_bottom); toplevel->page_current->undo_bottom = NULL; } toplevel->page_current->undo_tos = toplevel->page_current->undo_current; toplevel->page_current->undo_tos = s_undo_add(toplevel->page_current->undo_tos, flag, filename, object_list, toplevel->page_current->left, toplevel->page_current->top, toplevel->page_current->right, toplevel->page_current->bottom, toplevel->page_current->page_control, toplevel->page_current->up); toplevel->page_current->undo_current = toplevel->page_current->undo_tos; if (toplevel->page_current->undo_bottom == NULL) { toplevel->page_current->undo_bottom = toplevel->page_current->undo_tos; } #if DEBUG printf("\n\n---Undo----\n"); s_undo_print_all(toplevel->page_current->undo_bottom); printf("BOTTOM: %s\n", toplevel->page_current->undo_bottom->filename); printf("TOS: %s\n", toplevel->page_current->undo_tos->filename); printf("CURRENT: %s\n", toplevel->page_current->undo_current->filename); printf("----\n"); #endif g_free(filename); /* Now go through and see if we need to free/remove some undo levels */ /* so we stay within the limits */ /* only check history every 10 undo savestates */ if (undo_file_index % 10) { return; } levels = s_undo_levels(toplevel->page_current->undo_bottom); #if DEBUG printf("levels: %d\n", levels); #endif if (levels >= w_current->undo_levels + UNDO_PADDING) { levels = levels - w_current->undo_levels; #if DEBUG printf("Trimming: %d levels\n", levels); #endif u_current = toplevel->page_current->undo_bottom; while(u_current && levels > 0) { u_current_next = u_current->next; if (u_current->filename) { #if DEBUG printf("Freeing: %s\n", u_current->filename); #endif unlink(u_current->filename); g_free(u_current->filename); } if (u_current->object_list) { s_delete_object_glist (toplevel, u_current->object_list); u_current->object_list = NULL; } u_current->next = NULL; u_current->prev = NULL; g_free(u_current); u_current = u_current_next; levels--; } /* Because we use a pad you are always garanteed to never */ /* exhaust the list */ u_current->prev = NULL; toplevel->page_current->undo_bottom = u_current; #if DEBUG printf("New current is: %s\n", u_current->filename); #endif } #if DEBUG printf("\n\n---Undo----\n"); s_undo_print_all(toplevel->page_current->undo_bottom); printf("BOTTOM: %s\n", toplevel->page_current->undo_bottom->filename); printf("TOS: %s\n", toplevel->page_current->undo_tos->filename); printf("CURRENT: %s\n", toplevel->page_current->undo_current->filename); printf("----\n"); #endif }