/*
 * Bind command
 *	++Jam
 */

#include <global.h>
#include <sproto.h>

int command_bind (object *op, char *params)
{
  static char buf[MAX_BUF];
  int flags;

  if (!params) {
    new_draw_info(NDI_UNIQUE, 0,op, "Usage: bind [-nfrge] {<commandline>/commandkey/firekey{1/2}/runkey{1/2}}");
    return 0;
  }

  if (!strcmp(params, "commandkey")) {
    op->contr->write_buf[0] ='C';
    new_draw_info(NDI_UNIQUE, 0,op, "Push key to bind new commandkey.");
    op->contr->state = ST_CONFIGURE;
    return 1;
  }
  if (!strcmp(params, "firekey1")) {
    op->contr->write_buf[0] ='F';
    new_draw_info(NDI_UNIQUE, 0,op, "Push key to bind new firekey 1.");
    op->contr->state = ST_CONFIGURE;
    return 1;
  }
  if (!strcmp(params, "firekey2")) {
    op->contr->write_buf[0] ='f';
    new_draw_info(NDI_UNIQUE, 0,op, "Push key to bind new firekey 2.");
    op->contr->state = ST_CONFIGURE;
    return 1;
  }
  if (!strcmp(params, "runkey1")) {
    op->contr->write_buf[0] ='R';
    new_draw_info(NDI_UNIQUE, 0,op, "Push key to bind new runkey 1.");
    op->contr->state = ST_CONFIGURE;
    return 1;
  }
  if (!strcmp(params, "runkey2")) {
    op->contr->write_buf[0] ='r';
    new_draw_info(NDI_UNIQUE, 0,op, "Push key to bind new runkey 2.");
    op->contr->state = ST_CONFIGURE;
    return 1;
  }

  if (params[0] != '-')
    flags =(KEYF_NORMAL|KEYF_FIRE|KEYF_RUN);
  else {
    flags =0;
    for (params++; *params != ' '; params++)
      switch (*params) {
      case 'n':
	flags |= KEYF_NORMAL;
	break;
      case 'f':
	flags |= KEYF_FIRE;
	break;
      case 'r':
	flags |= KEYF_RUN;
	break;
      case 'e':
	flags |= KEYF_EDIT;
	break;
      case 'g':
	flags |= 0x1000;
	break;
      case '\0':
	new_draw_info(NDI_UNIQUE, 0,op, "Try unbind to remove bindings..");
	return 0;
      default:
	new_draw_info_format(NDI_UNIQUE, 0,op,"Unknown flag to bind: '%c'", *params);
	return 0;
      }
    params++;
  }
  
  if (!(flags & (KEYF_NORMAL|KEYF_FIRE|KEYF_RUN)))
    flags |= (KEYF_NORMAL|KEYF_FIRE|KEYF_RUN);

  if (!params[0]) {
    new_draw_info(NDI_UNIQUE, 0,op, "Try unbind to remove bindings..");
    return 0;
  }

  new_draw_info_format(NDI_UNIQUE, 0, op,
	 "Push key to bind '%s'.", params);
  sprintf(buf, "%i %s", flags, params);
  sprintf(op->contr->write_buf, "B%s", buf);
  op->contr->state = ST_CONFIGURE;
  return 1;
}


extern char *find_func_name(CommFunc func);

void show_keys(object *op, int mode)
{
  int i, bi, count=1;
  Key_s *key;
  char buf[MAX_BUF], buff[4];

  new_draw_info_format(NDI_UNIQUE, 0, op,
	"Commandkey %s (%d)", XKeysymToString(op->contr->commandkeysym),
	  op->contr->commandkey);

  new_draw_info_format(NDI_UNIQUE, 0, op,
	"Firekeys 1: %s (%d), 2: %s (%d)",
	  XKeysymToString(op->contr->firekeysym[0]), op->contr->firekey[0],
	  XKeysymToString(op->contr->firekeysym[1]), op->contr->firekey[1]);

  new_draw_info_format(NDI_UNIQUE, 0, op,
	"Runkeys 1: %s (%d), 2: %s (%d)",
	  XKeysymToString(op->contr->runkeysym[0]), op->contr->runkey[0],
	  XKeysymToString(op->contr->runkeysym[1]), op->contr->runkey[1]);

  for (i=0; i<COMMAND_HASH_SIZE; i++)
    for (key=op->contr->keys[i]; key; key =key->next) {
      if ((!!mode) == (!(key->flags & KEYF_DEFAULT))) 
	break;
      buff[0] ='\0';
      buff[1] ='\0';
      buff[2] ='\0';
      buff[3] ='\0';
      bi =0;
      if (key->flags & KEYF_DEFAULT)
	buff[bi++] ='d';
      if (key->flags & KEYF_WIZ)
	buff[bi++] ='w';
      if ((key->flags & (KEYF_NORMAL|KEYF_FIRE|KEYF_RUN)) ==
	  (KEYF_NORMAL|KEYF_FIRE|KEYF_RUN))
	buff[bi++] ='A';
      else {
	if (key->flags & KEYF_NORMAL)
	  buff[bi++] ='N';
	if (key->flags & KEYF_FIRE)
	  buff[bi++] ='F';
	if (key->flags & KEYF_RUN)
	  buff[bi++] ='R';
      }
      if (key->flags & KEYF_EDIT)
	buff[bi++] ='E';

      if(key->keysym == NoSymbol) {
	if (key->func)
	  if (key->params)
	    sprintf(buf, "%3d key (null) (%i) %s %s %s", count, 
		    (int)key->keycode,buff, find_func_name(key->func), key->params);
	  else
	    sprintf(buf, "%3d key (null) (%i) %s %s", count, 
		    (int)key->keycode, buff, find_func_name(key->func));
	else
	  if (key->params)
	    sprintf(buf, "%3d key (null) (%i) %s %s", count, 
		    (int)key->keycode, buff, key->params);
	  else
	    sprintf(buf, "%3d key (null) (%i) %s", count, 
		    (int)key->keycode, buff);
      } else {
	if (key->func)
	  if (key->params)
	    sprintf(buf, "%3d key %s (%i) %s %s %s", count, 
		    XKeysymToString(key->keysym), (int)key->keycode,
		    buff, find_func_name(key->func), key->params);
	  else
	    sprintf(buf, "%3d key %s (%i) %s %s", count, 
		    XKeysymToString(key->keysym), (int)key->keycode,
		    buff, find_func_name(key->func));
	else
	  if (key->params)
	    sprintf(buf, "%3d key %s (%i) %s %s", count, 
		    XKeysymToString(key->keysym), (int)key->keycode,
		    buff, key->params);
	  else
	    sprintf(buf, "%3d key %s (%i) %s (null)", count, 
		    XKeysymToString(key->keysym), (int)key->keycode, buff);
      }
	  
      new_draw_info(NDI_UNIQUE, 0,op, buf);
      count++;
    }				/* for */
}

