Add task-bar icon
[xboard.git] / xboard.c
index 845c168..0ac3a44 100644 (file)
--- a/xboard.c
+++ b/xboard.c
@@ -149,38 +149,6 @@ extern char *getenv();
 #include <locale.h>
 #endif
 
-#include <X11/Intrinsic.h>
-#include <X11/StringDefs.h>
-#include <X11/Shell.h>
-#include <X11/cursorfont.h>
-#include <X11/Xatom.h>
-#include <X11/Xmu/Atoms.h>
-#if USE_XAW3D
-#include <X11/Xaw3d/Dialog.h>
-#include <X11/Xaw3d/Form.h>
-#include <X11/Xaw3d/List.h>
-#include <X11/Xaw3d/Label.h>
-#include <X11/Xaw3d/SimpleMenu.h>
-#include <X11/Xaw3d/SmeBSB.h>
-#include <X11/Xaw3d/SmeLine.h>
-#include <X11/Xaw3d/Box.h>
-#include <X11/Xaw3d/MenuButton.h>
-#include <X11/Xaw3d/Text.h>
-#include <X11/Xaw3d/AsciiText.h>
-#else
-#include <X11/Xaw/Dialog.h>
-#include <X11/Xaw/Form.h>
-#include <X11/Xaw/List.h>
-#include <X11/Xaw/Label.h>
-#include <X11/Xaw/SimpleMenu.h>
-#include <X11/Xaw/SmeBSB.h>
-#include <X11/Xaw/SmeLine.h>
-#include <X11/Xaw/Box.h>
-#include <X11/Xaw/MenuButton.h>
-#include <X11/Xaw/Text.h>
-#include <X11/Xaw/AsciiText.h>
-#endif
-
 // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
 #include "common.h"
 
@@ -221,15 +189,16 @@ int main P((int argc, char **argv));
 RETSIGTYPE CmailSigHandler P((int sig));
 RETSIGTYPE IntSigHandler P((int sig));
 RETSIGTYPE TermSizeSigHandler P((int sig));
-Widget CreateMenuBar P((Menu *mb, int boardWidth));
 #if ENABLE_NLS
 char *InsertPxlSize P((char *pattern, int targetPxlSize));
 XFontSet CreateFontSet P((char *base_fnt_lst));
 #else
 char *FindFont P((char *pattern, int targetPxlSize));
 #endif
-void EventProc P((Widget widget, caddr_t unused, XEvent *event));
 void DelayedDrag P((void));
+void ICSInputBoxPopUp P((void));
+gboolean KeyPressProc P((GtkWindow *window, GdkEventKey *eventkey, gpointer data));
+#ifdef TODO_GTK
 static void MoveTypeInProc P((Widget widget, caddr_t unused, XEvent *event));
 void HandlePV P((Widget w, XEvent * event,
                     String * params, Cardinal * nParams));
@@ -237,7 +206,6 @@ void DrawPositionProc P((Widget w, XEvent *event,
                     String *prms, Cardinal *nprms));
 void CommentClick P((Widget w, XEvent * event,
                   String * params, Cardinal * nParams));
-void ICSInputBoxPopUp P((void));
 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
 void KeyBindingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void QuitWrapper P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
@@ -246,20 +214,21 @@ static void UpKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)
 static void DownKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void TempBackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void TempForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
-Boolean TempBackwardActive = False;
 void ManInner P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void SelectMove P((Widget w, XEvent * event, String * params, Cardinal * nParams));
+#endif
+Boolean TempBackwardActive = False;
 void DisplayMove P((int moveNumber));
 void ICSInitScript P((void));
-void SelectMove P((Widget w, XEvent * event, String * params, Cardinal * nParams));
 void update_ics_width P(());
 int CopyMemoProc P(());
 
+#ifdef TODO_GTK
 /*
 * XBoard depends on Xt R4 or higher
 */
 int xtVersion = XtSpecificationRelease;
 
