PageRenderTime 64ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/xboard-4.5.2a/xoptions.c

#
C | 1873 lines | 1653 code | 158 blank | 62 comment | 301 complexity | 7b4439034da70a23c3519959c048c411 MD5 | raw file
Possible License(s): GPL-3.0, MPL-2.0-no-copyleft-exception
  1. /*
  2. * xoptions.c -- Move list window, part of X front end for XBoard
  3. *
  4. * Copyright 2000, 2009, 2010, 2011 Free Software Foundation, Inc.
  5. * ------------------------------------------------------------------------
  6. *
  7. * GNU XBoard is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation, either version 3 of the License, or (at
  10. * your option) any later version.
  11. *
  12. * GNU XBoard is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program. If not, see http://www.gnu.org/licenses/. *
  19. *
  20. *------------------------------------------------------------------------
  21. ** See the file ChangeLog for a revision history. */
  22. // [HGM] this file is the counterpart of woptions.c, containing xboard popup menus
  23. // similar to those of WinBoard, to set the most common options interactively.
  24. #include "config.h"
  25. #include <stdio.h>
  26. #include <ctype.h>
  27. #include <errno.h>
  28. #include <sys/types.h>
  29. #if STDC_HEADERS
  30. # include <stdlib.h>
  31. # include <string.h>
  32. #else /* not STDC_HEADERS */
  33. extern char *getenv();
  34. # if HAVE_STRING_H
  35. # include <string.h>
  36. # else /* not HAVE_STRING_H */
  37. # include <strings.h>
  38. # endif /* not HAVE_STRING_H */
  39. #endif /* not STDC_HEADERS */
  40. #if HAVE_UNISTD_H
  41. # include <unistd.h>
  42. #endif
  43. #include <stdint.h>
  44. #include <X11/Intrinsic.h>
  45. #include <X11/StringDefs.h>
  46. #include <X11/Shell.h>
  47. #include <X11/Xatom.h>
  48. #include <X11/Xaw/Dialog.h>
  49. #include <X11/Xaw/Form.h>
  50. #include <X11/Xaw/List.h>
  51. #include <X11/Xaw/Label.h>
  52. #include <X11/Xaw/SimpleMenu.h>
  53. #include <X11/Xaw/SmeBSB.h>
  54. #include <X11/Xaw/SmeLine.h>
  55. #include <X11/Xaw/Box.h>
  56. #include <X11/Xaw/Paned.h>
  57. #include <X11/Xaw/MenuButton.h>
  58. #include <X11/cursorfont.h>
  59. #include <X11/Xaw/Text.h>
  60. #include <X11/Xaw/AsciiText.h>
  61. #include <X11/Xaw/Viewport.h>
  62. #include <X11/Xaw/Toggle.h>
  63. #include "common.h"
  64. #include "backend.h"
  65. #include "xboard.h"
  66. #include "gettext.h"
  67. #ifdef ENABLE_NLS
  68. # define _(s) gettext (s)
  69. # define N_(s) gettext_noop (s)
  70. #else
  71. # define _(s) (s)
  72. # define N_(s) s
  73. #endif
  74. extern void SendToProgram P((char *message, ChessProgramState *cps));
  75. FILE * XsraSelFile P((Widget w, char *prompt, char *ok, char *cancel, char *failed,
  76. char *init_path, char *filter, char *mode, int (*show_entry)(), char **name_return));
  77. extern Widget formWidget, shellWidget, boardWidget, menuBarWidget;
  78. extern Display *xDisplay;
  79. extern int squareSize;
  80. extern Pixmap xMarkPixmap;
  81. extern char *layoutName;
  82. extern Window xBoardWindow;
  83. extern Arg layoutArgs[2], formArgs[2];
  84. Pixel timerForegroundPixel, timerBackgroundPixel;
  85. extern int searchTime;
  86. extern Atom wm_delete_window;
  87. extern int lineGap;
  88. // [HGM] the following code for makng menu popups was cloned from the FileNamePopUp routines
  89. static Widget previous = NULL;
  90. void SetFocus(Widget w, XtPointer data, XEvent *event, Boolean *b)
  91. {
  92. Arg args[2];
  93. char *s;
  94. if(previous) {
  95. XtSetArg(args[0], XtNdisplayCaret, False);
  96. XtSetValues(previous, args, 1);
  97. }
  98. XtSetArg(args[0], XtNstring, &s);
  99. XtGetValues(w, args, 1);
  100. XtSetArg(args[0], XtNdisplayCaret, True);
  101. XtSetArg(args[1], XtNinsertPosition, strlen(s));
  102. XtSetValues(w, args, 2);
  103. XtSetKeyboardFocus((Widget) data, w);
  104. previous = w;
  105. }
  106. //--------------------------- New Shuffle Game --------------------------------------------
  107. extern int shuffleOpenings;
  108. extern int startedFromPositionFile;
  109. int shuffleUp;
  110. Widget shuffleShell;
  111. void ShufflePopDown()
  112. {
  113. if (!shuffleUp) return;
  114. XtPopdown(shuffleShell);
  115. XtDestroyWidget(shuffleShell);
  116. shuffleUp = False;
  117. ModeHighlight();
  118. }
  119. void ShuffleCallback(w, client_data, call_data)
  120. Widget w;
  121. XtPointer client_data, call_data;
  122. {
  123. String name;
  124. Widget w2;
  125. Arg args[16];
  126. char buf[MSG_SIZ];
  127. XtSetArg(args[0], XtNlabel, &name);
  128. XtGetValues(w, args, 1);
  129. if (strcmp(name, _("cancel")) == 0) {
  130. ShufflePopDown();
  131. return;
  132. }
  133. if (strcmp(name, _("off")) == 0) {
  134. ShufflePopDown();
  135. shuffleOpenings = False; // [HGM] should be moved to New Variant menu, once we have it!
  136. ResetGameEvent();
  137. return;
  138. }
  139. if (strcmp(name, _("random")) == 0) {
  140. snprintf(buf, MSG_SIZ, "%d", rand());
  141. XtSetArg(args[0],XtNvalue, buf); // erase bad (non-numeric) value
  142. XtSetValues(XtParent(w), args, 1);
  143. return;
  144. }
  145. if (strcmp(name, _("ok")) == 0) {
  146. int nr; String name;
  147. name = XawDialogGetValueString(w2 = XtParent(w));
  148. if(sscanf(name ,"%d",&nr) != 1) {
  149. snprintf(buf, MSG_SIZ, "%d", appData.defaultFrcPosition);
  150. XtSetArg(args[0],XtNvalue, buf); // erase bad (non-numeric) value
  151. XtSetValues(w2, args, 1);
  152. return;
  153. }
  154. appData.defaultFrcPosition = nr;
  155. shuffleOpenings = True;
  156. ShufflePopDown();
  157. ResetGameEvent();
  158. return;
  159. }
  160. }
  161. void ShufflePopUp()
  162. {
  163. Arg args[16];
  164. Widget popup, layout, dialog, edit;
  165. Window root, child;
  166. int x, y, i;
  167. int win_x, win_y;
  168. unsigned int mask;
  169. char def[MSG_SIZ];
  170. i = 0;
  171. XtSetArg(args[i], XtNresizable, True); i++;
  172. XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
  173. shuffleShell = popup =
  174. XtCreatePopupShell(_("New Shuffle Game"), transientShellWidgetClass,
  175. shellWidget, args, i);
  176. layout =
  177. XtCreateManagedWidget(layoutName, formWidgetClass, popup,
  178. layoutArgs, XtNumber(layoutArgs));
  179. snprintf(def, MSG_SIZ, "%d\n", appData.defaultFrcPosition);
  180. i = 0;
  181. XtSetArg(args[i], XtNlabel, _("Start-position number:")); i++;
  182. XtSetArg(args[i], XtNvalue, def); i++;
  183. XtSetArg(args[i], XtNborderWidth, 0); i++;
  184. dialog = XtCreateManagedWidget(_("Shuffle"), dialogWidgetClass,
  185. layout, args, i);
  186. // XtSetArg(args[0], XtNeditType, XawtextEdit); // [HGM] can't get edit to work decently
  187. // XtSetArg(args[1], XtNuseStringInPlace, False);
  188. // XtSetValues(dialog, args, 2);
  189. XawDialogAddButton(dialog, _("ok"), ShuffleCallback, (XtPointer) dialog);
  190. XawDialogAddButton(dialog, _("cancel"), ShuffleCallback, (XtPointer) dialog);
  191. XawDialogAddButton(dialog, _("random"), ShuffleCallback, (XtPointer) dialog);
  192. XawDialogAddButton(dialog, _("off"), ShuffleCallback, (XtPointer) dialog);
  193. XtRealizeWidget(popup);
  194. CatchDeleteWindow(popup, "ShufflePopDown");
  195. XQueryPointer(xDisplay, xBoardWindow, &root, &child,
  196. &x, &y, &win_x, &win_y, &mask);
  197. XtSetArg(args[0], XtNx, x - 10);
  198. XtSetArg(args[1], XtNy, y - 30);
  199. XtSetValues(popup, args, 2);
  200. XtPopup(popup, XtGrabExclusive);
  201. shuffleUp = True;
  202. edit = XtNameToWidget(dialog, "*value");
  203. XtSetKeyboardFocus(popup, edit);
  204. }
  205. void ShuffleMenuProc(w, event, prms, nprms)
  206. Widget w;
  207. XEvent *event;
  208. String *prms;
  209. Cardinal *nprms;
  210. {
  211. // if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
  212. // Reset(FALSE, TRUE);
  213. // }
  214. ShufflePopUp();
  215. }
  216. //--------------------------- Time-Control Menu Popup ----------------------------------
  217. int TimeControlUp;
  218. Widget TimeControlShell;
  219. int tcInc;
  220. Widget tcMess1, tcMess2, tcData, tcTime, tcOdds1, tcOdds2;
  221. int tcIncrement, tcMoves;
  222. void TimeControlPopDown()
  223. {
  224. if (!TimeControlUp) return;
  225. previous = NULL;
  226. XtPopdown(TimeControlShell);
  227. XtDestroyWidget(TimeControlShell);
  228. TimeControlUp = False;
  229. ModeHighlight();
  230. }
  231. void TimeControlCallback(w, client_data, call_data)
  232. Widget w;
  233. XtPointer client_data, call_data;
  234. {
  235. String name, txt;
  236. Arg args[16];
  237. char buf[MSG_SIZ];
  238. int j;
  239. XtSetArg(args[0], XtNlabel, &name);
  240. XtGetValues(w, args, 1);
  241. if (strcmp(name, _("classical")) == 0) {
  242. if(tcInc == 0) return;
  243. j=0;
  244. XtSetArg(args[j], XtNlabel, _("minutes for each")); j++;
  245. XtSetValues(tcMess1, args, j);
  246. j=0;
  247. XtSetArg(args[j], XtNlabel, _("moves")); j++;
  248. XtSetValues(tcMess2, args, j);
  249. if(tcInc == 1) {
  250. j=0;
  251. XtSetArg(args[j], XtNstring, &name); j++;
  252. XtGetValues(tcData, args, j);
  253. tcIncrement = 0; sscanf(name, "%d", &tcIncrement);
  254. }
  255. snprintf(buf, MSG_SIZ, "%d", tcMoves);
  256. j=0;
  257. XtSetArg(args[j], XtNstring, buf); j++;
  258. XtSetValues(tcData, args, j);
  259. tcInc = 0;
  260. return;
  261. }
  262. if (strcmp(name, _("incremental")) == 0) {
  263. if(tcInc == 1) return;
  264. j=0;
  265. XtSetArg(args[j], XtNlabel, _("minutes, plus")); j++;
  266. XtSetValues(tcMess1, args, j);
  267. j=0;
  268. XtSetArg(args[j], XtNlabel, _("sec/move")); j++;
  269. XtSetValues(tcMess2, args, j);
  270. if(tcInc == 0) {
  271. j=0;
  272. XtSetArg(args[j], XtNstring, &name); j++;
  273. XtGetValues(tcData, args, j);
  274. tcMoves = appData.movesPerSession; sscanf(name, "%d", &tcMoves);
  275. }
  276. snprintf(buf, MSG_SIZ, "%d", tcIncrement);
  277. j=0;
  278. XtSetArg(args[j], XtNstring, buf); j++;
  279. XtSetValues(tcData, args, j);
  280. tcInc = 1;
  281. return;
  282. }
  283. if (strcmp(name, _("fixed time")) == 0) {
  284. if(tcInc == 2) return;
  285. j=0;
  286. XtSetArg(args[j], XtNlabel, _("sec/move (max)")); j++;
  287. XtSetValues(tcMess1, args, j);
  288. j=0;
  289. XtSetArg(args[j], XtNlabel, _("")); j++;
  290. XtSetValues(tcMess2, args, j);
  291. j=0;
  292. XtSetArg(args[j], XtNstring, ""); j++;
  293. XtSetValues(tcData, args, j);
  294. tcInc = 2;
  295. return;
  296. }
  297. if (strcmp(name, _(" OK ")) == 0) {
  298. int inc, mps, ok;
  299. XtSetArg(args[0], XtNstring, &txt);
  300. XtGetValues(tcData, args, 1);
  301. switch(tcInc) {
  302. case 1:
  303. ok = sscanf(txt, "%d", &inc); mps = 0;
  304. if(!ok && txt[0] == 0) { inc = 0; ok = 1; } // accept empty string as zero
  305. ok &= (inc >= 0);
  306. break;
  307. case 0:
  308. ok = sscanf(txt, "%d", &mps); inc = -1;
  309. ok &= (mps > 0);
  310. break;
  311. case 2:
  312. ok = 1; inc = -1; mps = 40;
  313. }
  314. if(ok != 1) {
  315. XtSetArg(args[0], XtNstring, ""); // erase any offending input
  316. XtSetValues(tcData, args, 1);
  317. return;
  318. }
  319. XtSetArg(args[0], XtNstring, &txt);
  320. XtGetValues(tcTime, args, 1);
  321. if(tcInc == 2) {
  322. if(sscanf(txt, "%d", &inc) != 1) {
  323. XtSetArg(args[0], XtNstring, ""); // erase any offending input
  324. XtSetValues(tcTime, args, 1);
  325. DisplayError(_("Bad Time-Control String"), 0);
  326. return;
  327. }
  328. searchTime = inc;
  329. } else {
  330. if(!ParseTimeControl(txt, inc, mps)) {
  331. XtSetArg(args[0], XtNstring, ""); // erase any offending input
  332. XtSetValues(tcTime, args, 1);
  333. DisplayError(_("Bad Time-Control String"), 0);
  334. return;
  335. }
  336. searchTime = 0;
  337. appData.movesPerSession = mps;
  338. appData.timeIncrement = inc;
  339. appData.timeControl = strdup(txt);
  340. }
  341. XtSetArg(args[0], XtNstring, &txt);
  342. XtGetValues(tcOdds1, args, 1);
  343. appData.firstTimeOdds = first.timeOdds
  344. = (sscanf(txt, "%d", &j) == 1 && j > 0) ? j : 1;
  345. XtGetValues(tcOdds2, args, 1);
  346. appData.secondTimeOdds = second.timeOdds
  347. = (sscanf(txt, "%d", &j) == 1 && j > 0) ? j : 1;
  348. Reset(True, True);
  349. TimeControlPopDown();
  350. return;
  351. }
  352. }
  353. void TimeControlPopUp()
  354. {
  355. Arg args[16];
  356. Widget popup, layout, form, b_ok, b_cancel, b_clas, b_inc, mess;
  357. Window root, child;
  358. int x, y, i, j;
  359. int win_x, win_y;
  360. unsigned int mask;
  361. char def[MSG_SIZ];
  362. tcInc = searchTime > 0 ? 2 : (appData.timeIncrement >= 0);
  363. tcMoves = appData.movesPerSession; tcIncrement = appData.timeIncrement;
  364. if(!tcInc) tcIncrement = 0;
  365. snprintf(def, MSG_SIZ, "%d", tcInc ? tcIncrement : tcMoves);
  366. i = 0;
  367. XtSetArg(args[i], XtNresizable, True); i++;
  368. // XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
  369. TimeControlShell = popup =
  370. XtCreatePopupShell(_("TimeControl Menu"), transientShellWidgetClass,
  371. shellWidget, args, i);
  372. layout =
  373. XtCreateManagedWidget(layoutName, formWidgetClass, popup,
  374. layoutArgs, XtNumber(layoutArgs));
  375. form =
  376. XtCreateManagedWidget(layoutName, formWidgetClass, layout,
  377. formArgs, XtNumber(formArgs));
  378. j = 0;
  379. // XtSetArg(args[j], XtNwidth, (XtArgVal) 300); j++;
  380. // XtSetArg(args[j], XtNheight, (XtArgVal) 85); j++;
  381. XtSetValues(popup, args, j);
  382. j= 0;
  383. XtSetArg(args[j], XtNborderWidth, 1); j++;
  384. XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
  385. XtSetArg(args[j], XtNuseStringInPlace, False); j++;
  386. XtSetArg(args[j], XtNstring, appData.timeControl); j++;
  387. XtSetArg(args[j], XtNdisplayCaret, False); j++;
  388. XtSetArg(args[j], XtNtop, XtChainTop); j++;
  389. XtSetArg(args[j], XtNbottom, XtChainTop); j++;
  390. XtSetArg(args[j], XtNleft, XtChainLeft); j++;
  391. XtSetArg(args[j], XtNright, XtChainRight); j++;
  392. XtSetArg(args[j], XtNresizable, True); j++;
  393. XtSetArg(args[j], XtNwidth, 85); j++;
  394. XtSetArg(args[j], XtNinsertPosition, 9999); j++;
  395. tcTime = XtCreateManagedWidget("TC", asciiTextWidgetClass, form, args, j);
  396. XtAddEventHandler(tcTime, ButtonPressMask, False, SetFocus, (XtPointer) popup);
  397. j= 0;
  398. XtSetArg(args[j], XtNlabel, tcInc ? tcInc == 2 ? _("sec/move (max) ") : _(" minutes, plus ") : _("minutes for each")); j++;
  399. XtSetArg(args[j], XtNborderWidth, 0); j++;
  400. XtSetArg(args[j], XtNfromHoriz, tcTime); j++;
  401. XtSetArg(args[j], XtNtop, XtChainTop); j++;
  402. XtSetArg(args[j], XtNbottom, XtChainTop); j++;
  403. XtSetArg(args[j], XtNleft, XtChainRight); j++;
  404. XtSetArg(args[j], XtNright, XtChainRight); j++;
  405. // XtSetArg(args[j], XtNwidth, 100); j++;
  406. // XtSetArg(args[j], XtNheight, 20); j++;
  407. tcMess1 = XtCreateManagedWidget("TCtext", labelWidgetClass, form, args, j);
  408. j= 0;
  409. XtSetArg(args[j], XtNborderWidth, 1); j++;
  410. XtSetArg(args[j], XtNfromHoriz, tcMess1); j++;
  411. XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
  412. XtSetArg(args[j], XtNuseStringInPlace, False); j++;
  413. XtSetArg(args[j], XtNstring, def); j++;
  414. XtSetArg(args[j], XtNdisplayCaret, False); j++;
  415. XtSetArg(args[j], XtNtop, XtChainTop); j++;
  416. XtSetArg(args[j], XtNbottom, XtChainTop); j++;
  417. XtSetArg(args[j], XtNleft, XtChainRight); j++;
  418. XtSetArg(args[j], XtNright, XtChainRight); j++;
  419. XtSetArg(args[j], XtNresizable, True); j++;
  420. XtSetArg(args[j], XtNwidth, 40); j++;
  421. // XtSetArg(args[j], XtNheight, 20); j++;
  422. tcData = XtCreateManagedWidget("MPS", asciiTextWidgetClass, form, args, j);
  423. XtAddEventHandler(tcData, ButtonPressMask, False, SetFocus, (XtPointer) popup);
  424. j= 0;
  425. XtSetArg(args[j], XtNlabel, tcInc ? tcInc == 2 ? _(" ") : _("sec/move") : _("moves ")); j++;
  426. XtSetArg(args[j], XtNjustify, XtJustifyLeft); j++;
  427. XtSetArg(args[j], XtNborderWidth, 0); j++;
  428. XtSetArg(args[j], XtNfromHoriz, tcData); j++;
  429. XtSetArg(args[j], XtNtop, XtChainTop); j++;
  430. XtSetArg(args[j], XtNbottom, XtChainTop); j++;
  431. XtSetArg(args[j], XtNleft, XtChainRight); j++;
  432. XtSetArg(args[j], XtNright, XtChainRight); j++;
  433. // XtSetArg(args[j], XtNwidth, 80); j++;
  434. // XtSetArg(args[j], XtNheight, 20); j++;
  435. tcMess2 = XtCreateManagedWidget("MPStext", labelWidgetClass,
  436. form, args, j);
  437. j= 0;
  438. XtSetArg(args[j], XtNborderWidth, 1); j++;
  439. XtSetArg(args[j], XtNfromVert, tcTime); j++;
  440. XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
  441. XtSetArg(args[j], XtNuseStringInPlace, False); j++;
  442. XtSetArg(args[j], XtNstring, "1"); j++;
  443. XtSetArg(args[j], XtNdisplayCaret, False); j++;
  444. XtSetArg(args[j], XtNtop, XtChainTop); j++;
  445. XtSetArg(args[j], XtNbottom, XtChainTop); j++;
  446. XtSetArg(args[j], XtNleft, XtChainLeft); j++;
  447. XtSetArg(args[j], XtNright, XtChainLeft); j++;
  448. XtSetArg(args[j], XtNresizable, True); j++;
  449. XtSetArg(args[j], XtNwidth, 40); j++;
  450. // XtSetArg(args[j], XtNheight, 20); j++;
  451. tcOdds1 = XtCreateManagedWidget("Odds1", asciiTextWidgetClass, form, args, j);
  452. XtAddEventHandler(tcOdds1, ButtonPressMask, False, SetFocus, (XtPointer) popup);
  453. j= 0;
  454. XtSetArg(args[j], XtNborderWidth, 1); j++;
  455. XtSetArg(args[j], XtNfromVert, tcTime); j++;
  456. XtSetArg(args[j], XtNfromHoriz, tcOdds1); j++;
  457. XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
  458. XtSetArg(args[j], XtNuseStringInPlace, False); j++;
  459. XtSetArg(args[j], XtNstring, "1"); j++;
  460. XtSetArg(args[j], XtNdisplayCaret, False); j++;
  461. XtSetArg(args[j], XtNtop, XtChainTop); j++;
  462. XtSetArg(args[j], XtNbottom, XtChainTop); j++;
  463. XtSetArg(args[j], XtNleft, XtChainLeft); j++;
  464. XtSetArg(args[j], XtNright, XtChainLeft); j++;
  465. XtSetArg(args[j], XtNresizable, True); j++;
  466. XtSetArg(args[j], XtNwidth, 40); j++;
  467. // XtSetArg(args[j], XtNheight, 20); j++;
  468. tcOdds2 = XtCreateManagedWidget("Odds2", asciiTextWidgetClass, form, args, j);
  469. XtAddEventHandler(tcOdds2, ButtonPressMask, False, SetFocus, (XtPointer) popup);
  470. j= 0;
  471. XtSetArg(args[j], XtNlabel, _("Engine #1 and #2 Time-Odds Factors")); j++;
  472. XtSetArg(args[j], XtNjustify, XtJustifyLeft); j++;
  473. XtSetArg(args[j], XtNborderWidth, 0); j++;
  474. XtSetArg(args[j], XtNfromVert, tcTime); j++;
  475. XtSetArg(args[j], XtNfromHoriz, tcOdds2); j++;
  476. XtSetArg(args[j], XtNtop, XtChainTop); j++;
  477. XtSetArg(args[j], XtNbottom, XtChainTop); j++;
  478. XtSetArg(args[j], XtNleft, XtChainLeft); j++;
  479. XtSetArg(args[j], XtNright, XtChainRight); j++;
  480. // XtSetArg(args[j], XtNwidth, 200); j++;
  481. // XtSetArg(args[j], XtNheight, 20); j++;
  482. mess = XtCreateManagedWidget("Oddstext", labelWidgetClass,
  483. form, args, j);
  484. j=0;
  485. XtSetArg(args[j], XtNfromVert, tcOdds1); j++;
  486. XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
  487. XtSetArg(args[j], XtNtop, XtChainBottom); j++;
  488. XtSetArg(args[j], XtNleft, XtChainLeft); j++;
  489. XtSetArg(args[j], XtNright, XtChainLeft); j++;
  490. XtSetArg(args[j], XtNstate, tcInc==0); j++;
  491. b_clas= XtCreateManagedWidget(_("classical"), toggleWidgetClass,
  492. form, args, j);
  493. XtAddCallback(b_clas, XtNcallback, TimeControlCallback, (XtPointer) 0);
  494. j=0;
  495. XtSetArg(args[j], XtNradioGroup, b_clas); j++;
  496. XtSetArg(args[j], XtNfromVert, tcOdds1); j++;
  497. XtSetArg(args[j], XtNfromHoriz, b_clas); j++;
  498. XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
  499. XtSetArg(args[j], XtNtop, XtChainBottom); j++;
  500. XtSetArg(args[j], XtNleft, XtChainLeft); j++;
  501. XtSetArg(args[j], XtNright, XtChainLeft); j++;
  502. XtSetArg(args[j], XtNstate, tcInc==1); j++;
  503. b_inc = XtCreateManagedWidget(_("incremental"), toggleWidgetClass,
  504. form, args, j);
  505. XtAddCallback(b_inc, XtNcallback, TimeControlCallback, (XtPointer) 0);
  506. j=0;
  507. XtSetArg(args[j], XtNradioGroup, b_inc); j++;
  508. XtSetArg(args[j], XtNfromVert, tcOdds1); j++;
  509. XtSetArg(args[j], XtNfromHoriz, b_inc); j++;
  510. XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
  511. XtSetArg(args[j], XtNtop, XtChainBottom); j++;
  512. XtSetArg(args[j], XtNleft, XtChainLeft); j++;
  513. XtSetArg(args[j], XtNright, XtChainLeft); j++;
  514. XtSetArg(args[j], XtNstate, tcInc==2); j++;
  515. b_inc = XtCreateManagedWidget(_("fixed time"), toggleWidgetClass,
  516. form, args, j);
  517. XtAddCallback(b_inc, XtNcallback, TimeControlCallback, (XtPointer) 0);
  518. j=0;
  519. XtSetArg(args[j], XtNfromVert, tcOdds1); j++;
  520. XtSetArg(args[j], XtNfromHoriz, tcData); j++;
  521. XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
  522. XtSetArg(args[j], XtNtop, XtChainBottom); j++;
  523. XtSetArg(args[j], XtNleft, XtChainRight); j++;
  524. XtSetArg(args[j], XtNright, XtChainRight); j++;
  525. b_ok= XtCreateManagedWidget(_(" OK "), commandWidgetClass,
  526. form, args, j);
  527. XtAddCallback(b_ok, XtNcallback, TimeControlCallback, (XtPointer) 0);
  528. j=0;
  529. XtSetArg(args[j], XtNfromVert, tcOdds1); j++;
  530. XtSetArg(args[j], XtNfromHoriz, b_ok); j++;
  531. XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
  532. XtSetArg(args[j], XtNtop, XtChainBottom); j++;
  533. XtSetArg(args[j], XtNleft, XtChainRight); j++;
  534. XtSetArg(args[j], XtNright, XtChainRight); j++;
  535. b_cancel= XtCreateManagedWidget(_("cancel"), commandWidgetClass,
  536. form, args, j);
  537. XtAddCallback(b_cancel, XtNcallback, TimeControlPopDown, (XtPointer) 0);
  538. XtRealizeWidget(popup);
  539. CatchDeleteWindow(popup, "TimeControlPopDown");
  540. XQueryPointer(xDisplay, xBoardWindow, &root, &child,
  541. &x, &y, &win_x, &win_y, &mask);
  542. XtSetArg(args[0], XtNx, x - 10);
  543. XtSetArg(args[1], XtNy, y - 30);
  544. XtSetValues(popup, args, 2);
  545. XtPopup(popup, XtGrabExclusive);
  546. TimeControlUp = True;
  547. previous = NULL;
  548. SetFocus(tcTime, popup, (XEvent*) NULL, False);
  549. // XtSetKeyboardFocus(popup, tcTime);
  550. }
  551. void TimeControlProc(w, event, prms, nprms)
  552. Widget w;
  553. XEvent *event;
  554. String *prms;
  555. Cardinal *nprms;
  556. {
  557. TimeControlPopUp();
  558. }
  559. //--------------------------- Engine-specific options menu ----------------------------------
  560. int values[MAX_OPTIONS];
  561. ChessProgramState *currentCps;
  562. static Option *currentOption;
  563. extern Widget shells[];
  564. static Boolean browserUp;
  565. void CheckCallback(Widget ww, XtPointer data, XEvent *event, Boolean *b)
  566. {
  567. Widget w = currentOption[(int)(intptr_t)data].handle;
  568. Boolean s;
  569. Arg args[16];
  570. XtSetArg(args[0], XtNstate, &s);
  571. XtGetValues(w, args, 1);
  572. XtSetArg(args[0], XtNstate, !s);
  573. XtSetValues(w, args, 1);
  574. }
  575. void SpinCallback(w, client_data, call_data)
  576. Widget w;
  577. XtPointer client_data, call_data;
  578. {
  579. String name, val;
  580. Arg args[16];
  581. char buf[MSG_SIZ], *p;
  582. int j;
  583. int data = (intptr_t) client_data;
  584. XtSetArg(args[0], XtNlabel, &name);
  585. XtGetValues(w, args, 1);
  586. j = 0;
  587. XtSetArg(args[0], XtNstring, &val);
  588. XtGetValues(currentOption[data].handle, args, 1);
  589. sscanf(val, "%d", &j);
  590. if (strcmp(name, "browse") == 0) {
  591. char *q, *r;
  592. XtSetArg(args[0], XtNstring, &q);
  593. XtGetValues(currentOption[data].handle, args, 1);
  594. for(r = ""; *q; q++) if(*q == '.') r = q; else if(*q == '/') r = ""; // last dot after last slash
  595. browserUp = True;
  596. if(XsraSelFile(shells[0], currentOption[data].name, NULL, NULL, "", "", r,
  597. currentOption[data].type == PathName ? "p" : "f", NULL, &p)) {
  598. int len = strlen(p);
  599. if(len && p[len-1] == '/') p[len-1] = NULLCHAR;
  600. XtSetArg(args[0], XtNstring, p);
  601. XtSetValues(currentOption[data].handle, args, 1);
  602. }
  603. browserUp = False;
  604. SetFocus(currentOption[data].handle, shells[0], (XEvent*) NULL, False);
  605. return;
  606. } else
  607. if (strcmp(name, "+") == 0) {
  608. if(++j > currentOption[data].max) return;
  609. } else
  610. if (strcmp(name, "-") == 0) {
  611. if(--j < currentOption[data].min) return;
  612. } else return;
  613. snprintf(buf, MSG_SIZ, "%d", j);
  614. XtSetArg(args[0], XtNstring, buf);
  615. XtSetValues(currentOption[data].handle, args, 1);
  616. SetFocus(currentOption[data].handle, shells[0], NULL, False);
  617. }
  618. void ComboSelect(w, addr, index) // callback for all combo items
  619. Widget w;
  620. caddr_t addr;
  621. caddr_t index;
  622. {
  623. Arg args[16];
  624. int i = ((intptr_t)addr)>>8;
  625. int j = 255 & (intptr_t) addr;
  626. values[i] = j; // store in temporary, for transfer at OK
  627. XtSetArg(args[0], XtNlabel, ((char**)currentOption[i].textValue)[j]);
  628. XtSetValues(currentOption[i].handle, args, 1);
  629. }
  630. void CreateComboPopup(parent, name, n, mb)
  631. Widget parent;
  632. String name;
  633. int n;
  634. char *mb[];
  635. {
  636. int i=0, j;
  637. Widget menu, entry;
  638. Arg args[16];
  639. menu = XtCreatePopupShell(name, simpleMenuWidgetClass,
  640. parent, NULL, 0);
  641. j = 0;
  642. XtSetArg(args[j], XtNwidth, 100); j++;
  643. // XtSetArg(args[j], XtNright, XtChainRight); j++;
  644. while (mb[i] != NULL) {
  645. entry = XtCreateManagedWidget(mb[i], smeBSBObjectClass,
  646. menu, args, j);
  647. XtAddCallback(entry, XtNcallback,
  648. (XtCallbackProc) ComboSelect,
  649. (caddr_t)(intptr_t) (256*n+i));
  650. i++;
  651. }
  652. }
  653. //----------------------------Generic dialog --------------------------------------------
  654. // cloned from Engine Settings dialog (and later merged with it)
  655. typedef void ButtonCallback(int n);
  656. char *trialSound;
  657. static int oldCores, oldPonder;
  658. int MakeColors P((void));
  659. void CreateGCs P((int redo));
  660. void CreateAnyPieces P((void));
  661. void GenericReadout P((int selected));
  662. Widget shells[10];
  663. Widget marked[10];
  664. Boolean shellUp[10];
  665. WindowPlacement *wp[10];
  666. Option *dialogOptions[10];
  667. void MarkMenu(char *item, int dlgNr)
  668. {
  669. Arg args[2];
  670. XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
  671. XtSetValues(marked[dlgNr] = XtNameToWidget(menuBarWidget, item), args, 1);
  672. }
  673. int PopDown(int n)
  674. {
  675. int j;
  676. Arg args[10];
  677. Dimension windowH, windowW; Position windowX, windowY;
  678. if (!shellUp[n]) return 0;
  679. if(n && wp[n]) { // remember position
  680. j = 0;
  681. XtSetArg(args[j], XtNx, &windowX); j++;
  682. XtSetArg(args[j], XtNy, &windowY); j++;
  683. XtSetArg(args[j], XtNheight, &windowH); j++;
  684. XtSetArg(args[j], XtNwidth, &windowW); j++;
  685. XtGetValues(shells[n], args, j);
  686. wp[n]->x = windowX;
  687. wp[n]->x = windowY;
  688. wp[n]->width = windowW;
  689. wp[n]->height = windowH;
  690. }
  691. previous = NULL;
  692. XtPopdown(shells[n]);
  693. if(n == 0) XtDestroyWidget(shells[n]);
  694. shellUp[n] = False;
  695. if(marked[n]) {
  696. XtSetArg(args[0], XtNleftBitmap, None);
  697. XtSetValues(marked[n], args, 1);
  698. }
  699. if(!n) currentCps = NULL; // if an Engine Settings dialog was up, we must be popping it down now
  700. return 1;
  701. }
  702. void GenericPopDown(w, event, prms, nprms)
  703. Widget w;
  704. XEvent *event;
  705. String *prms;
  706. Cardinal *nprms;
  707. {
  708. int n;
  709. if(browserUp) return; // prevent closing dialog when it has an open file-browse daughter
  710. PopDown(prms[0][0] - '0');
  711. }
  712. Option matchOptions[] = {
  713. { 0, 2, 1000000000, NULL, (void*) &appData.defaultMatchGames, "", NULL, Spin, N_("Default Number of Games in Match:") },
  714. { 0, 0, 1000000000, NULL, (void*) &appData.matchPause, "", NULL, Spin, N_("Pause between Match Games (msec):") },
  715. { 0, 0, 0, NULL, (void*) &appData.loadGameFile, "", NULL, FileName, N_("Game File with Opening Lines:") },
  716. { 0, -2, 1000000000, NULL, (void*) &appData.loadGameIndex, "", NULL, Spin, N_("Game Number (-1 or -2 = Auto-Increment):") },
  717. { 0, 0, 0, NULL, (void*) &appData.loadPositionFile, "", NULL, FileName, N_("File with Start Positions:") },
  718. { 0, -2, 1000000000, NULL, (void*) &appData.loadPositionIndex, "", NULL, Spin, N_("Position Number (-1 or -2 = Auto-Increment):") },
  719. { 0, 0, 1000000000, NULL, (void*) &appData.rewindIndex, "", NULL, Spin, N_("Rewind Index after this many Games (0 = never):") },
  720. { 0, 0, 0, NULL, NULL, "", NULL, EndMark , "" }
  721. };
  722. void GeneralOptionsOK(int n)
  723. {
  724. int newPonder = appData.ponderNextMove;
  725. appData.ponderNextMove = oldPonder;
  726. PonderNextMoveEvent(newPonder);
  727. }
  728. Option generalOptions[] = {
  729. { 0, 0, 0, NULL, (void*) &appData.alwaysPromoteToQueen, "", NULL, CheckBox, N_("Always Queen") },
  730. { 0, 0, 0, NULL, (void*) &appData.animateDragging, "", NULL, CheckBox, N_("Animate Dragging") },
  731. { 0, 0, 0, NULL, (void*) &appData.animate, "", NULL, CheckBox, N_("Animate Moving") },
  732. { 0, 0, 0, NULL, (void*) &appData.autoCallFlag, "", NULL, CheckBox, N_("Auto Flag") },
  733. { 0, 0, 0, NULL, (void*) &appData.autoFlipView, "", NULL, CheckBox, N_("Auto Flip View") },
  734. { 0, 0, 0, NULL, (void*) &appData.blindfold, "", NULL, CheckBox, N_("Blindfold") },
  735. { 0, 0, 0, NULL, (void*) &appData.dropMenu, "", NULL, CheckBox, N_("Drop Menu") },
  736. { 0, 0, 0, NULL, (void*) &appData.highlightDragging, "", NULL, CheckBox, N_("Highlight Dragging (Show Move Targets)") },
  737. { 0, 0, 0, NULL, (void*) &appData.highlightLastMove, "", NULL, CheckBox, N_("Highlight Last Move") },
  738. { 0, 0, 0, NULL, (void*) &appData.highlightMoveWithArrow, "", NULL, CheckBox, N_("Highlight with Arrow") },
  739. { 0, 0, 0, NULL, (void*) &appData.ringBellAfterMoves, "", NULL, CheckBox, N_("Move Sound") },
  740. { 0, 0, 0, NULL, (void*) &appData.oneClick, "", NULL, CheckBox, N_("One-Click Moving") },
  741. { 0, 0, 0, NULL, (void*) &appData.periodicUpdates, "", NULL, CheckBox, N_("Periodic Updates (in Analysis Mode)") },
  742. { 0, 0, 0, NULL, (void*) &appData.ponderNextMove, "", NULL, CheckBox, N_("Ponder Next Move") },
  743. { 0, 0, 0, NULL, (void*) &appData.popupExitMessage, "", NULL, CheckBox, N_("Popup Exit Messages") },
  744. { 0, 0, 0, NULL, (void*) &appData.popupMoveErrors, "", NULL, CheckBox, N_("Popup Move Errors") },
  745. { 0, 0, 0, NULL, (void*) &appData.showCoords, "", NULL, CheckBox, N_("Show Coordinates") },
  746. { 0, 0, 0, NULL, (void*) &appData.markers, "", NULL, CheckBox, N_("Show Target Squares") },
  747. { 0, 0, 0, NULL, (void*) &appData.hideThinkingFromHuman, "", NULL, CheckBox, N_("Hide Thinking from Human") },
  748. { 0, 0, 0, NULL, (void*) &appData.testLegality, "", NULL, CheckBox, N_("Test Legality") },
  749. { 0, 0, 10, NULL, (void*) &appData.flashCount, "", NULL, Spin, N_("Flash Moves (0 = no flashing):") },
  750. { 0, 1, 10, NULL, (void*) &appData.flashRate, "", NULL, Spin, N_("Flash Rate (high = fast):") },
  751. { 0, 5, 100,NULL, (void*) &appData.animSpeed, "", NULL, Spin, N_("Animation Speed (high = slow):") },
  752. { 0, 0, 0, NULL, (void*) &GeneralOptionsOK, "", NULL, EndMark , "" }
  753. };
  754. void Pick(int n)
  755. {
  756. VariantClass v = currentOption[n].value;
  757. if(!appData.noChessProgram) {
  758. char *name = VariantName(v), buf[MSG_SIZ];
  759. if (first.protocolVersion > 1 && StrStr(first.variants, name) == NULL) {
  760. /* [HGM] in protocol 2 we check if variant is suported by engine */
  761. snprintf(buf, MSG_SIZ, _("Variant %s not supported by %s"), name, first.tidy);
  762. DisplayError(buf, 0);
  763. return; /* ignore OK if first engine does not support it */
  764. } else
  765. if (second.initDone && second.protocolVersion > 1 && StrStr(second.variants, name) == NULL) {
  766. snprintf(buf, MSG_SIZ, _("Warning: second engine (%s) does not support this!"), second.tidy);
  767. DisplayError(buf, 0); /* use of second engine is optional; only warn user */
  768. }
  769. }
  770. GenericReadout(-1); // make sure ranks and file settings are read
  771. gameInfo.variant = v;
  772. appData.variant = VariantName(v);
  773. shuffleOpenings = FALSE; /* [HGM] shuffle: possible shuffle reset when we switch */
  774. startedFromPositionFile = FALSE; /* [HGM] loadPos: no longer valid in new variant */
  775. appData.pieceToCharTable = NULL;
  776. appData.pieceNickNames = "";
  777. appData.colorNickNames = "";
  778. Reset(True, True);
  779. PopDown(0);
  780. return;
  781. }
  782. Option variantDescriptors[] = {
  783. { VariantNormal, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("normal")},
  784. { VariantFairy, 1, 135, NULL, (void*) &Pick, "#BFBFBF", NULL, Button, N_("fairy")},
  785. { VariantFischeRandom, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("FRC")},
  786. { VariantSChess, 1, 135, NULL, (void*) &Pick, "#FFBFBF", NULL, Button, N_("Seirawan")},
  787. { VariantWildCastle, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("wild castle")},
  788. { VariantSuper, 1, 135, NULL, (void*) &Pick, "#FFBFBF", NULL, Button, N_("Superchess")},
  789. { VariantNoCastle, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("no castle")},
  790. { VariantCrazyhouse, 1, 135, NULL, (void*) &Pick, "#FFBFBF", NULL, Button, N_("crazyhouse")},
  791. { VariantKnightmate, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("knightmate")},
  792. { VariantBughouse, 1, 135, NULL, (void*) &Pick, "#FFBFBF", NULL, Button, N_("bughouse")},
  793. { VariantBerolina, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("berolina")},
  794. { VariantShogi, 1, 135, NULL, (void*) &Pick, "#BFFFFF", NULL, Button, N_("shogi (9x9)")},
  795. { VariantCylinder, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("cylinder")},
  796. { VariantXiangqi, 1, 135, NULL, (void*) &Pick, "#BFFFFF", NULL, Button, N_("xiangqi (9x10)")},
  797. { VariantShatranj, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("shatranj")},
  798. { VariantCourier, 1, 135, NULL, (void*) &Pick, "#BFFFBF", NULL, Button, N_("courier (12x8)")},
  799. { VariantMakruk, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("makruk")},
  800. { VariantGreat, 1, 135, NULL, (void*) &Pick, "#BFBFFF", NULL, Button, N_("Great Shatranj (10x8)")},
  801. { VariantAtomic, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("atomic")},
  802. { VariantCapablanca, 1, 135, NULL, (void*) &Pick, "#BFBFFF", NULL, Button, N_("Capablanca (10x8)")},
  803. { VariantTwoKings, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("two kings")},
  804. { VariantGothic, 1, 135, NULL, (void*) &Pick, "#BFBFFF", NULL, Button, N_("Gothic (10x8)")},
  805. { Variant3Check, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("3-checks")},
  806. { VariantJanus, 1, 135, NULL, (void*) &Pick, "#BFBFFF", NULL, Button, N_("janus (10x8)")},
  807. { VariantSuicide, 0, 135, NULL, (void*) &Pick, "#FFFFBF", NULL, Button, N_("suicide")},
  808. { VariantCapaRandom, 1, 135, NULL, (void*) &Pick, "#BFBFFF", NULL, Button, N_("CRC (10x8)")},
  809. { VariantGiveaway, 0, 135, NULL, (void*) &Pick, "#FFFFBF", NULL, Button, N_("give-away")},
  810. { VariantSpartan, 1, 135, NULL, (void*) &Pick, "#FF0000", NULL, Button, N_("Spartan")},
  811. { VariantLosers, 0, 135, NULL, (void*) &Pick, "#FFFFBF", NULL, Button, N_("losers")},
  812. { 0, 0, 0, NULL, NULL, NULL, NULL, Label, N_("Board size ( -1 = default for selected variant):")},
  813. { 0, -1, BOARD_RANKS-1, NULL, (void*) &appData.NrRanks, "", NULL, Spin, N_("Number of Board Ranks:") },
  814. { 0, -1, BOARD_FILES, NULL, (void*) &appData.NrFiles, "", NULL, Spin, N_("Number of Board Files:") },
  815. { 0, -1, BOARD_RANKS-1, NULL, (void*) &appData.holdingsSize, "", NULL, Spin, N_("Holdings Size:") },
  816. { 0, 0, 0, NULL, NULL, NULL, NULL, Label,
  817. N_("WARNING: variants with un-orthodox\n"
  818. "pieces only have built-in bitmaps\n"
  819. "for -boardSize middling, bulky and\n"
  820. "petite, and substitute king or amazon\n"
  821. "for missing bitmaps. (See manual.)")},
  822. { 0, 2, 0, NULL, NULL, "", NULL, EndMark , "" }
  823. };
  824. void CommonOptionsOK(int n)
  825. {
  826. int newPonder = appData.ponderNextMove;
  827. // make sure changes are sent to first engine by re-initializing it
  828. // if it was already started pre-emptively at end of previous game
  829. if(gameMode == BeginningOfGame) Reset(True, True); else {
  830. // Some changed setting need immediate sending always.
  831. if(oldCores != appData.smpCores)
  832. NewSettingEvent(False, &(first.maxCores), "cores", appData.smpCores);
  833. appData.ponderNextMove = oldPonder;
  834. PonderNextMoveEvent(newPonder);
  835. }
  836. }
  837. Option commonEngineOptions[] = {
  838. { 0, 0, 0, NULL, (void*) &appData.ponderNextMove, "", NULL, CheckBox, N_("Ponder Next Move") },
  839. { 0, 0, 1000, NULL, (void*) &appData.smpCores, "", NULL, Spin, N_("Maximum Number of CPUs per Engine:") },
  840. { 0, 0, 0, NULL, (void*) &appData.polyglotDir, "", NULL, PathName, N_("Polygot Directory:") },
  841. { 0, 0, 16000, NULL, (void*) &appData.defaultHashSize, "", NULL, Spin, N_("Hash-Table Size (MB):") },
  842. { 0, 0, 0, NULL, (void*) &appData.defaultPathEGTB, "", NULL, PathName, N_("Nalimov EGTB Path:") },
  843. { 0, 0, 1000, NULL, (void*) &appData.defaultCacheSizeEGTB, "", NULL, Spin, N_("EGTB Cache Size (MB):") },
  844. { 0, 0, 0, NULL, (void*) &appData.usePolyglotBook, "", NULL, CheckBox, N_("Use GUI Book") },
  845. { 0, 0, 0, NULL, (void*) &appData.polyglotBook, "", NULL, FileName, N_("Opening-Book Filename:") },
  846. { 0, 0, 100, NULL, (void*) &appData.bookDepth, "", NULL, Spin, N_("Book Depth (moves):") },
  847. { 0, 0, 100, NULL, (void*) &appData.bookStrength, "", NULL, Spin, N_("Book Variety (0) vs. Strength (100):") },
  848. { 0, 0, 0, NULL, (void*) &appData.firstHasOwnBookUCI, "", NULL, CheckBox, N_("Engine #1 Has Own Book") },
  849. { 0, 0, 0, NULL, (void*) &appData.secondHasOwnBookUCI, "", NULL, CheckBox, N_("Engine #2 Has Own Book ") },
  850. { 0, 1, 0, NULL, (void*) &CommonOptionsOK, "", NULL, EndMark , "" }
  851. };
  852. Option adjudicationOptions[] = {
  853. { 0, 0, 0, NULL, (void*) &appData.checkMates, "", NULL, CheckBox, N_("Detect all Mates") },
  854. { 0, 0, 0, NULL, (void*) &appData.testClaims, "", NULL, CheckBox, N_("Verify Engine Result Claims") },
  855. { 0, 0, 0, NULL, (void*) &appData.materialDraws, "", NULL, CheckBox, N_("Draw if Insufficient Mating Material") },
  856. { 0, 0, 0, NULL, (void*) &appData.trivialDraws, "", NULL, CheckBox, N_("Adjudicate Trivial Draws (3-Move Delay)") },
  857. { 0, 0, 100, NULL, (void*) &appData.ruleMoves, "", NULL, Spin, N_("N-Move Rule:") },
  858. { 0, 0, 6, NULL, (void*) &appData.drawRepeats, "", NULL, Spin, N_("N-fold Repeats:") },
  859. { 0, 0, 1000, NULL, (void*) &appData.adjudicateDrawMoves, "", NULL, Spin, N_("Draw after N Moves Total:") },
  860. { 0,-5000, 0, NULL, (void*) &appData.adjudicateLossThreshold, "", NULL, Spin, N_("Win / Loss Threshold:") },
  861. { 0, 0, 0, NULL, (void*) &first.scoreIsAbsolute, "", NULL, CheckBox, N_("Negate Score of Engine #1") },
  862. { 0, 0, 0, NULL, (void*) &second.scoreIsAbsolute, "", NULL, CheckBox, N_("Negate Score of Engine #2") },
  863. { 0, 1, 0, NULL, NULL, "", NULL, EndMark , "" }
  864. };
  865. void IcsOptionsOK(int n)
  866. {
  867. ParseIcsTextColors();
  868. }
  869. Option icsOptions[] = {
  870. { 0, 0, 0, NULL, (void*) &appData.autoKibitz, "", NULL, CheckBox, N_("Auto-Kibitz") },
  871. { 0, 0, 0, NULL, (void*) &appData.autoComment, "", NULL, CheckBox, N_("Auto-Comment") },
  872. { 0, 0, 0, NULL, (void*) &appData.autoObserve, "", NULL, CheckBox, N_("Auto-Observe") },
  873. { 0, 0, 0, NULL, (void*) &appData.autoRaiseBoard, "", NULL, CheckBox, N_("Auto-Raise Board") },
  874. { 0, 0, 0, NULL, (void*) &appData.bgObserve, "", NULL, CheckBox, N_("Background Observe while Playing") },
  875. { 0, 0, 0, NULL, (void*) &appData.dualBoard, "", NULL, CheckBox, N_("Dual Board for Background-Observed Game") },
  876. { 0, 0, 0, NULL, (void*) &appData.getMoveList, "", NULL, CheckBox, N_("Get Move List") },
  877. { 0, 0, 0, NULL, (void*) &appData.quietPlay, "", NULL, CheckBox, N_("Quiet Play") },
  878. { 0, 0, 0, NULL, (void*) &appData.seekGraph, "", NULL, CheckBox, N_("Seek Graph") },
  879. { 0, 0, 0, NULL, (void*) &appData.autoRefresh, "", NULL, CheckBox, N_("Auto-Refresh Seek Graph") },
  880. { 0, 0, 0, NULL, (void*) &appData.premove, "", NULL, CheckBox, N_("Premove") },
  881. { 0, 0, 0, NULL, (void*) &appData.premoveWhite, "", NULL, CheckBox, N_("Premove for White") },
  882. { 0, 0, 0, NULL, (void*) &appData.premoveWhiteText, "", NULL, TextBox, N_("First White Move:") },
  883. { 0, 0, 0, NULL, (void*) &appData.premoveBlack, "", NULL, CheckBox, N_("Premove for Black") },
  884. { 0, 0, 0, NULL, (void*) &appData.premoveBlackText, "", NULL, TextBox, N_("First Black Move:") },
  885. { 0, 0, 0, NULL, NULL, NULL, NULL, Break, "" },
  886. { 0, 0, 0, NULL, (void*) &appData.icsAlarm, "", NULL, CheckBox, N_("Alarm") },
  887. { 0, 0, 100000000, NULL, (void*) &appData.icsAlarmTime, "", NULL, Spin, N_("Alarm Time (msec):") },
  888. //{ 0, 0, 0, NULL, (void*) &appData.chatBoxes, "", NULL, TextBox, N_("Startup Chat Boxes:") },
  889. { 0, 0, 0, NULL, (void*) &appData.colorize, "", NULL, CheckBox, N_("Colorize Messages") },
  890. { 0, 0, 0, NULL, (void*) &appData.colorShout, "", NULL, TextBox, N_("Shout Text Colors:") },
  891. { 0, 0, 0, NULL, (void*) &appData.colorSShout, "", NULL, TextBox, N_("S-Shout Text Colors:") },
  892. { 0, 0, 0, NULL, (void*) &appData.colorChannel1, "", NULL, TextBox, N_("Channel #1 Text Colors:") },
  893. { 0, 0, 0, NULL, (void*) &appData.colorChannel, "", NULL, TextBox, N_("Other Channel Text Colors:") },
  894. { 0, 0, 0, NULL, (void*) &appData.colorKibitz, "", NULL, TextBox, N_("Kibitz Text Colors:") },
  895. { 0, 0, 0, NULL, (void*) &appData.colorTell, "", NULL, TextBox, N_("Tell Text Colors:") },
  896. { 0, 0, 0, NULL, (void*) &appData.colorChallenge, "", NULL, TextBox, N_("Challenge Text Colors:") },
  897. { 0, 0, 0, NULL, (void*) &appData.colorRequest, "", NULL, TextBox, N_("Request Text Colors:") },
  898. { 0, 0, 0, NULL, (void*) &appData.colorSeek, "", NULL, TextBox, N_("Seek Text Colors:") },
  899. { 0, 0, 0, NULL, (void*) &IcsOptionsOK, "", NULL, EndMark , "" }
  900. };
  901. Option loadOptions[] = {
  902. { 0, 0, 0, NULL, (void*) &appData.autoDisplayTags, "", NULL, CheckBox, N_("Auto-Display Tags") },
  903. { 0, 0, 0, NULL, (void*) &appData.autoDisplayComment, "", NULL, CheckBox, N_("Auto-Display Comment") },
  904. { 0, 0, 0, NULL, NULL, NULL, NULL, Label, N_("Auto-Play speed of loaded games\n(0 = instant, -1 = off):") },
  905. { 0, -1, 10000000, NULL, (void*) &appData.timeDelay, "", NULL, Fractional, N_("Seconds per Move:") },
  906. { 0, 0, 0, NULL, NULL, "", NULL, EndMark , "" }
  907. };
  908. Option saveOptions[] = {
  909. { 0, 0, 0, NULL, (void*) &appData.autoSaveGames, "", NULL, CheckBox, N_("Auto-Save Games") },
  910. { 0, 0, 0, NULL, (void*) &appData.saveGameFile, "", NULL, FileName, N_("Save Games on File:") },
  911. { 0, 0, 0, NULL, (void*) &appData.savePositionFile, "", NULL, FileName, N_("Save Final Positions on File:") },
  912. { 0, 0, 0, NULL, (void*) &appData.pgnEventHeader, "", NULL, TextBox, N_("PGN Event Header:") },
  913. { 0, 0, 0, NULL, (void*) &appData.oldSaveStyle, "", NULL, CheckBox, N_("Old Save Style (as opposed to PGN)") },
  914. { 0, 0, 0, NULL, (void*) &appData.saveExtendedInfoInPGN, "", NULL, CheckBox, N_("Save Score/Depth Info in PGN") },
  915. { 0, 0, 0, NULL, (void*) &appData.saveOutOfBookInfo, "", NULL, CheckBox, N_("Save Out-of-Book Info in PGN ") },
  916. { 0, 1, 0, NULL, NULL, "", NULL, EndMark , "" }
  917. };
  918. char *soundNames[] = {
  919. N_("No Sound"),
  920. N_("Default Beep"),
  921. N_("Above WAV File"),
  922. N_("Car Horn"),
  923. N_("Cymbal"),
  924. N_("Ding"),
  925. N_("Gong"),
  926. N_("Laser"),
  927. N_("Penalty"),
  928. N_("Phone"),
  929. N_("Pop"),
  930. N_("Slap"),
  931. N_("Wood Thunk"),
  932. NULL,
  933. N_("User File")
  934. };
  935. char *soundFiles[] = { // sound files corresponding to above names
  936. "",
  937. "$",
  938. "*", // kludge alert: as first thing in the dialog readout this is replaced with the user-given .WAV filename
  939. "honkhonk.wav",
  940. "cymbal.wav",
  941. "ding1.wav",
  942. "gong.wav",
  943. "laser.wav",
  944. "penalty.wav",
  945. "phone.wav",
  946. "pop2.wav",
  947. "slap.wav",
  948. "woodthunk.wav",
  949. NULL,
  950. NULL
  951. };
  952. void Test(int n)
  953. {
  954. GenericReadout(2);
  955. if(soundFiles[values[3]]) PlaySound(soundFiles[values[3]]);
  956. }
  957. Option soundOptions[] = {
  958. { 0, 0, 0, NULL, (void*) &appData.soundProgram, "", NULL, TextBox, N_("Sound Program:") },
  959. { 0, 0, 0, NULL, (void*) &appData.soundDirectory, "", NULL, PathName, N_("Sounds Directory:") },
  960. { 0, 0, 0, NULL, (void*) (soundFiles+2) /* kludge! */, "", NULL, FileName, N_("User WAV File:") },
  961. { 0, 0, 0, NULL, (void*) &trialSound, (char*) soundNames, soundFiles, ComboBox, N_("Try-Out Sound:") },
  962. { 0, 1, 0, NULL, (void*) &Test, NULL, NULL, Button, N_("Play") },
  963. { 0, 0, 0, NULL, (void*) &appData.soundMove, (char*) soundNames, soundFiles, ComboBox, N_("Move:") },
  964. { 0, 0, 0, NULL, (void*) &appData.soundIcsWin, (char*) soundNames, soundFiles, ComboBox, N_("Win:") },
  965. { 0, 0, 0, NULL, (void*) &appData.soundIcsLoss, (char*) soundNames, soundFiles, ComboBox, N_("Lose:") },
  966. { 0, 0, 0, NULL, (void*) &appData.soundIcsDraw, (char*) soundNames, soundFiles, ComboBox, N_("Draw:") },
  967. { 0, 0, 0, NULL, (void*) &appData.soundIcsUnfinished, (char*) soundNames, soundFiles, ComboBox, N_("Unfinished:") },
  968. { 0, 0, 0, NULL, (void*) &appData.soundIcsAlarm, (char*) soundNames, soundFiles, ComboBox, N_("Alarm:") },
  969. { 0, 0, 0, NULL, (void*) &appData.soundShout, (char*) soundNames, soundFiles, ComboBox, N_("Shout:") },
  970. { 0, 0, 0, NULL, (void*) &appData.soundSShout, (char*) soundNames, soundFiles, ComboBox, N_("S-Shout:") },
  971. { 0, 0, 0, NULL, (void*) &appData.soundChannel, (char*) soundNames, soundFiles, ComboBox, N_("Channel:") },
  972. { 0, 0, 0, NULL, (void*) &appData.soundChannel1, (char*) soundNames, soundFiles, ComboBox, N_("Channel 1:") },
  973. { 0, 0, 0, NULL, (void*) &appData.soundTell, (char*) soundNames, soundFiles, ComboBox, N_("Tell:") },
  974. { 0, 0, 0, NULL, (void*) &appData.soundKibitz, (char*) soundNames, soundFiles, ComboBox, N_("Kibitz:") },
  975. { 0, 0, 0, NULL, (void*) &appData.soundChallenge, (char*) soundNames, soundFiles, ComboBox, N_("Challenge:") },
  976. { 0, 0, 0, NULL, (void*) &appData.soundRequest, (char*) soundNames, soundFiles, ComboBox, N_("Request:") },
  977. { 0, 0, 0, NULL, (void*) &appData.soundSeek, (char*) soundNames, soundFiles, ComboBox, N_("Seek:") },
  978. { 0, 1, 0, NULL, NULL, "", NULL, EndMark , "" }
  979. };
  980. void SetColor(char *colorName, Widget box)
  981. {
  982. Arg args[5];
  983. Pixel buttonColor;
  984. XrmValue vFrom, vTo;
  985. if (!appData.monoMode) {
  986. vFrom.addr = (caddr_t) colorName;
  987. vFrom.size = strlen(colorName);
  988. XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
  989. if (vTo.addr == NULL) {
  990. buttonColor = (Pixel) -1;
  991. } else {
  992. buttonColor = *(Pixel *) vTo.addr;
  993. }
  994. }
  995. XtSetArg(args[0], XtNbackground, buttonColor);;
  996. XtSetValues(box, args, 1);
  997. }
  998. void SetColorText(int n, char *buf)
  999. {
  1000. Arg args[5];
  1001. XtSetArg(args[0], XtNstring, buf);
  1002. XtSetValues(currentOption[n-1].handle, args, 1);
  1003. SetFocus(currentOption[n-1].handle, shells[0], NULL, False);
  1004. SetColor(buf, currentOption[n].handle);
  1005. }
  1006. void DefColor(int n)
  1007. {
  1008. SetColorText(n, (char*) currentOption[n].choice);
  1009. }
  1010. void RefreshColor(int source, int n)
  1011. {
  1012. int col, j, r, g, b, step = 10;
  1013. char *s, buf[MSG_SIZ]; // color string
  1014. Arg args[5];
  1015. XtSetArg(args[0], XtNstring, &s);
  1016. XtGetValues(currentOption[source].handle, args, 1);
  1017. if(sscanf(s, "#%x", &col) != 1) return; // malformed
  1018. b = col & 0xFF; g = col & 0xFF00; r = col & 0xFF0000;
  1019. switch(n) {
  1020. case 1: r += 0x10000*step;break;
  1021. case 2: g += 0x100*step; break;
  1022. case 3: b += step; break;
  1023. case 4: r -= 0x10000*step; g -= 0x100*step; b -= step; break;
  1024. }
  1025. if(r < 0) r = 0; if(g < 0) g = 0; if(b < 0) b = 0;
  1026. if(r > 0xFF0000) r = 0xFF0000; if(g > 0xFF00) g = 0xFF00; if(b > 0xFF) b = 0xFF;
  1027. col = r | g | b;
  1028. snprintf(buf, MSG_SIZ, "#%06x", col);
  1029. for(j=1; j<7; j++) if(buf[j] >= 'a') buf[j] -= 32; // capitalize
  1030. SetColorText(source+1, buf);
  1031. }
  1032. void ColorChanged(Widget w, XtPointer data, XEvent *event, Boolean *b)
  1033. {
  1034. char buf[10];
  1035. if ( (XLookupString(&(event->xkey), buf, 2, NULL, NULL) == 1) && *buf == '\r' )
  1036. RefreshColor((int)(intptr_t) data, 0);
  1037. }
  1038. void AdjustColor(int i)
  1039. {
  1040. int n = currentOption[i].value;
  1041. RefreshColor(i-n-1, n);
  1042. }
  1043. void BoardOptionsOK(int n)
  1044. {
  1045. extern int defaultLineGap, useImages, useImageSqs;
  1046. if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap; else lineGap = defaultLineGap;
  1047. useImages = useImageSqs = 0;
  1048. MakeColors(); CreateGCs(True);
  1049. CreateAnyPieces();
  1050. InitDrawingSizes(-1, 0);
  1051. DrawPosition(True, NULL);
  1052. }
  1053. Option boardOptions[] = {
  1054. { 0, 0, 70, NULL, (void*) &appData.whitePieceColor, "", NULL, TextBox, N_("White Piece Color:") },
  1055. { 1000, 1, 0, NULL, (void*) &DefColor, NULL, (char**) "#FFFFCC", Button, " " },
  1056. { 1, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "R" },
  1057. { 2, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "G" },
  1058. { 3, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "B" },
  1059. { 4, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "D" },
  1060. { 0, 0, 70, NULL, (void*) &appData.blackPieceColor, "", NULL, TextBox, N_("Black Piece Color:") },
  1061. { 1000, 1, 0, NULL, (void*) &DefColor, NULL, (char**) "#202020", Button, " " },
  1062. { 1, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "R" },
  1063. { 2, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "G" },
  1064. { 3, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "B" },
  1065. { 4, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "D" },
  1066. { 0, 0, 70, NULL, (void*) &appData.lightSquareColor, "", NULL, TextBox, N_("Light Square Color:") },
  1067. { 1000, 1, 0, NULL, (void*) &DefColor, NULL, (char**) "#C8C365", Button, " " },
  1068. { 1, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "R" },
  1069. { 2, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "G" },
  1070. { 3, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "B" },
  1071. { 4, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "D" },
  1072. { 0, 0, 70, NULL, (void*) &appData.darkSquareColor, "", NULL, TextBox, N_("Dark Square Color:") },
  1073. { 1000, 1, 0, NULL, (void*) &DefColor, NULL, (char**) "#77A26D", Button, " " },
  1074. { 1, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "R" },
  1075. { 2, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "G" },
  1076. { 3, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "B" },
  1077. { 4, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "D" },
  1078. { 0, 0, 70, NULL, (void*) &appData.highlightSquareColor, "", NULL, TextBox, N_("Highlight Color:") },
  1079. { 1000, 1, 0, NULL, (void*) &DefColor, NULL, (char**) "#FFFF00", Button, " " },
  1080. { 1, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "R" },
  1081. { 2, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "G" },
  1082. { 3, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "B" },
  1083. { 4, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "D" },
  1084. { 0, 0, 70, NULL, (void*) &appData.premoveHighlightColor, "", NULL, TextBox, N_("Premove Highlight Color:") },
  1085. { 1000, 1, 0, NULL, (void*) &DefColor, NULL, (char**) "#FF0000", Button, " " },
  1086. { 1, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "R" },
  1087. { 2, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "G" },
  1088. { 3, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "B" },
  1089. { 4, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, "D" },
  1090. { 0, 0, 0, NULL, (void*) &appData.upsideDown, "", NULL, CheckBox, N_("Flip Pieces Shogi Style (Colored buttons restore default)") },
  1091. //{ 0, 0, 0, NULL, (void*) &appData.allWhite, "", NULL, CheckBox, N_("Use Outline Pieces for Black") },
  1092. { 0, 0, 0, NULL, (void*) &appData.monoMode, "", NULL, CheckBox, N_("Mono Mode") },
  1093. { 0,-1, 5, NULL, (void*) &appData.overrideLineGap, "", NULL, Spin, N_("Line Gap ( -1 = default for board size):") },
  1094. { 0, 0, 0, NULL, (void*) &appData.liteBackTextureFile, "", NULL, FileName, N_("Light-Squares Texture File:") },
  1095. { 0, 0, 0, NULL, (void*) &appData.darkBackTextureFile, "", NULL, FileName, N_("Dark-Squares Texture File:") },
  1096. { 0, 0, 0, NULL, (void*) &appData.bitmapDirectory, "", NULL, PathName, N_("Directory with Bitmap Pieces:") },
  1097. { 0, 0, 0, NULL, (void*) &appData.pixmapDirectory, "", NULL, PathName, N_("Directory with Pixmap Pieces:") },
  1098. { 0, 0, 0, NULL, (void*) &BoardOptionsOK, "", NULL, EndMark , "" }
  1099. };
  1100. void GenericReadout(int selected)
  1101. {
  1102. int i, j;
  1103. String name, val;
  1104. Arg args[16];
  1105. char buf[MSG_SIZ], **dest;
  1106. float x;
  1107. for(i=0; ; i++) { // send all options that had to be OK-ed to engine
  1108. if(selected >= 0) { if(i < selected) continue; else if(i > selected) break; }
  1109. switch(currentOption[i].type) {
  1110. case TextBox:
  1111. case FileName:
  1112. case PathName:
  1113. XtSetArg(args[0], XtNstring, &val);
  1114. XtGetValues(currentOption[i].handle, args, 1);
  1115. dest = currentCps ? &(currentOption[i].textValue) : (char**) currentOption[i].target;
  1116. if(*dest == NULL || strcmp(*dest, val)) {
  1117. if(currentCps) {
  1118. snprintf(buf, MSG_SIZ, "option %s=%s\n", currentOption[i].name, val);
  1119. SendToProgram(buf, currentCps);
  1120. } else *dest = currentOption[i].name + 100; // option gets to point to private storage;
  1121. safeStrCpy(*dest, val, MSG_SIZ - (*dest - currentOption[i].name)); // copy text there
  1122. }
  1123. break;
  1124. case Spin:
  1125. case Fractional:
  1126. XtSetArg(args[0], XtNstring, &val);
  1127. XtGetValues(currentOption[i].handle, args, 1);
  1128. sscanf(val, "%f", &x);
  1129. if(x > currentOption[i].max) x = currentOption[i].max;
  1130. if(x < currentOption[i].min) x = currentOption[i].min;
  1131. if(currentOption[i].type == Fractional)
  1132. *(float*) currentOption[i].target = x; // engines never have float options!
  1133. else if(currentOption[i].value != x) {
  1134. currentOption[i].value = x;
  1135. if(currentCps) {
  1136. snprintf(buf, MSG_SIZ, "option %s=%.0f\n", currentOption[i].name, x);
  1137. SendToProgram(buf, currentCps);
  1138. } else *(int*) currentOption[i].target = x;
  1139. }
  1140. break;
  1141. case CheckBox:
  1142. j = 0;
  1143. XtSetArg(args[0], XtNstate, &j);
  1144. XtGetValues(currentOption[i].handle, args, 1);
  1145. if(currentOption[i].value != j) {
  1146. currentOption[i].value = j;
  1147. if(currentCps) {
  1148. snprintf(buf, MSG_SIZ, "option %s=%d\n", currentOption[i].name, j);
  1149. SendToProgram(buf, currentCps);
  1150. } else *(Boolean*) currentOption[i].target = j;
  1151. }
  1152. break;
  1153. case ComboBox:
  1154. val = ((char**)currentOption[i].choice)[values[i]];
  1155. if(currentCps) {
  1156. if(currentOption[i].value == values[i]) break; // not changed
  1157. currentOption[i].value = values[i];
  1158. snprintf(buf, MSG_SIZ, "option %s=%s\n", currentOption[i].name,
  1159. ((char**)currentOption[i].textValue)[values[i]]);
  1160. SendToProgram(buf, currentCps);
  1161. } else if(val && (*(char**) currentOption[i].target == NULL || strcmp(*(char**) currentOption[i].target, val))) {
  1162. if(*(char**) currentOption[i].target) free(*(char**) currentOption[i].target);
  1163. *(char**) currentOption[i].target = strdup(val);
  1164. }
  1165. break;
  1166. case EndMark:
  1167. if(currentOption[i].target) // callback for implementing necessary actions on OK (like redraw)
  1168. ((ButtonCallback*) currentOption[i].target)(i);
  1169. break;
  1170. default:
  1171. printf("GenericReadout: unexpected case in switch.\n");
  1172. case Button:
  1173. case SaveButton:
  1174. case Label:
  1175. case Break:
  1176. break;
  1177. }
  1178. if(currentOption[i].type == EndMark) break;
  1179. }
  1180. }
  1181. void GenericCallback(w, client_data, call_data)
  1182. Widget w;
  1183. XtPointer client_data, call_data;
  1184. {
  1185. String name, val;
  1186. Arg args[16];
  1187. char buf[MSG_SIZ];
  1188. int i, j;
  1189. int data = (intptr_t) client_data;
  1190. currentOption = dialogOptions[data>>16]; data &= 0xFFFF;
  1191. XtSetArg(args[0], XtNlabel, &name);
  1192. XtGetValues(w, args, 1);
  1193. if (strcmp(name, _("cancel")) == 0) {
  1194. PopDown(data);
  1195. return;
  1196. }
  1197. if (strcmp(name, _("OK")) == 0) { // save buttons imply OK
  1198. GenericReadout(-1);
  1199. PopDown(data);
  1200. return;
  1201. }
  1202. if(currentCps) {
  1203. if(currentOption[data].type == SaveButton) GenericReadout(-1);
  1204. snprintf(buf, MSG_SIZ, "option %s\n", name);
  1205. SendToProgram(buf, currentCps);
  1206. } else ((ButtonCallback*) currentOption[data].target)(data);
  1207. }
  1208. static char *oneLiner = "<Key>Return: redraw-display()\n";
  1209. int
  1210. GenericPopUp(Option *option, char *title, int dlgNr)
  1211. {
  1212. Arg args[16];
  1213. Widget popup, layout, dialog, edit=NULL, form, last, b_ok, b_cancel, leftMargin = NULL, textField = NULL;
  1214. Window root, child;
  1215. int x, y, i, j, height=999, width=1, h, c, w;
  1216. int win_x, win_y, maxWidth, maxTextWidth;
  1217. unsigned int mask;
  1218. char def[MSG_SIZ], *msg;
  1219. static char pane[6] = "paneX";
  1220. Widget texts[100], forelast = NULL, anchor, widest, lastrow = NULL;
  1221. if(shellUp[dlgNr]) return 0; // already up
  1222. if(dlgNr && shells[dlgNr]) {
  1223. XtPopup(shells[dlgNr], XtGrabNone);
  1224. shellUp[dlgNr] = True;
  1225. return 0;
  1226. }
  1227. dialogOptions[dlgNr] = option; // make available to callback
  1228. // post currentOption globally, so Spin and Combo callbacks can already use it
  1229. // WARNING: this kludge does not work for persistent dialogs, so that these cannot have spin or combo controls!
  1230. currentOption = option;
  1231. if(currentCps) { // Settings popup for engine: format through heuristic
  1232. int n = currentCps->nrOptions;
  1233. if(n > 50) width = 4; else if(n>24) width = 2; else width = 1;
  1234. height = n / width + 1;
  1235. if(currentOption[n-1].type == Button || currentOption[n-1].type == SaveButton) currentOption[n].min = 1; // OK on same line
  1236. currentOption[n].type = EndMark; currentOption[n].target = NULL; // delimit list by callback-less end mark
  1237. }
  1238. i = 0;
  1239. XtSetArg(args[i], XtNresizable, True); i++;
  1240. popup = shells[dlgNr] =
  1241. XtCreatePopupShell(title, transientShellWidgetClass,
  1242. shellWidget, args, i);
  1243. layout =
  1244. XtCreateManagedWidget(layoutName, formWidgetClass, popup,
  1245. layoutArgs, XtNumber(layoutArgs));
  1246. for(c=0; c<width; c++) {
  1247. pane[4] = 'A'+c;
  1248. form =
  1249. XtCreateManagedWidget(pane, formWidgetClass, layout,
  1250. formArgs, XtNumber(formArgs));
  1251. j=0;
  1252. XtSetArg(args[j], XtNfromHoriz, leftMargin); j++;
  1253. XtSetValues(form, args, j);
  1254. leftMargin = form;
  1255. last = widest = NULL; anchor = lastrow;
  1256. for(h=0; h<height; h++) {
  1257. i = h + c*height;
  1258. if(option[i].type == EndMark) break;
  1259. lastrow = forelast;
  1260. forelast = last;
  1261. switch(option[i].type) {
  1262. case Fractional:
  1263. snprintf(def, MSG_SIZ, "%.2f", *(float*)option[i].target);
  1264. option[i].value = *(float*)option[i].target;
  1265. goto tBox;
  1266. case Spin:
  1267. if(!currentCps) option[i].value = *(int*)option[i].target;
  1268. snprintf(def, MSG_SIZ, "%d", option[i].value);
  1269. case TextBox:
  1270. case FileName:
  1271. case PathName:
  1272. tBox:
  1273. if(option[i].name[0]) {
  1274. j=0;
  1275. XtSetArg(args[j], XtNfromVert, last); j++;
  1276. XtSetArg(args[j], XtNleft, XtChainLeft); j++;
  1277. XtSetArg(args[j], XtNright, XtChainLeft); j++;
  1278. XtSetArg(args[j], XtNborderWidth, 0); j++;
  1279. XtSetArg(args[j], XtNjustify, XtJustifyLeft); j++;
  1280. texts[h] =
  1281. dialog = XtCreateManagedWidget(option[i].name, labelWidgetClass, form, args, j);
  1282. } else texts[h] = dialog = NULL;
  1283. w = option[i].type == Spin || option[i].type == Fractional ? 70 : option[i].max ? option[i].max : 205;
  1284. if(option[i].type == FileName || option[i].type == PathName) w -= 55;
  1285. j=0;
  1286. XtSetArg(args[j], XtNfromVert, last); j++;
  1287. XtSetArg(args[j], XtNfromHoriz, dialog); j++;
  1288. XtSetArg(args[j], XtNborderWidth, 1); j++;
  1289. XtSetArg(args[j], XtNwidth, w); j++;
  1290. if(option[i].type == TextBox && option[i].min) {
  1291. XtSetArg(args[j], XtNheight, option[i].min); j++;
  1292. if(option[i].value & 1) { XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++; }
  1293. if(option[i].value & 2) { XtSetArg(args[j], XtNscrollHorizontal, XawtextScrollAlways); j++; }
  1294. if(option[i].value & 4) { XtSetArg(args[j], XtNautoFill, True); j++; }
  1295. if(option[i].value & 8) { XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++; }
  1296. }
  1297. XtSetArg(args[j], XtNleft, XtChainLeft); j++;
  1298. XtSetArg(args[j], XtNeditType, XawtextEdit); j++;
  1299. XtSetArg(args[j], XtNuseStringInPlace, False); j++;
  1300. XtSetArg(args[j], XtNdisplayCaret, False); j++;
  1301. XtSetArg(args[j], XtNright, XtChainRight); j++;
  1302. XtSetArg(args[j], XtNresizable, True); j++;
  1303. XtSetArg(args[j], XtNinsertPosition, 9999); j++;
  1304. XtSetArg(args[j], XtNstring, option[i].type==Spin || option[i].type==Fractional ? def :
  1305. currentCps ? option[i].textValue : *(char**)option[i].target); j++;
  1306. edit = last;
  1307. option[i].handle = (void*)
  1308. (textField = last = XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j));
  1309. XtAddEventHandler(last, ButtonPressMask, False, SetFocus, (XtPointer) popup);
  1310. if(option[i].min == 0 || option[i].type != TextBox)
  1311. XtOverrideTranslations(last, XtParseTranslationTable(oneLiner));
  1312. if(option[i].type == TextBox || option[i].type == Fractional) break;
  1313. // add increment and decrement controls for spin
  1314. j=0;
  1315. XtSetArg(args[j], XtNfromVert, edit); j++;
  1316. XtSetArg(args[j], XtNfromHoriz, last); j++;
  1317. XtSetArg(args[j], XtNleft, XtChainRight); j++;
  1318. XtSetArg(args[j], XtNright, XtChainRight); j++;
  1319. if(option[i].type == FileName || option[i].type == PathName) {
  1320. w = 50; msg = "browse";
  1321. } else {
  1322. XtSetArg(args[j], XtNheight, 10); j++;
  1323. w = 20; msg = "+";
  1324. }
  1325. XtSetArg(args[j], XtNwidth, w); j++;
  1326. edit = XtCreateManagedWidget(msg, commandWidgetClass, form, args, j);
  1327. XtAddCallback(edit, XtNcallback, SpinCallback, (XtPointer)(intptr_t) i);
  1328. if(option[i].type != Spin) break;
  1329. j=0;
  1330. XtSetArg(args[j], XtNfromVert, edit); j++;
  1331. XtSetArg(args[j], XtNfromHoriz, last); j++;
  1332. XtSetArg(args[j], XtNheight, 10); j++;
  1333. XtSetArg(args[j], XtNwidth, 20); j++;
  1334. XtSetArg(args[j], XtNleft, XtChainRight); j++;
  1335. XtSetArg(args[j], XtNright, XtChainRight); j++;
  1336. last = XtCreateManagedWidget("-", commandWidgetClass, form, args, j);
  1337. XtAddCallback(last, XtNcallback, SpinCallback, (XtPointer)(intptr_t) i);
  1338. break;
  1339. case CheckBox:
  1340. if(!currentCps) option[i].value = *(Boolean*)option[i].target;
  1341. j=0;
  1342. XtSetArg(args[j], XtNfromVert, last); j++;
  1343. XtSetArg(args[j], XtNwidth, 10); j++;
  1344. XtSetArg(args[j], XtNheight, 10); j++;
  1345. XtSetArg(args[j], XtNleft, XtChainLeft); j++;
  1346. XtSetArg(args[j], XtNright, XtChainLeft); j++;
  1347. XtSetArg(args[j], XtNstate, option[i].value); j++;
  1348. option[i].handle = (void*)
  1349. (dialog = XtCreateManagedWidget(" ", toggleWidgetClass, form, args, j));
  1350. case Label:
  1351. msg = option[i].name;
  1352. if(*msg == NULLCHAR) msg = option[i].textValue;
  1353. if(!msg) break;
  1354. j=0;
  1355. XtSetArg(args[j], XtNfromVert, last); j++;
  1356. XtSetArg(args[j], XtNfromHoriz, option[i].type != Label ? dialog : NULL); j++;
  1357. XtSetArg(args[j], XtNleft, XtChainLeft); j++;
  1358. XtSetArg(args[j], XtNborderWidth, 0); j++;
  1359. XtSetArg(args[j], XtNjustify, XtJustifyLeft); j++;
  1360. last = XtCreateManagedWidget(msg, labelWidgetClass, form, args, j);
  1361. if(option[i].type == CheckBox)
  1362. XtAddEventHandler(last, ButtonPressMask, False, CheckCallback, (XtPointer)(intptr_t) i);
  1363. break;
  1364. case SaveButton:
  1365. case Button:
  1366. j=0;
  1367. XtSetArg(args[j], XtNfromVert, option[i].min & 1 ? lastrow : last); j++;
  1368. if(option[i].min & 1) { XtSetArg(args[j], XtNfromHoriz, last); j++; }
  1369. else { XtSetArg(args[j], XtNfromHoriz, NULL); j++; lastrow = forelast; }
  1370. if(option[i].max) XtSetArg(args[j], XtNwidth, option[i].max); j++;
  1371. if(option[i].textValue) { // special for buttons of New Variant dialog
  1372. XtSetArg(args[j], XtNsensitive, appData.noChessProgram || option[i].value < 0
  1373. || strstr(first.variants, VariantName(option[i].value))); j++;
  1374. XtSetArg(args[j], XtNborderWidth, (gameInfo.variant == option[i].value)+1); j++;
  1375. }
  1376. option[i].handle = (void*)
  1377. (dialog = last = XtCreateManagedWidget(option[i].name, commandWidgetClass, form, args, j));
  1378. if(option[i].choice && ((char*)option[i].choice)[0] == '#' && !currentCps) {
  1379. SetColor( *(char**) option[i-1].target, last);
  1380. XtAddEventHandler(option[i-1].handle, KeyReleaseMask, False, ColorChanged, (XtPointer)(intptr_t) i-1);
  1381. }
  1382. XtAddCallback(last, XtNcallback, GenericCallback,
  1383. (XtPointer)(intptr_t) i + (dlgNr<<16));
  1384. if(option[i].textValue) SetColor( option[i].textValue, last);
  1385. forelast = lastrow; // next button can go on same row
  1386. break;
  1387. case ComboBox:
  1388. j=0;
  1389. XtSetArg(args[j], XtNfromVert, last); j++;
  1390. XtSetArg(args[j], XtNleft, XtChainLeft); j++;
  1391. XtSetArg(args[j], XtNright, XtChainLeft); j++;
  1392. XtSetArg(args[j], XtNborderWidth, 0); j++;
  1393. XtSetArg(args[j], XtNjustify, XtJustifyLeft); j++;
  1394. texts[h] = dialog = XtCreateManagedWidget(option[i].name, labelWidgetClass, form, args, j);
  1395. if(currentCps) option[i].choice = (char**) option[i].textValue; else {
  1396. for(j=0; option[i].choice[j]; j++)
  1397. if(*(char**)option[i].target && !strcmp(*(char**)option[i].target, option[i].choice[j])) break;
  1398. option[i].value = j + (option[i].choice[j] == NULL);
  1399. }
  1400. j=0;
  1401. XtSetArg(args[j], XtNfromVert, last); j++;
  1402. XtSetArg(args[j], XtNfromHoriz, dialog); j++;
  1403. XtSetArg(args[j], XtNwidth, option[i].max && !currentCps ? option[i].max : 100); j++;
  1404. XtSetArg(args[j], XtNleft, XtChainLeft); j++;
  1405. XtSetArg(args[j], XtNmenuName, XtNewString(option[i].name)); j++;
  1406. XtSetArg(args[j], XtNlabel, ((char**)option[i].textValue)[option[i].value]); j++;
  1407. option[i].handle = (void*)
  1408. (last = XtCreateManagedWidget(" ", menuButtonWidgetClass, form, args, j));
  1409. CreateComboPopup(last, option[i].name, i, (char **) option[i].textValue);
  1410. values[i] = option[i].value;
  1411. break;
  1412. case Break:
  1413. width++;
  1414. height = i+1;
  1415. break;
  1416. default:
  1417. printf("GenericPopUp: unexpected case in switch.\n");
  1418. break;
  1419. }
  1420. }
  1421. // make an attempt to align all spins and textbox controls
  1422. maxWidth = maxTextWidth = 0;
  1423. for(h=0; h<height; h++) {
  1424. i = h + c*height;
  1425. if(option[i].type == EndMark) break;
  1426. if(option[i].type == Spin || option[i].type == TextBox || option[i].type == ComboBox
  1427. || option[i].type == PathName || option[i].type == FileName) {
  1428. Dimension w;
  1429. if(!texts[h]) continue;
  1430. j=0;
  1431. XtSetArg(args[j], XtNwidth, &w); j++;
  1432. XtGetValues(texts[h], args, j);
  1433. if(option[i].type == Spin) {
  1434. if(w > maxWidth) maxWidth = w;
  1435. widest = texts[h];
  1436. } else {
  1437. if(w > maxTextWidth) maxTextWidth = w;
  1438. if(!widest) widest = texts[h];
  1439. }
  1440. }
  1441. }
  1442. if(maxTextWidth + 110 < maxWidth)
  1443. maxTextWidth = maxWidth - 110;
  1444. else maxWidth = maxTextWidth + 110;
  1445. for(h=0; h<height; h++) {
  1446. i = h + c*height;
  1447. if(option[i].type == EndMark) break;
  1448. if(!texts[h]) continue;
  1449. j=0;
  1450. if(option[i].type == Spin) {
  1451. XtSetArg(args[j], XtNwidth, maxWidth); j++;
  1452. XtSetValues(texts[h], args, j);
  1453. } else
  1454. if(option[i].type == TextBox || option[i].type == ComboBox || option[i].type == PathName || option[i].type == FileName) {
  1455. XtSetArg(args[j], XtNwidth, maxTextWidth); j++;
  1456. XtSetValues(texts[h], args, j);
  1457. }
  1458. }
  1459. }
  1460. if(!(option[i].min & 2)) {
  1461. j=0;
  1462. if(option[i].min & 1) { XtSetArg(args[j], XtNfromHoriz, last); last = forelast; } else
  1463. XtSetArg(args[j], XtNfromHoriz, widest ? widest : dialog); j++;
  1464. XtSetArg(args[j], XtNfromVert, anchor ? anchor : last); j++;
  1465. XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
  1466. XtSetArg(args[j], XtNtop, XtChainBottom); j++;
  1467. XtSetArg(args[j], XtNleft, XtChainRight); j++;
  1468. XtSetArg(args[j], XtNright, XtChainRight); j++;
  1469. b_ok = XtCreateManagedWidget(_("OK"), commandWidgetClass, form, args, j);
  1470. XtAddCallback(b_ok, XtNcallback, GenericCallback, (XtPointer)(intptr_t) dlgNr + (dlgNr<<16));
  1471. XtSetArg(args[0], XtNfromHoriz, b_ok);
  1472. b_cancel = XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
  1473. XtAddCallback(b_cancel, XtNcallback, GenericCallback, (XtPointer)(intptr_t) dlgNr);
  1474. }
  1475. XtRealizeWidget(popup);
  1476. XSetWMProtocols(xDisplay, XtWindow(popup), &wm_delete_window, 1);
  1477. snprintf(def, MSG_SIZ, "<Message>WM_PROTOCOLS: GenericPopDown(\"%d\") \n", dlgNr);
  1478. XtAugmentTranslations(popup, XtParseTranslationTable(def));
  1479. XQueryPointer(xDisplay, xBoardWindow, &root, &child,
  1480. &x, &y, &win_x, &win_y, &mask);
  1481. XtSetArg(args[0], XtNx, x - 10);
  1482. XtSetArg(args[1], XtNy, y - 30);
  1483. XtSetValues(popup, args, 2);
  1484. XtPopup(popup, dlgNr ? XtGrabNone : XtGrabExclusive);
  1485. shellUp[dlgNr] = True;
  1486. previous = NULL;
  1487. if(textField)SetFocus(textField, popup, (XEvent*) NULL, False);
  1488. if(dlgNr && wp[dlgNr] && wp[dlgNr]->width > 0) { // if persistent window-info available, reposition
  1489. j = 0;
  1490. XtSetArg(args[j], XtNheight, (Dimension) (wp[dlgNr]->height)); j++;
  1491. XtSetArg(args[j], XtNwidth, (Dimension) (wp[dlgNr]->width)); j++;
  1492. XtSetArg(args[j], XtNx, (Position) (wp[dlgNr]->x)); j++;
  1493. XtSetArg(args[j], XtNy, (Position) (wp[dlgNr]->y)); j++;
  1494. XtSetValues(popup, args, j);
  1495. }
  1496. return 1;
  1497. }
  1498. void IcsOptionsProc(w, event, prms, nprms)
  1499. Widget w;
  1500. XEvent *event;
  1501. String *prms;
  1502. Cardinal *nprms;
  1503. {
  1504. GenericPopUp(icsOptions, _("ICS Options"), 0);
  1505. }
  1506. void LoadOptionsProc(w, event, prms, nprms)
  1507. Widget w;
  1508. XEvent *event;
  1509. String *prms;
  1510. Cardinal *nprms;
  1511. {
  1512. GenericPopUp(loadOptions, _("Load Game Options"), 0);
  1513. }
  1514. void SaveOptionsProc(w, event, prms, nprms)
  1515. Widget w;
  1516. XEvent *event;
  1517. String *prms;
  1518. Cardinal *nprms;
  1519. {
  1520. GenericPopUp(saveOptions, _("Save Game Options"), 0);
  1521. }
  1522. void SoundOptionsProc(w, event, prms, nprms)
  1523. Widget w;
  1524. XEvent *event;
  1525. String *prms;
  1526. Cardinal *nprms;
  1527. {
  1528. soundFiles[2] = "*";
  1529. GenericPopUp(soundOptions, _("Sound Options"), 0);
  1530. }
  1531. void BoardOptionsProc(w, event, prms, nprms)
  1532. Widget w;
  1533. XEvent *event;
  1534. String *prms;
  1535. Cardinal *nprms;
  1536. {
  1537. GenericPopUp(boardOptions, _("Board Options"), 0);
  1538. }
  1539. void EngineMenuProc(w, event, prms, nprms)
  1540. Widget w;
  1541. XEvent *event;
  1542. String *prms;
  1543. Cardinal *nprms;
  1544. {
  1545. GenericPopUp(adjudicationOptions, "Adjudicate non-ICS Games", 0);
  1546. }
  1547. void UciMenuProc(w, event, prms, nprms)
  1548. Widget w;
  1549. XEvent *event;
  1550. String *prms;
  1551. Cardinal *nprms;
  1552. {
  1553. oldCores = appData.smpCores;
  1554. oldPonder = appData.ponderNextMove;
  1555. GenericPopUp(commonEngineOptions, _("Common Engine Settings"), 0);
  1556. }
  1557. void NewVariantProc(w, event, prms, nprms)
  1558. Widget w;
  1559. XEvent *event;
  1560. String *prms;
  1561. Cardinal *nprms;
  1562. {
  1563. GenericPopUp(variantDescriptors, _("New Variant"), 0);
  1564. }
  1565. void OptionsProc(w, event, prms, nprms)
  1566. Widget w;
  1567. XEvent *event;
  1568. String *prms;
  1569. Cardinal *nprms;
  1570. {
  1571. oldPonder = appData.ponderNextMove;
  1572. GenericPopUp(generalOptions, _("General Options"), 0);
  1573. }
  1574. void MatchOptionsProc(w, event, prms, nprms)
  1575. Widget w;
  1576. XEvent *event;
  1577. String *prms;
  1578. Cardinal *nprms;
  1579. {
  1580. GenericPopUp(matchOptions, _("Match Options"), 0);
  1581. }
  1582. Option textOptions[100];
  1583. extern char *icsTextMenuString;
  1584. void PutText P((char *text, int pos));
  1585. SendString(char *p)
  1586. {
  1587. char buf[MSG_SIZ], *q;
  1588. if(q = strstr(p, "$input")) {
  1589. if(!shellUp[4]) return;
  1590. strncpy(buf, p, MSG_SIZ);
  1591. strncpy(buf + (q-p), q+6, MSG_SIZ-(q-p));
  1592. PutText(buf, q-p);
  1593. return;
  1594. }
  1595. snprintf(buf, MSG_SIZ, "%s\n", p);
  1596. SendToICS(buf);
  1597. }
  1598. /* function called when the data to Paste is ready */
  1599. static void
  1600. SendTextCB(Widget w, XtPointer client_data, Atom *selection,
  1601. Atom *type, XtPointer value, unsigned long *len, int *format)
  1602. {
  1603. char buf[MSG_SIZ], *p = (char*) textOptions[(int)(intptr_t) client_data].choice, *name = (char*) value, *q;
  1604. if (value==NULL || *len==0) return; /* nothing selected, abort */
  1605. name[*len]='\0';
  1606. strncpy(buf, p, MSG_SIZ);
  1607. q = strstr(p, "$name");
  1608. snprintf(buf + (q-p), MSG_SIZ -(q-p), "%s%s", name, q+5);
  1609. SendString(buf);
  1610. XtFree(value);
  1611. }
  1612. void SendText(int n)
  1613. {
  1614. char *p = (char*) textOptions[n].choice;
  1615. if(strstr(p, "$name")) {
  1616. XtGetSelectionValue(menuBarWidget,
  1617. XA_PRIMARY, XA_STRING,
  1618. /* (XtSelectionCallbackProc) */ SendTextCB,
  1619. (XtPointer) (intptr_t) n, /* client_data passed to PastePositionCB */
  1620. CurrentTime
  1621. );
  1622. } else SendString(p);
  1623. }
  1624. void IcsTextProc(w, event, prms, nprms)
  1625. Widget w;
  1626. XEvent *event;
  1627. String *prms;
  1628. Cardinal *nprms;
  1629. {
  1630. int i=0, j;
  1631. char *p, *q, *r;
  1632. if((p = icsTextMenuString) == NULL) return;
  1633. do {
  1634. q = r = p; while(*p && *p != ';') p++;
  1635. for(j=0; j<p-q; j++) textOptions[i].name[j] = *r++;
  1636. textOptions[i].name[j++] = 0;
  1637. if(!*p) break;
  1638. if(*++p == '\n') p++; // optional linefeed after button-text terminating semicolon
  1639. q = p;
  1640. textOptions[i].choice = (char**) (r = textOptions[i].name + j);
  1641. while(*p && (*p != ';' || p[1] != '\n')) textOptions[i].name[j++] = *p++;
  1642. textOptions[i].name[j++] = 0;
  1643. if(*p) p += 2;
  1644. textOptions[i].max = 135;
  1645. textOptions[i].min = i&1;
  1646. textOptions[i].handle = NULL;
  1647. textOptions[i].target = &SendText;
  1648. textOptions[i].textValue = strstr(r, "$input") ? "#80FF80" : strstr(r, "$name") ? "#FF8080" : "#FFFFFF";
  1649. textOptions[i].type = Button;
  1650. } while(++i < 99 && *p);
  1651. if(i == 0) return;
  1652. textOptions[i].type = EndMark;
  1653. textOptions[i].target = NULL;
  1654. textOptions[i].min = 2;
  1655. MarkMenu("menuView.ICStex", 3);
  1656. GenericPopUp(textOptions, _("ICS text menu"), 3);
  1657. }
  1658. extern char ICSInputTranslations[];
  1659. char *icsText;
  1660. Option boxOptions[] = {
  1661. { 0, 30, 400, NULL, (void*) &icsText, "", NULL, TextBox, "" },
  1662. { 0, 3, 0, NULL, NULL, "", NULL, EndMark , "" }
  1663. };
  1664. void PutText(char *text, int pos)
  1665. {
  1666. Widget edit;
  1667. Arg args[16];
  1668. char buf[MSG_SIZ], *p;
  1669. if(strstr(text, "$add ") == text) {
  1670. XtSetArg(args[0], XtNstring, &p);
  1671. XtGetValues(boxOptions[0].handle, args, 1);
  1672. snprintf(buf, MSG_SIZ, "%s%s", p, text+5); text = buf;
  1673. pos += strlen(p) - 5;
  1674. }
  1675. XtSetArg(args[0], XtNstring, text);
  1676. XtSetValues(boxOptions[0].handle, args, 1);
  1677. XtSetArg(args[0], XtNinsertPosition, pos);
  1678. XtSetValues(boxOptions[0].handle, args, 1);
  1679. // SetFocus(boxOptions[0].handle, shells[4], NULL, False); // No idea why this does not work, and the following is needed:
  1680. XSetInputFocus(xDisplay, XtWindow(boxOptions[0].handle), RevertToPointerRoot, CurrentTime);
  1681. }
  1682. void InputBoxPopup()
  1683. {
  1684. MarkMenu("menuView.ICS Input Box", 4);
  1685. if(GenericPopUp(boxOptions, _("ICS input box"), 4))
  1686. XtOverrideTranslations(boxOptions[0].handle, XtParseTranslationTable(ICSInputTranslations));
  1687. }
  1688. void
  1689. SettingsPopUp(ChessProgramState *cps)
  1690. {
  1691. currentCps = cps;
  1692. GenericPopUp(cps->option, _("Engine Settings"), 0);
  1693. }
  1694. void FirstSettingsProc(w, event, prms, nprms)
  1695. Widget w;
  1696. XEvent *event;
  1697. String *prms;
  1698. Cardinal *nprms;
  1699. {
  1700. SettingsPopUp(&first);
  1701. }
  1702. void SecondSettingsProc(w, event, prms, nprms)
  1703. Widget w;
  1704. XEvent *event;
  1705. String *prms;
  1706. Cardinal *nprms;
  1707. {
  1708. if(WaitForSecond(SettingsMenuIfReady)) return;
  1709. SettingsPopUp(&second);
  1710. }
  1711. //---------------------------- Chat Windows ----------------------------------------------
  1712. void OutputChatMessage(int partner, char *mess)
  1713. {
  1714. return; // dummy
  1715. }