/*------------------------------------------------------------------------------*
 * File Name: utilities.h														*
 * Creation: CPY 3/1/2001														*
 * Purpose: Origin C internal utility classes									*
 * Copyright (c) OriginLab Corp.2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007	*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 *------------------------------------------------------------------------------*/

#ifndef _UTILITIES_H
#define _UTILITIES_H

#include <common.h> // must always include this
#include <mswin.h> // kernel32 functions

#ifndef _STRING_H
#include <string.h> // String Class
#endif // _STRING_H

#ifndef _DATA_H
#include <data.h>   //Dataset handling classes(vector, Dataset, matrix, Matrix ...)
#endif // _DATA_H

//#include <mscomm.h>

#define	PBOX_ENDBUTTON	0x4000	// instead of Cancel button
#define PBOX_NO_BUTTON	0x0200 // no cancel or end button, cannot click to cancel
#define PBOX_NO_BAR		0x2000	// just dialog with title and label, no progress bar and buttons
#define PBOX_OFF_CENTER	0x0400
// Please note that Origin C is not yet a full C++ language. Only internal classes
// can be declared as C++ classes. User C++ classes can only be supported via
// user supplied DLL.

/** >User Interface Controls
		A progress dialog box is a small dialog box used to indicate that a software is busy
		processing data. The dialog box contains a progress bar indicating the fraction of
		processing that has been completed. The progress dialog box is generally used in
		conjunction with some sort of iterative loop. The progressBox class provides methods
		and properties needed to open and control progress dialog boxes.
	Example:
 		int imax = 10;
		progressBox aa("This is an example:");
		aa.SetRange(0,imax);
		for(int ii = 0; ii < imax; ii++)
		{
			if(aa.Set(ii))
				printf("Hello, at %d\n", ii);
			else
			{
				out_str("User abort!");
				break;
			}
			LT_execute("sec -p 0.5"); // wasting some time
		}
*/ 
class progressBox
{
public:
	progressBox(LPCTSTR lpstrTitle, int nStyle = 0);
	/**
			Set the integer range for the progressbox to loop through. 
			If you do not call this method, the default range of 0 to 100 will be used.
		Parameters:
			nMin = beginning value
			nMax = end value
		Return:
			TRUE if the range is reasonable, FALSE otherwise.
		SeeAlso:
			Set
	*/
	BOOL	SetRange(int nMin, int nMax);

	/**
			Set the current position of the progress bar. This value is typically within range set
			by the SetRange method
		Parameters:
			nCurrent = the current progress bar position
		Return:
			TRUE normally, FALSE if user has clicked the Cancel or End button prior to this method was called
		Example:
			void run_progressBox()
			{
					int iMax = 10, iMin = 0;
					progressBox prgbBox("This is a ProgressBox example:");
					prgbBox.SetRange(iMin, iMax);
					for (int ii=iMin; ii<=iMax; ii++)
					{
						if(prgbBox.Set(ii))
							printf("Hi, it is now at %d.\n", ii);
						else 
						{
							out_str("User abort!");
							break;
						}
						LT_execute("sec -p 0.5");
					}
			}
	*/
	BOOL	Set(int nCurrent);

	/**
			the current progress bar position
	*/
	int		m_nCurrent;
};


/** >User Interface Controls
		A wait cursor is a visual cue (such as an hour glass) used to indicate that a software
		is busy processing data. The waitCursor class provides methods and properties needed
		to open and control wait cursors.
	Example:
		int imax = 100000;
		waitCursor junk; // just need to declare this, no need to reference to it
		double	aa = 0.5;
		DWORD	dw1 = GetTickCount();
		for(int ii = 0; ii < imax; ii++)
			aa = sin(aa) + ii * aa;
		printf("It took %d ms for %d loop\n",GetTickCount()-dw1,imax);
*/
class waitCursor
{
public:
	waitCursor();
	waitCursor(int nCursorType);

	/**
	The CheckEsc method allows a program to capture user hitting ESC to abort the current operation
	Return:
		TRUE if user has hit the ESC key, FALSE otherwise
		
	Example:
		Worksheet wks = Project.ActiveLayer();
		if(wks==NULL)
			return;
		
		waitCursor	cur;
		string	str;
		int		nCol = 0;
		for(int ii = 0; ii < 10000 && !cur.CheckEsc();ii++)
		{
			wks.AddCol();
			str.Format("Adding col %d", nCol++);
			SetDataDisplayText(str);
		}
		if(ii < 10000)
			printf("User abort adding columns, only %d columns are added\n", nCol);
	*/
	BOOL CheckEsc();
};

///////////////////////

#pragma dll(msvcrt, system)

/** >Memory Management
		Allocates a certain number of bytes on heap.
	Parameters:
    	nBytes =  Bytes to allocate.
    Return:
    	Returns a void pointer to the allocated space, or NULL if there is insufficient memory available. 
	Example:
		void	run_malloc()
		{
			char		*pstr;
			UINT		nNumerOfBytesToAllocate = 200;
			pstr = (char*)malloc(nNumerOfBytesToAllocate);
			if (pstr != NULL)
				out_str("Allocation succesful");
			else
				out_str("Allocation failed!");
			
			// free the allocated memory:
			free(pstr);
		}
*/
void *	malloc(UINT nBytes);

/** >Memory Management
		calloc function is used to allocate an array in memory with elements initialized to 0.
    Parameters:
    	nElements = Number of elements 
		nSize = Length in bytes of each element 
	Return:
		returns a pointer to the allocated space, or NULL if there is insufficient memory available. 
	Example:
		void	run_calloc()
		{
			int			*pn;
			UINT		nNumerOfIntegersToAllocate = 200;
			pn = (int*)calloc(nNumerOfIntegersToAllocate, sizeof(int));
			if (pn != NULL)
				out_str("Allocation succesful");
			else
				out_str("Allocation failed!");
			
			// free the allocated memory:
			free(pn);
		}
*/
void *	calloc(UINT nElements, UINT nSize);

