summaryrefslogtreecommitdiff
path: root/choice.c
blob: d77006347681d0f8a8bfdeb3c9a535ca6626a6d8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
/*
** xgc
**
** choice.c
**
** All the generic stuff for dealing with choice widgets.
*/

#include <stdio.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Xaw/Form.h>
#include <X11/Xaw/Label.h>
#include <X11/Xaw/Toggle.h>

#include "xgc.h"

static void print_text_to_buffer(Widget, caddr_t, caddr_t);

/* create_choice(w,info)
** ---------------------
** What a choice widget is:  A collection of toggle buttons placed inside
** a form widget.  Exactly one of these toggle buttons can be "on" at
** any given time;  the rest are "off".  "On" toggle buttons have
** the foreground and background colors reversed.
** Also, specifically because it comes in handy in xgc, choosing one
** of the buttons causes a string associated with it to be printed out
** (and interpreted).  Half of the string is global to the whole form
** and the other half is local to each button.
**
** For example, pressing the "xor" button in the "function" form would
** cause xgc to interpret the string "function xor", thus changing the
** function in the GC to xor.
**
** There's also a label widget to the left of that mess, with an
** incredibly descriptive title.
**
** create_choice() makes one.
**
** w is the form widget (already created) into which we will place the
** toggle buttons.  info contains lots of useful information, such
** as the names of the buttons and their strings (see xgc.h).
*/

ChoiceDesc *
create_choice(Widget w, XgcStuff *info)
{
  ChoiceDesc *choice;		/* What we will return.  Contains
				** Widget ID's of the label and toggles. */
  int i;			/* Counter */
  char *text;			/* Text to be interpreted when the
				** toggle widget is selected. */

  /* ArgList for the label widget */
  static Arg labelargs[] = {
    {XtNborderWidth,  (XtArgVal) 0},
    {XtNjustify,      (XtArgVal) XtJustifyRight},
    {XtNvertDistance, (XtArgVal) 4}
  };

  /* ArgList for the toggle widgets */
  static Arg toggleargs[] = {
    {XtNfromHoriz,     (XtArgVal) NULL},
    {XtNfromVert,      (XtArgVal) NULL},
    {XtNhorizDistance, (XtArgVal) 4},
    {XtNvertDistance,  (XtArgVal) 4},
    {XtNradioGroup,    (XtArgVal) NULL},
    {XtNcallback,      (XtArgVal) NULL}
  };

  /* Callback list for the toggle widgets */
  static XtCallbackRec callbacklist[] = {
    {(XtCallbackProc)  print_text_to_buffer, NULL},
    {NULL,                                   NULL}
  };

  /* Allocate space for the widgets and initialize choice */
  choice = (ChoiceDesc *) XtMalloc(sizeof(ChoiceDesc));
  choice->widgets = (WidgetList) XtMalloc(sizeof(Widget) *
					  info->choice.num_toggles);
  choice->size = info->choice.num_toggles;
  choice->label = XtCreateManagedWidget(info->choice.name,labelWidgetClass,w,
					labelargs,XtNumber(labelargs));

  /* set up the toggle widgets */
  toggleargs[5].value = (XtArgVal) callbacklist;
  for (i = 0; i < info->choice.num_toggles; ++i) {
    if (i == 0) {
      /* the upper left toggle; put it next to the label
       and don't worry about radio groups */
      toggleargs[0].value = (XtArgVal) choice->label;
      toggleargs[1].value = (XtArgVal) NULL;
      toggleargs[2].value = (XtArgVal) 10;
      toggleargs[3].value = (XtArgVal) 4;
      toggleargs[4].value = (XtArgVal) NULL;
    }
    else {
      toggleargs[4].value = (XtArgVal) choice->widgets[0];
				/* are we starting a new row? */
      if (info->choice.columns > 0 &&
	  i > 1 &&
	  (i % (info->choice.columns) == 0)) {
	toggleargs[0].value = (XtArgVal) choice->label;
	/* under the appropriate toggle */
	toggleargs[1].value = (XtArgVal) choice->widgets[i - info->choice.columns];
	toggleargs[2].value = (XtArgVal) 10;
	toggleargs[3].value = (XtArgVal) 4;
      }
      else {			/* we're in the middle of a row */
	/* to the right of the previous toggle */
	toggleargs[0].value = (XtArgVal) choice->widgets[i - 1];
	toggleargs[1].value = (XtArgVal) NULL;
	toggleargs[2].value = (XtArgVal) -1; /* overlapping slightly */
	toggleargs[3].value = (XtArgVal) 4;
      }

      if (info->choice.columns > 0 &&
	  i >= info->choice.columns) {
	/* correct vertical spacing */
	toggleargs[1].value = (XtArgVal) choice->widgets[i - info->choice.columns];
	toggleargs[3].value = (XtArgVal) -1;
      }
    }

    /* Put the correct stuff in the text field */
    text = (char *) XtMalloc((unsigned) (strlen(info->choice.text) +
					 strlen((info->data)[i].text) + 3));
    strcpy(text, info->choice.text);
    strcat(text, " ");
    strcat(text, (info->data)[i].text);
    strcat(text, "\n");
    callbacklist[0].closure = (caddr_t) text;

    /* Create it finally */
    choice->widgets[i] = XtCreateManagedWidget((info->data[i]).name,
					       toggleWidgetClass,
					       w,
					       toggleargs,
					       XtNumber(toggleargs));
  }

  /* The toggle widgets have all been created;
  ** now make the all the same width if that's
  ** what we want to do.                    */

  if (info->choice.columns > 0) {
    Dimension maxwidth = 0;	/* maximum width we've found */
    Dimension width;		/* width of the current widget */
    static Arg args[] = {	/* for getting and setting the width */
      {XtNwidth,    (XtArgVal) NULL}
    };

    args[0].value = (XtArgVal) &width;

    /* Find the maximum width of any toggle widget */
    for (i = 0; i < info->choice.num_toggles; ++i) {
      XtGetValues(choice->widgets[i],args,1);
      maxwidth = max(maxwidth,width);
    }

    /* Now set them all to that width */
    args[0].value = (XtArgVal) maxwidth;
    for (i = 0; i < info->choice.num_toggles; ++i)
      XtSetValues(choice->widgets[i],args,1);
  }

  /* return the list of toggles that were just created */
  return (choice);
}



