choice.c 8.2 KB

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