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

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

imlib: make JCFont use vec2i classes.

File size: 12.4 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);
205    else if (text)
206        pos2 += wm->font()->Size() * vec2i(strlen(text), 1) + vec2i(6);
207    else
208        pos2 += visual->Size() + vec2i(6);
209
210    x1 = pos1.x; y1 = pos1.y;
211    x2 = pos2.x; y2 = pos2.y;
212}
213
214
215button::button(int X, int Y, int ID, char const *Text, ifield *Next)
216{
217    m_pos = vec2i(X, Y);
218    id = ID;
219    act_id=-1;
220    text = strdup(Text);
221    up=1; next=Next; act=0;
222    visual=NULL;
223    pressed=NULL;
224}
225
226
227button::button(int X, int Y, int ID, image *vis, ifield *Next)
228{
229    m_pos = vec2i(X, Y);
230    id=ID; text=NULL;
231    act_id=-1;
232    visual=vis; up=1; next=Next; act=0;
233    pressed=NULL;
234}
235
236button::button(int X, int Y, int ID, image *Depressed, image *Pressed, image *active, ifield *Next)
237{
238    m_pos = vec2i(X, Y);
239    id=ID; text=NULL;
240    act_id=-1;
241    visual=Depressed; up=1; next=Next; act=0;
242    pressed=Pressed;
243    act_pict=active;
244}
245
246
247void text_field::change_data(char const *new_data, int new_cursor, // cursor==-1, does not change it.
248                 int active, image *screen)
249{
250  if (strlen(format)<strlen(new_data))
251    data=(char *)realloc(data,strlen(new_data));
252
253  strcpy(data,new_data);
254  if (new_cursor!=-1)
255    cur=new_cursor;
256  draw_first(screen);
257  draw(active,screen);
258}
259
260char *text_field::read()
261{
262  while (*data && data[strlen(data)-1]==' ') data[strlen(data)-1]=0;
263  return data;
264}
265
266void text_field::handle_event(Event &ev, image *screen, InputManager *im)
267{
268  int xx;
269  if (ev.type==EV_KEY)
270  {
271    switch (ev.key)
272    {
273      case JK_LEFT : if (cur) { draw_cur(wm->dark_color(),screen); cur--;
274                           draw_cur(wm->bright_color(),screen); } break;
275      case JK_RIGHT : if (cur<(int)strlen(format)-1) { draw_cur(wm->dark_color(),screen); cur++;
276                           draw_cur(wm->bright_color(),screen); } break;
277      case JK_END : if (cur!=last_spot())
278                          { draw_cur(wm->dark_color(),screen); cur=last_spot();
279                            if (cur==(int)strlen(format)-1) cur--;
280                           draw_cur(wm->bright_color(),screen); } break;
281      case JK_HOME : if (cur)
282                          { draw_cur(wm->dark_color(),screen); cur=0;
283                           draw_cur(wm->bright_color(),screen); } break;
284      case JK_BACKSPACE : if (cur)
285         { draw_cur(wm->dark_color(),screen); cur--;
286           for (xx=cur; xx<(int)strlen(format)-1; xx++)
287             data[xx]=data[xx+1];
288           data[strlen(format)-1]=' ';
289           draw_text(screen);
290           draw_cur(wm->bright_color(),screen);
291           wm->Push(new Event(id,(char *)this));
292         } break;
293      default : if (ev.key>=' ' && ev.key<='~')
294         {
295           draw_cur(wm->dark_color(),screen);
296           for (xx=strlen(format)-1; xx>cur && xx>0; xx--)
297             data[xx]=data[xx-1];
298           data[cur]=ev.key;
299           if (cur<(int)strlen(format)-1)
300             cur++;
301       data[strlen(format)]=0;
302           draw_text(screen);
303           draw_cur(wm->bright_color(),screen);
304           wm->Push(new Event(id,(char *)this));
305         } break;
306    }
307  }
308}
309
310void text_field::draw(int active, image *screen)
311{
312  if (active)
313  {
314    screen->Rectangle(vec2i(xstart(), m_pos.y), vec2i(xend(), yend()),
315                      wm->bright_color());
316    draw_cur(wm->bright_color(),screen);
317  }
318  else
319  {
320    screen->Rectangle(vec2i(xstart(), m_pos.y), vec2i(xend(), yend()),
321                      wm->dark_color());
322    draw_cur(wm->dark_color(),screen);
323  }
324}
325
326void text_field::area(int &x1, int &y1, int &x2, int &y2)
327{
328    x1 = m_pos.x; y1 = m_pos.y;
329    x2 = xend(); y2 = yend();
330}
331
332text_field::text_field(int X, int Y, int ID, char const *Prompt,
333                       char const *Format, char const *Data, ifield *Next)
334{
335    int slen=(strlen(Format)>strlen(Data) ? strlen(Format) : strlen(Data));
336
337    m_pos = vec2i(X, Y);
338    id=ID;
339    prompt = strdup(Prompt);
340    format=strcpy((char *)malloc(slen+1),Format);
341    data=strcpy((char *)malloc(slen+1),Data);
342    cur=strlen(data);
343    while (cur && data[cur-1]==' ') cur--;
344    next=Next;
345}
346
347text_field::text_field(int X, int Y, int ID, char const *Prompt,
348                       char const *Format, double Data, ifield *Next)
349{
350  char num[20];
351  sprintf(num,"%g",Data);
352  int slen=(strlen(Format)>strlen(num) ? strlen(Format) : strlen(num));
353  m_pos = vec2i(X, Y); id=ID;
354  prompt = strdup(Prompt);
355  format=strcpy((char *)malloc(slen+1),Format);
356  data=strcpy((char *)malloc(slen+1),num);
357  cur=strlen(num);
358  while (cur && data[cur-1]==' ') cur--;
359  next=Next;
360}
361
362
363void button::push()
364{ up=!up; }
365
366void button::handle_event(Event &ev, image *screen, InputManager *im)
367{
368  if ((ev.type==EV_KEY && ev.key==13) || (ev.type==EV_MOUSE_BUTTON &&
369                                         ev.mouse_button))
370  {
371    int  x1,y1,x2,y2;
372    area(x1,y1,x2,y2);
373    up=!up;
374    draw_first(screen);
375    draw(act,screen);
376    wm->Push(new Event(id,(char *)this));
377  }
378}
379
380void button::draw(int active, image *screen)
381{
382  int x1,y1,x2,y2,color=(active ? wm->bright_color() : wm->medium_color());
383  area(x1,y1,x2,y2);
384  if (active!=act  && act_id!=-1 && active)
385    wm->Push(new Event(act_id,NULL));
386
387  if (pressed)
388  {
389    if (up)
390    {
391      if (!active)
392        screen->PutImage(visual, m_pos);
393      else
394        screen->PutImage(pressed, m_pos);
395    } else screen->PutImage(act_pict, m_pos);
396  }
397  else
398  {
399    screen->Rectangle(vec2i(x1 + 2, y1 + 2), vec2i(x2 - 2, y2 - 2), color);
400    act = active;
401  }
402}
403
404void button::draw_first(image *screen)
405{
406    if (pressed)
407    {
408        draw(0, screen);
409        return;
410    }
411
412    int x1,y1,x2,y2;
413    area(x1,y1,x2,y2);
414
415    if (up)
416    {
417      screen->Rectangle(vec2i(x1, y1), vec2i(x2, y2), wm->black());
418//      screen->widget_bar(,wm->bright_color(),wm->medium_color(),wm->dark_color());
419      screen->WidgetBar(vec2i(x1 + 1, y1 + 1), vec2i(x2 - 1, y2 - 1),
420                        wm->bright_color(),wm->medium_color(),wm->dark_color());
421    }
422    else
423    {
424      screen->Line(vec2i(x1, y1), vec2i(x2, y1), wm->dark_color());
425      screen->Line(vec2i(x1, y1), vec2i(x1, y2), wm->dark_color());
426      screen->Line(vec2i(x2, y1 + 1), vec2i(x2, y2), wm->bright_color());
427      screen->Line(vec2i(x1 + 1, y2), vec2i(x2, y2), wm->bright_color());
428      screen->Bar(vec2i(x1 + 1, y1 + 1), vec2i(x2 - 1, y2 - 1),
429                  wm->medium_color());
430    }
431
432    if ((up && text) || (!up && !visual))
433    {
434        wm->font()->PutString(screen, m_pos + vec2i(4, 5), text, wm->black());
435        wm->font()->PutString(screen, m_pos + vec2i(3, 4), text);
436    }
437    else if (up)
438        screen->PutImage(visual, m_pos + vec2i(3, 3), 1);
439    else
440        screen->PutImage(visual, vec2i(x1 + 3, y1 + 3), 1);
441}
442
443void text_field::draw_first(image *screen)
444{
445  wm->font()->PutString(screen, m_pos + vec2i(0, 3), prompt);
446  screen->Bar(vec2i(xstart(), m_pos.y), vec2i(xend(), yend()), wm->dark_color());
447  wm->font()->PutString(screen, vec2i(xstart() + 1, m_pos.y + 3), data);
448}
449
450
451void text_field::draw_cur(int color, image *screen)
452{
453  screen->Bar(vec2i(xstart() + cur * wm->font()->Size().x + 1, yend() - 2),
454              vec2i(xstart() + (cur + 1) * wm->font()->Size().x, yend() - 1),
455              color);
456}
457
458
459
460info_field::info_field(int X, int Y, int ID, char const *info, ifield *Next)
461{
462  m_pos = vec2i(X, Y); id = ID; next = Next;
463  text = strdup(info);
464  w = -1;
465}
466
467
468void info_field::area(int &x1, int &y1, int &x2, int &y2)
469{
470  if (w==-1)     // if we haven't calculated this yet
471  {
472    int fw = wm->font()->Size().x, fh = wm->font()->Size().y, maxw = 0;
473    char *info=text;
474    for (w=fw,h=fh+1; *info; info++)
475    {
476      if (w>maxw) maxw=w;
477      if (*info=='\n')
478      {
479    h+=fh+1;
480    w=1;
481      }
482      else w+=fw;
483    }
484    w=maxw;
485  }
486  x1 = m_pos.x;
487  y1 = m_pos.y;
488  x2 = m_pos.x + w;
489  y2 = m_pos.y + h;
490}
491
492void info_field::put_para(image *screen, char const *st, int dx, int dy,
493              int xspace, int yspace, JCFont *font, int color)
494{
495  int ox=dx;
496  while (*st)
497  {
498    if (*st=='\n')
499    {
500      dx=ox;
501      dy+=yspace;
502    }
503    else
504    {
505      font->PutChar(screen, vec2i(dx, dy), *st, color);
506      dx+=xspace;
507    }
508    st++;
509  }
510}
511
512void info_field::draw_first(image *screen)
513{
514  put_para(screen, text, m_pos.x+1, m_pos.y+1, wm->font()->Size().x,
515           wm->font()->Size().y, wm->font(), wm->black());
516  put_para(screen, text, m_pos.x, m_pos.y, wm->font()->Size().x,
517           wm->font()->Size().y, wm->font(), wm->bright_color());
518}
519
Note: See TracBrowser for help on using the repository browser.