1/*
2 * Copyright (c) 2001 by The XFree86 Project, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 *
22 * Except as contained in this notice, the name of the XFree86 Project shall
23 * not be used in advertising or otherwise to promote the sale, use or other
24 * dealings in this Software without prior written authorization from the
25 * XFree86 Project.
26 *
27 * Author: Paulo César Pereira de Andrade
28 */
29
30/* $XFree86: xc/programs/xedit/lisp/modules/xaw.c,v 1.15tsi Exp $ */
31
32#include <stdlib.h>
33#include <X11/Intrinsic.h>
34#include <X11/StringDefs.h>
35#include <X11/Xaw/AsciiSink.h>
36#include <X11/Xaw/AsciiSrc.h>
37#include <X11/Xaw/AsciiText.h>
38#include <X11/Xaw/Box.h>
39#include <X11/Xaw/Command.h>
40#include <X11/Xaw/Dialog.h>
41#include <X11/Xaw/Form.h>
42#include <X11/Xaw/Grip.h>
43#include <X11/Xaw/Label.h>
44#include <X11/Xaw/List.h>
45#include <X11/Xaw/MenuButton.h>
46#include <X11/Xaw/MultiSink.h>
47#include <X11/Xaw/MultiSrc.h>
48#include <X11/Xaw/Paned.h>
49#include <X11/Xaw/Panner.h>
50#include <X11/Xaw/Porthole.h>
51#include <X11/Xaw/Repeater.h>
52#include <X11/Xaw/Scrollbar.h>
53#include <X11/Xaw/Simple.h>
54#include <X11/Xaw/SimpleMenu.h>
55#include <X11/Xaw/SmeBSB.h>
56#include <X11/Xaw/Sme.h>
57#include <X11/Xaw/SmeLine.h>
58#include <X11/Xaw/StripChart.h>
59#include <X11/Xaw/Text.h>
60#include <X11/Xaw/TextSink.h>
61#include <X11/Xaw/TextSrc.h>
62#include <X11/Xaw/Tip.h>
63#include <X11/Xaw/Toggle.h>
64#include <X11/Xaw/Tree.h>
65#include <X11/Xaw/Viewport.h>
66#include <X11/Vendor.h>
67#include "lisp/internal.h"
68#include "lisp/private.h"
69
70/*
71 * Types
72 */
73typedef struct {
74    LispObj *object;
75    void *data;
76} WidgetData;
77
78/*
79 * Prototypes
80 */
81int xawLoadModule(void);
82void LispXawCleanupCallback(Widget, XtPointer, XtPointer);
83
84/* until a better/smarter interface be written... */
85LispObj *Lisp_XawCoerceToListReturnStruct(LispBuiltin*);
86LispObj *Lisp_XawScrollbarCoerceToReal(LispBuiltin*);
87
88LispObj *Lisp_XawFormDoLayout(LispBuiltin*);
89LispObj *Lisp_XawListChange(LispBuiltin*);
90LispObj *Lisp_XawListHighlight(LispBuiltin*);
91LispObj *Lisp_XawListUnhighlight(LispBuiltin*);
92LispObj *Lisp_XawTextGetSource(LispBuiltin*);
93LispObj *Lisp_XawTextLastPosition(LispBuiltin*);
94LispObj *Lisp_XawTextReplace(LispBuiltin*);
95LispObj *Lisp_XawTextSearch(LispBuiltin*);
96LispObj *Lisp_XawTextGetInsertionPoint(LispBuiltin*);
97LispObj *Lisp_XawTextSetInsertionPoint(LispBuiltin*);
98LispObj *Lisp_XawScrollbarSetThumb(LispBuiltin*);
99
100/*
101 * Initialization
102 */
103
104static LispBuiltin lispbuiltins[] = {
105    {LispFunction, Lisp_XawCoerceToListReturnStruct, "xaw-coerce-to-list-return-struct opaque"},
106    {LispFunction, Lisp_XawScrollbarCoerceToReal, "xaw-scrollbar-coerce-to-real opaque"},
107
108    {LispFunction, Lisp_XawScrollbarSetThumb, "xaw-scrollbar-set-thumb widget top &optional shown"},
109    {LispFunction, Lisp_XawFormDoLayout, "xaw-form-do-layout widget force"},
110    {LispFunction, Lisp_XawListChange, "xaw-list-change widget list &optional longest resize"},
111    {LispFunction, Lisp_XawListHighlight, "xaw-list-highlight widget index"},
112    {LispFunction, Lisp_XawListUnhighlight, "xaw-list-unhighlight widget"},
113    {LispFunction, Lisp_XawTextGetSource, "xaw-text-get-source widget"},
114    {LispFunction, Lisp_XawTextLastPosition, "xaw-text-last-position widget"},
115    {LispFunction, Lisp_XawTextReplace, "xaw-text-replace widget left right text"},
116    {LispFunction, Lisp_XawTextSearch, "xaw-text-search widget direction text"},
117    {LispFunction, Lisp_XawTextGetInsertionPoint, "xaw-text-get-insertion-point widget"},
118    {LispFunction, Lisp_XawTextSetInsertionPoint, "xaw-text-set-insertion-point widget position"},
119};
120
121LispModuleData xawLispModuleData = {
122    LISP_MODULE_VERSION,
123    xawLoadModule
124};
125
126static int xawWidget_t, xawWidgetClass_t, xawListReturnStruct_t, xawFloatp_t;
127static WidgetData **list_data;
128static int num_list_data;
129
130/*
131 * Implementation
132 */
133int
134xawLoadModule(void)
135{
136    int i;
137    char *fname = "XAW-LOAD-MODULE";
138
139    xawWidget_t = LispRegisterOpaqueType("Widget");
140    xawWidgetClass_t = LispRegisterOpaqueType("WidgetClass");
141    xawListReturnStruct_t = LispRegisterOpaqueType("XawListReturnStruct");
142    xawFloatp_t = LispRegisterOpaqueType("float*");
143
144    LispExecute("(DEFSTRUCT XAW-LIST-RETURN-STRUCT STRING INDEX)\n");
145
146    GCDisable();
147    (void)LispSetVariable(ATOM2("ASCII-SINK-OBJECT-CLASS"),
148			  OPAQUE(asciiSinkObjectClass, xawWidgetClass_t),
149			  fname, 0);
150    (void)LispSetVariable(ATOM2("ASCII-SRC-OBJECT-CLASS"),
151			  OPAQUE(asciiSinkObjectClass, xawWidgetClass_t),
152			  fname, 0);
153    (void)LispSetVariable(ATOM2("ASCII-TEXT-WIDGET-CLASS"),
154			  OPAQUE(asciiTextWidgetClass, xawWidgetClass_t),
155			  fname, 0);
156    (void)LispSetVariable(ATOM2("BOX-WIDGET-CLASS"),
157			  OPAQUE(boxWidgetClass, xawWidgetClass_t),
158			  fname, 0);
159    (void)LispSetVariable(ATOM2("COMMAND-WIDGET-CLASS"),
160			  OPAQUE(commandWidgetClass, xawWidgetClass_t),
161			  fname, 0);
162    (void)LispSetVariable(ATOM2("DIALOG-WIDGET-CLASS"),
163			  OPAQUE(dialogWidgetClass, xawWidgetClass_t),
164			  fname, 0);
165    (void)LispSetVariable(ATOM2("FORM-WIDGET-CLASS"),
166			  OPAQUE(formWidgetClass, xawWidgetClass_t),
167			  fname, 0);
168    (void)LispSetVariable(ATOM2("GRIP-WIDGET-CLASS"),
169			  OPAQUE(gripWidgetClass, xawWidgetClass_t),
170			  fname, 0);
171    (void)LispSetVariable(ATOM2("LABEL-WIDGET-CLASS"),
172			  OPAQUE(labelWidgetClass, xawWidgetClass_t),
173			  fname, 0);
174    (void)LispSetVariable(ATOM2("LIST-WIDGET-CLASS"),
175			  OPAQUE(listWidgetClass, xawWidgetClass_t),
176			  fname, 0);
177    (void)LispSetVariable(ATOM2("MENU-BUTTON-WIDGET-CLASS"),
178			  OPAQUE(menuButtonWidgetClass, xawWidgetClass_t),
179			  fname, 0);
180    (void)LispSetVariable(ATOM2("MULTI-SINK-OBJEC-TCLASS"),
181			  OPAQUE(multiSinkObjectClass, xawWidgetClass_t),
182			  fname, 0);
183    (void)LispSetVariable(ATOM2("MULTI-SRC-OBJECT-CLASS"),
184			  OPAQUE(multiSrcObjectClass, xawWidgetClass_t),
185			  fname, 0);
186    (void)LispSetVariable(ATOM2("PANED-WIDGET-CLASS"),
187			  OPAQUE(panedWidgetClass, xawWidgetClass_t),
188			  fname, 0);
189    (void)LispSetVariable(ATOM2("PANNER-WIDGET-CLASS"),
190			  OPAQUE(pannerWidgetClass, xawWidgetClass_t),
191			  fname, 0);
192    (void)LispSetVariable(ATOM2("PORTHOLE-WIDGET-CLASS"),
193			  OPAQUE(portholeWidgetClass, xawWidgetClass_t),
194			  fname, 0);
195    (void)LispSetVariable(ATOM2("REPEATER-WIDGET-CLASS"),
196			  OPAQUE(repeaterWidgetClass, xawWidgetClass_t),
197			  fname, 0);
198    (void)LispSetVariable(ATOM2("SCROLLBAR-WIDGET-CLASS"),
199			  OPAQUE(scrollbarWidgetClass, xawWidgetClass_t),
200			  fname, 0);
201    (void)LispSetVariable(ATOM2("SIMPLE-MENU-WIDGET-CLASS"),
202			  OPAQUE(simpleMenuWidgetClass, xawWidgetClass_t),
203			  fname, 0);
204    (void)LispSetVariable(ATOM2("SIMPLE-WIDGET-CLASS"),
205			  OPAQUE(simpleWidgetClass, xawWidgetClass_t),
206			  fname, 0);
207    (void)LispSetVariable(ATOM2("SME-BSB-OBJECT-CLASS"),
208			  OPAQUE(smeBSBObjectClass, xawWidgetClass_t),
209			  fname, 0);
210    (void)LispSetVariable(ATOM2("SME-LINE-OBJECT-CLASS"),
211			  OPAQUE(smeLineObjectClass, xawWidgetClass_t),
212			  fname, 0);
213    (void)LispSetVariable(ATOM2("SME-OBJECT-CLASS"),
214			  OPAQUE(smeObjectClass, xawWidgetClass_t),
215			  fname, 0);
216    (void)LispSetVariable(ATOM2("STRIP-CHART-WIDGET-CLASS"),
217			  OPAQUE(stripChartWidgetClass, xawWidgetClass_t),
218			  fname, 0);
219    (void)LispSetVariable(ATOM2("TEXT-WIDGET-CLASS"),
220			  OPAQUE(textWidgetClass, xawWidgetClass_t),
221			  fname, 0);
222    (void)LispSetVariable(ATOM2("TEXT-SINKOBJECT-CLASS"),
223			  OPAQUE(textSinkObjectClass, xawWidgetClass_t),
224			  fname, 0);
225    (void)LispSetVariable(ATOM2("TEXT-SRC-OBJECT-CLASS"),
226			  OPAQUE(textSrcObjectClass, xawWidgetClass_t),
227			  fname, 0);
228    (void)LispSetVariable(ATOM2("TIP-WIDGET-CLASS"),
229			  OPAQUE(tipWidgetClass, xawWidgetClass_t),
230			  fname, 0);
231    (void)LispSetVariable(ATOM2("TOGGLE-WIDGET-CLASS"),
232			  OPAQUE(toggleWidgetClass, xawWidgetClass_t),
233			  fname, 0);
234    (void)LispSetVariable(ATOM2("TREE-WIDGET-CLASS"),
235			  OPAQUE(treeWidgetClass, xawWidgetClass_t),
236			  fname, 0);
237    (void)LispSetVariable(ATOM2("VIEWPORT-WIDGET-CLASS"),
238			  OPAQUE(viewportWidgetClass, xawWidgetClass_t),
239			  fname, 0);
240    (void)LispSetVariable(ATOM2("VENDOR-SHELL-WIDGET-CLASS"),
241			  OPAQUE(vendorShellWidgetClass, xawWidgetClass_t),
242			  fname, 0);
243
244    /* return codes of XawTextReplace */
245    (void)LispSetVariable(ATOM2("XAW-REPLACE-ERROR"),
246			  INTEGER(XawReplaceError), fname, 0);
247    (void)LispSetVariable(ATOM2("XAW-EDIT-DONE"),
248			  INTEGER(XawEditDone), fname, 0);
249    (void)LispSetVariable(ATOM2("XAW-EDIT-ERROR"),
250			  INTEGER(XawEditError), fname, 0);
251    (void)LispSetVariable(ATOM2("XAW-POSITION-ERROR"),
252			  INTEGER(XawPositionError), fname, 0);
253
254    /* return code of XawTextSearch */
255    (void)LispSetVariable(ATOM2("XAW-TEXT-SEARCH-ERROR"),
256			  INTEGER(XawTextSearchError), fname, 0);
257
258    /* enum XawTextScanDirection */
259    (void)LispSetVariable(ATOM2("XAWSD-LEFT"),
260			  INTEGER(XawsdLeft), fname, 0);
261    (void)LispSetVariable(ATOM2("XAWSD-RIGHT"),
262			  INTEGER(XawsdRight), fname, 0);
263    GCEnable();
264
265    for (i = 0; i < sizeof(lispbuiltins) / sizeof(lispbuiltins[0]); i++)
266	LispAddBuiltinFunction(&lispbuiltins[i]);
267
268    return (1);
269}
270
271void
272LispXawCleanupCallback(Widget w, XtPointer user_data, XtPointer call_data)
273{
274    WidgetData *data = (WidgetData*)user_data;
275
276    UPROTECT(CAR(data->object), data->object);
277    XtFree((XtPointer)data->data);
278    XtFree((XtPointer)data);
279}
280
281LispObj *
282Lisp_XawCoerceToListReturnStruct(LispBuiltin *builtin)
283/*
284 xaw-coerce-to-list-return-struct opaque
285 */
286{
287    LispObj *result, *code, *ocod = COD;
288    XawListReturnStruct *retlist;
289
290    LispObj *opaque;
291
292    opaque = ARGUMENT(0);
293
294    if (!CHECKO(opaque, xawListReturnStruct_t))
295	LispDestroy("%s: cannot convert %s to XawListReturnStruct",
296		    STRFUN(builtin), STROBJ(opaque));
297
298    retlist = (XawListReturnStruct*)(opaque->data.opaque.data);
299
300    GCDisable();
301    code = CONS(ATOM("MAKE-XAW-LIST-RETURN-STRUCT"),
302		CONS(KEYWORD("STRING"),
303		       CONS(STRING(retlist->string),
304			    CONS(KEYWORD("INDEX"),
305				 CONS(INTEGER(retlist->list_index), NIL)))));
306    COD = CONS(code, COD);
307    GCEnable();
308
309    result = EVAL(code);
310    COD = ocod;
311
312    return (result);
313}
314
315LispObj *
316Lisp_XawScrollbarCoerceToReal(LispBuiltin *builtin)
317/*
318 xaw-scrollbar-coerce-to-real opaque
319 */
320{
321    float *floatp;
322    double real;
323
324    LispObj *opaque;
325
326    opaque = ARGUMENT(0);
327
328    if (!CHECKO(opaque, xawFloatp_t))
329	LispDestroy("%s: cannot convert %s to float*",
330		    STRFUN(builtin), STROBJ(opaque));
331
332    floatp = (float*)(opaque->data.opaque.data);
333    real = *floatp;
334
335    return (DFLOAT(real));
336}
337
338LispObj *
339Lisp_XawFormDoLayout(LispBuiltin *builtin)
340/*
341 xaw-form-do-layout widget force
342 */
343{
344    int force;
345
346    LispObj *owidget, *oforce;
347
348    oforce = ARGUMENT(1);
349    owidget = ARGUMENT(0);
350
351    if (!CHECKO(owidget, xawWidget_t))
352	LispDestroy("%s: cannot convert %s to Widget",
353		    STRFUN(builtin), STROBJ(owidget));
354
355    force = oforce != NIL;
356    XawFormDoLayout((Widget)(owidget->data.opaque.data), force);
357
358    return (oforce);
359}
360
361LispObj *
362Lisp_XawTextGetSource(LispBuiltin *builtin)
363/*
364 xaw-text-get-source widget
365 */
366{
367    LispObj *owidget;
368
369    owidget = ARGUMENT(0);
370
371    if (!CHECKO(owidget, xawWidget_t))
372	LispDestroy("%s: cannot convert %s to Widget",
373		    STRFUN(builtin), STROBJ(owidget));
374
375    return (OPAQUE(XawTextGetSource((Widget)(owidget->data.opaque.data)),
376		   xawWidget_t));
377}
378
379LispObj *
380Lisp_XawTextLastPosition(LispBuiltin *builtin)
381/*
382 xaw-text-last-position widget
383 */
384{
385    LispObj *owidget;
386
387    owidget = ARGUMENT(0);
388
389    if (!CHECKO(owidget, xawWidget_t))
390	LispDestroy("%s: cannot convert %s to Widget",
391		    STRFUN(builtin), STROBJ(owidget));
392
393    return (FIXNUM(XawTextLastPosition((Widget)(owidget->data.opaque.data))));
394}
395
396LispObj *
397Lisp_XawTextGetInsertionPoint(LispBuiltin *builtin)
398/*
399 xaw-text-get-insertion-point widget
400 */
401{
402    LispObj *owidget;
403
404    owidget = ARGUMENT(0);
405
406    if (!CHECKO(owidget, xawWidget_t))
407	LispDestroy("%s: cannot convert %s to Widget",
408		    STRFUN(builtin), STROBJ(owidget));
409
410    return (FIXNUM(XawTextGetInsertionPoint((Widget)(owidget->data.opaque.data))));
411}
412
413LispObj *
414Lisp_XawTextSetInsertionPoint(LispBuiltin *builtin)
415/*
416 xaw-text-set-insertion-point widget position
417 */
418{
419    Widget widget;
420    XawTextPosition position;
421
422    LispObj *owidget, *oposition;
423
424    oposition = ARGUMENT(1);
425    owidget = ARGUMENT(0);
426
427    if (!CHECKO(owidget, xawWidget_t))
428	LispDestroy("%s: cannot convert %s to Widget",
429		    STRFUN(builtin), STROBJ(owidget));
430    widget = (Widget)(owidget->data.opaque.data);
431
432    CHECK_INDEX(oposition);
433    position = (XawTextPosition)FIXNUM_VALUE(oposition);
434
435    XawTextSetInsertionPoint(widget, position);
436
437    return (oposition);
438}
439
440LispObj *
441Lisp_XawTextReplace(LispBuiltin *builtin)
442/*
443 xaw-text-replace widget left right text
444 */
445{
446    Widget widget;
447    XawTextPosition left, right;
448    XawTextBlock block;
449
450    LispObj *owidget, *oleft, *oright, *otext;
451
452    otext = ARGUMENT(3);
453    oright = ARGUMENT(2);
454    oleft = ARGUMENT(1);
455    owidget = ARGUMENT(0);
456
457    if (!CHECKO(owidget, xawWidget_t))
458	LispDestroy("%s: cannot convert %s to Widget",
459		    STRFUN(builtin), STROBJ(owidget));
460    widget = (Widget)(owidget->data.opaque.data);
461
462    CHECK_INDEX(oleft);
463    left = (XawTextPosition)FIXNUM_VALUE(oleft);
464
465    CHECK_INDEX(oright);
466    right = (XawTextPosition)FIXNUM_VALUE(oright);
467
468    CHECK_STRING(otext);
469    block.firstPos = 0;
470    block.ptr = THESTR(otext);
471    block.length = strlen(block.ptr);
472    block.format = FMT8BIT;
473
474    return (FIXNUM(XawTextReplace(widget, left, right, &block)));
475}
476
477LispObj *
478Lisp_XawTextSearch(LispBuiltin *builtin)
479/*
480 xaw-text-search widget direction text
481 */
482{
483    Widget widget;
484    XawTextScanDirection direction;
485    XawTextBlock block;
486
487    LispObj *owidget, *odirection, *otext;
488
489    otext = ARGUMENT(2);
490    odirection = ARGUMENT(1);
491    owidget = ARGUMENT(0);
492
493    if (!CHECKO(owidget, xawWidget_t))
494	LispDestroy("%s: cannot convert %s to Widget",
495		    STRFUN(builtin), STROBJ(owidget));
496    widget = (Widget)(owidget->data.opaque.data);
497
498    CHECK_INDEX(odirection);
499    direction = (XawTextPosition)FIXNUM_VALUE(odirection);
500    if (direction != XawsdLeft && direction != XawsdRight)
501	LispDestroy("%s: %d does not fit in XawTextScanDirection",
502		    STRFUN(builtin), direction);
503
504    CHECK_STRING(otext);
505    block.firstPos = 0;
506    block.ptr = THESTR(otext);
507    block.length = strlen(block.ptr);
508    block.format = FMT8BIT;
509
510    return (FIXNUM(XawTextSearch(widget, direction, &block)));
511}
512
513LispObj *
514Lisp_XawListChange(LispBuiltin *builtin)
515/*
516 xaw-list-change widget list &optional longest resize
517 */
518{
519    Widget widget;
520    String *list;
521    int i, nitems;
522    int longest;
523    Boolean resize;
524    LispObj *object;
525    WidgetData *data;
526
527    LispObj *owidget, *olist, *olongest, *oresize;
528
529    oresize = ARGUMENT(3);
530    olongest = ARGUMENT(2);
531    olist = ARGUMENT(1);
532    owidget = ARGUMENT(0);
533
534    if (!CHECKO(owidget, xawWidget_t))
535	LispDestroy("%s: cannot convert %s to Widget",
536		    STRFUN(builtin), STROBJ(owidget));
537    widget = (Widget)(owidget->data.opaque.data);
538
539    CHECK_LIST(olist);
540    for (nitems = 0, object = olist; CONSP(object);
541	 ++nitems, object = CDR(object))
542	CHECK_STRING(CAR(object));
543
544    if (olongest != UNSPEC) {
545	CHECK_INDEX(olongest);
546	longest = FIXNUM_VALUE(olongest);
547    }
548    else
549	XtVaGetValues(widget, XtNlongest, &longest, NULL, 0);
550    resize = oresize != UNSPEC && oresize != NIL;
551
552    /* No errors in arguments, build string list */
553    list = (String*)XtMalloc(sizeof(String) * nitems);
554    for (i = 0, object = olist; CONSP(object); i++, object = CDR(object))
555	list[i] = THESTR(CAR(object));
556
557    /* Check if xaw-list-change was already called
558      * for this widget and free previous data */
559    for (i = 0; i < num_list_data; i++)
560	if ((Widget)CAR(list_data[i]->object)->data.opaque.data == widget) {
561	    XtRemoveCallback(widget, XtNdestroyCallback,
562			     LispXawCleanupCallback, list_data[i]);
563	    LispXawCleanupCallback(widget, list_data[i], NULL);
564	    break;
565	}
566
567    if (i >= num_list_data) {
568	++num_list_data;
569	list_data = (WidgetData**)XtRealloc((XtPointer)list_data,
570					    sizeof(WidgetData*) * num_list_data);
571    }
572
573    data = (WidgetData*)XtMalloc(sizeof(WidgetData));
574    data->data = list;
575    list_data[i] = data;
576    data->object = CONS(owidget, olist);
577    PROTECT(owidget, data->object);
578    XtAddCallback(widget, XtNdestroyCallback, LispXawCleanupCallback, data);
579
580    XawListChange(widget, list, nitems, longest, resize);
581
582    return (olist);
583}
584
585LispObj *
586Lisp_XawListHighlight(LispBuiltin *builtin)
587/*
588 xaw-list-highlight widget index
589 */
590{
591    Widget widget;
592    int position;
593
594    LispObj *owidget, *oindex;
595
596    oindex = ARGUMENT(1);
597    owidget = ARGUMENT(0);
598
599    if (!CHECKO(owidget, xawWidget_t))
600	LispDestroy("%s: cannot convert %s to Widget",
601		    STRFUN(builtin), STROBJ(owidget));
602    widget = (Widget)(owidget->data.opaque.data);
603
604    CHECK_INDEX(oindex);
605    position = FIXNUM_VALUE(oindex);
606
607    XawListHighlight(widget, position);
608
609    return (oindex);
610}
611
612LispObj *
613Lisp_XawListUnhighlight(LispBuiltin *builtin)
614/*
615 xaw-list-unhighlight widget
616 */
617{
618    LispObj *owidget;
619
620    owidget = ARGUMENT(0);
621
622    if (!CHECKO(owidget, xawWidget_t))
623	LispDestroy("%s: cannot convert %s to Widget",
624		    STRFUN(builtin), STROBJ(owidget));
625
626    XawListUnhighlight((Widget)(owidget->data.opaque.data));
627
628    return (NIL);
629}
630
631LispObj *
632Lisp_XawScrollbarSetThumb(LispBuiltin *builtin)
633/*
634 xaw-scrollbar-set-thumb widget top &optional shown
635 */
636{
637    Widget widget;
638    double top, shown;
639
640    LispObj *owidget, *otop, *oshown;
641
642    oshown = ARGUMENT(2);
643    otop = ARGUMENT(1);
644    owidget = ARGUMENT(0);
645
646    if (!CHECKO(owidget, xawWidget_t))
647	LispDestroy("%s: cannot convert %s to Widget",
648		    STRFUN(builtin), STROBJ(owidget));
649    widget = (Widget)(owidget->data.opaque.data);
650
651    CHECK_DFLOAT(otop);
652    top = DFLOAT_VALUE(otop);
653
654    if (oshown == UNSPEC)
655	shown = 1.0;
656    else {
657	CHECK_DFLOAT(oshown);
658	shown = DFLOAT_VALUE(oshown);
659    }
660
661    XawScrollbarSetThumb(widget, top, shown);
662
663    return (oshown == UNSPEC ? DFLOAT(shown) : oshown);
664}
665