blob: 68de1085509e2f31734e1c216a36f798e3e3f26f [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_vcl.hxx"
struct XIMArg
{
char *name;
char *value;
};
#if defined(SOLARIS) && !defined(__GNUC__)
#include <varargs.h>
#else
#include <stdarg.h>
#endif
#include <sal/alloca.h>
#include <string.h>
#include <dlfcn.h>
#include <X11/Xlib.h>
#include <X11/Xlibint.h>
#include "unx/XIM.h"
#define XIIIMP_LIB "xiiimp.so.2"
#ifdef SOLARIS
#define XIIIMP_PATH "/usr/openwin/lib/locale/common/" XIIIMP_LIB
#else /* Linux */
#define XIIIMP_PATH "/usr/lib/im/" XIIIMP_LIB
#endif
extern "C" {
typedef XIM (*OpenFunction)(Display*, XrmDatabase, char*, char*, XIMArg*);
}
/* global variables */
static void *g_dlmodule = 0;
static OpenFunction g_open_im = (OpenFunction)NULL;
/* utility function to transform vararg list into an array of XIMArg */
int
XvaCountArgs( XIMArg *pInArgs )
{
int nArgs = 0;
char *pName, *pValue;
while ( (pName = pInArgs->name) != NULL )
{
pValue = pInArgs->value;
if ( strcmp(pName, XNVaNestedList) == 0 )
{
nArgs += XvaCountArgs( (XIMArg*)pValue );
}
else
{
nArgs += 1;
}
pInArgs++;
}
return nArgs;
}
int
XvaCountArgs( va_list pInArgs )
{
int nArgs = 0;
char *pName, *pValue;
while ( (pName = va_arg(pInArgs, char*)) != NULL)
{
pValue = va_arg(pInArgs, char*);
if ( strcmp(pName, XNVaNestedList) == 0 )
{
nArgs += XvaCountArgs( (XIMArg*)pValue );
}
else
{
nArgs += 1;
}
}
return nArgs;
}
XIMArg*
XvaGetArgs( XIMArg *pInArgs, XIMArg *pOutArgs )
{
char *pName, *pValue;
while ( (pName = pInArgs->name) != NULL )
{
pValue = pInArgs->value;
if ( strcmp(pName, XNVaNestedList) == 0 )
{
pOutArgs = XvaGetArgs( (XIMArg*)pValue, pOutArgs );
}
else
{
pOutArgs->name = pName;
pOutArgs->value = pValue;
pOutArgs++;
}
pInArgs++;
}
return pOutArgs;
}
void
XvaGetArgs( va_list pInArgs, XIMArg *pOutArgs )
{
char *pName, *pValue;
while ((pName = va_arg(pInArgs, char*)) != NULL)
{
pValue = va_arg(pInArgs, char*);
if ( strcmp(pName, XNVaNestedList) == 0 )
{
pOutArgs = XvaGetArgs( (XIMArg*)pValue, pOutArgs );
}
else
{
pOutArgs->name = pName;
pOutArgs->value = pValue;
pOutArgs++;
}
}
pOutArgs->name = NULL;
pOutArgs->value = NULL;
}
/* Puplic functions */
#ifdef __cplusplus
extern "C"
#endif
XIM
XvaOpenIM(Display *display, XrmDatabase rdb,
char *res_name, char *res_class, ...)
{
XIM xim = (XIM)0;
va_list variable;
int total_count = 0;
/*
* so count the stuff dangling here
*/
#if defined(SOLARIS) && !defined(__GNUC__)
va_start(variable);
#else
va_start(variable, res_class);
#endif
total_count = XvaCountArgs(variable);
va_end(variable);
if (total_count > 0)
{
/* call a new open IM method */
XIMArg* args = (XIMArg*)alloca( (total_count + 1) * sizeof(XIMArg) );
/*
* now package it up so we can set it along
*/
#if defined(SOLARIS) && !defined(__GNUC__)
va_start(variable);
#else
va_start(variable, res_class);
#endif
XvaGetArgs( variable, args );
va_end(variable);
if (!g_dlmodule)
{
g_dlmodule = dlopen(XIIIMP_LIB, RTLD_LAZY);
if(!g_dlmodule)
{
g_dlmodule = dlopen(XIIIMP_PATH, RTLD_LAZY);
if (!g_dlmodule)
goto legacy_XIM;
}
g_open_im = (OpenFunction)(long)dlsym(g_dlmodule, "__XOpenIM");
if (!g_open_im)
goto legacy_XIM;
xim = (*g_open_im)(display, (XrmDatabase)rdb,
(char*)res_name, (char *)res_class, (XIMArg*)args);
}
else
{
goto legacy_XIM;
}
}
// in #if to prevent warning "warning: label 'legacy_XIM' defined but not used"
legacy_XIM:
if (!xim)
xim = XOpenIM(display, rdb, res_name, res_class);
return xim;
}
/*
* Close the connection to the input manager, and free the XIM structure
*/
Status XvaCloseIM(XIM)
{
Status s = False;
if (!g_dlmodule)
{
/* assuming one XvaOpenIM call */
dlclose(g_dlmodule);
g_dlmodule = (void*)0;
g_open_im = (OpenFunction)NULL;
s = True;
}
return (s);
}