gschem
|
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 }