moved show/hide thinking procs to gtk
[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 ShowThinkingProc(object, user_data)
349      GtkObject *object;
350      gpointer user_data;
351 {
352     appData.showThinking = !appData.showThinking; 
353     ShowThinkingEvent();
354
355     return;
356 }
357
358 void HideThinkingProc(object, user_data)
359      GtkObject *object;
360      gpointer user_data;
361 {
362     appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman;
363     ShowThinkingEvent();
364
365     return;
366 }
367
368 void FlipViewProc(object, user_data)
369      GtkObject *object;
370      gpointer user_data;
371 {
372     flipView = !flipView;
373     DrawPosition(True, NULL);
374     return;
375 }
376
377
378 gboolean CloseWindowProc(GtkWidget *button)
379 {
380     gtk_widget_destroy(gtk_widget_get_toplevel(button));
381     return TRUE;
382 }
383
384 void
385 ResetProc (object, user_data)
386      GtkObject *object;
387      gpointer user_data;
388 {
389   ResetGameEvent();
390   AnalysisPopDown();
391 }
392
393 void WhiteClockProc(object, user_data)
394      GtkObject *object;
395      gpointer user_data;
396 {
397     if (gameMode == EditPosition || gameMode == IcsExamining) {
398         SetWhiteToPlayEvent();
399     } else if (gameMode == IcsPlayingBlack || gameMode == MachinePlaysWhite) {
400         CallFlagEvent();
401     }
402 }
403
404 void BlackClockProc(object, user_data)
405      GtkObject *object;
406      gpointer user_data;
407 {
408     if (gameMode == EditPosition || gameMode == IcsExamining) {
409         SetBlackToPlayEvent();
410     } else if (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack) {
411         CallFlagEvent();
412     }
413 }
414
415
416 void ShowCoordsProc(object, user_data)
417      GtkObject *object;
418      gpointer user_data;
419 {
420     appData.showCoords = !appData.showCoords;
421
422     DrawPosition(True, NULL);
423 }
424
425 void ErrorPopDownProc(object, user_data)
426      GtkObject *object;
427      gpointer user_data;
428 {
429   gtk_widget_destroy(GTK_WIDGET(object));
430   ErrorPopDown();
431 }
432
433 void PauseProc(object, user_data)
434      GtkObject *object;
435      gpointer user_data;
436 {
437     // todo this toggling of the pause button doesn't seem to work?
438     // e.g. select pause from buttonbar doesn't activate menumode.pause
439   PauseEvent();
440 }
441
442
443 void LoadGameProc(object, user_data)
444      GtkObject *object;
445      gpointer user_data;
446 {
447   GtkWidget *dialog;
448   dialog = gtk_file_chooser_dialog_new (_("Load game file name?"),
449                                         GTK_WINDOW(GUI_Window),
450                                         GTK_FILE_CHOOSER_ACTION_OPEN,
451                                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
452                                         GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
453                                         NULL);
454   if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
455     {
456       char *filename;
457       FILE *f;
458
459       filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
460
461       //see loadgamepopup
462       f = fopen(filename, "rb");
463       if (f == NULL) 
464         {
465           DisplayError(_("Failed to open file"), errno);
466         }
467       else 
468         {
469           /* TODO add indec */
470           (void) LoadGamePopUp(f, 0, filename);
471         }
472       g_free (filename);
473     };
474   
475   gtk_widget_destroy (dialog);
476   ModeHighlight();
477   
478   return;
479 }
480
481
482 /*************
483  * EVENTS
484  *************/
485
486 void EventProc(window, event, data)
487      GtkWindow *window;
488      GdkEvent *event;
489      gpointer data;
490 {
491   /* todo do we still need this?
492     if (!XtIsRealized(widget))
493       return;
494   */
495
496     switch (event->type) {
497       case GDK_EXPOSE:
498         if (event->expose.count > 0) return;  /* no clipping is done */
499         DrawPosition(True, NULL);
500         break;
501       default:
502         return;
503     }
504 }
505
506
507 /*
508  * event handler for parsing user moves
509  */
510 void UserMoveProc(window, event, data)
511      GtkWindow *window;
512      GdkEvent *event;
513      gpointer data;
514 {
515     int x, y;
516     Boolean saveAnimate;
517     static int second = 0;
518
519     if (errorExitStatus != -1) return;
520
521     if (event->type == GDK_BUTTON_PRESS) ErrorPopDown();
522
523     if (promotionUp)
524       {
525         if (event->type == GDK_BUTTON_PRESS)
526           {
527             /* todo add promotionshellwidget
528                XtPopdown(promotionShell);
529                XtDestroyWidget(promotionShell); */
530             promotionUp = False;
531             ClearHighlights();
532             fromX = fromY = -1;
533           }
534         else
535           {
536             return;
537           }
538       }
539
540     x = EventToSquare( (int)event->button.x, BOARD_WIDTH  );
541     y = EventToSquare( (int)event->button.y, BOARD_HEIGHT );
542     if (!flipView && y >= 0)
543       {
544         y = BOARD_HEIGHT - 1 - y;
545       }
546     if (flipView && x >= 0)
547       {
548         x = BOARD_WIDTH - 1 - x;
549       }
550
551     if (fromX == -1)
552       {
553         if (event->type == ButtonPress)
554           {
555             /* First square */
556             if (OKToStartUserMove(x, y))
557               {
558                 fromX = x;
559                 fromY = y;
560                 second = 0;
561                 DragPieceBegin(event->button.x, event->button.y);
562                 if (appData.highlightDragging)
563                   {
564                     SetHighlights(x, y, -1, -1);
565                   }
566               }
567           }
568         return;
569       }
570
571     /* fromX != -1 */
572     if (event->type == GDK_BUTTON_PRESS && gameMode != EditPosition &&
573         x >= 0 && y >= 0) {
574         ChessSquare fromP;
575         ChessSquare toP;
576         /* Check if clicking again on the same color piece */
577         fromP = boards[currentMove][fromY][fromX];
578         toP = boards[currentMove][y][x];
579         if ((WhitePawn <= fromP && fromP <= WhiteKing &&
580              WhitePawn <= toP && toP <= WhiteKing) ||
581             (BlackPawn <= fromP && fromP <= BlackKing &&
582              BlackPawn <= toP && toP <= BlackKing)) {
583             /* Clicked again on same color piece -- changed his mind */
584             second = (x == fromX && y == fromY);
585             if (appData.highlightDragging) {
586                 SetHighlights(x, y, -1, -1);
587             } else {
588                 ClearHighlights();
589             }
590             if (OKToStartUserMove(x, y)) {
591                 fromX = x;
592                 fromY = y;
593                 DragPieceBegin(event->button.x, event->button.y);
594             }
595             return;
596         }
597     }
598
599     if (event->type == GDK_BUTTON_RELEASE &&    x == fromX && y == fromY)
600       {
601         DragPieceEnd(event->button.x, event->button.y);
602         if (appData.animateDragging)
603           {
604             /* Undo animation damage if any */
605             DrawPosition(FALSE, NULL);
606           }
607         if (second)
608           {
609             /* Second up/down in same square; just abort move */
610             second = 0;
611             fromX = fromY = -1;
612             ClearHighlights();
613             gotPremove = 0;
614             ClearPremoveHighlights();
615           }
616         else
617           {
618             /* First upclick in same square; start click-click mode */
619             SetHighlights(x, y, -1, -1);
620           }
621         return;
622       }
623
624     /* Completed move */
625     toX = x;
626     toY = y;
627     saveAnimate = appData.animate;
628
629     if (event->type == GDK_BUTTON_PRESS)
630       {
631         /* Finish clickclick move */
632         if (appData.animate || appData.highlightLastMove)
633           {
634             SetHighlights(fromX, fromY, toX, toY);
635           }
636         else
637           {
638             ClearHighlights();
639           }
640       }
641     else
642       {
643         /* Finish drag move */
644         if (appData.highlightLastMove)
645           {
646             SetHighlights(fromX, fromY, toX, toY);
647           }
648         else
649           {
650             ClearHighlights();
651           }
652         DragPieceEnd(event->button.x, event->button.y);
653         /* Don't animate move and drag both */
654         appData.animate = FALSE;
655       }
656
657     if (IsPromotion(fromX, fromY, toX, toY))
658       {
659         if (appData.alwaysPromoteToQueen)
660           {
661             UserMoveEvent(fromX, fromY, toX, toY, 'q');
662             if (!appData.highlightLastMove || gotPremove) ClearHighlights();
663             if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
664             fromX = fromY = -1;
665           }
666         else
667           {
668             SetHighlights(fromX, fromY, toX, toY);
669             PromotionPopUp();
670           }
671       }
672     else
673       {
674         UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);
675
676         if (!appData.highlightLastMove || gotPremove) ClearHighlights();
677         if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
678         fromX = fromY = -1;
679       }
680
681     appData.animate = saveAnimate;
682     if (appData.animate || appData.animateDragging) {
683         /* Undo animation damage if needed */
684         DrawPosition(FALSE, NULL);
685     }
686
687     return;
688 }
689
690 void GetMoveListProc(object, user_data)
691      GtkObject *object;
692      gpointer user_data;
693 {
694   appData.getMoveList = !appData.getMoveList;
695   
696   if (appData.getMoveList) 
697     {
698       GetMoveListEvent();
699     } 
700
701   // gets set automatically? if we set it with set_active we end up in an endless loop switching between 0 and 1
702   //  gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (object),(gboolean) appData.getMoveList );
703   
704   return;
705 }