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