source: abuse/trunk/src/imlib/input.cpp @ 579

Last change on this file since 579 was 579, checked in by Sam Hocevar, 8 years ago

imlib: refactor the Filter and ColorFilter? classes.

File size: 11.8 KB
Line 
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
21void button::remap(Filter *f)
22{
23  if (visual)
24  {
25    f->Apply(visual);
26    if (pressed)
27      f->Apply(pressed);
28  }
29}
30
31void button_box::press_button(int id)      // if button box doesn't contain id, nothing happens
32{
33}
34
35void button_box::remap(Filter *f)
36{
37  for (button *b=buttons; b; b=(button *)b->next)
38    b->remap(f);
39}
40
41ifield *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
49button_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
57button_box::~button_box()
58{
59  while (buttons)
60  {
61    button *b=buttons;
62    buttons=(button *)buttons->next;
63    delete b;
64  }
65}
66
67void 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
86void button_box::draw_first(image *screen)
87{
88  for (button *b=buttons; b; b=(button *)b->next)
89    b->draw_first(screen);
90}
91
92void button_box::draw(int active, image *screen)
93{
94  return ;
95}
96
97void 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
105char *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
115void 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
162void button_box::add_button(button *b)
163{
164  b->next=buttons;
165  buttons=b;
166}
167
168
169void 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
182void 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
195void button::change_visual(image *new_visual)
196{
197  CHECK(visual);
198  visual=new_visual;
199}
200
201void 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
224button::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
235button::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
242button::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
251void 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
264char *text_field::read()
265{
266  while (*data && data[strlen(data)-1]==' ') data[strlen(data)-1]=0;
267  return data;
268}
269
270void 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
314void 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
328void 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
335text_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
349text_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
365void button::push()
366{ up=!up; }
367
368void 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
382void 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
406void 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
446void 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
454void 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
464info_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
472void 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
496void 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
516void 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
Note: See TracBrowser for help on using the repository browser.