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

Last change on this file since 524 was 524, checked in by Sam Hocevar, 9 years ago

core: Get rid of mostly useless headers, move endianness handling to
common.h (and rewrite functions so that they do not need the SDL headers)
and move a few functions out of sdlport's video.cpp. These functions
were in the original video.cpp (which reappears) and shouldn't be part
of the SDL port.

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