diff lib/imlib/imic.c @ 0:92745d501b9a

initial import from kinput2-v3.1
author Yoshiki Yazawa <yaz@honeyplanet.jp>
date Mon, 08 Mar 2010 04:44:30 +0900
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/imlib/imic.c	Mon Mar 08 04:44:30 2010 +0900
@@ -0,0 +1,396 @@
+#ifndef lint
+static char *rcsid = "$Id: imic.c,v 1.12 2002/01/24 09:07:20 ishisone Exp $";
+#endif
+/*
+ * Copyright (c) 1994  Software Research Associates, Inc.
+ *
+ * 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 name of Software Research Associates not be
+ * used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.  Software Research
+ * Associates makes no representations about the suitability of this software
+ * for any purpose.  It is provided "as is" without express or implied
+ * warranty.
+ *
+ * Author:  Makoto Ishisone, Software Research Associates, Inc., Japan
+ */
+
+#include "im.h"
+
+#define IMHASHVAL(imp)	((imp)->id % IM_HASH_SIZE)
+#define ICHASHVAL(icp)	((icp)->id % IC_HASH_SIZE)
+
+static IMIM *id2IM _Pt_((IMConnection *conn, unsigned int id));
+static IMIC *id2IC _Pt_((IMIM *imp, unsigned int id));
+static unsigned int newIMID _Pt_((IMConnection *conn));
+static unsigned int newICID _Pt_((IMIM *imp));
+static void registerIM _Pt_((IMIM *imp));
+static void registerIC _Pt_((IMIC *icp));
+static int unregisterIM _Pt_((IMIM *imp));
+static int unregisterIC _Pt_((IMIC *icp));
+static int removeIM _Pt_((IMIM *imp));
+static int removeIC _Pt_((IMIC *icp));
+
+/*- id2IM: input-method ID to IM converter -*/
+static IMIM *
+id2IM(conn, id)
+IMConnection *conn;
+unsigned int id;
+{
+    IMIM **imHash = IMIMHash(conn->proto_widget);
+    IMIM *imp;
+
+    imp = imHash[id % IM_HASH_SIZE];
+    while (imp != NULL) {
+	if (imp->id == id) return imp;
+	imp = imp->hash_next;
+    }
+    return NULL;
+}
+
+/*- id2IC: input-context ID to IC converter -*/
+static IMIC *
+id2IC(imp, id)
+IMIM *imp;
+unsigned int id;
+{
+    IMIC **icHash = IMICHash(imp->connection->proto_widget);
+    IMIC *icp;
+
+    icp = icHash[id % IC_HASH_SIZE];
+    while (icp != NULL) {
+	if (icp->id == id) return icp;
+	icp = icp->hash_next;
+    }
+    return NULL;
+}
+
+/*- newIMID: return unused input-method ID -*/
+static unsigned int
+newIMID(conn)
+IMConnection *conn;
+{
+    Widget w = conn->proto_widget;
+    unsigned int id, id_start;
+
+    id = id_start = IMNextIMID(w);
+    do {
+	if (id2IM(conn, id) == NULL) return id;	/* unused ID */
+    } while ((id = IMNextIMID(w)) != id_start);
+    return 0;
+}
+
+/*- newICID: return unused input-context ID -*/
+static unsigned int
+newICID(imp)
+IMIM *imp;
+{
+    Widget w = imp->connection->proto_widget;
+    unsigned int id, id_start;
+
+    id = id_start = IMNextICID(w);
+    do {
+	if (id2IC(imp, id) == NULL) return id;	/* unused ID */
+    } while ((id = IMNextICID(w)) != id_start);
+    return 0;
+}
+
+/*- registerIM: register IM to hash table -*/
+static void
+registerIM(imp)
+IMIM *imp;
+{
+    IMIM **imHash = IMIMHash(imp->connection->proto_widget);
+
+    imp->hash_next = imHash[IMHASHVAL(imp)];
+    imHash[IMHASHVAL(imp)] = imp;
+}
+
+/*- registerIC: register IC to hash table -*/
+static void
+registerIC(icp)
+IMIC *icp;
+{
+    IMIC **icHash = IMICHash(icp->im->connection->proto_widget);
+
+    icp->hash_next = icHash[ICHASHVAL(icp)];
+    icHash[ICHASHVAL(icp)] = icp;
+}
+
+/*- unregisterIM: remove IM from hash table -*/
+static int
+unregisterIM(imp)
+IMIM *imp;
+{
+    IMIM **imHash = IMIMHash(imp->connection->proto_widget);
+    IMIM *p, *q;
+
+    p = imHash[IMHASHVAL(imp)];
+    q = NULL;
+
+    while (p != NULL && p != imp) {
+	q = p;
+	p = p->hash_next;
+    }
+    if (p == NULL) return 0;
+
+    if (q != NULL) {
+	q->hash_next = p->hash_next;
+    } else {
+	imHash[IMHASHVAL(imp)] = p->hash_next;
+    }
+    return 1;
+}
+
+/*- unregisterIC: remove IC from hash table -*/
+static int
+unregisterIC(icp)
+IMIC *icp;
+{
+    IMIC **icHash = IMICHash(icp->im->connection->proto_widget);
+    IMIC *p, *q;
+
+    p = icHash[ICHASHVAL(icp)];
+    q = NULL;
+
+    while (p != NULL && p != icp) {
+	q = p;
+	p = p->hash_next;
+    }
+    if (p == NULL) return 0;
+
+    if (q != NULL) {
+	q->hash_next = p->hash_next;
+    } else {
+	icHash[ICHASHVAL(icp)] = p->hash_next;
+    }
+    return 1;
+}
+
+/* removeIM: remove IM from IM list which connection holds */
+static int
+removeIM(imp)
+IMIM *imp;
+{
+    IMConnection *conn = imp->connection;
+    IMIM *p, *q;
+
+    p = conn->im_list;
+    q = NULL;
+    while (p != NULL) {
+	if (p == imp) break;
+	q = p;
+	p = p->next;
+    }
+
+    if (p == NULL) return 0;
+
+    if (q == NULL) {
+	conn->im_list = p->next;
+    } else {
+	q->next = p->next;
+    }
+    return 1;
+}
+
+/* removeIC: remove IC from IC list which IM holds */
+static int
+removeIC(icp)
+IMIC *icp;
+{
+    IMIM *imp = icp->im;
+    IMIC *p, *q;
+
+    p = imp->ic_list;
+    q = NULL;
+    while (p != NULL) {
+	if (p == icp) break;
+	q = p;
+	p = p->next;
+    }
+
+    if (p == NULL) return 0;
+
+    if (q == NULL) {
+	imp->ic_list = p->next;
+    } else {
+	q->next = p->next;
+    }
+    return 1;
+}
+
+/*
+ * Public functions
+ */
+
+IMIM *
+IMGetIM(conn, arglen)
+IMConnection *conn;
+int arglen;
+{
+    unsigned int id;
+    IMIM *imp;
+
+    /* Check argument length */
+    if (arglen < 2) {
+	IMSendError(conn, IMBadSomething, 0, 0, "input-method ID expected");
+	return NULL;
+    }
+
+    id = IMGetC16(conn, 0);
+    imp = id2IM(conn, id);
+    if (imp != NULL && imp->connection == conn)	return imp;
+    IMSendError(conn, IMBadSomething, 0, 0, "invalid input-method ID");
+    return NULL;
+}
+
+IMIC *
+IMGetIC(conn, arglen)
+IMConnection *conn;
+int arglen;
+{
+    unsigned int imid, icid;
+    IMIM *imp;
+    IMIC *icp;
+
+    /* Check argument length */
+    if (arglen < 4) {
+	IMSendError(conn, IMBadSomething, 0, 0, "input-method ID expected");
+	return NULL;
+    } else if (arglen < 4) {
+	IMSendError(conn, IMBadSomething, 0, 0, "input-context ID expected");
+	return NULL;
+    }
+
+    imid = IMGetC16(conn, 0);
+    icid = IMGetC16(conn, 2);
+
+    if ((imp = id2IM(conn, imid)) == NULL || imp->connection != conn) {
+	IMSendError(conn, IMBadSomething, 0, 0, "invalid input-method ID");
+	return NULL;
+    }
+    if ((icp = id2IC(imp, icid)) == NULL || icp->im != imp) {
+	IMSendError(conn, IMBadSomething, 0, 0, "invalid input-context ID");
+	return NULL;
+    }
+    return icp;
+}
+
+IMIM *
+IMCreateIM(conn, converter)
+IMConnection *conn;
+IMConverter *converter;
+{
+    IMIM *imp;
+
+    imp = XtNew(IMIM);
+
+    imp->id = newIMID(conn);
+    imp->connection = conn;
+    imp->converter = converter;
+    imp->mask = 0;
+    imp->ic_list = NULL;
+
+    registerIM(imp);
+    imp->next = conn->im_list;
+    conn->im_list = imp;
+
+    return imp;
+}
+
+
+IMIC *
+IMCreateIC(imp)
+IMIM *imp;
+{
+    IMIC *icp;
+
+    icp = XtNew(IMIC);
+
+    icp->id = newICID(imp);
+
+    /*
+     * Initialize data
+     */
+    icp->im = imp;
+    icp->conversion = NULL;
+    icp->state = 0;
+    icp->pending_events = NULL;
+    icp->style = IMSTYLE_SEPARATE;
+    icp->common_attr.set_mask = icp->common_attr.change_mask = 0;
+    icp->preedit_attr.set_mask = icp->preedit_attr.change_mask = 0;
+    icp->status_attr.set_mask = icp->status_attr.change_mask = 0;
+    icp->fonts = NULL;
+    icp->num_fonts = 0;
+    icp->status_fonts = NULL;
+    icp->num_status_fonts = 0;
+
+    registerIC(icp);
+    icp->next = imp->ic_list;
+    imp->ic_list = icp;
+
+    return icp;
+}
+
+void
+IMDestroyIM(imp)
+IMIM *imp;
+{
+    IMIC *icp = imp->ic_list;
+    IMIC *icp_next;
+
+    /*
+     * Destroy all the ICs belonging to this IM.
+     */
+    while (icp != NULL) {
+	icp_next = icp->next;
+	IMDestroyIC(icp);
+	icp = icp_next;
+    }
+
+    (void)unregisterIM(imp);
+    (void)removeIM(imp);
+
+    XtFree((char *)imp);
+}
+
+void
+IMDestroyIC(icp)
+IMIC *icp;
+{
+    IMPendingEvent *pending;
+
+    if (icp->state & IC_DESTROYING) return;
+    icp->state |= IC_DESTROYING;
+
+    /*
+     * Stop conversion.
+     */
+    if (icp->state & IC_CONVERTING) {
+	IMStopConversion(icp);
+    }
+
+    /*
+     * Free pending event queue.
+     */
+    pending = icp->pending_events;
+    while (pending != NULL) {
+	IMPendingEvent *next = pending->next;
+
+	XtFree((char *)pending);
+	pending = next;
+    }
+
+    /*
+     * Free IC attributes.
+     */
+    IMFreeICAttributes(icp);
+
+    (void)unregisterIC(icp);
+    (void)removeIC(icp);
+
+    XtFree((char *)icp);
+}