/*!
* \file src/macro.h
*
* \brief Some commonly used macros not related to a special C-file.
*
* The file is included by global.h after const.h
*
*
*
* Copyright.
\n
*
* PCB, interactive printed circuit board design
*
* Copyright (C) 1994,1995,1996 Thomas Nau
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Contact addresses for paper mail and Email:
* Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
* Thomas.Nau@rz.uni-ulm.de
*/
#ifndef PCB_MACRO_H
#define PCB_MACRO_H
/* ---------------------------------------------------------------------------
* macros to transform coord systems
* draw.c uses a different definition of TO_SCREEN
*/
#ifndef SWAP_IDENT
#define SWAP_IDENT Settings.ShowBottomSide
#endif
#define SWAP_SIGN_X(x) (x)
#define SWAP_SIGN_Y(y) (-(y))
#define SWAP_ANGLE(a) (-(a))
#define SWAP_DELTA(d) (-(d))
#define SWAP_X(x) (SWAP_SIGN_X(x))
#define SWAP_Y(y) (PCB->MaxHeight +SWAP_SIGN_Y(y))
/* ---------------------------------------------------------------------------
* misc macros, some might already be defined by
*/
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#endif
#ifndef SGN
#define SGN(a) ((a) >0 ? 1 : ((a) == 0 ? 0 : -1))
#endif
#define SGNZ(a) ((a) >=0 ? 1 : -1)
#define MAKEMIN(a,b) if ((b) < (a)) (a) = (b)
#define MAKEMAX(a,b) if ((b) > (a)) (a) = (b)
#define ARG(n) (argc > (n) ? argv[n] : 0)
#define ENTRIES(x) (sizeof((x))/sizeof((x)[0]))
#define UNKNOWN(a) ((a) && *(a) ? (a) : "(unknown)")
#define UNKNOWN_NAME(a, n) ((a) && *(a) ? (a) : (n))
#define NSTRCMP(a, b) ((a) ? ((b) ? strcmp((a),(b)) : 1) : -1)
#define EMPTY(a) ((a) ? (a) : "")
#define EMPTY_STRING_P(a) ((a) ? (a)[0]==0 : 1)
#define XOR(a,b) (((a) && !(b)) || (!(a) && (b)))
#define SQUARE(x) ((float) (x) * (float) (x))
#define TO_RADIANS(degrees) (M180 * (degrees))
/* Proper rounding for double -> Coord. */
#define DOUBLE_TO_COORD(x) ((x) >= 0 ? (Coord)((x) + 0.5) : (Coord)((x) - 0.5))
/* ---------------------------------------------------------------------------
* layer macros
*/
#define LAYER_ON_STACK(n) (&PCB->Data->Layer[LayerStack[(n)]])
#define LAYER_PTR(n) (&PCB->Data->Layer[(n)])
#define CURRENT (PCB->SilkActive ? &PCB->Data->Layer[ \
(Settings.ShowBottomSide ? bottom_silk_layer : top_silk_layer)] \
: LAYER_ON_STACK(0))
#define INDEXOFCURRENT (PCB->SilkActive ? \
(Settings.ShowBottomSide ? bottom_silk_layer : top_silk_layer) \
: LayerStack[0])
#define SILKLAYER Layer[ \
(Settings.ShowBottomSide ? bottom_silk_layer : top_silk_layer)]
#define BACKSILKLAYER Layer[ \
(Settings.ShowBottomSide ? top_silk_layer : bottom_silk_layer)]
#define TEST_SILK_LAYER(layer) (GetLayerNumber (PCB->Data, layer) >= max_copper_layer)
/* ---------------------------------------------------------------------------
* returns the object ID
*/
#define OBJECT_ID(p) (((AnyObjectType *) p)->ID)
/* ---------------------------------------------------------------------------
* access macro for current buffer
*/
#define PASTEBUFFER (&Buffers[Settings.BufferNumber])
/* flag macros moved to flag.h */
/* ---------------------------------------------------------------------------
* access macros for elements name structure
*/
#define DESCRIPTION_INDEX 0
#define NAMEONPCB_INDEX 1
#define VALUE_INDEX 2
#define NAME_INDEX(p) (TEST_FLAG(NAMEONPCBFLAG,(p)) ? NAMEONPCB_INDEX :\
(TEST_FLAG(DESCRIPTIONFLAG, (p)) ? \
DESCRIPTION_INDEX : VALUE_INDEX))
#define ELEMENT_NAME(p,e) ((e)->Name[NAME_INDEX((p))].TextString)
#define DESCRIPTION_NAME(e) ((e)->Name[DESCRIPTION_INDEX].TextString)
#define NAMEONPCB_NAME(e) ((e)->Name[NAMEONPCB_INDEX].TextString)
#define VALUE_NAME(e) ((e)->Name[VALUE_INDEX].TextString)
#define ELEMENT_TEXT(p,e) ((e)->Name[NAME_INDEX((p))])
#define DESCRIPTION_TEXT(e) ((e)->Name[DESCRIPTION_INDEX])
#define NAMEONPCB_TEXT(e) ((e)->Name[NAMEONPCB_INDEX])
#define VALUE_TEXT(e) ((e)->Name[VALUE_INDEX])
/* ---------------------------------------------------------------------------
* Determines if text is actually visible
*/
#define TEXT_IS_VISIBLE(b, l, t) \
((l)->On)
/* ---------------------------------------------------------------------------
* Determines if object is on front or back
*/
#define FRONT(o) \
((TEST_FLAG(ONSOLDERFLAG, (o)) != 0) == SWAP_IDENT)
/* ---------------------------------------------------------------------------
* Determines if an object is on the given side. side is either BOTTOM_GROUP
* or TOP_GROUP.
*/
#define ON_SIDE(element, side) \
(TEST_FLAG (ONSOLDERFLAG, element) == (side == BOTTOM_SIDE))
/* ---------------------------------------------------------------------------
* some loop shortcuts
*
* a pointer is created from index addressing because the base pointer
* may change when new memory is allocated;
*
* all data is relativ to an objects name 'top' which can be either
* PCB or PasteBuffer
*/
#define END_LOOP }} while (0)
#define STYLE_LOOP(top) do { \
Cardinal n; \
RouteStyleType *style; \
for (n = 0; n < NUM_STYLES; n++) \
{ \
style = &(top)->RouteStyle[n]
#define VIA_LOOP(top) do { \
GList *__iter, *__next; \
Cardinal n = 0; \
for (__iter = (top)->Via, __next = g_list_next (__iter); \
__iter != NULL; \
__iter = __next, __next = g_list_next (__iter), n++) { \
PinType *via = __iter->data;
#define DRILL_LOOP(top) do { \
Cardinal n; \
DrillType *drill; \
for (n = 0; (top)->DrillN > 0 && n < (top)->DrillN; n++) \
{ \
drill = &(top)->Drill[n]
#define NETLIST_LOOP(top) do { \
Cardinal n; \
NetListType *netlist; \
for (n = (top)->NetListN-1; n != -1; n--) \
{ \
netlist = &(top)->NetList[n]
#define NET_LOOP(top) do { \
Cardinal n; \
NetType *net; \
for (n = (top)->NetN-1; n != -1; n--) \
{ \
net = &(top)->Net[n]
#define CONNECTION_LOOP(net) do { \
Cardinal n; \
ConnectionType *connection; \
for (n = (net)->ConnectionN-1; n != -1; n--) \
{ \
connection = & (net)->Connection[n]
#define ELEMENT_LOOP(top) do { \
GList *__iter, *__next; \
Cardinal n = 0; \
for (__iter = (top)->Element, __next = g_list_next (__iter); \
__iter != NULL; \
__iter = __next, __next = g_list_next (__iter), n++) { \
ElementType *element = __iter->data;
#define RAT_LOOP(top) do { \
GList *__iter, *__next; \
Cardinal n = 0; \
for (__iter = (top)->Rat, __next = g_list_next (__iter); \
__iter != NULL; \
__iter = __next, __next = g_list_next (__iter), n++) { \
RatType *line = __iter->data;
#define ELEMENTTEXT_LOOP(element) do { \
Cardinal n; \
TextType *text; \
for (n = MAX_ELEMENTNAMES-1; n != -1; n--) \
{ \
text = &(element)->Name[n]
#define ELEMENTNAME_LOOP(element) do { \
Cardinal n; \
char *textstring; \
for (n = MAX_ELEMENTNAMES-1; n != -1; n--) \
{ \
textstring = (element)->Name[n].TextString
#define PIN_LOOP(element) do { \
GList *__iter, *__next; \
Cardinal n = 0; \
for (__iter = (element)->Pin, __next = g_list_next (__iter); \
__iter != NULL; \
__iter = __next, __next = g_list_next (__iter), n++) { \
PinType *pin = __iter->data;
#define PAD_LOOP(element) do { \
GList *__iter, *__next; \
Cardinal n = 0; \
for (__iter = (element)->Pad, __next = g_list_next (__iter); \
__iter != NULL; \
__iter = __next, __next = g_list_next (__iter), n++) { \
PadType *pad = __iter->data;
#define ARC_LOOP(element) do { \
GList *__iter, *__next; \
Cardinal n = 0; \
for (__iter = (element)->Arc, __next = g_list_next (__iter); \
__iter != NULL; \
__iter = __next, __next = g_list_next (__iter), n++) { \
ArcType *arc = __iter->data;
#define ELEMENTLINE_LOOP(element) do { \
GList *__iter, *__next; \
Cardinal n = 0; \
for (__iter = (element)->Line, __next = g_list_next (__iter); \
__iter != NULL; \
__iter = __next, __next = g_list_next (__iter), n++) { \
LineType *line = __iter->data;
#define ELEMENTARC_LOOP(element) do { \
GList *__iter, *__next; \
Cardinal n = 0; \
for (__iter = (element)->Arc, __next = g_list_next (__iter); \
__iter != NULL; \
__iter = __next, __next = g_list_next (__iter), n++) { \
ArcType *arc = __iter->data;
#define LINE_LOOP(layer) do { \
GList *__iter, *__next; \
Cardinal n = 0; \
for (__iter = (layer)->Line, __next = g_list_next (__iter); \
__iter != NULL; \
__iter = __next, __next = g_list_next (__iter), n++) { \
LineType *line = __iter->data;
#define TEXT_LOOP(layer) do { \
GList *__iter, *__next; \
Cardinal n = 0; \
for (__iter = (layer)->Text, __next = g_list_next (__iter); \
__iter != NULL; \
__iter = __next, __next = g_list_next (__iter), n++) { \
TextType *text = __iter->data;
#define POLYGON_LOOP(layer) do { \
GList *__iter, *__next; \
Cardinal n = 0; \
for (__iter = (layer)->Polygon, __next = g_list_next (__iter); \
__iter != NULL; \
__iter = __next, __next = g_list_next (__iter), n++) { \
PolygonType *polygon = __iter->data;
#define POLYGONPOINT_LOOP(polygon) do { \
Cardinal n; \
PointType *point; \
for (n = (polygon)->PointN-1; n != -1; n--) \
{ \
point = &(polygon)->Points[n]
#define ENDALL_LOOP }} while (0); }} while(0)
#define ALLPIN_LOOP(top) \
ELEMENT_LOOP(top); \
PIN_LOOP(element)\
#define ALLPAD_LOOP(top) \
ELEMENT_LOOP(top); \
PAD_LOOP(element)
#define ALLLINE_LOOP(top) do { \
Cardinal l; \
LayerType *layer = (top)->Layer; \
for (l = 0; l < max_copper_layer + SILK_LAYER; l++, layer++) \
{ \
LINE_LOOP(layer)
#define ALLARC_LOOP(top) do { \
Cardinal l; \
LayerType *layer = (top)->Layer; \
for (l =0; l < max_copper_layer + SILK_LAYER; l++, layer++) \
{ \
ARC_LOOP(layer)
#define ALLPOLYGON_LOOP(top) do { \
Cardinal l; \
LayerType *layer = (top)->Layer; \
for (l = 0; l < max_copper_layer + SILK_LAYER; l++, layer++) \
{ \
POLYGON_LOOP(layer)
#define COPPERLINE_LOOP(top) do { \
Cardinal l; \
LayerType *layer = (top)->Layer; \
for (l = 0; l < max_copper_layer; l++, layer++) \
{ \
LINE_LOOP(layer)
#define COPPERARC_LOOP(top) do { \
Cardinal l; \
LayerType *layer = (top)->Layer; \
for (l =0; l < max_copper_layer; l++, layer++) \
{ \
ARC_LOOP(layer)
#define COPPERPOLYGON_LOOP(top) do { \
Cardinal l; \
LayerType *layer = (top)->Layer; \
for (l = 0; l < max_copper_layer; l++, layer++) \
{ \
POLYGON_LOOP(layer)
#define SILKLINE_LOOP(top) do { \
Cardinal l; \
LayerType *layer = (top)->Layer; \
layer += max_copper_layer + BOTTOM_SILK_LAYER; \
for (l = 0; l < 2; l++, layer++) \
{ \
LINE_LOOP(layer)
#define SILKARC_LOOP(top) do { \
Cardinal l; \
LayerType *layer = (top)->Layer; \
layer += max_copper_layer + BOTTOM_SILK_LAYER; \
for (l = 0; l < 2; l++, layer++) \
{ \
ARC_LOOP(layer)
#define SILKPOLYGON_LOOP(top) do { \
Cardinal l; \
LayerType *layer = (top)->Layer; \
layer += max_copper_layer + BOTTOM_SILK_LAYER; \
for (l = 0; l < 2; l++, layer++) \
{ \
POLYGON_LOOP(layer)
#define ALLTEXT_LOOP(top) do { \
Cardinal l; \
LayerType *layer = (top)->Layer; \
for (l = 0; l < max_copper_layer + SILK_LAYER; l++, layer++) \
{ \
TEXT_LOOP(layer)
#define VISIBLELINE_LOOP(top) do { \
Cardinal l; \
LayerType *layer = (top)->Layer; \
for (l = 0; l < max_copper_layer + SILK_LAYER; l++, layer++) \
{ \
if (layer->On) \
LINE_LOOP(layer)
#define VISIBLEARC_LOOP(top) do { \
Cardinal l; \
LayerType *layer = (top)->Layer; \
for (l = 0; l < max_copper_layer + SILK_LAYER; l++, layer++) \
{ \
if (layer->On) \
ARC_LOOP(layer)
#define VISIBLETEXT_LOOP(board) do { \
Cardinal l; \
LayerType *layer = (board)->Data->Layer; \
for (l = 0; l < max_copper_layer + SILK_LAYER; l++, layer++) \
{ \
TEXT_LOOP(layer); \
if (TEXT_IS_VISIBLE((board), layer, text))
#define VISIBLEPOLYGON_LOOP(top) do { \
Cardinal l; \
LayerType *layer = (top)->Layer; \
for (l = 0; l < max_copper_layer + SILK_LAYER; l++, layer++) \
{ \
if (layer->On) \
POLYGON_LOOP(layer)
#define POINTER_LOOP(top) do { \
Cardinal n; \
void **ptr; \
for (n = (top)->PtrN-1; n != -1; n--) \
{ \
ptr = &(top)->Ptr[n]
#define MENU_LOOP(top) do { \
Cardinal l; \
LibraryMenuType *menu; \
for (l = (top)->MenuN-1; l != -1; l--) \
{ \
menu = &(top)->Menu[l]
#define ENTRY_LOOP(top) do { \
Cardinal n; \
LibraryEntryType *entry; \
for (n = (top)->EntryN-1; n != -1; n--) \
{ \
entry = &(top)->Entry[n]
#define GROUP_LOOP(data, group) do { \
Cardinal entry; \
for (entry = 0; entry < ((PCBType *)(data->pcb))->LayerGroups.Number[(group)]; entry++) \
{ \
LayerType *layer; \
Cardinal number; \
number = ((PCBType *)(data->pcb))->LayerGroups.Entries[(group)][entry]; \
if (number >= max_copper_layer) \
continue; \
layer = &data->Layer[number];
#define LAYER_LOOP(data, ml) do { \
Cardinal n; \
for (n = 0; n < ml; n++) \
{ \
LayerType *layer = (&data->Layer[(n)]);
#define LAYER_TYPE_LOOP(data, ml, type) do { \
Cardinal n; \
for (n = 0; n < ml; n++) { \
LayerType *layer = (&data->Layer[(n)]); \
if (layer->Type != (type)) \
continue;
#endif
#define VIA_IS_BURIED(via) (via->BuriedFrom != 0 || via->BuriedTo != 0)
#define VIA_ON_LAYER(via, layer) (layer >= via->BuriedFrom && layer <= via->BuriedTo )