-#ifdef TODO_GTK
 int xScreen;
 Display *xDisplay;
 Window xBoardWindow;
@@ -285,8 +254,11 @@ char *layoutName;
 
 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
 
-Position commentX = -1, commentY = -1;
-Dimension commentW, commentH;
+/* pixbufs */
+static GdkPixbuf       *mainwindowIcon=NULL;
+static GdkPixbuf       *WhiteIcon=NULL;
+static GdkPixbuf       *BlackIcon=NULL;
+
 typedef unsigned int BoardSize;
 BoardSize boardSize;
 Boolean chessProgram;
@@ -296,9 +268,11 @@ int smallLayout = 0, tinyLayout = 0,
   marginW, marginH, // [HGM] for run-time resizing
   fromX = -1, fromY = -1, toX, toY, commentUp = False,
   errorExitStatus = -1, defaultLineGap;
+#ifdef TODO_GTK
 Dimension textHeight;
 Pixel timerForegroundPixel, timerBackgroundPixel;
 Pixel buttonForegroundPixel, buttonBackgroundPixel;
+#endif
 char *chessDir, *programName, *programVersion;
 Boolean alwaysOnTop = False;
 char *icsTextMenuString;
@@ -1045,9 +1019,10 @@ main (int argc, char **argv)
 #ifdef TODO_GTK
     XSetWindowAttributes window_attributes;
     Arg args[16];
+    Dimension boardWidth, boardHeight, w, h;
 #else
 #endif
-    Dimension boardWidth, boardHeight, w, h;
+    int boardWidth, boardHeight, w, h;
     char *p;
     int forceMono = False;
     GError *gtkerror=NULL;
@@ -1273,14 +1248,6 @@ main (int argc, char **argv)
        appData.monoMode = True;
     }
 
-    if (appData.monoMode && appData.debugMode) {
-#ifdef TODO_GTK
-       fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
-               (unsigned long) XWhitePixel(xDisplay, xScreen),
-               (unsigned long) XBlackPixel(xDisplay, xScreen));
-#endif
-    }
-
     ParseIcsTextColors();
 
 #ifdef TODO_GTK
@@ -1336,18 +1303,13 @@ main (int argc, char **argv)
     InitMenuMarkers();
 
     /*
-     * Create an icon.
+     * Create an icon. (Use two icons, to indicate whther it is white's or black's turn.)
      */
-#ifdef TODO_GTK
-    ReadBitmap(&wIconPixmap, "icon_white.bm",
-              icon_white_bits, icon_white_width, icon_white_height);
-    ReadBitmap(&bIconPixmap, "icon_black.bm",
-              icon_black_bits, icon_black_width, icon_black_height);
-    iconPixmap = wIconPixmap;
-    i = 0;
-    XtSetArg(args[i], XtNiconPixmap, iconPixmap);  i++;
-    XtSetValues(shellWidget, args, i);
-#endif
+    WhiteIcon  = gdk_pixbuf_new_from_file(SVGDIR "/icon_white.svg", NULL);
+    BlackIcon  = gdk_pixbuf_new_from_file(SVGDIR "/icon_black.svg", NULL);
+    mainwindowIcon = WhiteIcon;
+    gtk_window_set_icon(GTK_WINDOW(shellWidget), mainwindowIcon);
+
 
     /*
      * Create a cursor for the board widget.
@@ -1398,6 +1360,7 @@ main (int argc, char **argv)
     XtAddEventHandler(shellWidget, StructureNotifyMask, False,
                      (XtEventHandler) EventProc, NULL);
 #endif
+    g_signal_connect(shells[BoardWindow], "key-press-event", G_CALLBACK(KeyPressProc), NULL);
 
     /* [AS] Restore layout */
     if( wpMoveHistory.visible ) {
@@ -1672,6 +1635,26 @@ SetMenuEnables (Enables *enab)
   }
 }
 
