libgeda

scheme_object.c

Go to the documentation of this file.
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 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines