Make generic XBoard popup, and implement 2 dialogs
[xboard.git] / xboard.c
index 94133b9..1b95e50 100644 (file)
--- a/xboard.c
+++ b/xboard.c
@@ -5,7 +5,7 @@
  * Massachusetts.
  *
  * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
- * 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+ * 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
  *
  * The following terms apply to Digital Equipment Corporation's copyright
  * interest in XBoard:
@@ -60,6 +60,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <pwd.h>
+#include <math.h>
 
 #if !OMIT_SOCKETS
 # if HAVE_SYS_SOCKET_H
@@ -391,28 +392,21 @@ void AnimateDraggingProc P((Widget w, XEvent *event, String *prms,
                         Cardinal *nprms));
 void AnimateMovingProc P((Widget w, XEvent *event, String *prms,
                         Cardinal *nprms));
-void AutocommProc P((Widget w, XEvent *event, String *prms,
-                    Cardinal *nprms));
 void AutoflagProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void AutoflipProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
-void AutobsProc P((Widget w, XEvent *event, String *prms,
-                       Cardinal *nprms));
-void AutoraiseProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
-void AutosaveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void BlindfoldProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void FlashMovesProc P((Widget w, XEvent *event, String *prms,
                       Cardinal *nprms));
 void FlipViewProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
-void GetMoveListProc P((Widget w, XEvent *event, String *prms,
-                       Cardinal *nprms));
 void HighlightDraggingProc P((Widget w, XEvent *event, String *prms,
                              Cardinal *nprms));
 void HighlightLastMoveProc P((Widget w, XEvent *event, String *prms,
                              Cardinal *nprms));
+void HighlightArrowProc P((Widget w, XEvent *event, String *prms,
+                             Cardinal *nprms));
 void MoveSoundProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