/* select_button(choice,togglenum)
** -------------------------------
** "Selects" the togglenumth toggle widget in the choice layout
** represented by choice.  It simply turns the widget on, as if the
** user had selected it, without calling any callbacks.  It's used
** to give feedback when reading from a script.
*/

void
select_button(ChoiceDesc *choice, int togglenum)
{
  static Arg toggleargs[] = {
    {XtNstate,   (XtArgVal) True}
  };

  XtSetValues(choice->widgets[togglenum],toggleargs,XtNumber(toggleargs));
}

/* line_up_labels(descs,numdescs)
** ------------------------------
** descs represents a bunch of choice layouts (numdescs is the size of
** descs).  This function sets each label in descs to the same width,
** thus making them line up nicely since they're all on the left margin.
*/

void
line_up_labels(ChoiceDesc *descs[], int numdescs)
{
  int i;			/* counter */
  Dimension width;		/* current width */
  Dimension maxwidth = (Dimension) 0; /* max width found */

  static Arg widthargs[] = {
    {XtNwidth,     (XtArgVal) NULL }
  };

  widthargs[0].value = (XtArgVal) &width;

  /* Find the maximum width */
  for (i = 0; i < numdescs; ++i) {
    XtGetValues(descs[i]->label, widthargs, XtNumber(widthargs));
    maxwidth = max(maxwidth,width);
  }

  /* Set all labels to that width */
  widthargs[0].value = (XtArgVal) maxwidth;
  for (i = 0; i < numdescs; ++i) {
    XtSetValues(descs[i]->label, widthargs, XtNumber(widthargs));
  }
}

/* choose_defaults(descs,numdescs)
** -------------------------------
** descs represents a bunch of choice layouts (numdescs is the size of
** descs).  This function goes through all of descs and selects the
** appropriate toggle widget for each one.  This includes calling
** the callbacks associated with that widget.
**
** This function ends up initializing both the screen and the GC, and
** ensures that they are consistent.
*/

void
choose_defaults(ChoiceDesc *descs[], int numdescs)
{
  int i;			/* which choice layout */
  int j;			/* which toggle within it */

  for (i = 0; i < numdescs; ++i) {
    j = 0;
    if (i == 0)
      j = 3;
    select_button(descs[i],j);
    XtCallCallbacks(descs[i]->widgets[j], XtNcallback, (caddr_t) NULL);
  }
}


/* print_text_to_buffer(w,closure,call_data)
** -----------------------------------------
** This is also in the list of callbacks for the toggle buttons in a
** choice widget.  It sends the string contained in closure (which
** was set way back in create_choice()) over to interpret(), which
** decides what to do with it.
*/

/*ARGSUSED*/
static void
print_text_to_buffer(
    Widget  w,
    caddr_t closure,           /* contains the string */
    caddr_t call_data)
{
  interpret((char *) closure);          /* Gee, that was easy */
}