libgeda
|
00001 /* gEDA - GPL Electronic Design Automation 00002 * libgeda - gEDA's library - Scheme API 00003 * Copyright (C) 2010-2012 Peter Brett <peter@peter-b.co.uk> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License as published by 00007 * the Free Software Foundation; either version 2 of the License, or 00008 * (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software 00017 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA 00018 */ 00019 00025 #include <config.h> 00026 00027 #include "libgeda_priv.h" 00028 #include "libgedaguile_priv.h" 00029 00030 SCM_SYMBOL (wrong_type_arg_sym , "wrong-type-arg"); 00031 SCM_SYMBOL (line_sym , "line"); 00032 SCM_SYMBOL (net_sym , "net"); 00033 SCM_SYMBOL (bus_sym , "bus"); 00034 SCM_SYMBOL (box_sym , "box"); 00035 SCM_SYMBOL (picture_sym , "picture"); 00036 SCM_SYMBOL (circle_sym , "circle"); 00037 SCM_SYMBOL (complex_sym , "complex"); 00038 SCM_SYMBOL (text_sym , "text"); 00039 SCM_SYMBOL (path_sym , "path"); 00040 SCM_SYMBOL (pin_sym , "pin"); 00041 SCM_SYMBOL (arc_sym , "arc"); 00042 00043 SCM_SYMBOL (lower_left_sym , "lower-left"); 00044 SCM_SYMBOL (middle_left_sym , "middle-left"); 00045 SCM_SYMBOL (upper_left_sym , "upper-left"); 00046 SCM_SYMBOL (lower_center_sym , "lower-center"); 00047 SCM_SYMBOL (middle_center_sym , "middle-center"); 00048 SCM_SYMBOL (upper_center_sym , "upper-center"); 00049 SCM_SYMBOL (lower_right_sym , "lower-right"); 00050 SCM_SYMBOL (middle_right_sym , "middle-right"); 00051 SCM_SYMBOL (upper_right_sym , "upper-right"); 00052 00053 SCM_SYMBOL (name_sym , "name"); 00054 SCM_SYMBOL (value_sym , "value"); 00055 SCM_SYMBOL (both_sym , "both"); 00056 00057 SCM_SYMBOL (none_sym, "none"); 00058 SCM_SYMBOL (square_sym , "square"); 00059 SCM_SYMBOL (round_sym , "round"); 00060 00061 SCM_SYMBOL (solid_sym , "solid"); 00062 SCM_SYMBOL (dotted_sym , "dotted"); 00063 SCM_SYMBOL (dashed_sym , "dashed"); 00064 SCM_SYMBOL (center_sym , "center"); 00065 SCM_SYMBOL (phantom_sym , "phantom"); 00066 00067 SCM_SYMBOL (hollow_sym , "hollow"); 00068 SCM_SYMBOL (mesh_sym , "mesh"); 00069 SCM_SYMBOL (hatch_sym , "hatch"); 00070 00071 SCM_SYMBOL (moveto_sym , "moveto"); 00072 SCM_SYMBOL (lineto_sym , "lineto"); 00073 SCM_SYMBOL (curveto_sym , "curveto"); 00074 SCM_SYMBOL (closepath_sym , "closepath"); 00075 00076 void o_page_changed (TOPLEVEL *t, OBJECT *o) 00077 { 00078 PAGE *p = o_get_page (t, o); 00079 if (p != NULL) p->CHANGED = TRUE; 00080 } 00081 00097 GList * 00098 edascm_to_object_glist (SCM objs, const char *subr) 00099 { 00100 GList *result = NULL; 00101 SCM lst; 00102 00103 SCM_ASSERT (scm_is_true (scm_list_p (objs)), objs, SCM_ARGn, subr); 00104 00105 scm_dynwind_begin (0); 00106 scm_dynwind_unwind_handler ((void (*)(void *))g_list_free, result, 0); 00107 00108 for (lst = objs; lst != SCM_EOL; lst = SCM_CDR (lst)) { 00109 SCM smob = SCM_CAR (lst); 00110 result = g_list_prepend (result, (gpointer) edascm_to_object (smob)); 00111 } 00112 00113 scm_remember_upto_here_1 (lst); 00114 00115 scm_dynwind_end (); 00116 00117 return g_list_reverse (result); 00118 } 00119 00132 SCM 00133 edascm_from_object_glist (const GList *objs) 00134 { 00135 SCM lst = SCM_EOL; 00136 SCM rlst; 00137 GList *iter = (GList *) objs; 00138 00139 while (iter != NULL) { 00140 lst = scm_cons (edascm_from_object (iter->data), lst); 00141 iter = g_list_next (iter); 00142 } 00143 00144 rlst = scm_reverse (lst); 00145 00146 scm_remember_upto_here_1 (lst); 00147 return rlst; 00148 } 00149 00160 int 00161 edascm_is_object_type (SCM smob, int type) 00162 { 00163 if (!EDASCM_OBJECTP(smob)) return 0; 00164 00165 OBJECT *obj = edascm_to_object (smob); 00166 return (obj->type == type); 00167 } 00168 00180 SCM_DEFINE (copy_object, "%copy-object", 1, 0, 0, 00181 (SCM obj_s), "Copy an object.") 00182 { 00183 SCM result; 00184 SCM_ASSERT (EDASCM_OBJECTP (obj_s), obj_s, 00185 SCM_ARG1, s_copy_object); 00186 00187 TOPLEVEL *toplevel = edascm_c_current_toplevel (); 00188 OBJECT *obj = edascm_to_object (obj_s); 00189 00190 result = edascm_from_object (o_object_copy (toplevel, obj)); 00191 00192 /* At the moment, the only pointer to the object is owned by the 00193 * smob. */ 00194 edascm_c_set_gc (result, TRUE); 00195 00196 return result; 00197 } 00198 00209 SCM_DEFINE (object_type, "%object-type", 1, 0, 0, 00210 (SCM obj_s), "Get an object smob's type") 00211 { 00212 SCM result; 00213 00214 SCM_ASSERT (EDASCM_OBJECTP (obj_s), obj_s, 00215 SCM_ARG1, s_object_type); 00216 00217 OBJECT *obj = edascm_to_object (obj_s); 00218 switch (obj->type) { 00219 case OBJ_LINE: result = line_sym; break; 00220 case OBJ_NET: result = net_sym; break; 00221 case OBJ_BUS: result = bus_sym; break; 00222 case OBJ_BOX: result = box_sym; break; 00223 case OBJ_PICTURE: result = picture_sym; break; 00224 case OBJ_CIRCLE: result = circle_sym; break; 00225 case OBJ_PLACEHOLDER: 00226 case OBJ_COMPLEX: result = complex_sym; break; 00227 case OBJ_TEXT: result = text_sym; break; 00228 case OBJ_PATH: result = path_sym; break; 00229 case OBJ_PIN: result = pin_sym; break; 00230 case OBJ_ARC: result = arc_sym; break; 00231 default: 00232 scm_misc_error (s_object_type, _("Object ~A has bad type '~A'"), 00233 scm_list_2 (obj_s, 00234 scm_integer_to_char (scm_from_int (obj->type)))); 00235 } 00236 00237 return result; 00238 } 00239 00264 SCM_DEFINE (object_bounds, "%object-bounds", 0, 0, 1, 00265 (SCM rst_s), "Get the bounds of a list of objects") 00266 { 00267 TOPLEVEL *toplevel = edascm_c_current_toplevel (); 00268 00269 GList *obj_list = edascm_to_object_glist (rst_s, s_object_bounds); 00270 00271 int success, left, top, right, bottom; 00272 if (toplevel->show_hidden_text) { 00273 success = world_get_object_glist_bounds (toplevel, obj_list, 00274 &left, &top, &right, &bottom); 00275 } else { 00276 toplevel->show_hidden_text = TRUE; 00277 o_recalc_object_glist (toplevel, obj_list); 00278 00279 success = world_get_object_glist_bounds (toplevel, obj_list, 00280 &left, &top, &right, &bottom); 00281 00282 toplevel->show_hidden_text = FALSE; 00283 o_recalc_object_glist (toplevel, obj_list); 00284 } 00285 00286 SCM result = SCM_BOOL_F; 00287 if (success) { 00288 result = scm_cons (scm_cons (scm_from_int (min(left, right)), 00289 scm_from_int (max(top, bottom))), 00290 scm_cons (scm_from_int (max(left, right)), 00291 scm_from_int (min(top, bottom)))); 00292 } 00293 00294 scm_remember_upto_here_1 (rst_s); 00295 return result; 00296 } 00297 00298 00319 SCM_DEFINE (object_stroke, "%object-stroke", 1, 0, 0, 00320 (SCM obj_s), "Get the stroke properties of an object.") 00321 { 00322 SCM_ASSERT ((edascm_is_object_type (obj_s, OBJ_LINE) 00323 || edascm_is_object_type (obj_s, OBJ_BOX) 00324 || edascm_is_object_type (obj_s, OBJ_CIRCLE) 00325 || edascm_is_object_type (obj_s, OBJ_ARC) 00326 || edascm_is_object_type (obj_s, OBJ_PATH)), 00327 obj_s, SCM_ARG1, s_object_stroke); 00328 00329 OBJECT *obj = edascm_to_object (obj_s); 00330 00331 int end, type, width, length, space; 00332 o_get_line_options (obj, (OBJECT_END *) &end, (OBJECT_TYPE *) &type, &width, 00333 &length, &space); 00334 00335 SCM width_s = scm_from_int (width); 00336 SCM length_s = scm_from_int (length); 00337 SCM space_s = scm_from_int (space); 00338 00339 SCM cap_s; 00340 switch (end) { 00341 case END_NONE: cap_s = none_sym; break; 00342 case END_SQUARE: cap_s = square_sym; break; 00343 case END_ROUND: cap_s = round_sym; break; 00344 default: 00345 scm_misc_error (s_object_stroke, 00346 _("Object ~A has invalid stroke cap style ~A"), 00347 scm_list_2 (obj_s, scm_from_int (end))); 00348 } 00349 00350 SCM dash_s; 00351 switch (type) { 00352 case TYPE_SOLID: dash_s = solid_sym; break; 00353 case TYPE_DOTTED: dash_s = dotted_sym; break; 00354 case TYPE_DASHED: dash_s = dashed_sym; break; 00355 case TYPE_CENTER: dash_s = center_sym; break; 00356 case TYPE_PHANTOM: dash_s = phantom_sym; break; 00357 default: 00358 scm_misc_error (s_object_stroke, 00359 _("Object ~A has invalid stroke dash style ~A"), 00360 scm_list_2 (obj_s, scm_from_int (type))); 00361 } 00362 00363 switch (type) { 00364 case TYPE_DASHED: 00365 case TYPE_CENTER: 00366 case TYPE_PHANTOM: 00367 return scm_list_5 (width_s, cap_s, dash_s, space_s, length_s); 00368 case TYPE_DOTTED: 00369 return scm_list_4 (width_s, cap_s, dash_s, space_s); 00370 default: 00371 return scm_list_3 (width_s, cap_s, dash_s); 00372 } 00373 } 00374 00394 SCM_DEFINE (set_object_stroke_x, "%set-object-stroke!", 4, 2, 0, 00395 (SCM obj_s, SCM width_s, SCM cap_s, SCM dash_s, SCM space_s, 00396 SCM length_s), "Set the stroke properties of an object.") 00397 { 00398 SCM_ASSERT ((edascm_is_object_type (obj_s, OBJ_LINE) 00399 || edascm_is_object_type (obj_s, OBJ_BOX) 00400 || edascm_is_object_type (obj_s, OBJ_CIRCLE) 00401 || edascm_is_object_type (obj_s, OBJ_ARC) 00402 || edascm_is_object_type (obj_s, OBJ_PATH)), 00403 obj_s, SCM_ARG1, s_set_object_stroke_x); 00404 00405 TOPLEVEL *toplevel = edascm_c_current_toplevel (); 00406 OBJECT *obj = edascm_to_object (obj_s); 00407 int cap, type, width, length = -1, space = -1; 00408 00409 SCM_ASSERT (scm_is_integer (width_s), width_s, 00410 SCM_ARG2, s_set_object_stroke_x); 00411 SCM_ASSERT (scm_is_symbol (cap_s), cap_s, 00412 SCM_ARG3, s_set_object_stroke_x); 00413 SCM_ASSERT (scm_is_symbol (dash_s), dash_s, 00414 SCM_ARG4, s_set_object_stroke_x); 00415 00416 width = scm_to_int (width_s); 00417 00418 if (cap_s == none_sym) { cap = END_NONE; } 00419 else if (cap_s == square_sym) { cap = END_SQUARE; } 00420 else if (cap_s == round_sym) { cap = END_ROUND; } 00421 else { 00422 scm_misc_error (s_set_object_stroke_x, 00423 _("Invalid stroke cap style ~A."), 00424 scm_list_1 (cap_s)); 00425 } 00426 00427 if (dash_s == solid_sym) { type = TYPE_SOLID; } 00428 else if (dash_s == dotted_sym) { type = TYPE_DOTTED; } 00429 else if (dash_s == dashed_sym) { type = TYPE_DASHED; } 00430 else if (dash_s == center_sym) { type = TYPE_CENTER; } 00431 else if (dash_s == phantom_sym) { type = TYPE_PHANTOM; } 00432 else { 00433 scm_misc_error (s_set_object_stroke_x, 00434 _("Invalid stroke dash style ~A."), 00435 scm_list_1 (dash_s)); 00436 } 00437 00438 switch (type) { 00439 case TYPE_DASHED: 00440 case TYPE_CENTER: 00441 case TYPE_PHANTOM: 00442 if (length_s == SCM_UNDEFINED) { 00443 scm_misc_error (s_set_object_stroke_x, 00444 _("Missing dash length parameter for dash style ~A."), 00445 scm_list_1 (length_s)); 00446 } 00447 SCM_ASSERT (scm_is_integer (length_s), length_s, 00448 SCM_ARG6, s_set_object_stroke_x); 00449 length = scm_to_int (length_s); 00450 /* This case intentionally falls through */ 00451 case TYPE_DOTTED: 00452 if (space_s == SCM_UNDEFINED) { 00453 scm_misc_error (s_set_object_stroke_x, 00454 _("Missing dot/dash space parameter for dash style ~A."), 00455 scm_list_1 (space_s)); 00456 } 00457 SCM_ASSERT (scm_is_integer (space_s), space_s, 00458 SCM_ARG5, s_set_object_stroke_x); 00459 space = scm_to_int (space_s); 00460 /* This case intentionally falls through */ 00461 } 00462 00463 o_set_line_options (toplevel, obj, cap, type, width, length, space); 00464 o_page_changed (toplevel, obj); 00465 00466 return obj_s; 00467 } 00468 00488 SCM_DEFINE (object_fill, "%object-fill", 1, 0, 0, 00489 (SCM obj_s), "Get the fill properties of an object.") 00490 { 00491 SCM_ASSERT ((edascm_is_object_type (obj_s, OBJ_BOX) 00492 || edascm_is_object_type (obj_s, OBJ_CIRCLE) 00493 || edascm_is_object_type (obj_s, OBJ_PATH)), 00494 obj_s, SCM_ARG1, s_object_fill); 00495 00496 OBJECT *obj = edascm_to_object (obj_s); 00497 00498 int type, width, pitch1, angle1, pitch2, angle2; 00499 o_get_fill_options (obj, (OBJECT_FILLING *) &type, &width, &pitch1, &angle1, 00500 &pitch2, &angle2); 00501 00502 SCM width_s = scm_from_int (width); 00503 SCM pitch1_s = scm_from_int (pitch1); 00504 SCM angle1_s = scm_from_int (angle1); 00505 SCM pitch2_s = scm_from_int (pitch2); 00506 SCM angle2_s = scm_from_int (angle2); 00507 00508 SCM type_s; 00509 switch (type) { 00510 case FILLING_HOLLOW: type_s = hollow_sym; break; 00511 case FILLING_FILL: type_s = solid_sym; break; 00512 case FILLING_MESH: type_s = mesh_sym; break; 00513 case FILLING_HATCH: type_s = hatch_sym; break; 00514 default: 00515 scm_misc_error (s_object_fill, 00516 _("Object ~A has invalid fill style ~A"), 00517 scm_list_2 (obj_s, scm_from_int (type))); 00518 } 00519 00520 switch (type) { 00521 case FILLING_MESH: 00522 return scm_list_n (type_s, width_s, pitch1_s, angle1_s, pitch2_s, angle2_s, 00523 SCM_UNDEFINED); 00524 case FILLING_HATCH: 00525 return scm_list_4 (type_s, width_s, pitch1_s, angle1_s); 00526 default: 00527 return scm_list_1 (type_s); 00528 } 00529 } 00530 00545 SCM_DEFINE (set_object_fill_x, "%set-object-fill!", 2, 5, 0, 00546 (SCM obj_s, SCM type_s, SCM width_s, SCM space1_s, SCM angle1_s, 00547 SCM space2_s, SCM angle2_s), 00548 "Set the fill properties of an object.") 00549 { 00550 SCM_ASSERT ((edascm_is_object_type (obj_s, OBJ_BOX) 00551 || edascm_is_object_type (obj_s, OBJ_CIRCLE) 00552 || edascm_is_object_type (obj_s, OBJ_PATH)), 00553 obj_s, SCM_ARG1, s_set_object_fill_x); 00554 00555 TOPLEVEL *toplevel = edascm_c_current_toplevel (); 00556 OBJECT *obj = edascm_to_object (obj_s); 00557 int type, width = -1, angle1 = -1, space1 = -1, angle2 = -1, space2 = -1; 00558 00559 if (type_s == hollow_sym) { type = FILLING_HOLLOW; } 00560 else if (type_s == solid_sym) { type = FILLING_FILL; } 00561 else if (type_s == hatch_sym) { type = FILLING_HATCH; } 00562 else if (type_s == mesh_sym) { type = FILLING_MESH; } 00563 else { 00564 scm_misc_error (s_set_object_fill_x, 00565 _("Invalid fill style ~A."), 00566 scm_list_1 (type_s)); 00567 } 00568 00569 switch (type) { 00570 case FILLING_MESH: 00571 if (space2_s == SCM_UNDEFINED) { 00572 scm_misc_error (s_set_object_fill_x, 00573 _("Missing second space parameter for fill style ~A."), 00574 scm_list_1 (space2_s)); 00575 } 00576 SCM_ASSERT (scm_is_integer (space2_s), space2_s, 00577 SCM_ARG6, s_set_object_fill_x); 00578 space2 = scm_to_int (space2_s); 00579 00580 if (angle2_s == SCM_UNDEFINED) { 00581 scm_misc_error (s_set_object_fill_x, 00582 _("Missing second angle parameter for fill style ~A."), 00583 scm_list_1 (angle2_s)); 00584 } 00585 SCM_ASSERT (scm_is_integer (angle2_s), angle2_s, 00586 SCM_ARG7, s_set_object_fill_x); 00587 angle2 = scm_to_int (angle2_s); 00588 /* This case intentionally falls through */ 00589 case FILLING_HATCH: 00590 if (width_s == SCM_UNDEFINED) { 00591 scm_misc_error (s_set_object_fill_x, 00592 _("Missing stroke width parameter for fill style ~A."), 00593 scm_list_1 (width_s)); 00594 } 00595 SCM_ASSERT (scm_is_integer (width_s), width_s, 00596 SCM_ARG3, s_set_object_fill_x); 00597 width = scm_to_int (width_s); 00598 00599 if (space1_s == SCM_UNDEFINED) { 00600 scm_misc_error (s_set_object_fill_x, 00601 _("Missing space parameter for fill style ~A."), 00602 scm_list_1 (space1_s)); 00603 } 00604 SCM_ASSERT (scm_is_integer (space1_s), space1_s, 00605 SCM_ARG4, s_set_object_fill_x); 00606 space1 = scm_to_int (space1_s); 00607 00608 if (angle1_s == SCM_UNDEFINED) { 00609 scm_misc_error (s_set_object_fill_x, 00610 _("Missing angle parameter for fill style ~A."), 00611 scm_list_1 (angle1_s)); 00612 } 00613 SCM_ASSERT (scm_is_integer (angle1_s), angle1_s, 00614 SCM_ARG5, s_set_object_fill_x); 00615 angle1 = scm_to_int (angle1_s); 00616 /* This case intentionally falls through */ 00617 } 00618 00619 o_set_fill_options (toplevel, obj, type, width, 00620 space1, angle1, space2, angle2); 00621 o_page_changed (toplevel, obj); 00622 00623 return obj_s; 00624 } 00625 00638 SCM_DEFINE (object_color, "%object-color", 1, 0, 0, 00639 (SCM obj_s), "Get the color of an object.") 00640 { 00641 SCM_ASSERT (EDASCM_OBJECTP (obj_s), obj_s, 00642 SCM_ARG1, s_object_color); 00643 00644 OBJECT *obj = edascm_to_object (obj_s); 00645 return scm_from_int (obj->color); 00646 } 00647 00661 SCM_DEFINE (set_object_color_x, "%set-object-color!", 2, 0, 0, 00662 (SCM obj_s, SCM color_s), "Set the color of an object.") 00663 { 00664 SCM_ASSERT (EDASCM_OBJECTP (obj_s), obj_s, 00665 SCM_ARG1, s_set_object_color_x); 00666 SCM_ASSERT (scm_is_integer (color_s), color_s, 00667 SCM_ARG2, s_set_object_color_x); 00668 00669 TOPLEVEL *toplevel = edascm_c_current_toplevel (); 00670 OBJECT *obj = edascm_to_object (obj_s); 00671 o_set_color (toplevel, obj, scm_to_int (color_s)); 00672 00673 o_page_changed (toplevel, obj); 00674 00675 return obj_s; 00676 } 00677 00688 SCM_DEFINE (make_line, "%make-line", 0, 0, 0, 00689 (), "Create a new line object.") 00690 { 00691 OBJECT *obj = o_line_new (edascm_c_current_toplevel (), 00692 OBJ_LINE, DEFAULT_COLOR, 00693 0, 0, 0, 0); 00694 00695 SCM result = edascm_from_object (obj); 00696 00697 /* At the moment, the only pointer to the object is owned by the 00698 * smob. */ 00699 edascm_c_set_gc (result, TRUE); 00700 00701 return result; 00702 } 00703 00724 SCM_DEFINE (set_line_x, "%set-line!", 6, 0, 0, 00725 (SCM line_s, SCM x1_s, SCM y1_s, SCM x2_s, SCM y2_s, SCM color_s), 00726 "Set line parameters.") 00727 { 00728 SCM_ASSERT ((edascm_is_object_type (line_s, OBJ_LINE) 00729 || edascm_is_object_type (line_s, OBJ_NET) 00730 || edascm_is_object_type (line_s, OBJ_BUS) 00731 || edascm_is_object_type (line_s, OBJ_PIN)), 00732 line_s, SCM_ARG1, s_set_line_x); 00733 00734 SCM_ASSERT (scm_is_integer (x1_s), x1_s, SCM_ARG2, s_set_line_x); 00735 SCM_ASSERT (scm_is_integer (y1_s), y1_s, SCM_ARG3, s_set_line_x); 00736 SCM_ASSERT (scm_is_integer (x2_s), x2_s, SCM_ARG4, s_set_line_x); 00737 SCM_ASSERT (scm_is_integer (y2_s), y2_s, SCM_ARG5, s_set_line_x); 00738 SCM_ASSERT (scm_is_integer (color_s), color_s, SCM_ARG6, s_set_line_x); 00739 00740 TOPLEVEL *toplevel = edascm_c_current_toplevel (); 00741 OBJECT *obj = edascm_to_object (line_s); 00742 int x1 = scm_to_int (x1_s); 00743 int y1 = scm_to_int (y1_s); 00744 int x2 = scm_to_int (x2_s); 00745 int y2 = scm_to_int (y2_s); 00746 00747 /* We may need to update connectivity. */ 00748 s_conn_remove_object (toplevel, obj); 00749 00750 switch (obj->type) { 00751 case OBJ_LINE: 00752 o_line_modify (toplevel, obj, x1, y1, LINE_END1); 00753 o_line_modify (toplevel, obj, x2, y2, LINE_END2); 00754 break; 00755 case OBJ_NET: 00756 o_net_modify (toplevel, obj, x1, y1, 0); 00757 o_net_modify (toplevel, obj, x2, y2, 1); 00758 break; 00759 case OBJ_BUS: 00760 o_bus_modify (toplevel, obj, x1, y1, 0); 00761 o_bus_modify (toplevel, obj, x2, y2, 1); 00762 break; 00763 case OBJ_PIN: 00764 /* Swap ends according to pin's whichend flag. */ 00765 o_pin_modify (toplevel, obj, x1, y1, obj->whichend ? 1 : 0); 00766 o_pin_modify (toplevel, obj, x2, y2, obj->whichend ? 0 : 1); 00767 break; 00768 default: 00769 return line_s; 00770 } 00771 o_set_color (toplevel, obj, scm_to_int (color_s)); 00772 00773 /* We may need to update connectivity. */ 00774 s_tile_update_object (toplevel, obj); 00775 s_conn_update_object (toplevel, obj); 00776 00777 o_page_changed (toplevel, obj); 00778 00779 return line_s; 00780 } 00781 00799 SCM_DEFINE (line_info, "%line-info", 1, 0, 0, 00800 (SCM line_s), "Get line parameters.") 00801 { 00802 SCM_ASSERT ((edascm_is_object_type (line_s, OBJ_LINE) 00803 || edascm_is_object_type (line_s, OBJ_NET) 00804 || edascm_is_object_type (line_s, OBJ_BUS) 00805 || edascm_is_object_type (line_s, OBJ_PIN)), 00806 line_s, SCM_ARG1, s_line_info); 00807 00808 OBJECT *obj = edascm_to_object (line_s); 00809 SCM x1 = scm_from_int (obj->line->x[0]); 00810 SCM y1 = scm_from_int (obj->line->y[0]); 00811 SCM x2 = scm_from_int (obj->line->x[1]); 00812 SCM y2 = scm_from_int (obj->line->y[1]); 00813 SCM color = scm_from_int (obj->color); 00814 00815 /* Swap ends according to pin's whichend flag. */ 00816 if ((obj->type == OBJ_PIN) && obj->whichend) { 00817 SCM s; 00818 s = x1; x1 = x2; x2 = s; 00819 s = y1; y1 = y2; y2 = s; 00820 } 00821 00822 return scm_list_n (x1, y1, x2, y2, color, SCM_UNDEFINED); 00823 } 00824 00835 SCM_DEFINE (make_net, "%make-net", 0, 0, 0, 00836 (), "Create a new net object.") 00837 { 00838 OBJECT *obj; 00839 SCM result; 00840 00841 obj = o_net_new (edascm_c_current_toplevel (), 00842 OBJ_NET, NET_COLOR, 0, 0, 0, 0); 00843 00844 00845 result = edascm_from_object (obj); 00846 00847 /* At the moment, the only pointer to the object is owned by the 00848 * smob. */ 00849 edascm_c_set_gc (result, 1); 00850 00851 return result; 00852 } 00853 00866 SCM_DEFINE (make_bus, "%make-bus", 0, 0, 0, 00867 (), "Create a new bus object.") 00868 { 00869 OBJECT *obj; 00870 SCM result; 00871 00872 obj = o_bus_new (edascm_c_current_toplevel (), 00873 OBJ_BUS, BUS_COLOR, 0, 0, 0, 0, 00874 0); /* Bus ripper direction */ 00875 00876 result = edascm_from_object (obj); 00877 00878 /* At the moment, the only pointer to the object is owned by the 00879 * smob. */ 00880 edascm_c_set_gc (result, 1); 00881 00882 return result; 00883 } 00884 00896 SCM_DEFINE (make_pin, "%make-pin", 1, 0, 0, 00897 (SCM type_s), "Create a new pin object.") 00898 { 00899 SCM_ASSERT (scm_is_symbol (type_s), 00900 type_s, SCM_ARG1, s_make_pin); 00901 00902 int type; 00903 if (type_s == net_sym) { 00904 type = PIN_TYPE_NET; 00905 } else if (type_s == bus_sym) { 00906 type = PIN_TYPE_BUS; 00907 } else { 00908 scm_misc_error (s_make_pin, 00909 _("Invalid pin type ~A, must be 'net or 'bus"), 00910 scm_list_1 (type_s)); 00911 } 00912 00913 OBJECT *obj = o_pin_new (edascm_c_current_toplevel (), 00914 OBJ_PIN, PIN_COLOR, 0, 0, 0, 0, type, 0); 00915 SCM result = edascm_from_object (obj); 00916 00917 /* At the moment, the only pointer to the object is owned by the 00918 * smob. */ 00919 edascm_c_set_gc (result, 1); 00920 00921 return result; 00922 } 00923 00934 SCM_DEFINE (pin_type, "%pin-type", 1, 0, 0, 00935 (SCM pin_s), "Get the type of a pin object.") 00936 { 00937 SCM_ASSERT (edascm_is_object_type (pin_s, OBJ_PIN), pin_s, 00938 SCM_ARG1, s_pin_type); 00939 00940 OBJECT *obj = edascm_to_object (pin_s); 00941 SCM result; 00942 00943 switch (obj->pin_type) { 00944 case PIN_TYPE_NET: 00945 result = net_sym; 00946 break; 00947 case PIN_TYPE_BUS: 00948 result = bus_sym; 00949 break; 00950 default: 00951 scm_misc_error (s_make_pin, 00952 _("Object ~A has invalid pin type."), 00953 scm_list_1 (pin_s)); 00954 } 00955 00956 return result; 00957 } 00958 00969 SCM_DEFINE (make_box, "%make-box", 0, 0, 0, 00970 (), "Create a new box object.") 00971 { 00972 OBJECT *obj = o_box_new (edascm_c_current_toplevel (), 00973 OBJ_BOX, DEFAULT_COLOR, 00974 0, 0, 0, 0); 00975 00976 SCM result = edascm_from_object (obj); 00977 00978 /* At the moment, the only pointer to the object is owned by the 00979 * smob. */ 00980 edascm_c_set_gc (result, 1); 00981 00982 return result; 00983 } 00984 01002 SCM_DEFINE (set_box_x, "%set-box!", 6, 0, 0, 01003 (SCM box_s, SCM x1_s, SCM y1_s, SCM x2_s, SCM y2_s, SCM color_s), 01004 "Set box parameters.") 01005 { 01006 SCM_ASSERT (edascm_is_object_type (box_s, OBJ_BOX), box_s, 01007 SCM_ARG1, s_set_box_x); 01008 SCM_ASSERT (scm_is_integer (x1_s), x1_s, SCM_ARG2, s_set_box_x); 01009 SCM_ASSERT (scm_is_integer (y1_s), y1_s, SCM_ARG3, s_set_box_x); 01010 SCM_ASSERT (scm_is_integer (x2_s), x2_s, SCM_ARG4, s_set_box_x); 01011 SCM_ASSERT (scm_is_integer (y2_s), y2_s, SCM_ARG5, s_set_box_x); 01012 SCM_ASSERT (scm_is_integer (color_s), color_s, SCM_ARG6, s_set_box_x); 01013 01014 TOPLEVEL *toplevel = edascm_c_current_toplevel (); 01015 OBJECT *obj = edascm_to_object (box_s); 01016 o_box_modify_all (toplevel, obj, 01017 scm_to_int (x1_s), scm_to_int (y1_s), 01018 scm_to_int (x2_s), scm_to_int (y2_s)); 01019 o_set_color (toplevel, obj, scm_to_int (color_s)); 01020 01021 o_page_changed (toplevel, obj); 01022 01023 return box_s; 01024 } 01025 01040 SCM_DEFINE (box_info, "%box-info", 1, 0, 0, 01041 (SCM box_s), "Get box parameters.") 01042 { 01043 SCM_ASSERT (edascm_is_object_type (box_s, OBJ_BOX), box_s, 01044 SCM_ARG1, s_box_info); 01045 01046 OBJECT *obj = edascm_to_object (box_s); 01047 01048 return scm_list_n (scm_from_int (obj->box->upper_x), 01049 scm_from_int (obj->box->upper_y), 01050 scm_from_int (obj->box->lower_x), 01051 scm_from_int (obj->box->lower_y), 01052 scm_from_int (obj->color), 01053 SCM_UNDEFINED); 01054 } 01055 01067 SCM_DEFINE (make_circle, "%make-circle", 0, 0, 0, 01068 (), "Create a new circle object.") 01069 { 01070 OBJECT *obj = o_circle_new (edascm_c_current_toplevel (), 01071 OBJ_CIRCLE, DEFAULT_COLOR, 01072 0, 0, 1); 01073 01074 SCM result = edascm_from_object (obj); 01075 01076 /* At the moment, the only pointer to the object is owned by the 01077 * smob. */ 01078 edascm_c_set_gc (result, 1); 01079 01080 return result; 01081 } 01082 01099 SCM_DEFINE (set_circle_x, "%set-circle!", 5, 0, 0, 01100 (SCM circle_s, SCM x_s, SCM y_s, SCM r_s, SCM color_s), 01101 "Set circle parameters") 01102 { 01103 SCM_ASSERT (edascm_is_object_type (circle_s, OBJ_CIRCLE), circle_s, 01104 SCM_ARG1, s_set_circle_x); 01105 SCM_ASSERT (scm_is_integer (x_s), x_s, SCM_ARG2, s_set_circle_x); 01106 SCM_ASSERT (scm_is_integer (y_s), y_s, SCM_ARG3, s_set_circle_x); 01107 SCM_ASSERT (scm_is_integer (r_s), r_s, SCM_ARG4, s_set_circle_x); 01108 SCM_ASSERT (scm_is_integer (color_s), color_s, SCM_ARG5, s_set_circle_x); 01109 01110 TOPLEVEL *toplevel = edascm_c_current_toplevel (); 01111 OBJECT *obj = edascm_to_object (circle_s); 01112 o_circle_modify (toplevel, obj, scm_to_int(x_s), scm_to_int(y_s), 01113 CIRCLE_CENTER); 01114 o_circle_modify (toplevel, obj, scm_to_int(r_s), 0, CIRCLE_RADIUS); 01115 o_set_color (toplevel, obj, scm_to_int (color_s)); 01116 01117 o_page_changed (toplevel, obj); 01118 01119 return circle_s; 01120 } 01121 01136 SCM_DEFINE (circle_info, "%circle-info", 1, 0, 0, 01137 (SCM circle_s), "Get circle parameters.") 01138 { 01139 SCM_ASSERT (edascm_is_object_type (circle_s, OBJ_CIRCLE), 01140 circle_s, SCM_ARG1, s_circle_info); 01141 01142 OBJECT *obj = edascm_to_object (circle_s); 01143 01144 return scm_list_n (scm_from_int (obj->circle->center_x), 01145 scm_from_int (obj->circle->center_y), 01146 scm_from_int (obj->circle->radius), 01147 scm_from_int (obj->color), 01148 SCM_UNDEFINED); 01149 } 01150 01161 SCM_DEFINE (make_arc, "%make-arc", 0, 0, 0, 01162 (), "Create a new arc object.") 01163 { 01164 OBJECT *obj = o_arc_new (edascm_c_current_toplevel (), 01165 OBJ_ARC, DEFAULT_COLOR, 01166 0, 0, 1, 0, 0); 01167 01168 SCM result = edascm_from_object (obj); 01169 01170 /* At the moment, the only pointer to the object is owned by the 01171 * smob. */ 01172 edascm_c_set_gc (result, 1); 01173 01174 return result; 01175 } 01176 01195 SCM_DEFINE (set_arc_x, "%set-arc!", 7, 0, 0, 01196 (SCM arc_s, SCM x_s, SCM y_s, SCM r_s, SCM start_angle_s, 01197 SCM end_angle_s, SCM color_s), 01198 "Set arc parameters") 01199 { 01200 SCM_ASSERT (edascm_is_object_type (arc_s, OBJ_ARC), arc_s, 01201 SCM_ARG1, s_set_arc_x); 01202 SCM_ASSERT (scm_is_integer (x_s), x_s, SCM_ARG2, s_set_arc_x); 01203 SCM_ASSERT (scm_is_integer (y_s), y_s, SCM_ARG3, s_set_arc_x); 01204 SCM_ASSERT (scm_is_integer (r_s), r_s, SCM_ARG4, s_set_arc_x); 01205 SCM_ASSERT (scm_is_integer (color_s), color_s, SCM_ARG7, s_set_arc_x); 01206 SCM_ASSERT (scm_is_integer (start_angle_s), 01207 start_angle_s, SCM_ARG5, s_set_arc_x); 01208 SCM_ASSERT (scm_is_integer (end_angle_s), 01209 end_angle_s, SCM_ARG6, s_set_arc_x); 01210 01211 TOPLEVEL *toplevel = edascm_c_current_toplevel (); 01212 OBJECT *obj = edascm_to_object (arc_s); 01213 o_arc_modify (toplevel, obj, scm_to_int(x_s), scm_to_int(y_s), 01214 ARC_CENTER); 01215 o_arc_modify (toplevel, obj, scm_to_int(r_s), 0, ARC_RADIUS); 01216 o_arc_modify (toplevel, obj, scm_to_int(start_angle_s), 0, ARC_START_ANGLE); 01217 o_arc_modify (toplevel, obj, scm_to_int(end_angle_s), 0, ARC_END_ANGLE); 01218 o_set_color (toplevel, obj, scm_to_int (color_s)); 01219 01220 o_page_changed (toplevel, obj); 01221 01222 return arc_s; 01223 } 01224 01243 SCM_DEFINE (arc_info, "%arc-info", 1, 0, 0, 01244 (SCM arc_s), "Get arc parameters.") 01245 { 01246 SCM_ASSERT (edascm_is_object_type (arc_s, OBJ_ARC), 01247 arc_s, SCM_ARG1, s_arc_info); 01248 01249 OBJECT *obj = edascm_to_object (arc_s); 01250 01251 return scm_list_n (scm_from_int (obj->arc->x), 01252 scm_from_int (obj->arc->y), 01253 scm_from_int (obj->arc->width / 2), 01254 scm_from_int (obj->arc->start_angle), 01255 scm_from_int (obj->arc->end_angle), 01256 scm_from_int (obj->color), 01257 SCM_UNDEFINED); 01258 } 01259 01270 SCM_DEFINE (make_text, "%make-text", 0, 0, 0, 01271 (), "Create a new text object.") 01272 { 01273 OBJECT *obj = o_text_new (edascm_c_current_toplevel (), 01274 OBJ_TEXT, DEFAULT_COLOR, 01275 0, 0, LOWER_LEFT, 0, "", 10, 01276 VISIBLE, SHOW_NAME_VALUE); 01277 01278 SCM result = edascm_from_object (obj); 01279 01280 /* At the moment, the only pointer to the object is owned by the 01281 * smob. */ 01282 edascm_c_set_gc (result, 1); 01283 01284 return result; 01285 } 01286 01314 SCM_DEFINE (set_text_x, "%set-text!", 10, 0, 0, 01315 (SCM text_s, SCM x_s, SCM y_s, SCM align_s, SCM angle_s, 01316 SCM string_s, SCM size_s, SCM visible_s, SCM show_s, SCM color_s), 01317 "Set text parameters") 01318 { 01319 SCM_ASSERT (edascm_is_object_type (text_s, OBJ_TEXT), text_s, 01320 SCM_ARG1, s_set_text_x); 01321 SCM_ASSERT (scm_is_integer (x_s), x_s, SCM_ARG2, s_set_text_x); 01322 SCM_ASSERT (scm_is_integer (y_s), y_s, SCM_ARG3, s_set_text_x); 01323 SCM_ASSERT (scm_is_symbol (align_s), align_s, SCM_ARG4, s_set_text_x); 01324 SCM_ASSERT (scm_is_integer (angle_s), angle_s, SCM_ARG5, s_set_text_x); 01325 SCM_ASSERT (scm_is_string (string_s), string_s, SCM_ARG6, s_set_text_x); 01326 SCM_ASSERT (scm_is_integer (size_s), size_s, SCM_ARG7, s_set_text_x); 01327 01328 SCM_ASSERT (scm_is_symbol (show_s), show_s, 9, s_set_text_x); 01329 SCM_ASSERT (scm_is_integer (color_s), color_s, 10, s_set_text_x); 01330 01331 TOPLEVEL *toplevel = edascm_c_current_toplevel (); 01332 OBJECT *obj = edascm_to_object (text_s); 01333 01334 /* Alignment. Sadly we can't switch on pointers. :-( */ 01335 int align; 01336 if (align_s == lower_left_sym) { align = LOWER_LEFT; } 01337 else if (align_s == middle_left_sym) { align = MIDDLE_LEFT; } 01338 else if (align_s == upper_left_sym) { align = UPPER_LEFT; } 01339 else if (align_s == lower_center_sym) { align = LOWER_MIDDLE; } 01340 else if (align_s == middle_center_sym) { align = MIDDLE_MIDDLE; } 01341 else if (align_s == upper_center_sym) { align = UPPER_MIDDLE; } 01342 else if (align_s == lower_right_sym) { align = LOWER_RIGHT; } 01343 else if (align_s == middle_right_sym) { align = MIDDLE_RIGHT; } 01344 else if (align_s == upper_right_sym) { align = UPPER_RIGHT; } 01345 else { 01346 scm_misc_error (s_set_text_x, 01347 _("Invalid text alignment ~A."), 01348 scm_list_1 (align_s)); 01349 } 01350 01351 /* Angle */ 01352 int angle = scm_to_int (angle_s); 01353 switch (angle) { 01354 case 0: 01355 case 90: 01356 case 180: 01357 case 270: 01358 /* These are all fine. */ 01359 break; 01360 default: 01361 /* Otherwise, not fine. */ 01362 scm_misc_error (s_set_text_x, 01363 _("Invalid text angle ~A. Must be 0, 90, 180, or 270 degrees"), 01364 scm_list_1 (angle_s)); 01365 } 01366 01367 /* Visibility */ 01368 int visibility; 01369 if (scm_is_false (visible_s)) { 01370 visibility = INVISIBLE; 01371 } else { 01372 visibility = VISIBLE; 01373 } 01374 01375 /* Name/value visibility */ 01376 int show; 01377 if (show_s == name_sym) { show = SHOW_NAME; } 01378 else if (show_s == value_sym) { show = SHOW_VALUE; } 01379 else if (show_s == both_sym) { show = SHOW_NAME_VALUE; } 01380 else { 01381 scm_misc_error (s_set_text_x, 01382 _("Invalid text name/value visibility ~A."), 01383 scm_list_1 (show_s)); 01384 } 01385 01386 /* Actually make changes */ 01387 o_emit_pre_change_notify (toplevel, obj); 01388 01389 obj->text->x = scm_to_int (x_s); 01390 obj->text->y = scm_to_int (y_s); 01391 obj->text->alignment = align; 01392 obj->text->angle = angle; 01393 01394 obj->text->size = scm_to_int (size_s); 01395 obj->visibility = visibility; 01396 obj->show_name_value = show; 01397 01398 o_emit_change_notify (toplevel, obj); 01399 01400 char *tmp = scm_to_utf8_string (string_s); 01401 o_text_set_string (toplevel, obj, tmp); 01402 free (tmp); 01403 01404 o_text_recreate (toplevel, obj); 01405 01406 /* Color */ 01407 o_set_color (toplevel, obj, scm_to_int (color_s)); 01408 01409 o_page_changed (toplevel, obj); 01410 01411 return text_s; 01412 } 01413 01435 SCM_DEFINE (text_info, "%text-info", 1, 0, 0, 01436 (SCM text_s), "Get text parameters.") 01437 { 01438 SCM_ASSERT (edascm_is_object_type (text_s, OBJ_TEXT), 01439 text_s, SCM_ARG1, s_text_info); 01440 01441 TOPLEVEL *toplevel = edascm_c_current_toplevel (); 01442 OBJECT *obj = edascm_to_object (text_s); 01443 SCM align_s, visible_s, show_s; 01444 01445 switch (obj->text->alignment) { 01446 case LOWER_LEFT: align_s = lower_left_sym; break; 01447 case MIDDLE_LEFT: align_s = middle_left_sym; break; 01448 case UPPER_LEFT: align_s = upper_left_sym; break; 01449 case LOWER_MIDDLE: align_s = lower_center_sym; break; 01450 case MIDDLE_MIDDLE: align_s = middle_center_sym; break; 01451 case UPPER_MIDDLE: align_s = upper_center_sym; break; 01452 case LOWER_RIGHT: align_s = lower_right_sym; break; 01453 case MIDDLE_RIGHT: align_s = middle_right_sym; break; 01454 case UPPER_RIGHT: align_s = upper_right_sym; break; 01455 default: 01456 scm_misc_error (s_text_info, 01457 _("Text object ~A has invalid text alignment ~A"), 01458 scm_list_2 (text_s, scm_from_int (obj->text->alignment))); 01459 } 01460 01461 switch (obj->visibility) { 01462 case VISIBLE: visible_s = SCM_BOOL_T; break; 01463 case INVISIBLE: visible_s = SCM_BOOL_F; break; 01464 default: 01465 scm_misc_error (s_text_info, 01466 _("Text object ~A has invalid visibility ~A"), 01467 scm_list_2 (text_s, scm_from_int (obj->visibility))); 01468 } 01469 01470 switch (obj->show_name_value) { 01471 case SHOW_NAME: show_s = name_sym; break; 01472 case SHOW_VALUE: show_s = value_sym; break; 01473 case SHOW_NAME_VALUE: show_s = both_sym; break; 01474 default: 01475 scm_misc_error (s_text_info, 01476 _("Text object ~A has invalid text attribute visibility ~A"), 01477 scm_list_2 (text_s, scm_from_int (obj->show_name_value))); 01478 } 01479 01480 return scm_list_n (scm_from_int (obj->text->x), 01481 scm_from_int (obj->text->y), 01482 align_s, 01483 scm_from_int (obj->text->angle), 01484 scm_from_utf8_string (o_text_get_string (toplevel, obj)), 01485 scm_from_int (obj->text->size), 01486 visible_s, 01487 show_s, 01488 scm_from_int (obj->color), 01489 SCM_UNDEFINED); 01490 } 01491 01505 SCM_DEFINE (object_connections, "%object-connections", 1, 0, 0, 01506 (SCM obj_s), "Get objects that are connected to an object.") 01507 { 01508 /* Ensure that the argument is an object smob */ 01509 SCM_ASSERT (edascm_is_object (obj_s), obj_s, 01510 SCM_ARG1, s_object_connections); 01511 01512 TOPLEVEL *toplevel = edascm_c_current_toplevel (); 01513 OBJECT *obj = edascm_to_object (obj_s); 01514 if (o_get_page (toplevel, obj) == NULL) { 01515 scm_error (edascm_object_state_sym, 01516 s_object_connections, 01517 _("Object ~A is not included in a page."), 01518 scm_list_1 (obj_s), SCM_EOL); 01519 } 01520 01521 GList *lst = s_conn_return_others (NULL, obj); 01522 SCM result = edascm_from_object_glist (lst); 01523 g_list_free (lst); 01524 return result; 01525 } 01526 01538 SCM_DEFINE (object_complex, "%object-complex", 1, 0, 0, 01539 (SCM obj_s), "Get containing complex object of an object.") 01540 { 01541 /* Ensure that the argument is an object smob */ 01542 SCM_ASSERT (edascm_is_object (obj_s), obj_s, 01543 SCM_ARG1, s_object_complex); 01544 01545 TOPLEVEL *toplevel = edascm_c_current_toplevel (); 01546 OBJECT *obj = edascm_to_object (obj_s); 01547 OBJECT *parent = o_get_parent (toplevel, obj); 01548 01549 if (parent == NULL) return SCM_BOOL_F; 01550 01551 return edascm_from_object (parent); 01552 } 01553 01564 SCM_DEFINE (make_path, "%make-path", 0, 0, 0, 01565 (), "Create a new path object") 01566 { 01567 OBJECT *obj = o_path_new (edascm_c_current_toplevel (), 01568 OBJ_PATH, DEFAULT_COLOR, ""); 01569 01570 SCM result = edascm_from_object (obj); 01571 01572 /* At the moment, the only pointer to the object is owned by the 01573 * smob. */ 01574 edascm_c_set_gc (result, TRUE); 01575 01576 return result; 01577 } 01578 01589 SCM_DEFINE (path_length, "%path-length", 1, 0, 0, 01590 (SCM obj_s), "Get number of elements in a path object.") 01591 { 01592 /* Ensure that the argument is a path object */ 01593 SCM_ASSERT (edascm_is_object_type (obj_s, OBJ_PATH), obj_s, 01594 SCM_ARG1, s_path_length); 01595 01596 OBJECT *obj = edascm_to_object (obj_s); 01597 return scm_from_int (obj->path->num_sections); 01598 } 01599 01628 SCM_DEFINE (path_ref, "%path-ref", 2, 0, 0, 01629 (SCM obj_s, SCM index_s), 01630 "Get a path element from a path object.") 01631 { 01632 /* Ensure that the arguments are a path object and integer */ 01633 SCM_ASSERT (edascm_is_object_type (obj_s, OBJ_PATH), obj_s, 01634 SCM_ARG1, s_path_ref); 01635 SCM_ASSERT (scm_is_integer (index_s), index_s, SCM_ARG2, s_path_ref); 01636 01637 OBJECT *obj = edascm_to_object (obj_s); 01638 int idx = scm_to_int (index_s); 01639 01640 /* Check index is valid for path */ 01641 if ((idx < 0) || (idx >= obj->path->num_sections)) { 01642 scm_out_of_range (s_path_ref, index_s); 01643 } 01644 01645 PATH_SECTION *section = &obj->path->sections[idx]; 01646 01647 switch (section->code) { 01648 case PATH_MOVETO: 01649 case PATH_MOVETO_OPEN: 01650 return scm_list_3 (moveto_sym, 01651 scm_from_int (section->x3), 01652 scm_from_int (section->y3)); 01653 case PATH_LINETO: 01654 return scm_list_3 (lineto_sym, 01655 scm_from_int (section->x3), 01656 scm_from_int (section->y3)); 01657 case PATH_CURVETO: 01658 return scm_list_n (curveto_sym, 01659 scm_from_int (section->x1), 01660 scm_from_int (section->y1), 01661 scm_from_int (section->x2), 01662 scm_from_int (section->y2), 01663 scm_from_int (section->x3), 01664 scm_from_int (section->y3), 01665 SCM_UNDEFINED); 01666 case PATH_END: 01667 return scm_list_1 (closepath_sym); 01668 default: 01669 scm_misc_error (s_path_ref, 01670 _("Path object ~A has invalid element type ~A at index ~A"), 01671 scm_list_3 (obj_s, scm_from_int (section->code), index_s)); 01672 } 01673 01674 } 01675 01689 SCM_DEFINE (path_remove_x, "%path-remove!", 2, 0, 0, 01690 (SCM obj_s, SCM index_s), 01691 "Remove a path element from a path object.") 01692 { 01693 /* Ensure that the arguments are a path object and integer */ 01694 SCM_ASSERT (edascm_is_object_type (obj_s, OBJ_PATH), obj_s, 01695 SCM_ARG1, s_path_ref); 01696 SCM_ASSERT (scm_is_integer (index_s), index_s, SCM_ARG2, s_path_ref); 01697 01698 TOPLEVEL *toplevel = edascm_c_current_toplevel (); 01699 OBJECT *obj = edascm_to_object (obj_s); 01700 int idx = scm_to_int (index_s); 01701 01702 if ((idx < 0) || (idx >= obj->path->num_sections)) { 01703 /* Index is valid for path */ 01704 scm_out_of_range (s_path_ref, index_s); 01705 01706 } 01707 01708 o_emit_pre_change_notify (toplevel, obj); 01709 01710 if (idx + 1 == obj->path->num_sections) { 01711 /* Section is last in path */ 01712 obj->path->num_sections--; 01713 01714 } else { 01715 /* Remove section at index by moving all sections above index one 01716 * location down. */ 01717 memmove (&obj->path->sections[idx], 01718 &obj->path->sections[idx+1], 01719 sizeof (PATH_SECTION) * (obj->path->num_sections - idx - 1)); 01720 obj->path->num_sections--; 01721 } 01722 01723 o_emit_change_notify (toplevel, obj); 01724 o_page_changed (toplevel, obj); 01725 01726 return obj_s; 01727 } 01728 01762 SCM_DEFINE (path_insert_x, "%path-insert", 3, 6, 0, 01763 (SCM obj_s, SCM index_s, SCM type_s, 01764 SCM x1_s, SCM y1_s, SCM x2_s, SCM y2_s, SCM x3_s, SCM y3_s), 01765 "Insert a path element into a path object.") 01766 { 01767 SCM_ASSERT (edascm_is_object_type (obj_s, OBJ_PATH), obj_s, 01768 SCM_ARG1, s_path_insert_x); 01769 SCM_ASSERT (scm_is_integer (index_s), index_s, SCM_ARG2, s_path_insert_x); 01770 SCM_ASSERT (scm_is_symbol (type_s), type_s, SCM_ARG3, s_path_insert_x); 01771 01772 TOPLEVEL *toplevel = edascm_c_current_toplevel (); 01773 OBJECT *obj = edascm_to_object (obj_s); 01774 PATH *path = obj->path; 01775 PATH_SECTION section = {0, 0, 0, 0, 0, 0, 0}; 01776 01777 /* Check & extract path element type. */ 01778 if (type_s == closepath_sym) { section.code = PATH_END; } 01779 else if (type_s == moveto_sym) { section.code = PATH_MOVETO; } 01780 else if (type_s == lineto_sym) { section.code = PATH_LINETO; } 01781 else if (type_s == curveto_sym) { section.code = PATH_CURVETO; } 01782 else { 01783 scm_misc_error (s_path_insert_x, 01784 _("Invalid path element type ~A."), 01785 scm_list_1 (type_s)); 01786 } 01787 01788 /* Check the right number of coordinates have been provided. */ 01789 switch (section.code) { 01790 case PATH_CURVETO: 01791 SCM_ASSERT (scm_is_integer (x1_s), x1_s, SCM_ARG4, s_path_insert_x); 01792 section.x1 = scm_to_int (x1_s); 01793 SCM_ASSERT (scm_is_integer (y1_s), y1_s, SCM_ARG5, s_path_insert_x); 01794 section.y1 = scm_to_int (y1_s); 01795 SCM_ASSERT (scm_is_integer (x2_s), x2_s, SCM_ARG6, s_path_insert_x); 01796 section.x2 = scm_to_int (x2_s); 01797 SCM_ASSERT (scm_is_integer (y2_s), y2_s, SCM_ARG7, s_path_insert_x); 01798 section.y2 = scm_to_int (y2_s); 01799 SCM_ASSERT (scm_is_integer (x3_s), x3_s, 8, s_path_insert_x); 01800 section.x3 = scm_to_int (x3_s); 01801 SCM_ASSERT (scm_is_integer (y3_s), y3_s, 9, s_path_insert_x); 01802 section.y3 = scm_to_int (y3_s); 01803 break; 01804 case PATH_MOVETO: 01805 case PATH_MOVETO_OPEN: 01806 case PATH_LINETO: 01807 SCM_ASSERT (scm_is_integer (x1_s), x1_s, SCM_ARG4, s_path_insert_x); 01808 section.x3 = scm_to_int (x1_s); 01809 SCM_ASSERT (scm_is_integer (y1_s), y1_s, SCM_ARG5, s_path_insert_x); 01810 section.y3 = scm_to_int (y1_s); 01811 break; 01812 case PATH_END: 01813 break; 01814 } 01815 01816 /* Start making changes */ 01817 o_emit_pre_change_notify (toplevel, obj); 01818 01819 /* Make sure there's enough space for the new element */ 01820 if (path->num_sections == path->num_sections_max) { 01821 path->sections = g_realloc (path->sections, 01822 (path->num_sections_max <<= 1) * sizeof (PATH_SECTION)); 01823 } 01824 01825 /* Move path contents to make a gap in the right place. */ 01826 int idx = scm_to_int (index_s); 01827 01828 if ((idx < 0) || (idx > path->num_sections)) { 01829 idx = path->num_sections; 01830 } else { 01831 memmove (&path->sections[idx+1], &path->sections[idx], 01832 sizeof (PATH_SECTION) * (path->num_sections - idx)); 01833 } 01834 01835 path->num_sections++; 01836 path->sections[idx] = section; 01837 01838 o_emit_change_notify (toplevel, obj); 01839 o_page_changed (toplevel, obj); 01840 01841 return obj_s; 01842 } 01843 01855 SCM_DEFINE (make_picture, "%make-picture", 0, 0, 0, (), 01856 "Create a new picture object") 01857 { 01858 OBJECT *obj = o_picture_new (edascm_c_current_toplevel (), 01859 NULL, 0, NULL, OBJ_PICTURE, 01860 0, 0, 0, 0, 0, FALSE, TRUE); 01861 SCM result = edascm_from_object (obj); 01862 01863 /* At the moment, the only pointer to the object is owned by the 01864 * smob. */ 01865 edascm_c_set_gc (result, 1); 01866 01867 return result; 01868 } 01869 01889 SCM_DEFINE (picture_info, "%picture-info", 1, 0, 0, 01890 (SCM obj_s), "Get picture object parameters") 01891 { 01892 SCM_ASSERT (edascm_is_object_type (obj_s, OBJ_PICTURE), obj_s, 01893 SCM_ARG1, s_picture_info); 01894 01895 TOPLEVEL *toplevel = edascm_c_current_toplevel (); 01896 OBJECT *obj = edascm_to_object (obj_s); 01897 const gchar *filename = o_picture_get_filename (toplevel, obj); 01898 01899 SCM filename_s = SCM_BOOL_F; 01900 if (filename != NULL) { 01901 filename_s = scm_from_utf8_string (filename); 01902 } 01903 01904 return scm_list_n (filename_s, 01905 scm_from_int (obj->picture->upper_x), 01906 scm_from_int (obj->picture->upper_y), 01907 scm_from_int (obj->picture->lower_x), 01908 scm_from_int (obj->picture->lower_y), 01909 scm_from_int (obj->picture->angle), 01910 (obj->picture->mirrored ? SCM_BOOL_T : SCM_BOOL_F), 01911 SCM_UNDEFINED); 01912 } 01913 01914 /* \brief Set picture object parameters. 01915 * \par Function Description 01916 * Sets the parameters of the picture object \a obj_s. 01917 * 01918 * \note Scheme API: Implements the %set-picture! procedure in the 01919 * (geda core object) module. 01920 * 01921 * \param obj_s the picture object to modify 01922 * \param x1_s the new x-coordinate of the top left of the picture. 01923 * \param y1_s the new y-coordinate of the top left of the picture. 01924 * \param x2_s the new x-coordinate of the bottom right of the picture. 01925 * \param y2_s the new y-coordinate of the bottom right of the picture. 01926 * \param angle_s the new rotation angle. 01927 * \param mirror_s whether the picture object should be mirrored. 01928 * \return the modify \a obj_s. 01929 */ 01930 SCM_DEFINE (set_picture_x, "%set-picture!", 7, 0, 0, 01931 (SCM obj_s, SCM x1_s, SCM y1_s, SCM x2_s, SCM y2_s, SCM angle_s, 01932 SCM mirror_s), "Set picture object parameters") 01933 { 01934 SCM_ASSERT (edascm_is_object_type (obj_s, OBJ_PICTURE), obj_s, 01935 SCM_ARG1, s_set_picture_x); 01936 SCM_ASSERT (scm_is_integer (x1_s), x1_s, SCM_ARG2, s_set_picture_x); 01937 SCM_ASSERT (scm_is_integer (y1_s), x1_s, SCM_ARG3, s_set_picture_x); 01938 SCM_ASSERT (scm_is_integer (x2_s), x1_s, SCM_ARG4, s_set_picture_x); 01939 SCM_ASSERT (scm_is_integer (y2_s), x1_s, SCM_ARG5, s_set_picture_x); 01940 SCM_ASSERT (scm_is_integer (angle_s), angle_s, SCM_ARG6, s_set_picture_x); 01941 01942 TOPLEVEL *toplevel = edascm_c_current_toplevel (); 01943 OBJECT *obj = edascm_to_object (obj_s); 01944 01945 /* Angle */ 01946 int angle = scm_to_int (angle_s); 01947 switch (angle) { 01948 case 0: 01949 case 90: 01950 case 180: 01951 case 270: 01952 /* These are all fine. */ 01953 break; 01954 default: 01955 /* Otherwise, not fine. */ 01956 scm_misc_error (s_set_picture_x, 01957 _("Invalid picture angle ~A. Must be 0, 90, 180, or 270 degrees"), 01958 scm_list_1 (angle_s)); 01959 } 01960 01961 o_emit_pre_change_notify (toplevel, obj); 01962 01963 obj->picture->angle = scm_to_int (angle_s); 01964 obj->picture->mirrored = scm_is_true (mirror_s); 01965 o_picture_modify_all (toplevel, obj, 01966 scm_to_int (x1_s), scm_to_int (y1_s), 01967 scm_to_int (x2_s), scm_to_int (y2_s)); 01968 01969 o_emit_change_notify (toplevel, obj); 01970 return obj_s; 01971 } 01972 01989 SCM_DEFINE (set_picture_data_vector_x, "%set-picture-data/vector!", 01990 3, 0, 0, (SCM obj_s, SCM data_s, SCM filename_s), 01991 "Set a picture object's data from a vector.") 01992 { 01993 SCM vec_s = scm_any_to_s8vector (data_s); 01994 /* Check argument types */ 01995 SCM_ASSERT (edascm_is_object_type (obj_s, OBJ_PICTURE), obj_s, 01996 SCM_ARG1, s_set_picture_data_vector_x); 01997 SCM_ASSERT (scm_is_true (scm_s8vector_p (vec_s)), data_s, SCM_ARG2, 01998 s_set_picture_data_vector_x); 01999 SCM_ASSERT (scm_is_string (filename_s), filename_s, SCM_ARG3, 02000 s_set_picture_data_vector_x); 02001 02002 scm_dynwind_begin (0); 02003 02004 /* Convert vector to contiguous buffer */ 02005 scm_t_array_handle handle; 02006 size_t len; 02007 ssize_t inc; 02008 const scm_t_int8 *elt = scm_s8vector_elements (vec_s, &handle, &len, &inc); 02009 gchar *buf = g_malloc (len); 02010 int i; 02011 02012 scm_dynwind_unwind_handler (g_free, buf, SCM_F_WIND_EXPLICITLY); 02013 02014 for (i = 0; i < len; i++, elt += inc) { 02015 buf[i] = (gchar) *elt; 02016 } 02017 scm_array_handle_release (&handle); 02018 02019 gboolean status; 02020 GError *error = NULL; 02021 TOPLEVEL *toplevel = edascm_c_current_toplevel (); 02022 OBJECT *obj = edascm_to_object (obj_s); 02023 gchar *filename = scm_to_utf8_string (filename_s); 02024 scm_dynwind_unwind_handler (g_free, filename, SCM_F_WIND_EXPLICITLY); 02025 02026 status = o_picture_set_from_buffer (toplevel, obj, filename, 02027 buf, len, &error); 02028 02029 if (!status) { 02030 scm_dynwind_unwind_handler ((void (*)(void *)) g_error_free, error, 02031 SCM_F_WIND_EXPLICITLY); 02032 scm_misc_error (s_set_picture_data_vector_x, 02033 "Failed to set picture image data from vector: ~S", 02034 scm_list_1 (scm_from_utf8_string (error->message))); 02035 } 02036 02037 o_page_changed (toplevel, obj); 02038 scm_dynwind_end (); 02039 return obj_s; 02040 } 02041 02042 02043 02057 SCM_DEFINE (translate_object_x, "%translate-object!", 3, 0, 0, 02058 (SCM obj_s, SCM dx_s, SCM dy_s), "Translate an object.") 02059 { 02060 /* Check argument types */ 02061 SCM_ASSERT (edascm_is_object (obj_s), obj_s, 02062 SCM_ARG1, s_translate_object_x); 02063 SCM_ASSERT (scm_is_integer (dx_s), dx_s, 02064 SCM_ARG2, s_translate_object_x); 02065 SCM_ASSERT (scm_is_integer (dy_s), dy_s, 02066 SCM_ARG3, s_translate_object_x); 02067 02068 TOPLEVEL *toplevel = edascm_c_current_toplevel (); 02069 OBJECT *obj = edascm_to_object (obj_s); 02070 int dx = scm_to_int (dx_s); 02071 int dy = scm_to_int (dy_s); 02072 02073 o_emit_pre_change_notify (toplevel, obj); 02074 o_translate_world (toplevel, dx, dy, obj); 02075 o_emit_change_notify (toplevel, obj); 02076 o_page_changed (toplevel, obj); 02077 02078 return obj_s; 02079 } 02080 02096 SCM_DEFINE (rotate_object_x, "%rotate-object!", 4, 0, 0, 02097 (SCM obj_s, SCM x_s, SCM y_s, SCM angle_s), 02098 "Rotate an object.") 02099 { 02100 /* Check argument types */ 02101 SCM_ASSERT (edascm_is_object (obj_s), obj_s, 02102 SCM_ARG1, s_rotate_object_x); 02103 SCM_ASSERT (scm_is_integer (x_s), x_s, 02104 SCM_ARG2, s_rotate_object_x); 02105 SCM_ASSERT (scm_is_integer (y_s), y_s, 02106 SCM_ARG3, s_rotate_object_x); 02107 SCM_ASSERT (scm_is_integer (angle_s), angle_s, 02108 SCM_ARG4, s_rotate_object_x); 02109 02110 TOPLEVEL *toplevel = edascm_c_current_toplevel (); 02111 OBJECT *obj = edascm_to_object (obj_s); 02112 int x = scm_to_int (x_s); 02113 int y = scm_to_int (y_s); 02114 int angle = scm_to_int (angle_s); 02115 02116 /* FIXME Work around horribly broken libgeda behaviour. Some 02117 * libgeda functions treat a rotation of -90 degrees as a rotation 02118 * of +90 degrees, etc., which is not sane. */ 02119 while (angle < 0) angle += 360; 02120 while (angle >= 360) angle -= 360; 02121 SCM_ASSERT (angle % 90 == 0, angle_s, 02122 SCM_ARG4, s_rotate_object_x); 02123 02124 o_emit_pre_change_notify (toplevel, obj); 02125 o_rotate_world (toplevel, x, y, angle, obj); 02126 o_emit_change_notify (toplevel, obj); 02127 o_page_changed (toplevel, obj); 02128 02129 return obj_s; 02130 } 02131 02143 SCM_DEFINE (mirror_object_x, "%mirror-object!", 2, 0, 0, 02144 (SCM obj_s, SCM x_s), 02145 "Mirror an object.") 02146 { 02147 /* Check argument types */ 02148 SCM_ASSERT (edascm_is_object (obj_s), obj_s, 02149 SCM_ARG1, s_mirror_object_x); 02150 SCM_ASSERT (scm_is_integer (x_s), x_s, 02151 SCM_ARG2, s_mirror_object_x); 02152 02153 TOPLEVEL *toplevel = edascm_c_current_toplevel (); 02154 OBJECT *obj = edascm_to_object (obj_s); 02155 int x = scm_to_int (x_s); 02156 02157 o_emit_pre_change_notify (toplevel, obj); 02158 o_mirror_world (toplevel, x, 0, obj); 02159 o_emit_change_notify (toplevel, obj); 02160 o_page_changed (toplevel, obj); 02161 02162 return obj_s; 02163 } 02164 02171 static void 02172 init_module_geda_core_object () 02173 { 02174 /* Register the functions and symbols */ 02175 #include "scheme_object.x" 02176 02177 /* Add them to the module's public definitions. */ 02178 scm_c_export (s_object_type, s_copy_object, s_object_bounds, 02179 s_object_stroke, s_set_object_stroke_x, 02180 s_object_fill, s_set_object_fill_x, 02181 s_object_color, s_set_object_color_x, 02182 s_make_line, s_make_net, s_make_bus, 02183 s_make_pin, s_pin_type, 02184 s_set_line_x, s_line_info, 02185 s_make_box, s_set_box_x, s_box_info, 02186 s_make_circle, s_set_circle_x, s_circle_info, 02187 s_make_arc, s_set_arc_x, s_arc_info, 02188 s_make_text, s_set_text_x, s_text_info, 02189 s_object_connections, s_object_complex, 02190 s_make_path, s_path_length, s_path_ref, 02191 s_path_remove_x, s_path_insert_x, 02192 s_make_picture, s_picture_info, s_set_picture_x, 02193 s_set_picture_data_vector_x, 02194 s_translate_object_x, s_rotate_object_x, 02195 s_mirror_object_x, 02196 NULL); 02197 } 02198 02205 void 02206 edascm_init_object () 02207 { 02208 /* Define the (geda core object) module */ 02209 scm_c_define_module ("geda core object", 02210 init_module_geda_core_object, 02211 NULL); 02212 }