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