pcb 4.1.1
An interactive printed circuit board layout editor.
|
00001 00054 #ifdef HAVE_CONFIG_H 00055 #include "config.h" 00056 #endif 00057 00058 #include <assert.h> 00059 #include <memory.h> 00060 #include "global.h" 00061 00062 #include "buffer.h" 00063 #include "change.h" 00064 #include "create.h" 00065 #include "data.h" 00066 #include "draw.h" 00067 #include "error.h" 00068 #include "insert.h" 00069 #include "misc.h" 00070 #include "mirror.h" 00071 #include "move.h" 00072 #include "mymem.h" 00073 #include "polygon.h" 00074 #include "remove.h" 00075 #include "rotate.h" 00076 #include "rtree.h" 00077 #include "search.h" 00078 #include "set.h" 00079 #include "undo.h" 00080 #include "strflags.h" 00081 00082 #ifdef HAVE_LIBDMALLOC 00083 #include <dmalloc.h> 00084 #endif 00085 00086 static bool between_increment_and_restore = false; 00087 static bool added_undo_between_increment_and_restore = false; 00088 00089 /* --------------------------------------------------------------------------- 00090 * some local data types 00091 */ 00092 00096 typedef struct 00097 { 00098 char *Name; 00099 } ChangeNameType; 00100 00104 typedef struct 00105 { 00106 Coord DX; 00107 Coord DY; 00108 } MoveType; 00109 00113 typedef struct 00114 { 00115 Coord X; 00116 Coord Y; 00117 int ID; 00118 Cardinal Index; 00119 bool last_in_contour; 00120 } RemovedPointType; 00121 00125 typedef struct 00126 { 00127 Coord CenterX; 00128 Coord CenterY; 00129 Cardinal Steps; 00130 } RotateType; 00131 00135 typedef struct 00136 { 00137 Cardinal OriginalLayer; 00138 } MoveToLayerType; 00139 00143 typedef struct 00144 { 00145 int old_index; 00146 int new_index; 00147 } LayerChangeType; 00148 00152 typedef struct 00153 { 00154 int from; 00155 int to; 00156 } SetViaLayersChangeType; 00157 00161 typedef struct 00162 { 00163 bool Clear; 00164 LayerType *Layer; 00165 } ClearPolyType; 00166 00170 typedef struct 00171 { 00172 LibraryType *old; 00173 LibraryType *lib; 00174 } NetlistChangeType; 00175 00179 typedef struct 00180 { 00181 int Serial, 00182 Type, 00183 Kind, 00184 ID; 00185 union /* Some additional information. */ 00186 { 00187 ChangeNameType ChangeName; 00188 MoveType Move; 00189 RemovedPointType RemovedPoint; 00190 RotateType Rotate; 00191 MoveToLayerType MoveToLayer; 00192 FlagType Flags; 00193 Coord Size; 00194 int Scale; 00195 LayerChangeType LayerChange; 00196 ClearPolyType ClearPoly; 00197 NetlistChangeType NetlistChange; 00198 SetViaLayersChangeType SetViaLayersChange; 00199 long int CopyID; 00200 } 00201 Data; 00202 } UndoListType; 00203 00204 /* --------------------------------------------------------------------------- 00205 * some local variables 00206 */ 00207 static DataType *RemoveList = NULL; 00208 static UndoListType *UndoList = NULL; 00209 static int Serial = 1; 00210 static int SavedSerial; 00211 static size_t UndoN; 00212 static size_t RedoN; 00213 static size_t UndoMax; 00214 static bool Locked = false; 00215 static bool andDraw = true; 00216 /* flag is set; prevents from */ 00217 /* infinite loops */ 00218 00219 /* --------------------------------------------------------------------------- 00220 * some local prototypes 00221 */ 00222 static UndoListType *GetUndoSlot (int, int, int); 00223 static void DrawRecoveredObject (int, void *, void *, void *); 00224 static bool UndoRotate (UndoListType *); 00225 static bool UndoChangeName (UndoListType *); 00226 static bool UndoCopyOrCreate (UndoListType *); 00227 static bool UndoMove (UndoListType *); 00228 static bool UndoRemove (UndoListType *); 00229 static bool UndoRemovePoint (UndoListType *); 00230 static bool UndoInsertPoint (UndoListType *); 00231 static bool UndoRemoveContour (UndoListType *); 00232 static bool UndoInsertContour (UndoListType *); 00233 static bool UndoMoveToLayer (UndoListType *); 00234 static bool UndoFlag (UndoListType *); 00235 static bool UndoMirror (UndoListType *); 00236 static bool UndoChangeSize (UndoListType *); 00237 static bool UndoChange2ndSize (UndoListType *); 00238 static bool UndoChangeAngles (UndoListType *); 00239 static bool UndoChangeClearSize (UndoListType *); 00240 static bool UndoChangeMaskSize (UndoListType *); 00241 static bool UndoClearPoly (UndoListType *); 00242 static bool UndoSetViaLayers (UndoListType *); 00243 static int PerformUndo (UndoListType *); 00244 00248 static UndoListType * 00249 GetUndoSlot (int CommandType, int ID, int Kind) 00250 { 00251 UndoListType *ptr; 00252 void *ptr1, *ptr2, *ptr3; 00253 int type; 00254 static size_t limit = UNDO_WARNING_SIZE; 00255 00256 #ifdef DEBUG_ID 00257 if (SearchObjectByID (PCB->Data, &ptr1, &ptr2, &ptr3, ID, Kind) == NO_TYPE) 00258 Message ("hace: ID (%d) and Type (%x) mismatch in AddObject...\n", ID, 00259 Kind); 00260 #endif 00261 00262 /* allocate memory */ 00263 if (UndoN >= UndoMax) 00264 { 00265 size_t size; 00266 00267 UndoMax += STEP_UNDOLIST; 00268 size = UndoMax * sizeof (UndoListType); 00269 UndoList = (UndoListType *) realloc (UndoList, size); 00270 memset (&UndoList[UndoN], 0, STEP_REMOVELIST * sizeof (UndoListType)); 00271 00272 /* ask user to flush the table because of it's size */ 00273 if (size > limit) 00274 { 00275 limit = (size / UNDO_WARNING_SIZE + 1) * UNDO_WARNING_SIZE; 00276 Message (_("Size of 'undo-list' exceeds %li kb\n"), 00277 (long) (size >> 10)); 00278 } 00279 } 00280 00281 /* free structures from the pruned redo list */ 00282 00283 for (ptr = &UndoList[UndoN]; RedoN; ptr++, RedoN--) 00284 switch (ptr->Type) 00285 { 00286 case UNDO_CHANGENAME: 00287 free (ptr->Data.ChangeName.Name); 00288 break; 00289 case UNDO_REMOVE: 00290 type = 00291 SearchObjectByID (RemoveList, &ptr1, &ptr2, &ptr3, ptr->ID, 00292 ptr->Kind); 00293 if (type != NO_TYPE) 00294 { 00295 DestroyObject (RemoveList, type, ptr1, ptr2, ptr3); 00296 } 00297 break; 00298 default: 00299 break; 00300 } 00301 00302 if (between_increment_and_restore) 00303 added_undo_between_increment_and_restore = true; 00304 00305 /* copy typefield and serial number to the list */ 00306 ptr = &UndoList[UndoN++]; 00307 ptr->Type = CommandType; 00308 ptr->Kind = Kind; 00309 ptr->ID = ID; 00310 ptr->Serial = Serial; 00311 return (ptr); 00312 } 00313 00317 static void 00318 DrawRecoveredObject (int Type, void *Ptr1, void *Ptr2, void *Ptr3) 00319 { 00320 if (Type & (LINE_TYPE | TEXT_TYPE | POLYGON_TYPE | ARC_TYPE)) 00321 { 00322 LayerType *layer; 00323 00324 layer = LAYER_PTR (GetLayerNumber (RemoveList, (LayerType *) Ptr1)); 00325 DrawObject (Type, (void *) layer, Ptr2); 00326 } 00327 else 00328 DrawObject (Type, Ptr1, Ptr2); 00329 } 00330 00336 static bool 00337 UndoRotate (UndoListType *Entry) 00338 { 00339 void *ptr1, *ptr2, *ptr3; 00340 int type; 00341 00342 /* lookup entry by it's ID */ 00343 type = 00344 SearchObjectByID (PCB->Data, &ptr1, &ptr2, &ptr3, Entry->ID, Entry->Kind); 00345 if (type != NO_TYPE) 00346 { 00347 RotateObject (type, ptr1, ptr2, ptr3, 00348 Entry->Data.Rotate.CenterX, Entry->Data.Rotate.CenterY, 00349 (4 - Entry->Data.Rotate.Steps) & 0x03); 00350 Entry->Data.Rotate.Steps = (4 - Entry->Data.Rotate.Steps) & 0x03; 00351 return (true); 00352 } 00353 return (false); 00354 } 00355 00361 static bool 00362 UndoClearPoly (UndoListType *Entry) 00363 { 00364 void *ptr1, *ptr2, *ptr3; 00365 int type; 00366 00367 type = 00368 SearchObjectByID (PCB->Data, &ptr1, &ptr2, &ptr3, Entry->ID, Entry->Kind); 00369 if (type != NO_TYPE) 00370 { 00371 if (Entry->Data.ClearPoly.Clear) 00372 RestoreToPolygon (PCB->Data, type, Entry->Data.ClearPoly.Layer, ptr3); 00373 else 00374 ClearFromPolygon (PCB->Data, type, Entry->Data.ClearPoly.Layer, ptr3); 00375 Entry->Data.ClearPoly.Clear = !Entry->Data.ClearPoly.Clear; 00376 return true; 00377 } 00378 return false; 00379 } 00380 00386 static bool 00387 UndoChangeName (UndoListType *Entry) 00388 { 00389 void *ptr1, *ptr2, *ptr3; 00390 int type; 00391 00392 /* lookup entry by it's ID */ 00393 type = 00394 SearchObjectByID (PCB->Data, &ptr1, &ptr2, &ptr3, Entry->ID, Entry->Kind); 00395 if (type != NO_TYPE) 00396 { 00397 Entry->Data.ChangeName.Name = 00398 (char *)(ChangeObjectName (type, ptr1, ptr2, ptr3, 00399 Entry->Data.ChangeName.Name)); 00400 return (true); 00401 } 00402 return (false); 00403 } 00404 00408 static bool 00409 UndoChange2ndSize (UndoListType *Entry) 00410 { 00411 void *ptr1, *ptr2, *ptr3; 00412 int type; 00413 Coord swap; 00414 00415 /* lookup entry by ID */ 00416 type = 00417 SearchObjectByID (PCB->Data, &ptr1, &ptr2, &ptr3, Entry->ID, Entry->Kind); 00418 if (type != NO_TYPE) 00419 { 00420 swap = ((PinType *) ptr2)->DrillingHole; 00421 if (andDraw) 00422 EraseObject (type, ptr1, ptr2); 00423 ((PinType *) ptr2)->DrillingHole = Entry->Data.Size; 00424 Entry->Data.Size = swap; 00425 DrawObject (type, ptr1, ptr2); 00426 return (true); 00427 } 00428 return (false); 00429 } 00430 00434 static bool 00435 UndoChangeAngles (UndoListType *Entry) 00436 { 00437 void *ptr1, *ptr2, *ptr3; 00438 int type; 00439 long int old_sa, old_da; 00440 00441 /* lookup entry by ID */ 00442 type = 00443 SearchObjectByID (PCB->Data, &ptr1, &ptr2, &ptr3, Entry->ID, Entry->Kind); 00444 if (type == ARC_TYPE) 00445 { 00446 LayerType *Layer = (LayerType *) ptr1; 00447 ArcType *a = (ArcType *) ptr2; 00448 r_delete_entry (Layer->arc_tree, (BoxType *) a); 00449 old_sa = a->StartAngle; 00450 old_da = a->Delta; 00451 if (andDraw) 00452 EraseObject (type, Layer, a); 00453 a->StartAngle = Entry->Data.Move.DX; 00454 a->Delta = Entry->Data.Move.DY; 00455 SetArcBoundingBox (a); 00456 r_insert_entry (Layer->arc_tree, (BoxType *) a, 0); 00457 Entry->Data.Move.DX = old_sa; 00458 Entry->Data.Move.DY = old_da;; 00459 DrawObject (type, ptr1, a); 00460 return (true); 00461 } 00462 return (false); 00463 } 00464 00468 static bool 00469 UndoChangeClearSize (UndoListType *Entry) 00470 { 00471 void *ptr1, *ptr2, *ptr3; 00472 int type; 00473 Coord swap; 00474 00475 /* lookup entry by ID */ 00476 type = 00477 SearchObjectByID (PCB->Data, &ptr1, &ptr2, &ptr3, Entry->ID, Entry->Kind); 00478 if (type != NO_TYPE) 00479 { 00480 swap = ((PinType *) ptr2)->Clearance; 00481 RestoreToPolygon (PCB->Data, type, ptr1, ptr2); 00482 if (andDraw) 00483 EraseObject (type, ptr1, ptr2); 00484 ((PinType *) ptr2)->Clearance = Entry->Data.Size; 00485 ClearFromPolygon (PCB->Data, type, ptr1, ptr2); 00486 Entry->Data.Size = swap; 00487 if (andDraw) 00488 DrawObject (type, ptr1, ptr2); 00489 return (true); 00490 } 00491 return (false); 00492 } 00493 00497 static bool 00498 UndoChangeMaskSize (UndoListType *Entry) 00499 { 00500 void *ptr1, *ptr2, *ptr3; 00501 int type; 00502 Coord swap; 00503 00504 /* lookup entry by ID */ 00505 type = 00506 SearchObjectByID (PCB->Data, &ptr1, &ptr2, &ptr3, Entry->ID, Entry->Kind); 00507 if (type & (VIA_TYPE | PIN_TYPE | PAD_TYPE)) 00508 { 00509 swap = 00510 (type == 00511 PAD_TYPE ? ((PadType *) ptr2)->Mask : ((PinType *) ptr2)->Mask); 00512 if (andDraw) 00513 EraseObject (type, ptr1, ptr2); 00514 if (type == PAD_TYPE) 00515 ((PadType *) ptr2)->Mask = Entry->Data.Size; 00516 else 00517 ((PinType *) ptr2)->Mask = Entry->Data.Size; 00518 Entry->Data.Size = swap; 00519 if (andDraw) 00520 DrawObject (type, ptr1, ptr2); 00521 return (true); 00522 } 00523 return (false); 00524 } 00525 00526 00530 static bool 00531 UndoChangeSize (UndoListType *Entry) 00532 { 00533 void *ptr1, *ptr2, *ptr3; 00534 int type, iswap = 0; 00535 Coord swap = 0; 00536 00537 /* lookup entry by ID */ 00538 type = 00539 SearchObjectByID (PCB->Data, &ptr1, &ptr2, &ptr3, Entry->ID, Entry->Kind); 00540 if (type != NO_TYPE) 00541 { 00542 /* Wow! can any object be treated as a pin type for size change?? */ 00543 /* pins, vias, lines, and arcs can. Text can't but it has it's own mechanism */ 00544 switch (type) 00545 { 00546 case PIN_TYPE: 00547 case VIA_TYPE: 00548 swap = ((PinType *) ptr2)->Thickness; 00549 break; 00550 case LINE_TYPE: 00551 case ELEMENTLINE_TYPE: 00552 swap = ((LineType *) ptr2)->Thickness; 00553 break; 00554 case TEXT_TYPE: 00555 case ELEMENTNAME_TYPE: 00556 iswap = ((TextType *) ptr2)->Scale; 00557 break; 00558 case PAD_TYPE: 00559 swap = ((PadType *) ptr2)->Thickness; 00560 break; 00561 case ARC_TYPE: 00562 case ELEMENTARC_TYPE: 00563 swap = ((ArcType *) ptr2)->Thickness; 00564 break; 00565 } 00566 00567 RestoreToPolygon (PCB->Data, type, ptr1, ptr2); 00568 if (andDraw) 00569 EraseObject (type, ptr1, ptr2); 00570 00571 switch (type) 00572 { 00573 case PIN_TYPE: 00574 case VIA_TYPE: 00575 ((PinType *) ptr2)->Thickness = Entry->Data.Size; 00576 Entry->Data.Size = swap; 00577 break; 00578 case LINE_TYPE: 00579 case ELEMENTLINE_TYPE: 00580 ((LineType *) ptr2)->Thickness = Entry->Data.Size; 00581 Entry->Data.Size = swap; 00582 break; 00583 case TEXT_TYPE: 00584 case ELEMENTNAME_TYPE: 00585 ((TextType *) ptr2)->Scale = Entry->Data.Scale; 00586 Entry->Data.Scale = iswap; 00587 break; 00588 case PAD_TYPE: 00589 ((PadType *) ptr2)->Thickness = Entry->Data.Size; 00590 Entry->Data.Size = swap; 00591 break; 00592 case ARC_TYPE: 00593 case ELEMENTARC_TYPE: 00594 ((ArcType *) ptr2)->Thickness = Entry->Data.Size; 00595 Entry->Data.Size = swap; 00596 break; 00597 } 00598 00599 ClearFromPolygon (PCB->Data, type, ptr1, ptr2); 00600 if (andDraw) 00601 DrawObject (type, ptr1, ptr2); 00602 return (true); 00603 } 00604 return (false); 00605 } 00606 00610 static bool 00611 UndoFlag (UndoListType *Entry) 00612 { 00613 void *ptr1, *ptr2, *ptr3; 00614 int type; 00615 FlagType swap; 00616 int must_redraw; 00617 00618 /* lookup entry by ID */ 00619 type = 00620 SearchObjectByID (PCB->Data, &ptr1, &ptr2, &ptr3, Entry->ID, Entry->Kind); 00621 if (type != NO_TYPE) 00622 { 00623 FlagType f1, f2; 00624 PinType *pin = (PinType *) ptr2; 00625 00626 swap = pin->Flags; 00627 00628 must_redraw = 0; 00629 f1 = MaskFlags (pin->Flags, ~DRAW_FLAGS); 00630 f2 = MaskFlags (Entry->Data.Flags, ~DRAW_FLAGS); 00631 00632 if (!FLAGS_EQUAL (f1, f2)) 00633 must_redraw = 1; 00634 00635 if (andDraw && must_redraw) 00636 EraseObject (type, ptr1, ptr2); 00637 00638 pin->Flags = Entry->Data.Flags; 00639 00640 Entry->Data.Flags = swap; 00641 00642 if (andDraw && must_redraw) 00643 DrawObject (type, ptr1, ptr2); 00644 return (true); 00645 } 00646 Message ("hace Internal error: Can't find ID %d type %08x\n", Entry->ID, 00647 Entry->Kind); 00648 Message ("for UndoFlag Operation. Previous flags: %s\n", 00649 flags_to_string (Entry->Data.Flags, 0)); 00650 return (false); 00651 } 00652 00658 static bool 00659 UndoMirror (UndoListType *Entry) 00660 { 00661 void *ptr1, *ptr2, *ptr3; 00662 int type; 00663 00664 /* lookup entry by ID */ 00665 type = 00666 SearchObjectByID (PCB->Data, &ptr1, &ptr2, &ptr3, Entry->ID, Entry->Kind); 00667 if (type == ELEMENT_TYPE) 00668 { 00669 ElementType *element = (ElementType *) ptr3; 00670 if (andDraw) 00671 EraseElement (element); 00672 MirrorElementCoordinates (PCB->Data, element, Entry->Data.Move.DY); 00673 if (andDraw) 00674 DrawElement (element); 00675 return (true); 00676 } 00677 Message ("hace Internal error: UndoMirror on object type %d\n", type); 00678 return (false); 00679 } 00680 00686 static bool 00687 UndoCopyOrCreate (UndoListType *Entry) 00688 { 00689 void *ptr1, *ptr2, *ptr3; 00690 int type; 00691 00692 /* lookup entry by it's ID */ 00693 type = 00694 SearchObjectByID (PCB->Data, &ptr1, &ptr2, &ptr3, Entry->ID, Entry->Kind); 00695 if (type != NO_TYPE) 00696 { 00697 if (!RemoveList) 00698 RemoveList = CreateNewBuffer (); 00699 if (andDraw) 00700 EraseObject (type, ptr1, ptr2); 00701 /* in order to make this re-doable we move it to the RemoveList */ 00702 MoveObjectToBuffer (RemoveList, PCB->Data, type, ptr1, ptr2, ptr3); 00703 Entry->Type = UNDO_REMOVE; 00704 return (true); 00705 } 00706 return (false); 00707 } 00708 00714 static bool 00715 UndoMove (UndoListType *Entry) 00716 { 00717 void *ptr1, *ptr2, *ptr3; 00718 int type; 00719 00720 /* lookup entry by it's ID */ 00721 type = 00722 SearchObjectByID (PCB->Data, &ptr1, &ptr2, &ptr3, Entry->ID, Entry->Kind); 00723 if (type != NO_TYPE) 00724 { 00725 MoveObject (type, ptr1, ptr2, ptr3, 00726 -Entry->Data.Move.DX, -Entry->Data.Move.DY); 00727 Entry->Data.Move.DX *= -1; 00728 Entry->Data.Move.DY *= -1; 00729 return (true); 00730 } 00731 return (false); 00732 } 00733 00739 static bool 00740 UndoRemove (UndoListType *Entry) 00741 { 00742 void *ptr1, *ptr2, *ptr3; 00743 int type; 00744 00745 /* lookup entry by it's ID */ 00746 type = 00747 SearchObjectByID (RemoveList, &ptr1, &ptr2, &ptr3, Entry->ID, 00748 Entry->Kind); 00749 if (type != NO_TYPE) 00750 { 00751 if (andDraw) 00752 DrawRecoveredObject (type, ptr1, ptr2, ptr3); 00753 MoveObjectToBuffer (PCB->Data, RemoveList, type, ptr1, ptr2, ptr3); 00754 Entry->Type = UNDO_CREATE; 00755 return (true); 00756 } 00757 return (false); 00758 } 00759 00765 static bool 00766 UndoMoveToLayer (UndoListType *Entry) 00767 { 00768 void *ptr1, *ptr2, *ptr3; 00769 int type, swap; 00770 00771 /* lookup entry by it's ID */ 00772 type = 00773 SearchObjectByID (PCB->Data, &ptr1, &ptr2, &ptr3, Entry->ID, Entry->Kind); 00774 if (type != NO_TYPE) 00775 { 00776 swap = GetLayerNumber (PCB->Data, (LayerType *) ptr1); 00777 MoveObjectToLayer (type, ptr1, ptr2, ptr3, 00778 LAYER_PTR (Entry->Data. 00779 MoveToLayer.OriginalLayer), true); 00780 Entry->Data.MoveToLayer.OriginalLayer = swap; 00781 return (true); 00782 } 00783 return (false); 00784 } 00785 00791 static bool 00792 UndoRemovePoint (UndoListType *Entry) 00793 { 00794 LayerType *layer; 00795 PolygonType *polygon; 00796 void *ptr3; 00797 int type; 00798 00799 /* lookup entry (polygon not point was saved) by it's ID */ 00800 assert (Entry->Kind == POLYGON_TYPE); 00801 type = 00802 SearchObjectByID (PCB->Data, (void **) &layer, (void **) &polygon, &ptr3, 00803 Entry->ID, Entry->Kind); 00804 switch (type) 00805 { 00806 case POLYGON_TYPE: /* restore the removed point */ 00807 { 00808 /* recover the point */ 00809 if (andDraw && layer->On) 00810 ErasePolygon (polygon); 00811 InsertPointIntoObject (POLYGON_TYPE, layer, polygon, 00812 &Entry->Data.RemovedPoint.Index, 00813 Entry->Data.RemovedPoint.X, 00814 Entry->Data.RemovedPoint.Y, true, 00815 Entry->Data.RemovedPoint.last_in_contour); 00816 00817 polygon->Points[Entry->Data.RemovedPoint.Index].ID = 00818 Entry->Data.RemovedPoint.ID; 00819 if (andDraw && layer->On) 00820 DrawPolygon (layer, polygon); 00821 Entry->Type = UNDO_INSERT_POINT; 00822 Entry->ID = Entry->Data.RemovedPoint.ID; 00823 Entry->Kind = POLYGONPOINT_TYPE; 00824 return (true); 00825 } 00826 00827 default: 00828 return (false); 00829 } 00830 } 00831 00837 static bool 00838 UndoInsertPoint (UndoListType *Entry) 00839 { 00840 LayerType *layer; 00841 PolygonType *polygon; 00842 PointType *pnt; 00843 int type; 00844 Cardinal point_idx; 00845 Cardinal hole; 00846 bool last_in_contour = false; 00847 00848 assert (Entry->Kind == POLYGONPOINT_TYPE); 00849 /* lookup entry by it's ID */ 00850 type = 00851 SearchObjectByID (PCB->Data, (void **) &layer, (void **) &polygon, 00852 (void **) &pnt, Entry->ID, Entry->Kind); 00853 switch (type) 00854 { 00855 case POLYGONPOINT_TYPE: /* removes an inserted polygon point */ 00856 { 00857 if (andDraw && layer->On) 00858 ErasePolygon (polygon); 00859 00860 /* Check whether this point was at the end of its contour. 00861 * If so, we need to flag as such when re-adding the point 00862 * so it goes back in the correct place 00863 */ 00864 point_idx = polygon_point_idx (polygon, pnt); 00865 for (hole = 0; hole < polygon->HoleIndexN; hole++) 00866 if (point_idx == polygon->HoleIndex[hole] - 1) 00867 last_in_contour = true; 00868 if (point_idx == polygon->PointN - 1) 00869 last_in_contour = true; 00870 Entry->Data.RemovedPoint.last_in_contour = last_in_contour; 00871 00872 Entry->Data.RemovedPoint.X = pnt->X; 00873 Entry->Data.RemovedPoint.Y = pnt->Y; 00874 Entry->Data.RemovedPoint.ID = pnt->ID; 00875 Entry->ID = polygon->ID; 00876 Entry->Kind = POLYGON_TYPE; 00877 Entry->Type = UNDO_REMOVE_POINT; 00878 Entry->Data.RemovedPoint.Index = point_idx; 00879 DestroyObject (PCB->Data, POLYGONPOINT_TYPE, layer, polygon, pnt); 00880 if (andDraw && layer->On) 00881 DrawPolygon (layer, polygon); 00882 return (true); 00883 } 00884 00885 default: 00886 return (false); 00887 } 00888 } 00889 00890 static bool 00891 UndoSwapCopiedObject (UndoListType *Entry) 00892 { 00893 void *ptr1, *ptr2, *ptr3; 00894 void *ptr1b, *ptr2b, *ptr3b; 00895 AnyObjectType *obj, *obj2; 00896 int type; 00897 long int swap_id; 00898 00899 /* lookup entry by it's ID */ 00900 type = 00901 SearchObjectByID (RemoveList, &ptr1, &ptr2, &ptr3, Entry->Data.CopyID, 00902 Entry->Kind); 00903 if (type == NO_TYPE) 00904 return false; 00905 00906 type = 00907 SearchObjectByID (PCB->Data, &ptr1b, &ptr2b, &ptr3b, Entry->ID, 00908 Entry->Kind); 00909 if (type == NO_TYPE) 00910 return FALSE; 00911 00912 obj = (AnyObjectType *)ptr2; 00913 obj2 = (AnyObjectType *)ptr2b; 00914 00915 swap_id = obj->ID; 00916 obj->ID = obj2->ID; 00917 obj2->ID = swap_id; 00918 00919 MoveObjectToBuffer (RemoveList, PCB->Data, type, ptr1b, ptr2b, ptr3b); 00920 00921 if (andDraw) 00922 DrawRecoveredObject (Entry->Kind, ptr1, ptr2, ptr3); 00923 00924 obj = (AnyObjectType *)MoveObjectToBuffer (PCB->Data, RemoveList, type, ptr1, ptr2, ptr3); 00925 if (Entry->Kind == POLYGON_TYPE) 00926 InitClip (PCB->Data, (LayerType *)ptr1b, (PolygonType *)obj); 00927 return (true); 00928 } 00929 00935 static bool 00936 UndoRemoveContour (UndoListType *Entry) 00937 { 00938 assert (Entry->Kind == POLYGON_TYPE); 00939 return UndoSwapCopiedObject (Entry); 00940 } 00941 00947 static bool 00948 UndoInsertContour (UndoListType *Entry) 00949 { 00950 assert (Entry->Kind == POLYGON_TYPE); 00951 return UndoSwapCopiedObject (Entry); 00952 } 00953 00959 static bool 00960 UndoLayerChange (UndoListType *Entry) 00961 { 00962 LayerChangeType *l = &Entry->Data.LayerChange; 00963 int tmp; 00964 00965 tmp = l->new_index; 00966 l->new_index = l->old_index; 00967 l->old_index = tmp; 00968 00969 if (MoveLayer (l->old_index, l->new_index)) 00970 return false; 00971 else 00972 return true; 00973 } 00974 00980 static bool 00981 UndoNetlistChange (UndoListType *Entry) 00982 { 00983 NetlistChangeType *l = & Entry->Data.NetlistChange; 00984 unsigned int i, j; 00985 LibraryType *lib, *saved; 00986 00987 lib = l->lib; 00988 saved = l->old; 00989 00990 /* iterate over each net */ 00991 for (i = 0 ; i < lib->MenuN; i++) 00992 { 00993 if (lib->Menu[i].Name) 00994 free (lib->Menu[i].Name); 00995 00996 if (lib->Menu[i].directory) 00997 free (lib->Menu[i].directory); 00998 00999 if (lib->Menu[i].Style) 01000 free (lib->Menu[i].Style); 01001 01002 /* iterate over each pin on the net */ 01003 for (j = 0; j < lib->Menu[i].EntryN; j++) { 01004 01005 if (lib->Menu[i].Entry[j].ListEntry) 01006 free (lib->Menu[i].Entry[j].ListEntry); 01007 01008 if (lib->Menu[i].Entry[j].AllocatedMemory) 01009 free (lib->Menu[i].Entry[j].AllocatedMemory); 01010 01011 if (lib->Menu[i].Entry[j].Template) 01012 free (lib->Menu[i].Entry[j].Template); 01013 01014 if (lib->Menu[i].Entry[j].Package) 01015 free (lib->Menu[i].Entry[j].Package); 01016 01017 if (lib->Menu[i].Entry[j].Value) 01018 free (lib->Menu[i].Entry[j].Value); 01019 01020 if (lib->Menu[i].Entry[j].Description) 01021 free (lib->Menu[i].Entry[j].Description); 01022 01023 } 01024 } 01025 01026 if (lib->Menu) 01027 free (lib->Menu); 01028 01029 *lib = *saved; 01030 01031 NetlistChanged (0); 01032 return true; 01033 } 01034 01035 /* --------------------------------------------------------------------------- 01036 * recovers an object from a Size change operation 01037 */ 01038 static bool 01039 UndoSetViaLayers (UndoListType *Entry) 01040 { 01041 void *ptr1, *ptr2, *ptr3; 01042 int type; 01043 int from, to; 01044 01045 /* lookup entry by ID */ 01046 type = 01047 SearchObjectByID (PCB->Data, &ptr1, &ptr2, &ptr3, Entry->ID, Entry->Kind); 01048 if (type == VIA_TYPE) 01049 { 01050 from = ((PinType *) ptr2)->BuriedFrom; 01051 to = ((PinType *) ptr2)->BuriedTo; 01052 RestoreToPolygon (PCB->Data, type, ptr1, ptr2); 01053 if (andDraw) 01054 EraseObject (type, ptr1, ptr2); 01055 ((PinType *) ptr2)->BuriedFrom = Entry->Data.SetViaLayersChange.from; 01056 ((PinType *) ptr2)->BuriedTo = Entry->Data.SetViaLayersChange.to; 01057 Entry->Data.SetViaLayersChange.from = from; 01058 Entry->Data.SetViaLayersChange.to = to; 01059 ClearFromPolygon (PCB->Data, type, ptr1, ptr2); 01060 if (andDraw) 01061 DrawObject (type, ptr1, ptr2); 01062 return (true); 01063 } 01064 return (false); 01065 } 01066 01067 /* --------------------------------------------------------------------------- 01068 * \brief Undo of any 'hard to recover' operation 01069 * 01070 * \return The bitfield for the types of operations that were undone. 01071 */ 01072 int 01073 Undo (bool draw) 01074 { 01075 UndoListType *ptr; 01076 int Types = 0; 01077 int unique; 01078 bool error_undoing = false; 01079 01080 unique = TEST_FLAG (UNIQUENAMEFLAG, PCB); 01081 CLEAR_FLAG (UNIQUENAMEFLAG, PCB); 01082 01083 andDraw = draw; 01084 01085 if (Serial == 0) 01086 { 01087 Message (_("ERROR: Attempt to Undo() with Serial == 0\n" 01088 " Please save your work and report this bug.\n")); 01089 return 0; 01090 } 01091 01092 if (UndoN == 0) 01093 { 01094 Message (_("Nothing to undo - buffer is empty\n")); 01095 return 0; 01096 } 01097 01098 Serial --; 01099 01100 ptr = &UndoList[UndoN - 1]; 01101 01102 if (ptr->Serial > Serial) 01103 { 01104 Message (_("ERROR: Bad undo serial number %d in undo stack - expecting %d or lower\n" 01105 " Please save your work and report this bug.\n"), 01106 ptr->Serial, Serial); 01107 01108 /* It is likely that the serial number got corrupted through some bad 01109 * use of the SaveUndoSerialNumber() / RestoreUndoSerialNumber() APIs. 01110 * 01111 * Reset the serial number to be consistent with that of the last 01112 * operation on the undo stack in the hope that this might clear 01113 * the problem and allow the user to hit Undo again. 01114 */ 01115 Serial = ptr->Serial + 1; 01116 return 0; 01117 } 01118 01119 LockUndo (); /* lock undo module to prevent from loops */ 01120 01121 /* Loop over all entries with the correct serial number */ 01122 for (; UndoN && ptr->Serial == Serial; ptr--, UndoN--, RedoN++) 01123 { 01124 int undid = PerformUndo (ptr); 01125 if (undid == 0) 01126 error_undoing = true; 01127 Types |= undid; 01128 } 01129 01130 UnlockUndo (); 01131 01132 if (error_undoing) 01133 Message (_("ERROR: Failed to undo some operations\n")); 01134 01135 if (Types && andDraw) 01136 Draw (); 01137 01138 /* restore the unique flag setting */ 01139 if (unique) 01140 SET_FLAG (UNIQUENAMEFLAG, PCB); 01141 01142 return Types; 01143 } 01144 01145 static int 01146 PerformUndo (UndoListType *ptr) 01147 { 01148 switch (ptr->Type) 01149 { 01150 case UNDO_CHANGENAME: 01151 if (UndoChangeName (ptr)) 01152 return (UNDO_CHANGENAME); 01153 break; 01154 01155 case UNDO_CREATE: 01156 if (UndoCopyOrCreate (ptr)) 01157 return (UNDO_CREATE); 01158 break; 01159 01160 case UNDO_MOVE: 01161 if (UndoMove (ptr)) 01162 return (UNDO_MOVE); 01163 break; 01164 01165 case UNDO_REMOVE: 01166 if (UndoRemove (ptr)) 01167 return (UNDO_REMOVE); 01168 break; 01169 01170 case UNDO_REMOVE_POINT: 01171 if (UndoRemovePoint (ptr)) 01172 return (UNDO_REMOVE_POINT); 01173 break; 01174 01175 case UNDO_INSERT_POINT: 01176 if (UndoInsertPoint (ptr)) 01177 return (UNDO_INSERT_POINT); 01178 break; 01179 01180 case UNDO_REMOVE_CONTOUR: 01181 if (UndoRemoveContour (ptr)) 01182 return (UNDO_REMOVE_CONTOUR); 01183 break; 01184 01185 case UNDO_INSERT_CONTOUR: 01186 if (UndoInsertContour (ptr)) 01187 return (UNDO_INSERT_CONTOUR); 01188 break; 01189 01190 case UNDO_ROTATE: 01191 if (UndoRotate (ptr)) 01192 return (UNDO_ROTATE); 01193 break; 01194 01195 case UNDO_CLEAR: 01196 if (UndoClearPoly (ptr)) 01197 return (UNDO_CLEAR); 01198 break; 01199 01200 case UNDO_MOVETOLAYER: 01201 if (UndoMoveToLayer (ptr)) 01202 return (UNDO_MOVETOLAYER); 01203 break; 01204 01205 case UNDO_FLAG: 01206 if (UndoFlag (ptr)) 01207 return (UNDO_FLAG); 01208 break; 01209 01210 case UNDO_CHANGESIZE: 01211 if (UndoChangeSize (ptr)) 01212 return (UNDO_CHANGESIZE); 01213 break; 01214 01215 case UNDO_CHANGECLEARSIZE: 01216 if (UndoChangeClearSize (ptr)) 01217 return (UNDO_CHANGECLEARSIZE); 01218 break; 01219 01220 case UNDO_CHANGEMASKSIZE: 01221 if (UndoChangeMaskSize (ptr)) 01222 return (UNDO_CHANGEMASKSIZE); 01223 break; 01224 01225 case UNDO_CHANGE2NDSIZE: 01226 if (UndoChange2ndSize (ptr)) 01227 return (UNDO_CHANGE2NDSIZE); 01228 break; 01229 01230 case UNDO_CHANGEANGLES: 01231 if (UndoChangeAngles (ptr)) 01232 return (UNDO_CHANGEANGLES); 01233 break; 01234 01235 case UNDO_LAYERCHANGE: 01236 if (UndoLayerChange (ptr)) 01237 return (UNDO_LAYERCHANGE); 01238 break; 01239 01240 case UNDO_NETLISTCHANGE: 01241 if (UndoNetlistChange (ptr)) 01242 return (UNDO_NETLISTCHANGE); 01243 break; 01244 01245 case UNDO_MIRROR: 01246 if (UndoMirror (ptr)) 01247 return (UNDO_MIRROR); 01248 break; 01249 01250 case UNDO_CHANGESETVIALAYERS: 01251 if (UndoSetViaLayers (ptr)) 01252 return (UNDO_CHANGESETVIALAYERS); 01253 break; 01254 } 01255 return 0; 01256 } 01257 01263 int 01264 Redo (bool draw) 01265 { 01266 UndoListType *ptr; 01267 int Types = 0; 01268 bool error_undoing = false; 01269 01270 andDraw = draw; 01271 01272 if (RedoN == 0) 01273 { 01274 Message (_("Nothing to redo. Perhaps changes have been made since last undo\n")); 01275 return 0; 01276 } 01277 01278 ptr = &UndoList[UndoN]; 01279 01280 if (ptr->Serial < Serial) 01281 { 01282 Message (_("ERROR: Bad undo serial number %d in redo stack - expecting %d or higher\n" 01283 " Please save your work and report this bug.\n"), 01284 ptr->Serial, Serial); 01285 01286 /* It is likely that the serial number got corrupted through some bad 01287 * use of the SaveUndoSerialNumber() / RestoreUndoSerialNumber() APIs. 01288 * 01289 * Reset the serial number to be consistent with that of the first 01290 * operation on the redo stack in the hope that this might clear 01291 * the problem and allow the user to hit Redo again. 01292 */ 01293 Serial = ptr->Serial; 01294 return 0; 01295 } 01296 01297 LockUndo (); /* lock undo module to prevent from loops */ 01298 01299 /* and loop over all entries with the correct serial number */ 01300 for (; RedoN && ptr->Serial == Serial; ptr++, UndoN++, RedoN--) 01301 { 01302 int undid = PerformUndo (ptr); 01303 if (undid == 0) 01304 error_undoing = true; 01305 Types |= undid; 01306 } 01307 01308 /* Make next serial number current */ 01309 Serial++; 01310 01311 UnlockUndo (); 01312 01313 if (error_undoing) 01314 Message (_("ERROR: Failed to redo some operations\n")); 01315 01316 if (Types && andDraw) 01317 Draw (); 01318 01319 return Types; 01320 } 01321 01325 void 01326 RestoreUndoSerialNumber (void) 01327 { 01328 if (added_undo_between_increment_and_restore) 01329 Message (_("ERROR: Operations were added to the Undo stack with an incorrect serial number\n")); 01330 between_increment_and_restore = false; 01331 added_undo_between_increment_and_restore = false; 01332 Serial = SavedSerial; 01333 } 01334 01338 void 01339 SaveUndoSerialNumber (void) 01340 { 01341 Bumped = false; 01342 between_increment_and_restore = false; 01343 added_undo_between_increment_and_restore = false; 01344 SavedSerial = Serial; 01345 } 01346 01353 void 01354 IncrementUndoSerialNumber (void) 01355 { 01356 if (!Locked) 01357 { 01358 /* Set the changed flag if anything was added prior to this bump */ 01359 if (UndoN > 0 && UndoList[UndoN - 1].Serial == Serial) 01360 SetChangedFlag (true); 01361 Serial++; 01362 Bumped = true; 01363 between_increment_and_restore = true; 01364 } 01365 } 01366 01370 void 01371 ClearUndoList (bool Force) 01372 { 01373 UndoListType *undo; 01374 01375 if (UndoN 01376 && (Force || gui->confirm_dialog ("OK to clear 'undo' buffer?", 0))) 01377 { 01378 /* release memory allocated by objects in undo list */ 01379 for (undo = UndoList; UndoN; undo++, UndoN--) 01380 { 01381 if (undo->Type == UNDO_CHANGENAME) 01382 free (undo->Data.ChangeName.Name); 01383 } 01384 free (UndoList); 01385 UndoList = NULL; 01386 if (RemoveList) 01387 { 01388 FreeDataMemory (RemoveList); 01389 free (RemoveList); 01390 RemoveList = NULL; 01391 } 01392 01393 /* reset some counters */ 01394 UndoN = UndoMax = RedoN = 0; 01395 } 01396 01397 /* reset counter in any case */ 01398 Serial = 1; 01399 } 01400 01404 void 01405 AddObjectToClearPolyUndoList (int Type, void *Ptr1, void *Ptr2, void *Ptr3, 01406 bool clear) 01407 { 01408 UndoListType *undo; 01409 01410 if (!Locked) 01411 { 01412 undo = GetUndoSlot (UNDO_CLEAR, OBJECT_ID (Ptr3), Type); 01413 undo->Data.ClearPoly.Clear = clear; 01414 undo->Data.ClearPoly.Layer = (LayerType *) Ptr1; 01415 } 01416 } 01417 01421 void 01422 AddObjectToMirrorUndoList (int Type, void *Ptr1, void *Ptr2, void *Ptr3, 01423 Coord yoff) 01424 { 01425 UndoListType *undo; 01426 01427 if (!Locked) 01428 { 01429 undo = GetUndoSlot (UNDO_MIRROR, OBJECT_ID (Ptr3), Type); 01430 undo->Data.Move.DY = yoff; 01431 } 01432 } 01433 01437 void 01438 AddObjectToRotateUndoList (int Type, void *Ptr1, void *Ptr2, void *Ptr3, 01439 Coord CenterX, Coord CenterY, 01440 BYTE Steps) 01441 { 01442 UndoListType *undo; 01443 01444 if (!Locked) 01445 { 01446 undo = GetUndoSlot (UNDO_ROTATE, OBJECT_ID (Ptr3), Type); 01447 undo->Data.Rotate.CenterX = CenterX; 01448 undo->Data.Rotate.CenterY = CenterY; 01449 undo->Data.Rotate.Steps = Steps; 01450 } 01451 } 01452 01457 void 01458 MoveObjectToRemoveUndoList (int Type, void *Ptr1, void *Ptr2, void *Ptr3) 01459 { 01460 if (Locked) 01461 return; 01462 01463 if (!RemoveList) 01464 RemoveList = CreateNewBuffer (); 01465 01466 GetUndoSlot (UNDO_REMOVE, OBJECT_ID (Ptr3), Type); 01467 MoveObjectToBuffer (RemoveList, PCB->Data, Type, Ptr1, Ptr2, Ptr3); 01468 } 01469 01473 void 01474 AddObjectToRemovePointUndoList (int Type, 01475 void *Ptr1, void *Ptr2, Cardinal index) 01476 { 01477 UndoListType *undo; 01478 PolygonType *polygon = (PolygonType *) Ptr2; 01479 Cardinal hole; 01480 bool last_in_contour = false; 01481 01482 if (!Locked) 01483 { 01484 switch (Type) 01485 { 01486 case POLYGONPOINT_TYPE: 01487 { 01488 /* save the ID of the parent object; else it will be 01489 * impossible to recover the point 01490 */ 01491 undo = 01492 GetUndoSlot (UNDO_REMOVE_POINT, OBJECT_ID (polygon), 01493 POLYGON_TYPE); 01494 undo->Data.RemovedPoint.X = polygon->Points[index].X; 01495 undo->Data.RemovedPoint.Y = polygon->Points[index].Y; 01496 undo->Data.RemovedPoint.ID = polygon->Points[index].ID; 01497 undo->Data.RemovedPoint.Index = index; 01498 01499 /* Check whether this point was at the end of its contour. 01500 * If so, we need to flag as such when re-adding the point 01501 * so it goes back in the correct place 01502 */ 01503 for (hole = 0; hole < polygon->HoleIndexN; hole++) 01504 if (index == polygon->HoleIndex[hole] - 1) 01505 last_in_contour = true; 01506 if (index == polygon->PointN - 1) 01507 last_in_contour = true; 01508 undo->Data.RemovedPoint.last_in_contour = last_in_contour; 01509 } 01510 break; 01511 } 01512 } 01513 } 01514 01518 void 01519 AddObjectToInsertPointUndoList (int Type, void *Ptr1, void *Ptr2, void *Ptr3) 01520 { 01521 if (!Locked) 01522 GetUndoSlot (UNDO_INSERT_POINT, OBJECT_ID (Ptr3), Type); 01523 } 01524 01525 static void 01526 CopyObjectToUndoList (int undo_type, int Type, void *Ptr1, void *Ptr2, void *Ptr3) 01527 { 01528 UndoListType *undo; 01529 AnyObjectType *copy; 01530 01531 if (Locked) 01532 return; 01533 01534 if (!RemoveList) 01535 RemoveList = CreateNewBuffer (); 01536 01537 undo = GetUndoSlot (undo_type, OBJECT_ID (Ptr2), Type); 01538 copy = (AnyObjectType *)CopyObjectToBuffer (RemoveList, PCB->Data, Type, Ptr1, Ptr2, Ptr3); 01539 undo->Data.CopyID = copy->ID; 01540 } 01541 01547 void 01548 AddObjectToRemoveContourUndoList (int Type, 01549 LayerType *Layer, PolygonType *Polygon) 01550 { 01551 CopyObjectToUndoList (UNDO_REMOVE_CONTOUR, Type, Layer, Polygon, NULL); 01552 } 01553 01559 void 01560 AddObjectToInsertContourUndoList (int Type, 01561 LayerType *Layer, PolygonType *Polygon) 01562 { 01563 CopyObjectToUndoList (UNDO_INSERT_CONTOUR, Type, Layer, Polygon, NULL); 01564 } 01565 01569 void 01570 AddObjectToMoveUndoList (int Type, void *Ptr1, void *Ptr2, void *Ptr3, 01571 Coord DX, Coord DY) 01572 { 01573 UndoListType *undo; 01574 01575 if (!Locked) 01576 { 01577 undo = GetUndoSlot (UNDO_MOVE, OBJECT_ID (Ptr3), Type); 01578 undo->Data.Move.DX = DX; 01579 undo->Data.Move.DY = DY; 01580 } 01581 } 01582 01586 void 01587 AddObjectToChangeNameUndoList (int Type, void *Ptr1, void *Ptr2, void *Ptr3, 01588 char *OldName) 01589 { 01590 UndoListType *undo; 01591 01592 if (!Locked) 01593 { 01594 undo = GetUndoSlot (UNDO_CHANGENAME, OBJECT_ID (Ptr3), Type); 01595 undo->Data.ChangeName.Name = OldName; 01596 } 01597 } 01598 01602 void 01603 AddObjectToMoveToLayerUndoList (int Type, void *Ptr1, void *Ptr2, void *Ptr3) 01604 { 01605 UndoListType *undo; 01606 01607 if (!Locked) 01608 { 01609 undo = GetUndoSlot (UNDO_MOVETOLAYER, OBJECT_ID (Ptr3), Type); 01610 undo->Data.MoveToLayer.OriginalLayer = 01611 GetLayerNumber (PCB->Data, (LayerType *) Ptr1); 01612 } 01613 } 01614 01618 void 01619 AddObjectToCreateUndoList (int Type, void *Ptr1, void *Ptr2, void *Ptr3) 01620 { 01621 if (!Locked) 01622 GetUndoSlot (UNDO_CREATE, OBJECT_ID (Ptr3), Type); 01623 ClearFromPolygon (PCB->Data, Type, Ptr1, Ptr2); 01624 } 01625 01629 void 01630 AddObjectToFlagUndoList (int Type, void *Ptr1, void *Ptr2, void *Ptr3) 01631 { 01632 UndoListType *undo; 01633 01634 if (!Locked) 01635 { 01636 undo = GetUndoSlot (UNDO_FLAG, OBJECT_ID (Ptr2), Type); 01637 undo->Data.Flags = ((PinType *) Ptr2)->Flags; 01638 } 01639 } 01640 01644 void 01645 AddObjectToSizeUndoList (int Type, void *ptr1, void *ptr2, void *ptr3) 01646 { 01647 UndoListType *undo; 01648 01649 if (!Locked) 01650 { 01651 undo = GetUndoSlot (UNDO_CHANGESIZE, OBJECT_ID (ptr2), Type); 01652 switch (Type) 01653 { 01654 case PIN_TYPE: 01655 case VIA_TYPE: 01656 undo->Data.Size = ((PinType *) ptr2)->Thickness; 01657 break; 01658 case LINE_TYPE: 01659 case ELEMENTLINE_TYPE: 01660 undo->Data.Size = ((LineType *) ptr2)->Thickness; 01661 break; 01662 case TEXT_TYPE: 01663 case ELEMENTNAME_TYPE: 01664 undo->Data.Scale = ((TextType *) ptr2)->Scale; 01665 break; 01666 case PAD_TYPE: 01667 undo->Data.Size = ((PadType *) ptr2)->Thickness; 01668 break; 01669 case ARC_TYPE: 01670 case ELEMENTARC_TYPE: 01671 undo->Data.Size = ((ArcType *) ptr2)->Thickness; 01672 break; 01673 } 01674 } 01675 } 01676 01680 void 01681 AddObjectToClearSizeUndoList (int Type, void *ptr1, void *ptr2, void *ptr3) 01682 { 01683 UndoListType *undo; 01684 01685 if (!Locked) 01686 { 01687 undo = GetUndoSlot (UNDO_CHANGECLEARSIZE, OBJECT_ID (ptr2), Type); 01688 switch (Type) 01689 { 01690 case PIN_TYPE: 01691 case VIA_TYPE: 01692 undo->Data.Size = ((PinType *) ptr2)->Clearance; 01693 break; 01694 case LINE_TYPE: 01695 undo->Data.Size = ((LineType *) ptr2)->Clearance; 01696 break; 01697 case PAD_TYPE: 01698 undo->Data.Size = ((PadType *) ptr2)->Clearance; 01699 break; 01700 case ARC_TYPE: 01701 undo->Data.Size = ((ArcType *) ptr2)->Clearance; 01702 break; 01703 } 01704 } 01705 } 01706 01710 void 01711 AddObjectToMaskSizeUndoList (int Type, void *ptr1, void *ptr2, void *ptr3) 01712 { 01713 UndoListType *undo; 01714 01715 if (!Locked) 01716 { 01717 undo = GetUndoSlot (UNDO_CHANGEMASKSIZE, OBJECT_ID (ptr2), Type); 01718 switch (Type) 01719 { 01720 case PIN_TYPE: 01721 case VIA_TYPE: 01722 undo->Data.Size = ((PinType *) ptr2)->Mask; 01723 break; 01724 case PAD_TYPE: 01725 undo->Data.Size = ((PadType *) ptr2)->Mask; 01726 break; 01727 } 01728 } 01729 } 01730 01734 void 01735 AddObjectTo2ndSizeUndoList (int Type, void *ptr1, void *ptr2, void *ptr3) 01736 { 01737 UndoListType *undo; 01738 01739 if (!Locked) 01740 { 01741 undo = GetUndoSlot (UNDO_CHANGE2NDSIZE, OBJECT_ID (ptr2), Type); 01742 if (Type == PIN_TYPE || Type == VIA_TYPE) 01743 undo->Data.Size = ((PinType *) ptr2)->DrillingHole; 01744 } 01745 } 01746 01753 void 01754 AddObjectToChangeAnglesUndoList (int Type, void *Ptr1, void *Ptr2, void *Ptr3) 01755 { 01756 UndoListType *undo; 01757 ArcType *a = (ArcType *) Ptr3; 01758 01759 if (!Locked) 01760 { 01761 undo = GetUndoSlot (UNDO_CHANGEANGLES, OBJECT_ID (Ptr3), Type); 01762 undo->Data.Move.DX = a->StartAngle; 01763 undo->Data.Move.DY = a->Delta; 01764 } 01765 } 01766 01770 void 01771 AddLayerChangeToUndoList (int old_index, int new_index) 01772 { 01773 UndoListType *undo; 01774 01775 if (!Locked) 01776 { 01777 undo = GetUndoSlot (UNDO_LAYERCHANGE, 0, 0); 01778 undo->Data.LayerChange.old_index = old_index; 01779 undo->Data.LayerChange.new_index = new_index; 01780 } 01781 } 01782 01786 void 01787 AddNetlistLibToUndoList (LibraryType *lib) 01788 { 01789 UndoListType *undo; 01790 unsigned int i, j; 01791 LibraryType *old; 01792 01793 if (!Locked) 01794 { 01795 undo = GetUndoSlot (UNDO_NETLISTCHANGE, 0, 0); 01796 /* keep track of where the data needs to go */ 01797 undo->Data.NetlistChange.lib = lib; 01798 01799 /* and what the old data is that we'll need to restore */ 01800 undo->Data.NetlistChange.old = (LibraryType *)malloc (sizeof (LibraryType)); 01801 old = undo->Data.NetlistChange.old; 01802 old->MenuN = lib->MenuN; 01803 old->MenuMax = lib->MenuMax; 01804 old->Menu = (LibraryMenuType *)malloc (old->MenuMax * sizeof (LibraryMenuType)); 01805 if (old->Menu == NULL) 01806 { 01807 fprintf (stderr, "malloc() failed in %s\n", __FUNCTION__); 01808 exit (1); 01809 } 01810 01811 /* iterate over each net */ 01812 for (i = 0 ; i < lib->MenuN; i++) 01813 { 01814 old->Menu[i].EntryN = lib->Menu[i].EntryN; 01815 old->Menu[i].EntryMax = lib->Menu[i].EntryMax; 01816 01817 old->Menu[i].Name = 01818 lib->Menu[i].Name ? strdup (lib->Menu[i].Name) : NULL; 01819 01820 old->Menu[i].directory = 01821 lib->Menu[i].directory ? strdup (lib->Menu[i].directory) : NULL; 01822 01823 old->Menu[i].Style = 01824 lib->Menu[i].Style ? strdup (lib->Menu[i].Style) : NULL; 01825 01826 01827 old->Menu[i].Entry = 01828 (LibraryEntryType *)malloc (old->Menu[i].EntryMax * sizeof (LibraryEntryType)); 01829 if (old->Menu[i].Entry == NULL) 01830 { 01831 fprintf (stderr, "malloc() failed in %s\n", __FUNCTION__); 01832 exit (1); 01833 } 01834 01835 /* iterate over each pin on the net */ 01836 for (j = 0; j < lib->Menu[i].EntryN; j++) { 01837 01838 old->Menu[i].Entry[j].ListEntry = 01839 lib->Menu[i].Entry[j].ListEntry ? 01840 strdup (lib->Menu[i].Entry[j].ListEntry) : 01841 NULL; 01842 01843 old->Menu[i].Entry[j].AllocatedMemory = 01844 lib->Menu[i].Entry[j].AllocatedMemory ? 01845 strdup (lib->Menu[i].Entry[j].AllocatedMemory) : 01846 NULL; 01847 01848 old->Menu[i].Entry[j].Template = 01849 lib->Menu[i].Entry[j].Template ? 01850 strdup (lib->Menu[i].Entry[j].Template) : 01851 NULL; 01852 01853 old->Menu[i].Entry[j].Package = 01854 lib->Menu[i].Entry[j].Package ? 01855 strdup (lib->Menu[i].Entry[j].Package) : 01856 NULL; 01857 01858 old->Menu[i].Entry[j].Value = 01859 lib->Menu[i].Entry[j].Value ? 01860 strdup (lib->Menu[i].Entry[j].Value) : 01861 NULL; 01862 01863 old->Menu[i].Entry[j].Description = 01864 lib->Menu[i].Entry[j].Description ? 01865 strdup (lib->Menu[i].Entry[j].Description) : 01866 NULL; 01867 01868 01869 } 01870 } 01871 01872 } 01873 } 01874 01875 /* --------------------------------------------------------------------------- 01876 * adds an object to the list of objects with buried info data 01877 */ 01878 void 01879 AddObjectToSetViaLayersUndoList (void *ptr1, void *ptr2, void *ptr3) 01880 { 01881 UndoListType *undo; 01882 01883 if (!Locked) 01884 { 01885 undo = GetUndoSlot (UNDO_CHANGESETVIALAYERS, OBJECT_ID (ptr2), VIA_TYPE); 01886 undo->Data.SetViaLayersChange.from = ((PinType *) ptr2)->BuriedFrom; 01887 undo->Data.SetViaLayersChange.to = ((PinType *) ptr2)->BuriedTo; 01888 } 01889 } 01890 01891 01892 /* --------------------------------------------------------------------------- 01893 * \brief Set lock flag 01894 */ 01895 void 01896 LockUndo (void) 01897 { 01898 Locked = true; 01899 } 01900 01904 void 01905 UnlockUndo (void) 01906 { 01907 Locked = false; 01908 } 01909 01913 bool 01914 Undoing (void) 01915 { 01916 return (Locked); 01917 }