Introduce POLYGONHOLE_MODE for creating holes in polygons
[geda-pcb/gde.git] / src / macro.h
blob819d2021ffa94b83ee7584bf34902f7a44e51524
1 /*
2 * COPYRIGHT
4 * PCB, interactive printed circuit board design
5 * Copyright (C) 1994,1995,1996 Thomas Nau
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * Contact addresses for paper mail and Email:
22 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
23 * Thomas.Nau@rz.uni-ulm.de
25 * RCS: $Id$
28 /* some commonly used macros not related to a special C-file
29 * the file is included by global.h after const.h
32 #ifndef __MACRO_INCLUDED__
33 #define __MACRO_INCLUDED__
35 /* ---------------------------------------------------------------------------
36 * macros to transform coord systems
37 * draw.c uses a different definition of TO_SCREEN
39 #ifndef SWAP_IDENT
40 #define SWAP_IDENT Settings.ShowSolderSide
41 #endif
43 #ifndef XORIG
44 #define XORIG Xorig
45 #define YORIG Yorig
46 #endif
48 #define SWAP_SIGN_X(x) (x)
49 #define SWAP_SIGN_Y(y) (-(y))
50 #define SWAP_ANGLE(a) (-(a))
51 #define SWAP_DELTA(d) (-(d))
52 #define SWAP_X(x) (SWAP_SIGN_X(x))
53 #define SWAP_Y(y) (PCB->MaxHeight +SWAP_SIGN_Y(y))
54 #define SATURATE(x) ((x) > 32767 ? 32767 : ((x) < -32767 ? -32767 : (x)))
56 #define TO_DRAW_X(x) TO_SCREEN((SWAP_IDENT ? SWAP_X(x) : (x)) - XORIG)
57 #define TO_DRAWABS_X(x) (TO_SCREEN((x) - XORIG))
58 #define TO_DRAW_Y(y) TO_SCREEN((SWAP_IDENT ? SWAP_Y(y) : (y)) - YORIG)
59 #define TO_DRAWABS_Y(y) (TO_SCREEN((y) - YORIG))
60 #define TO_LIMIT_X(x) ((Position)(SATURATE(Local_Zoom * ((x) - XORIG))))
61 #define TO_LIMIT_Y(y) ((Position)(SATURATE(Local_Zoom * \
62 ((SWAP_IDENT ? SWAP_Y(y) : (y)) - YORIG))))
63 #define TO_SCREEN_ANGLE(a) (SWAP_IDENT ? SWAP_ANGLE((a)) : (a))
64 #define TO_SCREEN_DELTA(d) (SWAP_IDENT ? SWAP_DELTA((d)) : (d))
65 #define TO_SCREEN_SIGN_X(x) (SWAP_IDENT ? SWAP_SIGN_X(x) : (x))
66 #define TO_SCREEN_SIGN_Y(y) (SWAP_IDENT ? SWAP_SIGN_Y(y) : (y))
68 #ifndef TO_PCB
69 #define TO_PCB(x) ((LocationType)((x)/Zoom_Multiplier))
70 #endif
71 #define TO_PCB_X(x) TO_PCB(x) + Xorig
72 #define TO_PCB_Y(y) (SWAP_IDENT ? \
73 PCB->MaxHeight - TO_PCB(y) - Yorig : TO_PCB(y) + Yorig)
74 #ifdef __GNUC__
75 #pragma GCC poison TO_SCREEN TO_SCREEN_X TO_SCREEN_Y
76 #endif
78 /* ---------------------------------------------------------------------------
79 * misc macros, some might already be defined by <limits.h>
81 #ifndef MIN
82 #define MIN(a,b) ((a) < (b) ? (a) : (b))
83 #define MAX(a,b) ((a) > (b) ? (a) : (b))
84 #endif
85 #ifndef SGN
86 #define SGN(a) ((a) >0 ? 1 : ((a) == 0 ? 0 : -1))
87 #endif
88 #define SGNZ(a) ((a) >=0 ? 1 : -1)
89 #define MAKEMIN(a,b) if ((b) < (a)) (a) = (b)
90 #define MAKEMAX(a,b) if ((b) > (a)) (a) = (b)
92 #define ENTRIES(x) (sizeof((x))/sizeof((x)[0]))
93 #define UNKNOWN(a) ((a) && *(a) ? (a) : "(unknown)")
94 #define NSTRCMP(a, b) ((a) ? ((b) ? strcmp((a),(b)) : 1) : -1)
95 #define EMPTY(a) ((a) ? (a) : "")
96 #define EMPTY_STRING_P(a) ((a) ? (a)[0]==0 : 1)
97 #define XOR(a,b) (((a) && !(b)) || (!(a) && (b)))
98 #define SQUARE(x) ((float) (x) * (float) (x))
99 #define TO_RADIANS(degrees) (M180 * (degrees))
101 /* ---------------------------------------------------------------------------
102 * macros to determine if something is on the visible part of the screen
105 #define VELEMENT(e) ((e)->BoundingBox.X1 <= vxh && \
106 (e)->BoundingBox.X2 >= vxl && \
107 (e)->BoundingBox.Y1 <= vyh && \
108 (e)->BoundingBox.Y2 >= vyl)
109 #define VELTEXT(e) (ELEMENT_TEXT(PCB,(e)).BoundingBox.X1 <= vxh && \
110 ELEMENT_TEXT(PCB,(e)).BoundingBox.X2 >= vxl && \
111 ELEMENT_TEXT(PCB,(e)).BoundingBox.Y1 <= vyh && \
112 ELEMENT_TEXT(PCB,(e)).BoundingBox.Y2 >= vyl)
113 #define VTEXT(t) ((t)->BoundingBox.X1 <= vxh && \
114 (t)->BoundingBox.X2 >= vxl && \
115 (t)->BoundingBox.Y1 <= vyh && \
116 (t)->BoundingBox.Y2 >= vyl)
117 #define VLINE(l) ((((l)->Point2.X >= vxl - (l)->Thickness && \
118 (l)->Point1.X <= vxh + (l)->Thickness) || \
119 ((l)->Point1.X >= vxl - (l)->Thickness && \
120 (l)->Point2.X <= vxh + (l)->Thickness)) && \
121 ((((l)->Point2.Y >= vyl - (l)->Thickness && \
122 (l)->Point1.Y <= vyh + (l)->Thickness) || \
123 ((l)->Point1.Y >= vyl - (l)->Thickness && \
124 (l)->Point2.Y <= vyh + (l)->Thickness))))
125 #define VARC(a) ((a)->BoundingBox.X1 <= vxh && \
126 (a)->BoundingBox.X2 >= vxl && \
127 (a)->BoundingBox.Y1 <= vyh && \
128 (a)->BoundingBox.Y2 >= vyl)
129 #define VPOLY(p) (IsRectangleInPolygon(vxl, vyl, vxh, vyh, (p)))
130 /* (p)->BoundingBox.X1 <= vxh && \
131 (p)->BoundingBox.X2 >= vxl && \
132 (p)->BoundingBox.Y1 <= vyh && \
133 (p)->BoundingBox.Y2 >= vyl)
135 #define VVIA(v) ((v)->X+(v)->Thickness >= vxl && (v)->X - (v)->Thickness <= vxh && \
136 (v)->Y+(v)->Thickness >= vyl && (v)->Y - (v)->Thickness <= vyh)
137 #define VTHERM(v) ((v)->X + (v)->Thickness + (v)->Clearance >= vxl && \
138 (v)->X - (v)->Thickness - (v)->Clearance <= vxh && \
139 (v)->Y + (v)->Thickness + (v)->Thickness >= vyl && \
140 (v)->Y - (v)->Thickness - (v)->Clearance <= vyh)
142 #undef VELEMENT
143 #define VELEMENT(e) 1
144 #undef VELTEXT
145 #define VELTEXT(e) 1
146 #undef VTEXT
147 #define VTEXT(e) 1
148 #undef VLINE
149 #define VLINE(e) 1
150 #undef VARC
151 #define VARC(e) 1
152 #undef VPOLY
153 #define VPOLY(e) 1
154 #undef VVIA
155 #define VVIA(e) 1
156 #undef VTHERM
157 #define VTHERM(e) 1
159 /* ---------------------------------------------------------------------------
160 * layer macros
162 #define LAYER_ON_STACK(n) (&PCB->Data->Layer[LayerStack[(n)]])
163 #define LAYER_PTR(n) (&PCB->Data->Layer[(n)])
164 #define CURRENT (PCB->SilkActive ? &PCB->Data->Layer[max_layer + \
165 (Settings.ShowSolderSide ? SOLDER_LAYER : COMPONENT_LAYER)] \
166 : LAYER_ON_STACK(0))
167 #define INDEXOFCURRENT (PCB->SilkActive ? max_layer + \
168 (Settings.ShowSolderSide ? SOLDER_LAYER : COMPONENT_LAYER) \
169 : LayerStack[0])
170 #define SILKLAYER Layer[max_layer + \
171 (Settings.ShowSolderSide ? SOLDER_LAYER : COMPONENT_LAYER)]
172 #define BACKSILKLAYER Layer[max_layer + \
173 (Settings.ShowSolderSide ? COMPONENT_LAYER : SOLDER_LAYER)]
175 #define TEST_SILK_LAYER(layer) (GetLayerNumber (PCB->Data, layer) >= max_layer)
178 /* ---------------------------------------------------------------------------
179 * returns the object ID
181 #define OBJECT_ID(p) (((AnyObjectTypePtr) p)->ID)
183 /* ---------------------------------------------------------------------------
184 * access macro for current buffer
186 #define PASTEBUFFER (&Buffers[Settings.BufferNumber])
188 /* ---------------------------------------------------------------------------
189 * some routines for flag setting, clearing, changing and testing
191 #define SET_FLAG(F,P) ((P)->Flags.f |= (F))
192 #define CLEAR_FLAG(F,P) ((P)->Flags.f &= (~(F)))
193 #define TEST_FLAG(F,P) ((P)->Flags.f & (F) ? 1 : 0)
194 #define TOGGLE_FLAG(F,P) ((P)->Flags.f ^= (F))
195 #define ASSIGN_FLAG(F,V,P) ((P)->Flags.f = ((P)->Flags.f & (~(F))) | ((V) ? (F) : 0))
196 #define TEST_FLAGS(F,P) (((P)->Flags.f & (F)) == (F) ? 1 : 0)
198 #define FLAGS_EQUAL(F1,F2) (memcmp (&F1, &F2, sizeof(FlagType)) == 0)
200 #define THERMFLAG(L) (0xf << (4 *((L) % 2)))
202 #define TEST_THERM(L,P) ((P)->Flags.t[(L)/2] & THERMFLAG(L) ? 1 : 0)
203 #define GET_THERM(L,P) (((P)->Flags.t[(L)/2] >> (4 * ((L) % 2))) & 0xf)
204 #define CLEAR_THERM(L,P) (P)->Flags.t[(L)/2] &= ~THERMFLAG(L)
205 #define ASSIGN_THERM(L,V,P) (P)->Flags.t[(L)/2] = ((P)->Flags.t[(L)/2] & ~THERMFLAG(L)) | ((V) << (4 * ((L) % 2)))
207 extern int mem_any_set (unsigned char *, int);
208 #define TEST_ANY_THERMS(P) mem_any_set((P)->Flags.t, sizeof((P)->Flags.t))
210 /* ---------------------------------------------------------------------------
211 * access macros for elements name structure
213 #define DESCRIPTION_INDEX 0
214 #define NAMEONPCB_INDEX 1
215 #define VALUE_INDEX 2
216 #define NAME_INDEX(p) (TEST_FLAG(NAMEONPCBFLAG,(p)) ? NAMEONPCB_INDEX :\
217 (TEST_FLAG(DESCRIPTIONFLAG, (p)) ? \
218 DESCRIPTION_INDEX : VALUE_INDEX))
219 #define ELEMENT_NAME(p,e) ((e)->Name[NAME_INDEX((p))].TextString)
220 #define DESCRIPTION_NAME(e) ((e)->Name[DESCRIPTION_INDEX].TextString)
221 #define NAMEONPCB_NAME(e) ((e)->Name[NAMEONPCB_INDEX].TextString)
222 #define VALUE_NAME(e) ((e)->Name[VALUE_INDEX].TextString)
223 #define ELEMENT_TEXT(p,e) ((e)->Name[NAME_INDEX((p))])
224 #define DESCRIPTION_TEXT(e) ((e)->Name[DESCRIPTION_INDEX])
225 #define NAMEONPCB_TEXT(e) ((e)->Name[NAMEONPCB_INDEX])
226 #define VALUE_TEXT(e) ((e)->Name[VALUE_INDEX])
228 /* ----------------------------------------------------------------------
229 * checks for correct X values
231 #define VALID_PIXMAP(p) ((p) != BadValue && \
232 (p) != BadAlloc && \
233 (p) != BadDrawable)
235 #define VALID_GC(p) ((p) != BadValue && \
236 (p) != BadAlloc && \
237 (p) != BadDrawable && \
238 (p) != BadFont && \
239 (p) != BadMatch && \
240 (p) != BadPixmap)
242 /* ---------------------------------------------------------------------------
243 * Determines if text is actually visible
244 #define TEXT_IS_VISIBLE(b, l, t) \
245 (((l)->On && !TEST_FLAG(ONSILKFLAG, (t))) || \
246 (TEST_FLAG(ONSILKFLAG, (t)) && (b)->ElementOn \
247 && ((b)->InvisibleObjectsOn || \
248 (TEST_FLAG(ONSOLDERFLAG, (t)) != 0) == SWAP_IDENT)))
250 #define TEXT_IS_VISIBLE(b, l, t) \
251 ((l)->On)
253 /* ---------------------------------------------------------------------------
254 * Determines if object is on front or back
256 #define FRONT(o) \
257 ((TEST_FLAG(ONSOLDERFLAG, (o)) != 0) == SWAP_IDENT)
259 /* ---------------------------------------------------------------------------
260 * some loop shortcuts
261 * all object loops run backwards to prevent from errors when deleting objects
263 * a pointer is created from index addressing because the base pointer
264 * may change when new memory is allocated;
266 * all data is relativ to an objects name 'top' which can be either
267 * PCB or PasteBuffer
269 #define END_LOOP }} while (0)
271 #define STYLE_LOOP(top) do { \
272 Cardinal n; \
273 RouteStyleTypePtr style; \
274 for (n = 0; n < NUM_STYLES; n++) \
276 style = &(top)->RouteStyle[n]
278 #define VIA_LOOP(top) do { \
279 Cardinal n, sn; \
280 PinTypePtr via; \
281 for (sn = (top)->ViaN, n = 0; (top)->ViaN > 0 && n < (top)->ViaN ; \
282 n += 1 + (top)->ViaN - sn, sn = (top)->ViaN) \
284 via = &(top)->Via[n]
286 #define DRILL_LOOP(top) do { \
287 Cardinal n; \
288 DrillTypePtr drill; \
289 for (n = 0; (top)->DrillN > 0 && n < (top)->DrillN; n++) \
291 drill = &(top)->Drill[n]
293 #define NETLIST_LOOP(top) do { \
294 Cardinal n; \
295 NetListTypePtr netlist; \
296 for (n = (top)->NetListN-1; n != -1; n--) \
298 netlist = &(top)->NetList[n]
300 #define NET_LOOP(top) do { \
301 Cardinal n; \
302 NetTypePtr net; \
303 for (n = (top)->NetN-1; n != -1; n--) \
305 net = &(top)->Net[n]
307 #define CONNECTION_LOOP(net) do { \
308 Cardinal n; \
309 ConnectionTypePtr connection; \
310 for (n = (net)->ConnectionN-1; n != -1; n--) \
312 connection = & (net)->Connection[n]
314 #define ELEMENT_LOOP(top) do { \
315 Cardinal n; \
316 ElementTypePtr element; \
317 for (n = (top)->ElementN-1; n != -1; n--) \
319 element = &(top)->Element[n]
321 #define RAT_LOOP(top) do { \
322 Cardinal n; \
323 RatTypePtr line; \
324 for (n = (top)->RatN-1; n != -1; n--) \
326 line = &(top)->Rat[n]
329 #define ELEMENTTEXT_LOOP(element) do { \
330 Cardinal n; \
331 TextTypePtr text; \
332 for (n = MAX_ELEMENTNAMES-1; n != -1; n--) \
334 text = &(element)->Name[n]
336 #define ELEMENTNAME_LOOP(element) do { \
337 Cardinal n; \
338 char *textstring; \
339 for (n = MAX_ELEMENTNAMES-1; n != -1; n--) \
341 textstring = (element)->Name[n].TextString
343 #define PIN_LOOP(element) do { \
344 Cardinal n, sn; \
345 PinTypePtr pin; \
346 for (sn = (element)->PinN, n = 0; (element)->PinN > 0 && n < (element)->PinN ; \
347 n += 1 + (element)->PinN - sn, sn = (element)->PinN) \
349 pin = &(element)->Pin[n]
351 #define PAD_LOOP(element) do { \
352 Cardinal n, sn; \
353 PadTypePtr pad; \
354 for (sn = (element)->PadN, n = 0; (element)->PadN > 0 && n < (element)->PadN ; \
355 sn == (element)->PadN ? n++ : 0) \
357 pad = &(element)->Pad[n]
359 #define ARC_LOOP(element) do { \
360 Cardinal n; \
361 ArcTypePtr arc; \
362 for (n = (element)->ArcN-1; n != -1; n--) \
364 arc = &(element)->Arc[n]
366 #define ELEMENTLINE_LOOP(element) do { \
367 Cardinal n; \
368 LineTypePtr line; \
369 for (n = (element)->LineN-1; n != -1; n--) \
371 line = &(element)->Line[n]
373 #define ELEMENTARC_LOOP(element) do { \
374 Cardinal n; \
375 ArcTypePtr arc; \
376 for (n = (element)->ArcN-1; n != -1; n--) \
378 arc = &(element)->Arc[n]
380 #define LINE_LOOP(layer) do { \
381 Cardinal n; \
382 LineTypePtr line; \
383 for (n = (layer)->LineN-1; n != -1; n--) \
385 line = &(layer)->Line[n]
387 #define TEXT_LOOP(layer) do { \
388 Cardinal n; \
389 TextTypePtr text; \
390 for (n = (layer)->TextN-1; n != -1; n--) \
392 text = &(layer)->Text[n]
394 #define POLYGON_LOOP(layer) do { \
395 Cardinal n; \
396 PolygonTypePtr polygon; \
397 for (n = (layer)->PolygonN-1; n != -1; n--) \
399 polygon = &(layer)->Polygon[n]
401 #define POLYGONPOINT_LOOP(polygon) do { \
402 Cardinal n; \
403 PointTypePtr point; \
404 for (n = (polygon)->PointN-1; n != -1; n--) \
406 point = &(polygon)->Points[n]
408 #define ENDALL_LOOP }} while (0); }} while (0)
410 #define ALLPIN_LOOP(top) \
411 ELEMENT_LOOP(top); \
412 PIN_LOOP(element)\
414 #define ALLPAD_LOOP(top) \
415 ELEMENT_LOOP(top); \
416 PAD_LOOP(element)
418 #define ALLLINE_LOOP(top) do { \
419 Cardinal l; \
420 LayerTypePtr layer = (top)->Layer; \
421 for (l = 0; l < max_layer + 2; l++, layer++) \
423 LINE_LOOP(layer)
425 #define ALLARC_LOOP(top) do { \
426 Cardinal l; \
427 LayerTypePtr layer = (top)->Layer; \
428 for (l =0; l < max_layer + 2; l++, layer++) \
430 ARC_LOOP(layer)
432 #define ALLPOLYGON_LOOP(top) do { \
433 Cardinal l; \
434 LayerTypePtr layer = (top)->Layer; \
435 for (l = 0; l < max_layer + 2; l++, layer++) \
437 POLYGON_LOOP(layer)
439 #define COPPERLINE_LOOP(top) do { \
440 Cardinal l; \
441 LayerTypePtr layer = (top)->Layer; \
442 for (l = 0; l < max_layer; l++, layer++) \
444 LINE_LOOP(layer)
446 #define COPPERARC_LOOP(top) do { \
447 Cardinal l; \
448 LayerTypePtr layer = (top)->Layer; \
449 for (l =0; l < max_layer; l++, layer++) \
451 ARC_LOOP(layer)
453 #define COPPERPOLYGON_LOOP(top) do { \
454 Cardinal l; \
455 LayerTypePtr layer = (top)->Layer; \
456 for (l = 0; l < max_layer; l++, layer++) \
458 POLYGON_LOOP(layer)
460 #define SILKLINE_LOOP(top) do { \
461 Cardinal l; \
462 LayerTypePtr layer = (top)->Layer; \
463 layer += max_layer; \
464 for (l = 0; l < 2; l++, layer++) \
466 LINE_LOOP(layer)
468 #define SILKARC_LOOP(top) do { \
469 Cardinal l; \
470 LayerTypePtr layer = (top)->Layer; \
471 layer += max_layer; \
472 for (l = 0; l < 2; l++, layer++) \
474 ARC_LOOP(layer)
476 #define SILKPOLYGON_LOOP(top) do { \
477 Cardinal l; \
478 LayerTypePtr layer = (top)->Layer; \
479 layer += max_layer; \
480 for (l = 0; l < 2; l++, layer++) \
482 POLYGON_LOOP(layer)
484 #define ALLTEXT_LOOP(top) do { \
485 Cardinal l; \
486 LayerTypePtr layer = (top)->Layer; \
487 for (l = 0; l < max_layer + 2; l++, layer++) \
489 TEXT_LOOP(layer)
491 #define VISIBLELINE_LOOP(top) do { \
492 Cardinal l; \
493 LayerTypePtr layer = (top)->Layer; \
494 for (l = 0; l < max_layer + 2; l++, layer++) \
496 if (layer->On) \
497 LINE_LOOP(layer)
499 #define VISIBLEARC_LOOP(top) do { \
500 Cardinal l; \
501 LayerTypePtr layer = (top)->Layer; \
502 for (l = 0; l < max_layer + 2; l++, layer++) \
504 if (layer->On) \
505 ARC_LOOP(layer)
507 #define VISIBLETEXT_LOOP(board) do { \
508 Cardinal l; \
509 LayerTypePtr layer = (board)->Data->Layer; \
510 for (l = 0; l < max_layer + 2; l++, layer++) \
512 TEXT_LOOP(layer); \
513 if (TEXT_IS_VISIBLE((board), layer, text))
515 #define VISIBLEPOLYGON_LOOP(top) do { \
516 Cardinal l; \
517 LayerTypePtr layer = (top)->Layer; \
518 for (l = 0; l < max_layer + 2; l++, layer++) \
520 if (layer->On) \
521 POLYGON_LOOP(layer)
523 #define POINTER_LOOP(top) do { \
524 Cardinal n; \
525 void **ptr; \
526 for (n = (top)->PtrN-1; n != -1; n--) \
528 ptr = &(top)->Ptr[n]
530 #define MENU_LOOP(top) do { \
531 Cardinal l; \
532 LibraryMenuTypePtr menu; \
533 for (l = (top)->MenuN-1; l != -1; l--) \
535 menu = &(top)->Menu[l]
537 #define ENTRY_LOOP(top) do { \
538 Cardinal n; \
539 LibraryEntryTypePtr entry; \
540 for (n = (top)->EntryN-1; n != -1; n--) \
542 entry = &(top)->Entry[n]
544 #define GROUP_LOOP(data, group) do { \
545 Cardinal entry; \
546 for (entry = 0; entry < ((PCBTypePtr)(data->pcb))->LayerGroups.Number[(group)]; entry++) \
548 LayerTypePtr layer; \
549 Cardinal number; \
550 number = ((PCBTypePtr)(data->pcb))->LayerGroups.Entries[(group)][entry]; \
551 if (number >= max_layer) \
552 continue; \
553 layer = &data->Layer[number];
555 #define LAYER_LOOP(data, ml) do { \
556 Cardinal n; \
557 for (n = 0; n < ml; n++) \
559 LayerTypePtr layer = (&data->Layer[(n)]);
561 #endif