/** >Memory Management
		Deallocates or frees a memory block that was allocated with malloc or calloc.
    Parameter:
    	pmem = Previously allocated memory block to be freed.
    Return:
    	None.
	Example:
		void	run_free()
		{
			char		*pstr;
			UINT		nNumerOfBytesToAllocate = 200;
			pstr = (char*)malloc(nNumerOfBytesToAllocate);
			if (pstr != NULL)
				out_str("Allocation succesful");
			else
				out_str("Allocation failed!");
			
			// free the allocated memory:
			free(pstr);
		}
*/
void	free(void * pmem);

/** >Character/String Manipulation
		Converts string to a double.
	Parameter:
		lpcsz = the string to convert
	Return:
		a double value.
	Example:
		void	run_atof()
		{
			char	szString[] = "-234.789";
			double	rr = atof(szString);
			out_double("value = ", rr);
		}
*/
double	atof(LPCSTR lpcsz);

/** >Character/String Manipulation
		Converts string to an integer.
	Parameter:
		lpcsz = the string to convert.
	Return:
		an integer value.
	Example:
		void	run_atoi()
		{
			char	szString[] = "-234987";
			int		nn = atoi(szString);
			out_int("value = ", nn);
		}
*/
int		atoi(LPCSTR lpcsz);

/** >Character/String Manipulation
		Converts string to a long.
	Parameter:
		lpcsz = the string to convert.
	Return:
		a long value
	Example:
		void	run_atol()
		{
			char	szString[] = "-556677";
			long	nn = atol(szString);
			out_int("value = ", nn);
		}
*/
long	atol(LPCSTR lpcsz);

/** >File Management
		Get the current working directory.
	Parameters:
		buffer = Storage location for path to be returned by the function
		maxlen = Maximum length of path in characters
	Return:
		returns a pointer to buffer. A NULL return value indicates an error.
	Example:
		void	run_getcwd()
		{
			char		szcurDirectory[MAXFULLPATH];
			if ( _getcwd(szcurDirectory, MAXFULLPATH) != NULL )
			{
				out_str(szcurDirectory);
			}
		}
*/
char*	_getcwd( char *buffer, int maxlen );// get the current working path

/** >File Management
		Change the current working directory.
	Parameter:
		*lpcszPath = Path of new working directory.
	Return:
		0 if successful. A return value of -1 indicates that the specified path could not be found
	Example:
		void	run_chdir()
		{
			string		strNewCurrentDir = "c:\\";
			if (0 == _chdir(strNewCurrentDir))
			{
				// If it succeded, display the new current directory:
				char		szcurDirectory[MAXFULLPATH];
				if ( _getcwd(szcurDirectory, MAXFULLPATH) != NULL )
				{
					out_str(szcurDirectory);
				}
			}
		}
*/
int		_chdir( const char *lpcszPath ); // change the current working directory to the specified path


/** >File Management
		Get the current working drive.
	Parameter:
		None.
	Return:
		returns the current (default) drive (1 = A, 2 = B, and so on).
	Example:
		void	run_getdrive()
		{
			int		nCurrentDrive = _getdrive();
			printf("Current drive is %c\n", (char)(nCurrentDrive + 'A' - 1));
		}
*/
int		_getdrive( ); // get the current working drive

/** >File Management
		Changes the current working drive.
	Parameter:
		drive: Number of new working drive, A drive is 1, B drive is 2, C drive is 3, and so on.
	Returns:
		returns a value of 0 if the working drive is successfully changed. A return value of -1 indicates an error.
	Example:
		void	run_chdrive()
		{
			int		nCurrentDrive = _getdrive();
			printf("Current drive is %c\n", (char)(nCurrentDrive + 'A' - 1));
			
			if (0 == _chdrive(4))
			{
				nCurrentDrive = _getdrive();
				printf("Current drive is %c\n", (char)(nCurrentDrive + 'A' - 1));
			}
			else
				out_str("Failed to change current drive!");
		}
*/
int		_chdrive( int drive ); // change the current working drive



// Origin internal functions
// all function prototypes from here on must be implemented from within the Origin OUTL DLL
#pragma dll(@OUTL)
/**	>File Management
		Comare the contents of two files. This function does a byte by byte binary compare
	Parameters:
		lpcszFilename1 = fullpath filename of the first file
		lpcszFilename2 = fullpath filename of the second file
	Returns:
		0 if two files match in contents
		1 if two files are different
		-1 if error
	Example:
		void	run_file_compare()
		{
			string	strPath = GetAppPath();
			string strLineOTP = strPath + "Line.otp";
			string strOriginOTP = strPath + "Origin.otp";
			if(file_compare(strLineOTP, strOriginOTP) == 0)
				out_str("Line graph template is using default template");
			else
				out_str("Line graph template is different from default Origin template");
		}
*/
int file_compare(LPCSTR lpcszFilename1, LPCSTR lpcszFilename2);

// Origin internal functions
// all function prototypes from here on must be implemented from within the Origin OK DLL

/** >Character/String Manipulation
	Replace all occurances of certain characters in given buffer with a new character
	Parameters:
		lpBuff = input and output buffer to replace characters with
		nSize = size in bytes of lpBuff
		chOldList = an array of bytes that we need to replace, zero is allowed
		nOldListSize = size of the chOldList array
		chNew = new character to replace any of the characters in chOldList
	Returns:
		number of replacement, or -1 if error
	Example:
		char szTemp[10] = "A\tB\r\nC";
		char szNonePrintable[] = "\t\r\n";
		memory_replace(szTemp, lstrlen(szTemp),szNonePrintable,lstrlen(szNonePrintable),'.');
		out_str(szTemp);
*/
int memory_replace(LPSTR lpBuff, int nSize, LPSTR chOldList, int nOldListSize, char chNew);

