libgeda: Make sure paths are set up during initialisation.
[geda-gaf/whiteaudio.git] / libgeda / src / o_pin_basic.c
blobef91efb908d60662daf35b3d24a9f3b5bc0757ff
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
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 /*! \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,
63 OBJECT *object)
65 *x = object->line->x[object->whichend];
66 *y = object->line->y[object->whichend];
67 return TRUE;
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,
86 char type, int color,
87 int x1, int y1, int x2, int y2, int pin_type, int whichend)
89 OBJECT *new_node;
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;
107 return new_node;
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) {
123 return;
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)
150 OBJECT *new_obj;
151 char type;
152 int x1, y1;
153 int x2, y2;
154 int color;
155 int pin_type;
156 int whichend;
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;
161 whichend = -1;
162 } else {
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"),
172 whichend);
173 whichend = 0;
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,
187 pin_type, whichend);
189 return new_obj;
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)
203 int x1, x2, y1, y2;
204 int pin_type, whichend;
205 char *buf;
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);
217 return(buf);
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)
256 OBJECT *new_obj;
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);
263 return new_obj;
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)
280 int pin_width;
281 int x1, y1;
282 int x2, y2;
284 if (o_current == NULL) {
285 printf("got null in o_pin_print\n");
286 return;
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;
295 pin_width = 2;
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,
318 OBJECT *object)
320 int newx, newy;
322 if (angle == 0)
323 return;
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,
329 &newx, &newy);
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,
335 &newx, &newy);
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
370 * is (\a x, \a y).
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)
407 OBJECT *o_current;
408 GList *iter;
409 int top = 0, left = 0;
410 int right = 0, bottom = 0;
411 int d1, d2, d3, d4;
412 int min0, min1;
413 int min0_whichend, min1_whichend;
414 int rleft, rtop, rright, rbottom;
415 int found;
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);
421 } else {
422 found = 0;
424 /* only look at the pins to calculate bounds of the symbol */
425 iter = object_list;
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;
434 if ( found ) {
435 left = min( left, rleft );
436 top = min( top, rtop );
437 right = max( right, rright );
438 bottom = max( bottom, rbottom );
439 } else {
440 left = rleft;
441 top = rtop;
442 right = rright;
443 bottom = rbottom;
444 found = 1;
447 iter = g_list_next (iter);
451 } else {
452 return;
455 iter = object_list;
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]) {
461 /* horizontal */
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;
471 } else {
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);
478 if (d1 <= d2) {
479 min0 = d1;
480 min0_whichend = 0;
481 } else {
482 min0 = d2;
483 min0_whichend = 1;
486 if (d3 <= d4) {
487 min1 = d3;
488 min1_whichend = 0;
489 } else {
490 min1 = d4;
491 min1_whichend = 1;
494 if (min0 <= min1) {
495 o_current->whichend = min0_whichend;
496 } else {
497 o_current->whichend = min1_whichend;
501 } else if (o_current->line->x[0] == o_current->line->x[1]) {
502 /* vertical */
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;
512 } else {
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);
519 if (d1 <= d2) {
520 min0 = d1;
521 min0_whichend = 0;
522 } else {
523 min0 = d2;
524 min0_whichend = 1;
527 if (d3 <= d4) {
528 min1 = d3;
529 min1_whichend = 0;
530 } else {
531 min1 = d4;
532 min1_whichend = 1;
535 if (min0 <= min1) {
536 o_current->whichend = min0_whichend;
537 } else {
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);
560 switch (pin_type) {
561 default:
562 g_critical ("o_pin_set_type: Got invalid pin type %i\n", pin_type);
563 /* Fall through */
564 case PIN_TYPE_NET:
565 o_current->line_width = PIN_WIDTH_NET;
566 o_current->pin_type = PIN_TYPE_NET;
567 break;
568 case PIN_TYPE_BUS:
569 o_current->line_width = PIN_WIDTH_BUS;
570 o_current->pin_type = PIN_TYPE_BUS;
571 break;
573 o_emit_change_notify (toplevel, o_current);