1 /*!
2  * \file src/macro.h
3  *
4  * \brief Some commonly used macros not related to a special C-file.
5  *
6  * The file is included by global.h after const.h
7  *
8  * <hr>
9  *
10  * <h1><b>Copyright.</b></h1>\n
11  *
12  * PCB, interactive printed circuit board design
13  *
14  * Copyright (C) 1994,1995,1996 Thomas Nau
15  *
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.
20  *
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.
25  *
26  * You should have received a copy of the GNU General Public License along
27  * with this program; if not, write to the Free Software Foundation, Inc.,
28  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29  *
30  * Contact addresses for paper mail and Email:
31  * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
32  * Thomas.Nau@rz.uni-ulm.de
33  */
34 
35 #ifndef	PCB_MACRO_H
36 #define	PCB_MACRO_H
37 
38 /* ---------------------------------------------------------------------------
39  * macros to transform coord systems
40  * draw.c uses a different definition of TO_SCREEN
41  */
42 #ifndef	SWAP_IDENT
43 #define	SWAP_IDENT			Settings.ShowBottomSide
44 #endif
45 
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))
52 
53 /* ---------------------------------------------------------------------------
54  * misc macros, some might already be defined by <limits.h>
55  */
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)
66 
67 #define ARG(n) (argc > (n) ? argv[n] : 0)
68 
69 #define	ENTRIES(x)		(sizeof((x))/sizeof((x)[0]))
70 #define	UNKNOWN(a)		((a) && *(a) ? (a) : "(unknown)")
71 #define	UNKNOWN_NAME(a, n)	((a) && *(a) ? (a) : (n))
72 #define NSTRCMP(a, b)		((a) ? ((b) ? strcmp((a),(b)) : 1) : -1)
73 #define	EMPTY(a)		((a) ? (a) : "")
74 #define	EMPTY_STRING_P(a)	((a) ? (a)[0]==0 : 1)
75 #define XOR(a,b)		(((a) && !(b)) || (!(a) && (b)))
76 #define SQUARE(x)		((float) (x) * (float) (x))
77 #define TO_RADIANS(degrees)	(M180 * (degrees))
78 
79 /* Proper rounding for double -> Coord. */
80 #define DOUBLE_TO_COORD(x) ((x) >= 0 ? (Coord)((x) + 0.5) : (Coord)((x) - 0.5))
81 
82 /* ---------------------------------------------------------------------------
83  * layer macros
84  */
85 #define	LAYER_ON_STACK(n)	(&PCB->Data->Layer[LayerStack[(n)]])
86 #define LAYER_PTR(n)            (&PCB->Data->Layer[(n)])
87 #define	CURRENT			(PCB->SilkActive ? &PCB->Data->Layer[ \
88 				(Settings.ShowBottomSide ? bottom_silk_layer : top_silk_layer)] \
89 				: LAYER_ON_STACK(0))
90 #define	INDEXOFCURRENT		(PCB->SilkActive ? \
91 				(Settings.ShowBottomSide ? bottom_silk_layer : top_silk_layer) \
92 				: LayerStack[0])
93 #define SILKLAYER		Layer[ \
94 				(Settings.ShowBottomSide ? bottom_silk_layer : top_silk_layer)]
95 #define BACKSILKLAYER		Layer[ \
96 				(Settings.ShowBottomSide ? top_silk_layer : bottom_silk_layer)]
97 
98 #define TEST_SILK_LAYER(layer)	(GetLayerNumber (PCB->Data, layer) >= max_copper_layer)
99 
100 
101 /* ---------------------------------------------------------------------------
102  * returns the object ID
103  */
104 #define	OBJECT_ID(p)		(((AnyObjectType *) p)->ID)
105 
106 /* ---------------------------------------------------------------------------
107  * access macro for current buffer
108  */
109 #define	PASTEBUFFER		(&Buffers[Settings.BufferNumber])
110 
111 /* flag macros moved to flag.h */
112 
113 /* ---------------------------------------------------------------------------
114  * access macros for elements name structure
115  */
116 #define	DESCRIPTION_INDEX	0
117 #define	NAMEONPCB_INDEX		1
118 #define	VALUE_INDEX		2
119 #define	NAME_INDEX(p)		(TEST_FLAG(NAMEONPCBFLAG,(p)) ? NAMEONPCB_INDEX :\
120 				(TEST_FLAG(DESCRIPTIONFLAG, (p)) ?		\
121 				DESCRIPTION_INDEX : VALUE_INDEX))
122 #define	ELEMENT_NAME(p,e)	((e)->Name[NAME_INDEX((p))].TextString)
123 #define	DESCRIPTION_NAME(e)	((e)->Name[DESCRIPTION_INDEX].TextString)
124 #define	NAMEONPCB_NAME(e)	((e)->Name[NAMEONPCB_INDEX].TextString)
125 #define	VALUE_NAME(e)		((e)->Name[VALUE_INDEX].TextString)
126 #define	ELEMENT_TEXT(p,e)	((e)->Name[NAME_INDEX((p))])
127 #define	DESCRIPTION_TEXT(e)	((e)->Name[DESCRIPTION_INDEX])
128 #define	NAMEONPCB_TEXT(e)	((e)->Name[NAMEONPCB_INDEX])
129 #define	VALUE_TEXT(e)		((e)->Name[VALUE_INDEX])
130 
131 /* ---------------------------------------------------------------------------
132  *  Determines if text is actually visible
133  */
134 #define TEXT_IS_VISIBLE(b, l, t) \
135 	((l)->On)
136 
137 /* ---------------------------------------------------------------------------
138  *  Determines if object is on front or back
139  */
140 #define FRONT(o)	\
141 	((TEST_FLAG(ONSOLDERFLAG, (o)) != 0) == SWAP_IDENT)
142 
143 /* ---------------------------------------------------------------------------
144  *  Determines if an object is on the given side. side is either BOTTOM_GROUP
145  *  or TOP_GROUP.
146  */
147 #define ON_SIDE(element, side) \
148         (TEST_FLAG (ONSOLDERFLAG, element) == (side == BOTTOM_SIDE))
149 
150 /* ---------------------------------------------------------------------------
151  * some loop shortcuts
152  *
153  * a pointer is created from index addressing because the base pointer
154  * may change when new memory is allocated;
155  *
156  * all data is relativ to an objects name 'top' which can be either
157  * PCB or PasteBuffer
158  */
159 #define END_LOOP  }} while (0)
160 
161 #define STYLE_LOOP(top)  do {                                       \
162         Cardinal n;                                                 \
163         RouteStyleType *style;                                      \
164         for (n = 0; n < NUM_STYLES; n++)                            \
165         {                                                           \
166                 style = &(top)->RouteStyle[n]
167 
168 #define VIA_LOOP(top) do {                                          \
169   GList *__iter, *__next;                                           \
170   Cardinal n = 0;                                                   \
171   for (__iter = (top)->Via, __next = g_list_next (__iter);          \
172        __iter != NULL;                                              \
173        __iter = __next, __next = g_list_next (__iter), n++) {       \
174     PinType *via = __iter->data;
175 
176 #define DRILL_LOOP(top) do             {               \
177         Cardinal        n;                                      \
178         DrillType *drill;                                       \
179         for (n = 0; (top)->DrillN > 0 && n < (top)->DrillN; n++)                        \
180         {                                                       \
181                 drill = &(top)->Drill[n]
182 
183 #define NETLIST_LOOP(top) do   {                         \
184         Cardinal        n;                                      \
185         NetListType *netlist;                                   \
186         for (n = (top)->NetListN-1; n != -1; n--)               \
187         {                                                       \
188                 netlist = &(top)->NetList[n]
189 
190 #define NET_LOOP(top) do   {                             \
191         Cardinal        n;                                      \
192         NetType *net;                                           \
193         for (n = (top)->NetN-1; n != -1; n--)                   \
194         {                                                       \
195                 net = &(top)->Net[n]
196 
197 #define CONNECTION_LOOP(net) do {                         \
198         Cardinal        n;                                      \
199         ConnectionType *connection;                             \
200         for (n = (net)->ConnectionN-1; n != -1; n--)            \
201         {                                                       \
202                 connection = & (net)->Connection[n]
203 
204 #define ELEMENT_LOOP(top) do {                                      \
205   GList *__iter, *__next;                                           \
206   Cardinal n = 0;                                                   \
207   for (__iter = (top)->Element, __next = g_list_next (__iter);      \
208        __iter != NULL;                                              \
209        __iter = __next, __next = g_list_next (__iter), n++) {       \
210     ElementType *element = __iter->data;
211 
212 #define RAT_LOOP(top) do {                                          \
213   GList *__iter, *__next;                                           \
214   Cardinal n = 0;                                                   \
215   for (__iter = (top)->Rat, __next = g_list_next (__iter);          \
216        __iter != NULL;                                              \
217        __iter = __next, __next = g_list_next (__iter), n++) {       \
218     RatType *line = __iter->data;
219 
220 #define	ELEMENTTEXT_LOOP(element) do { 	\
221 	Cardinal	n;				\
222 	TextType *text;					\
223 	for (n = MAX_ELEMENTNAMES-1; n != -1; n--)	\
224 	{						\
225 		text = &(element)->Name[n]
226 
227 
228 #define	ELEMENTNAME_LOOP(element) do	{ 			\
229 	Cardinal	n;					\
230 	char		*textstring;				\
231 	for (n = MAX_ELEMENTNAMES-1; n != -1; n--)		\
232 	{							\
233 		textstring = (element)->Name[n].TextString
234 
235 #define PIN_LOOP(element) do {                                      \
236   GList *__iter, *__next;                                           \
237   Cardinal n = 0;                                                   \
238   for (__iter = (element)->Pin, __next = g_list_next (__iter);      \
239        __iter != NULL;                                              \
240        __iter = __next, __next = g_list_next (__iter), n++) {       \
241     PinType *pin = __iter->data;
242 
243 #define PAD_LOOP(element) do {                                      \
244   GList *__iter, *__next;                                           \
245   Cardinal n = 0;                                                   \
246   for (__iter = (element)->Pad, __next = g_list_next (__iter);      \
247        __iter != NULL;                                              \
248        __iter = __next, __next = g_list_next (__iter), n++) {       \
249     PadType *pad = __iter->data;
250 
251 #define ARC_LOOP(element) do {                                      \
252   GList *__iter, *__next;                                           \
253   Cardinal n = 0;                                                   \
254   for (__iter = (element)->Arc, __next = g_list_next (__iter);      \
255        __iter != NULL;                                              \
256        __iter = __next, __next = g_list_next (__iter), n++) {       \
257     ArcType *arc = __iter->data;
258 
259 #define ELEMENTLINE_LOOP(element) do {                              \
260   GList *__iter, *__next;                                           \
261   Cardinal n = 0;                                                   \
262   for (__iter = (element)->Line, __next = g_list_next (__iter);     \
263        __iter != NULL;                                              \
264        __iter = __next, __next = g_list_next (__iter), n++) {       \
265     LineType *line = __iter->data;
266 
267 #define ELEMENTARC_LOOP(element) do {                               \
268   GList *__iter, *__next;                                           \
269   Cardinal n = 0;                                                   \
270   for (__iter = (element)->Arc, __next = g_list_next (__iter);      \
271        __iter != NULL;                                              \
272        __iter = __next, __next = g_list_next (__iter), n++) {       \
273     ArcType *arc = __iter->data;
274 
275 #define LINE_LOOP(layer) do {                                       \
276   GList *__iter, *__next;                                           \
277   Cardinal n = 0;                                                   \
278   for (__iter = (layer)->Line, __next = g_list_next (__iter);       \
279        __iter != NULL;                                              \
280        __iter = __next, __next = g_list_next (__iter), n++) {       \
281     LineType *line = __iter->data;
282 
283 #define TEXT_LOOP(layer) do {                                       \
284   GList *__iter, *__next;                                           \
285   Cardinal n = 0;                                                   \
286   for (__iter = (layer)->Text, __next = g_list_next (__iter);       \
287        __iter != NULL;                                              \
288        __iter = __next, __next = g_list_next (__iter), n++) {       \
289     TextType *text = __iter->data;
290 
291 #define POLYGON_LOOP(layer) do {                                    \
292   GList *__iter, *__next;                                           \
293   Cardinal n = 0;                                                   \
294   for (__iter = (layer)->Polygon, __next = g_list_next (__iter);    \
295        __iter != NULL;                                              \
296        __iter = __next, __next = g_list_next (__iter), n++) {       \
297     PolygonType *polygon = __iter->data;
298 
299 #define	POLYGONPOINT_LOOP(polygon) do	{	\
300 	Cardinal			n;		\
301 	PointType *point;				\
302 	for (n = (polygon)->PointN-1; n != -1; n--)	\
303 	{						\
304 		point = &(polygon)->Points[n]
305 
306 #define ENDALL_LOOP }} while (0); }} while(0)
307 
308 #define	ALLPIN_LOOP(top)	\
309         ELEMENT_LOOP(top); \
310 	        PIN_LOOP(element)\
311 
312 #define	ALLPAD_LOOP(top) \
313 	ELEMENT_LOOP(top); \
314 	  PAD_LOOP(element)
315 
316 #define	ALLLINE_LOOP(top) do	{		\
317 	Cardinal		l;			\
318 	LayerType *layer = (top)->Layer;		\
319 	for (l = 0; l < max_copper_layer + SILK_LAYER; l++, layer++)	\
320 	{ \
321 		LINE_LOOP(layer)
322 
323 #define ALLARC_LOOP(top) do {		\
324 	Cardinal		l;			\
325 	LayerType *layer = (top)->Layer;		\
326 	for (l =0; l < max_copper_layer + SILK_LAYER; l++, layer++)		\
327 	{ \
328 		ARC_LOOP(layer)
329 
330 #define	ALLPOLYGON_LOOP(top)	do {		\
331 	Cardinal		l;			\
332 	LayerType *layer = (top)->Layer;		\
333 	for (l = 0; l < max_copper_layer + SILK_LAYER; l++, layer++)	\
334 	{ \
335 		POLYGON_LOOP(layer)
336 
337 #define	COPPERLINE_LOOP(top) do	{		\
338 	Cardinal		l;			\
339 	LayerType *layer = (top)->Layer;		\
340 	for (l = 0; l < max_copper_layer; l++, layer++)	\
341 	{ \
342 		LINE_LOOP(layer)
343 
344 #define COPPERARC_LOOP(top) do	{		\
345 	Cardinal		l;			\
346 	LayerType *layer = (top)->Layer;		\
347 	for (l =0; l < max_copper_layer; l++, layer++)		\
348 	{ \
349 		ARC_LOOP(layer)
350 
351 #define	COPPERPOLYGON_LOOP(top) do	{		\
352 	Cardinal		l;			\
353 	LayerType *layer = (top)->Layer;		\
354 	for (l = 0; l < max_copper_layer; l++, layer++)	\
355 	{ \
356 		POLYGON_LOOP(layer)
357 
358 #define	SILKLINE_LOOP(top) do	{		\
359 	Cardinal		l;			\
360 	LayerType *layer = (top)->Layer;		\
361 	layer += max_copper_layer + BOTTOM_SILK_LAYER;			\
362 	for (l = 0; l < 2; l++, layer++)		\
363 	{ \
364 		LINE_LOOP(layer)
365 
366 #define SILKARC_LOOP(top) do	{		\
367 	Cardinal		l;			\
368 	LayerType *layer = (top)->Layer;		\
369 	layer += max_copper_layer + BOTTOM_SILK_LAYER;			\
370 	for (l = 0; l < 2; l++, layer++)		\
371 	{ \
372 		ARC_LOOP(layer)
373 
374 #define	SILKPOLYGON_LOOP(top) do	{		\
375 	Cardinal		l;			\
376 	LayerType *layer = (top)->Layer;		\
377 	layer += max_copper_layer + BOTTOM_SILK_LAYER;			\
378 	for (l = 0; l < 2; l++, layer++)		\
379 	{ \
380 		POLYGON_LOOP(layer)
381 
382 #define	ALLTEXT_LOOP(top)	do {		\
383 	Cardinal		l;			\
384 	LayerType *layer = (top)->Layer;		\
385 	for (l = 0; l < max_copper_layer + SILK_LAYER; l++, layer++)	\
386 	{ \
387 		TEXT_LOOP(layer)
388 
389 #define	VISIBLELINE_LOOP(top) do	{		\
390 	Cardinal		l;			\
391 	LayerType *layer = (top)->Layer;		\
392 	for (l = 0; l < max_copper_layer + SILK_LAYER; l++, layer++)	\
393 	{ \
394 		if (layer->On)				\
395 			LINE_LOOP(layer)
396 
397 #define	VISIBLEARC_LOOP(top) do	{		\
398 	Cardinal		l;			\
399 	LayerType *layer = (top)->Layer;		\
400 	for (l = 0; l < max_copper_layer + SILK_LAYER; l++, layer++)	\
401 	{ \
402 		if (layer->On)				\
403 			ARC_LOOP(layer)
404 
405 #define	VISIBLETEXT_LOOP(board) do	{		\
406 	Cardinal		l;			\
407 	LayerType *layer = (board)->Data->Layer;		\
408 	for (l = 0; l < max_copper_layer + SILK_LAYER; l++, layer++)	\
409 	{ \
410                 TEXT_LOOP(layer);                                      \
411                   if (TEXT_IS_VISIBLE((board), layer, text))
412 
413 #define	VISIBLEPOLYGON_LOOP(top) do	{	\
414 	Cardinal		l;			\
415 	LayerType *layer = (top)->Layer;		\
416 	for (l = 0; l < max_copper_layer + SILK_LAYER; l++, layer++)	\
417 	{ \
418 		if (layer->On)				\
419 			POLYGON_LOOP(layer)
420 
421 #define POINTER_LOOP(top) do	{	\
422 	Cardinal	n;			\
423 	void	**ptr;				\
424 	for (n = (top)->PtrN-1; n != -1; n--)	\
425 	{					\
426 		ptr = &(top)->Ptr[n]
427 
428 #define MENU_LOOP(top)	do {	\
429 	Cardinal	l;			\
430 	LibraryMenuType *menu;			\
431 	for (l = (top)->MenuN-1; l != -1; l--)	\
432 	{					\
433 		menu = &(top)->Menu[l]
434 
435 #define ENTRY_LOOP(top) do	{	\
436 	Cardinal	n;			\
437 	LibraryEntryType *entry;		\
438 	for (n = (top)->EntryN-1; n != -1; n--)	\
439 	{					\
440 		entry = &(top)->Entry[n]
441 
442 #define GROUP_LOOP(data, group) do { 	\
443 	Cardinal entry; \
444         for (entry = 0; entry < ((PCBType *)(data->pcb))->LayerGroups.Number[(group)]; entry++) \
445         { \
446 		LayerType *layer;		\
447 		Cardinal number; 		\
448 		number = ((PCBType *)(data->pcb))->LayerGroups.Entries[(group)][entry]; \
449 		if (number >= max_copper_layer)	\
450 		  continue;			\
451 		layer = &data->Layer[number];
452 
453 #define LAYER_LOOP(data, ml) do { \
454         Cardinal n; \
455 	for (n = 0; n < ml; n++) \
456 	{ \
457 	   LayerType *layer = (&data->Layer[(n)]);
458 
459 #define LAYER_TYPE_LOOP(data, ml, type) do { \
460         Cardinal n; \
461         for (n = 0; n < ml; n++) { \
462           LayerType *layer = (&data->Layer[(n)]); \
463           if (layer->Type != (type)) \
464             continue;
465 
466 #endif
467 
468 #define VIA_IS_BURIED(via) (via->BuriedFrom != 0 || via->BuriedTo != 0)
469 #define VIA_ON_LAYER(via, layer) (layer >= via->BuriedFrom && layer <= via->BuriedTo )
470