/** >Date Time
	Convert a SYSTEMTIME structure to a formatted string.
	Parameters:
		pSysTime = pointer to the source SYSTEMTIME structure
		lpstr = pointer to the buffer to receive the formatted string
		wFormat = a date format flag to determine the appearance of the formatted string. See LDF_* definitions in OC_Const.h
	Returns:
		If successful then TRUE else FALSE
	Example:
		SYSTEMTIME syst;
		syst.wYear = 2003;
		syst.wMonth = 1;
		syst.wDayOfWeek = 2;
		syst.wDay = 28;
		syst.wHour = 11;
		syst.wMinute = 17;
		syst.wSecond = 33;
		syst.wMilliseconds = 0;
		
		string str;
		LPSTR lpstr = str.GetBuffer(255);
		if( lpstr )
		{
			systemtime_to_date_str(&syst, lpstr, LDF_LONG);
			str.ReleaseBuffer();
		}
*/
BOOL systemtime_to_date_str(SYSTEMTIME *pSysTime, LPSTR lpstr, WORD wFormat=LDF_SHORT);

#if  _OC_VER > 0x0703
/** >Date Time
	Convert a SYSTEMTIME structure to a Julian date value.
	Parameters:
		lpdDate = pointer to the destination value
		lpSysTime = pointer to the source SYSTEMTIME structure
	Example:
		void	test_get_date_str()
		{
			SYSTEMTIME st;
			GetSystemTime(&st);              // gets current time
			double dDate;
			SystemTimeToJulianDate(&dDate, &st);
			out_str(get_date_str(dDate, LDF_LONG));
		}
	Returns:
		TRUE if successful, else FALSE
*/
BOOL SystemTimeToJulianDate(double *lpdDate, SYSTEMTIME *lpSysTime);

/**#
	get the string for given plot designation
	Example:
		void run_get_plot_designation_str()
		{
			char szTemp[50];
			if(get_plot_designation_str(COLDESIG_X, szTemp, 50))
			{
				out_str(szTemp);
			}	
		}
*/
BOOL get_plot_designation_str(int nPlotDesignation, LPSTR lpBuffer, int nBuffSize);

/**#
	convert Column(n).GetType() return values which are in the enum of OKDATAOBJ_DESIGNATION_Y
	return COLDESIG_Y enums
	Example:
		void run_cvt_col_type_to_designation()
		{
			int nRet = cvt_col_type_to_designation(OKDATAOBJ_DESIGNATION_Y);
			out_int("",nRet);
		}
*/
int cvt_col_type_to_designation(int nColType);

/**#
*/
//int		ConvertPlotIds(int nType, DWORD* pdwCntrl);
int		ConvertPlotIds(int nType, DWORD* pdwCntrl, DWORD *pdwLTPlotInfo = NULL);

/**#
*/
int cvt_x_from_step_to_str(double xFrom, double xStep, LPSTR lpBuffer, int nSize);


/**#
*/
int	WINAPI string_to_prefix_end_number(LPSTR lpszBuffer, LPCSTR lpcszString);

/**#
*/
int get_base_plot_type(int nPlotType);
/**#
	Compare the two given plot types and return 1 if they are compatible, returns 0 if not
*/
int compare_plot_types(int nPlotType1, int nPlotType2);

/** >File Management
		Add extension to file name if not present, or to get file extension string
	Parameters:
		lpszFilename = filename with or without path, typically from a buffer with MAXFULLPATH in size
		lpcszFileExt = file extension, without the dot.
		lpszExt2 = optional buffer, see Remark
	Remark:
		This function assumes that lpszFilename has extra space to append file extension
		if lpcszExt ==NULL, then return false if has extension and copied to into lpszExt2 if not NULL
		if lpcszExt !=NULL, then 
			if lpszExt2 == NULL, then replace/append ext regardless if existed or not, return FALSE if no change
			if lpszExt2 != NULL, then it is assumed to be 2nd ext, replace/append if not either, return FALSE if no change 
	Returns:
		It depends on the various combinations of the arguments, but in general TRUE indicates that extension is added or updated. FALSE indicate that there is no change to lpszFilename
	Example:
		void run_check_add_file_ext()
		{	
			char szTemp[20];
			char strFileName[100];
			string str = GetAppPath(1) + "origin.ini";
			lstrcat(strFileName, str);
			
			BOOL bRet = check_add_file_ext(strFileName,NULL,szTemp);
			out_str(szTemp);
		}
*/
BOOL check_add_file_ext(LPSTR lpszFilename, LPCSTR lpcszExt, LPSTR lpszExt2 = NULL);

/** >Font
		Get system fonts details
	Parameters:
		nType = OEM_FIXED_FONT, SYSTEM_FONT etc const, can also pass in GSFI_TYPE_DEFAULT, GSFI_TYPE_FIXED_WIDTH, GSFI_TYPE_SCALABLE for Origin fonts
		lpnFontSize = pointer to int to receive font size
		lpnCharSet = pointer to a byte to receive Character Set type
		lpszFontName = buffer to receive font face name
		nNameSize = size of lpszFontName
	Example:
		string get_system_font_name(int nType, int* lpnCharSet) // = ANSI_VAR_FONT, NULL);
		{
			int nFontSize;
			byte nCharSet = ANSI_CHARSET;
			
			string str;
			char	szTemp[LF_FACESIZE + 1];
			if(get_system_font_info(nType, &nFontSize, &nCharSet, szTemp, LF_FACESIZE))
				str = szTemp;
			if(lpnCharSet)
				*lpnCharSet = nCharSet;
			
			return str;
		}
*/
BOOL  get_system_font_info(int nType, int* lpnFontSize, byte* lpnCharSet, LPSTR lpszFontName, int nNameSize);

