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