init
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Close stale issues and PRs / stale (push) Has been cancelled

This commit is contained in:
allhaileris
2026-02-16 15:50:16 +03:00
commit afb81b8278
13816 changed files with 3689732 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
SUBDIRS = indicator wayland xim preedit-window candidate nim
DISTCLEANFILES = Makefile.in

View File

@@ -0,0 +1,25 @@
moduledir = $(libdir)/nimf/modules/services
module_LTLIBRARIES = libnimf-candidate.la
libnimf_candidate_la_SOURCES = \
nimf-candidate.c \
$(NULL)
libnimf_candidate_la_CFLAGS = \
$(EXTRA_CFLAGS) \
-I$(top_srcdir)/libnimf \
-DG_LOG_DOMAIN=\"nimf\" \
$(NIMF_CANDIDATE_DEPS_CFLAGS)
libnimf_candidate_la_LDFLAGS = -avoid-version -module $(NIMF_CANDIDATE_DEPS_LIBS)
libnimf_candidate_la_LIBADD = $(top_builddir)/libnimf/libnimf.la
DISTCLEANFILES = Makefile.in
install-data-hook:
chmod -x $(DESTDIR)$(moduledir)/libnimf-candidate.so
rm -f $(DESTDIR)$(moduledir)/libnimf-candidate.la
uninstall-hook:
rm -f $(DESTDIR)$(moduledir)/libnimf-candidate.so
-rmdir -p $(DESTDIR)$(moduledir)

View File

@@ -0,0 +1,702 @@
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
/*
* nimf-candidate.c
* This file is part of Nimf.
*
* Copyright (C) 2015-2019 Hodong Kim <cogniti@gmail.com>
*
* Nimf is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Nimf is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include "nimf.h"
#define NIMF_TYPE_CANDIDATE (nimf_candidate_get_type ())
#define NIMF_CANDIDATE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NIMF_TYPE_CANDIDATE, NimfCandidate))
#define NIMF_CANDIDATE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NIMF_TYPE_CANDIDATE, NimfCandidateClass))
#define NIMF_IS_CANDIDATE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NIMF_TYPE_CANDIDATE))
#define NIMF_IS_CANDIDATE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NIMF_TYPE_CANDIDATE))
#define NIMF_CANDIDATE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NIMF_TYPE_CANDIDATE, NimfCandidateClass))
typedef struct _NimfCandidate NimfCandidate;
typedef struct _NimfCandidateClass NimfCandidateClass;
struct _NimfCandidateClass
{
NimfServiceClass parent_class;
};
struct _NimfCandidate
{
NimfService parent_instance;
gchar *id;
gboolean active;
NimfServiceIC *target;
GtkWidget *window;
GtkWidget *entry;
GtkWidget *treeview;
GtkWidget *scrollbar;
gint cell_height;
};
GType nimf_candidate_get_type (void) G_GNUC_CONST;
enum
{
INDEX_COLUMN,
MAIN_COLUMN,
EXTRA_COLUMN,
N_COLUMNS
};
static void
nimf_candidate_show (NimfCandidatable *candidatable,
NimfServiceIC *target,
gboolean show_entry)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfCandidate *candidate = NIMF_CANDIDATE (candidatable);
GtkRequisition natural_size;
int x, y, w, h;
GdkRectangle geometry;
const NimfRectangle *cursor_area;
cursor_area = nimf_service_ic_get_cursor_location (target);
#if GTK_CHECK_VERSION (3, 22, 0)
GdkDisplay *display = gtk_widget_get_display (candidate->window);
GdkMonitor *monitor;
monitor = gdk_display_get_monitor_at_point (display,
cursor_area->x, cursor_area->y);
gdk_monitor_get_geometry (monitor, &geometry);
#else
GdkScreen *screen = gtk_widget_get_screen (candidate->window);
gint monitor_num = gdk_screen_get_monitor_at_point (screen,
cursor_area->x,
cursor_area->y);
gdk_screen_get_monitor_geometry (screen, monitor_num, &geometry);
#endif
candidate->target = target;
if (show_entry)
gtk_widget_show (candidate->entry);
else
gtk_widget_hide (candidate->entry);
gtk_widget_show_all (candidate->window);
gtk_widget_get_preferred_size (candidate->window, NULL, &natural_size);
gtk_window_resize (GTK_WINDOW (candidate->window),
natural_size.width, natural_size.height);
gtk_window_get_size (GTK_WINDOW (candidate->window), &w, &h);
x = cursor_area->x - cursor_area->width;
y = cursor_area->y + cursor_area->height;
if (x + w > geometry.x + geometry.width)
x = geometry.x + geometry.width - w;
if ((y + h > geometry.y + geometry.height) &&
((cursor_area->y - h) >= geometry.y))
y = cursor_area->y - h;
gtk_window_move (GTK_WINDOW (candidate->window), x, y);
}
static void
nimf_candidate_hide (NimfCandidatable *candidatable)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
gtk_widget_hide (NIMF_CANDIDATE (candidatable)->window);
}
static gboolean
nimf_candidate_is_visible (NimfCandidatable *candidatable)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
return gtk_widget_is_visible (NIMF_CANDIDATE (candidatable)->window);
}
static void
nimf_candidate_set_page_values (NimfCandidatable *candidatable,
NimfServiceIC *target,
gint page_index,
gint n_pages,
gint page_size)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfCandidate *candidate = NIMF_CANDIDATE (candidatable);
GtkRange *range = GTK_RANGE (candidate->scrollbar);
candidate->target = target;
gtk_range_set_range (range, 1.0, (gdouble) n_pages + 1.0);
if (page_index != (gint) gtk_range_get_value (range))
gtk_range_set_value (range, (gdouble) page_index);
gtk_widget_set_size_request (candidate->treeview,
(gint) (candidate->cell_height * 10 / 1.6),
candidate->cell_height * page_size);
}
static void
nimf_candidate_clear (NimfCandidatable *candidatable,
NimfServiceIC *target)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfCandidate *candidate = NIMF_CANDIDATE (candidatable);
GtkTreeModel *model;
model = gtk_tree_view_get_model (GTK_TREE_VIEW (candidate->treeview));
gtk_list_store_clear (GTK_LIST_STORE (model));
nimf_candidate_set_page_values (candidatable, target, 1, 1, 5);
}
static void
nimf_candidate_append (NimfCandidatable *candidatable,
const gchar *text1,
const gchar *text2)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfCandidate *candidate = NIMF_CANDIDATE (candidatable);
GtkTreeModel *model;
GtkTreeIter iter;
gint n_row;
model = gtk_tree_view_get_model (GTK_TREE_VIEW (candidate->treeview));
n_row = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (model), NULL);
gtk_list_store_append (GTK_LIST_STORE (model), &iter);
gtk_list_store_set (GTK_LIST_STORE (model), &iter,
INDEX_COLUMN, (n_row + 1) % 10,
MAIN_COLUMN, text1, -1);
if (text2)
gtk_list_store_set (GTK_LIST_STORE (model), &iter,
EXTRA_COLUMN, text2, -1);
}
static gint
nimf_candidate_get_selected_index (NimfCandidatable *candidatable)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfCandidate *candidate = NIMF_CANDIDATE (candidatable);
GtkTreeIter iter;
GtkTreeModel *model;
GtkTreeSelection *selection;
gint index = -1;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (candidate->treeview));
if (gtk_tree_selection_get_selected (selection, &model, &iter))
{
GtkTreePath *path = gtk_tree_model_get_path (model, &iter);
gint *indices = gtk_tree_path_get_indices (path);
if (indices)
index = indices[0];
gtk_tree_path_free (path);
}
return index;
}
static gchar *
nimf_candidate_get_selected_text (NimfCandidatable *candidatable)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfCandidate *candidate = NIMF_CANDIDATE (candidatable);
GtkTreeIter iter;
GtkTreeModel *model;
gchar *text = NULL;
GtkTreeSelection *selection;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (candidate->treeview));
if (gtk_tree_selection_get_selected (selection, &model, &iter))
gtk_tree_model_get (model, &iter, MAIN_COLUMN, &text, -1);
return text;
}
static void
nimf_candidate_select_first_item_in_page (NimfCandidatable *candidatable)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfCandidate *candidate = NIMF_CANDIDATE (candidatable);
GtkTreeModel *model;
GtkTreeSelection *selection;
GtkTreeIter iter;
model = gtk_tree_view_get_model (GTK_TREE_VIEW (candidate->treeview));
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (candidate->treeview));
if (gtk_tree_model_get_iter_first (model, &iter))
gtk_tree_selection_select_iter (selection, &iter);
}
static void
nimf_candidate_select_last_item_in_page (NimfCandidatable *candidatable)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfCandidate *candidate = NIMF_CANDIDATE (candidatable);
GtkTreeModel *model;
GtkTreeSelection *selection;
GtkTreeIter iter;
model = gtk_tree_view_get_model (GTK_TREE_VIEW (candidate->treeview));
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (candidate->treeview));
gint n_row = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (model), NULL);
if (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (model),
&iter, NULL, MAX (0, n_row - 1)))
gtk_tree_selection_select_iter (selection, &iter);
}
static void
nimf_candidate_select_item_by_index_in_page (NimfCandidatable *candidatable,
gint index)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfCandidate *candidate = NIMF_CANDIDATE (candidatable);
GtkTreeModel *model;
GtkTreeSelection *selection;
GtkTreeIter iter;
model = gtk_tree_view_get_model (GTK_TREE_VIEW (candidate->treeview));
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (candidate->treeview));
if (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (model), &iter, NULL, index))
gtk_tree_selection_select_iter (selection, &iter);
}
static void
nimf_candidate_select_previous_item (NimfCandidatable *candidatable)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfCandidate *candidate = NIMF_CANDIDATE (candidatable);
GtkTreeModel *model;
GtkTreeSelection *selection;
GtkTreeIter iter;
model = gtk_tree_view_get_model (GTK_TREE_VIEW (candidate->treeview));
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (candidate->treeview));
if (gtk_tree_selection_get_selected (selection, &model, &iter) == FALSE)
{
nimf_candidate_select_last_item_in_page (candidatable);
return;
}
if (gtk_tree_model_iter_previous (model, &iter))
{
gtk_tree_selection_select_iter (selection, &iter);
}
else
{
NimfEngineClass *engine_class;
NimfEngine *engine;
engine = nimf_service_ic_get_engine (candidate->target);
engine_class = NIMF_ENGINE_GET_CLASS (engine);
if (engine_class->candidate_page_up)
{
if (engine_class->candidate_page_up (engine, candidate->target))
nimf_candidate_select_last_item_in_page (candidatable);
}
}
}
static void
nimf_candidate_select_next_item (NimfCandidatable *candidatable)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfCandidate *candidate = NIMF_CANDIDATE (candidatable);
GtkTreeModel *model;
GtkTreeSelection *selection;
GtkTreeIter iter;
model = gtk_tree_view_get_model (GTK_TREE_VIEW (candidate->treeview));
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (candidate->treeview));
if (gtk_tree_selection_get_selected (selection, &model, &iter) == FALSE)
{
nimf_candidate_select_first_item_in_page (candidatable);
return;
}
if (gtk_tree_model_iter_next (model, &iter))
{
gtk_tree_selection_select_iter (selection, &iter);
}
else
{
NimfEngineClass *engine_class;
NimfEngine *engine;
engine = nimf_service_ic_get_engine (candidate->target);
engine_class = NIMF_ENGINE_GET_CLASS (engine);
if (engine_class->candidate_page_down)
{
if (engine_class->candidate_page_down (engine, candidate->target))
nimf_candidate_select_first_item_in_page (candidatable);
}
}
}
static void
nimf_candidate_set_auxiliary_text (NimfCandidatable *candidatable,
const gchar *text,
gint cursor_pos)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfCandidate *candidate = NIMF_CANDIDATE (candidatable);
gtk_entry_set_text (GTK_ENTRY (candidate->entry), text);
gtk_editable_set_position (GTK_EDITABLE (candidate->entry), cursor_pos);
}
static void
nimf_candidate_iface_init (NimfCandidatableInterface *iface)
{
iface->show = nimf_candidate_show;
iface->hide = nimf_candidate_hide;
iface->is_visible = nimf_candidate_is_visible;
iface->clear = nimf_candidate_clear;
iface->set_page_values = nimf_candidate_set_page_values;
iface->append = nimf_candidate_append;
iface->get_selected_index = nimf_candidate_get_selected_index;
iface->get_selected_text = nimf_candidate_get_selected_text;
iface->select_first_item_in_page = nimf_candidate_select_first_item_in_page;
iface->select_last_item_in_page = nimf_candidate_select_last_item_in_page;
iface->select_item_by_index_in_page = nimf_candidate_select_item_by_index_in_page;
iface->select_previous_item = nimf_candidate_select_previous_item;
iface->select_next_item = nimf_candidate_select_next_item;
iface->set_auxiliary_text = nimf_candidate_set_auxiliary_text;
}
G_DEFINE_DYNAMIC_TYPE_EXTENDED (NimfCandidate,
nimf_candidate,
NIMF_TYPE_SERVICE,
0,
G_IMPLEMENT_INTERFACE_DYNAMIC (NIMF_TYPE_CANDIDATABLE,
nimf_candidate_iface_init));
static const gchar *
nimf_candidate_get_id (NimfService *service)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
g_return_val_if_fail (NIMF_IS_SERVICE (service), NULL);
return NIMF_CANDIDATE (service)->id;
}
static gboolean
nimf_candidate_is_active (NimfService *service)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
return NIMF_CANDIDATE (service)->active;
}
static void
on_tree_view_row_activated (GtkTreeView *tree_view,
GtkTreePath *path,
GtkTreeViewColumn *column,
NimfCandidate *candidate)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfEngineClass *engine_class;
NimfEngine *engine;
engine = nimf_service_ic_get_engine (candidate->target);
g_return_if_fail (candidate->target && NIMF_IS_ENGINE (engine));
engine_class = NIMF_ENGINE_GET_CLASS (engine);
gchar *text;
gint *indices = gtk_tree_path_get_indices (path);
text = nimf_candidate_get_selected_text (NIMF_CANDIDATABLE (candidate));
if (engine_class->candidate_clicked)
engine_class->candidate_clicked (engine,
candidate->target, text, indices[0]);
g_free (text);
}
static gboolean
on_range_change_value (GtkRange *range,
GtkScrollType scroll,
gdouble value,
NimfCandidate *candidate)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfEngine *engine = nimf_service_ic_get_engine (candidate->target);
g_return_val_if_fail (candidate->target && NIMF_IS_ENGINE (engine), FALSE);
NimfEngineClass *engine_class;
GtkAdjustment *adjustment;
gdouble lower, upper;
adjustment = gtk_range_get_adjustment (range);
lower = gtk_adjustment_get_lower (adjustment);
upper = gtk_adjustment_get_upper (adjustment);
if (value < lower)
value = lower;
if (value > upper - 1)
value = upper - 1;
engine_class = NIMF_ENGINE_GET_CLASS (engine);
if (engine_class->candidate_scrolled)
engine_class->candidate_scrolled (engine, candidate->target, value);
return FALSE;
}
static gboolean
on_entry_draw (GtkWidget *widget,
cairo_t *cr,
gpointer user_data)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
GtkStyleContext *style_context;
PangoContext *pango_context;
PangoLayout *layout;
const char *text;
gint cursor_index;
gint x, y;
style_context = gtk_widget_get_style_context (widget);
pango_context = gtk_widget_get_pango_context (widget);
layout = gtk_entry_get_layout (GTK_ENTRY (widget));
text = pango_layout_get_text (layout);
gtk_entry_get_layout_offsets (GTK_ENTRY (widget), &x, &y);
cursor_index = g_utf8_offset_to_pointer (text, gtk_editable_get_position (GTK_EDITABLE (widget))) - text;
gtk_render_insertion_cursor (style_context, cr, x, y, layout, cursor_index,
pango_context_get_base_dir (pango_context));
return FALSE;
}
static gboolean
nimf_candidate_start (NimfService *service)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfCandidate *candidate = NIMF_CANDIDATE (service);
if (candidate->active)
return TRUE;
GtkCellRenderer *renderer;
GtkTreeViewColumn *column[N_COLUMNS];
GtkListStore *store;
gint fixed_height = 32;
gint horizontal_space;
gtk_init (NULL, NULL);
/* gtk entry */
candidate->entry = gtk_entry_new ();
gtk_editable_set_editable (GTK_EDITABLE (candidate->entry), FALSE);
gtk_widget_set_no_show_all (candidate->entry, TRUE);
g_signal_connect_after (candidate->entry, "draw",
G_CALLBACK (on_entry_draw), NULL);
/* gtk tree view */
store = gtk_list_store_new (N_COLUMNS, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING);
candidate->treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
g_object_unref (store);
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (candidate->treeview), FALSE);
gtk_tree_view_set_activate_on_single_click (GTK_TREE_VIEW (candidate->treeview), TRUE);
gtk_widget_style_get (candidate->treeview, "horizontal-separator",
&horizontal_space, NULL);
candidate->cell_height = fixed_height + horizontal_space / 2;
gtk_widget_set_size_request (candidate->treeview,
(gint) (candidate->cell_height * 10 / 1.6),
candidate->cell_height * 10);
g_signal_connect (candidate->treeview, "row-activated",
(GCallback) on_tree_view_row_activated, candidate);
/* column */
renderer = gtk_cell_renderer_text_new ();
g_object_set (renderer, "height", fixed_height, "font", "Sans 14", NULL);
column[INDEX_COLUMN] = gtk_tree_view_column_new_with_attributes ("Index",
renderer, "text", INDEX_COLUMN, NULL);
column[MAIN_COLUMN] = gtk_tree_view_column_new_with_attributes ("Main",
renderer, "text", MAIN_COLUMN, NULL);
column[EXTRA_COLUMN] = gtk_tree_view_column_new_with_attributes ("Extra",
renderer, "text", EXTRA_COLUMN, NULL);
gtk_tree_view_column_set_sizing (column[INDEX_COLUMN], GTK_TREE_VIEW_COLUMN_AUTOSIZE);
gtk_tree_view_column_set_sizing (column[MAIN_COLUMN], GTK_TREE_VIEW_COLUMN_AUTOSIZE);
gtk_tree_view_column_set_sizing (column[EXTRA_COLUMN], GTK_TREE_VIEW_COLUMN_AUTOSIZE);
gtk_tree_view_append_column (GTK_TREE_VIEW (candidate->treeview),
column[INDEX_COLUMN]);
gtk_tree_view_append_column (GTK_TREE_VIEW (candidate->treeview),
column[MAIN_COLUMN]);
gtk_tree_view_append_column (GTK_TREE_VIEW (candidate->treeview),
column[EXTRA_COLUMN]);
/* scrollbar */
GtkAdjustment *adjustment = gtk_adjustment_new (1.0, 1.0, 2.0, 1.0, 1.0, 1.0);
candidate->scrollbar = gtk_scrollbar_new (GTK_ORIENTATION_VERTICAL, adjustment);
gtk_range_set_slider_size_fixed (GTK_RANGE (candidate->scrollbar), FALSE);
g_signal_connect (candidate->scrollbar, "change-value",
G_CALLBACK (on_range_change_value), candidate);
GtkCssProvider *provider;
GtkStyleContext *style_context;
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_data (GTK_CSS_PROVIDER (provider),
".scrollbar {"
" -GtkScrollbar-has-backward-stepper: true;"
" -GtkScrollbar-has-forward-stepper: true;"
" -GtkScrollbar-has-secondary-forward-stepper: true;"
"}" , -1, NULL);
style_context = gtk_widget_get_style_context (candidate->scrollbar);
gtk_style_context_add_provider (style_context,
GTK_STYLE_PROVIDER (provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
g_object_unref (provider);
/* gtk box */
GtkWidget *vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
GtkWidget *hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_box_pack_start (GTK_BOX (vbox), candidate->entry, TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (hbox), candidate->treeview, TRUE, TRUE, 0);
gtk_box_pack_end (GTK_BOX (hbox), candidate->scrollbar, FALSE, TRUE, 0);
/* gtk window */
candidate->window = gtk_window_new (GTK_WINDOW_POPUP);
gtk_window_set_type_hint (GTK_WINDOW (candidate->window),
GDK_WINDOW_TYPE_HINT_POPUP_MENU);
gtk_container_set_border_width (GTK_CONTAINER (candidate->window), 1);
gtk_container_add (GTK_CONTAINER (candidate->window), vbox);
gtk_widget_realize (candidate->window);
candidate->active = TRUE;
return TRUE;
}
static void
nimf_candidate_stop (NimfService *service)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfCandidate *candidate = NIMF_CANDIDATE (service);
if (!candidate->active)
return;
candidate->active = FALSE;
}
static void
nimf_candidate_init (NimfCandidate *candidate)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
candidate->id = g_strdup ("nimf-candidate");
}
static void
nimf_candidate_finalize (GObject *object)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfCandidate *candidate = NIMF_CANDIDATE (object);
if (candidate->active)
nimf_candidate_stop (NIMF_SERVICE (candidate));
gtk_widget_destroy (candidate->window);
g_free (candidate->id);
G_OBJECT_CLASS (nimf_candidate_parent_class)->finalize (object);
}
static void
nimf_candidate_class_init (NimfCandidateClass *class)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
GObjectClass *object_class = G_OBJECT_CLASS (class);
NimfServiceClass *service_class = NIMF_SERVICE_CLASS (class);
service_class->get_id = nimf_candidate_get_id;
service_class->start = nimf_candidate_start;
service_class->stop = nimf_candidate_stop;
service_class->is_active = nimf_candidate_is_active;
object_class->finalize = nimf_candidate_finalize;
}
static void
nimf_candidate_class_finalize (NimfCandidateClass *class)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
}
void module_register_type (GTypeModule *type_module)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
nimf_candidate_register_type (type_module);
}
GType module_get_type ()
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
return nimf_candidate_get_type ();
}

View File

@@ -0,0 +1,26 @@
moduledir = $(libdir)/nimf/modules/services
module_LTLIBRARIES = libnimf-indicator.la
libnimf_indicator_la_SOURCES = \
nimf-indicator.c \
$(NULL)
libnimf_indicator_la_CFLAGS = \
$(EXTRA_CFLAGS) \
-I$(top_srcdir)/libnimf \
-DG_LOG_DOMAIN=\"nimf\" \
-DNIMF_MODULE_DIR=\"$(libdir)/nimf/modules\" \
$(NIMF_INDICATOR_DEPS_CFLAGS)
libnimf_indicator_la_LDFLAGS = -avoid-version -module $(NIMF_INDICATOR_DEPS_LIBS)
libnimf_indicator_la_LIBADD = $(top_builddir)/libnimf/libnimf.la
DISTCLEANFILES = Makefile.in
install-data-hook:
chmod -x $(DESTDIR)$(moduledir)/libnimf-indicator.so
rm -f $(DESTDIR)$(moduledir)/libnimf-indicator.la
uninstall-hook:
rm -f $(DESTDIR)$(moduledir)/libnimf-indicator.so
-rmdir -p $(DESTDIR)$(moduledir)

View File

