
/* 
  pairs a binding to a function
  */ 

#include "nawm.h"
#include "bindings.h"

BindInfo bind_list;
unsigned bind_cnt;
int current_mode = DEFAULT_MODE;
Window current_window = (Window)0;
Window focus_window = (Window)0;

init_bindings()
{
  bind_list = (BindInfo)malloc(0);
  bind_cnt = 0;
}

BindInfo realloc_binding()
{
  static BindInfo tmp;

  tmp = (BindInfo)realloc((char *) bind_list, (unsigned) ++bind_cnt * sizeof(BindInfo_S));
  if(!tmp) {
    die("Out of memory");
  }
  bind_list = tmp;
  return &bind_list[bind_cnt-1];
}

grab_things()
{
  unsigned int i;
  BindInfo bi;
  
  for(i = 0, bi = bind_list; i < bind_cnt; bi++, i++)
    
    if(bi->whatmode == ANY_MODE || bi->whatmode == current_mode) {
      /* break, but continue loop.  this allows 
	 multiple bindings to the same event */
      switch(bi->type) {
      case ButtonPress:
	XGrabButton(dpy, bi->button, bi->modifiers, root, False, ButtonReleaseMask | PointerMotionMask,
		    GrabModeAsync,GrabModeAsync,None, None);
	break;
      case KeyPress:
	XGrabKey(dpy, bi->keycode, bi->modifiers, root, False, GrabModeAsync,GrabModeAsync);
	break;
      }
    }
}

	 
ungrab_things()
{
  unsigned int i;
  BindInfo bi;
  
  for(i = 0, bi = bind_list; i < bind_cnt; bi++, i++)
    
      if (bi->whatmode == ANY_MODE || bi->whatmode == current_mode) {
	/* break, but continue loop.  this allows 
	   multiple bindings to the same event */
	switch(bi->type) {
	case ButtonPress:
	  XUngrabButton(dpy, bi->button, bi->modifiers, root);
	  break;
	case KeyPress:
	  XUngrabKey(dpy, bi->keycode, bi->modifiers, root);
	  break;
	}
      }
}

	 


add_motion_binding(modifiers, bi)
     unsigned int modifiers;
     BindInfo bi;
{
  bi->type = MotionNotify;
  bi->modifiers = modifiers;
}

add_key_binding(keycode, modifiers, bi)
     KeyCode keycode;
     unsigned int modifiers;
     BindInfo bi;
{
  bi->type = KeyPress;
  bi->keycode = keycode;
  bi->modifiers = modifiers;
}

add_button_binding(button, modifiers, bi)
     unsigned int button;
     unsigned int modifiers;
     BindInfo bi;
{

  bi->type = ButtonPress;
  bi->button = button;
  bi->modifiers = modifiers;

}

set_mode (n)
     int n;
{
  if (current_mode == n) return;
  ungrab_things();
  current_mode = n;
  grab_things();
}

wait_for_binding()
{
  XEvent ev;
  unsigned int i;
  BindInfo bi;
  int mode;

#ifdef USE_CACHE
  if (use_cache)
    start_cache();
#endif
  grab_things();
  for(;;) {
    XNextEvent(dpy, &ev);
#ifdef USE_CACHE
      update_cache(&ev);
#endif
    switch(ev.type) {
    case MotionNotify:
      inform_user(10, "MotionNotify event");
      current_window = ev.xmotion.subwindow;
      break;
    case ButtonPress:
      inform_user(10, "ButtonPress event");
      current_window = ev.xbutton.subwindow;
      break;
    case KeyPress:
      current_window = ev.xkey.subwindow;
      break;
    }
    focus_window = current_window;
    mode = current_mode;
    for(i = 0, bi = bind_list; i < bind_cnt; bi++, i++) {
      if(bi->type == ev.type && (bi->whatmode == ANY_MODE || bi->whatmode == mode)) {
	/* break, but continue loop.  this allows 
	   multiple bindings to the same event */
	switch(ev.type) {
	case MotionNotify:
	  do_binding(bi, &ev);
	  break;

	case ButtonPress:
	  if(bi->button == ev.xbutton.button &&
	     (bi->modifiers |AnyButton) == (ev.xbutton.state |AnyButton))
	    do_binding(bi, &ev);
	  break;

	case KeyPress:
	  if(bi->keycode == ev.xkey.keycode &&
	     bi->modifiers == ev.xkey.state)
	    do_binding(bi, &ev);
	  break;
	}
      }	 
    }
    icon_dispatch(&ev);
  }
}