-void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
-void OldSaveStyleProc P((Widget w, XEvent *event, String *prms,
-                        Cardinal *nprms));
+//void IcsAlarmProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void OneClickProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void PeriodicUpdatesProc P((Widget w, XEvent *event, String *prms,
                         Cardinal *nprms));
 void PonderNextMoveProc P((Widget w, XEvent *event, String *prms,
@@ -421,8 +415,7 @@ void PopupMoveErrorsProc P((Widget w, XEvent *event, String *prms,
                        Cardinal *nprms));
 void PopupExitMessageProc P((Widget w, XEvent *event, String *prms,
                             Cardinal *nprms));
-void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
-void QuietPlayProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+//void PremoveProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void ShowCoordsProc P((Widget w, XEvent *event, String *prms,
                       Cardinal *nprms));
 void ShowThinkingProc P((Widget w, XEvent *event, String *prms,
@@ -461,6 +454,8 @@ void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void GameListOptionsPopUp P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void LoadOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void SaveOptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void GameListOptionsPopDown P(());
 void ShufflePopDown P(());
 void EnginePopDown P(());
@@ -471,6 +466,9 @@ void SettingsPopDown P(());
 void update_ics_width P(());
 int get_term_width P(());
 int CopyMemoProc P(());
+void DrawArrowHighlight P((int fromX, int fromY, int toX,int toY));
+Boolean IsDrawArrowEnabled P(());
+
 /*
 * XBoard depends on Xt R4 or higher
 */
@@ -601,9 +599,9 @@ MenuItem fileMenu[] = {
 //    {N_("Load Next Game"), "Load Next Game", LoadNextGameProc},
 //    {N_("Load Previous Game"), "Load Previous Game", LoadPrevGameProc},
 //    {N_("Reload Same Game"), "Reload Same Game", ReloadGameProc},
+    {N_("Next Position     Shift+PgDn"), "Load Next Position", LoadNextPositionProc},
+    {N_("Prev Position     Shift+PgUp"), "Load Previous Position", LoadPrevPositionProc},
     {"----", NULL, NothingProc},
-//    {N_("Load Next Position"), "Load Next Position", LoadNextPositionProc},
-//    {N_("Load Previous Position"), "Load Previous Position", LoadPrevPositionProc},
 //    {N_("Reload Same Position"), "Reload Same Position", ReloadPositionProc},
     {N_("Save Game       Ctrl+S"),        "Save Game", SaveGameProc},
     {N_("Save Position    Ctrl+Shift+S"), "Save Position", SavePositionProc},
@@ -704,33 +702,31 @@ MenuItem optionsMenu[] = {
     {N_("Time Control ...       Alt+Shift+T"), "Time Control", TimeControlProc},
     {N_("Common Engine ...  Alt+Shift+U"),     "Common Engine", UciMenuProc},
     {N_("Adjudications ...      Alt+Shift+J"), "Adjudications", EngineMenuProc},
+    {N_("Load Game ..."),    "Load Game", LoadOptionsProc},
+    {N_("Save Game ..."),    "Save Game", SaveOptionsProc},
+//    {N_(" ..."),    "", OptionsProc},
     {N_("Game List ..."),    "Game List", GameListOptionsPopUp},
     {"----", NULL, NothingProc},
     {N_("Always Queen        Ctrl+Shift+Q"),   "Always Queen", AlwaysQueenProc},
     {N_("Animate Dragging"), "Animate Dragging", AnimateDraggingProc},
     {N_("Animate Moving      Ctrl+Shift+A"),   "Animate Moving", AnimateMovingProc},
-    {N_("Auto Comment"),     "Auto Comment", AutocommProc},
     {N_("Auto Flag               Ctrl+Shift+F"), "Auto Flag", AutoflagProc},
     {N_("Auto Flip View"),   "Auto Flip View", AutoflipProc},
-    {N_("Auto Observe"),     "Auto Observe", AutobsProc},
-    {N_("Auto Raise Board"), "Auto Raise Board", AutoraiseProc},
-    {N_("Auto Save"),        "Auto Save", AutosaveProc},
     {N_("Blindfold"),        "Blindfold", BlindfoldProc},
     {N_("Flash Moves"),      "Flash Moves", FlashMovesProc},
-    {N_("Get Move List"),    "Get Move List", GetMoveListProc},
 #if HIGHDRAG
     {N_("Highlight Dragging"),    "Highlight Dragging", HighlightDraggingProc},
 #endif
     {N_("Highlight Last Move"),   "Highlight Last Move", HighlightLastMoveProc},
+    {N_("Highlight With Arrow"),  "Arrow", HighlightArrowProc},
     {N_("Move Sound"),            "Move Sound", MoveSoundProc},
-    {N_("ICS Alarm"),             "ICS Alarm", IcsAlarmProc},
-    {N_("Old Save Style"),        "Old Save Style", OldSaveStyleProc},
+//    {N_("ICS Alarm"),             "ICS Alarm", IcsAlarmProc},
+    {N_("One-Click Moving"),      "OneClick", OneClickProc},
     {N_("Periodic Updates"),      "Periodic Updates", PeriodicUpdatesProc},
     {N_("Ponder Next Move  Ctrl+Shift+P"), "Ponder Next Move", PonderNextMoveProc},
     {N_("Popup Exit Message"),    "Popup Exit Message", PopupExitMessageProc},
     {N_("Popup Move Errors"),     "Popup Move Errors", PopupMoveErrorsProc},
-    {N_("Premove"),               "Premove", PremoveProc},
-    {N_("Quiet Play"),            "Quiet Play", QuietPlayProc},
+//    {N_("Premove"),               "Premove", PremoveProc},
     {N_("Show Coords"),           "Show Coords", ShowCoordsProc},
     {N_("Hide Thinking        Ctrl+Shift+H"),   "Hide Thinking", HideThinkingProc},
     {N_("Test Legality          Ctrl+Shift+L"), "Test Legality", TestLegalityProc},
@@ -922,7 +918,6 @@ XtActionsRec boardActions[] = {
     { "ShowMoveListProc", HistoryShowProc},
     { "EditTagsProc", EditCommentProc },
     { "EditCommentProc", EditCommentProc },
-    { "IcsAlarmProc", IcsAlarmProc },
     { "IcsInputBoxProc", IcsInputBoxProc },
     { "PauseProc", PauseProc },
     { "AcceptProc", AcceptProc },
@@ -959,26 +954,20 @@ XtActionsRec boardActions[] = {
     { "AnimateMovingProc", AnimateMovingProc },
     { "AutoflagProc", AutoflagProc },
     { "AutoflipProc", AutoflipProc },
-    { "AutobsProc", AutobsProc },
-    { "AutoraiseProc", AutoraiseProc },
-    { "AutosaveProc", AutosaveProc },
     { "BlindfoldProc", BlindfoldProc },
     { "FlashMovesProc", FlashMovesProc },
     { "FlipViewProc", FlipViewProc },
-    { "GetMoveListProc", GetMoveListProc },
 #if HIGHDRAG
     { "HighlightDraggingProc", HighlightDraggingProc },
 #endif
     { "HighlightLastMoveProc", HighlightLastMoveProc },
-    { "IcsAlarmProc", IcsAlarmProc },
+//    { "IcsAlarmProc", IcsAlarmProc },
     { "MoveSoundProc", MoveSoundProc },
-    { "OldSaveStyleProc", OldSaveStyleProc },
     { "PeriodicUpdatesProc", PeriodicUpdatesProc },
     { "PonderNextMoveProc", PonderNextMoveProc },
     { "PopupExitMessageProc", PopupExitMessageProc },
     { "PopupMoveErrorsProc", PopupMoveErrorsProc },
-    { "PremoveProc", PremoveProc },
-    { "QuietPlayProc", QuietPlayProc },
+//    { "PremoveProc", PremoveProc },
     { "ShowCoordsProc", ShowCoordsProc },
     { "ShowThinkingProc", ShowThinkingProc },
     { "HideThinkingProc", HideThinkingProc },
@@ -1027,8 +1016,8 @@ char globalTranslations[] =
    :Ctrl<Key>c: CopyGameProc() \n \
    :Ctrl<Key>v: PasteGameProc() \n \
    :Ctrl<Key>O: LoadPositionProc() \n \
-   :Shift Meta<Key>Next: LoadNextPositionProc() \n \
-   :Shift Meta<Key>Prior: LoadPrevPositionProc() \n \
+   :Shift<Key>Next: LoadNextPositionProc() \n \
+   :Shift<Key>Prior: LoadPrevPositionProc() \n \
    :Ctrl<Key>S: SavePositionProc() \n \
    :Ctrl<Key>C: CopyPositionProc() \n \
    :Ctrl<Key>V: PastePositionProc() \n \
@@ -1475,7 +1464,7 @@ void
 SaveFontArg(FILE *f, ArgDescriptor *ad)
 {
   char *name;
-  int i, n = (int)ad->argLoc;
+  int i, n = (int)(intptr_t)ad->argLoc;
   switch(n) {
     case 0: // CLOCK_FONT
        name = appData.clockFont;
@@ -1507,14 +1496,14 @@ ExportSounds()
 void
 SaveAttribsArg(FILE *f, ArgDescriptor *ad)
 {      // here the "argLoc" defines a table index. It could have contained the 'ta' pointer itself, though
-       fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, (&appData.colorShout)[(int)ad->argLoc]);
+       fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, (&appData.colorShout)[(int)(intptr_t)ad->argLoc]);
 }
 
 void
 SaveColor(FILE *f, ArgDescriptor *ad)
 {      // in WinBoard the color is an int and has to be converted to text. In X it would be a string already?
-       if(colorVariable[(int)ad->argLoc])
-       fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, *(char**)colorVariable[(int)ad->argLoc]);
+       if(colorVariable[(int)(intptr_t)ad->argLoc])
+       fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, *(char**)colorVariable[(int)(intptr_t)ad->argLoc]);
 }
 
 void
@@ -2404,10 +2393,6 @@ XBoard square size (hint): %d\n\
        XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"),
                    args, 1);
     }
-    if (appData.autoComment) {
-       XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
-                   args, 1);
-    }
     if (appData.autoCallFlag) {
        XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"),
                    args, 1);
@@ -2416,26 +2401,6 @@ XBoard square size (hint): %d\n\
        XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"),
                    args, 1);
     }
