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

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

#define GETTK_C
#define I_BUFFLOOP_C
#define I_LOOP_C
#define I_SET_C
#define I_DISPLAY_C
#define I_FIELDEDIT_C
#define I_FINDS_C
#define I_FOLDING_C
#define I_FOLDFILING_C
#define I_GETMSG_C
#define I_INIT_C
#define I_KEYBOARD_C
#define I_KEYTAB_C
#define I_MAIN_C
#define I_MESSAGES_C
#define I_MISC_C
#define I_ORIEDT_C
#define I_PROMPT_C
#define I_SCREEN_C
#define I_SIGNALS_C
#define I_VIRTUAL_C

#include "origami.h"
#include <lib/ori_add_lib.h>
/*}}}  */

/*{{{  vars*/
public TOKEN const *macro_pos;
public boolean defining_macro=False;
private boolean prompting=False;
private int argument=0;
private int macro_count;

public int bind_const[RCC_SIZE];
public TOKEN const empty_macro[]={M_END_MACRO};
public TOKEN a_f_mac[]={ O_FLUSH,(TOKEN)0,M_END_MACRO };
public macro_entry const *fix_macros=0;
public boolean macro_tag;
public boolean run_abort_mac=False;
public int executing_macro=0;
public int scr_off=0;
public stackent *ocl_var=0;
/*}}}  */

/*{{{  OCL stack             push/pop int or adresses for OCL stack*/
/*{{{  variables*/
#define STACK_BLOCK 16

private stackent *ocl_stack=0;
private int ocl_stack_size=0;
/*}}}  */

/*{{{  check_stack           maybe make stack bigger*/
private boolean check_stack(void)
{
  if (ocl_stack_size-1<=executing_macro)
   /*{{{  expand it*/
   { stackent *ns;

     if (!(ns=ori_malloc((ocl_stack_size+STACK_BLOCK)*sizeof(stackent))))
      { msg_message(M_B_NO_MEMORY);
        return(True);
      }
     if (ocl_stack)
      /*{{{  copy and free*/
      { memcpy(ns,ocl_stack,ocl_stack_size*sizeof(stackent));
        paket_free(ocl_stack);
      }
      /*}}}  */
     ocl_stack=ns;
     ocl_stack_size+=STACK_BLOCK;
   }
   /*}}}  */
  return(False);
}
/*}}}  */
/*{{{  push                  push on stack*/
#define push(val) \
   (check_stack()?True:(ocl_stack[executing_macro++]=(val),False))
/*}}}  */
/*{{{  push_el               push typed on stack*/
#define push_el(val,type) \
   (check_stack()?True:(ocl_stack[executing_macro++].type=(val),False))
/*}}}  */
/*{{{  push_tp               push adress*/
#define push_tp(a) push_el((a),tp)
/*}}}  */
/*{{{  push_v                push int*/
#define push_v(val) push_el((val),v)
/*}}}  */
/*{{{  push_l                push line*/
#define push_l(line) push_el((line),l)
/*}}}  */
/*{{{  pop_check             check, if pop can be done*/
#define pop_check()                                                           \
 ( (executing_macro<=0)                                                       \
     ? (exit_origami(r_ocl_err,get_msg(F_INT_OCL,STR_POP_EMPTY_STACK,0)),0)   \
     : 0)
/*}}}  */
/*{{{  pop                   pop from stack*/
#define pop() (pop_check(),ocl_stack[--executing_macro])
/*}}}  */
/*{{{  pop_el                pop typed from stack*/
#define pop_el(type) (pop_check(),ocl_stack[--executing_macro].type)
/*}}}  */
/*{{{  pop_tp                pop adress*/
#define pop_tp() pop_el(tp)
/*}}}  */
/*{{{  pop_v                 pop int*/
#define pop_v() pop_el(v)
/*}}}  */
/*{{{  pop_l                 pop line*/
#define pop_l() pop_el(l)
/*}}}  */
/*}}}  */