@@ -0,0 +1,584 @@
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
/*
* nimf-indicator.c
* This file is part of Nimf.
*
* Copyright (C) 2015-2020 Hodong Kim <cogniti@gmail.com>
*
* Nimf is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Nimf is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include "nimf.h"
#include <libayatana-appindicator/app-indicator.h>
#include <libxklavier/xklavier.h>
#include <gdk/gdkx.h>
#include "nimf-utils-private.h"
#define NIMF_TYPE_INDICATOR (nimf_indicator_get_type ())
#define NIMF_INDICATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NIMF_TYPE_INDICATOR, NimfIndicator))
#define NIMF_INDICATOR_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), NIMF_TYPE_INDICATOR, NimfIndicatorClass))
#define NIMF_IS_INDICATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NIMF_TYPE_INDICATOR))
#define NIMF_IS_INDICATOR_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), NIMF_TYPE_INDICATOR))
#define NIMF_INDICATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NIMF_TYPE_INDICATOR, NimfIndicatorClass))
typedef struct _NimfIndicator NimfIndicator;
typedef struct _NimfIndicatorClass NimfIndicatorClass;
struct _NimfIndicatorClass
{
NimfServiceClass parent_class;
};
struct _NimfIndicator
{
NimfService parent_instance;
gchar *id;
gboolean active;
AppIndicator *appindicator;
gchar *engine_id;
guint watcher_id;
guint source_id;
XklEngine *xklengine;
GMenu *menu;
};
GType nimf_indicator_get_type (void) G_GNUC_CONST;
G_DEFINE_DYNAMIC_TYPE (NimfIndicator, nimf_indicator, NIMF_TYPE_SERVICE);
static void
on_menu_engine (GSimpleAction *action,
GVariant *parameter,
gpointer server)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
const gchar *engine_method;
gchar **strv;
engine_method = g_variant_get_string (parameter, NULL);
strv = g_strsplit (engine_method, ",", -1);
if (g_strv_length (strv) == 1)
nimf_server_change_engine_by_id (server, engine_method);
else
nimf_server_change_engine (server, strv[0], strv[1]);
g_strfreev (strv);
}
static void
on_menu_settings (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
g_spawn_command_line_async ("nimf-settings", NULL);
}
static void
on_menu_about (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
static GtkWidget *about = NULL;
if (!about)
{
GtkWidget *parent;
gchar *artists[] = {_("Hodong Kim <cogniti@gmail.com>"), NULL};
gchar *authors[] = {_("Hodong Kim <cogniti@gmail.com>"), NULL};
gchar *documenters[] = {_("Hodong Kim <cogniti@gmail.com>"),
_("Bumsik Kim <k.bumsik@gmail.com>"), NULL};
parent = gtk_window_new (GTK_WINDOW_TOPLEVEL);
about = gtk_about_dialog_new ();
gtk_window_set_transient_for (GTK_WINDOW (about), GTK_WINDOW (parent));
gtk_window_set_destroy_with_parent (GTK_WINDOW (about), TRUE);
gtk_window_set_icon_name (GTK_WINDOW (about), "nimf-logo");
g_object_set (about,
"artists", artists,
"authors", authors,
"comments", _("Nimf is an input method framework"),
"copyright", _("Copyright (c) 2015-2019 Hodong Kim"),
"documenters", documenters,
"license-type", GTK_LICENSE_LGPL_3_0,
"logo-icon-name", "nimf-logo",
"program-name", _("Nimf"),
"translator-credits", _("Hodong Kim, Max Neupert"),
"version", VERSION,
"website", "https://github.com/hamonikr/nimf",
"website-label", _("Website"),
NULL);
gtk_dialog_run (GTK_DIALOG (about));
gtk_widget_destroy (parent);
about = NULL;
}
else
{
gtk_window_present (GTK_WINDOW (about));
}
}
const GActionEntry entries[] = {
{ "engine", on_menu_engine, "s", NULL, NULL },
{ "settings", on_menu_settings, NULL, NULL, NULL },
{ "about", on_menu_about, NULL, NULL, NULL }
};
static void on_engine_changed (NimfServer *server,
const gchar *engine_id,
const gchar *icon_name,
NimfIndicator *indicator)
{
g_debug (G_STRLOC ": %s: icon_name: %s", G_STRFUNC, icon_name);
g_free (indicator->engine_id);
indicator->engine_id = g_strdup (engine_id);
app_indicator_set_icon_full (indicator->appindicator, icon_name, icon_name);
}
static void on_engine_status_changed (NimfServer *server,
const gchar *engine_id,
const gchar *icon_name,
NimfIndicator *indicator)
{
g_debug (G_STRLOC ": %s: icon_name: %s", G_STRFUNC, icon_name);
if (!g_strcmp0 (indicator->engine_id, engine_id))
app_indicator_set_icon_full (indicator->appindicator, icon_name, icon_name);
}
const gchar *
nimf_indicator_get_id (NimfService *service)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
g_return_val_if_fail (NIMF_IS_SERVICE (service), NULL);
return NIMF_INDICATOR (service)->id;
}
static gboolean nimf_indicator_is_active (NimfService *service)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
return NIMF_INDICATOR (service)->active;
}
static GMenu *
nimf_indicator_build_section1 (NimfIndicator *indicator,
NimfServer *server)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
gchar **engine_ids;
guint i;
GMenu *section1 = g_menu_new ();
engine_ids = nimf_server_get_loaded_engine_ids (server);
for (i = 0; engine_ids && engine_ids[i]; i++)
{
GMenuItem *engine_menu;
GSettings *settings;
gchar *schema_id;
gchar *schema_name;
GModule *module;
gchar *path;
gchar *symbol_name;
gchar *p;
NimfMethodInfo ** (* get_method_infos) ();
schema_id = g_strdup_printf ("org.nimf.engines.%s", engine_ids[i]);
settings = g_settings_new (schema_id);
schema_name = g_settings_get_string (settings, "hidden-schema-name");
path = g_module_build_path (NIMF_MODULE_DIR, engine_ids[i]);
module = g_module_open (path, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
symbol_name = g_strdup_printf ("%s_get_method_infos", engine_ids[i]);
for (p = symbol_name; *p; p++)
if (*p == '-')
*p = '_';
if (g_module_symbol (module, symbol_name, (gpointer *) &get_method_infos))
{
GMenu *submenu1;
NimfMethodInfo **infos;
const char *prev_group = NULL;
gboolean gnome;
gint j;
infos = get_method_infos ();
submenu1 = g_menu_new ();
engine_menu = g_menu_item_new (schema_name, "indicator.engine");
g_menu_item_set_submenu (engine_menu, G_MENU_MODEL (submenu1));
gnome = gnome_is_running ();
for (j = 0; infos[j]; j++)
{
GMenu *submenu2 = NULL;
GMenuItem *menu_item;
gchar *engine_method;
if (!gnome && infos[j]->group && g_strcmp0 (infos[j]->group, prev_group))
{
GMenuItem *lang_menu;
submenu2 = g_menu_new ();
lang_menu = g_menu_item_new (infos[j]->group, NULL);
g_menu_item_set_submenu (lang_menu, G_MENU_MODEL (submenu2));
g_menu_append_item (submenu1, lang_menu);
g_object_unref (lang_menu);
}
menu_item = g_menu_item_new (infos[j]->label, "indicator.engine");
engine_method = g_strjoin (",", engine_ids[i], infos[j]->method_id, NULL);
g_menu_item_set_attribute (menu_item, G_MENU_ATTRIBUTE_TARGET, "s", engine_method);
if (!gnome && infos[j]->group)
g_menu_append_item (submenu2, menu_item);
else
g_menu_append_item (submenu1, menu_item);
prev_group = infos[j]->group;
g_object_unref (menu_item);
if (submenu2)
g_object_unref (submenu2);
g_free (engine_method);
}
nimf_method_info_freev (infos);
g_object_unref (submenu1);
}
else
{
engine_menu = g_menu_item_new (schema_name, "indicator.engine");
g_menu_item_set_attribute (engine_menu, G_MENU_ATTRIBUTE_TARGET, "s", engine_ids[i]);
}
g_menu_append_item (section1, engine_menu);
g_object_unref (engine_menu);
g_free (symbol_name);
g_module_close (module);
g_free (path);
g_free (schema_name);
g_free (schema_id);
g_object_unref (settings);
}
g_strfreev (engine_ids);
return section1;
}
static GtkMenu*
nimf_indicator_build_menu (NimfIndicator *indicator)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
if (!gtk_init_check (NULL, NULL))
return NULL;
/* menu */
GtkWidget *gtk_menu;
GMenu *section1;
GMenu *section2;
GMenuItem *settings_menu;
GMenuItem *about_menu;
GIcon *settings_icon;
GIcon *about_icon;
GSimpleActionGroup *actions;
indicator->menu = g_menu_new ();
gtk_menu = gtk_menu_new_from_model (G_MENU_MODEL (indicator->menu));
actions = g_simple_action_group_new ();
NimfServer *server = nimf_server_get_default ();
g_action_map_add_action_entries (G_ACTION_MAP (actions), entries, G_N_ELEMENTS (entries), server);
gtk_widget_insert_action_group (gtk_menu, "indicator", G_ACTION_GROUP (actions));
section1 = nimf_indicator_build_section1 (indicator, server);
section2 = g_menu_new ();
settings_menu = g_menu_item_new (_("Settings"), "indicator.settings");
about_menu = g_menu_item_new (_("About"), "indicator.about");
settings_icon = g_icon_new_for_string ("preferences-system", NULL);
about_icon = g_icon_new_for_string ("help-about", NULL);
g_menu_item_set_icon (settings_menu, settings_icon);
g_menu_item_set_icon (about_menu, about_icon);
g_menu_append_item (section2, settings_menu);
g_menu_append_item (section2, about_menu);
g_menu_append_section (indicator->menu, NULL, G_MENU_MODEL (section1));
g_menu_append_section (indicator->menu, NULL, G_MENU_MODEL (section2));
g_object_unref (section1);
g_object_unref (section2);
g_object_unref (settings_icon);
g_object_unref (about_icon);
g_object_unref (settings_menu);
g_object_unref (about_menu);
g_object_unref (actions);
gtk_widget_show_all (gtk_menu);
return GTK_MENU (gtk_menu);
}
static void
nimf_indicator_update_menu (NimfIndicator *indicator)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
GMenu *section1;
section1 = nimf_indicator_build_section1 (indicator,
nimf_server_get_default ());
g_menu_remove (indicator->menu, 0);
g_menu_prepend_section (indicator->menu, NULL, G_MENU_MODEL (section1));
g_object_unref (section1);
}
static void
nimf_indicator_create_appindicator (NimfIndicator *indicator)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
GtkMenu *gtk_menu = nimf_indicator_build_menu (indicator);
NimfServer *server = nimf_server_get_default ();
indicator->appindicator = app_indicator_new ("nimf-indicator",
"nimf-focus-out",
APP_INDICATOR_CATEGORY_APPLICATION_STATUS);
app_indicator_set_status (indicator->appindicator,
APP_INDICATOR_STATUS_ACTIVE);
app_indicator_set_icon_full (indicator->appindicator,
"nimf-focus-out", "Nimf");
app_indicator_set_menu (indicator->appindicator, gtk_menu);
g_signal_connect (server, "engine-changed",
G_CALLBACK (on_engine_changed), indicator);
g_signal_connect (server, "engine-status-changed",
G_CALLBACK (on_engine_status_changed), indicator);
g_signal_connect_swapped (server, "engine-loaded",
G_CALLBACK (nimf_indicator_update_menu), indicator);
g_signal_connect_swapped (server, "engine-unloaded",
G_CALLBACK (nimf_indicator_update_menu), indicator);
/* activate xkb options for x11 */
if ((!gnome_xkb_is_available () || !gnome_is_running ()) &&
!g_strcmp0 (g_getenv ("XDG_SESSION_TYPE"), "x11"))
{
XklConfigRec *rec;
GSettings *settings;
if (!indicator->xklengine)
indicator->xklengine = xkl_engine_get_instance (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
rec = xkl_config_rec_new ();
settings = g_settings_new ("org.nimf.settings");
xkl_config_rec_get_from_server (rec, indicator->xklengine);
g_strfreev (rec->options);
rec->options = g_settings_get_strv (settings, "xkb-options");
xkl_config_rec_activate (rec, indicator->xklengine);
g_object_unref (settings);
g_object_unref (rec);
}
}
static void
on_name_appeared (GDBusConnection *connection,
const gchar *name,
const gchar *name_owner,
gpointer user_data)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfIndicator *indicator = user_data;
if (indicator->source_id)
{
g_source_remove (indicator->source_id);
indicator->source_id = 0;
}
g_bus_unwatch_name (indicator->watcher_id);
indicator->watcher_id = 0;
nimf_indicator_create_appindicator (indicator);
}
static gboolean
on_timeout (NimfIndicator *indicator)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
if (indicator->watcher_id)
{
g_bus_unwatch_name (indicator->watcher_id);
indicator->watcher_id = 0;
}
indicator->source_id = 0;
nimf_indicator_create_appindicator (indicator);
return G_SOURCE_REMOVE;
}
static gboolean nimf_indicator_start (NimfService *service)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfIndicator *indicator = NIMF_INDICATOR (service);
if (indicator->active)
return TRUE;
/*
* After the watcher is ready, nimf-indicator should be started.
* Otherwise, the icon of nimf-indicator may appears strange in some
* environments. In addition, after the window manager sets the xkb options,
* the nimf-indicator will set the xkb options again.
* So we will delay the launch of the nimf-indicator until the watcher is
* ready.
*/
indicator->watcher_id = g_bus_watch_name (G_BUS_TYPE_SESSION,
"org.nimf.settings",
G_BUS_NAME_WATCHER_FLAGS_NONE,
on_name_appeared, NULL,
indicator, NULL);
indicator->source_id = g_timeout_add_seconds (3, (GSourceFunc) on_timeout, indicator);
return indicator->active = TRUE;
}
static void nimf_indicator_stop (NimfService *service)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfIndicator *indicator = NIMF_INDICATOR (service);
if (!indicator->active)
return;
if (indicator->watcher_id)
{
g_bus_unwatch_name (indicator->watcher_id);
indicator->watcher_id = 0;
}
if (indicator->source_id)
{
g_source_remove (indicator->source_id);
indicator->source_id = 0;
}
if (indicator->appindicator)
{
g_signal_handlers_disconnect_by_data (nimf_server_get_default (), indicator);
g_object_unref (indicator->appindicator);
}
if (indicator->menu)
g_object_unref (indicator->menu);
indicator->active = FALSE;
}
static void
nimf_indicator_init (NimfIndicator *indicator)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
indicator->id = g_strdup ("nimf-indicator");
}
static void
nimf_indicator_finalize (GObject *object)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfIndicator *indicator = NIMF_INDICATOR (object);
if (indicator->active)
nimf_indicator_stop (NIMF_SERVICE (indicator));
if (indicator->xklengine)
g_object_unref (indicator->xklengine);
g_free (indicator->engine_id);
g_free (indicator->id);
G_OBJECT_CLASS (nimf_indicator_parent_class)->finalize (object);
}
static void
nimf_indicator_class_init (NimfIndicatorClass *class)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
GObjectClass *object_class = G_OBJECT_CLASS (class);
NimfServiceClass *service_class = NIMF_SERVICE_CLASS (class);
service_class->get_id = nimf_indicator_get_id;
service_class->start = nimf_indicator_start;
service_class->stop = nimf_indicator_stop;
service_class->is_active = nimf_indicator_is_active;
object_class->finalize = nimf_indicator_finalize;
}
static void
nimf_indicator_class_finalize (NimfIndicatorClass *class)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
}
void module_register_type (GTypeModule *type_module)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
nimf_indicator_register_type (type_module);
}
GType module_get_type ()
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
return nimf_indicator_get_type ();
}

View File

@@ -0,0 +1,30 @@
moduledir = $(libdir)/nimf/modules/services
module_LTLIBRARIES = libnimf-nim.la
libnimf_nim_la_SOURCES = \
nimf-nim.c \
nimf-nim.h \
nimf-nim-ic.c \
nimf-nim-ic.h \
nimf-connection.c \
nimf-connection.h \
$(NULL)
libnimf_nim_la_CFLAGS = \
$(EXTRA_CFLAGS) \
-I$(top_srcdir)/libnimf \
-DG_LOG_DOMAIN=\"nimf\" \
$(NIMF_NIM_DEPS_CFLAGS)
libnimf_nim_la_LDFLAGS = -avoid-version -module $(NIMF_NIM_DEPS_LIBS)
libnimf_nim_la_LIBADD = $(top_builddir)/libnimf/libnimf.la
DISTCLEANFILES = Makefile.in
install-data-hook:
chmod -x $(DESTDIR)$(moduledir)/libnimf-nim.so
rm -f $(DESTDIR)$(moduledir)/libnimf-nim.la
uninstall-hook:
rm -f $(DESTDIR)$(moduledir)/libnimf-nim.so
-rmdir -p $(DESTDIR)$(moduledir)

View File

@@ -0,0 +1,124 @@
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
/*
* nimf-connection.c
* This file is part of Nimf.
*
* Copyright (C) 2015-2019 Hodong Kim <cogniti@gmail.com>
*
* Nimf is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Nimf is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; If not, see <http://www.gnu.org/licenses/>.
*/
#include "nimf-connection.h"
#include "nimf-events.h"
#include "nimf-service-ic.h"
#include <string.h>
#include "nimf-nim-ic.h"
G_DEFINE_TYPE (NimfConnection, nimf_connection, G_TYPE_OBJECT);
void
nimf_connection_change_engine_by_id (NimfConnection *connection,
const gchar *engine_id)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
GHashTableIter iter;
gpointer im;
g_hash_table_iter_init (&iter, connection->ics);
while (g_hash_table_iter_next (&iter, NULL, &im))
{
if (NIMF_NIM_IC (im)->icid == connection->nim->last_focused_icid)
nimf_service_ic_change_engine_by_id (im, engine_id);
}
}
void
nimf_connection_change_engine (NimfConnection *connection,
const gchar *engine_id,
const gchar *method_id)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
GHashTableIter iter;
gpointer im;
g_hash_table_iter_init (&iter, connection->ics);
while (g_hash_table_iter_next (&iter, NULL, &im))
{
if (NIMF_NIM_IC (im)->icid == connection->nim->last_focused_icid)
nimf_service_ic_change_engine (im, engine_id, method_id);
}
}
static void
nimf_connection_init (NimfConnection *connection)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
connection->result = nimf_result_new ();
connection->ics = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
(GDestroyNotify) g_object_unref);
}
static void
nimf_connection_finalize (GObject *object)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfConnection *connection = NIMF_CONNECTION (object);
if (connection->source)
{
g_source_destroy (connection->source);
g_source_unref (connection->source);
}
if (connection->socket_connection)
g_object_unref (connection->socket_connection);
nimf_result_unref (connection->result);
g_hash_table_unref (connection->ics);
G_OBJECT_CLASS (nimf_connection_parent_class)->finalize (object);
}
static void
nimf_connection_class_init (NimfConnectionClass *class)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
GObjectClass *object_class = G_OBJECT_CLASS (class);
object_class->finalize = nimf_connection_finalize;
}
NimfConnection *
nimf_connection_new ()
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
return g_object_new (NIMF_TYPE_CONNECTION, NULL);
}
guint16
nimf_connection_get_id (NimfConnection *connection)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
g_return_val_if_fail (NIMF_IS_CONNECTION (connection), 0);
return connection->id;
}

View File

@@ -0,0 +1,70 @@
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
/*
* nimf-connection.h
* This file is part of Nimf.
*
* Copyright (C) 2015-2019 Hodong Kim <cogniti@gmail.com>
*
* Nimf is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Nimf is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __NIMF_CONNECTION_H__
#define __NIMF_CONNECTION_H__
#include <glib-object.h>
#include "nimf-nim.h"
#include "nimf-message-private.h"
G_BEGIN_DECLS
#define NIMF_TYPE_CONNECTION (nimf_connection_get_type ())
#define NIMF_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NIMF_TYPE_CONNECTION, NimfConnection))
#define NIMF_CONNECTION_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), NIMF_TYPE_CONNECTION, NimfConnectionClass))
#define NIMF_IS_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NIMF_TYPE_CONNECTION))
#define NIMF_IS_CONNECTION_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), NIMF_TYPE_CONNECTION))
#define NIMF_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NIMF_TYPE_CONNECTION, NimfConnectionClass))
typedef struct _NimfConnection NimfConnection;
typedef struct _NimfConnectionClass NimfConnectionClass;
struct _NimfConnection
{
GObject parent_instance;
guint16 id;
NimfNim *nim;
GSocket *socket;
NimfResult *result;
GSource *source;
GSocketConnection *socket_connection;
GHashTable *ics;
};
struct _NimfConnectionClass
{
GObjectClass parent_class;
};
GType nimf_connection_get_type (void) G_GNUC_CONST;
NimfConnection *nimf_connection_new (void);
guint16 nimf_connection_get_id (NimfConnection *connection);
void nimf_connection_change_engine_by_id
(NimfConnection *connection,
const gchar *engine_id);
void nimf_connection_change_engine (NimfConnection *connection,
const gchar *engine_id,
const gchar *method_id);
G_END_DECLS
#endif /* __NIMF_CONNECTION_H__ */

View File

@@ -0,0 +1,211 @@
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
/*
* nimf-nim-ic.c
* This file is part of Nimf.
*
* Copyright (C) 2015-2019 Hodong Kim <cogniti@gmail.com>
*
* Nimf is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Nimf is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; If not, see <http://www.gnu.org/licenses/>.
*/
#include "nimf-nim-ic.h"
#include <string.h>
#include "nimf-connection.h"
#include "nimf-message-private.h"
G_DEFINE_TYPE (NimfNimIC, nimf_nim_ic, NIMF_TYPE_SERVICE_IC);
void
nimf_nim_ic_emit_commit (NimfServiceIC *ic,
const gchar *text)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfNimIC *nic = NIMF_NIM_IC (ic);
nimf_send_message (nic->connection->socket, nic->icid, NIMF_MESSAGE_COMMIT,
(gchar *) text, strlen (text) + 1, NULL);
nimf_result_iteration_until (nic->connection->result, NULL, nic->icid,
NIMF_MESSAGE_COMMIT_REPLY);
}
void nimf_nim_ic_emit_preedit_start (NimfServiceIC *ic)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfNimIC *nic = NIMF_NIM_IC (ic);
nimf_send_message (nic->connection->socket, nic->icid,
NIMF_MESSAGE_PREEDIT_START, NULL, 0, NULL);
nimf_result_iteration_until (nic->connection->result, NULL, nic->icid,
NIMF_MESSAGE_PREEDIT_START_REPLY);
}
void
nimf_nim_ic_emit_preedit_changed (NimfServiceIC *ic,
const gchar *preedit_string,
NimfPreeditAttr **attrs,
gint cursor_pos)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfNimIC *nic = NIMF_NIM_IC (ic);
gchar *data;
gsize data_len;
gint str_len = strlen (preedit_string);
gint n_attr = 0;
gint i;
while (attrs[n_attr] != NULL)
n_attr++;
data_len = str_len + 1 + n_attr * sizeof (NimfPreeditAttr) + sizeof (gint);
data = g_strndup (preedit_string, data_len - 1);
for (i = 0; attrs[i] != NULL; i++)
*(NimfPreeditAttr *)
(data + str_len + 1 + i * sizeof (NimfPreeditAttr)) = *attrs[i];
*(gint *) (data + data_len - sizeof (gint)) = cursor_pos;
nimf_send_message (nic->connection->socket, nic->icid,
NIMF_MESSAGE_PREEDIT_CHANGED, data, data_len, g_free);
nimf_result_iteration_until (nic->connection->result, NULL, nic->icid,
NIMF_MESSAGE_PREEDIT_CHANGED_REPLY);
}
void nimf_nim_ic_emit_preedit_end (NimfServiceIC *ic)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfNimIC *nic = NIMF_NIM_IC (ic);
nimf_send_message (nic->connection->socket, nic->icid,
NIMF_MESSAGE_PREEDIT_END, NULL, 0, NULL);
nimf_result_iteration_until (nic->connection->result, NULL, nic->icid,
NIMF_MESSAGE_PREEDIT_END_REPLY);
}
gboolean
nimf_nim_ic_emit_retrieve_surrounding (NimfServiceIC *ic)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfNimIC *nic = NIMF_NIM_IC (ic);
nimf_send_message (nic->connection->socket, nic->icid,
NIMF_MESSAGE_RETRIEVE_SURROUNDING, NULL, 0, NULL);
nimf_result_iteration_until (nic->connection->result, NULL, nic->icid,
NIMF_MESSAGE_RETRIEVE_SURROUNDING_REPLY);
if (nic->connection->result->reply == NULL)
return FALSE;
return *(gboolean *) (nic->connection->result->reply->data);
}
gboolean
nimf_nim_ic_emit_delete_surrounding (NimfServiceIC *ic,
gint offset,
gint n_chars)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfNimIC *nic = NIMF_NIM_IC (ic);
gint *data = g_malloc (2 * sizeof (gint));
data[0] = offset;
data[1] = n_chars;
nimf_send_message (nic->connection->socket, nic->icid,
NIMF_MESSAGE_DELETE_SURROUNDING,
data, 2 * sizeof (gint), g_free);
nimf_result_iteration_until (nic->connection->result, NULL, nic->icid,
NIMF_MESSAGE_DELETE_SURROUNDING_REPLY);
if (nic->connection->result->reply == NULL)
return FALSE;
return *(gboolean *) (nic->connection->result->reply->data);
}
void nimf_nim_ic_emit_beep (NimfServiceIC *ic)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfNimIC *nic = NIMF_NIM_IC (ic);
nimf_send_message (nic->connection->socket, nic->icid,
NIMF_MESSAGE_BEEP, NULL, 0, NULL);
nimf_result_iteration_until (nic->connection->result, NULL, nic->icid,
NIMF_MESSAGE_BEEP_REPLY);
}
const gchar *
nimf_nim_ic_get_service_id (NimfServiceIC *ic)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfService *service = NIMF_SERVICE (NIMF_NIM_IC (ic)->connection->nim);
return nimf_service_get_id (service);
}
NimfNimIC *
nimf_nim_ic_new (guint16 icid,
NimfConnection *connection)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfNimIC *nic = g_object_new (NIMF_TYPE_NIM_IC, NULL);
nic->connection = connection;
nic->icid = icid;
return nic;
}
static void
nimf_nim_ic_init (NimfNimIC *nic)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
}
static void
nimf_nim_ic_finalize (GObject *object)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
G_OBJECT_CLASS (nimf_nim_ic_parent_class)->finalize (object);
}
static void
nimf_nim_ic_class_init (NimfNimICClass *class)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
GObjectClass *object_class = G_OBJECT_CLASS (class);
NimfServiceICClass *service_im_class = NIMF_SERVICE_IC_CLASS (class);
object_class->finalize = nimf_nim_ic_finalize;
service_im_class->emit_commit = nimf_nim_ic_emit_commit;
service_im_class->emit_preedit_start = nimf_nim_ic_emit_preedit_start;
service_im_class->emit_preedit_changed = nimf_nim_ic_emit_preedit_changed;
service_im_class->emit_preedit_end = nimf_nim_ic_emit_preedit_end;
service_im_class->emit_retrieve_surrounding = nimf_nim_ic_emit_retrieve_surrounding;
service_im_class->emit_delete_surrounding = nimf_nim_ic_emit_delete_surrounding;
service_im_class->emit_beep = nimf_nim_ic_emit_beep;
service_im_class->get_service_id = nimf_nim_ic_get_service_id;
}

View File

@@ -0,0 +1,58 @@
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
/*
* nimf-nim-ic.h
* This file is part of Nimf.
*
* Copyright (C) 2015-2019 Hodong Kim <cogniti@gmail.com>
*
* Nimf is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Nimf is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __NIMF_NIM_IC_H__
#define __NIMF_NIM_IC_H__
#include <glib-object.h>
#include "nimf-service-ic.h"
#include "nimf-connection.h"
G_BEGIN_DECLS
#define NIMF_TYPE_NIM_IC (nimf_nim_ic_get_type ())
#define NIMF_NIM_IC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NIMF_TYPE_NIM_IC, NimfNimIC))
#define NIMF_NIM_IC_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), NIMF_TYPE_NIM_IC, NimfNimICClass))
#define NIMF_IS_NIM_IC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NIMF_TYPE_NIM_IC))
#define NIMF_IS_NIM_IC_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), NIMF_TYPE_NIM_IC))
#define NIMF_NIM_IC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NIMF_TYPE_NIM_IC, NimfNimICClass))
typedef struct _NimfNimIC NimfNimIC;
typedef struct _NimfNimICClass NimfNimICClass;
struct _NimfNimICClass
{
NimfServiceICClass parent_class;
};
struct _NimfNimIC
{
NimfServiceIC parent_instance;
NimfConnection *connection;
guint16 icid;
};
GType nimf_nim_ic_get_type (void) G_GNUC_CONST;
NimfNimIC *nimf_nim_ic_new (guint16 icid, NimfConnection *connection);
G_END_DECLS
#endif /* __NIMF_NIM_IC_H__ */

View File

@@ -0,0 +1,380 @@
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
/*
* nimf-nim.c
* This file is part of Nimf.
*
* Copyright (C) 2015-2019 Hodong Kim <cogniti@gmail.com>
*
* Nimf is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Nimf is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; If not, see <http://www.gnu.org/licenses/>.
*/
#include "nimf-nim.h"
#include "nimf-nim-ic.h"
#include "nimf-message-private.h"
#include "nimf-connection.h"
#include <gio/gunixsocketaddress.h>
#include <glib.h>
#include <glib/gstdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "nimf-utils.h"
G_DEFINE_DYNAMIC_TYPE (NimfNim, nimf_nim, NIMF_TYPE_SERVICE);
static const gchar *
nimf_nim_get_id (NimfService *service)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
g_return_val_if_fail (NIMF_IS_SERVICE (service), NULL);
return NIMF_NIM (service)->id;
}
static gboolean
on_incoming (GSocket *socket,
GIOCondition condition,
NimfConnection *connection)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfMessage *message;
gboolean retval;
nimf_message_unref (connection->result->reply);
connection->result->is_dispatched = TRUE;
if (condition & (G_IO_HUP | G_IO_ERR))
{
g_debug (G_STRLOC ": condition & (G_IO_HUP | G_IO_ERR)");
g_socket_close (socket, NULL);
GHashTableIter iter;
gpointer ic;
g_hash_table_iter_init (&iter, connection->ics);
while (g_hash_table_iter_next (&iter, NULL, &ic))
nimf_service_ic_reset (ic);
connection->result->reply = NULL;
g_hash_table_remove (connection->nim->connections,
GUINT_TO_POINTER (nimf_connection_get_id (connection)));
return G_SOURCE_REMOVE;
}
message = nimf_recv_message (socket);
connection->result->reply = message;
if (G_UNLIKELY (message == NULL))
{
g_critical (G_STRLOC ": NULL message");
return G_SOURCE_CONTINUE;
}
NimfNimIC *nic;
guint16 icid = message->header->icid;
nic = g_hash_table_lookup (connection->ics, GUINT_TO_POINTER (icid));
switch (message->header->type)
{
case NIMF_MESSAGE_CREATE_CONTEXT:
nic = nimf_nim_ic_new (icid, connection);
g_hash_table_insert (connection->ics, GUINT_TO_POINTER (icid), nic);
nimf_send_message (socket, icid, NIMF_MESSAGE_CREATE_CONTEXT_REPLY,
NULL, 0, NULL);
break;
case NIMF_MESSAGE_DESTROY_CONTEXT:
g_hash_table_remove (connection->ics, GUINT_TO_POINTER (icid));
nimf_send_message (socket, icid, NIMF_MESSAGE_DESTROY_CONTEXT_REPLY,
NULL, 0, NULL);
break;
case NIMF_MESSAGE_FILTER_EVENT:
nimf_message_ref (message);
retval = nimf_service_ic_filter_event (NIMF_SERVICE_IC (nic), (NimfEvent *) message->data);
nimf_message_unref (message);
nimf_send_message (socket, icid, NIMF_MESSAGE_FILTER_EVENT_REPLY,
&retval, sizeof (gboolean), NULL);
break;
case NIMF_MESSAGE_RESET:
nimf_service_ic_reset (NIMF_SERVICE_IC (nic));
nimf_send_message (socket, icid, NIMF_MESSAGE_RESET_REPLY,
NULL, 0, NULL);
break;
case NIMF_MESSAGE_FOCUS_IN:
nimf_service_ic_focus_in (NIMF_SERVICE_IC (nic));
nimf_send_message (socket, icid, NIMF_MESSAGE_FOCUS_IN_REPLY,
NULL, 0, NULL);
connection->nim->last_focused_conn_id = connection->id;
connection->nim->last_focused_icid = icid;
break;
case NIMF_MESSAGE_FOCUS_OUT:
nimf_service_ic_focus_out (NIMF_SERVICE_IC (nic));
nimf_send_message (socket, icid, NIMF_MESSAGE_FOCUS_OUT_REPLY,
NULL, 0, NULL);
break;
case NIMF_MESSAGE_SET_SURROUNDING:
{
nimf_message_ref (message);
gchar *data = message->data;
guint16 data_len = message->header->data_len;
gint str_len = data_len - 1 - 2 * sizeof (gint);
gint cursor_index = *(gint *) (data + data_len - sizeof (gint));
nimf_service_ic_set_surrounding (NIMF_SERVICE_IC (nic), data, str_len, cursor_index);
nimf_message_unref (message);
nimf_send_message (socket, icid,
NIMF_MESSAGE_SET_SURROUNDING_REPLY, NULL, 0, NULL);
}
break;
case NIMF_MESSAGE_SET_CURSOR_LOCATION:
nimf_message_ref (message);
nimf_service_ic_set_cursor_location (NIMF_SERVICE_IC (nic), (NimfRectangle *) message->data);
nimf_message_unref (message);
nimf_send_message (socket, icid, NIMF_MESSAGE_SET_CURSOR_LOCATION_REPLY,
NULL, 0, NULL);
break;
case NIMF_MESSAGE_SET_USE_PREEDIT:
nimf_message_ref (message);
nimf_service_ic_set_use_preedit (NIMF_SERVICE_IC (nic), *(gboolean *) message->data);
nimf_message_unref (message);
nimf_send_message (socket, icid, NIMF_MESSAGE_SET_USE_PREEDIT_REPLY,
NULL, 0, NULL);
break;
case NIMF_MESSAGE_PREEDIT_START_REPLY:
case NIMF_MESSAGE_PREEDIT_CHANGED_REPLY:
case NIMF_MESSAGE_PREEDIT_END_REPLY:
case NIMF_MESSAGE_COMMIT_REPLY:
case NIMF_MESSAGE_RETRIEVE_SURROUNDING_REPLY:
case NIMF_MESSAGE_DELETE_SURROUNDING_REPLY:
case NIMF_MESSAGE_BEEP_REPLY:
break;
default:
g_warning ("Unknown message type: %d", message->header->type);
break;
}
return G_SOURCE_CONTINUE;
}
static guint16
nimf_nim_add_connection (NimfNim *nim,
NimfConnection *connection)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
guint16 id;
do
id = nim->next_id++;
while (id == 0 || g_hash_table_contains (nim->connections,
GUINT_TO_POINTER (id)));
connection->id = id;
connection->nim = nim;
g_hash_table_insert (nim->connections, GUINT_TO_POINTER (id), connection);
return id;
}
static gboolean
on_new_connection (GSocketService *service,
GSocketConnection *socket_connection,
GObject *source_object,
NimfNim *nim)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfConnection *connection;
connection = nimf_connection_new ();
connection->socket = g_socket_connection_get_socket (socket_connection);
nimf_nim_add_connection (nim, connection);
connection->source = g_socket_create_source (connection->socket, G_IO_IN, NULL);
connection->socket_connection = g_object_ref (socket_connection);
g_source_set_can_recurse (connection->source, TRUE);
g_source_set_callback (connection->source,
(GSourceFunc) on_incoming,
connection, NULL);
g_source_attach (connection->source, NULL);
return TRUE;
}
static void nimf_nim_change_engine (NimfService *service,
const gchar *engine_id,
const gchar *method_id)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfNim *nim = NIMF_NIM (service);
if (nim->last_focused_conn_id > 0)
{
NimfConnection *connection;
connection = g_hash_table_lookup (nim->connections,
GUINT_TO_POINTER (nim->last_focused_conn_id));
if (connection)
nimf_connection_change_engine (connection, engine_id, method_id);
}
}
static void nimf_nim_change_engine_by_id (NimfService *service,
const gchar *engine_id)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfNim *nim = NIMF_NIM (service);
if (nim->last_focused_conn_id > 0)
{
NimfConnection *connection;
connection = g_hash_table_lookup (nim->connections,
GUINT_TO_POINTER (nim->last_focused_conn_id));
if (connection)
nimf_connection_change_engine_by_id (connection, engine_id);
}
}
static gboolean nimf_nim_is_active (NimfService *service)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
return NIMF_NIM (service)->active;
}
static gboolean
nimf_nim_start (NimfService *service)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfNim *nim = NIMF_NIM (service);
if (nim->active)
return TRUE;
GSocketAddress *address;
gchar *path;
GError *error = NULL;
nim->service = g_socket_service_new ();
path = nimf_get_socket_path ();
address = g_unix_socket_address_new_with_type (path, -1,
G_UNIX_SOCKET_ADDRESS_PATH);
g_socket_listener_add_address (G_SOCKET_LISTENER (nim->service), address,
G_SOCKET_TYPE_STREAM,
G_SOCKET_PROTOCOL_DEFAULT,
NULL, NULL, &error);
g_object_unref (address);
g_chmod (path, 0600);
g_free (path);
if (error)
{
g_critical (G_STRLOC ": %s: %s", G_STRFUNC, error->message);
g_clear_error (&error);
return FALSE;
}
g_signal_connect (nim->service, "incoming",
G_CALLBACK (on_new_connection), nim);
g_socket_service_start (nim->service);
return nim->active = TRUE;
}
static void nimf_nim_stop (NimfService *service)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfNim *nim = NIMF_NIM (service);
if (!nim->active)
return;
g_socket_service_stop (nim->service);
nim->active = FALSE;
}
static void
nimf_nim_init (NimfNim *nim)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
nim->id = g_strdup ("nimf-nim");
nim->connections = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
(GDestroyNotify) g_object_unref);
}
static void nimf_nim_finalize (GObject *object)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfService *service = NIMF_SERVICE (object);
NimfNim *nim = NIMF_NIM (object);
if (nimf_nim_is_active (service))
nimf_nim_stop (service);
if (nim->service != NULL)
g_object_unref (nim->service);
g_hash_table_unref (nim->connections);
g_free (nim->id);
G_OBJECT_CLASS (nimf_nim_parent_class)->finalize (object);
}
static void
nimf_nim_class_init (NimfNimClass *class)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
GObjectClass *object_class = G_OBJECT_CLASS (class);
NimfServiceClass *service_class = NIMF_SERVICE_CLASS (class);
service_class->get_id = nimf_nim_get_id;
service_class->start = nimf_nim_start;
service_class->stop = nimf_nim_stop;
service_class->is_active = nimf_nim_is_active;
service_class->change_engine = nimf_nim_change_engine;
service_class->change_engine_by_id = nimf_nim_change_engine_by_id;
object_class->finalize = nimf_nim_finalize;
}
static void
nimf_nim_class_finalize (NimfNimClass *class)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
}
void module_register_type (GTypeModule *type_module)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
nimf_nim_register_type (type_module);
}
GType module_get_type ()
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
return nimf_nim_get_type ();
}

