| /* Copyright 2012, Russ.Dill@asu.edu | |
| * Released under LGPLv2 or later */ | |
| #include <math.h> | |
| #include "config.h" | |
| #include "data.h" | |
| #include "rtree.h" | |
| #include "mirror.h" | |
| #include "remove.h" | |
| #include "select.h" | |
| #include "draw.h" | |
| #include "undo.h" | |
| #include "move.h" | |
| #include "change.h" | |
| #include "copy.h" | |
| #include "rotate.h" | |
| #include "global.h" | |
| static char *new_footprint; | |
| static int | |
| direction (Coord x1, Coord y1, Coord x2, Coord y2) | |
| { | |
| if (x1 != x2 || y1 != y2) | |
| { | |
| double theta = atan2(y2 - y1, x2 - x1); | |
| theta *= 2.0 / M_PI; | |
| theta += 4.5; | |
| return (int) theta % 4; | |
| } | |
| return -1; | |
| } | |
| static BYTE | |
| _ElementOrientation (ElementType *e) | |
| { | |
| BYTE ret; | |
| PIN_LOOP (e) | |
| { | |
| ret = direction(e->MarkX, e->MarkY, pin->X, pin->Y); | |
| if (ret != -1) | |
| return ret; | |
| } | |
| END_LOOP; | |
| PAD_LOOP (e) | |
| { | |
| ret = direction(e->MarkX, e->MarkY, pad->Point1.X, pad->Point1.Y); | |
| if (ret != -1) | |
| return ret; | |
| ret = direction(e->MarkX, e->MarkY, pad->Point2.X, pad->Point2.Y); | |
| if (ret != -1) | |
| return ret; | |
| } | |
| END_LOOP; | |
| return 0; | |
| } | |
| static void * | |
| ReplaceElement (ElementType *Element) | |
| { | |
| int i; | |
| FlagType flags; | |
| Coord element_x, element_y; | |
| Coord text_x, text_y; | |
| TextType *name; | |
| BYTE element_rotation; | |
| BYTE text_rotation; | |
| BYTE paste_rotation; | |
| BYTE new_rotation; | |
| int scale; | |
| char *refdes; | |
| char *value; | |
| char *old; | |
| ElementType *paste_element = NULL; | |
| ELEMENT_LOOP (PASTEBUFFER->Data) | |
| { | |
| if (paste_element) | |
| { | |
| /* More than one element */ | |
| return NULL; | |
| } | |
| paste_element = element; | |
| } | |
| END_LOOP; | |
| if (!paste_element) | |
| { | |
| /* No element to paste */ | |
| return NULL; | |
| } | |
| flags = Element->Flags; | |
| element_x = Element->MarkX; | |
| element_y = Element->MarkY; | |
| element_rotation = _ElementOrientation (Element); | |
| name = &Element->Name[NAMEONPCB_INDEX]; | |
| text_x = name->X; | |
| text_y = name->Y; | |
| text_rotation = name->Direction; | |
| scale = name->Scale; | |
| refdes = strdup (name->TextString); | |
| name = &Element->Name[VALUE_INDEX]; | |
| value = strdup (name->TextString); | |
| paste_element = CopyElementLowLevel(PCB->Data, NULL, paste_element, | |
| TEST_FLAG (UNIQUENAMEFLAG, PCB), | |
| element_x - paste_element->MarkX, | |
| element_y - paste_element->MarkY); | |
| if (!FRONT (Element)) | |
| MirrorElementCoordinates (PCB->Data, paste_element, | |
| paste_element->MarkY*2 - PCB->MaxHeight); | |
| // Thermals and polygon zero clearance | |
| PIN_LOOP (Element) | |
| { | |
| PinType *old = pin; | |
| if (pin->Number) | |
| { | |
| PIN_LOOP (paste_element) | |
| { | |
| if (pin->Number && !strcmp (pin->Number, old->Number)) | |
| { | |
| if (!old->Clearance) | |
| pin->Clearance = 0; | |
| for (i = 0; i < MAX_LAYER; i++) | |
| ASSIGN_THERM (i, GET_THERM (i, old), pin); | |
| } | |
| } | |
| END_LOOP; | |
| } | |
| } | |
| END_LOOP; | |
| PAD_LOOP (Element) | |
| { | |
| PadType *old = pad; | |
| if (old->Number) | |
| { | |
| PAD_LOOP (paste_element) | |
| { | |
| if (pad->Number && !strcmp (pad->Number, old->Number)) | |
| { | |
| if (!old->Clearance) | |
| pad->Clearance = 0; | |
| for (i = 0; i < MAX_LAYER; i++) | |
| ASSIGN_THERM (i, GET_THERM (i, old), pad); | |
| } | |
| } | |
| END_LOOP; | |
| } | |
| } | |
| END_LOOP; | |
| RemoveElement(Element); | |
| paste_element->Flags = flags; | |
| old = ChangeElementText(PCB, PCB->Data, paste_element, NAMEONPCB_INDEX, | |
| refdes); | |
| if (old) | |
| free(old); | |
| old = ChangeElementText(PCB, PCB->Data, paste_element, VALUE_INDEX, | |
| value); | |
| if (old) | |
| free(old); | |
| if (new_footprint) | |
| { | |
| old = ChangeElementText(PCB, PCB->Data, paste_element, DESCRIPTION_INDEX, | |
| strdup (new_footprint)); | |
| if (old) | |
| free(old); | |
| } | |
| SaveUndoSerialNumber (); | |
| paste_rotation = _ElementOrientation (paste_element); | |
| new_rotation = (paste_rotation - element_rotation) & 3; | |
| RotateElementLowLevel (PCB->Data, paste_element, paste_element->MarkX, | |
| paste_element->MarkY, new_rotation); | |
| ELEMENTTEXT_LOOP (paste_element); | |
| { | |
| BYTE rot; | |
| if (PCB->Data->name_tree[n]) | |
| r_delete_entry (PCB->Data->name_tree[n], (BoxType *)text); | |
| MOVE_TEXT_LOWLEVEL (text, text_x - text->X, text_y - text->Y); | |
| text->Scale = scale; | |
| rot = text_rotation - text->Direction + 4; | |
| RotateTextLowLevel (text, text->X, text->Y, rot & 3); | |
| if (PCB->Data->name_tree[n]) | |
| r_insert_entry (PCB->Data->name_tree[n], (BoxType *)text, 0); | |
| } | |
| END_LOOP; | |
| RestoreUndoSerialNumber (); | |
| AddObjectToCreateUndoList (ELEMENT_TYPE, paste_element, paste_element, | |
| paste_element); | |
| if (PCB->ElementOn && (FRONT (paste_element) || PCB->InvisibleObjectsOn)) | |
| { | |
| DrawElementName (paste_element); | |
| DrawElementPackage (paste_element); | |
| } | |
| if (PCB->PinOn) | |
| { | |
| DrawElementPinsAndPads (paste_element); | |
| } | |
| return NULL; | |
| } | |
| static ObjectFunctionType ReplaceFunctions = { | |
| NULL, | |
| NULL, | |
| NULL, | |
| NULL, | |
| ReplaceElement, | |
| NULL, | |
| NULL, | |
| NULL, | |
| NULL, | |
| NULL, | |
| NULL, | |
| NULL, | |
| }; | |
| static int | |
| replace (int argc, char **argv, Coord x, Coord y) | |
| { | |
| new_footprint = NULL; | |
| if (argc > 0) | |
| { | |
| new_footprint = argv[0]; | |
| } | |
| if (SelectedOperation (&ReplaceFunctions, true, ELEMENT_TYPE)) | |
| { | |
| IncrementUndoSerialNumber (); | |
| Draw (); | |
| } | |
| else | |
| { | |
| } | |
| return 0; | |
| } | |
| static HID_Action replace_action_list[] = { | |
| {"ReplaceSelected", NULL, replace, | |
| NULL, NULL} | |
| }; | |
| REGISTER_ACTIONS (replace_action_list) | |
| void | |
| pcb_plugin_init() | |
| { | |
| register_replace_action_list(); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment