/* MINITAB Header file
 * GD 2001.07.12
 */
 
 #ifndef _MINITAB_H
 #define _MINITAB_H

// 1,2,4,8, default is 8
#pragma pack(push,1)

/*
 * First part of file - 80 bytes
 */
  typedef struct tagHeader1 {
 	int		var1;	// Unknown	1
 	int		var2;	// Unknown	36
 	int		var3;	// Unknown	12
 	int		var4;	// Unknown	0
 	char	ID[16]; // "MTB13   WIN     " That 'WIN' might be 'MAC' on MAC systems - not tested
 	int		var5;	// Unknown	Large and varies : 9.27731E8 to 9.71718E8 for example
 	int		var6;	// Unknown	5
 	int		var7;	// Unknown	32
 	int		var8;	// Unknown	12
 	int		NCols;	// Number of Columns - last column with data, counts those without data
 	int		NRows;	// Number of Rows - last row with data
 	int		Mult;	// Product of NCols and NRows
 	int		var12;	// Unknown	0
 	int		var13;	// Unknown	0
 	int		var14;	// Unknown	6
 	int		var15;	// Unknown	varies : 23 to 29 for example
 	int		var16;	// Unknown	12
 } Header1;
  
/*
 * Four strings follow. Each is defined by an integer indicating length,
 * followed by that many characters (no null terminator)
 */
 //	int		WorksheetNameLength
 //	string	WorksheetName
 //	int		UserNameLength
 //	string	UserName
 //	int		DateLengthLength
 //	string	Date (although any text is acceptable)
 //	int		NotesLength
 //	string	Notes
 
/*
 * No real information on this data - 60 bytes
 */
 typedef struct tagHeader2 {
 	int	var1;	// Unknown	7
 	int	var2;	// Unknown	Mostly 115, sometimes 111 or 125
 	int	var3;	// Unknown	12
 	int	var4;	// Unknown	1
 	int	var5;	// Unknown	0 (saw one instance of 1)
 	int	var6;	// Unknown	0
 	int	var7;	// Unknown	Mostly 1, also 4, 5, 7, 8, 9, 12
 	int	var8;	// Unknown	Mostly 0, also 1, 3, 17, 18, 30
 	int	var9;	// Unknown	1
 	int	var10;	// Unknown	Mostly 1, also 18, 23, 77
 	int	var11;	// Unknown	8
 	int	var12;	// Unknown	0
 	int	var13;	// Unknown	2
 	int	var14;	// Unknown	10
 	int	var15;	// Unknown	10
 } Header2;
 
/*
 * Two strings follow. Each is defined by an integer indicating length,
 * followed by that many characters
 */
 // int		FontNameLength
 //	string	FontName
 // int		LabelFontNameLength
 //	string	LabelFontName
 
/*
 * Some real guesses made here due to the odd length - 37
 * MUST use struct, can't use typedef struct
 * Two files were found that did not have a var9
 * I included code to 'back-up' (4 bytes) and test for a '3'
 * which should be the start of column data.
 * For the limited number of version 12 files I have,
 * there have been no var9 and no var8.
 * I included code to 'back-up' (12 bytes) and test for a '3'
 */
 struct Header3 {
 	int		var1;	// Unknown	1
 	int		var2;	// Unknown	42
 	char	var3;	// Unknown	0
 	int		var4;	// Unknown	1
 	int		var5;	// Unknown	1
 	int		var6;	// Unknown	1
 	int		var7;	// Unknown	1
 	double	var8;	// Unknown	8 - possibly a default width (Row headers?)
 	int		var9;	// Unknown	1
 };

/*
 * START OF COLUMN DATA
 * That should bring us to the data which is stored in column order
 * There are three formats : Text, Numeric and Date/Time
 * which have some differences in header length
 * I split the header into three parts: preamble, amble (ha, ha) and postamble (ha, ha, ha)
 * The preamble length is 'always' 60
 */

/*
 * The preamble - 60 bytes
 * When format type is Text and SortOrder is User Sort
 * then there are two blocks of data. The code always reads the second block.
 */
typedef struct tagPre {
	int var1;	// Unknown	3
	int var2;	// Unknown	varies by format type
	int var3;	// Unknown	varies by format type
	int ColNum;	// The Column number (indexed from 1)
	int var5;	// Unknown	1 for Numeric and Date/Time, 2 for Text
	int var6;	// Unknown	8 for Numeric and Date/Time, 14 for Text
	int Rows1;	// Number of rows - first copy (?)
	int var8;	// Unknown	28
	int Rows2;	// Number of rows - second copy (sometimes)
	int var10;	// Unknown	0
	int var11;	// Unknown	8 for Numeric and Date/Time, 0 for Text
	int var12;	// Unknown	0
	int var13;	// Unknown	8 for Numeric and Date/Time, 0 for Text
	int var14;	// Unknown	0
	int SortOrder;	// 0 is 'Alpha Sort', 1 is 'Occurrence Sort', 2 is 'User Sort'
} Pre;

/*
 * The amble is two strings (integer length, followed by characters) and an integer
 * Each of the strings can be empty - indicated by length zero
 */
