1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00
cde/cde/programs/dtimsstart/start.c
2018-06-28 04:19:15 +01:00

949 lines
22 KiB
C

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they 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 these libraries and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/* @(#)$TOG: start.c /main/9 1998/04/06 13:36:49 mgreess $ */
#include "xims.h"
#include <signal.h>
#include <sys/wait.h>
#include <setjmp.h>
#include <unistd.h>
#if (defined(__linux__) || defined(CSRG_BASED)) && !defined(_NFILE)
#define _NFILE FOPEN_MAX
#endif
#if !defined(__linux__) && !defined(CSRG_BASED)
extern char *sys_errlist[];
extern int sys_nerr;
#endif
/* local functions */
static int check_ims_opt(/* ptr */);
static char *find_session_resfile(/* res_type */);
static int check_selection(/* sel */);
static int build_run_env(/* sel */);
static int run_ims(/* sel */);
static int invoke_ims(/* sel */);
static void on_sig_chld(/* sig */);
static bool is_ims_running(/* renv, ims */);
static int settle_ims(/* sel */);
static Window property_owner(/* prop_atom, prop_str */);
# ifdef old_hpux
static void catch_alarm(/* sig */);
static int try_connection(/* sel */);
static int create_dummy_ic(/* xim */);
# endif /* old_hpux */
void ximsStart(void)
{
int ret;
UserSelection *sel = &userSel;
OpStateVal oldOpState = OpState;
DPR(("ximsStart(): OpState=%s OpErrCode=%s[%d]\n",
StateName(), error_name(OpErrCode), OpErrCode));
OpState = State_Start;
#ifdef DEBUG
if (DebugLvl > 1) pr_UserSelection(sel);
#endif
ret = NoError;
if (oldOpState == State_Select_Err) {
/* don't change OpErrCode */
OpState = State_Start_Err;
return;
}
if (oldOpState == State_Select_Canceled) {
clear_UserSelection(sel);
ret = ErrNoSelection;
} else { /* save selection */
if (!(OpFlag & FLAG_NOSAVE) && (sel->flag & F_SELECT_CHANGED)) {
if (save_user_selection(sel, NULL) != NoError) {
DPR(("save_user_selection(): failed\n"));
put_xims_warnmsg(ErrSaveSelection, 0, 0, 0);
/* ret = ErrSaveSelection; */
}
}
}
if (ret != NoError) {
OpErrCode = ret;
OpState = State_Start_Err;
return;
}
if ((ret = check_selection(sel)) != NoError) {
if (ret == ErrIsNone || ret == ErrNotRun) {
build_run_env(sel); /* for make_new_environ() */
}
OpErrCode = ret;
OpState = State_Start_Done;
return;
}
build_run_env(sel);
if (useWINDOW()) /* initilaize Xt */
init_window_env();
ret = run_ims(sel);
OpErrCode = ret;
OpState = ret == NoError ? State_Start_Done : State_Start_Err;
return;
}
void ximsWait(void)
{
OpStateVal oldOpState = OpState;
UserSelection *sel = &userSel;
struct timeval interval;
time_t start_tm = 0;
int lapse;
DPR(("ximsWait(): OpState=%s OpErrCode=%s[%d]\n",
StateName(), error_name(OpErrCode), OpErrCode));
OpState = State_Wait;
if (oldOpState == State_Start_Err) {
/* don't change OpErrCode */
OpState = State_Wait_Err;
return;
}
if (!is_waiting() || (OpFlag & FLAG_NOWAIT)) {
ximsWaitDone();
}
if (im_mod_available(sel->renv) != 1) {
if (useWINDOW()) {
xt_start_waiting(); /* never returns unless failed */
}
/* waiting */
lapse = 0;
interval.tv_sec = Opt.Interval / 1000;
interval.tv_usec = (Opt.Interval % 1000) * 1000;
start_tm = time((time_t) 0);
while (is_waiting()) {
select(0, 0, 0, 0, &interval); /* usleep */
lapse = (int) time((time_t) 0) - start_tm;
if (im_mod_available(sel->renv) != 0 || lapse >= Opt.Timeout) {
DPR(("ximsWait(tmout=%d): wait done (%d sec.)\n",
Opt.Timeout, lapse));
break;
}
}
}
ximsWaitDone();
}
void ximsWaitDone(void)
{
int ret;
UserSelection *sel = &userSel;
DPR(("ximsWaitDone():\tOpState=%s OpErrCode=%s[%d]\n",
StateName(), error_name(OpErrCode), OpErrCode));
set_sig_chld(False);
ret = sel->renv->status;
switch (ret) {
case ErrImsWaiting:
sel->status = ErrImsTimeout;
put_xims_log("'%s' timed-out.", sel->name, 0, 0);
break;
case ErrImsWaitDone:
sel->status = NoError;
# ifdef old_hpux
if ((OpFlag & FLAG_CONNECT)
|| (sel->ent->ims->flags & F_TRY_CONNECT)) {
sel->status = try_connection(sel);
}
# endif /* old_hpux */
break;
case ErrImsConnecting:
case ErrImsConnectDone:
sel->status = NoError;
break;
case ErrImsAborted:
/* put_xims_log("'%s' aborted.", sel->name, 0, 0); */
case ErrImsExecution:
default:
sel->status = ret;
break;
}
if (sel->status != NoError) {
OpErrCode = sel->status;
DPR(("ximsWaitDone(): OpErrCode=%s[%d]\n",
error_name(OpErrCode), OpErrCode));
}
restore_resources();
settle_ims(sel); /* clear WM_COMMAND property */
OpState = OpErrCode == NoError ? State_Wait_Done : State_Wait_Err;
ximsMain();
}
int is_waiting(void)
{
return userSel.renv && userSel.renv->status == ErrImsWaiting;
}
void set_sig_chld(int enable)
{
DPR(("set_sig_chld(%s)\n", enable ? "Enabled" : "Disabled"));
signal(SIGCHLD, enable ? on_sig_chld : SIG_IGN);
}
int im_mod_available(RunEnv *renv)
{
Window owner;
if (!renv) {
if (!(renv = userSel.renv))
return -1;
}
if (renv->status != ErrImsWaiting)
return -1;
#ifdef DEBUG
if (DebugLvl >= 1) putc('.', LogFp), fflush(LogFp);
#endif
owner = property_owner(&renv->prop_atom, renv->atom_name);
if (owner != None) {
#ifdef ReconfirmProperty
{
int wait_period = 2; /* 2 sec. */
DPR(("im_mod_available(): [RECONFIRM] sleep(%d)\n", wait_period));
sleep(wait_period);
if (property_owner(&renv->prop_atom, renv->atom_name) == None) {
DPR(("\t[RECONFIRM] owner lost\n"));
return 0;
}
}
#endif /* ReconfirmProperty */
#ifdef DEBUG
if (DebugLvl >= 1) putc('\n', LogFp), fflush(LogFp);
#endif
DPR2(("check_im_mod(): wait done\n"));
renv->status = ErrImsWaitDone;
return 1;
}
return 0;
}
/* ***** IMS options ***** */
int mk_ims_option(char *ptr, UserSelection *sel)
{
char *bp = ptr;
FileSel *fsel = sel->fsel;
ImsConf *ims = sel->ent->ims;
*bp = 0;
if (ims->flags & F_NO_OPTION) /* not applicable */
return 0;
if (fsel) {
if (fsel->com_opt /* common option */
&& check_ims_opt(fsel->com_opt)) {
/* bp = strcpyx(bp, fsel->com_opt); */
bp += expand_string(fsel->com_opt, bp, BUFSIZ, ims);
*bp++ = ' ';
}
if (fsel->opts) { /* individual option */
ImsOpt **op;
for (op = fsel->opts; *op; op++) {
if (strcmp((*op)->ims_name, sel->name) == 0
&& check_ims_opt((*op)->opt_str)) {
/* bp = strcpyx(bp, (*op)->opt_str); */
bp += expand_string((*op)->opt_str, bp, BUFSIZ, ims);
*bp++ = ' ';
}
}
}
}
if (Opt.ImsOption && check_ims_opt(Opt.ImsOption)) {
/* bp = strcpyx(bp, Opt.ImsOption); */
bp += expand_string(Opt.ImsOption, bp, BUFSIZ, ims);
}
if (sel->iconic > 0 && strstr(ptr, STR_ICONIC_OPT) == NULL) {
bp = strcpyx(bp, STR_ICONIC_OPT);
}
*bp = 0;
return (int) (bp - ptr);
}
static int check_ims_opt(char *ptr)
{
/* option string must not contain any of shell's metacaharacters */
if (strpbrk(ptr, "`'\"#;&()|<>\n")) {
put_xims_log("ims option ignored: %s", ptr, 0, 0);
DPR(("\tshell's meta-char in option \"%s\" -- ignored\n", ptr));
return False;
}
return True;
}
/* ******** resource ******** */
#define RES_TYPE_DT 0
#define RES_TYPE_VUE 1
static bool resource_loaded = False;
int load_resources(void)
{
int ret;
int empty;
char *sess_res, *res_file;
if (resource_loaded) {
DPR2(("load_resources: already done -- not loaded\n"));
return False;
}
empty = !save_RM();
if (!empty) { /* load if RESOURCE_MANAGER is empty */
DPR2(("load_resources: RESOURCE_MANGER is not empty -- not loaded\n"));
return False;
}
sess_res = res_file = NULL;
if (!(OpFlag & FLAG_NORESOURCE)) {
if (isDT()) {
sess_res = find_session_resfile(RES_TYPE_DT);
}
# ifdef old_hpux
else if (isVUE()) {
sess_res = find_session_resfile(RES_TYPE_VUE);
}
# endif /* old_hpux */
if (sess_res && !is_readable(sess_res, False)) {
FREE(sess_res);
sess_res = NULL;
}
}
if (Opt.ResourceFile && is_readable(Opt.ResourceFile, False))
res_file = Opt.ResourceFile;
DPR(("load_resources():\tsess='%s' res='%s'\n", sess_res, res_file));
if (!isDT() && !sess_res && !res_file) return False;
if ((ret = open_display()) != NoError) return False;
ret = merge_RM(sess_res, res_file);
resource_loaded = True;
if (sess_res) FREE(sess_res);
return ret;
}
int restore_resources(void)
{
if (!resource_loaded) {
DPR2(("restore_resources: not loaded yet -- not restored\n"));
return False;
}
resource_loaded = False;
return restore_RM();
}
static char *find_session_resfile(int res_type)
{
char path[MAXPATHLEN];
char **ls = (char **) 0, **pp;
char *res = NULL;
bool found = False;
if (res_type == RES_TYPE_DT) { /* DT */
res = Conf.dt ? (Conf.dt)->resPath : NULL;
}
# ifdef old_hpux
else if (res_type == RES_TYPE_VUE && Conf.vue) { /* VUE */
VueEnv *vue = Conf.vue;
res = vue->resPath;
if (vue->uselite) {
expand_string(vue->uselite, path, MAXPATHLEN, (ImsConf *)0);
if (access(path, R_OK) == 0)
res = vue->litePath;
}
}
# endif /* old_hpux */
if (!res) return NULL;
if (ls = parse_strlist(res, ':')) {
for (pp = ls; *pp; pp++) {
expand_string(*pp, path, MAXPATHLEN, (ImsConf *)0);
if (access(path, R_OK) == 0) {
found = True;
break;
}
}
FREE_LIST(ls);
}
/* DPR2(("find_session_resfile(): '%s'\n", path)); */
if (found)
return NEWSTR(path);
return NULL;
}
/* ***** local functions ***** */
static int check_selection(UserSelection *sel)
{
int ret = NoError;
if (!sel->name || !sel->list)
ret = ErrNoSelection;
else if (sel->ims_idx < 0 || sel->ims_idx >= sel->list->num_ent)
ret = ErrNoSelection;
else if (sel->status != NoError)
ret = sel->status;
else if (strcmp(sel->name, NAME_NONE) == 0)
ret = sel->status = ErrIsNone;
else if (sel->ent->ims->flags & F_NO_SERVER)
ret = sel->status = ErrNotRun;
else if (OpFlag & FLAG_NOSTART)
ret = sel->status = ErrNotRun;
return ret;
}
static int build_run_env(UserSelection *sel)
{
char *p;
int proto;
int len;
int tmout, intv;
char *log_path;
char *bp;
char envbuf[BUFSIZ], optbuf[BUFSIZ];
RunEnv *renv;
ImsConf *ims = sel->ent->ims;
char *cmd_param = ims->cmd_param ? ims->cmd_param : "";
renv = ALLOC(1, RunEnv);
renv->is_remote = sel->host_type == HOST_REMOTE ? True : False;
/* proto, im_mod & atom */
proto = renv->proto = default_protocol(ims);
if (p = Conf.xmod[proto]) {
char buf[BUFSIZ];
expand_string(p, buf, BUFSIZ, ims);
renv->im_mod = NEWSTR(buf);
}
if (p = Conf.atom[proto]) {
char buf[BUFSIZ];
expand_string(p, buf, BUFSIZ, ims);
renv->atom_name = NEWSTR(buf);
} else { /* copy im_mod, instead */
renv->atom_name = NEWSTR(renv->im_mod);
# ifdef old_hpux
if ((p = renv->atom_name) && strchr(p, '#')) {
while (p = strchr(p, '#')) /* replace '#' with '@' */
*p++ = '@';
}
# endif /* old_hpux */
}
/* others */
renv->pid = (pid_t) 0;
renv->status = NoError;
renv->wait_status = 0;
sel->renv = renv;
if (sel->status != NoError) /* ErrIsNone or ErrNotRun */
return sel->status;
if (renv->is_remote)
return NoError;
/* command line */
optbuf[0] = envbuf[0] = 0;
log_path = Opt.LogPath;
bp = envbuf;
/* set XMODIFIERS */
bp = strcpyx(bp, "XMODIFIERS='");
bp = strcpyx(bp, ENV_MOD_IM);
bp = strcpyx(bp, renv->im_mod);
bp = strcpyx(bp, "'");
*bp = 0;
/* Local, LANG & DISPLAY have been already set to *environ by putenv() */
/* IMS options */
mk_ims_option(optbuf, sel);
/* len = sysconf(_SC_ARG_MAX) / 2; len = Max(len, BUFSIZ); */
len = strlen(envbuf) + strlen(ims->cmd_path)
+ strlen(cmd_param) + strlen(optbuf) + strlen(log_path) + 40;
/* for local execution */
renv->cmdbuf = ALLOC(len, char);
sprintf(renv->cmdbuf, " %s; export XMODIFIERS; exec %s %s %s >> %s 2>&1 ",
envbuf, ims->cmd_path, cmd_param, optbuf, log_path);
/* timeout & interval */
if (Opt.Timeout > 0) tmout = Opt.Timeout;
else if (ims->timeout > 0) tmout = ims->timeout;
else tmout = DEFAULT_TIMEOUT;
if (Opt.Interval > 0) intv = Opt.Interval;
else if (ims->interval > 0) intv = ims->interval;
else intv = DEFAULT_INTERVAL;
tmout = Max(tmout, MIN_TIMEOUT);
intv = Max(intv, MIN_INTERVAL);
if (intv/1000 > tmout) intv = tmout * 1000;
/* else if (intv/10 < tmout) intv = tmout * 10; */
Opt.Timeout = tmout;
Opt.Interval = intv;
#ifdef DEBUG
if (DebugLvl >= 1) pr_RunEnv(sel->renv);
DPR(("build_run_env(): Timeout=%d (sec) Interval=%d (msec)\n",
tmout, intv));
#endif
return NoError;
}
static int run_ims(UserSelection *sel)
{
int ret = NoError;
if ((ret = open_display()) != NoError)
return ret;
if (is_ims_running(sel->renv, sel->ent->ims)) {
sel->status = ErrImsRunning;
DPR(("run_ims(): '%s' is already running\n", sel->name));
return sel->status;
}
load_resources();
if (sel->renv->is_remote) {
/* ret = set_host_acss(sel->hostname); */
ret = exec_remote_ims(sel);
return ret;
}
ret = invoke_ims(sel);
return ret;
}
static int invoke_ims(UserSelection *sel)
{
RunEnv *renv = sel->renv;
pid_t pid;
int i;
set_sig_chld(True);
pid = fork();
if (pid == (pid_t) -1) {
put_xims_log("fork failed [%s]",
(errno <= sys_nerr) ? sys_errlist[errno] : NULL, 0, 0);
#ifdef DEBUG
perror("fork");
#endif
return renv->status = ErrImsExecution;
}
if (pid == (pid_t) 0) { /* child */
for (i = 0; i < _NFILE; i++)
(void) close(i);
#if defined(CSRG_BASED)
setsid();
#else
setpgrp();
#endif
execl(SH_PATH, "sh", "-c", renv->cmdbuf, NULL);
put_xims_log("%s: exec failed [%s]", SH_PATH,
(errno <= sys_nerr) ? sys_errlist[errno] : NULL, 0, 0);
/* perror(SH_PATH); */
sleep(1);
_exit(1);
}
/* parent */
renv->pid = pid;
renv->wait_status = 0;
renv->status = ErrImsWaiting;
put_xims_log("'%s' started for %s", sel->name, userEnv.displayname, 0);
DPR(("invoke_ims(%s): pid=%d\n", sel->name, pid));
return NoError;
}
static void on_sig_chld(int sig)
{
int wait_status = 0;
pid_t pid;
int cause;
RunEnv *renv = userSel.renv;
errno = 0;
do {
#ifdef _XPG4_EXTENDED
pid = wait3(&wait_status, WNOHANG, (struct rusage *)NULL);
#else
pid = waitpid((pid_t) -1, &wait_status, WNOHANG);
#endif /* _XPG4_EXTENDED */
} while (pid == -1 && errno == EINTR);
DPR(("\ton_sig_chld(): pid=%d errno=%d\n", pid, errno));
if (pid == -1)
return;
signal(SIGCHLD, on_sig_chld);
if (WIFEXITED(wait_status)) {
cause = ErrImsAborted;
} else if (WIFSIGNALED(wait_status)) {
cause = ErrImsAborted;
} else { /* WIFSTOPPED(wait_status) */
return;
}
if (renv->pid == pid) {
if (renv->status == ErrImsWaiting || renv->status == ErrImsConnecting) {
renv->status = cause;
renv->wait_status = wait_status;
DPR(("on_sig_chld(): '%s' aborts (wait_status=%#x)\n",
userSel.name, wait_status));
put_xims_log("'%s' aborted.", userSel.name, 0, 0);
ximsWaitDone();
}
#ifdef DEBUG
else {
DPR(("\tsig_chld: renv->state=%s is not ErrImsWaiting\n",
error_name(renv->status)));
}
#endif
}
#ifdef DEBUG
else {
DPR(("\tsig_chld: pid=%d != renv->pid=%d\n", pid, renv->pid));
}
#endif
return;
}
static bool is_ims_running(RunEnv *renv, ImsConf *ims)
{
char *prop_str;
Window owner;
Atom *atomp;
if (prop_str = ims->property) {
atomp = (Atom *)0;
} else {
if (!(prop_str = renv->atom_name))
return False;
atomp = &renv->prop_atom;
}
owner = property_owner(atomp, prop_str);
DPR2(("is_ims_running(): prop='%s'[%d] owned by %#x\n",
prop_str, atomp ? *atomp : -1, owner));
#ifdef unused
/* check primary server name for XIM */
if (owner == None && !ims->property && renv->proto == Proto_XIM
&& ims->server_name2 && strstr(renv->atom_name, ims->server_name2) {
char buf[BUFSIZ], *p;
prop_str = strcpy(buf, renv->atom_name);
if (p = strchr(prop_str, '=')) {
strcpy(p + 1, ims->servername);
atomp = (Atom *)0;
owner = property_owner(atomp, prop_str);
DPR2(("is_ims_running(): prop='%s'[%d] owned by %#x\n",
prop_str, atomp ? *atomp : -1, owner));
}
}
#endif
return owner == None ? False : True;
}
static int settle_ims(UserSelection *sel)
{
if (isXsession()) {
char *prop_str;
Window owner;
Atom *atomp;
ImsConf *ims = sel->ent->ims;
owner = None;
if (prop_str = ims->property) {
atomp = (Atom *)0;
owner = property_owner(atomp, prop_str);
}
#if 0
else if (sel->renv) {
if (prop_str = sel->renv->atom_name)
owner = search_clear_cmd_property(prop_str);
}
#endif
if (owner)
clear_cmd_property(owner);
}
return NoError;
}
static Window property_owner(Atom *prop_atom, char *prop_str)
{
Atom property = prop_atom ? *prop_atom : None;
if (property == None) {
property = XInternAtom(Dpy, prop_str, True);
if (property == None)
return None;
if (prop_atom)
*prop_atom = property;
}
return XGetSelectionOwner(Dpy, property);
}
# ifdef old_hpux
/* ***** try_connection ***** */
#define MAX_RETRY 5
static jmp_buf jmp_env;
static Window dmy_win = 0; /* temporary window used for XCreateIC() */
static void catch_alarm(int sig)
{
signal(SIGALRM, SIG_IGN);
alarm(0);
longjmp(jmp_env, 1);
}
static int try_connection(UserSelection *sel)
{
RunEnv *renv = sel->renv;
ImsConf *ims = sel->ent->ims;
char envbuf[BUFSIZ], *bp;
XIM xim;
int ic_ok, retry_cnt;
static char *saved_xmod = NULL;
#ifdef DEBUG
time_t last_time;
#endif
DPR(("try_connection(%s):\n", sel->name));
if (sel->status != NoError || !renv->im_mod)
return sel->status;
renv->status = ErrImsConnecting;
set_sig_chld(True);
/* set XMODIFIERS */
saved_xmod = NULL;
bp = strcpyx(envbuf, ENV_MOD_IM);
bp = strcpyx(bp, renv->im_mod);
saved_xmod = XSetLocaleModifiers(envbuf);
DPR(("\tXSetLocaleModifiers(%s)\n", envbuf));
ic_ok = False;
if (setjmp(jmp_env) == 0) {
signal(SIGALRM, catch_alarm);
alarm(Opt.Timeout);
for (retry_cnt = 0; !ic_ok && retry_cnt <= MAX_RETRY; retry_cnt++) {
if (retry_cnt) sleep(retry_cnt * retry_cnt);
#ifdef DEBUG
last_time = time((time_t)0);
#endif
xim = XOpenIM(Dpy, (XrmDatabase)0, ims->servername, ims->classname);
if (xim) {
DPR(("try_connection(%d): XOpenIM() OK [%d sec.]",
retry_cnt, time((time_t)0) - last_time));
#ifdef DEBUG
last_time = time((time_t)0);
#endif
ic_ok = create_dummy_ic(xim);
DPR(("\tXCreateIC() %s [%d sec.]\n",
ic_ok ? "OK" : "Failed", time((time_t)0) - last_time));
XCloseIM(xim); xim = 0;
} else {
DPR(("try_connection(%d): XOpenIM() failed.\n", retry_cnt));
ic_ok = False;
}
}
} else { /* long_jmp() by alarm [timeout] */
alarm(0); signal(SIGALRM, SIG_IGN);
DPR(("try_connection(): XOpenIM() & XCreateIC() timed-out.\n"));
if (dmy_win) {
XDestroyWindow(Dpy, dmy_win); dmy_win = 0;
}
/* neither XDestroyIC() nor XCloseIM() should be called */
xim = 0;
ic_ok = False;
}
alarm(0); signal(SIGALRM, SIG_IGN);
/* restore XMODIFIERS */
if (saved_xmod) {
DPR2(("\tXSetLocaleModifiers(save='%s')\n", saved_xmod));
XSetLocaleModifiers(saved_xmod);
}
set_sig_chld(False);
renv->status = ErrImsConnectDone;
return ic_ok ? NoError : ErrImsTimeout; /* ErrImsConnect; */
}
static int create_dummy_ic(XIM xim)
{
int scr;
XFontSet fset;
XIMStyles *im_styles;
XIMStyle style;
XIC ic;
unsigned long fg, bg;
XRectangle area;
XVaNestedList status_attr;
scr = DefaultScreen(Dpy);
fg = BlackPixel(Dpy, scr);
bg = WhitePixel(Dpy, scr);
dmy_win = XCreateSimpleWindow(Dpy, RootWindow(Dpy, scr),
0, 0, 1, 1, 0, bg, fg);
/* search (PreeditNothing | StatusNothing [or StatusArea]) style */
ic = 0;
style = (XIMStyle) 0;
im_styles = (XIMStyles *) 0;
if (XGetIMValues(xim, XNQueryInputStyle, &im_styles, NULL)) {
DPR(("create_dummy_ic(): XGetIMValues(XNQueryInutStyle) failed.\n"));
goto _err;
}
if (!im_styles || !im_styles->count_styles) {
DPR(("create_dummy_ic(): No input styles supported on IMS.\n"));
if (im_styles) XFree(im_styles);
goto _err;
}
if ((int)im_styles->count_styles > 0) {
int i, alt;
for (i = 0, alt = -1; i < (int)im_styles->count_styles; i++)
if (im_styles->supported_styles[i] & XIMPreeditNothing) {
if (im_styles->supported_styles[i] & XIMStatusNothing) {
style = im_styles->supported_styles[i];
break;
} else if (im_styles->supported_styles[i] & XIMStatusArea) {
alt = i;
}
}
if (!style && alt >= 0) style = im_styles->supported_styles[alt];
XFree(im_styles);
}
if (!style) {
DPR(("create_dummy_ic(): 'PreeditNothing' styles not supported.\n"));
goto _err;
/* style = XIMPreeditNothing | XIMStatusNothing; */
}
fset = 0;
status_attr = (XVaNestedList) 0;
if (style & XIMStatusArea) {
area.x = area.y = 0; area.width = area.height = 1;
status_attr = XVaCreateNestedList(NULL,
XNArea, &area,
XNForeground, fg,
XNBackground, bg,
XNFontSet, fset,
NULL );
}
ic = XCreateIC(xim, XNInputStyle, style,
XNClientWindow, dmy_win,
XNStatusAttributes, status_attr,
XNFocusWindow, dmy_win,
NULL );
/* if (fset) XFreeFontSet(Dpy, fset); */
if (ic) XDestroyIC(ic);
_err:
if (dmy_win) XDestroyWindow(Dpy, dmy_win);
dmy_win = 0;
return ic ? True : False;
}
# endif /* old_hpux */