Index: undo.c =================================================================== --- undo.c (revision 10673) +++ undo.c (revision 10674) @@ -28,7 +28,7 @@ * * Description: * There are two lists which hold - * - information about a command + * - the uundo list (information about a command) * - data of removed objects * Both lists are organized as first-in-last-out which means that the undo * list can always use the last entry of the remove list. @@ -43,7 +43,6 @@ #include "config.h" #include -#include #include #include "board.h" @@ -66,83 +65,22 @@ #include "obj_elem_draw.h" #include "obj_poly_draw.h" -#define STEP_REMOVELIST 500 -#define STEP_UNDOLIST 500 - static pcb_bool between_increment_and_restore = pcb_false; static pcb_bool added_undo_between_increment_and_restore = pcb_false; -#include "undo_old_str.h" +pcb_data_t *RemoveList = NULL; /* lists of removed objects */ +static pcb_bool Locked = pcb_false; /* do not add entries if */ +pcb_bool pcb_undo_and_draw = pcb_true; /* flag is set; prevents from infinite loops */ +static uundo_list_t pcb_uundo; -pcb_data_t *RemoveList = NULL; /* list of removed objects */ -static UndoListTypePtr UndoList = NULL; /* list of operations */ -static int Serial = 1, /* serial number */ - SavedSerial; -static size_t UndoN, RedoN, /* number of entries */ - UndoMax; -static pcb_bool Locked = pcb_false; /* do not add entries if */ -pcb_bool pcb_undo_and_draw = pcb_true; - /* flag is set; prevents from */ - /* infinite loops */ - -/* --------------------------------------------------------------------------- - * adds a command plus some data to the undo list - */ -void *GetUndoSlot(int CommandType, int ID, int Kind, size_t item_len) +void *pcb_undo_alloc(pcb_board_t *pcb, const uundo_oper_t *oper, size_t data_len) { - UndoListTypePtr ptr; - size_t limit = ((size_t)conf_core.editor.undo_warning_size) * 1024; - -#ifdef DEBUG_ID - if (pcb_search_obj_by_id(PCB->Data, &ptr1, &ptr2, &ptr3, ID, Kind) == PCB_TYPE_NONE) - pcb_message(PCB_MSG_ERROR, "hace: ID (%d) and Type (%x) mismatch in AddObject...\n", ID, Kind); -#endif - - /* allocate memory */ - if (UndoN >= UndoMax) { - size_t size; - - UndoMax += STEP_UNDOLIST; - size = UndoMax * item_len; - UndoList = (UndoListTypePtr) realloc(UndoList, size); - memset(&UndoList[UndoN], 0, STEP_REMOVELIST * item_len); - - /* ask user to flush the table because of it's size */ - if (size > limit) { - size_t l2; - l2 = (size / limit + 1) * limit; - pcb_message(PCB_MSG_INFO, _("Size of 'undo-list' exceeds %li kb\n"), (long) (l2 >> 10)); - } - } - - /* free structures from the pruned redo list */ - - for (ptr = &UndoList[UndoN]; RedoN; ptr++, RedoN--) - pcb_undo_old_free(ptr); - - if (between_increment_and_restore) - added_undo_between_increment_and_restore = pcb_true; - - /* copy typefield and serial number to the list */ - ptr = &UndoList[UndoN++]; - ptr->Type = CommandType; - ptr->Kind = Kind; - ptr->ID = ID; - ptr->Serial = Serial; - return (ptr); + return uundo_append(&pcb_uundo, oper, data_len); } -/* --------------------------------------------------------------------------- - * undo of any 'hard to recover' operation - * - * returns the bitfield for the types of operations that were undone - */ int pcb_undo(pcb_bool draw) { - UndoListTypePtr ptr; - int Types = 0; - int unique; - pcb_bool error_undoing = pcb_false; + int res, unique; unique = conf_core.editor.unique_names; conf_force_set_bool(conf_core.editor.unique_names, 0); @@ -149,20 +87,17 @@ pcb_undo_and_draw = draw; - if (Serial == 0) { + if (pcb_uundo.serial == 0) { pcb_message(PCB_MSG_ERROR, _("ERROR: Attempt to pcb_undo() with Serial == 0\n" " Please save your work and report this bug.\n")); return 0; } - if (UndoN == 0) { + if (pcb_uundo.num_undo == 0) { pcb_message(PCB_MSG_INFO, _("Nothing to undo - buffer is empty\n")); return 0; } - Serial--; - - ptr = &UndoList[UndoN - 1]; - +#ifdef TODO if (ptr->Serial > Serial) { pcb_message(PCB_MSG_ERROR, _("ERROR: Bad undo serial number %d in undo stack - expecting %d or lower\n" " Please save your work and report this bug.\n"), ptr->Serial, Serial); @@ -177,51 +112,35 @@ Serial = ptr->Serial + 1; return 0; } +#endif - pcb_undo_lock(); /* lock undo module to prevent from loops */ - - /* Loop over all entries with the correct serial number */ - for (; UndoN && ptr->Serial == Serial; ptr--, UndoN--, RedoN++) { - int undid = pcb_undo_old_perform(ptr); - if (undid == 0) - error_undoing = pcb_true; - Types |= undid; - } - + pcb_undo_lock(); /* lock undo module to prevent from loops */ + res = uundo_undo(&pcb_uundo); pcb_undo_unlock(); - if (error_undoing) + if (res != 0) pcb_message(PCB_MSG_ERROR, _("ERROR: Failed to undo some operations\n")); - - if (Types && pcb_undo_and_draw) + else if (pcb_undo_and_draw) pcb_draw(); /* restore the unique flag setting */ conf_force_set_bool(conf_core.editor.unique_names, unique); - return Types; + return res; } -/* --------------------------------------------------------------------------- - * redo of any 'hard to recover' operation - * - * returns the number of operations redone - */ int pcb_redo(pcb_bool draw) { - UndoListTypePtr ptr; - int Types = 0; - pcb_bool error_undoing = pcb_false; + int res; pcb_undo_and_draw = draw; - if (RedoN == 0) { + if (pcb_uundo.num_redo == 0) { pcb_message(PCB_MSG_INFO, _("Nothing to redo. Perhaps changes have been made since last undo\n")); return 0; } - ptr = &UndoList[UndoN]; - +#if TODO if (ptr->Serial < Serial) { pcb_message(PCB_MSG_ERROR, _("ERROR: Bad undo serial number %d in redo stack - expecting %d or higher\n" " Please save your work and report this bug.\n"), ptr->Serial, Serial); @@ -236,29 +155,18 @@ Serial = ptr->Serial; return 0; } +#endif - pcb_undo_lock(); /* lock undo module to prevent from loops */ - - /* and loop over all entries with the correct serial number */ - for (; RedoN && ptr->Serial == Serial; ptr++, UndoN++, RedoN--) { - int undid = pcb_undo_old_perform(ptr); - if (undid == 0) - error_undoing = pcb_true; - Types |= undid; - } - - /* Make next serial number current */ - Serial++; - + pcb_undo_lock(); /* lock undo module to prevent from loops */ + res = uundo_redo(&pcb_uundo); pcb_undo_unlock(); - if (error_undoing) + if (res != 0) pcb_message(PCB_MSG_ERROR, _("ERROR: Failed to redo some operations\n")); - - if (Types && pcb_undo_and_draw) + else if (pcb_undo_and_draw) pcb_draw(); - return Types; + return res; } /* --------------------------------------------------------------------------- @@ -270,7 +178,7 @@ pcb_message(PCB_MSG_ERROR, _("ERROR: Operations were added to the Undo stack with an incorrect serial number\n")); between_increment_and_restore = pcb_false; added_undo_between_increment_and_restore = pcb_false; - Serial = SavedSerial; + uundo_restore_serial(&pcb_uundo); } /* --------------------------------------------------------------------------- @@ -281,7 +189,7 @@ pcb_bumped = pcb_false; between_increment_and_restore = pcb_false; added_undo_between_increment_and_restore = pcb_false; - SavedSerial = Serial; + uundo_save_serial(&pcb_uundo); } /* --------------------------------------------------------------------------- @@ -292,10 +200,12 @@ void pcb_undo_inc_serial(void) { if (!Locked) { +#if TODO /* Set the changed flag if anything was added prior to this bump */ if (UndoN > 0 && UndoList[UndoN - 1].Serial == Serial) pcb_board_set_changed_flag(pcb_true); - Serial++; +#endif + uundo_inc_serial(&pcb_uundo); pcb_bumped = pcb_true; between_increment_and_restore = pcb_true; } @@ -306,27 +216,8 @@ */ void pcb_undo_clear_list(pcb_bool Force) { - UndoListTypePtr undo; - - if (UndoN && (Force || pcb_gui->confirm_dialog("OK to clear 'undo' buffer?", 0))) { - /* release memory allocated by objects in undo list */ - for (undo = UndoList; UndoN; undo++, UndoN--) - pcb_undo_old_free(undo); - - free(UndoList); - UndoList = NULL; - if (RemoveList) { - pcb_data_free(RemoveList); - free(RemoveList); - RemoveList = NULL; - } - - /* reset some counters */ - UndoN = UndoMax = RedoN = 0; - } - - /* reset counter in any case */ - Serial = 1; + if (pcb_uundo.num_undo && (Force || pcb_gui->confirm_dialog("OK to clear 'undo' buffer?", 0))) + uundo_list_clear(&pcb_uundo); } /* --------------------------------------------------------------------------- @@ -355,42 +246,21 @@ int undo_check(void) { - size_t n; - int last_serial = -2; - for(n = 0; n < UndoN; n++) { - if (last_serial != UndoList[n].Serial) { - if (last_serial > UndoList[n].Serial) { -# ifndef NDEBUG - printf("Undo broken check #1:\n"); - undo_dump(); -# endif - return 1; - } - last_serial = UndoList[n].Serial; - } + const char *res = uundo_check(&pcb_uundo, NULL); + +#ifndef NDEBUG + if (res != NULL) { + printf("Undo broken: %s\n", res); + uundo_dump(&pcb_uundo, NULL, NULL); } - if (Serial < last_serial) { -# ifndef NDEBUG - printf("Undo broken check #2:\n"); - undo_dump(); -# endif - return 1; - } - return 0; +#endif + + return (res != NULL); } #ifndef NDEBUG void undo_dump(void) { - size_t n; - int last_serial = -2; - printf("Serial=%d\n", Serial); - for(n = 0; n < UndoN; n++) { - if (last_serial != UndoList[n].Serial) { - printf("--- serial=%d\n", UndoList[n].Serial); - last_serial = UndoList[n].Serial; - } - printf(" type=%s kind=%d ID=%d\n", undo_type2str(UndoList[n].Type), UndoList[n].Kind, UndoList[n].ID); - } + uundo_dump(&pcb_uundo, NULL, NULL); } #endif