/*! * \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 )