View File

@@ -0,0 +1,63 @@
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
/*
* nimf-nim.h
* This file is part of Nimf.
*
* Copyright (C) 2015-2019 Hodong Kim <cogniti@gmail.com>
*
* Nimf is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Nimf is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __NIMF_NIM_H__
#define __NIMF_NIM_H__
#include "config.h"
#include <nimf.h>
#include <glib/gi18n.h>
G_BEGIN_DECLS
#define NIMF_TYPE_NIM (nimf_nim_get_type ())
#define NIMF_NIM(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), NIMF_TYPE_NIM, NimfNim))
#define NIMF_NIM_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), NIMF_TYPE_NIM, NimfNimClass))
#define NIMF_IS_NIM(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), NIMF_TYPE_NIM))
#define NIMF_IS_NIM_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), NIMF_TYPE_NIM))
#define NIMF_NIM_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS ((object), NIMF_TYPE_NIM, NimfNimClass))
typedef struct _NimfNim NimfNim;
typedef struct _NimfNimClass NimfNimClass;
struct _NimfNim
{
NimfService parent_instance;
gchar *id;
gboolean active;
GHashTable *connections;
guint16 next_id;
guint16 last_focused_conn_id;
guint16 last_focused_icid;
GSocketService *service;
};
struct _NimfNimClass
{
NimfServiceClass parent_class;
};
GType nimf_nim_get_type (void) G_GNUC_CONST;
G_END_DECLS
#endif /* __NIMF_NIM_H__ */

View File

@@ -0,0 +1,25 @@
moduledir = $(libdir)/nimf/modules/services
module_LTLIBRARIES = libnimf-preedit-window.la
libnimf_preedit_window_la_SOURCES = \
nimf-preedit-window.c \
$(NULL)
libnimf_preedit_window_la_CFLAGS = \
$(EXTRA_CFLAGS) \
-I$(top_srcdir)/libnimf \
-DG_LOG_DOMAIN=\"nimf\" \
$(NIMF_PREEDIT_WINDOW_DEPS_CFLAGS)
libnimf_preedit_window_la_LDFLAGS = -avoid-version -module $(NIMF_PREEDIT_WINDOW_DEPS_LIBS)
libnimf_preedit_window_la_LIBADD = $(top_builddir)/libnimf/libnimf.la
DISTCLEANFILES = Makefile.in
install-data-hook:
chmod -x $(DESTDIR)$(moduledir)/libnimf-preedit-window.so
rm -f $(DESTDIR)$(moduledir)/libnimf-preedit-window.la
uninstall-hook:
rm -f $(DESTDIR)$(moduledir)/libnimf-preedit-window.so
-rmdir -p $(DESTDIR)$(moduledir)

View File

@@ -0,0 +1,293 @@
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
/*
* nimf-preedit-window.c
* This file is part of Nimf.
*
* Copyright (C) 2017-2019 Hodong Kim <cogniti@gmail.com>
*
* Nimf is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Nimf is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include "nimf.h"
#define NIMF_TYPE_PREEDIT_WINDOW (nimf_preedit_window_get_type ())
#define NIMF_PREEDIT_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NIMF_TYPE_PREEDIT_WINDOW, NimfPreeditWindow))
#define NIMF_PREEDIT_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NIMF_TYPE_PREEDIT_WINDOW, NimfPreeditWindowClass))
#define NIMF_IS_PREEDIT_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NIMF_TYPE_PREEDIT_WINDOW))
#define NIMF_IS_PREEDIT_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NIMF_TYPE_PREEDIT_WINDOW))
#define NIMF_PREEDIT_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NIMF_TYPE_PREEDIT_WINDOW, NimfPreeditWindowClass))
typedef struct _NimfPreeditWindow NimfPreeditWindow;
typedef struct _NimfPreeditWindowClass NimfPreeditWindowClass;
struct _NimfPreeditWindowClass
{
NimfServiceClass parent_class;
};
struct _NimfPreeditWindow
{
NimfService parent_instance;
gchar *id;
gboolean active;
GtkWidget *window;
GtkWidget *entry;
NimfRectangle cursor_area;
};
GType nimf_preedit_window_get_type (void) G_GNUC_CONST;
static void nimf_preedit_window_show (NimfPreeditable *preeditable)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfPreeditWindow *preedit_window = NIMF_PREEDIT_WINDOW (preeditable);
GtkRequisition natural_size;
int x, y, w, h;
int screen_width, screen_height;
#if GTK_CHECK_VERSION (3, 22, 0)
GdkRectangle geometry;
GdkDisplay *display = gtk_widget_get_display (preedit_window->window);
GdkWindow *window = gtk_widget_get_window (preedit_window->window);
GdkMonitor *monitor = gdk_display_get_monitor_at_window (display, window);
gdk_monitor_get_geometry (monitor, &geometry);
screen_width = geometry.width;
screen_height = geometry.height;
#else
screen_width = gdk_screen_width ();
screen_height = gdk_screen_height ();
#endif
gtk_widget_show_all (preedit_window->window);
gtk_widget_get_preferred_size (preedit_window->window, NULL, &natural_size);
gtk_window_resize (GTK_WINDOW (preedit_window->window),
natural_size.width, natural_size.height);
gtk_window_get_size (GTK_WINDOW (preedit_window->window), &w, &h);
x = preedit_window->cursor_area.x - preedit_window->cursor_area.width;
y = preedit_window->cursor_area.y + preedit_window->cursor_area.height;
if (x + w > screen_width)
x = screen_width - w;
if (y + h > screen_height)
y = preedit_window->cursor_area.y - h;
gtk_window_move (GTK_WINDOW (preedit_window->window), x, y);
}
static void nimf_preedit_window_hide (NimfPreeditable *preeditable)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
gtk_widget_hide (NIMF_PREEDIT_WINDOW (preeditable)->window);
}
static gboolean nimf_preedit_window_is_visible (NimfPreeditable *preeditable)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
return gtk_widget_is_visible (NIMF_PREEDIT_WINDOW (preeditable)->window);
}
static void nimf_preedit_window_set_text (NimfPreeditable *preeditable,
const gchar *text,
gint cursor_pos)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
GtkEntry *entry = GTK_ENTRY (NIMF_PREEDIT_WINDOW (preeditable)->entry);
gtk_entry_set_text (entry, text);
gtk_editable_set_position (GTK_EDITABLE (entry), cursor_pos);
gtk_entry_set_width_chars (entry, g_utf8_strlen (text, -1) * 2);
}
static void
nimf_preedit_window_set_cursor_location (NimfPreeditable *preeditable,
const NimfRectangle *area)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfPreeditWindow *preedit_window = NIMF_PREEDIT_WINDOW (preeditable);
preedit_window->cursor_area = *area;
}
static void
nimf_preedit_window_iface_init (NimfPreeditableInterface *iface)
{
iface->show = nimf_preedit_window_show;
iface->hide = nimf_preedit_window_hide;
iface->is_visible = nimf_preedit_window_is_visible;
iface->set_text = nimf_preedit_window_set_text;
iface->set_cursor_location = nimf_preedit_window_set_cursor_location;
}
G_DEFINE_DYNAMIC_TYPE_EXTENDED (NimfPreeditWindow,
nimf_preedit_window,
NIMF_TYPE_SERVICE,
0,
G_IMPLEMENT_INTERFACE_DYNAMIC (NIMF_TYPE_PREEDITABLE,
nimf_preedit_window_iface_init));
const gchar *
nimf_preedit_window_get_id (NimfService *service)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
g_return_val_if_fail (NIMF_IS_SERVICE (service), NULL);
return NIMF_PREEDIT_WINDOW (service)->id;
}
static gboolean nimf_preedit_window_is_active (NimfService *service)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
return NIMF_PREEDIT_WINDOW (service)->active;
}
static gboolean
on_entry_draw (GtkWidget *widget,
cairo_t *cr,
gpointer user_data)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
GtkStyleContext *style_context;
PangoContext *pango_context;
PangoLayout *layout;
const char *text;
gint cursor_index;
gint x, y;
style_context = gtk_widget_get_style_context (widget);
pango_context = gtk_widget_get_pango_context (widget);
layout = gtk_entry_get_layout (GTK_ENTRY (widget));
text = pango_layout_get_text (layout);
gtk_entry_get_layout_offsets (GTK_ENTRY (widget), &x, &y);
cursor_index = g_utf8_offset_to_pointer (text, gtk_editable_get_position (GTK_EDITABLE (widget))) - text;
gtk_render_insertion_cursor (style_context, cr, x, y, layout, cursor_index,
pango_context_get_base_dir (pango_context));
return FALSE;
}
static gboolean nimf_preedit_window_start (NimfService *service)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfPreeditWindow *preedit_window = NIMF_PREEDIT_WINDOW (service);
if (preedit_window->active)
return TRUE;
if (!gtk_init_check (NULL, NULL))
return FALSE;
preedit_window->entry = gtk_entry_new ();
gtk_editable_set_editable (GTK_EDITABLE (preedit_window->entry), FALSE);
g_signal_connect_after (preedit_window->entry, "draw",
G_CALLBACK (on_entry_draw), NULL);
/* gtk window */
preedit_window->window = gtk_window_new (GTK_WINDOW_POPUP);
gtk_window_set_type_hint (GTK_WINDOW (preedit_window->window),
GDK_WINDOW_TYPE_HINT_POPUP_MENU);
gtk_container_set_border_width (GTK_CONTAINER (preedit_window->window), 1);
gtk_container_add (GTK_CONTAINER (preedit_window->window),
preedit_window->entry);
gtk_widget_realize (preedit_window->window);
gtk_window_move (GTK_WINDOW (preedit_window->window), 0, 0);
preedit_window->active = TRUE;
return TRUE;
}
static void nimf_preedit_window_stop (NimfService *service)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfPreeditWindow *preedit_window = NIMF_PREEDIT_WINDOW (service);
if (!preedit_window->active)
return;
preedit_window->active = FALSE;
}
static void
nimf_preedit_window_init (NimfPreeditWindow *preedit_window)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
preedit_window->id = g_strdup ("nimf-preedit-window");
}
static void
nimf_preedit_window_finalize (GObject *object)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfPreeditWindow *preedit_window = NIMF_PREEDIT_WINDOW (object);
if (preedit_window->active)
nimf_preedit_window_stop (NIMF_SERVICE (preedit_window));
gtk_widget_destroy (preedit_window->window);
g_free (preedit_window->id);
G_OBJECT_CLASS (nimf_preedit_window_parent_class)->finalize (object);
}
static void
nimf_preedit_window_class_init (NimfPreeditWindowClass *class)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
GObjectClass *object_class = G_OBJECT_CLASS (class);
NimfServiceClass *service_class = NIMF_SERVICE_CLASS (class);
service_class->get_id = nimf_preedit_window_get_id;
service_class->start = nimf_preedit_window_start;
service_class->stop = nimf_preedit_window_stop;
service_class->is_active = nimf_preedit_window_is_active;
object_class->finalize = nimf_preedit_window_finalize;
}
static void
nimf_preedit_window_class_finalize (NimfPreeditWindowClass *class)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
}
void module_register_type (GTypeModule *type_module)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
nimf_preedit_window_register_type (type_module);
}
GType module_get_type ()
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
return nimf_preedit_window_get_type ();
}

View File

@@ -0,0 +1,45 @@
moduledir = $(libdir)/nimf/modules/services
module_LTLIBRARIES = libnimf-wayland.la
WAYLAND_IM_XML_PATH = `pkg-config --variable=pkgdatadir wayland-protocols`/unstable/input-method/input-method-unstable-v1.xml
BUILT_SOURCES = \
input-method-unstable-v1-client-protocol.h \
input-method-unstable-v1-protocol.c \
$(NULL)
libnimf_wayland_la_SOURCES = \
nimf-wayland.c \
nimf-wayland-ic.c \
nimf-wayland-ic.h \
$(BUILT_SOURCES) \
$(NULL)
libnimf_wayland_la_CFLAGS = \
$(EXTRA_CFLAGS) \
-I$(top_srcdir)/libnimf \
-DG_LOG_DOMAIN=\"nimf\" \
$(NIMF_WAYLAND_DEPS_CFLAGS)
libnimf_wayland_la_LDFLAGS = -avoid-version -module $(NIMF_WAYLAND_DEPS_LIBS)
libnimf_wayland_la_LIBADD = $(top_builddir)/libnimf/libnimf.la
input-method-unstable-v1-client-protocol.h:
$(AM_V_GEN) wayland-scanner client-header < $(WAYLAND_IM_XML_PATH) \
> input-method-unstable-v1-client-protocol.h
input-method-unstable-v1-protocol.c:
$(AM_V_GEN) wayland-scanner code < $(WAYLAND_IM_XML_PATH) \
> input-method-unstable-v1-protocol.c
install-data-hook:
chmod -x $(DESTDIR)$(moduledir)/libnimf-wayland.so
rm -f $(DESTDIR)$(moduledir)/libnimf-wayland.la
uninstall-hook:
rm -f $(DESTDIR)$(moduledir)/libnimf-wayland.so
-rmdir -p $(DESTDIR)$(moduledir)
CLEANFILES = $(BUILT_SOURCES)
DISTCLEANFILES = Makefile.in

View File

@@ -0,0 +1,105 @@
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
/*
* nimf-wayland-ic.c
* This file is part of Nimf.
*
* Copyright (C) 2017-2019 Hodong Kim <cogniti@gmail.com>
*
* Nimf is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Nimf is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; If not, see <http://www.gnu.org/licenses/>.
*/
#include "nimf-wayland-ic.h"
#include "input-method-unstable-v1-client-protocol.h"
G_DEFINE_TYPE (NimfWaylandIC, nimf_wayland_ic, NIMF_TYPE_SERVICE_IC);
NimfWaylandIC *nimf_wayland_ic_new (NimfWayland *wayland)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfWaylandIC *wic;
wic = g_object_new (NIMF_TYPE_WAYLAND_IC, NULL);
wic->wayland = wayland;
return wic;
}
void
nimf_wayland_ic_emit_commit (NimfServiceIC *ic,
const gchar *text)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfWayland *wayland = NIMF_WAYLAND_IC (ic)->wayland;
zwp_input_method_context_v1_commit_string (wayland->context,
wayland->serial,
text);
}
void nimf_wayland_ic_emit_preedit_start (NimfServiceIC *ic)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
}
void
nimf_wayland_ic_emit_preedit_changed (NimfServiceIC *ic,
const gchar *preedit_string,
NimfPreeditAttr **attrs,
gint cursor_pos)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfWayland *wayland = NIMF_WAYLAND_IC (ic)->wayland;
zwp_input_method_context_v1_preedit_cursor (wayland->context, cursor_pos);
zwp_input_method_context_v1_preedit_string (wayland->context,
wayland->serial, preedit_string, preedit_string);
}
void nimf_wayland_ic_emit_preedit_end (NimfServiceIC *ic)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
}
static void
nimf_wayland_ic_init (NimfWaylandIC *wic)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
}
static void
nimf_wayland_ic_finalize (GObject *object)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
G_OBJECT_CLASS (nimf_wayland_ic_parent_class)->finalize (object);
}
static void
nimf_wayland_ic_class_init (NimfWaylandICClass *class)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
GObjectClass *object_class = G_OBJECT_CLASS (class);
NimfServiceICClass *service_im_class = NIMF_SERVICE_IC_CLASS (class);
object_class->finalize = nimf_wayland_ic_finalize;
service_im_class->emit_commit = nimf_wayland_ic_emit_commit;
service_im_class->emit_preedit_start = nimf_wayland_ic_emit_preedit_start;
service_im_class->emit_preedit_changed = nimf_wayland_ic_emit_preedit_changed;
service_im_class->emit_preedit_end = nimf_wayland_ic_emit_preedit_end;
}

View File

@@ -0,0 +1,59 @@
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
/*
* nimf-wayland-ic.h
* This file is part of Nimf.
*
* Copyright (C) 2017-2019 Hodong Kim <cogniti@gmail.com>
*
* Nimf is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Nimf is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __NIMF_WAYLAND_IC_H__
#define __NIMF_WAYLAND_IC_H__
#include "nimf.h"
#include "nimf-wayland.h"
G_BEGIN_DECLS
#define NIMF_TYPE_WAYLAND_IC (nimf_wayland_ic_get_type ())
#define NIMF_WAYLAND_IC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NIMF_TYPE_WAYLAND_IC, NimfWaylandIC))
#define NIMF_WAYLAND_IC_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), NIMF_TYPE_WAYLAND_IC, NimfWaylandICClass))
#define NIMF_IS_WAYLAND_IC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NIMF_TYPE_WAYLAND_IC))
#define NIMF_IS_WAYLAND_IC_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), NIMF_TYPE_WAYLAND_IC))
#define NIMF_WAYLAND_IC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NIMF_TYPE_WAYLAND_IC, NimfWaylandICClass))
typedef struct _NimfWayland NimfWayland;
typedef struct _NimfWaylandIC NimfWaylandIC;
typedef struct _NimfWaylandICClass NimfWaylandICClass;
struct _NimfWaylandICClass
{
NimfServiceICClass parent_class;
};
struct _NimfWaylandIC
{
NimfServiceIC parent_instance;
NimfWayland *wayland;
};
GType nimf_wayland_ic_get_type (void) G_GNUC_CONST;
NimfWaylandIC *nimf_wayland_ic_new (NimfWayland *wayland);
G_END_DECLS
#endif /* __NIMF_WAYLAND_IC_H__ */

View File

@@ -0,0 +1,621 @@
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
/*
* nimf-wayland.c
* This file is part of Nimf.
*
* Copyright (C) 2012 Intel Corporation
* Copyright (C) 2017-2019 Hodong Kim <cogniti@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "config.h"
#include "nimf-wayland-ic.h"
#include "nimf-wayland.h"
#include "nimf-service.h"
G_DEFINE_DYNAMIC_TYPE (NimfWayland, nimf_wayland, NIMF_TYPE_SERVICE);
typedef struct
{
GSource source;
NimfWayland *wayland;
GPollFD poll_fd;
gboolean reading;
} NimfWaylandEventSource;
static gboolean nimf_wayland_source_prepare (GSource *base,
gint *timeout)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfWaylandEventSource *source = (NimfWaylandEventSource *) base;
*timeout = -1;
if (source->reading)
return FALSE;
if (wl_display_prepare_read (source->wayland->display) != 0)
return TRUE;
source->reading = TRUE;
if (wl_display_flush (source->wayland->display) < 0)
g_critical (G_STRLOC ": %s: wl_display_flush() failed: %s", G_STRFUNC,
g_strerror (errno));
return FALSE;
}
static void nimf_wayland_stop (NimfService *service)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfWayland *wayland = NIMF_WAYLAND (service);
if (!wayland->active)
return;
if (wayland->event_source)
{
g_source_destroy (wayland->event_source);
g_source_unref (wayland->event_source);
}
wayland->active = FALSE;
}
static gboolean nimf_wayland_source_check (GSource *base)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfWaylandEventSource *source = (NimfWaylandEventSource *) base;
if (source->reading)
{
if (source->poll_fd.revents & G_IO_IN)
{
if (wl_display_read_events (source->wayland->display) < 0)
{
g_critical (G_STRLOC ": %s: wl_display_read_events() failed: %s",
G_STRFUNC, g_strerror (errno));
nimf_wayland_stop (NIMF_SERVICE (source->wayland));
}
}
else
{
wl_display_cancel_read (source->wayland->display);
}
source->reading = FALSE;
}
return source->poll_fd.revents;
}
static gboolean nimf_wayland_source_dispatch (GSource *base,
GSourceFunc callback,
gpointer user_data)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfWaylandEventSource *source = (NimfWaylandEventSource *) base;
if (wl_display_dispatch_pending (source->wayland->display) < 0)
{
g_critical (G_STRLOC ": %s: wl_display_dispatch_pending() failed: %s: %m",
G_STRFUNC, g_strerror (errno));
nimf_wayland_stop (NIMF_SERVICE (source->wayland));
}
source->poll_fd.revents = 0;
return TRUE;
}
static void nimf_wayland_source_finalize (GSource *base)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfWaylandEventSource *source = (NimfWaylandEventSource *) base;
if (source->reading)
wl_display_cancel_read (source->wayland->display);
source->reading = FALSE;
}
static GSourceFuncs event_funcs = {
nimf_wayland_source_prepare,
nimf_wayland_source_check,
nimf_wayland_source_dispatch,
nimf_wayland_source_finalize
};
GSource *
nimf_wayland_source_new (NimfWayland *wayland)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
GSource *source;
NimfWaylandEventSource *wl_source;
source = g_source_new (&event_funcs, sizeof (NimfWaylandEventSource));
wl_source = (NimfWaylandEventSource *) source;
wl_source->wayland = wayland;
wl_source->poll_fd.fd = wl_display_get_fd (wl_source->wayland->display);
wl_source->poll_fd.events = G_IO_IN | G_IO_ERR | G_IO_HUP;
g_source_add_poll (source, &wl_source->poll_fd);
g_source_set_priority (source, G_PRIORITY_DEFAULT);
g_source_set_can_recurse (source, TRUE);
return source;
}
static void
handle_surrounding_text (void *data,
struct zwp_input_method_context_v1 *context,
const char *text,
uint32_t cursor,
uint32_t anchor)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
}
static void
handle_reset (void *data,
struct zwp_input_method_context_v1 *context)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
}
static void
handle_content_type (void *data,
struct zwp_input_method_context_v1 *context,
uint32_t hint,
uint32_t purpose)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
}
static void
handle_invoke_action (void *data,
struct zwp_input_method_context_v1 *context,
uint32_t button,
uint32_t index)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
}
static void
handle_commit_state (void *data,
struct zwp_input_method_context_v1 *context,
uint32_t serial)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfWayland *wayland = data;
wayland->serial = serial;
}
static void
handle_preferred_language (void *data,
struct zwp_input_method_context_v1 *context,
const char *language)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
}
static const struct zwp_input_method_context_v1_listener input_method_context_listener = {
handle_surrounding_text,
handle_reset,
handle_content_type,
handle_invoke_action,
handle_commit_state,
handle_preferred_language
};
static void
input_method_keyboard_keymap (void *data,
struct wl_keyboard *wl_keyboard,
uint32_t format,
int32_t fd,
uint32_t size)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfWayland *wayland = data;
char *map_str;
if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1)
{
close (fd);
return;
}
map_str = mmap (NULL, size, PROT_READ, MAP_SHARED, fd, 0);
if (map_str == MAP_FAILED)
{
close (fd);
return;
}
wayland->keymap = xkb_keymap_new_from_string (wayland->xkb_context,
map_str,
XKB_KEYMAP_FORMAT_TEXT_V1,
XKB_KEYMAP_COMPILE_NO_FLAGS);
munmap (map_str, size);
close (fd);
if (!wayland->keymap)
{
g_critical (G_STRLOC ": %s: xkb_keymap_new_from_string() failed",
G_STRFUNC);
return;
}
wayland->state = xkb_state_new (wayland->keymap);
if (!wayland->state)
{
g_critical (G_STRLOC ": %s: xkb_state_new() failed", G_STRFUNC);
xkb_keymap_unref(wayland->keymap);
return;
}
wayland->shift_mask =
1 << xkb_keymap_mod_get_index (wayland->keymap, "Shift");
wayland->lock_mask =
1 << xkb_keymap_mod_get_index (wayland->keymap, "Lock");
wayland->control_mask =
1 << xkb_keymap_mod_get_index (wayland->keymap, "Control");
wayland->mod1_mask =
1 << xkb_keymap_mod_get_index (wayland->keymap, "Mod1");
wayland->mod2_mask =
1 << xkb_keymap_mod_get_index (wayland->keymap, "Mod2");
wayland->mod3_mask =
1 << xkb_keymap_mod_get_index (wayland->keymap, "Mod3");
wayland->mod4_mask =
1 << xkb_keymap_mod_get_index (wayland->keymap, "Mod4");
wayland->mod5_mask =
1 << xkb_keymap_mod_get_index (wayland->keymap, "Mod5");
wayland->super_mask =
1 << xkb_keymap_mod_get_index (wayland->keymap, "Super");
wayland->hyper_mask =
1 << xkb_keymap_mod_get_index (wayland->keymap, "Hyper");
wayland->meta_mask =
1 << xkb_keymap_mod_get_index (wayland->keymap, "Meta");
}
static void
input_method_keyboard_key (void *data,
struct wl_keyboard *wl_keyboard,
uint32_t serial,
uint32_t time,
uint32_t key,
uint32_t state_w)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfWayland *wayland = data;
uint32_t code;
uint32_t num_syms;
const xkb_keysym_t *syms;
xkb_keysym_t sym;
enum wl_keyboard_key_state state = state_w;
guint32 modifiers;
NimfEvent *event;
if (!wayland->state)
return;
code = key + 8;
num_syms = xkb_state_key_get_syms (wayland->state, code, &syms);
sym = XKB_KEY_NoSymbol;
if (num_syms == 1)
sym = syms[0];
event = nimf_event_new (NIMF_EVENT_NOTHING);
modifiers = wayland->modifiers;
if (state == WL_KEYBOARD_KEY_STATE_RELEASED)
{
modifiers |= NIMF_RELEASE_MASK;
event->key.type = NIMF_EVENT_KEY_RELEASE;
}
else
{
event->key.type = NIMF_EVENT_KEY_PRESS;
}
event->key.state = modifiers;
event->key.keyval = sym;
event->key.hardware_keycode = code;
if (!nimf_service_ic_filter_event (NIMF_SERVICE_IC (wayland->wic), event))
zwp_input_method_context_v1_key (wayland->context, serial, time, key, state);
nimf_event_free (event);
}
static void
input_method_keyboard_modifiers (void *data,
struct wl_keyboard *wl_keyboard,
uint32_t serial,
uint32_t mods_depressed,
uint32_t mods_latched,
uint32_t mods_locked,
uint32_t group)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfWayland *wayland = data;
struct zwp_input_method_context_v1 *context = wayland->context;
xkb_mod_mask_t mask;
xkb_state_update_mask (wayland->state, mods_depressed,
mods_latched, mods_locked, 0, 0, group);
mask = xkb_state_serialize_mods (wayland->state,
XKB_STATE_MODS_DEPRESSED |
XKB_STATE_MODS_LATCHED);
wayland->modifiers = 0;
if (mask & wayland->shift_mask)
wayland->modifiers |= NIMF_SHIFT_MASK;
if (mask & wayland->lock_mask)
wayland->modifiers |= NIMF_LOCK_MASK;
if (mask & wayland->control_mask)
wayland->modifiers |= NIMF_CONTROL_MASK;
if (mask & wayland->mod1_mask)
wayland->modifiers |= NIMF_MOD1_MASK;
if (mask & wayland->mod2_mask)
wayland->modifiers |= NIMF_MOD2_MASK;
if (mask & wayland->mod3_mask)
wayland->modifiers |= NIMF_MOD3_MASK;
if (mask & wayland->mod4_mask)
wayland->modifiers |= NIMF_MOD4_MASK;
if (mask & wayland->mod5_mask)
wayland->modifiers |= NIMF_MOD5_MASK;
if (mask & wayland->super_mask)
wayland->modifiers |= NIMF_SUPER_MASK;
if (mask & wayland->hyper_mask)
wayland->modifiers |= NIMF_HYPER_MASK;
if (mask & wayland->meta_mask)
wayland->modifiers |= NIMF_META_MASK;
zwp_input_method_context_v1_modifiers (context, serial,
mods_depressed, mods_depressed,
mods_latched, group);
}
static const struct wl_keyboard_listener input_method_keyboard_listener = {
input_method_keyboard_keymap,
NULL, /* enter */
NULL, /* leave */
input_method_keyboard_key,
input_method_keyboard_modifiers
};
static void
input_method_activate (void *data,
struct zwp_input_method_v1 *input_method,
struct zwp_input_method_context_v1 *context)
{
g_debug (G_STRLOC ": %s: %p, %p", G_STRFUNC, input_method, context);
NimfWayland *wayland = data;
if (wayland->context)
zwp_input_method_context_v1_destroy (wayland->context);
wayland->serial = 0;
wayland->context = context;
zwp_input_method_context_v1_add_listener (context,
&input_method_context_listener,
wayland);
wayland->keyboard = zwp_input_method_context_v1_grab_keyboard (context);
wl_keyboard_add_listener (wayland->keyboard,
&input_method_keyboard_listener,
wayland);
}
static void
input_method_deactivate (void *data,
struct zwp_input_method_v1 *input_method,
struct zwp_input_method_context_v1 *context)
{
g_debug (G_STRLOC ": %s: %p, %p", G_STRFUNC, input_method, context);
NimfWayland *wayland = data;
if (!wayland->context)
return;
nimf_service_ic_reset (NIMF_SERVICE_IC (wayland->wic));
zwp_input_method_context_v1_destroy (wayland->context);
wayland->context = NULL;
}
static const struct zwp_input_method_v1_listener input_method_listener = {
input_method_activate,
input_method_deactivate
};
static void
registry_handle_global (void *data,
struct wl_registry *registry,
uint32_t name,
const char *interface,
uint32_t version)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfWayland *wayland = data;
if (!g_strcmp0 (interface, "zwp_input_method_v1"))
{
wayland->input_method =
wl_registry_bind (registry, name, &zwp_input_method_v1_interface, 1);
zwp_input_method_v1_add_listener (wayland->input_method,
&input_method_listener, wayland);
}
}
static void
registry_handle_global_remove (void *data, struct wl_registry *registry,
uint32_t name)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
}
static const struct wl_registry_listener registry_listener = {
registry_handle_global,
registry_handle_global_remove
};
static gboolean nimf_wayland_is_active (NimfService *service)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
return NIMF_WAYLAND (service)->active;
}
static gboolean nimf_wayland_start (NimfService *service)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfWayland *wayland = NIMF_WAYLAND (service);
const gchar *type;
if (wayland->active)
return TRUE;
type = g_getenv ("XDG_SESSION_TYPE");
if (type && g_strcmp0 (type, "wayland"))
return FALSE;
wayland->display = wl_display_connect (NULL);
if (wayland->display == NULL)
{
g_warning (G_STRLOC ": %s: wl_display_connect() failed", G_STRFUNC);
return FALSE;
}
wayland->registry = wl_display_get_registry (wayland->display);
wl_registry_add_listener (wayland->registry, &registry_listener, wayland);
wl_display_roundtrip (wayland->display);
if (wayland->input_method == NULL)
{
g_critical (G_STRLOC ": %s: No input_method global", G_STRFUNC);
return FALSE;
}
wayland->xkb_context = xkb_context_new (XKB_CONTEXT_NO_FLAGS);
if (wayland->xkb_context == NULL) {
g_critical (G_STRLOC ": %s: xkb_context_new() failed", G_STRFUNC);
return FALSE;
}
wayland->wic = nimf_wayland_ic_new (wayland);
wayland->context = NULL;
wayland->event_source = nimf_wayland_source_new (wayland);
g_source_attach (wayland->event_source, NULL);
wayland->active = TRUE;
return TRUE;
}
static const gchar *
nimf_wayland_get_id (NimfService *service)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
g_return_val_if_fail (NIMF_IS_SERVICE (service), NULL);
return NIMF_WAYLAND (service)->id;
}
static void
nimf_wayland_init (NimfWayland *wayland)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
wayland->id = g_strdup ("nimf-wayland");
}
static void
nimf_wayland_finalize (GObject *object)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfWayland *wayland = NIMF_WAYLAND (object);
if (wayland->active)
nimf_wayland_stop (NIMF_SERVICE (wayland));
g_free (wayland->id);
if (wayland->wic)
g_object_unref (wayland->wic);
G_OBJECT_CLASS (nimf_wayland_parent_class)->finalize (object);
}
static void
nimf_wayland_class_init (NimfWaylandClass *class)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
GObjectClass *object_class = G_OBJECT_CLASS (class);
NimfServiceClass *service_class = NIMF_SERVICE_CLASS (class);
service_class->get_id = nimf_wayland_get_id;
service_class->start = nimf_wayland_start;
service_class->stop = nimf_wayland_stop;
service_class->is_active = nimf_wayland_is_active;
object_class->finalize = nimf_wayland_finalize;
}
static void
nimf_wayland_class_finalize (NimfWaylandClass *class)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
}
void module_register_type (GTypeModule *type_module)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
nimf_wayland_register_type (type_module);
}
GType module_get_type ()
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
return nimf_wayland_get_type ();
}

