Fix castling rights on using -lgf
[xboard.git] / gtk / xboard.c
index b76faef..d6f47d7 100644 (file)
@@ -5,7 +5,7 @@
  * Massachusetts.
  *
  * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
- * 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
+ * 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
  *
  * The following terms apply to Digital Equipment Corporation's copyright
  * interest in XBoard:
@@ -167,16 +167,20 @@ extern char *getenv();
 #include "gettext.h"
 #include "draw.h"
 
-#ifdef OSX
-#  include "gtkmacintegration/gtkosxapplication.h"
-   // prevent pathname of positional file argument provided by OSx being be mistaken for option name
+#ifdef __APPLE__
+#  include <gtkmacintegration/gtkosxapplication.h>
+   // prevent pathname of positional file argument provided by OS X being be mistaken for option name
    // (price is that we won't recognize Windows option format anymore).
 #  define SLASH '-'
    // redefine some defaults
 #  undef ICS_LOGON
-#  undef SYSCONFDIR
+#  undef DATADIR
+#  undef SETTINGS_FILE
 #  define ICS_LOGON "Library/Preferences/XboardICS.conf"
-#  define SYSCONFDIR "../etc"
+#  define DATADIR dataDir
+#  define SETTINGS_FILE masterSettings
+   char dataDir[MSG_SIZ]; // for expanding ~~
+   char masterSettings[MSG_SIZ];
 #else
 #  define SLASH '/'
 #endif
@@ -200,8 +204,8 @@ int main P((int argc, char **argv));
 RETSIGTYPE CmailSigHandler P((int sig));
 RETSIGTYPE IntSigHandler P((int sig));
 RETSIGTYPE TermSizeSigHandler P((int sig));
-#if ENABLE_NLS
 char *InsertPxlSize P((char *pattern, int targetPxlSize));
+#if ENABLE_NLS
 XFontSet CreateFontSet P((char *base_fnt_lst));
 #else
 char *FindFont P((char *pattern, int targetPxlSize));