-    if (appData.autoObserve) {
-       XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
-                   args, 1);
-    }
-    if (appData.autoRaiseBoard) {
-       XtSetValues(XtNameToWidget(menuBarWidget,
-                                  "menuOptions.Auto Raise Board"), args, 1);
-    }
-    if (appData.autoSaveGames) {
-       XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
-                   args, 1);
-    }
-    if (appData.saveGameFile[0] != NULLCHAR) {
-       /* Can't turn this off from menu */
-       XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
-                   args, 1);
-       XtSetSensitive(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
-                      False);
-
-    }
     if (appData.blindfold) {
        XtSetValues(XtNameToWidget(menuBarWidget,
                                   "menuOptions.Blindfold"), args, 1);
@@ -2445,10 +2410,6 @@ XBoard square size (hint): %d\n\
                                   "menuOptions.Flash Moves"),
                    args, 1);
     }
-    if (appData.getMoveList) {
-       XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
-                   args, 1);
-    }
 #if HIGHDRAG
     if (appData.highlightDragging) {
        XtSetValues(XtNameToWidget(menuBarWidget,
@@ -2461,17 +2422,22 @@ XBoard square size (hint): %d\n\
                                   "menuOptions.Highlight Last Move"),
                    args, 1);
     }
-    if (appData.icsAlarm) {
-       XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
+    if (appData.highlightMoveWithArrow) {
+       XtSetValues(XtNameToWidget(menuBarWidget,
+                                  "menuOptions.Arrow"),
                    args, 1);
     }
+//    if (appData.icsAlarm) {
+//     XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"),
+//                 args, 1);
+//    }
     if (appData.ringBellAfterMoves) {
        XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"),
                    args, 1);
     }
-    if (appData.oldSaveStyle) {
+    if (appData.oneClick) {
        XtSetValues(XtNameToWidget(menuBarWidget,
-                                  "menuOptions.Old Save Style"), args, 1);
+                                  "menuOptions.OneClick"), args, 1);
     }
     if (appData.periodicUpdates) {
        XtSetValues(XtNameToWidget(menuBarWidget,
@@ -2489,14 +2455,10 @@ XBoard square size (hint): %d\n\
        XtSetValues(XtNameToWidget(menuBarWidget,
                                   "menuOptions.Popup Move Errors"), args, 1);
     }
-    if (appData.premove) {
-       XtSetValues(XtNameToWidget(menuBarWidget,
-                                  "menuOptions.Premove"), args, 1);
-    }
-    if (appData.quietPlay) {
-       XtSetValues(XtNameToWidget(menuBarWidget,
-                                  "menuOptions.Quiet Play"), args, 1);
-    }
+//    if (appData.premove) {
+//     XtSetValues(XtNameToWidget(menuBarWidget,
+//                                "menuOptions.Premove"), args, 1);
+//    }
     if (appData.showCoords) {
        XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"),
                    args, 1);
@@ -2799,15 +2761,10 @@ Enables ncpEnables[] = {
     { "menuEngine.Engine #2 Settings", False },
     { "menuEngine.Move Now", False },
     { "menuEngine.Retract Move", False },
-    { "menuOptions.Auto Comment", False },
     { "menuOptions.Auto Flag", False },
     { "menuOptions.Auto Flip View", False },
-    { "menuOptions.Auto Observe", False },
-    { "menuOptions.Auto Raise Board", False },
-    { "menuOptions.Get Move List", False },
-    { "menuOptions.ICS Alarm", False },
+//    { "menuOptions.ICS Alarm", False },
     { "menuOptions.Move Sound", False },
-    { "menuOptions.Quiet Play", False },
     { "menuOptions.Hide Thinking", False },
     { "menuOptions.Periodic Updates", False },
     { "menuOptions.Ponder Next Move", False },
@@ -2828,12 +2785,6 @@ Enables gnuEnables[] = {
     { "menuAction.Upload to Examine", False },
     { "menuEdit.Revert", False },
     { "menuEdit.Annotate", False },
-    { "menuOptions.Auto Comment", False },
-    { "menuOptions.Auto Observe", False },
-    { "menuOptions.Auto Raise Board", False },
-    { "menuOptions.Get Move List", False },
-    { "menuOptions.Premove", False },
-    { "menuOptions.Quiet Play", False },
 
     /* The next two options rely on SetCmailMode being called *after*    */
     /* SetGNUMode so that when GNU is being used to give hints these     */
@@ -2989,50 +2940,50 @@ SetMachineThinkingEnables()
 }
 
 // [HGM] code borrowed from winboard.c (which should thus go to backend.c!)
-#define HISTORY_SIZE 64\r
-static char *history[HISTORY_SIZE];\r
-int histIn = 0, histP = 0;\r
-\r
-void\r
-SaveInHistory(char *cmd)\r
-{\r
-  if (history[histIn] != NULL) {\r
-    free(history[histIn]);\r
-    history[histIn] = NULL;\r
-  }\r
-  if (*cmd == NULLCHAR) return;\r
-  history[histIn] = StrSave(cmd);\r
-  histIn = (histIn + 1) % HISTORY_SIZE;\r
-  if (history[histIn] != NULL) {\r
-    free(history[histIn]);\r
-    history[histIn] = NULL;\r
-  }\r
-  histP = histIn;\r
-}\r
-\r
-char *\r
-PrevInHistory(char *cmd)\r
-{\r
-  int newhp;\r
-  if (histP == histIn) {\r
-    if (history[histIn] != NULL) free(history[histIn]);\r
-    history[histIn] = StrSave(cmd);\r
-  }\r
-  newhp = (histP - 1 + HISTORY_SIZE) % HISTORY_SIZE;\r
-  if (newhp == histIn || history[newhp] == NULL) return NULL;\r
-  histP = newhp;\r
-  return history[histP];\r
-}\r
-\r
-char *\r
-NextInHistory()\r
-{\r
-  if (histP == histIn) return NULL;\r
-  histP = (histP + 1) % HISTORY_SIZE;\r
-  return history[histP];   \r
-}
-// end of borrowed code\r
-\r
+#define HISTORY_SIZE 64
+static char *history[HISTORY_SIZE];
+int histIn = 0, histP = 0;
+
+void
+SaveInHistory(char *cmd)
+{
+  if (history[histIn] != NULL) {
+    free(history[histIn]);
+    history[histIn] = NULL;
+  }
+  if (*cmd == NULLCHAR) return;
+  history[histIn] = StrSave(cmd);
+  histIn = (histIn + 1) % HISTORY_SIZE;
+  if (history[histIn] != NULL) {
+    free(history[histIn]);
+    history[histIn] = NULL;
+  }
+  histP = histIn;
+}
+
+char *
+PrevInHistory(char *cmd)
+{
+  int newhp;
+  if (histP == histIn) {
+    if (history[histIn] != NULL) free(history[histIn]);
+    history[histIn] = StrSave(cmd);
+  }
+  newhp = (histP - 1 + HISTORY_SIZE) % HISTORY_SIZE;
+  if (newhp == histIn || history[newhp] == NULL) return NULL;
+  histP = newhp;
+  return history[histP];
+}
+
+char *
+NextInHistory()
+{
+  if (histP == histIn) return NULL;
+  histP = (histP + 1) % HISTORY_SIZE;
+  return history[histP];   
+}
+// end of borrowed code
+
 #define Abs(n) ((n)<0 ? -(n) : (n))
 
 /*
@@ -3289,6 +3240,8 @@ void loadXIM(xim, xmask, filename, dest, mask)
        }
     }
 
+    fclose(fp);
+
     /* create Pixmap of piece */
     *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
                          w, h, xim->depth);
@@ -3945,11 +3898,7 @@ void WhiteClock(w, event, prms, nprms)
      String *prms;
      Cardinal *nprms;
 {
-    if (gameMode == EditPosition || gameMode == IcsExamining) {
-       SetWhiteToPlayEvent();
-    } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
-       CallFlagEvent();
-    }
+    ClockClick(0);
 }
 
 void BlackClock(w, event, prms, nprms)
@@ -3958,11 +3907,7 @@ void BlackClock(w, event, prms, nprms)
      String *prms;
      Cardinal *nprms;
 {
-    if (gameMode == EditPosition || gameMode == IcsExamining) {
-       SetBlackToPlayEvent();
-    } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
-       CallFlagEvent();
-    }
+    ClockClick(1);
 }
 
 
@@ -4259,7 +4204,7 @@ static void colorDrawPieceImage(piece, square_color, x, y, dest)
        }
        break;
     }
-    if(appData.upsideDown && flipView) kind ^= 2; // swap white and black pieces
+    if(appData.upsideDown && flipView) { kind ^= 2; p += p < BlackPawn ? BlackPawn : -BlackPawn; }// swap white and black pieces
     if(useTexture & square_color+1) {
         BlankSquare(x, y, square_color, piece, dest, 1); // erase previous contents with background
        XSetClipMask(xDisplay, wlPieceGC, xpmMask[p]);
@@ -4455,7 +4400,7 @@ void EventProc(widget, unused, event)
        }
        break;
       case MotionNotify:
-        if(SeekGraphClick(Press, event->xbutton.x, event->xbutton.y, 1)) break;\r
+        if(SeekGraphClick(Press, event->xbutton.x, event->xbutton.y, 1)) break;
       default:
        return;
     }
@@ -4603,6 +4548,10 @@ void XDrawPosition(w, repaint, board)
 
     if (!repaint && lastBoardValid[nr] && (nr == 1 || lastFlipView == flipView)) {
 
+       if ( lineGap && IsDrawArrowEnabled())
+           XDrawSegments(xDisplay, xBoardWindow, lineGC,
+                       gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
+
        /* If too much changes (begin observing new game, etc.), don't
           do flashing */
        do_flash = too_many_diffs(board, lastBoard[nr]) ? 0 : 1;
@@ -4665,6 +4614,7 @@ void XDrawPosition(w, repaint, board)
     if (hi2X >= 0 && hi2Y >= 0) {
       drawHighlight(hi2X, hi2Y, highlineGC);
     }
+    DrawArrowHighlight(hi1X, hi1Y, hi2X, hi2Y);
   }
     /* If piece being dragged around board, must redraw that too */
     DrawDragPiece();
@@ -4976,9 +4926,9 @@ Widget MiscCreate(name, text, mutable, callback, lines)
     XTranslateCoordinates(xDisplay, XtWindow(shellWidget),
                          RootWindowOfScreen(XtScreen(shellWidget)),
                          (bw_width - w) / 2, 0 - h / 2, &xx, &yy, &junk);
-#endif /*!NOTDEF*/
     x = xx;
     y = yy;
+#endif /*!NOTDEF*/
     if (y < 0) y = 0; /*avoid positioning top offscreen*/
 
     j = 0;
@@ -5357,6 +5307,16 @@ void PromotionPopUp()
                                   layout, args, j);
 
   if(gameInfo.variant != VariantShogi) {
+   if(gameInfo.variant == VariantSpartan && !WhiteOnMove(currentMove)) {
+      XawDialogAddButton(dialog, _("Warlord"), PromotionCallback,
+                        (XtPointer) dialog);
+      XawDialogAddButton(dialog, _("General"), PromotionCallback,
+                        (XtPointer) dialog);
+      XawDialogAddButton(dialog, _("Lieutenant"), PromotionCallback,
+                        (XtPointer) dialog);
+      XawDialogAddButton(dialog, _("Captain"), PromotionCallback,
+                        (XtPointer) dialog);
+    } else {\r
     XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
                       (XtPointer) dialog);
     XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
@@ -5365,7 +5325,9 @@ void PromotionPopUp()
                       (XtPointer) dialog);
     XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
                       (XtPointer) dialog);
+    }
     if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
+        gameInfo.variant == VariantSpartan && !WhiteOnMove(currentMove) ||\r
         gameInfo.variant == VariantGiveaway) {
       XawDialogAddButton(dialog, _("King"), PromotionCallback,
                         (XtPointer) dialog);
@@ -5929,6 +5891,7 @@ SendGameSelection(Widget w, Atom *selection, Atom *target,
     rewind(f);
     selection_tmp = XtMalloc(len + 1);
     count = fread(selection_tmp, 1, len, f);
+    fclose(f);
     if (len != count) {
       XtFree(selection_tmp);
       return False;
@@ -6536,26 +6499,6 @@ void AnimateMovingProc(w, event, prms, nprms)
                args, 1);
 }
 
-void AutocommProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
-{
-    Arg args[16];
-
-    appData.autoComment = !appData.autoComment;
-
-    if (appData.autoComment) {
-       XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
-    } else {
-       XtSetArg(args[0], XtNleftBitmap, None);
-    }
-    XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Comment"),
-               args, 1);
-}
-
-
 void AutoflagProc(w, event, prms, nprms)
      Widget w;
      XEvent *event;