View File

@@ -0,0 +1,96 @@
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
/*
* nimf-wayland.h
* This file is part of Nimf.
*
* Copyright (C) 2012 Intel Corporation
* Copyright (C) 2017 Hodong Kim <cogniti@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef __NIMF_WAYLAND_H__
#define __NIMF_WAYLAND_H__
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <errno.h>
#include <wayland-client.h>
#include <wayland-server.h>
#include <xkbcommon/xkbcommon.h>
#include "input-method-unstable-v1-client-protocol.h"
#define NIMF_TYPE_WAYLAND (nimf_wayland_get_type ())
#define NIMF_WAYLAND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NIMF_TYPE_WAYLAND, NimfWayland))
#define NIMF_WAYLAND_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), NIMF_TYPE_WAYLAND, NimfWaylandClass))
#define NIMF_IS_WAYLAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NIMF_TYPE_WAYLAND))
#define NIMF_IS_WAYLAND_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), NIMF_TYPE_WAYLAND))
#define NIMF_WAYLAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NIMF_TYPE_WAYLAND, NimfWaylandClass))
typedef struct _NimfWaylandIC NimfWaylandIC;
typedef struct _NimfWayland NimfWayland;
typedef struct _NimfWaylandClass NimfWaylandClass;
struct _NimfWaylandClass
{
NimfServiceClass parent_class;
};
struct _NimfWayland
{
NimfService parent_instance;
GSource *event_source;
gchar *id;
gboolean active;
NimfWaylandIC *wic;
struct zwp_input_method_v1 *input_method;
struct zwp_input_method_context_v1 *context;
struct wl_display *display;
struct wl_registry *registry;
struct wl_keyboard *keyboard;
struct xkb_context *xkb_context;
NimfModifierType modifiers;
struct xkb_keymap *keymap;
struct xkb_state *state;
xkb_mod_mask_t shift_mask;
xkb_mod_mask_t lock_mask;
xkb_mod_mask_t control_mask;
xkb_mod_mask_t mod1_mask;
xkb_mod_mask_t mod2_mask;
xkb_mod_mask_t mod3_mask;
xkb_mod_mask_t mod4_mask;
xkb_mod_mask_t mod5_mask;
xkb_mod_mask_t super_mask;
xkb_mod_mask_t hyper_mask;
xkb_mod_mask_t meta_mask;
uint32_t serial;
};
GType nimf_wayland_get_type (void) G_GNUC_CONST;
#endif /* __NIMF_WAYLAND_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,131 @@
/******************************************************************
Copyright 1993, 1994 by Digital Equipment Corporation, Maynard, Massachusetts,
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the names of Digital or MIT not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
Author: Hiroyuki Miyamoto Digital Equipment Corporation
miyamoto@jrd.dec.com
This version tidied and debugged by Steve Underwood May 1999
******************************************************************/
#ifndef FRAMEMGR_H
#define FRAMEMGR_H
#include <X11/Xmd.h>
#include <X11/Xlib.h>
#include <stdio.h>
#if defined(VAXC) && !defined(__DECC)
#define xim_externalref globalref
#define xim_externaldef globaldef
#else
#define xim_externalref extern
#define xim_externaldef
#endif
/* Definitions for FrameMgr */
#define COUNTER_MASK 0x10
typedef enum
{
BIT8 = 0x1, /* {CARD8* | INT8*} */
BIT16 = 0x2, /* {CARD16* | INT16*} */
BIT32 = 0x3, /* {CARD32* | INT32*} */
BIT64 = 0x4, /* {CARD64* | INT64*} */
BARRAY = 0x5, /* int*, void* */
ITER = 0x6, /* int* */
POINTER = 0x7, /* specifies next item is a PTR_ITEM */
PTR_ITEM = 0x8, /* specifies the item has a pointer */
/* BOGUS - POINTER and PTR_ITEM
* In the current implementation, PTR_ITEM should be lead by
* POINTER. But actually, it's just redundant logically. Someone
* may remove this redundancy and POINTER from the enum member but he
* should also modify the logic in FrameMgr program.
*/
PADDING = 0x9, /* specifies that a padding is needed.
* This requires extra data in data field.
*/
EOL = 0xA, /* specifies the end of list */
COUNTER_BIT8 = COUNTER_MASK | 0x1,
COUNTER_BIT16 = COUNTER_MASK | 0x2,
COUNTER_BIT32 = COUNTER_MASK | 0x3,
COUNTER_BIT64 = COUNTER_MASK | 0x4
} XimFrameType;
/* Convenient macro */
#define _FRAME(a) {a, NULL}
#define _PTR(p) {PTR_ITEM, (void *)p}
/* PADDING's usage of data field
* B15-B8 : Shows the number of effective items.
* B7-B0 : Shows padding unit. ex) 04 shows 4 unit padding.
*/
#define _PAD2(n) {PADDING, (void*)((n)<<8|2)}
#define _PAD4(n) {PADDING, (void*)((n)<<8|4)}
#define FmCounterByte 0
#define FmCounterNumber 1
#define _BYTE_COUNTER(type, offset) \
{(COUNTER_MASK|type), (void*)((offset)<<8|FmCounterByte)}
#define _NUMBER_COUNTER(type, offset) \
{(COUNTER_MASK|type), (void*)((offset)<<8|FmCounterNumber)}
typedef struct _XimFrame
{
XimFrameType type;
void* data; /* For PTR_ITEM and PADDING */
} XimFrameRec, *XimFrame;
typedef enum
{
FmSuccess,
FmEOD,
FmInvalidCall,
FmBufExist,
FmCannotCalc,
FmNoMoreData
} FmStatus;
typedef struct _FrameMgr *FrameMgr;
FrameMgr FrameMgrInit(XimFrame frame, char* area, Bool byte_swap);
void FrameMgrInitWithData(FrameMgr fm, XimFrame frame, void* area,
Bool byte_swap);
void FrameMgrFree(FrameMgr fm);
FmStatus FrameMgrSetBuffer(FrameMgr, void*);
FmStatus _FrameMgrPutToken(FrameMgr, void*, int);
FmStatus _FrameMgrGetToken(FrameMgr, void*, int);
FmStatus FrameMgrSetSize(FrameMgr, int);
FmStatus FrameMgrSetIterCount(FrameMgr, int);
FmStatus FrameMgrSetTotalSize(FrameMgr, int);
int FrameMgrGetTotalSize(FrameMgr);
int FrameMgrGetSize(FrameMgr);
FmStatus FrameMgrSkipToken(FrameMgr, int);
void FrameMgrReset(FrameMgr);
Bool FrameMgrIsIterLoopEnd(FrameMgr, FmStatus*);
#define FrameMgrPutToken(fm, obj) _FrameMgrPutToken((fm), &(obj), sizeof(obj))
#define FrameMgrGetToken(fm, obj) _FrameMgrGetToken((fm), &(obj), sizeof(obj))
#endif /* FRAMEMGR_H */

View File

@@ -0,0 +1,474 @@
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
/******************************************************************
Copyright (C) 1994-1995 Sun Microsystems, Inc.
Copyright (C) 1993-1994 Hewlett-Packard Company
Copyright (C) 2014 Peng Huang <shawn.p.huang@gmail.com>
Copyright (C) 2014 Red Hat, Inc.
Permission to use, copy, modify, distribute, and sell this software
and its documentation for any purpose is hereby granted without fee,
provided that the above copyright notice appear in all copies and
that both that copyright notice and this permission notice appear
in supporting documentation, and that the name of Sun Microsystems, Inc.
and Hewlett-Packard not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior permission.
Sun Microsystems, Inc. and Hewlett-Packard make no representations about
the suitability of this software for any purpose. It is provided "as is"
without express or implied warranty.
SUN MICROSYSTEMS INC. AND HEWLETT-PACKARD COMPANY DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
SUN MICROSYSTEMS, INC. AND HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Author: Hidetoshi Tajima(tajima@Eng.Sun.COM) Sun Microsystems, Inc.
This version tidied and debugged by Steve Underwood May 1999
******************************************************************/
#ifndef _Xi18n_h
#define _Xi18n_h
#include <X11/Xlib.h>
#include <X11/Xfuncs.h>
#include <X11/Xos.h>
#include "XimProto.h"
/*
* Minor Protocol Number for Extension Protocol
*/
#define XIM_EXTENSION 128
#define XIM_EXT_SET_EVENT_MASK (0x30)
#define XIM_EXT_FORWARD_KEYEVENT (0x32)
#define XIM_EXT_MOVE (0x33)
#define COMMON_EXTENSIONS_NUM 3
#include <stddef.h>
#include <stdlib.h>
/* XI18N Valid Attribute Name Definition */
#define ExtForwardKeyEvent "extForwardKeyEvent"
#define ExtMove "extMove"
#define ExtSetEventMask "extSetEventMask"
/*
* Padding macro
*/
#define IMPAD(length) ((4 - ((length)%4))%4)
/*
* Target Atom for Transport Connection
*/
#define LOCALES "LOCALES"
#define TRANSPORT "TRANSPORT"
typedef struct _NimfXim NimfXim;
typedef struct _XIMPending
{
unsigned char *p;
struct _XIMPending *next;
} XIMPending;
typedef struct _XimProtoHdr
{
CARD8 major_opcode;
CARD8 minor_opcode;
CARD16 length;
} XimProtoHdr;
typedef struct
{
CARD16 attribute_id;
CARD16 type;
CARD16 length;
char *name;
} XIMAttr;
typedef struct
{
CARD16 attribute_id;
CARD16 type;
CARD16 length;
char *name;
} XICAttr;
typedef struct
{
int attribute_id;
CARD16 name_length;
char *name;
int value_length;
void *value;
int type;
} XIMAttribute;
typedef struct
{
int attribute_id;
CARD16 name_length;
char *name;
int value_length;
void *value;
int type;
} XICAttribute;
typedef struct
{
int length;
char *name;
} XIMStr;
typedef struct
{
CARD16 major_opcode;
CARD16 minor_opcode;
CARD16 length;
char *name;
} XIMExt;
typedef struct
{
Atom key;
unsigned long offset;
} Xi18nAtomOffsetPair;
typedef struct
{
size_t capacity;
size_t size;
Xi18nAtomOffsetPair *data;
} Xi18nOffsetCache;
typedef struct _Xi18nClient
{
int connect_id;
CARD8 byte_order;
/*
'?': initial value
'B': for Big-Endian
'l': for little-endian
*/
int sync;
XIMPending *pending;
Xi18nOffsetCache offset_cache;
void *trans_rec; /* contains transport specific data */
struct _Xi18nClient *next;
} Xi18nClient;
/*
* Callback Struct for XIM Protocol
*/
typedef struct
{
int major_code;
int minor_code;
CARD16 connect_id;
} IMAnyStruct;
typedef struct
{
int major_code;
int minor_code;
CARD16 connect_id;
CARD8 byte_order;
CARD16 major_version;
CARD16 minor_version;
} IMConnectStruct;
typedef struct
{
int major_code;
int minor_code;
CARD16 connect_id;
} IMDisConnectStruct;
typedef struct
{
int major_code;
int minor_code;
CARD16 connect_id;
XIMStr lang;
} IMOpenStruct;
typedef struct
{
int major_code;
int minor_code;
CARD16 connect_id;
} IMCloseStruct;
typedef struct
{
int major_code;
int minor_code;
CARD16 connect_id;
CARD16 number;
XIMStr *extension;
} IMQueryExtensionStruct;
typedef struct
{
int major_code;
int minor_code;
CARD16 connect_id;
CARD16 number;
char **im_attr_list;
} IMGetIMValuesStruct;
typedef struct
{
int major_code;
int minor_code;
CARD16 connect_id;
CARD16 icid;
CARD16 preedit_attr_num;
CARD16 status_attr_num;
CARD16 ic_attr_num;
XICAttribute *preedit_attr;
XICAttribute *status_attr;
XICAttribute *ic_attr;
} IMChangeICStruct;
typedef struct
{
int major_code;
int minor_code;
CARD16 connect_id;
CARD16 icid;
} IMDestroyICStruct;
typedef struct
{
int major_code;
int minor_code;
CARD16 connect_id;
CARD16 icid;
CARD16 length;
char *commit_string;
} IMResetICStruct;
typedef struct
{
int major_code;
int minor_code;
CARD16 connect_id;
CARD16 icid;
} IMChangeFocusStruct;
typedef struct
{
int major_code;
int minor_code;
CARD16 connect_id;
CARD16 icid;
BITMASK16 sync_bit;
CARD16 serial_number;
XEvent event;
} IMForwardEventStruct;
typedef struct
{
int major_code;
int minor_code;
CARD16 connect_id;
CARD16 icid;
CARD16 flag;
KeySym keysym;
char *commit_string;
} IMCommitStruct;
typedef struct
{
int major_code;
int minor_code;
CARD16 connect_id;
CARD16 icid;
CARD32 flag;
CARD32 key_index;
CARD32 event_mask;
} IMTriggerNotifyStruct;
typedef struct
{
int major_code;
int minor_code;
CARD16 connect_id;
CARD16 encoding_number;
XIMStr *encoding; /* name information */
CARD16 encoding_info_number;
XIMStr *encodinginfo; /* detailed information */
CARD16 category; /* #0 for name, #1 for detail */
INT16 enc_index; /* index of the encoding determined */
} IMEncodingNegotiationStruct;
typedef struct
{
int major_code;
int minor_code;
CARD16 connect_id;
CARD16 icid;
CARD32 flag;
CARD32 forward_event_mask;
CARD32 sync_event_mask;
} IMSetEventMaskStruct;
typedef struct
{
int major_code;
int minor_code;
CARD16 connect_id;
CARD16 icid;
CARD32 filter_event_mask;
CARD32 intercept_event_mask;
CARD32 select_event_mask;
CARD32 forward_event_mask;
CARD32 sync_event_mask;
} IMExtSetEventMaskStruct;
typedef struct
{
int major_code;
int minor_code;
CARD16 connect_id;
CARD16 icid;
CARD16 x;
CARD16 y;
} IMMoveStruct;
typedef struct
{
int major_code;
int minor_code;
CARD16 connect_id;
CARD16 icid;
BITMASK16 flag;
CARD16 error_code;
CARD16 str_length;
CARD16 error_type;
char *error_detail;
} IMErrorStruct;
typedef struct
{
int major_code;
int minor_code;
CARD16 connect_id;
CARD16 icid;
} IMPreeditStateStruct;
/* Callbacks */
typedef struct
{
int major_code;
int minor_code;
CARD16 connect_id;
CARD16 icid;
} IMGeometryCBStruct;
typedef struct
{
int major_code;
int minor_code;
CARD16 connect_id;
CARD16 icid;
union
{
int return_value; /* PreeditStart */
XIMPreeditDrawCallbackStruct draw; /* PreeditDraw */
XIMPreeditCaretCallbackStruct caret; /* PreeditCaret */
} todo;
} IMPreeditCBStruct;
typedef struct
{
int major_code;
int minor_code;
CARD16 connect_id;
CARD16 icid;
union
{
XIMStatusDrawCallbackStruct draw; /* StatusDraw */
} todo;
} IMStatusCBStruct;
typedef struct
{
int major_code;
int minor_code;
CARD16 connect_id;
CARD16 icid;
XIMStringConversionCallbackStruct strconv;
} IMStrConvCBStruct;
typedef struct
{
int major_code;
int minor_code;
CARD16 connect_id;
CARD16 icid;
} IMSyncXlibStruct;
typedef union _IMProtocol
{
int major_code;
IMAnyStruct any;
IMConnectStruct imconnect;
IMDisConnectStruct imdisconnect;
IMOpenStruct imopen;
IMCloseStruct imclose;
IMQueryExtensionStruct queryext;
IMGetIMValuesStruct getim;
IMEncodingNegotiationStruct encodingnego;
IMExtSetEventMaskStruct extsetevent;
IMMoveStruct extmove;
IMSetEventMaskStruct setevent;
IMChangeICStruct changeic;
IMDestroyICStruct destroyic;
IMResetICStruct resetic;
IMChangeFocusStruct changefocus;
IMCommitStruct commitstring;
IMForwardEventStruct forwardevent;
IMTriggerNotifyStruct triggernotify;
IMPreeditStateStruct preedit_state;
IMErrorStruct imerror;
IMGeometryCBStruct geometry_callback;
IMPreeditCBStruct preedit_callback;
IMStatusCBStruct status_callback;
IMStrConvCBStruct strconv_callback;
IMSyncXlibStruct sync_xlib;
long pad[32];
} IMProtocol;
typedef int (*IMProtoHandler) (NimfXim *, IMProtocol*, void*);
/* Xi18nAddressRec structure */
typedef struct _Xi18nAddressRec
{
/* XIM_SERVERS target Atoms */
Atom selection;
Atom Localename;
Atom Transportname;
/* XIM/XIC Attr */
int im_attr_num;
XIMAttr *xim_attr;
int ic_attr_num;
XICAttr *xic_attr;
CARD16 preeditAttr_id;
CARD16 statusAttr_id;
CARD16 separatorAttr_id;
/* XIMExtension List */
int ext_num;
XIMExt extension[COMMON_EXTENSIONS_NUM];
/* clients table */
Xi18nClient *clients;
Xi18nClient *free_clients;
} Xi18nAddressRec;
#endif

View File

@@ -0,0 +1,65 @@
/******************************************************************
Copyright 1994, 1995 by Sun Microsystems, Inc.
Copyright 1993, 1994 by Hewlett-Packard Company
Permission to use, copy, modify, distribute, and sell this software
and its documentation for any purpose is hereby granted without fee,
provided that the above copyright notice appear in all copies and
that both that copyright notice and this permission notice appear
in supporting documentation, and that the name of Sun Microsystems, Inc.
and Hewlett-Packard not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior permission.
Sun Microsystems, Inc. and Hewlett-Packard make no representations about
the suitability of this software for any purpose. It is provided "as is"
without express or implied warranty.
SUN MICROSYSTEMS INC. AND HEWLETT-PACKARD COMPANY DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
SUN MICROSYSTEMS, INC. AND HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Author: Hidetoshi Tajima(tajima@Eng.Sun.COM) Sun Microsystems, Inc.
This version tidied and debugged by Steve Underwood May 1999
******************************************************************/
#ifndef _XimFunc_h
#define _XimFunc_h
/* i18nAttr.c */
void _Xi18nInitAttrList (NimfXim *xim);
void _Xi18nInitExtension(NimfXim *xim);
/* i18nClbk.c */
int _Xi18nGeometryCallback (NimfXim *xim, IMProtocol *call_data);
int _Xi18nPreeditStartCallback (NimfXim *xim, IMProtocol *call_data);
int _Xi18nPreeditDrawCallback (NimfXim *xim, IMProtocol *call_data);
int _Xi18nPreeditCaretCallback (NimfXim *xim, IMProtocol *call_data);
int _Xi18nPreeditDoneCallback (NimfXim *xim, IMProtocol *call_data);
int _Xi18nStatusStartCallback (NimfXim *xim, IMProtocol *call_data);
int _Xi18nStatusDrawCallback (NimfXim *xim, IMProtocol *call_data);
int _Xi18nStatusDoneCallback (NimfXim *xim, IMProtocol *call_data);
int _Xi18nStringConversionCallback (NimfXim *xim, IMProtocol *call_data);
/* i18nIc.c */
void _Xi18nChangeIC (NimfXim *xim, IMProtocol *call_data, unsigned char *p,
int create_flag);
void _Xi18nGetIC (NimfXim *xim, IMProtocol *call_data, unsigned char *p);
/* i18nUtil.c */
int _Xi18nNeedSwap (NimfXim *xim, CARD16 connect_id);
Xi18nClient *_Xi18nNewClient(NimfXim *xim);
Xi18nClient *_Xi18nFindClient (NimfXim *xim, CARD16 connect_id);
void _Xi18nDeleteClient (NimfXim *xim, CARD16 connect_id);
void _Xi18nSendMessage (NimfXim *xim, CARD16 connect_id, CARD8 major_opcode,
CARD8 minor_opcode, unsigned char *data, long length);
void _Xi18nSetEventMask (NimfXim *xim, CARD16 connect_id, CARD16 im_id,
CARD16 ic_id, CARD32 forward_mask, CARD32 sync_mask);
#endif

View File

