/*
 * $Id: datafile.h,v 1.21 2007/02/23 17:46:17 sfeam Exp $
 */

/* GNUPLOT - datafile.h */

/*[
 * Copyright 1986 - 1993, 1998, 2004   Thomas Williams, Colin Kelley
 *
 * Permission to use, copy, and distribute this software and its
 * documentation for any purpose with or without fee is hereby granted,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.
 *
 * Permission to modify the software is granted, but not the right to
 * distribute the complete modified source code.  Modifications are to
 * be distributed as patches to the released version.  Permission to
 * distribute binaries produced by compiling modified sources is granted,
 * provided you
 *   1. distribute the corresponding source modifications from the
 *    released version in the form of a patch file along with the binaries,
 *   2. add special version identification to distinguish your version
 *    in addition to the base release version number,
 *   3. provide your name and address as the primary contact for the
 *    support of your modified version, and
 *   4. retain our contact information in regard to use of the base
 *    software.
 * Permission to distribute the released version of the source code along
 * with corresponding source modifications in the form of a patch file is
 * granted with same provisions 2 through 4 for binary distributions.
 *
 * This software is provided "as is" without express or implied warranty
 * to the extent permitted by applicable law.
]*/

#ifndef GNUPLOT_DATAFILE_H
# define GNUPLOT_DATAFILE_H

/* #if... / #include / #define collection: */

#include "axis.h"
#include "graph3d.h"
#include "graphics.h"

/* returns from DF_READLINE in datafile.c */
/* +ve is number of columns read */
#define DF_EOF          (-1)
#define DF_UNDEFINED    (-2)
#define DF_FIRST_BLANK  (-3)
#define DF_SECOND_BLANK (-4)
#define DF_MISSING      (-5)
#define DF_FOUND_KEY_TITLE   (-6)
#define DF_KEY_TITLE_MISSING (-7)
#define DF_STRINGDATA	(-8)
#define DF_BAD		(0)
#define	DF_GOOD		(1)

#ifdef EAM_HISTOGRAMS
/* should really be a parameter to df_readline rather than a global */
extern struct curve_points *df_current_plot;
#endif


#ifndef MAXINT			/* should there be one already defined ? */
# ifdef INT_MAX			/* in limits.h ? */
#  define MAXINT INT_MAX
# else
#  define MAXINT ((~0)>>1)
# endif
#endif

/* Variables of datafile.c needed by other modules: */

/* how many using columns were specified, and max possible */
extern int df_no_use_specs;
#define MAXDATACOLS 7

/* suggested x value if none given */
extern int df_datum;

/* is this a matrix splot? */
extern TBOOLEAN df_matrix;

/* is this a binary file? */
extern TBOOLEAN df_binary;

extern int df_eof;
extern int df_line_number;
extern AXIS_INDEX df_axis[];
extern struct udft_entry ydata_func; /* HBB 990829: moved from command.h */

#ifdef EAM_DATASTRINGS
/* Returned to caller by df_readline() */
extern char *df_tokens[];
#endif

/* string representing missing values, ascii datafiles */
extern char *missing_val;

/* input field separator, NUL if whitespace is the separator */
extern char df_separator;

/* comments chars */
extern char *df_commentschars;

/* flag if any 'inline' data are in use, for the current plot */
extern TBOOLEAN plotted_data_from_stdin;

/* Setting this allows the parser to recognize Fortran D or Q   */
/* format constants in the input file. But it slows things down */
extern TBOOLEAN df_fortran_constants;

/* Prototypes of functions exported by datafile.c */

int df_open (const char *, int);
int df_readline (double [], int);
void df_close (void);
void df_showdata (void);
int df_2dbinary (struct curve_points *);
int df_3dmatrix (struct surface_points *, int);
#ifdef EAM_DATASTRINGS
void df_set_key_title (struct curve_points *);
int expect_string (const char column );
#endif

void df_reset_after_error (void);
void f_dollars (union argument *x);
void f_column  (union argument *x);
void f_valid   (union argument *x);
void f_timecolumn   (union argument *x);
#ifdef GP_STRING_VARS
void f_stringcolumn   (union argument *x);
#endif

struct use_spec_s {
    int column;
#ifdef EAM_DATASTRINGS
    int expected_type;
#endif
    struct at_type *at;
};

#ifndef BINARY_DATA_FILE
#define df_set_plot_mode(mode)	/* Not needed except for binary data files */
#endif

#ifdef BINARY_DATA_FILE
/* Details about the records contained in a binary data file. */

typedef enum df_translation_type {
    DF_TRANSLATE_DEFAULT,     /* Gnuplot will position in first quadrant at origin. */
    DF_TRANSLATE_VIA_ORIGIN,
    DF_TRANSLATE_VIA_CENTER
} df_translation_type;

typedef enum df_sample_scan_type {
    DF_SCAN_POINT = -3,  /* fastest */
    DF_SCAN_LINE  = -4,
    DF_SCAN_PLANE = -5   /* slowest */
} df_sample_scan_type;

/* To generate a swap, take the bit-wise complement of the lowest two bits. */
typedef enum df_endianess_type {
    DF_LITTLE_ENDIAN,
    DF_PDP_ENDIAN,
    DF_DPD_ENDIAN,
    DF_BIG_ENDIAN,
    DF_ENDIAN_TYPE_LENGTH  /* Must be last */
} df_endianess_type;

