1/*
2** planemask.c
3**
4** How to make a widget to choose a planemask.
5**
6** NOTE: This file uses static variables.  Therefore, trying to use these
7**       functions to create more than one of these planemask choice things
8**       will fail in a big way.
9*/
10
11#include <X11/Xos.h>
12#include <stdio.h>
13#include <stdlib.h>
14#include <X11/Intrinsic.h>
15#include <X11/StringDefs.h>
16#include <X11/Xaw/Form.h>
17#include <X11/Xaw/Label.h>
18#include <X11/Xaw/Toggle.h>
19#include "xgc.h"
20
21static void choose_plane(Widget, caddr_t, caddr_t);
22
23static unsigned long planemask;
24static Widget *pm;
25
26/* create_planemask_choice(w)
27** -------------------------
28** Inside w (a form widget), creates a bunch of little toggle buttons
29** in a row, representing the planemask.  There's also a label so
30** the user knows what it is.
31*/
32
33void
34create_planemask_choice(Widget w)
35{
36  /* callback list for the toggle widgets */
37  static XtCallbackRec callbacklist[] = {
38    {(XtCallbackProc) choose_plane, NULL},
39    {NULL,                          NULL}
40  };
41
42  /* ArgList for the label */
43  static Arg labelargs[] = {
44    {XtNborderWidth,     (XtArgVal) 0},
45    {XtNjustify,         (XtArgVal) XtJustifyRight},
46    {XtNvertDistance,    (XtArgVal) 4}
47  };
48
49  /* ArgList for the toggles */
50  static Arg pmargs[] = {
51    {XtNcallback,          (XtArgVal) NULL},
52    {XtNhorizDistance,     (XtArgVal) NULL},
53    {XtNfromHoriz,         (XtArgVal) NULL},
54    {XtNwidth,             (XtArgVal) 10},
55    {XtNheight,            (XtArgVal) 10},
56    {XtNhighlightThickness,(XtArgVal) 1},
57    {XtNstate,             (XtArgVal) True},
58    {XtNlabel,             (XtArgVal) ""}
59  };
60
61  static Widget label;		/* the label, of course */
62  static int *pminfo;		/* contains integers saying which bit
63				   a particular button is; sent to
64				   choose_plane to tell it which
65				   bit got changed */
66
67  int i, num_planes;
68
69  char buf[40];
70  char name[20];
71
72  num_planes = PlanesOfScreen(X.scr);
73
74  planemask = (1<<num_planes)-1;
75  snprintf(buf, sizeof buf, "planemask %lu",planemask);
76  interpret(buf);
77
78  /* Allocate space for stuff that we don't know the size of yet */
79
80  pm = (Widget *) malloc(num_planes * sizeof(Widget));
81  pminfo = (int *) malloc(num_planes * sizeof(int));
82
83  /* Make the label widget */
84
85  label = XtCreateManagedWidget("planemask",labelWidgetClass,w,
86				labelargs,XtNumber(labelargs));
87
88  pmargs[0].value = (XtArgVal) callbacklist;
89
90  for (i=0;i<num_planes;++i) {	/* go through all the buttons */
91    if (i==0) {			/* offset the first one from the label */
92      pmargs[1].value = (XtArgVal) 10;
93      pmargs[2].value = (XtArgVal) label;
94    }
95    else {			/* put it directly to the right of the
96				   last one, no space in between */
97      pmargs[1].value = (XtArgVal) -1;
98      pmargs[2].value = (XtArgVal) pm[i-1];
99    }
100
101    /* set its original state depending on the state of that bit
102    ** of the planemask */
103
104    if (planemask & 1<<i)
105      pmargs[6].value = (XtArgVal) True;
106    else
107      pmargs[6].value = (XtArgVal) False;
108
109    snprintf(name, sizeof name, "planemask%d",i);
110
111    pminfo[i] = i;		/* which bit we're on; this is needed in
112				   choose_plane (the callback) */
113    callbacklist[0].closure = (caddr_t) &pminfo[i];
114
115    pm[i] = XtCreateManagedWidget(name,toggleWidgetClass,w,
116				  pmargs,XtNumber(pmargs));
117  }
118}
119
120/* choose_plane(w,closure,call_data)
121** ------------------------------------
122** This function is called when the user toggles a toggle widget.  It
123** makes the appropriate change to the planemask and sends it off
124** to interpret().
125** Funny args are because it's a callback.
126*/
127
128/*ARGSUSED*/
129static void
130choose_plane(Widget w, caddr_t closure, caddr_t call_data)
131{
132  int num;			/* what number button it is */
133  Boolean on;			/* is it currently on or off? */
134
135  char buf[80];			/* string to send to interpret() */
136
137  static Arg args[] = {
138    {XtNstate,    (XtArgVal) NULL}
139  };
140
141  /* set up ArgList so that 'on' will contain the state */
142  args[0].value = (XtArgVal) &on;
143
144  num = * (int *) closure;	/* we put it here back in the last function */
145  XtGetValues(w,args,XtNumber(args));
146
147  /* Modify the planemask appropriately */
148
149  if (on)
150    planemask |= 1<<num;
151  else
152    planemask &= ~(1<<num);
153
154  (void) snprintf(buf, sizeof buf, "planemask %lu\n",planemask);
155  interpret(buf);
156}
157
158/* update_planemask(mask)
159** ----------------------
160** Updates the display of the planemask so that it corresponds to mask.
161*/
162
163void
164update_planemask(long mask)
165{
166  int i;			/* counter */
167  static Arg maskargs[] = {	/* ArgList for setting toggle state */
168    {XtNstate,     (XtArgVal) NULL}
169  };
170
171  /* First set the internal representation */
172
173  planemask = mask;
174
175  for (i = 0; i < PlanesOfScreen(X.scr); ++i) {
176    if (planemask & 1<<i) {        /* if it's set, make it look that way */
177      maskargs[0].value = (XtArgVal) True;
178    }
179    else {
180      maskargs[0].value = (XtArgVal) False;
181    }
182
183    XtSetValues(pm[i],maskargs,XtNumber(maskargs));
184  }
185}
186