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 <string.h>
27 #include "bugpane.h"
28 #include "global.h"
29 #include "eboard.h"
30 
31 string BugPane::BugTell;
32 
33 // ---------------- BareBoard
34 
BareBoard()35 BareBoard::BareBoard() : WidgetProxy() {
36   global.addPieceClient(this);
37   Names[0]=_("None");
38   Names[1]=_("None");
39 
40   widget=gtk_drawing_area_new();
41   gtk_widget_set_events(widget,GDK_EXPOSURE_MASK);
42   gtk_signal_connect(GTK_OBJECT(widget),"expose_event",
43 		     GTK_SIGNAL_FUNC(bareboard_expose),(gpointer)this);
44 
45   pixbuf=0;
46 
47   pset=0;
48   if (global.pieceset)
49     pset=new PieceSet(global.pieceset);
50 
51   clock.setHost(this);
52 
53   upending=false;
54   frozen=0;
55 }
56 
~BareBoard()57 BareBoard::~BareBoard() {
58   global.removePieceClient(this);
59   if (pixbuf)
60     gdk_pixmap_unref(pixbuf);
61 }
62 
setPosition(Position & pos)63 void BareBoard::setPosition(Position &pos) {
64   position = pos;
65   repaint();
66 }
67 
addPTell(char * text)68 void BareBoard::addPTell(char *text) {
69   PTells.push_back(string(text));
70   if (PTells.size() > 15) PTells.pop_front();
71 }
72 
setWhite(char * name)73 void BareBoard::setWhite(char *name) {
74   Names[0]=name;
75   repaint();
76 }
77 
setBlack(char * name)78 void BareBoard::setBlack(char *name) {
79   Names[1]=name;
80   repaint();
81 }
82 
update()83 void BareBoard::update() {
84   if (frozen>0)
85     upending=true;
86   else {
87     repaint();
88     upending=false;
89   }
90 }
91 
updateClock()92 void BareBoard::updateClock() {
93   repaint();
94 }
95 
setClock2(int wmsecs,int bmsecs,int actv,int cdown)96 void BareBoard::setClock2(int wmsecs,int bmsecs,int actv,int cdown) {
97   clock.setClock2(wmsecs,bmsecs,actv,cdown);
98   update();
99 }
100 
pieceSetChanged()101 void BareBoard::pieceSetChanged() {
102   if (pset)
103     delete pset;
104   pset = new PieceSet(global.pieceset);
105   update();
106 }
107 
reloadPieceSet()108 void BareBoard::reloadPieceSet() {
109   if (pset)
110     delete pset;
111   pset = new PieceSet(global.pieceset);
112 }
113 
freeze()114 void BareBoard::freeze() {
115   ++frozen;
116 }
117 
thaw()118 void BareBoard::thaw() {
119   --frozen;
120   if ( (frozen<1) && upending )
121     update();
122 }
123 
bareboard_expose(GtkWidget * widget,GdkEventExpose * ee,gpointer data)124 gboolean bareboard_expose(GtkWidget *widget,GdkEventExpose *ee,
125 			  gpointer data) {
126 
127   BareBoard *me;
128   int i,j,k,ww,wh,zh,x,y=0;
129   int sqside;
130   GdkGC *gc;
131   char z[256],t[64];
132   list<string>::iterator pti;
133   rgbptr tmp;
134   int rowsz;
135   bool flip;
136 
137   static piece stock[5]={PAWN,ROOK,KNIGHT,BISHOP,QUEEN};
138 
139   flip=global.BoardList.front()->effectiveFlip();
140   flip=!flip;
141 
142   me=(BareBoard *)data;
143 
144   gdk_window_get_size(widget->window,&ww,&wh);
145   zh=wh;
146   sqside=ww/8;
147 
148   if ( (!global.UseVectorPieces) && (me->pset->extruded) )
149     wh-=wh/16;
150 
151   if (wh<ww) sqside=wh/8;
152 
153   if (me->pixbuf) {
154     if (ww != me->pixw || wh != me->pixh) {
155       gdk_pixmap_unref(me->pixbuf);
156       me->pixbuf=0;
157       me->pixw=ww;
158       me->pixh=wh;
159     }
160   }
161 
162   if (! me->pixbuf)
163     me->pixbuf=gdk_pixmap_new(widget->window,ww,wh,-1);
164 
165   gc=gdk_gc_new(me->pixbuf);
166   gdk_rgb_gc_set_foreground(gc,0);
167   gdk_draw_rectangle(me->pixbuf,gc,TRUE,0,0,ww,wh);
168 
169   me->C.prepare(widget,me->pixbuf,gc,0,0,ww,wh);
170   me->C.setFont(0,global.InfoFont);
171 
172   if (sqside > 8) {
173 
174     if (global.UseVectorPieces) {
175       global.vpieces.drawSquares(me->pixbuf,gc,sqside);
176 
177       for(i=0;i<8;i++)
178 	for(j=0;j<8;j++)
179 	  global.vpieces.drawPiece(me->pixbuf,gc,sqside,
180 				   i*sqside, j*sqside,
181 				   me->position.getPiece(flip?7-i:i,
182 							 flip?j:7-j));
183     } else {
184       if (me->pset->extruded) y=sqside/2;
185       if (me->pset->side != sqside) {
186 	me->reloadPieceSet();
187 	me->pset->scale(sqside);
188       }
189 
190       rowsz=sqside*8;
191       tmp=(rgbptr)g_malloc(rowsz * (rowsz+sqside/2) * 4);
192 
193 
194       me->pset->beginQueueing();
195       for(i=0;i<8;i++)
196 	for(j=0;j<8;j++)
197 	  me->pset->drawPieceAndSquare(me->position.getPiece(flip?7-i:i,
198 							     flip?j:7-j),
199 				       tmp, i*sqside , y+j*sqside, rowsz,
200 				       (i+j)%2);
201       me->pset->endQueueing();
202 
203       gdk_draw_rgb_image(me->pixbuf, gc, 0, 0, rowsz, rowsz+y,
204 			 GDK_RGB_DITHER_NORMAL, tmp, rowsz*3);
205 
206       g_free(tmp);
207 
208     }
209 
210 
211     x=sqside*8+10;
212 
213     int fh = me->C.fontHeight(0);
214 
215     me->C.setColor(0xffffff);
216     me->C.drawString(x,10,0,_("Bughouse: Partner Game"));
217     me->C.drawString(x+1,10,0,_("Bughouse: Partner Game"));
218 
219     // white's clock
220 
221     if (me->clock.getActive() == -1) {
222       //gdk_draw_rectangle(me->pixbuf,gc,TRUE,x-5,(flip?40:zh-5-fh), 150, 20);
223       me->C.setColor(0xff8800);
224     }
225 
226     me->clockString(me->clock.getValue2(0),t,64);
227     snprintf(z,256,_("White: %s - %s"),me->Names[0].c_str(),t);
228 
229     me->C.drawString(x,flip?40:zh-5-fh,0,z);
230 
231     // black's clock
232 
233     me->C.setColor(0xffffff);
234     if (me->clock.getActive() == 1) {
235       //gdk_draw_rectangle(me->pixbuf,gc,TRUE,x-5,(flip?zh-5-fh:40), 150, 20);
236       me->C.setColor(0xff8800);
237     }
238 
239     me->clockString(me->clock.getValue2(1),t,64);
240     snprintf(z,256,_("Black: %s - %s"),me->Names[1].c_str(),t);
241     me->C.drawString(x,flip?zh-5-fh:40,0,z);
242 
243     // paint stock
244 
245     // white's stock
246 
247     x=sqside*8+10;
248     for(i=0;i<5;i++) {
249       k=me->position.getStockCount(stock[i]|WHITE);
250       for(j=0;j<k;j++) {
251 	global.vpieces.drawPiece(me->pixbuf,gc,sqside,x,flip?45:zh-5-sqside-20,
252 				 stock[i]|WHITE);
253 	x+=sqside+2;
254       }
255     }
256 
257     // black's stock
258 
259     x=sqside*8+10;
260     for(i=0;i<5;i++) {
261       k=me->position.getStockCount(stock[i]|BLACK);
262       for(j=0;j<k;j++) {
263 	global.vpieces.drawPiece(me->pixbuf,gc,sqside,x,flip?zh-5-sqside-20:45,
264 				 stock[i]|BLACK);
265 	x+=sqside+2;
266       }
267     }
268 
269     // paint ptells
270 
271     x=sqside*8+10;
272     me->C.setColor(global.Colors.TextBright);
273     me->C.drawString(x,40+sqside,0,_("Partner Tells:"));
274 
275     if (!me->PTells.empty()) {
276       me->C.setColor(global.Colors.PrivateTell);
277       i=zh-20-5-sqside;
278 
279       pti=me->PTells.end();
280       for(pti--;i>(59+sqside);i-=20, pti--) {
281 	me->C.drawString(x,i,0,(*pti).c_str() );
282 	if (pti == me->PTells.begin())
283 	  break;
284       }
285     }
286   }
287   gdk_gc_destroy(gc);
288   gc=gdk_gc_new(widget->window);
289   gdk_draw_pixmap(widget->window,gc,me->pixbuf,0,0,0,0,ww,zh);
290   gdk_gc_destroy(gc);
291   return 1;
292 }
293 
294 // ---------------- BugPane
295 
BugPane()296 BugPane::BugPane() {
297   GtkWidget *v, *tbl, *qb[18];
298   GdkColor gray[5];
299   GtkStyle *style;
300   int i,c,r;
301   static const char *stuff[18]={"---","--","-","+","++","+++",
302 				"P","N","B","R","Q","Diag",
303 				"Sit","Go","Fast","Hard","Dead","Safe"};
304 
305 
306   widget = gtk_hbox_new(FALSE,0);
307 
308   board = new BareBoard();
309   board->show();
310 
311   gtk_box_pack_start(GTK_BOX(widget), board->widget, TRUE,TRUE, 0);
312 
313   // vbox
314   v=gtk_vbox_new(FALSE,0);
315   gtk_box_pack_start(GTK_BOX(widget), v, FALSE, TRUE, 0);
316 
317   // table
318   tbl=gtk_table_new(6,3,FALSE);
319   gray[0].red=gray[0].green=gray[0].blue=0xaaaa;
320   gray[1].red=gray[1].green=gray[1].blue=0x8888;
321   gray[2].red=gray[2].green=gray[2].blue=0xcccc;
322   gray[3].red=gray[3].green=gray[3].blue=0x8888;
323   gray[4].red=gray[4].green=gray[4].blue=0xaaaa;
324   style=gtk_style_copy( gtk_widget_get_default_style() );
325   for(i=0;i<5;i++)
326     style->bg[i]=gray[i];
327 
328   // buttons
329   for(i=0;i<18;i++) {
330 
331     qb[i]=gtk_button_new_with_label(stuff[i]);
332     if (i<6)
333       gtk_widget_set_style(qb[i],style);
334 
335     c=i/6;
336     r=i%6;
337     gtk_table_attach_defaults(GTK_TABLE(tbl),qb[i],c,c+1,r,r+1);
338     gshow(qb[i]);
339     gtk_signal_connect(GTK_OBJECT(qb[i]),"clicked",
340 		       GTK_SIGNAL_FUNC(bug_ptell),(gpointer)(stuff[i]));
341   }
342 
343   gtk_box_pack_start(GTK_BOX(v), tbl, FALSE, FALSE, 0);
344 
345   Gtk::show(tbl,v,NULL);
346 }
347 
stopClock()348 void BugPane::stopClock() {
349   board->setClock2(0,0,0,1);
350 }
351 
reset()352 void BugPane::reset() {
353   Position p;
354 
355   freeze();
356   board->setClock2(0,0,0,1);
357   board->setPosition(p);
358   board->setWhite(_("None"));
359   board->setBlack(_("None"));
360   thaw();
361 
362 }
363 
addBugText(char * text)364 void BugPane::addBugText(char *text) {
365   board->addPTell(text);
366   board->update();
367 }
368 
setPlayerNames(char * white,char * black)369 void BugPane::setPlayerNames(char *white, char *black) {
370   board->setWhite(white);
371   board->setBlack(black);
372   board->update();
373 }
374 
setPosition(Position & pos)375 void BugPane::setPosition(Position &pos) {
376   board->setPosition(pos);
377   board->update();
378 }
379 
setClock2(int wmsecs,int bmsecs,int actv,int cdown)380 void BugPane::setClock2(int wmsecs,int bmsecs,int actv,int cdown) {
381   board->setClock2(wmsecs,bmsecs,actv,cdown);
382 }
383 
freeze()384 void BugPane::freeze() { board->freeze(); }
thaw()385 void BugPane::thaw()   { board->thaw(); }
386 
bug_ptell(GtkWidget * b,gpointer data)387 void bug_ptell(GtkWidget *b,gpointer data) {
388   char z[256],x[256],c;
389 
390   g_strlcpy(z,(char *)data,256);
391 
392   if ((z[0]=='-')||(z[0]=='+')) {
393     BugPane::BugTell=z;
394     return;
395   } else {
396     if (BugPane::BugTell.empty())
397       BugPane::BugTell=z;
398     else {
399       g_strlcpy(x,BugPane::BugTell.c_str(),256);
400       c=x[strlen(x)-1];
401       if ((c=='+')||(c=='-'))
402 	BugPane::BugTell+=z;
403       else
404 	BugPane::BugTell=z;
405     }
406   }
407 
408   if (global.protocol) {
409     snprintf(z,256,"ptell %s",BugPane::BugTell.c_str());
410     global.protocol->sendUserInput(z);
411   }
412 }
413