+gboolean KeyPressProc(window, eventkey, data)
+     GtkWindow *window;
+     GdkEventKey  *eventkey;
+     gpointer data;
+{
+
+    MoveTypeInProc(eventkey); // pop up for typed in moves
+
+#ifdef TODO_GTK
+    /* check for other key values */
+    switch(eventkey->keyval) {
+        case GDK_question:
+         AboutGameEvent();
+         break;
+        default:
+         break;
+    }
+#endif
+    return False;
+}
 #ifdef TODO_GTK
 void
 KeyBindingProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
@@ -1719,10 +1702,7 @@ do_flash_delay (unsigned long msec)
 void
 FlashDelay (int flash_delay)
 {
-#ifdef TODO_GTK
-       XSync(xDisplay, False);
        if(flash_delay) do_flash_delay(flash_delay);
-#endif
 }
 
 double
@@ -1832,72 +1812,26 @@ DelayedDrag ()
 #endif
 }
 
+#ifdef TODO_GTK
 void
 EventProc (Widget widget, caddr_t unused, XEvent *event)
 {
-#ifdef TODO_GTK
     if(XtIsRealized(widget) && event->type == ConfigureNotify || appData.useStickyWindows)
        DelayedDrag(); // as long as events keep coming in faster than 50 msec, they destroy each other
-#endif
 }
+#endif
 
 /*
  * event handler for redrawing the board
  */
+#ifdef TODO_GTK
 void
 DrawPositionProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     DrawPosition(True, NULL);
 }
-
-
-#ifdef TODO_GTK
-void
-HandlePV (Widget w, XEvent * event, String * params, Cardinal * nParams)
-{   // [HGM] pv: walk PV
-    MovePV(event->xmotion.x, event->xmotion.y, lineGap + BOARD_HEIGHT * (squareSize + lineGap));
-}
-#endif
-
-static int savedIndex;  /* gross that this is global */
-
-void
-CommentClick (Widget w, XEvent * event, String * params, Cardinal * nParams)
-{
-#ifdef TODO_GTK
-       String val;
-       XawTextPosition index, dummy;
-       Arg arg;
-
-       XawTextGetSelectionPos(w, &index, &dummy);
-       XtSetArg(arg, XtNstring, &val);
-       XtGetValues(w, &arg, 1);
-       ReplaceComment(savedIndex, val);
-       if(savedIndex != currentMove) ToNrEvent(savedIndex);
-       LoadVariation( index, val ); // [HGM] also does the actual moving to it, now
 #endif
-}
-
-void
-EditCommentPopUp (int index, char *title, char *text)
-{
-    savedIndex = index;
-    if (text == NULL) text = "";
-    NewCommentPopup(title, text, index);
-}
-
-void
-CommentPopUp (char *title, char *text)
-{
-    savedIndex = currentMove; // [HGM] vari
-    NewCommentPopup(title, text, currentMove);
-}
 
-void
-CommentPopDown ()
-{
-    PopDown(CommentDlg);
-}
 
 
 /* Disable all user input other than deleting the window */
@@ -1927,10 +1861,7 @@ ModeHighlight ()
     static int oldPausing = FALSE;
     static GameMode oldmode = (GameMode) -1;
     char *wname;
-#ifdef TODO_GTK
-    Arg args[16];
-
-    if (!boardWidget || !XtIsRealized(boardWidget)) return;
+    if (!boardWidget) return;
 
     if (pausing != oldPausing) {
        oldPausing = pausing;
@@ -1940,19 +1871,11 @@ ModeHighlight ()
          /* Always toggle, don't set.  Previous code messes up when
             invoked while the button is pressed, as releasing it
             toggles the state again. */
-         {
-           Pixel oldbg, oldfg;
-           XtSetArg(args[0], XtNbackground, &oldbg);
-           XtSetArg(args[1], XtNforeground, &oldfg);
-           XtGetValues(optList[W_PAUSE].handle,
-                       args, 2);
-           XtSetArg(args[0], XtNbackground, oldfg);
-           XtSetArg(args[1], XtNforeground, oldbg);
-         }
-         XtSetValues(optList[W_PAUSE].handle, args, 2);
+           GdkColor color;     
+            gdk_color_parse( pausing ? "#808080" : "#F0F0F0", &color );
+            gtk_widget_modify_bg ( GTK_WIDGET(optList[W_PAUSE].handle), GTK_STATE_NORMAL, &color );
        }
     }
