1 /*
2 * Abuse - dark 2D side-scrolling platform game
3 * Copyright (c) 1995 Crack dot Com
4 * Copyright (c) 2005-2011 Sam Hocevar <sam@hocevar.net>
5 *
6 * This software was released into the Public Domain. As with most public
7 * domain software, no warranty is made or implied by Crack dot Com, by
8 * Jonathan Clark, or by Sam Hocevar.
9 */
10
11 #if defined HAVE_CONFIG_H
12 # include "config.h"
13 #endif
14
15 #include <string.h>
16
17 #include "common.h"
18
19 #include "input.h"
20
remap(Filter * f)21 void button::remap(Filter *f)
22 {
23 if (visual)
24 {
25 f->Apply(visual);
26 if (pressed)
27 f->Apply(pressed);
28 }
29 }
30
press_button(int id)31 void button_box::press_button(int id) // if button box doesn't contain id, nothing happens
32 {
33 }
34
remap(Filter * f)35 void button_box::remap(Filter *f)
36 {
37 for (button *b=buttons; b; b=(button *)b->next)
38 b->remap(f);
39 }
40
find(int search_id)41 ifield *button_box::find(int search_id)
42 {
43 if (search_id==id) return this;
44 for (ifield *i=(ifield *)buttons; i; i=i->next)
45 if (search_id==i->id) return i;
46 return NULL;
47 }
48
button_box(int X,int Y,int ID,int MaxDown,button * Buttons,ifield * Next)49 button_box::button_box(int X, int Y, int ID, int MaxDown, button *Buttons, ifield *Next)
50 {
51 x=X; y=Y; id=ID; next=Next;
52 buttons=Buttons;
53 maxdown=MaxDown;
54 if (buttons && maxdown) buttons->push(); // the first button is automatically selected!
55 }
56
~button_box()57 button_box::~button_box()
58 {
59 while (buttons)
60 {
61 button *b=buttons;
62 buttons=(button *)buttons->next;
63 delete b;
64 }
65 }
66
area(int & x1,int & y1,int & x2,int & y2)67 void button_box::area(int &x1, int &y1, int &x2, int &y2)
68 {
69 button *b=buttons;
70 if (!b) return ;
71 else
72 {
73 b->area(x1,y1,x2,y2);
74 int xp1,yp1,xp2,yp2;
75 for (b=(button *)b->next; b; b=(button *)b->next)
76 {
77 b->area(xp1,yp1,xp2,yp2);
78 if (xp1<x1) x1=xp1;
79 if (xp2>x2) x2=xp2;
80 if (yp1<y1) y1=yp1;
81 if (yp2>y2) y2=yp2;
82 }
83 }
84 }
85
draw_first(image * screen)86 void button_box::draw_first(image *screen)
87 {
88 for (button *b=buttons; b; b=(button *)b->next)
89 b->draw_first(screen);
90 }
91
draw(int active,image * screen)92 void button_box::draw(int active, image *screen)
93 {
94 return ;
95 }
96
move(int newx,int newy)97 void button_box::move(int newx, int newy)
98 {
99 for(button * b = buttons; b; b = (button *)b->next)
100 b->move(newx + b->x, newy + b->y);
101 x = newx;
102 y = newy;
103 }
104
read()105 char *button_box::read()
106 {
107 for (button *b=buttons; b; b=(button *)b->next)
108 {
109 if (*((int *)b->read())==0)
110 return (char *)b;
111 }
112 return NULL;
113 }
114
handle_event(event & ev,image * screen,InputManager * im)115 void button_box::handle_event(event &ev, image *screen, InputManager *im)
116 {
117 switch (ev.type)
118 {
119 case EV_MOUSE_BUTTON :
120 {
121 int x1,y1,x2,y2;
122 int found=0;
123 for (button *b=buttons; !found && b; b=(button *)b->next) // see if the user clicked on a button
124 {
125 b->area(x1,y1,x2,y2);
126 if (ev.mouse_move.x>=x1 && ev.mouse_move.x<=x2 &&
127 ev.mouse_move.y>=y1 && ev.mouse_move.y<=y2)
128 {
129 b->handle_event(ev,screen,im);
130
131 int total=0;
132 button *b2=buttons;
133 for (; b2; b2=(button *)b2->next)
134 if (*((int *)b2->read())==0)
135 total++;
136
137 if (*((int *)b->read())==0) // did the user press or release the button
138 {
139 if (total>maxdown)
140 {
141 for (b2=buttons; total>maxdown && b2; b2=(button *)b2->next)
142 if ((b!=b2 || maxdown==0) && *((int *)b2->read())==0)
143 {
144 total--;
145 b2->push();
146 b2->draw_first(screen);
147 }
148 }
149 b->draw_first(screen);
150 } else if (total==0 && maxdown)
151 b->push(); // don't let the user de-press a button if non others are selected.
152
153 found=1; // don't look at anymore buttons
154
155 }
156 }
157 } break;
158 }
159 }
160
161
add_button(button * b)162 void button_box::add_button(button *b)
163 {
164 b->next=buttons;
165 buttons=b;
166 }
167
168
arrange_left_right()169 void button_box::arrange_left_right()
170 {
171 button *b=buttons;
172 int x_on=x,x1,y1,x2,y2;
173 for (; b; b=(button *)b->next)
174 {
175 b->area(x1,y1,x2,y2);
176 b->x=x_on;
177 b->y=y;
178 x_on+=(x2-x1+1)+1;
179 }
180 }
181
arrange_up_down()182 void button_box::arrange_up_down()
183 {
184 button *b=buttons;
185 int y_on=y,x1,y1,x2,y2;
186 for (; b; b=(button *)b->next)
187 {
188 b->area(x1,y1,x2,y2);
189 b->y=y_on;
190 b->x=x;
191 y_on+=(y2-y1+1)+1;
192 }
193 }
194
change_visual(image * new_visual)195 void button::change_visual(image *new_visual)
196 {
197 CHECK(visual);
198 visual=new_visual;
199 }
200
area(int & x1,int & y1,int & x2,int & y2)201 void button::area(int &x1, int &y1, int &x2, int &y2)
202 {
203 x1=x; y1=y;
204 if (pressed)
205 {
206 x2=x+pressed->Size().x-1;
207 y2=y+pressed->Size().y-1;
208 }
209 else
210 {
211 if (text)
212 {
213 x2=x+wm->font()->width()*strlen(text)+6;
214 y2=y+wm->font()->height()+6;
215 } else
216 {
217 x2=x+6+visual->Size().x;
218 y2=y+6+visual->Size().y;
219 }
220 }
221 }
222
223
button(int X,int Y,int ID,char const * Text,ifield * Next)224 button::button(int X, int Y, int ID, char const *Text, ifield *Next)
225 {
226 x=X; y=Y; id=ID;
227 act_id=-1;
228 text = strdup(Text);
229 up=1; next=Next; act=0;
230 visual=NULL;
231 pressed=NULL;
232 }
233
234
button(int X,int Y,int ID,image * vis,ifield * Next)235 button::button(int X, int Y, int ID, image *vis, ifield *Next)
236 { x=X; y=Y; id=ID; text=NULL;
237 act_id=-1;
238 visual=vis; up=1; next=Next; act=0;
239 pressed=NULL;
240 }
241
button(int X,int Y,int ID,image * Depressed,image * Pressed,image * active,ifield * Next)242 button::button(int X, int Y, int ID, image *Depressed, image *Pressed, image *active, ifield *Next)
243 { x=X; y=Y; id=ID; text=NULL;
244 act_id=-1;
245 visual=Depressed; up=1; next=Next; act=0;
246 pressed=Pressed;
247 act_pict=active;
248 }
249
250
change_data(char const * new_data,int new_cursor,int active,image * screen)251 void text_field::change_data(char const *new_data, int new_cursor, // cursor==-1, does not change it.
252 int active, image *screen)
253 {
254 if (strlen(format)<strlen(new_data))
255 data=(char *)realloc(data,strlen(new_data));
256
257 strcpy(data,new_data);
258 if (new_cursor!=-1)
259 cur=new_cursor;
260 draw_first(screen);
261 draw(active,screen);
262 }
263
read()264 char *text_field::read()
265 {
266 while (*data && data[strlen(data)-1]==' ') data[strlen(data)-1]=0;
267 return data;
268 }
269
handle_event(event & ev,image * screen,InputManager * im)270 void text_field::handle_event(event &ev, image *screen, InputManager *im)
271 {
272 int xx;
273 if (ev.type==EV_KEY)
274 {
275 switch (ev.key)
276 {
277 case JK_LEFT : if (cur) { draw_cur(wm->dark_color(),screen); cur--;
278 draw_cur(wm->bright_color(),screen); } break;
279 case JK_RIGHT : if (cur<(int)strlen(format)-1) { draw_cur(wm->dark_color(),screen); cur++;
280 draw_cur(wm->bright_color(),screen); } break;
281 case JK_END : if (cur!=last_spot())
282 { draw_cur(wm->dark_color(),screen); cur=last_spot();
283 if (cur==(int)strlen(format)-1) cur--;
284 draw_cur(wm->bright_color(),screen); } break;
285 case JK_HOME : if (cur)
286 { draw_cur(wm->dark_color(),screen); cur=0;
287 draw_cur(wm->bright_color(),screen); } break;
288 case JK_BACKSPACE : if (cur)
289 { draw_cur(wm->dark_color(),screen); cur--;
290 for (xx=cur; xx<(int)strlen(format)-1; xx++)
291 data[xx]=data[xx+1];
292 data[strlen(format)-1]=' ';
293 draw_text(screen);
294 draw_cur(wm->bright_color(),screen);
295 wm->push_event(new event(id,(char *)this));
296 } break;
297 default : if (ev.key>=' ' && ev.key<='~')
298 {
299 draw_cur(wm->dark_color(),screen);
300 for (xx=strlen(format)-1; xx>cur && xx>0; xx--)
301 data[xx]=data[xx-1];
302 data[cur]=ev.key;
303 if (cur<(int)strlen(format)-1)
304 cur++;
305 data[strlen(format)]=0;
306 draw_text(screen);
307 draw_cur(wm->bright_color(),screen);
308 wm->push_event(new event(id,(char *)this));
309 } break;
310 }
311 }
312 }
313
draw(int active,image * screen)314 void text_field::draw(int active, image *screen)
315 {
316 if (active)
317 {
318 screen->rectangle(xstart(),y,xend(),yend(),wm->bright_color());
319 draw_cur(wm->bright_color(),screen);
320 }
321 else
322 {
323 screen->rectangle(xstart(),y,xend(),yend(),wm->dark_color());
324 draw_cur(wm->dark_color(),screen);
325 }
326 }
327
area(int & x1,int & y1,int & x2,int & y2)328 void text_field::area(int &x1, int &y1, int &x2, int &y2)
329 {
330 x1=x; y1=y;
331 x2=xend();
332 y2=yend();
333 }
334
text_field(int X,int Y,int ID,char const * Prompt,char const * Format,char const * Data,ifield * Next)335 text_field::text_field(int X, int Y, int ID, char const *Prompt,
336 char const *Format, char const *Data, ifield *Next)
337 {
338 int slen=(strlen(Format)>strlen(Data) ? strlen(Format) : strlen(Data));
339
340 x=X; y=Y; id=ID;
341 prompt = strdup(Prompt);
342 format=strcpy((char *)malloc(slen+1),Format);
343 data=strcpy((char *)malloc(slen+1),Data);
344 cur=strlen(data);
345 while (cur && data[cur-1]==' ') cur--;
346 next=Next;
347 }
348
text_field(int X,int Y,int ID,char const * Prompt,char const * Format,double Data,ifield * Next)349 text_field::text_field(int X, int Y, int ID, char const *Prompt,
350 char const *Format, double Data, ifield *Next)
351 {
352 char num[20];
353 sprintf(num,"%g",Data);
354 int slen=(strlen(Format)>strlen(num) ? strlen(Format) : strlen(num));
355 x=X; y=Y; id=ID;
356 prompt = strdup(Prompt);
357 format=strcpy((char *)malloc(slen+1),Format);
358 data=strcpy((char *)malloc(slen+1),num);
359 cur=strlen(num);
360 while (cur && data[cur-1]==' ') cur--;
361 next=Next;
362 }
363
364
push()365 void button::push()
366 { up=!up; }
367
handle_event(event & ev,image * screen,InputManager * im)368 void button::handle_event(event &ev, image *screen, InputManager *im)
369 {
370 if ((ev.type==EV_KEY && ev.key==13) || (ev.type==EV_MOUSE_BUTTON &&
371 ev.mouse_button))
372 {
373 int x1,y1,x2,y2;
374 area(x1,y1,x2,y2);
375 up=!up;
376 draw_first(screen);
377 draw(act,screen);
378 wm->push_event(new event(id,(char *)this));
379 }
380 }
381
draw(int active,image * screen)382 void button::draw(int active, image *screen)
383 {
384 int x1,y1,x2,y2,color=(active ? wm->bright_color() : wm->medium_color());
385 area(x1,y1,x2,y2);
386 if (active!=act && act_id!=-1 && active)
387 wm->push_event(new event(act_id,NULL));
388
389 if (pressed)
390 {
391 if (up)
392 {
393 if (!active)
394 visual->put_image(screen,x,y);
395 else
396 pressed->put_image(screen,x,y);
397 } else act_pict->put_image(screen,x,y);
398 }
399 else
400 {
401 screen->rectangle(x1+2,y1+2,x2-2,y2-2,color);
402 act=active;
403 }
404 }
405
draw_first(image * screen)406 void button::draw_first(image *screen)
407 {
408 if (pressed)
409 draw(0,screen);
410 else
411 {
412
413 int x1,y1,x2,y2;
414 area(x1,y1,x2,y2);
415
416
417 if (up)
418 {
419 screen->rectangle(x1,y1,x2,y2,wm->black());
420 // screen->widget_bar(,wm->bright_color(),wm->medium_color(),wm->dark_color());
421 screen->widget_bar(x1+1,y1+1,x2-1,y2-1,wm->bright_color(),wm->medium_color(),wm->dark_color());
422 if (text)
423 {
424 wm->font()->put_string(screen,x+4,y+5,text,wm->black());
425 wm->font()->put_string(screen,x+3,y+4,text);
426 }
427 else visual->put_image(screen,x+3,y+3,1);
428 } else
429 {
430 screen->line(x1,y1,x2,y1,wm->dark_color());
431 screen->line(x1,y1,x1,y2,wm->dark_color());
432 screen->line(x2,y1+1,x2,y2,wm->bright_color());
433 screen->line(x1+1,y2,x2,y2,wm->bright_color());
434 screen->bar(x1+1,y1+1,x2-1,y2-1,wm->medium_color());
435 if (visual)
436 visual->put_image(screen,x1+3,y1+3,1);
437 else
438 {
439 wm->font()->put_string(screen,x+4,y+5,text,wm->black());
440 wm->font()->put_string(screen,x+3,y+4,text);
441 }
442 }
443 }
444 }
445
draw_first(image * screen)446 void text_field::draw_first(image *screen)
447 {
448 wm->font()->put_string(screen,x,y+3,prompt);
449 screen->bar(xstart(),y,xend(),yend(),wm->dark_color());
450 wm->font()->put_string(screen,xstart()+1,y+3,data);
451 }
452
453
draw_cur(int color,image * screen)454 void text_field::draw_cur(int color, image *screen)
455 {
456 screen->bar(xstart()+cur*wm->font()->width()+1,
457 yend()-2,
458 xstart()+(cur+1)*wm->font()->width(),
459 yend()-1,color);
460 }
461
462
463
info_field(int X,int Y,int ID,char const * info,ifield * Next)464 info_field::info_field(int X, int Y, int ID, char const *info, ifield *Next)
465 {
466 x = X; y = Y; id = ID; next = Next;
467 text = strdup(info);
468 w = -1;
469 }
470
471
area(int & x1,int & y1,int & x2,int & y2)472 void info_field::area(int &x1, int &y1, int &x2, int &y2)
473 {
474 if (w==-1) // if we haven't calculated this yet
475 {
476 int fw=wm->font()->width(),fh=wm->font()->height(),maxw=0;
477 char *info=text;
478 for (w=fw,h=fh+1; *info; info++)
479 {
480 if (w>maxw) maxw=w;
481 if (*info=='\n')
482 {
483 h+=fh+1;
484 w=1;
485 }
486 else w+=fw;
487 }
488 w=maxw;
489 }
490 x1=x;
491 y1=y;
492 x2=x+w;
493 y2=y+h;
494 }
495
put_para(image * screen,char const * st,int dx,int dy,int xspace,int yspace,JCFont * font,int color)496 void info_field::put_para(image *screen, char const *st, int dx, int dy,
497 int xspace, int yspace, JCFont *font, int color)
498 {
499 int ox=dx;
500 while (*st)
501 {
502 if (*st=='\n')
503 {
504 dx=ox;
505 dy+=yspace;
506 }
507 else
508 {
509 font->put_char(screen,dx,dy,*st,color);
510 dx+=xspace;
511 }
512 st++;
513 }
514 }
515
draw_first(image * screen)516 void info_field::draw_first(image *screen)
517 {
518 put_para(screen,text,x+1,y+1,wm->font()->width(),wm->font()->height(),wm->font(),wm->black());
519 put_para(screen,text,x,y,wm->font()->width(),wm->font()->height(),wm->font(),wm->bright_color());
520 }
521
522
523
524
525