1 /*
2 * IceBreaker
3 * Copyright (c) 2000-2002 Matthew Miller <mattdm@mattdm.org> and
4 *   Enrico Tassi <gareuselesinge@infinito.it>
5 *
6 * <http://www.mattdm.org/icebreaker/>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 2 of the License, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 * for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc., 59
20 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23 
24 #include <SDL.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include "icebreaker.h"
28 #include "globals.h"
29 #include "text.h"
30 #include "laundry.h"
31 #include "dialog.h"
32 #include "sound.h"
33 #include "hiscore.h"
34 #include "options.h"
35 #include "fullscreen.h"
36 #include "themes.h"
37 #include "grid.h"
38 #include "status.h"
39 #include "level.h"
40 #include "event.h"
41 
42 
gethighusername(int highest)43 PopupReturnType gethighusername(int highest)
44 {
45 	SDL_Rect tmprect,namerect,okayrect;
46 	SDL_Event event;
47 	int done=false;
48 	PopupReturnType rc=POPUPDONOTHING;
49 	int okayglow=false;
50 	int okaypressed=false;
51 	int clearname=true;
52 
53 	char keypressed;
54 	int insertionpoint=0;
55 
56 	tmprect.w=282;
57 	tmprect.h=92;
58 	tmprect.x=(WIDTH/2)-(tmprect.w/2)-1;
59 	tmprect.y=(HEIGHT/2)+31;
60 	SDL_FillRect(screen,&tmprect,color.gridline);
61 
62 	tmprect.w-=2; tmprect.h-=2;
63 	tmprect.x++; tmprect.y++;
64 	SDL_FillRect(screen,&tmprect,color.background);
65 
66 	if (highest)
67 		puttext(tmprect.x+7,tmprect.y+7,2,color.normaltext,"NEW TOP SCORE!");
68 	else
69 		puttext(tmprect.x+7,tmprect.y+7,2,color.normaltext,"NEW HIGH SCORE.");
70 	puttext(tmprect.x+7,tmprect.y+7+16,2,color.normaltext,"ENTER YOUR NAME:");
71 
72 	namerect.w=268;
73 	namerect.h=29;
74 	namerect.x=tmprect.x+6;
75 	namerect.y=tmprect.y+7+32;
76 
77 	SDL_FillRect(screen,&namerect,color.textentrybox);
78 
79 	// this makes sure username fits. maybe a bit gross to have this
80 	// truncated here, but hey.
81 	while(strlen(username)>1 && gettextwidth(4,username) > namerect.w-8)
82 	{
83 		username[strlen(username)-1]='\0';
84 	}
85 
86 	puttext(namerect.x+4,namerect.y+5,4,color.textentrytext,username);
87 
88 	okayrect.x=tmprect.x+tmprect.w-32;
89 	okayrect.y=tmprect.y+7+64;
90 	okayrect.h=CHARHEIGHT*2+3;
91 	okayrect.w=CHARWIDTH*2*2+1;
92 
93 	//SDL_FillRect(screen,&okayrect,color.textentrybox);
94 	puttext(okayrect.x+3,okayrect.y+3,2,color.normaltext,"OK");
95 
96 
97 	updateall();  // fix -- is this really needed? we should soil() the
98 	              // above rectangles instead, i  think
99 
100 
101 	SDL_EnableUNICODE(1);
102 	SDL_EnableKeyRepeat(500,90);
103 
104 	clean();
105 	do
106 	{
107 		SDL_WaitEvent(NULL); // no new CPU cooler needed. :)
108 		while (pollevent(&event))
109 		{
110 			if (event.type == SDL_QUIT)
111 			{
112 				done=true;
113 				rc=POPUPQUITGAME;
114 			}
115 			else if (event.type == SDL_MOUSEBUTTONDOWN)
116 			{  // fix -- make this left button only
117 				if (event.button.x>=okayrect.x
118 				 && event.button.y>=okayrect.y
119 				 && event.button.x<okayrect.x+okayrect.w
120 				 && event.button.y<okayrect.y+okayrect.h)
121 				okaypressed=true;
122 			}
123 			else if (event.type == SDL_MOUSEBUTTONUP)
124 			{
125 				if (okaypressed
126 				 && event.button.x>=okayrect.x
127 				 && event.button.y>=okayrect.y
128 				 && event.button.x<okayrect.x+okayrect.w
129 				 && event.button.y<okayrect.y+okayrect.h)
130 				{
131 					if (username[0]!='\0')
132 					{
133 						done=true;
134 						rc=POPUPOK;
135 					}
136 					else
137 					{
138 						playsound(SNDOUCH);
139 					}
140 				}
141 				else if (okayglow)
142 				{
143 					okayglow=false;
144 					SDL_FillRect(screen,&okayrect,color.background);
145 					puttext(okayrect.x+3,okayrect.y+3,2,color.normaltext,"OK");
146 					soil(okayrect);
147 				}
148 				okaypressed=false;
149 			}
150 			else if (event.type == SDL_MOUSEMOTION)
151 			{
152 				if (event.motion.x>=okayrect.x
153 				 && event.motion.y>=okayrect.y
154 				 && event.motion.x<okayrect.x+okayrect.w
155 				 && event.motion.y<okayrect.y+okayrect.h)
156 				 {
157 					if (!okayglow)
158 					{
159 						okayglow=true;
160 						SDL_FillRect(screen,&okayrect,color.menuhighlight);
161 						puttext(okayrect.x+3,okayrect.y+3,2,color.background,"OK");
162 						soil(okayrect);
163 					}
164 
165 				}
166 				else
167 				{
168 					if (okayglow && !okaypressed)
169 					{
170 						okayglow=false;
171 						SDL_FillRect(screen,&okayrect,color.background);
172 						puttext(okayrect.x+3,okayrect.y+3,2,color.normaltext,"OK");
173 						soil(okayrect);
174 					}
175 				}
176 
177 			}
178 			else if (event.type==SDL_KEYDOWN)
179 			{
180 
181 				if (event.key.keysym.sym==SDLK_BACKSPACE ||
182 				    event.key.keysym.sym==SDLK_DELETE ||
183 				    event.key.keysym.sym==SDLK_LEFT)
184 				{
185 					if (clearname)
186 					{
187 						insertionpoint=0;
188 						username[0]='\0'; // null out username
189 					}
190 					else if (insertionpoint>0)
191 					{
192 						insertionpoint--;
193 						username[insertionpoint]='\0';
194 					}
195 					else
196 					{
197 						playsound(SNDOUCH);
198 					}
199 					clearname=false;
200 				}
201 				else if (event.key.keysym.sym==SDLK_RETURN || event.key.keysym.sym==SDLK_KP_ENTER)
202 				{
203 					if (username[0]!='\0')
204 					{
205 						done=true;
206 						rc=POPUPOK;
207 					}
208 					else
209 					{
210 						playsound(SNDOUCH);
211 					}
212 					clearname=false;
213 				}
214 				else if (event.key.keysym.sym==SDLK_ESCAPE || event.key.keysym.sym==SDLK_CLEAR) // fix -- make ctrl-u work here
215 				{
216 					insertionpoint=0;
217 					username[0]='\0'; // null out username
218 					clearname=false;
219 				}
220 				else if ((event.key.keysym.unicode & 0xFF80) == 0) // make sure it's ascii
221 				{
222 					keypressed=event.key.keysym.unicode & 0x7F;
223 					if (keypressed==32) keypressed=95;
224 					if (keypressed>32 && keypressed<127)
225 					{
226 						if (clearname)
227 						{
228 							insertionpoint=0;
229 							clearname=false;
230 						}
231 						if (insertionpoint<(50-1) && gettextwidth(4,username)+getletterwidth(4,keypressed) <= namerect.w-8) //(insertionpoint<12)
232 						{
233 							username[insertionpoint]=keypressed;
234 							username[insertionpoint+1]='\0';
235 							insertionpoint++;
236 						}
237 						else
238 						{
239 							playsound(SNDOUCH);
240 						}
241 					}
242 				}
243 				SDL_FillRect(screen,&namerect,color.textentrybox);
244 				puttext(namerect.x+4,namerect.y+5,4,color.textentrytext,username);
245 				soil(namerect);
246 			}
247 		}
248 		clean();
249 	} while (!done);
250 
251 	// because the game is over, restore of background is unnecessary
252 
253 	SDL_EnableKeyRepeat(0,0);
254 	SDL_EnableUNICODE(0);
255 	return(rc);
256 }
257 
258 
popuphighscores()259 PopupReturnType popuphighscores()
260 {
261 	SDL_Rect scorelistrect,borderrect;
262 	SDL_Surface * scorelistsave;
263 	PopupReturnType rc=POPUPDONOTHING;
264 	int i;
265 	char buf[30]; // plenty big. :)
266 
267 	scorelistrect.w=PLAYWIDTH-(BLOCKWIDTH*11);
268 	scorelistrect.h=PLAYHEIGHT-(BLOCKHEIGHT*4);
269 	scorelistrect.x=BORDERLEFT+PLAYWIDTH/2-scorelistrect.w/2+BLOCKWIDTH*4;
270 	scorelistrect.y=BORDERTOP+PLAYHEIGHT/2-scorelistrect.h/2+BLOCKHEIGHT/2;
271 
272 	borderrect.w=scorelistrect.w+2;
273 	borderrect.h=scorelistrect.h+2;
274 	borderrect.x=scorelistrect.x-1;
275 	borderrect.y=scorelistrect.y-1;
276 
277 	scorelistsave = SDL_CreateRGBSurface(SDL_SWSURFACE,borderrect.w,borderrect.h,screen->format->BitsPerPixel,0,0,0,0);
278 	SDL_BlitSurface(screen, &borderrect, scorelistsave, NULL);
279 
280 	SDL_FillRect(screen,&borderrect,color.gridline);
281 	SDL_FillRect(screen,&scorelistrect,color.background);
282 
283 	puttext(scorelistrect.x+(scorelistrect.w/2-(CHARWIDTH*2*9)),scorelistrect.y+BLOCKHEIGHT,4,color.bonusscrolltext,"HIGH SCORES");
284 
285 	// just in case they've changed...
286 	readhiscores();
287 
288 	for (i=0;i<HISCORENUM;i++)
289 	{
290 		snprintf(buf,sizeof(buf),"%d.",i+1);
291 		puttext(scorelistrect.x+BLOCKWIDTH,scorelistrect.y+45+i*(CHARHEIGHT*2+5),2,color.normaltext,buf);
292 		puttext(scorelistrect.x+BLOCKWIDTH*4,scorelistrect.y+45+i*(CHARHEIGHT*2+5),2,color.normaltext,hiscorename[i]);
293 		snprintf(buf,sizeof(buf),"%ld",hiscoreval[i]);
294 		puttext(scorelistrect.x+scorelistrect.w-(BLOCKWIDTH*5),scorelistrect.y+45+i*(CHARHEIGHT*2+5),2,color.normaltext,buf);
295 	}
296 
297 	soil(borderrect);
298 
299 	clean();
300 
301 	rc=waitforuser();
302 
303 	SDL_BlitSurface(scorelistsave, NULL, screen, &borderrect);
304 	soil(borderrect);
305 	clean();
306 
307 	SDL_FreeSurface(scorelistsave);
308 
309 	return(rc);
310 }
311 
popuphelp()312 PopupReturnType popuphelp()
313 {
314 	SDL_Rect helprect,borderrect;
315 	SDL_Surface * helpsave;
316 	PopupReturnType rc=POPUPDONOTHING;
317 	int i=0;
318 	char buf[80];
319 
320 
321 #ifdef ONEBUTTONMICEARESILLY
322 	char helptext[13][50]={
323 	     "Ok, so there's a bunch of penguins on an",
324 	     "iceberg in Antarctica. You must catch them",
325 	     "so they can be shipped to Finland. The",
326 	     "smaller the area in which they're caught,",
327 	     "the lower the shipping fees and the higher",
328 	     "your score - but don't take too long: the",
329 	     "clock is ticking. Once 80% of the 'berg is",
330 	     "cleared, it's on to the next shipment.",
331 	     "",
332 	     "The left mouse button starts lines; right",
333 	     "button or [spacebar] toggles direction.",
334 	     "",
335 	     "Check the README file for more info."
336 	      };
337 #else
338 	char helptext[13][50]={
339 	     "Ok, so there's a bunch of penguins on an",
340 	     "iceberg in Antarctica. You must catch them",
341 	     "so they can be shipped to Finland. The",
342 	     "smaller the area in which they're caught,",
343 	     "the lower the shipping fees and the higher",
344 	     "your score - but don't take too long: the",
345 	     "clock is ticking. Once 80% of the 'berg is",
346 	     "cleared, it's on to the next shipment.",
347 	     "",
348 	     "The left mouse button starts lines; right",
349 	     "button toggles direction. You'll catch on.",
350 	     "",
351 	     "Check the README file for more info."
352 	      };
353 #endif
354 
355 	helprect.w=PLAYWIDTH-(BLOCKWIDTH*2)+2;
356 	helprect.h=PLAYHEIGHT-(BLOCKHEIGHT*3);
357 	helprect.x=BORDERLEFT+PLAYWIDTH/2-helprect.w/2;
358 	helprect.y=BORDERTOP+PLAYHEIGHT/2-helprect.h/2;
359 
360 	borderrect.w=helprect.w+2;
361 	borderrect.h=helprect.h+2;
362 	borderrect.x=helprect.x-1;
363 	borderrect.y=helprect.y-1;
364 
365 	helpsave = SDL_CreateRGBSurface(SDL_SWSURFACE,borderrect.w,borderrect.h,screen->format->BitsPerPixel,0,0,0,0);
366 	SDL_BlitSurface(screen, &borderrect, helpsave, NULL);
367 
368 	SDL_FillRect(screen,&borderrect,color.gridline);
369 	SDL_FillRect(screen,&helprect,color.background);
370 
371 	for (i=0;i<13;i++)
372 	{
373 		puttext(helprect.x+BLOCKWIDTH/2,helprect.y+BLOCKHEIGHT/2+i*(CHARHEIGHT*2+4),2,color.normaltext,helptext[i]);
374 	}
375 	snprintf(buf,sizeof(buf),"v%d.%d.%d   %s",VERMAJOR,VERMINOR,VERSUB,"Copyright (c) 2000-2002 Matthew Miller. Released under the GPL.");
376 	puttext(helprect.x+BLOCKWIDTH/2,helprect.y+helprect.h-CHARHEIGHT*3,1,color.copyrighttext,buf);
377 	puttext(helprect.x+BLOCKWIDTH/2,helprect.y+helprect.h-CHARHEIGHT*1-3,1,color.copyrighttext,"Thanks to my wonderful wife Karen for inspiration (and for patience)!");
378 
379 	soil(borderrect);
380 
381 	clean();
382 
383 	rc=waitforuser();
384 
385 	SDL_BlitSurface(helpsave, NULL, screen, &borderrect);
386 	soil(borderrect);
387 	clean();
388 
389 	SDL_FreeSurface(helpsave);
390 
391 	return(rc);
392 }
393 
394 
395 /* Wait for the user to hit a key or button or quit; returns true if quit */
waitforuser()396 PopupReturnType waitforuser()
397 {
398 	int done=false;
399 	PopupReturnType rc=POPUPDONOTHING;
400 	SDL_Event event;
401 
402 	do
403 	{
404 		SDL_WaitEvent(NULL);
405 		while(pollevent(&event))
406 		{
407 			if ( event.type == SDL_QUIT)
408 			{
409 				done=true;
410 				rc=POPUPQUITGAME;
411 			}
412 			else if (event.type == SDL_MOUSEBUTTONUP)
413 			{
414 				done=true;
415 			}
416 			else if (event.type == SDL_KEYUP)
417 			{
418 				switch(translatekeyevent(&event))
419 				{
420 					case KEYCANCEL:     // falls through
421 					case KEYMENU:       // falls through
422 					case KEYSWITCHLINE: // falls through
423 					case KEYSTARTLINE:
424 						done=true;
425 					default:
426 					break;
427 				}
428 
429 			}
430 		}
431 	} while (!done);
432 	return(rc);
433 }
434 
435 
436 // fix -- make this more generic (one or two buttons, selectable button text)
yesnodialog(char * text1,char * text2,char * text3)437 PopupReturnType yesnodialog(char* text1, char* text2, char* text3)
438 {
439 	SDL_Rect tmprect, yesrect,norect;
440 	SDL_Event event;
441 	int done=false;
442 	int rc=POPUPDONOTHING;
443 	int yesglow=false;
444 	int yespressed=false;
445 	int noglow=false;
446 	int nopressed=false;
447 	SDL_Surface* bgsave;
448 
449 	tmprect.w=gettextwidth(2,text1);
450 	if (gettextwidth(2,text2)>tmprect.w) tmprect.w=gettextwidth(2,text2);
451 	if (gettextwidth(2,text3)>tmprect.w) tmprect.w=gettextwidth(2,text3);
452 	tmprect.w+=15;
453 	tmprect.h=92; // fix -- make dialog shorter if text3=null. maybe also text2, but that might be too short
454 	tmprect.x=(WIDTH/2)-(tmprect.w/2);
455 	tmprect.y=(HEIGHT/2)-(tmprect.h/2);
456 
457 	// fix -- error checking if this fails
458 	bgsave = SDL_CreateRGBSurface(SDL_SWSURFACE,tmprect.w,tmprect.h,screen->format->BitsPerPixel,0,0,0,0);
459 	SDL_BlitSurface(screen, &tmprect, bgsave, NULL);
460 
461 	SDL_FillRect(screen,&tmprect,color.gridline);
462 
463 	tmprect.w-=2; tmprect.h-=2;
464 	tmprect.x++; tmprect.y++;
465 	SDL_FillRect(screen,&tmprect,color.background);
466 	tmprect.w+=2; tmprect.h+=2; // yay kludgy
467 	tmprect.x--; tmprect.y--;
468 
469 
470 
471 	puttext(tmprect.x+(tmprect.w-gettextwidth(2,text1))/2,tmprect.y+7,2,color.normaltext,text1);
472 	puttext(tmprect.x+(tmprect.w-gettextwidth(2,text2))/2,tmprect.y+7+CHARHEIGHT*3,2,color.normaltext,text2);
473 	puttext(tmprect.x+(tmprect.w-gettextwidth(2,text3))/2,tmprect.y+7+CHARHEIGHT*6,2,color.normaltext,text3);
474 
475 	norect.x=tmprect.x+tmprect.w-33;
476 	norect.y=tmprect.y+7+64;
477 	norect.h=CHARHEIGHT*2+3;
478 	norect.w=CHARWIDTH*2*2+1;
479 
480 	yesrect.x=tmprect.x+7;
481 	yesrect.y=tmprect.y+7+64;
482 	yesrect.h=CHARHEIGHT*2+3;
483 	yesrect.w=CHARWIDTH*2*3+1;
484 
485 	puttext(norect.x+3,norect.y+3,2,color.normaltext,"NO");
486 	puttext(yesrect.x+3,yesrect.y+3,2,color.normaltext,"YES");
487 
488 
489 	soil(tmprect);
490 
491 	clean();
492 	do
493 	{
494 		SDL_WaitEvent(NULL);
495 		while (pollevent(&event))
496 		{
497 			if (event.type == SDL_QUIT)
498 			{
499 				done=true;
500 				rc=POPUPQUITGAME;
501 			}
502 			else if (event.type == SDL_MOUSEBUTTONDOWN)
503 			{  // fix -- make this left button only
504 				if (event.button.x>=norect.x
505 				 && event.button.y>=norect.y
506 				 && event.button.x<norect.x+norect.w
507 				 && event.button.y<norect.y+norect.h)
508 				nopressed=true;
509 				else if (event.button.x>=yesrect.x
510 				 && event.button.y>=yesrect.y
511 				 && event.button.x<yesrect.x+yesrect.w
512 				 && event.button.y<yesrect.y+yesrect.h)
513 				yespressed=true;
514 			}
515 			else if (event.type == SDL_MOUSEBUTTONUP)
516 			{
517 				if (nopressed
518 				 && event.button.x>=norect.x
519 				 && event.button.y>=norect.y
520 				 && event.button.x<norect.x+norect.w
521 				 && event.button.y<norect.y+norect.h)
522 				{
523 					done=true;
524 					rc=POPUPNO;
525 				}
526 				else if (noglow)
527 				{
528 					noglow=false;
529 					SDL_FillRect(screen,&norect,color.background);
530 					puttext(norect.x+3,norect.y+3,2,color.normaltext,"NO");
531 					soil(norect);
532 				}
533 				nopressed=false;
534 
535 				if (yespressed
536 				 && event.button.x>=yesrect.x
537 				 && event.button.y>=yesrect.y
538 				 && event.button.x<yesrect.x+yesrect.w
539 				 && event.button.y<yesrect.y+yesrect.h)
540 				{
541 					done=true;
542 					rc=POPUPYES;
543 				}
544 				else if (yesglow)
545 				{
546 					yesglow=false;
547 					SDL_FillRect(screen,&yesrect,color.background);
548 					puttext(yesrect.x+3,yesrect.y+3,2,color.normaltext,"YES");
549 					soil(yesrect);
550 				}
551 				yespressed=false;
552 			}
553 			else if (event.type == SDL_MOUSEMOTION)
554 			{
555 				if (event.motion.x>=norect.x
556 				 && event.motion.y>=norect.y
557 				 && event.motion.x<norect.x+norect.w
558 				 && event.motion.y<norect.y+norect.h)
559 				 {
560 					if (!noglow)
561 					{
562 						noglow=true;
563 						SDL_FillRect(screen,&norect,color.menuhighlight);
564 						puttext(norect.x+3,norect.y+3,2,color.background,"NO");
565 						soil(norect);
566 					}
567 
568 				}
569 				else
570 				{
571 					if (noglow && !nopressed)
572 					{
573 						noglow=false;
574 						SDL_FillRect(screen,&norect,color.background);
575 						puttext(norect.x+3,norect.y+3,2,color.normaltext,"NO");
576 						soil(norect);
577 					}
578 				}
579 				if (event.motion.x>=yesrect.x
580 				 && event.motion.y>=yesrect.y
581 				 && event.motion.x<yesrect.x+yesrect.w
582 				 && event.motion.y<yesrect.y+yesrect.h)
583 				 {
584 					if (!yesglow)
585 					{
586 						yesglow=true;
587 						SDL_FillRect(screen,&yesrect,color.menuhighlight);
588 						puttext(yesrect.x+3,yesrect.y+3,2,color.background,"YES");
589 						soil(yesrect);
590 					}
591 
592 				}
593 				else
594 				{
595 					if (yesglow && !yespressed)
596 					{
597 						yesglow=false;
598 						SDL_FillRect(screen,&yesrect,color.background);
599 						puttext(yesrect.x+3,yesrect.y+3,2,color.normaltext,"YES");
600 						soil(yesrect);
601 					}
602 				}
603 
604 			}
605 			else if (event.type==SDL_KEYDOWN)
606 			{
607 				if (event.key.keysym.sym==SDLK_n)
608 				{
609 					done=true;
610 					rc=POPUPNO;
611 				}
612 				else if (event.key.keysym.sym==SDLK_ESCAPE)
613 				{
614 					// little hack to keep escape key from "bleeding" into
615 					// cancelling the whole menu
616 					done=true;
617 					rc=POPUPYES;
618 					SDL_Delay(200);
619 					while(pollevent(&event) && (event.type==SDL_KEYDOWN || event.type==SDL_KEYUP));
620 				}
621 				else if (event.key.keysym.sym==SDLK_y || event.key.keysym.sym==SDLK_RETURN || event.key.keysym.sym==SDLK_KP_ENTER)
622 				{
623 					done=true;
624 					rc=POPUPYES;
625 				}
626 			}
627 		}
628 		clean();
629 	} while (!done);
630 
631 	SDL_BlitSurface(bgsave, NULL, screen, &tmprect);
632 	soil(tmprect);
633 	clean();
634 
635 	return(rc);
636 }
637