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