@@ -0,0 +1,211 @@
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
/* $XConsortium: XimProto.h,v 1.2 94/01/20 18:02:24 rws Exp $ */
/******************************************************************
Copyright 1992, 1993, 1994 by FUJITSU LIMITED
Permission to use, copy, modify, distribute, and sell this software
and its documentation for any purpose is hereby granted without fee,
provided that the above copyright notice appear in all copies and
that both that copyright notice and this permission notice appear
in supporting documentation, and that the name of FUJITSU LIMITED
not be used in advertising or publicity pertaining to distribution
of the software without specific, written prior permission.
FUJITSU LIMITED makes no representations about the suitability of
this software for any purpose.
It is provided "as is" without express or implied warranty.
FUJITSU LIMITED DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
EVENT SHALL FUJITSU LIMITED BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
Author: Takashi Fujiwara FUJITSU LIMITED
fujiwara@a80.tech.yk.fujitsu.co.jp
This version tidied and debugged by Steve Underwood May 1999
******************************************************************/
#ifndef _XIMPROTO_H
#define _XIMPROTO_H
#include <X11/Xmd.h>
/*
* Default Preconnection selection target
*/
#define XIM_SERVERS "XIM_SERVERS"
#define XIM_LOCALES "LOCALES"
#define XIM_TRANSPORT "TRANSPORT"
/*
* Xim implementation revision
*/
#define PROTOCOLMAJORVERSION 0
#define PROTOCOLMINORVERSION 0
/*
* Major Protocol number
*/
#define XIM_CONNECT 1
#define XIM_CONNECT_REPLY 2
#define XIM_DISCONNECT 3
#define XIM_DISCONNECT_REPLY 4
#define XIM_AUTH_REQUIRED 10
#define XIM_AUTH_REPLY 11
#define XIM_AUTH_NEXT 12
#define XIM_AUTH_SETUP 13
#define XIM_AUTH_NG 14
#define XIM_ERROR 20
#define XIM_OPEN 30
#define XIM_OPEN_REPLY 31
#define XIM_CLOSE 32
#define XIM_CLOSE_REPLY 33
#define XIM_SET_EVENT_MASK 37
#define XIM_ENCODING_NEGOTIATION 38
#define XIM_ENCODING_NEGOTIATION_REPLY 39
#define XIM_QUERY_EXTENSION 40
#define XIM_QUERY_EXTENSION_REPLY 41
#define XIM_SET_IM_VALUES 42
#define XIM_SET_IM_VALUES_REPLY 43
#define XIM_GET_IM_VALUES 44
#define XIM_GET_IM_VALUES_REPLY 45
#define XIM_CREATE_IC 50
#define XIM_CREATE_IC_REPLY 51
#define XIM_DESTROY_IC 52
#define XIM_DESTROY_IC_REPLY 53
#define XIM_SET_IC_VALUES 54
#define XIM_SET_IC_VALUES_REPLY 55
#define XIM_GET_IC_VALUES 56
#define XIM_GET_IC_VALUES_REPLY 57
#define XIM_SET_IC_FOCUS 58
#define XIM_UNSET_IC_FOCUS 59
#define XIM_FORWARD_EVENT 60
#define XIM_SYNC 61
#define XIM_SYNC_REPLY 62
#define XIM_COMMIT 63
#define XIM_RESET_IC 64
#define XIM_RESET_IC_REPLY 65
#define XIM_GEOMETRY 70
#define XIM_STR_CONVERSION 71
#define XIM_STR_CONVERSION_REPLY 72
#define XIM_PREEDIT_START 73
#define XIM_PREEDIT_START_REPLY 74
#define XIM_PREEDIT_DRAW 75
#define XIM_PREEDIT_CARET 76
#define XIM_PREEDIT_CARET_REPLY 77
#define XIM_PREEDIT_DONE 78
#define XIM_STATUS_START 79
#define XIM_STATUS_DRAW 80
#define XIM_STATUS_DONE 81
/*
* values for the flag of XIM_ERROR
*/
#define XIM_IMID_VALID 0x0001
#define XIM_ICID_VALID 0x0002
/*
* XIM Error Code
*/
#define XIM_BadAlloc 1
#define XIM_BadStyle 2
#define XIM_BadClientWindow 3
#define XIM_BadFocusWindow 4
#define XIM_BadArea 5
#define XIM_BadSpotLocation 6
#define XIM_BadColormap 7
#define XIM_BadAtom 8
#define XIM_BadPixel 9
#define XIM_BadPixmap 10
#define XIM_BadName 11
#define XIM_BadCursor 12
#define XIM_BadProtocol 13
#define XIM_BadForeground 14
#define XIM_BadBackground 15
#define XIM_LocaleNotSupported 16
#define XIM_BadSomething 999
/*
* values for the type of XIMATTR & XICATTR
*/
#define XimType_SeparatorOfNestedList 0
#define XimType_CARD8 1
#define XimType_CARD16 2
#define XimType_CARD32 3
#define XimType_STRING8 4
#define XimType_Window 5
#define XimType_XIMStyles 10
#define XimType_XRectangle 11
#define XimType_XPoint 12
#define XimType_XFontSet 13
#define XimType_XIMOptions 14
#define XimType_XIMHotKeyState 16
#define XimType_XIMStringConversion 17
#define XimType_XIMValuesList 18
#define XimType_NEST 0x7FFF
/*
* values for the category of XIM_ENCODING_NEGOTIATON_REPLY
*/
#define XIM_Encoding_NameCategory 0
#define XIM_Encoding_DetailCategory 1
/*
* value for the flag of XIM_FORWARD_EVENT, XIM_COMMIT
*/
#define XimSYNCHRONUS 0x0001
#define XimLookupChars 0x0002
#define XimLookupKeySym 0x0004
#define XimLookupBoth 0x0006
/*
* request packet header size
*/
#define XIM_HEADER_SIZE \
sizeof(CARD8) /* sizeof mejor-opcode */ \
+ sizeof(CARD8) /* sizeof minor-opcode */ \
+ sizeof(INT16) /* sizeof length */
/*
* Client Message data size
*/
#define XIM_CM_DATA_SIZE 20
/*
* XIM data structure
*/
typedef CARD16 BITMASK16;
typedef CARD32 BITMASK32;
typedef CARD32 EVENTMASK;
typedef CARD16 XIMID; /* Input Method ID */
typedef CARD16 XICID; /* Input Context ID */
/*
* Padding macro
*/
#define XIM_PAD(length) ((4 - ((length) % 4)) % 4)
#define XIM_SET_PAD(ptr, length) \
{ \
register int Counter = XIM_PAD((int)length); \
if (Counter) { \
register char *Ptr = (char *)(ptr) + (length); \
length += Counter; \
for (; Counter; --Counter, ++Ptr) \
*Ptr = '\0'; \
} \
}
#endif

View File

@@ -0,0 +1,174 @@
/******************************************************************
Copyright 1994, 1995 by Sun Microsystems, Inc.
Copyright 1993, 1994 by Hewlett-Packard Company
Permission to use, copy, modify, distribute, and sell this software
and its documentation for any purpose is hereby granted without fee,
provided that the above copyright notice appear in all copies and
that both that copyright notice and this permission notice appear
in supporting documentation, and that the name of Sun Microsystems, Inc.
and Hewlett-Packard not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior permission.
Sun Microsystems, Inc. and Hewlett-Packard make no representations about
the suitability of this software for any purpose. It is provided "as is"
without express or implied warranty.
SUN MICROSYSTEMS INC. AND HEWLETT-PACKARD COMPANY DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
SUN MICROSYSTEMS, INC. AND HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Author: Hidetoshi Tajima(tajima@Eng.Sun.COM) Sun Microsystems, Inc.
This version tidied and debugged by Steve Underwood May 1999
******************************************************************/
#include <X11/Xlib.h>
#include <X11/Xresource.h>
#include "Xi18n.h"
#include "XimFunc.h"
#include "nimf-xim.h"
typedef struct
{
char *name;
CARD16 type;
} IMListOfAttr;
typedef struct
{
char *name;
CARD8 major_opcode;
CARD8 minor_opcode;
} IMExtList;
IMListOfAttr Default_IMattr[] =
{
{XNQueryInputStyle, XimType_XIMStyles},
{(char *) NULL, (CARD16) 0}
};
IMListOfAttr Default_ICattr[] =
{
{XNInputStyle, XimType_CARD32},
{XNClientWindow, XimType_Window},
{XNFocusWindow, XimType_Window},
{XNFilterEvents, XimType_CARD32},
{XNPreeditAttributes, XimType_NEST},
{XNStatusAttributes, XimType_NEST},
{XNFontSet, XimType_XFontSet},
{XNArea, XimType_XRectangle},
{XNAreaNeeded, XimType_XRectangle},
{XNColormap, XimType_CARD32},
{XNStdColormap, XimType_CARD32},
{XNForeground, XimType_CARD32},
{XNBackground, XimType_CARD32},
{XNBackgroundPixmap, XimType_CARD32},
{XNSpotLocation, XimType_XPoint},
{XNLineSpace, XimType_CARD32},
{XNPreeditState, XimType_CARD32},
{XNSeparatorofNestedList, XimType_SeparatorOfNestedList},
{(char *) NULL, 0}
};
IMExtList Default_Extension[] =
{
{"XIM_EXT_MOVE", XIM_EXTENSION, XIM_EXT_MOVE},
{"XIM_EXT_SET_EVENT_MASK", XIM_EXTENSION, XIM_EXT_SET_EVENT_MASK},
{"XIM_EXT_FORWARD_KEYEVENT", XIM_EXTENSION, XIM_EXT_FORWARD_KEYEVENT},
{(char *) NULL, 0, 0}
};
static void CountAttrList(IMListOfAttr *attr, int *total_count)
{
*total_count = 0;
while (attr->name != NULL)
{
attr++;
++(*total_count);
}
}
static XIMAttr *CreateAttrList (NimfXim *xim,
IMListOfAttr *attr,
int *total_count)
{
XIMAttr *args, *p;
unsigned int buf_size;
CountAttrList(attr, total_count);
buf_size = (unsigned) (*total_count + 1)*sizeof (XIMAttr);
args = (XIMAttr *) malloc (buf_size);
if (!args)
return (XIMAttr *) NULL;
/*endif*/
memset (args, 0, buf_size);
for (p = args; attr->name != NULL; attr++, p++)
{
p->name = attr->name;
p->length = strlen (attr->name);
p->type = (CARD16) attr->type;
p->attribute_id = XrmStringToQuark (p->name);
if (strcmp (p->name, XNPreeditAttributes) == 0)
xim->address.preeditAttr_id = p->attribute_id;
else if (strcmp (p->name, XNStatusAttributes) == 0)
xim->address.statusAttr_id = p->attribute_id;
else if (strcmp (p->name, XNSeparatorofNestedList) == 0)
xim->address.separatorAttr_id = p->attribute_id;
/*endif*/
}
/*endfor*/
p->name = (char *) NULL;
return args;
}
void _Xi18nInitAttrList (NimfXim *xim)
{
XIMAttr *args;
int total_count;
/* init IMAttr list */
if (xim->address.xim_attr)
XFree ((char *) xim->address.xim_attr);
/*endif*/
args = CreateAttrList (xim, Default_IMattr, &total_count);
xim->address.im_attr_num = total_count;
xim->address.xim_attr = (XIMAttr *)args;
/* init ICAttr list */
if (xim->address.xic_attr)
XFree ((char *) xim->address.xic_attr);
/*endif*/
args = CreateAttrList (xim, Default_ICattr, &total_count);
xim->address.ic_attr_num = total_count;
xim->address.xic_attr = (XICAttr *) args;
}
void _Xi18nInitExtension(NimfXim *xim)
{
register int i;
IMExtList *extensions = (IMExtList *) Default_Extension;
XIMExt *ext_list = (XIMExt *) xim->address.extension;
for (i = 0; extensions->name; i++, ext_list++, extensions++)
{
ext_list->major_opcode = extensions->major_opcode;
ext_list->minor_opcode = extensions->minor_opcode;
ext_list->name = extensions->name;
ext_list->length = strlen(ext_list->name);
}
xim->address.ext_num = i;
}

View File

@@ -0,0 +1,501 @@
/******************************************************************
Copyright 1994, 1995 by Sun Microsystems, Inc.
Copyright 1993, 1994 by Hewlett-Packard Company
Permission to use, copy, modify, distribute, and sell this software
and its documentation for any purpose is hereby granted without fee,
provided that the above copyright notice appear in all copies and
that both that copyright notice and this permission notice appear
in supporting documentation, and that the name of Sun Microsystems, Inc.
and Hewlett-Packard not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior permission.
Sun Microsystems, Inc. and Hewlett-Packard make no representations about
the suitability of this software for any purpose. It is provided "as is"
without express or implied warranty.
SUN MICROSYSTEMS INC. AND HEWLETT-PACKARD COMPANY DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
SUN MICROSYSTEMS, INC. AND HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Author: Hidetoshi Tajima(tajima@Eng.Sun.COM) Sun Microsystems, Inc.
This version tidied and debugged by Steve Underwood May 1999
******************************************************************/
#include <X11/Xlib.h>
#include "Xi18n.h"
#include "FrameMgr.h"
#include "XimFunc.h"
#include "nimf-xim.h"
#include "i18nX.h"
int _Xi18nGeometryCallback (NimfXim *xim, IMProtocol *call_data)
{
FrameMgr fm;
extern XimFrameRec geometry_fr[];
register int total_size;
unsigned char *reply = NULL;
IMGeometryCBStruct *geometry_CB =
(IMGeometryCBStruct *) &call_data->geometry_callback;
CARD16 connect_id = call_data->any.connect_id;
fm = FrameMgrInit (geometry_fr,
NULL,
_Xi18nNeedSwap (xim, connect_id));
total_size = FrameMgrGetTotalSize (fm);
reply = (unsigned char *) malloc (total_size);
if (!reply)
{
_Xi18nSendMessage (xim, connect_id, XIM_ERROR, 0, 0, 0);
return False;
}
/*endif*/
memset (reply, 0, total_size);
FrameMgrSetBuffer (fm, reply);
FrameMgrPutToken (fm, connect_id);
FrameMgrPutToken (fm, geometry_CB->icid);
_Xi18nSendMessage (xim,
connect_id,
XIM_GEOMETRY,
0,
reply,
total_size);
FrameMgrFree (fm);
XFree (reply);
/* XIM_GEOMETRY is an asyncronous protocol,
so return immediately. */
return True;
}
int _Xi18nPreeditStartCallback (NimfXim *xim, IMProtocol *call_data)
{
FrameMgr fm;
extern XimFrameRec preedit_start_fr[];
register int total_size;
unsigned char *reply = NULL;
IMPreeditCBStruct *preedit_CB =
(IMPreeditCBStruct*) &call_data->preedit_callback;
CARD16 connect_id = call_data->any.connect_id;
fm = FrameMgrInit (preedit_start_fr,
NULL,
_Xi18nNeedSwap (xim, connect_id));
total_size = FrameMgrGetTotalSize (fm);
reply = (unsigned char *) malloc (total_size);
if (!reply)
{
_Xi18nSendMessage(xim, connect_id, XIM_ERROR, 0, 0, 0);
return False;
}
memset (reply, 0, total_size);
FrameMgrSetBuffer (fm, reply);
FrameMgrPutToken (fm, connect_id);
FrameMgrPutToken (fm, preedit_CB->icid);
_Xi18nSendMessage (xim,
connect_id,
XIM_PREEDIT_START,
0,
reply,
total_size);
FrameMgrFree (fm);
XFree (reply);
return True;
}
int _Xi18nPreeditDrawCallback (NimfXim *xim, IMProtocol *call_data)
{
FrameMgr fm;
extern XimFrameRec preedit_draw_fr[];
register int total_size;
unsigned char *reply = NULL;
IMPreeditCBStruct *preedit_CB =
(IMPreeditCBStruct *) &call_data->preedit_callback;
XIMPreeditDrawCallbackStruct *draw =
(XIMPreeditDrawCallbackStruct *) &preedit_CB->todo.draw;
CARD16 connect_id = call_data->any.connect_id;
register int feedback_count;
register int i;
BITMASK32 status = 0x0;
if (draw->text->length == 0)
status = 0x00000001;
else if (draw->text->feedback[0] == 0)
status = 0x00000002;
/*endif*/
fm = FrameMgrInit (preedit_draw_fr,
NULL,
_Xi18nNeedSwap (xim, connect_id));
/* set length of preedit string */
FrameMgrSetSize (fm, draw->text->length);
/* set iteration count for list of feedback */
for (i = 0; draw->text->feedback[i] != 0; i++)
;
/*endfor*/
feedback_count = i;
FrameMgrSetIterCount (fm, feedback_count);
total_size = FrameMgrGetTotalSize (fm);
reply = (unsigned char *) malloc (total_size);
if (!reply)
{
_Xi18nSendMessage (xim, connect_id, XIM_ERROR, 0, 0, 0);
return False;
}
/*endif*/
memset (reply, 0, total_size);
FrameMgrSetBuffer (fm, reply);
FrameMgrPutToken (fm, connect_id);
FrameMgrPutToken (fm, preedit_CB->icid);
FrameMgrPutToken (fm, draw->caret);
FrameMgrPutToken (fm, draw->chg_first);
FrameMgrPutToken (fm, draw->chg_length);
FrameMgrPutToken (fm, status);
FrameMgrPutToken (fm, draw->text->length);
FrameMgrPutToken (fm, draw->text->string);
for (i = 0; i < feedback_count; i++)
FrameMgrPutToken (fm, draw->text->feedback[i]);
/*endfor*/
_Xi18nSendMessage (xim,
connect_id,
XIM_PREEDIT_DRAW,
0,
reply,
total_size);
FrameMgrFree (fm);
XFree (reply);
/* XIM_PREEDIT_DRAW is an asyncronous protocol, so return immediately. */
return True;
}
int _Xi18nPreeditCaretCallback (NimfXim *xim, IMProtocol *call_data)
{
FrameMgr fm;
extern XimFrameRec preedit_caret_fr[];
register int total_size;
unsigned char *reply = NULL;
IMPreeditCBStruct *preedit_CB =
(IMPreeditCBStruct*) &call_data->preedit_callback;
XIMPreeditCaretCallbackStruct *caret =
(XIMPreeditCaretCallbackStruct *) &preedit_CB->todo.caret;
CARD16 connect_id = call_data->any.connect_id;
fm = FrameMgrInit (preedit_caret_fr,
NULL,
_Xi18nNeedSwap (xim, connect_id));
total_size = FrameMgrGetTotalSize (fm);
reply = (unsigned char *) malloc (total_size);
if (!reply)
{
_Xi18nSendMessage (xim, connect_id, XIM_ERROR, 0, 0, 0);
return False;
}
/*endif*/
memset (reply, 0, total_size);
FrameMgrSetBuffer (fm, reply);
FrameMgrPutToken (fm, connect_id);
FrameMgrPutToken (fm, preedit_CB->icid);
FrameMgrPutToken (fm, caret->position);
FrameMgrPutToken (fm, caret->direction);
FrameMgrPutToken (fm, caret->style);
_Xi18nSendMessage (xim,
connect_id,
XIM_PREEDIT_CARET,
0,
reply,
total_size);
FrameMgrFree (fm);
XFree (reply);
return True;
}
int _Xi18nPreeditDoneCallback (NimfXim *xim, IMProtocol *call_data)
{
FrameMgr fm;
extern XimFrameRec preedit_done_fr[];
register int total_size;
unsigned char *reply = NULL;
IMPreeditCBStruct *preedit_CB =
(IMPreeditCBStruct *) &call_data->preedit_callback;
CARD16 connect_id = call_data->any.connect_id;
fm = FrameMgrInit (preedit_done_fr,
NULL,
_Xi18nNeedSwap (xim, connect_id));
total_size = FrameMgrGetTotalSize (fm);
reply = (unsigned char *) malloc (total_size);
if (!reply)
{
_Xi18nSendMessage (xim, connect_id, XIM_ERROR, 0, 0, 0);
return False;
}
/*endif*/
memset (reply, 0, total_size);
FrameMgrSetBuffer (fm, reply);
FrameMgrPutToken (fm, connect_id);
FrameMgrPutToken (fm, preedit_CB->icid);
_Xi18nSendMessage (xim,
connect_id,
XIM_PREEDIT_DONE,
0,
reply,
total_size);
FrameMgrFree (fm);
XFree (reply);
/* XIM_PREEDIT_DONE is an asyncronous protocol, so return immediately. */
return True;
}
int _Xi18nStatusStartCallback (NimfXim *xim, IMProtocol *call_data)
{
FrameMgr fm;
extern XimFrameRec status_start_fr[];
register int total_size;
unsigned char *reply = NULL;
IMStatusCBStruct *status_CB =
(IMStatusCBStruct*) &call_data->status_callback;
CARD16 connect_id = call_data->any.connect_id;
fm = FrameMgrInit (status_start_fr,
NULL,
_Xi18nNeedSwap (xim, connect_id));
total_size = FrameMgrGetTotalSize (fm);
reply = (unsigned char *) malloc (total_size);
if (!reply)
{
_Xi18nSendMessage (xim, connect_id, XIM_ERROR, 0, 0, 0);
return False;
}
/*endif*/
memset (reply, 0, total_size);
FrameMgrSetBuffer (fm, reply);
FrameMgrPutToken (fm, connect_id);
FrameMgrPutToken (fm, status_CB->icid);
_Xi18nSendMessage (xim,
connect_id,
XIM_STATUS_START,
0,
reply,
total_size);
FrameMgrFree (fm);
XFree (reply);
/* XIM_STATUS_START is an asyncronous protocol, so return immediately. */
return True;
}
int _Xi18nStatusDrawCallback (NimfXim *xim, IMProtocol *call_data)
{
FrameMgr fm = (FrameMgr)0;
extern XimFrameRec status_draw_text_fr[];
extern XimFrameRec status_draw_bitmap_fr[];
register int total_size = 0;
unsigned char *reply = NULL;
IMStatusCBStruct *status_CB =
(IMStatusCBStruct *) &call_data->status_callback;
XIMStatusDrawCallbackStruct *draw =
(XIMStatusDrawCallbackStruct *) &status_CB->todo.draw;
CARD16 connect_id = call_data->any.connect_id;
register int feedback_count;
register int i;
BITMASK32 status = 0x0;
switch (draw->type)
{
case XIMTextType:
fm = FrameMgrInit (status_draw_text_fr,
NULL,
_Xi18nNeedSwap (xim, connect_id));
if (draw->data.text->length == 0)
status = 0x00000001;
else if (draw->data.text->feedback[0] == 0)
status = 0x00000002;
/*endif*/
/* set length of status string */
FrameMgrSetSize(fm, draw->data.text->length);
/* set iteration count for list of feedback */
for (i = 0; draw->data.text->feedback[i] != 0; i++)
;
/*endfor*/
feedback_count = i;
FrameMgrSetIterCount (fm, feedback_count);
total_size = FrameMgrGetTotalSize (fm);
reply = (unsigned char *) malloc (total_size);
if (!reply)
{
_Xi18nSendMessage (xim, connect_id, XIM_ERROR, 0, 0, 0);
return False;
}
/*endif*/
memset (reply, 0, total_size);
FrameMgrSetBuffer (fm, reply);
FrameMgrPutToken (fm, connect_id);
FrameMgrPutToken (fm, status_CB->icid);
FrameMgrPutToken (fm, draw->type);
FrameMgrPutToken (fm, status);
FrameMgrPutToken (fm, draw->data.text->length);
FrameMgrPutToken (fm, draw->data.text->string);
for (i = 0; i < feedback_count; i++)
FrameMgrPutToken (fm, draw->data.text->feedback[i]);
/*endfor*/
break;
case XIMBitmapType:
fm = FrameMgrInit (status_draw_bitmap_fr,
NULL,
_Xi18nNeedSwap (xim, connect_id));
total_size = FrameMgrGetTotalSize (fm);
reply = (unsigned char *) malloc (total_size);
if (!reply)
{
_Xi18nSendMessage (xim, connect_id, XIM_ERROR, 0, 0, 0);
return False;
}
/*endif*/
memset (reply, 0, total_size);
FrameMgrSetBuffer (fm, reply);
FrameMgrPutToken (fm, connect_id);
FrameMgrPutToken (fm, status_CB->icid);
FrameMgrPutToken (fm, draw->data.bitmap);
break;
}
/*endswitch*/
_Xi18nSendMessage (xim,
connect_id,
XIM_STATUS_DRAW,
0,
reply,
total_size);
FrameMgrFree (fm);
XFree (reply);
/* XIM_STATUS_DRAW is an asyncronous protocol, so return immediately. */
return True;
}
int _Xi18nStatusDoneCallback (NimfXim *xim, IMProtocol *call_data)
{
FrameMgr fm;
extern XimFrameRec status_done_fr[];
register int total_size;
unsigned char *reply = NULL;
IMStatusCBStruct *status_CB =
(IMStatusCBStruct *) &call_data->status_callback;
CARD16 connect_id = call_data->any.connect_id;
fm = FrameMgrInit (status_done_fr,
NULL,
_Xi18nNeedSwap (xim, connect_id));
total_size = FrameMgrGetTotalSize (fm);
reply = (unsigned char *) malloc (total_size);
if (!reply)
{
_Xi18nSendMessage (xim, connect_id, XIM_ERROR, 0, 0, 0);
return False;
}
/*endif*/
memset (reply, 0, total_size);
FrameMgrSetBuffer (fm, reply);
FrameMgrPutToken (fm, connect_id);
FrameMgrPutToken (fm, status_CB->icid);
_Xi18nSendMessage (xim,
connect_id,
XIM_STATUS_DONE,
0,
reply,
total_size);
FrameMgrFree (fm);
XFree (reply);
/* XIM_STATUS_DONE is an asyncronous protocol, so return immediately. */
return True;
}
int _Xi18nStringConversionCallback (NimfXim *xim, IMProtocol *call_data)
{
FrameMgr fm;
extern XimFrameRec str_conversion_fr[];
register int total_size;
unsigned char *reply = NULL;
IMStrConvCBStruct *call_back =
(IMStrConvCBStruct *) &call_data->strconv_callback;
XIMStringConversionCallbackStruct *strconv =
(XIMStringConversionCallbackStruct *) &call_back->strconv;
CARD16 connect_id = call_data->any.connect_id;
fm = FrameMgrInit (str_conversion_fr,
NULL,
_Xi18nNeedSwap (xim, connect_id));
total_size = FrameMgrGetTotalSize (fm);
reply = (unsigned char *) malloc (total_size);
if (!reply)
{
_Xi18nSendMessage (xim, connect_id, XIM_ERROR, 0, 0, 0);
return False;
}
/*endif*/
memset (reply, 0, total_size);
FrameMgrSetBuffer (fm, reply);
FrameMgrPutToken (fm, connect_id);
FrameMgrPutToken (fm, call_back->icid);
FrameMgrPutToken (fm, strconv->position);
FrameMgrPutToken (fm, strconv->direction);
FrameMgrPutToken (fm, strconv->operation);
_Xi18nSendMessage (xim, connect_id,
XIM_STR_CONVERSION,
0,
reply,
total_size);
FrameMgrFree (fm);
XFree (reply);
/* XIM_STR_CONVERSION is a syncronous protocol,
so should wait here for XIM_STR_CONVERSION_REPLY. */
if (Xi18nXWait (xim, connect_id, XIM_STR_CONVERSION_REPLY, 0) == False)
return False;
return True;
}

View File

