BSD 4_4_Lite2 development
[unix-history] / usr / src / contrib / X11R5-lib / lib / X / Xsi / XCrIC.c
/*
* $XConsortium: XCrIC.c,v 1.34 92/07/29 13:54:58 rws Exp $
*/
/*
* Copyright 1990, 1991 by OMRON Corporation
* Copyright 1991 by the Massachusetts Institute of Technology
*
* 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 names of OMRON and MIT not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. OMRON and MIT make no representations
* about the suitability of this software for any purpose. It is provided
* "as is" without express or implied warranty.
*
* OMRON AND MIT DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL OMRON OR MIT 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
* TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* Author: Seiji Kuwari OMRON Corporation
* kuwa@omron.co.jp
* kuwa%omron.co.jp@uunet.uu.net
*/
#include <stdio.h>
#include "Xlibint.h"
#include "Xi18nint.h"
#include "XIMlibint.h"
#if NeedVarargsPrototypes
# include <stdarg.h>
# define Va_start(a,b) va_start(a,b)
#else
# include <varargs.h>
# define Va_start(a,b) va_start(a)
#endif
#if __STDC__ && !defined(NORCONST)
#define RConst const
#else
#define RConst /**/
#endif
/*
* Free the input context.
*/
void
_XipDestroyIC(supic)
XIC supic;
{
XipIC ic = (XipIC)supic;
XipIM im = (XipIM)ic->core.im;
/* check xim and ic*/
if (im->fd >= 0) {
ximDestroyICReq req;
ximEventReply reply;
req.reqType = XIM_DestroyIC;
req.length = sz_ximDestroyICReq;
req.xic = ic->icid;
if ((_XipWriteToIM(im, (char *)&req, sz_ximDestroyICReq) >= 0) &&
(_XipFlushToIM(im) >= 0)) {
for (;;) {
if ((_XipReadFromIM(im, (char *)&reply, sz_ximEventReply) < 0)
|| (reply.state == 0xffff)) {
return;
}
if (reply.detail == XIM_CALLBACK) {
/*
* Call the callback routines.
*/
if (_XipCallCallbacks(ic) < 0) {
return;
}
} else {
break;
}
}
}
}
_XUnregisterFilter(im->core.display, ic->core.focus_window,
ic->prototype_filter, (XPointer)ic);
if (ic->mb) _XlcFreeLocale(ic->mb);
if (ic->wc) _XlcFreeLocale(ic->wc);
#ifdef XML
if (ic->xlc_num > 0) {
int i;
for (i = 0; i < ic->xlc_num; i++) {
_XlcFreeLocale(ic->mb_temp[i]);
_XlcFreeLocale(ic->wc_temp[i]);
}
}
if (ic->mb_temp) Xfree(ic->mb_temp);
if (ic->wc_temp) Xfree(ic->wc_temp);
if (ic->values.using_language) Xfree(ic->values.using_language);
if (ic->values.current_language) Xfree(ic->values.current_language);
#endif /* XML */
if (ic->ct_buf) Xfree(ic->ct_buf);
if (ic->wc_buf) Xfree(ic->wc_buf);
(void) _XipFreeAllICQueue(ic);
}
static RConst XICMethodsRec ic_methods = {
_XipDestroyIC,
_XipSetICFocus,
_XipUnsetICFocus,
_XipSetICValues,
_XipGetICValues,
_XipmbResetIC,
_XipwcResetIC,
_XipmbLookupString,
_XipwcLookupString
};
static Status
_StringToPixel(display, colormap, name, pixel)
Display *display;
Colormap colormap;
char *name;
unsigned long *pixel;
{
XColor c, e_c;
Status status;
if (name[0] == '#') {
status = XParseColor(display, colormap, name, &c);
if (status != 0) {
status = XAllocColor(display, colormap, &c);
}
} else {
status = XAllocNamedColor(display, colormap, name, &c, &e_c);
}
if (status == 0) {
return(-1);
} else {
*pixel = c.pixel;
return(0);
}
}
unsigned long
_XipReadRdb(display, ic, mask, rdb, res_name, res_class)
Display *display;
XipIC ic;
unsigned long mask;
XrmDatabase rdb;
char *res_name;
char *res_class;
{
XipIM im = ipIMofIC(ic);
unsigned long ret_mask = 0;
char name_prefix[256], class_prefix[256];
char res_name_buf[256], res_class_buf[256];
/*
char def_fontset[256];
*/
#ifdef XML
char def_language[256];
#endif /* XML */
char def_fg_name[256], def_bg_name[256];
unsigned long def_fg, def_bg;
char *str_type[20];
XrmValue value;
XIMArg args[8], pre_args[4], st_args[4];
int count = 0, pre_count = 0, st_count = 0;
Colormap colormap, def_colormap;
XWindowAttributes win_info;
if (rdb == NULL) {
return(0);
}
if (ic->core.client_window) {
XGetWindowAttributes(display, ic->core.client_window, &win_info);
} else {
XGetWindowAttributes(display,
RootWindow(display, DefaultScreen(display)),
&win_info);
}
def_colormap = win_info.colormap;
if (res_name == NULL || *res_name == '\0'
|| res_class == NULL || *res_class == '\0') {
strcpy(name_prefix, "*.");
strcpy(class_prefix, "*.");
} else {
strcpy(name_prefix, res_name);
strcpy(class_prefix, res_class);
strcat(name_prefix, ".");
strcat(class_prefix, ".");
}
if (!(mask & ((1 << ICForeground) | (1 << (ICForeground + StatusOffset))))){
strcpy(res_name_buf, name_prefix);
strcpy(res_class_buf, class_prefix);
strcat(res_name_buf, "foreground");
strcat(res_class_buf, "Foreground");
if (XrmGetResource(rdb, res_name_buf, res_class_buf,
str_type, &value) == True) {
strncpy(def_fg_name, value.addr, (int)value.size);
if (ic->core.preedit_attr.colormap) {
colormap = ic->core.preedit_attr.colormap;
} else {
colormap = def_colormap;
}
if (_StringToPixel(display, colormap, def_fg_name, &def_fg) == 0) {
if (!(mask & (1 << ICForeground))) {
pre_args[pre_count].name = (char *)XNForeground;
pre_args[pre_count].value = (XPointer)def_fg;
pre_count++;
}
if (!(mask & (1 << (ICForeground + StatusOffset)))) {
st_args[st_count].name = (char *)XNForeground;
st_args[st_count].value = (XPointer)def_fg;
st_count++;
}
} else {
fprintf(stderr, "XIM: Could not Alloc color \"%s\".",
def_fg_name);
}
}
}
if (!(mask & ((1 << ICBackground) | (1 << (ICBackground + StatusOffset))))){
strcpy(res_name_buf, name_prefix);
strcpy(res_class_buf, class_prefix);
strcat(res_name_buf, "background");
strcat(res_class_buf, "Background");
if (XrmGetResource(rdb, res_name_buf, res_class_buf,
str_type, &value) == True) {
strncpy(def_bg_name, value.addr, (int)value.size);
if (ic->core.preedit_attr.colormap) {
colormap = ic->core.preedit_attr.colormap;
} else {
colormap = def_colormap;
}
if (_StringToPixel(display, colormap, def_bg_name, &def_bg) == 0) {
if (!(mask & (1 << ICBackground))) {
pre_args[pre_count].name = (char *)XNBackground;
pre_args[pre_count].value = (XPointer)def_bg;
pre_count++;
}
if (!(mask & (1 << (ICBackground + StatusOffset)))) {
st_args[st_count].name = (char *)XNBackground;
st_args[st_count].value = (XPointer)def_bg;
st_count++;
}
} else {
fprintf(stderr, "XIM: Could not Alloc color \"%s\".",
def_bg_name);
}
}
}
/*
if (!(mask & ((1 << ICFontSet) | (1 << (ICFontSet + StatusOffset))))) {
strcpy(res_name_buf, name_prefix);
strcpy(res_class_buf, class_prefix);
strcat(res_name_buf, "fontSet");
strcat(res_class_buf, "FontSet");
if (XrmGetResource(rdb, res_name_buf, res_class_buf,
str_type, &value) == True) {
strncpy(def_fontset, value.addr, value.size);
if (!(mask & (1 << ICFontSet))) {
pre_args[pre_count].name = (char *)XNFontSet;
pre_args[pre_count].value = (XPointer)def_fontset;
pre_count++;
}
if (!(mask & (1 << (ICFontSet + StatusOffset)))) {
st_args[st_count].name = (char *)XNForeground;
st_args[st_count].value = (XPointer)def_fg;
st_count++;
}
}
}
*/
#ifdef XML
if (!(mask & (1 << ICUsingLanguage))) {
strcpy(res_name_buf, name_prefix);
strcpy(res_class_buf, class_prefix);
strcat(res_name_buf, "usingLanguage");
strcat(res_class_buf, "usingLanguage");
if (XrmGetResource(rdb, res_name_buf, res_class_buf,
str_type, &value) == True) {
strncpy(def_language, value.addr, (int)value.size);
args[count].name = (char *)XNUsingLanguage;
args[count].value = (XPointer)def_language;
count++;
}
}
#endif /* XML */
if(pre_count) {
pre_args[pre_count].name = (char *)NULL;
(void)_XipICSetAttrValues(im, pre_args, &ic->core.preedit_attr,
&ret_mask, 0);
}
if(st_count) {
st_args[st_count].name = (char *)NULL;
(void)_XipICSetAttrValues(im, st_args, &ic->core.status_attr,
&ret_mask, StatusOffset);
}
if (count) {
args[count].name = (char *)NULL;
(void)_XipICSetValues(ic, args, &ret_mask);
}
return(ret_mask);
}
Bool
_XipCreateDefIC(im)
XipIM im;
{
im->default_ic = (XipIC)Xcalloc(1, sizeof(XipICRec));
if (im->default_ic == NULL) {
return False;
}
im->default_ic->core.im = (XIM)im;
im->default_mask = _XipReadRdb(im->core.display, im->default_ic,
(unsigned long)0,
im->core.rdb, im->core.res_name,
im->core.res_class);
return True;
}
/*
* Create an input context within the input method,
* and return a pointer the input context ti the caller.
*/
XIC
_XipCreateIC(supim, args)
XIM supim;
XIMArg *args;
{
XipIM im = (XipIM)supim;
XipIC ic;
ximCreateICReq req;
ximCreateICReply reply;
ximEventReply reply1;
unsigned long mask;
extern Bool _XipBackEndFilter();
#ifdef XML
char *p, **nls_list, **l;
unsigned int i, n = 0;
XLocale xlc;
#endif /* XML */
/*
* If im is not specified or the file descripter is not available,
* return NULL.
*/
if (im->fd < 0) {
return(NULL);
}
if ((ic = (XipIC)Xcalloc(1, sizeof(XipICRec))) == NULL) {
return(NULL);
}
mask = im->default_mask;
if (mask)
bcopy((char *)&im->default_ic->values, (char *)&ic->values,
sizeof(struct _ICValues));
ic->methods = (XICMethods) &ic_methods;
ic->prototype_filter = _XipBackEndFilter;
ic->core.im = supim;
(void)_XipICSetValues(ic, args, &mask);
req.reqType = XIM_CreateIC;
req.length = sz_ximCreateICReq + strlen(im->client_data);
if ((_XipWriteToIM(im, (char *)&req, sz_ximCreateICReq) < 0) ||
(_XipWriteToIM(im, im->client_data, strlen(im->client_data)) < 0) ||
(_XipFlushToIM(im) < 0)) {
return(NULL);
}
if (im->core.rdb && ic->values.res_name && ic->values.res_class) {
mask |= _XipReadRdb(im->core.display, ic, mask, im->core.rdb,
ic->values.res_name, ic->values.res_class);
}
#ifdef XML
if (im->xlc != NULL) {
#endif /* XML */
ic->mb = _XlcDupLocale(im->xlc);
ic->wc = _XlcDupLocale(im->xlc);
#ifdef XML
ic->xlc_num = 0;
ic->mb_temp = NULL;
ic->wc_temp = NULL;
n = strlen(im->xlc->xlc_db->lc_name) + 1;
if ((p = Xmalloc(n)) == NULL) return(NULL);
strcpy(p, im->xlc->xlc_db->lc_name);
p[n - 1] = 0;
ic->values.using_language = p;
mask |= (1 << ICUsingLanguage);
} else {
ic->mb = NULL;
ic->wc = NULL;
ic->xlc_num = 0;
if ((ic->mb_temp = (XLocale*)Xmalloc(sizeof(XLocale) * 32)) == NULL) {
return(NULL);
}
if ((ic->wc_temp = (XLocale*)Xmalloc(sizeof(XLocale) * 32)) == NULL) {
return(NULL);
}
_XlcListLocale(&nls_list);
for (l = nls_list; *l; l++) {
xlc = _XlcMakeLocale(*l);
if (!xlc)
continue;
ic->mb_temp[ic->xlc_num] = xlc;
ic->wc_temp[ic->xlc_num] = _XlcDupLocale(xlc);
n += strlen(ic->mb_temp[ic->xlc_num]->xlc_db->lc_name) + 1;
ic->xlc_num++;
}
Xfree((char *)nls_list);
if ((p = Xmalloc(n)) == NULL) return(NULL);
p[0] = '\0';
for (i = 0; i < ic->xlc_num; i++) {
strcat(p, ic->mb_temp[i]->xlc_db->lc_name);
strcat(p, ";");
}
p[n - 1] = '\0';
ic->values.using_language = p;
mask |= (1 << ICUsingLanguage);
}
#endif /* XML */
/*
* Attempt to send IC data to the input manager. If sending failed,
* free IC structure and return NULL.
*/
_XipSendICValues(ic, mask);
ic->max_of_ct = ic->max_of_wc = 0;
ic->ct_buf = NULL;
ic->wc_buf = NULL;
for (;;) {
if ((_XipReadFromIM(im, (char *)&reply1, sz_ximEventReply) < 0) ||
(reply1.state == 0xffff)) {
goto _err_ret;
}
if (reply1.detail == XIM_CALLBACK) {
/*
* Call the callback routines.
*/
if (_XipCallCallbacks(ic) < 0) {
goto _err_ret;
}
} else if (reply1.detail == XIM_IC) {
if (_XipReadFromIM(im, (char *)&reply, sz_ximCreateICReply) < 0) {
goto _err_ret;
}
if (reply.state != 0) {
goto _err_ret;
}
ic->icid = reply.xic;
break;
} else {
break;
}
}
/*
* Attempt to get current IC data from the input manager.
*/
_XipReceiveICValues(ic, (unsigned long)ICAllMask);
#ifdef XML
if (ic->xlc_num > 0) {
for (i = 0; i < ic->xlc_num; i++) {
if (!strcmp(ic->values.current_language,
ic->mb_temp[i]->xlc_db->lc_name)) {
ic->mb = ic->mb_temp[i];
ic->wc = ic->wc_temp[i];
break;
}
}
if (ic->mb == NULL) {
ic->mb = ic->mb_temp[0];
ic->wc = ic->wc_temp[0];
}
}
#endif /* XML */
return((XIC)ic);
_err_ret:
if (ic->mb) _XlcFreeLocale(ic->mb);
if (ic->wc) _XlcFreeLocale(ic->wc);
#ifdef XML
if (ic->xlc_num > 0) {
for (i = 0; i < ic->xlc_num; i++) {
_XlcFreeLocale(ic->mb_temp[i]);
_XlcFreeLocale(ic->wc_temp[i]);
}
}
if (ic->mb_temp) Xfree(ic->mb_temp);
if (ic->wc_temp) Xfree(ic->wc_temp);
if (ic->values.using_language) Xfree(ic->values.using_language);
#endif /* XML */
Xfree((char *)ic);
return(NULL);
}
/*
* Reset the input context.
*/
wchar_t *
_XipwcResetIC(ic)
XIC ic; /* specified the input context to reset*/
{
XipIM im = ipIMofIC((XipIC)ic);
ximResetICReq req;
ximEventReply reply;
/*
* If im is not specified or the file descripter is not available,
* return NULL.
*/
if (im->fd < 0) {
return((wchar_t *)NULL);
}
req.reqType = XIM_ResetIC;
req.length = sz_ximResetICReq;
req.xic = ((XipIC)ic)->icid;
if ((_XipWriteToIM(im, (char *)&req, sz_ximResetICReq) >= 0) &&
(_XipFlushToIM(im) >= 0)) {
for (;;) {
if ((_XipReadFromIM(im, (char *)&reply, sz_ximEventReply) < 0) ||
(reply.state == 0xffff)) {
return((wchar_t *)NULL);
}
if (reply.detail == XIM_CALLBACK) {
/*
* Call the callback routines.
*/
if (_XipCallCallbacks(ic) < 0) {
return((wchar_t *)NULL);
}
} else {
break;
}
}
}
return((wchar_t *)NULL);
}
char *
_XipmbResetIC(ic)
XIC ic; /* specified the input context to reset*/
{
XipIM im = ipIMofIC((XipIC)ic);
ximResetICReq req;
ximEventReply reply;
/*
* If im is not specified or the file descripter is not available,
* return NULL.
*/
if (im->fd < 0) {
return(NULL);
}
req.reqType = XIM_ResetIC;
req.length = sz_ximResetICReq;
req.xic = ((XipIC)ic)->icid;
if ((_XipWriteToIM(im, (char *)&req, sz_ximResetICReq) >= 0) &&
(_XipFlushToIM(im) >= 0)) {
for (;;) {
if ((_XipReadFromIM(im, (char *)&reply, sz_ximEventReply) < 0) ||
(reply.state == 0xffff)) {
return(NULL);
}
if (reply.detail == XIM_CALLBACK) {
/*
* Call the callback routines.
*/
if (_XipCallCallbacks(ic) < 0) {
return(NULL);
}
} else {
break;
}
}
}
return(NULL);
}
#ifdef XML
void
_XipChangeLocale(ic, lc_name)
XipIC ic;
char *lc_name;
{
XLocale xlc;
int i;
for (i = 0; i < ic->xlc_num; i++) {
if ((!strcmp(lc_name, ic->mb_temp[i]->lc_lang)) ||
(!strcmp(lc_name, ic->mb_temp[i]->xlc_db->lc_name))) {
ic->mb = ic->mb_temp[i];
ic->wc = ic->wc_temp[i];
return;
}
}
xlc = _XlcMakeLocale(lc_name);
if (xlc) {
ic->mb = ic->mb_temp[ic->xlc_num] = xlc;
ic->wc = ic->wc_temp[ic->xlc_num] = _XlcDupLocale(xlc);
ic->xlc_num++;
}
}
#endif /* XML */