1 /*
2 * menus.c -- platform-indendent menu handling code for XBoard
3 *
4 * Copyright 1991 by Digital Equipment Corporation, Maynard,
5 * Massachusetts.
6 *
7 * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
8 * 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Free Software Foundation, Inc.
9 *
10 * The following terms apply to Digital Equipment Corporation's copyright
11 * interest in XBoard:
12 * ------------------------------------------------------------------------
13 * All Rights Reserved
14 *
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose and without fee is hereby granted,
17 * provided that the above copyright notice appear in all copies and that
18 * both that copyright notice and this permission notice appear in
19 * supporting documentation, and that the name of Digital not be
20 * used in advertising or publicity pertaining to distribution of the
21 * software without specific, written prior permission.
22 *
23 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
29 * SOFTWARE.
30 * ------------------------------------------------------------------------
31 *
32 * The following terms apply to the enhanced version of XBoard
33 * distributed by the Free Software Foundation:
34 * ------------------------------------------------------------------------
35 *
36 * GNU XBoard is free software: you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
38 * the Free Software Foundation, either version 3 of the License, or (at
39 * your option) any later version.
40 *
41 * GNU XBoard is distributed in the hope that it will be useful, but
42 * WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44 * General Public License for more details.
45 *
46 * You should have received a copy of the GNU General Public License
47 * along with this program. If not, see http://www.gnu.org/licenses/. *
48 *
49 *------------------------------------------------------------------------
50 ** See the file ChangeLog for a revision history. */
51
52 #define HIGHDRAG 1
53
54 #include "config.h"
55
56 #include <stdio.h>
57 #include <ctype.h>
58 #include <signal.h>
59 #include <errno.h>
60 #include <sys/types.h>
61 #include <sys/stat.h>
62 #include <pwd.h>
63 #include <math.h>
64
65 #if STDC_HEADERS
66 # include <stdlib.h>
67 # include <string.h>
68 #else /* not STDC_HEADERS */
69 extern char *getenv();
70 # if HAVE_STRING_H
71 # include <string.h>
72 # else /* not HAVE_STRING_H */
73 # include <strings.h>
74 # endif /* not HAVE_STRING_H */
75 #endif /* not STDC_HEADERS */
76
77 #if HAVE_UNISTD_H
78 # include <unistd.h>
79 #endif
80
81 #if ENABLE_NLS
82 #include <locale.h>
83 #endif
84
85 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
86 #include "common.h"
87
88 #include "frontend.h"
89 #include "backend.h"
90 #include "menus.h"
91 #include "gettext.h"
92
93 #ifdef ENABLE_NLS
94 # define _(s) gettext (s)
95 # define N_(s) gettext_noop (s)
96 #else
97 # define _(s) (s)
98 # define N_(s) s
99 #endif
100
101 /*
102 * Button/menu procedures
103 */
104
105 char *gameCopyFilename, *gamePasteFilename;
106 Boolean saveSettingsOnExit;
107 char *settingsFileName;
108 char gamesDir[MSG_SIZ], positionsDir[MSG_SIZ], textureDir[MSG_SIZ], bookDir[MSG_SIZ], piecesDir[MSG_SIZ];
109
110 static int
LoadGamePopUp(FILE * f,int gameNumber,char * title)111 LoadGamePopUp (FILE *f, int gameNumber, char *title)
112 {
113 cmailMsgLoaded = FALSE;
114 if (gameNumber == 0) {
115 int error = GameListBuild(f);
116 if (error) {
117 DisplayError(_("Cannot build game list"), error);
118 } else if (!ListEmpty(&gameList) &&
119 ((ListGame *) gameList.tailPred)->number > 1) {
120 GameListPopUp(f, title);
121 return TRUE;
122 }
123 GameListDestroy();
124 gameNumber = 1;
125 }
126 return LoadGame(f, gameNumber, title, FALSE);
127 }
128
129 void
LoadGameProc()130 LoadGameProc ()
131 {
132 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
133 Reset(FALSE, TRUE);
134 }
135 FileNamePopUp(_("Load game file name?"), "", ".pgn .game", LoadGamePopUp, "rb");
136 }
137
138 void
LoadNextGameProc()139 LoadNextGameProc ()
140 {
141 ReloadGame(1);
142 }
143
144 void
LoadPrevGameProc()145 LoadPrevGameProc ()
146 {
147 ReloadGame(-1);
148 }
149
150 void
ReloadGameProc()151 ReloadGameProc ()
152 {
153 ReloadGame(0);
154 }
155
156 void
LoadNextPositionProc()157 LoadNextPositionProc ()
158 {
159 ReloadPosition(1);
160 }
161
162 void
LoadPrevPositionProc()163 LoadPrevPositionProc ()
164 {
165 ReloadPosition(-1);
166 }
167
168 void
ReloadPositionProc()169 ReloadPositionProc ()
170 {
171 ReloadPosition(0);
172 }
173
174 void
LoadPositionProc()175 LoadPositionProc()
176 {
177 static char buf[MSG_SIZ];
178 if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
179 Reset(FALSE, TRUE);
180 }
181 snprintf(buf, MSG_SIZ, "%s/", appData.positionDir);
182 FileNamePopUp(_("Load position file name?"), buf, ".fen .epd .pos", LoadPosition, "rb");
183 }
184
185 void
SaveGameProc()186 SaveGameProc ()
187 {
188 FileNamePopUp(_("Save game file name?"),
189 DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
190 appData.oldSaveStyle ? ".game" : ".pgn",
191 SaveGame, "a");
192 }
193
194 void
SavePositionProc()195 SavePositionProc ()
196 {
197 FileNamePopUp(_("Save position file name?"),
198 DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
199 appData.oldSaveStyle ? ".pos" : ".fen",
200 SavePosition, "a");
201 }
202
203 void
ReloadCmailMsgProc()204 ReloadCmailMsgProc ()
205 {
206 ReloadCmailMsgEvent(FALSE);
207 }
208
209 void
CopyFENToClipboard()210 CopyFENToClipboard ()
211 { // wrapper to make call from back-end possible
212 CopyPositionProc();
213 }
214
215 void
CopyPositionProc()216 CopyPositionProc ()
217 {
218 static char *selected_fen_position=NULL;
219 if(gameMode == EditPosition) EditPositionDone(TRUE);
220 if (selected_fen_position) free(selected_fen_position);
221 selected_fen_position = (char *)PositionToFEN(currentMove, NULL, 1);
222 if (!selected_fen_position) return;
223 CopySomething(selected_fen_position);
224 }
225
226 void
CopyGameProc()227 CopyGameProc ()
228 {
229 int ret;
230
231 ret = SaveGameToFile(gameCopyFilename, FALSE);
232 if (!ret) return;
233
234 CopySomething(NULL);
235 }
236
237 void
CopyGameListProc()238 CopyGameListProc ()
239 {
240 if(!SaveGameListAsText(fopen(gameCopyFilename, "w"))) return;
241 CopySomething(NULL);
242 }
243
244 void
AutoSaveGame()245 AutoSaveGame ()
246 {
247 SaveGameProc();
248 }
249
250
251 void
QuitProc()252 QuitProc ()
253 {
254 ExitEvent(0);
255 }
256
257 void
MatchProc()258 MatchProc ()
259 {
260 static Enables matchOff[] = { { "Mode.MachineMatch", False }, { NULL, False } };
261 if(matchMode) SetMenuEnables(matchOff);
262 MatchEvent(2);
263 }
264
265 void
AdjuWhiteProc()266 AdjuWhiteProc ()
267 {
268 UserAdjudicationEvent(+1);
269 }
270
271 void
AdjuBlackProc()272 AdjuBlackProc ()
273 {
274 UserAdjudicationEvent(-1);
275 }
276
277 void
AdjuDrawProc()278 AdjuDrawProc ()
279 {
280 UserAdjudicationEvent(0);
281 }
282
283 void
RevertProc()284 RevertProc ()
285 {
286 RevertEvent(False);
287 }
288
289 void
AnnotateProc()290 AnnotateProc ()
291 {
292 RevertEvent(True);
293 }
294
295 void
FlipViewProc()296 FlipViewProc ()
297 {
298 if(twoBoards) { partnerUp = 1; DrawPosition(True, NULL); partnerUp = 0; }
299 flipView = !flipView;
300 DrawPosition(True, NULL);
301 }
302
303 void
SaveOnExitProc()304 SaveOnExitProc ()
305 {
306 saveSettingsOnExit = !saveSettingsOnExit;
307
308 MarkMenuItem("Options.SaveSettingsonExit", saveSettingsOnExit);
309 }
310
311 void
SaveSettingsProc()312 SaveSettingsProc ()
313 {
314 SaveSettings(settingsFileName);
315 }
316
317 void
BugReportProc()318 BugReportProc ()
319 {
320 char buf[MSG_SIZ];
321 snprintf(buf, MSG_SIZ, "%s mailto:bug-xboard@gnu.org", appData.sysOpen);
322 system(buf);
323 }
324
325 void
GuideProc()326 GuideProc ()
327 {
328 char buf[MSG_SIZ];
329 snprintf(buf, MSG_SIZ, "%s http://www.gnu.org/software/xboard/user_guide/UserGuide.html", appData.sysOpen);
330 system(buf);
331 }
332
333 void
HomePageProc()334 HomePageProc ()
335 {
336 char buf[MSG_SIZ];
337 snprintf(buf, MSG_SIZ, "%s http://www.gnu.org/software/xboard/", appData.sysOpen);
338 system(buf);
339 }
340
341 void
NewsPageProc()342 NewsPageProc ()
343 {
344 char buf[MSG_SIZ];
345 snprintf(buf, MSG_SIZ, "%s http://www.gnu.org/software/xboard/whats_new/portal.html", appData.sysOpen);
346 system(buf);
347 }
348
349 void
AboutProc()350 AboutProc ()
351 {
352 char buf[2 * MSG_SIZ];
353 #if ZIPPY
354 char *zippy = _(" (with Zippy code)");
355 #else
356 char *zippy = "";
357 #endif
358 snprintf(buf, sizeof(buf),
359 _("%s%s\n\n"
360 "Copyright 1991 Digital Equipment Corporation\n"
361 "Enhancements Copyright 1992-2015 Free Software Foundation\n"
362 "Enhancements Copyright 2005 Alessandro Scotti\n\n"
363 "%s is free software and carries NO WARRANTY;"
364 "see the file COPYING for more information.\n"
365 "The GTK build of this version is experimental and unstable\n\n"
366 "Visit XBoard on the web at: http://www.gnu.org/software/xboard/\n"
367 "Check out the newest features at: http://www.gnu.org/software/xboard/whats_new.html\n\n"
368 "Report bugs via email at: <bug-xboard@gnu.org>\n\n"
369 ),
370 programVersion, zippy, PACKAGE);
371 ErrorPopUp(_("About XBoard"), buf, FALSE);
372 }
373
374 void
DebugProc()375 DebugProc ()
376 {
377 appData.debugMode = !appData.debugMode;
378 if(!strcmp(appData.nameOfDebugFile, "stderr")) return; // stderr is already open, and should never be closed
379 if(!appData.debugMode) fclose(debugFP);
380 else {
381 debugFP = fopen(appData.nameOfDebugFile, "w");
382 if(debugFP == NULL) debugFP = stderr;
383 else setbuf(debugFP, NULL);
384 }
385 }
386
387 void
EditEngineProc()388 EditEngineProc ()
389 {
390 EditTagsPopUp(firstChessProgramNames, &firstChessProgramNames);
391 }
392
393 void
NothingProc()394 NothingProc ()
395 {
396 return;
397 }
398
399 #ifdef OPTIONSDIALOG
400 # define MARK_MENU_ITEM(X,Y)
401 #else
402 # define MARK_MENU_ITEM(X,Y) MarkMenuItem(X, Y)
403 #endif
404
405 void
PonderNextMoveProc()406 PonderNextMoveProc ()
407 {
408 PonderNextMoveEvent(!appData.ponderNextMove);
409 MARK_MENU_ITEM("Options.PonderNextMove", appData.ponderNextMove);
410 }
411
412 void
AlwaysQueenProc()413 AlwaysQueenProc ()
414 {
415 appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
416 MARK_MENU_ITEM("Options.AlwaysQueen", appData.alwaysPromoteToQueen);
417 }
418
419 void
AnimateDraggingProc()420 AnimateDraggingProc ()
421 {
422 appData.animateDragging = !appData.animateDragging;
423
424 if (appData.animateDragging) CreateAnimVars();
425 MARK_MENU_ITEM("Options.AnimateDragging", appData.animateDragging);
426 }
427
428 void
AnimateMovingProc()429 AnimateMovingProc ()
430 {
431 appData.animate = !appData.animate;
432 if (appData.animate) CreateAnimVars();
433 MARK_MENU_ITEM("Options.AnimateMoving", appData.animate);
434 }
435
436 void
AutoflagProc()437 AutoflagProc ()
438 {
439 appData.autoCallFlag = !appData.autoCallFlag;
440 MARK_MENU_ITEM("Options.AutoFlag", appData.autoCallFlag);
441 }
442
443 void
AutoflipProc()444 AutoflipProc ()
445 {
446 appData.autoFlipView = !appData.autoFlipView;
447 MARK_MENU_ITEM("Options.AutoFlipView", appData.autoFlipView);
448 }
449
450 void
BlindfoldProc()451 BlindfoldProc ()
452 {
453 appData.blindfold = !appData.blindfold;
454 MARK_MENU_ITEM("Options.Blindfold", appData.blindfold);
455 DrawPosition(True, NULL);
456 }
457
458 void
TestLegalityProc()459 TestLegalityProc ()
460 {
461 appData.testLegality = !appData.testLegality;
462 MARK_MENU_ITEM("Options.TestLegality", appData.testLegality);
463 }
464
465
466 void
FlashMovesProc()467 FlashMovesProc ()
468 {
469 if (appData.flashCount == 0) {
470 appData.flashCount = 3;
471 } else {
472 appData.flashCount = -appData.flashCount;
473 }
474 MARK_MENU_ITEM("Options.FlashMoves", appData.flashCount > 0);
475 }
476
477 #if HIGHDRAG
478 void
HighlightDraggingProc()479 HighlightDraggingProc ()
480 {
481 appData.highlightDragging = !appData.highlightDragging;
482 MARK_MENU_ITEM("Options.HighlightDragging", appData.highlightDragging);
483 }
484 #endif
485
486 void
HighlightLastMoveProc()487 HighlightLastMoveProc ()
488 {
489 appData.highlightLastMove = !appData.highlightLastMove;
490 MARK_MENU_ITEM("Options.HighlightLastMove", appData.highlightLastMove);
491 }
492
493 void
HighlightArrowProc()494 HighlightArrowProc ()
495 {
496 appData.highlightMoveWithArrow = !appData.highlightMoveWithArrow;
497 MARK_MENU_ITEM("Options.HighlightWithArrow", appData.highlightMoveWithArrow);
498 }
499
500 void
IcsAlarmProc()501 IcsAlarmProc ()
502 {
503 appData.icsAlarm = !appData.icsAlarm;
504 // MARK_MENU_ITEM("Options.ICSAlarm", appData.icsAlarm);
505 }
506
507 void
MoveSoundProc()508 MoveSoundProc ()
509 {
510 appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
511 MARK_MENU_ITEM("Options.MoveSound", appData.ringBellAfterMoves);
512 }
513
514 void
OneClickProc()515 OneClickProc ()
516 {
517 appData.oneClick = !appData.oneClick;
518 MARK_MENU_ITEM("Options.OneClickMoving", appData.oneClick);
519 }
520
521 void
PeriodicUpdatesProc()522 PeriodicUpdatesProc ()
523 {
524 PeriodicUpdatesEvent(!appData.periodicUpdates);
525 MARK_MENU_ITEM("Options.PeriodicUpdates", appData.periodicUpdates);
526 }
527
528 void
PopupExitMessageProc()529 PopupExitMessageProc ()
530 {
531 appData.popupExitMessage = !appData.popupExitMessage;
532 MARK_MENU_ITEM("Options.PopupExitMessage", appData.popupExitMessage);
533 }
534
535 void
PopupMoveErrorsProc()536 PopupMoveErrorsProc ()
537 {
538 appData.popupMoveErrors = !appData.popupMoveErrors;
539 MARK_MENU_ITEM("Options.PopupMoveErrors", appData.popupMoveErrors);
540 }
541
542 void
PremoveProc()543 PremoveProc ()
544 {
545 appData.premove = !appData.premove;
546 // MARK_MENU_ITEM("Options.Premove", appData.premove);
547 }
548
549 void
ShowCoordsProc()550 ShowCoordsProc ()
551 {
552 appData.showCoords = !appData.showCoords;
553 MARK_MENU_ITEM("Options.ShowCoords", appData.showCoords);
554 DrawPosition(True, NULL);
555 }
556
557 void
ShowThinkingProc()558 ShowThinkingProc ()
559 {
560 appData.showThinking = !appData.showThinking; // [HGM] thinking: taken out of ShowThinkingEvent
561 ShowThinkingEvent();
562 }
563
564 void
HideThinkingProc()565 HideThinkingProc ()
566 {
567 appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: taken out of ShowThinkingEvent
568 ShowThinkingEvent();
569
570 MARK_MENU_ITEM("Options.HideThinking", appData.hideThinkingFromHuman);
571 }
572
573 void
CreateBookDelayed()574 CreateBookDelayed ()
575 {
576 ScheduleDelayedEvent(CreateBookEvent, 50);
577 }
578
579 void
SaveSelectedProc()580 SaveSelectedProc ()
581 {
582 FileNamePopUp(_("Save game file name?"),
583 "",
584 ".pgn",
585 SaveSelected, "a");
586 }
587
588 /*
589 * Menu definition tables
590 */
591
592 MenuItem fileMenu[] = {
593 {N_("New Game"), "<Ctrl>n", "NewGame", ResetGameEvent},
594 {N_("New Shuffle Game..."), NULL, "NewShuffleGame", ShuffleMenuProc},
595 {N_("New Variant..."), "<Alt><Shift>v", "NewVariant", NewVariantProc},// [HGM] variant: not functional yet
596 {"----", NULL, NULL, NothingProc},
597 {N_("Load Game"), "<Ctrl>o", "LoadGame", LoadGameProc, CHECK},
598 {N_("Load Position"), "<Ctrl><Shift>o", "LoadPosition", LoadPositionProc},
599 {N_("Next Position"), "<Shift>Page_Down", "LoadNextPosition", LoadNextPositionProc},
600 {N_("Prev Position"), "<Shift>Page_Up", "LoadPreviousPosition", LoadPrevPositionProc},
601 {"----", NULL, NULL, NothingProc},
602 {N_("Save Game"), "<Ctrl>s", "SaveGame", SaveGameProc},
603 {N_("Save Position"), "<Ctrl><Shift>s", "SavePosition", SavePositionProc},
604 {N_("Save Selected Games"), NULL, "SaveSelected", SaveSelectedProc},
605 {N_("Save Games as Book"), NULL, "CreateBook", CreateBookDelayed},
606 {"----", NULL, NULL, NothingProc},
607 {N_("Mail Move"), NULL, "MailMove", MailMoveEvent},
608 {N_("Reload CMail Message"), NULL, "ReloadCMailMessage", ReloadCmailMsgProc},
609 {"----", NULL, NULL, NothingProc},
610 {N_("Quit "), "<Ctrl>q", "Quit", QuitProc},
611 {NULL, NULL, NULL, NULL}
612 };
613
614 MenuItem editMenu[] = {
615 {N_("Copy Game"), "<Ctrl>c", "CopyGame", CopyGameProc},
616 {N_("Copy Position"), "<Ctrl><Shift>c", "CopyPosition", CopyPositionProc},
617 {N_("Copy Game List"), NULL, "CopyGameList", CopyGameListProc},
618 {"----", NULL, NULL, NothingProc},
619 {N_("Paste Game"), "<Ctrl>v", "PasteGame", PasteGameProc},
620 {N_("Paste Position"), "<Ctrl><Shift>v", "PastePosition", PastePositionProc},
621 {"----", NULL, NULL, NothingProc},
622 {N_("Edit Game"), "<Ctrl>e", "EditGame", EditGameEvent},
623 {N_("Edit Position"), "<Ctrl><Shift>e", "EditPosition", EditPositionEvent},
624 {N_("Edit Tags"), NULL, "EditTags", EditTagsProc},
625 {N_("Edit Comment"), NULL, "EditComment", EditCommentProc},
626 {N_("Edit Book"), NULL, "EditBook", EditBookEvent},
627 {"----", NULL, NULL, NothingProc},
628 {N_("Revert"), "Home", "Revert", RevertProc},
629 {N_("Annotate"), NULL, "Annotate", AnnotateProc},
630 {N_("Truncate Game"), "End", "TruncateGame", TruncateGameEvent},
631 {"----", NULL, NULL, NothingProc},
632 {N_("Backward"), "<Alt>Left", "Backward", BackwardEvent},
633 {N_("Forward"), "<Alt>Right", "Forward", ForwardEvent},
634 {N_("Back to Start"), "<Alt>Home", "BacktoStart", ToStartEvent},
635 {N_("Forward to End"), "<Alt>End", "ForwardtoEnd", ToEndEvent},
636 {NULL, NULL, NULL, NULL}
637 };
638
639 MenuItem viewMenu[] = {
640 {N_("Flip View"), "F2", "FlipView", FlipViewProc, CHECK},
641 {"----", NULL, NULL, NothingProc},
642 {N_("Engine Output"), "<Alt><Shift>o", "EngineOutput", EngineOutputProc, CHECK},
643 {N_("Move History"), "<Alt><Shift>h", "MoveHistory", HistoryShowProc, CHECK}, // [HGM] hist: activate 4.2.7 code
644 {N_("Evaluation Graph"), "<Alt><Shift>e", "EvaluationGraph", EvalGraphProc, CHECK},
645 {N_("Game List"), "<Alt><Shift>g", "GameList", ShowGameListProc, CHECK},
646 {N_("ICS text menu"), NULL, "ICStextmenu", IcsTextProc, CHECK},
647 {"----", NULL, NULL, NothingProc},
648 {N_("Tags"), NULL, "Tags", EditTagsProc, CHECK},
649 {N_("Comments"), NULL, "Comments", EditCommentProc, CHECK},
650 {N_("ICS Input Box"), NULL, "ICSInputBox", IcsInputBoxProc, CHECK},
651 {N_("ICS/Chat Console"), NULL, "OpenChatWindow", ChatProc, CHECK},
652 {"----", NULL, NULL, NothingProc},
653 {N_("Board..."), NULL, "Board", BoardOptionsProc},
654 {N_("Game List Tags..."), NULL, "GameListTags", GameListOptionsProc},
655 {NULL, NULL, NULL, NULL}
656 };
657
658 MenuItem modeMenu[] = {
659 {N_("Machine White"), "<Ctrl>w", "MachineWhite", MachineWhiteEvent, RADIO },
660 {N_("Machine Black"), "<Ctrl>b", "MachineBlack", MachineBlackEvent, RADIO },
661 {N_("Two Machines"), "<Ctrl>t", "TwoMachines", TwoMachinesEvent, RADIO },
662 {N_("Analysis Mode"), "<Ctrl>a", "AnalysisMode", (MenuProc*) AnalyzeModeEvent, RADIO },
663 {N_("Analyze Game"), "<Ctrl>g", "AnalyzeFile", AnalyzeFileEvent, RADIO },
664 {N_("Edit Game"), "<Ctrl>e", "EditGame", EditGameEvent, RADIO },
665 {N_("Edit Position"), "<Ctrl><Shift>e", "EditPosition", EditPositionEvent, RADIO },
666 {N_("Training"), NULL, "Training", TrainingEvent, RADIO },
667 {N_("ICS Client"), NULL, "ICSClient", IcsClientEvent, RADIO },
668 {"----", NULL, NULL, NothingProc},
669 {N_("Machine Match"), NULL, "MachineMatch", MatchProc, CHECK },
670 {N_("Pause"), "Pause", "Pause", PauseEvent, CHECK },
671 {NULL, NULL, NULL, NULL}
672 };
673
674 MenuItem actionMenu[] = {
675 {N_("Accept"), "F3", "Accept", AcceptEvent},
676 {N_("Decline"), "F4", "Decline", DeclineEvent},
677 {N_("Rematch"), "F12", "Rematch", RematchEvent},
678 {"----", NULL, NULL, NothingProc},
679 {N_("Call Flag"), "F5", "CallFlag", CallFlagEvent},
680 {N_("Draw"), "F6", "Draw", DrawEvent},
681 {N_("Adjourn"), "F7", "Adjourn", AdjournEvent},
682 {N_("Abort"), "F8", "Abort", AbortEvent},
683 {N_("Resign"), "F9", "Resign", ResignEvent},
684 {"----", NULL, NULL, NothingProc},
685 {N_("Stop Observing"), "F10", "StopObserving", StopObservingEvent},
686 {N_("Stop Examining"), "F11", "StopExamining", StopExaminingEvent},
687 {N_("Upload to Examine"), NULL, "UploadtoExamine", UploadGameEvent},
688 {"----", NULL, NULL, NothingProc},
689 {N_("Adjudicate to White"), NULL, "AdjudicatetoWhite", AdjuWhiteProc},
690 {N_("Adjudicate to Black"), NULL, "AdjudicatetoBlack", AdjuBlackProc},
691 {N_("Adjudicate Draw"), NULL, "AdjudicateDraw", AdjuDrawProc},
692 {NULL, NULL, NULL, NULL}
693 };
694
695 MenuItem engineMenu[100] = {
696 {N_("Edit Engine List..."), NULL, "EditEngList", EditEngineProc},
697 {"----", NULL, NULL, NothingProc},
698 {N_("Load New 1st Engine..."), NULL, "LoadNew1stEngine", LoadEngine1Proc},
699 {N_("Load New 2nd Engine..."), NULL, "LoadNew2ndEngine", LoadEngine2Proc},
700 {"----", NULL, NULL, NothingProc},
701 {N_("Engine #1 Settings..."), NULL, "Engine#1Settings", FirstSettingsProc},
702 {N_("Engine #2 Settings..."), NULL, "Engine#2Settings", SecondSettingsProc},
703 {"----", NULL, NULL, NothingProc},
704 {N_("Hint"), NULL, "Hint", HintEvent},
705 {N_("Book"), NULL, "Book", BookEvent},
706 {"----", NULL, NULL, NothingProc},
707 {N_("Move Now"), "<Ctrl>m", "MoveNow", MoveNowEvent},
708 {N_("Retract Move"), "<Ctrl>x", "RetractMove", RetractMoveEvent},
709 {NULL, NULL, NULL, NULL}
710 };
711
712 MenuItem optionsMenu[] = {
713 #ifdef OPTIONSDIALOG
714 {N_("General..."), NULL, "General", OptionsProc},
715 #endif
716 {N_("Time Control..."), "<Alt><Shift>t", "TimeControl", TimeControlProc},
717 {N_("Common Engine..."), "<Alt><Shift>u", "CommonEngine", UciMenuProc},
718 {N_("Adjudications..."), "<Alt><Shift>j", "Adjudications", EngineMenuProc},
719 {N_("ICS..."), NULL, "ICS", IcsOptionsProc},
720 {N_("Tournament..."), NULL, "Match", MatchOptionsProc},
721 {N_("Load Game..."), NULL, "LoadGame", LoadOptionsProc},
722 {N_("Save Game..."), NULL, "SaveGame", SaveOptionsProc},
723 {N_("Game List..."), NULL, "GameList", GameListOptionsProc},
724 {N_("Sounds..."), NULL, "Sounds", SoundOptionsProc},
725 {"----", NULL, NULL, NothingProc},
726 #ifndef OPTIONSDIALOG
727 {N_("Always Queen"), "<Ctrl><Shift>q", "AlwaysQueen", AlwaysQueenProc},
728 {N_("Animate Dragging"), NULL, "AnimateDragging", AnimateDraggingProc},
729 {N_("Animate Moving"), "<Ctrl><Shift>a", "AnimateMoving", AnimateMovingProc},
730 {N_("Auto Flag"), "<Ctrl><Shift>f", "AutoFlag", AutoflagProc},
731 {N_("Auto Flip View"), NULL, "AutoFlipView", AutoflipProc},
732 {N_("Blindfold"), NULL, "Blindfold", BlindfoldProc},
733 {N_("Flash Moves"), NULL, "FlashMoves", FlashMovesProc},
734 #if HIGHDRAG
735 {N_("Highlight Dragging"), NULL, "HighlightDragging", HighlightDraggingProc},
736 #endif
737 {N_("Highlight Last Move"), NULL, "HighlightLastMove", HighlightLastMoveProc},
738 {N_("Highlight With Arrow"), NULL, "HighlightWithArrow", HighlightArrowProc},
739 {N_("Move Sound"), NULL, "MoveSound", MoveSoundProc},
740 {N_("One-Click Moving"), NULL, "OneClickMoving", OneClickProc},
741 {N_("Periodic Updates"), NULL, "PeriodicUpdates", PeriodicUpdatesProc},
742 {N_("Ponder Next Move"), "<Ctrl><Shift>p", "PonderNextMove", PonderNextMoveProc},
743 {N_("Popup Exit Message"), NULL, "PopupExitMessage", PopupExitMessageProc},
744 {N_("Popup Move Errors"), NULL, "PopupMoveErrors", PopupMoveErrorsProc},
745 {N_("Show Coords"), NULL, "ShowCoords", ShowCoordsProc},
746 {N_("Hide Thinking"), "<Ctrl><Shift>h", "HideThinking", HideThinkingProc},
747 {N_("Test Legality"), "<Ctrl><Shift>l", "TestLegality", TestLegalityProc},
748 {"----", NULL, NULL, NothingProc},
749 #endif
750 {N_("Save Settings Now"), NULL, "SaveSettingsNow", SaveSettingsProc},
751 {N_("Save Settings on Exit"), NULL, "SaveSettingsonExit", SaveOnExitProc, CHECK },
752 {NULL, NULL, NULL, NULL}
753 };
754
755 MenuItem helpMenu[] = {
756 {N_("Info XBoard"), NULL, "InfoXBoard", InfoProc},
757 {N_("Man XBoard"), "F1", "ManXBoard", ManProc},
758 {"----", NULL, NULL, NothingProc},
759 {N_("XBoard Home Page"), NULL, "XBoardHomePage", HomePageProc},
760 {N_("On-line User Guide"), NULL, "On-lineUserGuide", GuideProc},
761 {N_("Development News"), NULL, "DevelopmentNews", NewsPageProc},
762 {N_("e-Mail Bug Report"), NULL, "e-MailBugReport", BugReportProc},
763 {"----", NULL, NULL, NothingProc},
764 {N_("About XBoard"), NULL, "AboutXBoard", AboutProc},
765 {NULL, NULL, NULL, NULL}
766 };
767
768 MenuItem noMenu[] = {
769 { "", "<Alt>Next" ,"LoadNextGame", LoadNextGameProc },
770 { "", "<Alt>Prior" ,"LoadPrevGame", LoadPrevGameProc },
771 { "", NULL,"ReloadGame", ReloadGameProc },
772 { "", NULL,"ReloadPosition", ReloadPositionProc },
773 #ifndef OPTIONSDIALOG
774 { "", NULL,"AlwaysQueen", AlwaysQueenProc },
775 { "", NULL,"AnimateDragging", AnimateDraggingProc },
776 { "", NULL,"AnimateMoving", AnimateMovingProc },
777 { "", NULL,"Autoflag", AutoflagProc },
778 { "", NULL,"Autoflip", AutoflipProc },
779 { "", NULL,"Blindfold", BlindfoldProc },
780 { "", NULL,"FlashMoves", FlashMovesProc },
781 #if HIGHDRAG
782 { "", NULL,"HighlightDragging", HighlightDraggingProc },
783 #endif
784 { "", NULL,"HighlightLastMove", HighlightLastMoveProc },
785 { "", NULL,"MoveSound", MoveSoundProc },
786 { "", NULL,"PeriodicUpdates", PeriodicUpdatesProc },
787 { "", NULL,"PopupExitMessage", PopupExitMessageProc },
788 { "", NULL,"PopupMoveErrors", PopupMoveErrorsProc },
789 { "", NULL,"ShowCoords", ShowCoordsProc },
790 { "", NULL,"ShowThinking", ShowThinkingProc },
791 { "", NULL,"HideThinking", HideThinkingProc },
792 { "", NULL,"TestLegality", TestLegalityProc },
793 #endif
794 { "", NULL,"AboutGame", AboutGameEvent },
795 { "", "<Ctrl>d" ,"DebugProc", DebugProc },
796 { "", NULL,"Nothing", NothingProc },
797 {NULL, NULL, NULL, NULL}
798 };
799
800 Menu menuBar[] = {
801 {N_("File"), "File", fileMenu},
802 {N_("Edit"), "Edit", editMenu},
803 {N_("View"), "View", viewMenu},
804 {N_("Mode"), "Mode", modeMenu},
805 {N_("Action"), "Action", actionMenu},
806 {N_("Engine"), "Engine", engineMenu},
807 {N_("Options"), "Options", optionsMenu},
808 {N_("Help"), "Help", helpMenu},
809 {NULL, NULL, NULL},
810 { "", "None", noMenu}
811 };
812
813 MenuItem *
MenuNameToItem(char * menuName)814 MenuNameToItem (char *menuName)
815 {
816 int i=0;
817 char buf[MSG_SIZ], *p;
818 MenuItem *menuTab;
819 static MenuItem a = { NULL, NULL, NULL, NothingProc };
820 extern Option mainOptions[];
821 safeStrCpy(buf, menuName, MSG_SIZ);
822 p = strchr(buf, '.');
823 if(!p) menuTab = noMenu, p = menuName; else {
824 *p++ = NULLCHAR;
825 for(i=0; menuBar[i].name; i++)
826 if(!strcmp(buf, menuBar[i].name)) break;
827 if(!menuBar[i].name) return NULL; // main menu not found
828 menuTab = menuBar[i].mi;
829 }
830 if(*p == NULLCHAR) { a.handle = mainOptions[i+1].handle; return &a; } // main menu bar
831 for(i=0; menuTab[i].string; i++)
832 if(menuTab[i].ref && !strcmp(p, menuTab[i].ref)) return menuTab + i;
833 return NULL; // item not found
834 }
835
836 int firstEngineItem;
837
838 void
AppendEnginesToMenu(char * list)839 AppendEnginesToMenu (char *list)
840 {
841 int i=0;
842 char *p;
843 if(appData.icsActive || appData.recentEngines <= 0) return;
844 for(firstEngineItem=0; engineMenu[firstEngineItem].string; firstEngineItem++);
845 recentEngines = strdup(list);
846 while (*list) {
847 p = strchr(list, '\n'); if(p == NULL) break;
848 if(i == 0) engineMenu[firstEngineItem++].string = "----"; // at least one valid item to add
849 *p = 0;
850 if(firstEngineItem + i < 99)
851 engineMenu[firstEngineItem+i].string = strdup(list); // just set name; MenuProc stays NULL
852 i++; *p = '\n'; list = p + 1;
853 }
854 }
855
856 Enables icsEnables[] = {
857 { "File.MailMove", False },
858 { "File.ReloadCMailMessage", False },
859 { "Mode.MachineBlack", False },
860 { "Mode.MachineWhite", False },
861 { "Mode.AnalysisMode", False },
862 { "Mode.AnalyzeFile", False },
863 { "Mode.TwoMachines", False },
864 { "Mode.MachineMatch", False },
865 #if !ZIPPY
866 { "Engine.Hint", False },
867 { "Engine.Book", False },
868 { "Engine.MoveNow", False },
869 #ifndef OPTIONSDIALOG
870 { "PeriodicUpdates", False },
871 { "HideThinking", False },
872 { "PonderNextMove", False },
873 #endif
874 #endif
875 { "Engine.Engine#1Settings", False },
876 { "Engine.Engine#2Settings", False },
877 { "Engine.Load1stEngine", False },
878 { "Engine.Load2ndEngine", False },
879 { "Edit.Annotate", False },
880 { "Options.Match", False },
881 { NULL, False }
882 };
883
884 Enables ncpEnables[] = {
885 { "File.MailMove", False },
886 { "File.ReloadCMailMessage", False },
887 { "Mode.MachineWhite", False },
888 { "Mode.MachineBlack", False },
889 { "Mode.AnalysisMode", False },
890 { "Mode.AnalyzeFile", False },
891 { "Mode.TwoMachines", False },
892 { "Mode.MachineMatch", False },
893 { "Mode.ICSClient", False },
894 { "View.ICStextmenu", False },
895 { "View.ICSInputBox", False },
896 { "View.OpenChatWindow", False },
897 { "Action.", False },
898 { "Edit.Revert", False },
899 { "Edit.Annotate", False },
900 { "Engine.Engine#1Settings", False },
901 { "Engine.Engine#2Settings", False },
902 { "Engine.MoveNow", False },
903 { "Engine.RetractMove", False },
904 { "Options.ICS", False },
905 #ifndef OPTIONSDIALOG
906 { "Options.AutoFlag", False },
907 { "Options.AutoFlip View", False },
908 // { "Options.ICSAlarm", False },
909 { "Options.MoveSound", False },
910 { "Options.HideThinking", False },
911 { "Options.PeriodicUpdates", False },
912 { "Options.PonderNextMove", False },
913 #endif
914 { "Engine.Hint", False },
915 { "Engine.Book", False },
916 { NULL, False }
917 };
918
919 Enables gnuEnables[] = {
920 { "Mode.ICSClient", False },
921 { "View.ICStextmenu", False },
922 { "View.ICSInputBox", False },
923 { "View.OpenChatWindow", False },
924 { "Action.Accept", False },
925 { "Action.Decline", False },
926 { "Action.Rematch", False },
927 { "Action.Adjourn", False },
928 { "Action.StopExamining", False },
929 { "Action.StopObserving", False },
930 { "Action.UploadtoExamine", False },
931 { "Edit.Revert", False },
932 { "Edit.Annotate", False },
933 { "Options.ICS", False },
934
935 /* The next two options rely on SetCmailMode being called *after* */
936 /* SetGNUMode so that when GNU is being used to give hints these */
937 /* menu options are still available */
938
939 { "File.MailMove", False },
940 { "File.ReloadCMailMessage", False },
941 // [HGM] The following have been added to make a switch from ncp to GNU mode possible
942 { "Mode.MachineWhite", True },
943 { "Mode.MachineBlack", True },
944 { "Mode.AnalysisMode", True },
945 { "Mode.AnalyzeFile", True },
946 { "Mode.TwoMachines", True },
947 { "Mode.MachineMatch", True },
948 { "Engine.Engine#1Settings", True },
949 { "Engine.Engine#2Settings", True },
950 { "Engine.Hint", True },
951 { "Engine.Book", True },
952 { "Engine.MoveNow", True },
953 { "Engine.RetractMove", True },
954 { "Action.", True },
955 { NULL, False }
956 };
957
958 Enables cmailEnables[] = {
959 { "Action.", True },
960 { "Action.CallFlag", False },
961 { "Action.Draw", True },
962 { "Action.Adjourn", False },
963 { "Action.Abort", False },
964 { "Action.StopObserving", False },
965 { "Action.StopExamining", False },
966 { "File.MailMove", True },
967 { "File.ReloadCMailMessage", True },
968 { NULL, False }
969 };
970
971 Enables trainingOnEnables[] = {
972 { "Edit.EditComment", False },
973 { "Mode.Pause", False },
974 { "Edit.Forward", False },
975 { "Edit.Backward", False },
976 { "Edit.ForwardtoEnd", False },
977 { "Edit.BacktoStart", False },
978 { "Engine.MoveNow", False },
979 { "Edit.TruncateGame", False },
980 { NULL, False }
981 };
982
983 Enables trainingOffEnables[] = {
984 { "Edit.EditComment", True },
985 { "Mode.Pause", True },
986 { "Edit.Forward", True },
987 { "Edit.Backward", True },
988 { "Edit.ForwardtoEnd", True },
989 { "Edit.BacktoStart", True },
990 { "Engine.MoveNow", True },
991 { "Engine.TruncateGame", True },
992 { NULL, False }
993 };
994
995 Enables machineThinkingEnables[] = {
996 { "File.LoadGame", False },
997 // { "LoadNextGame", False },
998 // { "LoadPreviousGame", False },
999 // { "ReloadSameGame", False },
1000 { "Edit.PasteGame", False },
1001 { "File.LoadPosition", False },
1002 // { "LoadNextPosition", False },
1003 // { "LoadPreviousPosition", False },
1004 // { "ReloadSamePosition", False },
1005 { "Edit.PastePosition", False },
1006 { "Mode.MachineWhite", False },
1007 { "Mode.MachineBlack", False },
1008 { "Mode.TwoMachines", False },
1009 // { "MachineMatch", False },
1010 { "Engine.RetractMove", False },
1011 { NULL, False }
1012 };
1013
1014 Enables userThinkingEnables[] = {
1015 { "File.LoadGame", True },
1016 // { "LoadNextGame", True },
1017 // { "LoadPreviousGame", True },
1018 // { "ReloadSameGame", True },
1019 { "Edit.PasteGame", True },
1020 { "File.LoadPosition", True },
1021 // { "LoadNextPosition", True },
1022 // { "LoadPreviousPosition", True },
1023 // { "ReloadSamePosition", True },
1024 { "Edit.PastePosition", True },
1025 { "Mode.MachineWhite", True },
1026 { "Mode.MachineBlack", True },
1027 { "Mode.TwoMachines", True },
1028 // { "MachineMatch", True },
1029 { "Engine.RetractMove", True },
1030 { NULL, False }
1031 };
1032
1033 void
SetICSMode()1034 SetICSMode ()
1035 {
1036 SetMenuEnables(icsEnables);
1037
1038 #if ZIPPY
1039 if (appData.zippyPlay && !appData.noChessProgram) { /* [DM] icsEngineAnalyze */
1040 EnableNamedMenuItem("Mode.AnalysisMode", True);
1041 EnableNamedMenuItem("Engine.Engine#1Settings", True);
1042 }
1043 #endif
1044 }
1045
1046 void
SetNCPMode()1047 SetNCPMode ()
1048 {
1049 SetMenuEnables(ncpEnables);
1050 }
1051
1052 void
SetGNUMode()1053 SetGNUMode ()
1054 {
1055 SetMenuEnables(gnuEnables);
1056 }
1057
1058 void
SetCmailMode()1059 SetCmailMode ()
1060 {
1061 SetMenuEnables(cmailEnables);
1062 }
1063
1064 void
SetTrainingModeOn()1065 SetTrainingModeOn ()
1066 {
1067 SetMenuEnables(trainingOnEnables);
1068 if (appData.showButtonBar) {
1069 EnableButtonBar(False);
1070 }
1071 CommentPopDown();
1072 }
1073
1074 void
SetTrainingModeOff()1075 SetTrainingModeOff ()
1076 {
1077 SetMenuEnables(trainingOffEnables);
1078 if (appData.showButtonBar) {
1079 EnableButtonBar(True);
1080 }
1081 }
1082
1083 void
SetUserThinkingEnables()1084 SetUserThinkingEnables ()
1085 {
1086 if (appData.noChessProgram) return;
1087 SetMenuEnables(userThinkingEnables);
1088 }
1089
1090 void
SetMachineThinkingEnables()1091 SetMachineThinkingEnables ()
1092 {
1093 if (appData.noChessProgram) return;
1094 SetMenuEnables(machineThinkingEnables);
1095 switch (gameMode) {
1096 case MachinePlaysBlack:
1097 case MachinePlaysWhite:
1098 case TwoMachinesPlay:
1099 EnableNamedMenuItem(ModeToWidgetName(gameMode), True);
1100 break;
1101 default:
1102 break;
1103 }
1104 }
1105
1106 void
GreyRevert(Boolean grey)1107 GreyRevert (Boolean grey)
1108 {
1109 EnableNamedMenuItem("Edit.Revert", !grey);
1110 EnableNamedMenuItem("Edit.Annotate", !grey);
1111 }
1112
1113 char *
ModeToWidgetName(GameMode mode)1114 ModeToWidgetName (GameMode mode)
1115 {
1116 switch (mode) {
1117 case BeginningOfGame:
1118 if (appData.icsActive)
1119 return "Mode.ICSClient";
1120 else if (appData.noChessProgram ||
1121 *appData.cmailGameName != NULLCHAR)
1122 return "Mode.EditGame";
1123 else
1124 return "Mode.MachineBlack";
1125 case MachinePlaysBlack:
1126 return "Mode.MachineBlack";
1127 case MachinePlaysWhite:
1128 return "Mode.MachineWhite";
1129 case AnalyzeMode:
1130 return "Mode.AnalysisMode";
1131 case AnalyzeFile:
1132 return "Mode.AnalyzeFile";
1133 case TwoMachinesPlay:
1134 return "Mode.TwoMachines";
1135 case EditGame:
1136 return "Mode.EditGame";
1137 case PlayFromGameFile:
1138 return "File.LoadGame";
1139 case EditPosition:
1140 return "Mode.EditPosition";
1141 case Training:
1142 return "Mode.Training";
1143 case IcsPlayingWhite:
1144 case IcsPlayingBlack:
1145 case IcsObserving:
1146 case IcsIdle:
1147 case IcsExamining:
1148 return "Mode.ICSClient";
1149 default:
1150 case EndOfGame:
1151 return NULL;
1152 }
1153 }
1154
1155 static void
InstallNewEngine(char * command,char * dir,char * variants,char * protocol)1156 InstallNewEngine (char *command, char *dir, char *variants, char *protocol)
1157 { // install the given engine in XBoard's -firstChessProgramNames
1158 char buf[MSG_SIZ], *quote = "";
1159 if(strchr(command, ' ')) { // quoting needed
1160 if(!strchr(command, '"')) quote = "\""; else
1161 if(!strchr(command, '\'')) quote = "'"; else {
1162 printf("Could not auto-install %s\n", command); // too complex
1163 }
1164 }
1165 // construct engine line, with optional -fd and -fUCI arguments
1166 snprintf(buf, MSG_SIZ, "%s%s%s", quote, command, quote);
1167 if(strcmp(dir, "") && strcmp(dir, "."))
1168 snprintf(buf + strlen(buf), MSG_SIZ - strlen(buf), " -fd %s", dir);
1169 if(!strcmp(protocol, "uci"))
1170 snprintf(buf + strlen(buf), MSG_SIZ - strlen(buf), " -fUCI");
1171 if(strstr(firstChessProgramNames, buf)) return; // avoid duplicats
1172 // append line
1173 quote = malloc(strlen(firstChessProgramNames) + strlen(buf) + 2);
1174 sprintf(quote, "%s%s\n", firstChessProgramNames, buf);
1175 FREE(firstChessProgramNames); firstChessProgramNames = quote;
1176 }
1177
1178 #ifdef HAVE_DIRENT_H
1179 #include <dirent.h>
1180 #else
1181 #include <sys/dir.h>
1182 #define dirent direct
1183 #endif
1184
1185 static void
InstallFromDir(char * dirName,char * protocol,char * settingsFile)1186 InstallFromDir (char *dirName, char *protocol, char *settingsFile)
1187 { // scan system for new plugin specs in given directory
1188 DIR *dir;
1189 struct dirent *dp;
1190 struct stat statBuf;
1191 time_t lastSaved = 0;
1192 char buf[1024];
1193
1194 if(!stat(settingsFile, &statBuf)) lastSaved = statBuf.st_mtime;
1195 snprintf(buf, 1024, "%s/%s", dirName, protocol);
1196
1197 if(!(dir = opendir(buf))) return;
1198 while( (dp = readdir(dir))) {
1199 time_t installed = 0;
1200 if(!strstr(dp->d_name, ".eng")) continue; // to suppress . and ..
1201 snprintf(buf, 1024, "%s/%s/%s", dirName, protocol, dp->d_name);
1202 if(!stat(buf, &statBuf)) installed = statBuf.st_mtime;
1203 if(lastSaved == 0 || (int) (installed - lastSaved) > 0) { // first time we see it
1204 FILE *f = fopen(buf, "r");
1205 if(f) { // read the plugin-specs
1206 char engineCommand[1024], engineDir[1024], variants[1024];
1207 char bad=0, dummy, *engineCom = engineCommand;
1208 int major, minor;
1209 if(fscanf(f, "plugin spec %d.%d%c", &major, &minor, &dummy) != 3 ||
1210 fscanf(f, "%[^\n]%c", engineCommand, &dummy) != 2 ||
1211 fscanf(f, "%[^\n]%c", variants, &dummy) != 2) bad = 1;
1212 fclose(f);
1213 if(bad) continue;
1214 // uncomment following two lines for chess-only installs
1215 // if(!(p = strstr(variants, "chess")) ||
1216 // p != variants && p[-1] != ',' || p[5] && p[5] != ',') continue;
1217 // split off engine working directory (if any)
1218 strcpy(engineDir, "");
1219 if(sscanf(engineCommand, "cd %[^;];%c", engineDir, &dummy) == 2)
1220 engineCom = engineCommand + strlen(engineDir) + 4;
1221 InstallNewEngine(engineCom, engineDir, variants, protocol);
1222 }
1223 }
1224 }
1225 closedir(dir);
1226 }
1227
1228 static void
AutoInstallProtocol(char * settingsFile,char * protocol)1229 AutoInstallProtocol (char *settingsFile, char *protocol)
1230 { // install new engines for given protocol (both from package and source)
1231 InstallFromDir("/usr/local/share/games/plugins", protocol, settingsFile);
1232 InstallFromDir("/usr/share/games/plugins", protocol, settingsFile);
1233 }
1234
1235 void
AutoInstall(char * settingsFile)1236 AutoInstall (char *settingsFile)
1237 { // install all new XBoard and UCI engines
1238 AutoInstallProtocol(settingsFile, "xboard");
1239 AutoInstallProtocol(settingsFile, "uci");
1240 }
1241
1242 void
InitMenuMarkers()1243 InitMenuMarkers()
1244 {
1245 #ifndef OPTIONSDIALOG
1246 if (appData.alwaysPromoteToQueen) {
1247 MarkMenuItem("Options.Always Queen", True);
1248 }
1249 if (appData.animateDragging) {
1250 MarkMenuItem("Options.Animate Dragging", True);
1251 }
1252 if (appData.animate) {
1253 MarkMenuItem("Options.Animate Moving", True);
1254 }
1255 if (appData.autoCallFlag) {
1256 MarkMenuItem("Options.Auto Flag", True);
1257 }
1258 if (appData.autoFlipView) {
1259 XtSetValues(XtNameToWidget(menuBarWidget,"Options.Auto Flip View", True);
1260 }
1261 if (appData.blindfold) {
1262 MarkMenuItem("Options.Blindfold", True);
1263 }
1264 if (appData.flashCount > 0) {
1265 MarkMenuItem("Options.Flash Moves", True);
1266 }
1267 #if HIGHDRAG
1268 if (appData.highlightDragging) {
1269 MarkMenuItem("Options.Highlight Dragging", True);
1270 }
1271 #endif
1272 if (appData.highlightLastMove) {
1273 MarkMenuItem("Options.Highlight Last Move", True);
1274 }
1275 if (appData.highlightMoveWithArrow) {
1276 MarkMenuItem("Options.Arrow", True);
1277 }
1278 // if (appData.icsAlarm) {
1279 // MarkMenuItem("Options.ICS Alarm", True);
1280 // }
1281 if (appData.ringBellAfterMoves) {
1282 MarkMenuItem("Options.Move Sound", True);
1283 }
1284 if (appData.oneClick) {
1285 MarkMenuItem("Options.OneClick", True);
1286 }
1287 if (appData.periodicUpdates) {
1288 MarkMenuItem("Options.Periodic Updates", True);
1289 }
1290 if (appData.ponderNextMove) {
1291 MarkMenuItem("Options.Ponder Next Move", True);
1292 }
1293 if (appData.popupExitMessage) {
1294 MarkMenuItem("Options.Popup Exit Message", True);
1295 }
1296 if (appData.popupMoveErrors) {
1297 MarkMenuItem("Options.Popup Move Errors", True);
1298 }
1299 // if (appData.premove) {
1300 // MarkMenuItem("Options.Premove", True);
1301 // }
1302 if (appData.showCoords) {
1303 MarkMenuItem("Options.Show Coords", True);
1304 }
1305 if (appData.hideThinkingFromHuman) {
1306 MarkMenuItem("Options.Hide Thinking", True);
1307 }
1308 if (appData.testLegality) {
1309 MarkMenuItem("Options.Test Legality", True);
1310 }
1311 #endif
1312 if (saveSettingsOnExit) {
1313 MarkMenuItem("Options.SaveSettingsonExit", True);
1314 }
1315 EnableNamedMenuItem("File.SaveSelected", False);
1316
1317 // all XBoard builds get here, but not WinBoard...
1318 if(*appData.autoInstall) AutoInstall(settingsFileName);
1319 }
1320