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

Last change on this file since 659 was 659, checked in by Sam Hocevar, 11 years ago

imlib: rename Jwindow's x and y members to m_pos.

File size: 12.5 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  m_pos = vec2i(X, 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(vec2i pos)
98{
99    for(button * b = buttons; b; b = (button *)b->next)
100        b->Move(pos + b->m_pos);
101    m_pos = pos;
102}
103
104char *button_box::read()
105{
106  for (button *b=buttons; b; b=(button *)b->next)
107  {
108    if (*((int *)b->read())==0)
109      return (char *)b;
110  }
111  return NULL;
112}
113
114void button_box::handle_event(Event &ev, image *screen, InputManager *im)
115{
116  switch (ev.type)
117  {
118    case EV_MOUSE_BUTTON :
119    {
120      int x1,y1,x2,y2;
121      int found=0;
122      for (button *b=buttons; !found && b; b=(button *)b->next)  // see if the user clicked on a button
123      {
124    b->area(x1,y1,x2,y2);
125    if (ev.mouse_move.x>=x1 && ev.mouse_move.x<=x2 &&
126        ev.mouse_move.y>=y1 && ev.mouse_move.y<=y2)
127    {
128      b->handle_event(ev,screen,im);
129
130      int total=0;
131      button *b2=buttons;
132      for (; b2; b2=(button *)b2->next)
133        if (*((int *)b2->read())==0)
134          total++;
135
136      if (*((int *)b->read())==0)  // did the user press or release the button
137      {
138        if (total>maxdown)
139        {
140          for (b2=buttons; total>maxdown && b2; b2=(button *)b2->next)
141            if ((b!=b2 || maxdown==0) && *((int *)b2->read())==0)
142        {
143          total--;
144          b2->push();
145          b2->draw_first(screen);
146        }
147        }
148        b->draw_first(screen);
149      } else if (total==0 && maxdown)
150        b->push();    // don't let the user de-press a button if non others are selected.
151
152      found=1; // don't look at anymore buttons
153
154    }
155      }
156    } break;
157  }
158}
159
160
161void button_box::add_button(button *b)
162{
163  b->next=buttons;
164  buttons=b;
165}
166
167
168void button_box::arrange_left_right()
169{
170    vec2i on = m_pos;
171    for (button *b = buttons; b; b = (button *)b->next)
172    {
173        int x1, y1, x2, y2;
174        b->area(x1, y1, x2, y2);
175        b->m_pos = on;
176        on.x += (x2 - x1 + 1) + 1;
177    }
178}
179
180void button_box::arrange_up_down()
181{
182    vec2i on = m_pos;
183    for (button *b = buttons; b; b = (button *)b->next)
184    {
185        int x1, y1, x2, y2;
186        b->area(x1,y1,x2,y2);
187        b->m_pos = on;
188        on.y += (y2 - y1 + 1) + 1;
189    }
190}
191
192void button::change_visual(image *new_visual)
193{
194  CHECK(visual);
195  visual=new_visual;
196}
197
198void button::area(int &x1, int &y1, int &x2, int &y2)
199{
200    vec2i pos1 = m_pos;
201    vec2i pos2 = m_pos;
202
203    if (pressed)
204        pos2 += pressed->Size() - vec2i(1, 1);
205    else if (text)
206        pos2 += vec2i(wm->font()->width() * strlen(text) + 6,
207                      wm->font()->height() + 6);
208    else
209        pos2 += visual->Size() + vec2i(6, 6);
210
211    x1 = pos1.x; y1 = pos1.y;
212    x2 = pos2.x; y2 = pos2.y;
213}
214
215
216button::button(int X, int Y, int ID, char const *Text, ifield *Next)
217{
218    m_pos = vec2i(X, Y);
219    id = ID;
220    act_id=-1;
221    text = strdup(Text);
222    up=1; next=Next; act=0;
223    visual=NULL;
224    pressed=NULL;
225}
226
227
228button::button(int X, int Y, int ID, image *vis, ifield *Next)
229{
230    m_pos = vec2i(X, Y);
231    id=ID; text=NULL;
232    act_id=-1;
233    visual=vis; up=1; next=Next; act=0;
234    pressed=NULL;
235}
236
237button::button(int X, int Y, int ID, image *Depressed, image *Pressed, image *active, ifield *Next)
238{
239    m_pos = vec2i(X, Y);
240    id=ID; text=NULL;
241    act_id=-1;
242    visual=Depressed; up=1; next=Next; act=0;
243    pressed=Pressed;
244    act_pict=active;
245}
246
247
248void text_field::change_data(char const *new_data, int new_cursor, // cursor==-1, does not change it.
249                 int active, image *screen)
250{
251  if (strlen(format)<strlen(new_data))
252    data=(char *)realloc(data,strlen(new_data));
253
254  strcpy(data,new_data);
255  if (new_cursor!=-1)
256    cur=new_cursor;
257  draw_first(screen);
258  draw(active,screen);
259}
260
261char *text_field::read()
262{
263  while (*data && data[strlen(data)-1]==' ') data[strlen(data)-1]=0;
264  return data;
265}
266
267void text_field::handle_event(Event &ev, image *screen, InputManager *im)
268{
269  int xx;
270  if (ev.type==EV_KEY)
271  {
272    switch (ev.key)
273    {
274      case JK_LEFT : if (cur) { draw_cur(wm->dark_color(),screen); cur--;
275                           draw_cur(wm->bright_color(),screen); } break;
276      case JK_RIGHT : if (cur<(int)strlen(format)-1) { draw_cur(wm->dark_color(),screen); cur++;
277                           draw_cur(wm->bright_color(),screen); } break;
278      case JK_END : if (cur!=last_spot())
279                          { draw_cur(wm->dark_color(),screen); cur=last_spot();
280                            if (cur==(int)strlen(format)-1) cur--;
281                           draw_cur(wm->bright_color(),screen); } break;
282      case JK_HOME : if (cur)
283                          { draw_cur(wm->dark_color(),screen); cur=0;
284                           draw_cur(wm->bright_color(),screen); } break;
285      case JK_BACKSPACE : if (cur)
286         { draw_cur(wm->dark_color(),screen); cur--;
287           for (xx=cur; xx<(int)strlen(format)-1; xx++)
288             data[xx]=data[xx+1];
289           data[strlen(format)-1]=' ';
290           draw_text(screen);
291           draw_cur(wm->bright_color(),screen);
292           wm->Push(new Event(id,(char *)this));
293         } break;
294      default : if (ev.key>=' ' && ev.key<='~')
295         {
296           draw_cur(wm->dark_color(),screen);
297           for (xx=strlen(format)-1; xx>cur && xx>0; xx--)
298             data[xx]=data[xx-1];
299           data[cur]=ev.key;
300           if (cur<(int)strlen(format)-1)
301             cur++;
302       data[strlen(format)]=0;
303           draw_text(screen);
304           draw_cur(wm->bright_color(),screen);
305           wm->Push(new Event(id,(char *)this));
306         } break;
307    }
308  }
309}
310
311void text_field::draw(int active, image *screen)
312{
313  if (active)
314  {
315    screen->Rectangle(vec2i(xstart(), m_pos.y), vec2i(xend(), yend()),
316                      wm->bright_color());
317    draw_cur(wm->bright_color(),screen);
318  }
319  else
320  {
321    screen->Rectangle(vec2i(xstart(), m_pos.y), vec2i(xend(), yend()),
322                      wm->dark_color());
323    draw_cur(wm->dark_color(),screen);
324  }
325}
326
327void text_field::area(int &x1, int &y1, int &x2, int &y2)
328{
329    x1 = m_pos.x; y1 = m_pos.y;
330    x2 = xend(); y2 = yend();
331}
332
333text_field::text_field(int X, int Y, int ID, char const *Prompt,
334                       char const *Format, char const *Data, ifield *Next)
335{
336    int slen=(strlen(Format)>strlen(Data) ? strlen(Format) : strlen(Data));
337
338    m_pos = vec2i(X, Y);
339    id=ID;
340    prompt = strdup(Prompt);
341    format=strcpy((char *)malloc(slen+1),Format);
342    data=strcpy((char *)malloc(slen+1),Data);
343    cur=strlen(data);
344    while (cur && data[cur-1]==' ') cur--;
345    next=Next;
346}
347
348text_field::text_field(int X, int Y, int ID, char const *Prompt,
349                       char const *Format, double Data, ifield *Next)
350{
351  char num[20];
352  sprintf(num,"%g",Data);
353  int slen=(strlen(Format)>strlen(num) ? strlen(Format) : strlen(num));
354  m_pos = vec2i(X, Y); id=ID;
355  prompt = strdup(Prompt);
356  format=strcpy((char *)malloc(slen+1),Format);
357  data=strcpy((char *)malloc(slen+1),num);
358  cur=strlen(num);
359  while (cur && data[cur-1]==' ') cur--;
360  next=Next;
361}
362
363
364void button::push()
365{ up=!up; }
366
367void button::handle_event(Event &ev, image *screen, InputManager *im)
368{
369  if ((ev.type==EV_KEY && ev.key==13) || (ev.type==EV_MOUSE_BUTTON &&
370                                         ev.mouse_button))
371  {
372    int  x1,y1,x2,y2;
373    area(x1,y1,x2,y2);
374    up=!up;
375    draw_first(screen);
376    draw(act,screen);
377    wm->Push(new Event(id,(char *)this));
378  }
379}
380
381void button::draw(int active, image *screen)
382{
383  int x1,y1,x2,y2,color=(active ? wm->bright_color() : wm->medium_color());
384  area(x1,y1,x2,y2);
385  if (active!=act  && act_id!=-1 && active)
386    wm->Push(new Event(act_id,NULL));
387
388  if (pressed)
389  {
390    if (up)
391    {
392      if (!active)
393        screen->PutImage(visual, m_pos);
394      else
395        screen->PutImage(pressed, m_pos);
396    } else screen->PutImage(act_pict, m_pos);
397  }
398  else
399  {
400    screen->Rectangle(vec2i(x1 + 2, y1 + 2), vec2i(x2 - 2, y2 - 2), color);
401    act = active;
402  }
403}
404
405void button::draw_first(image *screen)
406{
407  if (pressed)
408    draw(0,screen);
409  else
410  {
411
412    int x1,y1,x2,y2;
413    area(x1,y1,x2,y2);
414
415
416    if (up)
417    {
418      screen->Rectangle(vec2i(x1, y1), vec2i(x2, y2), wm->black());
419//      screen->widget_bar(,wm->bright_color(),wm->medium_color(),wm->dark_color());
420      screen->WidgetBar(vec2i(x1 + 1, y1 + 1), vec2i(x2 - 1, y2 - 1),
421                        wm->bright_color(),wm->medium_color(),wm->dark_color());
422      if (text)
423      {
424        wm->font()->put_string(screen,m_pos.x+4,m_pos.y+5,text,wm->black());
425        wm->font()->put_string(screen,m_pos.x+3,m_pos.y+4,text);
426      }
427      else screen->PutImage(visual, m_pos + vec2i(3, 3), 1);
428    } else
429    {
430      screen->Line(vec2i(x1, y1), vec2i(x2, y1), wm->dark_color());
431      screen->Line(vec2i(x1, y1), vec2i(x1, y2), wm->dark_color());
432      screen->Line(vec2i(x2, y1 + 1), vec2i(x2, y2), wm->bright_color());
433      screen->Line(vec2i(x1 + 1, y2), vec2i(x2, y2), wm->bright_color());
434      screen->Bar(vec2i(x1 + 1, y1 + 1), vec2i(x2 - 1, y2 - 1),
435                  wm->medium_color());
436      if (visual)
437        screen->PutImage(visual, vec2i(x1 + 3, y1 + 3), 1);
438      else
439      {
440        wm->font()->put_string(screen,m_pos.x+4,m_pos.y+5,text,wm->black());
441        wm->font()->put_string(screen,m_pos.x+3,m_pos.y+4,text);
442      }
443    }
444  }
445}
446
447void text_field::draw_first(image *screen)
448{
449  wm->font()->put_string(screen,m_pos.x,m_pos.y+3,prompt);
450  screen->Bar(vec2i(xstart(), m_pos.y), vec2i(xend(), yend()), wm->dark_color());
451  wm->font()->put_string(screen,xstart()+1,m_pos.y+3,data);
452}
453
454
455void text_field::draw_cur(int color, image *screen)
456{
457  screen->Bar(vec2i(xstart() + cur * wm->font()->width() + 1, yend() - 2),
458              vec2i(xstart() + (cur + 1) * wm->font()->width(), yend() - 1),
459              color);
460}
461
462
463
464info_field::info_field(int X, int Y, int ID, char const *info, ifield *Next)
465{
466  m_pos = vec2i(X, 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 = m_pos.x;
491  y1 = m_pos.y;
492  x2 = m_pos.x + w;
493  y2 = m_pos.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,m_pos.x+1,m_pos.y+1,wm->font()->width(),wm->font()->height(),wm->font(),wm->black());
519  put_para(screen,text,m_pos.x,m_pos.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.