libgeda
|
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