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