removed unused variables (-Wunused-variable)
[xboard.git] / menus.c
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 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 "backendz.h"
91 #include "moves.h"
92 #include "xhistory.h"
93 #include "xedittags.h"
94 #include "menus.h"
95 #include "gettext.h"
96
97 #ifdef ENABLE_NLS
98 # define  _(s) gettext (s)
99 # define N_(s) gettext_noop (s)
100 #else
101 # define  _(s) (s)
102 # define N_(s)  s
103 #endif
104
105 /*
106  * Button/menu procedures
107  */
108
109 char  *gameCopyFilename, *gamePasteFilename;
110 Boolean saveSettingsOnExit;
111 char *settingsFileName;
112
113 static int
114 LoadGamePopUp (FILE *f, int gameNumber, char *title)
115 {
116     cmailMsgLoaded = FALSE;
117     if (gameNumber == 0) {
118         int error = GameListBuild(f);
119         if (error) {
120             DisplayError(_("Cannot build game list"), error);
121         } else if (!ListEmpty(&gameList) &&
122                    ((ListGame *) gameList.tailPred)->number > 1) {
123             GameListPopUp(f, title);
124             return TRUE;
125         }
126         GameListDestroy();
127         gameNumber = 1;
128     }
129     return LoadGame(f, gameNumber, title, FALSE);
130 }
131
132 void
133 LoadGameProc ()
134 {
135     if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
136         Reset(FALSE, TRUE);
137     }
138     FileNamePopUp(_("Load game file name?"), "", ".pgn .game", LoadGamePopUp, "rb");
139 }
140
141 void
142 LoadNextGameProc ()
143 {
144     ReloadGame(1);
145 }
146
147 void
148 LoadPrevGameProc ()
149 {
150     ReloadGame(-1);
151 }
152
153 void
154 ReloadGameProc ()
155 {
156     ReloadGame(0);
157 }
158
159 void
160 LoadNextPositionProc ()
161 {
162     ReloadPosition(1);
163 }
164
165 void
166 LoadPrevPositionProc ()
167 {
168     ReloadPosition(-1);
169 }
170
171 void
172 ReloadPositionProc ()
173 {
174     ReloadPosition(0);
175 }
176
177 void
178 LoadPositionProc() 
179 {
180     if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
181         Reset(FALSE, TRUE);
182     }
183     FileNamePopUp(_("Load position file name?"), "", ".fen .epd .pos", LoadPosition, "rb");
184 }
185
186 void
187 SaveGameProc ()
188 {
189     FileNamePopUp(_("Save game file name?"),
190                   DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"),
191                   appData.oldSaveStyle ? ".game" : ".pgn",
192                   SaveGame, "a");
193 }
194
195 void
196 SavePositionProc ()
197 {
198     FileNamePopUp(_("Save position file name?"),
199                   DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"),
200                   appData.oldSaveStyle ? ".pos" : ".fen",
201                   SavePosition, "a");
202 }
203
204 void
205 ReloadCmailMsgProc ()
206 {
207     ReloadCmailMsgEvent(FALSE);
208 }
209
210 void
211 CopyFENToClipboard ()
212 { // wrapper to make call from back-end possible
213   CopyPositionProc();
214 }
215
216 void
217 CopyPositionProc ()
218 {
219     static char *selected_fen_position=NULL;
220     if(gameMode == EditPosition) EditPositionDone(TRUE);
221     if (selected_fen_position) free(selected_fen_position);
222     selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
223     if (!selected_fen_position) return;
224     CopySomething(selected_fen_position);
225 }
226
227 void
228 CopyGameProc ()
229 {
230   int ret;
231
232   ret = SaveGameToFile(gameCopyFilename, FALSE);
233   if (!ret) return;
234
235   CopySomething(NULL);
236 }
237
238 void
239 CopyGameListProc ()
240 {
241   if(!SaveGameListAsText(fopen(gameCopyFilename, "w"))) return;
242   CopySomething(NULL);
243 }
244
245 void
246 AutoSaveGame ()
247 {
248     SaveGameProc();
249 }
250
251
252 void
253 QuitProc ()
254 {
255     ExitEvent(0);
256 }
257
258 void
259 AnalyzeModeProc ()
260 {
261     char buf[MSG_SIZ];
262
263     if (!first.analysisSupport) {
264       snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
265       DisplayError(buf, 0);
266       return;
267     }
268     /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
269     if (appData.icsActive) {
270         if (gameMode != IcsObserving) {
271           snprintf(buf, MSG_SIZ, _("You are not observing a game"));
272             DisplayError(buf, 0);
273             /* secure check */
274             if (appData.icsEngineAnalyze) {
275                 if (appData.debugMode)
276                     fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
277                 ExitAnalyzeMode();
278                 ModeHighlight();
279             }
280             return;
281         }
282         /* if enable, use want disable icsEngineAnalyze */
283         if (appData.icsEngineAnalyze) {
284                 ExitAnalyzeMode();
285                 ModeHighlight();
286                 return;
287         }
288         appData.icsEngineAnalyze = TRUE;
289         if (appData.debugMode)
290             fprintf(debugFP, _("ICS engine analyze starting... \n"));
291     }
292 #ifndef OPTIONSDIALOG
293     if (!appData.showThinking)
294       ShowThinkingProc();
295 #endif
296
297     AnalyzeModeEvent();
298 }
299
300 void
301 AnalyzeFileProc ()
302 {
303     if (!first.analysisSupport) {
304       char buf[MSG_SIZ];
305       snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
306       DisplayError(buf, 0);
307       return;
308     }
309 //    Reset(FALSE, TRUE);
310 #ifndef OPTIONSDIALOG
311     if (!appData.showThinking)
312       ShowThinkingProc();
313 #endif
314     AnalyzeFileEvent();
315 //    FileNamePopUp(_("File to analyze"), "", ".pgn .game", LoadGamePopUp, "rb");
316     AnalysisPeriodicEvent(1);
317 }
318
319 void
320 MatchProc ()
321 {
322     MatchEvent(2);
323 }
324
325 void
326 AdjuWhiteProc ()
327 {
328     UserAdjudicationEvent(+1);
329 }
330
331 void
332 AdjuBlackProc ()
333 {
334     UserAdjudicationEvent(-1);
335 }
336
337 void
338 AdjuDrawProc ()
339 {
340     UserAdjudicationEvent(0);
341 }
342
343 void
344 RevertProc ()
345 {
346     RevertEvent(False);
347 }
348
349 void
350 AnnotateProc ()
351 {
352     RevertEvent(True);
353 }
354
355 void
356 FlipViewProc ()
357 {
358     if(twoBoards) { partnerUp = 1; DrawPosition(True, NULL); partnerUp = 0; }
359     flipView = !flipView;
360     DrawPosition(True, NULL);
361 }
362
363 void
364 SaveOnExitProc ()
365 {
366   saveSettingsOnExit = !saveSettingsOnExit;
367
368   MarkMenuItem("Options.SaveSettingsonExit", saveSettingsOnExit);
369 }
370
371 void
372 SaveSettingsProc ()
373 {
374   SaveSettings(settingsFileName);
375 }
376
377 void
378 InfoProc ()
379 {
380     char buf[MSG_SIZ];
381     snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
382             INFODIR, INFOFILE);
383     system(buf);
384 }
385
386 void
387 ManProc ()
388 {   // called from menu
389     ManInner(NULL, NULL, NULL, NULL);
390 }
391
392 void
393 BugReportProc ()
394 {
395     char buf[MSG_SIZ];
396     snprintf(buf, MSG_SIZ, "%s mailto:bug-xboard@gnu.org", appData.sysOpen);
397     system(buf);
398 }
399
400 void
401 GuideProc ()
402 {
403     char buf[MSG_SIZ];
404     snprintf(buf, MSG_SIZ, "%s http://www.gnu.org/software/xboard/user_guide/UserGuide.html", appData.sysOpen);
405     system(buf);
406 }
407
408 void
409 HomePageProc ()
410 {
411     char buf[MSG_SIZ];
412     snprintf(buf, MSG_SIZ, "%s http://www.gnu.org/software/xboard/", appData.sysOpen);
413     system(buf);
414 }
415
416 void
417 NewsPageProc ()
418 {
419     char buf[MSG_SIZ];
420     snprintf(buf, MSG_SIZ, "%s http://www.gnu.org/software/xboard/whats_new/portal.html", appData.sysOpen);
421     system(buf);
422 }
423
424 void
425 AboutProc ()
426 {
427     char buf[2 * MSG_SIZ];
428 #if ZIPPY
429     char *zippy = _(" (with Zippy code)");
430 #else
431     char *zippy = "";
432 #endif
433     snprintf(buf, sizeof(buf), 
434 _("%s%s\n\n"
435 "Copyright 1991 Digital Equipment Corporation\n"
436 "Enhancements Copyright 1992-2012 Free Software Foundation\n"
437 "Enhancements Copyright 2005 Alessandro Scotti\n\n"
438 "%s is free software and carries NO WARRANTY;"
439 "see the file COPYING for more information.\n\n"
440 "Visit XBoard on the web at: http://www.gnu.org/software/xboard/\n"
441 "Check out the newest features at: http://www.gnu.org/software/xboard/whats_new.html\n\n"
442 "Report bugs via email at: <bug-xboard@gnu.org>\n\n"
443   ),
444             programVersion, zippy, PACKAGE);
445     ErrorPopUp(_("About XBoard"), buf, FALSE);
446 }
447
448 void
449 DebugProc ()
450 {
451     appData.debugMode = !appData.debugMode;
452     if(!strcmp(appData.nameOfDebugFile, "stderr")) return; // stderr is already open, and should never be closed
453     if(!appData.debugMode) fclose(debugFP);
454     else {
455         debugFP = fopen(appData.nameOfDebugFile, "w");
456         if(debugFP == NULL) debugFP = stderr;
457         else setbuf(debugFP, NULL);
458     }
459 }
460
461 void
462 NothingProc ()
463 {
464     return;
465 }
466
467 #ifdef OPTIONSDIALOG
468 #   define MARK_MENU_ITEM(X,Y)
469 #else
470 #   define MARK_MENU_ITEM(X,Y) MarkMenuItem(X, Y)
471 #endif
472
473 void
474 PonderNextMoveProc ()
475 {
476   PonderNextMoveEvent(!appData.ponderNextMove);
477   MARK_MENU_ITEM("Options.PonderNextMove", appData.ponderNextMove);
478 }
479
480 void
481 AlwaysQueenProc ()
482 {
483     appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen;
484     MARK_MENU_ITEM("Options.AlwaysQueen", appData.alwaysPromoteToQueen);
485 }
486
487 void
488 AnimateDraggingProc ()
489 {
490     appData.animateDragging = !appData.animateDragging;
491
492     if (appData.animateDragging) CreateAnimVars();
493     MARK_MENU_ITEM("Options.AnimateDragging", appData.animateDragging);
494 }
495
496 void
497 AnimateMovingProc ()
498 {
499     appData.animate = !appData.animate;
500     if (appData.animate) CreateAnimVars();
501     MARK_MENU_ITEM("Options.AnimateMoving", appData.animate);
502 }
503
504 void
505 AutoflagProc ()
506 {
507     appData.autoCallFlag = !appData.autoCallFlag;
508     MARK_MENU_ITEM("Options.AutoFlag", appData.autoCallFlag);
509 }
510
511 void
512 AutoflipProc ()
513 {
514     appData.autoFlipView = !appData.autoFlipView;
515     MARK_MENU_ITEM("Options.AutoFlipView", appData.autoFlipView);
516 }
517
518 void
519 BlindfoldProc ()
520 {
521     appData.blindfold = !appData.blindfold;
522     MARK_MENU_ITEM("Options.Blindfold", appData.blindfold);
523     DrawPosition(True, NULL);
524 }
525
526 void
527 TestLegalityProc ()
528 {
529     appData.testLegality = !appData.testLegality;
530     MARK_MENU_ITEM("Options.TestLegality", appData.testLegality);
531 }
532
533
534 void
535 FlashMovesProc ()
536 {
537     if (appData.flashCount == 0) {
538         appData.flashCount = 3;
539     } else {
540         appData.flashCount = -appData.flashCount;
541     }
542     MARK_MENU_ITEM("Options.FlashMoves", appData.flashCount > 0);
543 }
544
545 #if HIGHDRAG
546 void
547 HighlightDraggingProc ()
548 {
549     appData.highlightDragging = !appData.highlightDragging;
550     MARK_MENU_ITEM("Options.HighlightDragging", appData.highlightDragging);
551 }
552 #endif
553
554 void
555 HighlightLastMoveProc ()
556 {
557     appData.highlightLastMove = !appData.highlightLastMove;
558     MARK_MENU_ITEM("Options.HighlightLastMove", appData.highlightLastMove);
559 }
560
561 void
562 HighlightArrowProc ()
563 {
564     appData.highlightMoveWithArrow = !appData.highlightMoveWithArrow;
565     MARK_MENU_ITEM("Options.HighlightWithArrow", appData.highlightMoveWithArrow);
566 }
567
568 void
569 IcsAlarmProc ()
570 {
571     appData.icsAlarm = !appData.icsAlarm;
572 //    MARK_MENU_ITEM("Options.ICSAlarm", appData.icsAlarm);
573 }
574
575 void
576 MoveSoundProc ()
577 {
578     appData.ringBellAfterMoves = !appData.ringBellAfterMoves;
579     MARK_MENU_ITEM("Options.MoveSound", appData.ringBellAfterMoves);
580 }
581
582 void
583 OneClickProc ()
584 {
585     appData.oneClick = !appData.oneClick;
586     MARK_MENU_ITEM("Options.OneClickMoving", appData.oneClick);
587 }
588
589 void
590 PeriodicUpdatesProc ()
591 {
592     PeriodicUpdatesEvent(!appData.periodicUpdates);
593     MARK_MENU_ITEM("Options.PeriodicUpdates", appData.periodicUpdates);
594 }
595
596 void
597 PopupExitMessageProc ()
598 {
599     appData.popupExitMessage = !appData.popupExitMessage;
600     MARK_MENU_ITEM("Options.PopupExitMessage", appData.popupExitMessage);
601 }
602
603 void
604 PopupMoveErrorsProc ()
605 {
606     appData.popupMoveErrors = !appData.popupMoveErrors;
607     MARK_MENU_ITEM("Options.PopupMoveErrors", appData.popupMoveErrors);
608 }
609
610 void
611 PremoveProc ()
612 {
613     appData.premove = !appData.premove;
614 //    MARK_MENU_ITEM("Options.Premove", appData.premove);
615 }
616
617 void
618 ShowCoordsProc ()
619 {
620     appData.showCoords = !appData.showCoords;
621     MARK_MENU_ITEM("Options.ShowCoords", appData.showCoords);
622     DrawPosition(True, NULL);
623 }
624
625 void
626 ShowThinkingProc ()
627 {
628     appData.showThinking = !appData.showThinking; // [HGM] thinking: taken out of ShowThinkingEvent
629     ShowThinkingEvent();
630 }
631
632 void
633 HideThinkingProc ()
634 {
635   appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: taken out of ShowThinkingEvent
636   ShowThinkingEvent();
637
638   MARK_MENU_ITEM("Options.HideThinking", appData.hideThinkingFromHuman);
639 }
640
641 /*
642  *  Menu definition tables
643  */
644
645 MenuItem fileMenu[] = {
646     {N_("New Game        Ctrl+N"),        "NewGame", ResetGameEvent},
647     {N_("New Shuffle Game ..."),          "NewShuffleGame", ShuffleMenuProc},
648     {N_("New Variant ...   Alt+Shift+V"), "NewVariant", NewVariantProc},      // [HGM] variant: not functional yet
649     {"----", NULL, NothingProc},
650     {N_("Load Game       Ctrl+O"),        "LoadGame", LoadGameProc},
651     {N_("Load Position    Ctrl+Shift+O"), "LoadPosition", LoadPositionProc},
652 //    {N_("Load Next Game"), "LoadNextGame", LoadNextGameProc},
653 //    {N_("Load Previous Game"), "LoadPreviousGame", LoadPrevGameProc},
654 //    {N_("Reload Same Game"), "ReloadSameGame", ReloadGameProc},
655     {N_("Next Position     Shift+PgDn"), "LoadNextPosition", LoadNextPositionProc},
656     {N_("Prev Position     Shift+PgUp"), "LoadPreviousPosition", LoadPrevPositionProc},
657     {"----", NULL, NothingProc},
658 //    {N_("Reload Same Position"), "Reload Same Position", ReloadPositionProc},
659     {N_("Save Game       Ctrl+S"),        "SaveGame", SaveGameProc},
660     {N_("Save Position    Ctrl+Shift+S"), "SavePosition", SavePositionProc},
661     {"----", NULL, NothingProc},
662     {N_("Mail Move"),            "MailMove", MailMoveEvent},
663     {N_("Reload CMail Message"), "ReloadCMailMessage", ReloadCmailMsgProc},
664     {"----", NULL, NothingProc},
665     {N_("Quit                 Ctr+Q"), "Quit", QuitProc},
666     {NULL, NULL, NULL}
667 };
668
669 MenuItem editMenu[] = {
670     {N_("Copy Game    Ctrl+C"),        "CopyGame", CopyGameProc},
671     {N_("Copy Position Ctrl+Shift+C"), "CopyPosition", CopyPositionProc},
672     {N_("Copy Game List"),        "CopyGameList", CopyGameListProc},
673     {"----", NULL, NothingProc},
674     {N_("Paste Game    Ctrl+V"),        "PasteGame", PasteGameProc},
675     {N_("Paste Position Ctrl+Shift+V"), "PastePosition", PastePositionProc},
676     {"----", NULL, NothingProc},
677     {N_("Edit Game      Ctrl+E"),        "EditGame", EditGameEvent},
678     {N_("Edit Position   Ctrl+Shift+E"), "EditPosition", EditPositionEvent},
679     {N_("Edit Tags"),                    "EditTags", EditTagsProc},
680     {N_("Edit Comment"),                 "EditComment", EditCommentProc},
681     {N_("Edit Book"),                    "EditBook", EditBookEvent},
682     {"----", NULL, NothingProc},
683     {N_("Revert              Home"), "Revert", RevertProc},
684     {N_("Annotate"),                 "Annotate", AnnotateProc},
685     {N_("Truncate Game  End"),       "TruncateGame", TruncateGameEvent},
686     {"----", NULL, NothingProc},
687     {N_("Backward         Alt+Left"),   "Backward", BackwardEvent},
688     {N_("Forward           Alt+Right"), "Forward", ForwardEvent},
689     {N_("Back to Start     Alt+Home"),  "BacktoStart", ToStartEvent},
690     {N_("Forward to End Alt+End"),      "ForwardtoEnd", ToEndEvent},
691     {NULL, NULL, NULL}
692 };
693
694 MenuItem viewMenu[] = {
695     {N_("Flip View             F2"),         "FlipView", FlipViewProc},
696     {"----", NULL, NothingProc},
697     {N_("Engine Output      Alt+Shift+O"),   "EngineOutput", EngineOutputProc},
698     {N_("Move History       Alt+Shift+H"),   "MoveHistory", HistoryShowProc}, // [HGM] hist: activate 4.2.7 code
699     {N_("Evaluation Graph  Alt+Shift+E"),    "EvaluationGraph", EvalGraphProc},
700     {N_("Game List            Alt+Shift+G"), "GameList", ShowGameListProc},
701     {N_("ICS text menu"), "ICStextmenu", IcsTextProc},
702     {"----", NULL, NothingProc},
703     {N_("Tags"),             "Tags", EditTagsProc},
704     {N_("Comments"),         "Comments", EditCommentProc},
705     {N_("ICS Input Box"),    "ICSInputBox", IcsInputBoxProc},
706     {"----", NULL, NothingProc},
707     {N_("Board..."),          "Board", BoardOptionsProc},
708     {N_("Game List Tags..."), "GameListTags", GameListOptionsProc},
709     {NULL, NULL, NULL}
710 };
711
712 MenuItem modeMenu[] = {
713     {N_("Machine White  Ctrl+W"), "MachineWhite", MachineWhiteEvent},
714     {N_("Machine Black  Ctrl+B"), "MachineBlack", MachineBlackEvent},
715     {N_("Two Machines   Ctrl+T"), "TwoMachines", TwoMachinesEvent},
716     {N_("Analysis Mode  Ctrl+A"), "AnalysisMode", AnalyzeModeProc},
717     {N_("Analyze Game   Ctrl+G"), "AnalyzeFile", AnalyzeFileProc },
718     {N_("Edit Game         Ctrl+E"), "EditGame", EditGameEvent},
719     {N_("Edit Position      Ctrl+Shift+E"), "EditPosition", EditPositionEvent},
720     {N_("Training"),      "Training", TrainingEvent},
721     {N_("ICS Client"),    "ICSClient", IcsClientEvent},
722     {"----", NULL, NothingProc},
723     {N_("Machine Match"),         "MachineMatch", MatchProc},
724     {N_("Pause               Pause"),         "Pause", PauseEvent},
725     {NULL, NULL, NULL}
726 };
727
728 MenuItem actionMenu[] = {
729     {N_("Accept             F3"), "Accept", AcceptEvent},
730     {N_("Decline            F4"), "Decline", DeclineEvent},
731     {N_("Rematch           F12"), "Rematch", RematchEvent},
732     {"----", NULL, NothingProc},
733     {N_("Call Flag          F5"), "CallFlag", CallFlagEvent},
734     {N_("Draw                F6"), "Draw", DrawEvent},
735     {N_("Adjourn            F7"),  "Adjourn", AdjournEvent},
736     {N_("Abort                F8"),"Abort", AbortEvent},
737     {N_("Resign              F9"), "Resign", ResignEvent},
738     {"----", NULL, NothingProc},
739     {N_("Stop Observing  F10"), "StopObserving", StopObservingEvent},
740     {N_("Stop Examining  F11"), "StopExamining", StopExaminingEvent},
741     {N_("Upload to Examine"),   "UploadtoExamine", UploadGameEvent},
742     {"----", NULL, NothingProc},
743     {N_("Adjudicate to White"), "AdjudicatetoWhite", AdjuWhiteProc},
744     {N_("Adjudicate to Black"), "AdjudicatetoBlack", AdjuBlackProc},
745     {N_("Adjudicate Draw"),     "AdjudicateDraw", AdjuDrawProc},
746     {NULL, NULL, NULL}
747 };
748
749 MenuItem engineMenu[] = {
750     {N_("Load New 1st Engine ..."), "LoadEngine", LoadEngine1Proc},
751     {N_("Load New 2nd Engine ..."), "LoadEngine", LoadEngine2Proc},
752     {"----", NULL, NothingProc},
753     {N_("Engine #1 Settings ..."), "Engine#1Settings", FirstSettingsProc},
754     {N_("Engine #2 Settings ..."), "Engine#2Settings", SecondSettingsProc},
755     {"----", NULL, NothingProc},
756     {N_("Hint"), "Hint", HintEvent},
757     {N_("Book"), "Book", BookEvent},
758     {"----", NULL, NothingProc},
759     {N_("Move Now     Ctrl+M"),     "MoveNow", MoveNowEvent},
760     {N_("Retract Move  Ctrl+X"), "RetractMove", RetractMoveEvent},
761     {NULL, NULL, NULL}
762 };
763
764 MenuItem optionsMenu[] = {
765 #ifdef OPTIONSDIALOG
766     {N_("General ..."), "General", OptionsProc},
767 #endif
768     {N_("Time Control ...       Alt+Shift+T"), "TimeControl", TimeControlProc},
769     {N_("Common Engine ...  Alt+Shift+U"),     "CommonEngine", UciMenuProc},
770     {N_("Adjudications ...      Alt+Shift+J"), "Adjudications", EngineMenuProc},
771     {N_("ICS ..."),    "ICS", IcsOptionsProc},
772     {N_("Match ..."), "Match", MatchOptionsProc},
773     {N_("Load Game ..."),    "LoadGame", LoadOptionsProc},
774     {N_("Save Game ..."),    "SaveGame", SaveOptionsProc},
775 //    {N_(" ..."),    "", OptionsProc},
776     {N_("Game List ..."),    "GameList", GameListOptionsProc},
777     {N_("Sounds ..."),    "Sounds", SoundOptionsProc},
778     {"----", NULL, NothingProc},
779 #ifndef OPTIONSDIALOG
780     {N_("Always Queen        Ctrl+Shift+Q"),   "AlwaysQueen", AlwaysQueenProc},
781     {N_("Animate Dragging"), "AnimateDragging", AnimateDraggingProc},
782     {N_("Animate Moving      Ctrl+Shift+A"),   "AnimateMoving", AnimateMovingProc},
783     {N_("Auto Flag               Ctrl+Shift+F"), "AutoFlag", AutoflagProc},
784     {N_("Auto Flip View"),   "AutoFlipView", AutoflipProc},
785     {N_("Blindfold"),        "Blindfold", BlindfoldProc},
786     {N_("Flash Moves"),      "FlashMoves", FlashMovesProc},
787 #if HIGHDRAG
788     {N_("Highlight Dragging"),    "HighlightDragging", HighlightDraggingProc},
789 #endif
790     {N_("Highlight Last Move"),   "HighlightLastMove", HighlightLastMoveProc},
791     {N_("Highlight With Arrow"),  "HighlightWithArrow", HighlightArrowProc},
792     {N_("Move Sound"),            "MoveSound", MoveSoundProc},
793 //    {N_("ICS Alarm"),             "ICSAlarm", IcsAlarmProc},
794     {N_("One-Click Moving"),      "OneClickMoving", OneClickProc},
795     {N_("Periodic Updates"),      "PeriodicUpdates", PeriodicUpdatesProc},
796     {N_("Ponder Next Move  Ctrl+Shift+P"), "PonderNextMove", PonderNextMoveProc},
797     {N_("Popup Exit Message"),    "PopupExitMessage", PopupExitMessageProc},
798     {N_("Popup Move Errors"),     "PopupMoveErrors", PopupMoveErrorsProc},
799 //    {N_("Premove"),               "Premove", PremoveProc},
800     {N_("Show Coords"),           "ShowCoords", ShowCoordsProc},
801     {N_("Hide Thinking        Ctrl+Shift+H"),   "HideThinking", HideThinkingProc},
802     {N_("Test Legality          Ctrl+Shift+L"), "TestLegality", TestLegalityProc},
803     {"----", NULL, NothingProc},
804 #endif
805     {N_("Save Settings Now"),     "SaveSettingsNow", SaveSettingsProc},
806     {N_("Save Settings on Exit"), "SaveSettingsonExit", SaveOnExitProc},
807     {NULL, NULL, NULL}
808 };
809
810 MenuItem helpMenu[] = {
811     {N_("Info XBoard"),     "InfoXBoard", InfoProc},
812     {N_("Man XBoard   F1"), "ManXBoard", ManProc},
813     {"----", NULL, NothingProc},
814     {N_("XBoard Home Page"), "XBoardHomePage", HomePageProc},
815     {N_("On-line User Guide"), "On-lineUserGuide", GuideProc},
816     {N_("Development News"), "DevelopmentNews", NewsPageProc},
817     {N_("e-Mail Bug Report"), "e-MailBugReport", BugReportProc},
818     {"----", NULL, NothingProc},
819     {N_("About XBoard"), "AboutXBoard", AboutProc},
820     {NULL, NULL, NULL}
821 };
822
823 MenuItem noMenu[] = {
824     { "", "LoadNextGame", LoadNextGameProc },
825     { "", "LoadPrevGame", LoadPrevGameProc },
826     { "", "ReloadGame", ReloadGameProc },
827     { "", "ReloadPosition", ReloadPositionProc },
828 #ifndef OPTIONSDIALOG
829     { "", "AlwaysQueen", AlwaysQueenProc },
830     { "", "AnimateDragging", AnimateDraggingProc },
831     { "", "AnimateMoving", AnimateMovingProc },
832     { "", "Autoflag", AutoflagProc },
833     { "", "Autoflip", AutoflipProc },
834     { "", "Blindfold", BlindfoldProc },
835     { "", "FlashMoves", FlashMovesProc },
836 #if HIGHDRAG
837     { "", "HighlightDragging", HighlightDraggingProc },
838 #endif
839     { "", "HighlightLastMove", HighlightLastMoveProc },
840 //    { "", "IcsAlarm", IcsAlarmProc },
841     { "", "MoveSound", MoveSoundProc },
842     { "", "PeriodicUpdates", PeriodicUpdatesProc },
843     { "", "PopupExitMessage", PopupExitMessageProc },
844     { "", "PopupMoveErrors", PopupMoveErrorsProc },
845 //    { "", "Premove", PremoveProc },
846     { "", "ShowCoords", ShowCoordsProc },
847     { "", "ShowThinking", ShowThinkingProc },
848     { "", "HideThinking", HideThinkingProc },
849     { "", "TestLegality", TestLegalityProc },
850 #endif
851     { "", "AboutGame", AboutGameEvent },
852     { "", "Debug", DebugProc },
853     { "", "Nothing", NothingProc },
854     {NULL, NULL, NULL}
855 };
856
857 Menu menuBar[] = {
858     {N_("File"),    "File", fileMenu},
859     {N_("Edit"),    "Edit", editMenu},
860     {N_("View"),    "View", viewMenu},
861     {N_("Mode"),    "Mode", modeMenu},
862     {N_("Action"),  "Action", actionMenu},
863     {N_("Engine"),  "Engine", engineMenu},
864     {N_("Options"), "Options", optionsMenu},
865     {N_("Help"),    "Help", helpMenu},
866     {NULL, NULL, NULL}
867 };
868
869 MenuItem *
870 MenuNameToItem (char *menuName)
871 {
872     int i;
873     char buf[MSG_SIZ], *p;
874     MenuItem *menuTab;
875     static MenuItem a = { NULL, NULL, NothingProc };
876     extern Option mainOptions[];
877     safeStrCpy(buf, menuName, MSG_SIZ);
878     p = strchr(buf, '.');
879     if(!p) menuTab = noMenu; else {
880         *p++ = NULLCHAR;
881         for(i=0; menuBar[i].name; i++)
882             if(!strcmp(buf, menuBar[i].name)) break;
883         if(!menuBar[i].name) return NULL; // main menu not found
884         menuTab = menuBar[i].mi;
885     }
886     if(*p == NULLCHAR) { a.handle = mainOptions[i+1].handle; return &a; } // main menu bar
887     for(i=0; menuTab[i].string; i++)
888         if(menuTab[i].ref && !strcmp(p, menuTab[i].ref)) return menuTab + i;
889     return NULL; // item not found
890 }
891
892 void
893 AppendEnginesToMenu (char *list)
894 {
895     int i=0;
896     char *p;
897     if(appData.icsActive || appData.recentEngines <= 0) return;
898     recentEngines = strdup(list);
899     while (*list) {
900         p = strchr(list, '\n'); if(p == NULL) break;
901         if(i == 0) AppendMenuItem("----", 0); // at least one valid item to add
902         *p = 0;
903         AppendMenuItem(list, i);
904         i++; *p = '\n'; list = p + 1;
905     }
906 }
907
908 Enables icsEnables[] = {
909     { "File.MailMove", False },
910     { "File.ReloadCMailMessage", False },
911     { "Mode.MachineBlack", False },
912     { "Mode.MachineWhite", False },
913     { "Mode.AnalysisMode", False },
914     { "Mode.AnalyzeFile", False },
915     { "Mode.TwoMachines", False },
916     { "Mode.MachineMatch", False },
917 #ifndef ZIPPY
918     { "Engine.Hint", False },
919     { "Engine.Book", False },
920     { "Engine.MoveNow", False },
921 #ifndef OPTIONSDIALOG
922     { "PeriodicUpdates", False },
923     { "HideThinking", False },
924     { "PonderNextMove", False },
925 #endif
926 #endif
927     { "Engine.Engine#1Settings", False },
928     { "Engine.Engine#2Settings", False },
929     { "Engine.LoadEngine", False },
930     { "Edit.Annotate", False },
931     { "Options.Match", False },
932     { NULL, False }
933 };
934
935 Enables ncpEnables[] = {
936     { "File.MailMove", False },
937     { "File.ReloadCMailMessage", False },
938     { "Mode.MachineWhite", False },
939     { "Mode.MachineBlack", False },
940     { "Mode.AnalysisMode", False },
941     { "Mode.AnalyzeFile", False },
942     { "Mode.TwoMachines", False },
943     { "Mode.MachineMatch", False },
944     { "Mode.ICSClient", False },
945     { "View.ICStextmenu", False },
946     { "View.ICSInputBox", False },
947     { "Action.", False },
948     { "Edit.Revert", False },
949     { "Edit.Annotate", False },
950     { "Engine.Engine#1Settings", False },
951     { "Engine.Engine#2Settings", False },
952     { "Engine.MoveNow", False },
953     { "Engine.RetractMove", False },
954     { "Options.ICS", False },
955 #ifndef OPTIONSDIALOG
956     { "Options.AutoFlag", False },
957     { "Options.AutoFlip View", False },
958 //    { "Options.ICSAlarm", False },
959     { "Options.MoveSound", False },
960     { "Options.HideThinking", False },
961     { "Options.PeriodicUpdates", False },
962     { "Options.PonderNextMove", False },
963 #endif
964     { "Engine.Hint", False },
965     { "Engine.Book", False },
966     { NULL, False }
967 };
968
969 Enables gnuEnables[] = {
970     { "Mode.ICSClient", False },
971     { "View.ICStextmenu", False },
972     { "View.ICSInputBox", False },
973     { "Action.Accept", False },
974     { "Action.Decline", False },
975     { "Action.Rematch", False },
976     { "Action.Adjourn", False },
977     { "Action.StopExamining", False },
978     { "Action.StopObserving", False },
979     { "Action.UploadtoExamine", False },
980     { "Edit.Revert", False },
981     { "Edit.Annotate", False },
982     { "Options.ICS", False },
983
984     /* The next two options rely on SetCmailMode being called *after*    */
985     /* SetGNUMode so that when GNU is being used to give hints these     */
986     /* menu options are still available                                  */
987
988     { "File.MailMove", False },
989     { "File.ReloadCMailMessage", False },
990     // [HGM] The following have been added to make a switch from ncp to GNU mode possible
991     { "Mode.MachineWhite", True },
992     { "Mode.MachineBlack", True },
993     { "Mode.AnalysisMode", True },
994     { "Mode.AnalyzeFile", True },
995     { "Mode.TwoMachines", True },
996     { "Mode.MachineMatch", True },
997     { "Engine.Engine#1Settings", True },
998     { "Engine.Engine#2Settings", True },
999     { "Engine.Hint", True },
1000     { "Engine.Book", True },
1001     { "Engine.MoveNow", True },
1002     { "Engine.RetractMove", True },
1003     { "Action.", True },
1004     { NULL, False }
1005 };
1006
1007 Enables cmailEnables[] = {
1008     { "Action.", True },
1009     { "Action.CallFlag", False },
1010     { "Action.Draw", True },
1011     { "Action.Adjourn", False },
1012     { "Action.Abort", False },
1013     { "Action.StopObserving", False },
1014     { "Action.StopExamining", False },
1015     { "File.MailMove", True },
1016     { "File.ReloadCMailMessage", True },
1017     { NULL, False }
1018 };
1019
1020 Enables trainingOnEnables[] = {
1021   { "Edit.EditComment", False },
1022   { "Mode.Pause", False },
1023   { "Edit.Forward", False },
1024   { "Edit.Backward", False },
1025   { "Edit.ForwardtoEnd", False },
1026   { "Edit.BacktoStart", False },
1027   { "Engine.MoveNow", False },
1028   { "Edit.TruncateGame", False },
1029   { NULL, False }
1030 };
1031
1032 Enables trainingOffEnables[] = {
1033   { "Edit.EditComment", True },
1034   { "Mode.Pause", True },
1035   { "Edit.Forward", True },
1036   { "Edit.Backward", True },
1037   { "Edit.ForwardtoEnd", True },
1038   { "Edit.BacktoStart", True },
1039   { "Engine.MoveNow", True },
1040   { "Engine.TruncateGame", True },
1041   { NULL, False }
1042 };
1043
1044 Enables machineThinkingEnables[] = {
1045   { "File.LoadGame", False },
1046 //  { "LoadNextGame", False },
1047 //  { "LoadPreviousGame", False },
1048 //  { "ReloadSameGame", False },
1049   { "Edit.PasteGame", False },
1050   { "File.LoadPosition", False },
1051 //  { "LoadNextPosition", False },
1052 //  { "LoadPreviousPosition", False },
1053 //  { "ReloadSamePosition", False },
1054   { "Edit.PastePosition", False },
1055   { "Mode.MachineWhite", False },
1056   { "Mode.MachineBlack", False },
1057   { "Mode.TwoMachines", False },
1058 //  { "MachineMatch", False },
1059   { "Engine.RetractMove", False },
1060   { NULL, False }
1061 };
1062
1063 Enables userThinkingEnables[] = {
1064   { "File.LoadGame", True },
1065 //  { "LoadNextGame", True },
1066 //  { "LoadPreviousGame", True },
1067 //  { "ReloadSameGame", True },
1068   { "Edit.PasteGame", True },
1069   { "File.LoadPosition", True },
1070 //  { "LoadNextPosition", True },
1071 //  { "LoadPreviousPosition", True },
1072 //  { "ReloadSamePosition", True },
1073   { "Edit.PastePosition", True },
1074   { "Mode.MachineWhite", True },
1075   { "Mode.MachineBlack", True },
1076   { "Mode.TwoMachines", True },
1077 //  { "MachineMatch", True },
1078   { "Engine.RetractMove", True },
1079   { NULL, False }
1080 };
1081
1082 void
1083 SetICSMode ()
1084 {
1085   SetMenuEnables(icsEnables);
1086
1087 #if ZIPPY
1088   if (appData.zippyPlay && !appData.noChessProgram) { /* [DM] icsEngineAnalyze */
1089      EnableMenuItem("Analysis Mode", True);
1090      EnableMenuItem("Engine #1 Settings", True);
1091   }
1092 #endif
1093 }
1094
1095 void
1096 SetNCPMode ()
1097 {
1098   SetMenuEnables(ncpEnables);
1099 }
1100
1101 void
1102 SetGNUMode ()
1103 {
1104   SetMenuEnables(gnuEnables);
1105 }
1106
1107 void
1108 SetCmailMode ()
1109 {
1110   SetMenuEnables(cmailEnables);
1111 }
1112
1113 void
1114 SetTrainingModeOn ()
1115 {
1116   SetMenuEnables(trainingOnEnables);
1117   if (appData.showButtonBar) {
1118     EnableButtonBar(False);
1119   }
1120   CommentPopDown();
1121 }
1122
1123 void
1124 SetTrainingModeOff ()
1125 {
1126   SetMenuEnables(trainingOffEnables);
1127   if (appData.showButtonBar) {
1128     EnableButtonBar(True);
1129   }
1130 }
1131
1132 void
1133 SetUserThinkingEnables ()
1134 {
1135   if (appData.noChessProgram) return;
1136   SetMenuEnables(userThinkingEnables);
1137 }
1138
1139 void
1140 SetMachineThinkingEnables ()
1141 {
1142   if (appData.noChessProgram) return;
1143   SetMenuEnables(machineThinkingEnables);
1144   switch (gameMode) {
1145   case MachinePlaysBlack:
1146   case MachinePlaysWhite:
1147   case TwoMachinesPlay:
1148     EnableMenuItem(ModeToWidgetName(gameMode), True);
1149     break;
1150   default:
1151     break;
1152   }
1153 }
1154
1155 void
1156 GreyRevert (Boolean grey)
1157 {
1158     MarkMenuItem("Edit.Revert", !grey);
1159     MarkMenuItem("Edit.Annotate", !grey);
1160 }
1161
1162 char *
1163 ModeToWidgetName (GameMode mode)
1164 {
1165     switch (mode) {
1166       case BeginningOfGame:
1167         if (appData.icsActive)
1168           return "Mode.ICSClient";
1169         else if (appData.noChessProgram ||
1170                  *appData.cmailGameName != NULLCHAR)
1171           return "Mode.EditGame";
1172         else
1173           return "Mode.MachineBlack";
1174       case MachinePlaysBlack:
1175         return "Mode.MachineBlack";
1176       case MachinePlaysWhite:
1177         return "Mode.MachineWhite";
1178       case AnalyzeMode:
1179         return "Mode.AnalysisMode";
1180       case AnalyzeFile:
1181         return "Mode.AnalyzeFile";
1182       case TwoMachinesPlay:
1183         return "Mode.TwoMachines";
1184       case EditGame:
1185         return "Mode.EditGame";
1186       case PlayFromGameFile:
1187         return "File.LoadGame";
1188       case EditPosition:
1189         return "Mode.EditPosition";
1190       case Training:
1191         return "Mode.Training";
1192       case IcsPlayingWhite:
1193       case IcsPlayingBlack:
1194       case IcsObserving:
1195       case IcsIdle:
1196       case IcsExamining:
1197         return "Mode.ICSClient";
1198       default:
1199       case EndOfGame:
1200         return NULL;
1201     }
1202 }
1203
1204 void
1205 InitMenuMarkers()
1206 {
1207 #ifndef OPTIONSDIALOG
1208     if (appData.alwaysPromoteToQueen) {
1209         MarkMenuItem("Options.Always Queen", True);
1210     }
1211     if (appData.animateDragging) {
1212         MarkMenuItem("Options.Animate Dragging", True);
1213     }
1214     if (appData.animate) {
1215         MarkMenuItem("Options.Animate Moving", True);
1216     }
1217     if (appData.autoCallFlag) {
1218         MarkMenuItem("Options.Auto Flag", True);
1219     }
1220     if (appData.autoFlipView) {
1221         XtSetValues(XtNameToWidget(menuBarWidget,"Options.Auto Flip View", True);
1222     }
1223     if (appData.blindfold) {
1224         MarkMenuItem("Options.Blindfold", True);
1225     }
1226     if (appData.flashCount > 0) {
1227         MarkMenuItem("Options.Flash Moves", True);
1228     }
1229 #if HIGHDRAG
1230     if (appData.highlightDragging) {
1231         MarkMenuItem("Options.Highlight Dragging", True);
1232     }
1233 #endif
1234     if (appData.highlightLastMove) {
1235         MarkMenuItem("Options.Highlight Last Move", True);
1236     }
1237     if (appData.highlightMoveWithArrow) {
1238         MarkMenuItem("Options.Arrow", True);
1239     }
1240 //    if (appData.icsAlarm) {
1241 //      MarkMenuItem("Options.ICS Alarm", True);
1242 //    }
1243     if (appData.ringBellAfterMoves) {
1244         MarkMenuItem("Options.Move Sound", True);
1245     }
1246     if (appData.oneClick) {
1247         MarkMenuItem("Options.OneClick", True);
1248     }
1249     if (appData.periodicUpdates) {
1250         MarkMenuItem("Options.Periodic Updates", True);
1251     }
1252     if (appData.ponderNextMove) {
1253         MarkMenuItem("Options.Ponder Next Move", True);
1254     }
1255     if (appData.popupExitMessage) {
1256         MarkMenuItem("Options.Popup Exit Message", True);
1257     }
1258     if (appData.popupMoveErrors) {
1259         MarkMenuItem("Options.Popup Move Errors", True);
1260     }
1261 //    if (appData.premove) {
1262 //      MarkMenuItem("Options.Premove", True);
1263 //    }
1264     if (appData.showCoords) {
1265         MarkMenuItem("Options.Show Coords", True);
1266     }
1267     if (appData.hideThinkingFromHuman) {
1268         MarkMenuItem("Options.Hide Thinking", True);
1269     }
1270     if (appData.testLegality) {
1271         MarkMenuItem("Options.Test Legality", True);
1272     }
1273 #endif
1274     if (saveSettingsOnExit) {
1275         MarkMenuItem("Options.SaveSettingsonExit", True);
1276     }
1277 }
1278
1279