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

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

#include <local/bool.h>

#define FOLDFILING_C
#define I_DISPLAY_C
#define I_FINDS_C
#define I_FOLDHELP_C
#define I_FOLDING_C
#define I_GETMSG_C
#define I_GETTK_C
#define I_KEYBOARD_C
#define I_MAIN_C
#define I_MESSAGES_C
#define I_MISC_C
#define I_ORIEDT_C
#define I_PROMPT_C
#define I_READFOLDS_C
#define I_SCREEN_C
#define I_SIGNALS_C
#define I_VIRTUAL_C
#define I_WRITEF_C

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

/*{{{  type edit_file_buffer*/
typedef struct edit_file_buffer
 { char *filename;
   struct edit_file_buffer *next;
 } edit_file_buffer;
/*}}}  */
/*{{{  variable*/
private edit_file_buffer *file_ring=0;
private edit_file_buffer *cmd_last=0;
private edit_file_buffer *current_ring_file=0;
/*}}}  */

/*{{{  delay_auto_write*/
public void delay_auto_write(void)
{
  if (auto_save) set_alarm(0);
}
/*}}}  */
/*{{{  proc_language*/
public void proc_language(void)
{ if (dialect!=F_C_TDS || yes(get_msg(M_LEAVE_INMOS)))
   /*{{{  get and set new dialect*/
   { f_c_types j;

     j=menu_item(language_string,dialect,FALSE);
     if (j>=F_C_NONE && j<=F_C_TDS)
      /*{{{  set new dialect*/
      { dialect=j;
        if (dialect==F_C_USER)
         /*{{{  get user-comments*/
         { readprompt(dialect_start[dialect],get_msg(M_CO_START),tag_length-1);
           readprompt(dialect_end[dialect],get_msg(M_CO_END),tag_length-1);
         }
         /*}}}  */
        title_op(CHGTITLE);
      }
      /*}}}  */
   }
   /*}}}  */
  no_message();
}
/*}}}  */
/*{{{  file_fold*/
public void file_fold(void)
{
  if (filed_or_fold(current)) {
    if (normal_att(current,TRUE)) {
      if (current->foldline == START_FOLD) {
        /*{{{  file*/
        FILE *fp;
        bool can_open;
        unsigned char newfilename[_POSIX_PATH_MAX+1];
        unsigned char *s;

        check_fold(current);
        strcpy((char *)newfilename,(char *)get_data(Start_of_fold));
        /*{{{  get filename to newfilename*/
        s=newfilename;
        while (*s && *s!=' ') s++;
        *s='\0';
        /*}}}  */
        if (access((char *)newfilename, F_OK|R_OK|W_OK)==0)
          can_open=yes(get_msg(F_TCFF,"toggle-create-file-fold",newfilename));
        else if ((fp=fopen((char *)newfilename,WRITE))) {
          fclose(fp);
          can_open=TRUE;
        } else
          can_open=FALSE;
        if (can_open) {
          set_data(End_of_fold,newfilename);
          write_fold(End_of_fold, Start_of_fold, (FILE*)0);
          if (Start_of_fold->fold != End_of_fold)
          delete_list(Start_of_fold->fold, End_of_fold->prec);
          Start_of_fold->fold = End_of_fold;
          End_of_fold->prec = Start_of_fold;
          Start_of_fold->foldline = START_FILED;
        } else
          message(get_msg(F_NO_OPEN,newfilename),TRUE);
        /*}}}  */
      } else {
        /*{{{  unfile*/
        f_c_types olddia;
        bool oldview;

        olddia=dialect;
        oldview=read_only;
        pre_open_fold(current);
        if (Start_of_fold->next == End_of_fold)
        insert_file(End_of_fold, Start_of_fold, End_of_fold, FALSE, (bool*)0, (FILE*)0);
        close_fold_at(current);
        dialect=olddia;
        read_only=oldview;
        /*}}}  */
      }
      write_dsp_line(current, cursor_level);
    }
  }
}
/*}}}  */
/*{{{  attach_file*/
public void attach_file(void)
{
  if (current->foldline == START_FOLD) {
    if (normal_att(current,FALSE)) {
      check_fold(current);
      if (Start_of_fold->fold == End_of_fold) {
        unsigned char filename[_POSIX_PATH_MAX+1];
        unsigned char *s=filename;

        strcpy((char *)filename,(char *)get_data(Start_of_fold));
        /*{{{  cut filename at first whitespace*/
        while (*s && (*s!=' ')) s++;
        *s='\0';
        /*}}}  */
        /*{{{  try to access the file*/
        if (access((char *)filename,R_OK)==0)
         { set_data(End_of_fold,filename);
           Start_of_fold->foldline = START_FILED;
           write_dsp_line(current, cursor_level);
         }
        else
           message(get_msg(F_F_FAILED,filename),TRUE);
        /*}}}  */
      }
    }
  }
}
/*}}}  */
/*{{{  filter_buffer*/
public void filter_buffer(void)
{
  /*{{{  variables*/
  unsigned char filename[_POSIX_PATH_MAX+1];
  unsigned char filtername[_POSIX_PATH_MAX+1];
  unsigned char pipename[_POSIX_PATH_MAX+1];
  FILE *pipeout,*pipein;
  int line;
  /*}}}  */

  /*{{{  errors*/
  if (dialect==F_C_TDS) {
    message(get_msg(M_NOT_IF_TDS),TRUE);
    return;
  }
  if (dir_edit) {
    message(get_msg(M_DIR_EDIT),FALSE);
    return;
  }
  /*}}}  */
  /*{{{  prepare filtering*/
  while (tail != real_tail) {exit_fold();message(get_msg(M_EX_NFF),TRUE);}
  line=line_no(current);
  readprompt(filtername,(unsigned char*)"filter-buffer",LINELEN);
  if (*filtername=='\0' || aborted) return;
  /*}}}  */
  /*{{{  write to pipe*/
  strcpy((char *)filename,(char *)get_data(real_tail));
  /*{{{  open pipe for output the file*/
  if ((pipeout=fopen((char *)filename,WRITE))==(FILE*)0) {
    err_message(get_msg(M_NO_OUTFILE),filename,TRUE);
    return;
  }
  /*}}}  */
  message(get_msg(M_WRITING),TRUE);
  total_save(pipeout);
  /*{{{  close*/
  if (fclose(pipeout)<0) {
    err_message(get_msg(M_CLOSE_FAILED),filename,TRUE);
    return;
  }
  /*}}}  */
  /*}}}  */
  /*{{{  read from pipe*/
  /*{{{  open the pipe for filtered file*/
  strcpy((char *)pipename,(char *)filtername);
  strcat((char *)pipename," <");
  strcat((char *)pipename,(char *)filename);
  put_vars();
  if ((pipein=popen((char *)pipename,"r"))==(FILE*)0) {
    err_message(get_msg(M_CANTOPEN),M_PSTR,TRUE);
    return;
  }
  /*}}}  */
  /*{{{  read the filtered file*/
  current=pre_find_element(1);
  close_and_open_folds(current);
  while (current!=real_tail) pre_remove_line(&current);
  message(get_msg(M_READING),TRUE);
  insert_file((element *)0,current->prec, current, FALSE, (bool*)0, pipein);
  /*}}}  */
  if ((macro_int[ocl_arg]=pclose(pipein))<0)
     err_message(get_msg(M_CLOSE_FAILED),M_PSTR,TRUE);
  /*{{{  display it at old position*/
  file_changed=TRUE;
  title_op(SET_CF);
  find_element(line,4);
  /*}}}  */
  message(get_msg(M_READ),TRUE);
  /*}}}  */
  return;
}
/*}}}  */
/*{{{  pipe_from_command*/
public void pipe_from_command(void)
{
  /*{{{  variables*/
  unsigned char command[_POSIX_PATH_MAX+1];
  FILE *pipein;
  int olddia=dialect;
  /*}}}  */

  /*{{{  errors*/
  if (dialect==F_C_TDS) {
    message(get_msg(M_NOT_IF_TDS),TRUE);
    return;
  }
  /*}}}  */
  /*{{{  open pipe*/
  readprompt(command,(unsigned char*)"pipe-from-command",LINELEN);
  if (*command=='\0' || aborted) return;
  put_vars();
  if ((pipein=popen((char *)command,"r"))==(FILE*)0) {
    err_message(get_msg(M_CANTOPEN),M_PSTR,TRUE);
    return;
  }
  /*}}}  */
  message(get_msg(M_READING),TRUE);
  insert_file((element *)0,current->prec, current, FALSE, (bool*)0, pipein);
  dialect=olddia;
  if ((macro_int[ocl_arg]=pclose(pipein))<0)
    err_message(get_msg(M_CLOSE_FAILED),M_PSTR,TRUE);
  else
    message(get_msg(M_READ),TRUE);
}
/*}}}  */
/*{{{  pipe_kbd_from_command*/
public void pipe_kbd_from_command(void)
{
  /*{{{  variables*/
  unsigned char command[_POSIX_PATH_MAX+1];
  FILE *pipein;
  /*}}}  */

  /*{{{  open pipe*/
  readprompt(command,(unsigned char*)"pipe-kbd-from-command",LINELEN);
  if (*command=='\0' || aborted) return;
  put_vars();
  if ((pipein=popen((char *)command,READ_BIN))==(FILE*)0) {
    err_message(get_msg(M_CANTOPEN),M_PSTR,TRUE);
    return;
  }
  /*}}}  */
  if (kbd_pipe(pipein)) {
    kbd_pipe((FILE*)0);
    message(get_msg(M_KBD_PIPE_FAILED),FALSE);
  }
}
/*}}}  */
/*{{{  pipe_to_command*/
public void pipe_to_command(void)
{
  /*{{{  variables*/
  unsigned char command[_POSIX_PATH_MAX+1];
  FILE *pipeout;
  bool ch=file_changed;
  /*}}}  */

  /*{{{  errors*/
  if (tail!=real_tail) {
    message(get_msg(M_NO_TOP),TRUE);
    return;
  } else if (dialect==F_C_TDS) {
    message(get_msg(M_NOT_IF_TDS),TRUE);
    return;
  }
  /*}}}  */
  /*{{{  open pipe*/
  readprompt(command,(unsigned char*)"pipe-to-command",LINELEN);
  if (*command=='\0' || aborted) return;
  put_vars();
  if ((pipeout=popen((char *)command,"w"))==(FILE*)0) {
    err_message(get_msg(M_CANTWRITE),M_PSTR,TRUE);
    return;
  }
  /*}}}  */
  message(get_msg(M_WRITING),TRUE);
  total_save(pipeout);
  /*{{{  maybe reset cf-Flag*/
  if (ch) {
    file_changed=TRUE;
    title_op(SET_CF);
  }
  /*}}}  */
  if ((macro_int[ocl_arg]=pclose(pipeout))<0)
    err_message(get_msg(M_CLOSE_FAILED),M_PSTR,TRUE);
  else
    message(get_msg(M_WRITTEN),TRUE);
}
/*}}}  */
/*{{{  do_save_file*/
public void do_save_file(void)
{
  if (!file_changed) {
    message(get_msg(M_NO_CHANGE),TRUE);
    return;
  }
  while (tail != real_tail) exit_fold();
  total_save((FILE*)0);
}
/*}}}  */
/*{{{  dump_file*/
public char *dump_file(char *name)
{
  if (!file_changed) return name;
  while (tail != real_tail) exit_fold();
  strcpy(name,ORICORE_NAME);
  mktemp(name);
  set_data(new_file_ptr,(unsigned char*)name);
  fold_out=FALSE;
  write_fold(new_file_ptr, real_head->next, (FILE*)0);
  return(name);
}
/*}}}  */
/*{{{  save_file*/
public void save_file(void)
{
  if (!file_changed) {
    message(get_msg(M_NO_CHANGE),TRUE);
    delay_auto_write();
  } else if (dir_edit) {
    message(get_msg(M_DIR_EDIT),FALSE);
  } else if (tail == real_tail) {
    total_save((FILE*)0);
    delay_auto_write();
  } else
    message(get_msg(M_NO_TOP),TRUE);
}
/*}}}  */
/*{{{  auto_write*/
#ifdef AUTOSAVE_FILE
   public bool autosave_done=FALSE;
