/*{{{  #includes*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#include <local/bool.h>

#define VIEW_MAIN_C

#include "../h/os.h"
#include "../h/keys.h"

#include "viewrc.h"

#define GETRC
#define I_RC_CODE

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

/*{{{  variables*/
/*{{{  prototypes for getopt*/
int getopt(int,char**,char*);
extern char *optarg;
extern int optind;
/*}}}  */
char *filebase="";
FILE *rc;
bool usage=FALSE;
bool std=FALSE;
bool info=FALSE;
/*{{{  fold-marks*/
char fo[tag_length]=begin_standard;
char fc[tag_length]=end_standard;
/*}}}  */
char ctrl_c[]="@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_";
#include "name.h"
/*}}}  */

/*{{{  completebase*/
char *completebase(char *s, char *t)
{
  char *h=getenv(HOME);

  if (!h || *filebase)
    *s='\0';
  else {
    strcpy(s,h);
    strcat(s,PATH_SEP);
  }
  strcat(s,*filebase?filebase:STD_BASENAME);
  strcat(s,t);
  return(s);
}
/*}}}  */
/*{{{  decode_mac*/
/*{{{  get_dec*/
char *get_dec(TOKEN x)
{
  if (x>=O_NOP && x<=O_EXE_MACRO)
    return(dec[x-O_NOP]);
  else if (x>O_EXE_MACRO)
   { static char s[32];

     sprintf(s,"O_CALL_FIX %d",x-O_EXE_MACRO);
     return(s);
   }
  else
    return(M_UNKNOWN);
}
/*}}}  */

bool decode_mac(FILE *f,int lg)
{
  int pc=0;
  TOKEN x;
  bool dopc=TRUE;

  while (lg) {
    /*{{{  show each statement*/
    x=rc_get_w(f);
    lg--;
    if (x==EOF)
      return(TRUE);
    else if (x<O_NOP) {
      /*{{{  normal chars*/
      if (dopc) {
        /*{{{  with pc*/
        if (x>=' ')
          printf(F_NORM_PC,pc,(char) x);
        else
          printf(F_NORM,pc,x);
        dopc=FALSE;
        /*}}}  */
      } else {
        /*{{{  without pc*/
        if (x>=' ')
          printf(F_CHAR,(char) x);
        else
          printf(F_DIGIT,x);
        /*}}}  */
      }
      pc++;
      /*}}}  */
    } else {
      /*{{{  opcodes*/
      COM_TYPES t;

      /*{{{  maybe end string in last line*/
      if (!dopc) {
        printf(M_END_ST);
        dopc=TRUE;
      }
      /*}}}  */
      /*{{{  get commandtyp*/
      if (x<O_NOP || x>O_EXE_MACRO)
         t=COM;
      else
         t=cmd_type[x-O_NOP];
      /*}}}  */
      switch (t) {
        /*{{{  two int args*/
        case COM_II: {
          int x1=rc_get_w(rc);
          int x2=rc_get_w(rc);

          lg-=2;
          printf(F_OP_2_INT,pc,get_dec(x),x1,x2);
          pc+=3;
          break;
        }
        /*}}}  */
        /*{{{  one int arg*/
        case COM_I: {
          lg--;
          printf(F_OP_1_INT,pc,get_dec(x),rc_get_w(rc));
          pc+=2;
          break;
        }
        /*}}}  */
        /*{{{  one char-argument*/
        case COM_C: {
          int x1=rc_get_w(rc);

          lg--;
          if (x1>=' ')
            printf(F_OP_CHAR,pc,get_dec(x),x1);
          else
            printf(F_OP_CODE,pc,get_dec(x),ctrl_c[x1]);
          pc+=2;
          break;
        }
        /*}}}  */
        /*{{{  0/1/2 int + prompt*/
        case COM_IIP:
        case COM_IP:
        case COM_P: {
          if (t==COM_IIP)
           /*{{{  show cmd + 2 ints*/
           { int x1,x2;

             x1=rc_get_w(rc);
             x2=rc_get_w(rc);
             lg-=2;
             pc+=3;
             printf(F_OP_IIP,pc,get_dec(x),x1,x2);
           }
           /*}}}  */
          else if (t==COM_IP)
           /*{{{  show cmd + int*/
           {
             printf(F_PROMPT_START,pc,get_dec(x),rc_get_w(rc));
             lg--;
             pc+=2;
           }
           /*}}}  */
          else
           /*{{{  show cmd*/
           { printf(F_EXIT_START,pc,get_dec(x));
             pc++;
           }
           /*}}}  */
          for (;;)
           /*{{{  show one item of prompt, break on M_END_MACRO or macro/file end*/
           { if (lg)
              /*{{{  get token from macro*/
              { lg--;
                x=rc_get_w(rc);
              }
              /*}}}  */
             else
              /*{{{  break, M_END comes from auto-end!*/
              { printf(">\n");
                break;
              }
              /*}}}  */
             if (x==M_END_MACRO)
              /*{{{  show and break*/
              { pc++;
                printf(F_END_MACRO,get_dec(M_END_MACRO));
                break;
              }
              /*}}}  */
             else if (x==EOF)
              /*{{{  break, error*/
                break;
              /*}}}  */
             else if (x<O_NOP && x>=0)
              /*{{{  show char*/
                printf(F_CHAR,x);
              /*}}}  */
             else if (x<0)
              /*{{{  show message*/
                printf(F_MSG,-x);
              /*}}}  */
             else
              /*{{{  hope, it was counter ?*/
              { printf(F_COUNTER,rc_get_w(rc));
                lg--;
                pc++;
              }
              /*}}}  */
             pc++;
           }
           /*}}}  */
          break;
        }
        /*}}}  */
        /*{{{  adress*/
        case COM_A: {
          int ad=rc_get_w(rc);

          printf(F_OP_ADRESS,pc,get_dec(x),pc+2+ad,ad);
          lg--;
          pc+=2;
          break;
        }
        /*}}}  */
        /*{{{  else only command*/
        case COM: {
          if (x>O_EXE_MACRO)
             printf(F_OP_1_INT,pc,"O_CALL_FIX",x-O_EXE_MACRO);
          else
             printf(F_OP,pc,get_dec(x));
          pc+=1;
          break;
        }
        /*}}}  */
      }
      /*}}}  */
    }
    /*}}}  */
  }
  /*{{{  maybe end string in previous line*/
  if (!dopc) printf(M_END_ST);
  /*}}}  */
  /*{{{  automatic M_END_MACRO (generated in origami when reading rc)*/
  printf(F_AUTO_END,pc,get_dec(M_END_MACRO));
  /*}}}  */
  return(FALSE);
}
/*}}}  */
/*{{{  do_usage*/
void do_usage(void)
{
  printf(M_USAGE);
  exit(0);
}
/*}}}  */

