diff options
Diffstat (limited to 'lisp/modules/xt.c')
-rw-r--r-- | lisp/modules/xt.c | 1797 |
1 files changed, 1797 insertions, 0 deletions
diff --git a/lisp/modules/xt.c b/lisp/modules/xt.c new file mode 100644 index 0000000..13c7ae7 --- /dev/null +++ b/lisp/modules/xt.c @@ -0,0 +1,1797 @@ +/* + * Copyright (c) 2001 by The XFree86 Project, Inc. + * + * 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 XFREE86 PROJECT 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 XFree86 Project 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 + * XFree86 Project. + * + * Author: Paulo César Pereira de Andrade + */ + +/* $XFree86: xc/programs/xedit/lisp/modules/xt.c,v 1.19 2002/11/23 08:26:52 paulo Exp $ */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <X11/Intrinsic.h> +#include <X11/StringDefs.h> +#include <X11/Shell.h> +#include "internal.h" +#include "private.h" + +/* + * Types + */ +typedef struct { + XrmQuark qname; + XrmQuark qtype; + Cardinal size; +} ResourceInfo; + +typedef struct { + WidgetClass widget_class; + ResourceInfo **resources; + Cardinal num_resources; + Cardinal num_cons_resources; +} ResourceList; + +typedef struct { + Arg *args; + Cardinal num_args; +} Resources; + +typedef struct { + LispObj *data; + /* data is => (list* widget callback argument) */ +} CallbackArgs; + +/* + * Prototypes + */ +int xtLoadModule(LispMac*); +void LispXtCleanupCallback(Widget, XtPointer, XtPointer); + +void LispXtCallback(Widget, XtPointer, XtPointer); +void LispXtInputCallback(XtPointer, int*, XtInputId*); + +/* a hack... */ +LispObj *Lisp_XtCoerceToWidgetList(LispBuiltin*); + +LispObj *Lisp_XtAddCallback(LispBuiltin*); +LispObj *Lisp_XtAppInitialize(LispBuiltin*); +LispObj *Lisp_XtAppMainLoop(LispBuiltin*); +LispObj *Lisp_XtAppAddInput(LispBuiltin*); +LispObj *Lisp_XtAppPending(LispBuiltin*); +LispObj *Lisp_XtAppProcessEvent(LispBuiltin*); +LispObj *Lisp_XtCreateWidget(LispBuiltin*); +LispObj *Lisp_XtCreateManagedWidget(LispBuiltin*); +LispObj *Lisp_XtCreatePopupShell(LispBuiltin*); +LispObj *Lisp_XtDestroyWidget(LispBuiltin*); +LispObj *Lisp_XtGetKeyboardFocusWidget(LispBuiltin*); +LispObj *Lisp_XtGetValues(LispBuiltin*); +LispObj *Lisp_XtManageChild(LispBuiltin*); +LispObj *Lisp_XtUnmanageChild(LispBuiltin*); +LispObj *Lisp_XtSetMappedWhenManaged(LispBuiltin*); +LispObj *Lisp_XtMapWidget(LispBuiltin*); +LispObj *Lisp_XtName(LispBuiltin*); +LispObj *Lisp_XtParent(LispBuiltin*); +LispObj *Lisp_XtUnmapWidget(LispBuiltin*); +LispObj *Lisp_XtPopup(LispBuiltin*); +LispObj *Lisp_XtPopdown(LispBuiltin*); +LispObj *Lisp_XtIsRealized(LispBuiltin*); +LispObj *Lisp_XtRealizeWidget(LispBuiltin*); +LispObj *Lisp_XtUnrealizeWidget(LispBuiltin*); +LispObj *Lisp_XtRemoveInput(LispBuiltin*); +LispObj *Lisp_XtSetSensitive(LispBuiltin*); +LispObj *Lisp_XtSetValues(LispBuiltin*); +LispObj *Lisp_XtWidgetToApplicationContext(LispBuiltin*); +LispObj *Lisp_XtDisplay(LispBuiltin*); +LispObj *Lisp_XtDisplayOfObject(LispBuiltin*); +LispObj *Lisp_XtScreen(LispBuiltin*); +LispObj *Lisp_XtScreenOfObject(LispBuiltin*); +LispObj *Lisp_XtSetKeyboardFocus(LispBuiltin*); +LispObj *Lisp_XtWindow(LispBuiltin*); +LispObj *Lisp_XtWindowOfObject(LispBuiltin*); +LispObj *Lisp_XtAddGrab(LispBuiltin*); +LispObj *Lisp_XtRemoveGrab(LispBuiltin*); +LispObj *Lisp_XtAppGetExitFlag(LispBuiltin*); +LispObj *Lisp_XtAppSetExitFlag(LispBuiltin*); + +LispObj *LispXtCreateWidget(LispBuiltin*, int); + +static Resources *LispConvertResources(LispObj*, Widget, + ResourceList*, ResourceList*); +static void LispFreeResources(Resources*); + +static int bcmp_action_resource(_Xconst void*, _Xconst void*); +static ResourceInfo *GetResourceInfo(char*, ResourceList*, ResourceList*); +static ResourceList *GetResourceList(WidgetClass); +static int bcmp_action_resource_list(_Xconst void*, _Xconst void*); +static ResourceList *FindResourceList(WidgetClass); +static int qcmp_action_resource_list(_Xconst void*, _Xconst void*); +static ResourceList *CreateResourceList(WidgetClass); +static int qcmp_action_resource(_Xconst void*, _Xconst void*); +static void BindResourceList(ResourceList*); + +static void PopdownAction(Widget, XEvent*, String*, Cardinal*); +static void QuitAction(Widget, XEvent*, String*, Cardinal*); + +/* + * Initialization + */ +static LispBuiltin lispbuiltins[] = { + {LispFunction, Lisp_XtCoerceToWidgetList, "xt-coerce-to-widget-list number opaque"}, + + {LispFunction, Lisp_XtAddGrab, "xt-add-grab widget exclusive spring-loaded"}, + {LispFunction, Lisp_XtAddCallback, "xt-add-callback widget callback-name callback &optional client-data"}, + {LispFunction, Lisp_XtAppAddInput, "xt-app-add-input app-context fileno condition function &optional client-data"}, + {LispFunction, Lisp_XtAppInitialize, "xt-app-initialize app-context-return application-class &optional options fallback-resources"}, + {LispFunction, Lisp_XtAppPending, "xt-app-pending app-context"}, + {LispFunction, Lisp_XtAppMainLoop, "xt-app-main-loop app-context"}, + {LispFunction, Lisp_XtAppProcessEvent, "xt-app-process-event app-context &optional mask"}, + {LispFunction, Lisp_XtAppGetExitFlag, "xt-app-get-exit-flag app-context"}, + {LispFunction, Lisp_XtAppSetExitFlag, "xt-app-set-exit-flag app-context"}, + {LispFunction, Lisp_XtCreateManagedWidget, "xt-create-managed-widget name widget-class parent &optional arguments"}, + {LispFunction, Lisp_XtCreateWidget, "xt-create-widget name widget-class parent &optional arguments"}, + {LispFunction, Lisp_XtCreatePopupShell, "xt-create-popup-shell name widget-class parent &optional arguments"}, + {LispFunction, Lisp_XtDestroyWidget, "xt-destroy-widget widget"}, + {LispFunction, Lisp_XtGetKeyboardFocusWidget, "xt-get-keyboard-focus-widget widget"}, + {LispFunction, Lisp_XtGetValues, "xt-get-values widget arguments"}, + {LispFunction, Lisp_XtManageChild, "xt-manage-child widget"}, + {LispFunction, Lisp_XtName, "xt-name widget"}, + {LispFunction, Lisp_XtUnmanageChild, "xt-unmanage-child widget"}, + {LispFunction, Lisp_XtMapWidget, "xt-map-widget widget"}, + {LispFunction, Lisp_XtUnmapWidget, "xt-unmap-widget widget"}, + {LispFunction, Lisp_XtSetMappedWhenManaged, "xt-set-mapped-when-managed widget map-when-managed"}, + {LispFunction, Lisp_XtParent, "xt-parent widget"}, + {LispFunction, Lisp_XtPopup, "xt-popup widget grab-kind"}, + {LispFunction, Lisp_XtPopdown, "xt-popdown widget"}, + {LispFunction, Lisp_XtIsRealized, "xt-is-realized widget"}, + {LispFunction, Lisp_XtRealizeWidget, "xt-realize-widget widget"}, + {LispFunction, Lisp_XtUnrealizeWidget, "xt-unrealize-widget widget"}, + {LispFunction, Lisp_XtRemoveInput, "xt-remove-input input"}, + {LispFunction, Lisp_XtRemoveGrab, "xt-remove-grab widget"}, + {LispFunction, Lisp_XtSetKeyboardFocus, "xt-set-keyboard-focus widget descendant"}, + {LispFunction, Lisp_XtSetSensitive, "xt-set-sensitive widget sensitive"}, + {LispFunction, Lisp_XtSetValues, "xt-set-values widget arguments"}, + {LispFunction, Lisp_XtWidgetToApplicationContext, "xt-widget-to-application-context widget"}, + {LispFunction, Lisp_XtDisplay, "xt-display widget"}, + {LispFunction, Lisp_XtDisplayOfObject, "xt-display-of-object object"}, + {LispFunction, Lisp_XtScreen, "xt-screen widget"}, + {LispFunction, Lisp_XtScreenOfObject, "xt-screen-of-object object"}, + {LispFunction, Lisp_XtWindow, "xt-window widget"}, + {LispFunction, Lisp_XtWindowOfObject, "xt-window-of-object object"}, +}; + +LispModuleData xtLispModuleData = { + LISP_MODULE_VERSION, + xtLoadModule, +}; + +static ResourceList **resource_list; +static Cardinal num_resource_list; + +static Atom delete_window; +static int xtAppContext_t, xtWidget_t, xtWidgetClass_t, xtWidgetList_t, + xtInputId_t, xtDisplay_t, xtScreen_t, xtWindow_t; + +static XtActionsRec actions[] = { + {"xt-popdown", PopdownAction}, + {"xt-quit", QuitAction}, +}; + +static XrmQuark qCardinal, qInt, qString, qWidget, qFloat; + +static CallbackArgs **input_list; +static Cardinal num_input_list, size_input_list; + +/* + * Implementation + */ +int +xtLoadModule(void) +{ + int i; + char *fname = "XT-LOAD-MODULE"; + + xtAppContext_t = LispRegisterOpaqueType("XtAppContext"); + xtWidget_t = LispRegisterOpaqueType("Widget"); + xtWidgetClass_t = LispRegisterOpaqueType("WidgetClass"); + xtWidgetList_t = LispRegisterOpaqueType("WidgetList"); + xtInputId_t = LispRegisterOpaqueType("XtInputId"); + xtDisplay_t = LispRegisterOpaqueType("Display*"); + xtScreen_t = LispRegisterOpaqueType("Screen*"); + xtWindow_t = LispRegisterOpaqueType("Window"); + + LispExecute("(DEFSTRUCT XT-WIDGET-LIST NUM-CHILDREN CHILDREN)\n"); + + GCDisable(); + (void)LispSetVariable(ATOM2("CORE-WIDGET-CLASS"), + OPAQUE(coreWidgetClass, xtWidgetClass_t), + fname, 0); + (void)LispSetVariable(ATOM2("COMPOSITE-WIDGET-CLASS"), + OPAQUE(compositeWidgetClass, xtWidgetClass_t), + fname, 0); + (void)LispSetVariable(ATOM2("CONSTRAINT-WIDGET-CLASS"), + OPAQUE(constraintWidgetClass, xtWidgetClass_t), + fname, 0); + (void)LispSetVariable(ATOM2("TRANSIENT-SHELL-WIDGET-CLASS"), + OPAQUE(transientShellWidgetClass, xtWidgetClass_t), + fname, 0); + + /* parameters for XtPopup */ + (void)LispSetVariable(ATOM2("XT-GRAB-EXCLUSIVE"), + INTEGER(XtGrabExclusive), fname, 0); + (void)LispSetVariable(ATOM2("XT-GRAB-NONE"), + INTEGER(XtGrabNone), fname, 0); + (void)LispSetVariable(ATOM2("XT-GRAB-NONE-EXCLUSIVE"), + INTEGER(XtGrabNonexclusive), fname, 0); + + /* parameters for XtAppProcessEvent */ + (void)LispSetVariable(ATOM2("XT-IM-XEVENT"), + INTEGER(XtIMXEvent), fname, 0); + (void)LispSetVariable(ATOM2("XT-IM-TIMER"), + INTEGER(XtIMTimer), fname, 0); + (void)LispSetVariable(ATOM2("XT-IM-ALTERNATE-INPUT"), + INTEGER(XtIMAlternateInput), fname, 0); + (void)LispSetVariable(ATOM2("XT-IM-SIGNAL"), + INTEGER(XtIMSignal), fname, 0); + (void)LispSetVariable(ATOM2("XT-IM-ALL"), + INTEGER(XtIMAll), fname, 0); + + /* parameters for XtAppAddInput */ + (void)LispSetVariable(ATOM2("XT-INPUT-READ-MASK"), + INTEGER(XtInputReadMask), fname, 0); + (void)LispSetVariable(ATOM2("XT-INPUT-WRITE-MASK"), + INTEGER(XtInputWriteMask), fname, 0); + (void)LispSetVariable(ATOM2("XT-INPUT-EXCEPT-MASK"), + INTEGER(XtInputExceptMask), fname, 0); + GCEnable(); + + qCardinal = XrmPermStringToQuark(XtRCardinal); + qInt = XrmPermStringToQuark(XtRInt); + qString = XrmPermStringToQuark(XtRString); + qWidget = XrmPermStringToQuark(XtRWidget); + qFloat = XrmPermStringToQuark(XtRFloat); + + for (i = 0; i < sizeof(lispbuiltins) / sizeof(lispbuiltins[0]); i++) + LispAddBuiltinFunction(&lispbuiltins[i]); + + return (1); +} + +void +LispXtCallback(Widget w, XtPointer user_data, XtPointer call_data) +{ + CallbackArgs *args = (CallbackArgs*)user_data; + LispObj *code, *ocod = COD; + + GCDisable(); + /* callback name */ /* reall caller */ + code = CONS(CDR(CDR(args->data)), CONS(OPAQUE(w, xtWidget_t), + CONS(CAR(CDR(args->data)), CONS(OPAQUE(call_data, 0), NIL)))); + /* user arguments */ + COD = CONS(code, COD); + GCEnable(); + + (void)EVAL(code); + COD = ocod; +} + + +void +LispXtCleanupCallback(Widget w, XtPointer user_data, XtPointer call_data) +{ + CallbackArgs *args = (CallbackArgs*)user_data; + + UPROTECT(CAR(args->data), args->data); + XtFree((XtPointer)args); +} + +void +LispXtInputCallback(XtPointer closure, int *source, XtInputId *id) +{ + CallbackArgs *args = (CallbackArgs*)closure; + LispObj *code, *ocod = COD; + + GCDisable(); + /* callback name */ /* user arguments */ + code = CONS(CDR(CDR(args->data)), CONS(CAR(CDR(args->data)), + CONS(INTEGER(*source), CONS(CAR(args->data), NIL)))); + /* input source */ /* input id */ + COD = CONS(code, COD); + GCEnable(); + + (void)EVAL(code); + COD = ocod; +} + +LispObj * +Lisp_XtCoerceToWidgetList(LispBuiltin *builtin) +/* + xt-coerce-to-widget-list number opaque + */ +{ + int i; + WidgetList children; + Cardinal num_children; + LispObj *cons, *widget_list, *result; + + LispObj *onumber, *opaque; + + opaque = ARGUMENT(1); + onumber = ARGUMENT(0); + + CHECK_INDEX(onumber); + num_children = FIXNUM_VALUE(onumber); + + if (!CHECKO(opaque, xtWidgetList_t)) + LispDestroy("%s: cannot convert %s to WidgetList", + STRFUN(builtin), STROBJ(opaque)); + children = (WidgetList)(opaque->data.opaque.data); + + GCDisable(); + widget_list = cons = NIL; + for (i = 0; i < num_children; i++) { + result = CONS(OPAQUE(children[i], xtWidget_t), NIL); + if (widget_list == NIL) + widget_list = cons = result; + else { + RPLACD(cons, result); + cons = CDR(cons); + } + } + + result = APPLY(ATOM("MAKE-XT-WIDGET-LIST"), + CONS(KEYWORD("NUM-CHILDREN"), + CONS(INTEGER(num_children), + CONS(KEYWORD("CHILDREN"), + CONS(widget_list, NIL))))); + GCEnable(); + + return (result); +} + +LispObj * +Lisp_XtAddCallback(LispBuiltin *builtin) +/* + xt-add-callback widget callback-name callback &optional client-data + */ +{ + CallbackArgs *arguments; + LispObj *data; + + LispObj *widget, *callback_name, *callback, *client_data; + + client_data = ARGUMENT(3); + callback = ARGUMENT(2); + callback_name = ARGUMENT(1); + widget = ARGUMENT(0); + + if (!CHECKO(widget, xtWidget_t)) + LispDestroy("%s: cannot convert %s to Widget", + STRFUN(builtin), STROBJ(widget)); + + CHECK_STRING(callback_name); + if (!SYMBOLP(callback) && callback->type != LispLambda_t) + LispDestroy("%s: %s cannot be used as a callback", + STRFUN(builtin), STROBJ(callback)); + + if (client_data == UNSPEC) + client_data = NIL; + + data = CONS(widget, CONS(client_data, callback)); + PROTECT(widget, data); + + arguments = XtNew(CallbackArgs); + arguments->data = data; + + XtAddCallback((Widget)(widget->data.opaque.data), THESTR(callback_name), + LispXtCallback, (XtPointer)arguments); + XtAddCallback((Widget)(widget->data.opaque.data), XtNdestroyCallback, + LispXtCleanupCallback, (XtPointer)arguments); + + return (client_data); +} + +LispObj * +Lisp_XtAppAddInput(LispBuiltin *builtin) +/* + xt-app-add-input app-context fileno condition function &optional client-data + */ +{ + LispObj *data, *input; + XtAppContext appcon; + int source, condition; + CallbackArgs *arguments; + XtInputId id; + + LispObj *app_context, *fileno, *ocondition, *function, *client_data; + + client_data = ARGUMENT(4); + function = ARGUMENT(3); + ocondition = ARGUMENT(2); + fileno = ARGUMENT(1); + app_context = ARGUMENT(0); + + if (!CHECKO(app_context, xtAppContext_t)) + LispDestroy("%s: cannot convert %s to XtAppContext", + STRFUN(builtin), STROBJ(app_context)); + appcon = (XtAppContext)(app_context->data.opaque.data); + + CHECK_LONGINT(fileno); + source = LONGINT_VALUE(fileno); + + CHECK_FIXNUM(ocondition); + condition = FIXNUM_VALUE(ocondition); + + if (!SYMBOLP(function) && function->type != LispLambda_t) + LispDestroy("%s: %s cannot be used as a callback", + STRFUN(builtin), STROBJ(function)); + + /* client data optional */ + if (client_data == UNSPEC) + client_data = NIL; + + data = CONS(NIL, CONS(client_data, function)); + + arguments = XtNew(CallbackArgs); + arguments->data = data; + + id = XtAppAddInput(appcon, source, (XtPointer)condition, + LispXtInputCallback, (XtPointer)arguments); + GCDisable(); + input = OPAQUE(id, xtInputId_t); + GCEnable(); + RPLACA(data, input); + PROTECT(input, data); + + if (num_input_list + 1 >= size_input_list) { + ++size_input_list; + input_list = (CallbackArgs**) + XtRealloc((XtPointer)input_list, + sizeof(CallbackArgs*) * size_input_list); + } + input_list[num_input_list++] = arguments; + + return (input); +} + +LispObj * +Lisp_XtRemoveInput(LispBuiltin *builtin) +/* + xt-remove-input input + */ +{ + int i; + XtInputId id; + CallbackArgs *args; + + LispObj *input; + + input = ARGUMENT(0); + + if (!CHECKO(input, xtInputId_t)) + LispDestroy("%s: cannot convert %s to XtInputId", + STRFUN(builtin), STROBJ(input)); + + id = (XtInputId)(input->data.opaque.data); + for (i = 0; i < num_input_list; i++) { + args = input_list[i]; + if (id == (XtInputId)(CAR(args->data)->data.opaque.data)) { + UPROTECT(CAR(args->data), args->data); + XtFree((XtPointer)args); + + if (i + 1 < num_input_list) + memmove(input_list + i, input_list + i + 1, + sizeof(CallbackArgs*) * (num_input_list - i - 1)); + --num_input_list; + + XtRemoveInput(id); + + return (T); + } + } + + return (NIL); +} + +LispObj * +Lisp_XtAppInitialize(LispBuiltin *builtin) +/* + xt-app-initialize app-context-return application-class &optional options fallback-resources + */ +{ + XtAppContext appcon; + Widget shell; + int zero = 0; + Resources *resources = NULL; + String *fallback = NULL; + + LispObj *app_context_return, *application_class, + *options, *fallback_resources; + + fallback_resources = ARGUMENT(3); + options = ARGUMENT(2); + application_class = ARGUMENT(1); + app_context_return = ARGUMENT(0); + + CHECK_SYMBOL(app_context_return); + CHECK_STRING(application_class); + CHECK_LIST(options); + + /* check fallback resources, if given */ + if (fallback_resources != UNSPEC) { + LispObj *string; + int count; + + CHECK_CONS(fallback_resources); + for (string = fallback_resources, count = 0; CONS_P(string); + string = CDR(string), count++) + CHECK_STRING(CAR(string)); + + /* fallback resources was correctly specified */ + fallback = LispMalloc(sizeof(String) * (count + 1)); + for (string = fallback_resources, count = 0; CONS_P(string); + string = CDR(string), count++) + fallback[count] = THESTR(CAR(string)); + fallback[count] = NULL; + } + + shell = XtAppInitialize(&appcon, THESTR(application_class), NULL, + 0, &zero, NULL, fallback, NULL, 0); + if (fallback) + LispFree(fallback); + (void)LispSetVariable(app_context_return, + OPAQUE(appcon, xtAppContext_t), + STRFUN(builtin), 0); + + XtAppAddActions(appcon, actions, XtNumber(actions)); + + if (options != UNSPEC) { + resources = LispConvertResources(options, shell, + GetResourceList(XtClass(shell)), + NULL); + if (resources) { + XtSetValues(shell, resources->args, resources->num_args); + LispFreeResources(resources); + } + } + + return (OPAQUE(shell, xtWidget_t)); +} + +LispObj * +Lisp_XtAppMainLoop(LispBuiltin *builtin) +/* + xt-app-main-loop app-context + */ +{ + LispObj *app_context; + + app_context = ARGUMENT(0); + + if (!CHECKO(app_context, xtAppContext_t)) + LispDestroy("%s: cannot convert %s to XtAppContext", + STRFUN(builtin), STROBJ(app_context)); + + XtAppMainLoop((XtAppContext)(app_context->data.opaque.data)); + + return (NIL); +} + +LispObj * +Lisp_XtAppPending(LispBuiltin *builtin) +/* + xt-app-pending app-context + */ +{ + LispObj *app_context; + + app_context = ARGUMENT(0); + + if (!CHECKO(app_context, xtAppContext_t)) + LispDestroy("%s: cannot convert %s to XtAppContext", + STRFUN(builtin), STROBJ(app_context)); + + return (INTEGER( + XtAppPending((XtAppContext)(app_context->data.opaque.data)))); +} + +LispObj * +Lisp_XtAppProcessEvent(LispBuiltin *builtin) +/* + xt-app-process-event app-context &optional mask + */ +{ + XtInputMask mask; + XtAppContext appcon; + + LispObj *app_context, *omask; + + omask = ARGUMENT(1); + app_context = ARGUMENT(0); + + if (!CHECKO(app_context, xtAppContext_t)) + LispDestroy("%s: cannot convert %s to XtAppContext", + STRFUN(builtin), STROBJ(app_context)); + + appcon = (XtAppContext)(app_context->data.opaque.data); + if (omask == UNSPEC) + mask = XtIMAll; + else { + CHECK_FIXNUM(omask); + mask = FIXNUM_VALUE(omask); + } + + if (mask != (mask & XtIMAll)) + LispDestroy("%s: %d does not fit in XtInputMask %d", + STRFUN(builtin), mask); + + if (mask) + XtAppProcessEvent(appcon, mask); + + return (omask == NIL ? FIXNUM(mask) : omask); +} + +LispObj * +Lisp_XtRealizeWidget(LispBuiltin *builtin) +/* + xt-realize-widget widget + */ +{ + Widget widget; + + LispObj *owidget; + + owidget = ARGUMENT(0); + + if (!CHECKO(owidget, xtWidget_t)) + LispDestroy("%s: cannot convert %s to Widget", + STRFUN(builtin), STROBJ(owidget)); + widget = (Widget)(owidget->data.opaque.data); + XtRealizeWidget(widget); + + if (XtIsSubclass(widget, shellWidgetClass)) { + if (!delete_window) + delete_window = XInternAtom(XtDisplay(widget), + "WM_DELETE_WINDOW", False); + (void)XSetWMProtocols(XtDisplay(widget), XtWindow(widget), + &delete_window, 1); + } + + return (owidget); +} + +LispObj * +Lisp_XtUnrealizeWidget(LispBuiltin *builtin) +/* + xt-unrealize-widget widget + */ +{ + LispObj *widget; + + widget = ARGUMENT(0); + + if (!CHECKO(widget, xtWidget_t)) + LispDestroy("%s: cannot convert %s to Widget", + STRFUN(builtin), STROBJ(widget)); + + XtUnrealizeWidget((Widget)(widget->data.opaque.data)); + + return (widget); +} + +LispObj * +Lisp_XtIsRealized(LispBuiltin *builtin) +/* + xt-is-realized widget + */ +{ + LispObj *widget; + + widget = ARGUMENT(0); + + if (!CHECKO(widget, xtWidget_t)) + LispDestroy("%s: cannot convert %s to Widget", + STRFUN(builtin), STROBJ(widget)); + + return (XtIsRealized((Widget)(widget->data.opaque.data)) ? T : NIL); +} + +LispObj * +Lisp_XtDestroyWidget(LispBuiltin *builtin) +/* + xt-destroy-widget widget + */ +{ + LispObj *widget; + + widget = ARGUMENT(0); + + if (!CHECKO(widget, xtWidget_t)) + LispDestroy("%s: cannot convert %s to Widget", + STRFUN(builtin), STROBJ(widget)); + + XtDestroyWidget((Widget)(widget->data.opaque.data)); + + return (NIL); +} + +#define UNMANAGED 0 +#define MANAGED 1 +#define SHELL 2 +LispObj * +Lisp_XtCreateWidget(LispBuiltin *builtin) +/* + xt-create-widget name widget-class parent &optional arguments + */ +{ + return (LispXtCreateWidget(builtin, UNMANAGED)); +} + +LispObj * +Lisp_XtCreateManagedWidget(LispBuiltin *builtin) +/* + xt-create-managed-widget name widget-class parent &optional arguments + */ +{ + return (LispXtCreateWidget(builtin, MANAGED)); +} + +LispObj * +Lisp_XtCreatePopupShell(LispBuiltin *builtin) +/* + xt-create-popup-shell name widget-class parent &optional arguments + */ +{ + return (LispXtCreateWidget(builtin, SHELL)); +} + +LispObj * +LispXtCreateWidget(LispBuiltin *builtin, int options) +/* + xt-create-widget name widget-class parent &optional arguments + xt-create-managed-widget name widget-class parent &optional arguments + xt-create-popup-shell name widget-class parent &optional arguments + */ +{ + char *name; + WidgetClass widget_class; + Widget widget, parent; + Resources *resources = NULL; + + LispObj *oname, *owidget_class, *oparent, *arguments; + + arguments = ARGUMENT(3); + oparent = ARGUMENT(2); + owidget_class = ARGUMENT(1); + oname = ARGUMENT(0); + + CHECK_STRING(oname); + name = THESTR(oname); + + if (!CHECKO(owidget_class, xtWidgetClass_t)) + LispDestroy("%s: cannot convert %s to WidgetClass", + STRFUN(builtin), STROBJ(owidget_class)); + widget_class = (WidgetClass)(owidget_class->data.opaque.data); + + if (!CHECKO(oparent, xtWidget_t)) + LispDestroy("%s: cannot convert %s to Widget", + STRFUN(builtin), STROBJ(oparent)); + parent = (Widget)(oparent->data.opaque.data); + + CHECK_LIST(arguments); + + if (options == SHELL) + widget = XtCreatePopupShell(name, widget_class, parent, NULL, 0); + else + widget = XtCreateWidget(name, widget_class, parent, NULL, 0); + + if (arguments == UNSPEC || arguments == NIL) + resources = NULL; + else { + resources = LispConvertResources(arguments, widget, + GetResourceList(widget_class), + GetResourceList(XtClass(parent))); + XtSetValues(widget, resources->args, resources->num_args); + } + if (options == MANAGED) + XtManageChild(widget); + if (resources) + LispFreeResources(resources); + + return (OPAQUE(widget, xtWidget_t)); +} + +LispObj * +Lisp_XtGetKeyboardFocusWidget(LispBuiltin *builtin) +/* + xt-get-keyboard-focus-widget widget + */ +{ + LispObj *widget; + + widget = ARGUMENT(0); + + if (!CHECKO(widget, xtWidget_t)) + LispDestroy("%s: cannot convert %s to Widget", + STRFUN(builtin), STROBJ(widget)); + return (OPAQUE(XtGetKeyboardFocusWidget((Widget)(widget->data.opaque.data)), + xtWidget_t)); +} + +LispObj * +Lisp_XtGetValues(LispBuiltin *builtin) +/* + xt-get-values widget arguments + */ +{ + Arg args[1]; + Widget widget; + ResourceList *rlist, *plist; + ResourceInfo *resource; + LispObj *list, *object = NIL, *result, *cons = NIL; + char c1; + short c2; + int c4; +#ifdef LONG64 + long c8; +#endif + + LispObj *owidget, *arguments; + + arguments = ARGUMENT(1); + owidget = ARGUMENT(0); + + if (arguments == NIL) + return (NIL); + + if (!CHECKO(owidget, xtWidget_t)) + LispDestroy("%s: cannot convert %s to Widget", + STRFUN(builtin), STROBJ(owidget)); + widget = (Widget)(owidget->data.opaque.data); + CHECK_CONS(arguments); + + rlist = GetResourceList(XtClass(widget)); + plist = XtParent(widget) ? + GetResourceList(XtClass(XtParent(widget))) : NULL; + + GCDisable(); + result = NIL; + for (list = arguments; CONS_P(list); list = CDR(list)) { + CHECK_STRING(CAR(list)); + if ((resource = GetResourceInfo(THESTR(CAR(list)), rlist, plist)) + == NULL) { + int i; + Widget child; + + for (i = 0; i < rlist->num_resources; i++) { + if (rlist->resources[i]->qtype == qWidget) { + XtSetArg(args[0], + XrmQuarkToString(rlist->resources[i]->qname), + &child); + XtGetValues(widget, args, 1); + if (child && XtParent(child) == widget) { + resource = + GetResourceInfo(THESTR(CAR(list)), + GetResourceList(XtClass(child)), + NULL); + if (resource) + break; + } + } + } + if (resource == NULL) { + LispMessage("%s: resource %s not available", + STRFUN(builtin), THESTR(CAR(list))); + continue; + } + } + switch (resource->size) { + case 1: + XtSetArg(args[0], THESTR(CAR(list)), &c1); + break; + case 2: + XtSetArg(args[0], THESTR(CAR(list)), &c2); + break; + case 4: + XtSetArg(args[0], THESTR(CAR(list)), &c4); + break; +#ifdef LONG64 + case 1: + XtSetArg(args[0], THESTR(CAR(list)), &c8); + break; +#endif + } + XtGetValues(widget, args, 1); + + /* special resources */ + if (resource->qtype == qString) { +#ifdef LONG64 + object = CONS(CAR(list), STRING(c8)); +#else + object = CONS(CAR(list), STRING(c4)); +#endif + } + else if (resource->qtype == qCardinal || resource->qtype == qInt) { +#ifdef LONG64 + if (sizeof(int) == 8) + object = CONS(CAR(list), INTEGER(c8)); + else +#endif + object = CONS(CAR(list), INTEGER(c4)); + } + else { + switch (resource->size) { + case 1: + object = CONS(CAR(list), OPAQUE(c1, 0)); + break; + case 2: + object = CONS(CAR(list), OPAQUE(c2, 0)); + break; + case 4: + object = CONS(CAR(list), OPAQUE(c4, 0)); + break; +#ifdef LONG64 + case 8: + object = CONS(CAR(list), OPAQUE(c8, 0)); + break; +#endif + } + } + + if (result == NIL) + result = cons = CONS(object, NIL); + else { + RPLACD(cons, CONS(object, NIL)); + cons = CDR(cons); + } + } + GCEnable(); + + return (result); +} + +LispObj * +Lisp_XtManageChild(LispBuiltin *builtin) +/* + xt-manage-child widget + */ +{ + LispObj *widget; + + widget = ARGUMENT(0); + + if (!CHECKO(widget, xtWidget_t)) + LispDestroy("%s: cannot convert %s to Widget", + STRFUN(builtin), STROBJ(widget)); + XtManageChild((Widget)(widget->data.opaque.data)); + + return (widget); +} + +LispObj * +Lisp_XtUnmanageChild(LispBuiltin *builtin) +/* + xt-unmanage-child widget + */ +{ + LispObj *widget; + + widget = ARGUMENT(0); + + if (!CHECKO(widget, xtWidget_t)) + LispDestroy("%s: cannot convert %s to Widget", + STRFUN(builtin), STROBJ(widget)); + XtUnmanageChild((Widget)(widget->data.opaque.data)); + + return (widget); +} + +LispObj * +Lisp_XtMapWidget(LispBuiltin *builtin) +/* + xt-map-widget widget + */ +{ + LispObj *widget; + + widget = ARGUMENT(0); + + if (!CHECKO(widget, xtWidget_t)) + LispDestroy("%s: cannot convert %s to Widget", + STRFUN(builtin), STROBJ(widget)); + XtMapWidget((Widget)(widget->data.opaque.data)); + + return (widget); +} + +LispObj * +Lisp_XtUnmapWidget(LispBuiltin *builtin) +/* + xt-unmap-widget widget + */ +{ + LispObj *widget; + + widget = ARGUMENT(0); + + if (!CHECKO(widget, xtWidget_t)) + LispDestroy("%s: cannot convert %s to Widget", + STRFUN(builtin), STROBJ(widget)); + XtUnmapWidget((Widget)(widget->data.opaque.data)); + + return (widget); +} + +LispObj * +Lisp_XtSetMappedWhenManaged(LispBuiltin *builtin) +/* + xt-set-mapped-when-managed widget map-when-managed + */ +{ + LispObj *widget, *map_when_managed; + + map_when_managed = ARGUMENT(1); + widget = ARGUMENT(0); + + if (!CHECKO(widget, xtWidget_t)) + LispDestroy("%s: cannot convert %s to Widget", + STRFUN(builtin), STROBJ(widget)); + + XtSetMappedWhenManaged((Widget)(widget->data.opaque.data), + map_when_managed != NIL); + + return (map_when_managed); +} + +LispObj * +Lisp_XtPopup(LispBuiltin *builtin) +/* + xt-popup widget grab-kind + */ +{ + XtGrabKind kind; + + LispObj *widget, *grab_kind; + + grab_kind = ARGUMENT(1); + widget = ARGUMENT(0); + + if (!CHECKO(widget, xtWidget_t)) + LispDestroy("%s: cannot convert %s to Widget", + STRFUN(builtin), STROBJ(widget)); + CHECK_INDEX(grab_kind); + kind = (XtGrabKind)FIXNUM_VALUE(grab_kind); + if (kind != XtGrabExclusive && kind != XtGrabNone && + kind != XtGrabNonexclusive) + LispDestroy("%s: %d does not fit in XtGrabKind", + STRFUN(builtin), kind); + XtPopup((Widget)(widget->data.opaque.data), kind); + + return (grab_kind); +} + +LispObj * +Lisp_XtPopdown(LispBuiltin *builtin) +/* + xt-popdown widget + */ +{ + LispObj *widget; + + widget = ARGUMENT(0); + + if (!CHECKO(widget, xtWidget_t)) + LispDestroy("%s: cannot convert %s to Widget", + STRFUN(builtin), STROBJ(widget)); + XtPopdown((Widget)(widget->data.opaque.data)); + + return (widget); +} + +LispObj * +Lisp_XtSetKeyboardFocus(LispBuiltin *builtin) +/* + xt-set-keyboard-focus widget descendant + */ +{ + LispObj *widget, *descendant; + + descendant = ARGUMENT(1); + widget = ARGUMENT(0); + + if (!CHECKO(widget, xtWidget_t)) + LispDestroy("%s: cannot convert %s to Widget", + STRFUN(builtin), STROBJ(widget)); + if (!CHECKO(descendant, xtWidget_t)) + LispDestroy("%s: cannot convert %s to Widget", + STRFUN(builtin), STROBJ(descendant)); + XtSetKeyboardFocus((Widget)(widget->data.opaque.data), + (Widget)(descendant->data.opaque.data)); + + return (widget); +} + +LispObj * +Lisp_XtSetSensitive(LispBuiltin *builtin) +/* + xt-set-sensitive widget sensitive + */ +{ + LispObj *widget, *sensitive; + + sensitive = ARGUMENT(1); + widget = ARGUMENT(0); + + if (!CHECKO(widget, xtWidget_t)) + LispDestroy("%s: cannot convert %s to Widget", + STRFUN(builtin), STROBJ(widget)); + XtSetSensitive((Widget)(widget->data.opaque.data), sensitive != NIL); + + return (sensitive); +} + +LispObj * +Lisp_XtSetValues(LispBuiltin *builtin) +/* + xt-set-values widget arguments + */ +{ + Widget widget; + Resources *resources; + + LispObj *owidget, *arguments; + + arguments = ARGUMENT(1); + owidget = ARGUMENT(0); + + if (arguments == NIL) + return (owidget); + + if (!CHECKO(owidget, xtWidget_t)) + LispDestroy("%s: cannot convert %s to Widget", + STRFUN(builtin), STROBJ(owidget)); + widget = (Widget)(owidget->data.opaque.data); + CHECK_CONS(arguments); + resources = LispConvertResources(arguments, widget, + GetResourceList(XtClass(widget)), + XtParent(widget) ? + GetResourceList(XtClass(XtParent(widget))) : + NULL); + XtSetValues(widget, resources->args, resources->num_args); + LispFreeResources(resources); + + return (owidget); +} + +LispObj * +Lisp_XtWidgetToApplicationContext(LispBuiltin *builtin) +/* + xt-widget-to-application-context widget + */ +{ + Widget widget; + XtAppContext appcon; + + LispObj *owidget; + + owidget = ARGUMENT(0); + + if (!CHECKO(owidget, xtWidget_t)) + LispDestroy("%s: cannot convert %s to Widget", + STRFUN(builtin), STROBJ(owidget)); + widget = (Widget)(owidget->data.opaque.data); + appcon = XtWidgetToApplicationContext(widget); + + return (OPAQUE(appcon, xtAppContext_t)); +} + +LispObj * +Lisp_XtDisplay(LispBuiltin *builtin) +/* + xt-display widget + */ +{ + Widget widget; + Display *display; + + LispObj *owidget; + + owidget = ARGUMENT(0); + + if (!CHECKO(owidget, xtWidget_t)) + LispDestroy("%s: cannot convert %s to Widget", + STRFUN(builtin), STROBJ(owidget)); + widget = (Widget)(owidget->data.opaque.data); + display = XtDisplay(widget); + + return (OPAQUE(display, xtDisplay_t)); +} + +LispObj * +Lisp_XtDisplayOfObject(LispBuiltin *builtin) +/* + xt-display-of-object object + */ +{ + Widget widget; + Display *display; + + LispObj *object; + + object = ARGUMENT(0); + + if (!CHECKO(object, xtWidget_t)) + LispDestroy("%s: cannot convert %s to Widget", + STRFUN(builtin), STROBJ(object)); + widget = (Widget)(object->data.opaque.data); + display = XtDisplayOfObject(widget); + + return (OPAQUE(display, xtDisplay_t)); +} + +LispObj * +Lisp_XtScreen(LispBuiltin *builtin) +/* + xt-screen widget + */ +{ + Widget widget; + Screen *screen; + + LispObj *owidget; + + owidget = ARGUMENT(0); + + if (!CHECKO(owidget, xtWidget_t)) + LispDestroy("%s: cannot convert %s to Widget", + STRFUN(builtin), STROBJ(owidget)); + widget = (Widget)(owidget->data.opaque.data); + screen = XtScreen(widget); + + return (OPAQUE(screen, xtScreen_t)); +} + +LispObj * +Lisp_XtScreenOfObject(LispBuiltin *builtin) +/* + xt-screen-of-object object + */ +{ + Widget widget; + Screen *screen; + + LispObj *object; + + object = ARGUMENT(0); + + if (!CHECKO(object, xtWidget_t)) + LispDestroy("%s: cannot convert %s to Widget", + STRFUN(builtin), STROBJ(object)); + widget = (Widget)(object->data.opaque.data); + screen = XtScreenOfObject(widget); + + return (OPAQUE(screen, xtScreen_t)); +} + +LispObj * +Lisp_XtWindow(LispBuiltin *builtin) +/* + xt-window widget + */ +{ + Widget widget; + Window window; + + LispObj *owidget; + + owidget = ARGUMENT(0); + + if (!CHECKO(owidget, xtWidget_t)) + LispDestroy("%s: cannot convert %s to Widget", + STRFUN(builtin), STROBJ(owidget)); + widget = (Widget)(owidget->data.opaque.data); + window = XtWindow(widget); + + return (OPAQUE(window, xtWindow_t)); +} + +LispObj * +Lisp_XtWindowOfObject(LispBuiltin *builtin) +/* + xt-window-of-object widget + */ +{ + Widget widget; + Window window; + + LispObj *object; + + object = ARGUMENT(0); + + if (!CHECKO(object, xtWidget_t)) + LispDestroy("%s: cannot convert %s to Widget", + STRFUN(builtin), STROBJ(object)); + widget = (Widget)(object->data.opaque.data); + window = XtWindowOfObject(widget); + + return (OPAQUE(window, xtWindow_t)); +} + +LispObj * +Lisp_XtAddGrab(LispBuiltin *builtin) +/* + xt-add-grab widget exclusive spring-loaded + */ +{ + Widget widget; + Bool exclusive, spring_loaded; + + LispObj *owidget, *oexclusive, *ospring_loaded; + + ospring_loaded = ARGUMENT(2); + oexclusive = ARGUMENT(1); + owidget = ARGUMENT(0); + + if (!CHECKO(owidget, xtWidget_t)) + LispDestroy("%s: cannot convert %s to Widget", + STRFUN(builtin), STROBJ(owidget)); + widget = (Widget)(owidget->data.opaque.data); + exclusive = oexclusive != NIL; + spring_loaded = ospring_loaded != NIL; + + XtAddGrab(widget, exclusive, spring_loaded); + + return (T); +} + +LispObj * +Lisp_XtRemoveGrab(LispBuiltin *builtin) +/* + xt-remove-grab widget + */ +{ + LispObj *widget; + + widget = ARGUMENT(0); + + if (!CHECKO(widget, xtWidget_t)) + LispDestroy("%s: cannot convert %s to Widget", + STRFUN(builtin), STROBJ(widget)); + + XtRemoveGrab((Widget)(widget->data.opaque.data)); + + return (NIL); +} + +LispObj * +Lisp_XtName(LispBuiltin *builtin) +/* + xt-name widget + */ +{ + LispObj *widget; + + widget = ARGUMENT(0); + + if (!CHECKO(widget, xtWidget_t)) + LispDestroy("%s: cannot convert %s to Widget", + STRFUN(builtin), STROBJ(widget)); + + return (STRING(XtName((Widget)(widget->data.opaque.data)))); +} + +LispObj * +Lisp_XtParent(LispBuiltin *builtin) +/* + xt-parent widget + */ +{ + LispObj *widget; + + widget = ARGUMENT(0); + + if (!CHECKO(widget, xtWidget_t)) + LispDestroy("%s: cannot convert %s to Widget", + STRFUN(builtin), STROBJ(widget)); + + return (OPAQUE(XtParent((Widget)widget->data.opaque.data), xtWidget_t)); +} + +LispObj * +Lisp_XtAppGetExitFlag(LispBuiltin *builtin) +/* + xt-app-get-exit-flag app-context + */ +{ + LispObj *app_context; + + app_context = ARGUMENT(0); + + if (!CHECKO(app_context, xtAppContext_t)) + LispDestroy("%s: cannot convert %s to XtAppContext", + STRFUN(builtin), STROBJ(app_context)); + + return (XtAppGetExitFlag((XtAppContext)(app_context->data.opaque.data)) ? + T : NIL); +} + +LispObj * +Lisp_XtAppSetExitFlag(LispBuiltin *builtin) +/* + xt-app-get-exit-flag app-context + */ +{ + LispObj *app_context; + + app_context = ARGUMENT(0); + + if (!CHECKO(app_context, xtAppContext_t)) + LispDestroy("%s: cannot convert %s to XtAppContext", + STRFUN(builtin), STROBJ(app_context)); + + XtAppSetExitFlag((XtAppContext)(app_context->data.opaque.data)); + + return (T); +} + +static Resources * +LispConvertResources(LispObj *list, Widget widget, + ResourceList *rlist, ResourceList *plist) +{ + char c1; + short c2; + int c4; +#ifdef LONG64 + long c8; +#endif + XrmValue from, to; + LispObj *arg, *val; + ResourceInfo *resource; + char *fname = "XT-CONVERT-RESOURCES"; + Resources *resources = (Resources*)XtCalloc(1, sizeof(Resources)); + + for (; CONSP(list); list = CDR(list)) { + if (!CONSP(CAR(list))) { + XtFree((XtPointer)resources); + LispDestroy("%s: %s is not a cons", fname, STROBJ(CAR(list))); + } + arg = CAR(CAR(list)); + val = CDR(CAR(list)); + + if (!STRINGP(arg)) { + XtFree((XtPointer)resources); + LispDestroy("%s: %s is not a string", fname, STROBJ(arg)); + } + + if ((resource = GetResourceInfo(THESTR(arg), rlist, plist)) == NULL) { + int i; + Arg args[1]; + Widget child; + + for (i = 0; i < rlist->num_resources; i++) { + if (rlist->resources[i]->qtype == qWidget) { + XtSetArg(args[0], + XrmQuarkToString(rlist->resources[i]->qname), + &child); + XtGetValues(widget, args, 1); + if (child && XtParent(child) == widget) { + resource = + GetResourceInfo(THESTR(arg), + GetResourceList(XtClass(child)), + NULL); + if (resource) + break; + } + } + } + if (resource == NULL) { + LispMessage("%s: resource %s not available", + fname, THESTR(arg)); + continue; + } + } + + if (LONGINTP(val) || DFLOATP(val) || OPAQUEP(val)) { + resources->args = (Arg*) + XtRealloc((XtPointer)resources->args, + sizeof(Arg) * (resources->num_args + 1)); + if (!OPAQUEP(val)) { + float fvalue; + + if (DFLOATP(val)) + fvalue = DFLOAT_VALUE(val); + else + fvalue = LONGINT_VALUE(val); + if (resource->qtype == qFloat) { + XtSetArg(resources->args[resources->num_args], + XrmQuarkToString(resource->qname), fvalue); + } + else + XtSetArg(resources->args[resources->num_args], + XrmQuarkToString(resource->qname), + (int)fvalue); + } + else + XtSetArg(resources->args[resources->num_args], + XrmQuarkToString(resource->qname), val->data.opaque.data); + ++resources->num_args; + continue; + } + else if (val == NIL) { + /* XXX assume it is a pointer or a boolean */ +#ifdef DEBUG + LispWarning("%s: assuming %s is a pointer or boolean", + fname, XrmQuarkToString(resource->qname)); +#endif + resources->args = (Arg*) + XtRealloc((XtPointer)resources->args, + sizeof(Arg) * (resources->num_args + 1)); + XtSetArg(resources->args[resources->num_args], + XrmQuarkToString(resource->qname), NULL); + ++resources->num_args; + continue; + } + else if (val == T) { + /* XXX assume it is a boolean */ +#ifdef DEBUG + LispWarning("%s: assuming %s is a boolean", + fname, XrmQuarkToString(resource->qname)); +#endif + resources->args = (Arg*) + XtRealloc((XtPointer)resources->args, + sizeof(Arg) * (resources->num_args + 1)); + XtSetArg(resources->args[resources->num_args], + XrmQuarkToString(resource->qname), True); + ++resources->num_args; + continue; + } + else if (!STRINGP(val)) { + XtFree((XtPointer)resources); + LispDestroy("%s: resource value must be string, number or opaque, not %s", + fname, STROBJ(val)); + } + + from.size = val == NIL ? 1 : strlen(THESTR(val)) + 1; + from.addr = val == NIL ? "" : THESTR(val); + switch (to.size = resource->size) { + case 1: + to.addr = (XtPointer)&c1; + break; + case 2: + to.addr = (XtPointer)&c2; + break; + case 4: + to.addr = (XtPointer)&c4; + break; +#ifdef LONG64 + case 8: + to.addr = (XtPointer)&c8; + break; +#endif + default: + LispWarning("%s: bad resource size %d for %s", + fname, to.size, THESTR(arg)); + continue; + } + + if (qString == resource->qtype) +#ifdef LONG64 + c8 = (long)from.addr; +#else + c4 = (long)from.addr; +#endif + else if (!XtConvertAndStore(widget, XtRString, &from, + XrmQuarkToString(resource->qtype), &to)) + /* The type converter already have printed an error message */ + continue; + + resources->args = (Arg*) + XtRealloc((XtPointer)resources->args, + sizeof(Arg) * (resources->num_args + 1)); + switch (to.size) { + case 1: + XtSetArg(resources->args[resources->num_args], + XrmQuarkToString(resource->qname), c1); + break; + case 2: + XtSetArg(resources->args[resources->num_args], + XrmQuarkToString(resource->qname), c2); + break; + case 4: + XtSetArg(resources->args[resources->num_args], + XrmQuarkToString(resource->qname), c4); + break; +#ifdef LONG64 + case 8: + XtSetArg(resources->args[resources->num_args], + XrmQuarkToString(resource->qname), c8); + break; +#endif + } + ++resources->num_args; + } + + return (resources); +} + +static void +LispFreeResources(Resources *resources) +{ + if (resources) { + XtFree((XtPointer)resources->args); + XtFree((XtPointer)resources); + } +} + +static int +bcmp_action_resource(_Xconst void *string, _Xconst void *resource) +{ + return (strcmp((String)string, + XrmQuarkToString((*(ResourceInfo**)resource)->qname))); +} + +static ResourceInfo * +GetResourceInfo(char *name, ResourceList *rlist, ResourceList *plist) +{ + ResourceInfo **resource = NULL; + + if (rlist->resources) + resource = (ResourceInfo**) + bsearch(name, rlist->resources, rlist->num_resources, + sizeof(ResourceInfo*), bcmp_action_resource); + + if (resource == NULL && plist) { + resource = (ResourceInfo**) + bsearch(name, &plist->resources[plist->num_resources], + plist->num_cons_resources, sizeof(ResourceInfo*), + bcmp_action_resource); + } + + return (resource ? *resource : NULL); +} + +static ResourceList * +GetResourceList(WidgetClass wc) +{ + ResourceList *list; + + if ((list = FindResourceList(wc)) == NULL) + list = CreateResourceList(wc); + + return (list); +} + +static int +bcmp_action_resource_list(_Xconst void *wc, _Xconst void *list) +{ + return ((char*)wc - (char*)((*(ResourceList**)list)->widget_class)); +} + +static ResourceList * +FindResourceList(WidgetClass wc) +{ + ResourceList **list; + + if (!resource_list) + return (NULL); + + list = (ResourceList**) + bsearch(wc, resource_list, num_resource_list, + sizeof(ResourceList*), bcmp_action_resource_list); + + return (list ? *list : NULL); +} + +static int +qcmp_action_resource_list(_Xconst void *left, _Xconst void *right) +{ + return ((char*)((*(ResourceList**)left)->widget_class) - + (char*)((*(ResourceList**)right)->widget_class)); +} + +static ResourceList * +CreateResourceList(WidgetClass wc) +{ + ResourceList *list; + + list = (ResourceList*)XtMalloc(sizeof(ResourceList)); + list->widget_class = wc; + list->num_resources = list->num_cons_resources = 0; + list->resources = NULL; + + resource_list = (ResourceList**) + XtRealloc((XtPointer)resource_list, sizeof(ResourceList*) * + (num_resource_list + 1)); + resource_list[num_resource_list++] = list; + qsort(resource_list, num_resource_list, sizeof(ResourceList*), + qcmp_action_resource_list); + BindResourceList(list); + + return (list); +} + +static int +qcmp_action_resource(_Xconst void *left, _Xconst void *right) +{ + return (strcmp(XrmQuarkToString((*(ResourceInfo**)left)->qname), + XrmQuarkToString((*(ResourceInfo**)right)->qname))); +} + +static void +BindResourceList(ResourceList *list) +{ + XtResourceList xt_list, cons_list; + Cardinal i, num_xt, num_cons; + + XtGetResourceList(list->widget_class, &xt_list, &num_xt); + XtGetConstraintResourceList(list->widget_class, &cons_list, &num_cons); + list->num_resources = num_xt; + list->num_cons_resources = num_cons; + + list->resources = (ResourceInfo**) + XtMalloc(sizeof(ResourceInfo*) * (num_xt + num_cons)); + + for (i = 0; i < num_xt; i++) { + list->resources[i] = (ResourceInfo*)XtMalloc(sizeof(ResourceInfo)); + list->resources[i]->qname = + XrmPermStringToQuark(xt_list[i].resource_name); + list->resources[i]->qtype = + XrmPermStringToQuark(xt_list[i].resource_type); + list->resources[i]->size = xt_list[i].resource_size; + } + + for (; i < num_xt + num_cons; i++) { + list->resources[i] = (ResourceInfo*)XtMalloc(sizeof(ResourceInfo)); + list->resources[i]->qname = + XrmPermStringToQuark(cons_list[i - num_xt].resource_name); + list->resources[i]->qtype = + XrmPermStringToQuark(cons_list[i - num_xt].resource_type); + list->resources[i]->size = cons_list[i - num_xt].resource_size; + } + + XtFree((XtPointer)xt_list); + if (cons_list) + XtFree((XtPointer)cons_list); + + qsort(list->resources, list->num_resources, sizeof(ResourceInfo*), + qcmp_action_resource); + if (num_cons) + qsort(&list->resources[num_xt], list->num_cons_resources, + sizeof(ResourceInfo*), qcmp_action_resource); +} + +/*ARGSUSED*/ +static void +PopdownAction(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + XtPopdown(w); +} + +/*ARGSUSED*/ +static void +QuitAction(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + XtAppSetExitFlag(XtWidgetToApplicationContext(w)); +} |