first draft of a MoveHistory window
[xboard.git] / callback.c
1 #include <gtk/gtk.h>
2 #include "common.h"
3 #include "xboard.h"
4 #include <errno.h>
5 #include "backend.h"
6
7 #ifdef ENABLE_NLS
8 # define  _(s) gettext (s)
9 # define N_(s) gettext_noop (s)
10 #else
11 # define  _(s) (s)
12 # define N_(s)  s
13 #endif
14
15
16 extern GtkWidget  *about;
17 extern GtkWidget  *GUI_Window;
18
19 extern char *programVersion;
20 extern int errorExitStatus;
21 extern int promotionUp;
22 extern int fromX;
23 extern int fromY;
24 extern int toX;
25 extern int toY;
26
27 void
28 QuitProc (object, user_data)
29      GtkObject *object;
30      gpointer user_data;
31 {
32   gtk_main_quit();
33   ExitEvent(0);
34 }
35
36 /* Help Menu */
37 void InfoProc(object, user_data)
38      GtkObject *object;
39      gpointer user_data;
40 {
41     char buf[MSG_SIZ];
42     snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
43             INFODIR, INFOFILE);
44     system(buf);
45     return;
46 }
47
48 void ManProc(object, user_data)
49      GtkObject *object;
50      gpointer user_data;
51 {
52     char buf[MSG_SIZ];
53     snprintf(buf, sizeof(buf), "xterm -e man xboard &");
54     system(buf);
55     return;
56 }
57
58 void HintProc(object, user_data)
59      GtkObject *object;
60      gpointer user_data;
61 {
62     HintEvent();
63     return;
64 }
65
66 void BookProc(object, user_data)
67      GtkObject *object;
68      gpointer user_data;
69 {
70     BookEvent();
71     return;
72 }
73
74 void AboutProc (object, user_data)
75      GtkObject *object;
76      gpointer user_data;
77 {
78   GtkWidget               *about;
79
80   const gchar *authors[] = {"Tim Mann <tim@tim-mann.org>",
81                             "John Chanak",
82                             "Evan Welsh <Evan.Welsh@msdw.com>",
83                             "Elmar Bartel <bartel@informatik.tu-muenchen.de>",
84                             "Jochen Wiedmann",
85                             "Frank McIngvale",
86                             "Hugh Fisher <Hugh.Fisher@cs.anu.edu.au>",
87                             "Allessandro Scotti",
88                             "H.G. Muller <h.g.muller AT hccnet DOT nl>",
89                             "Eric Mullins <emwine AT earthlink DOT net>",
90                             "Arun Persaud <arun@nubati.net>"};
91
92   /* set up about window */
93   about =  GTK_WIDGET(gtk_about_dialog_new());
94
95   /* fill in some information */
96   char buf[MSG_SIZ];
97 #if ZIPPY
98   char *zippy = " (with Zippy code)";
99 #else
100   char *zippy = "";
101 #endif
102   sprintf(buf, "%s%s",  programVersion, zippy);
103
104   gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(about),buf);
105
106   gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(about),
107                                  "Copyright 1991 Digital Equipment Corporation\n"
108                                  "Enhancements Copyright 1992-2009 Free Software Foundation\n"
109                                  "Enhancements Copyright 2005 Alessandro Scotti");
110   gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(about),"http://www.gnu.org/software/xboard/");
111   gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(about),authors);
112   gtk_about_dialog_set_translator_credits(GTK_ABOUT_DIALOG(about),
113                                           " A. Alper (turkish)\n"
114                                           " A. Persaud (german)\n");
115
116   /* end set up about window */
117   gtk_dialog_run(GTK_DIALOG (about));
118   gtk_widget_destroy(about);
119 }
120
121 /* End Help Menu */
122
123 void IcsClientProc(object, user_data)
124      GtkObject *object;
125      gpointer user_data;
126 {
127     IcsClientEvent();
128     return;
129 }
130
131 void LoadNextGameProc(object, user_data)
132      GtkObject *object;
133      gpointer user_data;
134 {
135     ReloadGame(1);
136     return;
137 }
138
139 void LoadPrevGameProc(object, user_data)
140      GtkObject *object;
141      gpointer user_data;
142 {
143     ReloadGame(-1);
144     return;
145 }
146
147 void ReloadGameProc(object, user_data)
148      GtkObject *object;
149      gpointer user_data;
150 {
151     ReloadGame(0);
152     return;
153 }
154
155 void MachineWhiteProc(object, user_data)
156      GtkObject *object;
157      gpointer user_data;
158 {
159     MachineWhiteEvent();
160     return;
161 }
162
163 void MachineBlackProc(object, user_data)
164      GtkObject *object;
165      gpointer user_data;
166 {
167     MachineBlackEvent();
168     return;
169 }
170
171 void TwoMachinesProc(object, user_data)
172      GtkObject *object;
173      gpointer user_data;
174 {
175     TwoMachinesEvent();
176     return;
177 }
178
179 void AcceptProc(object, user_data)
180      GtkObject *object;
181      gpointer user_data;
182 {
183     AcceptEvent();
184     return;
185 }
186
187 void DeclineProc(object, user_data)
188      GtkObject *object;
189      gpointer user_data;
190 {
191     DeclineEvent();
192     return;
193 }
194
195 void RematchProc(object, user_data)
196      GtkObject *object;
197      gpointer user_data;
198 {
199     RematchEvent();
200     return;
201 }
202
203 void CallFlagProc(object, user_data)
204      GtkObject *object;
205      gpointer user_data;
206 {
207     CallFlagEvent();
208     return;
209 }
210
211 void DrawProc(object, user_data)
212      GtkObject *object;
213      gpointer user_data;
214 {
215     DrawEvent();
216     return;
217 }
218
219 void AbortProc(object, user_data)
220      GtkObject *object;
221      gpointer user_data;
222 {
223     AbortEvent();
224     return;
225 }
226
227 void AdjournProc(object, user_data)
228      GtkObject *object;
229      gpointer user_data;
230 {
231     AdjournEvent();
232     return;
233 }
234
235 void ResignProc(object, user_data)
236      GtkObject *object;
237      gpointer user_data;
238 {
239     ResignEvent();
240     return;
241 }
242
243 void StopObservingProc(object, user_data)
244      GtkObject *object;
245      gpointer user_data;
246 {
247     StopObservingEvent();
248     return;
249 }
250
251 void StopExaminingProc(object, user_data)
252      GtkObject *object;
253      gpointer user_data;
254 {
255     StopExaminingEvent();
256     return;
257 }
258
259 void AdjuWhiteProc(object, user_data)
260      GtkObject *object;
261      gpointer user_data;
262 {
263     UserAdjudicationEvent(+1);
264     return;
265 }
266
267 void AdjuBlackProc(object, user_data)
268      GtkObject *object;
269      gpointer user_data;
270 {
271     UserAdjudicationEvent(-1);
272     return;
273 }
274
275 void AdjuDrawProc(object, user_data)
276      GtkObject *object;
277      gpointer user_data;
278 {
279     UserAdjudicationEvent(0);
280     return;
281 }
282
283 void BackwardProc(object, user_data)
284      GtkObject *object;
285      gpointer user_data;
286 {
287     BackwardEvent();
288     return;
289 }
290
291 void ForwardProc(object, user_data)
292      GtkObject *object;
293      gpointer user_data;
294 {
295     ForwardEvent();
296     return;
297 }
298
299 void ToStartProc(object, user_data)
300      GtkObject *object;
301      gpointer user_data;
302 {
303     ToStartEvent();
304     return;
305 }
306
307 void ToEndProc(object, user_data)
308      GtkObject *object;
309      gpointer user_data;
310 {
311     ToEndEvent();
312     return;
313 }
314
315 void RevertProc(object, user_data)
316      GtkObject *object;
317      gpointer user_data;
318 {
319     RevertEvent();
320     return;
321 }
322
323 void TruncateGameProc(object, user_data)
324      GtkObject *object;
325      gpointer user_data;
326 {
327     TruncateGameEvent();
328     return;
329 }
330
331 void MoveNowProc(object, user_data)
332      GtkObject *object;
333      gpointer user_data;
334 {
335     MoveNowEvent();
336     return;
337 }
338
339 void RetractMoveProc(object, user_data)
340      GtkObject *object;
341      gpointer user_data;
342 {
343     RetractMoveEvent();
344     return;
345 }
346
347 /* Option Menu */
348 void FlipViewProc(object, user_data)
349      GtkObject *object;
350      gpointer user_data;
351 {
352     flipView = !flipView;
353     DrawPosition(True, NULL);
354     return;
355 }
356
357
358 gboolean CloseWindowProc(GtkWidget *button)
359 {
360     gtk_widget_destroy(gtk_widget_get_toplevel(button));
361     return TRUE;
362 }
363
364 void
365 ResetProc (object, user_data)
366      GtkObject *object;
367      gpointer user_data;
368 {
369   ResetGameEvent();
370   AnalysisPopDown();
371 }
372
373 void WhiteClockProc(object, user_data)
374      GtkObject *object;
375      gpointer user_data;
376 {
377     if (gameMode == EditPosition || gameMode == IcsExamining) {
378         SetWhiteToPlayEvent();
379     } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
380         CallFlagEvent();
381     }
382 }
383
384 void BlackClockProc(object, user_data)
385      GtkObject *object;
386      gpointer user_data;
387 {
388     if (gameMode == EditPosition || gameMode == IcsExamining) {
389         SetBlackToPlayEvent();
390     } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
391         CallFlagEvent();
392     }
393 }
394
395
396 void ShowCoordsProc(object, user_data)
397      GtkObject *object;
398      gpointer user_data;
399 {
400     appData.showCoords = !appData.showCoords;
401
402     DrawPosition(True, NULL);
403 }
404
405 void ErrorPopDownProc(object, user_data)
406      GtkObject *object;
407      gpointer user_data;
408 {
409   gtk_widget_destroy(GTK_WIDGET(object));
410   ErrorPopDown();
411 }
412
413 void PauseProc(object, user_data)
414      GtkObject *object;
415      gpointer user_data;
416 {
417     // todo this toggling of the pause button doesn't seem to work?
418     // e.g. select pause from buttonbar doesn't activate menumode.pause
419   PauseEvent();
420 }
421
422
423 void LoadGameProc(object, user_data)
424      GtkObject *object;
425      gpointer user_data;
426 {
427   GtkWidget *dialog;
428   dialog = gtk_file_chooser_dialog_new (_("Load game file name?"),
429                                         GTK_WINDOW(GUI_Window),
430                                         GTK_FILE_CHOOSER_ACTION_OPEN,
431                                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
432                                         GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
433                                         NULL);
434   if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
435     {
436       char *filename;
437       FILE *f;
438
439       filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
440
441       //see loadgamepopup
442       f = fopen(filename, "rb");
443       if (f == NULL) 
444         {
445           DisplayError(_("Failed to open file"), errno);
446         }
447       else 
448         {
449           /* TODO add indec */
450           (void) LoadGamePopUp(f, 0, filename);
451         }
452       g_free (filename);
453     };
454   
455   gtk_widget_destroy (dialog);
456   ModeHighlight();
457   
458   return;
459 }
460
461
462 /*************
463  * EVENTS
464  *************/
465
466 void EventProc(window, event, data)
467      GtkWindow *window;
468      GdkEvent *event;
469      gpointer data;
470 {
471   /* todo do we still need this?
472     if (!XtIsRealized(widget))
473       return;
474   */
475
476     switch (event->type) {
477       case GDK_EXPOSE:
478         if (event->expose.count > 0) return;  /* no clipping is done */
479         DrawPosition(True, NULL);
480         break;
481       default:
482         return;
483     }
484 }
485
486
487 /*
488  * event handler for parsing user moves
489  */
490 void UserMoveProc(window, event, data)
491      GtkWindow *window;
492      GdkEvent *event;
493      gpointer data;
494 {
495     int x, y;
496     Boolean saveAnimate;
497     static int second = 0;
498
499     if (errorExitStatus != -1) return;
500
501     if (event->type == GDK_BUTTON_PRESS) ErrorPopDown();
502
503     if (promotionUp)
504       {
505         if (event->type == GDK_BUTTON_PRESS)
506           {
507             /* todo add promotionshellwidget
508                XtPopdown(promotionShell);
509                XtDestroyWidget(promotionShell); */
510             promotionUp = False;
511             ClearHighlights();
512             fromX = fromY = -1;
513           }
514         else
515           {
516             return;
517           }
518       }
519
520     x = EventToSquare( (int)event->button.x, BOARD_WIDTH  );
521     y = EventToSquare( (int)event->button.y, BOARD_HEIGHT );
522     if (!flipView && y >= 0)
523       {
524         y = BOARD_HEIGHT - 1 - y;
525       }
526     if (flipView && x >= 0)
527       {
528         x = BOARD_WIDTH - 1 - x;
529       }
530
531     if (fromX == -1)
532       {
533         if (event->type == ButtonPress)
534           {
535             /* First square */
536             if (OKToStartUserMove(x, y))
537               {
538                 fromX = x;
539                 fromY = y;
540                 second = 0;
541                 DragPieceBegin(event->button.x, event->button.y);
542                 if (appData.highlightDragging)
543                   {
544                     SetHighlights(x, y, -1, -1);
545                   }
546               }
547           }
548         return;
549       }
550
551     /* fromX != -1 */
552     if (event->type == GDK_BUTTON_PRESS && gameMode != EditPosition &&
553         x >= 0 && y >= 0) {
554         ChessSquare fromP;
555         ChessSquare toP;
556         /* Check if clicking again on the same color piece */
557         fromP = boards[currentMove][fromY][fromX];
558         toP = boards[currentMove][y][x];
559         if ((WhitePawn <= fromP && fromP <= WhiteKing &&
560              WhitePawn <= toP && toP <= WhiteKing) ||
561             (BlackPawn <= fromP && fromP <= BlackKing &&
562              BlackPawn <= toP && toP <= BlackKing)) {
563             /* Clicked again on same color piece -- changed his mind */
564             second = (x == fromX && y == fromY);
565             if (appData.highlightDragging) {
566                 SetHighlights(x, y, -1, -1);
567             } else {
568                 ClearHighlights();
569             }
570             if (OKToStartUserMove(x, y)) {
571                 fromX = x;
572                 fromY = y;
573                 DragPieceBegin(event->button.x, event->button.y);
574             }
575             return;
576         }
577     }
578
579     if (event->type == GDK_BUTTON_RELEASE &&    x == fromX && y == fromY)
580       {
581         DragPieceEnd(event->button.x, event->button.y);
582         if (appData.animateDragging)
583           {
584             /* Undo animation damage if any */
585             DrawPosition(FALSE, NULL);
586           }
587         if (second)
588           {
589             /* Second up/down in same square; just abort move */
590             second = 0;
591             fromX = fromY = -1;
592             ClearHighlights();
593             gotPremove = 0;
594             ClearPremoveHighlights();
595           }
596         else
597           {
598             /* First upclick in same square; start click-click mode */
599             SetHighlights(x, y, -1, -1);
600           }
601         return;
602       }
603
604     /* Completed move */
605     toX = x;
606     toY = y;
607     saveAnimate = appData.animate;
608
609     if (event->type == GDK_BUTTON_PRESS)
610       {
611         /* Finish clickclick move */
612         if (appData.animate || appData.highlightLastMove)
613           {
614             SetHighlights(fromX, fromY, toX, toY);
615           }
616         else
617           {
618             ClearHighlights();
619           }
620       }
621     else
622       {
623         /* Finish drag move */
624         if (appData.highlightLastMove)
625           {
626             SetHighlights(fromX, fromY, toX, toY);
627           }
628         else
629           {
630             ClearHighlights();
631           }
632         DragPieceEnd(event->button.x, event->button.y);
633         /* Don't animate move and drag both */
634         appData.animate = FALSE;
635       }
636
637     if (IsPromotion(fromX, fromY, toX, toY))
638       {
639         if (appData.alwaysPromoteToQueen)
640           {
641             UserMoveEvent(fromX, fromY, toX, toY, 'q');
642             if (!appData.highlightLastMove || gotPremove) ClearHighlights();
643             if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
644             fromX = fromY = -1;
645           }
646         else
647           {
648             SetHighlights(fromX, fromY, toX, toY);
649             PromotionPopUp();
650           }
651       }
652     else
653       {
654         UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
655
656         if (!appData.highlightLastMove || gotPremove) ClearHighlights();
657         if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
658         fromX = fromY = -1;
659       }
660
661     appData.animate = saveAnimate;
662     if (appData.animate || appData.animateDragging) {
663         /* Undo animation damage if needed */
664         DrawPosition(FALSE, NULL);
665     }
666
667     return;
668 }
669
670 void GetMoveListProc(object, user_data)
671      GtkObject *object;
672      gpointer user_data;
673 {
674   appData.getMoveList = !appData.getMoveList;
675   
676   if (appData.getMoveList) 
677     {
678       GetMoveListEvent();
679     } 
680
681   // gets set automatically? if we set it with set_active we end up in an endless loop switching between 0 and 1
682   //  gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (object),(gboolean) appData.getMoveList );
683   
684   return;
685 }