@@ -380,7 +384,8 @@ ParseFont (char *name, int number)
   if(sscanf(name, "size%d:", &size)) {
     // [HGM] font: font is meant for specific boardSize (likely from settings file);
     //       defer processing it until we know if it matches our board size
-    if(size >= 0 && size<MAX_SIZE) { // for now, fixed limit
+    if(!strstr(name, "-*-") &&       // ignore X-fonts
+       size >= 0 && size<MAX_SIZE) { // for now, fixed limit
        fontTable[number][size] = strdup(strchr(name, ':')+1);
        fontValid[number][size] = True;
     }
@@ -421,6 +426,12 @@ ParseColor (int n, char *name)
   if(colorVariable[n]) *(char**)colorVariable[n] = strdup(name);
 }
 
+char *
+Col2Text (int n)
+{
+    return *(char**)colorVariable[n];
+}
+
 void
 ParseTextAttribs (ColorClass cc, char *s)
 {
@@ -519,6 +530,12 @@ GetActualPlacement (GtkWidget *shell, WindowPlacement *wp)
 }
 
 void
+GetPlacement (DialogClass dlg, WindowPlacement *wp)
+{ // wrapper to shield back-end from widget type
+  if(shellUp[dlg]) GetActualPlacement(shells[dlg], wp);
+}
+
+void
 GetWindowCoords ()
 { // wrapper to shield use of window handles from back-end (make addressible by number?)
   // In XBoard this will have to wait until awareness of window parameters is implemented
@@ -529,6 +546,7 @@ GetWindowCoords ()
   if(shellUp[GameListDlg]) GetActualPlacement(shells[GameListDlg], &wpGameList);
   if(shellUp[CommentDlg]) GetActualPlacement(shells[CommentDlg], &wpComment);
   if(shellUp[TagsDlg]) GetActualPlacement(shells[TagsDlg], &wpTags);
+  GetPlacement(ChatDlg, &wpConsole); if(appData.icsActive) wpConsole.visible = shellUp[ChatDlg];
 }
 
 void
@@ -582,7 +600,7 @@ void
 ResizeBoardWindow (int w, int h, int inhibit)
 {
     GtkAllocation a;
-    if(clockKludge) return; // ignore as long as clock does not have final height
+//    if(clockKludge) return; // ignore as long as clock does not have final height
     gtk_widget_get_allocation(optList[W_WHITE].handle, &a);
     w += marginW + 1; // [HGM] not sure why the +1 is (sometimes) needed...
     h += marginH + a.height + 1;
@@ -598,6 +616,18 @@ MakeColors ()
 void
 InitializeFonts (int clockFontPxlSize, int coordFontPxlSize, int fontPxlSize)
 {   // determine what fonts to use, and create them
+
+    if(!fontIsSet[CLOCK_FONT] && fontValid[CLOCK_FONT][squareSize])
+       appData.clockFont = fontTable[CLOCK_FONT][squareSize];
+    if(!fontIsSet[MESSAGE_FONT] && fontValid[MESSAGE_FONT][squareSize])
+       appData.font = fontTable[MESSAGE_FONT][squareSize];
+    if(!fontIsSet[COORD_FONT] && fontValid[COORD_FONT][squareSize])
+       appData.coordFont = fontTable[COORD_FONT][squareSize];
+
+    appData.font = InsertPxlSize(appData.font, fontPxlSize);
+    appData.clockFont = InsertPxlSize(appData.clockFont, clockFontPxlSize);
+    appData.coordFont = InsertPxlSize(appData.coordFont, coordFontPxlSize);
+
 #ifdef TODO_GTK
     XrmValue vTo;
     XrmDatabase xdb;
@@ -676,6 +706,7 @@ PrintArg (ArgType t)
     case ArgTwo:
     case ArgNone:
     case ArgCommSettings:
+    default:
       break;
   }
   return p;
@@ -725,7 +756,7 @@ SlaveResize (Option *opt)
   gtk_window_resize(GTK_WINDOW(shells[DummyDlg]), slaveW + opt->max, slaveH + opt->value);
 }
 
-#ifdef OSX
+#ifdef __APPLE__
 static char clickedFile[MSG_SIZ];
 static int suppress;
 
@@ -747,7 +778,7 @@ int
 main (int argc, char **argv)
 {
     int i, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
-    int boardWidth, boardHeight, w, h;
+    int boardWidth, w, h; //, boardHeight;
     char *p;
     int forceMono = False;
 
@@ -758,7 +789,7 @@ main (int argc, char **argv)
     debugFP = stderr;
 
     if(argc > 1 && (!strcmp(argv[1], "-v" ) || !strcmp(argv[1], "--version" ))) {
-       printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
+        printf("%s version %s\n\n  configure options: %s\n", PACKAGE_NAME, PACKAGE_VERSION, CONFIGURE_OPTIONS);
        exit(0);
     }
 
@@ -769,9 +800,12 @@ main (int argc, char **argv)
 
     /* set up GTK */
     gtk_init (&argc, &argv);
-#ifdef OSX
+#ifdef __APPLE__
     {   // prepare to catch OX OpenFile signal, which will tell us the clicked file
        GtkosxApplication *theApp = g_object_new(GTKOSX_TYPE_APPLICATION, NULL);
+       char *path = gtkosx_application_get_bundle_path();
+       strncpy(dataDir, path, MSG_SIZ);
+       snprintf(masterSettings, MSG_SIZ, "%s/Contents/Resources/etc/xboard.conf", path);
        g_signal_connect(theApp, "NSApplicationOpenFile", G_CALLBACK(StartNewXBoard), NULL);
        // we must call application ready before we can get the signal,
        // and supply a (dummy) menu bar before that, to avoid problems with dual apples in it
@@ -792,6 +826,23 @@ main (int argc, char **argv)
     }
 #endif
 
+    if(argc > 1 && !strcmp(argv[1], "--show-config")) { // [HGM] install: called to print config info
+       typedef struct {char *name, *value; } Config;
+       static Config configList[] = {
+         { "Datadir", DATADIR },
+         { "Sysconfdir", SYSCONFDIR },
+         { NULL }
+       };
+       int i;
+
+       for(i=0; configList[i].name; i++) {
+           if(argc > 2 && strcmp(argv[2], configList[i].name)) continue;
+           if(argc > 2) printf("%s", configList[i].value);
+           else printf("%-12s: %s\n", configList[i].name, configList[i].value);
+       }
+       exit(0);
+    }
+
     /* set up keyboard accelerators group */
     GtkAccelerators = gtk_accel_group_new();
 
@@ -823,6 +874,8 @@ main (int argc, char **argv)
 
     { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
        static char buf[MSG_SIZ];
+       snprintf(buf, MSG_SIZ, appData.sysOpen, DATADIR);
+       ASSIGN(appData.sysOpen, buf); // expand %s in -openCommand to DATADIR (usefull for OS X configuring)
        EscapeExpand(buf, appData.firstInitString);
        appData.firstInitString = strdup(buf);
        EscapeExpand(buf, appData.secondInitString);
@@ -884,6 +937,8 @@ main (int argc, char **argv)
                    programName, appData.boardSize);
            exit(2);
        }
+       if(BOARD_WIDTH > 8)
+           squareSize = (squareSize*8 + BOARD_WIDTH/2)/BOARD_WIDTH; // scale height
        if (i < 7) {
            /* Find some defaults; use the nearest known size */
            SizeDefaults *szd, *nearest;
@@ -907,11 +962,11 @@ main (int argc, char **argv)
     } else {
         SizeDefaults *szd = sizeDefaults;
         if (*appData.boardSize == NULLCHAR) {
-            GdkScreen *screen = gtk_window_get_screen(GTK_WINDOW(mainwindow));
+            GdkScreen *screen = gtk_window_get_screen(GTK_WINDOW(mainwindow)); // TODO: this does not work, as no mainwindow yet
             guint screenwidth = gdk_screen_get_width(screen);
             guint screenheight = gdk_screen_get_height(screen);
-           while (screenwidth < szd->minScreenSize ||
-                  screenheight < szd->minScreenSize) {
+           while (screenwidth  < (szd->minScreenSize*BOARD_WIDTH  + 4)/8 ||
+                  screenheight < (szd->minScreenSize*BOARD_HEIGHT + 4)/8) {
              szd++;
            }
            if (szd->name == NULL) szd--;
@@ -940,14 +995,12 @@ main (int argc, char **argv)
 
     /* [HR] height treated separately (hacked) */
     boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
-    boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
+//    boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
 
     /*
      * Determine what fonts to use.
      */
-#ifdef TODO_GTK
-    InitializeFonts(clockFontPxlSize, coordFontPxlSize, fontPxlSize);
-#endif
+    InitializeFonts((2*clockFontPxlSize+1)/3, coordFontPxlSize, fontPxlSize);
 
     /*
      * Detect if there are not enough colors available and adapt.
@@ -1094,6 +1147,14 @@ main (int argc, char **argv)
       EngineOutputPopUp();
     }
 
+    if( wpConsole.visible && appData.icsActive ) {
+      ChatProc();
+      BoardToTop();
+    }
+
+    gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
+    InitPosition(TRUE);
+
     InitBackEnd2();
 
     if (errorExitStatus == -1) {
@@ -1114,8 +1175,6 @@ main (int argc, char **argv)
        }
     }
 
-    gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
-    InitPosition(TRUE);
     UpdateLogos(TRUE);
 //    XtSetKeyboardFocus(shellWidget, formWidget);
 #ifdef TODO_GTK
@@ -1169,7 +1228,16 @@ CmailSigHandlerCallBack (InputSourceRef isr, VOIDSTAR closure, char *message, in
 
 #define Abs(n) ((n)<0 ? -(n) : (n))
 
+char *
+InsertPxlSize (char *pattern, int targetPxlSize)
+{
+    char buf[MSG_SIZ];
+    snprintf(buf, MSG_SIZ, pattern, targetPxlSize); // pattern is something like "Sans Bold %d"
+    return strdup(buf);
+}
+
 #ifdef ENABLE_NLS
+#ifdef TODO_GTK
 char *
 InsertPxlSize (char *pattern, int targetPxlSize)
 {
@@ -1220,6 +1288,7 @@ InsertPxlSize (char *pattern, int targetPxlSize)
 
     return base_fnt_lst;
 }
+#endif
 
 #ifdef TODO_GTK
 XFontSet
@@ -1267,13 +1336,13 @@ CreateFontSet (char *base_fnt_lst)
  * The return value should be freed with XtFree when no
  * longer needed.
  */
+#ifdef TODO_GTK
 char *
 FindFont (char *pattern, int targetPxlSize)
 {
     char **fonts, *p, *best, *scalable, *scalableTail;
     int i, j, nfonts, minerr, err, pxlSize;
 
-#ifdef TODO_GTK
     fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
     if (nfonts < 1) {
        fprintf(stderr, _("%s: no fonts match pattern %s\n"),
@@ -1322,17 +1391,17 @@ FindFont (char *pattern, int targetPxlSize)
                pattern, targetPxlSize, p);
     }
     XFreeFontNames(fonts);
-#endif
     return p;
 }
 #endif
+#endif
 
 void
 EnableNamedMenuItem (char *menuRef, int state)
 {
     MenuItem *item = MenuNameToItem(menuRef);
 
-    if(item) gtk_widget_set_sensitive(item->handle, state);
+    if(item && item->handle) gtk_widget_set_sensitive(item->handle, state);
 }
 
 void
@@ -1486,15 +1555,13 @@ ReSize (WindowPlacement *wp)
        int sqx, sqy, w, h, hc, lg = lineGap;
        gtk_widget_get_allocation(optList[W_WHITE].handle, &a);
        hc = a.height; // clock height can depend on single / double line clock text!
-        if(clockKludge == a.height) return; // wait for clock to get final size at startup
-       if(clockKludge) { // clock height OK now; calculate desired initial board height
-           clockKludge = 0;
-           wp->height = BOARD_HEIGHT * (squareSize + lineGap) + lineGap + marginH + hc;
-       }
+        if(clockKludge && hc != clockKludge) wp->height += hc - clockKludge, clockKludge = 0;
+       wpMain.height = BOARD_HEIGHT * (squareSize + lineGap) + lineGap + marginH + hc;
        if(wp->width == wpMain.width && wp->height == wpMain.height) return; // not sized
        sqx = (wp->width  - lg - marginW) / BOARD_WIDTH - lg;
        sqy = (wp->height - lg - marginH - hc) / BOARD_HEIGHT - lg;
        if(sqy < sqx) sqx = sqy;
+        if(sqx < 20) return;
        if(appData.overrideLineGap < 0) { // do second iteration with adjusted lineGap
            lg = lineGap = sqx < 37 ? 1 : sqx < 59 ? 2 : sqx < 116 ? 3 : 4;
            sqx = (wp->width  - lg - marginW) / BOARD_WIDTH - lg;
@@ -1502,7 +1569,6 @@ ReSize (WindowPlacement *wp)
            if(sqy < sqx) sqx = sqy;
        }
        if(sqx != squareSize) {
-//printf("new sq size %d (%dx%d)\n", sqx, wp->width, wp->height);
            squareSize = sqx; // adopt new square size
            CreatePNGPieces(); // make newly scaled pieces
            InitDrawingSizes(0, 0); // creates grid etc.
@@ -1533,6 +1599,7 @@ DragProc ()
            if(shellUp[HistoryDlg]) CoDrag(shells[HistoryDlg], &wpMoveHistory);
            if(shellUp[EvalGraphDlg]) CoDrag(shells[EvalGraphDlg], &wpEvalGraph);
            if(shellUp[GameListDlg]) CoDrag(shells[GameListDlg], &wpGameList);
+           if(shellUp[ChatDlg]) CoDrag(shells[ChatDlg], &wpConsole);
         }
        wpMain = wpNew;
        DrawPosition(True, NULL);
@@ -1748,7 +1815,7 @@ void MoveTypeInProc(eventkey)
     buf[0]=eventkey->keyval;
     buf[1]='\0';
     if (eventkey->keyval > 32 && eventkey->keyval < 256)
-       BoxAutoPopUp (buf);
+       ConsoleAutoPopUp (buf);
 }
 
 #ifdef TODO_GTK
@@ -1776,26 +1843,17 @@ TempForwardProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
     ForwardEvent();
        TempBackwardActive = False;
 }
-
-void
-ManInner (Widget w, XEvent *event, String *prms, Cardinal *nprms)
-{   // called as key binding
-    char buf[MSG_SIZ];
-    String name;
-    if (nprms && *nprms > 0)
-      name = prms[0];
-    else
-      name = "xboard";
-    snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
-    system(buf);
-}
 #endif
 
 void
 ManProc ()
 {   // called from menu
-#ifdef TODO_GTK
-    ManInner(NULL, NULL, NULL, NULL);
+#ifdef __APPLE__
+    char buf[MSG_SIZ];
+    snprintf(buf, MSG_SIZ, "%s ./man.command", appData.sysOpen);
+    system(buf);
+#else
+    system("xterm -e man xboard &");
 #endif
 }
 
@@ -1881,11 +1939,15 @@ DisplayTimerLabel (Option *opt, char *color, long timer, int highlight)
     gtk_widget_modify_bg(gtk_widget_get_parent(opt->handle), GTK_STATE_NORMAL, &col);
 
     if (appData.clockMode) {
-        markup = g_markup_printf_escaped("<span size=\"xx-large\" weight=\"heavy\" background=\"%s\" foreground=\"%s\">%s:%s%s</span>",
+        markup = g_markup_printf_escaped("<span font=\"%s\" background=\"%s\" foreground=\"%s\">%s:%s%s</span>", appData.clockFont,
                                         bgcolor, fgcolor, color, appData.logoSize && !partnerUp ? "\n" : " ", TimeString(timer));
+//        markup = g_markup_printf_escaped("<span size=\"xx-large\" weight=\"heavy\" background=\"%s\" foreground=\"%s\">%s:%s%s</span>",
+//                                      bgcolor, fgcolor, color, appData.logoSize && !partnerUp ? "\n" : " ", TimeString(timer));
     } else {
-        markup = g_markup_printf_escaped("<span size=\"xx-large\" weight=\"heavy\" background=\"%s\" foreground=\"%s\">%s  </span>",
+        markup = g_markup_printf_escaped("<span font=\"%s\" background=\"%s\" foreground=\"%s\">%s  </span>", appData.clockFont,
                                         bgcolor, fgcolor, color);
+//        markup = g_markup_printf_escaped("<span size=\"xx-large\" weight=\"heavy\" background=\"%s\" foreground=\"%s\">%s  </span>",
+//                                      bgcolor, fgcolor, color);
     }
     gtk_label_set_markup(GTK_LABEL(w), markup);
     g_free(markup);
@@ -1939,6 +2001,11 @@ DoInputCallback(io, cond, data)
        count = read(is->fd, is->unused,
                     INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf));
        if (count <= 0) {
+           if(count == 0 && is->kind == CPReal && shells[ChatDlg]) { // [HGM] absence of terminal is no error if ICS Console present
+               RemoveInputSource(is); // cease reading stdin
+               stdoutClosed = TRUE;   // suppress future output
+               return True;
+           } 
            (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
            return True;
        }