/** >Date Time
		Convert a text string that represents date/time into a Julian date value
	Parameters:
		lpcszDateStr = a date/time string
		lpcszFormatStr = pointer to a format picture string that is used to form the date string
	Returns:
		If successful then Julian date else NANUM
	Example:
		string strDate = "2003-03-21";
		string strFormt = "yyyy'-'MM'-'dd";
		double db;
		
		if(str_to_date_custom(strDate, strFormt,&db))
		{
			printf("You have entered %s\n", get_date_str(db));
		}
*/
BOOL str_to_date_custom(LPCSTR lpcszDateStr, LPCSTR lpcszFormatStr, double* pDate);

/** >Date Time
		Convert a Julian date value to a string formatted according to that represents date/time 
	Parameters:
		rDate = Julian date value
		lpcszFormatStr = pointer to a format picture string that is used to form the date string
		lpszDateStr = pointer to the target buffer
	Returns:
		If successful then TRUE else FALSE
	Example:
		string strDateIn = "2003-03-21";
		string strFormat = "yyyy'-'MM'-'dd";
		char szDateOut[MAXLINE];
		double db;
		
		if( str_to_date_custom(strDateIn, strFormat, &db) )
		{
			if( date_to_str_custom(db, strFormat, szDateOut) )
			{
				if( !strDateIn.CompareNoCase(szDateOut) )
					printf("success\n"); // date_to_str_custom gets what str_to_date_custom puts
				else
					printf("failure\n"); // date_to_str_custom did not get what str_to_date_custom put
			}
		}
*/
BOOL date_to_str_custom(double rDate, LPCSTR lpcszFormatStr, LPSTR lpszDateStr);

/** >Date Time
		Convert a time formated string to a Julian value
	Parameters:
		lpcszTime = string containing the time
		dwFlags = 
	Returns:
		A double containing a Julian date value
	Example:
		string strTime = "001:12:00:00.0"; // 1 day, 12 hrs, 0 mins, 0 secs
		double dTime;
		dTime = str_to_time(strTime);
		printf("%s = %f\n", strTime, dTime);
*/
double str_to_time(LPCTSTR lpcszTime, DWORD dwFlags=0);

#endif //#if  _OC_VER > 0x0703

#pragma dll(@OK)


/** >LabTalk Interface
		Evaluate an expression in LabTalk syntax.
	Parameters:
		lpcszLabTalkExpression = Pointer to a string containing the expression in LabTalk syntax.
		lpdbResult = Pointer to a double value to receive the results.
	Returns:
		TRUE if expression is valid, FALSE if expression leads to missing value
	Example:
		void	run_LT_evaluate()
		{
			double		vv;
			LT_get_var("@D",&vv); // get machine curremt date/time as Julian value	
			out_double("@D = ", vv);
			LT_evaluate("0^0",&vv); // evaluate expression using LabTalk interpreter
			out_double("0^0 = ", vv);
		}
*/
BOOL	LT_evaluate(LPCSTR lpcszLabTalkExpression, double * lpdbResult);

/** >LabTalk Interface
		Execute LabTalk script code.
	Parameters:
		lpcszLabTalkStr = Pointer to a string containing the LabTalk script code to execute.
		wCntrl = not used (must be 0)
	Return:
		TRUE if success, FALSE if LabTalk execution leads to error
	Example:
		void	run_LT_execute()
		{
			// Execute the LabTalk script which will bring up a message box and display
			// the value of the system string %Y:
			LT_execute("type -b %Y");
		}
*/
BOOL	LT_execute(LPCSTR lpcszLabTalkStr, int wCntrl = 0);

/** >LabTalk Interface
		You can use this command to get LabTalk variables, including system variables whose names begin with @
		This command is similar to LT_evaluate but you can tell if given name corresponds to a LabTalk variable
		even if its value is missing value, while LT_evaluate will not be able to differentiate. Also, using
		LT_evaluate to get value of a variable is slower. 
	Parameters:
		lpcszLabTalkVarName = LabTalk variable name, case insensitive
		lpdbResult = the double variable pointed to by lpdbResult recieves the LabTalk variable value
	Return:
		TRUE if lpcszLabTalkVarName is a LabTalk variable, and FALSE if it is not
	Example:
		void	run_LT_get_var()
		{
			double vv;
			LT_get_var("X2", &vv); // get the current X axis right limit (the variable "X2")
			out_double("vv = ", vv);
			LT_get_var("@D",&vv); // get machine curremt date/time as Julian value (the system variable @D)	
			out_double("vv = ", vv);
			if(LT_get_var("XYZ", &vv))	// try to get the value of the variable "XYZ"
				printf("in LabTalk, XYZ = %lf\n", vv);
			else
				out_str("XYZ is not a LabTalk variable");
		}
*/
BOOL	LT_get_var(LPCSTR lpcszLabTalkVarName, double * lpdbResult);  // Get LabTalk variable value

/** >LabTalk Interface
		It sets the value of a LabTalk variable
	Parameters:
		lpcszLabTalkVarName = LabTalk variable name, case insensitive
		dbValue = the new value
	Return:
		TRUE if OK, and FALSE if it fails.
	Example:
		void	run_LT_set_var()
		{
			double vv;
			if(LT_get_var("X", &vv))
			{
				vv += 10;
				// Set the new value:
				if(LT_set_var("X", vv))
					out_str("set X in LabTalk succeeded");
				else
					out_str("set X in LabTalk failed");
				
				LT_get_var("X", &vv);
				out_double("new value is ", vv);
			}
		}
*/
BOOL	LT_set_var(LPCSTR lpcszLabTalkVarName, double dbValue);	// Set LabTalk variable value