@@ -6594,63 +6537,6 @@ void AutoflipProc(w, event, prms, nprms)
                args, 1);
 }
 
-void AutobsProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
-{
-    Arg args[16];
-
-    appData.autoObserve = !appData.autoObserve;
-
-    if (appData.autoObserve) {
-       XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
-    } else {
-       XtSetArg(args[0], XtNleftBitmap, None);
-    }
-    XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Observe"),
-               args, 1);
-}
-
-void AutoraiseProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
-{
-    Arg args[16];
-
-    appData.autoRaiseBoard = !appData.autoRaiseBoard;
-
-    if (appData.autoRaiseBoard) {
-       XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
-    } else {
-       XtSetArg(args[0], XtNleftBitmap, None);
-    }
-    XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Raise Board"),
-               args, 1);
-}
-
-void AutosaveProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
-{
-    Arg args[16];
-
-    appData.autoSaveGames = !appData.autoSaveGames;
-
-    if (appData.autoSaveGames) {
-       XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
-    } else {
-       XtSetArg(args[0], XtNleftBitmap, None);
-    }
-    XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Save"),
-               args, 1);
-}
-
 void BlindfoldProc(w, event, prms, nprms)
      Widget w;
      XEvent *event;
@@ -6725,7 +6611,8 @@ void FlipViewProc(w, event, prms, nprms)
     DrawPosition(True, NULL);
 }
 
-void GetMoveListProc(w, event, prms, nprms)
+#if HIGHDRAG
+void HighlightDraggingProc(w, event, prms, nprms)
      Widget w;
      XEvent *event;
      String *prms;
@@ -6733,20 +6620,19 @@ void GetMoveListProc(w, event, prms, nprms)
 {
     Arg args[16];
 
-    appData.getMoveList = !appData.getMoveList;
+    appData.highlightDragging = !appData.highlightDragging;
 
-    if (appData.getMoveList) {
+    if (appData.highlightDragging) {
        XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
-       GetMoveListEvent();
     } else {
        XtSetArg(args[0], XtNleftBitmap, None);
     }
-    XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Get Move List"),
-               args, 1);
+    XtSetValues(XtNameToWidget(menuBarWidget,
+                              "menuOptions.Highlight Dragging"), args, 1);
 }
+#endif
 
-#if HIGHDRAG
-void HighlightDraggingProc(w, event, prms, nprms)
+void HighlightLastMoveProc(w, event, prms, nprms)
      Widget w;
      XEvent *event;
      String *prms;
@@ -6754,19 +6640,18 @@ void HighlightDraggingProc(w, event, prms, nprms)
 {
     Arg args[16];
 
-    appData.highlightDragging = !appData.highlightDragging;
+    appData.highlightLastMove = !appData.highlightLastMove;
 
-    if (appData.highlightDragging) {
+    if (appData.highlightLastMove) {
        XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
     } else {
        XtSetArg(args[0], XtNleftBitmap, None);
     }
     XtSetValues(XtNameToWidget(menuBarWidget,
-                              "menuOptions.Highlight Dragging"), args, 1);
+                              "menuOptions.Highlight Last Move"), args, 1);
 }
-#endif
 
-void HighlightLastMoveProc(w, event, prms, nprms)
+void HighlightArrowProc(w, event, prms, nprms)
      Widget w;
      XEvent *event;
      String *prms;
@@ -6774,17 +6659,18 @@ void HighlightLastMoveProc(w, event, prms, nprms)
 {
     Arg args[16];
 
-    appData.highlightLastMove = !appData.highlightLastMove;
+    appData.highlightMoveWithArrow = !appData.highlightMoveWithArrow;
 
-    if (appData.highlightLastMove) {
+    if (appData.highlightMoveWithArrow) {
        XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
     } else {
        XtSetArg(args[0], XtNleftBitmap, None);
     }
     XtSetValues(XtNameToWidget(menuBarWidget,
-                              "menuOptions.Highlight Last Move"), args, 1);
+                              "menuOptions.Arrow"), args, 1);
 }
 
+#if 0
 void IcsAlarmProc(w, event, prms, nprms)
      Widget w;
      XEvent *event;
@@ -6803,6 +6689,7 @@ void IcsAlarmProc(w, event, prms, nprms)
     XtSetValues(XtNameToWidget(menuBarWidget,
                               "menuOptions.ICS Alarm"), args, 1);
 }
+#endif
 
 void MoveSoundProc(w, event, prms, nprms)
      Widget w;
@@ -6823,8 +6710,7 @@ void MoveSoundProc(w, event, prms, nprms)
                args, 1);
 }
 
-
-void OldSaveStyleProc(w, event, prms, nprms)
+void OneClickProc(w, event, prms, nprms)
      Widget w;
      XEvent *event;
      String *prms;
@@ -6832,14 +6718,14 @@ void OldSaveStyleProc(w, event, prms, nprms)
 {
     Arg args[16];
 
-    appData.oldSaveStyle = !appData.oldSaveStyle;
+    appData.oneClick = !appData.oneClick;
 
-    if (appData.oldSaveStyle) {
+    if (appData.oneClick) {
        XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
     } else {
        XtSetArg(args[0], XtNleftBitmap, None);
     }
-    XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Old Save Style"),
+    XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.OneClick"),
                args, 1);
 }
 
@@ -6919,6 +6805,7 @@ void PopupMoveErrorsProc(w, event, prms, nprms)
                args, 1);
 }
 
+#if 0
 void PremoveProc(w, event, prms, nprms)
      Widget w;
      XEvent *event;
@@ -6937,25 +6824,7 @@ void PremoveProc(w, event, prms, nprms)
     XtSetValues(XtNameToWidget(menuBarWidget,
                               "menuOptions.Premove"), args, 1);
 }
-
-void QuietPlayProc(w, event, prms, nprms)
-     Widget w;
-     XEvent *event;
-     String *prms;
-     Cardinal *nprms;
-{
-    Arg args[16];
-
-    appData.quietPlay = !appData.quietPlay;
-
-    if (appData.quietPlay) {
-       XtSetArg(args[0], XtNleftBitmap, xMarkPixmap);
-    } else {
-       XtSetArg(args[0], XtNleftBitmap, None);
-    }
-    XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Quiet Play"),
-               args, 1);
-}
+#endif
 
 void ShowCoordsProc(w, event, prms, nprms)
      Widget w;
@@ -8729,6 +8598,7 @@ BeginAnimation(anim, piece, startColor, start)
 {
   Pixmap mask;
 
+  if(appData.upsideDown && flipView) piece += piece < BlackPawn ? BlackPawn : -BlackPawn;
   /* The old buffer is initialised with the start square (empty) */
   BlankSquare(start->x, start->y, startColor, EmptySquare, anim->saveBuf, 0);
   anim->prevFrame = *start;
@@ -9093,3 +8963,196 @@ void NotifyFrontendLogin()
 {
     update_ics_width();
 }
+
+/* [AS] Arrow highlighting support */
+
+static double A_WIDTH = 5; /* Width of arrow body */
+
+#define A_HEIGHT_FACTOR 6   /* Length of arrow "point", relative to body width */
+#define A_WIDTH_FACTOR  3   /* Width of arrow "point", relative to body width */
+
+static double Sqr( double x )
+{
+    return x*x;
+}
+
+static int Round( double x )
+{
+    return (int) (x + 0.5);
+}
+
+void SquareToPos(int rank, int file, int *x, int *y)
+{
+    if (flipView) {
+       *x = lineGap + ((BOARD_WIDTH-1)-file) * (squareSize + lineGap);
+       *y = lineGap + rank * (squareSize + lineGap);
+    } else {
+       *x = lineGap + file * (squareSize + lineGap);
+       *y = lineGap + ((BOARD_HEIGHT-1)-rank) * (squareSize + lineGap);
+    }
+}
+
+/* Draw an arrow between two points using current settings */
+void DrawArrowBetweenPoints( int s_x, int s_y, int d_x, int d_y )
+{
+    XPoint arrow[7];
+    double dx, dy, j, k, x, y;
+
+    if( d_x == s_x ) {
+        int h = (d_y > s_y) ? +A_WIDTH*A_HEIGHT_FACTOR : -A_WIDTH*A_HEIGHT_FACTOR;
+
+        arrow[0].x = s_x + A_WIDTH + 0.5;
+        arrow[0].y = s_y;
+
+        arrow[1].x = s_x + A_WIDTH + 0.5;
+        arrow[1].y = d_y - h;
+
+        arrow[2].x = arrow[1].x + A_WIDTH*(A_WIDTH_FACTOR-1) + 0.5;
+        arrow[2].y = d_y - h;
+
+        arrow[3].x = d_x;
+        arrow[3].y = d_y;
+
+        arrow[5].x = arrow[1].x - 2*A_WIDTH + 0.5;
+        arrow[5].y = d_y - h;
+
+        arrow[4].x = arrow[5].x - A_WIDTH*(A_WIDTH_FACTOR-1) + 0.5;
+        arrow[4].y = d_y - h;
+
+        arrow[6].x = arrow[1].x - 2*A_WIDTH + 0.5;
+        arrow[6].y = s_y;
+    }
+    else if( d_y == s_y ) {
+        int w = (d_x > s_x) ? +A_WIDTH*A_HEIGHT_FACTOR : -A_WIDTH*A_HEIGHT_FACTOR;
+
+        arrow[0].x = s_x;
+        arrow[0].y = s_y + A_WIDTH + 0.5;
+
+        arrow[1].x = d_x - w;
+        arrow[1].y = s_y + A_WIDTH + 0.5;
+
+        arrow[2].x = d_x - w;
+        arrow[2].y = arrow[1].y + A_WIDTH*(A_WIDTH_FACTOR-1) + 0.5;
+
+        arrow[3].x = d_x;
+        arrow[3].y = d_y;
+
+        arrow[5].x = d_x - w;
+        arrow[5].y = arrow[1].y - 2*A_WIDTH + 0.5;
+
+        arrow[4].x = d_x - w;
+        arrow[4].y = arrow[5].y - A_WIDTH*(A_WIDTH_FACTOR-1) + 0.5;
+
+        arrow[6].x = s_x;
+        arrow[6].y = arrow[1].y - 2*A_WIDTH + 0.5;
+    }
+    else {
+        /* [AS] Needed a lot of paper for this! :-) */
+        dy = (double) (d_y - s_y) / (double) (d_x - s_x);
+        dx = (double) (s_x - d_x) / (double) (s_y - d_y);
+
+        j = sqrt( Sqr(A_WIDTH) / (1.0 + Sqr(dx)) );
+
+        k = sqrt( Sqr(A_WIDTH*A_HEIGHT_FACTOR) / (1.0 + Sqr(dy)) );
+
+        x = s_x;
+        y = s_y;
+
+        arrow[0].x = Round(x - j);
+        arrow[0].y = Round(y + j*dx);
+
+        arrow[1].x = Round(arrow[0].x + 2*j);   // [HGM] prevent width to be affected by rounding twice
+        arrow[1].y = Round(arrow[0].y - 2*j*dx);
+
+        if( d_x > s_x ) {
+            x = (double) d_x - k;
+            y = (double) d_y - k*dy;
+        }
+        else {
+            x = (double) d_x + k;
+            y = (double) d_y + k*dy;
+        }
+
+        x = Round(x); y = Round(y); // [HGM] make sure width of shaft is rounded the same way on both ends
+
+        arrow[6].x = Round(x - j);
+        arrow[6].y = Round(y + j*dx);
+
+        arrow[2].x = Round(arrow[6].x + 2*j);
+        arrow[2].y = Round(arrow[6].y - 2*j*dx);
+
+        arrow[3].x = Round(arrow[2].x + j*(A_WIDTH_FACTOR-1));
+        arrow[3].y = Round(arrow[2].y - j*(A_WIDTH_FACTOR-1)*dx);
+
+        arrow[4].x = d_x;
+        arrow[4].y = d_y;
+
+        arrow[5].x = Round(arrow[6].x - j*(A_WIDTH_FACTOR-1));
+        arrow[5].y = Round(arrow[6].y + j*(A_WIDTH_FACTOR-1)*dx);
+    }
+
+    XFillPolygon(xDisplay, xBoardWindow, highlineGC, arrow, 7, Nonconvex, CoordModeOrigin);
+//    Polygon( hdc, arrow, 7 );
+}
+
+/* [AS] Draw an arrow between two squares */
+void DrawArrowBetweenSquares( int s_col, int s_row, int d_col, int d_row )
+{
+    int s_x, s_y, d_x, d_y, hor, vert, i;
+
+    if( s_col == d_col && s_row == d_row ) {
+        return;
+    }
+
+    /* Get source and destination points */
+    SquareToPos( s_row, s_col, &s_x, &s_y);
+    SquareToPos( d_row, d_col, &d_x, &d_y);
+
+    if( d_y > s_y ) {
+        d_y += squareSize / 2 - squareSize / 4; // [HGM] round towards same centers on all sides!
+    }
+    else if( d_y < s_y ) {
+        d_y += squareSize / 2 + squareSize / 4;
+    }
+    else {
+        d_y += squareSize / 2;
+    }
+
+    if( d_x > s_x ) {
+        d_x += squareSize / 2 - squareSize / 4;
+    }
+    else if( d_x < s_x ) {
+        d_x += squareSize / 2 + squareSize / 4;
+    }
+    else {
+        d_x += squareSize / 2;
+    }
+
+    s_x += squareSize / 2;
+    s_y += squareSize / 2;
+
+    /* Adjust width */
+    A_WIDTH = squareSize / 14.; //[HGM] make float
+
+    DrawArrowBetweenPoints( s_x, s_y, d_x, d_y );
+
+    hor = 64*s_col + 32; vert = 64*s_row + 32;
+    for(i=0; i<= 64; i++) {
+            damage[0][vert+6>>6][hor+6>>6] = True;
+            damage[0][vert-6>>6][hor+6>>6] = True;
+            damage[0][vert+6>>6][hor-6>>6] = True;
+            damage[0][vert-6>>6][hor-6>>6] = True;
+            hor += d_col - s_col; vert += d_row - s_row;
+    }
+}
+
+Boolean IsDrawArrowEnabled()
+{
+    return appData.highlightMoveWithArrow && squareSize >= 32;
+}
+
+void DrawArrowHighlight(int fromX, int fromY, int toX,int toY)
+{
+    if( IsDrawArrowEnabled() && fromX >= 0 && fromY >= 0 && toX >= 0 && toY >= 0)
+        DrawArrowBetweenSquares(fromX, fromY, toX, toY);
+}