@@ -0,0 +1,773 @@
/******************************************************************
Copyright 1993, 1994 by Digital Equipment Corporation, Maynard, Massachusetts,
Copyright 1993, 1994 by Hewlett-Packard Company
Copyright 1994, 1995 by Sun Microsystems, Inc.
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the names of Digital or MIT not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
DIGITAL AND HEWLETT-PACKARD COMPANY DISCLAIMS ALL WARRANTIES WITH REGARD
TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL DIGITAL AND HEWLETT-PACKARD COMPANY BE LIABLE
FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Author: Hiroyuki Miyamoto Digital Equipment Corporation
miyamoto@jrd.dec.com
Hidetoshi Tajima(tajima@Eng.Sun.COM) Sun Microsystems, Inc.
This version tidied and debugged by Steve Underwood May 1999
******************************************************************/
/* Protocol Packet frames */
#include "FrameMgr.h"
/* Data type definitions */
static XimFrameRec ximattr_fr[] =
{
_FRAME(BIT16), /* attribute ID */
_FRAME(BIT16), /* type of the value */
_FRAME(BIT16), /* length of im-attribute */
_FRAME(BARRAY), /* im-attribute */
_PAD4(2),
_FRAME(EOL),
};
static XimFrameRec xicattr_fr[] =
{
_FRAME(BIT16), /* attribute ID */
_FRAME(BIT16), /* type of the value */
_FRAME(BIT16), /* length of ic-attribute */
_FRAME(BARRAY), /* ic-attribute */
_PAD4(2),
_FRAME(EOL),
};
static XimFrameRec ximattribute_fr[] =
{
_FRAME(BIT16), /* attribute ID */
_FRAME(BIT16), /* value length */
_FRAME(BARRAY), /* value */
_PAD4(1),
_FRAME(EOL),
};
static XimFrameRec xicattribute_fr[] =
{
_FRAME(BIT16), /* attribute ID */
_FRAME(BIT16), /* value length */
_FRAME(BARRAY), /* value */
_PAD4(1),
_FRAME(EOL),
};
static XimFrameRec ximtriggerkey_fr[] =
{
_FRAME(BIT32), /* keysym */
_FRAME(BIT32), /* modifier */
_FRAME(BIT32), /* modifier mask */
_FRAME(EOL),
};
static XimFrameRec encodinginfo_fr[] =
{
_FRAME(BIT16), /* length of encoding info */
_FRAME(BARRAY), /* encoding info */
_PAD4(2),
_FRAME(EOL),
};
static XimFrameRec str_fr[] =
{
_FRAME(BIT8), /* number of byte */
_FRAME(BARRAY), /* string */
_FRAME(EOL),
};
static XimFrameRec xpcs_fr[] =
{
_FRAME(BIT16), /* length of string in bytes */
_FRAME(BARRAY), /* string */
_PAD4(2),
};
static XimFrameRec ext_fr[] =
{
_FRAME(BIT8), /* extension major-opcode */
_FRAME(BIT8), /* extension minor-opcode */
_FRAME(BIT16), /* length of extension name */
_FRAME(BARRAY), /* extension name */
_PAD4(1),
_FRAME(EOL),
};
static XimFrameRec inputstyle_fr[] =
{
_FRAME(BIT32), /* inputstyle */
_FRAME(EOL),
};
/* Protocol definitions */
xim_externaldef XimFrameRec attr_head_fr[] =
{
_FRAME(BIT16), /* attribute id */
_FRAME(BIT16), /* attribute length */
_FRAME(EOL),
};
xim_externaldef XimFrameRec short_fr[] =
{
_FRAME(BIT16), /* value */
_FRAME(EOL),
};
xim_externaldef XimFrameRec long_fr[] =
{
_FRAME(BIT32), /* value */
_FRAME(EOL),
};
xim_externaldef XimFrameRec xrectangle_fr[] =
{
_FRAME(BIT16), /* x */
_FRAME(BIT16), /* y */
_FRAME(BIT16), /* width */
_FRAME(BIT16), /* height */
_FRAME(EOL),
};
xim_externaldef XimFrameRec xpoint_fr[] =
{
_FRAME(BIT16), /* x */
_FRAME(BIT16), /* y */
_FRAME(EOL),
};
xim_externaldef XimFrameRec fontset_fr[] =
{
_FRAME(BIT16), /* length of base font name */
_FRAME(BARRAY), /* base font name list */
_PAD4(2), /* unused */
_FRAME(EOL),
};
xim_externaldef XimFrameRec input_styles_fr[] =
{
_FRAME(BIT16), /* number of list */
_PAD4(1), /* unused */
_FRAME(ITER), /* XIMStyle list */
_FRAME(POINTER),
_PTR(inputstyle_fr),
_FRAME(EOL),
};
xim_externaldef XimFrameRec packet_header_fr[] =
{
_FRAME(BIT8), /* major-opcode */
_FRAME(BIT8), /* minor-opcode */
_FRAME(BIT16), /* length */
_FRAME(EOL),
};
xim_externaldef XimFrameRec error_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* input-context-ID */
_FRAME(BIT16), /* flag */
_FRAME(BIT16), /* Error Code */
_FRAME(BIT16), /* length of error detail */
_FRAME(BIT16), /* type of error detail */
_FRAME(BARRAY), /* error detail */
_PAD4(1),
_FRAME(EOL),
};
xim_externaldef XimFrameRec connect_fr[] =
{
_FRAME(BIT8), /* byte order */
_PAD2(1), /* unused */
_FRAME(BIT16), /* client-major-protocol-version */
_FRAME(BIT16), /* client-minor-protocol-version */
_BYTE_COUNTER(BIT16, 1), /* length of client-auth-protocol-names */
_FRAME(ITER), /* client-auth-protocol-names */
_FRAME(POINTER),
_PTR(xpcs_fr),
_FRAME(EOL),
};
xim_externaldef XimFrameRec connect_reply_fr[] =
{
_FRAME(BIT16), /* server-major-protocol-version */
_FRAME(BIT16), /* server-minor-protocol-version */
_FRAME(EOL),
};
xim_externaldef XimFrameRec auth_required_fr[] =
{
_FRAME(BIT8), /* auth-protocol-index */
_FRAME(BIT8), /* auth-data1 */
_FRAME(BARRAY), /* auth-data2 */
_PAD4(3),
_FRAME(EOL),
};
xim_externaldef XimFrameRec auth_reply_fr[] =
{
_FRAME(BIT8),
_FRAME(BARRAY),
_PAD4(2),
_FRAME(EOL),
};
xim_externaldef XimFrameRec auth_next_fr[] =
{
_FRAME(BIT8), /* auth-data1 */
_FRAME(BARRAY), /* auth-data2 */
_PAD4(2),
_FRAME(EOL),
};
xim_externaldef XimFrameRec auth_setup_fr[] =
{
_BYTE_COUNTER(BIT16, 2), /* number of client-auth-protocol-names */
_PAD4(1), /* unused */
_FRAME(ITER), /* server-auth-protocol-names */
_FRAME(POINTER),
_PTR(xpcs_fr),
_FRAME(EOL),
};
xim_externaldef XimFrameRec auth_ng_fr[] =
{
_FRAME(EOL),
};
xim_externaldef XimFrameRec disconnect_fr[] =
{
_FRAME(EOL),
};
xim_externaldef XimFrameRec disconnect_reply_fr[] =
{
_FRAME(EOL),
};
xim_externaldef XimFrameRec open_fr[] =
{
_FRAME(POINTER), /* locale name */
_PTR(str_fr),
_PAD4(1),
_FRAME(EOL),
};
xim_externaldef XimFrameRec open_reply_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_BYTE_COUNTER(BIT16, 1), /* byte length of IM attributes supported */
_FRAME(ITER), /* IM attribute supported */
_FRAME(POINTER),
_PTR(ximattr_fr),
_BYTE_COUNTER(BIT16, 2), /* number of IC attribute supported */
_PAD4(1), /* unused */
_FRAME(ITER), /* IC attribute supported */
_FRAME(POINTER),
_PTR(xicattr_fr),
_FRAME(EOL),
};
xim_externaldef XimFrameRec close_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_PAD4(1), /* unused */
_FRAME(EOL),
};
xim_externaldef XimFrameRec close_reply_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_PAD4(1), /* unused */
_FRAME(EOL),
};
xim_externaldef XimFrameRec register_triggerkeys_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_PAD4(1), /* unused */
_BYTE_COUNTER(BIT32, 1), /* byte length of on-keys */
_FRAME(ITER), /* on-keys list */
_FRAME(POINTER),
_PTR(ximtriggerkey_fr),
_BYTE_COUNTER(BIT32, 1), /* byte length of off-keys */
_FRAME(ITER), /* off-keys list */
_FRAME(POINTER),
_PTR(ximtriggerkey_fr),
_FRAME(EOL),
};
xim_externaldef XimFrameRec trigger_notify_fr[] =
{
_FRAME(BIT16), /* input-mehotd-ID */
_FRAME(BIT16), /* input-context-ID */
_FRAME(BIT32), /* flag */
_FRAME(BIT32), /* index of keys list */
_FRAME(BIT32), /* client-select-event-mask */
_FRAME(EOL),
};
xim_externaldef XimFrameRec trigger_notify_reply_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* input-context-ID */
_FRAME(EOL),
};
xim_externaldef XimFrameRec set_event_mask_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* input-context-ID */
_FRAME(BIT32), /* forward-event-mask */
_FRAME(BIT32), /* synchronous-event-mask */
_FRAME(EOL),
};
xim_externaldef XimFrameRec encoding_negotiation_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_BYTE_COUNTER(BIT16, 1), /* byte length of encodings listed by name */
_FRAME(ITER), /* supported list of encoding in IM library */
_FRAME(POINTER),
_PTR(str_fr),
_PAD4(1),
_BYTE_COUNTER(BIT16, 2), /* byte length of encodings listed by
detailed data */
_PAD4(1),
_FRAME(ITER), /* list of encodings supported in the
IM library */
_FRAME(POINTER),
_PTR(encodinginfo_fr),
_FRAME(EOL),
};
xim_externaldef XimFrameRec encoding_negotiation_reply_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* category of the encoding determined */
_FRAME(BIT16), /* index of the encoding dterminated */
_PAD4(1),
_FRAME(EOL),
};
xim_externaldef XimFrameRec query_extension_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_BYTE_COUNTER(BIT16, 1), /* byte length of extensions supported
by the IM library */
_FRAME(ITER), /* extensions supported by the IM library */
_FRAME(POINTER),
_PTR(str_fr),
_PAD4(1),
_FRAME(EOL),
};
xim_externaldef XimFrameRec query_extension_reply_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_BYTE_COUNTER(BIT16, 1), /* byte length of extensions supported
by the IM server */
_FRAME(ITER), /* list of extensions supported by the
IM server */
_FRAME(POINTER),
_PTR(ext_fr),
_FRAME(EOL),
};
xim_externaldef XimFrameRec get_im_values_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_BYTE_COUNTER(BIT16, 1), /* byte length of im-attribute-id */
_FRAME(ITER), /* im-attribute-id */
_FRAME(BIT16),
_PAD4(1),
_FRAME(EOL),
};
xim_externaldef XimFrameRec get_im_values_reply_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_BYTE_COUNTER(BIT16, 1), /* byte length of im-attribute returned */
_FRAME(ITER), /* im-attribute returned */
_FRAME(POINTER),
_PTR(ximattribute_fr),
_FRAME(EOL),
};
xim_externaldef XimFrameRec create_ic_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_BYTE_COUNTER(BIT16, 1), /* byte length of ic-attributes */
_FRAME(ITER), /* ic-attributes */
_FRAME(POINTER),
_PTR(xicattribute_fr),
_FRAME(EOL),
};
xim_externaldef XimFrameRec create_ic_reply_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* input-context-ID */
_FRAME(EOL),
};
xim_externaldef XimFrameRec destroy_ic_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* input-context-ID */
_FRAME(EOL),
};
xim_externaldef XimFrameRec destroy_ic_reply_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* input-context-ID */
_FRAME(EOL),
};
xim_externaldef XimFrameRec set_ic_values_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* input-context-ID */
_BYTE_COUNTER(BIT16, 2), /* byte length of ic-attributes */
_PAD4(1),
_FRAME(ITER), /* ic-attribute */
_FRAME(POINTER),
_PTR(xicattribute_fr),
_FRAME(EOL),
};
xim_externaldef XimFrameRec set_ic_values_reply_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* input-context-ID */
_FRAME(EOL),
};
xim_externaldef XimFrameRec get_ic_values_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* input-context-ID */
_BYTE_COUNTER(BIT16, 1), /* byte length of ic-attribute-id */
_FRAME(ITER), /* ic-attribute */
_FRAME(BIT16),
_PAD4(2),
_FRAME(EOL),
};
xim_externaldef XimFrameRec get_ic_values_reply_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* input-context-ID */
_BYTE_COUNTER(BIT16, 2), /* byte length of ic-attribute */
_PAD4(1),
_FRAME(ITER), /* ic-attribute */
_FRAME(POINTER),
_PTR(xicattribute_fr),
_FRAME(EOL),
};
xim_externaldef XimFrameRec set_ic_focus_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* input-context-ID */
_FRAME(EOL),
};
xim_externaldef XimFrameRec unset_ic_focus_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* input-context-ID */
_FRAME(EOL),
};
xim_externaldef XimFrameRec forward_event_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* input-context-ID */
_FRAME(BIT16), /* flag */
_FRAME(BIT16), /* sequence number */
_FRAME(EOL),
};
xim_externaldef XimFrameRec wire_keyevent_fr[] = {
_FRAME(BIT8), /* type */
_FRAME(BIT8), /* detail */
_FRAME(BIT16), /* serial number */
_FRAME(BIT32), /* time */
_FRAME(BIT32), /* root */
_FRAME(BIT32), /* window */
_FRAME(BIT32), /* subwindow */
_FRAME(BIT16), /* rootX */
_FRAME(BIT16), /* rootY */
_FRAME(BIT16), /* X */
_FRAME(BIT16), /* Y */
_FRAME(BIT16), /* state */
_FRAME(BIT8), /* sameScreen */
_FRAME(EOL),
};
xim_externaldef XimFrameRec sync_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* input-context-ID */
_FRAME(EOL),
};
xim_externaldef XimFrameRec sync_reply_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* input-context-ID */
_FRAME(EOL),
};
#if 0
xim_externaldef XimFrameRec commit_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* input-context-ID */
_FRAME(BIT16), /* flag */
_FRAME(BIT16), /* byte length of committed string */
_FRAME(BARRAY), /* committed string */
_PAD4(1),
_BYTE_COUNTER(BIT16, 1), /* byte length of keysym */
_FRAME(ITER), /* keysym */
_FRAME(BIT32),
_PAD4(1),
_FRAME(EOL),
};
#endif
xim_externaldef XimFrameRec commit_chars_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* input-context-ID */
_FRAME(BIT16), /* flag */
_FRAME(BIT16), /* byte length of committed string */
_FRAME(BARRAY), /* committed string */
_PAD4(1),
_FRAME(EOL),
};
xim_externaldef XimFrameRec commit_both_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* input-context-ID */
_FRAME(BIT16), /* flag */
_PAD4(1), /* unused */
_FRAME(BIT32), /* keysym */
_FRAME(BIT16), /* byte length of committed string */
_FRAME(BARRAY), /* committed string */
_PAD4(2),
_FRAME(EOL),
};
xim_externaldef XimFrameRec reset_ic_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* input-context-ID */
_FRAME(EOL),
};
xim_externaldef XimFrameRec reset_ic_reply_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* input-context-ID */
_FRAME(BIT16), /* byte length of committed string */
_FRAME(BARRAY), /* committed string */
_PAD4(2),
_FRAME(EOL),
};
xim_externaldef XimFrameRec geometry_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* input-context-ID */
_FRAME(EOL),
};
xim_externaldef XimFrameRec str_conversion_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* input-context-ID */
_FRAME(BIT32), /* XIMStringConversionPosition */
_FRAME(BIT32), /* XIMStringConversionType */
_FRAME(BIT32), /* XIMStringConversionOperation */
_FRAME(BIT16), /* length to multiply the
XIMStringConversionType */
_FRAME(BIT16), /* length of the string to be
substituted */
#if 0
_FRAME(BARRAY), /* string */
_PAD4(1),
#endif
_FRAME(EOL),
};
xim_externaldef XimFrameRec str_conversion_reply_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* input-context-ID */
_FRAME(BIT32), /* XIMStringConversionFeedback */
_FRAME(BIT16), /* length of the retrieved string */
_FRAME(BARRAY), /* retrieved string */
_PAD4(2),
_BYTE_COUNTER(BIT16, 2), /* number of feedback array */
_PAD4(1),
_FRAME(ITER), /* feedback array */
_FRAME(BIT32),
_FRAME(EOL),
};
xim_externaldef XimFrameRec preedit_start_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* input-context-ID */
_FRAME(EOL),
};
xim_externaldef XimFrameRec preedit_start_reply_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* input-context-ID */
_FRAME(BIT32), /* return value */
_FRAME(EOL),
};
xim_externaldef XimFrameRec preedit_draw_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* input-context-ID */
_FRAME(BIT32), /* caret */
_FRAME(BIT32), /* chg_first */
_FRAME(BIT32), /* chg_length */
_FRAME(BIT32), /* status */
_FRAME(BIT16), /* length of preedit string */
_FRAME(BARRAY), /* preedit string */
_PAD4(2),
_BYTE_COUNTER(BIT16, 2), /* number of feedback array */
_PAD4(1),
_FRAME(ITER), /* feedback array */
_FRAME(BIT32),
_FRAME(EOL),
};
xim_externaldef XimFrameRec preedit_caret_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* input-context-ID */
_FRAME(BIT32), /* position */
_FRAME(BIT32), /* direction */
_FRAME(BIT32), /* style */
_FRAME(EOL),
};
xim_externaldef XimFrameRec preedit_caret_reply_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* input-context-ID */
_FRAME(BIT32), /* position */
_FRAME(EOL),
};
xim_externaldef XimFrameRec preedit_done_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* input-context-ID */
_FRAME(EOL),
};
xim_externaldef XimFrameRec status_start_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* input-context-ID */
_FRAME(EOL),
};
xim_externaldef XimFrameRec status_draw_text_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* input-context-ID */
_FRAME(BIT32), /* type */
_FRAME(BIT32), /* status */
_FRAME(BIT16), /* length of status string */
_FRAME(BARRAY), /* status string */
_PAD4(2),
_BYTE_COUNTER(BIT16, 2), /* number of feedback array */
_PAD4(1),
_FRAME(ITER), /* feedback array */
_FRAME(BIT32),
_FRAME(EOL),
};
xim_externaldef XimFrameRec status_draw_bitmap_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* input-context-ID */
_FRAME(BIT32), /* type */
_FRAME(BIT32), /* pixmap data */
_FRAME(EOL),
};
xim_externaldef XimFrameRec status_done_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* input-context-ID */
_FRAME(EOL),
};
xim_externaldef XimFrameRec ext_set_event_mask_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* input-context-ID */
_FRAME(BIT32), /* filter-event-mask */
_FRAME(BIT32), /* intercept-event-mask */
_FRAME(BIT32), /* select-event-mask */
_FRAME(BIT32), /* forward-event-mask */
_FRAME(BIT32), /* synchronous-event-mask */
_FRAME(EOL),
};
xim_externaldef XimFrameRec ext_forward_keyevent_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* input-context-ID */
_FRAME(BIT16), /* flag */
_FRAME(BIT16), /* sequence number */
_FRAME(BIT8), /* xEvent.u.u.type */
_FRAME(BIT8), /* keycode */
_FRAME(BIT16), /* state */
_FRAME(BIT32), /* time */
_FRAME(BIT32), /* window */
_FRAME(EOL),
};
xim_externaldef XimFrameRec ext_move_fr[] =
{
_FRAME(BIT16), /* input-method-ID */
_FRAME(BIT16), /* input-context-ID */
_FRAME(BIT16), /* X */
_FRAME(BIT16), /* Y */
_FRAME(EOL),
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,537 @@
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
/******************************************************************
Copyright 1994, 1995 by Sun Microsystems, Inc.
Copyright 1993, 1994 by Hewlett-Packard Company
Permission to use, copy, modify, distribute, and sell this software
and its documentation for any purpose is hereby granted without fee,
provided that the above copyright notice appear in all copies and
that both that copyright notice and this permission notice appear
in supporting documentation, and that the name of Sun Microsystems, Inc.
and Hewlett-Packard not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior permission.
Sun Microsystems, Inc. and Hewlett-Packard make no representations about
the suitability of this software for any purpose. It is provided "as is"
without express or implied warranty.
SUN MICROSYSTEMS INC. AND HEWLETT-PACKARD COMPANY DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
SUN MICROSYSTEMS, INC. AND HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Author: Hidetoshi Tajima(tajima@Eng.Sun.COM) Sun Microsystems, Inc.
This version tidied and debugged by Steve Underwood May 1999
******************************************************************/
#include "i18nMethod.h"
#include "FrameMgr.h"
#include "Xi18n.h"
#include "XimFunc.h"
#include <glib.h>
/* How to generate SUPPORTED_LOCALES
#!/usr/bin/ruby
# -*- coding: utf-8 -*-
require 'set'
set = Set.new
File.open("/usr/share/i18n/SUPPORTED", "r").each do |line|
set << line.split(/_| /)[0]
end
puts set.to_a.join(",")
*/
#define SUPPORTED_LOCALES \
"aa,af,agr,ak,am,an,anp,ar,ayc,az,as,ast,be,bem,ber,bg,bhb,bho,bi,bn,bo," \
"br,brx,bs,byn,ca,ce,chr,cmn,crh,cs,csb,cv,cy,da,de,doi,dsb,dv,dz,el,en," \
"eo,es,et,eu,fa,ff,fi,fil,fo,fr,fur,fy,ga,gd,gez,gl,gu,gv,ha,hak,he,hi," \
"hif,hne,hr,hsb,ht,hu,hy,ia,id,ig,ik,is,it,iu,ja,ka,kab,kk,kl,km,kn,ko," \
"kok,ks,ku,kw,ky,lb,lg,li,lij,ln,lo,lt,lv,lzh,mag,mai,mfe,mg,mhr,mi,miq," \
"mjw,mk,ml,mn,mni,mr,ms,mt,my,nan,nb,nds,ne,nhn,niu,nl,nn,nr,nso,oc,om,or," \
"os,pa,pap,pl,ps,pt,quz,raj,ro,ru,rw,sa,sah,sat,sc,sd,se,sgs,shn,shs,si," \
"sid,sk,sl,sm,so,sq,sr,ss,st,sv,sw,szl,ta,tcy,te,tg,th,the,ti,tig,tk,tl," \
"tn,to,tpi,tr,ts,tt,ug,uk,unm,ur,uz,ve,vi,wa,wae,wal,wo,xh,yi,yo,yue,yuw," \
"zh,zu"
extern Xi18nClient *_Xi18nFindClient (NimfXim *, CARD16);
#ifndef XIM_SERVERS
#define XIM_SERVERS "XIM_SERVERS"
#endif
static Atom XIM_Servers = None;
static int SetXi18nSelectionOwner (NimfXim *xim, Window im_window)
{
Window root = RootWindow (xim->display, DefaultScreen (xim->display));
Atom realtype;
int realformat;
unsigned long bytesafter;
long *data=NULL;
unsigned long length;
Atom atom;
int i;
int found;
int forse = False;
if ((atom = XInternAtom (xim->display, "@server=nimf", False)) == 0)
return False;
xim->address.selection = atom;
if (XIM_Servers == None)
XIM_Servers = XInternAtom (xim->display, XIM_SERVERS, False);
/*endif*/
XGetWindowProperty (xim->display,
root,
XIM_Servers,
0L,
1000000L,
False,
XA_ATOM,
&realtype,
&realformat,
&length,
&bytesafter,
(unsigned char **) (&data));
if (realtype != None && (realtype != XA_ATOM || realformat != 32)) {
if (data != NULL)
XFree ((char *) data);
return False;
}
found = False;
for (i = 0; i < length; i++) {
if (data[i] == atom) {
Window owner;
found = True;
if ((owner = XGetSelectionOwner (xim->display, atom)) != im_window) {
if (owner == None || forse == True)
XSetSelectionOwner (xim->display, atom, im_window, CurrentTime);
else
return False;
}
break;
}
}
if (found == False) {
XSetSelectionOwner (xim->display, atom, im_window, CurrentTime);
XChangeProperty (xim->display,
root,
XIM_Servers,
XA_ATOM,
32,
PropModePrepend,
(unsigned char *) &atom,
1);
}
else {
/*
* We always need to generate the PropertyNotify to the Root Window
*/
XChangeProperty (xim->display,
root,
XIM_Servers,
XA_ATOM,
32,
PropModePrepend,
(unsigned char *) data,
0);
}
if (data != NULL)
XFree ((char *) data);
/* Intern "LOCALES" and "TRANSOPORT" Target Atoms */
xim->address.Localename = XInternAtom (xim->display, LOCALES, False);
xim->address.Transportname = XInternAtom (xim->display, TRANSPORT, False);
return (XGetSelectionOwner (xim->display, atom) == im_window);
}
static int DeleteXi18nAtom (NimfXim *xim)
{
Window root = RootWindow (xim->display, DefaultScreen (xim->display));
Atom realtype;
int realformat;
unsigned long bytesafter;
long *data=NULL;
unsigned long length;
Atom atom;
int i, ret;
int found;
if ((atom = XInternAtom (xim->display, "@server=nimf", False)) == 0)
return False;
xim->address.selection = atom;
if (XIM_Servers == None)
XIM_Servers = XInternAtom (xim->display, XIM_SERVERS, False);
XGetWindowProperty (xim->display,
root,
XIM_Servers,
0L,
1000000L,
False,
XA_ATOM,
&realtype,
&realformat,
&length,
&bytesafter,
(unsigned char **) (&data));
if (realtype != XA_ATOM || realformat != 32) {
if (data != NULL)
XFree ((char *) data);
return False;
}
found = False;
for (i = 0; i < length; i++) {
if (data[i] == atom) {
found = True;
break;
}
}
if (found == True) {
for (i=i+1; i<length; i++)
data[i-1] = data[i];
XChangeProperty (xim->display,
root,
XIM_Servers,
XA_ATOM,
32,
PropModeReplace,
(unsigned char *)data,
length-1);
ret = True;
}
else {
XChangeProperty (xim->display,
root,
XIM_Servers,
XA_ATOM,
32,
PropModePrepend,
(unsigned char *)data,
0);
ret = False;
}
if (data != NULL)
XFree ((char *) data);
return ret;
}
static void
ReturnSelectionNotify (NimfXim *xim, XSelectionRequestEvent *ev)
{
XEvent event;
const char *data = NULL;
event.type = SelectionNotify;
event.xselection.requestor = ev->requestor;
event.xselection.selection = ev->selection;
event.xselection.target = ev->target;
event.xselection.time = ev->time;
event.xselection.property = ev->property;
if (ev->target == xim->address.Localename)
data = "@locale=C" SUPPORTED_LOCALES;
else if (ev->target == xim->address.Transportname)
data = "@transport=X/";
XChangeProperty (xim->display,
event.xselection.requestor,
ev->target,
ev->target,
8,
PropModeReplace,
(unsigned char *) data,
strlen (data));
XSendEvent (xim->display, event.xselection.requestor, False, NoEventMask, &event);
XFlush (xim->display);
}
Bool
WaitXSelectionRequest (NimfXim *xim,
XEvent *ev)
{
if (((XSelectionRequestEvent *) ev)->selection == xim->address.selection)
{
ReturnSelectionNotify (xim, (XSelectionRequestEvent *) ev);
return True;
}
return False;
}
Status
xi18n_openIM (NimfXim *xim, Window im_window)
{
if (!SetXi18nSelectionOwner (xim, im_window))
return False;
xim->_protocol = XInternAtom (xim->display, "_XIM_PROTOCOL", False);
xim->_xconnect = XInternAtom (xim->display, "_XIM_XCONNECT", False);
XFlush (xim->display);
return True;
}
Status xi18n_closeIM (NimfXim *xim)
{
DeleteXi18nAtom (xim);
return True;
}
static void EventToWireEvent (XEvent *ev, xEvent *event,
CARD16 *serial, Bool byte_swap)
{
FrameMgr fm;
extern XimFrameRec wire_keyevent_fr[];
extern XimFrameRec short_fr[];
BYTE b;
CARD16 c16;
CARD32 c32;
*serial = (CARD16)(ev->xany.serial >> 16);
switch (ev->type) {
case KeyPress:
case KeyRelease:
{
XKeyEvent *kev = (XKeyEvent*)ev;
/* create FrameMgr */
fm = FrameMgrInit(wire_keyevent_fr, (char *)(&(event->u)), byte_swap);
/* set values */
b = (BYTE)kev->type; FrameMgrPutToken(fm, b);
b = (BYTE)kev->keycode; FrameMgrPutToken(fm, b);
c16 = (CARD16)(kev->serial & (unsigned long)0xffff);
FrameMgrPutToken(fm, c16);
c32 = (CARD32)kev->time; FrameMgrPutToken(fm, c32);
c32 = (CARD32)kev->root; FrameMgrPutToken(fm, c32);
c32 = (CARD32)kev->window; FrameMgrPutToken(fm, c32);
c32 = (CARD32)kev->subwindow; FrameMgrPutToken(fm, c32);
c16 = (CARD16)kev->x_root; FrameMgrPutToken(fm, c16);
c16 = (CARD16)kev->y_root; FrameMgrPutToken(fm, c16);
c16 = (CARD16)kev->x; FrameMgrPutToken(fm, c16);
c16 = (CARD16)kev->y; FrameMgrPutToken(fm, c16);
c16 = (CARD16)kev->state; FrameMgrPutToken(fm, c16);
b = (BYTE)kev->same_screen; FrameMgrPutToken(fm, b);
}
break;
default:
/* create FrameMgr */
fm = FrameMgrInit(short_fr, (char *)(&(event->u.u.sequenceNumber)),
byte_swap);
c16 = (CARD16)(ev->xany.serial & (unsigned long)0xffff);
FrameMgrPutToken(fm, c16);
break;
}
/* free FrameMgr */
FrameMgrFree(fm);
}
Status xi18n_forwardEvent (NimfXim *xim, XPointer xp)
{
IMForwardEventStruct *call_data = (IMForwardEventStruct *)xp;
FrameMgr fm;
extern XimFrameRec forward_event_fr[];
register int total_size;
unsigned char *reply = NULL;
unsigned char *replyp;
CARD16 serial;
int event_size;
Xi18nClient *client;
client = (Xi18nClient *) _Xi18nFindClient (xim, call_data->connect_id);
/* create FrameMgr */
fm = FrameMgrInit (forward_event_fr,
NULL,
_Xi18nNeedSwap (xim, call_data->connect_id));
total_size = FrameMgrGetTotalSize (fm);
event_size = sizeof (xEvent);
reply = (unsigned char *) malloc (total_size + event_size);
if (!reply)
{
_Xi18nSendMessage (xim,
call_data->connect_id,
XIM_ERROR,
0,
0,
0);
return False;
}
/*endif*/
memset (reply, 0, total_size + event_size);
FrameMgrSetBuffer (fm, reply);
replyp = reply;
call_data->sync_bit = 1; /* always sync */
client->sync = True;
FrameMgrPutToken (fm, call_data->connect_id);
FrameMgrPutToken (fm, call_data->icid);
FrameMgrPutToken (fm, call_data->sync_bit);
replyp += total_size;
EventToWireEvent (&(call_data->event),
(xEvent *) replyp,
&serial,
_Xi18nNeedSwap (xim, call_data->connect_id));
FrameMgrPutToken (fm, serial);
_Xi18nSendMessage (xim,
call_data->connect_id,
XIM_FORWARD_EVENT,
0,
reply,
total_size + event_size);
XFree (reply);
FrameMgrFree (fm);
return True;
}
Status xi18n_commit (NimfXim *xim, XPointer xp)
{
IMCommitStruct *call_data = (IMCommitStruct *)xp;
FrameMgr fm;
extern XimFrameRec commit_chars_fr[];
extern XimFrameRec commit_both_fr[];
register int total_size;
unsigned char *reply = NULL;
CARD16 str_length;
call_data->flag |= XimSYNCHRONUS; /* always sync */
if (!(call_data->flag & XimLookupKeySym)
&&
(call_data->flag & XimLookupChars))
{
fm = FrameMgrInit (commit_chars_fr,
NULL,
_Xi18nNeedSwap (xim, call_data->connect_id));
/* set length of STRING8 */
str_length = strlen (call_data->commit_string);
FrameMgrSetSize (fm, str_length);
total_size = FrameMgrGetTotalSize (fm);
reply = (unsigned char *) malloc (total_size);
if (!reply)
{
_Xi18nSendMessage (xim,
call_data->connect_id,
XIM_ERROR,
0,
0,
0);
return False;
}
/*endif*/
memset (reply, 0, total_size);
FrameMgrSetBuffer (fm, reply);
str_length = FrameMgrGetSize (fm);
FrameMgrPutToken (fm, call_data->connect_id);
FrameMgrPutToken (fm, call_data->icid);
FrameMgrPutToken (fm, call_data->flag);
FrameMgrPutToken (fm, str_length);
FrameMgrPutToken (fm, call_data->commit_string);
}
else
{
fm = FrameMgrInit (commit_both_fr,
NULL,
_Xi18nNeedSwap (xim, call_data->connect_id));
/* set length of STRING8 */
str_length = strlen (call_data->commit_string);
if (str_length > 0)
FrameMgrSetSize (fm, str_length);
/*endif*/
total_size = FrameMgrGetTotalSize (fm);
reply = (unsigned char *) malloc (total_size);
if (!reply)
{
_Xi18nSendMessage (xim,
call_data->connect_id,
XIM_ERROR,
0,
0,
0);
return False;
}
/*endif*/
FrameMgrSetBuffer (fm, reply);
FrameMgrPutToken (fm, call_data->connect_id);
FrameMgrPutToken (fm, call_data->icid);
FrameMgrPutToken (fm, call_data->flag);
FrameMgrPutToken (fm, call_data->keysym);
if (str_length > 0)
{
str_length = FrameMgrGetSize (fm);
FrameMgrPutToken (fm, str_length);
FrameMgrPutToken (fm, call_data->commit_string);
}
/*endif*/
}
/*endif*/
_Xi18nSendMessage (xim,
call_data->connect_id,
XIM_COMMIT,
0,
reply,
total_size);
FrameMgrFree (fm);
XFree (reply);
return True;
}
int nimf_xim_call_callback (NimfXim *xim, XPointer xp)
{
IMProtocol *call_data = (IMProtocol *)xp;
switch (call_data->major_code)
{
case XIM_GEOMETRY:
return _Xi18nGeometryCallback (xim, call_data);
case XIM_PREEDIT_START:
return _Xi18nPreeditStartCallback (xim, call_data);
case XIM_PREEDIT_DRAW:
return _Xi18nPreeditDrawCallback (xim, call_data);
case XIM_PREEDIT_CARET:
return _Xi18nPreeditCaretCallback (xim, call_data);
case XIM_PREEDIT_DONE:
return _Xi18nPreeditDoneCallback (xim, call_data);
case XIM_STATUS_START:
return _Xi18nStatusStartCallback (xim, call_data);
case XIM_STATUS_DRAW:
return _Xi18nStatusDrawCallback (xim, call_data);
case XIM_STATUS_DONE:
return _Xi18nStatusDoneCallback (xim, call_data);
case XIM_STR_CONVERSION:
return _Xi18nStringConversionCallback (xim, call_data);
}
/*endswitch*/
return False;
}

View File

@@ -0,0 +1,54 @@
/******************************************************************
Copyright 1994, 1995 by Sun Microsystems, Inc.
Copyright 1993, 1994 by Hewlett-Packard Company
Permission to use, copy, modify, distribute, and sell this software
and its documentation for any purpose is hereby granted without fee,
provided that the above copyright notice appear in all copies and
that both that copyright notice and this permission notice appear
in supporting documentation, and that the name of Sun Microsystems, Inc.
and Hewlett-Packard not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior permission.
Sun Microsystems, Inc. and Hewlett-Packard make no representations about
the suitability of this software for any purpose. It is provided "as is"
without express or implied warranty.
SUN MICROSYSTEMS INC. AND HEWLETT-PACKARD COMPANY DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
SUN MICROSYSTEMS, INC. AND HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Author: Hidetoshi Tajima(tajima@Eng.Sun.COM) Sun Microsystems, Inc.
This version tidied and debugged by Steve Underwood May 1999
******************************************************************/
#ifndef I18N_METHOD_H
#define I18N_METHOD_H
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#ifndef NEED_EVENTS
#define NEED_EVENTS
#endif
#include <X11/Xproto.h>
#undef NEED_EVENTS
#include "nimf-xim.h"
Bool WaitXSelectionRequest (NimfXim *xim, XEvent *ev);
int nimf_xim_call_callback (NimfXim *, XPointer);
Status xi18n_openIM (NimfXim *, Window);
Status xi18n_closeIM (NimfXim *);
Status xi18n_forwardEvent (NimfXim *, XPointer);
Status xi18n_commit (NimfXim *, XPointer);
int xi18n_syncXlib (NimfXim *, XPointer);
#endif /* I18N_METHOD_H */

View File

@@ -0,0 +1,97 @@
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
/*
* Copyright (C) 2014 Peng Huang <shawn.p.huang@gmail.com>
* Copyright (C) 2014 Red Hat, Inc.
*
* Permission to use, copy, modify, distribute, and sell this
* software and its documentation for any purpose is hereby granted
* without fee, provided that the above copyright notice appear in
* all copies and that both that copyright notice and this permission
* notice appear in supporting documentation, and that the name of
* the copyright holders not be used in advertising or publicity
* pertaining to distribution of the software without specific,
* written prior permission. The copyright holders make no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied
* warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
* THIS SOFTWARE.
*
* Author: Klemens Baum <klemensbaum@gmail.com>
*/
#include <X11/Xlib.h>
#include <stddef.h>
#include "Xi18n.h"
/*
* The XIM specification does not limit the number of window properties
* that can be used to transfer data, but Xlib uses the atom strings
* _client0 through _client20.
*
* So use that as a sensible initial size for the offset cache.
*/
#define INITIAL_OFFSET_CACHE_CAPACITY 21
#define OFFSET_CACHE_GROWTH_FACTOR 2
void _Xi18nInitOffsetCache (Xi18nOffsetCache *offset_cache)
{
offset_cache->size = 0;
offset_cache->capacity = INITIAL_OFFSET_CACHE_CAPACITY;
offset_cache->data = (Xi18nAtomOffsetPair *) malloc (
INITIAL_OFFSET_CACHE_CAPACITY * sizeof (Xi18nAtomOffsetPair));
}
unsigned long _Xi18nLookupPropertyOffset (Xi18nOffsetCache *offset_cache,
Atom key)
{
Xi18nAtomOffsetPair *data;
size_t i;
data = offset_cache->data;
for (i = 0; i < offset_cache->size; ++i) {
if (data[i].key == key) {
return data[i].offset;
}
}
return 0;
}
void _Xi18nSetPropertyOffset (Xi18nOffsetCache *offset_cache, Atom key,
unsigned long offset)
{
Xi18nAtomOffsetPair *data = offset_cache->data;
size_t i;
for (i = 0; i < offset_cache->size; ++i) {
if (data[i].key == key) {
data[i].offset = offset;
return;
}
}
if (++offset_cache->size > offset_cache->capacity) {
offset_cache->capacity *= OFFSET_CACHE_GROWTH_FACTOR;
offset_cache->data = (Xi18nAtomOffsetPair *) realloc (data,
offset_cache->capacity * sizeof (Xi18nAtomOffsetPair));
if (offset_cache->data == NULL) {
offset_cache->data = data;
--offset_cache->size;
}
data = offset_cache->data;
}
if (offset_cache->size > 0) {
data[i].key = key;
data[i].offset = offset;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,215 @@
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
/******************************************************************
Copyright (C) 1994-1995 Sun Microsystems, Inc.
Copyright (C) 1993-1994 Hewlett-Packard Company
Copyright (C) 2014 Peng Huang <shawn.p.huang@gmail.com>
Copyright (C) 2014 Red Hat, Inc.
Permission to use, copy, modify, distribute, and sell this software
and its documentation for any purpose is hereby granted without fee,
provided that the above copyright notice appear in all copies and
that both that copyright notice and this permission notice appear
in supporting documentation, and that the name of Sun Microsystems, Inc.
and Hewlett-Packard not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior permission.
Sun Microsystems, Inc. and Hewlett-Packard make no representations about
the suitability of this software for any purpose. It is provided "as is"
without express or implied warranty.
SUN MICROSYSTEMS INC. AND HEWLETT-PACKARD COMPANY DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
SUN MICROSYSTEMS, INC. AND HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Author: Hidetoshi Tajima(tajima@Eng.Sun.COM) Sun Microsystems, Inc.
This version tidied and debugged by Steve Underwood May 1999
******************************************************************/
#include <X11/Xlib.h>
#include "Xi18n.h"
#include "FrameMgr.h"
#include "XimFunc.h"
#include "nimf-xim.h"
#include "i18nX.h"
Xi18nClient *_Xi18nFindClient (NimfXim *, CARD16);
void _Xi18nInitOffsetCache (Xi18nOffsetCache *);
int
_Xi18nNeedSwap (NimfXim *xim, CARD16 connect_id)
{
Xi18nClient *client = _Xi18nFindClient (xim, connect_id);
return (client->byte_order != xim->byte_order);
}
Xi18nClient *_Xi18nNewClient (NimfXim *xim)
{
static CARD16 connect_id = 0;
int new_connect_id;
Xi18nClient *client;
if (xim->address.free_clients)
{
client = xim->address.free_clients;
xim->address.free_clients = client->next;
new_connect_id = client->connect_id;
}
else
{
client = (Xi18nClient *) malloc (sizeof (Xi18nClient));
new_connect_id = ++connect_id;
}
/*endif*/
memset (client, 0, sizeof (Xi18nClient));
client->connect_id = new_connect_id;
client->pending = (XIMPending *) NULL;
client->sync = False;
client->byte_order = '?'; /* initial value */
memset (&client->pending, 0, sizeof (XIMPending *));
_Xi18nInitOffsetCache (&client->offset_cache);
client->next = xim->address.clients;
xim->address.clients = client;
return (Xi18nClient *) client;
}
Xi18nClient *_Xi18nFindClient (NimfXim *xim, CARD16 connect_id)
{
Xi18nClient *client = xim->address.clients;
while (client)
{
if (client->connect_id == connect_id)
return client;
/*endif*/
client = client->next;
}
/*endwhile*/
return NULL;
}
void _Xi18nDeleteClient (NimfXim *xim, CARD16 connect_id)
{
Xi18nClient *target = _Xi18nFindClient (xim, connect_id);
Xi18nClient *ccp;
Xi18nClient *ccp0;
for (ccp = xim->address.clients, ccp0 = NULL;
ccp != NULL;
ccp0 = ccp, ccp = ccp->next)
{
if (ccp == target)
{
if (ccp0 == NULL)
xim->address.clients = ccp->next;
else
ccp0->next = ccp->next;
/*endif*/
/* put it back to free list */
target->next = xim->address.free_clients;
xim->address.free_clients = target;
return;
}
/*endif*/
}
/*endfor*/
}
void _Xi18nSendMessage (NimfXim *xim,
CARD16 connect_id,
CARD8 major_opcode,
CARD8 minor_opcode,
unsigned char *data,
long length)
{
FrameMgr fm;
extern XimFrameRec packet_header_fr[];
unsigned char *reply_hdr = NULL;
int header_size;
unsigned char *reply = NULL;
unsigned char *replyp;
int reply_length;
long p_len = length/4;
fm = FrameMgrInit (packet_header_fr,
NULL,
_Xi18nNeedSwap (xim, connect_id));
header_size = FrameMgrGetTotalSize (fm);
reply_hdr = (unsigned char *) malloc (header_size);
if (reply_hdr == NULL)
{
_Xi18nSendMessage (xim, connect_id, XIM_ERROR, 0, 0, 0);
return;
}
/*endif*/
FrameMgrSetBuffer (fm, reply_hdr);
/* put data */
FrameMgrPutToken (fm, major_opcode);
FrameMgrPutToken (fm, minor_opcode);
FrameMgrPutToken (fm, p_len);
reply_length = header_size + length;
reply = (unsigned char *) malloc (reply_length);
replyp = reply;
memmove (reply, reply_hdr, header_size);
replyp += header_size;
if (length > 0 && data != NULL)
memmove (replyp, data, length);
Xi18nXSend (xim, connect_id, reply, reply_length);
XFree (reply);
XFree (reply_hdr);
FrameMgrFree (fm);
}
void _Xi18nSetEventMask (NimfXim *xim,
CARD16 connect_id,
CARD16 im_id,
CARD16 ic_id,
CARD32 forward_mask,
CARD32 sync_mask)
{
FrameMgr fm;
extern XimFrameRec set_event_mask_fr[];
unsigned char *reply = NULL;
register int total_size;
fm = FrameMgrInit (set_event_mask_fr,
NULL,
_Xi18nNeedSwap (xim, connect_id));
total_size = FrameMgrGetTotalSize (fm);
reply = (unsigned char *) malloc (total_size);
if (!reply)
return;
/*endif*/
memset (reply, 0, total_size);
FrameMgrSetBuffer (fm, reply);
FrameMgrPutToken (fm, im_id); /* input-method-id */
FrameMgrPutToken (fm, ic_id); /* input-context-id */
FrameMgrPutToken (fm, forward_mask);
FrameMgrPutToken (fm, sync_mask);
_Xi18nSendMessage (xim,
connect_id,
XIM_SET_EVENT_MASK,
0,
reply,
total_size);
FrameMgrFree (fm);
XFree(reply);
}

View File

@@ -0,0 +1,419 @@
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
/******************************************************************
Copyright (C) 1994-1995 Sun Microsystems, Inc.
Copyright (C) 1993-1994 Hewlett-Packard Company
Copyright (C) 2014 Peng Huang <shawn.p.huang@gmail.com>
Copyright (C) 2014 Red Hat, Inc.
Permission to use, copy, modify, distribute, and sell this software
and its documentation for any purpose is hereby granted without fee,
provided that the above copyright notice appear in all copies and
that both that copyright notice and this permission notice appear
in supporting documentation, and that the name of Sun Microsystems, Inc.
and Hewlett-Packard not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior permission.
Sun Microsystems, Inc. and Hewlett-Packard make no representations about
the suitability of this software for any purpose. It is provided "as is"
without express or implied warranty.
SUN MICROSYSTEMS INC. AND HEWLETT-PACKARD COMPANY DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
SUN MICROSYSTEMS, INC. AND HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Author: Hidetoshi Tajima(tajima@Eng.Sun.COM) Sun Microsystems, Inc.
This version tidied and debugged by Steve Underwood May 1999
******************************************************************/
#include "i18nX.h"
#include "FrameMgr.h"
#include "Xi18n.h"
#include "XimFunc.h"
extern Xi18nClient *_Xi18nFindClient (NimfXim *, CARD16);
extern Xi18nClient *_Xi18nNewClient (NimfXim *);
extern void _Xi18nDeleteClient (NimfXim *, CARD16);
extern unsigned long _Xi18nLookupPropertyOffset (Xi18nOffsetCache *, Atom);
extern void _Xi18nSetPropertyOffset (Xi18nOffsetCache *, Atom, unsigned long);
#define XCM_DATA_LIMIT 20
typedef struct _XClient
{
Window client_win; /* client window */
Window accept_win; /* accept window */
} XClient;
static XClient *NewXClient (NimfXim *xim, Window new_client)
{
Xi18nClient *client = _Xi18nNewClient (xim);
XClient *x_client;
x_client = (XClient *) malloc (sizeof (XClient));
x_client->client_win = new_client;
x_client->accept_win = XCreateSimpleWindow (xim->display,
DefaultRootWindow (xim->display),
0, 0, 1, 1, 0, 0, 0);
client->trans_rec = x_client;
return ((XClient *) x_client);
}
static unsigned char *ReadXIMMessage (NimfXim *xim,
XClientMessageEvent *ev,
int *connect_id)
{
Xi18nClient *client = xim->address.clients;
XClient *x_client = NULL;
FrameMgr fm;
extern XimFrameRec packet_header_fr[];
unsigned char *p = NULL;
unsigned char *p1;
while (client != NULL) {
x_client = (XClient *) client->trans_rec;
if (x_client->accept_win == ev->window) {
*connect_id = client->connect_id;
break;
}
client = client->next;
}
if (ev->format == 8) {
/* ClientMessage only */
XimProtoHdr *hdr = (XimProtoHdr *) ev->data.b;
unsigned char *rec = (unsigned char *) (hdr + 1);
register int total_size;
CARD8 major_opcode;
CARD8 minor_opcode;
CARD16 length;
extern int _Xi18nNeedSwap (NimfXim *, CARD16);
if (client->byte_order == '?')
{
if (hdr->major_opcode != XIM_CONNECT)
return (unsigned char *) NULL; /* can do nothing */
client->byte_order = (CARD8) rec[0];
}
fm = FrameMgrInit (packet_header_fr,
(char *) hdr,
_Xi18nNeedSwap (xim, *connect_id));
total_size = FrameMgrGetTotalSize (fm);
/* get data */
FrameMgrGetToken (fm, major_opcode);
FrameMgrGetToken (fm, minor_opcode);
FrameMgrGetToken (fm, length);
FrameMgrFree (fm);
if ((p = (unsigned char *) malloc (total_size + length * 4)) == NULL)
return (unsigned char *) NULL;
p1 = p;
memmove (p1, &major_opcode, sizeof (CARD8));
p1 += sizeof (CARD8);
memmove (p1, &minor_opcode, sizeof (CARD8));
p1 += sizeof (CARD8);
memmove (p1, &length, sizeof (CARD16));
p1 += sizeof (CARD16);
memmove (p1, rec, length * 4);
}
else if (ev->format == 32) {
/* ClientMessage and WindowProperty */
unsigned long length = (unsigned long) ev->data.l[0];
Atom atom = (Atom) ev->data.l[1];
int return_code;
Atom actual_type_ret;
int actual_format_ret;
unsigned long bytes_after_ret;
unsigned char *prop;
unsigned long nitems;
Xi18nOffsetCache *offset_cache = &client->offset_cache;
unsigned long offset;
unsigned long end;
unsigned long long_begin;
unsigned long long_end;
if (length == 0) {
fprintf (stderr, "%s: invalid length 0\n", __func__);
return NULL;
}
offset = _Xi18nLookupPropertyOffset (offset_cache, atom);
end = offset + length;
/* The property data is retrieved in 32-bit chunks */
long_begin = offset / 4;
long_end = (end + 3) / 4;
return_code = XGetWindowProperty (xim->display,
x_client->accept_win,
atom,
long_begin,
long_end - long_begin,
True,
AnyPropertyType,
&actual_type_ret,
&actual_format_ret,
&nitems,
&bytes_after_ret,
&prop);
if (return_code != Success || actual_format_ret == 0 || nitems == 0) {
if (return_code == Success)
XFree (prop);
fprintf (stderr,
"(XIM-IMdkit) ERROR: XGetWindowProperty failed.\n"
"Protocol data is likely to be inconsistent.\n");
_Xi18nSetPropertyOffset (offset_cache, atom, 0);
return (unsigned char *) NULL;
}
/* Update the offset to read next time as needed */
if (bytes_after_ret > 0)
_Xi18nSetPropertyOffset (offset_cache, atom, offset + length);
else
_Xi18nSetPropertyOffset (offset_cache, atom, 0);
/* if hit, it might be an error */
if ((p = (unsigned char *) malloc (length)) == NULL)
return (unsigned char *) NULL;
memcpy (p, prop + (offset % 4), length);
XFree (prop);
}
return (unsigned char *) p;
}
void ReadXConnectMessage (NimfXim *xim, XClientMessageEvent *ev)
{
XEvent event;
Window new_client = ev->data.l[0];
CARD32 major_version = ev->data.l[1];
CARD32 minor_version = ev->data.l[2];
XClient *x_client = NewXClient (xim, new_client);
if (ev->window != xim->im_window)
return; /* incorrect connection request */
if (major_version != 0 || minor_version != 0)
{
major_version =
minor_version = 0;
/* Only supporting only-CM & Property-with-CM method */
}
/*endif*/
event.xclient.type = ClientMessage;
event.xclient.display = xim->display;
event.xclient.window = new_client;
event.xclient.message_type = xim->_xconnect;
event.xclient.format = 32;
event.xclient.data.l[0] = x_client->accept_win;
event.xclient.data.l[1] = major_version;
event.xclient.data.l[2] = minor_version;
event.xclient.data.l[3] = XCM_DATA_LIMIT;
XSendEvent (xim->display,
new_client,
False,
NoEventMask,
&event);
XFlush (xim->display);
}
static char *MakeNewAtom (CARD16 connect_id, char *atomName)
{
static uint8_t sequence = 0;
sprintf (atomName,
"_server%d_%d",
connect_id,
((sequence > 20) ? (sequence = 0) : (0x1f & sequence)));
sequence++;
return atomName;
}
Bool Xi18nXSend (NimfXim *xim,
CARD16 connect_id,
unsigned char *reply,
long length)
{
Xi18nClient *client = _Xi18nFindClient (xim, connect_id);
XClient *x_client = (XClient *) client->trans_rec;
XEvent event;
event.type = ClientMessage;
event.xclient.window = x_client->client_win;
event.xclient.message_type = xim->_protocol;
if (length > XCM_DATA_LIMIT)
{
Atom atom;
char atomName[16];
Atom actual_type_ret;
int actual_format_ret;
int return_code;
unsigned long nitems_ret;
unsigned long bytes_after_ret;
unsigned char *win_data;
event.xclient.format = 32;
atom = XInternAtom (xim->display,
MakeNewAtom (connect_id, atomName),
False);
return_code = XGetWindowProperty (xim->display,
x_client->client_win,
atom,
0L,
10000L,
False,
XA_STRING,
&actual_type_ret,
&actual_format_ret,
&nitems_ret,
&bytes_after_ret,
&win_data);
if (return_code != Success)
return False;
/*endif*/
if (win_data)
XFree ((char *) win_data);
/*endif*/
XChangeProperty (xim->display,
x_client->client_win,
atom,
XA_STRING,
8,
PropModeAppend,
(unsigned char *) reply,
length);
event.xclient.data.l[0] = length;
event.xclient.data.l[1] = atom;
}
else
{
unsigned char buffer[XCM_DATA_LIMIT];
int i;
event.xclient.format = 8;
/* Clear unused field with NULL */
memmove(buffer, reply, length);
for (i = length; i < XCM_DATA_LIMIT; i++)
buffer[i] = (char) 0;
/*endfor*/
length = XCM_DATA_LIMIT;
memmove (event.xclient.data.b, buffer, length);
}
XSendEvent (xim->display,
x_client->client_win,
False,
NoEventMask,
&event);
XFlush (xim->display);
return True;
}
static Bool CheckCMEvent (Display *display, XEvent *event, XPointer arg)
{
NimfXim *xim = NIMF_XIM (arg);
if ((event->type == ClientMessage) &&
(event->xclient.message_type == xim->_protocol))
return True;
return False;
}
Bool Xi18nXWait (NimfXim *xim,
CARD16 connect_id,
CARD8 major_opcode,
CARD8 minor_opcode)
{
XEvent event;
Xi18nClient *client = _Xi18nFindClient (xim, connect_id);
XClient *x_client = (XClient *) client->trans_rec;
for (;;)
{
unsigned char *packet;
XimProtoHdr *hdr;
int connect_id_ret = 0;
XIfEvent (xim->display,
&event,
CheckCMEvent,
(XPointer) xim);
if (event.xclient.window == x_client->accept_win)
{
if ((packet = ReadXIMMessage (xim,
(XClientMessageEvent *) & event,
&connect_id_ret))
== (unsigned char*) NULL)
{
return False;
}
/*endif*/
hdr = (XimProtoHdr *)packet;
if ((hdr->major_opcode == major_opcode)
&&
(hdr->minor_opcode == minor_opcode))
{
XFree (packet);
return True;
}
else if (hdr->major_opcode == XIM_ERROR)
{
XFree (packet);
return False;
}
XFree (packet);
}
/*endif*/
}
/*endfor*/
}
Bool Xi18nXDisconnect (NimfXim *xim, CARD16 connect_id)
{
Xi18nClient *client = _Xi18nFindClient (xim, connect_id);
XClient *x_client = (XClient *) client->trans_rec;
XDestroyWindow (xim->display, x_client->accept_win);
XFree (x_client);
_Xi18nDeleteClient (xim, connect_id);
return True;
}
Bool WaitXIMProtocol (NimfXim *xim,
XEvent *ev)
{
extern void _Xi18nMessageHandler (NimfXim *, CARD16, unsigned char *, Bool *);
Bool delete = True;
unsigned char *packet;
int connect_id = 0;
if (((XClientMessageEvent *) ev)->message_type
== xim->_protocol)
{
if ((packet = ReadXIMMessage (xim,
(XClientMessageEvent *) ev,
&connect_id))
== (unsigned char *) NULL)
{
return False;
}
/*endif*/
_Xi18nMessageHandler (xim, connect_id, packet, &delete);
if (delete == True)
XFree (packet);
/*endif*/
return True;
}
/*endif*/
return False;
}

View File

@@ -0,0 +1,55 @@
/******************************************************************
Copyright (C) 1994-1995 Sun Microsystems, Inc.
Copyright (C) 1993-1994 Hewlett-Packard Company
Copyright (C) 2014 Peng Huang <shawn.p.huang@gmail.com>
Copyright (C) 2014 Red Hat, Inc.
Permission to use, copy, modify, distribute, and sell this software
and its documentation for any purpose is hereby granted without fee,
provided that the above copyright notice appear in all copies and
that both that copyright notice and this permission notice appear
in supporting documentation, and that the name of Sun Microsystems, Inc.
and Hewlett-Packard not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior permission.
Sun Microsystems, Inc. and Hewlett-Packard make no representations about
the suitability of this software for any purpose. It is provided "as is"
without express or implied warranty.
SUN MICROSYSTEMS INC. AND HEWLETT-PACKARD COMPANY DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
SUN MICROSYSTEMS, INC. AND HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Author: Hidetoshi Tajima(tajima@Eng.Sun.COM) Sun Microsystems, Inc.
This version tidied and debugged by Steve Underwood May 1999
******************************************************************/
#ifndef I18N_X_H
#define I18N_X_H
#include <stddef.h>
#include <stdint.h>
#include <limits.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include "nimf-xim.h"
void ReadXConnectMessage (NimfXim *xim, XClientMessageEvent *ev);
Bool WaitXIMProtocol (NimfXim*, XEvent*);
Bool Xi18nXWait (NimfXim *xim,
CARD16 connect_id,
CARD8 major_opcode,
CARD8 minor_opcode);
Bool Xi18nXDisconnect (NimfXim *xim, CARD16 connect_id);
Bool Xi18nXSend (NimfXim *xim,
CARD16 connect_id,
unsigned char *reply,
long length);
#endif /* I18N_X_H */

View File

@@ -0,0 +1,48 @@
moduledir = $(libdir)/nimf/modules/services
module_LTLIBRARIES = libnimf-xim.la
IMdkit_SOURCES = \
IMdkit/FrameMgr.h \
IMdkit/Xi18n.h \
IMdkit/XimFunc.h \
IMdkit/XimProto.h \
IMdkit/FrameMgr.c \
IMdkit/i18nAttr.c \
IMdkit/i18nClbk.c \
IMdkit/i18nIc.c \
IMdkit/i18nIMProto.c \
IMdkit/i18nMethod.c \
IMdkit/i18nMethod.h \
IMdkit/i18nOffsetCache.c \
IMdkit/i18nPtHdr.c \
IMdkit/i18nUtil.c \
IMdkit/i18nX.c \
IMdkit/i18nX.h \
$(NULL)
libnimf_xim_la_SOURCES = \
nimf-xim.c \
nimf-xim.h \
nimf-xim-ic.c \
nimf-xim-ic.h \
$(IMdkit_SOURCES) \
$(NULL)
libnimf_xim_la_CFLAGS = \
$(EXTRA_CFLAGS) \
-I$(top_srcdir)/libnimf \
-DG_LOG_DOMAIN=\"nimf\" \
$(NIMF_XIM_DEPS_CFLAGS)
libnimf_xim_la_LDFLAGS = -avoid-version -module $(NIMF_XIM_DEPS_LIBS)
libnimf_xim_la_LIBADD = $(top_builddir)/libnimf/libnimf.la
DISTCLEANFILES = Makefile.in
install-data-hook:
chmod -x $(DESTDIR)$(moduledir)/libnimf-xim.so
rm -f $(DESTDIR)$(moduledir)/libnimf-xim.la
uninstall-hook:
rm -f $(DESTDIR)$(moduledir)/libnimf-xim.so
-rmdir -p $(DESTDIR)$(moduledir)

View File

@@ -0,0 +1,260 @@
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
/*
* nimf-xim-ic.c
* This file is part of Nimf.
*
* Copyright (C) 2015-2019 Hodong Kim <cogniti@gmail.com>
*
* Nimf is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Nimf is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; If not, see <http://www.gnu.org/licenses/>.
*/
#include "nimf-xim-ic.h"
#include <X11/Xutil.h>
#include "IMdkit/i18nMethod.h"
G_DEFINE_TYPE (NimfXimIC, nimf_xim_ic, NIMF_TYPE_SERVICE_IC);
void nimf_xim_ic_set_cursor_location (NimfXimIC *xic,
gint x,
gint y)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfRectangle area = {0};
Window window;
if (xic->focus_window)
window = xic->focus_window;
else
window = xic->client_window;
if (window)
{
Window child;
XWindowAttributes attr;
const char *xft_dpi;
int dpi = 0;
int dpi_x = 0;
int dpi_y = 0;
XGetWindowAttributes (xic->xim->display, window, &attr);
if (x < 0 && y < 0)
XTranslateCoordinates (xic->xim->display, window, attr.root,
0, attr.height, &area.x, &area.y, &child);
else
XTranslateCoordinates (xic->xim->display, window, attr.root,
x, y, &area.x, &area.y, &child);
xft_dpi = XGetDefault (xic->xim->display, "Xft", "dpi");
if (xft_dpi)
dpi = atoi (xft_dpi);
if (dpi)
{
area.x = (double) area.x * (96.0 / dpi);
area.y = (double) area.y * (96.0 / dpi);
}
else
{
dpi_x = ((double) WidthOfScreen (attr.screen)) * 25.4 /
((double) WidthMMOfScreen (attr.screen));
dpi_y = ((double) HeightOfScreen (attr.screen)) * 25.4 /
((double) HeightMMOfScreen (attr.screen));
area.x = (double) area.x * (96.0 / dpi_x);
area.y = (double) area.y * (96.0 / dpi_y);
}
}
nimf_service_ic_set_cursor_location (NIMF_SERVICE_IC (xic), &area);
}
static void
nimf_xim_ic_emit_commit (NimfServiceIC *ic,
const gchar *text)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfXimIC *xic = NIMF_XIM_IC (ic);
XTextProperty property;
Xutf8TextListToTextProperty (xic->xim->display,
(char **)&text, 1, XCompoundTextStyle,
&property);
IMCommitStruct commit_data = {0};
commit_data.major_code = XIM_COMMIT;
commit_data.connect_id = xic->connect_id;
commit_data.icid = xic->icid;
commit_data.flag = XimLookupChars;
commit_data.commit_string = (gchar *) property.value;
xi18n_commit (xic->xim, (XPointer) &commit_data);
XFree (property.value);
}
static void nimf_xim_ic_emit_preedit_end (NimfServiceIC *ic)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfXimIC *xic = NIMF_XIM_IC (ic);
IMPreeditCBStruct preedit_cb_data = {0};
preedit_cb_data.major_code = XIM_PREEDIT_DONE;
preedit_cb_data.connect_id = xic->connect_id;
preedit_cb_data.icid = xic->icid;
nimf_xim_call_callback (xic->xim, (XPointer) &preedit_cb_data);
}
static void nimf_xim_ic_emit_preedit_start (NimfServiceIC *ic)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfXimIC *xic = NIMF_XIM_IC (ic);
IMPreeditCBStruct preedit_cb_data = {0};
preedit_cb_data.major_code = XIM_PREEDIT_START;
preedit_cb_data.connect_id = xic->connect_id;
preedit_cb_data.icid = xic->icid;
nimf_xim_call_callback (xic->xim, (XPointer) &preedit_cb_data);
}
static void
nimf_xim_ic_emit_preedit_changed (NimfServiceIC *ic,
const gchar *preedit_string,
NimfPreeditAttr **attrs,
gint cursor_pos)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfXimIC *xic = NIMF_XIM_IC (ic);
IMPreeditCBStruct preedit_cb_data = {0};
XIMText text;
XTextProperty text_property;
static XIMFeedback *feedback;
gint i, j, len;
len = g_utf8_strlen (preedit_string, -1);
feedback = g_malloc0 (sizeof (XIMFeedback) * (len + 1));
for (i = 0; attrs[i]; i++)
{
switch (attrs[i]->type)
{
case NIMF_PREEDIT_ATTR_HIGHLIGHT:
for (j = attrs[i]->start_index; j < attrs[i]->end_index; j++)
feedback[j] |= XIMHighlight;
break;
case NIMF_PREEDIT_ATTR_UNDERLINE:
for (j = attrs[i]->start_index; j < attrs[i]->end_index; j++)
feedback[j] |= XIMUnderline;
break;
default:
break;
}
}
feedback[len] = 0;
preedit_cb_data.major_code = XIM_PREEDIT_DRAW;
preedit_cb_data.connect_id = xic->connect_id;
preedit_cb_data.icid = xic->icid;
preedit_cb_data.todo.draw.caret = cursor_pos;
preedit_cb_data.todo.draw.chg_first = 0;
preedit_cb_data.todo.draw.chg_length = xic->prev_preedit_length;
preedit_cb_data.todo.draw.text = &text;
text.feedback = feedback;
if (len > 0)
{
Xutf8TextListToTextProperty (xic->xim->display,
(char **) &preedit_string, 1,
XCompoundTextStyle, &text_property);
text.encoding_is_wchar = 0;
text.length = strlen ((char *) text_property.value);
text.string.multi_byte = (char *) text_property.value;
nimf_xim_call_callback (xic->xim, (XPointer) &preedit_cb_data);
XFree (text_property.value);
}
else
{
text.encoding_is_wchar = 0;
text.length = 0;
text.string.multi_byte = "";
nimf_xim_call_callback (xic->xim, (XPointer) &preedit_cb_data);
len = 0;
}
xic->prev_preedit_length = len;
g_free (feedback);
}
NimfXimIC *
nimf_xim_ic_new (NimfXim *xim,
guint16 connect_id,
guint16 icid)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfXimIC *xic = g_object_new (NIMF_TYPE_XIM_IC, NULL);
xic->xim = xim;
xic->connect_id = connect_id;
xic->icid = icid;
return xic;
}
const gchar *
nimf_xim_ic_get_service_id (NimfServiceIC *ic)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
return nimf_service_get_id (NIMF_SERVICE (NIMF_XIM_IC (ic)->xim));
}
static void
nimf_xim_ic_init (NimfXimIC *xic)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
}
static void
nimf_xim_ic_finalize (GObject *object)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
G_OBJECT_CLASS (nimf_xim_ic_parent_class)->finalize (object);
}
static void
nimf_xim_ic_class_init (NimfXimICClass *class)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
GObjectClass *object_class = G_OBJECT_CLASS (class);
NimfServiceICClass *service_im_class = NIMF_SERVICE_IC_CLASS (class);
service_im_class->emit_commit = nimf_xim_ic_emit_commit;
service_im_class->emit_preedit_start = nimf_xim_ic_emit_preedit_start;
service_im_class->emit_preedit_changed = nimf_xim_ic_emit_preedit_changed;
service_im_class->emit_preedit_end = nimf_xim_ic_emit_preedit_end;
service_im_class->get_service_id = nimf_xim_ic_get_service_id;
object_class->finalize = nimf_xim_ic_finalize;
}

