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

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

#define WRITEFOLDS_C
#define I_LOOP_C
#define I_DISPLAY_C
#define I_FOLDING_C
#define I_FOLDHELP_C
#define I_GETMSG_C
#define I_GETTK_C
#define I_KEYBOARD_C
#define I_MAIN_C
#define I_MESSAGES_C
#define I_ORIEDT_C
#define I_PROMPT_C
#define I_READFOLDS_C
#define I_VIRTUAL_C

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

/*{{{  variables*/
private element const *wf_pn;
private element const *wf_p;
private unsigned char *wf_dsp_line;
private FILE *wf_tdsfile;
public int current_ind;
/*}}}  */

/*{{{  write_fold*/
/*{{{  move_on_full_wf_pn*/
private void move_on_full_wf_pn(void)
{
  if (test_linetyp(*wf_pn,(START_FOLD|START_FILED)))
    wf_pn = wf_pn->x.fold.data;
  else
    wf_pn = wf_pn->next;
}
/*}}}  */
/*{{{  write_tds*/
/*{{{  write_tag*/
private void write_tag(int tag,int value)
{
  if (value > 63)
   { fputc((unsigned)(((int)value) >> 6) + 192,wf_tdsfile);
     file_io_size.c++;
   }

  fputc((int)((tag << 6) + (value & 63)),wf_tdsfile);
  file_io_size.c++;
}
/*}}}  */
/*{{{  write_string*/
private void write_string(unsigned char const * const s)
{ int l=ustrlen(s);

  write_tag(0,l);
  fwrite(s,(size_t)1,(size_t)l,wf_tdsfile);
  file_io_size.c+=l;
}
/*}}}  */
/*{{{  write_header*/
private void write_header(void)
{
  write_tag(2, 0);   /*startlist*/
  write_string(wf_dsp_line);
  write_tag(1, (int)wf_p->x.fold.UU.U1.type);
  write_tag(1, (int)wf_p->x.fold.UU.U1.contents);
  write_tag(1, (int)wf_p->x.fold.UU.U1.indent);
  write_tag(2, 1);   /*endlist*/
}
/*}}}  */
/*{{{  write_a_list*/
private void write_a_list(void)
{
  linetyp lt;

  write_tag(2, 0);
  while ((lt=get_linetyp(*wf_pn)) != END_FOLD)
   { if (aborted)
        return;
     wf_p = wf_pn;
     move_on_full_wf_pn();
     ustrcpy(wf_dsp_line,get_data(wf_p));
     trailing_spaces(wf_dsp_line);
     switch (lt)
      { case NOT_FOLD:
           write_string(wf_dsp_line);
           file_io_size.l++;
        default:
           break;
        case START_FOLD:
        case START_OPEN_FOLD:
           file_io_size.l+=2;
           write_tag(2, 2);
           write_header();
           write_a_list();
           write_tag(2, 3);   /*endfold*/
           continue;
        case START_FILED:
           file_io_size.l+=3;
           write_tag(2, 4);
           write_header();
           write_string(get_data(wf_p->x.fold.other_end));
           write_tag(2, 5);   /*endfiled*/
           move_on_full_wf_pn();
           continue;
      }
   }
  write_tag(2, 1);
  move_on_full_wf_pn();
}
/*}}}  */

private boolean write_tds(unsigned char const * const filename)
{
  /*{{{  open tds-file*/
  wf_tdsfile = fopen((char *)filename,(char*)"wb");
  if (wf_tdsfile == (FILE*)0)
   { err_message(M_CANTWRITE,filename);
     return(False);
   }
  /*}}}  */
  write_a_list();
  /*{{{  close tds-file*/
  if (fclose(wf_tdsfile)<0)
   { err_message(M_CLOSE_FAILED,filename);
     return(False);
   }
  /*}}}  */
  message
   ( get_msg
      ( F_SIZE_FILE,
        filename,
        "wrote",
        file_io_size.l,
        file_io_size.c
      )
   );
  wf_tdsfile = 0;
  return(!aborted);
}
/*}}}  */
/*{{{  w_lang_mark*/
private void w_lang_mark(FILE * const tstorefile)
{
  unsigned char *m;

  m=get_msg
     ( MSG_ARG_FORMAT,
       "%s%s%s%s\n",
       dialects[bd.m.dialect.typ].txt.start,
       bd.f.str.open_f,
       bd.f.str.close_f,
       dialects[bd.m.dialect.typ].txt.end
    );
  fputs((char*)m,tstorefile);
  file_io_size.c+=ustrlen(m);
  file_io_size.l++;
}
/*}}}  */

