source: abuse/trunk/src/imlib/jwindow.cpp @ 481

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

Fuck the history, I'm renaming all .hpp files to .h for my own sanity.

File size: 17.8 KB
Line 
1/*
2 *  Abuse - dark 2D side-scrolling platform game
3 *  Copyright (c) 1995 Crack dot Com
4 *
5 *  This software was released into the Public Domain. As with most public
6 *  domain software, no warranty is made or implied by Crack dot Com or
7 *  Jonathan Clark.
8 */
9
10#include "config.h"
11
12#include <string.h>
13
14#include "video.h"
15#include "image.h"
16#include "input.h"
17#include "event.h"
18#include "filter.h"
19#include "event.h"
20#include "jwindow.h"
21
22static int jw_left = 3, jw_right = 3, jw_top = 2, jw_bottom = 3;
23
24int frame_top() { return jw_top; }
25int frame_bottom() { return jw_bottom; }
26int frame_left() { return jw_left; }
27int frame_right() { return jw_right; }
28
29//
30//  Sets the size of the border around each window
31//
32void set_frame_size(int x)
33{
34    if(x < 1)
35        x = 1;
36    jw_left = x;
37    jw_right = x;
38    jw_top = 2;
39    jw_bottom = x;
40}
41
42 // true if a window lies in this area
43int WindowManager::window_in_area(int x1, int y1, int x2, int y2)
44{
45  for (Jwindow *f=first;f;f=f->next)
46    if (f->x<=x2 && f->y<=y2 && f->x+f->l-1>=x1 && f->y+f->h-1>=y1)
47      return 1;
48  return 0;
49}
50
51void WindowManager::grab_focus(Jwindow *j)
52{ grab=j; }
53
54void WindowManager::release_focus()
55{ grab=NULL; }
56
57
58void WindowManager::close_window(Jwindow *j)
59{
60    delete j;
61}
62
63void WindowManager::hide_windows()
64{
65  Jwindow *p;
66  for (p=first;p;p=p->next)
67  {
68    if (!p->is_hidden())
69    {
70      p->hide();
71      screen->add_dirty(p->x,p->y,p->x+p->l-1,p->y+p->h-1);
72    }
73  }
74}
75
76void WindowManager::show_windows()
77{
78  Jwindow *p;
79  for (p=first;p;p=p->next)
80    if (p->is_hidden())
81      show_window(p);
82}
83
84void WindowManager::hide_window(Jwindow *j)
85{
86  Jwindow *k;
87  if (j==first)
88    first=first->next;
89  else
90  {
91    for (k=first;k->next!=j;k=k->next)
92      k->screen->add_dirty(j->x-k->x,j->y-k->y,
93                   j->x+j->l-1-k->x,j->y+j->h-1-k->y);
94    k->screen->add_dirty(j->x-k->x,j->y-k->y,
95                   j->x+j->l-1-k->x,j->y+j->h-1-k->y);
96    k->next=j->next;
97  }
98  screen->add_dirty(j->x,j->y,j->x+j->l-1,j->y+j->h-1);
99  j->hide();
100}
101
102void WindowManager::show_window(Jwindow *j)
103{
104  if (j->is_hidden())
105  {
106    j->show();
107    j->screen->add_dirty(0,0,j->l-1,j->h-1);
108  }
109}
110
111void WindowManager::get_event(event &ev)
112{
113  Jwindow *j;
114  eh->get_event(ev);
115  if (ev.type==EV_KEY)
116    key_state[ev.key]=1;
117  else if (ev.type==EV_KEYRELEASE)
118    key_state[ev.key]=0;
119
120  if (state==inputing)
121  {
122    for (ev.window=NULL,j=first;j;j=j->next)
123      if (!j->is_hidden() && ev.mouse_move.x>=j->x && ev.mouse_move.y>=j->y &&
124          ev.mouse_move.x<j->x+j->l && ev.mouse_move.y<j->y+j->h)
125        ev.window=j;
126
127    if (!ev.window && grab) ev.window=grab;
128
129    if (ev.window)
130    {
131      int closew=0,movew=0;
132
133      if ((ev.type==EV_MOUSE_BUTTON && ev.mouse_button==1 && ev.window &&
134       ev.mouse_move.x>=ev.window->x && ev.mouse_move.y>=ev.window->y &&
135       ev.mouse_move.x<ev.window->x+ev.window->l && ev.mouse_move.y<ev.window->y+ev.window->y1()))
136      {
137    if (ev.mouse_move.x-ev.window->x<11) closew=1;
138    else if (ev.window->is_moveable()) movew=1;
139      } else if (grab)
140        ev.window=grab;
141
142      if (ev.type==EV_KEY && ev.key==JK_ESC)
143        closew=1;
144
145
146
147      if (closew)
148        ev.type=EV_CLOSE_WINDOW;
149      else if (movew)
150      {   
151    int red=0;
152    if (ev.window==first)       // see if we need to raise the window
153    {
154      first=first->next;
155      if (first)
156        red=1;
157    }
158    else
159    {
160      Jwindow *last=first;
161      for (;last->next!=ev.window;last=last->next);
162      if (ev.window->next)
163        red=1;
164      last->next=ev.window->next;
165    }
166    if (!first)
167      first=ev.window;
168    else
169    {
170      Jwindow *last=first;
171      for (;last->next;last=last->next);
172      last->next=ev.window;
173    }
174    ev.window->next=NULL;
175    if (red)
176    {
177      Jwindow *j=ev.window;
178/*      screen->add_dirty(j->x,j->y,j->x+j->l-1,j->y+j->h-1);
179      for (p=first;p!=j;p=p->next)
180        p->screen->add_dirty(j->x-p->x,j->y-p->y,j->x+j->l-1-p->x,j->y+j->h-1-p->y);*/
181      j->screen->add_dirty(0,0,j->l-1,j->h-1);
182      flush_screen();
183    }
184
185        state=dragging;
186        drag_window=ev.window;
187        drag_mousex=ev.window->x-ev.mouse_move.x;
188        drag_mousey=ev.window->y-ev.mouse_move.y;
189        ev.type=EV_SPURIOUS;
190      } else if (ev.window)
191        ev.window->inm->handle_event(ev,ev.window);
192    }
193  } else if (state==dragging)
194  {
195    ev.window=drag_window;
196    if (ev.type==EV_MOUSE_BUTTON && ev.mouse_button==0)  // user released the mouse
197    {
198      state=inputing;
199      ev.type=EV_SPURIOUS;
200    } else if (ev.type==EV_MOUSE_MOVE)
201    {
202       move_window(drag_window,ev.mouse_move.x+drag_mousex,ev.mouse_move.y+drag_mousey);
203       flush_screen();
204       ev.type=EV_DRAG_WINDOW;
205       ev.window_position.x=ev.mouse_move.x+drag_mousex;
206       ev.window_position.y=ev.mouse_move.y+drag_mousey;
207    }
208  }
209  if (ev.type==EV_REDRAW)
210  {
211    for (j=first;j;j=j->next)
212       j->screen->add_dirty(ev.redraw.x1-j->x,ev.redraw.y1-j->y,
213             ev.redraw.x2-j->x,ev.redraw.y2-j->y);
214    screen->add_dirty(ev.redraw.x1,ev.redraw.y1,ev.redraw.x2,ev.redraw.y2);
215    flush_screen();
216    ev.type=EV_SPURIOUS;   // we took care of this one by ourselves.
217  }
218}
219
220void Jwindow::resize(int L, int H)
221{
222  screen->change_size(L,H);
223  l=L; h=H;
224}
225
226void WindowManager::resize_window(Jwindow *j, int l, int h)
227{
228  Jwindow *p;
229  screen->add_dirty(j->x,j->y,j->x+j->l-1,j->y+j->h-1);
230  for (p=first;p!=j;p=p->next)
231    p->screen->add_dirty(j->x-p->x,j->y-p->y,j->x+j->l-1-p->x,j->y+j->h-1-p->y);
232  j->resize(l,h);
233  if (!frame_suppress)
234  j->redraw();
235}
236
237void WindowManager::move_window(Jwindow *j, int x, int y)
238{
239    screen->add_dirty(j->x, j->y, j->x + j->l - 1, j->y + j->h - 1);
240    for(Jwindow *p = first; p != j; p = p->next)
241        p->screen->add_dirty(j->x - p->x, j->y - p->y, j->x + j->l - 1 - p->x,
242                             j->y + j->h - 1 - p->y);
243    j->x = x;
244    j->y = y;
245    j->screen->add_dirty(0, 0, j->l - 1, j->h - 1);
246}
247
248WindowManager::WindowManager(image *Screen, palette *Pal, int Hi,
249                             int Med, int Low, JCFont *Font)
250{
251    wm = this;
252    screen = Screen;
253    hi = Hi; low = Low; med = Med; first = NULL; pal = Pal; grab = NULL;
254    bk = pal->find_closest(0, 0, 0);
255    state = inputing; fnt = Font;  wframe_fnt = Font;
256    memset(key_state, 0, sizeof(key_state));
257    eh = new event_handler(screen, pal);
258    frame_suppress = 0;
259}
260
261WindowManager::~WindowManager()
262{
263    delete eh;
264    while(first)
265        close_window(first);
266    wm = NULL;
267}
268
269void WindowManager::add_window(Jwindow *win)
270{
271    if(!first)
272        first = win;
273    else
274    {
275        Jwindow *tmp = first;
276        while(tmp->next)
277            tmp = tmp->next;
278        tmp->next = win;
279        win->next = NULL;
280    }
281}
282
283void WindowManager::remove_window(Jwindow *win)
284{
285    if(grab == win)
286        grab = NULL;
287
288    // close the window we were dragging
289    if(state == dragging && win == drag_window)
290        state = inputing;
291
292    if(first == win)
293        first = first->next;
294    else
295    {
296        Jwindow * search;
297        for(search = first; search->next != win; search = search->next)
298            search->screen->add_dirty(win->x - search->x,
299                                      win->y - search->y,
300                                      win->x + win->l - 1 - search->x,
301                                      win->y + win->h - 1 - search->y);
302        search->screen->add_dirty(win->x - search->x, win->y - search->y,
303                                  win->x + win->l - 1 - search->x,
304                                  win->y + win->h - 1 - search->y);
305        search->next = win->next;
306    }
307
308    screen->add_dirty(win->x, win->y, win->x + win->l - 1,
309                      win->y + win->h - 1);
310}
311
312Jwindow * WindowManager::new_window(int x, int y, int l, int h,
313                                     ifield * fields, char const *name)
314{
315    if(x > screen->width () - 4)
316        x = screen->width () - 25;
317    if(y > screen->height () - 4)
318        y = screen->height () - 10;
319
320    Jwindow * j = new Jwindow (x, y, l, h, fields, name);
321    j->show();
322
323    return j;
324}
325
326void WindowManager::flush_screen()
327{
328    Jwindow *p, *q;
329
330    int mx = 0, my = 0;
331    image *mouse_pic = NULL, *mouse_save = NULL;
332
333    if(has_mouse())
334    {
335        mouse_pic = eh->mouse_sprite()->visual;
336        mouse_save = eh->mouse_sprite()->save;
337        mx = eh->mouse->drawx();
338        my = eh->mouse->drawy();
339
340        screen->put_part(mouse_save, 0, 0, mx, my,
341                         mx + mouse_pic->width() - 1,
342                         my + mouse_pic->height() - 1);
343        mouse_pic->put_image(screen, mx, my, 1);
344    }
345
346    for(p = first; p; p = p->next)
347        if(!p->is_hidden())
348            screen->delete_dirty(p->x, p->y, p->x + p->l - 1, p->y + p->h - 1);
349    update_dirty(screen);
350
351    if(has_mouse())
352        mouse_save->put_image(screen, mx, my);
353
354    for(p = first; p; p = p->next)
355    {
356        if(p->is_hidden())
357            continue;
358
359        if(has_mouse())
360        {
361            p->screen->put_part(mouse_save, 0, 0, mx - p->x, my - p->y,
362                                mx - p->x + mouse_pic->width() - 1,
363                                my - p->y + mouse_pic->height() - 1);
364            if(has_mouse())
365                mouse_pic->put_image(p->screen, mx - p->x, my - p->y, 1);
366        }
367
368//          screen->delete_dirty(p->x, p->y, p->x+p->l-1, p->y+p->h-1);
369        for(q = p->next; q; q = q->next)
370            if(!q->is_hidden())
371                p->screen->delete_dirty(q->x - p->x, q->y - p->y,
372                                        q->x + q->l - 1 - p->x,
373                                        q->y + q->h - 1 - p->y);
374        update_dirty(p->screen, p->x, p->y);
375        if(has_mouse())
376            mouse_save->put_image(p->screen, mx - p->x, my - p->y, 0);
377    }
378}
379
380Jwindow::Jwindow(char const *name)
381{
382    _x1 = left_border();
383    _y1 = jw_top + 5;
384    _x2 = _y2 = 0;
385
386    _hidden = true;
387    _moveable = true;
388    // property.flags = JWINDOW_NOAUTOHIDE_FLAG;
389
390    inm = new InputManager(this, NULL);
391    reconfigure();
392
393    screen = NULL;
394    next = NULL;
395
396    _name = NULL;
397    if(name)
398        _name = strdup(name);
399    wm->add_window(this);
400}
401
402Jwindow::Jwindow(int X, int Y, int L, int H, ifield *f, char const *name)
403{
404    l = 0;
405    h = 0;
406    _hidden = false;
407    _moveable = true;
408
409    _x1 = left_border();
410    _y1 = name ? top_border() : jw_top + 5;
411
412    screen = NULL;
413    inm = new InputManager(screen, f);
414    reconfigure(); /* FIXME: TODO */
415
416    l = L >= 0 ? L + left_border() : l - L;
417    h = H >= 0 ? H + top_border() : h - H;
418    y = Y >= 0 ? Y : yres - h + Y - top_border() - bottom_border() - 1;
419    x = X >= 0 ? X : xres - l + X - left_border() - right_border() - 1;
420
421    backg = wm->medium_color();
422
423    _x2 = l - 1;
424    _y2 = h - 1;
425    l += right_border();
426    h += bottom_border();
427
428    if(L == -1)
429        if(l < 15 + left_border() + right_border())
430            l = 15 + left_border() + right_border();
431    if(H == -1)
432        if(h < top_border() + bottom_border())
433            h = top_border() + bottom_border();
434    screen = new image(l, h, NULL, 2);
435    screen->clear(backg);
436    // Keep this from getting destroyed when image list is cleared
437    image_list.unlink(screen);
438    inm->screen = screen;
439
440    next = NULL;
441
442    _name = NULL;
443    if(name)
444        _name = strdup(name);
445
446    wm->add_window(this);
447    if(!wm->frame_suppress)
448        redraw();
449}
450
451Jwindow::~Jwindow()
452{
453    wm->remove_window(this);
454    local_close();
455    if(screen)
456        delete screen;
457    delete inm;
458    if(_name)
459        free(_name);
460}
461
462void Jwindow::reconfigure()
463{
464    int x1, y1, x2, y2;
465    ifield *i;
466    l = 2;
467    h = 2;
468    for(i = inm->first; i; i = i->next)
469    {
470        i->set_owner(this);
471        i->area(x1, y1, x2, y2);
472        if ((int)y2 > (int)h)
473            h = y2;
474        if ((int)x2 > (int)l)
475            l = x2;
476    }
477}
478
479void Jwindow::local_close()
480{
481    ;
482}
483
484void Jwindow::redraw()
485{
486    int hi = wm->bright_color ();
487    int med = wm->medium_color ();
488    int low = wm->dark_color ();
489    JCFont * fnt = wm->frame_font ();
490
491    if(_name)
492    {
493        if (right_border() >= 1)
494        {
495            screen->widget_bar (0, 0, l - 1, h - 1, hi, med, low);
496            if (right_border() >= 3)
497                screen->widget_bar (right_border() - 1, top_border() - 1,
498                                l - left_border(), h - bottom_border(), low,
499                                med, hi);
500
501          else
502            screen->line (left_border() - 1, top_border() - 1,
503                           right_border() - 1, top_border() - 1, low);
504        }
505      screen->rectangle (2, 2, top_border() - 2, top_border() - 3,
506                           wm->black ());
507      screen->widget_bar (3, 3, top_border() - 3, top_border() - 4, hi, med, low);     // draws the 'close' button
508    }
509
510  else
511    {
512      if (right_border() >= 1)
513        {
514          screen->widget_bar (0, 0, l - 1, h - 1, hi, med, low);
515          if (right_border() >= 3)
516            screen->widget_bar (right_border() - 1, jw_top + 4,
517                                l - left_border(), h - bottom_border(), low,
518                                med, hi);
519
520          else
521            screen->line (left_border() - 1, jw_top + 4, right_border() - 1,
522                           jw_top + 4, low);
523        }
524      screen->rectangle (1, 1, 4, 4, wm->black ());
525      screen->widget_bar (2, 2, 3, 3, hi, med, low);   // draws the 'close' button
526    }
527  if (_name && _name[0])
528    {
529      screen->bar (top_border(), 1,
530                    top_border() + fnt->width () * strlen (_name) + 1,
531                    top_border() - 2, med);
532      fnt->put_string (screen, top_border() + 1, 1, _name, low);
533    }
534  screen->bar (x1 (), y1 (), x2 (), y2 (), backg);  // clear 'client' region
535  inm->redraw ();
536}
537
538int Jwindow::left_border()
539{
540    return frame_left();
541}
542
543int Jwindow::right_border()
544{
545    return frame_right();
546}
547
548int Jwindow::top_border()
549{
550    return wm->font()->height() + frame_top();
551}
552
553int Jwindow::bottom_border()
554{
555    return frame_bottom();
556}
557
558
559ifield *InputManager::unlink(int id)     // unlinks ID from fields list and return the pointer to it
560{
561  for (ifield *i=first,*last=NULL;i;i=i->next)
562  {
563    if (i->id==id)
564    {
565      if (i==first)
566    first=first->next;
567      else
568        last->next=i->next;
569      if (active==i)
570        active=first;
571      return i;
572    }
573    ifield *x=i->unlink(id);
574    if (x) return x;
575    last=i;
576  }
577  return NULL;   // no such id
578}
579
580InputManager::~InputManager()
581{ ifield *i;
582  while (first)
583  { i=first;
584    first=first->next;
585    delete i;
586  }
587}
588
589void InputManager::clear_current()
590{
591    if(owner)
592        screen = owner->screen;
593    if(active)
594        active->draw(0, screen);
595    active = NULL;
596}
597
598void InputManager::handle_event(event &ev, Jwindow *j)
599{
600  ifield *i,*in_area=NULL;
601  int x1,y1,x2,y2;
602
603  if(owner)
604      screen = owner->screen;
605
606  if (j)
607  {
608    ev.mouse_move.x-=j->x;
609    ev.mouse_move.y-=j->y;
610    cur=j;
611  }
612
613  if (!grab)
614  {
615    if ((ev.type==EV_MOUSE_BUTTON && ev.mouse_button==1) || ev.type==EV_MOUSE_MOVE)
616    {
617      for (i=first;i;i=i->next)
618      {
619    i->area(x1,y1,x2,y2);
620    if (ev.mouse_move.x>=x1 && ev.mouse_move.y>=y1 &&
621        ev.mouse_move.x<=x2 && ev.mouse_move.y<=y2)
622        in_area=i;
623      }
624      if (in_area!=active && (no_selections_allowed || (in_area && in_area->selectable())))
625      {
626    if (active)
627          active->draw(0,screen);
628
629    active=in_area;
630
631    if (active)
632      active->draw(1,screen);
633      }
634    }
635    if (ev.type==EV_KEY && ev.key==JK_TAB && active)
636    {
637      active->draw(0,screen);
638      do
639      {
640    active=active->next;
641    if (!active) active=first;
642      } while (active && !active->selectable());
643      active->draw(1,screen);
644    }
645  } else active=grab;
646
647  if (active)
648  {
649    if (ev.type!=EV_MOUSE_MOVE && ev.type!=EV_MOUSE_BUTTON)
650      active->handle_event(ev,screen,this);
651    else
652    {
653      active->area(x1,y1,x2,y2);
654      if (grab || (ev.mouse_move.x>=x1 && ev.mouse_move.y>=y1 &&
655          ev.mouse_move.x<=x2 && ev.mouse_move.y<=y2))
656      {
657    if (j)
658      active->handle_event(ev,screen,j->inm);
659    else active->handle_event(ev,screen,this);
660      }
661    }
662  }
663
664  if (j)
665  {
666    ev.mouse_move.x+=j->x;
667    ev.mouse_move.y+=j->y;
668  }
669}
670
671void InputManager::allow_no_selections()
672{
673  no_selections_allowed=1;
674}
675
676void InputManager::redraw()
677{
678    ifield *i;
679    if(owner)
680        screen = owner->screen;
681    for(i = first; i; i = i->next)
682        i->draw_first(screen);
683    if(active)
684        active->draw(1, screen);
685}
686
687InputManager::InputManager(image *Screen, ifield *First)
688{
689    no_selections_allowed = 0;
690    cur = NULL;
691    grab = NULL;
692    owner = NULL;
693    screen = Screen;
694    active = first = First;
695    while(active && !active->selectable())
696        active = active->next;
697    if(screen)
698        redraw();
699}
700
701InputManager::InputManager(Jwindow *Owner, ifield *First)
702{
703    no_selections_allowed = 0;
704    cur = NULL;
705    grab = NULL;
706    owner = Owner;
707    screen = NULL;
708    active = first = First;
709    while(active && !active->selectable())
710        active = active->next;
711}
712
713void InputManager::grab_focus(ifield *i)
714{ grab=i;
715  if (cur)
716    wm->grab_focus(cur);
717}
718
719void InputManager::release_focus()
720{ grab=NULL;
721  if (cur)
722    wm->release_focus();
723}
724
725void InputManager::remap(filter *f)
726{
727  for (ifield *i=first;i;i=i->next)
728   i->remap(f);
729  redraw();
730}
731
732void InputManager::add(ifield *i)
733{ ifield *f=first;
734  if (i->selectable())
735  {
736    if (!f)
737      first=i;
738    else
739    {
740      while (f->next) f=f->next;
741      f->next=i;
742    }
743  }
744}
745
746ifield *InputManager::get(int id)
747{
748  ifield *f;
749  for (f=first;f;f=f->next)
750  {
751    ifield *ret=f->find(id);
752    if (ret) return ret;
753  }
754  return NULL;
755}
756
757ifield::ifield()
758{
759    owner = NULL;
760    x = 0;
761    y = 0;
762    next = NULL;
763    id = 0;
764}
765
766ifield::~ifield()
767{
768    ;
769}
770
771/* re-position the control with respect to the "client" area of the window */
772void ifield::set_owner(Jwindow * newowner)
773{
774    if(owner)
775        move(x - owner->x1(), y - owner->y1());
776    owner = newowner;
777    if(owner)
778        move(x + owner->x1(), y + owner->y1());
779}
780
Note: See TracBrowser for help on using the repository browser.