-#endif
 
     wname = ModeToWidgetName(oldmode);
     if (wname != NULL) {
@@ -2151,62 +2074,31 @@ PasteGameProc ()
 }
 
 
+#ifdef TODO_GTK
 void
 QuitWrapper (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     QuitProc();
 }
-
-int
-ShiftKeys ()
-{   // bassic primitive for determining if modifier keys are pressed
-    int i,j,  k=0;
-#ifdef TODO_GTK
-    long int codes[] = { XK_Meta_L, XK_Meta_R, XK_Control_L, XK_Control_R, XK_Shift_L, XK_Shift_R };
-    char keys[32];
-    XQueryKeymap(xDisplay,keys);
-    for(i=0; i<6; i++) {
-       k <<= 1;
-       j = XKeysymToKeycode(xDisplay, codes[i]);
-       k += ( (keys[j>>3]&1<<(j&7)) != 0 );
-    }
 #endif
-    return k;
-}
 
-static void
-MoveTypeInProc (Widget widget, caddr_t unused, XEvent *event)
+void MoveTypeInProc(eventkey)
+    GdkEventKey  *eventkey;
 {
-#ifdef TODO_GTK
     char buf[10];
-    KeySym sym;
-    int n = XLookupString(&(event->xkey), buf, 10, &sym, NULL);
-    if ( n == 1 && *buf >= 32 // printable
-        && !(ShiftKeys() & 0x3C) // no Alt, Ctrl
-       ) BoxAutoPopUp (buf);
-#endif
-}
-
-#ifdef TODO_GTK
-static void
-UpKeyProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
-{   // [HGM] input: let up-arrow recall previous line from history
-    IcsKey(1);
-}
 
-static void
-DownKeyProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
-{   // [HGM] input: let down-arrow recall next line from history
-    IcsKey(-1);
-}
+    // ingnore if ctrl or alt is pressed
+    if (eventkey->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK)) {
+        return;
+    }
 
-static void
-EnterKeyProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
-{
-    IcsKey(0);
+    buf[0]=eventkey->keyval;
+    buf[1]='\0';
+    if (*buf >= 32)        
+       BoxAutoPopUp (buf);
 }
 
-
+#ifdef TODO_GTK
 void
 TempBackwardProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
@@ -2348,22 +2240,16 @@ DisplayTimerLabel (Option *opt, char *color, long timer, int highlight)
     g_free(markup);
 }
 
-#ifdef TODO_GTK
-static Pixmap *clockIcons[] = { &wIconPixmap, &bIconPixmap };
-#endif
+static GdkPixbuf **clockIcons[] = { &WhiteIcon, &BlackIcon };
 
 void
 SetClockIcon (int color)
 {
-#ifdef TODO_GTK
-    Arg args[16];
-    Pixmap pm = *clockIcons[color];
-    if (iconPixmap != pm) {
-       iconPixmap = pm;
-       XtSetArg(args[0], XtNiconPixmap, iconPixmap);
-       XtSetValues(shellWidget, args, 1);
+    GdkPixbuf *pm = *clockIcons[color];
+    if (mainwindowIcon != pm) {
+        mainwindowIcon = pm;
+       gtk_window_set_icon(GTK_WINDOW(shellWidget), mainwindowIcon);
     }
-#endif
 }
 
 #define INPUT_SOURCE_BUF_SIZE 8192
@@ -2500,11 +2386,8 @@ FrameAlarm (int sig)
 void
 FrameDelay (int time)
 {
-#ifdef TODO_GTK
   struct itimerval delay;
 
-  XSync(xDisplay, False);
-
   if (time > 0) {
     frameWaiting = True;
     signal(SIGALRM, FrameAlarm);
@@ -2518,7 +2401,6 @@ FrameDelay (int time)
     delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
     setitimer(ITIMER_REAL, &delay, NULL);
   }
-#endif
 }
 
 #else
@@ -2529,6 +2411,8 @@ FrameDelay (int time)
 #ifdef TODO_GTK
   XSync(xDisplay, False);
 #endif
+//  gtk_main_iteration_do(False);
+
   if (time > 0)
     usleep(time * 1000);
 }
