|
Packit Service |
1d8f1c |
/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
|
|
Packit Service |
1d8f1c |
/* vim:set et sts=4: */
|
|
Packit Service |
1d8f1c |
/* IBus - The Input Bus
|
|
Packit Service |
1d8f1c |
* Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
|
|
Packit Service |
1d8f1c |
* Copyright (C) 2018 Takao Fujiwara <takao.fujiwara1@gmail.com>
|
|
Packit Service |
1d8f1c |
* Copyright (C) 2008-2018 Red Hat, Inc.
|
|
Packit Service |
1d8f1c |
*
|
|
Packit Service |
1d8f1c |
* This library is free software; you can redistribute it and/or
|
|
Packit Service |
1d8f1c |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit Service |
1d8f1c |
* License as published by the Free Software Foundation; either
|
|
Packit Service |
1d8f1c |
* version 2.1 of the License, or (at your option) any later version.
|
|
Packit Service |
1d8f1c |
*
|
|
Packit Service |
1d8f1c |
* This library is distributed in the hope that it will be useful,
|
|
Packit Service |
1d8f1c |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
1d8f1c |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit Service |
1d8f1c |
* Lesser General Public License for more details.
|
|
Packit Service |
1d8f1c |
*
|
|
Packit Service |
1d8f1c |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit Service |
1d8f1c |
* License along with this library; if not, write to the Free Software
|
|
Packit Service |
1d8f1c |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
|
Packit Service |
1d8f1c |
* USA
|
|
Packit Service |
1d8f1c |
*/
|
|
Packit Service |
1d8f1c |
#include <errno.h>
|
|
Packit Service |
1d8f1c |
#include <string.h>
|
|
Packit Service |
1d8f1c |
#include <stdio.h>
|
|
Packit Service |
1d8f1c |
#include <stdlib.h>
|
|
Packit Service |
1d8f1c |
#include <glib/gstdio.h>
|
|
Packit Service |
1d8f1c |
#include "ibuskeys.h"
|
|
Packit Service |
1d8f1c |
#include "ibuskeysyms.h"
|
|
Packit Service |
1d8f1c |
#include "ibuskeymap.h"
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
typedef guint KEYMAP[256][7];
|
|
Packit Service |
1d8f1c |
/* functions prototype */
|
|
Packit Service |
1d8f1c |
static void ibus_keymap_destroy (IBusKeymap *keymap);
|
|
Packit Service |
1d8f1c |
static gboolean ibus_keymap_load (const gchar *name,
|
|
Packit Service |
1d8f1c |
KEYMAP keymap);
|
|
Packit Service |
1d8f1c |
static GHashTable *keymaps = NULL;
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
G_DEFINE_TYPE (IBusKeymap, ibus_keymap, IBUS_TYPE_OBJECT)
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
static void
|
|
Packit Service |
1d8f1c |
ibus_keymap_class_init (IBusKeymapClass *class)
|
|
Packit Service |
1d8f1c |
{
|
|
Packit Service |
1d8f1c |
IBusObjectClass *object_class = IBUS_OBJECT_CLASS (class);
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
object_class->destroy = (IBusObjectDestroyFunc) ibus_keymap_destroy;
|
|
Packit Service |
1d8f1c |
}
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
static void
|
|
Packit Service |
1d8f1c |
ibus_keymap_init (IBusKeymap *keymap)
|
|
Packit Service |
1d8f1c |
{
|
|
Packit Service |
1d8f1c |
gint i;
|
|
Packit Service |
1d8f1c |
keymap->name = NULL;
|
|
Packit Service |
1d8f1c |
for (i = 0; i < sizeof (keymap->keymap) / sizeof (guint); i++) {
|
|
Packit Service |
1d8f1c |
((guint *)keymap->keymap)[i] = IBUS_KEY_VoidSymbol;
|
|
Packit Service |
1d8f1c |
}
|
|
Packit Service |
1d8f1c |
}
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
static void
|
|
Packit Service |
1d8f1c |
ibus_keymap_destroy (IBusKeymap *keymap)
|
|
Packit Service |
1d8f1c |
{
|
|
Packit Service |
1d8f1c |
if (keymap->name != NULL) {
|
|
Packit Service |
1d8f1c |
g_free (keymap->name);
|
|
Packit Service |
1d8f1c |
keymap->name = NULL;
|
|
Packit Service |
1d8f1c |
}
|
|
Packit Service |
1d8f1c |
IBUS_OBJECT_CLASS (ibus_keymap_parent_class)->destroy ((IBusObject *)keymap);
|
|
Packit Service |
1d8f1c |
}
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
#define SKIP_SPACE(p) \
|
|
Packit Service |
1d8f1c |
while (*p == ' ') p++;
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
static gboolean
|
|
Packit Service |
1d8f1c |
ibus_keymap_parse_line (gchar *str,
|
|
Packit Service |
1d8f1c |
KEYMAP keymap)
|
|
Packit Service |
1d8f1c |
{
|
|
Packit Service |
1d8f1c |
gchar *p1, *p2, ch;
|
|
Packit Service |
1d8f1c |
gint i;
|
|
Packit Service |
1d8f1c |
guint keycode;
|
|
Packit Service |
1d8f1c |
guint keysym;
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
const struct {
|
|
Packit Service |
1d8f1c |
const gchar *prefix;
|
|
Packit Service |
1d8f1c |
const gint len;
|
|
Packit Service |
1d8f1c |
} prefix [] = {
|
|
Packit Service |
1d8f1c |
{ "keycode ", sizeof ("keycode ") - 1 },
|
|
Packit Service |
1d8f1c |
{ "shift keycode ", sizeof ("shift keycode ") - 1 },
|
|
Packit Service |
1d8f1c |
{ "capslock keycode ", sizeof ("capslock keycode ") - 1 },
|
|
Packit Service |
1d8f1c |
{ "shift capslock keycode ", sizeof ("shift capslock keycode ") - 1 },
|
|
Packit Service |
1d8f1c |
{ "altgr keycode ", sizeof ("altgr keycode ") - 1},
|
|
Packit Service |
1d8f1c |
{ "shift altgr keycode ", sizeof ("shift altgr keycode ") - 1},
|
|
Packit Service |
1d8f1c |
{ "numlock keycode ", sizeof ("numlock keycode ") - 1},
|
|
Packit Service |
1d8f1c |
};
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
p1 = str;
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
SKIP_SPACE(p1);
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
if (*p1 == '#')
|
|
Packit Service |
1d8f1c |
return TRUE;
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
if (strncmp (p1, "include ", sizeof ("include ") - 1) == 0) {
|
|
Packit Service |
1d8f1c |
p1 += sizeof ("include ") - 1;
|
|
Packit Service |
1d8f1c |
for (p2 = p1; *p2 != '\n'; p2++);
|
|
Packit Service |
1d8f1c |
*p2 = '\0';
|
|
Packit Service |
1d8f1c |
return ibus_keymap_load (p1, keymap);
|
|
Packit Service |
1d8f1c |
}
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
for (i = 0; i < sizeof (prefix) / sizeof (prefix[0]); i++) {
|
|
Packit Service |
1d8f1c |
if (strncmp (p1, prefix[i].prefix, prefix[i].len) == 0) {
|
|
Packit Service |
1d8f1c |
p1 += prefix[i].len;
|
|
Packit Service |
1d8f1c |
break;
|
|
Packit Service |
1d8f1c |
}
|
|
Packit Service |
1d8f1c |
}
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
if (i >= sizeof (prefix) / sizeof (prefix[0]))
|
|
Packit Service |
1d8f1c |
return FALSE;
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
keycode = (guint) strtoul (p1, &p2, 10);
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
if (keycode == 0 && p1 == p2)
|
|
Packit Service |
1d8f1c |
return FALSE;
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
if ((int) keycode < 0 || keycode > 255)
|
|
Packit Service |
1d8f1c |
return FALSE;
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
p1 = p2;
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
if (*p1++ != ' ')
|
|
Packit Service |
1d8f1c |
return FALSE;
|
|
Packit Service |
1d8f1c |
if (*p1++ != '=')
|
|
Packit Service |
1d8f1c |
return FALSE;
|
|
Packit Service |
1d8f1c |
if (*p1++ != ' ')
|
|
Packit Service |
1d8f1c |
return FALSE;
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
for (p2 = p1; *p2 != '\n' && *p2 != ' '; p2++);
|
|
Packit Service |
1d8f1c |
*p2 = '\0'; p2++;
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
keysym = ibus_keyval_from_name (p1);
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
if (keysym == IBUS_KEY_VoidSymbol)
|
|
Packit Service |
1d8f1c |
return FALSE;
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
/* Do not assign *p1 to g_ascii_isalpha() directly for the syntax check */
|
|
Packit Service |
1d8f1c |
if (i == 0 &&
|
|
Packit Service |
1d8f1c |
strncmp (p2, "addupper", sizeof ("addupper") - 1) == 0 &&
|
|
rpm-build |
0a7332 |
(ch = *p1) && (ch >= 0) && g_ascii_isalpha (ch)) {
|
|
Packit Service |
1d8f1c |
gchar buf[] = "a";
|
|
Packit Service |
1d8f1c |
buf[0] = g_ascii_toupper(ch);
|
|
Packit Service |
1d8f1c |
keymap[keycode][0] = keymap[keycode][3] = keysym;
|
|
Packit Service |
1d8f1c |
keymap[keycode][1] = keymap[keycode][2] = ibus_keyval_from_name (buf);
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
}
|
|
Packit Service |
1d8f1c |
else {
|
|
Packit Service |
1d8f1c |
keymap[keycode][i] = keysym;
|
|
Packit Service |
1d8f1c |
}
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
return TRUE;
|
|
Packit Service |
1d8f1c |
}
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
static gboolean
|
|
Packit Service |
1d8f1c |
ibus_keymap_load (const gchar *name,
|
|
Packit Service |
1d8f1c |
KEYMAP keymap)
|
|
Packit Service |
1d8f1c |
{
|
|
Packit Service |
1d8f1c |
const gchar *envstr;
|
|
Packit Service |
1d8f1c |
gchar *fname;
|
|
Packit Service |
1d8f1c |
FILE *pf;
|
|
Packit Service |
1d8f1c |
gchar buf[256];
|
|
Packit Service |
1d8f1c |
gint lineno;
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
if ((envstr = g_getenv ("IBUS_KEYMAP_PATH")) != NULL)
|
|
Packit Service |
1d8f1c |
fname = g_build_filename (envstr, name, NULL);
|
|
Packit Service |
1d8f1c |
else
|
|
Packit Service |
1d8f1c |
fname = g_build_filename (IBUS_DATA_DIR, "keymaps", name, NULL);
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
if (fname == NULL) {
|
|
Packit Service |
1d8f1c |
return FALSE;
|
|
Packit Service |
1d8f1c |
}
|
|
Packit Service |
1d8f1c |
pf = g_fopen (fname, "r");
|
|
Packit Service |
1d8f1c |
g_free (fname);
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
if (pf == NULL) {
|
|
Packit Service |
1d8f1c |
return FALSE;
|
|
Packit Service |
1d8f1c |
}
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
lineno = 0;
|
|
Packit Service |
1d8f1c |
while (fgets (buf, sizeof (buf), pf) != NULL) {
|
|
Packit Service |
1d8f1c |
lineno ++;
|
|
Packit Service |
1d8f1c |
if (!ibus_keymap_parse_line (buf, keymap)) {
|
|
Packit Service |
1d8f1c |
g_warning ("parse %s failed on %d line", name, lineno);
|
|
Packit Service |
1d8f1c |
lineno = -1;
|
|
Packit Service |
1d8f1c |
break;
|
|
Packit Service |
1d8f1c |
}
|
|
Packit Service |
1d8f1c |
}
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
fclose (pf);
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
if (lineno == -1) {
|
|
Packit Service |
1d8f1c |
return FALSE;
|
|
Packit Service |
1d8f1c |
}
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
return TRUE;
|
|
Packit Service |
1d8f1c |
}
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
void
|
|
Packit Service |
1d8f1c |
ibus_keymap_fill (KEYMAP keymap)
|
|
Packit Service |
1d8f1c |
{
|
|
Packit Service |
1d8f1c |
gint i;
|
|
Packit Service |
1d8f1c |
for (i = 0; i < 256; i++) {
|
|
Packit Service |
1d8f1c |
/* fill shift */
|
|
Packit Service |
1d8f1c |
if (keymap[i][1] == IBUS_KEY_VoidSymbol)
|
|
Packit Service |
1d8f1c |
keymap[i][1] = keymap[i][0];
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
/* fill capslock */
|
|
Packit Service |
1d8f1c |
if (keymap[i][2] == IBUS_KEY_VoidSymbol)
|
|
Packit Service |
1d8f1c |
keymap[i][2] = keymap[i][0];
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
/* fill shift capslock */
|
|
Packit Service |
1d8f1c |
if (keymap[i][3] == IBUS_KEY_VoidSymbol)
|
|
Packit Service |
1d8f1c |
keymap[i][3] = keymap[i][1];
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
/* fill altgr */
|
|
Packit Service |
1d8f1c |
if (keymap[i][4] == IBUS_KEY_VoidSymbol)
|
|
Packit Service |
1d8f1c |
keymap[i][4] = keymap[i][0];
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
/* fill shift altgr */
|
|
Packit Service |
1d8f1c |
if (keymap[i][5] == IBUS_KEY_VoidSymbol)
|
|
Packit Service |
1d8f1c |
keymap[i][5] = keymap[i][1];
|
|
Packit Service |
1d8f1c |
}
|
|
Packit Service |
1d8f1c |
}
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
static void
|
|
Packit Service |
1d8f1c |
_keymap_destroy_cb (IBusKeymap *keymap,
|
|
Packit Service |
1d8f1c |
gpointer user_data)
|
|
Packit Service |
1d8f1c |
{
|
|
Packit Service |
1d8f1c |
g_hash_table_remove (keymaps, keymap->name);
|
|
Packit Service |
1d8f1c |
g_object_unref (keymap);
|
|
Packit Service |
1d8f1c |
}
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
IBusKeymap *
|
|
Packit Service |
1d8f1c |
ibus_keymap_new (const gchar *name)
|
|
Packit Service |
1d8f1c |
{
|
|
Packit Service |
1d8f1c |
return ibus_keymap_get (name);
|
|
Packit Service |
1d8f1c |
}
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
IBusKeymap *
|
|
Packit Service |
1d8f1c |
ibus_keymap_get (const gchar *name)
|
|
Packit Service |
1d8f1c |
{
|
|
Packit Service |
1d8f1c |
g_assert (name != NULL);
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
IBusKeymap *keymap;
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
if (keymaps == NULL) {
|
|
Packit Service |
1d8f1c |
keymaps = g_hash_table_new_full (g_str_hash,
|
|
Packit Service |
1d8f1c |
g_str_equal,
|
|
Packit Service |
1d8f1c |
(GDestroyNotify) g_free,
|
|
Packit Service |
1d8f1c |
(GDestroyNotify) g_object_unref);
|
|
Packit Service |
1d8f1c |
}
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
keymap = (IBusKeymap *) g_hash_table_lookup (keymaps, name);
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
if (keymap == NULL) {
|
|
Packit Service |
1d8f1c |
keymap = g_object_new (IBUS_TYPE_KEYMAP, NULL);
|
|
Packit Service |
1d8f1c |
g_object_ref_sink (keymap);
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
if (ibus_keymap_load (name, keymap->keymap)) {
|
|
Packit Service |
1d8f1c |
ibus_keymap_fill (keymap->keymap);
|
|
Packit Service |
1d8f1c |
keymap->name = g_strdup (name);
|
|
Packit Service |
1d8f1c |
g_hash_table_insert (keymaps, g_strdup (keymap->name), keymap);
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
g_signal_connect (keymap, "destroy", G_CALLBACK (_keymap_destroy_cb), NULL);
|
|
Packit Service |
1d8f1c |
}
|
|
Packit Service |
1d8f1c |
else {
|
|
Packit Service |
1d8f1c |
g_object_unref (keymap);
|
|
Packit Service |
1d8f1c |
keymap = NULL;
|
|
Packit Service |
1d8f1c |
}
|
|
Packit Service |
1d8f1c |
}
|
|
Packit Service |
1d8f1c |
if (keymap != NULL)
|
|
Packit Service |
1d8f1c |
g_object_ref_sink (keymap);
|
|
Packit Service |
1d8f1c |
return keymap;
|
|
Packit Service |
1d8f1c |
}
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
guint32
|
|
Packit Service |
1d8f1c |
ibus_keymap_lookup_keysym (IBusKeymap *keymap,
|
|
Packit Service |
1d8f1c |
guint16 keycode,
|
|
Packit Service |
1d8f1c |
guint32 state)
|
|
Packit Service |
1d8f1c |
{
|
|
Packit Service |
1d8f1c |
g_assert (IBUS_IS_KEYMAP (keymap));
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
if (keycode < 256) {
|
|
Packit Service |
1d8f1c |
/* numlock */
|
|
Packit Service |
1d8f1c |
if ((state & IBUS_MOD2_MASK) &&
|
|
Packit Service |
1d8f1c |
(keymap->keymap[keycode][6] != IBUS_KEY_VoidSymbol)) {
|
|
Packit Service |
1d8f1c |
return keymap->keymap[keycode][6];
|
|
Packit Service |
1d8f1c |
}
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
state &= IBUS_SHIFT_MASK | IBUS_LOCK_MASK | IBUS_MOD5_MASK;
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
switch (state) {
|
|
Packit Service |
1d8f1c |
case 0:
|
|
Packit Service |
1d8f1c |
return keymap->keymap[keycode][0];
|
|
Packit Service |
1d8f1c |
case IBUS_SHIFT_MASK:
|
|
Packit Service |
1d8f1c |
return keymap->keymap[keycode][1];
|
|
Packit Service |
1d8f1c |
case IBUS_LOCK_MASK:
|
|
Packit Service |
1d8f1c |
return keymap->keymap[keycode][2];
|
|
Packit Service |
1d8f1c |
case IBUS_SHIFT_MASK | IBUS_LOCK_MASK:
|
|
Packit Service |
1d8f1c |
return keymap->keymap[keycode][3];
|
|
Packit Service |
1d8f1c |
case IBUS_MOD5_MASK:
|
|
Packit Service |
1d8f1c |
case IBUS_MOD5_MASK | IBUS_LOCK_MASK:
|
|
Packit Service |
1d8f1c |
return keymap->keymap[keycode][4];
|
|
Packit Service |
1d8f1c |
case IBUS_MOD5_MASK | IBUS_SHIFT_MASK:
|
|
Packit Service |
1d8f1c |
case IBUS_MOD5_MASK | IBUS_LOCK_MASK | IBUS_SHIFT_MASK:
|
|
Packit Service |
1d8f1c |
return keymap->keymap[keycode][5];
|
|
Packit Service |
1d8f1c |
default:
|
|
Packit Service |
1d8f1c |
break;
|
|
Packit Service |
1d8f1c |
}
|
|
Packit Service |
1d8f1c |
}
|
|
Packit Service |
1d8f1c |
|
|
Packit Service |
1d8f1c |
return IBUS_KEY_VoidSymbol;
|
|
Packit Service |
1d8f1c |
}
|