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