* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#include "config.h"
-#include "gdkinternals.h"
-#include "gdkkeys.h"
-
+#include "gdkkeysyms.h"
+#include "gdkkeysprivate.h"
#include "gdkdisplay.h"
+#include "gdkdisplaymanagerprivate.h"
/**
LAST_SIGNAL
};
+
+static GdkModifierType gdk_keymap_real_get_modifier_mask (GdkKeymap *keymap,
+ GdkModifierIntent intent);
+
+
static guint signals[LAST_SIGNAL] = { 0 };
G_DEFINE_TYPE (GdkKeymap, gdk_keymap, G_TYPE_OBJECT)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ klass->get_modifier_mask = gdk_keymap_real_get_modifier_mask;
+
/**
* GdkKeymap::direction-changed:
* @keymap: the object on which the signal is emitted
- *
+ *
* The ::direction-changed signal gets emitted when the direction of
- * the keymap changes.
+ * the keymap changes.
*
* Since: 2.0
*/
G_STRUCT_OFFSET (GdkKeymapClass, state_changed),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE,
+ G_TYPE_NONE,
0);
}
/* Other key-handling stuff
*/
-#ifndef HAVE_XCONVERTCASE
-#include "gdkkeysyms.h"
-
-/* compatibility function from X11R6.3, since XConvertCase is not
- * supplied by X11R5.
- */
/**
* gdk_keyval_convert_case:
* @symbol: a keyval
*
* Obtains the upper- and lower-case versions of the keyval @symbol.
* Examples of keyvals are #GDK_KEY_a, #GDK_KEY_Enter, #GDK_KEY_F1, etc.
- *
- **/
+ */
void
gdk_keyval_convert_case (guint symbol,
- guint *lower,
- guint *upper)
+ guint *lower,
+ guint *upper)
{
- guint xlower = symbol;
- guint xupper = symbol;
+ GdkDisplayManager *manager = gdk_display_manager_get ();
- /* Check for directly encoded 24-bit UCS characters: */
- if ((symbol & 0xff000000) == 0x01000000)
- {
- if (lower)
- *lower = gdk_unicode_to_keyval (g_unichar_tolower (symbol & 0x00ffffff));
- if (upper)
- *upper = gdk_unicode_to_keyval (g_unichar_toupper (symbol & 0x00ffffff));
- return;
- }
-
- switch (symbol >> 8)
- {
- case 0: /* Latin 1 */
- if ((symbol >= GDK_KEY_A) && (symbol <= GDK_KEY_Z))
- xlower += (GDK_KEY_a - GDK_KEY_A);
- else if ((symbol >= GDK_KEY_a) && (symbol <= GDK_KEY_z))
- xupper -= (GDK_KEY_a - GDK_KEY_A);
- else if ((symbol >= GDK_KEY_Agrave) && (symbol <= GDK_KEY_Odiaeresis))
- xlower += (GDK_KEY_agrave - GDK_KEY_Agrave);
- else if ((symbol >= GDK_KEY_agrave) && (symbol <= GDK_KEY_odiaeresis))
- xupper -= (GDK_KEY_agrave - GDK_KEY_Agrave);
- else if ((symbol >= GDK_KEY_Ooblique) && (symbol <= GDK_KEY_Thorn))
- xlower += (GDK_KEY_oslash - GDK_KEY_Ooblique);
- else if ((symbol >= GDK_KEY_oslash) && (symbol <= GDK_KEY_thorn))
- xupper -= (GDK_KEY_oslash - GDK_KEY_Ooblique);
- break;
-
- case 1: /* Latin 2 */
- /* Assume the KeySym is a legal value (ignore discontinuities) */
- if (symbol == GDK_KEY_Aogonek)
- xlower = GDK_KEY_aogonek;
- else if (symbol >= GDK_KEY_Lstroke && symbol <= GDK_KEY_Sacute)
- xlower += (GDK_KEY_lstroke - GDK_KEY_Lstroke);
- else if (symbol >= GDK_KEY_Scaron && symbol <= GDK_KEY_Zacute)
- xlower += (GDK_KEY_scaron - GDK_KEY_Scaron);
- else if (symbol >= GDK_KEY_Zcaron && symbol <= GDK_KEY_Zabovedot)
- xlower += (GDK_KEY_zcaron - GDK_KEY_Zcaron);
- else if (symbol == GDK_KEY_aogonek)
- xupper = GDK_KEY_Aogonek;
- else if (symbol >= GDK_KEY_lstroke && symbol <= GDK_KEY_sacute)
- xupper -= (GDK_KEY_lstroke - GDK_KEY_Lstroke);
- else if (symbol >= GDK_KEY_scaron && symbol <= GDK_KEY_zacute)
- xupper -= (GDK_KEY_scaron - GDK_KEY_Scaron);
- else if (symbol >= GDK_KEY_zcaron && symbol <= GDK_KEY_zabovedot)
- xupper -= (GDK_KEY_zcaron - GDK_KEY_Zcaron);
- else if (symbol >= GDK_KEY_Racute && symbol <= GDK_KEY_Tcedilla)
- xlower += (GDK_KEY_racute - GDK_KEY_Racute);
- else if (symbol >= GDK_KEY_racute && symbol <= GDK_KEY_tcedilla)
- xupper -= (GDK_KEY_racute - GDK_KEY_Racute);
- break;
-
- case 2: /* Latin 3 */
- /* Assume the KeySym is a legal value (ignore discontinuities) */
- if (symbol >= GDK_KEY_Hstroke && symbol <= GDK_KEY_Hcircumflex)
- xlower += (GDK_KEY_hstroke - GDK_KEY_Hstroke);
- else if (symbol >= GDK_KEY_Gbreve && symbol <= GDK_KEY_Jcircumflex)
- xlower += (GDK_KEY_gbreve - GDK_KEY_Gbreve);
- else if (symbol >= GDK_KEY_hstroke && symbol <= GDK_KEY_hcircumflex)
- xupper -= (GDK_KEY_hstroke - GDK_KEY_Hstroke);
- else if (symbol >= GDK_KEY_gbreve && symbol <= GDK_KEY_jcircumflex)
- xupper -= (GDK_KEY_gbreve - GDK_KEY_Gbreve);
- else if (symbol >= GDK_KEY_Cabovedot && symbol <= GDK_KEY_Scircumflex)
- xlower += (GDK_KEY_cabovedot - GDK_KEY_Cabovedot);
- else if (symbol >= GDK_KEY_cabovedot && symbol <= GDK_KEY_scircumflex)
- xupper -= (GDK_KEY_cabovedot - GDK_KEY_Cabovedot);
- break;
-
- case 3: /* Latin 4 */
- /* Assume the KeySym is a legal value (ignore discontinuities) */
- if (symbol >= GDK_KEY_Rcedilla && symbol <= GDK_KEY_Tslash)
- xlower += (GDK_KEY_rcedilla - GDK_KEY_Rcedilla);
- else if (symbol >= GDK_KEY_rcedilla && symbol <= GDK_KEY_tslash)
- xupper -= (GDK_KEY_rcedilla - GDK_KEY_Rcedilla);
- else if (symbol == GDK_KEY_ENG)
- xlower = GDK_KEY_eng;
- else if (symbol == GDK_KEY_eng)
- xupper = GDK_KEY_ENG;
- else if (symbol >= GDK_KEY_Amacron && symbol <= GDK_KEY_Umacron)
- xlower += (GDK_KEY_amacron - GDK_KEY_Amacron);
- else if (symbol >= GDK_KEY_amacron && symbol <= GDK_KEY_umacron)
- xupper -= (GDK_KEY_amacron - GDK_KEY_Amacron);
- break;
-
- case 6: /* Cyrillic */
- /* Assume the KeySym is a legal value (ignore discontinuities) */
- if (symbol >= GDK_KEY_Serbian_DJE && symbol <= GDK_KEY_Serbian_DZE)
- xlower -= (GDK_KEY_Serbian_DJE - GDK_KEY_Serbian_dje);
- else if (symbol >= GDK_KEY_Serbian_dje && symbol <= GDK_KEY_Serbian_dze)
- xupper += (GDK_KEY_Serbian_DJE - GDK_KEY_Serbian_dje);
- else if (symbol >= GDK_KEY_Cyrillic_YU && symbol <= GDK_KEY_Cyrillic_HARDSIGN)
- xlower -= (GDK_KEY_Cyrillic_YU - GDK_KEY_Cyrillic_yu);
- else if (symbol >= GDK_KEY_Cyrillic_yu && symbol <= GDK_KEY_Cyrillic_hardsign)
- xupper += (GDK_KEY_Cyrillic_YU - GDK_KEY_Cyrillic_yu);
- break;
-
- case 7: /* Greek */
- /* Assume the KeySym is a legal value (ignore discontinuities) */
- if (symbol >= GDK_KEY_Greek_ALPHAaccent && symbol <= GDK_KEY_Greek_OMEGAaccent)
- xlower += (GDK_KEY_Greek_alphaaccent - GDK_KEY_Greek_ALPHAaccent);
- else if (symbol >= GDK_KEY_Greek_alphaaccent && symbol <= GDK_KEY_Greek_omegaaccent &&
- symbol != GDK_KEY_Greek_iotaaccentdieresis &&
- symbol != GDK_KEY_Greek_upsilonaccentdieresis)
- xupper -= (GDK_KEY_Greek_alphaaccent - GDK_KEY_Greek_ALPHAaccent);
- else if (symbol >= GDK_KEY_Greek_ALPHA && symbol <= GDK_KEY_Greek_OMEGA)
- xlower += (GDK_KEY_Greek_alpha - GDK_KEY_Greek_ALPHA);
- else if (symbol >= GDK_KEY_Greek_alpha && symbol <= GDK_KEY_Greek_omega &&
- symbol != GDK_KEY_Greek_finalsmallsigma)
- xupper -= (GDK_KEY_Greek_alpha - GDK_KEY_Greek_ALPHA);
- break;
- }
-
- if (lower)
- *lower = xlower;
- if (upper)
- *upper = xupper;
+ GDK_DISPLAY_MANAGER_GET_CLASS (manager)->keyval_convert_case (manager, symbol, lower, upper);
}
-#endif
/**
* gdk_keyval_to_upper:
gdk_keyval_to_upper (guint keyval)
{
guint result;
-
+
gdk_keyval_convert_case (keyval, NULL, &result);
return result;
gdk_keyval_to_lower (guint keyval)
{
guint result;
-
+
gdk_keyval_convert_case (keyval, &result, NULL);
return result;
if (keyval)
{
guint upper_val = 0;
-
+
gdk_keyval_convert_case (keyval, NULL, &upper_val);
return upper_val == keyval;
}
if (keyval)
{
guint lower_val = 0;
-
+
gdk_keyval_convert_case (keyval, &lower_val, NULL);
return lower_val == keyval;
}
return FALSE;
}
-/**
+/**
* gdk_keymap_get_default:
*
* Returns the #GdkKeymap attached to the default display.
/**
* gdk_keymap_get_direction:
- * @keymap: a #GdkKeymap or %NULL to use the default keymap
+ * @keymap: a #GdkKeymap
*
* Returns the direction of effective layout of the keymap.
*
PangoDirection
gdk_keymap_get_direction (GdkKeymap *keymap)
{
- return GDK_KEYMAP_GET_CLASS(keymap)->get_direction (keymap);
+ g_return_val_if_fail (GDK_IS_KEYMAP (keymap), PANGO_DIRECTION_LTR);
+
+ return GDK_KEYMAP_GET_CLASS (keymap)->get_direction (keymap);
}
/**
* gdk_keymap_have_bidi_layouts:
- * @keymap: a #GdkKeymap or %NULL to use the default keymap
+ * @keymap: a #GdkKeymap
*
* Determines if keyboard layouts for both right-to-left and left-to-right
* languages are in use.
gboolean
gdk_keymap_have_bidi_layouts (GdkKeymap *keymap)
{
- return GDK_KEYMAP_GET_CLASS(keymap)->have_bidi_layouts (keymap);
+ g_return_val_if_fail (GDK_IS_KEYMAP (keymap), FALSE);
+
+ return GDK_KEYMAP_GET_CLASS (keymap)->have_bidi_layouts (keymap);
}
/**
gboolean
gdk_keymap_get_caps_lock_state (GdkKeymap *keymap)
{
- return GDK_KEYMAP_GET_CLASS(keymap)->get_caps_lock_state (keymap);
+ g_return_val_if_fail (GDK_IS_KEYMAP (keymap), FALSE);
+
+ return GDK_KEYMAP_GET_CLASS (keymap)->get_caps_lock_state (keymap);
}
/**
gboolean
gdk_keymap_get_num_lock_state (GdkKeymap *keymap)
{
- return GDK_KEYMAP_GET_CLASS(keymap)->get_num_lock_state (keymap);
+ g_return_val_if_fail (GDK_IS_KEYMAP (keymap), FALSE);
+
+ return GDK_KEYMAP_GET_CLASS (keymap)->get_num_lock_state (keymap);
+}
+
+/**
+ * gdk_keymap_get_modifier_state:
+ * @keymap: a #GdkKeymap
+ *
+ * Returns the current modifier state.
+ *
+ * Returns: the current modifier state.
+ *
+ * Since: 3.4
+ */
+guint
+gdk_keymap_get_modifier_state (GdkKeymap *keymap)
+{
+ g_return_val_if_fail (GDK_IS_KEYMAP (keymap), FALSE);
+
+ if (GDK_KEYMAP_GET_CLASS (keymap)->get_modifier_state)
+ return GDK_KEYMAP_GET_CLASS (keymap)->get_modifier_state (keymap);
+
+ return 0;
}
/**
* gdk_keymap_get_entries_for_keyval:
- * @keymap: (allow-none): a #GdkKeymap, or %NULL to use the default keymap
+ * @keymap: a #GdkKeymap
* @keyval: a keyval, such as %GDK_a, %GDK_Up, %GDK_Return, etc.
- * @keys: (out): return location for an array of #GdkKeymapKey
- * @n_keys: (out): return location for number of elements in returned array
+ * @keys: (out) (array length=n_keys) (transfer full): return location
+ * for an array of #GdkKeymapKey
+ * @n_keys: return location for number of elements in returned array
*
* Obtains a list of keycode/group/level combinations that will
* generate @keyval. Groups and levels are two kinds of keyboard mode;
GdkKeymapKey **keys,
gint *n_keys)
{
- return GDK_KEYMAP_GET_CLASS(keymap)->get_entries_for_keyval (keymap, keyval, keys, n_keys);
+ g_return_val_if_fail (GDK_IS_KEYMAP (keymap), FALSE);
+ g_return_val_if_fail (keys != NULL, FALSE);
+ g_return_val_if_fail (n_keys != NULL, FALSE);
+ g_return_val_if_fail (keyval != 0, FALSE);
+
+ return GDK_KEYMAP_GET_CLASS (keymap)->get_entries_for_keyval (keymap, keyval,
+ keys, n_keys);
}
/**
* gdk_keymap_get_entries_for_keycode:
- * @keymap: (allow-none): a #GdkKeymap or %NULL to use the default keymap
+ * @keymap: a #GdkKeymap
* @hardware_keycode: a keycode
- * @keys: (out): return location for array of #GdkKeymapKey, or %NULL
- * @keyvals: (out): return location for array of keyvals, or %NULL
+ * @keys: (out) (array length=n_entries) (transfer full): return
+ * location for array of #GdkKeymapKey, or %NULL
+ * @keyvals: (out) (array length=n_entries) (transfer full): return
+ * location for array of keyvals, or %NULL
* @n_entries: length of @keys and @keyvals
*
* Returns the keyvals bound to @hardware_keycode.
guint **keyvals,
gint *n_entries)
{
- return GDK_KEYMAP_GET_CLASS(keymap)->get_entries_for_keycode (keymap, hardware_keycode, keys, keyvals, n_entries);
+ g_return_val_if_fail (GDK_IS_KEYMAP (keymap), FALSE);
+ g_return_val_if_fail (n_entries != NULL, FALSE);
+
+ return GDK_KEYMAP_GET_CLASS (keymap)->get_entries_for_keycode (keymap, hardware_keycode,
+ keys, keyvals, n_entries);
}
/**
* gdk_keymap_lookup_key:
- * @keymap: a #GdkKeymap or %NULL to use the default keymap
+ * @keymap: a #GdkKeymap
* @key: a #GdkKeymapKey with keycode, group, and level initialized
*
* Looks up the keyval mapped to a keycode/group/level triplet.
gdk_keymap_lookup_key (GdkKeymap *keymap,
const GdkKeymapKey *key)
{
- return GDK_KEYMAP_GET_CLASS(keymap)->lookup_key (keymap, key);
+ g_return_val_if_fail (GDK_IS_KEYMAP (keymap), 0);
+ g_return_val_if_fail (key != NULL, 0);
+
+ return GDK_KEYMAP_GET_CLASS (keymap)->lookup_key (keymap, key);
}
/**
* gdk_keymap_translate_keyboard_state:
- * @keymap: (allow-none): a #GdkKeymap, or %NULL to use the default
+ * @keymap: a #GdkKeymap
* @hardware_keycode: a keycode
* @state: a modifier state
* @group: active keyboard group
* @keyval: (out) (allow-none): return location for keyval, or %NULL
- * @effective_group: (out) (allow-none): return location for effective group, or %NULL
- * @level: (out) (allow-none): return location for level, or %NULL
- * @consumed_modifiers: (out) (allow-none): return location for modifiers that were used to
- * determine the group or level, or %NULL
+ * @effective_group: (out) (allow-none): return location for effective
+ * group, or %NULL
+ * @level: (out) (allow-none): return location for level, or %NULL
+ * @consumed_modifiers: (out) (allow-none): return location for modifiers
+ * that were used to determine the group or level, or %NULL
*
* Translates the contents of a #GdkEventKey into a keyval, effective
* group, and level. Modifiers that affected the translation and
* are thus unavailable for application use are returned in
- * @consumed_modifiers. See <xref linkend="key-group-explanation"/> for an explanation of
- * groups and levels. The @effective_group is the group that was
+ * @consumed_modifiers.
+ * See <xref linkend="key-group-explanation"/> for an explanation of
+ * groups and levels. The @effective_group is the group that was
* actually used for the translation; some keys such as Enter are not
* affected by the active keyboard group. The @level is derived from
* @state. For convenience, #GdkEventKey already contains the translated
gint *level,
GdkModifierType *consumed_modifiers)
{
- return GDK_KEYMAP_GET_CLASS(keymap)->translate_keyboard_state (keymap,
+ g_return_val_if_fail (GDK_IS_KEYMAP (keymap), FALSE);
+
+ return GDK_KEYMAP_GET_CLASS (keymap)->translate_keyboard_state (keymap,
hardware_keycode,
state,
group,
/**
* gdk_keymap_add_virtual_modifiers:
* @keymap: a #GdkKeymap
- * @state: pointer to the modifier mask to change
+ * @state: (inout): pointer to the modifier mask to change
*
- * Adds virtual modifiers (i.e. Super, Hyper and Meta) which correspond
- * to the real modifiers (i.e Mod2, Mod3, ...) in @modifiers.
- * are set in @state to their non-virtual counterparts (i.e. Mod2,
- * Mod3,...) and set the corresponding bits in @state.
+ * Maps the non-virtual modifiers (i.e Mod2, Mod3, ...) which are set
+ * in @state to the virtual modifiers (i.e. Super, Hyper and Meta) and
+ * set the corresponding bits in @state.
*
* GDK already does this before delivering key events, but for
* compatibility reasons, it only sets the first virtual modifier
gdk_keymap_add_virtual_modifiers (GdkKeymap *keymap,
GdkModifierType *state)
{
- GDK_KEYMAP_GET_CLASS(keymap)->add_virtual_modifiers (keymap, state);
+ g_return_if_fail (GDK_IS_KEYMAP (keymap));
+
+ GDK_KEYMAP_GET_CLASS (keymap)->add_virtual_modifiers (keymap, state);
}
/**
* gdk_keymap_map_virtual_modifiers:
* @keymap: a #GdkKeymap
- * @state: pointer to the modifier state to map
+ * @state: (inout): pointer to the modifier state to map
*
* Maps the virtual modifiers (i.e. Super, Hyper and Meta) which
* are set in @state to their non-virtual counterparts (i.e. Mod2,
gdk_keymap_map_virtual_modifiers (GdkKeymap *keymap,
GdkModifierType *state)
{
+ g_return_val_if_fail (GDK_IS_KEYMAP (keymap), FALSE);
+
return GDK_KEYMAP_GET_CLASS(keymap)->map_virtual_modifiers (keymap, state);
}
+
+static GdkModifierType
+gdk_keymap_real_get_modifier_mask (GdkKeymap *keymap,
+ GdkModifierIntent intent)
+{
+ switch (intent)
+ {
+ case GDK_MODIFIER_INTENT_PRIMARY_ACCELERATOR:
+ return GDK_CONTROL_MASK;
+
+ case GDK_MODIFIER_INTENT_CONTEXT_MENU:
+ return 0;
+
+ case GDK_MODIFIER_INTENT_EXTEND_SELECTION:
+ return GDK_SHIFT_MASK;
+
+ case GDK_MODIFIER_INTENT_MODIFY_SELECTION:
+ return GDK_CONTROL_MASK;
+
+ case GDK_MODIFIER_INTENT_NO_TEXT_INPUT:
+ return GDK_MOD1_MASK | GDK_CONTROL_MASK;
+
+ case GDK_MODIFIER_INTENT_SHIFT_GROUP:
+ return 0;
+
+ default:
+ g_return_val_if_reached (0);
+ }
+}
+
+/**
+ * gdk_keymap_get_modifier_mask:
+ * @keymap: a #GdkKeymap
+ * @intent: the use case for the modifier mask
+ *
+ * Returns the modifier mask the @keymap's windowing system backend
+ * uses for a particular purpose.
+ *
+ * Note that this function always returns real hardware modifiers, not
+ * virtual ones (e.g. it will return #GDK_MOD1_MASK rather than
+ * #GDK_META_MASK if the backend maps MOD1 to META), so there are use
+ * cases where the return value of this function has to be transformed
+ * by gdk_keymap_add_virtual_modifiers() in order to contain the
+ * expected result.
+ *
+ * Returns: the modifier mask used for @intent.
+ *
+ * Since: 3.4
+ **/
+GdkModifierType
+gdk_keymap_get_modifier_mask (GdkKeymap *keymap,
+ GdkModifierIntent intent)
+{
+ g_return_val_if_fail (GDK_IS_KEYMAP (keymap), 0);
+
+ return GDK_KEYMAP_GET_CLASS (keymap)->get_modifier_mask (keymap, intent);
+}
+
+
+/**
+ * gdk_keyval_name:
+ * @keyval: a key value
+ *
+ * Converts a key value into a symbolic name.
+ *
+ * The names are the same as those in the
+ * <filename><gdk/gdkkeysyms.h></filename> header file
+ * but without the leading "GDK_KEY_".
+ *
+ * Return value: (transfer none): a string containing the name of the key,
+ * or %NULL if @keyval is not a valid key. The string should not be
+ * modified.
+ */
+gchar *
+gdk_keyval_name (guint keyval)
+{
+ GdkDisplayManager *manager = gdk_display_manager_get ();
+
+ return GDK_DISPLAY_MANAGER_GET_CLASS (manager)->get_keyval_name (manager,
+ keyval);
+}
+
+/**
+ * gdk_keyval_from_name:
+ * @keyval_name: a key name
+ *
+ * Converts a key name to a key value.
+ *
+ * The names are the same as those in the
+ * <filename><gdk/gdkkeysyms.h></filename> header file
+ * but without the leading "GDK_KEY_".
+ *
+ * Returns: the corresponding key value, or %GDK_KEY_VoidSymbol
+ * if the key name is not a valid key
+ */
+guint
+gdk_keyval_from_name (const gchar *keyval_name)
+{
+ GdkDisplayManager *manager = gdk_display_manager_get ();
+
+ return GDK_DISPLAY_MANAGER_GET_CLASS (manager)->lookup_keyval (manager,
+ keyval_name);
+}
+
+void
+_gdk_display_manager_real_keyval_convert_case (GdkDisplayManager *manager,
+ guint symbol,
+ guint *lower,
+ guint *upper)
+{
+ guint xlower = symbol;
+ guint xupper = symbol;
+
+ /* Check for directly encoded 24-bit UCS characters: */
+ if ((symbol & 0xff000000) == 0x01000000)
+ {
+ if (lower)
+ *lower = gdk_unicode_to_keyval (g_unichar_tolower (symbol & 0x00ffffff));
+ if (upper)
+ *upper = gdk_unicode_to_keyval (g_unichar_toupper (symbol & 0x00ffffff));
+ return;
+ }
+
+ switch (symbol >> 8)
+ {
+ case 0: /* Latin 1 */
+ if ((symbol >= GDK_KEY_A) && (symbol <= GDK_KEY_Z))
+ xlower += (GDK_KEY_a - GDK_KEY_A);
+ else if ((symbol >= GDK_KEY_a) && (symbol <= GDK_KEY_z))
+ xupper -= (GDK_KEY_a - GDK_KEY_A);
+ else if ((symbol >= GDK_KEY_Agrave) && (symbol <= GDK_KEY_Odiaeresis))
+ xlower += (GDK_KEY_agrave - GDK_KEY_Agrave);
+ else if ((symbol >= GDK_KEY_agrave) && (symbol <= GDK_KEY_odiaeresis))
+ xupper -= (GDK_KEY_agrave - GDK_KEY_Agrave);
+ else if ((symbol >= GDK_KEY_Ooblique) && (symbol <= GDK_KEY_Thorn))
+ xlower += (GDK_KEY_oslash - GDK_KEY_Ooblique);
+ else if ((symbol >= GDK_KEY_oslash) && (symbol <= GDK_KEY_thorn))
+ xupper -= (GDK_KEY_oslash - GDK_KEY_Ooblique);
+ break;
+
+ case 1: /* Latin 2 */
+ /* Assume the KeySym is a legal value (ignore discontinuities) */
+ if (symbol == GDK_KEY_Aogonek)
+ xlower = GDK_KEY_aogonek;
+ else if (symbol >= GDK_KEY_Lstroke && symbol <= GDK_KEY_Sacute)
+ xlower += (GDK_KEY_lstroke - GDK_KEY_Lstroke);
+ else if (symbol >= GDK_KEY_Scaron && symbol <= GDK_KEY_Zacute)
+ xlower += (GDK_KEY_scaron - GDK_KEY_Scaron);
+ else if (symbol >= GDK_KEY_Zcaron && symbol <= GDK_KEY_Zabovedot)
+ xlower += (GDK_KEY_zcaron - GDK_KEY_Zcaron);
+ else if (symbol == GDK_KEY_aogonek)
+ xupper = GDK_KEY_Aogonek;
+ else if (symbol >= GDK_KEY_lstroke && symbol <= GDK_KEY_sacute)
+ xupper -= (GDK_KEY_lstroke - GDK_KEY_Lstroke);
+ else if (symbol >= GDK_KEY_scaron && symbol <= GDK_KEY_zacute)
+ xupper -= (GDK_KEY_scaron - GDK_KEY_Scaron);
+ else if (symbol >= GDK_KEY_zcaron && symbol <= GDK_KEY_zabovedot)
+ xupper -= (GDK_KEY_zcaron - GDK_KEY_Zcaron);
+ else if (symbol >= GDK_KEY_Racute && symbol <= GDK_KEY_Tcedilla)
+ xlower += (GDK_KEY_racute - GDK_KEY_Racute);
+ else if (symbol >= GDK_KEY_racute && symbol <= GDK_KEY_tcedilla)
+ xupper -= (GDK_KEY_racute - GDK_KEY_Racute);
+ break;
+
+ case 2: /* Latin 3 */
+ /* Assume the KeySym is a legal value (ignore discontinuities) */
+ if (symbol >= GDK_KEY_Hstroke && symbol <= GDK_KEY_Hcircumflex)
+ xlower += (GDK_KEY_hstroke - GDK_KEY_Hstroke);
+ else if (symbol >= GDK_KEY_Gbreve && symbol <= GDK_KEY_Jcircumflex)
+ xlower += (GDK_KEY_gbreve - GDK_KEY_Gbreve);
+ else if (symbol >= GDK_KEY_hstroke && symbol <= GDK_KEY_hcircumflex)
+ xupper -= (GDK_KEY_hstroke - GDK_KEY_Hstroke);
+ else if (symbol >= GDK_KEY_gbreve && symbol <= GDK_KEY_jcircumflex)
+ xupper -= (GDK_KEY_gbreve - GDK_KEY_Gbreve);
+ else if (symbol >= GDK_KEY_Cabovedot && symbol <= GDK_KEY_Scircumflex)
+ xlower += (GDK_KEY_cabovedot - GDK_KEY_Cabovedot);
+ else if (symbol >= GDK_KEY_cabovedot && symbol <= GDK_KEY_scircumflex)
+ xupper -= (GDK_KEY_cabovedot - GDK_KEY_Cabovedot);
+ break;
+
+ case 3: /* Latin 4 */
+ /* Assume the KeySym is a legal value (ignore discontinuities) */
+ if (symbol >= GDK_KEY_Rcedilla && symbol <= GDK_KEY_Tslash)
+ xlower += (GDK_KEY_rcedilla - GDK_KEY_Rcedilla);
+ else if (symbol >= GDK_KEY_rcedilla && symbol <= GDK_KEY_tslash)
+ xupper -= (GDK_KEY_rcedilla - GDK_KEY_Rcedilla);
+ else if (symbol == GDK_KEY_ENG)
+ xlower = GDK_KEY_eng;
+ else if (symbol == GDK_KEY_eng)
+ xupper = GDK_KEY_ENG;
+ else if (symbol >= GDK_KEY_Amacron && symbol <= GDK_KEY_Umacron)
+ xlower += (GDK_KEY_amacron - GDK_KEY_Amacron);
+ else if (symbol >= GDK_KEY_amacron && symbol <= GDK_KEY_umacron)
+ xupper -= (GDK_KEY_amacron - GDK_KEY_Amacron);
+ break;
+
+ case 6: /* Cyrillic */
+ /* Assume the KeySym is a legal value (ignore discontinuities) */
+ if (symbol >= GDK_KEY_Serbian_DJE && symbol <= GDK_KEY_Serbian_DZE)
+ xlower -= (GDK_KEY_Serbian_DJE - GDK_KEY_Serbian_dje);
+ else if (symbol >= GDK_KEY_Serbian_dje && symbol <= GDK_KEY_Serbian_dze)
+ xupper += (GDK_KEY_Serbian_DJE - GDK_KEY_Serbian_dje);
+ else if (symbol >= GDK_KEY_Cyrillic_YU && symbol <= GDK_KEY_Cyrillic_HARDSIGN)
+ xlower -= (GDK_KEY_Cyrillic_YU - GDK_KEY_Cyrillic_yu);
+ else if (symbol >= GDK_KEY_Cyrillic_yu && symbol <= GDK_KEY_Cyrillic_hardsign)
+ xupper += (GDK_KEY_Cyrillic_YU - GDK_KEY_Cyrillic_yu);
+ break;
+
+ case 7: /* Greek */
+ /* Assume the KeySym is a legal value (ignore discontinuities) */
+ if (symbol >= GDK_KEY_Greek_ALPHAaccent && symbol <= GDK_KEY_Greek_OMEGAaccent)
+ xlower += (GDK_KEY_Greek_alphaaccent - GDK_KEY_Greek_ALPHAaccent);
+ else if (symbol >= GDK_KEY_Greek_alphaaccent && symbol <= GDK_KEY_Greek_omegaaccent &&
+ symbol != GDK_KEY_Greek_iotaaccentdieresis &&
+ symbol != GDK_KEY_Greek_upsilonaccentdieresis)
+ xupper -= (GDK_KEY_Greek_alphaaccent - GDK_KEY_Greek_ALPHAaccent);
+ else if (symbol >= GDK_KEY_Greek_ALPHA && symbol <= GDK_KEY_Greek_OMEGA)
+ xlower += (GDK_KEY_Greek_alpha - GDK_KEY_Greek_ALPHA);
+ else if (symbol >= GDK_KEY_Greek_alpha && symbol <= GDK_KEY_Greek_omega &&
+ symbol != GDK_KEY_Greek_finalsmallsigma)
+ xupper -= (GDK_KEY_Greek_alpha - GDK_KEY_Greek_ALPHA);
+ break;
+ }
+
+ if (lower)
+ *lower = xlower;
+ if (upper)
+ *upper = xupper;
+}