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