Mercurial > kinput2.yaz
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); +}