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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 #include "libgeda_priv.h"
27 #ifdef HAVE_LIBDMALLOC
31 /*! \file o_pin_basic.c
32 * \brief functions for the pin object
35 /*! \brief calculate and return the boundaries of a pin object
36 * \par Function Description
37 * This function calculates the object boudaries of a pin \a object.
39 * \param [in] toplevel The TOPLEVEL object.
40 * \param [in] object a pin object
41 * \param [out] left the left world coord
42 * \param [out] top the top world coord
43 * \param [out] right the right world coord
44 * \param [out] bottom the bottom world coord
46 void world_get_pin_bounds(TOPLEVEL
*toplevel
, OBJECT
*object
, int *left
, int *top
,
47 int *right
, int *bottom
)
49 world_get_line_bounds( toplevel
, object
, left
, top
, right
, bottom
);
52 /*! \brief get the position of a whichend of the pin object
53 * \par Function Description
54 * This function gets the position of the whichend side of a pin object.
56 * \param [in] toplevel The toplevel environment.
57 * \param [out] x pointer to the x-position
58 * \param [out] y pointer to the y-position
59 * \param [in] object The object to get the position.
60 * \return TRUE if successfully determined the position, FALSE otherwise
62 gboolean
o_pin_get_position (TOPLEVEL
*toplevel
, gint
*x
, gint
*y
,
65 *x
= object
->line
->x
[object
->whichend
];
66 *y
= object
->line
->y
[object
->whichend
];
70 /*! \brief create a new pin object
71 * \par Function Description
72 * This function creates and returns a new pin object.
74 * \param [in] toplevel The TOPLEVEL object.
75 * \param [in] type The OBJECT type (usually OBJ_PIN)
76 * \param [in] color The color of the pin
77 * \param [in] x1 x-coord of the first point
78 * \param [in] y1 y-coord of the first point
79 * \param [in] x2 x-coord of the second point
80 * \param [in] y2 y-coord of the second point
81 * \param [in] pin_type type of pin (PIN_TYPE_NET or PIN_TYPE_BUS)
82 * \param [in] whichend The connectable end of the pin
83 * \return A new pin OBJECT
85 OBJECT
*o_pin_new(TOPLEVEL
*toplevel
,
87 int x1
, int y1
, int x2
, int y2
, int pin_type
, int whichend
)
91 new_node
= s_basic_new_object(type
, "pin");
92 new_node
->color
= color
;
94 new_node
->line
= (LINE
*) g_malloc(sizeof(LINE
));
96 new_node
->line
->x
[0] = x1
;
97 new_node
->line
->y
[0] = y1
;
98 new_node
->line
->x
[1] = x2
;
99 new_node
->line
->y
[1] = y2
;
101 o_pin_set_type (toplevel
, new_node
, pin_type
);
103 o_pin_recalc (toplevel
, new_node
);
105 new_node
->whichend
= whichend
;
110 /*! \brief recalc the visual properties of a pin object
111 * \par Function Description
112 * This function updates the visual coords of the \a o_current object.
114 * \param [in] toplevel The TOPLEVEL object.
115 * \param [in] o_current a pin object.
118 void o_pin_recalc(TOPLEVEL
*toplevel
, OBJECT
*o_current
)
120 int left
, right
, top
, bottom
;
122 if (o_current
->line
== NULL
) {
126 world_get_pin_bounds(toplevel
, o_current
, &left
, &top
, &right
, &bottom
);
128 o_current
->w_left
= left
;
129 o_current
->w_top
= top
;
130 o_current
->w_right
= right
;
131 o_current
->w_bottom
= bottom
;
132 o_current
->w_bounds_valid
= TRUE
;
135 /*! \brief read a pin object from a char buffer
136 * \par Function Description
137 * This function reads a pin object from the buffer \a buf.
138 * If the pin object was read successfully, a new pin object is
139 * allocated and appended to the \a object_list.
141 * \param [in] toplevel The TOPLEVEL object
142 * \param [in] buf a text buffer (usually a line of a schematic file)
143 * \param [in] release_ver The release number gEDA
144 * \param [in] fileformat_ver a integer value of the file format
145 * \return The object list
147 OBJECT
*o_pin_read (TOPLEVEL
*toplevel
, char buf
[],
148 unsigned int release_ver
, unsigned int fileformat_ver
)
158 if (release_ver
<= VERSION_20020825
) {
159 sscanf (buf
, "%c %d %d %d %d %d\n", &type
, &x1
, &y1
, &x2
, &y2
, &color
);
160 pin_type
= PIN_TYPE_NET
;
163 sscanf (buf
, "%c %d %d %d %d %d %d %d\n", &type
, &x1
, &y1
, &x2
, &y2
,
164 &color
, &pin_type
, &whichend
);
167 if (whichend
== -1) {
168 s_log_message (_("Found a pin which did not have the whichone field set.\n"
169 "Verify and correct manually.\n"));
170 } else if (whichend
< -1 || whichend
> 1) {
171 s_log_message (_("Found an invalid whichend on a pin (reseting to zero): %d\n"),
176 if (color
< 0 || color
> MAX_COLORS
) {
177 s_log_message (_("Found an invalid color [ %s ]\n"), buf
);
178 s_log_message (_("Setting color to default color\n"));
179 color
= DEFAULT_COLOR
;
182 if (toplevel
->override_pin_color
!= -1) {
183 color
= toplevel
->override_pin_color
;
186 new_obj
= o_pin_new (toplevel
, type
, color
, x1
, y1
, x2
, y2
,
192 /*! \brief Create a string representation of the pin object
193 * \par Function Description
194 * This function takes a pin \a object and return a string
195 * according to the file format definition.
197 * \param [in] toplevel a TOPLEVEL structure
198 * \param [in] object a pin OBJECT
199 * \return the string representation of the pin OBJECT
201 char *o_pin_save(TOPLEVEL
*toplevel
, OBJECT
*object
)
204 int pin_type
, whichend
;
207 x1
= object
->line
->x
[0];
208 y1
= object
->line
->y
[0];
209 x2
= object
->line
->x
[1];
210 y2
= object
->line
->y
[1];
212 pin_type
= object
->pin_type
;
213 whichend
= object
->whichend
;
215 buf
= g_strdup_printf("%c %d %d %d %d %d %d %d", object
->type
,
216 x1
, y1
, x2
, y2
, object
->color
, pin_type
, whichend
);
220 /*! \brief move a pin object
221 * \par Function Description
222 * This function changes the position of a pin \a object.
224 * \param [in] toplevel The TOPLEVEL object
225 * \param [in] dx The x-distance to move the object
226 * \param [in] dy The y-distance to move the object
227 * \param [in] object The pin OBJECT to be moved
229 void o_pin_translate_world(TOPLEVEL
*toplevel
, int dx
, int dy
, OBJECT
*object
)
231 if (object
== NULL
) printf("ptw NO!\n");
234 /* Update world coords */
235 object
->line
->x
[0] = object
->line
->x
[0] + dx
;
236 object
->line
->y
[0] = object
->line
->y
[0] + dy
;
237 object
->line
->x
[1] = object
->line
->x
[1] + dx
;
238 object
->line
->y
[1] = object
->line
->y
[1] + dy
;
240 /* Update bounding box */
241 o_pin_recalc (toplevel
, object
);
243 s_tile_update_object(toplevel
, object
);
246 /*! \brief create a copy of a pin object
247 * \par Function Description
248 * This function creates a copy of the pin object \a o_current.
250 * \param [in] toplevel The TOPLEVEL object
251 * \param [in] o_current The object that is copied
252 * \return a new pin object
254 OBJECT
*o_pin_copy(TOPLEVEL
*toplevel
, OBJECT
*o_current
)
258 new_obj
= o_pin_new (toplevel
, OBJ_PIN
, o_current
->color
,
259 o_current
->line
->x
[0], o_current
->line
->y
[0],
260 o_current
->line
->x
[1], o_current
->line
->y
[1],
261 o_current
->pin_type
, o_current
->whichend
);
266 /*! \brief postscript print command for a pin object
267 * \par Function Description
268 * This function writes the postscript command of the pin object \a o_current
269 * into the FILE \a fp points to.
271 * \param [in] toplevel The TOPLEVEL object
272 * \param [in] fp pointer to a FILE structure
273 * \param [in] o_current The OBJECT to print
274 * \param [in] origin_x x-coord of the postscript origin
275 * \param [in] origin_y y-coord of the postscript origin
277 void o_pin_print(TOPLEVEL
*toplevel
, FILE *fp
, OBJECT
*o_current
,
278 int origin_x
, int origin_y
)
284 if (o_current
== NULL
) {
285 printf("got null in o_pin_print\n");
289 f_print_set_color(toplevel
, fp
, o_current
->color
);
291 x1
= o_current
->line
->x
[0] - origin_x
;
292 y1
= o_current
->line
->y
[0] - origin_y
;
293 x2
= o_current
->line
->x
[1] - origin_x
;
294 y2
= o_current
->line
->y
[1] - origin_y
;
296 if(toplevel
->pin_style
== THICK
) {
297 pin_width
= o_current
->line_width
;
300 fprintf(fp
, "%d %d %d %d %d line\n",x1
,y1
,x2
,y2
,pin_width
);
304 /*! \brief rotate a pin object around a centerpoint
305 * \par Function Description
306 * This function rotates a pin \a object around the point
307 * (\a world_centerx, \a world_centery).
309 * \param [in] toplevel The TOPLEVEL object
310 * \param [in] world_centerx x-coord of the rotation center
311 * \param [in] world_centery y-coord of the rotation center
312 * \param [in] angle The angle to rotat the pin object
313 * \param [in] object The pin object
314 * \note only steps of 90 degrees are allowed for the \a angle
316 void o_pin_rotate_world(TOPLEVEL
*toplevel
, int world_centerx
,
317 int world_centery
, int angle
,
325 /* translate object to origin */
326 o_pin_translate_world(toplevel
, -world_centerx
, -world_centery
, object
);
328 rotate_point_90(object
->line
->x
[0], object
->line
->y
[0], angle
,
331 object
->line
->x
[0] = newx
;
332 object
->line
->y
[0] = newy
;
334 rotate_point_90(object
->line
->x
[1], object
->line
->y
[1], angle
,
337 object
->line
->x
[1] = newx
;
338 object
->line
->y
[1] = newy
;
340 o_pin_translate_world(toplevel
, world_centerx
, world_centery
, object
);
343 /*! \brief mirror a pin object horizontaly at a centerpoint
344 * \par Function Description
345 * This function mirrors a pin \a object horizontaly at the point
346 * (\a world_centerx, \a world_centery).
348 * \param [in] toplevel The TOPLEVEL object
349 * \param [in] world_centerx x-coord of the mirror position
350 * \param [in] world_centery y-coord of the mirror position
351 * \param [in] object The pin object
353 void o_pin_mirror_world(TOPLEVEL
*toplevel
,
354 int world_centerx
, int world_centery
, OBJECT
*object
)
356 /* translate object to origin */
357 o_pin_translate_world(toplevel
, -world_centerx
, -world_centery
, object
);
359 object
->line
->x
[0] = -object
->line
->x
[0];
361 object
->line
->x
[1] = -object
->line
->x
[1];
363 o_pin_translate_world(toplevel
, world_centerx
, world_centery
, object
);
366 /*! \brief modify one point of a pin object
367 * \par Function Description
368 * This function modifies one point of a pin \a object. The point
369 * is specified by the \a whichone variable and the new coordinate
372 * \param toplevel The TOPLEVEL object
373 * \param object The pin OBJECT to modify
374 * \param x new x-coord of the pin point
375 * \param y new y-coord of the pin point
376 * \param whichone pin point to modify
379 void o_pin_modify(TOPLEVEL
*toplevel
, OBJECT
*object
,
380 int x
, int y
, int whichone
)
382 object
->line
->x
[whichone
] = x
;
383 object
->line
->y
[whichone
] = y
;
385 o_pin_recalc (toplevel
, object
);
387 s_tile_update_object(toplevel
, object
);
390 /*! \brief guess the whichend of pins of object list
391 * \par Function Description
392 * This function determines the whichend of the pins in the \a object_list.
393 * In older libgeda file format versions there was no information about the
394 * active end of pins.
395 * This function calculates the bounding box of all pins in the object list.
396 * The side of the pins that are closer to the boundary of the box are
397 * set as active ends of the pins.
399 * \param toplevel The TOPLEVEL object
400 * \param object_list list of OBJECTs
401 * \param num_pins pin count in the object list
404 void o_pin_update_whichend(TOPLEVEL
*toplevel
,
405 GList
*object_list
, int num_pins
)
409 int top
= 0, left
= 0;
410 int right
= 0, bottom
= 0;
413 int min0_whichend
, min1_whichend
;
414 int rleft
, rtop
, rright
, rbottom
;
417 if (object_list
&& num_pins
) {
418 if (num_pins
== 1 || toplevel
->force_boundingbox
) {
419 world_get_object_glist_bounds (toplevel
, object_list
,
420 &left
, &top
, &right
, &bottom
);
424 /* only look at the pins to calculate bounds of the symbol */
426 while (iter
!= NULL
) {
427 o_current
= (OBJECT
*)iter
->data
;
428 if (o_current
->type
== OBJ_PIN
) {
429 rleft
= o_current
->w_left
;
430 rtop
= o_current
->w_top
;
431 rright
= o_current
->w_right
;
432 rbottom
= o_current
->w_bottom
;
435 left
= min( left
, rleft
);
436 top
= min( top
, rtop
);
437 right
= max( right
, rright
);
438 bottom
= max( bottom
, rbottom
);
447 iter
= g_list_next (iter
);
456 while (iter
!= NULL
) {
457 o_current
= (OBJECT
*)iter
->data
;
458 /* Determine which end of the pin is on or nearest the boundary */
459 if (o_current
->type
== OBJ_PIN
&& o_current
->whichend
== -1) {
460 if (o_current
->line
->y
[0] == o_current
->line
->y
[1]) {
463 if (o_current
->line
->x
[0] == left
) {
464 o_current
->whichend
= 0;
465 } else if (o_current
->line
->x
[1] == left
) {
466 o_current
->whichend
= 1;
467 } else if (o_current
->line
->x
[0] == right
) {
468 o_current
->whichend
= 0;
469 } else if (o_current
->line
->x
[1] == right
) {
470 o_current
->whichend
= 1;
473 d1
= abs(o_current
->line
->x
[0] - left
);
474 d2
= abs(o_current
->line
->x
[1] - left
);
475 d3
= abs(o_current
->line
->x
[0] - right
);
476 d4
= abs(o_current
->line
->x
[1] - right
);
495 o_current
->whichend
= min0_whichend
;
497 o_current
->whichend
= min1_whichend
;
501 } else if (o_current
->line
->x
[0] == o_current
->line
->x
[1]) {
504 if (o_current
->line
->y
[0] == top
) {
505 o_current
->whichend
= 0;
506 } else if (o_current
->line
->y
[1] == top
) {
507 o_current
->whichend
= 1;
508 } else if (o_current
->line
->x
[0] == bottom
) {
509 o_current
->whichend
= 0;
510 } else if (o_current
->line
->x
[1] == bottom
) {
511 o_current
->whichend
= 1;
514 d1
= abs(o_current
->line
->y
[0] - top
);
515 d2
= abs(o_current
->line
->y
[1] - top
);
516 d3
= abs(o_current
->line
->y
[0] - bottom
);
517 d4
= abs(o_current
->line
->y
[1] - bottom
);
536 o_current
->whichend
= min0_whichend
;
538 o_current
->whichend
= min1_whichend
;
543 iter
= g_list_next (iter
);
548 /*! \brief Sets the type, and corresponding width of a pin
550 * \par Function Description
551 * Sets the pin's type and width to a particular style.
553 * \param [in] toplevel The TOPLEVEL object
554 * \param [in] o_current The pin OBJECT being modified
555 * \param [in] pin_type The new type of this pin
557 void o_pin_set_type (TOPLEVEL
*toplevel
, OBJECT
*o_current
, int pin_type
)
559 o_emit_pre_change_notify (toplevel
, o_current
);
562 g_critical ("o_pin_set_type: Got invalid pin type %i\n", pin_type
);
565 o_current
->line_width
= PIN_WIDTH_NET
;
566 o_current
->pin_type
= PIN_TYPE_NET
;
569 o_current
->line_width
= PIN_WIDTH_BUS
;
570 o_current
->pin_type
= PIN_TYPE_BUS
;
573 o_emit_change_notify (toplevel
, o_current
);