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

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

#define FOLDING_C
#define I_BUFFLOOP_C
#define I_DISPLAY_C
#define I_FINDS_C
#define I_FOLDFILING_C
#define I_FOLDHELP_C
#define I_GETMSG_C
#define I_GETTK_C
#define I_KEYBOARD_C
#define I_LOOP_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_STRING_C
#define I_VIRTUAL_C
#define I_WRITEF_C

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

/*{{{  variables*/
public element *pick_head,*pick_tail;
public unsigned char cur_dsp_line[LINELEN+1];
/*}}}  */

/*{{{  normal_att*/
public boolean normal_att(fold_data const * const p,boolean text)
{
  return
   (     p->UU.U1.type==DEFAULT_TYPE
     && ((p->UU.U1.contents==TEXT_CONTENTS)||text)
   );
}
/*}}}  */
/*{{{  insert_link_before*/
public void insert_link_before(element * const ptr_to_new)
{
  element *ptr_to_prec;

  ptr_to_new->indent=bd.f.current->indent;
  ori_assert(bd.f.cur_line_typ==get_linetyp(*bd.f.current),"check cur_linetyp");
  if (bd.f.cur_line_typ==START_OPEN_FOLD)
     ptr_to_new->indent-=bd.f.current->x.fold.UU.U1.indent;
  ptr_to_prec = bd.f.current->prec;
  if (bd.scr.start == bd.f.current)
     bd.scr.start = ptr_to_new;
  join_links(ptr_to_prec, ptr_to_new);
  join_links(ptr_to_new, bd.f.current);
  bd.f.current = ptr_to_new;
}
/*}}}  */
/*{{{  copy_a_line*/
public element *copy_a_line(void)
{
  /*{{{  check if filed fold is inside*/
  if (bd.m.dialect.typ==F_C_TDS)
   { element const *p;

     for (p=bd.f.current;p!=bd.f.current->next;p=move_on(p))
        if (test_linetyp(*p,START_FILED))
         { msg_message(M_NO_FF_COPY);
           return(0);
         }
   }
  /*}}}  */
  /*{{{  copy the line*/
  { element const *p;
    element *q, *last, *fold_ptr, *result;
    linetyp lt_last;
    boolean warned;

    /*{{{  init the links*/
    p = bd.f.current;
    last = 0;
    fold_ptr = 0; /* using other-end to store list of open folds */
    result = 0;
    warned=False;
    /*}}}  */
    while (p != bd.f.current->next)
     /*{{{  handle one line of copy-region*/
     { linetyp lt_new;

       /*{{{  copy the node to a new one*/
       q=proc_new_element();
       *q = *p;
       lt_new=get_linetyp(*q);
       /*}}}  */
       /*{{{  copy data to new node!*/
       { unsigned char const *s;

         new_data(q);   /* *q=*p destroyed the initialised data! */
         s=get_data(p);
         if (*s)
            set_data(q,s,lt_new==NOT_FOLD);
       }
       /*}}}  */
       /*{{{  handle the links and move on*/
       q->prec = last;
       if (last)
        /*{{{  handle last node*/
        { last->next = q;
          switch(lt_last)
           { case START_FOLD:
             case START_FILED:
                last->x.fold.data = q;
                break;
             case END_FOLD:
                q->prec = last->x.fold.other_end;
                q->prec->next = q;
             default:
                break;
           }
        }
        /*}}}  */
       else
        /*{{{  current line is the result!*/
          result = q;
        /*}}}  */
       /*{{{  handle current node and move on*/
       switch(lt_new)
        { case START_FILED:
             if (!warned)
                msg_message(M_FF_COPY);
             warned=True;
          case START_FOLD:
             /*{{{  store fold in other-end list*/
             q->x.fold.other_end = fold_ptr;
             fold_ptr = q;
             /*}}}  */
             p=p->x.fold.data;
             break;
          case END_FOLD:
             /*{{{  connect fold and cut other-end list*/
             q->x.fold.other_end = fold_ptr;
             fold_ptr = fold_ptr->x.fold.other_end;
             q->x.fold.other_end->x.fold.other_end = q;
             /*}}}  */
          default:
             p=p->next;
             break;
        }
       /*}}}  */
       /*}}}  */
       /*{{{  last=current*/
       lt_last=lt_new;
       last=q;
       /*}}}  */
     }
     /*}}}  */
    return(result);
  }
  /*}}}  */
}
/*}}}  */
/*{{{  chg_foldtype*/
public boolean chg_foldtype(int const type, int const contents)
{
  ori_assert(bd.f.cur_line_typ==get_linetyp(*bd.f.current),"check cur_linetyp");
  if (bd.f.cur_line_typ&(START_FILED|START_FOLD))
   { bd.f.current->x.fold.UU.U1.type=type;
     bd.f.current->x.fold.UU.U1.contents=contents;
     return(False);
   }
  return(True);
}
/*}}}  */
/*{{{  start_make_fold*/
public void start_make_fold(sel_mod mark)
{
  ori_assert(bd.f.cur_line_typ==get_linetyp(*bd.f.current),"check cur_linetyp");
  if
   (      (bd.f.cur_line_typ=get_linetyp(*bd.f.current))
        & (START_ENTER_FOLD|START_ENTER_FILED)
     || (bd.scr.cursor.w - 1)/dsp.norm>=LINELEN-5
   )
     try_unchange();
  else
   { element *p;

     p=proc_new_element();
     p->x.fold.close_line = bd.scr.cursor.h;
     bd.e.makefold_indent = (bd.scr.cursor.w - 1)/dsp.norm;
     /*{{{  set the string for p*/
     { int sp_diff;

       if (bd.f.cur_line_typ&START_OPEN_FOLD)
          sp_diff=bd.f.current->x.fold.UU.U1.indent;
       else
        { if (bd.e.makefold_indent<bd.f.current->indent)
             bd.e.makefold_indent=bd.f.current->indent;
          sp_diff=0;
        }
       spaces(line_buffer,bd.e.makefold_indent-bd.f.current->indent+sp_diff);
     }
     ustrcat(line_buffer,bd.f.str.open_f);
     set_data(p,line_buffer,False);
     /*}}}  */
     undel_before(p);
     bd.f.cur_line_typ=get_linetyp(*bd.f.current);
     bd.m.select_mode = mark;
     bd.f.select_ptr = bd.f.current;
     move_down();
   }
}
/*}}}  */
/*{{{  make_fold*/
public void make_fold(void)
{
  /*{{{  variables*/
  element *p;
  int open_count, ind, i;
  boolean indented_enough;
  int on_screen_line;
  int skip_indent;
  /*}}}  */

  /*{{{  check indentation and open/close-folds*/
  p = bd.f.select_ptr->next;
  indented_enough = True;
  open_count = 0;
  skip_indent=bd.f.select_ptr->indent;
  while (p != bd.f.current && open_count >= 0 && indented_enough)
   /*{{{  check single line*/
   { linetyp lt;

     lt=get_linetyp(*p);
     if (p==bd.f.tail)
      { msg_message(M_NO_BACK_FOLDING);
        return;
      }
     /*{{{  check indentation >= bd.e.makefold_indent*/
     /* check not across open fold boundaries,ie no of open folds=no of end folds */
     if (open_count == 0)
      { if (lt&START_OPEN_FOLD)
           indented_enough = (bd.e.makefold_indent <= p->indent);
        else if (lt&(START_FOLD|START_FILED))
           indented_enough=bd.e.makefold_indent<=(p->indent+p->x.fold.UU.U1.indent);
        else if (lt&NOT_FOLD)
         /*{{{  check spaces in front*/
         { unsigned char *s=get_data(p);

           for (i=bd.e.makefold_indent-skip_indent;i--;)
            { if (!*s)
                 break;
              else if (*s!=' ')
                 { indented_enough=False;break; }
              else
                 s++;
            }
         }
         /*}}}  */
      }
     /*}}}  */
     if (lt&START_OPEN_FOLD)
        open_count++;
     else if (lt&END_FOLD)
        open_count--;
     p = p->next;
   }
   /*}}}  */
  if (!(indented_enough && open_count == 0))
   /*{{{  complain and return*/
   { msg_message(M_FOLDERR);
     return;
   }
   /*}}}  */
  /*}}}  */
  /*{{{  change indentation data of folded lines*/
  p = bd.f.select_ptr->next;
  ind = bd.e.makefold_indent - skip_indent;
  while (p != bd.f.current)
   { linetyp lt;

     if (test_linetyp(*p,START_OPEN_FOLD)) close_fold_at(p);
     lt=get_linetyp(*p);
     if (lt&(START_FOLD|START_FILED)) p->x.fold.UU.U1.indent -= ind;
     if (lt&NOT_FOLD)
        set_data(p,strsub(get_data(p),ind+1),True);
     p->indent = 0;
     p = p->next;
   }
  /*}}}  */
  /*{{{  new node for close, join links and set data*/
  p=proc_new_element();
  insert_link_before(p);
  bd.f.End_of_fold = bd.f.current;
  bd.f.Line_after_fold = bd.f.End_of_fold->next;
  bd.f.Start_of_fold = bd.f.select_ptr;
  bd.f.Start_of_fold->x.fold.data = bd.f.Start_of_fold->next;
  bd.f.Start_of_fold->x.fold.other_end = bd.f.End_of_fold;
  bd.f.End_of_fold->x.fold.other_end = bd.f.Start_of_fold;
  bd.f.Line_after_fold->prec = bd.f.Start_of_fold;
  bd.f.Start_of_fold->next = bd.f.Line_after_fold;
  set_linetyp(*bd.f.Start_of_fold,START_FOLD);
  bd.f.Start_of_fold->indent = bd.e.makefold_indent - ind;
  bd.f.Start_of_fold->x.fold.UU.U1.indent = ind;
  set_linetyp(*bd.f.End_of_fold,END_FOLD);
  bd.f.End_of_fold->indent = 0;
  bd.f.current = bd.f.Start_of_fold;
  bd.m.select_mode = no_selection;
  upd_highlight(bd.f.select_ptr,bd.f.current,False);
  bd.f.select_ptr = 0;
  set_0_data(bd.f.End_of_fold);
  set_0_data(bd.f.Start_of_fold);
  /*}}}  */
  /*{{{  update the screen*/
  bd.scr.cursor.w=(bd.f.current->indent+bd.f.current->x.fold.UU.U1.indent+6)*dsp.norm-dsp.norm+1;
  if ((on_screen_line=on_screen(bd.f.current)))
     bd.f.current->x.fold.close_line=on_screen_line;
  restore_element(bd.f.current->x.fold.close_line);
  /* if on_screen and enough lines to fill screen */
  /*   then restore_from(on_screen_line);         */
  /*}}}  */
}
/*}}}  */
/*{{{  remove_line*/
public void remove_line(element ** const p)
{
  ori_assert(bd.f.cur_line_typ==get_linetyp(*bd.f.current),"check cur_linetyp");
  if
   (    (bd.f.cur_line_typ&(NOT_FOLD|START_FOLD|START_FILED))
     && (bd.f.current != bd.f.tail)
   )
   { if (*p)
        proc_dispose(*p);
     pre_remove_line(p);
     if (bd.scr.cursor.h < bd.scr.txt_size.h)
        up_a_bit(bd.scr.cursor.h);
     else
        clrbuffline(bd.scr.txt_size.h,1);
     if (bd.scr.end != bd.f.tail)
      { bd.scr.end = bd.scr.end->next;
        write_dsp_line(bd.scr.end, bd.scr.txt_size.h);
      }
     else
      { bd.scr.end_level--;
        whole_screen_down();
      }
   }
}
/*}}}  */
/*{{{  pre_enter_fold*/
private void pre_enter_fold(element * const cur)
{
  check_fold(cur);
  bd.f.Line_after_fold->prec = bd.f.End_of_fold;
  bd.f.entered++;
  bd.scr.cursor.w-=(bd.f.Start_of_fold->indent+bd.f.Start_of_fold->x.fold.UU.U1.indent)*dsp.norm;
  bd.f.enter_spaces+=bd.f.Start_of_fold->indent+bd.f.Start_of_fold->x.fold.UU.U1.indent;
  bd.f.Start_of_fold->next = bd.f.Start_of_fold->x.fold.data;
  set_linetyp(*bd.f.Start_of_fold,START_ENTER_FOLD);
  bd.f.Start_of_fold->x.fold.data = bd.f.head;
  bd.f.head = bd.f.Start_of_fold->prec;
  bd.f.End_of_fold->x.fold.data = bd.f.tail;
  bd.f.tail = bd.f.End_of_fold;
  /*save indent*/
  bd.f.End_of_fold->x.fold.UU.U1.indent = bd.f.Start_of_fold->indent;
  bd.f.Start_of_fold->indent = 0;
}
/*}}}  */
/*{{{  erase_current_link*/
private void erase_current_link(void)
{
  element *prec_ptr, *p;

  if (bd.f.current != bd.f.tail)
   { p = bd.f.current;
     prec_ptr = p->prec;
     bd.f.current = p->next;
     proc_dispose(p);
     join_links(prec_ptr, bd.f.current);
   }
}
/*}}}  */
/*{{{  delete_list*/
public void delete_list(element *from_ptr, element * const to_ptr)
{
  for(;;)
   { element *p;

     p = from_ptr->next;
     proc_dispose(from_ptr);
     if (from_ptr==to_ptr)
        break;
     from_ptr = p;
   }
}
/*}}}  */
/*{{{  pre_exit_fold*/
public void pre_exit_fold(void)
{
  element *p;

  bd.f.entered--;
  bd.f.Start_of_fold = bd.f.head->next;
  bd.f.End_of_fold = bd.f.tail;
  bd.f.Line_after_fold = bd.f.tail->next;
  bd.f.tail = bd.f.End_of_fold->x.fold.data;
  set_linetyp(*bd.f.Start_of_fold,START_FOLD);
  bd.f.head = bd.f.Start_of_fold->x.fold.data;
  bd.f.Start_of_fold->x.fold.data = bd.f.Start_of_fold->next;
  bd.f.Start_of_fold->next = bd.f.Line_after_fold;
  bd.f.Line_after_fold->prec = bd.f.Start_of_fold;
  /*restore indent*/
  bd.f.Start_of_fold->indent = bd.f.End_of_fold->x.fold.UU.U1.indent;
  bd.scr.cursor.w+=(bd.f.Start_of_fold->indent+bd.f.Start_of_fold->x.fold.UU.U1.indent)*dsp.norm;
  bd.f.enter_spaces-=bd.f.Start_of_fold->indent+bd.f.Start_of_fold->x.fold.UU.U1.indent;
  bd.f.current = bd.f.Start_of_fold;
  check_fold(bd.f.current);
  for (p=bd.f.Start_of_fold->x.fold.data;;)
   { switch (get_linetyp(*p))
      { case END_FOLD:
           break;
        case START_OPEN_FOLD:
           close_fold_at(p);
        default:
           p=p->next;
           continue;
      }
     break;
   }
}
/*}}}  */
/*{{{  pre_top_fold*/
public void pre_top_fold(void)
{
  while (bd.f.tail != bd.f.real_tail)
     pre_exit_fold();
}
/*}}}  */
/*{{{  pre_pre_open_fold*/
private void pre_pre_open_fold(element * const q)
{
  check_fold(q);
  bd.f.Line_after_fold->prec = bd.f.End_of_fold;
  bd.f.Start_of_fold->next = bd.f.Start_of_fold->x.fold.data;
  set_linetyp(*bd.f.Start_of_fold,START_OPEN_FOLD);
}
/*}}}  */
/*{{{  pre_open_fold*/
public void pre_open_fold(element * const q)
{
  element *p;
  int i;

  pre_pre_open_fold(q);
  p = bd.f.Start_of_fold;
  i=p->indent+p->x.fold.UU.U1.indent;
  p->indent = i;
  do
   { p = p->next;
     p->indent += i;
   }
  while (p != bd.f.End_of_fold);
}
/*}}}  */
/*{{{  enter_fold*/
public void enter_fold(unsigned char const * const f_name)
{ element *p;

  title_op(CHGXY);
  ori_assert(bd.f.cur_line_typ==get_linetyp(*bd.f.current),"check cur_linetyp");
  if (!f_name && bd.f.cur_line_typ&START_FOLD)
   /*{{{  normal fold -> enter*/
   { bd.f.current->x.fold.close_line = bd.scr.cursor.h;
     pre_enter_fold(bd.f.current);
     bd.f.current = bd.f.current->next;
     restore_element(DEF_CURSOR_LINE);
   }
   /*}}}  */
  else
   /*{{{  try to enter file*/
   { unsigned char const *filename;
     int return_line_no;

     add_edit_file((char*)0,cur_line_no(),False);
     return_line_no=cur_line_no()-line_no(bd.f.head->next,bd.f.real_head);
     if (!f_name && bd.f.cur_line_typ&START_FILED)
      /*{{{  check filed fold*/
        if (!normal_att(&(bd.f.current->x.fold),True))
         /*{{{  no access*/
         { msg_message(M_NO_TEXT);
           return;
         }
         /*}}}  */
        else if (bd.f.current->x.fold.data != bd.f.current->x.fold.other_end)
         /*{{{  no list enter*/
         { msg_message(M_NO_ENTER_LIST_FF);
           return;
         }
         /*}}}  */
        else
         { unsigned char f_buff[_POSIX_PATH_MAX+1];

           ustrcpy(f_buff,get_data(bd.f.current->x.fold.other_end));
           home_expand((char*)f_buff);
           filename=f_buff;
           if (access((char *)filename,R_OK) == -1)
              if
               /*{{{  can get dirname(current-file)/name)*/
               (    bd.f.real_tail!=bd.f.real_head
                 && join_fd(f_buff,get_data(bd.f.real_tail))
               )
               /*}}}  */
               /*{{{  test, if existing*/
                 if (access((char*)filename,R_OK)==-1)
                    goto enter_cant_open;
                 else
                    warn_message(get_msg(F_ADD_PATH,filename));
               /*}}}  */
              else
               /*{{{  cannot open file*/
               { enter_cant_open:

                 err_message
                  ( M_CANTOPEN,
                    get_data(bd.f.current->x.fold.other_end)
                  );
                 return;
               }
               /*}}}  */
           add_history(file_history,filename);
           p = bd.f.current;
           total_save((FILE*)0);
           if
            (    bd.m.file_changed_status!=unchanged_file
              && !yes(get_msg(M_NO_SAVE_CANCEL))
            )
              return;
           bd.scr.cursor.w = 1;
           bd.f.current = p;
           set_data(bd.f.current->x.fold.other_end,f_buff,False);
           set_linetyp(*bd.f.current,START_FOLD); /* for copy ! */
         }
      /*}}}  */
     else
      /*{{{  get filename to push on enter-stack*/
      { unsigned char buff[_POSIX_PATH_MAX+1];
        unsigned char *hd;
        int cursor_x_pos;

        if (f_name)
         /*{{{  use given name*/
         { filename=hd=buff;
           ustrcpy(hd,f_name);
         }
         /*}}}  */
        else
         /*{{{  get filename from line or prompt*/
         { filename=(hd=get_data(bd.f.current));
           cursor_x_pos=scr2txt(bd.f.enter_spaces,bd.scr.cursor.w,filename);
           /*{{{  get filename*/
           /*{{{  copy pattern from current line*/
           while (cursor_x_pos--)
              if (*filename ) filename++; else break;
           { unsigned char *d=buff;
             int i=0;

             while
              (   *filename
               && *filename!='"'
               && *filename!='\''
               && *filename!=' '
               && *filename!='\t'
               && i<_POSIX_PATH_MAX
              ) *d++ = *filename++;
             *d='\0';
           }
           /*}}}  */
           filename=buff;
           if (!*filename || access((char*)filename,R_OK) == -1)
              hd=fileprompt(buff);
           else
              add_history(file_history,filename);
           if (aborted || !*filename) return;
           /*}}}  */
         }
         /*}}}  */
        find_element(cur_line_no(),bd.scr.cursor.h);
        total_save((FILE*)0);
        restore_element(bd.scr.cursor.h);
        if
         (    bd.m.file_changed_status!=unchanged_file
           && !yes(get_msg(M_NO_SAVE_CANCEL))
         )
           return;
        /*{{{  make fold for filename, after save!*/
        for (;;)
         { ori_assert(bd.f.cur_line_typ==get_linetyp(*bd.f.current),"check cur_linetyp");
           if (bd.f.cur_line_typ&(START_ENTER_FOLD|START_ENTER_FILED))
            { move_down();
              bd.f.cur_line_typ=get_linetyp(*bd.f.current);
            }
           else
              break;
         }
        ocl_screen_off();
        start_make_fold(False);
        make_fold();
        ocl_screen_on();
        set_data(bd.f.current,hd,False);
        set_data(bd.f.current->x.fold.other_end,filename,False);
        /*}}}  */
      }
      /*}}}  */
     /*{{{  read the filed fold*/
     if (!bd.m.user_view) bd.m.read_only=False;
     bd.f.real_tail->x.fold.UU.U0.old_line=return_line_no;
     bd.f.real_tail->x.fold.UU.U0.v_mode = bd.m.read_only;
     bd.f.real_tail->x.fold.close_line = bd.scr.cursor.h;
     p=copy_a_line();
     bd.f.current = p;
     delete_list(bd.f.head->next->next, bd.f.tail->prec);   /*except for bd.f.tail/bd.f.head*/
     set_linetyp(*bd.f.current,START_ENTER_FILED);
     bd.f.real_tail = bd.f.current->x.fold.data;
     bd.f.current->next = bd.f.real_tail;
     bd.f.head = bd.f.real_head->next;
     join_links(bd.f.head, bd.f.current);
     bd.f.real_head = bd.f.head;
     join_links(bd.f.real_tail, bd.f.tail);
     bd.f.tail = bd.f.real_tail;   /*ie file_ptr*/
     bd.m.file_changed_status=unchanged_file;
     title_op(CHGTITLE);
     if (f_name && !(*f_name))
      { gen_arg_list(bd.f.head,bd.f.tail);
        bd.f.current=bd.f.head->next;
      }
     else
      { insert_file(bd.f.tail,bd.f.current,bd.f.tail,True,bd.f.real_head,&bd.m.dir_edit,&bd.f.count_comment_line,(FILE*)0);
        bd.f.current = bd.f.current->next;
      }
     restore_element(DEF_CURSOR_LINE);
#     ifdef WINDOW_TITLE_CHANGE
        wt_buff_id= -1;
#     endif
     /*}}}  */
     call_number_macro(auto_macro);
     /*{{{  current_ring_file*/
     bd.e.file_no=add_edit_file((char*)get_data(bd.f.real_tail),1,True);
     /*}}}  */
     warn_mult_edit();
   }
   /*}}}  */
}
/*}}}  */
/*{{{  exit_fold*/
public void exit_fold(void)
{
  title_op(CHGXY);
  if (bd.f.tail != bd.f.real_tail)
   /*{{{  normal fold, exit it*/
   { pre_exit_fold();
     restore_element(bd.f.current->x.fold.close_line);
     return;
   }
   /*}}}  */
  else if (bd.f.real_tail->next == (element*)0 && !*get_data(bd.f.real_tail))
   /*{{{  top, fail*/
   { msg_message(M_TOP);
     return;
   }
   /*}}}  */
  else
   /*{{{  save file and read surrounding file*/
   { total_save((FILE*)0);
     add_edit_file((char*)0,cur_line_no(),False);
     if (bd.m.file_changed_status!=unchanged_file)
        if (yes(get_msg(M_NO_SAVE_CANCEL)))
         { bd.m.file_changed_status=unchanged_file;
           title_op(CHGTITLE);
         }
        else
           return;
     if
      (    !bd.f.real_tail->next
        || !get_data(bd.f.real_tail->next)[0]
      )
      /*{{{  surrounding file is the list of edited files*/
        open_arg_list();
      /*}}}  */
     else
      /*{{{  open the normal filed fold*/
      {
        /*{{{  remove data of entered file*/
        bd.f.real_tail = bd.f.tail->next;
        bd.f.real_head = bd.f.head->prec;
        delete_list(bd.f.head->next, bd.f.tail);
        join_links(bd.f.head,bd.f.real_tail);
        bd.f.tail = bd.f.real_tail;
        bd.f.head = bd.f.real_head;
        /*}}}  */
        /*{{{  show new, corrected title, before reading!*/
        bd.m.read_only=(bd.f.real_tail->x.fold.UU.U0.v_mode||bd.m.user_view);
        title_op(CHGTITLE);
        /*}}}  */
        /*{{{  get file*/
        { int l=bd.f.real_tail->x.fold.UU.U0.old_line;

          bd.f.real_tail->x.fold.UU.U0.old_line=0;
          insert_file(bd.f.tail,bd.f.head->next,bd.f.tail,True,bd.f.real_head,&bd.m.dir_edit,&bd.f.count_comment_line,(FILE*)0);
          find_element(l,bd.f.real_tail->x.fold.close_line);
        }
        /*}}}  */
        /*{{{  update title and windowtitle*/
        title_op(CHGTITLE);
#        ifdef WINDOW_TITLE_CHANGE
           wt_buff_id= -1;
#        endif
        /*}}}  */
        call_number_macro(auto_macro);
        /*{{{  current_ring_file*/
        bd.e.file_no=add_edit_file((char*)get_data(bd.f.real_tail),1,True);
        /*}}}  */
      }
      /*}}}  */
     warn_mult_edit();
   }
   /*}}}  */
}
/*}}}  */
/*{{{  open_fold*/
public void open_fold(void)
{
  ori_assert(bd.f.cur_line_typ==get_linetyp(*bd.f.current),"check cur_linetyp");
  if (!(bd.f.cur_line_typ&START_FOLD))
     msg_message(M_NO_SIMPLE_FOLD);
  else
   { bd.f.current->x.fold.close_line = bd.scr.cursor.h;
     pre_open_fold(bd.f.current);
     restore_to_end(bd.scr.cursor.h);
   }
}
/*}}}  */
/*{{{  close_fold*/
public void close_fold(void)
{
  element *p;
  linetyp lt;

  p = bd.f.current;
  if (test_linetyp(*p,END_FOLD))
     p = p->x.fold.other_end;
  while (p!=bd.f.head && (lt=get_linetyp(*p))!=START_OPEN_FOLD)
   { if (lt==END_FOLD)
        p=p->x.fold.other_end->prec;
     else
        p=p->prec;
   }
  if (p != bd.f.head)
   { bd.f.current = p;
     close_fold_at(p);
     title_op(CHGXY);
     restore_or_restore_to_end();
   }
  else if (bd.f.tail != bd.f.real_tail)
     msg_message(M_USE_EXIT);
  else
     verbose_msg_message(M_TOP);
}
/*}}}  */
/*{{{  unfold*/
public void unfold(void)
{
  element *new, *p;
  int ind, f_ind;

  if (!test_linetyp(*bd.f.current,START_FOLD))
   /*{{{  complain*/
   { msg_message(M_NO_SIMPLE_FOLD);
     try_unchange();
   }
   /*}}}  */
  else
   /*{{{  do it*/
   { ind = bd.f.current->indent;
     f_ind = bd.f.current->x.fold.UU.U1.indent;
     pre_pre_open_fold(bd.f.current);
     new = bd.f.Start_of_fold->next;
     p = new;
     while (p != bd.f.End_of_fold)
      { p->indent = ind;
        if (test_linetyp(*p,NOT_FOLD))
         { spaces(line_buffer,f_ind);
           ustrcat(line_buffer,get_data(p));
           set_data(p,line_buffer,True);
         }
        else
           p->x.fold.UU.U1.indent += f_ind;
        p = p->next;
      }
     if (new == bd.f.End_of_fold)
        new = bd.f.Line_after_fold;
     bd.f.current = bd.f.End_of_fold;
     erase_current_link();
     bd.f.current = bd.f.Start_of_fold;
     erase_current_link();
     bd.f.current = new;
     if (bd.scr.start == bd.f.Start_of_fold)
        restore_element(DEF_CURSOR_LINE);
     else if (new == bd.f.Line_after_fold)
        restore_or_restore_to_end();
     else
        restore_to_end(bd.scr.cursor.h);
   }
   /*}}}  */
}
/*}}}  */
/*{{{  create_list*/
public void create_list(void)
{
  element *p;

  bd.f.head=proc_new_element();
  bd.f.head->prec = 0;
  bd.f.tail=proc_new_element();
  bd.f.tail->next = 0;
  p=proc_new_element();
  join_links(bd.f.head, p);
  join_links(p, bd.f.tail);
  set_linetyp(*p,START_ENTER_FILED);
  p->x.fold.other_end = bd.f.tail;
  bd.f.tail->x.fold.other_end = p;
  set_linetyp(*bd.f.tail,END_FOLD);
  bd.f.real_head = bd.f.head;
  bd.f.real_tail = bd.f.tail;
  insert_file((element *)0,p,bd.f.tail,True,bd.f.head,&bd.m.dir_edit,&bd.f.count_comment_line,(FILE*)0);
  bd.f.current = p->next;
}
/*}}}  */
/*{{{  chg_marks*/
/*{{{  get_mark*/
private boolean get_mark
 ( unsigned char * const s,
   unsigned char const * const def,
   unsigned char const * const f
 )
{
  s_readprompt(s,f,FOLD_TAG_LENGTH,no_history);
  if (!aborted)
     switch (s[0])
      { case '\0':
           ustrcpy(s,def);
        default:
           if (ustrlen(s)==FOLD_TAG_LENGTH)
              return(False);
        case ' ':
        case '\t':
           break;
      }
  msg_message(M_FAILED);
  return(True);
}
/*}}}  */

public void chg_marks(void)
{
  struct f_m_str s;

  if
   (   get_mark(s.open_f,(unsigned char*)BEGIN_STANDARD,(unsigned char*)STR_M_F_BEG)
    || get_mark(s.file_f,(unsigned char*)FILE_STANDARD,(unsigned char*)STR_M_F_NAM)
    || get_mark(s.line_f,(unsigned char*)LINE_STANDARD,(unsigned char*)STR_M_F_LIN)
    || get_mark(s.close_f,(unsigned char*)END_STANDARD,(unsigned char*)STR_M_F_END)
    || (    !ustrcmp(bd.f.str.open_f,s.open_f)
         && !ustrcmp(bd.f.str.close_f,s.close_f)
         && !ustrcmp(bd.f.str.file_f,s.file_f)
         && !ustrcmp(bd.f.str.line_f,s.line_f)
       )
   )
     try_unchange();
  else
   /*{{{  change the marks*/
   { set_fold_mark_dsp_length(&s);
     init_buffer.f.str=bd.f.str=s;
     restore(1);
   }
   /*}}}  */
}
/*}}}  */
