1/*
2    Title:      X-Windows/Motif Interface.
3
4    Copyright (c) 2000
5        Cambridge University Technical Services Limited
6
7    This library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Lesser General Public
9    License as published by the Free Software Foundation; either
10    version 2.1 of the License, or (at your option) any later version.
11
12    This library is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Lesser General Public License for more details.
16
17    You should have received a copy of the GNU Lesser General Public
18    License along with this library; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20
21*/
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#elif defined(_WIN32)
26#include "winconfig.h"
27#else
28#error "No configuration file"
29#endif
30
31#if (defined(WITH_XWINDOWS))
32// X-Windows is required.
33
34/* xwindows.c */
35
36/* Removed indirection from get_C_* functions SPF 31/10/93 */
37/* Added Handle type 2/11/93 */
38/* Fixed "GetString can only be used once" bug 17/11/93 */
39
40/* Dealing with gcc warning messages SPF 6/1/94 */
41/* Retrofit to old Sun cc SPF 7/1/94 */
42/* 25/1/94 SPF Fixed bug in EmptyVisual (core-dump when v==NULL) */
43
44/* Comment added 4/11/93 SPF
45
46Global Invariants:
47
48(1) Get functions promise not to allocate on the Poly/ML heap
49
50(2) The Poly/ML heap contains pointers into the C heap!
51    As these are only valid for one session, the run-time
52    system records which Poly/ML objects have been created
53    in the current session. Only these objects contain
54    valid C pointers, and so may be dereferenced.
55
56    The "bad" Poly/ML objects are:
57
58Flags      Object                      Bad Field                    Access Function
59-----      ------                      ---------                    ---------------
60M      X_GC_Object             GC               *gc                 GetGC
61       X_Font_Object           Font             *font               GetFont
62       ditto                   XFontStruct     **fs                 GetFS
63       X_Cursor_Object         Cursor           *cursor             GetCursor
64BM     X_Window_Object         Drawable         *drawable           GetDrawable, GetPixmap
65       X_Pixmap_Object         Pixmap           *pixmap             GetDrawable, GetPixmap
66       X_Colormap_Object       Colormap         *cmap               GetColormap
67       X_Visual_Object         Visual          **visual             GetVisual  (* FISHY *)
68B      X_Display_Object        Display          *display            (?) GetDisplay (?)
69       ditto                   XtAppContext      app_context        NONE(?)
70M      X_Widget_Object         Widget           *widget             GetWidget, GetNWidget
71B      X_Trans_Object          XtTranslations    table              GetTrans
72B      X_Acc_Object            XtAccelerators    acc                GetAcc
73
74   WARNING: the above list of unsafe fields was created by SPF
75            and may be incomplete.
76
77   The function CheckExists should be called on these objects
78   before it is safe to use any of the above fields. That's
79   because the object may have been created in a previous ML
80   session, so the pointers that it contains may no longer be
81   valid. Using the appropriate access function listed above
82   guarantees that CheckExists is called.
83
84   Exception: the fields can safely be tested against C's zero
85   (None, Null) even if CheckExists hasn't been called. Note that
86   this is only database-safe because this value is used for
87   uninitialised fields, so it doesn't confuse the garbage-collector.
88
89   For all the above fields EXCEPT display, app_context, table, acc
90   the run-time system creates an indirection object in the Poly heap.
91   These fields don't need an indirection object because the object
92   which contains them is itself a BYTE object.
93
94   This indirection is a byte-object. The indirection is necessary
95   because the garbage collector would object to finding a C pointer
96   in a standard ML labelled record. The alternative would be to store
97   the C pointer as an ML integer, but then we would have to convert
98   back to a C pointer befor we could dereference it.
99
100   For similar reasons, eventMask is also stored as a boxed PolyWord.
101
102  abstype Colormap = Colormap with end; (* X_Colormap_Object *)
103  abstype Cursor   = Cursor   with end; (* X_Cursor_Object   *)
104  abstype Drawable = Drawable with end; (* X_Window_Object, XPixmap_Object *)
105  abstype Font     = Font     with end; (* X_Font_Object     *)
106  abstype GC       = GC       with end; (* X_GC_Object       *)
107  abstype Visual   = Visual   with end; (* X_Visual_Object   *)
108  abstype Display  = Display  with end; (* X_Display_Object  *)
109
110  abstype Widget         = Widget         of int with end;
111  abstype XtAccelerators = XtAccelerators of int with end;
112  abstype XtTranslations = XtTranslations of int with end;
113*/
114
115
116
117/* MLXPoint, MLXRectangle, MLXArc, MLPair, MLTriple added 31/10/93 SPF */
118
119#ifdef HAVE_STDIO_H
120#include <stdio.h>
121#endif
122
123#ifdef HAVE_SYS_TYPES_H
124#include <sys/types.h>
125#endif
126
127#ifdef HAVE_SYS_TIME_H
128#include <sys/time.h>
129#endif
130
131#ifdef HAVE_SIGNAL_H
132#include <signal.h>
133#endif
134
135#ifdef HAVE_STDLIB_H
136#include <stdlib.h>
137#endif
138
139#ifdef HAVE_FCNTL_H
140#include <fcntl.h>
141#endif
142
143#ifdef HAVE_CTYPE_H
144#include <ctype.h>
145#endif
146
147#ifdef HAVE_STDLIB_H
148#include <stdlib.h>
149#endif
150
151#ifdef HAVE_ASSERT_H
152#include <assert.h>
153#endif
154
155#ifdef HAVE_UNISTD_H
156#include <unistd.h>
157#endif
158
159#ifdef HAVE_ALLOCA_H
160#include <alloca.h>
161#endif
162
163#ifdef HAVE_ERRNO_H
164#include <errno.h>
165#endif
166
167/* what goes wrong? ... gid, fd, private15 inaccessible */
168/* THIS NEEDS TO BE FIXED!!!! */
169#define XLIB_ILLEGAL_ACCESS 1       /* We need access to some opaque structures */
170
171/* use prototypes, but make sure we get Booleans, not ints */
172#define NeedWidePrototypes 0
173
174#include <X11/Xlib.h>
175
176#include <X11/keysym.h> /* IsCursorKey, IsFunctionKey, et cetera */
177#include <X11/Xproto.h> /* needed for protocol names such as X_CreateWindow */
178#include <X11/Xatom.h>  /* XA_ATOM, et cetera */
179
180#include <Xm/Xm.h>
181#include <Xm/ArrowB.h>
182#include <Xm/ArrowBG.h>
183#include <Xm/BulletinB.h>
184#include <Xm/CascadeB.h>
185#include <Xm/CascadeBG.h>
186#include <Xm/Command.h>
187#include <Xm/DialogS.h>
188#include <Xm/DrawingA.h>
189#include <Xm/DrawnB.h>
190#include <Xm/FileSB.h>
191#include <Xm/Form.h>
192#include <Xm/Frame.h>
193#include <Xm/Label.h>
194#include <Xm/LabelG.h>
195#include <Xm/List.h>
196#include <Xm/MainW.h>
197#include <Xm/MenuShell.h>
198#include <Xm/MessageB.h>
199#include <Xm/PanedW.h>
200#include <Xm/PushB.h>
201#include <Xm/PushBG.h>
202#include <Xm/RowColumn.h>
203#include <Xm/Scale.h>
204#include <Xm/ScrollBar.h>
205#include <Xm/ScrolledW.h>
206#include <Xm/SelectioB.h>
207#include <Xm/SeparatoG.h>
208#include <Xm/Separator.h>
209#include <Xm/Text.h>
210#include <Xm/TextF.h>
211#include <Xm/ToggleB.h>
212#include <Xm/ToggleBG.h>
213
214/* Motif 1.2 */
215#include <Xm/VendorS.h>
216/* for XmIsDesktopObject */
217#include <Xm/DesktopP.h>
218/* for XmIsExtObject */
219#include <Xm/ExtObjectP.h>
220/* for XmIsShellExt */
221#include <Xm/ShellEP.h>
222/* for XmIsVendorShellExt */
223#include <Xm/VendorSEP.h>
224#if(0)
225/* for XmIsWorldObject */
226/* This is not supported in FreeBSD or Solaris 8. */
227#include <Xm/WorldP.h>
228#endif
229
230#include "globals.h"
231#include "sys.h"
232#include "xwindows.h"
233
234#include "run_time.h"
235#include "arb.h"
236#include "mpoly.h"
237#include "gc.h"
238#include "xcall_numbers.h"
239#include "diagnostics.h"
240#include "processes.h"
241#include "save_vec.h"
242#include "polystring.h"
243#include "scanaddrs.h"
244#include "memmgr.h"
245#include "machine_dep.h"
246#include "processes.h"
247#include "rts_module.h"
248#include "rtsentry.h"
249
250extern "C" {
251    POLYEXTERNALSYMBOL POLYUNSIGNED PolyXWindowsGeneral(FirstArgument threadId, PolyWord params);
252}
253/* The following are only forward so we can declare attributes */
254static void RaiseXWindows(TaskData *taskData, const char *s) __attribute__((noreturn));
255
256
257#define ButtonClickMask (((unsigned)1 << 29))
258
259#define XMASK(m) ((m) &~ButtonClickMask)
260
261#undef SIZEOF
262
263#define debug1(fmt,p1) { /*EMPTY*/ }
264#undef  debug1
265#define debug1(fmt,p1) {if (debugOptions & DEBUG_X) printf(fmt,p1);}
266#define debug3(fmt,p1,p2,p3) {if (debugOptions & DEBUG_X) printf(fmt,p1,p2,p3);}
267
268#define debugCreate(type,value)  debug1("%lx " #type " created\n",(unsigned long)(value))
269#define debugReclaim(type,value) debug1("%lx " #type " reclaimed\n",(unsigned long)(value))
270#define debugReclaimRef(type,value) debug1("%lx " #type " reference reclaimed\n",(unsigned long)(value))
271#define debugRefer(type,value) debug1("%lx " #type " referenced\n",(unsigned long)(value))
272#define debugCreateCallback(MLValue,CValue,CListCell)  debug3("%p Widget callback reference created (%p,%p)\n",CValue,CListCell,MLValue)
273#define debugReclaimCallback(MLValue,CValue,CListCell) debug3("%p Widget callback reference removed (%p,%p)\n",CValue,CListCell,MLValue)
274
275
276/* forward declarations */
277
278static Atom WM_DELETE_WINDOW(Display *d); /* was int SPF 6/1/94 */
279
280#define DEREFDISPLAYHANDLE(h) ((X_Display_Object *)DEREFHANDLE(h))
281#define DEREFWINDOWHANDLE(h)  ((X_Window_Object *)DEREFHANDLE(h))
282#define DEREFXOBJECTHANDLE(h) ((X_Object *)DEREFHANDLE(h))
283
284#define SAVE(x) taskData->saveVec.push(x)
285
286#define Make_int(x) Make_arbitrary_precision(taskData, x)
287#define Make_string(s) SAVE(C_string_to_Poly(taskData, s))
288#define Make_bool(b) Make_arbitrary_precision(taskData, (b) != 0)
289
290#define SIZEOF(x) (sizeof(x)/sizeof(PolyWord))
291
292#define min(a,b) (a < b ? a : b)
293#define max(a,b) (a > b ? a : b)
294
295#define ISNIL(p)  (ML_Cons_Cell::IsNull(p))
296#define NONNIL(p) (!ISNIL(p))
297
298typedef Handle EventHandle;
299
300
301/********************************************************************************/
302/* Objects are created MUTABLE and are FINISHED when all their fields have been */
303/* filled in (assuming they are immutable objects). This is so that we can      */
304/* consider the possibility of storing immutable objects in read-only memory    */
305/* segments (not currently implemented).    SPF 7/12/93                         */
306/********************************************************************************/
307static Handle FINISHED(TaskData *taskData, Handle P)
308{
309    PolyObject *pt = DEREFHANDLE(P);
310    assert(taskData->saveVec.isValidHandle(P));
311    assert(pt->IsMutable());
312    POLYUNSIGNED lengthW = pt->LengthWord();
313    pt->SetLengthWord(lengthW & ~_OBJ_MUTABLE_BIT);
314    return P;
315}
316
317
318static void RaiseXWindows(TaskData *taskData, const char *s)
319{
320  if (mainThreadPhase == MTP_USER_CODE)
321    {
322      raise_exception_string(taskData, EXC_XWindows,s);
323    }
324  else
325    {
326     /* Crash added 7/7/94 SPF */
327     Crash("Tried to raise exception (XWindows \"%s\") during garbage collection\n",s);
328    }
329  /*NOTREACHED*/
330}
331
332
333/* bugfixed 6/12/94 SPF */
334#define RaiseXWindows2(varmessage,constmessage) \
335{ \
336   const char message[] = constmessage; \
337   int n1 = strlen(varmessage); \
338   int n2 = strlen(message); \
339   char *mess = (char *)alloca(n1 + n2 + 1); \
340   strcat(strncpy(mess,varmessage,n1),message); \
341   RaiseXWindows(taskData, mess); \
342   /*NOTREACHED*/ \
343}
344
345static void RaiseRange(TaskData *taskData)
346{
347  raise_exception0(taskData, EXC_size);
348}
349
350typedef unsigned char uchar;
351
352static uchar get_C_uchar(TaskData *taskData, PolyWord a)
353{
354    unsigned u = get_C_ushort(taskData, a);
355
356    if (u >= 256) RaiseRange(taskData);
357
358    return u;
359}
360
361
362/******************************************************************************/
363/*                                                                            */
364/*      String                                                                */
365/*                                                                            */
366/******************************************************************************/
367
368//#define String PolyStringObject
369
370//#define GetString(s) _GetString((PolyWord *)(s))
371/* can only be called TABLESIZE times per X opcode */
372static PolyStringObject *GetString(PolyWord s)
373{
374#define TABLESIZE 5
375  static PolyStringObject string[TABLESIZE];
376  static int index = 0;
377
378  if (! s.IsTagged()) return (PolyStringObject *) s.AsObjPtr();
379
380  index = (index + 1) % TABLESIZE;
381  string[index].length = 1;
382  string[index].chars[0] = UNTAGGED(s);
383
384  return &string[index];
385#undef TABLESIZE
386}
387
388
389/******************************************************************************/
390/*                                                                            */
391/*      XObjects (Type definitions)                                           */
392/*                                                                            */
393/******************************************************************************/
394
395/* We keep a list of all objects created by calls to X.         */
396/* When an object is created we add an entry to the list and    */
397/* return the entry. If the entry becomes inaccessible          */
398/* by the garbage collector then we free the object.            */
399/* The list is created by malloc so that it is not in the heap. */
400
401
402// Types of objects.  These are tagged when they are stored
403// in objects because some objects are not byte objects.
404typedef enum
405{
406  X_GC       = 111,
407  X_Font     = 222,
408  X_Cursor   = 333,
409  X_Window   = 444,
410  X_Pixmap   = 555,
411  X_Colormap = 666,
412  X_Visual   = 777,
413  X_Display  = 888,
414  X_Widget   = 999,
415  X_Trans    = 1111,
416  X_Acc      = 2222
417} X_types;
418
419class X_Object: public PolyObject
420{
421public:
422    X_Object(): type(TAGGED(1)) {} // Just to keep gcc happy
423    PolyWord type;
424};
425
426class X_Trans_Object: public X_Object              /* BYTE object */
427{
428public:
429  XtTranslations table;      /* C value */
430};
431
432class X_Acc_Object: public X_Object               /* BYTE object */
433{
434public:
435  XtAccelerators acc;        /* C value */
436};
437
438class X_Display_Object: public X_Object             /* BYTE object */
439{
440public:
441  Display     *display;     /* C value */
442  unsigned     screen;      /* C value */
443  XtAppContext app_context; /* C value */
444} ;
445
446class X_Font_Object: public X_Object
447{
448public:
449  Font             *font;  /* Token for C value */
450  XFontStruct     **fs;    /* Token for C value */
451  X_Display_Object *ds;    /* Token */
452} ;
453
454class X_Cursor_Object: public X_Object
455{
456public:
457  Cursor           *cursor; /* Token for C value */
458  X_Display_Object *ds;     /* Token */
459} ;
460
461class X_Pixmap_Object: public X_Object
462{
463public:
464  Pixmap           *pixmap;  /* Token for C value */
465  X_Display_Object *ds;      /* Token */
466} ;
467
468class X_Colormap_Object: public X_Object
469{
470public:
471  Colormap         *cmap;  /* Token for C value */
472  X_Display_Object *ds;    /* Token */
473} ;
474
475class X_Widget_Object: public X_Object                    /* MUTABLE */
476{
477public:
478  Widget       *widget;       /* Token for C value */
479  PolyWord     callbackList; /* mutable */
480  PolyWord     state;        /* mutable */
481  X_Display_Object *ds;           /* Token */
482} ;
483
484class X_Visual_Object: public X_Object
485{
486public:
487  Visual          **visual;  /* Token for C value */
488  X_Display_Object *ds;      /* Token */
489} ;
490
491class X_GC_Object: public X_Object                   /* MUTABLE */
492{
493public:
494  GC               *gc;          /* Token for C value */
495  X_Font_Object    *font_object; /* mutable; may be 0 */
496  X_Pixmap_Object  *tile;        /* mutable; may be 0 */
497  X_Pixmap_Object  *stipple;     /* mutable; may be 0 */
498  X_Pixmap_Object  *clipMask;    /* mutable; may be 0 */
499  X_Display_Object *ds;          /* Token */
500} ;
501
502class X_Window_Struct: public X_Object                 /* MUTABLE */
503{
504public:
505  Drawable          *drawable;         /* Token for C value */
506  PolyWord          handler;          /* mutable? */
507  PolyWord          state;            /* mutable? */
508  PolyObject        *eventMask;        /* Token for C value; token itself is mutable */
509  X_Colormap_Object *colormap_object;  /* mutable; may be 0 */
510  X_Cursor_Object   *cursor_object;    /* mutable; may be 0 */
511  X_Pixmap_Object   *backgroundPixmap; /* mutable; may be 0 */
512  X_Pixmap_Object   *borderPixmap;     /* mutable; may be 0 */
513  X_Window_Struct   *parent;           /* may be 0 */
514  X_Display_Object  *ds;               /* Token */
515};
516
517typedef X_Window_Struct X_Window_Object;
518
519
520/******************************************************************************/
521/*                                                                            */
522/*      Forward declarations                                                  */
523/*                                                                            */
524/******************************************************************************/
525static Font           GetFont(TaskData *taskData, X_Object *P);
526static Cursor         GetCursor(TaskData *taskData,X_Object *P);
527static Colormap       GetColormap(TaskData *taskData,X_Object *P);
528static Visual        *GetVisual(TaskData *taskData,X_Object *P);
529static XtTranslations GetTrans(TaskData *taskData,X_Object *P);
530static XtAccelerators GetAcc(TaskData *taskData,X_Object *P);
531static Pixmap         GetPixmap(TaskData *, X_Object *P);
532static Widget         GetNWidget(TaskData *, X_Object *P);
533static Window         GetWindow(TaskData *, X_Object *P);
534static Display       *GetDisplay(TaskData *, X_Object *P);
535
536static void DestroyWindow(X_Object *W);
537static void DestroySubwindows(X_Object *W);
538
539static X_GC_Object     *GCObject(X_Object *P);
540static X_Pixmap_Object *PixmapObject(X_Object *P);
541static X_Widget_Object *WidgetObject(TaskData *, X_Object *P);
542static X_Window_Object *WindowObject(X_Object *P);
543
544/******************************************************************************/
545/*                                                                            */
546/*      C lists (Type definitions)                                            */
547/*                                                                            */
548/******************************************************************************/
549
550typedef struct X_List_struct X_List;
551
552struct X_List_struct
553{
554  X_List   *next;           /* pointer into C heap */
555  X_Object *object;         /* pointer into Poly heap; weak */
556};
557
558typedef struct timeval TimeVal;
559
560/* In C heap */
561typedef struct T_List_struct T_List;
562struct T_List_struct
563{
564  T_List          *next;           /* pointer into C heap */
565  TimeVal          timeout;       /* here */
566  X_Window_Object *window_object; /* pointer into Poly heap, or 0; weak */
567  X_Widget_Object *widget_object; /* pointer into Poly heap, or 0; strong */
568  PolyObject       *alpha;         /* pointer into Poly heap; strong */
569  PolyObject       *handler;       /* pointer into Poly heap; strong */
570  int              expired;       /* here */
571};
572/* NB precisely one of window_object and widget_object should be non-zero */
573
574/* In C heap */
575typedef struct C_List_struct C_List;
576struct C_List_struct
577{
578  PolyObject      *function; /* pointer into Poly heap; strong */
579  X_Widget_Object *widget_object;   /* pointer into Poly heap; strong */
580  C_List          *next;     /* pointer into C heap */
581};
582
583/* lists of X objects currently in Poly heap i.e. those created in this session */
584#define XLISTSIZE 1001 /* must be coprime to 4 ('cos pointers are PolyWord-aligned) */
585static X_List *XList[XLISTSIZE] = {0};
586
587static T_List *TList       = 0; /* C pending messages list, ordered by arrival time */
588static C_List *CList       = 0; /* Acts as root for objects "owned" by C callbacks */
589static PolyWord FList = TAGGED(0); /* ML Callback list - acts as a Root for the Heap */
590static PolyWord GList = TAGGED(0); /* ML Event list - acts as a Root for the Heap */
591
592static Bool callbacks_enabled = False;
593
594
595
596/******************************************************************************/
597/*                                                                            */
598/*      High-speed XList routines                                             */
599/*                                                                            */
600/******************************************************************************/
601
602/* maps an (X_Object *) to an (unsigned); this mapping from must give the same   */
603/* (unsigned) for each (X_Object) for an entire Poly/ML session, even though its */
604/* address may change at every garbage collection.                               */
605/* The way we achieve this is by returning the address of the corresponding C    */
606/* object. Note that since the ML object doesn't necessarily correspond to a real*/
607/* C object, this value may be neither valid nor sensible (but it WILL be a      */
608/* constant).                                                                    */
609/* Unfortunately, we can't do this for GCs or VISUALS, since the actual C object */
610/* contains the id we want, and we can't access the id if we haven't got the     */
611/* object. For these, we return a constant instead.                              */
612static unsigned long hashId(X_Object *P)
613{
614
615#define HASH_GC     0
616#define HASH_VISUAL 1
617
618  switch(UNTAGGED(P->type))
619  {
620    case X_GC:       return HASH_GC;
621    case X_Font:     return (unsigned long)(*(((X_Font_Object*)P)->font));
622    case X_Cursor:   return (unsigned long)(*(((X_Cursor_Object*)P)->cursor));
623    case X_Window:   return (unsigned long)(*(((X_Window_Struct*)P)->drawable));
624    case X_Pixmap:   return (unsigned long)(*(((X_Pixmap_Object*)P)->pixmap));
625    case X_Colormap: return (unsigned long)(*(((X_Colormap_Object*)P)->cmap));
626    case X_Visual:   return HASH_VISUAL;
627    case X_Display:  return (unsigned long)(((X_Display_Object*)P)->display);
628    case X_Widget:   return (unsigned long)(*(((X_Widget_Object*)P)->widget));
629    case X_Trans:    return (unsigned long)(((X_Trans_Object*)P)->table);
630    case X_Acc:      return (unsigned long)(((X_Acc_Object*)P)->acc);
631    default:         Crash ("Bad X_Object type (%d) in hashId",UNTAGGED(P->type));
632  }
633  /*NOTREACHED*/
634}
635
636static void initXList(void)
637{
638  int i;
639
640  for (i = 0; i < XLISTSIZE; i++)
641    {
642      XList[i] = NULL;
643    }
644}
645
646static X_List **hashXList(X_Object *P)
647{
648  unsigned long id = hashId(P);
649  unsigned n  = (id % XLISTSIZE); /* a poor hash function, but good enough for now */
650  return &(XList[n]);
651}
652
653static X_List *findXList(unsigned long id)
654{
655  unsigned n  = (id % XLISTSIZE); /* a poor hash function, but good enough for now */
656  return XList[n];
657}
658
659/******************************************************************************/
660/*                                                                            */
661/*      C lists (Polymorphic functions)                                       */
662/*                                                                            */
663/******************************************************************************/
664// Creates a list from a vector of items.
665
666static Handle CreateList4(TaskData *taskData, unsigned n, void *p, unsigned objSize, Handle (*f)(TaskData *, void *))
667{
668
669    Handle saved = taskData->saveVec.mark();
670    Handle list  = SAVE(ListNull);
671    // Process the vector in reverse order.  That way we can make the
672    // cells as immutable objects rather than having to create them as
673    // mutable and then lock them.
674    while (n)
675    {
676        n--;
677        byte *objP = (byte*)p + objSize*n;
678        Handle value = (* f)(taskData, objP);
679        Handle next  = alloc_and_save(taskData, SIZEOF(ML_Cons_Cell));
680        DEREFLISTHANDLE(next)->h = DEREFWORDHANDLE(value);
681        DEREFLISTHANDLE(next)->t = DEREFLISTHANDLE(list);
682
683        /* reset save vector to stop it overflowing */
684        taskData->saveVec.reset(saved);
685        list = SAVE(DEREFHANDLE(next));
686    }
687
688    return list;
689}
690
691static Handle CreateList4I(TaskData *taskData, unsigned n, void *p, unsigned objSize,
692                           Handle (*f)(TaskData *, void *, unsigned i))
693{
694
695    Handle saved = taskData->saveVec.mark();
696    Handle list  = SAVE(ListNull);
697    while (n)
698    {
699        n--;
700        byte *objP = (byte*)p + objSize*n;
701        Handle value = (* f)(taskData, objP, n);
702        Handle next  = alloc_and_save(taskData, SIZEOF(ML_Cons_Cell));
703        DEREFLISTHANDLE(next)->h = DEREFWORDHANDLE(value);
704        DEREFLISTHANDLE(next)->t = DEREFLISTHANDLE(list);
705
706        /* reset save vector to stop it overflowing */
707        taskData->saveVec.reset(saved);
708        list = SAVE(DEREFHANDLE(next));
709    }
710
711    return list;
712}
713
714static Handle CreateList5(TaskData *taskData, POLYUNSIGNED n, void *p, POLYUNSIGNED objSize,
715                          Handle (*f)(TaskData *, void *, Handle), Handle a1)
716{
717    Handle saved = taskData->saveVec.mark();
718    Handle list  = SAVE(ListNull);
719    // Process the vector in reverse order.  That way we can make the
720    // cells as immutable objects rather than having to create them as
721    // mutable and then lock them.
722    while (n)
723    {
724        n--;
725        byte *objP = (byte*)p + objSize*n;
726        Handle value = (* f)(taskData, objP, a1);
727        Handle next  = alloc_and_save(taskData, SIZEOF(ML_Cons_Cell));
728        DEREFLISTHANDLE(next)->h = DEREFWORDHANDLE(value);
729        DEREFLISTHANDLE(next)->t = DEREFLISTHANDLE(list);
730
731        /* reset save vector to stop it overflowing */
732        taskData->saveVec.reset(saved);
733        list = SAVE(DEREFHANDLE(next));
734    }
735
736    return list;
737}
738
739static void GetList4(TaskData *taskData, PolyWord list, void *v, unsigned bytes,
740                     void (*get)(TaskData *, PolyWord, void*, unsigned))
741{
742    unsigned i = 0;
743    byte *s = (byte*)v;
744
745    for(PolyWord p = list; NONNIL(p); p = ((ML_Cons_Cell*)p.AsObjPtr())->t)
746    {
747        (* get)(taskData, ((ML_Cons_Cell*)p.AsObjPtr())->h, s, i);
748        s += bytes;
749        i++;
750    }
751}
752
753/* ListLength no longer requires indirection via handle SPF 4/11/93 */
754static unsigned ListLength(PolyWord list)
755{
756    unsigned  n = 0;
757
758    for(PolyWord p = list; NONNIL(p); p = ((ML_Cons_Cell*)p.AsObjPtr())->t) n++;
759
760    return n;
761}
762
763/******************************************************************************/
764/*                                                                            */
765/*      TList Purge Functions (SPF 29/11/93)                                  */
766/*                                                                            */
767/******************************************************************************/
768static void PurgePendingWidgetMessages(X_Widget_Object *P)
769{
770  T_List **T = &TList;
771
772  while(*T)
773  {
774    T_List *t = *T;
775
776    if (t->widget_object == P)  /* clear out pending messages for this widget */
777    {
778      *T = t->next;
779      free(t);
780    }
781    else T = &t->next;
782  }
783}
784
785static void PurgePendingWindowMessages(X_Window_Object *P)
786{
787  T_List **T = &TList;
788
789  while(*T)
790  {
791    T_List *t = *T;
792
793    if (t->window_object == P)  /* clear out pending messages for this window */
794    {
795      *T = t->next;
796      free(t);
797    }
798    else T = &t->next;
799  }
800}
801
802/******************************************************************************/
803/*                                                                            */
804/*      CList Purge Functions (SPF 29/2/96)                                   */
805/*                                                                            */
806/******************************************************************************/
807static void PurgeCCallbacks(X_Widget_Object *P, Widget w)
808{
809  C_List **C = &CList;
810
811  while(*C)
812  {
813    C_List *c = *C;
814
815    if (c->widget_object == P)  /* clear out callback info for this widget */
816    {
817      debugReclaimCallback(P,w,c);
818      *C = c->next;
819      free(c);
820    }
821    else C = &c->next;
822  }
823}
824
825/******************************************************************************/
826/*                                                                            */
827/*      XObjects (Polymorphic functions 1)                                    */
828/*                                                                            */
829/******************************************************************************/
830static int ResourceExists(X_Object *P)
831{
832  X_List *L;
833
834  for(L = *hashXList(P); L; L = L->next)
835    {
836      if (L->object == P) return 1;
837    }
838
839  return 0;
840}
841
842/* SafeResourceExists is like ResourceExists but doesn't assume that
843   we actually have a valid X object, so it doesn't use hashing.
844   SPF 6/4/95 */
845static int SafeResourceExists(X_Object *P)
846{
847  unsigned n;
848
849  for (n = 0; n < XLISTSIZE; n++)
850  {
851    X_List *L;
852
853    for(L = XList[n]; L; L = L->next)
854      {
855    if (L->object == P) return 1;
856      }
857  }
858  return 0;
859}
860
861static void DestroyXObject(X_Object *P)
862{
863    TaskData *taskData = processes->GetTaskDataForThread();
864
865    X_List **X = hashXList(P);
866
867    switch(UNTAGGED(P->type))
868    {
869    case X_GC:
870        {
871            X_GC_Object *G = GCObject(P);
872
873            GC       gc = *G->gc;
874            Display *d  =  G->ds->display;
875
876            if (gc == DefaultGC(d,G->ds->screen))
877            {
878                debugReclaimRef(GC,gc->gid);
879            }
880            else
881            {
882                debugReclaim(GC,gc->gid);
883                XFreeGC(d,gc); /* SAFE(?) */
884            }
885            break;
886        }
887
888    case X_Font:
889        {
890            Font f = GetFont(taskData, P);
891
892            if (f == None)
893            {
894                debugReclaimRef(Font,f);
895            }
896            else
897            {
898                debugReclaim(Font,f);
899
900#if NEVER
901                XUnloadFont(GetDisplay(taskData, P),f);
902#endif
903            }
904            break;
905        }
906
907    case X_Cursor:
908        {
909            Cursor cursor = GetCursor(taskData, P);
910
911            if (cursor == None)
912            {
913                debugReclaimRef(Cursor,cursor);
914            }
915            else
916            {
917                debugReclaim(Cursor,cursor);
918
919#if NEVER
920                XFreeCursor(GetDisplay(taskData, P),cursor);
921#endif
922            }
923
924            break;
925        }
926
927    case X_Window:
928        {
929            /* added 29/11/93 SPF */
930            PurgePendingWindowMessages(WindowObject(P));
931
932            if (((X_Window_Object *)P)->parent != 0) /* this clients window */
933            {
934                debugReclaim(Window,GetWindow(taskData, P));
935                DestroyWindow(P);
936            }
937            else /* None, ParentRelative, and other clients windows */
938            {
939                debugReclaimRef(Window,GetWindow(taskData, P));
940            }
941            break;
942        }
943
944    case X_Pixmap:
945        {
946            Pixmap pixmap = GetPixmap(taskData, P);
947
948            if (pixmap == None)
949            {
950                debugReclaimRef(Pixmap,pixmap);
951            }
952            else
953            {
954                debugReclaim(Pixmap,pixmap);
955
956#if NEVER
957                XFreePixmap(GetDisplay(taskData, P),pixmap);
958#endif
959            }
960
961            break;
962        }
963
964    case X_Colormap:
965        {
966            Colormap cmap = GetColormap(taskData, P);
967
968            if (cmap == None)
969            {
970                debugReclaimRef(Colormap,cmap);
971            }
972            else
973            {
974                debugReclaim(Colormap,cmap);
975#if NEVER
976                XFreeColormap(GetDisplay(taskData, P),cmap);
977#endif
978            }
979            break;
980        }
981
982    case X_Visual:
983        {
984            Visual *visual = GetVisual(taskData, P);
985
986            debugReclaimRef(Visual,visual->visualid);
987            break;
988        }
989
990    case X_Widget:
991        {
992            Widget widget = GetNWidget(taskData, P);
993
994            PurgePendingWidgetMessages(WidgetObject(taskData, P));
995            debugReclaimRef(Widget,widget);
996            break;
997        }
998
999    case X_Trans:
1000        {
1001            XtTranslations table = GetTrans(taskData, P);
1002
1003            debugReclaimRef(Trans,table);
1004            break;
1005        }
1006
1007    case X_Acc:
1008        {
1009            XtAccelerators acc = GetAcc(taskData, (X_Object *)P);
1010
1011            debugReclaimRef(Acc,acc);
1012            break;
1013        }
1014
1015    default: Crash ("Unknown X_Object type %d",UNTAGGED(P->type));
1016  }
1017
1018  while(*X)
1019  {
1020      X_List *L = *X;
1021
1022      if (L->object == P)
1023      {
1024          *X = L->next;
1025          free(L);
1026          return;
1027      }
1028      else X = &L->next;
1029  }
1030  printf("DestroyXObject: destroy failed\n");
1031}
1032
1033#define CheckExists(P,resource) \
1034{\
1035  if (! ResourceExists(P)) RaiseXWindows(taskData, (char*) "Non-existent " #resource); \
1036}
1037
1038static X_Font_Object *FontObject(X_Object *P)
1039{
1040  assert(UNTAGGED(P->type) == X_Font);
1041
1042  return (X_Font_Object *)P;
1043}
1044
1045static X_Object *FindResource
1046(
1047  Handle   dsHandle,   /* Handle to (X_Display_Object *) */
1048  X_types  type,
1049  unsigned long id,
1050  unsigned long hashid
1051)
1052{
1053  X_List *L;
1054  X_Display_Object *d = (type == X_Widget) ? NULL : DEREFDISPLAYHANDLE(dsHandle);
1055
1056  for(L = findXList(hashid); L; L = L->next)
1057  {
1058    X_Object *P = L->object;
1059
1060    if (UNTAGGED(P->type) == type)
1061    {
1062      switch(type)
1063      {
1064        case X_GC:       if (((X_GC_Object*)P)->ds == d && (*((X_GC_Object*)P)->gc)->gid          == id) return P; break;
1065        case X_Font:     if (((X_Font_Object*)P)->ds == d && (*((X_Font_Object*)P)->font)             == id) return P; break;
1066        case X_Cursor:   if (((X_Cursor_Object*)P)->ds == d && (*((X_Cursor_Object*)P)->cursor)           == id) return P; break;
1067        case X_Window:   if (((X_Window_Object*)P)->ds == d && (*((X_Window_Object*)P)->drawable)         == id) return P; break;
1068        case X_Pixmap:   if (((X_Pixmap_Object*)P)->ds == d && (*((X_Pixmap_Object*)P)->pixmap)           == id) return P; break;
1069        case X_Colormap: if (((X_Colormap_Object*)P)->ds == d && (*((X_Colormap_Object*)P)->cmap)             == id) return P; break;
1070        case X_Visual:   if (((X_Visual_Object*)P)->ds == d && (*((X_Visual_Object*)P)->visual)->visualid == id) return P; break;
1071
1072        case X_Widget:   if (*(((X_Widget_Object*)P)->widget) == (Widget) id) return P; break;
1073
1074        case X_Display:  break;
1075        case X_Trans:    break;
1076        case X_Acc:      break;
1077
1078        default: Crash ("Bad X_Object type (%d) in FindResource", type);
1079      }
1080    }
1081  }
1082
1083  return 0;
1084}
1085
1086// Why are there these casts to unsigned here????
1087#define FindWindow(d,id)   ((X_Window_Object *)   FindResource(d,X_Window,(unsigned long)id,(unsigned long)id))
1088#define FindPixmap(d,id)   ((X_Pixmap_Object *)   FindResource(d,X_Pixmap,(unsigned long)id,(unsigned long)id))
1089#define FindCursor(d,id)   ((X_Cursor_Object *)   FindResource(d,X_Cursor,(unsigned long)id,(unsigned long)id))
1090#define FindFont(d,id)     ((X_Font_Object *)     FindResource(d,X_Font,(unsigned long)id,(unsigned long)id))
1091#define FindColormap(d,id) ((X_Colormap_Object *) FindResource(d,X_Colormap,(unsigned long)id,(unsigned long)id))
1092#define FindWidget(id)     ((X_Widget_Object *)   FindResource((Handle)NULL,X_Widget,(unsigned long)id,(unsigned long)id))
1093
1094/* can't use id for hashing in the following, so use arbitrary values instead */
1095#define FindGC(d,id)       ((X_GC_Object *)       FindResource(d,X_GC,(unsigned long)id,HASH_GC))
1096#define FindVisual(d,id)   ((X_Visual_Object *)   FindResource(d,X_Visual,(unsigned long)id,HASH_VISUAL))
1097
1098static Handle AddXObject(Handle objectHandle)
1099{
1100  X_List **X = hashXList(DEREFXOBJECTHANDLE(objectHandle));
1101  X_List  *L = (X_List *) malloc(sizeof(X_List));
1102
1103  L->next   = *X;
1104  L->object = (X_Object *)DEREFHANDLE(objectHandle);
1105
1106  *X = L;
1107
1108  return objectHandle;
1109}
1110
1111/******************************************************************************/
1112/*                                                                            */
1113/*      MLXPoint - implements ML XPoint datatype                              */
1114/*                                                                            */
1115/******************************************************************************/
1116typedef struct /* depends on XPoint datatype + ML compiler hash function */
1117{
1118    PolyWord    x; /* ML int */
1119    PolyWord    y; /* ML int */
1120} MLXPoint;
1121
1122inline MLXPoint * Point(PolyWord p) { return (MLXPoint *) p.AsObjPtr(); }
1123
1124/* shouldn't these be long values? */
1125inline short GetPointX(TaskData *taskData, PolyWord p) { return get_C_short(taskData, Point(p)->x); }
1126inline short GetPointY(TaskData *taskData, PolyWord p) { return get_C_short(taskData, Point(p)->y); }
1127
1128inline short GetOffsetX(TaskData *taskData, PolyWord p) { return get_C_ushort(taskData, Point(p)->x); }
1129inline short GetOffsetY(TaskData *taskData, PolyWord p) { return get_C_ushort(taskData, Point(p)->y); }
1130
1131static Handle CreatePoint(TaskData *taskData, int x, int y)
1132{
1133  Handle pointHandle = alloc_and_save(taskData, SIZEOF(MLXPoint), F_MUTABLE_BIT);
1134
1135/* Still allocating, so must use explicit DEREF for each element */
1136#define point ((MLXPoint *)DEREFHANDLE(pointHandle))
1137  point->x = DEREFWORD(Make_int(x));
1138  point->y = DEREFWORD(Make_int(y));
1139#undef point
1140
1141  return FINISHED(taskData, pointHandle);
1142}
1143
1144static void GetPoints(TaskData *taskData, PolyWord p, void *v, unsigned)
1145{
1146    XPoint *A = (XPoint *)v;
1147    A->x = GetPointX(taskData, p);
1148    A->y = GetPointY(taskData, p);
1149}
1150
1151/******************************************************************************/
1152/*                                                                            */
1153/*      MLXRectangle - implements ML XRectangle datatype                      */
1154/*                                                                            */
1155/******************************************************************************/
1156
1157typedef struct /* depends on XRectangle datatype + ML compiler hash function */
1158{
1159    PolyWord    top;     /* ML int */
1160    PolyWord    left;    /* ML int */
1161    PolyWord    right;   /* ML int */
1162    PolyWord    bottom;  /* ML int */
1163} MLXRectangle;
1164
1165inline MLXRectangle *Rect(PolyWord R) { return (MLXRectangle *) R.AsObjPtr(); }
1166
1167inline short GetRectTop(TaskData *taskData, PolyWord R)    { return get_C_short(taskData, Rect(R)->top); }
1168inline short GetRectLeft(TaskData *taskData, PolyWord R)   { return get_C_short(taskData, Rect(R)->left); }
1169inline short GetRectRight(TaskData *taskData, PolyWord R)  { return get_C_short(taskData, Rect(R)->right); }
1170inline short GetRectBottom(TaskData *taskData, PolyWord R) { return get_C_short(taskData, Rect(R)->bottom); }
1171
1172#define GetRectX(taskData, R)  GetRectLeft(taskData, R)
1173#define GetRectY(taskData, R)  GetRectTop(taskData, R)
1174
1175/* functions added 29/10/93 SPF */
1176static unsigned GetRectW(TaskData *taskData, PolyWord R)
1177{
1178  long result = GetRectRight(taskData, R) - GetRectLeft(taskData, R);
1179
1180  if (result < 0) RaiseRange(taskData);
1181  return (unsigned)result;
1182}
1183
1184static unsigned GetRectH(TaskData *taskData, PolyWord R)
1185{
1186  long result = GetRectBottom(taskData, R) - GetRectTop(taskData, R);
1187
1188  if (result < 0) RaiseRange(taskData);
1189  return (unsigned)result;
1190}
1191
1192/* static MLXRectangle **CreateRect(top,left,bottom,right) */
1193static Handle CreateRect(TaskData *taskData, int top, int left, int bottom, int right)
1194{
1195  Handle rectHandle = alloc_and_save(taskData, SIZEOF(MLXRectangle), F_MUTABLE_BIT);
1196
1197/* Still allocating, so must use explicit DEREF for each element */
1198#define rect ((MLXRectangle *)DEREFHANDLE(rectHandle))
1199  rect->top    = DEREFWORD(Make_int(top));
1200  rect->left   = DEREFWORD(Make_int(left));
1201  rect->right  = DEREFWORD(Make_int(right));
1202  rect->bottom = DEREFWORD(Make_int(bottom));
1203#undef rect
1204
1205  return FINISHED(taskData, rectHandle);
1206}
1207
1208#define CreateArea(w,h) CreateRect(taskData, 0,0,(int)h,(int)w)
1209
1210static void GetRects(TaskData *taskData, PolyWord p, void *v, unsigned)
1211{
1212    XRectangle *A = (XRectangle *)v;
1213    A->x      = GetRectX(taskData, p);
1214    A->y      = GetRectY(taskData, p);
1215    A->width  = GetRectW(taskData, p);
1216    A->height = GetRectH(taskData, p);
1217}
1218
1219static void CheckZeroRect(TaskData *taskData, PolyWord R)
1220{
1221  unsigned x = GetRectX(taskData, R);
1222  unsigned y = GetRectY(taskData, R);
1223  unsigned w = GetRectW(taskData, R);
1224  unsigned h = GetRectH(taskData, R);
1225
1226  if (x != 0 || y != 0 ||
1227/*     w <= 0 || h <= 0 ||   w,h now unsigned SPF 29/10/93 */
1228       w == 0 || h == 0 ||
1229       w > 65535 || h > 65535) RaiseRange(taskData);
1230}
1231
1232
1233/******************************************************************************/
1234/*                                                                            */
1235/*      MLXArc - implements ML XArc datatype                                  */
1236/*                                                                            */
1237/******************************************************************************/
1238
1239/* MLXArc added 31/10/93 SPF; depends on ML XArc datatype */
1240typedef struct
1241{
1242    PolyWord    r;      /* MMLXRectangle* */
1243    PolyWord    a1;   /* ML int */
1244    PolyWord    a2;   /* ML int */
1245} MLXArc;
1246
1247inline MLXArc *Arc(PolyWord A) { return (MLXArc *) A.AsObjPtr(); }
1248
1249inline PolyWord GetArcR(PolyWord A)  { return Arc(A)->r; }
1250inline short GetArcA1(TaskData *taskData, PolyWord A) { return get_C_short(taskData, Arc(A)->a1); }
1251inline short GetArcA2(TaskData *taskData, PolyWord A) { return get_C_short(taskData, Arc(A)->a2); }
1252
1253static void GetArcs(TaskData *taskData, PolyWord p, void *v, unsigned)
1254{
1255    XArc *A = (XArc *)v;
1256    A->x      = GetRectX(taskData, GetArcR(p));
1257    A->y      = GetRectY(taskData, GetArcR(p));
1258    A->width  = GetRectW(taskData, GetArcR(p));
1259    A->height = GetRectH(taskData, GetArcR(p));
1260    A->angle1 = GetArcA1(taskData, p);
1261    A->angle2 = GetArcA2(taskData, p);
1262}
1263
1264
1265/******************************************************************************/
1266/*                                                                            */
1267/*      Colormap                                                              */
1268/*                                                                            */
1269/******************************************************************************/
1270
1271static X_Colormap_Object *ColormapObject(X_Object *P)
1272{
1273  assert(UNTAGGED(P->type) == X_Colormap);
1274
1275  return (X_Colormap_Object *)P;
1276}
1277
1278static Colormap GetColormap(TaskData *taskData, X_Object *P)
1279{
1280  assert(UNTAGGED(P->type) == X_Colormap);
1281
1282  /* val NoColormap = xcall (23,0) : Colormap; */
1283  /* special case for NoColormap - correct(?) */
1284  if ( *(((X_Colormap_Object *)P)->cmap) == None) return None;
1285
1286  CheckExists(P,colormap);
1287
1288  return *(((X_Colormap_Object *)P)->cmap);
1289}
1290
1291static Handle EmptyColormap
1292(
1293  TaskData *taskData,
1294  Handle   dsHandle /* Handle to (X_Display_Object *) */,
1295  Colormap id
1296)
1297{
1298  X_Colormap_Object *E = FindColormap(dsHandle,id);
1299
1300  if (E)
1301  {
1302    return SAVE(E);
1303  }
1304  else
1305  {
1306    Handle objectHandle = alloc_and_save(taskData, SIZEOF(X_Colormap_Object), F_MUTABLE_BIT);
1307    Handle cmapHandle   = alloc_and_save(taskData, 1, F_MUTABLE_BIT | F_BYTE_OBJ);
1308
1309    /* Must do all allocations before we do the first dereference */
1310    X_Colormap_Object *object = (X_Colormap_Object *)DEREFHANDLE(objectHandle);
1311    Colormap          *cmap   = (Colormap *)DEREFHANDLE(cmapHandle);
1312
1313    *cmap = id; FINISHED(taskData, cmapHandle);
1314
1315    object->type = TAGGED(X_Colormap);
1316    object->cmap = cmap;
1317    object->ds   = DEREFDISPLAYHANDLE(dsHandle);
1318
1319    debugRefer(Colormap,id);
1320
1321    return AddXObject(FINISHED(taskData, objectHandle));
1322  }
1323}
1324
1325
1326/******************************************************************************/
1327/*                                                                            */
1328/*      Visual                                                                */
1329/*                                                                            */
1330/******************************************************************************/
1331static Visual *GetVisual(TaskData *taskData, X_Object *P)
1332{
1333  static Visual EMPTYVISUAL = { 0 };
1334
1335  assert(UNTAGGED(P->type) == X_Visual);
1336
1337  /* val NoVisual = xcall (24,0) : Visual; */
1338  /* special case for NoVisual */
1339  if (*(((X_Visual_Object *)P)->visual) == None) return &EMPTYVISUAL; /* FISHY (?) */
1340
1341  CheckExists(P,visual);
1342
1343  return *(((X_Visual_Object *)P)->visual);
1344}
1345
1346static Handle EmptyVisual
1347(
1348  TaskData *taskData,
1349  Handle  dsHandle, /* Handle to (X_Display_Object *) */
1350  Visual *v
1351)
1352{
1353  if (v != None)
1354    {
1355      X_Visual_Object *E = FindVisual(dsHandle,v->visualid);
1356
1357      if (E) return SAVE(E);
1358    }
1359
1360  /* else */
1361  {
1362    Handle objectHandle = alloc_and_save(taskData, SIZEOF(X_Visual_Object), F_MUTABLE_BIT);
1363    Handle visualHandle = alloc_and_save(taskData, 1, F_MUTABLE_BIT|F_BYTE_OBJ);
1364
1365    /* Must do all allocations before we do the first dereference */
1366    X_Visual_Object *object = (X_Visual_Object *)DEREFHANDLE(objectHandle);
1367    Visual         **visual = (Visual **)DEREFHANDLE(visualHandle);
1368
1369    *visual = v; FINISHED(taskData, visualHandle);
1370
1371    object->type   = TAGGED(X_Visual);
1372    object->visual = visual;
1373    object->ds     = DEREFDISPLAYHANDLE(dsHandle);
1374
1375    debugRefer(Visual,(v == None) ? None : v->visualid);
1376
1377    return AddXObject(FINISHED(taskData, objectHandle));
1378  }
1379}
1380
1381/******************************************************************************/
1382/*                                                                            */
1383/*      GC                                                                    */
1384/*                                                                            */
1385/******************************************************************************/
1386static X_GC_Object *GCObject(X_Object *P)
1387{
1388  assert(UNTAGGED(P->type) == X_GC);
1389
1390  return (X_GC_Object *)P;
1391}
1392
1393static GC GetGC(TaskData *taskData, X_Object *P)
1394{
1395  assert(UNTAGGED(P->type) == X_GC);
1396
1397  CheckExists(P,gc);
1398
1399  return *(((X_GC_Object *)P)->gc);
1400}
1401
1402
1403static Handle GetDefaultGC(TaskData *taskData, Handle dsHandle /* Handle to (X_Display_Object *) */)
1404{
1405  GC defaultGC =
1406    DefaultGC(DEREFDISPLAYHANDLE(dsHandle)->display,
1407              DEREFDISPLAYHANDLE(dsHandle)->screen);
1408
1409  X_GC_Object *G = FindGC(dsHandle,defaultGC->gid);
1410
1411  if (G)
1412  {
1413    return SAVE(G);
1414  }
1415  else
1416  {
1417    Handle objectHandle = alloc_and_save(taskData, SIZEOF(X_GC_Object), F_MUTABLE_BIT);
1418    Handle GCHandle     = alloc_and_save(taskData, 1, F_MUTABLE_BIT|F_BYTE_OBJ);
1419
1420    /* Must do all allocations before we do the first dereference */
1421    X_GC_Object *object  = (X_GC_Object *)DEREFHANDLE(objectHandle);
1422    GC          *gc      = (GC *)DEREFHANDLE(GCHandle);
1423
1424    *gc = defaultGC; FINISHED(taskData, GCHandle);
1425
1426    debugRefer(GC,defaultGC->gid);
1427
1428    object->type = TAGGED(X_GC);
1429    object->gc   = gc;
1430    object->ds   = DEREFDISPLAYHANDLE(dsHandle);
1431/*
1432    object->font_object = 0;
1433    object->tile        = 0;
1434    object->stipple     = 0;
1435    object->clipMask    = 0;
1436*/
1437
1438    return AddXObject(objectHandle); /* must stay MUTABLE */
1439  }
1440}
1441
1442static void ChangeGC(TaskData *taskData, X_GC_Object *G, unsigned n, PolyWord P)
1443{
1444  XGCValues v;
1445
1446  unsigned mask = 1 << n;
1447
1448  switch(mask)
1449  {
1450    case GCFunction:          v.function           = get_C_ushort(taskData, P); break;
1451    case GCPlaneMask:         v.plane_mask         = get_C_ulong (taskData, P); break;
1452    case GCForeground:        v.foreground         = get_C_ulong (taskData, P); break;
1453    case GCBackground:        v.background         = get_C_ulong (taskData, P); break;
1454    case GCLineWidth:         v.line_width         = get_C_short (taskData, P); break;
1455    case GCLineStyle:         v.line_style         = get_C_ushort(taskData, P); break;
1456    case GCCapStyle:          v.cap_style          = get_C_ushort(taskData, P); break;
1457    case GCJoinStyle:         v.join_style         = get_C_ushort(taskData, P); break;
1458    case GCFillStyle:         v.fill_style         = get_C_ushort(taskData, P); break;
1459    case GCFillRule:          v.fill_rule          = get_C_ushort(taskData, P); break;
1460    case GCTileStipXOrigin:   v.ts_x_origin        = get_C_short (taskData, P); break;
1461    case GCTileStipYOrigin:   v.ts_y_origin        = get_C_short (taskData, P); break;
1462    case GCSubwindowMode:     v.subwindow_mode     = get_C_ushort(taskData, P); break;
1463    case GCGraphicsExposures: v.graphics_exposures = get_C_ushort(taskData, P); break;
1464    case GCClipXOrigin:       v.clip_x_origin      = get_C_short (taskData, P); break;
1465    case GCClipYOrigin:       v.clip_y_origin      = get_C_short (taskData, P); break;
1466    case GCDashOffset:        v.dash_offset        = get_C_ushort(taskData, P); break;
1467    case GCDashList:          v.dashes             = get_C_uchar (taskData, P); break;
1468    case GCArcMode:           v.arc_mode           = get_C_ushort(taskData, P); break;
1469
1470    case GCFont:     v.font = GetFont(taskData, (X_Object *)P.AsObjPtr());
1471                     G->font_object = FontObject((X_Object *)P.AsObjPtr());
1472                     break;
1473
1474    case GCTile:     v.tile = GetPixmap(taskData, (X_Object *)P.AsObjPtr());
1475                     G->tile = PixmapObject((X_Object *)P.AsObjPtr());
1476                     break;
1477
1478    case GCStipple:  v.stipple = GetPixmap(taskData, (X_Object *)P.AsObjPtr());
1479                     G->stipple = PixmapObject((X_Object *)P.AsObjPtr());
1480                     break;
1481
1482    case GCClipMask: v.clip_mask = GetPixmap(taskData, (X_Object *)P.AsObjPtr());
1483                     G->clipMask = PixmapObject((X_Object *)P.AsObjPtr());
1484                     break;
1485
1486    default: Crash ("Bad gc mask %u",mask);
1487  }
1488
1489  XChangeGC(GetDisplay(taskData, (X_Object *)G),GetGC(taskData, (X_Object *)G),mask,&v);
1490}
1491
1492static Handle CreateGC
1493(
1494  TaskData *taskData,
1495  Handle   dsHandle /* Handle to (X_Display_Object *) */,
1496  Drawable w
1497)
1498{
1499  Handle objectHandle = alloc_and_save(taskData, SIZEOF(X_GC_Object), F_MUTABLE_BIT);
1500  Handle GCHandle     = alloc_and_save(taskData, 1, F_MUTABLE_BIT|F_BYTE_OBJ);
1501
1502  /* Must do all allocations before we do the first dereference */
1503  X_GC_Object *object  = (X_GC_Object *)DEREFHANDLE(objectHandle);
1504  GC          *gc      = (GC *)DEREFHANDLE(GCHandle);
1505
1506  *gc = XCreateGC(DEREFDISPLAYHANDLE(dsHandle)->display,w,0,0);
1507  FINISHED(taskData, GCHandle);
1508
1509  debugCreate(GC,(*gc)->gid);
1510
1511  object->type = TAGGED(X_GC);
1512  object->gc   = gc;
1513  object->ds   = DEREFDISPLAYHANDLE(dsHandle);
1514/*
1515  object->font_object = 0;
1516  object->tile        = 0;
1517  object->stipple     = 0;
1518  object->clipMask    = 0;
1519*/
1520  return AddXObject(objectHandle); /* must remain MUTABLE */
1521}
1522
1523
1524/******************************************************************************/
1525/*                                                                            */
1526/*      Window                                                                */
1527/*                                                                            */
1528/******************************************************************************/
1529static X_Window_Object *WindowObject(X_Object *P)
1530
1531{
1532  assert(UNTAGGED(P->type) == X_Window);
1533
1534  return (X_Window_Object *)P;
1535}
1536
1537static Window GetWindow(TaskData *taskData, X_Object *P)
1538{
1539  if (UNTAGGED(P->type) == X_Pixmap)
1540  {
1541    if (*((X_Pixmap_Object*)P)->pixmap == None) return None;
1542
1543    RaiseXWindows(taskData, "Not a window");
1544  }
1545
1546  assert(UNTAGGED(P->type) == X_Window);
1547
1548  CheckExists(P,window);
1549
1550  return *(((X_Window_Object*)P)->drawable);
1551}
1552
1553static Handle EmptyWindow
1554(
1555  TaskData *taskData,
1556  Handle dsHandle, /* Handle to (X_Display_Object *) */
1557  Window w
1558)
1559{
1560  X_Window_Object *W = FindWindow(dsHandle,w);
1561
1562  if (W)
1563  {
1564    return SAVE(W);
1565  }
1566  else
1567  {
1568
1569    Handle objectHandle    = alloc_and_save(taskData, SIZEOF(X_Window_Object), F_MUTABLE_BIT);
1570    Handle eventMaskHandle = alloc_and_save(taskData, 1, F_MUTABLE_BIT|F_BYTE_OBJ);
1571    Handle drawableHandle  = alloc_and_save(taskData, 1, F_MUTABLE_BIT|F_BYTE_OBJ);
1572
1573    /* Must do all allocations before we do the first dereference */
1574    X_Window_Object *object    = DEREFWINDOWHANDLE(objectHandle);
1575    Drawable        *drawable  = (Drawable *)DEREFHANDLE(drawableHandle);
1576    PolyObject      *eventMask = DEREFHANDLE(eventMaskHandle);
1577
1578    *drawable  = w; FINISHED(taskData, drawableHandle);
1579
1580#ifdef nodef
1581    /* DCJM: This gets in the way of trying to handle ButtonPress events -
1582       get rid of it. */
1583    /* so that Motif windows get ButtonClick XEvent structures */
1584    eventMask->Set(0, PolyWord::FromUnsigned(ButtonClickMask)); /* eventMask must remain MUTABLE */
1585#else
1586    eventMask->Set(0, PolyWord::FromUnsigned(0));
1587#endif
1588
1589    object->type      = TAGGED(X_Window);
1590    object->drawable  = drawable;
1591    object->handler   = TAGGED(0);
1592    object->state     = TAGGED(0);
1593    object->eventMask = eventMask;
1594/*
1595    object->colormap_object  = 0;
1596    object->cursor_object    = 0;
1597    object->backgroundPixmap = 0;
1598    object->borderPixmap     = 0;
1599    object->parent           = 0;
1600*/
1601    object->ds        = DEREFDISPLAYHANDLE(dsHandle);
1602
1603    debugRefer(Window,w);
1604
1605    return AddXObject(objectHandle); /* must remain MUTABLE */
1606  }
1607}
1608
1609
1610/******************************************************************************/
1611/*                                                                            */
1612/*      Pixmap                                                                */
1613/*                                                                            */
1614/******************************************************************************/
1615
1616static X_Pixmap_Object *PixmapObject(X_Object *P)
1617{
1618  assert(UNTAGGED(P->type) == X_Pixmap);
1619
1620  return (X_Pixmap_Object *)P;
1621}
1622
1623static Pixmap GetPixmap(TaskData *taskData, X_Object *P)
1624{
1625  if (UNTAGGED(P->type) == X_Window)
1626  {
1627
1628    if (! ResourceExists(P))
1629      {
1630        debug1("Non-existent window %lx\n",(long)P);
1631      }
1632
1633    if (*(((X_Window_Object*)P)->drawable) == None) return None;
1634
1635    RaiseXWindows(taskData, "Not a pixmap");
1636  }
1637
1638  assert(UNTAGGED(P->type) == X_Pixmap);
1639
1640  /* val NoDrawable     = xcall (20,0) : Drawable; */
1641  /* val ParentRelative = xcall (20,1) : Drawable; */
1642
1643  /* special case for NoDrawable */
1644  if (*((X_Pixmap_Object*)P)->pixmap == 0) return None;
1645
1646  /* special case for ParentRelative */
1647  if (*((X_Pixmap_Object*)P)->pixmap == 1) return None;
1648
1649  CheckExists(P,pixmap);
1650
1651  return *(((X_Pixmap_Object*)P)->pixmap);
1652}
1653
1654static Handle EmptyPixmap
1655(
1656  TaskData *taskData,
1657  Handle dsHandle, /* Handle to (X_Display_Object *) */
1658  Pixmap id
1659)
1660{
1661  X_Pixmap_Object *E = FindPixmap(dsHandle,id);
1662
1663  if (E)
1664  {
1665    return SAVE(E);
1666  }
1667  else
1668  {
1669    Handle objectHandle = alloc_and_save(taskData, SIZEOF(X_Pixmap_Object), F_MUTABLE_BIT);
1670    Handle pixmapHandle = alloc_and_save(taskData, 1, F_MUTABLE_BIT|F_BYTE_OBJ);
1671
1672    /* Must do all allocations before we do the first dereference */
1673    X_Pixmap_Object *object  = (X_Pixmap_Object *)DEREFHANDLE(objectHandle);
1674    Pixmap          *pixmap  = (Pixmap *)DEREFHANDLE(pixmapHandle);
1675
1676    *pixmap = id; FINISHED(taskData, pixmapHandle);
1677
1678    object->type   = TAGGED(X_Pixmap);
1679    object->pixmap = pixmap;
1680    object->ds     = DEREFDISPLAYHANDLE(dsHandle);
1681
1682    debugCreate(Pixmap,id);
1683
1684    return AddXObject(FINISHED(taskData, objectHandle));
1685  }
1686}
1687
1688
1689/******************************************************************************/
1690/*                                                                            */
1691/*      Drawable                                                              */
1692/*                                                                            */
1693/******************************************************************************/
1694
1695static Drawable GetDrawable(TaskData *taskData, X_Object *P)
1696{
1697  CheckExists(P,drawable);
1698
1699  switch(UNTAGGED(P->type))
1700  {
1701    case X_Window: return *(((X_Window_Object*)P)->drawable);
1702    case X_Pixmap: return *(((X_Pixmap_Object*)P)->pixmap);
1703    default: Crash ("Bad X_Object type (%d) in GetDrawable",UNTAGGED(P->type));
1704  }
1705
1706  /*NOTREACHED*/
1707}
1708
1709/******************************************************************************/
1710/*                                                                            */
1711/*      DS / Display                                                          */
1712/*                                                                            */
1713/******************************************************************************/
1714static Handle GetDS(TaskData *taskData, X_Object *P)
1715{
1716  X_Display_Object *ds;
1717
1718  CheckExists(P,resource);
1719
1720  switch(UNTAGGED(P->type))
1721  {
1722    case X_GC:       ds = ((X_GC_Object*)P)->ds; break;
1723    case X_Font:     ds = ((X_Font_Object*)P)->ds; break;
1724    case X_Cursor:   ds = ((X_Cursor_Object*)P)->ds; break;
1725    case X_Window:   ds = ((X_Window_Object*)P)->ds; break;
1726    case X_Pixmap:   ds = ((X_Pixmap_Object*)P)->ds; break;
1727    case X_Colormap: ds = ((X_Colormap_Object*)P)->ds; break;
1728    case X_Visual:   ds = ((X_Visual_Object*)P)->ds; break;
1729    case X_Widget:   ds = ((X_Widget_Object*)P)->ds; break;
1730    case X_Display:  ds = (X_Display_Object*)P; break; /* i.e. P cast to the right type */
1731
1732    default: Crash ("Bad X_Object type (%d) in GetDS",UNTAGGED(P->type));
1733  }
1734
1735  assert((PolyWord)ds != TAGGED(0));
1736
1737  return SAVE(ds);
1738}
1739
1740
1741static Display *GetDisplay(TaskData *taskData, X_Object *P)
1742{
1743  CheckExists(P,resource);
1744
1745  switch(UNTAGGED(P->type))
1746  {
1747    case X_GC:       return ((X_GC_Object*)P)->ds->display;
1748    case X_Font:     return ((X_Font_Object*)P)->ds->display;
1749    case X_Cursor:   return ((X_Cursor_Object*)P)->ds->display;
1750    case X_Window:   return ((X_Window_Object*)P)->ds->display;
1751    case X_Pixmap:   return ((X_Pixmap_Object*)P)->ds->display;
1752    case X_Colormap: return ((X_Colormap_Object*)P)->ds->display;
1753    case X_Visual:   return ((X_Visual_Object*)P)->ds->display;
1754    case X_Widget:   return ((X_Widget_Object*)P)->ds->display;
1755    case X_Display:  return ((X_Display_Object*)P)->display;
1756
1757    default:         Crash ("Bad X_Object type (%d) in GetDisplay",UNTAGGED(P->type));
1758  }
1759
1760  /*NOTREACHED*/
1761}
1762
1763
1764/******************************************************************************/
1765/*                                                                            */
1766/*      FS / Font                                                             */
1767/*                                                                            */
1768/******************************************************************************/
1769static Font GetFont(TaskData *taskData, X_Object *P)
1770{
1771  assert(UNTAGGED(P->type) == X_Font);
1772
1773  /* val NoFont = xcall (22,0) : Font; */
1774  /* special case for NoFont - valid(?) */
1775  if (*(((X_Font_Object *)P)->font) == None) return None;
1776
1777  CheckExists(P,font);
1778
1779  return *(((X_Font_Object *)P)->font);
1780}
1781
1782
1783static Handle EmptyFont
1784(
1785  TaskData     *taskData,
1786  Handle       dsHandle, /* Handle to (X_Display_Object *) */
1787  Font         id,
1788  XFontStruct *fs
1789)
1790{
1791  X_Font_Object *E = FindFont(dsHandle,id);
1792
1793  if (E && (fs == NULL || *(E->fs) == fs))
1794  {
1795    return SAVE(E);
1796  }
1797  else
1798  {
1799
1800    Handle objectHandle  = alloc_and_save(taskData, SIZEOF(X_Font_Object), F_MUTABLE_BIT);
1801    Handle fontHandle    = alloc_and_save(taskData, 1, F_MUTABLE_BIT|F_BYTE_OBJ);
1802    Handle FSHandle      = alloc_and_save(taskData, 1, F_MUTABLE_BIT|F_BYTE_OBJ);
1803
1804    /* Must do all allocations before we do the first dereference */
1805    X_Font_Object *object = (X_Font_Object *)DEREFHANDLE(objectHandle);
1806    Font          *font   = (Font *)DEREFHANDLE(fontHandle);
1807    XFontStruct  **xfstr  = (XFontStruct **)DEREFHANDLE(FSHandle);
1808
1809    *font = id; FINISHED(taskData, fontHandle);
1810    *xfstr = fs; FINISHED(taskData, FSHandle);
1811
1812    object->type = TAGGED(X_Font);
1813    object->font = font;
1814    object->fs   = xfstr;
1815    object->ds   = DEREFDISPLAYHANDLE(dsHandle);
1816
1817    debugCreate(Font,id);
1818
1819    return AddXObject(FINISHED(taskData, objectHandle));
1820  }
1821}
1822
1823
1824
1825/******************************************************************************/
1826/*                                                                            */
1827/*      Cursor                                                                */
1828/*                                                                            */
1829/******************************************************************************/
1830static X_Cursor_Object *CursorObject(X_Object *P)
1831{
1832  assert(UNTAGGED(P->type) == X_Cursor);
1833
1834  return (X_Cursor_Object *)P;
1835}
1836
1837static Cursor GetCursor(TaskData *taskData, X_Object *P)
1838{
1839  assert(UNTAGGED(P->type) == X_Cursor);
1840
1841  /* val NoCursor = xcall (21,0) : Cursor; */
1842  /* special case for NoCursor */
1843  if (*(((X_Cursor_Object *)P)->cursor) == None) return None;
1844
1845  CheckExists(P,cursor);
1846
1847  return *(((X_Cursor_Object *)P)->cursor);
1848}
1849
1850
1851static Handle EmptyCursor
1852(
1853  TaskData *taskData,
1854  Handle dsHandle, /* Handle to (X_Display_Object *) */
1855  Cursor id
1856)
1857{
1858  X_Cursor_Object *E = FindCursor(dsHandle,id);
1859
1860  if (E)
1861  {
1862    return SAVE(E);
1863  }
1864  else
1865  {
1866
1867    Handle objectHandle  = alloc_and_save(taskData, SIZEOF(X_Cursor_Object), F_MUTABLE_BIT);
1868    Handle cursorHandle  = alloc_and_save(taskData, 1, F_MUTABLE_BIT|F_BYTE_OBJ);
1869
1870    /* Must do all allocations before we do the first dereference */
1871    X_Cursor_Object *object = (X_Cursor_Object *)DEREFHANDLE(objectHandle);
1872    Cursor          *cursor = (Cursor *)DEREFHANDLE(cursorHandle);
1873
1874    *cursor = id; FINISHED(taskData, cursorHandle);
1875
1876    object->type   = TAGGED(X_Cursor);
1877    object->cursor = cursor;
1878    object->ds     = DEREFDISPLAYHANDLE(dsHandle);
1879
1880    debugRefer(Cursor,id);
1881
1882    return AddXObject(FINISHED(taskData, objectHandle));
1883  }
1884}
1885
1886static Handle CreateFontCursor
1887(
1888  TaskData *taskData,
1889  Handle   dsHandle, /* Handle to (X_Display_Object *) */
1890  unsigned shape
1891)
1892{
1893  return EmptyCursor(taskData, dsHandle,XCreateFontCursor(DEREFDISPLAYHANDLE(dsHandle)->display,shape));
1894}
1895
1896static Handle CreateGlyphCursor
1897(
1898  TaskData *taskData,
1899  Handle    dsHandle, /* Handle to (X_Display_Object *) */
1900  Font      sf,
1901  Font      mf,
1902  unsigned  sc,
1903  unsigned  mc,
1904  XColor   *foreground,
1905  XColor   *background
1906)
1907{
1908  return EmptyCursor(taskData, dsHandle,XCreateGlyphCursor(DEREFDISPLAYHANDLE(dsHandle)->display,sf,mf,sc,mc,foreground,background));
1909}
1910
1911static Handle CreatePixmapCursor
1912(
1913  TaskData *taskData,
1914  Handle    dsHandle, /* Handle to (X_Display_Object *) */
1915  Pixmap    source,
1916  Pixmap    mask,
1917  XColor   *foreground,
1918  XColor   *background,
1919  unsigned  x,
1920  unsigned  y
1921)
1922{
1923  return EmptyCursor(taskData, dsHandle,XCreatePixmapCursor(DEREFDISPLAYHANDLE(dsHandle)->display,source,mask,foreground,background,x,y));
1924}
1925
1926/******************************************************************************/
1927/*                                                                            */
1928/*      Widget                                                                */
1929/*                                                                            */
1930/******************************************************************************/
1931static Widget GetNWidget(TaskData *taskData, X_Object *P)
1932{
1933  assert(UNTAGGED(P->type) == X_Widget);
1934
1935  if (*(((X_Widget_Object *)P)->widget) == NULL) return NULL;
1936
1937  CheckExists(P,widget);
1938
1939  return *(((X_Widget_Object *)P)->widget);
1940}
1941
1942static Widget GetWidget(TaskData *taskData, X_Object *P)
1943{
1944  assert(UNTAGGED(P->type) == X_Widget);
1945
1946  if (*(((X_Widget_Object *)P)->widget) == NULL)
1947    {
1948      RaiseXWindows(taskData, "Not a real widget");
1949    }
1950
1951  CheckExists(P,widget);
1952
1953  return *(((X_Widget_Object *)P)->widget);
1954}
1955
1956/* added 6/11/94 SPF */
1957static Widget GetRealizedWidget(TaskData *taskData, char *where, X_Object *P)
1958{
1959  Widget w;
1960
1961  assert(UNTAGGED(P->type) == X_Widget);
1962
1963  w = *(((X_Widget_Object *)P)->widget);
1964
1965  if (w == NULL)
1966  {
1967     RaiseXWindows2(where,": not a real widget");
1968  }
1969
1970  CheckExists(P,widget);
1971
1972  if (XtIsRealized(w) == False)
1973  {
1974     RaiseXWindows2(where,": widget is not realized");
1975  }
1976
1977  return w;
1978}
1979
1980/* P is a pointer to an X_Widget_Object */
1981static X_Widget_Object *WidgetObjectToken(X_Object *P)
1982{
1983  assert(UNTAGGED(P->type) == X_Widget);
1984  return (X_Widget_Object *)P;
1985}
1986
1987/* P is a pointer to an X_Widget_Object, which is bound to a C widget */
1988static X_Widget_Object *WidgetObject(TaskData *taskData, X_Object *P)
1989{
1990  assert(UNTAGGED(P->type) == X_Widget);
1991
1992  CheckExists(P,widget);
1993
1994  return (X_Widget_Object *)P;
1995}
1996
1997
1998static Handle EmptyWidget
1999(
2000  TaskData *taskData,
2001  Handle dsHandle, /* Handle to (X_Display_Object *) */
2002  Widget id
2003)
2004{
2005  X_Widget_Object *E = FindWidget(id);
2006
2007  if (E)
2008  {
2009    return SAVE(E);
2010  }
2011  else
2012  {
2013
2014    Handle objectHandle = alloc_and_save(taskData, SIZEOF(X_Widget_Object), F_MUTABLE_BIT);
2015    Handle widgetHandle = alloc_and_save(taskData, 1, F_MUTABLE_BIT|F_BYTE_OBJ);
2016
2017    /* Must do all allocations before we do the first dereference */
2018    X_Widget_Object *object = (X_Widget_Object *)DEREFHANDLE(objectHandle);
2019    Widget          *widget = (Widget *)DEREFHANDLE(widgetHandle);
2020
2021    *widget = id; FINISHED(taskData, widgetHandle);
2022
2023    object->type         = TAGGED(X_Widget);
2024    object->widget       = widget;
2025    object->callbackList = ListNull;
2026    object->state        = TAGGED(0);
2027    object->ds           = DEREFDISPLAYHANDLE(dsHandle);
2028
2029    debugRefer(Widget,id);
2030
2031    return AddXObject(objectHandle); /* Must stay MUTABLE */
2032  }
2033}
2034
2035static Handle NewWidget
2036(
2037  TaskData *taskData,
2038  Handle dsHandle, /* Handle to (X_Display_Object *) */
2039  Widget id
2040)
2041{
2042  X_Widget_Object *E = FindWidget(id);
2043
2044  if (E) DestroyXObject((X_Object *)E);
2045
2046  return EmptyWidget(taskData, dsHandle,id);
2047}
2048
2049
2050/******************************************************************************/
2051/*                                                                            */
2052/*      Text Widgets                                                          */
2053/*                                                                            */
2054/******************************************************************************/
2055static Widget GetTextWidget(TaskData *taskData, char *funcname, X_Object *P)
2056{
2057  Widget w = GetWidget(taskData, P);
2058
2059  if (XmIsText(w)) return w;
2060
2061  /* Text operations are also legal on TextField widgets */
2062  if (XmIsTextField(w)) return w;
2063
2064  RaiseXWindows2(funcname,": not a Text or TextField widget");
2065  /*NOTREACHED*/
2066}
2067
2068
2069/******************************************************************************/
2070/*                                                                            */
2071/*      TextField Widgets                                                     */
2072/*                                                                            */
2073/******************************************************************************/
2074static Widget GetTextFieldWidget(TaskData *taskData, char *funcname, X_Object *P)
2075{
2076  Widget w = GetWidget(taskData, P);
2077
2078  if (XmIsTextField(w)) return w;
2079
2080  RaiseXWindows2(funcname,": not a TextField widget");
2081  /*NOTREACHED*/
2082}
2083
2084/******************************************************************************/
2085/*                                                                            */
2086/*      List Widgets                                                          */
2087/*                                                                            */
2088/******************************************************************************/
2089static Widget GetListWidget(TaskData *taskData, char *funcname, X_Object *P)
2090{
2091  Widget w = GetWidget(taskData, P);
2092
2093  if (XmIsList(w)) return w;
2094
2095  RaiseXWindows2(funcname,": not a List widget");
2096  /*NOTREACHED*/
2097}
2098
2099
2100/******************************************************************************/
2101/*                                                                            */
2102/*      Window                                                                */
2103/*                                                                            */
2104/******************************************************************************/
2105static void RemoveWindowEvents(Display *d, Window w)
2106{
2107  XEvent event;
2108
2109  XSync(d,False);
2110
2111  while(XCheckWindowEvent(d,w,~0,&event))
2112  {
2113    /* do nothing */
2114  }
2115}
2116
2117
2118static Handle AddWindow
2119(
2120  TaskData *taskData,
2121  Window W,
2122  Handle handlerHandle, /* Handle to (PolyWord *) (?)  */
2123  Handle stateHandle,   /* Handle to (PolyWord *) (?)  */
2124  Handle parentHandle   /* Handle to (X_Window_Object *) */
2125)
2126{
2127  XWMHints hints;
2128  Atom deleteWindow; /* was int SPF 6/1/94 */
2129  Display *d = GetDisplay(taskData, DEREFXOBJECTHANDLE(parentHandle));
2130
2131  Handle objectHandle    = alloc_and_save(taskData, SIZEOF(X_Window_Object), F_MUTABLE_BIT);
2132  Handle eventMaskHandle = alloc_and_save(taskData, 1, F_MUTABLE_BIT|F_BYTE_OBJ);
2133  Handle drawableHandle  = alloc_and_save(taskData, 1, F_MUTABLE_BIT|F_BYTE_OBJ);
2134
2135  /* Must do all allocations before we do the first dereference */
2136  X_Window_Object *object    = DEREFWINDOWHANDLE(objectHandle);
2137  Drawable        *drawable  = (Drawable *)DEREFHANDLE(drawableHandle);
2138  PolyObject      *eventMask = DEREFHANDLE(eventMaskHandle);
2139
2140  eventMask->Set(0, PolyWord::FromUnsigned(0)); /* eventMask must remain MUTABLE */
2141  *drawable  = W; FINISHED(taskData, drawableHandle);
2142
2143  hints.flags = InputHint;
2144  hints.input = True;
2145
2146  XSetWMHints(d,W,&hints);
2147
2148  deleteWindow = WM_DELETE_WINDOW(d);
2149
2150  if (deleteWindow != None) XSetWMProtocols(d,W,&deleteWindow,1);
2151
2152  debugCreate(Window,W);
2153
2154  object->type      = TAGGED(X_Window);
2155  object->drawable  = drawable;
2156  object->eventMask = eventMask;
2157  object->handler   = DEREFHANDLE(handlerHandle);
2158  object->state     = DEREFHANDLE(stateHandle);
2159  object->parent    = DEREFWINDOWHANDLE(parentHandle);
2160  object->ds        = DEREFWINDOWHANDLE(parentHandle)->ds; /* Tidy up (?) */
2161/*
2162  object->colormap_object  = 0;
2163  object->cursor_object    = 0;
2164  object->backgroundPixmap = 0;
2165  object->borderPixmap     = 0;
2166*/
2167
2168  if (ISNIL(DEREFHANDLE(handlerHandle))) Crash ("No handler set");
2169
2170  return AddXObject(objectHandle); /* object must remain MUTABLE */
2171}
2172
2173static void DestroyWindow(X_Object *W /* Should be a Window Object! */)
2174{
2175    TaskData *taskData = processes->GetTaskDataForThread();
2176  Window   w = GetWindow(taskData, W);
2177  Display *d = GetDisplay(taskData, W);
2178
2179  debugReclaim(Window,w);
2180
2181  XUnmapWindow(d,w);
2182
2183  DestroySubwindows(W);
2184
2185  XDestroyWindow(d,w);
2186
2187  RemoveWindowEvents(d,w);
2188}
2189
2190static Handle CreateSimpleWindow
2191(
2192  TaskData *taskData,
2193  Handle   parent, /* Handle to (X_Window_Object *) */
2194  int      x,
2195  int      y,
2196  unsigned w,
2197  unsigned h,
2198  unsigned borderWidth,
2199  unsigned border,
2200  unsigned background,
2201  Handle   handler, /* Handle to (PolyWord *) (?) */
2202  Handle   state    /* Handle to (PolyWord *) (?) */
2203)
2204{
2205  Window W = XCreateSimpleWindow(GetDisplay(taskData, DEREFXOBJECTHANDLE(parent)),
2206                                   GetWindow(taskData, DEREFXOBJECTHANDLE(parent)),
2207                                   x,y,w,h,
2208                                   borderWidth,border,background);
2209
2210  if (W == 0) RaiseXWindows(taskData, "XCreateSimpleWindow failed");
2211
2212  return AddWindow(taskData,W,handler,state,parent);
2213}
2214
2215static Handle CreateWindow
2216(
2217  TaskData *taskData,
2218  Handle   parent, /* Handle to (X_Window_Object *) */
2219  int      x,
2220  int      y,
2221  unsigned w,
2222  unsigned h,
2223  unsigned borderWidth,
2224  unsigned depth,
2225  unsigned clas,
2226  Visual   *visual,
2227  Handle   handler, /* Handle to (PolyWord *) (?) */
2228  Handle   state    /* Handle to (PolyWord *) (?) */
2229)
2230{
2231  Window W;
2232
2233  W = XCreateWindow(GetDisplay(taskData, DEREFXOBJECTHANDLE(parent)),
2234                      GetWindow(taskData, DEREFXOBJECTHANDLE(parent)),
2235                      x,y,w,h,
2236                      borderWidth,depth,clas,visual,0,0);
2237
2238  if (W == 0) RaiseXWindows(taskData, "XCreateWindow failed");
2239
2240  return AddWindow(taskData,W,handler,state,parent);
2241}
2242
2243static void DestroySubwindows(X_Object *W /* should be a Window object! */)
2244{
2245    TaskData *taskData = processes->GetTaskDataForThread();
2246  Window   root,parent,*children;
2247  unsigned n;
2248  int      s;
2249
2250  Window   w = GetWindow(taskData, W);
2251  Display *d = GetDisplay(taskData, W);
2252
2253  s = XQueryTree(d,w,&root,&parent,&children,&n);
2254
2255  if (s == 0)
2256  {
2257    RaiseXWindows(taskData, "XDestroySubwindows failed");
2258    return;
2259  }
2260
2261  XUnmapSubwindows(d,w);
2262
2263  if (n)
2264  {
2265    Handle dsHandle = GetDS(taskData, W);
2266
2267    while(n--)
2268    {
2269      X_Window_Object *child = FindWindow(dsHandle,children[n]);
2270
2271      if (child) DestroyXObject((X_Object *)child);
2272    }
2273
2274    XFree((char *)children);
2275  }
2276
2277  XDestroySubwindows(d,w);
2278}
2279
2280
2281/******************************************************************************/
2282/*                                                                            */
2283/*      Translations / Accelerators                                           */
2284/*                                                                            */
2285/******************************************************************************/
2286static Handle EmptyTrans(TaskData *taskData, XtTranslations table)
2287{
2288  Handle objectHandle = alloc_and_save(taskData, SIZEOF(X_Trans_Object), F_MUTABLE_BIT|F_BYTE_OBJ);
2289
2290  /* Must do all allocations before we do the first dereference */
2291  X_Trans_Object *object = (X_Trans_Object *)DEREFHANDLE(objectHandle);
2292
2293  /* OK to store C values because this is a byte object */
2294  object->type  = TAGGED(X_Trans);
2295  object->table = table;
2296
2297  debugRefer(Trans,table);
2298
2299  return AddXObject(FINISHED(taskData, objectHandle));
2300}
2301
2302static XtTranslations GetTrans(TaskData *taskData, X_Object *P)
2303{
2304  assert(UNTAGGED(P->type) == X_Trans);
2305
2306  CheckExists(P,trans);
2307
2308  return ((X_Trans_Object *)P)->table;
2309}
2310
2311static Handle EmptyAcc(TaskData *taskData, XtTranslations acc)
2312{
2313
2314  Handle objectHandle = alloc_and_save(taskData, SIZEOF(X_Acc_Object), F_MUTABLE_BIT|F_BYTE_OBJ);
2315
2316  /* Must do all allocations before we do the first dereference */
2317  X_Acc_Object *object = (X_Acc_Object *)DEREFHANDLE(objectHandle);
2318
2319  /* OK to store C values because this is a byte object */
2320  object->type = TAGGED(X_Acc);
2321  object->acc  = acc;
2322
2323  debugRefer(Acc,acc);
2324
2325  return AddXObject(FINISHED(taskData, objectHandle));
2326}
2327
2328static XtAccelerators GetAcc(TaskData *taskData, X_Object *P)
2329{
2330  assert(UNTAGGED(P->type) == X_Acc);
2331
2332  CheckExists(P,acc);
2333
2334  return ((X_Acc_Object *)P)->acc;
2335}
2336
2337/******************************************************************************/
2338/*                                                                            */
2339/*      Utility functions                                                     */
2340/*                                                                            */
2341/******************************************************************************/
2342
2343static XtGrabKind GetXtGrabKind(TaskData *taskData, PolyWord P)
2344{
2345  int i = get_C_long(taskData, P);
2346
2347  /* This encoding must be the same as that used in Motif/ml_bind.ML */
2348  switch (i)
2349  {
2350    case 0:  return XtGrabNone;
2351    case 1:  return XtGrabNonexclusive;
2352    case 2:  return XtGrabExclusive;
2353
2354    default: Crash ("Bad XtGrabKind index (%d) in GetXtGrabKind",i);
2355  }
2356
2357  return XtGrabNone; /* to keep lint/gcc happy */
2358}
2359
2360/******************************************************************************/
2361/*                                                                            */
2362/*      MLXStandardColormap - implements ML XStandardColormap datatype        */
2363/*                                                                            */
2364/******************************************************************************/
2365
2366typedef struct
2367{
2368    X_Colormap_Object *Colormap;
2369    PolyWord          redMax;    /* ML int */
2370    PolyWord          redMult;   /* ML int */
2371    PolyWord          greenMax;  /* ML int */
2372    PolyWord          greenMult; /* ML int */
2373    PolyWord          blueMax;   /* ML int */
2374    PolyWord          blueMult;  /* ML int */
2375    PolyWord          basePixel; /* ML int */
2376    X_Visual_Object   *visual;
2377}  MLXStandardColormap;
2378
2379
2380static void GetStandardColormap(TaskData *taskData, PolyWord p, void *v, unsigned)
2381{
2382    MLXStandardColormap *P = (MLXStandardColormap *)p.AsObjPtr();
2383    XStandardColormap *s = (XStandardColormap *)v;
2384    s->colormap   = GetColormap(taskData, (X_Object *)P->Colormap);
2385
2386    s->red_max    = get_C_ulong(taskData, P->redMax);
2387    s->red_mult   = get_C_ulong(taskData, P->redMult);
2388    s->green_max  = get_C_ulong(taskData, P->greenMax);
2389    s->green_mult = get_C_ulong(taskData, P->greenMult);
2390    s->blue_max   = get_C_ulong(taskData, P->blueMax);
2391    s->blue_mult  = get_C_ulong(taskData, P->blueMult);
2392    s->base_pixel = get_C_ulong(taskData, P->basePixel);
2393
2394    s->visualid   = GetVisual(taskData, (X_Object *)P->visual)->visualid; /* UNSAFE(?) */
2395    s->killid     = None;
2396}
2397
2398static Handle CreateStandardColormap
2399(
2400  TaskData *taskData,
2401  void *v,
2402  Handle dsHandle /* Handle to (X_Display_Object *) */
2403)
2404{
2405    XStandardColormap *s = (XStandardColormap *)v;
2406  XVisualInfo T;
2407  XVisualInfo *info;
2408  int count;
2409
2410  Handle tupleHandle = alloc_and_save(taskData, SIZEOF(MLXStandardColormap), F_MUTABLE_BIT);
2411
2412  T.visualid = s->visualid;
2413  T.visual   = None;
2414
2415  info = XGetVisualInfo(DEREFDISPLAYHANDLE(dsHandle)->display,VisualIDMask,&T,&count);
2416
2417  if (info)
2418  {
2419    T.visual = info->visual;
2420
2421    XFree((char *)info);
2422  }
2423
2424/* Still allocating, so must use explicit DEREF for each element */
2425#define tuple /* hack */((MLXStandardColormap *)DEREFHANDLE(tupleHandle))
2426  tuple->Colormap  = (X_Colormap_Object *)DEREFHANDLE(EmptyColormap(taskData, dsHandle,s->colormap));
2427  tuple->redMax    = DEREFWORD(Make_arbitrary_precision(taskData, s->red_max));
2428  tuple->redMult   = DEREFWORD(Make_arbitrary_precision(taskData, s->red_mult));
2429  tuple->greenMax  = DEREFWORD(Make_arbitrary_precision(taskData, s->green_max));
2430  tuple->greenMult = DEREFWORD(Make_arbitrary_precision(taskData, s->green_mult));
2431  tuple->blueMax   = DEREFWORD(Make_arbitrary_precision(taskData, s->blue_max));
2432  tuple->blueMult  = DEREFWORD(Make_arbitrary_precision(taskData, s->blue_mult));
2433  tuple->basePixel = DEREFWORD(Make_arbitrary_precision(taskData, s->base_pixel));
2434  tuple->visual    = (X_Visual_Object *)DEREFHANDLE(EmptyVisual(taskData, dsHandle,T.visual));
2435#undef tuple
2436
2437  return FINISHED(taskData, tupleHandle);
2438}
2439
2440
2441/******************************************************************************/
2442/*                                                                            */
2443/*      Polymorphic pairs                                                     */
2444/*                                                                            */
2445/******************************************************************************/
2446
2447class MLPair: public PolyObject
2448{
2449public:
2450    PolyWord x0; /* first value  */
2451    PolyWord x1; /* second value */
2452};
2453
2454
2455/* Polymorphic pair creation */
2456static Handle CreatePair(TaskData *taskData, Handle p1, Handle p2)
2457{
2458  Handle pairHandle = alloc_and_save(taskData, SIZEOF(MLPair), F_MUTABLE_BIT);
2459
2460/* Still allocating, so must use explicit DEREF for each element */
2461#define pair ((MLPair *)DEREFHANDLE(pairHandle))
2462  pair->x0 = DEREFWORD(p1);
2463  pair->x1 = DEREFWORD(p2);
2464#undef pair
2465
2466  return FINISHED(taskData, pairHandle);
2467}
2468
2469
2470/******************************************************************************/
2471/*                                                                            */
2472/*      Polymorphic triples                                                   */
2473/*                                                                            */
2474/******************************************************************************/
2475
2476class MLTriple: public PolyObject
2477{
2478public:
2479    PolyWord x0; /* first value  */
2480    PolyWord x1; /* second value */
2481    PolyWord x2; /* third value  */
2482};
2483
2484inline PolyWord FST(PolyWord P)   { return ((MLTriple*)P.AsObjPtr())->x0; }
2485inline PolyWord SND(PolyWord P)   { return ((MLTriple*)P.AsObjPtr())->x1; }
2486inline PolyWord THIRD(PolyWord P) { return ((MLTriple*)P.AsObjPtr())->x2; }
2487
2488static Handle CreateTriple(TaskData *taskData, Handle p1, Handle p2, Handle p3)
2489{
2490  Handle tripleHandle = alloc_and_save(taskData, SIZEOF(MLTriple), F_MUTABLE_BIT);
2491
2492/* Still allocating, so must use explicit DEREF for each element */
2493#define triple ((MLTriple *)DEREFHANDLE(tripleHandle))
2494  triple->x0 = DEREFWORD(p1);
2495  triple->x1 = DEREFWORD(p2);
2496  triple->x2 = DEREFWORD(p3);
2497#undef triple
2498
2499  return FINISHED(taskData, tripleHandle);
2500}
2501
2502
2503/******************************************************************************/
2504/*                                                                            */
2505/*      MLXImage - Implements ML XImage datatype                              */
2506/*                                                                            */
2507/******************************************************************************/
2508typedef struct
2509{
2510  PolyWord data;            /* ML (abstype containing) string */
2511  PolyWord size;            /* MLXRectangle * */
2512  PolyWord depth;           /* ML int */
2513  PolyWord format;          /* (short ML int) XYBitmap | XYPixmap | ZPixmap */
2514  PolyWord xoffset;         /* ML int */
2515  PolyWord bitmapPad;       /* ML int */
2516  PolyWord byteOrder;       /* (short ML int) LSBFirst | MSBFirst */
2517  PolyWord bitmapUnit;      /* ML int */
2518  PolyWord bitsPerPixel;    /* ML int */
2519  PolyWord bytesPerLine;    /* ML int */
2520  PolyWord visualRedMask;   /* ML int */
2521  PolyWord bitmapBitOrder;  /* (short ML int) LSBFirst | MSBFirst */
2522  PolyWord visualBlueMask;  /* ML int */
2523  PolyWord visualGreenMask; /* ML int */
2524} MLXImage;
2525
2526#define MLImageFormat(n) (n+1)
2527#define MLImageOrder(n)  (n+1)
2528#define CImageFormat(n)  (n-1)
2529#define CImageOrder(n)   (n-1)
2530
2531static unsigned ImageBytes(XImage *image)
2532{
2533    unsigned dsize = image->bytes_per_line * image->height;
2534    if (image->format == XYPixmap) dsize = dsize * image->depth;
2535    return dsize;
2536}
2537
2538static XImage *GetXImage(TaskData *taskData, Display *d, PolyWord p)
2539/* can only be called once per X opcode */
2540{
2541    MLXImage *I = (MLXImage *)p.AsObjPtr();
2542  static XImage image = { 0 };
2543
2544  PolyStringObject  *data           = GetString(I->data);
2545  unsigned width          = GetRectW(taskData, I->size);
2546  unsigned height         = GetRectH(taskData, I->size);
2547  unsigned depth          = get_C_ulong(taskData, I->depth);
2548  unsigned format         = get_C_ulong(taskData, I->format);
2549  int      xoffset        = get_C_short(taskData, I->xoffset);
2550  int      bitmapPad      = get_C_short(taskData, I->bitmapPad);
2551  int      bytesPerLine   = get_C_long (taskData, I->bytesPerLine);
2552
2553  unsigned byteOrder      = get_C_ulong(taskData, I->byteOrder);
2554  unsigned bitmapUnit     = get_C_ulong(taskData, I->bitmapUnit);
2555  unsigned bitsPerPixel   = get_C_ulong(taskData, I->bitsPerPixel);
2556  unsigned bitmapBitOrder = get_C_ulong(taskData, I->bitmapBitOrder);
2557
2558  format         = CImageFormat(format);
2559  byteOrder      = CImageOrder(byteOrder);
2560  bitmapBitOrder = CImageOrder(bitmapBitOrder);
2561
2562  image.width            = width;
2563  image.height           = height;
2564  image.xoffset          = xoffset;
2565  image.format           = format;
2566  image.data             = data->chars;
2567  image.byte_order       = byteOrder;
2568  image.bitmap_unit      = bitmapUnit;
2569  image.bitmap_bit_order = bitmapBitOrder;
2570  image.bitmap_pad       = bitmapPad;
2571  image.depth            = depth;
2572  image.bytes_per_line   = bytesPerLine;
2573  image.bits_per_pixel   = bitsPerPixel;
2574  image.red_mask         = get_C_ulong(taskData, I->visualRedMask);
2575  image.green_mask       = get_C_ulong(taskData, I->visualGreenMask);
2576  image.blue_mask        = get_C_ulong(taskData, I->visualBlueMask);
2577
2578  if (ImageBytes(&image) != data->length) RaiseXWindows(taskData, "Bad image string length");
2579
2580  XInitImage(&image);
2581
2582  return &image;
2583}
2584
2585static Handle CreateImage(TaskData *taskData, XImage *image)
2586{
2587  Handle XHandle = alloc_and_save(taskData, SIZEOF(MLXImage), F_MUTABLE_BIT);
2588
2589  int dsize = ImageBytes(image);
2590
2591/* Still allocating, so must use explicit DEREF for each element */
2592#define  X ((MLXImage *)DEREFHANDLE(XHandle))
2593  X->data            = C_string_to_Poly(taskData, image->data,dsize);
2594  X->size            = DEREFWORD(CreateArea(image->width,image->height));
2595  X->depth           = DEREFWORD(Make_arbitrary_precision(taskData, image->depth));
2596  X->format          = DEREFWORD(Make_arbitrary_precision(taskData, MLImageFormat(image->format)));
2597  X->xoffset         = DEREFWORD(Make_int(image->xoffset));
2598  X->bitmapPad       = DEREFWORD(Make_int(image->bitmap_pad));
2599  X->byteOrder       = DEREFWORD(Make_arbitrary_precision(taskData, MLImageOrder(image->byte_order)));
2600  X->bitmapUnit      = DEREFWORD(Make_arbitrary_precision(taskData, image->bitmap_unit));
2601  X->bitsPerPixel    = DEREFWORD(Make_arbitrary_precision(taskData, image->bits_per_pixel));
2602  X->bytesPerLine    = DEREFWORD(Make_int(image->bytes_per_line));
2603  X->visualRedMask   = DEREFWORD(Make_arbitrary_precision(taskData, image->red_mask));
2604  X->bitmapBitOrder  = DEREFWORD(Make_arbitrary_precision(taskData, MLImageOrder(image->bitmap_bit_order)));
2605  X->visualBlueMask  = DEREFWORD(Make_arbitrary_precision(taskData, image->blue_mask));
2606  X->visualGreenMask = DEREFWORD(Make_arbitrary_precision(taskData, image->green_mask));
2607#undef X
2608
2609  XDestroyImage(image);
2610
2611  return FINISHED(taskData, XHandle);
2612}
2613
2614static Handle GetImage
2615(
2616  TaskData *taskData,
2617  Display *d,
2618  Drawable drawable,
2619  int      x,
2620  int      y,
2621  unsigned w,
2622  unsigned h,
2623  unsigned /* long */ mask,
2624  int format
2625)
2626{
2627  XImage *image = XGetImage(d,drawable,x,y,w,h,mask,CImageFormat(format));
2628
2629  if (image == 0) RaiseXWindows(taskData, "XGetImage failed");
2630
2631  return CreateImage(taskData, image);
2632}
2633
2634static Handle SubImage
2635(
2636  TaskData *taskData,
2637  XImage   *image,
2638  int      x,
2639  int      y,
2640  unsigned w,
2641  unsigned h
2642)
2643{
2644  XImage *subimage = XSubImage(image,x,y,w,h);
2645
2646  if (subimage == 0) RaiseXWindows(taskData, "XSubImage failed");
2647
2648  return CreateImage(taskData, subimage);
2649}
2650
2651
2652/******************************************************************************/
2653/*                                                                            */
2654/*      XImage                                                                */
2655/*                                                                            */
2656/******************************************************************************/
2657static void GetSubImage
2658(
2659  Display  *d,
2660  Drawable  drawable,
2661  int       sx,
2662  int       sy,
2663  unsigned  sw,
2664  unsigned  sh,
2665  unsigned /* long */ mask,
2666  int       format,
2667  XImage   *image,
2668  int       dx,
2669  int       dy
2670)
2671{
2672  XGetSubImage(d,drawable,sx,sy,sw,sh,mask,CImageFormat(format),image,dx,dy);
2673
2674  /* XFree((char *)image); */
2675}
2676
2677static void PutImage
2678(
2679  Display  *d,
2680  Drawable drawable,
2681  GC       gc,
2682  XImage  *image,
2683  int      sx,
2684  int      sy,
2685  int      dx,
2686  int      dy,
2687  unsigned dw,
2688  unsigned dh
2689)
2690{
2691  XPutImage(d,drawable,gc,image,sx,sy,dx,dy,dw,dh);
2692
2693  /* XFree((char *)image); */
2694}
2695
2696static Handle GetPixel(TaskData *taskData, XImage *image, int x, int y)
2697{
2698  unsigned pixel = XGetPixel(image,x,y);
2699
2700  /* XFree((char *)image); */
2701
2702  return Make_arbitrary_precision(taskData, pixel);
2703}
2704
2705static void PutPixel(XImage *image, int x, int y, unsigned pixel)
2706{
2707  XPutPixel(image,x,y,pixel);
2708
2709  /* XFree((char *)image); */
2710}
2711
2712static void AddPixel(XImage *image, unsigned value)
2713{
2714  XAddPixel(image,value);
2715
2716  /* XFree((char *)image); */
2717}
2718
2719
2720/******************************************************************************/
2721/*                                                                            */
2722/*      TimeVal                                                               */
2723/*                                                                            */
2724/******************************************************************************/
2725static int DoubleClickTime = 250; /* Double click time in milliseconds       */
2726static int MouseDrift      = 5;   /* Mouse movement allowed in button events */
2727
2728static void NormaliseTime(TimeVal *t)
2729{
2730  while(t->tv_usec >= 1000000) { t->tv_usec -= 1000000; t->tv_sec++; }
2731  while(t->tv_usec < 0)        { t->tv_usec += 1000000; t->tv_sec--; }
2732}
2733
2734static void TimeAdd(TimeVal *a, TimeVal *b, TimeVal *t)
2735{
2736  t->tv_sec  = a->tv_sec  + b->tv_sec;
2737  t->tv_usec = a->tv_usec + b->tv_usec;
2738
2739  NormaliseTime(t);
2740}
2741
2742static int TimeLt(TimeVal *a, TimeVal *b)
2743{
2744  return ((a->tv_sec <  b->tv_sec) ||
2745         ((a->tv_sec == b->tv_sec) && (a->tv_usec <  b->tv_usec)));
2746}
2747
2748static int TimeLeq(TimeVal *a, TimeVal *b)
2749{
2750  return ((a->tv_sec <  b->tv_sec) ||
2751         ((a->tv_sec == b->tv_sec) && (a->tv_usec <=  b->tv_usec)));
2752}
2753
2754/******************************************************************************/
2755/*                                                                            */
2756/*      (?)                                                                   */
2757/*                                                                            */
2758/******************************************************************************/
2759typedef struct
2760{
2761  XButtonEvent *button;    /* initial button press event   */
2762  int           up,down;   /* count of button transitions  */
2763} PredicateArgs;
2764
2765static Bool SameClickEvent(Display *dpy, XEvent *ev, XPointer arg)
2766{
2767  PredicateArgs *A = (PredicateArgs *)arg;
2768
2769  switch(ev->type)
2770  {
2771    case MotionNotify:
2772    {
2773      int dx = ev->xmotion.x - A->button->x;
2774      int dy = ev->xmotion.y - A->button->y;
2775
2776      if (ev->xmotion.window != A->button->window) return False;
2777
2778      if (abs(dx) > MouseDrift) return False;
2779      if (abs(dy) > MouseDrift) return False;
2780
2781      return True;
2782    }
2783
2784    case ButtonPress:
2785    case ButtonRelease:
2786    {
2787      int dx = ev->xbutton.x - A->button->x;
2788      int dy = ev->xbutton.y - A->button->y;
2789
2790      if (ev->xbutton.window != A->button->window) return False;
2791
2792      if (ev->xbutton.button != A->button->button) return False;
2793
2794      if (abs(dx) > MouseDrift) return False;
2795      if (abs(dy) > MouseDrift) return False;
2796
2797      if (ev->type == ButtonPress) A->down++; else A->up++;
2798
2799      return True;
2800    }
2801  }
2802
2803  return False;
2804}
2805
2806static void WaitDoubleClickTime(Handle dsHandle, PredicateArgs *A)
2807{
2808  XEvent N;
2809  TimeVal start_time,end_time,dt;
2810  Display *d = DEREFDISPLAYHANDLE(dsHandle)->display;
2811
2812  /*
2813    AIX doesn't document support for NULL pointers in the select call,
2814     so we have to initialise empty fd_sets instead. SPF 30/10/95
2815  */
2816  fd_set read_fds, write_fds, except_fds;
2817  FD_ZERO(&read_fds);
2818  FD_ZERO(&write_fds);
2819  FD_ZERO(&except_fds);
2820
2821  {
2822    int fd = d->fd;
2823    assert (0 <= fd && fd < FD_SETSIZE);
2824    FD_SET(fd,&read_fds);
2825  }
2826
2827  gettimeofday(&start_time, NULL);
2828
2829  dt.tv_sec  = 0;
2830  dt.tv_usec = DoubleClickTime * 1000;
2831
2832  TimeAdd(&start_time,&dt,&end_time);
2833
2834  for (;;)
2835  {
2836    int extended = 0;
2837
2838    while(XCheckIfEvent(d,&N,SameClickEvent,(char *) A))
2839    {
2840      if (DEREFDISPLAYHANDLE(dsHandle)->app_context) XtDispatchEvent(&N);
2841
2842      extended = 1;
2843    }
2844
2845    if (QLength(d)) break;  /* some other event to be processed next */
2846
2847    if (extended)           /* button event extended, so extend time period */
2848    {
2849      dt.tv_sec  = 0;
2850      dt.tv_usec = DoubleClickTime * 1000;
2851
2852      TimeAdd(&end_time,&dt,&end_time);
2853    }
2854
2855    if (TimeLeq(&end_time,&start_time)) break; /* the time period has elapsed */
2856
2857    select(FD_SETSIZE,&read_fds,&write_fds,&except_fds,&dt);
2858
2859    gettimeofday(&start_time, NULL);
2860  }
2861}
2862
2863static Handle GetKeyVector(TaskData *taskData, void *k, unsigned i)
2864{
2865    uchar *keys = (uchar*)k;
2866    unsigned index = i / 8;
2867    unsigned mask  = 1 << (i % 8);
2868    return Make_bool(keys[index] & mask);
2869}
2870
2871static Handle QueryKeymap(TaskData *taskData, Display *d)
2872{
2873    char keys[32];
2874    XQueryKeymap(d, keys);
2875    return CreateList4I(taskData, 256,keys,0,GetKeyVector);
2876}
2877
2878/******************************************************************************/
2879/*                                                                            */
2880/*      EventName                                                             */
2881/*                                                                            */
2882/******************************************************************************/
2883typedef struct
2884{
2885  const char *name;
2886  int   type;
2887} EventName;
2888
2889static EventName EventNames[] =
2890{
2891  { "KeyPress",KeyPress },
2892  { "KeyRelease",KeyRelease },
2893  { "ButtonPress",ButtonPress },
2894  { "ButtonRelease",ButtonRelease },
2895  { "MotionNotify",MotionNotify },
2896  { "EnterNotify",EnterNotify },
2897  { "LeaveNotify",LeaveNotify },
2898  { "FocusIn",FocusIn },
2899  { "FocusOut",FocusOut },
2900  { "KeymapNotify",KeymapNotify },
2901  { "Expose",Expose },
2902  { "GraphicsExpose",GraphicsExpose },
2903  { "NoExpose",NoExpose },
2904  { "VisibilityNotify",VisibilityNotify },
2905  { "CreateNotify",CreateNotify },
2906  { "DestroyNotify",DestroyNotify },
2907  { "UnmapNotify",UnmapNotify },
2908  { "MapNotify",MapNotify },
2909  { "MapRequest",MapRequest },
2910  { "ReparentNotify",ReparentNotify },
2911  { "ConfigureNotify",ConfigureNotify },
2912  { "ConfigureRequest",ConfigureRequest },
2913  { "GravityNotify",GravityNotify },
2914  { "ResizeRequest",ResizeRequest },
2915  { "CirculateNotify",CirculateNotify },
2916  { "CirculateRequest",CirculateRequest },
2917  { "PropertyNotify",PropertyNotify },
2918  { "SelectionClear",SelectionClear },
2919  { "SelectionRequest",SelectionRequest },
2920  { "SelectionNotify",SelectionNotify },
2921  { "ColormapNotify",ColormapNotify },
2922  { "ClientMessage",ClientMessage },
2923  { "MappingNotify",MappingNotify },
2924};
2925
2926#define NEVENTS (sizeof(EventNames)/sizeof(EventName))
2927
2928static const char *DebugEventName(int type)
2929{
2930    for(unsigned i = 0; i < NEVENTS; i++)
2931    {
2932        if (EventNames[i].type == type) return EventNames[i].name;
2933    }
2934
2935    return "** BAD EVENT **";
2936}
2937
2938static int WM_PROTOCOLS(Display *d)
2939{
2940  static int protocols = None;
2941
2942  if (protocols == None) protocols = XInternAtom(d,"WM_PROTOCOLS",True);
2943
2944  return protocols;
2945}
2946
2947static Atom WM_DELETE_WINDOW(Display *d)
2948{
2949  static Atom deleteWindow = None;
2950
2951  if (deleteWindow == None) deleteWindow = XInternAtom(d,"WM_DELETE_WINDOW",True);
2952
2953  return deleteWindow;
2954}
2955
2956/******************************************************************************/
2957/*                                                                            */
2958/*      Structures used by CreateEvent function.                              */
2959/*                                                                            */
2960/* These typedefs should correspond with the tuples used by MakeXKeyEvent etc */
2961/*                                                                            */
2962/******************************************************************************/
2963
2964
2965typedef struct
2966{
2967X_Window_Object *root;
2968X_Window_Object *subwindow;
2969PolyWord        time;       /* ML int */
2970MLXPoint        *pointer;
2971MLXPoint        *rootPointer;
2972PolyWord        modifiers;  /* ML modifier (int) */
2973PolyWord        keycode;    /* ML int */
2974} ML_KeyEvent_Data;
2975
2976typedef struct
2977{
2978X_Window_Object *root;
2979X_Window_Object *subwindow;
2980PolyWord        time;       /* ML int */
2981MLXPoint        *pointer;
2982MLXPoint        *rootPointer;
2983PolyWord        modifiers;  /* ML modifier (int) */
2984PolyWord        button;     /* ML int */
2985} ML_ButtonEvent_Data;
2986
2987typedef struct
2988{
2989X_Window_Object *root;
2990X_Window_Object *subwindow;
2991PolyWord        time;       /* ML int */
2992MLXPoint        *pointer;
2993MLXPoint        *rootPointer;
2994PolyWord        modifiers;  /* ML modifier (int) */
2995PolyWord        button;     /* ML int */
2996PolyWord        up;         /* ML int */
2997PolyWord        down;       /* ML int */
2998} ML_ButtonClick_Data;
2999
3000typedef struct
3001{
3002X_Window_Object *root;
3003X_Window_Object *subwindow;
3004PolyWord        time;       /* ML int */
3005MLXPoint        *pointer;
3006MLXPoint        *rootPointer;
3007PolyWord        modifiers;  /* ML modifier (int) */
3008PolyWord        isHint;     /* ML bool */
3009} ML_MotionEvent_Data;
3010
3011
3012typedef struct
3013{
3014X_Window_Object *root;
3015X_Window_Object *subwindow;
3016PolyWord        time;       /* ML int */
3017MLXPoint        *pointer;
3018MLXPoint        *rootPointer;
3019PolyWord        mode;        /* ?  */
3020PolyWord        detail;      /* ? */
3021PolyWord        focus;       /* ? */
3022PolyWord        modifiers;   /* ML modifier (int) */
3023} ML_CrossingEvent_Data;
3024
3025
3026typedef struct
3027{
3028    MLXRectangle *region;
3029    PolyWord     count;  /* ML int */
3030} ML_ExposeEvent_Data;
3031
3032typedef struct
3033{
3034    X_Window_Object *window;
3035    MLXPoint        *position;
3036    MLXRectangle    *size;
3037    PolyWord       borderWidth;      /* ML int */
3038    X_Window_Object *above;
3039    PolyWord        overrideRedirect; /* ML bool */
3040} ML_ConfigureNotify_Data;
3041
3042typedef struct
3043{
3044    X_Window_Object *window;
3045    MLXPoint        *position;
3046    MLXRectangle    *size;
3047    PolyWord        borderWidth;
3048    X_Window_Object *above;
3049    PolyWord        detail;      /* ? */
3050} ML_ConfigureRequest_Data;
3051
3052
3053typedef struct
3054{
3055    MLXRectangle *region;
3056    PolyWord     count;  /* ML int */
3057    PolyWord     code;   /* ML int */
3058} ML_GraphicsExposeEvent_Data;
3059
3060typedef struct
3061{
3062    PolyWord mode;   /* ML int ? */
3063    PolyWord detail; /* ML int ? */
3064    } ML_FocusChangeEvent_Data;
3065
3066typedef struct
3067{
3068    X_Window_Object *window;
3069    MLXPoint        *position;
3070    MLXRectangle    *size;
3071    PolyWord       borderWidth;      /* ML int */
3072    PolyWord       overrideRedirect; /* ML bool */
3073} ML_CreateEvent_Data;
3074
3075typedef struct
3076{
3077    X_Window_Object *window;
3078    PolyWord        fromConfigure; /* ML bool */
3079} ML_UnmapEvent_Data;
3080
3081typedef struct
3082{
3083    X_Window_Object *window;
3084    PolyWord        overrideRedirect; /* ML bool */
3085} ML_MapEvent_Data;
3086
3087typedef struct
3088{
3089X_Window_Object *window;
3090X_Window_Object *parent;
3091MLXPoint        *position;
3092PolyWord        overrideRedirect; /* ML bool */
3093} ML_ReparentEvent_Data;
3094
3095typedef struct
3096{
3097X_Window_Object *window;
3098MLXPoint        *position;
3099} ML_GravityEvent_Data;
3100
3101typedef struct
3102{
3103X_Window_Object *window;
3104PolyWord        place;
3105} ML_CirculateEvent_Data;
3106
3107typedef struct
3108{
3109X_Colormap_Object *colormap_object;
3110PolyWord          c_new;        /* ML bool */
3111PolyWord          installed;  /* ML bool */
3112} ML_ColormapEvent_Data;
3113
3114typedef struct
3115{
3116PolyWord selection; /* ML int */
3117PolyWord time;      /* ML int */
3118} ML_SelectionClear_Data;
3119
3120typedef struct
3121{
3122    X_Window_Object *requestor;
3123    PolyWord        selection; /* ML int */
3124    PolyWord        target;    /* ML int */
3125    PolyWord        property;  /* ML int */
3126    PolyWord        time;      /* ML int */
3127} ML_SelectionRequest_Data;
3128
3129
3130typedef struct
3131{
3132    PolyWord selection; /* ML int */
3133    PolyWord target;    /* ML int */
3134    PolyWord property;  /* ML int */
3135    PolyWord time;      /* ML int */
3136} ML_Selection_Data;
3137
3138
3139class ML_Event: public PolyObject
3140{
3141public:
3142    PolyWord        type;       /* ML (?) */
3143    PolyWord        sendEvent;  /* ML bool */
3144    PolyWord        window;     /* X_Window_Object* */
3145    PolyWord        data;       /* pointer to event-specific data, in ML_XXX_Data format */
3146    PolyWord        callbacks;  /* ML list of something */
3147    PolyWord        events;     /* ML list */
3148};
3149
3150
3151/******************************************************************************/
3152/*                                                                            */
3153/*      CreateEvent function                                                  */
3154/*                                                                            */
3155/******************************************************************************/
3156
3157static Handle CreateEvent
3158(
3159  TaskData *taskData,
3160  Handle  dsHandle, /* Handle to (X_Display_Object *) */
3161  XEvent *ev,
3162  Handle  W         /* Handle to (X_Window_Object *) */
3163)
3164{
3165  Handle eventHandle = alloc_and_save(taskData, SIZEOF(ML_Event), F_MUTABLE_BIT);
3166
3167  Display *d     = DEREFDISPLAYHANDLE(dsHandle)->display;
3168  int type       = ev->xany.type;
3169  int send_event = ev->xany.send_event;
3170
3171  assert(d == ev->xany.display);
3172
3173  if (debugOptions & DEBUG_X)
3174  {
3175    printf("CreateEvent called, type=%s,", DebugEventName(type));
3176    printf(" window=%lx\n", ev->xany.window);
3177  }
3178
3179#define event ((ML_Event *)DEREFHANDLE(eventHandle))
3180  event->type      = DEREFWORD(Make_arbitrary_precision(taskData, type));
3181  event->sendEvent = DEREFWORD(Make_bool(send_event));
3182  event->window    = DEREFWINDOWHANDLE(W);
3183
3184  switch(type)
3185  {
3186    case KeyPress:
3187    case KeyRelease:
3188    {
3189      Handle dataHandle = alloc_and_save(taskData, SIZEOF(ML_KeyEvent_Data), F_MUTABLE_BIT);
3190
3191#define data ((ML_KeyEvent_Data *)DEREFHANDLE(dataHandle))
3192      data->root        = DEREFWINDOWHANDLE(EmptyWindow(taskData, dsHandle,ev->xkey.root));
3193      data->subwindow   = DEREFWINDOWHANDLE(EmptyWindow(taskData, dsHandle,ev->xkey.subwindow));
3194      data->time        = DEREFWORD(Make_arbitrary_precision(taskData, ev->xkey.time));
3195      data->pointer     = (MLXPoint *)DEREFHANDLE(CreatePoint(taskData, ev->xkey.x,ev->xkey.y));
3196      data->rootPointer = (MLXPoint *)DEREFHANDLE(CreatePoint(taskData, ev->xkey.x_root,ev->xkey.y_root));
3197      data->modifiers   = DEREFWORD(Make_arbitrary_precision(taskData, ev->xkey.state));
3198      data->keycode     = DEREFWORD(Make_arbitrary_precision(taskData, ev->xkey.keycode));
3199#undef data
3200
3201      event->data = DEREFHANDLE(FINISHED(taskData, dataHandle));
3202
3203      break;
3204    }
3205
3206
3207    case ButtonPress:
3208    case ButtonRelease:
3209    {
3210
3211      if (DEREFWINDOWHANDLE(W)->eventMask->Get(0).AsUnsigned() & ButtonClickMask)
3212      {
3213        Handle dataHandle;
3214        PredicateArgs A;
3215
3216        A.button = &ev->xbutton;
3217        A.up     = (ev->type == ButtonRelease);
3218        A.down   = (ev->type == ButtonPress);
3219
3220        WaitDoubleClickTime(dsHandle,&A);
3221
3222        dataHandle = alloc_and_save(taskData, SIZEOF(ML_ButtonClick_Data), F_MUTABLE_BIT);
3223
3224#define data ((ML_ButtonClick_Data *)DEREFHANDLE(dataHandle))
3225        data->root        = DEREFWINDOWHANDLE(EmptyWindow(taskData, dsHandle,ev->xbutton.root));
3226        data->subwindow   = DEREFWINDOWHANDLE(EmptyWindow(taskData, dsHandle,ev->xbutton.subwindow));
3227        data->time        = DEREFWORD(Make_arbitrary_precision(taskData, ev->xbutton.time));
3228        data->pointer     = (MLXPoint *)       DEREFHANDLE(CreatePoint(taskData, ev->xbutton.x,ev->xbutton.y));
3229        data->rootPointer = (MLXPoint *)       DEREFHANDLE(CreatePoint(taskData, ev->xbutton.x_root,ev->xbutton.y_root));
3230        data->modifiers   = DEREFWORD(Make_arbitrary_precision(taskData, ev->xbutton.state));
3231        data->button      = DEREFWORD(Make_arbitrary_precision(taskData, ev->xbutton.button));
3232        data->up          = DEREFWORD(Make_arbitrary_precision(taskData, A.up));
3233        data->down        = DEREFWORD(Make_arbitrary_precision(taskData, A.down));
3234#undef data
3235
3236        event->type = DEREFWORD(Make_arbitrary_precision(taskData, 42)); /* What's this for? */
3237        event->data = DEREFWORD(FINISHED(taskData, dataHandle));
3238
3239      }
3240      else
3241      {
3242        Handle dataHandle = alloc_and_save(taskData, SIZEOF(ML_ButtonEvent_Data), F_MUTABLE_BIT);
3243
3244#define data ((ML_ButtonEvent_Data *)DEREFHANDLE(dataHandle))
3245        data->root        = DEREFWINDOWHANDLE(EmptyWindow(taskData, dsHandle,ev->xbutton.root));
3246        data->subwindow   = DEREFWINDOWHANDLE(EmptyWindow(taskData, dsHandle,ev->xbutton.subwindow));
3247        data->time        = DEREFWORD(Make_arbitrary_precision(taskData, ev->xbutton.time));
3248        data->pointer     = (MLXPoint *)       DEREFHANDLE(CreatePoint(taskData, ev->xbutton.x,ev->xbutton.y));
3249        data->rootPointer = (MLXPoint *)       DEREFHANDLE(CreatePoint(taskData, ev->xbutton.x_root,ev->xbutton.y_root));
3250        data->modifiers   = DEREFWORD(Make_arbitrary_precision(taskData, ev->xbutton.state));
3251        data->button      = DEREFWORD(Make_arbitrary_precision(taskData, ev->xbutton.button));
3252#undef data
3253
3254        event->data = DEREFWORD(FINISHED(taskData, dataHandle));
3255
3256      }
3257
3258      break;
3259    }
3260
3261
3262    case MotionNotify:
3263    {
3264
3265      Handle dataHandle = alloc_and_save(taskData, SIZEOF(ML_MotionEvent_Data), F_MUTABLE_BIT);
3266
3267#define data ((ML_MotionEvent_Data *)DEREFHANDLE(dataHandle))
3268      data->root        = DEREFWINDOWHANDLE(EmptyWindow(taskData, dsHandle,ev->xmotion.root));
3269      data->subwindow   = DEREFWINDOWHANDLE(EmptyWindow(taskData, dsHandle,ev->xmotion.subwindow));
3270      data->time        = DEREFWORD(Make_arbitrary_precision(taskData, ev->xmotion.time));
3271      data->pointer     = (MLXPoint *)       DEREFHANDLE(CreatePoint(taskData, ev->xmotion.x,ev->xmotion.y));
3272      data->rootPointer = (MLXPoint *)       DEREFHANDLE(CreatePoint(taskData, ev->xmotion.x_root,ev->xmotion.y_root));
3273      data->modifiers   = DEREFWORD(Make_arbitrary_precision(taskData, ev->xmotion.state));
3274      data->isHint      = DEREFWORD(Make_arbitrary_precision(taskData, ev->xmotion.is_hint));
3275#undef data
3276
3277      event->data = DEREFWORD(FINISHED(taskData, dataHandle));
3278
3279
3280      break;
3281    }
3282
3283    case EnterNotify:
3284    case LeaveNotify:
3285    {
3286      Handle dataHandle = alloc_and_save(taskData, SIZEOF(ML_CrossingEvent_Data), F_MUTABLE_BIT);
3287
3288#define data ((ML_CrossingEvent_Data *)DEREFHANDLE(dataHandle))
3289      data->root        = DEREFWINDOWHANDLE(EmptyWindow(taskData, dsHandle,ev->xcrossing.root));
3290      data->subwindow   = DEREFWINDOWHANDLE(EmptyWindow(taskData, dsHandle,ev->xcrossing.subwindow));
3291      data->time        = DEREFWORD(Make_arbitrary_precision(taskData, ev->xcrossing.time));
3292      data->pointer     = (MLXPoint *)       DEREFHANDLE(CreatePoint(taskData, ev->xcrossing.x,ev->xcrossing.y));
3293      data->rootPointer = (MLXPoint *)       DEREFHANDLE(CreatePoint(taskData, ev->xcrossing.x_root,ev->xcrossing.y_root));
3294      data->mode        = DEREFWORD(Make_arbitrary_precision(taskData, ev->xcrossing.mode));
3295      data->detail      = DEREFWORD(Make_arbitrary_precision(taskData, ev->xcrossing.detail));
3296      data->focus       = DEREFWORD(Make_bool(ev->xcrossing.focus));
3297      data->modifiers   = DEREFWORD(Make_arbitrary_precision(taskData, ev->xcrossing.state));
3298#undef data
3299
3300      event->data = DEREFWORD(FINISHED(taskData, dataHandle));
3301
3302      break;
3303    }
3304
3305    case Expose:
3306    {
3307      int left   = ev->xexpose.x;
3308      int top    = ev->xexpose.y;
3309      int right  = left + ev->xexpose.width;
3310      int bottom = top  + ev->xexpose.height;
3311
3312      Handle dataHandle;
3313
3314      while(XCheckTypedWindowEvent(d,ev->xexpose.window,Expose,ev))
3315      {
3316        int L = ev->xexpose.x;
3317        int T = ev->xexpose.y;
3318        int R = L + ev->xexpose.width;
3319        int B = T + ev->xexpose.height;
3320
3321        assert(ev->type == Expose);
3322
3323        left   = min(left,L);
3324        top    = min(top,T);
3325        right  = max(right,R);
3326        bottom = max(bottom,B);
3327      }
3328
3329      dataHandle = alloc_and_save(taskData, SIZEOF(ML_ExposeEvent_Data), F_MUTABLE_BIT);
3330
3331#define data ((ML_ExposeEvent_Data *)DEREFHANDLE(dataHandle))
3332      data->region = (MLXRectangle *)DEREFHANDLE(CreateRect(taskData, top,left,bottom,right));
3333      data->count  = DEREFWORD(Make_arbitrary_precision(taskData, 0));
3334#undef data
3335
3336      event->data = DEREFWORD(FINISHED(taskData, dataHandle));
3337
3338      break;
3339    }
3340
3341
3342    case GraphicsExpose:
3343    {
3344      int left   = ev->xgraphicsexpose.x;
3345      int top    = ev->xgraphicsexpose.y;
3346      int right  = left + ev->xgraphicsexpose.width;
3347      int bottom = top  + ev->xgraphicsexpose.height;
3348
3349      Handle dataHandle = alloc_and_save(taskData, SIZEOF(ML_GraphicsExposeEvent_Data), F_MUTABLE_BIT);
3350
3351#define data ((ML_GraphicsExposeEvent_Data *)DEREFHANDLE(dataHandle))
3352      data->region = (MLXRectangle *)DEREFHANDLE(CreateRect(taskData, top,left,bottom,right));
3353      data->count  = DEREFWORD(Make_arbitrary_precision(taskData, ev->xgraphicsexpose.count));
3354      data->code   = DEREFWORD(Make_arbitrary_precision(taskData, ev->xgraphicsexpose.major_code));
3355#undef data
3356
3357      event->data = DEREFWORD(FINISHED(taskData, dataHandle));
3358
3359      break;
3360    }
3361
3362    case NoExpose:
3363    {
3364      event->data = DEREFWORD(Make_arbitrary_precision(taskData, ev->xnoexpose.major_code));
3365
3366      break;
3367    }
3368
3369    case ConfigureNotify:
3370    {
3371      Handle dataHandle = alloc_and_save(taskData, SIZEOF(ML_ConfigureNotify_Data), F_MUTABLE_BIT);
3372
3373#define data ((ML_ConfigureNotify_Data *)DEREFHANDLE(dataHandle))
3374      data->window           = DEREFWINDOWHANDLE(EmptyWindow(taskData, dsHandle,ev->xconfigure.window));
3375      data->position         = (MLXPoint *)       DEREFHANDLE(CreatePoint(taskData, ev->xconfigure.x,ev->xconfigure.y));
3376      data->size             = (MLXRectangle *)   DEREFHANDLE(CreateArea(ev->xconfigure.width,ev->xconfigure.height));
3377      data->borderWidth      = DEREFWORD(Make_int(ev->xconfigure.border_width));
3378      data->above            = DEREFWINDOWHANDLE(EmptyWindow(taskData, dsHandle,ev->xconfigure.above));
3379      data->overrideRedirect = DEREFWORD(Make_bool(ev->xconfigure.override_redirect));
3380#undef data
3381
3382      event->data = DEREFWORD(FINISHED(taskData, dataHandle));
3383
3384      break;
3385    }
3386
3387
3388
3389    case FocusIn:
3390    case FocusOut:
3391    {
3392      Handle dataHandle = alloc_and_save(taskData, SIZEOF(ML_FocusChangeEvent_Data), F_MUTABLE_BIT);
3393
3394#define data ((ML_FocusChangeEvent_Data *)DEREFHANDLE(dataHandle))
3395      data->mode   = DEREFWORD(Make_int(ev->xfocus.mode));
3396      data->detail = DEREFWORD(Make_int(ev->xfocus.detail));
3397#undef data
3398
3399      event->data = DEREFWORD(FINISHED(taskData, dataHandle));
3400
3401      break;
3402    }
3403
3404    case VisibilityNotify:
3405    {
3406      event->data = DEREFWORD(Make_int(ev->xvisibility.state));
3407
3408      break;
3409    }
3410
3411
3412    case CreateNotify:
3413    {
3414      Handle dataHandle = alloc_and_save(taskData, SIZEOF(ML_CreateEvent_Data), F_MUTABLE_BIT);
3415
3416#define data ((ML_CreateEvent_Data *)DEREFHANDLE(dataHandle))
3417      data->window           = DEREFWINDOWHANDLE(EmptyWindow(taskData, dsHandle,ev->xcreatewindow.window));
3418      data->position         = (MLXPoint *)       DEREFHANDLE(CreatePoint(taskData, ev->xcreatewindow.x,ev->xcreatewindow.y));
3419      data->size             = (MLXRectangle *)   DEREFHANDLE(CreateArea(ev->xcreatewindow.width,ev->xcreatewindow.height));
3420      data->borderWidth      = DEREFWORD(Make_int(ev->xcreatewindow.border_width));
3421      data->overrideRedirect = DEREFWORD(Make_bool(ev->xcreatewindow.override_redirect));
3422#undef data
3423
3424      event->data = DEREFHANDLE(FINISHED(taskData, dataHandle));
3425
3426      break;
3427    }
3428
3429    case DestroyNotify:
3430    {
3431      debugReclaim(Window,ev->xdestroywindow.window);
3432      event->data = DEREFWORD(EmptyWindow(taskData, dsHandle,ev->xdestroywindow.window));
3433
3434      break;
3435    }
3436
3437    case UnmapNotify:
3438    {
3439      Handle dataHandle = alloc_and_save(taskData, SIZEOF(ML_UnmapEvent_Data), F_MUTABLE_BIT);
3440
3441#define data ((ML_UnmapEvent_Data *)DEREFHANDLE(dataHandle))
3442      data->window        = DEREFWINDOWHANDLE(EmptyWindow(taskData, dsHandle,ev->xunmap.window));
3443      data->fromConfigure = DEREFWORD(Make_bool(ev->xunmap.from_configure));
3444#undef data
3445
3446      event->data = DEREFWORD(FINISHED(taskData, dataHandle));
3447
3448      break;
3449    }
3450
3451    case MapNotify:
3452    {
3453      Handle dataHandle = alloc_and_save(taskData, SIZEOF(ML_MapEvent_Data), F_MUTABLE_BIT);
3454
3455#define data ((ML_MapEvent_Data *)DEREFHANDLE(dataHandle))
3456      data->window           = DEREFWINDOWHANDLE(EmptyWindow(taskData, dsHandle,ev->xmap.window));
3457      data->overrideRedirect = DEREFWORD(Make_bool(ev->xmap.override_redirect));
3458#undef data
3459
3460      event->data = DEREFWORD(FINISHED(taskData, dataHandle));
3461
3462      break;
3463    }
3464
3465    case MapRequest:
3466    {
3467      event->data = DEREFWORD(EmptyWindow(taskData, dsHandle,ev->xmaprequest.window));
3468
3469      break;
3470    }
3471
3472
3473    case ReparentNotify:
3474    {
3475      Handle dataHandle = alloc_and_save(taskData, SIZEOF(ML_ReparentEvent_Data), F_MUTABLE_BIT);
3476
3477#define data ((ML_ReparentEvent_Data *)DEREFHANDLE(dataHandle))
3478      data->window           = DEREFWINDOWHANDLE(EmptyWindow(taskData, dsHandle,ev->xreparent.window));
3479      data->parent           = DEREFWINDOWHANDLE(EmptyWindow(taskData, dsHandle,ev->xreparent.parent));
3480      data->position         = (MLXPoint *)       DEREFHANDLE(CreatePoint(taskData, ev->xreparent.x,ev->xreparent.y));
3481      data->overrideRedirect = DEREFWORD(Make_bool(ev->xreparent.override_redirect));
3482#undef data
3483
3484      event->data = DEREFWORD(FINISHED(taskData, dataHandle));
3485
3486      break;
3487    }
3488
3489
3490    case ConfigureRequest:
3491    {
3492      Handle dataHandle = alloc_and_save(taskData, SIZEOF(ML_ConfigureRequest_Data), F_MUTABLE_BIT);
3493
3494#define data ((ML_ConfigureRequest_Data *)DEREFHANDLE(dataHandle))
3495      data->window      = DEREFWINDOWHANDLE(EmptyWindow(taskData, dsHandle,ev->xconfigurerequest.window));
3496      data->position    = (MLXPoint *)       DEREFHANDLE(CreatePoint(taskData, ev->xconfigurerequest.x,ev->xconfigurerequest.y));
3497      data->size        = (MLXRectangle *)   DEREFHANDLE(CreateArea(ev->xconfigurerequest.width,ev->xconfigurerequest.height));
3498      data->borderWidth = DEREFWORD(Make_int(ev->xconfigurerequest.border_width));
3499      data->above       = DEREFWINDOWHANDLE(EmptyWindow(taskData, dsHandle,ev->xconfigurerequest.above));
3500      data->detail      = DEREFWORD(Make_int(ev->xconfigurerequest.detail));
3501#undef data
3502
3503      event->data = DEREFWORD(FINISHED(taskData, dataHandle));
3504
3505      break;
3506    }
3507
3508    case GravityNotify:
3509    {
3510      Handle dataHandle = alloc_and_save(taskData, SIZEOF(ML_GravityEvent_Data), F_MUTABLE_BIT);
3511
3512#define data ((ML_GravityEvent_Data *)DEREFHANDLE(dataHandle))
3513      data->window   = DEREFWINDOWHANDLE(EmptyWindow(taskData, dsHandle,ev->xgravity.window));
3514      data->position = (MLXPoint *)       DEREFHANDLE(CreatePoint(taskData, ev->xgravity.x,ev->xgravity.y));
3515#undef data
3516
3517      event->data = DEREFWORD(FINISHED(taskData, dataHandle));
3518
3519      break;
3520    }
3521
3522    case ResizeRequest:
3523    {
3524      event->data = DEREFWORD(CreateArea(ev->xresizerequest.width,ev->xresizerequest.height));
3525
3526      break;
3527    }
3528
3529
3530    case CirculateNotify:
3531    {
3532      Handle dataHandle = alloc_and_save(taskData, SIZEOF(ML_CirculateEvent_Data), F_MUTABLE_BIT);
3533
3534#define data ((ML_CirculateEvent_Data *)DEREFHANDLE(dataHandle))
3535      data->window = DEREFWINDOWHANDLE(EmptyWindow(taskData, dsHandle,ev->xcirculate.window));
3536      data->place  = DEREFWORD(Make_int(ev->xcirculate.place));
3537#undef data
3538
3539      event->data = DEREFWORD(FINISHED(taskData, dataHandle));
3540
3541      break;
3542    }
3543
3544    case CirculateRequest:
3545    {
3546      Handle dataHandle = alloc_and_save(taskData, SIZEOF(ML_CirculateEvent_Data), F_MUTABLE_BIT);
3547
3548#define data ((ML_CirculateEvent_Data *)DEREFHANDLE(dataHandle))
3549      data->window = DEREFWINDOWHANDLE(EmptyWindow(taskData, dsHandle,ev->xcirculaterequest.window));
3550      data->place  = DEREFWORD(Make_int(ev->xcirculaterequest.place));
3551#undef data
3552
3553      event->data = DEREFWORD(FINISHED(taskData, dataHandle));
3554
3555      break;
3556    }
3557
3558    case ColormapNotify:
3559    {
3560      Handle dataHandle = alloc_and_save(taskData, SIZEOF(ML_ColormapEvent_Data), F_MUTABLE_BIT);
3561
3562#define data ((ML_ColormapEvent_Data *)DEREFHANDLE(dataHandle))
3563      data->colormap_object = (X_Colormap_Object *)DEREFHANDLE(EmptyColormap(taskData, dsHandle,ev->xcolormap.colormap));
3564      data->c_new             = DEREFWORD(Make_bool(ev->xcolormap.c_new));
3565      data->installed       = DEREFWORD(Make_bool(ev->xcolormap.state == ColormapInstalled));
3566#undef data
3567
3568      event->data = DEREFWORD(FINISHED(taskData, dataHandle));
3569
3570      break;
3571    }
3572
3573    case MappingNotify:
3574    {
3575      XRefreshKeyboardMapping((XMappingEvent *)ev); /* cast added SPF 6/1/94 */
3576      return 0; /* HACK !!!! */
3577    }
3578
3579    case SelectionClear:
3580    {
3581      Handle dataHandle = alloc_and_save(taskData, SIZEOF(ML_SelectionClear_Data), F_MUTABLE_BIT);
3582
3583#define data ((ML_SelectionClear_Data *)DEREFHANDLE(dataHandle))
3584      data->selection = DEREFWORD(Make_arbitrary_precision(taskData, ev->xselectionclear.selection));
3585      data->time      = DEREFWORD(Make_arbitrary_precision(taskData, ev->xselectionclear.time));
3586#undef data
3587
3588      event->data = DEREFWORD(FINISHED(taskData, dataHandle));
3589
3590      break;
3591    }
3592
3593    case SelectionNotify:
3594    {
3595      Handle dataHandle = alloc_and_save(taskData, SIZEOF(ML_Selection_Data), F_MUTABLE_BIT);
3596
3597#define data ((ML_Selection_Data *)DEREFHANDLE(dataHandle))
3598      data->selection = DEREFWORD(Make_arbitrary_precision(taskData, ev->xselection.selection));
3599      data->target    = DEREFWORD(Make_arbitrary_precision(taskData, ev->xselection.target));
3600      data->property  = DEREFWORD(Make_arbitrary_precision(taskData, ev->xselection.property));
3601      data->time      = DEREFWORD(Make_arbitrary_precision(taskData, ev->xselection.time));
3602#undef data
3603
3604      event->data = DEREFWORD(FINISHED(taskData, dataHandle));
3605
3606      break;
3607    }
3608
3609    case SelectionRequest:
3610    {
3611      Handle dataHandle = alloc_and_save(taskData, SIZEOF(ML_SelectionRequest_Data), F_MUTABLE_BIT);
3612
3613#define data ((ML_SelectionRequest_Data *)DEREFHANDLE(dataHandle))
3614      data->requestor = DEREFWINDOWHANDLE(EmptyWindow(taskData, dsHandle,ev->xselectionrequest.requestor));
3615      data->selection = DEREFWORD(Make_arbitrary_precision(taskData, ev->xselectionrequest.selection));
3616      data->target    = DEREFWORD(Make_arbitrary_precision(taskData, ev->xselectionrequest.target));
3617      data->property  = DEREFWORD(Make_arbitrary_precision(taskData, ev->xselectionrequest.property));
3618      data->time      = DEREFWORD(Make_arbitrary_precision(taskData, ev->xselectionrequest.time));
3619#undef data
3620
3621      event->data = DEREFWORD(FINISHED(taskData, dataHandle));
3622
3623      break;
3624    }
3625
3626    case ClientMessage:
3627    {
3628      unsigned protocols    = WM_PROTOCOLS(d);
3629      int deleteWindow = WM_DELETE_WINDOW(d);
3630
3631      if (protocols                != None      &&
3632           deleteWindow             != None      &&
3633           ev->xclient.message_type == protocols &&
3634           ev->xclient.format       == 32        &&
3635           ev->xclient.data.l[0]    == deleteWindow)
3636      {
3637        event->type = DEREFWORD(Make_arbitrary_precision(taskData, 43)); /* (?) */
3638
3639        break;
3640      }
3641      else return 0;
3642    }
3643
3644    case PropertyNotify: return 0;
3645
3646    case KeymapNotify: return 0;   /* Broken: the window field does not tell me the window requesting this event */
3647
3648    default: Crash ("Bad event type %x",ev->type);
3649  }
3650
3651  event->callbacks = FList; /* Safe, since FList is a Root */
3652  FList = TAGGED(0);
3653
3654  event->events = GList; /* Safe, since GList is a Root */
3655  GList = TAGGED(0);
3656
3657  return FINISHED(taskData, eventHandle);
3658#undef event
3659}
3660
3661/******************************************************************************/
3662/*                                                                            */
3663/*      HERE                                                                  */
3664/*                                                                            */
3665/******************************************************************************/
3666static Handle LookupString(TaskData *taskData, Display *d, unsigned keycode, unsigned modifiers)
3667{
3668  XKeyEvent ev;
3669  int n;
3670  KeySym keysym; /* was int SPF 6/1/94 */
3671  char buffer[500];
3672
3673  ev.display = d;
3674  ev.keycode = keycode;
3675  ev.state   = modifiers;
3676
3677  n = XLookupString(&ev,buffer,sizeof(buffer)-1,&keysym,NULL);
3678
3679  buffer[n] = '\0';
3680
3681  return CreatePair(taskData, Make_string(buffer),Make_arbitrary_precision(taskData, keysym));
3682}
3683
3684static Handle GetScreenSaver(TaskData *taskData, Display *d)
3685{
3686  int timeout,interval,blanking,exposures;
3687  Handle tuple;
3688
3689  XGetScreenSaver(d,&timeout,&interval,&blanking,&exposures);
3690
3691  tuple = alloc_and_save(taskData, 4, F_MUTABLE_BIT);
3692
3693#define data DEREFHANDLE(tuple)
3694  data->Set(0, DEREFWORD(Make_int(timeout)));
3695  data->Set(1, DEREFWORD(Make_int(interval)));
3696  data->Set(2, DEREFWORD(Make_arbitrary_precision(taskData, blanking)));
3697  data->Set(3, DEREFWORD(Make_arbitrary_precision(taskData, exposures)));
3698#undef data
3699
3700  return FINISHED(taskData, tuple);
3701}
3702
3703static Handle TranslateCoordinates
3704(
3705  TaskData *taskData,
3706  Handle dsHandle, /* Handle to (X_Display_Object *) */
3707  Window src,
3708  Window dst,
3709  int    x,
3710  int    y
3711)
3712{
3713  Window child;
3714  int    dx,dy,s;
3715
3716  s = XTranslateCoordinates(DEREFDISPLAYHANDLE(dsHandle)->display,src,dst,x,y,&dx,&dy,&child);
3717
3718  if (s == 0) RaiseXWindows(taskData, "XTranslateCoordinates failed");
3719
3720  return CreatePair(taskData, CreatePoint(taskData, dx,dy),EmptyWindow(taskData, dsHandle,child));
3721}
3722
3723
3724static Handle QueryBest
3725(
3726 TaskData *taskData,
3727 int    (*f)(Display*, Drawable, unsigned, unsigned, unsigned *, unsigned *),
3728 Display *d,
3729 Drawable drawable,
3730 unsigned width,
3731 unsigned height
3732 )
3733{
3734    unsigned W,H;
3735
3736    int s = (* f)(d,drawable,width,height,&W,&H);
3737
3738    if (s == 0) RaiseXWindows(taskData, "XQueryBest failed");
3739
3740    return CreateArea(W,H);
3741}
3742
3743static Handle QueryPointer
3744(
3745  TaskData *taskData,
3746  Handle dsHandle, /* Handle to (X_Display_Object *) */
3747  Window  w
3748)
3749{
3750  Window   root,child;
3751  int      rootX,rootY;
3752  int      winX,winY;
3753  unsigned mask;
3754  int      s;
3755  Handle tuple;
3756
3757  s = XQueryPointer(DEREFDISPLAYHANDLE(dsHandle)->display,w,&root,&child,&rootX,&rootY,&winX,&winY,&mask);
3758
3759  tuple = alloc_and_save(taskData, 6, F_MUTABLE_BIT);
3760
3761#define data DEREFHANDLE(tuple)
3762  data->Set(0, DEREFWORD(Make_arbitrary_precision(taskData, s)));
3763  data->Set(1, DEREFWORD(EmptyWindow(taskData, dsHandle,root)));
3764  data->Set(2, DEREFWORD(EmptyWindow(taskData, dsHandle,child)));
3765  data->Set(3, DEREFWORD(CreatePoint(taskData, rootX,rootY)));
3766  data->Set(4, DEREFWORD(CreatePoint(taskData, winX,winY)));
3767  data->Set(5, DEREFWORD(Make_arbitrary_precision(taskData, mask)));
3768#undef data
3769
3770  return FINISHED(taskData, tuple);
3771}
3772
3773static Handle ReadBitmap
3774(
3775  TaskData *taskData,
3776  Handle   dsHandle, /* handle to (X_Display_Object *) */
3777  Drawable w,
3778  PolyStringObject  *string
3779)
3780{
3781  unsigned width,height;
3782  char name[500];
3783  int s,xhot,yhot;
3784  Pixmap pixmap;
3785  Handle tuple;
3786
3787  Poly_string_to_C(string,name,sizeof(name));
3788
3789  s = XReadBitmapFile(DEREFDISPLAYHANDLE(dsHandle)->display,w,name,&width,&height,&pixmap,&xhot,&yhot);
3790
3791  tuple = alloc_and_save(taskData, 4, F_MUTABLE_BIT);
3792
3793#define data DEREFHANDLE(tuple)
3794
3795  data->Set(0,DEREFWORD(Make_arbitrary_precision(taskData, s)));
3796
3797  if (s == BitmapSuccess)
3798  {
3799    data->Set(1, DEREFWORD(EmptyPixmap(taskData, dsHandle,pixmap)));
3800    data->Set(2, DEREFWORD(CreateArea(width,height)));
3801    data->Set(3, DEREFWORD(CreatePoint(taskData, xhot,yhot)));
3802  }
3803
3804  /******************** What if we don't succeed? Badly-formed tuple !!!! */
3805
3806#undef data
3807
3808  return FINISHED(taskData, tuple);
3809}
3810
3811static Handle WriteBitmapFile
3812(
3813  TaskData *taskData,
3814  PolyStringObject  *string,
3815  Display *d,
3816  Pixmap   bitmap,
3817  unsigned w,
3818  unsigned h,
3819  int      x,
3820  int      y
3821)
3822{
3823  char name[500]; int s;
3824
3825  Poly_string_to_C(string,name,sizeof(name));
3826
3827  s = XWriteBitmapFile(d,name,bitmap,w,h,x,y);
3828
3829  return Make_arbitrary_precision(taskData, s);
3830}
3831
3832static Handle GetDefault(TaskData *taskData, Display *d, PolyStringObject *s1, PolyStringObject *s2)
3833{
3834  char program[500]; char option[500]; char *s;
3835
3836  Poly_string_to_C(s1,program,sizeof(program));
3837  Poly_string_to_C(s2,option ,sizeof(option));
3838
3839  s = XGetDefault(d,program,option);
3840
3841  if (s == NULL) RaiseXWindows(taskData, "XGetDefault failed");
3842
3843  return Make_string(s);
3844}
3845
3846
3847static void GetWindows(TaskData *taskData, PolyWord p, void *w, unsigned)
3848{
3849    *(Window *)w = GetWindow(taskData, (X_Object *)p.AsObjPtr());
3850}
3851
3852
3853static void GetSegments(TaskData *taskData, PolyWord pp, void *w, unsigned)
3854{
3855    XSegment *A = (XSegment *)w;
3856    PolyObject *p = pp.AsObjPtr();
3857    A->x1 = GetPointX(taskData, p->Get(0));
3858    A->y1 = GetPointY(taskData, p->Get(0));
3859    A->x2 = GetPointX(taskData, p->Get(1));
3860    A->y2 = GetPointY(taskData, p->Get(1));
3861}
3862
3863static void GetChar2(TaskData *taskData, PolyWord p, void *v, unsigned)
3864{
3865    XChar2b *A = (XChar2b *)v;
3866    unsigned short u = get_C_ushort(taskData, p);
3867    A->byte1 = u >> 8;
3868    A->byte2 = u &0xFF;
3869}
3870
3871static void CopyString(TaskData *, PolyWord w, void *v, unsigned)
3872{
3873    char **p = (char**)v;
3874    PolyStringObject *s = GetString(w);
3875    POLYUNSIGNED    n = s->length+1;
3876    *p = (char*)malloc(n);
3877    Poly_string_to_C(s,*p,n);
3878}
3879
3880static void GetText(TaskData *taskData, PolyWord p, void *w, unsigned)
3881{
3882    XTextItem *A = (XTextItem *)w;
3883    PolyObject *obj = p.AsObjPtr();
3884    CopyString(taskData, obj->Get(0), &A->chars, 0);
3885
3886    A->nchars = strlen(A->chars);
3887    A->delta  = get_C_short(taskData, obj->Get(1));
3888    A->font   = GetFont(taskData, (X_Object *)obj->Get(2).AsObjPtr());
3889}
3890
3891static void GetText16(TaskData *taskData, PolyWord p, void *v, unsigned)
3892{
3893    XTextItem16 *A = (XTextItem16 *)v;
3894    PolyObject *obj = p.AsObjPtr();
3895    unsigned     N = ListLength(obj->Get(0));
3896    XChar2b *L = (XChar2b *) malloc(N * sizeof(XChar2b));
3897
3898    GetList4(taskData,obj->Get(0),L,sizeof(XChar2b),GetChar2);
3899
3900    A->chars  = L;
3901    A->nchars = N;
3902    A->delta  = get_C_short(taskData, obj->Get(1));
3903    A->font   = GetFont(taskData, (X_Object *)obj->Get(2).AsObjPtr());
3904}
3905
3906typedef void (*GetFunc)(TaskData *taskData, PolyWord, void*, unsigned);
3907
3908static void SetClipRectangles
3909(
3910  TaskData *taskData,
3911  Display *d,
3912  GC       gc,
3913  int      x,
3914  int      y,
3915  Handle   list,
3916  unsigned order
3917)
3918{
3919  if (ISNIL(DEREFWORD(list)))
3920  {
3921    XSetClipRectangles(d,gc,x,y,NULL,0,order);
3922  }
3923  else
3924  {
3925    unsigned        N = ListLength(DEREFWORD(list));
3926    XRectangle *L = (XRectangle *) alloca(N * sizeof(XRectangle));
3927
3928    GetList4(taskData, DEREFWORD(list),L,sizeof(XRectangle),GetRects);
3929
3930    XSetClipRectangles(d,gc,x,y,L,N,order);
3931  }
3932}
3933
3934static void GetUChars(TaskData *taskData, PolyWord p, void *u, unsigned)
3935{
3936    *(uchar*)u = get_C_uchar(taskData, p);
3937}
3938
3939static void SetDashes
3940(
3941 TaskData *taskData,
3942 Display *d,
3943 GC       gc,
3944 unsigned offset,
3945 Handle   list
3946 )
3947{
3948    if (NONNIL(DEREFWORD(list)))
3949    {
3950        unsigned   N = ListLength(DEREFWORD(list));
3951        char *D  = (char *) alloca(N);
3952
3953        GetList4(taskData,DEREFWORD(list),D,sizeof(uchar),GetUChars);
3954
3955        XSetDashes(d,gc,offset,D,N);
3956    }
3957}
3958
3959static Handle CreateDrawable
3960(
3961  TaskData *taskData,
3962  void  *p,
3963  Handle   dsHandle /* Handle to (X_Display_Object *) */
3964)
3965{
3966    return EmptyWindow(taskData, dsHandle,*(Window*)p);
3967}
3968
3969static Handle QueryTree
3970(
3971  TaskData *taskData,
3972  Handle   dsHandle, /* Handle to (X_Display_Object *) */
3973  Window   w
3974)
3975{
3976  Window root,parent,*children;
3977  unsigned n;
3978  Handle data;
3979
3980  int s = XQueryTree(DEREFDISPLAYHANDLE(dsHandle)->display,w,&root,&parent,&children,&n);
3981
3982  if (s == 0) RaiseXWindows(taskData, "XQueryTree failed");
3983
3984  data = CreateTriple(taskData, EmptyWindow(taskData, dsHandle,root),
3985                      EmptyWindow(taskData, dsHandle,parent),
3986                      CreateList5(taskData, n,children,sizeof(Window),CreateDrawable,dsHandle));
3987
3988  if (n) XFree((char *)children);
3989
3990  return data;
3991}
3992
3993static void RestackWindows(TaskData *taskData, Handle list /* handle to list of X_Window_Objects (?) */)
3994{
3995  if (NONNIL(DEREFWORD(list)))
3996  {
3997    unsigned N = ListLength(DEREFWORD(list));
3998    Window  *W = (Window *) alloca(N * sizeof(Window));
3999    Display *d = GetDisplay(taskData, (X_Object *)DEREFLISTHANDLE(list)->h.AsObjPtr());
4000
4001    GetList4(taskData, DEREFWORD(list),W,sizeof(Window),GetWindows);
4002
4003    XRestackWindows(d,W,N);
4004  }
4005}
4006
4007static Handle GetGeometry
4008(
4009  TaskData *taskData,
4010  Handle   dsHandle, /* Handle to (X_Display_Object *) */
4011  Drawable w
4012)
4013{
4014  int x,y;
4015  unsigned width,height,borderWidth,depth;
4016  Window root;
4017  Handle dataHandle;
4018
4019  int s = XGetGeometry(DEREFDISPLAYHANDLE(dsHandle)->display,w,&root,&x,&y,&width,&height,&borderWidth,&depth);
4020
4021  if (s == 0) RaiseXWindows(taskData, "XGetGeometry failed");
4022
4023  dataHandle = alloc_and_save(taskData, 5, F_MUTABLE_BIT);
4024
4025#define data DEREFHANDLE(dataHandle)
4026  data->Set(0, DEREFWORD(EmptyWindow(taskData, dsHandle,root)));
4027  data->Set(1, DEREFWORD(CreatePoint(taskData, x,y)));
4028  data->Set(2, DEREFWORD(CreateArea(width,height)));
4029  data->Set(3, DEREFWORD(Make_arbitrary_precision(taskData, borderWidth)));
4030  data->Set(4, DEREFWORD(Make_arbitrary_precision(taskData, depth)));
4031#undef data
4032
4033  return FINISHED(taskData, dataHandle);
4034}
4035
4036static Handle GetWindowAttributes
4037(
4038  TaskData *taskData,
4039  Handle   dsHandle, /* Handle to (X_Display_Object *) */
4040  Drawable w
4041)
4042{
4043  XWindowAttributes wa;
4044  Handle dataHandle;
4045
4046  int s = XGetWindowAttributes(DEREFDISPLAYHANDLE(dsHandle)->display,w,&wa);
4047
4048  if (s == 0) RaiseXWindows(taskData, "XGetWindowAttributes failed");
4049
4050  dataHandle = alloc_and_save(taskData, 20, F_MUTABLE_BIT);
4051
4052/* HACKY - should define struct? */
4053  DEREFHANDLE(dataHandle)->Set( 0, DEREFWORD(CreatePoint(taskData, wa.x,wa.y)));
4054  DEREFHANDLE(dataHandle)->Set( 1, DEREFWORD(CreateArea(wa.width,wa.height)));
4055  DEREFHANDLE(dataHandle)->Set( 2, DEREFWORD(Make_int(wa.border_width)));
4056  DEREFHANDLE(dataHandle)->Set( 3, DEREFWORD(Make_arbitrary_precision(taskData, wa.depth)));
4057  DEREFHANDLE(dataHandle)->Set( 4, DEREFWORD(EmptyVisual(taskData, dsHandle,wa.visual)));
4058  DEREFHANDLE(dataHandle)->Set( 5, DEREFWORD(EmptyWindow(taskData, dsHandle,wa.root)));
4059  DEREFHANDLE(dataHandle)->Set( 6, DEREFWORD(Make_arbitrary_precision(taskData, wa.c_class)));
4060  DEREFHANDLE(dataHandle)->Set( 7, DEREFWORD(Make_arbitrary_precision(taskData, wa.bit_gravity)));
4061  DEREFHANDLE(dataHandle)->Set( 8, DEREFWORD(Make_arbitrary_precision(taskData, wa.win_gravity)));
4062  DEREFHANDLE(dataHandle)->Set( 9, DEREFWORD(Make_arbitrary_precision(taskData, wa.backing_store)));
4063  DEREFHANDLE(dataHandle)->Set(10, DEREFWORD(Make_arbitrary_precision(taskData, wa.backing_planes)));
4064  DEREFHANDLE(dataHandle)->Set(11, DEREFWORD(Make_arbitrary_precision(taskData, wa.backing_pixel)));
4065  DEREFHANDLE(dataHandle)->Set(12, DEREFWORD(Make_bool(wa.save_under)));
4066  DEREFHANDLE(dataHandle)->Set(13, DEREFWORD(EmptyColormap(taskData, dsHandle,wa.colormap)));
4067  DEREFHANDLE(dataHandle)->Set(14, DEREFWORD(Make_bool(wa.map_installed)));
4068  DEREFHANDLE(dataHandle)->Set(15, DEREFWORD(Make_arbitrary_precision(taskData, wa.map_state)));
4069  DEREFHANDLE(dataHandle)->Set(16, DEREFWORD(Make_arbitrary_precision(taskData, wa.all_event_masks)));
4070  DEREFHANDLE(dataHandle)->Set(17, DEREFWORD(Make_arbitrary_precision(taskData, wa.your_event_mask)));
4071  DEREFHANDLE(dataHandle)->Set(18, DEREFWORD(Make_arbitrary_precision(taskData, wa.do_not_propagate_mask)));
4072  DEREFHANDLE(dataHandle)->Set(19, DEREFWORD(Make_bool(wa.override_redirect)));
4073
4074  return FINISHED(taskData, dataHandle);
4075}
4076
4077static void ChangeWindowAttributes
4078(
4079  TaskData *taskData,
4080  X_Window_Object *W,
4081  unsigned         n,
4082  PolyWord         P
4083)
4084{
4085  XSetWindowAttributes a;
4086
4087  unsigned mask = 1 << n;
4088
4089  switch(mask)
4090  {
4091    case CWBitGravity:       a.bit_gravity           = get_C_ulong(taskData, P); break;
4092    case CWWinGravity:       a.win_gravity           = get_C_ulong(taskData, P); break;
4093    case CWBackingStore:     a.backing_store         = get_C_ulong(taskData, P); break;
4094    case CWBackingPlanes:    a.backing_planes        = get_C_ulong(taskData, P); break;
4095    case CWBackingPixel:     a.backing_pixel         = get_C_ulong(taskData, P); break;
4096    case CWOverrideRedirect: a.override_redirect     = get_C_ulong(taskData, P); break;
4097    case CWSaveUnder:        a.save_under            = get_C_ulong(taskData, P); break;
4098    case CWEventMask:        a.event_mask            = get_C_ulong(taskData, P); break;
4099    case CWDontPropagate:    a.do_not_propagate_mask = get_C_ulong(taskData, P); break;
4100
4101    case CWBackPixel:    a.background_pixel = get_C_ulong(taskData, P);
4102                         W->backgroundPixmap = 0;
4103                         break;
4104
4105    case CWBackPixmap:   a.background_pixmap = GetPixmap(taskData, (X_Object *)P.AsObjPtr());
4106                         W->backgroundPixmap = PixmapObject((X_Object *)P.AsObjPtr());
4107                         break;
4108
4109    case CWBorderPixel:  a.border_pixel = get_C_ulong(taskData, P);
4110                         W->borderPixmap = 0;
4111                         break;
4112
4113    case CWBorderPixmap: a.border_pixmap = GetPixmap(taskData, (X_Object *)P.AsObjPtr());
4114                         W->borderPixmap = PixmapObject((X_Object *)P.AsObjPtr());
4115                         break;
4116
4117    case CWColormap:     a.colormap = GetColormap(taskData, (X_Object *)P.AsObjPtr());
4118                         W->colormap_object = ColormapObject((X_Object *)P.AsObjPtr());
4119                         break;
4120
4121    case CWCursor:       a.cursor = GetCursor(taskData, (X_Object *)P.AsObjPtr());
4122                         W->cursor_object = CursorObject((X_Object *)P.AsObjPtr());
4123                         break;
4124
4125    default: Crash ("Bad window mask %u",mask);
4126  }
4127
4128  XChangeWindowAttributes(GetDisplay(taskData, (X_Object *)W),GetWindow(taskData, (X_Object *)W),mask,&a);
4129}
4130
4131
4132static void ConfigureWindow
4133(
4134  TaskData *taskData,
4135  Display *d,
4136  Window   w,
4137  PolyWord   tup /* (P,S,w,d,s,flags) */
4138)
4139{
4140    PolyObject *tuple = tup.AsObjPtr();
4141  XWindowChanges wc;
4142
4143  unsigned mask = get_C_ulong(taskData, tuple->Get(5));
4144
4145  CheckZeroRect(taskData, tuple->Get(1));
4146
4147  wc.x            = GetPointX  (taskData,tuple->Get(0));
4148  wc.y            = GetPointY  (taskData,tuple->Get(0));
4149  wc.width        = GetRectW   (taskData,tuple->Get(1));
4150  wc.height       = GetRectH   (taskData,tuple->Get(1));
4151  wc.border_width = get_C_ulong(taskData, tuple->Get(2));
4152  wc.sibling      = GetWindow  (taskData,(X_Object *)tuple->Get(3).AsObjPtr());
4153  wc.stack_mode   = get_C_ulong(taskData, tuple->Get(4));
4154
4155  XConfigureWindow(d,w,mask,&wc);
4156}
4157
4158
4159
4160/* The order of these depends on the XColor datatype */
4161
4162typedef struct
4163{
4164  PolyWord red;     /* ML bool */
4165  PolyWord blue;    /* ML bool */
4166  PolyWord doRed;   /* ML bool */
4167  PolyWord green;   /* ML int */
4168  PolyWord pixel;   /* ML int */
4169  PolyWord doBlue;  /* ML int */
4170  PolyWord doGreen; /* ML int */
4171} MLXColor;      /* in Poly heap */
4172
4173static void ClearXColor(XColor *x)
4174{
4175  x->red = x->green = x->blue = x->pixel = x->flags = 0;
4176}
4177
4178static Handle CreateXColor(TaskData *taskData, XColor *x)
4179{
4180  Handle XHandle = alloc_and_save(taskData, SIZEOF(MLXColor), F_MUTABLE_BIT);
4181
4182#define X ((MLXColor *)DEREFHANDLE(XHandle))
4183  X->red     = DEREFWORD(Make_arbitrary_precision(taskData, x->red));
4184  X->green   = DEREFWORD(Make_arbitrary_precision(taskData, x->green));
4185  X->blue    = DEREFWORD(Make_arbitrary_precision(taskData, x->blue));
4186  X->pixel   = DEREFWORD(Make_arbitrary_precision(taskData, x->pixel));
4187  X->doRed   = DEREFWORD(Make_bool(x->flags &DoRed));
4188  X->doGreen = DEREFWORD(Make_bool(x->flags &DoGreen));
4189  X->doBlue  = DEREFWORD(Make_bool(x->flags &DoBlue));
4190#undef X
4191
4192  return FINISHED(taskData, XHandle);
4193}
4194
4195static Handle CreateXColorF(TaskData *taskData, void *p)
4196{
4197    return CreateXColor(taskData, (XColor*)p);
4198}
4199
4200static XColor xcolor1 = { 0 };
4201static XColor xcolor2 = { 0 };
4202
4203static void GetXColor(TaskData *taskData, PolyWord p, void *v, unsigned)
4204{
4205    MLXColor *P = (MLXColor *)p.AsObjPtr();
4206    XColor *x = (XColor *)v;
4207    x->red   = get_C_ushort(taskData, P->red);
4208    x->green = get_C_ushort(taskData, P->green);
4209    x->blue  = get_C_ushort(taskData, P->blue);
4210    x->pixel = get_C_ulong (taskData, P->pixel);
4211
4212    x->flags = (DoRed   * get_C_ulong(taskData, P->doRed))
4213        | (DoGreen * get_C_ulong(taskData, P->doGreen))
4214        | (DoBlue  * get_C_ulong(taskData, P->doBlue));
4215}
4216
4217static XColor *GetXColor1(TaskData *taskData, PolyWord P)
4218{
4219    GetXColor(taskData, P, &xcolor1, 0);
4220    return &xcolor1;
4221}
4222
4223static XColor *GetXColor2(TaskData *taskData, PolyWord P)
4224{
4225    GetXColor(taskData, P, &xcolor2, 0);
4226    return &xcolor2;
4227}
4228
4229static Handle AllocColor(TaskData *taskData, Display *d, Colormap cmap, XColor *x)
4230{
4231  int s = XAllocColor(d,cmap,x);
4232
4233  if (s == 0) RaiseXWindows(taskData, "XAllocColor failed");
4234
4235  return CreateXColor(taskData, x);
4236}
4237
4238static Handle CreateUnsigned(TaskData *taskData, void *q)
4239{
4240    unsigned *p = (unsigned *)q;
4241    return Make_arbitrary_precision(taskData, *p);
4242}
4243
4244static Handle CreateUnsignedLong(TaskData *taskData, void *p)
4245{
4246    return Make_arbitrary_precision(taskData, *(unsigned long*)p);
4247}
4248
4249static Handle AllocColorCells
4250(
4251  TaskData *taskData,
4252  Display *d,
4253  Colormap cmap,
4254  unsigned contig,
4255  unsigned nplanes,
4256  unsigned ncolors
4257)
4258{
4259  unsigned long *masks;  /* was unsigned SPF 6/1/94 */
4260  unsigned long *pixels; /* was unsigned SPF 6/1/94 */
4261  int s;
4262
4263  if (ncolors < 1) RaiseRange(taskData);
4264
4265  masks  = (unsigned long *) alloca(nplanes * sizeof(unsigned long));
4266  pixels = (unsigned long *) alloca(ncolors * sizeof(unsigned long));
4267
4268  s = XAllocColorCells(d,cmap,contig,masks,nplanes,pixels,ncolors);
4269
4270  if (s == 0) RaiseXWindows (taskData, "XAllocColorCells failed");
4271
4272  return CreatePair(taskData, CreateList4(taskData,nplanes,masks ,sizeof(unsigned long),CreateUnsignedLong),
4273                    CreateList4(taskData,ncolors,pixels,sizeof(unsigned long),CreateUnsignedLong));
4274}
4275
4276static Handle AllocColorPlanes
4277(
4278  TaskData *taskData,
4279  Display *d,
4280  Colormap cmap,
4281  unsigned contig,
4282  unsigned ncolors,
4283  unsigned nreds,
4284  unsigned ngreens,
4285  unsigned nblues
4286)
4287{
4288  unsigned long rmask;   /* was unsigned SPF 6/1/94 */
4289  unsigned long gmask;   /* was unsigned SPF 6/1/94 */
4290  unsigned long bmask;   /* was unsigned SPF 6/1/94 */
4291  unsigned long *pixels; /* was unsigned SPF 6/1/94 */
4292  Handle tuple;
4293  int s;
4294
4295  if (ncolors < 1) RaiseRange(taskData);
4296
4297  pixels = (unsigned long *) alloca(ncolors * sizeof(unsigned long));
4298
4299  s = XAllocColorPlanes(d,cmap,contig,pixels,ncolors,nreds,ngreens,nblues,&rmask,&gmask,&bmask);
4300
4301  if (s == 0) RaiseXWindows (taskData, "XAllocColorPlanes failed");
4302
4303  tuple = alloc_and_save(taskData, 4, F_MUTABLE_BIT);
4304
4305#define data DEREFHANDLE(tuple)
4306  data->Set(0, DEREFWORD(CreateList4(taskData,ncolors,pixels,sizeof(unsigned long),CreateUnsignedLong)));
4307  data->Set(1, DEREFWORD(Make_arbitrary_precision(taskData, rmask)));
4308  data->Set(2, DEREFWORD(Make_arbitrary_precision(taskData, gmask)));
4309  data->Set(3, DEREFWORD(Make_arbitrary_precision(taskData, bmask)));
4310#undef data
4311
4312  return FINISHED(taskData, tuple);
4313}
4314
4315static Handle AllocNamedColor(TaskData *taskData, Display *d, Colormap cmap, PolyStringObject *string)
4316{
4317  char   name[500];
4318  int    s;
4319  XColor hardware;
4320  XColor database;
4321
4322  ClearXColor(&hardware);
4323  ClearXColor(&database);
4324
4325  Poly_string_to_C(string,name,sizeof(name));
4326
4327  s = XAllocNamedColor(d,cmap,name,&hardware,&database);
4328
4329  if (s == 0) RaiseXWindows (taskData, "XAllocNamedColor failed");
4330
4331  return CreatePair(taskData, CreateXColor(taskData, &hardware),CreateXColor(taskData, &database));
4332}
4333
4334static Handle LookupColor(TaskData *taskData, Display *d, Colormap cmap, PolyStringObject *string)
4335{
4336  char   name[500];
4337  int    s;
4338  XColor hardware;
4339  XColor database;
4340
4341  ClearXColor(&hardware);
4342  ClearXColor(&database);
4343
4344  Poly_string_to_C(string,name,sizeof(name));
4345
4346  s = XLookupColor(d,cmap,name,&database,&hardware);
4347
4348  if (s == 0) RaiseXWindows (taskData, "XLookupColor failed");
4349
4350  return CreatePair(taskData, CreateXColor(taskData, &database),CreateXColor(taskData, &hardware));
4351}
4352
4353static Handle ParseColor(TaskData *taskData, Display *d, Colormap cmap, PolyStringObject *string)
4354{
4355  char   name[500];
4356  int    s;
4357  XColor x;
4358
4359  ClearXColor(&x);
4360
4361  Poly_string_to_C(string,name,sizeof(name));
4362
4363  s = XParseColor(d,cmap,name,&x);
4364
4365  if (s == 0) RaiseXWindows(taskData, "XParseColor failed");
4366
4367  return CreateXColor(taskData, &x);
4368}
4369
4370static Handle QueryColor(TaskData *taskData, Display *d, Colormap cmap, unsigned pixel)
4371{
4372  XColor x;
4373
4374  ClearXColor(&x);
4375
4376  x.pixel = pixel;
4377
4378  XQueryColor(d,cmap,&x);
4379
4380  return CreateXColor(taskData, &x);
4381}
4382
4383static void GetXPixel(TaskData *taskData, PolyWord p, void *v, unsigned)
4384{
4385    XColor *X = (XColor *)v;
4386    ClearXColor(X);
4387    X->pixel = get_C_ulong(taskData, p);
4388}
4389
4390static Handle QueryColors(TaskData *taskData, Display *d, Colormap cmap, Handle list)
4391{
4392  unsigned N = ListLength(DEREFWORD(list));
4393  XColor  *P = (XColor *) alloca(N * sizeof(XColor));
4394
4395  GetList4(taskData, DEREFWORD(list),P,sizeof(XColor),GetXPixel);
4396
4397  XQueryColors(d,cmap,P,N);
4398
4399  return CreateList4(taskData,N,P,sizeof(XColor),CreateXColorF);
4400}
4401
4402static void StoreNamedColor
4403(
4404  Display *d,
4405  Colormap cmap,
4406  PolyStringObject  *string,
4407  unsigned pixel,
4408  unsigned doRed,
4409  unsigned doGreen,
4410  unsigned doBlue
4411)
4412{
4413  unsigned flags = (DoRed * doRed) | (DoGreen * doGreen) | (DoBlue * doBlue);
4414
4415  char name[500];
4416
4417  Poly_string_to_C(string,name,sizeof(name));
4418
4419  XStoreNamedColor(d,cmap,name,pixel,flags);
4420}
4421
4422static void StoreColors(TaskData *taskData, Display *d, Colormap cmap, Handle list)
4423{
4424  unsigned N = ListLength(DEREFWORD(list));
4425  XColor  *P = (XColor *) alloca(N * sizeof(XColor));
4426
4427  GetList4(taskData, DEREFWORD(list),P,sizeof(XColor),GetXColor);
4428
4429  XStoreColors(d,cmap,P,N);
4430}
4431
4432static void GetUnsigned(TaskData *taskData, PolyWord p, void *v, unsigned)
4433{
4434    unsigned *u = (unsigned *)v;
4435    *u = get_C_ulong(taskData, p);
4436}
4437
4438static void GetUnsignedLong(TaskData *taskData, PolyWord p, void *v, unsigned)
4439{
4440    unsigned long *u = (unsigned long *)v;
4441    *u = get_C_ulong(taskData, p);
4442}
4443
4444
4445static void FreeColors
4446(
4447  TaskData *taskData,
4448  Display *d,
4449  Colormap cmap,
4450  Handle   list,
4451  unsigned planes
4452)
4453{
4454  unsigned  N = ListLength(DEREFWORD(list));
4455  unsigned long *P = (unsigned long *) alloca(N * sizeof(unsigned long));
4456
4457  GetList4(taskData,DEREFWORD(list),P,sizeof(unsigned long),GetUnsignedLong);
4458
4459  XFreeColors(d,cmap,P,N,planes);
4460}
4461
4462static Handle CreateColormap
4463(
4464  TaskData *taskData,
4465  void *p,
4466  Handle   dsHandle /* handle to (X_Display_Object *) */
4467)
4468{
4469  return EmptyColormap(taskData, dsHandle,*(Colormap *)p);
4470}
4471
4472static Handle ListInstalledColormaps
4473(
4474  TaskData *taskData,
4475  Handle   dsHandle, /* handle to (X_Display_Object *) */
4476  Drawable drawable
4477)
4478{
4479  int  count;
4480  Colormap *cmaps;
4481  Handle list;
4482
4483  cmaps = XListInstalledColormaps(DEREFDISPLAYHANDLE(dsHandle)->display,drawable,&count);
4484
4485  if (cmaps == 0) RaiseXWindows(taskData, "XListInstalledColormaps failed");
4486
4487  list = CreateList5(taskData,count,cmaps,sizeof(Colormap),CreateColormap,dsHandle);
4488
4489  XFree((char *)cmaps);
4490
4491  return list;
4492}
4493
4494
4495static Handle GetTimeOfDay(TaskData *taskData)
4496{
4497  TimeVal now;
4498
4499  gettimeofday(&now, NULL);
4500
4501  return CreatePair(taskData, Make_arbitrary_precision(taskData, now.tv_sec),Make_arbitrary_precision(taskData, now.tv_usec));
4502}
4503
4504static Handle GetState(TaskData *taskData, X_Window_Object *P)
4505{
4506  assert(UNTAGGED(P->type) == X_Window);
4507
4508  CheckExists((X_Object *)P,window);
4509
4510  if (ISNIL(P->handler)) Crash ("No handler set");
4511
4512  return CreatePair(taskData, SAVE(P->handler),SAVE(P->state));
4513}
4514
4515static void SetState(X_Window_Object *W, PolyWord handler, PolyWord state)
4516{
4517  if (! ResourceExists((X_Object *)W)) return;
4518
4519  assert(W->type == TAGGED(X_Window));
4520
4521  if (NONNIL(handler))
4522  {
4523    /* we are setting the handler and initial state    */
4524    /* so we need to remove all pending messages for   */
4525    /* this window since they will have the wrong type */
4526
4527    PurgePendingWindowMessages(W);
4528
4529    W->handler = handler;
4530    W->state = state;
4531
4532  }
4533  else W->state = state;   /* just update state */
4534}
4535
4536/* Check if the first timer event has already expired. */
4537static void CheckTimerQueue(void)
4538{
4539  if (TList)
4540  {
4541    TimeVal now;
4542    gettimeofday(&now, NULL);
4543    TList->expired = TimeLeq(&TList->timeout,&now);
4544  }
4545}
4546
4547static void InsertTimeout
4548(
4549  TaskData *taskData,
4550  X_Window_Object *window_object,
4551  unsigned        ms,
4552  PolyWord        alpha,
4553  PolyWord        handler
4554)
4555{
4556  T_List **tail;
4557  T_List *newp;
4558  TimeVal now;
4559
4560  assert(window_object->type == TAGGED(X_Window));
4561  CheckExists((X_Object *)window_object,window);
4562
4563  if (ISNIL(window_object->handler)) Crash ("No handler set");
4564
4565  if (window_object->handler != handler) RaiseXWindows(taskData, "Handler mismatch");
4566
4567  { /* find insertion point in list */
4568    TimeVal dt;
4569
4570    gettimeofday(&now, NULL);
4571    dt.tv_sec  = ms / 1000;
4572    dt.tv_usec = 1000 * (ms % 1000);
4573
4574    newp = (T_List *) malloc(sizeof(T_List));
4575    TimeAdd(&now,&dt,&newp->timeout);
4576
4577    /* We use TimeLt here, not TimeLeq, because we
4578       want to add new messages AFTER existing ones.
4579       SPF 21/3/97
4580    */
4581    for(tail = &TList; *tail; tail = &(*tail)->next)
4582    {
4583      if (TimeLt(&newp->timeout,&(*tail)->timeout)) break;
4584    }
4585  }
4586
4587  newp->next          = *tail;
4588  newp->window_object = window_object;
4589  newp->widget_object = (X_Widget_Object *)0;
4590  newp->alpha         = alpha.AsObjPtr();
4591  newp->handler       = handler.AsObjPtr();
4592  newp->expired       = 0;
4593
4594  *tail = newp;
4595}
4596
4597/* called when a widget is destroyed by Xt/Motif */
4598static void DestroyWidgetCallback
4599(
4600  Widget    widget,
4601  XtPointer client_data,
4602  XtPointer call_data
4603)
4604{
4605  /* find the ML widget (if any) associated with the C widget */
4606  X_Widget_Object *widget_object = FindWidget(widget);
4607
4608  if (widget_object != NULL)
4609    {
4610      /* Destroy the ML widget representations */
4611      DestroyXObject((X_Object *)widget_object);
4612      /* Assume we can't get a C callback from a destroyed widget */
4613      PurgeCCallbacks(widget_object,widget);
4614    }
4615
4616  debugReclaim(Widget,widget);
4617}
4618
4619#if 0
4620#define CheckRealized(Widget,Where)\
4621{ \
4622  if (XtIsRealized(Widget) == False) \
4623    RaiseXWindows(taskData, #Where ": widget is not realized"); \
4624}
4625
4626static Window WindowOfWidget(TaskData *taskData, Widget widget)
4627{
4628  CheckRealized(widget,WindowOfWidget);
4629  return XtWindowOfObject(widget);
4630}
4631#endif
4632
4633/* Now returns NULL (None) for unrealized widgets SPF 1/2/94 */
4634static Window WindowOfWidget(Widget widget)
4635{
4636  return XtIsRealized(widget) ? XtWindowOfObject(widget) : None;
4637}
4638
4639
4640static void InsertWidgetTimeout
4641(
4642 TaskData *taskData,
4643 X_Widget_Object *widget_object,
4644 unsigned         ms,
4645 PolyWord         alpha,
4646 PolyWord         handler
4647 )
4648{
4649    T_List **tail;
4650    T_List *newp;
4651    TimeVal now;
4652
4653    assert(widget_object->type == TAGGED(X_Widget));
4654    CheckExists((X_Object *)widget_object,widget);
4655#if NEVER
4656    CheckRealized(GetWidget(taskData, (X_Object *)widget_object),InsertWidgetTimeout);
4657#endif
4658
4659    /* check that handler occurs in widget's callback list */
4660    {
4661        PolyWord p = widget_object->callbackList;
4662        for(; NONNIL(p); p = ((ML_Cons_Cell*)p.AsObjPtr())->t)
4663        {
4664            MLPair *q = (MLPair *)((ML_Cons_Cell*)p.AsObjPtr())->h.AsObjPtr();
4665            if (SND(q) == handler) break;
4666        }
4667        if (ISNIL(p)) RaiseXWindows(taskData, "Handler mismatch");
4668    }
4669
4670
4671    {
4672        TimeVal dt;
4673
4674        gettimeofday(&now, NULL);
4675
4676        dt.tv_sec = ms / 1000;
4677        dt.tv_usec = 1000 * (ms % 1000);
4678
4679        newp = (T_List *) malloc(sizeof(T_List));
4680
4681        TimeAdd(&now,&dt,&newp->timeout);
4682
4683        /* We use TimeNegative here, not TimeExpired, because we
4684        want to add new messages AFTER existing ones.
4685        SPF 21/3/97
4686        */
4687        for(tail = &TList; *tail; tail = &(*tail)->next)
4688        {
4689            if (TimeLt(&newp->timeout,&(*tail)->timeout)) break;
4690        }
4691    }
4692
4693    newp->next          = *tail;
4694    newp->window_object = (X_Window_Object *)0;
4695    newp->widget_object = widget_object;
4696    newp->alpha         = alpha.AsObjPtr();
4697    newp->handler       = handler.AsObjPtr();
4698    newp->expired       = 0;
4699
4700    *tail = newp;
4701}
4702
4703static Handle NextEvent(TaskData *taskData, Handle dsHandle /* handle to (X_Display_Object *) */)
4704{
4705    for (;;)
4706    {
4707        /* Added here SPF 23/2/95 - check whether a timer event has expired */
4708        CheckTimerQueue();
4709
4710        if (TList && TList->expired)
4711        {
4712            T_List *next = TList->next;
4713
4714            EventHandle E = alloc_and_save(taskData, SIZEOF(ML_Event), F_MUTABLE_BIT);
4715
4716#define event ((ML_Event *)DEREFHANDLE(E))
4717            event->type       = DEREFWORD(Make_arbitrary_precision(taskData, 99));
4718            event->sendEvent  = DEREFWORD(Make_bool(True));
4719            event->data       = TList->alpha;
4720
4721            if (TList->window_object != 0)
4722            {
4723                assert(TList->widget_object == 0);
4724
4725                event->window     = TList->window_object;
4726                event->callbacks  = ListNull;
4727                event->events     = ListNull;
4728
4729                assert(TList->window_object->handler == TList->handler);
4730            }
4731            else /* it is a Widget message */
4732            {
4733                /* TList->widget_object etc. act like Roots */
4734                assert(TList->widget_object != 0);
4735
4736                {
4737                    Window w        = WindowOfWidget(GetWidget(taskData, (X_Object *)TList->widget_object));
4738                    event->window   = DEREFWINDOWHANDLE(EmptyWindow(taskData, GetDS(taskData, (X_Object *)TList->widget_object),w));
4739                }
4740
4741                { /* create callback list - allocates storage */
4742                    Handle tailHandle    = SAVE(ListNull);
4743                    Handle widgetHandle  = SAVE(TList->widget_object);
4744                    Handle handlerHandle = SAVE(TList->handler);
4745                    Handle pairHandle    = CreatePair(taskData, widgetHandle,handlerHandle);
4746
4747                    event->callbacks     = DEREFLISTHANDLE(CreatePair(taskData, pairHandle,tailHandle));
4748                    event->events        = ListNull;
4749                }
4750            }
4751#undef event
4752
4753            free(TList);
4754
4755            TList = next;
4756
4757            return FINISHED(taskData, E);
4758        }
4759        else /* ! (TList && TList->expired) */ if (DEREFDISPLAYHANDLE(dsHandle)->app_context == 0)
4760                /* use XNextEvent to get next event */
4761        {
4762            Display *display = DEREFDISPLAYHANDLE(dsHandle)->display;
4763            int      pending = XPending(display);
4764
4765            if (pending == 0)
4766            {
4767                WaitInputFD waiter(display->fd);
4768                processes->ThreadPauseForIO(taskData, &waiter);
4769            }
4770            else /* X Event arrived */
4771            {
4772                XEvent ev;
4773                X_Window_Object *W;
4774
4775                XNextEvent(display,&ev);
4776                W = FindWindow(dsHandle,ev.xany.window);
4777
4778                if (W && NONNIL(W->handler))
4779                {
4780                    EventHandle E = CreateEvent(taskData, dsHandle,&ev,SAVE(W));
4781                    if (E) return E;
4782                }
4783            }
4784        }
4785        else /* use XtAppNextEvent to get next event */
4786        {
4787            /* should use Xt to do time events as well */
4788            int pending = XtAppPending(DEREFDISPLAYHANDLE(dsHandle)->app_context);
4789
4790            if (pending == 0)
4791            {
4792                WaitInputFD waiter(DEREFDISPLAYHANDLE(dsHandle)->display->fd);
4793                processes->ThreadPauseForIO(taskData, &waiter);
4794            }
4795            else
4796            {
4797                if ((pending & XtIMXEvent) == 0)   /* not an X Event, probably an Xt timer event */
4798                {
4799                    assert(FList == TAGGED(0));
4800
4801                    callbacks_enabled = True;
4802                    XtAppProcessEvent(DEREFDISPLAYHANDLE(dsHandle)->app_context,pending);
4803                    callbacks_enabled = False;
4804
4805                    if (FList != TAGGED(0))
4806                    {
4807                        EventHandle E = alloc_and_save(taskData, SIZEOF(ML_Event), F_MUTABLE_BIT);
4808
4809#define event ((ML_Event *)DEREFHANDLE(E))
4810                        event->type      = DEREFWORD(Make_arbitrary_precision(taskData, 100));
4811                        event->sendEvent = DEREFWORD(Make_bool(True));
4812                        event->window    = TAGGED(0);
4813                        event->data      = TAGGED(0);
4814                        event->callbacks = FList; /* FList != 0 */
4815                        event->events    = GList;
4816#undef event
4817                        FList = TAGGED(0);
4818                        GList = TAGGED(0);
4819                        return FINISHED(taskData, E);
4820                    }
4821                }
4822                else /* Xt Event arrived */
4823                {
4824                    XEvent ev;
4825                    int dispatched;
4826
4827                    assert(FList == TAGGED(0));
4828
4829                    XtAppNextEvent(DEREFDISPLAYHANDLE(dsHandle)->app_context,&ev);
4830
4831                    callbacks_enabled = True;
4832                    dispatched = XtDispatchEvent(&ev);
4833                    callbacks_enabled = False;
4834
4835                    if (!dispatched)
4836                    {
4837                        X_Window_Object *W = FindWindow(dsHandle,ev.xany.window);
4838
4839                        assert(FList == TAGGED(0) && GList == TAGGED(0));
4840
4841                        if (W && NONNIL(W->handler))
4842                        {
4843                            EventHandle E = CreateEvent(taskData, dsHandle,&ev,SAVE(W));
4844                            if (E) return E;
4845                        }
4846                    }
4847                    else if (! FList.IsTagged() || ! GList.IsTagged())
4848                    {
4849                        EventHandle E = CreateEvent(taskData, dsHandle,&ev,EmptyWindow(taskData, dsHandle,ev.xany.window));
4850                        if (E) return E;
4851                    }
4852                }
4853            }
4854        }
4855    }
4856}
4857
4858static Handle GetInputFocus(TaskData *taskData, Handle dsHandle /* handle to (X_Display_Object *) */)
4859{
4860  Window focus;
4861  int revertTo;
4862
4863  XGetInputFocus(DEREFDISPLAYHANDLE(dsHandle)->display,&focus,&revertTo);
4864
4865  return CreatePair(taskData, EmptyWindow(taskData, dsHandle,focus),Make_arbitrary_precision(taskData, revertTo));
4866}
4867
4868static void SetSelectionOwner
4869(
4870  Handle   dsHandle, /* handle to (X_Display_Object *) */
4871  unsigned selection,
4872  Window   owner,
4873  unsigned time
4874)
4875{
4876  Window old = XGetSelectionOwner(DEREFDISPLAYHANDLE(dsHandle)->display,selection);
4877
4878  if (old != owner)
4879  {
4880    /* SelectionClear is only sent by the server when the ownership of a */
4881    /* selection passes from one client to another.  We want every ML    */
4882    /* window to behave like a separate client, so when the ownership of */
4883    /* a selection passes from one ML window to another we have to send  */
4884    /* the SelectionClear ourselves.                                     */
4885
4886    X_Window_Object *W = FindWindow(dsHandle,old);
4887
4888    if (W && NONNIL(W->handler))   /* this clients window */
4889    {
4890      XEvent event; /* was XSelectionClearEvent SPF 6/1/94 */
4891
4892      event.xselectionclear.type       = SelectionClear;
4893      event.xselectionclear.serial     = 0;
4894      event.xselectionclear.send_event = True;
4895      event.xselectionclear.display    = DEREFDISPLAYHANDLE(dsHandle)->display;
4896      event.xselectionclear.window     = old;
4897      event.xselectionclear.selection  = selection;
4898      event.xselectionclear.time       = time;
4899
4900      XSendEvent(DEREFDISPLAYHANDLE(dsHandle)->display,old,True,0,&event);
4901    }
4902  }
4903
4904  XSetSelectionOwner(DEREFDISPLAYHANDLE(dsHandle)->display,selection,owner,time);
4905}
4906
4907static void SendSelectionNotify
4908(
4909  Display *d,
4910  unsigned selection,
4911  unsigned target,
4912  unsigned property,
4913  Window   requestor,
4914  unsigned time
4915)
4916{
4917  XEvent event; /* was XSelectionEvent SPF 6/1/94 */
4918
4919  event.xselection.type       = SelectionNotify;
4920  event.xselection.serial     = 0;
4921  event.xselection.send_event = True;
4922  event.xselection.display    = d;
4923  event.xselection.requestor  = requestor;
4924  event.xselection.selection  = selection;
4925  event.xselection.target     = target;
4926  event.xselection.property   = property;
4927  event.xselection.time       = time;
4928
4929  XSendEvent(d,requestor,True,0,&event);
4930}
4931
4932static Handle InternAtom
4933(
4934  TaskData *taskData,
4935  Display *d,
4936  PolyStringObject  *string,
4937  Bool     only_if_exists
4938)
4939{
4940  char name[500];
4941
4942  Poly_string_to_C(string,name,sizeof(name));
4943
4944  return Make_arbitrary_precision(taskData, XInternAtom(d,name,only_if_exists));
4945}
4946
4947static Handle GetAtomName(TaskData *taskData, Display *d, unsigned atom)
4948{
4949  Handle s;
4950
4951  char *name = XGetAtomName(d,atom);
4952
4953  if (name == NULL) RaiseXWindows(taskData, "XGetAtomName failed");
4954
4955  s = Make_string(name);
4956
4957  XFree((char *)name);
4958
4959  return s;
4960}
4961
4962/* The order of these depends on the XCharStruct datatype */
4963typedef struct
4964{
4965    PolyWord width;      /* ML int */
4966    PolyWord ascent;     /* ML int */
4967    PolyWord descent;    /* ML int */
4968    PolyWord lbearing;   /* ML int */
4969    PolyWord rbearing;   /* ML int */
4970    PolyWord attributes; /* ML int */
4971} MLXCharStruct;
4972
4973static Handle CreateCharStruct(TaskData *taskData, void *v)
4974{
4975    XCharStruct *cs = (XCharStruct *)v;
4976  Handle dataHandle = alloc_and_save(taskData, SIZEOF(MLXCharStruct), F_MUTABLE_BIT);
4977
4978#define data ((MLXCharStruct *)DEREFHANDLE(dataHandle))
4979  data->width      = DEREFWORD(Make_int(cs->width));
4980  data->ascent     = DEREFWORD(Make_int(cs->ascent));
4981  data->descent    = DEREFWORD(Make_int(cs->descent));
4982  data->lbearing   = DEREFWORD(Make_int(cs->lbearing));
4983  data->rbearing   = DEREFWORD(Make_int(cs->rbearing));
4984  data->attributes = DEREFWORD(Make_arbitrary_precision(taskData, cs->attributes));
4985#undef data
4986
4987  return FINISHED(taskData, dataHandle);
4988}
4989
4990/* The order of these depends on the XFontStruct datatype */
4991typedef struct
4992{
4993    X_Font_Object  *font_object;
4994    PolyWord       ascent;        /* ML int */
4995    PolyWord       descent;       /* ML int */
4996    PolyWord       maxChar;       /* ML int */
4997    PolyWord       minChar;       /* ML int */
4998    PolyWord       perChar;       /* ML XCharStruct list */
4999    PolyWord       maxByte1;      /* ML int */
5000    PolyWord       minByte1;      /* ML int */
5001    PolyWord       direction;     /* (short ML int) FontLeftToRight | FontRightToLeft */
5002    MLXCharStruct  *maxBounds;
5003    MLXCharStruct  *minBounds;
5004    PolyWord       defaultChar;   /* ML int */
5005    PolyWord       allCharsExist; /* ML bool */
5006} MLXFontStruct;
5007
5008static Handle CreateFontStruct
5009(
5010  TaskData *taskData,
5011  void *v,
5012  Handle       dsHandle /* Handle to (X_Display_Object *) */
5013)
5014{
5015  XFontStruct *fs = (XFontStruct *)v;
5016  Handle dataHandle = alloc_and_save(taskData, SIZEOF(MLXFontStruct), F_MUTABLE_BIT);
5017
5018  int n = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1;
5019
5020  if (fs->per_char == 0) n = 0;
5021
5022#define data ((MLXFontStruct *)DEREFHANDLE(dataHandle))
5023  data->font_object   = (X_Font_Object *)DEREFHANDLE(EmptyFont(taskData, dsHandle,fs->fid,fs));
5024  data->ascent        = DEREFWORD(Make_int(fs->ascent));
5025  data->descent       = DEREFWORD(Make_int(fs->descent));
5026  data->maxChar       = DEREFWORD(Make_arbitrary_precision(taskData, fs->max_char_or_byte2));
5027  data->minChar       = DEREFWORD(Make_arbitrary_precision(taskData, fs->min_char_or_byte2));
5028  data->perChar       = DEREFHANDLE(CreateList4(taskData,n,fs->per_char,sizeof(XCharStruct),CreateCharStruct));
5029  data->maxByte1      = DEREFWORD(Make_arbitrary_precision(taskData, fs->max_byte1));
5030  data->minByte1      = DEREFWORD(Make_arbitrary_precision(taskData, fs->min_byte1));
5031  data->direction     = DEREFWORD(Make_arbitrary_precision(taskData, (fs->direction == FontLeftToRight) ? 1 : 2));
5032  data->maxBounds     = (MLXCharStruct *)DEREFHANDLE(CreateCharStruct(taskData, &fs->max_bounds));
5033  data->minBounds     = (MLXCharStruct *)DEREFHANDLE(CreateCharStruct(taskData, &fs->min_bounds));
5034  data->defaultChar   = DEREFWORD(Make_arbitrary_precision(taskData, fs->default_char));
5035  data->allCharsExist = DEREFWORD(Make_bool(fs->all_chars_exist));
5036#undef data
5037
5038  return FINISHED(taskData, dataHandle);
5039}
5040
5041static XFontStruct *GetFS(TaskData *taskData, X_Font_Object *P)
5042{
5043
5044  assert(UNTAGGED(P->type) == X_Font);
5045
5046  if (*(P->fs) == NULL) RaiseXWindows(taskData, "Not a real XFontStruct");
5047
5048  CheckExists((X_Object *)P,font);
5049
5050  return *(P->fs);
5051}
5052
5053static XFontStruct *GetFontStruct(TaskData *taskData,PolyWord p)
5054{
5055    MLXFontStruct *P = (MLXFontStruct *)p.AsObjPtr();
5056    return GetFS(taskData,P->font_object);
5057}
5058
5059static Handle CreateString(TaskData *taskData, void *s)
5060{
5061    return Make_string(*(char **)s);
5062}
5063
5064static Handle GetFontPath(TaskData *taskData, Display *d)
5065{
5066  Handle list;
5067  char **names;
5068  int count;
5069
5070  names = XGetFontPath(d,&count);
5071
5072  if (names == 0) RaiseXWindows(taskData, "XGetFontPath failed");
5073
5074  list = CreateList4(taskData,count,names,sizeof(char *),CreateString);
5075
5076  XFreeFontNames(names);
5077
5078  return list;
5079}
5080
5081static void FreeStrings(char **s, int n)
5082{
5083  while(n--) free(*s++);
5084  return;
5085}
5086
5087static void SetFontPath(TaskData *taskData, Display *d, Handle list)
5088{
5089  if (NONNIL(DEREFWORD(list)))
5090  {
5091    unsigned   N = ListLength(DEREFWORD(list));
5092    char **D = (char **) alloca(N * sizeof(char *));
5093
5094    GetList4(taskData, DEREFWORD(list),D,sizeof(char *),CopyString);
5095
5096    XSetFontPath(d,D,N);
5097
5098    FreeStrings(D,N);
5099  }
5100  return;
5101}
5102
5103static Handle ListFonts(TaskData *taskData,Display *d, PolyStringObject *string, unsigned maxnames)
5104{
5105  char name[500];
5106  Handle list;
5107  char **names;
5108  int count;
5109
5110  Poly_string_to_C(string,name,sizeof(name));
5111
5112  names = XListFonts(d,name,maxnames,&count);
5113
5114  if (names == 0) RaiseXWindows(taskData, "XListFonts failed");
5115
5116  list = CreateList4(taskData,count,names,sizeof(char *),CreateString);
5117
5118  XFreeFontNames(names);
5119
5120  return list;
5121}
5122
5123static Handle ListFontsWithInfo
5124(
5125  TaskData *taskData,
5126  Handle   dsHandle, /* Handle to (X_Display_Object *) */
5127  PolyStringObject  *string,
5128  unsigned maxnames
5129)
5130{
5131  char name[500];
5132  char **names;
5133  int count;
5134  XFontStruct *info;
5135  Handle pair;
5136
5137  Poly_string_to_C(string,name,sizeof(name));
5138
5139  names = XListFontsWithInfo(DEREFDISPLAYHANDLE(dsHandle)->display,name,maxnames,&count,&info);
5140
5141  if (names == 0) RaiseXWindows(taskData, "XListFontsWithInfo failed");
5142
5143  pair = CreatePair(taskData, CreateList4(taskData,count,names,sizeof(char *),CreateString),
5144                    CreateList5(taskData,count,info,sizeof(XFontStruct),CreateFontStruct,dsHandle));
5145
5146  XFree((char *)info);
5147  XFreeFontNames(names);
5148
5149  return pair;
5150}
5151
5152static Handle LoadFont
5153(
5154  TaskData *taskData,
5155  Handle  dsHandle, /* Handle to (X_Display_Object *) */
5156  PolyStringObject *string
5157)
5158{
5159  char name[500]; Font font;
5160
5161  Poly_string_to_C(string,name,sizeof(name));
5162
5163  font = XLoadFont(DEREFDISPLAYHANDLE(dsHandle)->display,name);
5164
5165  if (font == 0) RaiseXWindows(taskData, "XLoadFont failed");
5166
5167  return EmptyFont(taskData, dsHandle,font,(XFontStruct *)NULL);
5168}
5169
5170static Handle LoadQueryFont
5171(
5172  TaskData *taskData,
5173  Handle  dsHandle, /* Handle to (X_Display_Object *) */
5174  PolyStringObject *string
5175)
5176{
5177  char name[500]; XFontStruct *fs;
5178
5179  Poly_string_to_C(string,name,sizeof(name));
5180
5181  fs = XLoadQueryFont(DEREFDISPLAYHANDLE(dsHandle)->display,name);
5182
5183  if (fs == 0) RaiseXWindows(taskData, "XLoadQueryFont failed");
5184
5185  return CreateFontStruct(taskData,fs,dsHandle);
5186}
5187
5188static Handle QueryFont
5189(
5190  TaskData *taskData,
5191  Handle dsHandle, /* Handle to (X_Display_Object *) */
5192  Font   font
5193)
5194{
5195  XFontStruct *fs;
5196
5197  fs = XQueryFont(DEREFDISPLAYHANDLE(dsHandle)->display,font);
5198
5199  if (fs == 0) RaiseXWindows(taskData, "XQueryFont failed");
5200
5201  return CreateFontStruct(taskData,fs,dsHandle);
5202}
5203
5204static Handle TextExtents(TaskData *taskData, XFontStruct *fs, PolyStringObject *s)
5205{
5206  Handle dataHandle = alloc_and_save(taskData, 4, F_MUTABLE_BIT);
5207
5208  int direction,ascent,descent; XCharStruct overall;
5209
5210  XTextExtents(fs,s->chars,s->length,&direction,&ascent,&descent,&overall);
5211
5212#define data DEREFHANDLE(dataHandle)
5213  data->Set(0, DEREFWORD(Make_arbitrary_precision(taskData, (direction == FontLeftToRight) ? 1 : 2)));
5214  data->Set(1, DEREFWORD(Make_int(ascent)));
5215  data->Set(2, DEREFWORD(Make_int(descent)));
5216  data->Set(3, DEREFWORD(CreateCharStruct(taskData, &overall)));
5217#undef data
5218
5219  return FINISHED(taskData, dataHandle);
5220}
5221
5222static Handle TextExtents16(TaskData *taskData, XFontStruct *fs, Handle list)
5223{
5224  Handle dataHandle = alloc_and_save(taskData, 4, F_MUTABLE_BIT);
5225
5226  int direction,ascent,descent; XCharStruct overall;
5227
5228  unsigned     N = ListLength(DEREFWORD(list));
5229  XChar2b *L = (XChar2b *) alloca(N * sizeof(XChar2b));
5230
5231  GetList4(taskData,DEREFWORD(list),L,sizeof(XChar2b),GetChar2);
5232
5233  XTextExtents16(fs,L,N,&direction,&ascent,&descent,&overall);
5234
5235#define data DEREFHANDLE(dataHandle)
5236  data->Set(0, DEREFWORD(Make_arbitrary_precision(taskData, (direction == FontLeftToRight) ? 1 : 2)));
5237  data->Set(1, DEREFWORD(Make_int(ascent)));
5238  data->Set(2, DEREFWORD(Make_int(descent)));
5239  data->Set(3, DEREFWORD(CreateCharStruct(taskData, &overall)));
5240#undef data
5241
5242  return FINISHED(taskData, dataHandle);
5243}
5244
5245static Handle TextWidth(TaskData *taskData, XFontStruct *fs, PolyStringObject *s)
5246{
5247  if (fs->per_char == 0) return Make_int(s->length * fs->max_bounds.width);
5248
5249  return Make_int(XTextWidth(fs,s->chars,s->length));
5250}
5251
5252static Handle TextWidth16(TaskData *taskData, XFontStruct *fs, Handle list)
5253{
5254  unsigned     N = ListLength(DEREFWORD(list));
5255  XChar2b *L = (XChar2b *) alloca(N * sizeof(XChar2b));
5256
5257  GetList4(taskData, DEREFWORD(list),L,sizeof(XChar2b),GetChar2);
5258
5259  return Make_int(XTextWidth16(fs,L,N));
5260}
5261
5262static Handle GetTextProperty(TaskData *taskData, Display *d, Window w, unsigned property)
5263{
5264  XTextProperty T;
5265  Handle tuple;
5266
5267  int s = XGetTextProperty(d,w,&T,property);
5268
5269  if (s == 0) RaiseXWindows(taskData, "XGetTextProperty failed");
5270
5271  tuple = alloc_and_save(taskData, 4, F_MUTABLE_BIT);
5272
5273#define data DEREFHANDLE(tuple)
5274  data->Set(0, C_string_to_Poly(taskData, (char *)T.value,T.nitems * T.format / 8));
5275  data->Set(1, DEREFWORD(Make_arbitrary_precision(taskData, T.encoding)));
5276  data->Set(2, DEREFWORD(Make_int(T.format)));
5277  data->Set(3, DEREFWORD(Make_arbitrary_precision(taskData, T.nitems)));
5278#undef data
5279
5280  return FINISHED(taskData, tuple);
5281}
5282
5283static void GetXWMHints(TaskData *taskData, PolyWord p, void *v, unsigned)
5284{
5285    PolyObject *P = p.AsObjPtr();
5286    XWMHints *H = (XWMHints *)v;
5287    H->input         = get_C_ulong(taskData, P->Get(0));
5288    H->initial_state = get_C_ulong(taskData, P->Get(1));
5289    H->icon_pixmap   = GetPixmap(taskData, (X_Object *)P->Get(2).AsObjPtr());
5290    H->icon_window   = GetWindow(taskData, (X_Object *)P->Get(3).AsObjPtr());
5291    H->icon_x        = GetPointX(taskData, P->Get(4));
5292    H->icon_y        = GetPointY(taskData, P->Get(4));
5293    H->icon_mask     = GetPixmap(taskData, (X_Object *)P->Get(5).AsObjPtr());
5294    H->flags         = get_C_ulong(taskData, P->Get(6));
5295    H->window_group  = 0;
5296}
5297
5298
5299
5300typedef struct
5301{
5302    PolyWord    x0;
5303    PolyWord    x1;
5304    PolyWord    x2;
5305    PolyWord    x3;
5306    PolyWord    x4;
5307    PolyWord    x5;  /* pair of points */
5308    PolyWord    x6;
5309    PolyWord    x7;
5310    PolyWord    x8;
5311} MLXWMSizeHintsTuple;
5312
5313static void GetXWMSizeHints(TaskData *taskData, PolyWord p, void *v, unsigned)
5314{
5315    MLXWMSizeHintsTuple *P = (MLXWMSizeHintsTuple *)p.AsObjPtr();
5316    XSizeHints *H = (XSizeHints *)v;
5317    CheckZeroRect(taskData, P->x1);
5318    CheckZeroRect(taskData, P->x2);
5319    CheckZeroRect(taskData, P->x3);
5320    CheckZeroRect(taskData, P->x4);
5321    CheckZeroRect(taskData, P->x6);
5322
5323    H->x            = GetPointX(taskData, P->x0);
5324    H->y            = GetPointY(taskData, P->x0);
5325    H->width        = GetRectW(taskData, P->x1);
5326    H->height       = GetRectH(taskData, P->x1);
5327    H->min_width    = GetRectW(taskData, P->x2);
5328    H->min_height   = GetRectH(taskData, P->x2);
5329    H->max_width    = GetRectW(taskData, P->x3);
5330    H->max_height   = GetRectH(taskData, P->x3);
5331    H->width_inc    = GetRectW(taskData, P->x4);
5332    H->height_inc   = GetRectH(taskData, P->x4);
5333    H->min_aspect.x = GetPointX(taskData, FST(P->x5));
5334    H->min_aspect.y = GetPointY(taskData, FST(P->x5));
5335    H->max_aspect.x = GetPointX(taskData, SND(P->x5));
5336    H->max_aspect.y = GetPointY(taskData, SND(P->x5));
5337    H->base_width   = GetRectW(taskData, P->x6);
5338    H->base_height  = GetRectH(taskData, P->x6);
5339    H->win_gravity  = get_C_ulong(taskData, P -> x7);
5340    H->flags        = get_C_ulong(taskData, P -> x8);
5341}
5342
5343static void GetIconSize(TaskData *taskData, PolyWord p, void *v, unsigned)
5344{
5345    MLTriple *P = (MLTriple *)p.AsObjPtr();
5346    XIconSize *s = (XIconSize *)v;
5347    CheckZeroRect(taskData, FST(P));
5348    CheckZeroRect(taskData, SND(P));
5349    CheckZeroRect(taskData, THIRD(P));
5350
5351    s->min_width = GetRectW(taskData, FST(P));
5352    s->min_height = GetRectH(taskData, FST(P));
5353    s->max_width = GetRectW(taskData, SND(P));
5354    s->max_height = GetRectH(taskData, SND(P));
5355    s->width_inc = GetRectW(taskData, THIRD(P));
5356    s->height_inc = GetRectH(taskData, THIRD(P));
5357}
5358
5359static void GetSigned(TaskData *taskData, PolyWord p, void *i, unsigned)
5360{
5361    *(int*)i = get_C_long(taskData, p);
5362}
5363
5364static void GetPixmaps(TaskData *taskData, PolyWord pp, void *m, unsigned)
5365{
5366    X_Object *p = (X_Object *)pp.AsObjPtr();
5367    *(Pixmap *)m = GetPixmap(taskData, p);
5368}
5369
5370static void GetColormaps(TaskData *taskData, PolyWord pp, void *v, unsigned)
5371{
5372    X_Object *p = (X_Object *)pp.AsObjPtr();
5373    *(Colormap *)v = GetColormap(taskData, p);
5374}
5375
5376static void GetCursors(TaskData *taskData, PolyWord pp, void *c, unsigned)
5377{
5378    X_Object *p = (X_Object *)pp.AsObjPtr();
5379    *(Cursor *)c = GetCursor(taskData, p);
5380}
5381
5382static void GetDrawables(TaskData *taskData, PolyWord pp, void *d, unsigned)
5383{
5384    X_Object *p = (X_Object *)pp.AsObjPtr();
5385    *(Drawable *)d = GetDrawable(taskData, p);
5386}
5387
5388static void GetFonts(TaskData *taskData, PolyWord pp, void *f, unsigned)
5389{
5390    X_Object *p = (X_Object *)pp.AsObjPtr();
5391    *(Font *)f = GetFont(taskData, p);
5392}
5393
5394static void GetVisualIds(TaskData *taskData, PolyWord pp, void *u, unsigned)
5395{
5396    X_Object *p = (X_Object *)pp.AsObjPtr();
5397    *(unsigned *)u = GetVisual(taskData, p)->visualid;
5398}
5399
5400static void SetProperty
5401(
5402  TaskData *taskData,
5403  Display *d,
5404  Window   w,
5405  unsigned property,
5406  unsigned target,
5407  Handle   list,
5408  unsigned encoding
5409)
5410{
5411    unsigned format;
5412    unsigned bytes;
5413    uchar *value;
5414
5415    /* SPF 7/7/94 - XA_STRING pulled out as special case; this enables */
5416    /* gcc to understand the previously data-dependant control flow.   */
5417    if (encoding == XA_STRING)
5418    {
5419        PolyStringObject *s = GetString (DEREFHANDLE(list));
5420
5421        format = 8;
5422        bytes  = s->length;
5423        value  = (uchar *) s->chars;
5424    }
5425
5426    else
5427    {
5428        unsigned length = ListLength(DEREFWORD(list));
5429        unsigned size;
5430        GetFunc get;
5431
5432        switch(encoding)
5433        {
5434        case XA_ATOM:          size = sizeof(unsigned);          get = GetUnsigned;         format = 32; break;
5435        case XA_BITMAP:        size = sizeof(Pixmap);            get = GetPixmaps;          format = 32; break;
5436        case XA_COLORMAP:      size = sizeof(Colormap);          get = GetColormaps;        format = 32; break;
5437        case XA_CURSOR:        size = sizeof(Cursor);            get = GetCursors;          format = 32; break;
5438        case XA_DRAWABLE:      size = sizeof(Drawable);          get = GetDrawables;        format = 32; break;
5439        case XA_FONT:          size = sizeof(Font);              get = GetFonts;            format = 32; break;
5440        case XA_PIXMAP:        size = sizeof(Pixmap);            get = GetPixmaps;          format = 32; break;
5441        case XA_VISUALID:      size = sizeof(unsigned);          get = GetVisualIds;        format = 32; break;
5442        case XA_CARDINAL:      size = sizeof(unsigned);          get = GetUnsigned;         format = 32; break;
5443        case XA_INTEGER:       size = sizeof(int);               get = GetSigned;           format = 32; break;
5444        case XA_WINDOW:        size = sizeof(Window);            get = GetWindows;          format = 32; break;
5445        case XA_ARC:           size = sizeof(XArc);              get = GetArcs;             format = 16; break;
5446        case XA_POINT:         size = sizeof(XPoint);            get = GetPoints;           format = 16; break;
5447        case XA_RECTANGLE:     size = sizeof(XRectangle);        get = GetRects;            format = 16; break;
5448        case XA_RGB_COLOR_MAP: size = sizeof(XStandardColormap); get = GetStandardColormap; format = 32; break;
5449        case XA_WM_HINTS:      size = sizeof(XWMHints);          get = GetXWMHints;         format = 32; break;
5450        case XA_WM_SIZE_HINTS: size = sizeof(XSizeHints);        get = GetXWMSizeHints;     format = 32; break;
5451        case XA_WM_ICON_SIZE:  size = sizeof(XIconSize);         get = GetIconSize;         format = 32; break;
5452        default: Crash ("Bad property type %x",encoding); /*NOTREACHED*/
5453        }
5454
5455        bytes  = length * size;
5456        value  = (uchar *) alloca(bytes);
5457        GetList4(taskData, DEREFWORD(list),value,(int)size,get);
5458    }
5459
5460    {
5461        XTextProperty T;
5462
5463        T.value    = value;
5464        T.encoding = target;
5465        T.format   = format;
5466        T.nitems   = (bytes * 8) / format;
5467
5468        XSetTextProperty(d,w,&T,property);
5469    }
5470}
5471
5472static Handle GetWMHints
5473(
5474  TaskData *taskData,
5475  Handle dsHandle, /* Handle to (X_Display_Object *) */
5476  Window w
5477)
5478{
5479  Handle tuple = alloc_and_save(taskData, 7, F_MUTABLE_BIT);
5480
5481  XWMHints *H = XGetWMHints(DEREFDISPLAYHANDLE(dsHandle)->display,w);
5482
5483  if (H)
5484  {
5485
5486#define data DEREFHANDLE(tuple)
5487    data->Set(0, DEREFWORD(Make_arbitrary_precision(taskData, H->input)));
5488    data->Set(1, DEREFWORD(Make_arbitrary_precision(taskData, H->initial_state)));
5489    data->Set(2, DEREFWORD(EmptyPixmap(taskData, dsHandle,H->icon_pixmap)));
5490    data->Set(3, DEREFWORD(EmptyWindow(taskData, dsHandle,H->icon_window)));
5491    data->Set(4, DEREFWORD(CreatePoint(taskData, H->icon_x,H->icon_y)));
5492    data->Set(5, DEREFWORD(EmptyPixmap(taskData, dsHandle,H->icon_mask)));
5493    data->Set(6, DEREFWORD(Make_arbitrary_precision(taskData, H->flags)));
5494#undef data
5495
5496    XFree((char *)H);
5497  }
5498
5499  /* else what (?) */
5500
5501  return FINISHED(taskData, tuple);
5502}
5503
5504static Handle GetWMSizeHints
5505(
5506  TaskData *taskData,
5507  Display *d,
5508  Window   w,
5509  unsigned property
5510)
5511{
5512  XSizeHints H;
5513  long supplied; /* was unsigned SPF 6/1/94 */
5514
5515  Handle tuple = alloc_and_save(taskData, 9, F_MUTABLE_BIT);
5516
5517  int s = XGetWMSizeHints(d,w,&H,&supplied,property);
5518
5519  if (s)
5520  {
5521    Handle p1 = CreatePoint(taskData, H.min_aspect.x,H.min_aspect.y);
5522    Handle p2 = CreatePoint(taskData, H.max_aspect.x,H.max_aspect.y);
5523
5524#define data DEREFHANDLE(tuple)
5525    data->Set(0, DEREFWORD(CreatePoint(taskData, H.x,H.y)));
5526    data->Set(1, DEREFWORD(CreateArea(H.width,H.height)));
5527    data->Set(2, DEREFWORD(CreateArea(H.min_width,H.min_height)));
5528    data->Set(3, DEREFWORD(CreateArea(H.max_width,H.max_height)));
5529    data->Set(4, DEREFWORD(CreateArea(H.width_inc,H.height_inc)));
5530    data->Set(5, DEREFWORD(CreatePair(taskData, p1,p2)));
5531    data->Set(6, DEREFWORD(CreateArea(H.base_width,H.base_height)));
5532    data->Set(7, DEREFWORD(Make_arbitrary_precision(taskData, H.win_gravity)));
5533    data->Set(8, DEREFWORD(Make_arbitrary_precision(taskData, H.flags)));
5534#undef data
5535  }
5536
5537  /* else (?) */
5538
5539  return FINISHED(taskData, tuple);
5540}
5541
5542#if 0
5543typedef struct
5544{
5545MLPair       *x0; /* pair of points */
5546MLXRectangle *x1;
5547PolyWord     x2; /* ML int */
5548} MLWMGeometryTriple;
5549#endif
5550
5551static Handle WMGeometry
5552(
5553  TaskData *taskData,
5554  Handle        dsHandle, /* Handle to (X_Display_Object *) */
5555  PolyStringObject        *user,
5556  PolyStringObject        *def,
5557  unsigned      borderWidth,
5558  PolyWord      P
5559)
5560{
5561  XSizeHints H; int x,y,width,height,gravity,mask;
5562
5563  char userGeometry[500],defaultGeometry[500];
5564
5565  GetXWMSizeHints(taskData, P, &H, 0);
5566
5567  Poly_string_to_C(user,userGeometry   ,sizeof(userGeometry));
5568  Poly_string_to_C(def ,defaultGeometry,sizeof(defaultGeometry));
5569
5570  mask = XWMGeometry(DEREFDISPLAYHANDLE(dsHandle)->display,
5571                       DEREFDISPLAYHANDLE(dsHandle)->screen,
5572                       userGeometry,
5573                       defaultGeometry,
5574                       borderWidth,
5575                       &H,&x,&y,&width,&height,&gravity);
5576
5577  return CreateTriple(taskData, CreatePoint(taskData, x,y),CreateArea(width,height),Make_arbitrary_precision(taskData, gravity));
5578}
5579
5580static Handle CreateIconSize(TaskData *taskData, void *v)
5581{
5582    XIconSize *s = (XIconSize *)v;
5583    return CreateTriple(taskData, CreateArea(s->min_width,s->min_height),
5584                        CreateArea(s->max_width,s->max_height),
5585                        CreateArea(s->width_inc,s->height_inc));
5586}
5587
5588static Handle GetIconSizes(TaskData *taskData, Display *d, Window w)
5589{
5590    XIconSize *sizes;
5591    int count;
5592
5593    int s = XGetIconSizes(d,w,&sizes,&count);
5594
5595    if (s)
5596    {
5597        Handle list = CreateList4(taskData,count,sizes,sizeof(XIconSize),CreateIconSize);
5598
5599        XFree((char *)sizes);
5600
5601        return list;
5602    }
5603
5604    return SAVE(ListNull);
5605}
5606
5607static Handle GetTransientForHint
5608(
5609  TaskData *taskData,
5610  Handle dsHandle, /* Handle to (X_Display_Object *) */
5611  Window w
5612)
5613{
5614  Window p;
5615
5616  int s = XGetTransientForHint(DEREFDISPLAYHANDLE(dsHandle)->display,w,&p);
5617
5618  if (s == 0) RaiseXWindows(taskData, "XGetTransientForHint failed");
5619
5620  return EmptyWindow(taskData, dsHandle,p);
5621}
5622
5623static Handle GetWMColormapWindows
5624(
5625  TaskData *taskData,
5626  Handle dsHandle, /* Handle to (X_Display_Object *) */
5627  Window parent
5628)
5629{
5630  Window *windows;
5631  int count;
5632
5633  int s = XGetWMColormapWindows(DEREFDISPLAYHANDLE(dsHandle)->display,parent,&windows,&count);
5634
5635  if (s)
5636  {
5637    Handle list = CreateList5(taskData,count,windows,sizeof(Window),CreateDrawable,dsHandle);
5638
5639    XFree((char *)windows);
5640
5641    return list;
5642  }
5643
5644  return SAVE(ListNull);
5645}
5646
5647
5648static Handle GetRGBColormaps
5649(
5650  TaskData *taskData,
5651  Handle   dsHandle, /* Handle to (X_Display_Object *) */
5652  Window   w,
5653  unsigned property
5654)
5655{
5656  XStandardColormap *maps;
5657  int count;
5658
5659  int s = XGetRGBColormaps(DEREFDISPLAYHANDLE(dsHandle)->display,w,&maps,&count,property);
5660
5661  if (s)
5662  {
5663    Handle list = CreateList5(taskData,count,maps,sizeof(XStandardColormap),CreateStandardColormap,dsHandle);
5664
5665    XFree((char *)maps);
5666
5667    return list;
5668  }
5669
5670  return SAVE(ListNull);
5671}
5672
5673static Handle GetID(TaskData *taskData, X_Object *P)
5674{
5675    switch(UNTAGGED(P->type))
5676    {
5677    case X_GC:       return Make_arbitrary_precision(taskData, GetGC(taskData, P)->gid);           /* GCID       */
5678    case X_Font:     return Make_arbitrary_precision(taskData, GetFont(taskData, P));              /* FontID     */
5679    case X_Cursor:   return Make_arbitrary_precision(taskData, GetCursor(taskData, P));            /* CursorId   */
5680    case X_Window:   return Make_arbitrary_precision(taskData, GetWindow(taskData, P));            /* DrawableID */
5681    case X_Pixmap:   return Make_arbitrary_precision(taskData, GetPixmap(taskData, P));            /* DrawableID */
5682    case X_Colormap: return Make_arbitrary_precision(taskData, GetColormap(taskData, P));          /* ColormapID */
5683    case X_Visual:   return Make_arbitrary_precision(taskData, GetVisual(taskData, P)->visualid);  /* VisualID   */
5684    case X_Widget:   return Make_arbitrary_precision(taskData, (unsigned long)GetNWidget(taskData, P)); /* Widget -- SAFE(?) */
5685    default:         Crash ("Bad X_Object type (%d) in GetID",UNTAGGED(P->type)) /*NOTREACHED*/;
5686    }
5687}
5688
5689static Handle OpenDisplay(TaskData *taskData, PolyStringObject *string)
5690{
5691    char               name[500];
5692    Display           *display;
5693    Handle dsHandle /* Handle to (X_Display_Object *) */;
5694
5695    Poly_string_to_C(string,name,sizeof(name));
5696
5697    display = XOpenDisplay(name);
5698
5699    if (display == 0) RaiseXWindows(taskData, "XOpenDisplay failed");
5700
5701    /* I don't think this is needed.  DCJM 26/5/2000. */
5702    /* add_file_descr(display->fd); */
5703
5704    dsHandle = alloc_and_save(taskData, SIZEOF(X_Display_Object), F_MUTABLE_BIT|F_BYTE_OBJ);
5705
5706    debug1 ("%s display opened\n",DisplayString(display));
5707
5708    debug1 ("%x display fd\n",display->fd);
5709
5710#define ds DEREFDISPLAYHANDLE(dsHandle)
5711    /* Ok to store C values because this is a byte object */
5712    ds->type        = TAGGED(X_Display);
5713    ds->display     = display;
5714    ds->screen      = DefaultScreen(display);
5715    ds->app_context = 0;
5716#undef ds
5717
5718    return AddXObject(FINISHED(taskData, dsHandle));
5719}
5720
5721/* indirection removed SPF 11/11/93 */
5722static XmFontList GetXmFontList(PolyWord p /* NOT a handle */)
5723{
5724    if (NONNIL(p))
5725    {
5726        char       charset[500];
5727        XmFontList L;
5728        MLPair    *q = (MLPair *)(((ML_Cons_Cell*)p.AsObjPtr())->h.AsObjPtr());
5729
5730        Poly_string_to_C(SND(q),charset,sizeof(charset));
5731        L = XmFontListCreate((XFontStruct *)FST(q).AsObjPtr(),charset); /* cast added SPF 6/1/94 */
5732
5733        p = ((ML_Cons_Cell*)p.AsObjPtr())->t;
5734
5735        while(NONNIL(p))
5736        {
5737            q = (MLPair *)(((ML_Cons_Cell*)p.AsObjPtr())->h.AsObjPtr());
5738
5739            Poly_string_to_C(SND(q),charset,sizeof(charset));
5740            L = XmFontListAdd(L,(XFontStruct *)FST(q).AsObjPtr(),charset); /* cast added SPF 6/1/94 */
5741
5742            p = ((ML_Cons_Cell*)p.AsObjPtr())->t;
5743        }
5744
5745        return L;
5746    }
5747
5748    return 0;
5749}
5750
5751/*
5752      datatype CType = CAccelerators  of XtAccelerators
5753                     | CBool          of bool
5754                     | CColormap      of Colormap
5755                     | CCursor        of Cursor
5756                     | CDimension     of int
5757                     | CFontList      of (XFontStruct * string) list
5758                     | CInt           of int
5759                     | CIntTable      of int list
5760                     | CKeySym        of int
5761                     | CPixmap        of Drawable
5762                     | CPosition      of int
5763                     | CString        of string
5764                     | CStringTable   of string list
5765                     | CTrans         of XtTranslations
5766                     | CUnsignedChar  of int
5767                     | CUnsignedTable of int list
5768                     | CVisual        of Visual
5769                     | CWidget        of Widget
5770                     | CWidgetList    of Widget list
5771                     | CXmString      of XmString
5772                     | CXmStringTable of XmString list;
5773*/
5774
5775#define CAccelerators  1
5776#define CBool          2
5777#define CColormap      3
5778#define CCursor        4
5779#define CDimension     5
5780#define CFontList      6
5781#define CInt           7
5782#define CIntTable      8
5783#define CKeySym        9
5784#define CPixmap        10
5785#define CPosition      11
5786#define CString        12
5787#define CStringTable   13
5788#define CTrans         14
5789#define CUnsignedChar  15
5790#define CUnsignedTable 16
5791#define CVisual        17
5792#define CWidget        18
5793#define CWidgetList    19
5794#define CXmString      20
5795#define CXmStringTable 21
5796
5797typedef struct
5798{
5799    unsigned  tag;
5800    unsigned  N;
5801    char *name;
5802    union
5803    {
5804        XtAccelerators acc;
5805        Boolean        boolean;
5806        Colormap       cmap;
5807        Cursor         cursor;
5808        Dimension      dim;
5809        XmFontList     F;
5810        int            i;
5811        int           *I;
5812        KeySym         keysym;
5813        Pixmap         pixmap;
5814        Position       posn;
5815        char          *string;
5816        char         **S;
5817        XtTranslations trans;
5818        uchar          u;
5819        uchar         *U;
5820        Visual        *visual;
5821        Widget         widget;
5822        WidgetList     W;
5823        XmString       xmString;
5824        XmString      *X;
5825    } u;
5826} ArgType;
5827
5828
5829static void GetXmString(TaskData *taskData, PolyWord w, void *v, unsigned )
5830{
5831    XmString *p = (XmString *)v;
5832    char *s;
5833    CopyString(taskData, w, &s, 0);
5834    *p = XmStringCreateLtoR(s, (char *)XmSTRING_DEFAULT_CHARSET);
5835    free(s);
5836}
5837
5838static void GetXmStrings(TaskData *taskData, PolyWord list, ArgType *T)
5839{
5840    T->N   = 0;
5841    T->u.X = 0;
5842
5843    if (NONNIL(list))
5844    {
5845        T->N   = ListLength(list);
5846        T->u.X = (XmString *) malloc(T->N * sizeof(XmString));
5847
5848        GetList4(taskData, list,T->u.X,sizeof(XmString),GetXmString);
5849    }
5850}
5851
5852static void GetStrings(TaskData *taskData, PolyWord list, ArgType *T)
5853{
5854    T->N   = 0;
5855    T->u.S = 0;
5856
5857    if (NONNIL(list))
5858    {
5859        T->N   = ListLength(list);
5860        T->u.S = (char **) malloc(T->N * sizeof(char *));
5861
5862        GetList4(taskData, list,T->u.S,sizeof(char *),CopyString);
5863    }
5864}
5865
5866static void FreeXmStrings(ArgType *T)
5867{
5868    for(unsigned i = 0; i < T->N; i++) XmStringFree (T->u.X[i]);
5869
5870    free(T->u.X);
5871}
5872
5873static void GetITable(TaskData *taskData, PolyWord list, ArgType *T)
5874{
5875    T->N   = 0;
5876    T->u.I = 0;
5877
5878    if (NONNIL(list))
5879    {
5880        T->N   = ListLength(list);
5881        T->u.I = (int *) malloc(T->N * sizeof(int));
5882
5883        GetList4(taskData, list,T->u.I,sizeof(int),GetUnsigned);
5884    }
5885}
5886
5887static void GetUTable(TaskData *taskData, PolyWord list, ArgType *T)
5888{
5889    T->N   = 0;
5890    T->u.U = 0;
5891
5892    if (NONNIL(list))
5893    {
5894        T->N   = ListLength(list);
5895        T->u.U = (uchar *)malloc(T->N * sizeof(uchar));
5896
5897        GetList4(taskData, list,T->u.U,sizeof(uchar),GetUChars);
5898    }
5899}
5900
5901/*
5902    case CIntTable:      GetITable   ((ML_Cons_Cell *)v,T); break;
5903    case CUnsignedTable: GetUTable   ((ML_Cons_Cell *)v,T); break;
5904    case CString:        CopyString  (v,&T->u.string); break;
5905    case CStringTable:   GetStrings  ((ML_Cons_Cell *)v,T); break;
5906    case CXmString:      GetXmString (v,&T->u.xmString); break;
5907    case CXmStringTable: GetXmStrings((ML_Cons_Cell *)v,T); break;
5908*/
5909
5910static void FreeArgs(ArgType *T, unsigned N)
5911{
5912  while(N--)
5913  {
5914    free(T->name);
5915
5916    switch(T->tag)
5917    {
5918      case CAccelerators:  break;
5919      case CBool:          break;
5920      case CColormap:      break;
5921      case CCursor:        break;
5922      case CDimension:     break;
5923      case CFontList:      XmFontListFree(T->u.F); break;
5924      case CInt:           break;
5925      case CIntTable:      break;
5926      case CKeySym:        break;
5927      case CPixmap:        break;
5928      case CPosition:      break;
5929      case CString:        XtFree(T->u.string); break;
5930      case CStringTable:   FreeStrings(T->u.S,T->N); free(T->u.S); break;
5931      case CTrans:         break;
5932      case CUnsignedChar:  break;
5933      case CUnsignedTable: break;
5934      case CVisual:        break;
5935      case CWidget:        break;
5936      case CWidgetList:    break;
5937      case CXmString:      XmStringFree (T->u.xmString); break;
5938      case CXmStringTable: FreeXmStrings(T); break;
5939
5940      default: Crash ("Bad arg type %x",T->tag);
5941    }
5942
5943    T++;
5944  }
5945}
5946
5947/*
5948type Arg sharing type Arg = exn;
5949val Exn: Arg -> Exn = Cast;
5950val Arg: Exn -> Arg = Cast;
5951datatype Exn = EXN of unit ref * string * unit;
5952*/
5953
5954/* (string,(v,tag)) */
5955static void SetArgTypeP(TaskData *taskData, PolyWord fst, PolyWord snd, ArgType *T)
5956{
5957  PolyWord v = FST(snd);
5958
5959  T->tag = UNTAGGED(SND(snd));
5960  T->N   = 0;
5961  T->u.i = 0;
5962
5963  CopyString(taskData, fst, &T->name, 0);
5964
5965  switch(T->tag)
5966  {
5967    case CAccelerators:  T->u.acc    = GetAcc       (taskData, (X_Object *)v.AsObjPtr()); break;
5968    case CBool:          T->u.boolean   = get_C_ulong  (taskData, v); break;
5969    case CColormap:      T->u.cmap   = GetColormap  (taskData, (X_Object *)v.AsObjPtr()); break;
5970    case CCursor:        T->u.cursor = GetCursor    (taskData, (X_Object *)v.AsObjPtr()); break;
5971    case CDimension:     T->u.dim    = get_C_ushort (taskData, v); break;
5972    case CFontList:      T->u.F      = GetXmFontList(v); break;
5973    case CInt:           T->u.i      = get_C_long   (taskData, v); break;
5974    case CKeySym:        T->u.keysym = get_C_ulong  (taskData, v); break;
5975    case CPixmap:        T->u.pixmap = GetPixmap    (taskData, (X_Object *)v.AsObjPtr()); break;
5976    case CPosition:      T->u.posn   = get_C_short  (taskData, v); break;
5977    case CTrans:         T->u.trans  = GetTrans     (taskData, (X_Object *)v.AsObjPtr()); break;
5978    case CUnsignedChar:  T->u.u      = get_C_uchar  (taskData, v); break;
5979    case CVisual:        T->u.visual = GetVisual    (taskData, (X_Object *)v.AsObjPtr()); break;
5980    case CWidget:        T->u.widget = GetNWidget   (taskData, (X_Object *)v.AsObjPtr()); break;
5981
5982    /* The following types allocate memory, but only in the C heap */
5983
5984    case CIntTable:      GetITable   (taskData, v,T); break;
5985    case CUnsignedTable: GetUTable   (taskData, v,T); break;
5986    case CString:        CopyString  (taskData, v, &T->u.string, 0); break;
5987    case CStringTable:   GetStrings  (taskData, v,T); break;
5988    case CXmString:      GetXmString (taskData, v, &T->u.xmString, 0); break;
5989    case CXmStringTable: GetXmStrings(taskData, v,T); break;
5990
5991    default: Crash ("Bad arg type %x",T->tag);
5992  }
5993}
5994
5995static void SetArgType(TaskData *taskData, PolyWord p, void *v, unsigned)
5996{
5997    ArgType *T = (ArgType *)v;
5998    SetArgTypeP(taskData, FST(p), SND(p), T);
5999}
6000
6001static void SetArgs(Arg *A, ArgType *T, unsigned N)
6002{
6003  while(N--)
6004  {
6005    A->name = T->name;
6006
6007    switch(T->tag)
6008    {
6009      case CAccelerators:  A->value = (XtArgVal) T->u.acc; break;
6010      case CBool:          A->value = (XtArgVal) T->u.boolean; break;
6011      case CColormap:      A->value = (XtArgVal) T->u.cmap; break;
6012      case CCursor:        A->value = (XtArgVal) T->u.cursor; break;
6013      case CDimension:     A->value = (XtArgVal) T->u.dim; break;
6014      case CFontList:      A->value = (XtArgVal) T->u.F; break;
6015      case CInt:           A->value = (XtArgVal) T->u.i; break;
6016      case CIntTable:      A->value = (XtArgVal) T->u.I; break;
6017      case CKeySym:        A->value = (XtArgVal) T->u.keysym; break;
6018      case CPixmap:        A->value = (XtArgVal) T->u.pixmap; break;
6019      case CPosition:      A->value = (XtArgVal) T->u.posn; break;
6020      case CString:        A->value = (XtArgVal) T->u.string; break;
6021      case CStringTable:   A->value = (XtArgVal) T->u.S; break;
6022      case CTrans:         A->value = (XtArgVal) T->u.trans; break;
6023      case CUnsignedChar:  A->value = (XtArgVal) T->u.u; break;
6024      case CUnsignedTable: A->value = (XtArgVal) T->u.U; break;
6025      case CVisual:        A->value = (XtArgVal) T->u.visual; break;
6026      case CWidget:        A->value = (XtArgVal) T->u.widget; break;
6027      case CXmString:      A->value = (XtArgVal) T->u.xmString; break;
6028      case CXmStringTable: A->value = (XtArgVal) T->u.X; break;
6029
6030      default: Crash ("Bad arg type %x",T->tag);
6031    }
6032
6033    A++;
6034    T++;
6035  }
6036}
6037
6038/* add current callback to (pending?) FList */
6039static void RunWidgetCallback(Widget w, XtPointer closure, XtPointer call_data)
6040{
6041    C_List *C = (C_List *)closure;
6042
6043    if (callbacks_enabled)
6044    {
6045        // Only synchronous callbacks are handled.
6046        TaskData *taskData = processes->GetTaskDataForThread();
6047        Handle tailHandle     = SAVE(FList);
6048        Handle widgetHandle   = SAVE(C->widget_object);
6049        Handle functionHandle = SAVE(C->function);
6050        Handle pairHandle     = CreatePair(taskData, widgetHandle,functionHandle);
6051
6052        FList = DEREFWORD(CreatePair(taskData, pairHandle,tailHandle));
6053    }
6054#if 0
6055    else printf("Ignoring event for widget %p\n",C->widget_object);
6056#endif
6057}
6058
6059static void SetCallbacks(TaskData *taskData, X_Widget_Object *W, PolyWord list, PolyWord initial)
6060{
6061    char name[100];
6062    Widget w = GetWidget(taskData, (X_Object *)W);
6063
6064    assert(w != NULL); /* SPF */
6065    assert(w != (Widget)1); /* SPF */
6066
6067    for(PolyWord pp = W->callbackList; NONNIL(pp); pp = ((ML_Cons_Cell*)pp.AsObjPtr())->t)
6068    {
6069        MLPair *q = (MLPair *)((ML_Cons_Cell*)pp.AsObjPtr())->h.AsObjPtr();
6070
6071        Poly_string_to_C(FST(q),name,sizeof(name));
6072
6073        if (strcmp(name,"messageCallback")  != 0
6074            && strcmp(name,XtNdestroyCallback) != 0)
6075        {
6076            XtRemoveAllCallbacks(w,name);
6077        }
6078    }
6079
6080#if 0
6081    /* We no longer need the old callback data for this widget,
6082    assuming we've replaced all the callbacks. But what if
6083    we've only replaced some of them? It's probably better
6084    to allow this space leak that to delete vital callback data.
6085    I'll have to think about this hard sometime. (Of course, the
6086    user isn't supposed to call XtSetCallbacks more than once, in which
6087    case the problem doesn't even arise.) SPF 29/2/96 */
6088    PurgeCCallbacks(W,w);
6089#endif
6090
6091    for(PolyWord p = list; NONNIL(p); p = ((ML_Cons_Cell*)p.AsObjPtr())->t)
6092    {
6093        C_List *C = (C_List *)malloc(sizeof(C_List));
6094        MLPair *q = (MLPair *)((ML_Cons_Cell*)p.AsObjPtr())->h.AsObjPtr();
6095
6096        C->function      = SND(q).AsObjPtr();
6097        C->widget_object = W;
6098        C->next          = CList;
6099
6100        debugCreateCallback(W,w,C);
6101
6102        CList = C;
6103
6104        Poly_string_to_C(FST(q),name,sizeof(name));
6105
6106        if (strcmp(name,"messageCallback")  != 0
6107            && strcmp(name,XtNdestroyCallback) != 0)
6108        {
6109            XtAddCallback(w,name,RunWidgetCallback,C);
6110        }
6111    }
6112
6113    W->state = initial;
6114    W->callbackList = list;
6115}
6116
6117static void RunWidgetEventhandler (Widget w, XtPointer p, XEvent *ev, Boolean *c)
6118{
6119    C_List *C = (C_List *)p;
6120    if ( callbacks_enabled )
6121    {
6122        TaskData *taskData = processes->GetTaskDataForThread();
6123        Handle tailHandle     = SAVE(GList);
6124        Handle widgetHandle   = SAVE(C->widget_object);
6125        Handle functionHandle = SAVE(C->function);
6126        Handle pairHandle     = CreatePair(taskData, widgetHandle,functionHandle);
6127
6128        GList = (ML_Cons_Cell *)DEREFHANDLE(CreatePair(taskData, pairHandle,tailHandle));
6129    }
6130}
6131
6132static void AddEventhandler (
6133   TaskData *taskData, X_Widget_Object *W, EventMask EventM, Boolean nonmask, Handle p)
6134{
6135  Widget w = GetWidget(taskData, (X_Object *)W) ;
6136  C_List *C = (C_List *) malloc ( sizeof(C_List) ) ;
6137  /* Add the function to the callback list, so that it
6138     will not be G.C'ed away. */
6139  C->function = DEREFHANDLE(p);
6140  C->widget_object   = W ;
6141  C->next     = CList ;
6142
6143  CList = C ;
6144
6145  XtAddEventHandler (w, EventM, nonmask, RunWidgetEventhandler, C);
6146}
6147
6148static Handle AppInitialise
6149(
6150 TaskData *taskData,
6151 PolyWord s1,
6152 PolyWord s2,
6153 PolyWord s3,
6154 Handle fallbackHead,
6155 Handle argHead
6156 )
6157{
6158    char               displayName[500];
6159    char               appName[500];
6160    char               appClass[500];
6161    XtAppContext       app_context;
6162    Display           *display;
6163    Widget             shell;
6164    Handle dsHandle /* Handle to (X_Display_Object *) */;
6165    int                argc = 0; /* an "int" for Solaris, but should be "unsigned" for SunOS */
6166    unsigned           F = ListLength(DEREFWORD(fallbackHead)) + 1;
6167    unsigned           N = ListLength(DEREFWORD(argHead));
6168    char             **S = (char   **) alloca(F * sizeof(char *));
6169    Arg               *R = (Arg     *) alloca(N * sizeof(Arg));
6170    ArgType           *T = (ArgType *) alloca(N * sizeof(ArgType));
6171
6172    Poly_string_to_C(s1,displayName ,sizeof(displayName));
6173    Poly_string_to_C(s2,appName     ,sizeof(appName));
6174    Poly_string_to_C(s3,appClass    ,sizeof(appClass));
6175
6176    app_context = XtCreateApplicationContext();
6177
6178    GetList4(taskData, DEREFWORD(fallbackHead),S,sizeof(char *),CopyString);
6179    S[F-1] = NULL;   /* list must be NULL terminated */
6180    XtAppSetFallbackResources(app_context,S);
6181
6182    display = XtOpenDisplay(app_context,displayName,appName,appClass,NULL,0,&argc,0);
6183    if (display == 0) RaiseXWindows(taskData, "XtAppInitialise failed (can't open display)");
6184
6185    /* I don't think this is needed.  DCJM 26/5/2000 */
6186    /* add_file_descr(display->fd); */
6187
6188    debug1 ("%s display opened\n",DisplayString(display));
6189    debug1 ("%x display fd\n",display->fd);
6190
6191    /* ok to store C values because this is a BYTE object */
6192    dsHandle = alloc_and_save(taskData, SIZEOF(X_Display_Object), F_MUTABLE_BIT|F_BYTE_OBJ);
6193    DEREFDISPLAYHANDLE(dsHandle)->type        = TAGGED(X_Display);
6194    DEREFDISPLAYHANDLE(dsHandle)->display     = display;
6195    DEREFDISPLAYHANDLE(dsHandle)->screen      = DefaultScreen(display);
6196    DEREFDISPLAYHANDLE(dsHandle)->app_context = app_context;
6197    AddXObject(FINISHED(taskData, dsHandle));
6198
6199    GetList4(taskData, DEREFWORD(argHead),T,sizeof(ArgType),SetArgType);
6200    SetArgs(R,T,N);
6201    shell = XtAppCreateShell(appName,appClass,applicationShellWidgetClass,display,R,N);
6202    FreeArgs(T,N);
6203
6204    if (shell == 0) RaiseXWindows(taskData, "XtAppInitialise failed  (can't create application shell)");
6205
6206    /* added 7/12/94 SPF */
6207    XtAddCallback(shell,XtNdestroyCallback,DestroyWidgetCallback,NULL);
6208
6209    return NewWidget(taskData, dsHandle,shell);
6210}
6211
6212static Handle CreatePopupShell
6213(
6214  TaskData *taskData,
6215  PolyStringObject  *s,
6216  Handle  dsHandle, /* Handle to (X_Display_Object *) */
6217  Widget  parent,
6218  Handle  list
6219)
6220{
6221  char name[100]; Widget shell;
6222
6223  unsigned     N = ListLength(DEREFWORD(list));
6224  Arg     *A = (Arg     *) alloca(N * sizeof(Arg));
6225  ArgType *T = (ArgType *) alloca(N * sizeof(ArgType));
6226
6227  GetList4(taskData, DEREFWORD(list),T,sizeof(ArgType),SetArgType);
6228  SetArgs(A,T,N);
6229
6230  Poly_string_to_C(s,name,sizeof(name));
6231
6232  shell = XtCreatePopupShell(name,applicationShellWidgetClass,parent,A,N);
6233
6234  FreeArgs(T,N);
6235
6236  if (shell == 0) RaiseXWindows(taskData, "XtCreatePopupShell failed");
6237
6238  /* added 7/12/94 SPF */
6239  XtAddCallback(shell,XtNdestroyCallback,DestroyWidgetCallback,NULL);
6240
6241  return NewWidget(taskData, dsHandle,shell);
6242}
6243
6244static Handle CreateXm
6245(
6246  TaskData *taskData,
6247  Widget (*create)(Widget, String, ArgList, Cardinal),
6248  char   *failed,
6249  Handle  dsHandle, /* Handle to (X_Display_Object *) */
6250  Widget  parent,
6251  PolyStringObject *s,
6252  Handle  list      /* Handle to (ML_Cons_Cell *) */
6253)
6254{
6255  char name[100]; Widget w;
6256
6257
6258  unsigned     N = ListLength(DEREFWORD(list));
6259  Arg     *A = (Arg     *) alloca(N * sizeof(Arg));
6260  ArgType *T = (ArgType *) alloca(N * sizeof(ArgType));
6261
6262  GetList4(taskData, DEREFWORD(list),T,sizeof(ArgType),SetArgType);
6263  SetArgs(A,T,N);
6264
6265  Poly_string_to_C(s,name,sizeof(name));
6266
6267  w = (* create)(parent,name,A,N);
6268
6269  FreeArgs(T,N);
6270
6271  if (w == 0) RaiseXWindows(taskData, failed);
6272
6273  XtAddCallback(w,XtNdestroyCallback,DestroyWidgetCallback,NULL);
6274
6275  return NewWidget(taskData, dsHandle,w);
6276}
6277
6278static void SetValues(TaskData *taskData, Widget w, Handle list)
6279{
6280  unsigned     N = ListLength(DEREFWORD(list));
6281  Arg     *A = (Arg     *) alloca(N * sizeof(Arg));
6282  ArgType *T = (ArgType *) alloca(N * sizeof(ArgType));
6283
6284  GetList4(taskData, DEREFWORD(list),T,sizeof(ArgType),SetArgType);
6285  SetArgs(A,T,N);
6286
6287  XtSetValues(w,A,N);
6288
6289  FreeArgs(T,N);
6290}
6291
6292typedef struct
6293{
6294  const char *listName;
6295  char *intName;
6296} StringPair;
6297
6298static StringPair listTypes[] =
6299{
6300  {"argv"                  ,(char *) "argc"},
6301  {"buttonAccelerators"    ,(char *) "buttonCount"},
6302  {"buttonAcceleratorText" ,(char *) "buttonCount"},
6303  {"buttonMnemonicCharSets",(char *) "buttonCount"},
6304  {"buttonMnemonics"       ,(char *) "buttonCount"},
6305  {"buttons"               ,(char *) "buttonCount"},
6306  {"buttonType"            ,(char *) "buttonCount"},
6307  {"children"              ,(char *) "numChildren"},
6308  {"dirListItems"          ,(char *) "dirListItemCount"},
6309  {"fileListItems"         ,(char *) "fileListItemCount"},
6310  {"historyItems"          ,(char *) "historyItemCount"},
6311  {"items"                 ,(char *) "itemCount"},
6312  {"listItems"             ,(char *) "listItemCount"},
6313  {"selectedItems"         ,(char *) "selectedItemCount"},
6314  {"selectionArray"        ,(char *) "selectionArrayCount"},
6315};
6316
6317#define MAXListTYPES (sizeof(listTypes)/sizeof(listTypes[0]))
6318
6319/* (string,(v,tag)) - ML (string*Ctype) */
6320static void GetArgType
6321(
6322  TaskData *taskData,
6323  PolyWord p,
6324  ArgType *T,
6325  int      i, /* not used; needed to keep function type right */
6326  Widget   w
6327)
6328{
6329    T->tag = UNTAGGED(SND(SND(p)));
6330    T->N   = 0;
6331    T->u.i = 0;
6332
6333    CopyString(taskData, FST(p), &T->name, 0);
6334
6335    if (T->tag == CIntTable      ||
6336        T->tag == CUnsignedTable ||
6337        T->tag == CWidgetList    ||
6338        T->tag == CStringTable   ||
6339        T->tag == CXmStringTable)      /* if it is a list type we need to get the length from another resource */
6340    {
6341        Arg arg;
6342        unsigned i;
6343        int result;
6344
6345        for(i = 0; i < MAXListTYPES; i++)
6346        {
6347            if (strcmp(listTypes[i].listName,T->name) == 0) break;
6348        }
6349
6350        if (i == MAXListTYPES) Crash ("Bad list resource name %s",T->name);
6351
6352    arg.name = listTypes[i].intName;
6353        arg.value = (XtArgVal) &result;
6354        /* Bug fix here which only appeared in OpenMotif and LessTif.  We need
6355           to pass the address of an integer here to receive the result.
6356           DCJM 17/5/02. */
6357
6358        XtGetValues(w, &arg, 1);
6359
6360        T->N = result;
6361    }
6362}
6363
6364static Handle CreateWidget(TaskData *taskData, void *p, Handle dsHandle /* Handle to (X_Display_Object *) */)
6365{
6366    return EmptyWidget(taskData, dsHandle, *(Widget*)p);
6367}
6368
6369static Handle CreateXmString(TaskData *taskData, void *t)
6370{
6371    char  *s;
6372    Handle S;
6373
6374    XmStringGetLtoR(*(XmString *)t,(char *) XmSTRING_DEFAULT_CHARSET,&s);
6375
6376    S = Make_string(s);
6377
6378    XtFree(s);
6379
6380    return S;
6381}
6382
6383static Handle CreateFontList
6384(
6385 TaskData *taskData,
6386 Handle     dsHandle, /* Handle to (X_Display_Object *) */
6387 XmFontList F
6388 )
6389{
6390    XmFontContext   C;
6391    XmStringCharSet charset;
6392    XFontStruct    *fs;
6393
6394    Handle list  = 0;
6395    Handle tail  = 0;
6396
6397    if (XmFontListInitFontContext(&C,F) == False) return SAVE(ListNull);
6398    // TODO: This previously reset the save vector each time to make sure it
6399    // didn't overflow.  I've removed that code but it needs to be put back.
6400
6401    while (XmFontListGetNextFont(C,&charset,&fs))
6402    {
6403        Handle L = alloc_and_save(taskData, SIZEOF(ML_Cons_Cell), F_MUTABLE_BIT);
6404
6405        if (list == 0) list = L; // This is the first.
6406
6407        if (tail != 0)
6408        {
6409            DEREFLISTHANDLE(tail)->t = DEREFWORD(L);
6410            FINISHED(taskData, tail);
6411        }
6412
6413        tail = L;
6414        /* the new list element is joined on, but not filled in */
6415        DEREFLISTHANDLE(tail)->h = DEREFWORD(CreatePair(taskData, CreateFontStruct(taskData,fs,dsHandle),Make_string(charset)));
6416        DEREFLISTHANDLE(tail)->t = ListNull;
6417    }
6418
6419    XmFontListFreeFontContext(C);
6420
6421    if (tail != 0) FINISHED(taskData, tail);
6422
6423    return list;
6424}
6425
6426static Handle CreateUChar(TaskData *taskData, void *p)
6427{
6428  return Make_arbitrary_precision(taskData, *(uchar *)p);
6429}
6430
6431static Handle CreateArg(TaskData *taskData, void *v, Handle   dsHandle /* Handle to (X_Display_Object *) */)
6432{
6433    ArgType *T = (ArgType *)v;
6434    Handle value;
6435
6436    switch(T->tag)
6437    {
6438    case CAccelerators:  value = EmptyAcc      (taskData, T->u.acc);       break;
6439    case CBool:          value = Make_bool     (T->u.boolean);      break;
6440    case CColormap:      value = EmptyColormap (taskData, dsHandle,T->u.cmap);   break;
6441    case CCursor:        value = EmptyCursor   (taskData, dsHandle,T->u.cursor); break;
6442    case CDimension:     value = Make_int      (T->u.dim);       break;
6443    case CFontList:      value = CreateFontList(taskData, dsHandle,T->u.F);      break;
6444    case CInt:           value = Make_int      (T->u.i);         break;
6445    case CKeySym:        value = Make_arbitrary_precision (taskData, T->u.keysym);    break;
6446    case CPixmap:        value = EmptyPixmap   (taskData, dsHandle,T->u.pixmap); break;
6447    case CPosition:      value = Make_int      (T->u.posn);      break;
6448    case CString:        value = Make_string   (T->u.string);    break;
6449    case CTrans:         value = EmptyTrans    (taskData, T->u.trans);     break;
6450    case CUnsignedChar:  value = Make_arbitrary_precision (taskData, T->u.u);         break;
6451    case CVisual:        value = EmptyVisual   (taskData, dsHandle,T->u.visual); break;
6452    case CWidget:        value = EmptyWidget   (taskData, dsHandle,T->u.widget); break;
6453
6454    case CXmString:      value = CreateXmString(taskData, &T->u.xmString); break;
6455
6456    case CIntTable:      value = CreateList4(taskData, T->N,T->u.I,sizeof(int),     CreateUnsigned);        break;
6457    case CUnsignedTable: value = CreateList4(taskData, T->N,T->u.U,sizeof(uchar),   CreateUChar);           break;
6458    case CStringTable:   value = CreateList4(taskData, T->N,T->u.S,sizeof(char *),  CreateString);          break;
6459    case CWidgetList:    value = CreateList5(taskData,T->N,T->u.W,sizeof(Widget),  CreateWidget,dsHandle); break;
6460    case CXmStringTable: value = CreateList4(taskData, T->N,T->u.X,sizeof(XmString),CreateXmString);        break;
6461
6462    default: Crash ("Bad arg type %x",T->tag); /*NOTREACHED*/
6463    }
6464
6465    return value;
6466}
6467
6468static Handle GetValue
6469(
6470 TaskData *taskData,
6471 Handle  dsHandle, /* Handle to (X_Display_Object *) */
6472 Widget  w,
6473 PolyWord pair /* ML (string*Ctype) */
6474 )
6475{
6476    Arg       A;
6477    ArgType   T;
6478    XmString *X = (XmString *) 0x55555555;
6479    XmString *Y = (XmString *) 0xAAAAAAAA;
6480
6481    GetArgType(taskData,pair,&T,0,w);
6482
6483    A.name  = T.name;
6484    A.value = (XtArgVal) &T.u;
6485    T.u.X   = X;
6486
6487    /* The value is set to X. If it is left set to X      */
6488    /* then this may be a value this widget doesn't have. */
6489
6490    XtGetValues(w,&A,1);
6491
6492    if (T.u.X == X)
6493    {
6494        T.u.X = Y;
6495
6496        XtGetValues(w,&A,1);
6497
6498        if (T.u.X == Y)
6499        {
6500            char buffer[500];
6501
6502            sprintf(buffer,"XtGetValues (%s) failed",T.name);
6503
6504            RaiseXWindows(taskData, buffer);
6505        }
6506    }
6507
6508    return CreateArg(taskData, &T,dsHandle);
6509}
6510
6511/* What is the real ML type of p? (string*Ctype*string*string*string*Ctype) */
6512static void GetResource
6513(
6514 TaskData *taskData,
6515 PolyWord      pp,
6516 XtResource *R,
6517 int         i,
6518 ArgType    *T,
6519 ArgType    *D,
6520 Widget      w
6521 )
6522{
6523    PolyObject *p = pp.AsObjPtr();
6524    GetArgType(taskData,pp,&T[i],0,w); /* HACK !!! */
6525
6526    CopyString(taskData, p->Get(0), &R->resource_name, 0);
6527    CopyString(taskData, p->Get(2), &R->resource_class, 0);
6528    CopyString(taskData, p->Get(3), &R->resource_type, 0);
6529
6530    R->resource_size   = 4;
6531    R->resource_offset = (byte*)(&T[i].u) - (byte*)(T);
6532
6533    SetArgTypeP(taskData, p->Get(4), p->Get(5), &D[i]); /* This was a hack.  I hope I converted it correctly.  DCJM */
6534
6535    R->default_type = D[i].name;
6536
6537    if (UNTAGGED(p->Get(5).AsObjPtr()->Get(1)) == CString)
6538        R->default_addr = (XtPointer) D[i].u.string;
6539    else
6540        R->default_addr = (XtPointer) &D[i].u;
6541}
6542
6543static Handle GetSubresources
6544(
6545 TaskData *taskData,
6546 Handle  dsHandle, /* Handle to (X_Display_Object *) */
6547 Widget  w,
6548 PolyStringObject *s1,
6549 PolyStringObject *s2,
6550 Handle  list
6551 )
6552{
6553    char name [100];
6554    char clas[100];
6555
6556    unsigned        N = ListLength(DEREFWORD(list));
6557    ArgType    *T = (ArgType    *) alloca(N * sizeof(ArgType));
6558    ArgType    *D = (ArgType    *) alloca(N * sizeof(ArgType));
6559    XtResource *R = (XtResource *) alloca(N * sizeof(XtResource));
6560
6561    {
6562        unsigned i = 0;
6563
6564        for(PolyWord p = DEREFWORD(list); NONNIL(p); p = ((ML_Cons_Cell *)p.AsObjPtr())->t)
6565        {
6566            GetResource(taskData,((ML_Cons_Cell *)p.AsObjPtr())->h,&R[i],i,T,D,w);
6567            i++;
6568        }
6569    }
6570
6571    Poly_string_to_C(s1,name ,sizeof(name));
6572    Poly_string_to_C(s2,clas,sizeof(clas));
6573
6574    XtGetSubresources(w,T,name,clas,R,N,NULL,0);
6575
6576    return CreateList5(taskData,N,T,sizeof(ArgType),CreateArg,dsHandle);
6577}
6578
6579static Handle GetApplicationResources (TaskData *taskData,
6580                                       Handle  dsHandle, /* Handle to (X_Display_Object *) */
6581                                       Widget  w,
6582                                       Handle  list
6583                                       )
6584{
6585    unsigned        N = ListLength (DEREFLISTHANDLE(list)) ;
6586    ArgType    *T = (ArgType    *) alloca ( N * sizeof(ArgType) ) ;
6587    ArgType    *D = (ArgType    *) alloca ( N * sizeof(ArgType) ) ;
6588    XtResource *R = (XtResource *) alloca ( N * sizeof(XtResource) ) ;
6589
6590    {
6591        unsigned i = 0;
6592        for(PolyWord p = DEREFWORD(list); NONNIL(p); p = ((ML_Cons_Cell *)p.AsObjPtr())->t)
6593        {
6594            GetResource(taskData,((ML_Cons_Cell *)p.AsObjPtr())->h,&R[i],i,T,D,w);
6595            i++;
6596        }
6597    }
6598
6599    XtGetApplicationResources ( w,T,R,N,NULL,0 ) ;
6600
6601    return CreateList5 (taskData, N,T,sizeof(ArgType),CreateArg,dsHandle ) ;
6602}
6603
6604static void GetChild(TaskData *taskData, PolyWord p, void *v, unsigned)
6605{
6606    Widget *w = (Widget *)v;
6607    *w = GetWidget(taskData, (X_Object *)p.AsObjPtr());
6608
6609    if (XtParent(*w) == NULL) RaiseXWindows(taskData, "not a child");
6610}
6611
6612static void ManageChildren(TaskData *taskData, Handle list)
6613{
6614    unsigned    N = ListLength(DEREFWORD(list));
6615    Widget *W = (Widget *) alloca(N * sizeof(Widget));
6616
6617    GetList4(taskData, DEREFWORD(list),W,sizeof(Widget),GetChild);
6618
6619    XtManageChildren(W,N);
6620}
6621
6622static void UnmanageChildren(TaskData *taskData, Handle list)
6623{
6624    unsigned    N = ListLength(DEREFWORD(list));
6625    Widget *W = (Widget *) alloca(N * sizeof(Widget));
6626
6627    GetList4(taskData, DEREFWORD(list),W,sizeof(Widget),GetChild);
6628
6629    XtUnmanageChildren(W,N);
6630}
6631
6632static Handle ParseTranslationTable(TaskData *taskData, PolyStringObject *s)
6633{
6634    XtTranslations table;
6635
6636    int   size   = s->length + 1;
6637    char *buffer = (char *)alloca(size);
6638
6639    Poly_string_to_C(s,buffer,size);
6640    table = XtParseTranslationTable(buffer);
6641
6642    return EmptyTrans(taskData, table);
6643}
6644
6645static void CommandError(TaskData *taskData, Widget w, PolyWord s)
6646{
6647    XmString p;
6648    GetXmString(taskData, s, &p, 0);
6649    XmCommandError(w,p);
6650    XmStringFree (p);
6651}
6652
6653static void FileSelectionDoSearch(TaskData *taskData, Widget w, PolyWord s)
6654{
6655    XmString p;
6656    GetXmString(taskData, s, &p, 0);
6657    XmFileSelectionDoSearch(w,p);
6658    XmStringFree (p);
6659}
6660
6661static void MenuPosition (Widget w, int x, int y)
6662{
6663    XButtonPressedEvent ev;
6664    memset (&ev, 0, sizeof(ev));
6665    ev.type = 4; /* Must be button. */
6666    ev.x_root = x;
6667    ev.y_root = y;
6668    ev.button = 3; /* Is this required? */
6669    ev.same_screen = 1; /* Assume this. */
6670    XmMenuPosition (w, &ev);
6671}
6672
6673static Handle XmIsSomething(TaskData *taskData, unsigned is_code, Widget widget)
6674{
6675  unsigned i;
6676
6677  switch(is_code)
6678  {
6679    case  1: i = XmIsArrowButton        (widget); break;
6680    case  2: i = XmIsArrowButtonGadget  (widget); break;
6681    case  3: i = XmIsBulletinBoard      (widget); break;
6682    case  4: i = XmIsCascadeButton      (widget); break;
6683    case  5: i = XmIsCascadeButtonGadget(widget); break;
6684    case  6: i = XmIsCommand            (widget); break;
6685    case  7: i = XmIsDesktopObject      (widget); break; /* ok - SPF 9/8/94 */
6686    case  8: i = XmIsDialogShell        (widget); break;
6687/* Unsupported in Motif 1.2
6688    case  9: i = XmIsDisplayObject      (widget); break;
6689*/
6690    case 10: i = XmIsDrawingArea        (widget); break;
6691    case 11: i = XmIsDrawnButton        (widget); break;
6692    case 12: i = XmIsExtObject          (widget); break; /* ok - SPF 9/8/94 */
6693    case 13: i = XmIsFileSelectionBox   (widget); break;
6694    case 14: i = XmIsForm               (widget); break;
6695    case 15: i = XmIsFrame              (widget); break;
6696    case 16: i = XmIsGadget             (widget); break;
6697    case 17: i = XmIsLabel              (widget); break;
6698    case 18: i = XmIsLabelGadget        (widget); break;
6699    case 19: i = XmIsList               (widget); break;
6700    case 20: i = XmIsMainWindow         (widget); break;
6701    case 21: i = XmIsManager            (widget); break;
6702    case 22: i = XmIsMenuShell          (widget); break;
6703    case 23: i = XmIsMessageBox         (widget); break;
6704    case 24: i = XmIsMotifWMRunning     (widget); break;
6705    case 25: i = XmIsPanedWindow        (widget); break;
6706    case 26: i = XmIsPrimitive          (widget); break;
6707    case 27: i = XmIsPushButton         (widget); break;
6708    case 28: i = XmIsPushButtonGadget   (widget); break;
6709    case 29: i = XmIsRowColumn          (widget); break;
6710    case 30: i = XmIsScale              (widget); break;
6711/* Unsupported in Motif 1.2
6712    case 31: i = XmIsScreenObject       (widget); break;
6713*/
6714    case 32: i = XmIsScrollBar          (widget); break;
6715    case 33: i = XmIsScrolledWindow     (widget); break;
6716    case 34: i = XmIsSelectionBox       (widget); break;
6717    case 35: i = XmIsSeparator          (widget); break;
6718    case 36: i = XmIsSeparatorGadget    (widget); break;
6719#ifdef LESSTIF_VERSION
6720/* This is not supported in LessTif, at least not 0.89. */
6721    case 37: RaiseXWindows(taskData, "XmIsShellExt: not implemented");
6722#else
6723    case 37: i = XmIsShellExt           (widget); break; /* ok - SPF 9/8/94 */
6724#endif
6725    case 38: i = XmIsText               (widget); break;
6726    case 39: i = XmIsTextField          (widget); break;
6727    case 40: i = XmIsToggleButton       (widget); break;
6728    case 41: i = XmIsToggleButtonGadget (widget); break;
6729    case 42: i = XmIsVendorShell        (widget); break;
6730    case 43: i = XmIsVendorShellExt     (widget); break; /* ok - SPF 9/8/94 */
6731/* Unsupported in Motif 1.2
6732    case 44: i = XmIsWorldObject        (widget); break;
6733*/
6734
6735    default: Crash ("Bad code (%d) in XmIsSomething",is_code);
6736            /* NOTREACHED*/
6737  }
6738
6739  return Make_bool(i);
6740}
6741
6742
6743/******************************************************************************/
6744/*                                                                            */
6745/*      Wrappers for standard widget operations                               */
6746/*                                                                            */
6747/******************************************************************************/
6748
6749/************************* 0 parameters, no result ****************************/
6750
6751/* widget -> unit */
6752static void WidgetAction
6753(
6754  TaskData *taskData,
6755  char *func_name,
6756  Widget getWidget(TaskData *, char *, X_Object *),
6757  void applyFunc(Widget),
6758  X_Object *arg1
6759)
6760{
6761  Widget w = getWidget(taskData,func_name,arg1);
6762  applyFunc(w);
6763}
6764
6765/************************* 1 parameter, no result *****************************/
6766
6767/* widget -> bool -> unit */
6768static void WidgetBoolAction
6769(
6770  TaskData *taskData,
6771  char *func_name,
6772  Widget getWidget(TaskData *, char *, X_Object *),
6773  void applyFunc(Widget, Boolean),
6774  X_Object *arg1,
6775  PolyWord arg2
6776)
6777{
6778  Widget w  = getWidget(taskData,func_name,arg1);
6779  Boolean b = (get_C_short(taskData, arg2) != 0);
6780  applyFunc(w,b);
6781}
6782
6783/* widget -> int -> unit */
6784static void WidgetIntAction
6785(
6786  TaskData *taskData,
6787  char *func_name,
6788  Widget getWidget(TaskData *, char *, X_Object *),
6789  void applyFunc(Widget, int),
6790  X_Object *arg1,
6791  PolyWord arg2
6792)
6793{
6794  Widget w = getWidget(taskData,func_name,arg1);
6795  int i    = get_C_long(taskData, arg2);
6796  applyFunc(w,i);
6797}
6798
6799/* widget -> int -> unit */
6800static void WidgetLongAction
6801(
6802  TaskData *taskData,
6803  char *func_name,
6804  Widget getWidget(TaskData *, char *, X_Object *),
6805  void applyFunc(Widget, long),
6806  X_Object *arg1,
6807  PolyWord arg2
6808)
6809{
6810  Widget w = getWidget(taskData,func_name,arg1);
6811  long i   = get_C_long(taskData, arg2);
6812  applyFunc(w,i);
6813}
6814
6815/* widget -> string -> unit */
6816static void WidgetXmstringAction
6817(
6818  TaskData *taskData,
6819  char *func_name,
6820  Widget getWidget(TaskData *, char *, X_Object *),
6821  void applyFunc(Widget, XmString),
6822  X_Object *arg1,
6823  PolyWord arg2
6824)
6825{
6826  Widget w     = getWidget(taskData,func_name,arg1);
6827  XmString s;
6828  GetXmString(taskData, arg2, &s, 0);
6829  applyFunc(w,s);
6830  XmStringFree(s);
6831}
6832
6833
6834/* widget -> string list -> unit */
6835static void WidgetXmstringlistAction
6836(
6837  TaskData *taskData,
6838  char *func_name,
6839  Widget getWidget(TaskData *, char *, X_Object *),
6840  void applyFunc(Widget, XmString *, int),
6841  X_Object *arg1,
6842  ML_Cons_Cell *arg2
6843)
6844{
6845  Widget w          = getWidget(taskData,func_name,arg1);
6846  unsigned n             = ListLength(arg2);
6847  XmString *strings = (XmString *)alloca(n * sizeof(XmString));
6848  GetList4(taskData, arg2,strings,sizeof(XmString),GetXmString);
6849  applyFunc(w,strings,n);
6850  for (unsigned i = 0; i < n; i ++) XmStringFree(strings[i]);
6851}
6852
6853/************************* 2 parameters, no result ****************************/
6854
6855/* widget -> int -> bool -> unit */
6856static void WidgetIntBoolAction
6857(
6858  TaskData *taskData,
6859  char *func_name,
6860  Widget getWidget(TaskData *, char *, X_Object *),
6861  void applyFunc(Widget, int, Boolean),
6862  X_Object *arg1,
6863  PolyWord arg2,
6864  PolyWord arg3
6865)
6866{
6867  Widget w  = getWidget(taskData,func_name,arg1);
6868  int i     = get_C_long(taskData, arg2);
6869  Boolean b = (get_C_ushort(taskData, arg3) != 0);
6870  applyFunc(w,i,b);
6871}
6872
6873/* widget -> int -> int -> unit */
6874static void WidgetIntIntAction
6875(
6876  TaskData *taskData,
6877  char *func_name,
6878  Widget getWidget(TaskData *, char *, X_Object *),
6879  void applyFunc(Widget, int, int),
6880  X_Object *arg1,
6881  PolyWord arg2,
6882  PolyWord arg3
6883)
6884{
6885  Widget w  = getWidget(taskData,func_name,arg1);
6886  int x     = get_C_long(taskData, arg2);
6887  int y     = get_C_long(taskData, arg3);
6888  applyFunc(w,x,y);
6889}
6890
6891/* widget -> string -> bool -> unit */
6892static void WidgetXmstringBoolAction
6893(
6894  TaskData *taskData,
6895  char *func_name,
6896  Widget getWidget(TaskData *, char *, X_Object *),
6897  void applyFunc(Widget, XmString, Boolean),
6898  X_Object *arg1,
6899  PolyWord arg2,
6900  PolyWord arg3
6901)
6902{
6903  Widget w     = getWidget(taskData,func_name,arg1);
6904  XmString s;
6905  Boolean b    = (get_C_ushort(taskData, arg3) != 0);
6906
6907  GetXmString(taskData, arg2, &s, 0);
6908  applyFunc(w,s,b);
6909  XmStringFree(s);
6910}
6911
6912
6913/* widget -> string -> int -> unit */
6914static void WidgetXmstringIntAction
6915(
6916  TaskData *taskData,
6917  char *func_name,
6918  Widget getWidget(TaskData *, char *, X_Object *),
6919  void applyFunc(Widget, XmString, int),
6920  X_Object *arg1,
6921  PolyWord arg2,
6922  PolyWord arg3
6923)
6924{
6925  Widget w     = getWidget(taskData,func_name,arg1);
6926  XmString s;
6927  int i        = get_C_long(taskData, arg3);
6928  GetXmString(taskData, arg2, &s, 0);
6929  applyFunc(w,s,i);
6930  XmStringFree(s);
6931}
6932
6933/* widget -> string list -> int -> unit */
6934static void WidgetXmstringlistIntAction
6935(
6936  TaskData *taskData,
6937  char *func_name,
6938  Widget getWidget(TaskData *, char *, X_Object *),
6939  void applyFunc(Widget, XmString *, int, int),
6940  X_Object *arg1,
6941  ML_Cons_Cell *arg2,
6942  PolyWord arg3
6943)
6944{
6945  Widget w          = getWidget(taskData,func_name,arg1);
6946  unsigned n             = ListLength(arg2);
6947  int i             = get_C_long(taskData, arg3);
6948  XmString *strings = (XmString *)alloca(n * sizeof(XmString));
6949
6950  GetList4(taskData, arg2,strings,sizeof(XmString),GetXmString);
6951  applyFunc(w,strings,n,i);
6952  for (unsigned i = 0; i < n; i ++) XmStringFree(strings[i]);
6953}
6954
6955/************************* n parameters, some result **************************/
6956static Handle int_ptr_to_arb(TaskData *taskData, void *p)
6957{
6958    return Make_arbitrary_precision(taskData, *(int *)p);
6959}
6960
6961/* widget -> int */
6962static Handle WidgetToInt
6963(
6964  TaskData *taskData,
6965  char *func_name,
6966  Widget getWidget(TaskData *, char *, X_Object *),
6967  int applyFunc(Widget),
6968  X_Object *arg1
6969)
6970{
6971  Widget w = getWidget(taskData, func_name,arg1);
6972  int res  = applyFunc(w);
6973  return(Make_arbitrary_precision(taskData, res));
6974}
6975
6976/* widget -> int */
6977static Handle WidgetToLong
6978(
6979  TaskData *taskData,
6980  char *func_name,
6981  Widget getWidget(TaskData *taskData, char *, X_Object *),
6982  long applyFunc(Widget),
6983  X_Object *arg1
6984)
6985{
6986  Widget w = getWidget(taskData, func_name,arg1);
6987  long res  = applyFunc(w);
6988  return(Make_arbitrary_precision(taskData, res));
6989}
6990
6991#if 0
6992/* widget -> int */
6993static Handle WidgetToUnsigned
6994(
6995  TaskData *taskData,
6996  char *func_name,
6997  Widget getWidget(TaskData *, char *, X_Object *),
6998  unsigned applyFunc(Widget),
6999  X_Object *arg1
7000)
7001{
7002  Widget w = getWidget(taskData, func_name,arg1);
7003  unsigned res  = applyFunc(w);
7004  return(Make_arbitrary_precision(taskData, res));
7005}
7006#endif
7007
7008/* widget -> bool */
7009static Handle WidgetToBool
7010(
7011  TaskData *taskData,
7012  char *func_name,
7013  Widget getWidget(TaskData *, char *, X_Object *),
7014  Boolean applyFunc(Widget),
7015  X_Object *arg1
7016)
7017{
7018  Widget w = getWidget(taskData, func_name,arg1);
7019  Boolean res  = applyFunc(w);
7020  return(Make_bool(res));
7021}
7022
7023/* widget -> string */
7024static Handle WidgetToString
7025(
7026  TaskData *taskData,
7027  char *func_name,
7028  Widget getWidget(TaskData *, char *, X_Object *),
7029  char *applyFunc(Widget),
7030  X_Object *arg1
7031)
7032{
7033  Widget w   = getWidget(taskData, func_name,arg1);
7034  char *s    = applyFunc(w);
7035  Handle res = Make_string(s); /* safe, even if C pointer is NULL */
7036  XtFree(s);
7037  return(res);
7038}
7039
7040/* widget -> int list */
7041static Handle WidgetToIntlist
7042(
7043  TaskData *taskData,
7044  char *func_name,
7045  Widget getWidget(TaskData *, char *, X_Object *),
7046  Boolean applyFunc(Widget, int**, int *),
7047  X_Object *arg1
7048)
7049{
7050  int item_count, *items;
7051  Boolean non_empty;
7052  Widget w  = getWidget(taskData,func_name,arg1);
7053
7054  non_empty = applyFunc(w, &items, &item_count);
7055
7056  if (non_empty != TRUE)
7057    /* nothing found, and Motif hasn't allocated any space */
7058    /* so just retun nil */
7059    {
7060       return (SAVE(ListNull));
7061    }
7062  else
7063    /* copy the list into the ML heap, then free it */
7064    {
7065      Handle res = CreateList4(taskData, item_count,items,sizeof(int),int_ptr_to_arb);
7066      XtFree((char *)items);
7067      return res;
7068    }
7069}
7070
7071/* widget -> string -> int list */
7072static Handle WidgetXmstringToIntlist
7073(
7074  TaskData *taskData,
7075  char *func_name,
7076  Widget getWidget(TaskData *, char *, X_Object *),
7077  Boolean applyFunc(Widget, XmString, int**, int *),
7078  X_Object *arg1,
7079  PolyWord arg2
7080)
7081{
7082  int item_count, *items;
7083  Boolean non_empty;
7084  Widget w     = getWidget(taskData,func_name,arg1);
7085  XmString s;
7086
7087  GetXmString(taskData, arg2, &s, 0);
7088  non_empty = applyFunc(w, s, &items, &item_count);
7089  XmStringFree(s);
7090
7091  if (non_empty != TRUE)
7092    /* nothing found, so just retun nil */
7093    {
7094       return (SAVE(ListNull));
7095    }
7096  else
7097    /* copy the list into the ML heap, then free it */
7098    {
7099      Handle res = CreateList4(taskData, item_count,items,sizeof(int),int_ptr_to_arb);
7100      XtFree((char *)items);
7101      return res;
7102    }
7103}
7104
7105/* widget -> string -> int */
7106static Handle WidgetXmstringToInt
7107(
7108  TaskData *taskData,
7109  char *func_name,
7110  Widget getWidget(TaskData *, char *, X_Object *),
7111  int applyFunc(Widget, XmString),
7112  X_Object *arg1,
7113  PolyWord arg2
7114)
7115{
7116  Widget w     = getWidget(taskData,func_name,arg1);
7117  XmString s;
7118  int res;
7119
7120  GetXmString(taskData, arg2, &s, 0);
7121  res = applyFunc(w, s);
7122  XmStringFree(s);
7123
7124  return (Make_int(res));
7125}
7126
7127/* widget -> string -> bool */
7128static Handle WidgetXmstringToBool
7129(
7130  TaskData *taskData,
7131  char *func_name,
7132  Widget getWidget(TaskData *, char *, X_Object *),
7133  Boolean applyFunc(Widget, XmString),
7134  X_Object *arg1,
7135  PolyWord arg2
7136)
7137{
7138  Widget w     = getWidget(taskData,func_name,arg1);
7139  XmString s;
7140  Boolean res;
7141
7142  GetXmString(taskData, arg2, &s, 0);
7143  res = applyFunc(w, s);
7144  XmStringFree(s);
7145
7146  return (Make_bool(res));
7147}
7148
7149
7150/******************************************************************************/
7151
7152/* code added SPF 25/2/95 */
7153static bool isPossibleString(PolyObject *P)
7154{
7155    if (!OBJ_IS_DATAPTR(P)) return false;
7156
7157    POLYUNSIGNED L = P->LengthWord();
7158
7159    if (! OBJ_IS_BYTE_OBJECT(L)) return false;
7160
7161    /* get object PolyWord count */
7162    POLYUNSIGNED n = OBJ_OBJECT_LENGTH(L);
7163
7164    if (n < 1) return false;
7165
7166    /* get string byte count */
7167    POLYUNSIGNED m = P->Get(0).AsUnsigned();
7168
7169    /* number of words to hold the bytes */
7170    m = (m + 3) / 4;
7171
7172    /* number of words to hold the bytes, plus the byte count */
7173    m = m + 1;
7174
7175    /* If that's the same as the object PolyWord count,
7176    we've probably got a genuine string! */
7177    return (m == n);
7178}
7179
7180/* Prints out the contents of a PolyWord in the X interface tuple */
7181static void DebugPrintWord(PolyWord P /* was X_Object *P */)
7182{
7183    TaskData *taskData = processes->GetTaskDataForThread();
7184    if (IS_INT((P)))
7185    {
7186        printf("Short %d", (int)UNTAGGED(P));
7187        return;
7188    }
7189
7190    if (isPossibleString(P.AsObjPtr()))
7191    {
7192        if (((PolyStringObject*)P.AsObjPtr())->length <= 40)
7193        {
7194            printf("String: \"");
7195            print_string((PolyStringObject*) P.AsObjPtr());
7196            printf("\"");
7197            return;
7198        }
7199        else
7200        {
7201            printf("Long String: %p", P.AsAddress());
7202            return;
7203        }
7204    }
7205
7206    /* The problem with the following code was that we can't be sure
7207    that the object we have is really an X_Object - it might just
7208    look like one. If this is the case, when we try to validate
7209    the object using ResourceExists we may get a core dump because
7210    ResourceExists assumes it has a valid X_Object and calls
7211    hashId which dereferences fields within the so-called X_object.
7212    That's why we redefine ResourceExists to be SafeResourceExists
7213    which doesn't make any assumptions about the contents of the
7214    so-called X_object. SPF 6/4/95 */
7215
7216#define XP ((X_Object *)P.AsObjPtr())
7217#define ResourceExists SafeResourceExists
7218    {
7219        switch(UNTAGGED(XP->type))
7220        {
7221        case X_GC:       (ResourceExists(XP)
7222                             ? printf("GC %lx", GetGC(taskData, XP)->gid)
7223                             : printf("Old GC <%lx>",P.AsUnsigned()));
7224            return;
7225
7226        case X_Font:     (ResourceExists(XP)
7227                             ? printf("Font %lx",GetFont(taskData, XP))
7228                             : printf("Old Font <%x>",(int)P.AsUnsigned()));
7229            return;
7230
7231        case X_Cursor:   (ResourceExists(XP)
7232                             ? printf("Cursor %lx",GetCursor(taskData, XP))
7233                             : printf("Old Cursor <%x>",(int)P.AsUnsigned()));
7234            return;
7235
7236        case X_Window:   (ResourceExists(XP)
7237                             ? printf("Window %lx",GetWindow(taskData, XP))
7238                             : printf("Old Window <%p>",P.AsAddress()));
7239            return;
7240
7241        case X_Pixmap:   (ResourceExists(XP)
7242                             ? printf("Pixmap %lx",GetPixmap(taskData, XP))
7243                             : printf("Old Pixmap <%p>",P.AsAddress()));
7244            return;
7245
7246        case X_Colormap: (ResourceExists(XP)
7247                             ? printf("Colormap %lx",GetColormap(taskData, XP))
7248                             : printf("Old Colormap <%p>",P.AsAddress()));
7249            return;
7250
7251        case X_Visual:   (ResourceExists(XP)
7252                             ? printf("Visual %lx",GetVisual(taskData, XP)->visualid)
7253                             : printf("Old Visual <%p>",P.AsAddress()));
7254            return;
7255
7256        case X_Widget:   (ResourceExists(XP)
7257                             ? printf("Widget %p",GetNWidget(taskData, XP))
7258                             : printf("Old Widget <%p>",P.AsAddress()));
7259            return;
7260
7261        case X_Trans:    (ResourceExists(XP)
7262                             ? printf("Trans %p",GetTrans(taskData, XP))
7263                             : printf("Old Trans <%p>",P.AsAddress()));
7264            return;
7265
7266        case X_Acc:      (ResourceExists(XP)
7267                             ? printf("Acc %p",GetAcc(taskData, XP))
7268                             : printf("Old Acc <%p>",P.AsAddress()));
7269            return;
7270
7271        case X_Display:  (ResourceExists(XP)
7272                             ? printf("Display %s", DisplayString(GetDisplay(taskData, XP)))
7273                             + printf(":%x", GetDisplay(taskData, XP)->fd)
7274                             : printf("Old Display <%p>",P.AsAddress()));
7275            return;
7276
7277        default:         printf("Pointer "ZERO_X"%p",P.AsAddress());
7278            return;
7279        }
7280    }
7281#undef ResourceExists
7282#undef XP
7283}
7284
7285/* Prints out the contents of the X interface tuple */
7286static void DebugPrintCode(PolyObject *pt)
7287{
7288    POLYUNSIGNED N = pt->Length();
7289    POLYUNSIGNED i = 1;
7290    assert(IS_INT(pt->Get(0)));
7291
7292    printf("%ld:(", UNTAGGED(pt->Get(0)));
7293
7294    while(i < N)
7295    {
7296        DebugPrintWord(pt->Get(i++));
7297        if (i < N)
7298            printf(",");
7299    }
7300
7301    printf(")\n");
7302}
7303
7304#define P0  DEREFHANDLE(params)->Get(0)
7305#define P1  DEREFHANDLE(params)->Get(1)
7306#define P2  DEREFHANDLE(params)->Get(2)
7307#define P3  DEREFHANDLE(params)->Get(3)
7308#define P4  DEREFHANDLE(params)->Get(4)
7309#define P5  DEREFHANDLE(params)->Get(5)
7310#define P6  DEREFHANDLE(params)->Get(6)
7311#define P7  DEREFHANDLE(params)->Get(7)
7312#define P8  DEREFHANDLE(params)->Get(8)
7313#define P9  DEREFHANDLE(params)->Get(9)
7314#define P10 DEREFHANDLE(params)->Get(10)
7315#define P11 DEREFHANDLE(params)->Get(11)
7316#define P12 DEREFHANDLE(params)->Get(12)
7317
7318#define XP1 ((X_Object *)P1.AsObjPtr())
7319#define XP2 ((X_Object *)P2.AsObjPtr())
7320#define XP3 ((X_Object *)P3.AsObjPtr())
7321#define XP4 ((X_Object *)P4.AsObjPtr())
7322#define XP5 ((X_Object *)P5.AsObjPtr())
7323#define XP6 ((X_Object *)P6.AsObjPtr())
7324#define XP7 ((X_Object *)P7.AsObjPtr())
7325
7326/* Xwindows_c gets passed the address of an object in save_vec, */
7327/* which is itself a pointer to a tuple in the Poly heap.       */
7328
7329Handle XWindows_c(TaskData *taskData, Handle params)
7330{
7331    int code = get_C_short(taskData, P0);
7332
7333    if ((debugOptions & DEBUG_X)) DebugPrintCode(DEREFHANDLE(params));
7334
7335    switch(code)
7336    {
7337    case XCALL_Not:
7338        return Make_arbitrary_precision(taskData, ~ get_C_ulong(taskData, P1));
7339
7340    case XCALL_And:
7341        return Make_arbitrary_precision(taskData, get_C_ulong(taskData, P1) & get_C_ulong(taskData, P2));
7342
7343    case XCALL_Or:
7344        return Make_arbitrary_precision(taskData, get_C_ulong(taskData, P1) | get_C_ulong(taskData, P2));
7345
7346    case XCALL_Xor:
7347        return Make_arbitrary_precision(taskData, get_C_ulong(taskData, P1) ^ get_C_ulong(taskData, P2));
7348
7349    case XCALL_DownShift:
7350        return Make_arbitrary_precision(taskData, get_C_ulong(taskData, P1) >> get_C_ulong(taskData, P2));
7351
7352    case XCALL_UpShift:
7353        return Make_arbitrary_precision(taskData, get_C_ulong(taskData, P1) << get_C_ulong(taskData, P2));
7354
7355    case XCALL_NoDrawable:
7356        return EmptyPixmap(taskData, SAVE(ListNull),(Pixmap)get_C_ulong(taskData, P1));
7357
7358    case XCALL_NoCursor:
7359        return EmptyCursor(taskData, SAVE(ListNull),(Cursor)None);
7360
7361    case XCALL_NoFont:
7362        return EmptyFont(taskData, SAVE(ListNull),(Font)None,(XFontStruct *)NULL);
7363
7364    case XCALL_NoColormap:
7365        return EmptyColormap(taskData, SAVE(ListNull),(Colormap) None);
7366
7367    case XCALL_NoVisual:
7368        return EmptyVisual(taskData, SAVE(ListNull),(Visual *)None);
7369
7370    case XCALL_GetTimeOfDay:
7371        return GetTimeOfDay(taskData);
7372
7373        /* Colorcells 100 */
7374    case XCALL_XAllocColor:
7375        return AllocColor(taskData, GetDisplay(taskData, XP1),GetColormap(taskData, XP1),GetXColor1(taskData, P2));
7376
7377    case XCALL_XAllocColorCells:
7378        return AllocColorCells(taskData, GetDisplay(taskData, XP1),
7379            GetColormap(taskData, XP1),
7380            get_C_ulong(taskData, P2),
7381            get_C_ulong(taskData, P3),
7382            get_C_ulong(taskData, P4));
7383
7384    case XCALL_XAllocColorPlanes:
7385        return AllocColorPlanes(taskData, GetDisplay(taskData, XP1),
7386            GetColormap(taskData, XP1),
7387            get_C_ulong(taskData, P2),
7388            get_C_ulong(taskData, P3),
7389            get_C_ulong(taskData, P4),
7390            get_C_ulong(taskData, P5),
7391            get_C_ulong(taskData, P6));
7392
7393    case XCALL_XAllocNamedColor:
7394        return AllocNamedColor(taskData, GetDisplay(taskData, XP1),GetColormap(taskData, XP1),GetString(P2));
7395
7396    case XCALL_XFreeColors:
7397        FreeColors(taskData, GetDisplay(taskData, XP1),GetColormap(taskData, XP1),SAVE(P2),get_C_ulong(taskData, P3));
7398        break;
7399
7400    case XCALL_XLookupColor:
7401        return LookupColor(taskData, GetDisplay(taskData, XP1),GetColormap(taskData, XP1),GetString(P2));
7402
7403    case XCALL_XParseColor:
7404        return ParseColor(taskData, GetDisplay(taskData, XP1),GetColormap(taskData, XP1),GetString(P2));
7405
7406    case XCALL_XQueryColor:
7407        return QueryColor(taskData, GetDisplay(taskData, XP1),GetColormap(taskData, XP1),get_C_ulong(taskData, P2));
7408
7409    case XCALL_XQueryColors:
7410        return QueryColors(taskData, GetDisplay(taskData, XP1),GetColormap(taskData, XP1),SAVE(P2));
7411
7412    case XCALL_XStoreColor:
7413        XStoreColor(GetDisplay(taskData, XP1),GetColormap(taskData, XP1),GetXColor1(taskData, P2));
7414        break;
7415
7416    case XCALL_XStoreColors:
7417        StoreColors(taskData, GetDisplay(taskData, XP1),GetColormap(taskData, XP1),SAVE(P2));
7418        break;
7419
7420    case XCALL_XStoreNamedColor:
7421        StoreNamedColor(GetDisplay(taskData, XP1),
7422            GetColormap(taskData, XP1),
7423            GetString(P2),
7424            get_C_ulong(taskData, P3),
7425            get_C_ulong(taskData, P4),
7426            get_C_ulong(taskData, P5),
7427            get_C_ulong(taskData, P6));
7428        break;
7429
7430    case XCALL_BlackPixel:
7431        { Handle dsHandle /* Handle to (X_Display_Object *) */ = GetDS(taskData, XP1);
7432        return Make_arbitrary_precision(taskData, BlackPixel(DEREFDISPLAYHANDLE(dsHandle)->display,
7433            DEREFDISPLAYHANDLE(dsHandle)->screen)); }
7434
7435    case XCALL_WhitePixel:
7436        { Handle dsHandle /* Handle to (X_Display_Object *) */ = GetDS(taskData, XP1);
7437        return Make_arbitrary_precision(taskData, WhitePixel(DEREFDISPLAYHANDLE(dsHandle)->display,
7438            DEREFDISPLAYHANDLE(dsHandle)->screen)); }
7439
7440        /* Colormaps 150 */
7441    case XCALL_XCopyColormapAndFree:
7442        return EmptyColormap(taskData, GetDS(taskData, XP1),XCopyColormapAndFree(GetDisplay(taskData, XP1),GetColormap(taskData, XP1)));
7443
7444    case XCALL_XCreateColormap:
7445        return EmptyColormap(taskData, GetDS(taskData, XP1),XCreateColormap(GetDisplay(taskData, XP1),GetDrawable(taskData, XP1),GetVisual(taskData, XP2),get_C_ulong(taskData, P3)));
7446
7447    case XCALL_XInstallColormap:
7448        XInstallColormap(GetDisplay(taskData, XP1),GetColormap(taskData, XP1)); break;
7449
7450    case XCALL_XListInstalledColormaps:
7451        return ListInstalledColormaps(taskData, GetDS(taskData, XP1),GetDrawable(taskData, XP1));
7452
7453    case XCALL_XUninstallColormap:
7454        XUninstallColormap(GetDisplay(taskData, XP1),GetColormap(taskData, XP1)); break;
7455
7456    case XCALL_DefaultColormap:
7457        { Handle dsHandle /* Handle to (X_Display_Object *) */ = GetDS(taskData, XP1);
7458        return EmptyColormap(taskData, dsHandle,
7459            DefaultColormap(DEREFDISPLAYHANDLE(dsHandle)->display,
7460            DEREFDISPLAYHANDLE(dsHandle)->screen));
7461        }
7462
7463    case XCALL_DefaultVisual:
7464        { Handle dsHandle /* Handle to (X_Display_Object *) */ = GetDS(taskData, XP1);
7465        return EmptyVisual(taskData, dsHandle,
7466            DefaultVisual(DEREFDISPLAYHANDLE(dsHandle)->display,
7467            DEREFDISPLAYHANDLE(dsHandle)->screen));
7468        }
7469
7470    case XCALL_DisplayCells:
7471        { Handle dsHandle /* Handle to (X_Display_Object *) */ = GetDS(taskData, XP1);
7472        return Make_arbitrary_precision(taskData, DisplayCells(DEREFDISPLAYHANDLE(dsHandle)->display,
7473            DEREFDISPLAYHANDLE(dsHandle)->screen));
7474        }
7475
7476    case XCALL_VisualClass:
7477        return Make_arbitrary_precision(taskData, GetVisual(taskData, XP1)->c_class);
7478
7479    case XCALL_VisualRedMask:
7480        return Make_arbitrary_precision(taskData, GetVisual(taskData, XP1)->red_mask);
7481
7482    case XCALL_VisualGreenMask:
7483        return Make_arbitrary_precision(taskData, GetVisual(taskData, XP1)->green_mask);
7484
7485    case XCALL_VisualBlueMask:
7486        return Make_arbitrary_precision(taskData, GetVisual(taskData, XP1)->blue_mask);
7487
7488        /* Cursors 200 */
7489    case XCALL_XCreateFontCursor:
7490        return CreateFontCursor(taskData, GetDS(taskData, XP1),get_C_ulong(taskData, P2));
7491
7492    case XCALL_XCreateGlyphCursor:
7493        return CreateGlyphCursor(taskData, GetDS(taskData, XP1),
7494            GetFont(taskData, XP1),
7495            GetFont(taskData, XP2),
7496            get_C_ulong(taskData, P3),
7497            get_C_ulong(taskData, P4),
7498            GetXColor1(taskData, P5),
7499            GetXColor2(taskData, P6));
7500
7501    case XCALL_XCreatePixmapCursor:
7502        return CreatePixmapCursor(taskData, GetDS(taskData, XP1),
7503            GetPixmap(taskData, XP1),  /* source     */
7504            GetPixmap(taskData, XP2),  /* mask       */
7505            GetXColor1(taskData, P3), /* foreground */
7506            GetXColor2(taskData, P4), /* background */
7507            GetOffsetX(taskData, P5), /* x          */
7508            GetOffsetY(taskData, P5)  /* y          */);
7509
7510    case XCALL_XDefineCursor:
7511        XDefineCursor(GetDisplay(taskData, XP1),GetWindow(taskData, XP1),GetCursor(taskData, XP2));
7512        WindowObject(XP1)->cursor_object = CursorObject(XP2);
7513        break;
7514
7515    case XCALL_XQueryBestCursor:
7516        CheckZeroRect(taskData, P2);
7517        return QueryBest(taskData, XQueryBestCursor,
7518            GetDisplay(taskData, XP1),
7519            GetDrawable(taskData, XP1),
7520            GetRectW(taskData, P2),
7521            GetRectH(taskData, P2));
7522
7523    case XCALL_XRecolorCursor:
7524        XRecolorCursor(GetDisplay(taskData, XP1),
7525            GetCursor(taskData, XP1),
7526            GetXColor1(taskData, P2),
7527            GetXColor2(taskData, P3));
7528        break;
7529
7530    case XCALL_XUndefineCursor:
7531        XUndefineCursor(GetDisplay(taskData, XP1),GetWindow(taskData, XP1));
7532        WindowObject(XP1)->cursor_object = 0;
7533        break;
7534
7535        /* Display Specifications 250 */
7536
7537    case XCALL_XOpenDisplay:
7538        return OpenDisplay(taskData, GetString(XP1));
7539
7540#define DODISPLAYOP(op) \
7541        {\
7542        Handle dsHandle /* Handle to (X_Display_Object *) */ = GetDS(taskData, XP1);\
7543        return Make_arbitrary_precision(taskData, op(DEREFDISPLAYHANDLE(dsHandle)->display,\
7544        DEREFDISPLAYHANDLE(dsHandle)->screen));\
7545        }
7546
7547    case XCALL_CellsOfScreen:
7548        { Handle dsHandle /* Handle to (X_Display_Object *) */ = GetDS(taskData, XP1);
7549        return Make_arbitrary_precision(taskData, CellsOfScreen(ScreenOfDisplay(DEREFDISPLAYHANDLE(dsHandle)->display,
7550            DEREFDISPLAYHANDLE(dsHandle)->screen)));
7551        }
7552
7553    case XCALL_DefaultDepth:
7554        DODISPLAYOP(DefaultDepth)
7555
7556    case XCALL_DisplayHeight:
7557        DODISPLAYOP(DisplayHeight)
7558
7559    case XCALL_DisplayHeightMM:
7560        DODISPLAYOP(DisplayHeightMM)
7561
7562    case XCALL_DisplayPlanes:
7563        DODISPLAYOP(DisplayPlanes)
7564
7565    case XCALL_DisplayString:
7566        { Handle dsHandle /* Handle to (X_Display_Object *) */ = GetDS(taskData, XP1);
7567        return Make_string(DisplayString(DEREFDISPLAYHANDLE(dsHandle)->display));
7568        }
7569
7570    case XCALL_DisplayWidth:
7571        DODISPLAYOP(DisplayWidth)
7572
7573    case XCALL_DisplayWidthMM:
7574        DODISPLAYOP(DisplayWidthMM)
7575#undef DODISPLAYOP
7576
7577
7578#define DODISPLAYSCREENOP(op) \
7579        {\
7580        Handle dsHandle /* Handle to (X_Display_Object *) */ = GetDS(taskData, XP1);\
7581        return Make_arbitrary_precision(taskData, op(ScreenOfDisplay(DEREFDISPLAYHANDLE(dsHandle)->display,\
7582        DEREFDISPLAYHANDLE(dsHandle)->screen)));\
7583        }
7584
7585    case XCALL_DoesBackingStore:
7586        DODISPLAYSCREENOP(DoesBackingStore)
7587
7588    case XCALL_DoesSaveUnders:
7589        DODISPLAYSCREENOP(DoesSaveUnders)
7590
7591    case XCALL_EventMaskOfScreen:
7592        DODISPLAYSCREENOP(EventMaskOfScreen)
7593
7594    case XCALL_MaxCmapsOfScreen:
7595        DODISPLAYSCREENOP(MaxCmapsOfScreen)
7596
7597    case XCALL_MinCmapsOfScreen:
7598        DODISPLAYSCREENOP(MinCmapsOfScreen)
7599#undef DODISPLAYSCREENOP
7600
7601    case XCALL_ProtocolRevision:
7602        { Handle dsHandle /* Handle to (X_Display_Object *) */ = GetDS(taskData, XP1);
7603        return Make_arbitrary_precision(taskData, ProtocolRevision(DEREFDISPLAYHANDLE(dsHandle)->display));
7604        }
7605
7606    case XCALL_ProtocolVersion:
7607        { Handle dsHandle /* Handle to (X_Display_Object *) */ = GetDS(taskData, XP1);
7608        return Make_arbitrary_precision(taskData, ProtocolVersion(DEREFDISPLAYHANDLE(dsHandle)->display));
7609        }
7610
7611    case XCALL_ServerVendor:
7612        { Handle dsHandle /* Handle to (X_Display_Object *) */ = GetDS(taskData, XP1);
7613        return Make_string  (ServerVendor(DEREFDISPLAYHANDLE(dsHandle)->display));
7614        }
7615
7616    case XCALL_VendorRelease:
7617        { Handle dsHandle /* Handle to (X_Display_Object *) */ = GetDS(taskData, XP1);
7618        return Make_arbitrary_precision(taskData, VendorRelease(DEREFDISPLAYHANDLE(dsHandle)->display));
7619        }
7620
7621        /* Drawing Primitives 300 */
7622    case XCALL_XClearArea:
7623        XClearArea(GetDisplay(taskData, XP1),
7624            GetWindow(taskData, XP1),
7625            GetRectX(taskData, P2),
7626            GetRectY(taskData, P2),
7627            GetRectW(taskData, P2),
7628            GetRectH(taskData, P2),
7629            get_C_ulong(taskData, P3));
7630        break;
7631
7632    case XCALL_XClearWindow:
7633        XClearWindow(GetDisplay(taskData, XP1),GetWindow(taskData, XP1));
7634        break;
7635
7636    case XCALL_XCopyArea:
7637        XCopyArea(GetDisplay(taskData, XP1),
7638            GetDrawable(taskData, XP1),
7639            GetDrawable(taskData, XP2),
7640            GetGC(taskData, XP3),
7641            GetPointX(taskData, P4),
7642            GetPointY(taskData, P4),
7643            GetRectW(taskData, P5),
7644            GetRectH(taskData, P5),
7645            GetRectX(taskData, P5),
7646            GetRectY(taskData, P5));
7647        break;
7648
7649    case XCALL_XCopyPlane:
7650        XCopyPlane(GetDisplay(taskData, XP1),
7651            GetDrawable(taskData, XP1),
7652            GetDrawable(taskData, XP2),
7653            GetGC(taskData, XP3),
7654            GetPointX(taskData, P4),
7655            GetPointY(taskData, P4),
7656            GetRectW(taskData, P5),
7657            GetRectH(taskData, P5),
7658            GetRectX(taskData, P5),
7659            GetRectY(taskData, P5),
7660            get_C_ulong(taskData, P6));
7661        break;
7662
7663    case XCALL_XDrawArc:
7664        XDrawArc(GetDisplay(taskData, XP1),
7665            GetDrawable(taskData, XP1),
7666            GetGC(taskData, XP2),
7667            GetRectX(taskData, GetArcR(P3)),
7668            GetRectY(taskData, GetArcR(P3)),
7669            GetRectW(taskData, GetArcR(P3)),
7670            GetRectH(taskData, GetArcR(P3)),
7671            GetArcA1(taskData, P3),
7672            GetArcA2(taskData, P3));
7673        break;
7674
7675    case XCALL_XDrawArcs:
7676        {
7677            Handle list = SAVE(P3);
7678            if (NONNIL(DEREFWORD(list)))
7679            {
7680                unsigned  N = ListLength(DEREFWORD(list));
7681                XArc *L = (XArc *)alloca(N * sizeof(XArc));
7682                GetList4(taskData, DEREFWORD(list), L, sizeof(XArc), GetArcs);
7683                XDrawArcs(GetDisplay(taskData, XP1), GetDrawable(taskData, XP1), GetGC(taskData, XP2), L, N);
7684            }
7685        }
7686        break;
7687
7688    case XCALL_XDrawImageString:
7689        XDrawImageString(GetDisplay(taskData, XP1),
7690            GetDrawable(taskData, XP1),
7691            GetGC(taskData, XP2),
7692            GetPointX(taskData, P3),
7693            GetPointY(taskData, P3),
7694            GetString(P4)->chars,
7695            GetString(P4)->length);
7696        break;
7697
7698    case XCALL_XDrawImageString16:
7699        {
7700            Handle list = SAVE(P4);
7701            if (NONNIL(DEREFWORD(list)))
7702            {
7703                unsigned  N = ListLength(DEREFWORD(list));
7704                XChar2b *L = (XChar2b *)alloca(N * sizeof(XChar2b));
7705                GetList4(taskData, DEREFWORD(list),L, sizeof(XChar2b), GetChar2);
7706                XDrawImageString16(GetDisplay(taskData, XP1),GetDrawable(taskData, XP1),GetGC(taskData, XP2),GetPointX(taskData, P3),GetPointY(taskData, P3),L,N);
7707            }
7708        }
7709        break;
7710
7711    case XCALL_XDrawLine:
7712        XDrawLine(GetDisplay(taskData, XP1), GetDrawable(taskData, XP1), GetGC(taskData, XP2), GetPointX(taskData, P3), GetPointY(taskData, P3),
7713            GetPointX(taskData, P4), GetPointY(taskData, P4));
7714        break;
7715
7716    case XCALL_XDrawLines:
7717        {
7718            Handle list = SAVE(P3);
7719            if (NONNIL(DEREFWORD(list)))
7720            {
7721                unsigned  N = ListLength(DEREFWORD(list));
7722                XPoint *L = (XPoint *)alloca(N * sizeof(XPoint));
7723                GetList4(taskData, DEREFWORD(list), L, sizeof(XPoint), GetPoints);
7724                XDrawLines(GetDisplay(taskData, XP1), GetDrawable(taskData, XP1), GetGC(taskData, XP2), L, N, get_C_ulong(taskData, P4));
7725            }
7726        }
7727        break;
7728
7729    case XCALL_XDrawPoint:
7730        XDrawPoint(GetDisplay(taskData, XP1),
7731            GetDrawable(taskData, XP1),
7732            GetGC(taskData, XP2),
7733            GetPointX(taskData, P3),
7734            GetPointY(taskData, P3));
7735        break;
7736
7737    case XCALL_XDrawPoints:
7738        {
7739            Handle list = SAVE(P3);
7740            if (NONNIL(DEREFWORD(list)))
7741            {
7742                unsigned  N = ListLength(DEREFWORD(list));
7743                XPoint *L = (XPoint *)alloca(N * sizeof(XPoint));
7744                GetList4(taskData, DEREFWORD(list),L,sizeof(XPoint),GetPoints);
7745                XDrawPoints(GetDisplay(taskData, XP1), GetDrawable(taskData, XP1), GetGC(taskData, XP2), L, N, get_C_ulong(taskData, P4));
7746            }
7747        }
7748        break;
7749
7750    case XCALL_XDrawRectangle:
7751        XDrawRectangle(GetDisplay(taskData, XP1),
7752            GetDrawable(taskData, XP1),
7753            GetGC(taskData, XP2),
7754            GetRectX(taskData, P3),
7755            GetRectY(taskData, P3),
7756            GetRectW(taskData, P3),
7757            GetRectH(taskData, P3));
7758        break;
7759
7760    case XCALL_XDrawRectangles:
7761        {
7762            Handle list = SAVE(P3);
7763            if (NONNIL(DEREFWORD(list)))
7764            {
7765                unsigned  N = ListLength(DEREFWORD(list));
7766                XRectangle *L = (XRectangle *)alloca(N * sizeof(XRectangle));
7767                GetList4(taskData, DEREFWORD(list),L,sizeof(XRectangle),GetRects);
7768                XDrawRectangles(GetDisplay(taskData, XP1),GetDrawable(taskData, XP1),GetGC(taskData, XP2),L,N);
7769            }
7770        }
7771        break;
7772
7773    case XCALL_XDrawSegments:
7774        {
7775            Handle list = SAVE(P3);
7776            if (NONNIL(DEREFWORD(list)))
7777            {
7778                unsigned  N = ListLength(DEREFWORD(list));
7779                XSegment *L = (XSegment *)alloca(N * sizeof(XSegment));
7780                GetList4(taskData, DEREFWORD(list),L,sizeof(XSegment),GetSegments);
7781                XDrawSegments(GetDisplay(taskData, XP1),GetDrawable(taskData, XP1),GetGC(taskData, XP2),L,N);
7782            }
7783        }
7784        break;
7785
7786    case XCALL_XDrawString:
7787        XDrawString(GetDisplay(taskData, XP1),
7788            GetDrawable(taskData, XP1),
7789            GetGC(taskData, XP2),
7790            GetPointX(taskData, P3),
7791            GetPointY(taskData, P3),
7792            GetString(P4)->chars,
7793            GetString(P4)->length);
7794        break;
7795
7796    case XCALL_XDrawString16:
7797        {
7798            Handle list = SAVE(P4);
7799            if (NONNIL(DEREFWORD(list)))
7800            {
7801                unsigned  N = ListLength(DEREFWORD(list));
7802                XChar2b *L = (XChar2b *)alloca(N * sizeof(XChar2b));
7803
7804                GetList4(taskData, DEREFWORD(list),L,sizeof(XChar2b),GetChar2);
7805
7806                XDrawString16(GetDisplay(taskData, XP1),GetDrawable(taskData, XP1),GetGC(taskData, XP2),GetPointX(taskData, P3),GetPointY(taskData, P3),L,N);
7807            }
7808        }
7809        break;
7810
7811    case XCALL_XDrawText:
7812        {
7813            Handle list = SAVE(P4);
7814            if (NONNIL(DEREFWORD(list)))
7815            {
7816                unsigned  N = ListLength(DEREFWORD(list));
7817                XTextItem *L = (XTextItem *)alloca(N * sizeof(XTextItem));
7818
7819                GetList4(taskData, DEREFWORD(list),L,sizeof(XTextItem),GetText);
7820                XDrawText(GetDisplay(taskData, XP1),GetDrawable(taskData, XP1),GetGC(taskData, XP2),GetPointX(taskData, P3),GetPointY(taskData, P3),L,N);
7821
7822                while (N--) { free(L->chars); L++; }
7823            }
7824        }
7825        break;
7826
7827    case XCALL_XDrawText16:
7828        {
7829            Handle list = SAVE(P4);
7830            if (NONNIL(DEREFWORD(list)))
7831            {
7832                unsigned  N = ListLength(DEREFWORD(list));
7833                XTextItem16 *L = (XTextItem16 *)alloca(N * sizeof(XTextItem16));
7834                GetList4(taskData, DEREFWORD(list),L,sizeof(XTextItem16), GetText16);
7835                XDrawText16(GetDisplay(taskData, XP1),GetDrawable(taskData, XP1),GetGC(taskData, XP2),GetPointX(taskData, P3),GetPointY(taskData, P3),L,N);
7836
7837                while (N--) { free(L->chars); L++; }
7838            }
7839        }
7840        break;
7841
7842    case XCALL_XFillArc:
7843        XFillArc(GetDisplay(taskData, XP1),
7844            GetDrawable(taskData, XP1),
7845            GetGC(taskData, XP2),
7846            GetRectX(taskData, GetArcR(P3)),
7847            GetRectY(taskData, GetArcR(P3)),
7848            GetRectW(taskData, GetArcR(P3)),
7849            GetRectH(taskData, GetArcR(P3)),
7850            GetArcA1(taskData, P3),
7851            GetArcA2(taskData, P3));
7852        break;
7853
7854    case XCALL_XFillArcs:
7855        {
7856            Handle list = SAVE(P3);
7857            if (NONNIL(DEREFWORD(list)))
7858            {
7859                unsigned  N = ListLength(DEREFWORD(list));
7860                XArc *L = (XArc *)alloca(N * sizeof(XArc));
7861
7862                GetList4(taskData, DEREFWORD(list),L,sizeof(XArc),GetArcs);
7863
7864                XFillArcs(GetDisplay(taskData, XP1),GetDrawable(taskData, XP1),GetGC(taskData, XP2),L,N);
7865            }
7866        }
7867        break;
7868
7869    case XCALL_XFillPolygon:
7870        {
7871            Handle list = SAVE(P3);
7872            if (NONNIL(DEREFWORD(list)))
7873            {
7874                unsigned  N = ListLength(DEREFWORD(list));
7875                XPoint *L = (XPoint *)alloca(N * sizeof(XPoint));
7876
7877                GetList4(taskData, DEREFWORD(list),L,sizeof(XPoint),GetPoints);
7878
7879                XFillPolygon(GetDisplay(taskData, XP1),GetDrawable(taskData, XP1),GetGC(taskData, XP2),L,N,get_C_ulong(taskData, P4),get_C_ulong(taskData, P5));
7880            }
7881        }
7882        break;
7883
7884    case XCALL_XFillRectangle:
7885        XFillRectangle(GetDisplay(taskData, XP1),
7886            GetDrawable(taskData, XP1),
7887            GetGC(taskData, XP2),
7888            GetRectX(taskData, P3),
7889            GetRectY(taskData, P3),
7890            GetRectW(taskData, P3),
7891            GetRectH(taskData, P3));
7892        break;
7893
7894    case XCALL_XFillRectangles:
7895        {
7896            Handle list = SAVE(P3);
7897            if (NONNIL(DEREFWORD(list)))
7898            {
7899                unsigned  N = ListLength(DEREFWORD(list));
7900                XRectangle *L = (XRectangle *)alloca(N * sizeof(XRectangle));
7901                GetList4(taskData, DEREFWORD(list),L,sizeof(XRectangle),GetRects);
7902                XFillRectangles(GetDisplay(taskData, XP1),GetDrawable(taskData, XP1),GetGC(taskData, XP2),L,N);
7903            }
7904        }
7905        break;
7906
7907        /* Events 350 */
7908
7909    case XCALL_XSelectInput:
7910        (WindowObject(XP1))->eventMask->Set(0, PolyWord::FromUnsigned(get_C_ulong(taskData, P2)));
7911        XSelectInput(GetDisplay(taskData, XP1),GetWindow(taskData, XP1),XMASK((WindowObject(XP1))->eventMask->Get(0).AsUnsigned()));
7912        break;
7913
7914    case XCALL_XSynchronize:
7915        XSynchronize(GetDisplay(taskData, XP1),get_C_ulong(taskData, P2));
7916        break;
7917
7918    case XCALL_GetState:
7919        return GetState(taskData, WindowObject(XP1)); /* WindowObject added SPF */
7920
7921    case XCALL_SetState:
7922        SetState(WindowObject(XP1),P2,P3); /* WindowObject added SPF */
7923        break;
7924
7925    case XCALL_NextEvent:
7926        return NextEvent(taskData, GetDS(taskData, XP1));
7927
7928    case XCALL_InsertTimeout:
7929        InsertTimeout(taskData, WindowObject(XP1),get_C_ulong(taskData, P2),P3,P4); /* WindowObject added SPF */
7930        break;
7931
7932    case XCALL_XSetInputFocus:
7933        XSetInputFocus(GetDisplay(taskData, XP1),GetWindow(taskData, XP2),get_C_ulong(taskData, P3),get_C_ulong(taskData, P4));
7934        break;
7935
7936    case XCALL_XGetInputFocus:
7937        return GetInputFocus(taskData, GetDS(taskData, XP1));
7938
7939    case XCALL_XSetSelectionOwner:
7940        SetSelectionOwner(GetDS(taskData, XP1),get_C_ulong(taskData, P2),GetWindow(taskData, XP3),get_C_ulong(taskData, P4));
7941        break;
7942
7943    case XCALL_XGetSelectionOwner:
7944        { Handle dsHandle /* Handle to (X_Display_Object *) */ = GetDS(taskData, XP1);
7945        return EmptyWindow(taskData, dsHandle,XGetSelectionOwner(DEREFDISPLAYHANDLE(dsHandle)->display,
7946            get_C_ulong(taskData, P2)));
7947        }
7948
7949    case XCALL_XConvertSelection:
7950        XConvertSelection(GetDisplay(taskData, XP4),
7951            get_C_ulong(taskData, P1),
7952            get_C_ulong(taskData, P2),
7953            get_C_ulong(taskData, P3),
7954            GetWindow(taskData, XP4),
7955            get_C_ulong(taskData, P5));
7956        break;
7957
7958    case XCALL_XSendSelectionNotify:
7959        SendSelectionNotify(GetDisplay(taskData, XP4),
7960            get_C_ulong(taskData, P1),
7961            get_C_ulong(taskData, P2),
7962            get_C_ulong(taskData, P3),
7963            GetWindow(taskData, XP4),
7964            get_C_ulong(taskData, P5));
7965        break;
7966
7967    case XCALL_XDeleteProperty:
7968        XDeleteProperty(GetDisplay(taskData, XP1),GetWindow(taskData, XP1),get_C_ulong(taskData, P2));
7969        break;
7970
7971    case XCALL_XInternAtom:
7972        return InternAtom(taskData, GetDisplay(taskData, XP1),GetString(P2),get_C_long(taskData, P3));
7973
7974    case XCALL_XGetAtomName:
7975        return GetAtomName(taskData, GetDisplay(taskData, XP1),get_C_ulong(taskData, P2));
7976
7977        /* Fonts 400 */
7978
7979    case XCALL_XGetFontPath:
7980        return GetFontPath(taskData, GetDisplay(taskData, XP1));
7981
7982    case XCALL_XListFonts:
7983        return ListFonts(taskData, GetDisplay(taskData, XP1),GetString(P2),get_C_ulong(taskData, P3));
7984
7985    case XCALL_XListFontsWithInfo:
7986        return ListFontsWithInfo(taskData, GetDS(taskData, XP1),GetString(P2),get_C_ulong(taskData, P3));
7987
7988    case XCALL_XLoadFont:
7989        return LoadFont(taskData, GetDS(taskData, XP1),GetString(P2));
7990
7991    case XCALL_XLoadQueryFont:
7992        return LoadQueryFont(taskData, GetDS(taskData, XP1),GetString(P2));
7993
7994    case XCALL_XQueryFont:
7995        return QueryFont(taskData, GetDS(taskData, XP1),GetFont(taskData, XP1));
7996
7997    case XCALL_XSetFontPath:
7998        SetFontPath(taskData, GetDisplay(taskData, XP1),SAVE(P2));
7999        break;
8000
8001        /* Grabbing 450 */
8002
8003        /* Graphics Context 500 */
8004
8005    case XCALL_DefaultGC:
8006        return GetDefaultGC(taskData, GetDS(taskData, XP1));
8007
8008    case XCALL_UpdateGC:
8009        ChangeGC(taskData, GCObject(XP1),get_C_ulong(taskData, P2),P3);
8010        break;
8011
8012    case XCALL_XCreateGC:
8013        return CreateGC(taskData, GetDS(taskData, XP1),GetDrawable(taskData, XP1));
8014
8015    case XCALL_XSetClipRectangles:
8016        SetClipRectangles(taskData, GetDisplay(taskData, XP1),
8017            GetGC(taskData, XP1),
8018            GetPointX(taskData, P2),
8019            GetPointY(taskData, P2),
8020            SAVE(P3),
8021            get_C_ulong(taskData, P4));
8022        break;
8023
8024    case XCALL_XSetDashes:
8025        SetDashes(taskData, GetDisplay(taskData, XP1),
8026            GetGC(taskData, XP1),
8027            get_C_ulong(taskData, P2),
8028            SAVE(P3));
8029        break;
8030
8031        /* Images 550 */
8032
8033    case XCALL_XAddPixel:
8034        AddPixel(GetXImage(taskData, GetDisplay(taskData, XP1),P2),get_C_ulong(taskData, P3));
8035        break;
8036
8037    case XCALL_XGetImage:
8038        return GetImage(taskData, GetDisplay(taskData, XP1),
8039            GetDrawable(taskData, XP1),
8040            GetRectX(taskData, P2),
8041            GetRectY(taskData, P2),
8042            GetRectW(taskData, P2),
8043            GetRectH(taskData, P2),
8044            get_C_ulong(taskData, P3),
8045            get_C_long(taskData, P4));
8046
8047    case XCALL_XGetPixel:
8048        return GetPixel(taskData, GetXImage(taskData, GetDisplay(taskData, XP1),P2),
8049            GetPointX(taskData, P3),
8050            GetPointY(taskData, P3));
8051
8052    case XCALL_XGetSubImage:
8053        GetSubImage(GetDisplay(taskData, XP1),
8054            GetDrawable(taskData, XP1),
8055            GetRectX(taskData, P2),
8056            GetRectY(taskData, P2),
8057            GetRectW(taskData, P2),
8058            GetRectH(taskData, P2),
8059            get_C_ulong(taskData, P3),
8060            get_C_long(taskData, P4),
8061            GetXImage(taskData, GetDisplay(taskData, XP1),P5),
8062            GetPointX(taskData, P6),
8063            GetPointY(taskData, P6));
8064        break;
8065
8066    case XCALL_XPutImage:
8067        PutImage(GetDisplay(taskData, XP1),
8068            GetDrawable(taskData, XP1),
8069            GetGC(taskData, XP2),
8070            GetXImage(taskData, GetDisplay(taskData, XP1),P3),
8071            GetPointX(taskData, P4),
8072            GetPointY(taskData, P4),
8073            GetRectX(taskData, P5),
8074            GetRectY(taskData, P5),
8075            GetRectW(taskData, P5),
8076            GetRectH(taskData, P5));
8077        break;
8078
8079    case XCALL_XPutPixel:
8080        PutPixel(GetXImage(taskData, GetDisplay(taskData, XP1),P2),
8081            GetPointX(taskData, P3),
8082            GetPointY(taskData, P3),
8083            get_C_ulong(taskData, P4));
8084        break;
8085
8086    case XCALL_XSubImage:
8087        return SubImage(taskData, GetXImage(taskData, GetDisplay(taskData, XP1),P2),
8088            GetRectX(taskData, P3),
8089            GetRectY(taskData, P3),
8090            GetRectW(taskData, P3),
8091            GetRectH(taskData, P3));
8092
8093    case XCALL_BitmapBitOrder:
8094        return Make_arbitrary_precision(taskData, MLImageOrder(BitmapBitOrder(GetDisplay(taskData, XP1))));
8095
8096    case XCALL_BitmapPad:
8097        return Make_arbitrary_precision(taskData, BitmapPad(GetDisplay(taskData, XP1)));
8098
8099    case XCALL_BitmapUnit:
8100        return Make_arbitrary_precision(taskData, BitmapUnit(GetDisplay(taskData, XP1)));
8101
8102    case XCALL_ByteOrder:
8103        return Make_arbitrary_precision(taskData, MLImageOrder(ImageByteOrder(GetDisplay(taskData, XP1))));
8104
8105        /* Keyboard 600 */
8106    case XCALL_XLookupString:
8107        return LookupString(taskData, GetDisplay(taskData, XP1),get_C_ulong(taskData, P2),get_C_ulong(taskData, P3));
8108
8109    case XCALL_XQueryKeymap:
8110        return QueryKeymap(taskData, GetDisplay(taskData, XP1));
8111
8112    case XCALL_IsCursorKey:
8113        return Make_bool(IsCursorKey(get_C_ulong(taskData, P1)));
8114
8115    case XCALL_IsFunctionKey:
8116        return Make_bool(IsFunctionKey(get_C_ulong(taskData, P1)));
8117
8118    case XCALL_IsKeypadKey:
8119        return Make_bool(IsKeypadKey(get_C_ulong(taskData, P1)));
8120
8121    case XCALL_IsMiscFunctionKey:
8122        return Make_bool(IsMiscFunctionKey(get_C_ulong(taskData, P1)));
8123
8124    case XCALL_IsModifierKey:
8125        return Make_bool(IsModifierKey(get_C_ulong(taskData, P1)));
8126
8127    case XCALL_IsPFKey:
8128        return Make_bool(IsPFKey(get_C_ulong(taskData, P1)));
8129
8130        /* Output Buffer 650 */
8131    case XCALL_XFlush:
8132        XFlush(GetDisplay(taskData, XP1));
8133        break;
8134
8135    case XCALL_XSync:
8136        XSync(GetDisplay(taskData, XP1),get_C_ulong(taskData, P2));
8137        break;
8138
8139        /* Pointers 700 */
8140    case XCALL_XQueryPointer:
8141        return QueryPointer(taskData, GetDS(taskData, XP1),GetWindow(taskData, XP1));
8142
8143        /* Regions 750*/
8144
8145        /* SAVE Set 800 */
8146
8147        /* Screen Saver 850 */
8148    case XCALL_XActivateScreenSaver:
8149        XActivateScreenSaver(GetDisplay(taskData, XP1));
8150        break;
8151
8152    case XCALL_XForceScreenSaver:
8153        XForceScreenSaver(GetDisplay(taskData, XP1),get_C_ulong(taskData, P2));
8154        break;
8155
8156    case XCALL_XGetScreenSaver:
8157        return GetScreenSaver(taskData, GetDisplay(taskData, XP1));
8158
8159    case XCALL_XResetScreenSaver:
8160        XResetScreenSaver(GetDisplay(taskData, XP1));
8161        break;
8162
8163    case XCALL_XSetScreenSaver:
8164        XSetScreenSaver(GetDisplay(taskData, XP1),
8165            get_C_long(taskData, P2),
8166            get_C_long(taskData, P3),
8167            get_C_ulong(taskData, P4),
8168            get_C_ulong(taskData, P5));
8169        break;
8170
8171        /* Standard Geometry 900 */
8172    case XCALL_XTranslateCoordinates:
8173        return TranslateCoordinates(taskData, GetDS(taskData, XP1),
8174            GetWindow(taskData, XP1),
8175            GetWindow(taskData, XP2),
8176            GetPointX(taskData, P3),
8177            GetPointY(taskData, P3));
8178
8179        /* Text 950 */
8180    case XCALL_XTextExtents:
8181        return TextExtents(taskData, GetFontStruct(taskData, P1),GetString(P2));
8182
8183    case XCALL_XTextExtents16:
8184        return TextExtents16(taskData, GetFontStruct(taskData, P1),SAVE(P2));
8185
8186    case XCALL_XTextWidth:
8187        return TextWidth(taskData, GetFontStruct(taskData, P1),GetString(P2));
8188
8189    case XCALL_XTextWidth16:
8190        return TextWidth16(taskData, GetFontStruct(taskData, P1),SAVE(P2));
8191
8192        /* Tiles, Pixmaps, Stipples and Bitmaps 1000 */
8193    case XCALL_XCreateBitmapFromData:
8194        {
8195            Handle dsHandle /* Handle to (X_Display_Object *) */ = GetDS(taskData, XP1);
8196            CheckZeroRect(taskData, P3);
8197            return EmptyPixmap(taskData, dsHandle,
8198                XCreateBitmapFromData(
8199                DEREFDISPLAYHANDLE(dsHandle)->display,
8200                GetDrawable(taskData, XP1),     /* drawable */
8201                GetString(P2)->chars, /* data     */
8202                GetRectW(taskData, P3),         /* width    */
8203                GetRectH(taskData, P3)));       /* height   */
8204        }
8205
8206    case XCALL_XCreatePixmap:
8207        {
8208            Handle dsHandle /* Handle to (X_Display_Object *) */ = GetDS(taskData, XP1);
8209            CheckZeroRect(taskData, P2);
8210            return EmptyPixmap(taskData, dsHandle,
8211                XCreatePixmap(
8212                DEREFDISPLAYHANDLE(dsHandle)->display,
8213                GetDrawable(taskData, XP1),  /* drawable */
8214                GetRectW(taskData, P2),      /* width    */
8215                GetRectH(taskData, P2),      /* height   */
8216                get_C_ulong(taskData, P3))); /* depth    */
8217        }
8218
8219    case XCALL_XCreatePixmapFromBitmapData:
8220        {
8221            Handle dsHandle /* Handle to (X_Display_Object *) */ = GetDS(taskData, XP1);
8222            CheckZeroRect(taskData, P3);
8223
8224            return EmptyPixmap(taskData, dsHandle,
8225                XCreatePixmapFromBitmapData(
8226                DEREFDISPLAYHANDLE(dsHandle)->display,
8227                GetDrawable(taskData, XP1),     /* drawable */
8228                GetString(P2)->chars, /* data     */
8229                GetRectW(taskData, P3),         /* width    */
8230                GetRectH(taskData, P3),         /* height   */
8231                get_C_ulong(taskData, P4),      /* foreground */
8232                get_C_ulong(taskData, P5),      /* background */
8233                get_C_ulong(taskData, P6)));    /* depth    */
8234        }
8235
8236    case XCALL_XQueryBestStipple:
8237        CheckZeroRect(taskData, P2);
8238        return QueryBest(taskData, XQueryBestStipple,
8239            GetDisplay(taskData, XP1),
8240            GetDrawable(taskData, XP1),
8241            GetRectW(taskData, P2),
8242            GetRectH(taskData, P2));
8243
8244    case XCALL_XQueryBestTile:
8245        CheckZeroRect(taskData, P2);
8246        return QueryBest(taskData, XQueryBestTile,
8247            GetDisplay(taskData, XP1),
8248            GetDrawable(taskData, XP1),
8249            GetRectW(taskData, P2),
8250            GetRectH(taskData, P2));
8251
8252    case XCALL_XReadBitmapFile:
8253        return ReadBitmap(taskData, GetDS(taskData, XP1),GetDrawable(taskData, XP1),GetString(P2));
8254
8255    case XCALL_XWriteBitmapFile:
8256        CheckZeroRect(taskData, P3);
8257        return WriteBitmapFile(taskData, GetString(XP1),
8258            GetDisplay(taskData, XP2),
8259            GetPixmap(taskData, XP2),
8260            GetRectW(taskData, P3),
8261            GetRectH(taskData, P3),
8262            GetPointX(taskData, P4),
8263            GetPointY(taskData, P4));
8264
8265        /* User Preferences 1050 */
8266    case XCALL_XAutoRepeatOff:
8267        XAutoRepeatOff(GetDisplay(taskData, XP1));
8268        break;
8269
8270    case XCALL_XAutoRepeatOn:
8271        XAutoRepeatOn (GetDisplay(taskData, XP1));
8272        break;
8273
8274    case XCALL_XBell:
8275        XBell(GetDisplay(taskData, XP1),get_C_short(taskData, P2));
8276        break;
8277
8278    case XCALL_XGetDefault:
8279        return GetDefault(taskData, GetDisplay(taskData, XP1),GetString(P2),GetString(P3));
8280
8281        /* Window Attributes 1100 */
8282    case XCALL_ChangeWindow:
8283        ChangeWindowAttributes(taskData, WindowObject(XP1),get_C_ulong(taskData, P2),P3);
8284        break;
8285
8286    case XCALL_XGetGeometry:
8287        return GetGeometry(taskData, GetDS(taskData, XP1),GetDrawable(taskData, XP1));
8288
8289    case XCALL_XGetWindowAttributes:
8290        return GetWindowAttributes(taskData, GetDS(taskData, XP1),GetDrawable(taskData, XP1));
8291
8292    case XCALL_XSetWindowBorderWidth:
8293        XSetWindowBorderWidth(GetDisplay(taskData, XP1),GetWindow(taskData, XP1),get_C_ulong(taskData, P2));
8294        break;
8295
8296        /* Window Configuration 1150 */
8297    case XCALL_XCirculateSubwindows:
8298        XCirculateSubwindows(GetDisplay(taskData, XP1),GetWindow(taskData, XP1),get_C_ulong(taskData, P2));
8299        break;
8300
8301    case XCALL_XConfigureWindow:
8302        ConfigureWindow(taskData, GetDisplay(taskData, XP1),GetWindow(taskData, XP1), P2);
8303        break;
8304
8305    case XCALL_XLowerWindow:
8306        XLowerWindow(GetDisplay(taskData, XP1),GetWindow(taskData, XP1));
8307        break;
8308
8309    case XCALL_XMapRaised:
8310        XMapRaised(GetDisplay(taskData, XP1),GetWindow(taskData, XP1));
8311        break;
8312
8313    case XCALL_XMapSubwindows:
8314        XMapSubwindows(GetDisplay(taskData, XP1),GetWindow(taskData, XP1));
8315        break;
8316
8317    case XCALL_XMapWindow:
8318        XMapWindow(GetDisplay(taskData, XP1),GetWindow(taskData, XP1));
8319        break;
8320
8321    case XCALL_XMoveResizeWindow:
8322        CheckZeroRect(taskData, P3);
8323        XMoveResizeWindow(GetDisplay(taskData, XP1),
8324            GetWindow(taskData, XP1),
8325            GetPointX(taskData, P2),
8326            GetPointY(taskData, P2),
8327            GetRectW(taskData, P3),
8328            GetRectH(taskData, P3));
8329        break;
8330
8331    case XCALL_XMoveWindow:
8332        XMoveWindow(GetDisplay(taskData, XP1),
8333            GetWindow(taskData, XP1),
8334            GetPointX(taskData, P2),
8335            GetPointY(taskData, P2));
8336        break;
8337
8338    case XCALL_XQueryTree:
8339        return QueryTree(taskData,GetDS(taskData, XP1),GetWindow(taskData, XP1));
8340
8341    case XCALL_XRaiseWindow:
8342        XRaiseWindow(GetDisplay(taskData, XP1),GetWindow(taskData, XP1));
8343        break;
8344
8345    case XCALL_XReparentWindow:
8346        XReparentWindow(GetDisplay(taskData, XP1),
8347            GetWindow(taskData, XP1),
8348            GetWindow(taskData, XP2),
8349            GetPointX(taskData, P3),
8350            GetPointY(taskData, P3));
8351        break;
8352
8353    case XCALL_XResizeWindow:
8354        CheckZeroRect(taskData, P2);
8355        XResizeWindow(GetDisplay(taskData, XP1),
8356            GetWindow(taskData, XP1),
8357            GetRectW(taskData, P2),
8358            GetRectH(taskData, P2));
8359        break;
8360
8361    case XCALL_XRestackWindows:
8362        RestackWindows(taskData, SAVE(P1));
8363        break;
8364
8365    case XCALL_XUnmapSubwindows:
8366        XUnmapSubwindows(GetDisplay(taskData, XP1),GetWindow(taskData, XP1));
8367        break;
8368
8369    case XCALL_XUnmapWindow:
8370        XUnmapWindow(GetDisplay(taskData, XP1),GetWindow(taskData, XP1));
8371        break;
8372
8373        /* Window Existence 1200 */
8374    case XCALL_RootWindow:
8375        { Handle dsHandle /* Handle to (X_Display_Object *) */ = GetDS(taskData, XP1);
8376        return EmptyWindow(taskData, dsHandle,
8377            RootWindow(DEREFDISPLAYHANDLE(dsHandle)->display,
8378            DEREFDISPLAYHANDLE(dsHandle)->screen));
8379        }
8380
8381    case XCALL_DestroyXObject:
8382        DestroyXObject(XP1);
8383        break;
8384
8385    case XCALL_XDestroySubwindows:
8386        DestroySubwindows(XP1);
8387        break;
8388
8389    case XCALL_XCreateSimpleWindow:
8390        CheckZeroRect(taskData, P3);
8391        return CreateSimpleWindow(taskData,
8392            SAVE(XP1),       /* parent      */
8393            GetPointX(taskData, P2),   /* x           */
8394            GetPointY(taskData, P2),   /* y           */
8395            GetRectW(taskData, P3),    /* w           */
8396            GetRectH(taskData, P3),    /* h           */
8397            get_C_ulong(taskData, P4), /* borderWidth */
8398            get_C_ulong(taskData, P5), /* border      */
8399            get_C_ulong(taskData, P6), /* background  */
8400            SAVE(P7),        /* handler     */
8401            SAVE(P8));       /* state       */
8402
8403    case XCALL_XCreateWindow:
8404        CheckZeroRect(taskData, P3);
8405        return CreateWindow(taskData,
8406            SAVE(XP1),       /* parent      */
8407            GetPointX(taskData, P2),   /* x           */
8408            GetPointY(taskData, P2),   /* y           */
8409            GetRectW(taskData, P3),    /* w           */
8410            GetRectH(taskData, P3),    /* h           */
8411            get_C_ulong(taskData, P4), /* borderWidth */
8412            get_C_ulong(taskData, P5), /* depth       */
8413            get_C_ulong(taskData, P6), /* class       */
8414            GetVisual(taskData, XP7),  /* visual      */
8415            SAVE(P8),        /* handler     */
8416            SAVE(P9));       /* state       */
8417
8418        /* Window Manager 1250 */
8419    case XCALL_XSetProperty:
8420        SetProperty(taskData, GetDisplay(taskData, XP1),
8421            GetWindow(taskData, XP1),
8422            get_C_ulong(taskData, P2),
8423            get_C_ulong(taskData, P3),
8424            SAVE(P4),
8425            get_C_ulong(taskData, P5));
8426        break;
8427
8428    case XCALL_XGetTextProperty:
8429        return GetTextProperty(taskData, GetDisplay(taskData, XP1),GetWindow(taskData, XP1),get_C_ulong(taskData, P2));
8430
8431    case XCALL_XGetWMHints:
8432        return GetWMHints(taskData, GetDS(taskData, XP1),GetWindow(taskData, XP1));
8433
8434    case XCALL_XGetWMSizeHints:
8435        return GetWMSizeHints(taskData, GetDisplay(taskData, XP1),GetWindow(taskData, XP1),get_C_ulong(taskData, P2));
8436
8437    case XCALL_XGetIconSizes:
8438        return GetIconSizes(taskData, GetDisplay(taskData, XP1),GetWindow(taskData, XP1));
8439
8440    case XCALL_XGetTransientForHint:
8441        return GetTransientForHint(taskData, GetDS(taskData, XP1),GetWindow(taskData, XP1));
8442
8443    case XCALL_XGetWMColormapWindows:
8444        return GetWMColormapWindows(taskData, GetDS(taskData, XP1),GetWindow(taskData, XP1));
8445
8446    case XCALL_XGetRGBColormaps:
8447        return GetRGBColormaps(taskData, GetDS(taskData, XP1),GetWindow(taskData, XP1),get_C_ulong(taskData, P2));
8448
8449    case XCALL_XWMGeometry:
8450        return WMGeometry(taskData, GetDS(taskData, XP1),
8451            GetString(P2),
8452            GetString(P3),
8453            get_C_ulong(taskData, P4),
8454            P5);
8455
8456        /* Miscellaneous 1300 */
8457    case XCALL_GetID:
8458        return GetID(taskData, XP1);
8459
8460    case XCALL_ResourceExists:
8461        return Make_bool(ResourceExists(XP1));
8462
8463    case XCALL_GetDisplay:
8464        return GetDS(taskData, XP1);
8465
8466        /******************************************************************************/
8467        /*                                                                            */
8468        /*      Xt Calls                                                              */
8469        /*                                                                            */
8470        /******************************************************************************/
8471    case XCALL_NoWidget:
8472        return EmptyWidget(taskData, SAVE(ListNull), (Widget)NULL);
8473
8474    case XCALL_AppInitialise:
8475        return AppInitialise(taskData, P1, /* display name      */
8476            P2, /* application name  */
8477            P3, /* application class */
8478            SAVE(P4),     /* Fallback list     */
8479            SAVE(P5)      /* Arg list          */);
8480
8481    case XCALL_XtRealizeWidget:
8482        XtRealizeWidget(GetWidget(taskData, XP1));
8483        break;
8484
8485    case XCALL_XtManageChildren:
8486        ManageChildren(taskData, SAVE(P1));
8487        break;
8488
8489    case XCALL_XtUnmanageChildren:
8490        UnmanageChildren(taskData, SAVE(P1));
8491        break;
8492
8493    case XCALL_XtDestroyWidget:
8494        {
8495            Widget w = GetWidget(taskData, XP1);
8496            XtDestroyWidget(w);
8497            /* The following test seems necessary - sometimes the callback from  */
8498            /* the above call destroys the widget, sometimes it doesn't. I think */
8499            /* it always should, and I can't work out why this strange behaviour */
8500            /* occurs.                                               SPF 9/12/93 */
8501            if (ResourceExists(XP1))
8502            {
8503                DestroyXObject(XP1);
8504                PurgeCCallbacks((X_Widget_Object *)XP1,w);
8505            }
8506            break;
8507        }
8508
8509    case XCALL_SetCallbacks:
8510        SetCallbacks (taskData, WidgetObject(taskData, XP1),P2,P3);
8511        break; /* WidgetObject added SPF */
8512
8513    case XCALL_XtSetValues:
8514        SetValues(taskData, GetWidget(taskData, XP1),SAVE(P2));
8515        break;
8516
8517    case XCALL_GetValue:
8518        return GetValue(taskData, GetDS(taskData, XP1),GetWidget(taskData, XP1),P2);
8519
8520    case XCALL_XtParent:
8521        return EmptyWidget(taskData, GetDS(taskData, XP1),XtParent(GetWidget(taskData, XP1)));
8522
8523    case XCALL_XtWindow:
8524        return EmptyWindow(taskData, GetDS(taskData, XP1),WindowOfWidget(GetWidget(taskData, XP1)));
8525
8526    case XCALL_XtDisplay:
8527        return GetDS(taskData, XP1);
8528
8529    case XCALL_XtUnrealizeWidget:
8530        XtUnrealizeWidget(GetWidget(taskData, XP1)); break;
8531
8532    case XCALL_XtName:
8533        return Make_string(XtName(GetWidget(taskData, XP1)));
8534
8535    case XCALL_XtParseTranslationTable:
8536        return ParseTranslationTable(taskData, GetString(XP1));
8537
8538    case XCALL_XtOverrideTranslations:
8539        XtOverrideTranslations(GetWidget(taskData, XP1),GetTrans(taskData, XP2));
8540        break;
8541
8542    case XCALL_XtAugmentTranslations:
8543        XtAugmentTranslations(GetWidget(taskData, XP1),GetTrans(taskData, XP2));
8544        break;
8545
8546    case XCALL_XtUninstallTranslations: XtUninstallTranslations(GetWidget(taskData, XP1)); break;
8547
8548    /*
8549    case XCALL_XtTranslateTablePrint: _XtTranslateTablePrint(GetTrans(taskData, XP1)); break;
8550        */
8551
8552    case XCALL_XtCreatePopupShell:
8553        return CreatePopupShell(taskData, GetString(XP1),GetDS(taskData, XP2),GetWidget(taskData, XP2),SAVE(P3));
8554
8555    case XCALL_InsertWidgetTimeout:
8556        InsertWidgetTimeout(taskData, WidgetObject(taskData, XP1),get_C_ulong(taskData, P2),P3,P4);
8557        break; /* WidgetObject added SPF */
8558
8559    case XCALL_GetWidgetState:
8560        return SAVE(WidgetObjectToken(XP1)->state); /* was WidgetObject(XP1) (SPF) */
8561
8562    case XCALL_SetWidgetState:
8563        WidgetObjectToken(XP1)->state = P2;
8564        break;  /* was WidgetObject(XP1) (SPF) */
8565
8566    case XCALL_XtSetSensitive:
8567        XtSetSensitive(GetWidget(taskData, XP1),get_C_ulong(taskData, P2));
8568        break;
8569
8570    case XCALL_XtIsSensitive:
8571        return Make_bool(XtIsSensitive(GetWidget(taskData, XP1)));
8572
8573    case XCALL_GetSubresources:
8574        return GetSubresources(taskData, GetDS(taskData, XP1),
8575            GetWidget(taskData, XP1),
8576            GetString(P2),
8577            GetString(P3),
8578            SAVE(P4));
8579
8580    case XCALL_Cast:
8581        return SAVE(P1);
8582
8583    case XCALL_XtPopup:
8584        XtPopup(GetWidget(taskData, XP1),GetXtGrabKind(taskData, P2));
8585        break;
8586
8587    case XCALL_XtPopdown:
8588        XtPopdown(GetWidget(taskData, XP1));
8589        break;
8590
8591    case XCALL_XtMapWidget:
8592        XtMapWidget(GetRealizedWidget(taskData, (char *) "XtMapWidget",XP1));
8593        break;
8594
8595    case XCALL_XtUnmapWidget:
8596        XtUnmapWidget(GetRealizedWidget(taskData, (char *) "XtUnmapWidget",XP1));
8597        break;
8598
8599    case XCALL_XtIsManaged:
8600        return Make_bool(XtIsManaged(GetWidget(taskData, XP1)));
8601
8602    case XCALL_XtIsRealized:
8603        return Make_bool(XtIsRealized(GetWidget(taskData, XP1)));
8604
8605        /* Added DCJM. */
8606    case XCALL_XtGetApplicationResources:
8607        return GetApplicationResources (taskData, GetDS(taskData, XP1),GetWidget(taskData, XP1),SAVE(P2) ) ;
8608
8609    case XCALL_XtAddEventHandler:
8610        AddEventhandler (taskData, WidgetObject(taskData, XP1), get_C_ulong(taskData, P2),
8611            get_C_ulong(taskData, P3), SAVE(P4)); break;
8612
8613
8614        /******************************************************************************/
8615        /*                                                                            */
8616        /*      Motif Calls - widget creation                                         */
8617        /*                                                                            */
8618        /******************************************************************************/
8619        /* Motif 4000 */
8620
8621#define XMCREATE(number,name) \
8622    case number: return CreateXm(taskData, name, (char *)   \
8623#name   " failed",  \
8624    GetDS(taskData, XP1), \
8625    GetWidget(taskData, XP1), \
8626    GetString(P2),      \
8627        SAVE(P3))
8628
8629        XMCREATE(XCALL_XmCreateArrowButton,XmCreateArrowButton);
8630        XMCREATE(XCALL_XmCreateArrowButtonGadget,XmCreateArrowButtonGadget);
8631        XMCREATE(XCALL_XmCreateBulletinBoard,XmCreateBulletinBoard);
8632        XMCREATE(XCALL_XmCreateBulletinBoardDialog,XmCreateBulletinBoardDialog);
8633        XMCREATE(XCALL_XmCreateCascadeButton,XmCreateCascadeButton);
8634        XMCREATE(XCALL_XmCreateCascadeButtonGadget,XmCreateCascadeButtonGadget);
8635        XMCREATE(XCALL_XmCreateCommand,XmCreateCommand);
8636        XMCREATE(XCALL_XmCreateDialogShell,XmCreateDialogShell);
8637        XMCREATE(XCALL_XmCreateDrawingArea,XmCreateDrawingArea);
8638        XMCREATE(XCALL_XmCreateDrawnButton,XmCreateDrawnButton);
8639        XMCREATE(XCALL_XmCreateErrorDialog,XmCreateErrorDialog);
8640        XMCREATE(XCALL_XmCreateFileSelectionBox,XmCreateFileSelectionBox);
8641        XMCREATE(XCALL_XmCreateFileSelectionDialog,XmCreateFileSelectionDialog);
8642        XMCREATE(XCALL_XmCreateForm,XmCreateForm);
8643        XMCREATE(XCALL_XmCreateFormDialog,XmCreateFormDialog);
8644        XMCREATE(XCALL_XmCreateFrame,XmCreateFrame);
8645        XMCREATE(XCALL_XmCreateInformationDialog,XmCreateInformationDialog);
8646        XMCREATE(XCALL_XmCreateLabel,XmCreateLabel);
8647        XMCREATE(XCALL_XmCreateLabelGadget,XmCreateLabelGadget);
8648        XMCREATE(XCALL_XmCreateList,XmCreateList);
8649        XMCREATE(XCALL_XmCreateMainWindow,XmCreateMainWindow);
8650        XMCREATE(XCALL_XmCreateMenuBar,XmCreateMenuBar);
8651        XMCREATE(XCALL_XmCreateMenuShell,XmCreateMenuShell);
8652        XMCREATE(XCALL_XmCreateMessageBox,XmCreateMessageBox);
8653        XMCREATE(XCALL_XmCreateMessageDialog,XmCreateMessageDialog);
8654        XMCREATE(XCALL_XmCreateOptionMenu,XmCreateOptionMenu);
8655        XMCREATE(XCALL_XmCreatePanedWindow,XmCreatePanedWindow);
8656        XMCREATE(XCALL_XmCreatePopupMenu,XmCreatePopupMenu);
8657        XMCREATE(XCALL_XmCreatePromptDialog,XmCreatePromptDialog);
8658        XMCREATE(XCALL_XmCreatePulldownMenu,XmCreatePulldownMenu);
8659        XMCREATE(XCALL_XmCreatePushButton,XmCreatePushButton);
8660        XMCREATE(XCALL_XmCreatePushButtonGadget,XmCreatePushButtonGadget);
8661        XMCREATE(XCALL_XmCreateQuestionDialog,XmCreateQuestionDialog);
8662        XMCREATE(XCALL_XmCreateRadioBox,XmCreateRadioBox);
8663        XMCREATE(XCALL_XmCreateRowColumn,XmCreateRowColumn);
8664        XMCREATE(XCALL_XmCreateScale,XmCreateScale);
8665        XMCREATE(XCALL_XmCreateScrollBar,XmCreateScrollBar);
8666        XMCREATE(XCALL_XmCreateScrolledList,XmCreateScrolledList);
8667        XMCREATE(XCALL_XmCreateScrolledText,XmCreateScrolledText);
8668        XMCREATE(XCALL_XmCreateScrolledWindow,XmCreateScrolledWindow);
8669        XMCREATE(XCALL_XmCreateSelectionBox,XmCreateSelectionBox);
8670        XMCREATE(XCALL_XmCreateSelectionDialog,XmCreateSelectionDialog);
8671        XMCREATE(XCALL_XmCreateSeparator,XmCreateSeparator);
8672        XMCREATE(XCALL_XmCreateSeparatorGadget,XmCreateSeparatorGadget);
8673        XMCREATE(XCALL_XmCreateSimpleCheckBox,XmCreateSimpleCheckBox);
8674        XMCREATE(XCALL_XmCreateSimpleMenuBar,XmCreateSimpleMenuBar);
8675        XMCREATE(XCALL_XmCreateSimpleOptionMenu,XmCreateSimpleOptionMenu);
8676        XMCREATE(XCALL_XmCreateSimplePopupMenu,XmCreateSimplePopupMenu);
8677        XMCREATE(XCALL_XmCreateSimplePulldownMenu,XmCreateSimplePulldownMenu);
8678        XMCREATE(XCALL_XmCreateSimpleRadioBox,XmCreateSimpleRadioBox);
8679        XMCREATE(XCALL_XmCreateText,XmCreateText);
8680        XMCREATE(XCALL_XmCreateTextField,XmCreateTextField);
8681        XMCREATE(XCALL_XmCreateToggleButton,XmCreateToggleButton);
8682        XMCREATE(XCALL_XmCreateToggleButtonGadget,XmCreateToggleButtonGadget);
8683        XMCREATE(XCALL_XmCreateWarningDialog,XmCreateWarningDialog);
8684        XMCREATE(XCALL_XmCreateWorkArea,XmCreateWorkArea);
8685        XMCREATE(XCALL_XmCreateWorkingDialog,XmCreateWorkingDialog);
8686
8687#undef XMCREATE
8688
8689        /******************************************************************************/
8690        /*                                                                            */
8691        /*      Motif Calls - miscellaneous                                           */
8692        /*                                                                            */
8693        /******************************************************************************/
8694    case XCALL_XmCascadeButtonHighlight:
8695        XmCascadeButtonHighlight(GetWidget(taskData, XP1),get_C_ulong(taskData, P2));
8696        break;
8697
8698    case XCALL_XmCommandError:
8699        CommandError(taskData, GetWidget(taskData, XP1),P2);
8700        break;
8701
8702    case XCALL_XmCommandGetChild:
8703        return EmptyWidget(taskData, GetDS(taskData, XP1),
8704            XmCommandGetChild(GetWidget(taskData, XP1),get_C_ulong(taskData, P2)));
8705
8706    case XCALL_XmFileSelectionBoxGetChild:
8707        return EmptyWidget(taskData, GetDS(taskData, XP1),
8708            XmFileSelectionBoxGetChild(GetWidget(taskData, XP1),get_C_ulong(taskData, P2)));
8709
8710    case XCALL_XmFileSelectionDoSearch:
8711        FileSelectionDoSearch(taskData, GetWidget(taskData, XP1),P2);
8712        break;
8713
8714    case XCALL_XmIsSomething:
8715        return XmIsSomething(taskData, get_C_ulong(taskData, P1),GetWidget(taskData, XP2));
8716
8717    case XCALL_XmMainWindowSetAreas:
8718        XmMainWindowSetAreas(GetWidget(taskData, XP1),
8719            GetNWidget(taskData, XP2),
8720            GetNWidget(taskData, XP3),
8721            GetNWidget(taskData, XP4),
8722            GetNWidget(taskData, XP5),
8723            GetNWidget(taskData, XP6));
8724        break;
8725
8726    case XCALL_XmMainWindowSepX:
8727        switch(get_C_ulong(taskData, P2))
8728        {
8729        case 1:
8730            return EmptyWidget(taskData, GetDS(taskData, XP1),XmMainWindowSep1(GetWidget(taskData, XP1)));
8731
8732        case 2:
8733            return EmptyWidget(taskData, GetDS(taskData, XP1),XmMainWindowSep2(GetWidget(taskData, XP1)));
8734
8735        default:
8736            return EmptyWidget(taskData, GetDS(taskData, XP1),XmMainWindowSep3(GetWidget(taskData, XP1)));
8737        }
8738
8739        case XCALL_XmMessageBoxGetChild:
8740            return EmptyWidget(taskData, GetDS(taskData, XP1),
8741                XmMessageBoxGetChild(GetWidget(taskData, XP1),get_C_ulong(taskData, P2)));
8742
8743        case XCALL_XmOptionButtonGadget:
8744            return EmptyWidget(taskData, GetDS(taskData, XP1),XmOptionButtonGadget(GetWidget(taskData, XP1)));
8745
8746        case XCALL_XmOptionLabelGadget:
8747            return EmptyWidget(taskData, GetDS(taskData, XP1),XmOptionLabelGadget (GetWidget(taskData, XP1)));
8748
8749        case XCALL_XmSelectionBoxGetChild:
8750            return EmptyWidget(taskData, GetDS(taskData, XP1),
8751                XmSelectionBoxGetChild(GetWidget(taskData, XP1),get_C_ulong(taskData, P2)));
8752
8753        case XCALL_XmSetMenuCursor:
8754            XmSetMenuCursor(GetDisplay(taskData, XP1),GetCursor(taskData, XP2)); break;
8755
8756        case XCALL_XmScrolledWindowSetAreas:
8757            XmScrolledWindowSetAreas(GetWidget(taskData, XP1),
8758                GetNWidget(taskData, XP2),
8759                GetNWidget(taskData, XP3),
8760                GetNWidget(taskData, XP4));
8761            break;
8762
8763
8764            /******************************************************************************/
8765            /*                                                                            */
8766            /*      Operations on XmText widgets                                          */
8767            /*                                                                            */
8768            /******************************************************************************/
8769
8770#define TextWidgetToLong(func) \
8771        case XCALL_ ## func : \
8772            return(WidgetToLong(taskData,(char *) #func,GetTextWidget,func,XP1))
8773
8774#define TextWidgetToInt(func) \
8775        case XCALL_ ## func : \
8776            return(WidgetToInt(taskData,(char *) #func,GetTextWidget,func,XP1))
8777
8778#define TextWidgetToBool(func) \
8779        case XCALL_ ## func : \
8780            return(WidgetToBool(taskData,(char *) #func,GetTextWidget,func,XP1))
8781
8782#define TextWidgetToString(func) \
8783        case XCALL_ ## func : \
8784            return(WidgetToString(taskData,(char *) #func,GetTextWidget,func,XP1))
8785
8786#define TextWidgetIntAction(func) \
8787        case XCALL_ ## func : \
8788        WidgetIntAction(taskData,(char *) #func,GetTextWidget,func,XP1,P2); \
8789            break
8790
8791#define TextWidgetLongAction(func) \
8792        case XCALL_ ## func : \
8793        WidgetLongAction(taskData,(char *) #func,GetTextWidget,func,XP1,P2); \
8794            break
8795
8796#define TextWidgetBoolAction(func) \
8797        case XCALL_ ## func : \
8798        WidgetBoolAction(taskData,(char *) #func,GetTextWidget,func,XP1,P2); \
8799            break
8800
8801
8802            /* XmTextClearSelection not supported */
8803            /* XmTextCopy not supported */
8804            /* XmTextCut not supported */
8805#ifdef LESSTIF_VERSION
8806            /* This is not supported in LessTif, at least not 0.89. */
8807        case XCALL_XmTextGetAddMode:
8808            RaiseXWindows(taskData, "XmTextGetAddMode: not implemented");
8809#else
8810            TextWidgetToBool(XmTextGetAddMode);
8811#endif
8812            TextWidgetToLong(XmTextGetCursorPosition);
8813            TextWidgetToInt(XmTextGetBaseline);
8814            TextWidgetToBool(XmTextGetEditable);
8815            TextWidgetToLong(XmTextGetInsertionPosition);
8816            TextWidgetToLong(XmTextGetLastPosition);
8817            TextWidgetToInt(XmTextGetMaxLength);
8818            TextWidgetToString(XmTextGetSelection);
8819            /* XmTextGetSelectionPosition not supported */
8820            TextWidgetToString(XmTextGetString);
8821            /* XmTextGetSource not supported */
8822            TextWidgetToLong(XmTextGetTopCharacter);
8823
8824        case XCALL_XmTextInsert:
8825            {
8826          Widget w = GetTextWidget(taskData, (char *) "XmTextInsert",XP1);
8827                {
8828                    unsigned pos = get_C_ulong(taskData, P2);
8829                    PolyStringObject *s    = GetString(P3);
8830                    int   size   = s->length + 1;
8831                    char *buffer = (char *)alloca(size);
8832
8833                    Poly_string_to_C(s,buffer,size);
8834                    XmTextInsert(w,pos,buffer);
8835                    break;
8836                }
8837            }
8838
8839            TextWidgetToBool(XmTextPaste); /* with side effect! */
8840            /* XmTextPosToXY not supported */
8841            TextWidgetToBool(XmTextRemove); /* with side effect! */
8842
8843        case XCALL_XmTextReplace:
8844            {
8845          Widget w = GetTextWidget(taskData, (char *) "XmTextReplace",XP1);
8846                {
8847                    unsigned from_pos = get_C_ulong(taskData, P2);
8848                    unsigned to_pos   = get_C_ulong(taskData, P3);
8849                    PolyStringObject *s    = GetString(P4);
8850                    int   size   = s->length + 1;
8851                    char *buffer = (char *)alloca(size);
8852
8853                    Poly_string_to_C(s,buffer,size);
8854                    XmTextReplace(w,from_pos,to_pos,buffer);
8855                    break;
8856                }
8857            }
8858
8859            TextWidgetIntAction(XmTextScroll); /* for side effect! */
8860            TextWidgetBoolAction(XmTextSetAddMode);
8861            TextWidgetLongAction(XmTextSetCursorPosition);
8862            TextWidgetBoolAction(XmTextSetEditable);
8863            /* XmTextSetHighlight not supported */
8864            TextWidgetLongAction(XmTextSetInsertionPosition);
8865            TextWidgetIntAction(XmTextSetMaxLength);
8866            /* XmTextSetSelection not supported */
8867            /* XmTextSetSource not supported */
8868
8869
8870            /* inlined SPF 15/2/94 */
8871        case XCALL_XmTextSetString:
8872            {
8873          Widget w = GetTextWidget(taskData, (char *) "XmTextSetString",XP1);
8874                {
8875                    PolyStringObject *s    = GetString(P2);
8876                    int   size   = s->length + 1;
8877                    char *buffer = (char *)alloca(size);
8878
8879                    Poly_string_to_C(s,buffer,size);
8880                    XmTextSetString(w,buffer);
8881                    break;
8882                }
8883            }
8884
8885            TextWidgetLongAction(XmTextSetTopCharacter);
8886            TextWidgetLongAction(XmTextShowPosition);
8887
8888        case XCALL_XmTextXYToPos:
8889            {
8890                Widget w = GetTextWidget(taskData, (char *) "XmTextXYToPos",XP1);
8891                {
8892                    int x = get_C_long(taskData, P2);
8893                    int y = get_C_long(taskData, P3);
8894                    return Make_int(XmTextXYToPos(w,x,y));
8895                }
8896            }
8897
8898#undef TextWidgetToLong
8899#undef TextWidgetToInt
8900#undef TextWidgetToBool
8901#undef TextWidgetToString
8902#undef TextWidgetIntAction
8903#undef TextWidgetBoolAction
8904
8905            /******************************************************************************/
8906            /*                                                                            */
8907            /*      Operations on XmTextField widgets                                     */
8908            /*                                                                            */
8909            /******************************************************************************/
8910
8911#define TextFieldWidgetToLong(func) \
8912        case XCALL_ ## func : \
8913            return(WidgetToLong(taskData, (char *) #func,GetTextFieldWidget,func,XP1))
8914
8915
8916#define TextFieldWidgetToInt(func) \
8917        case XCALL_ ## func : \
8918            return(WidgetToInt(taskData, (char *) #func,GetTextFieldWidget,func,XP1))
8919
8920#define TextFieldWidgetToBool(func) \
8921        case XCALL_ ## func : \
8922            return(WidgetToBool(taskData, (char *) #func,GetTextFieldWidget,func,XP1))
8923
8924#define TextFieldWidgetToString(func) \
8925        case XCALL_ ## func : \
8926            return(WidgetToString(taskData, (char *) #func,GetTextFieldWidget,func,XP1))
8927
8928#define TextFieldWidgetIntAction(func) \
8929        case XCALL_ ## func : \
8930        WidgetIntAction(taskData, (char *) #func,GetTextFieldWidget,func,XP1,P2); \
8931            break
8932
8933#define TextFieldWidgetLongAction(func) \
8934        case XCALL_ ## func : \
8935        WidgetLongAction(taskData, (char *) #func,GetTextFieldWidget,func,XP1,P2); \
8936            break
8937
8938#define TextFieldWidgetBoolAction(func) \
8939        case XCALL_ ## func : \
8940        WidgetBoolAction(taskData, (char *) #func,GetTextFieldWidget,func,XP1,P2); \
8941            break
8942
8943
8944            /* XmTextFieldClearSelection not supported */
8945            /* XmTextFieldCopy not supported */
8946            /* XmTextFieldCut not supported */
8947#ifdef LESSTIF_VERSION
8948            /* This is not supported in LessTif, at least not 0.89. */
8949        case XCALL_XmTextFieldGetAddMode:
8950            RaiseXWindows(taskData, "XmTextFieldGetAddMode: not implemented");
8951#else
8952            TextFieldWidgetToBool(XmTextFieldGetAddMode);
8953#endif
8954            TextFieldWidgetToInt(XmTextFieldGetBaseline);
8955            TextFieldWidgetToLong(XmTextFieldGetCursorPosition);
8956            TextFieldWidgetToBool(XmTextFieldGetEditable);
8957            TextFieldWidgetToLong(XmTextFieldGetInsertionPosition);
8958            TextFieldWidgetToLong(XmTextFieldGetLastPosition);
8959            TextFieldWidgetToInt(XmTextFieldGetMaxLength);
8960            TextFieldWidgetToString(XmTextFieldGetSelection);
8961            /* XmTextFieldGetSelectionPosition not supported */
8962            TextFieldWidgetToString(XmTextFieldGetString);
8963            /* XmTextFieldGetSource not supported */
8964
8965        case XCALL_XmTextFieldInsert:
8966            {
8967                Widget w = GetTextFieldWidget(taskData, (char *) "XmTextFieldInsert",XP1);
8968                {
8969                    unsigned pos = get_C_ulong(taskData, P2);
8970                    PolyStringObject *s    = GetString(P3);
8971                    int   size   = s->length + 1;
8972                    char *buffer = (char *)alloca(size);
8973
8974                    Poly_string_to_C(s,buffer,size);
8975                    XmTextFieldInsert(w,pos,buffer);
8976                    break;
8977                }
8978            }
8979
8980            TextFieldWidgetToBool(XmTextFieldPaste); /* for side effect! */
8981            /* XmTextFieldPosToXY not supported */
8982            TextFieldWidgetToBool(XmTextFieldRemove); /* for side effect! */
8983
8984        case XCALL_XmTextFieldReplace:
8985            {
8986                Widget w = GetTextFieldWidget(taskData, (char *) "XmTextFieldReplace",XP1);
8987                {
8988                    unsigned from_pos = get_C_ulong(taskData, P2);
8989                    unsigned to_pos   = get_C_ulong(taskData, P3);
8990                    PolyStringObject *s    = GetString(P4);
8991                    int   size   = s->length + 1;
8992                    char *buffer = (char *)alloca(size);
8993
8994                    Poly_string_to_C(s,buffer,size);
8995                    XmTextFieldReplace(w,from_pos,to_pos,buffer);
8996                    break;
8997                }
8998            }
8999
9000            TextFieldWidgetBoolAction(XmTextFieldSetAddMode);
9001            TextFieldWidgetLongAction(XmTextFieldSetCursorPosition);
9002            TextFieldWidgetBoolAction(XmTextFieldSetEditable);
9003            /* XmTextFieldSetHighlight not supported */
9004            TextFieldWidgetLongAction(XmTextFieldSetInsertionPosition);
9005            TextFieldWidgetIntAction(XmTextFieldSetMaxLength);
9006            /* XmTextFieldSetSelection not supported */
9007
9008
9009            /* inlined SPF 15/2/94 */
9010        case XCALL_XmTextFieldSetString:
9011            {
9012                Widget w = GetTextFieldWidget(taskData, (char *) "XmTextFieldSetString",XP1);
9013                {
9014                    PolyStringObject *s    = GetString(P2);
9015                    int   size   = s->length + 1;
9016                    char *buffer = (char *)alloca(size);
9017
9018                    Poly_string_to_C(s,buffer,size);
9019                    XmTextFieldSetString(w,buffer);
9020                    break;
9021                }
9022            }
9023
9024            TextFieldWidgetLongAction(XmTextFieldShowPosition);  /* for side effect! */
9025
9026        case XCALL_XmTextFieldXYToPos:
9027            {
9028                Widget w = GetTextFieldWidget(taskData, (char *) "XmTextFieldXYToPos",XP1);
9029                {
9030                    int x = get_C_long(taskData, P2);
9031                    int y = get_C_long(taskData, P3);
9032                    return Make_int(XmTextFieldXYToPos(w,x,y));
9033                }
9034            }
9035
9036        case XCALL_XmTrackingLocate:
9037            return EmptyWidget(taskData, GetDS(taskData, XP1),
9038                XmTrackingLocate(GetWidget(taskData, XP1),GetCursor(taskData, XP2),get_C_ulong(taskData, P3)));
9039
9040        case XCALL_XmUpdateDisplay:
9041            XmUpdateDisplay(GetWidget(taskData, XP1));
9042            break;
9043
9044#undef TextFieldWidgetToLong
9045#undef TextFieldWidgetToInt
9046#undef TextFieldWidgetToBool
9047#undef TextFieldWidgetToString
9048#undef TextFieldWidgetIntAction
9049#undef TextFieldWidgetLongAction
9050#undef TextFieldWidgetBoolAction
9051
9052            /******************************************************************************/
9053            /*                                                                            */
9054            /*      Operations on XmList widgets                                          */
9055            /*                                                                            */
9056            /******************************************************************************/
9057
9058#define ListWidgetAction(func) \
9059        case XCALL_ ## func : \
9060        WidgetAction(taskData, (char *) #func,GetListWidget,func,XP1); \
9061            break
9062
9063#define ListWidgetBoolAction(func) \
9064        case XCALL_ ## func : \
9065        WidgetBoolAction(taskData, (char *) #func,GetListWidget,func,XP1,P2); \
9066            break
9067
9068#define ListWidgetXmstringAction(func) \
9069        case XCALL_ ## func : \
9070        WidgetXmstringAction(taskData, (char *) #func,GetListWidget,func,XP1,P2); \
9071            break
9072
9073#define ListWidgetXmstringlistAction(func) \
9074        case XCALL_ ## func : \
9075        WidgetXmstringlistAction(taskData, (char *)  #func,GetListWidget,func,XP1,(ML_Cons_Cell *)XP2); \
9076            break
9077
9078#define ListWidgetIntAction(func) \
9079        case XCALL_ ## func : \
9080      WidgetIntAction(taskData, (char *) #func,GetListWidget,func,XP1,P2); \
9081            break
9082
9083#define ListWidgetIntIntAction(func) \
9084        case XCALL_ ## func : \
9085        WidgetIntIntAction(taskData, (char *) #func,GetListWidget,func,XP1,P2,P3); \
9086            break
9087
9088#define ListWidgetXmstringIntAction(func) \
9089        case XCALL_ ## func : \
9090        WidgetXmstringIntAction(taskData, (char *) #func,GetListWidget,func,XP1,P2,P3); \
9091            break
9092
9093#define ListWidgetIntBoolAction(func) \
9094        case XCALL_ ## func : \
9095        WidgetIntBoolAction(taskData, (char *) #func,GetListWidget,func,XP1,P2,P3); \
9096            break
9097
9098#define ListWidgetXmstringBoolAction(func) \
9099        case XCALL_ ## func : \
9100        WidgetXmstringBoolAction(taskData, (char *) #func,GetListWidget,func,XP1,P2,P3); \
9101            break
9102
9103#define ListWidgetXmstringlistIntAction(func) \
9104        case XCALL_ ## func : \
9105        WidgetXmstringlistIntAction(taskData, (char *) #func,GetListWidget,func,XP1,(ML_Cons_Cell *)XP2,P3); \
9106            break
9107
9108#define ListWidgetXmstringToIntlist(func) \
9109        case XCALL_ ## func : \
9110            return(WidgetXmstringToIntlist(taskData, (char *)  #func,GetListWidget,func,XP1,P2))
9111
9112#define ListWidgetToIntlist(func) \
9113        case XCALL_ ## func : \
9114            return(WidgetToIntlist(taskData, (char *) #func,GetListWidget,func,XP1))
9115
9116#define ListWidgetXmstringToBool(func) \
9117        case XCALL_ ## func : \
9118            return(WidgetXmstringToBool(taskData, (char *) #func,GetListWidget,func,XP1,P2))
9119
9120#define ListWidgetXmstringToInt(func) \
9121        case XCALL_ ## func : \
9122            return(WidgetXmstringToInt(taskData, (char *)  #func,GetListWidget,func,XP1,P2))
9123
9124            /************************* Adding Items to List *******************************/
9125            ListWidgetXmstringIntAction(XmListAddItem);
9126            ListWidgetXmstringIntAction(XmListAddItemUnselected);
9127            ListWidgetXmstringlistIntAction(XmListAddItems);
9128
9129            /************************* Deleting Items from List ***************************/
9130            ListWidgetAction(XmListDeleteAllItems);
9131            ListWidgetXmstringAction(XmListDeleteItem);
9132            ListWidgetXmstringlistAction(XmListDeleteItems);
9133            ListWidgetIntAction(XmListDeletePos);
9134            ListWidgetIntIntAction(XmListDeleteItemsPos);
9135
9136            /************************* Deselecting Items **********************************/
9137            ListWidgetAction(XmListDeselectAllItems);
9138            ListWidgetXmstringAction(XmListDeselectItem);
9139            ListWidgetIntAction(XmListDeselectPos);
9140
9141
9142            /************************* Query Functions ************************************/
9143            ListWidgetXmstringToIntlist(XmListGetMatchPos);
9144            ListWidgetToIntlist(XmListGetSelectedPos);
9145            ListWidgetXmstringToBool(XmListItemExists);
9146            ListWidgetXmstringToInt(XmListItemPos);
9147
9148            /************************* Replacing Items in the List ************************/
9149    case XCALL_XmListReplaceItems:
9150        /* Unpairing the strings is done in the ML, because it's easier there. */
9151        {
9152      Widget w = GetListWidget(taskData, (char *) "XmListReplaceItems",XP1);
9153            unsigned n    = ListLength(P2);
9154            unsigned n2   = ListLength(P3);
9155
9156            if (n != n2)
9157            {
9158                RaiseXWindows(taskData, "XmListReplaceItems: strings lists are different lengths");
9159            }
9160            else
9161            {
9162                XmString *oldstrings = (XmString *)alloca(n * sizeof(XmString));
9163                XmString *newstrings = (XmString *)alloca(n * sizeof(XmString));
9164
9165                GetList4(taskData, P2,oldstrings,sizeof(XmString),GetXmString);
9166                GetList4(taskData, P3,newstrings,sizeof(XmString),GetXmString);
9167                XmListReplaceItems(w,oldstrings,n,newstrings);
9168                for (unsigned i = 0; i < n; i ++) XmStringFree(oldstrings[i]);
9169                for (unsigned i = 0; i < n; i ++) XmStringFree(newstrings[i]);
9170            }
9171            break;
9172        }
9173
9174        ListWidgetXmstringlistIntAction(XmListReplaceItemsPos);
9175
9176        /************************* Selecting Items in the List ************************/
9177        ListWidgetXmstringBoolAction(XmListSelectItem);
9178        ListWidgetIntBoolAction(XmListSelectPos);
9179
9180        /************************* Set Add Mode ***************************************/
9181        ListWidgetBoolAction(XmListSetAddMode);
9182
9183        /************************* Set Appearance *************************************/
9184        ListWidgetXmstringAction(XmListSetBottomItem);
9185        ListWidgetIntAction(XmListSetBottomPos);
9186        ListWidgetIntAction(XmListSetHorizPos);
9187        ListWidgetXmstringAction(XmListSetItem);
9188        ListWidgetIntAction(XmListSetPos);
9189
9190#undef ListWidgetAction
9191#undef ListWidgetBoolAction
9192#undef ListWidgetXmstringAction
9193#undef ListWidgetXmstringlistAction
9194#undef ListWidgetIntAction
9195#undef ListWidgetIntIntAction
9196#undef ListWidgetXmstringIntAction
9197#undef ListWidgetXmstringBoolAction
9198#undef ListWidgetXmstringlistIntAction
9199#undef ListWidgetXmstringToIntlist
9200#undef ListWidgetToIntlist
9201#undef ListWidgetXmstringToBool
9202#undef ListWidgetXmstringToInt
9203
9204
9205        /* Calls added by DCJM. */
9206    case XCALL_XmMenuPosition:
9207        MenuPosition( GetWidget(taskData, XP1), get_C_ulong(taskData, P2), get_C_ulong(taskData, P3)); break;
9208        /******************************************************************************/
9209        /*                                                                            */
9210        /*      Default case                                                          */
9211        /*                                                                            */
9212        /******************************************************************************/
9213
9214    default: Crash ("Unimplemented X Windows call %d", code);
9215  }
9216
9217  return Make_bool(False);
9218}
9219
9220typedef struct
9221{
9222  int   code;
9223  const char *name;
9224} CodeName;
9225
9226static CodeName ProtocolNames[] =
9227{
9228  { X_CreateWindow,"XCreateWindow"},
9229  { X_ChangeWindowAttributes,"XChangeWindowAttributes"},
9230  { X_GetWindowAttributes,"XGetWindowAttributes"},
9231  { X_DestroyWindow,"XDestroyWindow"},
9232  { X_DestroySubwindows,"XDestroySubwindows"},
9233  { X_ChangeSaveSet,"XChangeSAVESet"},
9234  { X_ReparentWindow,"XReparentWindow"},
9235  { X_MapWindow,"XMapWindow"},
9236  { X_MapSubwindows,"XMapSubwindows"},
9237  { X_UnmapWindow,"XUnmapWindow"},
9238  { X_UnmapSubwindows,"XUnmapSubwindows"},
9239  { X_ConfigureWindow,"XConfigureWindow"},
9240  { X_CirculateWindow,"XCirculateWindow"},
9241  { X_GetGeometry,"XGetGeometry"},
9242  { X_QueryTree,"XQueryTree"},
9243  { X_InternAtom,"XInternAtom"},
9244  { X_GetAtomName,"XGetAtomName"},
9245  { X_ChangeProperty,"XChangeProperty"},
9246  { X_DeleteProperty,"XDeleteProperty"},
9247  { X_GetProperty,"XGetProperty"},
9248  { X_ListProperties,"XListProperties"},
9249  { X_SetSelectionOwner,"XSetSelectionOwner"},
9250  { X_GetSelectionOwner,"XGetSelectionOwner"},
9251  { X_ConvertSelection,"XConvertSelection"},
9252  { X_SendEvent,"XSendEvent"},
9253  { X_GrabPointer,"XGrabPointer"},
9254  { X_UngrabPointer,"XUngrabPointer"},
9255  { X_GrabButton,"XGrabButton"},
9256  { X_UngrabButton,"XUngrabButton"},
9257  { X_ChangeActivePointerGrab,"XChangeActivePointerGrab"},
9258  { X_GrabKeyboard,"XGrabKeyboard"},
9259  { X_UngrabKeyboard,"XUngrabKeyboard"},
9260  { X_GrabKey,"XGrabKey"},
9261  { X_UngrabKey,"XUngrabKey"},
9262  { X_AllowEvents,"XAllowEvents"},
9263  { X_GrabServer,"XGrabServer"},
9264  { X_UngrabServer,"XUngrabServer"},
9265  { X_QueryPointer,"XQueryPointer"},
9266  { X_GetMotionEvents,"XGetMotionEvents"},
9267  { X_TranslateCoords,"XTranslateCoords"},
9268  { X_WarpPointer,"XWarpPointer"},
9269  { X_SetInputFocus,"XSetInputFocus"},
9270  { X_GetInputFocus,"XGetInputFocus"},
9271  { X_QueryKeymap,"XQueryKeymap"},
9272  { X_OpenFont,"XOpenFont"},
9273  { X_CloseFont,"XCloseFont"},
9274  { X_QueryFont,"XQueryFont"},
9275  { X_QueryTextExtents,"XQueryTextExtents"},
9276  { X_ListFonts,"XListFonts"},
9277  { X_ListFontsWithInfo,"XListFontsWithInfo"},
9278  { X_SetFontPath,"XSetFontPath"},
9279  { X_GetFontPath,"XGetFontPath"},
9280  { X_CreatePixmap,"XCreatePixmap"},
9281  { X_FreePixmap,"XFreePixmap"},
9282  { X_CreateGC,"XCreateGC"},
9283  { X_ChangeGC,"XChangeGC"},
9284  { X_CopyGC,"XCopyGC"},
9285  { X_SetDashes,"XSetDashes"},
9286  { X_SetClipRectangles,"XSetClipRectangles"},
9287  { X_FreeGC,"XFreeGC"},
9288  { X_ClearArea,"XClearArea"},
9289  { X_CopyArea,"XCopyArea"},
9290  { X_CopyPlane,"XCopyPlane"},
9291  { X_PolyPoint,"XPolyPoint"},
9292  { X_PolyLine,"XPolyLine"},
9293  { X_PolySegment,"XPolySegment"},
9294  { X_PolyRectangle,"XPolyRectangle"},
9295  { X_PolyArc,"XPolyArc"},
9296  { X_FillPoly,"XFillPoly"},
9297  { X_PolyFillRectangle,"XPolyFillRectangle"},
9298  { X_PolyFillArc,"XPolyFillArc"},
9299  { X_PutImage,"XPutImage"},
9300  { X_GetImage,"XGetImage"},
9301  { X_PolyText8,"XPolyText8"},
9302  { X_PolyText16,"XPolyText16"},
9303  { X_ImageText8,"XImageText8"},
9304  { X_ImageText16,"XImageText16"},
9305  { X_CreateColormap,"XCreateColormap"},
9306  { X_FreeColormap,"XFreeColormap"},
9307  { X_CopyColormapAndFree,"XCopyColormapAndFree"},
9308  { X_InstallColormap,"XInstallColormap"},
9309  { X_UninstallColormap,"XUninstallColormap"},
9310  { X_ListInstalledColormaps,"XListInstalledColormaps"},
9311  { X_AllocColor,"XAllocColor"},
9312  { X_AllocNamedColor,"XAllocNamedColor"},
9313  { X_AllocColorCells,"XAllocColorCells"},
9314  { X_AllocColorPlanes,"XAllocColorPlanes"},
9315  { X_FreeColors,"XFreeColors"},
9316  { X_StoreColors,"XStoreColors"},
9317  { X_StoreNamedColor,"XStoreNamedColor"},
9318  { X_QueryColors,"XQueryColors"},
9319  { X_LookupColor,"XLookupColor"},
9320  { X_CreateCursor,"XCreateCursor"},
9321  { X_CreateGlyphCursor,"XCreateGlyphCursor"},
9322  { X_FreeCursor,"XFreeCursor"},
9323  { X_RecolorCursor,"XRecolorCursor"},
9324  { X_QueryBestSize,"XQueryBestSize"},
9325  { X_QueryExtension,"XQueryExtension"},
9326  { X_ListExtensions,"XListExtensions"},
9327  { X_ChangeKeyboardMapping,"XChangeKeyboardMapping"},
9328  { X_GetKeyboardMapping,"XGetKeyboardMapping"},
9329  { X_ChangeKeyboardControl,"XChangeKeyboardControl"},
9330  { X_GetKeyboardControl,"XGetKeyboardControl"},
9331  { X_Bell,"XBell"},
9332  { X_ChangePointerControl,"XChangePointerControl"},
9333  { X_GetPointerControl,"XGetPointerControl"},
9334  { X_SetScreenSaver,"XSetScreenSaver"},
9335  { X_GetScreenSaver,"XGetScreenSaver"},
9336  { X_ChangeHosts,"XChangeHosts"},
9337  { X_ListHosts,"XListHosts"},
9338  { X_SetAccessControl,"XSetAccessControl"},
9339  { X_SetCloseDownMode,"XSetCloseDownMode"},
9340  { X_KillClient,"XKillClient"},
9341  { X_RotateProperties,"XRotateProperties"},
9342  { X_ForceScreenSaver,"XForceScreenSaver"},
9343  { X_SetPointerMapping,"XSetPointerMapping"},
9344  { X_GetPointerMapping,"XGetPointerMapping"},
9345  { X_SetModifierMapping,"XSetModifierMapping"},
9346  { X_GetModifierMapping,"XGetModifierMapping"},
9347  { X_NoOperation,"XNoOperation"}
9348};
9349
9350static CodeName ProtocolErrors[] =
9351{
9352  { Success,"Success"},
9353  { BadRequest,"BadRequest"},
9354  { BadValue,"BadValue"},
9355  { BadWindow,"BadWindow"},
9356  { BadPixmap,"BadPixmap"},
9357  { BadAtom,"BadAtom"},
9358  { BadCursor,"BadCursor"},
9359  { BadFont,"BadFont"},
9360  { BadMatch,"BadMatch"},
9361  { BadDrawable,"BadDrawable"},
9362  { BadAccess,"BadAccess"},
9363  { BadAlloc,"BadAlloc"},
9364  { BadColor,"BadColor"},
9365  { BadGC,"BadGC"},
9366  { BadIDChoice,"BadIDChoice"},
9367  { BadName,"BadName"},
9368  { BadLength,"BadLength"},
9369  { BadImplementation,"BadImplementation"}
9370};
9371
9372static int XWindowsError(Display *display, XErrorEvent *error)
9373{
9374  const char *errorName   = "unknown";
9375  const char *requestName = "unknown";
9376  int   i,n;
9377  char  buffer[500];
9378
9379  n = sizeof(ProtocolErrors) / sizeof(ProtocolErrors[0]);
9380
9381  for(i = 0; i < n; i++)
9382    {
9383     if (ProtocolErrors[i].code == error->error_code)
9384       {
9385        errorName = ProtocolErrors[i].name;
9386       }
9387    }
9388
9389  n = sizeof(ProtocolNames) / sizeof(ProtocolNames[0]);
9390
9391  for(i = 0; i < n; i++)
9392    {
9393     if (ProtocolNames[i].code == error->request_code)
9394       {
9395         requestName = ProtocolNames[i].name;
9396       }
9397    }
9398
9399  sprintf(buffer,"%s in %s",errorName,requestName);
9400
9401  printf("\nX Error %s\n\n", buffer);
9402
9403#if NEVER
9404  /* Raise exception if we are running in synchronous mode */
9405  if (display->private15) RaiseXWindows(taskData, buffer);
9406#endif
9407
9408  return 0; /* DUMMY value - SPF 6/1/94 */
9409}
9410
9411struct _entrypts xwindowsEPT[] =
9412{
9413    { "PolyXWindowsGeneral",            (polyRTSFunction)&PolyXWindowsGeneral},
9414
9415    { NULL, NULL} // End of list.
9416};
9417
9418class XWinModule: public RtsModule
9419{
9420public:
9421    virtual void Init(void);
9422    void GarbageCollect(ScanAddress *process);
9423};
9424
9425// Declare this.  It will be automatically added to the table.
9426static XWinModule xwinModule;
9427
9428
9429void XWinModule::GarbageCollect(ScanAddress *process)
9430{
9431    /* Process all the objects in the list. If an object */
9432    /* is not found from outside then it is removed.     */
9433
9434    T_List **T = &TList;
9435    C_List **C = &CList;
9436
9437    int i;
9438
9439    /* process all XList headers */
9440    for (i = 0; i < XLISTSIZE; i++)
9441    {
9442        X_List *L = XList[i];
9443
9444        while(L)
9445        {
9446            PolyObject *P = L->object;  /* copy object pointer */
9447            X_List   *N = L->next;    /* copy next   pointer */
9448            process->ScanRuntimeAddress(&P, ScanAddress::STRENGTH_WEAK);
9449
9450            /* P may have been moved, or overwritten with a 0 if not accessible */
9451
9452            if (P == 0)
9453                DestroyXObject(L->object);
9454            else
9455                L->object = (X_Object*)P;
9456
9457            L = N;
9458        }
9459    }
9460
9461    /* Process the timeout/message list */
9462
9463    while (*T)
9464    {
9465        T_List *t = *T;
9466
9467        process->ScanRuntimeAddress(&t->alpha, ScanAddress::STRENGTH_STRONG);
9468        process->ScanRuntimeAddress(&t->handler, ScanAddress::STRENGTH_STRONG);
9469
9470        PolyObject *obj = t->window_object;
9471        process->ScanRuntimeAddress(&obj, ScanAddress::STRENGTH_WEAK);
9472        t->window_object = (X_Window_Object*)obj;
9473
9474        obj = t->widget_object;
9475        process->ScanRuntimeAddress(&obj, ScanAddress::STRENGTH_STRONG);
9476        t->widget_object = (X_Widget_Object*)obj;
9477
9478        // DCJM: I don't understand this.  The widget entry will never go
9479        // to zero since it's strong not weak.
9480        if (t->window_object == 0 && t->widget_object == 0)
9481        {
9482            *T = t->next;
9483
9484            free(t);
9485        }
9486        else T = &t->next;
9487    }
9488
9489    /* Process the callback list */
9490
9491    while(*C)
9492    {
9493        C_List *c = *C;
9494        process->ScanRuntimeAddress(&c->function, ScanAddress::STRENGTH_STRONG);
9495
9496        PolyObject *obj = c->widget_object;
9497        process->ScanRuntimeAddress(&obj, ScanAddress::STRENGTH_STRONG);
9498        c->widget_object = (X_Widget_Object*)obj;
9499
9500        /* DCJM: This doesn't make sense.  The widget entry will only
9501           go to zero if the G.C. operation was weak, not strong as in
9502           the line above. */
9503        if (c->widget_object == 0)
9504        {
9505            *C = c->next;
9506
9507            free(c);
9508        }
9509        else C = &c->next;
9510    }
9511
9512    /* Process the callback waiting list */
9513    if (! FList.IsTagged())
9514    {
9515        PolyObject *obj = FList.AsObjPtr();
9516        process->ScanRuntimeAddress(&obj, ScanAddress::STRENGTH_STRONG);
9517        FList = obj;
9518    }
9519
9520    /* and the Xt event waiting list. */
9521    if (! GList.IsTagged())
9522    {
9523        PolyObject *obj = GList.AsObjPtr();
9524        process->ScanRuntimeAddress(&obj, ScanAddress::STRENGTH_STRONG) ;
9525        GList = obj;
9526    }
9527}
9528
9529
9530void XWinModule::Init(void)
9531{
9532    initXList(); /* added 9/12/93 SPF */
9533
9534    XtToolkitThreadInitialize();
9535    XtToolkitInitialize();
9536
9537    XSetErrorHandler(XWindowsError);
9538}
9539
9540POLYUNSIGNED PolyXWindowsGeneral(FirstArgument threadId, PolyWord params)
9541{
9542    TaskData *taskData = TaskData::FindTaskForId(threadId);
9543    taskData->PreRTSCall();
9544    Handle reset = taskData->saveVec.mark();
9545    Handle pushedArg = taskData->saveVec.push(params);
9546    Handle result = 0;
9547
9548    try {
9549        result = XWindows_c(taskData, pushedArg);
9550    }
9551    catch (KillException &) {
9552        processes->ThreadExit(taskData); // May test for kill
9553    }
9554    catch (...) { } // If an ML exception is raised
9555
9556    taskData->saveVec.reset(reset);
9557    taskData->PostRTSCall();
9558    if (result == 0) return TAGGED(0).AsUnsigned();
9559    else return result->Word().AsUnsigned();
9560}
9561
9562#else
9563// We haven't got X or we haven't got Motif
9564
9565#include "globals.h"
9566#include "run_time.h"
9567#include "sys.h"
9568#include "save_vec.h"
9569#include "machine_dep.h"
9570#include "processes.h"
9571#include "rtsentry.h"
9572
9573#include "xwindows.h"
9574
9575extern "C" {
9576    POLYEXTERNALSYMBOL POLYUNSIGNED PolyXWindowsGeneral(FirstArgument threadId, PolyWord params);
9577}
9578
9579Handle XWindows_c(TaskData *taskData, Handle/*params*/)
9580{
9581    raise_exception_string(taskData, EXC_XWindows, "Not implemented");
9582
9583    /*NOTREACHED*/
9584    return taskData->saveVec.push(TAGGED(0)); /* just to keep lint happy */
9585}
9586
9587POLYUNSIGNED PolyXWindowsGeneral(FirstArgument threadId, PolyWord /*params*/)
9588{
9589    TaskData *taskData = TaskData::FindTaskForId(threadId);
9590    taskData->PreRTSCall();
9591
9592    try {
9593        raise_exception_string(taskData, EXC_XWindows, "Not implemented");
9594    } catch (...) { } // Handle the C++ exception
9595
9596    taskData->PostRTSCall();
9597    return TAGGED(0).AsUnsigned(); // Return unit since we're raising an exception
9598}
9599
9600struct _entrypts xwindowsEPT[] =
9601{
9602    { "PolyXWindowsGeneral",            (polyRTSFunction)&PolyXWindowsGeneral},
9603
9604    { NULL, NULL} // End of list.
9605};
9606
9607#endif
9608
9609