src/macro.h: Converted plain comments into doxygen comments.
[geda-pcb/pcjc2.git] / src / macro.h
bloba66d2aa0ca2d1dc36b6f58ec5de53e3ce6ae7ccf
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))
77 /* Proper rounding for double -> Coord. */
78 #define DOUBLE_TO_COORD(x) ((x) >= 0 ? (Coord)((x) + 0.5) : (Coord)((x) - 0.5))
80 /* ---------------------------------------------------------------------------
81 * layer macros
83 #define LAYER_ON_STACK(n) (&PCB->Data->Layer[LayerStack[(n)]])
84 #define LAYER_PTR(n) (&PCB->Data->Layer[(n)])
85 #define CURRENT (PCB->SilkActive ? &PCB->Data->Layer[ \
86 (Settings.ShowBottomSide ? bottom_silk_layer : top_silk_layer)] \
87 : LAYER_ON_STACK(0))
88 #define INDEXOFCURRENT (PCB->SilkActive ? \
89 (Settings.ShowBottomSide ? bottom_silk_layer : top_silk_layer) \
90 : LayerStack[0])
91 #define SILKLAYER Layer[ \
92 (Settings.ShowBottomSide ? bottom_silk_layer : top_silk_layer)]
93 #define BACKSILKLAYER Layer[ \
94 (Settings.ShowBottomSide ? top_silk_layer : bottom_silk_layer)]
96 #define TEST_SILK_LAYER(layer) (GetLayerNumber (PCB->Data, layer) >= max_copper_layer)
99 /* ---------------------------------------------------------------------------
100 * returns the object ID
102 #define OBJECT_ID(p) (((AnyObjectType *) p)->ID)
104 /* ---------------------------------------------------------------------------
105 * access macro for current buffer
107 #define PASTEBUFFER (&Buffers[Settings.BufferNumber])
109 /* ---------------------------------------------------------------------------
110 * some routines for flag setting, clearing, changing and testing
112 #define SET_FLAG(F,P) ((P)->Flags.f |= (F))
113 #define CLEAR_FLAG(F,P) ((P)->Flags.f &= (~(F)))
114 #define TEST_FLAG(F,P) ((P)->Flags.f & (F) ? 1 : 0)
115 #define TOGGLE_FLAG(F,P) ((P)->Flags.f ^= (F))
116 #define ASSIGN_FLAG(F,V,P) ((P)->Flags.f = ((P)->Flags.f & (~(F))) | ((V) ? (F) : 0))
117 #define TEST_FLAGS(F,P) (((P)->Flags.f & (F)) == (F) ? 1 : 0)
119 #define FLAGS_EQUAL(F1,F2) (memcmp (&F1, &F2, sizeof(FlagType)) == 0)
121 #define THERMFLAG(L) (0xf << (4 *((L) % 2)))
123 #define TEST_THERM(L,P) ((P)->Flags.t[(L)/2] & THERMFLAG(L) ? 1 : 0)
124 #define GET_THERM(L,P) (((P)->Flags.t[(L)/2] >> (4 * ((L) % 2))) & 0xf)
125 #define CLEAR_THERM(L,P) (P)->Flags.t[(L)/2] &= ~THERMFLAG(L)
126 #define ASSIGN_THERM(L,V,P) (P)->Flags.t[(L)/2] = ((P)->Flags.t[(L)/2] & ~THERMFLAG(L)) | ((V) << (4 * ((L) % 2)))
128 extern int mem_any_set (unsigned char *, int);
129 #define TEST_ANY_THERMS(P) mem_any_set((P)->Flags.t, sizeof((P)->Flags.t))
131 /* ---------------------------------------------------------------------------
132 * access macros for elements name structure
134 #define DESCRIPTION_INDEX 0
135 #define NAMEONPCB_INDEX 1
136 #define VALUE_INDEX 2
137 #define NAME_INDEX(p) (TEST_FLAG(NAMEONPCBFLAG,(p)) ? NAMEONPCB_INDEX :\
138 (TEST_FLAG(DESCRIPTIONFLAG, (p)) ? \
139 DESCRIPTION_INDEX : VALUE_INDEX))
140 #define ELEMENT_NAME(p,e) ((e)->Name[NAME_INDEX((p))].TextString)
141 #define DESCRIPTION_NAME(e) ((e)->Name[DESCRIPTION_INDEX].TextString)
142 #define NAMEONPCB_NAME(e) ((e)->Name[NAMEONPCB_INDEX].TextString)
143 #define VALUE_NAME(e) ((e)->Name[VALUE_INDEX].TextString)
144 #define ELEMENT_TEXT(p,e) ((e)->Name[NAME_INDEX((p))])
145 #define DESCRIPTION_TEXT(e) ((e)->Name[DESCRIPTION_INDEX])
146 #define NAMEONPCB_TEXT(e) ((e)->Name[NAMEONPCB_INDEX])
147 #define VALUE_TEXT(e) ((e)->Name[VALUE_INDEX])
149 /* ---------------------------------------------------------------------------
150 * Determines if text is actually visible
152 #define TEXT_IS_VISIBLE(b, l, t) \
153 ((l)->On)
155 /* ---------------------------------------------------------------------------
156 * Determines if object is on front or back
158 #define FRONT(o) \
159 ((TEST_FLAG(ONSOLDERFLAG, (o)) != 0) == SWAP_IDENT)
161 /* ---------------------------------------------------------------------------
162 * Determines if an object is on the given side. side is either BOTTOM_GROUP
163 * or TOP_GROUP.
165 #define ON_SIDE(element, side) \
166 (TEST_FLAG (ONSOLDERFLAG, element) == (side == BOTTOM_SIDE))
168 /* ---------------------------------------------------------------------------
169 * some loop shortcuts
171 * a pointer is created from index addressing because the base pointer
172 * may change when new memory is allocated;
174 * all data is relativ to an objects name 'top' which can be either
175 * PCB or PasteBuffer
177 #define END_LOOP }} while (0)
179 #define STYLE_LOOP(top) do { \
180 Cardinal n; \
181 RouteStyleType *style; \
182 for (n = 0; n < NUM_STYLES; n++) \
184 style = &(top)->RouteStyle[n]
186 #define VIA_LOOP(top) do { \
187 GList *__iter, *__next; \
188 Cardinal n = 0; \
189 for (__iter = (top)->Via, __next = g_list_next (__iter); \
190 __iter != NULL; \
191 __iter = __next, __next = g_list_next (__iter), n++) { \
192 PinType *via = __iter->data;
194 #define DRILL_LOOP(top) do { \
195 Cardinal n; \
196 DrillType *drill; \
197 for (n = 0; (top)->DrillN > 0 && n < (top)->DrillN; n++) \
199 drill = &(top)->Drill[n]
201 #define NETLIST_LOOP(top) do { \
202 Cardinal n; \
203 NetListType *netlist; \
204 for (n = (top)->NetListN-1; n != -1; n--) \
206 netlist = &(top)->NetList[n]
208 #define NET_LOOP(top) do { \
209 Cardinal n; \
210 NetType *net; \
211 for (n = (top)->NetN-1; n != -1; n--) \
213 net = &(top)->Net[n]
215 #define CONNECTION_LOOP(net) do { \
216 Cardinal n; \
217 ConnectionType *connection; \
218 for (n = (net)->ConnectionN-1; n != -1; n--) \
220 connection = & (net)->Connection[n]
222 #define ELEMENT_LOOP(top) do { \
223 GList *__iter, *__next; \
224 Cardinal n = 0; \
225 for (__iter = (top)->Element, __next = g_list_next (__iter); \
226 __iter != NULL; \
227 __iter = __next, __next = g_list_next (__iter), n++) { \
228 ElementType *element = __iter->data;
230 #define RAT_LOOP(top) do { \
231 GList *__iter, *__next; \
232 Cardinal n = 0; \
233 for (__iter = (top)->Rat, __next = g_list_next (__iter); \
234 __iter != NULL; \
235 __iter = __next, __next = g_list_next (__iter), n++) { \
236 RatType *line = __iter->data;
238 #define ELEMENTTEXT_LOOP(element) do { \
239 Cardinal n; \
240 TextType *text; \
241 for (n = MAX_ELEMENTNAMES-1; n != -1; n--) \
243 text = &(element)->Name[n]
246 #define ELEMENTNAME_LOOP(element) do { \
247 Cardinal n; \
248 char *textstring; \
249 for (n = MAX_ELEMENTNAMES-1; n != -1; n--) \
251 textstring = (element)->Name[n].TextString
253 #define PIN_LOOP(element) do { \
254 GList *__iter, *__next; \
255 Cardinal n = 0; \
256 for (__iter = (element)->Pin, __next = g_list_next (__iter); \
257 __iter != NULL; \
258 __iter = __next, __next = g_list_next (__iter), n++) { \
259 PinType *pin = __iter->data;
261 #define PAD_LOOP(element) do { \
262 GList *__iter, *__next; \
263 Cardinal n = 0; \
264 for (__iter = (element)->Pad, __next = g_list_next (__iter); \
265 __iter != NULL; \
266 __iter = __next, __next = g_list_next (__iter), n++) { \
267 PadType *pad = __iter->data;
269 #define ARC_LOOP(element) do { \
270 GList *__iter, *__next; \
271 Cardinal n = 0; \
272 for (__iter = (element)->Arc, __next = g_list_next (__iter); \
273 __iter != NULL; \
274 __iter = __next, __next = g_list_next (__iter), n++) { \
275 ArcType *arc = __iter->data;
277 #define ELEMENTLINE_LOOP(element) do { \
278 GList *__iter, *__next; \
279 Cardinal n = 0; \
280 for (__iter = (element)->Line, __next = g_list_next (__iter); \
281 __iter != NULL; \
282 __iter = __next, __next = g_list_next (__iter), n++) { \
283 LineType *line = __iter->data;
285 #define ELEMENTARC_LOOP(element) do { \
286 GList *__iter, *__next; \
287 Cardinal n = 0; \
288 for (__iter = (element)->Arc, __next = g_list_next (__iter); \
289 __iter != NULL; \
290 __iter = __next, __next = g_list_next (__iter), n++) { \
291 ArcType *arc = __iter->data;
293 #define LINE_LOOP(layer) do { \
294 GList *__iter, *__next; \
295 Cardinal n = 0; \
296 for (__iter = (layer)->Line, __next = g_list_next (__iter); \
297 __iter != NULL; \
298 __iter = __next, __next = g_list_next (__iter), n++) { \
299 LineType *line = __iter->data;
301 #define TEXT_LOOP(layer) do { \
302 GList *__iter, *__next; \
303 Cardinal n = 0; \
304 for (__iter = (layer)->Text, __next = g_list_next (__iter); \
305 __iter != NULL; \
306 __iter = __next, __next = g_list_next (__iter), n++) { \
307 TextType *text = __iter->data;
309 #define POLYGON_LOOP(layer) do { \
310 GList *__iter, *__next; \
311 Cardinal n = 0; \
312 for (__iter = (layer)->Polygon, __next = g_list_next (__iter); \
313 __iter != NULL; \
314 __iter = __next, __next = g_list_next (__iter), n++) { \
315 PolygonType *polygon = __iter->data;
317 #define POLYGONPOINT_LOOP(polygon) do { \
318 Cardinal n; \
319 PointType *point; \
320 for (n = (polygon)->PointN-1; n != -1; n--) \
322 point = &(polygon)->Points[n]
324 #define ENDALL_LOOP }} while (0); }} while(0)
326 #define ALLPIN_LOOP(top) \
327 ELEMENT_LOOP(top); \
328 PIN_LOOP(element)\
330 #define ALLPAD_LOOP(top) \
331 ELEMENT_LOOP(top); \
332 PAD_LOOP(element)
334 #define ALLLINE_LOOP(top) do { \
335 Cardinal l; \
336 LayerType *layer = (top)->Layer; \
337 for (l = 0; l < max_copper_layer + SILK_LAYER; l++, layer++) \
339 LINE_LOOP(layer)
341 #define ALLARC_LOOP(top) do { \
342 Cardinal l; \
343 LayerType *layer = (top)->Layer; \
344 for (l =0; l < max_copper_layer + SILK_LAYER; l++, layer++) \
346 ARC_LOOP(layer)
348 #define ALLPOLYGON_LOOP(top) do { \
349 Cardinal l; \
350 LayerType *layer = (top)->Layer; \
351 for (l = 0; l < max_copper_layer + SILK_LAYER; l++, layer++) \
353 POLYGON_LOOP(layer)
355 #define COPPERLINE_LOOP(top) do { \
356 Cardinal l; \
357 LayerType *layer = (top)->Layer; \
358 for (l = 0; l < max_copper_layer; l++, layer++) \
360 LINE_LOOP(layer)
362 #define COPPERARC_LOOP(top) do { \
363 Cardinal l; \
364 LayerType *layer = (top)->Layer; \
365 for (l =0; l < max_copper_layer; l++, layer++) \
367 ARC_LOOP(layer)
369 #define COPPERPOLYGON_LOOP(top) do { \
370 Cardinal l; \
371 LayerType *layer = (top)->Layer; \
372 for (l = 0; l < max_copper_layer; l++, layer++) \
374 POLYGON_LOOP(layer)
376 #define SILKLINE_LOOP(top) do { \
377 Cardinal l; \
378 LayerType *layer = (top)->Layer; \
379 layer += max_copper_layer + BOTTOM_SILK_LAYER; \
380 for (l = 0; l < 2; l++, layer++) \
382 LINE_LOOP(layer)
384 #define SILKARC_LOOP(top) do { \
385 Cardinal l; \
386 LayerType *layer = (top)->Layer; \
387 layer += max_copper_layer + BOTTOM_SILK_LAYER; \
388 for (l = 0; l < 2; l++, layer++) \
390 ARC_LOOP(layer)
392 #define SILKPOLYGON_LOOP(top) do { \
393 Cardinal l; \
394 LayerType *layer = (top)->Layer; \
395 layer += max_copper_layer + BOTTOM_SILK_LAYER; \
396 for (l = 0; l < 2; l++, layer++) \
398 POLYGON_LOOP(layer)
400 #define ALLTEXT_LOOP(top) do { \
401 Cardinal l; \
402 LayerType *layer = (top)->Layer; \
403 for (l = 0; l < max_copper_layer + SILK_LAYER; l++, layer++) \
405 TEXT_LOOP(layer)
407 #define VISIBLELINE_LOOP(top) do { \
408 Cardinal l; \
409 LayerType *layer = (top)->Layer; \
410 for (l = 0; l < max_copper_layer + SILK_LAYER; l++, layer++) \
412 if (layer->On) \
413 LINE_LOOP(layer)
415 #define VISIBLEARC_LOOP(top) do { \
416 Cardinal l; \
417 LayerType *layer = (top)->Layer; \
418 for (l = 0; l < max_copper_layer + SILK_LAYER; l++, layer++) \
420 if (layer->On) \
421 ARC_LOOP(layer)
423 #define VISIBLETEXT_LOOP(board) do { \
424 Cardinal l; \
425 LayerType *layer = (board)->Data->Layer; \
426 for (l = 0; l < max_copper_layer + SILK_LAYER; l++, layer++) \
428 TEXT_LOOP(layer); \
429 if (TEXT_IS_VISIBLE((board), layer, text))
431 #define VISIBLEPOLYGON_LOOP(top) do { \
432 Cardinal l; \
433 LayerType *layer = (top)->Layer; \
434 for (l = 0; l < max_copper_layer + SILK_LAYER; l++, layer++) \
436 if (layer->On) \
437 POLYGON_LOOP(layer)
439 #define POINTER_LOOP(top) do { \
440 Cardinal n; \
441 void **ptr; \
442 for (n = (top)->PtrN-1; n != -1; n--) \
444 ptr = &(top)->Ptr[n]
446 #define MENU_LOOP(top) do { \
447 Cardinal l; \
448 LibraryMenuType *menu; \
449 for (l = (top)->MenuN-1; l != -1; l--) \
451 menu = &(top)->Menu[l]
453 #define ENTRY_LOOP(top) do { \
454 Cardinal n; \
455 LibraryEntryType *entry; \
456 for (n = (top)->EntryN-1; n != -1; n--) \
458 entry = &(top)->Entry[n]
460 #define GROUP_LOOP(data, group) do { \
461 Cardinal entry; \
462 for (entry = 0; entry < ((PCBType *)(data->pcb))->LayerGroups.Number[(group)]; entry++) \
464 LayerType *layer; \
465 Cardinal number; \
466 number = ((PCBType *)(data->pcb))->LayerGroups.Entries[(group)][entry]; \
467 if (number >= max_copper_layer) \
468 continue; \
469 layer = &data->Layer[number];
471 #define LAYER_LOOP(data, ml) do { \
472 Cardinal n; \
473 for (n = 0; n < ml; n++) \
475 LayerType *layer = (&data->Layer[(n)]);
477 #define LAYER_TYPE_LOOP(data, ml, type) do { \
478 Cardinal n; \
479 for (n = 0; n < ml; n++) { \
480 LayerType *layer = (&data->Layer[(n)]); \
481 if (layer->Type != (type)) \
482 continue;
484 #endif