Updated all files to GPL version 3.
[xboard.git] / xoptions.c
1 /*\r
2  * xoptions.c -- Move list window, part of X front end for XBoard\r
3  *\r
4  * Copyright 2000,2009 Free Software Foundation, Inc.\r
5  * ------------------------------------------------------------------------\r
6  *\r
7  * GNU XBoard is free software: you can redistribute it and/or modify\r
8  * it under the terms of the GNU General Public License as published by\r
9  * the Free Software Foundation, either version 3 of the License, or (at\r
10  * your option) any later version.\r
11  *\r
12  * GNU XBoard is distributed in the hope that it will be useful, but\r
13  * WITHOUT ANY WARRANTY; without even the implied warranty of\r
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
15  * General Public License for more details.\r
16  *\r
17  * You should have received a copy of the GNU General Public License\r
18  * along with this program. If not, see http://www.gnu.org/licenses/.  *\r
19  *\r
20  *------------------------------------------------------------------------\r
21  ** See the file ChangeLog for a revision history.  */\r
22 \r
23 // [HGM] this file is the counterpart of woptions.c, containing xboard popup menus\r
24 // similar to those of WinBoard, to set the most common options interactively.\r
25 \r
26 #include "config.h"\r
27 \r
28 #include <stdio.h>\r
29 #include <ctype.h>\r
30 #include <errno.h>\r
31 #include <sys/types.h>\r
32 \r
33 #if STDC_HEADERS\r
34 # include <stdlib.h>\r
35 # include <string.h>\r
36 #else /* not STDC_HEADERS */\r
37 extern char *getenv();\r
38 # if HAVE_STRING_H\r
39 #  include <string.h>\r
40 # else /* not HAVE_STRING_H */\r
41 #  include <strings.h>\r
42 # endif /* not HAVE_STRING_H */\r
43 #endif /* not STDC_HEADERS */\r
44 \r
45 #if HAVE_UNISTD_H\r
46 # include <unistd.h>\r
47 #endif\r
48 \r
49 #include <X11/Intrinsic.h>\r
50 #include <X11/StringDefs.h>\r
51 #include <X11/Shell.h>\r
52 #include <X11/Xaw/Dialog.h>\r
53 #include <X11/Xaw/Form.h>\r
54 #include <X11/Xaw/List.h>\r
55 #include <X11/Xaw/Label.h>\r
56 #include <X11/Xaw/SimpleMenu.h>\r
57 #include <X11/Xaw/SmeBSB.h>\r
58 #include <X11/Xaw/SmeLine.h>\r
59 #include <X11/Xaw/Box.h>\r
60 #include <X11/Xaw/Paned.h>\r
61 #include <X11/Xaw/MenuButton.h>\r
62 #include <X11/cursorfont.h>\r
63 #include <X11/Xaw/Text.h>\r
64 #include <X11/Xaw/AsciiText.h>\r
65 #include <X11/Xaw/Viewport.h>\r
66 #include <X11/Xaw/Toggle.h>\r
67 \r
68 #include "common.h"\r
69 #include "backend.h"\r
70 #include "xboard.h"\r
71 #include "gettext.h"\r
72 \r
73 #ifdef ENABLE_NLS\r
74 # define  _(s) gettext (s)\r
75 # define N_(s) gettext_noop (s)\r
76 #else\r
77 # define  _(s) (s)\r
78 # define N_(s)  s\r
79 #endif\r
80 \r
81 extern Widget formWidget, shellWidget, boardWidget, menuBarWidget;\r
82 extern Display *xDisplay;\r
83 extern int squareSize;\r
84 extern Pixmap xMarkPixmap;\r
85 extern char *layoutName;\r
86 extern Window xBoardWindow;\r
87 extern Arg layoutArgs[2], formArgs[2];\r
88 Pixel timerForegroundPixel, timerBackgroundPixel;\r
89 \r
90 // [HGM] the following code for makng menu popups was cloned from the FileNamePopUp routines\r
91 \r
92 static Widget previous = NULL;\r
93 \r
94 void SetFocus(Widget w, XtPointer data, XEvent *event, Boolean *b)\r
95 {\r
96     Arg args;\r
97 \r
98     if(previous) {\r
99         XtSetArg(args, XtNdisplayCaret, False);\r
100         XtSetValues(previous, &args, 1);\r
101     }\r
102     XtSetArg(args, XtNdisplayCaret, True);\r
103     XtSetValues(w, &args, 1);\r
104     XtSetKeyboardFocus((Widget) data, w);\r
105     previous = w;\r
106 }\r
107 \r
108 //--------------------------- New Shuffle Game --------------------------------------------\r
109 extern int shuffleOpenings;\r
110 extern int startedFromPositionFile;\r
111 int shuffleUp;\r
112 Widget shuffleShell;\r
113 \r
114 void ShufflePopDown()\r
115 {\r
116     if (!shuffleUp) return;\r
117     XtPopdown(shuffleShell);\r
118     XtDestroyWidget(shuffleShell);\r
119     shuffleUp = False;\r
120     ModeHighlight();\r
121 }\r
122 \r
123 void ShuffleCallback(w, client_data, call_data)\r
124      Widget w;\r
125      XtPointer client_data, call_data;\r
126 {\r
127     String name;\r
128     Widget w2;\r
129     Arg args[16];\r
130     char buf[80];\r
131     \r
132     XtSetArg(args[0], XtNlabel, &name);\r
133     XtGetValues(w, args, 1);\r
134     \r
135     if (strcmp(name, _("cancel")) == 0) {\r
136         ShufflePopDown();\r
137         return;\r
138     }\r
139     if (strcmp(name, _("off")) == 0) {\r
140         ShufflePopDown();\r
141         shuffleOpenings = False; // [HGM] should be moved to New Variant menu, once we have it!\r
142         ResetGameEvent();\r
143         AnalysisPopDown();\r
144         return;\r
145     }\r
146     if (strcmp(name, _("random")) == 0) {\r
147         sprintf(buf, "%d", rand());\r
148         XtSetArg(args[0],XtNvalue, buf); // erase bad (non-numeric) value\r
149         XtSetValues(XtParent(w), args, 1);\r
150         return;\r
151     }\r
152     if (strcmp(name, _("ok")) == 0) {\r
153         int nr; String name;\r
154         name = XawDialogGetValueString(w2 = XtParent(w));\r
155         if(sscanf(name ,"%d",&nr) != 1) {\r
156             sprintf(buf, "%d", appData.defaultFrcPosition);\r
157             XtSetArg(args[0],XtNvalue, buf); // erase bad (non-numeric) value\r
158             XtSetValues(w2, args, 1);\r
159             return;\r
160         }\r
161         appData.defaultFrcPosition = nr;\r
162         shuffleOpenings = True;\r
163         ShufflePopDown();\r
164         ResetGameEvent();\r
165         AnalysisPopDown();\r
166         return;\r
167     }\r
168 }\r
169 \r
170 void ShufflePopUp()\r
171 {\r
172     Arg args[16];\r
173     Widget popup, layout, dialog, edit;\r
174     Window root, child;\r
175     int x, y, i;\r
176     int win_x, win_y;\r
177     unsigned int mask;\r
178     char def[80];\r
179     \r
180     i = 0;\r
181     XtSetArg(args[i], XtNresizable, True); i++;\r
182     XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;\r
183     shuffleShell = popup =\r
184       XtCreatePopupShell(_("New Shuffle Game"), transientShellWidgetClass,\r
185                          shellWidget, args, i);\r
186     \r
187     layout =\r
188       XtCreateManagedWidget(layoutName, formWidgetClass, popup,\r
189                             layoutArgs, XtNumber(layoutArgs));\r
190   \r
191     sprintf(def, "%d\n", appData.defaultFrcPosition);\r
192     i = 0;\r
193     XtSetArg(args[i], XtNlabel, _("Start-position number:")); i++;\r
194     XtSetArg(args[i], XtNvalue, def); i++;\r
195     XtSetArg(args[i], XtNborderWidth, 0); i++;\r
196     dialog = XtCreateManagedWidget(_("Shuffle"), dialogWidgetClass,\r
197                                    layout, args, i);\r
198     \r
199 //    XtSetArg(args[0], XtNeditType, XawtextEdit);  // [HGM] can't get edit to work decently\r
200 //    XtSetArg(args[1], XtNuseStringInPlace, False);\r
201 //    XtSetValues(dialog, args, 2);\r
202 \r
203     XawDialogAddButton(dialog, _("ok"), ShuffleCallback, (XtPointer) dialog);\r
204     XawDialogAddButton(dialog, _("cancel"), ShuffleCallback, (XtPointer) dialog);\r
205     XawDialogAddButton(dialog, _("random"), ShuffleCallback, (XtPointer) dialog);\r
206     XawDialogAddButton(dialog, _("off"), ShuffleCallback, (XtPointer) dialog);\r
207     \r
208     XtRealizeWidget(popup);\r
209     CatchDeleteWindow(popup, "ShufflePopDown");\r
210     \r
211     XQueryPointer(xDisplay, xBoardWindow, &root, &child,\r
212                   &x, &y, &win_x, &win_y, &mask);\r
213     \r
214     XtSetArg(args[0], XtNx, x - 10);\r
215     XtSetArg(args[1], XtNy, y - 30);\r
216     XtSetValues(popup, args, 2);\r
217     \r
218     XtPopup(popup, XtGrabExclusive);\r
219     shuffleUp = True;\r
220     \r
221     edit = XtNameToWidget(dialog, "*value");\r
222 \r
223     XtSetKeyboardFocus(popup, edit);\r
224 }\r
225 \r
226 void ShuffleMenuProc(w, event, prms, nprms)\r
227      Widget w;\r
228      XEvent *event;\r
229      String *prms;\r
230      Cardinal *nprms;\r
231 {\r
232 //    if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {\r
233 //      Reset(FALSE, TRUE);\r
234 //    }\r
235     ShufflePopUp();\r
236 }\r
237 \r
238 //--------------------------- Time-Control Menu Popup ----------------------------------\r
239 int TimeControlUp;\r
240 Widget TimeControlShell;\r
241 int tcInc;\r
242 Widget tcMess1, tcMess2, tcData, tcTime, tcOdds1, tcOdds2;\r
243 int tcIncrement, tcMoves;\r
244 \r
245 void TimeControlPopDown()\r
246 {\r
247     if (!TimeControlUp) return;\r
248     XtPopdown(TimeControlShell);\r
249     XtDestroyWidget(TimeControlShell);\r
250     TimeControlUp = False;\r
251     ModeHighlight();\r
252 }\r
253 \r
254 void TimeControlCallback(w, client_data, call_data)\r
255      Widget w;\r
256      XtPointer client_data, call_data;\r
257 {\r
258     String name, txt;\r
259     Widget w2;\r
260     Arg args[16];\r
261     char buf[80];\r
262     int j;\r
263 \r
264     XtSetArg(args[0], XtNlabel, &name);\r
265     XtGetValues(w, args, 1);\r
266     \r
267     if (strcmp(name, _("classical")) == 0) {\r
268         if(!tcInc) return;\r
269         j=0;\r
270         XtSetArg(args[j], XtNlabel, _("minutes for each")); j++;\r
271         XtSetValues(tcMess1, args, j);\r
272         j=0;\r
273         XtSetArg(args[j], XtNlabel, _("moves")); j++;\r
274         XtSetValues(tcMess2, args, j);\r
275         j=0;\r
276         XtSetArg(args[j], XtNstring, &name); j++;\r
277         XtGetValues(tcData, args, j);\r
278         tcIncrement = 0; sscanf(name, "%d", &tcIncrement);\r
279         sprintf(buf, "%d", tcMoves);\r
280         j=0;\r
281         XtSetArg(args[j], XtNstring, buf); j++;\r
282         XtSetValues(tcData, args, j);\r
283         tcInc = False;\r
284         return;\r
285     }\r
286     if (strcmp(name, _("incremental")) == 0) {\r
287         if(tcInc) return;\r
288         j=0;\r
289         XtSetArg(args[j], XtNlabel, _("minutes, plus")); j++;\r
290         XtSetValues(tcMess1, args, j);\r
291         j=0;\r
292         XtSetArg(args[j], XtNlabel, _("sec/move")); j++;\r
293         XtSetValues(tcMess2, args, j);\r
294         j=0;\r
295         XtSetArg(args[j], XtNstring, &name); j++;\r
296         XtGetValues(tcData, args, j);\r
297         tcMoves = appData.movesPerSession; sscanf(name, "%d", &tcMoves);\r
298         sprintf(buf, "%d", tcIncrement);\r
299         j=0;\r
300         XtSetArg(args[j], XtNstring, buf); j++;\r
301         XtSetValues(tcData, args, j);\r
302         tcInc = True;\r
303         return;\r
304     }\r
305     if (strcmp(name, _(" OK ")) == 0) {\r
306         int inc, mps, tc, ok;\r
307         XtSetArg(args[0], XtNstring, &txt);\r
308         XtGetValues(tcData, args, 1);\r
309         if(tcInc) {\r
310             ok = sscanf(txt, "%d", &inc); mps = 0;\r
311             if(!ok && txt[0] == 0) { inc = 0; ok = 1; } // accept empty string as zero\r
312             ok &= (inc >= 0);\r
313         } else {\r
314             ok = sscanf(txt, "%d", &mps); inc = -1;\r
315             ok &= (mps > 0);\r
316         }\r
317         if(ok != 1) {\r
318             XtSetArg(args[0], XtNstring, ""); // erase any offending input\r
319             XtSetValues(tcData, args, 1);\r
320             return;\r
321         }\r
322         XtSetArg(args[0], XtNstring, &txt);\r
323         XtGetValues(tcTime, args, 1);\r
324         if(!ParseTimeControl(txt, inc, mps)) {\r
325             XtSetArg(args[0], XtNstring, ""); // erase any offending input\r
326             XtSetValues(tcTime, args, 1);\r
327             DisplayError(_("Bad Time-Control String"), 0);\r
328             return;\r
329         }\r
330         appData.movesPerSession = mps;\r
331         appData.timeIncrement = inc;\r
332         appData.timeControl = strdup(txt);\r
333         XtSetArg(args[0], XtNstring, &txt);\r
334         XtGetValues(tcOdds1, args, 1);\r
335         appData.firstTimeOdds = first.timeOdds \r
336                 = (sscanf(txt, "%d", &j) == 1 && j > 0) ? j : 1;\r
337         XtGetValues(tcOdds2, args, 1);\r
338         appData.secondTimeOdds = second.timeOdds \r
339                 = (sscanf(txt, "%d", &j) == 1 && j > 0) ? j : 1;\r
340 \r
341         Reset(True, True);\r
342         TimeControlPopDown();\r
343         return;\r
344     }\r
345 }\r
346 \r
347 void TimeControlPopUp()\r
348 {\r
349     Arg args[16];\r
350     Widget popup, layout, form, edit, b_ok, b_cancel, b_clas, b_inc, mess;\r
351     Window root, child;\r
352     int x, y, i, j;\r
353     int win_x, win_y;\r
354     unsigned int mask;\r
355     char def[80];\r
356     \r
357     tcInc = (appData.timeIncrement >= 0);\r
358     tcMoves = appData.movesPerSession; tcIncrement = appData.timeIncrement;\r
359     if(!tcInc) tcIncrement = 0;\r
360     sprintf(def, "%d", tcInc ? tcIncrement : tcMoves);\r
361 \r
362     i = 0;\r
363     XtSetArg(args[i], XtNresizable, True); i++;\r
364 //    XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;\r
365     TimeControlShell = popup =\r
366       XtCreatePopupShell(_("TimeControl Menu"), transientShellWidgetClass,\r
367                          shellWidget, args, i);\r
368     \r
369     layout =\r
370       XtCreateManagedWidget(layoutName, formWidgetClass, popup,\r
371                             layoutArgs, XtNumber(layoutArgs));\r
372   \r
373     form =\r
374       XtCreateManagedWidget(layoutName, formWidgetClass, layout,\r
375                             formArgs, XtNumber(formArgs));\r
376   \r
377     j = 0;\r
378 //    XtSetArg(args[j], XtNwidth,     (XtArgVal) 300); j++;\r
379 //    XtSetArg(args[j], XtNheight,    (XtArgVal) 85); j++;\r
380     XtSetValues(popup, args, j);\r
381 \r
382     j= 0;\r
383     XtSetArg(args[j], XtNborderWidth, 1); j++;\r
384     XtSetArg(args[j], XtNeditType, XawtextEdit);  j++;\r
385     XtSetArg(args[j], XtNuseStringInPlace, False);  j++;\r
386     XtSetArg(args[j], XtNstring, appData.timeControl);  j++;\r
387     XtSetArg(args[j], XtNdisplayCaret, False);  j++;\r
388     XtSetArg(args[j], XtNtop, XtChainTop);  j++;\r
389     XtSetArg(args[j], XtNbottom, XtChainTop);  j++;\r
390     XtSetArg(args[j], XtNleft, XtChainLeft);  j++;\r
391     XtSetArg(args[j], XtNright, XtChainRight);  j++;\r
392     XtSetArg(args[j], XtNresizable, True);  j++;\r
393     XtSetArg(args[j], XtNwidth,  85);  j++;\r
394 //    XtSetArg(args[j], XtNheight, 20);  j++;\r
395     tcTime = XtCreateManagedWidget("TC", asciiTextWidgetClass, form, args, j);\r
396     XtAddEventHandler(tcTime, ButtonPressMask, False, SetFocus, (XtPointer) popup);\r
397 \r
398     j= 0;\r
399     XtSetArg(args[j], XtNlabel, tcInc ? _("   minutes, plus   ") : _("minutes for each")); j++;\r
400     XtSetArg(args[j], XtNborderWidth, 0); j++;\r
401     XtSetArg(args[j], XtNfromHoriz, tcTime); j++;\r
402     XtSetArg(args[j], XtNtop, XtChainTop);  j++;\r
403     XtSetArg(args[j], XtNbottom, XtChainTop);  j++;\r
404     XtSetArg(args[j], XtNleft, XtChainRight);  j++;\r
405     XtSetArg(args[j], XtNright, XtChainRight);  j++;\r
406   //  XtSetArg(args[j], XtNwidth,  100);  j++;\r
407   //  XtSetArg(args[j], XtNheight, 20);  j++;\r
408     tcMess1 = XtCreateManagedWidget("TCtext", labelWidgetClass, form, args, j);\r
409 \r
410     j= 0;\r
411     XtSetArg(args[j], XtNborderWidth, 1); j++;\r
412     XtSetArg(args[j], XtNfromHoriz, tcMess1); j++;\r
413     XtSetArg(args[j], XtNeditType, XawtextEdit);  j++;\r
414     XtSetArg(args[j], XtNuseStringInPlace, False);  j++;\r
415     XtSetArg(args[j], XtNstring, def);  j++;\r
416     XtSetArg(args[j], XtNdisplayCaret, False);  j++;\r
417     XtSetArg(args[j], XtNtop, XtChainTop);  j++;\r
418     XtSetArg(args[j], XtNbottom, XtChainTop);  j++;\r
419     XtSetArg(args[j], XtNleft, XtChainRight);  j++;\r
420     XtSetArg(args[j], XtNright, XtChainRight);  j++;\r
421     XtSetArg(args[j], XtNresizable, True);  j++;\r
422     XtSetArg(args[j], XtNwidth,  40);  j++;\r
423 //    XtSetArg(args[j], XtNheight, 20);  j++;\r
424     tcData = XtCreateManagedWidget("MPS", asciiTextWidgetClass, form, args, j);\r
425     XtAddEventHandler(tcData, ButtonPressMask, False, SetFocus, (XtPointer) popup);\r
426 \r
427     j= 0;\r
428     XtSetArg(args[j], XtNlabel, tcInc ? _("sec/move") : _("moves     ")); j++;\r
429     XtSetArg(args[j], XtNjustify, XtJustifyLeft); j++;\r
430     XtSetArg(args[j], XtNborderWidth, 0); j++;\r
431     XtSetArg(args[j], XtNfromHoriz, tcData); j++;\r
432     XtSetArg(args[j], XtNtop, XtChainTop);  j++;\r
433     XtSetArg(args[j], XtNbottom, XtChainTop);  j++;\r
434     XtSetArg(args[j], XtNleft, XtChainRight);  j++;\r
435     XtSetArg(args[j], XtNright, XtChainRight);  j++;\r
436 //    XtSetArg(args[j], XtNwidth,  80);  j++;\r
437 //    XtSetArg(args[j], XtNheight, 20);  j++;\r
438     tcMess2 = XtCreateManagedWidget("MPStext", labelWidgetClass,\r
439                                    form, args, j);\r
440 \r
441     j= 0;\r
442     XtSetArg(args[j], XtNborderWidth, 1); j++;\r
443     XtSetArg(args[j], XtNfromVert, tcTime); j++;\r
444     XtSetArg(args[j], XtNeditType, XawtextEdit);  j++;\r
445     XtSetArg(args[j], XtNuseStringInPlace, False);  j++;\r
446     XtSetArg(args[j], XtNstring, "1");  j++;\r
447     XtSetArg(args[j], XtNdisplayCaret, False);  j++;\r
448     XtSetArg(args[j], XtNtop, XtChainTop);  j++;\r
449     XtSetArg(args[j], XtNbottom, XtChainTop);  j++;\r
450     XtSetArg(args[j], XtNleft, XtChainLeft);  j++;\r
451     XtSetArg(args[j], XtNright, XtChainLeft);  j++;\r
452     XtSetArg(args[j], XtNresizable, True);  j++;\r
453     XtSetArg(args[j], XtNwidth,  40);  j++;\r
454 //    XtSetArg(args[j], XtNheight, 20);  j++;\r
455     tcOdds1 = XtCreateManagedWidget("Odds1", asciiTextWidgetClass, form, args, j);\r
456     XtAddEventHandler(tcOdds1, ButtonPressMask, False, SetFocus, (XtPointer) popup);\r
457 \r
458     j= 0;\r
459     XtSetArg(args[j], XtNborderWidth, 1); j++;\r
460     XtSetArg(args[j], XtNfromVert, tcTime); j++;\r
461     XtSetArg(args[j], XtNfromHoriz, tcOdds1); j++;\r
462     XtSetArg(args[j], XtNeditType, XawtextEdit);  j++;\r
463     XtSetArg(args[j], XtNuseStringInPlace, False);  j++;\r
464     XtSetArg(args[j], XtNstring, "1");  j++;\r
465     XtSetArg(args[j], XtNdisplayCaret, False);  j++;\r
466     XtSetArg(args[j], XtNtop, XtChainTop);  j++;\r
467     XtSetArg(args[j], XtNbottom, XtChainTop);  j++;\r
468     XtSetArg(args[j], XtNleft, XtChainLeft);  j++;\r
469     XtSetArg(args[j], XtNright, XtChainLeft);  j++;\r
470     XtSetArg(args[j], XtNresizable, True);  j++;\r
471     XtSetArg(args[j], XtNwidth,  40);  j++;\r
472 //    XtSetArg(args[j], XtNheight, 20);  j++;\r
473     tcOdds2 = XtCreateManagedWidget("Odds2", asciiTextWidgetClass, form, args, j);\r
474     XtAddEventHandler(tcOdds2, ButtonPressMask, False, SetFocus, (XtPointer) popup);\r
475 \r
476     j= 0;\r
477     XtSetArg(args[j], XtNlabel, _("Engine #1 and #2 Time-Odds Factors")); j++;\r
478     XtSetArg(args[j], XtNjustify, XtJustifyLeft); j++;\r
479     XtSetArg(args[j], XtNborderWidth, 0); j++;\r
480     XtSetArg(args[j], XtNfromVert, tcTime); j++;\r
481     XtSetArg(args[j], XtNfromHoriz, tcOdds2); j++;\r
482     XtSetArg(args[j], XtNtop, XtChainTop);  j++;\r
483     XtSetArg(args[j], XtNbottom, XtChainTop);  j++;\r
484     XtSetArg(args[j], XtNleft, XtChainLeft);  j++;\r
485     XtSetArg(args[j], XtNright, XtChainRight);  j++;\r
486 //    XtSetArg(args[j], XtNwidth,  200);  j++;\r
487 //    XtSetArg(args[j], XtNheight, 20);  j++;\r
488     mess = XtCreateManagedWidget("Oddstext", labelWidgetClass,\r
489                                    form, args, j);\r
490     j=0;\r
491     XtSetArg(args[j], XtNfromVert, tcOdds1);  j++;\r
492     XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;\r
493     XtSetArg(args[j], XtNtop, XtChainBottom);  j++;\r
494     XtSetArg(args[j], XtNleft, XtChainLeft);  j++;\r
495     XtSetArg(args[j], XtNright, XtChainLeft);  j++;\r
496     b_clas= XtCreateManagedWidget(_("classical"), commandWidgetClass,\r
497                                    form, args, j);   \r
498     XtAddCallback(b_clas, XtNcallback, TimeControlCallback, (XtPointer) 0);\r
499 \r
500     j=0;\r
501     XtSetArg(args[j], XtNfromVert, tcOdds1);  j++;\r
502     XtSetArg(args[j], XtNfromHoriz, b_clas);  j++;\r
503     XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;\r
504     XtSetArg(args[j], XtNtop, XtChainBottom);  j++;\r
505     XtSetArg(args[j], XtNleft, XtChainLeft);  j++;\r
506     XtSetArg(args[j], XtNright, XtChainLeft);  j++;\r
507     b_inc = XtCreateManagedWidget(_("incremental"), commandWidgetClass,\r
508                                    form, args, j);   \r
509     XtAddCallback(b_inc, XtNcallback, TimeControlCallback, (XtPointer) 0);\r
510 \r
511     j=0;\r
512     XtSetArg(args[j], XtNfromVert, tcOdds1);  j++;\r
513     XtSetArg(args[j], XtNfromHoriz, tcData);  j++;\r
514     XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;\r
515     XtSetArg(args[j], XtNtop, XtChainBottom);  j++;\r
516     XtSetArg(args[j], XtNleft, XtChainRight);  j++;\r
517     XtSetArg(args[j], XtNright, XtChainRight);  j++;\r
518     b_ok= XtCreateManagedWidget(_(" OK "), commandWidgetClass,\r
519                                    form, args, j);   \r
520     XtAddCallback(b_ok, XtNcallback, TimeControlCallback, (XtPointer) 0);\r
521 \r
522     j=0;\r
523     XtSetArg(args[j], XtNfromVert, tcOdds1);  j++;\r
524     XtSetArg(args[j], XtNfromHoriz, b_ok);  j++;\r
525     XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;\r
526     XtSetArg(args[j], XtNtop, XtChainBottom);  j++;\r
527     XtSetArg(args[j], XtNleft, XtChainRight);  j++;\r
528     XtSetArg(args[j], XtNright, XtChainRight);  j++;\r
529     b_cancel= XtCreateManagedWidget(_("cancel"), commandWidgetClass,\r
530                                    form, args, j);   \r
531     XtAddCallback(b_cancel, XtNcallback, TimeControlPopDown, (XtPointer) 0);\r
532 \r
533     XtRealizeWidget(popup);\r
534     CatchDeleteWindow(popup, "TimeControlPopDown");\r
535     \r
536     XQueryPointer(xDisplay, xBoardWindow, &root, &child,\r
537                   &x, &y, &win_x, &win_y, &mask);\r
538     \r
539     XtSetArg(args[0], XtNx, x - 10);\r
540     XtSetArg(args[1], XtNy, y - 30);\r
541     XtSetValues(popup, args, 2);\r
542     \r
543     XtPopup(popup, XtGrabExclusive);\r
544     TimeControlUp = True;\r
545     \r
546     previous = NULL;\r
547     SetFocus(tcTime, popup, (XEvent*) NULL, False);\r
548 //    XtSetKeyboardFocus(popup, tcTime);\r
549 }\r
550 \r
551 void TimeControlProc(w, event, prms, nprms)\r
552      Widget w;\r
553      XEvent *event;\r
554      String *prms;\r
555      Cardinal *nprms;\r
556 {\r
557    TimeControlPopUp();\r
558 }\r
559 \r
560 //--------------------------- Engine-Options Menu Popup ----------------------------------\r
561 int EngineUp;\r
562 Widget EngineShell;\r
563 extern int adjudicateLossThreshold;\r
564 \r
565 Widget engDrawMoves, engThreshold, engRule, engRepeat;\r
566 \r
567 void EnginePopDown()\r
568 {\r
569     if (!EngineUp) return;\r
570     XtPopdown(EngineShell);\r
571     XtDestroyWidget(EngineShell);\r
572     EngineUp = False;\r
573     ModeHighlight();\r
574 }\r
575 \r
576 int ReadToggle(Widget w)\r
577 {\r
578     Arg args; Boolean res;\r
579 \r
580     XtSetArg(args, XtNstate, &res);\r
581     XtGetValues(w, &args, 1);\r
582 \r
583     return res;\r
584 }\r
585 \r
586 Widget w1, w2, w3, w4, w5, w6, w7, w8;\r
587 \r
588 void EngineCallback(w, client_data, call_data)\r
589      Widget w;\r
590      XtPointer client_data, call_data;\r
591 {\r
592     String name;\r
593     Widget s2;\r
594     Arg args[16];\r
595     char buf[80];\r
596     int j;\r
597     \r
598     XtSetArg(args[0], XtNlabel, &name);\r
599     XtGetValues(w, args, 1);\r
600     \r
601     if (strcmp(name, _("OK")) == 0) {\r
602         // read all switches\r
603         appData.periodicUpdates = ReadToggle(w1);\r
604 //      appData.hideThinkingFromHuman = ReadToggle(w2);\r
605         appData.firstScoreIsAbsolute  = ReadToggle(w3);\r
606         appData.secondScoreIsAbsolute = ReadToggle(w4);\r
607         appData.testClaims    = ReadToggle(w5);\r
608         appData.checkMates    = ReadToggle(w6);\r
609         appData.materialDraws = ReadToggle(w7);\r
610         appData.trivialDraws  = ReadToggle(w8);\r
611 \r
612         // adjust setting in other menu for duplicates \r
613         // (perhaps duplicates should be removed from general Option Menu?)\r
614 //      XtSetArg(args[0], XtNleftBitmap, appData.showThinking ? xMarkPixmap : None);\r
615 //      XtSetValues(XtNameToWidget(menuBarWidget,\r
616 //                                 "menuOptions.Show Thinking"), args, 1);\r
617 \r
618         // read out numeric controls, simply ignore bad formats for now\r
619         XtSetArg(args[0], XtNstring, &name);\r
620         XtGetValues(engDrawMoves, args, 1);\r
621         if(sscanf(name, "%d", &j) == 1) appData.adjudicateDrawMoves = j;\r
622         XtGetValues(engThreshold, args, 1);\r
623         if(sscanf(name, "%d", &j) == 1) \r
624                 adjudicateLossThreshold = appData.adjudicateLossThreshold = -j; // inverted!\r
625         XtGetValues(engRule, args, 1);\r
626         if(sscanf(name, "%d", &j) == 1) appData.ruleMoves = j;\r
627         XtGetValues(engRepeat, args, 1);\r
628         if(sscanf(name, "%d", &j) == 1) appData.drawRepeats = j;\r
629 \r
630         EnginePopDown();\r
631         ShowThinkingEvent(); // [HGM] thinking: score adjudication might need thinking output\r
632         return;\r
633     }\r
634 }\r
635 \r
636 void EnginePopUp()\r
637 {\r
638     Arg args[16];\r
639     Widget popup, layout, form, edit, b_ok, b_cancel, b_clas, b_inc, s1; \r
640     Window root, child;\r
641     int x, y, i, j, width;\r
642     int win_x, win_y;\r
643     unsigned int mask;\r
644     char def[80];\r
645     \r
646     tcInc = (appData.timeIncrement >= 0);\r
647     tcMoves = appData.movesPerSession; tcIncrement = appData.timeIncrement;\r
648     if(!tcInc) tcIncrement = 0;\r
649     sprintf(def, "%d", tcInc ? tcIncrement : tcMoves);\r
650 \r
651     i = 0;\r
652     XtSetArg(args[i], XtNresizable, True); i++;\r
653 //    XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;\r
654     EngineShell = popup =\r
655       XtCreatePopupShell(_("Adjudications"), transientShellWidgetClass,\r
656                          shellWidget, args, i);\r
657     \r
658     layout =\r
659       XtCreateManagedWidget(layoutName, formWidgetClass, popup,\r
660                             layoutArgs, XtNumber(layoutArgs));\r
661   \r
662     form =\r
663       XtCreateManagedWidget(layoutName, formWidgetClass, layout,\r
664                             formArgs, XtNumber(formArgs));\r
665   \r
666     j = 0;\r
667 //    XtSetArg(args[j], XtNwidth,     (XtArgVal) 250); j++;\r
668 //    XtSetArg(args[j], XtNheight,    (XtArgVal) 400); j++;\r
669 //    XtSetValues(popup, args, j);\r
670 \r
671     j = 0;\r
672 //    XtSetArg(args[j], XtNwidth,       (XtArgVal) 250); j++;\r
673 //    XtSetArg(args[j], XtNheight,      (XtArgVal) 20); j++;\r
674     XtSetArg(args[j], XtNleft,        (XtArgVal) XtChainLeft); j++;\r
675     XtSetArg(args[j], XtNright,       (XtArgVal) XtChainRight); j++;\r
676     XtSetArg(args[j], XtNstate,       appData.periodicUpdates); j++;\r
677 //    XtSetArg(args[j], XtNjustify,     (XtArgVal) XtJustifyLeft); j++;\r
678     w1 = XtCreateManagedWidget(_("Periodic Updates (Analysis Mode)"), toggleWidgetClass, form, args, j);\r
679 \r
680     XtSetArg(args[j], XtNwidth,       (XtArgVal) &width);\r
681     XtGetValues(w1, &args[j], 1);\r
682 \r
683 //    XtSetArg(args[j-1], XtNfromVert,  (XtArgVal) w1);\r
684 //    XtSetArg(args[j-3], XtNstate,       appData.hideThinkingFromHuman);\r
685 //    w2 = XtCreateManagedWidget(_("Hide Thinking from Human"), toggleWidgetClass, form, args, j);\r
686 \r
687     XtSetArg(args[j], XtNwidth,       (XtArgVal) width); j++;\r
688     XtSetArg(args[j-2], XtNstate,     appData.firstScoreIsAbsolute);\r
689     XtSetArg(args[j], XtNfromVert,    (XtArgVal) w1); j++;\r
690     w3 = XtCreateManagedWidget(_("Engine #1 Score is Absolute"), toggleWidgetClass, form, args, j);\r
691 \r
692     XtSetArg(args[j-1], XtNfromVert,  (XtArgVal) w3);\r
693     XtSetArg(args[j-3], XtNstate,       appData.secondScoreIsAbsolute);\r
694     w4 = XtCreateManagedWidget(_("Engine #2 Score is Absolute"), toggleWidgetClass, form, args, j);\r
695 \r
696     s1 = XtCreateManagedWidget(_("\nEngine-Engine Adjudications:"), labelWidgetClass, form, args, 3);\r
697 \r
698     XtSetArg(args[j-1], XtNfromVert,  (XtArgVal) s1);\r
699     XtSetArg(args[j-3], XtNstate,       appData.testClaims);\r
700     w5 = XtCreateManagedWidget(_("Verify Engine Result Claims"), toggleWidgetClass, form, args, j);\r
701 \r
702     XtSetArg(args[j-1], XtNfromVert,  (XtArgVal) w5);\r
703     XtSetArg(args[j-3], XtNstate,       appData.checkMates);\r
704     w6 = XtCreateManagedWidget(_("Detect All Mates"), toggleWidgetClass, form, args, j);\r
705 \r
706     XtSetArg(args[j-1], XtNfromVert,  (XtArgVal) w6);\r
707     XtSetArg(args[j-3], XtNstate,       appData.materialDraws);\r
708     w7 = XtCreateManagedWidget(_("Draw when Insuff. Mating Material"), toggleWidgetClass, form, args, j);\r
709 \r
710     XtSetArg(args[j-1], XtNfromVert,  (XtArgVal) w7);\r
711     XtSetArg(args[j-3], XtNstate,       appData.trivialDraws);\r
712     w8 = XtCreateManagedWidget(_("Adjudicate Trivial Draws"), toggleWidgetClass, form, args, j);\r
713 \r
714     XtSetArg(args[0], XtNfromVert,  (XtArgVal) w4);\r
715     XtSetArg(args[1], XtNborderWidth, (XtArgVal) 0);\r
716     XtSetValues(s1, args, 2);\r
717 \r
718     sprintf(def, "%d", appData.adjudicateDrawMoves);\r
719     j= 0;\r
720     XtSetArg(args[j], XtNborderWidth, 1); j++;\r
721     XtSetArg(args[j], XtNfromVert, w8); j++;\r
722     XtSetArg(args[j], XtNeditType, XawtextEdit);  j++;\r
723     XtSetArg(args[j], XtNuseStringInPlace, False);  j++;\r
724     XtSetArg(args[j], XtNstring, def);  j++;\r
725     XtSetArg(args[j], XtNdisplayCaret, False);  j++;\r
726     XtSetArg(args[j], XtNtop, XtChainBottom);  j++;\r
727     XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;\r
728     XtSetArg(args[j], XtNleft, XtChainLeft);  j++;\r
729     XtSetArg(args[j], XtNright, XtChainLeft);  j++;\r
730     XtSetArg(args[j], XtNresizable, True);  j++;\r
731     XtSetArg(args[j], XtNwidth,  60);  j++;\r
732 //    XtSetArg(args[j], XtNheight, 20);  j++;\r
733     engDrawMoves = XtCreateManagedWidget("Length", asciiTextWidgetClass, form, args, j);\r
734     XtAddEventHandler(engDrawMoves, ButtonPressMask, False, SetFocus, (XtPointer) popup);\r
735 \r
736     j= 0;\r
737     XtSetArg(args[j], XtNlabel, _(" moves maximum, then draw")); j++;\r
738     XtSetArg(args[j], XtNjustify,     (XtArgVal) XtJustifyLeft); j++;\r
739     XtSetArg(args[j], XtNborderWidth, 0); j++;\r
740     XtSetArg(args[j], XtNfromVert, w8); j++;\r
741     XtSetArg(args[j], XtNfromHoriz, engDrawMoves); j++;\r
742     XtSetArg(args[j], XtNtop, XtChainBottom);  j++;\r
743     XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;\r
744     XtSetArg(args[j], XtNleft, XtChainLeft);  j++;\r
745     XtSetArg(args[j], XtNright, XtChainLeft);  j++;\r
746 //    XtSetArg(args[j], XtNwidth,  170);  j++;\r
747 //    XtSetArg(args[j], XtNheight, 20);  j++;\r
748     tcMess1 = XtCreateManagedWidget("TCtext", labelWidgetClass, form, args, j);\r
749 \r
750     sprintf(def, "%d", -appData.adjudicateLossThreshold); // inverted!\r
751     j= 0;\r
752     XtSetArg(args[j], XtNborderWidth, 1); j++;\r
753     XtSetArg(args[j], XtNfromVert, engDrawMoves); j++;\r
754     XtSetArg(args[j], XtNeditType, XawtextEdit);  j++;\r
755     XtSetArg(args[j], XtNuseStringInPlace, False);  j++;\r
756     XtSetArg(args[j], XtNstring, def);  j++;\r
757     XtSetArg(args[j], XtNdisplayCaret, False);  j++;\r
758     XtSetArg(args[j], XtNtop, XtChainBottom);  j++;\r
759     XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;\r
760     XtSetArg(args[j], XtNleft, XtChainLeft);  j++;\r
761     XtSetArg(args[j], XtNright, XtChainLeft);  j++;\r
762     XtSetArg(args[j], XtNresizable, True);  j++;\r
763     XtSetArg(args[j], XtNwidth,  60);  j++;\r
764 //    XtSetArg(args[j], XtNheight, 20);  j++;\r
765     engThreshold = XtCreateManagedWidget("Threshold", asciiTextWidgetClass, form, args, j);\r
766     XtAddEventHandler(engThreshold, ButtonPressMask, False, SetFocus, (XtPointer) popup);\r
767 \r
768     j= 0;\r
769     XtSetArg(args[j], XtNlabel, _("-centiPawn lead is win")); j++;\r
770     XtSetArg(args[j], XtNjustify, XtJustifyLeft); j++;\r
771     XtSetArg(args[j], XtNborderWidth, 0); j++;\r
772     XtSetArg(args[j], XtNfromVert, engDrawMoves); j++;\r
773     XtSetArg(args[j], XtNfromHoriz, engThreshold); j++;\r
774     XtSetArg(args[j], XtNtop, XtChainBottom);  j++;\r
775     XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;\r
776     XtSetArg(args[j], XtNleft, XtChainLeft);  j++;\r
777     XtSetArg(args[j], XtNright, XtChainLeft);  j++;\r
778 //    XtSetArg(args[j], XtNwidth,  150);  j++;\r
779 //    XtSetArg(args[j], XtNheight, 20);  j++;\r
780     tcMess2 = XtCreateManagedWidget("MPStext", labelWidgetClass, form, args, j);\r
781 \r
782     sprintf(def, "%d", appData.ruleMoves);\r
783     j= 0;\r
784     XtSetArg(args[j], XtNborderWidth, 1); j++;\r
785     XtSetArg(args[j], XtNfromVert, engThreshold); j++;\r
786     XtSetArg(args[j], XtNeditType, XawtextEdit);  j++;\r
787     XtSetArg(args[j], XtNuseStringInPlace, False);  j++;\r
788     XtSetArg(args[j], XtNstring, def);  j++;\r
789     XtSetArg(args[j], XtNdisplayCaret, False);  j++;\r
790     XtSetArg(args[j], XtNtop, XtChainBottom);  j++;\r
791     XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;\r
792     XtSetArg(args[j], XtNleft, XtChainLeft);  j++;\r
793     XtSetArg(args[j], XtNright, XtChainLeft);  j++;\r
794     XtSetArg(args[j], XtNresizable, True);  j++;\r
795     XtSetArg(args[j], XtNwidth,  30);  j++;\r
796 //    XtSetArg(args[j], XtNheight, 20);  j++;\r
797     engRule = XtCreateManagedWidget("Rule", asciiTextWidgetClass, form, args, j);\r
798     XtAddEventHandler(engRule, ButtonPressMask, False, SetFocus, (XtPointer) popup);\r
799 \r
800     j= 0;\r
801     XtSetArg(args[j], XtNlabel, _("-move rule applied")); j++;\r
802     XtSetArg(args[j], XtNjustify,     (XtArgVal) XtJustifyLeft); j++;\r
803     XtSetArg(args[j], XtNborderWidth, 0); j++;\r
804     XtSetArg(args[j], XtNfromVert, engThreshold); j++;\r
805     XtSetArg(args[j], XtNfromHoriz, engRule); j++;\r
806     XtSetArg(args[j], XtNtop, XtChainBottom);  j++;\r
807     XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;\r
808     XtSetArg(args[j], XtNleft, XtChainLeft);  j++;\r
809     XtSetArg(args[j], XtNright, XtChainLeft);  j++;\r
810 //    XtSetArg(args[j], XtNwidth,  130);  j++;\r
811 //    XtSetArg(args[j], XtNheight, 20);  j++;\r
812     tcMess1 = XtCreateManagedWidget("TCtext", labelWidgetClass, form, args, j);\r
813 \r
814     sprintf(def, "%d", appData.drawRepeats);\r
815     j= 0;\r
816     XtSetArg(args[j], XtNborderWidth, 1); j++;\r
817     XtSetArg(args[j], XtNfromVert, engRule); j++;\r
818     XtSetArg(args[j], XtNeditType, XawtextEdit);  j++;\r
819     XtSetArg(args[j], XtNuseStringInPlace, False);  j++;\r
820     XtSetArg(args[j], XtNstring, def);  j++;\r
821     XtSetArg(args[j], XtNdisplayCaret, False);  j++;\r
822     XtSetArg(args[j], XtNtop, XtChainBottom);  j++;\r
823     XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;\r
824     XtSetArg(args[j], XtNleft, XtChainLeft);  j++;\r
825     XtSetArg(args[j], XtNright, XtChainLeft);  j++;\r
826     XtSetArg(args[j], XtNresizable, True);  j++;\r
827     XtSetArg(args[j], XtNwidth,  30);  j++;\r
828 //    XtSetArg(args[j], XtNheight, 20);  j++;\r
829     engRepeat = XtCreateManagedWidget("Repeats", asciiTextWidgetClass, form, args, j);\r
830     XtAddEventHandler(engRepeat, ButtonPressMask, False, SetFocus, (XtPointer) popup);\r
831 \r
832     j= 0;\r
833     XtSetArg(args[j], XtNlabel, _("-fold repeat is draw")); j++;\r
834     XtSetArg(args[j], XtNjustify, XtJustifyLeft); j++;\r
835     XtSetArg(args[j], XtNborderWidth, 0); j++;\r
836     XtSetArg(args[j], XtNfromVert, engRule); j++;\r
837     XtSetArg(args[j], XtNfromHoriz, engRepeat); j++;\r
838     XtSetArg(args[j], XtNtop, XtChainBottom);  j++;\r
839     XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;\r
840     XtSetArg(args[j], XtNleft, XtChainLeft);  j++;\r
841     XtSetArg(args[j], XtNright, XtChainLeft);  j++;\r
842 //    XtSetArg(args[j], XtNwidth,  130);  j++;\r
843 //    XtSetArg(args[j], XtNheight, 20);  j++;\r
844     tcMess2 = XtCreateManagedWidget("MPStext", labelWidgetClass, form, args, j);\r
845 \r
846     j=0;\r
847     XtSetArg(args[j], XtNfromVert, engRepeat);  j++;\r
848     XtSetArg(args[j], XtNfromHoriz, tcMess2);  j++;\r
849     XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;\r
850     XtSetArg(args[j], XtNtop, XtChainBottom);  j++;\r
851     XtSetArg(args[j], XtNleft, XtChainRight);  j++;\r
852     XtSetArg(args[j], XtNright, XtChainRight);  j++;\r
853     b_ok= XtCreateManagedWidget(_("OK"), commandWidgetClass, form, args, j);   \r
854     XtAddCallback(b_ok, XtNcallback, EngineCallback, (XtPointer) 0);\r
855 \r
856     j=0;\r
857     XtSetArg(args[j], XtNfromVert, engRepeat);  j++;\r
858     XtSetArg(args[j], XtNfromHoriz, b_ok);  j++;\r
859     XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;\r
860     XtSetArg(args[j], XtNtop, XtChainBottom);  j++;\r
861     XtSetArg(args[j], XtNleft, XtChainRight);  j++;\r
862     XtSetArg(args[j], XtNright, XtChainRight);  j++;\r
863     b_cancel= XtCreateManagedWidget(_("cancel"), commandWidgetClass,\r
864                                    form, args, j);   \r
865     XtAddCallback(b_cancel, XtNcallback, EnginePopDown, (XtPointer) 0);\r
866 \r
867     XtRealizeWidget(popup);\r
868     CatchDeleteWindow(popup, "EnginePopDown");\r
869     \r
870     XQueryPointer(xDisplay, xBoardWindow, &root, &child,\r
871                   &x, &y, &win_x, &win_y, &mask);\r
872     \r
873     XtSetArg(args[0], XtNx, x - 10);\r
874     XtSetArg(args[1], XtNy, y - 30);\r
875     XtSetValues(popup, args, 2);\r
876     \r
877     XtPopup(popup, XtGrabExclusive);\r
878     EngineUp = True;\r
879     \r
880     previous = NULL;\r
881     SetFocus(engThreshold, popup, (XEvent*) NULL, False);\r
882 }\r
883 \r
884 void EngineMenuProc(w, event, prms, nprms)\r
885      Widget w;\r
886      XEvent *event;\r
887      String *prms;\r
888      Cardinal *nprms;\r
889 {\r
890    EnginePopUp();\r
891 }\r
892 \r
893 //--------------------------- New-Variant Menu PopUp -----------------------------------\r
894 struct NewVarButton {\r
895   char   *name;\r
896   char *color;\r
897   Widget handle;\r
898   VariantClass variant;\r
899 };\r
900 \r
901 struct NewVarButton buttonDesc[] = {\r
902     {N_("normal"),            "#FFFFFF", 0, VariantNormal},\r
903     {N_("FRC"),               "#FFFFFF", 0, VariantFischeRandom},\r
904     {N_("wild castle"),       "#FFFFFF", 0, VariantWildCastle},\r
905     {N_("no castle"),         "#FFFFFF", 0, VariantNoCastle},\r
906     {N_("knightmate"),        "#FFFFFF", 0, VariantKnightmate},\r
907     {N_("berolina"),          "#FFFFFF", 0, VariantBerolina},\r
908     {N_("cylinder"),          "#FFFFFF", 0, VariantCylinder},\r
909     {N_("shatranj"),          "#FFFFFF", 0, VariantShatranj},\r
910     {N_("atomic"),            "#FFFFFF", 0, VariantAtomic},\r
911     {N_("two kings"),         "#FFFFFF", 0, VariantTwoKings},\r
912     {N_("3-checks"),          "#FFFFFF", 0, Variant3Check},\r
913     {N_("suicide"),           "#FFFFBF", 0, VariantSuicide},\r
914     {N_("give-away"),         "#FFFFBF", 0, VariantGiveaway},\r
915     {N_("losers"),            "#FFFFBF", 0, VariantLosers},\r
916     {N_("fairy"),             "#BFBFBF", 0, VariantFairy},\r
917     {N_("Superchess"),        "#FFBFBF", 0, VariantSuper},\r
918     {N_("crazyhouse"),        "#FFBFBF", 0, VariantCrazyhouse},\r
919     {N_("bughouse"),          "#FFBFBF", 0, VariantBughouse},\r
920     {N_("shogi (9x9)"),       "#BFFFFF", 0, VariantShogi},\r
921     {N_("xiangqi (9x10)"),    "#BFFFFF", 0, VariantXiangqi},\r
922     {N_("courier (12x8)"),    "#BFFFBF", 0, VariantCourier},\r
923     {N_("janus (10x8)"),      "#BFBFFF", 0, VariantJanus},\r
924     {N_("Capablanca (10x8)"), "#BFBFFF", 0, VariantCapablanca},\r
925     {N_("CRC (10x8)"),        "#BFBFFF", 0, VariantCapaRandom},\r
926 #ifdef GOTHIC\r
927     {N_("Gothic (10x8)"),     "#BFBFFF", 0, VariantGothic},\r
928 #endif\r
929 #ifdef FALCON\r
930     {N_("Falcon (10x8)"),     "#BFBFFF", 0, VariantFalcon},\r
931 #endif\r
932     {NULL,                0, 0, (VariantClass) 0}\r
933 };\r
934 \r
935 int NewVariantUp;\r
936 Widget NewVariantShell;\r
937 \r
938 void NewVariantPopDown()\r
939 {\r
940     if (!NewVariantUp) return;\r
941     XtPopdown(NewVariantShell);\r
942     XtDestroyWidget(NewVariantShell);\r
943     NewVariantUp = False;\r
944     ModeHighlight();\r
945 }\r
946 \r
947 void NewVariantCallback(w, client_data, call_data)\r
948      Widget w;\r
949      XtPointer client_data, call_data;\r
950 {\r
951     String name;\r
952     Widget w2;\r
953     Arg args[16];\r
954     char buf[80];\r
955     VariantClass v;\r
956     \r
957     XtSetArg(args[0], XtNlabel, &name);\r
958     XtGetValues(w, args, 1);\r
959     \r
960     if (strcmp(name, _("  OK  ")) == 0) {\r
961         int nr = (int) XawToggleGetCurrent(buttonDesc[0].handle) - 1;\r
962         if(nr < 0) return;\r
963         v = buttonDesc[nr].variant;\r
964         if(!appData.noChessProgram) { \r
965             char *name = VariantName(v), buf[MSG_SIZ];\r
966             if (first.protocolVersion > 1 && StrStr(first.variants, name) == NULL) {\r
967                 /* [HGM] in protocol 2 we check if variant is suported by engine */\r
968                 sprintf(buf, _("Variant %s not supported by %s"), name, first.tidy);\r
969                 DisplayError(buf, 0);\r
970 //              NewVariantPopDown();\r
971                 return; /* ignore OK if first engine does not support it */\r
972             } else\r
973             if (second.initDone && second.protocolVersion > 1 && StrStr(second.variants, name) == NULL) {\r
974                 sprintf(buf, _("Warning: second engine (%s) does not support this!"), second.tidy);\r
975                 DisplayError(buf, 0);   /* use of second engine is optional; only warn user */\r
976             }\r
977         }\r
978 \r
979         gameInfo.variant = v;\r
980         appData.variant = VariantName(v);\r
981 \r
982         shuffleOpenings = FALSE; /* [HGM] shuffle: possible shuffle reset when we switch */\r
983         startedFromPositionFile = FALSE; /* [HGM] loadPos: no longer valid in new variant */\r
984         appData.pieceToCharTable = NULL;\r
985         Reset(True, True);\r
986         NewVariantPopDown();\r
987         return;\r
988     }\r
989 }\r
990 \r
991 void NewVariantPopUp()\r
992 {\r
993     Arg args[16];\r
994     Widget popup, layout, dialog, edit, form, last = NULL, b_ok, b_cancel;\r
995     Window root, child;\r
996     int x, y, i, j;\r
997     int win_x, win_y;\r
998     unsigned int mask;\r
999     char def[80];\r
1000     XrmValue vFrom, vTo;\r
1001 \r
1002     i = 0;\r
1003     XtSetArg(args[i], XtNresizable, True); i++;\r
1004 //    XtSetArg(args[i], XtNwidth, 250); i++;\r
1005 //    XtSetArg(args[i], XtNheight, 300); i++;\r
1006     NewVariantShell = popup =\r
1007       XtCreatePopupShell(_("NewVariant Menu"), transientShellWidgetClass,\r
1008                          shellWidget, args, i);\r
1009     \r
1010     layout =\r
1011       XtCreateManagedWidget(layoutName, formWidgetClass, popup,\r
1012                             layoutArgs, XtNumber(layoutArgs));\r
1013   \r
1014     form =\r
1015       XtCreateManagedWidget("form", formWidgetClass, layout,\r
1016                             formArgs, XtNumber(formArgs));\r
1017   \r
1018     for(i = 0; buttonDesc[i].name != NULL; i++) {\r
1019         Pixel buttonColor;\r
1020         if (!appData.monoMode) {\r
1021             vFrom.addr = (caddr_t) buttonDesc[i].color;\r
1022             vFrom.size = strlen(buttonDesc[i].color);\r
1023             XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);\r
1024             if (vTo.addr == NULL) {\r
1025                 buttonColor = (Pixel) -1;\r
1026             } else {\r
1027                 buttonColor = *(Pixel *) vTo.addr;\r
1028             }\r
1029         }\r
1030     \r
1031         j = 0;\r
1032         XtSetArg(args[j], XtNradioGroup, last); j++;\r
1033         XtSetArg(args[j], XtNwidth, 125); j++;\r
1034 //      XtSetArg(args[j], XtNheight, 16); j++;\r
1035         XtSetArg(args[j], XtNfromVert, i == 15 ? NULL : last); j++;\r
1036         XtSetArg(args[j], XtNfromHoriz, i < 15 ? NULL : buttonDesc[i-15].handle); j++;\r
1037         XtSetArg(args[j], XtNradioData, i+1); j++;\r
1038         XtSetArg(args[j], XtNbackground, buttonColor); j++;\r
1039         XtSetArg(args[j], XtNstate, gameInfo.variant == buttonDesc[i].variant); j++;\r
1040         buttonDesc[i].handle = last =\r
1041             XtCreateManagedWidget(buttonDesc[i].name, toggleWidgetClass, form, args, j);\r
1042     }\r
1043 \r
1044     j=0;\r
1045     XtSetArg(args[j], XtNfromVert, buttonDesc[12].handle);  j++;\r
1046     XtSetArg(args[j], XtNfromHoriz, buttonDesc[12].handle);  j++;\r
1047     XtSetArg(args[j], XtNheight, 35); j++;\r
1048 //    XtSetArg(args[j], XtNwidth, 60); j++;\r
1049     XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;\r
1050     XtSetArg(args[j], XtNtop, XtChainBottom);  j++;\r
1051     XtSetArg(args[j], XtNleft, XtChainRight);  j++;\r
1052     XtSetArg(args[j], XtNright, XtChainRight);  j++;\r
1053     b_cancel= XtCreateManagedWidget(_("CANCEL"), commandWidgetClass, form, args, j);   \r
1054     XtAddCallback(b_cancel, XtNcallback, NewVariantPopDown, (XtPointer) 0);\r
1055 \r
1056     j=0;\r
1057     XtSetArg(args[j], XtNfromHoriz, b_cancel);  j++;\r
1058     XtSetArg(args[j], XtNfromVert, buttonDesc[12].handle);  j++;\r
1059     XtSetArg(args[j], XtNheight, 35); j++;\r
1060 //    XtSetArg(args[j], XtNwidth, 60); j++;\r
1061     XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;\r
1062     XtSetArg(args[j], XtNtop, XtChainBottom);  j++;\r
1063     XtSetArg(args[j], XtNleft, XtChainRight);  j++;\r
1064     XtSetArg(args[j], XtNright, XtChainRight);  j++;\r
1065     b_ok= XtCreateManagedWidget(_("  OK  "), commandWidgetClass, form, args, j);   \r
1066     XtAddCallback(b_ok, XtNcallback, NewVariantCallback, (XtPointer) 0);\r
1067 \r
1068     XtRealizeWidget(popup);\r
1069     CatchDeleteWindow(popup, "NewVariantPopDown");\r
1070     \r
1071     XQueryPointer(xDisplay, xBoardWindow, &root, &child,\r
1072                   &x, &y, &win_x, &win_y, &mask);\r
1073     \r
1074     XtSetArg(args[0], XtNx, x - 10);\r
1075     XtSetArg(args[1], XtNy, y - 30);\r
1076     XtSetValues(popup, args, 2);\r
1077     \r
1078     XtPopup(popup, XtGrabExclusive);\r
1079     NewVariantUp = True;\r
1080 }\r
1081 \r
1082 void NewVariantProc(w, event, prms, nprms)\r
1083      Widget w;\r
1084      XEvent *event;\r
1085      String *prms;\r
1086      Cardinal *nprms;\r
1087 {\r
1088    NewVariantPopUp();\r
1089 }\r
1090 \r
1091 //--------------------------- UCI Menu Popup ------------------------------------------\r
1092 int UciUp;\r
1093 Widget UciShell;\r
1094 \r
1095 struct UciControl {\r
1096   char *name;\r
1097   Widget handle;\r
1098   void *ptr;\r
1099 };\r
1100 \r
1101 struct UciControl controlDesc[] = {\r
1102   {N_("maximum nr of CPUs:"), 0, &appData.smpCores},\r
1103   {N_("Polyglot Directory:"), 0, &appData.polyglotDir},\r
1104   {N_("Hash Size (MB):"),     0, &appData.defaultHashSize},\r
1105   {N_("EGTB Path:"),          0, &appData.defaultPathEGTB},\r
1106   {N_("EGTB Cache (MB):"),    0, &appData.defaultCacheSizeEGTB},\r
1107   {N_("Polyglot Book:"),      0, &appData.polyglotBook},\r
1108   {NULL, 0, NULL},\r
1109 };\r
1110 \r
1111 void UciPopDown()\r
1112 {\r
1113     if (!UciUp) return;\r
1114     XtPopdown(UciShell);\r
1115     XtDestroyWidget(UciShell);\r
1116     UciUp = False;\r
1117     ModeHighlight();\r
1118 }\r
1119 \r
1120 void UciCallback(w, client_data, call_data)\r
1121      Widget w;\r
1122      XtPointer client_data, call_data;\r
1123 {\r
1124     String name;\r
1125     Arg args[16];\r
1126     char buf[80];\r
1127     int oldCores = appData.smpCores, ponder = 0;\r
1128     \r
1129     XtSetArg(args[0], XtNlabel, &name);\r
1130     XtGetValues(w, args, 1);\r
1131     \r
1132     if (strcmp(name, _("OK")) == 0) {\r
1133         int nr, i, j; String name;\r
1134         for(i=0; i<6; i++) {\r
1135             XtSetArg(args[0], XtNstring, &name);\r
1136             XtGetValues(controlDesc[i].handle, args, 1);\r
1137             if(i&1) {\r
1138                 if(name)\r
1139                     *(char**) controlDesc[i].ptr = strdup(name);\r
1140             } else {\r
1141                 if(sscanf(name, "%d", &j) == 1) \r
1142                     *(int*) controlDesc[i].ptr = j;\r
1143             }\r
1144         }\r
1145         XtSetArg(args[0], XtNstate, &appData.usePolyglotBook);\r
1146         XtGetValues(w1, args, 1);\r
1147         XtSetArg(args[0], XtNstate, &appData.firstHasOwnBookUCI);\r
1148         XtGetValues(w2, args, 1);\r
1149         XtSetArg(args[0], XtNstate, &appData.secondHasOwnBookUCI);\r
1150         XtGetValues(w3, args, 1);\r
1151         XtSetArg(args[0], XtNstate, &ponder);\r
1152         XtGetValues(w4, args, 1);\r
1153 \r
1154         // adjust setting in other menu for duplicates \r
1155         // (perhaps duplicates should be removed from general Option Menu?)\r
1156         XtSetArg(args[0], XtNleftBitmap, ponder ? xMarkPixmap : None);\r
1157         XtSetValues(XtNameToWidget(menuBarWidget,\r
1158                                    "menuOptions.Ponder Next Move"), args, 1);\r
1159 \r
1160         // make sure changes are sent to first engine by re-initializing it\r
1161         // if it was already started pre-emptively at end of previous game\r
1162         if(gameMode == BeginningOfGame) Reset(True, True); else {\r
1163             // Some changed setting need immediate sending always.\r
1164             PonderNextMoveEvent(ponder);\r
1165             if(oldCores != appData.smpCores)\r
1166                 NewSettingEvent(False, "cores", appData.smpCores);\r
1167       }\r
1168       UciPopDown();\r
1169       return;\r
1170     }\r
1171 }\r
1172 \r
1173 void UciPopUp()\r
1174 {\r
1175     Arg args[16];\r
1176     Widget popup, layout, dialog, edit, form, b_ok, b_cancel, last = NULL, new, upperLeft;\r
1177     Window root, child;\r
1178     int x, y, i, j;\r
1179     int win_x, win_y;\r
1180     unsigned int mask;\r
1181     char def[80];\r
1182     \r
1183     i = 0;\r
1184     XtSetArg(args[i], XtNresizable, True); i++;\r
1185 //    XtSetArg(args[i], XtNwidth, 300); i++;\r
1186     UciShell = popup =\r
1187       XtCreatePopupShell(_("Engine Settings"), transientShellWidgetClass,\r
1188                          shellWidget, args, i);\r
1189     \r
1190     layout =\r
1191       XtCreateManagedWidget(layoutName, formWidgetClass, popup,\r
1192                             layoutArgs, XtNumber(layoutArgs));\r
1193   \r
1194     \r
1195     form =\r
1196       XtCreateManagedWidget("form", formWidgetClass, layout,\r
1197                             formArgs, XtNumber(formArgs));\r
1198   \r
1199     j = 0;\r
1200     XtSetArg(args[j], XtNtop, XtChainTop);  j++;\r
1201     XtSetArg(args[j], XtNbottom, XtChainTop);  j++;\r
1202     XtSetArg(args[j], XtNleft, XtChainLeft);  j++;\r
1203 //    XtSetArg(args[j], XtNheight, 20); j++;\r
1204     for(i = 0; controlDesc[i].name != NULL; i++) {\r
1205         j = 3;\r
1206         XtSetArg(args[j], XtNfromVert, last); j++;\r
1207 //      XtSetArg(args[j], XtNwidth, 130); j++;\r
1208         XtSetArg(args[j], XtNjustify, XtJustifyLeft); j++;\r
1209         XtSetArg(args[j], XtNright, XtChainLeft);  j++;\r
1210         XtSetArg(args[j], XtNborderWidth, 0); j++;\r
1211         new = XtCreateManagedWidget(controlDesc[i].name, labelWidgetClass, form, args, j);\r
1212         if(i==0) upperLeft = new;\r
1213 \r
1214         j = 4;\r
1215         XtSetArg(args[j], XtNborderWidth, 1); j++;\r
1216         XtSetArg(args[j], XtNeditType, XawtextEdit);  j++;\r
1217         XtSetArg(args[j], XtNuseStringInPlace, False);  j++;\r
1218         XtSetArg(args[j], XtNdisplayCaret, False);  j++;\r
1219         XtSetArg(args[j], XtNright, XtChainRight);  j++;\r
1220         XtSetArg(args[j], XtNresizable, True);  j++;\r
1221         XtSetArg(args[j], XtNwidth, i&1 ? 245 : 50); j++;\r
1222         if(i&1) {\r
1223             XtSetArg(args[j], XtNstring, * (char**) controlDesc[i].ptr ? \r
1224                                          * (char**) controlDesc[i].ptr : ""); j++;\r
1225         } else {\r
1226             sprintf(def, "%d", * (int*) controlDesc[i].ptr);\r
1227             XtSetArg(args[j], XtNstring, def); j++;\r
1228         }\r
1229         XtSetArg(args[j], XtNfromHoriz, upperLeft); j++;\r
1230         controlDesc[i].handle = last =\r
1231             XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);\r
1232         XtAddEventHandler(last, ButtonPressMask, False, SetFocus, (XtPointer) popup);\r
1233     }\r
1234 \r
1235     j=0;\r
1236     XtSetArg(args[j], XtNfromHoriz, controlDesc[0].handle);  j++;\r
1237     XtSetArg(args[j], XtNbottom, XtChainTop);  j++;\r
1238     XtSetArg(args[j], XtNtop, XtChainTop);  j++;\r
1239     XtSetArg(args[j], XtNleft, XtChainRight);  j++;\r
1240     XtSetArg(args[j], XtNright, XtChainRight);  j++;\r
1241     XtSetArg(args[j], XtNstate, appData.ponderNextMove);  j++;\r
1242     w4 = XtCreateManagedWidget(_("Ponder"), toggleWidgetClass, form, args, j);   \r
1243 \r
1244     j=0;\r
1245     XtSetArg(args[j], XtNfromVert, last);  j++;\r
1246     XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;\r
1247     XtSetArg(args[j], XtNtop, XtChainBottom);  j++;\r
1248     XtSetArg(args[j], XtNleft, XtChainLeft);  j++;\r
1249     XtSetArg(args[j], XtNright, XtChainLeft);  j++;\r
1250     b_ok = XtCreateManagedWidget(_("OK"), commandWidgetClass, form, args, j);   \r
1251     XtAddCallback(b_ok, XtNcallback, UciCallback, (XtPointer) 0);\r
1252 \r
1253     XtSetArg(args[j], XtNfromHoriz, b_ok);  j++;\r
1254     b_cancel = XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);   \r
1255     XtAddCallback(b_cancel, XtNcallback, UciPopDown, (XtPointer) 0);\r
1256 \r
1257     j = 5;\r
1258     XtSetArg(args[j], XtNfromHoriz, upperLeft);  j++;\r
1259     XtSetArg(args[j], XtNstate, appData.usePolyglotBook);  j++;\r
1260     w1 = XtCreateManagedWidget(_(" use book "), toggleWidgetClass, form, args, j);   \r
1261 //    XtAddCallback(w1, XtNcallback, UciCallback, (XtPointer) 0);\r
1262 \r
1263     j = 5;\r
1264     XtSetArg(args[j], XtNfromHoriz, w1);  j++;\r
1265     XtSetArg(args[j], XtNstate, appData.firstHasOwnBookUCI);  j++;\r
1266     w2 = XtCreateManagedWidget(_("own book 1"), toggleWidgetClass, form, args, j);   \r
1267 //    XtAddCallback(w2, XtNcallback, UciCallback, (XtPointer) 0);\r
1268 \r
1269     j = 5;\r
1270     XtSetArg(args[j], XtNfromHoriz, w2);  j++;\r
1271     XtSetArg(args[j], XtNstate, appData.secondHasOwnBookUCI);  j++;\r
1272     w3 = XtCreateManagedWidget(_("own book 2"), toggleWidgetClass, form, args, j);   \r
1273 //    XtAddCallback(w3, XtNcallback, UciCallback, (XtPointer) 0);\r
1274 \r
1275     XtRealizeWidget(popup);\r
1276     CatchDeleteWindow(popup, "UciPopDown");\r
1277     \r
1278     XQueryPointer(xDisplay, xBoardWindow, &root, &child,\r
1279                   &x, &y, &win_x, &win_y, &mask);\r
1280     \r
1281     XtSetArg(args[0], XtNx, x - 10);\r
1282     XtSetArg(args[1], XtNy, y - 30);\r
1283     XtSetValues(popup, args, 2);\r
1284     \r
1285     XtPopup(popup, XtGrabExclusive);\r
1286     UciUp = True;\r
1287 \r
1288     previous = NULL;\r
1289     SetFocus(controlDesc[2].handle, popup, (XEvent*) NULL, False);\r
1290 //    XtSetKeyboardFocus(popup, controlDesc[1].handle);\r
1291 }\r
1292 \r
1293 void UciMenuProc(w, event, prms, nprms)\r
1294      Widget w;\r
1295      XEvent *event;\r
1296      String *prms;\r
1297      Cardinal *nprms;\r
1298 {\r
1299    UciPopUp();\r
1300 }\r
1301 \r
1302 //--------------------------- Engine-specific options menu ----------------------------------\r
1303 \r
1304 int SettingsUp;\r
1305 Widget SettingsShell;\r
1306 int values[MAX_OPTIONS];\r
1307 ChessProgramState *currentCps;\r
1308 \r
1309 void SettingsPopDown()\r
1310 {\r
1311     if (!SettingsUp) return;\r
1312     XtPopdown(SettingsShell);\r
1313     XtDestroyWidget(SettingsShell);\r
1314     SettingsUp = False;\r
1315     ModeHighlight();\r
1316 }\r
1317 \r
1318 void SpinCallback(w, client_data, call_data)\r
1319      Widget w;\r
1320      XtPointer client_data, call_data;\r
1321 {\r
1322     String name, val;\r
1323     Widget w2;\r
1324     Arg args[16];\r
1325     char buf[MSG_SIZ];\r
1326     int i, j;\r
1327     \r
1328     XtSetArg(args[0], XtNlabel, &name);\r
1329     XtGetValues(w, args, 1);\r
1330     \r
1331     j = 0;\r
1332     XtSetArg(args[0], XtNstring, &val);\r
1333     XtGetValues(currentCps->option[(int)client_data].handle, args, 1);\r
1334     sscanf(val, "%d", &j);\r
1335     if (strcmp(name, "+") == 0) {\r
1336         if(++j > currentCps->option[(int)client_data].max) return;\r
1337     } else\r
1338     if (strcmp(name, "-") == 0) {\r
1339         if(--j < currentCps->option[(int)client_data].min) return;\r
1340     } else return;\r
1341     sprintf(buf, "%d", j);\r
1342     XtSetArg(args[0], XtNstring, buf);\r
1343     XtSetValues(currentCps->option[(int)client_data].handle, args, 1);\r
1344 }\r
1345 \r
1346 void SettingsCallback(w, client_data, call_data)\r
1347      Widget w;\r
1348      XtPointer client_data, call_data;\r
1349 {\r
1350     String name, val;\r
1351     Widget w2;\r
1352     Arg args[16];\r
1353     char buf[MSG_SIZ];\r
1354     int i, j;\r
1355     \r
1356     XtSetArg(args[0], XtNlabel, &name);\r
1357     XtGetValues(w, args, 1);\r
1358     \r
1359     if (strcmp(name, _("cancel")) == 0) {\r
1360         SettingsPopDown();\r
1361         return;\r
1362     }\r
1363     if (strcmp(name, _("OK")) == 0 || (int)client_data) { // save buttons imply OK\r
1364         int nr;\r
1365 \r
1366         for(i=0; i<currentCps->nrOptions; i++) { // send all options that had to be OK-ed to engine\r
1367             switch(currentCps->option[i].type) {\r
1368                 case TextBox:\r
1369                     XtSetArg(args[0], XtNstring, &val);\r
1370                     XtGetValues(currentCps->option[i].handle, args, 1);\r
1371                     if(strcmp(currentCps->option[i].textValue, val)) {\r
1372                         strcpy(currentCps->option[i].textValue, val);\r
1373                         sprintf(buf, _("option %s %s\n"), currentCps->option[i].name, val);\r
1374                         SendToProgram(buf, currentCps);\r
1375                     }\r
1376                     break;\r
1377                 case Spin:\r
1378                     XtSetArg(args[0], XtNstring, &val);\r
1379                     XtGetValues(currentCps->option[i].handle, args, 1);\r
1380                     sscanf(val, "%d", &j);\r
1381                     if(j > currentCps->option[i].max) j = currentCps->option[i].max;\r
1382                     if(j < currentCps->option[i].min) j = currentCps->option[i].min;\r
1383                     if(currentCps->option[i].value != j) {\r
1384                         currentCps->option[i].value = j;\r
1385                         sprintf(buf, _("option %s %d\n"), currentCps->option[i].name, j);\r
1386                         SendToProgram(buf, currentCps);\r
1387                     }\r
1388                     break;\r
1389                 case CheckBox:\r
1390                     j = 0;\r
1391                     XtSetArg(args[0], XtNstate, &j);\r
1392                     XtGetValues(currentCps->option[i].handle, args, 1);\r
1393                     if(currentCps->option[i].value != j) {\r
1394                         currentCps->option[i].value = j;\r
1395                         sprintf(buf, _("option %s %d\n"), currentCps->option[i].name, j);\r
1396                         SendToProgram(buf, currentCps);\r
1397                     }\r
1398                     break;\r
1399                 case ComboBox:\r
1400                     if(currentCps->option[i].value != values[i]) {\r
1401                         currentCps->option[i].value = values[i];\r
1402                         sprintf(buf, _("option %s %s\n"), currentCps->option[i].name, \r
1403                                 ((char**)currentCps->option[i].textValue)[values[i]]);\r
1404                         SendToProgram(buf, currentCps);\r
1405                     }\r
1406                     break;\r
1407             }\r
1408         }\r
1409         if((int)client_data) { // send save-button command to engine\r
1410             sprintf(buf, _("option %s\n"), name);\r
1411             SendToProgram(buf, currentCps);\r
1412         }\r
1413         SettingsPopDown();\r
1414         return;\r
1415     }\r
1416     sprintf(buf, _("option %s\n"), name);\r
1417     SendToProgram(buf, currentCps);\r
1418 }\r
1419 \r
1420 void ComboSelect(w, addr, index) // callback for all combo items\r
1421      Widget w;\r
1422      caddr_t addr;\r
1423      caddr_t index;\r
1424 {\r
1425     Arg args[16];\r
1426     int i = ((int)addr)>>8;\r
1427     int j = 255 & (int) addr;\r
1428 \r
1429     values[i] = j; // store in temporary, for transfer at OK\r
1430     XtSetArg(args[0], XtNlabel, ((char**)currentCps->option[i].textValue)[j]);\r
1431     XtSetValues(currentCps->option[i].handle, args, 1);\r
1432 }\r
1433 \r
1434 void CreateComboPopup(parent, name, n, mb)\r
1435      Widget parent;\r
1436      String name;\r
1437      int n;\r
1438      char *mb[];\r
1439 {\r
1440     int i=0, j;\r
1441     Widget menu, entry;\r
1442     Arg args[16];\r
1443 \r
1444     menu = XtCreatePopupShell(name, simpleMenuWidgetClass,\r
1445                               parent, NULL, 0);\r
1446     j = 0;\r
1447     XtSetArg(args[j], XtNwidth, 100);  j++;\r
1448 //    XtSetArg(args[j], XtNright, XtChainRight);  j++;\r
1449     while (mb[i] != NULL) {\r
1450             entry = XtCreateManagedWidget(mb[i], smeBSBObjectClass,\r
1451                                           menu, args, j);\r
1452             XtAddCallback(entry, XtNcallback,\r
1453                           (XtCallbackProc) ComboSelect,\r
1454                           (caddr_t) (256*n+i));\r
1455         i++;\r
1456     }\r
1457 }       \r
1458 \r
1459 void SettingsPopUp(ChessProgramState *cps)\r
1460 {\r
1461     Arg args[16];\r
1462     Widget popup, layout, dialog, edit, form, oldform, last, b_ok, b_cancel;\r
1463     Window root, child;\r
1464     int x, y, i, j;\r
1465     int win_x, win_y;\r
1466     unsigned int mask;\r
1467     char def[80], *p, *q;\r
1468 \r
1469     // to do: start up second engine if needed\r
1470     if(!cps->initDone || !cps->nrOptions) return; // nothing to be done\r
1471     currentCps = cps;\r
1472 \r
1473     i = 0;\r
1474     XtSetArg(args[i], XtNresizable, True); i++;\r
1475     SettingsShell = popup =\r
1476       XtCreatePopupShell(_("Settings Menu"), transientShellWidgetClass,\r
1477                          shellWidget, args, i);\r
1478     \r
1479     layout =\r
1480       XtCreateManagedWidget(layoutName, formWidgetClass, popup,\r
1481                             layoutArgs, XtNumber(layoutArgs));\r
1482   \r
1483     form =\r
1484       XtCreateManagedWidget(layoutName, formWidgetClass, layout,\r
1485                             formArgs, XtNumber(formArgs));\r
1486   \r
1487     last = NULL;\r
1488     for(i=0; i<cps->nrOptions; i++) {\r
1489         Widget box;\r
1490         switch(cps->option[i].type) {\r
1491           case Spin:\r
1492             sprintf(def, "%d", cps->option[i].value);\r
1493           case TextBox:\r
1494             j=0;\r
1495             XtSetArg(args[j], XtNfromVert, last);  j++;\r
1496             XtSetArg(args[j], XtNborderWidth, 0);  j++;\r
1497             XtSetArg(args[j], XtNjustify, XtJustifyLeft);  j++;\r
1498             dialog = XtCreateManagedWidget(cps->option[i].name, labelWidgetClass, form, args, j);   \r
1499             j=0;\r
1500             XtSetArg(args[j], XtNfromVert, last);  j++;\r
1501             XtSetArg(args[j], XtNfromHoriz, dialog);  j++;\r
1502             XtSetArg(args[j], XtNborderWidth, 1); j++;\r
1503             XtSetArg(args[j], XtNwidth, cps->option[i].type == Spin ? 40 : 100); j++;\r
1504             XtSetArg(args[j], XtNeditType, XawtextEdit);  j++;\r
1505             XtSetArg(args[j], XtNuseStringInPlace, False);  j++;\r
1506             XtSetArg(args[j], XtNdisplayCaret, False);  j++;\r
1507             XtSetArg(args[j], XtNright, XtChainRight);  j++;\r
1508             XtSetArg(args[j], XtNresizable, True);  j++;\r
1509             XtSetArg(args[j], XtNstring, cps->option[i].type==Spin ? def : cps->option[i].textValue);  j++;\r
1510             edit = last;\r
1511             cps->option[i].handle = (void*)\r
1512                 (last = XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j));   \r
1513             XtAddEventHandler(box, ButtonPressMask, False, SetFocus, (XtPointer) popup);\r
1514             if(cps->option[i].type == TextBox) break;\r
1515             // add increment and decrement controls for spin\r
1516             j=0;\r
1517             XtSetArg(args[j], XtNfromVert, edit);  j++;\r
1518             XtSetArg(args[j], XtNfromHoriz, box);  j++;\r
1519             XtSetArg(args[j], XtNheight, 10);  j++;\r
1520             XtSetArg(args[j], XtNwidth, 20);  j++;\r
1521             edit = XtCreateManagedWidget("+", commandWidgetClass, form, args, j);\r
1522             XtAddCallback(edit, XtNcallback, SpinCallback, (XtPointer) i);\r
1523             j=0;\r
1524             XtSetArg(args[j], XtNfromVert, edit);  j++;\r
1525             XtSetArg(args[j], XtNfromHoriz, last);  j++;\r
1526             XtSetArg(args[j], XtNheight, 10);  j++;\r
1527             XtSetArg(args[j], XtNwidth, 20);  j++;\r
1528             last = XtCreateManagedWidget("-", commandWidgetClass, form, args, j);\r
1529             XtAddCallback(last, XtNcallback, SpinCallback, (XtPointer) i);\r
1530             break;\r
1531           case CheckBox:\r
1532             j=0;\r
1533             XtSetArg(args[j], XtNfromVert, last);  j++;\r
1534             XtSetArg(args[j], XtNwidth, 10);  j++;\r
1535             XtSetArg(args[j], XtNheight, 10);  j++;\r
1536             XtSetArg(args[j], XtNstate, cps->option[i].value);  j++;\r
1537             cps->option[i].handle = (void*) \r
1538                 (dialog = XtCreateManagedWidget(" ", toggleWidgetClass, form, args, j));   \r
1539             j=0;\r
1540             XtSetArg(args[j], XtNfromVert, last);  j++;\r
1541             XtSetArg(args[j], XtNfromHoriz, dialog);  j++;\r
1542             XtSetArg(args[j], XtNborderWidth, 0);  j++;\r
1543             XtSetArg(args[j], XtNjustify, XtJustifyLeft);  j++;\r
1544             last = XtCreateManagedWidget(cps->option[i].name, labelWidgetClass, form, args, j);\r
1545             break;\r
1546           case SaveButton:\r
1547           case Button:\r
1548             j=0;\r
1549             XtSetArg(args[j], XtNfromVert, last);  j++;\r
1550             XtSetArg(args[j], XtNstate, cps->option[i].value);  j++;\r
1551             cps->option[i].handle = (void*) \r
1552                 (last = XtCreateManagedWidget(cps->option[i].name, commandWidgetClass, form, args, j));   \r
1553             XtAddCallback(last, XtNcallback, SettingsCallback, (XtPointer) (cps->option[i].type == SaveButton));\r
1554             break;\r
1555           case ComboBox:\r
1556             j=0;\r
1557             XtSetArg(args[j], XtNfromVert, last);  j++;\r
1558             XtSetArg(args[j], XtNborderWidth, 0);  j++;\r
1559             XtSetArg(args[j], XtNjustify, XtJustifyLeft);  j++;\r
1560             dialog = XtCreateManagedWidget(cps->option[i].name, labelWidgetClass, form, args, j);\r
1561 \r
1562             j=0;\r
1563             XtSetArg(args[j], XtNfromVert, last);  j++;\r
1564             XtSetArg(args[j], XtNfromHoriz, dialog);  j++;\r
1565             XtSetArg(args[j], XtNwidth, 100);  j++;\r
1566             XtSetArg(args[j], XtNmenuName, XtNewString(cps->option[i].name));  j++;\r
1567             XtSetArg(args[j], XtNlabel, ((char**)cps->option[i].textValue)[cps->option[i].value]);  j++;\r
1568             cps->option[i].handle = (void*) \r
1569                 (last = XtCreateManagedWidget(" ", menuButtonWidgetClass, form, args, j));   \r
1570             CreateComboPopup(last, cps->option[i].name, i, (char **) cps->option[i].textValue);\r
1571             values[i] = cps->option[i].value;\r
1572             break;\r
1573         }\r
1574     }\r
1575 \r
1576     j=0;\r
1577     XtSetArg(args[j], XtNfromVert, last);  j++;\r
1578     XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;\r
1579     XtSetArg(args[j], XtNtop, XtChainBottom);  j++;\r
1580     XtSetArg(args[j], XtNleft, XtChainLeft);  j++;\r
1581     XtSetArg(args[j], XtNright, XtChainLeft);  j++;\r
1582     b_ok = XtCreateManagedWidget(_("OK"), commandWidgetClass, form, args, j);   \r
1583     XtAddCallback(b_ok, XtNcallback, SettingsCallback, (XtPointer) 0);\r
1584 \r
1585     XtSetArg(args[j], XtNfromHoriz, b_ok);  j++;\r
1586     b_cancel = XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);   \r
1587     XtAddCallback(b_cancel, XtNcallback, SettingsPopDown, (XtPointer) 0);\r
1588 \r
1589     XtRealizeWidget(popup);\r
1590     CatchDeleteWindow(popup, "SettingsPopDown");\r
1591     \r
1592     XQueryPointer(xDisplay, xBoardWindow, &root, &child,\r
1593                   &x, &y, &win_x, &win_y, &mask);\r
1594     \r
1595     XtSetArg(args[0], XtNx, x - 10);\r
1596     XtSetArg(args[1], XtNy, y - 30);\r
1597     XtSetValues(popup, args, 2);\r
1598     \r
1599     XtPopup(popup, XtGrabExclusive);\r
1600     SettingsUp = True;\r
1601 \r
1602     previous = NULL;\r
1603     SetFocus(edit, popup, (XEvent*) NULL, False);\r
1604 }\r
1605 \r
1606 void FirstSettingsProc(w, event, prms, nprms)\r
1607      Widget w;\r
1608      XEvent *event;\r
1609      String *prms;\r
1610      Cardinal *nprms;\r
1611 {\r
1612    SettingsPopUp(&first);\r
1613 }\r
1614 \r
1615 void SecondSettingsProc(w, event, prms, nprms)\r
1616      Widget w;\r
1617      XEvent *event;\r
1618      String *prms;\r
1619      Cardinal *nprms;\r
1620 {\r
1621    SettingsPopUp(&second);\r
1622 }\r
1623 \r
1624 //--------------------------- General Popup for Cloning ----------------------------------\r
1625 #if 0\r
1626 int XXXUp;\r
1627 Widget XXXShell;\r
1628 \r
1629 void XXXPopDown()\r
1630 {\r
1631     if (!XXXUp) return;\r
1632     XtPopdown(XXXShell);\r
1633     XtDestroyWidget(XXXShell);\r
1634     XXXUp = False;\r
1635     ModeHighlight();\r
1636 }\r
1637 \r
1638 void XXXCallback(w, client_data, call_data)\r
1639      Widget w;\r
1640      XtPointer client_data, call_data;\r
1641 {\r
1642     String name;\r
1643     Widget w2;\r
1644     Arg args[16];\r
1645     char buf[80];\r
1646     \r
1647     XtSetArg(args[0], XtNlabel, &name);\r
1648     XtGetValues(w, args, 1);\r
1649     \r
1650     if (strcmp(name, _("cancel")) == 0) {\r
1651         XXXPopDown();\r
1652         return;\r
1653     }\r
1654     if (strcmp(name, _("ok")) == 0) {\r
1655         int nr; String name;\r
1656         name = XawDialogGetValueString(w2 = XtParent(w));\r
1657         if(sscanf(name ,"%d",&nr) != 1) {\r
1658             sprintf(buf, "%d", appData.defaultFrcPosition);\r
1659             XtSetArg(args[0],XtNvalue, buf); // erase bad (non-numeric) value\r
1660             XtSetValues(w2, args, 1);\r
1661             return;\r
1662         }\r
1663         XXXPopDown();\r
1664         return;\r
1665     }\r
1666 }\r
1667 \r
1668 void XXXPopUp()\r
1669 {\r
1670     Arg args[16];\r
1671     Widget popup, layout, dialog, edit;\r
1672     Window root, child;\r
1673     int x, y, i;\r
1674     int win_x, win_y;\r
1675     unsigned int mask;\r
1676     char def[80];\r
1677     \r
1678     i = 0;\r
1679     XtSetArg(args[i], XtNresizable, True); i++;\r
1680     XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;\r
1681     XXXShell = popup =\r
1682       XtCreatePopupShell(_("XXX Menu"), transientShellWidgetClass,\r
1683                          shellWidget, args, i);\r
1684     \r
1685     layout =\r
1686       XtCreateManagedWidget(layoutName, formWidgetClass, popup,\r
1687                             layoutArgs, XtNumber(layoutArgs));\r
1688   \r
1689     sprintf(def, "%d\n", appData.defaultFrcPosition);\r
1690     i = 0;\r
1691     XtSetArg(args[i], XtNlabel, ""); i++;\r
1692     XtSetArg(args[i], XtNvalue, def); i++;\r
1693     XtSetArg(args[i], XtNborderWidth, 0); i++;\r
1694     dialog = XtCreateManagedWidget("XXX", dialogWidgetClass,\r
1695                                    layout, args, i);\r
1696     \r
1697     XawDialogAddButton(dialog, _("ok"), XXXCallback, (XtPointer) dialog);\r
1698     XawDialogAddButton(dialog, _("cancel"), XXXCallback, (XtPointer) dialog);\r
1699     \r
1700     XtRealizeWidget(popup);\r
1701     CatchDeleteWindow(popup, "XXXPopDown");\r
1702     \r
1703     XQueryPointer(xDisplay, xBoardWindow, &root, &child,\r
1704                   &x, &y, &win_x, &win_y, &mask);\r
1705     \r
1706     XtSetArg(args[0], XtNx, x - 10);\r
1707     XtSetArg(args[1], XtNy, y - 30);\r
1708     XtSetValues(popup, args, 2);\r
1709     \r
1710     XtPopup(popup, XtGrabExclusive);\r
1711     XXXUp = True;\r
1712     \r
1713     edit = XtNameToWidget(dialog, "*value");\r
1714 \r
1715     previous = NULL;\r
1716     SetFocus(engThreshold, popup, (XEvent*) NULL, False);\r
1717 }\r
1718 \r
1719 void XXXMenuProc(w, event, prms, nprms)\r
1720      Widget w;\r
1721      XEvent *event;\r
1722      String *prms;\r
1723      Cardinal *nprms;\r
1724 {\r
1725    XXXPopUp();\r
1726 }\r
1727 #endif\r
1728 \r