@@ -2562,3 +2446,104 @@ UpdateLogos (int displ)
     return;
 }
 
+void FileNamePopUpGTK(label, def, filter, proc, pathFlag, openMode, name, fp)
+     char *label;
+     char *def;
+     char *filter;
+     FileProc proc;
+     char *openMode;
+     Boolean pathFlag;
+     char **name;
+     FILE **fp;
+{
+  GtkWidget     *dialog;
+  GtkFileFilter *gtkfilter;
+  GtkFileFilter *gtkfilter_all;
+  char space[]     = " ";
+  char fileext[10] = "";
+  char *result     = NULL;
+  char *cp;
+
+  /* make a copy of the filter string, so that strtok can work with it*/
+  cp = strndup(filter,strlen(filter));
+
+  /* add filters for file extensions */
+  gtkfilter     = gtk_file_filter_new();
+  gtkfilter_all = gtk_file_filter_new();
+
+  /* one filter to show everything */
+  gtk_file_filter_add_pattern(gtkfilter_all, "*.*");
+  gtk_file_filter_set_name   (gtkfilter_all, "All Files");
+
+  /* add filter if present */
+  result = strtok(cp, space);
+  while( result != NULL  ) {
+    snprintf(fileext,10,"*%s",result);
+    result = strtok( NULL, space );
+    gtk_file_filter_add_pattern(gtkfilter, fileext);
+  };
+
+  /* second filter to only show what's useful */
+  gtk_file_filter_set_name (gtkfilter,filter);
+
+  if (openMode[0] == 'r')
+    {
+      dialog = gtk_file_chooser_dialog_new (label,
+                                           NULL,
+                                           GTK_FILE_CHOOSER_ACTION_OPEN,
+                                           GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                                           GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
+                                           NULL);
+    }
+  else
+    {
+      dialog = gtk_file_chooser_dialog_new (label,
+                                           NULL,
+                                           GTK_FILE_CHOOSER_ACTION_SAVE,
+                                           GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                                           GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
+                                           NULL);
+      /* add filename suggestions */
+      if (strlen(def) > 0 )
+       gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), def);
+
+      //gtk_file_chooser_set_create_folders(GTK_FILE_CHOOSER (dialog),TRUE);
+    }
+
+  /* add filters */
+  gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(dialog),gtkfilter_all);
+  gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(dialog),gtkfilter);
+  /* activate filter */
+  gtk_file_chooser_set_filter (GTK_FILE_CHOOSER(dialog),gtkfilter);
+
+  if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
+    {
+      char *filename;
+      FILE *f;
+
+      filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+
+      //see loadgamepopup
+      f = fopen(filename, openMode);
+      if (f == NULL)
+        {
+          DisplayError(_("Failed to open file"), errno);
+        }
+      else
+        {
+          /* TODO add indec */
+           *fp = f;
+           ASSIGN(*name, filename);
+           ScheduleDelayedEvent(DelayedLoad, 50);
+        }
+      g_free (filename);
+    };
+
+  gtk_widget_destroy (dialog);
+  ModeHighlight();
+
+  free(cp);
+  return;
+
+}
+