/** >LabTalk Interface
		lstrcpyn is used inside Origin to copy LabTalk string into the buffer supplied, so that if the buffer
		is too small, the result string will have one less character than specified to leave room for the
		terminating character.
	Parameters:
		lpcszLabTalkString = LabTalk global string, or any other LabTalk string expression
		pBuffer = character buffer to receive the string
		nBufferSize = size of the buffer including the terminating zero
	Return:
		Return TRUE if success, return FALSE if string variable is not correctly specified or string is 
		too long.
	Example:
		void	run_LT_get_str()
		{
			char	szBuffer[200];
			// Get the value of the string variable %Y (it usually contains the
			// Origin's client path)
			LT_get_str("%Y", szBuffer, 200);
			out_str(szBuffer);
		}
*/
BOOL	LT_get_str(LPCSTR lpcszLabTalkString, char* pBuffer, int nBufferSize); // Get LabTalk string


/** >LabTalk Interface
		Sets the value of a LabTalk global string variable or a LabTalk object string property.
	Parameters:
		lpcszVar = Origin string variables, %A through %Z, as well as LabTalk Object string properties
		lpcszContent = string content to be copied to Origin string variable, can be NULL to empty a string
	Return:
		Return TRUE if success, return FALSE if string variable is not correctly specified or string is 
		too long.
	Example:
		void	run_LT_set_str()
		{
			char	szBuffer[200];
			// Get the value of the string variable %L
			LT_get_str("%L", szBuffer, 200);
			
			// Display the value:
			out_str(szBuffer);
			
			// Now set it to a new value:
			LT_set_str("%L", "New string value!");
			// Get the value of the string variable %L
			LT_get_str("%L", szBuffer, 200);
			
			// Display the value:
			out_str(szBuffer);
		}
*/
BOOL	LT_set_str(LPCSTR lpcszVar, LPCSTR lpcszContent); // Set LabTalk string	variable



// these are defined in oc_tyeps.h
//#define AIC_LISTCTRL_SETNUMCOLS		1
//#define AIC_LISTCTRL_SETCELL			2
//#define AIC_LISTCTRL_DELROW			3
//#define AIC_LISTCTRL_ADDROW			4
// when uMsg = AIC_LISTCTRL_SET_GET_COL_TYPE, the function will set or get the types of the column;
// lp1 should be the column number, lp2 should be the type one want to set, lp3 = 0 means to get, else
// lp3 = 1 means to set; 
//the types are as following:
// NUMERIC           0
// TEXT              1
// TIME              2
// DATE              3
// MONTH             4
// DAY_OF_WEEK       5
// TEXT_NUMERIC  	 6

/**#
*/
int AscImpListCtrlMsg(LPCSTR lpcstrName, UINT uMsg, UINT lP1 = 0, UINT lP2 = 0, UINT lP3 = 0);

/**#
*/
int AscImpListCtrlInsRow(LPCSTR lpcstrName, StringArray *psa, int iRow=-1, BOOL bAddCol=TRUE);

//------ CPY 9/24/02 v7.0404 QA70-2658 ASCII_IMPORT_FROM_OC
// requires Origin 7 SR3 or later
/**	>Import Export
	Scan and analyse the given file to gather information for ascii import into worksheets.
	This function will look read the file to look for consistent structure by trying different
	separators that will yield the largest number of columns.
	Example:
		ASCIMP	ascimp;
		string strFile = GetOpenBox("*.dat");
		if(AscImpReadFileStruct(strFile,&ascimp)==0)
		{
			out_int("# of header lines= ", ascimp.iHeaderLines);
			out_int("# of columns = ", ascimp.iNumcolumns);
		}
		
	Parameters:
		lpcszFilename = a full path ASCII file name
		pASCIMPstruct = pointer to an ASCIMP struct that is not initialized on input but will be set when function returns
		dwCntrl = additional flags to control the reading, only AIRF_USE_ASCIMP is defined for now.
				dwCntrl = 0 for pASCIMPstruct to be used only as output, if AIRF_USE_ASCIMP, then it will be used as starting point for further scanning
	Return:
		 Returns 0 if no error, otherwise an error code is returned
	SeeAlso:
		Worksheet::ImportASCII
	
*/
int AscImpReadFileStruct(LPCSTR lpcszFilename, ASCIMP* pASCIMPstruct, DWORD dwCntrl=0);

// OLE Automation Object and COM support is only available only for OriginPro versions, or with a special COM enabled license.

#ifdef	ORIGIN_COM_SUPPORT
/** >COM
		Create an automation (COM) object.
	Remarks:
		This function is available only for OriginPro versions, or with a special COM enabled license
	Example:
		void	run_CreateObject()
		{
			Object	obj;
			// Create an MS Word application object:
			obj = CreateObject("Word.Application");
			// Make the application visible
			obj.Visible = true;
		}
	Parameters:
		lpcszObjectName=Name of the object to be created
	Return:
		 Returns a reference to the created object.

*/
Object	CreateObject(LPCSTR lpcszObjectName); // Create an automation (COM) object.

/** >COM
		It sets up an event handler for an automation object.
	Remarks:
		This function is available only for OriginPro versions, or with a special COM enabled license
	Parameters:
		pObj = pointer to an existing COM object reference  which must have been initialized.
		lpcszEventName = event name (it can retrieved from the object library for the given object)
		pOCFunc = pointer to a Function object which has been intialized with an existing Origin C function.
	Returns:
		0 if the event handler was set up successfully, 2 if an events COM interface cannot be retrieved from
		the object, 3 if the event name was wrong, 
	Example:
		Object	obj;	// this is the object which will fire an event
		// This is the event handler which catches the event. The prototype must agree
		// with the event's declaration, which can be found out by inspecting
		// the object library for each particular object.
		void	MyEventHandler()
		{
			printf("Event hanled\r\n");
		}
		void	run_SetEventHandlerForObject()
		{
			// Declare a function object (the function MyEventHandler must have been defined before)
			Function		fnEventHandler(MyEventHandler);
			
			Object obj = CreateObject("SomeObject.SomeObject");
			
			int		iRet;
			// This sets up the event handler. It tells the object obj: Call the function
			// MyEventHandler when event "SomeEvent" happens.
			iRet = SetEventHandlerForObject(&obj, "SomeEvent", &fnEventHandler);
			if (0 == iRet)
				out_str("Eevent handler set up successfully.");
		}

*/
int		SetEventHandlerForObject(Object *pObj, LPCSTR lpcszEventName, Function *pOCFunc);
#endif //#ifdef	ORIGIN_COM_SUPPORT

