pcb 4.1.1
An interactive printed circuit board layout editor.
|
00001 00035 #ifdef HAVE_CONFIG_H 00036 #include "config.h" 00037 #endif 00038 00039 #include <setjmp.h> 00040 #include <stdlib.h> 00041 00042 #include "global.h" 00043 00044 #include "create.h" 00045 #include "crosshair.h" 00046 #include "data.h" 00047 #include "draw.h" 00048 #include "error.h" 00049 #include "misc.h" 00050 #include "move.h" 00051 #include "mymem.h" 00052 #include "polygon.h" 00053 #include "rtree.h" 00054 #include "search.h" 00055 #include "select.h" 00056 #include "thermal.h" 00057 #include "undo.h" 00058 00059 #ifdef HAVE_LIBDMALLOC 00060 #include <dmalloc.h> 00061 #endif 00062 00063 /* --------------------------------------------------------------------------- 00064 * some local prototypes 00065 */ 00066 static void *MoveElementName (ElementType *); 00067 static void *MoveElement (ElementType *); 00068 static void *MoveVia (PinType *); 00069 static void *MoveLine (LayerType *, LineType *); 00070 static void *MoveArc (LayerType *, ArcType *); 00071 static void *MoveText (LayerType *, TextType *); 00072 static void *MovePolygon (LayerType *, PolygonType *); 00073 static void *MoveLinePoint (LayerType *, LineType *, PointType *); 00074 static void *MovePolygonPoint (LayerType *, PolygonType *, PointType *); 00075 static void *MoveLineToLayer (LayerType *, LineType *); 00076 static void *MoveArcToLayer (LayerType *, ArcType *); 00077 static void *MoveRatToLayer (RatType *); 00078 static void *MoveTextToLayer (LayerType *, TextType *); 00079 static void *MovePolygonToLayer (LayerType *, PolygonType *); 00080 00081 /* --------------------------------------------------------------------------- 00082 * some local identifiers 00083 */ 00084 static Coord DeltaX, DeltaY; /* used by local routines as offset */ 00085 static LayerType *Dest; 00086 static bool MoreToCome; 00087 static ObjectFunctionType MoveFunctions = { 00088 MoveLine, 00089 MoveText, 00090 MovePolygon, 00091 MoveVia, 00092 MoveElement, 00093 MoveElementName, 00094 NULL, 00095 NULL, 00096 MoveLinePoint, 00097 MovePolygonPoint, 00098 MoveArc, 00099 NULL 00100 }, MoveToLayerFunctions = 00101 00102 { 00103 MoveLineToLayer, 00104 MoveTextToLayer, 00105 MovePolygonToLayer, 00106 NULL, NULL, NULL, NULL, NULL, NULL, NULL, MoveArcToLayer, MoveRatToLayer}; 00107 00111 void 00112 MoveElementLowLevel (DataType *Data, ElementType *Element, 00113 Coord DX, Coord DY) 00114 { 00115 if (Data) 00116 r_delete_entry (Data->element_tree, (BoxType *)Element); 00117 ELEMENTLINE_LOOP (Element); 00118 { 00119 MOVE_LINE_LOWLEVEL (line, DX, DY); 00120 } 00121 END_LOOP; 00122 PIN_LOOP (Element); 00123 { 00124 if (Data) 00125 { 00126 r_delete_entry (Data->pin_tree, (BoxType *)pin); 00127 RestoreToPolygon (Data, PIN_TYPE, Element, pin); 00128 } 00129 MOVE_PIN_LOWLEVEL (pin, DX, DY); 00130 if (Data) 00131 { 00132 r_insert_entry (Data->pin_tree, (BoxType *)pin, 0); 00133 ClearFromPolygon (Data, PIN_TYPE, Element, pin); 00134 } 00135 } 00136 END_LOOP; 00137 PAD_LOOP (Element); 00138 { 00139 if (Data) 00140 { 00141 r_delete_entry (Data->pad_tree, (BoxType *)pad); 00142 RestoreToPolygon (Data, PAD_TYPE, Element, pad); 00143 } 00144 MOVE_PAD_LOWLEVEL (pad, DX, DY); 00145 if (Data) 00146 { 00147 r_insert_entry (Data->pad_tree, (BoxType *)pad, 0); 00148 ClearFromPolygon (Data, PAD_TYPE, Element, pad); 00149 } 00150 } 00151 END_LOOP; 00152 ARC_LOOP (Element); 00153 { 00154 MOVE_ARC_LOWLEVEL (arc, DX, DY); 00155 } 00156 END_LOOP; 00157 ELEMENTTEXT_LOOP (Element); 00158 { 00159 if (Data && Data->name_tree[n]) 00160 r_delete_entry (PCB->Data->name_tree[n], (BoxType *)text); 00161 MOVE_TEXT_LOWLEVEL (text, DX, DY); 00162 if (Data && Data->name_tree[n]) 00163 r_insert_entry (PCB->Data->name_tree[n], (BoxType *)text, 0); 00164 } 00165 END_LOOP; 00166 MOVE_BOX_LOWLEVEL (&Element->BoundingBox, DX, DY); 00167 MOVE_BOX_LOWLEVEL (&Element->VBox, DX, DY); 00168 MOVE (Element->MarkX, Element->MarkY, DX, DY); 00169 if (Data) 00170 r_insert_entry (Data->element_tree, (BoxType *)Element, 0); 00171 } 00172 00176 static void * 00177 MoveElementName (ElementType *Element) 00178 { 00179 if (PCB->ElementOn && (FRONT (Element) || PCB->InvisibleObjectsOn)) 00180 { 00181 EraseElementName (Element); 00182 ELEMENTTEXT_LOOP (Element); 00183 { 00184 if (PCB->Data->name_tree[n]) 00185 r_delete_entry (PCB->Data->name_tree[n], (BoxType *)text); 00186 MOVE_TEXT_LOWLEVEL (text, DeltaX, DeltaY); 00187 if (PCB->Data->name_tree[n]) 00188 r_insert_entry (PCB->Data->name_tree[n], (BoxType *)text, 0); 00189 } 00190 END_LOOP; 00191 DrawElementName (Element); 00192 Draw (); 00193 } 00194 else 00195 { 00196 ELEMENTTEXT_LOOP (Element); 00197 { 00198 if (PCB->Data->name_tree[n]) 00199 r_delete_entry (PCB->Data->name_tree[n], (BoxType *)text); 00200 MOVE_TEXT_LOWLEVEL (text, DeltaX, DeltaY); 00201 if (PCB->Data->name_tree[n]) 00202 r_insert_entry (PCB->Data->name_tree[n], (BoxType *)text, 0); 00203 } 00204 END_LOOP; 00205 } 00206 return (Element); 00207 } 00208 00212 static void * 00213 MoveElement (ElementType *Element) 00214 { 00215 bool didDraw = false; 00216 00217 if (PCB->ElementOn && (FRONT (Element) || PCB->InvisibleObjectsOn)) 00218 { 00219 EraseElement (Element); 00220 MoveElementLowLevel (PCB->Data, Element, DeltaX, DeltaY); 00221 DrawElementName (Element); 00222 DrawElementPackage (Element); 00223 didDraw = true; 00224 } 00225 else 00226 { 00227 if (PCB->PinOn) 00228 EraseElementPinsAndPads (Element); 00229 MoveElementLowLevel (PCB->Data, Element, DeltaX, DeltaY); 00230 } 00231 if (PCB->PinOn) 00232 { 00233 DrawElementPinsAndPads (Element); 00234 didDraw = true; 00235 } 00236 if (didDraw) 00237 Draw (); 00238 return (Element); 00239 } 00240 00244 static void * 00245 MoveVia (PinType *Via) 00246 { 00247 r_delete_entry (PCB->Data->via_tree, (BoxType *)Via); 00248 RestoreToPolygon (PCB->Data, VIA_TYPE, Via, Via); 00249 MOVE_VIA_LOWLEVEL (Via, DeltaX, DeltaY); 00250 if (PCB->ViaOn) 00251 EraseVia (Via); 00252 r_insert_entry (PCB->Data->via_tree, (BoxType *)Via, 0); 00253 ClearFromPolygon (PCB->Data, VIA_TYPE, Via, Via); 00254 if (PCB->ViaOn) 00255 { 00256 DrawVia (Via); 00257 Draw (); 00258 } 00259 return (Via); 00260 } 00261 00265 static void * 00266 MoveLine (LayerType *Layer, LineType *Line) 00267 { 00268 if (Layer->On) 00269 EraseLine (Line); 00270 RestoreToPolygon (PCB->Data, LINE_TYPE, Layer, Line); 00271 r_delete_entry (Layer->line_tree, (BoxType *)Line); 00272 MOVE_LINE_LOWLEVEL (Line, DeltaX, DeltaY); 00273 r_insert_entry (Layer->line_tree, (BoxType *)Line, 0); 00274 ClearFromPolygon (PCB->Data, LINE_TYPE, Layer, Line); 00275 if (Layer->On) 00276 { 00277 DrawLine (Layer, Line); 00278 Draw (); 00279 } 00280 return (Line); 00281 } 00282 00286 static void * 00287 MoveArc (LayerType *Layer, ArcType *Arc) 00288 { 00289 RestoreToPolygon (PCB->Data, ARC_TYPE, Layer, Arc); 00290 r_delete_entry (Layer->arc_tree, (BoxType *)Arc); 00291 if (Layer->On) 00292 { 00293 EraseArc (Arc); 00294 MOVE_ARC_LOWLEVEL (Arc, DeltaX, DeltaY); 00295 DrawArc (Layer, Arc); 00296 Draw (); 00297 } 00298 else 00299 { 00300 MOVE_ARC_LOWLEVEL (Arc, DeltaX, DeltaY); 00301 } 00302 r_insert_entry (Layer->arc_tree, (BoxType *)Arc, 0); 00303 ClearFromPolygon (PCB->Data, ARC_TYPE, Layer, Arc); 00304 return (Arc); 00305 } 00306 00310 static void * 00311 MoveText (LayerType *Layer, TextType *Text) 00312 { 00313 RestoreToPolygon (PCB->Data, TEXT_TYPE, Layer, Text); 00314 r_delete_entry (Layer->text_tree, (BoxType *)Text); 00315 if (Layer->On) 00316 { 00317 EraseText (Layer, Text); 00318 MOVE_TEXT_LOWLEVEL (Text, DeltaX, DeltaY); 00319 DrawText (Layer, Text); 00320 Draw (); 00321 } 00322 else 00323 MOVE_TEXT_LOWLEVEL (Text, DeltaX, DeltaY); 00324 r_insert_entry (Layer->text_tree, (BoxType *)Text, 0); 00325 ClearFromPolygon (PCB->Data, TEXT_TYPE, Layer, Text); 00326 return (Text); 00327 } 00328 00332 void 00333 MovePolygonLowLevel (PolygonType *Polygon, Coord DeltaX, Coord DeltaY) 00334 { 00335 POLYGONPOINT_LOOP (Polygon); 00336 { 00337 MOVE (point->X, point->Y, DeltaX, DeltaY); 00338 } 00339 END_LOOP; 00340 MOVE_BOX_LOWLEVEL (&Polygon->BoundingBox, DeltaX, DeltaY); 00341 } 00342 00346 static void * 00347 MovePolygon (LayerType *Layer, PolygonType *Polygon) 00348 { 00349 if (Layer->On) 00350 { 00351 ErasePolygon (Polygon); 00352 } 00353 r_delete_entry (Layer->polygon_tree, (BoxType *)Polygon); 00354 MovePolygonLowLevel (Polygon, DeltaX, DeltaY); 00355 r_insert_entry (Layer->polygon_tree, (BoxType *)Polygon, 0); 00356 InitClip (PCB->Data, Layer, Polygon); 00357 if (Layer->On) 00358 { 00359 DrawPolygon (Layer, Polygon); 00360 Draw (); 00361 } 00362 return (Polygon); 00363 } 00364 00368 static void * 00369 MoveLinePoint (LayerType *Layer, LineType *Line, PointType *Point) 00370 { 00371 if (Layer) 00372 { 00373 if (Layer->On) 00374 EraseLine (Line); 00375 RestoreToPolygon (PCB->Data, LINE_TYPE, Layer, Line); 00376 r_delete_entry (Layer->line_tree, &Line->BoundingBox); 00377 MOVE (Point->X, Point->Y, DeltaX, DeltaY); 00378 SetLineBoundingBox (Line); 00379 r_insert_entry (Layer->line_tree, &Line->BoundingBox, 0); 00380 ClearFromPolygon (PCB->Data, LINE_TYPE, Layer, Line); 00381 if (Layer->On) 00382 { 00383 DrawLine (Layer, Line); 00384 Draw (); 00385 } 00386 return (Line); 00387 } 00388 else /* must be a rat */ 00389 { 00390 if (PCB->RatOn) 00391 EraseRat ((RatType *) Line); 00392 r_delete_entry (PCB->Data->rat_tree, &Line->BoundingBox); 00393 MOVE (Point->X, Point->Y, DeltaX, DeltaY); 00394 SetLineBoundingBox (Line); 00395 r_insert_entry (PCB->Data->rat_tree, &Line->BoundingBox, 0); 00396 if (PCB->RatOn) 00397 { 00398 DrawRat ((RatType *) Line); 00399 Draw (); 00400 } 00401 return (Line); 00402 } 00403 } 00404 00408 static void * 00409 MovePolygonPoint (LayerType *Layer, PolygonType *Polygon, 00410 PointType *Point) 00411 { 00412 if (Layer->On) 00413 { 00414 ErasePolygon (Polygon); 00415 } 00416 r_delete_entry (Layer->polygon_tree, (BoxType *)Polygon); 00417 MOVE (Point->X, Point->Y, DeltaX, DeltaY); 00418 SetPolygonBoundingBox (Polygon); 00419 r_insert_entry (Layer->polygon_tree, (BoxType *)Polygon, 0); 00420 RemoveExcessPolygonPoints (Layer, Polygon); 00421 InitClip (PCB->Data, Layer, Polygon); 00422 if (Layer->On) 00423 { 00424 DrawPolygon (Layer, Polygon); 00425 Draw (); 00426 } 00427 return (Point); 00428 } 00429 00433 static void * 00434 MoveLineToLayerLowLevel (LayerType *Source, LineType *line, 00435 LayerType *Destination) 00436 { 00437 r_delete_entry (Source->line_tree, (BoxType *)line); 00438 00439 Source->Line = g_list_remove (Source->Line, line); 00440 Source->LineN --; 00441 Destination->Line = g_list_append (Destination->Line, line); 00442 Destination->LineN ++; 00443 00444 if (!Destination->line_tree) 00445 Destination->line_tree = r_create_tree (NULL, 0, 0); 00446 r_insert_entry (Destination->line_tree, (BoxType *)line, 0); 00447 return line; 00448 } 00449 00453 static void * 00454 MoveArcToLayerLowLevel (LayerType *Source, ArcType *arc, 00455 LayerType *Destination) 00456 { 00457 r_delete_entry (Source->arc_tree, (BoxType *)arc); 00458 00459 Source->Arc = g_list_remove (Source->Arc, arc); 00460 Source->ArcN --; 00461 Destination->Arc = g_list_append (Destination->Arc, arc); 00462 Destination->ArcN ++; 00463 00464 if (!Destination->arc_tree) 00465 Destination->arc_tree = r_create_tree (NULL, 0, 0); 00466 r_insert_entry (Destination->arc_tree, (BoxType *)arc, 0); 00467 return arc; 00468 } 00469 00470 00474 static void * 00475 MoveArcToLayer (LayerType *Layer, ArcType *Arc) 00476 { 00477 ArcType *newone; 00478 00479 if (TEST_FLAG (LOCKFLAG, Arc)) 00480 { 00481 Message (_("Sorry, the object is locked\n")); 00482 return NULL; 00483 } 00484 if (Dest == Layer && Layer->On) 00485 { 00486 DrawArc (Layer, Arc); 00487 Draw (); 00488 } 00489 if (((long int) Dest == -1) || Dest == Layer) 00490 return (Arc); 00491 AddObjectToMoveToLayerUndoList (ARC_TYPE, Layer, Arc, Arc); 00492 RestoreToPolygon (PCB->Data, ARC_TYPE, Layer, Arc); 00493 if (Layer->On) 00494 EraseArc (Arc); 00495 newone = (ArcType *)MoveArcToLayerLowLevel (Layer, Arc, Dest); 00496 ClearFromPolygon (PCB->Data, ARC_TYPE, Dest, Arc); 00497 if (Dest->On) 00498 DrawArc (Dest, newone); 00499 Draw (); 00500 return (newone); 00501 } 00502 00506 static void * 00507 MoveRatToLayer (RatType *Rat) 00508 { 00509 LineType *newone; 00510 //Coord X1 = Rat->Point1.X, Y1 = Rat->Point1.Y; 00511 //Coord X1 = Rat->Point1.X, Y1 = Rat->Point1.Y; 00512 // if VIAFLAG 00513 // if we're on a pin, add a thermal 00514 // else make a via and a wire, but 0-length wire not good 00515 // else as before 00516 00517 newone = CreateNewLineOnLayer (Dest, Rat->Point1.X, Rat->Point1.Y, 00518 Rat->Point2.X, Rat->Point2.Y, 00519 Settings.LineThickness, 2 * Settings.Keepaway, 00520 Rat->Flags); 00521 if (TEST_FLAG (CLEARNEWFLAG, PCB)) 00522 SET_FLAG (CLEARLINEFLAG, newone); 00523 if (!newone) 00524 return (NULL); 00525 AddObjectToCreateUndoList (LINE_TYPE, Dest, newone, newone); 00526 if (PCB->RatOn) 00527 EraseRat (Rat); 00528 MoveObjectToRemoveUndoList (RATLINE_TYPE, Rat, Rat, Rat); 00529 DrawLine (Dest, newone); 00530 Draw (); 00531 return (newone); 00532 } 00533 00538 struct via_info 00539 { 00540 Coord X, Y; 00541 Cardinal layer_from, layer_to; 00542 jmp_buf env; 00543 }; 00544 00545 static int 00546 moveline_callback (const BoxType * b, void *cl) 00547 { 00548 struct via_info *i = (struct via_info *) cl; 00549 PinType *via; 00550 00551 if ((via = 00552 CreateNewViaEx (PCB->Data, i->X, i->Y, 00553 Settings.ViaThickness, 2 * Settings.Keepaway, 00554 NOFLAG, Settings.ViaDrillingHole, NULL, 00555 NoFlags (), i->layer_from, i->layer_to)) != NULL) 00556 { 00557 AddObjectToCreateUndoList (VIA_TYPE, via, via, via); 00558 DrawVia (via); 00559 } 00560 longjmp (i->env, 1); 00561 } 00562 00563 static void * 00564 MoveLineToLayer (LayerType *Layer, LineType *Line) 00565 { 00566 struct via_info info; 00567 BoxType sb; 00568 LineType *newone; 00569 void *ptr1, *ptr2, *ptr3; 00570 00571 if (TEST_FLAG (LOCKFLAG, Line)) 00572 { 00573 Message (_("Sorry, the object is locked\n")); 00574 return NULL; 00575 } 00576 if (Dest == Layer && Layer->On) 00577 { 00578 DrawLine (Layer, Line); 00579 Draw (); 00580 } 00581 if (((long int) Dest == -1) || Dest == Layer) 00582 return (Line); 00583 00584 AddObjectToMoveToLayerUndoList (LINE_TYPE, Layer, Line, Line); 00585 if (Layer->On) 00586 EraseLine (Line); 00587 RestoreToPolygon (PCB->Data, LINE_TYPE, Layer, Line); 00588 newone = (LineType *)MoveLineToLayerLowLevel (Layer, Line, Dest); 00589 Line = NULL; 00590 ClearFromPolygon (PCB->Data, LINE_TYPE, Dest, newone); 00591 if (Dest->On) 00592 DrawLine (Dest, newone); 00593 Draw (); 00594 if (!PCB->ViaOn || MoreToCome || 00595 GetLayerGroupNumberByPointer (Layer) == 00596 GetLayerGroupNumberByPointer (Dest) || 00597 TEST_SILK_LAYER(Layer) || 00598 TEST_SILK_LAYER(Dest)) 00599 return (newone); 00600 00601 if (TEST_FLAG (AUTOBURIEDVIASFLAG, PCB)) 00602 { 00603 info.layer_from = GetLayerNumber (PCB->Data, Layer); 00604 info.layer_to = GetLayerNumber (PCB->Data, Dest); 00605 } 00606 else 00607 { 00608 info.layer_from = 0; 00609 info.layer_to = 0; 00610 } 00611 /* consider via at Point1 */ 00612 sb.X1 = newone->Point1.X - newone->Thickness / 2; 00613 sb.X2 = newone->Point1.X + newone->Thickness / 2; 00614 sb.Y1 = newone->Point1.Y - newone->Thickness / 2; 00615 sb.Y2 = newone->Point1.Y + newone->Thickness / 2; 00616 if ((SearchObjectByLocation (PIN_TYPES, &ptr1, &ptr2, &ptr3, 00617 newone->Point1.X, newone->Point1.Y, 00618 Settings.ViaThickness / 2) == NO_TYPE)) 00619 { 00620 info.X = newone->Point1.X; 00621 info.Y = newone->Point1.Y; 00622 if (setjmp (info.env) == 0) 00623 r_search (Layer->line_tree, &sb, NULL, moveline_callback, &info); 00624 } 00625 /* consider via at Point2 */ 00626 sb.X1 = newone->Point2.X - newone->Thickness / 2; 00627 sb.X2 = newone->Point2.X + newone->Thickness / 2; 00628 sb.Y1 = newone->Point2.Y - newone->Thickness / 2; 00629 sb.Y2 = newone->Point2.Y + newone->Thickness / 2; 00630 if ((SearchObjectByLocation (PIN_TYPES, &ptr1, &ptr2, &ptr3, 00631 newone->Point2.X, newone->Point2.Y, 00632 Settings.ViaThickness / 2) == NO_TYPE)) 00633 { 00634 info.X = newone->Point2.X; 00635 info.Y = newone->Point2.Y; 00636 if (setjmp (info.env) == 0) 00637 r_search (Layer->line_tree, &sb, NULL, moveline_callback, &info); 00638 } 00639 Draw (); 00640 return (newone); 00641 } 00642 00646 static void * 00647 MoveTextToLayerLowLevel (LayerType *Source, TextType *text, 00648 LayerType *Destination) 00649 { 00650 RestoreToPolygon (PCB->Data, TEXT_TYPE, Source, text); 00651 r_delete_entry (Source->text_tree, (BoxType *)text); 00652 00653 Source->Text = g_list_remove (Source->Text, text); 00654 Source->TextN --; 00655 Destination->Text = g_list_append (Destination->Text, text); 00656 Destination->TextN ++; 00657 00658 if (GetLayerGroupNumberBySide (BOTTOM_SIDE) == 00659 GetLayerGroupNumberByPointer (Destination)) 00660 SET_FLAG (ONSOLDERFLAG, text); 00661 else 00662 CLEAR_FLAG (ONSOLDERFLAG, text); 00663 00664 /* re-calculate the bounding box (it could be mirrored now) */ 00665 SetTextBoundingBox (&PCB->Font, text); 00666 if (!Destination->text_tree) 00667 Destination->text_tree = r_create_tree (NULL, 0, 0); 00668 r_insert_entry (Destination->text_tree, (BoxType *)text, 0); 00669 ClearFromPolygon (PCB->Data, TEXT_TYPE, Destination, text); 00670 00671 return text; 00672 } 00673 00677 static void * 00678 MoveTextToLayer (LayerType *layer, TextType *text) 00679 { 00680 if (TEST_FLAG (LOCKFLAG, text)) 00681 { 00682 Message (_("Sorry, the object is locked\n")); 00683 return NULL; 00684 } 00685 if (Dest != layer) 00686 { 00687 AddObjectToMoveToLayerUndoList (TEXT_TYPE, layer, text, text); 00688 if (layer->On) 00689 EraseText (layer, text); 00690 text = MoveTextToLayerLowLevel (layer, text, Dest); 00691 if (Dest->On) 00692 DrawText (Dest, text); 00693 if (layer->On || Dest->On) 00694 Draw (); 00695 } 00696 return text; 00697 } 00698 00702 static void * 00703 MovePolygonToLayerLowLevel (LayerType *Source, PolygonType *polygon, 00704 LayerType *Destination) 00705 { 00706 r_delete_entry (Source->polygon_tree, (BoxType *)polygon); 00707 00708 Source->Polygon = g_list_remove (Source->Polygon, polygon); 00709 Source->PolygonN --; 00710 Destination->Polygon = g_list_append (Destination->Polygon, polygon); 00711 Destination->PolygonN ++; 00712 00713 if (!Destination->polygon_tree) 00714 Destination->polygon_tree = r_create_tree (NULL, 0, 0); 00715 r_insert_entry (Destination->polygon_tree, (BoxType *)polygon, 0); 00716 00717 return polygon; 00718 } 00719 00720 struct mptlc 00721 { 00722 Cardinal snum, dnum; 00723 int type; 00724 PolygonType *polygon; 00725 } mptlc; 00726 00727 int 00728 mptl_pin_callback (const BoxType *b, void *cl) 00729 { 00730 struct mptlc *d = (struct mptlc *) cl; 00731 PinType *pin = (PinType *) b; 00732 if (!TEST_THERM (d->snum, pin) || ! 00733 IsPointInPolygon (pin->X, pin->Y, pin->Thickness + pin->Clearance + 2, 00734 d->polygon)) 00735 return 0; 00736 if (d->type == PIN_TYPE) 00737 AddObjectToFlagUndoList (PIN_TYPE, pin->Element, pin, pin); 00738 else 00739 AddObjectToFlagUndoList (VIA_TYPE, pin, pin, pin); 00740 ASSIGN_THERM (d->dnum, GET_THERM (d->snum, pin), pin); 00741 CLEAR_THERM (d->snum, pin); 00742 return 1; 00743 } 00744 00748 static void * 00749 MovePolygonToLayer (LayerType *Layer, PolygonType *Polygon) 00750 { 00751 PolygonType *newone; 00752 struct mptlc d; 00753 00754 if (TEST_FLAG (LOCKFLAG, Polygon)) 00755 { 00756 Message (_("Sorry, the object is locked\n")); 00757 return NULL; 00758 } 00759 if (((long int) Dest == -1) || (Layer == Dest)) 00760 return (Polygon); 00761 AddObjectToMoveToLayerUndoList (POLYGON_TYPE, Layer, Polygon, Polygon); 00762 if (Layer->On) 00763 ErasePolygon (Polygon); 00764 /* Move all of the thermals with the polygon */ 00765 d.snum = GetLayerNumber (PCB->Data, Layer); 00766 d.dnum = GetLayerNumber (PCB->Data, Dest); 00767 d.polygon = Polygon; 00768 d.type = PIN_TYPE; 00769 r_search (PCB->Data->pin_tree, &Polygon->BoundingBox, NULL, mptl_pin_callback, &d); 00770 d.type = VIA_TYPE; 00771 r_search (PCB->Data->via_tree, &Polygon->BoundingBox, NULL, mptl_pin_callback, &d); 00772 newone = (struct polygon_st *)MovePolygonToLayerLowLevel (Layer, Polygon, Dest); 00773 InitClip (PCB->Data, Dest, newone); 00774 if (Dest->On) 00775 { 00776 DrawPolygon (Dest, newone); 00777 Draw (); 00778 } 00779 return (newone); 00780 } 00781 00786 void * 00787 MoveObject (int Type, void *Ptr1, void *Ptr2, void *Ptr3, Coord DX, Coord DY) 00788 { 00789 void *result; 00790 /* setup offset */ 00791 DeltaX = DX; 00792 DeltaY = DY; 00793 AddObjectToMoveUndoList (Type, Ptr1, Ptr2, Ptr3, DX, DY); 00794 result = ObjectOperation (&MoveFunctions, Type, Ptr1, Ptr2, Ptr3); 00795 return (result); 00796 } 00797 00802 void * 00803 MoveObjectAndRubberband (int Type, void *Ptr1, void *Ptr2, void *Ptr3, 00804 Coord DX, Coord DY) 00805 { 00806 RubberbandType *ptr; 00807 void *ptr2; 00808 00809 /* setup offset */ 00810 DeltaX = DX; 00811 DeltaY = DY; 00812 00813 /* move all the lines... and reset the counter */ 00814 ptr = Crosshair.AttachedObject.Rubberband; 00815 while (Crosshair.AttachedObject.RubberbandN) 00816 { 00817 /* first clear any marks that we made in the line flags */ 00818 CLEAR_FLAG (RUBBERENDFLAG, ptr->Line); 00819 /* only update undo list if an actual movement happened */ 00820 if (DX != 0 || DY != 0) 00821 { 00822 AddObjectToMoveUndoList (LINEPOINT_TYPE, 00823 ptr->Layer, ptr->Line, 00824 ptr->MovedPoint, DX, DY); 00825 MoveLinePoint (ptr->Layer, ptr->Line, ptr->MovedPoint); 00826 } 00827 Crosshair.AttachedObject.RubberbandN--; 00828 ptr++; 00829 } 00830 00831 if (DX == 0 && DY == 0) 00832 return (NULL); 00833 00834 AddObjectToMoveUndoList (Type, Ptr1, Ptr2, Ptr3, DX, DY); 00835 ptr2 = ObjectOperation (&MoveFunctions, Type, Ptr1, Ptr2, Ptr3); 00836 IncrementUndoSerialNumber (); 00837 return (ptr2); 00838 } 00839 00844 void * 00845 MoveObjectToLayer (int Type, void *Ptr1, void *Ptr2, void *Ptr3, 00846 LayerType *Target, bool enmasse) 00847 { 00848 void *result; 00849 00850 /* setup global identifiers */ 00851 Dest = Target; 00852 MoreToCome = enmasse; 00853 result = ObjectOperation (&MoveToLayerFunctions, Type, Ptr1, Ptr2, Ptr3); 00854 IncrementUndoSerialNumber (); 00855 return (result); 00856 } 00857 00862 bool 00863 MoveSelectedObjectsToLayer (LayerType *Target) 00864 { 00865 bool changed; 00866 00867 /* setup global identifiers */ 00868 Dest = Target; 00869 MoreToCome = true; 00870 changed = SelectedOperation (&MoveToLayerFunctions, true, ALL_TYPES); 00871 /* passing true to above operation causes Undoserial to auto-increment */ 00872 return (changed); 00873 } 00874 00875 static void 00876 move_one_thermal (int old_index, int new_index, PinType *pin) 00877 { 00878 int t1=0, i; 00879 int oi=old_index, ni=new_index; 00880 00881 if (old_index != -1) 00882 t1 = GET_THERM (old_index, pin); 00883 00884 if (oi == -1) 00885 oi = MAX_LAYER-1; /* inserting a layer */ 00886 if (ni == -1) 00887 ni = MAX_LAYER-1; /* deleting a layer */ 00888 00889 if (oi < ni) 00890 { 00891 for (i=oi; i<ni; i++) 00892 ASSIGN_THERM (i, GET_THERM (i+1, pin), pin); 00893 } 00894 else 00895 { 00896 for (i=oi; i>ni; i--) 00897 ASSIGN_THERM (i, GET_THERM (i-1, pin), pin); 00898 } 00899 00900 if (new_index != -1) 00901 ASSIGN_THERM (new_index, t1, pin); 00902 else 00903 ASSIGN_THERM (ni, 0, pin); 00904 } 00905 00906 static void 00907 move_all_thermals (int old_index, int new_index) 00908 { 00909 VIA_LOOP (PCB->Data); 00910 { 00911 move_one_thermal (old_index, new_index, via); 00912 } 00913 END_LOOP; 00914 00915 ALLPIN_LOOP (PCB->Data); 00916 { 00917 move_one_thermal (old_index, new_index, pin); 00918 } 00919 ENDALL_LOOP; 00920 } 00921 00922 static int 00923 LastNormalLayerInSideGroup (int side, int layer) 00924 { 00925 int side_group = GetLayerGroupNumberBySide (side); 00926 int lgroup = GetLayerGroupNumberByNumber (layer); 00927 if (side_group == lgroup 00928 && PCB->LayerGroups.Number[lgroup] == 2) 00929 return 1; 00930 return 0; 00931 } 00932 00942 int 00943 MoveLayer (int old_index, int new_index) 00944 { 00945 int group_of_layer[MAX_ALL_LAYER], l, g, i; 00946 LayerType saved_layer; 00947 int saved_group; 00948 00949 AddLayerChangeToUndoList (old_index, new_index); 00950 00951 if (old_index < -1 || old_index >= max_copper_layer) 00952 { 00953 Message ("Invalid old layer %d for move: must be -1..%d\n", 00954 old_index, max_copper_layer - 1); 00955 return 1; 00956 } 00957 if (new_index < -1 || new_index > max_copper_layer || 00958 new_index >= MAX_LAYER) 00959 { 00960 Message ("Invalid new layer %d for move: must be -1..%d\n", 00961 new_index, max_copper_layer); 00962 return 1; 00963 } 00964 if (old_index == new_index) 00965 return 0; 00966 00967 if (new_index == -1 00968 && LastNormalLayerInSideGroup (TOP_SIDE, old_index)) 00969 { 00970 gui->confirm_dialog ("You can't delete the last top-side layer\n", "Ok", NULL); 00971 return 1; 00972 } 00973 00974 if (new_index == -1 00975 && LastNormalLayerInSideGroup (BOTTOM_SIDE, old_index)) 00976 { 00977 gui->confirm_dialog ("You can't delete the last bottom-side layer\n", "Ok", NULL); 00978 return 1; 00979 } 00980 00981 for (l = 0; l < MAX_ALL_LAYER; l++) 00982 group_of_layer[l] = -1; 00983 00984 for (g = 0; g < MAX_GROUP; g++) 00985 for (i = 0; i < PCB->LayerGroups.Number[g]; i++) 00986 group_of_layer[PCB->LayerGroups.Entries[g][i]] = g; 00987 00988 if (old_index == -1) 00989 { 00990 LayerType *lp; 00991 if (max_copper_layer == MAX_LAYER) 00992 { 00993 Message ("No room for new layers\n"); 00994 return 1; 00995 } 00996 /* Create a new layer at new_index. */ 00997 lp = &PCB->Data->Layer[new_index]; 00998 memmove (&PCB->Data->Layer[new_index + 1], 00999 &PCB->Data->Layer[new_index], 01000 (max_copper_layer + SILK_LAYER - new_index) * sizeof (LayerType)); 01001 memmove (&group_of_layer[new_index + 1], 01002 &group_of_layer[new_index], 01003 (max_copper_layer + SILK_LAYER - new_index) * sizeof (int)); 01004 max_copper_layer++; 01005 memset (lp, 0, sizeof (LayerType)); 01006 lp->On = 1; 01007 lp->Name = strdup ("New Layer"); 01008 lp->Color = Settings.LayerColor[new_index]; 01009 lp->SelectedColor = Settings.LayerSelectedColor[new_index]; 01010 for (l = 0; l < max_copper_layer; l++) 01011 if (LayerStack[l] >= new_index) 01012 LayerStack[l]++; 01013 LayerStack[max_copper_layer - 1] = new_index; 01014 01015 if (!Undoing ()) 01016 ChangeBuriedViasAfterLayerCreate (new_index); 01017 } 01018 else if (new_index == -1) 01019 { 01020 /* Delete the layer at old_index */ 01021 memmove (&PCB->Data->Layer[old_index], 01022 &PCB->Data->Layer[old_index + 1], 01023 (max_copper_layer + SILK_LAYER - old_index - 1) * 01024 sizeof (LayerType)); 01025 memset (&PCB->Data->Layer[max_copper_layer + SILK_LAYER - 1], 01026 0, sizeof (LayerType)); 01027 memmove (&group_of_layer[old_index], 01028 &group_of_layer[old_index + 1], 01029 (max_copper_layer + SILK_LAYER - old_index - 1) * sizeof (int)); 01030 for (l = 0; l < max_copper_layer; l++) 01031 if (LayerStack[l] == old_index) 01032 memmove (LayerStack + l, 01033 LayerStack + l + 1, 01034 (max_copper_layer - l - 1) * sizeof (LayerStack[0])); 01035 max_copper_layer--; 01036 for (l = 0; l < max_copper_layer; l++) 01037 if (LayerStack[l] > old_index) 01038 LayerStack[l]--; 01039 01040 if (!Undoing ()) 01041 ChangeBuriedViasAfterLayerDelete (old_index); 01042 } 01043 else 01044 { 01045 /* Move an existing layer */ 01046 memcpy (&saved_layer, &PCB->Data->Layer[old_index], sizeof (LayerType)); 01047 saved_group = group_of_layer[old_index]; 01048 if (old_index < new_index) 01049 { 01050 memmove (&PCB->Data->Layer[old_index], 01051 &PCB->Data->Layer[old_index + 1], 01052 (new_index - old_index) * sizeof (LayerType)); 01053 memmove (&group_of_layer[old_index], 01054 &group_of_layer[old_index + 1], 01055 (new_index - old_index) * sizeof (int)); 01056 } 01057 else 01058 { 01059 memmove (&PCB->Data->Layer[new_index + 1], 01060 &PCB->Data->Layer[new_index], 01061 (old_index - new_index) * sizeof (LayerType)); 01062 memmove (&group_of_layer[new_index + 1], 01063 &group_of_layer[new_index], 01064 (old_index - new_index) * sizeof (int)); 01065 } 01066 memcpy (&PCB->Data->Layer[new_index], &saved_layer, sizeof (LayerType)); 01067 group_of_layer[new_index] = saved_group; 01068 01069 if (!Undoing ()) 01070 ChangeBuriedViasAfterLayerMove (old_index, new_index); 01071 } 01072 01073 IncrementUndoSerialNumber (); 01074 01075 move_all_thermals(old_index, new_index); 01076 01077 for (g = 0; g < MAX_GROUP; g++) 01078 PCB->LayerGroups.Number[g] = 0; 01079 for (l = 0; l < max_copper_layer + SILK_LAYER; l++) 01080 { 01081 g = group_of_layer[l]; 01082 01083 /* XXX: Should this ever happen? */ 01084 if (g < 0) 01085 continue; 01086 01087 i = PCB->LayerGroups.Number[g]++; 01088 PCB->LayerGroups.Entries[g][i] = l; 01089 } 01090 01091 for (g = 1; g < MAX_GROUP; g++) 01092 if (PCB->LayerGroups.Number[g - 1] == 0) 01093 { 01094 memmove (&PCB->LayerGroups.Number[g - 1], 01095 &PCB->LayerGroups.Number[g], 01096 (MAX_GROUP - g) * sizeof (PCB->LayerGroups.Number[g])); 01097 memmove (&PCB->LayerGroups.Entries[g - 1], 01098 &PCB->LayerGroups.Entries[g], 01099 (MAX_GROUP - g) * sizeof (PCB->LayerGroups.Entries[g])); 01100 } 01101 01102 hid_action ("LayersChanged"); 01103 gui->invalidate_all (); 01104 return 0; 01105 } 01106 01107 /* --------------------------------------------------------------------------- */ 01108 01109 static const char movelayer_syntax[] = "MoveLayer(old,new)"; 01110 01111 static const char movelayer_help[] = "Moves/Creates/Deletes Layers."; 01112 01113 /* %start-doc actions MoveLayer 01114 01115 Moves a layer, creates a new layer, or deletes a layer. 01116 01117 @table @code 01118 01119 @item old 01120 The is the layer number to act upon. Allowed values are: 01121 @table @code 01122 01123 @item c 01124 Currently selected layer. 01125 01126 @item -1 01127 Create a new layer. 01128 01129 @item number 01130 An existing layer number. 01131 01132 @end table 01133 01134 @item new 01135 Specifies where to move the layer to. Allowed values are: 01136 @table @code 01137 @item -1 01138 Deletes the layer. 01139 01140 @item up 01141 Moves the layer up. 01142 01143 @item down 01144 Moves the layer down. 01145 01146 @item c 01147 Creates a new layer. 01148 01149 @end table 01150 01151 @end table 01152 01153 %end-doc */ 01154 01155 int 01156 MoveLayerAction (int argc, char **argv, Coord x, Coord y) 01157 { 01158 int old_index, new_index; 01159 int new_top = -1; 01160 01161 if (argc != 2) 01162 { 01163 Message ("Usage; MoveLayer(old,new)"); 01164 return 1; 01165 } 01166 01167 if (strcmp (argv[0], "c") == 0) 01168 old_index = INDEXOFCURRENT; 01169 else 01170 old_index = atoi (argv[0]); 01171 01172 if (strcmp (argv[1], "c") == 0) 01173 { 01174 new_index = INDEXOFCURRENT; 01175 if (new_index < 0) 01176 new_index = 0; 01177 } 01178 else if (strcmp (argv[1], "up") == 0) 01179 { 01180 new_index = INDEXOFCURRENT - 1; 01181 if (new_index < 0) 01182 return 1; 01183 new_top = new_index; 01184 } 01185 else if (strcmp (argv[1], "down") == 0) 01186 { 01187 new_index = INDEXOFCURRENT + 1; 01188 if (new_index >= max_copper_layer) 01189 return 1; 01190 new_top = new_index; 01191 } 01192 else 01193 new_index = atoi (argv[1]); 01194 01195 if (MoveLayer (old_index, new_index)) 01196 return 1; 01197 01198 if (new_index == -1) 01199 { 01200 new_top = old_index; 01201 if (new_top >= max_copper_layer) 01202 new_top--; 01203 new_index = new_top; 01204 } 01205 if (old_index == -1) 01206 new_top = new_index; 01207 01208 if (new_top != -1) 01209 ChangeGroupVisibility (new_index, 1, 1); 01210 01211 return 0; 01212 } 01213 01214 HID_Action move_action_list[] = { 01215 {"MoveLayer", 0, MoveLayerAction, 01216 movelayer_help, movelayer_syntax} 01217 }; 01218 01219 REGISTER_ACTIONS (move_action_list)