Updated copyright text/header in most source files.
[geda-gaf/peter-b.git] / libgeda / src / o_pin_basic.c
blobb0c83d20e4804fe0c38544deb813903d5360a6be
1 /* gEDA - GPL Electronic Design Automation
2 * libgeda - gEDA's library
3 * Copyright (C) 1998-2010 Ales Hvezda
4 * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
20 #include <config.h>
22 #include <stdio.h>
23 #include <math.h>
25 #include "libgeda_priv.h"
27 #ifdef HAVE_LIBDMALLOC
28 #include <dmalloc.h>
29 #endif
31 /*! \file o_pin_basic.c
32 * \brief functions for the pin object
35 /*! Default setting for pin draw function. */
36 void (*pin_draw_func)() = NULL;
38 /*! \brief calculate and return the boundaries of a pin object
39 * \par Function Description
40 * This function calculates the object boudaries of a pin \a object.
42 * \param [in] toplevel The TOPLEVEL object.
43 * \param [in] object a pin object
44 * \param [out] left the left world coord
45 * \param [out] top the top world coord
46 * \param [out] right the right world coord
47 * \param [out] bottom the bottom world coord
49 void world_get_pin_bounds(TOPLEVEL *toplevel, OBJECT *object, int *left, int *top,
50 int *right, int *bottom)
52 world_get_line_bounds( toplevel, object, left, top, right, bottom );
55 /*! \brief get the position of a whichend of the pin object
56 * \par Function Description
57 * This function gets the position of the whichend side of a pin object.
59 * \param [in] toplevel The toplevel environment.
60 * \param [out] x pointer to the x-position
61 * \param [out] y pointer to the y-position
62 * \param [in] object The object to get the position.
63 * \return TRUE if successfully determined the position, FALSE otherwise
65 gboolean o_pin_get_position (TOPLEVEL *toplevel, gint *x, gint *y,
66 OBJECT *object)
68 *x = object->line->x[object->whichend];
69 *y = object->line->y[object->whichend];
70 return TRUE;
73 /*! \brief create a new pin object
74 * \par Function Description
75 * This function creates and returns a new pin object.
77 * \param [in] toplevel The TOPLEVEL object.
78 * \param [in] type The OBJECT type (usually OBJ_PIN)
79 * \param [in] color The color of the pin
80 * \param [in] x1 x-coord of the first point
81 * \param [in] y1 y-coord of the first point
82 * \param [in] x2 x-coord of the second point
83 * \param [in] y2 y-coord of the second point
84 * \param [in] pin_type type of pin (PIN_TYPE_NET or PIN_TYPE_BUS)
85 * \param [in] whichend The connectable end of the pin
86 * \return A new pin OBJECT
88 OBJECT *o_pin_new(TOPLEVEL *toplevel,
89 char type, int color,
90 int x1, int y1, int x2, int y2, int pin_type, int whichend)
92 OBJECT *new_node;
94 new_node = s_basic_new_object(type, "pin");
95 new_node->color = color;
97 new_node->line = (LINE *) g_malloc(sizeof(LINE));
99 new_node->line->x[0] = x1;
100 new_node->line->y[0] = y1;
101 new_node->line->x[1] = x2;
102 new_node->line->y[1] = y2;
104 o_pin_set_type (toplevel, new_node, pin_type);
106 o_pin_recalc (toplevel, new_node);
108 new_node->draw_func = pin_draw_func;
109 new_node->sel_func = select_func;
111 new_node->whichend = whichend;
113 if (!toplevel->ADDING_SEL) {
114 s_tile_add_object (toplevel, new_node);
115 s_conn_update_object (toplevel, new_node);
118 return new_node;
121 /*! \brief recalc the visual properties of a pin object
122 * \par Function Description
123 * This function updates the visual coords of the \a o_current object.
125 * \param [in] toplevel The TOPLEVEL object.
126 * \param [in] o_current a pin object.
129 void o_pin_recalc(TOPLEVEL *toplevel, OBJECT *o_current)
131 int left, right, top, bottom;
133 if (o_current->line == NULL) {
134 return;
137 world_get_pin_bounds(toplevel, o_current, &left, &top, &right, &bottom);
139 o_current->w_left = left;
140 o_current->w_top = top;
141 o_current->w_right = right;
142 o_current->w_bottom = bottom;
143 o_current->w_bounds_valid = TRUE;
146 /*! \brief read a pin object from a char buffer
147 * \par Function Description
148 * This function reads a pin object from the buffer \a buf.
149 * If the pin object was read successfully, a new pin object is
150 * allocated and appended to the \a object_list.
152 * \param [in] toplevel The TOPLEVEL object
153 * \param [in] object_list list of OBJECTS to append a new pin
154 * \param [in] buf a text buffer (usually a line of a schematic file)
155 * \param [in] release_ver The release number gEDA
156 * \param [in] fileformat_ver a integer value of the file format
157 * \return The object list
159 OBJECT *o_pin_read (TOPLEVEL *toplevel, char buf[],
160 unsigned int release_ver, unsigned int fileformat_ver)
162 OBJECT *new_obj;
163 char type;
164 int x1, y1;
165 int x2, y2;
166 int color;
167 int pin_type;
168 int whichend;
170 if (release_ver <= VERSION_20020825) {
171 sscanf (buf, "%c %d %d %d %d %d\n", &type, &x1, &y1, &x2, &y2, &color);
172 pin_type = PIN_TYPE_NET;
173 whichend = -1;
174 } else {
175 sscanf (buf, "%c %d %d %d %d %d %d %d\n", &type, &x1, &y1, &x2, &y2,
176 &color, &pin_type, &whichend);
179 if (whichend == -1) {
180 s_log_message (_("Found a pin which did not have the whichone field set.\n"
181 "Verify and correct manually.\n"));
182 } else if (whichend < -1 || whichend > 1) {
183 s_log_message (_("Found an invalid whichend on a pin (reseting to zero): %d\n"),
184 whichend);
185 whichend = 0;
188 if (x1 == x2 && y1 == y2) {
189 s_log_message (_("Found a zero length pin: [ %s ]\n"), buf);
192 if (color < 0 || color > MAX_COLORS) {
193 s_log_message (_("Found an invalid color [ %s ]\n"), buf);
194 s_log_message (_("Setting color to default color\n"));
195 color = DEFAULT_COLOR;
198 if (toplevel->override_pin_color != -1) {
199 color = toplevel->override_pin_color;
202 new_obj = o_pin_new (toplevel, type, color, x1, y1, x2, y2,
203 pin_type, whichend);
205 return new_obj;
208 /*! \brief Create a string representation of the pin object
209 * \par Function Description
210 * This function takes a pin \a object and return a string
211 * according to the file format definition.
213 * \param [in] object a pin OBJECT
214 * \return the string representation of the pin OBJECT
216 char *o_pin_save(OBJECT *object)
218 int x1, x2, y1, y2;
219 int pin_type, whichend;
220 char *buf;
222 x1 = object->line->x[0];
223 y1 = object->line->y[0];
224 x2 = object->line->x[1];
225 y2 = object->line->y[1];
227 pin_type = object->pin_type;
228 whichend = object->whichend;
230 buf = g_strdup_printf("%c %d %d %d %d %d %d %d", object->type,
231 x1, y1, x2, y2, object->color, pin_type, whichend);
232 return(buf);
235 /*! \brief move a pin object
236 * \par Function Description
237 * This function changes the position of a pin \a object.
239 * \param [in] toplevel The TOPLEVEL object
240 * \param [in] dx The x-distance to move the object
241 * \param [in] dy The y-distance to move the object
242 * \param [in] object The pin OBJECT to be moved
244 void o_pin_translate_world(TOPLEVEL *toplevel, int dx, int dy, OBJECT *object)
246 if (object == NULL) printf("ptw NO!\n");
249 /* Update world coords */
250 object->line->x[0] = object->line->x[0] + dx;
251 object->line->y[0] = object->line->y[0] + dy;
252 object->line->x[1] = object->line->x[1] + dx;
253 object->line->y[1] = object->line->y[1] + dy;
255 /* Update bounding box */
256 o_pin_recalc (toplevel, object);
258 s_tile_update_object(toplevel, object);
261 /*! \brief create a copy of a pin object
262 * \par Function Description
263 * This function creates a copy of the pin object \a o_current.
265 * \param [in] toplevel The TOPLEVEL object
266 * \param [in] o_current The object that is copied
267 * \return a new pin object
269 OBJECT *o_pin_copy(TOPLEVEL *toplevel, OBJECT *o_current)
271 OBJECT *new_obj;
273 new_obj = o_pin_new (toplevel, OBJ_PIN, o_current->color,
274 o_current->line->x[0], o_current->line->y[0],
275 o_current->line->x[1], o_current->line->y[1],
276 o_current->pin_type, o_current->whichend);
278 return new_obj;
281 /*! \brief postscript print command for a pin object
282 * \par Function Description
283 * This function writes the postscript command of the pin object \a o_current
284 * into the FILE \a fp points to.
286 * \param [in] toplevel The TOPLEVEL object
287 * \param [in] fp pointer to a FILE structure
288 * \param [in] o_current The OBJECT to print
289 * \param [in] origin_x x-coord of the postscript origin
290 * \param [in] origin_y y-coord of the postscript origin
292 void o_pin_print(TOPLEVEL *toplevel, FILE *fp, OBJECT *o_current,
293 int origin_x, int origin_y)
295 int pin_width;
296 int x1, y1;
297 int x2, y2;
299 if (o_current == NULL) {
300 printf("got null in o_pin_print\n");
301 return;
304 f_print_set_color(toplevel, fp, o_current->color);
306 x1 = o_current->line->x[0] - origin_x;
307 y1 = o_current->line->y[0] - origin_y;
308 x2 = o_current->line->x[1] - origin_x;
309 y2 = o_current->line->y[1] - origin_y;
310 pin_width = 2;
311 if(toplevel->pin_style == THICK) {
312 pin_width = o_current->line_width;
315 fprintf(fp, "%d %d %d %d %d line\n",x1,y1,x2,y2,pin_width);
319 /*! \brief rotate a pin object around a centerpoint
320 * \par Function Description
321 * This function rotates a pin \a object around the point
322 * (\a world_centerx, \a world_centery).
324 * \param [in] toplevel The TOPLEVEL object
325 * \param [in] world_centerx x-coord of the rotation center
326 * \param [in] world_centery y-coord of the rotation center
327 * \param [in] angle The angle to rotat the pin object
328 * \param [in] object The pin object
329 * \note only steps of 90 degrees are allowed for the \a angle
331 void o_pin_rotate_world(TOPLEVEL *toplevel, int world_centerx,
332 int world_centery, int angle,
333 OBJECT *object)
335 int newx, newy;
337 if (angle == 0)
338 return;
340 /* translate object to origin */
341 o_pin_translate_world(toplevel, -world_centerx, -world_centery, object);
343 rotate_point_90(object->line->x[0], object->line->y[0], angle,
344 &newx, &newy);
346 object->line->x[0] = newx;
347 object->line->y[0] = newy;
349 rotate_point_90(object->line->x[1], object->line->y[1], angle,
350 &newx, &newy);
352 object->line->x[1] = newx;
353 object->line->y[1] = newy;
355 o_pin_translate_world(toplevel, world_centerx, world_centery, object);
358 /*! \brief mirror a pin object horizontaly at a centerpoint
359 * \par Function Description
360 * This function mirrors a pin \a object horizontaly at the point
361 * (\a world_centerx, \a world_centery).
363 * \param [in] toplevel The TOPLEVEL object
364 * \param [in] world_centerx x-coord of the mirror position
365 * \param [in] world_centery y-coord of the mirror position
366 * \param [in] object The pin object
368 void o_pin_mirror_world(TOPLEVEL *toplevel,
369 int world_centerx, int world_centery, OBJECT *object)
371 /* translate object to origin */
372 o_pin_translate_world(toplevel, -world_centerx, -world_centery, object);
374 object->line->x[0] = -object->line->x[0];
376 object->line->x[1] = -object->line->x[1];
378 o_pin_translate_world(toplevel, world_centerx, world_centery, object);
381 /*! \brief modify one point of a pin object
382 * \par Function Description
383 * This function modifies one point of a pin \a object. The point
384 * is specified by the \a whichone variable and the new coordinate
385 * is (\a x, \a y).
387 * \param toplevel The TOPLEVEL object
388 * \param object The pin OBJECT to modify
389 * \param x new x-coord of the pin point
390 * \param y new y-coord of the pin point
391 * \param whichone pin point to modify
394 void o_pin_modify(TOPLEVEL *toplevel, OBJECT *object,
395 int x, int y, int whichone)
397 object->line->x[whichone] = x;
398 object->line->y[whichone] = y;
400 o_pin_recalc (toplevel, object);
402 s_tile_update_object(toplevel, object);
405 /*! \brief guess the whichend of pins of object list
406 * \par Function Description
407 * This function determines the whichend of the pins in the \a object_list.
408 * In older libgeda file format versions there was no information about the
409 * active end of pins.
410 * This function calculates the bounding box of all pins in the object list.
411 * The side of the pins that are closer to the boundary of the box are
412 * set as active ends of the pins.
414 * \param toplevel The TOPLEVEL object
415 * \param object_list list of OBJECTs
416 * \param num_pins pin count in the object list
419 void o_pin_update_whichend(TOPLEVEL *toplevel,
420 GList *object_list, int num_pins)
422 OBJECT *o_current;
423 GList *iter;
424 int top = 0, left = 0;
425 int right = 0, bottom = 0;
426 int d1, d2, d3, d4;
427 int min0, min1;
428 int min0_whichend, min1_whichend;
429 int rleft, rtop, rright, rbottom;
430 int found;
432 if (object_list && num_pins) {
433 if (num_pins == 1 || toplevel->force_boundingbox) {
434 world_get_object_glist_bounds (toplevel, object_list,
435 &left, &top, &right, &bottom);
436 } else {
437 found = 0;
439 /* only look at the pins to calculate bounds of the symbol */
440 iter = object_list;
441 while (iter != NULL) {
442 o_current = (OBJECT *)iter->data;
443 if (o_current->type == OBJ_PIN) {
444 rleft = o_current->w_left;
445 rtop = o_current->w_top;
446 rright = o_current->w_right;
447 rbottom = o_current->w_bottom;
449 if ( found ) {
450 left = min( left, rleft );
451 top = min( top, rtop );
452 right = max( right, rright );
453 bottom = max( bottom, rbottom );
454 } else {
455 left = rleft;
456 top = rtop;
457 right = rright;
458 bottom = rbottom;
459 found = 1;
462 iter = g_list_next (iter);
466 } else {
467 return;
470 iter = object_list;
471 while (iter != NULL) {
472 o_current = (OBJECT *)iter->data;
473 /* Determine which end of the pin is on or nearest the boundary */
474 if (o_current->type == OBJ_PIN && o_current->whichend == -1) {
475 if (o_current->line->y[0] == o_current->line->y[1]) {
476 /* horizontal */
478 if (o_current->line->x[0] == left) {
479 o_current->whichend = 0;
480 } else if (o_current->line->x[1] == left) {
481 o_current->whichend = 1;
482 } else if (o_current->line->x[0] == right) {
483 o_current->whichend = 0;
484 } else if (o_current->line->x[1] == right) {
485 o_current->whichend = 1;
486 } else {
488 d1 = abs(o_current->line->x[0] - left);
489 d2 = abs(o_current->line->x[1] - left);
490 d3 = abs(o_current->line->x[0] - right);
491 d4 = abs(o_current->line->x[1] - right);
493 if (d1 <= d2) {
494 min0 = d1;
495 min0_whichend = 0;
496 } else {
497 min0 = d2;
498 min0_whichend = 1;
501 if (d3 <= d4) {
502 min1 = d3;
503 min1_whichend = 0;
504 } else {
505 min1 = d4;
506 min1_whichend = 1;
509 if (min0 <= min1) {
510 o_current->whichend = min0_whichend;
511 } else {
512 o_current->whichend = min1_whichend;
516 } else if (o_current->line->x[0] == o_current->line->x[1]) {
517 /* vertical */
519 if (o_current->line->y[0] == top) {
520 o_current->whichend = 0;
521 } else if (o_current->line->y[1] == top) {
522 o_current->whichend = 1;
523 } else if (o_current->line->x[0] == bottom) {
524 o_current->whichend = 0;
525 } else if (o_current->line->x[1] == bottom) {
526 o_current->whichend = 1;
527 } else {
529 d1 = abs(o_current->line->y[0] - top);
530 d2 = abs(o_current->line->y[1] - top);
531 d3 = abs(o_current->line->y[0] - bottom);
532 d4 = abs(o_current->line->y[1] - bottom);
534 if (d1 <= d2) {
535 min0 = d1;
536 min0_whichend = 0;
537 } else {
538 min0 = d2;
539 min0_whichend = 1;
542 if (d3 <= d4) {
543 min1 = d3;
544 min1_whichend = 0;
545 } else {
546 min1 = d4;
547 min1_whichend = 1;
550 if (min0 <= min1) {
551 o_current->whichend = min0_whichend;
552 } else {
553 o_current->whichend = min1_whichend;
558 iter = g_list_next (iter);
563 /*! \brief Sets the type, and corresponding width of a pin
565 * \par Function Description
566 * Sets the pin's type and width to a particular style.
568 * \param [in] toplevel The TOPLEVEL object
569 * \param [in] o_current The pin OBJECT being modified
570 * \param [in] type The new type of this pin
572 void o_pin_set_type (TOPLEVEL *toplevel, OBJECT *o_current, int pin_type)
574 switch (pin_type) {
575 default:
576 g_critical ("o_pin_set_type: Got invalid pin type %i\n", pin_type);
577 /* Fall through */
578 case PIN_TYPE_NET:
579 o_current->line_width = PIN_WIDTH_NET;
580 o_current->pin_type = PIN_TYPE_NET;
581 break;
582 case PIN_TYPE_BUS:
583 o_current->line_width = PIN_WIDTH_BUS;
584 o_current->pin_type = PIN_TYPE_BUS;
585 break;