/* * Abuse - dark 2D side-scrolling platform game * Copyright (c) 1995 Crack dot Com * Copyright (c) 2005-2011 Sam Hocevar * * This software was released into the Public Domain. As with most public * domain software, no warranty is made or implied by Crack dot Com, by * Jonathan Clark, or by Sam Hocevar. */ #if defined HAVE_CONFIG_H # include "config.h" #endif #include #include "common.h" #include "video.h" #include "image.h" #include "input.h" #include "event.h" #include "filter.h" #include "jwindow.h" static int jw_left = 3, jw_right = 3, jw_top = 2, jw_bottom = 3; int frame_top() { return jw_top; } int frame_bottom() { return jw_bottom; } int frame_left() { return jw_left; } int frame_right() { return jw_right; } // // Sets the size of the border around each window // void set_frame_size(int x) { if(x < 1) x = 1; jw_left = x; jw_right = x; jw_top = 2; jw_bottom = x; } // true if a window lies in this area int WindowManager::window_in_area(int x1, int y1, int x2, int y2) { for (Jwindow *f=m_first; f; f=f->next) if (f->m_pos.x<=x2 && f->m_pos.y<=y2 && f->m_pos.x+f->l-1>=x1 && f->m_pos.y+f->h-1>=y1) return 1; return 0; } void WindowManager::grab_focus(Jwindow *j) { m_grab=j; } void WindowManager::release_focus() { m_grab=NULL; } void WindowManager::close_window(Jwindow *j) { delete j; } void WindowManager::hide_windows() { for (Jwindow *p = m_first; p; p = p->next) { if (!p->is_hidden()) { p->hide(); m_surf->AddDirty(p->m_pos.x, p->m_pos.y, p->m_pos.x + p->l, p->m_pos.y + p->h); } } } void WindowManager::show_windows() { Jwindow *p; for (p=m_first; p; p=p->next) if (p->is_hidden()) show_window(p); } void WindowManager::hide_window(Jwindow *j) { if (j == m_first) m_first = m_first->next; else { Jwindow *k; for (k = m_first; k->next != j; k = k->next) k->m_surf->AddDirty(j->m_pos.x - k->m_pos.x, j->m_pos.y - k->m_pos.y, j->m_pos.x + j->l - k->m_pos.x, j->m_pos.y + j->h - k->m_pos.y); k->m_surf->AddDirty(j->m_pos.x - k->m_pos.x, j->m_pos.y - k->m_pos.y, j->m_pos.x + j->l - k->m_pos.x, j->m_pos.y + j->h - k->m_pos.y); k->next = j->next; } m_surf->AddDirty(j->m_pos.x, j->m_pos.y, j->m_pos.x + j->l, j->m_pos.y + j->h); j->hide(); } void WindowManager::show_window(Jwindow *j) { if (j->is_hidden()) { j->show(); j->m_surf->AddDirty(0, 0, j->l, j->h); } } void WindowManager::get_event(Event &ev) { Get(ev); if (ev.type==EV_KEY) key_state[ev.key]=1; else if (ev.type==EV_KEYRELEASE) key_state[ev.key]=0; if (state==inputing) { Jwindow *j; for (ev.window=NULL,j=m_first; j; j=j->next) if (!j->is_hidden() && ev.mouse_move >= j->m_pos && ev.mouse_move < j->m_pos + vec2i(j->l, j->h)) ev.window=j; if (!ev.window && m_grab) ev.window=m_grab; if (ev.window) { int closew=0,movew=0; if ((ev.type==EV_MOUSE_BUTTON && ev.mouse_button==1 && ev.window && ev.mouse_move >= ev.window->m_pos && ev.mouse_move < ev.window->m_pos + vec2i(ev.window->l, ev.window->y1()))) { if (ev.mouse_move.x-ev.window->m_pos.x < 11) closew=1; else if (ev.window->is_moveable()) movew=1; } else if (m_grab) ev.window=m_grab; if (ev.type==EV_KEY && ev.key==JK_ESC) closew=1; if (closew) ev.type=EV_CLOSE_WINDOW; else if (movew) { int red=0; if (ev.window==m_first) // see if we need to raise the window { m_first=m_first->next; if (m_first) red=1; } else { Jwindow *last=m_first; for (; last->next!=ev.window; last=last->next); if (ev.window->next) red=1; last->next=ev.window->next; } if (!m_first) m_first=ev.window; else { Jwindow *last=m_first; for (; last->next; last=last->next); last->next=ev.window; } ev.window->next=NULL; if (red) { Jwindow *j=ev.window; /* m_surf->AddDirty(j->x,j->y,j->x+j->l,j->y+j->h); for (p=m_first; p!=j; p=p->next) p->m_surf->AddDirty(j->x-p->x,j->y-p->y,j->x+j->l-p->x,j->y+j->h-p->y); */ j->m_surf->AddDirty(0, 0, j->l, j->h); flush_screen(); } state=dragging; drag_window=ev.window; drag_mousex=ev.window->m_pos.x-ev.mouse_move.x; drag_mousey=ev.window->m_pos.y-ev.mouse_move.y; ev.type=EV_SPURIOUS; } else if (ev.window) ev.window->inm->handle_event(ev,ev.window); } } else if (state==dragging) { ev.window=drag_window; if (ev.type==EV_MOUSE_BUTTON && ev.mouse_button==0) // user released the mouse { state=inputing; ev.type=EV_SPURIOUS; } else if (ev.type==EV_MOUSE_MOVE) { move_window(drag_window,ev.mouse_move.x+drag_mousex,ev.mouse_move.y+drag_mousey); flush_screen(); ev.type=EV_DRAG_WINDOW; ev.window_position.x=ev.mouse_move.x+drag_mousex; ev.window_position.y=ev.mouse_move.y+drag_mousey; } } if (ev.type == EV_REDRAW) { for (Jwindow *j = m_first; j; j = j->next) j->m_surf->AddDirty(ev.redraw.x1 - j->m_pos.x, ev.redraw.y1 - j->m_pos.y, ev.redraw.x2 + 1 - j->m_pos.x, ev.redraw.y2 + 1 - j->m_pos.y); m_surf->AddDirty(ev.redraw.x1, ev.redraw.y1, ev.redraw.x2 + 1, ev.redraw.y2 + 1); flush_screen(); ev.type=EV_SPURIOUS; // we took care of this one by ourselves. } } void Jwindow::resize(int L, int H) { m_surf->SetSize(vec2i(L,H)); l=L; h=H; } void WindowManager::resize_window(Jwindow *j, int l, int h) { Jwindow *p; m_surf->AddDirty(j->m_pos.x, j->m_pos.y, j->m_pos.x + j->l, j->m_pos.y + j->h); for (p=m_first; p!=j; p=p->next) p->m_surf->AddDirty(j->m_pos.x - p->m_pos.x, j->m_pos.y - p->m_pos.y, j->m_pos.x + j->l - p->m_pos.x, j->m_pos.y + j->h - p->m_pos.y); j->resize(l,h); if (!frame_suppress) j->redraw(); } void WindowManager::move_window(Jwindow *j, int x, int y) { m_surf->AddDirty(j->m_pos.x, j->m_pos.y, j->m_pos.x + j->l, j->m_pos.y + j->h); for(Jwindow *p = m_first; p != j; p = p->next) p->m_surf->AddDirty(j->m_pos.x - p->m_pos.x, j->m_pos.y - p->m_pos.y, j->m_pos.x + j->l - p->m_pos.x, j->m_pos.y + j->h - p->m_pos.y); j->m_pos.x = x; j->m_pos.y = y; j->m_surf->AddDirty(0, 0, j->l, j->h); } WindowManager::WindowManager(image *screen, palette *pal, int Hi, int Med, int Low, JCFont *Font) : EventHandler(screen, pal) { wm = this; m_surf = screen; hi = Hi; low = Low; med = Med; m_first = NULL; m_pal = pal; m_grab = NULL; bk = pal->find_closest(0, 0, 0); state = inputing; fnt = Font; wframe_fnt = Font; memset(key_state, 0, sizeof(key_state)); frame_suppress = 0; } WindowManager::~WindowManager() { while(m_first) close_window(m_first); wm = NULL; } void WindowManager::add_window(Jwindow *win) { if(!m_first) m_first = win; else { Jwindow *tmp = m_first; while(tmp->next) tmp = tmp->next; tmp->next = win; win->next = NULL; } } void WindowManager::remove_window(Jwindow *win) { if(m_grab == win) m_grab = NULL; // close the window we were dragging if(state == dragging && win == drag_window) state = inputing; if(m_first == win) m_first = m_first->next; else { Jwindow * search; for(search = m_first; search->next != win; search = search->next) search->m_surf->AddDirty(win->m_pos.x - search->m_pos.x, win->m_pos.y - search->m_pos.y, win->m_pos.x + win->l - search->m_pos.x, win->m_pos.y + win->h - search->m_pos.y); search->m_surf->AddDirty(win->m_pos.x - search->m_pos.x, win->m_pos.y - search->m_pos.y, win->m_pos.x + win->l - search->m_pos.x, win->m_pos.y + win->h - search->m_pos.y); search->next = win->next; } m_surf->AddDirty(win->m_pos.x, win->m_pos.y, win->m_pos.x + win->l, win->m_pos.y + win->h); } Jwindow * WindowManager::new_window(int x, int y, int l, int h, ifield * fields, char const *name) { if(x > m_surf->Size().x - 4) x = m_surf->Size().x - 25; if(y > m_surf->Size().y - 4) y = m_surf->Size().y - 10; Jwindow * j = new Jwindow (vec2i(x, y), l, h, fields, name); j->show(); return j; } void WindowManager::flush_screen() { vec2i m1(0, 0); if (has_mouse()) { m1 = m_pos - m_center; vec2i m2 = m1 + m_sprite->visual->Size() - vec2i(1, 1); m_sprite->save->PutPart(m_surf, 0, 0, m1.x, m1.y, m2.x, m2.y); m_surf->PutImage(m_sprite->visual, m1, 1); } for (Jwindow *p = m_first; p; p = p->next) if (!p->is_hidden()) m_surf->delete_dirty(p->m_pos.x, p->m_pos.y, p->m_pos.x + p->l, p->m_pos.y + p->h); update_dirty(m_surf); if (has_mouse()) m_surf->PutImage(m_sprite->save, m1); for (Jwindow *p = m_first; p; p = p->next) { if (p->is_hidden()) continue; if (has_mouse()) { m_sprite->save->PutPart(p->m_surf, 0, 0, m1.x - p->m_pos.x, m1.y - p->m_pos.y, m1.x - p->m_pos.x + m_sprite->visual->Size().x - 1, m1.y - p->m_pos.y + m_sprite->visual->Size().y - 1); p->m_surf->PutImage(m_sprite->visual, m1 - p->m_pos, 1); } // m_surf->delete_dirty(p->m_pos.x, p->m_pos.y, p->m_pos.x+p->l, p->m_pos.y+p->h); for (Jwindow *q = p->next; q; q = q->next) if (!q->is_hidden()) p->m_surf->delete_dirty(q->m_pos.x - p->m_pos.x, q->m_pos.y - p->m_pos.y, q->m_pos.x + q->l - p->m_pos.x, q->m_pos.y + q->h - p->m_pos.y); update_dirty(p->m_surf, p->m_pos.x, p->m_pos.y); if (has_mouse()) p->m_surf->PutImage(m_sprite->save, m1 - p->m_pos, 0); } } Jwindow::Jwindow(char const *name) { _x1 = left_border(); _y1 = jw_top + 5; _x2 = _y2 = 0; _hidden = true; _moveable = true; // property.flags = JWINDOW_NOAUTOHIDE_FLAG; inm = new InputManager(this, NULL); reconfigure(); m_surf = NULL; next = NULL; _name = NULL; if(name) _name = strdup(name); wm->add_window(this); } Jwindow::Jwindow(vec2i pos, int L, int H, ifield *f, char const *name) { l = 0; h = 0; _hidden = false; _moveable = true; _x1 = left_border(); _y1 = name ? top_border() : jw_top + 5; m_surf = NULL; inm = new InputManager(m_surf, f); reconfigure(); /* FIXME: TODO */ l = L >= 0 ? L + left_border() : l - L; h = H >= 0 ? H + top_border() : h - H; m_pos.x = pos.x >= 0 ? pos.x : xres - l + pos.x - left_border() - right_border() - 1; m_pos.y = pos.y >= 0 ? pos.y : yres - h + pos.y - top_border() - bottom_border() - 1; backg = wm->medium_color(); _x2 = l - 1; _y2 = h - 1; l += right_border(); h += bottom_border(); if(L == -1) if(l < 15 + left_border() + right_border()) l = 15 + left_border() + right_border(); if(H == -1) if(h < top_border() + bottom_border()) h = top_border() + bottom_border(); m_surf = new image(vec2i(l, h), NULL, 2); m_surf->clear(backg); // Keep this from getting destroyed when image list is cleared image_list.unlink(m_surf); inm->m_surf = m_surf; next = NULL; _name = NULL; if(name) _name = strdup(name); wm->add_window(this); if(!wm->frame_suppress) redraw(); } Jwindow::~Jwindow() { wm->remove_window(this); local_close(); delete m_surf; delete inm; if(_name) free(_name); } void Jwindow::reconfigure() { int x1, y1, x2, y2; ifield *i; l = 2; h = 2; for(i = inm->m_first; i; i = i->next) { i->set_owner(this); i->area(x1, y1, x2, y2); if ((int)y2 > (int)h) h = y2; if ((int)x2 > (int)l) l = x2; } } void Jwindow::local_close() { ; } void Jwindow::redraw() { int hi = wm->bright_color(); int med = wm->medium_color(); int low = wm->dark_color(); JCFont * fnt = wm->frame_font(); if(_name) { if (right_border() >= 1) { m_surf->WidgetBar(vec2i(0, 0), vec2i(l - 1, h - 1), hi, med, low); if (right_border() >= 3) m_surf->WidgetBar(vec2i(right_border() - 1, top_border() - 1), vec2i(l - left_border(), h - bottom_border()), low, med, hi); else m_surf->Line(vec2i(left_border() - 1, top_border() - 1), vec2i(right_border() - 1, top_border() - 1), low); } m_surf->Rectangle(vec2i(2, 2), vec2i(top_border() - 2, top_border() - 3), wm->black()); m_surf->WidgetBar(vec2i(3, 3), vec2i(top_border() - 3, top_border() - 4), hi, med, low); // draws the 'close' button } else { if (right_border() >= 1) { m_surf->WidgetBar(vec2i(0, 0), vec2i(l - 1, h - 1), hi, med, low); if (right_border() >= 3) m_surf->WidgetBar(vec2i(right_border() - 1, jw_top + 4), vec2i(l - left_border(), h - bottom_border()), low, med, hi); else m_surf->Line(vec2i(left_border() - 1, jw_top + 4), vec2i(right_border() - 1, jw_top + 4), low); } // Draw the 'close' button m_surf->Rectangle(vec2i(1, 1), vec2i(4, 4), wm->black ()); m_surf->WidgetBar(vec2i(2, 2), vec2i(3, 3), hi, med, low); } if (_name && _name[0]) { m_surf->Bar(vec2i(top_border(), 1), vec2i(top_border() + fnt->width() * strlen (_name) + 1, top_border() - 2), med); fnt->put_string(m_surf, top_border() + 1, 1, _name, low); } // clear 'client' region m_surf->Bar(vec2i(x1(), y1()), vec2i(x2(), y2()), backg); inm->redraw (); } int Jwindow::left_border() { return frame_left(); } int Jwindow::right_border() { return frame_right(); } int Jwindow::top_border() { return wm->font()->height() + frame_top(); } int Jwindow::bottom_border() { return frame_bottom(); } ifield *InputManager::unlink(int id) // unlinks ID from fields list and return the pointer to it { for (ifield *i=m_first,*last=NULL; i; i=i->next) { if (i->id==id) { if (i==m_first) m_first=m_first->next; else last->next=i->next; if (m_active==i) m_active=m_first; return i; } ifield *x=i->unlink(id); if (x) return x; last=i; } return NULL; // no such id } InputManager::~InputManager() { ifield *i; while (m_first) { i=m_first; m_first=m_first->next; delete i; } } void InputManager::clear_current() { if(m_owner) m_surf = m_owner->m_surf; if(m_active) m_active->draw(0, m_surf); m_active = NULL; } void InputManager::handle_event(Event &ev, Jwindow *j) { ifield *i,*in_area=NULL; int x1,y1,x2,y2; if(m_owner) m_surf = m_owner->m_surf; if (j) { ev.mouse_move -= j->m_pos; m_cur = j; } if (!m_grab) { if ((ev.type==EV_MOUSE_BUTTON && ev.mouse_button==1) || ev.type==EV_MOUSE_MOVE) { for (i=m_first; i; i=i->next) { i->area(x1,y1,x2,y2); if (ev.mouse_move.x>=x1 && ev.mouse_move.y>=y1 && ev.mouse_move.x<=x2 && ev.mouse_move.y<=y2) in_area=i; } if (in_area!=m_active && (no_selections_allowed || (in_area && in_area->selectable()))) { if (m_active) m_active->draw(0,m_surf); m_active=in_area; if (m_active) m_active->draw(1,m_surf); } } if (ev.type==EV_KEY && ev.key==JK_TAB && m_active) { m_active->draw(0,m_surf); do { m_active=m_active->next; if (!m_active) m_active=m_first; } while (m_active && !m_active->selectable()); m_active->draw(1,m_surf); } } else m_active=m_grab; if (m_active) { if (ev.type!=EV_MOUSE_MOVE && ev.type!=EV_MOUSE_BUTTON) m_active->handle_event(ev,m_surf,this); else { m_active->area(x1,y1,x2,y2); if (m_grab || (ev.mouse_move.x>=x1 && ev.mouse_move.y>=y1 && ev.mouse_move.x<=x2 && ev.mouse_move.y<=y2)) { if (j) m_active->handle_event(ev,m_surf,j->inm); else m_active->handle_event(ev,m_surf,this); } } } if (j) ev.mouse_move += j->m_pos; } void InputManager::allow_no_selections() { no_selections_allowed=1; } void InputManager::redraw() { ifield *i; if(m_owner) m_surf = m_owner->m_surf; for(i = m_first; i; i = i->next) i->draw_first(m_surf); if(m_active) m_active->draw(1, m_surf); } InputManager::InputManager(image *screen, ifield *first) { no_selections_allowed = 0; m_cur = NULL; m_grab = NULL; m_owner = NULL; m_surf = screen; m_active = m_first = first; while(m_active && !m_active->selectable()) m_active = m_active->next; if(m_surf) redraw(); } InputManager::InputManager(Jwindow *owner, ifield *first) { no_selections_allowed = 0; m_cur = NULL; m_grab = NULL; m_owner = owner; m_surf = NULL; m_active = m_first = first; while(m_active && !m_active->selectable()) m_active = m_active->next; } void InputManager::grab_focus(ifield *i) { m_grab = i; if (m_cur) wm->grab_focus(m_cur); } void InputManager::release_focus() { m_grab = NULL; if (m_cur) wm->release_focus(); } void InputManager::remap(Filter *f) { for (ifield *i = m_first; i; i = i->next) i->remap(f); redraw(); } void InputManager::add(ifield *i) { ifield *f=m_first; if (i->selectable()) { if (!f) m_first=i; else { while (f->next) f=f->next; f->next=i; } } } ifield *InputManager::get(int id) { ifield *f; for (f=m_first; f; f=f->next) { ifield *ret=f->find(id); if (ret) return ret; } return NULL; } ifield::ifield() { owner = NULL; m_pos = vec2i(0, 0); next = NULL; id = 0; } ifield::~ifield() { ; } /* re-position the control with respect to the "client" area of the window */ void ifield::set_owner(Jwindow * newowner) { if(owner) Move(m_pos - vec2i(owner->x1(), owner->y1())); owner = newowner; if(owner) Move(m_pos + vec2i(owner->x1(), owner->y1())); }