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