public boolean write_fold
 ( unsigned char const * const filename,
   element const * const from_ptr,
   FILE * const write_pipe
 )
{
  /*{{{  variables*/
  unsigned char dsp_line[LINELEN + 1];
  FILE *tstorefile;
  /*}}}  */

  /*{{{  init writing*/
  wf_dsp_line=dsp_line;
  wf_pn = from_ptr;
  wf_pn=move_on(wf_pn);
  current_ind = 0;
  file_io_size.c=0;
  file_io_size.l=0;
  /*}}}  */
  /*{{{  if not pipe, check dir and show write string*/
  if (write_pipe==(FILE*)0)
     if (is_dir((FILE*)0,(char*)filename))
      { msg_message(M_DIR_EDIT);
        return(False);
      }
     else
        message(get_msg(F_WRITING,filename));
  /*}}}  */
  if (bd.m.dialect.typ != F_C_TDS)
   /*{{{  ascii-types*/
   { boolean mark_comments=(bd.m.dialect.typ!=F_C_NONE) && !no_fold_out;

     /*{{{  open tstorefile*/
     if (write_pipe)
       tstorefile=write_pipe;
     else
       tstorefile = fopen((char *)filename,(char*)"w");
     if (tstorefile==(FILE*)0)
      { err_message(M_CANTWRITE,filename);
        return(False);
      }
     if (is_dir(wf_tdsfile,(char*)0)) {
       fclose(wf_tdsfile);
       msg_message(M_DIR_EDIT);
       return(False);
     }
     /*}}}  */
     if (!executing_macro) enable_abort();
     while (wf_pn != from_ptr->x.fold.other_end && !aborted)    /*tail*/
      /*{{{  handle one line*/
      { linetyp lt;

        wf_p = wf_pn;
        lt=get_linetyp(*wf_p);
        /*{{{  get text data for current line and move #*/
        { unsigned char *s;

          s=wf_dsp_line;
          /*{{{  get line data*/
          if (current_ind>0)
           { spaces(wf_dsp_line,current_ind);
             copyin(s+=current_ind,wf_p,True);
             if (!*s)
              { wf_dsp_line[0]='\0';
                goto no_hash_shift;
              }
           }
          else
             copyin(s,wf_p,True);
          /*}}}  */
          if (bd.m.hash_shift)
           /*{{{  move #*/
           { for (;;s++)
              { switch (*s)
                 { case '#':
                      *s=' ';
                      *wf_dsp_line='#';
                   default:
                      break;
                   case ' ':
                      continue;
                 }
                break;
              }
           }
           /*}}}  */
          no_hash_shift:;
        }
        /*}}}  */
        /*{{{  maybe print language-mark-line*/
        if (mark_comments && lt!=NOT_FOLD) {
          int i;

          for
           ( i=(lt&(START_FOLD|START_FILED))
                ? wf_p->indent+wf_p->x.fold.UU.U1.indent
                : current_ind+wf_p->indent
           ; i--
           ; file_io_size.c++
           )
             fputc(' ',tstorefile);
          w_lang_mark(tstorefile);
          mark_comments=False;
        }
        /*}}}  */
        /*{{{  write the line*/
        fputs((char *)wf_dsp_line,tstorefile);
        fputc('\n',tstorefile);
        /*}}}  */
        /*{{{  count chars and lines*/
        file_io_size.l++;
        file_io_size.c+=ustrlen(wf_dsp_line)+1;
        /*}}}  */
        switch (lt)
         { case START_FOLD:
           case START_FILED:
              current_ind+=wf_p->indent+wf_p->x.fold.UU.U1.indent;
           case START_OPEN_FOLD:
            /*{{{  handle additional informations*/
            { boolean norm_att_f;

              /*{{{  generate correct fold-file-string*/
              spaces(wf_dsp_line,current_ind);
              ustrcat(wf_dsp_line,dialects[bd.m.dialect.typ].txt.start);
              ustrcat(wf_dsp_line,bd.f.str.file_f);
              /*}}}  */
              norm_att_f=normal_att(&(wf_p->x.fold),False);
              if (!norm_att_f)
               /*{{{  write the tags*/
               { unsigned char *a;

                 a=get_msg
                    ( MSG_ARG_FORMAT,
                      "%s%s%d %d %s%s\n",
                      wf_dsp_line,
                      fold_a,
                      wf_p->x.fold.UU.U1.type,
                      wf_p->x.fold.UU.U1.contents,
                      get_data(wf_p->x.fold.other_end),
                      dialects[bd.m.dialect.typ].txt.end
                    );
                 fputs((char*)a,tstorefile);
                 /*{{{  count chars and lines*/
                 file_io_size.c+=ustrlen(a);
                 file_io_size.l++;
                 /*}}}  */
               }
               /*}}}  */
              else if (lt==START_FILED)
               /*{{{  write the filename*/
               { unsigned char *a;

                 a=get_msg
                    ( MSG_ARG_FORMAT,
                      "%s%s%s%s\n",
                      wf_dsp_line,
                      fold_f,
                      get_data(wf_p->x.fold.other_end),
                      dialects[bd.m.dialect.typ].txt.end
                    );
                 fputs((char*)a,tstorefile);
                 /*{{{  count chars and lines*/
                 file_io_size.c+=ustrlen(a);
                 file_io_size.l++;
                 /*}}}  */
                 if (wf_p->x.fold.UU.U1.type == 1)
                  /*{{{  handle missing close-fold and indent*/
                  {
                    /*{{{  if !normal_att, so write the close-fold line*/
                    if (!norm_att_f)
                     { if (current_ind)
                        { int x=current_ind;

                          do
                           { fputc(' ',tstorefile);
                             file_io_size.c++;
                           }
                          while (--x>0);
                        }
                       a=get_msg
                          ( MSG_ARG_FORMAT,
                            "%s%s  %s\n",
                            dialects[bd.m.dialect.typ].txt.start,
                            bd.f.str.close_f,
                            dialects[bd.m.dialect.typ].txt.end
                          );
                       fputs((char*)a,tstorefile);
                       /*{{{  count chars and lines*/
                       file_io_size.c+=ustrlen(a);
                       file_io_size.l++;
                       /*}}}  */
                     }
                    /*}}}  */
                    current_ind-=wf_p->indent+wf_p->x.fold.UU.U1.indent;
                    wf_pn = wf_p->x.fold.other_end;
                  }
                  /*}}}  */
               }
               /*}}}  */
            }
            /*}}}  */
           default:
              break;
         }
        move_on_full_wf_pn();
        if (lt==END_FOLD)
          if (test_linetyp(*(wf_p->x.fold.other_end),(START_FOLD|START_FILED)))
            current_ind-=
                 wf_p->x.fold.other_end->indent
               + wf_p->x.fold.other_end->x.fold.UU.U1.indent;
      }
      /*}}}  */
     if (!executing_macro) disable_abort();
     /*{{{  maybe print language-mark-line*/
     if (mark_comments) w_lang_mark(tstorefile);
     /*}}}  */
     /*{{{  show wrote message*/
     message
      ( get_msg
         ( F_SIZE_FILE,
           (write_pipe?M_PSTR:filename),
           "wrote",
           file_io_size.l,
           file_io_size.c
         )
      );
     /*}}}  */
     /*{{{  maybe close tstorefile*/
     if (write_pipe==(FILE*)0) {
       if (fclose(tstorefile)<0)
        { err_message(M_CLOSE_FAILED,filename);
          return(False);
        }
     }
     return(!aborted);
     /*}}}  */
   }
   /*}}}  */
  else
    return(write_tds(filename));
}
/*}}}  */
/*{{{  total_save*/
public void total_save(FILE * const write_pipe)
{
  pre_top_fold();
  if
   (    (bd.m.file_changed_status!=unchanged_file && !bd.m.read_only)
     || write_pipe
   )
     if
      (    write_fold(get_data(bd.f.real_tail),bd.f.real_head->next,write_pipe)
        && write_pipe==(FILE*)0
      )
      { bd.m.file_changed_status=unchanged_file;
        title_op(CHGTITLE);
      }
}
/*}}}  */