/* The various types of numerical types that can be read from a data file. */
typedef enum df_data_type 
{
	DF_NIL = -1,
	DF_CHAR, DF_UCHAR, DF_SHORT, DF_USHORT, DF_INT,
	DF_UINT, DF_LONG,  DF_ULONG, DF_FLOAT,  DF_DOUBLE,
	DF_BAD_TYPE
} df_data_type;
#define DF_DEFAULT_TYPE DF_FLOAT

/* Some macros for making the compiler figure out what function
 * the "machine independent" names should execute to read the
 * appropriately sized variable from a data file.
 */ 
#define SIGNED_TEST(val) ((val)==sizeof(long) ? DF_LONG : \
			 ((val)==sizeof(int) ? DF_INT : \
			 ((val)==sizeof(short) ? DF_SHORT : \
			 ((val)==sizeof(char) ? DF_CHAR : DF_BAD_TYPE))))
#define UNSIGNED_TEST(val) ((val)==sizeof(unsigned long) ? DF_ULONG : \
			   ((val)==sizeof(unsigned int) ? DF_UINT : \
			   ((val)==sizeof(unsigned short) ? DF_USHORT : \
			   ((val)==sizeof(unsigned char) ? DF_UCHAR : DF_BAD_TYPE))))
#define FLOAT_TEST(val) ((val)==sizeof(float) ? DF_FLOAT : \
			((val)==sizeof(double) ? DF_DOUBLE : DF_BAD_TYPE))

typedef enum df_records_type {
    DF_CURRENT_RECORDS,
    DF_DEFAULT_RECORDS
} df_records_type;

typedef struct df_binary_type_struct {
    df_data_type read_type;
    unsigned short read_size;
} df_binary_type_struct;

typedef struct df_column_bininfo_struct {
    short skip_bytes;
    df_binary_type_struct column;
} df_column_bininfo_struct;

/* NOTE TO THOSE WRITING FILE TYPE FUNCTIONS
 *
 * "cart" means Cartesian, i.e., the (x,y,z) [or (r,t,z)] coordinate
 * system of the plot.  "scan" refers to the scanning method of the
 * file in question, i.e., first points, then lines, then planes.
 * The important variables for a file type function to fill in are
 * those beginning with "scan".  There is a tricky set of rules
 * related to the "scan_cart" mapping, the file-specified variables,
 * the default variables, and the command-line variables.  Basically,
 * command line overrides data file which overrides default.  (Yes,
 * like a confusing version of rock, paper, scissors.) So, from the
 * file type function perspective, it is better to leave those
 * variables which are not specifically known from file data or
 * otherwise (e.g., sample periods "scan_delta") unaltered in case
 * the user has issued "set datafile" to define defaults.
 */
typedef struct df_binary_file_record_struct {
    int cart_dim[3];                  /* dimension array size, x/y/z */
    int cart_dir[3];                  /* 1 scan in positive direction, -1 negative, x/y/z */
    double cart_delta[3];             /* spacing between array points, x/y/z */
    df_translation_type cart_trans;   /* translate via origin, center or default */
    double cart_cen_or_ori[3];        /* vector representing center or origin, x/y/z */
    double cart_alpha;                /* 2D rotation angle (rotate) */
    double cart_p[3];                 /* 3D rotation normal vector (perpendicular) */

    df_sample_scan_type cart_scan[3]; /* how to assign the dimensions read from file when generating coordinates */
    TBOOLEAN scan_generate_coord;     /* whether or not Gnuplot should generate coordinates. */
    int scan_skip[3];                 /* skip bytes before the record, line, plane */

    /* Not controllable by the user, only by file type functions.
     * These are all points/lines/planes format.
     */
    int scan_dim[3];                  /* number of points, lines, planes */
    int scan_dir[3];                  /* 1 scan in positive direction wrt Cartesian coordinate system, -1 negative */
    double scan_delta[3];             /* sample period along points, lines, planes */
    df_translation_type scan_trans;   /* translate via origin, center or default */
    double scan_cen_or_ori[3];        /* vector representing center or origin, x/y/z */

    /* *** Do not modify outside of datafile.c!!! *** */
    char GPFAR *memory_data;
} df_binary_file_record_struct;

extern df_binary_file_record_struct *df_bin_record;
extern int df_num_bin_records;

extern struct use_spec_s use_spec[];

/* Prototypes of functions exported by datafile.c */

void df_show_binary (FILE *fp);
void df_show_datasizes (FILE *fp);
void df_show_filetypes (FILE *fp);
void df_set_datafile_binary (void); 
void df_unset_datafile_binary (void);
void df_add_binary_records (int, df_records_type);
void df_extend_binary_columns (int);
void df_set_skip_before (int col, int bytes);                /* Number of bytes to skip before a binary column. */
#define df_set_skip_after(col,bytes) df_set_skip_before(col+1,bytes)  /* Number of bytes to skip after a binary column. */
void df_set_read_type (int col, df_data_type type);          /* Type of data in the binary column. */
df_data_type df_get_read_type (int col);                     /* Type of data in the binary column. */
int df_get_read_size (int col);                              /* Size of data in the binary column. */
int df_get_num_matrix_cols (void);
void df_set_plot_mode (int);
#endif /* BINARY_DATA_FILE */

#endif /* GNUPLOT_DATAFILE_H */
