1 /*
2 
3     eboard - chess client
4     http://www.bergo.eng.br/eboard
5     https://github.com/fbergo/eboard
6     Copyright (C) 2000-2016 Felipe Bergo
7     fbergo/at/gmail/dot/com
8 
9     This program is free software; you can redistribute it and/or modify
10     it under the terms of the GNU General Public License as published by
11     the Free Software Foundation; either version 2 of the License, or
12     (at your option) any later version.
13 
14     This program is distributed in the hope that it will be useful,
15     but WITHOUT ANY WARRANTY; without even the implied warranty of
16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17     GNU General Public License for more details.
18 
19     You should have received a copy of the GNU General Public License
20     along with this program; if not, write to the Free Software
21     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22 
23 */
24 
25 #include <iostream>
26 #include <stdio.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <sys/types.h>
30 #include <dirent.h>
31 #include <gdk/gdkkeysyms.h>
32 #include "mainwindow.h"
33 #include "chess.h"
34 #include "bugpane.h"
35 #include "global.h"
36 #include "p2p.h"
37 
38 #include "config.h"
39 
40 #include "xpm/icon-eboard.xpm"
41 
42 #include "xpm/back1.xpm"
43 #include "xpm/backn.xpm"
44 #include "xpm/forward1.xpm"
45 #include "xpm/forwardn.xpm"
46 #include "xpm/movelist.xpm"
47 #include "xpm/flip.xpm"
48 #include "xpm/trash.xpm"
49 #include "xpm/toscratch.xpm"
50 
51 #include "xpm/sealoff.xpm"
52 #include "xpm/sealon.xpm"
53 
54 GdkWindow * MainWindow::RefWindow=0;
55 
56 static GtkItemFactoryEntry mainwindow_mainmenu[] = {
57   { (gchar *)N_("/_Peer"),                NULL,         NULL, 0, (gchar *)"<Branch>" },
58   { (gchar *)N_("/Peer/Connect to _FICS"),NULL,GTK_SIGNAL_FUNC(peer_connect_fics),0,NULL },
59   { (gchar *)N_("/Peer/ICS _Bookmarks"),  NULL, NULL, FA_ICSBOOKMARKS, (gchar *)"<Branch>" },
60   { (gchar *)N_("/Peer/_Connect to Other Server..."),NULL,GTK_SIGNAL_FUNC(peer_connect_ask),0,NULL },
61   { (gchar *)N_("/Peer/Direct connect with _Remote eboard..."),NULL,GTK_SIGNAL_FUNC(peer_connect_p2p),0,NULL },
62   { (gchar *)N_("/Peer/sep4"),            NULL,           NULL, 0, (gchar *)"<Separator>" },
63   { (gchar *)N_("/Peer/Play against _Engine"),NULL, NULL, 0,(gchar *)"<Branch>" },
64   { (gchar *)N_("/Peer/Play against Engine/GNU Chess _4..."),NULL,GTK_SIGNAL_FUNC(peer_connect_gnuchess4),0, NULL },
65   { (gchar *)N_("/Peer/Play against Engine/_Sjeng..."),NULL,GTK_SIGNAL_FUNC(peer_connect_sjeng), 0, NULL },
66   { (gchar *)N_("/Peer/Play against Engine/Cr_afty..."),NULL,GTK_SIGNAL_FUNC(peer_connect_crafty), 0, NULL },
67   { (gchar *)N_("/Peer/Play against Engine/sep1"),NULL,NULL,0,(gchar *)"<Separator>" },
68   { (gchar *)N_("/Peer/Play against Engine/_Generic Engine..."),NULL,GTK_SIGNAL_FUNC(peer_connect_xboard), 0,NULL },
69   { (gchar *)N_("/Peer/Engine B_ookmarks"), NULL, NULL, FA_ENGBOOKMARKS,(gchar *)"<Branch>" },
70   { (gchar *)N_("/Peer/sep3"),            NULL,           NULL, 0, (gchar *)"<Separator>" },
71   { (gchar *)N_("/Peer/_Empty Scratch Board"), NULL,  GTK_SIGNAL_FUNC(peer_scratch_empty), 0, NULL },
72   { (gchar *)N_("/Peer/_Scratch Board with Initial Position"),NULL,  GTK_SIGNAL_FUNC(peer_scratch_initial), 0, NULL },
73   { (gchar *)N_("/Peer/sep3"),            NULL,           NULL, 0, (gchar *)"<Separator>" },
74   { (gchar *)N_("/Peer/_Disconnect"),     NULL,  GTK_SIGNAL_FUNC(peer_disconnect), 0, NULL },
75   { (gchar *)N_("/Peer/sep2"),            NULL,           NULL, 0, (gchar *)"<Separator>" },
76   { (gchar *)N_("/Peer/_Quit"),           NULL,  GTK_SIGNAL_FUNC(mainwindow_destroy), 0, NULL },
77   { (gchar *)N_("/_Game"),                NULL,         NULL, 0, (gchar *)"<Branch>" },
78   { (gchar *)N_("/Game/_Resign"),         NULL,  GTK_SIGNAL_FUNC(game_resign), 0, NULL },
79   { (gchar *)N_("/Game/_Offer Draw"),     NULL,  GTK_SIGNAL_FUNC(game_draw), 0, NULL },
80   { (gchar *)N_("/Game/_Abort"),          NULL,  GTK_SIGNAL_FUNC(game_abort), 0, NULL },
81   { (gchar *)N_("/Game/Ad_journ"),        NULL,  GTK_SIGNAL_FUNC(game_adjourn), 0, NULL },
82   { (gchar *)N_("/Game/Retract _Move"),   NULL,  GTK_SIGNAL_FUNC(game_retract), 0, NULL },
83   { (gchar *)N_("/_Settings"),            NULL,         NULL, 0, (gchar *)"<Branch>" },
84   { (gchar *)N_("/Settings/_Highlight Last Move"),NULL, NULL, FA_HIGHLIGHT, (gchar *)"<CheckItem>" },
85   { (gchar *)N_("/Settings/_Animate Moves"),NULL,       NULL, FA_ANIMATE,(gchar *)"<CheckItem>" },
86   { (gchar *)N_("/Settings/Pre_move"),      NULL,       NULL, FA_PREMOVE,(gchar *)"<CheckItem>" },
87   { (gchar *)N_("/Settings/Sho_w Coordinates"), NULL,   NULL, FA_COORDS,(gchar *)"<CheckItem>" },
88   { (gchar *)N_("/Settings/sep3"),          NULL,       NULL, 0, (gchar *)"<Separator>" },
89   { (gchar *)N_("/Settings/_Beep on Opponent Moves"),NULL,NULL, FA_MOVEBEEP,(gchar *)"<CheckItem>" },
90   { (gchar *)N_("/Settings/_Enable Other Sounds"),NULL,NULL,    FA_SOUND,(gchar *)"<CheckItem>" },
91   { (gchar *)N_("/Settings/sep3"),          NULL,       NULL, 0, (gchar *)"<Separator>" },
92   { (gchar *)N_("/Settings/_ICS Behavior"),   NULL,       NULL, 0, (gchar *)"<Branch>" },
93   { (gchar *)N_("/Settings/ICS Behavior/Popup Board Panes _Upon Creation"),NULL,NULL,FA_POPUP,(gchar *)"<CheckItem>" },
94   { (gchar *)N_("/Settings/ICS Behavior/Smart _Discard Observed Boards After Game Ends"),NULL,NULL,FA_SMART,(gchar *)"<CheckItem>" },
95   { (gchar *)N_("/Settings/sep3"),          NULL,       NULL, 0, (gchar *)"<Separator>" },
96   { (gchar *)N_("/Settings/Enable Legality _Checking"),NULL,NULL,FA_LEGALITY,(gchar *)"<CheckItem>"},
97   { (gchar *)N_("/Settings/sep3"),          NULL,       NULL, 0, (gchar *)"<Separator>" },
98   { (gchar *)N_("/Settings/_Vectorized Pieces (Faster Rendering)"),NULL,NULL,FA_VECTOR,(gchar *)"<CheckItem>" },
99   { (gchar *)N_("/Settings/Bitmapped Piece _Sets"),   NULL,       NULL, 0, (gchar *)"<Branch>" },
100   { (gchar *)N_("/Settings/Bitmapped Piece Sets/Load _Theme"), NULL,NULL, FA_LOADTHEME, (gchar *)"<Branch>" },
101   { (gchar *)N_("/Settings/Bitmapped Piece Sets/Load _Pieces Only"),NULL,NULL,FA_LOADPIECES,(gchar *)"<Branch>"},
102   { (gchar *)N_("/Settings/Bitmapped Piece Sets/Load _Squares Only"), NULL, NULL, FA_LOADSQUARES, (gchar *)"<Branch>" },
103   { (gchar *)N_("/Settings/sep3"),          NULL,       NULL, 0, (gchar *)"<Separator>" },
104   { (gchar *)N_("/Settings/_Preferences..."), NULL,  GTK_SIGNAL_FUNC(sett_prefs), 0, NULL },
105   { (gchar *)N_("/_Windows"),              NULL,         NULL,0, (gchar *)"<Branch>" },
106   { (gchar *)N_("/Windows/_Games on Server..."),NULL,  GTK_SIGNAL_FUNC(windows_games), 0, NULL },
107   { (gchar *)N_("/Windows/_Ads on Server..."),NULL,  GTK_SIGNAL_FUNC(windows_sough), 0, NULL },
108   { (gchar *)N_("/Windows/sep1"), NULL, NULL, 0, (gchar *)"<Separator>" },
109   { (gchar *)N_("/Windows/Games on _Client..."),NULL,  GTK_SIGNAL_FUNC(windows_stock), 0, NULL },
110   { (gchar *)N_("/Windows/sep2"), NULL, NULL, 0, (gchar *)"<Separator>" },
111   { (gchar *)N_("/Windows/_Run Script..."),  NULL,  GTK_SIGNAL_FUNC(windows_script), 0, NULL },
112   { (gchar *)N_("/Windows/sep3"), NULL, NULL, 0, (gchar *)"<Separator>" },
113   { (gchar *)N_("/Windows/_Detached Console"),  NULL,  GTK_SIGNAL_FUNC(windows_detached), 0, NULL },
114   { (gchar *)N_("/Windows/sep3"), NULL, NULL, 0, (gchar *)"<Separator>" },
115   { (gchar *)N_("/Windows/_Find Text (upwards)..."), NULL, GTK_SIGNAL_FUNC(windows_find), 0, NULL },
116   { (gchar *)N_("/Windows/Find _Previous"), NULL, GTK_SIGNAL_FUNC(windows_findp), 0, NULL },
117   { (gchar *)N_("/Windows/Save _Text Buffer..."), NULL, GTK_SIGNAL_FUNC(windows_savebuffer),0,NULL},
118   { (gchar *)N_("/Windows/sep3"), NULL, NULL, 0, (gchar *)"<Separator>" },
119   { (gchar *)N_("/Windows/Save Desktop _Geometry"), NULL, GTK_SIGNAL_FUNC(windows_savedesk), 0, NULL },
120   { (gchar *)N_("/_Help"),              NULL,         NULL,0, (gchar *)"<Branch>" },
121   { (gchar *)N_("/Help/_Getting Started"),NULL, GTK_SIGNAL_FUNC(help_starting), 0, NULL },
122   { (gchar *)N_("/Help/_Keys"),NULL, GTK_SIGNAL_FUNC(help_keys), 0, NULL },
123   { (gchar *)N_("/Help/_Debug Info"),NULL, GTK_SIGNAL_FUNC(help_debug), 0, NULL },
124   { (gchar *)N_("/Help/sep4"),            NULL,           NULL, 0, (gchar *)"<Separator>" },
125   { (gchar *)N_("/Help/_About eboard..."),NULL,  GTK_SIGNAL_FUNC(help_about), 0, NULL },
126 
127 };
128 
129 MainWindow *mainw;
130 
gtkgettext(const char * text,gpointer data)131 gchar * gtkgettext(const char *text, gpointer data) {
132   return((gchar *)eboard_gettext(text));
133 }
134 
MainWindow()135 MainWindow::MainWindow() {
136   GtkAccelGroup *mag;
137   GtkWidget *tw[10];
138   GtkWidget *bhb,*whb,*dm;
139 
140   GtkWidget *P,*SN, *tl1, *tl2;
141 
142   Board *tmp;
143   int i;
144   int nitems=sizeof(mainwindow_mainmenu)/sizeof(mainwindow_mainmenu[0]);
145 
146   gamelist=0;
147   stocklist=0;
148   adlist=0;
149   consolecopy=0;
150   scriptlist=0;
151   ims=0;
152 
153   io_tag = -1;
154 
155   asetprefix.set("%%prefix *");
156   arunscript.set("%%do *");
157 
158   for(i=0;i<8;i++)
159     nav_enable[i]=true;
160 
161   widget=gtk_window_new(GTK_WINDOW_TOPLEVEL);
162   gtk_widget_set_events(widget,GDK_KEY_PRESS_MASK);
163   setTitle("eboard");
164   gtk_widget_realize(widget);
165   gtk_window_resize(GTK_WINDOW(widget),800,600);
166   RefWindow=widget->window;
167 
168   tooltips=GTK_TOOLTIPS(gtk_tooltips_new());
169 
170   /* menu bar */
171   mag=gtk_accel_group_new();
172   gif=gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", mag);
173 
174 #ifdef ENABLE_NLS
175   gtk_item_factory_set_translate_func(gif,(GtkTranslateFunc) gtkgettext, 0, 0);
176 #endif
177 
178   gtk_item_factory_create_items (gif, nitems, mainwindow_mainmenu, NULL);
179   gtk_window_add_accel_group(GTK_WINDOW(widget), mag);
180 
181   v=gtk_vbox_new(FALSE,0);
182   gshow(v);
183   gtk_container_add(GTK_CONTAINER(widget),v);
184   menubar = gtk_item_factory_get_widget (gif, "<main>");
185 
186   /* find out themes */
187   searchThemes();
188   global.readRC();
189 
190   /* build ics bookmark submenu under Peer */
191   updateBookmarks();
192 
193   /* promotion menu */
194   promote=new PromotionPicker(widget->window);
195 
196   /* restore main window geometry */
197   if (!global.Desk.wMain.isNull()) {
198     gtk_window_move(GTK_WINDOW(widget),global.Desk.wMain.X,global.Desk.wMain.Y);
199     gtk_window_resize(GTK_WINDOW(widget),global.Desk.wMain.W,global.Desk.wMain.H);
200   }
201 
202   whb=gtk_hbox_new(FALSE,0);
203   gtk_box_pack_start (GTK_BOX (v), whb, FALSE, TRUE, 0);
204 
205   gtk_box_pack_start (GTK_BOX (whb), menubar, TRUE, TRUE, 0);
206   gshow (menubar);
207 
208   gtk_box_pack_end (GTK_BOX (whb), promote->widget, FALSE, FALSE, 0);
209   promote->show();
210 
211   gshow(whb);
212 
213   /* paned widget */
214   P=gtk_vpaned_new();
215   global.mainpaned=P;
216   gtk_box_pack_start(GTK_BOX(v), P, TRUE, TRUE, 0);
217 
218   /* main notebook */
219   notebook=new Notebook();
220   {
221     GtkPositionType rqda[4]={GTK_POS_RIGHT,GTK_POS_LEFT,GTK_POS_TOP,GTK_POS_BOTTOM};
222     notebook->setTabPosition(rqda[global.TabPos%4]);
223   }
224   notebook->show();
225 
226   SN=gtk_notebook_new();
227   gtk_paned_pack1 (GTK_PANED (P), notebook->widget, TRUE, TRUE);
228   gtk_paned_pack2 (GTK_PANED (P), SN, TRUE, TRUE);
229 
230   /* restore pane divider position */
231   if (global.Desk.PanePosition)
232     gtk_paned_set_position(GTK_PANED(P),global.Desk.PanePosition);
233   else
234     gtk_paned_set_position(GTK_PANED(P),7000);
235 
236   global.lowernotebook = SN;
237 
238   /* the console set */
239 
240   icsout=new TextSet();
241 
242   /* console snippet */
243 
244   tl1=gtk_label_new(_("Console"));
245   xconsole=new Text();
246 
247   gtk_notebook_append_page(GTK_NOTEBOOK(SN), xconsole->widget, tl1);
248   gtk_notebook_set_tab_pos(GTK_NOTEBOOK(SN), GTK_POS_RIGHT);
249 
250   xconsole->show();
251   Gtk::show(tl1,SN,P,NULL);
252 
253   icsout->addTarget(xconsole);
254 
255   /* bugpane */
256 
257   global.bugpane = new BugPane();
258   global.bugpane->show();
259   tl2=gtk_label_new(_("Bughouse"));
260   gtk_notebook_append_page(GTK_NOTEBOOK(SN), global.bugpane->widget, tl2);
261   gshow(tl2);
262 
263   gtk_notebook_set_page(GTK_NOTEBOOK(SN),0);
264 
265   /* main board */
266 
267   tmp=new Board();
268   notebook->addPage(tmp->widget,_("Main Board"),-1);
269   tmp->setNotebook(notebook,-1);
270 
271   /* quick bar */
272   quickbar=new QuickBar(widget);
273   gtk_box_pack_start(GTK_BOX(v), quickbar->widget, FALSE,TRUE, 0);
274   quickbar->show();
275   QuickbarVisible=true;
276   if (!global.ShowQuickbar)
277     hideQuickbar();
278 
279   inconsole=new Text();
280   icsout->addTarget(inconsole);
281   inconsole->show();
282   notebook->addPage(inconsole->widget,_("Console"),-2);
283   inconsole->setNotebook(notebook,-2);
284 
285   greet();
286 
287   /* bottom entry box */
288   tw[0]=gtk_frame_new(0);
289   gtk_frame_set_shadow_type(GTK_FRAME(tw[0]),GTK_SHADOW_ETCHED_OUT);
290   tw[1]=gtk_hbox_new(FALSE,0);
291   gtk_container_add(GTK_CONTAINER(tw[0]),tw[1]);
292   gtk_container_set_border_width(GTK_CONTAINER(tw[1]),4);
293   inputbox=gtk_entry_new();
294   gtk_widget_set_events(inputbox,(GdkEventMask)(gtk_widget_get_events(inputbox)|GDK_FOCUS_CHANGE_MASK));
295 
296   gtk_signal_connect(GTK_OBJECT(inputbox),"focus_out_event",
297 		     GTK_SIGNAL_FUNC(mainwindow_input_focus_out),NULL);
298 
299   ims=new InputModeSelector();
300 
301   gtk_box_pack_start(GTK_BOX(tw[1]),ims->widget,FALSE,TRUE,0);
302   gtk_box_pack_start(GTK_BOX(tw[1]),inputbox,TRUE,TRUE,4);
303 
304 
305   gshow(inputbox);
306   ims->show();
307   Gtk::show(tw[0],tw[1],NULL);
308   gtk_box_pack_start(GTK_BOX(v),tw[0],FALSE,FALSE,0);
309 
310   InputHistory=new History(256);
311 
312   /* status bar */
313   status=new Status();
314   status->show();
315 
316   bhb=gtk_hbox_new(FALSE,0);
317   gtk_box_pack_start(GTK_BOX(v),bhb,FALSE,TRUE,0);
318   gshow(bhb);
319 
320   // timeseal icon
321   createSealPix(bhb);
322 
323   gtk_box_pack_start(GTK_BOX(bhb),status->widget,TRUE,TRUE,0);
324 
325   /* game browsing buttons */
326   createNavbar(bhb);
327 
328   gtk_signal_connect (GTK_OBJECT (widget), "delete_event",
329                       GTK_SIGNAL_FUNC (mainwindow_delete), NULL);
330   gtk_signal_connect (GTK_OBJECT (widget), "destroy",
331                       GTK_SIGNAL_FUNC (mainwindow_destroy), NULL);
332   gtk_signal_connect (GTK_OBJECT (inputbox), "key_press_event",
333 		      GTK_SIGNAL_FUNC (input_key_press), (gpointer)this);
334   gtk_signal_connect (GTK_OBJECT (widget), "key_press_event",
335 		      GTK_SIGNAL_FUNC (main_key_press), (gpointer)this);
336 
337   /* FIXME
338   gtk_signal_connect (GTK_OBJECT (inconsole->getTextArea()), "changed",
339 		      GTK_SIGNAL_FUNC (mainwindow_icsout_changed),
340 		      (gpointer)this);
341   */
342 
343   dm=gtk_item_factory_get_widget_by_action(gif,FA_HIGHLIGHT);
344   gmiset(GTK_CHECK_MENU_ITEM(dm),global.HilightLastMove);
345   gtk_signal_connect(GTK_OBJECT(dm),"toggled",GTK_SIGNAL_FUNC(sett_hilite),0);
346 
347   dm=gtk_item_factory_get_widget_by_action(gif,FA_ANIMATE);
348   gmiset(GTK_CHECK_MENU_ITEM(dm),global.AnimateMoves);
349   gtk_signal_connect(GTK_OBJECT(dm),"toggled",GTK_SIGNAL_FUNC(sett_animate),0);
350 
351   dm=gtk_item_factory_get_widget_by_action(gif,FA_PREMOVE);
352   gmiset(GTK_CHECK_MENU_ITEM(dm),global.Premove);
353   gtk_signal_connect(GTK_OBJECT(dm),"toggled",GTK_SIGNAL_FUNC(sett_premove),0);
354 
355   dm=gtk_item_factory_get_widget_by_action(gif,FA_MOVEBEEP);
356   gmiset(GTK_CHECK_MENU_ITEM(dm),global.BeepWhenOppMoves);
357   gtk_signal_connect(GTK_OBJECT(dm),"toggled",GTK_SIGNAL_FUNC(sett_beepopp),0);
358 
359   dm=gtk_item_factory_get_widget_by_action(gif,FA_SOUND);
360   gmiset(GTK_CHECK_MENU_ITEM(dm),global.EnableSounds);
361   gtk_signal_connect(GTK_OBJECT(dm),"toggled",GTK_SIGNAL_FUNC(sett_osound),0);
362 
363   dm=gtk_item_factory_get_widget_by_action(gif,FA_VECTOR);
364   gmiset(GTK_CHECK_MENU_ITEM(dm),global.UseVectorPieces);
365   gtk_signal_connect(GTK_OBJECT(dm),"toggled",GTK_SIGNAL_FUNC(sett_vector),0);
366   vector_checkbox=dm;
367 
368   dm=gtk_item_factory_get_widget_by_action(gif,FA_LEGALITY);
369   gmiset(GTK_CHECK_MENU_ITEM(dm),global.CheckLegality);
370   gtk_signal_connect(GTK_OBJECT(dm),"toggled",GTK_SIGNAL_FUNC(sett_legal),0);
371 
372   dm=gtk_item_factory_get_widget_by_action(gif,FA_COORDS);
373   gmiset(GTK_CHECK_MENU_ITEM(dm),global.ShowCoordinates);
374   gtk_signal_connect(GTK_OBJECT(dm),"toggled",GTK_SIGNAL_FUNC(sett_coord),0);
375 
376   dm=gtk_item_factory_get_widget_by_action(gif,FA_POPUP);
377   gmiset(GTK_CHECK_MENU_ITEM(dm),global.PopupSecondaryGames);
378   gtk_signal_connect(GTK_OBJECT(dm),"toggled",GTK_SIGNAL_FUNC(sett_popup),0);
379 
380   dm=gtk_item_factory_get_widget_by_action(gif,FA_SMART);
381   gmiset(GTK_CHECK_MENU_ITEM(dm),global.SmartDiscard);
382   gtk_signal_connect(GTK_OBJECT(dm),"toggled",GTK_SIGNAL_FUNC(sett_smarttrash),0);
383 
384   setIcon(icon_eboard_xpm,"eboard");
385   HideMode=0;
386 
387   global.input=this;
388   global.output=icsout;
389   global.status=status;
390   global.chandler=(ConnectionHandler *)this;
391   global.promotion=(PieceProvider *)promote;
392   global.ebook=notebook;
393   global.inputhistory=InputHistory;
394   global.bmlistener=(BookmarkListener *)this;
395   global.qbcontainer=(UpdateInterface *)this;
396   global.iowatcher=(IONotificationInterface *)this;
397   global.quickbar=quickbar;
398   global.killbox=tw[1];
399   global.toplevelwidget=widget;
400   mainw=this;
401 
402   notebook->setListener(this);
403   paneChanged(0,-1);
404 
405   gtk_timeout_add(150,forced_focus,(gpointer)inputbox);
406 }
407 
update()408 void MainWindow::update() {
409   bool dState;
410   dState = global.ShowQuickbar ? true : false;
411   if (dState != QuickbarVisible) {
412     if (QuickbarVisible) hideQuickbar(); else showQuickbar();
413   }
414 }
415 
showQuickbar()416 void MainWindow::showQuickbar() {
417   if (!QuickbarVisible) {
418     quickbar->update();
419     quickbar->show();
420     QuickbarVisible = true;
421   }
422 }
423 
hideQuickbar()424 void MainWindow::hideQuickbar() {
425   if (QuickbarVisible) {
426     quickbar->hide();
427     QuickbarVisible = false;
428   }
429 }
430 
setSealPix(int flag)431 void MainWindow::setSealPix(int flag) {
432   gtk_pixmap_set(GTK_PIXMAP(picseal),sealmap[flag?1:0],
433 		 sealmask[flag?1:0]);
434   gtk_widget_queue_resize(picseal);
435 }
436 
createSealPix(GtkWidget * box)437 void MainWindow::createSealPix(GtkWidget *box) {
438   GtkWidget *fr;
439   GtkStyle *style;
440 
441   fr=gtk_frame_new(0);
442   gtk_frame_set_shadow_type(GTK_FRAME(fr),GTK_SHADOW_ETCHED_OUT);
443 
444   style=gtk_widget_get_style(widget);
445   sealmap[0] = gdk_pixmap_create_from_xpm_d (widget->window, &sealmask[0],
446 					     &style->bg[GTK_STATE_NORMAL],
447 					     (gchar **) sealoff_xpm);
448   sealmap[1] = gdk_pixmap_create_from_xpm_d (widget->window, &sealmask[1],
449 					     &style->bg[GTK_STATE_NORMAL],
450 					     (gchar **) sealon_xpm);
451 
452   picseal=gtk_pixmap_new(sealmap[0],sealmask[0]);
453   gtk_container_add(GTK_CONTAINER(fr),picseal);
454 
455   gtk_box_pack_start(GTK_BOX(box),fr,FALSE,FALSE,0);
456   Gtk::show(picseal,fr,NULL);
457 }
458 
createNavbar(GtkWidget * box)459 void MainWindow::createNavbar(GtkWidget *box) {
460   GdkPixmap *d[8];
461   GdkBitmap *mask[8];
462   GtkWidget *p[8],*b[8],*fr,*mb,*lb;
463   GtkStyle *style;
464   int i;
465 
466   style=gtk_widget_get_style(widget);
467   d[0] = gdk_pixmap_create_from_xpm_d (widget->window, &mask[0],
468                                        &style->bg[GTK_STATE_NORMAL],
469                                        (gchar **) backn_xpm);
470   d[1] = gdk_pixmap_create_from_xpm_d (widget->window, &mask[1],
471                                        &style->bg[GTK_STATE_NORMAL],
472                                        (gchar **) back1_xpm);
473   d[2] = gdk_pixmap_create_from_xpm_d (widget->window, &mask[2],
474                                        &style->bg[GTK_STATE_NORMAL],
475                                        (gchar **) forward1_xpm);
476   d[3] = gdk_pixmap_create_from_xpm_d (widget->window, &mask[3],
477                                        &style->bg[GTK_STATE_NORMAL],
478                                        (gchar **) forwardn_xpm);
479   d[4] = gdk_pixmap_create_from_xpm_d (widget->window, &mask[4],
480                                        &style->bg[GTK_STATE_NORMAL],
481                                        (gchar **) movelist_xpm);
482   d[5] = gdk_pixmap_create_from_xpm_d (widget->window, &mask[5],
483                                        &style->bg[GTK_STATE_NORMAL],
484                                        (gchar **) flip_xpm);
485   d[6] = gdk_pixmap_create_from_xpm_d (widget->window, &mask[6],
486                                        &style->bg[GTK_STATE_NORMAL],
487                                        (gchar **) trash_xpm);
488   d[7] = gdk_pixmap_create_from_xpm_d (widget->window, &mask[7],
489                                        &style->bg[GTK_STATE_NORMAL],
490                                        (gchar **) toscratch_xpm);
491   mb=gtk_hbox_new(FALSE,0);
492   fr=gtk_frame_new(0);
493   gtk_frame_set_shadow_type(GTK_FRAME(fr),GTK_SHADOW_ETCHED_OUT);
494   gtk_container_add(GTK_CONTAINER(fr),mb);
495 
496   lb=gtk_label_new(_("Game/Board: "));
497   gtk_box_pack_start(GTK_BOX(mb),lb,FALSE,FALSE,2);
498 
499   for(i=0;i<8;i++) {
500     b[i]=gtk_button_new();
501     p[i]=gtk_pixmap_new(d[i],mask[i]);
502     gtk_container_add(GTK_CONTAINER(b[i]),p[i]);
503     gshow(p[i]);
504     gtk_box_pack_start(GTK_BOX(mb),b[i],FALSE,TRUE,0);
505     gshow(b[i]);
506     navbar[i]=b[i];
507   }
508 
509 
510   gtk_box_pack_end(GTK_BOX(box),fr,FALSE,FALSE,0);
511   Gtk::show(mb,lb,fr,NULL);
512 
513   gtk_tooltips_set_tip(tooltips,b[0],_("goes back to start of game"),0);
514   gtk_tooltips_set_tip(tooltips,b[1],_("goes back 1 halfmove"),0);
515   gtk_tooltips_set_tip(tooltips,b[2],_("goes forward 1 halfmove"),0);
516   gtk_tooltips_set_tip(tooltips,b[3],_("goes forward to end of game"),0);
517   gtk_tooltips_set_tip(tooltips,b[4],_("pops up the move list"),0);
518   gtk_tooltips_set_tip(tooltips,b[5],_("flips board"),0);
519   gtk_tooltips_set_tip(tooltips,b[6],_("discards board"),0);
520   gtk_tooltips_set_tip(tooltips,b[7],_("opens new scratch board with position"),0);
521 
522   gtk_signal_connect(GTK_OBJECT(b[0]),"clicked",
523 		     GTK_SIGNAL_FUNC(navbar_back_all),this);
524   gtk_signal_connect(GTK_OBJECT(b[1]),"clicked",
525 		     GTK_SIGNAL_FUNC(navbar_back_1),this);
526   gtk_signal_connect(GTK_OBJECT(b[2]),"clicked",
527 		     GTK_SIGNAL_FUNC(navbar_forward_1),this);
528   gtk_signal_connect(GTK_OBJECT(b[3]),"clicked",
529 		     GTK_SIGNAL_FUNC(navbar_forward_all),this);
530   gtk_signal_connect(GTK_OBJECT(b[4]),"clicked",
531 		     GTK_SIGNAL_FUNC(navbar_movelist),this);
532   gtk_signal_connect(GTK_OBJECT(b[5]),"clicked",
533 		     GTK_SIGNAL_FUNC(navbar_flip),this);
534   gtk_signal_connect(GTK_OBJECT(b[6]),"clicked",
535 		     GTK_SIGNAL_FUNC(navbar_trash),this);
536   gtk_signal_connect(GTK_OBJECT(b[7]),"clicked",
537 		     GTK_SIGNAL_FUNC(navbar_toscratch),this);
538 }
539 
setTitle(const char * msg)540 void MainWindow::setTitle(const char *msg) {
541   gtk_window_set_title(GTK_WINDOW(widget),msg);
542 }
543 
restoreDesk()544 void MainWindow::restoreDesk() {
545   // main window is restored in the constructor
546 
547   if (! global.Desk.wGames.isNull() ) {
548     openGameList();
549     gamelist->restorePosition(& global.Desk.wGames);
550   }
551 
552   if (! global.Desk.wLocal.isNull() ) {
553     openStockList();
554     stocklist->restorePosition(& global.Desk.wLocal);
555   }
556 
557   if (! global.Desk.wAds.isNull() ) {
558     openAdList();
559     adlist->restorePosition(& global.Desk.wAds);
560   }
561 
562   global.Desk.spawnConsoles(icsout);
563 }
564 
parseThemeFile(char * name)565 void MainWindow::parseThemeFile(char *name) {
566   static const char * comma = ",";
567   char s[256], aux[16];
568   ThemeEntry *te;
569   list<ThemeEntry *>::iterator it;
570   tstring t;
571   string *p;
572   int ndc=0;
573 
574   if (name==0) return;
575 
576   ifstream f(name);
577   if (!f) return;
578 
579   global.debug("MainWindow","parseThemeFile",name);
580 
581   while( memset(s,0,256), f.getline(s,255,'\n') ) {
582     if (s[0]=='#') continue;
583 
584     // sound file
585     if (s[0]=='+') {
586       t.set(&s[1]);
587       p=t.token(comma);
588       if ( p && !global.hasSoundFile(*p) )
589 	global.SoundFiles.push_back( * (new string(*p)) );
590       continue;
591     }
592 
593     t.set(s);
594     p=t.token(comma);
595     if (!p) continue;
596     te=new ThemeEntry();
597     te->Filename=*p;
598     p=t.token(comma);
599     if (p) te->Text=*p;
600 
601     // avoid dupes
602     for(it=Themes.begin();it!=Themes.end();it++) {
603       if ( (*it)->isDupe(te) ) {
604 	delete te;
605 	te=0;
606 	break;
607       }
608       if ( (*it)->isNameDupe(te) ) {
609 	++ndc;
610 	snprintf(aux,16," (%d)",ndc);
611 	te->Text+=aux;
612       }
613     }
614 
615     if (te)
616       Themes.push_back(te);
617   }
618   f.close();
619 }
620 
updateBookmarks()621 void MainWindow::updateBookmarks() {
622   GtkWidget *pmenu, *item;
623   GList *r,*s;
624   list<HostBookmark *>::iterator hi;
625   list<EngineBookmark *>::iterator ei;
626   char z[256];
627   int i;
628   string x;
629 
630   // ics bookmarks
631 
632   pmenu=gtk_item_factory_get_widget_by_action(gif,FA_ICSBOOKMARKS);
633 
634   r=gtk_container_children(GTK_CONTAINER(pmenu));
635   for(s=r;s!=0;s=g_list_next(s))
636     gtk_container_remove( GTK_CONTAINER(pmenu), GTK_WIDGET(s->data) );
637   g_list_free(r);
638 
639   i=1;
640   for(hi=global.HostHistory.begin();hi!=global.HostHistory.end();hi++,i++) {
641     snprintf(z,256,_("%d. Connect to %s:%d (%s)"),i,(*hi)->host,(*hi)->port,(*hi)->protocol);
642     item=gtk_menu_item_new_with_label( z );
643 
644     gtk_signal_connect(GTK_OBJECT(item),"activate",
645 		       GtkSignalFunc(mainwindow_connect_bookmark),
646 		       (gpointer)(*hi));
647 
648     gtk_menu_shell_append(GTK_MENU_SHELL(pmenu),item);
649     gshow(item);
650   }
651 
652   if (global.HostHistory.empty()) {
653     item=gtk_menu_item_new_with_label(_("(no bookmarks)"));
654     gtk_widget_set_sensitive(item,FALSE);
655     gtk_menu_shell_append(GTK_MENU_SHELL(pmenu),item);
656     gshow(item);
657   }
658 
659   // engine bookmarks
660 
661   pmenu=gtk_item_factory_get_widget_by_action(gif,FA_ENGBOOKMARKS);
662 
663   r=gtk_container_children(GTK_CONTAINER(pmenu));
664   for(s=r;s!=0;s=g_list_next(s))
665     gtk_container_remove( GTK_CONTAINER(pmenu), GTK_WIDGET(s->data) );
666   g_list_free(r);
667 
668   if (!global.EnginePresets.empty()) {
669     item=gtk_menu_item_new_with_label(_("Edit Bookmarks..."));
670     gtk_menu_shell_append(GTK_MENU_SHELL(pmenu),item);
671     gshow(item);
672 
673     gtk_signal_connect(GTK_OBJECT(item),"activate",
674 		       GtkSignalFunc(mainwindow_edit_engbm),
675 		       (gpointer) this);
676 
677     item=gtk_separator_menu_item_new();
678     gtk_menu_shell_append(GTK_MENU_SHELL(pmenu),item);
679     gshow(item);
680   }
681 
682   i=1;
683   for(ei=global.EnginePresets.begin();ei!=global.EnginePresets.end();ei++, i++) {
684     snprintf(z,256,"%d. ",i);
685     x=z;
686     x+=(*ei)->caption;
687     item=gtk_menu_item_new_with_label( x.c_str() );
688 
689     gtk_signal_connect(GTK_OBJECT(item),"activate",
690 		       GtkSignalFunc(mainwindow_connect_bookmark2),
691 		       (gpointer)(*ei));
692 
693     gtk_menu_shell_append(GTK_MENU_SHELL(pmenu),item);
694     gshow(item);
695   }
696 
697   if (global.EnginePresets.empty()) {
698     item=gtk_menu_item_new_with_label(_("(no bookmarks)"));
699     gtk_widget_set_sensitive(item,FALSE);
700     gtk_menu_shell_append(GTK_MENU_SHELL(pmenu),item);
701     gshow(item);
702   }
703 }
704 
searchThemes()705 void MainWindow::searchThemes() {
706   EboardFileFinder eff;
707   list<ThemeEntry *>::iterator it;
708   GtkWidget *tmenu[3];
709   GtkWidget *menuitem;
710   int i,j;
711   char tmp[512];
712   DIR *dh;
713   struct dirent *ds;
714   ExtPatternMatcher ExtraConf;
715   string s;
716 
717   tmenu[0]=gtk_item_factory_get_widget_by_action(gif,FA_LOADTHEME);
718   tmenu[1]=gtk_item_factory_get_widget_by_action(gif,FA_LOADPIECES);
719   tmenu[2]=gtk_item_factory_get_widget_by_action(gif,FA_LOADSQUARES);
720 
721   j=eff.getPathCount();
722 
723   for(i=0;i<j;i++) {
724     g_strlcpy(tmp,eff.getPath(i).c_str(),512);
725     g_strlcat(tmp,"/",512);
726     g_strlcat(tmp,"eboard_themes.conf",512);
727     parseThemeFile(tmp);
728   }
729 
730   // now load all DATADIR/eboard/themeconf.*
731   dh=opendir(DATADIR "/eboard");
732   if (dh) {
733     ExtraConf.set("themeconf.*");
734 
735     while( (ds=readdir(dh)) != 0 ) {
736       if (ExtraConf.match(ds->d_name)) {
737 	snprintf(tmp,512,DATADIR "/eboard/%s",ds->d_name);
738 	parseThemeFile(tmp);
739       }
740     }
741     closedir(dh);
742   }
743 
744   if (!Themes.empty()) {
745     for(i=0,it=Themes.begin();it!=Themes.end();it++,i++) {
746 
747       // load all
748 
749       menuitem=gtk_menu_item_new_with_label( (*it)->Text.c_str() );
750       gtk_signal_connect(GTK_OBJECT(menuitem),"activate",
751 			 GtkSignalFunc(mainwindow_themeitem),
752 			 (gpointer)(*it));
753       gtk_menu_shell_append(GTK_MENU_SHELL(tmenu[0]),menuitem);
754       gshow(menuitem);
755 
756       // load pieces
757 
758       menuitem=gtk_menu_item_new_with_label( (*it)->Text.c_str() );
759       gtk_signal_connect(GTK_OBJECT(menuitem),"activate",
760 			 GtkSignalFunc(mainwindow_themeitem2),
761 			 (gpointer)(*it));
762       gtk_menu_shell_append(GTK_MENU_SHELL(tmenu[1]),menuitem);
763       gshow(menuitem);
764 
765       // load squares
766 
767       menuitem=gtk_menu_item_new_with_label( (*it)->Text.c_str() );
768       gtk_signal_connect(GTK_OBJECT(menuitem),"activate",
769 			 GtkSignalFunc(mainwindow_themeitem3),
770 			 (gpointer)(*it));
771       gtk_menu_shell_append(GTK_MENU_SHELL(tmenu[2]),menuitem);
772       gshow(menuitem);
773 
774     }
775     global.setPieceSet(Themes.front()->Filename,true,true);
776   } else {
777     s="classic.png";
778     global.setPieceSet(s,true,true);
779   }
780 }
781 
greet()782 void MainWindow::greet() {
783   char z[128];
784   snprintf (z,128,_("eboard version %s (%s)"),global.Version,global.SystemType);
785   icsout->append(z,0xc0ff00,IM_IGNORE);
786   snprintf (z,128,_("(c) 2000-%d Felipe Bergo <fbergo@gmail.com> (FICS handle: Pulga)"), 2016);
787   icsout->append(z,0xc0ff00,IM_IGNORE);
788   icsout->append(_("Distributed under the terms of the GNU General Public License, version 2 or later"),0xffc000,IM_IGNORE);
789   icsout->append("http://www.gnu.org/copyleft/gpl.html",0xffc000,IM_IGNORE);
790   icsout->append(_("Source code available at https://github.com/fbergo/eboard"),0xc0ff00,IM_IGNORE);
791   icsout->append("---",0xc0ff00,IM_IGNORE);
792 
793 }
794 
updatePrefix()795 void MainWindow::updatePrefix() {
796   int id;
797   id=notebook->getCurrentPageId();
798   if (id==-2) {
799     imscache.set(-2,global.ConsoleReply);
800     ims->setPrefix( * (imscache.get(-2)) );
801   }
802 }
803 
setPasswordMode(int pm)804 void MainWindow::setPasswordMode(int pm) {
805   HideMode=pm;
806   global.PauseLog=pm;
807   gtk_entry_set_visibility(GTK_ENTRY(inputbox),(pm?FALSE:TRUE));
808   global.setPasswordMode(pm);
809 }
810 
openGameList()811 void MainWindow::openGameList() {
812   if (gamelist)
813     return;
814   gamelist=new GameListDialog(this);
815   gamelist->show();
816 }
817 
openAdList()818 void MainWindow::openAdList() {
819   if (adlist)
820     return;
821   adlist=new AdListDialog(this);
822   adlist->show();
823 }
824 
gameListClosed()825 void MainWindow::gameListClosed() {
826   if (gamelist)
827     delete gamelist;
828   gamelist=0;
829 }
830 
openStockList()831 void MainWindow::openStockList() {
832   if (stocklist)
833     return;
834   stocklist=new StockListDialog(this);
835   stocklist->show();
836 }
837 
stockListClosed()838 void MainWindow::stockListClosed() {
839   if (stocklist)
840     delete stocklist;
841   stocklist=0;
842 }
843 
adListClosed()844 void MainWindow::adListClosed() {
845   if (adlist)
846     delete adlist;
847   adlist=0;
848 }
849 
openDetachedConsole()850 void MainWindow::openDetachedConsole() {
851   if (consolecopy)
852     return;
853   consolecopy=new DetachedConsole(icsout,this);
854   consolecopy->show();
855 }
856 
peekKeys(GtkWidget * who)857 void MainWindow::peekKeys(GtkWidget *who) {
858   gtk_signal_connect(GTK_OBJECT(who),"key_press_event",
859 		     GTK_SIGNAL_FUNC(main_key_press),(gpointer)this);
860 }
861 
consoleClosed()862 void MainWindow::consoleClosed() {
863   if (consolecopy)
864     delete consolecopy;
865   consolecopy=0;
866 }
867 
userInput(const char * text)868 void MainWindow::userInput(const char *text) {
869   char *nv;
870   int i,j;
871   if (text==0) return;
872 
873   j=strlen(text);
874 
875   nv=(char *) Global::safeMalloc(j+1);
876   strcpy(nv,text);
877 
878   // join multi-line pastes in one single line
879   for(i=0;i<j;i++)
880     if ((nv[i]=='\n')||(nv[i]=='\r'))
881       nv[i]=' ';
882 
883   if (HideMode)
884     icsout->append(_("> (password sent)"),global.SelfInputColor);
885   else
886     icsout->append("> ",nv,global.SelfInputColor);
887 
888   if (global.protocol)
889     global.protocol->sendUserInput(nv);
890 
891   if (!HideMode)
892     InputHistory->appendString(nv);
893 }
894 
injectInput()895 void MainWindow::injectInput() {
896   char z[4096],y[256];
897   int id;
898 
899   g_strlcpy(z,gtk_entry_get_text(GTK_ENTRY(inputbox)),4096);
900 
901   if (ims->getSearchMode()) {
902     inconsole->SearchString = z;
903     inconsole->execSearch();
904     ims->setSearchMode(false);
905     goto ii_nothing_else;
906   }
907 
908   if (asetprefix.match(z)) {
909     id=notebook->getCurrentPageId();
910     imscache.set(id, asetprefix.getStarToken(0) );
911     ims->setPrefix( * (imscache.get(id)) );
912     goto ii_nothing_else;
913   }
914 
915   if (arunscript.match(z)) {
916     g_strlcpy(y,arunscript.getStarToken(0),256);
917     new ScriptInstance(y);
918     goto ii_nothing_else;
919     return;
920   }
921 
922   if (ims->getChatMode()) {
923     g_strlcpy(z,ims->getPrefix().c_str(),4096);
924     if (z[0])
925       g_strlcat(z," ",4096);
926   } else
927     z[0]=0;
928   g_strlcat(z,gtk_entry_get_text(GTK_ENTRY(inputbox)),4096);
929 
930   userInput(z);
931 
932  ii_nothing_else:
933   gtk_entry_set_text(GTK_ENTRY(inputbox),"\0");
934 }
935 
historyUp()936 void MainWindow::historyUp() {
937   gtk_entry_set_text(GTK_ENTRY(inputbox),InputHistory->moveUp());
938   gtk_editable_set_position(GTK_EDITABLE(inputbox),-1);
939 }
940 
historyDown()941 void MainWindow::historyDown() {
942   gtk_entry_set_text(GTK_ENTRY(inputbox),InputHistory->moveDown());
943   gtk_editable_set_position(GTK_EDITABLE(inputbox),-1);
944 }
945 
saveBuffer()946 void MainWindow::saveBuffer() {
947   inconsole->saveBuffer();
948 }
949 
saveDesk()950 void MainWindow::saveDesk() {
951   global.Desk.clear();
952 
953   global.Desk.wMain.retrieve(widget);
954   if (gamelist)   global.Desk.wGames.retrieve(gamelist->widget);
955   if (adlist)     global.Desk.wAds.retrieve(adlist->widget);
956   if (stocklist)  global.Desk.wLocal.retrieve(stocklist->widget);
957   if (scriptlist) global.Desk.wLocal.retrieve(scriptlist->widget);
958 
959   global.Desk.PanePosition = gtk_paned_get_position(GTK_PANED(global.mainpaned));
960   global.gatherConsoleState();
961   global.writeRC();
962 }
963 
openServer(const char * host,int port,Protocol * protocol,const char * helper)964 void MainWindow::openServer(const char *host,int port,Protocol *protocol,
965 			    const char *helper) {
966   global.debug("MainWindow","openServer",host);
967   inconsole->pop();
968   tryConnect(host,port,protocol,helper);
969 }
970 
openServer(NetConnection * conn,Protocol * protocol)971 void MainWindow::openServer(NetConnection *conn, Protocol *protocol) {
972   if (!conn->isConnected())
973     return;
974 
975   inconsole->pop();
976 
977   if ((global.protocol)||(global.network))
978     disconnect();
979 
980   global.protocol=protocol;
981   global.network=conn;
982   global.network->notifyReadReady(this);
983 
984   setSealPix(conn->hasTimeGuard());
985   //  incrementHook();
986 }
987 
openXBoardEngine()988 void MainWindow::openXBoardEngine() {
989   XBoardProtocol *xpp;
990   global.debug("MainWindow","openXBoardEngine");
991   xpp=new XBoardProtocol();
992   openEngine(xpp);
993 }
994 
openGnuChess4()995 void MainWindow::openGnuChess4() {
996   GnuChess4Protocol *gpp;
997   global.debug("MainWindow","openGnuChess4");
998   gpp=new GnuChess4Protocol();
999   openEngine(gpp);
1000 }
1001 
openCrafty()1002 void MainWindow::openCrafty() {
1003   CraftyProtocol *cpp;
1004   global.debug("MainWindow","openCrafty");
1005   cpp=new CraftyProtocol();
1006   openEngine(cpp);
1007 }
1008 
openSjeng()1009 void MainWindow::openSjeng() {
1010   SjengProtocol *spp;
1011   global.debug("MainWindow","openSjeng");
1012   spp=new SjengProtocol();
1013   openEngine(spp);
1014 }
1015 
openEngineBookmark(EngineBookmark * bm)1016 void MainWindow::openEngineBookmark(EngineBookmark *bm) {
1017   EngineProtocol *xpp;
1018 
1019   switch(bm->proto) {
1020   case 0: xpp=new XBoardProtocol(); break;
1021   case 1: xpp=new CraftyProtocol(); break;
1022   case 2: xpp=new SjengProtocol(); break;
1023   case 3: xpp=new GnuChess4Protocol(); break;
1024   default:
1025     cerr << _("** [eboard] bad engine protocol # in bookmark: ") << bm->proto << endl;
1026     return;
1027   }
1028 
1029   disconnect();
1030   if (xpp->run(bm)) {
1031     // success
1032     global.protocol=xpp;
1033     global.network->notifyReadReady(this);
1034     // incrementHook();
1035   }
1036 }
1037 
openEngine(EngineProtocol * xpp,EngineBookmark * ebm)1038 void MainWindow::openEngine(EngineProtocol *xpp, EngineBookmark *ebm) {
1039   int i;
1040   global.debug("MainWindow","openEngine");
1041   disconnect();
1042 
1043   if (ebm)
1044     i=xpp->run(ebm);
1045   else
1046     i=xpp->run();
1047 
1048   if (i) {
1049     // success
1050     global.protocol=xpp;
1051     global.network->notifyReadReady(this);
1052     // incrementHook();
1053   }
1054 }
1055 
tryConnect(const char * host,int port,Protocol * protocol,const char * helper)1056 void MainWindow::tryConnect(const char *host,int port,Protocol *protocol,
1057 			    const char *helper)
1058 {
1059   DirectConnection *bytcp;
1060   PipeConnection *bypipe;
1061   FallBackConnection *glue;
1062   NetConnection *net;
1063 
1064   global.debug("MainWindow","tryConnect",host);
1065 
1066   if ((global.protocol)||(global.network))
1067     disconnect();
1068 
1069   if (helper) {
1070     glue=new FallBackConnection();
1071     bypipe=new PipeConnection(host,port,helper,global.SystemType);
1072     bypipe->TimeGuard=1;
1073     bytcp=new DirectConnection(host,port);
1074     glue->append(bypipe);
1075     glue->append(bytcp);
1076     net=glue;
1077   } else {
1078     net=new DirectConnection(host,port);
1079   }
1080 
1081   global.protocol=protocol;
1082   global.network=net;
1083 
1084   if (net->open()) {
1085     // failure
1086     global.protocol=NULL;
1087     global.network=NULL;
1088     status->setText(net->getError(),10);
1089     delete net;
1090     delete protocol;
1091   } else {
1092     // success
1093     setSealPix(net->hasTimeGuard());
1094     net->notifyReadReady(this);
1095     // incrementHook();
1096   }
1097 }
1098 
disconnect()1099 void MainWindow::disconnect() {
1100   global.debug("MainWindow","disconnect");
1101   cleanUpConnection();
1102 }
1103 
cleanUpConnection()1104 void MainWindow::cleanUpConnection() {
1105   list<Board *>::iterator bli;
1106   global.debug("MainWindow","cleanUpConnection");
1107   setSealPix(0);
1108 
1109   if (global.protocol!=NULL) {
1110     global.protocol->finalize();
1111     delete global.protocol;
1112     global.protocol=NULL;
1113   }
1114   if (global.network!=NULL) {
1115     global.network->close();
1116     delete global.network;
1117     global.network=NULL;
1118     icsout->append(_("--- Disconnected"),0xc0ff00);
1119   }
1120 
1121   // stop all clocks
1122   for(bli=global.BoardList.begin();bli!=global.BoardList.end();bli++)
1123     (*bli)->stopClock();
1124 
1125   status->setText(_("No peer."),15);
1126 }
1127 
cloneOnScratch(ChessGame * cg0)1128 void MainWindow::cloneOnScratch(ChessGame *cg0) {
1129   Board *b;
1130   ChessGame *cg;
1131   char z[64];
1132   int id;
1133 
1134   id = global.nextFreeGameId(30000);
1135   cg=new ChessGame(cg0);
1136   cg->GameNumber = id;
1137   cg->LocalEdit = true;
1138   cg->source = GS_Other;
1139 
1140   global.appendGame(cg,false);
1141   b=new EditBoard(cg);
1142   cg->setBoard(b);
1143   cg->StopClock = 1;
1144 
1145   snprintf(z,64,_("Scratch %d"),++global.LastScratch);
1146   notebook->addPage(b->widget,z,id);
1147   b->setNotebook(notebook,id);
1148   notebook->goToPageId(id);
1149   b->update();
1150 }
1151 
newScratchBoard(bool clearboard)1152 void MainWindow::newScratchBoard(bool clearboard) {
1153   Board *b;
1154   ChessGame *cg;
1155   Position *p;
1156   int id,i,j;
1157   char z[64];
1158 
1159   id = global.nextFreeGameId(30000);
1160 
1161   cg=new ChessGame(id, 0, 0, 0, REGULAR,
1162 		   "Nobody","Nessuno");
1163   cg->LocalEdit=true;
1164 
1165   global.appendGame(cg,false);
1166   b=new EditBoard(cg);
1167   cg->setBoard(b);
1168   cg->StopClock = 1;
1169 
1170   snprintf(z,64,_("Scratch %d"),++global.LastScratch);
1171   notebook->addPage(b->widget,z,id);
1172   b->setNotebook(notebook,id);
1173 
1174   p=new Position();
1175   if (clearboard)
1176     for(i=0;i<8;i++)
1177       for(j=0;j<8;j++)
1178 	p->setPiece(i,j,EMPTY);
1179 
1180   cg->updatePosition2(*p,1,0,0,0,_("<editing>"),false);
1181   notebook->goToPageId(id);
1182 }
1183 
gameWalk(int op)1184 void MainWindow::gameWalk(int op) {
1185   Board *b=0;
1186   ChessGame *cg=0;
1187   int id;
1188 
1189   global.debug("MainWindow","gameWalk");
1190 
1191   id=notebook->getCurrentPageId();
1192 
1193   if (id<=-2) // text panes
1194     return;
1195 
1196   if (id==-1)
1197     b=global.BoardList.front();
1198   else {
1199     cg=global.getGame(id);
1200     if (cg)
1201       b=cg->getBoard();
1202   }
1203 
1204   if (!b)
1205     return;
1206 
1207   // examining
1208   if (cg)
1209     if (cg->protodata[0]==258) {
1210       switch(op) {
1211       case 0: global.protocol->exaBackward(999); return;
1212       case 1: global.protocol->exaBackward(1); return;
1213       case 2: global.protocol->exaForward(1); return;
1214       case 3: global.protocol->exaForward(999); return;
1215       }
1216     }
1217 
1218   switch(op) {
1219   case 0: b->walkBackAll(); break;
1220   case 1: b->walkBack1(); break;
1221   case 2: b->walkForward1(); break;
1222   case 3: b->walkForwardAll(); break;
1223   case 4: b->openMovelist(); break;
1224   case 5:
1225     if ((id<=0)||(!cg)) break;
1226     if ( (cg->protodata[1]) || ( ! global.protocol ) || (cg->LocalEdit) ) {
1227       cg->protodata[1]=0;
1228       global.ebook->removePage(cg->GameNumber);
1229       global.removeBoard(b);
1230       delete(b);
1231       cg->setBoard(NULL);
1232       if (cg->LocalEdit)
1233 	global.deleteGame(cg);
1234     } else {
1235       if ((id>0)&&(global.protocol!=NULL))
1236 	global.protocol->discardGame(cg->GameNumber);
1237     }
1238     break;
1239   case 6:
1240     b->setFlipInversion(!b->getFlipInversion());
1241     break;
1242   case 7: // clone on scratch
1243     cloneOnScratch(b->getGame());
1244     break;
1245   }
1246 }
1247 
1248 static int smart_remove_pending=0;
1249 
1250 // take care of pending 'smart removals'
do_smart_remove(gpointer data)1251 gboolean do_smart_remove(gpointer data) {
1252   vector<int> evil_ids;
1253   int i,j,pgid;
1254 
1255   smart_remove_pending=0;
1256   pgid=global.ebook->getCurrentPageId();
1257 
1258   global.ebook->getNaughty(evil_ids);
1259   j=evil_ids.size();
1260   if ( (!j) || (! global.protocol) ) return FALSE;
1261   for(i=0;i<j;i++) {
1262     if (evil_ids[i]==pgid) continue; /* almost impossible, would require a heck
1263 					of race condition */
1264     if (evil_ids[i]>=0)
1265       global.protocol->discardGame(evil_ids[i]);
1266   }
1267 
1268   return FALSE;
1269 }
1270 
1271 // changes enabling of buttons upon pane change
1272 // also schedules 'smart removes' for finished boards
paneChanged(int pgseq,int pgid)1273 void MainWindow::paneChanged(int pgseq,int pgid) {
1274   bool nv[8];
1275   int i;
1276 
1277   // #     button(s)  constraint for enabling
1278   // ------------------------------------------------------
1279   // 0..3  game move   requires game
1280   // 4     move list   requires game
1281   // 5     flip        requires board
1282   // 6     trash       requires board other than main board
1283   // 7     new scratch requires game
1284 
1285   // main board: -1  console: -2  seek graph: -3
1286   // channel tabs: -200 .. -455 (for FICS, formula is -(200+channelnum) )
1287   // other boards: >= 0
1288   // most probably computer thinking pane will be -4
1289 
1290   // change talking prefix as appropriate:
1291 
1292   if ( (pgid != -2) && imscache.get(pgid)) {
1293     ims->setPrefix(* (imscache.get(pgid)));
1294   } else if (pgid <= -200) {
1295     int ch;
1296     char z[32];
1297     ch=-200-pgid;
1298     snprintf(z,32,"t %d",ch);
1299     ims->setPrefix(z);
1300     imscache.set(pgid, ims->getPrefix());
1301   } else if (pgid >= 0) {
1302     ims->setPrefix(",");
1303     imscache.set(pgid, ims->getPrefix());
1304   } else if (pgid == -2) {
1305     ims->setPrefix(global.ConsoleReply);
1306     imscache.set(pgid, ims->getPrefix());
1307   } else if (pgid == -1) {
1308     ims->setPrefix("say");
1309     imscache.set(pgid, ims->getPrefix());
1310   }
1311 
1312   for(i=0;i<8;i++) nv[i]=true;
1313 
1314   // 0..4
1315   if (pgid < -1) nv[0]=false;
1316   if ( (pgid == -1) && (! global.BoardList.front()->hasGame()) ) nv[0]=false;
1317 
1318   nv[1]=nv[2]=nv[3]=nv[4]=nv[7]=nv[0];
1319 
1320   // 5
1321   if (pgid < -1) nv[5]=false;
1322 
1323   // 6
1324   if (pgid < 0) nv[6]=false;
1325 
1326   for(i=0;i<8;i++) {
1327     if (nv[i]!=nav_enable[i]) {
1328       gtk_widget_set_sensitive(navbar[i],nv[i]?TRUE:FALSE);
1329       nav_enable[i]=nv[i];
1330     }
1331   }
1332 
1333   if ((global.ebook->hasNaughty())&&(!smart_remove_pending)) {
1334     smart_remove_pending=1;
1335     gtk_timeout_add(500,do_smart_remove,NULL);
1336   }
1337 }
1338 
1339 // some key was pressed in some other window, but it's (possibly) a
1340 // global keybind
1341 int
keyPressed(int keyval,int state)1342 MainWindow::keyPressed(int keyval, int state) {
1343   GdkEventKey e;
1344   e.keyval = keyval;
1345   e.state  = state;
1346   return(main_key_press(0, &e, this));
1347 }
1348 
1349 /* callbacks */
1350 
1351 gint
mainwindow_delete(GtkWidget * widget,GdkEvent * event,gpointer data)1352 mainwindow_delete (GtkWidget * widget, GdkEvent * event, gpointer data) {
1353   global.Quitting=1;
1354   return FALSE;
1355 }
1356 
1357 void
mainwindow_destroy(GtkWidget * widget,gpointer data)1358 mainwindow_destroy (GtkWidget * widget, gpointer data) {
1359   global.Quitting=1;
1360   global.WrappedMainQuit();
1361 }
1362 
1363 int
main_key_press(GtkWidget * wid,GdkEventKey * evt,gpointer data)1364 main_key_press (GtkWidget * wid, GdkEventKey * evt, gpointer data) {
1365   MainWindow *ptr;
1366   int cpage;
1367   ptr=(MainWindow *)data;
1368 
1369   if (evt->state&GDK_CONTROL_MASK) {
1370     switch(evt->keyval) {
1371     case GDK_Left:
1372       ptr->gameWalk(1);
1373       break;
1374     case GDK_Right:
1375       ptr->gameWalk(2);
1376       break;
1377     case GDK_F:
1378     case GDK_f:
1379       windows_find(0,0);
1380       break;
1381     case GDK_G:
1382     case GDK_g:
1383       windows_findp(0,0);
1384       break;
1385     case GDK_T:
1386     case GDK_t:
1387       global.ShowTimestamp = (global.ShowTimestamp ? 0 : 1);
1388       global.output->updateFont();
1389       global.updateFont();
1390       global.writeRC();
1391       break;
1392     default:
1393       return 0;
1394     }
1395     return 1;
1396   }
1397 
1398   switch(evt->keyval) {
1399   case GDK_Escape:
1400     if (ptr->ims)
1401       ptr->ims->flip();
1402     break;
1403   case GDK_F3: // previous pane
1404     global.ebook->goToPrevious();
1405     break;
1406   case GDK_F4: // next pane
1407     global.ebook->goToNext();
1408     break;
1409   case GDK_F5: // pop main board
1410     global.ebook->goToPageId(-1);
1411     break;
1412   case GDK_F6: // pop console
1413     global.ebook->goToPageId(-2);
1414     break;
1415   case GDK_F7: // pop seek graph
1416     global.ebook->goToPageId(-3);
1417     break;
1418   case GDK_F8: // toggle shortcut bar
1419     global.ShowQuickbar = ! (global.ShowQuickbar);
1420     global.qbcontainer->update();
1421     global.writeRC();
1422     break;
1423   case GDK_Page_Up:
1424     if (wid != 0) {
1425       cpage = global.ebook->getCurrentPageId();
1426       if (cpage==-2)
1427 	ptr->inconsole->pageUp();
1428       if (cpage >= -500 && cpage <= -200)
1429 	global.channelPageUp(-200-cpage);
1430       ptr->xconsole->pageUp();
1431     }
1432     break;
1433   case GDK_Page_Down:
1434     if (wid != 0) {
1435       cpage = global.ebook->getCurrentPageId();
1436       if (cpage==-2)
1437 	ptr->inconsole->pageDown();
1438       if (cpage >= -500 && cpage <= -200)
1439 	global.channelPageDown(-200-cpage);
1440       ptr->xconsole->pageDown();
1441     }
1442     break;
1443   default:
1444     return 0;
1445   }
1446   return 1;
1447 }
1448 
1449 int
input_key_press(GtkWidget * wid,GdkEventKey * evt,gpointer data)1450 input_key_press (GtkWidget * wid, GdkEventKey * evt, gpointer data) {
1451   MainWindow *ptr;
1452   ptr=(MainWindow *)data;
1453 
1454   switch(evt->keyval) {
1455   case GDK_Up:
1456     gtk_signal_emit_stop_by_name(GTK_OBJECT(wid), "key_press_event");
1457     ptr->historyUp();
1458     return 1;
1459   case GDK_Down:
1460     gtk_signal_emit_stop_by_name(GTK_OBJECT(wid), "key_press_event");
1461     ptr->historyDown();
1462     return 1;
1463   case GDK_KP_Enter:
1464     gtk_signal_emit_stop_by_name(GTK_OBJECT(wid), "key_press_event");
1465   case GDK_Return:
1466     ptr->injectInput();
1467     return 1;
1468   }
1469   return 0;
1470 }
1471 
1472 void
mainwindow_themeitem(GtkMenuItem * menuitem,gpointer data)1473 mainwindow_themeitem (GtkMenuItem *menuitem, gpointer data) {
1474   ThemeEntry *te;
1475   te=(ThemeEntry *)data;
1476   gmiset(GTK_CHECK_MENU_ITEM(mainw->vector_checkbox),0);
1477   global.UseVectorPieces=0;
1478   global.setPieceSet(te->Filename,true,true);
1479   global.writeRC();
1480 }
1481 
1482 void
mainwindow_themeitem2(GtkMenuItem * menuitem,gpointer data)1483 mainwindow_themeitem2 (GtkMenuItem *menuitem, gpointer data) {
1484   ThemeEntry *te;
1485   te=(ThemeEntry *)data;
1486   gmiset(GTK_CHECK_MENU_ITEM(mainw->vector_checkbox),0);
1487   global.UseVectorPieces=0;
1488   global.setPieceSet(te->Filename,true,false);
1489   global.writeRC();
1490 }
1491 
1492 void
mainwindow_themeitem3(GtkMenuItem * menuitem,gpointer data)1493 mainwindow_themeitem3 (GtkMenuItem *menuitem, gpointer data) {
1494   ThemeEntry *te;
1495   te=(ThemeEntry *)data;
1496   gmiset(GTK_CHECK_MENU_ITEM(mainw->vector_checkbox),0);
1497   global.UseVectorPieces=0;
1498   global.setPieceSet(te->Filename,false,true);
1499   global.writeRC();
1500 }
1501 
1502 void
peer_disconnect(gpointer data)1503 peer_disconnect(gpointer data) {
1504   mainw->disconnect();
1505 }
1506 
1507 void
peer_scratch_empty(gpointer data)1508 peer_scratch_empty(gpointer data) {
1509   mainw->newScratchBoard(true);
1510 }
1511 
1512 void
peer_scratch_initial(gpointer data)1513 peer_scratch_initial(gpointer data) {
1514   mainw->newScratchBoard(false);
1515 }
1516 
1517 void
peer_connect_fics(gpointer data)1518 peer_connect_fics(gpointer data) {
1519   mainw->openServer("freechess.org",5000,new FicsProtocol(),"timeseal");
1520   if (global.FicsAutoLogin)
1521     if (global.network)
1522       if (global.network->isConnected())
1523 	new ScriptInstance("autofics.pl");
1524 }
1525 
peer_connect_xboard(gpointer data)1526 void peer_connect_xboard(gpointer data) {
1527   mainw->openXBoardEngine();
1528 }
1529 
peer_connect_gnuchess4(gpointer data)1530 void peer_connect_gnuchess4(gpointer data) {
1531   mainw->openGnuChess4();
1532 }
peer_connect_crafty(gpointer data)1533 void peer_connect_crafty(gpointer data) {
1534   mainw->openCrafty();
1535 }
1536 
peer_connect_sjeng(gpointer data)1537 void peer_connect_sjeng(gpointer data) {
1538   mainw->openSjeng();
1539 }
1540 
1541 void
peer_connect_ask(gpointer data)1542 peer_connect_ask(gpointer data) {
1543   (new ConnectDialog())->show();
1544 }
1545 
1546 void
peer_connect_p2p(gpointer data)1547 peer_connect_p2p(gpointer data) {
1548   (new P2PDialog())->show();
1549 }
1550 
1551 void
windows_games(GtkWidget * w,gpointer data)1552 windows_games(GtkWidget *w, gpointer data)
1553 {
1554   mainw->openGameList();
1555 }
1556 
1557 void
windows_sough(GtkWidget * w,gpointer data)1558 windows_sough(GtkWidget *w, gpointer data)
1559 {
1560   mainw->openAdList();
1561 }
1562 
1563 void
windows_stock(GtkWidget * w,gpointer data)1564 windows_stock(GtkWidget *w, gpointer data)
1565 {
1566   mainw->openStockList();
1567 }
1568 
1569 void
windows_detached(GtkWidget * w,gpointer data)1570 windows_detached(GtkWidget *w, gpointer data)
1571 {
1572   mainw->openDetachedConsole();
1573 }
1574 
1575 void
windows_script(GtkWidget * w,gpointer data)1576 windows_script(GtkWidget *w, gpointer data)
1577 {
1578   (new ScriptList())->show();
1579 }
1580 
1581 void
windows_savedesk(GtkWidget * w,gpointer data)1582 windows_savedesk(GtkWidget *w, gpointer data) {
1583   mainw->saveDesk();
1584 }
1585 
1586 void
windows_savebuffer(GtkWidget * w,gpointer data)1587 windows_savebuffer(GtkWidget *w, gpointer data) {
1588   mainw->saveBuffer();
1589 }
1590 
1591 void
windows_find(GtkWidget * w,gpointer data)1592 windows_find(GtkWidget *w, gpointer data) {
1593   mainw->ims->setSearchMode(true);
1594 }
1595 
1596 void
windows_findp(GtkWidget * w,gpointer data)1597 windows_findp(GtkWidget *w, gpointer data) {
1598   mainw->inconsole->findTextNext();
1599 }
1600 
1601 void
help_about(gpointer data)1602 help_about(gpointer data) {
1603   (new Help::AboutDialog())->show();
1604 }
1605 
1606 void
help_keys(gpointer data)1607 help_keys(gpointer data) {
1608   (new Help::KeysDialog())->show();
1609 }
1610 
1611 void
help_debug(gpointer data)1612 help_debug(gpointer data) {
1613   (new Help::DebugDialog())->show();
1614 }
1615 
1616 void
help_starting(gpointer data)1617 help_starting(gpointer data) {
1618   (new Help::GettingStarted())->show();
1619 }
1620 
readAvailable(int handle)1621 void MainWindow::readAvailable(int handle) {
1622   NetConnection *net;
1623   char line[2048];
1624   int gotinput, loopc;
1625 
1626   global.debug("MainWindow","readAvailable");
1627   net = global.network;
1628 
1629   if ((net==NULL)||(!net->isConnected())||(global.protocol==NULL)) {
1630     cleanUpConnection();
1631     return;
1632   }
1633 
1634   if (handle == net->getReadHandle()) { /* got input from main connection */
1635 
1636     loopc = 0;
1637     do {
1638       gotinput=0;
1639       if (net->readLine(line,2048)==0) {
1640 	gotinput=1;
1641 	global.protocol->receiveString(line);
1642 	global.agentBroadcast(line);
1643       } else {
1644 	if (global.protocol->hasAuthenticationPrompts())
1645 	  if ((net->bufferMatch("login:"))||
1646 	      (net->bufferMatch("password:")))
1647 	    if (net->readPartial(line,2048)==0) {
1648 	      global.protocol->receiveString(line);
1649 	      global.agentBroadcast(line);
1650 	      gotinput=1;
1651 	    }
1652       }
1653       ++loopc;
1654       if (loopc%10 == 9)
1655 	gtk_main_iteration();
1656 
1657       if ( (global.network==0) || (global.protocol==0) )
1658 	break;
1659 
1660     } while(gotinput);
1661 
1662   } else { /* got input from an agent (script) */
1663 
1664     if (io_tag < 0)
1665       io_tag = gtk_timeout_add(200, mainwindow_read_agents, (gpointer) this);
1666   }
1667 
1668 }
1669 
mainwindow_read_agents(gpointer data)1670 gboolean mainwindow_read_agents(gpointer data) {
1671   MainWindow *me = (MainWindow *) data;
1672   int loopc;
1673   char line[2048];
1674 
1675   if (global.protocol==NULL)
1676     return FALSE;
1677 
1678   loopc = 0;
1679   while(global.receiveAgentLine(line,2048)) {
1680     global.protocol->sendUserInput(line);
1681     ++loopc;
1682     if (loopc > 4)
1683       return TRUE;
1684   }
1685   me->io_tag = -1;
1686   return FALSE;
1687 }
1688 
writeAvailable(int handle)1689 void MainWindow::writeAvailable(int handle) {
1690   // not used, write is buffered, the OS takes care for us, thanks.
1691 }
1692 
1693 void
mainwindow_icsout_changed(GtkEditable * gtke,gpointer data)1694 mainwindow_icsout_changed(GtkEditable *gtke, gpointer data) {
1695   MainWindow *me;
1696 
1697   me=(MainWindow *)data;
1698   me->inconsole->contentUpdated();
1699 }
1700 
1701 void
navbar_back_all(GtkWidget * w,gpointer data)1702 navbar_back_all(GtkWidget *w,gpointer data) {
1703   MainWindow *me;
1704   me=(MainWindow *)data;
1705   me->gameWalk(0);
1706 }
1707 
1708 void
navbar_back_1(GtkWidget * w,gpointer data)1709 navbar_back_1(GtkWidget *w,gpointer data) {
1710   MainWindow *me;
1711   me=(MainWindow *)data;
1712   me->gameWalk(1);
1713 }
1714 
1715 void
navbar_forward_1(GtkWidget * w,gpointer data)1716 navbar_forward_1(GtkWidget *w,gpointer data) {
1717   MainWindow *me;
1718   me=(MainWindow *)data;
1719   me->gameWalk(2);
1720 }
1721 
1722 void
navbar_forward_all(GtkWidget * w,gpointer data)1723 navbar_forward_all(GtkWidget *w,gpointer data) {
1724   MainWindow *me;
1725   me=(MainWindow *)data;
1726   me->gameWalk(3);
1727 }
1728 
1729 void
navbar_movelist(GtkWidget * w,gpointer data)1730 navbar_movelist(GtkWidget *w,gpointer data) {
1731   MainWindow *me;
1732   me=(MainWindow *)data;
1733   me->gameWalk(4);
1734 }
1735 
1736 void
navbar_trash(GtkWidget * w,gpointer data)1737 navbar_trash(GtkWidget *w,gpointer data) {
1738   MainWindow *me;
1739   me=(MainWindow *)data;
1740   me->gameWalk(5);
1741 }
1742 
1743 void
navbar_toscratch(GtkWidget * w,gpointer data)1744 navbar_toscratch(GtkWidget *w,gpointer data) {
1745   MainWindow *me;
1746   me=(MainWindow *)data;
1747   me->gameWalk(7);
1748 }
1749 
1750 void
navbar_flip(GtkWidget * w,gpointer data)1751 navbar_flip(GtkWidget *w,gpointer data) {
1752   MainWindow *me;
1753   me=(MainWindow *)data;
1754   me->gameWalk(6);
1755 }
1756 
1757 void
sett_prefs(gpointer data)1758 sett_prefs(gpointer data) {
1759   (new PreferencesDialog())->show();
1760 }
1761 
1762 void
sett_hilite(GtkWidget * w,gpointer data)1763 sett_hilite(GtkWidget *w,gpointer data) {
1764   global.HilightLastMove=GTK_CHECK_MENU_ITEM(w)->active;
1765   global.writeRC();
1766   global.repaintAllBoards();
1767 }
1768 
1769 void
sett_animate(GtkWidget * w,gpointer data)1770 sett_animate(GtkWidget *w,gpointer data) {
1771   global.AnimateMoves=GTK_CHECK_MENU_ITEM(w)->active;
1772   global.writeRC();
1773 }
1774 
1775 void
sett_premove(GtkWidget * w,gpointer data)1776 sett_premove(GtkWidget *w,gpointer data) {
1777   global.Premove=GTK_CHECK_MENU_ITEM(w)->active;
1778   global.writeRC();
1779   if (global.protocol && global.network)
1780     if (global.network->isConnected())
1781       global.protocol->updateVar(PV_premove);
1782 }
1783 
1784 void
sett_beepopp(GtkWidget * w,gpointer data)1785 sett_beepopp(GtkWidget *w,gpointer data) {
1786   global.BeepWhenOppMoves=GTK_CHECK_MENU_ITEM(w)->active;
1787   global.writeRC();
1788 }
1789 
1790 void
sett_osound(GtkWidget * w,gpointer data)1791 sett_osound(GtkWidget *w,gpointer data) {
1792   global.EnableSounds=GTK_CHECK_MENU_ITEM(w)->active;
1793   global.writeRC();
1794 }
1795 
1796 void
sett_vector(GtkWidget * w,gpointer data)1797 sett_vector(GtkWidget *w,gpointer data) {
1798   global.UseVectorPieces=GTK_CHECK_MENU_ITEM(w)->active;
1799   global.writeRC();
1800   global.repaintAllBoards();
1801 }
1802 
1803 void
sett_legal(GtkWidget * w,gpointer data)1804 sett_legal(GtkWidget *w,gpointer data) {
1805   global.CheckLegality=GTK_CHECK_MENU_ITEM(w)->active;
1806   global.writeRC();
1807 }
1808 
1809 void
sett_popup(GtkWidget * w,gpointer data)1810 sett_popup(GtkWidget *w,gpointer data) {
1811   global.PopupSecondaryGames=GTK_CHECK_MENU_ITEM(w)->active;
1812   global.writeRC();
1813 }
1814 
1815 void
sett_smarttrash(GtkWidget * w,gpointer data)1816 sett_smarttrash(GtkWidget *w,gpointer data) {
1817   global.SmartDiscard=GTK_CHECK_MENU_ITEM(w)->active;
1818   global.writeRC();
1819 }
1820 
1821 void
sett_coord(GtkWidget * w,gpointer data)1822 sett_coord(GtkWidget *w,gpointer data) {
1823   global.ShowCoordinates=GTK_CHECK_MENU_ITEM(w)->active;
1824   global.writeRC();
1825   global.repaintAllBoards();
1826 }
1827 
1828 void
game_resign(GtkWidget * w,gpointer data)1829 game_resign(GtkWidget *w,gpointer data) {
1830   if (global.protocol) global.protocol->resign();
1831 }
1832 
1833 void
game_draw(GtkWidget * w,gpointer data)1834 game_draw(GtkWidget *w,gpointer data) {
1835   if (global.protocol) global.protocol->draw();
1836 }
1837 
1838 void
game_adjourn(GtkWidget * w,gpointer data)1839 game_adjourn(GtkWidget *w,gpointer data) {
1840   if (global.protocol) global.protocol->adjourn();
1841 }
1842 
1843 void
game_abort(GtkWidget * w,gpointer data)1844 game_abort(GtkWidget *w,gpointer data) {
1845   if (global.protocol) global.protocol->abort();
1846 }
1847 
game_retract(GtkWidget * w,gpointer data)1848 void game_retract(GtkWidget *w,gpointer data) {
1849   if (global.protocol) global.protocol->retractMove();
1850 }
1851 
1852 // the next 2 functions keep focus in the input box
1853 // gcp was particularly annoyed by the focus not being
1854 // kept there...
1855 
1856 gboolean
forced_focus(gpointer data)1857 forced_focus(gpointer data)
1858 {
1859   gint a,b;
1860   gtk_editable_get_selection_bounds(GTK_EDITABLE(data),&a,&b); //FIXME
1861   gtk_widget_grab_focus(GTK_WIDGET(data));
1862   gtk_editable_select_region(GTK_EDITABLE(data),a,b);
1863   return FALSE;
1864 }
1865 
1866 gboolean
mainwindow_input_focus_out(GtkWidget * widget,GdkEventFocus * event,gpointer user_data)1867 mainwindow_input_focus_out(GtkWidget *widget,GdkEventFocus *event,gpointer user_data)
1868 {
1869   gtk_timeout_add(100,forced_focus,(gpointer)widget);
1870   return FALSE;
1871 }
1872 
1873 void
mainwindow_connect_bookmark(GtkWidget * w,gpointer data)1874 mainwindow_connect_bookmark(GtkWidget *w, gpointer data) {
1875   HostBookmark *bm;
1876   char p[32];
1877   bm=(HostBookmark *)data;
1878 
1879   // gcc 2.95 and up are just annoying with this const / non-const thing
1880   strcpy(p,"timeseal");
1881   global.chandler->openServer(bm->host,bm->port,new FicsProtocol(),
1882 			      strcmp(bm->protocol,"FICS") ? 0 : p);
1883 }
1884 
1885 void
mainwindow_connect_bookmark2(GtkWidget * w,gpointer data)1886 mainwindow_connect_bookmark2(GtkWidget *w, gpointer data) {
1887   EngineBookmark *bm;
1888   bm=(EngineBookmark *)data;
1889 
1890   mainw->openEngineBookmark(bm);
1891 }
1892 
1893 void
mainwindow_edit_engbm(GtkWidget * w,gpointer data)1894 mainwindow_edit_engbm(GtkWidget *w, gpointer data) {
1895   MainWindow *me;
1896   me=(MainWindow *) data;
1897   (new EditEngineBookmarksDialog( (BookmarkListener *) me ))->show();
1898 }
1899 
1900 // ThemeEntry
1901 
isDupe(ThemeEntry * te)1902 bool ThemeEntry::isDupe(ThemeEntry *te) {
1903   if (!te) return false;
1904   if (!Filename.compare(te->Filename)) return true;
1905   return false;
1906 }
1907 
isNameDupe(ThemeEntry * te)1908 bool ThemeEntry::isNameDupe(ThemeEntry *te) {
1909   if (!te) return false;
1910   if (!Text.compare(te->Text)) return true;
1911   return false;
1912 }
1913 
1914 // --- input mode selector
1915 
InputModeSelector()1916 InputModeSelector::InputModeSelector() {
1917   GtkWidget *h;
1918   int i;
1919 
1920   ChatMode=false;
1921   SearchMode=false;
1922   prefix.erase();
1923 
1924   widget = gtk_button_new();
1925 
1926   h=gtk_hbox_new(FALSE,0);
1927   l[0]=gtk_label_new(_("[cmd]"));
1928   l[1]=gtk_label_new("");
1929 
1930   gtk_container_add(GTK_CONTAINER(widget),h);
1931   for(i=0;i<2;i++) {
1932     gtk_box_pack_start(GTK_BOX(h),l[i],FALSE,TRUE,3*i);
1933     gshow(l[i]);
1934   }
1935 
1936   gshow(h);
1937 
1938   gtk_signal_connect(GTK_OBJECT(widget), "clicked",
1939 		     GTK_SIGNAL_FUNC(ims_switch), (gpointer) this);
1940 }
1941 
getChatMode()1942 bool InputModeSelector::getChatMode() {
1943   return ChatMode;
1944 }
1945 
getSearchMode()1946 bool InputModeSelector::getSearchMode() {
1947   return SearchMode;
1948 
1949 }
1950 
setSearchMode(bool m)1951 void InputModeSelector::setSearchMode(bool m) {
1952   SearchMode = m;
1953 
1954   if (!SearchMode) {
1955     setChatMode(ChatMode);
1956     return;
1957   }
1958 
1959   gtk_label_set_text(GTK_LABEL(l[0]), _("[find]"));
1960   gtk_label_set_text(GTK_LABEL(l[1]), "");
1961   setColor(l[0],0,0x80,0);
1962   setColor(l[1],0,0,0);
1963 }
1964 
setChatMode(bool m)1965 void InputModeSelector::setChatMode(bool m) {
1966   string x;
1967   ChatMode=m;
1968 
1969   x=m?_("[chat]"):
1970       _("[cmd]");
1971   gtk_label_set_text(GTK_LABEL(l[0]), x.c_str());
1972 
1973   if (m) {
1974     x=prefix;
1975     setColor(l[0],0xff,0,0);
1976     setColor(l[1],0,0,0xff);
1977   } else {
1978     x.erase();
1979     setColor(l[0],0,0,0);
1980   }
1981 
1982 
1983 
1984   gtk_label_set_text(GTK_LABEL(l[1]), x.c_str());
1985   gtk_widget_queue_resize(widget);
1986 }
1987 
getPrefix()1988 string & InputModeSelector::getPrefix() {
1989   return prefix;
1990 }
1991 
setPrefix(const char * s)1992 void InputModeSelector::setPrefix(const char *s) {
1993   prefix=s;
1994   if (ChatMode) setChatMode(true);
1995 }
1996 
setPrefix(string & s)1997 void InputModeSelector::setPrefix(string &s) {
1998   prefix=s;
1999   if (ChatMode) setChatMode(true);
2000 }
2001 
setColor(GtkWidget * w,int R,int G,int B)2002 void InputModeSelector::setColor(GtkWidget *w, int R,int G, int B) {
2003   GdkColor nc;
2004   GtkStyle *style;
2005   int i;
2006 
2007   nc.red   = R << 8;
2008   nc.green = G << 8;
2009   nc.blue  = B << 8;
2010   style=gtk_style_copy( gtk_widget_get_style(w) );
2011 
2012   for(i=0;i<5;i++)
2013     style->fg[i]=nc;
2014 
2015   gtk_widget_set_style( w, style );
2016   gtk_widget_queue_draw( w );
2017 }
2018 
flip()2019 void InputModeSelector::flip() {
2020   setChatMode(!ChatMode);
2021 }
2022 
ims_switch(GtkWidget * w,gpointer data)2023 void ims_switch(GtkWidget *w, gpointer data) {
2024   InputModeSelector *me;
2025   me=(InputModeSelector *) data;
2026   me->flip();
2027 }
2028 
get(int id)2029 string * PrefixCache::get(int id) {
2030   int i;
2031   // search back to front, since we are likely to get the latest
2032   // to be added
2033   for(i=ids.size()-1;i>=0;i--)
2034     if (ids[i] == id) return( text[i] );
2035   return 0;
2036 }
2037 
set(int id,string & val)2038 void PrefixCache::set(int id,string &val) {
2039   int i;
2040   for(i=ids.size()-1;i>=0;i--)
2041     if (ids[i] == id) {
2042       if (text[i]) delete(text[i]);
2043       text[i]=new string(val);
2044       return;
2045     }
2046   ids.push_back(id);
2047   text.push_back( new string(val) );
2048 }
2049 
set(int id,char * val)2050 void PrefixCache::set(int id,char *val) {
2051   set( id, * (new string(val)) );
2052 }
2053 
setIfNotSet(int id,string & val)2054 void PrefixCache::setIfNotSet(int id, string &val) {
2055   int i;
2056   for(i=ids.size()-1;i>=0;i--)
2057     if (ids[i] == id)
2058       return;
2059   ids.push_back(id);
2060   text.push_back( new string(val) );
2061 }
2062