gschem

g_window.c

Go to the documentation of this file.
00001 /* gEDA - GPL Electronic Design Automation
00002  * gschem - gEDA Schematic Capture
00003  * Copyright (C) 2010-2011 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 #include <config.h>
00020 
00021 #include "gschem.h"
00022 
00023 SCM scheme_window_fluid = SCM_UNDEFINED;
00024 
00025 scm_t_bits window_smob_tag;
00026 
00033 static size_t
00034 smob_free (SCM smob)
00035 {
00036   GSCHEM_TOPLEVEL *window = (GSCHEM_TOPLEVEL *) SCM_SMOB_DATA (smob);
00037 
00038   /* If the weak ref has been cleared, do nothing */
00039   if (window == NULL) return 0;
00040 
00041   /* Otherwise, go away. */
00042   window->smob = SCM_UNDEFINED;
00043 
00044   return 0;
00045 }
00046 
00054 static int
00055 smob_print (SCM smob, SCM port, scm_print_state *pstate)
00056 {
00057   gchar *hexstring;
00058 
00059   scm_puts ("#<gschem-window", port);
00060 
00061   scm_dynwind_begin (0);
00062   hexstring = g_strdup_printf (" %zx", SCM_SMOB_DATA (smob));
00063   scm_dynwind_unwind_handler (g_free, hexstring, SCM_F_WIND_EXPLICITLY);
00064   scm_puts (hexstring, port);
00065   scm_dynwind_end ();
00066 
00067   scm_puts (">", port);
00068 
00069   /* Non-zero means success */
00070   return 1;
00071 }
00072 
00080 SCM
00081 g_scm_from_window (GSCHEM_TOPLEVEL *w_current)
00082 {
00083   g_assert (w_current != NULL);
00084 
00085   if (w_current->smob == SCM_UNDEFINED) {
00086     SCM_NEWSMOB (w_current->smob, window_smob_tag, w_current);
00087   }
00088 
00089   return w_current->smob;
00090 }
00091 
00102 void
00103 g_dynwind_window (GSCHEM_TOPLEVEL *w_current)
00104 {
00105   SCM window_s = g_scm_from_window (w_current);
00106   scm_dynwind_fluid (scheme_window_fluid, window_s);
00107   edascm_dynwind_toplevel (w_current->toplevel);
00108 }
00109 
00116 SCM_DEFINE (current_window, "%current-window", 0, 0, 0,
00117             (),
00118             "Get the GSCHEM_TOPLEVEL for the current dynamic context.")
00119 {
00120   return scm_fluid_ref (scheme_window_fluid);
00121 }
00122 
00129 GSCHEM_TOPLEVEL *
00130 g_current_window ()
00131 {
00132   SCM window_s = current_window ();
00133 
00134   if (!(SCM_SMOB_PREDICATE (window_smob_tag, window_s)
00135         &&  ((void *)SCM_SMOB_DATA (window_s) != NULL))) {
00136     scm_misc_error (NULL, _("Found invalid gschem window smob ~S"),
00137                     scm_list_1 (window_s));
00138   }
00139 
00140   return (GSCHEM_TOPLEVEL *) SCM_SMOB_DATA (window_s);
00141 }
00142 
00154 SCM_DEFINE (active_page, "%active-page", 0, 0, 0,
00155             (), "Get the active page.")
00156 {
00157   TOPLEVEL *toplevel = edascm_c_current_toplevel ();
00158   if (toplevel->page_current != NULL) {
00159     return edascm_from_page (toplevel->page_current);
00160   } else {
00161     return SCM_BOOL_F;
00162   }
00163 }
00164 
00177 SCM_DEFINE (set_active_page_x, "%set-active-page!", 1, 0, 0,
00178             (SCM page_s), "Set the active page.")
00179 {
00180   SCM_ASSERT (edascm_is_page (page_s), page_s, SCM_ARG1, s_set_active_page_x);
00181 
00182   PAGE *page = edascm_to_page (page_s);
00183   x_window_set_current_page (g_current_window (), page);
00184 
00185   return page_s;
00186 }
00187 
00200 SCM_DEFINE (override_close_page_x, "%close-page!", 1, 0, 0,
00201             (SCM page_s), "Close a page.")
00202 {
00203   /* Ensure that the argument is a page smob */
00204   SCM_ASSERT (edascm_is_page (page_s), page_s,
00205               SCM_ARG1, s_override_close_page_x);
00206 
00207   GSCHEM_TOPLEVEL *w_current = g_current_window ();
00208   TOPLEVEL *toplevel = w_current->toplevel;
00209   PAGE *page = edascm_to_page (page_s);
00210 
00211   /* If page is not the current page, switch pages, then switch back
00212    * after closing page. */
00213   PAGE *curr_page = toplevel->page_current;
00214   int reset_page = (page != curr_page);
00215   if (reset_page)
00216     x_window_set_current_page (w_current, page);
00217 
00218   x_window_close_page (w_current, w_current->toplevel->page_current);
00219 
00220   if (reset_page)
00221     x_window_set_current_page (w_current, curr_page);
00222 
00223   return SCM_UNDEFINED;
00224 }
00225 
00242 SCM_DEFINE (pointer_position, "%pointer-position", 0, 0, 0,
00243             (), "Get the current pointer position.")
00244 {
00245   int x, y;
00246   GSCHEM_TOPLEVEL *w_current = g_current_window ();
00247   if (x_event_get_pointer_position (w_current, FALSE, &x, &y)) {
00248     return scm_cons (scm_from_int (x), scm_from_int (y));
00249   }
00250   return SCM_BOOL_F;
00251 }
00252 
00271 SCM_DEFINE (snap_point, "%snap-point", 2, 0, 0,
00272             (SCM x_s, SCM y_s), "Get the current snap grid size.")
00273 {
00274   SCM_ASSERT (scm_is_integer (x_s), x_s, SCM_ARG1, s_snap_point);
00275   SCM_ASSERT (scm_is_integer (y_s), y_s, SCM_ARG2, s_snap_point);
00276 
00277   /* We save and restore the current snap setting, because we want to
00278    * *always* snap the requested cordinates. */
00279   GSCHEM_TOPLEVEL *w_current = g_current_window ();
00280   int save_snap = w_current->snap;
00281   w_current->snap = SNAP_GRID;
00282   int x = snap_grid (w_current, scm_to_int (x_s));
00283   int y = snap_grid (w_current, scm_to_int (y_s));
00284   w_current->snap = save_snap;
00285 
00286   return scm_cons (scm_from_int (x), scm_from_int (y));
00287 }
00288 
00295 static void
00296 init_module_gschem_core_window ()
00297 {
00298   /* Register the functions */
00299   #include "g_window.x"
00300 
00301   /* Add them to the module's public definitions. */
00302   scm_c_export (s_current_window, s_active_page, s_set_active_page_x,
00303                 s_override_close_page_x, s_pointer_position,
00304                 s_snap_point, NULL);
00305 
00306   /* Override procedures in the (geda core page) module */
00307   {
00308     SCM geda_page_module = scm_c_resolve_module ("geda core page");
00309     SCM close_page_proc =
00310       scm_variable_ref (scm_c_lookup (s_override_close_page_x));
00311     scm_c_module_define (geda_page_module, "close-page!", close_page_proc);
00312   }
00313 }
00314 
00323 void
00324 g_init_window ()
00325 {
00326   /* Register gEDA smob type */
00327   window_smob_tag = scm_make_smob_type ("gschem-window", 0);
00328   scm_set_smob_free (window_smob_tag, smob_free);
00329   scm_set_smob_print (window_smob_tag, smob_print);
00330 
00331   /* Create fluid */
00332   scheme_window_fluid = scm_permanent_object (scm_make_fluid ());
00333 
00334   /* Define the (gschem core window) module */
00335   scm_c_define_module ("gschem core window",
00336                        init_module_gschem_core_window,
00337                        NULL);
00338 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines