DisplayList.c revision 775e7de9
1/*
2 * Copyright (c) 1998 by The XFree86 Project, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 *
22 * Except as contained in this notice, the name of the XFree86 Project shall
23 * not be used in advertising or otherwise to promote the sale, use or other
24 * dealings in this Software without prior written authorization from the
25 * XFree86 Project.
26 *
27 * Author: Paulo César Pereira de Andrade
28 */
29
30/* $XFree86: xc/lib/Xaw/DisplayList.c,v 3.18 2003/05/23 14:51:15 tsi Exp $ */
31
32#ifdef HAVE_CONFIG_H
33#include <config.h>
34#endif
35#include <ctype.h>
36#include <string.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <X11/IntrinsicP.h>
40#include <X11/StringDefs.h>
41#include <X11/CoreP.h>
42#include <X11/Xfuncs.h>
43#include <X11/Xmu/CharSet.h>
44#include <X11/Xmu/SysUtil.h>
45#include "Private.h"
46
47#ifdef __UNIXOS2__
48static char dummy;
49#endif
50
51#ifndef OLDXAW
52
53/*
54 * Types
55 */
56typedef struct _XawDLProc XawDLProc;
57typedef struct _XawDLData XawDLData;
58typedef struct _XawDLInfo XawDLInfo;
59
60struct _XawDLProc {
61  XrmQuark qname;
62  String *params;
63  Cardinal num_params;
64  XawDisplayListProc proc;
65  XtPointer args;
66  XawDLData *data;
67};
68
69struct _XawDLData {
70  XawDLClass *dlclass;
71  XtPointer data;
72};
73
74struct _XawDLInfo {
75  String name;
76  XrmQuark qname;
77  XawDisplayListProc proc;
78};
79
80struct _XawDL {
81  XawDLProc **procs;
82  Cardinal num_procs;
83  XawDLData **data;
84  Cardinal num_data;
85  Screen *screen;
86  Colormap colormap;
87  int depth;
88  XrmQuark qrep;  /* for cache lookup */
89};
90
91struct _XawDLClass {
92  String name;
93  XawDLInfo **infos;
94  Cardinal num_infos;
95  XawDLArgsInitProc args_init;
96  XawDLArgsDestructor args_destructor;
97  XawDLDataInitProc data_init;
98  XawDLDataDestructor data_destructor;
99};
100
101/*
102 * Private Methods
103 */
104static XawDLClass *_XawFindDLClass(String);
105static int qcmp_dlist_class(_Xconst void*, _Xconst void*);
106static int bcmp_dlist_class(_Xconst void*, _Xconst void*);
107static XawDLInfo *_XawFindDLInfo(XawDLClass*, String);
108static int qcmp_dlist_info(_Xconst void*, _Xconst void*);
109static int bcmp_dlist_info(_Xconst void*, _Xconst void*);
110static void *_Xaw_Xlib_ArgsInitProc(String, String*, Cardinal*,
111				    Screen*, Colormap, int);
112static void _Xaw_Xlib_ArgsDestructor(Display*, String, XtPointer,
113				     String*, Cardinal*);
114static void *_Xaw_Xlib_DataInitProc(String, Screen*, Colormap, int);
115static void _Xaw_Xlib_DataDestructor(Display*, String, XtPointer);
116
117/*
118 * Initialization
119 */
120static XawDLClass **classes;
121static Cardinal num_classes;
122static String xlib = "xlib";
123
124/*
125 * Implementation
126 */
127void
128XawRunDisplayList(Widget w, _XawDisplayList *list,
129		       XEvent *event, Region region)
130{
131  XawDLProc *proc;
132  Cardinal i;
133
134  if (!XtIsRealized(w))
135    return;
136
137  for (i = 0; i < list->num_procs; i++)
138    {
139      proc = list->procs[i];
140      proc->proc(w, proc->args, proc->data->data, event, region);
141    }
142}
143
144#define DLERR  -2
145#define DLEOF  -1
146#define DLEND  1
147#define DLNAME 2
148#define DLARG  3
149static char *
150read_token(char *src, char *dst, Cardinal size, int *status)
151{
152  int ch;
153  Bool esc, quote;
154  Cardinal i;
155
156  i = 0;
157  esc = quote = False;
158
159  /*CONSTCOND*/
160  while (1)
161    {
162      ch = *src;
163      if (ch != '\n' && isspace(ch))
164	++src;
165      else
166	break;
167    }
168
169  for (; i < size - 1; src++)
170    {
171      ch = *src;
172      if (ch == '"')
173	{
174	  if (quote)
175	    {
176	      quote = False;
177	      continue;
178	    }
179	  quote = True;
180	  continue;
181	}
182      if (ch == '\\')
183	{
184	  if (esc)
185	    {
186	      dst[i++] = ch;
187	      esc = False;
188	      continue;
189	    }
190	  esc = True;
191	  continue;
192	}
193      if (ch == '\0')
194	{
195	  *status = DLEOF;
196	  dst[i] = '\0';
197	  return (src);
198	}
199      else if (!esc)
200	{
201	  if (!quote)
202	    {
203	      if (ch == ',')
204		{
205		  *status = DLARG;
206		  dst[i] = '\0';
207		  return (++src);
208		}
209	      else if (ch == ' ' || ch == '\t')
210		{
211		  *status = DLNAME;
212		  dst[i] = '\0';
213		  return (++src);
214		}
215	      else if (ch == ';' || ch == '\n')
216		{
217		  *status = DLEND;
218		  dst[i] = '\0';
219		  return (++src);
220		}
221	    }
222	}
223      else
224	esc = False;
225      dst[i++] = ch;
226    }
227
228  *status = DLERR;
229  dst[i] = '\0';
230
231  return (src);
232}
233
234_XawDisplayList *XawCreateDisplayList(String string, Screen *screen,
235				     Colormap colormap, int depth)
236{
237  _XawDisplayList *dlist;
238  XawDLClass *lc, *xlibc;
239  XawDLData *data;
240  XawDLInfo *info;
241  XawDLProc *proc;
242  char cname[64], fname[64], aname[1024];
243  Cardinal i;
244  char *cp, *fp, *lp;
245  int status;
246
247  xlibc = XawGetDisplayListClass(xlib);
248  if (!xlibc)
249    {
250      XawDisplayListInitialize();
251      xlibc = XawGetDisplayListClass(xlib);
252    }
253
254  dlist = (_XawDisplayList *)XtMalloc(sizeof(_XawDisplayList));
255  dlist->procs = NULL;
256  dlist->num_procs = 0;
257  dlist->data = NULL;
258  dlist->num_data = 0;
259  dlist->screen = screen;
260  dlist->colormap = colormap;
261  dlist->depth = depth;
262  dlist->qrep = NULLQUARK;
263  if (!string || !string[0])
264    return (dlist);
265
266  cp = string;
267
268  status = 0;
269  while (status != DLEOF)
270    {
271      lp = cp;
272      cp = read_token(cp, fname, sizeof(fname), &status);
273
274      if (status != DLNAME && status != DLEND && status != DLEOF)
275	{
276	  char msg[256];
277
278	  XmuSnprintf(msg, sizeof(msg),
279		      "Error parsing displayList at \"%s\"", lp);
280	  XtAppWarning(XtDisplayToApplicationContext(DisplayOfScreen(screen)),
281		       msg);
282	  XawDestroyDisplayList(dlist);
283	  return (NULL);
284	}
285      fp = fname;
286      /*CONSTCOND*/
287      while (1)
288	{
289	  fp = strchr(fp, ':');
290	  if (!fp || (fp == cp || fp[-1] != '\\'))
291	    break;
292	  ++fp;
293	}
294      if (fp)
295	{
296	  XmuSnprintf(cname, fp - fname + 1, fname);
297	  memmove(fname, fp + 1, strlen(fp));
298	  lc = cname[0] ? XawGetDisplayListClass(cname) : xlibc;
299	  if (!lc)
300	    {
301	      char msg[256];
302
303	      XmuSnprintf(msg, sizeof(msg),
304			  "Cannot find displayList class \"%s\"", cname);
305	      XtAppWarning(XtDisplayToApplicationContext
306			   (DisplayOfScreen(screen)), msg);
307	      XawDestroyDisplayList(dlist);
308	      return (NULL);
309	    }
310	}
311      else
312	lc = xlibc;
313
314      if (status == DLEOF && !fname[0])
315	break;
316
317      if ((info = _XawFindDLInfo(lc, fname)) == NULL)
318	{
319	  char msg[256];
320
321	  XmuSnprintf(msg, sizeof(msg),
322		      "Cannot find displayList procedure \"%s\"", fname);
323	  XtAppWarning(XtDisplayToApplicationContext(DisplayOfScreen(screen)),
324		       msg);
325	  XawDestroyDisplayList(dlist);
326	  return (NULL);
327	}
328
329      proc = (XawDLProc *)XtMalloc(sizeof(XawDLProc));
330      proc->qname = info->qname;
331      proc->params = NULL;
332      proc->num_params = 0;
333      proc->proc = info->proc;
334      proc->args = NULL;
335      proc->data = NULL;
336
337      if (!dlist->procs)
338	{
339	  dlist->num_procs = 1;
340	  dlist->procs = (XawDLProc**)XtMalloc(sizeof(XawDLProc*));
341	}
342      else
343	{
344	  ++dlist->num_procs;
345	  dlist->procs = (XawDLProc**)
346	    XtRealloc((char *)dlist->procs, sizeof(XawDLProc*) *
347		      dlist->num_procs);
348	}
349      dlist->procs[dlist->num_procs - 1] = proc;
350
351      while (status != DLEND && status != DLEOF)
352	{
353	  lp = cp;
354	  cp = read_token(cp, aname, sizeof(aname), &status);
355
356	  if (status != DLARG && status != DLEND && status != DLEOF)
357	    {
358	      char msg[256];
359
360	      XmuSnprintf(msg, sizeof(msg),
361			  "Error parsing displayList at \"%s\"", lp);
362	      XtAppWarning(XtDisplayToApplicationContext
363			   (DisplayOfScreen(screen)), msg);
364	      XawDestroyDisplayList(dlist);
365	      return (NULL);
366	    }
367
368	  if (!proc->num_params)
369	    {
370	      proc->num_params = 1;
371	      proc->params = (String *)XtMalloc(sizeof(String));
372	    }
373	  else
374	    {
375	      ++proc->num_params;
376	      proc->params = (String *)XtRealloc((char *)proc->params,
377						 sizeof(String) *
378						 proc->num_params);
379	    }
380	  proc->params[proc->num_params - 1] = XtNewString(aname);
381	}
382
383      /* verify if data is already created for lc */
384      data = NULL;
385      for (i = 0; i < dlist->num_data; i++)
386	if (dlist->data[i]->dlclass == lc)
387	  {
388	    data = dlist->data[i];
389	    break;
390	  }
391
392      if (!data)
393	{
394	  data = (XawDLData *)XtMalloc(sizeof(XawDLData));
395	  data->dlclass = lc;
396	  if (lc->data_init)
397	    data->data = lc->data_init(lc->name, screen, colormap, depth);
398	  else
399	    data->data = NULL;
400
401	  if (!dlist->data)
402	    {
403	      dlist->num_data = 1;
404	      dlist->data = (XawDLData **)XtMalloc(sizeof(XawDLData*));
405	    }
406	  else
407	    {
408	      ++dlist->num_data;
409	      dlist->data = (XawDLData **)
410		XtRealloc((char *)dlist->data, sizeof(XawDLData*) *
411			  dlist->num_data);
412	    }
413	  dlist->data[dlist->num_data - 1] = data;
414	}
415
416      if (lc->args_init)
417	{
418	  proc->args = lc->args_init(fname, proc->params, &proc->num_params,
419				    screen, colormap, depth);
420	  if (proc->args == XAWDL_CONVERT_ERROR)
421	    {
422	      char msg[256];
423
424	      proc->args = NULL;
425	      XmuSnprintf(msg, sizeof(msg),
426			  "Cannot convert arguments to displayList function \"%s\"", fname);
427	      XtAppWarning(XtDisplayToApplicationContext
428			   (DisplayOfScreen(screen)), msg);
429	      XawDestroyDisplayList(dlist);
430	      return (NULL);
431	    }
432	}
433      else
434	proc->args = NULL;
435
436      proc->data = data;
437    }
438
439  dlist->qrep = XrmStringToQuark(string);
440  return (dlist);
441}
442
443String
444XawDisplayListString(_XawDisplayList *dlist)
445{
446  if (!dlist || dlist->qrep == NULLQUARK)
447    return ("");
448  return (XrmQuarkToString(dlist->qrep));
449}
450
451void
452XawDestroyDisplayList(_XawDisplayList *dlist)
453{
454  Cardinal i, j;
455  XawDLProc *proc;
456  XawDLData *data;
457
458  if (!dlist)
459    return;
460
461  for (i = 0; i < dlist->num_procs; i++)
462    {
463      proc = dlist->procs[i];
464      data = proc->data;
465
466      if (data)
467	{
468	  if (data->dlclass->args_destructor)
469	    data->dlclass->args_destructor(DisplayOfScreen(dlist->screen),
470					   XrmQuarkToString(proc->qname),
471					   proc->args,
472					   proc->params, &proc->num_params);
473	  if (data->data)
474	    {
475	      if (data->dlclass->data_destructor)
476		{
477		  data->dlclass
478		    ->data_destructor(DisplayOfScreen(dlist->screen),
479				      data->dlclass->name,  data->data);
480		  data->data = NULL;
481		}
482	    }
483	}
484
485      for (j = 0; j < proc->num_params; j++)
486	XtFree(proc->params[j]);
487      if (proc->num_params)
488	XtFree((char *)proc->params);
489      XtFree((char *)proc);
490    }
491
492  if (dlist->num_procs)
493    XtFree((char *)dlist->procs);
494
495  XtFree((char *)dlist);
496}
497
498/**********************************************************************
499 * If you want to implement your own class of procedures, look at
500 * the code bellow.
501 **********************************************************************/
502/* Start of Implementation of class "xlib" */
503typedef struct _XawXlibData {
504  GC gc;
505  unsigned long mask;
506  XGCValues values;
507  int shape;
508  int mode;
509  char *dashes;
510  /* these fields can be used for optimization, to
511   * avoid unnecessary coordinates recalculation.
512   */
513  Position x, y;
514  Dimension width, height;
515} XawXlibData;
516
517typedef struct _XawDLPosition {
518  Position pos;
519  short denom;
520  Boolean high;
521} XawDLPosition;
522
523typedef struct _XawDLPositionPtr {
524  XawDLPosition *pos;
525  Cardinal num_pos;
526} XawDLPositionPtr;
527
528typedef struct _XawDLArcArgs {
529  XawDLPosition pos[4];
530  int angle1;
531  int angle2;
532} XawDLArcArgs;
533
534typedef struct _XawDLStringArgs {
535  XawDLPosition pos[2];
536  char *string;
537  int length;
538} XawDLStringArgs;
539
540typedef struct _XawDLCopyArgs {
541  XawPixmap *pixmap;
542  XawDLPosition pos[6];
543  int plane;
544} XawDLCopyArgs;
545
546typedef struct _XawDLImageArgs {
547  XawPixmap *pixmap;
548  XawDLPosition pos[4];
549  int depth;
550} XawDLImageArgs;
551
552#define X_ARG(x) (Position)(((x).denom != 0) ?				      \
553		  ((float)XtWidth(w) * ((float)(x).pos / (float)(x).denom)) : \
554		  ((x).high ? XtWidth(w) - (x).pos : (x).pos))
555#define Y_ARG(x) (Position)(((x).denom != 0) ?				      \
556		  ((float)XtHeight(w) * ((float)(x).pos / (float)(x).denom)): \
557		  ((x).high ? XtHeight(w) - (x).pos : (x).pos))
558#define DRECT		0
559#define FRECT		1
560#define LINE		2
561#define GCFG		3
562#define GCBG		4
563#define FPOLY		5
564#define DARC		6
565#define FARC		7
566#define DLINES		8
567#define MASK		9
568#define UMASK		10
569#define LWIDTH		11
570#define POINT		12
571#define POINTS		13
572#define SEGMENTS	14
573#define ARCMODE		15
574#define COORDMODE	16
575#define SHAPEMODE	17
576#define LINESTYLE	18
577#define CAPSTYLE	19
578#define JOINSTYLE	20
579#define FILLSTYLE	21
580#define FILLRULE	22
581#define	TILE		23
582#define STIPPLE		24
583#define TSORIGIN	25
584#define FUNCTION	26
585#define PLANEMASK	27
586#define DSTRING		28
587#define PSTRING		29
588#define FONT		30
589#define DASHES		31
590#define SUBWMODE	32
591#define EXPOSURES	33
592#define CLIPORIGIN	34
593#define CLIPMASK	35
594#define CLIPRECTS	36
595#define COPYAREA	37
596#define COPYPLANE	38
597#define IMAGE		39
598
599static void
600Dl1Point(Widget w, XtPointer args, XtPointer data, int id)
601{
602  XawDLPosition *pos = (XawDLPosition *)args;
603  XawXlibData *xdata = (XawXlibData *)data;
604  Display *display;
605  Window window;
606  Position x, y;
607
608  x = X_ARG(pos[0]);
609  y = Y_ARG(pos[1]);
610
611  if (!XtIsWidget(w))
612    {
613      Position xpad, ypad;
614
615      xpad = XtX(w) + XtBorderWidth(w);
616      ypad = XtY(w) + XtBorderWidth(w);
617      x += xpad;
618      y += ypad;
619      display = XtDisplayOfObject(w);
620      window = XtWindowOfObject(w);
621    }
622  else
623    {
624      display = XtDisplay(w);
625      window = XtWindow(w);
626    }
627
628  if (id == POINT)
629    XDrawPoint(display, window, xdata->gc, x, y);
630  else if (id == TSORIGIN)
631    {
632      xdata->values.ts_x_origin = x;
633      xdata->values.ts_y_origin = y;
634      xdata->mask |= GCTileStipXOrigin | GCTileStipYOrigin;
635      XSetTSOrigin(display, xdata->gc, x, y);
636    }
637  else if (id == CLIPORIGIN)
638    {
639      xdata->values.clip_x_origin = x;
640      xdata->values.clip_y_origin = y;
641      xdata->mask |= GCClipXOrigin | GCClipYOrigin;
642      XSetClipOrigin(display, xdata->gc, x, y);
643    }
644}
645
646static void
647Dl2Points(Widget w, XtPointer args, XtPointer data, int id)
648{
649  XawDLPosition *pos = (XawDLPosition *)args;
650  XawXlibData *xdata = (XawXlibData *)data;
651  Display *display;
652  Window window;
653  Position x1, y1, x2, y2;
654
655  x1 = X_ARG(pos[0]);
656  y1 = Y_ARG(pos[1]);
657  x2 = X_ARG(pos[2]);
658  y2 = Y_ARG(pos[3]);
659
660  if (!XtIsWidget(w))
661    {
662      Position xpad, ypad;
663
664      xpad = XtX(w) + XtBorderWidth(w);
665      ypad = XtY(w) + XtBorderWidth(w);
666      x1 += xpad; y1 += ypad;
667      x2 += xpad; y2 += ypad;
668      display = XtDisplayOfObject(w);
669      window = XtWindowOfObject(w);
670    }
671  else
672    {
673      display = XtDisplay(w);
674      window = XtWindow(w);
675    }
676
677  if (id == DRECT)
678    XDrawRectangle(display, window, xdata->gc, x1, y1, x2 - x1, y2 - y1);
679  else if (id == FRECT)
680    XFillRectangle(display, window, xdata->gc, x1, y1, x2 - x1, y2 - y1);
681  else if (id == LINE)
682    XDrawLine(display, window, xdata->gc, x1, y1, x2, y2);
683}
684
685/* ARGSUSED */
686static void
687DlLine(Widget w, XtPointer args, XtPointer data, XEvent *event, Region region)
688{
689  Dl2Points(w, args, data, LINE);
690}
691
692/* ARGSUSED */
693static void
694DlDrawRectangle(Widget w, XtPointer args, XtPointer data,
695		XEvent *event, Region region)
696{
697  Dl2Points(w, args, data, DRECT);
698}
699
700/* ARGSUSED */
701static void
702DlFillRectangle(Widget w, XtPointer args, XtPointer data,
703		XEvent *event, Region region)
704{
705  Dl2Points(w, args, data, FRECT);
706}
707
708static void
709DlXPoints(Widget w, XtPointer args, XtPointer data, int id)
710{
711  XawDLPositionPtr *pos_ptr = (XawDLPositionPtr *)args;
712  XawXlibData *xdata = (XawXlibData *)data;
713  XawDLPosition *pos;
714  XPoint points_buf[16];
715  XPoint *points;
716  Display *display;
717  Window window;
718  Cardinal num_points, i, j;
719
720  num_points = pos_ptr->num_pos>>1;
721  points = (XPoint *)XawStackAlloc(sizeof(XPoint) * num_points, points_buf);
722
723  for (i = j = 0; i < num_points; i++, j = i << 1)
724    {
725      pos = &pos_ptr->pos[j];
726      points[i].x = X_ARG(pos[0]);
727      points[i].y = Y_ARG(pos[1]);
728    }
729
730  if (!XtIsWidget(w))
731    {
732      Position xpad, ypad;
733
734      xpad = XtX(w) + XtBorderWidth(w);
735      ypad = XtY(w) + XtBorderWidth(w);
736      if (xdata->mode != CoordModePrevious)
737	{
738	  for (i = 0; i < num_points; i++)
739	    {
740	      points[i].x += xpad;
741	      points[i].y += ypad;
742	    }
743	}
744      else
745	{
746	  points[0].x += xpad;
747	  points[0].y += ypad;
748	}
749      display = XtDisplayOfObject(w);
750      window = XtWindowOfObject(w);
751    }
752  else
753    {
754      display = XtDisplay(w);
755      window = XtWindow(w);
756    }
757
758  if (id == FPOLY)
759    XFillPolygon(display, window, xdata->gc, points, num_points,
760		 xdata->shape, xdata->mode);
761  else if (id == DLINES)
762    XDrawLines(display, window, xdata->gc, points, num_points, xdata->mode);
763  else if (id == POINTS)
764    XDrawPoints(display, window, xdata->gc, points, num_points, xdata->mode);
765
766  XawStackFree(points, points_buf);
767}
768
769/* ARGSUSED */
770static void
771DlFillPolygon(Widget w, XtPointer args, XtPointer data,
772	      XEvent *event, Region region)
773{
774  DlXPoints(w, args, data, FPOLY);
775}
776
777/* ARGSUSED */
778static void
779DlDrawLines(Widget w, XtPointer args, XtPointer data,
780	    XEvent *event, Region region)
781{
782  DlXPoints(w, args, data, DLINES);
783}
784
785/* ARGSUSED */
786static void
787DlDrawPoints(Widget w, XtPointer args, XtPointer data,
788	    XEvent *event, Region region)
789{
790  DlXPoints(w, args, data, POINTS);
791}
792
793/* ARGSUSED */
794static void
795DlForeground(Widget w, XtPointer args, XtPointer data,
796	     XEvent *event, Region region)
797{
798  XawXlibData *xdata = (XawXlibData *)data;
799  Pixel foreground = (Pixel)args;
800
801  if (xdata->values.foreground != foreground)
802    {
803      xdata->mask |= GCForeground;
804      xdata->values.foreground = foreground;
805      XSetForeground(XtDisplayOfObject(w), xdata->gc, foreground);
806    }
807}
808
809/* ARGSUSED */
810static void
811DlBackground(Widget w, XtPointer args, XtPointer data,
812	     XEvent *event, Region region)
813{
814  XawXlibData *xdata = (XawXlibData *)data;
815  Pixel background = (Pixel)args;
816
817  if (xdata->values.background != background)
818    {
819      xdata->mask |= GCBackground;
820      xdata->values.background = background;
821      XSetBackground(XtDisplayOfObject(w), xdata->gc, background);
822    }
823}
824
825static void
826DlArc(Widget w, XtPointer args, XtPointer data, Bool fill)
827{
828  XawXlibData *xdata = (XawXlibData *)data;
829  XawDLArcArgs *arc = (XawDLArcArgs *)args;
830  Position x1, y1, x2, y2;
831  Display *display;
832  Window window;
833
834  x1 = X_ARG(arc->pos[0]);
835  y1 = Y_ARG(arc->pos[1]);
836  x2 = X_ARG(arc->pos[2]);
837  y2 = Y_ARG(arc->pos[3]);
838
839  if (!XtIsWidget(w))
840    {
841      Position xpad, ypad;
842
843      xpad = XtX(w) + XtBorderWidth(w);
844      ypad = XtY(w) + XtBorderWidth(w);
845      x1 += xpad;
846      y1 += ypad;
847      x2 += xpad;
848      y2 += ypad;
849      display = XtDisplayOfObject(w);
850      window = XtWindowOfObject(w);
851    }
852  else
853    {
854      display = XtDisplay(w);
855      window = XtWindow(w);
856    }
857
858  if (fill)
859    XFillArc(display, window, xdata->gc, x1, y1, x2 - x1, y2 - y1,
860	     arc->angle1, arc->angle2);
861  else
862    XDrawArc(display, window, xdata->gc, x1, y1, x2 - x1, y2 - y1,
863	     arc->angle1, arc->angle2);
864}
865
866/* ARGSUSED */
867static void
868DlDrawArc(Widget w, XtPointer args, XtPointer data,
869	  XEvent *event, Region region)
870{
871  DlArc(w, args, data, False);
872}
873
874/* ARGSUSED */
875static void
876DlFillArc(Widget w, XtPointer args, XtPointer data,
877	  XEvent *event, Region region)
878{
879  DlArc(w, args, data, True);
880}
881
882/*ARGSUSED*/
883static void
884DlMask(Widget w, XtPointer args, XtPointer data,
885       XEvent *event, Region region)
886{
887  XawXlibData *xdata = (XawXlibData *)data;
888  Display *display = XtDisplayOfObject(w);
889
890  if (region)
891    XSetRegion(display, xdata->gc, region);
892  else if (event)
893    {
894      XRectangle rect;
895
896      rect.x = event->xexpose.x;
897      rect.y = event->xexpose.y;
898      rect.width = event->xexpose.width;
899      rect.height = event->xexpose.height;
900      XSetClipRectangles(display, xdata->gc, 0, 0, &rect, 1, Unsorted);
901    }
902}
903
904/* ARGSUSED */
905static void
906DlUmask(Widget w, XtPointer args, XtPointer data,
907	XEvent *event, Region region)
908{
909  XawXlibData *xdata = (XawXlibData *)data;
910
911  XSetClipMask(XtDisplayOfObject(w), xdata->gc, None);
912}
913
914/* ARGSUSED */
915static void
916DlLineWidth(Widget w, XtPointer args, XtPointer data,
917	    XEvent *event, Region region)
918{
919  XawXlibData *xdata = (XawXlibData *)data;
920  unsigned line_width = (unsigned long)args;
921
922  if (xdata->values.line_width != line_width)
923    {
924      xdata->mask |= GCLineWidth;
925      xdata->values.line_width = line_width;
926      XChangeGC(XtDisplayOfObject(w), xdata->gc, GCLineWidth, &xdata->values);
927    }
928}
929
930/* ARGSUSED */
931static void
932DlDrawPoint(Widget w, XtPointer args, XtPointer data, XEvent *event, Region region)
933{
934  Dl1Point(w, args, data, POINT);
935}
936
937/* ARGSUSED */
938static void
939DlDrawSegments(Widget w, XtPointer args, XtPointer data,
940	       XEvent *event, Region region)
941{
942  XawDLPositionPtr *pos_ptr = (XawDLPositionPtr *)args;
943  XawXlibData *xdata = (XawXlibData *)data;
944  XawDLPosition *pos;
945  XSegment *segments;
946  XSegment segments_buf[8];
947  Display *display;
948  Window window;
949  Cardinal num_segments, i, j;
950
951  num_segments = pos_ptr->num_pos>>2;
952  segments = (XSegment *)XawStackAlloc(sizeof(XSegment) * num_segments, segments_buf);
953
954  for (i = j = 0; i < num_segments; i++, j = i << 2)
955    {
956      pos = &pos_ptr->pos[j];
957      segments[i].x1 = X_ARG(pos[0]);
958      segments[i].y1 = Y_ARG(pos[1]);
959      segments[i].x2 = X_ARG(pos[2]);
960      segments[i].y2 = Y_ARG(pos[3]);
961    }
962
963  if (!XtIsWidget(w))
964    {
965      Position xpad, ypad;
966
967      xpad = XtX(w) + XtBorderWidth(w);
968      ypad = XtY(w) + XtBorderWidth(w);
969      for (i = 0; i < num_segments; i++)
970	{
971	  segments[i].x1 += xpad;
972	  segments[i].y1 += ypad;
973	  segments[i].x2 += xpad;
974	  segments[i].y2 += ypad;
975	}
976      display = XtDisplayOfObject(w);
977      window = XtWindowOfObject(w);
978    }
979  else
980    {
981      display = XtDisplay(w);
982      window = XtWindow(w);
983    }
984
985  XDrawSegments(display, window, xdata->gc, segments, num_segments);
986
987  XawStackFree(segments, segments_buf);
988}
989
990/* ARGSUSED */
991static void
992DlArcMode(Widget w, XtPointer args, XtPointer data,
993	  XEvent *event, Region region)
994{
995  XawXlibData *xdata = (XawXlibData *)data;
996  int arc_mode  = (long)args;
997
998  if (xdata->values.arc_mode != arc_mode)
999    {
1000      xdata->mask |= GCArcMode;
1001      xdata->values.arc_mode = arc_mode;
1002      XSetArcMode(XtDisplayOfObject(w), xdata->gc, arc_mode);
1003    }
1004}
1005
1006/* ARGSUSED */
1007static void
1008DlCoordMode(Widget w, XtPointer args, XtPointer data,
1009	    XEvent *event, Region region)
1010{
1011  XawXlibData *xdata = (XawXlibData *)data;
1012  int mode  = (long)args;
1013
1014  xdata->mode = mode;
1015}
1016
1017/* ARGSUSED */
1018static void
1019DlShapeMode(Widget w, XtPointer args, XtPointer data,
1020	    XEvent *event, Region region)
1021{
1022  XawXlibData *xdata = (XawXlibData *)data;
1023  int shape  = (long)args;
1024
1025  xdata->shape = shape;
1026}
1027
1028/* ARGSUSED */
1029static void
1030DlLineStyle(Widget w, XtPointer args, XtPointer data,
1031	    XEvent *event, Region region)
1032{
1033  XawXlibData *xdata = (XawXlibData *)data;
1034  int line_style = (long)args;
1035
1036  if (xdata->values.line_style != line_style)
1037    {
1038      xdata->mask |= GCLineStyle;
1039      xdata->values.line_style = line_style;
1040      XChangeGC(XtDisplayOfObject(w), xdata->gc, GCLineStyle, &xdata->values);
1041    }
1042}
1043
1044/* ARGSUSED */
1045static void
1046DlCapStyle(Widget w, XtPointer args, XtPointer data,
1047	   XEvent *event, Region region)
1048{
1049  XawXlibData *xdata = (XawXlibData *)data;
1050  int cap_style = (long)args;
1051
1052  if (xdata->values.cap_style != cap_style)
1053    {
1054      xdata->mask |= GCCapStyle;
1055      xdata->values.cap_style = cap_style;
1056      XChangeGC(XtDisplayOfObject(w), xdata->gc, GCCapStyle, &xdata->values);
1057    }
1058}
1059
1060/* ARGSUSED */
1061static void
1062DlJoinStyle(Widget w, XtPointer args, XtPointer data,
1063	    XEvent *event, Region region)
1064{
1065  XawXlibData *xdata = (XawXlibData *)data;
1066  int join_style = (long)args;
1067
1068  if (xdata->values.join_style != join_style)
1069    {
1070      xdata->mask |= GCJoinStyle;
1071      xdata->values.join_style = join_style;
1072      XChangeGC(XtDisplayOfObject(w), xdata->gc, GCJoinStyle, &xdata->values);
1073    }
1074}
1075
1076/* ARGSUSED */
1077static void
1078DlFillStyle(Widget w, XtPointer args, XtPointer data,
1079	    XEvent *event, Region region)
1080{
1081  XawXlibData *xdata = (XawXlibData *)data;
1082  int fill_style = (long)args;
1083
1084  if (xdata->values.fill_style != fill_style)
1085    {
1086      xdata->mask |= GCFillStyle;
1087      xdata->values.fill_style = fill_style;
1088      XSetFillStyle(XtDisplayOfObject(w), xdata->gc, fill_style);
1089    }
1090}
1091
1092/* ARGSUSED */
1093static void
1094DlFillRule(Widget w, XtPointer args, XtPointer data,
1095	   XEvent *event, Region region)
1096{
1097  XawXlibData *xdata = (XawXlibData *)data;
1098  int fill_rule = (long)args;
1099
1100  if (xdata->values.fill_rule != fill_rule)
1101    {
1102      xdata->mask |= GCFillRule;
1103      xdata->values.fill_rule = fill_rule;
1104      XSetFillRule(XtDisplayOfObject(w), xdata->gc, fill_rule);
1105    }
1106}
1107
1108/* ARGSUSED */
1109static void
1110DlTile(Widget w, XtPointer args, XtPointer data,
1111       XEvent *event, Region region)
1112{
1113  XawXlibData *xdata = (XawXlibData *)data;
1114  XawPixmap *pixmap = (XawPixmap *)args;
1115
1116  if (pixmap && xdata->values.tile != pixmap->pixmap)
1117    {
1118      xdata->mask |= GCTile;
1119      xdata->values.tile = pixmap->pixmap;
1120      XSetTile(XtDisplayOfObject(w), xdata->gc, xdata->values.tile);
1121    }
1122}
1123
1124/* ARGSUSED */
1125static void
1126DlStipple(Widget w, XtPointer args, XtPointer data,
1127	  XEvent *event, Region region)
1128{
1129  XawXlibData *xdata = (XawXlibData *)data;
1130  XawPixmap *pixmap = (XawPixmap *)args;
1131
1132  if (pixmap && xdata->values.stipple != pixmap->pixmap)
1133    {
1134      xdata->mask |= GCStipple;
1135      xdata->values.stipple = pixmap->pixmap;
1136      XSetStipple(XtDisplayOfObject(w), xdata->gc, xdata->values.stipple);
1137    }
1138}
1139
1140/* ARGSUSED */
1141static void
1142DlTSOrigin(Widget w, XtPointer args, XtPointer data, XEvent *event, Region region)
1143{
1144  Dl1Point(w, args, data, TSORIGIN);
1145}
1146
1147/* ARGSUSED */
1148static void
1149DlFunction(Widget w, XtPointer args, XtPointer data,
1150	   XEvent *event, Region region)
1151{
1152  XawXlibData *xdata = (XawXlibData *)data;
1153  int function = (long)args;
1154
1155  if (function != xdata->values.function)
1156    {
1157      xdata->mask |= GCFunction;
1158      xdata->values.function = function;
1159      XSetFunction(XtDisplayOfObject(w), xdata->gc, function);
1160    }
1161}
1162
1163/* ARGSUSED */
1164static void
1165DlPlaneMask(Widget w, XtPointer args, XtPointer data,
1166	    XEvent *event, Region region)
1167{
1168  XawXlibData *xdata = (XawXlibData *)data;
1169  unsigned long plane_mask = (unsigned long)args;
1170
1171  if (xdata->values.plane_mask != plane_mask)
1172    {
1173      xdata->mask |= GCPlaneMask;
1174      xdata->values.plane_mask = plane_mask;
1175      XSetPlaneMask(XtDisplayOfObject(w), xdata->gc, plane_mask);
1176    }
1177}
1178
1179static void
1180DlString(Widget w, XtPointer args, XtPointer data, Bool image)
1181{
1182  XawDLStringArgs *string = (XawDLStringArgs *)args;
1183  XawXlibData *xdata = (XawXlibData *)data;
1184  Display *display;
1185  Window window;
1186  Position x, y;
1187
1188  x = X_ARG(string->pos[0]);
1189  y = Y_ARG(string->pos[1]);
1190
1191  if (!XtIsWidget(w))
1192    {
1193      Position xpad, ypad;
1194
1195      xpad = XtX(w) + XtBorderWidth(w);
1196      ypad = XtY(w) + XtBorderWidth(w);
1197      x += xpad;
1198      y += ypad;
1199      display = XtDisplayOfObject(w);
1200      window = XtWindowOfObject(w);
1201    }
1202  else
1203    {
1204      display = XtDisplay(w);
1205      window = XtWindow(w);
1206    }
1207
1208  if (image)
1209    XDrawImageString(display, window, xdata->gc, x, y, string->string, string->length);
1210  else
1211    XDrawString(display, window, xdata->gc, x, y, string->string, string->length);
1212}
1213
1214/* ARGSUSED */
1215static void
1216DlDrawString(Widget w, XtPointer args, XtPointer data,
1217	     XEvent *event, Region region)
1218{
1219  DlString(w, args, data, False);
1220}
1221
1222/* ARGSUSED */
1223static void
1224DlPaintString(Widget w, XtPointer args, XtPointer data,
1225	      XEvent *event, Region region)
1226{
1227  DlString(w, args, data, True);
1228}
1229
1230/* ARGSUSED */
1231static void
1232DlFont(Widget w, XtPointer args, XtPointer data,
1233       XEvent *event, Region region)
1234{
1235  XawXlibData *xdata = (XawXlibData *)data;
1236  Font font = (Font)args;
1237
1238  if (xdata->values.font != font)
1239    {
1240      xdata->mask |= GCFont;
1241      xdata->values.font = font;
1242      XSetFont(XtDisplayOfObject(w), xdata->gc, font);
1243    }
1244}
1245
1246/* ARGSUSED */
1247static void
1248DlDashes(Widget w, XtPointer args, XtPointer data,
1249	 XEvent *event, Region region)
1250{
1251  XawXlibData *xdata = (XawXlibData *)data;
1252  char *dashes = args;
1253
1254  if (xdata->dashes != dashes)
1255    {
1256      xdata->mask |= GCDashOffset | GCDashList;
1257      xdata->dashes = dashes;
1258      XSetDashes(XtDisplayOfObject(w), xdata->gc, 0, dashes + 1, *dashes);
1259    }
1260}
1261
1262/* ARGSUSED */
1263static void
1264DlSubwindowMode(Widget w, XtPointer args, XtPointer data,
1265		XEvent *event, Region region)
1266{
1267  XawXlibData *xdata = (XawXlibData *)data;
1268  int subwindow_mode = (long)args;
1269
1270  if (xdata->values.subwindow_mode != subwindow_mode)
1271    {
1272      xdata->mask |= GCSubwindowMode;
1273      xdata->values.subwindow_mode = subwindow_mode;
1274      XSetSubwindowMode(XtDisplayOfObject(w), xdata->gc, subwindow_mode);
1275    }
1276}
1277
1278/* ARGSUSED */
1279static void
1280DlExposures(Widget w, XtPointer args, XtPointer data,
1281	    XEvent *event, Region region)
1282{
1283  XawXlibData *xdata = (XawXlibData *)data;
1284  Bool graphics_exposures = (Bool)(long)args;
1285
1286  if (xdata->values.graphics_exposures != graphics_exposures)
1287    {
1288      xdata->mask |= GCGraphicsExposures;
1289      xdata->values.graphics_exposures = graphics_exposures;
1290      XSetGraphicsExposures(XtDisplayOfObject(w), xdata->gc, graphics_exposures);
1291    }
1292}
1293
1294/* ARGSUSED */
1295static void
1296DlClipOrigin(Widget w, XtPointer args, XtPointer data, XEvent *event, Region region)
1297{
1298  Dl1Point(w, args, data, CLIPORIGIN);
1299}
1300
1301/* ARGSUSED */
1302static void
1303DlClipMask(Widget w, XtPointer args, XtPointer data,
1304	   XEvent *event, Region region)
1305{
1306  XawXlibData *xdata = (XawXlibData *)data;
1307  XawPixmap *pixmap = (XawPixmap *)args;
1308  Pixmap clip_mask;
1309
1310  if (pixmap)
1311    clip_mask = pixmap->mask ? pixmap->mask : pixmap->pixmap;
1312  else
1313    clip_mask = None;
1314
1315  if (xdata->values.clip_mask != clip_mask)
1316    {
1317      xdata->mask |= GCClipMask;
1318      XSetClipMask(XtDisplayOfObject(w), xdata->gc, clip_mask);
1319    }
1320}
1321
1322/* ARGSUSED */
1323static void
1324DlClipRectangles(Widget w, XtPointer args, XtPointer data,
1325		 XEvent *event, Region region)
1326{
1327  XawDLPositionPtr *pos_ptr = (XawDLPositionPtr *)args;
1328  XawXlibData *xdata = (XawXlibData *)data;
1329  XawDLPosition *pos;
1330  XRectangle *rects;
1331  XRectangle rects_buf[8];
1332  Position x1, y1, x2, y2;
1333  Cardinal num_rects, i, j;
1334
1335  num_rects = pos_ptr->num_pos>>2;
1336  rects = (XRectangle *)XawStackAlloc(sizeof(XRectangle) * num_rects, rects_buf);
1337
1338  for (i = j = 0; i < num_rects; i++, j = i << 2)
1339    {
1340      pos = &pos_ptr->pos[j];
1341      x1 = X_ARG(pos[0]);
1342      y1 = Y_ARG(pos[1]);
1343      x2 = X_ARG(pos[2]);
1344      y2 = Y_ARG(pos[3]);
1345      rects[i].x = XawMin(x1, x2);
1346      rects[i].y = XawMin(y1, y2);
1347      rects[i].width = XawMax(x1, x2) - rects[i].x;
1348      rects[i].height = XawMax(y1, y2) - rects[i].y;
1349    }
1350
1351  if (!XtIsWidget(w))
1352    {
1353      Position xpad, ypad;
1354
1355      xpad = XtX(w) + XtBorderWidth(w);
1356      ypad = XtY(w) + XtBorderWidth(w);
1357      for (i = 0; i < num_rects; i++)
1358	{
1359	  rects[i].x += xpad;
1360	  rects[i].y += ypad;
1361	}
1362    }
1363
1364  XSetClipRectangles(XtDisplayOfObject(w), xdata->gc, 0, 0, rects, num_rects, Unsorted);
1365
1366  XawStackFree(rects, rects_buf);
1367}
1368
1369static void
1370DlCopy(Widget w, XtPointer args, XtPointer data, Bool plane)
1371{
1372  XawDLCopyArgs *copy = (XawDLCopyArgs *)args;
1373  XawXlibData *xdata = (XawXlibData *)data;
1374  int src_x, src_y, dst_x, dst_y, width, height, tmp1, tmp2;
1375
1376  tmp1 = X_ARG(copy->pos[0]);
1377  tmp2 = X_ARG(copy->pos[2]);
1378  dst_x = XawMin(tmp1, tmp2);
1379  width = XawMax(tmp1, tmp2) - dst_x;
1380
1381  tmp1 = Y_ARG(copy->pos[1]);
1382  tmp2 = Y_ARG(copy->pos[3]);
1383  dst_y = XawMin(tmp1, tmp2);
1384  height = XawMax(tmp1, tmp2) - dst_y;
1385
1386  src_x = X_ARG(copy->pos[4]);
1387  src_y = Y_ARG(copy->pos[5]);
1388
1389  if (width <= 0)
1390    {
1391      if (copy->pixmap)
1392	width = copy->pixmap->width;
1393      else
1394	{
1395	  if ((width = XtWidth(w) - src_x) < 0)
1396	    width = 0;
1397	}
1398    }
1399  if (height <= 0)
1400    {
1401      if (copy->pixmap)
1402	height = copy->pixmap->height;
1403      else
1404	{
1405	  if ((height = XtHeight(w) - src_y) < 0)
1406	    height = 0;
1407	}
1408    }
1409
1410  if (!XtIsWidget(w))
1411    {
1412      Position xpad, ypad;
1413
1414      xpad = XtX(w) + XtBorderWidth(w);
1415      ypad = XtY(w) + XtBorderWidth(w);
1416      src_x += xpad;
1417      src_y += ypad;
1418      dst_x += xpad;
1419      dst_y += ypad;
1420    }
1421
1422  if (plane)
1423    XCopyPlane(XtDisplayOfObject(w), XtWindowOfObject(w),
1424	       copy->pixmap ? copy->pixmap->pixmap : XtWindowOfObject(w),
1425	       xdata->gc, src_x, src_y, width, height, dst_x, dst_y,
1426	       copy->plane ? copy->plane : 1);
1427  else
1428    XCopyArea(XtDisplayOfObject(w),
1429	      copy->pixmap ? copy->pixmap->pixmap : XtWindowOfObject(w),
1430	      XtWindowOfObject(w), xdata->gc, src_x, src_y, width, height, dst_x, dst_y);
1431}
1432
1433/* ARGSUSED */
1434static void
1435DlCopyArea(Widget w, XtPointer args, XtPointer data,
1436	   XEvent *event, Region region)
1437{
1438  DlCopy(w, args, data, False);
1439}
1440
1441/* ARGSUSED */
1442static void
1443DlCopyPlane(Widget w, XtPointer args, XtPointer data,
1444	    XEvent *event, Region region)
1445{
1446  DlCopy(w, args, data, True);
1447}
1448
1449/*ARGSUSED*/
1450/* Note:
1451 *	  This function is destructive if you set the ts_x_origin, ts_y_origin,
1452 *	and/or clip-mask. It is meant to be the only function used in a display
1453 *	list. If you need to use other functions (and those values), be sure to
1454 *	set them after calling this function.
1455 */
1456static void
1457DlImage(Widget w, XtPointer args, XtPointer data, XEvent *event, Region region)
1458{
1459  XawDLImageArgs *image = (XawDLImageArgs *)args;
1460  XawXlibData *xdata = (XawXlibData *)data;
1461  int x, y, xs, ys, xe, ye, width, height;
1462  Display *display;
1463  Window window;
1464
1465  width = image->pixmap->width;
1466  height = image->pixmap->height;
1467  xs = X_ARG(image->pos[0]);
1468  ys = Y_ARG(image->pos[1]);
1469  xe = X_ARG(image->pos[2]);
1470  ye = Y_ARG(image->pos[3]);
1471
1472  if (xe <= 0)
1473    xe = xs + width;
1474  if (ye <= 0)
1475    ye = ys + height;
1476
1477  if (!XtIsWidget(w))
1478    {
1479      Position xpad, ypad;
1480
1481      xpad = XtX(w) + XtBorderWidth(w);
1482      ypad = XtY(w) + XtBorderWidth(w);
1483      xe += xpad;
1484      ye += ypad;
1485      xe += xpad;
1486      ye += ypad;
1487      display = XtDisplayOfObject(w);
1488      window = XtWindowOfObject(w);
1489    }
1490  else
1491    {
1492      display = XtDisplay(w);
1493      window = XtWindow(w);
1494    }
1495
1496  for (y = ys; y < ye; y += height)
1497    for (x = xs; x < xe; x += width)
1498      {
1499	XSetClipOrigin(display, xdata->gc, x, y);
1500	if (image->pixmap->mask)
1501	  XSetClipMask(display, xdata->gc, image->pixmap->mask);
1502	if (image->depth == 1)
1503	  XCopyPlane(display, image->pixmap->pixmap, window, xdata->gc,
1504		     0, 0, XawMin(width, xe - x), XawMin(height, ye - y),
1505		     x, y, 1L);
1506	else
1507	  XCopyArea(display, image->pixmap->pixmap, window, xdata->gc, 0, 0,
1508		     XawMin(width, xe - x), XawMin(height, ye - y), x, y);
1509      }
1510
1511  XSetClipMask(display, xdata->gc, None);
1512}
1513
1514typedef struct _Dl_init Dl_init;
1515struct _Dl_init {
1516  String name;
1517  XawDisplayListProc proc;
1518  Cardinal id;
1519};
1520
1521static Dl_init dl_init[] =
1522{
1523  {"arc-mode",		DlArcMode,		ARCMODE},
1524  {"background",	DlBackground,		GCBG},
1525  {"bg",		DlBackground,		GCBG},
1526  {"cap-style",		DlCapStyle,		CAPSTYLE},
1527  {"clip-mask",		DlClipMask,		CLIPMASK},
1528  {"clip-origin",	DlClipOrigin,		CLIPORIGIN},
1529  {"clip-rectangles",	DlClipRectangles,	CLIPRECTS},
1530  {"clip-rects",	DlClipRectangles,	CLIPRECTS},
1531  {"coord-mode",	DlCoordMode,		COORDMODE},
1532  {"copy-area",		DlCopyArea,		COPYAREA},
1533  {"copy-plane",	DlCopyPlane,		COPYPLANE},
1534  {"dashes",		DlDashes,		DASHES},
1535  {"draw-arc",		DlDrawArc,		DARC},
1536  {"draw-line",		DlLine,			LINE},
1537  {"draw-lines",	DlDrawLines,		DLINES},
1538  {"draw-point",	DlDrawPoint,		POINT},
1539  {"draw-points",	DlDrawPoints,		POINTS},
1540  {"draw-rect",		DlDrawRectangle,	DRECT},
1541  {"draw-rectangle",	DlDrawRectangle,	DRECT},
1542  {"draw-segments",	DlDrawSegments,		SEGMENTS},
1543  {"draw-string",	DlDrawString,		DSTRING},
1544  {"exposures",		DlExposures,		EXPOSURES},
1545  {"fg",		DlForeground,		GCFG},
1546  {"fill-arc",		DlFillArc,		FARC},
1547  {"fill-poly",		DlFillPolygon,		FPOLY},
1548  {"fill-polygon",	DlFillPolygon,		FPOLY},
1549  {"fill-rect",		DlFillRectangle,	FRECT},
1550  {"fill-rectangle",	DlFillRectangle,	FRECT},
1551  {"fill-rule",		DlFillRule,		FILLRULE},
1552  {"fill-style",	DlFillStyle,		FILLSTYLE},
1553  {"font",		DlFont,			FONT},
1554  {"foreground",	DlForeground,		GCFG},
1555  {"function",		DlFunction,		FUNCTION},
1556  {"image",		DlImage,		IMAGE},
1557  {"join-style",	DlJoinStyle,		JOINSTYLE},
1558  {"line",		DlLine,			LINE},
1559  {"line-style",	DlLineStyle,		LINESTYLE},
1560  {"line-width",	DlLineWidth,		LWIDTH},
1561  {"lines",		DlDrawLines,		DLINES},
1562  {"mask",		DlMask,			MASK},
1563  {"paint-string",	DlPaintString,		PSTRING},
1564  {"plane-mask",	DlPlaneMask,		PLANEMASK},
1565  {"point",		DlDrawPoint,		POINT},
1566  {"points",		DlDrawPoints,		POINTS},
1567  {"segments",		DlDrawSegments,		SEGMENTS},
1568  {"shape-mode",	DlShapeMode,		SHAPEMODE},
1569  {"stipple",		DlStipple,		STIPPLE},
1570  {"subwindow-mode",	DlSubwindowMode,	SUBWMODE},
1571  {"tile",		DlTile,			TILE},
1572  {"ts-origin",		DlTSOrigin,		TSORIGIN},
1573  {"umask",		DlUmask,		UMASK},
1574};
1575
1576void
1577XawDisplayListInitialize(void)
1578{
1579  static Bool first_time = True;
1580  XawDLClass *lc;
1581  Cardinal i;
1582
1583  if (first_time == False)
1584    return;
1585
1586  first_time = False;
1587
1588  lc = XawCreateDisplayListClass(xlib,
1589				 _Xaw_Xlib_ArgsInitProc,
1590				 _Xaw_Xlib_ArgsDestructor,
1591				 _Xaw_Xlib_DataInitProc,
1592				 _Xaw_Xlib_DataDestructor);
1593  for (i = 0; i < sizeof(dl_init) / sizeof(dl_init[0]); i++)
1594    (void)XawDeclareDisplayListProc(lc, dl_init[i].name, dl_init[i].proc);
1595}
1596
1597static int
1598bcmp_cvt_proc(register _Xconst void *string,
1599	      register _Xconst void *dlinfo)
1600{
1601  return (strcmp((String)string, ((Dl_init*)dlinfo)->name));
1602}
1603
1604static long
1605read_int(char *cp, char **cpp)
1606{
1607  long value = 0, sign = 1;
1608
1609  if (*cp == '-')
1610    {
1611      sign = -1;
1612      ++cp;
1613    }
1614  else if (*cp == '+')
1615    ++cp;
1616  value = 0;
1617  while (*cp >= '0' && *cp <= '9')
1618    {
1619      value = value * 10 + *cp - '0';
1620      ++cp;
1621    }
1622  if (cpp)
1623    *cpp = cp;
1624  return (value * sign);
1625}
1626
1627static void
1628read_position(char *arg, XawDLPosition *pos)
1629{
1630  int ch;
1631  char *str = arg;
1632
1633  ch = *str;
1634  if (ch == '-' || ch == '+')
1635    {
1636      ++str;
1637      if (ch == '-')
1638	pos->high = True;
1639      pos->pos = read_int(str, NULL);
1640    }
1641  else if (isdigit(ch))
1642    {
1643      pos->pos = read_int(str, &str);
1644      ch = *str++;
1645      if (ch == '/')
1646	pos->denom = read_int(str, NULL);
1647    }
1648}
1649
1650/* ARGSUSED */
1651static void *
1652_Xaw_Xlib_ArgsInitProc(String proc_name, String *params, Cardinal *num_params,
1653		       Screen *screen, Colormap colormap, int depth)
1654{
1655  Cardinal id, i;
1656  Dl_init *init;
1657  void *retval = XAWDL_CONVERT_ERROR;
1658
1659  init = (Dl_init *)bsearch(proc_name, dl_init,
1660			    sizeof(dl_init) / sizeof(dl_init[0]),
1661			    sizeof(dl_init[0]),
1662			    bcmp_cvt_proc);
1663
1664  id = init->id;
1665
1666  switch (id)
1667    {
1668    case LINE:
1669    case DRECT:
1670    case FRECT:
1671      if (*num_params == 4)
1672	{
1673	  XawDLPosition *pos = (XawDLPosition *)XtCalloc(1, sizeof(XawDLPosition) * 4);
1674
1675	  for (i = 0; i < 4; i++)
1676	    read_position(params[i], &pos[i]);
1677	  retval = (void *)pos;
1678	}
1679      break;
1680    case POINT:
1681    case TSORIGIN:
1682    case CLIPORIGIN:
1683      if (*num_params == 2)
1684	{
1685	  XawDLPosition *pos = (XawDLPosition *)XtCalloc(1, sizeof(XawDLPosition) * 2);
1686
1687	  read_position(params[0], &pos[0]);
1688	  read_position(params[1], &pos[1]);
1689	  retval = (void *)pos;
1690	}
1691      break;
1692    case DLINES:
1693    case FPOLY:
1694    case POINTS:
1695      if (*num_params >= 4 && !(*num_params & 1))
1696	{
1697	  XawDLPositionPtr *pos = XtNew(XawDLPositionPtr);
1698
1699	  pos->pos = (XawDLPosition *)XtCalloc(1, sizeof(XawDLPosition) *
1700					       *num_params);
1701	  pos->num_pos = *num_params;
1702	  for (i = 0; i < *num_params; i++)
1703	    read_position(params[i], &pos->pos[i]);
1704	  retval = (void *)pos;
1705	}
1706      break;
1707    case SEGMENTS:
1708    case CLIPRECTS:
1709      if (*num_params >= 4 && !(*num_params % 4))
1710	{
1711	  XawDLPositionPtr *pos = XtNew(XawDLPositionPtr);
1712
1713	  pos->pos = (XawDLPosition *)XtCalloc(1, sizeof(XawDLPosition) *
1714					       *num_params);
1715	  pos->num_pos = *num_params;
1716	  for (i = 0; i < *num_params; i++)
1717	    read_position(params[i], &pos->pos[i]);
1718	  retval = (void *)pos;
1719	}
1720      break;
1721    case DARC:
1722    case FARC:
1723      if (*num_params >= 4 && *num_params <= 6)
1724	{
1725	  XawDLArcArgs *args = (XawDLArcArgs *)XtCalloc(1, sizeof(XawDLArcArgs));
1726
1727	  args->angle1 = 0;
1728	  args->angle2 = 360;
1729	  for (i = 0; i < 4; i++)
1730	    read_position(params[i], &args->pos[i]);
1731	  if (*num_params > 4)
1732	    args->angle1 = read_int(params[4], NULL);
1733	  if (*num_params > 5)
1734	    args->angle2 = read_int(params[5], NULL);
1735	  args->angle1 *= 64;
1736	  args->angle2 *= 64;
1737	  retval = (void *)args;
1738	}
1739      break;
1740    case GCFG:
1741    case GCBG:
1742      {
1743	XColor xcolor;
1744
1745	if (*num_params == 1 &&
1746	    XAllocNamedColor(DisplayOfScreen(screen), colormap,
1747			     params[0], &xcolor, &xcolor))
1748	  retval = (void *)xcolor.pixel;
1749      } break;
1750    case MASK:
1751    case UMASK:
1752      if (*num_params == 0)
1753	retval = NULL;
1754      break;
1755    case LWIDTH:
1756      if (*num_params == 1)
1757	retval = (void *)read_int(params[0], NULL);
1758      break;
1759    case ARCMODE:
1760      if (*num_params == 1)
1761	{
1762	  if (XmuCompareISOLatin1(params[0], "pieslice") == 0)
1763	    retval = (void *)ArcPieSlice;
1764	  else if (XmuCompareISOLatin1(params[0], "chord") == 0)
1765	    retval = (void *)ArcChord;
1766	}
1767      break;
1768    case COORDMODE:
1769      if (*num_params == 1)
1770	{
1771	  if (XmuCompareISOLatin1(params[0], "origin") == 0)
1772	    retval = (void *)CoordModeOrigin;
1773	  else if (XmuCompareISOLatin1(params[0], "previous") == 0)
1774	    retval = (void *)CoordModePrevious;
1775	}
1776      break;
1777    case SHAPEMODE:
1778      if (*num_params == 1)
1779	{
1780	  if (XmuCompareISOLatin1(params[0], "complex") == 0)
1781	    retval = (void *)Complex;
1782	  else if (XmuCompareISOLatin1(params[0], "convex") == 0)
1783	    retval = (void *)Convex;
1784	  else if (XmuCompareISOLatin1(params[0], "nonconvex") == 0)
1785	    retval = (void *)Nonconvex;
1786	}
1787      break;
1788    case LINESTYLE:
1789      if (*num_params == 1)
1790	{
1791	  if (XmuCompareISOLatin1(params[0], "solid") == 0)
1792	    retval = (void *)LineSolid;
1793	  else if (XmuCompareISOLatin1(params[0], "onoffdash") == 0)
1794	    retval = (void *)LineOnOffDash;
1795	  else if (XmuCompareISOLatin1(params[0], "doubledash") == 0)
1796	    retval = (void *)LineDoubleDash;
1797	}
1798      break;
1799    case CAPSTYLE:
1800      if (*num_params == 1)
1801	{
1802	  if (XmuCompareISOLatin1(params[0], "notlast") == 0)
1803	    retval = (void *)CapNotLast;
1804	  else if (XmuCompareISOLatin1(params[0], "butt") == 0)
1805	    retval = (void *)CapButt;
1806	  else if (XmuCompareISOLatin1(params[0], "round") == 0)
1807	    retval = (void *)CapRound;
1808	  else if (XmuCompareISOLatin1(params[0], "projecting") == 0)
1809	    retval = (void *)CapProjecting;
1810	}
1811      break;
1812    case JOINSTYLE:
1813      if (*num_params == 1)
1814	{
1815	  if (XmuCompareISOLatin1(params[0], "miter") == 0)
1816	    retval = (void *)JoinMiter;
1817	  else if (XmuCompareISOLatin1(params[0], "round") == 0)
1818	    retval = (void *)JoinRound;
1819	  else if (XmuCompareISOLatin1(params[0], "bevel") == 0)
1820	    retval = (void *)JoinBevel;
1821	}
1822      break;
1823    case FILLSTYLE:
1824      if (*num_params == 1)
1825	{
1826	  if (*num_params && XmuCompareISOLatin1(params[0], "solid") == 0)
1827	    retval = (void *)FillSolid;
1828	  else if (*num_params && XmuCompareISOLatin1(params[0], "tiled") == 0)
1829	    retval = (void *)FillTiled;
1830	  else if (*num_params && XmuCompareISOLatin1(params[0], "stippled") == 0)
1831	    retval = (void *)FillStippled;
1832	  else if (*num_params && XmuCompareISOLatin1(params[0], "opaquestippled") == 0)
1833	    retval = (void *)FillOpaqueStippled;
1834	}
1835      break;
1836    case FILLRULE:
1837      if (*num_params == 1)
1838	{
1839	  if (XmuCompareISOLatin1(params[0], "evenodd") == 0)
1840	    retval = (void *)EvenOddRule;
1841	  else if (XmuCompareISOLatin1(params[0], "winding") == 0)
1842	    retval = (void *)WindingRule;
1843	}
1844      break;
1845    case TILE:
1846      if (*num_params == 1)
1847	retval = (void *)XawLoadPixmap(params[0], screen, colormap, depth);
1848      if (retval == NULL)
1849	{
1850	  XtDisplayStringConversionWarning(DisplayOfScreen(screen), (String)params[0],
1851					   XtRPixmap);
1852	  retval = XAWDL_CONVERT_ERROR;
1853	}
1854      break;
1855    case STIPPLE:
1856      if (*num_params == 1)
1857	retval = (void *)XawLoadPixmap(params[0], screen, colormap, 1);
1858      if (retval == NULL)
1859	{
1860	  XtDisplayStringConversionWarning(DisplayOfScreen(screen), (String)params[0],
1861					   XtRBitmap);
1862	  retval = XAWDL_CONVERT_ERROR;
1863	}
1864      break;
1865    case FUNCTION:
1866      if (*num_params == 1)
1867	{
1868	  if (XmuCompareISOLatin1(params[0], "set") == 0)
1869	    retval = (void *)GXset;
1870	  else if (XmuCompareISOLatin1(params[0], "clear") == 0)
1871	    retval = (void *)GXclear;
1872	  else if (XmuCompareISOLatin1(params[0], "and") == 0)
1873	    retval = (void *)GXand;
1874	  else if (XmuCompareISOLatin1(params[0], "andreverse") == 0)
1875	    retval = (void *)GXandReverse;
1876	  else if (XmuCompareISOLatin1(params[0], "copy") == 0)
1877	    retval = (void *)GXcopy;
1878	  else if (XmuCompareISOLatin1(params[0], "andinverted") == 0)
1879	    retval = (void *)GXandInverted;
1880	  else if (XmuCompareISOLatin1(params[0], "noop") == 0)
1881	    retval = (void *)GXnoop;
1882	  else if (XmuCompareISOLatin1(params[0], "xor") == 0)
1883	    retval = (void *)GXxor;
1884	  else if (XmuCompareISOLatin1(params[0], "or") == 0)
1885	    retval = (void *)GXor;
1886	  else if (XmuCompareISOLatin1(params[0], "nor") == 0)
1887	    retval = (void *)GXnor;
1888	  else if (XmuCompareISOLatin1(params[0], "equiv") == 0)
1889	    retval = (void *)GXequiv;
1890	  else if (XmuCompareISOLatin1(params[0], "invert") == 0)
1891	    retval = (void *)GXinvert;
1892	  else if (XmuCompareISOLatin1(params[0], "orreverse") == 0)
1893	    retval = (void *)GXorReverse;
1894	  else if (XmuCompareISOLatin1(params[0], "copyinverted") == 0)
1895	    retval = (void *)GXcopyInverted;
1896	  else if (XmuCompareISOLatin1(params[0], "nand") == 0)
1897	    retval = (void *)GXnand;
1898	}
1899      break;
1900    case PLANEMASK:
1901      if (*num_params == 1)
1902	retval = (void *)read_int(params[0], NULL);
1903      break;
1904    case DSTRING:
1905    case PSTRING:
1906      if (*num_params == 3)
1907	{
1908	  XawDLStringArgs *string = (XawDLStringArgs *)
1909		XtCalloc(1, sizeof(XawDLStringArgs));
1910
1911	  read_position(params[0], &string->pos[0]);
1912	  read_position(params[1], &string->pos[1]);
1913	  string->string = XtNewString(params[2]);
1914	  string->length = strlen(string->string);
1915	  retval = string;
1916	}
1917      break;
1918    case FONT:
1919      if (*num_params == 1)
1920	retval = (void *)XLoadFont(DisplayOfScreen(screen), params[0]);
1921      break;
1922    case DASHES:
1923      if (*num_params && *num_params < 127)
1924	{
1925	  char *dashes;
1926
1927	  dashes = XtMalloc(*num_params + 1);
1928
1929	  for (i = 0; i < *num_params; i++)
1930	    dashes[i + 1] = read_int(params[i], NULL);
1931	  *dashes = *num_params;
1932	  retval = dashes;
1933	}
1934      break;
1935    case SUBWMODE:
1936      if (*num_params == 1)
1937	{
1938	  if (XmuCompareISOLatin1(params[0], "clipbychildren") == 0)
1939	    retval = (void *)ClipByChildren;
1940	  else if (XmuCompareISOLatin1(params[0], "includeinferiors") == 0)
1941	    retval = (void *)IncludeInferiors;
1942	}
1943      break;
1944    case EXPOSURES:
1945      if (*num_params == 1)
1946	{
1947	  if (isdigit(params[0][0]) || params[0][0] == '+' || params[0][0] == '-')
1948	    retval = (void *)read_int(params[0], NULL);
1949	  else if (XmuCompareISOLatin1(params[0], "true") == 0 ||
1950	    XmuCompareISOLatin1(params[0], "on") == 0)
1951	    retval = (void *)True;
1952	  else if (XmuCompareISOLatin1(params[0], "false") == 0 ||
1953	    XmuCompareISOLatin1(params[0], "off") == 0)
1954	    retval = (void *)False;
1955	}
1956      break;
1957    case CLIPMASK:
1958      if (*num_params == 1)
1959	retval = (void *)XawLoadPixmap(params[0], screen, colormap, 1);
1960      if (retval == NULL)
1961	{
1962	  retval = XAWDL_CONVERT_ERROR;
1963	  XtDisplayStringConversionWarning(DisplayOfScreen(screen), (String)params[0],
1964					   XtRPixmap);
1965	}
1966      break;
1967    case COPYAREA:
1968    case COPYPLANE:
1969      if (*num_params > 2 && *num_params <= 7 + (id == COPYPLANE))
1970	{
1971	  XawDLCopyArgs *args = (XawDLCopyArgs *)
1972		XtCalloc(1, sizeof(XawDLCopyArgs));
1973
1974	  retval = args;
1975	  if (params[0][0] == '\0' || strcmp(params[0], ".") == 0)
1976	    args->pixmap = NULL;
1977	  else
1978	   {
1979	     args->pixmap = XawLoadPixmap(params[0], screen, colormap, id == COPYPLANE ? 1 : depth);
1980	     if (args->pixmap == NULL)
1981	      {
1982		XtDisplayStringConversionWarning(DisplayOfScreen(screen), (String)params[0],
1983						 XtRBitmap);
1984		retval = XAWDL_CONVERT_ERROR;
1985		XtFree((char *)args);
1986	      }
1987	  }
1988	  if (retval != XAWDL_CONVERT_ERROR)
1989	    {
1990	      for (i = 1; i < *num_params && i < 7; i++)
1991		read_position(params[i], &args->pos[i - 1]);
1992	      if (*num_params > 7)
1993		args->plane = read_int(params[7], NULL);
1994	    }
1995	}
1996      break;
1997    case IMAGE:
1998      if (*num_params > 2 && *num_params <= 7)
1999	{
2000	  XawDLImageArgs *args = (XawDLImageArgs *)
2001		XtCalloc(1, sizeof(XawDLImageArgs));
2002
2003	  retval = args;
2004	  args->pixmap = XawLoadPixmap(params[0], screen, colormap, depth);
2005	  if (args->pixmap == NULL)
2006	    {
2007	      XtDisplayStringConversionWarning(DisplayOfScreen(screen),
2008					       (String)params[0], XtRPixmap);
2009	      retval = XAWDL_CONVERT_ERROR;
2010	      XtFree((char *)args);
2011	    }
2012	  else
2013	    {
2014	      args->depth = depth;
2015	      for (i = 1; i < *num_params && i < 5; i++)
2016		read_position(params[i], &args->pos[i - 1]);
2017	    }
2018	}
2019      break;
2020    }
2021
2022  return (retval);
2023}
2024
2025/* ARGSUSED */
2026static void *
2027_Xaw_Xlib_DataInitProc(String class_name,
2028		       Screen *screen, Colormap colormap, int depth)
2029{
2030  XawXlibData *data;
2031  Window tmp_win;
2032
2033  data = (XawXlibData *)XtMalloc(sizeof(XawXlibData));
2034
2035  tmp_win = XCreateWindow(DisplayOfScreen(screen),
2036			  RootWindowOfScreen(screen),
2037			  0, 0, 1, 1, 1, depth,
2038			  InputOutput, (Visual *)CopyFromParent, 0, NULL);
2039  data->mask = 0;
2040  data->gc = XCreateGC(DisplayOfScreen(screen), tmp_win, 0, &data->values);
2041  XDestroyWindow(DisplayOfScreen(screen), tmp_win);
2042  data->shape = Complex;
2043  data->mode = CoordModeOrigin;
2044  data->dashes = NULL;
2045
2046  return ((void *)data);
2047}
2048
2049/* ARGSUSED */
2050static void
2051_Xaw_Xlib_ArgsDestructor(Display *display, String proc_name, XtPointer args,
2052			 String *params, Cardinal *num_params)
2053{
2054  Cardinal id;
2055  Dl_init *init;
2056
2057  init = (Dl_init *)bsearch(proc_name, dl_init,
2058			    sizeof(dl_init) / sizeof(dl_init[0]),
2059			    sizeof(dl_init[0]),
2060			    bcmp_cvt_proc);
2061
2062  id = init->id;
2063
2064  switch (id)
2065    {
2066    case LINE:
2067    case DRECT:
2068    case FRECT:
2069    case DARC:
2070    case FARC:
2071    case POINT:
2072    case TSORIGIN:
2073    case DASHES:
2074    case CLIPORIGIN:
2075    case COPYAREA:
2076    case COPYPLANE:
2077    case IMAGE:
2078      XtFree(args);
2079      break;
2080    case DSTRING:
2081    case PSTRING:
2082      {
2083	XawDLStringArgs *string = (XawDLStringArgs *)args;
2084	XtFree(string->string);
2085	XtFree(args);
2086      } break;
2087    case DLINES:
2088    case FPOLY:
2089    case POINTS:
2090    case SEGMENTS:
2091    case CLIPRECTS:
2092      {
2093	XawDLPositionPtr *ptr = (XawDLPositionPtr *)args;
2094
2095	XtFree((char *)ptr->pos);
2096	XtFree(args);
2097      } break;
2098    }
2099}
2100
2101/* ARGSUSED */
2102static void
2103_Xaw_Xlib_DataDestructor(Display *display, String class_name, XtPointer data)
2104{
2105  if (data)
2106    {
2107      XawXlibData *xdata = (XawXlibData *)data;
2108
2109      XFreeGC(display, xdata->gc);
2110      if (xdata->dashes)
2111	XtFree(xdata->dashes);
2112      XtFree((char *)data);
2113    }
2114}
2115
2116/* Start of DLInfo Management Functions */
2117static int
2118qcmp_dlist_info(register _Xconst void *left, register _Xconst void *right)
2119{
2120  return (strcmp((*(XawDLInfo **)left)->name, (*(XawDLInfo **)right)->name));
2121}
2122
2123Bool XawDeclareDisplayListProc(XawDLClass *lc, String name,
2124				  XawDisplayListProc proc)
2125{
2126  XawDLInfo *info;
2127
2128  if (!lc || !proc || !name || name[0] == '\0')
2129    return (False);
2130
2131  if ((info = _XawFindDLInfo(lc, name)) != NULL)
2132    /* Since the data structures to the displayList classes are(should be)
2133     * opaque, it is not a good idea to allow overriding a displayList
2134     * procedure; it's better to choose another name or class name!
2135     */
2136    return (False);
2137
2138  info = (XawDLInfo *)XtMalloc(sizeof(XawDLInfo));
2139  info->name = XtNewString(name);
2140  info->qname = XrmStringToQuark(info->name);
2141  info->proc = proc;
2142
2143  if (!lc->num_infos)
2144    {
2145      lc->num_infos = 1;
2146      lc->infos = (XawDLInfo **)XtMalloc(sizeof(XawDLInfo*));
2147    }
2148  else
2149    {
2150      ++lc->num_infos;
2151      lc->infos = (XawDLInfo **)
2152	XtRealloc((char *)lc->infos, sizeof(XawDLInfo*) * lc->num_infos);
2153    }
2154  lc->infos[lc->num_infos - 1] = info;
2155
2156  if (lc->num_infos > 1)
2157    qsort(lc->infos, lc->num_infos, sizeof(XawDLInfo*), qcmp_dlist_info);
2158
2159  return (True);
2160}
2161
2162static int
2163bcmp_dlist_info(register _Xconst void *string,
2164		register _Xconst void *dlinfo)
2165{
2166  return (strcmp((String)string, (*(XawDLClass **)dlinfo)->name));
2167}
2168
2169static XawDLInfo *
2170_XawFindDLInfo(XawDLClass *lc, String name)
2171{
2172  XawDLInfo **info;
2173
2174  if (!lc->infos)
2175    return (NULL);
2176
2177  info = (XawDLInfo **)bsearch(name, lc->infos, lc->num_infos,
2178			       sizeof(XawDLInfo*), bcmp_dlist_info);
2179
2180  return (info ? *info : NULL);
2181}
2182
2183/* Start of DLClass Management Functions */
2184XawDLClass *
2185XawGetDisplayListClass(String name)
2186{
2187  return (_XawFindDLClass(name));
2188}
2189
2190static int
2191qcmp_dlist_class(register _Xconst void *left, register _Xconst void *right)
2192{
2193  return (strcmp((*(XawDLClass **)left)->name, (*(XawDLClass **)right)->name));
2194}
2195
2196XawDLClass *
2197XawCreateDisplayListClass(String name,
2198			  XawDLArgsInitProc args_init,
2199			  XawDLArgsDestructor args_destructor,
2200			  XawDLDataInitProc data_init,
2201			  XawDLDataDestructor data_destructor)
2202{
2203  XawDLClass *lc;
2204
2205  if (!name || name[0] == '\0')
2206    return (NULL);
2207
2208  lc = (XawDLClass *)XtMalloc(sizeof(XawDLClass));
2209  lc->name = XtNewString(name);
2210  lc->infos = NULL;
2211  lc->num_infos = 0;
2212  lc->args_init = args_init;
2213  lc->args_destructor = args_destructor;
2214  lc->data_init = data_init;
2215  lc->data_destructor = data_destructor;
2216
2217  if (!classes)
2218    {
2219      num_classes = 1;
2220      classes = (XawDLClass **)XtMalloc(sizeof(XawDLClass));
2221    }
2222  else
2223    {
2224      ++num_classes;
2225      classes = (XawDLClass **)XtRealloc((char *)classes,
2226					 sizeof(XawDLClass) * num_classes);
2227    }
2228  classes[num_classes - 1] = lc;
2229
2230  if (num_classes > 1)
2231    qsort(&classes[0], num_classes, sizeof(XawDLClass*), qcmp_dlist_class);
2232
2233  return (lc);
2234}
2235
2236static int
2237bcmp_dlist_class(register _Xconst void *string,
2238		 register _Xconst void *dlist)
2239{
2240  return (strcmp((String)string, (*(XawDLClass **)dlist)->name));
2241}
2242
2243static XawDLClass *
2244_XawFindDLClass(String name)
2245{
2246  XawDLClass **lc;
2247
2248  if (!classes)
2249    return (NULL);
2250
2251  lc = (XawDLClass **)bsearch(name, &classes[0], num_classes,
2252			      sizeof(XawDLClass*), bcmp_dlist_class);
2253
2254  return (lc ? *lc : NULL);
2255}
2256
2257#endif /* OLDXAW */
2258