libgeda

scheme_page.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 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 (edascm_string_format_sym , "string-format");
00031 
00041 SCM_DEFINE (active_pages, "%active-pages", 0, 0, 0,
00042             (), "Retrieve a list of currently-opened pages")
00043 {
00044   TOPLEVEL *toplevel = edascm_c_current_toplevel ();
00045   SCM lst = SCM_EOL;
00046   SCM rlst;
00047   GList *page_list = geda_list_get_glist (toplevel->pages);
00048 
00049   while (page_list != NULL) {
00050     lst = scm_cons (edascm_from_page (page_list->data), lst);
00051     page_list = g_list_next (page_list);
00052   }
00053 
00054   rlst = scm_reverse (lst);
00055   scm_remember_upto_here_1 (lst);
00056   return rlst;
00057 }
00058 
00070 SCM_DEFINE (new_page, "%new-page", 1, 0, 0,
00071             (SCM filename_s), "Create a new page")
00072 {
00073   TOPLEVEL *toplevel = edascm_c_current_toplevel ();
00074   char *filename;
00075   PAGE *page;
00076 
00077   /* Ensure that the argument is a string */
00078   SCM_ASSERT (scm_is_string (filename_s), filename_s,
00079               SCM_ARG1, s_new_page);
00080 
00081   filename = scm_to_utf8_string (filename_s);
00082   page = s_page_new (toplevel, filename);
00083   g_free (filename);
00084 
00085   return edascm_from_page (page);
00086 }
00087 
00101 SCM_DEFINE (close_page_x, "%close-page!", 1, 0, 0,
00102             (SCM page_s), "Close a page.")
00103 {
00104   /* Ensure that the argument is a page smob */
00105   SCM_ASSERT (EDASCM_PAGEP (page_s), page_s,
00106               SCM_ARG1, s_close_page_x);
00107 
00108   TOPLEVEL *toplevel = edascm_c_current_toplevel ();
00109   PAGE *page = edascm_to_page (page_s);
00110 
00111   s_page_delete (toplevel, page);
00112 
00113   return SCM_UNDEFINED;
00114 }
00115 
00125 SCM_DEFINE (page_filename, "%page-filename", 1, 0, 0,
00126             (SCM page_s), "Get a page's associated filename")
00127 {
00128   PAGE *page;
00129 
00130   /* Ensure that the argument is a page smob */
00131   SCM_ASSERT (EDASCM_PAGEP (page_s), page_s,
00132               SCM_ARG1, s_page_filename);
00133 
00134 
00135   page = edascm_to_page (page_s);
00136   return scm_from_utf8_string (page->page_filename);
00137 }
00138 
00150 SCM_DEFINE (set_page_filename_x, "%set-page-filename!", 2, 0, 0,
00151             (SCM page_s, SCM filename_s), "Set a page's associated filename")
00152 {
00153   SCM_ASSERT (EDASCM_PAGEP (page_s), page_s,
00154               SCM_ARG1, s_set_page_filename_x);
00155   SCM_ASSERT (scm_is_string (filename_s), filename_s,
00156               SCM_ARG2, s_set_page_filename_x);
00157 
00158   PAGE *page = edascm_to_page (page_s);
00159   char *new_fn = scm_to_utf8_string (filename_s);
00160   if (page->page_filename != NULL) {
00161     g_free (page->page_filename);
00162   }
00163   page->page_filename = g_strdup (new_fn);
00164   free (new_fn);
00165 
00166   return page_s;
00167 }
00168 
00179 SCM_DEFINE (page_contents, "%page-contents", 1, 0, 0,
00180             (SCM page_s), "Get a page's contents.")
00181 {
00182   PAGE *page;
00183 
00184   /* Ensure that the argument is a page smob */
00185   SCM_ASSERT (EDASCM_PAGEP (page_s), page_s,
00186               SCM_ARG1, s_page_contents);
00187 
00188   page = edascm_to_page (page_s);
00189 
00190   return edascm_from_object_glist (s_page_objects (page));
00191 }
00192 
00204 SCM_DEFINE (object_page, "%object-page", 1, 0, 0,
00205             (SCM obj_s), "Get the page that an object smob belongs to")
00206 {
00207   SCM_ASSERT (EDASCM_OBJECTP (obj_s), obj_s,
00208               SCM_ARG1, s_object_page);
00209 
00210   PAGE *page = o_get_page (edascm_c_current_toplevel (),
00211                            edascm_to_object (obj_s));
00212 
00213   if (page != NULL) {
00214     return edascm_from_page (page);
00215   } else {
00216     return SCM_BOOL_F;
00217   }
00218 }
00219 
00220 
00231 SCM_DEFINE (page_append_x, "%page-append!", 2, 0, 0,
00232             (SCM page_s, SCM obj_s), "Add an object to a page.")
00233 {
00234   /* Ensure that the arguments have the correct types. */
00235   SCM_ASSERT (EDASCM_PAGEP (page_s), page_s,
00236               SCM_ARG1, s_page_append_x);
00237   SCM_ASSERT (EDASCM_OBJECTP (obj_s), obj_s,
00238               SCM_ARG2, s_page_append_x);
00239 
00240   PAGE *page = edascm_to_page (page_s);
00241   OBJECT *obj = edascm_to_object (obj_s);
00242   TOPLEVEL *toplevel = edascm_c_current_toplevel ();
00243 
00244   /* Check that the object isn't already attached to something. */
00245   PAGE *curr_page = o_get_page (toplevel, obj);
00246   if (((curr_page != NULL) && (curr_page != page))
00247       || (obj->parent != NULL)) {
00248     scm_error (edascm_object_state_sym, s_page_append_x,
00249                _("Object ~A is already attached to something"),
00250                scm_list_1 (obj_s), SCM_EOL);
00251   }
00252 
00253   if (curr_page == page) return obj_s;
00254 
00255   /* Object cleanup now managed by C code. */
00256   edascm_c_set_gc (obj_s, 0);
00257   o_emit_pre_change_notify (toplevel, obj);
00258   s_page_append (edascm_c_current_toplevel (), page, obj);
00259   o_emit_change_notify (toplevel, obj);
00260   page->CHANGED = 1; /* Ugh. */
00261 
00262   return page_s;
00263 }
00264 
00276 SCM_DEFINE (page_remove_x, "%page-remove!", 2, 0, 0,
00277             (SCM page_s, SCM obj_s), "Remove an object from a page.")
00278 {
00279   /* Ensure that the arguments have the correct types. */
00280   SCM_ASSERT (EDASCM_PAGEP (page_s), page_s,
00281               SCM_ARG1, s_page_remove_x);
00282   SCM_ASSERT (EDASCM_OBJECTP (obj_s), obj_s,
00283               SCM_ARG2, s_page_remove_x);
00284 
00285   PAGE *page = edascm_to_page (page_s);
00286   OBJECT *obj = edascm_to_object (obj_s);
00287   TOPLEVEL *toplevel = edascm_c_current_toplevel ();
00288 
00289   /* Check that the object is not attached to something else. */
00290   PAGE *curr_page = o_get_page (toplevel, obj);
00291   if ((curr_page != NULL && curr_page != page)
00292       || (obj->parent != NULL)) {
00293     scm_error (edascm_object_state_sym, s_page_remove_x,
00294                _("Object ~A is attached to a complex or different page"),
00295                scm_list_1 (obj_s), SCM_EOL);
00296   }
00297 
00298   /* Check that object is not attached as an attribute. */
00299   if (obj->attached_to != NULL) {
00300     scm_error (edascm_object_state_sym, s_page_remove_x,
00301                _("Object ~A is attached as an attribute"),
00302                scm_list_1 (obj_s), SCM_EOL);
00303   }
00304 
00305   /* Check that object doesn't have attributes. */
00306   if (obj->attribs != NULL) {
00307     scm_error (edascm_object_state_sym, s_page_remove_x,
00308                _("Object ~A has attributes"),
00309                scm_list_1 (obj_s), SCM_EOL);
00310   }
00311 
00312   if (curr_page == NULL) return obj_s;
00313 
00314   o_emit_pre_change_notify (toplevel, obj);
00315   s_page_remove (toplevel, page, obj);
00316   page->CHANGED = 1; /* Ugh. */
00317   /* If the object is currently selected, unselect it. */
00318   o_selection_remove (toplevel, page->selection_list, obj);
00319   o_emit_change_notify (toplevel, obj);
00320 
00321   /* Object cleanup now managed by Guile. */
00322   edascm_c_set_gc (obj_s, 1);
00323   return page_s;
00324 }
00325 
00337 SCM_DEFINE (page_dirty, "%page-dirty?", 1, 0, 0,
00338             (SCM page_s), "Check whether a page has been flagged as changed.")
00339 {
00340   /* Ensure that the argument is a page smob */
00341   SCM_ASSERT (EDASCM_PAGEP (page_s), page_s,
00342               SCM_ARG1, s_page_dirty);
00343 
00344   PAGE *page = edascm_to_page (page_s);
00345   return page->CHANGED ? SCM_BOOL_T : SCM_BOOL_F;
00346 }
00347 
00360 SCM_DEFINE (set_page_dirty_x, "%set-page-dirty!", 2, 0, 0,
00361             (SCM page_s, SCM flag_s),
00362             "Set whether a page is flagged as changed.")
00363 {
00364   /* Ensure that the argument is a page smob */
00365   SCM_ASSERT (EDASCM_PAGEP (page_s), page_s,
00366               SCM_ARG1, s_set_page_dirty_x);
00367 
00368   PAGE *page = edascm_to_page (page_s);
00369   page->CHANGED = scm_is_true (flag_s);
00370   return page_s;
00371 }
00372 
00383 SCM_DEFINE (page_to_string, "%page->string", 1, 0, 0,
00384             (SCM page_s),
00385             "Create a string representation of a page.")
00386 {
00387   /* Ensure that the argument is a page smob */
00388   SCM_ASSERT (EDASCM_PAGEP (page_s), page_s,
00389               SCM_ARG1, s_page_to_string);
00390 
00391   PAGE *page = edascm_to_page (page_s);
00392   TOPLEVEL *toplevel = edascm_c_current_toplevel ();
00393 
00394   gchar *buf = o_save_buffer (toplevel, s_page_objects (page));
00395   scm_dynwind_begin (0);
00396   scm_dynwind_unwind_handler (g_free, buf, SCM_F_WIND_EXPLICITLY);
00397   SCM result = scm_from_utf8_string (buf);
00398   scm_dynwind_end ();
00399   return result;
00400 }
00401 
00415 SCM_DEFINE (string_to_page, "%string->page", 2, 0, 0,
00416             (SCM filename_s, SCM str_s),
00417             "Create a new page from a string.")
00418 {
00419   /* Ensure that the arguments are strings */
00420   SCM_ASSERT (scm_is_string (filename_s), filename_s,
00421               SCM_ARG1, s_string_to_page);
00422   SCM_ASSERT (scm_is_string (str_s), str_s,
00423               SCM_ARG2, s_string_to_page);
00424 
00425   TOPLEVEL *toplevel = edascm_c_current_toplevel ();
00426   char *filename = scm_to_utf8_string (filename_s);
00427   PAGE *page = s_page_new (toplevel, filename);
00428   free (filename);
00429 
00430   size_t len;
00431   GError * err = NULL;
00432   char *str = scm_to_utf8_stringn (str_s, &len);
00433   GList *objects = o_read_buffer (toplevel, NULL, str, len,
00434                                   page->page_filename, &err);
00435   free (str);
00436 
00437   if (err) {
00438       SCM error_message = scm_from_utf8_string (err->message);
00439 
00440       g_error_free(err);
00441       scm_error (edascm_string_format_sym, s_string_to_page,
00442                  _("Parse error: ~s"), scm_list_1 (error_message), SCM_EOL);
00443   }
00444 
00445   s_page_append_list (toplevel, page, objects);
00446 
00447   return edascm_from_page (page);
00448 }
00449 
00456 static void
00457 init_module_geda_core_page ()
00458 {
00459   /* Register the functions */
00460   #include "scheme_page.x"
00461 
00462   /* Add them to the module's public definitions. */
00463 
00464   scm_c_export (s_active_pages, s_new_page, s_close_page_x,
00465                 s_page_filename, s_set_page_filename_x, s_page_contents,
00466                 s_object_page, s_page_append_x, s_page_remove_x, s_page_dirty,
00467                 s_set_page_dirty_x, s_page_to_string, s_string_to_page, NULL);
00468 }
00469 
00476 void
00477 edascm_init_page ()
00478 {
00479   /* Define the (geda core page) module */
00480   scm_c_define_module ("geda core page",
00481                        init_module_geda_core_page,
00482                        NULL);
00483 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines