1 /*!
2 * \file src/flags.c
3 *
4 * \brief .
5 *
6 * <hr>
7 *
8 * <h1><b>Copyright.</b></h1>\n
9 *
10 * PCB, interactive printed circuit board design
11 *
12 * Copyright (C) 2005 DJ Delorie
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 */
28
29
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33
34 #include <math.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #ifdef HAVE_STRING_H
38 #include <string.h>
39 #endif
40
41 #include "global.h"
42 #include "data.h"
43 #include "draw.h"
44 #include "pcb-printf.h"
45 #include "search.h"
46 #include "set.h" /* SetChangedFlag */
47 #include "strflags.h"
48 #include "undo.h"
49
50 #include <glib.h>
51
52 #ifdef HAVE_LIBDMALLOC
53 #include <dmalloc.h>
54 #endif
55
56 int pcb_flag_eq (FlagType *f1, FlagType *f2);
57
58 /*!
59 * \brief .
60 *
61 * \warning ignore unknowns for now: the only place where we use this
62 * function, undo.c, won't care.
63 */
64 int
pcb_flag_eq(FlagType * f1,FlagType * f2)65 pcb_flag_eq (FlagType *f1, FlagType *f2)
66 {
67 if (f1->f != f2->f)
68 return 0;
69
70 return (memcmp(f1->t, &f2->t, sizeof(f1->t)) == 0);
71 }
72
73 static int
FlagCurrentStyle(void * data)74 FlagCurrentStyle (void *data)
75 {
76 STYLE_LOOP (PCB);
77 {
78 if (style->Thick == Settings.LineThickness &&
79 style->Diameter == Settings.ViaThickness &&
80 style->Hole == Settings.ViaDrillingHole &&
81 style->Keepaway == Settings.Keepaway)
82 return n + 1;
83 }
84 END_LOOP;
85 return 0;
86 }
87
88 static int
FlagGrid(void * data)89 FlagGrid (void *data)
90 {
91 return PCB->Grid > 1;
92 }
93
94 static int
FlagGridSize(void * data)95 FlagGridSize (void *data)
96 {
97 return PCB->Grid;
98 }
99
100 static int
FlagUnitsMm(void * data)101 FlagUnitsMm (void *data)
102 {
103 static const Unit *u = NULL;
104 if (u == NULL)
105 u = get_unit_struct ("mm");
106 return (Settings.grid_unit == u);
107 }
108
109 static int
FlagUnitsMil(void * data)110 FlagUnitsMil (void *data)
111 {
112 static const Unit *u = NULL;
113 if (u == NULL)
114 u = get_unit_struct ("mil");
115 return (Settings.grid_unit == u);
116 }
117
118 static int
FlagBuffer(void * data)119 FlagBuffer (void *data)
120 {
121 return (int) (Settings.BufferNumber + 1);
122 }
123
124 static int
FlagElementName(void * data)125 FlagElementName (void *data)
126 {
127 if (TEST_FLAG (NAMEONPCBFLAG, PCB))
128 return 2;
129 if (TEST_FLAG (DESCRIPTIONFLAG, PCB))
130 return 1;
131 return 3;
132 }
133
134 static int
FlagTESTFLAG(void * data)135 FlagTESTFLAG (void *data)
136 {
137 int bit = GPOINTER_TO_INT (data);
138 return TEST_FLAG (bit, PCB) ? 1 : 0;
139 }
140
141 static int
FlagSETTINGS(void * data)142 FlagSETTINGS (void *data)
143 {
144 size_t ofs = (size_t)data;
145 return *(bool *) ((char *)(&Settings) + ofs);
146 }
147
148 static int
FlagMode(void * data)149 FlagMode (void *data)
150 {
151 int x = GPOINTER_TO_INT (data);
152 if (x == -1)
153 return Settings.Mode;
154 return Settings.Mode == x;
155 }
156
157 static int
FlagHaveRegex(void * data)158 FlagHaveRegex (void *data)
159 {
160 #if defined(HAVE_REGCOMP) || defined(HAVE_RE_COMP)
161 return 1;
162 #else
163 return 0;
164 #endif
165 }
166
167 enum {
168 FL_SILK = -6,
169 FL_PINS,
170 FL_RATS,
171 FL_VIAS,
172 FL_BACK,
173 FL_MASK
174 };
175
176 static int
FlagLayerShown(void * data)177 FlagLayerShown (void *data)
178 {
179 int n = GPOINTER_TO_INT (data);
180 switch (n)
181 {
182 case FL_SILK:
183 return PCB->ElementOn;
184 case FL_PINS:
185 return PCB->PinOn;
186 case FL_RATS:
187 return PCB->RatOn;
188 case FL_VIAS:
189 return PCB->ViaOn;
190 case FL_BACK:
191 return PCB->InvisibleObjectsOn;
192 case FL_MASK:
193 return TEST_FLAG (SHOWMASKFLAG, PCB);
194 default:
195 if (n >= 0 && n < max_copper_layer)
196 return PCB->Data->Layer[n].On;
197 }
198 return 0;
199 }
200
201 static int
FlagLayerActive(void * data)202 FlagLayerActive (void *data)
203 {
204 int test_layer = GPOINTER_TO_INT (data);
205 int current_layer;
206 if (PCB->RatDraw)
207 current_layer = FL_RATS;
208 else if (PCB->SilkActive)
209 current_layer = FL_SILK;
210 else
211 return 0;
212
213 return current_layer == test_layer;
214 }
215
216 int
mem_any_set(unsigned char * ptr,int bytes)217 mem_any_set (unsigned char *ptr, int bytes)
218 {
219 while (bytes--)
220 if (*ptr++)
221 return 1;
222 return 0;
223 }
224
225 /*!
226 * \brief This just fills in a FlagType with current flags.
227 */
228 FlagType
MakeFlags(unsigned int flags)229 MakeFlags (unsigned int flags)
230 {
231 FlagType rv;
232 memset (&rv, 0, sizeof (rv));
233 rv.f = flags;
234 return rv;
235 }
236
237 /*!
238 * \brief This converts old flag bits (from saved PCB files) to new
239 * format.
240 */
241 FlagType
OldFlags(unsigned int flags)242 OldFlags (unsigned int flags)
243 {
244 FlagType rv;
245 int i, f;
246 memset (&rv, 0, sizeof (rv));
247 /* If we move flag bits around, this is where we map old bits to them. */
248 rv.f = flags & 0xffff;
249 f = 0x10000;
250 for (i = 0; i < 8; i++)
251 {
252 /* use the closest thing to the old thermal style */
253 if (flags & f)
254 rv.t[i / 2] |= (1 << (4 * (i % 2)));
255 f <<= 1;
256 }
257 return rv;
258 }
259
260 FlagType
AddFlags(FlagType flag,unsigned int flags)261 AddFlags (FlagType flag, unsigned int flags)
262 {
263 flag.f |= flags;
264 return flag;
265 }
266
267 FlagType
MaskFlags(FlagType flag,unsigned int flags)268 MaskFlags (FlagType flag, unsigned int flags)
269 {
270 flag.f &= ~flags;
271 return flag;
272 }
273
274 /*!
275 * \brief Resets all used flags of pins and vias.
276 */
277 bool
ClearFlagOnPinsViasAndPads(int flag,bool undoable)278 ClearFlagOnPinsViasAndPads (int flag, bool undoable)
279 {
280 bool change = false;
281
282 VIA_LOOP (PCB->Data);
283 {
284 if (TEST_FLAG (flag, via))
285 {
286 if (undoable)
287 AddObjectToFlagUndoList (VIA_TYPE, via, via, via);
288 CLEAR_FLAG (flag, via);
289 change = true;
290 }
291 }
292 END_LOOP;
293 ELEMENT_LOOP (PCB->Data);
294 {
295 PIN_LOOP (element);
296 {
297 if (TEST_FLAG (flag, pin))
298 {
299 if (undoable)
300 AddObjectToFlagUndoList (PIN_TYPE, element, pin, pin);
301 CLEAR_FLAG (flag, pin);
302 change = true;
303 }
304 }
305 END_LOOP;
306 PAD_LOOP (element);
307 {
308 if (TEST_FLAG (flag, pad))
309 {
310 if (undoable)
311 AddObjectToFlagUndoList (PAD_TYPE, element, pad, pad);
312 CLEAR_FLAG (flag, pad);
313 change = true;
314 }
315 }
316 END_LOOP;
317 }
318 END_LOOP;
319 if (change)
320 SetChangedFlag (true);
321 return change;
322 }
323
324 /*!
325 * \brief Resets all used flags of LOs.
326 */
327 bool
ClearFlagOnLinesAndPolygons(int flag,bool undoable)328 ClearFlagOnLinesAndPolygons (int flag, bool undoable)
329 {
330 bool change = false;
331
332 RAT_LOOP (PCB->Data);
333 {
334 if (TEST_FLAG (flag, line))
335 {
336 if (undoable)
337 AddObjectToFlagUndoList (RATLINE_TYPE, line, line, line);
338 CLEAR_FLAG (flag, line);
339 change = true;
340 }
341 }
342 END_LOOP;
343 COPPERLINE_LOOP (PCB->Data);
344 {
345 if (TEST_FLAG (flag, line))
346 {
347 if (undoable)
348 AddObjectToFlagUndoList (LINE_TYPE, layer, line, line);
349 CLEAR_FLAG (flag, line);
350 change = true;
351 }
352 }
353 ENDALL_LOOP;
354 COPPERARC_LOOP (PCB->Data);
355 {
356 if (TEST_FLAG (flag, arc))
357 {
358 if (undoable)
359 AddObjectToFlagUndoList (ARC_TYPE, layer, arc, arc);
360 CLEAR_FLAG (flag, arc);
361 change = true;
362 }
363 }
364 ENDALL_LOOP;
365 COPPERPOLYGON_LOOP (PCB->Data);
366 {
367 if (TEST_FLAG (flag, polygon))
368 {
369 if (undoable)
370 AddObjectToFlagUndoList (POLYGON_TYPE, layer, polygon, polygon);
371 CLEAR_FLAG (flag, polygon);
372 change = true;
373 }
374 }
375 ENDALL_LOOP;
376 if (change)
377 SetChangedFlag (true);
378 return change;
379 }
380
381 /*!
382 * \brief Resets all found connections.
383 */
384 bool
ClearFlagOnAllObjects(int flag,bool undoable)385 ClearFlagOnAllObjects (int flag, bool undoable)
386 {
387 bool change = false;
388
389 change = ClearFlagOnPinsViasAndPads (flag, undoable) || change;
390 change = ClearFlagOnLinesAndPolygons (flag, undoable) || change;
391
392 return change;
393 }
394
395 static const char dump_flags_syntax[] = ("DumpFlags([Output file])");
396 static const char dump_flags_help[] = ("Write out a list of objects and their flags.");
397
398 static int
ActionDumpFlags(int argc,char ** argv,Coord x,Coord y)399 ActionDumpFlags(int argc, char **argv, Coord x, Coord y)
400 {
401 int i = -1;
402 bool found_something = false;
403 int type = 0;
404 FILE * fp;
405 void *p1, *p2, *p3, *p;
406
407 if (argc == 1) fp = fopen(argv[0], "w");
408 else fp = stdout;
409
410 while (1){
411 i++;
412 type = SearchObjectByID(PCB->Data, &p1, &p2, &p3, i, ALL_TYPES);
413 if (type == NO_TYPE){
414 /* There's a gap in the ID numbers at the beginning */
415 if (found_something) break;
416 else continue;
417 }
418 found_something = true;
419 /* Points don't use flags (I don't think) */
420 if (type & (LINEPOINT_TYPE | POLYGONPOINT_TYPE)) continue; /*p = p3;*/
421 else if (type && (LINE_TYPE | ARC_TYPE | TEXT_TYPE | POLYGON_TYPE | ELEMENTLINE_TYPE | ELEMENTARC_TYPE | ELEMENTNAME_TYPE | PIN_TYPE | PAD_TYPE)) p = p2;
422 else p = p1;
423
424 fprintf(fp, "%4d %3d %s\n", i, type,
425 flags_to_string(((AnyObjectType*)p)->Flags, type));
426 }
427
428 fclose(fp);
429 return 0;
430 }
431
432 HID_Action flag_action_list[] = {
433 {"DumpFlags", 0, ActionDumpFlags, dump_flags_help, dump_flags_syntax}
434 };
435
436 REGISTER_ACTIONS (flag_action_list)
437
438
439 #define OFFSET_POINTER(a, b) (&(((a *)0)->b))
440
441 HID_Flag flags_flag_list[] = {
442 {"style", FlagCurrentStyle, NULL},
443 {"grid", FlagGrid, NULL},
444 {"gridsize", FlagGridSize, NULL},
445 {"elementname", FlagElementName, NULL},
446 {"have_regex", FlagHaveRegex, NULL},
447
448 {"silk_shown", FlagLayerShown, GINT_TO_POINTER (FL_SILK)},
449 {"pins_shown", FlagLayerShown, GINT_TO_POINTER (FL_PINS)},
450 {"rats_shown", FlagLayerShown, GINT_TO_POINTER (FL_RATS)},
451 {"vias_shown", FlagLayerShown, GINT_TO_POINTER (FL_VIAS)},
452 {"back_shown", FlagLayerShown, GINT_TO_POINTER (FL_BACK)},
453 {"mask_shown", FlagLayerShown, GINT_TO_POINTER (FL_MASK)},
454
455 {"silk_active", FlagLayerActive, GINT_TO_POINTER (FL_SILK)},
456 {"rats_active", FlagLayerActive, GINT_TO_POINTER (FL_RATS)},
457
458 {"mode", FlagMode, GINT_TO_POINTER (-1)},
459 {"nomode", FlagMode, GINT_TO_POINTER (NO_MODE)},
460 {"arcmode", FlagMode, GINT_TO_POINTER (ARC_MODE)},
461 {"arrowmode", FlagMode, GINT_TO_POINTER (ARROW_MODE)},
462 {"copymode", FlagMode, GINT_TO_POINTER (COPY_MODE)},
463 {"insertpointmode", FlagMode, GINT_TO_POINTER (INSERTPOINT_MODE)},
464 {"linemode", FlagMode, GINT_TO_POINTER (LINE_MODE)},
465 {"lockmode", FlagMode, GINT_TO_POINTER (LOCK_MODE)},
466 {"movemode", FlagMode, GINT_TO_POINTER (MOVE_MODE)},
467 {"pastebuffermode", FlagMode, GINT_TO_POINTER (PASTEBUFFER_MODE)},
468 {"polygonmode", FlagMode, GINT_TO_POINTER (POLYGON_MODE)},
469 {"polygonholemode", FlagMode, GINT_TO_POINTER (POLYGONHOLE_MODE)},
470 {"rectanglemode", FlagMode, GINT_TO_POINTER (RECTANGLE_MODE)},
471 {"removemode", FlagMode, GINT_TO_POINTER (REMOVE_MODE)},
472 {"rotatemode", FlagMode, GINT_TO_POINTER (ROTATE_MODE)},
473 {"rubberbandmovemode", FlagMode, GINT_TO_POINTER (RUBBERBANDMOVE_MODE)},
474 {"textmode", FlagMode, GINT_TO_POINTER (TEXT_MODE)},
475 {"thermalmode", FlagMode, GINT_TO_POINTER (THERMAL_MODE)},
476 {"viamode", FlagMode, GINT_TO_POINTER (VIA_MODE)},
477
478 {"shownumber", FlagTESTFLAG, GINT_TO_POINTER (SHOWNUMBERFLAG)},
479 {"localref", FlagTESTFLAG, GINT_TO_POINTER (LOCALREFFLAG)},
480 {"checkplanes", FlagTESTFLAG, GINT_TO_POINTER (CHECKPLANESFLAG)},
481 {"showdrc", FlagTESTFLAG, GINT_TO_POINTER (SHOWDRCFLAG)},
482 {"rubberband", FlagTESTFLAG, GINT_TO_POINTER (RUBBERBANDFLAG)},
483 {"description", FlagTESTFLAG, GINT_TO_POINTER (DESCRIPTIONFLAG)},
484 {"nameonpcb", FlagTESTFLAG, GINT_TO_POINTER (NAMEONPCBFLAG)},
485 {"autodrc", FlagTESTFLAG, GINT_TO_POINTER (AUTODRCFLAG)},
486 {"alldirection", FlagTESTFLAG, GINT_TO_POINTER (ALLDIRECTIONFLAG)},
487 {"swapstartdir", FlagTESTFLAG, GINT_TO_POINTER (SWAPSTARTDIRFLAG)},
488 {"uniquename", FlagTESTFLAG, GINT_TO_POINTER (UNIQUENAMEFLAG)},
489 {"clearnew", FlagTESTFLAG, GINT_TO_POINTER (CLEARNEWFLAG)},
490 {"snappin", FlagTESTFLAG, GINT_TO_POINTER (SNAPPINFLAG)},
491 {"showmask", FlagTESTFLAG, GINT_TO_POINTER (SHOWMASKFLAG)},
492 {"thindraw", FlagTESTFLAG, GINT_TO_POINTER (THINDRAWFLAG)},
493 {"orthomove", FlagTESTFLAG, GINT_TO_POINTER (ORTHOMOVEFLAG)},
494 {"liveroute", FlagTESTFLAG, GINT_TO_POINTER (LIVEROUTEFLAG)},
495 {"thindrawpoly", FlagTESTFLAG, GINT_TO_POINTER (THINDRAWPOLYFLAG)},
496 {"locknames", FlagTESTFLAG, GINT_TO_POINTER (LOCKNAMESFLAG)},
497 {"onlynames", FlagTESTFLAG, GINT_TO_POINTER (ONLYNAMESFLAG)},
498 {"newfullpoly", FlagTESTFLAG, GINT_TO_POINTER (NEWFULLPOLYFLAG)},
499 {"hidenames", FlagTESTFLAG, GINT_TO_POINTER (HIDENAMESFLAG)},
500 {"autoburiedvias", FlagTESTFLAG, GINT_TO_POINTER (AUTOBURIEDVIASFLAG)},
501
502 {"grid_units_mm", FlagUnitsMm, NULL},
503 {"grid_units_mil", FlagUnitsMil, NULL},
504
505 {"fullpoly", FlagSETTINGS, OFFSET_POINTER (SettingType, FullPoly)},
506 {"clearline", FlagSETTINGS, OFFSET_POINTER (SettingType, ClearLine)},
507 {"uniquenames", FlagSETTINGS, OFFSET_POINTER (SettingType, UniqueNames)},
508 {"showsolderside", FlagSETTINGS, OFFSET_POINTER (SettingType, ShowBottomSide)},
509 {"savelastcommand", FlagSETTINGS, OFFSET_POINTER (SettingType, SaveLastCommand)},
510 {"saveintmp", FlagSETTINGS, OFFSET_POINTER (SettingType, SaveInTMP)},
511 {"drawgrid", FlagSETTINGS, OFFSET_POINTER (SettingType, DrawGrid)},
512 {"ratwarn", FlagSETTINGS, OFFSET_POINTER (SettingType, RatWarn)},
513 {"stipplepolygons", FlagSETTINGS, OFFSET_POINTER (SettingType, StipplePolygons)},
514 {"alldirectionlines", FlagSETTINGS, OFFSET_POINTER (SettingType, AllDirectionLines)},
515 {"rubberbandmode", FlagSETTINGS, OFFSET_POINTER (SettingType, RubberBandMode)},
516 {"swapstartdirection", FlagSETTINGS, OFFSET_POINTER (SettingType, SwapStartDirection)},
517 {"showdrcmode", FlagSETTINGS, OFFSET_POINTER (SettingType, ShowDRC)},
518 {"resetafterelement", FlagSETTINGS, OFFSET_POINTER (SettingType, ResetAfterElement)},
519 {"ringbellwhenfinished", FlagSETTINGS, OFFSET_POINTER (SettingType, RingBellWhenFinished)},
520
521 {"buffer", FlagBuffer, NULL},
522
523 };
524
525 REGISTER_FLAGS (flags_flag_list)
526
527