View File

@@ -0,0 +1,71 @@
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
/*
* nimf-xim-ic.h
* This file is part of Nimf.
*
* Copyright (C) 2015-2019 Hodong Kim <cogniti@gmail.com>
*
* Nimf is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Nimf is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __NIMF_XIM_IC_H__
#define __NIMF_XIM_IC_H__
#include <glib-object.h>
#include "nimf.h"
#include "IMdkit/Xi18n.h"
#include "nimf-xim.h"
G_BEGIN_DECLS
#define NIMF_TYPE_XIM_IC (nimf_xim_ic_get_type ())
#define NIMF_XIM_IC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NIMF_TYPE_XIM_IC, NimfXimIC))
#define NIMF_XIM_IC_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), NIMF_TYPE_XIM_IC, NimfXimICClass))
#define NIMF_IS_XIM_IC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NIMF_TYPE_XIM_IC))
#define NIMF_IS_XIM_IC_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), NIMF_TYPE_XIM_IC))
#define NIMF_XIM_IC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NIMF_TYPE_XIM_IC, NimfXimICClass))
typedef struct _NimfXim NimfXim;
typedef struct _NimfXimIC NimfXimIC;
typedef struct _NimfXimICClass NimfXimICClass;
struct _NimfXimICClass
{
NimfServiceICClass parent_class;
};
struct _NimfXimIC
{
NimfServiceIC parent_instance;
guint16 connect_id;
guint16 icid;
gint prev_preedit_length;
CARD32 input_style;
Window client_window;
Window focus_window;
NimfXim *xim;
};
GType nimf_xim_ic_get_type (void) G_GNUC_CONST;
NimfXimIC *nimf_xim_ic_new (NimfXim *xim,
guint16 connect_id,
guint16 icid);
void nimf_xim_ic_set_cursor_location (NimfXimIC *xic,
gint x,
gint y);
G_END_DECLS
#endif /* __NIMF_XIM_IC_H__ */

