/*{{{  #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>

#include <local/bool.h>

#define WRITEFOLDS_C
#define I_DISPLAY_C
#define I_FILETYP_C
#define I_FOLDING_C
#define I_GETMSG_C
#define I_MAIN_C
#define I_MESSAGES_C
#define I_ORIEDT_C
#define I_PROMPT_C
#define I_STRING_C
#define I_VIRTUAL_C

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

/*{{{  variables*/
private element *wf_file_ptr, *wf_p, *wf_pn;
private unsigned char *wf_dsp_line;
private FILE *wf_tdsfile;
/*}}}  */

/*{{{  write_tag*/
private void write_tag(int tag,int value)
{
  if (value > 63) fputc((unsigned)(((int)value) >> 6) + 192,wf_tdsfile);
  fputc((int)((tag << 6) + (value & 63)),wf_tdsfile);
}
/*}}}  */
/*{{{  write_string*/
private void write_string(unsigned char *s)
{ int l=strlen((char *)s);

  write_tag(0,l);
  fwrite(s,(size_t)1,(size_t)l,wf_tdsfile);
}
/*}}}  */
/*{{{  write_header*/
private void write_header(void)
{
  write_tag(2, 0);   /*startlist*/
  write_string(wf_dsp_line);
  write_tag(1, (int)wf_p->UU.U1.fold_type);
  write_tag(1, (int)wf_p->UU.U1.fold_contents);
  write_tag(1, (int)wf_p->UU.U1.fold_indent);
  write_tag(2, 1);   /*endlist*/
}
/*}}}  */
/*{{{  move_on_full*/
private void move_on_full(element **p)
{
  if (filed_or_fold(*p))
    *p = (*p)->fold;
  else
    *p = (*p)->next;
}
/*}}}  */
/*{{{  write_a_list*/
private void write_a_list(void)
{
  char STR1[LINELEN + 1];

  write_tag(2, 0);
  while (wf_pn->foldline != END_FOLD) {
    wf_p = wf_pn;
    move_on_full(&wf_pn);
    strcpy((char *)wf_dsp_line,(char *)get_data(wf_p));
    trailing_spaces(wf_dsp_line);
    if (wf_p->foldline == NOT_FOLD) write_string(wf_dsp_line);
    if (wf_p->foldline == START_FOLD || wf_p->foldline == START_OPEN_FOLD) {
      write_tag(2, 2);
      write_header();
      write_a_list();
      write_tag(2, 3);   /*endfold*/
      continue;
    }
    if (wf_p->foldline != START_FILED) continue;
    write_tag(2, 4);
    write_header();
    write_string((unsigned char *)strcpy(STR1,(char *)get_data(wf_p->other_end)));
    write_tag(2, 5);   /*endfiled*/
    move_on_full(&wf_pn);
  }
  write_tag(2, 1);
  if (wf_pn->foldline == END_FOLD) move_on_full(&wf_pn);
}
/*}}}  */
/*{{{  write_tds*/
private bool write_tds(unsigned char *filename)
{
  /*{{{  open tds-file*/
  wf_tdsfile = fopen((char *)filename,WRITE_BIN);
  if (wf_tdsfile == (FILE*)0) {
    err_message(get_msg(M_CANTWRITE),filename,TRUE);
    return(FALSE);
  }
  if (is_dir(wf_tdsfile)) {
    fclose(wf_tdsfile);
    message(get_msg(M_DIR_EDIT),FALSE);
    return(FALSE);
  }
  /*}}}  */
  write_a_list();
  /*{{{  close tds-file*/
  if (fclose(wf_tdsfile)<0) {
    err_message(get_msg(M_CLOSE_FAILED),filename,TRUE);
    return(FALSE);
  }
  /*}}}  */
  message(get_msg(F_WRITTEN,filename),TRUE);
  wf_tdsfile = 0;
  return(TRUE);
}
/*}}}  */
/*{{{  write_fold*/
public bool write_fold(element *file_ptr_,element *from_ptr, FILE *pipe)
{
  /*{{{  variables*/
  unsigned char STR[LINELEN + 1];
  unsigned char dsp_line[LINELEN + 1];
  unsigned char filename[_POSIX_PATH_MAX+1];
  FILE *tstorefile;
  /*}}}  */

  /*{{{  init writing*/
  wf_dsp_line=dsp_line;
  wf_file_ptr = file_ptr_;
  wf_pn = from_ptr;
  move_on(&wf_pn);
  current_ind = 0;
  /*}}}  */
  /*{{{  get name of file*/
  strcpy((char *)filename,(char *)get_data(wf_file_ptr));
  /*}}}  */
  /*{{{  if no pipe, show writing*/
  if (pipe==(FILE*)0)
    message(get_msg(F_WRITING,filename),TRUE);
  /*}}}  */
  if (dialect != F_C_TDS) {
    /*{{{  ascii-types*/
    bool usertype=(dialect==F_C_USER) && !fold_out;

    /*{{{  open tstorefile*/
    if (pipe)
      tstorefile=pipe;
    else
      tstorefile = fopen((char *)filename,WRITE);
    if (tstorefile==(FILE*)0) {
      err_message(get_msg(M_CANTWRITE), filename,TRUE);
      return(FALSE);
    }
    if (is_dir(wf_tdsfile)) {
      fclose(wf_tdsfile);
      message(get_msg(M_DIR_EDIT),FALSE);
      return(FALSE);
    }
    /*}}}  */
    while (wf_pn != from_ptr->other_end) {   /*tail*/
      /*{{{  handle one line*/
      wf_p = wf_pn;
      copyin(wf_dsp_line, wf_p, TRUE);
      trailing_spaces(wf_dsp_line);
      if (current_ind > 0) strinsert(spaces(STR, current_ind), wf_dsp_line);
      /*{{{  maybe move #*/
      if (c_hash_front) {
        unsigned char *s=wf_dsp_line;

        while (*(s++)==' ') ;
        if (*(--s)=='#') {*s=' ';*wf_dsp_line='#';}
      }
      /*}}}  */
      /*{{{  maybe print language-mark-line*/
      if (usertype && strstr((char *)wf_dsp_line,(char *)fold_open_str)) {
        fputs((char *)dialect_start[dialect],tstorefile);
        fputs((char *)fold_open_str,tstorefile);
        fputs((char *)fold_close_str,tstorefile);
        fputs((char *)dialect_end[dialect],tstorefile);
        fputc('\n',tstorefile);
        usertype=FALSE;
      }
      /*}}}  */
      trailing_spaces(wf_dsp_line);
      fputs((char *)wf_dsp_line,tstorefile);
      fputc('\n',tstorefile);
      if (filed_or_fold(wf_p)) current_ind += total_indent(wf_p);
      if (filed_or_fold(wf_p) || wf_p->foldline == START_OPEN_FOLD)
       /*{{{  handle additional informations*/
       {
         /*{{{  generate correct fold-file-string*/
         strcpy((char *)wf_dsp_line,(char *)spaces(STR, current_ind));
         strcat((char *)wf_dsp_line,(char *)dialect_start[dialect]);
         strcat((char *)wf_dsp_line,(char *)fold_file_str);
         /*}}}  */
         if (!normal_att(wf_p,FALSE))
          /*{{{  write the tags*/
          { fputs((char *)wf_dsp_line,tstorefile);
            fputs(fold_a,tstorefile);
            fputs(i_to_a(wf_p->UU.U1.fold_type),tstorefile);
            fputc(' ',tstorefile);
            fputs(i_to_a(wf_p->UU.U1.fold_contents),tstorefile);
            fputc(' ',tstorefile);
            fputs((char *)get_data(wf_p->other_end),tstorefile);
            fputs((char *)dialect_end[dialect],tstorefile);
            fputc('\n',tstorefile);
          }
          /*}}}  */
         if (wf_p->foldline == START_FILED)
          /*{{{  write the filename*/
          { fputs((char *)wf_dsp_line,tstorefile);
            fputs(fold_f,tstorefile);
            fputs((char *)get_data(wf_p->other_end),tstorefile);
            fputs((char *)dialect_end[dialect],tstorefile);
            fputc('\n',tstorefile);
          }
          /*}}}  */
         if (wf_p->UU.U1.fold_type == 1 && wf_p->foldline == START_FILED)
          /*{{{  handle missing close-fold and indent*/
          {
            /*{{{  if !normal_att, so write the close-fold line*/
            if (!normal_att(wf_p,FALSE))
             { fputs((char *)spaces(STR, current_ind),tstorefile);
               fputs((char *)dialect_start[dialect],tstorefile);
               fputs((char *)fold_close_str,tstorefile);
               fputs((char *)tspace+1,tstorefile);
               fputs((char *)dialect_end[dialect],tstorefile);
               fputc('\n',tstorefile);
             }
            /*}}}  */
            current_ind -= total_indent(wf_p);
            wf_pn = wf_p->other_end;
          }
          /*}}}  */
       }
       /*}}}  */
      move_on_full(&wf_pn);
      if (wf_p->foldline == END_FOLD)
        if (filed_or_fold(wf_p->other_end))
          current_ind -= total_indent(wf_p->other_end);
      /*}}}  */
    }
    /*{{{  maybe print language-mark-line*/
    if (usertype) {
      fputs((char *)dialect_start[dialect],tstorefile);
      fputs((char *)fold_open_str,tstorefile);
      fputs((char *)fold_close_str,tstorefile);
      fputs((char *)dialect_end[dialect],tstorefile);
      fputc('\n',tstorefile);
      usertype=FALSE;
    }
    /*}}}  */
    /*{{{  maybe close tstorefile*/
    if (pipe==(FILE*)0) {
      if (fclose(tstorefile)<0) {
        err_message(get_msg(M_CLOSE_FAILED),filename,FALSE);
        return(FALSE);
      }
      message(get_msg(F_WRITTEN,filename),TRUE);
      tstorefile=0;
    }
    return(TRUE);
    /*}}}  */
    /*}}}  */
  } else
    return(write_tds(filename));
}
/*}}}  */
/*{{{  total_save*/
public void total_save(FILE *pipe)
{
  while (tail != real_tail) pre_exit_fold();
  if ((file_changed && !read_only) || pipe ) {
    if (write_fold(real_tail, real_head->next,pipe) && pipe==(FILE*)0) {
      file_changed=FALSE;
      title_op(RESET_CF);
    }
  }
}
/*}}}  */