/** >User Interface Controls
		Opens a simple input box for entering a string.
	Parameters:
		lpcszMsg = Pointer to a string containing a message used to prompt the user.
		dwOption = not used (must be 0)
	Returns:
		the string which has been input
	Example:
		void	run_InputBox()
		{
			string		strInput = InputBox("Please enter your name");
			
			printf("You entered: %s\n", strInput);
			
		}
*/
string InputBox(LPCSTR lpcszMsg, DWORD dwOption = 0);

/** >Character/String Manipulation
		GetDecimalChar is used to return the character used inside Origin for decimal in numbers
	Returns:
		numeric decimal character, typically period('.') or comma(',').
	Example:
		void	run_GetDecimalChar()
		{
			char	chDecimalCharacter = GetDecimalChar();
			
			printf("Decimal character is %c\n", chDecimalCharacter);
		}
*/
char GetDecimalChar();

/** >Memory Management
		Convert the given memory into a hex string with every byte represented by two hexidecimal characters.
	Returns:
		the string for the hex dump.
	Parameters:
		lpcMemory = a memory pointer
		nSize = size of the memory in bytes to convert
		bAddGap = TRUE will add a space character between the hex characters
	Example:
		char szTemp[10] = "A\t\r\n";
		string strDump = GetHexDump(szTemp, 4);
		out_str(strDump);
*/
string GetHexDump(const LPVOID lpcMemory, int nSize, BOOL bAddGap=TRUE);

/** >Origin System
		Get Origin's software path including the last '\\' character.
	Parameter:
		bServerPath = TRUE to get the Origin's program path and to FALSE to get the User Files path.
	Returns:
		A string containing the requested path.
	Example:
		void	run_GetAppPath()
		{
			string strFile = GetAppPath(true) + "originc\\system\\wksheet.h";
			ASSERT(strFile.IsFile());  // system header should be installed only in program path
			strFile = GetAppPath(false) + "originc\\system\\wksheet.h";
			ASSERT(!strFile.IsFile()); // should not have this in user files path
			strFile = GetAppPath() + "origin.ini";
			ASSERT(strFile.IsFile());
		}
	Remarks:
		Origin's program path is typically where Origin's EXE and DLL files are located. In a network version, this is typically
		a remove path on a server computer where the server version of Origin is installed. In a single user installation, this
		is always the location where Origin's EXE and DLL files are installed. Origin C system files are always installed inside
		the program path.
		Origin's User Files path is typically assigned by the user when running Origin for the first time. This is where all the
		files related to a particular customization of Origin is located. You will find origin.ini and other templates and CNF files
		in this location.
*/
string GetAppPath(BOOL bServerPath = FALSE);

/** >User Interface Controls
		Set the text in the Data Display control. The Data Display is usually used for display
		Screen Reader coordinates. This function will also show the Data Display control if it is not already shown
	Parameter:
		lpcszText = text string to set, use NULL to close the Data Display if not docked.
	Returns:
		void
	Example:
		// test hide;// to hide the Data Display control
		// test "what ever";// to put text into Data Display control
		void	test(string str)
		{
			if(str.CompareNoCase("hide")==0)
				SetDataDisplayText(NULL);
			else	
				SetDataDisplayText(str);
		}
*/
BOOL SetDataDisplayText(LPCTSTR lpcszText);

/** >File Management
		Find a file in a given path. 
		If lpSubFolder1st is given (not NULL), then
		A. if bExcluded = FALSE, then find this subfolder first, 
		B. if bExcluded = TRUE, skip this subfolder
	Parameters:
		lpcszName = File name to search for.
		lpPath = on input, the starting path to search for a file. Output, to receive the full path of the file if found.
		lpSubPath = Optional subfolder of the given path(lpPath) to search in.
		bExcluded = whether to skip searching the subfolder (lpSubFolder1st) (FALSE to search it first) 
	Returns:
		If the file is found then TRUE else FALSE.
	Example:
		void	run_FindFile()
		{
			char		szTemp[MAXFULLPATH];
			lstrcpy(szTemp, GetAppPath());
			if(FindFile("APP_UTILS.c", szTemp, "Originlab", FALSE))
			{
				out_str("ok, found it");
				out_str(szTemp);
			}
			else
				out_str("Not found!");
		}
*/
BOOL FindFile(LPCTSTR lpcszName, LPSTR lpPath, LPCTSTR lpSubFolder1st = NULL, BOOL bExcluded = TRUE);

/** >Origin System
		Seach Origin's client and then server path to return the full path name of the specified file
		This function will separately look for server and client path only if Origin is a network version. For single user version,
		this function will simply return the full path from Origin's software path
	Parameters:
		lpcszFileName = File name to search for.
		lpSubPath = Optional subfolder of the Origin software path to search in.
		bLocalized = TRUE if the given file can be localized so that we will need to first try the localization location first
	Returns:
		If the file was found then a string containing the full path file name is returned else an empty string is returned.
	Example:
		void	run_GetFullPath()
		{
			string strFile = "origin.ini";
			string strFullPath = GetFullPath(strFile);
			if( !strFullPath.IsEmpty() )
			{
				string strPath = GetFilePath(strFullPath);
				printf("File %s was found in %s folder.\n", strFile, strPath);
			}
		}
*/
string GetFullPath(LPCSTR lpcszFileName, LPCSTR lpSubPath = NULL, BOOL bLocalized=FALSE);

/** >File Management
		Extracts the path from a full path file name string.
	Parameters:
		lpcszFullPathFileName = Pointer to a string containing a files full path name.
	Returns:
		A string containing only the path portion, including the last '\' character.
		If no path is present then the returned string is empty.
	Example:
		void	run_GetFilePath()
		{
			string	str = "c:\\c\\test.dat";
			string	strFilePath = GetFilePath(str);
			out_str(strFilePath);
		}
*/
string GetFilePath(LPCSTR lpcszFullPathFileName);

/** >File Management
		Extracts the file name from a full path file name string.
	Parameters:
		lpcszFullPathFileName=Pointer to a string containing a files full path name.
		bRemoveExt=TRUE will remove file extension so only the file name part will be returned
	Returns:
		A string containing only the file name with extension or not depending on bRemoveExt.
	Example:
		void	run_GetFileName()
		{
			string	str = "c:\\c\\test.dat";
			string	strFileName = GetFileName(str);
			out_str(strFileName);
		}
*/
string GetFileName(LPCSTR lpcszFullPathFileName, BOOL bRemoveExt=FALSE);

/**	>File Management
		Check the given path to see if is existed, if not, then create all the needed folders
	Parameters:
		lpcszFullPath= full path string to check for making folders
	Returns:
		TRUE if either the path already existed (can call string::IsPath if don't want to waste time).
		FALSE if error occurs when attempting to create the needed folders
	Example:
		void	test_CheckMakePath()
		{
			string	str = GetAppPath() + "junk\\some more junk";
			ASSERT(!str.IsPath());
			if(CheckMakePath(str))
			{
				ASSERT(str.IsPath());
			}
			else
				out_str("err in creating path");
		}
*/
BOOL CheckMakePath(LPCSTR lpcszFullPath);

/**	>File Management
		Rename a file with full path specified for both old and new file names
	Parameters:
		lpcszNewFilename= full path file name to rename to
		lpcszOldFilename = full path file name of the existing file to rename
	Returns:
		TRUE if success
	Remarks:
		The old file name must point to a valid file that can be renamed and the new file name specified 
		must be a full path in the same folder as the original.
	Example:
		void	test_RenameFile()
		{
			string	str = GetAppPath() + "origin.ini";
			CopyFile(str, GetAppPath() + "junk1.ini");
			string strNewName = GetAppPath() + "junk2.ini";
			ASSERT(!strNewName.IsFile());
			RenameFile(strNewName, GetAppPath() + "junk1.ini");
			ASSERT(strNewName.IsFile());
		}
*/
BOOL RenameFile(LPCSTR lpcszNewFilename, LPCSTR lpcszOldFilename);

#if  _OC_VER > 0x0703
/**	>Font
		Get font name.
	Parameters:
		nID = OEM_FIXED_FONT, ANSI_FIXED_FONT, ANSI_VAR_FONT, SYSTEM_FONT, etc
		plfHeight = if not NULL, to receive LOGFONT.lfHeight
	Returns:
		A string containing the font name.
	Remarks:
	Example:
		void	test_GetFontName()
		{
			string	str;
			str = GetFontName(SYSTEM_FONT);
			out_str(str);
		}
*/
string GetFontName(int nID, int* plfHeight);


/**# >Origin System
*/
uint GetOriginClipboardFormat(int nType = 0);

/**# >Origin System
*/
BOOL CopyThemeFromClipboard(LPCSTR lpcszFilename);

/**# >Origin System
*/
BOOL	ApplyFilterToTheme(LPCSTR lpcszSourceThemePathName, LPCSTR lpcszDestinationPathName, DWORD dwPropertiesFilter, DWORD dwObjectsFilter);

/** >Date Time
	convert a Julian date value into a string
	Parameters:
		dDateTime = A Julian date time value, where the integral part represent the Julian Days while the fractional part as fraction of a Day
		wFormat = must be the enumeration LDF_SHORT, LDF_LONG, LDF_ALPHAMONTH_NUMERICDAY, etc
	Returns:
		A string containing the converted date/time.
	Remarks:
	Example:
		void	test_get_date_str()
		{
			SYSTEMTIME st;
			GetSystemTime(&st);              // gets current time
			double dDate;
			SystemTimeToJulianDate(&dDate, &st);
			out_str(get_date_str(dDate, LDF_LONG));
		}	
*/
string	get_date_str(double dDateTime, WORD wFormat = LDF_SHORT_AND_HHMMSS_SEPARCOLON);

/** >System
	get the registry key in the general area for the Origin software
	Parameters:
		bLanguage = TRUE if to get to the subpath for language specific users, which is most typically the case

	Returns:
		A string containing the full path (key) that can be used in the Registry class

	Example:
		#include <settings.h>
		void test()
		{
			Registry reg(HKEY_CURRENT_USER);
			string strUserPath;
			if(reg.GetValue(GetRegKey(), "Path", strUserPath))
				printf("User path is stored as %s\n", strUserPath);
		}
*/
string GetRegKey(BOOL bLanguage = TRUE); 

/** >User Interface Controls
		Display message box.
	Parameters:
		lpcszMessage = Keyword for the text of the message to display.
		iBtnOpts = Message box style; can be one of: OM_RETURN_NOT_PRESENT, OM_RETURN_YNC_CANCEL, OM_RETURN_OK, OM_RETURN_CANCEL, OM_RETURN_YES, OM_RETURN_NO		
		lpcszAuxStr = Optional string - reserved.

	Example:
		BOOL bDelete = FALSE;
  		if ( OM_RETURN_OK == OptionalMessage( "DestroyOperationWithSource", MB_YESNO ) )
			bDelete = TRUE;

	Returns:
		User choice; can be one of: MB_OK, MB_OKCANCEL, MB_YESNO, MB_YESNOCANCEL.

*/
int	OptionalMessage(LPCSTR lpcszMessage, int iBtnOpts, LPCSTR lpcszAuxStr = NULL);

