diff options
Diffstat (limited to 'libX11/src')
-rw-r--r-- | libX11/src/CrGlCur.c | 540 | ||||
-rw-r--r-- | libX11/src/FSWrap.c | 524 | ||||
-rw-r--r-- | libX11/src/InitExt.c | 820 | ||||
-rw-r--r-- | libX11/src/KeyBind.c | 2156 | ||||
-rw-r--r-- | libX11/src/Makefile.am | 850 | ||||
-rw-r--r-- | libX11/src/Quarks.c | 826 | ||||
-rw-r--r-- | libX11/src/RdBitF.c | 524 | ||||
-rw-r--r-- | libX11/src/SetLocale.c | 508 | ||||
-rw-r--r-- | libX11/src/XlibInt.c | 4354 | ||||
-rw-r--r-- | libX11/src/Xrm.c | 5320 | ||||
-rw-r--r-- | libX11/src/xcms/LRGB.c | 3688 | ||||
-rw-r--r-- | libX11/src/xcms/PrOfId.c | 194 | ||||
-rw-r--r-- | libX11/src/xcms/cmsProp.c | 298 | ||||
-rw-r--r-- | libX11/src/xkb/XKBGAlloc.c | 2024 | ||||
-rw-r--r-- | libX11/src/xkb/XKBGeom.c | 1376 | ||||
-rw-r--r-- | libX11/src/xlibi18n/XDefaultIMIF.c | 940 | ||||
-rw-r--r-- | libX11/src/xlibi18n/XDefaultOMIF.c | 2526 | ||||
-rw-r--r-- | libX11/src/xlibi18n/XlcDL.c | 1224 | ||||
-rw-r--r-- | libX11/src/xlibi18n/lcCharSet.c | 450 | ||||
-rw-r--r-- | libX11/src/xlibi18n/lcDB.c | 2684 | ||||
-rw-r--r-- | libX11/src/xlibi18n/lcFile.c | 1658 | ||||
-rw-r--r-- | libX11/src/xlibi18n/lcGeneric.c | 2362 | ||||
-rw-r--r-- | libX11/src/xlibi18n/lcPublic.c | 630 |
23 files changed, 18238 insertions, 18238 deletions
diff --git a/libX11/src/CrGlCur.c b/libX11/src/CrGlCur.c index 4f332836b..510ff5d75 100644 --- a/libX11/src/CrGlCur.c +++ b/libX11/src/CrGlCur.c @@ -1,270 +1,270 @@ -/*
-
-Copyright 1986, 1998 The Open Group
-
-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.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include "Xlibint.h"
-
-#ifdef USE_DYNAMIC_XCURSOR
-
-#ifdef __UNIXOS2__
-#define RTLD_LAZY 1
-#define LIBXCURSOR "Xcursor.dll"
-#endif
-#include <stdio.h>
-#include <string.h>
-#if defined(hpux)
-#include <dl.h>
-#else
-#include <dlfcn.h>
-#endif
-#include "Cr.h"
-
-#ifdef __CYGWIN__
-#define LIBXCURSOR "cygXcursor-1.dll"
-#endif
-
-#if defined(hpux)
-typedef shl_t XModuleType;
-#else
-#ifdef _MSC_VER
-#include <X11/XWindows.h>
-typedef HANDLE XModuleType;
-#define dlsym GetProcAddress
-#else
-typedef void *XModuleType;
-#endif
-#endif
-
-#ifndef LIBXCURSOR
-#define LIBXCURSOR "libXcursor.so.1"
-#endif
-
-static char libraryName[] = LIBXCURSOR;
-
-static XModuleType
-open_library (void)
-{
- char *library = libraryName;
- char *dot;
- XModuleType module;
- for (;;)
- {
-#if defined(hpux)
- module = shl_load(library, BIND_DEFERRED, 0L);
-#else
-#ifdef _MSC_VER
- module = LoadLibrary(library);
-#else
- module = dlopen(library, RTLD_LAZY);
-#endif
-#endif
- if (module)
- return module;
- dot = strrchr (library, '.');
- if (!dot)
- break;
- *dot = '\0';
- }
- return NULL;
-}
-
-static void *
-fetch_symbol (XModuleType module, const char *under_symbol)
-{
- void *result = NULL;
- const char *symbol = under_symbol + 1;
-#if defined(hpux)
- int getsyms_cnt, i;
- struct shl_symbol *symbols;
-
- getsyms_cnt = shl_getsymbols(module, TYPE_PROCEDURE,
- EXPORT_SYMBOLS, malloc, &symbols);
-
- for(i=0; i<getsyms_cnt; i++) {
- if(!strcmp(symbols[i].name, symbol)) {
- result = symbols[i].value;
- break;
- }
- }
-
- if(getsyms_cnt > 0) {
- free(symbols);
- }
-#else
- result = dlsym (module, symbol);
- if (!result)
- result = dlsym (module, under_symbol);
-#endif
- return result;
-}
-
-typedef void (*NoticeCreateBitmapFunc) (Display *dpy,
- Pixmap pid,
- unsigned int width,
- unsigned int height);
-
-typedef void (*NoticePutBitmapFunc) (Display *dpy,
- Drawable draw,
- XImage *image);
-
-typedef Cursor (*TryShapeBitmapCursorFunc) (Display *dpy,
- Pixmap source,
- Pixmap mask,
- XColor *foreground,
- XColor *background,
- unsigned int x,
- unsigned int y);
-
-typedef Cursor (*TryShapeCursorFunc) (Display *dpy,
- Font source_font,
- Font mask_font,
- unsigned int source_char,
- unsigned int mask_char,
- XColor _Xconst *foreground,
- XColor _Xconst *background);
-
-static XModuleType _XcursorModule;
-static Bool _XcursorModuleTried;
-
-#define GetFunc(type,name,ret) {\
- static Bool been_here; \
- static type staticFunc; \
- \
- _XLockMutex (_Xglobal_lock); \
- if (!been_here) \
- { \
- been_here = True; \
- if (!_XcursorModuleTried) \
- { \
- _XcursorModuleTried = True; \
- _XcursorModule = open_library (); \
- } \
- if (_XcursorModule) \
- staticFunc = (type) fetch_symbol (_XcursorModule, "_" name); \
- } \
- ret = staticFunc; \
- _XUnlockMutex (_Xglobal_lock); \
-}
-
-static Cursor
-_XTryShapeCursor (Display *dpy,
- Font source_font,
- Font mask_font,
- unsigned int source_char,
- unsigned int mask_char,
- XColor _Xconst *foreground,
- XColor _Xconst *background)
-{
- TryShapeCursorFunc func;
-
- GetFunc (TryShapeCursorFunc, "XcursorTryShapeCursor", func);
- if (func)
- return (*func) (dpy, source_font, mask_font, source_char, mask_char,
- foreground, background);
- return None;
-}
-
-void
-_XNoticeCreateBitmap (Display *dpy,
- Pixmap pid,
- unsigned int width,
- unsigned int height)
-{
- NoticeCreateBitmapFunc func;
-
- GetFunc (NoticeCreateBitmapFunc, "XcursorNoticeCreateBitmap", func);
- if (func)
- (*func) (dpy, pid, width, height);
-}
-
-void
-_XNoticePutBitmap (Display *dpy,
- Drawable draw,
- XImage *image)
-{
- NoticePutBitmapFunc func;
-
- GetFunc (NoticePutBitmapFunc, "XcursorNoticePutBitmap", func);
- if (func)
- (*func) (dpy, draw, image);
-}
-
-Cursor
-_XTryShapeBitmapCursor (Display *dpy,
- Pixmap source,
- Pixmap mask,
- XColor *foreground,
- XColor *background,
- unsigned int x,
- unsigned int y)
-{
- TryShapeBitmapCursorFunc func;
-
- GetFunc (TryShapeBitmapCursorFunc, "XcursorTryShapeBitmapCursor", func);
- if (func)
- return (*func) (dpy, source, mask, foreground, background, x, y);
- return None;
-}
-#endif
-
-Cursor XCreateGlyphCursor(
- register Display *dpy,
- Font source_font,
- Font mask_font,
- unsigned int source_char,
- unsigned int mask_char,
- XColor _Xconst *foreground,
- XColor _Xconst *background)
-{
- Cursor cid;
- register xCreateGlyphCursorReq *req;
-
-#ifdef USE_DYNAMIC_XCURSOR
- cid = _XTryShapeCursor (dpy, source_font, mask_font,
- source_char, mask_char, foreground, background);
- if (cid)
- return cid;
-#endif
- LockDisplay(dpy);
- GetReq(CreateGlyphCursor, req);
- cid = req->cid = XAllocID(dpy);
- req->source = source_font;
- req->mask = mask_font;
- req->sourceChar = source_char;
- req->maskChar = mask_char;
- req->foreRed = foreground->red;
- req->foreGreen = foreground->green;
- req->foreBlue = foreground->blue;
- req->backRed = background->red;
- req->backGreen = background->green;
- req->backBlue = background->blue;
- UnlockDisplay(dpy);
- SyncHandle();
- return (cid);
-}
-
+/* + +Copyright 1986, 1998 The Open Group + +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. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include "Xlibint.h" + +#ifdef USE_DYNAMIC_XCURSOR + +#ifdef __UNIXOS2__ +#define RTLD_LAZY 1 +#define LIBXCURSOR "Xcursor.dll" +#endif +#include <stdio.h> +#include <string.h> +#if defined(hpux) +#include <dl.h> +#else +#include <dlfcn.h> +#endif +#include "Cr.h" + +#ifdef __CYGWIN__ +#define LIBXCURSOR "cygXcursor-1.dll" +#endif + +#if defined(hpux) +typedef shl_t XModuleType; +#else +#ifdef _MSC_VER +#include <X11/XWindows.h> +typedef HANDLE XModuleType; +#define dlsym GetProcAddress +#else +typedef void *XModuleType; +#endif +#endif + +#ifndef LIBXCURSOR +#define LIBXCURSOR "libXcursor.so.1" +#endif + +static char libraryName[] = LIBXCURSOR; + +static XModuleType +open_library (void) +{ + char *library = libraryName; + char *dot; + XModuleType module; + for (;;) + { +#if defined(hpux) + module = shl_load(library, BIND_DEFERRED, 0L); +#else +#ifdef _MSC_VER + module = LoadLibrary(library); +#else + module = dlopen(library, RTLD_LAZY); +#endif +#endif + if (module) + return module; + dot = strrchr (library, '.'); + if (!dot) + break; + *dot = '\0'; + } + return NULL; +} + +static void * +fetch_symbol (XModuleType module, const char *under_symbol) +{ + void *result = NULL; + const char *symbol = under_symbol + 1; +#if defined(hpux) + int getsyms_cnt, i; + struct shl_symbol *symbols; + + getsyms_cnt = shl_getsymbols(module, TYPE_PROCEDURE, + EXPORT_SYMBOLS, malloc, &symbols); + + for(i=0; i<getsyms_cnt; i++) { + if(!strcmp(symbols[i].name, symbol)) { + result = symbols[i].value; + break; + } + } + + if(getsyms_cnt > 0) { + free(symbols); + } +#else + result = dlsym (module, symbol); + if (!result) + result = dlsym (module, under_symbol); +#endif + return result; +} + +typedef void (*NoticeCreateBitmapFunc) (Display *dpy, + Pixmap pid, + unsigned int width, + unsigned int height); + +typedef void (*NoticePutBitmapFunc) (Display *dpy, + Drawable draw, + XImage *image); + +typedef Cursor (*TryShapeBitmapCursorFunc) (Display *dpy, + Pixmap source, + Pixmap mask, + XColor *foreground, + XColor *background, + unsigned int x, + unsigned int y); + +typedef Cursor (*TryShapeCursorFunc) (Display *dpy, + Font source_font, + Font mask_font, + unsigned int source_char, + unsigned int mask_char, + XColor _Xconst *foreground, + XColor _Xconst *background); + +static XModuleType _XcursorModule; +static Bool _XcursorModuleTried; + +#define GetFunc(type,name,ret) {\ + static Bool been_here; \ + static type staticFunc; \ + \ + _XLockMutex (_Xglobal_lock); \ + if (!been_here) \ + { \ + been_here = True; \ + if (!_XcursorModuleTried) \ + { \ + _XcursorModuleTried = True; \ + _XcursorModule = open_library (); \ + } \ + if (_XcursorModule) \ + staticFunc = (type) fetch_symbol (_XcursorModule, "_" name); \ + } \ + ret = staticFunc; \ + _XUnlockMutex (_Xglobal_lock); \ +} + +static Cursor +_XTryShapeCursor (Display *dpy, + Font source_font, + Font mask_font, + unsigned int source_char, + unsigned int mask_char, + XColor _Xconst *foreground, + XColor _Xconst *background) +{ + TryShapeCursorFunc func; + + GetFunc (TryShapeCursorFunc, "XcursorTryShapeCursor", func); + if (func) + return (*func) (dpy, source_font, mask_font, source_char, mask_char, + foreground, background); + return None; +} + +void +_XNoticeCreateBitmap (Display *dpy, + Pixmap pid, + unsigned int width, + unsigned int height) +{ + NoticeCreateBitmapFunc func; + + GetFunc (NoticeCreateBitmapFunc, "XcursorNoticeCreateBitmap", func); + if (func) + (*func) (dpy, pid, width, height); +} + +void +_XNoticePutBitmap (Display *dpy, + Drawable draw, + XImage *image) +{ + NoticePutBitmapFunc func; + + GetFunc (NoticePutBitmapFunc, "XcursorNoticePutBitmap", func); + if (func) + (*func) (dpy, draw, image); +} + +Cursor +_XTryShapeBitmapCursor (Display *dpy, + Pixmap source, + Pixmap mask, + XColor *foreground, + XColor *background, + unsigned int x, + unsigned int y) +{ + TryShapeBitmapCursorFunc func; + + GetFunc (TryShapeBitmapCursorFunc, "XcursorTryShapeBitmapCursor", func); + if (func) + return (*func) (dpy, source, mask, foreground, background, x, y); + return None; +} +#endif + +Cursor XCreateGlyphCursor( + register Display *dpy, + Font source_font, + Font mask_font, + unsigned int source_char, + unsigned int mask_char, + XColor _Xconst *foreground, + XColor _Xconst *background) +{ + Cursor cid; + register xCreateGlyphCursorReq *req; + +#ifdef USE_DYNAMIC_XCURSOR + cid = _XTryShapeCursor (dpy, source_font, mask_font, + source_char, mask_char, foreground, background); + if (cid) + return cid; +#endif + LockDisplay(dpy); + GetReq(CreateGlyphCursor, req); + cid = req->cid = XAllocID(dpy); + req->source = source_font; + req->mask = mask_font; + req->sourceChar = source_char; + req->maskChar = mask_char; + req->foreRed = foreground->red; + req->foreGreen = foreground->green; + req->foreBlue = foreground->blue; + req->backRed = background->red; + req->backGreen = background->green; + req->backBlue = background->blue; + UnlockDisplay(dpy); + SyncHandle(); + return (cid); +} + diff --git a/libX11/src/FSWrap.c b/libX11/src/FSWrap.c index d97c39504..0b7baffc9 100644 --- a/libX11/src/FSWrap.c +++ b/libX11/src/FSWrap.c @@ -1,262 +1,262 @@ -
-/*
- * Copyright 1991 by the Open Software Foundation
- * Copyright 1993 by the TOSHIBA Corp.
- *
- * 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 name Open Software Foundation
- * not be used in advertising or publicity pertaining to distribution of the
- * software without specific, written prior permission. Open Software
- * Foundation makes no representations about the suitability of this
- * software for any purpose. It is provided "as is" without express or
- * implied warranty.
- *
- * OPEN SOFTWARE FOUNDATION DISCLAIMS ALL WARRANTIES WITH REGARD TO
- * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS, IN NO EVENT SHALL OPEN SOFTWARE FOUNDATIONN 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 TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * M. Collins OSF
- *
- * Katsuhisa Yano TOSHIBA Corp.
- */
-
-/*
-
-Copyright 1991, 1998 The Open Group
-
-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.
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall
-not be used in advertising or otherwise to promote the sale, use or
-other dealings in this Software without prior written authorization
-from The Open Group.
-
-*/
-
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include "Xlibint.h"
-#include "Xlcint.h"
-#include <ctype.h>
-#include <X11/Xos.h>
-#include <unistd.h>
-
-#define XMAXLIST 256
-
-char **
-_XParseBaseFontNameList(
- char *str,
- int *num)
-{
- char *plist[XMAXLIST];
- char **list;
- char *ptr, *psave;
-
- *num = 0;
- if (!str || !*str) {
- return (char **)NULL;
- }
- while (*str && isspace(*str))
- str++;
- if (!*str)
- return (char **)NULL;
-
- if (!(ptr = strdup(str))) {
- return (char **)NULL;
- }
-
- psave = ptr;
- /* somebody who specifies more than XMAXLIST basefontnames will lose */
- while (*num < (sizeof plist / sizeof plist[0])) {
- char *back;
-
- plist[*num] = ptr;
- if ((ptr = strchr(ptr, ','))) {
- back = ptr;
- } else {
- back = plist[*num] + strlen(plist[*num]);
- }
- while (isspace(*(back - 1)))
- back--;
- *back = '\0';
- (*num)++;
- if (!ptr)
- break;
- ptr++;
- while (*ptr && isspace(*ptr))
- ptr++;
- if (!*ptr)
- break;
- }
- if (!(list = (char **) Xmalloc((unsigned)sizeof(char *) * (*num + 1)))) {
- Xfree(psave);
- return (char **)NULL;
- }
- memcpy((char *)list, (char *)plist, sizeof(char *) * (*num));
- *(list + *num) = NULL;
-
- return list;
-}
-
-static char **
-copy_string_list(
- char **string_list,
- int list_count)
-{
- char **string_list_ret, **list_src, **list_dst, *dst;
- int length, count;
-
- if (string_list == NULL || list_count == 0)
- return (char **) NULL;
-
- string_list_ret = (char **) Xmalloc(sizeof(char *) * list_count);
- if (string_list_ret == NULL)
- return (char **) NULL;
-
- list_src = string_list;
- count = list_count;
- for (length = 0; count-- > 0; list_src++)
- length += strlen(*list_src) + 1;
-
- dst = (char *) Xmalloc(length);
- if (dst == NULL) {
- Xfree(string_list_ret);
- return (char **) NULL;
- }
-
- list_src = string_list;
- count = list_count;
- list_dst = string_list_ret;
- for ( ; count-- > 0; list_src++) {
- strcpy(dst, *list_src);
- *list_dst++ = dst;
- dst += strlen(dst) + 1;
- }
-
- return string_list_ret;
-}
-
-XFontSet
-XCreateFontSet (
- Display *dpy,
- _Xconst char *base_font_name_list,
- char ***missing_charset_list,
- int *missing_charset_count,
- char **def_string)
-{
- XOM om;
- XOC oc;
- XOMCharSetList *list;
-
- *missing_charset_list = NULL;
- *missing_charset_count = 0;
-
- om = XOpenOM(dpy, NULL, NULL, NULL);
- if (om == NULL)
- return (XFontSet) NULL;
-
- if ((oc = XCreateOC(om, XNBaseFontName, base_font_name_list, NULL))) {
- list = &oc->core.missing_list;
- oc->core.om_automatic = True;
- } else
- list = &om->core.required_charset;
-
- *missing_charset_list = copy_string_list(list->charset_list,
- list->charset_count);
- *missing_charset_count = list->charset_count;
-
- if (list->charset_list && *missing_charset_list == NULL)
- oc = NULL;
-
- if (oc && def_string) {
- *def_string = oc->core.default_string;
- if (!*def_string)
- *def_string = "";
- }
-
- if (oc == NULL)
- XCloseOM(om);
-
- return (XFontSet) oc;
-}
-
-int
-XFontsOfFontSet(
- XFontSet font_set,
- XFontStruct ***font_struct_list,
- char ***font_name_list)
-{
- *font_name_list = font_set->core.font_info.font_name_list;
- *font_struct_list = font_set->core.font_info.font_struct_list;
- return font_set->core.font_info.num_font;
-}
-
-char *
-XBaseFontNameListOfFontSet(XFontSet font_set)
-{
- return font_set->core.base_name_list;
-}
-
-char *
-XLocaleOfFontSet(XFontSet font_set)
-{
- return font_set->core.om->core.lcd->core->name;
-}
-
-Bool
-XContextDependentDrawing(XFontSet font_set)
-{
- return font_set->core.om->core.context_dependent;
-}
-
-Bool
-XDirectionalDependentDrawing(XFontSet font_set)
-{
- return font_set->core.om->core.directional_dependent;
-}
-
-Bool
-XContextualDrawing(XFontSet font_set)
-{
- return font_set->core.om->core.contextual_drawing;
-}
-
-XFontSetExtents *
-XExtentsOfFontSet(XFontSet font_set)
-{
- if (!font_set)
- return NULL;
- return &font_set->core.font_set_extents;
-}
-
-void
-XFreeFontSet(
- Display *dpy,
- XFontSet font_set)
-{
- XCloseOM(font_set->core.om);
-}
+ +/* + * Copyright 1991 by the Open Software Foundation + * Copyright 1993 by the TOSHIBA Corp. + * + * 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 name Open Software Foundation + * not be used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. Open Software + * Foundation makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * OPEN SOFTWARE FOUNDATION DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL OPEN SOFTWARE FOUNDATIONN 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 TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * M. Collins OSF + * + * Katsuhisa Yano TOSHIBA Corp. + */ + +/* + +Copyright 1991, 1998 The Open Group + +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. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include "Xlibint.h" +#include "Xlcint.h" +#include <ctype.h> +#include <X11/Xos.h> +#include <unistd.h> + +#define XMAXLIST 256 + +char ** +_XParseBaseFontNameList( + char *str, + int *num) +{ + char *plist[XMAXLIST]; + char **list; + char *ptr, *psave; + + *num = 0; + if (!str || !*str) { + return (char **)NULL; + } + while (*str && isspace(*str)) + str++; + if (!*str) + return (char **)NULL; + + if (!(ptr = strdup(str))) { + return (char **)NULL; + } + + psave = ptr; + /* somebody who specifies more than XMAXLIST basefontnames will lose */ + while (*num < (sizeof plist / sizeof plist[0])) { + char *back; + + plist[*num] = ptr; + if ((ptr = strchr(ptr, ','))) { + back = ptr; + } else { + back = plist[*num] + strlen(plist[*num]); + } + while (isspace(*(back - 1))) + back--; + *back = '\0'; + (*num)++; + if (!ptr) + break; + ptr++; + while (*ptr && isspace(*ptr)) + ptr++; + if (!*ptr) + break; + } + if (!(list = (char **) Xmalloc((unsigned)sizeof(char *) * (*num + 1)))) { + Xfree(psave); + return (char **)NULL; + } + memcpy((char *)list, (char *)plist, sizeof(char *) * (*num)); + *(list + *num) = NULL; + + return list; +} + +static char ** +copy_string_list( + char **string_list, + int list_count) +{ + char **string_list_ret, **list_src, **list_dst, *dst; + int length, count; + + if (string_list == NULL || list_count == 0) + return (char **) NULL; + + string_list_ret = (char **) Xmalloc(sizeof(char *) * list_count); + if (string_list_ret == NULL) + return (char **) NULL; + + list_src = string_list; + count = list_count; + for (length = 0; count-- > 0; list_src++) + length += strlen(*list_src) + 1; + + dst = (char *) Xmalloc(length); + if (dst == NULL) { + Xfree(string_list_ret); + return (char **) NULL; + } + + list_src = string_list; + count = list_count; + list_dst = string_list_ret; + for ( ; count-- > 0; list_src++) { + strcpy(dst, *list_src); + *list_dst++ = dst; + dst += strlen(dst) + 1; + } + + return string_list_ret; +} + +XFontSet +XCreateFontSet ( + Display *dpy, + _Xconst char *base_font_name_list, + char ***missing_charset_list, + int *missing_charset_count, + char **def_string) +{ + XOM om; + XOC oc; + XOMCharSetList *list; + + *missing_charset_list = NULL; + *missing_charset_count = 0; + + om = XOpenOM(dpy, NULL, NULL, NULL); + if (om == NULL) + return (XFontSet) NULL; + + if ((oc = XCreateOC(om, XNBaseFontName, base_font_name_list, NULL))) { + list = &oc->core.missing_list; + oc->core.om_automatic = True; + } else + list = &om->core.required_charset; + + *missing_charset_list = copy_string_list(list->charset_list, + list->charset_count); + *missing_charset_count = list->charset_count; + + if (list->charset_list && *missing_charset_list == NULL) + oc = NULL; + + if (oc && def_string) { + *def_string = oc->core.default_string; + if (!*def_string) + *def_string = ""; + } + + if (oc == NULL) + XCloseOM(om); + + return (XFontSet) oc; +} + +int +XFontsOfFontSet( + XFontSet font_set, + XFontStruct ***font_struct_list, + char ***font_name_list) +{ + *font_name_list = font_set->core.font_info.font_name_list; + *font_struct_list = font_set->core.font_info.font_struct_list; + return font_set->core.font_info.num_font; +} + +char * +XBaseFontNameListOfFontSet(XFontSet font_set) +{ + return font_set->core.base_name_list; +} + +char * +XLocaleOfFontSet(XFontSet font_set) +{ + return font_set->core.om->core.lcd->core->name; +} + +Bool +XContextDependentDrawing(XFontSet font_set) +{ + return font_set->core.om->core.context_dependent; +} + +Bool +XDirectionalDependentDrawing(XFontSet font_set) +{ + return font_set->core.om->core.directional_dependent; +} + +Bool +XContextualDrawing(XFontSet font_set) +{ + return font_set->core.om->core.contextual_drawing; +} + +XFontSetExtents * +XExtentsOfFontSet(XFontSet font_set) +{ + if (!font_set) + return NULL; + return &font_set->core.font_set_extents; +} + +void +XFreeFontSet( + Display *dpy, + XFontSet font_set) +{ + XCloseOM(font_set->core.om); +} diff --git a/libX11/src/InitExt.c b/libX11/src/InitExt.c index f14da412c..53c2dbe90 100644 --- a/libX11/src/InitExt.c +++ b/libX11/src/InitExt.c @@ -1,410 +1,410 @@ -/*
-
-Copyright 1987, 1998 The Open Group
-
-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.
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall
-not be used in advertising or otherwise to promote the sale, use or
-other dealings in this Software without prior written authorization
-from The Open Group.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <X11/Xlibint.h>
-#include <X11/Xos.h>
-#include <stdio.h>
-#include <unistd.h>
-
-/*
- * This routine is used to link a extension in so it will be called
- * at appropriate times.
- */
-
-XExtCodes *XInitExtension (
- Display *dpy,
- _Xconst char *name)
-{
- XExtCodes codes; /* temp. place for extension information. */
- register _XExtension *ext;/* need a place to build it all */
- if (!XQueryExtension(dpy, name,
- &codes.major_opcode, &codes.first_event,
- &codes.first_error)) return (NULL);
-
- LockDisplay (dpy);
- if (! (ext = (_XExtension *) Xcalloc (1, sizeof (_XExtension))) ||
- ! (ext->name = strdup(name))) {
- if (ext) Xfree((char *) ext);
- UnlockDisplay(dpy);
- return (XExtCodes *) NULL;
- }
- codes.extension = dpy->ext_number++;
- ext->codes = codes;
-
- /* chain it onto the display list */
- ext->next = dpy->ext_procs;
- dpy->ext_procs = ext;
- UnlockDisplay (dpy);
-
- return (&ext->codes); /* tell him which extension */
-}
-
-XExtCodes *XAddExtension (Display *dpy)
-{
- register _XExtension *ext;
-
- LockDisplay (dpy);
- if (! (ext = (_XExtension *) Xcalloc (1, sizeof (_XExtension)))) {
- UnlockDisplay(dpy);
- return (XExtCodes *) NULL;
- }
- ext->codes.extension = dpy->ext_number++;
-
- /* chain it onto the display list */
- ext->next = dpy->ext_procs;
- dpy->ext_procs = ext;
- UnlockDisplay (dpy);
-
- return (&ext->codes); /* tell him which extension */
-}
-
-static _XExtension *XLookupExtension (
- register Display *dpy, /* display */
- register int extension) /* extension number */
-{
- register _XExtension *ext;
- for (ext = dpy->ext_procs; ext; ext = ext->next)
- if (ext->codes.extension == extension) return (ext);
- return (NULL);
-}
-
-XExtData **XEHeadOfExtensionList(XEDataObject object)
-{
- return *(XExtData ***)&object;
-}
-
-int
-XAddToExtensionList(
- XExtData **structure,
- XExtData *ext_data)
-{
- ext_data->next = *structure;
- *structure = ext_data;
- return 1;
-}
-
-XExtData *XFindOnExtensionList(
- XExtData **structure,
- int number)
-{
- XExtData *ext;
-
- ext = *structure;
- while (ext && (ext->number != number))
- ext = ext->next;
- return ext;
-}
-
-/*
- * Routines to hang procs on the extension structure.
- */
-CreateGCType XESetCreateGC(
- Display *dpy, /* display */
- int extension, /* extension number */
- CreateGCType proc) /* routine to call when GC created */
-{
- register _XExtension *e; /* for lookup of extension */
- register CreateGCType oldproc;
- if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);
- LockDisplay(dpy);
- oldproc = e->create_GC;
- e->create_GC = proc;
- UnlockDisplay(dpy);
- return (CreateGCType)oldproc;
-}
-
-CopyGCType XESetCopyGC(
- Display *dpy, /* display */
- int extension, /* extension number */
- CopyGCType proc) /* routine to call when GC copied */
-{
- register _XExtension *e; /* for lookup of extension */
- register CopyGCType oldproc;
- if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);
- LockDisplay(dpy);
- oldproc = e->copy_GC;
- e->copy_GC = proc;
- UnlockDisplay(dpy);
- return (CopyGCType)oldproc;
-}
-
-FlushGCType XESetFlushGC(
- Display *dpy, /* display */
- int extension, /* extension number */
- FlushGCType proc) /* routine to call when GC copied */
-{
- register _XExtension *e; /* for lookup of extension */
- register FlushGCType oldproc;
- if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);
- LockDisplay(dpy);
- oldproc = e->flush_GC;
- e->flush_GC = proc;
- UnlockDisplay(dpy);
- return (FlushGCType)oldproc;
-}
-
-FreeGCType XESetFreeGC(
- Display *dpy, /* display */
- int extension, /* extension number */
- FreeGCType proc) /* routine to call when GC freed */
-{
- register _XExtension *e; /* for lookup of extension */
- register FreeGCType oldproc;
- if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);
- LockDisplay(dpy);
- oldproc = e->free_GC;
- e->free_GC = proc;
- UnlockDisplay(dpy);
- return (FreeGCType)oldproc;
-}
-
-CreateFontType XESetCreateFont(
- Display *dpy, /* display */
- int extension, /* extension number */
- CreateFontType proc) /* routine to call when font created */
-{
- register _XExtension *e; /* for lookup of extension */
- register CreateFontType oldproc;
- if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);
- LockDisplay(dpy);
- oldproc = e->create_Font;
- e->create_Font = proc;
- UnlockDisplay(dpy);
- return (CreateFontType)oldproc;
-}
-
-FreeFontType XESetFreeFont(
- Display *dpy, /* display */
- int extension, /* extension number */
- FreeFontType proc) /* routine to call when font freed */
-{
- register _XExtension *e; /* for lookup of extension */
- register FreeFontType oldproc;
- if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);
- LockDisplay(dpy);
- oldproc = e->free_Font;
- e->free_Font = proc;
- UnlockDisplay(dpy);
- return (FreeFontType)oldproc;
-}
-
-CloseDisplayType XESetCloseDisplay(
- Display *dpy, /* display */
- int extension, /* extension number */
- CloseDisplayType proc) /* routine to call when display closed */
-{
- register _XExtension *e; /* for lookup of extension */
- register CloseDisplayType oldproc;
- if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);
- LockDisplay(dpy);
- oldproc = e->close_display;
- e->close_display = proc;
- UnlockDisplay(dpy);
- return (CloseDisplayType)oldproc;
-}
-
-typedef Bool (*WireToEventType) (
- Display* /* display */,
- XEvent* /* re */,
- xEvent* /* event */
-);
-
-WireToEventType XESetWireToEvent(
- Display *dpy, /* display */
- int event_number, /* event routine to replace */
- WireToEventType proc) /* routine to call when converting event */
-{
- register WireToEventType oldproc;
- if (proc == NULL) proc = (WireToEventType)_XUnknownWireEvent;
- LockDisplay (dpy);
- oldproc = dpy->event_vec[event_number];
- dpy->event_vec[event_number] = proc;
- UnlockDisplay (dpy);
- return (WireToEventType)oldproc;
-}
-
-typedef Bool (*WireToEventCookieType) (
- Display* /* display */,
- XGenericEventCookie* /* re */,
- xEvent* /* event */
-);
-
-WireToEventCookieType XESetWireToEventCookie(
- Display *dpy, /* display */
- int extension, /* extension major opcode */
- WireToEventCookieType proc /* routine to call for generic events */
- )
-{
- WireToEventCookieType oldproc;
- if (proc == NULL) proc = (WireToEventCookieType)_XUnknownWireEventCookie;
- LockDisplay (dpy);
- oldproc = dpy->generic_event_vec[extension & 0x7F];
- dpy->generic_event_vec[extension & 0x7F] = proc;
- UnlockDisplay (dpy);
- return (WireToEventCookieType)oldproc;
-}
-
-typedef Bool (*CopyEventCookieType) (
- Display* /* display */,
- XGenericEventCookie* /* in */,
- XGenericEventCookie* /* out */
-);
-
-CopyEventCookieType XESetCopyEventCookie(
- Display *dpy, /* display */
- int extension, /* extension major opcode */
- CopyEventCookieType proc /* routine to copy generic events */
- )
-{
- CopyEventCookieType oldproc;
- if (proc == NULL) proc = (CopyEventCookieType)_XUnknownCopyEventCookie;
- LockDisplay (dpy);
- oldproc = dpy->generic_event_copy_vec[extension & 0x7F];
- dpy->generic_event_copy_vec[extension & 0x7F] = proc;
- UnlockDisplay (dpy);
- return (CopyEventCookieType)oldproc;
-}
-
-
-typedef Status (*EventToWireType) (
- Display* /* display */,
- XEvent* /* re */,
- xEvent* /* event */
-);
-
-EventToWireType XESetEventToWire(
- Display *dpy, /* display */
- int event_number, /* event routine to replace */
- EventToWireType proc) /* routine to call when converting event */
-{
- register EventToWireType oldproc;
- if (proc == NULL) proc = (EventToWireType) _XUnknownNativeEvent;
- LockDisplay (dpy);
- oldproc = dpy->wire_vec[event_number];
- dpy->wire_vec[event_number] = proc;
- UnlockDisplay(dpy);
- return (EventToWireType)oldproc;
-}
-
-typedef Bool (*WireToErrorType) (
- Display* /* display */,
- XErrorEvent* /* he */,
- xError* /* we */
-);
-
-WireToErrorType XESetWireToError(
- Display *dpy, /* display */
- int error_number, /* error routine to replace */
- WireToErrorType proc) /* routine to call when converting error */
-{
- register WireToErrorType oldproc = NULL;
- if (proc == NULL) proc = (WireToErrorType)_XDefaultWireError;
- LockDisplay (dpy);
- if (!dpy->error_vec) {
- int i;
- dpy->error_vec = Xmalloc(256 * sizeof(oldproc));
- for (i = 1; i < 256; i++)
- dpy->error_vec[i] = _XDefaultWireError;
- }
- if (dpy->error_vec) {
- oldproc = dpy->error_vec[error_number];
- dpy->error_vec[error_number] = proc;
- }
- UnlockDisplay (dpy);
- return (WireToErrorType)oldproc;
-}
-
-ErrorType XESetError(
- Display *dpy, /* display */
- int extension, /* extension number */
- ErrorType proc) /* routine to call when X error happens */
-{
- register _XExtension *e; /* for lookup of extension */
- register ErrorType oldproc;
- if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);
- LockDisplay(dpy);
- oldproc = e->error;
- e->error = proc;
- UnlockDisplay(dpy);
- return (ErrorType)oldproc;
-}
-
-ErrorStringType XESetErrorString(
- Display *dpy, /* display */
- int extension, /* extension number */
- ErrorStringType proc) /* routine to call when I/O error happens */
-{
- register _XExtension *e; /* for lookup of extension */
- register ErrorStringType oldproc;
- if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);
- LockDisplay(dpy);
- oldproc = e->error_string;
- e->error_string = proc;
- UnlockDisplay(dpy);
- return (ErrorStringType)oldproc;
-}
-
-PrintErrorType XESetPrintErrorValues(
- Display *dpy, /* display */
- int extension, /* extension number */
- PrintErrorType proc) /* routine to call to print */
-{
- register _XExtension *e; /* for lookup of extension */
- register PrintErrorType oldproc;
- if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);
- LockDisplay(dpy);
- oldproc = e->error_values;
- e->error_values = proc;
- UnlockDisplay(dpy);
- return (PrintErrorType)oldproc;
-}
-
-BeforeFlushType XESetBeforeFlush(
- Display *dpy, /* display */
- int extension, /* extension number */
- BeforeFlushType proc) /* routine to call on flush */
-{
- register _XExtension *e; /* for lookup of extension */
- register BeforeFlushType oldproc;
- register _XExtension *ext;
- if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);
- LockDisplay(dpy);
- oldproc = e->before_flush;
- e->before_flush = proc;
- for (ext = dpy->flushes; ext && ext != e; ext = ext->next)
- ;
- if (!ext) {
- e->next_flush = dpy->flushes;
- dpy->flushes = e;
- }
- UnlockDisplay(dpy);
- return (BeforeFlushType)oldproc;
-}
+/* + +Copyright 1987, 1998 The Open Group + +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. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <X11/Xlibint.h> +#include <X11/Xos.h> +#include <stdio.h> +#include <unistd.h> + +/* + * This routine is used to link a extension in so it will be called + * at appropriate times. + */ + +XExtCodes *XInitExtension ( + Display *dpy, + _Xconst char *name) +{ + XExtCodes codes; /* temp. place for extension information. */ + register _XExtension *ext;/* need a place to build it all */ + if (!XQueryExtension(dpy, name, + &codes.major_opcode, &codes.first_event, + &codes.first_error)) return (NULL); + + LockDisplay (dpy); + if (! (ext = (_XExtension *) Xcalloc (1, sizeof (_XExtension))) || + ! (ext->name = strdup(name))) { + if (ext) Xfree((char *) ext); + UnlockDisplay(dpy); + return (XExtCodes *) NULL; + } + codes.extension = dpy->ext_number++; + ext->codes = codes; + + /* chain it onto the display list */ + ext->next = dpy->ext_procs; + dpy->ext_procs = ext; + UnlockDisplay (dpy); + + return (&ext->codes); /* tell him which extension */ +} + +XExtCodes *XAddExtension (Display *dpy) +{ + register _XExtension *ext; + + LockDisplay (dpy); + if (! (ext = (_XExtension *) Xcalloc (1, sizeof (_XExtension)))) { + UnlockDisplay(dpy); + return (XExtCodes *) NULL; + } + ext->codes.extension = dpy->ext_number++; + + /* chain it onto the display list */ + ext->next = dpy->ext_procs; + dpy->ext_procs = ext; + UnlockDisplay (dpy); + + return (&ext->codes); /* tell him which extension */ +} + +static _XExtension *XLookupExtension ( + register Display *dpy, /* display */ + register int extension) /* extension number */ +{ + register _XExtension *ext; + for (ext = dpy->ext_procs; ext; ext = ext->next) + if (ext->codes.extension == extension) return (ext); + return (NULL); +} + +XExtData **XEHeadOfExtensionList(XEDataObject object) +{ + return *(XExtData ***)&object; +} + +int +XAddToExtensionList( + XExtData **structure, + XExtData *ext_data) +{ + ext_data->next = *structure; + *structure = ext_data; + return 1; +} + +XExtData *XFindOnExtensionList( + XExtData **structure, + int number) +{ + XExtData *ext; + + ext = *structure; + while (ext && (ext->number != number)) + ext = ext->next; + return ext; +} + +/* + * Routines to hang procs on the extension structure. + */ +CreateGCType XESetCreateGC( + Display *dpy, /* display */ + int extension, /* extension number */ + CreateGCType proc) /* routine to call when GC created */ +{ + register _XExtension *e; /* for lookup of extension */ + register CreateGCType oldproc; + if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL); + LockDisplay(dpy); + oldproc = e->create_GC; + e->create_GC = proc; + UnlockDisplay(dpy); + return (CreateGCType)oldproc; +} + +CopyGCType XESetCopyGC( + Display *dpy, /* display */ + int extension, /* extension number */ + CopyGCType proc) /* routine to call when GC copied */ +{ + register _XExtension *e; /* for lookup of extension */ + register CopyGCType oldproc; + if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL); + LockDisplay(dpy); + oldproc = e->copy_GC; + e->copy_GC = proc; + UnlockDisplay(dpy); + return (CopyGCType)oldproc; +} + +FlushGCType XESetFlushGC( + Display *dpy, /* display */ + int extension, /* extension number */ + FlushGCType proc) /* routine to call when GC copied */ +{ + register _XExtension *e; /* for lookup of extension */ + register FlushGCType oldproc; + if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL); + LockDisplay(dpy); + oldproc = e->flush_GC; + e->flush_GC = proc; + UnlockDisplay(dpy); + return (FlushGCType)oldproc; +} + +FreeGCType XESetFreeGC( + Display *dpy, /* display */ + int extension, /* extension number */ + FreeGCType proc) /* routine to call when GC freed */ +{ + register _XExtension *e; /* for lookup of extension */ + register FreeGCType oldproc; + if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL); + LockDisplay(dpy); + oldproc = e->free_GC; + e->free_GC = proc; + UnlockDisplay(dpy); + return (FreeGCType)oldproc; +} + +CreateFontType XESetCreateFont( + Display *dpy, /* display */ + int extension, /* extension number */ + CreateFontType proc) /* routine to call when font created */ +{ + register _XExtension *e; /* for lookup of extension */ + register CreateFontType oldproc; + if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL); + LockDisplay(dpy); + oldproc = e->create_Font; + e->create_Font = proc; + UnlockDisplay(dpy); + return (CreateFontType)oldproc; +} + +FreeFontType XESetFreeFont( + Display *dpy, /* display */ + int extension, /* extension number */ + FreeFontType proc) /* routine to call when font freed */ +{ + register _XExtension *e; /* for lookup of extension */ + register FreeFontType oldproc; + if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL); + LockDisplay(dpy); + oldproc = e->free_Font; + e->free_Font = proc; + UnlockDisplay(dpy); + return (FreeFontType)oldproc; +} + +CloseDisplayType XESetCloseDisplay( + Display *dpy, /* display */ + int extension, /* extension number */ + CloseDisplayType proc) /* routine to call when display closed */ +{ + register _XExtension *e; /* for lookup of extension */ + register CloseDisplayType oldproc; + if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL); + LockDisplay(dpy); + oldproc = e->close_display; + e->close_display = proc; + UnlockDisplay(dpy); + return (CloseDisplayType)oldproc; +} + +typedef Bool (*WireToEventType) ( + Display* /* display */, + XEvent* /* re */, + xEvent* /* event */ +); + +WireToEventType XESetWireToEvent( + Display *dpy, /* display */ + int event_number, /* event routine to replace */ + WireToEventType proc) /* routine to call when converting event */ +{ + register WireToEventType oldproc; + if (proc == NULL) proc = (WireToEventType)_XUnknownWireEvent; + LockDisplay (dpy); + oldproc = dpy->event_vec[event_number]; + dpy->event_vec[event_number] = proc; + UnlockDisplay (dpy); + return (WireToEventType)oldproc; +} + +typedef Bool (*WireToEventCookieType) ( + Display* /* display */, + XGenericEventCookie* /* re */, + xEvent* /* event */ +); + +WireToEventCookieType XESetWireToEventCookie( + Display *dpy, /* display */ + int extension, /* extension major opcode */ + WireToEventCookieType proc /* routine to call for generic events */ + ) +{ + WireToEventCookieType oldproc; + if (proc == NULL) proc = (WireToEventCookieType)_XUnknownWireEventCookie; + LockDisplay (dpy); + oldproc = dpy->generic_event_vec[extension & 0x7F]; + dpy->generic_event_vec[extension & 0x7F] = proc; + UnlockDisplay (dpy); + return (WireToEventCookieType)oldproc; +} + +typedef Bool (*CopyEventCookieType) ( + Display* /* display */, + XGenericEventCookie* /* in */, + XGenericEventCookie* /* out */ +); + +CopyEventCookieType XESetCopyEventCookie( + Display *dpy, /* display */ + int extension, /* extension major opcode */ + CopyEventCookieType proc /* routine to copy generic events */ + ) +{ + CopyEventCookieType oldproc; + if (proc == NULL) proc = (CopyEventCookieType)_XUnknownCopyEventCookie; + LockDisplay (dpy); + oldproc = dpy->generic_event_copy_vec[extension & 0x7F]; + dpy->generic_event_copy_vec[extension & 0x7F] = proc; + UnlockDisplay (dpy); + return (CopyEventCookieType)oldproc; +} + + +typedef Status (*EventToWireType) ( + Display* /* display */, + XEvent* /* re */, + xEvent* /* event */ +); + +EventToWireType XESetEventToWire( + Display *dpy, /* display */ + int event_number, /* event routine to replace */ + EventToWireType proc) /* routine to call when converting event */ +{ + register EventToWireType oldproc; + if (proc == NULL) proc = (EventToWireType) _XUnknownNativeEvent; + LockDisplay (dpy); + oldproc = dpy->wire_vec[event_number]; + dpy->wire_vec[event_number] = proc; + UnlockDisplay(dpy); + return (EventToWireType)oldproc; +} + +typedef Bool (*WireToErrorType) ( + Display* /* display */, + XErrorEvent* /* he */, + xError* /* we */ +); + +WireToErrorType XESetWireToError( + Display *dpy, /* display */ + int error_number, /* error routine to replace */ + WireToErrorType proc) /* routine to call when converting error */ +{ + register WireToErrorType oldproc = NULL; + if (proc == NULL) proc = (WireToErrorType)_XDefaultWireError; + LockDisplay (dpy); + if (!dpy->error_vec) { + int i; + dpy->error_vec = Xmalloc(256 * sizeof(oldproc)); + for (i = 1; i < 256; i++) + dpy->error_vec[i] = _XDefaultWireError; + } + if (dpy->error_vec) { + oldproc = dpy->error_vec[error_number]; + dpy->error_vec[error_number] = proc; + } + UnlockDisplay (dpy); + return (WireToErrorType)oldproc; +} + +ErrorType XESetError( + Display *dpy, /* display */ + int extension, /* extension number */ + ErrorType proc) /* routine to call when X error happens */ +{ + register _XExtension *e; /* for lookup of extension */ + register ErrorType oldproc; + if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL); + LockDisplay(dpy); + oldproc = e->error; + e->error = proc; + UnlockDisplay(dpy); + return (ErrorType)oldproc; +} + +ErrorStringType XESetErrorString( + Display *dpy, /* display */ + int extension, /* extension number */ + ErrorStringType proc) /* routine to call when I/O error happens */ +{ + register _XExtension *e; /* for lookup of extension */ + register ErrorStringType oldproc; + if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL); + LockDisplay(dpy); + oldproc = e->error_string; + e->error_string = proc; + UnlockDisplay(dpy); + return (ErrorStringType)oldproc; +} + +PrintErrorType XESetPrintErrorValues( + Display *dpy, /* display */ + int extension, /* extension number */ + PrintErrorType proc) /* routine to call to print */ +{ + register _XExtension *e; /* for lookup of extension */ + register PrintErrorType oldproc; + if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL); + LockDisplay(dpy); + oldproc = e->error_values; + e->error_values = proc; + UnlockDisplay(dpy); + return (PrintErrorType)oldproc; +} + +BeforeFlushType XESetBeforeFlush( + Display *dpy, /* display */ + int extension, /* extension number */ + BeforeFlushType proc) /* routine to call on flush */ +{ + register _XExtension *e; /* for lookup of extension */ + register BeforeFlushType oldproc; + register _XExtension *ext; + if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL); + LockDisplay(dpy); + oldproc = e->before_flush; + e->before_flush = proc; + for (ext = dpy->flushes; ext && ext != e; ext = ext->next) + ; + if (!ext) { + e->next_flush = dpy->flushes; + dpy->flushes = e; + } + UnlockDisplay(dpy); + return (BeforeFlushType)oldproc; +} diff --git a/libX11/src/KeyBind.c b/libX11/src/KeyBind.c index 82d85fbe7..221cedd8c 100644 --- a/libX11/src/KeyBind.c +++ b/libX11/src/KeyBind.c @@ -1,1078 +1,1078 @@ -/*
-
-Copyright 1985, 1987, 1998 The Open Group
-
-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.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-*/
-
-/* Beware, here be monsters (still under construction... - JG */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <X11/Xlibint.h>
-#include <X11/Xutil.h>
-#define XK_MISCELLANY
-#define XK_LATIN1
-#define XK_LATIN2
-#define XK_LATIN3
-#define XK_LATIN4
-#define XK_LATIN8
-#define XK_LATIN9
-#define XK_CYRILLIC
-#define XK_GREEK
-#define XK_ARMENIAN
-#define XK_CAUCASUS
-#define XK_VIETNAMESE
-#define XK_XKB_KEYS
-#define XK_SINHALA
-#include <X11/keysymdef.h>
-#include <stdio.h>
-
-#ifdef USE_OWN_COMPOSE
-#include "imComp.h"
-
-#endif
-
-#include "Xresource.h"
-#include "Key.h"
-
-#ifdef XKB
-#include "XKBlib.h"
-#include "XKBlibint.h"
-#define XKeycodeToKeysym _XKeycodeToKeysym
-#define XKeysymToKeycode _XKeysymToKeycode
-#define XLookupKeysym _XLookupKeysym
-#define XRefreshKeyboardMapping _XRefreshKeyboardMapping
-#define XLookupString _XLookupString
-/* XKBBind.c */
-#else
-#define XkbKeysymToModifiers _XKeysymToModifiers
-#endif
-
-#define AllMods (ShiftMask|LockMask|ControlMask| \
- Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)
-
-static void
-ComputeMaskFromKeytrans(
- Display *dpy,
- register struct _XKeytrans *p);
-
-struct _XKeytrans {
- struct _XKeytrans *next;/* next on list */
- char *string; /* string to return when the time comes */
- int len; /* length of string (since NULL is legit)*/
- KeySym key; /* keysym rebound */
- unsigned int state; /* modifier state */
- KeySym *modifiers; /* modifier keysyms you want */
- int mlen; /* length of modifier list */
-};
-
-static KeySym
-KeyCodetoKeySym(register Display *dpy, KeyCode keycode, int col)
-{
- register int per = dpy->keysyms_per_keycode;
- register KeySym *syms;
- KeySym lsym, usym;
-
- if ((col < 0) || ((col >= per) && (col > 3)) ||
- ((int)keycode < dpy->min_keycode) || ((int)keycode > dpy->max_keycode))
- return NoSymbol;
-
- syms = &dpy->keysyms[(keycode - dpy->min_keycode) * per];
- if (col < 4) {
- if (col > 1) {
- while ((per > 2) && (syms[per - 1] == NoSymbol))
- per--;
- if (per < 3)
- col -= 2;
- }
- if ((per <= (col|1)) || (syms[col|1] == NoSymbol)) {
- XConvertCase(syms[col&~1], &lsym, &usym);
- if (!(col & 1))
- return lsym;
- else if (usym == lsym)
- return NoSymbol;
- else
- return usym;
- }
- }
- return syms[col];
-}
-
-KeySym
-XKeycodeToKeysym(Display *dpy,
-#if NeedWidePrototypes
- unsigned int kc,
-#else
- KeyCode kc,
-#endif
- int col)
-{
- if ((! dpy->keysyms) && (! _XKeyInitialize(dpy)))
- return NoSymbol;
- return KeyCodetoKeySym(dpy, kc, col);
-}
-
-KeyCode
-XKeysymToKeycode(
- Display *dpy,
- KeySym ks)
-{
- register int i, j;
-
- if ((! dpy->keysyms) && (! _XKeyInitialize(dpy)))
- return (KeyCode) 0;
- for (j = 0; j < dpy->keysyms_per_keycode; j++) {
- for (i = dpy->min_keycode; i <= dpy->max_keycode; i++) {
- if (KeyCodetoKeySym(dpy, (KeyCode) i, j) == ks)
- return i;
- }
- }
- return 0;
-}
-
-KeySym
-XLookupKeysym(
- register XKeyEvent *event,
- int col)
-{
- if ((! event->display->keysyms) && (! _XKeyInitialize(event->display)))
- return NoSymbol;
- return KeyCodetoKeySym(event->display, event->keycode, col);
-}
-
-static void
-ResetModMap(
- Display *dpy)
-{
- register XModifierKeymap *map;
- register int i, j, n;
- KeySym sym;
- register struct _XKeytrans *p;
-
- map = dpy->modifiermap;
- /* If any Lock key contains Caps_Lock, then interpret as Caps_Lock,
- * else if any contains Shift_Lock, then interpret as Shift_Lock,
- * else ignore Lock altogether.
- */
- dpy->lock_meaning = NoSymbol;
- /* Lock modifiers are in the second row of the matrix */
- n = 2 * map->max_keypermod;
- for (i = map->max_keypermod; i < n; i++) {
- for (j = 0; j < dpy->keysyms_per_keycode; j++) {
- sym = KeyCodetoKeySym(dpy, map->modifiermap[i], j);
- if (sym == XK_Caps_Lock) {
- dpy->lock_meaning = XK_Caps_Lock;
- break;
- } else if (sym == XK_Shift_Lock) {
- dpy->lock_meaning = XK_Shift_Lock;
- }
- else if (sym == XK_ISO_Lock) {
- dpy->lock_meaning = XK_Caps_Lock;
- break;
- }
- }
- }
- /* Now find any Mod<n> modifier acting as the Group or Numlock modifier */
- dpy->mode_switch = 0;
- dpy->num_lock = 0;
- n *= 4;
- for (i = 3*map->max_keypermod; i < n; i++) {
- for (j = 0; j < dpy->keysyms_per_keycode; j++) {
- sym = KeyCodetoKeySym(dpy, map->modifiermap[i], j);
- if (sym == XK_Mode_switch)
- dpy->mode_switch |= 1 << (i / map->max_keypermod);
- if (sym == XK_Num_Lock)
- dpy->num_lock |= 1 << (i / map->max_keypermod);
- }
- }
- for (p = dpy->key_bindings; p; p = p->next)
- ComputeMaskFromKeytrans(dpy, p);
-}
-
-static int
-InitModMap(
- Display *dpy)
-{
- register XModifierKeymap *map;
-
- if (! (map = XGetModifierMapping(dpy)))
- return 0;
- LockDisplay(dpy);
- if (dpy->modifiermap)
- XFreeModifiermap(dpy->modifiermap);
- dpy->modifiermap = map;
- dpy->free_funcs->modifiermap = XFreeModifiermap;
- if (dpy->keysyms)
- ResetModMap(dpy);
- UnlockDisplay(dpy);
- return 1;
-}
-
-int
-XRefreshKeyboardMapping(register XMappingEvent *event)
-{
-
- if(event->request == MappingKeyboard) {
- /* XXX should really only refresh what is necessary
- * for now, make initialize test fail
- */
- LockDisplay(event->display);
- if (event->display->keysyms) {
- Xfree ((char *)event->display->keysyms);
- event->display->keysyms = NULL;
- }
- UnlockDisplay(event->display);
- }
- if(event->request == MappingModifier) {
- LockDisplay(event->display);
- if (event->display->modifiermap) {
- XFreeModifiermap(event->display->modifiermap);
- event->display->modifiermap = NULL;
- }
- UnlockDisplay(event->display);
- /* go ahead and get it now, since initialize test may not fail */
- if (event->display->keysyms)
- (void) InitModMap(event->display);
- }
- return 1;
-}
-
-int
-_XKeyInitialize(
- Display *dpy)
-{
- int per, n;
- KeySym *keysyms;
-
- /*
- * lets go get the keysyms from the server.
- */
- if (!dpy->keysyms) {
- n = dpy->max_keycode - dpy->min_keycode + 1;
- keysyms = XGetKeyboardMapping (dpy, (KeyCode) dpy->min_keycode,
- n, &per);
- /* keysyms may be NULL */
- if (! keysyms) return 0;
-
- LockDisplay(dpy);
- if (dpy->keysyms)
- Xfree ((char *)dpy->keysyms);
- dpy->keysyms = keysyms;
- dpy->keysyms_per_keycode = per;
- if (dpy->modifiermap)
- ResetModMap(dpy);
- UnlockDisplay(dpy);
- }
- if (!dpy->modifiermap)
- return InitModMap(dpy);
- return 1;
-}
-
-static void
-UCSConvertCase( register unsigned code,
- KeySym *lower,
- KeySym *upper )
-{
- /* Case conversion for UCS, as in Unicode Data version 4.0.0 */
- /* NB: Only converts simple one-to-one mappings. */
-
- /* Tables are used where they take less space than */
- /* the code to work out the mappings. Zero values mean */
- /* undefined code points. */
-
- static unsigned short const IPAExt_upper_mapping[] = { /* part only */
- 0x0181, 0x0186, 0x0255, 0x0189, 0x018A,
- 0x0258, 0x018F, 0x025A, 0x0190, 0x025C, 0x025D, 0x025E, 0x025F,
- 0x0193, 0x0261, 0x0262, 0x0194, 0x0264, 0x0265, 0x0266, 0x0267,
- 0x0197, 0x0196, 0x026A, 0x026B, 0x026C, 0x026D, 0x026E, 0x019C,
- 0x0270, 0x0271, 0x019D, 0x0273, 0x0274, 0x019F, 0x0276, 0x0277,
- 0x0278, 0x0279, 0x027A, 0x027B, 0x027C, 0x027D, 0x027E, 0x027F,
- 0x01A6, 0x0281, 0x0282, 0x01A9, 0x0284, 0x0285, 0x0286, 0x0287,
- 0x01AE, 0x0289, 0x01B1, 0x01B2, 0x028C, 0x028D, 0x028E, 0x028F,
- 0x0290, 0x0291, 0x01B7
- };
-
- static unsigned short const LatinExtB_upper_mapping[] = { /* first part only */
- 0x0180, 0x0181, 0x0182, 0x0182, 0x0184, 0x0184, 0x0186, 0x0187,
- 0x0187, 0x0189, 0x018A, 0x018B, 0x018B, 0x018D, 0x018E, 0x018F,
- 0x0190, 0x0191, 0x0191, 0x0193, 0x0194, 0x01F6, 0x0196, 0x0197,
- 0x0198, 0x0198, 0x019A, 0x019B, 0x019C, 0x019D, 0x0220, 0x019F,
- 0x01A0, 0x01A0, 0x01A2, 0x01A2, 0x01A4, 0x01A4, 0x01A6, 0x01A7,
- 0x01A7, 0x01A9, 0x01AA, 0x01AB, 0x01AC, 0x01AC, 0x01AE, 0x01AF,
- 0x01AF, 0x01B1, 0x01B2, 0x01B3, 0x01B3, 0x01B5, 0x01B5, 0x01B7,
- 0x01B8, 0x01B8, 0x01BA, 0x01BB, 0x01BC, 0x01BC, 0x01BE, 0x01F7,
- 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C4, 0x01C4, 0x01C4, 0x01C7,
- 0x01C7, 0x01C7, 0x01CA, 0x01CA, 0x01CA
- };
-
- static unsigned short const LatinExtB_lower_mapping[] = { /* first part only */
- 0x0180, 0x0253, 0x0183, 0x0183, 0x0185, 0x0185, 0x0254, 0x0188,
- 0x0188, 0x0256, 0x0257, 0x018C, 0x018C, 0x018D, 0x01DD, 0x0259,
- 0x025B, 0x0192, 0x0192, 0x0260, 0x0263, 0x0195, 0x0269, 0x0268,
- 0x0199, 0x0199, 0x019A, 0x019B, 0x026F, 0x0272, 0x019E, 0x0275,
- 0x01A1, 0x01A1, 0x01A3, 0x01A3, 0x01A5, 0x01A5, 0x0280, 0x01A8,
- 0x01A8, 0x0283, 0x01AA, 0x01AB, 0x01AD, 0x01AD, 0x0288, 0x01B0,
- 0x01B0, 0x028A, 0x028B, 0x01B4, 0x01B4, 0x01B6, 0x01B6, 0x0292,
- 0x01B9, 0x01B9, 0x01BA, 0x01BB, 0x01BD, 0x01BD, 0x01BE, 0x01BF,
- 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C6, 0x01C6, 0x01C6, 0x01C9,
- 0x01C9, 0x01C9, 0x01CC, 0x01CC, 0x01CC
- };
-
- static unsigned short const Greek_upper_mapping[] = {
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0374, 0x0375, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x037A, 0x0000, 0x0000, 0x0000, 0x037E, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0384, 0x0385, 0x0386, 0x0387,
- 0x0388, 0x0389, 0x038A, 0x0000, 0x038C, 0x0000, 0x038E, 0x038F,
- 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
- 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
- 0x03A0, 0x03A1, 0x0000, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,
- 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x0386, 0x0388, 0x0389, 0x038A,
- 0x03B0, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
- 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
- 0x03A0, 0x03A1, 0x03A3, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,
- 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x038C, 0x038E, 0x038F, 0x0000,
- 0x0392, 0x0398, 0x03D2, 0x03D3, 0x03D4, 0x03A6, 0x03A0, 0x03D7,
- 0x03D8, 0x03D8, 0x03DA, 0x03DA, 0x03DC, 0x03DC, 0x03DE, 0x03DE,
- 0x03E0, 0x03E0, 0x03E2, 0x03E2, 0x03E4, 0x03E4, 0x03E6, 0x03E6,
- 0x03E8, 0x03E8, 0x03EA, 0x03EA, 0x03EC, 0x03EC, 0x03EE, 0x03EE,
- 0x039A, 0x03A1, 0x03F9, 0x03F3, 0x03F4, 0x0395, 0x03F6, 0x03F7,
- 0x03F7, 0x03F9, 0x03FA, 0x03FA, 0x0000, 0x0000, 0x0000, 0x0000
- };
-
- static unsigned short const Greek_lower_mapping[] = {
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0374, 0x0375, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x037A, 0x0000, 0x0000, 0x0000, 0x037E, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0384, 0x0385, 0x03AC, 0x0387,
- 0x03AD, 0x03AE, 0x03AF, 0x0000, 0x03CC, 0x0000, 0x03CD, 0x03CE,
- 0x0390, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
- 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
- 0x03C0, 0x03C1, 0x0000, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
- 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03AC, 0x03AD, 0x03AE, 0x03AF,
- 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
- 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
- 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
- 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x0000,
- 0x03D0, 0x03D1, 0x03D2, 0x03D3, 0x03D4, 0x03D5, 0x03D6, 0x03D7,
- 0x03D9, 0x03D9, 0x03DB, 0x03DB, 0x03DD, 0x03DD, 0x03DF, 0x03DF,
- 0x03E1, 0x03E1, 0x03E3, 0x03E3, 0x03E5, 0x03E5, 0x03E7, 0x03E7,
- 0x03E9, 0x03E9, 0x03EB, 0x03EB, 0x03ED, 0x03ED, 0x03EF, 0x03EF,
- 0x03F0, 0x03F1, 0x03F2, 0x03F3, 0x03B8, 0x03F5, 0x03F6, 0x03F8,
- 0x03F8, 0x03F2, 0x03FB, 0x03FB, 0x0000, 0x0000, 0x0000, 0x0000
- };
-
- static unsigned short const GreekExt_lower_mapping[] = {
- 0x1F00, 0x1F01, 0x1F02, 0x1F03, 0x1F04, 0x1F05, 0x1F06, 0x1F07,
- 0x1F00, 0x1F01, 0x1F02, 0x1F03, 0x1F04, 0x1F05, 0x1F06, 0x1F07,
- 0x1F10, 0x1F11, 0x1F12, 0x1F13, 0x1F14, 0x1F15, 0x0000, 0x0000,
- 0x1F10, 0x1F11, 0x1F12, 0x1F13, 0x1F14, 0x1F15, 0x0000, 0x0000,
- 0x1F20, 0x1F21, 0x1F22, 0x1F23, 0x1F24, 0x1F25, 0x1F26, 0x1F27,
- 0x1F20, 0x1F21, 0x1F22, 0x1F23, 0x1F24, 0x1F25, 0x1F26, 0x1F27,
- 0x1F30, 0x1F31, 0x1F32, 0x1F33, 0x1F34, 0x1F35, 0x1F36, 0x1F37,
- 0x1F30, 0x1F31, 0x1F32, 0x1F33, 0x1F34, 0x1F35, 0x1F36, 0x1F37,
- 0x1F40, 0x1F41, 0x1F42, 0x1F43, 0x1F44, 0x1F45, 0x0000, 0x0000,
- 0x1F40, 0x1F41, 0x1F42, 0x1F43, 0x1F44, 0x1F45, 0x0000, 0x0000,
- 0x1F50, 0x1F51, 0x1F52, 0x1F53, 0x1F54, 0x1F55, 0x1F56, 0x1F57,
- 0x0000, 0x1F51, 0x0000, 0x1F53, 0x0000, 0x1F55, 0x0000, 0x1F57,
- 0x1F60, 0x1F61, 0x1F62, 0x1F63, 0x1F64, 0x1F65, 0x1F66, 0x1F67,
- 0x1F60, 0x1F61, 0x1F62, 0x1F63, 0x1F64, 0x1F65, 0x1F66, 0x1F67,
- 0x1F70, 0x1F71, 0x1F72, 0x1F73, 0x1F74, 0x1F75, 0x1F76, 0x1F77,
- 0x1F78, 0x1F79, 0x1F7A, 0x1F7B, 0x1F7C, 0x1F7D, 0x0000, 0x0000,
- 0x1F80, 0x1F81, 0x1F82, 0x1F83, 0x1F84, 0x1F85, 0x1F86, 0x1F87,
- 0x1F80, 0x1F81, 0x1F82, 0x1F83, 0x1F84, 0x1F85, 0x1F86, 0x1F87,
- 0x1F90, 0x1F91, 0x1F92, 0x1F93, 0x1F94, 0x1F95, 0x1F96, 0x1F97,
- 0x1F90, 0x1F91, 0x1F92, 0x1F93, 0x1F94, 0x1F95, 0x1F96, 0x1F97,
- 0x1FA0, 0x1FA1, 0x1FA2, 0x1FA3, 0x1FA4, 0x1FA5, 0x1FA6, 0x1FA7,
- 0x1FA0, 0x1FA1, 0x1FA2, 0x1FA3, 0x1FA4, 0x1FA5, 0x1FA6, 0x1FA7,
- 0x1FB0, 0x1FB1, 0x1FB2, 0x1FB3, 0x1FB4, 0x0000, 0x1FB6, 0x1FB7,
- 0x1FB0, 0x1FB1, 0x1F70, 0x1F71, 0x1FB3, 0x1FBD, 0x1FBE, 0x1FBF,
- 0x1FC0, 0x1FC1, 0x1FC2, 0x1FC3, 0x1FC4, 0x0000, 0x1FC6, 0x1FC7,
- 0x1F72, 0x1F73, 0x1F74, 0x1F75, 0x1FC3, 0x1FCD, 0x1FCE, 0x1FCF,
- 0x1FD0, 0x1FD1, 0x1FD2, 0x1FD3, 0x0000, 0x0000, 0x1FD6, 0x1FD7,
- 0x1FD0, 0x1FD1, 0x1F76, 0x1F77, 0x0000, 0x1FDD, 0x1FDE, 0x1FDF,
- 0x1FE0, 0x1FE1, 0x1FE2, 0x1FE3, 0x1FE4, 0x1FE5, 0x1FE6, 0x1FE7,
- 0x1FE0, 0x1FE1, 0x1F7A, 0x1F7B, 0x1FE5, 0x1FED, 0x1FEE, 0x1FEF,
- 0x0000, 0x0000, 0x1FF2, 0x1FF3, 0x1FF4, 0x0000, 0x1FF6, 0x1FF7,
- 0x1F78, 0x1F79, 0x1F7C, 0x1F7D, 0x1FF3, 0x1FFD, 0x1FFE, 0x0000
- };
-
- static unsigned short const GreekExt_upper_mapping[] = {
- 0x1F08, 0x1F09, 0x1F0A, 0x1F0B, 0x1F0C, 0x1F0D, 0x1F0E, 0x1F0F,
- 0x1F08, 0x1F09, 0x1F0A, 0x1F0B, 0x1F0C, 0x1F0D, 0x1F0E, 0x1F0F,
- 0x1F18, 0x1F19, 0x1F1A, 0x1F1B, 0x1F1C, 0x1F1D, 0x0000, 0x0000,
- 0x1F18, 0x1F19, 0x1F1A, 0x1F1B, 0x1F1C, 0x1F1D, 0x0000, 0x0000,
- 0x1F28, 0x1F29, 0x1F2A, 0x1F2B, 0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F,
- 0x1F28, 0x1F29, 0x1F2A, 0x1F2B, 0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F,
- 0x1F38, 0x1F39, 0x1F3A, 0x1F3B, 0x1F3C, 0x1F3D, 0x1F3E, 0x1F3F,
- 0x1F38, 0x1F39, 0x1F3A, 0x1F3B, 0x1F3C, 0x1F3D, 0x1F3E, 0x1F3F,
- 0x1F48, 0x1F49, 0x1F4A, 0x1F4B, 0x1F4C, 0x1F4D, 0x0000, 0x0000,
- 0x1F48, 0x1F49, 0x1F4A, 0x1F4B, 0x1F4C, 0x1F4D, 0x0000, 0x0000,
- 0x1F50, 0x1F59, 0x1F52, 0x1F5B, 0x1F54, 0x1F5D, 0x1F56, 0x1F5F,
- 0x0000, 0x1F59, 0x0000, 0x1F5B, 0x0000, 0x1F5D, 0x0000, 0x1F5F,
- 0x1F68, 0x1F69, 0x1F6A, 0x1F6B, 0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F,
- 0x1F68, 0x1F69, 0x1F6A, 0x1F6B, 0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F,
- 0x1FBA, 0x1FBB, 0x1FC8, 0x1FC9, 0x1FCA, 0x1FCB, 0x1FDA, 0x1FDB,
- 0x1FF8, 0x1FF9, 0x1FEA, 0x1FEB, 0x1FFA, 0x1FFB, 0x0000, 0x0000,
- 0x1F88, 0x1F89, 0x1F8A, 0x1F8B, 0x1F8C, 0x1F8D, 0x1F8E, 0x1F8F,
- 0x1F88, 0x1F89, 0x1F8A, 0x1F8B, 0x1F8C, 0x1F8D, 0x1F8E, 0x1F8F,
- 0x1F98, 0x1F99, 0x1F9A, 0x1F9B, 0x1F9C, 0x1F9D, 0x1F9E, 0x1F9F,
- 0x1F98, 0x1F99, 0x1F9A, 0x1F9B, 0x1F9C, 0x1F9D, 0x1F9E, 0x1F9F,
- 0x1FA8, 0x1FA9, 0x1FAA, 0x1FAB, 0x1FAC, 0x1FAD, 0x1FAE, 0x1FAF,
- 0x1FA8, 0x1FA9, 0x1FAA, 0x1FAB, 0x1FAC, 0x1FAD, 0x1FAE, 0x1FAF,
- 0x1FB8, 0x1FB9, 0x1FB2, 0x1FBC, 0x1FB4, 0x0000, 0x1FB6, 0x1FB7,
- 0x1FB8, 0x1FB9, 0x1FBA, 0x1FBB, 0x1FBC, 0x1FBD, 0x0399, 0x1FBF,
- 0x1FC0, 0x1FC1, 0x1FC2, 0x1FCC, 0x1FC4, 0x0000, 0x1FC6, 0x1FC7,
- 0x1FC8, 0x1FC9, 0x1FCA, 0x1FCB, 0x1FCC, 0x1FCD, 0x1FCE, 0x1FCF,
- 0x1FD8, 0x1FD9, 0x1FD2, 0x1FD3, 0x0000, 0x0000, 0x1FD6, 0x1FD7,
- 0x1FD8, 0x1FD9, 0x1FDA, 0x1FDB, 0x0000, 0x1FDD, 0x1FDE, 0x1FDF,
- 0x1FE8, 0x1FE9, 0x1FE2, 0x1FE3, 0x1FE4, 0x1FEC, 0x1FE6, 0x1FE7,
- 0x1FE8, 0x1FE9, 0x1FEA, 0x1FEB, 0x1FEC, 0x1FED, 0x1FEE, 0x1FEF,
- 0x0000, 0x0000, 0x1FF2, 0x1FFC, 0x1FF4, 0x0000, 0x1FF6, 0x1FF7,
- 0x1FF8, 0x1FF9, 0x1FFA, 0x1FFB, 0x1FFC, 0x1FFD, 0x1FFE, 0x0000
- };
-
- *lower = code;
- *upper = code;
-
- /* Basic Latin and Latin-1 Supplement, U+0000 to U+00FF */
- if (code <= 0x00ff) {
- if (code >= 0x0041 && code <= 0x005a) /* A-Z */
- *lower += 0x20;
- else if (code >= 0x0061 && code <= 0x007a) /* a-z */
- *upper -= 0x20;
- else if ( (code >= 0x00c0 && code <= 0x00d6) ||
- (code >= 0x00d8 && code <= 0x00de) )
- *lower += 0x20;
- else if ( (code >= 0x00e0 && code <= 0x00f6) ||
- (code >= 0x00f8 && code <= 0x00fe) )
- *upper -= 0x20;
- else if (code == 0x00ff) /* y with diaeresis */
- *upper = 0x0178;
- else if (code == 0x00b5) /* micro sign */
- *upper = 0x039c;
- return;
- }
-
- /* Latin Extended-A, U+0100 to U+017F */
- if (code >= 0x0100 && code <= 0x017f) {
- if ( (code >= 0x0100 && code <= 0x012f) ||
- (code >= 0x0132 && code <= 0x0137) ||
- (code >= 0x014a && code <= 0x0177) ) {
- *upper = code & ~1;
- *lower = code | 1;
- }
- else if ( (code >= 0x0139 && code <= 0x0148) ||
- (code >= 0x0179 && code <= 0x017e) ) {
- if (code & 1)
- *lower += 1;
- else
- *upper -= 1;
- }
- else if (code == 0x0130)
- *lower = 0x0069;
- else if (code == 0x0131)
- *upper = 0x0049;
- else if (code == 0x0178)
- *lower = 0x00ff;
- else if (code == 0x017f)
- *upper = 0x0053;
- return;
- }
-
- /* Latin Extended-B, U+0180 to U+024F */
- if (code >= 0x0180 && code <= 0x024f) {
- if (code >= 0x01cd && code <= 0x01dc) {
- if (code & 1)
- *lower += 1;
- else
- *upper -= 1;
- }
- else if ( (code >= 0x01de && code <= 0x01ef) ||
- (code >= 0x01f4 && code <= 0x01f5) ||
- (code >= 0x01f8 && code <= 0x021f) ||
- (code >= 0x0222 && code <= 0x0233) ) {
- *lower |= 1;
- *upper &= ~1;
- }
- else if (code >= 0x0180 && code <= 0x01cc) {
- *lower = LatinExtB_lower_mapping[code - 0x0180];
- *upper = LatinExtB_upper_mapping[code - 0x0180];
- }
- else if (code == 0x01dd)
- *upper = 0x018e;
- else if (code == 0x01f1 || code == 0x01f2) {
- *lower = 0x01f3;
- *upper = 0x01f1;
- }
- else if (code == 0x01f3)
- *upper = 0x01f1;
- else if (code == 0x01f6)
- *lower = 0x0195;
- else if (code == 0x01f7)
- *lower = 0x01bf;
- else if (code == 0x0220)
- *lower = 0x019e;
- return;
- }
-
- /* IPA Extensions, U+0250 to U+02AF */
- if (code >= 0x0253 && code <= 0x0292) {
- *upper = IPAExt_upper_mapping[code - 0x0253];
- }
-
- /* Combining Diacritical Marks, U+0300 to U+036F */
- if (code == 0x0345) {
- *upper = 0x0399;
- }
-
- /* Greek and Coptic, U+0370 to U+03FF */
- if (code >= 0x0370 && code <= 0x03ff) {
- *lower = Greek_lower_mapping[code - 0x0370];
- *upper = Greek_upper_mapping[code - 0x0370];
- if (*upper == 0)
- *upper = code;
- if (*lower == 0)
- *lower = code;
- }
-
- /* Cyrillic and Cyrillic Supplementary, U+0400 to U+052F */
- if ( (code >= 0x0400 && code <= 0x04ff) ||
- (code >= 0x0500 && code <= 0x052f) ) {
- if (code >= 0x0400 && code <= 0x040f)
- *lower += 0x50;
- else if (code >= 0x0410 && code <= 0x042f)
- *lower += 0x20;
- else if (code >= 0x0430 && code <= 0x044f)
- *upper -= 0x20;
- else if (code >= 0x0450 && code <= 0x045f)
- *upper -= 0x50;
- else if ( (code >= 0x0460 && code <= 0x0481) ||
- (code >= 0x048a && code <= 0x04bf) ||
- (code >= 0x04d0 && code <= 0x04f5) ||
- (code >= 0x04f8 && code <= 0x04f9) ||
- (code >= 0x0500 && code <= 0x050f) ) {
- *upper &= ~1;
- *lower |= 1;
- }
- else if (code >= 0x04c1 && code <= 0x04ce) {
- if (code & 1)
- *lower += 1;
- else
- *upper -= 1;
- }
- }
-
- /* Armenian, U+0530 to U+058F */
- if (code >= 0x0530 && code <= 0x058f) {
- if (code >= 0x0531 && code <= 0x0556)
- *lower += 0x30;
- else if (code >=0x0561 && code <= 0x0586)
- *upper -= 0x30;
- }
-
- /* Latin Extended Additional, U+1E00 to U+1EFF */
- if (code >= 0x1e00 && code <= 0x1eff) {
- if ( (code >= 0x1e00 && code <= 0x1e95) ||
- (code >= 0x1ea0 && code <= 0x1ef9) ) {
- *upper &= ~1;
- *lower |= 1;
- }
- else if (code == 0x1e9b)
- *upper = 0x1e60;
- }
-
- /* Greek Extended, U+1F00 to U+1FFF */
- if (code >= 0x1f00 && code <= 0x1fff) {
- *lower = GreekExt_lower_mapping[code - 0x1f00];
- *upper = GreekExt_upper_mapping[code - 0x1f00];
- if (*upper == 0)
- *upper = code;
- if (*lower == 0)
- *lower = code;
- }
-
- /* Letterlike Symbols, U+2100 to U+214F */
- if (code >= 0x2100 && code <= 0x214f) {
- switch (code) {
- case 0x2126: *lower = 0x03c9; break;
- case 0x212a: *lower = 0x006b; break;
- case 0x212b: *lower = 0x00e5; break;
- }
- }
- /* Number Forms, U+2150 to U+218F */
- else if (code >= 0x2160 && code <= 0x216f)
- *lower += 0x10;
- else if (code >= 0x2170 && code <= 0x217f)
- *upper -= 0x10;
- /* Enclosed Alphanumerics, U+2460 to U+24FF */
- else if (code >= 0x24b6 && code <= 0x24cf)
- *lower += 0x1a;
- else if (code >= 0x24d0 && code <= 0x24e9)
- *upper -= 0x1a;
- /* Halfwidth and Fullwidth Forms, U+FF00 to U+FFEF */
- else if (code >= 0xff21 && code <= 0xff3a)
- *lower += 0x20;
- else if (code >= 0xff41 && code <= 0xff5a)
- *upper -= 0x20;
- /* Deseret, U+10400 to U+104FF */
- else if (code >= 0x10400 && code <= 0x10427)
- *lower += 0x28;
- else if (code >= 0x10428 && code <= 0x1044f)
- *upper -= 0x28;
-}
-
-void
-XConvertCase(
- register KeySym sym,
- KeySym *lower,
- KeySym *upper)
-{
- /* Latin 1 keysym */
- if (sym < 0x100) {
- UCSConvertCase(sym, lower, upper);
- return;
- }
-
- /* Unicode keysym */
- if ((sym & 0xff000000) == 0x01000000) {
- UCSConvertCase((sym & 0x00ffffff), lower, upper);
- *upper |= 0x01000000;
- *lower |= 0x01000000;
- return;
- }
-
- /* Legacy keysym */
-
- *lower = sym;
- *upper = sym;
-
- switch(sym >> 8) {
- case 1: /* Latin 2 */
- /* Assume the KeySym is a legal value (ignore discontinuities) */
- if (sym == XK_Aogonek)
- *lower = XK_aogonek;
- else if (sym >= XK_Lstroke && sym <= XK_Sacute)
- *lower += (XK_lstroke - XK_Lstroke);
- else if (sym >= XK_Scaron && sym <= XK_Zacute)
- *lower += (XK_scaron - XK_Scaron);
- else if (sym >= XK_Zcaron && sym <= XK_Zabovedot)
- *lower += (XK_zcaron - XK_Zcaron);
- else if (sym == XK_aogonek)
- *upper = XK_Aogonek;
- else if (sym >= XK_lstroke && sym <= XK_sacute)
- *upper -= (XK_lstroke - XK_Lstroke);
- else if (sym >= XK_scaron && sym <= XK_zacute)
- *upper -= (XK_scaron - XK_Scaron);
- else if (sym >= XK_zcaron && sym <= XK_zabovedot)
- *upper -= (XK_zcaron - XK_Zcaron);
- else if (sym >= XK_Racute && sym <= XK_Tcedilla)
- *lower += (XK_racute - XK_Racute);
- else if (sym >= XK_racute && sym <= XK_tcedilla)
- *upper -= (XK_racute - XK_Racute);
- break;
- case 2: /* Latin 3 */
- /* Assume the KeySym is a legal value (ignore discontinuities) */
- if (sym >= XK_Hstroke && sym <= XK_Hcircumflex)
- *lower += (XK_hstroke - XK_Hstroke);
- else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex)
- *lower += (XK_gbreve - XK_Gbreve);
- else if (sym >= XK_hstroke && sym <= XK_hcircumflex)
- *upper -= (XK_hstroke - XK_Hstroke);
- else if (sym >= XK_gbreve && sym <= XK_jcircumflex)
- *upper -= (XK_gbreve - XK_Gbreve);
- else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex)
- *lower += (XK_cabovedot - XK_Cabovedot);
- else if (sym >= XK_cabovedot && sym <= XK_scircumflex)
- *upper -= (XK_cabovedot - XK_Cabovedot);
- break;
- case 3: /* Latin 4 */
- /* Assume the KeySym is a legal value (ignore discontinuities) */
- if (sym >= XK_Rcedilla && sym <= XK_Tslash)
- *lower += (XK_rcedilla - XK_Rcedilla);
- else if (sym >= XK_rcedilla && sym <= XK_tslash)
- *upper -= (XK_rcedilla - XK_Rcedilla);
- else if (sym == XK_ENG)
- *lower = XK_eng;
- else if (sym == XK_eng)
- *upper = XK_ENG;
- else if (sym >= XK_Amacron && sym <= XK_Umacron)
- *lower += (XK_amacron - XK_Amacron);
- else if (sym >= XK_amacron && sym <= XK_umacron)
- *upper -= (XK_amacron - XK_Amacron);
- break;
- case 6: /* Cyrillic */
- /* Assume the KeySym is a legal value (ignore discontinuities) */
- if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE)
- *lower -= (XK_Serbian_DJE - XK_Serbian_dje);
- else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze)
- *upper += (XK_Serbian_DJE - XK_Serbian_dje);
- else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN)
- *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu);
- else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign)
- *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu);
- break;
- case 7: /* Greek */
- /* Assume the KeySym is a legal value (ignore discontinuities) */
- if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent)
- *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
- else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent &&
- sym != XK_Greek_iotaaccentdieresis &&
- sym != XK_Greek_upsilonaccentdieresis)
- *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
- else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA)
- *lower += (XK_Greek_alpha - XK_Greek_ALPHA);
- else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega &&
- sym != XK_Greek_finalsmallsigma)
- *upper -= (XK_Greek_alpha - XK_Greek_ALPHA);
- break;
- case 0x13: /* Latin 9 */
- if (sym == XK_OE)
- *lower = XK_oe;
- else if (sym == XK_oe)
- *upper = XK_OE;
- else if (sym == XK_Ydiaeresis)
- *lower = XK_ydiaeresis;
- break;
- }
-}
-
-int
-_XTranslateKey( register Display *dpy,
- KeyCode keycode,
- register unsigned int modifiers,
- unsigned int *modifiers_return,
- KeySym *keysym_return)
-{
- int per;
- register KeySym *syms;
- KeySym sym, lsym, usym;
-
- if ((! dpy->keysyms) && (! _XKeyInitialize(dpy)))
- return 0;
- *modifiers_return = ((ShiftMask|LockMask)
- | dpy->mode_switch | dpy->num_lock);
- if (((int)keycode < dpy->min_keycode) || ((int)keycode > dpy->max_keycode))
- {
- *keysym_return = NoSymbol;
- return 1;
- }
- per = dpy->keysyms_per_keycode;
- syms = &dpy->keysyms[(keycode - dpy->min_keycode) * per];
- while ((per > 2) && (syms[per - 1] == NoSymbol))
- per--;
- if ((per > 2) && (modifiers & dpy->mode_switch)) {
- syms += 2;
- per -= 2;
- }
- if ((modifiers & dpy->num_lock) &&
- (per > 1 && (IsKeypadKey(syms[1]) || IsPrivateKeypadKey(syms[1])))) {
- if ((modifiers & ShiftMask) ||
- ((modifiers & LockMask) && (dpy->lock_meaning == XK_Shift_Lock)))
- *keysym_return = syms[0];
- else
- *keysym_return = syms[1];
- } else if (!(modifiers & ShiftMask) &&
- (!(modifiers & LockMask) || (dpy->lock_meaning == NoSymbol))) {
- if ((per == 1) || (syms[1] == NoSymbol))
- XConvertCase(syms[0], keysym_return, &usym);
- else
- *keysym_return = syms[0];
- } else if (!(modifiers & LockMask) ||
- (dpy->lock_meaning != XK_Caps_Lock)) {
- if ((per == 1) || ((usym = syms[1]) == NoSymbol))
- XConvertCase(syms[0], &lsym, &usym);
- *keysym_return = usym;
- } else {
- if ((per == 1) || ((sym = syms[1]) == NoSymbol))
- sym = syms[0];
- XConvertCase(sym, &lsym, &usym);
- if (!(modifiers & ShiftMask) && (sym != syms[0]) &&
- ((sym != usym) || (lsym == usym)))
- XConvertCase(syms[0], &lsym, &usym);
- *keysym_return = usym;
- }
- if (*keysym_return == XK_VoidSymbol)
- *keysym_return = NoSymbol;
- return 1;
-}
-
-int
-_XTranslateKeySym(
- Display *dpy,
- register KeySym symbol,
- unsigned int modifiers,
- char *buffer,
- int nbytes)
-{
- register struct _XKeytrans *p;
- int length;
- unsigned long hiBytes;
- register unsigned char c;
-
- if (!symbol)
- return 0;
- /* see if symbol rebound, if so, return that string. */
- for (p = dpy->key_bindings; p; p = p->next) {
- if (((modifiers & AllMods) == p->state) && (symbol == p->key)) {
- length = p->len;
- if (length > nbytes) length = nbytes;
- memcpy (buffer, p->string, length);
- return length;
- }
- }
- /* try to convert to Latin-1, handling control */
- hiBytes = symbol >> 8;
- if (!(nbytes &&
- ((hiBytes == 0) ||
- ((hiBytes == 0xFF) &&
- (((symbol >= XK_BackSpace) && (symbol <= XK_Clear)) ||
- (symbol == XK_Return) ||
- (symbol == XK_Escape) ||
- (symbol == XK_KP_Space) ||
- (symbol == XK_KP_Tab) ||
- (symbol == XK_KP_Enter) ||
- ((symbol >= XK_KP_Multiply) && (symbol <= XK_KP_9)) ||
- (symbol == XK_KP_Equal) ||
- (symbol == XK_Delete))))))
- return 0;
-
- /* if X keysym, convert to ascii by grabbing low 7 bits */
- if (symbol == XK_KP_Space)
- c = XK_space & 0x7F; /* patch encoding botch */
- else if (hiBytes == 0xFF)
- c = symbol & 0x7F;
- else
- c = symbol & 0xFF;
- /* only apply Control key if it makes sense, else ignore it */
- if (modifiers & ControlMask) {
- if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F;
- else if (c == '2') c = '\000';
- else if (c >= '3' && c <= '7') c -= ('3' - '\033');
- else if (c == '8') c = '\177';
- else if (c == '/') c = '_' & 0x1F;
- }
- buffer[0] = c;
- return 1;
-}
-
-/*ARGSUSED*/
-int
-XLookupString (
- register XKeyEvent *event,
- char *buffer, /* buffer */
- int nbytes, /* space in buffer for characters */
- KeySym *keysym,
- XComposeStatus *status) /* not implemented */
-{
- unsigned int modifiers;
- KeySym symbol;
-
- if (! _XTranslateKey(event->display, event->keycode, event->state,
- &modifiers, &symbol))
- return 0;
-
-#ifdef USE_OWN_COMPOSE
- if ( status ) {
- static int been_here= 0;
- if ( !been_here ) {
- XimCompInitTables();
- been_here = 1;
- }
- if ( !XimCompLegalStatus(status) ) {
- status->compose_ptr = NULL;
- status->chars_matched = 0;
- }
- if ( ((status->chars_matched>0)&&(status->compose_ptr!=NULL)) ||
- XimCompIsComposeKey(symbol,event->keycode,status) ) {
- XimCompRtrn rtrn;
- switch (XimCompProcessSym(status,symbol,&rtrn)) {
- case XIM_COMP_IGNORE:
- break;
- case XIM_COMP_IN_PROGRESS:
- if ( keysym!=NULL )
- *keysym = NoSymbol;
- return 0;
- case XIM_COMP_FAIL:
- {
- int n = 0, len= 0;
- for (n=len=0;rtrn.sym[n]!=XK_VoidSymbol;n++) {
- if ( nbytes-len > 0 ) {
- len+= _XTranslateKeySym(event->display,rtrn.sym[n],
- event->state,
- buffer+len,nbytes-len);
- }
- }
- if ( keysym!=NULL ) {
- if ( n==1 ) *keysym = rtrn.sym[0];
- else *keysym = NoSymbol;
- }
- return len;
- }
- case XIM_COMP_SUCCEED:
- {
- int len,n = 0;
-
- symbol = rtrn.matchSym;
- if ( keysym!=NULL ) *keysym = symbol;
- if ( rtrn.str[0]!='\0' ) {
- strncpy(buffer,rtrn.str,nbytes-1);
- buffer[nbytes-1]= '\0';
- len = strlen(buffer);
- }
- else {
- len = _XTranslateKeySym(event->display,symbol,
- event->state,
- buffer,nbytes);
- }
- for (n=0;rtrn.sym[n]!=XK_VoidSymbol;n++) {
- if ( nbytes-len > 0 ) {
- len+= _XTranslateKeySym(event->display,rtrn.sym[n],
- event->state,
- buffer+len,nbytes-len);
- }
- }
- return len;
- }
- }
- }
- }
-#endif
-
- if (keysym)
- *keysym = symbol;
- /* arguable whether to use (event->state & ~modifiers) here */
- return _XTranslateKeySym(event->display, symbol, event->state,
- buffer, nbytes);
-}
-
-static void
-_XFreeKeyBindings(
- Display *dpy)
-{
- register struct _XKeytrans *p, *np;
-
- for (p = dpy->key_bindings; p; p = np) {
- np = p->next;
- Xfree(p->string);
- Xfree((char *)p->modifiers);
- Xfree((char *)p);
- }
-}
-
-int
-XRebindKeysym (
- Display *dpy,
- KeySym keysym,
- KeySym *mlist,
- int nm, /* number of modifiers in mlist */
- _Xconst unsigned char *str,
- int nbytes)
-{
- register struct _XKeytrans *tmp, *p;
- int nb;
-
- if ((! dpy->keysyms) && (! _XKeyInitialize(dpy)))
- return 0;
- LockDisplay(dpy);
- tmp = dpy->key_bindings;
- nb = sizeof(KeySym) * nm;
-
- if ((! (p = (struct _XKeytrans *) Xcalloc( 1, sizeof(struct _XKeytrans)))) ||
- ((! (p->string = (char *) Xmalloc( (unsigned) nbytes))) &&
- (nbytes > 0)) ||
- ((! (p->modifiers = (KeySym *) Xmalloc( (unsigned) nb))) &&
- (nb > 0))) {
- if (p) {
- if (p->string) Xfree(p->string);
- if (p->modifiers) Xfree((char *) p->modifiers);
- Xfree((char *) p);
- }
- UnlockDisplay(dpy);
- return 0;
- }
-
- dpy->key_bindings = p;
- dpy->free_funcs->key_bindings = _XFreeKeyBindings;
- p->next = tmp; /* chain onto list */
- memcpy (p->string, (char *) str, nbytes);
- p->len = nbytes;
- memcpy ((char *) p->modifiers, (char *) mlist, nb);
- p->key = keysym;
- p->mlen = nm;
- ComputeMaskFromKeytrans(dpy, p);
- UnlockDisplay(dpy);
- return 0;
-}
-
-unsigned
-_XKeysymToModifiers(
- Display *dpy,
- KeySym ks)
-{
- CARD8 code,mods;
- register KeySym *kmax;
- register KeySym *k;
- register XModifierKeymap *m;
-
- if ((! dpy->keysyms) && (! _XKeyInitialize(dpy)))
- return 0;
- kmax = dpy->keysyms +
- (dpy->max_keycode - dpy->min_keycode + 1) * dpy->keysyms_per_keycode;
- k = dpy->keysyms;
- m = dpy->modifiermap;
- mods= 0;
- while (k<kmax) {
- if (*k == ks ) {
- register int j = m->max_keypermod<<3;
-
- code=(((k-dpy->keysyms)/dpy->keysyms_per_keycode)+dpy->min_keycode);
-
- while (--j >= 0) {
- if (code == m->modifiermap[j])
- mods|= (1<<(j/m->max_keypermod));
- }
- }
- k++;
- }
- return mods;
-}
-
-/*
- * given a list of modifiers, computes the mask necessary for later matching.
- * This routine must lookup the key in the Keymap and then search to see
- * what modifier it is bound to, if any. Sets the AnyModifier bit if it
- * can't map some keysym to a modifier.
- */
-static void
-ComputeMaskFromKeytrans(
- Display *dpy,
- register struct _XKeytrans *p)
-{
- register int i;
-
- p->state = AnyModifier;
- for (i = 0; i < p->mlen; i++) {
- p->state|= XkbKeysymToModifiers(dpy,p->modifiers[i]);
- }
- p->state &= AllMods;
-}
+/* + +Copyright 1985, 1987, 1998 The Open Group + +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. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +/* Beware, here be monsters (still under construction... - JG */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <X11/Xlibint.h> +#include <X11/Xutil.h> +#define XK_MISCELLANY +#define XK_LATIN1 +#define XK_LATIN2 +#define XK_LATIN3 +#define XK_LATIN4 +#define XK_LATIN8 +#define XK_LATIN9 +#define XK_CYRILLIC +#define XK_GREEK +#define XK_ARMENIAN +#define XK_CAUCASUS +#define XK_VIETNAMESE +#define XK_XKB_KEYS +#define XK_SINHALA +#include <X11/keysymdef.h> +#include <stdio.h> + +#ifdef USE_OWN_COMPOSE +#include "imComp.h" + +#endif + +#include "Xresource.h" +#include "Key.h" + +#ifdef XKB +#include "XKBlib.h" +#include "XKBlibint.h" +#define XKeycodeToKeysym _XKeycodeToKeysym +#define XKeysymToKeycode _XKeysymToKeycode +#define XLookupKeysym _XLookupKeysym +#define XRefreshKeyboardMapping _XRefreshKeyboardMapping +#define XLookupString _XLookupString +/* XKBBind.c */ +#else +#define XkbKeysymToModifiers _XKeysymToModifiers +#endif + +#define AllMods (ShiftMask|LockMask|ControlMask| \ + Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask) + +static void +ComputeMaskFromKeytrans( + Display *dpy, + register struct _XKeytrans *p); + +struct _XKeytrans { + struct _XKeytrans *next;/* next on list */ + char *string; /* string to return when the time comes */ + int len; /* length of string (since NULL is legit)*/ + KeySym key; /* keysym rebound */ + unsigned int state; /* modifier state */ + KeySym *modifiers; /* modifier keysyms you want */ + int mlen; /* length of modifier list */ +}; + +static KeySym +KeyCodetoKeySym(register Display *dpy, KeyCode keycode, int col) +{ + register int per = dpy->keysyms_per_keycode; + register KeySym *syms; + KeySym lsym, usym; + + if ((col < 0) || ((col >= per) && (col > 3)) || + ((int)keycode < dpy->min_keycode) || ((int)keycode > dpy->max_keycode)) + return NoSymbol; + + syms = &dpy->keysyms[(keycode - dpy->min_keycode) * per]; + if (col < 4) { + if (col > 1) { + while ((per > 2) && (syms[per - 1] == NoSymbol)) + per--; + if (per < 3) + col -= 2; + } + if ((per <= (col|1)) || (syms[col|1] == NoSymbol)) { + XConvertCase(syms[col&~1], &lsym, &usym); + if (!(col & 1)) + return lsym; + else if (usym == lsym) + return NoSymbol; + else + return usym; + } + } + return syms[col]; +} + +KeySym +XKeycodeToKeysym(Display *dpy, +#if NeedWidePrototypes + unsigned int kc, +#else + KeyCode kc, +#endif + int col) +{ + if ((! dpy->keysyms) && (! _XKeyInitialize(dpy))) + return NoSymbol; + return KeyCodetoKeySym(dpy, kc, col); +} + +KeyCode +XKeysymToKeycode( + Display *dpy, + KeySym ks) +{ + register int i, j; + + if ((! dpy->keysyms) && (! _XKeyInitialize(dpy))) + return (KeyCode) 0; + for (j = 0; j < dpy->keysyms_per_keycode; j++) { + for (i = dpy->min_keycode; i <= dpy->max_keycode; i++) { + if (KeyCodetoKeySym(dpy, (KeyCode) i, j) == ks) + return i; + } + } + return 0; +} + +KeySym +XLookupKeysym( + register XKeyEvent *event, + int col) +{ + if ((! event->display->keysyms) && (! _XKeyInitialize(event->display))) + return NoSymbol; + return KeyCodetoKeySym(event->display, event->keycode, col); +} + +static void +ResetModMap( + Display *dpy) +{ + register XModifierKeymap *map; + register int i, j, n; + KeySym sym; + register struct _XKeytrans *p; + + map = dpy->modifiermap; + /* If any Lock key contains Caps_Lock, then interpret as Caps_Lock, + * else if any contains Shift_Lock, then interpret as Shift_Lock, + * else ignore Lock altogether. + */ + dpy->lock_meaning = NoSymbol; + /* Lock modifiers are in the second row of the matrix */ + n = 2 * map->max_keypermod; + for (i = map->max_keypermod; i < n; i++) { + for (j = 0; j < dpy->keysyms_per_keycode; j++) { + sym = KeyCodetoKeySym(dpy, map->modifiermap[i], j); + if (sym == XK_Caps_Lock) { + dpy->lock_meaning = XK_Caps_Lock; + break; + } else if (sym == XK_Shift_Lock) { + dpy->lock_meaning = XK_Shift_Lock; + } + else if (sym == XK_ISO_Lock) { + dpy->lock_meaning = XK_Caps_Lock; + break; + } + } + } + /* Now find any Mod<n> modifier acting as the Group or Numlock modifier */ + dpy->mode_switch = 0; + dpy->num_lock = 0; + n *= 4; + for (i = 3*map->max_keypermod; i < n; i++) { + for (j = 0; j < dpy->keysyms_per_keycode; j++) { + sym = KeyCodetoKeySym(dpy, map->modifiermap[i], j); + if (sym == XK_Mode_switch) + dpy->mode_switch |= 1 << (i / map->max_keypermod); + if (sym == XK_Num_Lock) + dpy->num_lock |= 1 << (i / map->max_keypermod); + } + } + for (p = dpy->key_bindings; p; p = p->next) + ComputeMaskFromKeytrans(dpy, p); +} + +static int +InitModMap( + Display *dpy) +{ + register XModifierKeymap *map; + + if (! (map = XGetModifierMapping(dpy))) + return 0; + LockDisplay(dpy); + if (dpy->modifiermap) + XFreeModifiermap(dpy->modifiermap); + dpy->modifiermap = map; + dpy->free_funcs->modifiermap = XFreeModifiermap; + if (dpy->keysyms) + ResetModMap(dpy); + UnlockDisplay(dpy); + return 1; +} + +int +XRefreshKeyboardMapping(register XMappingEvent *event) +{ + + if(event->request == MappingKeyboard) { + /* XXX should really only refresh what is necessary + * for now, make initialize test fail + */ + LockDisplay(event->display); + if (event->display->keysyms) { + Xfree ((char *)event->display->keysyms); + event->display->keysyms = NULL; + } + UnlockDisplay(event->display); + } + if(event->request == MappingModifier) { + LockDisplay(event->display); + if (event->display->modifiermap) { + XFreeModifiermap(event->display->modifiermap); + event->display->modifiermap = NULL; + } + UnlockDisplay(event->display); + /* go ahead and get it now, since initialize test may not fail */ + if (event->display->keysyms) + (void) InitModMap(event->display); + } + return 1; +} + +int +_XKeyInitialize( + Display *dpy) +{ + int per, n; + KeySym *keysyms; + + /* + * lets go get the keysyms from the server. + */ + if (!dpy->keysyms) { + n = dpy->max_keycode - dpy->min_keycode + 1; + keysyms = XGetKeyboardMapping (dpy, (KeyCode) dpy->min_keycode, + n, &per); + /* keysyms may be NULL */ + if (! keysyms) return 0; + + LockDisplay(dpy); + if (dpy->keysyms) + Xfree ((char *)dpy->keysyms); + dpy->keysyms = keysyms; + dpy->keysyms_per_keycode = per; + if (dpy->modifiermap) + ResetModMap(dpy); + UnlockDisplay(dpy); + } + if (!dpy->modifiermap) + return InitModMap(dpy); + return 1; +} + +static void +UCSConvertCase( register unsigned code, + KeySym *lower, + KeySym *upper ) +{ + /* Case conversion for UCS, as in Unicode Data version 4.0.0 */ + /* NB: Only converts simple one-to-one mappings. */ + + /* Tables are used where they take less space than */ + /* the code to work out the mappings. Zero values mean */ + /* undefined code points. */ + + static unsigned short const IPAExt_upper_mapping[] = { /* part only */ + 0x0181, 0x0186, 0x0255, 0x0189, 0x018A, + 0x0258, 0x018F, 0x025A, 0x0190, 0x025C, 0x025D, 0x025E, 0x025F, + 0x0193, 0x0261, 0x0262, 0x0194, 0x0264, 0x0265, 0x0266, 0x0267, + 0x0197, 0x0196, 0x026A, 0x026B, 0x026C, 0x026D, 0x026E, 0x019C, + 0x0270, 0x0271, 0x019D, 0x0273, 0x0274, 0x019F, 0x0276, 0x0277, + 0x0278, 0x0279, 0x027A, 0x027B, 0x027C, 0x027D, 0x027E, 0x027F, + 0x01A6, 0x0281, 0x0282, 0x01A9, 0x0284, 0x0285, 0x0286, 0x0287, + 0x01AE, 0x0289, 0x01B1, 0x01B2, 0x028C, 0x028D, 0x028E, 0x028F, + 0x0290, 0x0291, 0x01B7 + }; + + static unsigned short const LatinExtB_upper_mapping[] = { /* first part only */ + 0x0180, 0x0181, 0x0182, 0x0182, 0x0184, 0x0184, 0x0186, 0x0187, + 0x0187, 0x0189, 0x018A, 0x018B, 0x018B, 0x018D, 0x018E, 0x018F, + 0x0190, 0x0191, 0x0191, 0x0193, 0x0194, 0x01F6, 0x0196, 0x0197, + 0x0198, 0x0198, 0x019A, 0x019B, 0x019C, 0x019D, 0x0220, 0x019F, + 0x01A0, 0x01A0, 0x01A2, 0x01A2, 0x01A4, 0x01A4, 0x01A6, 0x01A7, + 0x01A7, 0x01A9, 0x01AA, 0x01AB, 0x01AC, 0x01AC, 0x01AE, 0x01AF, + 0x01AF, 0x01B1, 0x01B2, 0x01B3, 0x01B3, 0x01B5, 0x01B5, 0x01B7, + 0x01B8, 0x01B8, 0x01BA, 0x01BB, 0x01BC, 0x01BC, 0x01BE, 0x01F7, + 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C4, 0x01C4, 0x01C4, 0x01C7, + 0x01C7, 0x01C7, 0x01CA, 0x01CA, 0x01CA + }; + + static unsigned short const LatinExtB_lower_mapping[] = { /* first part only */ + 0x0180, 0x0253, 0x0183, 0x0183, 0x0185, 0x0185, 0x0254, 0x0188, + 0x0188, 0x0256, 0x0257, 0x018C, 0x018C, 0x018D, 0x01DD, 0x0259, + 0x025B, 0x0192, 0x0192, 0x0260, 0x0263, 0x0195, 0x0269, 0x0268, + 0x0199, 0x0199, 0x019A, 0x019B, 0x026F, 0x0272, 0x019E, 0x0275, + 0x01A1, 0x01A1, 0x01A3, 0x01A3, 0x01A5, 0x01A5, 0x0280, 0x01A8, + 0x01A8, 0x0283, 0x01AA, 0x01AB, 0x01AD, 0x01AD, 0x0288, 0x01B0, + 0x01B0, 0x028A, 0x028B, 0x01B4, 0x01B4, 0x01B6, 0x01B6, 0x0292, + 0x01B9, 0x01B9, 0x01BA, 0x01BB, 0x01BD, 0x01BD, 0x01BE, 0x01BF, + 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C6, 0x01C6, 0x01C6, 0x01C9, + 0x01C9, 0x01C9, 0x01CC, 0x01CC, 0x01CC + }; + + static unsigned short const Greek_upper_mapping[] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0374, 0x0375, 0x0000, 0x0000, + 0x0000, 0x0000, 0x037A, 0x0000, 0x0000, 0x0000, 0x037E, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0384, 0x0385, 0x0386, 0x0387, + 0x0388, 0x0389, 0x038A, 0x0000, 0x038C, 0x0000, 0x038E, 0x038F, + 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, + 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, + 0x03A0, 0x03A1, 0x0000, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, + 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x0386, 0x0388, 0x0389, 0x038A, + 0x03B0, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, + 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, + 0x03A0, 0x03A1, 0x03A3, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, + 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x038C, 0x038E, 0x038F, 0x0000, + 0x0392, 0x0398, 0x03D2, 0x03D3, 0x03D4, 0x03A6, 0x03A0, 0x03D7, + 0x03D8, 0x03D8, 0x03DA, 0x03DA, 0x03DC, 0x03DC, 0x03DE, 0x03DE, + 0x03E0, 0x03E0, 0x03E2, 0x03E2, 0x03E4, 0x03E4, 0x03E6, 0x03E6, + 0x03E8, 0x03E8, 0x03EA, 0x03EA, 0x03EC, 0x03EC, 0x03EE, 0x03EE, + 0x039A, 0x03A1, 0x03F9, 0x03F3, 0x03F4, 0x0395, 0x03F6, 0x03F7, + 0x03F7, 0x03F9, 0x03FA, 0x03FA, 0x0000, 0x0000, 0x0000, 0x0000 + }; + + static unsigned short const Greek_lower_mapping[] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0374, 0x0375, 0x0000, 0x0000, + 0x0000, 0x0000, 0x037A, 0x0000, 0x0000, 0x0000, 0x037E, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0384, 0x0385, 0x03AC, 0x0387, + 0x03AD, 0x03AE, 0x03AF, 0x0000, 0x03CC, 0x0000, 0x03CD, 0x03CE, + 0x0390, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, + 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, + 0x03C0, 0x03C1, 0x0000, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, + 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03AC, 0x03AD, 0x03AE, 0x03AF, + 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, + 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, + 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, + 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x0000, + 0x03D0, 0x03D1, 0x03D2, 0x03D3, 0x03D4, 0x03D5, 0x03D6, 0x03D7, + 0x03D9, 0x03D9, 0x03DB, 0x03DB, 0x03DD, 0x03DD, 0x03DF, 0x03DF, + 0x03E1, 0x03E1, 0x03E3, 0x03E3, 0x03E5, 0x03E5, 0x03E7, 0x03E7, + 0x03E9, 0x03E9, 0x03EB, 0x03EB, 0x03ED, 0x03ED, 0x03EF, 0x03EF, + 0x03F0, 0x03F1, 0x03F2, 0x03F3, 0x03B8, 0x03F5, 0x03F6, 0x03F8, + 0x03F8, 0x03F2, 0x03FB, 0x03FB, 0x0000, 0x0000, 0x0000, 0x0000 + }; + + static unsigned short const GreekExt_lower_mapping[] = { + 0x1F00, 0x1F01, 0x1F02, 0x1F03, 0x1F04, 0x1F05, 0x1F06, 0x1F07, + 0x1F00, 0x1F01, 0x1F02, 0x1F03, 0x1F04, 0x1F05, 0x1F06, 0x1F07, + 0x1F10, 0x1F11, 0x1F12, 0x1F13, 0x1F14, 0x1F15, 0x0000, 0x0000, + 0x1F10, 0x1F11, 0x1F12, 0x1F13, 0x1F14, 0x1F15, 0x0000, 0x0000, + 0x1F20, 0x1F21, 0x1F22, 0x1F23, 0x1F24, 0x1F25, 0x1F26, 0x1F27, + 0x1F20, 0x1F21, 0x1F22, 0x1F23, 0x1F24, 0x1F25, 0x1F26, 0x1F27, + 0x1F30, 0x1F31, 0x1F32, 0x1F33, 0x1F34, 0x1F35, 0x1F36, 0x1F37, + 0x1F30, 0x1F31, 0x1F32, 0x1F33, 0x1F34, 0x1F35, 0x1F36, 0x1F37, + 0x1F40, 0x1F41, 0x1F42, 0x1F43, 0x1F44, 0x1F45, 0x0000, 0x0000, + 0x1F40, 0x1F41, 0x1F42, 0x1F43, 0x1F44, 0x1F45, 0x0000, 0x0000, + 0x1F50, 0x1F51, 0x1F52, 0x1F53, 0x1F54, 0x1F55, 0x1F56, 0x1F57, + 0x0000, 0x1F51, 0x0000, 0x1F53, 0x0000, 0x1F55, 0x0000, 0x1F57, + 0x1F60, 0x1F61, 0x1F62, 0x1F63, 0x1F64, 0x1F65, 0x1F66, 0x1F67, + 0x1F60, 0x1F61, 0x1F62, 0x1F63, 0x1F64, 0x1F65, 0x1F66, 0x1F67, + 0x1F70, 0x1F71, 0x1F72, 0x1F73, 0x1F74, 0x1F75, 0x1F76, 0x1F77, + 0x1F78, 0x1F79, 0x1F7A, 0x1F7B, 0x1F7C, 0x1F7D, 0x0000, 0x0000, + 0x1F80, 0x1F81, 0x1F82, 0x1F83, 0x1F84, 0x1F85, 0x1F86, 0x1F87, + 0x1F80, 0x1F81, 0x1F82, 0x1F83, 0x1F84, 0x1F85, 0x1F86, 0x1F87, + 0x1F90, 0x1F91, 0x1F92, 0x1F93, 0x1F94, 0x1F95, 0x1F96, 0x1F97, + 0x1F90, 0x1F91, 0x1F92, 0x1F93, 0x1F94, 0x1F95, 0x1F96, 0x1F97, + 0x1FA0, 0x1FA1, 0x1FA2, 0x1FA3, 0x1FA4, 0x1FA5, 0x1FA6, 0x1FA7, + 0x1FA0, 0x1FA1, 0x1FA2, 0x1FA3, 0x1FA4, 0x1FA5, 0x1FA6, 0x1FA7, + 0x1FB0, 0x1FB1, 0x1FB2, 0x1FB3, 0x1FB4, 0x0000, 0x1FB6, 0x1FB7, + 0x1FB0, 0x1FB1, 0x1F70, 0x1F71, 0x1FB3, 0x1FBD, 0x1FBE, 0x1FBF, + 0x1FC0, 0x1FC1, 0x1FC2, 0x1FC3, 0x1FC4, 0x0000, 0x1FC6, 0x1FC7, + 0x1F72, 0x1F73, 0x1F74, 0x1F75, 0x1FC3, 0x1FCD, 0x1FCE, 0x1FCF, + 0x1FD0, 0x1FD1, 0x1FD2, 0x1FD3, 0x0000, 0x0000, 0x1FD6, 0x1FD7, + 0x1FD0, 0x1FD1, 0x1F76, 0x1F77, 0x0000, 0x1FDD, 0x1FDE, 0x1FDF, + 0x1FE0, 0x1FE1, 0x1FE2, 0x1FE3, 0x1FE4, 0x1FE5, 0x1FE6, 0x1FE7, + 0x1FE0, 0x1FE1, 0x1F7A, 0x1F7B, 0x1FE5, 0x1FED, 0x1FEE, 0x1FEF, + 0x0000, 0x0000, 0x1FF2, 0x1FF3, 0x1FF4, 0x0000, 0x1FF6, 0x1FF7, + 0x1F78, 0x1F79, 0x1F7C, 0x1F7D, 0x1FF3, 0x1FFD, 0x1FFE, 0x0000 + }; + + static unsigned short const GreekExt_upper_mapping[] = { + 0x1F08, 0x1F09, 0x1F0A, 0x1F0B, 0x1F0C, 0x1F0D, 0x1F0E, 0x1F0F, + 0x1F08, 0x1F09, 0x1F0A, 0x1F0B, 0x1F0C, 0x1F0D, 0x1F0E, 0x1F0F, + 0x1F18, 0x1F19, 0x1F1A, 0x1F1B, 0x1F1C, 0x1F1D, 0x0000, 0x0000, + 0x1F18, 0x1F19, 0x1F1A, 0x1F1B, 0x1F1C, 0x1F1D, 0x0000, 0x0000, + 0x1F28, 0x1F29, 0x1F2A, 0x1F2B, 0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F, + 0x1F28, 0x1F29, 0x1F2A, 0x1F2B, 0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F, + 0x1F38, 0x1F39, 0x1F3A, 0x1F3B, 0x1F3C, 0x1F3D, 0x1F3E, 0x1F3F, + 0x1F38, 0x1F39, 0x1F3A, 0x1F3B, 0x1F3C, 0x1F3D, 0x1F3E, 0x1F3F, + 0x1F48, 0x1F49, 0x1F4A, 0x1F4B, 0x1F4C, 0x1F4D, 0x0000, 0x0000, + 0x1F48, 0x1F49, 0x1F4A, 0x1F4B, 0x1F4C, 0x1F4D, 0x0000, 0x0000, + 0x1F50, 0x1F59, 0x1F52, 0x1F5B, 0x1F54, 0x1F5D, 0x1F56, 0x1F5F, + 0x0000, 0x1F59, 0x0000, 0x1F5B, 0x0000, 0x1F5D, 0x0000, 0x1F5F, + 0x1F68, 0x1F69, 0x1F6A, 0x1F6B, 0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F, + 0x1F68, 0x1F69, 0x1F6A, 0x1F6B, 0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F, + 0x1FBA, 0x1FBB, 0x1FC8, 0x1FC9, 0x1FCA, 0x1FCB, 0x1FDA, 0x1FDB, + 0x1FF8, 0x1FF9, 0x1FEA, 0x1FEB, 0x1FFA, 0x1FFB, 0x0000, 0x0000, + 0x1F88, 0x1F89, 0x1F8A, 0x1F8B, 0x1F8C, 0x1F8D, 0x1F8E, 0x1F8F, + 0x1F88, 0x1F89, 0x1F8A, 0x1F8B, 0x1F8C, 0x1F8D, 0x1F8E, 0x1F8F, + 0x1F98, 0x1F99, 0x1F9A, 0x1F9B, 0x1F9C, 0x1F9D, 0x1F9E, 0x1F9F, + 0x1F98, 0x1F99, 0x1F9A, 0x1F9B, 0x1F9C, 0x1F9D, 0x1F9E, 0x1F9F, + 0x1FA8, 0x1FA9, 0x1FAA, 0x1FAB, 0x1FAC, 0x1FAD, 0x1FAE, 0x1FAF, + 0x1FA8, 0x1FA9, 0x1FAA, 0x1FAB, 0x1FAC, 0x1FAD, 0x1FAE, 0x1FAF, + 0x1FB8, 0x1FB9, 0x1FB2, 0x1FBC, 0x1FB4, 0x0000, 0x1FB6, 0x1FB7, + 0x1FB8, 0x1FB9, 0x1FBA, 0x1FBB, 0x1FBC, 0x1FBD, 0x0399, 0x1FBF, + 0x1FC0, 0x1FC1, 0x1FC2, 0x1FCC, 0x1FC4, 0x0000, 0x1FC6, 0x1FC7, + 0x1FC8, 0x1FC9, 0x1FCA, 0x1FCB, 0x1FCC, 0x1FCD, 0x1FCE, 0x1FCF, + 0x1FD8, 0x1FD9, 0x1FD2, 0x1FD3, 0x0000, 0x0000, 0x1FD6, 0x1FD7, + 0x1FD8, 0x1FD9, 0x1FDA, 0x1FDB, 0x0000, 0x1FDD, 0x1FDE, 0x1FDF, + 0x1FE8, 0x1FE9, 0x1FE2, 0x1FE3, 0x1FE4, 0x1FEC, 0x1FE6, 0x1FE7, + 0x1FE8, 0x1FE9, 0x1FEA, 0x1FEB, 0x1FEC, 0x1FED, 0x1FEE, 0x1FEF, + 0x0000, 0x0000, 0x1FF2, 0x1FFC, 0x1FF4, 0x0000, 0x1FF6, 0x1FF7, + 0x1FF8, 0x1FF9, 0x1FFA, 0x1FFB, 0x1FFC, 0x1FFD, 0x1FFE, 0x0000 + }; + + *lower = code; + *upper = code; + + /* Basic Latin and Latin-1 Supplement, U+0000 to U+00FF */ + if (code <= 0x00ff) { + if (code >= 0x0041 && code <= 0x005a) /* A-Z */ + *lower += 0x20; + else if (code >= 0x0061 && code <= 0x007a) /* a-z */ + *upper -= 0x20; + else if ( (code >= 0x00c0 && code <= 0x00d6) || + (code >= 0x00d8 && code <= 0x00de) ) + *lower += 0x20; + else if ( (code >= 0x00e0 && code <= 0x00f6) || + (code >= 0x00f8 && code <= 0x00fe) ) + *upper -= 0x20; + else if (code == 0x00ff) /* y with diaeresis */ + *upper = 0x0178; + else if (code == 0x00b5) /* micro sign */ + *upper = 0x039c; + return; + } + + /* Latin Extended-A, U+0100 to U+017F */ + if (code >= 0x0100 && code <= 0x017f) { + if ( (code >= 0x0100 && code <= 0x012f) || + (code >= 0x0132 && code <= 0x0137) || + (code >= 0x014a && code <= 0x0177) ) { + *upper = code & ~1; + *lower = code | 1; + } + else if ( (code >= 0x0139 && code <= 0x0148) || + (code >= 0x0179 && code <= 0x017e) ) { + if (code & 1) + *lower += 1; + else + *upper -= 1; + } + else if (code == 0x0130) + *lower = 0x0069; + else if (code == 0x0131) + *upper = 0x0049; + else if (code == 0x0178) + *lower = 0x00ff; + else if (code == 0x017f) + *upper = 0x0053; + return; + } + + /* Latin Extended-B, U+0180 to U+024F */ + if (code >= 0x0180 && code <= 0x024f) { + if (code >= 0x01cd && code <= 0x01dc) { + if (code & 1) + *lower += 1; + else + *upper -= 1; + } + else if ( (code >= 0x01de && code <= 0x01ef) || + (code >= 0x01f4 && code <= 0x01f5) || + (code >= 0x01f8 && code <= 0x021f) || + (code >= 0x0222 && code <= 0x0233) ) { + *lower |= 1; + *upper &= ~1; + } + else if (code >= 0x0180 && code <= 0x01cc) { + *lower = LatinExtB_lower_mapping[code - 0x0180]; + *upper = LatinExtB_upper_mapping[code - 0x0180]; + } + else if (code == 0x01dd) + *upper = 0x018e; + else if (code == 0x01f1 || code == 0x01f2) { + *lower = 0x01f3; + *upper = 0x01f1; + } + else if (code == 0x01f3) + *upper = 0x01f1; + else if (code == 0x01f6) + *lower = 0x0195; + else if (code == 0x01f7) + *lower = 0x01bf; + else if (code == 0x0220) + *lower = 0x019e; + return; + } + + /* IPA Extensions, U+0250 to U+02AF */ + if (code >= 0x0253 && code <= 0x0292) { + *upper = IPAExt_upper_mapping[code - 0x0253]; + } + + /* Combining Diacritical Marks, U+0300 to U+036F */ + if (code == 0x0345) { + *upper = 0x0399; + } + + /* Greek and Coptic, U+0370 to U+03FF */ + if (code >= 0x0370 && code <= 0x03ff) { + *lower = Greek_lower_mapping[code - 0x0370]; + *upper = Greek_upper_mapping[code - 0x0370]; + if (*upper == 0) + *upper = code; + if (*lower == 0) + *lower = code; + } + + /* Cyrillic and Cyrillic Supplementary, U+0400 to U+052F */ + if ( (code >= 0x0400 && code <= 0x04ff) || + (code >= 0x0500 && code <= 0x052f) ) { + if (code >= 0x0400 && code <= 0x040f) + *lower += 0x50; + else if (code >= 0x0410 && code <= 0x042f) + *lower += 0x20; + else if (code >= 0x0430 && code <= 0x044f) + *upper -= 0x20; + else if (code >= 0x0450 && code <= 0x045f) + *upper -= 0x50; + else if ( (code >= 0x0460 && code <= 0x0481) || + (code >= 0x048a && code <= 0x04bf) || + (code >= 0x04d0 && code <= 0x04f5) || + (code >= 0x04f8 && code <= 0x04f9) || + (code >= 0x0500 && code <= 0x050f) ) { + *upper &= ~1; + *lower |= 1; + } + else if (code >= 0x04c1 && code <= 0x04ce) { + if (code & 1) + *lower += 1; + else + *upper -= 1; + } + } + + /* Armenian, U+0530 to U+058F */ + if (code >= 0x0530 && code <= 0x058f) { + if (code >= 0x0531 && code <= 0x0556) + *lower += 0x30; + else if (code >=0x0561 && code <= 0x0586) + *upper -= 0x30; + } + + /* Latin Extended Additional, U+1E00 to U+1EFF */ + if (code >= 0x1e00 && code <= 0x1eff) { + if ( (code >= 0x1e00 && code <= 0x1e95) || + (code >= 0x1ea0 && code <= 0x1ef9) ) { + *upper &= ~1; + *lower |= 1; + } + else if (code == 0x1e9b) + *upper = 0x1e60; + } + + /* Greek Extended, U+1F00 to U+1FFF */ + if (code >= 0x1f00 && code <= 0x1fff) { + *lower = GreekExt_lower_mapping[code - 0x1f00]; + *upper = GreekExt_upper_mapping[code - 0x1f00]; + if (*upper == 0) + *upper = code; + if (*lower == 0) + *lower = code; + } + + /* Letterlike Symbols, U+2100 to U+214F */ + if (code >= 0x2100 && code <= 0x214f) { + switch (code) { + case 0x2126: *lower = 0x03c9; break; + case 0x212a: *lower = 0x006b; break; + case 0x212b: *lower = 0x00e5; break; + } + } + /* Number Forms, U+2150 to U+218F */ + else if (code >= 0x2160 && code <= 0x216f) + *lower += 0x10; + else if (code >= 0x2170 && code <= 0x217f) + *upper -= 0x10; + /* Enclosed Alphanumerics, U+2460 to U+24FF */ + else if (code >= 0x24b6 && code <= 0x24cf) + *lower += 0x1a; + else if (code >= 0x24d0 && code <= 0x24e9) + *upper -= 0x1a; + /* Halfwidth and Fullwidth Forms, U+FF00 to U+FFEF */ + else if (code >= 0xff21 && code <= 0xff3a) + *lower += 0x20; + else if (code >= 0xff41 && code <= 0xff5a) + *upper -= 0x20; + /* Deseret, U+10400 to U+104FF */ + else if (code >= 0x10400 && code <= 0x10427) + *lower += 0x28; + else if (code >= 0x10428 && code <= 0x1044f) + *upper -= 0x28; +} + +void +XConvertCase( + register KeySym sym, + KeySym *lower, + KeySym *upper) +{ + /* Latin 1 keysym */ + if (sym < 0x100) { + UCSConvertCase(sym, lower, upper); + return; + } + + /* Unicode keysym */ + if ((sym & 0xff000000) == 0x01000000) { + UCSConvertCase((sym & 0x00ffffff), lower, upper); + *upper |= 0x01000000; + *lower |= 0x01000000; + return; + } + + /* Legacy keysym */ + + *lower = sym; + *upper = sym; + + switch(sym >> 8) { + case 1: /* Latin 2 */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (sym == XK_Aogonek) + *lower = XK_aogonek; + else if (sym >= XK_Lstroke && sym <= XK_Sacute) + *lower += (XK_lstroke - XK_Lstroke); + else if (sym >= XK_Scaron && sym <= XK_Zacute) + *lower += (XK_scaron - XK_Scaron); + else if (sym >= XK_Zcaron && sym <= XK_Zabovedot) + *lower += (XK_zcaron - XK_Zcaron); + else if (sym == XK_aogonek) + *upper = XK_Aogonek; + else if (sym >= XK_lstroke && sym <= XK_sacute) + *upper -= (XK_lstroke - XK_Lstroke); + else if (sym >= XK_scaron && sym <= XK_zacute) + *upper -= (XK_scaron - XK_Scaron); + else if (sym >= XK_zcaron && sym <= XK_zabovedot) + *upper -= (XK_zcaron - XK_Zcaron); + else if (sym >= XK_Racute && sym <= XK_Tcedilla) + *lower += (XK_racute - XK_Racute); + else if (sym >= XK_racute && sym <= XK_tcedilla) + *upper -= (XK_racute - XK_Racute); + break; + case 2: /* Latin 3 */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (sym >= XK_Hstroke && sym <= XK_Hcircumflex) + *lower += (XK_hstroke - XK_Hstroke); + else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex) + *lower += (XK_gbreve - XK_Gbreve); + else if (sym >= XK_hstroke && sym <= XK_hcircumflex) + *upper -= (XK_hstroke - XK_Hstroke); + else if (sym >= XK_gbreve && sym <= XK_jcircumflex) + *upper -= (XK_gbreve - XK_Gbreve); + else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex) + *lower += (XK_cabovedot - XK_Cabovedot); + else if (sym >= XK_cabovedot && sym <= XK_scircumflex) + *upper -= (XK_cabovedot - XK_Cabovedot); + break; + case 3: /* Latin 4 */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (sym >= XK_Rcedilla && sym <= XK_Tslash) + *lower += (XK_rcedilla - XK_Rcedilla); + else if (sym >= XK_rcedilla && sym <= XK_tslash) + *upper -= (XK_rcedilla - XK_Rcedilla); + else if (sym == XK_ENG) + *lower = XK_eng; + else if (sym == XK_eng) + *upper = XK_ENG; + else if (sym >= XK_Amacron && sym <= XK_Umacron) + *lower += (XK_amacron - XK_Amacron); + else if (sym >= XK_amacron && sym <= XK_umacron) + *upper -= (XK_amacron - XK_Amacron); + break; + case 6: /* Cyrillic */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE) + *lower -= (XK_Serbian_DJE - XK_Serbian_dje); + else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze) + *upper += (XK_Serbian_DJE - XK_Serbian_dje); + else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN) + *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu); + else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign) + *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu); + break; + case 7: /* Greek */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent) + *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent); + else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent && + sym != XK_Greek_iotaaccentdieresis && + sym != XK_Greek_upsilonaccentdieresis) + *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent); + else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA) + *lower += (XK_Greek_alpha - XK_Greek_ALPHA); + else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega && + sym != XK_Greek_finalsmallsigma) + *upper -= (XK_Greek_alpha - XK_Greek_ALPHA); + break; + case 0x13: /* Latin 9 */ + if (sym == XK_OE) + *lower = XK_oe; + else if (sym == XK_oe) + *upper = XK_OE; + else if (sym == XK_Ydiaeresis) + *lower = XK_ydiaeresis; + break; + } +} + +int +_XTranslateKey( register Display *dpy, + KeyCode keycode, + register unsigned int modifiers, + unsigned int *modifiers_return, + KeySym *keysym_return) +{ + int per; + register KeySym *syms; + KeySym sym, lsym, usym; + + if ((! dpy->keysyms) && (! _XKeyInitialize(dpy))) + return 0; + *modifiers_return = ((ShiftMask|LockMask) + | dpy->mode_switch | dpy->num_lock); + if (((int)keycode < dpy->min_keycode) || ((int)keycode > dpy->max_keycode)) + { + *keysym_return = NoSymbol; + return 1; + } + per = dpy->keysyms_per_keycode; + syms = &dpy->keysyms[(keycode - dpy->min_keycode) * per]; + while ((per > 2) && (syms[per - 1] == NoSymbol)) + per--; + if ((per > 2) && (modifiers & dpy->mode_switch)) { + syms += 2; + per -= 2; + } + if ((modifiers & dpy->num_lock) && + (per > 1 && (IsKeypadKey(syms[1]) || IsPrivateKeypadKey(syms[1])))) { + if ((modifiers & ShiftMask) || + ((modifiers & LockMask) && (dpy->lock_meaning == XK_Shift_Lock))) + *keysym_return = syms[0]; + else + *keysym_return = syms[1]; + } else if (!(modifiers & ShiftMask) && + (!(modifiers & LockMask) || (dpy->lock_meaning == NoSymbol))) { + if ((per == 1) || (syms[1] == NoSymbol)) + XConvertCase(syms[0], keysym_return, &usym); + else + *keysym_return = syms[0]; + } else if (!(modifiers & LockMask) || + (dpy->lock_meaning != XK_Caps_Lock)) { + if ((per == 1) || ((usym = syms[1]) == NoSymbol)) + XConvertCase(syms[0], &lsym, &usym); + *keysym_return = usym; + } else { + if ((per == 1) || ((sym = syms[1]) == NoSymbol)) + sym = syms[0]; + XConvertCase(sym, &lsym, &usym); + if (!(modifiers & ShiftMask) && (sym != syms[0]) && + ((sym != usym) || (lsym == usym))) + XConvertCase(syms[0], &lsym, &usym); + *keysym_return = usym; + } + if (*keysym_return == XK_VoidSymbol) + *keysym_return = NoSymbol; + return 1; +} + +int +_XTranslateKeySym( + Display *dpy, + register KeySym symbol, + unsigned int modifiers, + char *buffer, + int nbytes) +{ + register struct _XKeytrans *p; + int length; + unsigned long hiBytes; + register unsigned char c; + + if (!symbol) + return 0; + /* see if symbol rebound, if so, return that string. */ + for (p = dpy->key_bindings; p; p = p->next) { + if (((modifiers & AllMods) == p->state) && (symbol == p->key)) { + length = p->len; + if (length > nbytes) length = nbytes; + memcpy (buffer, p->string, length); + return length; + } + } + /* try to convert to Latin-1, handling control */ + hiBytes = symbol >> 8; + if (!(nbytes && + ((hiBytes == 0) || + ((hiBytes == 0xFF) && + (((symbol >= XK_BackSpace) && (symbol <= XK_Clear)) || + (symbol == XK_Return) || + (symbol == XK_Escape) || + (symbol == XK_KP_Space) || + (symbol == XK_KP_Tab) || + (symbol == XK_KP_Enter) || + ((symbol >= XK_KP_Multiply) && (symbol <= XK_KP_9)) || + (symbol == XK_KP_Equal) || + (symbol == XK_Delete)))))) + return 0; + + /* if X keysym, convert to ascii by grabbing low 7 bits */ + if (symbol == XK_KP_Space) + c = XK_space & 0x7F; /* patch encoding botch */ + else if (hiBytes == 0xFF) + c = symbol & 0x7F; + else + c = symbol & 0xFF; + /* only apply Control key if it makes sense, else ignore it */ + if (modifiers & ControlMask) { + if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F; + else if (c == '2') c = '\000'; + else if (c >= '3' && c <= '7') c -= ('3' - '\033'); + else if (c == '8') c = '\177'; + else if (c == '/') c = '_' & 0x1F; + } + buffer[0] = c; + return 1; +} + +/*ARGSUSED*/ +int +XLookupString ( + register XKeyEvent *event, + char *buffer, /* buffer */ + int nbytes, /* space in buffer for characters */ + KeySym *keysym, + XComposeStatus *status) /* not implemented */ +{ + unsigned int modifiers; + KeySym symbol; + + if (! _XTranslateKey(event->display, event->keycode, event->state, + &modifiers, &symbol)) + return 0; + +#ifdef USE_OWN_COMPOSE + if ( status ) { + static int been_here= 0; + if ( !been_here ) { + XimCompInitTables(); + been_here = 1; + } + if ( !XimCompLegalStatus(status) ) { + status->compose_ptr = NULL; + status->chars_matched = 0; + } + if ( ((status->chars_matched>0)&&(status->compose_ptr!=NULL)) || + XimCompIsComposeKey(symbol,event->keycode,status) ) { + XimCompRtrn rtrn; + switch (XimCompProcessSym(status,symbol,&rtrn)) { + case XIM_COMP_IGNORE: + break; + case XIM_COMP_IN_PROGRESS: + if ( keysym!=NULL ) + *keysym = NoSymbol; + return 0; + case XIM_COMP_FAIL: + { + int n = 0, len= 0; + for (n=len=0;rtrn.sym[n]!=XK_VoidSymbol;n++) { + if ( nbytes-len > 0 ) { + len+= _XTranslateKeySym(event->display,rtrn.sym[n], + event->state, + buffer+len,nbytes-len); + } + } + if ( keysym!=NULL ) { + if ( n==1 ) *keysym = rtrn.sym[0]; + else *keysym = NoSymbol; + } + return len; + } + case XIM_COMP_SUCCEED: + { + int len,n = 0; + + symbol = rtrn.matchSym; + if ( keysym!=NULL ) *keysym = symbol; + if ( rtrn.str[0]!='\0' ) { + strncpy(buffer,rtrn.str,nbytes-1); + buffer[nbytes-1]= '\0'; + len = strlen(buffer); + } + else { + len = _XTranslateKeySym(event->display,symbol, + event->state, + buffer,nbytes); + } + for (n=0;rtrn.sym[n]!=XK_VoidSymbol;n++) { + if ( nbytes-len > 0 ) { + len+= _XTranslateKeySym(event->display,rtrn.sym[n], + event->state, + buffer+len,nbytes-len); + } + } + return len; + } + } + } + } +#endif + + if (keysym) + *keysym = symbol; + /* arguable whether to use (event->state & ~modifiers) here */ + return _XTranslateKeySym(event->display, symbol, event->state, + buffer, nbytes); +} + +static void +_XFreeKeyBindings( + Display *dpy) +{ + register struct _XKeytrans *p, *np; + + for (p = dpy->key_bindings; p; p = np) { + np = p->next; + Xfree(p->string); + Xfree((char *)p->modifiers); + Xfree((char *)p); + } +} + +int +XRebindKeysym ( + Display *dpy, + KeySym keysym, + KeySym *mlist, + int nm, /* number of modifiers in mlist */ + _Xconst unsigned char *str, + int nbytes) +{ + register struct _XKeytrans *tmp, *p; + int nb; + + if ((! dpy->keysyms) && (! _XKeyInitialize(dpy))) + return 0; + LockDisplay(dpy); + tmp = dpy->key_bindings; + nb = sizeof(KeySym) * nm; + + if ((! (p = (struct _XKeytrans *) Xcalloc( 1, sizeof(struct _XKeytrans)))) || + ((! (p->string = (char *) Xmalloc( (unsigned) nbytes))) && + (nbytes > 0)) || + ((! (p->modifiers = (KeySym *) Xmalloc( (unsigned) nb))) && + (nb > 0))) { + if (p) { + if (p->string) Xfree(p->string); + if (p->modifiers) Xfree((char *) p->modifiers); + Xfree((char *) p); + } + UnlockDisplay(dpy); + return 0; + } + + dpy->key_bindings = p; + dpy->free_funcs->key_bindings = _XFreeKeyBindings; + p->next = tmp; /* chain onto list */ + memcpy (p->string, (char *) str, nbytes); + p->len = nbytes; + memcpy ((char *) p->modifiers, (char *) mlist, nb); + p->key = keysym; + p->mlen = nm; + ComputeMaskFromKeytrans(dpy, p); + UnlockDisplay(dpy); + return 0; +} + +unsigned +_XKeysymToModifiers( + Display *dpy, + KeySym ks) +{ + CARD8 code,mods; + register KeySym *kmax; + register KeySym *k; + register XModifierKeymap *m; + + if ((! dpy->keysyms) && (! _XKeyInitialize(dpy))) + return 0; + kmax = dpy->keysyms + + (dpy->max_keycode - dpy->min_keycode + 1) * dpy->keysyms_per_keycode; + k = dpy->keysyms; + m = dpy->modifiermap; + mods= 0; + while (k<kmax) { + if (*k == ks ) { + register int j = m->max_keypermod<<3; + + code=(((k-dpy->keysyms)/dpy->keysyms_per_keycode)+dpy->min_keycode); + + while (--j >= 0) { + if (code == m->modifiermap[j]) + mods|= (1<<(j/m->max_keypermod)); + } + } + k++; + } + return mods; +} + +/* + * given a list of modifiers, computes the mask necessary for later matching. + * This routine must lookup the key in the Keymap and then search to see + * what modifier it is bound to, if any. Sets the AnyModifier bit if it + * can't map some keysym to a modifier. + */ +static void +ComputeMaskFromKeytrans( + Display *dpy, + register struct _XKeytrans *p) +{ + register int i; + + p->state = AnyModifier; + for (i = 0; i < p->mlen; i++) { + p->state|= XkbKeysymToModifiers(dpy,p->modifiers[i]); + } + p->state &= AllMods; +} diff --git a/libX11/src/Makefile.am b/libX11/src/Makefile.am index ecf4a99aa..71e02e71b 100644 --- a/libX11/src/Makefile.am +++ b/libX11/src/Makefile.am @@ -1,425 +1,425 @@ -if XKB
-XKB_SUBDIRS = xkb
-endif
-SUBDIRS = util xcms xlibi18n $(XKB_SUBDIRS)
-
-lib_LTLIBRARIES = libX11.la libX11-xcb.la
-
-BUILT_SOURCES=ks_tables.h
-CLEANFILES=ks_tables.h ks_tables_h
-
-AM_CPPFLAGS= \
- -I$(top_srcdir)/include \
- -I$(top_srcdir)/include/X11 \
- -I$(top_builddir)/include \
- -I$(top_builddir)/include/X11 \
- -I$(top_srcdir)/src/xcms \
- -I$(top_srcdir)/src/xkb \
- -I$(top_srcdir)/src/xlibi18n \
- -D_BSD_SOURCE -DX11_t -DTRANS_CLIENT
-
-AM_CFLAGS= \
- $(X11_CFLAGS) \
- $(BIGFONT_CFLAGS) \
- $(XMALLOC_ZERO_CFLAGS) \
- $(CWARNFLAGS)
-
-#
-# =============================== I18N =============================
-#
-
-I18N_LIBS = \
- xlibi18n/libi18n.la
-
-#
-# =============================== XCMS =============================
-#
-
-XCMS_LIBS = \
- xcms/libxcms.la
-
-#
-# =============================== XKB ==============================
-#
-
-XKB_LIBS = \
- xkb/libxkb.la
-
-#
-# =============================== XLIB =============================
-#
-
-libX11_la_SOURCES = \
- AllCells.c \
- AllowEv.c \
- AllPlanes.c \
- AutoRep.c \
- Backgnd.c \
- BdrWidth.c \
- Bell.c \
- Border.c \
- ChAccCon.c \
- ChActPGb.c \
- ChClMode.c \
- ChCmap.c \
- ChGC.c \
- ChKeyCon.c \
- ChkIfEv.c \
- ChkMaskEv.c \
- ChkTypEv.c \
- ChkTypWEv.c \
- ChkWinEv.c \
- ChPntCon.c \
- ChProp.c \
- ChSaveSet.c \
- ChWAttrs.c \
- ChWindow.c \
- CirWin.c \
- CirWinDn.c \
- CirWinUp.c \
- ClDisplay.c \
- ClearArea.c \
- Clear.c \
- Cmap.h \
- ConfWind.c \
- Context.c \
- ConvSel.c \
- CopyArea.c \
- CopyCmap.c \
- CopyGC.c \
- CopyPlane.c \
- CrBFData.c \
- CrCmap.c \
- CrCursor.c \
- CrGC.c \
- CrGlCur.c \
- Cr.h \
- CrPFBData.c \
- CrPixmap.c \
- CrWindow.c \
- Cursor.c \
- DefCursor.c \
- DelProp.c \
- Depths.c \
- DestSubs.c \
- DestWind.c \
- DisName.c \
- DrArc.c \
- DrArcs.c \
- DrLine.c \
- DrLines.c \
- DrPoint.c \
- DrPoints.c \
- DrRect.c \
- DrRects.c \
- DrSegs.c \
- ErrDes.c \
- ErrHndlr.c \
- evtomask.c \
- EvToWire.c \
- FetchName.c \
- FillArc.c \
- FillArcs.c \
- FillPoly.c \
- FillRct.c \
- FillRcts.c \
- FilterEv.c \
- Flush.c \
- Font.c \
- FontInfo.c \
- FontNames.c \
- FreeCmap.c \
- FreeCols.c \
- FreeCurs.c \
- FreeEData.c \
- FreeEventData.c \
- FreeGC.c \
- FreePix.c \
- FSSaver.c \
- FSWrap.c \
- GCMisc.c \
- Geom.c \
- GetAtomNm.c \
- GetColor.c \
- GetDflt.c \
- GetEventData.c \
- GetFPath.c \
- GetFProp.c \
- GetGCVals.c \
- GetGeom.c \
- GetHColor.c \
- GetHints.c \
- GetIFocus.c \
- GetImage.c \
- GetKCnt.c \
- GetMoEv.c \
- GetNrmHint.c \
- GetPCnt.c \
- GetPntMap.c \
- GetProp.c \
- GetRGBCMap.c \
- GetSOwner.c \
- GetSSaver.c \
- GetStCmap.c \
- GetTxtProp.c \
- GetWAttrs.c \
- GetWMCMapW.c \
- GetWMProto.c \
- globals.c \
- GrButton.c \
- GrKeybd.c \
- GrKey.c \
- GrPointer.c \
- GrServer.c \
- Host.c \
- Iconify.c \
- IfEvent.c \
- imConv.c \
- ImText16.c \
- ImText.c \
- ImUtil.c \
- InitExt.c \
- InsCmap.c \
- IntAtom.c \
- KeyBind.c \
- Key.h \
- KeysymStr.c \
- KillCl.c \
- LiHosts.c \
- LiICmaps.c \
- LiProps.c \
- ListExt.c \
- LoadFont.c \
- LockDis.c \
- locking.c \
- locking.h \
- LookupCol.c \
- LowerWin.c \
- Macros.c \
- MapRaised.c \
- MapSubs.c \
- MapWindow.c \
- MaskEvent.c \
- Misc.c \
- ModMap.c \
- MoveWin.c \
- NextEvent.c \
- OCWrap.c \
- OMWrap.c \
- OpenDis.c \
- ParseCmd.c \
- ParseCol.c \
- ParseGeom.c \
- PeekEvent.c \
- PeekIfEv.c \
- Pending.c \
- PixFormats.c \
- PmapBgnd.c \
- PmapBord.c \
- poly.h \
- PolyReg.c \
- PolyTxt16.c \
- PolyTxt.c \
- PropAlloc.c \
- PutBEvent.c \
- PutImage.c \
- Quarks.c \
- QuBest.c \
- QuColor.c \
- QuColors.c \
- QuCurShp.c \
- QuExt.c \
- QuKeybd.c \
- QuPntr.c \
- QuStipShp.c \
- QuTextE16.c \
- QuTextExt.c \
- QuTileShp.c \
- QuTree.c \
- RaiseWin.c \
- RdBitF.c \
- RecolorC.c \
- ReconfWin.c \
- ReconfWM.c \
- Region.c \
- RegstFlt.c \
- RepWindow.c \
- RestackWs.c \
- RotProp.c \
- ScrResStr.c \
- SelInput.c \
- SendEvent.c \
- SetBack.c \
- SetClMask.c \
- SetClOrig.c \
- SetCRects.c \
- SetDashes.c \
- SetFont.c \
- SetFore.c \
- SetFPath.c \
- SetFunc.c \
- SetHints.c \
- SetIFocus.c \
- SetLocale.c \
- SetLStyle.c \
- SetNrmHint.c \
- SetPMask.c \
- SetPntMap.c \
- SetRGBCMap.c \
- SetSOwner.c \
- SetSSaver.c \
- SetState.c \
- SetStCmap.c \
- SetStip.c \
- SetTile.c \
- SetTSOrig.c \
- SetTxtProp.c \
- SetWMCMapW.c \
- SetWMProto.c \
- StBytes.c \
- StColor.c \
- StColors.c \
- StName.c \
- StNColor.c \
- StrKeysym.c \
- StrToText.c \
- Sync.c \
- Synchro.c \
- Text16.c \
- Text.c \
- TextExt16.c \
- TextExt.c \
- TextToStr.c \
- TrCoords.c \
- UndefCurs.c \
- UngrabBut.c \
- UngrabKbd.c \
- UngrabKey.c \
- UngrabPtr.c \
- UngrabSvr.c \
- UninsCmap.c \
- UnldFont.c \
- UnmapSubs.c \
- UnmapWin.c \
- utlist.h \
- VisUtil.c \
- WarpPtr.c \
- Window.c \
- WinEvent.c \
- Withdraw.c \
- WMGeom.c \
- WMProps.c \
- WrBitF.c \
- Xatomtype.h \
- xcb_disp.c \
- xcb_io.c \
- Xintatom.h \
- Xintconn.h \
- XlibAsync.c \
- XlibInt.c \
- Xprivate.h \
- XomGeneric.h \
- Xresinternal.h \
- Xrm.c \
- Xxcbint.h
-
-#
-# ========================= Extra stuff ============================
-#
-
-if OS2
-libX11_la_SOURCES+=os2Stubs.c
-endif OS2
-
-if UDC
-libX11_la_SOURCES+=udcInf.c
-endif
-
-if THRSTUBS
-libX11_la_SOURCES+=UIThrStubs.c
-endif
-
-x11datadir = @X11_DATADIR@
-x11data_DATA = XErrorDB
-
-EXTRA_DIST = \
- $(x11data_DATA) \
- os2Stubs.c \
- udcInf.c \
- UIThrStubs.c
-
-libX11_xcb_la_SOURCES = x11_xcb.c Xxcbint.h
-libX11_xcb_la_LDFLAGS = -version-number 1:0:0 -no-undefined
-libX11_xcb_la_LIBADD = libX11.la
-
-#
-# Figure out which sub-libraries to link into Xlib
-#
-
-if XLOCALE
-USE_I18N_LIBS = $(I18N_LIBS)
-endif
-
-if XCMS
-USE_XCMS_LIBS = $(XCMS_LIBS)
-endif
-
-if XKB
-USE_XKB_LIBS = $(XKB_LIBS)
-endif
-
-libX11_la_LDFLAGS = -version-number 6:3:0 -no-undefined
-
-libX11_la_LIBADD = \
- $(USE_I18N_LIBS) \
- $(USE_XCMS_LIBS) \
- $(USE_XKB_LIBS) \
- $(X11_LIBS)
-
-preprocess: $(patsubst %.c,%.ii,$(libX11_la_SOURCES))
-.c.ii:
- $(COMPILE) -E -o $@ `test -f '$<' || echo '$(srcdir)/'`$<
-
-if LINT
-# Check source code with tools like lint & sparse
-
-ALL_LINT_FLAGS=$(LINT_FLAGS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
- $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS)
-
-lint: $(BUILT_SOURCES)
- for f in $(libX11_la_SOURCES) ; do \
- $(LINT) $(ALL_LINT_FLAGS) $$f ; \
- done
- @for subdir in $(SUBDIRS) ; do \
- echo "Making $@ in src/$$subdir"; \
- (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) lint) ; \
- done
-endif LINT
-
-if MAKE_LINT_LIB
-lintlibdir = $(libdir)
-
-lintlib_DATA = $(LINTLIB)
-
-lintlib_src = $(libX11_la_SOURCES) xcms/*.c xkb/*.c
-
-CLEANFILES += $(lintlib_DATA)
-
-$(LINTLIB): $(libX11_la_SOURCES)
- $(AM_V_GEN)$(LINT) -y -oX11 -x $(ALL_LINT_FLAGS) $(lintlib_src)
-endif MAKE_LINT_LIB
-
-#
-# Building ks_tables.h requires the makekeys utility
-#
-
-KEYSYMDEFS=@KEYSYMDEFS@
-
-ks_tables.h: $(KEYSYMDEFS) $(top_builddir)/src/util/makekeys$(EXEEXT)
- $(top_builddir)/src/util/makekeys $(KEYSYMDEFS) > ks_tables_h
- mv ks_tables_h $@
-
-$(top_builddir)/src/util/makekeys$(EXEEXT): force
- cd util && $(MAKE)
-
-force:
+if XKB +XKB_SUBDIRS = xkb +endif +SUBDIRS = util xcms xlibi18n $(XKB_SUBDIRS) + +lib_LTLIBRARIES = libX11.la libX11-xcb.la + +BUILT_SOURCES=ks_tables.h +CLEANFILES=ks_tables.h ks_tables_h + +AM_CPPFLAGS= \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/include/X11 \ + -I$(top_builddir)/include \ + -I$(top_builddir)/include/X11 \ + -I$(top_srcdir)/src/xcms \ + -I$(top_srcdir)/src/xkb \ + -I$(top_srcdir)/src/xlibi18n \ + -D_BSD_SOURCE -DX11_t -DTRANS_CLIENT + +AM_CFLAGS= \ + $(X11_CFLAGS) \ + $(BIGFONT_CFLAGS) \ + $(XMALLOC_ZERO_CFLAGS) \ + $(CWARNFLAGS) + +# +# =============================== I18N ============================= +# + +I18N_LIBS = \ + xlibi18n/libi18n.la + +# +# =============================== XCMS ============================= +# + +XCMS_LIBS = \ + xcms/libxcms.la + +# +# =============================== XKB ============================== +# + +XKB_LIBS = \ + xkb/libxkb.la + +# +# =============================== XLIB ============================= +# + +libX11_la_SOURCES = \ + AllCells.c \ + AllowEv.c \ + AllPlanes.c \ + AutoRep.c \ + Backgnd.c \ + BdrWidth.c \ + Bell.c \ + Border.c \ + ChAccCon.c \ + ChActPGb.c \ + ChClMode.c \ + ChCmap.c \ + ChGC.c \ + ChKeyCon.c \ + ChkIfEv.c \ + ChkMaskEv.c \ + ChkTypEv.c \ + ChkTypWEv.c \ + ChkWinEv.c \ + ChPntCon.c \ + ChProp.c \ + ChSaveSet.c \ + ChWAttrs.c \ + ChWindow.c \ + CirWin.c \ + CirWinDn.c \ + CirWinUp.c \ + ClDisplay.c \ + ClearArea.c \ + Clear.c \ + Cmap.h \ + ConfWind.c \ + Context.c \ + ConvSel.c \ + CopyArea.c \ + CopyCmap.c \ + CopyGC.c \ + CopyPlane.c \ + CrBFData.c \ + CrCmap.c \ + CrCursor.c \ + CrGC.c \ + CrGlCur.c \ + Cr.h \ + CrPFBData.c \ + CrPixmap.c \ + CrWindow.c \ + Cursor.c \ + DefCursor.c \ + DelProp.c \ + Depths.c \ + DestSubs.c \ + DestWind.c \ + DisName.c \ + DrArc.c \ + DrArcs.c \ + DrLine.c \ + DrLines.c \ + DrPoint.c \ + DrPoints.c \ + DrRect.c \ + DrRects.c \ + DrSegs.c \ + ErrDes.c \ + ErrHndlr.c \ + evtomask.c \ + EvToWire.c \ + FetchName.c \ + FillArc.c \ + FillArcs.c \ + FillPoly.c \ + FillRct.c \ + FillRcts.c \ + FilterEv.c \ + Flush.c \ + Font.c \ + FontInfo.c \ + FontNames.c \ + FreeCmap.c \ + FreeCols.c \ + FreeCurs.c \ + FreeEData.c \ + FreeEventData.c \ + FreeGC.c \ + FreePix.c \ + FSSaver.c \ + FSWrap.c \ + GCMisc.c \ + Geom.c \ + GetAtomNm.c \ + GetColor.c \ + GetDflt.c \ + GetEventData.c \ + GetFPath.c \ + GetFProp.c \ + GetGCVals.c \ + GetGeom.c \ + GetHColor.c \ + GetHints.c \ + GetIFocus.c \ + GetImage.c \ + GetKCnt.c \ + GetMoEv.c \ + GetNrmHint.c \ + GetPCnt.c \ + GetPntMap.c \ + GetProp.c \ + GetRGBCMap.c \ + GetSOwner.c \ + GetSSaver.c \ + GetStCmap.c \ + GetTxtProp.c \ + GetWAttrs.c \ + GetWMCMapW.c \ + GetWMProto.c \ + globals.c \ + GrButton.c \ + GrKeybd.c \ + GrKey.c \ + GrPointer.c \ + GrServer.c \ + Host.c \ + Iconify.c \ + IfEvent.c \ + imConv.c \ + ImText16.c \ + ImText.c \ + ImUtil.c \ + InitExt.c \ + InsCmap.c \ + IntAtom.c \ + KeyBind.c \ + Key.h \ + KeysymStr.c \ + KillCl.c \ + LiHosts.c \ + LiICmaps.c \ + LiProps.c \ + ListExt.c \ + LoadFont.c \ + LockDis.c \ + locking.c \ + locking.h \ + LookupCol.c \ + LowerWin.c \ + Macros.c \ + MapRaised.c \ + MapSubs.c \ + MapWindow.c \ + MaskEvent.c \ + Misc.c \ + ModMap.c \ + MoveWin.c \ + NextEvent.c \ + OCWrap.c \ + OMWrap.c \ + OpenDis.c \ + ParseCmd.c \ + ParseCol.c \ + ParseGeom.c \ + PeekEvent.c \ + PeekIfEv.c \ + Pending.c \ + PixFormats.c \ + PmapBgnd.c \ + PmapBord.c \ + poly.h \ + PolyReg.c \ + PolyTxt16.c \ + PolyTxt.c \ + PropAlloc.c \ + PutBEvent.c \ + PutImage.c \ + Quarks.c \ + QuBest.c \ + QuColor.c \ + QuColors.c \ + QuCurShp.c \ + QuExt.c \ + QuKeybd.c \ + QuPntr.c \ + QuStipShp.c \ + QuTextE16.c \ + QuTextExt.c \ + QuTileShp.c \ + QuTree.c \ + RaiseWin.c \ + RdBitF.c \ + RecolorC.c \ + ReconfWin.c \ + ReconfWM.c \ + Region.c \ + RegstFlt.c \ + RepWindow.c \ + RestackWs.c \ + RotProp.c \ + ScrResStr.c \ + SelInput.c \ + SendEvent.c \ + SetBack.c \ + SetClMask.c \ + SetClOrig.c \ + SetCRects.c \ + SetDashes.c \ + SetFont.c \ + SetFore.c \ + SetFPath.c \ + SetFunc.c \ + SetHints.c \ + SetIFocus.c \ + SetLocale.c \ + SetLStyle.c \ + SetNrmHint.c \ + SetPMask.c \ + SetPntMap.c \ + SetRGBCMap.c \ + SetSOwner.c \ + SetSSaver.c \ + SetState.c \ + SetStCmap.c \ + SetStip.c \ + SetTile.c \ + SetTSOrig.c \ + SetTxtProp.c \ + SetWMCMapW.c \ + SetWMProto.c \ + StBytes.c \ + StColor.c \ + StColors.c \ + StName.c \ + StNColor.c \ + StrKeysym.c \ + StrToText.c \ + Sync.c \ + Synchro.c \ + Text16.c \ + Text.c \ + TextExt16.c \ + TextExt.c \ + TextToStr.c \ + TrCoords.c \ + UndefCurs.c \ + UngrabBut.c \ + UngrabKbd.c \ + UngrabKey.c \ + UngrabPtr.c \ + UngrabSvr.c \ + UninsCmap.c \ + UnldFont.c \ + UnmapSubs.c \ + UnmapWin.c \ + utlist.h \ + VisUtil.c \ + WarpPtr.c \ + Window.c \ + WinEvent.c \ + Withdraw.c \ + WMGeom.c \ + WMProps.c \ + WrBitF.c \ + Xatomtype.h \ + xcb_disp.c \ + xcb_io.c \ + Xintatom.h \ + Xintconn.h \ + XlibAsync.c \ + XlibInt.c \ + Xprivate.h \ + XomGeneric.h \ + Xresinternal.h \ + Xrm.c \ + Xxcbint.h + +# +# ========================= Extra stuff ============================ +# + +if OS2 +libX11_la_SOURCES+=os2Stubs.c +endif OS2 + +if UDC +libX11_la_SOURCES+=udcInf.c +endif + +if THRSTUBS +libX11_la_SOURCES+=UIThrStubs.c +endif + +x11datadir = @X11_DATADIR@ +x11data_DATA = XErrorDB + +EXTRA_DIST = \ + $(x11data_DATA) \ + os2Stubs.c \ + udcInf.c \ + UIThrStubs.c + +libX11_xcb_la_SOURCES = x11_xcb.c Xxcbint.h +libX11_xcb_la_LDFLAGS = -version-number 1:0:0 -no-undefined +libX11_xcb_la_LIBADD = libX11.la + +# +# Figure out which sub-libraries to link into Xlib +# + +if XLOCALE +USE_I18N_LIBS = $(I18N_LIBS) +endif + +if XCMS +USE_XCMS_LIBS = $(XCMS_LIBS) +endif + +if XKB +USE_XKB_LIBS = $(XKB_LIBS) +endif + +libX11_la_LDFLAGS = -version-number 6:3:0 -no-undefined + +libX11_la_LIBADD = \ + $(USE_I18N_LIBS) \ + $(USE_XCMS_LIBS) \ + $(USE_XKB_LIBS) \ + $(X11_LIBS) + +preprocess: $(patsubst %.c,%.ii,$(libX11_la_SOURCES)) +.c.ii: + $(COMPILE) -E -o $@ `test -f '$<' || echo '$(srcdir)/'`$< + +if LINT +# Check source code with tools like lint & sparse + +ALL_LINT_FLAGS=$(LINT_FLAGS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) + +lint: $(BUILT_SOURCES) + for f in $(libX11_la_SOURCES) ; do \ + $(LINT) $(ALL_LINT_FLAGS) $$f ; \ + done + @for subdir in $(SUBDIRS) ; do \ + echo "Making $@ in src/$$subdir"; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) lint) ; \ + done +endif LINT + +if MAKE_LINT_LIB +lintlibdir = $(libdir) + +lintlib_DATA = $(LINTLIB) + +lintlib_src = $(libX11_la_SOURCES) xcms/*.c xkb/*.c + +CLEANFILES += $(lintlib_DATA) + +$(LINTLIB): $(libX11_la_SOURCES) + $(AM_V_GEN)$(LINT) -y -oX11 -x $(ALL_LINT_FLAGS) $(lintlib_src) +endif MAKE_LINT_LIB + +# +# Building ks_tables.h requires the makekeys utility +# + +KEYSYMDEFS=@KEYSYMDEFS@ + +ks_tables.h: $(KEYSYMDEFS) $(top_builddir)/src/util/makekeys$(EXEEXT) + $(top_builddir)/src/util/makekeys $(KEYSYMDEFS) > ks_tables_h + mv ks_tables_h $@ + +$(top_builddir)/src/util/makekeys$(EXEEXT): force + cd util && $(MAKE) + +force: diff --git a/libX11/src/Quarks.c b/libX11/src/Quarks.c index aa64392f6..7a704b101 100644 --- a/libX11/src/Quarks.c +++ b/libX11/src/Quarks.c @@ -1,413 +1,413 @@ -
-/***********************************************************
-Copyright 1987, 1988, 1990 by Digital Equipment Corporation, Maynard,
-
- All Rights Reserved
-
-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 Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL 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 TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-******************************************************************/
-/*
-
-Copyright 1987, 1988, 1990, 1998 The Open Group
-
-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.
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall
-not be used in advertising or otherwise to promote the sale, use or
-other dealings in this Software without prior written authorization
-from The Open Group.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include "Xlibint.h"
-#include <X11/Xresource.h>
-#include "Xresinternal.h"
-
-/* Not cost effective, at least for vanilla MIT clients */
-/* #define PERMQ */
-
-#ifdef PERMQ
-typedef unsigned char Bits;
-#endif
-typedef unsigned long Entry; /* dont confuse with EntryRec from Xintatom.h */
-
-static XrmQuark nextQuark = 1; /* next available quark number */
-static unsigned long quarkMask = 0;
-static Entry zero = 0;
-static Entry *quarkTable = &zero; /* crock */
-static unsigned long quarkRehash;
-static XrmString **stringTable = NULL;
-#ifdef PERMQ
-static Bits **permTable = NULL;
-#endif
-static XrmQuark nextUniq = -1; /* next quark from XrmUniqueQuark */
-
-#define QUANTUMSHIFT 8
-#define QUANTUMMASK ((1 << QUANTUMSHIFT) - 1)
-#define CHUNKPER 8
-#define CHUNKMASK ((CHUNKPER << QUANTUMSHIFT) - 1)
-
-#define LARGEQUARK ((Entry)0x80000000L)
-#define QUARKSHIFT 18
-#define QUARKMASK ((LARGEQUARK - 1) >> QUARKSHIFT)
-#define XSIGMASK ((1L << QUARKSHIFT) - 1)
-
-#define STRQUANTSIZE (sizeof(XrmString) * (QUANTUMMASK + 1))
-#ifdef PERMQ
-#define QUANTSIZE (STRQUANTSIZE + \
- (sizeof(Bits) * ((QUANTUMMASK + 1) >> 3))
-#else
-#define QUANTSIZE STRQUANTSIZE
-#endif
-
-#define HASH(sig) ((sig) & quarkMask)
-#define REHASHVAL(sig) ((((sig) % quarkRehash) + 2) | 1)
-#define REHASH(idx,rehash) ((idx + rehash) & quarkMask)
-#define NAME(q) stringTable[(q) >> QUANTUMSHIFT][(q) & QUANTUMMASK]
-#ifdef PERMQ
-#define BYTEREF(q) permTable[(q) >> QUANTUMSHIFT][((q) & QUANTUMMASK) >> 3]
-#define ISPERM(q) (BYTEREF(q) & (1 << ((q) & 7)))
-#define SETPERM(q) BYTEREF(q) |= (1 << ((q) & 7))
-#define CLEARPERM(q) BYTEREF(q) &= ~(1 << ((q) & 7))
-#endif
-
-/* Permanent memory allocation */
-
-#define WALIGN sizeof(unsigned long)
-#define DALIGN sizeof(double)
-
-#define NEVERFREETABLESIZE ((8192-12) & ~(DALIGN-1))
-static char *neverFreeTable = NULL;
-static int neverFreeTableSize = 0;
-
-static char *permalloc(unsigned int length)
-{
- char *ret;
-
- if (neverFreeTableSize < length) {
- if (length >= NEVERFREETABLESIZE)
- return Xmalloc(length);
- if (! (ret = Xmalloc(NEVERFREETABLESIZE)))
- return (char *) NULL;
- neverFreeTableSize = NEVERFREETABLESIZE;
- neverFreeTable = ret;
- }
- ret = neverFreeTable;
- neverFreeTable += length;
- neverFreeTableSize -= length;
- return(ret);
-}
-
-#ifndef WORD64
-typedef struct {char a; double b;} TestType1;
-typedef struct {char a; unsigned long b;} TestType2;
-#endif
-
-#ifdef XTHREADS
-static char *_Xpermalloc(unsigned int length);
-
-char *Xpermalloc(unsigned int length)
-{
- char *p;
-
- _XLockMutex(_Xglobal_lock);
- p = _Xpermalloc(length);
- _XUnlockMutex(_Xglobal_lock);
- return p;
-}
-#define Xpermalloc _Xpermalloc
-
-static
-#endif /* XTHREADS */
-char *Xpermalloc(unsigned int length)
-{
- int i;
-
- if (neverFreeTableSize && length < NEVERFREETABLESIZE) {
-#ifndef WORD64
- if ((sizeof(TestType1) !=
- (sizeof(TestType2) - sizeof(unsigned long) + sizeof(double))) &&
- !(length & (DALIGN-1)) &&
- ((i = (NEVERFREETABLESIZE - neverFreeTableSize) & (DALIGN-1)))) {
- neverFreeTableSize -= DALIGN - i;
- neverFreeTable += DALIGN - i;
- } else
-#endif
- if ((i = (NEVERFREETABLESIZE - neverFreeTableSize) & (WALIGN-1))) {
- neverFreeTableSize -= WALIGN - i;
- neverFreeTable += WALIGN - i;
- }
- }
- return permalloc(length);
-}
-
-static Bool
-ExpandQuarkTable(void)
-{
- unsigned long oldmask, newmask;
- register char c, *s;
- register Entry *oldentries, *entries;
- register Entry entry;
- register int oldidx, newidx, rehash;
- Signature sig;
- XrmQuark q;
-
- oldentries = quarkTable;
- if ((oldmask = quarkMask))
- newmask = (oldmask << 1) + 1;
- else {
- if (!stringTable) {
- stringTable = (XrmString **)Xmalloc(sizeof(XrmString *) *
- CHUNKPER);
- if (!stringTable)
- return False;
- stringTable[0] = (XrmString *)NULL;
- }
-#ifdef PERMQ
- if (!permTable)
- permTable = (Bits **)Xmalloc(sizeof(Bits *) * CHUNKPER);
- if (!permTable)
- return False;
-#endif
- stringTable[0] = (XrmString *)Xpermalloc(QUANTSIZE);
- if (!stringTable[0])
- return False;
-#ifdef PERMQ
- permTable[0] = (Bits *)((char *)stringTable[0] + STRQUANTSIZE);
-#endif
- newmask = 0x1ff;
- }
- entries = Xcalloc(newmask + 1, sizeof(Entry));
- if (!entries)
- return False;
- quarkTable = entries;
- quarkMask = newmask;
- quarkRehash = quarkMask - 2;
- for (oldidx = 0; oldidx <= oldmask; oldidx++) {
- if ((entry = oldentries[oldidx])) {
- if (entry & LARGEQUARK)
- q = entry & (LARGEQUARK-1);
- else
- q = (entry >> QUARKSHIFT) & QUARKMASK;
- for (sig = 0, s = NAME(q); (c = *s++); )
- sig = (sig << 1) + c;
- newidx = HASH(sig);
- if (entries[newidx]) {
- rehash = REHASHVAL(sig);
- do {
- newidx = REHASH(newidx, rehash);
- } while (entries[newidx]);
- }
- entries[newidx] = entry;
- }
- }
- if (oldmask)
- Xfree((char *)oldentries);
- return True;
-}
-
-XrmQuark
-_XrmInternalStringToQuark(
- register _Xconst char *name, register int len, register Signature sig,
- Bool permstring)
-{
- register XrmQuark q;
- register Entry entry;
- register int idx, rehash;
- register int i;
- register char *s1, *s2;
- char *new;
-
- rehash = 0;
- idx = HASH(sig);
- _XLockMutex(_Xglobal_lock);
- while ((entry = quarkTable[idx])) {
- if (entry & LARGEQUARK)
- q = entry & (LARGEQUARK-1);
- else {
- if ((entry - sig) & XSIGMASK)
- goto nomatch;
- q = (entry >> QUARKSHIFT) & QUARKMASK;
- }
- for (i = len, s1 = (char *)name, s2 = NAME(q); --i >= 0; ) {
- if (*s1++ != *s2++)
- goto nomatch;
- }
- if (*s2) {
-nomatch: if (!rehash)
- rehash = REHASHVAL(sig);
- idx = REHASH(idx, rehash);
- continue;
- }
-#ifdef PERMQ
- if (permstring && !ISPERM(q)) {
- Xfree(NAME(q));
- NAME(q) = (char *)name;
- SETPERM(q);
- }
-#endif
- _XUnlockMutex(_Xglobal_lock);
- return q;
- }
- if (nextUniq == nextQuark)
- goto fail;
- if ((nextQuark + (nextQuark >> 2)) > quarkMask) {
- if (!ExpandQuarkTable())
- goto fail;
- _XUnlockMutex(_Xglobal_lock);
- return _XrmInternalStringToQuark(name, len, sig, permstring);
- }
- q = nextQuark;
- if (!(q & QUANTUMMASK)) {
- if (!(q & CHUNKMASK)) {
- if (!(new = Xrealloc((char *)stringTable,
- sizeof(XrmString *) *
- ((q >> QUANTUMSHIFT) + CHUNKPER))))
- goto fail;
- stringTable = (XrmString **)new;
-#ifdef PERMQ
- if (!(new = Xrealloc((char *)permTable,
- sizeof(Bits *) *
- ((q >> QUANTUMSHIFT) + CHUNKPER))))
- goto fail;
- permTable = (Bits **)new;
-#endif
- }
- new = Xpermalloc(QUANTSIZE);
- if (!new)
- goto fail;
- stringTable[q >> QUANTUMSHIFT] = (XrmString *)new;
-#ifdef PERMQ
- permTable[q >> QUANTUMSHIFT] = (Bits *)(new + STRQUANTSIZE);
-#endif
- }
- if (!permstring) {
- s2 = (char *)name;
-#ifdef PERMQ
- name = Xmalloc(len+1);
-#else
- name = permalloc(len+1);
-#endif
- if (!name)
- goto fail;
- for (i = len, s1 = (char *)name; --i >= 0; )
- *s1++ = *s2++;
- *s1++ = '\0';
-#ifdef PERMQ
- CLEARPERM(q);
- }
- else {
- SETPERM(q);
-#endif
- }
- NAME(q) = (char *)name;
- if (q <= QUARKMASK)
- entry = (q << QUARKSHIFT) | (sig & XSIGMASK);
- else
- entry = q | LARGEQUARK;
- quarkTable[idx] = entry;
- nextQuark++;
- _XUnlockMutex(_Xglobal_lock);
- return q;
- fail:
- _XUnlockMutex(_Xglobal_lock);
- return NULLQUARK;
-}
-
-XrmQuark
-XrmStringToQuark(
- _Xconst char *name)
-{
- register char c, *tname;
- register Signature sig = 0;
-
- if (!name)
- return (NULLQUARK);
-
- for (tname = (char *)name; (c = *tname++); )
- sig = (sig << 1) + c;
-
- return _XrmInternalStringToQuark(name, tname-(char *)name-1, sig, False);
-}
-
-XrmQuark
-XrmPermStringToQuark(
- _Xconst char *name)
-{
- register char c, *tname;
- register Signature sig = 0;
-
- if (!name)
- return (NULLQUARK);
-
- for (tname = (char *)name; (c = *tname++); )
- sig = (sig << 1) + c;
-
- return _XrmInternalStringToQuark(name, tname-(char *)name-1, sig, True);
-}
-
-XrmQuark XrmUniqueQuark(void)
-{
- XrmQuark q;
-
- _XLockMutex(_Xglobal_lock);
- if (nextUniq == nextQuark)
- q = NULLQUARK;
- else
- q = nextUniq--;
- _XUnlockMutex(_Xglobal_lock);
- return q;
-}
-
-XrmString XrmQuarkToString(register XrmQuark quark)
-{
- XrmString s;
-
- _XLockMutex(_Xglobal_lock);
- if (quark <= 0 || quark >= nextQuark)
- s = NULLSTRING;
- else {
-#ifdef PERMQ
- /* We have to mark the quark as permanent, since the caller might hold
- * onto the string pointer forver.
- */
- SETPERM(quark);
-#endif
- s = NAME(quark);
- }
- _XUnlockMutex(_Xglobal_lock);
- return s;
-}
+ +/*********************************************************** +Copyright 1987, 1988, 1990 by Digital Equipment Corporation, Maynard, + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* + +Copyright 1987, 1988, 1990, 1998 The Open Group + +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. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include "Xlibint.h" +#include <X11/Xresource.h> +#include "Xresinternal.h" + +/* Not cost effective, at least for vanilla MIT clients */ +/* #define PERMQ */ + +#ifdef PERMQ +typedef unsigned char Bits; +#endif +typedef unsigned long Entry; /* dont confuse with EntryRec from Xintatom.h */ + +static XrmQuark nextQuark = 1; /* next available quark number */ +static unsigned long quarkMask = 0; +static Entry zero = 0; +static Entry *quarkTable = &zero; /* crock */ +static unsigned long quarkRehash; +static XrmString **stringTable = NULL; +#ifdef PERMQ +static Bits **permTable = NULL; +#endif +static XrmQuark nextUniq = -1; /* next quark from XrmUniqueQuark */ + +#define QUANTUMSHIFT 8 +#define QUANTUMMASK ((1 << QUANTUMSHIFT) - 1) +#define CHUNKPER 8 +#define CHUNKMASK ((CHUNKPER << QUANTUMSHIFT) - 1) + +#define LARGEQUARK ((Entry)0x80000000L) +#define QUARKSHIFT 18 +#define QUARKMASK ((LARGEQUARK - 1) >> QUARKSHIFT) +#define XSIGMASK ((1L << QUARKSHIFT) - 1) + +#define STRQUANTSIZE (sizeof(XrmString) * (QUANTUMMASK + 1)) +#ifdef PERMQ +#define QUANTSIZE (STRQUANTSIZE + \ + (sizeof(Bits) * ((QUANTUMMASK + 1) >> 3)) +#else +#define QUANTSIZE STRQUANTSIZE +#endif + +#define HASH(sig) ((sig) & quarkMask) +#define REHASHVAL(sig) ((((sig) % quarkRehash) + 2) | 1) +#define REHASH(idx,rehash) ((idx + rehash) & quarkMask) +#define NAME(q) stringTable[(q) >> QUANTUMSHIFT][(q) & QUANTUMMASK] +#ifdef PERMQ +#define BYTEREF(q) permTable[(q) >> QUANTUMSHIFT][((q) & QUANTUMMASK) >> 3] +#define ISPERM(q) (BYTEREF(q) & (1 << ((q) & 7))) +#define SETPERM(q) BYTEREF(q) |= (1 << ((q) & 7)) +#define CLEARPERM(q) BYTEREF(q) &= ~(1 << ((q) & 7)) +#endif + +/* Permanent memory allocation */ + +#define WALIGN sizeof(unsigned long) +#define DALIGN sizeof(double) + +#define NEVERFREETABLESIZE ((8192-12) & ~(DALIGN-1)) +static char *neverFreeTable = NULL; +static int neverFreeTableSize = 0; + +static char *permalloc(unsigned int length) +{ + char *ret; + + if (neverFreeTableSize < length) { + if (length >= NEVERFREETABLESIZE) + return Xmalloc(length); + if (! (ret = Xmalloc(NEVERFREETABLESIZE))) + return (char *) NULL; + neverFreeTableSize = NEVERFREETABLESIZE; + neverFreeTable = ret; + } + ret = neverFreeTable; + neverFreeTable += length; + neverFreeTableSize -= length; + return(ret); +} + +#ifndef WORD64 +typedef struct {char a; double b;} TestType1; +typedef struct {char a; unsigned long b;} TestType2; +#endif + +#ifdef XTHREADS +static char *_Xpermalloc(unsigned int length); + +char *Xpermalloc(unsigned int length) +{ + char *p; + + _XLockMutex(_Xglobal_lock); + p = _Xpermalloc(length); + _XUnlockMutex(_Xglobal_lock); + return p; +} +#define Xpermalloc _Xpermalloc + +static +#endif /* XTHREADS */ +char *Xpermalloc(unsigned int length) +{ + int i; + + if (neverFreeTableSize && length < NEVERFREETABLESIZE) { +#ifndef WORD64 + if ((sizeof(TestType1) != + (sizeof(TestType2) - sizeof(unsigned long) + sizeof(double))) && + !(length & (DALIGN-1)) && + ((i = (NEVERFREETABLESIZE - neverFreeTableSize) & (DALIGN-1)))) { + neverFreeTableSize -= DALIGN - i; + neverFreeTable += DALIGN - i; + } else +#endif + if ((i = (NEVERFREETABLESIZE - neverFreeTableSize) & (WALIGN-1))) { + neverFreeTableSize -= WALIGN - i; + neverFreeTable += WALIGN - i; + } + } + return permalloc(length); +} + +static Bool +ExpandQuarkTable(void) +{ + unsigned long oldmask, newmask; + register char c, *s; + register Entry *oldentries, *entries; + register Entry entry; + register int oldidx, newidx, rehash; + Signature sig; + XrmQuark q; + + oldentries = quarkTable; + if ((oldmask = quarkMask)) + newmask = (oldmask << 1) + 1; + else { + if (!stringTable) { + stringTable = (XrmString **)Xmalloc(sizeof(XrmString *) * + CHUNKPER); + if (!stringTable) + return False; + stringTable[0] = (XrmString *)NULL; + } +#ifdef PERMQ + if (!permTable) + permTable = (Bits **)Xmalloc(sizeof(Bits *) * CHUNKPER); + if (!permTable) + return False; +#endif + stringTable[0] = (XrmString *)Xpermalloc(QUANTSIZE); + if (!stringTable[0]) + return False; +#ifdef PERMQ + permTable[0] = (Bits *)((char *)stringTable[0] + STRQUANTSIZE); +#endif + newmask = 0x1ff; + } + entries = Xcalloc(newmask + 1, sizeof(Entry)); + if (!entries) + return False; + quarkTable = entries; + quarkMask = newmask; + quarkRehash = quarkMask - 2; + for (oldidx = 0; oldidx <= oldmask; oldidx++) { + if ((entry = oldentries[oldidx])) { + if (entry & LARGEQUARK) + q = entry & (LARGEQUARK-1); + else + q = (entry >> QUARKSHIFT) & QUARKMASK; + for (sig = 0, s = NAME(q); (c = *s++); ) + sig = (sig << 1) + c; + newidx = HASH(sig); + if (entries[newidx]) { + rehash = REHASHVAL(sig); + do { + newidx = REHASH(newidx, rehash); + } while (entries[newidx]); + } + entries[newidx] = entry; + } + } + if (oldmask) + Xfree((char *)oldentries); + return True; +} + +XrmQuark +_XrmInternalStringToQuark( + register _Xconst char *name, register int len, register Signature sig, + Bool permstring) +{ + register XrmQuark q; + register Entry entry; + register int idx, rehash; + register int i; + register char *s1, *s2; + char *new; + + rehash = 0; + idx = HASH(sig); + _XLockMutex(_Xglobal_lock); + while ((entry = quarkTable[idx])) { + if (entry & LARGEQUARK) + q = entry & (LARGEQUARK-1); + else { + if ((entry - sig) & XSIGMASK) + goto nomatch; + q = (entry >> QUARKSHIFT) & QUARKMASK; + } + for (i = len, s1 = (char *)name, s2 = NAME(q); --i >= 0; ) { + if (*s1++ != *s2++) + goto nomatch; + } + if (*s2) { +nomatch: if (!rehash) + rehash = REHASHVAL(sig); + idx = REHASH(idx, rehash); + continue; + } +#ifdef PERMQ + if (permstring && !ISPERM(q)) { + Xfree(NAME(q)); + NAME(q) = (char *)name; + SETPERM(q); + } +#endif + _XUnlockMutex(_Xglobal_lock); + return q; + } + if (nextUniq == nextQuark) + goto fail; + if ((nextQuark + (nextQuark >> 2)) > quarkMask) { + if (!ExpandQuarkTable()) + goto fail; + _XUnlockMutex(_Xglobal_lock); + return _XrmInternalStringToQuark(name, len, sig, permstring); + } + q = nextQuark; + if (!(q & QUANTUMMASK)) { + if (!(q & CHUNKMASK)) { + if (!(new = Xrealloc((char *)stringTable, + sizeof(XrmString *) * + ((q >> QUANTUMSHIFT) + CHUNKPER)))) + goto fail; + stringTable = (XrmString **)new; +#ifdef PERMQ + if (!(new = Xrealloc((char *)permTable, + sizeof(Bits *) * + ((q >> QUANTUMSHIFT) + CHUNKPER)))) + goto fail; + permTable = (Bits **)new; +#endif + } + new = Xpermalloc(QUANTSIZE); + if (!new) + goto fail; + stringTable[q >> QUANTUMSHIFT] = (XrmString *)new; +#ifdef PERMQ + permTable[q >> QUANTUMSHIFT] = (Bits *)(new + STRQUANTSIZE); +#endif + } + if (!permstring) { + s2 = (char *)name; +#ifdef PERMQ + name = Xmalloc(len+1); +#else + name = permalloc(len+1); +#endif + if (!name) + goto fail; + for (i = len, s1 = (char *)name; --i >= 0; ) + *s1++ = *s2++; + *s1++ = '\0'; +#ifdef PERMQ + CLEARPERM(q); + } + else { + SETPERM(q); +#endif + } + NAME(q) = (char *)name; + if (q <= QUARKMASK) + entry = (q << QUARKSHIFT) | (sig & XSIGMASK); + else + entry = q | LARGEQUARK; + quarkTable[idx] = entry; + nextQuark++; + _XUnlockMutex(_Xglobal_lock); + return q; + fail: + _XUnlockMutex(_Xglobal_lock); + return NULLQUARK; +} + +XrmQuark +XrmStringToQuark( + _Xconst char *name) +{ + register char c, *tname; + register Signature sig = 0; + + if (!name) + return (NULLQUARK); + + for (tname = (char *)name; (c = *tname++); ) + sig = (sig << 1) + c; + + return _XrmInternalStringToQuark(name, tname-(char *)name-1, sig, False); +} + +XrmQuark +XrmPermStringToQuark( + _Xconst char *name) +{ + register char c, *tname; + register Signature sig = 0; + + if (!name) + return (NULLQUARK); + + for (tname = (char *)name; (c = *tname++); ) + sig = (sig << 1) + c; + + return _XrmInternalStringToQuark(name, tname-(char *)name-1, sig, True); +} + +XrmQuark XrmUniqueQuark(void) +{ + XrmQuark q; + + _XLockMutex(_Xglobal_lock); + if (nextUniq == nextQuark) + q = NULLQUARK; + else + q = nextUniq--; + _XUnlockMutex(_Xglobal_lock); + return q; +} + +XrmString XrmQuarkToString(register XrmQuark quark) +{ + XrmString s; + + _XLockMutex(_Xglobal_lock); + if (quark <= 0 || quark >= nextQuark) + s = NULLSTRING; + else { +#ifdef PERMQ + /* We have to mark the quark as permanent, since the caller might hold + * onto the string pointer forver. + */ + SETPERM(quark); +#endif + s = NAME(quark); + } + _XUnlockMutex(_Xglobal_lock); + return s; +} diff --git a/libX11/src/RdBitF.c b/libX11/src/RdBitF.c index 6b920c609..afdaee7fc 100644 --- a/libX11/src/RdBitF.c +++ b/libX11/src/RdBitF.c @@ -1,262 +1,262 @@ -/*
-
-Copyright 1987, 1998 The Open Group
-
-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.
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall
-not be used in advertising or otherwise to promote the sale, use or
-other dealings in this Software without prior written authorization
-from The Open Group.
-
-*/
-
-/*
- * Code to read bitmaps from disk files. Interprets
- * data from X10 and X11 bitmap files and creates
- * Pixmap representations of files. Returns Pixmap
- * ID and specifics about image.
- *
- * Modified for speedup by Jim Becker, changed image
- * data parsing logic (removed some fscanf()s).
- * Aug 5, 1988
- *
- * Note that this file and ../Xmu/RdBitF.c look very similar.... Keep them
- * that way (but don't use common source code so that people can have one
- * without the other).
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include "Xlibint.h"
-#include <X11/Xos.h>
-#include "Xutil.h"
-#include <stdio.h>
-#include <ctype.h>
-
-
-#define MAX_SIZE 255
-
-/* shared data for the image read/parse logic */
-static const signed char hexTable[256] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0
- , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- ,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0
- , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0
- , 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0
- , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- , 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0
- , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0
- , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-/*
- * read next hex value in the input stream, return -1 if EOF
- */
-static int
-NextInt (
- FILE *fstream)
-{
- int ch;
- int value = 0;
- int gotone = 0;
- int done = 0;
-
- /* loop, accumulate hex value until find delimiter */
- /* skip any initial delimiters found in read stream */
-
- while (!done) {
- ch = getc(fstream);
- if (ch == EOF) {
- value = -1;
- done++;
- } else {
- /* trim high bits, check type and accumulate */
- ch &= 0xff;
- if (isascii(ch) && isxdigit(ch)) {
- value = (value << 4) + hexTable[ch];
- gotone++;
- } else if ((hexTable[ch]) < 0 && gotone)
- done++;
- }
- }
- return value;
-}
-
-int
-XReadBitmapFileData (
- _Xconst char *filename,
- unsigned int *width, /* RETURNED */
- unsigned int *height, /* RETURNED */
- unsigned char **data, /* RETURNED */
- int *x_hot, /* RETURNED */
- int *y_hot) /* RETURNED */
-{
- FILE *fstream; /* handle on file */
- unsigned char *bits = NULL; /* working variable */
- char line[MAX_SIZE]; /* input line from file */
- int size; /* number of bytes of data */
- char name_and_type[MAX_SIZE]; /* an input line */
- char *type; /* for parsing */
- int value; /* from an input line */
- int version10p; /* boolean, old format */
- int padding; /* to handle alignment */
- int bytes_per_line; /* per scanline of data */
- unsigned int ww = 0; /* width */
- unsigned int hh = 0; /* height */
- int hx = -1; /* x hotspot */
- int hy = -1; /* y hotspot */
-
-#ifdef __UNIXOS2__
- filename = __XOS2RedirRoot(filename);
-#endif
- if (!(fstream = fopen(filename, "r")))
- return BitmapOpenFailed;
-
- /* error cleanup and return macro */
-#define RETURN(code) \
-{ if (bits) Xfree ((char *)bits); fclose (fstream); return code; }
-
- while (fgets(line, MAX_SIZE, fstream)) {
- if (strlen(line) == MAX_SIZE-1)
- RETURN (BitmapFileInvalid);
- if (sscanf(line,"#define %s %d",name_and_type,&value) == 2) {
- if (!(type = strrchr(name_and_type, '_')))
- type = name_and_type;
- else
- type++;
-
- if (!strcmp("width", type))
- ww = (unsigned int) value;
- if (!strcmp("height", type))
- hh = (unsigned int) value;
- if (!strcmp("hot", type)) {
- if (type-- == name_and_type || type-- == name_and_type)
- continue;
- if (!strcmp("x_hot", type))
- hx = value;
- if (!strcmp("y_hot", type))
- hy = value;
- }
- continue;
- }
-
- if (sscanf(line, "static short %s = {", name_and_type) == 1)
- version10p = 1;
- else if (sscanf(line,"static unsigned char %s = {",name_and_type) == 1)
- version10p = 0;
- else if (sscanf(line, "static char %s = {", name_and_type) == 1)
- version10p = 0;
- else
- continue;
-
- if (!(type = strrchr(name_and_type, '_')))
- type = name_and_type;
- else
- type++;
-
- if (strcmp("bits[]", type))
- continue;
-
- if (!ww || !hh)
- RETURN (BitmapFileInvalid);
-
- if ((ww % 16) && ((ww % 16) < 9) && version10p)
- padding = 1;
- else
- padding = 0;
-
- bytes_per_line = (ww+7)/8 + padding;
-
- size = bytes_per_line * hh;
- bits = (unsigned char *) Xmalloc ((unsigned int) size);
- if (!bits)
- RETURN (BitmapNoMemory);
-
- if (version10p) {
- unsigned char *ptr;
- int bytes;
-
- for (bytes=0, ptr=bits; bytes<size; (bytes += 2)) {
- if ((value = NextInt(fstream)) < 0)
- RETURN (BitmapFileInvalid);
- *(ptr++) = value;
- if (!padding || ((bytes+2) % bytes_per_line))
- *(ptr++) = value >> 8;
- }
- } else {
- unsigned char *ptr;
- int bytes;
-
- for (bytes=0, ptr=bits; bytes<size; bytes++, ptr++) {
- if ((value = NextInt(fstream)) < 0)
- RETURN (BitmapFileInvalid);
- *ptr=value;
- }
- }
-
- /* If we got to this point, we read a full bitmap file. Break so we don't
- * start reading another one from the same file and leak the memory
- * allocated for the previous one. */
- break;
- } /* end while */
-
- fclose(fstream);
- if (!bits)
- return (BitmapFileInvalid);
-
- *data = bits;
- *width = ww;
- *height = hh;
- if (x_hot) *x_hot = hx;
- if (y_hot) *y_hot = hy;
-
- return (BitmapSuccess);
-}
-
-int
-XReadBitmapFile (
- Display *display,
- Drawable d,
- _Xconst char *filename,
- unsigned int *width, /* RETURNED */
- unsigned int *height, /* RETURNED */
- Pixmap *pixmap, /* RETURNED */
- int *x_hot, /* RETURNED */
- int *y_hot) /* RETURNED */
-{
- unsigned char *data;
- int res;
-
- res = XReadBitmapFileData(filename, width, height, &data, x_hot, y_hot);
- if (res != BitmapSuccess)
- return res;
- *pixmap = XCreateBitmapFromData(display, d, (char *)data, *width, *height);
- Xfree((char *)data);
- if (*pixmap == None)
- return (BitmapNoMemory);
- return (BitmapSuccess);
-}
+/* + +Copyright 1987, 1998 The Open Group + +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. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +/* + * Code to read bitmaps from disk files. Interprets + * data from X10 and X11 bitmap files and creates + * Pixmap representations of files. Returns Pixmap + * ID and specifics about image. + * + * Modified for speedup by Jim Becker, changed image + * data parsing logic (removed some fscanf()s). + * Aug 5, 1988 + * + * Note that this file and ../Xmu/RdBitF.c look very similar.... Keep them + * that way (but don't use common source code so that people can have one + * without the other). + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include "Xlibint.h" +#include <X11/Xos.h> +#include "Xutil.h" +#include <stdio.h> +#include <ctype.h> + + +#define MAX_SIZE 255 + +/* shared data for the image read/parse logic */ +static const signed char hexTable[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0 + , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + ,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0 + , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0 + , 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0 + , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + , 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0 + , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0 + , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * read next hex value in the input stream, return -1 if EOF + */ +static int +NextInt ( + FILE *fstream) +{ + int ch; + int value = 0; + int gotone = 0; + int done = 0; + + /* loop, accumulate hex value until find delimiter */ + /* skip any initial delimiters found in read stream */ + + while (!done) { + ch = getc(fstream); + if (ch == EOF) { + value = -1; + done++; + } else { + /* trim high bits, check type and accumulate */ + ch &= 0xff; + if (isascii(ch) && isxdigit(ch)) { + value = (value << 4) + hexTable[ch]; + gotone++; + } else if ((hexTable[ch]) < 0 && gotone) + done++; + } + } + return value; +} + +int +XReadBitmapFileData ( + _Xconst char *filename, + unsigned int *width, /* RETURNED */ + unsigned int *height, /* RETURNED */ + unsigned char **data, /* RETURNED */ + int *x_hot, /* RETURNED */ + int *y_hot) /* RETURNED */ +{ + FILE *fstream; /* handle on file */ + unsigned char *bits = NULL; /* working variable */ + char line[MAX_SIZE]; /* input line from file */ + int size; /* number of bytes of data */ + char name_and_type[MAX_SIZE]; /* an input line */ + char *type; /* for parsing */ + int value; /* from an input line */ + int version10p; /* boolean, old format */ + int padding; /* to handle alignment */ + int bytes_per_line; /* per scanline of data */ + unsigned int ww = 0; /* width */ + unsigned int hh = 0; /* height */ + int hx = -1; /* x hotspot */ + int hy = -1; /* y hotspot */ + +#ifdef __UNIXOS2__ + filename = __XOS2RedirRoot(filename); +#endif + if (!(fstream = fopen(filename, "r"))) + return BitmapOpenFailed; + + /* error cleanup and return macro */ +#define RETURN(code) \ +{ if (bits) Xfree ((char *)bits); fclose (fstream); return code; } + + while (fgets(line, MAX_SIZE, fstream)) { + if (strlen(line) == MAX_SIZE-1) + RETURN (BitmapFileInvalid); + if (sscanf(line,"#define %s %d",name_and_type,&value) == 2) { + if (!(type = strrchr(name_and_type, '_'))) + type = name_and_type; + else + type++; + + if (!strcmp("width", type)) + ww = (unsigned int) value; + if (!strcmp("height", type)) + hh = (unsigned int) value; + if (!strcmp("hot", type)) { + if (type-- == name_and_type || type-- == name_and_type) + continue; + if (!strcmp("x_hot", type)) + hx = value; + if (!strcmp("y_hot", type)) + hy = value; + } + continue; + } + + if (sscanf(line, "static short %s = {", name_and_type) == 1) + version10p = 1; + else if (sscanf(line,"static unsigned char %s = {",name_and_type) == 1) + version10p = 0; + else if (sscanf(line, "static char %s = {", name_and_type) == 1) + version10p = 0; + else + continue; + + if (!(type = strrchr(name_and_type, '_'))) + type = name_and_type; + else + type++; + + if (strcmp("bits[]", type)) + continue; + + if (!ww || !hh) + RETURN (BitmapFileInvalid); + + if ((ww % 16) && ((ww % 16) < 9) && version10p) + padding = 1; + else + padding = 0; + + bytes_per_line = (ww+7)/8 + padding; + + size = bytes_per_line * hh; + bits = (unsigned char *) Xmalloc ((unsigned int) size); + if (!bits) + RETURN (BitmapNoMemory); + + if (version10p) { + unsigned char *ptr; + int bytes; + + for (bytes=0, ptr=bits; bytes<size; (bytes += 2)) { + if ((value = NextInt(fstream)) < 0) + RETURN (BitmapFileInvalid); + *(ptr++) = value; + if (!padding || ((bytes+2) % bytes_per_line)) + *(ptr++) = value >> 8; + } + } else { + unsigned char *ptr; + int bytes; + + for (bytes=0, ptr=bits; bytes<size; bytes++, ptr++) { + if ((value = NextInt(fstream)) < 0) + RETURN (BitmapFileInvalid); + *ptr=value; + } + } + + /* If we got to this point, we read a full bitmap file. Break so we don't + * start reading another one from the same file and leak the memory + * allocated for the previous one. */ + break; + } /* end while */ + + fclose(fstream); + if (!bits) + return (BitmapFileInvalid); + + *data = bits; + *width = ww; + *height = hh; + if (x_hot) *x_hot = hx; + if (y_hot) *y_hot = hy; + + return (BitmapSuccess); +} + +int +XReadBitmapFile ( + Display *display, + Drawable d, + _Xconst char *filename, + unsigned int *width, /* RETURNED */ + unsigned int *height, /* RETURNED */ + Pixmap *pixmap, /* RETURNED */ + int *x_hot, /* RETURNED */ + int *y_hot) /* RETURNED */ +{ + unsigned char *data; + int res; + + res = XReadBitmapFileData(filename, width, height, &data, x_hot, y_hot); + if (res != BitmapSuccess) + return res; + *pixmap = XCreateBitmapFromData(display, d, (char *)data, *width, *height); + Xfree((char *)data); + if (*pixmap == None) + return (BitmapNoMemory); + return (BitmapSuccess); +} diff --git a/libX11/src/SetLocale.c b/libX11/src/SetLocale.c index 81c946cdf..64166bda0 100644 --- a/libX11/src/SetLocale.c +++ b/libX11/src/SetLocale.c @@ -1,254 +1,254 @@ -
-/*
- * Copyright 1990, 1991 by OMRON Corporation, NTT Software Corporation,
- * and Nippon Telegraph and Telephone Corporation
- *
- * 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, NTT Software, and NTT
- * not be used in advertising or publicity pertaining to distribution of the
- * software without specific, written prior permission. OMRON, NTT Software,
- * and NTT make no representations about the suitability of this
- * software for any purpose. It is provided "as is" without express or
- * implied warranty.
- *
- * OMRON, NTT SOFTWARE, AND NTT, DISCLAIM ALL WARRANTIES WITH REGARD
- * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS, IN NO EVENT SHALL OMRON, NTT SOFTWARE, OR NTT, 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 TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * Authors: Li Yuhong OMRON Corporation
- * Tetsuya Kato NTT Software Corporation
- * Hiroshi Kuribayashi OMRON Corporation
- *
- */
-/*
-
-Copyright 1987,1998 The Open Group
-
-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.
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall
-not be used in advertising or otherwise to promote the sale, use or
-other dealings in this Software without prior written authorization
-from The Open Group.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include "Xlibint.h"
-#include "Xlcint.h"
-#include <X11/Xlocale.h>
-#include <X11/Xos.h>
-#include "XlcPubI.h"
-#include <unistd.h>
-
-#define MAXLOCALE 64 /* buffer size of locale name */
-
-#ifdef X_LOCALE
-
-/* alternative setlocale() for when the OS does not provide one */
-
-char *
-_Xsetlocale(
- int category,
- _Xconst char *name
-)
-{
- static char *xsl_name;
- char *old_name;
- XrmMethods methods;
- XPointer state;
-
- if (category != LC_CTYPE && category != LC_ALL)
- return NULL;
- if (!name) {
- if (xsl_name)
- return xsl_name;
- return "C";
- }
- if (!*name)
- name = getenv("LC_CTYPE");
- if (!name || !*name)
- name = getenv("LANG");
- if (name && strlen(name) >= MAXLOCALE)
- name = NULL;
- if (!name || !*name || !_XOpenLC((char *) name))
- name = "C";
- old_name = xsl_name;
- xsl_name = (char *)name;
- methods = _XrmInitParseInfo(&state);
- xsl_name = old_name;
- if (!methods)
- return NULL;
- name = (*methods->lcname)(state);
- xsl_name = strdup(name);
- if (!xsl_name) {
- xsl_name = old_name;
- (*methods->destroy)(state);
- return NULL;
- }
- if (old_name)
- Xfree(old_name);
- (*methods->destroy)(state);
- return xsl_name;
-}
-
-#else /* X_LOCALE */
-
-#if defined(__APPLE__) || defined(__CYGWIN__)
-char *
-_Xsetlocale(
- int category,
- _Xconst char *name
-)
-{
- return setlocale(category, name);
-}
-#endif /* __APPLE__ || __CYGWIN__ */
-
-/*
- * _XlcMapOSLocaleName is an implementation dependent routine that derives
- * the LC_CTYPE locale name as used in the sample implementation from that
- * returned by setlocale.
- *
- * Should match the code in Xt ExtractLocaleName.
- *
- * This function name is a bit of a misnomer. Even the siname parameter
- * name is a misnomer. On most modern operating systems this function is
- * a no-op, simply returning the osname; but on older operating systems
- * like Ultrix, or HPUX 9.x and earlier, when you set LANG=german.88591
- * then the string returned by setlocale(LC_ALL, "") will look something
- * like: "german.88591 german.88591 ... german.88591". Then this function
- * will pick out the LC_CTYPE component and return a pointer to that.
- */
-
-char *
-_XlcMapOSLocaleName(
- char *osname,
- char *siname)
-{
-#if defined(hpux) || defined(CSRG_BASED) || defined(sun) || defined(SVR4) || defined(sgi) || defined(__osf__) || defined(AIXV3) || defined(ultrix) || defined(WIN32) || defined(__UNIXOS2__) || defined(linux)
-# ifdef hpux
-# ifndef _LastCategory
- /* HPUX 9 and earlier */
-# define SKIPCOUNT 2
-# define STARTCHAR ':'
-# define ENDCHAR ';'
-# else
- /* HPUX 10 */
-# define ENDCHAR ' '
-# endif
-# else
-# ifdef ultrix
-# define SKIPCOUNT 2
-# define STARTCHAR '\001'
-# define ENDCHAR '\001'
-# else
-# if defined(WIN32) || defined(__UNIXOS2__)
-# define SKIPCOUNT 1
-# define STARTCHAR '='
-# define ENDCHAR ';'
-# define WHITEFILL
-# else
-# if defined(__osf__) || (defined(AIXV3) && !defined(AIXV4))
-# define STARTCHAR ' '
-# define ENDCHAR ' '
-# else
-# if defined(linux)
-# define STARTSTR "LC_CTYPE="
-# define ENDCHAR ';'
-# else
-# if !defined(sun) || defined(SVR4)
-# define STARTCHAR '/'
-# define ENDCHAR '/'
-# endif
-# endif
-# endif
-# endif
-# endif
-# endif
-
- char *start;
- char *end;
- int len;
-# ifdef SKIPCOUNT
- int n;
-# endif
-
- start = osname;
-# ifdef SKIPCOUNT
- for (n = SKIPCOUNT;
- --n >= 0 && start && (start = strchr (start, STARTCHAR));
- start++)
- ;
- if (!start)
- start = osname;
-# endif
-# ifdef STARTCHAR
- if (start && (start = strchr (start, STARTCHAR)))
-# elif defined (STARTSTR)
- if (start && (start = strstr (start,STARTSTR)))
-# endif
- {
-# ifdef STARTCHAR
- start++;
-# elif defined (STARTSTR)
- start += strlen(STARTSTR);
-# endif
- if ((end = strchr (start, ENDCHAR))) {
- len = end - start;
- if (len >= MAXLOCALE)
- len = MAXLOCALE - 1;
- strncpy(siname, start, len);
- *(siname + len) = '\0';
-# ifdef WHITEFILL
- for (start = siname; start = strchr(start, ' '); )
- *start++ = '-';
-# endif
- return siname;
- } else /* if no ENDCHAR is found we are at the end of the line */
- return start;
- }
-# ifdef WHITEFILL
- if (strchr(osname, ' ')) {
- len = strlen(osname);
- if (len >= MAXLOCALE - 1)
- len = MAXLOCALE - 1;
- strncpy(siname, osname, len);
- *(siname + len) = '\0';
- for (start = siname; start = strchr(start, ' '); )
- *start++ = '-';
- return siname;
- }
-# endif
-# undef STARTCHAR
-# undef ENDCHAR
-# undef WHITEFILL
-#endif
- return osname;
-}
-
-#endif /* X_LOCALE */
+ +/* + * Copyright 1990, 1991 by OMRON Corporation, NTT Software Corporation, + * and Nippon Telegraph and Telephone Corporation + * + * 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, NTT Software, and NTT + * not be used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. OMRON, NTT Software, + * and NTT make no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * OMRON, NTT SOFTWARE, AND NTT, DISCLAIM ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL OMRON, NTT SOFTWARE, OR NTT, 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 TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Authors: Li Yuhong OMRON Corporation + * Tetsuya Kato NTT Software Corporation + * Hiroshi Kuribayashi OMRON Corporation + * + */ +/* + +Copyright 1987,1998 The Open Group + +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. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include "Xlibint.h" +#include "Xlcint.h" +#include <X11/Xlocale.h> +#include <X11/Xos.h> +#include "XlcPubI.h" +#include <unistd.h> + +#define MAXLOCALE 64 /* buffer size of locale name */ + +#ifdef X_LOCALE + +/* alternative setlocale() for when the OS does not provide one */ + +char * +_Xsetlocale( + int category, + _Xconst char *name +) +{ + static char *xsl_name; + char *old_name; + XrmMethods methods; + XPointer state; + + if (category != LC_CTYPE && category != LC_ALL) + return NULL; + if (!name) { + if (xsl_name) + return xsl_name; + return "C"; + } + if (!*name) + name = getenv("LC_CTYPE"); + if (!name || !*name) + name = getenv("LANG"); + if (name && strlen(name) >= MAXLOCALE) + name = NULL; + if (!name || !*name || !_XOpenLC((char *) name)) + name = "C"; + old_name = xsl_name; + xsl_name = (char *)name; + methods = _XrmInitParseInfo(&state); + xsl_name = old_name; + if (!methods) + return NULL; + name = (*methods->lcname)(state); + xsl_name = strdup(name); + if (!xsl_name) { + xsl_name = old_name; + (*methods->destroy)(state); + return NULL; + } + if (old_name) + Xfree(old_name); + (*methods->destroy)(state); + return xsl_name; +} + +#else /* X_LOCALE */ + +#if defined(__APPLE__) || defined(__CYGWIN__) +char * +_Xsetlocale( + int category, + _Xconst char *name +) +{ + return setlocale(category, name); +} +#endif /* __APPLE__ || __CYGWIN__ */ + +/* + * _XlcMapOSLocaleName is an implementation dependent routine that derives + * the LC_CTYPE locale name as used in the sample implementation from that + * returned by setlocale. + * + * Should match the code in Xt ExtractLocaleName. + * + * This function name is a bit of a misnomer. Even the siname parameter + * name is a misnomer. On most modern operating systems this function is + * a no-op, simply returning the osname; but on older operating systems + * like Ultrix, or HPUX 9.x and earlier, when you set LANG=german.88591 + * then the string returned by setlocale(LC_ALL, "") will look something + * like: "german.88591 german.88591 ... german.88591". Then this function + * will pick out the LC_CTYPE component and return a pointer to that. + */ + +char * +_XlcMapOSLocaleName( + char *osname, + char *siname) +{ +#if defined(hpux) || defined(CSRG_BASED) || defined(sun) || defined(SVR4) || defined(sgi) || defined(__osf__) || defined(AIXV3) || defined(ultrix) || defined(WIN32) || defined(__UNIXOS2__) || defined(linux) +# ifdef hpux +# ifndef _LastCategory + /* HPUX 9 and earlier */ +# define SKIPCOUNT 2 +# define STARTCHAR ':' +# define ENDCHAR ';' +# else + /* HPUX 10 */ +# define ENDCHAR ' ' +# endif +# else +# ifdef ultrix +# define SKIPCOUNT 2 +# define STARTCHAR '\001' +# define ENDCHAR '\001' +# else +# if defined(WIN32) || defined(__UNIXOS2__) +# define SKIPCOUNT 1 +# define STARTCHAR '=' +# define ENDCHAR ';' +# define WHITEFILL +# else +# if defined(__osf__) || (defined(AIXV3) && !defined(AIXV4)) +# define STARTCHAR ' ' +# define ENDCHAR ' ' +# else +# if defined(linux) +# define STARTSTR "LC_CTYPE=" +# define ENDCHAR ';' +# else +# if !defined(sun) || defined(SVR4) +# define STARTCHAR '/' +# define ENDCHAR '/' +# endif +# endif +# endif +# endif +# endif +# endif + + char *start; + char *end; + int len; +# ifdef SKIPCOUNT + int n; +# endif + + start = osname; +# ifdef SKIPCOUNT + for (n = SKIPCOUNT; + --n >= 0 && start && (start = strchr (start, STARTCHAR)); + start++) + ; + if (!start) + start = osname; +# endif +# ifdef STARTCHAR + if (start && (start = strchr (start, STARTCHAR))) +# elif defined (STARTSTR) + if (start && (start = strstr (start,STARTSTR))) +# endif + { +# ifdef STARTCHAR + start++; +# elif defined (STARTSTR) + start += strlen(STARTSTR); +# endif + if ((end = strchr (start, ENDCHAR))) { + len = end - start; + if (len >= MAXLOCALE) + len = MAXLOCALE - 1; + strncpy(siname, start, len); + *(siname + len) = '\0'; +# ifdef WHITEFILL + for (start = siname; start = strchr(start, ' '); ) + *start++ = '-'; +# endif + return siname; + } else /* if no ENDCHAR is found we are at the end of the line */ + return start; + } +# ifdef WHITEFILL + if (strchr(osname, ' ')) { + len = strlen(osname); + if (len >= MAXLOCALE - 1) + len = MAXLOCALE - 1; + strncpy(siname, osname, len); + *(siname + len) = '\0'; + for (start = siname; start = strchr(start, ' '); ) + *start++ = '-'; + return siname; + } +# endif +# undef STARTCHAR +# undef ENDCHAR +# undef WHITEFILL +#endif + return osname; +} + +#endif /* X_LOCALE */ diff --git a/libX11/src/XlibInt.c b/libX11/src/XlibInt.c index 305670214..edba13dc1 100644 --- a/libX11/src/XlibInt.c +++ b/libX11/src/XlibInt.c @@ -1,2177 +1,2177 @@ -/*
-
-Copyright 1985, 1986, 1987, 1998 The Open Group
-
-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.
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall
-not be used in advertising or otherwise to promote the sale, use or
-other dealings in this Software without prior written authorization
-from The Open Group.
-
-*/
-
-/*
- * XlibInt.c - Internal support routines for the C subroutine
- * interface library (Xlib) to the X Window System Protocol V11.0.
- */
-
-#ifdef WIN32
-#define _XLIBINT_
-#include <X11\Xw32defs.h>
-#endif
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include "Xlibint.h"
-#include "Xprivate.h"
-#include <X11/Xpoll.h>
-#include <assert.h>
-#include <stdio.h>
-#ifdef WIN32
-#include <direct.h>
-#endif
-
-#ifdef XTHREADS
-#include "locking.h"
-
-/* these pointers get initialized by XInitThreads */
-LockInfoPtr _Xglobal_lock = NULL;
-void (*_XCreateMutex_fn)(LockInfoPtr) = NULL;
-/* struct _XCVList *(*_XCreateCVL_fn)() = NULL; */
-void (*_XFreeMutex_fn)(LockInfoPtr) = NULL;
-void (*_XLockMutex_fn)(
- LockInfoPtr /* lock */
-#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
- , char * /* file */
- , int /* line */
-#endif
- ) = NULL;
-void (*_XUnlockMutex_fn)(
- LockInfoPtr /* lock */
-#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
- , char * /* file */
- , int /* line */
-#endif
- ) = NULL;
-xthread_t (*_Xthread_self_fn)(void) = NULL;
-
-#define XThread_Self() ((*_Xthread_self_fn)())
-
-#endif /* XTHREADS */
-
-/* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX
- * systems are broken and return EWOULDBLOCK when they should return EAGAIN
- */
-#ifdef WIN32
-#define ETEST() (WSAGetLastError() == WSAEWOULDBLOCK)
-#else
-#ifdef __CYGWIN__ /* Cygwin uses ENOBUFS to signal socket is full */
-#define ETEST() (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS)
-#else
-#if defined(EAGAIN) && defined(EWOULDBLOCK)
-#define ETEST() (errno == EAGAIN || errno == EWOULDBLOCK)
-#else
-#ifdef EAGAIN
-#define ETEST() (errno == EAGAIN)
-#else
-#define ETEST() (errno == EWOULDBLOCK)
-#endif /* EAGAIN */
-#endif /* EAGAIN && EWOULDBLOCK */
-#endif /* __CYGWIN__ */
-#endif /* WIN32 */
-
-#ifdef WIN32
-#define ECHECK(err) (WSAGetLastError() == err)
-#define ESET(val) WSASetLastError(val)
-#else
-#ifdef __UNIXOS2__
-#define ECHECK(err) (errno == err)
-#define ESET(val)
-#else
-#define ECHECK(err) (errno == err)
-#define ESET(val) errno = val
-#endif
-#endif
-
-#if defined(LOCALCONN) || defined(LACHMAN)
-#ifdef EMSGSIZE
-#define ESZTEST() (ECHECK(EMSGSIZE) || ECHECK(ERANGE))
-#else
-#define ESZTEST() ECHECK(ERANGE)
-#endif
-#else
-#ifdef EMSGSIZE
-#define ESZTEST() ECHECK(EMSGSIZE)
-#endif
-#endif
-
-#ifdef __UNIXOS2__
-#include <limits.h>
-#define MAX_PATH _POSIX_PATH_MAX
-#endif
-
-/*
- * The following routines are internal routines used by Xlib for protocol
- * packet transmission and reception.
- *
- * _XIOError(Display *) will be called if any sort of system call error occurs.
- * This is assumed to be a fatal condition, i.e., XIOError should not return.
- *
- * _XError(Display *, xError *) will be called whenever an X_Error event is
- * received. This is not assumed to be a fatal condition, i.e., it is
- * acceptable for this procedure to return. However, XError should NOT
- * perform any operations (directly or indirectly) on the DISPLAY.
- *
- * Routines declared with a return type of 'Status' return 0 on failure,
- * and non 0 on success. Routines with no declared return type don't
- * return anything. Whenever possible routines that create objects return
- * the object they have created.
- */
-
-#define POLLFD_CACHE_SIZE 5
-
-#if _WIN32_WINNT < _WIN32_WINNT_VISTA
-struct pollfd {
-
- SOCKET fd;
- SHORT events;
- SHORT revents;
-
-};
-#define POLLRDNORM 0x0100
-#define POLLRDBAND 0x0200
-#define POLLIN (POLLRDNORM | POLLRDBAND)
-#endif
-
-/* initialize the struct array passed to poll() below */
-Bool _XPollfdCacheInit(
- Display *dpy)
-{
-#ifdef USE_POLL
- struct pollfd *pfp;
-
- pfp = (struct pollfd *)Xmalloc(POLLFD_CACHE_SIZE * sizeof(struct pollfd));
- if (!pfp)
- return False;
- pfp[0].fd = dpy->fd;
- pfp[0].events = POLLIN;
-
- dpy->filedes = (XPointer)pfp;
-#endif
- return True;
-}
-
-void _XPollfdCacheAdd(
- Display *dpy,
- int fd)
-{
-#ifdef USE_POLL
- struct pollfd *pfp = (struct pollfd *)dpy->filedes;
-
- if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) {
- pfp[dpy->im_fd_length].fd = fd;
- pfp[dpy->im_fd_length].events = POLLIN;
- }
-#endif
-}
-
-/* ARGSUSED */
-void _XPollfdCacheDel(
- Display *dpy,
- int fd) /* not used */
-{
-#ifdef USE_POLL
- struct pollfd *pfp = (struct pollfd *)dpy->filedes;
- struct _XConnectionInfo *conni;
-
- /* just recalculate whole list */
- if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) {
- int loc = 1;
- for (conni = dpy->im_fd_info; conni; conni=conni->next) {
- pfp[loc].fd = conni->fd;
- pfp[loc].events = POLLIN;
- loc++;
- }
- }
-#endif
-}
-
-#ifdef _MSC_VER
-#undef min
-#define min __min
-#endif
-
-static int sync_hazard(Display *dpy)
-{
- unsigned long span = dpy->request - dpy->last_request_read;
- unsigned long hazard = min((dpy->bufmax - dpy->buffer) / SIZEOF(xReq), 65535 - 10);
- return span >= 65535 - hazard - 10;
-}
-
-static
-void sync_while_locked(Display *dpy)
-{
-#ifdef XTHREADS
- if (dpy->lock)
- (*dpy->lock->user_lock_display)(dpy);
-#endif
- UnlockDisplay(dpy);
- SyncHandle();
- InternalLockDisplay(dpy, /* don't skip user locks */ 0);
-#ifdef XTHREADS
- if (dpy->lock)
- (*dpy->lock->user_unlock_display)(dpy);
-#endif
-}
-
-void _XSeqSyncFunction(
- register Display *dpy)
-{
- xGetInputFocusReply rep;
- register xReq *req;
-
- if ((dpy->request - dpy->last_request_read) >= (65535 - BUFSIZE/SIZEOF(xReq))) {
- GetEmptyReq(GetInputFocus, req);
- (void) _XReply (dpy, (xReply *)&rep, 0, xTrue);
- sync_while_locked(dpy);
- } else if (sync_hazard(dpy))
- _XSetPrivSyncFunction(dpy);
-}
-
-/* NOTE: only called if !XTHREADS, or when XInitThreads wasn't called. */
-static int
-_XPrivSyncFunction (Display *dpy)
-{
-#ifdef XTHREADS
- assert(!dpy->lock_fns);
-#endif
- assert(dpy->synchandler == _XPrivSyncFunction);
- assert((dpy->flags & XlibDisplayPrivSync) != 0);
- dpy->synchandler = dpy->savedsynchandler;
- dpy->savedsynchandler = NULL;
- dpy->flags &= ~XlibDisplayPrivSync;
- if(dpy->synchandler)
- dpy->synchandler(dpy);
- _XIDHandler(dpy);
- _XSeqSyncFunction(dpy);
- return 0;
-}
-
-void _XSetPrivSyncFunction(Display *dpy)
-{
-#ifdef XTHREADS
- if (dpy->lock_fns)
- return;
-#endif
- if (!(dpy->flags & XlibDisplayPrivSync)) {
- dpy->savedsynchandler = dpy->synchandler;
- dpy->synchandler = _XPrivSyncFunction;
- dpy->flags |= XlibDisplayPrivSync;
- }
-}
-
-void _XSetSeqSyncFunction(Display *dpy)
-{
- if (sync_hazard(dpy))
- _XSetPrivSyncFunction (dpy);
-}
-
-#ifdef LONG64
-void _XRead32(
- Display *dpy,
- register long *data,
- long len)
-{
- register int *buf;
- register long i;
-
- if (len) {
- (void) _XRead(dpy, (char *)data, len);
- i = len >> 2;
- buf = (int *)data + i;
- data += i;
- while (--i >= 0)
- *--data = *--buf;
- }
-}
-#endif /* LONG64 */
-
-#ifdef WORD64
-
-/*
- * XXX This is a *really* stupid way of doing this....
- * PACKBUFFERSIZE must be a multiple of 4.
- */
-
-#define PACKBUFFERSIZE 4096
-
-
-/*
- * _XRead32 - Read bytes from the socket unpacking each 32 bits
- * into a long (64 bits on a CRAY computer).
- *
- */
-static void _doXRead32(
- register Display *dpy,
- register long *data
- register long size,
- register char *packbuffer)
-{
- long *lpack,*lp;
- long mask32 = 0x00000000ffffffff;
- long maskw, nwords, i, bits;
-
- _XReadPad (dpy, packbuffer, size);
-
- lp = data;
- lpack = (long *) packbuffer;
- nwords = size >> 2;
- bits = 32;
-
- for(i=0;i<nwords;i++){
- maskw = mask32 << bits;
- *lp++ = ( *lpack & maskw ) >> bits;
- bits = bits ^32;
- if(bits){
- lpack++;
- }
- }
-}
-
-void _XRead32(
- Display *dpy,
- long *data,
- long len)
-{
- char packbuffer[PACKBUFFERSIZE];
- unsigned nunits = PACKBUFFERSIZE >> 2;
-
- for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) {
- _doXRead32 (dpy, data, PACKBUFFERSIZE, packbuffer);
- }
- if (len) _doXRead32 (dpy, data, len, packbuffer);
-}
-
-
-
-/*
- * _XRead16 - Read bytes from the socket unpacking each 16 bits
- * into a long (64 bits on a CRAY computer).
- *
- */
-static _doXRead16(
- register Display *dpy,
- register short *data,
- register long size,
- char *packbuffer)
-{
- long *lpack,*lp;
- long mask16 = 0x000000000000ffff;
- long maskw, nwords, i, bits;
-
- (void) _XRead(dpy,packbuffer,size); /* don't do a padded read... */
-
- lp = (long *) data;
- lpack = (long *) packbuffer;
- nwords = size >> 1; /* number of 16 bit words to be unpacked */
- bits = 48;
- for(i=0;i<nwords;i++){
- maskw = mask16 << bits;
- *lp++ = ( *lpack & maskw ) >> bits;
- bits -= 16;
- if(bits < 0){
- lpack++;
- bits = 48;
- }
- }
-}
-
-void _XRead16(
- Display *dpy,
- short *data,
- long len)
-{
- char packbuffer[PACKBUFFERSIZE];
- unsigned nunits = PACKBUFFERSIZE >> 1;
-
- for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) {
- _doXRead16 (dpy, data, PACKBUFFERSIZE, packbuffer);
- }
- if (len) _doXRead16 (dpy, data, len, packbuffer);
-}
-
-void _XRead16Pad(
- Display *dpy,
- short *data,
- long size)
-{
- int slop = (size & 3);
- short slopbuf[3];
-
- _XRead16 (dpy, data, size);
- if (slop > 0) {
- _XRead16 (dpy, slopbuf, 4 - slop);
- }
-}
-#endif /* WORD64 */
-
-/*
- * The hard part about this is that we only get 16 bits from a reply.
- * We have three values that will march along, with the following invariant:
- * dpy->last_request_read <= rep->sequenceNumber <= dpy->request
- * We have to keep
- * dpy->request - dpy->last_request_read < 2^16
- * or else we won't know for sure what value to use in events. We do this
- * by forcing syncs when we get close.
- */
-
-unsigned long
-_XSetLastRequestRead(
- register Display *dpy,
- register xGenericReply *rep)
-{
- register unsigned long newseq, lastseq;
-
- lastseq = dpy->last_request_read;
- /*
- * KeymapNotify has no sequence number, but is always guaranteed
- * to immediately follow another event, except when generated via
- * SendEvent (hmmm).
- */
- if ((rep->type & 0x7f) == KeymapNotify)
- return(lastseq);
-
- newseq = (lastseq & ~((unsigned long)0xffff)) | rep->sequenceNumber;
-
- if (newseq < lastseq) {
- newseq += 0x10000;
- if (newseq > dpy->request) {
- (void) fprintf (stderr,
- "Xlib: sequence lost (0x%lx > 0x%lx) in reply type 0x%x!\n",
- newseq, dpy->request,
- (unsigned int) rep->type);
- newseq -= 0x10000;
- }
- }
-
- dpy->last_request_read = newseq;
- return(newseq);
-}
-
-/*
- * Support for internal connections, such as an IM might use.
- * By Stephen Gildea, X Consortium, September 1993
- */
-
-/* _XRegisterInternalConnection
- * Each IM (or Xlib extension) that opens a file descriptor that Xlib should
- * include in its select/poll mask must call this function to register the
- * fd with Xlib. Any XConnectionWatchProc registered by XAddConnectionWatch
- * will also be called.
- *
- * Whenever Xlib detects input available on fd, it will call callback
- * with call_data to process it. If non-Xlib code calls select/poll
- * and detects input available, it must call XProcessInternalConnection,
- * which will call the associated callback.
- *
- * Non-Xlib code can learn about these additional fds by calling
- * XInternalConnectionNumbers or, more typically, by registering
- * a XConnectionWatchProc with XAddConnectionWatch
- * to be called when fds are registered or unregistered.
- *
- * Returns True if registration succeeded, False if not, typically
- * because could not allocate memory.
- * Assumes Display locked when called.
- */
-Status
-_XRegisterInternalConnection(
- Display* dpy,
- int fd,
- _XInternalConnectionProc callback,
- XPointer call_data
-)
-{
- struct _XConnectionInfo *new_conni, **iptr;
- struct _XConnWatchInfo *watchers;
- XPointer *wd;
-
- new_conni = (struct _XConnectionInfo*)Xmalloc(sizeof(struct _XConnectionInfo));
- if (!new_conni)
- return 0;
- new_conni->watch_data = (XPointer *)Xmalloc(dpy->watcher_count * sizeof(XPointer));
- if (!new_conni->watch_data) {
- Xfree(new_conni);
- return 0;
- }
- new_conni->fd = fd;
- new_conni->read_callback = callback;
- new_conni->call_data = call_data;
- new_conni->next = NULL;
- /* link new structure onto end of list */
- for (iptr = &dpy->im_fd_info; *iptr; iptr = &(*iptr)->next)
- ;
- *iptr = new_conni;
- dpy->im_fd_length++;
- _XPollfdCacheAdd(dpy, fd);
-
- for (watchers=dpy->conn_watchers, wd=new_conni->watch_data;
- watchers;
- watchers=watchers->next, wd++) {
- *wd = NULL; /* for cleanliness */
- (*watchers->fn) (dpy, watchers->client_data, fd, True, wd);
- }
-
- return 1;
-}
-
-/* _XUnregisterInternalConnection
- * Each IM (or Xlib extension) that closes a file descriptor previously
- * registered with _XRegisterInternalConnection must call this function.
- * Any XConnectionWatchProc registered by XAddConnectionWatch
- * will also be called.
- *
- * Assumes Display locked when called.
- */
-void
-_XUnregisterInternalConnection(
- Display* dpy,
- int fd
-)
-{
- struct _XConnectionInfo *info_list, **prev;
- struct _XConnWatchInfo *watch;
- XPointer *wd;
-
- for (prev = &dpy->im_fd_info; (info_list = *prev);
- prev = &info_list->next) {
- if (info_list->fd == fd) {
- *prev = info_list->next;
- dpy->im_fd_length--;
- for (watch=dpy->conn_watchers, wd=info_list->watch_data;
- watch;
- watch=watch->next, wd++) {
- (*watch->fn) (dpy, watch->client_data, fd, False, wd);
- }
- if (info_list->watch_data)
- Xfree (info_list->watch_data);
- Xfree (info_list);
- break;
- }
- }
- _XPollfdCacheDel(dpy, fd);
-}
-
-/* XInternalConnectionNumbers
- * Returns an array of fds and an array of corresponding call data.
- * Typically a XConnectionWatchProc registered with XAddConnectionWatch
- * will be used instead of this function to discover
- * additional fds to include in the select/poll mask.
- *
- * The list is allocated with Xmalloc and should be freed by the caller
- * with Xfree;
- */
-Status
-XInternalConnectionNumbers(
- Display *dpy,
- int **fd_return,
- int *count_return
-)
-{
- int count;
- struct _XConnectionInfo *info_list;
- int *fd_list;
-
- LockDisplay(dpy);
- count = 0;
- for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next)
- count++;
- fd_list = (int*) Xmalloc (count * sizeof(int));
- if (!fd_list) {
- UnlockDisplay(dpy);
- return 0;
- }
- count = 0;
- for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
- fd_list[count] = info_list->fd;
- count++;
- }
- UnlockDisplay(dpy);
-
- *fd_return = fd_list;
- *count_return = count;
- return 1;
-}
-
-void _XProcessInternalConnection(
- Display *dpy,
- struct _XConnectionInfo *conn_info)
-{
- dpy->flags |= XlibDisplayProcConni;
- UnlockDisplay(dpy);
- (*conn_info->read_callback) (dpy, conn_info->fd, conn_info->call_data);
- LockDisplay(dpy);
- dpy->flags &= ~XlibDisplayProcConni;
-}
-
-/* XProcessInternalConnection
- * Call the _XInternalConnectionProc registered by _XRegisterInternalConnection
- * for this fd.
- * The Display is NOT locked during the call.
- */
-void
-XProcessInternalConnection(
- Display* dpy,
- int fd
-)
-{
- struct _XConnectionInfo *info_list;
-
- LockDisplay(dpy);
- for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
- if (info_list->fd == fd) {
- _XProcessInternalConnection(dpy, info_list);
- break;
- }
- }
- UnlockDisplay(dpy);
-}
-
-/* XAddConnectionWatch
- * Register a callback to be called whenever _XRegisterInternalConnection
- * or _XUnregisterInternalConnection is called.
- * Callbacks are called with the Display locked.
- * If any connections are already registered, the callback is immediately
- * called for each of them.
- */
-Status
-XAddConnectionWatch(
- Display* dpy,
- XConnectionWatchProc callback,
- XPointer client_data
-)
-{
- struct _XConnWatchInfo *new_watcher, **wptr;
- struct _XConnectionInfo *info_list;
- XPointer *wd_array;
-
- LockDisplay(dpy);
-
- /* allocate new watch data */
- for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
- wd_array = (XPointer *)Xrealloc((char *)info_list->watch_data,
- (dpy->watcher_count + 1) *
- sizeof(XPointer));
- if (!wd_array) {
- UnlockDisplay(dpy);
- return 0;
- }
- info_list->watch_data = wd_array;
- wd_array[dpy->watcher_count] = NULL; /* for cleanliness */
- }
-
- new_watcher = (struct _XConnWatchInfo*)Xmalloc(sizeof(struct _XConnWatchInfo));
- if (!new_watcher) {
- UnlockDisplay(dpy);
- return 0;
- }
- new_watcher->fn = callback;
- new_watcher->client_data = client_data;
- new_watcher->next = NULL;
-
- /* link new structure onto end of list */
- for (wptr = &dpy->conn_watchers; *wptr; wptr = &(*wptr)->next)
- ;
- *wptr = new_watcher;
- dpy->watcher_count++;
-
- /* call new watcher on all currently registered fds */
- for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
- (*callback) (dpy, client_data, info_list->fd, True,
- info_list->watch_data + dpy->watcher_count - 1);
- }
-
- UnlockDisplay(dpy);
- return 1;
-}
-
-/* XRemoveConnectionWatch
- * Unregister a callback registered by XAddConnectionWatch.
- * Both callback and client_data must match what was passed to
- * XAddConnectionWatch.
- */
-void
-XRemoveConnectionWatch(
- Display* dpy,
- XConnectionWatchProc callback,
- XPointer client_data
-)
-{
- struct _XConnWatchInfo *watch;
- struct _XConnWatchInfo *previous = NULL;
- struct _XConnectionInfo *conni;
- int counter = 0;
-
- LockDisplay(dpy);
- for (watch=dpy->conn_watchers; watch; watch=watch->next) {
- if (watch->fn == callback && watch->client_data == client_data) {
- if (previous)
- previous->next = watch->next;
- else
- dpy->conn_watchers = watch->next;
- Xfree (watch);
- dpy->watcher_count--;
- /* remove our watch_data for each connection */
- for (conni=dpy->im_fd_info; conni; conni=conni->next) {
- /* don't bother realloc'ing; these arrays are small anyway */
- /* overlapping */
- memmove(conni->watch_data+counter,
- conni->watch_data+counter+1,
- dpy->watcher_count - counter);
- }
- break;
- }
- previous = watch;
- counter++;
- }
- UnlockDisplay(dpy);
-}
-
-/* end of internal connections support */
-
-/* Cookie jar implementation
- dpy->cookiejar is a linked list. _XEnq receives the events but leaves
- them in the normal EQ. _XStoreEvent returns the cookie event (minus
- data pointer) and adds it to the cookiejar. _XDeq just removes
- the entry like any other event but resets the data pointer for
- cookie events (to avoid double-free, the memory is re-used by Xlib).
-
- _XFetchEventCookie (called from XGetEventData) removes a cookie from the
- jar. _XFreeEventCookies removes all unclaimed cookies from the jar
- (called by XNextEvent).
-
- _XFreeDisplayStructure calls _XFreeEventCookies for each cookie in the
- normal EQ.
- */
-
-#include "utlist.h"
-struct stored_event {
- XGenericEventCookie ev;
- struct stored_event *prev;
- struct stored_event *next;
-};
-
-Bool
-_XIsEventCookie(Display *dpy, XEvent *ev)
-{
- return (ev->xcookie.type == GenericEvent &&
- dpy->generic_event_vec[ev->xcookie.extension & 0x7F] != NULL);
-}
-
-/**
- * Free all events in the event list.
- */
-void
-_XFreeEventCookies(Display *dpy)
-{
- struct stored_event **head, *e, *tmp;
-
- if (!dpy->cookiejar)
- return;
-
- head = (struct stored_event**)&dpy->cookiejar;
-
- DL_FOREACH_SAFE(*head, e, tmp) {
- if (dpy->cookiejar == e)
- dpy->cookiejar = NULL;
- XFree(e->ev.data);
- XFree(e);
- }
-}
-
-/**
- * Add an event to the display's event list. This event must be freed on the
- * next call to XNextEvent().
- */
-void
-_XStoreEventCookie(Display *dpy, XEvent *event)
-{
- XGenericEventCookie* cookie = &event->xcookie;
- struct stored_event **head, *add;
-
- if (!_XIsEventCookie(dpy, event))
- return;
-
- head = (struct stored_event**)(&dpy->cookiejar);
-
- add = Xmalloc(sizeof(struct stored_event));
- if (!add) {
- ESET(ENOMEM);
- _XIOError(dpy);
- }
- add->ev = *cookie;
- DL_APPEND(*head, add);
- cookie->data = NULL; /* don't return data yet, must be claimed */
-}
-
-/**
- * Return the event with the given cookie and remove it from the list.
- */
-Bool
-_XFetchEventCookie(Display *dpy, XGenericEventCookie* ev)
-{
- Bool ret = False;
- struct stored_event **head, *event;
- head = (struct stored_event**)&dpy->cookiejar;
-
- if (!_XIsEventCookie(dpy, (XEvent*)ev))
- return ret;
-
- DL_FOREACH(*head, event) {
- if (event->ev.cookie == ev->cookie &&
- event->ev.extension == ev->extension &&
- event->ev.evtype == ev->evtype) {
- *ev = event->ev;
- DL_DELETE(*head, event);
- Xfree(event);
- ret = True;
- break;
- }
- }
-
- return ret;
-}
-
-Bool
-_XCopyEventCookie(Display *dpy, XGenericEventCookie *in, XGenericEventCookie *out)
-{
- Bool ret = False;
- int extension;
-
- if (!_XIsEventCookie(dpy, (XEvent*)in) || !out)
- return ret;
-
- extension = in->extension & 0x7F;
-
- if (!dpy->generic_event_copy_vec[extension])
- return ret;
-
- ret = ((*dpy->generic_event_copy_vec[extension])(dpy, in, out));
- out->cookie = ret ? ++dpy->next_cookie : 0;
- return ret;
-}
-
-
-/*
- * _XEnq - Place event packets on the display's queue.
- * note that no squishing of move events in V11, since there
- * is pointer motion hints....
- */
-void _XEnq(
- register Display *dpy,
- register xEvent *event)
-{
- register _XQEvent *qelt;
- int type, extension;
-
- if ((qelt = dpy->qfree)) {
- /* If dpy->qfree is non-NULL do this, else malloc a new one. */
- dpy->qfree = qelt->next;
- }
- else if ((qelt =
- (_XQEvent *) Xmalloc((unsigned)sizeof(_XQEvent))) == NULL) {
- /* Malloc call failed! */
- ESET(ENOMEM);
- _XIOError(dpy);
- }
- qelt->next = NULL;
-
- type = event->u.u.type & 0177;
- extension = ((xGenericEvent*)event)->extension;
-
- qelt->event.type = type;
- /* If an extension has registerd a generic_event_vec handler, then
- * it can handle event cookies. Otherwise, proceed with the normal
- * event handlers.
- *
- * If the generic_event_vec is called, qelt->event is a event cookie
- * with the data pointer and the "free" pointer set. Data pointer is
- * some memory allocated by the extension.
- */
- if (type == GenericEvent && dpy->generic_event_vec[extension & 0x7F]) {
- XGenericEventCookie *cookie = &qelt->event.xcookie;
- (*dpy->generic_event_vec[extension & 0x7F])(dpy, cookie, event);
- cookie->cookie = ++dpy->next_cookie;
-
- qelt->qserial_num = dpy->next_event_serial_num++;
- if (dpy->tail) dpy->tail->next = qelt;
- else dpy->head = qelt;
-
- dpy->tail = qelt;
- dpy->qlen++;
- } else if ((*dpy->event_vec[type])(dpy, &qelt->event, event)) {
- qelt->qserial_num = dpy->next_event_serial_num++;
- if (dpy->tail) dpy->tail->next = qelt;
- else dpy->head = qelt;
-
- dpy->tail = qelt;
- dpy->qlen++;
- } else {
- /* ignored, or stashed away for many-to-one compression */
- qelt->next = dpy->qfree;
- dpy->qfree = qelt;
- }
-}
-
-/*
- * _XDeq - Remove event packet from the display's queue.
- */
-void _XDeq(
- register Display *dpy,
- register _XQEvent *prev, /* element before qelt */
- register _XQEvent *qelt) /* element to be unlinked */
-{
- if (prev) {
- if ((prev->next = qelt->next) == NULL)
- dpy->tail = prev;
- } else {
- /* no prev, so removing first elt */
- if ((dpy->head = qelt->next) == NULL)
- dpy->tail = NULL;
- }
- qelt->qserial_num = 0;
- qelt->next = dpy->qfree;
- dpy->qfree = qelt;
- dpy->qlen--;
-
- if (_XIsEventCookie(dpy, &qelt->event)) {
- XGenericEventCookie* cookie = &qelt->event.xcookie;
- /* dpy->qfree is re-used, reset memory to avoid double free on
- * _XFreeDisplayStructure */
- cookie->data = NULL;
- }
-}
-
-/*
- * EventToWire in separate file in that often not needed.
- */
-
-/*ARGSUSED*/
-Bool
-_XUnknownWireEvent(
- register Display *dpy, /* pointer to display structure */
- register XEvent *re, /* pointer to where event should be reformatted */
- register xEvent *event) /* wire protocol event */
-{
-#ifdef notdef
- (void) fprintf(stderr,
- "Xlib: unhandled wire event! event number = %d, display = %x\n.",
- event->u.u.type, dpy);
-#endif
- return(False);
-}
-
-Bool
-_XUnknownWireEventCookie(
- Display *dpy, /* pointer to display structure */
- XGenericEventCookie *re, /* pointer to where event should be reformatted */
- xEvent *event) /* wire protocol event */
-{
-#ifdef notdef
- fprintf(stderr,
- "Xlib: unhandled wire cookie event! extension number = %d, display = %x\n.",
- ((xGenericEvent*)event)->extension, dpy);
-#endif
- return(False);
-}
-
-Bool
-_XUnknownCopyEventCookie(
- Display *dpy, /* pointer to display structure */
- XGenericEventCookie *in, /* source */
- XGenericEventCookie *out) /* destination */
-{
-#ifdef notdef
- fprintf(stderr,
- "Xlib: unhandled cookie event copy! extension number = %d, display = %x\n.",
- in->extension, dpy);
-#endif
- return(False);
-}
-
-/*ARGSUSED*/
-Status
-_XUnknownNativeEvent(
- register Display *dpy, /* pointer to display structure */
- register XEvent *re, /* pointer to where event should be reformatted */
- register xEvent *event) /* wire protocol event */
-{
-#ifdef notdef
- (void) fprintf(stderr,
- "Xlib: unhandled native event! event number = %d, display = %x\n.",
- re->type, dpy);
-#endif
- return(0);
-}
-/*
- * reformat a wire event into an XEvent structure of the right type.
- */
-Bool
-_XWireToEvent(
- register Display *dpy, /* pointer to display structure */
- register XEvent *re, /* pointer to where event should be reformatted */
- register xEvent *event) /* wire protocol event */
-{
-
- re->type = event->u.u.type & 0x7f;
- ((XAnyEvent *)re)->serial = _XSetLastRequestRead(dpy,
- (xGenericReply *)event);
- ((XAnyEvent *)re)->send_event = ((event->u.u.type & 0x80) != 0);
- ((XAnyEvent *)re)->display = dpy;
-
- /* Ignore the leading bit of the event type since it is set when a
- client sends an event rather than the server. */
-
- switch (event-> u.u.type & 0177) {
- case KeyPress:
- case KeyRelease:
- {
- register XKeyEvent *ev = (XKeyEvent*) re;
- ev->root = event->u.keyButtonPointer.root;
- ev->window = event->u.keyButtonPointer.event;
- ev->subwindow = event->u.keyButtonPointer.child;
- ev->time = event->u.keyButtonPointer.time;
- ev->x = cvtINT16toInt(event->u.keyButtonPointer.eventX);
- ev->y = cvtINT16toInt(event->u.keyButtonPointer.eventY);
- ev->x_root = cvtINT16toInt(event->u.keyButtonPointer.rootX);
- ev->y_root = cvtINT16toInt(event->u.keyButtonPointer.rootY);
- ev->state = event->u.keyButtonPointer.state;
- ev->same_screen = event->u.keyButtonPointer.sameScreen;
- ev->keycode = event->u.u.detail;
- }
- break;
- case ButtonPress:
- case ButtonRelease:
- {
- register XButtonEvent *ev = (XButtonEvent *) re;
- ev->root = event->u.keyButtonPointer.root;
- ev->window = event->u.keyButtonPointer.event;
- ev->subwindow = event->u.keyButtonPointer.child;
- ev->time = event->u.keyButtonPointer.time;
- ev->x = cvtINT16toInt(event->u.keyButtonPointer.eventX);
- ev->y = cvtINT16toInt(event->u.keyButtonPointer.eventY);
- ev->x_root = cvtINT16toInt(event->u.keyButtonPointer.rootX);
- ev->y_root = cvtINT16toInt(event->u.keyButtonPointer.rootY);
- ev->state = event->u.keyButtonPointer.state;
- ev->same_screen = event->u.keyButtonPointer.sameScreen;
- ev->button = event->u.u.detail;
- }
- break;
- case MotionNotify:
- {
- register XMotionEvent *ev = (XMotionEvent *)re;
- ev->root = event->u.keyButtonPointer.root;
- ev->window = event->u.keyButtonPointer.event;
- ev->subwindow = event->u.keyButtonPointer.child;
- ev->time = event->u.keyButtonPointer.time;
- ev->x = cvtINT16toInt(event->u.keyButtonPointer.eventX);
- ev->y = cvtINT16toInt(event->u.keyButtonPointer.eventY);
- ev->x_root = cvtINT16toInt(event->u.keyButtonPointer.rootX);
- ev->y_root = cvtINT16toInt(event->u.keyButtonPointer.rootY);
- ev->state = event->u.keyButtonPointer.state;
- ev->same_screen = event->u.keyButtonPointer.sameScreen;
- ev->is_hint = event->u.u.detail;
- }
- break;
- case EnterNotify:
- case LeaveNotify:
- {
- register XCrossingEvent *ev = (XCrossingEvent *) re;
- ev->root = event->u.enterLeave.root;
- ev->window = event->u.enterLeave.event;
- ev->subwindow = event->u.enterLeave.child;
- ev->time = event->u.enterLeave.time;
- ev->x = cvtINT16toInt(event->u.enterLeave.eventX);
- ev->y = cvtINT16toInt(event->u.enterLeave.eventY);
- ev->x_root = cvtINT16toInt(event->u.enterLeave.rootX);
- ev->y_root = cvtINT16toInt(event->u.enterLeave.rootY);
- ev->state = event->u.enterLeave.state;
- ev->mode = event->u.enterLeave.mode;
- ev->same_screen = (event->u.enterLeave.flags &
- ELFlagSameScreen) && True;
- ev->focus = (event->u.enterLeave.flags &
- ELFlagFocus) && True;
- ev->detail = event->u.u.detail;
- }
- break;
- case FocusIn:
- case FocusOut:
- {
- register XFocusChangeEvent *ev = (XFocusChangeEvent *) re;
- ev->window = event->u.focus.window;
- ev->mode = event->u.focus.mode;
- ev->detail = event->u.u.detail;
- }
- break;
- case KeymapNotify:
- {
- register XKeymapEvent *ev = (XKeymapEvent *) re;
- ev->window = None;
- memcpy(&ev->key_vector[1],
- (char *)((xKeymapEvent *) event)->map,
- sizeof (((xKeymapEvent *) event)->map));
- }
- break;
- case Expose:
- {
- register XExposeEvent *ev = (XExposeEvent *) re;
- ev->window = event->u.expose.window;
- ev->x = event->u.expose.x;
- ev->y = event->u.expose.y;
- ev->width = event->u.expose.width;
- ev->height = event->u.expose.height;
- ev->count = event->u.expose.count;
- }
- break;
- case GraphicsExpose:
- {
- register XGraphicsExposeEvent *ev =
- (XGraphicsExposeEvent *) re;
- ev->drawable = event->u.graphicsExposure.drawable;
- ev->x = event->u.graphicsExposure.x;
- ev->y = event->u.graphicsExposure.y;
- ev->width = event->u.graphicsExposure.width;
- ev->height = event->u.graphicsExposure.height;
- ev->count = event->u.graphicsExposure.count;
- ev->major_code = event->u.graphicsExposure.majorEvent;
- ev->minor_code = event->u.graphicsExposure.minorEvent;
- }
- break;
- case NoExpose:
- {
- register XNoExposeEvent *ev = (XNoExposeEvent *) re;
- ev->drawable = event->u.noExposure.drawable;
- ev->major_code = event->u.noExposure.majorEvent;
- ev->minor_code = event->u.noExposure.minorEvent;
- }
- break;
- case VisibilityNotify:
- {
- register XVisibilityEvent *ev = (XVisibilityEvent *) re;
- ev->window = event->u.visibility.window;
- ev->state = event->u.visibility.state;
- }
- break;
- case CreateNotify:
- {
- register XCreateWindowEvent *ev =
- (XCreateWindowEvent *) re;
- ev->window = event->u.createNotify.window;
- ev->parent = event->u.createNotify.parent;
- ev->x = cvtINT16toInt(event->u.createNotify.x);
- ev->y = cvtINT16toInt(event->u.createNotify.y);
- ev->width = event->u.createNotify.width;
- ev->height = event->u.createNotify.height;
- ev->border_width = event->u.createNotify.borderWidth;
- ev->override_redirect = event->u.createNotify.override;
- }
- break;
- case DestroyNotify:
- {
- register XDestroyWindowEvent *ev =
- (XDestroyWindowEvent *) re;
- ev->window = event->u.destroyNotify.window;
- ev->event = event->u.destroyNotify.event;
- }
- break;
- case UnmapNotify:
- {
- register XUnmapEvent *ev = (XUnmapEvent *) re;
- ev->window = event->u.unmapNotify.window;
- ev->event = event->u.unmapNotify.event;
- ev->from_configure = event->u.unmapNotify.fromConfigure;
- }
- break;
- case MapNotify:
- {
- register XMapEvent *ev = (XMapEvent *) re;
- ev->window = event->u.mapNotify.window;
- ev->event = event->u.mapNotify.event;
- ev->override_redirect = event->u.mapNotify.override;
- }
- break;
- case MapRequest:
- {
- register XMapRequestEvent *ev = (XMapRequestEvent *) re;
- ev->window = event->u.mapRequest.window;
- ev->parent = event->u.mapRequest.parent;
- }
- break;
- case ReparentNotify:
- {
- register XReparentEvent *ev = (XReparentEvent *) re;
- ev->event = event->u.reparent.event;
- ev->window = event->u.reparent.window;
- ev->parent = event->u.reparent.parent;
- ev->x = cvtINT16toInt(event->u.reparent.x);
- ev->y = cvtINT16toInt(event->u.reparent.y);
- ev->override_redirect = event->u.reparent.override;
- }
- break;
- case ConfigureNotify:
- {
- register XConfigureEvent *ev = (XConfigureEvent *) re;
- ev->event = event->u.configureNotify.event;
- ev->window = event->u.configureNotify.window;
- ev->above = event->u.configureNotify.aboveSibling;
- ev->x = cvtINT16toInt(event->u.configureNotify.x);
- ev->y = cvtINT16toInt(event->u.configureNotify.y);
- ev->width = event->u.configureNotify.width;
- ev->height = event->u.configureNotify.height;
- ev->border_width = event->u.configureNotify.borderWidth;
- ev->override_redirect = event->u.configureNotify.override;
- }
- break;
- case ConfigureRequest:
- {
- register XConfigureRequestEvent *ev =
- (XConfigureRequestEvent *) re;
- ev->window = event->u.configureRequest.window;
- ev->parent = event->u.configureRequest.parent;
- ev->above = event->u.configureRequest.sibling;
- ev->x = cvtINT16toInt(event->u.configureRequest.x);
- ev->y = cvtINT16toInt(event->u.configureRequest.y);
- ev->width = event->u.configureRequest.width;
- ev->height = event->u.configureRequest.height;
- ev->border_width = event->u.configureRequest.borderWidth;
- ev->value_mask = event->u.configureRequest.valueMask;
- ev->detail = event->u.u.detail;
- }
- break;
- case GravityNotify:
- {
- register XGravityEvent *ev = (XGravityEvent *) re;
- ev->window = event->u.gravity.window;
- ev->event = event->u.gravity.event;
- ev->x = cvtINT16toInt(event->u.gravity.x);
- ev->y = cvtINT16toInt(event->u.gravity.y);
- }
- break;
- case ResizeRequest:
- {
- register XResizeRequestEvent *ev =
- (XResizeRequestEvent *) re;
- ev->window = event->u.resizeRequest.window;
- ev->width = event->u.resizeRequest.width;
- ev->height = event->u.resizeRequest.height;
- }
- break;
- case CirculateNotify:
- {
- register XCirculateEvent *ev = (XCirculateEvent *) re;
- ev->window = event->u.circulate.window;
- ev->event = event->u.circulate.event;
- ev->place = event->u.circulate.place;
- }
- break;
- case CirculateRequest:
- {
- register XCirculateRequestEvent *ev =
- (XCirculateRequestEvent *) re;
- ev->window = event->u.circulate.window;
- ev->parent = event->u.circulate.event;
- ev->place = event->u.circulate.place;
- }
- break;
- case PropertyNotify:
- {
- register XPropertyEvent *ev = (XPropertyEvent *) re;
- ev->window = event->u.property.window;
- ev->atom = event->u.property.atom;
- ev->time = event->u.property.time;
- ev->state = event->u.property.state;
- }
- break;
- case SelectionClear:
- {
- register XSelectionClearEvent *ev =
- (XSelectionClearEvent *) re;
- ev->window = event->u.selectionClear.window;
- ev->selection = event->u.selectionClear.atom;
- ev->time = event->u.selectionClear.time;
- }
- break;
- case SelectionRequest:
- {
- register XSelectionRequestEvent *ev =
- (XSelectionRequestEvent *) re;
- ev->owner = event->u.selectionRequest.owner;
- ev->requestor = event->u.selectionRequest.requestor;
- ev->selection = event->u.selectionRequest.selection;
- ev->target = event->u.selectionRequest.target;
- ev->property = event->u.selectionRequest.property;
- ev->time = event->u.selectionRequest.time;
- }
- break;
- case SelectionNotify:
- {
- register XSelectionEvent *ev = (XSelectionEvent *) re;
- ev->requestor = event->u.selectionNotify.requestor;
- ev->selection = event->u.selectionNotify.selection;
- ev->target = event->u.selectionNotify.target;
- ev->property = event->u.selectionNotify.property;
- ev->time = event->u.selectionNotify.time;
- }
- break;
- case ColormapNotify:
- {
- register XColormapEvent *ev = (XColormapEvent *) re;
- ev->window = event->u.colormap.window;
- ev->colormap = event->u.colormap.colormap;
- ev->new = event->u.colormap.new;
- ev->state = event->u.colormap.state;
- }
- break;
- case ClientMessage:
- {
- register int i;
- register XClientMessageEvent *ev
- = (XClientMessageEvent *) re;
- ev->window = event->u.clientMessage.window;
- ev->format = event->u.u.detail;
- switch (ev->format) {
- case 8:
- ev->message_type = event->u.clientMessage.u.b.type;
- for (i = 0; i < 20; i++)
- ev->data.b[i] = event->u.clientMessage.u.b.bytes[i];
- break;
- case 16:
- ev->message_type = event->u.clientMessage.u.s.type;
- ev->data.s[0] = cvtINT16toShort(event->u.clientMessage.u.s.shorts0);
- ev->data.s[1] = cvtINT16toShort(event->u.clientMessage.u.s.shorts1);
- ev->data.s[2] = cvtINT16toShort(event->u.clientMessage.u.s.shorts2);
- ev->data.s[3] = cvtINT16toShort(event->u.clientMessage.u.s.shorts3);
- ev->data.s[4] = cvtINT16toShort(event->u.clientMessage.u.s.shorts4);
- ev->data.s[5] = cvtINT16toShort(event->u.clientMessage.u.s.shorts5);
- ev->data.s[6] = cvtINT16toShort(event->u.clientMessage.u.s.shorts6);
- ev->data.s[7] = cvtINT16toShort(event->u.clientMessage.u.s.shorts7);
- ev->data.s[8] = cvtINT16toShort(event->u.clientMessage.u.s.shorts8);
- ev->data.s[9] = cvtINT16toShort(event->u.clientMessage.u.s.shorts9);
- break;
- case 32:
- ev->message_type = event->u.clientMessage.u.l.type;
- ev->data.l[0] = cvtINT32toLong(event->u.clientMessage.u.l.longs0);
- ev->data.l[1] = cvtINT32toLong(event->u.clientMessage.u.l.longs1);
- ev->data.l[2] = cvtINT32toLong(event->u.clientMessage.u.l.longs2);
- ev->data.l[3] = cvtINT32toLong(event->u.clientMessage.u.l.longs3);
- ev->data.l[4] = cvtINT32toLong(event->u.clientMessage.u.l.longs4);
- break;
- default: /* XXX should never occur */
- break;
- }
- }
- break;
- case MappingNotify:
- {
- register XMappingEvent *ev = (XMappingEvent *)re;
- ev->window = 0;
- ev->first_keycode = event->u.mappingNotify.firstKeyCode;
- ev->request = event->u.mappingNotify.request;
- ev->count = event->u.mappingNotify.count;
- }
- break;
- default:
- return(_XUnknownWireEvent(dpy, re, event));
- }
- return(True);
-}
-
-
-/*
- * _XDefaultIOError - Default fatal system error reporting routine. Called
- * when an X internal system error is encountered.
- */
-int _XDefaultIOError(
- Display *dpy)
-{
- if (ECHECK(EPIPE)) {
- (void) fprintf (stderr,
- "X connection to %s broken (explicit kill or server shutdown).\r\n",
- DisplayString (dpy));
- } else {
- (void) fprintf (stderr,
- "XIO: fatal IO error %d (%s) on X server \"%s\"\r\n",
-#ifdef WIN32
- WSAGetLastError(), strerror(WSAGetLastError()),
-#else
- errno, strerror (errno),
-#endif
- DisplayString (dpy));
- (void) fprintf (stderr,
- " after %lu requests (%lu known processed) with %d events remaining.\r\n",
- NextRequest(dpy) - 1, LastKnownRequestProcessed(dpy),
- QLength(dpy));
-
- }
- exit(1);
- return(0); /* dummy - function should never return */
-}
-
-
-static int _XPrintDefaultError(
- Display *dpy,
- XErrorEvent *event,
- FILE *fp)
-{
- char buffer[BUFSIZ];
- char mesg[BUFSIZ];
- char number[32];
- const char *mtype = "XlibMessage";
- register _XExtension *ext = (_XExtension *)NULL;
- _XExtension *bext = (_XExtension *)NULL;
- XGetErrorText(dpy, event->error_code, buffer, BUFSIZ);
- XGetErrorDatabaseText(dpy, mtype, "XError", "X Error", mesg, BUFSIZ);
- (void) fprintf(fp, "%s: %s\n ", mesg, buffer);
- XGetErrorDatabaseText(dpy, mtype, "MajorCode", "Request Major code %d",
- mesg, BUFSIZ);
- (void) fprintf(fp, mesg, event->request_code);
- if (event->request_code < 128) {
- sprintf(number, "%d", event->request_code);
- XGetErrorDatabaseText(dpy, "XRequest", number, "", buffer, BUFSIZ);
- } else {
- for (ext = dpy->ext_procs;
- ext && (ext->codes.major_opcode != event->request_code);
- ext = ext->next)
- ;
- if (ext) {
- strncpy(buffer, ext->name, BUFSIZ);
- buffer[BUFSIZ - 1] = '\0';
- } else
- buffer[0] = '\0';
- }
- (void) fprintf(fp, " (%s)\n", buffer);
- if (event->request_code >= 128) {
- XGetErrorDatabaseText(dpy, mtype, "MinorCode", "Request Minor code %d",
- mesg, BUFSIZ);
- fputs(" ", fp);
- (void) fprintf(fp, mesg, event->minor_code);
- if (ext) {
- sprintf(mesg, "%s.%d", ext->name, event->minor_code);
- XGetErrorDatabaseText(dpy, "XRequest", mesg, "", buffer, BUFSIZ);
- (void) fprintf(fp, " (%s)", buffer);
- }
- fputs("\n", fp);
- }
- if (event->error_code >= 128) {
- /* kludge, try to find the extension that caused it */
- buffer[0] = '\0';
- for (ext = dpy->ext_procs; ext; ext = ext->next) {
- if (ext->error_string)
- (*ext->error_string)(dpy, event->error_code, &ext->codes,
- buffer, BUFSIZ);
- if (buffer[0]) {
- bext = ext;
- break;
- }
- if (ext->codes.first_error &&
- ext->codes.first_error < (int)event->error_code &&
- (!bext || ext->codes.first_error > bext->codes.first_error))
- bext = ext;
- }
- if (bext)
- sprintf(buffer, "%s.%d", bext->name,
- event->error_code - bext->codes.first_error);
- else
- strcpy(buffer, "Value");
- XGetErrorDatabaseText(dpy, mtype, buffer, "", mesg, BUFSIZ);
- if (mesg[0]) {
- fputs(" ", fp);
- (void) fprintf(fp, mesg, event->resourceid);
- fputs("\n", fp);
- }
- /* let extensions try to print the values */
- for (ext = dpy->ext_procs; ext; ext = ext->next) {
- if (ext->error_values)
- (*ext->error_values)(dpy, event, fp);
- }
- } else if ((event->error_code == BadWindow) ||
- (event->error_code == BadPixmap) ||
- (event->error_code == BadCursor) ||
- (event->error_code == BadFont) ||
- (event->error_code == BadDrawable) ||
- (event->error_code == BadColor) ||
- (event->error_code == BadGC) ||
- (event->error_code == BadIDChoice) ||
- (event->error_code == BadValue) ||
- (event->error_code == BadAtom)) {
- if (event->error_code == BadValue)
- XGetErrorDatabaseText(dpy, mtype, "Value", "Value 0x%x",
- mesg, BUFSIZ);
- else if (event->error_code == BadAtom)
- XGetErrorDatabaseText(dpy, mtype, "AtomID", "AtomID 0x%x",
- mesg, BUFSIZ);
- else
- XGetErrorDatabaseText(dpy, mtype, "ResourceID", "ResourceID 0x%x",
- mesg, BUFSIZ);
- fputs(" ", fp);
- (void) fprintf(fp, mesg, event->resourceid);
- fputs("\n", fp);
- }
- XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d",
- mesg, BUFSIZ);
- fputs(" ", fp);
- (void) fprintf(fp, mesg, event->serial);
- XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%d",
- mesg, BUFSIZ);
- fputs("\n ", fp);
- (void) fprintf(fp, mesg, dpy->request);
- fputs("\n", fp);
- if (event->error_code == BadImplementation) return 0;
- return 1;
-}
-
-int _XDefaultError(
- Display *dpy,
- XErrorEvent *event)
-{
- if (_XPrintDefaultError (dpy, event, stderr) == 0) return 0;
- exit(1);
- /*NOTREACHED*/
-}
-
-/*ARGSUSED*/
-Bool _XDefaultWireError(Display *display, XErrorEvent *he, xError *we)
-{
- return True;
-}
-
-/*
- * _XError - upcall internal or user protocol error handler
- */
-int _XError (
- Display *dpy,
- register xError *rep)
-{
- /*
- * X_Error packet encountered! We need to unpack the error before
- * giving it to the user.
- */
- XEvent event; /* make it a large event */
- register _XAsyncHandler *async, *next;
-
- event.xerror.serial = _XSetLastRequestRead(dpy, (xGenericReply *)rep);
-
- for (async = dpy->async_handlers; async; async = next) {
- next = async->next;
- if ((*async->handler)(dpy, (xReply *)rep,
- (char *)rep, SIZEOF(xError), async->data))
- return 0;
- }
-
- event.xerror.display = dpy;
- event.xerror.type = X_Error;
- event.xerror.resourceid = rep->resourceID;
- event.xerror.error_code = rep->errorCode;
- event.xerror.request_code = rep->majorCode;
- event.xerror.minor_code = rep->minorCode;
- if (dpy->error_vec &&
- !(*dpy->error_vec[rep->errorCode])(dpy, &event.xerror, rep))
- return 0;
- if (_XErrorFunction != NULL) {
- int rtn_val;
-#ifdef XTHREADS
- if (dpy->lock)
- (*dpy->lock->user_lock_display)(dpy);
- UnlockDisplay(dpy);
-#endif
- rtn_val = (*_XErrorFunction)(dpy, (XErrorEvent *)&event); /* upcall */
-#ifdef XTHREADS
- LockDisplay(dpy);
- if (dpy->lock)
- (*dpy->lock->user_unlock_display)(dpy);
-#endif
- return rtn_val;
- } else {
- return _XDefaultError(dpy, (XErrorEvent *)&event);
- }
-}
-
-/*
- * _XIOError - call user connection error handler and exit
- */
-int
-_XIOError (
- Display *dpy)
-{
- dpy->flags |= XlibDisplayIOError;
-#ifdef WIN32
- errno = WSAGetLastError();
-#endif
-
- /* This assumes that the thread calling exit will call any atexit handlers.
- * If this does not hold, then an alternate solution would involve
- * registering an atexit handler to take over the lock, which would only
- * assume that the same thread calls all the atexit handlers. */
-#ifdef XTHREADS
- if (dpy->lock)
- (*dpy->lock->user_lock_display)(dpy);
-#endif
- UnlockDisplay(dpy);
-
- if (_XIOErrorFunction != NULL)
- (*_XIOErrorFunction)(dpy);
- else
- _XDefaultIOError(dpy);
- exit (1);
- return 0;
-}
-
-
-/*
- * This routine can be used to (cheaply) get some memory within a single
- * Xlib routine for scratch space. A single buffer is reused each time
- * if possible. To be MT safe, you can only call this between a call to
- * GetReq* and a call to Data* or _XSend*, or in a context when the thread
- * is guaranteed to not unlock the display.
- */
-char *_XAllocScratch(
- register Display *dpy,
- unsigned long nbytes)
-{
- if (nbytes > dpy->scratch_length) {
- if (dpy->scratch_buffer) Xfree (dpy->scratch_buffer);
- if ((dpy->scratch_buffer = Xmalloc((unsigned) nbytes)))
- dpy->scratch_length = nbytes;
- else dpy->scratch_length = 0;
- }
- return (dpy->scratch_buffer);
-}
-
-/*
- * Scratch space allocator you can call any time, multiple times, and be
- * MT safe, but you must hand the buffer back with _XFreeTemp.
- */
-char *_XAllocTemp(
- register Display *dpy,
- unsigned long nbytes)
-{
- char *buf;
-
- buf = _XAllocScratch(dpy, nbytes);
- dpy->scratch_buffer = NULL;
- dpy->scratch_length = 0;
- return buf;
-}
-
-void _XFreeTemp(
- register Display *dpy,
- char *buf,
- unsigned long nbytes)
-{
- if (dpy->scratch_buffer)
- Xfree(dpy->scratch_buffer);
- dpy->scratch_buffer = buf;
- dpy->scratch_length = nbytes;
-}
-
-/*
- * Given a visual id, find the visual structure for this id on this display.
- */
-Visual *_XVIDtoVisual(
- Display *dpy,
- VisualID id)
-{
- register int i, j, k;
- register Screen *sp;
- register Depth *dp;
- register Visual *vp;
- for (i = 0; i < dpy->nscreens; i++) {
- sp = &dpy->screens[i];
- for (j = 0; j < sp->ndepths; j++) {
- dp = &sp->depths[j];
- /* if nvisuals == 0 then visuals will be NULL */
- for (k = 0; k < dp->nvisuals; k++) {
- vp = &dp->visuals[k];
- if (vp->visualid == id) return (vp);
- }
- }
- }
- return (NULL);
-}
-
-int
-XFree (void *data)
-{
- Xfree (data);
- return 1;
-}
-
-#ifdef _XNEEDBCOPYFUNC
-void _Xbcopy(b1, b2, length)
- register char *b1, *b2;
- register length;
-{
- if (b1 < b2) {
- b2 += length;
- b1 += length;
- while (length--)
- *--b2 = *--b1;
- } else {
- while (length--)
- *b2++ = *b1++;
- }
-}
-#endif
-
-#ifdef DataRoutineIsProcedure
-void Data(
- Display *dpy,
- char *data,
- long len)
-{
- if (dpy->bufptr + (len) <= dpy->bufmax) {
- memcpy(dpy->bufptr, data, (int)len);
- dpy->bufptr += ((len) + 3) & ~3;
- } else {
- _XSend(dpy, data, len);
- }
-}
-#endif /* DataRoutineIsProcedure */
-
-
-#ifdef LONG64
-int
-_XData32(
- Display *dpy,
- register long *data,
- unsigned len)
-{
- register int *buf;
- register long i;
-
- while (len) {
- buf = (int *)dpy->bufptr;
- i = dpy->bufmax - (char *)buf;
- if (!i) {
- _XFlush(dpy);
- continue;
- }
- if (len < i)
- i = len;
- dpy->bufptr = (char *)buf + i;
- len -= i;
- i >>= 2;
- while (--i >= 0)
- *buf++ = *data++;
- }
- return 0;
-}
-#endif /* LONG64 */
-
-#ifdef WORD64
-
-/*
- * XXX This is a *really* stupid way of doing this. It should just use
- * dpy->bufptr directly, taking into account where in the word it is.
- */
-
-/*
- * Data16 - Place 16 bit data in the buffer.
- *
- * "dpy" is a pointer to a Display.
- * "data" is a pointer to the data.
- * "len" is the length in bytes of the data.
- */
-
-static doData16(
- register Display *dpy,
- short *data,
- unsigned len,
- char *packbuffer)
-{
- long *lp,*lpack;
- long i, nwords,bits;
- long mask16 = 0x000000000000ffff;
-
- lp = (long *)data;
- lpack = (long *)packbuffer;
-
-/* nwords is the number of 16 bit values to be packed,
- * the low order 16 bits of each word will be packed
- * into 64 bit words
- */
- nwords = len >> 1;
- bits = 48;
-
- for(i=0;i<nwords;i++){
- if (bits == 48) *lpack = 0;
- *lpack ^= (*lp & mask16) << bits;
- bits -= 16 ;
- lp++;
- if(bits < 0){
- lpack++;
- bits = 48;
- }
- }
- Data(dpy, packbuffer, len);
-}
-
-_XData16 (
- Display *dpy,
- short *data,
- unsigned len)
-{
- char packbuffer[PACKBUFFERSIZE];
- unsigned nunits = PACKBUFFERSIZE >> 1;
-
- for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) {
- doData16 (dpy, data, PACKBUFFERSIZE, packbuffer);
- }
- if (len) doData16 (dpy, data, len, packbuffer);
-}
-
-/*
- * Data32 - Place 32 bit data in the buffer.
- *
- * "dpy" is a pointer to a Display.
- * "data" is a pointer to the data.
- * "len" is the length in bytes of the data.
- */
-
-static doData32(
- register Display *dpy
- long *data,
- unsigned len,
- char *packbuffer)
-{
- long *lp,*lpack;
- long i,bits,nwords;
- long mask32 = 0x00000000ffffffff;
-
- lpack = (long *) packbuffer;
- lp = data;
-
-/* nwords is the number of 32 bit values to be packed
- * the low order 32 bits of each word will be packed
- * into 64 bit words
- */
- nwords = len >> 2;
- bits = 32;
-
- for(i=0;i<nwords;i++){
- if (bits == 32) *lpack = 0;
- *lpack ^= (*lp & mask32) << bits;
- bits = bits ^32;
- lp++;
- if(bits)
- lpack++;
- }
- Data(dpy, packbuffer, len);
-}
-
-void _XData32(
- Display *dpy,
- long *data,
- unsigned len)
-{
- char packbuffer[PACKBUFFERSIZE];
- unsigned nunits = PACKBUFFERSIZE >> 2;
-
- for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) {
- doData32 (dpy, data, PACKBUFFERSIZE, packbuffer);
- }
- if (len) doData32 (dpy, data, len, packbuffer);
-}
-
-#endif /* WORD64 */
-
-
-/* Make sure this produces the same string as DefineLocal/DefineSelf in xdm.
- * Otherwise, Xau will not be able to find your cookies in the Xauthority file.
- *
- * Note: POSIX says that the ``nodename'' member of utsname does _not_ have
- * to have sufficient information for interfacing to the network,
- * and so, you may be better off using gethostname (if it exists).
- */
-
-#if (defined(_POSIX_SOURCE) && !defined(AIXV3) && !defined(__QNX__)) || defined(hpux) || defined(SVR4)
-#define NEED_UTSNAME
-#include <sys/utsname.h>
-#else
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#endif
-
-/*
- * _XGetHostname - similar to gethostname but allows special processing.
- */
-int _XGetHostname (
- char *buf,
- int maxlen)
-{
- int len;
-
-#ifdef NEED_UTSNAME
- struct utsname name;
-
- if (maxlen <= 0 || buf == NULL)
- return 0;
-
- uname (&name);
- len = strlen (name.nodename);
- if (len >= maxlen) len = maxlen - 1;
- strncpy (buf, name.nodename, len);
- buf[len] = '\0';
-#else
- if (maxlen <= 0 || buf == NULL)
- return 0;
-
- buf[0] = '\0';
- (void) gethostname (buf, maxlen);
- buf [maxlen - 1] = '\0';
- len = strlen(buf);
-#endif /* NEED_UTSNAME */
- return len;
-}
-
-
-/*
- * _XScreenOfWindow - get the Screen of a given window
- */
-
-Screen *_XScreenOfWindow(Display *dpy, Window w)
-{
- register int i;
- Window root;
- int x, y; /* dummy variables */
- unsigned int width, height, bw, depth; /* dummy variables */
-
- if (XGetGeometry (dpy, w, &root, &x, &y, &width, &height,
- &bw, &depth) == False) {
- return NULL;
- }
- for (i = 0; i < ScreenCount (dpy); i++) { /* find root from list */
- if (root == RootWindow (dpy, i)) {
- return ScreenOfDisplay (dpy, i);
- }
- }
- return NULL;
-}
-
-
-#if defined(WIN32)
-
-/*
- * These functions are intended to be used internally to Xlib only.
- * These functions will always prefix the path with a DOS drive in the
- * form "<drive-letter>:". As such, these functions are only suitable
- * for use by Xlib function that supply a root-based path to some
- * particular file, e.g. <ProjectRoot>/lib/X11/locale/locale.dir will
- * be converted to "C:/usr/X11R6.3/lib/X11/locale/locale.dir".
- */
-
-static int access_file (path, pathbuf, len_pathbuf, pathret)
- char* path;
- char* pathbuf;
- int len_pathbuf;
- char** pathret;
-{
- if (access (path, F_OK) == 0) {
- if (strlen (path) < len_pathbuf)
- *pathret = pathbuf;
- else
- *pathret = Xmalloc (strlen (path) + 1);
- if (*pathret) {
- strcpy (*pathret, path);
- return 1;
- }
- }
- return 0;
-}
-
-static int AccessFile (path, pathbuf, len_pathbuf, pathret)
- char* path;
- char* pathbuf;
- int len_pathbuf;
- char** pathret;
-{
- unsigned long drives;
- int i, len;
- char* drive;
- char buf[MAX_PATH];
- char* bufp;
-
- /* just try the "raw" name first and see if it works */
- if (access_file (path, pathbuf, len_pathbuf, pathret))
- return 1;
-
- /* try the places set in the environment */
- drive = getenv ("_XBASEDRIVE");
-#ifdef __UNIXOS2__
- if (!drive)
- drive = getenv ("X11ROOT");
-#endif
- if (!drive)
- drive = "C:";
- len = strlen (drive) + strlen (path);
- if (len < MAX_PATH) bufp = buf;
- else bufp = Xmalloc (len + 1);
- strcpy (bufp, drive);
- strcat (bufp, path);
- if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
- if (bufp != buf) Xfree (bufp);
- return 1;
- }
-
-#ifndef __UNIXOS2__
- /* one last place to look */
- drive = getenv ("HOMEDRIVE");
- if (drive) {
- len = strlen (drive) + strlen (path);
- if (len < MAX_PATH) bufp = buf;
- else bufp = Xmalloc (len + 1);
- strcpy (bufp, drive);
- strcat (bufp, path);
- if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
- if (bufp != buf) Xfree (bufp);
- return 1;
- }
- }
-
- /* tried everywhere else, go fishing */
-#define C_DRIVE ('C' - 'A')
-#define Z_DRIVE ('Z' - 'A')
- /* does OS/2 (with or with gcc-emx) have getdrives? */
- drives = _getdrives ();
- for (i = C_DRIVE; i <= Z_DRIVE; i++) { /* don't check on A: or B: */
- if ((1 << i) & drives) {
- len = 2 + strlen (path);
- if (len < MAX_PATH) bufp = buf;
- else bufp = Xmalloc (len + 1);
- *bufp = 'A' + i;
- *(bufp + 1) = ':';
- *(bufp + 2) = '\0';
- strcat (bufp, path);
- if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
- if (bufp != buf) Xfree (bufp);
- return 1;
- }
- }
- }
-#endif
- return 0;
-}
-
-int _XOpenFile(path, flags)
- _Xconst char* path;
- int flags;
-{
- char buf[MAX_PATH];
- char* bufp = NULL;
- int ret = -1;
- UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
-
- if (AccessFile (path, buf, MAX_PATH, &bufp))
- ret = open (bufp, flags);
-
- (void) SetErrorMode (olderror);
-
- if (bufp != buf) Xfree (bufp);
-
- return ret;
-}
-
-int _XOpenFileMode(path, flags, mode)
- _Xconst char* path;
- int flags;
- mode_t mode;
-{
- char buf[MAX_PATH];
- char* bufp = NULL;
- int ret = -1;
- UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
-
- if (AccessFile (path, buf, MAX_PATH, &bufp))
- ret = open (bufp, flags, mode);
-
- (void) SetErrorMode (olderror);
-
- if (bufp != buf) Xfree (bufp);
-
- return ret;
-}
-
-void* _XFopenFile(path, mode)
- _Xconst char* path;
- _Xconst char* mode;
-{
- char buf[MAX_PATH];
- char* bufp = NULL;
- void* ret = NULL;
- UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
-
- if (AccessFile (path, buf, MAX_PATH, &bufp))
- ret = fopen (bufp, mode);
-
- (void) SetErrorMode (olderror);
-
- if (bufp != buf) Xfree (bufp);
-
- return ret;
-}
-
-int _XAccessFile(path)
- _Xconst char* path;
-{
- char buf[MAX_PATH];
- char* bufp;
- int ret = -1;
- UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
-
- ret = AccessFile (path, buf, MAX_PATH, &bufp);
-
- (void) SetErrorMode (olderror);
-
- if (bufp != buf) Xfree (bufp);
-
- return ret;
-}
-
-#endif
-
-#ifdef WIN32
-#undef _Xdebug
-int _Xdebug = 0;
-int *_Xdebug_p = &_Xdebug;
-void (**_XCreateMutex_fn_p)(LockInfoPtr) = &_XCreateMutex_fn;
-void (**_XFreeMutex_fn_p)(LockInfoPtr) = &_XFreeMutex_fn;
-void (**_XLockMutex_fn_p)(LockInfoPtr
-#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
- , char * /* file */
- , int /* line */
-#endif
- ) = &_XLockMutex_fn;
-void (**_XUnlockMutex_fn_p)(LockInfoPtr
-#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
- , char * /* file */
- , int /* line */
-#endif
- ) = &_XUnlockMutex_fn;
-LockInfoPtr *_Xglobal_lock_p = &_Xglobal_lock;
-#endif
+/* + +Copyright 1985, 1986, 1987, 1998 The Open Group + +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. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +/* + * XlibInt.c - Internal support routines for the C subroutine + * interface library (Xlib) to the X Window System Protocol V11.0. + */ + +#ifdef WIN32 +#define _XLIBINT_ +#include <X11\Xw32defs.h> +#endif +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include "Xlibint.h" +#include "Xprivate.h" +#include <X11/Xpoll.h> +#include <assert.h> +#include <stdio.h> +#ifdef WIN32 +#include <direct.h> +#endif + +#ifdef XTHREADS +#include "locking.h" + +/* these pointers get initialized by XInitThreads */ +LockInfoPtr _Xglobal_lock = NULL; +void (*_XCreateMutex_fn)(LockInfoPtr) = NULL; +/* struct _XCVList *(*_XCreateCVL_fn)() = NULL; */ +void (*_XFreeMutex_fn)(LockInfoPtr) = NULL; +void (*_XLockMutex_fn)( + LockInfoPtr /* lock */ +#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE) + , char * /* file */ + , int /* line */ +#endif + ) = NULL; +void (*_XUnlockMutex_fn)( + LockInfoPtr /* lock */ +#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE) + , char * /* file */ + , int /* line */ +#endif + ) = NULL; +xthread_t (*_Xthread_self_fn)(void) = NULL; + +#define XThread_Self() ((*_Xthread_self_fn)()) + +#endif /* XTHREADS */ + +/* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX + * systems are broken and return EWOULDBLOCK when they should return EAGAIN + */ +#ifdef WIN32 +#define ETEST() (WSAGetLastError() == WSAEWOULDBLOCK) +#else +#ifdef __CYGWIN__ /* Cygwin uses ENOBUFS to signal socket is full */ +#define ETEST() (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS) +#else +#if defined(EAGAIN) && defined(EWOULDBLOCK) +#define ETEST() (errno == EAGAIN || errno == EWOULDBLOCK) +#else +#ifdef EAGAIN +#define ETEST() (errno == EAGAIN) +#else +#define ETEST() (errno == EWOULDBLOCK) +#endif /* EAGAIN */ +#endif /* EAGAIN && EWOULDBLOCK */ +#endif /* __CYGWIN__ */ +#endif /* WIN32 */ + +#ifdef WIN32 +#define ECHECK(err) (WSAGetLastError() == err) +#define ESET(val) WSASetLastError(val) +#else +#ifdef __UNIXOS2__ +#define ECHECK(err) (errno == err) +#define ESET(val) +#else +#define ECHECK(err) (errno == err) +#define ESET(val) errno = val +#endif +#endif + +#if defined(LOCALCONN) || defined(LACHMAN) +#ifdef EMSGSIZE +#define ESZTEST() (ECHECK(EMSGSIZE) || ECHECK(ERANGE)) +#else +#define ESZTEST() ECHECK(ERANGE) +#endif +#else +#ifdef EMSGSIZE +#define ESZTEST() ECHECK(EMSGSIZE) +#endif +#endif + +#ifdef __UNIXOS2__ +#include <limits.h> +#define MAX_PATH _POSIX_PATH_MAX +#endif + +/* + * The following routines are internal routines used by Xlib for protocol + * packet transmission and reception. + * + * _XIOError(Display *) will be called if any sort of system call error occurs. + * This is assumed to be a fatal condition, i.e., XIOError should not return. + * + * _XError(Display *, xError *) will be called whenever an X_Error event is + * received. This is not assumed to be a fatal condition, i.e., it is + * acceptable for this procedure to return. However, XError should NOT + * perform any operations (directly or indirectly) on the DISPLAY. + * + * Routines declared with a return type of 'Status' return 0 on failure, + * and non 0 on success. Routines with no declared return type don't + * return anything. Whenever possible routines that create objects return + * the object they have created. + */ + +#define POLLFD_CACHE_SIZE 5 + +#if _WIN32_WINNT < _WIN32_WINNT_VISTA +struct pollfd { + + SOCKET fd; + SHORT events; + SHORT revents; + +}; +#define POLLRDNORM 0x0100 +#define POLLRDBAND 0x0200 +#define POLLIN (POLLRDNORM | POLLRDBAND) +#endif + +/* initialize the struct array passed to poll() below */ +Bool _XPollfdCacheInit( + Display *dpy) +{ +#ifdef USE_POLL + struct pollfd *pfp; + + pfp = (struct pollfd *)Xmalloc(POLLFD_CACHE_SIZE * sizeof(struct pollfd)); + if (!pfp) + return False; + pfp[0].fd = dpy->fd; + pfp[0].events = POLLIN; + + dpy->filedes = (XPointer)pfp; +#endif + return True; +} + +void _XPollfdCacheAdd( + Display *dpy, + int fd) +{ +#ifdef USE_POLL + struct pollfd *pfp = (struct pollfd *)dpy->filedes; + + if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) { + pfp[dpy->im_fd_length].fd = fd; + pfp[dpy->im_fd_length].events = POLLIN; + } +#endif +} + +/* ARGSUSED */ +void _XPollfdCacheDel( + Display *dpy, + int fd) /* not used */ +{ +#ifdef USE_POLL + struct pollfd *pfp = (struct pollfd *)dpy->filedes; + struct _XConnectionInfo *conni; + + /* just recalculate whole list */ + if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) { + int loc = 1; + for (conni = dpy->im_fd_info; conni; conni=conni->next) { + pfp[loc].fd = conni->fd; + pfp[loc].events = POLLIN; + loc++; + } + } +#endif +} + +#ifdef _MSC_VER +#undef min +#define min __min +#endif + +static int sync_hazard(Display *dpy) +{ + unsigned long span = dpy->request - dpy->last_request_read; + unsigned long hazard = min((dpy->bufmax - dpy->buffer) / SIZEOF(xReq), 65535 - 10); + return span >= 65535 - hazard - 10; +} + +static +void sync_while_locked(Display *dpy) +{ +#ifdef XTHREADS + if (dpy->lock) + (*dpy->lock->user_lock_display)(dpy); +#endif + UnlockDisplay(dpy); + SyncHandle(); + InternalLockDisplay(dpy, /* don't skip user locks */ 0); +#ifdef XTHREADS + if (dpy->lock) + (*dpy->lock->user_unlock_display)(dpy); +#endif +} + +void _XSeqSyncFunction( + register Display *dpy) +{ + xGetInputFocusReply rep; + register xReq *req; + + if ((dpy->request - dpy->last_request_read) >= (65535 - BUFSIZE/SIZEOF(xReq))) { + GetEmptyReq(GetInputFocus, req); + (void) _XReply (dpy, (xReply *)&rep, 0, xTrue); + sync_while_locked(dpy); + } else if (sync_hazard(dpy)) + _XSetPrivSyncFunction(dpy); +} + +/* NOTE: only called if !XTHREADS, or when XInitThreads wasn't called. */ +static int +_XPrivSyncFunction (Display *dpy) +{ +#ifdef XTHREADS + assert(!dpy->lock_fns); +#endif + assert(dpy->synchandler == _XPrivSyncFunction); + assert((dpy->flags & XlibDisplayPrivSync) != 0); + dpy->synchandler = dpy->savedsynchandler; + dpy->savedsynchandler = NULL; + dpy->flags &= ~XlibDisplayPrivSync; + if(dpy->synchandler) + dpy->synchandler(dpy); + _XIDHandler(dpy); + _XSeqSyncFunction(dpy); + return 0; +} + +void _XSetPrivSyncFunction(Display *dpy) +{ +#ifdef XTHREADS + if (dpy->lock_fns) + return; +#endif + if (!(dpy->flags & XlibDisplayPrivSync)) { + dpy->savedsynchandler = dpy->synchandler; + dpy->synchandler = _XPrivSyncFunction; + dpy->flags |= XlibDisplayPrivSync; + } +} + +void _XSetSeqSyncFunction(Display *dpy) +{ + if (sync_hazard(dpy)) + _XSetPrivSyncFunction (dpy); +} + +#ifdef LONG64 +void _XRead32( + Display *dpy, + register long *data, + long len) +{ + register int *buf; + register long i; + + if (len) { + (void) _XRead(dpy, (char *)data, len); + i = len >> 2; + buf = (int *)data + i; + data += i; + while (--i >= 0) + *--data = *--buf; + } +} +#endif /* LONG64 */ + +#ifdef WORD64 + +/* + * XXX This is a *really* stupid way of doing this.... + * PACKBUFFERSIZE must be a multiple of 4. + */ + +#define PACKBUFFERSIZE 4096 + + +/* + * _XRead32 - Read bytes from the socket unpacking each 32 bits + * into a long (64 bits on a CRAY computer). + * + */ +static void _doXRead32( + register Display *dpy, + register long *data + register long size, + register char *packbuffer) +{ + long *lpack,*lp; + long mask32 = 0x00000000ffffffff; + long maskw, nwords, i, bits; + + _XReadPad (dpy, packbuffer, size); + + lp = data; + lpack = (long *) packbuffer; + nwords = size >> 2; + bits = 32; + + for(i=0;i<nwords;i++){ + maskw = mask32 << bits; + *lp++ = ( *lpack & maskw ) >> bits; + bits = bits ^32; + if(bits){ + lpack++; + } + } +} + +void _XRead32( + Display *dpy, + long *data, + long len) +{ + char packbuffer[PACKBUFFERSIZE]; + unsigned nunits = PACKBUFFERSIZE >> 2; + + for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) { + _doXRead32 (dpy, data, PACKBUFFERSIZE, packbuffer); + } + if (len) _doXRead32 (dpy, data, len, packbuffer); +} + + + +/* + * _XRead16 - Read bytes from the socket unpacking each 16 bits + * into a long (64 bits on a CRAY computer). + * + */ +static _doXRead16( + register Display *dpy, + register short *data, + register long size, + char *packbuffer) +{ + long *lpack,*lp; + long mask16 = 0x000000000000ffff; + long maskw, nwords, i, bits; + + (void) _XRead(dpy,packbuffer,size); /* don't do a padded read... */ + + lp = (long *) data; + lpack = (long *) packbuffer; + nwords = size >> 1; /* number of 16 bit words to be unpacked */ + bits = 48; + for(i=0;i<nwords;i++){ + maskw = mask16 << bits; + *lp++ = ( *lpack & maskw ) >> bits; + bits -= 16; + if(bits < 0){ + lpack++; + bits = 48; + } + } +} + +void _XRead16( + Display *dpy, + short *data, + long len) +{ + char packbuffer[PACKBUFFERSIZE]; + unsigned nunits = PACKBUFFERSIZE >> 1; + + for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) { + _doXRead16 (dpy, data, PACKBUFFERSIZE, packbuffer); + } + if (len) _doXRead16 (dpy, data, len, packbuffer); +} + +void _XRead16Pad( + Display *dpy, + short *data, + long size) +{ + int slop = (size & 3); + short slopbuf[3]; + + _XRead16 (dpy, data, size); + if (slop > 0) { + _XRead16 (dpy, slopbuf, 4 - slop); + } +} +#endif /* WORD64 */ + +/* + * The hard part about this is that we only get 16 bits from a reply. + * We have three values that will march along, with the following invariant: + * dpy->last_request_read <= rep->sequenceNumber <= dpy->request + * We have to keep + * dpy->request - dpy->last_request_read < 2^16 + * or else we won't know for sure what value to use in events. We do this + * by forcing syncs when we get close. + */ + +unsigned long +_XSetLastRequestRead( + register Display *dpy, + register xGenericReply *rep) +{ + register unsigned long newseq, lastseq; + + lastseq = dpy->last_request_read; + /* + * KeymapNotify has no sequence number, but is always guaranteed + * to immediately follow another event, except when generated via + * SendEvent (hmmm). + */ + if ((rep->type & 0x7f) == KeymapNotify) + return(lastseq); + + newseq = (lastseq & ~((unsigned long)0xffff)) | rep->sequenceNumber; + + if (newseq < lastseq) { + newseq += 0x10000; + if (newseq > dpy->request) { + (void) fprintf (stderr, + "Xlib: sequence lost (0x%lx > 0x%lx) in reply type 0x%x!\n", + newseq, dpy->request, + (unsigned int) rep->type); + newseq -= 0x10000; + } + } + + dpy->last_request_read = newseq; + return(newseq); +} + +/* + * Support for internal connections, such as an IM might use. + * By Stephen Gildea, X Consortium, September 1993 + */ + +/* _XRegisterInternalConnection + * Each IM (or Xlib extension) that opens a file descriptor that Xlib should + * include in its select/poll mask must call this function to register the + * fd with Xlib. Any XConnectionWatchProc registered by XAddConnectionWatch + * will also be called. + * + * Whenever Xlib detects input available on fd, it will call callback + * with call_data to process it. If non-Xlib code calls select/poll + * and detects input available, it must call XProcessInternalConnection, + * which will call the associated callback. + * + * Non-Xlib code can learn about these additional fds by calling + * XInternalConnectionNumbers or, more typically, by registering + * a XConnectionWatchProc with XAddConnectionWatch + * to be called when fds are registered or unregistered. + * + * Returns True if registration succeeded, False if not, typically + * because could not allocate memory. + * Assumes Display locked when called. + */ +Status +_XRegisterInternalConnection( + Display* dpy, + int fd, + _XInternalConnectionProc callback, + XPointer call_data +) +{ + struct _XConnectionInfo *new_conni, **iptr; + struct _XConnWatchInfo *watchers; + XPointer *wd; + + new_conni = (struct _XConnectionInfo*)Xmalloc(sizeof(struct _XConnectionInfo)); + if (!new_conni) + return 0; + new_conni->watch_data = (XPointer *)Xmalloc(dpy->watcher_count * sizeof(XPointer)); + if (!new_conni->watch_data) { + Xfree(new_conni); + return 0; + } + new_conni->fd = fd; + new_conni->read_callback = callback; + new_conni->call_data = call_data; + new_conni->next = NULL; + /* link new structure onto end of list */ + for (iptr = &dpy->im_fd_info; *iptr; iptr = &(*iptr)->next) + ; + *iptr = new_conni; + dpy->im_fd_length++; + _XPollfdCacheAdd(dpy, fd); + + for (watchers=dpy->conn_watchers, wd=new_conni->watch_data; + watchers; + watchers=watchers->next, wd++) { + *wd = NULL; /* for cleanliness */ + (*watchers->fn) (dpy, watchers->client_data, fd, True, wd); + } + + return 1; +} + +/* _XUnregisterInternalConnection + * Each IM (or Xlib extension) that closes a file descriptor previously + * registered with _XRegisterInternalConnection must call this function. + * Any XConnectionWatchProc registered by XAddConnectionWatch + * will also be called. + * + * Assumes Display locked when called. + */ +void +_XUnregisterInternalConnection( + Display* dpy, + int fd +) +{ + struct _XConnectionInfo *info_list, **prev; + struct _XConnWatchInfo *watch; + XPointer *wd; + + for (prev = &dpy->im_fd_info; (info_list = *prev); + prev = &info_list->next) { + if (info_list->fd == fd) { + *prev = info_list->next; + dpy->im_fd_length--; + for (watch=dpy->conn_watchers, wd=info_list->watch_data; + watch; + watch=watch->next, wd++) { + (*watch->fn) (dpy, watch->client_data, fd, False, wd); + } + if (info_list->watch_data) + Xfree (info_list->watch_data); + Xfree (info_list); + break; + } + } + _XPollfdCacheDel(dpy, fd); +} + +/* XInternalConnectionNumbers + * Returns an array of fds and an array of corresponding call data. + * Typically a XConnectionWatchProc registered with XAddConnectionWatch + * will be used instead of this function to discover + * additional fds to include in the select/poll mask. + * + * The list is allocated with Xmalloc and should be freed by the caller + * with Xfree; + */ +Status +XInternalConnectionNumbers( + Display *dpy, + int **fd_return, + int *count_return +) +{ + int count; + struct _XConnectionInfo *info_list; + int *fd_list; + + LockDisplay(dpy); + count = 0; + for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) + count++; + fd_list = (int*) Xmalloc (count * sizeof(int)); + if (!fd_list) { + UnlockDisplay(dpy); + return 0; + } + count = 0; + for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) { + fd_list[count] = info_list->fd; + count++; + } + UnlockDisplay(dpy); + + *fd_return = fd_list; + *count_return = count; + return 1; +} + +void _XProcessInternalConnection( + Display *dpy, + struct _XConnectionInfo *conn_info) +{ + dpy->flags |= XlibDisplayProcConni; + UnlockDisplay(dpy); + (*conn_info->read_callback) (dpy, conn_info->fd, conn_info->call_data); + LockDisplay(dpy); + dpy->flags &= ~XlibDisplayProcConni; +} + +/* XProcessInternalConnection + * Call the _XInternalConnectionProc registered by _XRegisterInternalConnection + * for this fd. + * The Display is NOT locked during the call. + */ +void +XProcessInternalConnection( + Display* dpy, + int fd +) +{ + struct _XConnectionInfo *info_list; + + LockDisplay(dpy); + for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) { + if (info_list->fd == fd) { + _XProcessInternalConnection(dpy, info_list); + break; + } + } + UnlockDisplay(dpy); +} + +/* XAddConnectionWatch + * Register a callback to be called whenever _XRegisterInternalConnection + * or _XUnregisterInternalConnection is called. + * Callbacks are called with the Display locked. + * If any connections are already registered, the callback is immediately + * called for each of them. + */ +Status +XAddConnectionWatch( + Display* dpy, + XConnectionWatchProc callback, + XPointer client_data +) +{ + struct _XConnWatchInfo *new_watcher, **wptr; + struct _XConnectionInfo *info_list; + XPointer *wd_array; + + LockDisplay(dpy); + + /* allocate new watch data */ + for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) { + wd_array = (XPointer *)Xrealloc((char *)info_list->watch_data, + (dpy->watcher_count + 1) * + sizeof(XPointer)); + if (!wd_array) { + UnlockDisplay(dpy); + return 0; + } + info_list->watch_data = wd_array; + wd_array[dpy->watcher_count] = NULL; /* for cleanliness */ + } + + new_watcher = (struct _XConnWatchInfo*)Xmalloc(sizeof(struct _XConnWatchInfo)); + if (!new_watcher) { + UnlockDisplay(dpy); + return 0; + } + new_watcher->fn = callback; + new_watcher->client_data = client_data; + new_watcher->next = NULL; + + /* link new structure onto end of list */ + for (wptr = &dpy->conn_watchers; *wptr; wptr = &(*wptr)->next) + ; + *wptr = new_watcher; + dpy->watcher_count++; + + /* call new watcher on all currently registered fds */ + for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) { + (*callback) (dpy, client_data, info_list->fd, True, + info_list->watch_data + dpy->watcher_count - 1); + } + + UnlockDisplay(dpy); + return 1; +} + +/* XRemoveConnectionWatch + * Unregister a callback registered by XAddConnectionWatch. + * Both callback and client_data must match what was passed to + * XAddConnectionWatch. + */ +void +XRemoveConnectionWatch( + Display* dpy, + XConnectionWatchProc callback, + XPointer client_data +) +{ + struct _XConnWatchInfo *watch; + struct _XConnWatchInfo *previous = NULL; + struct _XConnectionInfo *conni; + int counter = 0; + + LockDisplay(dpy); + for (watch=dpy->conn_watchers; watch; watch=watch->next) { + if (watch->fn == callback && watch->client_data == client_data) { + if (previous) + previous->next = watch->next; + else + dpy->conn_watchers = watch->next; + Xfree (watch); + dpy->watcher_count--; + /* remove our watch_data for each connection */ + for (conni=dpy->im_fd_info; conni; conni=conni->next) { + /* don't bother realloc'ing; these arrays are small anyway */ + /* overlapping */ + memmove(conni->watch_data+counter, + conni->watch_data+counter+1, + dpy->watcher_count - counter); + } + break; + } + previous = watch; + counter++; + } + UnlockDisplay(dpy); +} + +/* end of internal connections support */ + +/* Cookie jar implementation + dpy->cookiejar is a linked list. _XEnq receives the events but leaves + them in the normal EQ. _XStoreEvent returns the cookie event (minus + data pointer) and adds it to the cookiejar. _XDeq just removes + the entry like any other event but resets the data pointer for + cookie events (to avoid double-free, the memory is re-used by Xlib). + + _XFetchEventCookie (called from XGetEventData) removes a cookie from the + jar. _XFreeEventCookies removes all unclaimed cookies from the jar + (called by XNextEvent). + + _XFreeDisplayStructure calls _XFreeEventCookies for each cookie in the + normal EQ. + */ + +#include "utlist.h" +struct stored_event { + XGenericEventCookie ev; + struct stored_event *prev; + struct stored_event *next; +}; + +Bool +_XIsEventCookie(Display *dpy, XEvent *ev) +{ + return (ev->xcookie.type == GenericEvent && + dpy->generic_event_vec[ev->xcookie.extension & 0x7F] != NULL); +} + +/** + * Free all events in the event list. + */ +void +_XFreeEventCookies(Display *dpy) +{ + struct stored_event **head, *e, *tmp; + + if (!dpy->cookiejar) + return; + + head = (struct stored_event**)&dpy->cookiejar; + + DL_FOREACH_SAFE(*head, e, tmp) { + if (dpy->cookiejar == e) + dpy->cookiejar = NULL; + XFree(e->ev.data); + XFree(e); + } +} + +/** + * Add an event to the display's event list. This event must be freed on the + * next call to XNextEvent(). + */ +void +_XStoreEventCookie(Display *dpy, XEvent *event) +{ + XGenericEventCookie* cookie = &event->xcookie; + struct stored_event **head, *add; + + if (!_XIsEventCookie(dpy, event)) + return; + + head = (struct stored_event**)(&dpy->cookiejar); + + add = Xmalloc(sizeof(struct stored_event)); + if (!add) { + ESET(ENOMEM); + _XIOError(dpy); + } + add->ev = *cookie; + DL_APPEND(*head, add); + cookie->data = NULL; /* don't return data yet, must be claimed */ +} + +/** + * Return the event with the given cookie and remove it from the list. + */ +Bool +_XFetchEventCookie(Display *dpy, XGenericEventCookie* ev) +{ + Bool ret = False; + struct stored_event **head, *event; + head = (struct stored_event**)&dpy->cookiejar; + + if (!_XIsEventCookie(dpy, (XEvent*)ev)) + return ret; + + DL_FOREACH(*head, event) { + if (event->ev.cookie == ev->cookie && + event->ev.extension == ev->extension && + event->ev.evtype == ev->evtype) { + *ev = event->ev; + DL_DELETE(*head, event); + Xfree(event); + ret = True; + break; + } + } + + return ret; +} + +Bool +_XCopyEventCookie(Display *dpy, XGenericEventCookie *in, XGenericEventCookie *out) +{ + Bool ret = False; + int extension; + + if (!_XIsEventCookie(dpy, (XEvent*)in) || !out) + return ret; + + extension = in->extension & 0x7F; + + if (!dpy->generic_event_copy_vec[extension]) + return ret; + + ret = ((*dpy->generic_event_copy_vec[extension])(dpy, in, out)); + out->cookie = ret ? ++dpy->next_cookie : 0; + return ret; +} + + +/* + * _XEnq - Place event packets on the display's queue. + * note that no squishing of move events in V11, since there + * is pointer motion hints.... + */ +void _XEnq( + register Display *dpy, + register xEvent *event) +{ + register _XQEvent *qelt; + int type, extension; + + if ((qelt = dpy->qfree)) { + /* If dpy->qfree is non-NULL do this, else malloc a new one. */ + dpy->qfree = qelt->next; + } + else if ((qelt = + (_XQEvent *) Xmalloc((unsigned)sizeof(_XQEvent))) == NULL) { + /* Malloc call failed! */ + ESET(ENOMEM); + _XIOError(dpy); + } + qelt->next = NULL; + + type = event->u.u.type & 0177; + extension = ((xGenericEvent*)event)->extension; + + qelt->event.type = type; + /* If an extension has registerd a generic_event_vec handler, then + * it can handle event cookies. Otherwise, proceed with the normal + * event handlers. + * + * If the generic_event_vec is called, qelt->event is a event cookie + * with the data pointer and the "free" pointer set. Data pointer is + * some memory allocated by the extension. + */ + if (type == GenericEvent && dpy->generic_event_vec[extension & 0x7F]) { + XGenericEventCookie *cookie = &qelt->event.xcookie; + (*dpy->generic_event_vec[extension & 0x7F])(dpy, cookie, event); + cookie->cookie = ++dpy->next_cookie; + + qelt->qserial_num = dpy->next_event_serial_num++; + if (dpy->tail) dpy->tail->next = qelt; + else dpy->head = qelt; + + dpy->tail = qelt; + dpy->qlen++; + } else if ((*dpy->event_vec[type])(dpy, &qelt->event, event)) { + qelt->qserial_num = dpy->next_event_serial_num++; + if (dpy->tail) dpy->tail->next = qelt; + else dpy->head = qelt; + + dpy->tail = qelt; + dpy->qlen++; + } else { + /* ignored, or stashed away for many-to-one compression */ + qelt->next = dpy->qfree; + dpy->qfree = qelt; + } +} + +/* + * _XDeq - Remove event packet from the display's queue. + */ +void _XDeq( + register Display *dpy, + register _XQEvent *prev, /* element before qelt */ + register _XQEvent *qelt) /* element to be unlinked */ +{ + if (prev) { + if ((prev->next = qelt->next) == NULL) + dpy->tail = prev; + } else { + /* no prev, so removing first elt */ + if ((dpy->head = qelt->next) == NULL) + dpy->tail = NULL; + } + qelt->qserial_num = 0; + qelt->next = dpy->qfree; + dpy->qfree = qelt; + dpy->qlen--; + + if (_XIsEventCookie(dpy, &qelt->event)) { + XGenericEventCookie* cookie = &qelt->event.xcookie; + /* dpy->qfree is re-used, reset memory to avoid double free on + * _XFreeDisplayStructure */ + cookie->data = NULL; + } +} + +/* + * EventToWire in separate file in that often not needed. + */ + +/*ARGSUSED*/ +Bool +_XUnknownWireEvent( + register Display *dpy, /* pointer to display structure */ + register XEvent *re, /* pointer to where event should be reformatted */ + register xEvent *event) /* wire protocol event */ +{ +#ifdef notdef + (void) fprintf(stderr, + "Xlib: unhandled wire event! event number = %d, display = %x\n.", + event->u.u.type, dpy); +#endif + return(False); +} + +Bool +_XUnknownWireEventCookie( + Display *dpy, /* pointer to display structure */ + XGenericEventCookie *re, /* pointer to where event should be reformatted */ + xEvent *event) /* wire protocol event */ +{ +#ifdef notdef + fprintf(stderr, + "Xlib: unhandled wire cookie event! extension number = %d, display = %x\n.", + ((xGenericEvent*)event)->extension, dpy); +#endif + return(False); +} + +Bool +_XUnknownCopyEventCookie( + Display *dpy, /* pointer to display structure */ + XGenericEventCookie *in, /* source */ + XGenericEventCookie *out) /* destination */ +{ +#ifdef notdef + fprintf(stderr, + "Xlib: unhandled cookie event copy! extension number = %d, display = %x\n.", + in->extension, dpy); +#endif + return(False); +} + +/*ARGSUSED*/ +Status +_XUnknownNativeEvent( + register Display *dpy, /* pointer to display structure */ + register XEvent *re, /* pointer to where event should be reformatted */ + register xEvent *event) /* wire protocol event */ +{ +#ifdef notdef + (void) fprintf(stderr, + "Xlib: unhandled native event! event number = %d, display = %x\n.", + re->type, dpy); +#endif + return(0); +} +/* + * reformat a wire event into an XEvent structure of the right type. + */ +Bool +_XWireToEvent( + register Display *dpy, /* pointer to display structure */ + register XEvent *re, /* pointer to where event should be reformatted */ + register xEvent *event) /* wire protocol event */ +{ + + re->type = event->u.u.type & 0x7f; + ((XAnyEvent *)re)->serial = _XSetLastRequestRead(dpy, + (xGenericReply *)event); + ((XAnyEvent *)re)->send_event = ((event->u.u.type & 0x80) != 0); + ((XAnyEvent *)re)->display = dpy; + + /* Ignore the leading bit of the event type since it is set when a + client sends an event rather than the server. */ + + switch (event-> u.u.type & 0177) { + case KeyPress: + case KeyRelease: + { + register XKeyEvent *ev = (XKeyEvent*) re; + ev->root = event->u.keyButtonPointer.root; + ev->window = event->u.keyButtonPointer.event; + ev->subwindow = event->u.keyButtonPointer.child; + ev->time = event->u.keyButtonPointer.time; + ev->x = cvtINT16toInt(event->u.keyButtonPointer.eventX); + ev->y = cvtINT16toInt(event->u.keyButtonPointer.eventY); + ev->x_root = cvtINT16toInt(event->u.keyButtonPointer.rootX); + ev->y_root = cvtINT16toInt(event->u.keyButtonPointer.rootY); + ev->state = event->u.keyButtonPointer.state; + ev->same_screen = event->u.keyButtonPointer.sameScreen; + ev->keycode = event->u.u.detail; + } + break; + case ButtonPress: + case ButtonRelease: + { + register XButtonEvent *ev = (XButtonEvent *) re; + ev->root = event->u.keyButtonPointer.root; + ev->window = event->u.keyButtonPointer.event; + ev->subwindow = event->u.keyButtonPointer.child; + ev->time = event->u.keyButtonPointer.time; + ev->x = cvtINT16toInt(event->u.keyButtonPointer.eventX); + ev->y = cvtINT16toInt(event->u.keyButtonPointer.eventY); + ev->x_root = cvtINT16toInt(event->u.keyButtonPointer.rootX); + ev->y_root = cvtINT16toInt(event->u.keyButtonPointer.rootY); + ev->state = event->u.keyButtonPointer.state; + ev->same_screen = event->u.keyButtonPointer.sameScreen; + ev->button = event->u.u.detail; + } + break; + case MotionNotify: + { + register XMotionEvent *ev = (XMotionEvent *)re; + ev->root = event->u.keyButtonPointer.root; + ev->window = event->u.keyButtonPointer.event; + ev->subwindow = event->u.keyButtonPointer.child; + ev->time = event->u.keyButtonPointer.time; + ev->x = cvtINT16toInt(event->u.keyButtonPointer.eventX); + ev->y = cvtINT16toInt(event->u.keyButtonPointer.eventY); + ev->x_root = cvtINT16toInt(event->u.keyButtonPointer.rootX); + ev->y_root = cvtINT16toInt(event->u.keyButtonPointer.rootY); + ev->state = event->u.keyButtonPointer.state; + ev->same_screen = event->u.keyButtonPointer.sameScreen; + ev->is_hint = event->u.u.detail; + } + break; + case EnterNotify: + case LeaveNotify: + { + register XCrossingEvent *ev = (XCrossingEvent *) re; + ev->root = event->u.enterLeave.root; + ev->window = event->u.enterLeave.event; + ev->subwindow = event->u.enterLeave.child; + ev->time = event->u.enterLeave.time; + ev->x = cvtINT16toInt(event->u.enterLeave.eventX); + ev->y = cvtINT16toInt(event->u.enterLeave.eventY); + ev->x_root = cvtINT16toInt(event->u.enterLeave.rootX); + ev->y_root = cvtINT16toInt(event->u.enterLeave.rootY); + ev->state = event->u.enterLeave.state; + ev->mode = event->u.enterLeave.mode; + ev->same_screen = (event->u.enterLeave.flags & + ELFlagSameScreen) && True; + ev->focus = (event->u.enterLeave.flags & + ELFlagFocus) && True; + ev->detail = event->u.u.detail; + } + break; + case FocusIn: + case FocusOut: + { + register XFocusChangeEvent *ev = (XFocusChangeEvent *) re; + ev->window = event->u.focus.window; + ev->mode = event->u.focus.mode; + ev->detail = event->u.u.detail; + } + break; + case KeymapNotify: + { + register XKeymapEvent *ev = (XKeymapEvent *) re; + ev->window = None; + memcpy(&ev->key_vector[1], + (char *)((xKeymapEvent *) event)->map, + sizeof (((xKeymapEvent *) event)->map)); + } + break; + case Expose: + { + register XExposeEvent *ev = (XExposeEvent *) re; + ev->window = event->u.expose.window; + ev->x = event->u.expose.x; + ev->y = event->u.expose.y; + ev->width = event->u.expose.width; + ev->height = event->u.expose.height; + ev->count = event->u.expose.count; + } + break; + case GraphicsExpose: + { + register XGraphicsExposeEvent *ev = + (XGraphicsExposeEvent *) re; + ev->drawable = event->u.graphicsExposure.drawable; + ev->x = event->u.graphicsExposure.x; + ev->y = event->u.graphicsExposure.y; + ev->width = event->u.graphicsExposure.width; + ev->height = event->u.graphicsExposure.height; + ev->count = event->u.graphicsExposure.count; + ev->major_code = event->u.graphicsExposure.majorEvent; + ev->minor_code = event->u.graphicsExposure.minorEvent; + } + break; + case NoExpose: + { + register XNoExposeEvent *ev = (XNoExposeEvent *) re; + ev->drawable = event->u.noExposure.drawable; + ev->major_code = event->u.noExposure.majorEvent; + ev->minor_code = event->u.noExposure.minorEvent; + } + break; + case VisibilityNotify: + { + register XVisibilityEvent *ev = (XVisibilityEvent *) re; + ev->window = event->u.visibility.window; + ev->state = event->u.visibility.state; + } + break; + case CreateNotify: + { + register XCreateWindowEvent *ev = + (XCreateWindowEvent *) re; + ev->window = event->u.createNotify.window; + ev->parent = event->u.createNotify.parent; + ev->x = cvtINT16toInt(event->u.createNotify.x); + ev->y = cvtINT16toInt(event->u.createNotify.y); + ev->width = event->u.createNotify.width; + ev->height = event->u.createNotify.height; + ev->border_width = event->u.createNotify.borderWidth; + ev->override_redirect = event->u.createNotify.override; + } + break; + case DestroyNotify: + { + register XDestroyWindowEvent *ev = + (XDestroyWindowEvent *) re; + ev->window = event->u.destroyNotify.window; + ev->event = event->u.destroyNotify.event; + } + break; + case UnmapNotify: + { + register XUnmapEvent *ev = (XUnmapEvent *) re; + ev->window = event->u.unmapNotify.window; + ev->event = event->u.unmapNotify.event; + ev->from_configure = event->u.unmapNotify.fromConfigure; + } + break; + case MapNotify: + { + register XMapEvent *ev = (XMapEvent *) re; + ev->window = event->u.mapNotify.window; + ev->event = event->u.mapNotify.event; + ev->override_redirect = event->u.mapNotify.override; + } + break; + case MapRequest: + { + register XMapRequestEvent *ev = (XMapRequestEvent *) re; + ev->window = event->u.mapRequest.window; + ev->parent = event->u.mapRequest.parent; + } + break; + case ReparentNotify: + { + register XReparentEvent *ev = (XReparentEvent *) re; + ev->event = event->u.reparent.event; + ev->window = event->u.reparent.window; + ev->parent = event->u.reparent.parent; + ev->x = cvtINT16toInt(event->u.reparent.x); + ev->y = cvtINT16toInt(event->u.reparent.y); + ev->override_redirect = event->u.reparent.override; + } + break; + case ConfigureNotify: + { + register XConfigureEvent *ev = (XConfigureEvent *) re; + ev->event = event->u.configureNotify.event; + ev->window = event->u.configureNotify.window; + ev->above = event->u.configureNotify.aboveSibling; + ev->x = cvtINT16toInt(event->u.configureNotify.x); + ev->y = cvtINT16toInt(event->u.configureNotify.y); + ev->width = event->u.configureNotify.width; + ev->height = event->u.configureNotify.height; + ev->border_width = event->u.configureNotify.borderWidth; + ev->override_redirect = event->u.configureNotify.override; + } + break; + case ConfigureRequest: + { + register XConfigureRequestEvent *ev = + (XConfigureRequestEvent *) re; + ev->window = event->u.configureRequest.window; + ev->parent = event->u.configureRequest.parent; + ev->above = event->u.configureRequest.sibling; + ev->x = cvtINT16toInt(event->u.configureRequest.x); + ev->y = cvtINT16toInt(event->u.configureRequest.y); + ev->width = event->u.configureRequest.width; + ev->height = event->u.configureRequest.height; + ev->border_width = event->u.configureRequest.borderWidth; + ev->value_mask = event->u.configureRequest.valueMask; + ev->detail = event->u.u.detail; + } + break; + case GravityNotify: + { + register XGravityEvent *ev = (XGravityEvent *) re; + ev->window = event->u.gravity.window; + ev->event = event->u.gravity.event; + ev->x = cvtINT16toInt(event->u.gravity.x); + ev->y = cvtINT16toInt(event->u.gravity.y); + } + break; + case ResizeRequest: + { + register XResizeRequestEvent *ev = + (XResizeRequestEvent *) re; + ev->window = event->u.resizeRequest.window; + ev->width = event->u.resizeRequest.width; + ev->height = event->u.resizeRequest.height; + } + break; + case CirculateNotify: + { + register XCirculateEvent *ev = (XCirculateEvent *) re; + ev->window = event->u.circulate.window; + ev->event = event->u.circulate.event; + ev->place = event->u.circulate.place; + } + break; + case CirculateRequest: + { + register XCirculateRequestEvent *ev = + (XCirculateRequestEvent *) re; + ev->window = event->u.circulate.window; + ev->parent = event->u.circulate.event; + ev->place = event->u.circulate.place; + } + break; + case PropertyNotify: + { + register XPropertyEvent *ev = (XPropertyEvent *) re; + ev->window = event->u.property.window; + ev->atom = event->u.property.atom; + ev->time = event->u.property.time; + ev->state = event->u.property.state; + } + break; + case SelectionClear: + { + register XSelectionClearEvent *ev = + (XSelectionClearEvent *) re; + ev->window = event->u.selectionClear.window; + ev->selection = event->u.selectionClear.atom; + ev->time = event->u.selectionClear.time; + } + break; + case SelectionRequest: + { + register XSelectionRequestEvent *ev = + (XSelectionRequestEvent *) re; + ev->owner = event->u.selectionRequest.owner; + ev->requestor = event->u.selectionRequest.requestor; + ev->selection = event->u.selectionRequest.selection; + ev->target = event->u.selectionRequest.target; + ev->property = event->u.selectionRequest.property; + ev->time = event->u.selectionRequest.time; + } + break; + case SelectionNotify: + { + register XSelectionEvent *ev = (XSelectionEvent *) re; + ev->requestor = event->u.selectionNotify.requestor; + ev->selection = event->u.selectionNotify.selection; + ev->target = event->u.selectionNotify.target; + ev->property = event->u.selectionNotify.property; + ev->time = event->u.selectionNotify.time; + } + break; + case ColormapNotify: + { + register XColormapEvent *ev = (XColormapEvent *) re; + ev->window = event->u.colormap.window; + ev->colormap = event->u.colormap.colormap; + ev->new = event->u.colormap.new; + ev->state = event->u.colormap.state; + } + break; + case ClientMessage: + { + register int i; + register XClientMessageEvent *ev + = (XClientMessageEvent *) re; + ev->window = event->u.clientMessage.window; + ev->format = event->u.u.detail; + switch (ev->format) { + case 8: + ev->message_type = event->u.clientMessage.u.b.type; + for (i = 0; i < 20; i++) + ev->data.b[i] = event->u.clientMessage.u.b.bytes[i]; + break; + case 16: + ev->message_type = event->u.clientMessage.u.s.type; + ev->data.s[0] = cvtINT16toShort(event->u.clientMessage.u.s.shorts0); + ev->data.s[1] = cvtINT16toShort(event->u.clientMessage.u.s.shorts1); + ev->data.s[2] = cvtINT16toShort(event->u.clientMessage.u.s.shorts2); + ev->data.s[3] = cvtINT16toShort(event->u.clientMessage.u.s.shorts3); + ev->data.s[4] = cvtINT16toShort(event->u.clientMessage.u.s.shorts4); + ev->data.s[5] = cvtINT16toShort(event->u.clientMessage.u.s.shorts5); + ev->data.s[6] = cvtINT16toShort(event->u.clientMessage.u.s.shorts6); + ev->data.s[7] = cvtINT16toShort(event->u.clientMessage.u.s.shorts7); + ev->data.s[8] = cvtINT16toShort(event->u.clientMessage.u.s.shorts8); + ev->data.s[9] = cvtINT16toShort(event->u.clientMessage.u.s.shorts9); + break; + case 32: + ev->message_type = event->u.clientMessage.u.l.type; + ev->data.l[0] = cvtINT32toLong(event->u.clientMessage.u.l.longs0); + ev->data.l[1] = cvtINT32toLong(event->u.clientMessage.u.l.longs1); + ev->data.l[2] = cvtINT32toLong(event->u.clientMessage.u.l.longs2); + ev->data.l[3] = cvtINT32toLong(event->u.clientMessage.u.l.longs3); + ev->data.l[4] = cvtINT32toLong(event->u.clientMessage.u.l.longs4); + break; + default: /* XXX should never occur */ + break; + } + } + break; + case MappingNotify: + { + register XMappingEvent *ev = (XMappingEvent *)re; + ev->window = 0; + ev->first_keycode = event->u.mappingNotify.firstKeyCode; + ev->request = event->u.mappingNotify.request; + ev->count = event->u.mappingNotify.count; + } + break; + default: + return(_XUnknownWireEvent(dpy, re, event)); + } + return(True); +} + + +/* + * _XDefaultIOError - Default fatal system error reporting routine. Called + * when an X internal system error is encountered. + */ +int _XDefaultIOError( + Display *dpy) +{ + if (ECHECK(EPIPE)) { + (void) fprintf (stderr, + "X connection to %s broken (explicit kill or server shutdown).\r\n", + DisplayString (dpy)); + } else { + (void) fprintf (stderr, + "XIO: fatal IO error %d (%s) on X server \"%s\"\r\n", +#ifdef WIN32 + WSAGetLastError(), strerror(WSAGetLastError()), +#else + errno, strerror (errno), +#endif + DisplayString (dpy)); + (void) fprintf (stderr, + " after %lu requests (%lu known processed) with %d events remaining.\r\n", + NextRequest(dpy) - 1, LastKnownRequestProcessed(dpy), + QLength(dpy)); + + } + exit(1); + return(0); /* dummy - function should never return */ +} + + +static int _XPrintDefaultError( + Display *dpy, + XErrorEvent *event, + FILE *fp) +{ + char buffer[BUFSIZ]; + char mesg[BUFSIZ]; + char number[32]; + const char *mtype = "XlibMessage"; + register _XExtension *ext = (_XExtension *)NULL; + _XExtension *bext = (_XExtension *)NULL; + XGetErrorText(dpy, event->error_code, buffer, BUFSIZ); + XGetErrorDatabaseText(dpy, mtype, "XError", "X Error", mesg, BUFSIZ); + (void) fprintf(fp, "%s: %s\n ", mesg, buffer); + XGetErrorDatabaseText(dpy, mtype, "MajorCode", "Request Major code %d", + mesg, BUFSIZ); + (void) fprintf(fp, mesg, event->request_code); + if (event->request_code < 128) { + sprintf(number, "%d", event->request_code); + XGetErrorDatabaseText(dpy, "XRequest", number, "", buffer, BUFSIZ); + } else { + for (ext = dpy->ext_procs; + ext && (ext->codes.major_opcode != event->request_code); + ext = ext->next) + ; + if (ext) { + strncpy(buffer, ext->name, BUFSIZ); + buffer[BUFSIZ - 1] = '\0'; + } else + buffer[0] = '\0'; + } + (void) fprintf(fp, " (%s)\n", buffer); + if (event->request_code >= 128) { + XGetErrorDatabaseText(dpy, mtype, "MinorCode", "Request Minor code %d", + mesg, BUFSIZ); + fputs(" ", fp); + (void) fprintf(fp, mesg, event->minor_code); + if (ext) { + sprintf(mesg, "%s.%d", ext->name, event->minor_code); + XGetErrorDatabaseText(dpy, "XRequest", mesg, "", buffer, BUFSIZ); + (void) fprintf(fp, " (%s)", buffer); + } + fputs("\n", fp); + } + if (event->error_code >= 128) { + /* kludge, try to find the extension that caused it */ + buffer[0] = '\0'; + for (ext = dpy->ext_procs; ext; ext = ext->next) { + if (ext->error_string) + (*ext->error_string)(dpy, event->error_code, &ext->codes, + buffer, BUFSIZ); + if (buffer[0]) { + bext = ext; + break; + } + if (ext->codes.first_error && + ext->codes.first_error < (int)event->error_code && + (!bext || ext->codes.first_error > bext->codes.first_error)) + bext = ext; + } + if (bext) + sprintf(buffer, "%s.%d", bext->name, + event->error_code - bext->codes.first_error); + else + strcpy(buffer, "Value"); + XGetErrorDatabaseText(dpy, mtype, buffer, "", mesg, BUFSIZ); + if (mesg[0]) { + fputs(" ", fp); + (void) fprintf(fp, mesg, event->resourceid); + fputs("\n", fp); + } + /* let extensions try to print the values */ + for (ext = dpy->ext_procs; ext; ext = ext->next) { + if (ext->error_values) + (*ext->error_values)(dpy, event, fp); + } + } else if ((event->error_code == BadWindow) || + (event->error_code == BadPixmap) || + (event->error_code == BadCursor) || + (event->error_code == BadFont) || + (event->error_code == BadDrawable) || + (event->error_code == BadColor) || + (event->error_code == BadGC) || + (event->error_code == BadIDChoice) || + (event->error_code == BadValue) || + (event->error_code == BadAtom)) { + if (event->error_code == BadValue) + XGetErrorDatabaseText(dpy, mtype, "Value", "Value 0x%x", + mesg, BUFSIZ); + else if (event->error_code == BadAtom) + XGetErrorDatabaseText(dpy, mtype, "AtomID", "AtomID 0x%x", + mesg, BUFSIZ); + else + XGetErrorDatabaseText(dpy, mtype, "ResourceID", "ResourceID 0x%x", + mesg, BUFSIZ); + fputs(" ", fp); + (void) fprintf(fp, mesg, event->resourceid); + fputs("\n", fp); + } + XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d", + mesg, BUFSIZ); + fputs(" ", fp); + (void) fprintf(fp, mesg, event->serial); + XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%d", + mesg, BUFSIZ); + fputs("\n ", fp); + (void) fprintf(fp, mesg, dpy->request); + fputs("\n", fp); + if (event->error_code == BadImplementation) return 0; + return 1; +} + +int _XDefaultError( + Display *dpy, + XErrorEvent *event) +{ + if (_XPrintDefaultError (dpy, event, stderr) == 0) return 0; + exit(1); + /*NOTREACHED*/ +} + +/*ARGSUSED*/ +Bool _XDefaultWireError(Display *display, XErrorEvent *he, xError *we) +{ + return True; +} + +/* + * _XError - upcall internal or user protocol error handler + */ +int _XError ( + Display *dpy, + register xError *rep) +{ + /* + * X_Error packet encountered! We need to unpack the error before + * giving it to the user. + */ + XEvent event; /* make it a large event */ + register _XAsyncHandler *async, *next; + + event.xerror.serial = _XSetLastRequestRead(dpy, (xGenericReply *)rep); + + for (async = dpy->async_handlers; async; async = next) { + next = async->next; + if ((*async->handler)(dpy, (xReply *)rep, + (char *)rep, SIZEOF(xError), async->data)) + return 0; + } + + event.xerror.display = dpy; + event.xerror.type = X_Error; + event.xerror.resourceid = rep->resourceID; + event.xerror.error_code = rep->errorCode; + event.xerror.request_code = rep->majorCode; + event.xerror.minor_code = rep->minorCode; + if (dpy->error_vec && + !(*dpy->error_vec[rep->errorCode])(dpy, &event.xerror, rep)) + return 0; + if (_XErrorFunction != NULL) { + int rtn_val; +#ifdef XTHREADS + if (dpy->lock) + (*dpy->lock->user_lock_display)(dpy); + UnlockDisplay(dpy); +#endif + rtn_val = (*_XErrorFunction)(dpy, (XErrorEvent *)&event); /* upcall */ +#ifdef XTHREADS + LockDisplay(dpy); + if (dpy->lock) + (*dpy->lock->user_unlock_display)(dpy); +#endif + return rtn_val; + } else { + return _XDefaultError(dpy, (XErrorEvent *)&event); + } +} + +/* + * _XIOError - call user connection error handler and exit + */ +int +_XIOError ( + Display *dpy) +{ + dpy->flags |= XlibDisplayIOError; +#ifdef WIN32 + errno = WSAGetLastError(); +#endif + + /* This assumes that the thread calling exit will call any atexit handlers. + * If this does not hold, then an alternate solution would involve + * registering an atexit handler to take over the lock, which would only + * assume that the same thread calls all the atexit handlers. */ +#ifdef XTHREADS + if (dpy->lock) + (*dpy->lock->user_lock_display)(dpy); +#endif + UnlockDisplay(dpy); + + if (_XIOErrorFunction != NULL) + (*_XIOErrorFunction)(dpy); + else + _XDefaultIOError(dpy); + exit (1); + return 0; +} + + +/* + * This routine can be used to (cheaply) get some memory within a single + * Xlib routine for scratch space. A single buffer is reused each time + * if possible. To be MT safe, you can only call this between a call to + * GetReq* and a call to Data* or _XSend*, or in a context when the thread + * is guaranteed to not unlock the display. + */ +char *_XAllocScratch( + register Display *dpy, + unsigned long nbytes) +{ + if (nbytes > dpy->scratch_length) { + if (dpy->scratch_buffer) Xfree (dpy->scratch_buffer); + if ((dpy->scratch_buffer = Xmalloc((unsigned) nbytes))) + dpy->scratch_length = nbytes; + else dpy->scratch_length = 0; + } + return (dpy->scratch_buffer); +} + +/* + * Scratch space allocator you can call any time, multiple times, and be + * MT safe, but you must hand the buffer back with _XFreeTemp. + */ +char *_XAllocTemp( + register Display *dpy, + unsigned long nbytes) +{ + char *buf; + + buf = _XAllocScratch(dpy, nbytes); + dpy->scratch_buffer = NULL; + dpy->scratch_length = 0; + return buf; +} + +void _XFreeTemp( + register Display *dpy, + char *buf, + unsigned long nbytes) +{ + if (dpy->scratch_buffer) + Xfree(dpy->scratch_buffer); + dpy->scratch_buffer = buf; + dpy->scratch_length = nbytes; +} + +/* + * Given a visual id, find the visual structure for this id on this display. + */ +Visual *_XVIDtoVisual( + Display *dpy, + VisualID id) +{ + register int i, j, k; + register Screen *sp; + register Depth *dp; + register Visual *vp; + for (i = 0; i < dpy->nscreens; i++) { + sp = &dpy->screens[i]; + for (j = 0; j < sp->ndepths; j++) { + dp = &sp->depths[j]; + /* if nvisuals == 0 then visuals will be NULL */ + for (k = 0; k < dp->nvisuals; k++) { + vp = &dp->visuals[k]; + if (vp->visualid == id) return (vp); + } + } + } + return (NULL); +} + +int +XFree (void *data) +{ + Xfree (data); + return 1; +} + +#ifdef _XNEEDBCOPYFUNC +void _Xbcopy(b1, b2, length) + register char *b1, *b2; + register length; +{ + if (b1 < b2) { + b2 += length; + b1 += length; + while (length--) + *--b2 = *--b1; + } else { + while (length--) + *b2++ = *b1++; + } +} +#endif + +#ifdef DataRoutineIsProcedure +void Data( + Display *dpy, + char *data, + long len) +{ + if (dpy->bufptr + (len) <= dpy->bufmax) { + memcpy(dpy->bufptr, data, (int)len); + dpy->bufptr += ((len) + 3) & ~3; + } else { + _XSend(dpy, data, len); + } +} +#endif /* DataRoutineIsProcedure */ + + +#ifdef LONG64 +int +_XData32( + Display *dpy, + register long *data, + unsigned len) +{ + register int *buf; + register long i; + + while (len) { + buf = (int *)dpy->bufptr; + i = dpy->bufmax - (char *)buf; + if (!i) { + _XFlush(dpy); + continue; + } + if (len < i) + i = len; + dpy->bufptr = (char *)buf + i; + len -= i; + i >>= 2; + while (--i >= 0) + *buf++ = *data++; + } + return 0; +} +#endif /* LONG64 */ + +#ifdef WORD64 + +/* + * XXX This is a *really* stupid way of doing this. It should just use + * dpy->bufptr directly, taking into account where in the word it is. + */ + +/* + * Data16 - Place 16 bit data in the buffer. + * + * "dpy" is a pointer to a Display. + * "data" is a pointer to the data. + * "len" is the length in bytes of the data. + */ + +static doData16( + register Display *dpy, + short *data, + unsigned len, + char *packbuffer) +{ + long *lp,*lpack; + long i, nwords,bits; + long mask16 = 0x000000000000ffff; + + lp = (long *)data; + lpack = (long *)packbuffer; + +/* nwords is the number of 16 bit values to be packed, + * the low order 16 bits of each word will be packed + * into 64 bit words + */ + nwords = len >> 1; + bits = 48; + + for(i=0;i<nwords;i++){ + if (bits == 48) *lpack = 0; + *lpack ^= (*lp & mask16) << bits; + bits -= 16 ; + lp++; + if(bits < 0){ + lpack++; + bits = 48; + } + } + Data(dpy, packbuffer, len); +} + +_XData16 ( + Display *dpy, + short *data, + unsigned len) +{ + char packbuffer[PACKBUFFERSIZE]; + unsigned nunits = PACKBUFFERSIZE >> 1; + + for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) { + doData16 (dpy, data, PACKBUFFERSIZE, packbuffer); + } + if (len) doData16 (dpy, data, len, packbuffer); +} + +/* + * Data32 - Place 32 bit data in the buffer. + * + * "dpy" is a pointer to a Display. + * "data" is a pointer to the data. + * "len" is the length in bytes of the data. + */ + +static doData32( + register Display *dpy + long *data, + unsigned len, + char *packbuffer) +{ + long *lp,*lpack; + long i,bits,nwords; + long mask32 = 0x00000000ffffffff; + + lpack = (long *) packbuffer; + lp = data; + +/* nwords is the number of 32 bit values to be packed + * the low order 32 bits of each word will be packed + * into 64 bit words + */ + nwords = len >> 2; + bits = 32; + + for(i=0;i<nwords;i++){ + if (bits == 32) *lpack = 0; + *lpack ^= (*lp & mask32) << bits; + bits = bits ^32; + lp++; + if(bits) + lpack++; + } + Data(dpy, packbuffer, len); +} + +void _XData32( + Display *dpy, + long *data, + unsigned len) +{ + char packbuffer[PACKBUFFERSIZE]; + unsigned nunits = PACKBUFFERSIZE >> 2; + + for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) { + doData32 (dpy, data, PACKBUFFERSIZE, packbuffer); + } + if (len) doData32 (dpy, data, len, packbuffer); +} + +#endif /* WORD64 */ + + +/* Make sure this produces the same string as DefineLocal/DefineSelf in xdm. + * Otherwise, Xau will not be able to find your cookies in the Xauthority file. + * + * Note: POSIX says that the ``nodename'' member of utsname does _not_ have + * to have sufficient information for interfacing to the network, + * and so, you may be better off using gethostname (if it exists). + */ + +#if (defined(_POSIX_SOURCE) && !defined(AIXV3) && !defined(__QNX__)) || defined(hpux) || defined(SVR4) +#define NEED_UTSNAME +#include <sys/utsname.h> +#else +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#endif + +/* + * _XGetHostname - similar to gethostname but allows special processing. + */ +int _XGetHostname ( + char *buf, + int maxlen) +{ + int len; + +#ifdef NEED_UTSNAME + struct utsname name; + + if (maxlen <= 0 || buf == NULL) + return 0; + + uname (&name); + len = strlen (name.nodename); + if (len >= maxlen) len = maxlen - 1; + strncpy (buf, name.nodename, len); + buf[len] = '\0'; +#else + if (maxlen <= 0 || buf == NULL) + return 0; + + buf[0] = '\0'; + (void) gethostname (buf, maxlen); + buf [maxlen - 1] = '\0'; + len = strlen(buf); +#endif /* NEED_UTSNAME */ + return len; +} + + +/* + * _XScreenOfWindow - get the Screen of a given window + */ + +Screen *_XScreenOfWindow(Display *dpy, Window w) +{ + register int i; + Window root; + int x, y; /* dummy variables */ + unsigned int width, height, bw, depth; /* dummy variables */ + + if (XGetGeometry (dpy, w, &root, &x, &y, &width, &height, + &bw, &depth) == False) { + return NULL; + } + for (i = 0; i < ScreenCount (dpy); i++) { /* find root from list */ + if (root == RootWindow (dpy, i)) { + return ScreenOfDisplay (dpy, i); + } + } + return NULL; +} + + +#if defined(WIN32) + +/* + * These functions are intended to be used internally to Xlib only. + * These functions will always prefix the path with a DOS drive in the + * form "<drive-letter>:". As such, these functions are only suitable + * for use by Xlib function that supply a root-based path to some + * particular file, e.g. <ProjectRoot>/lib/X11/locale/locale.dir will + * be converted to "C:/usr/X11R6.3/lib/X11/locale/locale.dir". + */ + +static int access_file (path, pathbuf, len_pathbuf, pathret) + char* path; + char* pathbuf; + int len_pathbuf; + char** pathret; +{ + if (access (path, F_OK) == 0) { + if (strlen (path) < len_pathbuf) + *pathret = pathbuf; + else + *pathret = Xmalloc (strlen (path) + 1); + if (*pathret) { + strcpy (*pathret, path); + return 1; + } + } + return 0; +} + +static int AccessFile (path, pathbuf, len_pathbuf, pathret) + char* path; + char* pathbuf; + int len_pathbuf; + char** pathret; +{ + unsigned long drives; + int i, len; + char* drive; + char buf[MAX_PATH]; + char* bufp; + + /* just try the "raw" name first and see if it works */ + if (access_file (path, pathbuf, len_pathbuf, pathret)) + return 1; + + /* try the places set in the environment */ + drive = getenv ("_XBASEDRIVE"); +#ifdef __UNIXOS2__ + if (!drive) + drive = getenv ("X11ROOT"); +#endif + if (!drive) + drive = "C:"; + len = strlen (drive) + strlen (path); + if (len < MAX_PATH) bufp = buf; + else bufp = Xmalloc (len + 1); + strcpy (bufp, drive); + strcat (bufp, path); + if (access_file (bufp, pathbuf, len_pathbuf, pathret)) { + if (bufp != buf) Xfree (bufp); + return 1; + } + +#ifndef __UNIXOS2__ + /* one last place to look */ + drive = getenv ("HOMEDRIVE"); + if (drive) { + len = strlen (drive) + strlen (path); + if (len < MAX_PATH) bufp = buf; + else bufp = Xmalloc (len + 1); + strcpy (bufp, drive); + strcat (bufp, path); + if (access_file (bufp, pathbuf, len_pathbuf, pathret)) { + if (bufp != buf) Xfree (bufp); + return 1; + } + } + + /* tried everywhere else, go fishing */ +#define C_DRIVE ('C' - 'A') +#define Z_DRIVE ('Z' - 'A') + /* does OS/2 (with or with gcc-emx) have getdrives? */ + drives = _getdrives (); + for (i = C_DRIVE; i <= Z_DRIVE; i++) { /* don't check on A: or B: */ + if ((1 << i) & drives) { + len = 2 + strlen (path); + if (len < MAX_PATH) bufp = buf; + else bufp = Xmalloc (len + 1); + *bufp = 'A' + i; + *(bufp + 1) = ':'; + *(bufp + 2) = '\0'; + strcat (bufp, path); + if (access_file (bufp, pathbuf, len_pathbuf, pathret)) { + if (bufp != buf) Xfree (bufp); + return 1; + } + } + } +#endif + return 0; +} + +int _XOpenFile(path, flags) + _Xconst char* path; + int flags; +{ + char buf[MAX_PATH]; + char* bufp = NULL; + int ret = -1; + UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS); + + if (AccessFile (path, buf, MAX_PATH, &bufp)) + ret = open (bufp, flags); + + (void) SetErrorMode (olderror); + + if (bufp != buf) Xfree (bufp); + + return ret; +} + +int _XOpenFileMode(path, flags, mode) + _Xconst char* path; + int flags; + mode_t mode; +{ + char buf[MAX_PATH]; + char* bufp = NULL; + int ret = -1; + UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS); + + if (AccessFile (path, buf, MAX_PATH, &bufp)) + ret = open (bufp, flags, mode); + + (void) SetErrorMode (olderror); + + if (bufp != buf) Xfree (bufp); + + return ret; +} + +void* _XFopenFile(path, mode) + _Xconst char* path; + _Xconst char* mode; +{ + char buf[MAX_PATH]; + char* bufp = NULL; + void* ret = NULL; + UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS); + + if (AccessFile (path, buf, MAX_PATH, &bufp)) + ret = fopen (bufp, mode); + + (void) SetErrorMode (olderror); + + if (bufp != buf) Xfree (bufp); + + return ret; +} + +int _XAccessFile(path) + _Xconst char* path; +{ + char buf[MAX_PATH]; + char* bufp; + int ret = -1; + UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS); + + ret = AccessFile (path, buf, MAX_PATH, &bufp); + + (void) SetErrorMode (olderror); + + if (bufp != buf) Xfree (bufp); + + return ret; +} + +#endif + +#ifdef WIN32 +#undef _Xdebug +int _Xdebug = 0; +int *_Xdebug_p = &_Xdebug; +void (**_XCreateMutex_fn_p)(LockInfoPtr) = &_XCreateMutex_fn; +void (**_XFreeMutex_fn_p)(LockInfoPtr) = &_XFreeMutex_fn; +void (**_XLockMutex_fn_p)(LockInfoPtr +#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE) + , char * /* file */ + , int /* line */ +#endif + ) = &_XLockMutex_fn; +void (**_XUnlockMutex_fn_p)(LockInfoPtr +#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE) + , char * /* file */ + , int /* line */ +#endif + ) = &_XUnlockMutex_fn; +LockInfoPtr *_Xglobal_lock_p = &_Xglobal_lock; +#endif diff --git a/libX11/src/Xrm.c b/libX11/src/Xrm.c index 7dff61e68..53467aedc 100644 --- a/libX11/src/Xrm.c +++ b/libX11/src/Xrm.c @@ -1,2660 +1,2660 @@ -
-/***********************************************************
-Copyright 1987, 1988, 1990 by Digital Equipment Corporation, Maynard
-
- All Rights Reserved
-
-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 Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL 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 TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-******************************************************************/
-/*
-
-Copyright 1987, 1988, 1990, 1998 The Open Group
-
-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.
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall
-not be used in advertising or otherwise to promote the sale, use or
-other dealings in this Software without prior written authorization
-from The Open Group.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <ctype.h>
-#include "Xlibint.h"
-#include <X11/Xresource.h>
-#include "Xlcint.h"
-#ifdef XTHREADS
-#include "locking.h"
-#endif
-#include <X11/Xos.h>
-#include <sys/stat.h>
-#include "Xresinternal.h"
-#include "Xresource.h"
-
-/*
-
-These Xrm routines allow very fast lookup of resources in the resource
-database. Several usage patterns are exploited:
-
-(1) Widgets get a lot of resources at one time. Rather than look up each from
-scratch, we can precompute the prioritized list of database levels once, then
-search for each resource starting at the beginning of the list.
-
-(2) Many database levels don't contain any leaf resource nodes. There is no
-point in looking for resources on a level that doesn't contain any. This
-information is kept on a per-level basis.
-
-(3) Sometimes the widget instance tree is structured such that you get the same
-class name repeated on the fully qualified widget name. This can result in the
-same database level occuring multiple times on the search list. The code below
-only checks to see if you get two identical search lists in a row, rather than
-look back through all database levels, but in practice this removes all
-duplicates I've ever observed.
-
-Joel McCormack
-
-*/
-
-/*
-
-The Xrm representation has been completely redesigned to substantially reduce
-memory and hopefully improve performance.
-
-The database is structured into two kinds of tables: LTables that contain
-only values, and NTables that contain only other tables.
-
-Some invariants:
-
-The next pointer of the top-level node table points to the top-level leaf
-table, if any.
-
-Within an LTable, for a given name, the tight value always precedes the
-loose value, and if both are present the loose value is always right after
-the tight value.
-
-Within an NTable, all of the entries for a given name are contiguous,
-in the order tight NTable, loose NTable, tight LTable, loose LTable.
-
-Bob Scheifler
-
-*/
-
-static XrmQuark XrmQString, XrmQANY;
-
-typedef Bool (*DBEnumProc)(
- XrmDatabase* /* db */,
- XrmBindingList /* bindings */,
- XrmQuarkList /* quarks */,
- XrmRepresentation* /* type */,
- XrmValue* /* value */,
- XPointer /* closure */
-);
-
-typedef struct _VEntry {
- struct _VEntry *next; /* next in chain */
- XrmQuark name; /* name of this entry */
- unsigned int tight:1; /* 1 if it is a tight binding */
- unsigned int string:1; /* 1 if type is String */
- unsigned int size:30; /* size of value */
-} VEntryRec, *VEntry;
-
-
-typedef struct _DEntry {
- VEntryRec entry; /* entry */
- XrmRepresentation type; /* representation type */
-} DEntryRec, *DEntry;
-
-/* the value is right after the structure */
-#define StringValue(ve) (XPointer)((ve) + 1)
-#define RepType(ve) ((DEntry)(ve))->type
-/* the value is right after the structure */
-#define DataValue(ve) (XPointer)(((DEntry)(ve)) + 1)
-#define RawValue(ve) (char *)((ve)->string ? StringValue(ve) : DataValue(ve))
-
-typedef struct _NTable {
- struct _NTable *next; /* next in chain */
- XrmQuark name; /* name of this entry */
- unsigned int tight:1; /* 1 if it is a tight binding */
- unsigned int leaf:1; /* 1 if children are values */
- unsigned int hasloose:1; /* 1 if has loose children */
- unsigned int hasany:1; /* 1 if has ANY entry */
- unsigned int pad:4; /* unused */
- unsigned int mask:8; /* hash size - 1 */
- unsigned int entries:16; /* number of children */
-} NTableRec, *NTable;
-
-/* the buckets are right after the structure */
-#define NodeBuckets(ne) ((NTable *)((ne) + 1))
-#define NodeHash(ne,q) NodeBuckets(ne)[(q) & (ne)->mask]
-
-/* leaf tables have an extra level of indirection for the buckets,
- * so that resizing can be done without invalidating a search list.
- * This is completely ugly, and wastes some memory, but the Xlib
- * spec doesn't really specify whether invalidation is OK, and the
- * old implementation did not invalidate.
- */
-typedef struct _LTable {
- NTableRec table;
- VEntry *buckets;
-} LTableRec, *LTable;
-
-#define LeafHash(le,q) (le)->buckets[(q) & (le)->table.mask]
-
-/* An XrmDatabase just holds a pointer to the first top-level table.
- * The type name is no longer descriptive, but better to not change
- * the Xresource.h header file. This type also gets used to define
- * XrmSearchList, which is a complete crock, but we'll just leave it
- * and caste types as required.
- */
-typedef struct _XrmHashBucketRec {
- NTable table;
- XPointer mbstate;
- XrmMethods methods;
-#ifdef XTHREADS
- LockInfoRec linfo;
-#endif
-} XrmHashBucketRec;
-
-/* closure used in get/put resource */
-typedef struct _VClosure {
- XrmRepresentation *type; /* type of value */
- XrmValuePtr value; /* value itself */
-} VClosureRec, *VClosure;
-
-/* closure used in get search list */
-typedef struct _SClosure {
- LTable *list; /* search list */
- int idx; /* index of last filled element */
- int limit; /* maximum index */
-} SClosureRec, *SClosure;
-
-/* placed in XrmSearchList to indicate next table is loose only */
-#define LOOSESEARCH ((LTable)1)
-
-/* closure used in enumerate database */
-typedef struct _EClosure {
- XrmDatabase db; /* the database */
- DBEnumProc proc; /* the user proc */
- XPointer closure; /* the user closure */
- XrmBindingList bindings; /* binding list */
- XrmQuarkList quarks; /* quark list */
- int mode; /* XrmEnum<kind> */
-} EClosureRec, *EClosure;
-
-/* types for typecasting ETable based functions to NTable based functions */
-typedef Bool (*getNTableSProcp)(
- NTable table,
- XrmNameList names,
- XrmClassList classes,
- SClosure closure);
-typedef Bool (*getNTableVProcp)(
- NTable table,
- XrmNameList names,
- XrmClassList classes,
- VClosure closure);
-typedef Bool (*getNTableEProcp)(
- NTable table,
- XrmNameList names,
- XrmClassList classes,
- register int level,
- EClosure closure);
-
-/* predicate to determine when to resize a hash table */
-#define GrowthPred(n,m) ((unsigned)(n) > (((m) + 1) << 2))
-
-#define GROW(prev) \
- if (GrowthPred((*prev)->entries, (*prev)->mask)) \
- GrowTable(prev)
-
-/* pick a reasonable value for maximum depth of resource database */
-#define MAXDBDEPTH 100
-
-/* macro used in get/search functions */
-
-/* find an entry named ename, with leafness given by leaf */
-#define NFIND(ename) \
- q = ename; \
- entry = NodeHash(table, q); \
- while (entry && entry->name != q) \
- entry = entry->next; \
- if (leaf && entry && !entry->leaf) { \
- entry = entry->next; \
- if (entry && !entry->leaf) \
- entry = entry->next; \
- if (entry && entry->name != q) \
- entry = (NTable)NULL; \
- }
-
-/* resourceQuarks keeps track of what quarks have been associated with values
- * in all LTables. If a quark has never been used in an LTable, we don't need
- * to bother looking for it.
- */
-
-static unsigned char *resourceQuarks = (unsigned char *)NULL;
-static XrmQuark maxResourceQuark = -1;
-
-/* determines if a quark has been used for a value in any database */
-#define IsResourceQuark(q) ((q) > 0 && (q) <= maxResourceQuark && \
- resourceQuarks[(q) >> 3] & (1 << ((q) & 7)))
-
-typedef unsigned char XrmBits;
-
-#define BSLASH ((XrmBits) (1 << 5))
-#define NORMAL ((XrmBits) (1 << 4))
-#define EOQ ((XrmBits) (1 << 3))
-#define SEP ((XrmBits) (1 << 2))
-#define ENDOF ((XrmBits) (1 << 1))
-#define SPACE (NORMAL|EOQ|SEP|(XrmBits)0)
-#define RSEP (NORMAL|EOQ|SEP|(XrmBits)1)
-#define EOS (EOQ|SEP|ENDOF|(XrmBits)0)
-#define EOL (EOQ|SEP|ENDOF|(XrmBits)1)
-#define BINDING (NORMAL|EOQ)
-#define ODIGIT (NORMAL|(XrmBits)1)
-
-#define next_char(ch,str) xrmtypes[(unsigned char)((ch) = *(++(str)))]
-#define next_mbchar(ch,len,str) xrmtypes[(unsigned char)(ch = (*db->methods->mbchar)(db->mbstate, str, &len), str += len, ch)]
-
-#define is_space(bits) ((bits) == SPACE)
-#define is_EOQ(bits) ((bits) & EOQ)
-#define is_EOF(bits) ((bits) == EOS)
-#define is_EOL(bits) ((bits) & ENDOF)
-#define is_binding(bits) ((bits) == BINDING)
-#define is_odigit(bits) ((bits) == ODIGIT)
-#define is_separator(bits) ((bits) & SEP)
-#define is_nonpcs(bits) (!(bits))
-#define is_normal(bits) ((bits) & NORMAL)
-#define is_simple(bits) ((bits) & (NORMAL|BSLASH))
-#define is_special(bits) ((bits) & (ENDOF|BSLASH))
-
-/* parsing types */
-static XrmBits const xrmtypes[256] = {
- EOS,0,0,0,0,0,0,0,
- 0,SPACE,EOL,0,0,
-#if defined(WIN32) || defined(__UNIXOS2__)
- EOL, /* treat CR the same as LF, just in case */
-#else
- 0,
-#endif
- 0,0,
- 0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,
- SPACE,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,
- NORMAL,NORMAL,BINDING,NORMAL,NORMAL,NORMAL,BINDING,NORMAL,
- ODIGIT,ODIGIT,ODIGIT,ODIGIT,ODIGIT,ODIGIT,ODIGIT,ODIGIT,
- NORMAL,NORMAL,RSEP,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,
- NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,
- NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,
- NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,
- NORMAL,NORMAL,NORMAL,NORMAL,BSLASH,NORMAL,NORMAL,NORMAL,
- NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,
- NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,
- NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,
- NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,0
- /* The rest will be automatically initialized to zero. */
-};
-
-void XrmInitialize(void)
-{
- XrmQString = XrmPermStringToQuark("String");
- XrmQANY = XrmPermStringToQuark("?");
-}
-
-XrmDatabase XrmGetDatabase(
- Display *display)
-{
- XrmDatabase retval;
- LockDisplay(display);
- retval = display->db;
- UnlockDisplay(display);
- return retval;
-}
-
-void XrmSetDatabase(
- Display *display,
- XrmDatabase database)
-{
- LockDisplay(display);
- /* destroy database if set up imlicitely by XGetDefault() */
- if (display->db && (display->flags & XlibDisplayDfltRMDB)) {
- XrmDestroyDatabase(display->db);
- display->flags &= ~XlibDisplayDfltRMDB;
- }
- display->db = database;
- UnlockDisplay(display);
-}
-
-void
-XrmStringToQuarkList(
- register _Xconst char *name,
- register XrmQuarkList quarks) /* RETURN */
-{
- register XrmBits bits;
- register Signature sig = 0;
- register char ch, *tname;
- register int i = 0;
-
- if ((tname = (char *)name)) {
- tname--;
- while (!is_EOF(bits = next_char(ch, tname))) {
- if (is_binding (bits)) {
- if (i) {
- /* Found a complete name */
- *quarks++ = _XrmInternalStringToQuark(name,tname - name,
- sig, False);
- i = 0;
- sig = 0;
- }
- name = tname+1;
- }
- else {
- sig = (sig << 1) + ch; /* Compute the signature. */
- i++;
- }
- }
- *quarks++ = _XrmInternalStringToQuark(name, tname - name, sig, False);
- }
- *quarks = NULLQUARK;
-}
-
-void
-XrmStringToBindingQuarkList(
- register _Xconst char *name,
- register XrmBindingList bindings, /* RETURN */
- register XrmQuarkList quarks) /* RETURN */
-{
- register XrmBits bits;
- register Signature sig = 0;
- register char ch, *tname;
- register XrmBinding binding;
- register int i = 0;
-
- if ((tname = (char *)name)) {
- tname--;
- binding = XrmBindTightly;
- while (!is_EOF(bits = next_char(ch, tname))) {
- if (is_binding (bits)) {
- if (i) {
- /* Found a complete name */
- *bindings++ = binding;
- *quarks++ = _XrmInternalStringToQuark(name, tname - name,
- sig, False);
-
- i = 0;
- sig = 0;
- binding = XrmBindTightly;
- }
- name = tname+1;
-
- if (ch == '*')
- binding = XrmBindLoosely;
- }
- else {
- sig = (sig << 1) + ch; /* Compute the signature. */
- i++;
- }
- }
- *bindings = binding;
- *quarks++ = _XrmInternalStringToQuark(name, tname - name, sig, False);
- }
- *quarks = NULLQUARK;
-}
-
-#ifdef DEBUG
-
-static void PrintQuarkList(
- XrmQuarkList quarks,
- FILE *stream)
-{
- Bool firstNameSeen;
-
- for (firstNameSeen = False; *quarks; quarks++) {
- if (firstNameSeen) {
- (void) fprintf(stream, ".");
- }
- firstNameSeen = True;
- (void) fputs(XrmQuarkToString(*quarks), stream);
- }
-} /* PrintQuarkList */
-
-#endif /* DEBUG */
-
-
-/*
- * Fallback methods for Xrm parsing.
- * Simulate a C locale. No state needed here.
- */
-
-static void
-c_mbnoop(
- XPointer state)
-{
-}
-
-static char
-c_mbchar(
- XPointer state,
- const char *str,
- int *lenp)
-{
- *lenp = 1;
- return *str;
-}
-
-static const char *
-c_lcname(
- XPointer state)
-{
- return "C";
-}
-
-static const XrmMethodsRec mb_methods = {
- c_mbnoop, /* mbinit */
- c_mbchar, /* mbchar */
- c_mbnoop, /* mbfinish */
- c_lcname, /* lcname */
- c_mbnoop /* destroy */
-};
-
-
-static XrmDatabase NewDatabase(void)
-{
- register XrmDatabase db;
-
- db = (XrmDatabase) Xmalloc(sizeof(XrmHashBucketRec));
- if (db) {
- _XCreateMutex(&db->linfo);
- db->table = (NTable)NULL;
- db->mbstate = (XPointer)NULL;
- db->methods = _XrmInitParseInfo(&db->mbstate);
- if (!db->methods)
- db->methods = &mb_methods;
- }
- return db;
-}
-
-/* move all values from ftable to ttable, and free ftable's buckets.
- * ttable is quaranteed empty to start with.
- */
-static void MoveValues(
- LTable ftable,
- register LTable ttable)
-{
- register VEntry fentry, nfentry;
- register VEntry *prev;
- register VEntry *bucket;
- register VEntry tentry;
- register int i;
-
- for (i = ftable->table.mask, bucket = ftable->buckets; i >= 0; i--) {
- for (fentry = *bucket++; fentry; fentry = nfentry) {
- prev = &LeafHash(ttable, fentry->name);
- tentry = *prev;
- *prev = fentry;
- /* chain on all with same name, to preserve invariant order */
- while ((nfentry = fentry->next) && nfentry->name == fentry->name)
- fentry = nfentry;
- fentry->next = tentry;
- }
- }
- Xfree((char *)ftable->buckets);
-}
-
-/* move all tables from ftable to ttable, and free ftable.
- * ttable is quaranteed empty to start with.
- */
-static void MoveTables(
- NTable ftable,
- register NTable ttable)
-{
- register NTable fentry, nfentry;
- register NTable *prev;
- register NTable *bucket;
- register NTable tentry;
- register int i;
-
- for (i = ftable->mask, bucket = NodeBuckets(ftable); i >= 0; i--) {
- for (fentry = *bucket++; fentry; fentry = nfentry) {
- prev = &NodeHash(ttable, fentry->name);
- tentry = *prev;
- *prev = fentry;
- /* chain on all with same name, to preserve invariant order */
- while ((nfentry = fentry->next) && nfentry->name == fentry->name)
- fentry = nfentry;
- fentry->next = tentry;
- }
- }
- Xfree((char *)ftable);
-}
-
-/* grow the table, based on current number of entries */
-static void GrowTable(
- NTable *prev)
-{
- register NTable table;
- register int i;
-
- table = *prev;
- i = table->mask;
- if (i == 255) /* biggest it gets */
- return;
- while (i < 255 && GrowthPred(table->entries, i))
- i = (i << 1) + 1;
- i++; /* i is now the new size */
- if (table->leaf) {
- register LTable ltable;
- LTableRec otable;
-
- ltable = (LTable)table;
- /* cons up a copy to make MoveValues look symmetric */
- otable = *ltable;
- ltable->buckets = Xcalloc(i, sizeof(VEntry));
- if (!ltable->buckets) {
- ltable->buckets = otable.buckets;
- return;
- }
- ltable->table.mask = i - 1;
- MoveValues(&otable, ltable);
- } else {
- register NTable ntable;
-
- ntable = Xcalloc(1, sizeof(NTableRec) + (i * sizeof(NTable)));
- if (!ntable)
- return;
- *ntable = *table;
- ntable->mask = i - 1;
- *prev = ntable;
- MoveTables(table, ntable);
- }
-}
-
-/* merge values from ftable into *pprev, destroy ftable in the process */
-static void MergeValues(
- LTable ftable,
- NTable *pprev,
- Bool override)
-{
- register VEntry fentry, tentry;
- register VEntry *prev;
- register LTable ttable;
- VEntry *bucket;
- int i;
- register XrmQuark q;
-
- ttable = (LTable)*pprev;
- if (ftable->table.hasloose)
- ttable->table.hasloose = 1;
- for (i = ftable->table.mask, bucket = ftable->buckets;
- i >= 0;
- i--, bucket++) {
- for (fentry = *bucket; fentry; ) {
- q = fentry->name;
- prev = &LeafHash(ttable, q);
- tentry = *prev;
- while (tentry && tentry->name != q)
- tentry = *(prev = &tentry->next);
- /* note: test intentionally uses fentry->name instead of q */
- /* permits serendipitous inserts */
- while (tentry && tentry->name == fentry->name) {
- /* if tentry is earlier, skip it */
- if (!fentry->tight && tentry->tight) {
- tentry = *(prev = &tentry->next);
- continue;
- }
- if (fentry->tight != tentry->tight) {
- /* no match, chain in fentry */
- *prev = fentry;
- prev = &fentry->next;
- fentry = *prev;
- *prev = tentry;
- ttable->table.entries++;
- } else if (override) {
- /* match, chain in fentry, splice out and free tentry */
- *prev = fentry;
- prev = &fentry->next;
- fentry = *prev;
- *prev = tentry->next;
- /* free the overridden entry */
- Xfree((char *)tentry);
- /* get next tentry */
- tentry = *prev;
- } else {
- /* match, discard fentry */
- prev = &tentry->next;
- tentry = fentry; /* use as a temp var */
- fentry = fentry->next;
- /* free the overpowered entry */
- Xfree((char *)tentry);
- /* get next tentry */
- tentry = *prev;
- }
- if (!fentry)
- break;
- }
- /* at this point, tentry cannot match any fentry named q */
- /* chain in all bindings together, preserve invariant order */
- while (fentry && fentry->name == q) {
- *prev = fentry;
- prev = &fentry->next;
- fentry = *prev;
- *prev = tentry;
- ttable->table.entries++;
- }
- }
- }
- Xfree((char *)ftable->buckets);
- Xfree((char *)ftable);
- /* resize if necessary, now that we're all done */
- GROW(pprev);
-}
-
-/* merge tables from ftable into *pprev, destroy ftable in the process */
-static void MergeTables(
- NTable ftable,
- NTable *pprev,
- Bool override)
-{
- register NTable fentry, tentry;
- NTable nfentry;
- register NTable *prev;
- register NTable ttable;
- NTable *bucket;
- int i;
- register XrmQuark q;
-
- ttable = *pprev;
- if (ftable->hasloose)
- ttable->hasloose = 1;
- if (ftable->hasany)
- ttable->hasany = 1;
- for (i = ftable->mask, bucket = NodeBuckets(ftable);
- i >= 0;
- i--, bucket++) {
- for (fentry = *bucket; fentry; ) {
- q = fentry->name;
- prev = &NodeHash(ttable, q);
- tentry = *prev;
- while (tentry && tentry->name != q)
- tentry = *(prev = &tentry->next);
- /* note: test intentionally uses fentry->name instead of q */
- /* permits serendipitous inserts */
- while (tentry && tentry->name == fentry->name) {
- /* if tentry is earlier, skip it */
- if ((fentry->leaf && !tentry->leaf) ||
- (!fentry->tight && tentry->tight &&
- (fentry->leaf || !tentry->leaf))) {
- tentry = *(prev = &tentry->next);
- continue;
- }
- nfentry = fentry->next;
- if (fentry->leaf != tentry->leaf ||
- fentry->tight != tentry->tight) {
- /* no match, just chain in */
- *prev = fentry;
- *(prev = &fentry->next) = tentry;
- ttable->entries++;
- } else {
- if (fentry->leaf)
- MergeValues((LTable)fentry, prev, override);
- else
- MergeTables(fentry, prev, override);
- /* bump to next tentry */
- tentry = *(prev = &(*prev)->next);
- }
- /* bump to next fentry */
- fentry = nfentry;
- if (!fentry)
- break;
- }
- /* at this point, tentry cannot match any fentry named q */
- /* chain in all bindings together, preserve invariant order */
- while (fentry && fentry->name == q) {
- *prev = fentry;
- prev = &fentry->next;
- fentry = *prev;
- *prev = tentry;
- ttable->entries++;
- }
- }
- }
- Xfree((char *)ftable);
- /* resize if necessary, now that we're all done */
- GROW(pprev);
-}
-
-void XrmCombineDatabase(
- XrmDatabase from, XrmDatabase *into,
- Bool override)
-{
- register NTable *prev;
- register NTable ftable, ttable, nftable;
-
- if (!*into) {
- *into = from;
- } else if (from) {
- _XLockMutex(&from->linfo);
- _XLockMutex(&(*into)->linfo);
- if ((ftable = from->table)) {
- prev = &(*into)->table;
- ttable = *prev;
- if (!ftable->leaf) {
- nftable = ftable->next;
- if (ttable && !ttable->leaf) {
- /* both have node tables, merge them */
- MergeTables(ftable, prev, override);
- /* bump to into's leaf table, if any */
- ttable = *(prev = &(*prev)->next);
- } else {
- /* into has no node table, link from's in */
- *prev = ftable;
- *(prev = &ftable->next) = ttable;
- }
- /* bump to from's leaf table, if any */
- ftable = nftable;
- } else {
- /* bump to into's leaf table, if any */
- if (ttable && !ttable->leaf)
- ttable = *(prev = &ttable->next);
- }
- if (ftable) {
- /* if into has a leaf, merge, else insert */
- if (ttable)
- MergeValues((LTable)ftable, prev, override);
- else
- *prev = ftable;
- }
- }
- (from->methods->destroy)(from->mbstate);
- _XUnlockMutex(&from->linfo);
- _XFreeMutex(&from->linfo);
- Xfree((char *)from);
- _XUnlockMutex(&(*into)->linfo);
- }
-}
-
-void XrmMergeDatabases(
- XrmDatabase from, XrmDatabase *into)
-{
- XrmCombineDatabase(from, into, True);
-}
-
-/* store a value in the database, overriding any existing entry */
-static void PutEntry(
- XrmDatabase db,
- XrmBindingList bindings,
- XrmQuarkList quarks,
- XrmRepresentation type,
- XrmValuePtr value)
-{
- register NTable *pprev, *prev;
- register NTable table;
- register XrmQuark q;
- register VEntry *vprev;
- register VEntry entry;
- NTable *nprev, *firstpprev;
-
-#define NEWTABLE(q,i) \
- table = (NTable)Xmalloc(sizeof(LTableRec)); \
- if (!table) \
- return; \
- table->name = q; \
- table->hasloose = 0; \
- table->hasany = 0; \
- table->mask = 0; \
- table->entries = 0; \
- if (quarks[i]) { \
- table->leaf = 0; \
- nprev = NodeBuckets(table); \
- } else { \
- table->leaf = 1; \
- if (!(nprev = (NTable *)Xmalloc(sizeof(VEntry *)))) {\
- Xfree(table); \
- return; \
- } \
- ((LTable)table)->buckets = (VEntry *)nprev; \
- } \
- *nprev = (NTable)NULL; \
- table->next = *prev; \
- *prev = table
-
- if (!db || !*quarks)
- return;
- table = *(prev = &db->table);
- /* if already at leaf, bump to the leaf table */
- if (!quarks[1] && table && !table->leaf)
- table = *(prev = &table->next);
- pprev = prev;
- if (!table || (quarks[1] && table->leaf)) {
- /* no top-level node table, create one and chain it in */
- NEWTABLE(NULLQUARK,1);
- table->tight = 1; /* arbitrary */
- prev = nprev;
- } else {
- /* search along until we need a value */
- while (quarks[1]) {
- q = *quarks;
- table = *(prev = &NodeHash(table, q));
- while (table && table->name != q)
- table = *(prev = &table->next);
- if (!table)
- break; /* not found */
- if (quarks[2]) {
- if (table->leaf)
- break; /* not found */
- } else {
- if (!table->leaf) {
- /* bump to leaf table, if any */
- table = *(prev = &table->next);
- if (!table || table->name != q)
- break; /* not found */
- if (!table->leaf) {
- /* bump to leaf table, if any */
- table = *(prev = &table->next);
- if (!table || table->name != q)
- break; /* not found */
- }
- }
- }
- if (*bindings == XrmBindTightly) {
- if (!table->tight)
- break; /* not found */
- } else {
- if (table->tight) {
- /* bump to loose table, if any */
- table = *(prev = &table->next);
- if (!table || table->name != q ||
- !quarks[2] != table->leaf)
- break; /* not found */
- }
- }
- /* found that one, bump to next quark */
- pprev = prev;
- quarks++;
- bindings++;
- }
- if (!quarks[1]) {
- /* found all the way to a leaf */
- q = *quarks;
- entry = *(vprev = &LeafHash((LTable)table, q));
- while (entry && entry->name != q)
- entry = *(vprev = &entry->next);
- /* if want loose and have tight, bump to next entry */
- if (entry && *bindings == XrmBindLoosely && entry->tight)
- entry = *(vprev = &entry->next);
- if (entry && entry->name == q &&
- (*bindings == XrmBindTightly) == entry->tight) {
- /* match, need to override */
- if ((type == XrmQString) == entry->string &&
- entry->size == value->size) {
- /* update type if not String, can be different */
- if (!entry->string)
- RepType(entry) = type;
- /* identical size, just overwrite value */
- memcpy(RawValue(entry), (char *)value->addr, value->size);
- return;
- }
- /* splice out and free old entry */
- *vprev = entry->next;
- Xfree((char *)entry);
- (*pprev)->entries--;
- }
- /* this is where to insert */
- prev = (NTable *)vprev;
- }
- }
- /* keep the top table, because we may have to grow it */
- firstpprev = pprev;
- /* iterate until we get to the leaf */
- while (quarks[1]) {
- /* build a new table and chain it in */
- NEWTABLE(*quarks,2);
- if (*quarks++ == XrmQANY)
- (*pprev)->hasany = 1;
- if (*bindings++ == XrmBindTightly) {
- table->tight = 1;
- } else {
- table->tight = 0;
- (*pprev)->hasloose = 1;
- }
- (*pprev)->entries++;
- pprev = prev;
- prev = nprev;
- }
- /* now allocate the value entry */
- entry = (VEntry)Xmalloc(((type == XrmQString) ?
- sizeof(VEntryRec) : sizeof(DEntryRec)) +
- value->size);
- if (!entry)
- return;
- entry->name = q = *quarks;
- if (*bindings == XrmBindTightly) {
- entry->tight = 1;
- } else {
- entry->tight = 0;
- (*pprev)->hasloose = 1;
- }
- /* chain it in, with a bit of type cast ugliness */
- entry->next = *((VEntry *)prev);
- *((VEntry *)prev) = entry;
- entry->size = value->size;
- if (type == XrmQString) {
- entry->string = 1;
- } else {
- entry->string = 0;
- RepType(entry) = type;
- }
- /* save a copy of the value */
- memcpy(RawValue(entry), (char *)value->addr, value->size);
- (*pprev)->entries++;
- /* this is a new leaf, need to remember it for search lists */
- if (q > maxResourceQuark) {
- unsigned oldsize = (maxResourceQuark + 1) >> 3;
- unsigned size = ((q | 0x7f) + 1) >> 3; /* reallocate in chunks */
- if (resourceQuarks) {
- unsigned char *prevQuarks = resourceQuarks;
-
- resourceQuarks = (unsigned char *)Xrealloc((char *)resourceQuarks,
- size);
- if (!resourceQuarks) {
- Xfree(prevQuarks);
- }
- } else
- resourceQuarks = (unsigned char *)Xmalloc(size);
- if (resourceQuarks) {
- bzero((char *)&resourceQuarks[oldsize], size - oldsize);
- maxResourceQuark = (size << 3) - 1;
- } else {
- maxResourceQuark = -1;
- }
- }
- if (q > 0 && resourceQuarks)
- resourceQuarks[q >> 3] |= 1 << (q & 0x7);
- GROW(firstpprev);
-
-#undef NEWTABLE
-}
-
-void XrmQPutResource(
- XrmDatabase *pdb,
- XrmBindingList bindings,
- XrmQuarkList quarks,
- XrmRepresentation type,
- XrmValuePtr value)
-{
- if (!*pdb) *pdb = NewDatabase();
- _XLockMutex(&(*pdb)->linfo);
- PutEntry(*pdb, bindings, quarks, type, value);
- _XUnlockMutex(&(*pdb)->linfo);
-}
-
-void
-XrmPutResource(
- XrmDatabase *pdb,
- _Xconst char *specifier,
- _Xconst char *type,
- XrmValuePtr value)
-{
- XrmBinding bindings[MAXDBDEPTH+1];
- XrmQuark quarks[MAXDBDEPTH+1];
-
- if (!*pdb) *pdb = NewDatabase();
- _XLockMutex(&(*pdb)->linfo);
- XrmStringToBindingQuarkList(specifier, bindings, quarks);
- PutEntry(*pdb, bindings, quarks, XrmStringToQuark(type), value);
- _XUnlockMutex(&(*pdb)->linfo);
-}
-
-void
-XrmQPutStringResource(
- XrmDatabase *pdb,
- XrmBindingList bindings,
- XrmQuarkList quarks,
- _Xconst char *str)
-{
- XrmValue value;
-
- if (!*pdb) *pdb = NewDatabase();
- value.addr = (XPointer) str;
- value.size = strlen(str)+1;
- _XLockMutex(&(*pdb)->linfo);
- PutEntry(*pdb, bindings, quarks, XrmQString, &value);
- _XUnlockMutex(&(*pdb)->linfo);
-}
-
-/* Function Name: GetDatabase
- * Description: Parses a string and stores it as a database.
- * Arguments: db - the database.
- * str - a pointer to the string containing the database.
- * filename - source filename, if any.
- * doall - whether to do all lines or just one
- */
-
-/*
- * This function is highly optimized to inline as much as possible.
- * Be very careful with modifications, or simplifications, as they
- * may adversely affect the performance.
- *
- * Chris Peterson, MIT X Consortium 5/17/90.
- */
-
-/*
- * Xlib spec says max 100 quarks in a lookup, will stop and return if
- * return if any single production's lhs has more than 100 components.
- */
-#define QLIST_SIZE 100
-
-/*
- * This should be big enough to handle things like the XKeysymDB or biggish
- * ~/.Xdefaults or app-defaults files. Anything bigger will be allocated on
- * the heap.
- */
-#define DEF_BUFF_SIZE 8192
-
-static void GetIncludeFile(
- XrmDatabase db,
- _Xconst char *base,
- _Xconst char *fname,
- int fnamelen);
-
-static void GetDatabase(
- XrmDatabase db,
- _Xconst register char *str,
- _Xconst char *filename,
- Bool doall)
-{
- char *rhs;
- char *lhs, lhs_s[DEF_BUFF_SIZE];
- XrmQuark quarks[QLIST_SIZE + 1]; /* allow for a terminal NullQuark */
- XrmBinding bindings[QLIST_SIZE + 1];
-
- register char *ptr;
- register XrmBits bits = 0;
- register char c;
- register Signature sig;
- register char *ptr_max;
- register int num_quarks;
- register XrmBindingList t_bindings;
-
- int len, alloc_chars;
- unsigned long str_len;
- XrmValue value;
- Bool only_pcs;
- Bool dolines;
-
- if (!db)
- return;
-
- /*
- * if strlen (str) < DEF_BUFF_SIZE allocate buffers on the stack for
- * speed otherwise malloc the buffer. From a buffer overflow standpoint
- * we can be sure that neither: a) a component on the lhs, or b) a
- * value on the rhs, will be longer than the overall length of str,
- * i.e. strlen(str).
- *
- * This should give good performance when parsing "*foo: bar" type
- * databases as might be passed with -xrm command line options; but
- * with larger databases, e.g. .Xdefaults, app-defaults, or KeysymDB
- * files, the size of the buffers will be overly large. One way
- * around this would be to double-parse each production with a resulting
- * performance hit. In any event we can be assured that a lhs component
- * name or a rhs value won't be longer than str itself.
- */
-
- str_len = strlen (str);
- if (DEF_BUFF_SIZE > str_len) lhs = lhs_s;
- else if ((lhs = (char*) Xmalloc (str_len)) == NULL)
- return;
-
- alloc_chars = DEF_BUFF_SIZE < str_len ? str_len : DEF_BUFF_SIZE;
- if ((rhs = (char*) Xmalloc (alloc_chars)) == NULL) {
- if (lhs != lhs_s) Xfree (lhs);
- return;
- }
-
- (*db->methods->mbinit)(db->mbstate);
- str--;
- dolines = True;
- while (!is_EOF(bits) && dolines) {
- dolines = doall;
-
- /*
- * First: Remove extra whitespace.
- */
-
- do {
- bits = next_char(c, str);
- } while is_space(bits);
-
- /*
- * Ignore empty lines.
- */
-
- if (is_EOL(bits))
- continue; /* start a new line. */
-
- /*
- * Second: check the first character in a line to see if it is
- * "!" signifying a comment, or "#" signifying a directive.
- */
-
- if (c == '!') { /* Comment, spin to next newline */
- while (is_simple(bits = next_char(c, str))) {}
- if (is_EOL(bits))
- continue;
- while (!is_EOL(bits = next_mbchar(c, len, str))) {}
- str--;
- continue; /* start a new line. */
- }
-
- if (c == '#') { /* Directive */
- /* remove extra whitespace */
- only_pcs = True;
- while (is_space(bits = next_char(c, str))) {};
- /* only "include" directive is currently defined */
- if (!strncmp(str, "include", 7)) {
- str += (7-1);
- /* remove extra whitespace */
- while (is_space(bits = next_char(c, str))) {};
- /* must have a starting " */
- if (c == '"') {
- _Xconst char *fname = str+1;
- len = 0;
- do {
- if (only_pcs) {
- bits = next_char(c, str);
- if (is_nonpcs(bits))
- only_pcs = False;
- }
- if (!only_pcs)
- bits = next_mbchar(c, len, str);
- } while (c != '"' && !is_EOL(bits));
- /* must have an ending " */
- if (c == '"')
- GetIncludeFile(db, filename, fname, str - len - fname);
- }
- }
- /* spin to next newline */
- if (only_pcs) {
- while (is_simple(bits))
- bits = next_char(c, str);
- if (is_EOL(bits))
- continue;
- }
- while (!is_EOL(bits))
- bits = next_mbchar(c, len, str);
- str--;
- continue; /* start a new line. */
- }
-
- /*
- * Third: loop through the LHS of the resource specification
- * storing characters and converting this to a Quark.
- */
-
- num_quarks = 0;
- t_bindings = bindings;
-
- sig = 0;
- ptr = lhs;
- *t_bindings = XrmBindTightly;
- for(;;) {
- if (!is_binding(bits)) {
- while (!is_EOQ(bits)) {
- *ptr++ = c;
- sig = (sig << 1) + c; /* Compute the signature. */
- bits = next_char(c, str);
- }
-
- quarks[num_quarks++] =
- _XrmInternalStringToQuark(lhs, ptr - lhs, sig, False);
-
- if (num_quarks > QLIST_SIZE) {
- Xfree(rhs);
- if (lhs != lhs_s) Xfree (lhs);
- (*db->methods->mbfinish)(db->mbstate);
- return;
- }
-
- if (is_separator(bits)) {
- if (!is_space(bits))
- break;
-
- /* Remove white space */
- do {
- *ptr++ = c;
- sig = (sig << 1) + c; /* Compute the signature. */
- } while (is_space(bits = next_char(c, str)));
-
- /*
- * The spec doesn't permit it, but support spaces
- * internal to resource name/class
- */
-
- if (is_separator(bits))
- break;
- num_quarks--;
- continue;
- }
-
- if (c == '.')
- *(++t_bindings) = XrmBindTightly;
- else
- *(++t_bindings) = XrmBindLoosely;
-
- sig = 0;
- ptr = lhs;
- }
- else {
- /*
- * Magic unspecified feature #254.
- *
- * If two separators appear with no Text between them then
- * ignore them.
- *
- * If anyone of those separators is a '*' then the binding
- * will be loose, otherwise it will be tight.
- */
-
- if (c == '*')
- *t_bindings = XrmBindLoosely;
- }
-
- bits = next_char(c, str);
- }
-
- quarks[num_quarks] = NULLQUARK;
-
- /*
- * Make sure that there is a ':' in this line.
- */
-
- if (c != ':') {
- char oldc;
-
- /*
- * A parsing error has occured, toss everything on the line
- * a new_line can still be escaped with a '\'.
- */
-
- while (is_normal(bits))
- bits = next_char(c, str);
- if (is_EOL(bits))
- continue;
- bits = next_mbchar(c, len, str);
- do {
- oldc = c;
- bits = next_mbchar(c, len, str);
- } while (c && (c != '\n' || oldc == '\\'));
- str--;
- continue;
- }
-
- /*
- * I now have a quark and binding list for the entire left hand
- * side. "c" currently points to the ":" separating the left hand
- * side for the right hand side. It is time to begin processing
- * the right hand side.
- */
-
- /*
- * Fourth: Remove more whitespace
- */
-
- for(;;) {
- if (is_space(bits = next_char(c, str)))
- continue;
- if (c != '\\')
- break;
- bits = next_char(c, str);
- if (c == '\n')
- continue;
- str--;
- bits = BSLASH;
- c = '\\';
- break;
- }
-
- /*
- * Fifth: Process the right hand side.
- */
-
- ptr = rhs;
- ptr_max = ptr + alloc_chars - 4;
- only_pcs = True;
- len = 1;
-
- for(;;) {
-
- /*
- * Tight loop for the normal case: Non backslash, non-end of value
- * character that will fit into the allocated buffer.
- */
-
- if (only_pcs) {
- while (is_normal(bits) && ptr < ptr_max) {
- *ptr++ = c;
- bits = next_char(c, str);
- }
- if (is_EOL(bits))
- break;
- if (is_nonpcs(bits)) {
- only_pcs = False;
- bits = next_mbchar(c, len, str);
- }
- }
- while (!is_special(bits) && ptr + len <= ptr_max) {
- len = -len;
- while (len)
- *ptr++ = str[len++];
- if (*str == '\0') {
- bits = EOS;
- break;
- }
- bits = next_mbchar(c, len, str);
- }
-
- if (is_EOL(bits)) {
- str--;
- break;
- }
-
- if (c == '\\') {
- /*
- * We need to do some magic after a backslash.
- */
- Bool read_next = True;
-
- if (only_pcs) {
- bits = next_char(c, str);
- if (is_nonpcs(bits))
- only_pcs = False;
- }
- if (!only_pcs)
- bits = next_mbchar(c, len, str);
-
- if (is_EOL(bits)) {
- if (is_EOF(bits))
- continue;
- } else if (c == 'n') {
- /*
- * "\n" means insert a newline.
- */
- *ptr++ = '\n';
- } else if (c == '\\') {
- /*
- * "\\" completes to just one backslash.
- */
- *ptr++ = '\\';
- } else {
- /*
- * pick up to three octal digits after the '\'.
- */
- char temp[3];
- int count = 0;
- while (is_odigit(bits) && count < 3) {
- temp[count++] = c;
- if (only_pcs) {
- bits = next_char(c, str);
- if (is_nonpcs(bits))
- only_pcs = False;
- }
- if (!only_pcs)
- bits = next_mbchar(c, len, str);
- }
-
- /*
- * If we found three digits then insert that octal code
- * into the value string as a character.
- */
-
- if (count == 3) {
- *ptr++ = (unsigned char) ((temp[0] - '0') * 0100 +
- (temp[1] - '0') * 010 +
- (temp[2] - '0'));
- }
- else {
- int tcount;
-
- /*
- * Otherwise just insert those characters into the
- * string, since no special processing is needed on
- * numerics we can skip the special processing.
- */
-
- for (tcount = 0; tcount < count; tcount++) {
- *ptr++ = temp[tcount]; /* print them in
- the correct order */
- }
- }
- read_next = False;
- }
- if (read_next) {
- if (only_pcs) {
- bits = next_char(c, str);
- if (is_nonpcs(bits))
- only_pcs = False;
- }
- if (!only_pcs)
- bits = next_mbchar(c, len, str);
- }
- }
-
- /*
- * It is important to make sure that there is room for at least
- * four more characters in the buffer, since I can add that
- * many characters into the buffer after a backslash has occured.
- */
-
- if (ptr + len > ptr_max) {
- char * temp_str;
-
- alloc_chars += BUFSIZ/10;
- temp_str = Xrealloc(rhs, sizeof(char) * alloc_chars);
-
- if (!temp_str) {
- Xfree(rhs);
- if (lhs != lhs_s) Xfree (lhs);
- (*db->methods->mbfinish)(db->mbstate);
- return;
- }
-
- ptr = temp_str + (ptr - rhs); /* reset pointer. */
- rhs = temp_str;
- ptr_max = rhs + alloc_chars - 4;
- }
- }
-
- /*
- * Lastly: Terminate the value string, and store this entry
- * into the database.
- */
-
- *ptr++ = '\0';
-
- /* Store it in database */
- value.size = ptr - rhs;
- value.addr = (XPointer) rhs;
-
- PutEntry(db, bindings, quarks, XrmQString, &value);
- }
-
- if (lhs != lhs_s) Xfree (lhs);
- Xfree (rhs);
-
- (*db->methods->mbfinish)(db->mbstate);
-}
-
-void
-XrmPutStringResource(
- XrmDatabase *pdb,
- _Xconst char*specifier,
- _Xconst char*str)
-{
- XrmValue value;
- XrmBinding bindings[MAXDBDEPTH+1];
- XrmQuark quarks[MAXDBDEPTH+1];
-
- if (!*pdb) *pdb = NewDatabase();
- XrmStringToBindingQuarkList(specifier, bindings, quarks);
- value.addr = (XPointer) str;
- value.size = strlen(str)+1;
- _XLockMutex(&(*pdb)->linfo);
- PutEntry(*pdb, bindings, quarks, XrmQString, &value);
- _XUnlockMutex(&(*pdb)->linfo);
-}
-
-
-void
-XrmPutLineResource(
- XrmDatabase *pdb,
- _Xconst char*line)
-{
- if (!*pdb) *pdb = NewDatabase();
- _XLockMutex(&(*pdb)->linfo);
- GetDatabase(*pdb, line, (char *)NULL, False);
- _XUnlockMutex(&(*pdb)->linfo);
-}
-
-XrmDatabase
-XrmGetStringDatabase(
- _Xconst char *data)
-{
- XrmDatabase db;
-
- db = NewDatabase();
- _XLockMutex(&db->linfo);
- GetDatabase(db, data, (char *)NULL, True);
- _XUnlockMutex(&db->linfo);
- return db;
-}
-
-/* Function Name: ReadInFile
- * Description: Reads the file into a buffer.
- * Arguments: filename - the name of the file.
- * Returns: An allocated string containing the contents of the file.
- */
-
-static char *
-ReadInFile(_Xconst char *filename)
-{
- register int fd, size;
- char * filebuf;
-
-#ifdef __UNIXOS2__
- filename = __XOS2RedirRoot(filename);
-#endif
-
- /*
- * MS-Windows and OS/2 note: Default open mode includes O_TEXT
- */
- if ( (fd = _XOpenFile (filename, O_RDONLY)) == -1 )
- return (char *)NULL;
-
- /*
- * MS-Windows and OS/2 note: depending on how the sources are
- * untarred, the newlines in resource files may or may not have
- * been expanded to CRLF. Either way the size returned by fstat
- * is sufficient to read the file into because in text-mode any
- * CRLFs in a file will be converted to newlines (LF) with the
- * result that the number of bytes actually read with be <=
- * to the size returned by fstat.
- */
- {
- struct stat status_buffer;
- if ( (fstat(fd, &status_buffer)) == -1 ) {
- close (fd);
- return (char *)NULL;
- } else
- size = status_buffer.st_size;
- }
-
- if (!(filebuf = Xmalloc(size + 1))) { /* leave room for '\0' */
- close(fd);
- return (char *)NULL;
- }
- size = read (fd, filebuf, size);
-
-#ifdef __UNIXOS2__
- { /* kill CRLF */
- int i,k;
- for (i=k=0; i<size; i++)
- if (filebuf[i] != 0x0d) {
- filebuf[k++] = filebuf[i];
- }
- filebuf[k] = 0;
- }
-#endif
-
- if (size < 0) {
- close (fd);
- Xfree(filebuf);
- return (char *)NULL;
- }
- close (fd);
-
- filebuf[size] = '\0'; /* NULL terminate it. */
- return filebuf;
-}
-
-static void
-GetIncludeFile(
- XrmDatabase db,
- _Xconst char *base,
- _Xconst char *fname,
- int fnamelen)
-{
- int len;
- char *str;
- char realfname[BUFSIZ];
-
- if (fnamelen <= 0 || fnamelen >= BUFSIZ)
- return;
- if (*fname != '/' && base && (str = strrchr(base, '/'))) {
- len = str - base + 1;
- if (len + fnamelen >= BUFSIZ)
- return;
- strncpy(realfname, base, len);
- strncpy(realfname + len, fname, fnamelen);
- realfname[len + fnamelen] = '\0';
- } else {
- strncpy(realfname, fname, fnamelen);
- realfname[fnamelen] = '\0';
- }
- if (!(str = ReadInFile(realfname)))
- return;
- GetDatabase(db, str, realfname, True);
- Xfree(str);
-}
-
-XrmDatabase
-XrmGetFileDatabase(
- _Xconst char *filename)
-{
- XrmDatabase db;
- char *str;
-
- if (!(str = ReadInFile(filename)))
- return (XrmDatabase)NULL;
-
- db = NewDatabase();
- _XLockMutex(&db->linfo);
- GetDatabase(db, str, filename, True);
- _XUnlockMutex(&db->linfo);
- Xfree(str);
- return db;
-}
-
-Status
-XrmCombineFileDatabase(
- _Xconst char *filename,
- XrmDatabase *target,
- Bool override)
-{
- XrmDatabase db;
- char *str;
-
- if (!(str = ReadInFile(filename)))
- return 0;
- if (override) {
- db = *target;
- if (!db)
- *target = db = NewDatabase();
- } else
- db = NewDatabase();
- _XLockMutex(&db->linfo);
- GetDatabase(db, str, filename, True);
- _XUnlockMutex(&db->linfo);
- Xfree(str);
- if (!override)
- XrmCombineDatabase(db, target, False);
- return 1;
-}
-
-/* call the user proc for every value in the table, arbitrary order.
- * stop if user proc returns True. level is current depth in database.
- */
-/*ARGSUSED*/
-static Bool EnumLTable(
- LTable table,
- XrmNameList names,
- XrmClassList classes,
- register int level,
- register EClosure closure)
-{
- register VEntry *bucket;
- register int i;
- register VEntry entry;
- XrmValue value;
- XrmRepresentation type;
- Bool tightOk;
-
- closure->bindings[level] = (table->table.tight ?
- XrmBindTightly : XrmBindLoosely);
- closure->quarks[level] = table->table.name;
- level++;
- tightOk = !*names;
- closure->quarks[level + 1] = NULLQUARK;
- for (i = table->table.mask, bucket = table->buckets;
- i >= 0;
- i--, bucket++) {
- for (entry = *bucket; entry; entry = entry->next) {
- if (entry->tight && !tightOk)
- continue;
- closure->bindings[level] = (entry->tight ?
- XrmBindTightly : XrmBindLoosely);
- closure->quarks[level] = entry->name;
- value.size = entry->size;
- if (entry->string) {
- type = XrmQString;
- value.addr = StringValue(entry);
- } else {
- type = RepType(entry);
- value.addr = DataValue(entry);
- }
- if ((*closure->proc)(&closure->db, closure->bindings+1,
- closure->quarks+1, &type, &value,
- closure->closure))
- return True;
- }
- }
- return False;
-}
-
-static Bool EnumAllNTable(
- NTable table,
- register int level,
- register EClosure closure)
-{
- register NTable *bucket;
- register int i;
- register NTable entry;
- XrmQuark empty = NULLQUARK;
-
- if (level >= MAXDBDEPTH)
- return False;
- for (i = table->mask, bucket = NodeBuckets(table);
- i >= 0;
- i--, bucket++) {
- for (entry = *bucket; entry; entry = entry->next) {
- if (entry->leaf) {
- if (EnumLTable((LTable)entry, &empty, &empty, level, closure))
- return True;
- } else {
- closure->bindings[level] = (entry->tight ?
- XrmBindTightly : XrmBindLoosely);
- closure->quarks[level] = entry->name;
- if (EnumAllNTable(entry, level+1, closure))
- return True;
- }
- }
- }
- return False;
-}
-
-/* recurse on every table in the table, arbitrary order.
- * stop if user proc returns True. level is current depth in database.
- */
-static Bool EnumNTable(
- NTable table,
- XrmNameList names,
- XrmClassList classes,
- register int level,
- register EClosure closure)
-{
- register NTable entry;
- register XrmQuark q;
- register unsigned int leaf;
- Bool (*get)(
- NTable table,
- XrmNameList names,
- XrmClassList classes,
- register int level,
- EClosure closure);
- Bool bilevel;
-
-/* find entries named ename, leafness leaf, tight or loose, and call get */
-#define ITIGHTLOOSE(ename) \
- NFIND(ename); \
- if (entry) { \
- if (leaf == entry->leaf) { \
- if (!leaf && !entry->tight && entry->next && \
- entry->next->name == q && entry->next->tight && \
- (bilevel || entry->next->hasloose) && \
- EnumLTable((LTable)entry->next, names+1, classes+1, \
- level, closure)) \
- return True; \
- if ((*get)(entry, names+1, classes+1, level, closure)) \
- return True; \
- if (entry->tight && (entry = entry->next) && \
- entry->name == q && leaf == entry->leaf && \
- (*get)(entry, names+1, classes+1, level, closure)) \
- return True; \
- } else if (entry->leaf) { \
- if ((bilevel || entry->hasloose) && \
- EnumLTable((LTable)entry, names+1, classes+1, level, closure))\
- return True; \
- if (entry->tight && (entry = entry->next) && \
- entry->name == q && (bilevel || entry->hasloose) && \
- EnumLTable((LTable)entry, names+1, classes+1, level, closure))\
- return True; \
- } \
- }
-
-/* find entries named ename, leafness leaf, loose only, and call get */
-#define ILOOSE(ename) \
- NFIND(ename); \
- if (entry && entry->tight && (entry = entry->next) && entry->name != q) \
- entry = (NTable)NULL; \
- if (entry) { \
- if (leaf == entry->leaf) { \
- if ((*get)(entry, names+1, classes+1, level, closure)) \
- return True; \
- } else if (entry->leaf && (bilevel || entry->hasloose)) { \
- if (EnumLTable((LTable)entry, names+1, classes+1, level, closure))\
- return True; \
- } \
- }
-
- if (level >= MAXDBDEPTH)
- return False;
- closure->bindings[level] = (table->tight ?
- XrmBindTightly : XrmBindLoosely);
- closure->quarks[level] = table->name;
- level++;
- if (!*names) {
- if (EnumAllNTable(table, level, closure))
- return True;
- } else {
- if (names[1] || closure->mode == XrmEnumAllLevels) {
- get = EnumNTable; /* recurse */
- leaf = 0;
- bilevel = !names[1];
- } else {
- get = (getNTableEProcp)EnumLTable; /* bottom of recursion */
- leaf = 1;
- bilevel = False;
- }
- if (table->hasloose && closure->mode == XrmEnumAllLevels) {
- NTable *bucket;
- int i;
- XrmQuark empty = NULLQUARK;
-
- for (i = table->mask, bucket = NodeBuckets(table);
- i >= 0;
- i--, bucket++) {
- q = NULLQUARK;
- for (entry = *bucket; entry; entry = entry->next) {
- if (!entry->tight && entry->name != q &&
- entry->name != *names && entry->name != *classes) {
- q = entry->name;
- if (entry->leaf) {
- if (EnumLTable((LTable)entry, &empty, &empty,
- level, closure))
- return True;
- } else {
- if (EnumNTable(entry, &empty, &empty,
- level, closure))
- return True;
- }
- }
- }
- }
- }
-
- ITIGHTLOOSE(*names); /* do name, tight and loose */
- ITIGHTLOOSE(*classes); /* do class, tight and loose */
- if (table->hasany) {
- ITIGHTLOOSE(XrmQANY); /* do ANY, tight and loose */
- }
- if (table->hasloose) {
- while (1) {
- names++;
- classes++;
- if (!*names)
- break;
- if (!names[1] && closure->mode != XrmEnumAllLevels) {
- get = (getNTableEProcp)EnumLTable; /* bottom of recursion */
- leaf = 1;
- }
- ILOOSE(*names); /* loose names */
- ILOOSE(*classes); /* loose classes */
- if (table->hasany) {
- ILOOSE(XrmQANY); /* loose ANY */
- }
- }
- names--;
- classes--;
- }
- }
- /* now look for matching leaf nodes */
- entry = table->next;
- if (!entry)
- return False;
- if (entry->leaf) {
- if (entry->tight && !table->tight)
- entry = entry->next;
- } else {
- entry = entry->next;
- if (!entry || !entry->tight)
- return False;
- }
- if (!entry || entry->name != table->name)
- return False;
- /* found one */
- level--;
- if ((!*names || entry->hasloose) &&
- EnumLTable((LTable)entry, names, classes, level, closure))
- return True;
- if (entry->tight && entry == table->next && (entry = entry->next) &&
- entry->name == table->name && (!*names || entry->hasloose))
- return EnumLTable((LTable)entry, names, classes, level, closure);
- return False;
-
-#undef ITIGHTLOOSE
-#undef ILOOSE
-}
-
-/* call the proc for every value in the database, arbitrary order.
- * stop if the proc returns True.
- */
-Bool XrmEnumerateDatabase(
- XrmDatabase db,
- XrmNameList names,
- XrmClassList classes,
- int mode,
- DBEnumProc proc,
- XPointer closure)
-{
- XrmBinding bindings[MAXDBDEPTH+2];
- XrmQuark quarks[MAXDBDEPTH+2];
- register NTable table;
- EClosureRec eclosure;
- Bool retval = False;
-
- if (!db)
- return False;
- _XLockMutex(&db->linfo);
- eclosure.db = db;
- eclosure.proc = proc;
- eclosure.closure = closure;
- eclosure.bindings = bindings;
- eclosure.quarks = quarks;
- eclosure.mode = mode;
- table = db->table;
- if (table && !table->leaf && !*names && mode == XrmEnumOneLevel)
- table = table->next;
- if (table) {
- if (!table->leaf)
- retval = EnumNTable(table, names, classes, 0, &eclosure);
- else
- retval = EnumLTable((LTable)table, names, classes, 0, &eclosure);
- }
- _XUnlockMutex(&db->linfo);
- return retval;
-}
-
-static void PrintBindingQuarkList(
- XrmBindingList bindings,
- XrmQuarkList quarks,
- FILE *stream)
-{
- Bool firstNameSeen;
-
- for (firstNameSeen = False; *quarks; bindings++, quarks++) {
- if (*bindings == XrmBindLoosely) {
- (void) fprintf(stream, "*");
- } else if (firstNameSeen) {
- (void) fprintf(stream, ".");
- }
- firstNameSeen = True;
- (void) fputs(XrmQuarkToString(*quarks), stream);
- }
-}
-
-/* output out the entry in correct file syntax */
-/*ARGSUSED*/
-static Bool DumpEntry(
- XrmDatabase *db,
- XrmBindingList bindings,
- XrmQuarkList quarks,
- XrmRepresentation *type,
- XrmValuePtr value,
- XPointer data)
-{
- FILE *stream = (FILE *)data;
- register unsigned int i;
- register char *s;
- register char c;
-
- if (*type != XrmQString)
- (void) putc('!', stream);
- PrintBindingQuarkList(bindings, quarks, stream);
- s = value->addr;
- i = value->size;
- if (*type == XrmQString) {
- (void) fputs(":\t", stream);
- if (i)
- i--;
- }
- else
- (void) fprintf(stream, "=%s:\t", XrmRepresentationToString(*type));
- if (i && (*s == ' ' || *s == '\t'))
- (void) putc('\\', stream); /* preserve leading whitespace */
- while (i--) {
- c = *s++;
- if (c == '\n') {
- if (i)
- (void) fputs("\\n\\\n", stream);
- else
- (void) fputs("\\n", stream);
- } else if (c == '\\')
- (void) fputs("\\\\", stream);
- else if ((c < ' ' && c != '\t') ||
- ((unsigned char)c >= 0x7f && (unsigned char)c < 0xa0))
- (void) fprintf(stream, "\\%03o", (unsigned char)c);
- else
- (void) putc(c, stream);
- }
- (void) putc('\n', stream);
- return ferror(stream) != 0;
-}
-
-#ifdef DEBUG
-
-void PrintTable(
- NTable table,
- FILE *file)
-{
- XrmBinding bindings[MAXDBDEPTH+1];
- XrmQuark quarks[MAXDBDEPTH+1];
- EClosureRec closure;
- XrmQuark empty = NULLQUARK;
-
- closure.db = (XrmDatabase)NULL;
- closure.proc = DumpEntry;
- closure.closure = (XPointer)file;
- closure.bindings = bindings;
- closure.quarks = quarks;
- closure.mode = XrmEnumAllLevels;
- if (table->leaf)
- EnumLTable((LTable)table, &empty, &empty, 0, &closure);
- else
- EnumNTable(table, &empty, &empty, 0, &closure);
-}
-
-#endif /* DEBUG */
-
-void
-XrmPutFileDatabase(
- XrmDatabase db,
- _Xconst char *fileName)
-{
- FILE *file;
- XrmQuark empty = NULLQUARK;
-
- if (!db) return;
- if (!(file = fopen(fileName, "w"))) return;
- if (XrmEnumerateDatabase(db, &empty, &empty, XrmEnumAllLevels,
- DumpEntry, (XPointer) file))
- unlink((char *)fileName);
- fclose(file);
-}
-
-/* macros used in get/search functions */
-
-/* find entries named ename, leafness leaf, tight or loose, and call get */
-#define GTIGHTLOOSE(ename,looseleaf) \
- NFIND(ename); \
- if (entry) { \
- if (leaf == entry->leaf) { \
- if (!leaf && !entry->tight && entry->next && \
- entry->next->name == q && entry->next->tight && \
- entry->next->hasloose && \
- looseleaf((LTable)entry->next, names+1, classes+1, closure)) \
- return True; \
- if ((*get)(entry, names+1, classes+1, closure)) \
- return True; \
- if (entry->tight && (entry = entry->next) && \
- entry->name == q && leaf == entry->leaf && \
- (*get)(entry, names+1, classes+1, closure)) \
- return True; \
- } else if (entry->leaf) { \
- if (entry->hasloose && \
- looseleaf((LTable)entry, names+1, classes+1, closure)) \
- return True; \
- if (entry->tight && (entry = entry->next) && \
- entry->name == q && entry->hasloose && \
- looseleaf((LTable)entry, names+1, classes+1, closure)) \
- return True; \
- } \
- }
-
-/* find entries named ename, leafness leaf, loose only, and call get */
-#define GLOOSE(ename,looseleaf) \
- NFIND(ename); \
- if (entry && entry->tight && (entry = entry->next) && entry->name != q) \
- entry = (NTable)NULL; \
- if (entry) { \
- if (leaf == entry->leaf) { \
- if ((*get)(entry, names+1, classes+1, closure)) \
- return True; \
- } else if (entry->leaf && entry->hasloose) { \
- if (looseleaf((LTable)entry, names+1, classes+1, closure)) \
- return True; \
- } \
- }
-
-/* add tight/loose entry to the search list, return True if list is full */
-/*ARGSUSED*/
-static Bool AppendLEntry(
- LTable table,
- XrmNameList names,
- XrmClassList classes,
- register SClosure closure)
-{
- /* check for duplicate */
- if (closure->idx >= 0 && closure->list[closure->idx] == table)
- return False;
- if (closure->idx == closure->limit)
- return True;
- /* append it */
- closure->idx++;
- closure->list[closure->idx] = table;
- return False;
-}
-
-/* add loose entry to the search list, return True if list is full */
-/*ARGSUSED*/
-static Bool AppendLooseLEntry(
- LTable table,
- XrmNameList names,
- XrmClassList classes,
- register SClosure closure)
-{
- /* check for duplicate */
- if (closure->idx >= 0 && closure->list[closure->idx] == table)
- return False;
- if (closure->idx >= closure->limit - 1)
- return True;
- /* append it */
- closure->idx++;
- closure->list[closure->idx] = LOOSESEARCH;
- closure->idx++;
- closure->list[closure->idx] = table;
- return False;
-}
-
-/* search for a leaf table */
-static Bool SearchNEntry(
- NTable table,
- XrmNameList names,
- XrmClassList classes,
- SClosure closure)
-{
- register NTable entry;
- register XrmQuark q;
- register unsigned int leaf;
- Bool (*get)(
- NTable table,
- XrmNameList names,
- XrmClassList classes,
- SClosure closure);
-
- if (names[1]) {
- get = SearchNEntry; /* recurse */
- leaf = 0;
- } else {
- get = (getNTableSProcp)AppendLEntry; /* bottom of recursion */
- leaf = 1;
- }
- GTIGHTLOOSE(*names, AppendLooseLEntry); /* do name, tight and loose */
- GTIGHTLOOSE(*classes, AppendLooseLEntry); /* do class, tight and loose */
- if (table->hasany) {
- GTIGHTLOOSE(XrmQANY, AppendLooseLEntry); /* do ANY, tight and loose */
- }
- if (table->hasloose) {
- while (1) {
- names++;
- classes++;
- if (!*names)
- break;
- if (!names[1]) {
- get = (getNTableSProcp)AppendLEntry; /* bottom of recursion */
- leaf = 1;
- }
- GLOOSE(*names, AppendLooseLEntry); /* loose names */
- GLOOSE(*classes, AppendLooseLEntry); /* loose classes */
- if (table->hasany) {
- GLOOSE(XrmQANY, AppendLooseLEntry); /* loose ANY */
- }
- }
- }
- /* now look for matching leaf nodes */
- entry = table->next;
- if (!entry)
- return False;
- if (entry->leaf) {
- if (entry->tight && !table->tight)
- entry = entry->next;
- } else {
- entry = entry->next;
- if (!entry || !entry->tight)
- return False;
- }
- if (!entry || entry->name != table->name)
- return False;
- /* found one */
- if (entry->hasloose &&
- AppendLooseLEntry((LTable)entry, names, classes, closure))
- return True;
- if (entry->tight && entry == table->next && (entry = entry->next) &&
- entry->name == table->name && entry->hasloose)
- return AppendLooseLEntry((LTable)entry, names, classes, closure);
- return False;
-}
-
-Bool XrmQGetSearchList(
- XrmDatabase db,
- XrmNameList names,
- XrmClassList classes,
- XrmSearchList searchList, /* RETURN */
- int listLength)
-{
- register NTable table;
- SClosureRec closure;
-
- if (listLength <= 0)
- return False;
- closure.list = (LTable *)searchList;
- closure.idx = -1;
- closure.limit = listLength - 2;
- if (db) {
- _XLockMutex(&db->linfo);
- table = db->table;
- if (*names) {
- if (table && !table->leaf) {
- if (SearchNEntry(table, names, classes, &closure)) {
- _XUnlockMutex(&db->linfo);
- return False;
- }
- } else if (table && table->hasloose &&
- AppendLooseLEntry((LTable)table, names, classes,
- &closure)) {
- _XUnlockMutex(&db->linfo);
- return False;
- }
- } else {
- if (table && !table->leaf)
- table = table->next;
- if (table &&
- AppendLEntry((LTable)table, names, classes, &closure)) {
- _XUnlockMutex(&db->linfo);
- return False;
- }
- }
- _XUnlockMutex(&db->linfo);
- }
- closure.list[closure.idx + 1] = (LTable)NULL;
- return True;
-}
-
-Bool XrmQGetSearchResource(
- XrmSearchList searchList,
- register XrmName name,
- register XrmClass class,
- XrmRepresentation *pType, /* RETURN */
- XrmValue *pValue) /* RETURN */
-{
- register LTable *list;
- register LTable table;
- register VEntry entry = NULL;
- int flags;
-
-/* find tight or loose entry */
-#define VTIGHTLOOSE(q) \
- entry = LeafHash(table, q); \
- while (entry && entry->name != q) \
- entry = entry->next; \
- if (entry) \
- break
-
-/* find loose entry */
-#define VLOOSE(q) \
- entry = LeafHash(table, q); \
- while (entry && entry->name != q) \
- entry = entry->next; \
- if (entry) { \
- if (!entry->tight) \
- break; \
- if ((entry = entry->next) && entry->name == q) \
- break; \
- }
-
- list = (LTable *)searchList;
- /* figure out which combination of name and class we need to search for */
- flags = 0;
- if (IsResourceQuark(name))
- flags = 2;
- if (IsResourceQuark(class))
- flags |= 1;
- if (!flags) {
- /* neither name nor class has ever been used to name a resource */
- table = (LTable)NULL;
- } else if (flags == 3) {
- /* both name and class */
- while ((table = *list++)) {
- if (table != LOOSESEARCH) {
- VTIGHTLOOSE(name); /* do name, tight and loose */
- VTIGHTLOOSE(class); /* do class, tight and loose */
- } else {
- table = *list++;
- VLOOSE(name); /* do name, loose only */
- VLOOSE(class); /* do class, loose only */
- }
- }
- } else {
- /* just one of name or class */
- if (flags == 1)
- name = class;
- while ((table = *list++)) {
- if (table != LOOSESEARCH) {
- VTIGHTLOOSE(name); /* tight and loose */
- } else {
- table = *list++;
- VLOOSE(name); /* loose only */
- }
- }
- }
- if (table) {
- /* found a match */
- if (entry->string) {
- *pType = XrmQString;
- pValue->addr = StringValue(entry);
- } else {
- *pType = RepType(entry);
- pValue->addr = DataValue(entry);
- }
- pValue->size = entry->size;
- return True;
- }
- *pType = NULLQUARK;
- pValue->addr = (XPointer)NULL;
- pValue->size = 0;
- return False;
-
-#undef VTIGHTLOOSE
-#undef VLOOSE
-}
-
-/* look for a tight/loose value */
-static Bool GetVEntry(
- LTable table,
- XrmNameList names,
- XrmClassList classes,
- VClosure closure)
-{
- register VEntry entry;
- register XrmQuark q;
-
- /* try name first */
- q = *names;
- entry = LeafHash(table, q);
- while (entry && entry->name != q)
- entry = entry->next;
- if (!entry) {
- /* not found, try class */
- q = *classes;
- entry = LeafHash(table, q);
- while (entry && entry->name != q)
- entry = entry->next;
- if (!entry)
- return False;
- }
- if (entry->string) {
- *closure->type = XrmQString;
- closure->value->addr = StringValue(entry);
- } else {
- *closure->type = RepType(entry);
- closure->value->addr = DataValue(entry);
- }
- closure->value->size = entry->size;
- return True;
-}
-
-/* look for a loose value */
-static Bool GetLooseVEntry(
- LTable table,
- XrmNameList names,
- XrmClassList classes,
- VClosure closure)
-{
- register VEntry entry;
- register XrmQuark q;
-
-#define VLOOSE(ename) \
- q = ename; \
- entry = LeafHash(table, q); \
- while (entry && entry->name != q) \
- entry = entry->next; \
- if (entry && entry->tight && (entry = entry->next) && entry->name != q) \
- entry = (VEntry)NULL;
-
- /* bump to last component */
- while (names[1]) {
- names++;
- classes++;
- }
- VLOOSE(*names); /* do name, loose only */
- if (!entry) {
- VLOOSE(*classes); /* do class, loose only */
- if (!entry)
- return False;
- }
- if (entry->string) {
- *closure->type = XrmQString;
- closure->value->addr = StringValue(entry);
- } else {
- *closure->type = RepType(entry);
- closure->value->addr = DataValue(entry);
- }
- closure->value->size = entry->size;
- return True;
-
-#undef VLOOSE
-}
-
-/* recursive search for a value */
-static Bool GetNEntry(
- NTable table,
- XrmNameList names,
- XrmClassList classes,
- VClosure closure)
-{
- register NTable entry;
- register XrmQuark q;
- register unsigned int leaf;
- Bool (*get)(
- NTable table,
- XrmNameList names,
- XrmClassList classes,
- VClosure closure);
- NTable otable;
-
- if (names[2]) {
- get = GetNEntry; /* recurse */
- leaf = 0;
- } else {
- get = (getNTableVProcp)GetVEntry; /* bottom of recursion */
- leaf = 1;
- }
- GTIGHTLOOSE(*names, GetLooseVEntry); /* do name, tight and loose */
- GTIGHTLOOSE(*classes, GetLooseVEntry); /* do class, tight and loose */
- if (table->hasany) {
- GTIGHTLOOSE(XrmQANY, GetLooseVEntry); /* do ANY, tight and loose */
- }
- if (table->hasloose) {
- while (1) {
- names++;
- classes++;
- if (!names[1])
- break;
- if (!names[2]) {
- get = (getNTableVProcp)GetVEntry; /* bottom of recursion */
- leaf = 1;
- }
- GLOOSE(*names, GetLooseVEntry); /* do name, loose only */
- GLOOSE(*classes, GetLooseVEntry); /* do class, loose only */
- if (table->hasany) {
- GLOOSE(XrmQANY, GetLooseVEntry); /* do ANY, loose only */
- }
- }
- }
- /* look for matching leaf tables */
- otable = table;
- table = table->next;
- if (!table)
- return False;
- if (table->leaf) {
- if (table->tight && !otable->tight)
- table = table->next;
- } else {
- table = table->next;
- if (!table || !table->tight)
- return False;
- }
- if (!table || table->name != otable->name)
- return False;
- /* found one */
- if (table->hasloose &&
- GetLooseVEntry((LTable)table, names, classes, closure))
- return True;
- if (table->tight && table == otable->next) {
- table = table->next;
- if (table && table->name == otable->name && table->hasloose)
- return GetLooseVEntry((LTable)table, names, classes, closure);
- }
- return False;
-}
-
-Bool XrmQGetResource(
- XrmDatabase db,
- XrmNameList names,
- XrmClassList classes,
- XrmRepresentation *pType, /* RETURN */
- XrmValuePtr pValue) /* RETURN */
-{
- register NTable table;
- VClosureRec closure;
-
- if (db && *names) {
- _XLockMutex(&db->linfo);
- closure.type = pType;
- closure.value = pValue;
- table = db->table;
- if (names[1]) {
- if (table && !table->leaf) {
- if (GetNEntry(table, names, classes, &closure)) {
- _XUnlockMutex(&db->linfo);
- return True;
- }
- } else if (table && table->hasloose &&
- GetLooseVEntry((LTable)table, names, classes, &closure)) {
- _XUnlockMutex (&db->linfo);
- return True;
- }
- } else {
- if (table && !table->leaf)
- table = table->next;
- if (table && GetVEntry((LTable)table, names, classes, &closure)) {
- _XUnlockMutex(&db->linfo);
- return True;
- }
- }
- _XUnlockMutex(&db->linfo);
- }
- *pType = NULLQUARK;
- pValue->addr = (XPointer)NULL;
- pValue->size = 0;
- return False;
-}
-
-Bool
-XrmGetResource(XrmDatabase db, _Xconst char *name_str, _Xconst char *class_str,
- XrmString *pType_str, XrmValuePtr pValue)
-{
- XrmName names[MAXDBDEPTH+1];
- XrmClass classes[MAXDBDEPTH+1];
- XrmRepresentation fromType;
- Bool result;
-
- XrmStringToNameList(name_str, names);
- XrmStringToClassList(class_str, classes);
- result = XrmQGetResource(db, names, classes, &fromType, pValue);
- (*pType_str) = XrmQuarkToString(fromType);
- return result;
-}
-
-/* destroy all values, plus table itself */
-static void DestroyLTable(
- LTable table)
-{
- register int i;
- register VEntry *buckets;
- register VEntry entry, next;
-
- buckets = table->buckets;
- for (i = table->table.mask; i >= 0; i--, buckets++) {
- for (next = *buckets; (entry = next); ) {
- next = entry->next;
- Xfree((char *)entry);
- }
- }
- Xfree((char *)table->buckets);
- Xfree((char *)table);
-}
-
-/* destroy all contained tables, plus table itself */
-static void DestroyNTable(
- NTable table)
-{
- register int i;
- register NTable *buckets;
- register NTable entry, next;
-
- buckets = NodeBuckets(table);
- for (i = table->mask; i >= 0; i--, buckets++) {
- for (next = *buckets; (entry = next); ) {
- next = entry->next;
- if (entry->leaf)
- DestroyLTable((LTable)entry);
- else
- DestroyNTable(entry);
- }
- }
- Xfree((char *)table);
-}
-
-const char *
-XrmLocaleOfDatabase(
- XrmDatabase db)
-{
- const char* retval;
- _XLockMutex(&db->linfo);
- retval = (*db->methods->lcname)(db->mbstate);
- _XUnlockMutex(&db->linfo);
- return retval;
-}
-
-void XrmDestroyDatabase(
- XrmDatabase db)
-{
- register NTable table, next;
-
- if (db) {
- _XLockMutex(&db->linfo);
- for (next = db->table; (table = next); ) {
- next = table->next;
- if (table->leaf)
- DestroyLTable((LTable)table);
- else
- DestroyNTable(table);
- }
- _XUnlockMutex(&db->linfo);
- _XFreeMutex(&db->linfo);
- (*db->methods->destroy)(db->mbstate);
- Xfree((char *)db);
- }
-}
+ +/*********************************************************** +Copyright 1987, 1988, 1990 by Digital Equipment Corporation, Maynard + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* + +Copyright 1987, 1988, 1990, 1998 The Open Group + +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. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include <ctype.h> +#include "Xlibint.h" +#include <X11/Xresource.h> +#include "Xlcint.h" +#ifdef XTHREADS +#include "locking.h" +#endif +#include <X11/Xos.h> +#include <sys/stat.h> +#include "Xresinternal.h" +#include "Xresource.h" + +/* + +These Xrm routines allow very fast lookup of resources in the resource +database. Several usage patterns are exploited: + +(1) Widgets get a lot of resources at one time. Rather than look up each from +scratch, we can precompute the prioritized list of database levels once, then +search for each resource starting at the beginning of the list. + +(2) Many database levels don't contain any leaf resource nodes. There is no +point in looking for resources on a level that doesn't contain any. This +information is kept on a per-level basis. + +(3) Sometimes the widget instance tree is structured such that you get the same +class name repeated on the fully qualified widget name. This can result in the +same database level occuring multiple times on the search list. The code below +only checks to see if you get two identical search lists in a row, rather than +look back through all database levels, but in practice this removes all +duplicates I've ever observed. + +Joel McCormack + +*/ + +/* + +The Xrm representation has been completely redesigned to substantially reduce +memory and hopefully improve performance. + +The database is structured into two kinds of tables: LTables that contain +only values, and NTables that contain only other tables. + +Some invariants: + +The next pointer of the top-level node table points to the top-level leaf +table, if any. + +Within an LTable, for a given name, the tight value always precedes the +loose value, and if both are present the loose value is always right after +the tight value. + +Within an NTable, all of the entries for a given name are contiguous, +in the order tight NTable, loose NTable, tight LTable, loose LTable. + +Bob Scheifler + +*/ + +static XrmQuark XrmQString, XrmQANY; + +typedef Bool (*DBEnumProc)( + XrmDatabase* /* db */, + XrmBindingList /* bindings */, + XrmQuarkList /* quarks */, + XrmRepresentation* /* type */, + XrmValue* /* value */, + XPointer /* closure */ +); + +typedef struct _VEntry { + struct _VEntry *next; /* next in chain */ + XrmQuark name; /* name of this entry */ + unsigned int tight:1; /* 1 if it is a tight binding */ + unsigned int string:1; /* 1 if type is String */ + unsigned int size:30; /* size of value */ +} VEntryRec, *VEntry; + + +typedef struct _DEntry { + VEntryRec entry; /* entry */ + XrmRepresentation type; /* representation type */ +} DEntryRec, *DEntry; + +/* the value is right after the structure */ +#define StringValue(ve) (XPointer)((ve) + 1) +#define RepType(ve) ((DEntry)(ve))->type +/* the value is right after the structure */ +#define DataValue(ve) (XPointer)(((DEntry)(ve)) + 1) +#define RawValue(ve) (char *)((ve)->string ? StringValue(ve) : DataValue(ve)) + +typedef struct _NTable { + struct _NTable *next; /* next in chain */ + XrmQuark name; /* name of this entry */ + unsigned int tight:1; /* 1 if it is a tight binding */ + unsigned int leaf:1; /* 1 if children are values */ + unsigned int hasloose:1; /* 1 if has loose children */ + unsigned int hasany:1; /* 1 if has ANY entry */ + unsigned int pad:4; /* unused */ + unsigned int mask:8; /* hash size - 1 */ + unsigned int entries:16; /* number of children */ +} NTableRec, *NTable; + +/* the buckets are right after the structure */ +#define NodeBuckets(ne) ((NTable *)((ne) + 1)) +#define NodeHash(ne,q) NodeBuckets(ne)[(q) & (ne)->mask] + +/* leaf tables have an extra level of indirection for the buckets, + * so that resizing can be done without invalidating a search list. + * This is completely ugly, and wastes some memory, but the Xlib + * spec doesn't really specify whether invalidation is OK, and the + * old implementation did not invalidate. + */ +typedef struct _LTable { + NTableRec table; + VEntry *buckets; +} LTableRec, *LTable; + +#define LeafHash(le,q) (le)->buckets[(q) & (le)->table.mask] + +/* An XrmDatabase just holds a pointer to the first top-level table. + * The type name is no longer descriptive, but better to not change + * the Xresource.h header file. This type also gets used to define + * XrmSearchList, which is a complete crock, but we'll just leave it + * and caste types as required. + */ +typedef struct _XrmHashBucketRec { + NTable table; + XPointer mbstate; + XrmMethods methods; +#ifdef XTHREADS + LockInfoRec linfo; +#endif +} XrmHashBucketRec; + +/* closure used in get/put resource */ +typedef struct _VClosure { + XrmRepresentation *type; /* type of value */ + XrmValuePtr value; /* value itself */ +} VClosureRec, *VClosure; + +/* closure used in get search list */ +typedef struct _SClosure { + LTable *list; /* search list */ + int idx; /* index of last filled element */ + int limit; /* maximum index */ +} SClosureRec, *SClosure; + +/* placed in XrmSearchList to indicate next table is loose only */ +#define LOOSESEARCH ((LTable)1) + +/* closure used in enumerate database */ +typedef struct _EClosure { + XrmDatabase db; /* the database */ + DBEnumProc proc; /* the user proc */ + XPointer closure; /* the user closure */ + XrmBindingList bindings; /* binding list */ + XrmQuarkList quarks; /* quark list */ + int mode; /* XrmEnum<kind> */ +} EClosureRec, *EClosure; + +/* types for typecasting ETable based functions to NTable based functions */ +typedef Bool (*getNTableSProcp)( + NTable table, + XrmNameList names, + XrmClassList classes, + SClosure closure); +typedef Bool (*getNTableVProcp)( + NTable table, + XrmNameList names, + XrmClassList classes, + VClosure closure); +typedef Bool (*getNTableEProcp)( + NTable table, + XrmNameList names, + XrmClassList classes, + register int level, + EClosure closure); + +/* predicate to determine when to resize a hash table */ +#define GrowthPred(n,m) ((unsigned)(n) > (((m) + 1) << 2)) + +#define GROW(prev) \ + if (GrowthPred((*prev)->entries, (*prev)->mask)) \ + GrowTable(prev) + +/* pick a reasonable value for maximum depth of resource database */ +#define MAXDBDEPTH 100 + +/* macro used in get/search functions */ + +/* find an entry named ename, with leafness given by leaf */ +#define NFIND(ename) \ + q = ename; \ + entry = NodeHash(table, q); \ + while (entry && entry->name != q) \ + entry = entry->next; \ + if (leaf && entry && !entry->leaf) { \ + entry = entry->next; \ + if (entry && !entry->leaf) \ + entry = entry->next; \ + if (entry && entry->name != q) \ + entry = (NTable)NULL; \ + } + +/* resourceQuarks keeps track of what quarks have been associated with values + * in all LTables. If a quark has never been used in an LTable, we don't need + * to bother looking for it. + */ + +static unsigned char *resourceQuarks = (unsigned char *)NULL; +static XrmQuark maxResourceQuark = -1; + +/* determines if a quark has been used for a value in any database */ +#define IsResourceQuark(q) ((q) > 0 && (q) <= maxResourceQuark && \ + resourceQuarks[(q) >> 3] & (1 << ((q) & 7))) + +typedef unsigned char XrmBits; + +#define BSLASH ((XrmBits) (1 << 5)) +#define NORMAL ((XrmBits) (1 << 4)) +#define EOQ ((XrmBits) (1 << 3)) +#define SEP ((XrmBits) (1 << 2)) +#define ENDOF ((XrmBits) (1 << 1)) +#define SPACE (NORMAL|EOQ|SEP|(XrmBits)0) +#define RSEP (NORMAL|EOQ|SEP|(XrmBits)1) +#define EOS (EOQ|SEP|ENDOF|(XrmBits)0) +#define EOL (EOQ|SEP|ENDOF|(XrmBits)1) +#define BINDING (NORMAL|EOQ) +#define ODIGIT (NORMAL|(XrmBits)1) + +#define next_char(ch,str) xrmtypes[(unsigned char)((ch) = *(++(str)))] +#define next_mbchar(ch,len,str) xrmtypes[(unsigned char)(ch = (*db->methods->mbchar)(db->mbstate, str, &len), str += len, ch)] + +#define is_space(bits) ((bits) == SPACE) +#define is_EOQ(bits) ((bits) & EOQ) +#define is_EOF(bits) ((bits) == EOS) +#define is_EOL(bits) ((bits) & ENDOF) +#define is_binding(bits) ((bits) == BINDING) +#define is_odigit(bits) ((bits) == ODIGIT) +#define is_separator(bits) ((bits) & SEP) +#define is_nonpcs(bits) (!(bits)) +#define is_normal(bits) ((bits) & NORMAL) +#define is_simple(bits) ((bits) & (NORMAL|BSLASH)) +#define is_special(bits) ((bits) & (ENDOF|BSLASH)) + +/* parsing types */ +static XrmBits const xrmtypes[256] = { + EOS,0,0,0,0,0,0,0, + 0,SPACE,EOL,0,0, +#if defined(WIN32) || defined(__UNIXOS2__) + EOL, /* treat CR the same as LF, just in case */ +#else + 0, +#endif + 0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + SPACE,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL, + NORMAL,NORMAL,BINDING,NORMAL,NORMAL,NORMAL,BINDING,NORMAL, + ODIGIT,ODIGIT,ODIGIT,ODIGIT,ODIGIT,ODIGIT,ODIGIT,ODIGIT, + NORMAL,NORMAL,RSEP,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL, + NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL, + NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL, + NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL, + NORMAL,NORMAL,NORMAL,NORMAL,BSLASH,NORMAL,NORMAL,NORMAL, + NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL, + NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL, + NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL, + NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,0 + /* The rest will be automatically initialized to zero. */ +}; + +void XrmInitialize(void) +{ + XrmQString = XrmPermStringToQuark("String"); + XrmQANY = XrmPermStringToQuark("?"); +} + +XrmDatabase XrmGetDatabase( + Display *display) +{ + XrmDatabase retval; + LockDisplay(display); + retval = display->db; + UnlockDisplay(display); + return retval; +} + +void XrmSetDatabase( + Display *display, + XrmDatabase database) +{ + LockDisplay(display); + /* destroy database if set up imlicitely by XGetDefault() */ + if (display->db && (display->flags & XlibDisplayDfltRMDB)) { + XrmDestroyDatabase(display->db); + display->flags &= ~XlibDisplayDfltRMDB; + } + display->db = database; + UnlockDisplay(display); +} + +void +XrmStringToQuarkList( + register _Xconst char *name, + register XrmQuarkList quarks) /* RETURN */ +{ + register XrmBits bits; + register Signature sig = 0; + register char ch, *tname; + register int i = 0; + + if ((tname = (char *)name)) { + tname--; + while (!is_EOF(bits = next_char(ch, tname))) { + if (is_binding (bits)) { + if (i) { + /* Found a complete name */ + *quarks++ = _XrmInternalStringToQuark(name,tname - name, + sig, False); + i = 0; + sig = 0; + } + name = tname+1; + } + else { + sig = (sig << 1) + ch; /* Compute the signature. */ + i++; + } + } + *quarks++ = _XrmInternalStringToQuark(name, tname - name, sig, False); + } + *quarks = NULLQUARK; +} + +void +XrmStringToBindingQuarkList( + register _Xconst char *name, + register XrmBindingList bindings, /* RETURN */ + register XrmQuarkList quarks) /* RETURN */ +{ + register XrmBits bits; + register Signature sig = 0; + register char ch, *tname; + register XrmBinding binding; + register int i = 0; + + if ((tname = (char *)name)) { + tname--; + binding = XrmBindTightly; + while (!is_EOF(bits = next_char(ch, tname))) { + if (is_binding (bits)) { + if (i) { + /* Found a complete name */ + *bindings++ = binding; + *quarks++ = _XrmInternalStringToQuark(name, tname - name, + sig, False); + + i = 0; + sig = 0; + binding = XrmBindTightly; + } + name = tname+1; + + if (ch == '*') + binding = XrmBindLoosely; + } + else { + sig = (sig << 1) + ch; /* Compute the signature. */ + i++; + } + } + *bindings = binding; + *quarks++ = _XrmInternalStringToQuark(name, tname - name, sig, False); + } + *quarks = NULLQUARK; +} + +#ifdef DEBUG + +static void PrintQuarkList( + XrmQuarkList quarks, + FILE *stream) +{ + Bool firstNameSeen; + + for (firstNameSeen = False; *quarks; quarks++) { + if (firstNameSeen) { + (void) fprintf(stream, "."); + } + firstNameSeen = True; + (void) fputs(XrmQuarkToString(*quarks), stream); + } +} /* PrintQuarkList */ + +#endif /* DEBUG */ + + +/* + * Fallback methods for Xrm parsing. + * Simulate a C locale. No state needed here. + */ + +static void +c_mbnoop( + XPointer state) +{ +} + +static char +c_mbchar( + XPointer state, + const char *str, + int *lenp) +{ + *lenp = 1; + return *str; +} + +static const char * +c_lcname( + XPointer state) +{ + return "C"; +} + +static const XrmMethodsRec mb_methods = { + c_mbnoop, /* mbinit */ + c_mbchar, /* mbchar */ + c_mbnoop, /* mbfinish */ + c_lcname, /* lcname */ + c_mbnoop /* destroy */ +}; + + +static XrmDatabase NewDatabase(void) +{ + register XrmDatabase db; + + db = (XrmDatabase) Xmalloc(sizeof(XrmHashBucketRec)); + if (db) { + _XCreateMutex(&db->linfo); + db->table = (NTable)NULL; + db->mbstate = (XPointer)NULL; + db->methods = _XrmInitParseInfo(&db->mbstate); + if (!db->methods) + db->methods = &mb_methods; + } + return db; +} + +/* move all values from ftable to ttable, and free ftable's buckets. + * ttable is quaranteed empty to start with. + */ +static void MoveValues( + LTable ftable, + register LTable ttable) +{ + register VEntry fentry, nfentry; + register VEntry *prev; + register VEntry *bucket; + register VEntry tentry; + register int i; + + for (i = ftable->table.mask, bucket = ftable->buckets; i >= 0; i--) { + for (fentry = *bucket++; fentry; fentry = nfentry) { + prev = &LeafHash(ttable, fentry->name); + tentry = *prev; + *prev = fentry; + /* chain on all with same name, to preserve invariant order */ + while ((nfentry = fentry->next) && nfentry->name == fentry->name) + fentry = nfentry; + fentry->next = tentry; + } + } + Xfree((char *)ftable->buckets); +} + +/* move all tables from ftable to ttable, and free ftable. + * ttable is quaranteed empty to start with. + */ +static void MoveTables( + NTable ftable, + register NTable ttable) +{ + register NTable fentry, nfentry; + register NTable *prev; + register NTable *bucket; + register NTable tentry; + register int i; + + for (i = ftable->mask, bucket = NodeBuckets(ftable); i >= 0; i--) { + for (fentry = *bucket++; fentry; fentry = nfentry) { + prev = &NodeHash(ttable, fentry->name); + tentry = *prev; + *prev = fentry; + /* chain on all with same name, to preserve invariant order */ + while ((nfentry = fentry->next) && nfentry->name == fentry->name) + fentry = nfentry; + fentry->next = tentry; + } + } + Xfree((char *)ftable); +} + +/* grow the table, based on current number of entries */ +static void GrowTable( + NTable *prev) +{ + register NTable table; + register int i; + + table = *prev; + i = table->mask; + if (i == 255) /* biggest it gets */ + return; + while (i < 255 && GrowthPred(table->entries, i)) + i = (i << 1) + 1; + i++; /* i is now the new size */ + if (table->leaf) { + register LTable ltable; + LTableRec otable; + + ltable = (LTable)table; + /* cons up a copy to make MoveValues look symmetric */ + otable = *ltable; + ltable->buckets = Xcalloc(i, sizeof(VEntry)); + if (!ltable->buckets) { + ltable->buckets = otable.buckets; + return; + } + ltable->table.mask = i - 1; + MoveValues(&otable, ltable); + } else { + register NTable ntable; + + ntable = Xcalloc(1, sizeof(NTableRec) + (i * sizeof(NTable))); + if (!ntable) + return; + *ntable = *table; + ntable->mask = i - 1; + *prev = ntable; + MoveTables(table, ntable); + } +} + +/* merge values from ftable into *pprev, destroy ftable in the process */ +static void MergeValues( + LTable ftable, + NTable *pprev, + Bool override) +{ + register VEntry fentry, tentry; + register VEntry *prev; + register LTable ttable; + VEntry *bucket; + int i; + register XrmQuark q; + + ttable = (LTable)*pprev; + if (ftable->table.hasloose) + ttable->table.hasloose = 1; + for (i = ftable->table.mask, bucket = ftable->buckets; + i >= 0; + i--, bucket++) { + for (fentry = *bucket; fentry; ) { + q = fentry->name; + prev = &LeafHash(ttable, q); + tentry = *prev; + while (tentry && tentry->name != q) + tentry = *(prev = &tentry->next); + /* note: test intentionally uses fentry->name instead of q */ + /* permits serendipitous inserts */ + while (tentry && tentry->name == fentry->name) { + /* if tentry is earlier, skip it */ + if (!fentry->tight && tentry->tight) { + tentry = *(prev = &tentry->next); + continue; + } + if (fentry->tight != tentry->tight) { + /* no match, chain in fentry */ + *prev = fentry; + prev = &fentry->next; + fentry = *prev; + *prev = tentry; + ttable->table.entries++; + } else if (override) { + /* match, chain in fentry, splice out and free tentry */ + *prev = fentry; + prev = &fentry->next; + fentry = *prev; + *prev = tentry->next; + /* free the overridden entry */ + Xfree((char *)tentry); + /* get next tentry */ + tentry = *prev; + } else { + /* match, discard fentry */ + prev = &tentry->next; + tentry = fentry; /* use as a temp var */ + fentry = fentry->next; + /* free the overpowered entry */ + Xfree((char *)tentry); + /* get next tentry */ + tentry = *prev; + } + if (!fentry) + break; + } + /* at this point, tentry cannot match any fentry named q */ + /* chain in all bindings together, preserve invariant order */ + while (fentry && fentry->name == q) { + *prev = fentry; + prev = &fentry->next; + fentry = *prev; + *prev = tentry; + ttable->table.entries++; + } + } + } + Xfree((char *)ftable->buckets); + Xfree((char *)ftable); + /* resize if necessary, now that we're all done */ + GROW(pprev); +} + +/* merge tables from ftable into *pprev, destroy ftable in the process */ +static void MergeTables( + NTable ftable, + NTable *pprev, + Bool override) +{ + register NTable fentry, tentry; + NTable nfentry; + register NTable *prev; + register NTable ttable; + NTable *bucket; + int i; + register XrmQuark q; + + ttable = *pprev; + if (ftable->hasloose) + ttable->hasloose = 1; + if (ftable->hasany) + ttable->hasany = 1; + for (i = ftable->mask, bucket = NodeBuckets(ftable); + i >= 0; + i--, bucket++) { + for (fentry = *bucket; fentry; ) { + q = fentry->name; + prev = &NodeHash(ttable, q); + tentry = *prev; + while (tentry && tentry->name != q) + tentry = *(prev = &tentry->next); + /* note: test intentionally uses fentry->name instead of q */ + /* permits serendipitous inserts */ + while (tentry && tentry->name == fentry->name) { + /* if tentry is earlier, skip it */ + if ((fentry->leaf && !tentry->leaf) || + (!fentry->tight && tentry->tight && + (fentry->leaf || !tentry->leaf))) { + tentry = *(prev = &tentry->next); + continue; + } + nfentry = fentry->next; + if (fentry->leaf != tentry->leaf || + fentry->tight != tentry->tight) { + /* no match, just chain in */ + *prev = fentry; + *(prev = &fentry->next) = tentry; + ttable->entries++; + } else { + if (fentry->leaf) + MergeValues((LTable)fentry, prev, override); + else + MergeTables(fentry, prev, override); + /* bump to next tentry */ + tentry = *(prev = &(*prev)->next); + } + /* bump to next fentry */ + fentry = nfentry; + if (!fentry) + break; + } + /* at this point, tentry cannot match any fentry named q */ + /* chain in all bindings together, preserve invariant order */ + while (fentry && fentry->name == q) { + *prev = fentry; + prev = &fentry->next; + fentry = *prev; + *prev = tentry; + ttable->entries++; + } + } + } + Xfree((char *)ftable); + /* resize if necessary, now that we're all done */ + GROW(pprev); +} + +void XrmCombineDatabase( + XrmDatabase from, XrmDatabase *into, + Bool override) +{ + register NTable *prev; + register NTable ftable, ttable, nftable; + + if (!*into) { + *into = from; + } else if (from) { + _XLockMutex(&from->linfo); + _XLockMutex(&(*into)->linfo); + if ((ftable = from->table)) { + prev = &(*into)->table; + ttable = *prev; + if (!ftable->leaf) { + nftable = ftable->next; + if (ttable && !ttable->leaf) { + /* both have node tables, merge them */ + MergeTables(ftable, prev, override); + /* bump to into's leaf table, if any */ + ttable = *(prev = &(*prev)->next); + } else { + /* into has no node table, link from's in */ + *prev = ftable; + *(prev = &ftable->next) = ttable; + } + /* bump to from's leaf table, if any */ + ftable = nftable; + } else { + /* bump to into's leaf table, if any */ + if (ttable && !ttable->leaf) + ttable = *(prev = &ttable->next); + } + if (ftable) { + /* if into has a leaf, merge, else insert */ + if (ttable) + MergeValues((LTable)ftable, prev, override); + else + *prev = ftable; + } + } + (from->methods->destroy)(from->mbstate); + _XUnlockMutex(&from->linfo); + _XFreeMutex(&from->linfo); + Xfree((char *)from); + _XUnlockMutex(&(*into)->linfo); + } +} + +void XrmMergeDatabases( + XrmDatabase from, XrmDatabase *into) +{ + XrmCombineDatabase(from, into, True); +} + +/* store a value in the database, overriding any existing entry */ +static void PutEntry( + XrmDatabase db, + XrmBindingList bindings, + XrmQuarkList quarks, + XrmRepresentation type, + XrmValuePtr value) +{ + register NTable *pprev, *prev; + register NTable table; + register XrmQuark q; + register VEntry *vprev; + register VEntry entry; + NTable *nprev, *firstpprev; + +#define NEWTABLE(q,i) \ + table = (NTable)Xmalloc(sizeof(LTableRec)); \ + if (!table) \ + return; \ + table->name = q; \ + table->hasloose = 0; \ + table->hasany = 0; \ + table->mask = 0; \ + table->entries = 0; \ + if (quarks[i]) { \ + table->leaf = 0; \ + nprev = NodeBuckets(table); \ + } else { \ + table->leaf = 1; \ + if (!(nprev = (NTable *)Xmalloc(sizeof(VEntry *)))) {\ + Xfree(table); \ + return; \ + } \ + ((LTable)table)->buckets = (VEntry *)nprev; \ + } \ + *nprev = (NTable)NULL; \ + table->next = *prev; \ + *prev = table + + if (!db || !*quarks) + return; + table = *(prev = &db->table); + /* if already at leaf, bump to the leaf table */ + if (!quarks[1] && table && !table->leaf) + table = *(prev = &table->next); + pprev = prev; + if (!table || (quarks[1] && table->leaf)) { + /* no top-level node table, create one and chain it in */ + NEWTABLE(NULLQUARK,1); + table->tight = 1; /* arbitrary */ + prev = nprev; + } else { + /* search along until we need a value */ + while (quarks[1]) { + q = *quarks; + table = *(prev = &NodeHash(table, q)); + while (table && table->name != q) + table = *(prev = &table->next); + if (!table) + break; /* not found */ + if (quarks[2]) { + if (table->leaf) + break; /* not found */ + } else { + if (!table->leaf) { + /* bump to leaf table, if any */ + table = *(prev = &table->next); + if (!table || table->name != q) + break; /* not found */ + if (!table->leaf) { + /* bump to leaf table, if any */ + table = *(prev = &table->next); + if (!table || table->name != q) + break; /* not found */ + } + } + } + if (*bindings == XrmBindTightly) { + if (!table->tight) + break; /* not found */ + } else { + if (table->tight) { + /* bump to loose table, if any */ + table = *(prev = &table->next); + if (!table || table->name != q || + !quarks[2] != table->leaf) + break; /* not found */ + } + } + /* found that one, bump to next quark */ + pprev = prev; + quarks++; + bindings++; + } + if (!quarks[1]) { + /* found all the way to a leaf */ + q = *quarks; + entry = *(vprev = &LeafHash((LTable)table, q)); + while (entry && entry->name != q) + entry = *(vprev = &entry->next); + /* if want loose and have tight, bump to next entry */ + if (entry && *bindings == XrmBindLoosely && entry->tight) + entry = *(vprev = &entry->next); + if (entry && entry->name == q && + (*bindings == XrmBindTightly) == entry->tight) { + /* match, need to override */ + if ((type == XrmQString) == entry->string && + entry->size == value->size) { + /* update type if not String, can be different */ + if (!entry->string) + RepType(entry) = type; + /* identical size, just overwrite value */ + memcpy(RawValue(entry), (char *)value->addr, value->size); + return; + } + /* splice out and free old entry */ + *vprev = entry->next; + Xfree((char *)entry); + (*pprev)->entries--; + } + /* this is where to insert */ + prev = (NTable *)vprev; + } + } + /* keep the top table, because we may have to grow it */ + firstpprev = pprev; + /* iterate until we get to the leaf */ + while (quarks[1]) { + /* build a new table and chain it in */ + NEWTABLE(*quarks,2); + if (*quarks++ == XrmQANY) + (*pprev)->hasany = 1; + if (*bindings++ == XrmBindTightly) { + table->tight = 1; + } else { + table->tight = 0; + (*pprev)->hasloose = 1; + } + (*pprev)->entries++; + pprev = prev; + prev = nprev; + } + /* now allocate the value entry */ + entry = (VEntry)Xmalloc(((type == XrmQString) ? + sizeof(VEntryRec) : sizeof(DEntryRec)) + + value->size); + if (!entry) + return; + entry->name = q = *quarks; + if (*bindings == XrmBindTightly) { + entry->tight = 1; + } else { + entry->tight = 0; + (*pprev)->hasloose = 1; + } + /* chain it in, with a bit of type cast ugliness */ + entry->next = *((VEntry *)prev); + *((VEntry *)prev) = entry; + entry->size = value->size; + if (type == XrmQString) { + entry->string = 1; + } else { + entry->string = 0; + RepType(entry) = type; + } + /* save a copy of the value */ + memcpy(RawValue(entry), (char *)value->addr, value->size); + (*pprev)->entries++; + /* this is a new leaf, need to remember it for search lists */ + if (q > maxResourceQuark) { + unsigned oldsize = (maxResourceQuark + 1) >> 3; + unsigned size = ((q | 0x7f) + 1) >> 3; /* reallocate in chunks */ + if (resourceQuarks) { + unsigned char *prevQuarks = resourceQuarks; + + resourceQuarks = (unsigned char *)Xrealloc((char *)resourceQuarks, + size); + if (!resourceQuarks) { + Xfree(prevQuarks); + } + } else + resourceQuarks = (unsigned char *)Xmalloc(size); + if (resourceQuarks) { + bzero((char *)&resourceQuarks[oldsize], size - oldsize); + maxResourceQuark = (size << 3) - 1; + } else { + maxResourceQuark = -1; + } + } + if (q > 0 && resourceQuarks) + resourceQuarks[q >> 3] |= 1 << (q & 0x7); + GROW(firstpprev); + +#undef NEWTABLE +} + +void XrmQPutResource( + XrmDatabase *pdb, + XrmBindingList bindings, + XrmQuarkList quarks, + XrmRepresentation type, + XrmValuePtr value) +{ + if (!*pdb) *pdb = NewDatabase(); + _XLockMutex(&(*pdb)->linfo); + PutEntry(*pdb, bindings, quarks, type, value); + _XUnlockMutex(&(*pdb)->linfo); +} + +void +XrmPutResource( + XrmDatabase *pdb, + _Xconst char *specifier, + _Xconst char *type, + XrmValuePtr value) +{ + XrmBinding bindings[MAXDBDEPTH+1]; + XrmQuark quarks[MAXDBDEPTH+1]; + + if (!*pdb) *pdb = NewDatabase(); + _XLockMutex(&(*pdb)->linfo); + XrmStringToBindingQuarkList(specifier, bindings, quarks); + PutEntry(*pdb, bindings, quarks, XrmStringToQuark(type), value); + _XUnlockMutex(&(*pdb)->linfo); +} + +void +XrmQPutStringResource( + XrmDatabase *pdb, + XrmBindingList bindings, + XrmQuarkList quarks, + _Xconst char *str) +{ + XrmValue value; + + if (!*pdb) *pdb = NewDatabase(); + value.addr = (XPointer) str; + value.size = strlen(str)+1; + _XLockMutex(&(*pdb)->linfo); + PutEntry(*pdb, bindings, quarks, XrmQString, &value); + _XUnlockMutex(&(*pdb)->linfo); +} + +/* Function Name: GetDatabase + * Description: Parses a string and stores it as a database. + * Arguments: db - the database. + * str - a pointer to the string containing the database. + * filename - source filename, if any. + * doall - whether to do all lines or just one + */ + +/* + * This function is highly optimized to inline as much as possible. + * Be very careful with modifications, or simplifications, as they + * may adversely affect the performance. + * + * Chris Peterson, MIT X Consortium 5/17/90. + */ + +/* + * Xlib spec says max 100 quarks in a lookup, will stop and return if + * return if any single production's lhs has more than 100 components. + */ +#define QLIST_SIZE 100 + +/* + * This should be big enough to handle things like the XKeysymDB or biggish + * ~/.Xdefaults or app-defaults files. Anything bigger will be allocated on + * the heap. + */ +#define DEF_BUFF_SIZE 8192 + +static void GetIncludeFile( + XrmDatabase db, + _Xconst char *base, + _Xconst char *fname, + int fnamelen); + +static void GetDatabase( + XrmDatabase db, + _Xconst register char *str, + _Xconst char *filename, + Bool doall) +{ + char *rhs; + char *lhs, lhs_s[DEF_BUFF_SIZE]; + XrmQuark quarks[QLIST_SIZE + 1]; /* allow for a terminal NullQuark */ + XrmBinding bindings[QLIST_SIZE + 1]; + + register char *ptr; + register XrmBits bits = 0; + register char c; + register Signature sig; + register char *ptr_max; + register int num_quarks; + register XrmBindingList t_bindings; + + int len, alloc_chars; + unsigned long str_len; + XrmValue value; + Bool only_pcs; + Bool dolines; + + if (!db) + return; + + /* + * if strlen (str) < DEF_BUFF_SIZE allocate buffers on the stack for + * speed otherwise malloc the buffer. From a buffer overflow standpoint + * we can be sure that neither: a) a component on the lhs, or b) a + * value on the rhs, will be longer than the overall length of str, + * i.e. strlen(str). + * + * This should give good performance when parsing "*foo: bar" type + * databases as might be passed with -xrm command line options; but + * with larger databases, e.g. .Xdefaults, app-defaults, or KeysymDB + * files, the size of the buffers will be overly large. One way + * around this would be to double-parse each production with a resulting + * performance hit. In any event we can be assured that a lhs component + * name or a rhs value won't be longer than str itself. + */ + + str_len = strlen (str); + if (DEF_BUFF_SIZE > str_len) lhs = lhs_s; + else if ((lhs = (char*) Xmalloc (str_len)) == NULL) + return; + + alloc_chars = DEF_BUFF_SIZE < str_len ? str_len : DEF_BUFF_SIZE; + if ((rhs = (char*) Xmalloc (alloc_chars)) == NULL) { + if (lhs != lhs_s) Xfree (lhs); + return; + } + + (*db->methods->mbinit)(db->mbstate); + str--; + dolines = True; + while (!is_EOF(bits) && dolines) { + dolines = doall; + + /* + * First: Remove extra whitespace. + */ + + do { + bits = next_char(c, str); + } while is_space(bits); + + /* + * Ignore empty lines. + */ + + if (is_EOL(bits)) + continue; /* start a new line. */ + + /* + * Second: check the first character in a line to see if it is + * "!" signifying a comment, or "#" signifying a directive. + */ + + if (c == '!') { /* Comment, spin to next newline */ + while (is_simple(bits = next_char(c, str))) {} + if (is_EOL(bits)) + continue; + while (!is_EOL(bits = next_mbchar(c, len, str))) {} + str--; + continue; /* start a new line. */ + } + + if (c == '#') { /* Directive */ + /* remove extra whitespace */ + only_pcs = True; + while (is_space(bits = next_char(c, str))) {}; + /* only "include" directive is currently defined */ + if (!strncmp(str, "include", 7)) { + str += (7-1); + /* remove extra whitespace */ + while (is_space(bits = next_char(c, str))) {}; + /* must have a starting " */ + if (c == '"') { + _Xconst char *fname = str+1; + len = 0; + do { + if (only_pcs) { + bits = next_char(c, str); + if (is_nonpcs(bits)) + only_pcs = False; + } + if (!only_pcs) + bits = next_mbchar(c, len, str); + } while (c != '"' && !is_EOL(bits)); + /* must have an ending " */ + if (c == '"') + GetIncludeFile(db, filename, fname, str - len - fname); + } + } + /* spin to next newline */ + if (only_pcs) { + while (is_simple(bits)) + bits = next_char(c, str); + if (is_EOL(bits)) + continue; + } + while (!is_EOL(bits)) + bits = next_mbchar(c, len, str); + str--; + continue; /* start a new line. */ + } + + /* + * Third: loop through the LHS of the resource specification + * storing characters and converting this to a Quark. + */ + + num_quarks = 0; + t_bindings = bindings; + + sig = 0; + ptr = lhs; + *t_bindings = XrmBindTightly; + for(;;) { + if (!is_binding(bits)) { + while (!is_EOQ(bits)) { + *ptr++ = c; + sig = (sig << 1) + c; /* Compute the signature. */ + bits = next_char(c, str); + } + + quarks[num_quarks++] = + _XrmInternalStringToQuark(lhs, ptr - lhs, sig, False); + + if (num_quarks > QLIST_SIZE) { + Xfree(rhs); + if (lhs != lhs_s) Xfree (lhs); + (*db->methods->mbfinish)(db->mbstate); + return; + } + + if (is_separator(bits)) { + if (!is_space(bits)) + break; + + /* Remove white space */ + do { + *ptr++ = c; + sig = (sig << 1) + c; /* Compute the signature. */ + } while (is_space(bits = next_char(c, str))); + + /* + * The spec doesn't permit it, but support spaces + * internal to resource name/class + */ + + if (is_separator(bits)) + break; + num_quarks--; + continue; + } + + if (c == '.') + *(++t_bindings) = XrmBindTightly; + else + *(++t_bindings) = XrmBindLoosely; + + sig = 0; + ptr = lhs; + } + else { + /* + * Magic unspecified feature #254. + * + * If two separators appear with no Text between them then + * ignore them. + * + * If anyone of those separators is a '*' then the binding + * will be loose, otherwise it will be tight. + */ + + if (c == '*') + *t_bindings = XrmBindLoosely; + } + + bits = next_char(c, str); + } + + quarks[num_quarks] = NULLQUARK; + + /* + * Make sure that there is a ':' in this line. + */ + + if (c != ':') { + char oldc; + + /* + * A parsing error has occured, toss everything on the line + * a new_line can still be escaped with a '\'. + */ + + while (is_normal(bits)) + bits = next_char(c, str); + if (is_EOL(bits)) + continue; + bits = next_mbchar(c, len, str); + do { + oldc = c; + bits = next_mbchar(c, len, str); + } while (c && (c != '\n' || oldc == '\\')); + str--; + continue; + } + + /* + * I now have a quark and binding list for the entire left hand + * side. "c" currently points to the ":" separating the left hand + * side for the right hand side. It is time to begin processing + * the right hand side. + */ + + /* + * Fourth: Remove more whitespace + */ + + for(;;) { + if (is_space(bits = next_char(c, str))) + continue; + if (c != '\\') + break; + bits = next_char(c, str); + if (c == '\n') + continue; + str--; + bits = BSLASH; + c = '\\'; + break; + } + + /* + * Fifth: Process the right hand side. + */ + + ptr = rhs; + ptr_max = ptr + alloc_chars - 4; + only_pcs = True; + len = 1; + + for(;;) { + + /* + * Tight loop for the normal case: Non backslash, non-end of value + * character that will fit into the allocated buffer. + */ + + if (only_pcs) { + while (is_normal(bits) && ptr < ptr_max) { + *ptr++ = c; + bits = next_char(c, str); + } + if (is_EOL(bits)) + break; + if (is_nonpcs(bits)) { + only_pcs = False; + bits = next_mbchar(c, len, str); + } + } + while (!is_special(bits) && ptr + len <= ptr_max) { + len = -len; + while (len) + *ptr++ = str[len++]; + if (*str == '\0') { + bits = EOS; + break; + } + bits = next_mbchar(c, len, str); + } + + if (is_EOL(bits)) { + str--; + break; + } + + if (c == '\\') { + /* + * We need to do some magic after a backslash. + */ + Bool read_next = True; + + if (only_pcs) { + bits = next_char(c, str); + if (is_nonpcs(bits)) + only_pcs = False; + } + if (!only_pcs) + bits = next_mbchar(c, len, str); + + if (is_EOL(bits)) { + if (is_EOF(bits)) + continue; + } else if (c == 'n') { + /* + * "\n" means insert a newline. + */ + *ptr++ = '\n'; + } else if (c == '\\') { + /* + * "\\" completes to just one backslash. + */ + *ptr++ = '\\'; + } else { + /* + * pick up to three octal digits after the '\'. + */ + char temp[3]; + int count = 0; + while (is_odigit(bits) && count < 3) { + temp[count++] = c; + if (only_pcs) { + bits = next_char(c, str); + if (is_nonpcs(bits)) + only_pcs = False; + } + if (!only_pcs) + bits = next_mbchar(c, len, str); + } + + /* + * If we found three digits then insert that octal code + * into the value string as a character. + */ + + if (count == 3) { + *ptr++ = (unsigned char) ((temp[0] - '0') * 0100 + + (temp[1] - '0') * 010 + + (temp[2] - '0')); + } + else { + int tcount; + + /* + * Otherwise just insert those characters into the + * string, since no special processing is needed on + * numerics we can skip the special processing. + */ + + for (tcount = 0; tcount < count; tcount++) { + *ptr++ = temp[tcount]; /* print them in + the correct order */ + } + } + read_next = False; + } + if (read_next) { + if (only_pcs) { + bits = next_char(c, str); + if (is_nonpcs(bits)) + only_pcs = False; + } + if (!only_pcs) + bits = next_mbchar(c, len, str); + } + } + + /* + * It is important to make sure that there is room for at least + * four more characters in the buffer, since I can add that + * many characters into the buffer after a backslash has occured. + */ + + if (ptr + len > ptr_max) { + char * temp_str; + + alloc_chars += BUFSIZ/10; + temp_str = Xrealloc(rhs, sizeof(char) * alloc_chars); + + if (!temp_str) { + Xfree(rhs); + if (lhs != lhs_s) Xfree (lhs); + (*db->methods->mbfinish)(db->mbstate); + return; + } + + ptr = temp_str + (ptr - rhs); /* reset pointer. */ + rhs = temp_str; + ptr_max = rhs + alloc_chars - 4; + } + } + + /* + * Lastly: Terminate the value string, and store this entry + * into the database. + */ + + *ptr++ = '\0'; + + /* Store it in database */ + value.size = ptr - rhs; + value.addr = (XPointer) rhs; + + PutEntry(db, bindings, quarks, XrmQString, &value); + } + + if (lhs != lhs_s) Xfree (lhs); + Xfree (rhs); + + (*db->methods->mbfinish)(db->mbstate); +} + +void +XrmPutStringResource( + XrmDatabase *pdb, + _Xconst char*specifier, + _Xconst char*str) +{ + XrmValue value; + XrmBinding bindings[MAXDBDEPTH+1]; + XrmQuark quarks[MAXDBDEPTH+1]; + + if (!*pdb) *pdb = NewDatabase(); + XrmStringToBindingQuarkList(specifier, bindings, quarks); + value.addr = (XPointer) str; + value.size = strlen(str)+1; + _XLockMutex(&(*pdb)->linfo); + PutEntry(*pdb, bindings, quarks, XrmQString, &value); + _XUnlockMutex(&(*pdb)->linfo); +} + + +void +XrmPutLineResource( + XrmDatabase *pdb, + _Xconst char*line) +{ + if (!*pdb) *pdb = NewDatabase(); + _XLockMutex(&(*pdb)->linfo); + GetDatabase(*pdb, line, (char *)NULL, False); + _XUnlockMutex(&(*pdb)->linfo); +} + +XrmDatabase +XrmGetStringDatabase( + _Xconst char *data) +{ + XrmDatabase db; + + db = NewDatabase(); + _XLockMutex(&db->linfo); + GetDatabase(db, data, (char *)NULL, True); + _XUnlockMutex(&db->linfo); + return db; +} + +/* Function Name: ReadInFile + * Description: Reads the file into a buffer. + * Arguments: filename - the name of the file. + * Returns: An allocated string containing the contents of the file. + */ + +static char * +ReadInFile(_Xconst char *filename) +{ + register int fd, size; + char * filebuf; + +#ifdef __UNIXOS2__ + filename = __XOS2RedirRoot(filename); +#endif + + /* + * MS-Windows and OS/2 note: Default open mode includes O_TEXT + */ + if ( (fd = _XOpenFile (filename, O_RDONLY)) == -1 ) + return (char *)NULL; + + /* + * MS-Windows and OS/2 note: depending on how the sources are + * untarred, the newlines in resource files may or may not have + * been expanded to CRLF. Either way the size returned by fstat + * is sufficient to read the file into because in text-mode any + * CRLFs in a file will be converted to newlines (LF) with the + * result that the number of bytes actually read with be <= + * to the size returned by fstat. + */ + { + struct stat status_buffer; + if ( (fstat(fd, &status_buffer)) == -1 ) { + close (fd); + return (char *)NULL; + } else + size = status_buffer.st_size; + } + + if (!(filebuf = Xmalloc(size + 1))) { /* leave room for '\0' */ + close(fd); + return (char *)NULL; + } + size = read (fd, filebuf, size); + +#ifdef __UNIXOS2__ + { /* kill CRLF */ + int i,k; + for (i=k=0; i<size; i++) + if (filebuf[i] != 0x0d) { + filebuf[k++] = filebuf[i]; + } + filebuf[k] = 0; + } +#endif + + if (size < 0) { + close (fd); + Xfree(filebuf); + return (char *)NULL; + } + close (fd); + + filebuf[size] = '\0'; /* NULL terminate it. */ + return filebuf; +} + +static void +GetIncludeFile( + XrmDatabase db, + _Xconst char *base, + _Xconst char *fname, + int fnamelen) +{ + int len; + char *str; + char realfname[BUFSIZ]; + + if (fnamelen <= 0 || fnamelen >= BUFSIZ) + return; + if (*fname != '/' && base && (str = strrchr(base, '/'))) { + len = str - base + 1; + if (len + fnamelen >= BUFSIZ) + return; + strncpy(realfname, base, len); + strncpy(realfname + len, fname, fnamelen); + realfname[len + fnamelen] = '\0'; + } else { + strncpy(realfname, fname, fnamelen); + realfname[fnamelen] = '\0'; + } + if (!(str = ReadInFile(realfname))) + return; + GetDatabase(db, str, realfname, True); + Xfree(str); +} + +XrmDatabase +XrmGetFileDatabase( + _Xconst char *filename) +{ + XrmDatabase db; + char *str; + + if (!(str = ReadInFile(filename))) + return (XrmDatabase)NULL; + + db = NewDatabase(); + _XLockMutex(&db->linfo); + GetDatabase(db, str, filename, True); + _XUnlockMutex(&db->linfo); + Xfree(str); + return db; +} + +Status +XrmCombineFileDatabase( + _Xconst char *filename, + XrmDatabase *target, + Bool override) +{ + XrmDatabase db; + char *str; + + if (!(str = ReadInFile(filename))) + return 0; + if (override) { + db = *target; + if (!db) + *target = db = NewDatabase(); + } else + db = NewDatabase(); + _XLockMutex(&db->linfo); + GetDatabase(db, str, filename, True); + _XUnlockMutex(&db->linfo); + Xfree(str); + if (!override) + XrmCombineDatabase(db, target, False); + return 1; +} + +/* call the user proc for every value in the table, arbitrary order. + * stop if user proc returns True. level is current depth in database. + */ +/*ARGSUSED*/ +static Bool EnumLTable( + LTable table, + XrmNameList names, + XrmClassList classes, + register int level, + register EClosure closure) +{ + register VEntry *bucket; + register int i; + register VEntry entry; + XrmValue value; + XrmRepresentation type; + Bool tightOk; + + closure->bindings[level] = (table->table.tight ? + XrmBindTightly : XrmBindLoosely); + closure->quarks[level] = table->table.name; + level++; + tightOk = !*names; + closure->quarks[level + 1] = NULLQUARK; + for (i = table->table.mask, bucket = table->buckets; + i >= 0; + i--, bucket++) { + for (entry = *bucket; entry; entry = entry->next) { + if (entry->tight && !tightOk) + continue; + closure->bindings[level] = (entry->tight ? + XrmBindTightly : XrmBindLoosely); + closure->quarks[level] = entry->name; + value.size = entry->size; + if (entry->string) { + type = XrmQString; + value.addr = StringValue(entry); + } else { + type = RepType(entry); + value.addr = DataValue(entry); + } + if ((*closure->proc)(&closure->db, closure->bindings+1, + closure->quarks+1, &type, &value, + closure->closure)) + return True; + } + } + return False; +} + +static Bool EnumAllNTable( + NTable table, + register int level, + register EClosure closure) +{ + register NTable *bucket; + register int i; + register NTable entry; + XrmQuark empty = NULLQUARK; + + if (level >= MAXDBDEPTH) + return False; + for (i = table->mask, bucket = NodeBuckets(table); + i >= 0; + i--, bucket++) { + for (entry = *bucket; entry; entry = entry->next) { + if (entry->leaf) { + if (EnumLTable((LTable)entry, &empty, &empty, level, closure)) + return True; + } else { + closure->bindings[level] = (entry->tight ? + XrmBindTightly : XrmBindLoosely); + closure->quarks[level] = entry->name; + if (EnumAllNTable(entry, level+1, closure)) + return True; + } + } + } + return False; +} + +/* recurse on every table in the table, arbitrary order. + * stop if user proc returns True. level is current depth in database. + */ +static Bool EnumNTable( + NTable table, + XrmNameList names, + XrmClassList classes, + register int level, + register EClosure closure) +{ + register NTable entry; + register XrmQuark q; + register unsigned int leaf; + Bool (*get)( + NTable table, + XrmNameList names, + XrmClassList classes, + register int level, + EClosure closure); + Bool bilevel; + +/* find entries named ename, leafness leaf, tight or loose, and call get */ +#define ITIGHTLOOSE(ename) \ + NFIND(ename); \ + if (entry) { \ + if (leaf == entry->leaf) { \ + if (!leaf && !entry->tight && entry->next && \ + entry->next->name == q && entry->next->tight && \ + (bilevel || entry->next->hasloose) && \ + EnumLTable((LTable)entry->next, names+1, classes+1, \ + level, closure)) \ + return True; \ + if ((*get)(entry, names+1, classes+1, level, closure)) \ + return True; \ + if (entry->tight && (entry = entry->next) && \ + entry->name == q && leaf == entry->leaf && \ + (*get)(entry, names+1, classes+1, level, closure)) \ + return True; \ + } else if (entry->leaf) { \ + if ((bilevel || entry->hasloose) && \ + EnumLTable((LTable)entry, names+1, classes+1, level, closure))\ + return True; \ + if (entry->tight && (entry = entry->next) && \ + entry->name == q && (bilevel || entry->hasloose) && \ + EnumLTable((LTable)entry, names+1, classes+1, level, closure))\ + return True; \ + } \ + } + +/* find entries named ename, leafness leaf, loose only, and call get */ +#define ILOOSE(ename) \ + NFIND(ename); \ + if (entry && entry->tight && (entry = entry->next) && entry->name != q) \ + entry = (NTable)NULL; \ + if (entry) { \ + if (leaf == entry->leaf) { \ + if ((*get)(entry, names+1, classes+1, level, closure)) \ + return True; \ + } else if (entry->leaf && (bilevel || entry->hasloose)) { \ + if (EnumLTable((LTable)entry, names+1, classes+1, level, closure))\ + return True; \ + } \ + } + + if (level >= MAXDBDEPTH) + return False; + closure->bindings[level] = (table->tight ? + XrmBindTightly : XrmBindLoosely); + closure->quarks[level] = table->name; + level++; + if (!*names) { + if (EnumAllNTable(table, level, closure)) + return True; + } else { + if (names[1] || closure->mode == XrmEnumAllLevels) { + get = EnumNTable; /* recurse */ + leaf = 0; + bilevel = !names[1]; + } else { + get = (getNTableEProcp)EnumLTable; /* bottom of recursion */ + leaf = 1; + bilevel = False; + } + if (table->hasloose && closure->mode == XrmEnumAllLevels) { + NTable *bucket; + int i; + XrmQuark empty = NULLQUARK; + + for (i = table->mask, bucket = NodeBuckets(table); + i >= 0; + i--, bucket++) { + q = NULLQUARK; + for (entry = *bucket; entry; entry = entry->next) { + if (!entry->tight && entry->name != q && + entry->name != *names && entry->name != *classes) { + q = entry->name; + if (entry->leaf) { + if (EnumLTable((LTable)entry, &empty, &empty, + level, closure)) + return True; + } else { + if (EnumNTable(entry, &empty, &empty, + level, closure)) + return True; + } + } + } + } + } + + ITIGHTLOOSE(*names); /* do name, tight and loose */ + ITIGHTLOOSE(*classes); /* do class, tight and loose */ + if (table->hasany) { + ITIGHTLOOSE(XrmQANY); /* do ANY, tight and loose */ + } + if (table->hasloose) { + while (1) { + names++; + classes++; + if (!*names) + break; + if (!names[1] && closure->mode != XrmEnumAllLevels) { + get = (getNTableEProcp)EnumLTable; /* bottom of recursion */ + leaf = 1; + } + ILOOSE(*names); /* loose names */ + ILOOSE(*classes); /* loose classes */ + if (table->hasany) { + ILOOSE(XrmQANY); /* loose ANY */ + } + } + names--; + classes--; + } + } + /* now look for matching leaf nodes */ + entry = table->next; + if (!entry) + return False; + if (entry->leaf) { + if (entry->tight && !table->tight) + entry = entry->next; + } else { + entry = entry->next; + if (!entry || !entry->tight) + return False; + } + if (!entry || entry->name != table->name) + return False; + /* found one */ + level--; + if ((!*names || entry->hasloose) && + EnumLTable((LTable)entry, names, classes, level, closure)) + return True; + if (entry->tight && entry == table->next && (entry = entry->next) && + entry->name == table->name && (!*names || entry->hasloose)) + return EnumLTable((LTable)entry, names, classes, level, closure); + return False; + +#undef ITIGHTLOOSE +#undef ILOOSE +} + +/* call the proc for every value in the database, arbitrary order. + * stop if the proc returns True. + */ +Bool XrmEnumerateDatabase( + XrmDatabase db, + XrmNameList names, + XrmClassList classes, + int mode, + DBEnumProc proc, + XPointer closure) +{ + XrmBinding bindings[MAXDBDEPTH+2]; + XrmQuark quarks[MAXDBDEPTH+2]; + register NTable table; + EClosureRec eclosure; + Bool retval = False; + + if (!db) + return False; + _XLockMutex(&db->linfo); + eclosure.db = db; + eclosure.proc = proc; + eclosure.closure = closure; + eclosure.bindings = bindings; + eclosure.quarks = quarks; + eclosure.mode = mode; + table = db->table; + if (table && !table->leaf && !*names && mode == XrmEnumOneLevel) + table = table->next; + if (table) { + if (!table->leaf) + retval = EnumNTable(table, names, classes, 0, &eclosure); + else + retval = EnumLTable((LTable)table, names, classes, 0, &eclosure); + } + _XUnlockMutex(&db->linfo); + return retval; +} + +static void PrintBindingQuarkList( + XrmBindingList bindings, + XrmQuarkList quarks, + FILE *stream) +{ + Bool firstNameSeen; + + for (firstNameSeen = False; *quarks; bindings++, quarks++) { + if (*bindings == XrmBindLoosely) { + (void) fprintf(stream, "*"); + } else if (firstNameSeen) { + (void) fprintf(stream, "."); + } + firstNameSeen = True; + (void) fputs(XrmQuarkToString(*quarks), stream); + } +} + +/* output out the entry in correct file syntax */ +/*ARGSUSED*/ +static Bool DumpEntry( + XrmDatabase *db, + XrmBindingList bindings, + XrmQuarkList quarks, + XrmRepresentation *type, + XrmValuePtr value, + XPointer data) +{ + FILE *stream = (FILE *)data; + register unsigned int i; + register char *s; + register char c; + + if (*type != XrmQString) + (void) putc('!', stream); + PrintBindingQuarkList(bindings, quarks, stream); + s = value->addr; + i = value->size; + if (*type == XrmQString) { + (void) fputs(":\t", stream); + if (i) + i--; + } + else + (void) fprintf(stream, "=%s:\t", XrmRepresentationToString(*type)); + if (i && (*s == ' ' || *s == '\t')) + (void) putc('\\', stream); /* preserve leading whitespace */ + while (i--) { + c = *s++; + if (c == '\n') { + if (i) + (void) fputs("\\n\\\n", stream); + else + (void) fputs("\\n", stream); + } else if (c == '\\') + (void) fputs("\\\\", stream); + else if ((c < ' ' && c != '\t') || + ((unsigned char)c >= 0x7f && (unsigned char)c < 0xa0)) + (void) fprintf(stream, "\\%03o", (unsigned char)c); + else + (void) putc(c, stream); + } + (void) putc('\n', stream); + return ferror(stream) != 0; +} + +#ifdef DEBUG + +void PrintTable( + NTable table, + FILE *file) +{ + XrmBinding bindings[MAXDBDEPTH+1]; + XrmQuark quarks[MAXDBDEPTH+1]; + EClosureRec closure; + XrmQuark empty = NULLQUARK; + + closure.db = (XrmDatabase)NULL; + closure.proc = DumpEntry; + closure.closure = (XPointer)file; + closure.bindings = bindings; + closure.quarks = quarks; + closure.mode = XrmEnumAllLevels; + if (table->leaf) + EnumLTable((LTable)table, &empty, &empty, 0, &closure); + else + EnumNTable(table, &empty, &empty, 0, &closure); +} + +#endif /* DEBUG */ + +void +XrmPutFileDatabase( + XrmDatabase db, + _Xconst char *fileName) +{ + FILE *file; + XrmQuark empty = NULLQUARK; + + if (!db) return; + if (!(file = fopen(fileName, "w"))) return; + if (XrmEnumerateDatabase(db, &empty, &empty, XrmEnumAllLevels, + DumpEntry, (XPointer) file)) + unlink((char *)fileName); + fclose(file); +} + +/* macros used in get/search functions */ + +/* find entries named ename, leafness leaf, tight or loose, and call get */ +#define GTIGHTLOOSE(ename,looseleaf) \ + NFIND(ename); \ + if (entry) { \ + if (leaf == entry->leaf) { \ + if (!leaf && !entry->tight && entry->next && \ + entry->next->name == q && entry->next->tight && \ + entry->next->hasloose && \ + looseleaf((LTable)entry->next, names+1, classes+1, closure)) \ + return True; \ + if ((*get)(entry, names+1, classes+1, closure)) \ + return True; \ + if (entry->tight && (entry = entry->next) && \ + entry->name == q && leaf == entry->leaf && \ + (*get)(entry, names+1, classes+1, closure)) \ + return True; \ + } else if (entry->leaf) { \ + if (entry->hasloose && \ + looseleaf((LTable)entry, names+1, classes+1, closure)) \ + return True; \ + if (entry->tight && (entry = entry->next) && \ + entry->name == q && entry->hasloose && \ + looseleaf((LTable)entry, names+1, classes+1, closure)) \ + return True; \ + } \ + } + +/* find entries named ename, leafness leaf, loose only, and call get */ +#define GLOOSE(ename,looseleaf) \ + NFIND(ename); \ + if (entry && entry->tight && (entry = entry->next) && entry->name != q) \ + entry = (NTable)NULL; \ + if (entry) { \ + if (leaf == entry->leaf) { \ + if ((*get)(entry, names+1, classes+1, closure)) \ + return True; \ + } else if (entry->leaf && entry->hasloose) { \ + if (looseleaf((LTable)entry, names+1, classes+1, closure)) \ + return True; \ + } \ + } + +/* add tight/loose entry to the search list, return True if list is full */ +/*ARGSUSED*/ +static Bool AppendLEntry( + LTable table, + XrmNameList names, + XrmClassList classes, + register SClosure closure) +{ + /* check for duplicate */ + if (closure->idx >= 0 && closure->list[closure->idx] == table) + return False; + if (closure->idx == closure->limit) + return True; + /* append it */ + closure->idx++; + closure->list[closure->idx] = table; + return False; +} + +/* add loose entry to the search list, return True if list is full */ +/*ARGSUSED*/ +static Bool AppendLooseLEntry( + LTable table, + XrmNameList names, + XrmClassList classes, + register SClosure closure) +{ + /* check for duplicate */ + if (closure->idx >= 0 && closure->list[closure->idx] == table) + return False; + if (closure->idx >= closure->limit - 1) + return True; + /* append it */ + closure->idx++; + closure->list[closure->idx] = LOOSESEARCH; + closure->idx++; + closure->list[closure->idx] = table; + return False; +} + +/* search for a leaf table */ +static Bool SearchNEntry( + NTable table, + XrmNameList names, + XrmClassList classes, + SClosure closure) +{ + register NTable entry; + register XrmQuark q; + register unsigned int leaf; + Bool (*get)( + NTable table, + XrmNameList names, + XrmClassList classes, + SClosure closure); + + if (names[1]) { + get = SearchNEntry; /* recurse */ + leaf = 0; + } else { + get = (getNTableSProcp)AppendLEntry; /* bottom of recursion */ + leaf = 1; + } + GTIGHTLOOSE(*names, AppendLooseLEntry); /* do name, tight and loose */ + GTIGHTLOOSE(*classes, AppendLooseLEntry); /* do class, tight and loose */ + if (table->hasany) { + GTIGHTLOOSE(XrmQANY, AppendLooseLEntry); /* do ANY, tight and loose */ + } + if (table->hasloose) { + while (1) { + names++; + classes++; + if (!*names) + break; + if (!names[1]) { + get = (getNTableSProcp)AppendLEntry; /* bottom of recursion */ + leaf = 1; + } + GLOOSE(*names, AppendLooseLEntry); /* loose names */ + GLOOSE(*classes, AppendLooseLEntry); /* loose classes */ + if (table->hasany) { + GLOOSE(XrmQANY, AppendLooseLEntry); /* loose ANY */ + } + } + } + /* now look for matching leaf nodes */ + entry = table->next; + if (!entry) + return False; + if (entry->leaf) { + if (entry->tight && !table->tight) + entry = entry->next; + } else { + entry = entry->next; + if (!entry || !entry->tight) + return False; + } + if (!entry || entry->name != table->name) + return False; + /* found one */ + if (entry->hasloose && + AppendLooseLEntry((LTable)entry, names, classes, closure)) + return True; + if (entry->tight && entry == table->next && (entry = entry->next) && + entry->name == table->name && entry->hasloose) + return AppendLooseLEntry((LTable)entry, names, classes, closure); + return False; +} + +Bool XrmQGetSearchList( + XrmDatabase db, + XrmNameList names, + XrmClassList classes, + XrmSearchList searchList, /* RETURN */ + int listLength) +{ + register NTable table; + SClosureRec closure; + + if (listLength <= 0) + return False; + closure.list = (LTable *)searchList; + closure.idx = -1; + closure.limit = listLength - 2; + if (db) { + _XLockMutex(&db->linfo); + table = db->table; + if (*names) { + if (table && !table->leaf) { + if (SearchNEntry(table, names, classes, &closure)) { + _XUnlockMutex(&db->linfo); + return False; + } + } else if (table && table->hasloose && + AppendLooseLEntry((LTable)table, names, classes, + &closure)) { + _XUnlockMutex(&db->linfo); + return False; + } + } else { + if (table && !table->leaf) + table = table->next; + if (table && + AppendLEntry((LTable)table, names, classes, &closure)) { + _XUnlockMutex(&db->linfo); + return False; + } + } + _XUnlockMutex(&db->linfo); + } + closure.list[closure.idx + 1] = (LTable)NULL; + return True; +} + +Bool XrmQGetSearchResource( + XrmSearchList searchList, + register XrmName name, + register XrmClass class, + XrmRepresentation *pType, /* RETURN */ + XrmValue *pValue) /* RETURN */ +{ + register LTable *list; + register LTable table; + register VEntry entry = NULL; + int flags; + +/* find tight or loose entry */ +#define VTIGHTLOOSE(q) \ + entry = LeafHash(table, q); \ + while (entry && entry->name != q) \ + entry = entry->next; \ + if (entry) \ + break + +/* find loose entry */ +#define VLOOSE(q) \ + entry = LeafHash(table, q); \ + while (entry && entry->name != q) \ + entry = entry->next; \ + if (entry) { \ + if (!entry->tight) \ + break; \ + if ((entry = entry->next) && entry->name == q) \ + break; \ + } + + list = (LTable *)searchList; + /* figure out which combination of name and class we need to search for */ + flags = 0; + if (IsResourceQuark(name)) + flags = 2; + if (IsResourceQuark(class)) + flags |= 1; + if (!flags) { + /* neither name nor class has ever been used to name a resource */ + table = (LTable)NULL; + } else if (flags == 3) { + /* both name and class */ + while ((table = *list++)) { + if (table != LOOSESEARCH) { + VTIGHTLOOSE(name); /* do name, tight and loose */ + VTIGHTLOOSE(class); /* do class, tight and loose */ + } else { + table = *list++; + VLOOSE(name); /* do name, loose only */ + VLOOSE(class); /* do class, loose only */ + } + } + } else { + /* just one of name or class */ + if (flags == 1) + name = class; + while ((table = *list++)) { + if (table != LOOSESEARCH) { + VTIGHTLOOSE(name); /* tight and loose */ + } else { + table = *list++; + VLOOSE(name); /* loose only */ + } + } + } + if (table) { + /* found a match */ + if (entry->string) { + *pType = XrmQString; + pValue->addr = StringValue(entry); + } else { + *pType = RepType(entry); + pValue->addr = DataValue(entry); + } + pValue->size = entry->size; + return True; + } + *pType = NULLQUARK; + pValue->addr = (XPointer)NULL; + pValue->size = 0; + return False; + +#undef VTIGHTLOOSE +#undef VLOOSE +} + +/* look for a tight/loose value */ +static Bool GetVEntry( + LTable table, + XrmNameList names, + XrmClassList classes, + VClosure closure) +{ + register VEntry entry; + register XrmQuark q; + + /* try name first */ + q = *names; + entry = LeafHash(table, q); + while (entry && entry->name != q) + entry = entry->next; + if (!entry) { + /* not found, try class */ + q = *classes; + entry = LeafHash(table, q); + while (entry && entry->name != q) + entry = entry->next; + if (!entry) + return False; + } + if (entry->string) { + *closure->type = XrmQString; + closure->value->addr = StringValue(entry); + } else { + *closure->type = RepType(entry); + closure->value->addr = DataValue(entry); + } + closure->value->size = entry->size; + return True; +} + +/* look for a loose value */ +static Bool GetLooseVEntry( + LTable table, + XrmNameList names, + XrmClassList classes, + VClosure closure) +{ + register VEntry entry; + register XrmQuark q; + +#define VLOOSE(ename) \ + q = ename; \ + entry = LeafHash(table, q); \ + while (entry && entry->name != q) \ + entry = entry->next; \ + if (entry && entry->tight && (entry = entry->next) && entry->name != q) \ + entry = (VEntry)NULL; + + /* bump to last component */ + while (names[1]) { + names++; + classes++; + } + VLOOSE(*names); /* do name, loose only */ + if (!entry) { + VLOOSE(*classes); /* do class, loose only */ + if (!entry) + return False; + } + if (entry->string) { + *closure->type = XrmQString; + closure->value->addr = StringValue(entry); + } else { + *closure->type = RepType(entry); + closure->value->addr = DataValue(entry); + } + closure->value->size = entry->size; + return True; + +#undef VLOOSE +} + +/* recursive search for a value */ +static Bool GetNEntry( + NTable table, + XrmNameList names, + XrmClassList classes, + VClosure closure) +{ + register NTable entry; + register XrmQuark q; + register unsigned int leaf; + Bool (*get)( + NTable table, + XrmNameList names, + XrmClassList classes, + VClosure closure); + NTable otable; + + if (names[2]) { + get = GetNEntry; /* recurse */ + leaf = 0; + } else { + get = (getNTableVProcp)GetVEntry; /* bottom of recursion */ + leaf = 1; + } + GTIGHTLOOSE(*names, GetLooseVEntry); /* do name, tight and loose */ + GTIGHTLOOSE(*classes, GetLooseVEntry); /* do class, tight and loose */ + if (table->hasany) { + GTIGHTLOOSE(XrmQANY, GetLooseVEntry); /* do ANY, tight and loose */ + } + if (table->hasloose) { + while (1) { + names++; + classes++; + if (!names[1]) + break; + if (!names[2]) { + get = (getNTableVProcp)GetVEntry; /* bottom of recursion */ + leaf = 1; + } + GLOOSE(*names, GetLooseVEntry); /* do name, loose only */ + GLOOSE(*classes, GetLooseVEntry); /* do class, loose only */ + if (table->hasany) { + GLOOSE(XrmQANY, GetLooseVEntry); /* do ANY, loose only */ + } + } + } + /* look for matching leaf tables */ + otable = table; + table = table->next; + if (!table) + return False; + if (table->leaf) { + if (table->tight && !otable->tight) + table = table->next; + } else { + table = table->next; + if (!table || !table->tight) + return False; + } + if (!table || table->name != otable->name) + return False; + /* found one */ + if (table->hasloose && + GetLooseVEntry((LTable)table, names, classes, closure)) + return True; + if (table->tight && table == otable->next) { + table = table->next; + if (table && table->name == otable->name && table->hasloose) + return GetLooseVEntry((LTable)table, names, classes, closure); + } + return False; +} + +Bool XrmQGetResource( + XrmDatabase db, + XrmNameList names, + XrmClassList classes, + XrmRepresentation *pType, /* RETURN */ + XrmValuePtr pValue) /* RETURN */ +{ + register NTable table; + VClosureRec closure; + + if (db && *names) { + _XLockMutex(&db->linfo); + closure.type = pType; + closure.value = pValue; + table = db->table; + if (names[1]) { + if (table && !table->leaf) { + if (GetNEntry(table, names, classes, &closure)) { + _XUnlockMutex(&db->linfo); + return True; + } + } else if (table && table->hasloose && + GetLooseVEntry((LTable)table, names, classes, &closure)) { + _XUnlockMutex (&db->linfo); + return True; + } + } else { + if (table && !table->leaf) + table = table->next; + if (table && GetVEntry((LTable)table, names, classes, &closure)) { + _XUnlockMutex(&db->linfo); + return True; + } + } + _XUnlockMutex(&db->linfo); + } + *pType = NULLQUARK; + pValue->addr = (XPointer)NULL; + pValue->size = 0; + return False; +} + +Bool +XrmGetResource(XrmDatabase db, _Xconst char *name_str, _Xconst char *class_str, + XrmString *pType_str, XrmValuePtr pValue) +{ + XrmName names[MAXDBDEPTH+1]; + XrmClass classes[MAXDBDEPTH+1]; + XrmRepresentation fromType; + Bool result; + + XrmStringToNameList(name_str, names); + XrmStringToClassList(class_str, classes); + result = XrmQGetResource(db, names, classes, &fromType, pValue); + (*pType_str) = XrmQuarkToString(fromType); + return result; +} + +/* destroy all values, plus table itself */ +static void DestroyLTable( + LTable table) +{ + register int i; + register VEntry *buckets; + register VEntry entry, next; + + buckets = table->buckets; + for (i = table->table.mask; i >= 0; i--, buckets++) { + for (next = *buckets; (entry = next); ) { + next = entry->next; + Xfree((char *)entry); + } + } + Xfree((char *)table->buckets); + Xfree((char *)table); +} + +/* destroy all contained tables, plus table itself */ +static void DestroyNTable( + NTable table) +{ + register int i; + register NTable *buckets; + register NTable entry, next; + + buckets = NodeBuckets(table); + for (i = table->mask; i >= 0; i--, buckets++) { + for (next = *buckets; (entry = next); ) { + next = entry->next; + if (entry->leaf) + DestroyLTable((LTable)entry); + else + DestroyNTable(entry); + } + } + Xfree((char *)table); +} + +const char * +XrmLocaleOfDatabase( + XrmDatabase db) +{ + const char* retval; + _XLockMutex(&db->linfo); + retval = (*db->methods->lcname)(db->mbstate); + _XUnlockMutex(&db->linfo); + return retval; +} + +void XrmDestroyDatabase( + XrmDatabase db) +{ + register NTable table, next; + + if (db) { + _XLockMutex(&db->linfo); + for (next = db->table; (table = next); ) { + next = table->next; + if (table->leaf) + DestroyLTable((LTable)table); + else + DestroyNTable(table); + } + _XUnlockMutex(&db->linfo); + _XFreeMutex(&db->linfo); + (*db->methods->destroy)(db->mbstate); + Xfree((char *)db); + } +} diff --git a/libX11/src/xcms/LRGB.c b/libX11/src/xcms/LRGB.c index 2dc5a20cf..5ecb7d120 100644 --- a/libX11/src/xcms/LRGB.c +++ b/libX11/src/xcms/LRGB.c @@ -1,1844 +1,1844 @@ -
-/*
- * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc.
- * All Rights Reserved
- *
- * This file is a component of an X Window System-specific implementation
- * of Xcms based on the TekColor Color Management System. Permission is
- * hereby granted to use, copy, modify, sell, and otherwise distribute this
- * software and its documentation for any purpose and without fee, provided
- * that this copyright, permission, and disclaimer notice is reproduced in
- * all copies of this software and in supporting documentation. TekColor
- * is a trademark of Tektronix, Inc.
- *
- * Tektronix makes no representation about the suitability of this software
- * for any purpose. It is provided "as is" and with all faults.
- *
- * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE,
- * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX 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 TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE.
- *
- *
- * NAME
- * XcmsLRGB.c
- *
- * DESCRIPTION
- * This file contains the conversion routines:
- * 1. CIE XYZ to RGB intensity
- * 2. RGB intensity to device RGB
- * 3. device RGB to RGB intensity
- * 4. RGB intensity to CIE XYZ
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <X11/Xos.h>
-#include <X11/Xatom.h>
-#include "Xlibint.h"
-#include "Xcmsint.h"
-#include "Cv.h"
-
-/*
- * LOCAL DEFINES
- * #define declarations local to this package.
- */
-#define EPS 0.001
-#ifndef MIN
-#define MIN(x,y) ((x) > (y) ? (y) : (x))
-#endif /* MIN */
-#ifndef MAX
-#define MAX(x,y) ((x) > (y) ? (x) : (y))
-#endif /* MAX */
-#ifndef MIN3
-#define MIN3(x,y,z) ((x) > (MIN((y), (z))) ? (MIN((y), (z))) : (x))
-#endif /* MIN3 */
-#ifndef MAX3
-#define MAX3(x,y,z) ((x) > (MAX((y), (z))) ? (x) : (MAX((y), (z))))
-#endif /* MAX3 */
-
-/*
- * LOCAL TYPEDEFS
- * typedefs local to this package (for use with local vars).
- *
- */
-
-/*
- * FORWARD DECLARATIONS
- */
-static void LINEAR_RGB_FreeSCCData(XPointer pScreenDataTemp);
-static int LINEAR_RGB_InitSCCData(Display *dpy,
- int screenNumber, XcmsPerScrnInfo *pPerScrnInfo);
-static int XcmsLRGB_RGB_ParseString(register char *spec, XcmsColor *pColor);
-static int XcmsLRGB_RGBi_ParseString(register char *spec, XcmsColor *pColor);
-static Status
-_XcmsGetTableType0(
- IntensityTbl *pTbl,
- int format,
- char **pChar,
- unsigned long *pCount);
-static Status
-_XcmsGetTableType1(
- IntensityTbl *pTbl,
- int format,
- char **pChar,
- unsigned long *pCount);
-
-/*
- * LOCALS VARIABLES
- * Variables local to this package.
- * Usage example:
- * static int ExampleLocalVar;
- */
-
-static unsigned short const MASK[17] = {
- 0x0000, /* 0 bitsPerRGB */
- 0x8000, /* 1 bitsPerRGB */
- 0xc000, /* 2 bitsPerRGB */
- 0xe000, /* 3 bitsPerRGB */
- 0xf000, /* 4 bitsPerRGB */
- 0xf800, /* 5 bitsPerRGB */
- 0xfc00, /* 6 bitsPerRGB */
- 0xfe00, /* 7 bitsPerRGB */
- 0xff00, /* 8 bitsPerRGB */
- 0xff80, /* 9 bitsPerRGB */
- 0xffc0, /* 10 bitsPerRGB */
- 0xffe0, /* 11 bitsPerRGB */
- 0xfff0, /* 12 bitsPerRGB */
- 0xfff8, /* 13 bitsPerRGB */
- 0xfffc, /* 14 bitsPerRGB */
- 0xfffe, /* 15 bitsPerRGB */
- 0xffff /* 16 bitsPerRGB */
-};
-
-
- /*
- * A NULL terminated array of function pointers that when applied
- * in series will convert an XcmsColor structure from XcmsRGBFormat
- * to XcmsCIEXYZFormat.
- */
-static XcmsConversionProc Fl_RGB_to_CIEXYZ[] = {
- (XcmsConversionProc)XcmsRGBToRGBi,
- (XcmsConversionProc)XcmsRGBiToCIEXYZ,
- NULL
-};
-
- /*
- * A NULL terminated array of function pointers that when applied
- * in series will convert an XcmsColor structure from XcmsCIEXYZFormat
- * to XcmsRGBFormat.
- */
-static XcmsConversionProc Fl_CIEXYZ_to_RGB[] = {
- (XcmsConversionProc)XcmsCIEXYZToRGBi,
- (XcmsConversionProc)XcmsRGBiToRGB,
- NULL
-};
-
- /*
- * A NULL terminated array of function pointers that when applied
- * in series will convert an XcmsColor structure from XcmsRGBiFormat
- * to XcmsCIEXYZFormat.
- */
-static XcmsConversionProc Fl_RGBi_to_CIEXYZ[] = {
- (XcmsConversionProc)XcmsRGBiToCIEXYZ,
- NULL
-};
-
- /*
- * A NULL terminated array of function pointers that when applied
- * in series will convert an XcmsColor structure from XcmsCIEXYZFormat
- * to XcmsRGBiFormat.
- */
-static XcmsConversionProc Fl_CIEXYZ_to_RGBi[] = {
- (XcmsConversionProc)XcmsCIEXYZToRGBi,
- NULL
-};
-
- /*
- * RGBi Color Spaces
- */
-XcmsColorSpace XcmsRGBiColorSpace =
- {
- _XcmsRGBi_prefix, /* prefix */
- XcmsRGBiFormat, /* id */
- XcmsLRGB_RGBi_ParseString, /* parseString */
- Fl_RGBi_to_CIEXYZ, /* to_CIEXYZ */
- Fl_CIEXYZ_to_RGBi, /* from_CIEXYZ */
- 1
- };
-
- /*
- * RGB Color Spaces
- */
-XcmsColorSpace XcmsRGBColorSpace =
- {
- _XcmsRGB_prefix, /* prefix */
- XcmsRGBFormat, /* id */
- XcmsLRGB_RGB_ParseString, /* parseString */
- Fl_RGB_to_CIEXYZ, /* to_CIEXYZ */
- Fl_CIEXYZ_to_RGB, /* from_CIEXYZ */
- 1
- };
-
- /*
- * Device-Independent Color Spaces known to the
- * LINEAR_RGB Screen Color Characteristics Function Set.
- */
-static XcmsColorSpace *DDColorSpaces[] = {
- &XcmsRGBColorSpace,
- &XcmsRGBiColorSpace,
- NULL
-};
-
-
-/*
- * GLOBALS
- * Variables declared in this package that are allowed
- * to be used globally.
- */
-
- /*
- * LINEAR_RGB Screen Color Characteristics Function Set.
- */
-XcmsFunctionSet XcmsLinearRGBFunctionSet =
- {
- &DDColorSpaces[0], /* pDDColorSpaces */
- LINEAR_RGB_InitSCCData, /* pInitScrnFunc */
- LINEAR_RGB_FreeSCCData /* pFreeSCCData */
- };
-
-/*
- * DESCRIPTION
- * Contents of Default SCCData should be replaced if other
- * data should be used as default.
- *
- *
- */
-
-/*
- * NAME Tektronix 19" (Sony) CRT
- * PART_NUMBER 119-2451-00
- * MODEL Tek4300, Tek4800
- */
-
-static IntensityRec const Default_RGB_RedTuples[] = {
- /* {unsigned short value, XcmsFloat intensity} */
- { 0x0000, 0.000000 },
- { 0x0909, 0.000000 },
- { 0x0a0a, 0.000936 },
- { 0x0f0f, 0.001481 },
- { 0x1414, 0.002329 },
- { 0x1919, 0.003529 },
- { 0x1e1e, 0.005127 },
- { 0x2323, 0.007169 },
- { 0x2828, 0.009699 },
- { 0x2d2d, 0.012759 },
- { 0x3232, 0.016392 },
- { 0x3737, 0.020637 },
- { 0x3c3c, 0.025533 },
- { 0x4141, 0.031119 },
- { 0x4646, 0.037431 },
- { 0x4b4b, 0.044504 },
- { 0x5050, 0.052373 },
- { 0x5555, 0.061069 },
- { 0x5a5a, 0.070624 },
- { 0x5f5f, 0.081070 },
- { 0x6464, 0.092433 },
- { 0x6969, 0.104744 },
- { 0x6e6e, 0.118026 },
- { 0x7373, 0.132307 },
- { 0x7878, 0.147610 },
- { 0x7d7d, 0.163958 },
- { 0x8282, 0.181371 },
- { 0x8787, 0.199871 },
- { 0x8c8c, 0.219475 },
- { 0x9191, 0.240202 },
- { 0x9696, 0.262069 },
- { 0x9b9b, 0.285089 },
- { 0xa0a0, 0.309278 },
- { 0xa5a5, 0.334647 },
- { 0xaaaa, 0.361208 },
- { 0xafaf, 0.388971 },
- { 0xb4b4, 0.417945 },
- { 0xb9b9, 0.448138 },
- { 0xbebe, 0.479555 },
- { 0xc3c3, 0.512202 },
- { 0xc8c8, 0.546082 },
- { 0xcdcd, 0.581199 },
- { 0xd2d2, 0.617552 },
- { 0xd7d7, 0.655144 },
- { 0xdcdc, 0.693971 },
- { 0xe1e1, 0.734031 },
- { 0xe6e6, 0.775322 },
- { 0xebeb, 0.817837 },
- { 0xf0f0, 0.861571 },
- { 0xf5f5, 0.906515 },
- { 0xfafa, 0.952662 },
- { 0xffff, 1.000000 }
-};
-
-static IntensityRec const Default_RGB_GreenTuples[] = {
- /* {unsigned short value, XcmsFloat intensity} */
- { 0x0000, 0.000000 },
- { 0x1313, 0.000000 },
- { 0x1414, 0.000832 },
- { 0x1919, 0.001998 },
- { 0x1e1e, 0.003612 },
- { 0x2323, 0.005736 },
- { 0x2828, 0.008428 },
- { 0x2d2d, 0.011745 },
- { 0x3232, 0.015740 },
- { 0x3737, 0.020463 },
- { 0x3c3c, 0.025960 },
- { 0x4141, 0.032275 },
- { 0x4646, 0.039449 },
- { 0x4b4b, 0.047519 },
- { 0x5050, 0.056520 },
- { 0x5555, 0.066484 },
- { 0x5a5a, 0.077439 },
- { 0x5f5f, 0.089409 },
- { 0x6464, 0.102418 },
- { 0x6969, 0.116485 },
- { 0x6e6e, 0.131625 },
- { 0x7373, 0.147853 },
- { 0x7878, 0.165176 },
- { 0x7d7d, 0.183604 },
- { 0x8282, 0.203140 },
- { 0x8787, 0.223783 },
- { 0x8c8c, 0.245533 },
- { 0x9191, 0.268384 },
- { 0x9696, 0.292327 },
- { 0x9b9b, 0.317351 },
- { 0xa0a0, 0.343441 },
- { 0xa5a5, 0.370580 },
- { 0xaaaa, 0.398747 },
- { 0xafaf, 0.427919 },
- { 0xb4b4, 0.458068 },
- { 0xb9b9, 0.489165 },
- { 0xbebe, 0.521176 },
- { 0xc3c3, 0.554067 },
- { 0xc8c8, 0.587797 },
- { 0xcdcd, 0.622324 },
- { 0xd2d2, 0.657604 },
- { 0xd7d7, 0.693588 },
- { 0xdcdc, 0.730225 },
- { 0xe1e1, 0.767459 },
- { 0xe6e6, 0.805235 },
- { 0xebeb, 0.843491 },
- { 0xf0f0, 0.882164 },
- { 0xf5f5, 0.921187 },
- { 0xfafa, 0.960490 },
- { 0xffff, 1.000000 }
-};
-
-static IntensityRec const Default_RGB_BlueTuples[] = {
- /* {unsigned short value, XcmsFloat intensity} */
- { 0x0000, 0.000000 },
- { 0x0e0e, 0.000000 },
- { 0x0f0f, 0.001341 },
- { 0x1414, 0.002080 },
- { 0x1919, 0.003188 },
- { 0x1e1e, 0.004729 },
- { 0x2323, 0.006766 },
- { 0x2828, 0.009357 },
- { 0x2d2d, 0.012559 },
- { 0x3232, 0.016424 },
- { 0x3737, 0.021004 },
- { 0x3c3c, 0.026344 },
- { 0x4141, 0.032489 },
- { 0x4646, 0.039481 },
- { 0x4b4b, 0.047357 },
- { 0x5050, 0.056154 },
- { 0x5555, 0.065903 },
- { 0x5a5a, 0.076634 },
- { 0x5f5f, 0.088373 },
- { 0x6464, 0.101145 },
- { 0x6969, 0.114968 },
- { 0x6e6e, 0.129862 },
- { 0x7373, 0.145841 },
- { 0x7878, 0.162915 },
- { 0x7d7d, 0.181095 },
- { 0x8282, 0.200386 },
- { 0x8787, 0.220791 },
- { 0x8c8c, 0.242309 },
- { 0x9191, 0.264937 },
- { 0x9696, 0.288670 },
- { 0x9b9b, 0.313499 },
- { 0xa0a0, 0.339410 },
- { 0xa5a5, 0.366390 },
- { 0xaaaa, 0.394421 },
- { 0xafaf, 0.423481 },
- { 0xb4b4, 0.453547 },
- { 0xb9b9, 0.484592 },
- { 0xbebe, 0.516587 },
- { 0xc3c3, 0.549498 },
- { 0xc8c8, 0.583291 },
- { 0xcdcd, 0.617925 },
- { 0xd2d2, 0.653361 },
- { 0xd7d7, 0.689553 },
- { 0xdcdc, 0.726454 },
- { 0xe1e1, 0.764013 },
- { 0xe6e6, 0.802178 },
- { 0xebeb, 0.840891 },
- { 0xf0f0, 0.880093 },
- { 0xf5f5, 0.919723 },
- { 0xfafa, 0.959715 },
- { 0xffff, 1.00000 }
-};
-
-static IntensityTbl Default_RGB_RedTbl = {
- /* IntensityRec *pBase */
- (IntensityRec *) Default_RGB_RedTuples,
- /* unsigned int nEntries */
- 52
-};
-
-static IntensityTbl Default_RGB_GreenTbl = {
- /* IntensityRec *pBase */
- (IntensityRec *)Default_RGB_GreenTuples,
- /* unsigned int nEntries */
- 50
-};
-
-static IntensityTbl Default_RGB_BlueTbl = {
- /* IntensityRec *pBase */
- (IntensityRec *)Default_RGB_BlueTuples,
- /* unsigned int nEntries */
- 51
-};
-
-static LINEAR_RGB_SCCData Default_RGB_SCCData = {
- /* XcmsFloat XYZtoRGBmatrix[3][3] */
- {
- { 3.48340481253539000, -1.52176374927285200, -0.55923133354049780 },
- {-1.07152751306193600, 1.96593795204372400, 0.03673691339553462 },
- { 0.06351179790497788, -0.20020501000496480, 0.81070942031648220 }
- },
-
- /* XcmsFloat RGBtoXYZmatrix[3][3] */
- {
- { 0.38106149108714790, 0.32025712365352110, 0.24834578525933100 },
- { 0.20729745115140850, 0.68054638776373240, 0.11215616108485920 },
- { 0.02133944350088028, 0.14297193020246480, 1.24172892629665500 }
- },
-
- /* IntensityTbl *pRedTbl */
- &Default_RGB_RedTbl,
-
- /* IntensityTbl *pGreenTbl */
- &Default_RGB_GreenTbl,
-
- /* IntensityTbl *pBlueTbl */
- &Default_RGB_BlueTbl
-};
-
-/************************************************************************
- * *
- * PRIVATE ROUTINES *
- * *
- ************************************************************************/
-
-/*
- * NAME
- * LINEAR_RGB_InitSCCData()
- *
- * SYNOPSIS
- */
-static Status
-LINEAR_RGB_InitSCCData(
- Display *dpy,
- int screenNumber,
- XcmsPerScrnInfo *pPerScrnInfo)
-/*
- * DESCRIPTION
- *
- * RETURNS
- * XcmsFailure if failed.
- * XcmsSuccess if succeeded.
- *
- */
-{
- Atom CorrectAtom = XInternAtom (dpy, XDCCC_CORRECT_ATOM_NAME, True);
- Atom MatrixAtom = XInternAtom (dpy, XDCCC_MATRIX_ATOM_NAME, True);
- int format_return, count, cType, nTables;
- unsigned long nitems, nbytes_return;
- char *property_return, *pChar;
- XcmsFloat *pValue;
-#ifdef ALLDEBUG
- IntensityRec *pIRec;
-#endif /* ALLDEBUG */
- VisualID visualID;
-
- LINEAR_RGB_SCCData *pScreenData, *pScreenDefaultData;
- XcmsIntensityMap *pNewMap;
-
- /*
- * Allocate memory for pScreenData
- */
- if (!(pScreenData = pScreenDefaultData = (LINEAR_RGB_SCCData *)
- Xcalloc (1, sizeof(LINEAR_RGB_SCCData)))) {
- return(XcmsFailure);
- }
-
- /*
- * 1. Get the XYZ->RGB and RGB->XYZ matrices
- */
-
- if (MatrixAtom == None ||
- !_XcmsGetProperty (dpy, RootWindow(dpy, screenNumber), MatrixAtom,
- &format_return, &nitems, &nbytes_return, &property_return) ||
- nitems != 18 || format_return != 32) {
- /*
- * As per the XDCCC, there must be 18 data items and each must be
- * in 32 bits !
- */
- goto FreeSCCData;
-
- } else {
-
- /*
- * RGBtoXYZ and XYZtoRGB matrices
- */
- pValue = (XcmsFloat *) pScreenData;
- pChar = property_return;
- for (count = 0; count < 18; count++) {
- *pValue++ = (long)_XcmsGetElement(format_return, &pChar,
- &nitems) / (XcmsFloat)XDCCC_NUMBER;
- }
- Xfree ((char *)property_return);
- pPerScrnInfo->screenWhitePt.spec.CIEXYZ.X =
- pScreenData->RGBtoXYZmatrix[0][0] +
- pScreenData->RGBtoXYZmatrix[0][1] +
- pScreenData->RGBtoXYZmatrix[0][2];
- pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y =
- pScreenData->RGBtoXYZmatrix[1][0] +
- pScreenData->RGBtoXYZmatrix[1][1] +
- pScreenData->RGBtoXYZmatrix[1][2];
- pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Z =
- pScreenData->RGBtoXYZmatrix[2][0] +
- pScreenData->RGBtoXYZmatrix[2][1] +
- pScreenData->RGBtoXYZmatrix[2][2];
-
- /*
- * Compute the Screen White Point
- */
- if ((pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y < (1.0 - EPS) )
- || (pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y > (1.0 + EPS))) {
- goto FreeSCCData;
- } else {
- pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y = 1.0;
- }
- pPerScrnInfo->screenWhitePt.format = XcmsCIEXYZFormat;
- pPerScrnInfo->screenWhitePt.pixel = 0;
-
-#ifdef PDEBUG
- printf ("RGB to XYZ Matrix values:\n");
- printf (" %f %f %f\n %f %f %f\n %f %f %f\n",
- pScreenData->RGBtoXYZmatrix[0][0],
- pScreenData->RGBtoXYZmatrix[0][1],
- pScreenData->RGBtoXYZmatrix[0][2],
- pScreenData->RGBtoXYZmatrix[1][0],
- pScreenData->RGBtoXYZmatrix[1][1],
- pScreenData->RGBtoXYZmatrix[1][2],
- pScreenData->RGBtoXYZmatrix[2][0],
- pScreenData->RGBtoXYZmatrix[2][1],
- pScreenData->RGBtoXYZmatrix[2][2]);
- printf ("XYZ to RGB Matrix values:\n");
- printf (" %f %f %f\n %f %f %f\n %f %f %f\n",
- pScreenData->XYZtoRGBmatrix[0][0],
- pScreenData->XYZtoRGBmatrix[0][1],
- pScreenData->XYZtoRGBmatrix[0][2],
- pScreenData->XYZtoRGBmatrix[1][0],
- pScreenData->XYZtoRGBmatrix[1][1],
- pScreenData->XYZtoRGBmatrix[1][2],
- pScreenData->XYZtoRGBmatrix[2][0],
- pScreenData->XYZtoRGBmatrix[2][1],
- pScreenData->XYZtoRGBmatrix[2][2]);
- printf ("Screen White Pt value: %f %f %f\n",
- pPerScrnInfo->screenWhitePt.spec.CIEXYZ.X,
- pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y,
- pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Z);
-#endif /* PDEBUG */
- }
-
- /*
- * 2. Get the Intensity Profile
- */
- if (CorrectAtom == None ||
- !_XcmsGetProperty (dpy, RootWindow(dpy, screenNumber), CorrectAtom,
- &format_return, &nitems, &nbytes_return, &property_return)) {
- goto FreeSCCData;
- }
-
- pChar = property_return;
-
- while (nitems) {
- switch (format_return) {
- case 8:
- /*
- * Must have at least:
- * VisualID0
- * VisualID1
- * VisualID2
- * VisualID3
- * type
- * count
- * length
- * intensity1
- * intensity2
- */
- if (nitems < 9) {
- goto Free_property_return;
- }
- count = 3;
- break;
- case 16:
- /*
- * Must have at least:
- * VisualID0
- * VisualID3
- * type
- * count
- * length
- * intensity1
- * intensity2
- */
- if (nitems < 7) {
- goto Free_property_return;
- }
- count = 1;
- break;
- case 32:
- /*
- * Must have at least:
- * VisualID0
- * type
- * count
- * length
- * intensity1
- * intensity2
- */
- if (nitems < 6) {
- goto Free_property_return;
- }
- count = 0;
- break;
- default:
- goto Free_property_return;
- }
-
- /*
- * Get VisualID
- */
- visualID = _XcmsGetElement(format_return, &pChar, &nitems);
- while (count--) {
- visualID = visualID << format_return;
- visualID |= _XcmsGetElement(format_return, &pChar, &nitems);
- }
-
- if (visualID == 0) {
- /*
- * This is a shared intensity table
- */
- pScreenData = pScreenDefaultData;
- } else {
- /*
- * This is a per-Visual intensity table
- */
- if (!(pScreenData = (LINEAR_RGB_SCCData *)
- Xcalloc (1, sizeof(LINEAR_RGB_SCCData)))) {
- goto Free_property_return;
- }
- /* copy matrices */
- memcpy((char *)pScreenData, (char *)pScreenDefaultData,
- 18 * sizeof(XcmsFloat));
-
- /* Create, initialize, and add map */
- if (!(pNewMap = (XcmsIntensityMap *)
- Xcalloc (1, sizeof(XcmsIntensityMap)))) {
- Xfree((char *)pScreenData);
- goto Free_property_return;
- }
- pNewMap->visualID = visualID;
- pNewMap->screenData = (XPointer)pScreenData;
- pNewMap->pFreeScreenData = LINEAR_RGB_FreeSCCData;
- pNewMap->pNext =
- (XcmsIntensityMap *)dpy->cms.perVisualIntensityMaps;
- dpy->cms.perVisualIntensityMaps = (XPointer)pNewMap;
- dpy->free_funcs->intensityMaps = _XcmsFreeIntensityMaps;
- }
-
- cType = _XcmsGetElement(format_return, &pChar, &nitems);
- nTables = _XcmsGetElement(format_return, &pChar, &nitems);
-
- if (cType == 0) {
-
- /* Red Intensity Table */
- if (!(pScreenData->pRedTbl = (IntensityTbl *)
- Xcalloc (1, sizeof(IntensityTbl)))) {
- goto Free_property_return;
- }
- if (_XcmsGetTableType0(pScreenData->pRedTbl, format_return, &pChar,
- &nitems) == XcmsFailure) {
- goto FreeRedTbl;
- }
-
- if (nTables == 1) {
- /* Green Intensity Table */
- pScreenData->pGreenTbl = pScreenData->pRedTbl;
- /* Blue Intensity Table */
- pScreenData->pBlueTbl = pScreenData->pRedTbl;
- } else {
- /* Green Intensity Table */
- if (!(pScreenData->pGreenTbl = (IntensityTbl *)
- Xcalloc (1, sizeof(IntensityTbl)))) {
- goto FreeRedTblElements;
- }
- if (_XcmsGetTableType0(pScreenData->pGreenTbl, format_return, &pChar,
- &nitems) == XcmsFailure) {
- goto FreeGreenTbl;
- }
-
- /* Blue Intensity Table */
- if (!(pScreenData->pBlueTbl = (IntensityTbl *)
- Xcalloc (1, sizeof(IntensityTbl)))) {
- goto FreeGreenTblElements;
- }
- if (_XcmsGetTableType0(pScreenData->pBlueTbl, format_return, &pChar,
- &nitems) == XcmsFailure) {
- goto FreeBlueTbl;
- }
- }
- } else if (cType == 1) {
- /* Red Intensity Table */
- if (!(pScreenData->pRedTbl = (IntensityTbl *)
- Xcalloc (1, sizeof(IntensityTbl)))) {
- goto Free_property_return;
- }
- if (_XcmsGetTableType1(pScreenData->pRedTbl, format_return, &pChar,
- &nitems) == XcmsFailure) {
- goto FreeRedTbl;
- }
-
- if (nTables == 1) {
-
- /* Green Intensity Table */
- pScreenData->pGreenTbl = pScreenData->pRedTbl;
- /* Blue Intensity Table */
- pScreenData->pBlueTbl = pScreenData->pRedTbl;
-
- } else {
-
- /* Green Intensity Table */
- if (!(pScreenData->pGreenTbl = (IntensityTbl *)
- Xcalloc (1, sizeof(IntensityTbl)))) {
- goto FreeRedTblElements;
- }
- if (_XcmsGetTableType1(pScreenData->pGreenTbl, format_return, &pChar,
- &nitems) == XcmsFailure) {
- goto FreeGreenTbl;
- }
-
- /* Blue Intensity Table */
- if (!(pScreenData->pBlueTbl = (IntensityTbl *)
- Xcalloc (1, sizeof(IntensityTbl)))) {
- goto FreeGreenTblElements;
- }
- if (_XcmsGetTableType1(pScreenData->pBlueTbl, format_return, &pChar,
- &nitems) == XcmsFailure) {
- goto FreeBlueTbl;
- }
- }
- } else {
- goto Free_property_return;
- }
-
-#ifdef ALLDEBUG
- printf ("Intensity Table RED %d\n", pScreenData->pRedTbl->nEntries);
- pIRec = (IntensityRec *) pScreenData->pRedTbl->pBase;
- for (count = 0; count < pScreenData->pRedTbl->nEntries; count++, pIRec++) {
- printf ("\t0x%4x\t%f\n", pIRec->value, pIRec->intensity);
- }
- if (pScreenData->pGreenTbl->pBase != pScreenData->pRedTbl->pBase) {
- printf ("Intensity Table GREEN %d\n", pScreenData->pGreenTbl->nEntries);
- pIRec = (IntensityRec *)pScreenData->pGreenTbl->pBase;
- for (count = 0; count < pScreenData->pGreenTbl->nEntries; count++, pIRec++) {
- printf ("\t0x%4x\t%f\n", pIRec->value, pIRec->intensity);
- }
- }
- if (pScreenData->pBlueTbl->pBase != pScreenData->pRedTbl->pBase) {
- printf ("Intensity Table BLUE %d\n", pScreenData->pBlueTbl->nEntries);
- pIRec = (IntensityRec *) pScreenData->pBlueTbl->pBase;
- for (count = 0; count < pScreenData->pBlueTbl->nEntries; count++, pIRec++) {
- printf ("\t0x%4x\t%f\n", pIRec->value, pIRec->intensity);
- }
- }
-#endif /* ALLDEBUG */
- }
-
- Xfree ((char *)property_return);
-
- /* Free the old memory and use the new structure created. */
- LINEAR_RGB_FreeSCCData(pPerScrnInfo->screenData);
-
- pPerScrnInfo->functionSet = (XPointer) &XcmsLinearRGBFunctionSet;
-
- pPerScrnInfo->screenData = (XPointer) pScreenData;
-
- pPerScrnInfo->state = XcmsInitSuccess;
-
- return(XcmsSuccess);
-
-FreeBlueTblElements:
- Xfree((char *)pScreenData->pBlueTbl->pBase);
-
-FreeBlueTbl:
- Xfree((char *)pScreenData->pBlueTbl);
-
-FreeGreenTblElements:
- Xfree((char *)pScreenData->pGreenTbl->pBase);
-
-FreeGreenTbl:
- Xfree((char *)pScreenData->pGreenTbl);
-
-FreeRedTblElements:
- Xfree((char *)pScreenData->pRedTbl->pBase);
-
-FreeRedTbl:
- Xfree((char *)pScreenData->pRedTbl);
-
-Free_property_return:
- Xfree ((char *)property_return);
-
-FreeSCCData:
- Xfree((char *)pScreenDefaultData);
- pPerScrnInfo->state = XcmsInitNone;
- return(XcmsFailure);
-}
-
-
-/*
- * NAME
- * LINEAR_RGB_FreeSCCData()
- *
- * SYNOPSIS
- */
-static void
-LINEAR_RGB_FreeSCCData(
- XPointer pScreenDataTemp)
-/*
- * DESCRIPTION
- *
- * RETURNS
- * 0 if failed.
- * 1 if succeeded with no modifications.
- *
- */
-{
- LINEAR_RGB_SCCData *pScreenData = (LINEAR_RGB_SCCData *) pScreenDataTemp;
-
- if (pScreenData && pScreenData != &Default_RGB_SCCData) {
- if (pScreenData->pRedTbl) {
- if (pScreenData->pGreenTbl) {
- if (pScreenData->pRedTbl->pBase !=
- pScreenData->pGreenTbl->pBase) {
- if (pScreenData->pGreenTbl->pBase) {
- Xfree ((char *)pScreenData->pGreenTbl->pBase);
- }
- }
- if (pScreenData->pGreenTbl != pScreenData->pRedTbl) {
- Xfree ((char *)pScreenData->pGreenTbl);
- }
- }
- if (pScreenData->pBlueTbl) {
- if (pScreenData->pRedTbl->pBase !=
- pScreenData->pBlueTbl->pBase) {
- if (pScreenData->pBlueTbl->pBase) {
- Xfree ((char *)pScreenData->pBlueTbl->pBase);
- }
- }
- if (pScreenData->pBlueTbl != pScreenData->pRedTbl) {
- Xfree ((char *)pScreenData->pBlueTbl);
- }
- }
- if (pScreenData->pRedTbl->pBase) {
- Xfree ((char *)pScreenData->pRedTbl->pBase);
- }
- Xfree ((char *)pScreenData->pRedTbl);
- }
- Xfree ((char *)pScreenData);
- }
-}
-
-
-
-/************************************************************************
- * *
- * API PRIVATE ROUTINES *
- * *
- ************************************************************************/
-
-/*
- * NAME
- * _XcmsGetTableType0
- *
- * SYNOPSIS
- */
-static Status
-_XcmsGetTableType0(
- IntensityTbl *pTbl,
- int format,
- char **pChar,
- unsigned long *pCount)
-/*
- * DESCRIPTION
- *
- * RETURNS
- * XcmsFailure if failed.
- * XcmsSuccess if succeeded.
- *
- */
-{
- unsigned int nElements;
- IntensityRec *pIRec;
-
- nElements = pTbl->nEntries =
- _XcmsGetElement(format, pChar, pCount) + 1;
- if (!(pIRec = pTbl->pBase = (IntensityRec *)
- Xcalloc (nElements, sizeof(IntensityRec)))) {
- return(XcmsFailure);
- }
-
- switch (format) {
- case 8:
- for (; nElements--; pIRec++) {
- /* 0xFFFF/0xFF = 0x101 */
- pIRec->value = _XcmsGetElement (format, pChar, pCount) * 0x101;
- pIRec->intensity =
- _XcmsGetElement (format, pChar, pCount) / (XcmsFloat)255.0;
- }
- break;
- case 16:
- for (; nElements--; pIRec++) {
- pIRec->value = _XcmsGetElement (format, pChar, pCount);
- pIRec->intensity = _XcmsGetElement (format, pChar, pCount)
- / (XcmsFloat)65535.0;
- }
- break;
- case 32:
- for (; nElements--; pIRec++) {
- pIRec->value = _XcmsGetElement (format, pChar, pCount);
- pIRec->intensity = _XcmsGetElement (format, pChar, pCount)
- / (XcmsFloat)4294967295.0;
- }
- break;
- default:
- return(XcmsFailure);
- }
- return(XcmsSuccess);
-}
-
-
-/*
- * NAME
- * _XcmsGetTableType1
- *
- * SYNOPSIS
- */
-static Status
-_XcmsGetTableType1(
- IntensityTbl *pTbl,
- int format,
- char **pChar,
- unsigned long *pCount)
-/*
- * DESCRIPTION
- *
- * RETURNS
- * XcmsFailure if failed.
- * XcmsSuccess if succeeded.
- *
- */
-{
- int count;
- unsigned int max_index;
- IntensityRec *pIRec;
-
- max_index = _XcmsGetElement(format, pChar, pCount);
- pTbl->nEntries = max_index + 1;
- if (!(pIRec = pTbl->pBase = (IntensityRec *)
- Xcalloc (max_index+1, sizeof(IntensityRec)))) {
- return(XcmsFailure);
- }
-
- switch (format) {
- case 8:
- for (count = 0; count < max_index+1; count++, pIRec++) {
- pIRec->value = (count * 65535) / max_index;
- pIRec->intensity = _XcmsGetElement (format, pChar, pCount)
- / (XcmsFloat)255.0;
- }
- break;
- case 16:
- for (count = 0; count < max_index+1; count++, pIRec++) {
- pIRec->value = (count * 65535) / max_index;
- pIRec->intensity = _XcmsGetElement (format, pChar, pCount)
- / (XcmsFloat)65535.0;
- }
- break;
- case 32:
- for (count = 0; count < max_index+1; count++, pIRec++) {
- pIRec->value = (count * 65535) / max_index;
- pIRec->intensity = _XcmsGetElement (format, pChar, pCount)
- / (XcmsFloat)4294967295.0;
- }
- break;
- default:
- return(XcmsFailure);
- }
-
- return(XcmsSuccess);
-}
-
-
-/*
- * NAME
- * ValueCmp
- *
- * SYNOPSIS
- */
-static int
-_XcmsValueCmp(
- IntensityRec *p1, IntensityRec *p2)
-/*
- * DESCRIPTION
- * Compares the value component of two IntensityRec
- * structures.
- *
- * RETURNS
- * 0 if p1->value is equal to p2->value
- * < 0 if p1->value is less than p2->value
- * > 0 if p1->value is greater than p2->value
- *
- */
-{
- return (p1->value - p2->value);
-}
-
-
-/*
- * NAME
- * IntensityCmp
- *
- * SYNOPSIS
- */
-static int
-_XcmsIntensityCmp(
- IntensityRec *p1, IntensityRec *p2)
-/*
- * DESCRIPTION
- * Compares the intensity component of two IntensityRec
- * structures.
- *
- * RETURNS
- * 0 if equal;
- * < 0 if first precedes second
- * > 0 if first succeeds second
- *
- */
-{
- if (p1->intensity < p2->intensity) {
- return (-1);
- }
- if (p1->intensity > p2->intensity) {
- return (XcmsSuccess);
- }
- return (XcmsFailure);
-}
-
-/*
- * NAME
- * ValueInterpolation
- *
- * SYNOPSIS
- */
-/* ARGSUSED */
-static int
-_XcmsValueInterpolation(
- IntensityRec *key, IntensityRec *lo, IntensityRec *hi, IntensityRec *answer,
- int bitsPerRGB)
-/*
- * DESCRIPTION
- * Based on a given value, performs a linear interpolation
- * on the intensities between two IntensityRec structures.
- * Note that the bitsPerRGB parameter is ignored.
- *
- * RETURNS
- * Returns 0 if failed; otherwise non-zero.
- */
-{
- XcmsFloat ratio;
-
- ratio = ((XcmsFloat)key->value - (XcmsFloat)lo->value) /
- ((XcmsFloat)hi->value - (XcmsFloat)lo->value);
- answer->value = key->value;
- answer->intensity = (hi->intensity - lo->intensity) * ratio;
- answer->intensity += lo->intensity;
- return (XcmsSuccess);
-}
-
-/*
- * NAME
- * IntensityInterpolation
- *
- * SYNOPSIS
- */
-static int
-_XcmsIntensityInterpolation(
- IntensityRec *key, IntensityRec *lo, IntensityRec *hi, IntensityRec *answer,
- int bitsPerRGB)
-/*
- * DESCRIPTION
- * Based on a given intensity, performs a linear interpolation
- * on the values between two IntensityRec structures.
- * The bitsPerRGB parameter is necessary to perform rounding
- * to the correct number of significant bits.
- *
- * RETURNS
- * Returns 0 if failed; otherwise non-zero.
- */
-{
- XcmsFloat ratio;
- long target, up, down;
- int shift = 16 - bitsPerRGB;
- int max_color = (1 << bitsPerRGB) - 1;
-
- ratio = (key->intensity - lo->intensity) / (hi->intensity - lo->intensity);
- answer->intensity = key->intensity;
- target = hi->value - lo->value;
- target *= ratio;
- target += lo->value;
-
- /*
- * Ok now, lets find the closest in respects to bits per RGB
- */
- up = ((target >> shift) * 0xFFFF) / max_color;
- if (up < target) {
- down = up;
- up = (MIN((down >> shift) + 1, max_color) * 0xFFFF) / max_color;
- } else {
- down = (MAX((up >> shift) - 1, 0) * 0xFFFF) / max_color;
- }
- answer->value = ((up - target) < (target - down) ? up : down);
- answer->value &= MASK[bitsPerRGB];
- return (XcmsSuccess);
-}
-
-
-
-typedef int (*comparProcp)(
- char *p1,
- char *p2);
-typedef int (*interpolProcp)(
- char *key,
- char *lo,
- char *hi,
- char *answer,
- int bitsPerRGB);
-
-/*
- * NAME
- * _XcmsTableSearch
- *
- * SYNOPSIS
- */
-static int
-_XcmsTableSearch(
- char *key,
- int bitsPerRGB,
- char *base,
- unsigned nel,
- unsigned nKeyPtrSize,
- int (*compar)(
- char *p1,
- char *p2),
- int (*interpol)(
- char *key,
- char *lo,
- char *hi,
- char *answer,
- int bitsPerRGB),
- char *answer)
-
-/*
- * DESCRIPTION
- * A binary search through the specificied table.
- *
- * RETURNS
- * Returns 0 if failed; otherwise non-zero.
- *
- */
-{
- char *hi, *lo, *mid, *last;
- int result;
-
- last = hi = base + ((nel - 1) * nKeyPtrSize);
- mid = lo = base;
-
- /* use only the significants bits, then scale into 16 bits */
- ((IntensityRec *)key)->value = ((unsigned long)
- (((IntensityRec *)key)->value >> (16 - bitsPerRGB)) * 0xFFFF)
- / ((1 << bitsPerRGB) - 1);
-
- /* Special case so that zero intensity always maps to zero value */
- if ((*compar) (key,lo) <= 0) {
- memcpy (answer, lo, nKeyPtrSize);
- ((IntensityRec *)answer)->value &= MASK[bitsPerRGB];
- return XcmsSuccess;
- }
- while (mid != last) {
- last = mid;
- mid = lo + (((unsigned)(hi - lo) / nKeyPtrSize) / 2) * nKeyPtrSize;
- result = (*compar) (key, mid);
- if (result == 0) {
-
- memcpy(answer, mid, nKeyPtrSize);
- ((IntensityRec *)answer)->value &= MASK[bitsPerRGB];
- return (XcmsSuccess);
- } else if (result < 0) {
- hi = mid;
- } else {
- lo = mid;
- }
- }
-
- /*
- * If we got to here, we didn't find a solution, so we
- * need to apply interpolation.
- */
- return ((*interpol)(key, lo, hi, answer, bitsPerRGB));
-}
-
-
-/*
- * NAME
- * _XcmsMatVec - multiply a 3 x 3 by a 3 x 1 vector
- *
- * SYNOPSIS
- */
-static void _XcmsMatVec(
- XcmsFloat *pMat, XcmsFloat *pIn, XcmsFloat *pOut)
-/*
- * DESCRIPTION
- * Multiply the passed vector by the passed matrix to return a
- * vector. Matrix is 3x3, vectors are of length 3.
- *
- * RETURNS
- * void
- */
-{
- int i, j;
-
- for (i = 0; i < 3; i++) {
- pOut[i] = 0.0;
- for (j = 0; j < 3; j++)
- pOut[i] += *(pMat+(i*3)+j) * pIn[j];
- }
-}
-
-
-/************************************************************************
- * *
- * PUBLIC ROUTINES *
- * *
- ************************************************************************/
-
-
-/*
- * NAME
- * XcmsLRGB_RGB_ParseString
- *
- * SYNOPSIS
- */
-static int
-XcmsLRGB_RGB_ParseString(
- register char *spec,
- XcmsColor *pColor)
-/*
- * DESCRIPTION
- * This routines takes a string and attempts to convert
- * it into a XcmsColor structure with XcmsRGBFormat.
- *
- * RETURNS
- * 0 if failed, non-zero otherwise.
- */
-{
- register int n, i;
- unsigned short r, g, b;
- char c;
- char *pchar;
- unsigned short *pShort;
-
- /*
- * Check for old # format
- */
- if (*spec == '#') {
- /*
- * Attempt to parse the value portion.
- */
- spec++;
- n = strlen(spec);
- if (n != 3 && n != 6 && n != 9 && n != 12) {
- return(XcmsFailure);
- }
-
- n /= 3;
- g = b = 0;
- do {
- r = g;
- g = b;
- b = 0;
- for (i = n; --i >= 0; ) {
- c = *spec++;
- b <<= 4;
- if (c >= '0' && c <= '9')
- b |= c - '0';
- /* assume string in lowercase
- else if (c >= 'A' && c <= 'F')
- b |= c - ('A' - 10);
- */
- else if (c >= 'a' && c <= 'f')
- b |= c - ('a' - 10);
- else return (XcmsFailure);
- }
- } while (*spec != '\0');
-
- /*
- * Succeeded !
- */
- n <<= 2;
- n = 16 - n;
- /* shift instead of scale, to match old broken semantics */
- pColor->spec.RGB.red = r << n;
- pColor->spec.RGB.green = g << n;
- pColor->spec.RGB.blue = b << n;
- } else {
- if ((pchar = strchr(spec, ':')) == NULL) {
- return(XcmsFailure);
- }
- n = (int)(pchar - spec);
-
- /*
- * Check for proper prefix.
- */
- if (strncmp(spec, _XcmsRGB_prefix, n) != 0) {
- return(XcmsFailure);
- }
-
- /*
- * Attempt to parse the value portion.
- */
- spec += (n + 1);
- pShort = &pColor->spec.RGB.red;
- for (i = 0; i < 3; i++, pShort++, spec++) {
- n = 0;
- *pShort = 0;
- while (*spec != '/' && *spec != '\0') {
- if (++n > 4) {
- return(XcmsFailure);
- }
- c = *spec++;
- *pShort <<= 4;
- if (c >= '0' && c <= '9')
- *pShort |= c - '0';
- /* assume string in lowercase
- else if (c >= 'A' && c <= 'F')
- *pShort |= c - ('A' - 10);
- */
- else if (c >= 'a' && c <= 'f')
- *pShort |= c - ('a' - 10);
- else return (XcmsFailure);
- }
- if (n == 0)
- return (XcmsFailure);
- if (n < 4) {
- *pShort = ((unsigned long)*pShort * 0xFFFF) / ((1 << n*4) - 1);
- }
- }
- }
- pColor->format = XcmsRGBFormat;
- pColor->pixel = 0;
- return (XcmsSuccess);
-}
-
-
-/*
- * NAME
- * XcmsLRGB_RGBi_ParseString
- *
- * SYNOPSIS
- */
-static int
-XcmsLRGB_RGBi_ParseString(
- register char *spec,
- XcmsColor *pColor)
-/*
- * DESCRIPTION
- * This routines takes a string and attempts to convert
- * it into a XcmsColor structure with XcmsRGBiFormat.
- * The assumed RGBi string syntax is:
- * RGBi:<r>/<g>/<b>
- * Where r, g, and b are in string input format for floats
- * consisting of:
- * a. an optional sign
- * b. a string of numbers possibly containing a decimal point,
- * c. an optional exponent field containing an 'E' or 'e'
- * followed by a possibly signed integer string.
- *
- * RETURNS
- * 0 if failed, non-zero otherwise.
- */
-{
- int n;
- char *pchar;
-
- if ((pchar = strchr(spec, ':')) == NULL) {
- return(XcmsFailure);
- }
- n = (int)(pchar - spec);
-
- /*
- * Check for proper prefix.
- */
- if (strncmp(spec, _XcmsRGBi_prefix, n) != 0) {
- return(XcmsFailure);
- }
-
- /*
- * Attempt to parse the value portion.
- */
- if (sscanf(spec + n + 1, "%lf/%lf/%lf",
- &pColor->spec.RGBi.red,
- &pColor->spec.RGBi.green,
- &pColor->spec.RGBi.blue) != 3) {
- char *s; /* Maybe failed due to locale */
- int f;
- if ((s = strdup(spec))) {
- for (f = 0; s[f]; ++f)
- if (s[f] == '.')
- s[f] = ',';
- else if (s[f] == ',')
- s[f] = '.';
- if (sscanf(s + n + 1, "%lf/%lf/%lf",
- &pColor->spec.RGBi.red,
- &pColor->spec.RGBi.green,
- &pColor->spec.RGBi.blue) != 3) {
- free(s);
- return(XcmsFailure);
- }
- free(s);
- } else
- return(XcmsFailure);
- }
-
- /*
- * Succeeded !
- */
- pColor->format = XcmsRGBiFormat;
- pColor->pixel = 0;
- return (XcmsSuccess);
-}
-
-
-/*
- * NAME
- * XcmsCIEXYZToRGBi - convert CIE XYZ to RGB
- *
- * SYNOPSIS
- */
-/* ARGSUSED */
-Status
-XcmsCIEXYZToRGBi(
- XcmsCCC ccc,
- XcmsColor *pXcmsColors_in_out,/* pointer to XcmsColors to convert */
- unsigned int nColors, /* Number of colors */
- Bool *pCompressed) /* pointer to an array of Bool */
-/*
- * DESCRIPTION
- * Converts color specifications in an array of XcmsColor
- * structures from RGB format to RGBi format.
- *
- * RETURNS
- * XcmsFailure if failed,
- * XcmsSuccess if succeeded without gamut compression.
- * XcmsSuccessWithCompression if succeeded with gamut
- * compression.
- */
-{
- LINEAR_RGB_SCCData *pScreenData;
- XcmsFloat tmp[3];
- int hasCompressed = 0;
- unsigned int i;
- XcmsColor *pColor = pXcmsColors_in_out;
-
- if (ccc == NULL) {
- return(XcmsFailure);
- }
-
- pScreenData = (LINEAR_RGB_SCCData *)ccc->pPerScrnInfo->screenData;
-
- /*
- * XcmsColors should be White Point Adjusted, if necessary, by now!
- */
-
- /*
- * NEW!!! for extended gamut compression
- *
- * 1. Need to zero out pCompressed
- *
- * 2. Need to save initial address of pColor
- *
- * 3. Need to save initial address of pCompressed
- */
-
- for (i = 0; i < nColors; i++) {
-
- /* Make sure format is XcmsCIEXYZFormat */
- if (pColor->format != XcmsCIEXYZFormat) {
- return(XcmsFailure);
- }
-
- /* Multiply [A]-1 * [XYZ] to get RGB intensity */
- _XcmsMatVec((XcmsFloat *) pScreenData->XYZtoRGBmatrix,
- (XcmsFloat *) &pColor->spec, tmp);
-
- if ((MIN3 (tmp[0], tmp[1], tmp[2]) < -EPS) ||
- (MAX3 (tmp[0], tmp[1], tmp[2]) > (1.0 + EPS))) {
-
- /*
- * RGBi out of screen's gamut
- */
-
- if (ccc->gamutCompProc == NULL) {
- /*
- * Aha!! Here's that little trick that will allow
- * gamut compression routines to get the out of bound
- * RGBi.
- */
- memcpy((char *)&pColor->spec, (char *)tmp, sizeof(tmp));
- pColor->format = XcmsRGBiFormat;
- return(XcmsFailure);
- } else if ((*ccc->gamutCompProc)(ccc, pXcmsColors_in_out, nColors,
- i, pCompressed) == 0) {
- return(XcmsFailure);
- }
-
- /*
- * The gamut compression function should return colors in CIEXYZ
- * Also check again to if the new color is within gamut.
- */
- if (pColor->format != XcmsCIEXYZFormat) {
- return(XcmsFailure);
- }
- _XcmsMatVec((XcmsFloat *) pScreenData->XYZtoRGBmatrix,
- (XcmsFloat *) &pColor->spec, tmp);
- if ((MIN3 (tmp[0], tmp[1], tmp[2]) < -EPS) ||
- (MAX3 (tmp[0], tmp[1], tmp[2]) > (1.0 + EPS))) {
- return(XcmsFailure);
- }
- hasCompressed++;
- }
- memcpy((char *)&pColor->spec, (char *)tmp, sizeof(tmp));
- /* These if statements are done to ensure the fudge factor is */
- /* is taken into account. */
- if (pColor->spec.RGBi.red < 0.0) {
- pColor->spec.RGBi.red = 0.0;
- } else if (pColor->spec.RGBi.red > 1.0) {
- pColor->spec.RGBi.red = 1.0;
- }
- if (pColor->spec.RGBi.green < 0.0) {
- pColor->spec.RGBi.green = 0.0;
- } else if (pColor->spec.RGBi.green > 1.0) {
- pColor->spec.RGBi.green = 1.0;
- }
- if (pColor->spec.RGBi.blue < 0.0) {
- pColor->spec.RGBi.blue = 0.0;
- } else if (pColor->spec.RGBi.blue > 1.0) {
- pColor->spec.RGBi.blue = 1.0;
- }
- (pColor++)->format = XcmsRGBiFormat;
- }
- return (hasCompressed ? XcmsSuccessWithCompression : XcmsSuccess);
-}
-
-
-/*
- * NAME
- * LINEAR_RGBi_to_CIEXYZ - convert RGBi to CIEXYZ
- *
- * SYNOPSIS
- */
-/* ARGSUSED */
-Status
-XcmsRGBiToCIEXYZ(
- XcmsCCC ccc,
- XcmsColor *pXcmsColors_in_out,/* pointer to XcmsColors to convert */
- unsigned int nColors, /* Number of colors */
- Bool *pCompressed) /* pointer to a bit array */
-/*
- * DESCRIPTION
- * Converts color specifications in an array of XcmsColor
- * structures from RGBi format to CIEXYZ format.
- *
- * RETURNS
- * XcmsFailure if failed,
- * XcmsSuccess if succeeded.
- */
-{
- LINEAR_RGB_SCCData *pScreenData;
- XcmsFloat tmp[3];
-
- /*
- * pCompressed ignored in this function.
- */
-
- if (ccc == NULL) {
- return(XcmsFailure);
- }
-
- pScreenData = (LINEAR_RGB_SCCData *)ccc->pPerScrnInfo->screenData;
-
- /*
- * XcmsColors should be White Point Adjusted, if necessary, by now!
- */
-
- while (nColors--) {
-
- /* Multiply [A]-1 * [XYZ] to get RGB intensity */
- _XcmsMatVec((XcmsFloat *) pScreenData->RGBtoXYZmatrix,
- (XcmsFloat *) &pXcmsColors_in_out->spec, tmp);
-
- memcpy((char *)&pXcmsColors_in_out->spec, (char *)tmp, sizeof(tmp));
- (pXcmsColors_in_out++)->format = XcmsCIEXYZFormat;
- }
- return(XcmsSuccess);
-}
-
-
-/*
- * NAME
- * XcmsRGBiToRGB
- *
- * SYNOPSIS
- */
-/* ARGSUSED */
-Status
-XcmsRGBiToRGB(
- XcmsCCC ccc,
- XcmsColor *pXcmsColors_in_out,/* pointer to XcmsColors to convert */
- unsigned int nColors, /* Number of colors */
- Bool *pCompressed) /* pointer to a bit array */
-/*
- * DESCRIPTION
- * Converts color specifications in an array of XcmsColor
- * structures from RGBi format to RGB format.
- *
- * RETURNS
- * XcmsFailure if failed,
- * XcmsSuccess if succeeded without gamut compression.
- * XcmsSuccessWithCompression if succeeded with gamut
- * compression.
- */
-{
- LINEAR_RGB_SCCData *pScreenData;
- XcmsRGB tmpRGB;
- IntensityRec keyIRec, answerIRec;
-
- /*
- * pCompressed ignored in this function.
- */
-
- if (ccc == NULL) {
- return(XcmsFailure);
- }
-
- pScreenData = (LINEAR_RGB_SCCData *)ccc->pPerScrnInfo->screenData;
-
- while (nColors--) {
-
- /* Make sure format is XcmsRGBiFormat */
- if (pXcmsColors_in_out->format != XcmsRGBiFormat) {
- return(XcmsFailure);
- }
-
- keyIRec.intensity = pXcmsColors_in_out->spec.RGBi.red;
- if (!_XcmsTableSearch((char *)&keyIRec, ccc->visual->bits_per_rgb,
- (char *)pScreenData->pRedTbl->pBase,
- (unsigned)pScreenData->pRedTbl->nEntries,
- (unsigned)sizeof(IntensityRec),
- (comparProcp)_XcmsIntensityCmp, (interpolProcp)_XcmsIntensityInterpolation, (char *)&answerIRec)) {
- return(XcmsFailure);
- }
- tmpRGB.red = answerIRec.value;
-
- keyIRec.intensity = pXcmsColors_in_out->spec.RGBi.green;
- if (!_XcmsTableSearch((char *)&keyIRec, ccc->visual->bits_per_rgb,
- (char *)pScreenData->pGreenTbl->pBase,
- (unsigned)pScreenData->pGreenTbl->nEntries,
- (unsigned)sizeof(IntensityRec),
- (comparProcp)_XcmsIntensityCmp, (interpolProcp)_XcmsIntensityInterpolation, (char *)&answerIRec)) {
- return(XcmsFailure);
- }
- tmpRGB.green = answerIRec.value;
-
- keyIRec.intensity = pXcmsColors_in_out->spec.RGBi.blue;
- if (!_XcmsTableSearch((char *)&keyIRec, ccc->visual->bits_per_rgb,
- (char *)pScreenData->pBlueTbl->pBase,
- (unsigned)pScreenData->pBlueTbl->nEntries,
- (unsigned)sizeof(IntensityRec),
- (comparProcp)_XcmsIntensityCmp, (interpolProcp)_XcmsIntensityInterpolation, (char *)&answerIRec)) {
- return(XcmsFailure);
- }
- tmpRGB.blue = answerIRec.value;
-
- memcpy((char *)&pXcmsColors_in_out->spec, (char *)&tmpRGB, sizeof(XcmsRGB));
- (pXcmsColors_in_out++)->format = XcmsRGBFormat;
- }
- return(XcmsSuccess);
-}
-
-
-/*
- * NAME
- * XcmsRGBToRGBi
- *
- * SYNOPSIS
- */
-/* ARGSUSED */
-Status
-XcmsRGBToRGBi(
- XcmsCCC ccc,
- XcmsColor *pXcmsColors_in_out,/* pointer to XcmsColors to convert */
- unsigned int nColors, /* Number of colors */
- Bool *pCompressed) /* pointer to a bit array */
-/*
- * DESCRIPTION
- * Converts color specifications in an array of XcmsColor
- * structures from RGB format to RGBi format.
- *
- * RETURNS
- * XcmsFailure if failed,
- * XcmsSuccess if succeeded.
- */
-{
- LINEAR_RGB_SCCData *pScreenData;
- XcmsRGBi tmpRGBi;
- IntensityRec keyIRec, answerIRec;
-
- /*
- * pCompressed ignored in this function.
- */
-
- if (ccc == NULL) {
- return(XcmsFailure);
- }
-
- pScreenData = (LINEAR_RGB_SCCData *)ccc->pPerScrnInfo->screenData;
-
- while (nColors--) {
-
- /* Make sure format is XcmsRGBFormat */
- if (pXcmsColors_in_out->format != XcmsRGBFormat) {
- return(XcmsFailure);
- }
-
- keyIRec.value = pXcmsColors_in_out->spec.RGB.red;
- if (!_XcmsTableSearch((char *)&keyIRec, ccc->visual->bits_per_rgb,
- (char *)pScreenData->pRedTbl->pBase,
- (unsigned)pScreenData->pRedTbl->nEntries,
- (unsigned)sizeof(IntensityRec),
- (comparProcp)_XcmsValueCmp, (interpolProcp)_XcmsValueInterpolation, (char *)&answerIRec)) {
- return(XcmsFailure);
- }
- tmpRGBi.red = answerIRec.intensity;
-
- keyIRec.value = pXcmsColors_in_out->spec.RGB.green;
- if (!_XcmsTableSearch((char *)&keyIRec, ccc->visual->bits_per_rgb,
- (char *)pScreenData->pGreenTbl->pBase,
- (unsigned)pScreenData->pGreenTbl->nEntries,
- (unsigned)sizeof(IntensityRec),
- (comparProcp)_XcmsValueCmp, (interpolProcp)_XcmsValueInterpolation, (char *)&answerIRec)) {
- return(XcmsFailure);
- }
- tmpRGBi.green = answerIRec.intensity;
-
- keyIRec.value = pXcmsColors_in_out->spec.RGB.blue;
- if (!_XcmsTableSearch((char *)&keyIRec, ccc->visual->bits_per_rgb,
- (char *)pScreenData->pBlueTbl->pBase,
- (unsigned)pScreenData->pBlueTbl->nEntries,
- (unsigned)sizeof(IntensityRec),
- (comparProcp)_XcmsValueCmp, (interpolProcp)_XcmsValueInterpolation, (char *)&answerIRec)) {
- return(XcmsFailure);
- }
- tmpRGBi.blue = answerIRec.intensity;
-
- memcpy((char *)&pXcmsColors_in_out->spec, (char *)&tmpRGBi, sizeof(XcmsRGBi));
- (pXcmsColors_in_out++)->format = XcmsRGBiFormat;
- }
- return(XcmsSuccess);
-}
-
-/*
- * NAME
- * _XcmsInitScrnDefaultInfo
- *
- * SYNOPSIS
- */
-/* ARGSUSED */
-int
-_XcmsLRGB_InitScrnDefault(
- Display *dpy,
- int screenNumber,
- XcmsPerScrnInfo *pPerScrnInfo)
-/*
- * DESCRIPTION
- * Given a display and screen number, this routine attempts
- * to initialize the Xcms per Screen Info structure
- * (XcmsPerScrnInfo) with defaults.
- *
- * RETURNS
- * Returns zero if initialization failed; non-zero otherwise.
- */
-{
- pPerScrnInfo->screenData = (XPointer)&Default_RGB_SCCData;
- pPerScrnInfo->screenWhitePt.spec.CIEXYZ.X =
- Default_RGB_SCCData.RGBtoXYZmatrix[0][0] +
- Default_RGB_SCCData.RGBtoXYZmatrix[0][1] +
- Default_RGB_SCCData.RGBtoXYZmatrix[0][2];
- pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y =
- Default_RGB_SCCData.RGBtoXYZmatrix[1][0] +
- Default_RGB_SCCData.RGBtoXYZmatrix[1][1] +
- Default_RGB_SCCData.RGBtoXYZmatrix[1][2];
- pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Z =
- Default_RGB_SCCData.RGBtoXYZmatrix[2][0] +
- Default_RGB_SCCData.RGBtoXYZmatrix[2][1] +
- Default_RGB_SCCData.RGBtoXYZmatrix[2][2];
- if ((pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y < (1.0 - EPS) )
- || (pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y > (1.0 + EPS))) {
- pPerScrnInfo->screenData = (XPointer)NULL;
- pPerScrnInfo->state = XcmsInitNone;
- return(0);
- }
- pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y = 1.0;
- pPerScrnInfo->screenWhitePt.format = XcmsCIEXYZFormat;
- pPerScrnInfo->screenWhitePt.pixel = 0;
- pPerScrnInfo->functionSet = (XPointer)&XcmsLinearRGBFunctionSet;
- pPerScrnInfo->state = XcmsInitFailure; /* default initialization */
- return(1);
-}
+ +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX 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 TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * NAME + * XcmsLRGB.c + * + * DESCRIPTION + * This file contains the conversion routines: + * 1. CIE XYZ to RGB intensity + * 2. RGB intensity to device RGB + * 3. device RGB to RGB intensity + * 4. RGB intensity to CIE XYZ + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include <X11/Xos.h> +#include <X11/Xatom.h> +#include "Xlibint.h" +#include "Xcmsint.h" +#include "Cv.h" + +/* + * LOCAL DEFINES + * #define declarations local to this package. + */ +#define EPS 0.001 +#ifndef MIN +#define MIN(x,y) ((x) > (y) ? (y) : (x)) +#endif /* MIN */ +#ifndef MAX +#define MAX(x,y) ((x) > (y) ? (x) : (y)) +#endif /* MAX */ +#ifndef MIN3 +#define MIN3(x,y,z) ((x) > (MIN((y), (z))) ? (MIN((y), (z))) : (x)) +#endif /* MIN3 */ +#ifndef MAX3 +#define MAX3(x,y,z) ((x) > (MAX((y), (z))) ? (x) : (MAX((y), (z)))) +#endif /* MAX3 */ + +/* + * LOCAL TYPEDEFS + * typedefs local to this package (for use with local vars). + * + */ + +/* + * FORWARD DECLARATIONS + */ +static void LINEAR_RGB_FreeSCCData(XPointer pScreenDataTemp); +static int LINEAR_RGB_InitSCCData(Display *dpy, + int screenNumber, XcmsPerScrnInfo *pPerScrnInfo); +static int XcmsLRGB_RGB_ParseString(register char *spec, XcmsColor *pColor); +static int XcmsLRGB_RGBi_ParseString(register char *spec, XcmsColor *pColor); +static Status +_XcmsGetTableType0( + IntensityTbl *pTbl, + int format, + char **pChar, + unsigned long *pCount); +static Status +_XcmsGetTableType1( + IntensityTbl *pTbl, + int format, + char **pChar, + unsigned long *pCount); + +/* + * LOCALS VARIABLES + * Variables local to this package. + * Usage example: + * static int ExampleLocalVar; + */ + +static unsigned short const MASK[17] = { + 0x0000, /* 0 bitsPerRGB */ + 0x8000, /* 1 bitsPerRGB */ + 0xc000, /* 2 bitsPerRGB */ + 0xe000, /* 3 bitsPerRGB */ + 0xf000, /* 4 bitsPerRGB */ + 0xf800, /* 5 bitsPerRGB */ + 0xfc00, /* 6 bitsPerRGB */ + 0xfe00, /* 7 bitsPerRGB */ + 0xff00, /* 8 bitsPerRGB */ + 0xff80, /* 9 bitsPerRGB */ + 0xffc0, /* 10 bitsPerRGB */ + 0xffe0, /* 11 bitsPerRGB */ + 0xfff0, /* 12 bitsPerRGB */ + 0xfff8, /* 13 bitsPerRGB */ + 0xfffc, /* 14 bitsPerRGB */ + 0xfffe, /* 15 bitsPerRGB */ + 0xffff /* 16 bitsPerRGB */ +}; + + + /* + * A NULL terminated array of function pointers that when applied + * in series will convert an XcmsColor structure from XcmsRGBFormat + * to XcmsCIEXYZFormat. + */ +static XcmsConversionProc Fl_RGB_to_CIEXYZ[] = { + (XcmsConversionProc)XcmsRGBToRGBi, + (XcmsConversionProc)XcmsRGBiToCIEXYZ, + NULL +}; + + /* + * A NULL terminated array of function pointers that when applied + * in series will convert an XcmsColor structure from XcmsCIEXYZFormat + * to XcmsRGBFormat. + */ +static XcmsConversionProc Fl_CIEXYZ_to_RGB[] = { + (XcmsConversionProc)XcmsCIEXYZToRGBi, + (XcmsConversionProc)XcmsRGBiToRGB, + NULL +}; + + /* + * A NULL terminated array of function pointers that when applied + * in series will convert an XcmsColor structure from XcmsRGBiFormat + * to XcmsCIEXYZFormat. + */ +static XcmsConversionProc Fl_RGBi_to_CIEXYZ[] = { + (XcmsConversionProc)XcmsRGBiToCIEXYZ, + NULL +}; + + /* + * A NULL terminated array of function pointers that when applied + * in series will convert an XcmsColor structure from XcmsCIEXYZFormat + * to XcmsRGBiFormat. + */ +static XcmsConversionProc Fl_CIEXYZ_to_RGBi[] = { + (XcmsConversionProc)XcmsCIEXYZToRGBi, + NULL +}; + + /* + * RGBi Color Spaces + */ +XcmsColorSpace XcmsRGBiColorSpace = + { + _XcmsRGBi_prefix, /* prefix */ + XcmsRGBiFormat, /* id */ + XcmsLRGB_RGBi_ParseString, /* parseString */ + Fl_RGBi_to_CIEXYZ, /* to_CIEXYZ */ + Fl_CIEXYZ_to_RGBi, /* from_CIEXYZ */ + 1 + }; + + /* + * RGB Color Spaces + */ +XcmsColorSpace XcmsRGBColorSpace = + { + _XcmsRGB_prefix, /* prefix */ + XcmsRGBFormat, /* id */ + XcmsLRGB_RGB_ParseString, /* parseString */ + Fl_RGB_to_CIEXYZ, /* to_CIEXYZ */ + Fl_CIEXYZ_to_RGB, /* from_CIEXYZ */ + 1 + }; + + /* + * Device-Independent Color Spaces known to the + * LINEAR_RGB Screen Color Characteristics Function Set. + */ +static XcmsColorSpace *DDColorSpaces[] = { + &XcmsRGBColorSpace, + &XcmsRGBiColorSpace, + NULL +}; + + +/* + * GLOBALS + * Variables declared in this package that are allowed + * to be used globally. + */ + + /* + * LINEAR_RGB Screen Color Characteristics Function Set. + */ +XcmsFunctionSet XcmsLinearRGBFunctionSet = + { + &DDColorSpaces[0], /* pDDColorSpaces */ + LINEAR_RGB_InitSCCData, /* pInitScrnFunc */ + LINEAR_RGB_FreeSCCData /* pFreeSCCData */ + }; + +/* + * DESCRIPTION + * Contents of Default SCCData should be replaced if other + * data should be used as default. + * + * + */ + +/* + * NAME Tektronix 19" (Sony) CRT + * PART_NUMBER 119-2451-00 + * MODEL Tek4300, Tek4800 + */ + +static IntensityRec const Default_RGB_RedTuples[] = { + /* {unsigned short value, XcmsFloat intensity} */ + { 0x0000, 0.000000 }, + { 0x0909, 0.000000 }, + { 0x0a0a, 0.000936 }, + { 0x0f0f, 0.001481 }, + { 0x1414, 0.002329 }, + { 0x1919, 0.003529 }, + { 0x1e1e, 0.005127 }, + { 0x2323, 0.007169 }, + { 0x2828, 0.009699 }, + { 0x2d2d, 0.012759 }, + { 0x3232, 0.016392 }, + { 0x3737, 0.020637 }, + { 0x3c3c, 0.025533 }, + { 0x4141, 0.031119 }, + { 0x4646, 0.037431 }, + { 0x4b4b, 0.044504 }, + { 0x5050, 0.052373 }, + { 0x5555, 0.061069 }, + { 0x5a5a, 0.070624 }, + { 0x5f5f, 0.081070 }, + { 0x6464, 0.092433 }, + { 0x6969, 0.104744 }, + { 0x6e6e, 0.118026 }, + { 0x7373, 0.132307 }, + { 0x7878, 0.147610 }, + { 0x7d7d, 0.163958 }, + { 0x8282, 0.181371 }, + { 0x8787, 0.199871 }, + { 0x8c8c, 0.219475 }, + { 0x9191, 0.240202 }, + { 0x9696, 0.262069 }, + { 0x9b9b, 0.285089 }, + { 0xa0a0, 0.309278 }, + { 0xa5a5, 0.334647 }, + { 0xaaaa, 0.361208 }, + { 0xafaf, 0.388971 }, + { 0xb4b4, 0.417945 }, + { 0xb9b9, 0.448138 }, + { 0xbebe, 0.479555 }, + { 0xc3c3, 0.512202 }, + { 0xc8c8, 0.546082 }, + { 0xcdcd, 0.581199 }, + { 0xd2d2, 0.617552 }, + { 0xd7d7, 0.655144 }, + { 0xdcdc, 0.693971 }, + { 0xe1e1, 0.734031 }, + { 0xe6e6, 0.775322 }, + { 0xebeb, 0.817837 }, + { 0xf0f0, 0.861571 }, + { 0xf5f5, 0.906515 }, + { 0xfafa, 0.952662 }, + { 0xffff, 1.000000 } +}; + +static IntensityRec const Default_RGB_GreenTuples[] = { + /* {unsigned short value, XcmsFloat intensity} */ + { 0x0000, 0.000000 }, + { 0x1313, 0.000000 }, + { 0x1414, 0.000832 }, + { 0x1919, 0.001998 }, + { 0x1e1e, 0.003612 }, + { 0x2323, 0.005736 }, + { 0x2828, 0.008428 }, + { 0x2d2d, 0.011745 }, + { 0x3232, 0.015740 }, + { 0x3737, 0.020463 }, + { 0x3c3c, 0.025960 }, + { 0x4141, 0.032275 }, + { 0x4646, 0.039449 }, + { 0x4b4b, 0.047519 }, + { 0x5050, 0.056520 }, + { 0x5555, 0.066484 }, + { 0x5a5a, 0.077439 }, + { 0x5f5f, 0.089409 }, + { 0x6464, 0.102418 }, + { 0x6969, 0.116485 }, + { 0x6e6e, 0.131625 }, + { 0x7373, 0.147853 }, + { 0x7878, 0.165176 }, + { 0x7d7d, 0.183604 }, + { 0x8282, 0.203140 }, + { 0x8787, 0.223783 }, + { 0x8c8c, 0.245533 }, + { 0x9191, 0.268384 }, + { 0x9696, 0.292327 }, + { 0x9b9b, 0.317351 }, + { 0xa0a0, 0.343441 }, + { 0xa5a5, 0.370580 }, + { 0xaaaa, 0.398747 }, + { 0xafaf, 0.427919 }, + { 0xb4b4, 0.458068 }, + { 0xb9b9, 0.489165 }, + { 0xbebe, 0.521176 }, + { 0xc3c3, 0.554067 }, + { 0xc8c8, 0.587797 }, + { 0xcdcd, 0.622324 }, + { 0xd2d2, 0.657604 }, + { 0xd7d7, 0.693588 }, + { 0xdcdc, 0.730225 }, + { 0xe1e1, 0.767459 }, + { 0xe6e6, 0.805235 }, + { 0xebeb, 0.843491 }, + { 0xf0f0, 0.882164 }, + { 0xf5f5, 0.921187 }, + { 0xfafa, 0.960490 }, + { 0xffff, 1.000000 } +}; + +static IntensityRec const Default_RGB_BlueTuples[] = { + /* {unsigned short value, XcmsFloat intensity} */ + { 0x0000, 0.000000 }, + { 0x0e0e, 0.000000 }, + { 0x0f0f, 0.001341 }, + { 0x1414, 0.002080 }, + { 0x1919, 0.003188 }, + { 0x1e1e, 0.004729 }, + { 0x2323, 0.006766 }, + { 0x2828, 0.009357 }, + { 0x2d2d, 0.012559 }, + { 0x3232, 0.016424 }, + { 0x3737, 0.021004 }, + { 0x3c3c, 0.026344 }, + { 0x4141, 0.032489 }, + { 0x4646, 0.039481 }, + { 0x4b4b, 0.047357 }, + { 0x5050, 0.056154 }, + { 0x5555, 0.065903 }, + { 0x5a5a, 0.076634 }, + { 0x5f5f, 0.088373 }, + { 0x6464, 0.101145 }, + { 0x6969, 0.114968 }, + { 0x6e6e, 0.129862 }, + { 0x7373, 0.145841 }, + { 0x7878, 0.162915 }, + { 0x7d7d, 0.181095 }, + { 0x8282, 0.200386 }, + { 0x8787, 0.220791 }, + { 0x8c8c, 0.242309 }, + { 0x9191, 0.264937 }, + { 0x9696, 0.288670 }, + { 0x9b9b, 0.313499 }, + { 0xa0a0, 0.339410 }, + { 0xa5a5, 0.366390 }, + { 0xaaaa, 0.394421 }, + { 0xafaf, 0.423481 }, + { 0xb4b4, 0.453547 }, + { 0xb9b9, 0.484592 }, + { 0xbebe, 0.516587 }, + { 0xc3c3, 0.549498 }, + { 0xc8c8, 0.583291 }, + { 0xcdcd, 0.617925 }, + { 0xd2d2, 0.653361 }, + { 0xd7d7, 0.689553 }, + { 0xdcdc, 0.726454 }, + { 0xe1e1, 0.764013 }, + { 0xe6e6, 0.802178 }, + { 0xebeb, 0.840891 }, + { 0xf0f0, 0.880093 }, + { 0xf5f5, 0.919723 }, + { 0xfafa, 0.959715 }, + { 0xffff, 1.00000 } +}; + +static IntensityTbl Default_RGB_RedTbl = { + /* IntensityRec *pBase */ + (IntensityRec *) Default_RGB_RedTuples, + /* unsigned int nEntries */ + 52 +}; + +static IntensityTbl Default_RGB_GreenTbl = { + /* IntensityRec *pBase */ + (IntensityRec *)Default_RGB_GreenTuples, + /* unsigned int nEntries */ + 50 +}; + +static IntensityTbl Default_RGB_BlueTbl = { + /* IntensityRec *pBase */ + (IntensityRec *)Default_RGB_BlueTuples, + /* unsigned int nEntries */ + 51 +}; + +static LINEAR_RGB_SCCData Default_RGB_SCCData = { + /* XcmsFloat XYZtoRGBmatrix[3][3] */ + { + { 3.48340481253539000, -1.52176374927285200, -0.55923133354049780 }, + {-1.07152751306193600, 1.96593795204372400, 0.03673691339553462 }, + { 0.06351179790497788, -0.20020501000496480, 0.81070942031648220 } + }, + + /* XcmsFloat RGBtoXYZmatrix[3][3] */ + { + { 0.38106149108714790, 0.32025712365352110, 0.24834578525933100 }, + { 0.20729745115140850, 0.68054638776373240, 0.11215616108485920 }, + { 0.02133944350088028, 0.14297193020246480, 1.24172892629665500 } + }, + + /* IntensityTbl *pRedTbl */ + &Default_RGB_RedTbl, + + /* IntensityTbl *pGreenTbl */ + &Default_RGB_GreenTbl, + + /* IntensityTbl *pBlueTbl */ + &Default_RGB_BlueTbl +}; + +/************************************************************************ + * * + * PRIVATE ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * LINEAR_RGB_InitSCCData() + * + * SYNOPSIS + */ +static Status +LINEAR_RGB_InitSCCData( + Display *dpy, + int screenNumber, + XcmsPerScrnInfo *pPerScrnInfo) +/* + * DESCRIPTION + * + * RETURNS + * XcmsFailure if failed. + * XcmsSuccess if succeeded. + * + */ +{ + Atom CorrectAtom = XInternAtom (dpy, XDCCC_CORRECT_ATOM_NAME, True); + Atom MatrixAtom = XInternAtom (dpy, XDCCC_MATRIX_ATOM_NAME, True); + int format_return, count, cType, nTables; + unsigned long nitems, nbytes_return; + char *property_return, *pChar; + XcmsFloat *pValue; +#ifdef ALLDEBUG + IntensityRec *pIRec; +#endif /* ALLDEBUG */ + VisualID visualID; + + LINEAR_RGB_SCCData *pScreenData, *pScreenDefaultData; + XcmsIntensityMap *pNewMap; + + /* + * Allocate memory for pScreenData + */ + if (!(pScreenData = pScreenDefaultData = (LINEAR_RGB_SCCData *) + Xcalloc (1, sizeof(LINEAR_RGB_SCCData)))) { + return(XcmsFailure); + } + + /* + * 1. Get the XYZ->RGB and RGB->XYZ matrices + */ + + if (MatrixAtom == None || + !_XcmsGetProperty (dpy, RootWindow(dpy, screenNumber), MatrixAtom, + &format_return, &nitems, &nbytes_return, &property_return) || + nitems != 18 || format_return != 32) { + /* + * As per the XDCCC, there must be 18 data items and each must be + * in 32 bits ! + */ + goto FreeSCCData; + + } else { + + /* + * RGBtoXYZ and XYZtoRGB matrices + */ + pValue = (XcmsFloat *) pScreenData; + pChar = property_return; + for (count = 0; count < 18; count++) { + *pValue++ = (long)_XcmsGetElement(format_return, &pChar, + &nitems) / (XcmsFloat)XDCCC_NUMBER; + } + Xfree ((char *)property_return); + pPerScrnInfo->screenWhitePt.spec.CIEXYZ.X = + pScreenData->RGBtoXYZmatrix[0][0] + + pScreenData->RGBtoXYZmatrix[0][1] + + pScreenData->RGBtoXYZmatrix[0][2]; + pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y = + pScreenData->RGBtoXYZmatrix[1][0] + + pScreenData->RGBtoXYZmatrix[1][1] + + pScreenData->RGBtoXYZmatrix[1][2]; + pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Z = + pScreenData->RGBtoXYZmatrix[2][0] + + pScreenData->RGBtoXYZmatrix[2][1] + + pScreenData->RGBtoXYZmatrix[2][2]; + + /* + * Compute the Screen White Point + */ + if ((pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y < (1.0 - EPS) ) + || (pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y > (1.0 + EPS))) { + goto FreeSCCData; + } else { + pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y = 1.0; + } + pPerScrnInfo->screenWhitePt.format = XcmsCIEXYZFormat; + pPerScrnInfo->screenWhitePt.pixel = 0; + +#ifdef PDEBUG + printf ("RGB to XYZ Matrix values:\n"); + printf (" %f %f %f\n %f %f %f\n %f %f %f\n", + pScreenData->RGBtoXYZmatrix[0][0], + pScreenData->RGBtoXYZmatrix[0][1], + pScreenData->RGBtoXYZmatrix[0][2], + pScreenData->RGBtoXYZmatrix[1][0], + pScreenData->RGBtoXYZmatrix[1][1], + pScreenData->RGBtoXYZmatrix[1][2], + pScreenData->RGBtoXYZmatrix[2][0], + pScreenData->RGBtoXYZmatrix[2][1], + pScreenData->RGBtoXYZmatrix[2][2]); + printf ("XYZ to RGB Matrix values:\n"); + printf (" %f %f %f\n %f %f %f\n %f %f %f\n", + pScreenData->XYZtoRGBmatrix[0][0], + pScreenData->XYZtoRGBmatrix[0][1], + pScreenData->XYZtoRGBmatrix[0][2], + pScreenData->XYZtoRGBmatrix[1][0], + pScreenData->XYZtoRGBmatrix[1][1], + pScreenData->XYZtoRGBmatrix[1][2], + pScreenData->XYZtoRGBmatrix[2][0], + pScreenData->XYZtoRGBmatrix[2][1], + pScreenData->XYZtoRGBmatrix[2][2]); + printf ("Screen White Pt value: %f %f %f\n", + pPerScrnInfo->screenWhitePt.spec.CIEXYZ.X, + pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y, + pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Z); +#endif /* PDEBUG */ + } + + /* + * 2. Get the Intensity Profile + */ + if (CorrectAtom == None || + !_XcmsGetProperty (dpy, RootWindow(dpy, screenNumber), CorrectAtom, + &format_return, &nitems, &nbytes_return, &property_return)) { + goto FreeSCCData; + } + + pChar = property_return; + + while (nitems) { + switch (format_return) { + case 8: + /* + * Must have at least: + * VisualID0 + * VisualID1 + * VisualID2 + * VisualID3 + * type + * count + * length + * intensity1 + * intensity2 + */ + if (nitems < 9) { + goto Free_property_return; + } + count = 3; + break; + case 16: + /* + * Must have at least: + * VisualID0 + * VisualID3 + * type + * count + * length + * intensity1 + * intensity2 + */ + if (nitems < 7) { + goto Free_property_return; + } + count = 1; + break; + case 32: + /* + * Must have at least: + * VisualID0 + * type + * count + * length + * intensity1 + * intensity2 + */ + if (nitems < 6) { + goto Free_property_return; + } + count = 0; + break; + default: + goto Free_property_return; + } + + /* + * Get VisualID + */ + visualID = _XcmsGetElement(format_return, &pChar, &nitems); + while (count--) { + visualID = visualID << format_return; + visualID |= _XcmsGetElement(format_return, &pChar, &nitems); + } + + if (visualID == 0) { + /* + * This is a shared intensity table + */ + pScreenData = pScreenDefaultData; + } else { + /* + * This is a per-Visual intensity table + */ + if (!(pScreenData = (LINEAR_RGB_SCCData *) + Xcalloc (1, sizeof(LINEAR_RGB_SCCData)))) { + goto Free_property_return; + } + /* copy matrices */ + memcpy((char *)pScreenData, (char *)pScreenDefaultData, + 18 * sizeof(XcmsFloat)); + + /* Create, initialize, and add map */ + if (!(pNewMap = (XcmsIntensityMap *) + Xcalloc (1, sizeof(XcmsIntensityMap)))) { + Xfree((char *)pScreenData); + goto Free_property_return; + } + pNewMap->visualID = visualID; + pNewMap->screenData = (XPointer)pScreenData; + pNewMap->pFreeScreenData = LINEAR_RGB_FreeSCCData; + pNewMap->pNext = + (XcmsIntensityMap *)dpy->cms.perVisualIntensityMaps; + dpy->cms.perVisualIntensityMaps = (XPointer)pNewMap; + dpy->free_funcs->intensityMaps = _XcmsFreeIntensityMaps; + } + + cType = _XcmsGetElement(format_return, &pChar, &nitems); + nTables = _XcmsGetElement(format_return, &pChar, &nitems); + + if (cType == 0) { + + /* Red Intensity Table */ + if (!(pScreenData->pRedTbl = (IntensityTbl *) + Xcalloc (1, sizeof(IntensityTbl)))) { + goto Free_property_return; + } + if (_XcmsGetTableType0(pScreenData->pRedTbl, format_return, &pChar, + &nitems) == XcmsFailure) { + goto FreeRedTbl; + } + + if (nTables == 1) { + /* Green Intensity Table */ + pScreenData->pGreenTbl = pScreenData->pRedTbl; + /* Blue Intensity Table */ + pScreenData->pBlueTbl = pScreenData->pRedTbl; + } else { + /* Green Intensity Table */ + if (!(pScreenData->pGreenTbl = (IntensityTbl *) + Xcalloc (1, sizeof(IntensityTbl)))) { + goto FreeRedTblElements; + } + if (_XcmsGetTableType0(pScreenData->pGreenTbl, format_return, &pChar, + &nitems) == XcmsFailure) { + goto FreeGreenTbl; + } + + /* Blue Intensity Table */ + if (!(pScreenData->pBlueTbl = (IntensityTbl *) + Xcalloc (1, sizeof(IntensityTbl)))) { + goto FreeGreenTblElements; + } + if (_XcmsGetTableType0(pScreenData->pBlueTbl, format_return, &pChar, + &nitems) == XcmsFailure) { + goto FreeBlueTbl; + } + } + } else if (cType == 1) { + /* Red Intensity Table */ + if (!(pScreenData->pRedTbl = (IntensityTbl *) + Xcalloc (1, sizeof(IntensityTbl)))) { + goto Free_property_return; + } + if (_XcmsGetTableType1(pScreenData->pRedTbl, format_return, &pChar, + &nitems) == XcmsFailure) { + goto FreeRedTbl; + } + + if (nTables == 1) { + + /* Green Intensity Table */ + pScreenData->pGreenTbl = pScreenData->pRedTbl; + /* Blue Intensity Table */ + pScreenData->pBlueTbl = pScreenData->pRedTbl; + + } else { + + /* Green Intensity Table */ + if (!(pScreenData->pGreenTbl = (IntensityTbl *) + Xcalloc (1, sizeof(IntensityTbl)))) { + goto FreeRedTblElements; + } + if (_XcmsGetTableType1(pScreenData->pGreenTbl, format_return, &pChar, + &nitems) == XcmsFailure) { + goto FreeGreenTbl; + } + + /* Blue Intensity Table */ + if (!(pScreenData->pBlueTbl = (IntensityTbl *) + Xcalloc (1, sizeof(IntensityTbl)))) { + goto FreeGreenTblElements; + } + if (_XcmsGetTableType1(pScreenData->pBlueTbl, format_return, &pChar, + &nitems) == XcmsFailure) { + goto FreeBlueTbl; + } + } + } else { + goto Free_property_return; + } + +#ifdef ALLDEBUG + printf ("Intensity Table RED %d\n", pScreenData->pRedTbl->nEntries); + pIRec = (IntensityRec *) pScreenData->pRedTbl->pBase; + for (count = 0; count < pScreenData->pRedTbl->nEntries; count++, pIRec++) { + printf ("\t0x%4x\t%f\n", pIRec->value, pIRec->intensity); + } + if (pScreenData->pGreenTbl->pBase != pScreenData->pRedTbl->pBase) { + printf ("Intensity Table GREEN %d\n", pScreenData->pGreenTbl->nEntries); + pIRec = (IntensityRec *)pScreenData->pGreenTbl->pBase; + for (count = 0; count < pScreenData->pGreenTbl->nEntries; count++, pIRec++) { + printf ("\t0x%4x\t%f\n", pIRec->value, pIRec->intensity); + } + } + if (pScreenData->pBlueTbl->pBase != pScreenData->pRedTbl->pBase) { + printf ("Intensity Table BLUE %d\n", pScreenData->pBlueTbl->nEntries); + pIRec = (IntensityRec *) pScreenData->pBlueTbl->pBase; + for (count = 0; count < pScreenData->pBlueTbl->nEntries; count++, pIRec++) { + printf ("\t0x%4x\t%f\n", pIRec->value, pIRec->intensity); + } + } +#endif /* ALLDEBUG */ + } + + Xfree ((char *)property_return); + + /* Free the old memory and use the new structure created. */ + LINEAR_RGB_FreeSCCData(pPerScrnInfo->screenData); + + pPerScrnInfo->functionSet = (XPointer) &XcmsLinearRGBFunctionSet; + + pPerScrnInfo->screenData = (XPointer) pScreenData; + + pPerScrnInfo->state = XcmsInitSuccess; + + return(XcmsSuccess); + +FreeBlueTblElements: + Xfree((char *)pScreenData->pBlueTbl->pBase); + +FreeBlueTbl: + Xfree((char *)pScreenData->pBlueTbl); + +FreeGreenTblElements: + Xfree((char *)pScreenData->pGreenTbl->pBase); + +FreeGreenTbl: + Xfree((char *)pScreenData->pGreenTbl); + +FreeRedTblElements: + Xfree((char *)pScreenData->pRedTbl->pBase); + +FreeRedTbl: + Xfree((char *)pScreenData->pRedTbl); + +Free_property_return: + Xfree ((char *)property_return); + +FreeSCCData: + Xfree((char *)pScreenDefaultData); + pPerScrnInfo->state = XcmsInitNone; + return(XcmsFailure); +} + + +/* + * NAME + * LINEAR_RGB_FreeSCCData() + * + * SYNOPSIS + */ +static void +LINEAR_RGB_FreeSCCData( + XPointer pScreenDataTemp) +/* + * DESCRIPTION + * + * RETURNS + * 0 if failed. + * 1 if succeeded with no modifications. + * + */ +{ + LINEAR_RGB_SCCData *pScreenData = (LINEAR_RGB_SCCData *) pScreenDataTemp; + + if (pScreenData && pScreenData != &Default_RGB_SCCData) { + if (pScreenData->pRedTbl) { + if (pScreenData->pGreenTbl) { + if (pScreenData->pRedTbl->pBase != + pScreenData->pGreenTbl->pBase) { + if (pScreenData->pGreenTbl->pBase) { + Xfree ((char *)pScreenData->pGreenTbl->pBase); + } + } + if (pScreenData->pGreenTbl != pScreenData->pRedTbl) { + Xfree ((char *)pScreenData->pGreenTbl); + } + } + if (pScreenData->pBlueTbl) { + if (pScreenData->pRedTbl->pBase != + pScreenData->pBlueTbl->pBase) { + if (pScreenData->pBlueTbl->pBase) { + Xfree ((char *)pScreenData->pBlueTbl->pBase); + } + } + if (pScreenData->pBlueTbl != pScreenData->pRedTbl) { + Xfree ((char *)pScreenData->pBlueTbl); + } + } + if (pScreenData->pRedTbl->pBase) { + Xfree ((char *)pScreenData->pRedTbl->pBase); + } + Xfree ((char *)pScreenData->pRedTbl); + } + Xfree ((char *)pScreenData); + } +} + + + +/************************************************************************ + * * + * API PRIVATE ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * _XcmsGetTableType0 + * + * SYNOPSIS + */ +static Status +_XcmsGetTableType0( + IntensityTbl *pTbl, + int format, + char **pChar, + unsigned long *pCount) +/* + * DESCRIPTION + * + * RETURNS + * XcmsFailure if failed. + * XcmsSuccess if succeeded. + * + */ +{ + unsigned int nElements; + IntensityRec *pIRec; + + nElements = pTbl->nEntries = + _XcmsGetElement(format, pChar, pCount) + 1; + if (!(pIRec = pTbl->pBase = (IntensityRec *) + Xcalloc (nElements, sizeof(IntensityRec)))) { + return(XcmsFailure); + } + + switch (format) { + case 8: + for (; nElements--; pIRec++) { + /* 0xFFFF/0xFF = 0x101 */ + pIRec->value = _XcmsGetElement (format, pChar, pCount) * 0x101; + pIRec->intensity = + _XcmsGetElement (format, pChar, pCount) / (XcmsFloat)255.0; + } + break; + case 16: + for (; nElements--; pIRec++) { + pIRec->value = _XcmsGetElement (format, pChar, pCount); + pIRec->intensity = _XcmsGetElement (format, pChar, pCount) + / (XcmsFloat)65535.0; + } + break; + case 32: + for (; nElements--; pIRec++) { + pIRec->value = _XcmsGetElement (format, pChar, pCount); + pIRec->intensity = _XcmsGetElement (format, pChar, pCount) + / (XcmsFloat)4294967295.0; + } + break; + default: + return(XcmsFailure); + } + return(XcmsSuccess); +} + + +/* + * NAME + * _XcmsGetTableType1 + * + * SYNOPSIS + */ +static Status +_XcmsGetTableType1( + IntensityTbl *pTbl, + int format, + char **pChar, + unsigned long *pCount) +/* + * DESCRIPTION + * + * RETURNS + * XcmsFailure if failed. + * XcmsSuccess if succeeded. + * + */ +{ + int count; + unsigned int max_index; + IntensityRec *pIRec; + + max_index = _XcmsGetElement(format, pChar, pCount); + pTbl->nEntries = max_index + 1; + if (!(pIRec = pTbl->pBase = (IntensityRec *) + Xcalloc (max_index+1, sizeof(IntensityRec)))) { + return(XcmsFailure); + } + + switch (format) { + case 8: + for (count = 0; count < max_index+1; count++, pIRec++) { + pIRec->value = (count * 65535) / max_index; + pIRec->intensity = _XcmsGetElement (format, pChar, pCount) + / (XcmsFloat)255.0; + } + break; + case 16: + for (count = 0; count < max_index+1; count++, pIRec++) { + pIRec->value = (count * 65535) / max_index; + pIRec->intensity = _XcmsGetElement (format, pChar, pCount) + / (XcmsFloat)65535.0; + } + break; + case 32: + for (count = 0; count < max_index+1; count++, pIRec++) { + pIRec->value = (count * 65535) / max_index; + pIRec->intensity = _XcmsGetElement (format, pChar, pCount) + / (XcmsFloat)4294967295.0; + } + break; + default: + return(XcmsFailure); + } + + return(XcmsSuccess); +} + + +/* + * NAME + * ValueCmp + * + * SYNOPSIS + */ +static int +_XcmsValueCmp( + IntensityRec *p1, IntensityRec *p2) +/* + * DESCRIPTION + * Compares the value component of two IntensityRec + * structures. + * + * RETURNS + * 0 if p1->value is equal to p2->value + * < 0 if p1->value is less than p2->value + * > 0 if p1->value is greater than p2->value + * + */ +{ + return (p1->value - p2->value); +} + + +/* + * NAME + * IntensityCmp + * + * SYNOPSIS + */ +static int +_XcmsIntensityCmp( + IntensityRec *p1, IntensityRec *p2) +/* + * DESCRIPTION + * Compares the intensity component of two IntensityRec + * structures. + * + * RETURNS + * 0 if equal; + * < 0 if first precedes second + * > 0 if first succeeds second + * + */ +{ + if (p1->intensity < p2->intensity) { + return (-1); + } + if (p1->intensity > p2->intensity) { + return (XcmsSuccess); + } + return (XcmsFailure); +} + +/* + * NAME + * ValueInterpolation + * + * SYNOPSIS + */ +/* ARGSUSED */ +static int +_XcmsValueInterpolation( + IntensityRec *key, IntensityRec *lo, IntensityRec *hi, IntensityRec *answer, + int bitsPerRGB) +/* + * DESCRIPTION + * Based on a given value, performs a linear interpolation + * on the intensities between two IntensityRec structures. + * Note that the bitsPerRGB parameter is ignored. + * + * RETURNS + * Returns 0 if failed; otherwise non-zero. + */ +{ + XcmsFloat ratio; + + ratio = ((XcmsFloat)key->value - (XcmsFloat)lo->value) / + ((XcmsFloat)hi->value - (XcmsFloat)lo->value); + answer->value = key->value; + answer->intensity = (hi->intensity - lo->intensity) * ratio; + answer->intensity += lo->intensity; + return (XcmsSuccess); +} + +/* + * NAME + * IntensityInterpolation + * + * SYNOPSIS + */ +static int +_XcmsIntensityInterpolation( + IntensityRec *key, IntensityRec *lo, IntensityRec *hi, IntensityRec *answer, + int bitsPerRGB) +/* + * DESCRIPTION + * Based on a given intensity, performs a linear interpolation + * on the values between two IntensityRec structures. + * The bitsPerRGB parameter is necessary to perform rounding + * to the correct number of significant bits. + * + * RETURNS + * Returns 0 if failed; otherwise non-zero. + */ +{ + XcmsFloat ratio; + long target, up, down; + int shift = 16 - bitsPerRGB; + int max_color = (1 << bitsPerRGB) - 1; + + ratio = (key->intensity - lo->intensity) / (hi->intensity - lo->intensity); + answer->intensity = key->intensity; + target = hi->value - lo->value; + target *= ratio; + target += lo->value; + + /* + * Ok now, lets find the closest in respects to bits per RGB + */ + up = ((target >> shift) * 0xFFFF) / max_color; + if (up < target) { + down = up; + up = (MIN((down >> shift) + 1, max_color) * 0xFFFF) / max_color; + } else { + down = (MAX((up >> shift) - 1, 0) * 0xFFFF) / max_color; + } + answer->value = ((up - target) < (target - down) ? up : down); + answer->value &= MASK[bitsPerRGB]; + return (XcmsSuccess); +} + + + +typedef int (*comparProcp)( + char *p1, + char *p2); +typedef int (*interpolProcp)( + char *key, + char *lo, + char *hi, + char *answer, + int bitsPerRGB); + +/* + * NAME + * _XcmsTableSearch + * + * SYNOPSIS + */ +static int +_XcmsTableSearch( + char *key, + int bitsPerRGB, + char *base, + unsigned nel, + unsigned nKeyPtrSize, + int (*compar)( + char *p1, + char *p2), + int (*interpol)( + char *key, + char *lo, + char *hi, + char *answer, + int bitsPerRGB), + char *answer) + +/* + * DESCRIPTION + * A binary search through the specificied table. + * + * RETURNS + * Returns 0 if failed; otherwise non-zero. + * + */ +{ + char *hi, *lo, *mid, *last; + int result; + + last = hi = base + ((nel - 1) * nKeyPtrSize); + mid = lo = base; + + /* use only the significants bits, then scale into 16 bits */ + ((IntensityRec *)key)->value = ((unsigned long) + (((IntensityRec *)key)->value >> (16 - bitsPerRGB)) * 0xFFFF) + / ((1 << bitsPerRGB) - 1); + + /* Special case so that zero intensity always maps to zero value */ + if ((*compar) (key,lo) <= 0) { + memcpy (answer, lo, nKeyPtrSize); + ((IntensityRec *)answer)->value &= MASK[bitsPerRGB]; + return XcmsSuccess; + } + while (mid != last) { + last = mid; + mid = lo + (((unsigned)(hi - lo) / nKeyPtrSize) / 2) * nKeyPtrSize; + result = (*compar) (key, mid); + if (result == 0) { + + memcpy(answer, mid, nKeyPtrSize); + ((IntensityRec *)answer)->value &= MASK[bitsPerRGB]; + return (XcmsSuccess); + } else if (result < 0) { + hi = mid; + } else { + lo = mid; + } + } + + /* + * If we got to here, we didn't find a solution, so we + * need to apply interpolation. + */ + return ((*interpol)(key, lo, hi, answer, bitsPerRGB)); +} + + +/* + * NAME + * _XcmsMatVec - multiply a 3 x 3 by a 3 x 1 vector + * + * SYNOPSIS + */ +static void _XcmsMatVec( + XcmsFloat *pMat, XcmsFloat *pIn, XcmsFloat *pOut) +/* + * DESCRIPTION + * Multiply the passed vector by the passed matrix to return a + * vector. Matrix is 3x3, vectors are of length 3. + * + * RETURNS + * void + */ +{ + int i, j; + + for (i = 0; i < 3; i++) { + pOut[i] = 0.0; + for (j = 0; j < 3; j++) + pOut[i] += *(pMat+(i*3)+j) * pIn[j]; + } +} + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + + +/* + * NAME + * XcmsLRGB_RGB_ParseString + * + * SYNOPSIS + */ +static int +XcmsLRGB_RGB_ParseString( + register char *spec, + XcmsColor *pColor) +/* + * DESCRIPTION + * This routines takes a string and attempts to convert + * it into a XcmsColor structure with XcmsRGBFormat. + * + * RETURNS + * 0 if failed, non-zero otherwise. + */ +{ + register int n, i; + unsigned short r, g, b; + char c; + char *pchar; + unsigned short *pShort; + + /* + * Check for old # format + */ + if (*spec == '#') { + /* + * Attempt to parse the value portion. + */ + spec++; + n = strlen(spec); + if (n != 3 && n != 6 && n != 9 && n != 12) { + return(XcmsFailure); + } + + n /= 3; + g = b = 0; + do { + r = g; + g = b; + b = 0; + for (i = n; --i >= 0; ) { + c = *spec++; + b <<= 4; + if (c >= '0' && c <= '9') + b |= c - '0'; + /* assume string in lowercase + else if (c >= 'A' && c <= 'F') + b |= c - ('A' - 10); + */ + else if (c >= 'a' && c <= 'f') + b |= c - ('a' - 10); + else return (XcmsFailure); + } + } while (*spec != '\0'); + + /* + * Succeeded ! + */ + n <<= 2; + n = 16 - n; + /* shift instead of scale, to match old broken semantics */ + pColor->spec.RGB.red = r << n; + pColor->spec.RGB.green = g << n; + pColor->spec.RGB.blue = b << n; + } else { + if ((pchar = strchr(spec, ':')) == NULL) { + return(XcmsFailure); + } + n = (int)(pchar - spec); + + /* + * Check for proper prefix. + */ + if (strncmp(spec, _XcmsRGB_prefix, n) != 0) { + return(XcmsFailure); + } + + /* + * Attempt to parse the value portion. + */ + spec += (n + 1); + pShort = &pColor->spec.RGB.red; + for (i = 0; i < 3; i++, pShort++, spec++) { + n = 0; + *pShort = 0; + while (*spec != '/' && *spec != '\0') { + if (++n > 4) { + return(XcmsFailure); + } + c = *spec++; + *pShort <<= 4; + if (c >= '0' && c <= '9') + *pShort |= c - '0'; + /* assume string in lowercase + else if (c >= 'A' && c <= 'F') + *pShort |= c - ('A' - 10); + */ + else if (c >= 'a' && c <= 'f') + *pShort |= c - ('a' - 10); + else return (XcmsFailure); + } + if (n == 0) + return (XcmsFailure); + if (n < 4) { + *pShort = ((unsigned long)*pShort * 0xFFFF) / ((1 << n*4) - 1); + } + } + } + pColor->format = XcmsRGBFormat; + pColor->pixel = 0; + return (XcmsSuccess); +} + + +/* + * NAME + * XcmsLRGB_RGBi_ParseString + * + * SYNOPSIS + */ +static int +XcmsLRGB_RGBi_ParseString( + register char *spec, + XcmsColor *pColor) +/* + * DESCRIPTION + * This routines takes a string and attempts to convert + * it into a XcmsColor structure with XcmsRGBiFormat. + * The assumed RGBi string syntax is: + * RGBi:<r>/<g>/<b> + * Where r, g, and b are in string input format for floats + * consisting of: + * a. an optional sign + * b. a string of numbers possibly containing a decimal point, + * c. an optional exponent field containing an 'E' or 'e' + * followed by a possibly signed integer string. + * + * RETURNS + * 0 if failed, non-zero otherwise. + */ +{ + int n; + char *pchar; + + if ((pchar = strchr(spec, ':')) == NULL) { + return(XcmsFailure); + } + n = (int)(pchar - spec); + + /* + * Check for proper prefix. + */ + if (strncmp(spec, _XcmsRGBi_prefix, n) != 0) { + return(XcmsFailure); + } + + /* + * Attempt to parse the value portion. + */ + if (sscanf(spec + n + 1, "%lf/%lf/%lf", + &pColor->spec.RGBi.red, + &pColor->spec.RGBi.green, + &pColor->spec.RGBi.blue) != 3) { + char *s; /* Maybe failed due to locale */ + int f; + if ((s = strdup(spec))) { + for (f = 0; s[f]; ++f) + if (s[f] == '.') + s[f] = ','; + else if (s[f] == ',') + s[f] = '.'; + if (sscanf(s + n + 1, "%lf/%lf/%lf", + &pColor->spec.RGBi.red, + &pColor->spec.RGBi.green, + &pColor->spec.RGBi.blue) != 3) { + free(s); + return(XcmsFailure); + } + free(s); + } else + return(XcmsFailure); + } + + /* + * Succeeded ! + */ + pColor->format = XcmsRGBiFormat; + pColor->pixel = 0; + return (XcmsSuccess); +} + + +/* + * NAME + * XcmsCIEXYZToRGBi - convert CIE XYZ to RGB + * + * SYNOPSIS + */ +/* ARGSUSED */ +Status +XcmsCIEXYZToRGBi( + XcmsCCC ccc, + XcmsColor *pXcmsColors_in_out,/* pointer to XcmsColors to convert */ + unsigned int nColors, /* Number of colors */ + Bool *pCompressed) /* pointer to an array of Bool */ +/* + * DESCRIPTION + * Converts color specifications in an array of XcmsColor + * structures from RGB format to RGBi format. + * + * RETURNS + * XcmsFailure if failed, + * XcmsSuccess if succeeded without gamut compression. + * XcmsSuccessWithCompression if succeeded with gamut + * compression. + */ +{ + LINEAR_RGB_SCCData *pScreenData; + XcmsFloat tmp[3]; + int hasCompressed = 0; + unsigned int i; + XcmsColor *pColor = pXcmsColors_in_out; + + if (ccc == NULL) { + return(XcmsFailure); + } + + pScreenData = (LINEAR_RGB_SCCData *)ccc->pPerScrnInfo->screenData; + + /* + * XcmsColors should be White Point Adjusted, if necessary, by now! + */ + + /* + * NEW!!! for extended gamut compression + * + * 1. Need to zero out pCompressed + * + * 2. Need to save initial address of pColor + * + * 3. Need to save initial address of pCompressed + */ + + for (i = 0; i < nColors; i++) { + + /* Make sure format is XcmsCIEXYZFormat */ + if (pColor->format != XcmsCIEXYZFormat) { + return(XcmsFailure); + } + + /* Multiply [A]-1 * [XYZ] to get RGB intensity */ + _XcmsMatVec((XcmsFloat *) pScreenData->XYZtoRGBmatrix, + (XcmsFloat *) &pColor->spec, tmp); + + if ((MIN3 (tmp[0], tmp[1], tmp[2]) < -EPS) || + (MAX3 (tmp[0], tmp[1], tmp[2]) > (1.0 + EPS))) { + + /* + * RGBi out of screen's gamut + */ + + if (ccc->gamutCompProc == NULL) { + /* + * Aha!! Here's that little trick that will allow + * gamut compression routines to get the out of bound + * RGBi. + */ + memcpy((char *)&pColor->spec, (char *)tmp, sizeof(tmp)); + pColor->format = XcmsRGBiFormat; + return(XcmsFailure); + } else if ((*ccc->gamutCompProc)(ccc, pXcmsColors_in_out, nColors, + i, pCompressed) == 0) { + return(XcmsFailure); + } + + /* + * The gamut compression function should return colors in CIEXYZ + * Also check again to if the new color is within gamut. + */ + if (pColor->format != XcmsCIEXYZFormat) { + return(XcmsFailure); + } + _XcmsMatVec((XcmsFloat *) pScreenData->XYZtoRGBmatrix, + (XcmsFloat *) &pColor->spec, tmp); + if ((MIN3 (tmp[0], tmp[1], tmp[2]) < -EPS) || + (MAX3 (tmp[0], tmp[1], tmp[2]) > (1.0 + EPS))) { + return(XcmsFailure); + } + hasCompressed++; + } + memcpy((char *)&pColor->spec, (char *)tmp, sizeof(tmp)); + /* These if statements are done to ensure the fudge factor is */ + /* is taken into account. */ + if (pColor->spec.RGBi.red < 0.0) { + pColor->spec.RGBi.red = 0.0; + } else if (pColor->spec.RGBi.red > 1.0) { + pColor->spec.RGBi.red = 1.0; + } + if (pColor->spec.RGBi.green < 0.0) { + pColor->spec.RGBi.green = 0.0; + } else if (pColor->spec.RGBi.green > 1.0) { + pColor->spec.RGBi.green = 1.0; + } + if (pColor->spec.RGBi.blue < 0.0) { + pColor->spec.RGBi.blue = 0.0; + } else if (pColor->spec.RGBi.blue > 1.0) { + pColor->spec.RGBi.blue = 1.0; + } + (pColor++)->format = XcmsRGBiFormat; + } + return (hasCompressed ? XcmsSuccessWithCompression : XcmsSuccess); +} + + +/* + * NAME + * LINEAR_RGBi_to_CIEXYZ - convert RGBi to CIEXYZ + * + * SYNOPSIS + */ +/* ARGSUSED */ +Status +XcmsRGBiToCIEXYZ( + XcmsCCC ccc, + XcmsColor *pXcmsColors_in_out,/* pointer to XcmsColors to convert */ + unsigned int nColors, /* Number of colors */ + Bool *pCompressed) /* pointer to a bit array */ +/* + * DESCRIPTION + * Converts color specifications in an array of XcmsColor + * structures from RGBi format to CIEXYZ format. + * + * RETURNS + * XcmsFailure if failed, + * XcmsSuccess if succeeded. + */ +{ + LINEAR_RGB_SCCData *pScreenData; + XcmsFloat tmp[3]; + + /* + * pCompressed ignored in this function. + */ + + if (ccc == NULL) { + return(XcmsFailure); + } + + pScreenData = (LINEAR_RGB_SCCData *)ccc->pPerScrnInfo->screenData; + + /* + * XcmsColors should be White Point Adjusted, if necessary, by now! + */ + + while (nColors--) { + + /* Multiply [A]-1 * [XYZ] to get RGB intensity */ + _XcmsMatVec((XcmsFloat *) pScreenData->RGBtoXYZmatrix, + (XcmsFloat *) &pXcmsColors_in_out->spec, tmp); + + memcpy((char *)&pXcmsColors_in_out->spec, (char *)tmp, sizeof(tmp)); + (pXcmsColors_in_out++)->format = XcmsCIEXYZFormat; + } + return(XcmsSuccess); +} + + +/* + * NAME + * XcmsRGBiToRGB + * + * SYNOPSIS + */ +/* ARGSUSED */ +Status +XcmsRGBiToRGB( + XcmsCCC ccc, + XcmsColor *pXcmsColors_in_out,/* pointer to XcmsColors to convert */ + unsigned int nColors, /* Number of colors */ + Bool *pCompressed) /* pointer to a bit array */ +/* + * DESCRIPTION + * Converts color specifications in an array of XcmsColor + * structures from RGBi format to RGB format. + * + * RETURNS + * XcmsFailure if failed, + * XcmsSuccess if succeeded without gamut compression. + * XcmsSuccessWithCompression if succeeded with gamut + * compression. + */ +{ + LINEAR_RGB_SCCData *pScreenData; + XcmsRGB tmpRGB; + IntensityRec keyIRec, answerIRec; + + /* + * pCompressed ignored in this function. + */ + + if (ccc == NULL) { + return(XcmsFailure); + } + + pScreenData = (LINEAR_RGB_SCCData *)ccc->pPerScrnInfo->screenData; + + while (nColors--) { + + /* Make sure format is XcmsRGBiFormat */ + if (pXcmsColors_in_out->format != XcmsRGBiFormat) { + return(XcmsFailure); + } + + keyIRec.intensity = pXcmsColors_in_out->spec.RGBi.red; + if (!_XcmsTableSearch((char *)&keyIRec, ccc->visual->bits_per_rgb, + (char *)pScreenData->pRedTbl->pBase, + (unsigned)pScreenData->pRedTbl->nEntries, + (unsigned)sizeof(IntensityRec), + (comparProcp)_XcmsIntensityCmp, (interpolProcp)_XcmsIntensityInterpolation, (char *)&answerIRec)) { + return(XcmsFailure); + } + tmpRGB.red = answerIRec.value; + + keyIRec.intensity = pXcmsColors_in_out->spec.RGBi.green; + if (!_XcmsTableSearch((char *)&keyIRec, ccc->visual->bits_per_rgb, + (char *)pScreenData->pGreenTbl->pBase, + (unsigned)pScreenData->pGreenTbl->nEntries, + (unsigned)sizeof(IntensityRec), + (comparProcp)_XcmsIntensityCmp, (interpolProcp)_XcmsIntensityInterpolation, (char *)&answerIRec)) { + return(XcmsFailure); + } + tmpRGB.green = answerIRec.value; + + keyIRec.intensity = pXcmsColors_in_out->spec.RGBi.blue; + if (!_XcmsTableSearch((char *)&keyIRec, ccc->visual->bits_per_rgb, + (char *)pScreenData->pBlueTbl->pBase, + (unsigned)pScreenData->pBlueTbl->nEntries, + (unsigned)sizeof(IntensityRec), + (comparProcp)_XcmsIntensityCmp, (interpolProcp)_XcmsIntensityInterpolation, (char *)&answerIRec)) { + return(XcmsFailure); + } + tmpRGB.blue = answerIRec.value; + + memcpy((char *)&pXcmsColors_in_out->spec, (char *)&tmpRGB, sizeof(XcmsRGB)); + (pXcmsColors_in_out++)->format = XcmsRGBFormat; + } + return(XcmsSuccess); +} + + +/* + * NAME + * XcmsRGBToRGBi + * + * SYNOPSIS + */ +/* ARGSUSED */ +Status +XcmsRGBToRGBi( + XcmsCCC ccc, + XcmsColor *pXcmsColors_in_out,/* pointer to XcmsColors to convert */ + unsigned int nColors, /* Number of colors */ + Bool *pCompressed) /* pointer to a bit array */ +/* + * DESCRIPTION + * Converts color specifications in an array of XcmsColor + * structures from RGB format to RGBi format. + * + * RETURNS + * XcmsFailure if failed, + * XcmsSuccess if succeeded. + */ +{ + LINEAR_RGB_SCCData *pScreenData; + XcmsRGBi tmpRGBi; + IntensityRec keyIRec, answerIRec; + + /* + * pCompressed ignored in this function. + */ + + if (ccc == NULL) { + return(XcmsFailure); + } + + pScreenData = (LINEAR_RGB_SCCData *)ccc->pPerScrnInfo->screenData; + + while (nColors--) { + + /* Make sure format is XcmsRGBFormat */ + if (pXcmsColors_in_out->format != XcmsRGBFormat) { + return(XcmsFailure); + } + + keyIRec.value = pXcmsColors_in_out->spec.RGB.red; + if (!_XcmsTableSearch((char *)&keyIRec, ccc->visual->bits_per_rgb, + (char *)pScreenData->pRedTbl->pBase, + (unsigned)pScreenData->pRedTbl->nEntries, + (unsigned)sizeof(IntensityRec), + (comparProcp)_XcmsValueCmp, (interpolProcp)_XcmsValueInterpolation, (char *)&answerIRec)) { + return(XcmsFailure); + } + tmpRGBi.red = answerIRec.intensity; + + keyIRec.value = pXcmsColors_in_out->spec.RGB.green; + if (!_XcmsTableSearch((char *)&keyIRec, ccc->visual->bits_per_rgb, + (char *)pScreenData->pGreenTbl->pBase, + (unsigned)pScreenData->pGreenTbl->nEntries, + (unsigned)sizeof(IntensityRec), + (comparProcp)_XcmsValueCmp, (interpolProcp)_XcmsValueInterpolation, (char *)&answerIRec)) { + return(XcmsFailure); + } + tmpRGBi.green = answerIRec.intensity; + + keyIRec.value = pXcmsColors_in_out->spec.RGB.blue; + if (!_XcmsTableSearch((char *)&keyIRec, ccc->visual->bits_per_rgb, + (char *)pScreenData->pBlueTbl->pBase, + (unsigned)pScreenData->pBlueTbl->nEntries, + (unsigned)sizeof(IntensityRec), + (comparProcp)_XcmsValueCmp, (interpolProcp)_XcmsValueInterpolation, (char *)&answerIRec)) { + return(XcmsFailure); + } + tmpRGBi.blue = answerIRec.intensity; + + memcpy((char *)&pXcmsColors_in_out->spec, (char *)&tmpRGBi, sizeof(XcmsRGBi)); + (pXcmsColors_in_out++)->format = XcmsRGBiFormat; + } + return(XcmsSuccess); +} + +/* + * NAME + * _XcmsInitScrnDefaultInfo + * + * SYNOPSIS + */ +/* ARGSUSED */ +int +_XcmsLRGB_InitScrnDefault( + Display *dpy, + int screenNumber, + XcmsPerScrnInfo *pPerScrnInfo) +/* + * DESCRIPTION + * Given a display and screen number, this routine attempts + * to initialize the Xcms per Screen Info structure + * (XcmsPerScrnInfo) with defaults. + * + * RETURNS + * Returns zero if initialization failed; non-zero otherwise. + */ +{ + pPerScrnInfo->screenData = (XPointer)&Default_RGB_SCCData; + pPerScrnInfo->screenWhitePt.spec.CIEXYZ.X = + Default_RGB_SCCData.RGBtoXYZmatrix[0][0] + + Default_RGB_SCCData.RGBtoXYZmatrix[0][1] + + Default_RGB_SCCData.RGBtoXYZmatrix[0][2]; + pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y = + Default_RGB_SCCData.RGBtoXYZmatrix[1][0] + + Default_RGB_SCCData.RGBtoXYZmatrix[1][1] + + Default_RGB_SCCData.RGBtoXYZmatrix[1][2]; + pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Z = + Default_RGB_SCCData.RGBtoXYZmatrix[2][0] + + Default_RGB_SCCData.RGBtoXYZmatrix[2][1] + + Default_RGB_SCCData.RGBtoXYZmatrix[2][2]; + if ((pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y < (1.0 - EPS) ) + || (pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y > (1.0 + EPS))) { + pPerScrnInfo->screenData = (XPointer)NULL; + pPerScrnInfo->state = XcmsInitNone; + return(0); + } + pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y = 1.0; + pPerScrnInfo->screenWhitePt.format = XcmsCIEXYZFormat; + pPerScrnInfo->screenWhitePt.pixel = 0; + pPerScrnInfo->functionSet = (XPointer)&XcmsLinearRGBFunctionSet; + pPerScrnInfo->state = XcmsInitFailure; /* default initialization */ + return(1); +} diff --git a/libX11/src/xcms/PrOfId.c b/libX11/src/xcms/PrOfId.c index 1ec36d96c..a96d28cec 100644 --- a/libX11/src/xcms/PrOfId.c +++ b/libX11/src/xcms/PrOfId.c @@ -1,97 +1,97 @@ -
-/*
- * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc.
- * All Rights Reserved
- *
- * This file is a component of an X Window System-specific implementation
- * of Xcms based on the TekColor Color Management System. Permission is
- * hereby granted to use, copy, modify, sell, and otherwise distribute this
- * software and its documentation for any purpose and without fee, provided
- * that this copyright, permission, and disclaimer notice is reproduced in
- * all copies of this software and in supporting documentation. TekColor
- * is a trademark of Tektronix, Inc.
- *
- * Tektronix makes no representation about the suitability of this software
- * for any purpose. It is provided "as is" and with all faults.
- *
- * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE,
- * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX 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 TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE.
- *
- *
- * NAME
- * XcmsPrOfId.c
- *
- * DESCRIPTION
- * Source for XcmsPrefixOfFormat()
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include "Xlibint.h"
-#include "Xcmsint.h"
-#include "Cv.h"
-
-
-/*
- * NAME
- * XcmsPrefixOfId
- *
- * SYNOPSIS
- */
-char *
-XcmsPrefixOfFormat(
- XcmsColorFormat id)
-/*
- * DESCRIPTION
- * Returns the color space prefix for the specified color
- * space ID if the color space is found in the Color
- * Conversion Context.
- *
- * RETURNS
- * Returns a color space prefix.
- *
- * CAVEATS
- * Space is allocated for the returned string, therefore,
- * the application is responsible for freeing (using XFree)
- * the space.
- *
- */
-{
- XcmsColorSpace **papColorSpaces;
-
- /*
- * First try Device-Independent color spaces
- */
- papColorSpaces = _XcmsDIColorSpaces;
- if (papColorSpaces != NULL) {
- while (*papColorSpaces != NULL) {
- if ((*papColorSpaces)->id == id) {
- return strdup((*papColorSpaces)->prefix);
- }
- papColorSpaces++;
- }
- }
-
- /*
- * Next try Device-Dependent color spaces
- */
- papColorSpaces = _XcmsDDColorSpaces;
- if (papColorSpaces != NULL) {
- while (*papColorSpaces != NULL) {
- if ((*papColorSpaces)->id == id) {
- return strdup((*papColorSpaces)->prefix);
- }
- papColorSpaces++;
- }
- }
-
- return(NULL);
-}
+ +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX 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 TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * NAME + * XcmsPrOfId.c + * + * DESCRIPTION + * Source for XcmsPrefixOfFormat() + * + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include "Xlibint.h" +#include "Xcmsint.h" +#include "Cv.h" + + +/* + * NAME + * XcmsPrefixOfId + * + * SYNOPSIS + */ +char * +XcmsPrefixOfFormat( + XcmsColorFormat id) +/* + * DESCRIPTION + * Returns the color space prefix for the specified color + * space ID if the color space is found in the Color + * Conversion Context. + * + * RETURNS + * Returns a color space prefix. + * + * CAVEATS + * Space is allocated for the returned string, therefore, + * the application is responsible for freeing (using XFree) + * the space. + * + */ +{ + XcmsColorSpace **papColorSpaces; + + /* + * First try Device-Independent color spaces + */ + papColorSpaces = _XcmsDIColorSpaces; + if (papColorSpaces != NULL) { + while (*papColorSpaces != NULL) { + if ((*papColorSpaces)->id == id) { + return strdup((*papColorSpaces)->prefix); + } + papColorSpaces++; + } + } + + /* + * Next try Device-Dependent color spaces + */ + papColorSpaces = _XcmsDDColorSpaces; + if (papColorSpaces != NULL) { + while (*papColorSpaces != NULL) { + if ((*papColorSpaces)->id == id) { + return strdup((*papColorSpaces)->prefix); + } + papColorSpaces++; + } + } + + return(NULL); +} diff --git a/libX11/src/xcms/cmsProp.c b/libX11/src/xcms/cmsProp.c index b732b800f..2826ee7be 100644 --- a/libX11/src/xcms/cmsProp.c +++ b/libX11/src/xcms/cmsProp.c @@ -1,149 +1,149 @@ -
-/*
- *
- * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc.
- * All Rights Reserved
- *
- * This file is a component of an X Window System-specific implementation
- * of Xcms based on the TekColor Color Management System. Permission is
- * hereby granted to use, copy, modify, sell, and otherwise distribute this
- * software and its documentation for any purpose and without fee, provided
- * that this copyright, permission, and disclaimer notice is reproduced in
- * all copies of this software and in supporting documentation. TekColor
- * is a trademark of Tektronix, Inc.
- *
- * Tektronix makes no representation about the suitability of this software
- * for any purpose. It is provided "as is" and with all faults.
- *
- * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE,
- * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX 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 TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE.
- *
- * NAME
- * XcmsProp.c
- *
- * DESCRIPTION
- * This utility routines for manipulating properties.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <X11/Xatom.h>
-#include "Xlibint.h"
-#include "Xcmsint.h"
-#include "Cv.h"
-
-
-/************************************************************************
- * *
- * API PRIVATE ROUTINES *
- * *
- ************************************************************************/
-
-
-/*
- * NAME
- * _XcmsGetElement -- get an element value from the property passed
- *
- * SYNOPSIS
- */
-unsigned long
-_XcmsGetElement(
- int format,
- char **pValue,
- unsigned long *pCount)
-/*
- * DESCRIPTION
- * Get the next element from the property and return it.
- * Also increment the pointer the amount needed.
- *
- * Returns
- * unsigned long
- */
-{
- unsigned long value;
-
- switch (format) {
- case 32:
- value = *((unsigned long *)(*pValue)) & 0xFFFFFFFF;
- *pValue += sizeof(unsigned long);
- *pCount -= 1;
- break;
- case 16:
- value = *((unsigned short *)(*pValue));
- *pValue += sizeof(unsigned short);
- *pCount -= 1;
- break;
- case 8:
- value = *((unsigned char *) (*pValue));
- *pValue += 1;
- *pCount -= 1;
- break;
- default:
- value = 0;
- break;
- }
- return(value);
-}
-
-
-/*
- * NAME
- * _XcmsGetProperty -- Determine the existance of a property
- *
- * SYNOPSIS
- */
-int
-_XcmsGetProperty(
- Display *pDpy,
- Window w,
- Atom property,
- int *pFormat,
- unsigned long *pNItems,
- unsigned long *pNBytes,
- char **pValue)
-/*
- * DESCRIPTION
- *
- * Returns
- * 0 if property does not exist.
- * 1 if property exists.
- */
-{
- char *prop_ret;
- int format_ret;
- long len = 6516;
- unsigned long nitems_ret, after_ret;
- Atom atom_ret;
- int xgwp_ret;
-
- while (True) {
- xgwp_ret = XGetWindowProperty (pDpy, w, property, 0, len, False,
- XA_INTEGER, &atom_ret, &format_ret,
- &nitems_ret, &after_ret,
- (unsigned char **)&prop_ret);
- if (xgwp_ret == Success && after_ret > 0) {
- len += nitems_ret * (format_ret >> 3);
- XFree (prop_ret);
- } else {
- break;
- }
- }
- if (xgwp_ret != Success || format_ret == 0 || nitems_ret == 0) {
- /* the property does not exist or is of an unexpected type or
- getting window property failed */
- return(XcmsFailure);
- }
-
- *pFormat = format_ret;
- *pNItems = nitems_ret;
- *pNBytes = nitems_ret * (format_ret >> 3);
- *pValue = prop_ret;
- return(XcmsSuccess);
-}
+ +/* + * + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX 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 TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * NAME + * XcmsProp.c + * + * DESCRIPTION + * This utility routines for manipulating properties. + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <X11/Xatom.h> +#include "Xlibint.h" +#include "Xcmsint.h" +#include "Cv.h" + + +/************************************************************************ + * * + * API PRIVATE ROUTINES * + * * + ************************************************************************/ + + +/* + * NAME + * _XcmsGetElement -- get an element value from the property passed + * + * SYNOPSIS + */ +unsigned long +_XcmsGetElement( + int format, + char **pValue, + unsigned long *pCount) +/* + * DESCRIPTION + * Get the next element from the property and return it. + * Also increment the pointer the amount needed. + * + * Returns + * unsigned long + */ +{ + unsigned long value; + + switch (format) { + case 32: + value = *((unsigned long *)(*pValue)) & 0xFFFFFFFF; + *pValue += sizeof(unsigned long); + *pCount -= 1; + break; + case 16: + value = *((unsigned short *)(*pValue)); + *pValue += sizeof(unsigned short); + *pCount -= 1; + break; + case 8: + value = *((unsigned char *) (*pValue)); + *pValue += 1; + *pCount -= 1; + break; + default: + value = 0; + break; + } + return(value); +} + + +/* + * NAME + * _XcmsGetProperty -- Determine the existance of a property + * + * SYNOPSIS + */ +int +_XcmsGetProperty( + Display *pDpy, + Window w, + Atom property, + int *pFormat, + unsigned long *pNItems, + unsigned long *pNBytes, + char **pValue) +/* + * DESCRIPTION + * + * Returns + * 0 if property does not exist. + * 1 if property exists. + */ +{ + char *prop_ret; + int format_ret; + long len = 6516; + unsigned long nitems_ret, after_ret; + Atom atom_ret; + int xgwp_ret; + + while (True) { + xgwp_ret = XGetWindowProperty (pDpy, w, property, 0, len, False, + XA_INTEGER, &atom_ret, &format_ret, + &nitems_ret, &after_ret, + (unsigned char **)&prop_ret); + if (xgwp_ret == Success && after_ret > 0) { + len += nitems_ret * (format_ret >> 3); + XFree (prop_ret); + } else { + break; + } + } + if (xgwp_ret != Success || format_ret == 0 || nitems_ret == 0) { + /* the property does not exist or is of an unexpected type or + getting window property failed */ + return(XcmsFailure); + } + + *pFormat = format_ret; + *pNItems = nitems_ret; + *pNBytes = nitems_ret * (format_ret >> 3); + *pValue = prop_ret; + return(XcmsSuccess); +} diff --git a/libX11/src/xkb/XKBGAlloc.c b/libX11/src/xkb/XKBGAlloc.c index 9dd1e4912..3f4f49670 100644 --- a/libX11/src/xkb/XKBGAlloc.c +++ b/libX11/src/xkb/XKBGAlloc.c @@ -1,1012 +1,1012 @@ -/************************************************************
-Copyright (c) 1993 by Silicon Graphics Computer Systems, 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 Silicon Graphics not be
-used in advertising or publicity pertaining to distribution
-of the software without specific prior written permission.
-Silicon Graphics makes no representation about the suitability
-of this software for any purpose. It is provided "as is"
-without any express or implied warranty.
-
-SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
-SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
-GRAPHICS 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 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
-THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-********************************************************/
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#elif defined(HAVE_CONFIG_H)
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <unistd.h>
-
-#ifndef XKB_IN_SERVER
-
-#include "Xlibint.h"
-#include "XKBlibint.h"
-#include <X11/extensions/XKBgeom.h>
-#include <X11/extensions/XKBproto.h>
-
-#else
-
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include "misc.h"
-#include "inputstr.h"
-#include <X11/extensions/XKBsrv.h>
-#include <X11/extensions/XKBgeom.h>
-
-#endif /* XKB_IN_SERVER */
-
-#ifdef X_NOT_POSIX
-#define Size_t unsigned int
-#else
-#define Size_t size_t
-#endif
-
-/***====================================================================***/
-
-static void
-_XkbFreeGeomLeafElems( Bool freeAll,
- int first,
- int count,
- unsigned short * num_inout,
- unsigned short * sz_inout,
- char ** elems,
- unsigned int elem_sz)
-{
- if ((freeAll)||(*elems==NULL)) {
- *num_inout= *sz_inout= 0;
- if (*elems!=NULL) {
- _XkbFree(*elems);
- *elems= NULL;
- }
- return;
- }
-
- if ((first>=(*num_inout))||(first<0)||(count<1))
- return;
-
- if (first+count>=(*num_inout)) {
- /* truncating the array is easy */
- (*num_inout)= first;
- }
- else {
- char * ptr;
- int extra;
- ptr= *elems;
- extra= ((*num_inout)-(first+count))*elem_sz;
- if (extra>0)
- memmove(&ptr[first*elem_sz],&ptr[(first+count)*elem_sz],extra);
- (*num_inout)-= count;
- }
- return;
-}
-
-typedef void (*ContentsClearFunc)(
- char * /* priv */
-);
-
-static void
-_XkbFreeGeomNonLeafElems( Bool freeAll,
- int first,
- int count,
- unsigned short * num_inout,
- unsigned short * sz_inout,
- char ** elems,
- unsigned int elem_sz,
- ContentsClearFunc freeFunc)
-{
-register int i;
-register char *ptr;
-
- if (freeAll) {
- first= 0;
- count= (*num_inout);
- }
- else if ((first>=(*num_inout))||(first<0)||(count<1))
- return;
- else if (first+count>(*num_inout))
- count= (*num_inout)-first;
- if (*elems==NULL)
- return;
-
- if (freeFunc) {
- ptr= *elems;
- ptr+= first*elem_sz;
- for (i=0;i<count;i++) {
- (*freeFunc)(ptr);
- ptr+= elem_sz;
- }
- }
- if (freeAll) {
- (*num_inout)= (*sz_inout)= 0;
- if (*elems) {
- _XkbFree(*elems);
- *elems= NULL;
- }
- }
- else if (first+count>=(*num_inout))
- *num_inout= first;
- else {
- i= ((*num_inout)-(first+count))*elem_sz;
- ptr= *elems;
- memmove(&ptr[first*elem_sz],&ptr[(first+count)*elem_sz],i);
- (*num_inout)-= count;
- }
- return;
-}
-
-/***====================================================================***/
-
-static void
-_XkbClearProperty(char *prop_in)
-{
-XkbPropertyPtr prop= (XkbPropertyPtr)prop_in;
-
- if (prop->name) {
- _XkbFree(prop->name);
- prop->name= NULL;
- }
- if (prop->value) {
- _XkbFree(prop->value);
- prop->value= NULL;
- }
- return;
-}
-
-void
-XkbFreeGeomProperties( XkbGeometryPtr geom,
- int first,
- int count,
- Bool freeAll)
-{
- _XkbFreeGeomNonLeafElems(freeAll,first,count,
- &geom->num_properties,&geom->sz_properties,
- (char **)&geom->properties,
- sizeof(XkbPropertyRec),_XkbClearProperty);
- return;
-}
-
-/***====================================================================***/
-
-void
-XkbFreeGeomKeyAliases( XkbGeometryPtr geom,
- int first,
- int count,
- Bool freeAll)
-{
- _XkbFreeGeomLeafElems(freeAll,first,count,
- &geom->num_key_aliases,&geom->sz_key_aliases,
- (char **)&geom->key_aliases,
- sizeof(XkbKeyAliasRec));
- return;
-}
-
-/***====================================================================***/
-
-static void
-_XkbClearColor(char *color_in)
-{
-XkbColorPtr color= (XkbColorPtr)color_in;
-
- if (color->spec)
- _XkbFree(color->spec);
- return;
-}
-
-void
-XkbFreeGeomColors(XkbGeometryPtr geom,int first,int count,Bool freeAll)
-{
- _XkbFreeGeomNonLeafElems(freeAll,first,count,
- &geom->num_colors,&geom->sz_colors,
- (char **)&geom->colors,
- sizeof(XkbColorRec),_XkbClearColor);
- return;
-}
-
-/***====================================================================***/
-
-void
-XkbFreeGeomPoints(XkbOutlinePtr outline,int first,int count,Bool freeAll)
-{
- _XkbFreeGeomLeafElems(freeAll,first,count,
- &outline->num_points,&outline->sz_points,
- (char **)&outline->points,
- sizeof(XkbPointRec));
- return;
-}
-
-/***====================================================================***/
-
-static void
-_XkbClearOutline(char *outline_in)
-{
-XkbOutlinePtr outline= (XkbOutlinePtr)outline_in;
-
- if (outline->points!=NULL)
- XkbFreeGeomPoints(outline,0,outline->num_points,True);
- return;
-}
-
-void
-XkbFreeGeomOutlines(XkbShapePtr shape,int first,int count,Bool freeAll)
-{
- _XkbFreeGeomNonLeafElems(freeAll,first,count,
- &shape->num_outlines,&shape->sz_outlines,
- (char **)&shape->outlines,
- sizeof(XkbOutlineRec),_XkbClearOutline);
-
- return;
-}
-
-/***====================================================================***/
-
-static void
-_XkbClearShape(char *shape_in)
-{
-XkbShapePtr shape= (XkbShapePtr)shape_in;
-
- if (shape->outlines)
- XkbFreeGeomOutlines(shape,0,shape->num_outlines,True);
- return;
-}
-
-void
-XkbFreeGeomShapes(XkbGeometryPtr geom,int first,int count,Bool freeAll)
-{
- _XkbFreeGeomNonLeafElems(freeAll,first,count,
- &geom->num_shapes,&geom->sz_shapes,
- (char **)&geom->shapes,
- sizeof(XkbShapeRec),_XkbClearShape);
- return;
-}
-
-/***====================================================================***/
-
-void
-XkbFreeGeomOverlayKeys(XkbOverlayRowPtr row,int first,int count,Bool freeAll)
-{
- _XkbFreeGeomLeafElems(freeAll,first,count,
- &row->num_keys,&row->sz_keys,
- (char **)&row->keys,
- sizeof(XkbOverlayKeyRec));
- return;
-}
-
-/***====================================================================***/
-
-static void
-_XkbClearOverlayRow(char *row_in)
-{
-XkbOverlayRowPtr row= (XkbOverlayRowPtr)row_in;
-
- if (row->keys!=NULL)
- XkbFreeGeomOverlayKeys(row,0,row->num_keys,True);
- return;
-}
-
-void
-XkbFreeGeomOverlayRows(XkbOverlayPtr overlay,int first,int count,Bool freeAll)
-{
- _XkbFreeGeomNonLeafElems(freeAll,first,count,
- &overlay->num_rows,&overlay->sz_rows,
- (char **)&overlay->rows,
- sizeof(XkbOverlayRowRec),_XkbClearOverlayRow);
- return;
-}
-
-/***====================================================================***/
-
-static void
-_XkbClearOverlay(char *overlay_in)
-{
-XkbOverlayPtr overlay= (XkbOverlayPtr)overlay_in;
-
- if (overlay->rows!=NULL)
- XkbFreeGeomOverlayRows(overlay,0,overlay->num_rows,True);
- return;
-}
-
-void
-XkbFreeGeomOverlays(XkbSectionPtr section,int first,int count,Bool freeAll)
-{
- _XkbFreeGeomNonLeafElems(freeAll,first,count,
- §ion->num_overlays,§ion->sz_overlays,
- (char **)§ion->overlays,
- sizeof(XkbOverlayRec),_XkbClearOverlay);
- return;
-}
-
-/***====================================================================***/
-
-void
-XkbFreeGeomKeys(XkbRowPtr row,int first,int count,Bool freeAll)
-{
- _XkbFreeGeomLeafElems(freeAll,first,count,
- &row->num_keys,&row->sz_keys,
- (char **)&row->keys,
- sizeof(XkbKeyRec));
- return;
-}
-
-/***====================================================================***/
-
-static void
-_XkbClearRow(char *row_in)
-{
-XkbRowPtr row= (XkbRowPtr)row_in;
-
- if (row->keys!=NULL)
- XkbFreeGeomKeys(row,0,row->num_keys,True);
- return;
-}
-
-void
-XkbFreeGeomRows(XkbSectionPtr section,int first,int count,Bool freeAll)
-{
- _XkbFreeGeomNonLeafElems(freeAll,first,count,
- §ion->num_rows,§ion->sz_rows,
- (char **)§ion->rows,
- sizeof(XkbRowRec),_XkbClearRow);
-}
-
-/***====================================================================***/
-
-static void
-_XkbClearSection(char *section_in)
-{
-XkbSectionPtr section= (XkbSectionPtr)section_in;
-
- if (section->rows!=NULL)
- XkbFreeGeomRows(section,0,section->num_rows,True);
- if (section->doodads!=NULL) {
- XkbFreeGeomDoodads(section->doodads,section->num_doodads,True);
- section->doodads= NULL;
- }
- return;
-}
-
-void
-XkbFreeGeomSections(XkbGeometryPtr geom,int first,int count,Bool freeAll)
-{
- _XkbFreeGeomNonLeafElems(freeAll,first,count,
- &geom->num_sections,&geom->sz_sections,
- (char **)&geom->sections,
- sizeof(XkbSectionRec),_XkbClearSection);
- return;
-}
-
-/***====================================================================***/
-
-static void
-_XkbClearDoodad(char *doodad_in)
-{
-XkbDoodadPtr doodad= (XkbDoodadPtr)doodad_in;
-
- switch (doodad->any.type) {
- case XkbTextDoodad:
- {
- if (doodad->text.text!=NULL) {
- _XkbFree(doodad->text.text);
- doodad->text.text= NULL;
- }
- if (doodad->text.font!=NULL) {
- _XkbFree(doodad->text.font);
- doodad->text.font= NULL;
- }
- }
- break;
- case XkbLogoDoodad:
- {
- if (doodad->logo.logo_name!=NULL) {
- _XkbFree(doodad->logo.logo_name);
- doodad->logo.logo_name= NULL;
- }
- }
- break;
- }
- return;
-}
-
-void
-XkbFreeGeomDoodads(XkbDoodadPtr doodads,int nDoodads,Bool freeAll)
-{
-register int i;
-register XkbDoodadPtr doodad;
-
- if (doodads) {
- for (i=0,doodad= doodads;i<nDoodads;i++,doodad++) {
- _XkbClearDoodad((char *)doodad);
- }
- if (freeAll)
- _XkbFree(doodads);
- }
- return;
-}
-
-void
-XkbFreeGeometry(XkbGeometryPtr geom,unsigned which,Bool freeMap)
-{
- if (geom==NULL)
- return;
- if (freeMap)
- which= XkbGeomAllMask;
- if ((which&XkbGeomPropertiesMask)&&(geom->properties!=NULL))
- XkbFreeGeomProperties(geom,0,geom->num_properties,True);
- if ((which&XkbGeomColorsMask)&&(geom->colors!=NULL))
- XkbFreeGeomColors(geom,0,geom->num_colors,True);
- if ((which&XkbGeomShapesMask)&&(geom->shapes!=NULL))
- XkbFreeGeomShapes(geom,0,geom->num_shapes,True);
- if ((which&XkbGeomSectionsMask)&&(geom->sections!=NULL))
- XkbFreeGeomSections(geom,0,geom->num_sections,True);
- if ((which&XkbGeomDoodadsMask)&&(geom->doodads!= NULL)) {
- XkbFreeGeomDoodads(geom->doodads,geom->num_doodads,True);
- geom->doodads= NULL;
- geom->num_doodads= geom->sz_doodads= 0;
- }
- if ((which&XkbGeomKeyAliasesMask)&&(geom->key_aliases!=NULL))
- XkbFreeGeomKeyAliases(geom,0,geom->num_key_aliases,True);
- if (freeMap) {
- if (geom->label_font!=NULL) {
- _XkbFree(geom->label_font);
- geom->label_font= NULL;
- }
- _XkbFree(geom);
- }
- return;
-}
-
-/***====================================================================***/
-
-static Status
-_XkbGeomAlloc( XPointer * old,
- unsigned short * num,
- unsigned short * total,
- int num_new,
- Size_t sz_elem)
-{
- if (num_new<1)
- return Success;
- if ((*old)==NULL)
- *num= *total= 0;
-
- if ((*num)+num_new<=(*total))
- return Success;
-
- *total= (*num)+num_new;
- if ((*old)!=NULL)
- (*old)= (XPointer)_XkbRealloc((*old),(*total)*sz_elem);
- else (*old)= (XPointer)_XkbCalloc((*total),sz_elem);
- if ((*old)==NULL) {
- *total= *num= 0;
- return BadAlloc;
- }
-
- if (*num>0) {
- char *tmp= (char *)(*old);
- bzero(&tmp[sz_elem*(*num)],(num_new*sz_elem));
- }
- return Success;
-}
-
-#define _XkbAllocProps(g,n) _XkbGeomAlloc((XPointer *)&(g)->properties,\
- &(g)->num_properties,&(g)->sz_properties,\
- (n),sizeof(XkbPropertyRec))
-#define _XkbAllocColors(g,n) _XkbGeomAlloc((XPointer *)&(g)->colors,\
- &(g)->num_colors,&(g)->sz_colors,\
- (n),sizeof(XkbColorRec))
-#define _XkbAllocShapes(g,n) _XkbGeomAlloc((XPointer *)&(g)->shapes,\
- &(g)->num_shapes,&(g)->sz_shapes,\
- (n),sizeof(XkbShapeRec))
-#define _XkbAllocSections(g,n) _XkbGeomAlloc((XPointer *)&(g)->sections,\
- &(g)->num_sections,&(g)->sz_sections,\
- (n),sizeof(XkbSectionRec))
-#define _XkbAllocDoodads(g,n) _XkbGeomAlloc((XPointer *)&(g)->doodads,\
- &(g)->num_doodads,&(g)->sz_doodads,\
- (n),sizeof(XkbDoodadRec))
-#define _XkbAllocKeyAliases(g,n) _XkbGeomAlloc((XPointer *)&(g)->key_aliases,\
- &(g)->num_key_aliases,&(g)->sz_key_aliases,\
- (n),sizeof(XkbKeyAliasRec))
-
-#define _XkbAllocOutlines(s,n) _XkbGeomAlloc((XPointer *)&(s)->outlines,\
- &(s)->num_outlines,&(s)->sz_outlines,\
- (n),sizeof(XkbOutlineRec))
-#define _XkbAllocRows(s,n) _XkbGeomAlloc((XPointer *)&(s)->rows,\
- &(s)->num_rows,&(s)->sz_rows,\
- (n),sizeof(XkbRowRec))
-#define _XkbAllocPoints(o,n) _XkbGeomAlloc((XPointer *)&(o)->points,\
- &(o)->num_points,&(o)->sz_points,\
- (n),sizeof(XkbPointRec))
-#define _XkbAllocKeys(r,n) _XkbGeomAlloc((XPointer *)&(r)->keys,\
- &(r)->num_keys,&(r)->sz_keys,\
- (n),sizeof(XkbKeyRec))
-#define _XkbAllocOverlays(s,n) _XkbGeomAlloc((XPointer *)&(s)->overlays,\
- &(s)->num_overlays,&(s)->sz_overlays,\
- (n),sizeof(XkbOverlayRec))
-#define _XkbAllocOverlayRows(o,n) _XkbGeomAlloc((XPointer *)&(o)->rows,\
- &(o)->num_rows,&(o)->sz_rows,\
- (n),sizeof(XkbOverlayRowRec))
-#define _XkbAllocOverlayKeys(r,n) _XkbGeomAlloc((XPointer *)&(r)->keys,\
- &(r)->num_keys,&(r)->sz_keys,\
- (n),sizeof(XkbOverlayKeyRec))
-
-Status
-XkbAllocGeomProps(XkbGeometryPtr geom,int nProps)
-{
- return _XkbAllocProps(geom,nProps);
-}
-
-Status
-XkbAllocGeomColors(XkbGeometryPtr geom,int nColors)
-{
- return _XkbAllocColors(geom,nColors);
-}
-
-Status
-XkbAllocGeomKeyAliases(XkbGeometryPtr geom,int nKeyAliases)
-{
- return _XkbAllocKeyAliases(geom,nKeyAliases);
-}
-
-Status
-XkbAllocGeomShapes(XkbGeometryPtr geom,int nShapes)
-{
- return _XkbAllocShapes(geom,nShapes);
-}
-
-Status
-XkbAllocGeomSections(XkbGeometryPtr geom,int nSections)
-{
- return _XkbAllocSections(geom,nSections);
-}
-
-Status
-XkbAllocGeomOverlays(XkbSectionPtr section,int nOverlays)
-{
- return _XkbAllocOverlays(section,nOverlays);
-}
-
-Status
-XkbAllocGeomOverlayRows(XkbOverlayPtr overlay,int nRows)
-{
- return _XkbAllocOverlayRows(overlay,nRows);
-}
-
-Status
-XkbAllocGeomOverlayKeys(XkbOverlayRowPtr row,int nKeys)
-{
- return _XkbAllocOverlayKeys(row,nKeys);
-}
-
-Status
-XkbAllocGeomDoodads(XkbGeometryPtr geom,int nDoodads)
-{
- return _XkbAllocDoodads(geom,nDoodads);
-}
-
-Status
-XkbAllocGeomSectionDoodads(XkbSectionPtr section,int nDoodads)
-{
- return _XkbAllocDoodads(section,nDoodads);
-}
-
-Status
-XkbAllocGeomOutlines(XkbShapePtr shape,int nOL)
-{
- return _XkbAllocOutlines(shape,nOL);
-}
-
-Status
-XkbAllocGeomRows(XkbSectionPtr section,int nRows)
-{
- return _XkbAllocRows(section,nRows);
-}
-
-Status
-XkbAllocGeomPoints(XkbOutlinePtr ol,int nPts)
-{
- return _XkbAllocPoints(ol,nPts);
-}
-
-Status
-XkbAllocGeomKeys(XkbRowPtr row,int nKeys)
-{
- return _XkbAllocKeys(row,nKeys);
-}
-
-Status
-XkbAllocGeometry(XkbDescPtr xkb,XkbGeometrySizesPtr sizes)
-{
-XkbGeometryPtr geom;
-Status rtrn;
-
- if (xkb->geom==NULL) {
- xkb->geom= _XkbTypedCalloc(1,XkbGeometryRec);
- if (!xkb->geom)
- return BadAlloc;
- }
- geom= xkb->geom;
- if ((sizes->which&XkbGeomPropertiesMask)&&
- ((rtrn=_XkbAllocProps(geom,sizes->num_properties))!=Success)) {
- goto BAIL;
- }
- if ((sizes->which&XkbGeomColorsMask)&&
- ((rtrn=_XkbAllocColors(geom,sizes->num_colors))!=Success)) {
- goto BAIL;
- }
- if ((sizes->which&XkbGeomShapesMask)&&
- ((rtrn=_XkbAllocShapes(geom,sizes->num_shapes))!=Success)) {
- goto BAIL;
- }
- if ((sizes->which&XkbGeomSectionsMask)&&
- ((rtrn=_XkbAllocSections(geom,sizes->num_sections))!=Success)) {
- goto BAIL;
- }
- if ((sizes->which&XkbGeomDoodadsMask)&&
- ((rtrn=_XkbAllocDoodads(geom,sizes->num_doodads))!=Success)) {
- goto BAIL;
- }
- if ((sizes->which&XkbGeomKeyAliasesMask)&&
- ((rtrn=_XkbAllocKeyAliases(geom,sizes->num_key_aliases))!=Success)) {
- goto BAIL;
- }
- return Success;
-BAIL:
- XkbFreeGeometry(geom,XkbGeomAllMask,True);
- xkb->geom= NULL;
- return rtrn;
-}
-
-/***====================================================================***/
-
-XkbPropertyPtr
-XkbAddGeomProperty(XkbGeometryPtr geom,char *name,char *value)
-{
-register int i;
-register XkbPropertyPtr prop;
-
- if ((!geom)||(!name)||(!value))
- return NULL;
- for (i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) {
- if ((prop->name)&&(strcmp(name,prop->name)==0)) {
- if (prop->value)
- _XkbFree(prop->value);
- prop->value= strdup(value);
- return prop;
- }
- }
- if ((geom->num_properties>=geom->sz_properties)&&
- (_XkbAllocProps(geom,1)!=Success)) {
- return NULL;
- }
- prop= &geom->properties[geom->num_properties];
- prop->name= strdup(name);
- if (!prop->name)
- return NULL;
- prop->value= strdup(value);
- if (!prop->value) {
- _XkbFree(prop->name);
- prop->name= NULL;
- return NULL;
- }
- geom->num_properties++;
- return prop;
-}
-
-XkbKeyAliasPtr
-XkbAddGeomKeyAlias(XkbGeometryPtr geom,char *aliasStr,char *realStr)
-{
-register int i;
-register XkbKeyAliasPtr alias;
-
- if ((!geom)||(!aliasStr)||(!realStr)||(!aliasStr[0])||(!realStr[0]))
- return NULL;
- for (i=0,alias=geom->key_aliases;i<geom->num_key_aliases;i++,alias++) {
- if (strncmp(alias->alias,aliasStr,XkbKeyNameLength)==0) {
- bzero(alias->real,XkbKeyNameLength);
- strncpy(alias->real,realStr,XkbKeyNameLength);
- return alias;
- }
- }
- if ((geom->num_key_aliases>=geom->sz_key_aliases)&&
- (_XkbAllocKeyAliases(geom,1)!=Success)) {
- return NULL;
- }
- alias= &geom->key_aliases[geom->num_key_aliases];
- bzero(alias,sizeof(XkbKeyAliasRec));
- strncpy(alias->alias,aliasStr,XkbKeyNameLength);
- strncpy(alias->real,realStr,XkbKeyNameLength);
- geom->num_key_aliases++;
- return alias;
-}
-
-XkbColorPtr
-XkbAddGeomColor(XkbGeometryPtr geom,char *spec,unsigned int pixel)
-{
-register int i;
-register XkbColorPtr color;
-
- if ((!geom)||(!spec))
- return NULL;
- for (i=0,color=geom->colors;i<geom->num_colors;i++,color++) {
- if ((color->spec)&&(strcmp(color->spec,spec)==0)) {
- color->pixel= pixel;
- return color;
- }
- }
- if ((geom->num_colors>=geom->sz_colors)&&
- (_XkbAllocColors(geom,1)!=Success)) {
- return NULL;
- }
- color= &geom->colors[geom->num_colors];
- color->pixel= pixel;
- color->spec= strdup(spec);
- if (!color->spec)
- return NULL;
- geom->num_colors++;
- return color;
-}
-
-XkbOutlinePtr
-XkbAddGeomOutline(XkbShapePtr shape,int sz_points)
-{
-XkbOutlinePtr outline;
-
- if ((!shape)||(sz_points<0))
- return NULL;
- if ((shape->num_outlines>=shape->sz_outlines)&&
- (_XkbAllocOutlines(shape,1)!=Success)) {
- return NULL;
- }
- outline= &shape->outlines[shape->num_outlines];
- bzero(outline,sizeof(XkbOutlineRec));
- if ((sz_points>0)&&(_XkbAllocPoints(outline,sz_points)!=Success))
- return NULL;
- shape->num_outlines++;
- return outline;
-}
-
-XkbShapePtr
-XkbAddGeomShape(XkbGeometryPtr geom,Atom name,int sz_outlines)
-{
-XkbShapePtr shape;
-register int i;
-
- if ((!geom)||(!name)||(sz_outlines<0))
- return NULL;
- if (geom->num_shapes>0) {
- for (shape=geom->shapes,i=0;i<geom->num_shapes;i++,shape++) {
- if (name==shape->name)
- return shape;
- }
- }
- if ((geom->num_shapes>=geom->sz_shapes)&&
- (_XkbAllocShapes(geom,1)!=Success))
- return NULL;
- shape= &geom->shapes[geom->num_shapes];
- bzero(shape,sizeof(XkbShapeRec));
- if ((sz_outlines>0)&&(_XkbAllocOutlines(shape,sz_outlines)!=Success))
- return NULL;
- shape->name= name;
- shape->primary= shape->approx= NULL;
- geom->num_shapes++;
- return shape;
-}
-
-XkbKeyPtr
-XkbAddGeomKey(XkbRowPtr row)
-{
-XkbKeyPtr key;
- if (!row)
- return NULL;
- if ((row->num_keys>=row->sz_keys)&&(_XkbAllocKeys(row,1)!=Success))
- return NULL;
- key= &row->keys[row->num_keys++];
- bzero(key,sizeof(XkbKeyRec));
- return key;
-}
-
-XkbRowPtr
-XkbAddGeomRow(XkbSectionPtr section,int sz_keys)
-{
-XkbRowPtr row;
-
- if ((!section)||(sz_keys<0))
- return NULL;
- if ((section->num_rows>=section->sz_rows)&&
- (_XkbAllocRows(section,1)!=Success))
- return NULL;
- row= §ion->rows[section->num_rows];
- bzero(row,sizeof(XkbRowRec));
- if ((sz_keys>0)&&(_XkbAllocKeys(row,sz_keys)!=Success))
- return NULL;
- section->num_rows++;
- return row;
-}
-
-XkbSectionPtr
-XkbAddGeomSection( XkbGeometryPtr geom,
- Atom name,
- int sz_rows,
- int sz_doodads,
- int sz_over)
-{
-register int i;
-XkbSectionPtr section;
-
- if ((!geom)||(name==None)||(sz_rows<0))
- return NULL;
- for (i=0,section=geom->sections;i<geom->num_sections;i++,section++) {
- if (section->name!=name)
- continue;
- if (((sz_rows>0)&&(_XkbAllocRows(section,sz_rows)!=Success))||
- ((sz_doodads>0)&&(_XkbAllocDoodads(section,sz_doodads)!=Success))||
- ((sz_over>0)&&(_XkbAllocOverlays(section,sz_over)!=Success)))
- return NULL;
- return section;
- }
- if ((geom->num_sections>=geom->sz_sections)&&
- (_XkbAllocSections(geom,1)!=Success))
- return NULL;
- section= &geom->sections[geom->num_sections];
- if ((sz_rows>0)&&(_XkbAllocRows(section,sz_rows)!=Success))
- return NULL;
- if ((sz_doodads>0)&&(_XkbAllocDoodads(section,sz_doodads)!=Success)) {
- if (section->rows) {
- _XkbFree(section->rows);
- section->rows= NULL;
- section->sz_rows= section->num_rows= 0;
- }
- return NULL;
- }
- section->name= name;
- geom->num_sections++;
- return section;
-}
-
-XkbDoodadPtr
-XkbAddGeomDoodad(XkbGeometryPtr geom,XkbSectionPtr section,Atom name)
-{
-XkbDoodadPtr old,doodad;
-register int i,nDoodads;
-
- if ((!geom)||(name==None))
- return NULL;
- if ((section!=NULL)&&(section->num_doodads>0)) {
- old= section->doodads;
- nDoodads= section->num_doodads;
- }
- else {
- old= geom->doodads;
- nDoodads= geom->num_doodads;
- }
- for (i=0,doodad=old;i<nDoodads;i++,doodad++) {
- if (doodad->any.name==name)
- return doodad;
- }
- if (section) {
- if ((section->num_doodads>=geom->sz_doodads)&&
- (_XkbAllocDoodads(section,1)!=Success)) {
- return NULL;
- }
- doodad= §ion->doodads[section->num_doodads++];
- }
- else {
- if ((geom->num_doodads>=geom->sz_doodads)&&
- (_XkbAllocDoodads(geom,1)!=Success))
- return NULL;
- doodad= &geom->doodads[geom->num_doodads++];
- }
- bzero(doodad,sizeof(XkbDoodadRec));
- doodad->any.name= name;
- return doodad;
-}
-
-XkbOverlayKeyPtr
-XkbAddGeomOverlayKey( XkbOverlayPtr overlay,
- XkbOverlayRowPtr row,
- char * over,
- char * under)
-{
-register int i;
-XkbOverlayKeyPtr key;
-XkbSectionPtr section;
-XkbRowPtr row_under;
-Bool found;
-
- if ((!overlay)||(!row)||(!over)||(!under))
- return NULL;
- section= overlay->section_under;
- if (row->row_under>=section->num_rows)
- return NULL;
- row_under= §ion->rows[row->row_under];
- for (i=0,found=False;i<row_under->num_keys;i++) {
- if (strncmp(under,row_under->keys[i].name.name,XkbKeyNameLength)==0) {
- found= True;
- break;
- }
- }
- if (!found)
- return NULL;
- if ((row->num_keys>=row->sz_keys)&&(_XkbAllocOverlayKeys(row,1)!=Success))
- return NULL;
- key= &row->keys[row->num_keys];
- strncpy(key->under.name,under,XkbKeyNameLength);
- strncpy(key->over.name,over,XkbKeyNameLength);
- row->num_keys++;
- return key;
-}
-
-XkbOverlayRowPtr
-XkbAddGeomOverlayRow(XkbOverlayPtr overlay,int row_under,int sz_keys)
-{
-register int i;
-XkbOverlayRowPtr row;
-
- if ((!overlay)||(sz_keys<0))
- return NULL;
- if (row_under>=overlay->section_under->num_rows)
- return NULL;
- for (i=0;i<overlay->num_rows;i++) {
- if (overlay->rows[i].row_under==row_under) {
- row= &overlay->rows[i];
- if ((row->sz_keys<sz_keys)&&
- (_XkbAllocOverlayKeys(row,sz_keys)!=Success)) {
- return NULL;
- }
- return &overlay->rows[i];
- }
- }
- if ((overlay->num_rows>=overlay->sz_rows)&&
- (_XkbAllocOverlayRows(overlay,1)!=Success))
- return NULL;
- row= &overlay->rows[overlay->num_rows];
- bzero(row,sizeof(XkbOverlayRowRec));
- if ((sz_keys>0)&&(_XkbAllocOverlayKeys(row,sz_keys)!=Success))
- return NULL;
- row->row_under= row_under;
- overlay->num_rows++;
- return row;
-}
-
-XkbOverlayPtr
-XkbAddGeomOverlay(XkbSectionPtr section,Atom name,int sz_rows)
-{
-register int i;
-XkbOverlayPtr overlay;
-
- if ((!section)||(name==None)||(sz_rows==0))
- return NULL;
-
- for (i=0,overlay=section->overlays;i<section->num_overlays;i++,overlay++) {
- if (overlay->name==name) {
- if ((sz_rows>0)&&(_XkbAllocOverlayRows(overlay,sz_rows)!=Success))
- return NULL;
- return overlay;
- }
- }
- if ((section->num_overlays>=section->sz_overlays)&&
- (_XkbAllocOverlays(section,1)!=Success))
- return NULL;
- overlay= §ion->overlays[section->num_overlays];
- if ((sz_rows>0)&&(_XkbAllocOverlayRows(overlay,sz_rows)!=Success))
- return NULL;
- overlay->name= name;
- overlay->section_under= section;
- section->num_overlays++;
- return overlay;
-}
+/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, 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 Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS 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 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH +THE USE OR PERFORMANCE OF THIS SOFTWARE. + +********************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#elif defined(HAVE_CONFIG_H) +#include <config.h> +#endif + +#include <stdio.h> +#include <unistd.h> + +#ifndef XKB_IN_SERVER + +#include "Xlibint.h" +#include "XKBlibint.h" +#include <X11/extensions/XKBgeom.h> +#include <X11/extensions/XKBproto.h> + +#else + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "inputstr.h" +#include <X11/extensions/XKBsrv.h> +#include <X11/extensions/XKBgeom.h> + +#endif /* XKB_IN_SERVER */ + +#ifdef X_NOT_POSIX +#define Size_t unsigned int +#else +#define Size_t size_t +#endif + +/***====================================================================***/ + +static void +_XkbFreeGeomLeafElems( Bool freeAll, + int first, + int count, + unsigned short * num_inout, + unsigned short * sz_inout, + char ** elems, + unsigned int elem_sz) +{ + if ((freeAll)||(*elems==NULL)) { + *num_inout= *sz_inout= 0; + if (*elems!=NULL) { + _XkbFree(*elems); + *elems= NULL; + } + return; + } + + if ((first>=(*num_inout))||(first<0)||(count<1)) + return; + + if (first+count>=(*num_inout)) { + /* truncating the array is easy */ + (*num_inout)= first; + } + else { + char * ptr; + int extra; + ptr= *elems; + extra= ((*num_inout)-(first+count))*elem_sz; + if (extra>0) + memmove(&ptr[first*elem_sz],&ptr[(first+count)*elem_sz],extra); + (*num_inout)-= count; + } + return; +} + +typedef void (*ContentsClearFunc)( + char * /* priv */ +); + +static void +_XkbFreeGeomNonLeafElems( Bool freeAll, + int first, + int count, + unsigned short * num_inout, + unsigned short * sz_inout, + char ** elems, + unsigned int elem_sz, + ContentsClearFunc freeFunc) +{ +register int i; +register char *ptr; + + if (freeAll) { + first= 0; + count= (*num_inout); + } + else if ((first>=(*num_inout))||(first<0)||(count<1)) + return; + else if (first+count>(*num_inout)) + count= (*num_inout)-first; + if (*elems==NULL) + return; + + if (freeFunc) { + ptr= *elems; + ptr+= first*elem_sz; + for (i=0;i<count;i++) { + (*freeFunc)(ptr); + ptr+= elem_sz; + } + } + if (freeAll) { + (*num_inout)= (*sz_inout)= 0; + if (*elems) { + _XkbFree(*elems); + *elems= NULL; + } + } + else if (first+count>=(*num_inout)) + *num_inout= first; + else { + i= ((*num_inout)-(first+count))*elem_sz; + ptr= *elems; + memmove(&ptr[first*elem_sz],&ptr[(first+count)*elem_sz],i); + (*num_inout)-= count; + } + return; +} + +/***====================================================================***/ + +static void +_XkbClearProperty(char *prop_in) +{ +XkbPropertyPtr prop= (XkbPropertyPtr)prop_in; + + if (prop->name) { + _XkbFree(prop->name); + prop->name= NULL; + } + if (prop->value) { + _XkbFree(prop->value); + prop->value= NULL; + } + return; +} + +void +XkbFreeGeomProperties( XkbGeometryPtr geom, + int first, + int count, + Bool freeAll) +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + &geom->num_properties,&geom->sz_properties, + (char **)&geom->properties, + sizeof(XkbPropertyRec),_XkbClearProperty); + return; +} + +/***====================================================================***/ + +void +XkbFreeGeomKeyAliases( XkbGeometryPtr geom, + int first, + int count, + Bool freeAll) +{ + _XkbFreeGeomLeafElems(freeAll,first,count, + &geom->num_key_aliases,&geom->sz_key_aliases, + (char **)&geom->key_aliases, + sizeof(XkbKeyAliasRec)); + return; +} + +/***====================================================================***/ + +static void +_XkbClearColor(char *color_in) +{ +XkbColorPtr color= (XkbColorPtr)color_in; + + if (color->spec) + _XkbFree(color->spec); + return; +} + +void +XkbFreeGeomColors(XkbGeometryPtr geom,int first,int count,Bool freeAll) +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + &geom->num_colors,&geom->sz_colors, + (char **)&geom->colors, + sizeof(XkbColorRec),_XkbClearColor); + return; +} + +/***====================================================================***/ + +void +XkbFreeGeomPoints(XkbOutlinePtr outline,int first,int count,Bool freeAll) +{ + _XkbFreeGeomLeafElems(freeAll,first,count, + &outline->num_points,&outline->sz_points, + (char **)&outline->points, + sizeof(XkbPointRec)); + return; +} + +/***====================================================================***/ + +static void +_XkbClearOutline(char *outline_in) +{ +XkbOutlinePtr outline= (XkbOutlinePtr)outline_in; + + if (outline->points!=NULL) + XkbFreeGeomPoints(outline,0,outline->num_points,True); + return; +} + +void +XkbFreeGeomOutlines(XkbShapePtr shape,int first,int count,Bool freeAll) +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + &shape->num_outlines,&shape->sz_outlines, + (char **)&shape->outlines, + sizeof(XkbOutlineRec),_XkbClearOutline); + + return; +} + +/***====================================================================***/ + +static void +_XkbClearShape(char *shape_in) +{ +XkbShapePtr shape= (XkbShapePtr)shape_in; + + if (shape->outlines) + XkbFreeGeomOutlines(shape,0,shape->num_outlines,True); + return; +} + +void +XkbFreeGeomShapes(XkbGeometryPtr geom,int first,int count,Bool freeAll) +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + &geom->num_shapes,&geom->sz_shapes, + (char **)&geom->shapes, + sizeof(XkbShapeRec),_XkbClearShape); + return; +} + +/***====================================================================***/ + +void +XkbFreeGeomOverlayKeys(XkbOverlayRowPtr row,int first,int count,Bool freeAll) +{ + _XkbFreeGeomLeafElems(freeAll,first,count, + &row->num_keys,&row->sz_keys, + (char **)&row->keys, + sizeof(XkbOverlayKeyRec)); + return; +} + +/***====================================================================***/ + +static void +_XkbClearOverlayRow(char *row_in) +{ +XkbOverlayRowPtr row= (XkbOverlayRowPtr)row_in; + + if (row->keys!=NULL) + XkbFreeGeomOverlayKeys(row,0,row->num_keys,True); + return; +} + +void +XkbFreeGeomOverlayRows(XkbOverlayPtr overlay,int first,int count,Bool freeAll) +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + &overlay->num_rows,&overlay->sz_rows, + (char **)&overlay->rows, + sizeof(XkbOverlayRowRec),_XkbClearOverlayRow); + return; +} + +/***====================================================================***/ + +static void +_XkbClearOverlay(char *overlay_in) +{ +XkbOverlayPtr overlay= (XkbOverlayPtr)overlay_in; + + if (overlay->rows!=NULL) + XkbFreeGeomOverlayRows(overlay,0,overlay->num_rows,True); + return; +} + +void +XkbFreeGeomOverlays(XkbSectionPtr section,int first,int count,Bool freeAll) +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + §ion->num_overlays,§ion->sz_overlays, + (char **)§ion->overlays, + sizeof(XkbOverlayRec),_XkbClearOverlay); + return; +} + +/***====================================================================***/ + +void +XkbFreeGeomKeys(XkbRowPtr row,int first,int count,Bool freeAll) +{ + _XkbFreeGeomLeafElems(freeAll,first,count, + &row->num_keys,&row->sz_keys, + (char **)&row->keys, + sizeof(XkbKeyRec)); + return; +} + +/***====================================================================***/ + +static void +_XkbClearRow(char *row_in) +{ +XkbRowPtr row= (XkbRowPtr)row_in; + + if (row->keys!=NULL) + XkbFreeGeomKeys(row,0,row->num_keys,True); + return; +} + +void +XkbFreeGeomRows(XkbSectionPtr section,int first,int count,Bool freeAll) +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + §ion->num_rows,§ion->sz_rows, + (char **)§ion->rows, + sizeof(XkbRowRec),_XkbClearRow); +} + +/***====================================================================***/ + +static void +_XkbClearSection(char *section_in) +{ +XkbSectionPtr section= (XkbSectionPtr)section_in; + + if (section->rows!=NULL) + XkbFreeGeomRows(section,0,section->num_rows,True); + if (section->doodads!=NULL) { + XkbFreeGeomDoodads(section->doodads,section->num_doodads,True); + section->doodads= NULL; + } + return; +} + +void +XkbFreeGeomSections(XkbGeometryPtr geom,int first,int count,Bool freeAll) +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + &geom->num_sections,&geom->sz_sections, + (char **)&geom->sections, + sizeof(XkbSectionRec),_XkbClearSection); + return; +} + +/***====================================================================***/ + +static void +_XkbClearDoodad(char *doodad_in) +{ +XkbDoodadPtr doodad= (XkbDoodadPtr)doodad_in; + + switch (doodad->any.type) { + case XkbTextDoodad: + { + if (doodad->text.text!=NULL) { + _XkbFree(doodad->text.text); + doodad->text.text= NULL; + } + if (doodad->text.font!=NULL) { + _XkbFree(doodad->text.font); + doodad->text.font= NULL; + } + } + break; + case XkbLogoDoodad: + { + if (doodad->logo.logo_name!=NULL) { + _XkbFree(doodad->logo.logo_name); + doodad->logo.logo_name= NULL; + } + } + break; + } + return; +} + +void +XkbFreeGeomDoodads(XkbDoodadPtr doodads,int nDoodads,Bool freeAll) +{ +register int i; +register XkbDoodadPtr doodad; + + if (doodads) { + for (i=0,doodad= doodads;i<nDoodads;i++,doodad++) { + _XkbClearDoodad((char *)doodad); + } + if (freeAll) + _XkbFree(doodads); + } + return; +} + +void +XkbFreeGeometry(XkbGeometryPtr geom,unsigned which,Bool freeMap) +{ + if (geom==NULL) + return; + if (freeMap) + which= XkbGeomAllMask; + if ((which&XkbGeomPropertiesMask)&&(geom->properties!=NULL)) + XkbFreeGeomProperties(geom,0,geom->num_properties,True); + if ((which&XkbGeomColorsMask)&&(geom->colors!=NULL)) + XkbFreeGeomColors(geom,0,geom->num_colors,True); + if ((which&XkbGeomShapesMask)&&(geom->shapes!=NULL)) + XkbFreeGeomShapes(geom,0,geom->num_shapes,True); + if ((which&XkbGeomSectionsMask)&&(geom->sections!=NULL)) + XkbFreeGeomSections(geom,0,geom->num_sections,True); + if ((which&XkbGeomDoodadsMask)&&(geom->doodads!= NULL)) { + XkbFreeGeomDoodads(geom->doodads,geom->num_doodads,True); + geom->doodads= NULL; + geom->num_doodads= geom->sz_doodads= 0; + } + if ((which&XkbGeomKeyAliasesMask)&&(geom->key_aliases!=NULL)) + XkbFreeGeomKeyAliases(geom,0,geom->num_key_aliases,True); + if (freeMap) { + if (geom->label_font!=NULL) { + _XkbFree(geom->label_font); + geom->label_font= NULL; + } + _XkbFree(geom); + } + return; +} + +/***====================================================================***/ + +static Status +_XkbGeomAlloc( XPointer * old, + unsigned short * num, + unsigned short * total, + int num_new, + Size_t sz_elem) +{ + if (num_new<1) + return Success; + if ((*old)==NULL) + *num= *total= 0; + + if ((*num)+num_new<=(*total)) + return Success; + + *total= (*num)+num_new; + if ((*old)!=NULL) + (*old)= (XPointer)_XkbRealloc((*old),(*total)*sz_elem); + else (*old)= (XPointer)_XkbCalloc((*total),sz_elem); + if ((*old)==NULL) { + *total= *num= 0; + return BadAlloc; + } + + if (*num>0) { + char *tmp= (char *)(*old); + bzero(&tmp[sz_elem*(*num)],(num_new*sz_elem)); + } + return Success; +} + +#define _XkbAllocProps(g,n) _XkbGeomAlloc((XPointer *)&(g)->properties,\ + &(g)->num_properties,&(g)->sz_properties,\ + (n),sizeof(XkbPropertyRec)) +#define _XkbAllocColors(g,n) _XkbGeomAlloc((XPointer *)&(g)->colors,\ + &(g)->num_colors,&(g)->sz_colors,\ + (n),sizeof(XkbColorRec)) +#define _XkbAllocShapes(g,n) _XkbGeomAlloc((XPointer *)&(g)->shapes,\ + &(g)->num_shapes,&(g)->sz_shapes,\ + (n),sizeof(XkbShapeRec)) +#define _XkbAllocSections(g,n) _XkbGeomAlloc((XPointer *)&(g)->sections,\ + &(g)->num_sections,&(g)->sz_sections,\ + (n),sizeof(XkbSectionRec)) +#define _XkbAllocDoodads(g,n) _XkbGeomAlloc((XPointer *)&(g)->doodads,\ + &(g)->num_doodads,&(g)->sz_doodads,\ + (n),sizeof(XkbDoodadRec)) +#define _XkbAllocKeyAliases(g,n) _XkbGeomAlloc((XPointer *)&(g)->key_aliases,\ + &(g)->num_key_aliases,&(g)->sz_key_aliases,\ + (n),sizeof(XkbKeyAliasRec)) + +#define _XkbAllocOutlines(s,n) _XkbGeomAlloc((XPointer *)&(s)->outlines,\ + &(s)->num_outlines,&(s)->sz_outlines,\ + (n),sizeof(XkbOutlineRec)) +#define _XkbAllocRows(s,n) _XkbGeomAlloc((XPointer *)&(s)->rows,\ + &(s)->num_rows,&(s)->sz_rows,\ + (n),sizeof(XkbRowRec)) +#define _XkbAllocPoints(o,n) _XkbGeomAlloc((XPointer *)&(o)->points,\ + &(o)->num_points,&(o)->sz_points,\ + (n),sizeof(XkbPointRec)) +#define _XkbAllocKeys(r,n) _XkbGeomAlloc((XPointer *)&(r)->keys,\ + &(r)->num_keys,&(r)->sz_keys,\ + (n),sizeof(XkbKeyRec)) +#define _XkbAllocOverlays(s,n) _XkbGeomAlloc((XPointer *)&(s)->overlays,\ + &(s)->num_overlays,&(s)->sz_overlays,\ + (n),sizeof(XkbOverlayRec)) +#define _XkbAllocOverlayRows(o,n) _XkbGeomAlloc((XPointer *)&(o)->rows,\ + &(o)->num_rows,&(o)->sz_rows,\ + (n),sizeof(XkbOverlayRowRec)) +#define _XkbAllocOverlayKeys(r,n) _XkbGeomAlloc((XPointer *)&(r)->keys,\ + &(r)->num_keys,&(r)->sz_keys,\ + (n),sizeof(XkbOverlayKeyRec)) + +Status +XkbAllocGeomProps(XkbGeometryPtr geom,int nProps) +{ + return _XkbAllocProps(geom,nProps); +} + +Status +XkbAllocGeomColors(XkbGeometryPtr geom,int nColors) +{ + return _XkbAllocColors(geom,nColors); +} + +Status +XkbAllocGeomKeyAliases(XkbGeometryPtr geom,int nKeyAliases) +{ + return _XkbAllocKeyAliases(geom,nKeyAliases); +} + +Status +XkbAllocGeomShapes(XkbGeometryPtr geom,int nShapes) +{ + return _XkbAllocShapes(geom,nShapes); +} + +Status +XkbAllocGeomSections(XkbGeometryPtr geom,int nSections) +{ + return _XkbAllocSections(geom,nSections); +} + +Status +XkbAllocGeomOverlays(XkbSectionPtr section,int nOverlays) +{ + return _XkbAllocOverlays(section,nOverlays); +} + +Status +XkbAllocGeomOverlayRows(XkbOverlayPtr overlay,int nRows) +{ + return _XkbAllocOverlayRows(overlay,nRows); +} + +Status +XkbAllocGeomOverlayKeys(XkbOverlayRowPtr row,int nKeys) +{ + return _XkbAllocOverlayKeys(row,nKeys); +} + +Status +XkbAllocGeomDoodads(XkbGeometryPtr geom,int nDoodads) +{ + return _XkbAllocDoodads(geom,nDoodads); +} + +Status +XkbAllocGeomSectionDoodads(XkbSectionPtr section,int nDoodads) +{ + return _XkbAllocDoodads(section,nDoodads); +} + +Status +XkbAllocGeomOutlines(XkbShapePtr shape,int nOL) +{ + return _XkbAllocOutlines(shape,nOL); +} + +Status +XkbAllocGeomRows(XkbSectionPtr section,int nRows) +{ + return _XkbAllocRows(section,nRows); +} + +Status +XkbAllocGeomPoints(XkbOutlinePtr ol,int nPts) +{ + return _XkbAllocPoints(ol,nPts); +} + +Status +XkbAllocGeomKeys(XkbRowPtr row,int nKeys) +{ + return _XkbAllocKeys(row,nKeys); +} + +Status +XkbAllocGeometry(XkbDescPtr xkb,XkbGeometrySizesPtr sizes) +{ +XkbGeometryPtr geom; +Status rtrn; + + if (xkb->geom==NULL) { + xkb->geom= _XkbTypedCalloc(1,XkbGeometryRec); + if (!xkb->geom) + return BadAlloc; + } + geom= xkb->geom; + if ((sizes->which&XkbGeomPropertiesMask)&& + ((rtrn=_XkbAllocProps(geom,sizes->num_properties))!=Success)) { + goto BAIL; + } + if ((sizes->which&XkbGeomColorsMask)&& + ((rtrn=_XkbAllocColors(geom,sizes->num_colors))!=Success)) { + goto BAIL; + } + if ((sizes->which&XkbGeomShapesMask)&& + ((rtrn=_XkbAllocShapes(geom,sizes->num_shapes))!=Success)) { + goto BAIL; + } + if ((sizes->which&XkbGeomSectionsMask)&& + ((rtrn=_XkbAllocSections(geom,sizes->num_sections))!=Success)) { + goto BAIL; + } + if ((sizes->which&XkbGeomDoodadsMask)&& + ((rtrn=_XkbAllocDoodads(geom,sizes->num_doodads))!=Success)) { + goto BAIL; + } + if ((sizes->which&XkbGeomKeyAliasesMask)&& + ((rtrn=_XkbAllocKeyAliases(geom,sizes->num_key_aliases))!=Success)) { + goto BAIL; + } + return Success; +BAIL: + XkbFreeGeometry(geom,XkbGeomAllMask,True); + xkb->geom= NULL; + return rtrn; +} + +/***====================================================================***/ + +XkbPropertyPtr +XkbAddGeomProperty(XkbGeometryPtr geom,char *name,char *value) +{ +register int i; +register XkbPropertyPtr prop; + + if ((!geom)||(!name)||(!value)) + return NULL; + for (i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) { + if ((prop->name)&&(strcmp(name,prop->name)==0)) { + if (prop->value) + _XkbFree(prop->value); + prop->value= strdup(value); + return prop; + } + } + if ((geom->num_properties>=geom->sz_properties)&& + (_XkbAllocProps(geom,1)!=Success)) { + return NULL; + } + prop= &geom->properties[geom->num_properties]; + prop->name= strdup(name); + if (!prop->name) + return NULL; + prop->value= strdup(value); + if (!prop->value) { + _XkbFree(prop->name); + prop->name= NULL; + return NULL; + } + geom->num_properties++; + return prop; +} + +XkbKeyAliasPtr +XkbAddGeomKeyAlias(XkbGeometryPtr geom,char *aliasStr,char *realStr) +{ +register int i; +register XkbKeyAliasPtr alias; + + if ((!geom)||(!aliasStr)||(!realStr)||(!aliasStr[0])||(!realStr[0])) + return NULL; + for (i=0,alias=geom->key_aliases;i<geom->num_key_aliases;i++,alias++) { + if (strncmp(alias->alias,aliasStr,XkbKeyNameLength)==0) { + bzero(alias->real,XkbKeyNameLength); + strncpy(alias->real,realStr,XkbKeyNameLength); + return alias; + } + } + if ((geom->num_key_aliases>=geom->sz_key_aliases)&& + (_XkbAllocKeyAliases(geom,1)!=Success)) { + return NULL; + } + alias= &geom->key_aliases[geom->num_key_aliases]; + bzero(alias,sizeof(XkbKeyAliasRec)); + strncpy(alias->alias,aliasStr,XkbKeyNameLength); + strncpy(alias->real,realStr,XkbKeyNameLength); + geom->num_key_aliases++; + return alias; +} + +XkbColorPtr +XkbAddGeomColor(XkbGeometryPtr geom,char *spec,unsigned int pixel) +{ +register int i; +register XkbColorPtr color; + + if ((!geom)||(!spec)) + return NULL; + for (i=0,color=geom->colors;i<geom->num_colors;i++,color++) { + if ((color->spec)&&(strcmp(color->spec,spec)==0)) { + color->pixel= pixel; + return color; + } + } + if ((geom->num_colors>=geom->sz_colors)&& + (_XkbAllocColors(geom,1)!=Success)) { + return NULL; + } + color= &geom->colors[geom->num_colors]; + color->pixel= pixel; + color->spec= strdup(spec); + if (!color->spec) + return NULL; + geom->num_colors++; + return color; +} + +XkbOutlinePtr +XkbAddGeomOutline(XkbShapePtr shape,int sz_points) +{ +XkbOutlinePtr outline; + + if ((!shape)||(sz_points<0)) + return NULL; + if ((shape->num_outlines>=shape->sz_outlines)&& + (_XkbAllocOutlines(shape,1)!=Success)) { + return NULL; + } + outline= &shape->outlines[shape->num_outlines]; + bzero(outline,sizeof(XkbOutlineRec)); + if ((sz_points>0)&&(_XkbAllocPoints(outline,sz_points)!=Success)) + return NULL; + shape->num_outlines++; + return outline; +} + +XkbShapePtr +XkbAddGeomShape(XkbGeometryPtr geom,Atom name,int sz_outlines) +{ +XkbShapePtr shape; +register int i; + + if ((!geom)||(!name)||(sz_outlines<0)) + return NULL; + if (geom->num_shapes>0) { + for (shape=geom->shapes,i=0;i<geom->num_shapes;i++,shape++) { + if (name==shape->name) + return shape; + } + } + if ((geom->num_shapes>=geom->sz_shapes)&& + (_XkbAllocShapes(geom,1)!=Success)) + return NULL; + shape= &geom->shapes[geom->num_shapes]; + bzero(shape,sizeof(XkbShapeRec)); + if ((sz_outlines>0)&&(_XkbAllocOutlines(shape,sz_outlines)!=Success)) + return NULL; + shape->name= name; + shape->primary= shape->approx= NULL; + geom->num_shapes++; + return shape; +} + +XkbKeyPtr +XkbAddGeomKey(XkbRowPtr row) +{ +XkbKeyPtr key; + if (!row) + return NULL; + if ((row->num_keys>=row->sz_keys)&&(_XkbAllocKeys(row,1)!=Success)) + return NULL; + key= &row->keys[row->num_keys++]; + bzero(key,sizeof(XkbKeyRec)); + return key; +} + +XkbRowPtr +XkbAddGeomRow(XkbSectionPtr section,int sz_keys) +{ +XkbRowPtr row; + + if ((!section)||(sz_keys<0)) + return NULL; + if ((section->num_rows>=section->sz_rows)&& + (_XkbAllocRows(section,1)!=Success)) + return NULL; + row= §ion->rows[section->num_rows]; + bzero(row,sizeof(XkbRowRec)); + if ((sz_keys>0)&&(_XkbAllocKeys(row,sz_keys)!=Success)) + return NULL; + section->num_rows++; + return row; +} + +XkbSectionPtr +XkbAddGeomSection( XkbGeometryPtr geom, + Atom name, + int sz_rows, + int sz_doodads, + int sz_over) +{ +register int i; +XkbSectionPtr section; + + if ((!geom)||(name==None)||(sz_rows<0)) + return NULL; + for (i=0,section=geom->sections;i<geom->num_sections;i++,section++) { + if (section->name!=name) + continue; + if (((sz_rows>0)&&(_XkbAllocRows(section,sz_rows)!=Success))|| + ((sz_doodads>0)&&(_XkbAllocDoodads(section,sz_doodads)!=Success))|| + ((sz_over>0)&&(_XkbAllocOverlays(section,sz_over)!=Success))) + return NULL; + return section; + } + if ((geom->num_sections>=geom->sz_sections)&& + (_XkbAllocSections(geom,1)!=Success)) + return NULL; + section= &geom->sections[geom->num_sections]; + if ((sz_rows>0)&&(_XkbAllocRows(section,sz_rows)!=Success)) + return NULL; + if ((sz_doodads>0)&&(_XkbAllocDoodads(section,sz_doodads)!=Success)) { + if (section->rows) { + _XkbFree(section->rows); + section->rows= NULL; + section->sz_rows= section->num_rows= 0; + } + return NULL; + } + section->name= name; + geom->num_sections++; + return section; +} + +XkbDoodadPtr +XkbAddGeomDoodad(XkbGeometryPtr geom,XkbSectionPtr section,Atom name) +{ +XkbDoodadPtr old,doodad; +register int i,nDoodads; + + if ((!geom)||(name==None)) + return NULL; + if ((section!=NULL)&&(section->num_doodads>0)) { + old= section->doodads; + nDoodads= section->num_doodads; + } + else { + old= geom->doodads; + nDoodads= geom->num_doodads; + } + for (i=0,doodad=old;i<nDoodads;i++,doodad++) { + if (doodad->any.name==name) + return doodad; + } + if (section) { + if ((section->num_doodads>=geom->sz_doodads)&& + (_XkbAllocDoodads(section,1)!=Success)) { + return NULL; + } + doodad= §ion->doodads[section->num_doodads++]; + } + else { + if ((geom->num_doodads>=geom->sz_doodads)&& + (_XkbAllocDoodads(geom,1)!=Success)) + return NULL; + doodad= &geom->doodads[geom->num_doodads++]; + } + bzero(doodad,sizeof(XkbDoodadRec)); + doodad->any.name= name; + return doodad; +} + +XkbOverlayKeyPtr +XkbAddGeomOverlayKey( XkbOverlayPtr overlay, + XkbOverlayRowPtr row, + char * over, + char * under) +{ +register int i; +XkbOverlayKeyPtr key; +XkbSectionPtr section; +XkbRowPtr row_under; +Bool found; + + if ((!overlay)||(!row)||(!over)||(!under)) + return NULL; + section= overlay->section_under; + if (row->row_under>=section->num_rows) + return NULL; + row_under= §ion->rows[row->row_under]; + for (i=0,found=False;i<row_under->num_keys;i++) { + if (strncmp(under,row_under->keys[i].name.name,XkbKeyNameLength)==0) { + found= True; + break; + } + } + if (!found) + return NULL; + if ((row->num_keys>=row->sz_keys)&&(_XkbAllocOverlayKeys(row,1)!=Success)) + return NULL; + key= &row->keys[row->num_keys]; + strncpy(key->under.name,under,XkbKeyNameLength); + strncpy(key->over.name,over,XkbKeyNameLength); + row->num_keys++; + return key; +} + +XkbOverlayRowPtr +XkbAddGeomOverlayRow(XkbOverlayPtr overlay,int row_under,int sz_keys) +{ +register int i; +XkbOverlayRowPtr row; + + if ((!overlay)||(sz_keys<0)) + return NULL; + if (row_under>=overlay->section_under->num_rows) + return NULL; + for (i=0;i<overlay->num_rows;i++) { + if (overlay->rows[i].row_under==row_under) { + row= &overlay->rows[i]; + if ((row->sz_keys<sz_keys)&& + (_XkbAllocOverlayKeys(row,sz_keys)!=Success)) { + return NULL; + } + return &overlay->rows[i]; + } + } + if ((overlay->num_rows>=overlay->sz_rows)&& + (_XkbAllocOverlayRows(overlay,1)!=Success)) + return NULL; + row= &overlay->rows[overlay->num_rows]; + bzero(row,sizeof(XkbOverlayRowRec)); + if ((sz_keys>0)&&(_XkbAllocOverlayKeys(row,sz_keys)!=Success)) + return NULL; + row->row_under= row_under; + overlay->num_rows++; + return row; +} + +XkbOverlayPtr +XkbAddGeomOverlay(XkbSectionPtr section,Atom name,int sz_rows) +{ +register int i; +XkbOverlayPtr overlay; + + if ((!section)||(name==None)||(sz_rows==0)) + return NULL; + + for (i=0,overlay=section->overlays;i<section->num_overlays;i++,overlay++) { + if (overlay->name==name) { + if ((sz_rows>0)&&(_XkbAllocOverlayRows(overlay,sz_rows)!=Success)) + return NULL; + return overlay; + } + } + if ((section->num_overlays>=section->sz_overlays)&& + (_XkbAllocOverlays(section,1)!=Success)) + return NULL; + overlay= §ion->overlays[section->num_overlays]; + if ((sz_rows>0)&&(_XkbAllocOverlayRows(overlay,sz_rows)!=Success)) + return NULL; + overlay->name= name; + overlay->section_under= section; + section->num_overlays++; + return overlay; +} diff --git a/libX11/src/xkb/XKBGeom.c b/libX11/src/xkb/XKBGeom.c index d8fe3ce32..283bc6426 100644 --- a/libX11/src/xkb/XKBGeom.c +++ b/libX11/src/xkb/XKBGeom.c @@ -1,688 +1,688 @@ -/************************************************************
-Copyright (c) 1993 by Silicon Graphics Computer Systems, 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 Silicon Graphics not be
-used in advertising or publicity pertaining to distribution
-of the software without specific prior written permission.
-Silicon Graphics makes no representation about the suitability
-of this software for any purpose. It is provided "as is"
-without any express or implied warranty.
-
-SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
-SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
-GRAPHICS 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 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
-THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-********************************************************/
-
-#ifdef DEBUG
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#endif
-
-#define NEED_MAP_READERS
-#include "Xlibint.h"
-#include <X11/extensions/XKBgeom.h>
-#include <X11/extensions/XKBproto.h>
-#include "XKBlibint.h"
-
-#define MINSHORT -32768
-#define MAXSHORT 32767
-
-/***====================================================================***/
-
-static void
-_XkbCheckBounds(XkbBoundsPtr bounds,int x,int y)
-{
- if (x<bounds->x1) bounds->x1= x;
- if (x>bounds->x2) bounds->x2= x;
- if (y<bounds->y1) bounds->y1= y;
- if (y>bounds->y2) bounds->y2= y;
- return;
-}
-
-Bool
-XkbComputeShapeBounds(XkbShapePtr shape)
-{
-register int o,p;
-XkbOutlinePtr outline;
-XkbPointPtr pt;
-
- if ((!shape)||(shape->num_outlines<1))
- return False;
- shape->bounds.x1= shape->bounds.y1= MAXSHORT;
- shape->bounds.x2= shape->bounds.y2= MINSHORT;
- for (outline=shape->outlines,o=0;o<shape->num_outlines;o++,outline++) {
- for (pt=outline->points,p=0;p<outline->num_points;p++,pt++) {
- _XkbCheckBounds(&shape->bounds,pt->x,pt->y);
- }
- if (outline->num_points<2) {
- _XkbCheckBounds(&shape->bounds,0,0);
- }
- }
- return True;
-}
-
-Bool
-XkbComputeShapeTop(XkbShapePtr shape,XkbBoundsPtr bounds)
-{
-register int p;
-XkbOutlinePtr outline;
-XkbPointPtr pt;
-
- if ((!shape)||(shape->num_outlines<1))
- return False;
- if (shape->approx) outline= shape->approx;
- else outline= &shape->outlines[shape->num_outlines-1];
- if (outline->num_points<2) {
- bounds->x1= bounds->y1= 0;
- bounds->x2= bounds->y2= 0;
- }
- else {
- bounds->x1= bounds->y1= MAXSHORT;
- bounds->x2= bounds->y2= MINSHORT;
- }
- for (pt=outline->points,p=0;p<outline->num_points;p++,pt++) {
- _XkbCheckBounds(bounds,pt->x,pt->y);
- }
- return True;
-}
-
-Bool
-XkbComputeRowBounds(XkbGeometryPtr geom,XkbSectionPtr section,XkbRowPtr row)
-{
-register int k,pos;
-XkbKeyPtr key;
-XkbBoundsPtr bounds,sbounds;
-
- if ((!geom)||(!section)||(!row))
- return False;
- bounds= &row->bounds;
- bzero(bounds,sizeof(XkbBoundsRec));
- for (key=row->keys,pos=k=0;k<row->num_keys;k++,key++) {
- sbounds= &XkbKeyShape(geom,key)->bounds;
- _XkbCheckBounds(bounds,pos,0);
- if (!row->vertical) {
- if (key->gap!=0) {
- pos+= key->gap;
- _XkbCheckBounds(bounds,pos,0);
- }
- _XkbCheckBounds(bounds,pos+sbounds->x1,sbounds->y1);
- _XkbCheckBounds(bounds,pos+sbounds->x2,sbounds->y2);
- pos+= sbounds->x2;
- }
- else {
- if (key->gap!=0) {
- pos+= key->gap;
- _XkbCheckBounds(bounds,0,pos);
- }
- _XkbCheckBounds(bounds,pos+sbounds->x1,sbounds->y1);
- _XkbCheckBounds(bounds,pos+sbounds->x2,sbounds->y2);
- pos+= sbounds->y2;
- }
- }
- return True;
-}
-
-Bool
-XkbComputeSectionBounds(XkbGeometryPtr geom,XkbSectionPtr section)
-{
-register int i;
-XkbShapePtr shape;
-XkbRowPtr row;
-XkbDoodadPtr doodad;
-XkbBoundsPtr bounds,rbounds;
-
- if ((!geom)||(!section))
- return False;
- bounds= §ion->bounds;
- bzero(bounds,sizeof(XkbBoundsRec));
- for (i=0,row=section->rows;i<section->num_rows;i++,row++) {
- if (!XkbComputeRowBounds(geom,section,row))
- return False;
- rbounds= &row->bounds;
- _XkbCheckBounds(bounds,row->left+rbounds->x1,row->top+rbounds->y1);
- _XkbCheckBounds(bounds,row->left+rbounds->x2,row->top+rbounds->y2);
- }
- for (i=0,doodad=section->doodads;i<section->num_doodads;i++,doodad++) {
- static XkbBoundsRec tbounds;
- switch (doodad->any.type) {
- case XkbOutlineDoodad:
- case XkbSolidDoodad:
- shape= XkbShapeDoodadShape(geom,&doodad->shape);
- rbounds= &shape->bounds;
- break;
- case XkbTextDoodad:
- tbounds.x1= doodad->text.left;
- tbounds.y1= doodad->text.top;
- tbounds.x2= tbounds.x1+doodad->text.width;
- tbounds.y2= tbounds.y1+doodad->text.height;
- rbounds= &tbounds;
- break;
- case XkbIndicatorDoodad:
- shape= XkbIndicatorDoodadShape(geom,&doodad->indicator);
- rbounds= &shape->bounds;
- break;
- case XkbLogoDoodad:
- shape= XkbLogoDoodadShape(geom,&doodad->logo);
- rbounds= &shape->bounds;
- break;
- default:
- tbounds.x1= tbounds.x2= doodad->any.left;
- tbounds.y1= tbounds.y2= doodad->any.top;
- rbounds= &tbounds;
- break;
- }
- _XkbCheckBounds(bounds,rbounds->x1,rbounds->y1);
- _XkbCheckBounds(bounds,rbounds->x2,rbounds->y2);
- }
- return True;
-}
-
-/***====================================================================***/
-
-char *
-XkbFindOverlayForKey(XkbGeometryPtr geom,XkbSectionPtr wanted,char *under)
-{
-int s;
-XkbSectionPtr section;
-
- if ((geom==NULL)||(under==NULL)||(geom->num_sections<1))
- return NULL;
-
- if (wanted)
- section= wanted;
- else section= geom->sections;
-
- for (s=0;s<geom->num_sections;s++,section++) {
- XkbOverlayPtr ol;
- int o;
-
- if (section->num_overlays<1)
- continue;
- for (o=0,ol=section->overlays;o<section->num_overlays;o++,ol++) {
- XkbOverlayRowPtr row;
- int r;
-
- for (r=0,row=ol->rows;r<ol->num_rows;r++,row++) {
- XkbOverlayKeyPtr key;
- int k;
- for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
- if (strncmp(under,key->under.name,XkbKeyNameLength)==0)
- return key->over.name;
- }
- }
- }
- if (wanted!=NULL)
- break;
- }
- return NULL;
-}
-
-/***====================================================================***/
-
-static Status
-_XkbReadGeomProperties( XkbReadBufferPtr buf,
- XkbGeometryPtr geom,
- xkbGetGeometryReply * rep)
-{
-Status rtrn;
-
- if (rep->nProperties<1)
- return Success;
- if ((rtrn=XkbAllocGeomProps(geom,rep->nProperties))==Success) {
- register int i;
- register Bool ok;
- char *name,*value;
- ok= True;
- for (i=0;(i<rep->nProperties)&&ok;i++) {
- name=NULL;
- value=NULL;
- ok= _XkbGetReadBufferCountedString(buf,&name)&&ok;
- ok= _XkbGetReadBufferCountedString(buf,&value)&&ok;
- ok= ok&&(XkbAddGeomProperty(geom,name,value)!=NULL);
- if (name)
- _XkbFree(name);
- if (value)
- _XkbFree(value);
- }
- if (ok) rtrn= Success;
- else rtrn= BadLength;
- }
- return rtrn;
-}
-
-static Status
-_XkbReadGeomKeyAliases( XkbReadBufferPtr buf,
- XkbGeometryPtr geom,
- xkbGetGeometryReply * rep)
-{
-Status rtrn;
-
- if (rep->nKeyAliases<1)
- return Success;
- if ((rtrn=XkbAllocGeomKeyAliases(geom,rep->nKeyAliases))==Success) {
- if (!_XkbCopyFromReadBuffer(buf,(char *)geom->key_aliases,
- (rep->nKeyAliases*XkbKeyNameLength*2)))
- return BadLength;
- geom->num_key_aliases= rep->nKeyAliases;
- return Success;
- }
- else { /* alloc failed, just skip the aliases */
- _XkbSkipReadBufferData(buf,(rep->nKeyAliases*XkbKeyNameLength*2));
- }
- return rtrn;
-}
-
-static Status
-_XkbReadGeomColors( XkbReadBufferPtr buf,
- XkbGeometryPtr geom,
- xkbGetGeometryReply * rep)
-{
-Status rtrn;
-
- if (rep->nColors<1)
- return Success;
- if ((rtrn=XkbAllocGeomColors(geom,rep->nColors))==Success) {
- register int i;
- char *spec;
- for (i=0;i<rep->nColors;i++) {
- spec = NULL;
- if (!_XkbGetReadBufferCountedString(buf,&spec))
- rtrn = BadLength;
- else if (XkbAddGeomColor(geom,spec,geom->num_colors)==NULL)
- rtrn = BadAlloc;
- if (spec)
- _XkbFree(spec);
- if (rtrn != Success)
- return rtrn;
- }
- return Success;
- }
- return rtrn;
-}
-
-static Status
-_XkbReadGeomShapes( XkbReadBufferPtr buf,
- XkbGeometryPtr geom,
- xkbGetGeometryReply * rep)
-{
-register int i;
-Status rtrn;
-
- if (rep->nShapes<1)
- return Success;
- if ((rtrn=XkbAllocGeomShapes(geom,rep->nShapes))!=Success)
- return rtrn;
- for (i=0;i<rep->nShapes;i++) {
- xkbShapeWireDesc *shapeWire;
- XkbShapePtr shape;
- register int o;
- shapeWire= (xkbShapeWireDesc *)
- _XkbGetReadBufferPtr(buf,SIZEOF(xkbShapeWireDesc));
- if (!shapeWire)
- return BadLength;
- shape= XkbAddGeomShape(geom,shapeWire->name,shapeWire->nOutlines);
- if (!shape)
- return BadAlloc;
- for (o=0;o<shapeWire->nOutlines;o++) {
- xkbOutlineWireDesc *olWire;
- XkbOutlinePtr ol;
- register int p;
- XkbPointPtr pt;
- olWire= (xkbOutlineWireDesc *)
- _XkbGetReadBufferPtr(buf,SIZEOF(xkbOutlineWireDesc));
- if (!olWire)
- return BadLength;
- ol= XkbAddGeomOutline(shape,olWire->nPoints);
- if (!ol)
- return BadAlloc;
- ol->corner_radius= olWire->cornerRadius;
- for (p=0,pt=ol->points;p<olWire->nPoints;p++,pt++) {
- xkbPointWireDesc * ptWire;
- ptWire= (xkbPointWireDesc *)
- _XkbGetReadBufferPtr(buf,SIZEOF(xkbPointWireDesc));
- if (!ptWire)
- return BadLength;
- pt->x= ptWire->x;
- pt->y= ptWire->y;
- }
- ol->num_points= olWire->nPoints;
- }
- if (shapeWire->primaryNdx!=XkbNoShape)
- shape->primary= &shape->outlines[shapeWire->primaryNdx];
- else shape->primary= NULL;
- if (shapeWire->approxNdx!=XkbNoShape)
- shape->approx= &shape->outlines[shapeWire->approxNdx];
- else shape->approx= NULL;
- XkbComputeShapeBounds(shape);
- }
- return Success;
-}
-
-static Status
-_XkbReadGeomDoodad( XkbReadBufferPtr buf,
- XkbGeometryPtr geom,
- XkbSectionPtr section)
-{
-XkbDoodadPtr doodad;
-xkbDoodadWireDesc * doodadWire;
-
- doodadWire= (xkbDoodadWireDesc *)
- _XkbGetReadBufferPtr(buf,SIZEOF(xkbDoodadWireDesc));
- if (!doodadWire)
- return BadLength;
- doodad= XkbAddGeomDoodad(geom,section,doodadWire->any.name);
- if (!doodad)
- return BadAlloc;
- doodad->any.type= doodadWire->any.type;
- doodad->any.priority= doodadWire->any.priority;
- doodad->any.top= doodadWire->any.top;
- doodad->any.left= doodadWire->any.left;
- doodad->any.angle= doodadWire->any.angle;
- switch (doodad->any.type) {
- case XkbOutlineDoodad:
- case XkbSolidDoodad:
- doodad->shape.color_ndx= doodadWire->shape.colorNdx;
- doodad->shape.shape_ndx= doodadWire->shape.shapeNdx;
- break;
- case XkbTextDoodad:
- doodad->text.width= doodadWire->text.width;
- doodad->text.height= doodadWire->text.height;
- doodad->text.color_ndx= doodadWire->text.colorNdx;
- if (!_XkbGetReadBufferCountedString(buf,&doodad->text.text))
- return BadLength;
- if (!_XkbGetReadBufferCountedString(buf,&doodad->text.font))
- return BadLength;
- break;
- case XkbIndicatorDoodad:
- doodad->indicator.shape_ndx= doodadWire->indicator.shapeNdx;
- doodad->indicator.on_color_ndx= doodadWire->indicator.onColorNdx;
- doodad->indicator.off_color_ndx= doodadWire->indicator.offColorNdx;
- break;
- case XkbLogoDoodad:
- doodad->logo.color_ndx= doodadWire->logo.colorNdx;
- doodad->logo.shape_ndx= doodadWire->logo.shapeNdx;
- if (!_XkbGetReadBufferCountedString(buf,&doodad->logo.logo_name))
- return BadLength;
- break;
- default:
- return BadValue;
- }
- return Success;
-}
-
-static Status
-_XkbReadGeomOverlay( XkbReadBufferPtr buf,
- XkbGeometryPtr geom,
- XkbSectionPtr section)
-{
-XkbOverlayPtr ol;
-xkbOverlayWireDesc * olWire;
-register int r;
-
- olWire= (xkbOverlayWireDesc *)
- _XkbGetReadBufferPtr(buf,SIZEOF(xkbOverlayWireDesc));
- if (olWire==NULL)
- return BadLength;
- ol= XkbAddGeomOverlay(section,olWire->name,olWire->nRows);
- if (ol==NULL)
- return BadLength;
- for (r=0;r<olWire->nRows;r++) {
- register int k;
- XkbOverlayRowPtr row;
- xkbOverlayRowWireDesc * rowWire;
- xkbOverlayKeyWireDesc * keyWire;
- rowWire= (xkbOverlayRowWireDesc *)
- _XkbGetReadBufferPtr(buf,SIZEOF(xkbOverlayRowWireDesc));
- if (rowWire==NULL)
- return BadLength;
- row= XkbAddGeomOverlayRow(ol,rowWire->rowUnder,rowWire->nKeys);
- row->row_under= rowWire->rowUnder;
- if (!row)
- return BadAlloc;
- if (rowWire->nKeys<1)
- continue;
- keyWire= (xkbOverlayKeyWireDesc *)
- _XkbGetReadBufferPtr(buf,
- SIZEOF(xkbOverlayKeyWireDesc)*rowWire->nKeys);
- if (keyWire==NULL)
- return BadLength;
- for (k=0;k<rowWire->nKeys;k++,keyWire++,row->num_keys++) {
- memcpy(row->keys[row->num_keys].over.name,keyWire->over,
- XkbKeyNameLength);
- memcpy(row->keys[row->num_keys].under.name,keyWire->under,
- XkbKeyNameLength);
- }
- }
- return Success;
-}
-
-static Status
-_XkbReadGeomSections( XkbReadBufferPtr buf,
- XkbGeometryPtr geom,
- xkbGetGeometryReply * rep)
-{
-register int s;
-XkbSectionPtr section;
-xkbSectionWireDesc * sectionWire;
-Status rtrn;
-
- if (rep->nSections<1)
- return Success;
- if ((rtrn=XkbAllocGeomSections(geom,rep->nSections))!=Success)
- return rtrn;
- for (s=0;s<rep->nSections;s++) {
- sectionWire= (xkbSectionWireDesc *)
- _XkbGetReadBufferPtr(buf,SIZEOF(xkbSectionWireDesc));
- if (!sectionWire)
- return BadLength;
- section= XkbAddGeomSection(geom,sectionWire->name,sectionWire->nRows,
- sectionWire->nDoodads,
- sectionWire->nOverlays);
- if (!section)
- return BadAlloc;
- section->top= sectionWire->top;
- section->left= sectionWire->left;
- section->width= sectionWire->width;
- section->height= sectionWire->height;
- section->angle= sectionWire->angle;
- section->priority= sectionWire->priority;
- if (sectionWire->nRows>0) {
- register int r;
- XkbRowPtr row;
- xkbRowWireDesc * rowWire;
- for (r=0;r<sectionWire->nRows;r++) {
- rowWire= (xkbRowWireDesc *)
- _XkbGetReadBufferPtr(buf,SIZEOF(xkbRowWireDesc));
- if (!rowWire)
- return BadLength;
- row= XkbAddGeomRow(section,rowWire->nKeys);
- if (!row)
- return BadAlloc;
- row->top= rowWire->top;
- row->left= rowWire->left;
- row->vertical= rowWire->vertical;
- if (rowWire->nKeys>0) {
- register int k;
- XkbKeyPtr key;
- xkbKeyWireDesc * keyWire;
- for (k=0;k<rowWire->nKeys;k++) {
- keyWire= (xkbKeyWireDesc *)
- _XkbGetReadBufferPtr(buf,SIZEOF(xkbKeyWireDesc));
- if (!keyWire)
- return BadLength;
- key= XkbAddGeomKey(row);
- if (!key)
- return BadAlloc;
- memcpy(key->name.name,keyWire->name,XkbKeyNameLength);
- key->gap= keyWire->gap;
- key->shape_ndx= keyWire->shapeNdx;
- key->color_ndx= keyWire->colorNdx;
- }
- }
- }
- }
- if (sectionWire->nDoodads>0) {
- register int d;
- for (d=0;d<sectionWire->nDoodads;d++) {
- if ((rtrn=_XkbReadGeomDoodad(buf,geom,section))!=Success)
- return rtrn;
- }
- }
- if (sectionWire->nOverlays>0) {
- register int o;
- for (o=0;o<sectionWire->nOverlays;o++) {
- if ((rtrn=_XkbReadGeomOverlay(buf,geom,section))!=Success)
- return rtrn;
- }
- }
- }
- return Success;
-}
-
-static Status
-_XkbReadGeomDoodads( XkbReadBufferPtr buf,
- XkbGeometryPtr geom,
- xkbGetGeometryReply * rep)
-{
-register int d;
-Status rtrn;
-
- if (rep->nDoodads<1)
- return Success;
- if ((rtrn=XkbAllocGeomDoodads(geom,rep->nDoodads))!=Success)
- return rtrn;
- for (d=0;d<rep->nDoodads;d++) {
- if ((rtrn=_XkbReadGeomDoodad(buf,geom,NULL))!=Success)
- return rtrn;
- }
- return Success;
-}
-
-Status
-_XkbReadGetGeometryReply( Display * dpy,
- xkbGetGeometryReply * rep,
- XkbDescPtr xkb,
- int * nread_rtrn)
-{
-XkbGeometryPtr geom;
-
- geom= _XkbTypedCalloc(1,XkbGeometryRec);
- if (!geom)
- return BadAlloc;
- if (xkb->geom)
- XkbFreeGeometry(xkb->geom,XkbGeomAllMask,True);
- xkb->geom= geom;
-
- geom->name= rep->name;
- geom->width_mm= rep->widthMM;
- geom->height_mm= rep->heightMM;
- if (rep->length) {
- XkbReadBufferRec buf;
- int left;
- if (_XkbInitReadBuffer(dpy,&buf,(int)rep->length*4)) {
- Status status= Success;
- if (nread_rtrn)
- *nread_rtrn= (int)rep->length*4;
- if (!_XkbGetReadBufferCountedString(&buf,&geom->label_font))
- status= BadLength;
- if (status==Success)
- status= _XkbReadGeomProperties(&buf,geom,rep);
- if (status==Success)
- status= _XkbReadGeomColors(&buf,geom,rep);
- if (status==Success)
- status= _XkbReadGeomShapes(&buf,geom,rep);
- if (status==Success)
- status= _XkbReadGeomSections(&buf,geom,rep);
- if (status==Success)
- status= _XkbReadGeomDoodads(&buf,geom,rep);
- if (status==Success)
- status= _XkbReadGeomKeyAliases(&buf,geom,rep);
- left= _XkbFreeReadBuffer(&buf);
- if ((status!=Success) || left || buf.error) {
- if (status==Success)
- status= BadLength;
- XkbFreeGeometry(geom,XkbGeomAllMask,True);
- xkb->geom= NULL;
- return status;
- }
- geom->base_color= &geom->colors[rep->baseColorNdx];
- geom->label_color= &geom->colors[rep->labelColorNdx];
- }
- else {
- XkbFreeGeometry(geom,XkbGeomAllMask,True);
- xkb->geom= NULL;
- return BadAlloc;
- }
- }
- return Success;
-}
-
-Status
-XkbGetGeometry(Display *dpy,XkbDescPtr xkb)
-{
-xkbGetGeometryReq *req;
-xkbGetGeometryReply rep;
-Status status;
-
- if ( (!xkb) || (dpy->flags & XlibDisplayNoXkb) ||
- (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
- return BadAccess;
-
- LockDisplay(dpy);
- GetReq(kbGetGeometry, req);
- req->reqType = dpy->xkb_info->codes->major_opcode;
- req->xkbReqType = X_kbGetGeometry;
- req->deviceSpec = xkb->device_spec;
- req->name= None;
- if (!_XReply(dpy, (xReply *)&rep, 0, xFalse))
- status = BadImplementation;
- else if (!rep.found)
- status = BadName;
- else
- status = _XkbReadGetGeometryReply(dpy,&rep,xkb,NULL);
- UnlockDisplay(dpy);
- SyncHandle();
- return status;
-}
-
-Status
-XkbGetNamedGeometry(Display *dpy,XkbDescPtr xkb,Atom name)
-{
-xkbGetGeometryReq *req;
-xkbGetGeometryReply rep;
-Status status;
-
- if ( (name==None) || (dpy->flags & XlibDisplayNoXkb) ||
- (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)) )
- return BadAccess;
-
- LockDisplay(dpy);
- GetReq(kbGetGeometry, req);
- req->reqType = dpy->xkb_info->codes->major_opcode;
- req->xkbReqType = X_kbGetGeometry;
- req->deviceSpec = xkb->device_spec;
- req->name= (CARD32)name;
- if ((!_XReply(dpy, (xReply *)&rep, 0, xFalse))||(!rep.found))
- status = BadImplementation;
- else if (!rep.found)
- status = BadName;
- else
- status = _XkbReadGetGeometryReply(dpy,&rep,xkb,NULL);
- UnlockDisplay(dpy);
- SyncHandle();
- return status;
-}
-
+/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, 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 Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS 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 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH +THE USE OR PERFORMANCE OF THIS SOFTWARE. + +********************************************************/ + +#ifdef DEBUG +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#endif + +#define NEED_MAP_READERS +#include "Xlibint.h" +#include <X11/extensions/XKBgeom.h> +#include <X11/extensions/XKBproto.h> +#include "XKBlibint.h" + +#define MINSHORT -32768 +#define MAXSHORT 32767 + +/***====================================================================***/ + +static void +_XkbCheckBounds(XkbBoundsPtr bounds,int x,int y) +{ + if (x<bounds->x1) bounds->x1= x; + if (x>bounds->x2) bounds->x2= x; + if (y<bounds->y1) bounds->y1= y; + if (y>bounds->y2) bounds->y2= y; + return; +} + +Bool +XkbComputeShapeBounds(XkbShapePtr shape) +{ +register int o,p; +XkbOutlinePtr outline; +XkbPointPtr pt; + + if ((!shape)||(shape->num_outlines<1)) + return False; + shape->bounds.x1= shape->bounds.y1= MAXSHORT; + shape->bounds.x2= shape->bounds.y2= MINSHORT; + for (outline=shape->outlines,o=0;o<shape->num_outlines;o++,outline++) { + for (pt=outline->points,p=0;p<outline->num_points;p++,pt++) { + _XkbCheckBounds(&shape->bounds,pt->x,pt->y); + } + if (outline->num_points<2) { + _XkbCheckBounds(&shape->bounds,0,0); + } + } + return True; +} + +Bool +XkbComputeShapeTop(XkbShapePtr shape,XkbBoundsPtr bounds) +{ +register int p; +XkbOutlinePtr outline; +XkbPointPtr pt; + + if ((!shape)||(shape->num_outlines<1)) + return False; + if (shape->approx) outline= shape->approx; + else outline= &shape->outlines[shape->num_outlines-1]; + if (outline->num_points<2) { + bounds->x1= bounds->y1= 0; + bounds->x2= bounds->y2= 0; + } + else { + bounds->x1= bounds->y1= MAXSHORT; + bounds->x2= bounds->y2= MINSHORT; + } + for (pt=outline->points,p=0;p<outline->num_points;p++,pt++) { + _XkbCheckBounds(bounds,pt->x,pt->y); + } + return True; +} + +Bool +XkbComputeRowBounds(XkbGeometryPtr geom,XkbSectionPtr section,XkbRowPtr row) +{ +register int k,pos; +XkbKeyPtr key; +XkbBoundsPtr bounds,sbounds; + + if ((!geom)||(!section)||(!row)) + return False; + bounds= &row->bounds; + bzero(bounds,sizeof(XkbBoundsRec)); + for (key=row->keys,pos=k=0;k<row->num_keys;k++,key++) { + sbounds= &XkbKeyShape(geom,key)->bounds; + _XkbCheckBounds(bounds,pos,0); + if (!row->vertical) { + if (key->gap!=0) { + pos+= key->gap; + _XkbCheckBounds(bounds,pos,0); + } + _XkbCheckBounds(bounds,pos+sbounds->x1,sbounds->y1); + _XkbCheckBounds(bounds,pos+sbounds->x2,sbounds->y2); + pos+= sbounds->x2; + } + else { + if (key->gap!=0) { + pos+= key->gap; + _XkbCheckBounds(bounds,0,pos); + } + _XkbCheckBounds(bounds,pos+sbounds->x1,sbounds->y1); + _XkbCheckBounds(bounds,pos+sbounds->x2,sbounds->y2); + pos+= sbounds->y2; + } + } + return True; +} + +Bool +XkbComputeSectionBounds(XkbGeometryPtr geom,XkbSectionPtr section) +{ +register int i; +XkbShapePtr shape; +XkbRowPtr row; +XkbDoodadPtr doodad; +XkbBoundsPtr bounds,rbounds; + + if ((!geom)||(!section)) + return False; + bounds= §ion->bounds; + bzero(bounds,sizeof(XkbBoundsRec)); + for (i=0,row=section->rows;i<section->num_rows;i++,row++) { + if (!XkbComputeRowBounds(geom,section,row)) + return False; + rbounds= &row->bounds; + _XkbCheckBounds(bounds,row->left+rbounds->x1,row->top+rbounds->y1); + _XkbCheckBounds(bounds,row->left+rbounds->x2,row->top+rbounds->y2); + } + for (i=0,doodad=section->doodads;i<section->num_doodads;i++,doodad++) { + static XkbBoundsRec tbounds; + switch (doodad->any.type) { + case XkbOutlineDoodad: + case XkbSolidDoodad: + shape= XkbShapeDoodadShape(geom,&doodad->shape); + rbounds= &shape->bounds; + break; + case XkbTextDoodad: + tbounds.x1= doodad->text.left; + tbounds.y1= doodad->text.top; + tbounds.x2= tbounds.x1+doodad->text.width; + tbounds.y2= tbounds.y1+doodad->text.height; + rbounds= &tbounds; + break; + case XkbIndicatorDoodad: + shape= XkbIndicatorDoodadShape(geom,&doodad->indicator); + rbounds= &shape->bounds; + break; + case XkbLogoDoodad: + shape= XkbLogoDoodadShape(geom,&doodad->logo); + rbounds= &shape->bounds; + break; + default: + tbounds.x1= tbounds.x2= doodad->any.left; + tbounds.y1= tbounds.y2= doodad->any.top; + rbounds= &tbounds; + break; + } + _XkbCheckBounds(bounds,rbounds->x1,rbounds->y1); + _XkbCheckBounds(bounds,rbounds->x2,rbounds->y2); + } + return True; +} + +/***====================================================================***/ + +char * +XkbFindOverlayForKey(XkbGeometryPtr geom,XkbSectionPtr wanted,char *under) +{ +int s; +XkbSectionPtr section; + + if ((geom==NULL)||(under==NULL)||(geom->num_sections<1)) + return NULL; + + if (wanted) + section= wanted; + else section= geom->sections; + + for (s=0;s<geom->num_sections;s++,section++) { + XkbOverlayPtr ol; + int o; + + if (section->num_overlays<1) + continue; + for (o=0,ol=section->overlays;o<section->num_overlays;o++,ol++) { + XkbOverlayRowPtr row; + int r; + + for (r=0,row=ol->rows;r<ol->num_rows;r++,row++) { + XkbOverlayKeyPtr key; + int k; + for (k=0,key=row->keys;k<row->num_keys;k++,key++) { + if (strncmp(under,key->under.name,XkbKeyNameLength)==0) + return key->over.name; + } + } + } + if (wanted!=NULL) + break; + } + return NULL; +} + +/***====================================================================***/ + +static Status +_XkbReadGeomProperties( XkbReadBufferPtr buf, + XkbGeometryPtr geom, + xkbGetGeometryReply * rep) +{ +Status rtrn; + + if (rep->nProperties<1) + return Success; + if ((rtrn=XkbAllocGeomProps(geom,rep->nProperties))==Success) { + register int i; + register Bool ok; + char *name,*value; + ok= True; + for (i=0;(i<rep->nProperties)&&ok;i++) { + name=NULL; + value=NULL; + ok= _XkbGetReadBufferCountedString(buf,&name)&&ok; + ok= _XkbGetReadBufferCountedString(buf,&value)&&ok; + ok= ok&&(XkbAddGeomProperty(geom,name,value)!=NULL); + if (name) + _XkbFree(name); + if (value) + _XkbFree(value); + } + if (ok) rtrn= Success; + else rtrn= BadLength; + } + return rtrn; +} + +static Status +_XkbReadGeomKeyAliases( XkbReadBufferPtr buf, + XkbGeometryPtr geom, + xkbGetGeometryReply * rep) +{ +Status rtrn; + + if (rep->nKeyAliases<1) + return Success; + if ((rtrn=XkbAllocGeomKeyAliases(geom,rep->nKeyAliases))==Success) { + if (!_XkbCopyFromReadBuffer(buf,(char *)geom->key_aliases, + (rep->nKeyAliases*XkbKeyNameLength*2))) + return BadLength; + geom->num_key_aliases= rep->nKeyAliases; + return Success; + } + else { /* alloc failed, just skip the aliases */ + _XkbSkipReadBufferData(buf,(rep->nKeyAliases*XkbKeyNameLength*2)); + } + return rtrn; +} + +static Status +_XkbReadGeomColors( XkbReadBufferPtr buf, + XkbGeometryPtr geom, + xkbGetGeometryReply * rep) +{ +Status rtrn; + + if (rep->nColors<1) + return Success; + if ((rtrn=XkbAllocGeomColors(geom,rep->nColors))==Success) { + register int i; + char *spec; + for (i=0;i<rep->nColors;i++) { + spec = NULL; + if (!_XkbGetReadBufferCountedString(buf,&spec)) + rtrn = BadLength; + else if (XkbAddGeomColor(geom,spec,geom->num_colors)==NULL) + rtrn = BadAlloc; + if (spec) + _XkbFree(spec); + if (rtrn != Success) + return rtrn; + } + return Success; + } + return rtrn; +} + +static Status +_XkbReadGeomShapes( XkbReadBufferPtr buf, + XkbGeometryPtr geom, + xkbGetGeometryReply * rep) +{ +register int i; +Status rtrn; + + if (rep->nShapes<1) + return Success; + if ((rtrn=XkbAllocGeomShapes(geom,rep->nShapes))!=Success) + return rtrn; + for (i=0;i<rep->nShapes;i++) { + xkbShapeWireDesc *shapeWire; + XkbShapePtr shape; + register int o; + shapeWire= (xkbShapeWireDesc *) + _XkbGetReadBufferPtr(buf,SIZEOF(xkbShapeWireDesc)); + if (!shapeWire) + return BadLength; + shape= XkbAddGeomShape(geom,shapeWire->name,shapeWire->nOutlines); + if (!shape) + return BadAlloc; + for (o=0;o<shapeWire->nOutlines;o++) { + xkbOutlineWireDesc *olWire; + XkbOutlinePtr ol; + register int p; + XkbPointPtr pt; + olWire= (xkbOutlineWireDesc *) + _XkbGetReadBufferPtr(buf,SIZEOF(xkbOutlineWireDesc)); + if (!olWire) + return BadLength; + ol= XkbAddGeomOutline(shape,olWire->nPoints); + if (!ol) + return BadAlloc; + ol->corner_radius= olWire->cornerRadius; + for (p=0,pt=ol->points;p<olWire->nPoints;p++,pt++) { + xkbPointWireDesc * ptWire; + ptWire= (xkbPointWireDesc *) + _XkbGetReadBufferPtr(buf,SIZEOF(xkbPointWireDesc)); + if (!ptWire) + return BadLength; + pt->x= ptWire->x; + pt->y= ptWire->y; + } + ol->num_points= olWire->nPoints; + } + if (shapeWire->primaryNdx!=XkbNoShape) + shape->primary= &shape->outlines[shapeWire->primaryNdx]; + else shape->primary= NULL; + if (shapeWire->approxNdx!=XkbNoShape) + shape->approx= &shape->outlines[shapeWire->approxNdx]; + else shape->approx= NULL; + XkbComputeShapeBounds(shape); + } + return Success; +} + +static Status +_XkbReadGeomDoodad( XkbReadBufferPtr buf, + XkbGeometryPtr geom, + XkbSectionPtr section) +{ +XkbDoodadPtr doodad; +xkbDoodadWireDesc * doodadWire; + + doodadWire= (xkbDoodadWireDesc *) + _XkbGetReadBufferPtr(buf,SIZEOF(xkbDoodadWireDesc)); + if (!doodadWire) + return BadLength; + doodad= XkbAddGeomDoodad(geom,section,doodadWire->any.name); + if (!doodad) + return BadAlloc; + doodad->any.type= doodadWire->any.type; + doodad->any.priority= doodadWire->any.priority; + doodad->any.top= doodadWire->any.top; + doodad->any.left= doodadWire->any.left; + doodad->any.angle= doodadWire->any.angle; + switch (doodad->any.type) { + case XkbOutlineDoodad: + case XkbSolidDoodad: + doodad->shape.color_ndx= doodadWire->shape.colorNdx; + doodad->shape.shape_ndx= doodadWire->shape.shapeNdx; + break; + case XkbTextDoodad: + doodad->text.width= doodadWire->text.width; + doodad->text.height= doodadWire->text.height; + doodad->text.color_ndx= doodadWire->text.colorNdx; + if (!_XkbGetReadBufferCountedString(buf,&doodad->text.text)) + return BadLength; + if (!_XkbGetReadBufferCountedString(buf,&doodad->text.font)) + return BadLength; + break; + case XkbIndicatorDoodad: + doodad->indicator.shape_ndx= doodadWire->indicator.shapeNdx; + doodad->indicator.on_color_ndx= doodadWire->indicator.onColorNdx; + doodad->indicator.off_color_ndx= doodadWire->indicator.offColorNdx; + break; + case XkbLogoDoodad: + doodad->logo.color_ndx= doodadWire->logo.colorNdx; + doodad->logo.shape_ndx= doodadWire->logo.shapeNdx; + if (!_XkbGetReadBufferCountedString(buf,&doodad->logo.logo_name)) + return BadLength; + break; + default: + return BadValue; + } + return Success; +} + +static Status +_XkbReadGeomOverlay( XkbReadBufferPtr buf, + XkbGeometryPtr geom, + XkbSectionPtr section) +{ +XkbOverlayPtr ol; +xkbOverlayWireDesc * olWire; +register int r; + + olWire= (xkbOverlayWireDesc *) + _XkbGetReadBufferPtr(buf,SIZEOF(xkbOverlayWireDesc)); + if (olWire==NULL) + return BadLength; + ol= XkbAddGeomOverlay(section,olWire->name,olWire->nRows); + if (ol==NULL) + return BadLength; + for (r=0;r<olWire->nRows;r++) { + register int k; + XkbOverlayRowPtr row; + xkbOverlayRowWireDesc * rowWire; + xkbOverlayKeyWireDesc * keyWire; + rowWire= (xkbOverlayRowWireDesc *) + _XkbGetReadBufferPtr(buf,SIZEOF(xkbOverlayRowWireDesc)); + if (rowWire==NULL) + return BadLength; + row= XkbAddGeomOverlayRow(ol,rowWire->rowUnder,rowWire->nKeys); + row->row_under= rowWire->rowUnder; + if (!row) + return BadAlloc; + if (rowWire->nKeys<1) + continue; + keyWire= (xkbOverlayKeyWireDesc *) + _XkbGetReadBufferPtr(buf, + SIZEOF(xkbOverlayKeyWireDesc)*rowWire->nKeys); + if (keyWire==NULL) + return BadLength; + for (k=0;k<rowWire->nKeys;k++,keyWire++,row->num_keys++) { + memcpy(row->keys[row->num_keys].over.name,keyWire->over, + XkbKeyNameLength); + memcpy(row->keys[row->num_keys].under.name,keyWire->under, + XkbKeyNameLength); + } + } + return Success; +} + +static Status +_XkbReadGeomSections( XkbReadBufferPtr buf, + XkbGeometryPtr geom, + xkbGetGeometryReply * rep) +{ +register int s; +XkbSectionPtr section; +xkbSectionWireDesc * sectionWire; +Status rtrn; + + if (rep->nSections<1) + return Success; + if ((rtrn=XkbAllocGeomSections(geom,rep->nSections))!=Success) + return rtrn; + for (s=0;s<rep->nSections;s++) { + sectionWire= (xkbSectionWireDesc *) + _XkbGetReadBufferPtr(buf,SIZEOF(xkbSectionWireDesc)); + if (!sectionWire) + return BadLength; + section= XkbAddGeomSection(geom,sectionWire->name,sectionWire->nRows, + sectionWire->nDoodads, + sectionWire->nOverlays); + if (!section) + return BadAlloc; + section->top= sectionWire->top; + section->left= sectionWire->left; + section->width= sectionWire->width; + section->height= sectionWire->height; + section->angle= sectionWire->angle; + section->priority= sectionWire->priority; + if (sectionWire->nRows>0) { + register int r; + XkbRowPtr row; + xkbRowWireDesc * rowWire; + for (r=0;r<sectionWire->nRows;r++) { + rowWire= (xkbRowWireDesc *) + _XkbGetReadBufferPtr(buf,SIZEOF(xkbRowWireDesc)); + if (!rowWire) + return BadLength; + row= XkbAddGeomRow(section,rowWire->nKeys); + if (!row) + return BadAlloc; + row->top= rowWire->top; + row->left= rowWire->left; + row->vertical= rowWire->vertical; + if (rowWire->nKeys>0) { + register int k; + XkbKeyPtr key; + xkbKeyWireDesc * keyWire; + for (k=0;k<rowWire->nKeys;k++) { + keyWire= (xkbKeyWireDesc *) + _XkbGetReadBufferPtr(buf,SIZEOF(xkbKeyWireDesc)); + if (!keyWire) + return BadLength; + key= XkbAddGeomKey(row); + if (!key) + return BadAlloc; + memcpy(key->name.name,keyWire->name,XkbKeyNameLength); + key->gap= keyWire->gap; + key->shape_ndx= keyWire->shapeNdx; + key->color_ndx= keyWire->colorNdx; + } + } + } + } + if (sectionWire->nDoodads>0) { + register int d; + for (d=0;d<sectionWire->nDoodads;d++) { + if ((rtrn=_XkbReadGeomDoodad(buf,geom,section))!=Success) + return rtrn; + } + } + if (sectionWire->nOverlays>0) { + register int o; + for (o=0;o<sectionWire->nOverlays;o++) { + if ((rtrn=_XkbReadGeomOverlay(buf,geom,section))!=Success) + return rtrn; + } + } + } + return Success; +} + +static Status +_XkbReadGeomDoodads( XkbReadBufferPtr buf, + XkbGeometryPtr geom, + xkbGetGeometryReply * rep) +{ +register int d; +Status rtrn; + + if (rep->nDoodads<1) + return Success; + if ((rtrn=XkbAllocGeomDoodads(geom,rep->nDoodads))!=Success) + return rtrn; + for (d=0;d<rep->nDoodads;d++) { + if ((rtrn=_XkbReadGeomDoodad(buf,geom,NULL))!=Success) + return rtrn; + } + return Success; +} + +Status +_XkbReadGetGeometryReply( Display * dpy, + xkbGetGeometryReply * rep, + XkbDescPtr xkb, + int * nread_rtrn) +{ +XkbGeometryPtr geom; + + geom= _XkbTypedCalloc(1,XkbGeometryRec); + if (!geom) + return BadAlloc; + if (xkb->geom) + XkbFreeGeometry(xkb->geom,XkbGeomAllMask,True); + xkb->geom= geom; + + geom->name= rep->name; + geom->width_mm= rep->widthMM; + geom->height_mm= rep->heightMM; + if (rep->length) { + XkbReadBufferRec buf; + int left; + if (_XkbInitReadBuffer(dpy,&buf,(int)rep->length*4)) { + Status status= Success; + if (nread_rtrn) + *nread_rtrn= (int)rep->length*4; + if (!_XkbGetReadBufferCountedString(&buf,&geom->label_font)) + status= BadLength; + if (status==Success) + status= _XkbReadGeomProperties(&buf,geom,rep); + if (status==Success) + status= _XkbReadGeomColors(&buf,geom,rep); + if (status==Success) + status= _XkbReadGeomShapes(&buf,geom,rep); + if (status==Success) + status= _XkbReadGeomSections(&buf,geom,rep); + if (status==Success) + status= _XkbReadGeomDoodads(&buf,geom,rep); + if (status==Success) + status= _XkbReadGeomKeyAliases(&buf,geom,rep); + left= _XkbFreeReadBuffer(&buf); + if ((status!=Success) || left || buf.error) { + if (status==Success) + status= BadLength; + XkbFreeGeometry(geom,XkbGeomAllMask,True); + xkb->geom= NULL; + return status; + } + geom->base_color= &geom->colors[rep->baseColorNdx]; + geom->label_color= &geom->colors[rep->labelColorNdx]; + } + else { + XkbFreeGeometry(geom,XkbGeomAllMask,True); + xkb->geom= NULL; + return BadAlloc; + } + } + return Success; +} + +Status +XkbGetGeometry(Display *dpy,XkbDescPtr xkb) +{ +xkbGetGeometryReq *req; +xkbGetGeometryReply rep; +Status status; + + if ( (!xkb) || (dpy->flags & XlibDisplayNoXkb) || + (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL))) + return BadAccess; + + LockDisplay(dpy); + GetReq(kbGetGeometry, req); + req->reqType = dpy->xkb_info->codes->major_opcode; + req->xkbReqType = X_kbGetGeometry; + req->deviceSpec = xkb->device_spec; + req->name= None; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) + status = BadImplementation; + else if (!rep.found) + status = BadName; + else + status = _XkbReadGetGeometryReply(dpy,&rep,xkb,NULL); + UnlockDisplay(dpy); + SyncHandle(); + return status; +} + +Status +XkbGetNamedGeometry(Display *dpy,XkbDescPtr xkb,Atom name) +{ +xkbGetGeometryReq *req; +xkbGetGeometryReply rep; +Status status; + + if ( (name==None) || (dpy->flags & XlibDisplayNoXkb) || + (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)) ) + return BadAccess; + + LockDisplay(dpy); + GetReq(kbGetGeometry, req); + req->reqType = dpy->xkb_info->codes->major_opcode; + req->xkbReqType = X_kbGetGeometry; + req->deviceSpec = xkb->device_spec; + req->name= (CARD32)name; + if ((!_XReply(dpy, (xReply *)&rep, 0, xFalse))||(!rep.found)) + status = BadImplementation; + else if (!rep.found) + status = BadName; + else + status = _XkbReadGetGeometryReply(dpy,&rep,xkb,NULL); + UnlockDisplay(dpy); + SyncHandle(); + return status; +} + diff --git a/libX11/src/xlibi18n/XDefaultIMIF.c b/libX11/src/xlibi18n/XDefaultIMIF.c index 80199669e..36a457ea5 100644 --- a/libX11/src/xlibi18n/XDefaultIMIF.c +++ b/libX11/src/xlibi18n/XDefaultIMIF.c @@ -1,470 +1,470 @@ -/*
-Copyright 1985, 1986, 1987, 1991, 1998 The Open Group
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions: The above copyright notice and this
-permission notice shall be included in all copies or substantial
-portions of the Software.
-
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
-EVEN IF ADVISED IN ADVANCE OF THE POSSIBILITY OF SUCH DAMAGES.
-
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-
-X Window System is a trademark of The Open Group
-
-OSF/1, OSF/Motif and Motif are registered trademarks, and OSF, the OSF
-logo, LBX, X Window System, and Xinerama are trademarks of the Open
-Group. All other trademarks and registered trademarks mentioned herein
-are the property of their respective owners. No right, title or
-interest in or to any trademark, service mark, logo or trade name of
-Sun Microsystems, Inc. or its licensors is granted.
-
-*/
-/*
- * Copyright 2000 Oracle and/or its affiliates. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <unistd.h>
-#include "Xlibint.h"
-#include "Xlcint.h"
-#include "XlcGeneric.h"
-
-#ifndef MAXINT
-#define MAXINT (~((unsigned int)1 << (8 * sizeof(int)) - 1))
-#endif /* !MAXINT */
-
-typedef struct _StaticXIM *StaticXIM;
-
-typedef struct _XIMStaticXIMRec {
- /* for CT => MB,WC converter */
- XlcConv ctom_conv;
- XlcConv ctow_conv;
-} XIMStaticXIMRec;
-
-typedef enum {
- CREATE_IC = 1,
- SET_ICVAL = 2,
- GET_ICVAL = 3
-} XICOp_t;
-
-typedef struct _StaticXIM {
- XIMMethods methods;
- XIMCoreRec core;
- XIMStaticXIMRec *private;
-} StaticXIMRec;
-
-static Status _CloseIM(
- XIM
-);
-
-static char *_SetIMValues(
- XIM, XIMArg *
-);
-
-static char *_GetIMValues(
- XIM, XIMArg*
-);
-
-static XIC _CreateIC(
- XIM, XIMArg*
-);
-
-static _Xconst XIMMethodsRec local_im_methods = {
- _CloseIM, /* close */
- _SetIMValues, /* set_values */
- _GetIMValues, /* get_values */
- _CreateIC, /* create_ic */
- NULL, /* ctstombs */
- NULL /* ctstowcs */
-};
-
-static void _DestroyIC(
- XIC
-);
-static void _SetFocus(
- XIC
-);
-static void _UnsetFocus(
- XIC
-);
-static char* _SetICValues(
- XIC, XIMArg *
-);
-static char* _GetICValues(
- XIC, XIMArg *
-);
-static char *_MbReset(
- XIC
-);
-static wchar_t *_WcReset(
- XIC
-);
-static int _MbLookupString(
- XIC, XKeyEvent *, char *, int, KeySym *, Status *
-);
-static int _WcLookupString(
- XIC, XKeyEvent *, wchar_t *, int, KeySym *, Status *
-);
-
-static _Xconst XICMethodsRec local_ic_methods = {
- _DestroyIC, /* destroy */
- _SetFocus, /* set_focus */
- _UnsetFocus, /* unset_focus */
- _SetICValues, /* set_values */
- _GetICValues, /* get_values */
- _MbReset, /* mb_reset */
- _WcReset, /* wc_reset */
- NULL, /* utf8_reset */ /* ??? */
- _MbLookupString, /* mb_lookup_string */
- _WcLookupString, /* wc_lookup_string */
- NULL /* utf8_lookup_string */ /* ??? */
-};
-
-XIM
-_XDefaultOpenIM(
- XLCd lcd,
- Display *dpy,
- XrmDatabase rdb,
- char *res_name,
- char *res_class)
-{
- StaticXIM im;
- XIMStaticXIMRec *local_impart;
- XlcConv ctom_conv, ctow_conv;
- int i;
- char *mod;
- char buf[BUFSIZ];
-
- if (!(ctom_conv = _XlcOpenConverter(lcd,
- XlcNCompoundText, lcd, XlcNMultiByte))) {
- return((XIM)NULL);
- }
-
- if (!(ctow_conv = _XlcOpenConverter(lcd,
- XlcNCompoundText, lcd, XlcNWideChar))) {
- return((XIM)NULL);
- }
-
- if ((im = (StaticXIM)Xmalloc(sizeof(StaticXIMRec))) == (StaticXIM)NULL) {
- return((XIM)NULL);
- }
- if ((local_impart = (XIMStaticXIMRec*)Xmalloc(sizeof(XIMStaticXIMRec)))
- == (XIMStaticXIMRec *)NULL) {
- Xfree(im);
- return((XIM)NULL);
- }
- memset(im, 0, sizeof(StaticXIMRec));
- memset(local_impart, 0, sizeof(XIMStaticXIMRec));
-
- buf[0] = '\0';
- i = 0;
- if ((lcd->core->modifiers) && (*lcd->core->modifiers)) {
-#define MODIFIER "@im="
- mod = strstr(lcd->core->modifiers, MODIFIER);
- if (mod) {
- mod += strlen(MODIFIER);
- while (*mod && *mod != '@' && i < BUFSIZ - 1) {
- buf[i++] = *mod++;
- }
- buf[i] = '\0';
- }
- }
-#undef MODIFIER
- if ((im->core.im_name = Xmalloc(i+1)) == NULL)
- goto Error2;
- strcpy(im->core.im_name, buf);
-
- im->private = local_impart;
- im->methods = (XIMMethods)&local_im_methods;
- im->core.lcd = lcd;
- im->core.ic_chain = (XIC)NULL;
- im->core.display = dpy;
- im->core.rdb = rdb;
- im->core.res_name = NULL;
- im->core.res_class = NULL;
-
- local_impart->ctom_conv = ctom_conv;
- local_impart->ctow_conv = ctow_conv;
-
- if ((res_name != NULL) && (*res_name != '\0')){
- im->core.res_name = strdup(res_name);
- }
- if ((res_class != NULL) && (*res_class != '\0')){
- im->core.res_class = strdup(res_class);
- }
-
- return (XIM)im;
-Error2 :
- Xfree(im->private);
- Xfree(im->core.im_name);
- Xfree(im);
- _XlcCloseConverter(ctom_conv);
- _XlcCloseConverter(ctow_conv);
- return(NULL);
-}
-
-static Status
-_CloseIM(XIM xim)
-{
- StaticXIM im = (StaticXIM)xim;
- _XlcCloseConverter(im->private->ctom_conv);
- _XlcCloseConverter(im->private->ctow_conv);
- XFree(im->private);
- XFree(im->core.im_name);
- if (im->core.res_name) XFree(im->core.res_name);
- if (im->core.res_class) XFree(im->core.res_class);
- return 1; /*bugID 4163122*/
-}
-
-static char *
-_SetIMValues(
- XIM xim,
- XIMArg *arg)
-{
- return(arg->name); /* evil */
-}
-
-static char *
-_GetIMValues(
- XIM xim,
- XIMArg *values)
-{
- XIMArg *p;
- XIMStyles *styles;
-
- for (p = values; p->name != NULL; p++) {
- if (strcmp(p->name, XNQueryInputStyle) == 0) {
- styles = (XIMStyles *)Xmalloc(sizeof(XIMStyles));
- *(XIMStyles **)p->value = styles;
- styles->count_styles = 1;
- styles->supported_styles =
- (XIMStyle*)Xmalloc(styles->count_styles * sizeof(XIMStyle));
- styles->supported_styles[0] = (XIMPreeditNone | XIMStatusNone);
- } else {
- break;
- }
- }
- return (p->name);
-}
-
-static char*
-_SetICValueData(XIC ic, XIMArg *values, XICOp_t mode)
-{
- XIMArg *p;
- char *return_name = NULL;
-
- for (p = values; p != NULL && p->name != NULL; p++) {
- if(strcmp(p->name, XNInputStyle) == 0) {
- if (mode == CREATE_IC)
- ic->core.input_style = (XIMStyle)p->value;
- } else if (strcmp(p->name, XNClientWindow) == 0) {
- ic->core.client_window = (Window)p->value ;
- } else if (strcmp(p->name, XNFocusWindow) == 0) {
- ic->core.focus_window = (Window)p->value ;
- } else if (strcmp(p->name, XNPreeditAttributes) == 0
- || strcmp(p->name, XNStatusAttributes) == 0) {
- return_name = _SetICValueData(ic, (XIMArg*)p->value, mode);
- if (return_name) break;
- } else {
- return_name = p->name;
- break;
- }
- }
- return(return_name);
-}
-
-static char*
-_GetICValueData(XIC ic, XIMArg *values, XICOp_t mode)
-{
- XIMArg *p;
- char *return_name = NULL;
-
- for (p = values; p->name != NULL; p++) {
- if(strcmp(p->name, XNInputStyle) == 0) {
- *((XIMStyle *)(p->value)) = ic->core.input_style;
- } else if (strcmp(p->name, XNClientWindow) == 0) {
- *((Window *)(p->value)) = ic->core.client_window;
- } else if (strcmp(p->name, XNFocusWindow) == 0) {
- *((Window *)(p->value)) = ic->core.focus_window;
- } else if (strcmp(p->name, XNFilterEvents) == 0) {
- *((unsigned long *)(p->value))= ic->core.filter_events;
- } else if (strcmp(p->name, XNPreeditAttributes) == 0
- || strcmp(p->name, XNStatusAttributes) == 0) {
- return_name = _GetICValueData(ic, (XIMArg*)p->value, mode);
- if (return_name) break;
- } else {
- return_name = p->name;
- break;
- }
- }
- return(return_name);
-}
-
-static XIC
-_CreateIC(XIM im, XIMArg *arg)
-{
- XIC ic;
-
- if ((ic = (XIC)Xmalloc(sizeof(XICRec))) == (XIC)NULL) {
- return ((XIC)NULL);
- }
- memset(ic, 0, sizeof(XICRec));
-
- ic->methods = (XICMethods)&local_ic_methods;
- ic->core.im = im;
- ic->core.filter_events = KeyPressMask;
-
- if (_SetICValueData(ic, arg, CREATE_IC) != NULL)
- goto err_return;
- if (!(ic->core.input_style))
- goto err_return;
-
- return (XIC)ic;
-err_return:
- XFree(ic);
- return ((XIC)NULL);
-}
-
-static void
-_DestroyIC(XIC ic)
-{
-/*BugId4255571. This Xfree() should be removed because XDestroyIC() still need ic after invoking _DestroyIC() and there is a XFree(ic) at the end of XDestroyIC() already.
- if(ic)
- XFree(ic); */
-}
-
-static void
-_SetFocus(XIC ic)
-{
-}
-
-static void
-_UnsetFocus(XIC ic)
-{
-}
-
-static char*
-_SetICValues(XIC ic, XIMArg *args)
-{
- char *ret = NULL;
- if (!ic) {
- return (args->name);
- }
- ret = _SetICValueData(ic, args, SET_ICVAL);
- return(ret);
-}
-
-static char*
-_GetICValues(XIC ic, XIMArg *args)
-{
- char *ret = NULL;
- if (!ic) {
- return (args->name);
- }
- ret = _GetICValueData(ic, args, GET_ICVAL);
- return(ret);
-}
-
-static char *
-_MbReset(XIC xic)
-{
- return(NULL);
-}
-
-static wchar_t *
-_WcReset(XIC xic)
-{
- return(NULL);
-}
-
-static int
-_MbLookupString(
- XIC xic,
- XKeyEvent *ev,
- char * buffer,
- int bytes,
- KeySym *keysym,
- Status *status)
-{
- XComposeStatus NotSupportedYet ;
- int length;
-
- length = XLookupString(ev, buffer, bytes, keysym, &NotSupportedYet);
-
- if (keysym && *keysym == NoSymbol){
- *status = XLookupNone;
- } else if (length > 0) {
- *status = XLookupBoth;
- } else {
- *status = XLookupKeySym;
- }
- return(length);
-}
-
-static int
-_WcLookupString(
- XIC xic,
- XKeyEvent *ev,
- wchar_t * buffer,
- int wlen,
- KeySym *keysym,
- Status *status)
-{
- XComposeStatus NotSupportedYet ;
- int length;
- /* In single-byte, mb_len = wc_len */
- char *mb_buf = (char *)Xmalloc(wlen);
-
- length = XLookupString(ev, mb_buf, wlen, keysym, &NotSupportedYet);
-
- if (keysym && *keysym == NoSymbol){
- *status = XLookupNone;
- } else if (length > 0) {
- *status = XLookupBoth;
- } else {
- *status = XLookupKeySym;
- }
- mbstowcs(buffer, mb_buf, length);
- XFree(mb_buf);
- return(length);
-}
+/* +Copyright 1985, 1986, 1987, 1991, 1998 The Open Group + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: The above copyright notice and this +permission notice shall be included in all copies or substantial +portions of the Software. + + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE +EVEN IF ADVISED IN ADVANCE OF THE POSSIBILITY OF SUCH DAMAGES. + + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +X Window System is a trademark of The Open Group + +OSF/1, OSF/Motif and Motif are registered trademarks, and OSF, the OSF +logo, LBX, X Window System, and Xinerama are trademarks of the Open +Group. All other trademarks and registered trademarks mentioned herein +are the property of their respective owners. No right, title or +interest in or to any trademark, service mark, logo or trade name of +Sun Microsystems, Inc. or its licensors is granted. + +*/ +/* + * Copyright 2000 Oracle and/or its affiliates. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include <unistd.h> +#include "Xlibint.h" +#include "Xlcint.h" +#include "XlcGeneric.h" + +#ifndef MAXINT +#define MAXINT (~((unsigned int)1 << (8 * sizeof(int)) - 1)) +#endif /* !MAXINT */ + +typedef struct _StaticXIM *StaticXIM; + +typedef struct _XIMStaticXIMRec { + /* for CT => MB,WC converter */ + XlcConv ctom_conv; + XlcConv ctow_conv; +} XIMStaticXIMRec; + +typedef enum { + CREATE_IC = 1, + SET_ICVAL = 2, + GET_ICVAL = 3 +} XICOp_t; + +typedef struct _StaticXIM { + XIMMethods methods; + XIMCoreRec core; + XIMStaticXIMRec *private; +} StaticXIMRec; + +static Status _CloseIM( + XIM +); + +static char *_SetIMValues( + XIM, XIMArg * +); + +static char *_GetIMValues( + XIM, XIMArg* +); + +static XIC _CreateIC( + XIM, XIMArg* +); + +static _Xconst XIMMethodsRec local_im_methods = { + _CloseIM, /* close */ + _SetIMValues, /* set_values */ + _GetIMValues, /* get_values */ + _CreateIC, /* create_ic */ + NULL, /* ctstombs */ + NULL /* ctstowcs */ +}; + +static void _DestroyIC( + XIC +); +static void _SetFocus( + XIC +); +static void _UnsetFocus( + XIC +); +static char* _SetICValues( + XIC, XIMArg * +); +static char* _GetICValues( + XIC, XIMArg * +); +static char *_MbReset( + XIC +); +static wchar_t *_WcReset( + XIC +); +static int _MbLookupString( + XIC, XKeyEvent *, char *, int, KeySym *, Status * +); +static int _WcLookupString( + XIC, XKeyEvent *, wchar_t *, int, KeySym *, Status * +); + +static _Xconst XICMethodsRec local_ic_methods = { + _DestroyIC, /* destroy */ + _SetFocus, /* set_focus */ + _UnsetFocus, /* unset_focus */ + _SetICValues, /* set_values */ + _GetICValues, /* get_values */ + _MbReset, /* mb_reset */ + _WcReset, /* wc_reset */ + NULL, /* utf8_reset */ /* ??? */ + _MbLookupString, /* mb_lookup_string */ + _WcLookupString, /* wc_lookup_string */ + NULL /* utf8_lookup_string */ /* ??? */ +}; + +XIM +_XDefaultOpenIM( + XLCd lcd, + Display *dpy, + XrmDatabase rdb, + char *res_name, + char *res_class) +{ + StaticXIM im; + XIMStaticXIMRec *local_impart; + XlcConv ctom_conv, ctow_conv; + int i; + char *mod; + char buf[BUFSIZ]; + + if (!(ctom_conv = _XlcOpenConverter(lcd, + XlcNCompoundText, lcd, XlcNMultiByte))) { + return((XIM)NULL); + } + + if (!(ctow_conv = _XlcOpenConverter(lcd, + XlcNCompoundText, lcd, XlcNWideChar))) { + return((XIM)NULL); + } + + if ((im = (StaticXIM)Xmalloc(sizeof(StaticXIMRec))) == (StaticXIM)NULL) { + return((XIM)NULL); + } + if ((local_impart = (XIMStaticXIMRec*)Xmalloc(sizeof(XIMStaticXIMRec))) + == (XIMStaticXIMRec *)NULL) { + Xfree(im); + return((XIM)NULL); + } + memset(im, 0, sizeof(StaticXIMRec)); + memset(local_impart, 0, sizeof(XIMStaticXIMRec)); + + buf[0] = '\0'; + i = 0; + if ((lcd->core->modifiers) && (*lcd->core->modifiers)) { +#define MODIFIER "@im=" + mod = strstr(lcd->core->modifiers, MODIFIER); + if (mod) { + mod += strlen(MODIFIER); + while (*mod && *mod != '@' && i < BUFSIZ - 1) { + buf[i++] = *mod++; + } + buf[i] = '\0'; + } + } +#undef MODIFIER + if ((im->core.im_name = Xmalloc(i+1)) == NULL) + goto Error2; + strcpy(im->core.im_name, buf); + + im->private = local_impart; + im->methods = (XIMMethods)&local_im_methods; + im->core.lcd = lcd; + im->core.ic_chain = (XIC)NULL; + im->core.display = dpy; + im->core.rdb = rdb; + im->core.res_name = NULL; + im->core.res_class = NULL; + + local_impart->ctom_conv = ctom_conv; + local_impart->ctow_conv = ctow_conv; + + if ((res_name != NULL) && (*res_name != '\0')){ + im->core.res_name = strdup(res_name); + } + if ((res_class != NULL) && (*res_class != '\0')){ + im->core.res_class = strdup(res_class); + } + + return (XIM)im; +Error2 : + Xfree(im->private); + Xfree(im->core.im_name); + Xfree(im); + _XlcCloseConverter(ctom_conv); + _XlcCloseConverter(ctow_conv); + return(NULL); +} + +static Status +_CloseIM(XIM xim) +{ + StaticXIM im = (StaticXIM)xim; + _XlcCloseConverter(im->private->ctom_conv); + _XlcCloseConverter(im->private->ctow_conv); + XFree(im->private); + XFree(im->core.im_name); + if (im->core.res_name) XFree(im->core.res_name); + if (im->core.res_class) XFree(im->core.res_class); + return 1; /*bugID 4163122*/ +} + +static char * +_SetIMValues( + XIM xim, + XIMArg *arg) +{ + return(arg->name); /* evil */ +} + +static char * +_GetIMValues( + XIM xim, + XIMArg *values) +{ + XIMArg *p; + XIMStyles *styles; + + for (p = values; p->name != NULL; p++) { + if (strcmp(p->name, XNQueryInputStyle) == 0) { + styles = (XIMStyles *)Xmalloc(sizeof(XIMStyles)); + *(XIMStyles **)p->value = styles; + styles->count_styles = 1; + styles->supported_styles = + (XIMStyle*)Xmalloc(styles->count_styles * sizeof(XIMStyle)); + styles->supported_styles[0] = (XIMPreeditNone | XIMStatusNone); + } else { + break; + } + } + return (p->name); +} + +static char* +_SetICValueData(XIC ic, XIMArg *values, XICOp_t mode) +{ + XIMArg *p; + char *return_name = NULL; + + for (p = values; p != NULL && p->name != NULL; p++) { + if(strcmp(p->name, XNInputStyle) == 0) { + if (mode == CREATE_IC) + ic->core.input_style = (XIMStyle)p->value; + } else if (strcmp(p->name, XNClientWindow) == 0) { + ic->core.client_window = (Window)p->value ; + } else if (strcmp(p->name, XNFocusWindow) == 0) { + ic->core.focus_window = (Window)p->value ; + } else if (strcmp(p->name, XNPreeditAttributes) == 0 + || strcmp(p->name, XNStatusAttributes) == 0) { + return_name = _SetICValueData(ic, (XIMArg*)p->value, mode); + if (return_name) break; + } else { + return_name = p->name; + break; + } + } + return(return_name); +} + +static char* +_GetICValueData(XIC ic, XIMArg *values, XICOp_t mode) +{ + XIMArg *p; + char *return_name = NULL; + + for (p = values; p->name != NULL; p++) { + if(strcmp(p->name, XNInputStyle) == 0) { + *((XIMStyle *)(p->value)) = ic->core.input_style; + } else if (strcmp(p->name, XNClientWindow) == 0) { + *((Window *)(p->value)) = ic->core.client_window; + } else if (strcmp(p->name, XNFocusWindow) == 0) { + *((Window *)(p->value)) = ic->core.focus_window; + } else if (strcmp(p->name, XNFilterEvents) == 0) { + *((unsigned long *)(p->value))= ic->core.filter_events; + } else if (strcmp(p->name, XNPreeditAttributes) == 0 + || strcmp(p->name, XNStatusAttributes) == 0) { + return_name = _GetICValueData(ic, (XIMArg*)p->value, mode); + if (return_name) break; + } else { + return_name = p->name; + break; + } + } + return(return_name); +} + +static XIC +_CreateIC(XIM im, XIMArg *arg) +{ + XIC ic; + + if ((ic = (XIC)Xmalloc(sizeof(XICRec))) == (XIC)NULL) { + return ((XIC)NULL); + } + memset(ic, 0, sizeof(XICRec)); + + ic->methods = (XICMethods)&local_ic_methods; + ic->core.im = im; + ic->core.filter_events = KeyPressMask; + + if (_SetICValueData(ic, arg, CREATE_IC) != NULL) + goto err_return; + if (!(ic->core.input_style)) + goto err_return; + + return (XIC)ic; +err_return: + XFree(ic); + return ((XIC)NULL); +} + +static void +_DestroyIC(XIC ic) +{ +/*BugId4255571. This Xfree() should be removed because XDestroyIC() still need ic after invoking _DestroyIC() and there is a XFree(ic) at the end of XDestroyIC() already. + if(ic) + XFree(ic); */ +} + +static void +_SetFocus(XIC ic) +{ +} + +static void +_UnsetFocus(XIC ic) +{ +} + +static char* +_SetICValues(XIC ic, XIMArg *args) +{ + char *ret = NULL; + if (!ic) { + return (args->name); + } + ret = _SetICValueData(ic, args, SET_ICVAL); + return(ret); +} + +static char* +_GetICValues(XIC ic, XIMArg *args) +{ + char *ret = NULL; + if (!ic) { + return (args->name); + } + ret = _GetICValueData(ic, args, GET_ICVAL); + return(ret); +} + +static char * +_MbReset(XIC xic) +{ + return(NULL); +} + +static wchar_t * +_WcReset(XIC xic) +{ + return(NULL); +} + +static int +_MbLookupString( + XIC xic, + XKeyEvent *ev, + char * buffer, + int bytes, + KeySym *keysym, + Status *status) +{ + XComposeStatus NotSupportedYet ; + int length; + + length = XLookupString(ev, buffer, bytes, keysym, &NotSupportedYet); + + if (keysym && *keysym == NoSymbol){ + *status = XLookupNone; + } else if (length > 0) { + *status = XLookupBoth; + } else { + *status = XLookupKeySym; + } + return(length); +} + +static int +_WcLookupString( + XIC xic, + XKeyEvent *ev, + wchar_t * buffer, + int wlen, + KeySym *keysym, + Status *status) +{ + XComposeStatus NotSupportedYet ; + int length; + /* In single-byte, mb_len = wc_len */ + char *mb_buf = (char *)Xmalloc(wlen); + + length = XLookupString(ev, mb_buf, wlen, keysym, &NotSupportedYet); + + if (keysym && *keysym == NoSymbol){ + *status = XLookupNone; + } else if (length > 0) { + *status = XLookupBoth; + } else { + *status = XLookupKeySym; + } + mbstowcs(buffer, mb_buf, length); + XFree(mb_buf); + return(length); +} diff --git a/libX11/src/xlibi18n/XDefaultOMIF.c b/libX11/src/xlibi18n/XDefaultOMIF.c index ad1983a0d..953475d37 100644 --- a/libX11/src/xlibi18n/XDefaultOMIF.c +++ b/libX11/src/xlibi18n/XDefaultOMIF.c @@ -1,1263 +1,1263 @@ -/*
-Copyright 1985, 1986, 1987, 1991, 1998 The Open Group
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions: The above copyright notice and this
-permission notice shall be included in all copies or substantial
-portions of the Software.
-
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
-EVEN IF ADVISED IN ADVANCE OF THE POSSIBILITY OF SUCH DAMAGES.
-
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-
-X Window System is a trademark of The Open Group
-
-OSF/1, OSF/Motif and Motif are registered trademarks, and OSF, the OSF
-logo, LBX, X Window System, and Xinerama are trademarks of the Open
-Group. All other trademarks and registered trademarks mentioned herein
-are the property of their respective owners. No right, title or
-interest in or to any trademark, service mark, logo or trade name of
-Sun Microsystems, Inc. or its licensors is granted.
-
-*/
-/*
- * Copyright 2000 Oracle and/or its affiliates. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include "Xlibint.h"
-#include "Xlcint.h"
-#include "XlcPublic.h"
-#include <X11/Xos.h>
-#include <X11/Xatom.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <stdint.h>
-
-#define MAXFONTS 100
-
-#define XOM_GENERIC(om) (&((XOMGeneric) om)->gen)
-#define XOC_GENERIC(font_set) (&((XOCGeneric) font_set)->gen)
-
-#define DefineLocalBuf char local_buf[BUFSIZ]
-#define AllocLocalBuf(length) (length > BUFSIZ ? (char *)Xmalloc(length) : local_buf)
-#define FreeLocalBuf(ptr) if (ptr != local_buf) Xfree(ptr)
-
-typedef struct _FontDataRec {
- char *name;
-} FontDataRec, *FontData;
-
-typedef struct _OMDataRec {
- int font_data_count;
- FontData font_data;
-} OMDataRec, *OMData;
-
-typedef struct _XOMGenericPart {
- OMData data;
-} XOMGenericPart;
-
-typedef struct _XOMGenericRec {
- XOMMethods methods;
- XOMCoreRec core;
- XOMGenericPart gen;
-} XOMGenericRec, *XOMGeneric;
-
-typedef struct _FontSetRec {
- int id;
- int font_data_count;
- FontData font_data;
- char *font_name;
- XFontStruct *info;
- XFontStruct *font;
-} FontSetRec, *FontSet;
-
-typedef struct _XOCGenericPart {
- XlcConv wcs_to_cs;
- FontSet font_set;
-} XOCGenericPart;
-
-typedef struct _XOCGenericRec {
- XOCMethods methods;
- XOCCoreRec core;
- XOCGenericPart gen;
-} XOCGenericRec, *XOCGeneric;
-
-static Bool
-init_fontset(
- XOC oc)
-{
- XOCGenericPart *gen;
- FontSet font_set;
- OMData data;
-
- data = XOM_GENERIC(oc->core.om)->data;
-
- font_set = Xcalloc(1, sizeof(FontSetRec));
- if (font_set == NULL)
- return False;
-
- gen = XOC_GENERIC(oc);
- gen->font_set = font_set;
-
- font_set->font_data_count = data->font_data_count;
- font_set->font_data = data->font_data;
-
- return True;
-}
-
-static char *
-get_prop_name(
- Display *dpy,
- XFontStruct *fs)
-{
- unsigned long fp;
-
- if (XGetFontProperty(fs, XA_FONT, &fp))
- return XGetAtomName(dpy, fp);
-
- return (char *) NULL;
-}
-
-static FontData
-check_charset(
- FontSet font_set,
- char *font_name)
-{
- FontData font_data;
- char *last;
- int count;
- ssize_t length, name_len;
-
- name_len = strlen(font_name);
- last = font_name + name_len;
-
- count = font_set->font_data_count;
- font_data = font_set->font_data;
-
- for ( ; count-- > 0; font_data++) {
- length = strlen(font_data->name);
-
- if (length > name_len)
- return(NULL);
-
- if (_XlcCompareISOLatin1(last - length, font_data->name) == 0)
- return font_data;
- }
- return (FontData) NULL;
-}
-
-#if 0 /* Unused */
-static int
-check_fontname(
- XOC oc,
- char *name)
-{
- Display *dpy = oc->core.om->core.display;
- XOCGenericPart *gen = XOC_GENERIC(oc);
- FontData data;
- FontSet font_set;
- XFontStruct *fs_list;
- char **fn_list, *fname, *prop_fname = NULL;
- int list_num, i;
- int list2_num;
- char **fn2_list = NULL;
- int found_num = 0;
-
- fn_list = XListFonts(dpy, name, MAXFONTS, &list_num);
- if (fn_list == NULL)
- return found_num;
-
- for (i = 0; i < list_num; i++) {
- fname = fn_list[i];
-
- font_set = gen->font_set;
-
- if ((data = check_charset(font_set, fname)) == NULL) {
- if ((fn2_list = XListFontsWithInfo(dpy, name, MAXFONTS,
- &list2_num, &fs_list))
- && (prop_fname = get_prop_name(dpy, fs_list))
- && (data = check_charset(font_set, prop_fname)))
- fname = prop_fname;
- }
- if (data) {
- font_set->font_name = strdup(fname);
- if (font_set->font_name) {
- found_num++;
- }
- }
- if (fn2_list) {
- XFreeFontInfo(fn2_list, fs_list, list2_num);
- fn2_list = NULL;
- if (prop_fname) {
- Xfree(prop_fname);
- prop_fname = NULL;
- }
- }
- if (found_num == 1)
- break;
- }
- XFreeFontNames(fn_list);
- return found_num;
-}
-#endif
-
-static Bool
-load_font(
- XOC oc)
-{
- Display *dpy = oc->core.om->core.display;
- XOCGenericPart *gen = XOC_GENERIC(oc);
- FontSet font_set = gen->font_set;
-
- if (font_set->font_name == NULL)
- return False;
-
- if (font_set->font == NULL) {
- font_set->font = XLoadQueryFont(dpy, font_set->font_name);
- if (font_set->font == NULL)
- return False;
- }
- return True;
-}
-
-#if 0
-static Bool
-load_font_info(
- XOC oc)
-{
- Display *dpy = oc->core.om->core.display;
- XOCGenericPart *gen = XOC_GENERIC(oc);
- FontSet font_set = gen->font_set;
- char **fn_list;
- int fn_num;
-
- if (font_set->font_name == NULL)
- return False;
-
- if (font_set->info == NULL) {
- fn_list = XListFontsWithInfo(dpy, font_set->font_name, 1, &fn_num,
- &font_set->info);
- if (font_set->info == NULL)
- return False;
- if (fn_num > 0)
- font_set->info->fid = XLoadFont(dpy, font_set->font_name);
-
- if (fn_list) XFreeFontNames(fn_list);
- }
- return True;
-}
-#endif
-
-static void
-set_fontset_extents(
- XOC oc)
-{
- XRectangle *ink = &oc->core.font_set_extents.max_ink_extent;
- XRectangle *logical = &oc->core.font_set_extents.max_logical_extent;
- XFontStruct **font_list, *font;
- XCharStruct overall;
- int logical_ascent, logical_descent;
-
- font_list = oc->core.font_info.font_struct_list;
- font = *font_list++;
- overall = font->max_bounds;
- overall.lbearing = font->min_bounds.lbearing;
- logical_ascent = font->ascent;
- logical_descent = font->descent;
-
- ink->x = overall.lbearing;
- ink->y = -(overall.ascent);
- ink->width = overall.rbearing - overall.lbearing;
- ink->height = overall.ascent + overall.descent;
-
- logical->x = 0;
- logical->y = -(logical_ascent);
- logical->width = overall.width;
- logical->height = logical_ascent + logical_descent;
-}
-
-static Bool
-init_core_part(
- XOC oc)
-{
- XOCGenericPart *gen = XOC_GENERIC(oc);
- FontSet font_set;
- XFontStruct **font_struct_list;
- char **font_name_list, *font_name_buf;
- int count, length;
-
- font_set = gen->font_set;
- count = length = 0;
-
- if (font_set->font_name != NULL) {
- length += strlen(font_set->font_name) + 1;
- count++;
- }
- if (count == 0)
- return False;
-
- font_struct_list = (XFontStruct **) Xmalloc(sizeof(XFontStruct *));
- if (font_struct_list == NULL)
- return False;
-
- font_name_list = (char **) Xmalloc(sizeof(char *));
- if (font_name_list == NULL)
- goto err;
-
- font_name_buf = (char *) Xmalloc(length);
- if (font_name_buf == NULL)
- goto err;
-
- oc->core.font_info.num_font = 1;
- oc->core.font_info.font_name_list = font_name_list;
- oc->core.font_info.font_struct_list = font_struct_list;
-
- font_set = gen->font_set;
-
- if (font_set->font_name != NULL) {
- font_set->id = 1;
- if (font_set->font)
- *font_struct_list++ = font_set->font;
- else
- *font_struct_list++ = font_set->info;
- strcpy(font_name_buf, font_set->font_name);
- Xfree(font_set->font_name);
- *font_name_list++ = font_set->font_name = font_name_buf;
- font_name_buf += strlen(font_name_buf) + 1;
- }
-
- set_fontset_extents(oc);
-
- return True;
-
-err:
- if (font_name_list)
- Xfree(font_name_list);
- Xfree(font_struct_list);
-
- return False;
-}
-
-static char *
-get_font_name(
- XOC oc,
- char *pattern)
-{
- char **list, *name;
- int count;
- XFontStruct *fs;
- Display *dpy = oc->core.om->core.display;
-
- list = XListFonts(dpy, pattern, 1, &count);
- if (list != NULL) {
- name = strdup(*list);
-
- XFreeFontNames(list);
- } else {
- fs = XLoadQueryFont(dpy, pattern);
- if (fs == NULL) return NULL;
-
- name = get_prop_name(dpy, fs);
- XFreeFont(dpy, fs);
- }
- return name;
-}
-
-static int
-parse_fontname(
- XOC oc)
-{
- XOCGenericPart *gen = XOC_GENERIC(oc);
- FontSet font_set;
- FontData font_data;
- char *pattern, *last, buf[BUFSIZ];
- int font_data_count, found_num = 0;
- ssize_t length;
- int count, num_fields;
- char *base_name, *font_name, **name_list, **cur_name_list;
- char *charset_p = NULL;
- Bool append_charset;
- /*
- append_charset flag should be set to True when the XLFD fontname
- doesn't contain a chaset part.
- */
-
- name_list = _XParseBaseFontNameList(oc->core.base_name_list, &count);
- if (name_list == NULL)
- return -1;
- cur_name_list = name_list;
-
- while (count-- > 0) {
- pattern = *cur_name_list++;
- if (pattern == NULL || *pattern == '\0')
- continue;
-
- append_charset = False;
-
- if (strchr(pattern, '*') == NULL &&
- (font_name = get_font_name(oc, pattern))) {
-
- font_set = gen->font_set;
-
- font_data = check_charset(font_set, font_name);
- if (font_data == NULL) {
- Display *dpy = oc->core.om->core.display;
- char **fn_list = NULL, *prop_fname = NULL;
- int list_num;
- XFontStruct *fs_list;
- if ((fn_list = XListFontsWithInfo(dpy, font_name,
- MAXFONTS,
- &list_num, &fs_list))
- && (prop_fname = get_prop_name(dpy, fs_list))
- && (font_data = check_charset(font_set, prop_fname))) {
- if (fn_list) {
- XFreeFontInfo(fn_list, fs_list, list_num);
- fn_list = NULL;
- }
- font_name = prop_fname;
- }
- }
- if (font_data == NULL)
- continue;
-
- font_set->font_name = strdup(font_name);
- Xfree(font_name);
- if (font_set->font_name == NULL) {
- goto err;
- }
- found_num++;
- goto found;
- }
-/*
-1266793
-Limit the length of the string copy to prevent stack corruption.
- strcpy(buf, pattern);
-*/
- strncpy(buf, pattern, BUFSIZ);
- buf[BUFSIZ-1] = '\0';
- length = strlen(buf);
- last = buf + length - 1;
-
- for (num_fields = 0, base_name = buf; *base_name != '\0'; base_name++)
- if (*base_name == '-') num_fields++;
- if (strchr(pattern, '*') == NULL) {
- if (num_fields == 12) {
- append_charset = True;
- *++last = '-';
- last++;
- } else
- continue;
- } else {
- if (num_fields == 13 || num_fields == 14) {
- /*
- * There are 14 fields in an XLFD name -- make certain the
- * charset (& encoding) is placed in the correct field.
- */
- append_charset = True;
- last = strrchr (buf, '-');
- if (num_fields == 14) {
- *last = '\0';
- last = strrchr (buf, '-');
- }
- last++;
- } else if (*last == '*') {
- append_charset = True;
- if (length > 3 && *(last-3) == '-' && *(last-2) == '*'
- && *(last-1) == '-') {
- last -= 2;
- }
- *++last = '-';
- last++;
- } else {
- last = strrchr (buf, '-');
- charset_p = last;
- charset_p = strrchr (buf, '-');
- while (*(--charset_p) != '-');
- charset_p++;
- }
- }
-
- font_set = gen->font_set;
-
- font_data = font_set->font_data;
- font_data_count = font_set->font_data_count;
- for ( ; font_data_count-- > 0; font_data++) {
- if (append_charset)
- {
-/*
-1266793
-Limit the length of the string copy to prevent stack corruption.
- strcpy(last, font_data->name);
-*/
- strncpy(last, font_data->name, BUFSIZ - length);
- buf[BUFSIZ-1] = '\0';
- }
- else {
- if (_XlcCompareISOLatin1(charset_p,
- font_data->name)) {
- continue;
- }
- }
- if ((font_set->font_name = get_font_name(oc, buf)))
- break;
- }
- if (font_set->font_name != NULL) {
- found_num++;
- goto found;
- }
- }
- found:
- base_name = strdup(oc->core.base_name_list);
- if (base_name == NULL)
- goto err;
-
- oc->core.base_name_list = base_name;
-
- XFreeStringList(name_list);
-
- return found_num;
-err:
- XFreeStringList(name_list);
-
- return -1;
-}
-
-static Bool
-set_missing_list(
- XOC oc)
-{
- XOCGenericPart *gen = XOC_GENERIC(oc);
- FontSet font_set;
- char **charset_list, *charset_buf;
- int count, length;
-
- font_set = gen->font_set;
- count = length = 0;
-
- if (!font_set->info && !font_set->font) {
- length += strlen(font_set->font_data->name) + 1;
- count++;
- }
-
- if (count == 0)
- return True;
-
- charset_list = (char **) Xmalloc(sizeof(char *));
- if (charset_list == NULL)
- return False;
-
- charset_buf = (char *) Xmalloc(length);
- if (charset_buf == NULL) {
- Xfree(charset_list);
- return False;
- }
-
- oc->core.missing_list.charset_list = charset_list;
-
- font_set = gen->font_set;
-
- if (!font_set->info && !font_set->font) {
- strcpy(charset_buf, font_set->font_data->name);
- *charset_list++ = charset_buf;
- charset_buf += strlen(charset_buf) + 1;
- }
- return True;
-}
-
-static Bool
-create_fontset(
- XOC oc)
-{
- int found_num;
-
- if (init_fontset(oc) == False)
- return False;
-
- found_num = parse_fontname(oc);
- if (found_num <= 0) {
- if (found_num == 0)
- set_missing_list(oc);
- return False;
- }
-
- if (load_font(oc) == False)
- return False;
-
- if (init_core_part(oc) == False)
- return False;
-
- if (set_missing_list(oc) == False)
- return False;
-
- return True;
-}
-
-static void
-destroy_oc(
- XOC oc)
-{
- Display *dpy = oc->core.om->core.display;
- XOCGenericPart *gen = XOC_GENERIC(oc);
- XFontStruct **font_list, *font;
-
- if (gen->font_set)
- Xfree(gen->font_set);
-
- if (oc->core.base_name_list)
- Xfree(oc->core.base_name_list);
-
- if (oc->core.font_info.font_name_list)
- XFreeStringList(oc->core.font_info.font_name_list);
-
- if ((font_list = oc->core.font_info.font_struct_list)) {
- if ((font = *font_list)) {
- if (font->fid)
- XFreeFont(dpy, font);
- else
- XFreeFontInfo(NULL, font, 1);
- }
- Xfree(oc->core.font_info.font_struct_list);
- }
-
- if (oc->core.missing_list.charset_list)
- XFreeStringList(oc->core.missing_list.charset_list);
-
-#ifdef notdef
- if (oc->core.res_name)
- Xfree(oc->core.res_name);
- if (oc->core.res_class)
- Xfree(oc->core.res_class);
-#endif
-
- Xfree(oc);
-}
-
-static char *
-set_oc_values(
- XOC oc,
- XlcArgList args,
- int num_args)
-{
- if (oc->core.resources == NULL)
- return NULL;
-
- return _XlcSetValues((XPointer) oc, oc->core.resources,
- oc->core.num_resources, args, num_args, XlcSetMask);
-}
-
-static char *
-get_oc_values(
- XOC oc,
- XlcArgList args,
- int num_args)
-{
- if (oc->core.resources == NULL)
- return NULL;
-
- return _XlcGetValues((XPointer) oc, oc->core.resources,
- oc->core.num_resources, args, num_args, XlcGetMask);
-}
-
-static Bool
-wcs_to_mbs(
- XOC oc,
- char *to,
- _Xconst wchar_t *from,
- int length)
-{
- XlcConv conv = XOC_GENERIC(oc)->wcs_to_cs;
- XLCd lcd;
- int ret, to_left = length;
-
- if (conv == NULL) {
- lcd = oc->core.om->core.lcd;
- conv = _XlcOpenConverter(lcd, XlcNWideChar, lcd, XlcNMultiByte);
- if (conv == NULL)
- return False;
- XOC_GENERIC(oc)->wcs_to_cs = conv;
- } else
- _XlcResetConverter(conv);
-
- ret = _XlcConvert(conv, (XPointer *) &from, &length, (XPointer *) &to,
- &to_left, NULL, 0);
- if (ret != 0 || length > 0)
- return False;
-
- return True;
-}
-
-static int
-_XmbDefaultTextEscapement(XOC oc, _Xconst char *text, int length)
-{
- return XTextWidth(*oc->core.font_info.font_struct_list, text, length);
-}
-
-static int
-_XwcDefaultTextEscapement(XOC oc, _Xconst wchar_t *text, int length)
-{
- DefineLocalBuf;
- char *buf = AllocLocalBuf(length);
- int ret = 0;
-
- if (buf == NULL)
- return 0;
-
- if (wcs_to_mbs(oc, buf, text, length) == False)
- goto err;
-
- ret = _XmbDefaultTextEscapement(oc, buf, length);
-
-err:
- FreeLocalBuf(buf);
-
- return ret;
-}
-
-static int
-_XmbDefaultTextExtents(XOC oc, _Xconst char *text, int length,
- XRectangle *overall_ink, XRectangle *overall_logical)
-{
- int direction, logical_ascent, logical_descent;
- XCharStruct overall;
-
- XTextExtents(*oc->core.font_info.font_struct_list, text, length, &direction,
- &logical_ascent, &logical_descent, &overall);
-
- if (overall_ink) {
- overall_ink->x = overall.lbearing;
- overall_ink->y = -(overall.ascent);
- overall_ink->width = overall.rbearing - overall.lbearing;
- overall_ink->height = overall.ascent + overall.descent;
- }
-
- if (overall_logical) {
- overall_logical->x = 0;
- overall_logical->y = -(logical_ascent);
- overall_logical->width = overall.width;
- overall_logical->height = logical_ascent + logical_descent;
- }
-
- return overall.width;
-}
-
-static int
-_XwcDefaultTextExtents(XOC oc, _Xconst wchar_t *text, int length,
- XRectangle *overall_ink, XRectangle *overall_logical)
-{
- DefineLocalBuf;
- char *buf = AllocLocalBuf(length);
- int ret = 0;
-
- if (buf == NULL)
- return 0;
-
- if (wcs_to_mbs(oc, buf, text, length) == False)
- goto err;
-
- ret = _XmbDefaultTextExtents(oc, buf, length, overall_ink, overall_logical);
-
-err:
- FreeLocalBuf(buf);
-
- return ret;
-}
-
-static Status
-_XmbDefaultTextPerCharExtents(XOC oc, _Xconst char *text, int length,
- XRectangle *ink_buf, XRectangle *logical_buf,
- int buf_size, int *num_chars,
- XRectangle *overall_ink,
- XRectangle *overall_logical)
-{
- XFontStruct *font = *oc->core.font_info.font_struct_list;
- XCharStruct *def, *cs, overall;
- Bool first = True;
-
- if (buf_size < length)
- return 0;
-
- bzero((char *) &overall, sizeof(XCharStruct));
- *num_chars = 0;
-
- CI_GET_DEFAULT_INFO_1D(font, def)
-
- while (length-- > 0) {
- CI_GET_CHAR_INFO_1D(font, *text, def, cs)
- text++;
- if (cs == NULL)
- continue;
-
- ink_buf->x = overall.width + cs->lbearing;
- ink_buf->y = -(cs->ascent);
- ink_buf->width = cs->rbearing - cs->lbearing;
- ink_buf->height = cs->ascent + cs->descent;
- ink_buf++;
-
- logical_buf->x = overall.width;
- logical_buf->y = -(font->ascent);
- logical_buf->width = cs->width;
- logical_buf->height = font->ascent + font->descent;
- logical_buf++;
-
- if (first) {
- overall = *cs;
- first = False;
- } else {
- overall.ascent = max(overall.ascent, cs->ascent);
- overall.descent = max(overall.descent, cs->descent);
- overall.lbearing = min(overall.lbearing, overall.width +
- cs->lbearing);
- overall.rbearing = max(overall.rbearing, overall.width +
- cs->rbearing);
- overall.width += cs->width;
- }
- (*num_chars)++;
- }
-
- if (overall_ink) {
- overall_ink->x = overall.lbearing;
- overall_ink->y = -(overall.ascent);
- overall_ink->width = overall.rbearing - overall.lbearing;
- overall_ink->height = overall.ascent + overall.descent;
- }
-
- if (overall_logical) {
- overall_logical->x = 0;
- overall_logical->y = -(font->ascent);
- overall_logical->width = overall.width;
- overall_logical->height = font->ascent + font->descent;
- }
-
- return 1;
-}
-
-static Status
-_XwcDefaultTextPerCharExtents(XOC oc, _Xconst wchar_t *text, int length,
- XRectangle *ink_buf, XRectangle *logical_buf,
- int buf_size, int *num_chars,
- XRectangle *overall_ink,
- XRectangle *overall_logical)
-{
- DefineLocalBuf;
- char *buf = AllocLocalBuf(length);
- Status ret = 0;
-
- if (buf == NULL)
- return 0;
-
- if (wcs_to_mbs(oc, buf, text, length) == False)
- goto err;
-
- ret = _XmbDefaultTextPerCharExtents(oc, buf, length, ink_buf, logical_buf,
- buf_size, num_chars, overall_ink,
- overall_logical);
-
-err:
- FreeLocalBuf(buf);
-
- return ret;
-}
-
-static int
-_XmbDefaultDrawString(Display *dpy, Drawable d, XOC oc, GC gc, int x, int y,
- _Xconst char *text, int length)
-{
- XFontStruct *font = *oc->core.font_info.font_struct_list;
-
- XSetFont(dpy, gc, font->fid);
- XDrawString(dpy, d, gc, x, y, text, length);
-
- return XTextWidth(font, text, length);
-}
-
-static int
-_XwcDefaultDrawString(Display *dpy, Drawable d, XOC oc, GC gc, int x, int y,
- _Xconst wchar_t *text, int length)
-{
- DefineLocalBuf;
- char *buf = AllocLocalBuf(length);
- int ret = 0;
-
- if (buf == NULL)
- return 0;
-
- if (wcs_to_mbs(oc, buf, text, length) == False)
- goto err;
-
- ret = _XmbDefaultDrawString(dpy, d, oc, gc, x, y, buf, length);
-
-err:
- FreeLocalBuf(buf);
-
- return ret;
-}
-
-static void
-_XmbDefaultDrawImageString(Display *dpy, Drawable d, XOC oc, GC gc, int x,
- int y, _Xconst char *text, int length)
-{
- XSetFont(dpy, gc, (*oc->core.font_info.font_struct_list)->fid);
- XDrawImageString(dpy, d, gc, x, y, text, length);
-}
-
-static void
-_XwcDefaultDrawImageString(Display *dpy, Drawable d, XOC oc, GC gc, int x,
- int y, _Xconst wchar_t *text, int length)
-{
- DefineLocalBuf;
- char *buf = AllocLocalBuf(length);
-
- if (buf == NULL)
- return;
-
- if (wcs_to_mbs(oc, buf, text, length) == False)
- goto err;
-
- _XmbDefaultDrawImageString(dpy, d, oc, gc, x, y, buf, length);
-
-err:
- FreeLocalBuf(buf);
-}
-
-static _Xconst XOCMethodsRec oc_default_methods = {
- destroy_oc,
- set_oc_values,
- get_oc_values,
- _XmbDefaultTextEscapement,
- _XmbDefaultTextExtents,
- _XmbDefaultTextPerCharExtents,
- _XmbDefaultDrawString,
- _XmbDefaultDrawImageString,
- _XwcDefaultTextEscapement,
- _XwcDefaultTextExtents,
- _XwcDefaultTextPerCharExtents,
- _XwcDefaultDrawString,
- _XwcDefaultDrawImageString
-};
-
-static XlcResource oc_resources[] = {
- { XNBaseFontName, NULLQUARK, sizeof(char *),
- XOffsetOf(XOCRec, core.base_name_list), XlcCreateMask | XlcGetMask },
- { XNOMAutomatic, NULLQUARK, sizeof(Bool),
- XOffsetOf(XOCRec, core.om_automatic), XlcGetMask },
- { XNMissingCharSet, NULLQUARK, sizeof(XOMCharSetList),
- XOffsetOf(XOCRec, core.missing_list), XlcGetMask },
- { XNDefaultString, NULLQUARK, sizeof(char *),
- XOffsetOf(XOCRec, core.default_string), XlcGetMask },
- { XNOrientation, NULLQUARK, sizeof(XOrientation),
- XOffsetOf(XOCRec, core.orientation), XlcSetMask | XlcGetMask },
- { XNResourceName, NULLQUARK, sizeof(char *),
- XOffsetOf(XOCRec, core.res_name), XlcSetMask | XlcGetMask },
- { XNResourceClass, NULLQUARK, sizeof(char *),
- XOffsetOf(XOCRec, core.res_class), XlcSetMask | XlcGetMask },
- { XNFontInfo, NULLQUARK, sizeof(XOMFontInfo),
- XOffsetOf(XOCRec, core.font_info), XlcGetMask }
-};
-
-static XOC
-create_oc(
- XOM om,
- XlcArgList args,
- int num_args)
-{
- XOC oc;
-
- oc = Xcalloc(1, sizeof(XOCGenericRec));
- if (oc == NULL)
- return (XOC) NULL;
-
- oc->core.om = om;
-
- if (oc_resources[0].xrm_name == NULLQUARK)
- _XlcCompileResourceList(oc_resources, XlcNumber(oc_resources));
-
- if (_XlcSetValues((XPointer) oc, oc_resources, XlcNumber(oc_resources),
- args, num_args, XlcCreateMask | XlcDefaultMask))
- goto err;
-
- if (oc->core.base_name_list == NULL)
- goto err;
-
- oc->core.resources = oc_resources;
- oc->core.num_resources = XlcNumber(oc_resources);
-
- if (create_fontset(oc) == False)
- goto err;
-
- oc->methods = (XOCMethods)&oc_default_methods;
-
- return oc;
-
-err:
- destroy_oc(oc);
-
- return (XOC) NULL;
-}
-
-static Status
-close_om(
- XOM om)
-{
- XOMGenericPart *gen = XOM_GENERIC(om);
- OMData data;
- FontData font_data;
- int count;
-
- if ((data = gen->data)) {
- if (data->font_data) {
- for (font_data = data->font_data, count = data->font_data_count;
- count-- > 0 ; font_data++) {
- if (font_data->name)
- Xfree(font_data->name);
- }
- Xfree(data->font_data);
- }
- Xfree(gen->data);
- }
-
- if (om->core.res_name)
- Xfree(om->core.res_name);
- if (om->core.res_class)
- Xfree(om->core.res_class);
- if (om->core.required_charset.charset_list)
- XFreeStringList(om->core.required_charset.charset_list);
- else
- Xfree((char*)om->core.required_charset.charset_list);
- if (om->core.orientation_list.orientation)
- Xfree(om->core.orientation_list.orientation);
-
- Xfree(om);
-
- return 1;
-}
-
-static char *
-set_om_values(
- XOM om,
- XlcArgList args,
- int num_args)
-{
- if (om->core.resources == NULL)
- return NULL;
-
- return _XlcSetValues((XPointer) om, om->core.resources,
- om->core.num_resources, args, num_args, XlcSetMask);
-}
-
-static char *
-get_om_values(
- XOM om,
- XlcArgList args,
- int num_args)
-{
- if (om->core.resources == NULL)
- return NULL;
-
- return _XlcGetValues((XPointer) om, om->core.resources,
- om->core.num_resources, args, num_args, XlcGetMask);
-}
-
-static _Xconst XOMMethodsRec methods = {
- close_om,
- set_om_values,
- get_om_values,
- create_oc
-};
-
-static XlcResource om_resources[] = {
- { XNRequiredCharSet, NULLQUARK, sizeof(XOMCharSetList),
- XOffsetOf(XOMRec, core.required_charset), XlcGetMask },
- { XNQueryOrientation, NULLQUARK, sizeof(XOMOrientation),
- XOffsetOf(XOMRec, core.orientation_list), XlcGetMask },
- { XNDirectionalDependentDrawing, NULLQUARK, sizeof(Bool),
- XOffsetOf(XOMRec, core.directional_dependent), XlcGetMask },
- { XNContextualDrawing, NULLQUARK, sizeof(Bool),
- XOffsetOf(XOMRec, core.contextual_drawing), XlcGetMask }
-};
-
-static OMData
-add_data(
- XOM om)
-{
- XOMGenericPart *gen = XOM_GENERIC(om);
- OMData new;
-
- new = Xcalloc(1, sizeof(OMDataRec));
-
- if (new == NULL)
- return NULL;
-
- gen->data = new;
-
- return new;
-}
-
-static _Xconst char *supported_charset_list[] = {
- "ISO8859-1",
-/* fix for bug4332979 */
- "adobe-fontspecific",
-/* fix for bug4237353: "JISX0201.1976-0" entry should be removed from
- supported_charset_list because it is not a supported_charset for C locale
- "JISX0201.1976-0", */
- "SUNOLCURSOR-1",
- "SUNOLGLYPH-1"
-};
-
-static Bool
-init_om(
- XOM om)
-{
- XOMGenericPart *gen = XOM_GENERIC(om);
- OMData data;
- FontData font_data;
- char **required_list;
- XOrientation *orientation;
- char **value, buf[BUFSIZ], *bufptr;
- int count, length = 0;
-
- value = (char**)supported_charset_list;
- count = XlcNumber(supported_charset_list);
-
- data = add_data(om);
- if (data == NULL)
- return False;
-
- font_data = Xcalloc(count, sizeof(FontDataRec));
- if (font_data == NULL)
- return False;
- data->font_data = font_data;
- data->font_data_count = count;
-
- for ( ; count-- > 0; font_data++) {
-/*
-1266793
-This one is fine. *value points to one of the local strings in
-supported_charset_list[].
-*/
- strcpy(buf, *value++);
- font_data->name = strdup(buf);
- if (font_data->name == NULL)
- return False;
- }
-
- length += strlen(data->font_data->name) + 1;
-
- /* required charset list */
- required_list = (char **) Xmalloc(sizeof(char *));
- if (required_list == NULL)
- return False;
-
- bufptr = (char *) Xmalloc(length);
- if (bufptr == NULL) {
- Xfree(required_list);
- return False;
- }
-
- om->core.required_charset.charset_list = required_list;
- om->core.required_charset.charset_count = 1; /* always 1 */
-
- data = gen->data;
-
- strcpy(bufptr, data->font_data->name);
- *required_list++ = bufptr;
- bufptr += strlen(bufptr) + 1;
-
- /* orientation list */
- orientation = (XOrientation *) Xmalloc(sizeof(XOrientation));
- if (orientation == NULL)
- return False;
-
- *orientation = XOMOrientation_LTR_TTB;
- om->core.orientation_list.orientation = orientation;
- om->core.orientation_list.num_orientation = 1;
-
- /* directional dependent drawing */
- om->core.directional_dependent = False;
-
- /* contexual drawing */
- om->core.contextual_drawing = False;
-
- /* context dependent */
- om->core.context_dependent = False;
-
- return True;
-}
-
-XOM
-_XDefaultOpenOM(XLCd lcd, Display *dpy, XrmDatabase rdb,
- _Xconst char *res_name, _Xconst char *res_class)
-{
- XOM om;
-
- om = Xcalloc(1, sizeof(XOMGenericRec));
- if (om == NULL)
- return (XOM) NULL;
-
- om->methods = (XOMMethods)&methods;
- om->core.lcd = lcd;
- om->core.display = dpy;
- om->core.rdb = rdb;
- if (res_name) {
- om->core.res_name = strdup(res_name);
- if (om->core.res_name == NULL)
- goto err;
- }
- if (res_class) {
- om->core.res_class = strdup(res_class);
- if (om->core.res_class == NULL)
- goto err;
- }
-
- if (om_resources[0].xrm_name == NULLQUARK)
- _XlcCompileResourceList(om_resources, XlcNumber(om_resources));
-
- om->core.resources = om_resources;
- om->core.num_resources = XlcNumber(om_resources);
-
- if (init_om(om) == False)
- goto err;
-
- return om;
-err:
- close_om(om);
-
- return (XOM) NULL;
-}
+/* +Copyright 1985, 1986, 1987, 1991, 1998 The Open Group + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: The above copyright notice and this +permission notice shall be included in all copies or substantial +portions of the Software. + + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE +EVEN IF ADVISED IN ADVANCE OF THE POSSIBILITY OF SUCH DAMAGES. + + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +X Window System is a trademark of The Open Group + +OSF/1, OSF/Motif and Motif are registered trademarks, and OSF, the OSF +logo, LBX, X Window System, and Xinerama are trademarks of the Open +Group. All other trademarks and registered trademarks mentioned herein +are the property of their respective owners. No right, title or +interest in or to any trademark, service mark, logo or trade name of +Sun Microsystems, Inc. or its licensors is granted. + +*/ +/* + * Copyright 2000 Oracle and/or its affiliates. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include "Xlibint.h" +#include "Xlcint.h" +#include "XlcPublic.h" +#include <X11/Xos.h> +#include <X11/Xatom.h> +#include <stdio.h> +#include <unistd.h> +#include <stdint.h> + +#define MAXFONTS 100 + +#define XOM_GENERIC(om) (&((XOMGeneric) om)->gen) +#define XOC_GENERIC(font_set) (&((XOCGeneric) font_set)->gen) + +#define DefineLocalBuf char local_buf[BUFSIZ] +#define AllocLocalBuf(length) (length > BUFSIZ ? (char *)Xmalloc(length) : local_buf) +#define FreeLocalBuf(ptr) if (ptr != local_buf) Xfree(ptr) + +typedef struct _FontDataRec { + char *name; +} FontDataRec, *FontData; + +typedef struct _OMDataRec { + int font_data_count; + FontData font_data; +} OMDataRec, *OMData; + +typedef struct _XOMGenericPart { + OMData data; +} XOMGenericPart; + +typedef struct _XOMGenericRec { + XOMMethods methods; + XOMCoreRec core; + XOMGenericPart gen; +} XOMGenericRec, *XOMGeneric; + +typedef struct _FontSetRec { + int id; + int font_data_count; + FontData font_data; + char *font_name; + XFontStruct *info; + XFontStruct *font; +} FontSetRec, *FontSet; + +typedef struct _XOCGenericPart { + XlcConv wcs_to_cs; + FontSet font_set; +} XOCGenericPart; + +typedef struct _XOCGenericRec { + XOCMethods methods; + XOCCoreRec core; + XOCGenericPart gen; +} XOCGenericRec, *XOCGeneric; + +static Bool +init_fontset( + XOC oc) +{ + XOCGenericPart *gen; + FontSet font_set; + OMData data; + + data = XOM_GENERIC(oc->core.om)->data; + + font_set = Xcalloc(1, sizeof(FontSetRec)); + if (font_set == NULL) + return False; + + gen = XOC_GENERIC(oc); + gen->font_set = font_set; + + font_set->font_data_count = data->font_data_count; + font_set->font_data = data->font_data; + + return True; +} + +static char * +get_prop_name( + Display *dpy, + XFontStruct *fs) +{ + unsigned long fp; + + if (XGetFontProperty(fs, XA_FONT, &fp)) + return XGetAtomName(dpy, fp); + + return (char *) NULL; +} + +static FontData +check_charset( + FontSet font_set, + char *font_name) +{ + FontData font_data; + char *last; + int count; + ssize_t length, name_len; + + name_len = strlen(font_name); + last = font_name + name_len; + + count = font_set->font_data_count; + font_data = font_set->font_data; + + for ( ; count-- > 0; font_data++) { + length = strlen(font_data->name); + + if (length > name_len) + return(NULL); + + if (_XlcCompareISOLatin1(last - length, font_data->name) == 0) + return font_data; + } + return (FontData) NULL; +} + +#if 0 /* Unused */ +static int +check_fontname( + XOC oc, + char *name) +{ + Display *dpy = oc->core.om->core.display; + XOCGenericPart *gen = XOC_GENERIC(oc); + FontData data; + FontSet font_set; + XFontStruct *fs_list; + char **fn_list, *fname, *prop_fname = NULL; + int list_num, i; + int list2_num; + char **fn2_list = NULL; + int found_num = 0; + + fn_list = XListFonts(dpy, name, MAXFONTS, &list_num); + if (fn_list == NULL) + return found_num; + + for (i = 0; i < list_num; i++) { + fname = fn_list[i]; + + font_set = gen->font_set; + + if ((data = check_charset(font_set, fname)) == NULL) { + if ((fn2_list = XListFontsWithInfo(dpy, name, MAXFONTS, + &list2_num, &fs_list)) + && (prop_fname = get_prop_name(dpy, fs_list)) + && (data = check_charset(font_set, prop_fname))) + fname = prop_fname; + } + if (data) { + font_set->font_name = strdup(fname); + if (font_set->font_name) { + found_num++; + } + } + if (fn2_list) { + XFreeFontInfo(fn2_list, fs_list, list2_num); + fn2_list = NULL; + if (prop_fname) { + Xfree(prop_fname); + prop_fname = NULL; + } + } + if (found_num == 1) + break; + } + XFreeFontNames(fn_list); + return found_num; +} +#endif + +static Bool +load_font( + XOC oc) +{ + Display *dpy = oc->core.om->core.display; + XOCGenericPart *gen = XOC_GENERIC(oc); + FontSet font_set = gen->font_set; + + if (font_set->font_name == NULL) + return False; + + if (font_set->font == NULL) { + font_set->font = XLoadQueryFont(dpy, font_set->font_name); + if (font_set->font == NULL) + return False; + } + return True; +} + +#if 0 +static Bool +load_font_info( + XOC oc) +{ + Display *dpy = oc->core.om->core.display; + XOCGenericPart *gen = XOC_GENERIC(oc); + FontSet font_set = gen->font_set; + char **fn_list; + int fn_num; + + if (font_set->font_name == NULL) + return False; + + if (font_set->info == NULL) { + fn_list = XListFontsWithInfo(dpy, font_set->font_name, 1, &fn_num, + &font_set->info); + if (font_set->info == NULL) + return False; + if (fn_num > 0) + font_set->info->fid = XLoadFont(dpy, font_set->font_name); + + if (fn_list) XFreeFontNames(fn_list); + } + return True; +} +#endif + +static void +set_fontset_extents( + XOC oc) +{ + XRectangle *ink = &oc->core.font_set_extents.max_ink_extent; + XRectangle *logical = &oc->core.font_set_extents.max_logical_extent; + XFontStruct **font_list, *font; + XCharStruct overall; + int logical_ascent, logical_descent; + + font_list = oc->core.font_info.font_struct_list; + font = *font_list++; + overall = font->max_bounds; + overall.lbearing = font->min_bounds.lbearing; + logical_ascent = font->ascent; + logical_descent = font->descent; + + ink->x = overall.lbearing; + ink->y = -(overall.ascent); + ink->width = overall.rbearing - overall.lbearing; + ink->height = overall.ascent + overall.descent; + + logical->x = 0; + logical->y = -(logical_ascent); + logical->width = overall.width; + logical->height = logical_ascent + logical_descent; +} + +static Bool +init_core_part( + XOC oc) +{ + XOCGenericPart *gen = XOC_GENERIC(oc); + FontSet font_set; + XFontStruct **font_struct_list; + char **font_name_list, *font_name_buf; + int count, length; + + font_set = gen->font_set; + count = length = 0; + + if (font_set->font_name != NULL) { + length += strlen(font_set->font_name) + 1; + count++; + } + if (count == 0) + return False; + + font_struct_list = (XFontStruct **) Xmalloc(sizeof(XFontStruct *)); + if (font_struct_list == NULL) + return False; + + font_name_list = (char **) Xmalloc(sizeof(char *)); + if (font_name_list == NULL) + goto err; + + font_name_buf = (char *) Xmalloc(length); + if (font_name_buf == NULL) + goto err; + + oc->core.font_info.num_font = 1; + oc->core.font_info.font_name_list = font_name_list; + oc->core.font_info.font_struct_list = font_struct_list; + + font_set = gen->font_set; + + if (font_set->font_name != NULL) { + font_set->id = 1; + if (font_set->font) + *font_struct_list++ = font_set->font; + else + *font_struct_list++ = font_set->info; + strcpy(font_name_buf, font_set->font_name); + Xfree(font_set->font_name); + *font_name_list++ = font_set->font_name = font_name_buf; + font_name_buf += strlen(font_name_buf) + 1; + } + + set_fontset_extents(oc); + + return True; + +err: + if (font_name_list) + Xfree(font_name_list); + Xfree(font_struct_list); + + return False; +} + +static char * +get_font_name( + XOC oc, + char *pattern) +{ + char **list, *name; + int count; + XFontStruct *fs; + Display *dpy = oc->core.om->core.display; + + list = XListFonts(dpy, pattern, 1, &count); + if (list != NULL) { + name = strdup(*list); + + XFreeFontNames(list); + } else { + fs = XLoadQueryFont(dpy, pattern); + if (fs == NULL) return NULL; + + name = get_prop_name(dpy, fs); + XFreeFont(dpy, fs); + } + return name; +} + +static int +parse_fontname( + XOC oc) +{ + XOCGenericPart *gen = XOC_GENERIC(oc); + FontSet font_set; + FontData font_data; + char *pattern, *last, buf[BUFSIZ]; + int font_data_count, found_num = 0; + ssize_t length; + int count, num_fields; + char *base_name, *font_name, **name_list, **cur_name_list; + char *charset_p = NULL; + Bool append_charset; + /* + append_charset flag should be set to True when the XLFD fontname + doesn't contain a chaset part. + */ + + name_list = _XParseBaseFontNameList(oc->core.base_name_list, &count); + if (name_list == NULL) + return -1; + cur_name_list = name_list; + + while (count-- > 0) { + pattern = *cur_name_list++; + if (pattern == NULL || *pattern == '\0') + continue; + + append_charset = False; + + if (strchr(pattern, '*') == NULL && + (font_name = get_font_name(oc, pattern))) { + + font_set = gen->font_set; + + font_data = check_charset(font_set, font_name); + if (font_data == NULL) { + Display *dpy = oc->core.om->core.display; + char **fn_list = NULL, *prop_fname = NULL; + int list_num; + XFontStruct *fs_list; + if ((fn_list = XListFontsWithInfo(dpy, font_name, + MAXFONTS, + &list_num, &fs_list)) + && (prop_fname = get_prop_name(dpy, fs_list)) + && (font_data = check_charset(font_set, prop_fname))) { + if (fn_list) { + XFreeFontInfo(fn_list, fs_list, list_num); + fn_list = NULL; + } + font_name = prop_fname; + } + } + if (font_data == NULL) + continue; + + font_set->font_name = strdup(font_name); + Xfree(font_name); + if (font_set->font_name == NULL) { + goto err; + } + found_num++; + goto found; + } +/* +1266793 +Limit the length of the string copy to prevent stack corruption. + strcpy(buf, pattern); +*/ + strncpy(buf, pattern, BUFSIZ); + buf[BUFSIZ-1] = '\0'; + length = strlen(buf); + last = buf + length - 1; + + for (num_fields = 0, base_name = buf; *base_name != '\0'; base_name++) + if (*base_name == '-') num_fields++; + if (strchr(pattern, '*') == NULL) { + if (num_fields == 12) { + append_charset = True; + *++last = '-'; + last++; + } else + continue; + } else { + if (num_fields == 13 || num_fields == 14) { + /* + * There are 14 fields in an XLFD name -- make certain the + * charset (& encoding) is placed in the correct field. + */ + append_charset = True; + last = strrchr (buf, '-'); + if (num_fields == 14) { + *last = '\0'; + last = strrchr (buf, '-'); + } + last++; + } else if (*last == '*') { + append_charset = True; + if (length > 3 && *(last-3) == '-' && *(last-2) == '*' + && *(last-1) == '-') { + last -= 2; + } + *++last = '-'; + last++; + } else { + last = strrchr (buf, '-'); + charset_p = last; + charset_p = strrchr (buf, '-'); + while (*(--charset_p) != '-'); + charset_p++; + } + } + + font_set = gen->font_set; + + font_data = font_set->font_data; + font_data_count = font_set->font_data_count; + for ( ; font_data_count-- > 0; font_data++) { + if (append_charset) + { +/* +1266793 +Limit the length of the string copy to prevent stack corruption. + strcpy(last, font_data->name); +*/ + strncpy(last, font_data->name, BUFSIZ - length); + buf[BUFSIZ-1] = '\0'; + } + else { + if (_XlcCompareISOLatin1(charset_p, + font_data->name)) { + continue; + } + } + if ((font_set->font_name = get_font_name(oc, buf))) + break; + } + if (font_set->font_name != NULL) { + found_num++; + goto found; + } + } + found: + base_name = strdup(oc->core.base_name_list); + if (base_name == NULL) + goto err; + + oc->core.base_name_list = base_name; + + XFreeStringList(name_list); + + return found_num; +err: + XFreeStringList(name_list); + + return -1; +} + +static Bool +set_missing_list( + XOC oc) +{ + XOCGenericPart *gen = XOC_GENERIC(oc); + FontSet font_set; + char **charset_list, *charset_buf; + int count, length; + + font_set = gen->font_set; + count = length = 0; + + if (!font_set->info && !font_set->font) { + length += strlen(font_set->font_data->name) + 1; + count++; + } + + if (count == 0) + return True; + + charset_list = (char **) Xmalloc(sizeof(char *)); + if (charset_list == NULL) + return False; + + charset_buf = (char *) Xmalloc(length); + if (charset_buf == NULL) { + Xfree(charset_list); + return False; + } + + oc->core.missing_list.charset_list = charset_list; + + font_set = gen->font_set; + + if (!font_set->info && !font_set->font) { + strcpy(charset_buf, font_set->font_data->name); + *charset_list++ = charset_buf; + charset_buf += strlen(charset_buf) + 1; + } + return True; +} + +static Bool +create_fontset( + XOC oc) +{ + int found_num; + + if (init_fontset(oc) == False) + return False; + + found_num = parse_fontname(oc); + if (found_num <= 0) { + if (found_num == 0) + set_missing_list(oc); + return False; + } + + if (load_font(oc) == False) + return False; + + if (init_core_part(oc) == False) + return False; + + if (set_missing_list(oc) == False) + return False; + + return True; +} + +static void +destroy_oc( + XOC oc) +{ + Display *dpy = oc->core.om->core.display; + XOCGenericPart *gen = XOC_GENERIC(oc); + XFontStruct **font_list, *font; + + if (gen->font_set) + Xfree(gen->font_set); + + if (oc->core.base_name_list) + Xfree(oc->core.base_name_list); + + if (oc->core.font_info.font_name_list) + XFreeStringList(oc->core.font_info.font_name_list); + + if ((font_list = oc->core.font_info.font_struct_list)) { + if ((font = *font_list)) { + if (font->fid) + XFreeFont(dpy, font); + else + XFreeFontInfo(NULL, font, 1); + } + Xfree(oc->core.font_info.font_struct_list); + } + + if (oc->core.missing_list.charset_list) + XFreeStringList(oc->core.missing_list.charset_list); + +#ifdef notdef + if (oc->core.res_name) + Xfree(oc->core.res_name); + if (oc->core.res_class) + Xfree(oc->core.res_class); +#endif + + Xfree(oc); +} + +static char * +set_oc_values( + XOC oc, + XlcArgList args, + int num_args) +{ + if (oc->core.resources == NULL) + return NULL; + + return _XlcSetValues((XPointer) oc, oc->core.resources, + oc->core.num_resources, args, num_args, XlcSetMask); +} + +static char * +get_oc_values( + XOC oc, + XlcArgList args, + int num_args) +{ + if (oc->core.resources == NULL) + return NULL; + + return _XlcGetValues((XPointer) oc, oc->core.resources, + oc->core.num_resources, args, num_args, XlcGetMask); +} + +static Bool +wcs_to_mbs( + XOC oc, + char *to, + _Xconst wchar_t *from, + int length) +{ + XlcConv conv = XOC_GENERIC(oc)->wcs_to_cs; + XLCd lcd; + int ret, to_left = length; + + if (conv == NULL) { + lcd = oc->core.om->core.lcd; + conv = _XlcOpenConverter(lcd, XlcNWideChar, lcd, XlcNMultiByte); + if (conv == NULL) + return False; + XOC_GENERIC(oc)->wcs_to_cs = conv; + } else + _XlcResetConverter(conv); + + ret = _XlcConvert(conv, (XPointer *) &from, &length, (XPointer *) &to, + &to_left, NULL, 0); + if (ret != 0 || length > 0) + return False; + + return True; +} + +static int +_XmbDefaultTextEscapement(XOC oc, _Xconst char *text, int length) +{ + return XTextWidth(*oc->core.font_info.font_struct_list, text, length); +} + +static int +_XwcDefaultTextEscapement(XOC oc, _Xconst wchar_t *text, int length) +{ + DefineLocalBuf; + char *buf = AllocLocalBuf(length); + int ret = 0; + + if (buf == NULL) + return 0; + + if (wcs_to_mbs(oc, buf, text, length) == False) + goto err; + + ret = _XmbDefaultTextEscapement(oc, buf, length); + +err: + FreeLocalBuf(buf); + + return ret; +} + +static int +_XmbDefaultTextExtents(XOC oc, _Xconst char *text, int length, + XRectangle *overall_ink, XRectangle *overall_logical) +{ + int direction, logical_ascent, logical_descent; + XCharStruct overall; + + XTextExtents(*oc->core.font_info.font_struct_list, text, length, &direction, + &logical_ascent, &logical_descent, &overall); + + if (overall_ink) { + overall_ink->x = overall.lbearing; + overall_ink->y = -(overall.ascent); + overall_ink->width = overall.rbearing - overall.lbearing; + overall_ink->height = overall.ascent + overall.descent; + } + + if (overall_logical) { + overall_logical->x = 0; + overall_logical->y = -(logical_ascent); + overall_logical->width = overall.width; + overall_logical->height = logical_ascent + logical_descent; + } + + return overall.width; +} + +static int +_XwcDefaultTextExtents(XOC oc, _Xconst wchar_t *text, int length, + XRectangle *overall_ink, XRectangle *overall_logical) +{ + DefineLocalBuf; + char *buf = AllocLocalBuf(length); + int ret = 0; + + if (buf == NULL) + return 0; + + if (wcs_to_mbs(oc, buf, text, length) == False) + goto err; + + ret = _XmbDefaultTextExtents(oc, buf, length, overall_ink, overall_logical); + +err: + FreeLocalBuf(buf); + + return ret; +} + +static Status +_XmbDefaultTextPerCharExtents(XOC oc, _Xconst char *text, int length, + XRectangle *ink_buf, XRectangle *logical_buf, + int buf_size, int *num_chars, + XRectangle *overall_ink, + XRectangle *overall_logical) +{ + XFontStruct *font = *oc->core.font_info.font_struct_list; + XCharStruct *def, *cs, overall; + Bool first = True; + + if (buf_size < length) + return 0; + + bzero((char *) &overall, sizeof(XCharStruct)); + *num_chars = 0; + + CI_GET_DEFAULT_INFO_1D(font, def) + + while (length-- > 0) { + CI_GET_CHAR_INFO_1D(font, *text, def, cs) + text++; + if (cs == NULL) + continue; + + ink_buf->x = overall.width + cs->lbearing; + ink_buf->y = -(cs->ascent); + ink_buf->width = cs->rbearing - cs->lbearing; + ink_buf->height = cs->ascent + cs->descent; + ink_buf++; + + logical_buf->x = overall.width; + logical_buf->y = -(font->ascent); + logical_buf->width = cs->width; + logical_buf->height = font->ascent + font->descent; + logical_buf++; + + if (first) { + overall = *cs; + first = False; + } else { + overall.ascent = max(overall.ascent, cs->ascent); + overall.descent = max(overall.descent, cs->descent); + overall.lbearing = min(overall.lbearing, overall.width + + cs->lbearing); + overall.rbearing = max(overall.rbearing, overall.width + + cs->rbearing); + overall.width += cs->width; + } + (*num_chars)++; + } + + if (overall_ink) { + overall_ink->x = overall.lbearing; + overall_ink->y = -(overall.ascent); + overall_ink->width = overall.rbearing - overall.lbearing; + overall_ink->height = overall.ascent + overall.descent; + } + + if (overall_logical) { + overall_logical->x = 0; + overall_logical->y = -(font->ascent); + overall_logical->width = overall.width; + overall_logical->height = font->ascent + font->descent; + } + + return 1; +} + +static Status +_XwcDefaultTextPerCharExtents(XOC oc, _Xconst wchar_t *text, int length, + XRectangle *ink_buf, XRectangle *logical_buf, + int buf_size, int *num_chars, + XRectangle *overall_ink, + XRectangle *overall_logical) +{ + DefineLocalBuf; + char *buf = AllocLocalBuf(length); + Status ret = 0; + + if (buf == NULL) + return 0; + + if (wcs_to_mbs(oc, buf, text, length) == False) + goto err; + + ret = _XmbDefaultTextPerCharExtents(oc, buf, length, ink_buf, logical_buf, + buf_size, num_chars, overall_ink, + overall_logical); + +err: + FreeLocalBuf(buf); + + return ret; +} + +static int +_XmbDefaultDrawString(Display *dpy, Drawable d, XOC oc, GC gc, int x, int y, + _Xconst char *text, int length) +{ + XFontStruct *font = *oc->core.font_info.font_struct_list; + + XSetFont(dpy, gc, font->fid); + XDrawString(dpy, d, gc, x, y, text, length); + + return XTextWidth(font, text, length); +} + +static int +_XwcDefaultDrawString(Display *dpy, Drawable d, XOC oc, GC gc, int x, int y, + _Xconst wchar_t *text, int length) +{ + DefineLocalBuf; + char *buf = AllocLocalBuf(length); + int ret = 0; + + if (buf == NULL) + return 0; + + if (wcs_to_mbs(oc, buf, text, length) == False) + goto err; + + ret = _XmbDefaultDrawString(dpy, d, oc, gc, x, y, buf, length); + +err: + FreeLocalBuf(buf); + + return ret; +} + +static void +_XmbDefaultDrawImageString(Display *dpy, Drawable d, XOC oc, GC gc, int x, + int y, _Xconst char *text, int length) +{ + XSetFont(dpy, gc, (*oc->core.font_info.font_struct_list)->fid); + XDrawImageString(dpy, d, gc, x, y, text, length); +} + +static void +_XwcDefaultDrawImageString(Display *dpy, Drawable d, XOC oc, GC gc, int x, + int y, _Xconst wchar_t *text, int length) +{ + DefineLocalBuf; + char *buf = AllocLocalBuf(length); + + if (buf == NULL) + return; + + if (wcs_to_mbs(oc, buf, text, length) == False) + goto err; + + _XmbDefaultDrawImageString(dpy, d, oc, gc, x, y, buf, length); + +err: + FreeLocalBuf(buf); +} + +static _Xconst XOCMethodsRec oc_default_methods = { + destroy_oc, + set_oc_values, + get_oc_values, + _XmbDefaultTextEscapement, + _XmbDefaultTextExtents, + _XmbDefaultTextPerCharExtents, + _XmbDefaultDrawString, + _XmbDefaultDrawImageString, + _XwcDefaultTextEscapement, + _XwcDefaultTextExtents, + _XwcDefaultTextPerCharExtents, + _XwcDefaultDrawString, + _XwcDefaultDrawImageString +}; + +static XlcResource oc_resources[] = { + { XNBaseFontName, NULLQUARK, sizeof(char *), + XOffsetOf(XOCRec, core.base_name_list), XlcCreateMask | XlcGetMask }, + { XNOMAutomatic, NULLQUARK, sizeof(Bool), + XOffsetOf(XOCRec, core.om_automatic), XlcGetMask }, + { XNMissingCharSet, NULLQUARK, sizeof(XOMCharSetList), + XOffsetOf(XOCRec, core.missing_list), XlcGetMask }, + { XNDefaultString, NULLQUARK, sizeof(char *), + XOffsetOf(XOCRec, core.default_string), XlcGetMask }, + { XNOrientation, NULLQUARK, sizeof(XOrientation), + XOffsetOf(XOCRec, core.orientation), XlcSetMask | XlcGetMask }, + { XNResourceName, NULLQUARK, sizeof(char *), + XOffsetOf(XOCRec, core.res_name), XlcSetMask | XlcGetMask }, + { XNResourceClass, NULLQUARK, sizeof(char *), + XOffsetOf(XOCRec, core.res_class), XlcSetMask | XlcGetMask }, + { XNFontInfo, NULLQUARK, sizeof(XOMFontInfo), + XOffsetOf(XOCRec, core.font_info), XlcGetMask } +}; + +static XOC +create_oc( + XOM om, + XlcArgList args, + int num_args) +{ + XOC oc; + + oc = Xcalloc(1, sizeof(XOCGenericRec)); + if (oc == NULL) + return (XOC) NULL; + + oc->core.om = om; + + if (oc_resources[0].xrm_name == NULLQUARK) + _XlcCompileResourceList(oc_resources, XlcNumber(oc_resources)); + + if (_XlcSetValues((XPointer) oc, oc_resources, XlcNumber(oc_resources), + args, num_args, XlcCreateMask | XlcDefaultMask)) + goto err; + + if (oc->core.base_name_list == NULL) + goto err; + + oc->core.resources = oc_resources; + oc->core.num_resources = XlcNumber(oc_resources); + + if (create_fontset(oc) == False) + goto err; + + oc->methods = (XOCMethods)&oc_default_methods; + + return oc; + +err: + destroy_oc(oc); + + return (XOC) NULL; +} + +static Status +close_om( + XOM om) +{ + XOMGenericPart *gen = XOM_GENERIC(om); + OMData data; + FontData font_data; + int count; + + if ((data = gen->data)) { + if (data->font_data) { + for (font_data = data->font_data, count = data->font_data_count; + count-- > 0 ; font_data++) { + if (font_data->name) + Xfree(font_data->name); + } + Xfree(data->font_data); + } + Xfree(gen->data); + } + + if (om->core.res_name) + Xfree(om->core.res_name); + if (om->core.res_class) + Xfree(om->core.res_class); + if (om->core.required_charset.charset_list) + XFreeStringList(om->core.required_charset.charset_list); + else + Xfree((char*)om->core.required_charset.charset_list); + if (om->core.orientation_list.orientation) + Xfree(om->core.orientation_list.orientation); + + Xfree(om); + + return 1; +} + +static char * +set_om_values( + XOM om, + XlcArgList args, + int num_args) +{ + if (om->core.resources == NULL) + return NULL; + + return _XlcSetValues((XPointer) om, om->core.resources, + om->core.num_resources, args, num_args, XlcSetMask); +} + +static char * +get_om_values( + XOM om, + XlcArgList args, + int num_args) +{ + if (om->core.resources == NULL) + return NULL; + + return _XlcGetValues((XPointer) om, om->core.resources, + om->core.num_resources, args, num_args, XlcGetMask); +} + +static _Xconst XOMMethodsRec methods = { + close_om, + set_om_values, + get_om_values, + create_oc +}; + +static XlcResource om_resources[] = { + { XNRequiredCharSet, NULLQUARK, sizeof(XOMCharSetList), + XOffsetOf(XOMRec, core.required_charset), XlcGetMask }, + { XNQueryOrientation, NULLQUARK, sizeof(XOMOrientation), + XOffsetOf(XOMRec, core.orientation_list), XlcGetMask }, + { XNDirectionalDependentDrawing, NULLQUARK, sizeof(Bool), + XOffsetOf(XOMRec, core.directional_dependent), XlcGetMask }, + { XNContextualDrawing, NULLQUARK, sizeof(Bool), + XOffsetOf(XOMRec, core.contextual_drawing), XlcGetMask } +}; + +static OMData +add_data( + XOM om) +{ + XOMGenericPart *gen = XOM_GENERIC(om); + OMData new; + + new = Xcalloc(1, sizeof(OMDataRec)); + + if (new == NULL) + return NULL; + + gen->data = new; + + return new; +} + +static _Xconst char *supported_charset_list[] = { + "ISO8859-1", +/* fix for bug4332979 */ + "adobe-fontspecific", +/* fix for bug4237353: "JISX0201.1976-0" entry should be removed from + supported_charset_list because it is not a supported_charset for C locale + "JISX0201.1976-0", */ + "SUNOLCURSOR-1", + "SUNOLGLYPH-1" +}; + +static Bool +init_om( + XOM om) +{ + XOMGenericPart *gen = XOM_GENERIC(om); + OMData data; + FontData font_data; + char **required_list; + XOrientation *orientation; + char **value, buf[BUFSIZ], *bufptr; + int count, length = 0; + + value = (char**)supported_charset_list; + count = XlcNumber(supported_charset_list); + + data = add_data(om); + if (data == NULL) + return False; + + font_data = Xcalloc(count, sizeof(FontDataRec)); + if (font_data == NULL) + return False; + data->font_data = font_data; + data->font_data_count = count; + + for ( ; count-- > 0; font_data++) { +/* +1266793 +This one is fine. *value points to one of the local strings in +supported_charset_list[]. +*/ + strcpy(buf, *value++); + font_data->name = strdup(buf); + if (font_data->name == NULL) + return False; + } + + length += strlen(data->font_data->name) + 1; + + /* required charset list */ + required_list = (char **) Xmalloc(sizeof(char *)); + if (required_list == NULL) + return False; + + bufptr = (char *) Xmalloc(length); + if (bufptr == NULL) { + Xfree(required_list); + return False; + } + + om->core.required_charset.charset_list = required_list; + om->core.required_charset.charset_count = 1; /* always 1 */ + + data = gen->data; + + strcpy(bufptr, data->font_data->name); + *required_list++ = bufptr; + bufptr += strlen(bufptr) + 1; + + /* orientation list */ + orientation = (XOrientation *) Xmalloc(sizeof(XOrientation)); + if (orientation == NULL) + return False; + + *orientation = XOMOrientation_LTR_TTB; + om->core.orientation_list.orientation = orientation; + om->core.orientation_list.num_orientation = 1; + + /* directional dependent drawing */ + om->core.directional_dependent = False; + + /* contexual drawing */ + om->core.contextual_drawing = False; + + /* context dependent */ + om->core.context_dependent = False; + + return True; +} + +XOM +_XDefaultOpenOM(XLCd lcd, Display *dpy, XrmDatabase rdb, + _Xconst char *res_name, _Xconst char *res_class) +{ + XOM om; + + om = Xcalloc(1, sizeof(XOMGenericRec)); + if (om == NULL) + return (XOM) NULL; + + om->methods = (XOMMethods)&methods; + om->core.lcd = lcd; + om->core.display = dpy; + om->core.rdb = rdb; + if (res_name) { + om->core.res_name = strdup(res_name); + if (om->core.res_name == NULL) + goto err; + } + if (res_class) { + om->core.res_class = strdup(res_class); + if (om->core.res_class == NULL) + goto err; + } + + if (om_resources[0].xrm_name == NULLQUARK) + _XlcCompileResourceList(om_resources, XlcNumber(om_resources)); + + om->core.resources = om_resources; + om->core.num_resources = XlcNumber(om_resources); + + if (init_om(om) == False) + goto err; + + return om; +err: + close_om(om); + + return (XOM) NULL; +} diff --git a/libX11/src/xlibi18n/XlcDL.c b/libX11/src/xlibi18n/XlcDL.c index 4a05c40e4..75e193c05 100644 --- a/libX11/src/xlibi18n/XlcDL.c +++ b/libX11/src/xlibi18n/XlcDL.c @@ -1,612 +1,612 @@ -/*
-Copyright 1985, 1986, 1987, 1991, 1998 The Open Group
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions: The above copyright notice and this
-permission notice shall be included in all copies or substantial
-portions of the Software.
-
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
-EVEN IF ADVISED IN ADVANCE OF THE POSSIBILITY OF SUCH DAMAGES.
-
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-
-X Window System is a trademark of The Open Group
-
-OSF/1, OSF/Motif and Motif are registered trademarks, and OSF, the OSF
-logo, LBX, X Window System, and Xinerama are trademarks of the Open
-Group. All other trademarks and registered trademarks mentioned herein
-are the property of their respective owners. No right, title or
-interest in or to any trademark, service mark, logo or trade name of
-Sun Microsystems, Inc. or its licensors is granted.
-
-*/
-/*
- * Copyright 2000 Oracle and/or its affiliates. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#else
-# if defined(hpux)
-# define HAVE_DL_H
-# else
-# define HAVE_DLFCN_H
-# endif
-#endif
-
-#include <stdio.h>
-
-#ifdef HAVE_DL_H
-#include <dl.h>
-#endif
-
-#ifdef HAVE_DLFCN_H
-#include <dlfcn.h>
-#endif
-
-#include <ctype.h>
-
-#include "Xlibint.h"
-#include "XlcPublic.h"
-#include "XlcPubI.h"
-
-#define XI18N_DLREL 2
-
-#define iscomment(ch) ((ch) == '\0' || (ch) == '#')
-
-typedef enum {
- XLC_OBJECT,
- XIM_OBJECT,
- XOM_OBJECT
-} XI18NDLType;
-
-typedef struct {
- XI18NDLType type;
- int locale_name_len;
- char *locale_name;
- char *dl_name;
- char *open;
- char *im_register;
- char *im_unregister;
- int dl_release;
- unsigned int refcount;
-#if defined(hpux)
- shl_t dl_module;
-#else
- void *dl_module;
-#endif
-} XI18NObjectsListRec, *XI18NObjectsList;
-
-#define OBJECT_INIT_LEN 8
-#define OBJECT_INC_LEN 4
-static int lc_len = 0;
-static XI18NObjectsListRec *xi18n_objects_list = NULL;
-static int lc_count = 0;
-
-static int
-parse_line(char *line, char **argv, int argsize)
-{
- int argc = 0;
- char *p = line;
-
- while (argc < argsize) {
- while (isspace(*p)) {
- ++p;
- }
- if (iscomment(*p)){
- break;
- }
- argv[argc++] = p;
- while (!isspace(*p)) {
- ++p;
- }
- if (iscomment(*p)) {
- break;
- }
- *p++ = '\0';
- }
- return argc;
-}
-
-static char *
-strdup_with_underscore(const char *symbol)
-{
- char *result;
-
- if ((result = malloc(strlen(symbol) + 2)) == NULL)
- return NULL;
- result[0] = '_';
- strcpy(result + 1, symbol);
- return result;
-}
-
-#ifndef hpux
-static void *
-try_both_dlsym (void *handle, char *name)
-{
- void *ret;
-
- ret = dlsym (handle, name);
- if (!ret)
- {
- name = strdup_with_underscore (name);
- if (name)
- {
- ret = dlsym (handle, name);
- free (name);
- }
- }
- return ret;
-}
-#endif
-
-static void
-resolve_object(char *path, const char *lc_name)
-{
- char filename[BUFSIZ];
- FILE *fp;
- char buf[BUFSIZ];
-
- if (lc_len == 0) { /* True only for the 1st time */
- lc_len = OBJECT_INIT_LEN;
- xi18n_objects_list = (XI18NObjectsList)
- Xmalloc(sizeof(XI18NObjectsListRec) * lc_len);
- if (!xi18n_objects_list) return;
- }
-/*
-1266793
-Limit the length of path to prevent stack buffer corruption.
- sprintf(filename, "%s/%s", path, "XI18N_OBJS");
-*/
- sprintf(filename, "%.*s/%s", BUFSIZ - 12, path, "XI18N_OBJS");
- fp = fopen(filename, "r");
- if (fp == (FILE *)NULL){
- return;
- }
-
- while (fgets(buf, BUFSIZ, fp) != NULL){
- char *p = buf;
- int n;
- char *args[6];
- while (isspace(*p)){
- ++p;
- }
- if (iscomment(*p)){
- continue;
- }
-
- if (lc_count == lc_len) {
- lc_len += OBJECT_INC_LEN;
- xi18n_objects_list = (XI18NObjectsList)
- Xrealloc(xi18n_objects_list,
- sizeof(XI18NObjectsListRec) * lc_len);
- if (!xi18n_objects_list) return;
- }
- n = parse_line(p, args, 6);
-
- if (n == 3 || n == 5) {
- if (!strcmp(args[0], "XLC")){
- xi18n_objects_list[lc_count].type = XLC_OBJECT;
- } else if (!strcmp(args[0], "XOM")){
- xi18n_objects_list[lc_count].type = XOM_OBJECT;
- } else if (!strcmp(args[0], "XIM")){
- xi18n_objects_list[lc_count].type = XIM_OBJECT;
- }
- xi18n_objects_list[lc_count].dl_name = strdup(args[1]);
- xi18n_objects_list[lc_count].open = strdup(args[2]);
- xi18n_objects_list[lc_count].dl_release = XI18N_DLREL;
- xi18n_objects_list[lc_count].locale_name = strdup(lc_name);
- xi18n_objects_list[lc_count].refcount = 0;
- xi18n_objects_list[lc_count].dl_module = (void*)NULL;
- if (n == 5) {
- xi18n_objects_list[lc_count].im_register = strdup(args[3]);
- xi18n_objects_list[lc_count].im_unregister = strdup(args[4]);
- } else {
- xi18n_objects_list[lc_count].im_register = NULL;
- xi18n_objects_list[lc_count].im_unregister = NULL;
- }
- lc_count++;
- }
- }
- fclose(fp);
-}
-
-static char*
-__lc_path(const char *dl_name, const char *lc_dir)
-{
- char *path;
- size_t len;
-
- /*
- * reject this for possible security issue
- */
- if (strstr (dl_name, "../"))
- return NULL;
-
- len = (lc_dir ? strlen(lc_dir) : 0 ) +
- (dl_name ? strlen(dl_name) : 0) + 10;
-#if defined POSTLOCALELIBDIR
- len += (strlen(POSTLOCALELIBDIR) + 1);
-#endif
- path = Xmalloc(len + 1);
-
- if (strchr(dl_name, '/') != NULL) {
- char *slash_p;
- slash_p = strrchr(lc_dir, '/');
- *slash_p = '\0';
- strcpy(path, lc_dir); strcat(path, "/");
-#if defined POSTLOCALELIBDIR
- strcat(path, POSTLOCALELIBDIR); strcat(path, "/");
-#endif
- strcat(path, dl_name); strcat(path, ".so.2");
- *slash_p = '/';
- } else {
- strcpy(path, lc_dir); strcat(path, "/");
-#if defined POSTLOCALELIBDIR
- strcat(path, POSTLOCALELIBDIR); strcat(path, "/");
-#endif
- strcat(path, dl_name); strcat(path, ".so.2");
- }
- return path;
-}
-
-/* We reference count dlopen() and dlclose() of modules; unfortunately,
- * since XCloseIM, XCloseOM, XlcClose aren't wrapped, but directly
- * call the close method of the object, we leak a reference count every
- * time we open then close a module. Fixing this would require
- * either creating proxy objects or hooks for close_im/close_om
- * in XLCd
- */
-static Bool
-open_object(
- XI18NObjectsList object,
- char *lc_dir)
-{
- char *path;
-
- if (object->refcount == 0) {
- path = __lc_path(object->dl_name, lc_dir);
- if (!path)
- return False;
-#if defined(hpux)
- object->dl_module = shl_load(path, BIND_DEFERRED, 0L);
-#else
- object->dl_module = dlopen(path, RTLD_LAZY);
-#endif
- Xfree(path);
-
- if (!object->dl_module)
- return False;
- }
-
- object->refcount++;
- return True;
-}
-
-static void *
-fetch_symbol(
- XI18NObjectsList object,
- char *symbol)
-{
- void *result = NULL;
-#if defined(hpux)
- int getsyms_cnt, i;
- struct shl_symbol *symbols;
-#endif
-
- if (symbol == NULL)
- return NULL;
-
-#if defined(hpux)
- getsyms_cnt = shl_getsymbols(object->dl_module, TYPE_PROCEDURE,
- EXPORT_SYMBOLS, malloc, &symbols);
-
- for(i=0; i<getsyms_cnt; i++) {
- if(!strcmp(symbols[i].name, symbol)) {
- result = symbols[i].value;
- break;
- }
- }
-
- if(getsyms_cnt > 0) {
- free(symbols);
- }
-#else
- result = try_both_dlsym(object->dl_module, symbol);
-#endif
-
- return result;
-}
-
-static void
-close_object(XI18NObjectsList object)
-{
- object->refcount--;
- if (object->refcount == 0)
- {
-#if defined(hpux)
- shl_unload(object->dl_module);
-#else
- dlclose(object->dl_module);
-#endif
- object->dl_module = NULL;
- }
-}
-
-
-typedef XLCd (*dynamicLoadProc)(const char *);
-
-XLCd
-_XlcDynamicLoad(const char *lc_name)
-{
- XLCd lcd = (XLCd)NULL;
- dynamicLoadProc lc_loader = (dynamicLoadProc)NULL;
- int count;
- XI18NObjectsList objects_list;
- char lc_dir[BUFSIZE], lc_lib_dir[BUFSIZE];
-
- if (lc_name == NULL) return (XLCd)NULL;
-
- if (_XlcLocaleDirName(lc_dir, BUFSIZE, (char *)lc_name) == (char *)NULL)
- return (XLCd)NULL;
- if (_XlcLocaleLibDirName(lc_lib_dir, BUFSIZE, (char *)lc_name) == (char*)NULL)
- return (XLCd)NULL;
-
- resolve_object(lc_dir, lc_name);
- resolve_object(lc_lib_dir, lc_name);
-
- objects_list = xi18n_objects_list;
- count = lc_count;
- for (; count-- > 0; objects_list++) {
- if (objects_list->type != XLC_OBJECT ||
- strcmp(objects_list->locale_name, lc_name)) continue;
- if (!open_object (objects_list, lc_dir) && \
- !open_object (objects_list, lc_lib_dir))
- continue;
-
- lc_loader = (dynamicLoadProc)fetch_symbol (objects_list, objects_list->open);
- if (!lc_loader) continue;
- lcd = (*lc_loader)(lc_name);
- if (lcd != (XLCd)NULL) {
- break;
- }
-
- close_object (objects_list);
- }
- return (XLCd)lcd;
-}
-
-
-typedef XIM (*dynamicOpenProcp)(XLCd, Display *, XrmDatabase, char *, char *);
-
-static XIM
-_XDynamicOpenIM(XLCd lcd, Display *display, XrmDatabase rdb,
- char *res_name, char *res_class)
-{
- XIM im = (XIM)NULL;
- char lc_dir[BUFSIZE];
- char *lc_name;
- dynamicOpenProcp im_openIM = (dynamicOpenProcp)NULL;
- int count;
- XI18NObjectsList objects_list = xi18n_objects_list;
-
- lc_name = lcd->core->name;
-
- if (_XlcLocaleLibDirName(lc_dir, BUFSIZE, lc_name) == NULL) return (XIM)0;
-
- count = lc_count;
- for (; count-- > 0; objects_list++) {
- if (objects_list->type != XIM_OBJECT ||
- strcmp(objects_list->locale_name, lc_name)) continue;
-
- if (!open_object (objects_list, lc_dir))
- continue;
-
- im_openIM = (dynamicOpenProcp)fetch_symbol(objects_list, objects_list->open);
- if (!im_openIM) continue;
- im = (*im_openIM)(lcd, display, rdb, res_name, res_class);
- if (im != (XIM)NULL) {
- break;
- }
-
- close_object (objects_list);
- }
- return (XIM)im;
-}
-
-typedef Bool (*dynamicRegisterCBProcp)(
- XLCd, Display *, XrmDatabase, char *, char *, XIDProc, XPointer);
-
-static Bool
-_XDynamicRegisterIMInstantiateCallback(
- XLCd lcd,
- Display *display,
- XrmDatabase rdb,
- char *res_name,
- char *res_class,
- XIDProc callback,
- XPointer client_data)
-{
- char lc_dir[BUFSIZE];
- char *lc_name;
- dynamicRegisterCBProcp im_registerIM = (dynamicRegisterCBProcp)NULL;
- Bool ret_flag = False;
- int count;
- XI18NObjectsList objects_list = xi18n_objects_list;
-#if defined(hpux)
- int getsyms_cnt, i;
- struct shl_symbol *symbols;
-#endif
-
- lc_name = lcd->core->name;
-
- if (_XlcLocaleLibDirName(lc_dir, BUFSIZE, lc_name) == NULL) return False;
-
- count = lc_count;
- for (; count-- > 0; objects_list++) {
- if (objects_list->type != XIM_OBJECT ||
- strcmp(objects_list->locale_name, lc_name)) continue;
-
- if (!open_object (objects_list, lc_dir))
- continue;
- im_registerIM = (dynamicRegisterCBProcp)fetch_symbol(objects_list,
- objects_list->im_register);
- if (!im_registerIM) continue;
- ret_flag = (*im_registerIM)(lcd, display, rdb,
- res_name, res_class,
- callback, client_data);
- if (ret_flag) break;
-
- close_object (objects_list);
- }
- return (Bool)ret_flag;
-}
-
-typedef Bool (*dynamicUnregisterProcp)(
- XLCd, Display *, XrmDatabase, char *, char *, XIDProc, XPointer);
-
-static Bool
-_XDynamicUnRegisterIMInstantiateCallback(
- XLCd lcd,
- Display *display,
- XrmDatabase rdb,
- char *res_name,
- char *res_class,
- XIDProc callback,
- XPointer client_data)
-{
- char lc_dir[BUFSIZE];
- char *lc_name;
- dynamicUnregisterProcp im_unregisterIM = (dynamicUnregisterProcp)NULL;
- Bool ret_flag = False;
- int count;
- XI18NObjectsList objects_list = xi18n_objects_list;
-#if defined(hpux)
- int getsyms_cnt, i;
- struct shl_symbol *symbols;
-#endif
-
- lc_name = lcd->core->name;
- if (_XlcLocaleDirName(lc_dir, BUFSIZE, lc_name) == NULL) return False;
-
- count = lc_count;
- for (; count-- > 0; objects_list++) {
- if (objects_list->type != XIM_OBJECT ||
- strcmp(objects_list->locale_name, lc_name)) continue;
-
- if (!objects_list->refcount) /* Must already be opened */
- continue;
-
- im_unregisterIM = (dynamicUnregisterProcp)fetch_symbol(objects_list,
- objects_list->im_unregister);
-
- if (!im_unregisterIM) continue;
- ret_flag = (*im_unregisterIM)(lcd, display, rdb,
- res_name, res_class,
- callback, client_data);
- if (ret_flag) {
- close_object (objects_list); /* opened in RegisterIMInstantiateCallback */
- break;
- }
- }
- return (Bool)ret_flag;
-}
-
-Bool
-_XInitDynamicIM(XLCd lcd)
-{
- if(lcd == (XLCd)NULL)
- return False;
- lcd->methods->open_im = _XDynamicOpenIM;
- lcd->methods->register_callback = _XDynamicRegisterIMInstantiateCallback;
- lcd->methods->unregister_callback = _XDynamicUnRegisterIMInstantiateCallback;
- return True;
-}
-
-
-typedef XOM (*dynamicIOpenProcp)(
- XLCd, Display *, XrmDatabase, _Xconst char *, _Xconst char *);
-
-static XOM
-_XDynamicOpenOM(XLCd lcd, Display *display, XrmDatabase rdb,
- _Xconst char *res_name, _Xconst char *res_class)
-{
- XOM om = (XOM)NULL;
- int count;
- char lc_dir[BUFSIZE];
- char *lc_name;
- dynamicIOpenProcp om_openOM = (dynamicIOpenProcp)NULL;
- XI18NObjectsList objects_list = xi18n_objects_list;
-#if defined(hpux)
- int getsyms_cnt, i;
- struct shl_symbol *symbols;
-#endif
-
- lc_name = lcd->core->name;
-
- if (_XlcLocaleLibDirName(lc_dir, BUFSIZE, lc_name) == NULL) return (XOM)0;
-
- count = lc_count;
- for (; count-- > 0; objects_list++) {
- if (objects_list->type != XOM_OBJECT ||
- strcmp(objects_list->locale_name, lc_name)) continue;
- if (!open_object (objects_list, lc_dir))
- continue;
-
- om_openOM = (dynamicIOpenProcp)fetch_symbol(objects_list, objects_list->open);
- if (!om_openOM) continue;
- om = (*om_openOM)(lcd, display, rdb, res_name, res_class);
- if (om != (XOM)NULL) {
- break;
- }
- close_object(objects_list);
- }
- return (XOM)om;
-}
-
-Bool
-_XInitDynamicOM(XLCd lcd)
-{
- if(lcd == (XLCd)NULL)
- return False;
-
- lcd->methods->open_om = _XDynamicOpenOM;
-
- return True;
-}
+/* +Copyright 1985, 1986, 1987, 1991, 1998 The Open Group + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: The above copyright notice and this +permission notice shall be included in all copies or substantial +portions of the Software. + + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE +EVEN IF ADVISED IN ADVANCE OF THE POSSIBILITY OF SUCH DAMAGES. + + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +X Window System is a trademark of The Open Group + +OSF/1, OSF/Motif and Motif are registered trademarks, and OSF, the OSF +logo, LBX, X Window System, and Xinerama are trademarks of the Open +Group. All other trademarks and registered trademarks mentioned herein +are the property of their respective owners. No right, title or +interest in or to any trademark, service mark, logo or trade name of +Sun Microsystems, Inc. or its licensors is granted. + +*/ +/* + * Copyright 2000 Oracle and/or its affiliates. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + + +#ifdef HAVE_CONFIG_H +# include <config.h> +#else +# if defined(hpux) +# define HAVE_DL_H +# else +# define HAVE_DLFCN_H +# endif +#endif + +#include <stdio.h> + +#ifdef HAVE_DL_H +#include <dl.h> +#endif + +#ifdef HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#include <ctype.h> + +#include "Xlibint.h" +#include "XlcPublic.h" +#include "XlcPubI.h" + +#define XI18N_DLREL 2 + +#define iscomment(ch) ((ch) == '\0' || (ch) == '#') + +typedef enum { + XLC_OBJECT, + XIM_OBJECT, + XOM_OBJECT +} XI18NDLType; + +typedef struct { + XI18NDLType type; + int locale_name_len; + char *locale_name; + char *dl_name; + char *open; + char *im_register; + char *im_unregister; + int dl_release; + unsigned int refcount; +#if defined(hpux) + shl_t dl_module; +#else + void *dl_module; +#endif +} XI18NObjectsListRec, *XI18NObjectsList; + +#define OBJECT_INIT_LEN 8 +#define OBJECT_INC_LEN 4 +static int lc_len = 0; +static XI18NObjectsListRec *xi18n_objects_list = NULL; +static int lc_count = 0; + +static int +parse_line(char *line, char **argv, int argsize) +{ + int argc = 0; + char *p = line; + + while (argc < argsize) { + while (isspace(*p)) { + ++p; + } + if (iscomment(*p)){ + break; + } + argv[argc++] = p; + while (!isspace(*p)) { + ++p; + } + if (iscomment(*p)) { + break; + } + *p++ = '\0'; + } + return argc; +} + +static char * +strdup_with_underscore(const char *symbol) +{ + char *result; + + if ((result = malloc(strlen(symbol) + 2)) == NULL) + return NULL; + result[0] = '_'; + strcpy(result + 1, symbol); + return result; +} + +#ifndef hpux +static void * +try_both_dlsym (void *handle, char *name) +{ + void *ret; + + ret = dlsym (handle, name); + if (!ret) + { + name = strdup_with_underscore (name); + if (name) + { + ret = dlsym (handle, name); + free (name); + } + } + return ret; +} +#endif + +static void +resolve_object(char *path, const char *lc_name) +{ + char filename[BUFSIZ]; + FILE *fp; + char buf[BUFSIZ]; + + if (lc_len == 0) { /* True only for the 1st time */ + lc_len = OBJECT_INIT_LEN; + xi18n_objects_list = (XI18NObjectsList) + Xmalloc(sizeof(XI18NObjectsListRec) * lc_len); + if (!xi18n_objects_list) return; + } +/* +1266793 +Limit the length of path to prevent stack buffer corruption. + sprintf(filename, "%s/%s", path, "XI18N_OBJS"); +*/ + sprintf(filename, "%.*s/%s", BUFSIZ - 12, path, "XI18N_OBJS"); + fp = fopen(filename, "r"); + if (fp == (FILE *)NULL){ + return; + } + + while (fgets(buf, BUFSIZ, fp) != NULL){ + char *p = buf; + int n; + char *args[6]; + while (isspace(*p)){ + ++p; + } + if (iscomment(*p)){ + continue; + } + + if (lc_count == lc_len) { + lc_len += OBJECT_INC_LEN; + xi18n_objects_list = (XI18NObjectsList) + Xrealloc(xi18n_objects_list, + sizeof(XI18NObjectsListRec) * lc_len); + if (!xi18n_objects_list) return; + } + n = parse_line(p, args, 6); + + if (n == 3 || n == 5) { + if (!strcmp(args[0], "XLC")){ + xi18n_objects_list[lc_count].type = XLC_OBJECT; + } else if (!strcmp(args[0], "XOM")){ + xi18n_objects_list[lc_count].type = XOM_OBJECT; + } else if (!strcmp(args[0], "XIM")){ + xi18n_objects_list[lc_count].type = XIM_OBJECT; + } + xi18n_objects_list[lc_count].dl_name = strdup(args[1]); + xi18n_objects_list[lc_count].open = strdup(args[2]); + xi18n_objects_list[lc_count].dl_release = XI18N_DLREL; + xi18n_objects_list[lc_count].locale_name = strdup(lc_name); + xi18n_objects_list[lc_count].refcount = 0; + xi18n_objects_list[lc_count].dl_module = (void*)NULL; + if (n == 5) { + xi18n_objects_list[lc_count].im_register = strdup(args[3]); + xi18n_objects_list[lc_count].im_unregister = strdup(args[4]); + } else { + xi18n_objects_list[lc_count].im_register = NULL; + xi18n_objects_list[lc_count].im_unregister = NULL; + } + lc_count++; + } + } + fclose(fp); +} + +static char* +__lc_path(const char *dl_name, const char *lc_dir) +{ + char *path; + size_t len; + + /* + * reject this for possible security issue + */ + if (strstr (dl_name, "../")) + return NULL; + + len = (lc_dir ? strlen(lc_dir) : 0 ) + + (dl_name ? strlen(dl_name) : 0) + 10; +#if defined POSTLOCALELIBDIR + len += (strlen(POSTLOCALELIBDIR) + 1); +#endif + path = Xmalloc(len + 1); + + if (strchr(dl_name, '/') != NULL) { + char *slash_p; + slash_p = strrchr(lc_dir, '/'); + *slash_p = '\0'; + strcpy(path, lc_dir); strcat(path, "/"); +#if defined POSTLOCALELIBDIR + strcat(path, POSTLOCALELIBDIR); strcat(path, "/"); +#endif + strcat(path, dl_name); strcat(path, ".so.2"); + *slash_p = '/'; + } else { + strcpy(path, lc_dir); strcat(path, "/"); +#if defined POSTLOCALELIBDIR + strcat(path, POSTLOCALELIBDIR); strcat(path, "/"); +#endif + strcat(path, dl_name); strcat(path, ".so.2"); + } + return path; +} + +/* We reference count dlopen() and dlclose() of modules; unfortunately, + * since XCloseIM, XCloseOM, XlcClose aren't wrapped, but directly + * call the close method of the object, we leak a reference count every + * time we open then close a module. Fixing this would require + * either creating proxy objects or hooks for close_im/close_om + * in XLCd + */ +static Bool +open_object( + XI18NObjectsList object, + char *lc_dir) +{ + char *path; + + if (object->refcount == 0) { + path = __lc_path(object->dl_name, lc_dir); + if (!path) + return False; +#if defined(hpux) + object->dl_module = shl_load(path, BIND_DEFERRED, 0L); +#else + object->dl_module = dlopen(path, RTLD_LAZY); +#endif + Xfree(path); + + if (!object->dl_module) + return False; + } + + object->refcount++; + return True; +} + +static void * +fetch_symbol( + XI18NObjectsList object, + char *symbol) +{ + void *result = NULL; +#if defined(hpux) + int getsyms_cnt, i; + struct shl_symbol *symbols; +#endif + + if (symbol == NULL) + return NULL; + +#if defined(hpux) + getsyms_cnt = shl_getsymbols(object->dl_module, TYPE_PROCEDURE, + EXPORT_SYMBOLS, malloc, &symbols); + + for(i=0; i<getsyms_cnt; i++) { + if(!strcmp(symbols[i].name, symbol)) { + result = symbols[i].value; + break; + } + } + + if(getsyms_cnt > 0) { + free(symbols); + } +#else + result = try_both_dlsym(object->dl_module, symbol); +#endif + + return result; +} + +static void +close_object(XI18NObjectsList object) +{ + object->refcount--; + if (object->refcount == 0) + { +#if defined(hpux) + shl_unload(object->dl_module); +#else + dlclose(object->dl_module); +#endif + object->dl_module = NULL; + } +} + + +typedef XLCd (*dynamicLoadProc)(const char *); + +XLCd +_XlcDynamicLoad(const char *lc_name) +{ + XLCd lcd = (XLCd)NULL; + dynamicLoadProc lc_loader = (dynamicLoadProc)NULL; + int count; + XI18NObjectsList objects_list; + char lc_dir[BUFSIZE], lc_lib_dir[BUFSIZE]; + + if (lc_name == NULL) return (XLCd)NULL; + + if (_XlcLocaleDirName(lc_dir, BUFSIZE, (char *)lc_name) == (char *)NULL) + return (XLCd)NULL; + if (_XlcLocaleLibDirName(lc_lib_dir, BUFSIZE, (char *)lc_name) == (char*)NULL) + return (XLCd)NULL; + + resolve_object(lc_dir, lc_name); + resolve_object(lc_lib_dir, lc_name); + + objects_list = xi18n_objects_list; + count = lc_count; + for (; count-- > 0; objects_list++) { + if (objects_list->type != XLC_OBJECT || + strcmp(objects_list->locale_name, lc_name)) continue; + if (!open_object (objects_list, lc_dir) && \ + !open_object (objects_list, lc_lib_dir)) + continue; + + lc_loader = (dynamicLoadProc)fetch_symbol (objects_list, objects_list->open); + if (!lc_loader) continue; + lcd = (*lc_loader)(lc_name); + if (lcd != (XLCd)NULL) { + break; + } + + close_object (objects_list); + } + return (XLCd)lcd; +} + + +typedef XIM (*dynamicOpenProcp)(XLCd, Display *, XrmDatabase, char *, char *); + +static XIM +_XDynamicOpenIM(XLCd lcd, Display *display, XrmDatabase rdb, + char *res_name, char *res_class) +{ + XIM im = (XIM)NULL; + char lc_dir[BUFSIZE]; + char *lc_name; + dynamicOpenProcp im_openIM = (dynamicOpenProcp)NULL; + int count; + XI18NObjectsList objects_list = xi18n_objects_list; + + lc_name = lcd->core->name; + + if (_XlcLocaleLibDirName(lc_dir, BUFSIZE, lc_name) == NULL) return (XIM)0; + + count = lc_count; + for (; count-- > 0; objects_list++) { + if (objects_list->type != XIM_OBJECT || + strcmp(objects_list->locale_name, lc_name)) continue; + + if (!open_object (objects_list, lc_dir)) + continue; + + im_openIM = (dynamicOpenProcp)fetch_symbol(objects_list, objects_list->open); + if (!im_openIM) continue; + im = (*im_openIM)(lcd, display, rdb, res_name, res_class); + if (im != (XIM)NULL) { + break; + } + + close_object (objects_list); + } + return (XIM)im; +} + +typedef Bool (*dynamicRegisterCBProcp)( + XLCd, Display *, XrmDatabase, char *, char *, XIDProc, XPointer); + +static Bool +_XDynamicRegisterIMInstantiateCallback( + XLCd lcd, + Display *display, + XrmDatabase rdb, + char *res_name, + char *res_class, + XIDProc callback, + XPointer client_data) +{ + char lc_dir[BUFSIZE]; + char *lc_name; + dynamicRegisterCBProcp im_registerIM = (dynamicRegisterCBProcp)NULL; + Bool ret_flag = False; + int count; + XI18NObjectsList objects_list = xi18n_objects_list; +#if defined(hpux) + int getsyms_cnt, i; + struct shl_symbol *symbols; +#endif + + lc_name = lcd->core->name; + + if (_XlcLocaleLibDirName(lc_dir, BUFSIZE, lc_name) == NULL) return False; + + count = lc_count; + for (; count-- > 0; objects_list++) { + if (objects_list->type != XIM_OBJECT || + strcmp(objects_list->locale_name, lc_name)) continue; + + if (!open_object (objects_list, lc_dir)) + continue; + im_registerIM = (dynamicRegisterCBProcp)fetch_symbol(objects_list, + objects_list->im_register); + if (!im_registerIM) continue; + ret_flag = (*im_registerIM)(lcd, display, rdb, + res_name, res_class, + callback, client_data); + if (ret_flag) break; + + close_object (objects_list); + } + return (Bool)ret_flag; +} + +typedef Bool (*dynamicUnregisterProcp)( + XLCd, Display *, XrmDatabase, char *, char *, XIDProc, XPointer); + +static Bool +_XDynamicUnRegisterIMInstantiateCallback( + XLCd lcd, + Display *display, + XrmDatabase rdb, + char *res_name, + char *res_class, + XIDProc callback, + XPointer client_data) +{ + char lc_dir[BUFSIZE]; + char *lc_name; + dynamicUnregisterProcp im_unregisterIM = (dynamicUnregisterProcp)NULL; + Bool ret_flag = False; + int count; + XI18NObjectsList objects_list = xi18n_objects_list; +#if defined(hpux) + int getsyms_cnt, i; + struct shl_symbol *symbols; +#endif + + lc_name = lcd->core->name; + if (_XlcLocaleDirName(lc_dir, BUFSIZE, lc_name) == NULL) return False; + + count = lc_count; + for (; count-- > 0; objects_list++) { + if (objects_list->type != XIM_OBJECT || + strcmp(objects_list->locale_name, lc_name)) continue; + + if (!objects_list->refcount) /* Must already be opened */ + continue; + + im_unregisterIM = (dynamicUnregisterProcp)fetch_symbol(objects_list, + objects_list->im_unregister); + + if (!im_unregisterIM) continue; + ret_flag = (*im_unregisterIM)(lcd, display, rdb, + res_name, res_class, + callback, client_data); + if (ret_flag) { + close_object (objects_list); /* opened in RegisterIMInstantiateCallback */ + break; + } + } + return (Bool)ret_flag; +} + +Bool +_XInitDynamicIM(XLCd lcd) +{ + if(lcd == (XLCd)NULL) + return False; + lcd->methods->open_im = _XDynamicOpenIM; + lcd->methods->register_callback = _XDynamicRegisterIMInstantiateCallback; + lcd->methods->unregister_callback = _XDynamicUnRegisterIMInstantiateCallback; + return True; +} + + +typedef XOM (*dynamicIOpenProcp)( + XLCd, Display *, XrmDatabase, _Xconst char *, _Xconst char *); + +static XOM +_XDynamicOpenOM(XLCd lcd, Display *display, XrmDatabase rdb, + _Xconst char *res_name, _Xconst char *res_class) +{ + XOM om = (XOM)NULL; + int count; + char lc_dir[BUFSIZE]; + char *lc_name; + dynamicIOpenProcp om_openOM = (dynamicIOpenProcp)NULL; + XI18NObjectsList objects_list = xi18n_objects_list; +#if defined(hpux) + int getsyms_cnt, i; + struct shl_symbol *symbols; +#endif + + lc_name = lcd->core->name; + + if (_XlcLocaleLibDirName(lc_dir, BUFSIZE, lc_name) == NULL) return (XOM)0; + + count = lc_count; + for (; count-- > 0; objects_list++) { + if (objects_list->type != XOM_OBJECT || + strcmp(objects_list->locale_name, lc_name)) continue; + if (!open_object (objects_list, lc_dir)) + continue; + + om_openOM = (dynamicIOpenProcp)fetch_symbol(objects_list, objects_list->open); + if (!om_openOM) continue; + om = (*om_openOM)(lcd, display, rdb, res_name, res_class); + if (om != (XOM)NULL) { + break; + } + close_object(objects_list); + } + return (XOM)om; +} + +Bool +_XInitDynamicOM(XLCd lcd) +{ + if(lcd == (XLCd)NULL) + return False; + + lcd->methods->open_om = _XDynamicOpenOM; + + return True; +} diff --git a/libX11/src/xlibi18n/lcCharSet.c b/libX11/src/xlibi18n/lcCharSet.c index 6be5f5d16..5d287811c 100644 --- a/libX11/src/xlibi18n/lcCharSet.c +++ b/libX11/src/xlibi18n/lcCharSet.c @@ -1,225 +1,225 @@ -/*
- * Copyright 1992, 1993 by TOSHIBA Corp.
- *
- * 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 TOSHIBA not be used in advertising
- * or publicity pertaining to distribution of the software without specific,
- * written prior permission. TOSHIBA make no representations about the
- * suitability of this software for any purpose. It is provided "as is"
- * without express or implied warranty.
- *
- * TOSHIBA DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
- * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
- * TOSHIBA 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 TORTIOUS ACTION,
- * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- *
- * Author: Katsuhisa Yano TOSHIBA Corp.
- * mopi@osa.ilab.toshiba.co.jp
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include "Xlibint.h"
-#include "XlcPublic.h"
-#include "XlcPubI.h"
-
-/* The list of all known XlcCharSets. They are identified by their name. */
-
-typedef struct _XlcCharSetListRec {
- XlcCharSet charset;
- struct _XlcCharSetListRec *next;
-} XlcCharSetListRec, *XlcCharSetList;
-
-static XlcCharSetList charset_list = NULL;
-
-/* Returns the charset with the given name (including side suffix).
- Returns NULL if not found. */
-XlcCharSet
-_XlcGetCharSet(
- const char *name)
-{
- XlcCharSetList list;
- XrmQuark xrm_name;
-
- xrm_name = XrmStringToQuark(name);
-
- for (list = charset_list; list; list = list->next) {
- if (xrm_name == list->charset->xrm_name)
- return (XlcCharSet) list->charset;
- }
-
- return (XlcCharSet) NULL;
-}
-
-/* Returns the charset with the given encoding (no side suffix) and
- responsible for at least the given side (XlcGL or XlcGR).
- Returns NULL if not found. */
-XlcCharSet
-_XlcGetCharSetWithSide(
- const char *encoding_name,
- XlcSide side)
-{
- XlcCharSetList list;
- XrmQuark xrm_encoding_name;
-
- xrm_encoding_name = XrmStringToQuark(encoding_name);
-
- for (list = charset_list; list; list = list->next) {
- if (list->charset->xrm_encoding_name == xrm_encoding_name
- && (list->charset->side == XlcGLGR || list->charset->side == side))
- return (XlcCharSet) list->charset;
- }
-
- return (XlcCharSet) NULL;
-}
-
-/* Registers an XlcCharSet in the list of character sets.
- Returns True if successful. */
-Bool
-_XlcAddCharSet(
- XlcCharSet charset)
-{
- XlcCharSetList list;
-
- if (_XlcGetCharSet(charset->name))
- return False;
-
- list = (XlcCharSetList) Xmalloc(sizeof(XlcCharSetListRec));
- if (list == NULL)
- return False;
-
- list->charset = charset;
- list->next = charset_list;
- charset_list = list;
-
- return True;
-}
-
-/* List of resources for XlcCharSet. */
-static XlcResource resources[] = {
- { XlcNName, NULLQUARK, sizeof(char *),
- XOffsetOf(XlcCharSetRec, name), XlcGetMask },
- { XlcNEncodingName, NULLQUARK, sizeof(char *),
- XOffsetOf(XlcCharSetRec, encoding_name), XlcGetMask },
- { XlcNSide, NULLQUARK, sizeof(XlcSide),
- XOffsetOf(XlcCharSetRec, side), XlcGetMask },
- { XlcNCharSize, NULLQUARK, sizeof(int),
- XOffsetOf(XlcCharSetRec, char_size), XlcGetMask },
- { XlcNSetSize, NULLQUARK, sizeof(int),
- XOffsetOf(XlcCharSetRec, set_size), XlcGetMask },
- { XlcNControlSequence, NULLQUARK, sizeof(char *),
- XOffsetOf(XlcCharSetRec, ct_sequence), XlcGetMask }
-};
-
-/* Retrieves a number of attributes of an XlcCharSet.
- Return NULL if successful, otherwise the name of the first argument
- specifiying a nonexistent attribute. */
-static char *
-get_values(
- XlcCharSet charset,
- XlcArgList args,
- int num_args)
-{
- if (resources[0].xrm_name == NULLQUARK)
- _XlcCompileResourceList(resources, XlcNumber(resources));
-
- return _XlcGetValues((XPointer) charset, resources, XlcNumber(resources),
- args, num_args, XlcGetMask);
-}
-
-/* Retrieves a number of attributes of an XlcCharSet.
- Return NULL if successful, otherwise the name of the first argument
- specifiying a nonexistent attribute. */
-char *
-_XlcGetCSValues(XlcCharSet charset, ...)
-{
- va_list var;
- XlcArgList args;
- char *ret;
- int num_args;
-
- va_start(var, charset);
- _XlcCountVaList(var, &num_args);
- va_end(var);
-
- va_start(var, charset);
- _XlcVaToArgList(var, num_args, &args);
- va_end(var);
-
- if (args == (XlcArgList) NULL)
- return (char *) NULL;
-
- ret = get_values(charset, args, num_args);
-
- Xfree(args);
-
- return ret;
-}
-
-/* Creates a new XlcCharSet, given its name (including side suffix) and
- Compound Text ESC sequence (normally at most 4 bytes). */
-XlcCharSet
-_XlcCreateDefaultCharSet(
- const char *name,
- const char *ct_sequence)
-{
- XlcCharSet charset;
- int name_len, ct_sequence_len;
- const char *colon;
- char *tmp;
-
- charset = Xcalloc(1, sizeof(XlcCharSetRec));
- if (charset == NULL)
- return (XlcCharSet) NULL;
-
- name_len = strlen(name);
- ct_sequence_len = strlen(ct_sequence);
-
- /* Fill in name and xrm_name. */
- tmp = (char *) Xmalloc(name_len + 1 + ct_sequence_len + 1);
- if (tmp == NULL) {
- Xfree((char *) charset);
- return (XlcCharSet) NULL;
- }
- memcpy(tmp, name, name_len+1);
- charset->name = tmp;
- charset->xrm_name = XrmStringToQuark(charset->name);
-
- /* Fill in encoding_name and xrm_encoding_name. */
- if ((colon = strchr(charset->name, ':')) != NULL) {
- unsigned int length = colon - charset->name;
- char *encoding_tmp = (char *) Xmalloc(length + 1);
- if (encoding_tmp == NULL) {
- Xfree((char *) charset->name);
- Xfree((char *) charset);
- return (XlcCharSet) NULL;
- }
- memcpy(encoding_tmp, charset->name, length);
- encoding_tmp[length] = '\0';
- charset->encoding_name = encoding_tmp;
- charset->xrm_encoding_name = XrmStringToQuark(charset->encoding_name);
- } else {
- charset->encoding_name = charset->name;
- charset->xrm_encoding_name = charset->xrm_name;
- }
-
- /* Fill in ct_sequence. */
- tmp += name_len + 1;
- memcpy(tmp, ct_sequence, ct_sequence_len+1);
- charset->ct_sequence = tmp;
-
- /* Fill in side, char_size, set_size. */
- if (!_XlcParseCharSet(charset))
- /* If ct_sequence is not usable in Compound Text, remove it. */
- charset->ct_sequence = "";
-
- return (XlcCharSet) charset;
-}
+/* + * Copyright 1992, 1993 by TOSHIBA Corp. + * + * 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 TOSHIBA not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. TOSHIBA make no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * TOSHIBA DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING + * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL + * TOSHIBA 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 TORTIOUS ACTION, + * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + * + * Author: Katsuhisa Yano TOSHIBA Corp. + * mopi@osa.ilab.toshiba.co.jp + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include "Xlibint.h" +#include "XlcPublic.h" +#include "XlcPubI.h" + +/* The list of all known XlcCharSets. They are identified by their name. */ + +typedef struct _XlcCharSetListRec { + XlcCharSet charset; + struct _XlcCharSetListRec *next; +} XlcCharSetListRec, *XlcCharSetList; + +static XlcCharSetList charset_list = NULL; + +/* Returns the charset with the given name (including side suffix). + Returns NULL if not found. */ +XlcCharSet +_XlcGetCharSet( + const char *name) +{ + XlcCharSetList list; + XrmQuark xrm_name; + + xrm_name = XrmStringToQuark(name); + + for (list = charset_list; list; list = list->next) { + if (xrm_name == list->charset->xrm_name) + return (XlcCharSet) list->charset; + } + + return (XlcCharSet) NULL; +} + +/* Returns the charset with the given encoding (no side suffix) and + responsible for at least the given side (XlcGL or XlcGR). + Returns NULL if not found. */ +XlcCharSet +_XlcGetCharSetWithSide( + const char *encoding_name, + XlcSide side) +{ + XlcCharSetList list; + XrmQuark xrm_encoding_name; + + xrm_encoding_name = XrmStringToQuark(encoding_name); + + for (list = charset_list; list; list = list->next) { + if (list->charset->xrm_encoding_name == xrm_encoding_name + && (list->charset->side == XlcGLGR || list->charset->side == side)) + return (XlcCharSet) list->charset; + } + + return (XlcCharSet) NULL; +} + +/* Registers an XlcCharSet in the list of character sets. + Returns True if successful. */ +Bool +_XlcAddCharSet( + XlcCharSet charset) +{ + XlcCharSetList list; + + if (_XlcGetCharSet(charset->name)) + return False; + + list = (XlcCharSetList) Xmalloc(sizeof(XlcCharSetListRec)); + if (list == NULL) + return False; + + list->charset = charset; + list->next = charset_list; + charset_list = list; + + return True; +} + +/* List of resources for XlcCharSet. */ +static XlcResource resources[] = { + { XlcNName, NULLQUARK, sizeof(char *), + XOffsetOf(XlcCharSetRec, name), XlcGetMask }, + { XlcNEncodingName, NULLQUARK, sizeof(char *), + XOffsetOf(XlcCharSetRec, encoding_name), XlcGetMask }, + { XlcNSide, NULLQUARK, sizeof(XlcSide), + XOffsetOf(XlcCharSetRec, side), XlcGetMask }, + { XlcNCharSize, NULLQUARK, sizeof(int), + XOffsetOf(XlcCharSetRec, char_size), XlcGetMask }, + { XlcNSetSize, NULLQUARK, sizeof(int), + XOffsetOf(XlcCharSetRec, set_size), XlcGetMask }, + { XlcNControlSequence, NULLQUARK, sizeof(char *), + XOffsetOf(XlcCharSetRec, ct_sequence), XlcGetMask } +}; + +/* Retrieves a number of attributes of an XlcCharSet. + Return NULL if successful, otherwise the name of the first argument + specifiying a nonexistent attribute. */ +static char * +get_values( + XlcCharSet charset, + XlcArgList args, + int num_args) +{ + if (resources[0].xrm_name == NULLQUARK) + _XlcCompileResourceList(resources, XlcNumber(resources)); + + return _XlcGetValues((XPointer) charset, resources, XlcNumber(resources), + args, num_args, XlcGetMask); +} + +/* Retrieves a number of attributes of an XlcCharSet. + Return NULL if successful, otherwise the name of the first argument + specifiying a nonexistent attribute. */ +char * +_XlcGetCSValues(XlcCharSet charset, ...) +{ + va_list var; + XlcArgList args; + char *ret; + int num_args; + + va_start(var, charset); + _XlcCountVaList(var, &num_args); + va_end(var); + + va_start(var, charset); + _XlcVaToArgList(var, num_args, &args); + va_end(var); + + if (args == (XlcArgList) NULL) + return (char *) NULL; + + ret = get_values(charset, args, num_args); + + Xfree(args); + + return ret; +} + +/* Creates a new XlcCharSet, given its name (including side suffix) and + Compound Text ESC sequence (normally at most 4 bytes). */ +XlcCharSet +_XlcCreateDefaultCharSet( + const char *name, + const char *ct_sequence) +{ + XlcCharSet charset; + int name_len, ct_sequence_len; + const char *colon; + char *tmp; + + charset = Xcalloc(1, sizeof(XlcCharSetRec)); + if (charset == NULL) + return (XlcCharSet) NULL; + + name_len = strlen(name); + ct_sequence_len = strlen(ct_sequence); + + /* Fill in name and xrm_name. */ + tmp = (char *) Xmalloc(name_len + 1 + ct_sequence_len + 1); + if (tmp == NULL) { + Xfree((char *) charset); + return (XlcCharSet) NULL; + } + memcpy(tmp, name, name_len+1); + charset->name = tmp; + charset->xrm_name = XrmStringToQuark(charset->name); + + /* Fill in encoding_name and xrm_encoding_name. */ + if ((colon = strchr(charset->name, ':')) != NULL) { + unsigned int length = colon - charset->name; + char *encoding_tmp = (char *) Xmalloc(length + 1); + if (encoding_tmp == NULL) { + Xfree((char *) charset->name); + Xfree((char *) charset); + return (XlcCharSet) NULL; + } + memcpy(encoding_tmp, charset->name, length); + encoding_tmp[length] = '\0'; + charset->encoding_name = encoding_tmp; + charset->xrm_encoding_name = XrmStringToQuark(charset->encoding_name); + } else { + charset->encoding_name = charset->name; + charset->xrm_encoding_name = charset->xrm_name; + } + + /* Fill in ct_sequence. */ + tmp += name_len + 1; + memcpy(tmp, ct_sequence, ct_sequence_len+1); + charset->ct_sequence = tmp; + + /* Fill in side, char_size, set_size. */ + if (!_XlcParseCharSet(charset)) + /* If ct_sequence is not usable in Compound Text, remove it. */ + charset->ct_sequence = ""; + + return (XlcCharSet) charset; +} diff --git a/libX11/src/xlibi18n/lcDB.c b/libX11/src/xlibi18n/lcDB.c index 7d3ba88c5..7f13cc3e2 100644 --- a/libX11/src/xlibi18n/lcDB.c +++ b/libX11/src/xlibi18n/lcDB.c @@ -1,1342 +1,1342 @@ -/*
- *
- * Copyright IBM Corporation 1993
- *
- * All Rights Reserved
- *
- * License 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 IBM not be
- * used in advertising or publicity pertaining to distribution of the
- * software without specific, written prior permission.
- *
- * IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
- * ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS, AND
- * NONINFRINGEMENT OF THIRD PARTY RIGHTS, IN NO EVENT SHALL
- * IBM 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 TORTIOUS ACTION,
- * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- *
-*/
-/*
- * (c) Copyright 1995 FUJITSU LIMITED
- * This is source code modified by FUJITSU LIMITED under the Joint
- * Development Agreement for the CDE/Motif PST.
- */
-
-
-
-#ifndef NOT_X_ENV
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <X11/Xlib.h>
-#include <X11/Xresource.h>
-#include "Xlibint.h"
-#include "XlcPubI.h"
-
-#else /* NOT_X_ENV */
-
-#define Xmalloc malloc
-#define Xrealloc realloc
-#define Xfree free
-
-#endif /* NOT_X_ENV */
-
-#include <stdint.h>
-
-/* specifying NOT_X_ENV allows users to just use
- the database parsing routine. */
-/* For UDC/VW */
-#ifndef BUFSIZE
-#define BUFSIZE 2048
-#endif
-
-#ifdef COMMENT
-#ifdef BUFSIZE
-#undef BUFSIZE
-#endif
-#define BUFSIZE 6144 /* 2048*3 */
-#endif
-
-#include <stdio.h>
-#include <unistd.h>
-
-typedef struct _DatabaseRec {
- char *category;
- char *name;
- char **value;
- int value_num;
- struct _DatabaseRec *next;
-} DatabaseRec, *Database;
-
-typedef enum {
- S_NULL, /* outside category */
- S_CATEGORY, /* inside category */
- S_NAME, /* has name, expecting values */
- S_VALUE
-} ParseState;
-
-typedef enum {
- T_NEWLINE,
- T_COMMENT,
- T_SEMICOLON,
- T_DOUBLE_QUOTE,
- T_LEFT_BRACE,
- T_RIGHT_BRACE,
- T_SPACE,
- T_TAB,
- T_BACKSLASH,
- T_NUMERIC_HEX,
- T_NUMERIC_DEC,
- T_NUMERIC_OCT,
- T_DEFAULT
-} Token;
-
-typedef struct {
- Token token; /* token id */
- int len; /* length of token sequence */
-} TokenTable;
-
-static int f_newline (const char *str, Token token, Database *db);
-static int f_comment (const char *str, Token token, Database *db);
-static int f_semicolon (const char *str, Token token, Database *db);
-static int f_double_quote (const char *str, Token token, Database *db);
-static int f_left_brace (const char *str, Token token, Database *db);
-static int f_right_brace (const char *str, Token token, Database *db);
-static int f_white (const char *str, Token token, Database *db);
-static int f_backslash (const char *str, Token token, Database *db);
-static int f_numeric (const char *str, Token token, Database *db);
-static int f_default (const char *str, Token token, Database *db);
-
-static const TokenTable token_tbl[] = {
- { T_NEWLINE, 1 },
- { T_COMMENT, 1 },
- { T_SEMICOLON, 1 },
- { T_DOUBLE_QUOTE, 1 },
- { T_LEFT_BRACE, 1 },
- { T_RIGHT_BRACE, 1 },
- { T_SPACE, 1 },
- { T_TAB, 1 },
- { T_BACKSLASH, 1 },
- { T_NUMERIC_HEX, 2 },
- { T_NUMERIC_DEC, 2 },
- { T_NUMERIC_OCT, 2 },
- { T_DEFAULT, 1 } /* any character */
-};
-
-#define SYM_CR '\r'
-#define SYM_NEWLINE '\n'
-#define SYM_COMMENT '#'
-#define SYM_SEMICOLON ';'
-#define SYM_DOUBLE_QUOTE '"'
-#define SYM_LEFT_BRACE '{'
-#define SYM_RIGHT_BRACE '}'
-#define SYM_SPACE ' '
-#define SYM_TAB '\t'
-#define SYM_BACKSLASH '\\'
-
-/************************************************************************/
-
-#define MAX_NAME_NEST 64
-
-typedef struct {
- ParseState pre_state;
- char *category;
- char *name[MAX_NAME_NEST];
- int nest_depth;
- char **value;
- int value_len;
- int value_num;
- int bufsize; /* bufMaxSize >= bufsize >= 0 */
- int bufMaxSize; /* default : BUFSIZE */
- char *buf;
-} DBParseInfo;
-
-static DBParseInfo parse_info;
-
-static void
-init_parse_info (void)
-{
- static int allocated /* = 0 */;
- char *ptr;
- int size;
- if (!allocated) {
- bzero(&parse_info, sizeof(DBParseInfo));
- parse_info.buf = (char *)Xmalloc(BUFSIZE);
- parse_info.bufMaxSize = BUFSIZE;
- allocated = 1;
- return;
- }
- ptr = parse_info.buf;
- size = parse_info.bufMaxSize;
- bzero(&parse_info, sizeof(DBParseInfo));
- parse_info.buf = ptr;
- parse_info.bufMaxSize = size;
-}
-
-static void
-clear_parse_info (void)
-{
- int i;
- char *ptr;
- int size;
- parse_info.pre_state = S_NULL;
- if (parse_info.category != NULL) {
- Xfree(parse_info.category);
- }
- for (i = 0; i <= parse_info.nest_depth; ++i) {
- if (parse_info.name[i]) {
- Xfree(parse_info.name[i]);
- }
- }
- if (parse_info.value) {
- if (*parse_info.value) {
- Xfree(*parse_info.value);
- }
- Xfree((char *)parse_info.value);
- }
- ptr = parse_info.buf;
- size = parse_info.bufMaxSize;
- bzero(&parse_info, sizeof(DBParseInfo));
- parse_info.buf = ptr;
- parse_info.bufMaxSize = size;
-}
-
-static Bool
-realloc_parse_info(
- int len)
-{
- char *p;
-
- parse_info.bufMaxSize = BUFSIZE * ((parse_info.bufsize + len)/BUFSIZE + 1);
- p = (char *)Xrealloc(parse_info.buf, parse_info.bufMaxSize);
- if (p == NULL)
- return False;
- parse_info.buf = p;
-
- return True;
-}
-
-/************************************************************************/
-
-typedef struct _Line {
- char *str;
- int cursize;
- int maxsize;
- int seq;
-} Line;
-
-static void
-free_line(
- Line *line)
-{
- if (line->str != NULL) {
- Xfree(line->str);
- }
- bzero(line, sizeof(Line));
-}
-
-static int
-realloc_line(
- Line *line,
- int size)
-{
- char *str = line->str;
-
- if (str != NULL) {
- str = (char *)Xrealloc(str, size);
- } else {
- str = (char *)Xmalloc(size);
- }
- if (str == NULL) {
- /* malloc error */
- if (line->str != NULL) {
- Xfree(line->str);
- }
- bzero(line, sizeof(Line));
- return 0;
- }
- line->str = str;
- line->maxsize = size;
- return 1;
-}
-
-#define iswhite(ch) ((ch) == SYM_SPACE || (ch) == SYM_TAB)
-
-static void
-zap_comment(
- char *str,
- int *quoted)
-{
- char *p = str;
-#ifdef never
- *quoted = 0;
- if (*p == SYM_COMMENT) {
- int len = strlen(str);
- if (p[len - 1] == SYM_NEWLINE || p[len - 1] == SYM_CR) {
- *p++ = SYM_NEWLINE;
- }
- *p = '\0';
- }
-#else
- while (*p) {
- if (*p == SYM_DOUBLE_QUOTE) {
- if (p == str || p[-1] != SYM_BACKSLASH) {
- /* unescaped double quote changes quoted state. */
- *quoted = *quoted ? 0 : 1;
- }
- }
- if (*p == SYM_COMMENT && !*quoted) {
- int pos = p - str;
- if (pos == 0 ||
- (iswhite(p[-1]) && (pos == 1 || p[-2] != SYM_BACKSLASH))) {
- int len = strlen(p);
- if (len > 0 && (p[len - 1] == SYM_NEWLINE || p[len-1] == SYM_CR)) {
- /* newline is the identifier for finding end of value.
- therefore, it should not be removed. */
- *p++ = SYM_NEWLINE;
- }
- *p = '\0';
- break;
- }
- }
- ++p;
- }
-#endif
-}
-
-static int
-read_line(
- FILE *fd,
- Line *line)
-{
- char buf[BUFSIZE], *p;
- int len;
- int quoted = 0; /* quoted by double quote? */
- char *str;
- int cur;
-
- str = line->str;
- cur = line->cursize = 0;
-
- while ((p = fgets(buf, BUFSIZE, fd)) != NULL) {
- ++line->seq;
- zap_comment(p, "ed); /* remove comment line */
- len = strlen(p);
- if (len == 0) {
- if (cur > 0) {
- break;
- }
- continue;
- }
- if (cur + len + 1 > line->maxsize) {
- /* need to reallocate buffer. */
- if (! realloc_line(line, line->maxsize + BUFSIZE)) {
- return -1; /* realloc error. */
- }
- str = line->str;
- }
- strncpy(str + cur, p, len);
-
- cur += len;
- str[cur] = '\0';
-#ifdef __UNIXOS2__ /* Take out carriage returns under OS/2 */
- if (cur>1) {
- if (str[cur-2] == '\r' && str[cur-1] == '\n') {
- str[cur-2] = '\n';
- str[cur-1] = '\0';
- cur--;
- }
- }
-#endif
- if (!quoted && cur > 1 && str[cur - 2] == SYM_BACKSLASH &&
- (str[cur - 1] == SYM_NEWLINE || str[cur-1] == SYM_CR)) {
- /* the line is ended backslash followed by newline.
- need to concatinate the next line. */
- cur -= 2;
- str[cur] = '\0';
- } else if (len < BUFSIZE - 1 || buf[len - 1] == SYM_NEWLINE ||
- buf[len - 1] == SYM_CR) {
- /* the line is shorter than BUFSIZE. */
- break;
- }
- }
- if (quoted) {
- /* error. still in quoted state. */
- return -1;
- }
- return line->cursize = cur;
-}
-
-/************************************************************************/
-
-static Token
-get_token(
- const char *str)
-{
- switch (*str) {
- case SYM_NEWLINE:
- case SYM_CR: return T_NEWLINE;
- case SYM_COMMENT: return T_COMMENT;
- case SYM_SEMICOLON: return T_SEMICOLON;
- case SYM_DOUBLE_QUOTE: return T_DOUBLE_QUOTE;
- case SYM_LEFT_BRACE: return T_LEFT_BRACE;
- case SYM_RIGHT_BRACE: return T_RIGHT_BRACE;
- case SYM_SPACE: return T_SPACE;
- case SYM_TAB: return T_TAB;
- case SYM_BACKSLASH:
- switch (str[1]) {
- case 'x': return T_NUMERIC_HEX;
- case 'd': return T_NUMERIC_DEC;
- case 'o': return T_NUMERIC_OCT;
- }
- return T_BACKSLASH;
- default:
- return T_DEFAULT;
- }
-}
-
-static int
-get_word(
- const char *str,
- char *word)
-{
- const char *p = str;
- char *w = word;
- Token token;
- int token_len;
-
- while (*p != '\0') {
- token = get_token(p);
- token_len = token_tbl[token].len;
- if (token == T_BACKSLASH) {
- p += token_len;
- if (*p == '\0')
- break;
- token = get_token(p);
- token_len = token_tbl[token].len;
- } else if (token != T_COMMENT && token != T_DEFAULT) {
- break;
- }
- strncpy(w, p, token_len);
- p += token_len; w += token_len;
- }
- *w = '\0';
- return p - str; /* return number of scanned chars */
-}
-
-static int
-get_quoted_word(
- const char *str,
- char *word)
-{
- const char *p = str;
- char *w = word;
- Token token;
- int token_len;
-
- if (*p == SYM_DOUBLE_QUOTE) {
- ++p;
- }
- while (*p != '\0') {
- token = get_token(p);
- token_len = token_tbl[token].len;
- if (token == T_DOUBLE_QUOTE) {
- p += token_len;
- goto found;
- }
- if (token == T_BACKSLASH) {
- p += token_len;
- if (*p == '\0') {
- break;
- }
- token = get_token(p);
- token_len = token_tbl[token].len;
- }
- strncpy(w, p, token_len);
- p += token_len; w += token_len;
- }
- /* error. cannot detect next double quote */
- return 0;
-
- found:;
- *w = '\0';
- return p - str;
-}
-
-/************************************************************************/
-
-static int
-append_value_list (void)
-{
- char **value_list = parse_info.value;
- char *value;
- int value_num = parse_info.value_num;
- int value_len = parse_info.value_len;
- char *str = parse_info.buf;
- int len = parse_info.bufsize;
- char *p;
-
- if (len < 1) {
- return 1; /* return with no error */
- }
-
- if (value_list == (char **)NULL) {
- value_list = (char **)Xmalloc(sizeof(char *) * 2);
- *value_list = NULL;
- } else {
- char **prev_list = value_list;
-
- value_list = (char **)
- Xrealloc(value_list, sizeof(char *) * (value_num + 2));
- if (value_list == NULL) {
- Xfree(prev_list);
- }
- }
- if (value_list == (char **)NULL)
- goto err2;
-
- value = *value_list;
- if (value == NULL) {
- value = (char *)Xmalloc(value_len + len + 1);
- } else {
- char *prev_value = value;
-
- value = (char *)Xrealloc(value, value_len + len + 1);
- if (value == NULL) {
- Xfree(prev_value);
- }
- }
- if (value == NULL) {
- goto err1;
- }
- if (value != *value_list) {
- int i;
- ssize_t delta;
- delta = value - *value_list;
- *value_list = value;
- for (i = 1; i < value_num; ++i) {
- value_list[i] += delta;
- }
- }
-
- value_list[value_num] = p = &value[value_len];
- value_list[value_num + 1] = NULL;
- strncpy(p, str, len);
- p[len] = 0;
-
- parse_info.value = value_list;
- parse_info.value_num = value_num + 1;
- parse_info.value_len = value_len + len + 1;
- parse_info.bufsize = 0;
- return 1;
-
- err1:
- if (value_list) {
- Xfree((char **)value_list);
- }
- if (value) {
- Xfree(value);
- }
- err2:
- parse_info.value = (char **)NULL;
- parse_info.value_num = 0;
- parse_info.value_len = 0;
- parse_info.bufsize = 0;
- return 0;
-}
-
-static int
-construct_name(
- char *name,
- int size)
-{
- int i;
- int len = 0;
- char *p = name;
-
- for (i = 0; i <= parse_info.nest_depth; ++i) {
- len += strlen(parse_info.name[i]) + 1;
- }
- if (len >= size)
- return 0;
-
- strcpy(p, parse_info.name[0]);
- p += strlen(parse_info.name[0]);
- for (i = 1; i <= parse_info.nest_depth; ++i) {
- *p++ = '.';
- strcpy(p, parse_info.name[i]);
- p += strlen(parse_info.name[i]);
- }
- return *name != '\0';
-}
-
-static int
-store_to_database(
- Database *db)
-{
- Database new = (Database)NULL;
- char name[BUFSIZE];
-
- if (parse_info.pre_state == S_VALUE) {
- if (! append_value_list()) {
- goto err;
- }
- }
-
- if (parse_info.name[parse_info.nest_depth] == NULL) {
- goto err;
- }
-
- new = Xcalloc(1, sizeof(DatabaseRec));
- if (new == (Database)NULL) {
- goto err;
- }
-
- new->category = strdup(parse_info.category);
- if (new->category == NULL) {
- goto err;
- }
-
- if (! construct_name(name, sizeof(name))) {
- goto err;
- }
- new->name = strdup(name);
- if (new->name == NULL) {
- goto err;
- }
- new->next = *db;
- new->value = parse_info.value;
- new->value_num = parse_info.value_num;
- *db = new;
-
- Xfree(parse_info.name[parse_info.nest_depth]);
- parse_info.name[parse_info.nest_depth] = NULL;
-
- parse_info.value = (char **)NULL;
- parse_info.value_num = 0;
- parse_info.value_len = 0;
-
- return 1;
-
- err:
- if (new) {
- if (new->category) {
- Xfree(new->category);
- }
- if (new->name) {
- Xfree(new->name);
- }
- Xfree(new);
- }
- if (parse_info.value) {
- if (*parse_info.value) {
- Xfree(*parse_info.value);
- }
- Xfree((char **)parse_info.value);
- parse_info.value = (char **)NULL;
- parse_info.value_num = 0;
- parse_info.value_len = 0;
- }
- return 0;
-}
-
-#define END_MARK "END"
-#define END_MARK_LEN 3 /*strlen(END_MARK)*/
-
-static int
-check_category_end(
- const char *str)
-{
- const char *p;
- int len;
-
- p = str;
- if (strncmp(p, END_MARK, END_MARK_LEN)) {
- return 0;
- }
- p += END_MARK_LEN;
-
- while (iswhite(*p)) {
- ++p;
- }
- len = strlen(parse_info.category);
- if (strncmp(p, parse_info.category, len)) {
- return 0;
- }
- p += len;
- return p - str;
-}
-
-/************************************************************************/
-
-static int
-f_newline(
- const char *str,
- Token token,
- Database *db)
-{
- switch (parse_info.pre_state) {
- case S_NULL:
- case S_CATEGORY:
- break;
- case S_NAME:
- return 0; /* no value */
- case S_VALUE:
- if (!store_to_database(db))
- return 0;
- parse_info.pre_state = S_CATEGORY;
- break;
- default:
- return 0;
- }
- return token_tbl[token].len;
-}
-
-static int
-f_comment(
- const char *str,
- Token token,
- Database *db)
-{
- /* NOTE: comment is already handled in read_line(),
- so this function is not necessary. */
-
- const char *p = str;
-
- while (*p != SYM_NEWLINE && *p != SYM_CR && *p != '\0') {
- ++p; /* zap to the end of line */
- }
- return p - str;
-}
-
-static int
-f_white(
- const char *str,
- Token token,
- Database *db)
-{
- const char *p = str;
-
- while (iswhite(*p)) {
- ++p;
- }
- return p - str;
-}
-
-static int
-f_semicolon(
- const char *str,
- Token token,
- Database *db)
-{
- switch (parse_info.pre_state) {
- case S_NULL:
- case S_CATEGORY:
- case S_NAME:
- return 0;
- case S_VALUE:
- if (! append_value_list())
- return 0;
- parse_info.pre_state = S_VALUE;
- break;
- default:
- return 0;
- }
- return token_tbl[token].len;
-}
-
-static int
-f_left_brace(
- const char *str,
- Token token,
- Database *db)
-{
- switch (parse_info.pre_state) {
- case S_NULL:
- case S_CATEGORY:
- case S_VALUE:
- return 0;
- case S_NAME:
- if (parse_info.name[parse_info.nest_depth] == NULL
- || parse_info.nest_depth + 1 > MAX_NAME_NEST)
- return 0;
- ++parse_info.nest_depth;
- parse_info.pre_state = S_CATEGORY;
- break;
- default:
- return 0;
- }
- return token_tbl[token].len;
-}
-
-static int
-f_right_brace(
- const char *str,
- Token token,
- Database *db)
-{
- if (parse_info.nest_depth < 1)
- return 0;
-
- switch (parse_info.pre_state) {
- case S_NULL:
- case S_NAME:
- return 0;
- case S_VALUE:
- if (! store_to_database(db))
- return 0;
- /* fall into next case */
- case S_CATEGORY:
- if (parse_info.name[parse_info.nest_depth] != NULL) {
- Xfree(parse_info.name[parse_info.nest_depth]);
- parse_info.name[parse_info.nest_depth] = NULL;
- }
- --parse_info.nest_depth;
- parse_info.pre_state = S_CATEGORY;
- break;
- default:
- return 0;
- }
- return token_tbl[token].len;
-}
-
-static int
-f_double_quote(
- const char *str,
- Token token,
- Database *db)
-{
- char word[BUFSIZE];
- char* wordp;
- int len;
-
- if ((len = strlen (str)) < sizeof word)
- wordp = word;
- else
- wordp = Xmalloc (len + 1);
- if (wordp == NULL)
- return 0;
-
- len = 0;
- switch (parse_info.pre_state) {
- case S_NULL:
- case S_CATEGORY:
- goto err;
- case S_NAME:
- case S_VALUE:
- len = get_quoted_word(str, wordp);
- if (len < 1)
- goto err;
- if ((parse_info.bufsize + (int)strlen(wordp) + 1)
- >= parse_info.bufMaxSize) {
- if (realloc_parse_info(strlen(wordp)+1) == False) {
- goto err;
- }
- }
- strcpy(&parse_info.buf[parse_info.bufsize], wordp);
- parse_info.bufsize += strlen(wordp);
- parse_info.pre_state = S_VALUE;
- break;
- default:
- goto err;
- }
- if (wordp != word)
- Xfree (wordp);
- return len; /* including length of token */
-
-err:
- if (wordp != word)
- Xfree (wordp);
- return 0;
-}
-
-static int
-f_backslash(
- const char *str,
- Token token,
- Database *db)
-{
- return f_default(str, token, db);
-}
-
-static int
-f_numeric(
- const char *str,
- Token token,
- Database *db)
-{
- char word[BUFSIZE];
- const char *p;
- char* wordp;
- int len;
- int token_len;
-
- if ((len = strlen (str)) < sizeof word)
- wordp = word;
- else
- wordp = Xmalloc (len + 1);
- if (wordp == NULL)
- return 0;
-
- switch (parse_info.pre_state) {
- case S_NULL:
- case S_CATEGORY:
- goto err;
- case S_NAME:
- case S_VALUE:
- token_len = token_tbl[token].len;
- p = str + token_len;
- len = get_word(p, wordp);
- if (len < 1)
- goto err;
- if ((parse_info.bufsize + token_len + (int)strlen(wordp) + 1)
- >= parse_info.bufMaxSize) {
- if (realloc_parse_info(token_len + strlen(wordp) + 1) == False)
- goto err;
- }
- strncpy(&parse_info.buf[parse_info.bufsize], str, token_len);
- strcpy(&parse_info.buf[parse_info.bufsize + token_len], wordp);
- parse_info.bufsize += token_len + strlen(wordp);
- parse_info.pre_state = S_VALUE;
- break;
- default:
- goto err;
- }
- if (wordp != word)
- Xfree (wordp);
- return len + token_len;
-
-err:
- if (wordp != word)
- Xfree (wordp);
- return 0;
-}
-
-static int
-f_default(
- const char *str,
- Token token,
- Database *db)
-{
- char word[BUFSIZE], *p;
- char* wordp;
- int len;
-
- if ((len = strlen (str)) < sizeof word)
- wordp = word;
- else
- wordp = Xmalloc (len + 1);
- if (wordp == NULL)
- return 0;
-
- len = get_word(str, wordp);
- if (len < 1)
- goto err;
-
- switch (parse_info.pre_state) {
- case S_NULL:
- if (parse_info.category != NULL)
- goto err;
- p = strdup(wordp);
- if (p == NULL)
- goto err;
- parse_info.category = p;
- parse_info.pre_state = S_CATEGORY;
- break;
- case S_CATEGORY:
- if (parse_info.nest_depth == 0) {
- if (check_category_end(str)) {
- /* end of category is detected.
- clear context and zap to end of this line */
- clear_parse_info();
- len = strlen(str);
- break;
- }
- }
- p = strdup(wordp);
- if (p == NULL)
- goto err;
- if (parse_info.name[parse_info.nest_depth] != NULL) {
- Xfree(parse_info.name[parse_info.nest_depth]);
- }
- parse_info.name[parse_info.nest_depth] = p;
- parse_info.pre_state = S_NAME;
- break;
- case S_NAME:
- case S_VALUE:
- if ((parse_info.bufsize + (int)strlen(wordp) + 1)
- >= parse_info.bufMaxSize) {
- if (realloc_parse_info(strlen(wordp) + 1) == False)
- goto err;
- }
- strcpy(&parse_info.buf[parse_info.bufsize], wordp);
- parse_info.bufsize += strlen(wordp);
- parse_info.pre_state = S_VALUE;
- break;
- default:
- goto err;
- }
- if (wordp != word)
- Xfree (wordp);
- return len;
-
-err:
- if (wordp != word)
- Xfree (wordp);
- return 0;
-}
-
-/************************************************************************/
-
-#ifdef DEBUG
-static void
-PrintDatabase(
- Database db)
-{
- Database p = db;
- int i = 0, j;
-
- printf("***\n*** BEGIN Database\n***\n");
- while (p) {
- printf("%3d: ", i++);
- printf("%s, %s, ", p->category, p->name);
- printf("\t[%d: ", p->value_num);
- for (j = 0; j < p->value_num; ++j) {
- printf("%s, ", p->value[j]);
- }
- printf("]\n");
- p = p->next;
- }
- printf("***\n*** END Database\n***\n");
-}
-#endif
-
-static void
-DestroyDatabase(
- Database db)
-{
- Database p = db;
-
- while (p) {
- if (p->category != NULL) {
- Xfree(p->category);
- }
- if (p->name != NULL) {
- Xfree(p->name);
- }
- if (p->value != (char **)NULL) {
- if (*p->value != NULL) {
- Xfree(*p->value);
- }
- Xfree((char *)p->value);
- }
- db = p->next;
- Xfree((char *)p);
- p = db;
- }
-}
-
-static int
-CountDatabase(
- Database db)
-{
- Database p = db;
- int cnt = 0;
-
- while (p) {
- ++cnt;
- p = p->next;
- }
- return cnt;
-}
-
-static Database
-CreateDatabase(
- char *dbfile)
-{
- Database db = (Database)NULL;
- FILE *fd;
- Line line;
- char *p;
- Token token;
- int len;
- int error = 0;
-
- fd = _XFopenFile(dbfile, "r");
- if (fd == (FILE *)NULL)
- return NULL;
-
- bzero(&line, sizeof(Line));
- init_parse_info();
-
- do {
- int rc = read_line(fd, &line);
- if (rc < 0) {
- error = 1;
- break;
- } else if (rc == 0) {
- break;
- }
- p = line.str;
- while (*p) {
- int (*parse_proc)(const char *str, Token token, Database *db) = NULL;
-
- token = get_token(p);
-
- switch (token_tbl[token].token) {
- case T_NEWLINE:
- parse_proc = f_newline;
- break;
- case T_COMMENT:
- parse_proc = f_comment;
- break;
- case T_SEMICOLON:
- parse_proc = f_semicolon;
- break;
- case T_DOUBLE_QUOTE:
- parse_proc = f_double_quote;
- break;
- case T_LEFT_BRACE:
- parse_proc = f_left_brace;
- break;
- case T_RIGHT_BRACE:
- parse_proc = f_right_brace;
- break;
- case T_SPACE:
- case T_TAB:
- parse_proc = f_white;
- break;
- case T_BACKSLASH:
- parse_proc = f_backslash;
- break;
- case T_NUMERIC_HEX:
- case T_NUMERIC_DEC:
- case T_NUMERIC_OCT:
- parse_proc = f_numeric;
- break;
- case T_DEFAULT:
- parse_proc = f_default;
- break;
- }
-
- len = parse_proc(p, token, &db);
-
- if (len < 1) {
- error = 1;
- break;
- }
- p += len;
- }
- } while (!error);
-
- if (parse_info.pre_state != S_NULL) {
- clear_parse_info();
- error = 1;
- }
- if (error) {
-#ifdef DEBUG
- fprintf(stderr, "database format error at line %d.\n", line.seq);
-#endif
- DestroyDatabase(db);
- db = (Database)NULL;
- }
-
- fclose(fd);
- free_line(&line);
-
-#ifdef DEBUG
- PrintDatabase(db);
-#endif
-
- return db;
-}
-
-/************************************************************************/
-
-#ifndef NOT_X_ENV
-
-/* locale framework functions */
-
-typedef struct _XlcDatabaseRec {
- XrmQuark category_q;
- XrmQuark name_q;
- Database db;
- struct _XlcDatabaseRec *next;
-} XlcDatabaseRec, *XlcDatabase;
-
-typedef struct _XlcDatabaseListRec {
- XrmQuark name_q;
- XlcDatabase lc_db;
- Database database;
- int ref_count;
- struct _XlcDatabaseListRec *next;
-} XlcDatabaseListRec, *XlcDatabaseList;
-
-/* database cache list (per file) */
-static XlcDatabaseList _db_list = (XlcDatabaseList)NULL;
-
-/************************************************************************/
-/* _XlcGetResource(lcd, category, class, value, count) */
-/*----------------------------------------------------------------------*/
-/* This function retrieves XLocale database information. */
-/************************************************************************/
-void
-_XlcGetResource(
- XLCd lcd,
- const char *category,
- const char *class,
- char ***value,
- int *count)
-{
- XLCdPublicMethodsPart *methods = XLC_PUBLIC_METHODS(lcd);
-
- (*methods->get_resource)(lcd, category, class, value, count);
- return;
-}
-
-/************************************************************************/
-/* _XlcGetLocaleDataBase(lcd, category, class, value, count) */
-/*----------------------------------------------------------------------*/
-/* This function retrieves XLocale database information. */
-/************************************************************************/
-void
-_XlcGetLocaleDataBase(
- XLCd lcd,
- const char *category,
- const char *name,
- char ***value,
- int *count)
-{
- XlcDatabase lc_db = (XlcDatabase)XLC_PUBLIC(lcd, xlocale_db);
- XrmQuark category_q, name_q;
-
- category_q = XrmStringToQuark(category);
- name_q = XrmStringToQuark(name);
- for (; lc_db->db; ++lc_db) {
- if (category_q == lc_db->category_q && name_q == lc_db->name_q) {
- *value = lc_db->db->value;
- *count = lc_db->db->value_num;
- return;
- }
- }
- *value = (char **)NULL;
- *count = 0;
-}
-
-/************************************************************************/
-/* _XlcDestroyLocaleDataBase(lcd) */
-/*----------------------------------------------------------------------*/
-/* This function destroy the XLocale Database that bound to the */
-/* specified lcd. If the XLocale Database is refered from some */
-/* other lcd, this function just decreases reference count of */
-/* the database. If no locale refers the database, this function */
-/* remove it from the cache list and free work area. */
-/************************************************************************/
-void
-_XlcDestroyLocaleDataBase(
- XLCd lcd)
-{
- XlcDatabase lc_db = (XlcDatabase)XLC_PUBLIC(lcd, xlocale_db);
- XlcDatabaseList p, prev;
-
- for (p = _db_list, prev = (XlcDatabaseList)NULL; p;
- prev = p, p = p->next) {
- if (p->lc_db == lc_db) {
- if ((-- p->ref_count) < 1) {
- if (p->lc_db != (XlcDatabase)NULL) {
- Xfree((char *)p->lc_db);
- }
- DestroyDatabase(p->database);
- if (prev == (XlcDatabaseList)NULL) {
- _db_list = p->next;
- } else {
- prev->next = p->next;
- }
- Xfree((char*)p);
- }
- break;
- }
- }
- XLC_PUBLIC(lcd, xlocale_db) = (XPointer)NULL;
-}
-
-/************************************************************************/
-/* _XlcCreateLocaleDataBase(lcd) */
-/*----------------------------------------------------------------------*/
-/* This function create an XLocale database which correspond to */
-/* the specified XLCd. */
-/************************************************************************/
-XPointer
-_XlcCreateLocaleDataBase(
- XLCd lcd)
-{
- XlcDatabaseList list, new;
- Database p, database = (Database)NULL;
- XlcDatabase lc_db = (XlcDatabase)NULL;
- XrmQuark name_q;
- char *name;
- int i, n;
-
- name = _XlcFileName(lcd, "locale");
- if (name == NULL)
- return (XPointer)NULL;
-
-#ifndef __UNIXOS2__
- name_q = XrmStringToQuark(name);
-#else
- name_q = XrmStringToQuark((char*)__XOS2RedirRoot(name));
-#endif
- for (list = _db_list; list; list = list->next) {
- if (name_q == list->name_q) {
- list->ref_count++;
- Xfree (name);
- return XLC_PUBLIC(lcd, xlocale_db) = (XPointer)list->lc_db;
- }
- }
-
- database = CreateDatabase(name);
- if (database == (Database)NULL) {
- Xfree (name);
- return (XPointer)NULL;
- }
- n = CountDatabase(database);
- lc_db = Xcalloc(n + 1, sizeof(XlcDatabaseRec));
- if (lc_db == (XlcDatabase)NULL)
- goto err;
- for (p = database, i = 0; p && i < n; p = p->next, ++i) {
- lc_db[i].category_q = XrmStringToQuark(p->category);
- lc_db[i].name_q = XrmStringToQuark(p->name);
- lc_db[i].db = p;
- }
-
- new = (XlcDatabaseList)Xmalloc(sizeof(XlcDatabaseListRec));
- if (new == (XlcDatabaseList)NULL) {
- goto err;
- }
- new->name_q = name_q;
- new->lc_db = lc_db;
- new->database = database;
- new->ref_count = 1;
- new->next = _db_list;
- _db_list = new;
-
- Xfree (name);
- return XLC_PUBLIC(lcd, xlocale_db) = (XPointer)lc_db;
-
- err:
- DestroyDatabase(database);
- if (lc_db != (XlcDatabase)NULL) {
- Xfree((char *)lc_db);
- }
- Xfree (name);
- return (XPointer)NULL;
-}
-
-#endif /* NOT_X_ENV */
+/* + * + * Copyright IBM Corporation 1993 + * + * All Rights Reserved + * + * License 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 IBM not be + * used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING + * ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS, AND + * NONINFRINGEMENT OF THIRD PARTY RIGHTS, IN NO EVENT SHALL + * IBM 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 TORTIOUS ACTION, + * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + * +*/ +/* + * (c) Copyright 1995 FUJITSU LIMITED + * This is source code modified by FUJITSU LIMITED under the Joint + * Development Agreement for the CDE/Motif PST. + */ + + + +#ifndef NOT_X_ENV + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <X11/Xlib.h> +#include <X11/Xresource.h> +#include "Xlibint.h" +#include "XlcPubI.h" + +#else /* NOT_X_ENV */ + +#define Xmalloc malloc +#define Xrealloc realloc +#define Xfree free + +#endif /* NOT_X_ENV */ + +#include <stdint.h> + +/* specifying NOT_X_ENV allows users to just use + the database parsing routine. */ +/* For UDC/VW */ +#ifndef BUFSIZE +#define BUFSIZE 2048 +#endif + +#ifdef COMMENT +#ifdef BUFSIZE +#undef BUFSIZE +#endif +#define BUFSIZE 6144 /* 2048*3 */ +#endif + +#include <stdio.h> +#include <unistd.h> + +typedef struct _DatabaseRec { + char *category; + char *name; + char **value; + int value_num; + struct _DatabaseRec *next; +} DatabaseRec, *Database; + +typedef enum { + S_NULL, /* outside category */ + S_CATEGORY, /* inside category */ + S_NAME, /* has name, expecting values */ + S_VALUE +} ParseState; + +typedef enum { + T_NEWLINE, + T_COMMENT, + T_SEMICOLON, + T_DOUBLE_QUOTE, + T_LEFT_BRACE, + T_RIGHT_BRACE, + T_SPACE, + T_TAB, + T_BACKSLASH, + T_NUMERIC_HEX, + T_NUMERIC_DEC, + T_NUMERIC_OCT, + T_DEFAULT +} Token; + +typedef struct { + Token token; /* token id */ + int len; /* length of token sequence */ +} TokenTable; + +static int f_newline (const char *str, Token token, Database *db); +static int f_comment (const char *str, Token token, Database *db); +static int f_semicolon (const char *str, Token token, Database *db); +static int f_double_quote (const char *str, Token token, Database *db); +static int f_left_brace (const char *str, Token token, Database *db); +static int f_right_brace (const char *str, Token token, Database *db); +static int f_white (const char *str, Token token, Database *db); +static int f_backslash (const char *str, Token token, Database *db); +static int f_numeric (const char *str, Token token, Database *db); +static int f_default (const char *str, Token token, Database *db); + +static const TokenTable token_tbl[] = { + { T_NEWLINE, 1 }, + { T_COMMENT, 1 }, + { T_SEMICOLON, 1 }, + { T_DOUBLE_QUOTE, 1 }, + { T_LEFT_BRACE, 1 }, + { T_RIGHT_BRACE, 1 }, + { T_SPACE, 1 }, + { T_TAB, 1 }, + { T_BACKSLASH, 1 }, + { T_NUMERIC_HEX, 2 }, + { T_NUMERIC_DEC, 2 }, + { T_NUMERIC_OCT, 2 }, + { T_DEFAULT, 1 } /* any character */ +}; + +#define SYM_CR '\r' +#define SYM_NEWLINE '\n' +#define SYM_COMMENT '#' +#define SYM_SEMICOLON ';' +#define SYM_DOUBLE_QUOTE '"' +#define SYM_LEFT_BRACE '{' +#define SYM_RIGHT_BRACE '}' +#define SYM_SPACE ' ' +#define SYM_TAB '\t' +#define SYM_BACKSLASH '\\' + +/************************************************************************/ + +#define MAX_NAME_NEST 64 + +typedef struct { + ParseState pre_state; + char *category; + char *name[MAX_NAME_NEST]; + int nest_depth; + char **value; + int value_len; + int value_num; + int bufsize; /* bufMaxSize >= bufsize >= 0 */ + int bufMaxSize; /* default : BUFSIZE */ + char *buf; +} DBParseInfo; + +static DBParseInfo parse_info; + +static void +init_parse_info (void) +{ + static int allocated /* = 0 */; + char *ptr; + int size; + if (!allocated) { + bzero(&parse_info, sizeof(DBParseInfo)); + parse_info.buf = (char *)Xmalloc(BUFSIZE); + parse_info.bufMaxSize = BUFSIZE; + allocated = 1; + return; + } + ptr = parse_info.buf; + size = parse_info.bufMaxSize; + bzero(&parse_info, sizeof(DBParseInfo)); + parse_info.buf = ptr; + parse_info.bufMaxSize = size; +} + +static void +clear_parse_info (void) +{ + int i; + char *ptr; + int size; + parse_info.pre_state = S_NULL; + if (parse_info.category != NULL) { + Xfree(parse_info.category); + } + for (i = 0; i <= parse_info.nest_depth; ++i) { + if (parse_info.name[i]) { + Xfree(parse_info.name[i]); + } + } + if (parse_info.value) { + if (*parse_info.value) { + Xfree(*parse_info.value); + } + Xfree((char *)parse_info.value); + } + ptr = parse_info.buf; + size = parse_info.bufMaxSize; + bzero(&parse_info, sizeof(DBParseInfo)); + parse_info.buf = ptr; + parse_info.bufMaxSize = size; +} + +static Bool +realloc_parse_info( + int len) +{ + char *p; + + parse_info.bufMaxSize = BUFSIZE * ((parse_info.bufsize + len)/BUFSIZE + 1); + p = (char *)Xrealloc(parse_info.buf, parse_info.bufMaxSize); + if (p == NULL) + return False; + parse_info.buf = p; + + return True; +} + +/************************************************************************/ + +typedef struct _Line { + char *str; + int cursize; + int maxsize; + int seq; +} Line; + +static void +free_line( + Line *line) +{ + if (line->str != NULL) { + Xfree(line->str); + } + bzero(line, sizeof(Line)); +} + +static int +realloc_line( + Line *line, + int size) +{ + char *str = line->str; + + if (str != NULL) { + str = (char *)Xrealloc(str, size); + } else { + str = (char *)Xmalloc(size); + } + if (str == NULL) { + /* malloc error */ + if (line->str != NULL) { + Xfree(line->str); + } + bzero(line, sizeof(Line)); + return 0; + } + line->str = str; + line->maxsize = size; + return 1; +} + +#define iswhite(ch) ((ch) == SYM_SPACE || (ch) == SYM_TAB) + +static void +zap_comment( + char *str, + int *quoted) +{ + char *p = str; +#ifdef never + *quoted = 0; + if (*p == SYM_COMMENT) { + int len = strlen(str); + if (p[len - 1] == SYM_NEWLINE || p[len - 1] == SYM_CR) { + *p++ = SYM_NEWLINE; + } + *p = '\0'; + } +#else + while (*p) { + if (*p == SYM_DOUBLE_QUOTE) { + if (p == str || p[-1] != SYM_BACKSLASH) { + /* unescaped double quote changes quoted state. */ + *quoted = *quoted ? 0 : 1; + } + } + if (*p == SYM_COMMENT && !*quoted) { + int pos = p - str; + if (pos == 0 || + (iswhite(p[-1]) && (pos == 1 || p[-2] != SYM_BACKSLASH))) { + int len = strlen(p); + if (len > 0 && (p[len - 1] == SYM_NEWLINE || p[len-1] == SYM_CR)) { + /* newline is the identifier for finding end of value. + therefore, it should not be removed. */ + *p++ = SYM_NEWLINE; + } + *p = '\0'; + break; + } + } + ++p; + } +#endif +} + +static int +read_line( + FILE *fd, + Line *line) +{ + char buf[BUFSIZE], *p; + int len; + int quoted = 0; /* quoted by double quote? */ + char *str; + int cur; + + str = line->str; + cur = line->cursize = 0; + + while ((p = fgets(buf, BUFSIZE, fd)) != NULL) { + ++line->seq; + zap_comment(p, "ed); /* remove comment line */ + len = strlen(p); + if (len == 0) { + if (cur > 0) { + break; + } + continue; + } + if (cur + len + 1 > line->maxsize) { + /* need to reallocate buffer. */ + if (! realloc_line(line, line->maxsize + BUFSIZE)) { + return -1; /* realloc error. */ + } + str = line->str; + } + strncpy(str + cur, p, len); + + cur += len; + str[cur] = '\0'; +#ifdef __UNIXOS2__ /* Take out carriage returns under OS/2 */ + if (cur>1) { + if (str[cur-2] == '\r' && str[cur-1] == '\n') { + str[cur-2] = '\n'; + str[cur-1] = '\0'; + cur--; + } + } +#endif + if (!quoted && cur > 1 && str[cur - 2] == SYM_BACKSLASH && + (str[cur - 1] == SYM_NEWLINE || str[cur-1] == SYM_CR)) { + /* the line is ended backslash followed by newline. + need to concatinate the next line. */ + cur -= 2; + str[cur] = '\0'; + } else if (len < BUFSIZE - 1 || buf[len - 1] == SYM_NEWLINE || + buf[len - 1] == SYM_CR) { + /* the line is shorter than BUFSIZE. */ + break; + } + } + if (quoted) { + /* error. still in quoted state. */ + return -1; + } + return line->cursize = cur; +} + +/************************************************************************/ + +static Token +get_token( + const char *str) +{ + switch (*str) { + case SYM_NEWLINE: + case SYM_CR: return T_NEWLINE; + case SYM_COMMENT: return T_COMMENT; + case SYM_SEMICOLON: return T_SEMICOLON; + case SYM_DOUBLE_QUOTE: return T_DOUBLE_QUOTE; + case SYM_LEFT_BRACE: return T_LEFT_BRACE; + case SYM_RIGHT_BRACE: return T_RIGHT_BRACE; + case SYM_SPACE: return T_SPACE; + case SYM_TAB: return T_TAB; + case SYM_BACKSLASH: + switch (str[1]) { + case 'x': return T_NUMERIC_HEX; + case 'd': return T_NUMERIC_DEC; + case 'o': return T_NUMERIC_OCT; + } + return T_BACKSLASH; + default: + return T_DEFAULT; + } +} + +static int +get_word( + const char *str, + char *word) +{ + const char *p = str; + char *w = word; + Token token; + int token_len; + + while (*p != '\0') { + token = get_token(p); + token_len = token_tbl[token].len; + if (token == T_BACKSLASH) { + p += token_len; + if (*p == '\0') + break; + token = get_token(p); + token_len = token_tbl[token].len; + } else if (token != T_COMMENT && token != T_DEFAULT) { + break; + } + strncpy(w, p, token_len); + p += token_len; w += token_len; + } + *w = '\0'; + return p - str; /* return number of scanned chars */ +} + +static int +get_quoted_word( + const char *str, + char *word) +{ + const char *p = str; + char *w = word; + Token token; + int token_len; + + if (*p == SYM_DOUBLE_QUOTE) { + ++p; + } + while (*p != '\0') { + token = get_token(p); + token_len = token_tbl[token].len; + if (token == T_DOUBLE_QUOTE) { + p += token_len; + goto found; + } + if (token == T_BACKSLASH) { + p += token_len; + if (*p == '\0') { + break; + } + token = get_token(p); + token_len = token_tbl[token].len; + } + strncpy(w, p, token_len); + p += token_len; w += token_len; + } + /* error. cannot detect next double quote */ + return 0; + + found:; + *w = '\0'; + return p - str; +} + +/************************************************************************/ + +static int +append_value_list (void) +{ + char **value_list = parse_info.value; + char *value; + int value_num = parse_info.value_num; + int value_len = parse_info.value_len; + char *str = parse_info.buf; + int len = parse_info.bufsize; + char *p; + + if (len < 1) { + return 1; /* return with no error */ + } + + if (value_list == (char **)NULL) { + value_list = (char **)Xmalloc(sizeof(char *) * 2); + *value_list = NULL; + } else { + char **prev_list = value_list; + + value_list = (char **) + Xrealloc(value_list, sizeof(char *) * (value_num + 2)); + if (value_list == NULL) { + Xfree(prev_list); + } + } + if (value_list == (char **)NULL) + goto err2; + + value = *value_list; + if (value == NULL) { + value = (char *)Xmalloc(value_len + len + 1); + } else { + char *prev_value = value; + + value = (char *)Xrealloc(value, value_len + len + 1); + if (value == NULL) { + Xfree(prev_value); + } + } + if (value == NULL) { + goto err1; + } + if (value != *value_list) { + int i; + ssize_t delta; + delta = value - *value_list; + *value_list = value; + for (i = 1; i < value_num; ++i) { + value_list[i] += delta; + } + } + + value_list[value_num] = p = &value[value_len]; + value_list[value_num + 1] = NULL; + strncpy(p, str, len); + p[len] = 0; + + parse_info.value = value_list; + parse_info.value_num = value_num + 1; + parse_info.value_len = value_len + len + 1; + parse_info.bufsize = 0; + return 1; + + err1: + if (value_list) { + Xfree((char **)value_list); + } + if (value) { + Xfree(value); + } + err2: + parse_info.value = (char **)NULL; + parse_info.value_num = 0; + parse_info.value_len = 0; + parse_info.bufsize = 0; + return 0; +} + +static int +construct_name( + char *name, + int size) +{ + int i; + int len = 0; + char *p = name; + + for (i = 0; i <= parse_info.nest_depth; ++i) { + len += strlen(parse_info.name[i]) + 1; + } + if (len >= size) + return 0; + + strcpy(p, parse_info.name[0]); + p += strlen(parse_info.name[0]); + for (i = 1; i <= parse_info.nest_depth; ++i) { + *p++ = '.'; + strcpy(p, parse_info.name[i]); + p += strlen(parse_info.name[i]); + } + return *name != '\0'; +} + +static int +store_to_database( + Database *db) +{ + Database new = (Database)NULL; + char name[BUFSIZE]; + + if (parse_info.pre_state == S_VALUE) { + if (! append_value_list()) { + goto err; + } + } + + if (parse_info.name[parse_info.nest_depth] == NULL) { + goto err; + } + + new = Xcalloc(1, sizeof(DatabaseRec)); + if (new == (Database)NULL) { + goto err; + } + + new->category = strdup(parse_info.category); + if (new->category == NULL) { + goto err; + } + + if (! construct_name(name, sizeof(name))) { + goto err; + } + new->name = strdup(name); + if (new->name == NULL) { + goto err; + } + new->next = *db; + new->value = parse_info.value; + new->value_num = parse_info.value_num; + *db = new; + + Xfree(parse_info.name[parse_info.nest_depth]); + parse_info.name[parse_info.nest_depth] = NULL; + + parse_info.value = (char **)NULL; + parse_info.value_num = 0; + parse_info.value_len = 0; + + return 1; + + err: + if (new) { + if (new->category) { + Xfree(new->category); + } + if (new->name) { + Xfree(new->name); + } + Xfree(new); + } + if (parse_info.value) { + if (*parse_info.value) { + Xfree(*parse_info.value); + } + Xfree((char **)parse_info.value); + parse_info.value = (char **)NULL; + parse_info.value_num = 0; + parse_info.value_len = 0; + } + return 0; +} + +#define END_MARK "END" +#define END_MARK_LEN 3 /*strlen(END_MARK)*/ + +static int +check_category_end( + const char *str) +{ + const char *p; + int len; + + p = str; + if (strncmp(p, END_MARK, END_MARK_LEN)) { + return 0; + } + p += END_MARK_LEN; + + while (iswhite(*p)) { + ++p; + } + len = strlen(parse_info.category); + if (strncmp(p, parse_info.category, len)) { + return 0; + } + p += len; + return p - str; +} + +/************************************************************************/ + +static int +f_newline( + const char *str, + Token token, + Database *db) +{ + switch (parse_info.pre_state) { + case S_NULL: + case S_CATEGORY: + break; + case S_NAME: + return 0; /* no value */ + case S_VALUE: + if (!store_to_database(db)) + return 0; + parse_info.pre_state = S_CATEGORY; + break; + default: + return 0; + } + return token_tbl[token].len; +} + +static int +f_comment( + const char *str, + Token token, + Database *db) +{ + /* NOTE: comment is already handled in read_line(), + so this function is not necessary. */ + + const char *p = str; + + while (*p != SYM_NEWLINE && *p != SYM_CR && *p != '\0') { + ++p; /* zap to the end of line */ + } + return p - str; +} + +static int +f_white( + const char *str, + Token token, + Database *db) +{ + const char *p = str; + + while (iswhite(*p)) { + ++p; + } + return p - str; +} + +static int +f_semicolon( + const char *str, + Token token, + Database *db) +{ + switch (parse_info.pre_state) { + case S_NULL: + case S_CATEGORY: + case S_NAME: + return 0; + case S_VALUE: + if (! append_value_list()) + return 0; + parse_info.pre_state = S_VALUE; + break; + default: + return 0; + } + return token_tbl[token].len; +} + +static int +f_left_brace( + const char *str, + Token token, + Database *db) +{ + switch (parse_info.pre_state) { + case S_NULL: + case S_CATEGORY: + case S_VALUE: + return 0; + case S_NAME: + if (parse_info.name[parse_info.nest_depth] == NULL + || parse_info.nest_depth + 1 > MAX_NAME_NEST) + return 0; + ++parse_info.nest_depth; + parse_info.pre_state = S_CATEGORY; + break; + default: + return 0; + } + return token_tbl[token].len; +} + +static int +f_right_brace( + const char *str, + Token token, + Database *db) +{ + if (parse_info.nest_depth < 1) + return 0; + + switch (parse_info.pre_state) { + case S_NULL: + case S_NAME: + return 0; + case S_VALUE: + if (! store_to_database(db)) + return 0; + /* fall into next case */ + case S_CATEGORY: + if (parse_info.name[parse_info.nest_depth] != NULL) { + Xfree(parse_info.name[parse_info.nest_depth]); + parse_info.name[parse_info.nest_depth] = NULL; + } + --parse_info.nest_depth; + parse_info.pre_state = S_CATEGORY; + break; + default: + return 0; + } + return token_tbl[token].len; +} + +static int +f_double_quote( + const char *str, + Token token, + Database *db) +{ + char word[BUFSIZE]; + char* wordp; + int len; + + if ((len = strlen (str)) < sizeof word) + wordp = word; + else + wordp = Xmalloc (len + 1); + if (wordp == NULL) + return 0; + + len = 0; + switch (parse_info.pre_state) { + case S_NULL: + case S_CATEGORY: + goto err; + case S_NAME: + case S_VALUE: + len = get_quoted_word(str, wordp); + if (len < 1) + goto err; + if ((parse_info.bufsize + (int)strlen(wordp) + 1) + >= parse_info.bufMaxSize) { + if (realloc_parse_info(strlen(wordp)+1) == False) { + goto err; + } + } + strcpy(&parse_info.buf[parse_info.bufsize], wordp); + parse_info.bufsize += strlen(wordp); + parse_info.pre_state = S_VALUE; + break; + default: + goto err; + } + if (wordp != word) + Xfree (wordp); + return len; /* including length of token */ + +err: + if (wordp != word) + Xfree (wordp); + return 0; +} + +static int +f_backslash( + const char *str, + Token token, + Database *db) +{ + return f_default(str, token, db); +} + +static int +f_numeric( + const char *str, + Token token, + Database *db) +{ + char word[BUFSIZE]; + const char *p; + char* wordp; + int len; + int token_len; + + if ((len = strlen (str)) < sizeof word) + wordp = word; + else + wordp = Xmalloc (len + 1); + if (wordp == NULL) + return 0; + + switch (parse_info.pre_state) { + case S_NULL: + case S_CATEGORY: + goto err; + case S_NAME: + case S_VALUE: + token_len = token_tbl[token].len; + p = str + token_len; + len = get_word(p, wordp); + if (len < 1) + goto err; + if ((parse_info.bufsize + token_len + (int)strlen(wordp) + 1) + >= parse_info.bufMaxSize) { + if (realloc_parse_info(token_len + strlen(wordp) + 1) == False) + goto err; + } + strncpy(&parse_info.buf[parse_info.bufsize], str, token_len); + strcpy(&parse_info.buf[parse_info.bufsize + token_len], wordp); + parse_info.bufsize += token_len + strlen(wordp); + parse_info.pre_state = S_VALUE; + break; + default: + goto err; + } + if (wordp != word) + Xfree (wordp); + return len + token_len; + +err: + if (wordp != word) + Xfree (wordp); + return 0; +} + +static int +f_default( + const char *str, + Token token, + Database *db) +{ + char word[BUFSIZE], *p; + char* wordp; + int len; + + if ((len = strlen (str)) < sizeof word) + wordp = word; + else + wordp = Xmalloc (len + 1); + if (wordp == NULL) + return 0; + + len = get_word(str, wordp); + if (len < 1) + goto err; + + switch (parse_info.pre_state) { + case S_NULL: + if (parse_info.category != NULL) + goto err; + p = strdup(wordp); + if (p == NULL) + goto err; + parse_info.category = p; + parse_info.pre_state = S_CATEGORY; + break; + case S_CATEGORY: + if (parse_info.nest_depth == 0) { + if (check_category_end(str)) { + /* end of category is detected. + clear context and zap to end of this line */ + clear_parse_info(); + len = strlen(str); + break; + } + } + p = strdup(wordp); + if (p == NULL) + goto err; + if (parse_info.name[parse_info.nest_depth] != NULL) { + Xfree(parse_info.name[parse_info.nest_depth]); + } + parse_info.name[parse_info.nest_depth] = p; + parse_info.pre_state = S_NAME; + break; + case S_NAME: + case S_VALUE: + if ((parse_info.bufsize + (int)strlen(wordp) + 1) + >= parse_info.bufMaxSize) { + if (realloc_parse_info(strlen(wordp) + 1) == False) + goto err; + } + strcpy(&parse_info.buf[parse_info.bufsize], wordp); + parse_info.bufsize += strlen(wordp); + parse_info.pre_state = S_VALUE; + break; + default: + goto err; + } + if (wordp != word) + Xfree (wordp); + return len; + +err: + if (wordp != word) + Xfree (wordp); + return 0; +} + +/************************************************************************/ + +#ifdef DEBUG +static void +PrintDatabase( + Database db) +{ + Database p = db; + int i = 0, j; + + printf("***\n*** BEGIN Database\n***\n"); + while (p) { + printf("%3d: ", i++); + printf("%s, %s, ", p->category, p->name); + printf("\t[%d: ", p->value_num); + for (j = 0; j < p->value_num; ++j) { + printf("%s, ", p->value[j]); + } + printf("]\n"); + p = p->next; + } + printf("***\n*** END Database\n***\n"); +} +#endif + +static void +DestroyDatabase( + Database db) +{ + Database p = db; + + while (p) { + if (p->category != NULL) { + Xfree(p->category); + } + if (p->name != NULL) { + Xfree(p->name); + } + if (p->value != (char **)NULL) { + if (*p->value != NULL) { + Xfree(*p->value); + } + Xfree((char *)p->value); + } + db = p->next; + Xfree((char *)p); + p = db; + } +} + +static int +CountDatabase( + Database db) +{ + Database p = db; + int cnt = 0; + + while (p) { + ++cnt; + p = p->next; + } + return cnt; +} + +static Database +CreateDatabase( + char *dbfile) +{ + Database db = (Database)NULL; + FILE *fd; + Line line; + char *p; + Token token; + int len; + int error = 0; + + fd = _XFopenFile(dbfile, "r"); + if (fd == (FILE *)NULL) + return NULL; + + bzero(&line, sizeof(Line)); + init_parse_info(); + + do { + int rc = read_line(fd, &line); + if (rc < 0) { + error = 1; + break; + } else if (rc == 0) { + break; + } + p = line.str; + while (*p) { + int (*parse_proc)(const char *str, Token token, Database *db) = NULL; + + token = get_token(p); + + switch (token_tbl[token].token) { + case T_NEWLINE: + parse_proc = f_newline; + break; + case T_COMMENT: + parse_proc = f_comment; + break; + case T_SEMICOLON: + parse_proc = f_semicolon; + break; + case T_DOUBLE_QUOTE: + parse_proc = f_double_quote; + break; + case T_LEFT_BRACE: + parse_proc = f_left_brace; + break; + case T_RIGHT_BRACE: + parse_proc = f_right_brace; + break; + case T_SPACE: + case T_TAB: + parse_proc = f_white; + break; + case T_BACKSLASH: + parse_proc = f_backslash; + break; + case T_NUMERIC_HEX: + case T_NUMERIC_DEC: + case T_NUMERIC_OCT: + parse_proc = f_numeric; + break; + case T_DEFAULT: + parse_proc = f_default; + break; + } + + len = parse_proc(p, token, &db); + + if (len < 1) { + error = 1; + break; + } + p += len; + } + } while (!error); + + if (parse_info.pre_state != S_NULL) { + clear_parse_info(); + error = 1; + } + if (error) { +#ifdef DEBUG + fprintf(stderr, "database format error at line %d.\n", line.seq); +#endif + DestroyDatabase(db); + db = (Database)NULL; + } + + fclose(fd); + free_line(&line); + +#ifdef DEBUG + PrintDatabase(db); +#endif + + return db; +} + +/************************************************************************/ + +#ifndef NOT_X_ENV + +/* locale framework functions */ + +typedef struct _XlcDatabaseRec { + XrmQuark category_q; + XrmQuark name_q; + Database db; + struct _XlcDatabaseRec *next; +} XlcDatabaseRec, *XlcDatabase; + +typedef struct _XlcDatabaseListRec { + XrmQuark name_q; + XlcDatabase lc_db; + Database database; + int ref_count; + struct _XlcDatabaseListRec *next; +} XlcDatabaseListRec, *XlcDatabaseList; + +/* database cache list (per file) */ +static XlcDatabaseList _db_list = (XlcDatabaseList)NULL; + +/************************************************************************/ +/* _XlcGetResource(lcd, category, class, value, count) */ +/*----------------------------------------------------------------------*/ +/* This function retrieves XLocale database information. */ +/************************************************************************/ +void +_XlcGetResource( + XLCd lcd, + const char *category, + const char *class, + char ***value, + int *count) +{ + XLCdPublicMethodsPart *methods = XLC_PUBLIC_METHODS(lcd); + + (*methods->get_resource)(lcd, category, class, value, count); + return; +} + +/************************************************************************/ +/* _XlcGetLocaleDataBase(lcd, category, class, value, count) */ +/*----------------------------------------------------------------------*/ +/* This function retrieves XLocale database information. */ +/************************************************************************/ +void +_XlcGetLocaleDataBase( + XLCd lcd, + const char *category, + const char *name, + char ***value, + int *count) +{ + XlcDatabase lc_db = (XlcDatabase)XLC_PUBLIC(lcd, xlocale_db); + XrmQuark category_q, name_q; + + category_q = XrmStringToQuark(category); + name_q = XrmStringToQuark(name); + for (; lc_db->db; ++lc_db) { + if (category_q == lc_db->category_q && name_q == lc_db->name_q) { + *value = lc_db->db->value; + *count = lc_db->db->value_num; + return; + } + } + *value = (char **)NULL; + *count = 0; +} + +/************************************************************************/ +/* _XlcDestroyLocaleDataBase(lcd) */ +/*----------------------------------------------------------------------*/ +/* This function destroy the XLocale Database that bound to the */ +/* specified lcd. If the XLocale Database is refered from some */ +/* other lcd, this function just decreases reference count of */ +/* the database. If no locale refers the database, this function */ +/* remove it from the cache list and free work area. */ +/************************************************************************/ +void +_XlcDestroyLocaleDataBase( + XLCd lcd) +{ + XlcDatabase lc_db = (XlcDatabase)XLC_PUBLIC(lcd, xlocale_db); + XlcDatabaseList p, prev; + + for (p = _db_list, prev = (XlcDatabaseList)NULL; p; + prev = p, p = p->next) { + if (p->lc_db == lc_db) { + if ((-- p->ref_count) < 1) { + if (p->lc_db != (XlcDatabase)NULL) { + Xfree((char *)p->lc_db); + } + DestroyDatabase(p->database); + if (prev == (XlcDatabaseList)NULL) { + _db_list = p->next; + } else { + prev->next = p->next; + } + Xfree((char*)p); + } + break; + } + } + XLC_PUBLIC(lcd, xlocale_db) = (XPointer)NULL; +} + +/************************************************************************/ +/* _XlcCreateLocaleDataBase(lcd) */ +/*----------------------------------------------------------------------*/ +/* This function create an XLocale database which correspond to */ +/* the specified XLCd. */ +/************************************************************************/ +XPointer +_XlcCreateLocaleDataBase( + XLCd lcd) +{ + XlcDatabaseList list, new; + Database p, database = (Database)NULL; + XlcDatabase lc_db = (XlcDatabase)NULL; + XrmQuark name_q; + char *name; + int i, n; + + name = _XlcFileName(lcd, "locale"); + if (name == NULL) + return (XPointer)NULL; + +#ifndef __UNIXOS2__ + name_q = XrmStringToQuark(name); +#else + name_q = XrmStringToQuark((char*)__XOS2RedirRoot(name)); +#endif + for (list = _db_list; list; list = list->next) { + if (name_q == list->name_q) { + list->ref_count++; + Xfree (name); + return XLC_PUBLIC(lcd, xlocale_db) = (XPointer)list->lc_db; + } + } + + database = CreateDatabase(name); + if (database == (Database)NULL) { + Xfree (name); + return (XPointer)NULL; + } + n = CountDatabase(database); + lc_db = Xcalloc(n + 1, sizeof(XlcDatabaseRec)); + if (lc_db == (XlcDatabase)NULL) + goto err; + for (p = database, i = 0; p && i < n; p = p->next, ++i) { + lc_db[i].category_q = XrmStringToQuark(p->category); + lc_db[i].name_q = XrmStringToQuark(p->name); + lc_db[i].db = p; + } + + new = (XlcDatabaseList)Xmalloc(sizeof(XlcDatabaseListRec)); + if (new == (XlcDatabaseList)NULL) { + goto err; + } + new->name_q = name_q; + new->lc_db = lc_db; + new->database = database; + new->ref_count = 1; + new->next = _db_list; + _db_list = new; + + Xfree (name); + return XLC_PUBLIC(lcd, xlocale_db) = (XPointer)lc_db; + + err: + DestroyDatabase(database); + if (lc_db != (XlcDatabase)NULL) { + Xfree((char *)lc_db); + } + Xfree (name); + return (XPointer)NULL; +} + +#endif /* NOT_X_ENV */ diff --git a/libX11/src/xlibi18n/lcFile.c b/libX11/src/xlibi18n/lcFile.c index 5a9b0f4ab..c7f13ffe8 100644 --- a/libX11/src/xlibi18n/lcFile.c +++ b/libX11/src/xlibi18n/lcFile.c @@ -1,829 +1,829 @@ -/*
- *
- * Copyright IBM Corporation 1993
- *
- * All Rights Reserved
- *
- * License 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 IBM not be
- * used in advertising or publicity pertaining to distribution of the
- * software without specific, written prior permission.
- *
- * IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
- * ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS, AND
- * NONINFRINGEMENT OF THIRD PARTY RIGHTS, IN NO EVENT SHALL
- * IBM 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 TORTIOUS ACTION,
- * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- *
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdlib.h>
-#include <stdio.h>
-#include <ctype.h>
-#include "Xlibint.h"
-#include "XlcPubI.h"
-#include <X11/Xos.h>
-#include <unistd.h>
-
-/************************************************************************/
-
-#ifdef __UNIXOS2__
-# define seteuid setuid
-#endif
-#define iscomment(ch) ((ch) == '#' || (ch) == '\0')
-#if defined(WIN32)
-#define isreadable(f) (_XAccessFile(f))
-#else
-#define isreadable(f) ((access((f), R_OK) != -1) ? 1 : 0)
-#endif
-
-#ifndef __UNIXOS2__
-#define LC_PATHDELIM ':'
-#else
-#define LC_PATHDELIM ';'
-#endif
-
-#define XLC_BUFSIZE 256
-
-#ifndef X_NOT_POSIX
-#ifdef _POSIX_SOURCE
-#include <limits.h>
-#else
-#define _POSIX_SOURCE
-#include <limits.h>
-#undef _POSIX_SOURCE
-#endif
-#endif
-#ifndef PATH_MAX
-#ifdef WIN32
-#define PATH_MAX 512
-#else
-#include <sys/param.h>
-#endif
-#ifndef PATH_MAX
-#ifdef MAXPATHLEN
-#define PATH_MAX MAXPATHLEN
-#else
-#define PATH_MAX 1024
-#endif
-#endif
-#endif
-
-#define NUM_LOCALEDIR 64
-
-/* Splits a NUL terminated line into constituents, at colons and newline
- characters. Leading whitespace is removed from constituents. The
- constituents are stored at argv[0..argsize-1]. The number of stored
- constituents (<= argsize) is returned. The line is destructively
- modified. */
-static int
-parse_line(
- char *line,
- char **argv,
- int argsize)
-{
- int argc = 0;
- char *p = line;
-
- while (argc < argsize) {
- while (isspace(*p)) {
- ++p;
- }
- if (*p == '\0') {
- break;
- }
- argv[argc++] = p;
- while (*p != ':' && *p != '\n' && *p != '\0') {
- ++p;
- }
- if (*p == '\0') {
- break;
- }
- *p++ = '\0';
- }
-
- return argc;
-}
-
-#ifdef __UNIXOS2__
-
-/* fg021216: entries in locale files are separated by colons while under
- OS/2, path entries are separated by semicolon, so we need two functions */
-
-static int
-parse_line1(
- char *line,
- char **argv,
- int argsize)
-{
- int argc = 0;
- char *p = line;
-
- while (argc < argsize) {
- while (isspace(*p)) {
- ++p;
- }
- if (*p == '\0') {
- break;
- }
- argv[argc++] = p;
- while (*p != ';' && *p != '\n' && *p != '\0') {
- ++p;
- }
- if (*p == '\0') {
- break;
- }
- *p++ = '\0';
- }
-
- return argc;
-}
-#elif defined(WIN32)
-
-/* this is parse_line but skips drive letters at the beginning of the entry */
-static int
-parse_line1(
- char *line,
- char **argv,
- int argsize)
-{
- int argc = 0;
- char *p = line;
-
- while (argc < argsize) {
- while (isspace(*p)) {
- ++p;
- }
- if (*p == '\0') {
- break;
- }
- argv[argc++] = p;
- if (isalpha(*p) && p[1] == ':') {
- p+= 2; /* skip drive letters */
- }
- while (*p != ':' && *p != '\n' && *p != '\0') {
- ++p;
- }
- if (*p == '\0') {
- break;
- }
- *p++ = '\0';
- }
-
- return argc;
-}
-
-#endif /* __UNIXOS2__ */
-
-/* Splits a colon separated list of directories, and returns the constituent
- paths (without trailing slash). At most argsize constituents are stored
- at argv[0..argsize-1]. The number of stored constituents is returned. */
-static int
-_XlcParsePath(
- char *path,
- char **argv,
- int argsize)
-{
- char *p = path;
- int n, i;
-
-#if !defined(__UNIXOS2__) && !defined(WIN32)
- n = parse_line(path, argv, argsize);
-#else
- n = parse_line1(path, argv, argsize);
-#endif
- for (i = 0; i < n; ++i) {
- int len;
- p = argv[i];
- len = strlen(p);
- if (len > 0 && p[len - 1] == '/') {
- /* eliminate trailing slash */
- p[len - 1] = '\0';
- }
- }
- return n;
-}
-
-#ifndef XLOCALEDIR
-#define XLOCALEDIR "locale"
-#endif
-
-void
-xlocaledir(
- char *buf,
- int buf_len)
-{
- char *p = buf;
- int len = 0;
-
-#ifndef NO_XLOCALEDIR
- char *dir;
- int priv = 1;
-
- dir = getenv("XLOCALEDIR");
-
- if (dir) {
-#ifndef WIN32
- /*
- * Only use the user-supplied path if the process isn't priviledged.
- */
- if (getuid() == geteuid() && getgid() == getegid()) {
-#if defined(HASSETUGID)
- priv = issetugid();
-#elif defined(HASGETRESUID)
- {
- uid_t ruid, euid, suid;
- gid_t rgid, egid, sgid;
- if ((getresuid(&ruid, &euid, &suid) == 0) &&
- (getresgid(&rgid, &egid, &sgid) == 0))
- priv = (euid != suid) || (egid != sgid);
- }
-#else
- /*
- * If there are saved ID's the process might still be priviledged
- * even though the above test succeeded. If issetugid() and
- * getresgid() aren't available, test this by trying to set
- * euid to 0.
- *
- * Note: this only protects setuid-root clients. It doesn't
- * protect other setuid or any setgid clients. If this tradeoff
- * isn't acceptable, set DisableXLocaleDirEnv to YES in host.def.
- */
- unsigned int oldeuid;
- oldeuid = geteuid();
- if (seteuid(0) != 0) {
- priv = 0;
- } else {
- if (seteuid(oldeuid) == -1) {
- /* XXX ouch, coudn't get back to original uid
- what can we do ??? */
- _exit(127);
- }
- priv = 1;
- }
-#endif
- }
-#else
- priv = 0;
-#endif
- if (!priv) {
- len = strlen(dir);
- strncpy(p, dir, buf_len);
- if (len < buf_len) {
- p[len++] = LC_PATHDELIM;
- p += len;
- }
- }
- }
-#endif /* NO_XLOCALEDIR */
-
- if (len < buf_len)
-#ifndef __UNIXOS2__
- strncpy(p, XLOCALEDIR, buf_len - len);
-#else
- strncpy(p,__XOS2RedirRoot(XLOCALEDIR), buf_len - len);
-#endif
- buf[buf_len-1] = '\0';
-}
-
-static void
-xlocalelibdir(
- char *buf,
- int buf_len)
-{
- char *p = buf;
- int len = 0;
-
-#ifndef NO_XLOCALEDIR
- char *dir;
- int priv = 1;
-
- dir = getenv("XLOCALELIBDIR");
-
- if (dir) {
-#ifndef WIN32
- /*
- * Only use the user-supplied path if the process isn't priviledged.
- */
- if (getuid() == geteuid() && getgid() == getegid()) {
-#if defined(HASSETUGID)
- priv = issetugid();
-#elif defined(HASGETRESUID)
- {
- uid_t ruid, euid, suid;
- gid_t rgid, egid, sgid;
- if ((getresuid(&ruid, &euid, &suid) == 0) &&
- (getresgid(&rgid, &egid, &sgid) == 0))
- priv = (euid != suid) || (egid != sgid);
- }
-#else
- /*
- * If there are saved ID's the process might still be priviledged
- * even though the above test succeeded. If issetugid() and
- * getresgid() aren't available, test this by trying to set
- * euid to 0.
- *
- * Note: this only protects setuid-root clients. It doesn't
- * protect other setuid or any setgid clients. If this tradeoff
- * isn't acceptable, set DisableXLocaleDirEnv to YES in host.def.
- */
- unsigned int oldeuid;
- oldeuid = geteuid();
- if (seteuid(0) != 0) {
- priv = 0;
- } else {
- if (seteuid(oldeuid) == -1) {
- /* XXX ouch, coudn't get back to original uid
- what can we do ??? */
- _exit(127);
- }
- priv = 1;
- }
-#endif
- }
-#else
- priv = 0;
-#endif
- if (!priv) {
- len = strlen(dir);
- strncpy(p, dir, buf_len);
- if (len < buf_len) {
- p[len++] = LC_PATHDELIM;
- p += len;
- }
- }
- }
-#endif /* NO_XLOCALEDIR */
-
- if (len < buf_len)
-#ifndef __UNIXOS2__
- strncpy(p, XLOCALELIBDIR, buf_len - len);
-#else
- strncpy(p,__XOS2RedirRoot(XLOCALELIBDIR), buf_len - len);
-#endif
- buf[buf_len-1] = '\0';
-}
-
-/* Mapping direction */
-typedef enum {
- LtoR, /* Map first field to second field */
- RtoL /* Map second field to first field */
-} MapDirection;
-
-static char *
-resolve_name(
- const char *lc_name,
- char *file_name,
- MapDirection direction)
-{
- FILE *fp;
- char buf[XLC_BUFSIZE], *name = NULL;
-
- fp = _XFopenFile (file_name, "r");
- if (fp == NULL)
- return NULL;
-
- while (fgets(buf, XLC_BUFSIZE, fp) != NULL) {
- char *p = buf;
- int n;
- char *args[2], *from, *to;
-#ifdef __UNIXOS2__ /* Take out CR under OS/2 */
- int len;
-
- len = strlen(p);
- if (len > 1) {
- if (*(p+len-2) == '\r' && *(p+len-1) == '\n') {
- *(p+len-2) = '\n';
- *(p+len-1) = '\0';
- }
- }
-#endif
- while (isspace(*p)) {
- ++p;
- }
- if (iscomment(*p)) {
- continue;
- }
- n = parse_line(p, args, 2); /* get first 2 fields */
- if (n != 2) {
- continue;
- }
- if (direction == LtoR) {
- from = args[0], to = args[1]; /* left to right */
- } else {
- from = args[1], to = args[0]; /* right to left */
- }
- if (! strcmp(from, lc_name)) {
- name = strdup(to);
- break;
- }
- }
- fclose(fp);
- return name;
-}
-
-#define c_tolower(ch) ((ch) >= 'A' && (ch) <= 'Z' ? (ch) - 'A' + 'a' : (ch))
-
-static char *
-lowercase(
- char *dst,
- const char *src)
-{
- const char *s;
- char *t;
-
- for (s = src, t = dst; *s; ++s, ++t)
- *t = c_tolower(*s);
- *t = '\0';
- return dst;
-}
-
-/*
- * normalize_lcname(): remove any '_' and '-' and convert any character
- * to lower case after the <language>_<territory> part. If result is identical
- * to argument, free result and
- * return NULL.
- */
-static char *
-normalize_lcname (const char *name)
-{
- char *p, *ret;
- const char *tmp = name;
-
- p = ret = Xmalloc(strlen(name) + 1);
- if (!p)
- return NULL;
-
- if (tmp) {
- while (*tmp && *tmp != '.' && *tmp != '@')
- *p++ = *tmp++;
- while (*tmp) {
- if (*tmp != '-')
- *p++ = c_tolower(*tmp);
- tmp++;
- }
- }
- *p = '\0';
-
- if (strcmp(ret, name) == 0) {
- Xfree(ret);
- return NULL;
- }
-
- return ret;
-}
-
-/************************************************************************/
-char *
-_XlcFileName(
- XLCd lcd,
- const char *category)
-{
- char *siname;
- char cat[XLC_BUFSIZE], dir[XLC_BUFSIZE];
- int i, n;
- char *args[NUM_LOCALEDIR];
- char *file_name = NULL;
-
- if (lcd == (XLCd)NULL)
- return NULL;
-
- siname = XLC_PUBLIC(lcd, siname);
-
- if (category)
- lowercase(cat, category);
- else
- cat[0] = '\0';
- xlocaledir(dir,XLC_BUFSIZE);
- n = _XlcParsePath(dir, args, NUM_LOCALEDIR);
- for (i = 0; i < n; ++i) {
- char buf[PATH_MAX], *name;
-
- name = NULL;
- if ((5 + (args[i] ? strlen (args[i]) : 0) + strlen(cat)) < PATH_MAX) {
- sprintf(buf, "%s/%s.dir", args[i], cat);
- name = resolve_name(siname, buf, RtoL);
- }
- if (name == NULL) {
- continue;
- }
- if (*name == '/') {
- /* supposed to be absolute path name */
- file_name = name;
- } else {
- file_name = Xmalloc(2 + (args[i] ? strlen (args[i]) : 0) +
- (name ? strlen (name) : 0));
- if (file_name != NULL)
- sprintf(file_name, "%s/%s", args[i], name);
- Xfree(name);
- }
- if (isreadable(file_name)) {
- break;
- }
- Xfree(file_name);
- file_name = NULL;
- /* Then, try with next dir */
- }
- return file_name;
-}
-
-/************************************************************************/
-#ifndef LOCALE_ALIAS
-#define LOCALE_ALIAS "locale.alias"
-#endif
-
-int
-_XlcResolveLocaleName(
- const char* lc_name,
- XLCdPublicPart* pub)
-{
- char dir[PATH_MAX], buf[PATH_MAX], *name = NULL;
- char *dst;
- int i, n, sinamelen;
- char *args[NUM_LOCALEDIR];
- static const char locale_alias[] = LOCALE_ALIAS;
- char *tmp_siname;
- char *nlc_name = NULL;
-
- xlocaledir (dir, PATH_MAX);
- n = _XlcParsePath(dir, args, NUM_LOCALEDIR);
- for (i = 0; i < n; ++i) {
- if ((2 + (args[i] ? strlen (args[i]) : 0) +
- strlen (locale_alias)) < PATH_MAX) {
- sprintf (buf, "%s/%s", args[i], locale_alias);
- name = resolve_name (lc_name, buf, LtoR);
- if (!name) {
- if (!nlc_name)
- nlc_name = normalize_lcname(lc_name);
- if (nlc_name)
- name = resolve_name (nlc_name, buf, LtoR);
- }
- }
- if (name != NULL) {
- break;
- }
- }
- if (nlc_name) Xfree(nlc_name);
-
- if (name == NULL) {
- /* vendor locale name == Xlocale name, no expansion of alias */
- pub->siname = strdup (lc_name);
- } else {
- pub->siname = name;
- }
-
- sinamelen = strlen (pub->siname);
- if (sinamelen == 1 && pub->siname[0] == 'C') {
- pub->language = pub->siname;
- pub->territory = pub->codeset = NULL;
- return 1;
- }
-
- /*
- * pub->siname is in the format <lang>_<terr>.<codeset>, typical would
- * be "en_US.ISO8859-1", "en_US.utf8", "ru_RU.KOI-8", or ja_JP.SJIS,
- * although it could be ja.SJIS too.
- */
- tmp_siname = Xrealloc (pub->siname, 2 * (sinamelen + 1));
- if (tmp_siname == NULL) {
- return 0;
- }
- pub->siname = tmp_siname;
-
- /* language */
- dst = &pub->siname[sinamelen + 1];
- strcpy (dst, pub->siname);
- pub->language = dst;
-
- /* territory */
- dst = strchr (dst, '_');
- if (dst) {
- *dst = '\0';
- pub->territory = ++dst;
- } else
- dst = &pub->siname[sinamelen + 1];
-
- /* codeset */
- dst = strchr (dst, '.');
- if (dst) {
- *dst = '\0';
- pub->codeset = ++dst;
- }
-
- return (pub->siname[0] != '\0') ? 1 : 0;
-}
-
-/************************************************************************/
-int
-_XlcResolveI18NPath(char *buf, int buf_len)
-{
- if (buf != NULL) {
- xlocaledir(buf, buf_len);
- }
- return 1;
-}
-
-char *
-_XlcLocaleDirName(char *dir_name, size_t dir_len, char *lc_name)
-{
- char dir[PATH_MAX], buf[PATH_MAX], *name = NULL;
- int i, n;
- char *args[NUM_LOCALEDIR];
- static char locale_alias[] = LOCALE_ALIAS;
- char *target_name = (char*)0;
- char *target_dir = (char*)0;
- char *nlc_name = NULL;
- static char* last_dir_name = 0;
- static size_t last_dir_len = 0;
- static char* last_lc_name = 0;
-
- if (last_lc_name != 0 && strcmp (last_lc_name, lc_name) == 0
- && dir_len >= last_dir_len) {
- strcpy (dir_name, last_dir_name);
- return dir_name;
- }
-
- xlocaledir (dir, PATH_MAX);
- n = _XlcParsePath(dir, args, 256);
- for (i = 0; i < n; ++i) {
-
- if ((2 + (args[i] ? strlen(args[i]) : 0) +
- strlen(locale_alias)) < PATH_MAX) {
- sprintf (buf, "%s/%s", args[i], locale_alias);
- name = resolve_name(lc_name, buf, LtoR);
- if (!name) {
- if (!nlc_name)
- nlc_name = normalize_lcname(lc_name);
- if (nlc_name)
- name = resolve_name (nlc_name, buf, LtoR);
- }
- }
-
- /* If name is not an alias, use lc_name for locale.dir search */
- if (name == NULL)
- name = lc_name;
-
- /* look at locale.dir */
-
- target_dir = args[i];
- if (!target_dir) {
- /* something wrong */
- if (name != lc_name)
- Xfree(name);
- continue;
- }
- if ((1 + strlen (target_dir) + strlen("locale.dir")) < PATH_MAX) {
- sprintf(buf, "%s/locale.dir", target_dir);
- target_name = resolve_name(name, buf, RtoL);
- }
- if (name != lc_name)
- Xfree(name);
- if (target_name != NULL) {
- char *p = 0;
- if ((p = strstr(target_name, "/XLC_LOCALE"))) {
- *p = '\0';
- break;
- }
- Xfree(target_name);
- target_name = NULL;
- }
- name = NULL;
- }
- if (nlc_name) Xfree(nlc_name);
-
- if (target_name == NULL) {
- /* vendor locale name == Xlocale name, no expansion of alias */
- target_dir = args[0];
- target_name = lc_name;
- }
- /* snprintf(dir_name, dir_len, "%s/%", target_dir, target_name); */
- strncpy(dir_name, target_dir, dir_len - 1);
- if (strlen(target_dir) >= dir_len - 1) {
- dir_name[dir_len - 1] = '\0';
- } else {
- strcat(dir_name, "/");
- strncat(dir_name, target_name, dir_len - strlen(dir_name) - 1);
- if (strlen(target_name) >= dir_len - strlen(dir_name) - 1)
- dir_name[dir_len - 1] = '\0';
- }
- if (target_name != lc_name)
- Xfree(target_name);
-
- if (last_dir_name != 0)
- Xfree (last_dir_name);
- if (last_lc_name != 0)
- Xfree (last_lc_name);
- last_dir_len = strlen (dir_name) + 1;
- last_dir_name = Xmalloc (last_dir_len);
- strcpy (last_dir_name, dir_name);
- last_lc_name = strdup (lc_name);
-
- return dir_name;
-}
-
-char *
-_XlcLocaleLibDirName(char *dir_name, size_t dir_len, char *lc_name)
-{
- char dir[PATH_MAX], buf[PATH_MAX], *name = NULL;
- int i, n;
- char *args[NUM_LOCALEDIR];
- static char locale_alias[] = LOCALE_ALIAS;
- char *target_name = (char*)0;
- char *target_dir = (char*)0;
- char *nlc_name = NULL;
- static char* last_dir_name = 0;
- static size_t last_dir_len = 0;
- static char* last_lc_name = 0;
-
- if (last_lc_name != 0 && strcmp (last_lc_name, lc_name) == 0
- && dir_len >= last_dir_len) {
- strcpy (dir_name, last_dir_name);
- return dir_name;
- }
-
- xlocalelibdir (dir, PATH_MAX);
- n = _XlcParsePath(dir, args, 256);
- for (i = 0; i < n; ++i) {
-
- if ((2 + (args[i] ? strlen(args[i]) : 0) +
- strlen(locale_alias)) < PATH_MAX) {
- sprintf (buf, "%s/%s", args[i], locale_alias);
- name = resolve_name(lc_name, buf, LtoR);
- if (!name) {
- if (!nlc_name)
- nlc_name = normalize_lcname(lc_name);
- if (nlc_name)
- name = resolve_name (nlc_name, buf, LtoR);
- }
- }
-
- /* If name is not an alias, use lc_name for locale.dir search */
- if (name == NULL)
- name = lc_name;
-
- /* look at locale.dir */
-
- target_dir = args[i];
- if (!target_dir) {
- /* something wrong */
- if (name != lc_name)
- Xfree(name);
- continue;
- }
- if ((1 + strlen (target_dir) + strlen("locale.dir")) < PATH_MAX) {
- sprintf(buf, "%s/locale.dir", target_dir);
- target_name = resolve_name(name, buf, RtoL);
- }
- if (name != lc_name)
- Xfree(name);
- if (target_name != NULL) {
- char *p = 0;
- if ((p = strstr(target_name, "/XLC_LOCALE"))) {
- *p = '\0';
- break;
- }
- Xfree(target_name);
- target_name = NULL;
- }
- name = NULL;
- }
- if (nlc_name) Xfree(nlc_name);
-
- if (target_name == NULL) {
- /* vendor locale name == Xlocale name, no expansion of alias */
- target_dir = args[0];
- target_name = lc_name;
- }
- /* snprintf(dir_name, dir_len, "%s/%", target_dir, target_name); */
- strncpy(dir_name, target_dir, dir_len - 1);
- if (strlen(target_dir) >= dir_len - 1) {
- dir_name[dir_len - 1] = '\0';
- } else {
- strcat(dir_name, "/");
- strncat(dir_name, target_name, dir_len - strlen(dir_name) - 1);
- if (strlen(target_name) >= dir_len - strlen(dir_name) - 1)
- dir_name[dir_len - 1] = '\0';
- }
- if (target_name != lc_name)
- Xfree(target_name);
-
- if (last_dir_name != 0)
- Xfree (last_dir_name);
- if (last_lc_name != 0)
- Xfree (last_lc_name);
- last_dir_len = strlen (dir_name) + 1;
- last_dir_name = Xmalloc (last_dir_len);
- strcpy (last_dir_name, dir_name);
- last_lc_name = strdup (lc_name);
-
- return dir_name;
-}
+/* + * + * Copyright IBM Corporation 1993 + * + * All Rights Reserved + * + * License 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 IBM not be + * used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING + * ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS, AND + * NONINFRINGEMENT OF THIRD PARTY RIGHTS, IN NO EVENT SHALL + * IBM 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 TORTIOUS ACTION, + * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + * +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdlib.h> +#include <stdio.h> +#include <ctype.h> +#include "Xlibint.h" +#include "XlcPubI.h" +#include <X11/Xos.h> +#include <unistd.h> + +/************************************************************************/ + +#ifdef __UNIXOS2__ +# define seteuid setuid +#endif +#define iscomment(ch) ((ch) == '#' || (ch) == '\0') +#if defined(WIN32) +#define isreadable(f) (_XAccessFile(f)) +#else +#define isreadable(f) ((access((f), R_OK) != -1) ? 1 : 0) +#endif + +#ifndef __UNIXOS2__ +#define LC_PATHDELIM ':' +#else +#define LC_PATHDELIM ';' +#endif + +#define XLC_BUFSIZE 256 + +#ifndef X_NOT_POSIX +#ifdef _POSIX_SOURCE +#include <limits.h> +#else +#define _POSIX_SOURCE +#include <limits.h> +#undef _POSIX_SOURCE +#endif +#endif +#ifndef PATH_MAX +#ifdef WIN32 +#define PATH_MAX 512 +#else +#include <sys/param.h> +#endif +#ifndef PATH_MAX +#ifdef MAXPATHLEN +#define PATH_MAX MAXPATHLEN +#else +#define PATH_MAX 1024 +#endif +#endif +#endif + +#define NUM_LOCALEDIR 64 + +/* Splits a NUL terminated line into constituents, at colons and newline + characters. Leading whitespace is removed from constituents. The + constituents are stored at argv[0..argsize-1]. The number of stored + constituents (<= argsize) is returned. The line is destructively + modified. */ +static int +parse_line( + char *line, + char **argv, + int argsize) +{ + int argc = 0; + char *p = line; + + while (argc < argsize) { + while (isspace(*p)) { + ++p; + } + if (*p == '\0') { + break; + } + argv[argc++] = p; + while (*p != ':' && *p != '\n' && *p != '\0') { + ++p; + } + if (*p == '\0') { + break; + } + *p++ = '\0'; + } + + return argc; +} + +#ifdef __UNIXOS2__ + +/* fg021216: entries in locale files are separated by colons while under + OS/2, path entries are separated by semicolon, so we need two functions */ + +static int +parse_line1( + char *line, + char **argv, + int argsize) +{ + int argc = 0; + char *p = line; + + while (argc < argsize) { + while (isspace(*p)) { + ++p; + } + if (*p == '\0') { + break; + } + argv[argc++] = p; + while (*p != ';' && *p != '\n' && *p != '\0') { + ++p; + } + if (*p == '\0') { + break; + } + *p++ = '\0'; + } + + return argc; +} +#elif defined(WIN32) + +/* this is parse_line but skips drive letters at the beginning of the entry */ +static int +parse_line1( + char *line, + char **argv, + int argsize) +{ + int argc = 0; + char *p = line; + + while (argc < argsize) { + while (isspace(*p)) { + ++p; + } + if (*p == '\0') { + break; + } + argv[argc++] = p; + if (isalpha(*p) && p[1] == ':') { + p+= 2; /* skip drive letters */ + } + while (*p != ':' && *p != '\n' && *p != '\0') { + ++p; + } + if (*p == '\0') { + break; + } + *p++ = '\0'; + } + + return argc; +} + +#endif /* __UNIXOS2__ */ + +/* Splits a colon separated list of directories, and returns the constituent + paths (without trailing slash). At most argsize constituents are stored + at argv[0..argsize-1]. The number of stored constituents is returned. */ +static int +_XlcParsePath( + char *path, + char **argv, + int argsize) +{ + char *p = path; + int n, i; + +#if !defined(__UNIXOS2__) && !defined(WIN32) + n = parse_line(path, argv, argsize); +#else + n = parse_line1(path, argv, argsize); +#endif + for (i = 0; i < n; ++i) { + int len; + p = argv[i]; + len = strlen(p); + if (len > 0 && p[len - 1] == '/') { + /* eliminate trailing slash */ + p[len - 1] = '\0'; + } + } + return n; +} + +#ifndef XLOCALEDIR +#define XLOCALEDIR "locale" +#endif + +void +xlocaledir( + char *buf, + int buf_len) +{ + char *p = buf; + int len = 0; + +#ifndef NO_XLOCALEDIR + char *dir; + int priv = 1; + + dir = getenv("XLOCALEDIR"); + + if (dir) { +#ifndef WIN32 + /* + * Only use the user-supplied path if the process isn't priviledged. + */ + if (getuid() == geteuid() && getgid() == getegid()) { +#if defined(HASSETUGID) + priv = issetugid(); +#elif defined(HASGETRESUID) + { + uid_t ruid, euid, suid; + gid_t rgid, egid, sgid; + if ((getresuid(&ruid, &euid, &suid) == 0) && + (getresgid(&rgid, &egid, &sgid) == 0)) + priv = (euid != suid) || (egid != sgid); + } +#else + /* + * If there are saved ID's the process might still be priviledged + * even though the above test succeeded. If issetugid() and + * getresgid() aren't available, test this by trying to set + * euid to 0. + * + * Note: this only protects setuid-root clients. It doesn't + * protect other setuid or any setgid clients. If this tradeoff + * isn't acceptable, set DisableXLocaleDirEnv to YES in host.def. + */ + unsigned int oldeuid; + oldeuid = geteuid(); + if (seteuid(0) != 0) { + priv = 0; + } else { + if (seteuid(oldeuid) == -1) { + /* XXX ouch, coudn't get back to original uid + what can we do ??? */ + _exit(127); + } + priv = 1; + } +#endif + } +#else + priv = 0; +#endif + if (!priv) { + len = strlen(dir); + strncpy(p, dir, buf_len); + if (len < buf_len) { + p[len++] = LC_PATHDELIM; + p += len; + } + } + } +#endif /* NO_XLOCALEDIR */ + + if (len < buf_len) +#ifndef __UNIXOS2__ + strncpy(p, XLOCALEDIR, buf_len - len); +#else + strncpy(p,__XOS2RedirRoot(XLOCALEDIR), buf_len - len); +#endif + buf[buf_len-1] = '\0'; +} + +static void +xlocalelibdir( + char *buf, + int buf_len) +{ + char *p = buf; + int len = 0; + +#ifndef NO_XLOCALEDIR + char *dir; + int priv = 1; + + dir = getenv("XLOCALELIBDIR"); + + if (dir) { +#ifndef WIN32 + /* + * Only use the user-supplied path if the process isn't priviledged. + */ + if (getuid() == geteuid() && getgid() == getegid()) { +#if defined(HASSETUGID) + priv = issetugid(); +#elif defined(HASGETRESUID) + { + uid_t ruid, euid, suid; + gid_t rgid, egid, sgid; + if ((getresuid(&ruid, &euid, &suid) == 0) && + (getresgid(&rgid, &egid, &sgid) == 0)) + priv = (euid != suid) || (egid != sgid); + } +#else + /* + * If there are saved ID's the process might still be priviledged + * even though the above test succeeded. If issetugid() and + * getresgid() aren't available, test this by trying to set + * euid to 0. + * + * Note: this only protects setuid-root clients. It doesn't + * protect other setuid or any setgid clients. If this tradeoff + * isn't acceptable, set DisableXLocaleDirEnv to YES in host.def. + */ + unsigned int oldeuid; + oldeuid = geteuid(); + if (seteuid(0) != 0) { + priv = 0; + } else { + if (seteuid(oldeuid) == -1) { + /* XXX ouch, coudn't get back to original uid + what can we do ??? */ + _exit(127); + } + priv = 1; + } +#endif + } +#else + priv = 0; +#endif + if (!priv) { + len = strlen(dir); + strncpy(p, dir, buf_len); + if (len < buf_len) { + p[len++] = LC_PATHDELIM; + p += len; + } + } + } +#endif /* NO_XLOCALEDIR */ + + if (len < buf_len) +#ifndef __UNIXOS2__ + strncpy(p, XLOCALELIBDIR, buf_len - len); +#else + strncpy(p,__XOS2RedirRoot(XLOCALELIBDIR), buf_len - len); +#endif + buf[buf_len-1] = '\0'; +} + +/* Mapping direction */ +typedef enum { + LtoR, /* Map first field to second field */ + RtoL /* Map second field to first field */ +} MapDirection; + +static char * +resolve_name( + const char *lc_name, + char *file_name, + MapDirection direction) +{ + FILE *fp; + char buf[XLC_BUFSIZE], *name = NULL; + + fp = _XFopenFile (file_name, "r"); + if (fp == NULL) + return NULL; + + while (fgets(buf, XLC_BUFSIZE, fp) != NULL) { + char *p = buf; + int n; + char *args[2], *from, *to; +#ifdef __UNIXOS2__ /* Take out CR under OS/2 */ + int len; + + len = strlen(p); + if (len > 1) { + if (*(p+len-2) == '\r' && *(p+len-1) == '\n') { + *(p+len-2) = '\n'; + *(p+len-1) = '\0'; + } + } +#endif + while (isspace(*p)) { + ++p; + } + if (iscomment(*p)) { + continue; + } + n = parse_line(p, args, 2); /* get first 2 fields */ + if (n != 2) { + continue; + } + if (direction == LtoR) { + from = args[0], to = args[1]; /* left to right */ + } else { + from = args[1], to = args[0]; /* right to left */ + } + if (! strcmp(from, lc_name)) { + name = strdup(to); + break; + } + } + fclose(fp); + return name; +} + +#define c_tolower(ch) ((ch) >= 'A' && (ch) <= 'Z' ? (ch) - 'A' + 'a' : (ch)) + +static char * +lowercase( + char *dst, + const char *src) +{ + const char *s; + char *t; + + for (s = src, t = dst; *s; ++s, ++t) + *t = c_tolower(*s); + *t = '\0'; + return dst; +} + +/* + * normalize_lcname(): remove any '_' and '-' and convert any character + * to lower case after the <language>_<territory> part. If result is identical + * to argument, free result and + * return NULL. + */ +static char * +normalize_lcname (const char *name) +{ + char *p, *ret; + const char *tmp = name; + + p = ret = Xmalloc(strlen(name) + 1); + if (!p) + return NULL; + + if (tmp) { + while (*tmp && *tmp != '.' && *tmp != '@') + *p++ = *tmp++; + while (*tmp) { + if (*tmp != '-') + *p++ = c_tolower(*tmp); + tmp++; + } + } + *p = '\0'; + + if (strcmp(ret, name) == 0) { + Xfree(ret); + return NULL; + } + + return ret; +} + +/************************************************************************/ +char * +_XlcFileName( + XLCd lcd, + const char *category) +{ + char *siname; + char cat[XLC_BUFSIZE], dir[XLC_BUFSIZE]; + int i, n; + char *args[NUM_LOCALEDIR]; + char *file_name = NULL; + + if (lcd == (XLCd)NULL) + return NULL; + + siname = XLC_PUBLIC(lcd, siname); + + if (category) + lowercase(cat, category); + else + cat[0] = '\0'; + xlocaledir(dir,XLC_BUFSIZE); + n = _XlcParsePath(dir, args, NUM_LOCALEDIR); + for (i = 0; i < n; ++i) { + char buf[PATH_MAX], *name; + + name = NULL; + if ((5 + (args[i] ? strlen (args[i]) : 0) + strlen(cat)) < PATH_MAX) { + sprintf(buf, "%s/%s.dir", args[i], cat); + name = resolve_name(siname, buf, RtoL); + } + if (name == NULL) { + continue; + } + if (*name == '/') { + /* supposed to be absolute path name */ + file_name = name; + } else { + file_name = Xmalloc(2 + (args[i] ? strlen (args[i]) : 0) + + (name ? strlen (name) : 0)); + if (file_name != NULL) + sprintf(file_name, "%s/%s", args[i], name); + Xfree(name); + } + if (isreadable(file_name)) { + break; + } + Xfree(file_name); + file_name = NULL; + /* Then, try with next dir */ + } + return file_name; +} + +/************************************************************************/ +#ifndef LOCALE_ALIAS +#define LOCALE_ALIAS "locale.alias" +#endif + +int +_XlcResolveLocaleName( + const char* lc_name, + XLCdPublicPart* pub) +{ + char dir[PATH_MAX], buf[PATH_MAX], *name = NULL; + char *dst; + int i, n, sinamelen; + char *args[NUM_LOCALEDIR]; + static const char locale_alias[] = LOCALE_ALIAS; + char *tmp_siname; + char *nlc_name = NULL; + + xlocaledir (dir, PATH_MAX); + n = _XlcParsePath(dir, args, NUM_LOCALEDIR); + for (i = 0; i < n; ++i) { + if ((2 + (args[i] ? strlen (args[i]) : 0) + + strlen (locale_alias)) < PATH_MAX) { + sprintf (buf, "%s/%s", args[i], locale_alias); + name = resolve_name (lc_name, buf, LtoR); + if (!name) { + if (!nlc_name) + nlc_name = normalize_lcname(lc_name); + if (nlc_name) + name = resolve_name (nlc_name, buf, LtoR); + } + } + if (name != NULL) { + break; + } + } + if (nlc_name) Xfree(nlc_name); + + if (name == NULL) { + /* vendor locale name == Xlocale name, no expansion of alias */ + pub->siname = strdup (lc_name); + } else { + pub->siname = name; + } + + sinamelen = strlen (pub->siname); + if (sinamelen == 1 && pub->siname[0] == 'C') { + pub->language = pub->siname; + pub->territory = pub->codeset = NULL; + return 1; + } + + /* + * pub->siname is in the format <lang>_<terr>.<codeset>, typical would + * be "en_US.ISO8859-1", "en_US.utf8", "ru_RU.KOI-8", or ja_JP.SJIS, + * although it could be ja.SJIS too. + */ + tmp_siname = Xrealloc (pub->siname, 2 * (sinamelen + 1)); + if (tmp_siname == NULL) { + return 0; + } + pub->siname = tmp_siname; + + /* language */ + dst = &pub->siname[sinamelen + 1]; + strcpy (dst, pub->siname); + pub->language = dst; + + /* territory */ + dst = strchr (dst, '_'); + if (dst) { + *dst = '\0'; + pub->territory = ++dst; + } else + dst = &pub->siname[sinamelen + 1]; + + /* codeset */ + dst = strchr (dst, '.'); + if (dst) { + *dst = '\0'; + pub->codeset = ++dst; + } + + return (pub->siname[0] != '\0') ? 1 : 0; +} + +/************************************************************************/ +int +_XlcResolveI18NPath(char *buf, int buf_len) +{ + if (buf != NULL) { + xlocaledir(buf, buf_len); + } + return 1; +} + +char * +_XlcLocaleDirName(char *dir_name, size_t dir_len, char *lc_name) +{ + char dir[PATH_MAX], buf[PATH_MAX], *name = NULL; + int i, n; + char *args[NUM_LOCALEDIR]; + static char locale_alias[] = LOCALE_ALIAS; + char *target_name = (char*)0; + char *target_dir = (char*)0; + char *nlc_name = NULL; + static char* last_dir_name = 0; + static size_t last_dir_len = 0; + static char* last_lc_name = 0; + + if (last_lc_name != 0 && strcmp (last_lc_name, lc_name) == 0 + && dir_len >= last_dir_len) { + strcpy (dir_name, last_dir_name); + return dir_name; + } + + xlocaledir (dir, PATH_MAX); + n = _XlcParsePath(dir, args, 256); + for (i = 0; i < n; ++i) { + + if ((2 + (args[i] ? strlen(args[i]) : 0) + + strlen(locale_alias)) < PATH_MAX) { + sprintf (buf, "%s/%s", args[i], locale_alias); + name = resolve_name(lc_name, buf, LtoR); + if (!name) { + if (!nlc_name) + nlc_name = normalize_lcname(lc_name); + if (nlc_name) + name = resolve_name (nlc_name, buf, LtoR); + } + } + + /* If name is not an alias, use lc_name for locale.dir search */ + if (name == NULL) + name = lc_name; + + /* look at locale.dir */ + + target_dir = args[i]; + if (!target_dir) { + /* something wrong */ + if (name != lc_name) + Xfree(name); + continue; + } + if ((1 + strlen (target_dir) + strlen("locale.dir")) < PATH_MAX) { + sprintf(buf, "%s/locale.dir", target_dir); + target_name = resolve_name(name, buf, RtoL); + } + if (name != lc_name) + Xfree(name); + if (target_name != NULL) { + char *p = 0; + if ((p = strstr(target_name, "/XLC_LOCALE"))) { + *p = '\0'; + break; + } + Xfree(target_name); + target_name = NULL; + } + name = NULL; + } + if (nlc_name) Xfree(nlc_name); + + if (target_name == NULL) { + /* vendor locale name == Xlocale name, no expansion of alias */ + target_dir = args[0]; + target_name = lc_name; + } + /* snprintf(dir_name, dir_len, "%s/%", target_dir, target_name); */ + strncpy(dir_name, target_dir, dir_len - 1); + if (strlen(target_dir) >= dir_len - 1) { + dir_name[dir_len - 1] = '\0'; + } else { + strcat(dir_name, "/"); + strncat(dir_name, target_name, dir_len - strlen(dir_name) - 1); + if (strlen(target_name) >= dir_len - strlen(dir_name) - 1) + dir_name[dir_len - 1] = '\0'; + } + if (target_name != lc_name) + Xfree(target_name); + + if (last_dir_name != 0) + Xfree (last_dir_name); + if (last_lc_name != 0) + Xfree (last_lc_name); + last_dir_len = strlen (dir_name) + 1; + last_dir_name = Xmalloc (last_dir_len); + strcpy (last_dir_name, dir_name); + last_lc_name = strdup (lc_name); + + return dir_name; +} + +char * +_XlcLocaleLibDirName(char *dir_name, size_t dir_len, char *lc_name) +{ + char dir[PATH_MAX], buf[PATH_MAX], *name = NULL; + int i, n; + char *args[NUM_LOCALEDIR]; + static char locale_alias[] = LOCALE_ALIAS; + char *target_name = (char*)0; + char *target_dir = (char*)0; + char *nlc_name = NULL; + static char* last_dir_name = 0; + static size_t last_dir_len = 0; + static char* last_lc_name = 0; + + if (last_lc_name != 0 && strcmp (last_lc_name, lc_name) == 0 + && dir_len >= last_dir_len) { + strcpy (dir_name, last_dir_name); + return dir_name; + } + + xlocalelibdir (dir, PATH_MAX); + n = _XlcParsePath(dir, args, 256); + for (i = 0; i < n; ++i) { + + if ((2 + (args[i] ? strlen(args[i]) : 0) + + strlen(locale_alias)) < PATH_MAX) { + sprintf (buf, "%s/%s", args[i], locale_alias); + name = resolve_name(lc_name, buf, LtoR); + if (!name) { + if (!nlc_name) + nlc_name = normalize_lcname(lc_name); + if (nlc_name) + name = resolve_name (nlc_name, buf, LtoR); + } + } + + /* If name is not an alias, use lc_name for locale.dir search */ + if (name == NULL) + name = lc_name; + + /* look at locale.dir */ + + target_dir = args[i]; + if (!target_dir) { + /* something wrong */ + if (name != lc_name) + Xfree(name); + continue; + } + if ((1 + strlen (target_dir) + strlen("locale.dir")) < PATH_MAX) { + sprintf(buf, "%s/locale.dir", target_dir); + target_name = resolve_name(name, buf, RtoL); + } + if (name != lc_name) + Xfree(name); + if (target_name != NULL) { + char *p = 0; + if ((p = strstr(target_name, "/XLC_LOCALE"))) { + *p = '\0'; + break; + } + Xfree(target_name); + target_name = NULL; + } + name = NULL; + } + if (nlc_name) Xfree(nlc_name); + + if (target_name == NULL) { + /* vendor locale name == Xlocale name, no expansion of alias */ + target_dir = args[0]; + target_name = lc_name; + } + /* snprintf(dir_name, dir_len, "%s/%", target_dir, target_name); */ + strncpy(dir_name, target_dir, dir_len - 1); + if (strlen(target_dir) >= dir_len - 1) { + dir_name[dir_len - 1] = '\0'; + } else { + strcat(dir_name, "/"); + strncat(dir_name, target_name, dir_len - strlen(dir_name) - 1); + if (strlen(target_name) >= dir_len - strlen(dir_name) - 1) + dir_name[dir_len - 1] = '\0'; + } + if (target_name != lc_name) + Xfree(target_name); + + if (last_dir_name != 0) + Xfree (last_dir_name); + if (last_lc_name != 0) + Xfree (last_lc_name); + last_dir_len = strlen (dir_name) + 1; + last_dir_name = Xmalloc (last_dir_len); + strcpy (last_dir_name, dir_name); + last_lc_name = strdup (lc_name); + + return dir_name; +} diff --git a/libX11/src/xlibi18n/lcGeneric.c b/libX11/src/xlibi18n/lcGeneric.c index 7001e69fd..bf85bfdbc 100644 --- a/libX11/src/xlibi18n/lcGeneric.c +++ b/libX11/src/xlibi18n/lcGeneric.c @@ -1,1181 +1,1181 @@ -/*
- * Copyright 1992, 1993 by TOSHIBA Corp.
- *
- * 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 TOSHIBA not be used in advertising
- * or publicity pertaining to distribution of the software without specific,
- * written prior permission. TOSHIBA make no representations about the
- * suitability of this software for any purpose. It is provided "as is"
- * without express or implied warranty.
- *
- * TOSHIBA DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
- * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
- * TOSHIBA 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 TORTIOUS ACTION,
- * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- *
- * Author: Katsuhisa Yano TOSHIBA Corp.
- * mopi@osa.ilab.toshiba.co.jp
- */
-/*
- * (c) Copyright 1995 FUJITSU LIMITED
- * This is source code modified by FUJITSU LIMITED under the Joint
- * Development Agreement for the CDE/Motif PST.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <unistd.h>
-#include "Xlibint.h"
-#include "XlcGeneric.h"
-
-static XLCd create (const char *name, XLCdMethods methods);
-static Bool initialize (XLCd lcd);
-static void destroy (XLCd lcd);
-
-static XLCdPublicMethodsRec genericMethods = {
- { NULL }, /* use default methods */
- {
- NULL,
- create,
- initialize,
- destroy,
- NULL
- }
-};
-
-XLCdMethods _XlcGenericMethods = (XLCdMethods) &genericMethods;
-
-static XLCd
-create(
- const char *name,
- XLCdMethods methods)
-{
- XLCd lcd;
- XLCdPublicMethods new;
-
- lcd = Xcalloc(1, sizeof(XLCdRec));
- if (lcd == NULL)
- return (XLCd) NULL;
-
- lcd->core = Xcalloc(1, sizeof(XLCdGenericRec));
- if (lcd->core == NULL)
- goto err;
-
- new = (XLCdPublicMethods) Xmalloc(sizeof(XLCdPublicMethodsRec));
- if (new == NULL)
- goto err;
- memcpy(new,methods,sizeof(XLCdPublicMethodsRec));
- lcd->methods = (XLCdMethods) new;
-
- return lcd;
-
-err:
- Xfree(lcd);
- return (XLCd) NULL;
-}
-
-static Bool
-string_to_encoding(
- const char *str,
- char *encoding)
-{
- char *next;
- long value;
- int base;
-
- while (*str) {
- if (*str == '\\') {
- switch (*(str + 1)) {
- case 'x':
- case 'X':
- base = 16;
- break;
- default:
- base = 8;
- break;
- }
- value = strtol(str + 2, &next, base);
- if (str + 2 != next) {
- *((unsigned char *) encoding++) = (unsigned char) value;
- str = next;
- continue;
- }
- }
- *encoding++ = *str++;
- }
-
- *encoding = '\0';
-
- return True;
-}
-
-static Bool
-string_to_ulong(
- const char *str,
- unsigned long *value)
-{
- const char *tmp1 = str;
- int base;
-
- if (*tmp1++ != '\\') {
- tmp1--;
- base = 10;
- } else {
- switch (*tmp1++) {
- case 'x':
- base = 16;
- break;
- case 'o':
- base = 8;
- break;
- case 'd':
- base = 10;
- break;
- default:
- return(False);
- }
- }
- *value = (unsigned long) strtol(tmp1, NULL, base);
- return(True);
-}
-
-
-static Bool
-add_charset(
- CodeSet codeset,
- XlcCharSet charset)
-{
- XlcCharSet *new_list;
- int num;
-
- if ((num = codeset->num_charsets))
- new_list = (XlcCharSet *) Xrealloc(codeset->charset_list,
- (num + 1) * sizeof(XlcCharSet));
- else
- new_list = (XlcCharSet *) Xmalloc(sizeof(XlcCharSet));
-
- if (new_list == NULL)
- return False;
-
- new_list[num] = charset;
- codeset->charset_list = new_list;
- codeset->num_charsets = num + 1;
-
- return True;
-}
-
-static CodeSet
-add_codeset(
- XLCdGenericPart *gen)
-{
- CodeSet new, *new_list;
- int num;
-
- new = Xcalloc(1, sizeof(CodeSetRec));
- if (new == NULL)
- return NULL;
-
- if ((num = gen->codeset_num))
- new_list = (CodeSet *) Xrealloc(gen->codeset_list,
- (num + 1) * sizeof(CodeSet));
- else
- new_list = (CodeSet *) Xmalloc(sizeof(CodeSet));
-
- if (new_list == NULL)
- goto err;
-
- new_list[num] = new;
- gen->codeset_list = new_list;
- gen->codeset_num = num + 1;
-
- return new;
-
-err:
- Xfree(new);
-
- return NULL;
-}
-
-static Bool
-add_parse_list(
- XLCdGenericPart *gen,
- EncodingType type,
- const char *encoding,
- CodeSet codeset)
-{
- ParseInfo new, *new_list;
- char *str;
- unsigned char ch;
- int num;
-
- str = strdup(encoding);
- if (str == NULL)
- return False;
-
- new = Xcalloc(1, sizeof(ParseInfoRec));
- if (new == NULL)
- goto err;
-
- if (gen->mb_parse_table == NULL) {
- gen->mb_parse_table = Xcalloc(1, 256); /* 2^8 */
- if (gen->mb_parse_table == NULL)
- goto err;
- }
-
- if ((num = gen->mb_parse_list_num))
- new_list = (ParseInfo *) Xrealloc(gen->mb_parse_list,
- (num + 2) * sizeof(ParseInfo));
- else {
- new_list = (ParseInfo *) Xmalloc(2 * sizeof(ParseInfo));
- }
-
- if (new_list == NULL)
- goto err;
-
- new_list[num] = new;
- new_list[num + 1] = NULL;
- gen->mb_parse_list = new_list;
- gen->mb_parse_list_num = num + 1;
-
- ch = (unsigned char) *str;
- if (gen->mb_parse_table[ch] == 0)
- gen->mb_parse_table[ch] = num + 1;
-
- new->type = type;
- new->encoding = str;
- new->codeset = codeset;
-
- if (codeset->parse_info == NULL)
- codeset->parse_info = new;
-
- return True;
-
-err:
- Xfree(str);
- if (new)
- Xfree(new);
-
- return False;
-}
-
-static void
-free_charset(
- XLCd lcd)
-{
- XLCdGenericPart *gen = XLC_GENERIC_PART(lcd);
- ParseInfo *parse_info;
- int num;
-
- if (gen->mb_parse_table)
- Xfree(gen->mb_parse_table);
- if ((num = gen->mb_parse_list_num) > 0) {
- for (parse_info = gen->mb_parse_list; num-- > 0; parse_info++) {
- if ((*parse_info)->encoding)
- Xfree((*parse_info)->encoding);
- Xfree(*parse_info);
- }
- Xfree(gen->mb_parse_list);
- }
-
- if ((num = gen->codeset_num) > 0)
- Xfree(gen->codeset_list);
-}
-
-/* For VW/UDC */
-
-#define FORWARD (unsigned long)'+'
-#define BACKWARD (unsigned long)'-'
-
-static const char *
-getscope(
- const char *str,
- FontScope scp)
-{
- unsigned long start = 0;
- unsigned long end = 0;
- unsigned long dest = 0;
- unsigned long shift = 0;
- unsigned long direction = 0;
- sscanf(str,"[\\x%lx,\\x%lx]->\\x%lx", &start, &end, &dest);
- if (dest) {
- if (dest >= start) {
- shift = dest - start;
- direction = FORWARD ;
- } else {
- shift = start - dest;
- direction = BACKWARD;
- }
- }
- scp->start = start ;
- scp->end = end ;
- scp->shift = shift ;
- scp->shift_direction
- = direction ;
- /* .......... */
- while (*str) {
- if (*str == ',' && *(str+1) == '[')
- break;
- str++;
- }
- return str+1;
-}
-
-static int
-count_scopemap(
- const char *str)
-{
- const char *ptr;
- int num=0;
- for (ptr=str; *ptr; ptr++) {
- if (*ptr == ']') {
- num++;
- }
- }
- return num;
-}
-
-FontScope
-_XlcParse_scopemaps(
- const char *str,
- int *size)
-{
- int num=0,i;
- FontScope scope,sc_ptr;
- const char *str_sc;
-
- num = count_scopemap(str);
- scope = (FontScope) Xmalloc(num * sizeof(FontScopeRec));
- if (scope == NULL)
- return NULL;
-
- for (i=0, str_sc=str, sc_ptr=scope; i < num; i++, sc_ptr++) {
- str_sc = getscope(str_sc, sc_ptr);
- }
- *size = num;
- return scope;
-}
-
-void
-_XlcDbg_printValue(
- const char *str,
- char **value,
- int num)
-{
-/*
- int i;
- for (i = 0; i < num; i++)
- fprintf(stderr, "%s value[%d] = %s\n", str, i, value[i]);
-*/
-}
-
-static void
-dmpscope(
- const char* name,
- FontScope sc,
- int num)
-{
-/*
- int i;
- fprintf(stderr, "dmpscope %s\n", name);
- for (i=0; i<num; i++)
- fprintf(stderr,"%x %x %x %x \n",
- sc[i].start,
- sc[i].end,
- sc[i].shift,
- sc[i].shift_direction);
- fprintf(stderr, "dmpscope end\n");
-*/
-}
-
-static XlcCharSet
-srch_charset_define(
- const char *name,
- int *new)
-{
- XlcCharSet charset;
-
- *new = 0;
- charset = _XlcGetCharSet(name);
- if (charset == NULL &&
- (charset = _XlcCreateDefaultCharSet(name, ""))) {
- _XlcAddCharSet(charset);
- *new = 1;
- charset->source = CSsrcXLC;
- }
- return charset;
-}
-
-static void
-read_charset_define(
- XLCd lcd,
- XLCdGenericPart *gen)
-{
- int i;
- char csd[16], cset_name[256];
- char name[BUFSIZ];
- XlcCharSet charsetd;
- char **value;
- int num, new = 0;
- XlcSide side = XlcUnknown;
- char *tmp;
-
- for (i=0; ; i++) { /* loop start */
- charsetd = 0;
- sprintf(csd, "csd%d", i);
-
- /* charset_name */
- sprintf(name, "%s.%s", csd, "charset_name");
- _XlcGetResource(lcd, "XLC_CHARSET_DEFINE", name, &value, &num);
- _XlcDbg_printValue(name,value,num);
- if (num > 0) {
- /* hackers will get truncated -- C'est la vie */
- strncpy(cset_name,value[0], sizeof cset_name - 1);
- cset_name[(sizeof cset_name) - 1] = '\0';
- sprintf(name, "%s.%s", csd , "side");
- _XlcGetResource(lcd, "XLC_CHARSET_DEFINE", name, &value, &num);
- if (num > 0) {
- _XlcDbg_printValue(name,value,num);
- if (!_XlcNCompareISOLatin1(value[0], "none", 4)) {
- side = XlcGLGR;
- } else if (!_XlcNCompareISOLatin1(value[0], "GL", 2)) {
- side = XlcGL;
- strcat(cset_name,":GL");
- } else {
- side = XlcGR;
- strcat(cset_name,":GR");
- }
- if (charsetd == NULL &&
- (charsetd = srch_charset_define(cset_name,&new)) == NULL)
- return;
- }
- } else {
- if (i == 0)
- continue;
- else
- break;
- }
- if (new) {
- tmp = strdup(cset_name);
- if (tmp == NULL)
- return;
- charsetd->name = tmp;
- }
- /* side */
- charsetd->side = side ;
- /* length */
- sprintf(name, "%s.%s", csd, "length");
- _XlcGetResource(lcd, "XLC_CHARSET_DEFINE", name, &value, &num);
- if (num > 0) {
- _XlcDbg_printValue(name,value,num);
- charsetd->char_size = atoi(value[0]);
- }
- /* gc_number */
- sprintf(name, "%s.%s", csd, "gc_number");
- _XlcGetResource(lcd, "XLC_CHARSET_DEFINE", name, &value, &num);
- if (num > 0) {
- _XlcDbg_printValue(name,value,num);
- charsetd->set_size = atoi(value[0]);
- }
- /* string_encoding */
- sprintf(name, "%s.%s", csd, "string_encoding");
- _XlcGetResource(lcd, "XLC_CHARSET_DEFINE", name, &value, &num);
- if (num > 0) {
- _XlcDbg_printValue(name,value,num);
- if (!strcmp("False",value[0])) {
- charsetd->string_encoding = False;
- } else {
- charsetd->string_encoding = True;
- }
- }
- /* sequence */
- sprintf(name, "%s.%s", csd, "sequence");
- _XlcGetResource(lcd, "XLC_CHARSET_DEFINE", name, &value, &num);
- if (num > 0) {
- _XlcDbg_printValue(name,value,num);
-/*
- if (charsetd->ct_sequence) {
- Xfree(charsetd->ct_sequence);
- }
-*/
- tmp = (char *)Xmalloc(strlen(value[0])+1);
- if (tmp == NULL)
- return;
- charsetd->ct_sequence = tmp;
- string_to_encoding(value[0],tmp);
- }
- /* encoding_name */
- sprintf(name, "%s.%s", csd, "encoding_name");
- _XlcGetResource(lcd, "XLC_CHARSET_DEFINE", name, &value, &num);
- if (num > 0) {
- _XlcDbg_printValue(name,value,num);
-/*
- if (charsetd->encoding_name) {
- Xfree(charsetd->encoding_name);
- }
-*/
- tmp = strdup(value[0]);
- charsetd->encoding_name = tmp;
- charsetd->xrm_encoding_name = XrmStringToQuark(tmp);
- }
- _XlcAddCT(charsetd->name, charsetd->ct_sequence);
- }
-}
-
-static SegConv
-add_conversion(
- XLCdGenericPart *gen)
-{
- SegConv new_list;
- int num;
-
- if ((num = gen->segment_conv_num) > 0) {
- new_list = (SegConv) Xrealloc(gen->segment_conv,
- (num + 1) * sizeof(SegConvRec));
- } else {
- new_list = (SegConv) Xmalloc(sizeof(SegConvRec));
- }
-
- if (new_list == NULL)
- return NULL;
-
- gen->segment_conv = new_list;
- gen->segment_conv_num = num + 1;
-
- return &new_list[num];
-
-}
-
-static void
-read_segmentconversion(
- XLCd lcd,
- XLCdGenericPart *gen)
-{
- int i;
- char conv[16];
- char name[BUFSIZ];
- char **value;
- int num,new;
- SegConv conversion;
- for (i=0 ; ; i++) { /* loop start */
- conversion = 0;
- sprintf(conv, "conv%d", i);
-
- /* length */
- sprintf(name, "%s.%s", conv, "length");
- _XlcGetResource(lcd, "XLC_SEGMENTCONVERSION", name, &value, &num);
- if (num > 0) {
- if (conversion == NULL &&
- (conversion = add_conversion(gen)) == NULL) {
- return;
- }
- _XlcDbg_printValue(name,value,num);
- } else {
- if (i == 0)
- continue;
- else
- break;
- }
- conversion->length = atoi(value[0]);
-
- /* source_encoding */
- sprintf(name, "%s.%s", conv, "source_encoding");
- _XlcGetResource(lcd, "XLC_SEGMENTCONVERSION", name, &value, &num);
- if (num > 0) {
- char *tmp;
- _XlcDbg_printValue(name,value,num);
- tmp = strdup(value[0]);
- if (tmp == NULL)
- return;
- conversion->source_encoding = tmp;
- conversion->source = srch_charset_define(tmp,&new);
- }
- /* destination_encoding */
- sprintf(name, "%s.%s", conv, "destination_encoding");
- _XlcGetResource(lcd, "XLC_SEGMENTCONVERSION", name, &value, &num);
- if (num > 0) {
- char *tmp;
- _XlcDbg_printValue(name,value,num);
- tmp = strdup(value[0]);
- if (tmp == NULL)
- return;
- conversion->destination_encoding = tmp;
- conversion->dest = srch_charset_define(tmp,&new);
- }
- /* range */
- sprintf(name, "%s.%s", conv, "range");
- _XlcGetResource(lcd, "XLC_SEGMENTCONVERSION", name, &value, &num);
- if (num > 0) {
- _XlcDbg_printValue(name,value,num);
- sscanf(value[0],"\\x%lx,\\x%lx",
- &(conversion->range.start), &(conversion->range.end));
- }
- /* conversion */
- sprintf(name, "%s.%s", conv, "conversion");
- _XlcGetResource(lcd, "XLC_SEGMENTCONVERSION", name, &value, &num);
- if (num > 0) {
- _XlcDbg_printValue(name,value,num);
- conversion->conv =
- _XlcParse_scopemaps(value[0],&conversion->conv_num);
- }
- } /* loop end */
-}
-
-static ExtdSegment
-create_ctextseg(
- char **value,
- int num)
-{
- ExtdSegment ret;
- char* ptr;
- char* cset_name = NULL;
- int i,new;
- FontScope scope;
- ret = (ExtdSegment)Xmalloc(sizeof(ExtdSegmentRec));
- if (ret == NULL)
- return NULL;
- ret->name = strdup(value[0]);
- if (ret->name == NULL) {
- Xfree (ret);
- return NULL;
- }
- cset_name = (char*) Xmalloc (strlen(ret->name) + 1);
- if (cset_name == NULL) {
- Xfree (ret->name);
- Xfree (ret);
- return NULL;
- }
- if (strchr(value[0],':')) {
- ptr = strchr(ret->name,':');
- *ptr = '\0';
- ptr++;
- if (!_XlcNCompareISOLatin1(ptr, "GL", 2)) {
- ret->side = XlcGL;
- sprintf(cset_name,"%s:%s",ret->name,"GL");
- } else {
- ret->side = XlcGR;
- sprintf(cset_name,"%s:%s",ret->name,"GR");
- }
- } else {
- ret->side = XlcGLGR;
- strcpy(cset_name,ret->name);
- }
- ret->area = (FontScope)Xmalloc((num - 1)*sizeof(FontScopeRec));
- if (ret->area == NULL) {
- Xfree (cset_name);
- Xfree (ret->name);
- Xfree (ret);
- return NULL;
- }
- ret->area_num = num - 1;
- scope = ret->area ;
- for (i = 1; i < num; i++) {
- sscanf(value[i],"\\x%lx,\\x%lx",
- &scope[i-1].start, &scope[i-1].end);
- }
- ret->charset = srch_charset_define(cset_name,&new);
- Xfree (cset_name);
-
- return ret;
-}
-/* For VW/UDC end */
-
-static Bool
-load_generic(
- XLCd lcd)
-{
- XLCdGenericPart *gen = XLC_GENERIC_PART(lcd);
- char **value;
- int num;
- unsigned long l;
- int i;
- int M,ii;
- XlcCharSet charset;
-
- gen->codeset_num = 0;
-
- /***** wc_encoding_mask *****/
- _XlcGetResource(lcd, "XLC_XLOCALE", "wc_encoding_mask", &value, &num);
- if (num > 0) {
- if (string_to_ulong(value[0], &l) == False)
- goto err;
- gen->wc_encode_mask = l;
- }
- /***** wc_shift_bits *****/
- _XlcGetResource(lcd, "XLC_XLOCALE", "wc_shift_bits", &value, &num);
- if (num > 0)
- gen->wc_shift_bits = atoi(value[0]);
- if (gen->wc_shift_bits < 1)
- gen->wc_shift_bits = 8;
- /***** use_stdc_env *****/
- _XlcGetResource(lcd, "XLC_XLOCALE", "use_stdc_env", &value, &num);
- if (num > 0 && !_XlcCompareISOLatin1(value[0], "True"))
- gen->use_stdc_env = True;
- else
- gen->use_stdc_env = False;
- /***** force_convert_to_mb *****/
- _XlcGetResource(lcd, "XLC_XLOCALE", "force_convert_to_mb", &value, &num);
- if (num > 0 && !_XlcCompareISOLatin1(value[0], "True"))
- gen->force_convert_to_mb = True;
- else
- gen->force_convert_to_mb = False;
-
- for (i = 0; ; i++) {
- CodeSetRec *codeset = NULL;
- char cs[16];
- char name[BUFSIZ];
-
- sprintf(cs, "cs%d", i);
-
- /***** codeset.side *****/
- sprintf(name, "%s.%s", cs , "side");
- _XlcGetResource(lcd, "XLC_XLOCALE", name, &value, &num);
- if (num > 0) {
- char *tmp;
-
- if (codeset == NULL && (codeset = add_codeset(gen)) == NULL)
- goto err;
-
- /* 3.4.1 side */
- if (!_XlcNCompareISOLatin1(value[0], "none", 4)) {
- codeset->side = XlcNONE;
- } else if (!_XlcNCompareISOLatin1(value[0], "GL", 2)) {
- codeset->side = XlcGL;
- } else {
- codeset->side = XlcGR;
- }
-
- tmp = strrchr(value[0], ':');
- if (tmp != NULL && !_XlcCompareISOLatin1(tmp + 1, "Default")) {
- if (codeset->side == XlcGR)
- gen->initial_state_GR = codeset;
- else
- gen->initial_state_GL = codeset;
- }
- }
-
- /***** codeset.length *****/
- sprintf(name, "%s.%s", cs , "length");
- _XlcGetResource(lcd, "XLC_XLOCALE", name, &value, &num);
- if (num > 0) {
- if (codeset == NULL && (codeset = add_codeset(gen)) == NULL)
- goto err;
- codeset->length = atoi(value[0]);
- if (codeset->length < 1)
- codeset->length = 1;
- }
-
- /***** codeset.mb_encoding *****/
- sprintf(name, "%s.%s", cs, "mb_encoding");
- _XlcGetResource(lcd, "XLC_XLOCALE", name, &value, &num);
- if (num > 0) {
- static struct {
- const char *str;
- EncodingType type;
- } shifts[] = {
- {"<SS>", E_SS},
- {"<LSL>", E_LSL},
- {"<LSR>", E_LSR},
- {0}
- };
- int j;
-
- if (codeset == NULL && (codeset = add_codeset(gen)) == NULL)
- goto err;
- for ( ; num-- > 0; value++) {
- char encoding[256];
- char *tmp = *value;
- EncodingType type = E_SS; /* for BC */
- for (j = 0; shifts[j].str; j++) {
- if (!_XlcNCompareISOLatin1(tmp, shifts[j].str,
- strlen(shifts[j].str))) {
- type = shifts[j].type;
- tmp += strlen(shifts[j].str);
- break;
- }
- }
- if (strlen (tmp) > sizeof encoding ||
- string_to_encoding(tmp, encoding) == False)
- goto err;
- add_parse_list(gen, type, encoding, codeset);
- }
- }
-
- /***** codeset.wc_encoding *****/
- sprintf(name, "%s.%s", cs, "wc_encoding");
- _XlcGetResource(lcd, "XLC_XLOCALE", name, &value, &num);
- if (num > 0) {
- if (codeset == NULL && (codeset = add_codeset(gen)) == NULL)
- goto err;
- if (string_to_ulong(value[0], &l) == False)
- goto err;
- codeset->wc_encoding = l;
- }
-
- /***** codeset.ct_encoding *****/
- sprintf(name, "%s.%s", cs, "ct_encoding");
- _XlcGetResource(lcd, "XLC_XLOCALE", name, &value, &num);
- if (num > 0) {
- char *encoding;
-
- if (codeset == NULL && (codeset = add_codeset(gen)) == NULL)
- goto err;
- for ( ; num-- > 0; value++) {
- if (strlen (*value) > sizeof name)
- goto err;
- string_to_encoding(*value, name);
- charset = NULL;
- if ((encoding = strchr(name, ':')) &&
- (encoding = strchr(encoding + 1, ':'))) {
- *encoding++ = '\0';
- charset = _XlcAddCT(name, encoding);
- }
- if (charset == NULL) {
- charset = _XlcGetCharSet(name);
- if (charset == NULL &&
- (charset = _XlcCreateDefaultCharSet(name, ""))) {
- charset->side = codeset->side;
- charset->char_size = codeset->length;
- _XlcAddCharSet(charset);
- }
- }
- if (charset) {
- if (add_charset(codeset, charset) == False)
- goto err;
- }
- }
- }
-
- if (codeset == NULL)
- break;
- codeset->cs_num = i;
- /* For VW/UDC */
- /***** 3.4.2 byteM (1 <= M <= length)*****/
- for (M=1; M-1 < codeset->length; M++) {
- unsigned long start,end;
- ByteInfo tmpb;
-
- sprintf(name,"%s.%s%d",cs,"byte",M);
- _XlcGetResource(lcd, "XLC_XLOCALE", name, &value, &num);
-
- if (M == 1) {
- if (num < 1) {
- codeset->byteM = NULL;
- break ;
- }
- codeset->byteM =
- (ByteInfoListRec *)Xmalloc(
- (codeset->length)*sizeof(ByteInfoListRec));
- if (codeset->byteM == NULL) {
- goto err;
- }
- }
-
- if (num > 0) {
- _XlcDbg_printValue(name,value,num);
- (codeset->byteM)[M-1].M = M;
- (codeset->byteM)[M-1].byteinfo_num = num;
- (codeset->byteM)[M-1].byteinfo =
- (ByteInfo)Xmalloc( num * sizeof(ByteInfoRec));
- for (ii = 0 ; ii < num ; ii++) {
- tmpb = (codeset->byteM)[M-1].byteinfo ;
- /* default 0x00 - 0xff */
- sscanf(value[ii],"\\x%lx,\\x%lx",&start,&end);
- tmpb[ii].start = (unsigned char)start;
- tmpb[ii].end = (unsigned char)end;
- }
- }
- /* .... */
- }
-
-
- /***** codeset.mb_conversion *****/
- sprintf(name, "%s.%s", cs, "mb_conversion");
- _XlcGetResource(lcd, "XLC_XLOCALE", name, &value, &num);
- if (num > 0) {
- _XlcDbg_printValue(name,value,num);
- codeset->mbconv = Xmalloc(sizeof(ConversionRec));
- codeset->mbconv->convlist =
- _XlcParse_scopemaps(value[0],&(codeset->mbconv->conv_num));
- dmpscope("mb_conv",codeset->mbconv->convlist,
- codeset->mbconv->conv_num);
- /* [\x%x,\x%x]->\x%x,... */
- }
- /***** codeset.ct_conversion *****/
- sprintf(name, "%s.%s", cs, "ct_conversion");
- _XlcGetResource(lcd, "XLC_XLOCALE", name, &value, &num);
- if (num > 0) {
- _XlcDbg_printValue(name,value,num);
- codeset->ctconv = Xmalloc(sizeof(ConversionRec));
- codeset->ctconv->convlist =
- _XlcParse_scopemaps(value[0],&(codeset->ctconv->conv_num));
- dmpscope("ctconv",codeset->ctconv->convlist,
- codeset->ctconv->conv_num);
- /* [\x%x,\x%x]->\x%x,... */
- }
- /***** codeset.ct_conversion_file *****/
- sprintf(name, "%s.%s", cs, "ct_conversion_file");
- _XlcGetResource(lcd, "XLC_XLOCALE", name, &value, &num);
- if (num > 0) {
- _XlcDbg_printValue(name,value,num);
- /* [\x%x,\x%x]->\x%x,... */
- }
- /***** codeset.ct_extended_segment *****/
- sprintf(name, "%s.%s", cs, "ct_extended_segment");
- _XlcGetResource(lcd, "XLC_XLOCALE", name, &value, &num);
- if (num > 0) {
- _XlcDbg_printValue(name,value,num);
- codeset->ctextseg = create_ctextseg(value,num);
- /* [\x%x,\x%x]->\x%x,... */
- }
- /* For VW/UDC end */
-
- }
-
- read_charset_define(lcd,gen); /* For VW/UDC */
- read_segmentconversion(lcd,gen); /* For VW/UDC */
-
- if (gen->initial_state_GL == NULL) {
- CodeSetRec *codeset;
- for (i = 0; i < gen->codeset_num; i++) {
- codeset = gen->codeset_list[i];
- if (codeset->side == XlcGL)
- gen->initial_state_GL = codeset;
- }
- }
-
- if (gen->initial_state_GR == NULL) {
- CodeSetRec *codeset;
- for (i = 0; i < gen->codeset_num; i++) {
- codeset = gen->codeset_list[i];
- if (codeset->side == XlcGR)
- gen->initial_state_GR = codeset;
- }
- }
-
- for (i = 0; i < gen->codeset_num; i++) {
- CodeSetRec *codeset = gen->codeset_list[i];
- for (ii = 0; ii < codeset->num_charsets; ii++) {
- charset = codeset->charset_list[ii];
- if (! strcmp(charset->encoding_name, "ISO8859-1"))
- charset->string_encoding = True;
- if ( charset->string_encoding )
- codeset->string_encoding = True;
- }
- }
- return True;
-
-err:
- free_charset(lcd);
-
- return False;
-}
-
-#ifdef USE_DYNAMIC_LC
-/* override the open_om and open_im methods which were set by
- super_class's initialize method() */
-
-static Bool
-initialize_core(
- XLCd lcd)
-{
- _XInitDynamicOM(lcd);
-
- _XInitDynamicIM(lcd);
-
- return True;
-}
-#endif
-
-static Bool
-initialize(XLCd lcd)
-{
- XLCdPublicMethods superclass = (XLCdPublicMethods) _XlcPublicMethods;
-
- XLC_PUBLIC_METHODS(lcd)->superclass = superclass;
-
- if (superclass->pub.initialize) {
- if ((*superclass->pub.initialize)(lcd) == False)
- return False;
- }
-
-#ifdef USE_DYNAMIC_LC
- if (initialize_core(lcd) == False)
- return False;
-#endif
-
- if (load_generic(lcd) == False)
- return False;
-
- return True;
-}
-
-/* VW/UDC start 95.01.08 */
-static void
-freeByteM(
- CodeSet codeset)
-{
- int i;
- ByteInfoList blst;
- if (codeset->byteM == NULL) {
- return ;
- }
- blst = codeset->byteM;
- for (i = 0; i < codeset->length; i++) {
- if (blst[i].byteinfo) {
- Xfree(blst[i].byteinfo);
- blst[i].byteinfo = NULL;
- }
- }
- Xfree(codeset->byteM);
- codeset->byteM = NULL;
-}
-
-static void
-freeConversion(
- CodeSet codeset)
-{
- Conversion mbconv,ctconv;
- if (codeset->mbconv) {
- mbconv = codeset->mbconv;
- /* ... */
- if (mbconv->convlist) {
- Xfree(mbconv->convlist);
- mbconv->convlist = NULL;
- }
- Xfree(mbconv);
- codeset->mbconv = NULL;
- }
- if (codeset->ctconv) {
- ctconv = codeset->ctconv;
- /* ... */
- if (ctconv->convlist) {
- Xfree(ctconv->convlist);
- ctconv->convlist = NULL;
- }
- Xfree(ctconv);
- codeset->ctconv = NULL;
- }
-}
-
-static void
-freeExtdSegment(
- CodeSet codeset)
-{
- ExtdSegment ctextseg;
- if (codeset->ctextseg == NULL) {
- return;
- }
- ctextseg = codeset->ctextseg;
- if (ctextseg->name) {
- Xfree(ctextseg->name);
- ctextseg->name = NULL;
- }
- if (ctextseg->area) {
- Xfree(ctextseg->area);
- ctextseg->area = NULL;
- }
- Xfree(codeset->ctextseg);
- codeset->ctextseg = NULL;
-}
-
-static void
-freeParseInfo(
- CodeSet codeset)
-{
- ParseInfo parse_info;
- if (codeset->parse_info == NULL) {
- return;
- }
- parse_info = codeset->parse_info;
- if (parse_info->encoding) {
- Xfree(parse_info->encoding);
- parse_info->encoding = NULL;
- }
- Xfree(codeset->parse_info);
- codeset->parse_info = NULL;
-}
-
-static void
-destroy_CodeSetList(
- XLCdGenericPart *gen)
-{
- CodeSet *codeset = gen->codeset_list;
- int i;
- if (gen->codeset_num == 0) {
- return;
- }
- for (i=0;i<gen->codeset_num;i++) {
- freeByteM(codeset[i]);
- freeConversion(codeset[i]);
- freeExtdSegment(codeset[i]);
- freeParseInfo(codeset[i]);
- if (codeset[i]->charset_list) {
- Xfree(codeset[i]->charset_list);
- codeset[i]->charset_list = NULL;
- }
- Xfree(codeset[i]); codeset[i]=NULL;
- }
- Xfree(codeset); gen->codeset_list = NULL;
-}
-
-static void
-destroy_SegConv(
- XLCdGenericPart *gen)
-{
- SegConv seg = gen->segment_conv;
- int i;
- if (gen->segment_conv_num == 0) {
- return;
- }
- for (i=0;i<gen->segment_conv_num;i++) {
- if (seg[i].source_encoding) {
- Xfree(seg[i].source_encoding);
- seg[i].source_encoding = NULL;
- }
- if (seg[i].destination_encoding) {
- Xfree(seg[i].destination_encoding);
- seg[i].destination_encoding = NULL;
- }
- if (seg[i].conv) {
- Xfree(seg[i].conv); seg[i].conv = NULL;
- }
- }
- Xfree(seg); gen->segment_conv = NULL;
-}
-
-static void
-destroy_gen(
- XLCd lcd)
-{
- XLCdGenericPart *gen = XLC_GENERIC_PART(lcd);
- destroy_SegConv(gen);
- destroy_CodeSetList(gen);
- if (gen->mb_parse_table) {
- Xfree(gen->mb_parse_table);
- gen->mb_parse_table = NULL;
- }
- if (gen->mb_parse_list) {
- Xfree(gen->mb_parse_list);
- gen->mb_parse_list = NULL;
- }
-}
-/* VW/UDC end 95.01.08 */
-
-static void
-destroy(
- XLCd lcd)
-{
- XLCdPublicMethods superclass = XLC_PUBLIC_METHODS(lcd)->superclass;
-
- destroy_gen(lcd); /* ADD 1996.01.08 */
- if (superclass && superclass->pub.destroy)
- (*superclass->pub.destroy)(lcd);
-}
+/* + * Copyright 1992, 1993 by TOSHIBA Corp. + * + * 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 TOSHIBA not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. TOSHIBA make no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * TOSHIBA DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING + * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL + * TOSHIBA 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 TORTIOUS ACTION, + * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + * + * Author: Katsuhisa Yano TOSHIBA Corp. + * mopi@osa.ilab.toshiba.co.jp + */ +/* + * (c) Copyright 1995 FUJITSU LIMITED + * This is source code modified by FUJITSU LIMITED under the Joint + * Development Agreement for the CDE/Motif PST. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include <unistd.h> +#include "Xlibint.h" +#include "XlcGeneric.h" + +static XLCd create (const char *name, XLCdMethods methods); +static Bool initialize (XLCd lcd); +static void destroy (XLCd lcd); + +static XLCdPublicMethodsRec genericMethods = { + { NULL }, /* use default methods */ + { + NULL, + create, + initialize, + destroy, + NULL + } +}; + +XLCdMethods _XlcGenericMethods = (XLCdMethods) &genericMethods; + +static XLCd +create( + const char *name, + XLCdMethods methods) +{ + XLCd lcd; + XLCdPublicMethods new; + + lcd = Xcalloc(1, sizeof(XLCdRec)); + if (lcd == NULL) + return (XLCd) NULL; + + lcd->core = Xcalloc(1, sizeof(XLCdGenericRec)); + if (lcd->core == NULL) + goto err; + + new = (XLCdPublicMethods) Xmalloc(sizeof(XLCdPublicMethodsRec)); + if (new == NULL) + goto err; + memcpy(new,methods,sizeof(XLCdPublicMethodsRec)); + lcd->methods = (XLCdMethods) new; + + return lcd; + +err: + Xfree(lcd); + return (XLCd) NULL; +} + +static Bool +string_to_encoding( + const char *str, + char *encoding) +{ + char *next; + long value; + int base; + + while (*str) { + if (*str == '\\') { + switch (*(str + 1)) { + case 'x': + case 'X': + base = 16; + break; + default: + base = 8; + break; + } + value = strtol(str + 2, &next, base); + if (str + 2 != next) { + *((unsigned char *) encoding++) = (unsigned char) value; + str = next; + continue; + } + } + *encoding++ = *str++; + } + + *encoding = '\0'; + + return True; +} + +static Bool +string_to_ulong( + const char *str, + unsigned long *value) +{ + const char *tmp1 = str; + int base; + + if (*tmp1++ != '\\') { + tmp1--; + base = 10; + } else { + switch (*tmp1++) { + case 'x': + base = 16; + break; + case 'o': + base = 8; + break; + case 'd': + base = 10; + break; + default: + return(False); + } + } + *value = (unsigned long) strtol(tmp1, NULL, base); + return(True); +} + + +static Bool +add_charset( + CodeSet codeset, + XlcCharSet charset) +{ + XlcCharSet *new_list; + int num; + + if ((num = codeset->num_charsets)) + new_list = (XlcCharSet *) Xrealloc(codeset->charset_list, + (num + 1) * sizeof(XlcCharSet)); + else + new_list = (XlcCharSet *) Xmalloc(sizeof(XlcCharSet)); + + if (new_list == NULL) + return False; + + new_list[num] = charset; + codeset->charset_list = new_list; + codeset->num_charsets = num + 1; + + return True; +} + +static CodeSet +add_codeset( + XLCdGenericPart *gen) +{ + CodeSet new, *new_list; + int num; + + new = Xcalloc(1, sizeof(CodeSetRec)); + if (new == NULL) + return NULL; + + if ((num = gen->codeset_num)) + new_list = (CodeSet *) Xrealloc(gen->codeset_list, + (num + 1) * sizeof(CodeSet)); + else + new_list = (CodeSet *) Xmalloc(sizeof(CodeSet)); + + if (new_list == NULL) + goto err; + + new_list[num] = new; + gen->codeset_list = new_list; + gen->codeset_num = num + 1; + + return new; + +err: + Xfree(new); + + return NULL; +} + +static Bool +add_parse_list( + XLCdGenericPart *gen, + EncodingType type, + const char *encoding, + CodeSet codeset) +{ + ParseInfo new, *new_list; + char *str; + unsigned char ch; + int num; + + str = strdup(encoding); + if (str == NULL) + return False; + + new = Xcalloc(1, sizeof(ParseInfoRec)); + if (new == NULL) + goto err; + + if (gen->mb_parse_table == NULL) { + gen->mb_parse_table = Xcalloc(1, 256); /* 2^8 */ + if (gen->mb_parse_table == NULL) + goto err; + } + + if ((num = gen->mb_parse_list_num)) + new_list = (ParseInfo *) Xrealloc(gen->mb_parse_list, + (num + 2) * sizeof(ParseInfo)); + else { + new_list = (ParseInfo *) Xmalloc(2 * sizeof(ParseInfo)); + } + + if (new_list == NULL) + goto err; + + new_list[num] = new; + new_list[num + 1] = NULL; + gen->mb_parse_list = new_list; + gen->mb_parse_list_num = num + 1; + + ch = (unsigned char) *str; + if (gen->mb_parse_table[ch] == 0) + gen->mb_parse_table[ch] = num + 1; + + new->type = type; + new->encoding = str; + new->codeset = codeset; + + if (codeset->parse_info == NULL) + codeset->parse_info = new; + + return True; + +err: + Xfree(str); + if (new) + Xfree(new); + + return False; +} + +static void +free_charset( + XLCd lcd) +{ + XLCdGenericPart *gen = XLC_GENERIC_PART(lcd); + ParseInfo *parse_info; + int num; + + if (gen->mb_parse_table) + Xfree(gen->mb_parse_table); + if ((num = gen->mb_parse_list_num) > 0) { + for (parse_info = gen->mb_parse_list; num-- > 0; parse_info++) { + if ((*parse_info)->encoding) + Xfree((*parse_info)->encoding); + Xfree(*parse_info); + } + Xfree(gen->mb_parse_list); + } + + if ((num = gen->codeset_num) > 0) + Xfree(gen->codeset_list); +} + +/* For VW/UDC */ + +#define FORWARD (unsigned long)'+' +#define BACKWARD (unsigned long)'-' + +static const char * +getscope( + const char *str, + FontScope scp) +{ + unsigned long start = 0; + unsigned long end = 0; + unsigned long dest = 0; + unsigned long shift = 0; + unsigned long direction = 0; + sscanf(str,"[\\x%lx,\\x%lx]->\\x%lx", &start, &end, &dest); + if (dest) { + if (dest >= start) { + shift = dest - start; + direction = FORWARD ; + } else { + shift = start - dest; + direction = BACKWARD; + } + } + scp->start = start ; + scp->end = end ; + scp->shift = shift ; + scp->shift_direction + = direction ; + /* .......... */ + while (*str) { + if (*str == ',' && *(str+1) == '[') + break; + str++; + } + return str+1; +} + +static int +count_scopemap( + const char *str) +{ + const char *ptr; + int num=0; + for (ptr=str; *ptr; ptr++) { + if (*ptr == ']') { + num++; + } + } + return num; +} + +FontScope +_XlcParse_scopemaps( + const char *str, + int *size) +{ + int num=0,i; + FontScope scope,sc_ptr; + const char *str_sc; + + num = count_scopemap(str); + scope = (FontScope) Xmalloc(num * sizeof(FontScopeRec)); + if (scope == NULL) + return NULL; + + for (i=0, str_sc=str, sc_ptr=scope; i < num; i++, sc_ptr++) { + str_sc = getscope(str_sc, sc_ptr); + } + *size = num; + return scope; +} + +void +_XlcDbg_printValue( + const char *str, + char **value, + int num) +{ +/* + int i; + for (i = 0; i < num; i++) + fprintf(stderr, "%s value[%d] = %s\n", str, i, value[i]); +*/ +} + +static void +dmpscope( + const char* name, + FontScope sc, + int num) +{ +/* + int i; + fprintf(stderr, "dmpscope %s\n", name); + for (i=0; i<num; i++) + fprintf(stderr,"%x %x %x %x \n", + sc[i].start, + sc[i].end, + sc[i].shift, + sc[i].shift_direction); + fprintf(stderr, "dmpscope end\n"); +*/ +} + +static XlcCharSet +srch_charset_define( + const char *name, + int *new) +{ + XlcCharSet charset; + + *new = 0; + charset = _XlcGetCharSet(name); + if (charset == NULL && + (charset = _XlcCreateDefaultCharSet(name, ""))) { + _XlcAddCharSet(charset); + *new = 1; + charset->source = CSsrcXLC; + } + return charset; +} + +static void +read_charset_define( + XLCd lcd, + XLCdGenericPart *gen) +{ + int i; + char csd[16], cset_name[256]; + char name[BUFSIZ]; + XlcCharSet charsetd; + char **value; + int num, new = 0; + XlcSide side = XlcUnknown; + char *tmp; + + for (i=0; ; i++) { /* loop start */ + charsetd = 0; + sprintf(csd, "csd%d", i); + + /* charset_name */ + sprintf(name, "%s.%s", csd, "charset_name"); + _XlcGetResource(lcd, "XLC_CHARSET_DEFINE", name, &value, &num); + _XlcDbg_printValue(name,value,num); + if (num > 0) { + /* hackers will get truncated -- C'est la vie */ + strncpy(cset_name,value[0], sizeof cset_name - 1); + cset_name[(sizeof cset_name) - 1] = '\0'; + sprintf(name, "%s.%s", csd , "side"); + _XlcGetResource(lcd, "XLC_CHARSET_DEFINE", name, &value, &num); + if (num > 0) { + _XlcDbg_printValue(name,value,num); + if (!_XlcNCompareISOLatin1(value[0], "none", 4)) { + side = XlcGLGR; + } else if (!_XlcNCompareISOLatin1(value[0], "GL", 2)) { + side = XlcGL; + strcat(cset_name,":GL"); + } else { + side = XlcGR; + strcat(cset_name,":GR"); + } + if (charsetd == NULL && + (charsetd = srch_charset_define(cset_name,&new)) == NULL) + return; + } + } else { + if (i == 0) + continue; + else + break; + } + if (new) { + tmp = strdup(cset_name); + if (tmp == NULL) + return; + charsetd->name = tmp; + } + /* side */ + charsetd->side = side ; + /* length */ + sprintf(name, "%s.%s", csd, "length"); + _XlcGetResource(lcd, "XLC_CHARSET_DEFINE", name, &value, &num); + if (num > 0) { + _XlcDbg_printValue(name,value,num); + charsetd->char_size = atoi(value[0]); + } + /* gc_number */ + sprintf(name, "%s.%s", csd, "gc_number"); + _XlcGetResource(lcd, "XLC_CHARSET_DEFINE", name, &value, &num); + if (num > 0) { + _XlcDbg_printValue(name,value,num); + charsetd->set_size = atoi(value[0]); + } + /* string_encoding */ + sprintf(name, "%s.%s", csd, "string_encoding"); + _XlcGetResource(lcd, "XLC_CHARSET_DEFINE", name, &value, &num); + if (num > 0) { + _XlcDbg_printValue(name,value,num); + if (!strcmp("False",value[0])) { + charsetd->string_encoding = False; + } else { + charsetd->string_encoding = True; + } + } + /* sequence */ + sprintf(name, "%s.%s", csd, "sequence"); + _XlcGetResource(lcd, "XLC_CHARSET_DEFINE", name, &value, &num); + if (num > 0) { + _XlcDbg_printValue(name,value,num); +/* + if (charsetd->ct_sequence) { + Xfree(charsetd->ct_sequence); + } +*/ + tmp = (char *)Xmalloc(strlen(value[0])+1); + if (tmp == NULL) + return; + charsetd->ct_sequence = tmp; + string_to_encoding(value[0],tmp); + } + /* encoding_name */ + sprintf(name, "%s.%s", csd, "encoding_name"); + _XlcGetResource(lcd, "XLC_CHARSET_DEFINE", name, &value, &num); + if (num > 0) { + _XlcDbg_printValue(name,value,num); +/* + if (charsetd->encoding_name) { + Xfree(charsetd->encoding_name); + } +*/ + tmp = strdup(value[0]); + charsetd->encoding_name = tmp; + charsetd->xrm_encoding_name = XrmStringToQuark(tmp); + } + _XlcAddCT(charsetd->name, charsetd->ct_sequence); + } +} + +static SegConv +add_conversion( + XLCdGenericPart *gen) +{ + SegConv new_list; + int num; + + if ((num = gen->segment_conv_num) > 0) { + new_list = (SegConv) Xrealloc(gen->segment_conv, + (num + 1) * sizeof(SegConvRec)); + } else { + new_list = (SegConv) Xmalloc(sizeof(SegConvRec)); + } + + if (new_list == NULL) + return NULL; + + gen->segment_conv = new_list; + gen->segment_conv_num = num + 1; + + return &new_list[num]; + +} + +static void +read_segmentconversion( + XLCd lcd, + XLCdGenericPart *gen) +{ + int i; + char conv[16]; + char name[BUFSIZ]; + char **value; + int num,new; + SegConv conversion; + for (i=0 ; ; i++) { /* loop start */ + conversion = 0; + sprintf(conv, "conv%d", i); + + /* length */ + sprintf(name, "%s.%s", conv, "length"); + _XlcGetResource(lcd, "XLC_SEGMENTCONVERSION", name, &value, &num); + if (num > 0) { + if (conversion == NULL && + (conversion = add_conversion(gen)) == NULL) { + return; + } + _XlcDbg_printValue(name,value,num); + } else { + if (i == 0) + continue; + else + break; + } + conversion->length = atoi(value[0]); + + /* source_encoding */ + sprintf(name, "%s.%s", conv, "source_encoding"); + _XlcGetResource(lcd, "XLC_SEGMENTCONVERSION", name, &value, &num); + if (num > 0) { + char *tmp; + _XlcDbg_printValue(name,value,num); + tmp = strdup(value[0]); + if (tmp == NULL) + return; + conversion->source_encoding = tmp; + conversion->source = srch_charset_define(tmp,&new); + } + /* destination_encoding */ + sprintf(name, "%s.%s", conv, "destination_encoding"); + _XlcGetResource(lcd, "XLC_SEGMENTCONVERSION", name, &value, &num); + if (num > 0) { + char *tmp; + _XlcDbg_printValue(name,value,num); + tmp = strdup(value[0]); + if (tmp == NULL) + return; + conversion->destination_encoding = tmp; + conversion->dest = srch_charset_define(tmp,&new); + } + /* range */ + sprintf(name, "%s.%s", conv, "range"); + _XlcGetResource(lcd, "XLC_SEGMENTCONVERSION", name, &value, &num); + if (num > 0) { + _XlcDbg_printValue(name,value,num); + sscanf(value[0],"\\x%lx,\\x%lx", + &(conversion->range.start), &(conversion->range.end)); + } + /* conversion */ + sprintf(name, "%s.%s", conv, "conversion"); + _XlcGetResource(lcd, "XLC_SEGMENTCONVERSION", name, &value, &num); + if (num > 0) { + _XlcDbg_printValue(name,value,num); + conversion->conv = + _XlcParse_scopemaps(value[0],&conversion->conv_num); + } + } /* loop end */ +} + +static ExtdSegment +create_ctextseg( + char **value, + int num) +{ + ExtdSegment ret; + char* ptr; + char* cset_name = NULL; + int i,new; + FontScope scope; + ret = (ExtdSegment)Xmalloc(sizeof(ExtdSegmentRec)); + if (ret == NULL) + return NULL; + ret->name = strdup(value[0]); + if (ret->name == NULL) { + Xfree (ret); + return NULL; + } + cset_name = (char*) Xmalloc (strlen(ret->name) + 1); + if (cset_name == NULL) { + Xfree (ret->name); + Xfree (ret); + return NULL; + } + if (strchr(value[0],':')) { + ptr = strchr(ret->name,':'); + *ptr = '\0'; + ptr++; + if (!_XlcNCompareISOLatin1(ptr, "GL", 2)) { + ret->side = XlcGL; + sprintf(cset_name,"%s:%s",ret->name,"GL"); + } else { + ret->side = XlcGR; + sprintf(cset_name,"%s:%s",ret->name,"GR"); + } + } else { + ret->side = XlcGLGR; + strcpy(cset_name,ret->name); + } + ret->area = (FontScope)Xmalloc((num - 1)*sizeof(FontScopeRec)); + if (ret->area == NULL) { + Xfree (cset_name); + Xfree (ret->name); + Xfree (ret); + return NULL; + } + ret->area_num = num - 1; + scope = ret->area ; + for (i = 1; i < num; i++) { + sscanf(value[i],"\\x%lx,\\x%lx", + &scope[i-1].start, &scope[i-1].end); + } + ret->charset = srch_charset_define(cset_name,&new); + Xfree (cset_name); + + return ret; +} +/* For VW/UDC end */ + +static Bool +load_generic( + XLCd lcd) +{ + XLCdGenericPart *gen = XLC_GENERIC_PART(lcd); + char **value; + int num; + unsigned long l; + int i; + int M,ii; + XlcCharSet charset; + + gen->codeset_num = 0; + + /***** wc_encoding_mask *****/ + _XlcGetResource(lcd, "XLC_XLOCALE", "wc_encoding_mask", &value, &num); + if (num > 0) { + if (string_to_ulong(value[0], &l) == False) + goto err; + gen->wc_encode_mask = l; + } + /***** wc_shift_bits *****/ + _XlcGetResource(lcd, "XLC_XLOCALE", "wc_shift_bits", &value, &num); + if (num > 0) + gen->wc_shift_bits = atoi(value[0]); + if (gen->wc_shift_bits < 1) + gen->wc_shift_bits = 8; + /***** use_stdc_env *****/ + _XlcGetResource(lcd, "XLC_XLOCALE", "use_stdc_env", &value, &num); + if (num > 0 && !_XlcCompareISOLatin1(value[0], "True")) + gen->use_stdc_env = True; + else + gen->use_stdc_env = False; + /***** force_convert_to_mb *****/ + _XlcGetResource(lcd, "XLC_XLOCALE", "force_convert_to_mb", &value, &num); + if (num > 0 && !_XlcCompareISOLatin1(value[0], "True")) + gen->force_convert_to_mb = True; + else + gen->force_convert_to_mb = False; + + for (i = 0; ; i++) { + CodeSetRec *codeset = NULL; + char cs[16]; + char name[BUFSIZ]; + + sprintf(cs, "cs%d", i); + + /***** codeset.side *****/ + sprintf(name, "%s.%s", cs , "side"); + _XlcGetResource(lcd, "XLC_XLOCALE", name, &value, &num); + if (num > 0) { + char *tmp; + + if (codeset == NULL && (codeset = add_codeset(gen)) == NULL) + goto err; + + /* 3.4.1 side */ + if (!_XlcNCompareISOLatin1(value[0], "none", 4)) { + codeset->side = XlcNONE; + } else if (!_XlcNCompareISOLatin1(value[0], "GL", 2)) { + codeset->side = XlcGL; + } else { + codeset->side = XlcGR; + } + + tmp = strrchr(value[0], ':'); + if (tmp != NULL && !_XlcCompareISOLatin1(tmp + 1, "Default")) { + if (codeset->side == XlcGR) + gen->initial_state_GR = codeset; + else + gen->initial_state_GL = codeset; + } + } + + /***** codeset.length *****/ + sprintf(name, "%s.%s", cs , "length"); + _XlcGetResource(lcd, "XLC_XLOCALE", name, &value, &num); + if (num > 0) { + if (codeset == NULL && (codeset = add_codeset(gen)) == NULL) + goto err; + codeset->length = atoi(value[0]); + if (codeset->length < 1) + codeset->length = 1; + } + + /***** codeset.mb_encoding *****/ + sprintf(name, "%s.%s", cs, "mb_encoding"); + _XlcGetResource(lcd, "XLC_XLOCALE", name, &value, &num); + if (num > 0) { + static struct { + const char *str; + EncodingType type; + } shifts[] = { + {"<SS>", E_SS}, + {"<LSL>", E_LSL}, + {"<LSR>", E_LSR}, + {0} + }; + int j; + + if (codeset == NULL && (codeset = add_codeset(gen)) == NULL) + goto err; + for ( ; num-- > 0; value++) { + char encoding[256]; + char *tmp = *value; + EncodingType type = E_SS; /* for BC */ + for (j = 0; shifts[j].str; j++) { + if (!_XlcNCompareISOLatin1(tmp, shifts[j].str, + strlen(shifts[j].str))) { + type = shifts[j].type; + tmp += strlen(shifts[j].str); + break; + } + } + if (strlen (tmp) > sizeof encoding || + string_to_encoding(tmp, encoding) == False) + goto err; + add_parse_list(gen, type, encoding, codeset); + } + } + + /***** codeset.wc_encoding *****/ + sprintf(name, "%s.%s", cs, "wc_encoding"); + _XlcGetResource(lcd, "XLC_XLOCALE", name, &value, &num); + if (num > 0) { + if (codeset == NULL && (codeset = add_codeset(gen)) == NULL) + goto err; + if (string_to_ulong(value[0], &l) == False) + goto err; + codeset->wc_encoding = l; + } + + /***** codeset.ct_encoding *****/ + sprintf(name, "%s.%s", cs, "ct_encoding"); + _XlcGetResource(lcd, "XLC_XLOCALE", name, &value, &num); + if (num > 0) { + char *encoding; + + if (codeset == NULL && (codeset = add_codeset(gen)) == NULL) + goto err; + for ( ; num-- > 0; value++) { + if (strlen (*value) > sizeof name) + goto err; + string_to_encoding(*value, name); + charset = NULL; + if ((encoding = strchr(name, ':')) && + (encoding = strchr(encoding + 1, ':'))) { + *encoding++ = '\0'; + charset = _XlcAddCT(name, encoding); + } + if (charset == NULL) { + charset = _XlcGetCharSet(name); + if (charset == NULL && + (charset = _XlcCreateDefaultCharSet(name, ""))) { + charset->side = codeset->side; + charset->char_size = codeset->length; + _XlcAddCharSet(charset); + } + } + if (charset) { + if (add_charset(codeset, charset) == False) + goto err; + } + } + } + + if (codeset == NULL) + break; + codeset->cs_num = i; + /* For VW/UDC */ + /***** 3.4.2 byteM (1 <= M <= length)*****/ + for (M=1; M-1 < codeset->length; M++) { + unsigned long start,end; + ByteInfo tmpb; + + sprintf(name,"%s.%s%d",cs,"byte",M); + _XlcGetResource(lcd, "XLC_XLOCALE", name, &value, &num); + + if (M == 1) { + if (num < 1) { + codeset->byteM = NULL; + break ; + } + codeset->byteM = + (ByteInfoListRec *)Xmalloc( + (codeset->length)*sizeof(ByteInfoListRec)); + if (codeset->byteM == NULL) { + goto err; + } + } + + if (num > 0) { + _XlcDbg_printValue(name,value,num); + (codeset->byteM)[M-1].M = M; + (codeset->byteM)[M-1].byteinfo_num = num; + (codeset->byteM)[M-1].byteinfo = + (ByteInfo)Xmalloc( num * sizeof(ByteInfoRec)); + for (ii = 0 ; ii < num ; ii++) { + tmpb = (codeset->byteM)[M-1].byteinfo ; + /* default 0x00 - 0xff */ + sscanf(value[ii],"\\x%lx,\\x%lx",&start,&end); + tmpb[ii].start = (unsigned char)start; + tmpb[ii].end = (unsigned char)end; + } + } + /* .... */ + } + + + /***** codeset.mb_conversion *****/ + sprintf(name, "%s.%s", cs, "mb_conversion"); + _XlcGetResource(lcd, "XLC_XLOCALE", name, &value, &num); + if (num > 0) { + _XlcDbg_printValue(name,value,num); + codeset->mbconv = Xmalloc(sizeof(ConversionRec)); + codeset->mbconv->convlist = + _XlcParse_scopemaps(value[0],&(codeset->mbconv->conv_num)); + dmpscope("mb_conv",codeset->mbconv->convlist, + codeset->mbconv->conv_num); + /* [\x%x,\x%x]->\x%x,... */ + } + /***** codeset.ct_conversion *****/ + sprintf(name, "%s.%s", cs, "ct_conversion"); + _XlcGetResource(lcd, "XLC_XLOCALE", name, &value, &num); + if (num > 0) { + _XlcDbg_printValue(name,value,num); + codeset->ctconv = Xmalloc(sizeof(ConversionRec)); + codeset->ctconv->convlist = + _XlcParse_scopemaps(value[0],&(codeset->ctconv->conv_num)); + dmpscope("ctconv",codeset->ctconv->convlist, + codeset->ctconv->conv_num); + /* [\x%x,\x%x]->\x%x,... */ + } + /***** codeset.ct_conversion_file *****/ + sprintf(name, "%s.%s", cs, "ct_conversion_file"); + _XlcGetResource(lcd, "XLC_XLOCALE", name, &value, &num); + if (num > 0) { + _XlcDbg_printValue(name,value,num); + /* [\x%x,\x%x]->\x%x,... */ + } + /***** codeset.ct_extended_segment *****/ + sprintf(name, "%s.%s", cs, "ct_extended_segment"); + _XlcGetResource(lcd, "XLC_XLOCALE", name, &value, &num); + if (num > 0) { + _XlcDbg_printValue(name,value,num); + codeset->ctextseg = create_ctextseg(value,num); + /* [\x%x,\x%x]->\x%x,... */ + } + /* For VW/UDC end */ + + } + + read_charset_define(lcd,gen); /* For VW/UDC */ + read_segmentconversion(lcd,gen); /* For VW/UDC */ + + if (gen->initial_state_GL == NULL) { + CodeSetRec *codeset; + for (i = 0; i < gen->codeset_num; i++) { + codeset = gen->codeset_list[i]; + if (codeset->side == XlcGL) + gen->initial_state_GL = codeset; + } + } + + if (gen->initial_state_GR == NULL) { + CodeSetRec *codeset; + for (i = 0; i < gen->codeset_num; i++) { + codeset = gen->codeset_list[i]; + if (codeset->side == XlcGR) + gen->initial_state_GR = codeset; + } + } + + for (i = 0; i < gen->codeset_num; i++) { + CodeSetRec *codeset = gen->codeset_list[i]; + for (ii = 0; ii < codeset->num_charsets; ii++) { + charset = codeset->charset_list[ii]; + if (! strcmp(charset->encoding_name, "ISO8859-1")) + charset->string_encoding = True; + if ( charset->string_encoding ) + codeset->string_encoding = True; + } + } + return True; + +err: + free_charset(lcd); + + return False; +} + +#ifdef USE_DYNAMIC_LC +/* override the open_om and open_im methods which were set by + super_class's initialize method() */ + +static Bool +initialize_core( + XLCd lcd) +{ + _XInitDynamicOM(lcd); + + _XInitDynamicIM(lcd); + + return True; +} +#endif + +static Bool +initialize(XLCd lcd) +{ + XLCdPublicMethods superclass = (XLCdPublicMethods) _XlcPublicMethods; + + XLC_PUBLIC_METHODS(lcd)->superclass = superclass; + + if (superclass->pub.initialize) { + if ((*superclass->pub.initialize)(lcd) == False) + return False; + } + +#ifdef USE_DYNAMIC_LC + if (initialize_core(lcd) == False) + return False; +#endif + + if (load_generic(lcd) == False) + return False; + + return True; +} + +/* VW/UDC start 95.01.08 */ +static void +freeByteM( + CodeSet codeset) +{ + int i; + ByteInfoList blst; + if (codeset->byteM == NULL) { + return ; + } + blst = codeset->byteM; + for (i = 0; i < codeset->length; i++) { + if (blst[i].byteinfo) { + Xfree(blst[i].byteinfo); + blst[i].byteinfo = NULL; + } + } + Xfree(codeset->byteM); + codeset->byteM = NULL; +} + +static void +freeConversion( + CodeSet codeset) +{ + Conversion mbconv,ctconv; + if (codeset->mbconv) { + mbconv = codeset->mbconv; + /* ... */ + if (mbconv->convlist) { + Xfree(mbconv->convlist); + mbconv->convlist = NULL; + } + Xfree(mbconv); + codeset->mbconv = NULL; + } + if (codeset->ctconv) { + ctconv = codeset->ctconv; + /* ... */ + if (ctconv->convlist) { + Xfree(ctconv->convlist); + ctconv->convlist = NULL; + } + Xfree(ctconv); + codeset->ctconv = NULL; + } +} + +static void +freeExtdSegment( + CodeSet codeset) +{ + ExtdSegment ctextseg; + if (codeset->ctextseg == NULL) { + return; + } + ctextseg = codeset->ctextseg; + if (ctextseg->name) { + Xfree(ctextseg->name); + ctextseg->name = NULL; + } + if (ctextseg->area) { + Xfree(ctextseg->area); + ctextseg->area = NULL; + } + Xfree(codeset->ctextseg); + codeset->ctextseg = NULL; +} + +static void +freeParseInfo( + CodeSet codeset) +{ + ParseInfo parse_info; + if (codeset->parse_info == NULL) { + return; + } + parse_info = codeset->parse_info; + if (parse_info->encoding) { + Xfree(parse_info->encoding); + parse_info->encoding = NULL; + } + Xfree(codeset->parse_info); + codeset->parse_info = NULL; +} + +static void +destroy_CodeSetList( + XLCdGenericPart *gen) +{ + CodeSet *codeset = gen->codeset_list; + int i; + if (gen->codeset_num == 0) { + return; + } + for (i=0;i<gen->codeset_num;i++) { + freeByteM(codeset[i]); + freeConversion(codeset[i]); + freeExtdSegment(codeset[i]); + freeParseInfo(codeset[i]); + if (codeset[i]->charset_list) { + Xfree(codeset[i]->charset_list); + codeset[i]->charset_list = NULL; + } + Xfree(codeset[i]); codeset[i]=NULL; + } + Xfree(codeset); gen->codeset_list = NULL; +} + +static void +destroy_SegConv( + XLCdGenericPart *gen) +{ + SegConv seg = gen->segment_conv; + int i; + if (gen->segment_conv_num == 0) { + return; + } + for (i=0;i<gen->segment_conv_num;i++) { + if (seg[i].source_encoding) { + Xfree(seg[i].source_encoding); + seg[i].source_encoding = NULL; + } + if (seg[i].destination_encoding) { + Xfree(seg[i].destination_encoding); + seg[i].destination_encoding = NULL; + } + if (seg[i].conv) { + Xfree(seg[i].conv); seg[i].conv = NULL; + } + } + Xfree(seg); gen->segment_conv = NULL; +} + +static void +destroy_gen( + XLCd lcd) +{ + XLCdGenericPart *gen = XLC_GENERIC_PART(lcd); + destroy_SegConv(gen); + destroy_CodeSetList(gen); + if (gen->mb_parse_table) { + Xfree(gen->mb_parse_table); + gen->mb_parse_table = NULL; + } + if (gen->mb_parse_list) { + Xfree(gen->mb_parse_list); + gen->mb_parse_list = NULL; + } +} +/* VW/UDC end 95.01.08 */ + +static void +destroy( + XLCd lcd) +{ + XLCdPublicMethods superclass = XLC_PUBLIC_METHODS(lcd)->superclass; + + destroy_gen(lcd); /* ADD 1996.01.08 */ + if (superclass && superclass->pub.destroy) + (*superclass->pub.destroy)(lcd); +} diff --git a/libX11/src/xlibi18n/lcPublic.c b/libX11/src/xlibi18n/lcPublic.c index 5082f05bb..12a344272 100644 --- a/libX11/src/xlibi18n/lcPublic.c +++ b/libX11/src/xlibi18n/lcPublic.c @@ -1,315 +1,315 @@ -/*
- * Copyright 1992, 1993 by TOSHIBA Corp.
- *
- * 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 TOSHIBA not be used in advertising
- * or publicity pertaining to distribution of the software without specific,
- * written prior permission. TOSHIBA make no representations about the
- * suitability of this software for any purpose. It is provided "as is"
- * without express or implied warranty.
- *
- * TOSHIBA DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
- * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
- * TOSHIBA 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 TORTIOUS ACTION,
- * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- *
- * Author: Katsuhisa Yano TOSHIBA Corp.
- * mopi@osa.ilab.toshiba.co.jp
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <unistd.h>
-#include "Xlibint.h"
-#include "XlcPubI.h"
-
-static const char *
-default_string(
- XLCd lcd)
-{
- return XLC_PUBLIC(lcd, default_string);
-}
-
-static XLCd create (const char *name, XLCdMethods methods);
-static Bool initialize (XLCd lcd);
-static void destroy (XLCd lcd);
-static char *get_values (XLCd lcd, XlcArgList args, int num_args);
-
-static XLCdPublicMethodsRec publicMethods = {
- {
- destroy,
- _XlcDefaultMapModifiers,
- NULL,
- NULL,
- _XrmDefaultInitParseInfo,
- _XmbTextPropertyToTextList,
- _XwcTextPropertyToTextList,
- _Xutf8TextPropertyToTextList,
- _XmbTextListToTextProperty,
- _XwcTextListToTextProperty,
- _Xutf8TextListToTextProperty,
- _XwcFreeStringList,
- default_string,
- NULL,
- NULL
- },
- {
- NULL,
- create,
- initialize,
- destroy,
- get_values,
- _XlcGetLocaleDataBase
- }
-};
-
-XLCdMethods _XlcPublicMethods = (XLCdMethods) &publicMethods;
-
-static XLCd
-create(
- const char *name,
- XLCdMethods methods)
-{
- XLCd lcd;
- XLCdPublicMethods new;
-
- lcd = Xcalloc(1, sizeof(XLCdRec));
- if (lcd == NULL)
- return (XLCd) NULL;
-
- lcd->core = Xcalloc(1, sizeof(XLCdPublicRec));
- if (lcd->core == NULL)
- goto err;
-
- new = (XLCdPublicMethods) Xmalloc(sizeof(XLCdPublicMethodsRec));
- if (new == NULL)
- goto err;
- memcpy(new,methods,sizeof(XLCdPublicMethodsRec));
- lcd->methods = (XLCdMethods) new;
-
- return lcd;
-
-err:
- Xfree(lcd);
- return (XLCd) NULL;
-}
-
-static Bool
-load_public(
- XLCd lcd)
-{
- XLCdPublicPart *pub = XLC_PUBLIC_PART(lcd);
- char **values, *str;
- int num;
-
- if(_XlcCreateLocaleDataBase(lcd) == NULL)
- return False;
-
- _XlcGetResource(lcd, "XLC_XLOCALE", "mb_cur_max", &values, &num);
- if (num > 0) {
- pub->mb_cur_max = atoi(values[0]);
- if (pub->mb_cur_max < 1)
- pub->mb_cur_max = 1;
- } else
- pub->mb_cur_max = 1;
-
- _XlcGetResource(lcd, "XLC_XLOCALE", "state_depend_encoding", &values, &num);
- if (num > 0 && !_XlcCompareISOLatin1(values[0], "True"))
- pub->is_state_depend = True;
- else
- pub->is_state_depend = False;
-
- _XlcGetResource(lcd, "XLC_XLOCALE", "encoding_name", &values, &num);
- str = (num > 0) ? values[0] : "STRING";
- pub->encoding_name = strdup(str);
- if (pub->encoding_name == NULL)
- return False;
-
- return True;
-}
-
-static Bool
-initialize_core(
- XLCd lcd)
-{
- XLCdMethods methods = lcd->methods;
- XLCdMethods core = &publicMethods.core;
-
- if (methods->close == NULL)
- methods->close = core->close;
-
- if (methods->map_modifiers == NULL)
- methods->map_modifiers = core->map_modifiers;
-
- if (methods->open_om == NULL)
-#ifdef USE_DYNAMIC_LC
- _XInitDefaultOM(lcd);
-#else
- _XInitOM(lcd);
-#endif
-
- if (methods->open_im == NULL)
-#ifdef USE_DYNAMIC_LC
- _XInitDefaultIM(lcd);
-#else
- _XInitIM(lcd);
-#endif
-
- if (methods->init_parse_info == NULL)
- methods->init_parse_info = core->init_parse_info;
-
- if (methods->mb_text_prop_to_list == NULL)
- methods->mb_text_prop_to_list = core->mb_text_prop_to_list;
-
- if (methods->wc_text_prop_to_list == NULL)
- methods->wc_text_prop_to_list = core->wc_text_prop_to_list;
-
- if (methods->utf8_text_prop_to_list == NULL)
- methods->utf8_text_prop_to_list = core->utf8_text_prop_to_list;
-
- if (methods->mb_text_list_to_prop == NULL)
- methods->mb_text_list_to_prop = core->mb_text_list_to_prop;
-
- if (methods->wc_text_list_to_prop == NULL)
- methods->wc_text_list_to_prop = core->wc_text_list_to_prop;
-
- if (methods->utf8_text_list_to_prop == NULL)
- methods->utf8_text_list_to_prop = core->utf8_text_list_to_prop;
-
- if (methods->wc_free_string_list == NULL)
- methods->wc_free_string_list = core->wc_free_string_list;
-
- if (methods->default_string == NULL)
- methods->default_string = core->default_string;
-
- return True;
-}
-
-static Bool
-initialize(
- XLCd lcd)
-{
- XLCdPublicMethodsPart *methods = XLC_PUBLIC_METHODS(lcd);
- XLCdPublicMethodsPart *pub_methods = &publicMethods.pub;
- XLCdPublicPart *pub = XLC_PUBLIC_PART(lcd);
- char *name;
-#if !defined(X_LOCALE)
- int len;
- char sinamebuf[256];
- char* siname;
-#endif
-
- _XlcInitCTInfo();
-
- if (initialize_core(lcd) == False)
- return False;
-
- name = lcd->core->name;
-#if !defined(X_LOCALE)
- /*
- * _XlMapOSLocaleName will return the same string or a substring
- * of name, so strlen(name) is okay
- */
- if ((len = strlen(name)) < sizeof sinamebuf)
- siname = sinamebuf;
- else
- siname = Xmalloc (len + 1);
- if (siname == NULL)
- return False;
- name = _XlcMapOSLocaleName(name, siname);
-#endif
- /* _XlcResolveLocaleName will lookup the SI's name for the locale */
- if (_XlcResolveLocaleName(name, pub) == 0) {
-#if !defined(X_LOCALE)
- if (siname != sinamebuf) Xfree (siname);
-#endif
- return False;
- }
-#if !defined(X_LOCALE)
- if (siname != sinamebuf)
- Xfree (siname);
-#endif
-
- if (pub->default_string == NULL)
- pub->default_string = "";
-
- if (methods->get_values == NULL)
- methods->get_values = pub_methods->get_values;
-
- if (methods->get_resource == NULL)
- methods->get_resource = pub_methods->get_resource;
-
- return load_public(lcd);
-}
-
-static void
-destroy_core(
- XLCd lcd)
-{
- if (lcd->core) {
- if (lcd->core->name)
- Xfree(lcd->core->name);
- Xfree(lcd->core);
- }
-
- if (lcd->methods)
- Xfree(lcd->methods);
-
- Xfree(lcd);
-}
-
-static void
-destroy(
- XLCd lcd)
-{
- XLCdPublicPart *pub = XLC_PUBLIC_PART(lcd);
-
- _XlcDestroyLocaleDataBase(lcd);
-
- if (pub->siname)
- Xfree(pub->siname);
- if (pub->encoding_name)
- Xfree(pub->encoding_name);
-
- destroy_core(lcd);
-}
-
-static XlcResource resources[] = {
- { XlcNCodeset, NULLQUARK, sizeof(char *),
- XOffsetOf(XLCdPublicRec, pub.codeset), XlcGetMask },
- { XlcNDefaultString, NULLQUARK, sizeof(char *),
- XOffsetOf(XLCdPublicRec, pub.default_string), XlcGetMask },
- { XlcNEncodingName, NULLQUARK, sizeof(char *),
- XOffsetOf(XLCdPublicRec, pub.encoding_name), XlcGetMask },
- { XlcNLanguage, NULLQUARK, sizeof(char *),
- XOffsetOf(XLCdPublicRec, pub.language), XlcGetMask },
- { XlcNMbCurMax, NULLQUARK, sizeof(int),
- XOffsetOf(XLCdPublicRec, pub.mb_cur_max), XlcGetMask },
- { XlcNStateDependentEncoding, NULLQUARK, sizeof(Bool),
- XOffsetOf(XLCdPublicRec, pub.is_state_depend), XlcGetMask },
- { XlcNTerritory, NULLQUARK, sizeof(char *),
- XOffsetOf(XLCdPublicRec, pub.territory), XlcGetMask }
-};
-
-static char *
-get_values(
- XLCd lcd,
- XlcArgList args,
- int num_args)
-{
- XLCdPublic pub = (XLCdPublic) lcd->core;
-
- if (resources[0].xrm_name == NULLQUARK)
- _XlcCompileResourceList(resources, XlcNumber(resources));
-
- return _XlcGetValues((XPointer) pub, resources, XlcNumber(resources), args,
- num_args, XlcGetMask);
-}
+/* + * Copyright 1992, 1993 by TOSHIBA Corp. + * + * 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 TOSHIBA not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. TOSHIBA make no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * TOSHIBA DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING + * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL + * TOSHIBA 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 TORTIOUS ACTION, + * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + * + * Author: Katsuhisa Yano TOSHIBA Corp. + * mopi@osa.ilab.toshiba.co.jp + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include <unistd.h> +#include "Xlibint.h" +#include "XlcPubI.h" + +static const char * +default_string( + XLCd lcd) +{ + return XLC_PUBLIC(lcd, default_string); +} + +static XLCd create (const char *name, XLCdMethods methods); +static Bool initialize (XLCd lcd); +static void destroy (XLCd lcd); +static char *get_values (XLCd lcd, XlcArgList args, int num_args); + +static XLCdPublicMethodsRec publicMethods = { + { + destroy, + _XlcDefaultMapModifiers, + NULL, + NULL, + _XrmDefaultInitParseInfo, + _XmbTextPropertyToTextList, + _XwcTextPropertyToTextList, + _Xutf8TextPropertyToTextList, + _XmbTextListToTextProperty, + _XwcTextListToTextProperty, + _Xutf8TextListToTextProperty, + _XwcFreeStringList, + default_string, + NULL, + NULL + }, + { + NULL, + create, + initialize, + destroy, + get_values, + _XlcGetLocaleDataBase + } +}; + +XLCdMethods _XlcPublicMethods = (XLCdMethods) &publicMethods; + +static XLCd +create( + const char *name, + XLCdMethods methods) +{ + XLCd lcd; + XLCdPublicMethods new; + + lcd = Xcalloc(1, sizeof(XLCdRec)); + if (lcd == NULL) + return (XLCd) NULL; + + lcd->core = Xcalloc(1, sizeof(XLCdPublicRec)); + if (lcd->core == NULL) + goto err; + + new = (XLCdPublicMethods) Xmalloc(sizeof(XLCdPublicMethodsRec)); + if (new == NULL) + goto err; + memcpy(new,methods,sizeof(XLCdPublicMethodsRec)); + lcd->methods = (XLCdMethods) new; + + return lcd; + +err: + Xfree(lcd); + return (XLCd) NULL; +} + +static Bool +load_public( + XLCd lcd) +{ + XLCdPublicPart *pub = XLC_PUBLIC_PART(lcd); + char **values, *str; + int num; + + if(_XlcCreateLocaleDataBase(lcd) == NULL) + return False; + + _XlcGetResource(lcd, "XLC_XLOCALE", "mb_cur_max", &values, &num); + if (num > 0) { + pub->mb_cur_max = atoi(values[0]); + if (pub->mb_cur_max < 1) + pub->mb_cur_max = 1; + } else + pub->mb_cur_max = 1; + + _XlcGetResource(lcd, "XLC_XLOCALE", "state_depend_encoding", &values, &num); + if (num > 0 && !_XlcCompareISOLatin1(values[0], "True")) + pub->is_state_depend = True; + else + pub->is_state_depend = False; + + _XlcGetResource(lcd, "XLC_XLOCALE", "encoding_name", &values, &num); + str = (num > 0) ? values[0] : "STRING"; + pub->encoding_name = strdup(str); + if (pub->encoding_name == NULL) + return False; + + return True; +} + +static Bool +initialize_core( + XLCd lcd) +{ + XLCdMethods methods = lcd->methods; + XLCdMethods core = &publicMethods.core; + + if (methods->close == NULL) + methods->close = core->close; + + if (methods->map_modifiers == NULL) + methods->map_modifiers = core->map_modifiers; + + if (methods->open_om == NULL) +#ifdef USE_DYNAMIC_LC + _XInitDefaultOM(lcd); +#else + _XInitOM(lcd); +#endif + + if (methods->open_im == NULL) +#ifdef USE_DYNAMIC_LC + _XInitDefaultIM(lcd); +#else + _XInitIM(lcd); +#endif + + if (methods->init_parse_info == NULL) + methods->init_parse_info = core->init_parse_info; + + if (methods->mb_text_prop_to_list == NULL) + methods->mb_text_prop_to_list = core->mb_text_prop_to_list; + + if (methods->wc_text_prop_to_list == NULL) + methods->wc_text_prop_to_list = core->wc_text_prop_to_list; + + if (methods->utf8_text_prop_to_list == NULL) + methods->utf8_text_prop_to_list = core->utf8_text_prop_to_list; + + if (methods->mb_text_list_to_prop == NULL) + methods->mb_text_list_to_prop = core->mb_text_list_to_prop; + + if (methods->wc_text_list_to_prop == NULL) + methods->wc_text_list_to_prop = core->wc_text_list_to_prop; + + if (methods->utf8_text_list_to_prop == NULL) + methods->utf8_text_list_to_prop = core->utf8_text_list_to_prop; + + if (methods->wc_free_string_list == NULL) + methods->wc_free_string_list = core->wc_free_string_list; + + if (methods->default_string == NULL) + methods->default_string = core->default_string; + + return True; +} + +static Bool +initialize( + XLCd lcd) +{ + XLCdPublicMethodsPart *methods = XLC_PUBLIC_METHODS(lcd); + XLCdPublicMethodsPart *pub_methods = &publicMethods.pub; + XLCdPublicPart *pub = XLC_PUBLIC_PART(lcd); + char *name; +#if !defined(X_LOCALE) + int len; + char sinamebuf[256]; + char* siname; +#endif + + _XlcInitCTInfo(); + + if (initialize_core(lcd) == False) + return False; + + name = lcd->core->name; +#if !defined(X_LOCALE) + /* + * _XlMapOSLocaleName will return the same string or a substring + * of name, so strlen(name) is okay + */ + if ((len = strlen(name)) < sizeof sinamebuf) + siname = sinamebuf; + else + siname = Xmalloc (len + 1); + if (siname == NULL) + return False; + name = _XlcMapOSLocaleName(name, siname); +#endif + /* _XlcResolveLocaleName will lookup the SI's name for the locale */ + if (_XlcResolveLocaleName(name, pub) == 0) { +#if !defined(X_LOCALE) + if (siname != sinamebuf) Xfree (siname); +#endif + return False; + } +#if !defined(X_LOCALE) + if (siname != sinamebuf) + Xfree (siname); +#endif + + if (pub->default_string == NULL) + pub->default_string = ""; + + if (methods->get_values == NULL) + methods->get_values = pub_methods->get_values; + + if (methods->get_resource == NULL) + methods->get_resource = pub_methods->get_resource; + + return load_public(lcd); +} + +static void +destroy_core( + XLCd lcd) +{ + if (lcd->core) { + if (lcd->core->name) + Xfree(lcd->core->name); + Xfree(lcd->core); + } + + if (lcd->methods) + Xfree(lcd->methods); + + Xfree(lcd); +} + +static void +destroy( + XLCd lcd) +{ + XLCdPublicPart *pub = XLC_PUBLIC_PART(lcd); + + _XlcDestroyLocaleDataBase(lcd); + + if (pub->siname) + Xfree(pub->siname); + if (pub->encoding_name) + Xfree(pub->encoding_name); + + destroy_core(lcd); +} + +static XlcResource resources[] = { + { XlcNCodeset, NULLQUARK, sizeof(char *), + XOffsetOf(XLCdPublicRec, pub.codeset), XlcGetMask }, + { XlcNDefaultString, NULLQUARK, sizeof(char *), + XOffsetOf(XLCdPublicRec, pub.default_string), XlcGetMask }, + { XlcNEncodingName, NULLQUARK, sizeof(char *), + XOffsetOf(XLCdPublicRec, pub.encoding_name), XlcGetMask }, + { XlcNLanguage, NULLQUARK, sizeof(char *), + XOffsetOf(XLCdPublicRec, pub.language), XlcGetMask }, + { XlcNMbCurMax, NULLQUARK, sizeof(int), + XOffsetOf(XLCdPublicRec, pub.mb_cur_max), XlcGetMask }, + { XlcNStateDependentEncoding, NULLQUARK, sizeof(Bool), + XOffsetOf(XLCdPublicRec, pub.is_state_depend), XlcGetMask }, + { XlcNTerritory, NULLQUARK, sizeof(char *), + XOffsetOf(XLCdPublicRec, pub.territory), XlcGetMask } +}; + +static char * +get_values( + XLCd lcd, + XlcArgList args, + int num_args) +{ + XLCdPublic pub = (XLCdPublic) lcd->core; + + if (resources[0].xrm_name == NULLQUARK) + _XlcCompileResourceList(resources, XlcNumber(resources)); + + return _XlcGetValues((XPointer) pub, resources, XlcNumber(resources), args, + num_args, XlcGetMask); +} |