#usage "Copy Wire (Polygon Wire) to any layer

" "This ULP copies copper wire and/or polygon from layer (1 or 16) of selected signals into " "the solderstop layers or any layer in order to keep it free from solder stop layer.

" "Use:
" "run copy-wire-to-solder-mask.ulp [signalname] [signalname]
" "run copy-wire-to-solder-mask.ulp $nameoff$
" "run copy-wire-to-solder-mask.ulp -p [signalname] [signalname]
" "run copy-wire-to-solder-mask.ulp +p [signalname] [signalname]
" "run copy-wire-to-solder-mask.ulp -p -f [signalname] [signalname]
" "run copy-wire-to-solder-mask.ulp +p +f [signalname] [signalname]
" "$nameoff$ switches off the checking of net names

" "Options are case sensitive.
" "$nameoff$ copy all signals.
" "-p copies also polygons.
" "+p copies only polygons.
" "-f copies only polygon contour as polygon.
" "-f copies polygon contour and filling as wire.
" "
" "Author: support@cadsoft.de" // THIS PROGRAM IS PROVIDED AS IS AND WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED. string Version = "ULP-Version: 1.5"; // 2008-04-23 check is a polygon placed // changed menu to copy to any layer // 2009-01-28 check polygon filling on orphan alf@cadsoft.de // 2009-04-23 check menu parameter // 2009-06-30 correct polygon export int NameOff = 0; // 0 = copy by signal name // 1 = copy without signal name (all) int PolygonOn = 0; // copy also polygon int onlyPolygon = 0; int fillPolygon = 0; // copy only polygon contour or copy polygon filling as wire 2006.01.20 alf int Player[]; string poly[]; int cntp = 0; string isRatsnest; string isLayer = "Top/Bottom"; // default layer int isLayerNb = 0; string toLayer = "t/bStop"; // default do Stop-Layer int Lused[]; // 2009-04-23 string signals[] = { "" }; string chsignals[] = { "" }; int chngsig = 0; int lastSigCh = -1; int decs; int index[]; int x1[], y1[], x2[], y2[], layer[]; int Wwidth[]; int n = 1; string cmd; string c; int nbIslayer; int nbTolayer; int test = 0; // 2009-06-30 for test menu // ************************************* string check(void) { // 2009-04-23 alf@cadsoft.de int isLfound = 0; int toLfound = 0; nbIslayer = strtol(isLayer); nbTolayer = strtol(toLayer); if (isLayer == "Top/Bottom") isLfound = -1; else { board(B) B.layers(L) { if (nbIslayer == L.number || isLayer == L.name) { isLfound = L.number; nbIslayer = L.number; break; } } } if (toLayer == "t/bStop") toLfound = -1; else { board(B) B.layers(L) { if (nbTolayer == L.number || toLayer == L.name) { toLfound = L.number; nbTolayer = L.number; break; } } } if (isLfound == -1); else if (!isLfound) return "!Select a available layer number or name for Copy layer."; else if (!Lused[isLfound]) return "!Not used layer Copy layer " + isLayer + "."; if (toLfound == -1); else if (!toLfound) return "!Select a available layer number or name for to layer."; else if (!Lused[toLfound]) return "!Not used layer to layer " + toLayer + "."; if (!NameOff && lastSigCh < 0 ) { return "!No signal selected"; } return ""; } int found(string fnam) { int fnd = 0; do { if (chsignals[fnd] == fnam) { return 1; break; } ++fnd; } while (chsignals[fnd]); return 0; } void changeLayer(int l) { if (toLayer == "t/bStop") { if (l == 1) sprintf(c, "CHANGE LAYER 29;\n"); if (l == 16) sprintf(c, "CHANGE LAYER 30;\n"); cmd+= c; } if (isLayer == "Top/Bottom") { // 2009-06-30 if (l == 1) { sprintf(c, "CHANGE LAYER 29;\n"); cmd+= c; } if (l == 16) { sprintf(c, "CHANGE LAYER 30;\n"); cmd+= c; } } else if (l == isLayerNb) { sprintf(c, "CHANGE LAYER %s;\n", toLayer); // 2009-04-23 cmd+= c; } return; } int delfromList(int selct) { if (lastSigCh >= 0) { lastSigCh--; for (int r = selct; r <= lastSigCh; r++) { chsignals[r] = chsignals[r + 1]; } chsignals[lastSigCh + 1] = ""; } return selct; } void AddList(string SigName) { int nofound = 1; for (int r = 0; r <= lastSigCh; r++) { if (chsignals[r] == SigName) { nofound = 0; break; } } if (nofound) { lastSigCh++; if (lastSigCh > 0) { for (int x = lastSigCh; x > 0; x--) { chsignals[x] = chsignals[x - 1]; } } chsignals[0] = SigName; } return; } void AddArgument(int n) { do { AddList(strupr(argv[n])); n++; } while(argv[n]); return; } void menue() { if (argc > 1) { if (argv[1] == "-p" || argv[1] == "+p" || argv[1] == "$nameoff$") { if (argv[1] == "-p") PolygonOn = 1; if (argv[1] == "+p") onlyPolygon = 1; if (argv[2] == "-f") fillPolygon = 0; // 2006.01.20 alf if (argv[2] == "+f") fillPolygon = 1; if (argv[1] == "$nameoff$") { NameOff = 1; AddArgument(2); } else if (argv[2] == "$nameoff$") { NameOff = 1; AddArgument(3); } else AddArgument(2); if (argv[2] == "$nameoff$") { NameOff = 1; AddArgument(3); } else if (argv[3] == "$nameoff$") { NameOff = 1; AddArgument(4); } else AddArgument(3); } else AddArgument(1); } else { string slist[]; int Result = dlgDialog("Copy wire to layer") { dlgLabel(Version); dlgHBoxLayout dlgSpacing(250); dlgCheckBox("Copy &all (without signal name)", NameOff); dlgSpacing(10); dlgStretch(0); dlgLabel("Add &signal to list"); dlgComboBox(signals, chngsig) { AddList(signals[chngsig]); dlgRedisplay();} dlgSpacing(30); dlgLabel("&Delete signal from list"); dlgComboBox(chsignals, decs) decs = delfromList(decs); dlgGroup("Polygon") { dlgCheckBox("Copy &polygon with signal name", PolygonOn); dlgCheckBox("Copy &only polygons", onlyPolygon); dlgHBoxLayout { dlgRadioButton("Copy only &contour", fillPolygon); dlgRadioButton("Copy with &filling", fillPolygon); } } dlgHBoxLayout { dlgLabel("Copy &layer "); dlgStringEdit(isLayer); dlgLabel(" &to layer "); dlgStringEdit(toLayer); dlgStretch(1); } dlgHBoxLayout { dlgPushButton("+OK") { string error = check(); // 2009-04-23 alf@cadsoft.de if(error) dlgMessageBox(error); else dlgAccept(); } dlgPushButton("-Cancel") dlgReject(); dlgStretch(1); dlgPushButton("&Help") dlgMessageBox(usage, "OK"); } dlgStretch(0); }; if (Result == 0) exit (0); } isLayerNb = nbIslayer; // 2009-04-23 return; } // main if (board) board(B) { B.layers(L) Lused[L.number] = L.used; isRatsnest = "! Start RATSNEST first!"; int cntPoly = 0; B.signals(S) { S.polygons(P) { cntPoly++; P.fillings(F) { // check if run RATSNEST isRatsnest = ""; break; } if (isRatsnest) { // check a orphan 2009-01-28 alf@cadsoft.de P.wires(W) { sprintf(isRatsnest, "Start RATSNEST and check polygon on (%.4f %.4f) mm!", u2mm(W.x1), u2mm(W.y1) ); dlgMessageBox(isRatsnest, "OK"); sprintf(isRatsnest, "GRID MM;\nWIN (%.4f %.4f);\nGRID LAST;\n", u2mm(W.x1), u2mm(W.y1) ); exit(isRatsnest); } } } } if (cntPoly) { if (isRatsnest) { dlgMessageBox(isRatsnest, "OK"); exit(0); } } int s = 0; B.signals(S) { signals[s] = S.name; s++; } menue(); sprintf(c, "GRID MM;\nSET WIRE_BEND 2;\nSET UNDO OFF;\n"); cmd+= c; B.signals(S) { if (found(S.name) || NameOff || onlyPolygon) { if (!onlyPolygon) { S.wires(W) { if ((isLayer == "Top/Bottom" && (W.layer == 1 || W.layer == 16)) || isLayerNb == W.layer) { // 2009-04-23 alf x1[n] = W.x1; y1[n] = W.y1; x2[n] = W.x2; y2[n] = W.y2; Wwidth[n] = W.width; layer[n] = W.layer; ++n; } } } if ( (PolygonOn && NameOff) || (onlyPolygon && !NameOff && found(S.name)) || (PolygonOn && !NameOff && found(S.name)) ) { S.polygons(POL) { if (isLayer && (POL.layer == 1 || POL.layer == 16) || isLayerNb == POL.layer) { // 2009-06-30 alf string p; int startx, starty; int first = 1; Player[cntp] = POL.layer; POL.contours(W) { if (first) { first = 0; startx = W.x1; starty = W.y1; sprintf(poly[cntp], "WIRE %.4f (%.4f %.4f) (%.4f %.4f)", // 2009-06-30 u2mm(W.width), u2mm(W.x1), u2mm(W.y1), u2mm(W.x2), u2mm(W.y2) ); } else { sprintf(p, " (%.4f %.4f)", u2mm(W.x2), u2mm(W.y2) ); poly[cntp] += p; if (startx == W.x2 && starty == W.y2) { sprintf(p, " (%.4f %.4f);\n", u2mm(startx), u2mm(starty) ); poly[cntp] += p; cntp++; break; } } } if (fillPolygon) { // Polygon filling with wire 2009-06-30 POL.fillings(W) { x1[n] = W.x1; y1[n] = W.y1; x2[n] = W.x2; y2[n] = W.y2; Wwidth[n] = W.width; layer[n] = W.layer; ++n; } } } } } } } sort(n, index, layer); int dl = 0; for (int i = 1; i < n; i++) { if(dl != layer[index[i]]) { dl = layer[index[i]]; changeLayer(dl); } sprintf(c, "WIRE %.4f (%.4f %.4f) (%.4f %.4f);\n", u2mm(Wwidth[index[i]]), u2mm(x1[index[i]]), u2mm(y1[index[i]]), u2mm(x2[index[i]]), u2mm(y2[index[i]]) ); cmd+= c; } sort(cntp, index, Player); for ( i = 0; i < cntp; ++i) { if(dl != Player[index[i]]) { dl = Player[index[i]]; changeLayer(dl); } sprintf(c, "WIRE %.4f (%.4f %.4f) (%.4f %.4f);\n", u2mm(Wwidth[index[i]]), u2mm(x1[index[i]]), u2mm(y1[index[i]]), u2mm(x2[index[i]]), u2mm(y2[index[i]]) ); cmd+= poly[index[i]]; } sprintf(c, "SET UNDO ON;\nGRID LAST;\n"); cmd+= c; if (test) { // 2009-06-30 dlgDialog("test") { dlgTextEdit(cmd); dlgHBoxLayout { dlgPushButton("OK") dlgAccept(); dlgPushButton("Cancel") { dlgReject(); exit(-9); } } }; } exit (cmd); } else dlgMessageBox("! Start this ULP in a Board", "OK");