1 /* gEDA - GPL Electronic Design Automation
2 * gschem - gEDA Schematic Capture
3 * Copyright (C) 1998-2010 Ales Hvezda
4 * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
38 #ifdef HAVE_LIBDMALLOC
42 #include <gdk/gdkkeysyms.h>
45 #define DEFINE_G_KEYS(name) \
46 SCM g_keys_ ## name(SCM rest) \
48 GSCHEM_TOPLEVEL *w_current = g_current_window (); \
49 i_callback_ ## name(w_current, 0, NULL); \
53 /*! \brief test-comment
56 DEFINE_G_KEYS(file_new
)
58 DEFINE_G_KEYS(file_new_window
)
60 /* don't use the widget parameter on this function, or do some checking... */
61 /* since there is a call: widget = NULL, data = 0 (will be w_current) */
62 /* This should be renamed to page_open perhaps... */
63 DEFINE_G_KEYS(file_open
)
65 /* don't use the widget parameter on this function, or do some checking... */
66 /* since there is a call: widget = NULL, data = 0 (will be w_current) */
67 DEFINE_G_KEYS(file_script
)
69 /* don't use the widget parameter on this function, or do some checking... */
70 /* since there is a call: widget = NULL, data = 0 (will be w_current) */
71 DEFINE_G_KEYS(file_save
)
72 DEFINE_G_KEYS(file_save_as
)
73 DEFINE_G_KEYS(file_save_all
)
74 DEFINE_G_KEYS(file_print
)
75 DEFINE_G_KEYS(file_write_png
)
77 /* don't use the widget parameter on this function, or do some checking... */
78 /* since there is a call: widget = NULL, data = 0 (will be w_current) */
79 /* this function closes a window */
80 DEFINE_G_KEYS(file_close
)
81 DEFINE_G_KEYS(file_quit
)
83 /* Select also does not update the middle button shortcut */
84 DEFINE_G_KEYS(edit_undo
)
85 DEFINE_G_KEYS(edit_redo
)
86 DEFINE_G_KEYS(edit_select
)
87 DEFINE_G_KEYS(edit_select_all
)
88 DEFINE_G_KEYS(edit_deselect
)
89 DEFINE_G_KEYS(edit_copy
)
90 DEFINE_G_KEYS(edit_mcopy
)
91 DEFINE_G_KEYS(edit_move
)
92 DEFINE_G_KEYS(edit_delete
)
93 DEFINE_G_KEYS(edit_rotate_90
)
94 DEFINE_G_KEYS(edit_mirror
)
95 DEFINE_G_KEYS(edit_slot
)
96 DEFINE_G_KEYS(edit_color
)
97 DEFINE_G_KEYS(edit_edit
)
98 DEFINE_G_KEYS(edit_pin_type
)
99 DEFINE_G_KEYS(edit_text
)
100 DEFINE_G_KEYS(edit_lock
)
101 DEFINE_G_KEYS(edit_unlock
)
102 DEFINE_G_KEYS(edit_linetype
)
103 DEFINE_G_KEYS(edit_filltype
)
104 DEFINE_G_KEYS(edit_translate
)
105 DEFINE_G_KEYS(edit_invoke_macro
)
106 DEFINE_G_KEYS(edit_embed
)
107 DEFINE_G_KEYS(edit_unembed
)
108 DEFINE_G_KEYS(edit_update
)
109 DEFINE_G_KEYS(edit_show_hidden
)
110 DEFINE_G_KEYS(edit_find
)
111 DEFINE_G_KEYS(edit_show_text
)
112 DEFINE_G_KEYS(edit_hide_text
)
113 DEFINE_G_KEYS(edit_autonumber_text
)
115 DEFINE_G_KEYS(clipboard_copy
)
116 DEFINE_G_KEYS(clipboard_cut
)
117 DEFINE_G_KEYS(clipboard_paste
)
119 DEFINE_G_KEYS(buffer_copy1
)
120 DEFINE_G_KEYS(buffer_copy2
)
121 DEFINE_G_KEYS(buffer_copy3
)
122 DEFINE_G_KEYS(buffer_copy4
)
123 DEFINE_G_KEYS(buffer_copy5
)
124 DEFINE_G_KEYS(buffer_cut1
)
125 DEFINE_G_KEYS(buffer_cut2
)
126 DEFINE_G_KEYS(buffer_cut3
)
127 DEFINE_G_KEYS(buffer_cut4
)
128 DEFINE_G_KEYS(buffer_cut5
)
129 DEFINE_G_KEYS(buffer_paste1
)
130 DEFINE_G_KEYS(buffer_paste2
)
131 DEFINE_G_KEYS(buffer_paste3
)
132 DEFINE_G_KEYS(buffer_paste4
)
133 DEFINE_G_KEYS(buffer_paste5
)
135 /* repeat middle shortcut doesn't make sense on redraw, just hit right
137 DEFINE_G_KEYS(view_redraw
)
139 /* for these functions, repeat middle shortcut would get into the way
140 * of what user is try to do */
141 DEFINE_G_KEYS(view_zoom_full
)
142 DEFINE_G_KEYS(view_zoom_extents
)
143 DEFINE_G_KEYS(view_zoom_in
)
144 DEFINE_G_KEYS(view_zoom_out
)
146 DEFINE_G_KEYS(view_zoom_box
)
147 DEFINE_G_KEYS(view_pan
)
148 DEFINE_G_KEYS(view_pan_left
)
149 DEFINE_G_KEYS(view_pan_right
)
150 DEFINE_G_KEYS(view_pan_up
)
151 DEFINE_G_KEYS(view_pan_down
)
152 DEFINE_G_KEYS(view_dark_colors
)
153 DEFINE_G_KEYS(view_light_colors
)
154 DEFINE_G_KEYS(view_bw_colors
)
155 DEFINE_G_KEYS(page_manager
)
156 DEFINE_G_KEYS(page_next
)
157 DEFINE_G_KEYS(page_prev
)
158 DEFINE_G_KEYS(page_close
)
159 DEFINE_G_KEYS(page_revert
)
160 DEFINE_G_KEYS(page_print
)
161 DEFINE_G_KEYS(add_component
)
162 DEFINE_G_KEYS(add_attribute
)
163 DEFINE_G_KEYS(add_net
)
164 DEFINE_G_KEYS(add_bus
)
165 DEFINE_G_KEYS(add_text
)
166 DEFINE_G_KEYS(add_line
)
167 DEFINE_G_KEYS(add_path
)
168 DEFINE_G_KEYS(add_box
)
169 DEFINE_G_KEYS(add_picture
)
170 DEFINE_G_KEYS(add_circle
)
171 DEFINE_G_KEYS(add_arc
)
172 DEFINE_G_KEYS(add_pin
)
173 DEFINE_G_KEYS(hierarchy_down_schematic
)
174 DEFINE_G_KEYS(hierarchy_down_symbol
)
175 DEFINE_G_KEYS(hierarchy_up
)
176 DEFINE_G_KEYS(attributes_attach
)
177 DEFINE_G_KEYS(attributes_detach
)
178 DEFINE_G_KEYS(attributes_show_name
)
179 DEFINE_G_KEYS(attributes_show_value
)
180 DEFINE_G_KEYS(attributes_show_both
)
181 DEFINE_G_KEYS(attributes_visibility_toggle
)
183 /* i_callback_script_console is not currently implemented */
184 DEFINE_G_KEYS(script_console
)
186 /* repeat last command doesn't make sense on options either??? (does
188 DEFINE_G_KEYS(options_text_size
)
190 /* repeat last command doesn't make sense on options either??? (does
192 DEFINE_G_KEYS(options_afeedback
)
193 DEFINE_G_KEYS(options_grid
)
194 DEFINE_G_KEYS(options_snap
)
195 DEFINE_G_KEYS(options_snap_size
)
196 DEFINE_G_KEYS(options_scale_up_snap_size
)
197 DEFINE_G_KEYS(options_scale_down_snap_size
)
198 DEFINE_G_KEYS(options_rubberband
)
199 DEFINE_G_KEYS(options_magneticnet
)
200 DEFINE_G_KEYS(options_show_log_window
)
201 DEFINE_G_KEYS(options_show_coord_window
)
203 DEFINE_G_KEYS(help_about
)
204 DEFINE_G_KEYS(help_hotkeys
)
206 /* be sure that you don't use the widget parameter in this one, since it is
207 being called with a null, I suppose we should call it with the right param.
209 DEFINE_G_KEYS(cancel
)
211 /*! Contains the smob tag for key smobs */
212 static scm_t_bits g_key_smob_tag
;
213 #define G_SCM_IS_KEY(x) SCM_SMOB_PREDICATE (g_key_smob_tag, (x))
215 /*! Type for keybindings. Used internally by gschem key smobs. */
218 GdkModifierType modifiers
;
219 gchar
*str
; /* UTF-8. Free with g_free(). */
220 gchar
*disp_str
; /* UTF-8. Free with g_free(). */
223 /*! \brief Test if a key is valid.
224 * \par Function Description
225 * Test if the key combination defined by \a keyval and \a modifiers
226 * is valid for key binding. This is a less restrictive version of
227 * gtk_accelerator_valid() from GTK 2.
229 * \param keyval The key that was pressed.
230 * \param modifiers The active modifiers when the key was pressed.
232 * \return TRUE if the key combination is valid for keybinding.
235 g_key_is_valid (guint keyval
, GdkModifierType modifiers
)
237 static const guint invalid_keyvals
[] = {
238 GDK_Shift_L
, GDK_Shift_R
, GDK_Shift_Lock
, GDK_Caps_Lock
, GDK_ISO_Lock
,
239 GDK_Control_L
, GDK_Control_R
, GDK_Meta_L
, GDK_Meta_R
,
240 GDK_Alt_L
, GDK_Alt_R
, GDK_Super_L
, GDK_Super_R
, GDK_Hyper_L
, GDK_Hyper_R
,
241 GDK_ISO_Level3_Shift
, GDK_ISO_Next_Group
, GDK_ISO_Prev_Group
,
242 GDK_ISO_First_Group
, GDK_ISO_Last_Group
,
243 GDK_Mode_switch
, GDK_Num_Lock
, GDK_Multi_key
,
244 GDK_Scroll_Lock
, GDK_Sys_Req
,
245 GDK_Tab
, GDK_ISO_Left_Tab
, GDK_KP_Tab
,
246 GDK_First_Virtual_Screen
, GDK_Prev_Virtual_Screen
,
247 GDK_Next_Virtual_Screen
, GDK_Last_Virtual_Screen
,
248 GDK_Terminate_Server
, GDK_AudibleBell_Enable
,
253 /* Exclude a bunch of control chars */
254 if (keyval
<= 0xFF) return keyval
>= 0x20;
256 /* Exclude special & modifier keys */
257 val
= invalid_keyvals
;
259 if (keyval
== *val
++) return FALSE
;
265 /*! \brief Create a new bindable key object.
266 * \par Function Description
267 * Create and return a new gschem key object from a \a keyval and a
268 * set of \a modifiers. If the key combination is invalid, return
271 * \param keyval the pressed key.
272 * \param modifiers the active modifiers for the key.
274 * \return a new bindable key object, or SCM_BOOL_F.
277 g_make_key (guint keyval
, GdkModifierType modifiers
)
279 SCM result
= SCM_BOOL_F
;
280 if (g_key_is_valid (keyval
, modifiers
)) {
281 GschemKey
*k
= g_new0 (GschemKey
, 1);
283 k
->modifiers
= modifiers
& GDK_MODIFIER_MASK
;
284 SCM_NEWSMOB (result
, g_key_smob_tag
, k
);
289 /*! \brief Test if a Scheme value is a bindable key object.
290 * \par Function Description
291 * Returns SCM_BOOL_T if \a key_s is a gschem key object. Otherwise,
292 * returns SCM_BOOL_F.
294 * \note Scheme API: Implements the %key? procedure in the
295 * (gschem core keymap) module.
297 * \param key_s value to test
298 * \return SCM_BOOL_T iff value is a key, otherwise SCM_BOOL_F.
300 SCM_DEFINE (g_keyp
, "%key?", 1, 0, 0, (SCM key_s
),
301 "Test if value is a gschem key.")
303 if (G_SCM_IS_KEY (key_s
)) {
310 /*! \brief Create a bindable key object from a string.
311 * \par Function Description
312 * Parse the string key description \a str_s to create and return a
313 * new gschem key object. If \a str_s contains syntax errors, or does
314 * not represent a valid bindable key combination, returns SCM_BOOL_F.
316 * \note Scheme API: Implements the %string-key procedure in the
317 * (gschem core keymap) module.
319 * \param str_s string to parse.
320 * \return a new gschem key object, or SCM_BOOL_F.
322 SCM_DEFINE (g_string_to_key
, "%string->key", 1, 0, 0, (SCM str_s
),
323 "Create a gschem key by parsing a string.")
325 SCM_ASSERT (scm_is_string (str_s
), str_s
, SCM_ARG1
, s_g_string_to_key
);
328 GdkModifierType modifiers
;
329 char *str
= scm_to_utf8_string (str_s
);
330 gtk_accelerator_parse (str
, &keyval
, &modifiers
);
331 if ((keyval
== 0) && (modifiers
== 0)) return SCM_BOOL_F
;
332 return g_make_key (keyval
, modifiers
);
335 /*! \brief Convert a bindable key object to a string.
336 * \par Function Description
337 * Returns a string representation of the gschem key object \a key_s,
338 * in a format suitable for parsing with %string->key.
340 * \note Scheme API: Implements the %key->string procedure in the
341 * (gschem core keymap) module.
343 * \param key_s Bindable key object to convert to string.
344 * \return a string representation of the key combination.
346 SCM_DEFINE (g_key_to_string
, "%key->string", 1, 0, 0, (SCM key_s
),
347 "Create a string from a gschem key.")
349 SCM_ASSERT (G_SCM_IS_KEY (key_s
), key_s
, SCM_ARG1
, s_g_key_to_string
);
351 GschemKey
*key
= (GschemKey
*) SCM_SMOB_DATA (key_s
);
352 if (key
->str
!= NULL
) return scm_from_utf8_string (key
->str
);
354 key
->str
= gtk_accelerator_name (key
->keyval
, key
->modifiers
);
355 return scm_from_utf8_string (key
->str
);
358 /*! \brief Convert a bindable key object to a displayable string.
359 * \par Function Description
360 * Returns a string representation of the gschem key object \a key_s,
361 * in a format suitable for display to the user (e.g. as accelerator
364 * \note Scheme API: Implements the %key->display-string procedure in
365 * the (gschem core keymap) module.
367 * \param key_s Bindable key object to convert to string.
368 * \return a string representation of the key combination.
370 SCM_DEFINE (g_key_to_display_string
, "%key->display-string", 1, 0, 0,
371 (SCM key_s
), "Create a display string from a gschem key.")
373 SCM_ASSERT (G_SCM_IS_KEY (key_s
), key_s
, SCM_ARG1
,
374 s_g_key_to_display_string
);
376 GschemKey
*key
= (GschemKey
*) SCM_SMOB_DATA (key_s
);
377 if (key
->disp_str
!= NULL
) return scm_from_utf8_string (key
->disp_str
);
379 key
->disp_str
= gtk_accelerator_get_label (key
->keyval
, key
->modifiers
);
380 return scm_from_utf8_string (key
->disp_str
);
383 /*! \brief Print a representation of a key smob
384 * \par Function Description
385 * Outputs a string representing the \a smob to a Scheme output \a
386 * port. The format used is "#<gschem-key \"Ctrl+A\">".
388 * Used internally to Guile.
391 g_key_print (SCM smob
, SCM port
, scm_print_state
*pstate
)
393 scm_puts ("#<gschem-key ", port
);
394 scm_write (g_key_to_display_string (smob
), port
);
395 scm_puts (">", port
);
397 /* Non-zero means success */
401 /* \brief Test if two key combinations are equivalent.
402 * \par Function Description
403 * Tests if the two gschem key objects \a a and \a b represent the
406 * Used internally to Guile.
409 g_key_equalp (SCM a
, SCM b
)
411 GschemKey
*akey
= (GschemKey
*) SCM_SMOB_DATA (a
);
412 GschemKey
*bkey
= (GschemKey
*) SCM_SMOB_DATA (b
);
413 if (akey
->keyval
!= bkey
->keyval
) return SCM_BOOL_F
;
414 if (akey
->modifiers
!= bkey
->modifiers
) return SCM_BOOL_F
;
418 /* \brief Destroy a bindable key object
419 * \par Function Description
420 * Destroys the contents of a gschem key object on garbage collection.
422 * Used internally to Guile.
425 g_key_free (SCM key
) {
426 GschemKey
*k
= (GschemKey
*) SCM_SMOB_DATA (key
);
428 g_free (k
->disp_str
);
433 SCM_SYMBOL (reset_keys_sym
, "reset-keys");
434 SCM_SYMBOL (press_key_sym
, "press-key");
435 SCM_SYMBOL (prefix_sym
, "prefix");
437 /*! \brief Clear the current key accelerator string.
438 * \par Function Description
439 * This function clears the current keyboard accelerator string in
440 * the status bar of the relevant toplevel. Called some time after a
441 * keystroke is pressed. If the current key sequence was a prefix,
444 * \param [in] data a pointer to the GSCHEM_TOPLEVEL to update.
445 * \return FALSE (this is a one-shot timer).
447 static gboolean
clear_keyaccel_string(gpointer data
)
449 GSCHEM_TOPLEVEL
*w_current
= data
;
451 /* If the window context has disappeared, do nothing. */
452 if (g_list_find(global_window_list
, w_current
) == NULL
) {
456 g_free(w_current
->keyaccel_string
);
457 w_current
->keyaccel_string
= NULL
;
458 w_current
->keyaccel_string_source_id
= 0;
459 i_show_state(w_current
, NULL
);
463 /*! \brief Reset the current key sequence.
464 * \par Function Description
465 * If any prefix keys are stored in the current key sequence, clears
468 * \param w_current The active #GSCHEM_TOPLEVEL context.
471 g_keys_reset (GSCHEM_TOPLEVEL
*w_current
)
473 SCM s_expr
= scm_list_1 (reset_keys_sym
);
475 /* Reset the status bar */
476 g_free (w_current
->keyaccel_string
);
477 w_current
->keyaccel_string
= NULL
;
478 i_show_state(w_current
, NULL
);
480 /* Reset the Scheme keybinding state */
481 scm_dynwind_begin (0);
482 g_dynwind_window (w_current
);
483 g_scm_eval_protected (s_expr
, scm_interaction_environment ());
487 /*! \brief Evaluate a user keystroke.
488 * \par Function Description
489 * Evaluates the key combination specified by \a event using the
490 * current keymap. Updates the gschem status bar with the current key
493 * \param w_current The active #GSCHEM_TOPLEVEL context.
494 * \param event A GdkEventKey structure.
496 * \return 1 if a binding was found for the keystroke, 0 otherwise.
499 g_keys_execute(GSCHEM_TOPLEVEL
*w_current
, GdkEventKey
*event
)
501 SCM s_retval
, s_key
, s_expr
;
502 guint key
, mods
, upper
, lower
, caps
;
505 GdkModifierType consumed_modifiers
;
507 g_return_val_if_fail (w_current
!= NULL
, 0);
508 g_return_val_if_fail (event
!= NULL
, 0);
510 display
= gtk_widget_get_display (w_current
->main_window
);
511 keymap
= gdk_keymap_get_for_display (display
);
513 /* Figure out what modifiers went into determining the key symbol */
514 gdk_keymap_translate_keyboard_state (keymap
,
515 event
->hardware_keycode
,
516 event
->state
, event
->group
,
517 NULL
, NULL
, NULL
, &consumed_modifiers
);
520 gdk_keyval_convert_case (event
->keyval
, &lower
, &upper
);
521 mods
= (event
->state
& gtk_accelerator_get_default_mod_mask ()
522 & ~consumed_modifiers
);
524 /* Handle Caps Lock. The idea is to obtain the same keybindings
525 * whether Caps Lock is enabled or not. */
526 if (upper
!= lower
) {
527 caps
= gdk_keymap_get_caps_lock_state (keymap
);
528 if ((caps
&& (key
== lower
)) || (!caps
&& (key
== upper
))) {
529 mods
|= GDK_SHIFT_MASK
;
533 /* Always process key as lower case */
536 /* Validate the key -- there are some keystrokes we mask out. */
537 if (!g_key_is_valid (key
, mods
)) {
541 /* Create Scheme key value */
542 s_key
= g_make_key (key
, mods
);
544 /* Update key hint string for status bar. */
545 gchar
*keystr
= gtk_accelerator_get_label (key
, mods
);
547 /* If no current hint string, or the hint string is going to be
548 * cleared anyway, use key string directly */
549 if ((w_current
->keyaccel_string
== NULL
) ||
550 w_current
->keyaccel_string_source_id
) {
551 g_free (w_current
->keyaccel_string
);
552 w_current
->keyaccel_string
= keystr
;
555 gchar
*p
= w_current
->keyaccel_string
;
556 w_current
->keyaccel_string
= g_strconcat (p
, " ", keystr
, NULL
);
561 /* Update status bar */
562 i_show_state(w_current
, NULL
);
564 /* Build and evaluate Scheme expression. */
565 scm_dynwind_begin (0);
566 g_dynwind_window (w_current
);
567 s_expr
= scm_list_2 (press_key_sym
, s_key
);
568 s_retval
= g_scm_eval_protected (s_expr
, scm_interaction_environment ());
571 /* If the keystroke was not part of a prefix, start a timer to clear
572 * the status bar display. */
573 if (w_current
->keyaccel_string_source_id
) {
574 /* Cancel any existing timers that haven't fired yet. */
576 g_main_context_find_source_by_id (NULL
,
577 w_current
->keyaccel_string_source_id
);
578 g_source_destroy (timer
);
579 w_current
->keyaccel_string_source_id
= 0;
581 if (!scm_is_eq (s_retval
, prefix_sym
)) {
582 w_current
->keyaccel_string_source_id
=
583 g_timeout_add(400, clear_keyaccel_string
, w_current
);
586 return !scm_is_false (s_retval
);
589 /*! \brief Exports the keymap in Scheme to a GtkListStore
590 * \par Function Description
591 * This function converts the list of key sequence/action pairs
592 * returned by the Scheme function \c dump-global-keymap into a
593 * GtkListStore with two columns. The first column contains the name
594 * of the action executed by the keybinding as a string, and the
595 * second contains the keybinding itself as a string suitable for
598 * The returned value must be freed by caller.
600 * \return A GtkListStore containing keymap data.
603 g_keys_to_list_store (void)
608 GtkListStore
*list_store
;
610 /* Call Scheme procedure to dump global keymap into list */
611 s_expr
= scm_list_1 (scm_from_utf8_symbol ("dump-global-keymap"));
612 s_lst
= g_scm_eval_protected (s_expr
, scm_interaction_environment ());
614 g_return_val_if_fail (scm_is_true (scm_list_p (s_lst
)), NULL
);
617 scm_dynwind_begin (0);
618 list_store
= gtk_list_store_new (2, G_TYPE_STRING
, G_TYPE_STRING
);
619 scm_dynwind_unwind_handler (g_object_unref
, list_store
, 0);
621 for (s_iter
= s_lst
; !scm_is_null (s_iter
); s_iter
= scm_cdr (s_iter
)) {
622 SCM s_binding
= scm_caar (s_iter
);
623 SCM s_keys
= scm_cdar (s_iter
);
624 char *binding
, *keys
;
627 scm_dynwind_begin (0);
629 binding
= scm_to_utf8_string (s_binding
);
630 scm_dynwind_free (binding
);
632 keys
= scm_to_utf8_string (s_keys
);
633 scm_dynwind_free (keys
);
635 gtk_list_store_insert_with_values (list_store
, &iter
, -1,
647 /*! \brief Create the (gschem core keymap) Scheme module
648 * \par Function Description
649 * Defines procedures in the (gschem core keymap) module. The module
650 * can be accessed using (use-modules (gschem core keymap)).
653 init_module_gschem_core_keymap ()
655 /* Register the functions */
658 /* Add them to the module's public definitions */
659 scm_c_export (s_g_keyp
, s_g_string_to_key
, s_g_key_to_string
,
660 s_g_key_to_display_string
, NULL
);
663 /*! \brief Initialise the key combination procedures
664 * \par Function Description
665 * Registers some Scheme procedures for working with key combinations.
666 * Should only be called by main_prog().
671 /* Register key smob type */
672 g_key_smob_tag
= scm_make_smob_type ("gschem-key", 0);
673 scm_set_smob_print (g_key_smob_tag
, g_key_print
);
674 scm_set_smob_equalp (g_key_smob_tag
, g_key_equalp
);
675 scm_set_smob_free (g_key_smob_tag
, g_key_free
);
677 scm_c_define_module ("gschem core keymap",
678 init_module_gschem_core_keymap
,