/*{{{  #includes*/
#ifdef CONFIG_H
#   include "config.h"
#endif

#include <sys/types.h>
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>

#include <local/bool.h>

#define KEYTAB_C
#define I_DISPLAY_C
#define I_FIELDEDIT_C
#define I_FINDS_C
#define I_FOLDING_C
#define I_GETMSG_C
#define I_GETTK_C
#define I_KEYBOARD_C
#define I_LOOP_C
#define I_MAIN_C
#define I_PROMPT_C
#define I_SCREEN_C
#define I_VIRTUAL_C

#include "origami.h"
/*}}}  */

/*{{{  variables*/
private KEY *toplevel[KBD_COUNT];
private KEY *find_current;
public int curr_kbd=0;
public int v_mac=0;
#ifdef MOUSY
  public TOKEN *mouse_mapping=0;
#endif
public int mouse_number=0;
/*}}}  */
/*{{{  key_infos key_info*/
#include "permlist.h"
/*}}}  */

/*{{{  kbd_change*/
public void kbd_change(int no)
{
  find_current=toplevel[curr_kbd=no];
}
/*}}}  */
/*{{{  set_key_top*/
public void set_key_top (KEY *top,int no)
{
  toplevel[no] = top;
  find_current = toplevel[curr_kbd];
}
/*}}}  */
/*{{{  find_key*/
public int find_key (int key)
{
  KEY *find=0;
  int foo;
  static bool K_S=FALSE;
  static TOKEN off=0;

  /*{{{  quoting???*/
  if (find_current==(KEY*)0) {
    find_current = toplevel[curr_kbd];
    foo=(unsigned char) key+off;
    off=0;
    return(foo);
  }
  /*}}}  */
  /*{{{  shifting???*/
  if (K_S)
   { K_S=FALSE;
     off=(off+(unsigned char) key)<<8;
     find_current=toplevel[curr_kbd];
     return(keytabcont);
   }
  /*}}}  */
  /*{{{  search in tree*/
  for (find = find_current->n_level;find;find = find->next)
    if (((unsigned char) key) == find->key) break;
  /*}}}  */
  /*{{{  sequence not found, end search*/
  if (find == (KEY*)0) {
    find_current = toplevel[curr_kbd];
    foo=off;
    off=0;
    return (foo?foo+(unsigned char) key:keytabend);
  }
  /*}}}  */
  /*{{{  an encoded sequence is found, end search*/
  if (find->code)
    if (find->code==K_QUOTE) {
      find_current=0;
      return(keytabcont);
    } else if (find->code==K_SHIFT) {
      K_S=TRUE;
      find_current=toplevel[curr_kbd];
      return(keytabcont);
    } else {
      find_current = toplevel[curr_kbd];
      foo=off+find->code;
      off=0;
      return (foo);
    }
  /*}}}  */
  /*{{{  the search continues*/
  if (find->n_level) {
    find_current = find;
    return (keytabcont);
  }
  /*}}}  */
  /*{{{  no level below this, the search ends*/
  find_current = toplevel[curr_kbd];
  foo=off;
  off=0;
  return (foo?foo+(unsigned char) key:keytabend);
  /*}}}  */
}
/*}}}  */
/*{{{  valid_key*/
public bool valid_key(bool *keypad, TOKEN *ch)
{
  bool browse_key;

  browse_key = (    *keypad
                && (*ch >= O_NOP)
                && (*ch <K_QUOTE)
                && (key_info[*ch - O_NOP]&KTI_B));
  if (read_only && !browse_key) {
    message(get_msg(M_VIEW),TRUE);
    if (v_mac) call_number_macro(v_mac);
    return FALSE;
  } else {
    if (!browse_key && !file_changed) {
      file_changed = TRUE;
      title_op(SET_CF);
    }
    return TRUE;
  }
}
/*}}}  */
/*{{{  valid_field_key check if token is a correct field_key*/
public bool valid_field_key(bool *keypad,TOKEN *ch)
{
  if (*keypad) return (key_info[*ch - O_NOP]&KTI_F);
  else return TRUE;
}
/*}}}  */
/*{{{  valid_screen_key*/
public bool valid_screen_key(bool *keypad,TOKEN *ch)
{
  if (*keypad && select_on)
    return (key_info[*ch - O_NOP]&KTI_S);
  else
    return TRUE;
}
/*}}}  */
/*{{{  invalid_prompt_key*/
public bool invalid_prompt_key(TOKEN c)
{
  if (c>=O_NOP && c<K_QUOTE && !(key_info[c-O_NOP]&KTI_P))
   /*{{{  maybe get unhandled OCL-args*/
   { switch (GET_T(c))
      { case COM_II:
           get_arg();
        case COM_I:
        case COM_C:
        case COM_A:
           get_arg();
        case COM:
           break;
        case COM_IIP:
           get_arg();
        case COM_IP:
           get_arg();
        case COM_P:
           while ((c=get_arg())!=M_END_MACRO) if (c==M_INT_STRING) get_arg();
           break;
      }
     return(TRUE);
   }
   /*}}}  */

  return(FALSE);
}
/*}}}  */
#ifdef MOUSY
  /*{{{  get clickposition and return correct token*/
  TOKEN handle_click(int x,int y, int but)
  {
    if (current==(element*)0) return(O_NOP);
    if (mouse_x!=mouse_y)
     /*{{{  set mouse-vars*/
     {
       /*{{{  get x/y-vars and check correct line*/
       {
         int i;
         element *p=current;

         /*{{{  get line and y-pos*/
         macro_int[mouse_outside]=0;
         i=macro_int[mouse_go_y]=y-cursor_level;
         while (i)
           /*{{{  one step to clicked line*/
           if (i>0) {
             /*{{{  move down*/
             if (current==tail) { macro_int[mouse_outside]=1; break; }
             current=current->next;
             i--;
             /*}}}  */
           } else {
             /*{{{  move up*/
             if (current->prec==head) { macro_int[mouse_outside]=1;break; }
             current=current->prec;
             i++;
             /*}}}  */
           }
           /*}}}  */
         macro_int[mouse_y]=line_no(current)-1;
         /*}}}  */
         /*{{{  maybe correct outside?*/
         if (   (!enter_depth && (current==tail || current->prec==head))
             || y>SCREEN_LEN)
            macro_int[mouse_outside]=1;
         /*}}}  */
         /*{{{  get x-vars*/
         if (cursor_level==y) x+=x_offset;
         macro_int[mouse_x]=x;
         /*}}}  */
         /*{{{  set current-line-pointer to correct saved value*/
         current=p;
         /*}}}  */
       }
       /*}}}  */
       macro_int[mouse_b]=but;
     }
     /*}}}  */
    /*{{{  reset keytab search -> started keysequences are cut*/
    find_current=toplevel[curr_kbd];
    /*}}}  */
    /*{{{  return TOKEN from mouse_but, if valid button, else O_PROMPT*/
    { TOKEN c=O_PROMPT;

      if ((but>=0)&&(but<mouse_number)) c=mouse_mapping[but];
      return(c==O_NOP?O_PROMPT:c);
    }
    /*}}}  */
  }
  /*}}}  */
#endif