#endif

public void auto_write(void)
{
  if (file_changed && dir_edit)
    message(get_msg(M_DIR_EDIT),FALSE);
  else if (file_changed && tail == real_tail) {
#     ifdef AUTOSAVE_FILE
        set_data(new_file_ptr,AUTOSAVE_FILE);
        write_fold(new_file_ptr, real_head->next, (FILE*)0);
        autosave_done=TRUE;
#     else
        total_save((FILE*)0);
#     endif
     message(get_msg(M_AUTO_SAVED),TRUE);
  } else if (file_changed)
     message(get_msg(M_NO_TOP_AUTO_SAVE),TRUE);
  do_auto_save=FALSE;
  set_alarm(0);
}
/*}}}  */
/*{{{  add_edit_file*/
public void add_edit_file(char *name,bool no_cmd_line)
{  if (*name)
    { if (!file_ring)
       /*{{{  init the list*/
       { if (!(file_ring=(edit_file_buffer*)malloc(sizeof(edit_file_buffer))))
            exit_origami(r_mem_full,M_NO_MEMORY);
         file_ring->filename=0;
         file_ring->next=file_ring;
       }
       /*}}}  */
      /*{{{  add additional entry*/
      { edit_file_buffer *x=file_ring;

        /*{{{  search in list*/
        do
         { if (!strcmp(name,x->filename)) { current_ring_file=x;return; }
           x=x->next;
         }
        while (x!=file_ring);
        /*}}}  */
        /*{{{  add entry*/
        { if (!(x=(edit_file_buffer*)malloc(sizeof(edit_file_buffer))))
             exit_origami(r_mem_full,M_NO_MEMORY);
          x->next=file_ring->next;
          x->filename=file_ring->filename;
          file_ring->next=x;
          /*{{{  set filename*/
          if (no_cmd_line)
           { if (!(file_ring->filename=malloc(strlen(name)+1)))
                exit_origami(r_mem_full,M_NO_MEMORY);
             strcpy(file_ring->filename,name);
           }
          else
           { cmd_last=file_ring;
             file_ring->filename=name;
           }
          /*}}}  */
          current_ring_file=file_ring;
          file_ring=x;
        }
        /*}}}  */
      }
      /*}}}  */
    }
}
/*}}}  */
/*{{{  open_arg_list*/
public void open_arg_list(void)
{ element *x, *y, *last;
  edit_file_buffer *s;

  s=file_ring;
  current=real_head->next;
  delete_list(real_head, real_tail);
  /*{{{  body of create_list, whitout insert file*/
  last=real_head->next;
  proc_new(&head);
  head->prec = 0;
  proc_new(&tail);
  tail->next = 0;
  proc_new(&x);
  join_links(head, x);
  join_links(x, tail);
  x->foldline = START_ENTER_FILED;
  x->other_end = tail;
  tail->other_end = x;
  tail->foldline = END_FOLD;
  real_head = head;
  real_tail = tail;
  /*}}}  */
  set_data(real_head->next,(unsigned char *)"editor files");
  set_data(real_tail,empty_text);
  last=real_head->next;
  do
   /*{{{  append a line*/
   { if (s->filename)
      {
        /*{{{  line*/
        proc_new(&y);
        y->foldline=START_FILED;
        y->fold_close_line=4;
        y->UU.U1.fold_type=0;
        y->UU.U1.fold_contents=1;
        y->UU.U1.indent=0;
        y->UU.U1.fold_indent=0;
        set_data(y,(unsigned char *)s->filename);
        /*}}}  */
        /*{{{  close the fold*/
        proc_new(&x);
        x->foldline=END_FOLD;
        x->other_end=y;
        x->prec=y;
        y->fold=x;
        y->other_end=x;
        set_data(x,(unsigned char *)s->filename);
        /*}}}  */
        join_links(last,y);
        join_links(y,tail);
        last=y;
        if (s==current_ring_file) current=y;
        if (s==cmd_last)
         /*{{{  insert a empty line*/
         { proc_new(&x);
           join_links(last,x);
           join_links(x,tail);
           last=x;
         }
         /*}}}  */
      }
     s=s->next;
   }
   /*}}}  */
  while (s!=file_ring);
  current_ring_file=0;
  /*{{{  modes*/
  dir_edit=TRUE;
  file_changed=FALSE;
  title_op(RESET_CF);
  /*}}}  */
  restore_element(4);
  title_op(CHGTITLE);
#  ifdef WINDOW_TITLE_CHANGE
     chg_w_title((char*)0);
#  endif
  delay_auto_write();
  call_number_macro(auto_macro);
}
/*}}}  */
/*{{{  open_file*/
public void open_file(void)
{
  unsigned char name[_POSIX_PATH_MAX+1];

  if (file_changed && yes(get_msg(M_CHANGED_SAVE))) total_save((FILE*)0);
  if (aborted) return;
  if (!filearg) fileprompt(filearg=name);
  add_edit_file((char*)filearg,TRUE);
  if (aborted) return;
  delete_list(real_head, real_tail);
  create_list((FILE*)0);
#  ifdef WINDOW_TITLE_CHANGE
     chg_w_title((char*)0);
#  endif
  restore_element(4);
  title_op(CHGTITLE);
  file_changed=FALSE;
  title_op(RESET_CF);
  delay_auto_write();
  call_number_macro(auto_macro);
}
/*}}}  */
/*{{{  next_file*/
public void next_file(int of,char *argv[])
{ edit_file_buffer *x=file_ring;

  if (!current_ring_file) { message(get_msg(M_TOP),TRUE);return; }
  /*{{{  shift next*/
  while (of>0)
   { of--;
     while (x!=current_ring_file) x=x->next;
     filearg=(unsigned char*)x->next->filename;
   }
  /*}}}  */
  /*{{{  shift previous*/
  while (of<0)
   { of++;
     while (x->next!=current_ring_file) x=x->next;
     filearg=(unsigned char*)x->filename;
   }
  /*}}}  */
  if (filearg) open_file(); else open_arg_list();
}
/*}}}  */
/*{{{  write_file*/
public void write_file(void)
{
  /*
  if (tail == real_tail) {
    unsigned char newfilename[_POSIX_PATH_MAX+1];

    fileprompt(newfilename);
    if (*newfilename != '\0' && !aborted) {
      set_data(new_file_ptr,newfilename);
      if (dialect != F_C_TDS)
        fold_out=yes(get_msg(M_LIST));
      else
        fold_out=FALSE;
      if (!aborted) write_fold(new_file_ptr, real_head->next, (FILE*)0);
      fold_out=FALSE;
    }
  } else
    message(get_msg(M_NO_TOP),TRUE);
  */
}
/*}}}  */
