More stackup changes
[geda-pcb/pcjc2/v2.git] / src / macro.h
blob2101e683fbc253ea05ca4bbef8fab20ddf60e05e
1 /*!
2 * \file src/macro.h
4 * \brief Some commonly used macros not related to a special C-file.
6 * The file is included by global.h after const.h
8 * <hr>
10 * <h1><b>Copyright.</b></h1>\n
12 * PCB, interactive printed circuit board design
14 * Copyright (C) 1994,1995,1996 Thomas Nau
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 * Contact addresses for paper mail and Email:
31 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
32 * Thomas.Nau@rz.uni-ulm.de
35 #ifndef PCB_MACRO_H
36 #define PCB_MACRO_H
38 /* ---------------------------------------------------------------------------
39 * macros to transform coord systems
40 * draw.c uses a different definition of TO_SCREEN
42 #ifndef SWAP_IDENT
43 #define SWAP_IDENT Settings.ShowBottomSide
44 #endif
46 #define SWAP_SIGN_X(x) (x)
47 #define SWAP_SIGN_Y(y) (-(y))
48 #define SWAP_ANGLE(a) (-(a))
49 #define SWAP_DELTA(d) (-(d))
50 #define SWAP_X(x) (SWAP_SIGN_X(x))
51 #define SWAP_Y(y) (PCB->MaxHeight +SWAP_SIGN_Y(y))
53 /* ---------------------------------------------------------------------------
54 * misc macros, some might already be defined by <limits.h>
56 #ifndef MIN
57 #define MIN(a,b) ((a) < (b) ? (a) : (b))
58 #define MAX(a,b) ((a) > (b) ? (a) : (b))
59 #endif
60 #ifndef SGN
61 #define SGN(a) ((a) >0 ? 1 : ((a) == 0 ? 0 : -1))
62 #endif
63 #define SGNZ(a) ((a) >=0 ? 1 : -1)
64 #define MAKEMIN(a,b) if ((b) < (a)) (a) = (b)
65 #define MAKEMAX(a,b) if ((b) > (a)) (a) = (b)
67 #define ENTRIES(x) (sizeof((x))/sizeof((x)[0]))
68 #define UNKNOWN(a) ((a) && *(a) ? (a) : "(unknown)")
69 #define UNKNOWN_NAME(a, n) ((a) && *(a) ? (a) : (n))
70 #define NSTRCMP(a, b) ((a) ? ((b) ? strcmp((a),(b)) : 1) : -1)
71 #define EMPTY(a) ((a) ? (a) : "")
72 #define EMPTY_STRING_P(a) ((a) ? (a)[0]==0 : 1)
73 #define XOR(a,b) (((a) && !(b)) || (!(a) && (b)))
74 #define SQUARE(x) ((float) (x) * (float) (x))
75 #define TO_RADIANS(degrees) (M180 * (degrees))
76 #define TO_DEGREES(radians) ((radians) / M180)
78 /* Proper rounding for double -> Coord. */
79 #define DOUBLE_TO_COORD(x) ((x) >= 0 ? (Coord)((x) + 0.5) : (Coord)((x) - 0.5))
81 /* ---------------------------------------------------------------------------
82 * layer macros
84 #define LAYER_ON_STACK(n) (&PCB->Data->Layer[LayerStack[(n)]])
85 #define LAYER_PTR(n) (&PCB->Data->Layer[(n)])
86 #define CURRENT (PCB->SilkActive ? &PCB->Data->Layer[ \
87 Settings.ShowBottomSide ? bottom_silk_layer : top_silk_layer] \
88 : PCB->SolderMaskActive ? &PCB->Data->Layer[ \
89 Settings.ShowBottomSide ? bottom_soldermask_layer : top_soldermask_layer] \
90 : LAYER_ON_STACK(0))
91 #define INDEXOFCURRENT (PCB->SilkActive ? \
92 Settings.ShowBottomSide ? bottom_silk_layer : top_silk_layer \
93 : PCB->SolderMaskActive ? \
94 Settings.ShowBottomSide ? bottom_soldermask_layer : top_soldermask_layer \
95 : LayerStack[0])
96 #define SILKLAYER Layer[ \
97 (Settings.ShowBottomSide ? bottom_silk_layer : top_silk_layer)]
98 #define BACKSILKLAYER Layer[ \
99 (Settings.ShowBottomSide ? top_silk_layer : bottom_silk_layer)]
100 #define SOLDERMASKLAYER Layer[ \
101 (Settings.ShowBottomSide ? bottom_soldermask_layer : top_soldermask_layer)]
102 #define BACKSOLDERMASKLAYER Layer[ \
103 (Settings.ShowBottomSide ? top_soldermask_layer : bottom_soldermask_layer)]
105 #define TEST_SILK_LAYER(layer) (GetLayerNumber (PCB->Data, layer) == top_silk_layer || \
106 GetLayerNumber (PCB->Data, layer) == bottom_silk_layer)
107 #define TEST_SOLDERMASK_LAYER(layer) (GetLayerNumber (PCB->Data, layer) == top_soldermask_layer || \
108 GetLayerNumber (PCB->Data, layer) == bottom_soldermask_layer)
111 /* ---------------------------------------------------------------------------
112 * returns the object ID
114 #define OBJECT_ID(p) (((AnyObjectType *) p)->ID)
116 /* ---------------------------------------------------------------------------
117 * access macro for current buffer
119 #define PASTEBUFFER (&Buffers[Settings.BufferNumber])
121 /* ---------------------------------------------------------------------------
122 * some routines for flag setting, clearing, changing and testing
124 #define SET_FLAG(F,P) ((P)->Flags.f |= (F))
125 #define CLEAR_FLAG(F,P) ((P)->Flags.f &= (~(F)))
126 #define TEST_FLAG(F,P) ((P)->Flags.f & (F) ? 1 : 0)
127 #define TOGGLE_FLAG(F,P) ((P)->Flags.f ^= (F))
128 #define ASSIGN_FLAG(F,V,P) ((P)->Flags.f = ((P)->Flags.f & (~(F))) | ((V) ? (F) : 0))
129 #define TEST_FLAGS(F,P) (((P)->Flags.f & (F)) == (F) ? 1 : 0)
131 #define FLAGS_EQUAL(F1,F2) (memcmp (&F1, &F2, sizeof(FlagType)) == 0)
133 #define THERMFLAG(L) (0xf << (4 *((L) % 2)))
135 #define TEST_THERM(L,P) ((P)->Flags.t[(L)/2] & THERMFLAG(L) ? 1 : 0)
136 #define GET_THERM(L,P) (((P)->Flags.t[(L)/2] >> (4 * ((L) % 2))) & 0xf)
137 #define CLEAR_THERM(L,P) (P)->Flags.t[(L)/2] &= ~THERMFLAG(L)
138 #define ASSIGN_THERM(L,V,P) (P)->Flags.t[(L)/2] = ((P)->Flags.t[(L)/2] & ~THERMFLAG(L)) | ((V) << (4 * ((L) % 2)))
140 extern int mem_any_set (unsigned char *, int);
141 #define TEST_ANY_THERMS(P) mem_any_set((P)->Flags.t, sizeof((P)->Flags.t))
143 /* ---------------------------------------------------------------------------
144 * access macros for elements name structure
146 #define DESCRIPTION_INDEX 0
147 #define NAMEONPCB_INDEX 1
148 #define VALUE_INDEX 2
149 #define NAME_INDEX(p) (TEST_FLAG(NAMEONPCBFLAG,(p)) ? NAMEONPCB_INDEX :\
150 (TEST_FLAG(DESCRIPTIONFLAG, (p)) ? \
151 DESCRIPTION_INDEX : VALUE_INDEX))
152 #define ELEMENT_NAME(p,e) ((e)->Name[NAME_INDEX((p))].TextString)
153 #define DESCRIPTION_NAME(e) ((e)->Name[DESCRIPTION_INDEX].TextString)
154 #define NAMEONPCB_NAME(e) ((e)->Name[NAMEONPCB_INDEX].TextString)
155 #define VALUE_NAME(e) ((e)->Name[VALUE_INDEX].TextString)
156 #define ELEMENT_TEXT(p,e) ((e)->Name[NAME_INDEX((p))])
157 #define DESCRIPTION_TEXT(e) ((e)->Name[DESCRIPTION_INDEX])
158 #define NAMEONPCB_TEXT(e) ((e)->Name[NAMEONPCB_INDEX])
159 #define VALUE_TEXT(e) ((e)->Name[VALUE_INDEX])
161 /* ---------------------------------------------------------------------------
162 * Determines if text is actually visible
164 #define TEXT_IS_VISIBLE(b, l, t) \
165 ((l)->On)
167 /* ---------------------------------------------------------------------------
168 * Determines if object is on front or back
170 #define FRONT(o) \
171 ((TEST_FLAG(ONSOLDERFLAG, (o)) != 0) == SWAP_IDENT)
173 /* ---------------------------------------------------------------------------
174 * Determines if an object is on the given side. side is either BOTTOM_GROUP
175 * or TOP_GROUP.
177 #define ON_SIDE(element, side) \
178 (TEST_FLAG (ONSOLDERFLAG, element) == (side == BOTTOM_SIDE))
180 /* ---------------------------------------------------------------------------
181 * some loop shortcuts
183 * a pointer is created from index addressing because the base pointer
184 * may change when new memory is allocated;
186 * all data is relativ to an objects name 'top' which can be either
187 * PCB or PasteBuffer
189 #define END_LOOP }} while (0)
191 #define STYLE_LOOP(top) do { \
192 Cardinal n; \
193 RouteStyleType *style; \
194 for (n = 0; n < NUM_STYLES; n++) \
196 style = &(top)->RouteStyle[n]
198 #define VIA_LOOP(top) do { \
199 GList *__iter, *__next; \
200 Cardinal n = 0; \
201 for (__iter = (top)->Via, __next = g_list_next (__iter); \
202 __iter != NULL; \
203 __iter = __next, __next = g_list_next (__iter), n++) { \
204 PinType *via = __iter->data;
206 #define DRILL_LOOP(top) do { \
207 Cardinal n; \
208 DrillType *drill; \
209 for (n = 0; (top)->DrillN > 0 && n < (top)->DrillN; n++) \
211 drill = &(top)->Drill[n]
213 #define NETLIST_LOOP(top) do { \
214 Cardinal n; \
215 NetListType *netlist; \
216 for (n = (top)->NetListN-1; n != -1; n--) \
218 netlist = &(top)->NetList[n]
220 #define NET_LOOP(top) do { \
221 Cardinal n; \
222 NetType *net; \
223 for (n = (top)->NetN-1; n != -1; n--) \
225 net = &(top)->Net[n]
227 #define CONNECTION_LOOP(net) do { \
228 Cardinal n; \
229 ConnectionType *connection; \
230 for (n = (net)->ConnectionN-1; n != -1; n--) \
232 connection = & (net)->Connection[n]
234 #define ELEMENT_LOOP(top) do { \
235 GList *__iter, *__next; \
236 Cardinal n = 0; \
237 for (__iter = (top)->Element, __next = g_list_next (__iter); \
238 __iter != NULL; \
239 __iter = __next, __next = g_list_next (__iter), n++) { \
240 ElementType *element = __iter->data;
242 #define RAT_LOOP(top) do { \
243 GList *__iter, *__next; \
244 Cardinal n = 0; \
245 for (__iter = (top)->Rat, __next = g_list_next (__iter); \
246 __iter != NULL; \
247 __iter = __next, __next = g_list_next (__iter), n++) { \
248 RatType *line = __iter->data;
250 #define ELEMENTTEXT_LOOP(element) do { \
251 Cardinal n; \
252 TextType *text; \
253 for (n = MAX_ELEMENTNAMES-1; n != -1; n--) \
255 text = &(element)->Name[n]
258 #define ELEMENTNAME_LOOP(element) do { \
259 Cardinal n; \
260 char *textstring; \
261 for (n = MAX_ELEMENTNAMES-1; n != -1; n--) \
263 textstring = (element)->Name[n].TextString
265 #define PIN_LOOP(element) do { \
266 GList *__iter, *__next; \
267 Cardinal n = 0; \
268 for (__iter = (element)->Pin, __next = g_list_next (__iter); \
269 __iter != NULL; \
270 __iter = __next, __next = g_list_next (__iter), n++) { \
271 PinType *pin = __iter->data;
273 #define PAD_LOOP(element) do { \
274 GList *__iter, *__next; \
275 Cardinal n = 0; \
276 for (__iter = (element)->Pad, __next = g_list_next (__iter); \
277 __iter != NULL; \
278 __iter = __next, __next = g_list_next (__iter), n++) { \
279 PadType *pad = __iter->data;
281 #define ARC_LOOP(element) do { \
282 GList *__iter, *__next; \
283 Cardinal n = 0; \
284 for (__iter = (element)->Arc, __next = g_list_next (__iter); \
285 __iter != NULL; \
286 __iter = __next, __next = g_list_next (__iter), n++) { \
287 ArcType *arc = __iter->data;
289 #define ELEMENTLINE_LOOP(element) do { \
290 GList *__iter, *__next; \
291 Cardinal n = 0; \
292 for (__iter = (element)->Line, __next = g_list_next (__iter); \
293 __iter != NULL; \
294 __iter = __next, __next = g_list_next (__iter), n++) { \
295 LineType *line = __iter->data;
297 #define ELEMENTARC_LOOP(element) do { \
298 GList *__iter, *__next; \
299 Cardinal n = 0; \
300 for (__iter = (element)->Arc, __next = g_list_next (__iter); \
301 __iter != NULL; \
302 __iter = __next, __next = g_list_next (__iter), n++) { \
303 ArcType *arc = __iter->data;
305 #define LINE_LOOP(layer) do { \
306 GList *__iter, *__next; \
307 Cardinal n = 0; \
308 for (__iter = (layer)->Line, __next = g_list_next (__iter); \
309 __iter != NULL; \
310 __iter = __next, __next = g_list_next (__iter), n++) { \
311 LineType *line = __iter->data;
313 #define TEXT_LOOP(layer) do { \
314 GList *__iter, *__next; \
315 Cardinal n = 0; \
316 for (__iter = (layer)->Text, __next = g_list_next (__iter); \
317 __iter != NULL; \
318 __iter = __next, __next = g_list_next (__iter), n++) { \
319 TextType *text = __iter->data;
321 #define POLYGON_LOOP(layer) do { \
322 GList *__iter, *__next; \
323 Cardinal n = 0; \
324 for (__iter = (layer)->Polygon, __next = g_list_next (__iter); \
325 __iter != NULL; \
326 __iter = __next, __next = g_list_next (__iter), n++) { \
327 PolygonType *polygon = __iter->data;
329 #define POLYGONPOINT_LOOP(polygon) do { \
330 Cardinal n; \
331 PointType *point; \
332 for (n = (polygon)->PointN-1; n != -1; n--) \
334 point = &(polygon)->Points[n]
336 #define ENDALL_LOOP }} while (0); }} while(0)
338 #define ALLPIN_LOOP(top) \
339 ELEMENT_LOOP(top); \
340 PIN_LOOP(element)\
342 #define ALLPAD_LOOP(top) \
343 ELEMENT_LOOP(top); \
344 PAD_LOOP(element)
346 #define ALLLINE_LOOP(top) do { \
347 Cardinal l; \
348 LayerType *layer = (top)->Layer; \
349 for (l = 0; l < max_copper_layer + EXTRA_LAYERS; l++, layer++) \
351 LINE_LOOP(layer)
353 #define ALLARC_LOOP(top) do { \
354 Cardinal l; \
355 LayerType *layer = (top)->Layer; \
356 for (l =0; l < max_copper_layer + EXTRA_LAYERS; l++, layer++) \
358 ARC_LOOP(layer)
360 #define ALLPOLYGON_LOOP(top) do { \
361 Cardinal l; \
362 LayerType *layer = (top)->Layer; \
363 for (l = 0; l < max_copper_layer + EXTRA_LAYERS; l++, layer++) \
365 POLYGON_LOOP(layer)
367 #define COPPERLINE_LOOP(top) do { \
368 Cardinal l; \
369 LayerType *layer = (top)->Layer; \
370 for (l = 0; l < max_copper_layer; l++, layer++) \
372 LINE_LOOP(layer)
374 #define COPPERARC_LOOP(top) do { \
375 Cardinal l; \
376 LayerType *layer = (top)->Layer; \
377 for (l =0; l < max_copper_layer; l++, layer++) \
379 ARC_LOOP(layer)
381 #define COPPERPOLYGON_LOOP(top) do { \
382 Cardinal l; \
383 LayerType *layer = (top)->Layer; \
384 for (l = 0; l < max_copper_layer; l++, layer++) \
386 POLYGON_LOOP(layer)
388 #define SILKLINE_LOOP(top) do { \
389 Cardinal l; \
390 LayerType *layer = (top)->Layer; \
391 layer += max_copper_layer + BOTTOM_SILK_LAYER; \
392 for (l = 0; l < 2; l++, layer++) \
394 LINE_LOOP(layer)
396 #define SILKARC_LOOP(top) do { \
397 Cardinal l; \
398 LayerType *layer = (top)->Layer; \
399 layer += max_copper_layer + BOTTOM_SILK_LAYER; \
400 for (l = 0; l < 2; l++, layer++) \
402 ARC_LOOP(layer)
404 #define SILKPOLYGON_LOOP(top) do { \
405 Cardinal l; \
406 LayerType *layer = (top)->Layer; \
407 layer += max_copper_layer + BOTTOM_SILK_LAYER; \
408 for (l = 0; l < 2; l++, layer++) \
410 POLYGON_LOOP(layer)
412 #define ALLTEXT_LOOP(top) do { \
413 Cardinal l; \
414 LayerType *layer = (top)->Layer; \
415 for (l = 0; l < max_copper_layer + EXTRA_LAYERS; l++, layer++) \
417 TEXT_LOOP(layer)
419 #define VISIBLELINE_LOOP(top) do { \
420 Cardinal l; \
421 LayerType *layer = (top)->Layer; \
422 for (l = 0; l < max_copper_layer + EXTRA_LAYERS; l++, layer++) \
424 if (layer->On) \
425 LINE_LOOP(layer)
427 #define VISIBLEARC_LOOP(top) do { \
428 Cardinal l; \
429 LayerType *layer = (top)->Layer; \
430 for (l = 0; l < max_copper_layer + EXTRA_LAYERS; l++, layer++) \
432 if (layer->On) \
433 ARC_LOOP(layer)
435 #define VISIBLETEXT_LOOP(board) do { \
436 Cardinal l; \
437 LayerType *layer = (board)->Data->Layer; \
438 for (l = 0; l < max_copper_layer + EXTRA_LAYERS; l++, layer++) \
440 TEXT_LOOP(layer); \
441 if (TEXT_IS_VISIBLE((board), layer, text))
443 #define VISIBLEPOLYGON_LOOP(top) do { \
444 Cardinal l; \
445 LayerType *layer = (top)->Layer; \
446 for (l = 0; l < max_copper_layer + EXTRA_LAYERS; l++, layer++) \
448 if (layer->On) \
449 POLYGON_LOOP(layer)
451 #define POINTER_LOOP(top) do { \
452 Cardinal n; \
453 void **ptr; \
454 for (n = (top)->PtrN-1; n != -1; n--) \
456 ptr = &(top)->Ptr[n]
458 #define MENU_LOOP(top) do { \
459 Cardinal l; \
460 LibraryMenuType *menu; \
461 for (l = (top)->MenuN-1; l != -1; l--) \
463 menu = &(top)->Menu[l]
465 #define ENTRY_LOOP(top) do { \
466 Cardinal n; \
467 LibraryEntryType *entry; \
468 for (n = (top)->EntryN-1; n != -1; n--) \
470 entry = &(top)->Entry[n]
472 #define GROUP_LOOP(data, group) do { \
473 Cardinal entry; \
474 for (entry = 0; entry < ((PCBType *)(data->pcb))->LayerGroups.Number[(group)]; entry++) \
476 LayerType *layer; \
477 Cardinal number; \
478 number = ((PCBType *)(data->pcb))->LayerGroups.Entries[(group)][entry]; \
479 if (number >= max_copper_layer) \
480 continue; \
481 layer = &data->Layer[number];
483 #define LAYER_LOOP(data, ml) do { \
484 Cardinal n; \
485 for (n = 0; n < ml; n++) \
487 LayerType *layer = (&data->Layer[(n)]);
489 #define LAYER_TYPE_LOOP(data, ml, type) do { \
490 Cardinal n; \
491 for (n = 0; n < ml; n++) { \
492 LayerType *layer = (&data->Layer[(n)]); \
493 if (layer->Type != (type)) \
494 continue;
496 #endif
498 #define VIA_IS_BURIED(via) (via->BuriedFrom != 0 || via->BuriedTo != 0) /*!< Despite the naming, this identifies any blind or buried via (any via which does not go right through the PCB) */
499 #define VIA_ON_LAYER(via, layer) (layer >= via->BuriedFrom && layer <= via->BuriedTo )