/*{{{  ori_abort             set tags for signal interrupt*/
public void ori_abort(int sig)
{ static int handle=False;

  if (!running || handle++)
     return;
  signal(SIGINT, SIG_IGN);
  if (defining_macro)
   { defining_macro=False;
     title_op(CHGTITLE);
   }
  aborted=True;
  if (sig==SIGINT && redraw_on_sig)
     interrupt_restore=True;
  ocl_msg("aborted %d",sig);
  signal(SIGINT, ori_abort);
  handle=0;
}
/*}}}  */
/*{{{  stop_macros           stop macro-execution at correct point*/
public void stop_macros(boolean full)
{
  if (full)
   { int i;

     argument=0;
     for (i=1;i<=mac_count;i++)
        unload_demand(i);
   }
  if (!argument)
     disable_abort();
  executing_macro=0;
  macro_pos=fix_macros[0].mac.txt;
}
/*}}}  */
/*{{{  push_macro            push a macro-call on the stack*/
public boolean push_macro(TOKEN const * const to)
{
  ocl_msg("push macro %d",(int)to);
  if (push_tp(macro_pos))
     return(True);
  if (!argument && executing_macro==1)
     enable_abort();
  macro_pos=to;

  return(False);
}
/*}}}  */
/*{{{  push_str_macro        create a macro from a string*/
public TOKEN const *push_str_macro(unsigned char const *s)
{
  /*{{{  use 2 buffers, to handle view-macro properly*/
  static TOKEN *dm_buff[2]={ 0,0 };
  static int dm_lg[2]={ 0,0 };
  static int dm_used=0;
  /*}}}  */
  int l;
  TOKEN *t;

  dm_used^=1;
  if ((l=ustrlen(s))==0)
     return(empty_macro);
  if (l>=dm_lg[dm_used])
   /*{{{  new macro place*/
   { if (dm_lg[dm_used])
        paket_free(dm_buff[dm_used]);
     dm_lg[dm_used]=
        (dm_buff[dm_used]=ori_malloc((l+3)*sizeof(TOKEN))) ? l : 0;
   }
   /*}}}  */
  if ((t=dm_buff[dm_used]))
   /*{{{  copy string*/
   { if (push_macro(t))
        return(0);
     while ((*t = *s++)) t++;
     /*{{{  append M_ASCII -1, to switch back the used buffer!*/
     *t++=M_ASCII;
     *t++= -1;
     /*}}}  */
     *t++=M_END_MACRO;
   }
   /*}}}  */

  return(dm_buff[dm_used]);
}
/*}}}  */
/*{{{  auto_flush            push flush-call on macro-stack*/
public void auto_flush(void)
{
  ocl_msg("auto_flush",0);
  dirty=False;
  push_macro(a_f_mac);
}
/*}}}  */
/*{{{  get_arg               get a int-Argument from macro-buffer*/
public TOKEN get_arg(char const * const s)
{
  if (!executing_macro)
   { ocl_msg("getarg without macro!",0);
     ori_abort(~SIGINT);
     return(0);
   }
  ocl_get_arg_dbg(*macro_pos,s);

  return(*macro_pos++);
}
/*}}}  */
/*{{{  get_arg_fixed         get a int-Argument from macro-buffer or opcode*/
public TOKEN get_arg_fixed(int d,char const * const s)
{
  return((d!=-RANGE_ADD)?d:get_arg(s));
}
/*}}}  */
/*{{{  call_number_macro     call macro with given number*/
public void call_number_macro(int mno)
{
  TOKEN const *c;

  ocl_msg("call number macro %d",mno);
  if (mno && (c=load_demand(mno)) && c!=empty_macro)
     push_macro(c);
}
/*}}}  */
/*{{{  def_mac_handle        maybe store the given token in the kbdmacro*/
private void def_mac_handle(TOKEN const ch)
{
  if (defining_macro && ch!=O_DEF_MACRO)
   { ((TOKEN*)fix_macros[0].mac.txt)[macro_count]=ch;
     if (macro_count<MAX_MACRO_LENGTH-1)
        macro_count++;
     else
      /*{{{  full*/
      { warn_message(get_msg(M_KEY_BUFF_FULL));
        ((TOKEN*)fix_macros[0].mac.txt)[macro_count]=M_END_MACRO;
        ocl_msg("macro buff full",0);
        ori_abort(~SIGINT);
      }
      /*}}}  */
   }
}
/*}}}  */
/*{{{  prompt_string         generate the correct string from macro*/
public void prompt_string(unsigned char *s)
{
  TOKEN read;
  unsigned char c[2];
  int lg;

  for (c[1]='\0',lg=LINELEN;(read=get_arg("string"))!=M_END_MACRO;)
   { unsigned char *x;

     /*{{{  get current append string*/
     if (read==M_GET_HISTORY)
      /*{{{  get history x 0*/
         access_history(0,get_arg("string-hist"),False,(int*)0,&x);
      /*}}}  */
     else if (read==M_INT_STRING)
      /*{{{  itoa*/
        x=i_to_ua(ocl_var[get_arg("string-counter")].v);
      /*}}}  */
     else if (read<-MSG_ARG_FORMAT)
      /*{{{  rc_msg*/
        x=rc_msg[-read-MSG_ARG_FORMAT-1];
      /*}}}  */
     else if (read<0)
      /*{{{  msg-msg*/
        x=get_msg
           ( -read,
             empty_text,
             empty_text,
             empty_text,
             empty_text,
             empty_text,
             empty_text
           );
      /*}}}  */
     else
      /*{{{  single char*/
      { c[0]=read;
        x=c;
      }
      /*}}}  */
     /*}}}  */
     /*{{{  copy it*/
     while (lg-->0 && (*s= *x++)) s++;
     /*}}}  */
   }
  *s='\0';
}
/*}}}  */
/*{{{  single_key            get a token*/
/*{{{  forward declaration for internal_hide_key*/
private TOKEN internal_hide_key(boolean);
/*}}}  */