int command_unbind (object *op, char *params)
{
  int i, j, bi, mode=0, count=0;
  Key_s *key, *tmp;
  char buf[MAX_BUF], buff[4];

  if (!params || !params[0]) {
    show_keys(op, 0);
    return 0;
  }

  if (!strcmp(params, "all") || !strcmp(params, "reset")) {
    load_default_keys(op->contr);
    new_draw_info(NDI_UNIQUE, 0,op, "Resetting to default bindings.");
    return 0;
  }

  if (params[0] == '-' && params[1] == 'g') {

    if (sscanf(params+2, "%d", &j)!=1) {
      show_keys(op, 1);
      return 0;
    }
    mode =1;
  } else if (sscanf(params, "%d", &j)!=1) {
    new_draw_info(NDI_UNIQUE, 0,op, "Usage: unbind [-g] [#]");
    return 0;
  }

  for (i=0; i<COMMAND_HASH_SIZE; i++)
    for (key=op->contr->keys[i]; key; key =key->next) {
      if ((!!mode) == (!(key->flags & KEYF_DEFAULT)))
	break;
      count++;
      if (j != count)
	continue;
      if (key->flags & KEYF_DEFAULT) {
	insert_key_complex(op->contr, key->keysym, key->keycode,
	   (key->flags&(KEYF_NORMAL|KEYF_FIRE|KEYF_RUN))|KEYF_USER, NULL);
	goto unbinded;
      }
      if (key == op->contr->keys[i]) {
	op->contr->keys[i] =key->next;
	goto unbinded;
      }
      for (tmp=op->contr->keys[i]; tmp->next; tmp=tmp->next)
	if (tmp->next == key) {
	  tmp->next =key->next;
	  goto unbinded;
	}
    }				/* for */

  new_draw_info(NDI_UNIQUE, 0,op, "No such entry. Try plain 'unbind' to find entry.");
  return 0;

  /*
   * Found. Now remove it.
   */
 unbinded:
  
  buff[0] ='\0';
  buff[1] ='\0';
  buff[2] ='\0';
  buff[3] ='\0';
  bi =0;
  if (key->flags & KEYF_DEFAULT)
    buff[bi++] ='d';
  if (key->flags & KEYF_WIZ)
    buff[bi++] ='w';
  if ((key->flags & (KEYF_NORMAL|KEYF_FIRE|KEYF_RUN)) ==
      (KEYF_NORMAL|KEYF_FIRE|KEYF_RUN))
    buff[bi++] ='A';
  else {
    if (key->flags & KEYF_NORMAL)
      buff[bi++] ='N';
    if (key->flags & KEYF_FIRE)
      buff[bi++] ='F';
    if (key->flags & KEYF_RUN)
      buff[bi++] ='R';
  }
  if (key->flags & KEYF_EDIT)
    buff[bi++] ='E';
  
  if(key->keysym == NoSymbol) {
    if (key->func)
      if (key->params)
	sprintf(buf, "%3d key (null) (%i) %s %s %s", count, 
		(int)key->keycode,buff, find_func_name(key->func), key->params);
	  else
	    sprintf(buf, "%3d key (null) (%i) %s %s", count, 
		    (int)key->keycode, buff, find_func_name(key->func));
    else
      if (key->params)
	sprintf(buf, "%3d key (null) (%i) %s %s", count, 
		(int)key->keycode, buff, key->params);
      else
	sprintf(buf, "%3d key (null) (%i) %s", count, 
		(int)key->keycode, buff);
  } else {
    if (key->func)
      if (key->params)
	sprintf(buf, "%3d key %s (%i) %s %s %s", count, 
		XKeysymToString(key->keysym), (int)key->keycode,
		buff, find_func_name(key->func), key->params);
      else
	sprintf(buf, "%3d key %s (%i) %s %s", count, 
		XKeysymToString(key->keysym), (int)key->keycode,
		buff, find_func_name(key->func));
    else
      if (key->params)
	sprintf(buf, "%3d key %s (%i) %s %s", count, 
		XKeysymToString(key->keysym), (int)key->keycode,
		buff, key->params);
      else
	sprintf(buf, "%3d key %s (%i) %s (null)", count, 
		XKeysymToString(key->keysym), (int)key->keycode, buff);
  }
  new_draw_info(NDI_UNIQUE, 0,op, buf);
  if (!(key->flags & KEYF_DEFAULT)) {
    if (key->params)
      free(key->params);
    free(key);
  }
  return 0;
}