View File

@@ -0,0 +1,756 @@
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
/*
* nimf-xim.c
* This file is part of Nimf.
*
* Copyright (C) 2015-2019 Hodong Kim <cogniti@gmail.com>
*
* Nimf is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Nimf is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; If not, see <http://www.gnu.org/licenses/>.
*/
#include "nimf-xim.h"
#include "IMdkit/i18nMethod.h"
#include "IMdkit/i18nX.h"
#include "IMdkit/XimFunc.h"
G_DEFINE_DYNAMIC_TYPE (NimfXim, nimf_xim, NIMF_TYPE_SERVICE);
static void
nimf_xim_change_engine (NimfService *service,
const gchar *engine_id,
const gchar *method_id)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfXim *xim = NIMF_XIM (service);
NimfServiceIC *ic;
ic = g_hash_table_lookup (xim->ics,
GUINT_TO_POINTER (xim->last_focused_icid));
if (ic)
nimf_service_ic_change_engine (ic, engine_id, method_id);
}
static void
nimf_xim_change_engine_by_id (NimfService *service,
const gchar *engine_id)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfXim *xim = NIMF_XIM (service);
NimfServiceIC *ic;
ic = g_hash_table_lookup (xim->ics,
GUINT_TO_POINTER (xim->last_focused_icid));
if (ic)
nimf_service_ic_change_engine_by_id (ic, engine_id);
}
static int nimf_xim_set_ic_values (NimfXim *xim,
IMChangeICStruct *data)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfServiceIC *ic;
NimfXimIC *xic;
CARD16 i;
ic = g_hash_table_lookup (xim->ics, GUINT_TO_POINTER (data->icid));
xic = NIMF_XIM_IC (ic);
for (i = 0; i < data->ic_attr_num; i++)
{
if (!g_strcmp0 (XNInputStyle, data->ic_attr[i].name))
{
xic->input_style = *(CARD32*) data->ic_attr[i].value;
nimf_service_ic_set_use_preedit (ic, !!(xic->input_style & XIMPreeditCallbacks));
}
else if (!g_strcmp0 (XNClientWindow, data->ic_attr[i].name))
{
xic->client_window = *(Window *) data->ic_attr[i].value;
}
else if (!g_strcmp0 (XNFocusWindow, data->ic_attr[i].name))
{
xic->focus_window = *(Window *) data->ic_attr[i].value;
}
else
{
g_warning (G_STRLOC ": %s %s", G_STRFUNC, data->ic_attr[i].name);
}
}
for (i = 0; i < data->preedit_attr_num; i++)
{
if (g_strcmp0 (XNPreeditState, data->preedit_attr[i].name) == 0)
{
XIMPreeditState state = *(XIMPreeditState *) data->preedit_attr[i].value;
switch (state)
{
case XIMPreeditEnable:
nimf_service_ic_set_use_preedit (ic, TRUE);
break;
case XIMPreeditDisable:
nimf_service_ic_set_use_preedit (ic, FALSE);
break;
case XIMPreeditUnKnown:
break;
default:
g_warning (G_STRLOC ": %s: XIMPreeditState: %ld is ignored",
G_STRFUNC, state);
break;
}
}
else if (g_strcmp0 (XNSpotLocation, data->preedit_attr[i].name) == 0)
{
nimf_xim_ic_set_cursor_location (xic,
((XPoint *) data->preedit_attr[i].value)->x,
((XPoint *) data->preedit_attr[i].value)->y);
NimfServer *server = nimf_server_get_default ();
NimfPreeditable *preeditable = nimf_server_get_preeditable (server);
if (nimf_preeditable_is_visible (preeditable))
nimf_preeditable_show (preeditable);
}
else
{
g_critical (G_STRLOC ": %s: %s is ignored",
G_STRFUNC, data->preedit_attr[i].name);
}
}
for (i = 0; i < data->status_attr_num; i++)
{
g_critical (G_STRLOC ": %s: %s is ignored",
G_STRFUNC, data->status_attr[i].name);
}
return 1;
}
static int nimf_xim_create_ic (NimfXim *xim,
IMChangeICStruct *data)
{
g_debug (G_STRLOC ": %s, data->connect_id: %d", G_STRFUNC, data->connect_id);
NimfXimIC *xic;
xic = g_hash_table_lookup (xim->ics, GUINT_TO_POINTER (data->icid));
if (!xic)
{
guint16 icid;
do
icid = xim->next_icid++;
while (icid == 0 ||
g_hash_table_contains (xim->ics, GUINT_TO_POINTER (icid)));
xic = nimf_xim_ic_new (xim, data->connect_id, icid);
g_hash_table_insert (xim->ics, GUINT_TO_POINTER (icid), xic);
data->icid = icid;
g_debug (G_STRLOC ": icid = %d", data->icid);
}
nimf_xim_set_ic_values (xim, data);
return 1;
}
static int nimf_xim_destroy_ic (NimfXim *xim,
IMDestroyICStruct *data)
{
g_debug (G_STRLOC ": %s, data->icid = %d", G_STRFUNC, data->icid);
return g_hash_table_remove (xim->ics, GUINT_TO_POINTER (data->icid));
}
static int nimf_xim_get_ic_values (NimfXim *xim,
IMChangeICStruct *data)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfServiceIC *ic;
ic = g_hash_table_lookup (xim->ics, GUINT_TO_POINTER (data->icid));
CARD16 i;
for (i = 0; i < data->ic_attr_num; i++)
{
if (g_strcmp0 (XNFilterEvents, data->ic_attr[i].name) == 0)
{
data->ic_attr[i].value_length = sizeof (CARD32);
data->ic_attr[i].value = g_malloc (sizeof (CARD32));
*(CARD32 *) data->ic_attr[i].value = KeyPressMask | KeyReleaseMask;
}
else
g_critical (G_STRLOC ": %s: %s is ignored",
G_STRFUNC, data->ic_attr[i].name);
}
for (i = 0; i < data->preedit_attr_num; i++)
{
if (g_strcmp0 (XNPreeditState, data->preedit_attr[i].name) == 0)
{
data->preedit_attr[i].value_length = sizeof (XIMPreeditState);
data->preedit_attr[i].value = g_malloc (sizeof (XIMPreeditState));
if (nimf_service_ic_get_use_preedit (ic))
*(XIMPreeditState *) data->preedit_attr[i].value = XIMPreeditEnable;
else
*(XIMPreeditState *) data->preedit_attr[i].value = XIMPreeditDisable;
}
else
g_critical (G_STRLOC ": %s: %s is ignored",
G_STRFUNC, data->preedit_attr[i].name);
}
for (i = 0; i < data->status_attr_num; i++)
g_critical (G_STRLOC ": %s: %s is ignored",
G_STRFUNC, data->status_attr[i].name);
return 1;
}
static int nimf_xim_forward_event (NimfXim *xim,
IMForwardEventStruct *data)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
XKeyEvent *xevent;
NimfEvent *event;
gboolean retval;
KeySym keysym;
unsigned int consumed;
NimfModifierType state;
xevent = (XKeyEvent*) &(data->event);
event = nimf_event_new (NIMF_EVENT_NOTHING);
if (xevent->type == KeyPress)
event->key.type = NIMF_EVENT_KEY_PRESS;
else
event->key.type = NIMF_EVENT_KEY_RELEASE;
event->key.state = (NimfModifierType) xevent->state;
event->key.keyval = NIMF_KEY_VoidSymbol;
event->key.hardware_keycode = xevent->keycode;
XkbLookupKeySym (xim->display,
event->key.hardware_keycode,
event->key.state,
&consumed, &keysym);
event->key.keyval = (guint) keysym;
state = event->key.state & ~consumed;
event->key.state |= (NimfModifierType) state;
NimfServiceIC *ic;
ic = g_hash_table_lookup (xim->ics, GUINT_TO_POINTER (data->icid));
retval = nimf_service_ic_filter_event (ic, event);
nimf_event_free (event);
if (G_UNLIKELY (!retval))
return xi18n_forwardEvent (xim, (XPointer) data);
return 1;
}
static const gchar *
nimf_xim_get_id (NimfService *service)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
g_return_val_if_fail (NIMF_IS_SERVICE (service), NULL);
return NIMF_XIM (service)->id;
}
static int nimf_xim_set_ic_focus (NimfXim *xim,
IMChangeFocusStruct *data)
{
NimfServiceIC *ic;
NimfXimIC *xic;
ic = g_hash_table_lookup (xim->ics, GUINT_TO_POINTER (data->icid));
xic = NIMF_XIM_IC (ic);
g_debug (G_STRLOC ": %s, icid = %d, connection id = %d",
G_STRFUNC, data->icid, xic->icid);
nimf_service_ic_focus_in (ic);
xim->last_focused_icid = xic->icid;
if (xic->input_style & XIMPreeditNothing)
nimf_xim_ic_set_cursor_location (xic, -1, -1);
return 1;
}
static int nimf_xim_unset_ic_focus (NimfXim *xim,
IMChangeFocusStruct *data)
{
NimfServiceIC *ic;
ic = g_hash_table_lookup (xim->ics, GUINT_TO_POINTER (data->icid));
g_debug (G_STRLOC ": %s, icid = %d", G_STRFUNC, data->icid);
nimf_service_ic_focus_out (ic);
return 1;
}
static int nimf_xim_reset_ic (NimfXim *xim,
IMResetICStruct *data)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfServiceIC *ic;
ic = g_hash_table_lookup (xim->ics, GUINT_TO_POINTER (data->icid));
nimf_service_ic_reset (ic);
return 1;
}
/* FIXME */
int
on_incoming_message (NimfXim *xim,
IMProtocol *data)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
g_return_val_if_fail (data != NULL, True);
int retval;
switch (data->major_code)
{
case XIM_OPEN:
g_debug (G_STRLOC ": XIM_OPEN: connect_id: %u", data->imopen.connect_id);
retval = 1;
break;
case XIM_CLOSE:
g_debug (G_STRLOC ": XIM_CLOSE: connect_id: %u",
data->imclose.connect_id);
retval = 1;
break;
case XIM_PREEDIT_START_REPLY:
g_debug (G_STRLOC ": XIM_PREEDIT_START_REPLY");
retval = 1;
break;
case XIM_CREATE_IC:
retval = nimf_xim_create_ic (xim, &data->changeic);
break;
case XIM_DESTROY_IC:
retval = nimf_xim_destroy_ic (xim, &data->destroyic);
break;
case XIM_SET_IC_VALUES:
retval = nimf_xim_set_ic_values (xim, &data->changeic);
break;
case XIM_GET_IC_VALUES:
retval = nimf_xim_get_ic_values (xim, &data->changeic);
break;
case XIM_FORWARD_EVENT:
retval = nimf_xim_forward_event (xim, &data->forwardevent);
break;
case XIM_SET_IC_FOCUS:
retval = nimf_xim_set_ic_focus (xim, &data->changefocus);
break;
case XIM_UNSET_IC_FOCUS:
retval = nimf_xim_unset_ic_focus (xim, &data->changefocus);
break;
case XIM_RESET_IC:
retval = nimf_xim_reset_ic (xim, &data->resetic);
break;
default:
g_warning (G_STRLOC ": %s: major op code %d not handled", G_STRFUNC,
data->major_code);
retval = 0;
break;
}
return retval;
}
static int
on_xerror (Display *display,
XErrorEvent *error)
{
gchar buf[64];
XGetErrorText (display, error->error_code, buf, 63);
g_warning (G_STRLOC ": %s: %s", G_STRFUNC, buf);
g_warning ("type: %d", error->type);
g_warning ("display name: %s", DisplayString (error->display));
g_warning ("serial: %lu", error->serial);
g_warning ("error_code: %d", error->error_code);
g_warning ("request_code: %d", error->request_code);
g_warning ("minor_code: %d", error->minor_code);
g_warning ("resourceid: %lu", error->resourceid);
return 1;
}
typedef struct
{
GSource source;
NimfXim *xim;
GPollFD poll_fd;
} NimfXEventSource;
static gboolean nimf_xevent_source_prepare (GSource *source,
gint *timeout)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
Display *display = ((NimfXEventSource *) source)->xim->display;
*timeout = -1;
return XPending (display) > 0;
}
static gboolean nimf_xevent_source_check (GSource *source)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfXEventSource *display_source = (NimfXEventSource *) source;
if (display_source->poll_fd.revents & G_IO_IN)
return XPending (display_source->xim->display) > 0;
else
return FALSE;
}
static gboolean
nimf_xevent_source_dispatch (GSource *source,
GSourceFunc callback,
gpointer user_data)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfXim *xim = ((NimfXEventSource*) source)->xim;
XEvent event;
while (XPending (xim->display) > 0)
{
XNextEvent (xim->display, &event);
if (!XFilterEvent (&event, None))
{
switch (event.type)
{
case SelectionRequest:
WaitXSelectionRequest (xim, &event);
break;
case ClientMessage:
{
XClientMessageEvent cme = *(XClientMessageEvent *) &event;
if (cme.message_type == xim->_xconnect)
ReadXConnectMessage (xim, (XClientMessageEvent *) &event);
else if (cme.message_type == xim->_protocol)
WaitXIMProtocol (xim, &event);
else
g_warning (G_STRLOC ": %s: ClientMessage type: %ld not handled",
G_STRFUNC, cme.message_type);
}
break;
case MappingNotify:
g_message (G_STRLOC ": %s: MappingNotify", G_STRFUNC);
break;
default:
g_warning (G_STRLOC ": %s: event type: %d not filtered",
G_STRFUNC, event.type);
break;
}
}
}
return TRUE;
}
static void nimf_xevent_source_finalize (GSource *source)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
}
static GSourceFuncs event_funcs = {
nimf_xevent_source_prepare,
nimf_xevent_source_check,
nimf_xevent_source_dispatch,
nimf_xevent_source_finalize
};
static GSource *nimf_xevent_source_new (NimfXim *xim)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
GSource *source;
NimfXEventSource *xevent_source;
source = g_source_new (&event_funcs, sizeof (NimfXEventSource));
xevent_source = (NimfXEventSource *) source;
xevent_source->xim = xim;
xevent_source->poll_fd.fd = ConnectionNumber (xevent_source->xim->display);
xevent_source->poll_fd.events = G_IO_IN;
g_source_add_poll (source, &xevent_source->poll_fd);
g_source_set_priority (source, G_PRIORITY_DEFAULT);
g_source_set_can_recurse (source, TRUE);
return source;
}
static gboolean nimf_xim_is_active (NimfService *service)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
return NIMF_XIM (service)->active;
}
static gboolean nimf_xim_start (NimfService *service)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfXim *xim = NIMF_XIM (service);
if (xim->active)
return TRUE;
xim->display = XOpenDisplay (NULL);
if (xim->display == NULL)
{
g_warning (G_STRLOC ": %s: Can't open display", G_STRFUNC);
return FALSE;
}
/*
* https://www.x.org/releases/X11R7.7/doc/libX11/libX11/libX11.html
* https://www.x.org/releases/X11R7.7/doc/libX11/XIM/xim.html
*
* The preedit category defines what type of support is provided by the input
* method for preedit information.
*
* XIMPreeditArea (as known as off-the-spot)
*
* The client application provides display windows for the pre-edit data to the
* input method which displays into them directly.
* If chosen, the input method would require the client to provide some area
* values for it to do its preediting. Refer to XIC values XNArea and
* XNAreaNeeded.
*
* XIMPreeditCallbacks (as known as on-the-spot)
*
* The client application is directed by the IM Server to display all pre-edit
* data at the site of text insertion. The client registers callbacks invoked by
* the input method during pre-editing.
* If chosen, the input method would require the client to define the set of
* preedit callbacks. Refer to XIC values XNPreeditStartCallback,
* XNPreeditDoneCallback, XNPreeditDrawCallback, and XNPreeditCaretCallback.
*
* XIMPreeditPosition (as known as over-the-spot)
*
* The input method displays pre-edit data in a window which it brings up
* directly over the text insertion position.
* If chosen, the input method would require the client to provide positional
* values. Refer to XIC values XNSpotLocation and XNFocusWindow.
*
* XIMPreeditNothing (as known as root-window)
*
* The input method displays all pre-edit data in a separate area of the screen
* in a window specific to the input method.
* If chosen, the input method can function without any preedit values.
*
* XIMPreeditNone none
*
* The input method does not provide any preedit feedback. Any preedit value is
* ignored. This style is mutually exclusive with the other preedit styles.
*
*
* The status category defines what type of support is provided by the input
* method for status information.
*
* XIMStatusArea
*
* The input method requires the client to provide some area values for it to do
* its status feedback. See XNArea and XNAreaNeeded.
*
* XIMStatusCallbacks
*
* The input method requires the client to define the set of status callbacks,
* XNStatusStartCallback, XNStatusDoneCallback, and XNStatusDrawCallback.
*
* XIMStatusNothing
*
* The input method can function without any status values.
*
* XIMStatusNone
*
* The input method does not provide any status feedback. If chosen, any status
* value is ignored. This style is mutually exclusive with the other status
* styles.
*/
xim->im_styles.count_styles = 6;
xim->im_styles.supported_styles = g_malloc (sizeof (XIMStyle) * xim->im_styles.count_styles);
/* on-the-spot */
xim->im_styles.supported_styles[0] = XIMPreeditCallbacks | XIMStatusNothing;
xim->im_styles.supported_styles[1] = XIMPreeditCallbacks | XIMStatusNone;
/* over-the-spot */
xim->im_styles.supported_styles[2] = XIMPreeditPosition | XIMStatusNothing;
xim->im_styles.supported_styles[3] = XIMPreeditPosition | XIMStatusNone;
/* root-window */
xim->im_styles.supported_styles[4] = XIMPreeditNothing | XIMStatusNothing;
xim->im_styles.supported_styles[5] = XIMPreeditNothing | XIMStatusNone;
xim->im_event_mask = KeyPressMask | KeyReleaseMask;
XSetWindowAttributes attrs;
attrs.event_mask = xim->im_event_mask;
attrs.override_redirect = True;
xim->im_window = XCreateWindow (xim->display, /* Display *display */
DefaultRootWindow (xim->display), /* Window parent */
0, 0, /* int x, y */
1, 1, /* unsigned int width, height */
0, /* unsigned int border_width */
0, /* int depth */
InputOutput, /* unsigned int class */
CopyFromParent, /* Visual *visual */
CWOverrideRedirect | CWEventMask, /* unsigned long valuemask */
&attrs); /* XSetWindowAttributes *attributes */
if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
xim->byte_order = 'l';
else
xim->byte_order = 'B';
_Xi18nInitAttrList (xim);
_Xi18nInitExtension (xim);
if (!xi18n_openIM (xim, xim->im_window))
{
XDestroyWindow (xim->display, xim->im_window);
XCloseDisplay (xim->display);
xim->im_window = 0;
xim->display = NULL;
g_warning (G_STRLOC ": %s: XIM is not started.", G_STRFUNC);
return FALSE;
}
xim->xevent_source = nimf_xevent_source_new (xim);
g_source_attach (xim->xevent_source, NULL);
XSetErrorHandler (on_xerror);
xim->active = TRUE;
return TRUE;
}
static void nimf_xim_stop (NimfService *service)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfXim *xim = NIMF_XIM (service);
if (!xim->active)
return;
if (xim->xevent_source)
{
g_source_destroy (xim->xevent_source);
g_source_unref (xim->xevent_source);
}
if (xim->im_window)
{
XDestroyWindow (xim->display, xim->im_window);
xim->im_window = 0;
}
g_free (xim->im_styles.supported_styles);
xi18n_closeIM (xim);
if (xim->display)
{
XCloseDisplay (xim->display);
xim->display = NULL;
}
xim->active = FALSE;
}
static void
nimf_xim_init (NimfXim *xim)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
xim->id = g_strdup ("nimf-xim");
xim->ics = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
(GDestroyNotify) g_object_unref);
}
static void nimf_xim_finalize (GObject *object)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
NimfService *service = NIMF_SERVICE (object);
NimfXim *xim = NIMF_XIM (object);
if (nimf_xim_is_active (service))
nimf_xim_stop (service);
g_hash_table_unref (xim->ics);
g_free (xim->id);
G_OBJECT_CLASS (nimf_xim_parent_class)->finalize (object);
}
static void
nimf_xim_class_init (NimfXimClass *class)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
GObjectClass *object_class = G_OBJECT_CLASS (class);
NimfServiceClass *service_class = NIMF_SERVICE_CLASS (class);
service_class->get_id = nimf_xim_get_id;
service_class->start = nimf_xim_start;
service_class->stop = nimf_xim_stop;
service_class->is_active = nimf_xim_is_active;
service_class->change_engine = nimf_xim_change_engine;
service_class->change_engine_by_id = nimf_xim_change_engine_by_id;
object_class->finalize = nimf_xim_finalize;
}
static void
nimf_xim_class_finalize (NimfXimClass *class)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
}
void module_register_type (GTypeModule *type_module)
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
nimf_xim_register_type (type_module);
}
GType module_get_type ()
{
g_debug (G_STRLOC ": %s", G_STRFUNC);
return nimf_xim_get_type ();
}

View File

@@ -0,0 +1,75 @@
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
/*
* nimf-xim.h
* This file is part of Nimf.
*
* Copyright (C) 2015-2019 Hodong Kim <cogniti@gmail.com>
*
* Nimf is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Nimf is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __NIMF_XIM_H__
#define __NIMF_XIM_H__
#include "config.h"
#include <nimf.h>
#include <glib/gi18n.h>
#include <X11/XKBlib.h>
#include "nimf-xim-ic.h"
#include "IMdkit/Xi18n.h"
G_BEGIN_DECLS
#define NIMF_TYPE_XIM (nimf_xim_get_type ())
#define NIMF_XIM(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), NIMF_TYPE_XIM, NimfXim))
#define NIMF_XIM_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), NIMF_TYPE_XIM, NimfXimClass))
#define NIMF_IS_XIM(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), NIMF_TYPE_XIM))
#define NIMF_IS_XIM_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), NIMF_TYPE_XIM))
#define NIMF_XIM_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS ((object), NIMF_TYPE_XIM, NimfXimClass))
typedef struct _NimfXim NimfXim;
typedef struct _NimfXimClass NimfXimClass;
struct _NimfXim
{
NimfService parent_instance;
GSource *xevent_source;
gchar *id;
GHashTable *ics;
guint16 next_icid;
guint16 last_focused_icid;
gboolean active;
Display *display;
Window im_window;
XIMStyles im_styles;
CARD32 im_event_mask;
Atom _xconnect;
Atom _protocol;
Bool sync;
Xi18nAddressRec address;
CARD8 byte_order;
};
struct _NimfXimClass
{
NimfServiceClass parent_class;
};
GType nimf_xim_get_type (void) G_GNUC_CONST;
G_END_DECLS
#endif /* __NIMF_XIM_H__ */