2 * dialogs.c -- platform-independent code for dialogs of XBoard
4 * Copyright 2000, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
5 * ------------------------------------------------------------------------
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.
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.
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/. *
20 *------------------------------------------------------------------------
21 ** See the file ChangeLog for a revision history. */
23 // [HGM] this file is the counterpart of woptions.c, containing xboard popup menus
24 // similar to those of WinBoard, to set the most common options interactively.
31 #include <sys/types.h>
36 #else /* not STDC_HEADERS */
37 extern char *getenv();
40 # else /* not HAVE_STRING_H */
42 # endif /* not HAVE_STRING_H */
43 #endif /* not STDC_HEADERS */
58 # define _(s) gettext (s)
59 # define N_(s) gettext_noop (s)
66 int values[MAX_OPTIONS];
67 ChessProgramState *currentCps;
68 ButtonCallback *comboCallback;
70 //----------------------------Generic dialog --------------------------------------------
72 // cloned from Engine Settings dialog (and later merged with it)
74 char *marked[NrOfDialogs];
75 Boolean shellUp[NrOfDialogs];
78 MarkMenu (char *item, int dlgNr)
80 MarkMenuItem(marked[dlgNr] = item, True);
84 AddLine (Option *opt, char *s)
87 AppendText(opt, "\n");
90 //---------------------------------------------- Update dialog controls ------------------------------------
93 GenericUpdate (Option *opts, int selected)
99 if(selected >= 0) { if(i < selected) continue; else if(i > selected) break; }
100 switch(opts[i].type) {
104 SetWidgetText(&opts[i], *(char**) opts[i].target, -1);
107 sprintf(buf, "%d", *(int*) opts[i].target);
108 SetWidgetText(&opts[i], buf, -1);
111 sprintf(buf, "%4.2f", *(float*) opts[i].target);
112 SetWidgetText(&opts[i], buf, -1);
115 SetWidgetState(&opts[i], *(Boolean*) opts[i].target);
118 for(j=0; opts[i].choice[j]; j++)
119 if(*(char**)opts[i].target && !strcmp(*(char**)opts[i].target, opts[i].choice[j])) break;
120 values[i] = opts[i].value = j + (opts[i].choice[j] == NULL);
121 // TODO: actually display this
126 printf("GenericUpdate: unexpected case in switch.\n");
136 //------------------------------------------- Read out dialog controls ------------------------------------
139 GenericReadout (Option *opts, int selected)
143 char buf[MSG_SIZ], **dest;
145 for(i=0; ; i++) { // send all options that had to be OK-ed to engine
146 if(selected >= 0) { if(i < selected) continue; else if(i > selected) break; }
147 switch(opts[i].type) {
151 GetWidgetText(&opts[i], &val);
152 dest = currentCps ? &(opts[i].textValue) : (char**) opts[i].target;
153 if(*dest == NULL || strcmp(*dest, val)) {
155 snprintf(buf, MSG_SIZ, "option %s=%s\n", opts[i].name, val);
156 SendToProgram(buf, currentCps);
158 if(*dest) free(*dest);
159 *dest = malloc(strlen(val)+1);
161 safeStrCpy(*dest, val, MSG_SIZ - (*dest - opts[i].name)); // copy text there
166 GetWidgetText(&opts[i], &val);
167 x = 0.0; // Initialise because sscanf() will fail if non-numeric text is entered
168 sscanf(val, "%f", &x);
169 if(x > opts[i].max) x = opts[i].max;
170 if(x < opts[i].min) x = opts[i].min;
171 if(opts[i].type == Fractional)
172 *(float*) opts[i].target = x; // engines never have float options!
173 else if(opts[i].value != x) {
176 snprintf(buf, MSG_SIZ, "option %s=%.0f\n", opts[i].name, x);
177 SendToProgram(buf, currentCps);
178 } else *(int*) opts[i].target = x;
183 GetWidgetState(&opts[i], &j);
184 if(opts[i].value != j) {
187 snprintf(buf, MSG_SIZ, "option %s=%d\n", opts[i].name, j);
188 SendToProgram(buf, currentCps);
189 } else *(Boolean*) opts[i].target = j;
193 val = ((char**)opts[i].choice)[values[i]];
195 if(opts[i].value == values[i]) break; // not changed
196 opts[i].value = values[i];
197 snprintf(buf, MSG_SIZ, "option %s=%s\n", opts[i].name,
198 ((char**)opts[i].textValue)[values[i]]);
199 SendToProgram(buf, currentCps);
200 } else if(val && (*(char**) opts[i].target == NULL || strcmp(*(char**) opts[i].target, val))) {
201 if(*(char**) opts[i].target) free(*(char**) opts[i].target);
202 *(char**) opts[i].target = strdup(val);
206 if(opts[i].target) // callback for implementing necessary actions on OK (like redraw)
207 res = ((OKCallback*) opts[i].target)(i);
210 printf("GenericReadout: unexpected case in switch.\n");
217 if(opts[i].type == EndMark) break;
222 //------------------------------------------- Match Options ------------------------------------------------------
224 char *engineName, *engineChoice, *tfName;
225 char *engineList[MAXENGINES] = {" "}, *engineMnemonic[MAXENGINES] = {""};
227 static void AddToTourney P((int n));
228 static void CloneTourney P((void));
229 static void ReplaceParticipant P((void));
230 static void UpgradeParticipant P((void));
235 ASSIGN(appData.participants, engineName);
236 if(!CreateTourney(tfName) || matchMode) return matchMode || !appData.participants[0];
237 PopDown(TransientDlg); // early popdown to prevent FreezeUI called through MatchEvent from causing XtGrab warning
238 MatchEvent(2); // start tourney
242 static Option matchOptions[] = {
243 { 0, 0, 0, NULL, (void*) &tfName, ".trn", NULL, FileName, N_("Tournament file:") },
244 { 0, 0, 0, NULL, (void*) &appData.roundSync, "", NULL, CheckBox, N_("Sync after round (for concurrent playing of a single") },
245 { 0, 0, 0, NULL, (void*) &appData.cycleSync, "", NULL, CheckBox, N_("Sync after cycle tourney with multiple XBoards)") },
246 { 0xD, 150, 0, NULL, (void*) &engineName, "", NULL, TextBox, N_("Tourney participants:") },
247 { 0, COMBO_CALLBACK | NO_GETTEXT,
248 0, NULL, (void*) &engineChoice, (char*) (engineMnemonic+1), (engineMnemonic+1), ComboBox, N_("Select Engine:") },
249 { 0, 0, 10, NULL, (void*) &appData.tourneyType, "", NULL, Spin, N_("Tourney type (0 = round-robin, 1 = gauntlet):") },
250 { 0, 1, 1000000000, NULL, (void*) &appData.tourneyCycles, "", NULL, Spin, N_("Number of tourney cycles (or Swiss rounds):") },
251 { 0, 1, 1000000000, NULL, (void*) &appData.defaultMatchGames, "", NULL, Spin, N_("Default Number of Games in Match (or Pairing):") },
252 { 0, 0, 1000000000, NULL, (void*) &appData.matchPause, "", NULL, Spin, N_("Pause between Match Games (msec):") },
253 { 0, 0, 0, NULL, (void*) &appData.saveGameFile, ".pgn", NULL, FileName, N_("Save Tourney Games on:") },
254 { 0, 0, 0, NULL, (void*) &appData.loadGameFile, ".pgn", NULL, FileName, N_("Game File with Opening Lines:") },
255 { 0, -2, 1000000000, NULL, (void*) &appData.loadGameIndex, "", NULL, Spin, N_("Game Number (-1 or -2 = Auto-Increment):") },
256 { 0, 0, 0, NULL, (void*) &appData.loadPositionFile, ".fen", NULL, FileName, N_("File with Start Positions:") },
257 { 0, -2, 1000000000, NULL, (void*) &appData.loadPositionIndex, "", NULL, Spin, N_("Position Number (-1 or -2 = Auto-Increment):") },
258 { 0, 0, 1000000000, NULL, (void*) &appData.rewindIndex, "", NULL, Spin, N_("Rewind Index after this many Games (0 = never):") },
259 { 0, 0, 0, NULL, (void*) &appData.defNoBook, "", NULL, CheckBox, N_("Disable own engine books by default") },
260 { 0, 0, 0, NULL, (void*) &ReplaceParticipant, NULL, NULL, Button, N_("Replace Engine") },
261 { 0, 1, 0, NULL, (void*) &UpgradeParticipant, NULL, NULL, Button, N_("Upgrade Engine") },
262 { 0, 1, 0, NULL, (void*) &CloneTourney, NULL, NULL, Button, N_("Clone Tourney") },
263 { 0, 1, 0, NULL, (void*) &MatchOK, "", NULL, EndMark , "" }
267 ReplaceParticipant ()
269 GenericReadout(matchOptions, 3);
270 Substitute(strdup(engineName), True);
274 UpgradeParticipant ()
276 GenericReadout(matchOptions, 3);
277 Substitute(strdup(engineName), False);
285 GetWidgetText(matchOptions, &name);
286 if(name && name[0] && (f = fopen(name, "r")) ) {
288 saveSaveFile = appData.saveGameFile; appData.saveGameFile = NULL; // this is a persistent option, protect from change
289 ParseArgsFromFile(f);
290 engineName = appData.participants; GenericUpdate(matchOptions, -1);
291 FREE(appData.saveGameFile); appData.saveGameFile = saveSaveFile;
292 } else DisplayError(_("First you must specify an existing tourney file to clone"), 0);
298 GenericReadout(matchOptions, 4); // selected engine
299 AddLine(&matchOptions[3], engineChoice);
305 NamesToList(firstChessProgramNames, engineList, engineMnemonic, "all");
306 comboCallback = &AddToTourney;
307 matchOptions[5].min = -(appData.pairingEngine[0] != NULLCHAR); // with pairing engine, allow Swiss
308 ASSIGN(tfName, appData.tourneyFile[0] ? appData.tourneyFile : MakeName(appData.defName));
309 ASSIGN(engineName, appData.participants);
310 GenericPopUp(matchOptions, _("Match Options"), TransientDlg);
313 // ------------------------------------------- General Options --------------------------------------------------
315 static int oldShow, oldBlind, oldPonder;
318 GeneralOptionsOK (int n)
320 int newPonder = appData.ponderNextMove;
321 appData.ponderNextMove = oldPonder;
322 PonderNextMoveEvent(newPonder);
323 if(!appData.highlightLastMove) ClearHighlights(), ClearPremoveHighlights();
324 if(oldShow != appData.showCoords || oldBlind != appData.blindfold) DrawPosition(TRUE, NULL);
328 static Option generalOptions[] = {
329 { 0, 0, 0, NULL, (void*) &appData.whitePOV, "", NULL, CheckBox, N_("Absolute Analysis Scores") },
330 { 0, 0, 0, NULL, (void*) &appData.sweepSelect, "", NULL, CheckBox, N_("Almost Always Queen (Detour Under-Promote)") },
331 { 0, 0, 0, NULL, (void*) &appData.animateDragging, "", NULL, CheckBox, N_("Animate Dragging") },
332 { 0, 0, 0, NULL, (void*) &appData.animate, "", NULL, CheckBox, N_("Animate Moving") },
333 { 0, 0, 0, NULL, (void*) &appData.autoCallFlag, "", NULL, CheckBox, N_("Auto Flag") },
334 { 0, 0, 0, NULL, (void*) &appData.autoFlipView, "", NULL, CheckBox, N_("Auto Flip View") },
335 { 0, 0, 0, NULL, (void*) &appData.blindfold, "", NULL, CheckBox, N_("Blindfold") },
336 { 0, 0, 0, NULL, (void*) &appData.dropMenu, "", NULL, CheckBox, N_("Drop Menu") },
337 { 0, 0, 0, NULL, (void*) &appData.hideThinkingFromHuman, "", NULL, CheckBox, N_("Hide Thinking from Human") },
338 { 0, 0, 0, NULL, (void*) &appData.highlightLastMove, "", NULL, CheckBox, N_("Highlight Last Move") },
339 { 0, 0, 0, NULL, (void*) &appData.highlightMoveWithArrow, "", NULL, CheckBox, N_("Highlight with Arrow") },
340 { 0, 0, 0, NULL, (void*) &appData.ringBellAfterMoves, "", NULL, CheckBox, N_("Move Sound") },
341 { 0, 0, 0, NULL, (void*) &appData.oneClick, "", NULL, CheckBox, N_("One-Click Moving") },
342 { 0, 0, 0, NULL, (void*) &appData.periodicUpdates, "", NULL, CheckBox, N_("Periodic Updates (in Analysis Mode)") },
343 { 0, 0, 0, NULL, (void*) &appData.ponderNextMove, "", NULL, CheckBox, N_("Ponder Next Move") },
344 { 0, 0, 0, NULL, (void*) &appData.popupExitMessage, "", NULL, CheckBox, N_("Popup Exit Messages") },
345 { 0, 0, 0, NULL, (void*) &appData.popupMoveErrors, "", NULL, CheckBox, N_("Popup Move Errors") },
346 { 0, 0, 0, NULL, (void*) &appData.showEvalInMoveHistory, "", NULL, CheckBox, N_("Scores in Move List") },
347 { 0, 0, 0, NULL, (void*) &appData.showCoords, "", NULL, CheckBox, N_("Show Coordinates") },
348 { 0, 0, 0, NULL, (void*) &appData.markers, "", NULL, CheckBox, N_("Show Target Squares") },
349 { 0, 0, 0, NULL, (void*) &appData.useStickyWindows, "", NULL, CheckBox, N_("Sticky Windows") },
350 { 0, 0, 0, NULL, (void*) &appData.testLegality, "", NULL, CheckBox, N_("Test Legality") },
351 { 0, 0, 10, NULL, (void*) &appData.flashCount, "", NULL, Spin, N_("Flash Moves (0 = no flashing):") },
352 { 0, 1, 10, NULL, (void*) &appData.flashRate, "", NULL, Spin, N_("Flash Rate (high = fast):") },
353 { 0, 5, 100,NULL, (void*) &appData.animSpeed, "", NULL, Spin, N_("Animation Speed (high = slow):") },
354 { 0, 1, 5, NULL, (void*) &appData.zoom, "", NULL, Spin, N_("Zoom factor in Evaluation Graph:") },
355 { 0, 0, 0, NULL, (void*) &GeneralOptionsOK, "", NULL, EndMark , "" }
361 oldPonder = appData.ponderNextMove;
362 oldShow = appData.showCoords; oldBlind = appData.blindfold;
363 GenericPopUp(generalOptions, _("General Options"), TransientDlg);
366 //---------------------------------------------- New Variant ------------------------------------------------
368 static void Pick P((int n));
370 static Option variantDescriptors[] = {
371 { VariantNormal, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("normal")},
372 { VariantFairy, 1, 135, NULL, (void*) &Pick, "#BFBFBF", NULL, Button, N_("fairy")},
373 { VariantFischeRandom, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("FRC")},
374 { VariantSChess, 1, 135, NULL, (void*) &Pick, "#FFBFBF", NULL, Button, N_("Seirawan")},
375 { VariantWildCastle, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("wild castle")},
376 { VariantSuper, 1, 135, NULL, (void*) &Pick, "#FFBFBF", NULL, Button, N_("Superchess")},
377 { VariantNoCastle, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("no castle")},
378 { VariantCrazyhouse, 1, 135, NULL, (void*) &Pick, "#FFBFBF", NULL, Button, N_("crazyhouse")},
379 { VariantKnightmate, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("knightmate")},
380 { VariantBughouse, 1, 135, NULL, (void*) &Pick, "#FFBFBF", NULL, Button, N_("bughouse")},
381 { VariantBerolina, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("berolina")},
382 { VariantShogi, 1, 135, NULL, (void*) &Pick, "#BFFFFF", NULL, Button, N_("shogi (9x9)")},
383 { VariantCylinder, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("cylinder")},
384 { VariantXiangqi, 1, 135, NULL, (void*) &Pick, "#BFFFFF", NULL, Button, N_("xiangqi (9x10)")},
385 { VariantShatranj, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("shatranj")},
386 { VariantCourier, 1, 135, NULL, (void*) &Pick, "#BFFFBF", NULL, Button, N_("courier (12x8)")},
387 { VariantMakruk, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("makruk")},
388 { VariantGreat, 1, 135, NULL, (void*) &Pick, "#BFBFFF", NULL, Button, N_("Great Shatranj (10x8)")},
389 { VariantAtomic, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("atomic")},
390 { VariantFalcon, 1, 135, NULL, (void*) &Pick, "#BFBFFF", NULL, Button, N_("falcon (10x8)")},
391 { VariantTwoKings, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("two kings")},
392 { VariantCapablanca, 1, 135, NULL, (void*) &Pick, "#BFBFFF", NULL, Button, N_("Capablanca (10x8)")},
393 { Variant3Check, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_("3-checks")},
394 { VariantGothic, 1, 135, NULL, (void*) &Pick, "#BFBFFF", NULL, Button, N_("Gothic (10x8)")},
395 { VariantSuicide, 0, 135, NULL, (void*) &Pick, "#FFFFBF", NULL, Button, N_("suicide")},
396 { VariantJanus, 1, 135, NULL, (void*) &Pick, "#BFBFFF", NULL, Button, N_("janus (10x8)")},
397 { VariantGiveaway, 0, 135, NULL, (void*) &Pick, "#FFFFBF", NULL, Button, N_("give-away")},
398 { VariantCapaRandom, 1, 135, NULL, (void*) &Pick, "#BFBFFF", NULL, Button, N_("CRC (10x8)")},
399 { VariantLosers, 0, 135, NULL, (void*) &Pick, "#FFFFBF", NULL, Button, N_("losers")},
400 { VariantGrand, 1, 135, NULL, (void*) &Pick, "#5070FF", NULL, Button, N_("grand (10x10)")},
401 { VariantSpartan, 0, 135, NULL, (void*) &Pick, "#FF0000", NULL, Button, N_("Spartan")},
402 { 0, 0, 0, NULL, NULL, NULL, NULL, Label, N_("Board size ( -1 = default for selected variant):")},
403 { 0, -1, BOARD_RANKS-1, NULL, (void*) &appData.NrRanks, "", NULL, Spin, N_("Number of Board Ranks:") },
404 { 0, -1, BOARD_FILES, NULL, (void*) &appData.NrFiles, "", NULL, Spin, N_("Number of Board Files:") },
405 { 0, -1, BOARD_RANKS-1, NULL, (void*) &appData.holdingsSize, "", NULL, Spin, N_("Holdings Size:") },
406 { 0, 0, 0, NULL, NULL, NULL, NULL, Label,
407 N_("WARNING: variants with un-orthodox\n"
408 "pieces only have built-in bitmaps\n"
409 "for -boardSize middling, bulky and\n"
410 "petite, and substitute king or amazon\n"
411 "for missing bitmaps. (See manual.)")},
412 { 0, 2, 0, NULL, NULL, "", NULL, EndMark , "" }
418 VariantClass v = variantDescriptors[n].value;
419 if(!appData.noChessProgram) {
420 char *name = VariantName(v), buf[MSG_SIZ];
421 if (first.protocolVersion > 1 && StrStr(first.variants, name) == NULL) {
422 /* [HGM] in protocol 2 we check if variant is suported by engine */
423 snprintf(buf, MSG_SIZ, _("Variant %s not supported by %s"), name, first.tidy);
424 DisplayError(buf, 0);
425 return; /* ignore OK if first engine does not support it */
427 if (second.initDone && second.protocolVersion > 1 && StrStr(second.variants, name) == NULL) {
428 snprintf(buf, MSG_SIZ, _("Warning: second engine (%s) does not support this!"), second.tidy);
429 DisplayError(buf, 0); /* use of second engine is optional; only warn user */
433 GenericReadout(variantDescriptors, -1); // make sure ranks and file settings are read
435 gameInfo.variant = v;
436 appData.variant = VariantName(v);
438 shuffleOpenings = FALSE; /* [HGM] shuffle: possible shuffle reset when we switch */
439 startedFromPositionFile = FALSE; /* [HGM] loadPos: no longer valid in new variant */
440 appData.pieceToCharTable = NULL;
441 appData.pieceNickNames = "";
442 appData.colorNickNames = "";
444 PopDown(TransientDlg);
451 GenericPopUp(variantDescriptors, _("New Variant"), TransientDlg);
454 //------------------------------------------- Common Engine Options -------------------------------------
459 CommonOptionsOK (int n)
461 int newPonder = appData.ponderNextMove;
462 // make sure changes are sent to first engine by re-initializing it
463 // if it was already started pre-emptively at end of previous game
464 if(gameMode == BeginningOfGame) Reset(True, True); else {
465 // Some changed setting need immediate sending always.
466 if(oldCores != appData.smpCores)
467 NewSettingEvent(False, &(first.maxCores), "cores", appData.smpCores);
468 appData.ponderNextMove = oldPonder;
469 PonderNextMoveEvent(newPonder);
474 static Option commonEngineOptions[] = {
475 { 0, 0, 0, NULL, (void*) &appData.ponderNextMove, "", NULL, CheckBox, N_("Ponder Next Move") },
476 { 0, 0, 1000, NULL, (void*) &appData.smpCores, "", NULL, Spin, N_("Maximum Number of CPUs per Engine:") },
477 { 0, 0, 0, NULL, (void*) &appData.polyglotDir, "", NULL, PathName, N_("Polygot Directory:") },
478 { 0, 0, 16000, NULL, (void*) &appData.defaultHashSize, "", NULL, Spin, N_("Hash-Table Size (MB):") },
479 { 0, 0, 0, NULL, (void*) &appData.defaultPathEGTB, "", NULL, PathName, N_("Nalimov EGTB Path:") },
480 { 0, 0, 1000, NULL, (void*) &appData.defaultCacheSizeEGTB, "", NULL, Spin, N_("EGTB Cache Size (MB):") },
481 { 0, 0, 0, NULL, (void*) &appData.usePolyglotBook, "", NULL, CheckBox, N_("Use GUI Book") },
482 { 0, 0, 0, NULL, (void*) &appData.polyglotBook, ".bin", NULL, FileName, N_("Opening-Book Filename:") },
483 { 0, 0, 100, NULL, (void*) &appData.bookDepth, "", NULL, Spin, N_("Book Depth (moves):") },
484 { 0, 0, 100, NULL, (void*) &appData.bookStrength, "", NULL, Spin, N_("Book Variety (0) vs. Strength (100):") },
485 { 0, 0, 0, NULL, (void*) &appData.firstHasOwnBookUCI, "", NULL, CheckBox, N_("Engine #1 Has Own Book") },
486 { 0, 0, 0, NULL, (void*) &appData.secondHasOwnBookUCI, "", NULL, CheckBox, N_("Engine #2 Has Own Book ") },
487 { 0, 1, 0, NULL, (void*) &CommonOptionsOK, "", NULL, EndMark , "" }
493 oldCores = appData.smpCores;
494 oldPonder = appData.ponderNextMove;
495 GenericPopUp(commonEngineOptions, _("Common Engine Settings"), TransientDlg);
498 //------------------------------------------ Adjudication Options --------------------------------------
500 static Option adjudicationOptions[] = {
501 { 0, 0, 0, NULL, (void*) &appData.checkMates, "", NULL, CheckBox, N_("Detect all Mates") },
502 { 0, 0, 0, NULL, (void*) &appData.testClaims, "", NULL, CheckBox, N_("Verify Engine Result Claims") },
503 { 0, 0, 0, NULL, (void*) &appData.materialDraws, "", NULL, CheckBox, N_("Draw if Insufficient Mating Material") },
504 { 0, 0, 0, NULL, (void*) &appData.trivialDraws, "", NULL, CheckBox, N_("Adjudicate Trivial Draws (3-Move Delay)") },
505 { 0, 0, 100, NULL, (void*) &appData.ruleMoves, "", NULL, Spin, N_("N-Move Rule:") },
506 { 0, 0, 6, NULL, (void*) &appData.drawRepeats, "", NULL, Spin, N_("N-fold Repeats:") },
507 { 0, 0, 1000, NULL, (void*) &appData.adjudicateDrawMoves, "", NULL, Spin, N_("Draw after N Moves Total:") },
508 { 0,-5000, 0, NULL, (void*) &appData.adjudicateLossThreshold, "", NULL, Spin, N_("Win / Loss Threshold:") },
509 { 0, 0, 0, NULL, (void*) &first.scoreIsAbsolute, "", NULL, CheckBox, N_("Negate Score of Engine #1") },
510 { 0, 0, 0, NULL, (void*) &second.scoreIsAbsolute, "", NULL, CheckBox, N_("Negate Score of Engine #2") },
511 { 0, 1, 0, NULL, NULL, "", NULL, EndMark , "" }
517 GenericPopUp(adjudicationOptions, _("Adjudicate non-ICS Games"), TransientDlg);
520 //--------------------------------------------- ICS Options ---------------------------------------------
525 ParseIcsTextColors();
529 Option icsOptions[] = {
530 { 0, 0, 0, NULL, (void*) &appData.autoKibitz, "", NULL, CheckBox, N_("Auto-Kibitz") },
531 { 0, 0, 0, NULL, (void*) &appData.autoComment, "", NULL, CheckBox, N_("Auto-Comment") },
532 { 0, 0, 0, NULL, (void*) &appData.autoObserve, "", NULL, CheckBox, N_("Auto-Observe") },
533 { 0, 0, 0, NULL, (void*) &appData.autoRaiseBoard, "", NULL, CheckBox, N_("Auto-Raise Board") },
534 { 0, 0, 0, NULL, (void*) &appData.bgObserve, "", NULL, CheckBox, N_("Background Observe while Playing") },
535 { 0, 0, 0, NULL, (void*) &appData.dualBoard, "", NULL, CheckBox, N_("Dual Board for Background-Observed Game") },
536 { 0, 0, 0, NULL, (void*) &appData.getMoveList, "", NULL, CheckBox, N_("Get Move List") },
537 { 0, 0, 0, NULL, (void*) &appData.quietPlay, "", NULL, CheckBox, N_("Quiet Play") },
538 { 0, 0, 0, NULL, (void*) &appData.seekGraph, "", NULL, CheckBox, N_("Seek Graph") },
539 { 0, 0, 0, NULL, (void*) &appData.autoRefresh, "", NULL, CheckBox, N_("Auto-Refresh Seek Graph") },
540 { 0, 0, 0, NULL, (void*) &appData.premove, "", NULL, CheckBox, N_("Premove") },
541 { 0, 0, 0, NULL, (void*) &appData.premoveWhite, "", NULL, CheckBox, N_("Premove for White") },
542 { 0, 0, 0, NULL, (void*) &appData.premoveWhiteText, "", NULL, TextBox, N_("First White Move:") },
543 { 0, 0, 0, NULL, (void*) &appData.premoveBlack, "", NULL, CheckBox, N_("Premove for Black") },
544 { 0, 0, 0, NULL, (void*) &appData.premoveBlackText, "", NULL, TextBox, N_("First Black Move:") },
545 { 0, 0, 0, NULL, NULL, NULL, NULL, Break, "" },
546 { 0, 0, 0, NULL, (void*) &appData.icsAlarm, "", NULL, CheckBox, N_("Alarm") },
547 { 0, 0, 100000000, NULL, (void*) &appData.icsAlarmTime, "", NULL, Spin, N_("Alarm Time (msec):") },
548 //{ 0, 0, 0, NULL, (void*) &appData.chatBoxes, "", NULL, TextBox, N_("Startup Chat Boxes:") },
549 { 0, 0, 0, NULL, (void*) &appData.colorize, "", NULL, CheckBox, N_("Colorize Messages") },
550 { 0, 0, 0, NULL, (void*) &appData.colorShout, "", NULL, TextBox, N_("Shout Text Colors:") },
551 { 0, 0, 0, NULL, (void*) &appData.colorSShout, "", NULL, TextBox, N_("S-Shout Text Colors:") },
552 { 0, 0, 0, NULL, (void*) &appData.colorChannel1, "", NULL, TextBox, N_("Channel #1 Text Colors:") },
553 { 0, 0, 0, NULL, (void*) &appData.colorChannel, "", NULL, TextBox, N_("Other Channel Text Colors:") },
554 { 0, 0, 0, NULL, (void*) &appData.colorKibitz, "", NULL, TextBox, N_("Kibitz Text Colors:") },
555 { 0, 0, 0, NULL, (void*) &appData.colorTell, "", NULL, TextBox, N_("Tell Text Colors:") },
556 { 0, 0, 0, NULL, (void*) &appData.colorChallenge, "", NULL, TextBox, N_("Challenge Text Colors:") },
557 { 0, 0, 0, NULL, (void*) &appData.colorRequest, "", NULL, TextBox, N_("Request Text Colors:") },
558 { 0, 0, 0, NULL, (void*) &appData.colorSeek, "", NULL, TextBox, N_("Seek Text Colors:") },
559 { 0, 0, 0, NULL, (void*) &IcsOptionsOK, "", NULL, EndMark , "" }
565 GenericPopUp(icsOptions, _("ICS Options"), TransientDlg);
568 //-------------------------------------------- Load Game Options ---------------------------------
570 static char *modeNames[] = { N_("Exact position match"), N_("Shown position is subset"), N_("Same material with exactly same Pawn chain"),
571 N_("Same material"), N_("Material range (top board half optional)"), N_("Material difference (optional stuff balanced)"), NULL };
572 static char *modeValues[] = { "1", "2", "3", "4", "5", "6" };
573 static char *searchMode;
578 appData.searchMode = atoi(searchMode);
582 static Option loadOptions[] = {
583 { 0, 0, 0, NULL, (void*) &appData.autoDisplayTags, "", NULL, CheckBox, N_("Auto-Display Tags") },
584 { 0, 0, 0, NULL, (void*) &appData.autoDisplayComment, "", NULL, CheckBox, N_("Auto-Display Comment") },
585 { 0, 0, 0, NULL, NULL, NULL, NULL, Label, N_("Auto-Play speed of loaded games\n(0 = instant, -1 = off):") },
586 { 0, -1, 10000000, NULL, (void*) &appData.timeDelay, "", NULL, Fractional, N_("Seconds per Move:") },
587 { 0, 0, 0, NULL, NULL, NULL, NULL, Label, N_("\noptions to use in game-viewer mode:") },
588 { 0, 0, 300, NULL, (void*) &appData.viewerOptions, "", NULL, TextBox, "" },
589 { 0, 0, 0, NULL, NULL, NULL, NULL, Label, N_("\nThresholds for position filtering in game list:") },
590 { 0, 0, 5000, NULL, (void*) &appData.eloThreshold1, "", NULL, Spin, N_("Elo of strongest player at least:") },
591 { 0, 0, 5000, NULL, (void*) &appData.eloThreshold2, "", NULL, Spin, N_("Elo of weakest player at least:") },
592 { 0, 0, 5000, NULL, (void*) &appData.dateThreshold, "", NULL, Spin, N_("No games before year:") },
593 { 0, 1, 50, NULL, (void*) &appData.stretch, "", NULL, Spin, N_("Minimum nr consecutive positions:") },
594 { 1, 0, 180, NULL, (void*) &searchMode, (char*) modeNames, modeValues, ComboBox, N_("Search mode:") },
595 { 0, 0, 0, NULL, (void*) &appData.ignoreColors, "", NULL, CheckBox, N_("Also match reversed colors") },
596 { 0, 0, 0, NULL, (void*) &appData.findMirror, "", NULL, CheckBox, N_("Also match left-right flipped position") },
597 { 0, 0, 0, NULL, (void*) &LoadOptionsOK, "", NULL, EndMark , "" }
603 ASSIGN(searchMode, modeValues[appData.searchMode-1]);
604 GenericPopUp(loadOptions, _("Load Game Options"), TransientDlg);
607 //------------------------------------------- Save Game Options --------------------------------------------
609 static Option saveOptions[] = {
610 { 0, 0, 0, NULL, (void*) &appData.autoSaveGames, "", NULL, CheckBox, N_("Auto-Save Games") },
611 { 0, 0, 0, NULL, (void*) &appData.saveGameFile, ".pgn", NULL, FileName, N_("Save Games on File:") },
612 { 0, 0, 0, NULL, (void*) &appData.savePositionFile, ".fen", NULL, FileName, N_("Save Final Positions on File:") },
613 { 0, 0, 0, NULL, (void*) &appData.pgnEventHeader, "", NULL, TextBox, N_("PGN Event Header:") },
614 { 0, 0, 0, NULL, (void*) &appData.oldSaveStyle, "", NULL, CheckBox, N_("Old Save Style (as opposed to PGN)") },
615 { 0, 0, 0, NULL, (void*) &appData.numberTag, "", NULL, CheckBox, N_("Include Number Tag in tourney PGN") },
616 { 0, 0, 0, NULL, (void*) &appData.saveExtendedInfoInPGN, "", NULL, CheckBox, N_("Save Score/Depth Info in PGN") },
617 { 0, 0, 0, NULL, (void*) &appData.saveOutOfBookInfo, "", NULL, CheckBox, N_("Save Out-of-Book Info in PGN ") },
618 { 0, 1, 0, NULL, NULL, "", NULL, EndMark , "" }
624 GenericPopUp(saveOptions, _("Save Game Options"), TransientDlg);
627 //----------------------------------------------- Sound Options ---------------------------------------------
629 static void Test P((int n));
630 static char *trialSound;
632 static char *soundNames[] = {
635 N_("Above WAV File"),
650 static char *soundFiles[] = { // sound files corresponding to above names
653 NULL, // kludge alert: as first thing in the dialog readout this is replaced with the user-given .WAV filename
668 static Option soundOptions[] = {
669 { 0, 0, 0, NULL, (void*) &appData.soundProgram, "", NULL, TextBox, N_("Sound Program:") },
670 { 0, 0, 0, NULL, (void*) &appData.soundDirectory, "", NULL, PathName, N_("Sounds Directory:") },
671 { 0, 0, 0, NULL, (void*) (soundFiles+2) /* kludge! */, ".wav", NULL, FileName, N_("User WAV File:") },
672 { 0, 0, 0, NULL, (void*) &trialSound, (char*) soundNames, soundFiles, ComboBox, N_("Try-Out Sound:") },
673 { 0, 1, 0, NULL, (void*) &Test, NULL, NULL, Button, N_("Play") },
674 { 0, 0, 0, NULL, (void*) &appData.soundMove, (char*) soundNames, soundFiles, ComboBox, N_("Move:") },
675 { 0, 0, 0, NULL, (void*) &appData.soundIcsWin, (char*) soundNames, soundFiles, ComboBox, N_("Win:") },
676 { 0, 0, 0, NULL, (void*) &appData.soundIcsLoss, (char*) soundNames, soundFiles, ComboBox, N_("Lose:") },
677 { 0, 0, 0, NULL, (void*) &appData.soundIcsDraw, (char*) soundNames, soundFiles, ComboBox, N_("Draw:") },
678 { 0, 0, 0, NULL, (void*) &appData.soundIcsUnfinished, (char*) soundNames, soundFiles, ComboBox, N_("Unfinished:") },
679 { 0, 0, 0, NULL, (void*) &appData.soundIcsAlarm, (char*) soundNames, soundFiles, ComboBox, N_("Alarm:") },
680 { 0, 0, 0, NULL, (void*) &appData.soundShout, (char*) soundNames, soundFiles, ComboBox, N_("Shout:") },
681 { 0, 0, 0, NULL, (void*) &appData.soundSShout, (char*) soundNames, soundFiles, ComboBox, N_("S-Shout:") },
682 { 0, 0, 0, NULL, (void*) &appData.soundChannel, (char*) soundNames, soundFiles, ComboBox, N_("Channel:") },
683 { 0, 0, 0, NULL, (void*) &appData.soundChannel1, (char*) soundNames, soundFiles, ComboBox, N_("Channel 1:") },
684 { 0, 0, 0, NULL, (void*) &appData.soundTell, (char*) soundNames, soundFiles, ComboBox, N_("Tell:") },
685 { 0, 0, 0, NULL, (void*) &appData.soundKibitz, (char*) soundNames, soundFiles, ComboBox, N_("Kibitz:") },
686 { 0, 0, 0, NULL, (void*) &appData.soundChallenge, (char*) soundNames, soundFiles, ComboBox, N_("Challenge:") },
687 { 0, 0, 0, NULL, (void*) &appData.soundRequest, (char*) soundNames, soundFiles, ComboBox, N_("Request:") },
688 { 0, 0, 0, NULL, (void*) &appData.soundSeek, (char*) soundNames, soundFiles, ComboBox, N_("Seek:") },
689 { 0, 1, 0, NULL, NULL, "", NULL, EndMark , "" }
695 GenericReadout(soundOptions, 2);
696 if(soundFiles[values[3]]) PlaySound(soundFiles[values[3]]);
703 soundFiles[2] = strdup("*");
704 GenericPopUp(soundOptions, _("Sound Options"), TransientDlg);
707 //--------------------------------------------- Board Options --------------------------------------
709 static void DefColor P((int n));
710 static void AdjustColor P((int i));
713 BoardOptionsOK (int n)
715 if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap; else lineGap = defaultLineGap;
716 useImages = useImageSqs = 0;
718 InitDrawingSizes(-1, 0);
719 DrawPosition(True, NULL);
723 static Option boardOptions[] = {
724 { 0, 0, 70, NULL, (void*) &appData.whitePieceColor, "", NULL, TextBox, N_("White Piece Color:") },
725 { 1000, 1, 0, NULL, (void*) &DefColor, NULL, (char**) "#FFFFCC", Button, " " },
726 /* TRANSLATORS: R = single letter for the color red */
727 { 1, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, N_("R") },
728 /* TRANSLATORS: G = single letter for the color green */
729 { 2, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, N_("G") },
730 /* TRANSLATORS: B = single letter for the color blue */
731 { 3, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, N_("B") },
732 /* TRANSLATORS: D = single letter to make a color darker */
733 { 4, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, N_("D") },
734 { 0, 0, 70, NULL, (void*) &appData.blackPieceColor, "", NULL, TextBox, N_("Black Piece Color:") },
735 { 1000, 1, 0, NULL, (void*) &DefColor, NULL, (char**) "#202020", Button, " " },
736 { 1, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, N_("R") },
737 { 2, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, N_("G") },
738 { 3, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, N_("B") },
739 { 4, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, N_("D") },
740 { 0, 0, 70, NULL, (void*) &appData.lightSquareColor, "", NULL, TextBox, N_("Light Square Color:") },
741 { 1000, 1, 0, NULL, (void*) &DefColor, NULL, (char**) "#C8C365", Button, " " },
742 { 1, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, N_("R") },
743 { 2, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, N_("G") },
744 { 3, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, N_("B") },
745 { 4, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, N_("D") },
746 { 0, 0, 70, NULL, (void*) &appData.darkSquareColor, "", NULL, TextBox, N_("Dark Square Color:") },
747 { 1000, 1, 0, NULL, (void*) &DefColor, NULL, (char**) "#77A26D", Button, " " },
748 { 1, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, N_("R") },
749 { 2, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, N_("G") },
750 { 3, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, N_("B") },
751 { 4, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, N_("D") },
752 { 0, 0, 70, NULL, (void*) &appData.highlightSquareColor, "", NULL, TextBox, N_("Highlight Color:") },
753 { 1000, 1, 0, NULL, (void*) &DefColor, NULL, (char**) "#FFFF00", Button, " " },
754 { 1, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, N_("R") },
755 { 2, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, N_("G") },
756 { 3, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, N_("B") },
757 { 4, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, N_("D") },
758 { 0, 0, 70, NULL, (void*) &appData.premoveHighlightColor, "", NULL, TextBox, N_("Premove Highlight Color:") },
759 { 1000, 1, 0, NULL, (void*) &DefColor, NULL, (char**) "#FF0000", Button, " " },
760 { 1, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, N_("R") },
761 { 2, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, N_("G") },
762 { 3, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, N_("B") },
763 { 4, 1, 0, NULL, (void*) &AdjustColor, NULL, NULL, Button, N_("D") },
764 { 0, 0, 0, NULL, (void*) &appData.upsideDown, "", NULL, CheckBox, N_("Flip Pieces Shogi Style (Colored buttons restore default)") },
765 //{ 0, 0, 0, NULL, (void*) &appData.allWhite, "", NULL, CheckBox, N_("Use Outline Pieces for Black") },
766 { 0, 0, 0, NULL, (void*) &appData.monoMode, "", NULL, CheckBox, N_("Mono Mode") },
767 { 0,-1, 5, NULL, (void*) &appData.overrideLineGap, "", NULL, Spin, N_("Line Gap ( -1 = default for board size):") },
768 { 0, 0, 0, NULL, (void*) &appData.useBitmaps, "", NULL, CheckBox, N_("Use Board Textures") },
769 { 0, 0, 0, NULL, (void*) &appData.liteBackTextureFile, ".xpm", NULL, FileName, N_("Light-Squares Texture File:") },
770 { 0, 0, 0, NULL, (void*) &appData.darkBackTextureFile, ".xpm", NULL, FileName, N_("Dark-Squares Texture File:") },
771 { 0, 0, 0, NULL, (void*) &appData.bitmapDirectory, "", NULL, PathName, N_("Directory with Bitmap Pieces:") },
772 { 0, 0, 0, NULL, (void*) &appData.pixmapDirectory, "", NULL, PathName, N_("Directory with Pixmap Pieces:") },
773 { 0, 0, 0, NULL, (void*) &BoardOptionsOK, "", NULL, EndMark , "" }
777 SetColorText (int n, char *buf)
779 SetWidgetText(&boardOptions[n-1], buf, TransientDlg);
780 SetColor(buf, &boardOptions[n]);
786 SetColorText(n, (char*) boardOptions[n].choice);
790 RefreshColor (int source, int n)
792 int col, j, r, g, b, step = 10;
793 char *s, buf[MSG_SIZ]; // color string
794 GetWidgetText(&boardOptions[source], &s);
795 if(sscanf(s, "#%x", &col) != 1) return; // malformed
796 b = col & 0xFF; g = col & 0xFF00; r = col & 0xFF0000;
798 case 1: r += 0x10000*step;break;
799 case 2: g += 0x100*step; break;
800 case 3: b += step; break;
801 case 4: r -= 0x10000*step; g -= 0x100*step; b -= step; break;
803 if(r < 0) r = 0; if(g < 0) g = 0; if(b < 0) b = 0;
804 if(r > 0xFF0000) r = 0xFF0000; if(g > 0xFF00) g = 0xFF00; if(b > 0xFF) b = 0xFF;
806 snprintf(buf, MSG_SIZ, "#%06x", col);
807 for(j=1; j<7; j++) if(buf[j] >= 'a') buf[j] -= 32; // capitalize
808 SetColorText(source+1, buf);
814 int n = boardOptions[i].value;
815 RefreshColor(i-n-1, n);
821 GenericPopUp(boardOptions, _("Board Options"), TransientDlg);
824 //-------------------------------------------- ICS Text Menu Options ------------------------------
826 Option textOptions[100];
827 static void PutText P((char *text, int pos));
832 char buf[MSG_SIZ], *q;
833 if(q = strstr(p, "$input")) {
834 if(!shellUp[TextMenuDlg]) return;
835 strncpy(buf, p, MSG_SIZ);
836 strncpy(buf + (q-p), q+6, MSG_SIZ-(q-p));
840 snprintf(buf, MSG_SIZ, "%s\n", p);
849 if((p = icsTextMenuString) == NULL) return;
851 q = r = p; while(*p && *p != ';') p++;
852 for(j=0; j<p-q; j++) textOptions[i].name[j] = *r++;
853 textOptions[i].name[j++] = 0;
855 if(*++p == '\n') p++; // optional linefeed after button-text terminating semicolon
857 textOptions[i].choice = (char**) (r = textOptions[i].name + j);
858 while(*p && (*p != ';' || p[1] != '\n')) textOptions[i].name[j++] = *p++;
859 textOptions[i].name[j++] = 0;
861 textOptions[i].max = 135;
862 textOptions[i].min = i&1;
863 textOptions[i].handle = NULL;
864 textOptions[i].target = &SendText;
865 textOptions[i].textValue = strstr(r, "$input") ? "#80FF80" : strstr(r, "$name") ? "#FF8080" : "#FFFFFF";
866 textOptions[i].type = Button;
867 } while(++i < 99 && *p);
869 textOptions[i].type = EndMark;
870 textOptions[i].target = NULL;
871 textOptions[i].min = 2;
872 MarkMenu("ICStex", TextMenuDlg);
873 GenericPopUp(textOptions, _("ICS text menu"), TextMenuDlg);
876 //---------------------------------------------------- Edit Comment -----------------------------------
878 static char *commentText;
879 static int commentIndex;
880 static void ClearComment P((int n));
881 static void SaveChanges P((int n));
884 NewComCallback (int n)
886 ReplaceComment(commentIndex, commentText);
890 Option commentOptions[] = {
891 { 0xD, 200, 250, NULL, (void*) &commentText, "", NULL, TextBox, "" },
892 { 0, 0, 50, NULL, (void*) &ClearComment, NULL, NULL, Button, N_("clear") },
893 { 0, 1, 100, NULL, (void*) &SaveChanges, NULL, NULL, Button, N_("save changes") },
894 { 0, 1, 0, NULL, (void*) &NewComCallback, "", NULL, EndMark , "" }
900 GenericReadout(commentOptions, 0);
901 ReplaceComment(commentIndex, commentText);
907 SetWidgetText(&commentOptions[0], "", CommentDlg);
911 NewCommentPopup (char *title, char *text, int index)
913 if(DialogExists(CommentDlg)) { // if already exists, alter title and content
914 SetDialogTitle(CommentDlg, title);
915 SetWidgetText(&commentOptions[0], text, CommentDlg);
917 if(commentText) free(commentText); commentText = strdup(text);
918 commentIndex = index;
919 MarkMenu("Show Comments", CommentDlg);
920 if(GenericPopUp(commentOptions, title, CommentDlg))
921 AddHandler(&commentOptions[0], 1);
928 if (PopDown(CommentDlg)) { // popdown succesful
929 MarkMenuItem("Edit Comment", False);
930 MarkMenuItem("Show Comments", False);
935 //------------------------------------------------------ Edit Tags ----------------------------------
937 static void changeTags P((int n));
938 static char *tagsText;
941 NewTagsCallback (int n)
943 ReplaceTags(tagsText, &gameInfo);
947 static Option tagsOptions[] = {
948 { 0, 0, 0, NULL, NULL, NULL, NULL, Label, "" },
949 { 0xD, 200, 200, NULL, (void*) &tagsText, "", NULL, TextBox, "" },
950 { 0, 0, 100, NULL, (void*) &changeTags, NULL, NULL, Button, N_("save changes") },
951 { 0, 1, 0, NULL, (void*) &NewTagsCallback, "", NULL, EndMark , "" }
957 GenericReadout(tagsOptions, 1);
958 if(bookUp) SaveToBook(tagsText); else
959 ReplaceTags(tagsText, &gameInfo);
963 NewTagsPopup (char *text, char *msg)
965 char *title = bookUp ? _("Edit book") : _("Tags");
967 if(DialogExists(TagsDlg)) { // if already exists, alter title and content
968 SetWidgetText(&tagsOptions[1], text, TagsDlg);
969 SetDialogTitle(TagsDlg, title);
971 if(tagsText) free(tagsText); tagsText = strdup(text);
972 tagsOptions[0].textValue = msg;
973 MarkMenu("Show Tags", TagsDlg);
974 GenericPopUp(tagsOptions, title, TagsDlg);
977 //---------------------------------------------- ICS Input Box ----------------------------------
981 // [HGM] code borrowed from winboard.c (which should thus go to backend.c!)
982 #define HISTORY_SIZE 64
983 static char *history[HISTORY_SIZE];
984 static int histIn = 0, histP = 0;
987 SaveInHistory (char *cmd)
989 if (history[histIn] != NULL) {
990 free(history[histIn]);
991 history[histIn] = NULL;
993 if (*cmd == NULLCHAR) return;
994 history[histIn] = StrSave(cmd);
995 histIn = (histIn + 1) % HISTORY_SIZE;
996 if (history[histIn] != NULL) {
997 free(history[histIn]);
998 history[histIn] = NULL;
1004 PrevInHistory (char *cmd)
1007 if (histP == histIn) {
1008 if (history[histIn] != NULL) free(history[histIn]);
1009 history[histIn] = StrSave(cmd);
1011 newhp = (histP - 1 + HISTORY_SIZE) % HISTORY_SIZE;
1012 if (newhp == histIn || history[newhp] == NULL) return NULL;
1014 return history[histP];
1020 if (histP == histIn) return NULL;
1021 histP = (histP + 1) % HISTORY_SIZE;
1022 return history[histP];
1024 // end of borrowed code
1031 GetWidgetText(&boxOptions[0], &val);
1033 SendMultiLineToICS(val);
1034 SetWidgetText(&boxOptions[0], val, InputBoxDlg);
1039 { // [HGM] input: let up-arrow recall previous line from history
1042 if (!shellUp[InputBoxDlg]) return;
1048 GetWidgetText(&boxOptions[0], &val);
1049 val = PrevInHistory(val);
1052 val = NextInHistory();
1054 SetWidgetText(&boxOptions[0], val ? val : "", InputBoxDlg);
1057 Option boxOptions[] = {
1058 { 0, 30, 400, NULL, (void*) &icsText, "", NULL, TextBox, "" },
1059 { 0, 3, 0, NULL, NULL, "", NULL, EndMark , "" }
1063 PutText (char *text, int pos)
1065 char buf[MSG_SIZ], *p;
1067 if(strstr(text, "$add ") == text) {
1068 GetWidgetText(&boxOptions[0], &p);
1069 snprintf(buf, MSG_SIZ, "%s%s", p, text+5); text = buf;
1070 pos += strlen(p) - 5;
1072 SetWidgetText(&boxOptions[0], text, TextMenuDlg);
1073 SetInsertPos(&boxOptions[0], pos);
1079 MarkMenu("ICS Input Box", InputBoxDlg);
1080 if(GenericPopUp(boxOptions, _("ICS input box"), InputBoxDlg))
1081 AddHandler(&boxOptions[0], 3);
1087 if (!PopDown(InputBoxDlg)) ICSInputBoxPopUp();
1090 //--------------------------------------------- Move Type In ------------------------------------------
1093 PopUpMoveDialog (char firstchar)
1096 buf[0] = firstchar; icsText = buf;
1097 if(GenericPopUp(boxOptions, _("Type a move"), TransientDlg))
1098 AddHandler(&boxOptions[0], 2);
1102 BoxAutoPopUp (char *buf)
1104 if(appData.icsActive) { // text typed to board in ICS mode: divert to ICS input box
1105 if(DialogExists(InputBoxDlg)) { // box already exists: append to current contents
1106 char *p, newText[MSG_SIZ];
1107 GetWidgetText(&boxOptions[0], &p);
1108 snprintf(newText, MSG_SIZ, "%s%c", p, *buf);
1109 SetWidgetText(&boxOptions[0], newText, InputBoxDlg);
1110 if(shellUp[InputBoxDlg]) HardSetFocus (&boxOptions[0]); //why???
1111 } else icsText = buf; // box did not exist: make sure it pops up with char in it
1113 } else PopUpMoveDialog(*buf);
1116 //------------------------------------------ Engine Settings ------------------------------------
1119 SettingsPopUp (ChessProgramState *cps)
1122 GenericPopUp(cps->option, _("Engine Settings"), TransientDlg);
1126 FirstSettingsProc ()
1128 SettingsPopUp(&first);
1132 SecondSettingsProc ()
1134 if(WaitForEngine(&second, SettingsMenuIfReady)) return;
1135 SettingsPopUp(&second);
1138 //----------------------------------------------- Load Engine --------------------------------------
1140 char *engineDir, *engineLine, *nickName, *params;
1141 Boolean isUCI, hasBook, storeVariant, v1, addToList, useNick;
1142 static char *engineNr[] = { N_("First Engine"), N_("Second Engine"), NULL };
1147 PopDown(TransientDlg); // early popdown, to allow FreezeUI to instate grab
1148 if(engineChoice[0] == engineNr[0][0]) Load(&first, 0); else Load(&second, 1);
1152 static Option installOptions[] = {
1153 { 0, NO_GETTEXT, 0, NULL, (void*) &engineLine, (char*) engineMnemonic, engineList, ComboBox, N_("Select engine from list:") },
1154 { 0, 0, 0, NULL, NULL, NULL, NULL, Label, N_("or specify one below:") },
1155 { 0, 0, 0, NULL, (void*) &nickName, NULL, NULL, TextBox, N_("Nickname (optional):") },
1156 { 0, 0, 0, NULL, (void*) &useNick, NULL, NULL, CheckBox, N_("Use nickname in PGN player tags of engine-engine games") },
1157 { 0, 0, 0, NULL, (void*) &engineDir, NULL, NULL, PathName, N_("Engine Directory:") },
1158 { 0, 0, 0, NULL, (void*) &engineName, NULL, NULL, FileName, N_("Engine Command:") },
1159 { 0, 0, 0, NULL, NULL, NULL, NULL, Label, N_("(Directory will be derived from engine path when empty)") },
1160 { 0, 0, 0, NULL, (void*) &isUCI, NULL, NULL, CheckBox, N_("UCI") },
1161 { 0, 0, 0, NULL, (void*) &v1, NULL, NULL, CheckBox, N_("WB protocol v1 (do not wait for engine features)") },
1162 { 0, 0, 0, NULL, (void*) &hasBook, NULL, NULL, CheckBox, N_("Must not use GUI book") },
1163 { 0, 0, 0, NULL, (void*) &addToList, NULL, NULL, CheckBox, N_("Add this engine to the list") },
1164 { 0, 0, 0, NULL, (void*) &storeVariant, NULL, NULL, CheckBox, N_("Force current variant with this engine") },
1165 { 0, 0, 0, NULL, (void*) &engineChoice, (char*) engineNr, engineNr, ComboBox, N_("Load mentioned engine as") },
1166 { 0, 1, 0, NULL, (void*) &InstallOK, "", NULL, EndMark , "" }
1172 isUCI = storeVariant = v1 = useNick = False; addToList = hasBook = True; // defaults
1173 if(engineChoice) free(engineChoice); engineChoice = strdup(engineNr[0]);
1174 if(engineLine) free(engineLine); engineLine = strdup("");
1175 if(engineDir) free(engineDir); engineDir = strdup("");
1176 if(nickName) free(nickName); nickName = strdup("");
1177 if(params) free(params); params = strdup("");
1178 NamesToList(firstChessProgramNames, engineList, engineMnemonic, "all");
1179 GenericPopUp(installOptions, _("Load engine"), TransientDlg);
1182 //----------------------------------------------------- Edit Book -----------------------------------------
1190 //--------------------------------------------------- New Shuffle Game ------------------------------
1192 static void SetRandom P((int n));
1201 static Option shuffleOptions[] = {
1202 { 0, 0, 50, NULL, (void*) &shuffleOpenings, NULL, NULL, CheckBox, N_("shuffle") },
1203 { 0,-1,2000000000, NULL, (void*) &appData.defaultFrcPosition, "", NULL, Spin, N_("Start-position number:") },
1204 { 0, 0, 0, NULL, (void*) &SetRandom, NULL, NULL, Button, N_("randomize") },
1205 { 0, 1, 0, NULL, (void*) &SetRandom, NULL, NULL, Button, N_("pick fixed") },
1206 { 0, 1, 0, NULL, (void*) &ShuffleOK, "", NULL, EndMark , "" }
1212 int r = n==2 ? -1 : random() & (1<<30)-1;
1214 snprintf(buf, MSG_SIZ, "%d", r);
1215 SetWidgetText(&shuffleOptions[1], buf, TransientDlg);
1216 SetWidgetState(&shuffleOptions[0], True);
1222 GenericPopUp(shuffleOptions, _("New Shuffle Game"), TransientDlg);
1225 //------------------------------------------------------ Time Control -----------------------------------
1227 static int TcOK P((int n));
1228 int tmpMoves, tmpTc, tmpInc, tmpOdds1, tmpOdds2, tcType;
1235 static void SetTcType P((int n));
1240 static char buf[MSG_SIZ];
1241 snprintf(buf, MSG_SIZ, "%d", n);
1245 static Option tcOptions[] = {
1246 { 0, 0, 0, NULL, (void*) &SetTcType, NULL, NULL, Button, N_("classical") },
1247 { 0, 1, 0, NULL, (void*) &SetTcType, NULL, NULL, Button, N_("incremental") },
1248 { 0, 1, 0, NULL, (void*) &SetTcType, NULL, NULL, Button, N_("fixed max") },
1249 { 0, 0, 200, NULL, (void*) &tmpMoves, NULL, NULL, Spin, N_("Moves per session:") },
1250 { 0, 0,10000, NULL, (void*) &tmpTc, NULL, NULL, Spin, N_("Initial time (min):") },
1251 { 0, 0, 10000, NULL, (void*) &tmpInc, NULL, NULL, Spin, N_("Increment or max (sec/move):") },
1252 { 0, 0, 0, NULL, NULL, NULL, NULL, Label, N_("Time-Odds factors:") },
1253 { 0, 1, 1000, NULL, (void*) &tmpOdds1, NULL, NULL, Spin, N_("Engine #1") },
1254 { 0, 1, 1000, NULL, (void*) &tmpOdds2, NULL, NULL, Spin, N_("Engine #2 / Human") },
1255 { 0, 0, 0, NULL, (void*) &TcOK, "", NULL, EndMark , "" }
1262 if(tcType == 0 && tmpMoves <= 0) return 0;
1263 if(tcType == 2 && tmpInc <= 0) return 0;
1264 GetWidgetText(&tcOptions[4], &tc); // get original text, in case it is min:sec
1268 if(!ParseTimeControl(tc, -1, tmpMoves)) return 0;
1269 appData.movesPerSession = tmpMoves;
1270 ASSIGN(appData.timeControl, tc);
1271 appData.timeIncrement = -1;
1274 if(!ParseTimeControl(tc, tmpInc, 0)) return 0;
1275 ASSIGN(appData.timeControl, tc);
1276 appData.timeIncrement = tmpInc;
1279 searchTime = tmpInc;
1281 appData.firstTimeOdds = first.timeOdds = tmpOdds1;
1282 appData.secondTimeOdds = second.timeOdds = tmpOdds2;
1290 switch(tcType = n) {
1292 SetWidgetText(&tcOptions[3], Value(tmpMoves), TransientDlg);
1293 SetWidgetText(&tcOptions[4], Value(tmpTc), TransientDlg);
1294 SetWidgetText(&tcOptions[5], _("Unused"), TransientDlg);
1297 SetWidgetText(&tcOptions[3], _("Unused"), TransientDlg);
1298 SetWidgetText(&tcOptions[4], Value(tmpTc), TransientDlg);
1299 SetWidgetText(&tcOptions[5], Value(tmpInc), TransientDlg);
1302 SetWidgetText(&tcOptions[3], _("Unused"), TransientDlg);
1303 SetWidgetText(&tcOptions[4], _("Unused"), TransientDlg);
1304 SetWidgetText(&tcOptions[5], Value(tmpInc), TransientDlg);
1311 tmpMoves = appData.movesPerSession;
1312 tmpInc = appData.timeIncrement; if(tmpInc < 0) tmpInc = 0;
1313 tmpOdds1 = tmpOdds2 = 1; tcType = 0;
1314 tmpTc = atoi(appData.timeControl);
1315 GenericPopUp(tcOptions, _("Time Control"), TransientDlg);
1318 //---------------------------- Chat Windows ----------------------------------------------
1321 OutputChatMessage (int partner, char *mess)
1326 //----------------------------- Various display boxes -----------------------------
1329 DisplayError (String message, int error)
1334 if (appData.debugMode || appData.matchMode) {
1335 fprintf(stderr, "%s: %s\n", programName, message);
1338 if (appData.debugMode || appData.matchMode) {
1339 fprintf(stderr, "%s: %s: %s\n",
1340 programName, message, strerror(error));
1342 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
1345 ErrorPopUp(_("Error"), message, FALSE);
1350 DisplayMoveError (String message)
1354 DrawPosition(FALSE, NULL);
1355 if (appData.debugMode || appData.matchMode) {
1356 fprintf(stderr, "%s: %s\n", programName, message);
1358 if (appData.popupMoveErrors) {
1359 ErrorPopUp(_("Error"), message, FALSE);
1361 DisplayMessage(message, "");
1367 DisplayFatalError (String message, int error, int status)
1371 errorExitStatus = status;
1373 fprintf(stderr, "%s: %s\n", programName, message);
1375 fprintf(stderr, "%s: %s: %s\n",
1376 programName, message, strerror(error));
1377 snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
1380 if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
1381 ErrorPopUp(status ? _("Fatal Error") : _("Exiting"), message, TRUE);
1388 DisplayInformation (String message)
1391 ErrorPopUp(_("Information"), message, TRUE);
1395 DisplayNote (String message)
1398 ErrorPopUp(_("Note"), message, FALSE);
1402 DisplayTitle (char *text)
1404 char title[MSG_SIZ];
1407 if (text == NULL) text = "";
1409 if (*text != NULLCHAR) {
1410 safeStrCpy(icon, text, sizeof(icon)/sizeof(icon[0]) );
1411 safeStrCpy(title, text, sizeof(title)/sizeof(title[0]) );
1412 } else if (appData.icsActive) {
1413 snprintf(icon, sizeof(icon), "%s", appData.icsHost);
1414 snprintf(title, sizeof(title), "%s: %s", programName, appData.icsHost);
1415 } else if (appData.cmailGameName[0] != NULLCHAR) {
1416 snprintf(icon, sizeof(icon), "%s", "CMail");
1417 snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
1419 // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
1420 } else if (gameInfo.variant == VariantGothic) {
1421 safeStrCpy(icon, programName, sizeof(icon)/sizeof(icon[0]) );
1422 safeStrCpy(title, GOTHIC, sizeof(title)/sizeof(title[0]) );
1425 } else if (gameInfo.variant == VariantFalcon) {
1426 safeStrCpy(icon, programName, sizeof(icon)/sizeof(icon[0]) );
1427 safeStrCpy(title, FALCON, sizeof(title)/sizeof(title[0]) );
1429 } else if (appData.noChessProgram) {
1430 safeStrCpy(icon, programName, sizeof(icon)/sizeof(icon[0]) );
1431 safeStrCpy(title, programName, sizeof(title)/sizeof(title[0]) );
1433 safeStrCpy(icon, first.tidy, sizeof(icon)/sizeof(icon[0]) );
1434 snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
1436 SetWindowTitle(text, title, icon);