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
25 #include "libgeda_priv.h"
27 #ifdef HAVE_LIBDMALLOC
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
,
68 *x
= object
->line
->x
[object
->whichend
];
69 *y
= object
->line
->y
[object
->whichend
];
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
,
90 int x1
, int y1
, int x2
, int y2
, int pin_type
, int whichend
)
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
);
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
) {
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
)
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
;
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"),
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
,
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
)
219 int pin_type
, whichend
;
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
);
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
)
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
);
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
)
299 if (o_current
== NULL
) {
300 printf("got null in o_pin_print\n");
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
;
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
,
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
,
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
,
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
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
)
424 int top
= 0, left
= 0;
425 int right
= 0, bottom
= 0;
428 int min0_whichend
, min1_whichend
;
429 int rleft
, rtop
, rright
, rbottom
;
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
);
439 /* only look at the pins to calculate bounds of the symbol */
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
;
450 left
= min( left
, rleft
);
451 top
= min( top
, rtop
);
452 right
= max( right
, rright
);
453 bottom
= max( bottom
, rbottom
);
462 iter
= g_list_next (iter
);
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]) {
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;
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
);
510 o_current
->whichend
= min0_whichend
;
512 o_current
->whichend
= min1_whichend
;
516 } else if (o_current
->line
->x
[0] == o_current
->line
->x
[1]) {
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;
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
);
551 o_current
->whichend
= min0_whichend
;
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
)
576 g_critical ("o_pin_set_type: Got invalid pin type %i\n", pin_type
);
579 o_current
->line_width
= PIN_WIDTH_NET
;
580 o_current
->pin_type
= PIN_TYPE_NET
;
583 o_current
->line_width
= PIN_WIDTH_BUS
;
584 o_current
->pin_type
= PIN_TYPE_BUS
;