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