/*{{{  main*/
void main(int argc,char **argv)
{ char rcfile[128];

  /*{{{  parse arguments*/
  { int c;

    while ((c=getopt(argc,argv,"ik:s"))!=EOF)
    switch (c)
     {
       /*{{{  i*/
       case 'i': info=TRUE;break;
       /*}}}  */
       /*{{{  k*/
       case 'k': filebase=optarg;break;
       /*}}}  */
       /*{{{  s*/
       case 's': std=TRUE;break;
       /*}}}  */
       case 'h':
       default:
        do_usage();
     }
    if (argv[optind]) do_usage();
  }
  /*}}}  */
  /*{{{  open .origamirc*/
  if (std)
    rc=stdin;
  else {
    if (!(rc=fopen(completebase(rcfile,"rc"),READ_BIN))) {
      fprintf(stderr,F_NO_RC,filebase);
      exit(1);
    }
  }
  /*}}}  */
  if (info) show_help();
  /*{{{  scan rc-file*/
  {
    int  input;
    int macsize=0;

    rc_get_w(rc);
    while (((input=rc_get_c(rc))!=RC_ENDE)&&(input!=RC_BIND)) {
      /*{{{  handle all rc-commands*/
      switch (input) {
        /*{{{  termalias*/
        case RC_TERMALIAS:
         { char tname[128];
           int ch;
           char *s;

           printf(M_T_ALIAS);
           while ((ch=rc_get_c(rc)) && ch!=EOF)
            { s=tname;
              do *s++=(ch=rc_get_c(rc)); while (ch && ch!=EOF);
              *s='\0';
              printf(F_T1_ALIAS,tname);
            }
           s=tname;
           do *s++=(ch=rc_get_c(rc)); while (ch && ch!=EOF);
           printf(F_T2_ALIAS,tname);
           break;
         }
        /*}}}  */
        /*{{{  keydef*/
        case RC_DEFKEY: {
          int nodes;
          int mark1;
          int mark2;
          int no=0;
          int kb=rc_get_c(rc);
          char kname[128];
          char *x=kname;

          while (*x++ = rc_get_c(rc));
          mark1=rc_get_w(rc);
          mark2=rc_get_w(rc);
          nodes=rc_get_w(rc);
          printf(F_KEY_HEAD,fo,kb,*kname?kname:"default",mark1,mark2,nodes);
          /*{{{  decode the tablenodes*/
          while (nodes--) {
            int co=rc_get_w(rc);
            unsigned char ke=rc_get_c(rc);
            int of1=rc_get_w(rc);
            int of2=rc_get_w(rc);
            char string[11];

            /*{{{  print values of the keytabnode*/
            if (ke==127)
               strcpy(string,"DEL");
            else if (ke>127)
               sprintf(string,"%.3X",ke);
            else if (ke<' ')
             { string[0]='C';
               string[1]='-';
               string[2]=ctrl_c[ke];
               string[4]='\0';
             }
            else
               sprintf(string,"%c  ",ke);
            printf(F_NODE_VALUE,
                   no,
                   ke,
                   string,
                   (of1 ? of1+no : -1),
                   (of2 ? of2+no : -1),
                   co);
            no++;
            /*}}}  */
            /*{{{  maybe print coded command*/
            if (!co)
              printf(M_NEWLINE);
            else if (co==127)
              printf(M_DEL_NODE,co);
            else if (co>=O_NOP)
              printf(M_COM_NODE,co,get_dec(co));
            else if (co>=' ')
              printf(M_CODE_NODE,co,co);
            else
              printf(M_CTRL_NODE,co,ctrl_c[co]);
            /*}}}  */
          }
          /*}}}  */
          printf(F_CLOSE,fc);
          break;
        }
        /*}}}  */
        /*{{{  macrodef/init*/
        case RC_INITMACRO:
        case RC_DEFMACRO: {
          int macro=rc_get_w(rc);
          int lg=rc_get_w(rc);

          macsize+=lg;
          printf(F_MACRO_HEAD,
                 fo,
                 macro,
                 lg+1,
                 (input==RC_INITMACRO ? "init" : "def"));
          if (!decode_mac(rc,lg)) printf("%s\n",fc);
          break;
        }
        /*}}}  */
        /*{{{  keyname*/
        case RC_KEYNAME: {
          int i=keyn_lg;
          char name[keyn_lg];
          char *n=name;

          while (i--) *n++=rc_get_c(rc);
          *n='\0';
          printf(F_NAME,name);
          break;
        }
        /*}}}  */
        /*{{{  sets*/
        case RC_CHARSET: {
          int no,word,off,po;
          char class[256];

          no=rc_get_w(rc);
          no = no/sizeof(Set);
          printf(F_SET_HEAD,fo,no);
          while (no)
           /*{{{  decode one class*/
           { printf(F_SET_NO,--no);
             printf(M_NEWLINE);
             for (word=0;word<sizeof(Set);word++)
              /*{{{  decode a byte*/
              { int byte=rc_get_c(rc);

                for (off=0;off<8;off++)
                 { po=word*8+off;
                   class[po]=(!(byte&(1<<off))?' ':((po>=' ')?po:'X'));
                 }
              }
              /*}}}  */
             /*{{{  print the title-index*/
             printf("    0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF");
             printf(M_NEWLINE);
             /*}}}  */
             for (word=0;word<16;word+=4)
              /*{{{  print line-index and following line-data*/
              { printf("%c-%c ",word+(word<10?'0':'A'-10),
                                word+(word<7 ?'3':'D'-10));
                for (off=0;off<64;off++)
                  printf("%c",class[off+word*16]);
                printf(M_NEWLINE);
              }
              /*}}}  */
             printf(M_NEWLINE);
           }
           /*}}}  */
          printf(F_CLOSE,fc);
          break;
        }
        /*}}}  */
        /*{{{  nostat*/
        case RC_NO_TITLE: {
          printf(M_STAT);
          break;
        }
        /*}}}  */
        /*{{{  usermodestrings*/
        case RC_MODE: {
          int no;
          int lg;
          char *c;
          char buff1[128];
          char buff2[128];


          no=rc_get_c(rc);
          /*{{{  get long*/
          lg=rc_get_w(rc);
          c=buff1;
          while (lg--) *c++=rc_get_c(rc);
          *c='\0';
          /*}}}  */
          /*{{{  get short*/
          lg=rc_get_w(rc);
          c=buff2;
          while (lg--) *c++=rc_get_c(rc);
          *c='\0';
          /*}}}  */
          printf(F_U_MODE,no,buff1,buff2);
          break;
        }
        /*}}}  */
        /*{{{  ints*/
        case RC_INTS:
          printf(F_INTS,rc_get_w(rc));
          break;
        /*}}}  */
        /*{{{  os-extension*/
        case RC_OS_EXTENSION:
          printf(M_OS_EXT);
          printf(" (");
          while ((input=rc_get_c(rc)) && input!=EOF) printf("%c",input);
          printf(")\n");
          break;
        /*}}}  */
        /*{{{  maccount*/
        case RC_MACCOUNT:
          printf(F_MACS,rc_get_w(rc));
          break;
        /*}}}  */
        /*{{{  begin_prompt_macro*/
        case RC_PROMPTIN:
          printf(F_PI_MACRO,rc_get_w(rc));
          break;
        /*}}}  */
        /*{{{  end_prompt_macro*/
        case RC_PROMPTOUT:
          printf(F_PO_MACRO,rc_get_w(rc));
          break;
        /*}}}  */
        /*{{{  auto_macro*/
        case RC_AUTOM:
          printf(F_A_MACRO,rc_get_w(rc));
          break;
        /*}}}  */
        /*{{{  keynotboundmacro*/
        case RC_KNBMAC:
          printf(F_K_MACRO,rc_get_w(rc));
          break;
        /*}}}  */
        /*{{{  viewmacro*/
        case RC_VMAC:
          printf(F_V_MACRO,rc_get_w(rc));
          break;
        /*}}}  */
        /*{{{  abort_macro*/
        case RC_ABORTM:
          printf(F_AB_MACRO,rc_get_w(rc));
          break;
        /*}}}  */
        /*{{{  break*/
        case RC_BREAK: {
          int k=rc_get_c(rc);

          printf(F_BREAK,
                 k,
                 (k>=' ' ? "" : "C-"),
                 (k>=' ' ? k : ctrl_c[k]));
          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(rc);
          name[mark_name_lg-1]='\0';
          /*}}}  */
          printf(F_MARK,name);
          /*{{{  mark*/
          putchar('@');
          putchar(' ');
          for (i=1;i<tag_length;i++)
           { putchar(rc_get_c(rc)); putchar(' '); }
          putchar('$');
          putchar(' ');
          /*}}}  */
          /*{{{  mark*/
          putchar('@');
          putchar(' ');
          for (i=1;i<tag_length;i++)
           { putchar(rc_get_c(rc)); putchar(' '); }
          putchar('$');
          putchar(' ');
          /*}}}  */
          /*{{{  mark*/
          putchar('@');
          putchar(' ');
          for (i=1;i<tag_length;i++)
           { putchar(rc_get_c(rc)); putchar(' '); }
          putchar('$');
          putchar(' ');
          /*}}}  */
          /*{{{  mark*/
          putchar('@');
          putchar(' ');
          for (i=1;i<tag_length;i++)
           { putchar(rc_get_c(rc)); putchar(' '); }
          putchar('$');
          putchar(' ');
          /*}}}  */
          printf(M_NEWLINE);
          break;
        }
        /*}}}  */
        /*{{{  standard-variables*/
        case RC_S_VAR:
         { int t,x,y,l,a;

           t=rc_get_w(rc);
           l=rc_get_w(rc);
           y=rc_get_w(rc);
           x=rc_get_w(rc);
           a=rc_get_w(rc);
           printf(F_S1_VAR,fo);
           printf(F_S2_VAR,t,x,y,l,a);
           printf(F_CLOSE,fc);
           break;
         }
        /*}}}  */
        /*{{{  mouse-vars*/
        case RC_M_VAR: {
          int x,y,b,gy,outs;

          x=rc_get_w(rc);
          y=rc_get_w(rc);
          b=rc_get_w(rc);
          gy=rc_get_w(rc);
          outs=rc_get_w(rc);
          printf(F_M_V1,fo);
          printf(F_M_V2,x,y,gy,outs,b);
          printf(F_CLOSE,fc);
          break;
        }
        /*}}}  */
        /*{{{  mouse-mapping*/
        case RC_M_TAB: {
          int i,j,map;

          printf(F_MO_MAP1,fo);
          for (j=0,i=rc_get_w(rc);i--;j++) {
            map=rc_get_w(rc);
            /*{{{  print it*/
            if (map==127)
              printf(F_MO_DEL,j);
            else if (map>=O_NOP)
              printf(F_MO_OP,j,map,get_dec(map));
            else if (map>=' ')
              printf(F_MO_CHAR,j,map,map);
            else
              printf(F_MO_CTRL,j,map,ctrl_c[map]);
            /*}}}  */
          }
          printf(F_CLOSE,fc);
          break;
        }
        /*}}}  */
        /*{{{  error!*/
        default: {
          printf(F_ERROR,M_LINE,M_TOK,input,M_NODIS);
          fprintf(stderr,M_BAD_DATA);
          exit (1);
        }
        /*}}}  */
      }
      /*}}}  */
    }
    printf(F_MACSIZE,macsize);
    /*{{{  maybe the text-help follows*/
    if (input==RC_BIND) {
      printf(F_HELPHEAD,fo);
      while((input=rc_get_c(rc))!=EOF) printf(F_CHAR,input);
      printf(F_CLOSE,fc);
    }
    /*}}}  */
  }
  /*}}}  */
  if (!std) fclose(rc);
  exit(0);
}
/*}}}  */