/** >Origin System
	get the path of the temp folder in which the OPJ attached files are placed.		
	Returns:
		empty string is no such path

	Example:
		#include <origin.h>
		
		void test()
		{
			string strPath;
			strPath = GetProjectAttachedFilesPath();
			if(strPath.IsEmpty())
				out_str("Not files attached to project");
			else
				out_str(strPath);
		}
*/
string GetProjectAttachedFilesPath();

/** >System
	launch an application
	Parameters:
		lpApp = module name
		lpArg = Command line.
		bTransferControl = if FALSE and if lpApp is not NULL, this function will not return until the application is terminated 
		bTryWinExec = try the older WinExec function from Windows if the standard method failed.
		
	Returns:
		TRUE if sucess, FALSE if failed

*/
BOOL ExecuteApp(LPCSTR lpApp, LPCSTR lpArg, BOOL bTransferControl = TRUE, BOOL bTryWinExec = FALSE);


/**#
		get name of a data plot from Origin's internal plot ID
	Parameters:
		nPlotType = plot type
		dwAuxPlotInfo = auxiliary plot info.
	Returns:
		plot type name
	Example:
*/
string  GetPlotTypeName(int nPlotType, DWORD dwAuxPlotInfo = 0, DWORD dwLTPlotInfo = 0);
/**#
	Parameters:
		lpcsz = english string
		
	Returns:
		original string if running in English OS, otherwised return localized string
	Example:
*/
string  GetLocalized(LPCSTR lpcsz, LPCSTR lpcszCategory = NULL);
#define _L(_STR)	GetLocalized(_STR) // use this for all literal strings that should be localized	
#define _LC(_STR, _CAT)	GetLocalized(_STR, _CAT)	// must define _CATEGORY at the beginning of the file


/**#
	It handles '|'-separated string.
*/
string  GetLocalizedEx(LPCSTR lpcsz, LPCSTR lpcszCategory = NULL, DWORD dwCtrl = 0);
#define _LB(_STR)	GetLocalizedEx(_STR)		// for bitwise-separated string


/**#
	Parameters:
		lpcszInOut = intput/output theme file 
		lpcszIn = second intput theme file 
		
	Returns:
		TRUE if successfully combined themes, otherwise FALSE
	Example:
*/
BOOL	CombineThemes(LPCSTR lpcszInOut, LPCSTR lpcszIn);

/** >Origin System
	Parameters:
		lpBuffer = Pointer to a string buffer that receives the null-terminated string specifying the temporary file path. 
				   The returned string ends with a backslash, for example, C:\TEMP\.  
		nBufferSize = Specifies the size of the string buffer identified by lpBuffer 
		
	Returns:
		0 = return by WinAPI GetTempPath
		1 = return TEMP folder in Origin ini path
		2 = failure
	Example:
		char szTemp[MAXFULLPATH];
		int nTempPathType = get_temp_path(szTemp, MAXFULLPATH);
		if(0 == nTempPathType)
		{
			printf("Temp path is %s\n which is the standard location and is writable.\n", szTemp);
		}
		else if(1 == nTempPathType)
		{
			printf("For some reason the standard windows temp path is not writable, so we have to use Origin's user files path as the temp path\n%s\n", szTemp);
		}
		else 
			out_str("Error getting a valid temp path");

*/
int get_temp_path(LPSTR lpBuffer, int nBufferSize);

/** >Mathematical
		Similar to LabTalk limit -r command, to round a set of min, max and increment values
	Parameters:
		pmin = pointer to the min value
		pmax = pointer to the max value
		pinc = pointer the the increment value
		nSteps = number of steps to divide the given range roughly defined by pmin and pmax. If you know the increment and do not want it to be changed, pass 0 for steps
		bLogScale = TRUE if the rounding should be done in log scale, otherwise it is rounded in linear scale
	Returns:
		If this function success, the return value is the number of steps determined after the rounding, otherwise a negative value will be returned.
	Example:
		double x1 = -23.4;
		double x2 = 235.89;
		double xinc;
		int nSteps = RoundLimits(&x1, &x2, &xinc);
		printf("After rounding, the result is %d divisions, from %f to %f with an increment of %f\n", nSteps, x1, x2, xinc);
		// we next force increment to a particular value to redo rounding
		xinc = 50;
		nSteps =RoundLimits(&x1, &x2, &xinc, 0);
		printf("Forcing increment to be 50, the result is %d divisions, from %f to %f with an increment of %f\n", nSteps, x1, x2, xinc);
*/
int RoundLimits(double* pmin, double* pmax, double* pinc, int nSteps = 8, BOOL bLogScale = FALSE);

/** >Character/String Manipulation
		Similar to LabTalk $(x) notation, convert a double value into a string using LabTalk formating notation
	Parameters:
		dbVal = value to convert
		lpszOutput = buffer to receive the output
		nOutputSize = size of the buffer
		lpcszFormat = LabTalk formatting string, "*", or "*5*" etc
	Returns:
		None

	Example:
		char szTemp[30];
		DoubleToStr(Pi, szTemp, 30, "*3");
		printf("Pi is %s for only 3 significant digits\n", szTemp);
*/
void DoubleToStr(double dbVal, LPSTR lpszOutput, int nOutputSize, LPCTSTR lpcszFormat);

#endif //_OC_VER > 0x0703

////////////////////////////////////////////////////////////////////
#endif //_UTILITIES_H
