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

#include <sys/types.h>
#include <signal.h>
#include <fcntl.h>
#include <limits.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

#include <local/bool.h>

#define INIT_C
#define I_DISPLAY_C
#define I_FOLDING_C
#define I_GETMSG_C
#define I_GETTK_C
#define I_KEYBOARD_C
#define I_KEYTAB_C
#define I_MAIN_C
#define I_MESSAGES_C
#define I_ORIEDT_C
#define I_PROMPT_C
#define I_SCREEN_C
#define I_SET_C
#define I_SIGNALS_C
#define I_VIRTUAL_C

#include "origami.h"

#define GETRC
#define I_RC_CODE

#include "../h/rcformat.h"
#include "../h/envvar_str.h"
/*}}}  */

/*{{{  variables*/
public char *mark_mode=0;
private char *ori_name=0;
public off_t helpofs=0;
#ifdef NOMEMDUMP
  public char *mem_dump_malloc;
#endif
/*}}}  */

/*{{{  mem_full*/
private void mem_full(void)
{
  oputs((char *)M_NO_MEMORY);
  oputc('\n');
}
/*}}}  */
/*{{{  parse rcfile*/
private bool rc_file_parser(FILE *rcfile)
{
  /*{{{  local vars*/
  int lg;
  int input;
  int var_count=0;
  int tab_var=0;
  int sx_var=0;
  int sy_var=0;
  int cy_var=0;
  char *terminal;
  bool kbd_init[KBD_COUNT];
  /*}}}  */

  /*{{{  terminal=ORITERM | TERM | DEFAULT*/
  if (!(terminal=getenv(ORITERM)) && !(terminal=getenv(TERM)))
#     ifdef DEFAULT_TERM
        terminal=DEFAULT_TERM;
#     else
        terminal=(char*)empty_text;
#     endif
  /*}}}  */
  /*{{{  no keybord is initialised*/
  for (lg=KBD_COUNT;lg--;kbd_init[lg]=FALSE);
  /*}}}  */
  /*{{{  empty user modes*/
  for (lg=MODE_COUNT;lg--;l_modes[lg]=s_modes[lg]=(char*)empty_text);
  /*}}}  */
  /*{{{  little rc-file test*/
  if (rc_get_w(rcfile)!=(O_RETURN+O_EXE_MACRO+O_QUIT)) return(TRUE);
  /*}}}  */
  while (((input=rc_get_c(rcfile))!=RC_ENDE)&&(input!=RC_BIND)) {
    char t_buff[LINELEN+1];

    switch (input) {
      /*{{{  termalias*/
      case RC_TERMALIAS:
       { char tname[LINELEN+1];
         int ch;
         char *s;
         bool found;

         found=FALSE;
         while ((ch=rc_get_c(rcfile)) && ch!=EOF)
          /*{{{  look for a alias*/
          { s=tname;
            do *s++=(ch=rc_get_c(rcfile)); while (ch && ch!=EOF);
            *s='\0';
            if (!strcmp(terminal,tname)) found=TRUE;
          }
          /*}}}  */
         /*{{{  get the replace term*/
         s=tname;
         do *s++=(ch=rc_get_c(rcfile)); while (ch && ch!=EOF);
         /*}}}  */
         if (found) strcpy(terminal=t_buff,tname);
         break;
       }
      /*}}}  */
      /*{{{  keydef*/
      case RC_DEFKEY: {
        int nodes;
        KEY *tp;
        int of;
        int kbd_no;
        KEY *top_level;
        char kname[LINELEN+1];
        char *x=kname;

        kbd_no=rc_get_c(rcfile);
        while (*x++ = rc_get_c(rcfile));
        if (!kbd_init[kbd_no] && (kname[0]=='\0' || !strcmp(kname,terminal)))
         /*{{{  read the table*/
         { kbd_init[kbd_no]=TRUE;
           bind_mark[kbd_no][0]=rc_get_w(rcfile);
           bind_mark[kbd_no][1]=rc_get_w(rcfile);
           /*{{{  get space for table*/
           nodes=rc_get_w(rcfile);
           if ((top_level=tp=(KEY*)malloc(nodes*sizeof(KEY)))==(KEY*)0) {
             mem_full();
             return(TRUE);
           }
           /*}}}  */
           /*{{{  read all nodes*/
           while (nodes--) {
             tp->code=rc_get_w(rcfile);
             tp->key=rc_get_c(rcfile);
             /*{{{  read offsets and buildt pointers*/
             of=rc_get_w(rcfile);
             if (of) tp->next=tp+of; else tp->next=(KEY*)0;
             of=rc_get_w(rcfile);
             if (of) tp->n_level=tp+of; else tp->n_level=(KEY*)0;
             tp++;
             /*}}}  */
           }
           /*}}}  */
           set_key_top(top_level,kbd_no);
         }
         /*}}}  */
        else
         /*{{{  don't read*/
         { rc_get_w(rcfile);
           rc_get_w(rcfile);
           nodes=rc_get_w(rcfile);
           while (nodes--){ rc_get_w(rcfile);rc_get_c(rcfile);rc_get_w(rcfile);rc_get_w(rcfile); }
         }
         /*}}}  */
        break;
      }
      /*}}}  */
      /*{{{  usermodestrings*/
      case RC_MODE: {
        int no=rc_get_c(rcfile);
        int size=1;

        do
         { int lg;
           char *c;

           lg=rc_get_w(rcfile);
           if (!(c=malloc(lg+2))) { mem_full();return(TRUE); }
           if (size) l_modes[no]=c; else s_modes[no]=c;
           *c++=comma;
           while (lg--) *c++=rc_get_c(rcfile);
           *c='\0';
         }
        while (size-->0);
        break;
      }
      /*}}}  */
      /*{{{  macrodef/init*/
      case RC_INITMACRO:
      case RC_DEFMACRO: {
        TOKEN *x;
        int macro;

        if (!fix_macros) return(TRUE);
        macro=rc_get_w(rcfile);
        if (macro>fix_m_count) return(TRUE);
        lg=rc_get_w(rcfile);
        fix_macros[macro].defineable=(input==RC_INITMACRO);
        if (lg) {
          if (!(x=fix_macros[macro].string=(TOKEN*)malloc((1+lg)*sizeof(TOKEN))))
           { mem_full();return(TRUE);}
          while (lg--) *x++=rc_get_w(rcfile);
          *x=M_END_MACRO;
        }
        break;
      }
      /*}}}  */
      /*{{{  keyname*/
      case RC_KEYNAME: {
        int i=keyn_lg;
        char *n=keybinding_name;

        while (i--) *n++=rc_get_c(rcfile);
        *n='\0';
        break;
      }
      /*}}}  */
      /*{{{  maccount*/
      case RC_MACCOUNT:
       { int i=rc_get_w(rcfile);

         fix_m_count=i;
         if (!(fix_macros=(macro_entry*)malloc( MAX_MACRO_LENGTH*sizeof(TOKEN)
                                               +(1+i)*sizeof(macro_entry))))
          { mem_full(); return(TRUE); }
         /*{{{  clear all buffers*/
         for
          ( i++;
            i--;
            fix_macros[i].defineable=TRUE,fix_macros[i].string=empty_macro
          );
         /*}}}  */
         fix_macros[0].string=(TOKEN*)(fix_macros+fix_m_count+1);
         break;
       }
      /*}}}  */
      /*{{{  ints*/
      case RC_INTS:
        var_count=input=rc_get_w(rcfile);
        if (!(macro_int=(int*)calloc(input,sizeof(int)))) {
          mem_full();
          return(TRUE);
        }
        break;
      /*}}}  */
      /*{{{  os-extension*/
      case RC_OS_EXTENSION:
#         ifdef RC_OS_EXT_HANDLE
            RC_OS_EXT_HANDLE(rcfile);
#         else
            while (input=rc_get_c(rcfile) && input!=EOF);
#         endif
         break;
      /*}}}  */
      /*{{{  standard-variables*/
      case RC_S_VAR:
        tab_var=rc_get_w(rcfile);
        cy_var=rc_get_w(rcfile);
        sy_var=rc_get_w(rcfile);
        sx_var=rc_get_w(rcfile);
        ocl_arg=rc_get_w(rcfile);
        break;
      /*}}}  */
      /*{{{  sets*/
      case RC_CHARSET:
        if (init_set(rcfile)) return(TRUE);
        break;
      /*}}}  */
      /*{{{  nostat*/
      case RC_NO_TITLE:
        no_title=1;
        break;
      /*}}}  */
      /*{{{  auto_macro*/
      case RC_AUTOM:
        auto_macro=rc_get_w(rcfile);
        break;
      /*}}}  */
      /*{{{  abort_macro*/
      case RC_ABORTM:
        ab_macro=rc_get_w(rcfile);
        break;
      /*}}}  */
      /*{{{  knb_mac*/
      case RC_KNBMAC:
        knb_mac=rc_get_w(rcfile);
        break;
      /*}}}  */
      /*{{{  v_mac*/
      case RC_VMAC:
        v_mac=rc_get_w(rcfile);
        break;
      /*}}}  */
      /*{{{  promptin*/
      case RC_PROMPTIN:
        p_in_m=rc_get_w(rcfile);
        break;
      /*}}}  */
      /*{{{  promptout*/
      case RC_PROMPTOUT:
        p_out_m=rc_get_w(rcfile);
        break;
      /*}}}  */
      /*{{{  break*/
      case RC_BREAK: {
        general_abort_key=rc_get_c(rcfile);
        break;
      }
      /*}}}  */
      /*{{{  marks*/
      case RC_MARKS: {
        char name[mark_name_lg];
        int i;

        /*{{{  read stored name*/
        for (i=0;i<(mark_name_lg-1);i++)
          name[i]=rc_get_c(rcfile);
        name[mark_name_lg-1]='\0';
        /*}}}  */
        if (mark_mode && !strcmp(mark_mode,name)) {
          /*{{{  reset mark-strings*/
          mark_mode=0;
          for (i=0;i<(tag_length-1);i++) fold_open_str[i]=rc_get_c(rcfile);
          for (i=0;i<(tag_length-1);i++) fold_line_str[i]=rc_get_c(rcfile);
          for (i=0;i<(tag_length-1);i++) fold_file_str[i]=rc_get_c(rcfile);
          for (i=0;i<(tag_length-1);i++) fold_close_str[i]=rc_get_c(rcfile);
          /*}}}  */
        } else
          /*{{{  overread the data*/
          for (i=0;i<(4*(tag_length-1));i++,rc_get_c(rcfile));
          /*}}}  */
        break;
      }
      /*}}}  */
      /*{{{  mouse-vars*/
      case RC_M_VAR:
#         ifdef MOUSY
          /*{{{  set mouse-vars*/
            mouse_x=rc_get_w(rcfile);
            mouse_y=rc_get_w(rcfile);
            mouse_b=rc_get_w(rcfile);
            mouse_go_y=rc_get_w(rcfile);
            mouse_outside=rc_get_w(rcfile);
          /*}}}  */
#         else
          /*{{{  overread the information*/
            rc_get_w(rcfile);
            rc_get_w(rcfile);
            rc_get_w(rcfile);
            rc_get_w(rcfile);
            rc_get_w(rcfile);
          /*}}}  */
#         endif
         break;
      /*}}}  */
      /*{{{  mouse-tab*/
      case RC_M_TAB:
      {
        mouse_number=rc_get_w(rcfile);
#        ifdef MOUSY
          /*{{{  read the bindings*/
          if ((mouse_mapping=(TOKEN*)malloc(mouse_number*sizeof(TOKEN)))==(TOKEN*)0)
          {
            mem_full();
            return(TRUE);
          }
          else
          {
            int i;

            for (i=0; i<mouse_number; mouse_mapping[i++]=rc_get_w(rcfile));
          }
          /*}}}  */
#        else
          /*{{{  overread the bindings*/
            for (; mouse_number--; rc_get_w(rcfile));
          /*}}}  */
#        endif
        break;
      }
      /*}}}  */
      /*{{{  error!*/
      default: return(TRUE);
      /*}}}  */
    }
  }
  /*{{{  store this end for bindhelp*/
  helpofs=ftell(rcfile);
  /*}}}  */
#  ifdef MOUSY
    /*{{{  check correct mouse-variables*/
    if (   mouse_x>=var_count
        || mouse_y>=var_count
        || mouse_b>=var_count
    ) return(TRUE);
    /*}}}  */
#  endif
  /*{{{  if marks needed and not found -> error*/
  if (mark_mode) {
    oputs((char *)get_msg(M_NO_MARKS));
    return(TRUE);
  }
  /*}}}  */
  /*{{{  if no macro-info given -> error*/
  if (!fix_macros) return(TRUE);
  /*}}}  */
  /*{{{  set standard-vars*/
  *(tab_size=macro_int+tab_var)=hard_tab>0?hard_tab:0;
  cy_ptr=macro_int+cy_var;
  sy_ptr=macro_int+sy_var;
  sx_ptr=macro_int+sx_var;
  macro_int[ocl_arg]=dialect;
  dialect=F_C_NONE;
  /*}}}  */
  return(FALSE);
}
/*}}}  */
/*{{{  open_sysfile*/
public char *open_sysfile(char *ending)
{ static char keyfile[_POSIX_PATH_MAX+1];
  char *base=rc_name ? rc_name
                     : (char*)get_msg(M_BASE_FORMAT,(unsigned char*)ori_name);

  /*{{{  try base-ending*/
  strcpy(keyfile,base);
  strcat(keyfile,ending);
  if (access(keyfile,R_OK)==0) return(keyfile);
  /*}}}  */
#  ifdef HOMERC
   /*{{{  try $HOME/base-ending*/
   {
     /*{{{  get home*/
     { char *h;

       if ((h=getenv(HOME))==(char*)0) {
         oputs((char*)M_NO_HOME);
         keyfile[0]='\0';
         return(keyfile);
       }
       strcpy(keyfile,h);
     }
     /*}}}  */
     strcat(keyfile,PATH_SEP);
     strcat(keyfile,base);
     strcat(keyfile,ending);
     if (access(keyfile,R_OK)==0) return(keyfile);
   }
   /*}}}  */
#  endif
#  ifdef ORIGAMI_PATH
   /*{{{  try sysdir/base-ending*/
   { strcpy(keyfile,ORIGAMI_PATH);
     strcat(keyfile,PATH_SEP);
     strcat(keyfile,base);
     strcat(keyfile,ending);
     if (access(keyfile,R_OK)==0) return(keyfile);
   }
   /*}}}  */
   /*{{{  for msg, try standard in ORIGAMI_PATH/STD_BASENAMEmsg*/
   { if (ending==M_MSGSTR)
      { strcpy(keyfile,ORIGAMI_PATH);
        strcat(keyfile,PATH_SEP);
        strcat(keyfile,STD_BASENAME);
        strcat(keyfile,ending);
        if (access(keyfile,R_OK)==0) return(keyfile);
      }
   }
   /*}}}  */
#  endif
  keyfile[0]='\0';

  return(keyfile);
}
/*}}}  */
/*{{{  HostBegin*/
public int HostBegin(char *program)
{
  /*{{{  maybe get storage for memdump*/
#  ifdef NOMEMDUMP
    if ((mem_dump_malloc=malloc(NOMEMDUMP))==(char*)0) {
      mem_full();
      return(1);
    }
#  endif
  /*}}}  */
  /*{{{  maybe generate keybase with argv[0]*/
  if (!rc_name)
   { ori_name=program;

     while (*program) if(*(program++)==PATH_C) ori_name=program;
   }
  /*}}}  */
  /*{{{  read messages*/
  { char *x=open_sysfile(M_MSGSTR);

    if (*x && (msg_file=open(x,O_RDONLY),TEST_CHAR==(get_msg(T_TEST))[0]))
     /*{{{  get prompts.. from msg-file*/
     { NO=get_msg(I_NO)[0];
       YES=get_msg(I_YES)[0];
       AB=get_msg(I_AB)[0];
       DO_AB=get_msg(I_DO_AB)[0];
       DO_REST=get_msg(I_DO_REST)[0];
       comma=get_msg(D_COMMA)[0];
       eoln_str=get_msg(D_EOLN)[0];
     }
     /*}}}  */
    else
     { oputs((char *)M_UN_MES);oputc('\n');return(1); }
  }
  /*}}}  */
  /*{{{  parse rc*/
  { char *x=open_sysfile(M_RCSTR);
    FILE *rcfile;

    if (!*x)
     /*{{{  complain and return 1*/
     { oputs((char*)get_msg(M_CANTOPEN));
       oputc(' ');
       oputs((char*)get_msg(M_RF));
       oputc('\n');
       return(1);
     }
     /*}}}  */
    rcfile=fopen(x,READ_BIN);
    if (rc_file_parser(rcfile))
     /*{{{  complain and return 1*/
     { oputs((char *)get_msg(M_NO_KTAB));return(1); }
     /*}}}  */
    fclose(rcfile);
  }
  /*}}}  */
  /*{{{  init keyboard and screen*/
  if (get_terminal_capability()) return(1);
  init_keyboard();
  init_signals();
  if (sg || xs || !(so && se)) inv_ctrl=FALSE;
  /*}}}  */
  return (0);
}
/*}}}  */
/*{{{  initialise links in editor*/
public void initialise(void)
{
  static element null_element;

  null_item_ptr = dispose_tail = dispose_head = &null_element;
  new_data(&null_element);
  null_item_ptr->foldline = NOT_FOLD;
  null_item_ptr->UU.U1.indent = 0;
  null_item_ptr->UU.U1.fold_indent = 0;
  null_item_ptr->fold = 0;
  null_item_ptr->UU.U1.fold_type = 0;
  null_item_ptr->UU.U1.fold_contents = 1;
  null_item_ptr->fold_close_line = 4;
  real_tail = real_head;
  proc_new(&new_file_ptr);
  proc_new(&pick_head);
  pick_tail = pick_head;
}
/*}}}  */
