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

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

#include <local/bool.h>

#define LOOP_C
#define I_DISPLAY_C
#define I_FIELDEDIT_C
#define I_FINDS_C
#define I_FOLDHELP_C
#define I_FOLDFILING_C
#define I_FOLDING_C
#define I_FOLDFILING_C
#define I_GETMSG_C
#define I_GETTK_C
#define I_KEYBOARD_C
#define I_KEYTAB_C
#define I_MAIN_C
#define I_MISC_C
#define I_MESSAGES_C
#define I_ORIEDT_C
#define I_PROMPT_C
#define I_READFOLDS_C
#define I_SCREEN_C
#define I_SHELL_C
#define I_SIGNALS_C
#define I_VIRTUAL_C
#define I_WRITEF_C

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

/*{{{  variables*/
public int scr_pos=0;
public unsigned char line_buffer[LINELEN + 1];
public FILE *start_pipe=0;
/*}}}  */

/*{{{  #define append_to_pick*/
#define append_to_pick() (join_links(pick_tail, pick_ptr), \
                       pick_ptr->UU.U1.indent = 0, \
                       pick_tail = pick_ptr)
/*}}}  */
/*{{{  ref_shifted_line*/
private void ref_shifted_line(void)
{ if (x_offset)
   /*{{{  line is shifted left, unshift it*/
   { write_dsp_line(current,cursor_level);x_offset=0; }
   /*}}}  */
}
/*}}}  */
/*{{{  main_editor_loop*/
public void main_editor_loop(char *argv[])
{
  /*{{{  variables*/
  TOKEN    ch;
  bool     keypad = TRUE;
  bool     quit = FALSE;
  bool     del_under = FALSE;
  int      i;
  element  *move_ptr = 0;
  element  *copy_ptr = 0;
  element  *pick_ptr = 0;
  element  *line_dsp_line = 0;
  /*}}}  */

  /*{{{  startup the session*/
  /*{{{  show empty screen with statusline*/
  ClrScr();
  title_op(PRTTITLE);
  /*}}}  */
  /*{{{  get text*/
  create_list((FILE*)0);
  if (real_head!=real_tail) add_edit_file((char *)get_data(real_tail),TRUE);
  if (start_pipe)
   /*{{{  append stuff, coming from stdin*/
   { element *x;

     /*{{{  move to end*/
     x=tail->prec;
     /*}}}  */
     /*{{{  read file*/
     message(get_msg(F_LOADING,"stdin"),TRUE);
     current=tail;
     insert_file((element *)0,current->prec,current,FALSE,&dir_edit,start_pipe);
     fclose(start_pipe);
     start_pipe=0;
     /*}}}  */
     if (x->next!=tail)
      /*{{{  move to start of piped text and maybe set file changed*/
      { file_changed = TRUE;title_op(SET_CF);current=x->next; }
      /*}}}  */
   }
   /*}}}  */
  /*}}}  */
  /*{{{  update statusline and window title*/
  if (overwrite) title_op(SET_OVER);
  if (auto_save) { title_op(SET_AUTO);set_alarm(0); }
  title_op(UPDTITLE);
#  ifdef WINDOW_TITLE_CHANGE
     chg_w_title((char*)0);
#  endif
  /*}}}  */
  /*{{{  show read text*/
  if (scr_pos>0)
     find_element(scr_pos,SCREEN_LEN/2);
  else
     restore_element(4);
  /*}}}  */
  /*{{{  init OCL-screen-vars*/
  *sy_ptr=SCREEN_LEN;
  *sx_ptr=W_dx;
  scr_pos=1;
  /*}}}  */
  call_number_macro(auto_macro);
  /*}}}  */
  do {
    *cy_ptr=cursor_level;
    /*{{{  get textline, call fieldedit, save textline*/
    copyin(current_dsp_line, current, FALSE);
    proc_to_edit_pos();
    /*{{{  interrupt_restore?*/
    if (interrupt_restore) {
      restore(1);
      interrupt_restore = FALSE;
    }
    /*}}}  */
    /*{{{  aborted?*/
    if (aborted) {
      if (scr_off) { scr_off=0;screen_on();restore_element(SCREEN_LEN/2); }
      aborted = FALSE;
      kbd_pipe((FILE*)0);
      message(get_msg(M_ABORTED), TRUE);
      call_number_macro(ab_macro);
    }
    /*}}}  */
    /*{{{  get next editor-token*/
    if (do_auto_save && !select_on)
      ch = O_AUTO_SAVE;
    else
      ch = field_edit(&keypad);
    /*}}}  */
    proc_from_edit_pos();
    if (current->foldline != END_FOLD) copyout(current_dsp_line, current);
    /*}}}  */
    if (dirty && ch!=O_PROMPT) restore(1);
    if (valid_screen_key(&keypad, &ch))
     { if (ch!=O_PROMPT) no_message();
       if (keypad)
        /*{{{  handle loop command*/
        { switch (ch) {
           /*{{{  M_EXIT*/
           case M_EXIT:{
            unsigned char string[100];

            prompt_string(string);
            if (*string != '\0') message(string, TRUE);
            stop_macros();
            break;
           }
           /*}}}  */
           /*{{{  M_SHOW_HELP*/
           case M_SHOW_HELP:
             set_area();
             break;
           /*}}}  */
           /*{{{  M_PIPE_HELP*/
           case M_PIPE_HELP:
             pipe_area();
             break;
           /*}}}  */
           /*{{{  M_WRITE_HELP*/
           case M_WRITE_HELP:
             write_area();
             break;
           /*}}}  */
           /*{{{  M_CHANGE_FOLD*/
           case M_CHANGE_FOLD:
            { int t=get_arg();

              change_foldtype(macro_int[t],macro_int[get_arg()]);
              break;
            }
           /*}}}  */
           /*{{{  O_AUTO_SAVE*/
           case O_AUTO_SAVE:{
             auto_write();
             break;
           }
           /*}}}  */
           /*{{{  O_ATTACH_FILE*/
           case O_ATTACH_FILE:{
             attach_file();
             break;
           }
           /*}}}  */
           /*{{{  O_A_AUTO_SAVE*/
           case O_A_AUTO_SAVE:{
             unsigned char time[12];

             readprompt(time, (unsigned char*)"auto-save-interval", 10);
             if (!aborted) {
               auto_save = TRUE;
               set_alarm(atoi((char *)time));
               title_op(SET_AUTO);
             }
             break;
           }
           /*}}}  */
           /*{{{  O_A_ECHO*/
           case O_A_ECHO:{
             switch_echo(TRUE);
             break;
           }
           /*}}}  */
           /*{{{  O_BOT_OF_FOLD*/
           case O_BOT_OF_FOLD:{
             ref_shifted_line();
             bottom();
             break;
           }
           /*}}}  */
           /*{{{  O_BREAK*/
           case O_BREAK:{
             break;
           }
           /*}}}  */
           /*{{{  O_CLOSE_FOLD*/
           case O_CLOSE_FOLD:{
             close_fold();
             break;
           }
           /*}}}  */
           /*{{{  O_COPY*/
           case O_COPY:{
             if (  (current->foldline == NOT_FOLD ||
                    current->foldline == START_FOLD)
                 && current != tail
                 && copy_a_line(&copy_ptr))
               undelete_after(copy_ptr);
             break;
           }
           /*}}}  */
           /*{{{  O_COPY_PICK*/
           case O_COPY_PICK:{
             if (current->foldline == NOT_FOLD || current->foldline == START_FOLD) {
               pick_ptr = 0;
               if (copy_a_line(&pick_ptr))
                 append_to_pick();
             }
             break;
           }
           /*}}}  */
           /*{{{  O_CREATE_FOLD*/
           case O_CREATE_FOLD:{
             if (!select_on) {
               if (!entered(current)) {
                 start_make_fold();
                 title_op(SET_FOLD);
               }
             } else {
               make_fold();
               if (!select_on) title_op(RESET_FOLD);
             }
             break;
           }
           /*}}}  */
           /*{{{  O_DEL_LINE*/
           case O_DEL_LINE:{
             remove_line(&line_dsp_line);
             break;
           }
           /*}}}  */
           /*{{{  O_DEL_CHAR_RIGHT/O_DELETES*/
           case O_DEL_CHAR_R:{
             ref_shifted_line();
             move_down();
             del_under = TRUE;
           }
           case O_DELETE:{
             if (current->foldline == NOT_FOLD) {
               if (current != tail && current != head->next
                   && current->prec->foldline == NOT_FOLD) {
                 strcpy((char *)line_buffer,(char *)get_data(current));
                 trailing_spaces(line_buffer);
                 move_up();
                 copyin(current_dsp_line, current, FALSE);
                 trailing_spaces(current_dsp_line);
                 scr_pos=txt2scr(enter_depth_spaces,
                                 strlen((char *)current_dsp_line),
                                 current_dsp_line);
                 if (scr_pos==1) scr_pos=current->UU.U1.indent+1;
                 if ((strlen((char *)line_buffer)+strlen((char *)current_dsp_line))
                     <= LINELEN-enter_depth_spaces)
                 {
                   strcpy((char *)current_dsp_line,(char *)get_data(current));
                   strcat((char *)current_dsp_line, (char *)line_buffer);
                   set_data(current,current_dsp_line);
                   write_dsp_line(current, cursor_level);
                   move_down();
                   part_line = 0;
                   remove_line(&part_line);
                   proc_dispose(part_line);
                   move_up();
                   del_under = FALSE;
                 } else {
                   if (del_under) move_up();
                   message(get_msg(M_LONG_LINE), TRUE);
                 }
                 break;
               }
             }
             if (del_under) {
               move_up();
               del_under = FALSE;
             }
             vmessage(get_msg(M_ERR_PO));
             break;
           }
           /*}}}  */
           /*{{{  O_DESCRIBE_BINDINGS*/
           case O_DESCRIBE_BINDINGS: {
             if (help(FALSE)) restore(1);
             break;
           }
           /*}}}  */
           /*{{{  O_D_AUTO_SAVE*/
           case O_D_AUTO_SAVE:{
             macro_int[ocl_arg]=auto_save?alarm_time:0;
             auto_save = FALSE;
             reset_alarm();
             title_op(RESET_AUTO);
             break;
           }
           /*}}}  */
           /*{{{  O_D_ECHO*/
           case O_D_ECHO:{
             switch_echo(FALSE);
             break;
           }
           /*}}}  */
           /*{{{  O_DOWN*/
           case O_DOWN:{
             ref_shifted_line();
             move_down();
             break;
           }
           /*}}}  */
           /*{{{  O_ENTER_FOLD*/
           case O_ENTER_FOLD:{
             enter_fold();
             break;
           }
           /*}}}  */
           /*{{{  O_EXIT_FOLD*/
           case O_EXIT_FOLD:{
             scr_pos = 1;
             exit_fold();
             break;
           }
           /*}}}  */
           /*{{{  O_FILE_FOLD*/
           case O_FILE_FOLD:{
             file_fold();
             break;
           }
           /*}}}  */
           /*{{{  O_FILTER_BUFFER*/
           case O_FILTER_BUFFER:{
             filter_buffer();
             break;
           }
           /*}}}  */
           /*{{{  O_FIND/O_FIND_REVERSE*/
           case O_FIND:
           case O_FIND_REVERSE:{
             ref_shifted_line();
             get_search();
             if (*item_to_look_for != '\0' && !aborted)
               if (!find_item(ch == O_FIND_REVERSE,TRUE))
                 message(get_msg(M_FAILED), FALSE);
             break;
           }
           /*}}}  */
           /*{{{  M/O_FINISH*/
           case M_FINISH:
             new_exit=macro_int[get_arg()];
           case O_FINISH:{
             do_save_file();
             quit = TRUE;
             break;
           }
           /*}}}  */
           /*{{{  O_FIRST_LINE_TO_FOLD_HEADER*/
           case O_FIRST_LINE_TO_FOLD_HEADER:{
             if (current->foldline == START_FOLD) {
               set_data(current,get_data(current->fold));
               write_dsp_line(current, cursor_level);
             }
             break;
           }
           /*}}}  */
           /*{{{  O_FOLD_INFO*/
           case O_FOLD_INFO:{
             /*{{{  generate internal message*/
             /*{{{  position*/
             strcpy((char*)print_buffer,
                    (char*)get_msg(F_INFO_1,
                                   line_no(current)-1,
                                   scr_pos+enter_depth_spaces,
                                   enter_depth,
                                   enter_depth_spaces));
             /*}}}  */
             if (filed_or_fold(current))
              /*{{{  fold-type*/
              { strcat((char*)print_buffer,
                       (char*)get_msg(F_INFO_2,
                                      fold_file_str,
                                      current->UU.U1.fold_type,
                                      current->UU.U1.fold_contents));
                macro_int[ocl_arg]=  ((current->UU.U1.fold_type&127)<<8)
                                   + current->UU.U1.fold_contents;
                if (current->UU.U1.fold_type&128)
                   macro_int[ocl_arg]= -macro_int[ocl_arg];
              }
              /*}}}  */
             if (current->foldline == START_FILED)
              /*{{{  filename*/
              { strcat((char*)print_buffer,(char*)tspace+2);
                strcat((char*)print_buffer,(char*)get_data(current->other_end));
              }
              /*}}}  */
             /*}}}  */
             message(print_buffer,TRUE);
             break;
           }
           /*}}}  */
           /*{{{  O_GOTO_LINE*/
           case O_GOTO_LINE:{
             goto_line();
             break;
           }
           /*}}}  */
           /*{{{  O_HELP*/
           case O_HELP:{
             if (help(TRUE)) restore(1);
             break;
           }
           /*}}}  */
           /*{{{  O_INSERT_FILE*/
           case O_INSERT_FILE:{
             if (!entered(current)) {
               f_c_types old_dia = dialect;
               bool old_view=read_only;

               insert_file((element *)0,current->prec,current,FALSE,(bool*)0,(FILE*)0);
               dialect = old_dia;
               read_only=old_view;
               title_op(CHGTITLE);
               restore_element(cursor_level);
             }
             break;
           }
           /*}}}  */
           /*{{{  O_ITS_REVERSE*/
           case O_ITS_REVERSE:{
             ref_shifted_line();
             its_search(TRUE);
             break;
           }
           /*}}}  */
           /*{{{  O_ITS_SEARCH*/
           case O_ITS_SEARCH:{
             ref_shifted_line();
             its_search(FALSE);
             break;
           }
           /*}}}  */
           /*{{{  O_LANGUAGE*/
           case O_LANGUAGE:{
             proc_language();
             break;
           }
           /*}}}  */
           /*{{{  O_MOVE*/
           case O_MOVE:{
             if (move_ptr) {
               if (!entered(current)) {
                 ref_shifted_line();
                 undelete_before(move_ptr);
                 move_ptr = 0;
               }
             } else
               remove_line(&move_ptr);
             break;
           }
           /*}}}  */
           /*{{{  O_NEXT_FILE*/
           case O_NEXT_FILE:{
             next_file(1, argv);
             break;
           }
           /*}}}  */
           /*{{{  O_OPEN_FOLD*/
           case O_OPEN_FOLD:{
             open_fold();
             break;
           }
           /*}}}  */
           /*{{{  O_OPEN_NEW_FILE*/
           case O_OPEN_NEW_FILE:{
             open_file();
             break;
           }
           /*}}}  */
           /*{{{  O_PAGE_DOWN*/
           case O_PAGE_DOWN:{
             ref_shifted_line();
             i=SCREEN_LEN-cursor_level+1;
             /*{{{  skip i lines*/
             while (i-- && current != tail) current = current->next;
             /*}}}  */
             restore_element(1);
             break;
           }
           /*}}}  */
           /*{{{  O_PAGE_UP*/
           case O_PAGE_UP:{
             ref_shifted_line();
             i=SCREEN_LEN+cursor_level-3;
             /*{{{  skip i lines*/
             while (i-- && current->prec != head) current = current->prec;
             /*}}}  */
             restore_element(1);
             break;
           }
           /*}}}  */
           /*{{{  O_PICK*/
           case O_PICK:{
             pick_ptr = 0;
             remove_line(&pick_ptr);
             if (pick_ptr) append_to_pick();
             break;
           }
           /*}}}  */
           /*{{{  O_PIPE_FROM_COMMAND*/
           case O_PIPE_FROM_COMMAND:{
             if (!entered(current)) {
               pipe_from_command();
               restore_element(cursor_level);
             }
             break;
           }
           /*}}}  */
           /*{{{  O_PIPE_KBD*/
           case O_PIPE_KBD: {
             pipe_kbd_from_command();
             break;
           }
           /*}}}  */
           /*{{{  O_PIPE_TO_COMMAND*/
           case O_PIPE_TO_COMMAND:{
             if (tail == real_tail)
               pipe_to_command();
             else
               message(get_msg(M_NO_TOP), TRUE);
             break;
           }
           /*}}}  */
           /*{{{  O_PREV_FILE*/
           case O_PREV_FILE:{
             next_file(-1, argv);
             break;
           }
           /*}}}  */
           /*{{{  O_PUT_PICK*/
           case O_PUT_PICK:{
             if (!entered(current))
               if (pick_head != pick_tail)
                 undelete_pick_before();
               else
                 message(get_msg(M_NO_PICK), TRUE);
             break;
           }
           /*}}}  */
           /*{{{  O_QUERY_REPLACE*/
           case O_QUERY_REPLACE:{
             ref_shifted_line();
             query_replace();
             break;
           }
           /*}}}  */
           /*{{{  O_QUIT*/
           case O_QUIT:{
             quit = (file_changed ? yes(get_msg(M_CHANGED_LEAVE)) : TRUE);
             break;
           }
           /*}}}  */
           /*{{{  O_FLUSH/O_REFRESH/O_TITLE_SHOW/O_TITLE_HIDE*/
           case O_TITLE_HIDE:
           case O_TITLE_SHOW:
             if (no_title==((ch==O_TITLE_HIDE)?1:0)) break;
             no_title=1-no_title;
             *sy_ptr=SCREEN_LEN;
             if (cursor_level > (SCREEN_LEN-2) && screen_end != tail)
                cursor_level--;
           case O_FLUSH:
             { int x=(ch==O_FLUSH && executing_macro)?macro_int[get_arg()]:0;

               if (x<1 || x>SCREEN_LEN-1) x=cursor_level;
               restore_element(x);
               title_op(PRTTITLE);
               break;
             }
           case O_REFRESH:{
             if (get_terminal_capability()) return;
             restore_element(SCREEN_LEN / 2);
             title_op(PRTTITLE);
             *sy_ptr=SCREEN_LEN;
             *sx_ptr=W_dx;
             /*{{{  window?*/
#             if defined(SIGWINCH) || defined(MGR)
             if (win_changed) {
               win_changed = FALSE;
               vmessage(get_msg(M_WIN_CHANGED));
             }
#             endif
             /*}}}  */
             break;
           }
           /*}}}  */
           /*{{{  O_REMOVE_FOLD*/
           case O_REMOVE_FOLD:{
             remove_fold();
             break;
           }
           /*}}}  */
           /*{{{  O_REPLACE*/
           case O_REPLACE:{
             replace();
             break;
           }
           /*}}}  */
           /*{{{  O_RETURN*/
           case O_RETURN:{
             ref_shifted_line();
             if (!select_on)
               if (split_line)
                 undelete_after(part_line);
               else {
                 undelete_before(part_line);
                 move_down();
               }
             break;
           }
           /*}}}  */
           /*{{{  O_SAVE_FILE*/
           case O_SAVE_FILE:{
             save_file();
             break;
           }
           /*}}}  */
           /*{{{  O_SHELL_COMMAND*/
           case O_SHELL_COMMAND:{
             unsigned char cmd[LINELEN + 1];
             TOKEN x;

             put_vars();
             readprompt(cmd, get_msg(M_SH_COMMAND), LINELEN);
             if (!*cmd) break;
             reset_keyboard();
             reset_terminal();
             macro_int[ocl_arg]=subshell((char*)cmd);
             init_terminal();
             init_keyboard();
             message(get_msg(M_END), TRUE);
             do
              { x=hide_key(); }
             while (x!=O_RETURN && x!=O_BREAK);
             title_op(CHGTITLE);
             restore(1);
             no_message();
             break;
           }
           /*}}}  */
           /*{{{  O_SHELL*/
           case O_SHELL:{
             put_vars();
             message(get_msg(M_SHELL_CREATED), TRUE);
             reset_keyboard();
             reset_terminal();
             subshell((char*)0);
             init_terminal();
             init_keyboard();
             title_op(CHGTITLE);
             restore(1);
             no_message();
             break;
           }
           /*}}}  */
           /*{{{  O_SUSPEND*/
           case O_SUSPEND: {
             bktoshell();
             break;
           }
           /*}}}  */
           /*{{{  O_TOP_OF_FOLD*/
           case O_TOP_OF_FOLD: {
             ref_shifted_line();
             top();
             break;
           }
           /*}}}  */
           /*{{{  O_UNDEL_LINE*/
           case O_UNDEL_LINE:{
             if (!entered(current))
                if (line_dsp_line)
                 { ref_shifted_line();
                   undelete_before(line_dsp_line);
                   line_dsp_line = 0;
                 }
                else
                   message(get_msg(M_NO_UNDEL), TRUE);
             break;
           }
           /*}}}  */
           /*{{{  O_UP*/
           case O_UP:{
             ref_shifted_line();
             move_up();
             break;
           }
           /*}}}  */
           /*{{{  O_WRITE_FILE*/
           case O_WRITE_FILE:{
             write_file();
             break;
           }
           /*}}}  */
           /*{{{  default*/
           default: break;
           /*}}}  */
          }
        }
        /*}}}  */
     }
    else
      message(get_msg(M_NOFOLDKEY), TRUE);
  } while (!quit);
}
/*}}}  */
