1fd7d9bd3Smrg/*
2fd7d9bd3Smrg** xgc
3fd7d9bd3Smrg**
4fd7d9bd3Smrg** choice.c
5fd7d9bd3Smrg**
6fd7d9bd3Smrg** All the generic stuff for dealing with choice widgets.
7fd7d9bd3Smrg*/
8fd7d9bd3Smrg
9fd7d9bd3Smrg#include <stdio.h>
10fd7d9bd3Smrg#include <X11/Intrinsic.h>
11fd7d9bd3Smrg#include <X11/StringDefs.h>
12fd7d9bd3Smrg#include <X11/Xaw/Form.h>
13fd7d9bd3Smrg#include <X11/Xaw/Label.h>
14fd7d9bd3Smrg#include <X11/Xaw/Toggle.h>
15fd7d9bd3Smrg
16fd7d9bd3Smrg#include "xgc.h"
17fd7d9bd3Smrg
18fd7d9bd3Smrgstatic void print_text_to_buffer(Widget, caddr_t, caddr_t);
19fd7d9bd3Smrg
20fd7d9bd3Smrg/* create_choice(w,info)
21fd7d9bd3Smrg** ---------------------
22fd7d9bd3Smrg** What a choice widget is:  A collection of toggle buttons placed inside
23fd7d9bd3Smrg** a form widget.  Exactly one of these toggle buttons can be "on" at
24fd7d9bd3Smrg** any given time;  the rest are "off".  "On" toggle buttons have
25fd7d9bd3Smrg** the foreground and background colors reversed.
26fd7d9bd3Smrg** Also, specifically because it comes in handy in xgc, choosing one
27fd7d9bd3Smrg** of the buttons causes a string associated with it to be printed out
28fd7d9bd3Smrg** (and interpreted).  Half of the string is global to the whole form
29fd7d9bd3Smrg** and the other half is local to each button.
30fd7d9bd3Smrg**
31fd7d9bd3Smrg** For example, pressing the "xor" button in the "function" form would
32fd7d9bd3Smrg** cause xgc to interpret the string "function xor", thus changing the
33fd7d9bd3Smrg** function in the GC to xor.
34fd7d9bd3Smrg**
35fd7d9bd3Smrg** There's also a label widget to the left of that mess, with an
36fd7d9bd3Smrg** incredibly descriptive title.
37fd7d9bd3Smrg**
38fd7d9bd3Smrg** create_choice() makes one.
39fd7d9bd3Smrg**
40fd7d9bd3Smrg** w is the form widget (already created) into which we will place the
41fd7d9bd3Smrg** toggle buttons.  info contains lots of useful information, such
42fd7d9bd3Smrg** as the names of the buttons and their strings (see xgc.h).
43fd7d9bd3Smrg*/
44fd7d9bd3Smrg
45fd7d9bd3SmrgChoiceDesc *
46fd7d9bd3Smrgcreate_choice(Widget w, XgcStuff *info)
47fd7d9bd3Smrg{
48fd7d9bd3Smrg  ChoiceDesc *choice;		/* What we will return.  Contains
49fd7d9bd3Smrg				** Widget ID's of the label and toggles. */
50fd7d9bd3Smrg  int i;			/* Counter */
51fd7d9bd3Smrg  char *text;			/* Text to be interpreted when the
52fd7d9bd3Smrg				** toggle widget is selected. */
53fd7d9bd3Smrg
54fd7d9bd3Smrg  /* ArgList for the label widget */
55e53c48bfSmrg  static Arg labelargs[] = {
56e53c48bfSmrg    {XtNborderWidth,  (XtArgVal) 0},
57fd7d9bd3Smrg    {XtNjustify,      (XtArgVal) XtJustifyRight},
58fd7d9bd3Smrg    {XtNvertDistance, (XtArgVal) 4}
59fd7d9bd3Smrg  };
60fd7d9bd3Smrg
61fd7d9bd3Smrg  /* ArgList for the toggle widgets */
62fd7d9bd3Smrg  static Arg toggleargs[] = {
63fd7d9bd3Smrg    {XtNfromHoriz,     (XtArgVal) NULL},
64fd7d9bd3Smrg    {XtNfromVert,      (XtArgVal) NULL},
65fd7d9bd3Smrg    {XtNhorizDistance, (XtArgVal) 4},
66fd7d9bd3Smrg    {XtNvertDistance,  (XtArgVal) 4},
67fd7d9bd3Smrg    {XtNradioGroup,    (XtArgVal) NULL},
68fd7d9bd3Smrg    {XtNcallback,      (XtArgVal) NULL}
69fd7d9bd3Smrg  };
70fd7d9bd3Smrg
71fd7d9bd3Smrg  /* Callback list for the toggle widgets */
72fd7d9bd3Smrg  static XtCallbackRec callbacklist[] = {
73fd7d9bd3Smrg    {(XtCallbackProc)  print_text_to_buffer, NULL},
74fd7d9bd3Smrg    {NULL,                                   NULL}
75fd7d9bd3Smrg  };
76fd7d9bd3Smrg
77fd7d9bd3Smrg  /* Allocate space for the widgets and initialize choice */
78fd7d9bd3Smrg  choice = (ChoiceDesc *) XtMalloc(sizeof(ChoiceDesc));
79e53c48bfSmrg  choice->widgets = (WidgetList) XtMalloc(sizeof(Widget) *
80fd7d9bd3Smrg					  info->choice.num_toggles);
81fd7d9bd3Smrg  choice->size = info->choice.num_toggles;
82fd7d9bd3Smrg  choice->label = XtCreateManagedWidget(info->choice.name,labelWidgetClass,w,
83fd7d9bd3Smrg					labelargs,XtNumber(labelargs));
84fd7d9bd3Smrg
85fd7d9bd3Smrg  /* set up the toggle widgets */
86fd7d9bd3Smrg  toggleargs[5].value = (XtArgVal) callbacklist;
87fd7d9bd3Smrg  for (i = 0; i < info->choice.num_toggles; ++i) {
88fd7d9bd3Smrg    if (i == 0) {
89fd7d9bd3Smrg      /* the upper left toggle; put it next to the label
90fd7d9bd3Smrg       and don't worry about radio groups */
91fd7d9bd3Smrg      toggleargs[0].value = (XtArgVal) choice->label;
92fd7d9bd3Smrg      toggleargs[1].value = (XtArgVal) NULL;
93fd7d9bd3Smrg      toggleargs[2].value = (XtArgVal) 10;
94fd7d9bd3Smrg      toggleargs[3].value = (XtArgVal) 4;
95fd7d9bd3Smrg      toggleargs[4].value = (XtArgVal) NULL;
96fd7d9bd3Smrg    }
97fd7d9bd3Smrg    else {
98fd7d9bd3Smrg      toggleargs[4].value = (XtArgVal) choice->widgets[0];
99fd7d9bd3Smrg				/* are we starting a new row? */
100e53c48bfSmrg      if (info->choice.columns > 0 &&
101e53c48bfSmrg	  i > 1 &&
102fd7d9bd3Smrg	  (i % (info->choice.columns) == 0)) {
103fd7d9bd3Smrg	toggleargs[0].value = (XtArgVal) choice->label;
104fd7d9bd3Smrg	/* under the appropriate toggle */
105fd7d9bd3Smrg	toggleargs[1].value = (XtArgVal) choice->widgets[i - info->choice.columns];
106fd7d9bd3Smrg	toggleargs[2].value = (XtArgVal) 10;
107fd7d9bd3Smrg	toggleargs[3].value = (XtArgVal) 4;
108fd7d9bd3Smrg      }
109fd7d9bd3Smrg      else {			/* we're in the middle of a row */
110fd7d9bd3Smrg	/* to the right of the previous toggle */
111fd7d9bd3Smrg	toggleargs[0].value = (XtArgVal) choice->widgets[i - 1];
112fd7d9bd3Smrg	toggleargs[1].value = (XtArgVal) NULL;
113fd7d9bd3Smrg	toggleargs[2].value = (XtArgVal) -1; /* overlapping slightly */
114fd7d9bd3Smrg	toggleargs[3].value = (XtArgVal) 4;
115fd7d9bd3Smrg      }
116fd7d9bd3Smrg
117fd7d9bd3Smrg      if (info->choice.columns > 0 &&
118fd7d9bd3Smrg	  i >= info->choice.columns) {
119fd7d9bd3Smrg	/* correct vertical spacing */
120fd7d9bd3Smrg	toggleargs[1].value = (XtArgVal) choice->widgets[i - info->choice.columns];
121fd7d9bd3Smrg	toggleargs[3].value = (XtArgVal) -1;
122fd7d9bd3Smrg      }
123fd7d9bd3Smrg    }
124fd7d9bd3Smrg
125fd7d9bd3Smrg    /* Put the correct stuff in the text field */
126fd7d9bd3Smrg    text = (char *) XtMalloc((unsigned) (strlen(info->choice.text) +
127fd7d9bd3Smrg					 strlen((info->data)[i].text) + 3));
128fd7d9bd3Smrg    strcpy(text, info->choice.text);
129fd7d9bd3Smrg    strcat(text, " ");
130fd7d9bd3Smrg    strcat(text, (info->data)[i].text);
131fd7d9bd3Smrg    strcat(text, "\n");
132fd7d9bd3Smrg    callbacklist[0].closure = (caddr_t) text;
133e53c48bfSmrg
134fd7d9bd3Smrg    /* Create it finally */
135e53c48bfSmrg    choice->widgets[i] = XtCreateManagedWidget((info->data[i]).name,
136fd7d9bd3Smrg					       toggleWidgetClass,
137fd7d9bd3Smrg					       w,
138fd7d9bd3Smrg					       toggleargs,
139fd7d9bd3Smrg					       XtNumber(toggleargs));
140fd7d9bd3Smrg  }
141e53c48bfSmrg
142fd7d9bd3Smrg  /* The toggle widgets have all been created;
143fd7d9bd3Smrg  ** now make the all the same width if that's
144fd7d9bd3Smrg  ** what we want to do.                    */
145fd7d9bd3Smrg
146fd7d9bd3Smrg  if (info->choice.columns > 0) {
147fd7d9bd3Smrg    Dimension maxwidth = 0;	/* maximum width we've found */
148fd7d9bd3Smrg    Dimension width;		/* width of the current widget */
149fd7d9bd3Smrg    static Arg args[] = {	/* for getting and setting the width */
150fd7d9bd3Smrg      {XtNwidth,    (XtArgVal) NULL}
151fd7d9bd3Smrg    };
152fd7d9bd3Smrg
153fd7d9bd3Smrg    args[0].value = (XtArgVal) &width;
154fd7d9bd3Smrg
155fd7d9bd3Smrg    /* Find the maximum width of any toggle widget */
156fd7d9bd3Smrg    for (i = 0; i < info->choice.num_toggles; ++i) {
157fd7d9bd3Smrg      XtGetValues(choice->widgets[i],args,1);
158fd7d9bd3Smrg      maxwidth = max(maxwidth,width);
159fd7d9bd3Smrg    }
160fd7d9bd3Smrg
161fd7d9bd3Smrg    /* Now set them all to that width */
162fd7d9bd3Smrg    args[0].value = (XtArgVal) maxwidth;
163fd7d9bd3Smrg    for (i = 0; i < info->choice.num_toggles; ++i)
164fd7d9bd3Smrg      XtSetValues(choice->widgets[i],args,1);
165fd7d9bd3Smrg  }
166fd7d9bd3Smrg
167fd7d9bd3Smrg  /* return the list of toggles that were just created */
168fd7d9bd3Smrg  return (choice);
169fd7d9bd3Smrg}
170fd7d9bd3Smrg
171fd7d9bd3Smrg
172fd7d9bd3Smrg
173fd7d9bd3Smrg/* select_button(choice,togglenum)
174fd7d9bd3Smrg** -------------------------------
175fd7d9bd3Smrg** "Selects" the togglenumth toggle widget in the choice layout
176fd7d9bd3Smrg** represented by choice.  It simply turns the widget on, as if the
177fd7d9bd3Smrg** user had selected it, without calling any callbacks.  It's used
178fd7d9bd3Smrg** to give feedback when reading from a script.
179fd7d9bd3Smrg*/
180fd7d9bd3Smrg
181fd7d9bd3Smrgvoid
182fd7d9bd3Smrgselect_button(ChoiceDesc *choice, int togglenum)
183fd7d9bd3Smrg{
184fd7d9bd3Smrg  static Arg toggleargs[] = {
185fd7d9bd3Smrg    {XtNstate,   (XtArgVal) True}
186fd7d9bd3Smrg  };
187fd7d9bd3Smrg
188fd7d9bd3Smrg  XtSetValues(choice->widgets[togglenum],toggleargs,XtNumber(toggleargs));
189fd7d9bd3Smrg}
190fd7d9bd3Smrg
191fd7d9bd3Smrg/* line_up_labels(descs,numdescs)
192fd7d9bd3Smrg** ------------------------------
193fd7d9bd3Smrg** descs represents a bunch of choice layouts (numdescs is the size of
194fd7d9bd3Smrg** descs).  This function sets each label in descs to the same width,
195fd7d9bd3Smrg** thus making them line up nicely since they're all on the left margin.
196fd7d9bd3Smrg*/
197fd7d9bd3Smrg
198fd7d9bd3Smrgvoid
199fd7d9bd3Smrgline_up_labels(ChoiceDesc *descs[], int numdescs)
200fd7d9bd3Smrg{
201fd7d9bd3Smrg  int i;			/* counter */
202fd7d9bd3Smrg  Dimension width;		/* current width */
203fd7d9bd3Smrg  Dimension maxwidth = (Dimension) 0; /* max width found */
204fd7d9bd3Smrg
205fd7d9bd3Smrg  static Arg widthargs[] = {
206fd7d9bd3Smrg    {XtNwidth,     (XtArgVal) NULL }
207fd7d9bd3Smrg  };
208fd7d9bd3Smrg
209fd7d9bd3Smrg  widthargs[0].value = (XtArgVal) &width;
210fd7d9bd3Smrg
211fd7d9bd3Smrg  /* Find the maximum width */
212fd7d9bd3Smrg  for (i = 0; i < numdescs; ++i) {
213fd7d9bd3Smrg    XtGetValues(descs[i]->label, widthargs, XtNumber(widthargs));
214fd7d9bd3Smrg    maxwidth = max(maxwidth,width);
215fd7d9bd3Smrg  }
216fd7d9bd3Smrg
217fd7d9bd3Smrg  /* Set all labels to that width */
218fd7d9bd3Smrg  widthargs[0].value = (XtArgVal) maxwidth;
219fd7d9bd3Smrg  for (i = 0; i < numdescs; ++i) {
220fd7d9bd3Smrg    XtSetValues(descs[i]->label, widthargs, XtNumber(widthargs));
221fd7d9bd3Smrg  }
222fd7d9bd3Smrg}
223fd7d9bd3Smrg
224fd7d9bd3Smrg/* choose_defaults(descs,numdescs)
225fd7d9bd3Smrg** -------------------------------
226fd7d9bd3Smrg** descs represents a bunch of choice layouts (numdescs is the size of
227fd7d9bd3Smrg** descs).  This function goes through all of descs and selects the
228fd7d9bd3Smrg** appropriate toggle widget for each one.  This includes calling
229fd7d9bd3Smrg** the callbacks associated with that widget.
230fd7d9bd3Smrg**
231fd7d9bd3Smrg** This function ends up initializing both the screen and the GC, and
232fd7d9bd3Smrg** ensures that they are consistent.
233fd7d9bd3Smrg*/
234fd7d9bd3Smrg
235fd7d9bd3Smrgvoid
236fd7d9bd3Smrgchoose_defaults(ChoiceDesc *descs[], int numdescs)
237fd7d9bd3Smrg{
238fd7d9bd3Smrg  int i;			/* which choice layout */
239fd7d9bd3Smrg  int j;			/* which toggle within it */
240fd7d9bd3Smrg
241fd7d9bd3Smrg  for (i = 0; i < numdescs; ++i) {
242fd7d9bd3Smrg    j = 0;
243fd7d9bd3Smrg    if (i == 0)
244fd7d9bd3Smrg      j = 3;
245fd7d9bd3Smrg    select_button(descs[i],j);
246fd7d9bd3Smrg    XtCallCallbacks(descs[i]->widgets[j], XtNcallback, (caddr_t) NULL);
247fd7d9bd3Smrg  }
248fd7d9bd3Smrg}
249fd7d9bd3Smrg
250fd7d9bd3Smrg
251fd7d9bd3Smrg/* print_text_to_buffer(w,closure,call_data)
252fd7d9bd3Smrg** -----------------------------------------
253fd7d9bd3Smrg** This is also in the list of callbacks for the toggle buttons in a
254fd7d9bd3Smrg** choice widget.  It sends the string contained in closure (which
255fd7d9bd3Smrg** was set way back in create_choice()) over to interpret(), which
256fd7d9bd3Smrg** decides what to do with it.
257fd7d9bd3Smrg*/
258fd7d9bd3Smrg
259fd7d9bd3Smrg/*ARGSUSED*/
260fd7d9bd3Smrgstatic void
261fd7d9bd3Smrgprint_text_to_buffer(
262fd7d9bd3Smrg    Widget  w,
263fd7d9bd3Smrg    caddr_t closure,           /* contains the string */
264fd7d9bd3Smrg    caddr_t call_data)
265fd7d9bd3Smrg{
266fd7d9bd3Smrg  interpret((char *) closure);          /* Gee, that was easy */
267fd7d9bd3Smrg}
268