libgeda

o_bus_basic.c

Go to the documentation of this file.
00001 /* gEDA - GPL Electronic Design Automation
00002  * libgeda - gEDA's library
00003  * Copyright (C) 1998-2010 Ales Hvezda
00004  * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details)
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00019  */
00020 
00025 #include <config.h>
00026 #include <stdio.h>
00027 #include <math.h>
00028 
00029 #include "libgeda_priv.h"
00030 
00031 #ifdef HAVE_LIBDMALLOC
00032 #include <dmalloc.h>
00033 #endif
00034 
00045 gboolean o_bus_get_position (TOPLEVEL *toplevel, gint *x, gint *y,
00046                               OBJECT *object)
00047 {
00048   return o_line_get_position(toplevel, x, y, object);
00049 }
00050 
00062 void world_get_bus_bounds(TOPLEVEL *toplevel, OBJECT *object, int *left, int *top,
00063               int *right, int *bottom)
00064 {
00065   world_get_line_bounds( toplevel, object, left, top, right, bottom );
00066 }
00067 
00082 OBJECT *o_bus_new(TOPLEVEL *toplevel,
00083           char type, int color,
00084           int x1, int y1, int x2, int y2,
00085           int bus_ripper_direction)
00086 {
00087   OBJECT *new_node;
00088 
00089   new_node = s_basic_new_object(type, "bus");
00090   new_node->color = color;
00091 
00092   new_node->line = (LINE *) g_malloc(sizeof(LINE));
00093   /* check for null */  
00094 
00095   new_node->line->x[0] = x1;
00096   new_node->line->y[0] = y1;
00097   new_node->line->x[1] = x2;
00098   new_node->line->y[1] = y2;
00099   new_node->line_width = BUS_WIDTH;
00100 
00101   new_node->bus_ripper_direction = bus_ripper_direction;
00102 
00103   o_bus_recalc (toplevel, new_node);
00104 
00105   return new_node;
00106 }
00107 
00115 void o_bus_recalc(TOPLEVEL *toplevel, OBJECT *o_current)
00116 {
00117   int left, right, top, bottom;
00118 
00119   if (o_current == NULL) {
00120     return;
00121   }
00122 
00123   if (o_current->line == NULL) {
00124     return;
00125   }
00126 
00127   world_get_bus_bounds(toplevel, o_current, &left, &top, &right, &bottom);
00128 
00129   o_current->w_left = left;
00130   o_current->w_top = top;
00131   o_current->w_right = right;
00132   o_current->w_bottom = bottom;
00133   o_current->w_bounds_valid = TRUE;
00134 }
00135 
00148 OBJECT *o_bus_read (TOPLEVEL *toplevel, const char buf[],
00149                     unsigned int release_ver, unsigned int fileformat_ver, GError **err)
00150 {
00151   OBJECT *new_obj;
00152   char type; 
00153   int x1, y1;
00154   int x2, y2;
00155   int color;
00156   int ripper_dir;
00157 
00158   if (release_ver <= VERSION_20020825) {
00159     if (sscanf (buf, "%c %d %d %d %d %d\n", &type, &x1, &y1, &x2, &y2, &color) != 6) {
00160       g_set_error(err, EDA_ERROR, EDA_ERROR_PARSE, _("Failed to parse bus object"));
00161       return NULL;
00162     }
00163     ripper_dir = 0;
00164   } else {
00165     if (sscanf (buf, "%c %d %d %d %d %d %d\n", &type, &x1, &y1, &x2, &y2, &color,
00166         &ripper_dir) != 7) {
00167       g_set_error(err, EDA_ERROR, EDA_ERROR_PARSE, _("Failed to parse bus object"));
00168       return NULL;
00169     }
00170   }
00171 
00172   if (x1 == x2 && y1 == y2) {
00173     s_log_message (_("Found a zero length bus [ %c %d %d %d %d %d ]\n"),
00174                     type, x1, y1, x2, y2, color);
00175   }
00176 
00177   if (toplevel->override_bus_color != -1) {
00178     color = toplevel->override_bus_color;
00179   }
00180 
00181   if (color < 0 || color > MAX_COLORS) {
00182     s_log_message (_("Found an invalid color [ %s ]\n"), buf);
00183     s_log_message (_("Setting color to default color\n"));
00184     color = DEFAULT_COLOR;
00185   }
00186 
00187   if (ripper_dir < -1 || ripper_dir > 1) {
00188     s_log_message (_("Found an invalid bus ripper direction [ %s ]\n"), buf);
00189     s_log_message (_("Resetting direction to neutral (no direction)\n"));
00190     ripper_dir = 0;
00191   }
00192 
00193   new_obj = o_bus_new (toplevel, type, color, x1, y1, x2, y2, ripper_dir);
00194 
00195   return new_obj;
00196 }
00197 
00207 char *o_bus_save(TOPLEVEL *toplevel, OBJECT *object)
00208 {
00209   int x1, x2, y1, y2;
00210   char *buf;
00211 
00212   x1 = object->line->x[0];
00213   y1 = object->line->y[0];
00214   x2 = object->line->x[1];
00215   y2 = object->line->y[1];
00216 
00217   buf = g_strdup_printf("%c %d %d %d %d %d %d", object->type,
00218           x1, y1, x2, y2, object->color, object->bus_ripper_direction);
00219   return(buf);
00220 }
00221        
00231 void o_bus_translate_world(TOPLEVEL *toplevel, int dx, int dy, OBJECT *object)
00232 {
00233   /* Update world coords */
00234   object->line->x[0] = object->line->x[0] + dx;
00235   object->line->y[0] = object->line->y[0] + dy;
00236   object->line->x[1] = object->line->x[1] + dx;
00237   object->line->y[1] = object->line->y[1] + dy;
00238 
00239   /* Update bounding box */
00240   o_bus_recalc (toplevel, object);
00241 
00242   s_tile_update_object(toplevel, object);
00243 }
00244 
00253 OBJECT *o_bus_copy(TOPLEVEL *toplevel, OBJECT *o_current)
00254 {
00255   OBJECT *new_obj;
00256 
00257   /* make sure you fix this in pin and bus as well */
00258   /* still doesn't work... you need to pass in the new values */
00259   /* or don't update and update later */
00260   /* I think for now I'll disable the update and manually update */
00261   new_obj = o_bus_new (toplevel, OBJ_BUS, o_current->color,
00262                        o_current->line->x[0], o_current->line->y[0],
00263                        o_current->line->x[1], o_current->line->y[1],
00264                        o_current->bus_ripper_direction);
00265 
00266   return new_obj;
00267 }
00268 
00280 void o_bus_print(TOPLEVEL *toplevel, FILE *fp, OBJECT *o_current,
00281          int origin_x, int origin_y)
00282 {
00283   int bus_width;
00284   int x1, y1;
00285   int x2, y2;
00286 
00287   if (o_current == NULL) {
00288     printf("got null in o_bus_print\n");
00289     return;
00290   }
00291 
00292   f_print_set_color(toplevel, fp, o_current->color);
00293 
00294   bus_width = 2;
00295   if (toplevel->bus_style == THICK) {
00296     bus_width = BUS_WIDTH;  
00297   }
00298 
00299   x1 = o_current->line->x[0]-origin_x,
00300   y1 = o_current->line->y[0]-origin_y;
00301   x2 = o_current->line->x[1]-origin_x,
00302   y2 = o_current->line->y[1]-origin_y;
00303 
00304   fprintf(fp, "%d %d %d %d %d line\n",
00305       x1,y1,x2,y2,bus_width);
00306 
00307 }
00308 
00309 
00322 void o_bus_rotate_world(TOPLEVEL *toplevel,
00323             int world_centerx, int world_centery, int angle,
00324             OBJECT *object)
00325 {
00326   int newx, newy;
00327 
00328   if (angle == 0)
00329   return;
00330 
00331   /* translate object to origin */
00332   o_bus_translate_world(toplevel, -world_centerx, -world_centery, object);
00333 
00334   rotate_point_90(object->line->x[0], object->line->y[0], angle,
00335                   &newx, &newy);
00336 
00337   object->line->x[0] = newx;
00338   object->line->y[0] = newy;
00339 
00340   rotate_point_90(object->line->x[1], object->line->y[1], angle,
00341                   &newx, &newy);
00342 
00343   object->line->x[1] = newx;
00344   object->line->y[1] = newy;
00345 
00346   o_bus_translate_world(toplevel, world_centerx, world_centery, object);
00347 }
00348 
00359 void o_bus_mirror_world(TOPLEVEL *toplevel,
00360             int world_centerx, int world_centery, OBJECT *object)
00361 {
00362   /* translate object to origin */
00363   o_bus_translate_world(toplevel, -world_centerx, -world_centery, object);
00364 
00365   object->line->x[0] = -object->line->x[0];
00366 
00367   object->line->x[1] = -object->line->x[1];
00368 
00369   o_bus_translate_world(toplevel, world_centerx, world_centery, object);
00370 }
00371 
00379 int o_bus_orientation(OBJECT *object)
00380 {
00381   if (object->line->y[0] == object->line->y[1]) {
00382     return(HORIZONTAL);
00383   }
00384 
00385   if (object->line->x[0] == object->line->x[1]) {
00386     return(VERTICAL);
00387   }
00388 
00389   return(NEITHER);  
00390 }
00391 
00392 
00393 /* \brief
00394  * \par Function Description
00395  * This function does the actual work of making one bus segment out of two
00396  * connected segments.
00397  * The second object (del_object) is the object that should be deleted.
00398  *
00399  * \todo This function is currently not used. Check it before using it
00400  */
00401 static void o_bus_consolidate_lowlevel (OBJECT *object,
00402                                         OBJECT *del_object, int orient)
00403 {
00404   int temp1, temp2;
00405   int final1, final2;
00406   int changed=0;
00407   GList *a_iter;
00408   OBJECT *a_current;
00409 
00410 #if DEBUG
00411   printf("o %d %d %d %d\n", object->line->x[0], object->line->y[0], object->line->x[1], object->line->y[1]);
00412   printf("d %d %d %d %d\n", del_object->line->x[0], del_object->line->y[0], del_object->line->x[1], del_object->line->y[1]);
00413 #endif
00414 
00415 
00416   if (orient == HORIZONTAL) {
00417 
00418     temp1 = min(object->line->x[0], 
00419                 del_object->line->x[0]);
00420     temp2 = min(object->line->x[1], 
00421                 del_object->line->x[1]);
00422 
00423     final1 = min(temp1, temp2);
00424 
00425     temp1 = max(object->line->x[0], 
00426                 del_object->line->x[0]);
00427     temp2 = max(object->line->x[1], 
00428                 del_object->line->x[1]);
00429 
00430     final2 = max(temp1, temp2);
00431 
00432     object->line->x[0] = final1;
00433     object->line->x[1] = final2;
00434     changed=1;
00435   }
00436 
00437   if (orient == VERTICAL) {
00438     temp1 = min(object->line->y[0], 
00439                 del_object->line->y[0]);
00440     temp2 = min(object->line->y[1], 
00441                 del_object->line->y[1]);
00442 
00443     final1 = min(temp1, temp2);
00444 
00445     temp1 = max(object->line->y[0], 
00446                 del_object->line->y[0]);
00447     temp2 = max(object->line->y[1], 
00448                 del_object->line->y[1]);
00449 
00450     final2 = max(temp1, temp2);
00451 
00452     object->line->y[0] = final1;
00453     object->line->y[1] = final2;
00454     changed=1;
00455   }
00456 
00457 #if DEBUG
00458   printf("fo %d %d %d %d\n", object->line->x[0], object->line->y[0], object->line->x[1], object->line->y[1]);
00459 #endif
00460 
00461   /* Move any attributes from the deleted object*/
00462   if (changed && del_object->attribs != NULL) {
00463 
00464     /* Reassign the attached_to pointer on attributes from the del object */
00465     a_iter = del_object->attribs;
00466     while (a_iter != NULL) {
00467       a_current = a_iter->data;
00468       a_current->attached_to = object;
00469       a_iter = g_list_next (a_iter);
00470     }
00471 
00472     object->attribs = g_list_concat (object->attribs, del_object->attribs);
00473 
00474     /* Don't free del_object->attribs as it's relinked into object's list */
00475     del_object->attribs = NULL;
00476   }
00477 }
00478 
00479 /* \brief
00480  * \par Function Description
00481  *
00482  * \todo Not Implemented Yet
00483  */
00484 static int o_bus_consolidate_segments (TOPLEVEL *toplevel, OBJECT *object)
00485 {
00486 
00487   return(0);
00488 }
00489 
00490 /* \brief
00491  * \par Function Description
00492  *
00493  * \todo Not Implemented Yet 
00494  */
00495 void o_bus_consolidate(TOPLEVEL *toplevel)
00496 {
00497 
00498 }
00499 
00512 void o_bus_modify(TOPLEVEL *toplevel, OBJECT *object,
00513           int x, int y, int whichone)
00514 {
00515   object->line->x[whichone] = x;
00516   object->line->y[whichone] = y;
00517 
00518   o_bus_recalc (toplevel, object);
00519 
00520   s_tile_update_object(toplevel, object);
00521 }
00522 
00523 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines