Fix multi-leg promotions
[xboard.git] / xaw / xboard.c
index 17a9752..1c3ffc7 100644 (file)
@@ -5,7 +5,8 @@
  * Massachusetts.
  *
  * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
- * 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
+ * 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Free
+ * Software Foundation, Inc.
  *
  * The following terms apply to Digital Equipment Corporation's copyright
  * interest in XBoard:
@@ -148,6 +149,7 @@ extern char *getenv();
 #include <locale.h>
 #endif
 
+#include <X11/keysym.h>
 #include <X11/Intrinsic.h>
 #include <X11/StringDefs.h>
 #include <X11/Shell.h>
@@ -256,6 +258,7 @@ void ManInner P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void DisplayMove P((int moveNumber));
 void update_ics_width P(());
 int CopyMemoProc P(());
+static int FindLogo P((char *place, char *name, char *buf));
 
 /*
 * XBoard depends on Xt R4 or higher
@@ -535,7 +538,7 @@ CreateFonts ()
 void
 ParseColor (int n, char *name)
 { // in XBoard, just copy the color-name string
-  if(colorVariable[n]) *(char**)colorVariable[n] = strdup(name);
+  if(colorVariable[n] && *name == '#') *(char**)colorVariable[n] = strdup(name);
 }
 
 char *
@@ -844,17 +847,18 @@ char *
 GenerateGlobalTranslationTable (void)
 {
   /* go through all menu items and extract the keyboard shortcuts, so that X11 can load them */
-  char *output;
+  char *output[2];
 
-  int i,j;
+  int i,j,n=0;
   MenuItem *mi;
 
-  output = strdup("");
+  output[0] = strdup(""); // build keystrokes with and wo mod keys separately
+  output[1] = strdup(""); // so the more specific can preceed the other
 
   /* loop over all menu entries */
-  for( i=0; menuBar[i].mi ; i++)
+  for( i=0; menuBar[i-n].mi || !n++; i++)
     {
-      mi = menuBar[i].mi;
+      mi = menuBar[i+n].mi; // kludge to access 'noMenu' behind sentinel
       for(j=0; mi[j].proc; j++)
        {
          if (mi[j].accel)
@@ -919,17 +923,16 @@ GenerateGlobalTranslationTable (void)
                mods[strlen(mods)-1]='\0';
 
              /* get the name for the callback, we can use MenuItem() here that will call KeyBindingProc */
-             size_t namesize = snprintf(NULL, 0, "%s.%s", menuBar[i].ref, mi[j].ref);
-             char *name = malloc(namesize+1);
-             snprintf(name, namesize+1, "%s.%s", menuBar[i].ref, mi[j].ref);
+             char *name = malloc(MSG_SIZ);
+             if(n) snprintf(name, MSG_SIZ, "%s", mi[j].ref);
+             else  snprintf(name, MSG_SIZ, "%s.%s", menuBar[i].ref, mi[j].ref);
 
-             size_t buffersize = snprintf(NULL, 0, ":%s<Key>%s: MenuItem(%s) \n ", mods, key, name);
-             char *buffer = malloc(buffersize+1);
-             snprintf(buffer, buffersize+1, ":%s<Key>%s: MenuItem(%s) \n ", mods, key, name);
+             char *buffer = malloc(MSG_SIZ);
+             snprintf(buffer, MSG_SIZ, ":%s<Key>%s: MenuItem(%s) \n ", mods, key, name);
 
              /* add string to the output */
-             output = realloc(output, strlen(output) + strlen(buffer)+1);
-             strncat(output, buffer, strlen(buffer));
+             output[shift|alt|ctrl] = realloc(output[shift|alt|ctrl], strlen(output[shift|alt|ctrl]) + strlen(buffer)+1);
+             strncat(output[shift|alt|ctrl], buffer, strlen(buffer));
 
              /* clean up */
              free(key);
@@ -939,7 +942,10 @@ GenerateGlobalTranslationTable (void)
            }
        }
     }
-  return output;
+  output[1] = realloc(output[1], strlen(output[1]) + strlen(output[0])+1);
+  strncat(output[1], output[0], strlen(output[0]));
+  free(output[0]);
+  return output[1];
 }
 
 
@@ -987,6 +993,9 @@ main (int argc, char **argv)
     char *p;
     int forceMono = False;
 
+    extern Option chatOptions[]; // FIXME: adapt Chat window, removing ICS pane and Hide button
+    chatOptions[6].type = chatOptions[10].type = Skip;
+
     srandom(time(0)); // [HGM] book: make random truly random
 
     setbuf(stdout, NULL);
@@ -1225,7 +1234,7 @@ main (int argc, char **argv)
     boardWidget      = optList[W_BOARD].handle;
     menuBarWidget    = optList[W_MENU].handle;
     dropMenu         = optList[W_DROP].handle;
-    titleWidget = optList[optList[W_TITLE].type != -1 ? W_TITLE : W_SMALL].handle;
+    titleWidget = optList[optList[W_TITLE].type != Skip ? W_TITLE : W_SMALL].handle;
     formWidget  = XtParent(boardWidget);
     XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
     XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
@@ -1281,13 +1290,15 @@ main (int argc, char **argv)
 
     CatchDeleteWindow(shellWidget, "QuitProc");
 
-    CreateAnyPieces();
+    CreateAnyPieces(1);
     CreateGrid();
 
     if(appData.logoSize)
     {   // locate and read user logo
-       char buf[MSG_SIZ];
-       snprintf(buf, MSG_SIZ, "%s/%s.png", appData.logoDir, UserName());
+       char buf[MSG_SIZ], name[MSG_SIZ];
+       snprintf(name, MSG_SIZ, "/home/%s", UserName());
+       if(!FindLogo(name, ".logo", buf))
+           FindLogo(appData.logoDir, name + 6, buf);
        ASSIGN(userLogo, buf);
     }
 
@@ -1698,7 +1709,7 @@ ReSize (WindowPlacement *wp)
        if(sqy < sqx) sqx = sqy;
        if(sqx != squareSize) {
            squareSize = sqx; // adopt new square size
-           CreatePNGPieces(); // make newly scaled pieces
+           CreatePNGPieces(appData.pieceDirectory); // make newly scaled pieces
            InitDrawingSizes(0, 0); // creates grid etc.
        } else ResizeBoardWindow(BOARD_WIDTH * (squareSize + lineGap) + lineGap, BOARD_HEIGHT * (squareSize + lineGap) + lineGap, 0);
        w = BOARD_WIDTH * (squareSize + lineGap) + lineGap;
@@ -1808,7 +1819,7 @@ ModeHighlight ()
 {
     Arg args[16];
     static int oldPausing = FALSE;
-    static GameMode oldmode = (GameMode) -1;
+    static GameMode oldMode = (GameMode) -1;
     char *wname;
 
     if (!boardWidget || !XtIsRealized(boardWidget)) return;
@@ -1834,7 +1845,7 @@ ModeHighlight ()
        }
     }
 
-    wname = ModeToWidgetName(oldmode);
+    wname = ModeToWidgetName(oldMode);
     if (wname != NULL) {
        MarkMenuItem(wname, False);
     }
@@ -1842,8 +1853,9 @@ ModeHighlight ()
     if (wname != NULL) {
        MarkMenuItem(wname, True);
     }
-    oldmode = gameMode;
+    if(oldMode == TwoMachinesPlay) EnableNamedMenuItem("Mode.MachineMatch", True);
     MarkMenuItem("Mode.MachineMatch", matchMode && matchGame < appData.matchGames);
+    oldMode = gameMode;
 
     /* Maybe all the enables should be handled here, not just this one */
     EnableNamedMenuItem("Mode.Training", gameMode == Training || gameMode == PlayFromGameFile);
@@ -1986,6 +1998,7 @@ PasteGameCB (Widget w, XtPointer client_data, Atom *selection,
             Atom *type, XtPointer value, unsigned long *len, int *format)
 {
   FILE* f;
+  int flip = appData.flipView;
   if (value == NULL || *len == 0) {
     return; /* nothing had been selected to copy */
   }
@@ -1997,7 +2010,9 @@ PasteGameCB (Widget w, XtPointer client_data, Atom *selection,
   fwrite(value, 1, *len, f);
   fclose(f);
   XtFree(value);
+  if(!appData.autoFlipView) appData.flipView = flipView;
   LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
+  appData.flipView = flip;
 }
 
 /* called when Paste Game button is pressed,
@@ -2114,6 +2129,15 @@ ManProc ()
 }
 
 void
+InfoProc ()
+{
+    char buf[MSG_SIZ];
+    snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
+             INFODIR, INFOFILE);
+    system(buf);
+}
+
+void
 SetWindowTitle (char *text, char *title, char *icon)
 {
     Arg args[16];
@@ -2486,6 +2510,19 @@ FrameDelay (int time)
 
 #endif
 
+static int
+FindLogo (char *place, char *name, char *buf)
+{   // check if file exists in given place
+    FILE *f;
+    if(!place) return 0;
+    snprintf(buf, MSG_SIZ, "%s/%s.png", place, name);
+    if(*place && strcmp(place, ".") && (f = fopen(buf, "r")) ) {
+       fclose(f);
+       return 1;
+    }
+    return 0;
+}
+
 static void
 LoadLogo (ChessProgramState *cps, int n, Boolean ics)
 {
@@ -2495,8 +2532,11 @@ LoadLogo (ChessProgramState *cps, int n, Boolean ics)
     } else if(appData.autoLogo) {
        if(ics) { // [HGM] logo: in ICS mode second can be used for ICS
            sprintf(buf, "%s/%s.png", appData.logoDir, appData.icsHost);
-       } else if(appData.directory[n] && appData.directory[n][0]) {
-           sprintf(buf, "%s/%s.png", appData.logoDir, cps->tidy);
+       } else { // engine; cascade
+           if(!FindLogo(appData.logoDir, cps->tidy, buf) &&   // first try user log folder
+              !FindLogo(appData.directory[n], "logo", buf) && // then engine directory
+              !FindLogo("/usr/local/share/games/plugins/logos", cps->tidy, buf) ) // then system folders
+               FindLogo("/usr/share/games/plugins/logos", cps->tidy, buf);
        }
     }
     if(logoName[0])