//	int		ColLabLength
//	char	ColumnLabel[ColLabLen]			// Column Label
//	int		ColDescLength
//	char	ColumnDescription[ColDescLen]	// Column Description
//	int		FormatType						// 1:Numeric, 2:Date/Time, 3:Text

/*
 * The postamble length appears to be Format and version specific
 * Version 13
 *	Numeric - 43 bytes
 *	Date/Time - 47 bytes
 *	Text - 35 bytes
 * Version 12
 *	Numeric - 34 bytes
 *	Date/Time - ??? bytes
 *	Text - 26 bytes
 */

/*
 * The postamble (v13), Numeric - 43 bytes
 */
struct PostN {
	int 	var1;	//	Unknown 39
	USHORT 	var2;	//	Unknown 8
	USHORT 	var3;	//	Unknown 8
	USHORT 	var4;	//	Unknown 8
	int 	var5;	//	Unknown 0,1
	int 	var6;	//	Unknown 1
	int 	var7;	//	Unknown 0,1
	int 	var8;	//	Unknown 1
	int 	var9;	//	Unknown 0
	USHORT 	var10;	//	Unknown 5
	USHORT 	var11;	//	Unknown 1
	double 	Width;	//	Column Width
	char 	Hidden;	//	Column Hidden flag - 0 is show, 1 is hidden
};

/*
 * The postamble (v13), Date/Time - 47 bytes
 */
struct PostD {
	int var1;		// Unknown 39
	USHORT var2;	// Unknown
	USHORT var3;	// Unknown
	USHORT var4;	// Unknown
	int var5;		// Unknown 0
	int var6;		// Unknown
	int var7;		// Unknown 0
	int var8;		// Unknown
	char var9[4];	// Unknown - varies widely
	int var10;		// Unknown - very large or zero
	USHORT var11;	// Unknown
	USHORT var12;	// Unknown
	double Width;	// Column Width
	char Hidden;	// Column Hidden flag - 0 is show, 1 is hidden
};

/*
 * The postamble (v13), Text - 35 bytes
 */
struct PostT {
	int var1;		// Unknown 31
	USHORT var2;	// Unknown 8, 23
	USHORT NumChars;// The maximum number of characters - seems to be used by every row
	USHORT var4;	// Unknown 8, 23
	int var5;		// Unknown 0,1
	int var6;		// Unknown 0,1
	int var7;		// Unknown 0,1
	int var8;		// Unknown 0,1
	double Width;	// Column Width
	char Hidden;	// Column Hidden flag - 0 is show, 1 is hidden
};

/*
 * The postamble (v12) Numeric - 34 bytes
 */
struct PostN12 {
	USHORT 	var1;	//	Unknown 1
	USHORT 	var2;	//	Unknown 2
	USHORT 	var3;	//	Unknown 3
	USHORT 	var4;	//	Unknown 4
	USHORT 	var5;	//	Unknown 5
	USHORT 	var6;	//	Unknown 6
	USHORT 	var7;	//	Unknown 7
	USHORT 	var8;	//	Unknown 8
	USHORT 	var9;	//	Unknown 9
	USHORT 	var10;	//	Unknown 10
	USHORT 	var11;	//	Unknown 11
	USHORT 	var12;	//	Unknown 12
	USHORT 	var13;	//	Unknown 13
	USHORT 	var14;	//	Unknown 14
	USHORT 	var15;	//	Unknown 15
	USHORT 	var16;	//	Unknown 16
	USHORT 	var17;	//	Unknown 17
};

/*
 * The postamble (v12), Date/Time - 38? bytes
 */
struct PostD12 {
	int var1;		// Unknown1
	int var2;		// Unknown2
	int var3;		// Unknown3
	int var4;		// Unknown4
	int var5;		// Unknown5
	int var6;		// Unknown6
	int var7;		// Unknown7
	int var8;		// Unknown8
	int var9;		// Unknown9
	USHORT var10;		// Unknown10
};

/*
 * The postamble (v12), Text - 26 bytes
 */
struct PostT12 {
	int var1;		// Unknown 31
	USHORT var2;	// Unknown 8, 23
	USHORT NumChars;// The maximum number of characters - seems to be used by every row
	USHORT var4;	// Unknown 8, 23
	int var5;		// Unknown 0,1
	int var6;		// Unknown 0,1
	int var7;		// Unknown 0,1
	int var8;		// Unknown 0,1
};

/*
 * Read the data here.
 * Numeric and Date/Time are both doubles.
 * The Date system used by MiniTab appears to be based on 12/30/1899.
 * so we must add 2451908 to date values.
 * Did not search for flags indicating Date or Time.
 * Release notes will warn that Dates around 1899, 1900 are probably Times.
 * For more columns, go back to START OF COLUMN DATA
 */

#pragma pack(pop)

// Prototypes

int read_numeric_data(file &fid, string TheWorksheet, uint TheColumn, uint NumRows);
int read_date_data(file &fid, string strWksName, uint TheColumn, uint NumRows);
int read_text_data(file &fid, string strWksName, uint TheColumn, uint NumRows, uint TheSortOrder, uint TheStringSize, uint TheVersion);
int	ImportMinitab(Page& pgTarget, TreeNode& trFilter, LPCSTR lpcszFile, int nFile);

#endif // _MINITAB_H
 
 