private TOKEN single_key(boolean hide)
{
  static TOKEN rep_token=O_NOP;
  static int set_argument= -1;
  TOKEN ch;

  do
   { scan_abort_key();
     /*{{{  get next token*/
     if (aborted)
      /*{{{  O_BREAK*/
      { if (executing_macro)
           stop_macros(True);
        ch=O_BREAK;
      }
      /*}}}  */
     else if (executing_macro)
      /*{{{  get from macro-string*/
        ch= *macro_pos++;
      /*}}}  */
     else
      /*{{{  get from keyboard*/
      { if (argument)
         /*{{{  handle repeating*/
         { ch=rep_token;
#          ifdef USE_SCR_BUFF
              if ((argument>ARG_FL_COUNT)&&((argument%ARG_FL_COUNT)==0))
               { ocl_msg("arg-rep auto-flush",0);
                 oflush;
               }
#          endif
           if (!(--argument))
              disable_abort();
         }
         /*}}}  */
        else if (set_argument>=0)
         /*{{{  end repeating*/
         { set_argument= -1;
           disable_abort();
           return(O_PROMPT);
         }
         /*}}}  */
        else
         /*{{{  read from keyboard*/
         { def_mac_handle(ch = get_key()); }
         /*}}}  */
        if (dirty)
           auto_flush();
      }
      /*}}}  */
     ocl_debug(executing_macro,ch);
     /*{{{  M_ASCII*/
     if (ch==M_ASCII)
      { int v;

        v=get_arg("insert-ascii");
        if (v>=0)
         /*{{{  use value from ocl-var*/
           ch=ocl_var[v].v;
         /*}}}  */
        else
         /*{{{  use rc-msg*/
         { if
            ( !push_str_macro
                ( (v==-1)
                    ? (unsigned char*)empty_text
                    : rc_msg[-v-MSG_ARG_FORMAT-1]
                )
            )
              ori_abort(~SIGINT);
           continue;
         }
         /*}}}  */
      }
     /*}}}  */
     /*}}}  */
     /*{{{  check correct char*/
     if (ch!=O_NOP)
      { chartest;
        if (ch==O_NOP)
         { if (knb_macro)
              call_number_macro(knb_macro);
           if (echo_active)
              msg_message(M_NOT_BOUND);
           return(O_PROMPT);
         }
      }
     /*}}}  */
     if (ch<O_EXE_MACRO && ch>0)
       /*{{{  normal commands*/
       { switch (ch) {
           /*{{{  M_ECHO_I*/
           case M_ECHO_I:
              send_terminal(ocl_var[get_arg("send-term")].v);
              flush_terminal();
              continue;
           /*}}}  */
           /*{{{  M_ECHO_P*/
           case M_ECHO_P:
            { unsigned char prompt[LINELEN+1];

              prompt_string(prompt);
              send_s_terminal(prompt);
              flush_terminal();
              continue;
            }
           /*}}}  */
           /*{{{  M_ENV_CMD*/
           case M_ENV_CMD:
            { unsigned char prompt[LINELEN+1];
              int t;

              t=get_arg("environ-cmd-type");
              prompt_string(prompt);
              switch(t)
               {
                 /*{{{  test TERM==prompt*/
                 case 0:
                    macro_tag=check_terminal((char*)prompt);
                    break;
                 /*}}}  */
                 /*{{{  getenv*/
                 case 1:
                  { char *e;

                    e=getenv((char*)prompt);
                    if (e && *e && !push_str_macro((unsigned char*)e))
                       ori_abort(~SIGINT);
                    break;
                  }
                 /*}}}  */
               }
              break;
            }
           /*}}}  */
           /*{{{  M_FOLD_DATA*/
           case M_FOLD_DATA:
              switch (get_arg("fold-comment-argtype"))
               {
                 /*{{{  0=start-length*/
                 case 0:
                    ocl_var[get_arg("fold-comment-start-length-dest")].v=
                       dialects[bd.m.dialect.typ].lg.start;
                    break;
                 /*}}}  */
                 /*{{{  2=end-length*/
                 case 2:
                    ocl_var[get_arg("fold-comment-end-length-dest")].v=
                       dialects[bd.m.dialect.typ].lg.end;
                    break;
                 /*}}}  */
                 /*{{{  1/3=start/end-data,4/5/6/7=mark-data*/
                 { unsigned char const *s;

                   case 1:
                    /*{{{  use start string*/
                      s=dialects[bd.m.dialect.typ].txt.start;
                      goto fold_data_main;
                    /*}}}  */
                   case 3:
                    /*{{{  use end string*/
                      s=dialects[bd.m.dialect.typ].txt.end;
                      goto fold_data_main;
                    /*}}}  */
                   case 4:
                    /*{{{  use fold-begin string*/
                      s=bd.f.str.open_f;
                      goto fold_data_main;
                    /*}}}  */
                   case 5:
                    /*{{{  use fold-end string*/
                      s=bd.f.str.close_f;
                      goto fold_data_main;
                    /*}}}  */
                   case 6:
                    /*{{{  use fold-file string*/
                      s=bd.f.str.file_f;
                      goto fold_data_main;
                    /*}}}  */
                   case 7:
                    /*{{{  use fold-file string*/
                      s=bd.f.str.line_f;
                      goto fold_data_main;
                    /*}}}  */
                   fold_data_main:
                    { int o;

                      o=ocl_var[get_arg("fold-comment-xxx offset")].v;
                      push_v((ustrlen(s)>=o && o>=0)?s[o]:0);
                      break;
                    }
                 }
                 /*}}}  */
                 default:
                    break;
               }
              break;
           /*}}}  */
           /*{{{  M_EXIT*/
           case M_EXIT:{
            unsigned char string[LINELEN+1];

            prompt_string(string);
            if (string[0])
               message(string);
            stop_macros(False);
            break;
           }
           /*}}}  */
           /*{{{  M_SCREEN_OFF*/
           case M_SCREEN_OFF:
             ocl_screen_off();
             continue;
           /*}}}  */
           /*{{{  M_SCREEN_ON*/
           case M_SCREEN_ON:
             ocl_screen_on();
             if (bd.m.upd_sel_delayed)
                upd_highlight(bd.f.real_head,bd.f.real_tail,True);
             continue;
           /*}}}  */
           /*{{{  M_LASTMES*/
           case M_LASTMES:
            { if ((macro_tag=((msgtyp)get_arg("last-message")==last_message)))
                 last_message=M_BASE_FORMAT;
              continue;
            }
           /*}}}  */
           /*{{{  M_GET_BUFFER*/
           case M_GET_BUFFER:
            { int x;
              int y;

              x=ocl_var[get_arg("get-buffer-x")].v;
              y=ocl_var[get_arg("get-buffer-y")].v;
              push_v(decode_buffer_mouse(x,y,False));
              break;
            }
           /*}}}  */
           /*{{{  M_GET_HISTORY*/
           case M_GET_HISTORY:
            { unsigned char *s;
              histories old_default;
              int off;

              old_default=overwrite_history_id;
              overwrite_history_id=(histories)get_arg("get-history");
              off=ocl_var[get_arg("get-h-offset")].v;
              access_history(off,overwrite_history_id,False,(int*)0,&s);
              overwrite_history_id=old_default;
              if (!push_str_macro(s))
                 ori_abort(~SIGINT);
              continue;
            }
           /*}}}  */
           /*{{{  M_LOAD_MAC*/
           case M_LOAD_MAC:
            { boolean in;
              int no;

              in=get_arg("load type")!=0;
              no=get_arg("unload arg");
              no=((no<0)?-no:ocl_var[no].v)-O_EXE_MACRO;
              if (in)
                 load_demand(no);
              else
                 unload_demand(no);
              continue;
            }
           /*}}}  */
           /*{{{  M_STORE_LINE_NO*/
           case M_STORE_LINE_NO:
            { int ind=get_arg("store-line-target");

              ocl_var[ind].v=bd.f.current?cur_line_no():0;
              continue;
            }
           /*}}}  */
           /*{{{  M_STORE_MARK*/
           case M_STORE_MARK:
            { int ind=get_arg("store-line-mark-target");

              ocl_var[ind].l=bd.f.current;
              continue;
            }
           /*}}}  */
           /*{{{  M_END_MACRO*/
           case M_END_MACRO:
              macro_pos=pop_tp();
              if (!executing_macro && !argument)
               { disable_abort();
                 run_abort_mac=False;
               }
              if (!executing_macro && !hide)
                 return(O_PROMPT);
              continue;
           /*}}}  */
           /*{{{  M_SET_COPY*/
           case M_SET_COPY:
            { int to=get_arg("set-copy-to");
              int from=get_arg("set-copy-from");

              set_copy(to,from);
              continue;
            }
           /*}}}  */
           /*{{{  M_SHOW_CURSOR*/
           case M_SHOW_CURSOR:
              restore_cursor_and_sleep(ocl_var[get_arg("delay")].v);
              continue;
           /*}}}  */
           /*{{{  M_EDITING*/
           case M_EDITING: {
             macro_tag=prompting;
             continue;
           }
           /*}}}  */
           /*{{{  M_CALL*/
           CASES_M_CALL
           case M_CALL: {
             int offset=get_arg_fixed(ch-M_CALL_0,"adress");

             if (push_macro(macro_pos+offset))
                break;
             continue;
           }
           /*}}}  */
           /*{{{  M_CHANGED*/
           case M_CHANGED: {
             macro_tag=(bd.m.file_changed_status!=unchanged_file);
             continue;
           }
           /*}}}  */
           /*{{{  M_FILETYP*/
           case M_FILETYP: {
             ocl_var[get_arg("FILE-target")].v=
                                   !bd.m.dir_edit             ?  0 :
                                  *(get_data(bd.f.real_tail)) ?  1 :
                                                                -1 ;
             continue;
           }
           /*}}}  */
           /*{{{  M_TEST_HASH*/
           case M_TEST_HASH: {
             macro_tag=bd.m.hash_shift;
             continue;
           }
           /*}}}  */
           /*{{{  M_TEST_OVER*/
           case M_TEST_OVER: {
             macro_tag=bd.m.overwrite;
             continue;
           }
           /*}}}  */
           /*{{{  M_TEST_AUTO*/
           case M_TEST_AUTO: {
             macro_tag=auto_save;
             continue;
           }
           /*}}}  */
           /*{{{  M_TEST_VERBOSE*/
           case M_TEST_VERBOSE:
              macro_tag=verbose;
              continue;
           /*}}}  */
           /*{{{  M_TEST_VIEW*/
           case M_TEST_VIEW: {
             macro_tag=bd.m.read_only;
             continue;
           }
           /*}}}  */
           /*{{{  M_TEST_ECHO*/
           case M_TEST_ECHO: {
             macro_tag=echo_active;
             continue;
           }
           /*}}}  */
           /*{{{  M_HISTORY*/
           case M_HISTORY:
               overwrite_history_id=(histories)get_arg("switch-history");
               continue;
           /*}}}  */
           /*{{{  O_UNCHANGE*/
           case O_UNCHANGE:
              if (bd.m.file_changed_status!=unchanged_file)
               { bd.m.file_changed_status=unchanged_file;
                 title_op(CHGTITLE);
               }
              no_message();
              break;
           /*}}}  */
           /*{{{  M_JMP*/
           CASES_M_JMP
           case M_JMP: {
             int diff;

             diff=get_arg_fixed(ch-M_JMP_0,"jmp-offset");
             macro_pos+=diff;
             continue;
           }
           /*}}}  */
           /*{{{  M_JMP_FALSE*/
           CASES_M_JMP_FALSE
           case M_JMP_FALSE: {
             int diff;

             diff=get_arg_fixed(ch-M_JMP_FALSE_0,"jpf-offset");
             if (!macro_tag) macro_pos+=diff;
             continue;
           }
           /*}}}  */
           /*{{{  M_JMP_TRUE*/
           CASES_M_JMP_TRUE
           case M_JMP_TRUE:
            { int diff;

              diff=get_arg_fixed(ch-M_JMP_TRUE_0,"jpt-offset");
              if (macro_tag)
                 macro_pos+=diff;
              continue;
            }
           /*}}}  */
           /*{{{  M_NOT*/
           case M_NOT: {
             macro_tag=!macro_tag;
             continue;
           }
           /*}}}  */
           /*{{{  M_LANGUAGE*/
           case M_LANGUAGE:
              macro_tag=(dialects[bd.m.dialect.typ].name[0]==get_arg("language"));
              continue;
           /*}}}  */
           /*{{{  M_TEXTLINE*/
           case M_TEXTLINE:
              ori_assert(bd.f.cur_line_typ==get_linetyp(*bd.f.current),"check cur_linetyp");
              macro_tag=(boolean)(bd.f.cur_line_typ&NOT_FOLD);
              continue;
           /*}}}  */
           /*{{{  M_TEST_FOLD*/
           case M_TEST_FOLD:
              macro_tag=bd.m.select_mode!=no_selection;
              ocl_var[var_ocl_arg].v=bd.m.select_mode-1;
              continue;
           /*}}}  */
           /*{{{  M_BEGIN_FOLD_COMMENT*/
           case M_BEGIN_FOLD_COMMENT:
              ori_assert(bd.f.cur_line_typ==get_linetyp(*bd.f.current),"check cur_linetyp");
              macro_tag=(boolean)(bd.f.cur_line_typ&START_OPEN_FOLD);
              continue;
           /*}}}  */
           /*{{{  M_CLOSED_FOLD*/
           case M_CLOSED_FOLD:
              ori_assert(bd.f.cur_line_typ==get_linetyp(*bd.f.current),"check cur_linetyp");
              macro_tag=(boolean)(bd.f.cur_line_typ&START_FOLD);
              continue;
           /*}}}  */
           /*{{{  M_END_FOLD_COMMENT*/
           case M_END_FOLD_COMMENT:
              ori_assert(bd.f.cur_line_typ==get_linetyp(*bd.f.current),"check cur_linetyp");
              macro_tag=(boolean)(bd.f.cur_line_typ&END_FOLD);
              continue;
           /*}}}  */
           /*{{{  M_FILED_FOLD*/
           case M_FILED_FOLD:
              ori_assert(bd.f.cur_line_typ==get_linetyp(*bd.f.current),"check cur_linetyp");
              macro_tag=(boolean)(bd.f.cur_line_typ&START_FILED);
              continue;
           /*}}}  */
           /*{{{  M_SET_COUNTER*/
           CASES_M_SET_COUNTER
           case M_SET_COUNTER: {
             int x=get_arg("set-target");

             ocl_var[x].v=get_arg_fixed(ch-M_SET_COUNTER_0,"set-source");
             continue;
           }
           /*}}}  */
           /*{{{  M_ENTERED*/
           case M_ENTERED:
             ocl_var[get_arg("entered-target")].v=bd.f.entered;
             continue;
           /*}}}  */
           /*{{{  M_S_ENTERED*/
           case M_S_ENTERED:
             ocl_var[get_arg("space-entered-target")].v=bd.f.enter_spaces;
             continue;
           /*}}}  */
           /*{{{  M_INT_STRING*/
           case M_INT_STRING:
              if (!push_str_macro(i_to_ua(ocl_var[get_arg("int-source")].v)))
                 ori_abort(~SIGINT);
             continue;
           /*}}}  */
           /*{{{  M_READ_REPEAT*/
           case M_READ_REPEAT: {
             ocl_var[get_arg("read-repeat")].v=set_argument;
             set_argument= -1;
             argument=0;
             continue;
           }
           /*}}}  */
           /*{{{  M_NULL_COUNTER*/
           case M_NULL_COUNTER:
              macro_tag=(ocl_var[get_arg("=0")].v==0);
              continue;
           /*}}}  */
           /*{{{  M_MENU*/
           case M_MENU: {
             int *x= &((ocl_var+get_arg("menu-target"))->v);
             unsigned char prompt[LINELEN+1];

             prompt_string(prompt);
             *x=menu_item(prompt,*x,True,True);
             no_message();
             continue;
           }
           /*}}}  */
           /*{{{  M_PROMPTs*/
           case M_PROMPT_C:
           case M_PROMPT: {
             int counter=get_arg("prompt-target");
             unsigned char string[LINELEN+1];
             unsigned char *s=string;
             unsigned char *d;
             TOKEN x=O_NOP;

             if (!prompting)
              { ori_assert(bd.scr.cur_shift_w<=LINELEN,"shift-check");
                title_op(UPDTITLE);
              }
             prompt_string(string);
             if (counter==-3)
              /*{{{  paste message to text*/
              { if (string[0])
                 { push_str_macro(string);
                   ch = *macro_pos++;
                   if (ch==M_END_MACRO)
                    { macro_pos--;
                      continue;
                    }
                 }
                else
                   ch=O_NOP;
                return(ch);
              }
              /*}}}  */
             else if (counter==-2)
              /*{{{  simply show*/
                if (ocl_var[var_mod_beh].v)
                 { if (verbose)
                      message(string);
                 }
                else
                   message(string);
              /*}}}  */
             else
              /*{{{  show and wait for input*/
              { while (*s++);
                d = --s;
                /*{{{  read the string direct from keyboard*/
                disable_abort();
                enable_echo(False);
                /* if aborted is true before get_key is called, then ... :-( */
                if (string[0] || ch==M_PROMPT)
                   message(string);
                *s=0;
                while (!aborted && (x=get_key())!=O_RETURN)
                 { if (ch==M_PROMPT_C)
                      break;
                   if (   x<O_NOP
                       && (   isalnum((char) x)
                           || ((char) x =='-')
                          )
                      )
                      *s++ = (char) x;
                   else if ((x==O_DELETE) && s!=d)
                      --s;
                   *s='\0';
                   message(string);
                 }
                enable_echo(True);
                enable_abort();
                /*}}}  */
                if (!aborted)
                   if (counter>=0)
                     if (ch==M_PROMPT_C)
                       ocl_var[counter].v=x;
                     else {
                       *d=toupper(*d);
                       if (*d==YES)
                         ocl_var[counter].v=1;
                       else if (*d==NO)
                         ocl_var[counter].v=0;
                       else
                         ocl_var[counter].v=atoi((char *)d);
                     }
              }
              /*}}}  */
             continue;
           }
           /*}}}  */
           /*{{{  M_PUSH_INT*/
           case M_PUSH_INT:
              if (push(ocl_var[get_arg("push")])) goto push_stack_crash;
              continue;
           /*}}}  */
           /*{{{  M_POP_DELBUFF*/
           case M_POP_DELBUF:
              if (deleted_lines[delete_ptr])
               { proc_dispose(deleted_lines[delete_ptr]);
                 deleted_lines[delete_ptr]=0;
               }
              if (--delete_ptr<0)
                 delete_ptr=UNDEL_LINES-1;
              continue;
           /*}}}  */
           /*{{{  M_POP_INT*/
           case M_POP_INT:
              ocl_var[get_arg("pop")]=pop();
              continue;
           /*}}}  */
           /*{{{  M_PUSH/POP_INT_X*/
           case M_PUSH_INT_X:
           case M_POP_INT_X:
            { int a1,a2,o;

              a1=get_arg("push/pop-array");
              a2=get_arg("push/pop-offset");
              o=a1+ocl_var[a2].v;
              if (o<0 || o>=var_count)
               { index_crash:
                 ocl_msg("invalid var adress",0);
                 ori_abort(~SIGINT);
                 warn_message(get_msg(F_INT_OCL,STR_INV_VAR,o));
               }
              else if (ch==M_POP_INT_X)
                 ocl_var[o]=pop();
              else if (push(ocl_var[o]))
               { push_stack_crash:
                 ori_abort(~SIGINT);
                 warn_message(get_msg(M_STACK_OVER));
                 break;
               }
              continue;
            }
           /*}}}  */
           /*{{{  M_POSITIV_COUNTER*/
           case M_POSITIV_COUNTER:
              macro_tag=(ocl_var[get_arg(">0")].v>0);
              continue;
           /*}}}  */
           /*{{{  M_ADD_COUNTER*/
           CASES_M_ADD_COUNTER
           case M_ADD_COUNTER:
            { int x=get_arg("add-target");

              macro_tag=((ocl_var[x].v+=get_arg_fixed(ch-M_ADD_COUNTER_0,"add-source"))==0);
              continue;
            }
           /*}}}  */
           /*{{{  M_INV_COUNTER*/
           case M_INV_COUNTER:
            { int x=get_arg("inv");

              macro_tag=((ocl_var[x].v= -ocl_var[x].v)==0);
              continue;
            }
           /*}}}  */
           /*{{{  M_SET_USER_MODE_NUMB*/
           case M_SET_USER_MODE_NUMB:
            { int i=get_arg("set-user-numb");
            
              n_modes[i]=ocl_var[get_arg("set-user-val")].v;
              um_active[i]=True;
              title_op(CHGTITLE);
              no_message();
              continue;
            }
           /*}}}  */
           /*{{{  M_(RE)SET_USER_MODE*/
           case M_RESET_USER_MODE:
           case M_SET_USER_MODE:
            { int i=get_arg("set-user");
            
              n_modes[i]=0;
              if (um_active[i]!=(ch==M_SET_USER_MODE))
               { um_active[i]=(ch==M_SET_USER_MODE);
                 title_op(CHGTITLE);
               }
              no_message();
              continue;
            }
           /*}}}  */
           /*{{{  M_SUM_COUNTER*/
           case M_SUM_COUNTER:
            { int x=get_arg("sum-target");

              macro_tag=((ocl_var[x].v+=ocl_var[get_arg("sum-source")].v)==0);
              continue;
            }
           /*}}}  */
           /*{{{  M_MULT*/
           case M_MULT:
            { int x=get_arg("mult-target");
            
              ocl_var[x].v *= ocl_var[get_arg("mult-source")].v;
              continue;
            }
           /*}}}  */
           /*{{{  M_MOD*/
           case M_MOD:
            { int x=get_arg("mod-target");
              int y=ocl_var[get_arg("mod-source")].v;
            
              if (y)
                 ocl_var[x].v %= y;
              else
               { ocl_msg("%d%%0",ocl_var[x].v);
                 ori_abort(~SIGINT);
               }
              continue;
            }
           /*}}}  */
           /*{{{  M_DIV*/
           case M_DIV:
            { int x=get_arg("div-target");
              int y=ocl_var[get_arg("div-source")].v;
            
              if (y)
                 ocl_var[x].v /= y;
              else
               { ocl_msg("%d/0",ocl_var[x].v);
                 ori_abort(~SIGINT);
               }
              continue;
            }
           /*}}}  */
           /*{{{  O_UNDEL_CHAR*/
           case O_UNDEL_CHAR:
              return(deleted_ch);
           /*}}}  */
           /*{{{  O_BELL*/
           case O_BELL:
              bell_audible();
              break;
           /*}}}  */
           /*{{{  O_BELL_VISIBLE*/
           case O_BELL_VISIBLE:
              bell_visible();
              break;
           /*}}}  */
           /*{{{  M_SW_KBD*/
           case M_SW_KBD:
              kbd_change(get_arg("kbd"));
              continue;
           /*}}}  */
           /*{{{  O_DEF_MACRO*/
           case O_DEF_MACRO:
              if (!hide) {
                defining_macro = !defining_macro;
                if (defining_macro)
                   macro_count=0;
                ((TOKEN*)fix_macros[0].mac.txt)[macro_count]=M_END_MACRO;
                no_message();
                title_op(CHGTITLE);
              }
              break;
           /*}}}  */
           /*{{{  O_DEF_FIX*/
           case O_DEF_FIX:
              if (!hide) {
                TOKEN const *mac;
                unsigned char temp[LINELEN+1];
                int x;

                /*{{{  testing error-cases*/
                if (defining_macro)
                 { warn_message(get_msg(M_FIX_EXE));
                   ocl_msg("def and copy mac",0);
                   ori_abort(~SIGINT);
                   break;
                 }
                /*}}}  */
                s_readprompt(temp,get_msg(M_WHICH_FIX),20,no_history);
                if (aborted) break;
                x=atoi((char *)temp);
                if (x<1 || x>mac_count || fix_macros[x].mode!=init)
                 { warn_message(get_msg(F_NO_DEFINE));
                   break;
                 }
                if (fix_macros[x].mac.txt!=empty_macro)
                 { paket_free((TOKEN*)fix_macros[x].mac.txt);
                   ((macro_entry*)fix_macros)[x].mac.txt=empty_macro;
                 }
                if (!(mac=ori_malloc((macro_count+1)*sizeof(TOKEN))))
                 { warn_message(get_msg(M_B_NO_MEMORY));
                   break;
                 }
                no_message();
                memcpy
                 ( (TOKEN*)(((macro_entry*)fix_macros)[x].mac.txt=mac),
                   fix_macros[0].mac.txt,
                   (macro_count+1)*sizeof(TOKEN)
                 );
              }
              break;
           /*}}}  */
           /*{{{  O_NOP*/
           case O_NOP:
              if (echo_active) no_message();
              continue;
           /*}}}  */
           /*{{{  handle O_REP_DEF*/
           case O_REP_0:
           case O_REP_1:
           case O_REP_2:
           case O_REP_3:
           case O_REP_4:
           case O_REP_5:
           case O_REP_6:
           case O_REP_7:
           case O_REP_8:
           case O_REP_9:
              if (set_argument<0)
               /*{{{  do it*/
               { if (defining_macro || executing_macro)
                  /*{{{  error: conflict define-macro and repeating!*/
                  { ocl_msg("rep and def mac",0);
                    ori_abort(~SIGINT);
                    continue;
                  }
                  /*}}}  */
                 /*{{{  get number and next token*/
                 { int x;
                   unsigned char prom[LINELEN+1];
                   unsigned char *s;

                   /*{{{  prepare internal data*/
                   ustrcpy(prom,get_msg(M_ARG));
                   s=prom+ustrlen(prom);
                   x=ch-O_REP_0;
                   set_argument=0;
                   /*}}}  */
                   /*{{{  get integer and the following token*/
                   for (;;)
                    { set_argument=10*set_argument+x;
                      *s++=hex_digits[x];
                      *s='\0';
                      message(prom);
                      ch=internal_hide_key(True);
                      x=0;
                      if (!quote_used)
                         switch(ch)
                          { case '9':case O_REP_9:x++;
                            case '8':case O_REP_8:x++;
                            case '7':case O_REP_7:x++;
                            case '6':case O_REP_6:x++;
                            case '5':case O_REP_5:x++;
                            case '4':case O_REP_4:x++;
                            case '3':case O_REP_3:x++;
                            case '2':case O_REP_2:x++;
                            case '1':case O_REP_1:x++;
                            case '0':case O_REP_0:continue;
                            default:              break;
                          }
                      break;
                    }
                   /*}}}  */
                 }
                 /*}}}  */
                 if (ch==O_BREAK || aborted)
                  /*{{{  ready*/
                  { set_argument= -1;
                    argument=0;
                    break;
                  }
                  /*}}}  */
                 else
                  /*{{{  start the repeating*/
                  { argument=set_argument;
                    rep_token=ch;
                    if (!argument) argument=1;
                    enable_abort();
                    continue;
                  }
                  /*}}}  */
               }
               /*}}}  */
              else
                 continue;
           /*}}}  */
           /*{{{  default: return the value*/
           default:
              return(ch);
           /*}}}  */
         }
       }
       /*}}}  */
     else if (ch<=(O_EXE_MACRO+mac_count) && ch>=O_EXE_MACRO)
      /*{{{  execute macros*/
      { TOKEN const *c;
        int number=ch-O_EXE_MACRO;

        if (ch==O_EXE_MACRO)
         /*{{{  some test for keyboard macro*/
         { if (defining_macro)
            { warn_message(get_msg(M_EXE_EXE));
              ocl_msg("def and exec kbd mac",0);
              ori_abort(~SIGINT);
              continue;
            }
           if (macro_count==0)
            { ch=O_NOP;
              break;
            }
         }
         /*}}}  */
        if (!(c=load_demand(number)))
         { ocl_msg("demand error",0);
           ori_abort(~SIGINT);
         }
        else if (push_macro(c)||hide)
         { ch=O_BREAK;
           break;
         }
        continue;
      }
      /*}}}  */
     else
        exit_origami(r_ocl_err,get_msg(F_INT_OCL,STR_INV_TOK,ch));
     ch=O_PROMPT;
     break;
   }
  while (!hide);
  return ch;
}
/*}}}  */
/*{{{  internal_hide_key     get a token direct from keyboard, store it to mac*/
private TOKEN internal_hide_key(boolean direct)
{ boolean oldprompt=prompting;
  boolean pr_tag;
  TOKEN x;

  enable_echo(False);
  prompting=True;
  pr_tag=macro_tag;
  if (pin_macro)
   /*{{{  call prompt-in*/
   { int old_exe_mac;

     old_exe_mac=executing_macro;
     call_number_macro(pin_macro);
     do
        single_key(True);
     while (old_exe_mac<executing_macro);
   }
   /*}}}  */
  macro_tag=pr_tag;
  /*{{{  get input-character*/
  if (direct)
     def_mac_handle(x=get_key());
  else
     do
        x=single_key(False);
     while (x==O_PROMPT || invalid_prompt_key(x));
  /*}}}  */
  pr_tag=macro_tag;
  if (pout_macro)
   /*{{{  call prompt-out*/
   { int old_exe_mac;

     old_exe_mac=executing_macro;
     call_number_macro(pout_macro);
     do
        single_key(True);
     while (old_exe_mac<executing_macro);
   }
   /*}}}  */
  macro_tag=pr_tag;
  prompting=oldprompt;
  enable_echo(True);

  return(x);
}
/*}}}  */
/*{{{  hide_key              get a token. mode is in-prompt*/
public TOKEN hide_key(void)
{
  return(internal_hide_key(False));
}
/*}}}  */
/*{{{  edit_key              get a token and set *keypad, mode is editing*/
public TOKEN edit_key(void)
{
  return(single_key(False));
}
/*}}}  */
