/*------------------------------------------------------------------------------*
 * File Name: sys_utils.c				 										*
 * Creation: GJL 3/13/02														*
 * Purpose: Basic and common utilities for general Origin C development.		*
 * Copyright (c) OriginLab Corp.	2002, 2003, 2004, 2005, 2006, 2007			*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 *	JCG 06/17/03 QA70-4575 IMP_WIZD_BUG_45_AND_28								*
 * EJP 07-10-2003 v7.0622 QA70-4745 SET_PAGE_IMPORT_INFO_ON_123_ASC_IMPORT		*
 * SY 09-12-2003 QA70-5158 v7.0694 OC_NEED_ROBUST_GET_TEMP_PATH_FUNCTION		*
 * EJP 11-20-2003 v7.5764 QA70-5587 FAIL_TO_EXPORT_1200DPI_BITMAP				*
 * EJP 11-24-2003 v7.5769 QA70-5604 LOCALIZE_FILE_TYPE_ALL_FILES				*
 * AW 10/27/03 v7.0733 QA70-5398 ADD_OC_BASIC_IO								*
 * EJP 04-29-2004 v7.5837 QA70-6342 ACCESS_STR_TO_TIME_FUNC_FROM_LABTALK		*
 * Frank 5/26/04  v8.0878 QA70-6418 GET_ALLUSER_FOLDEL_PATH						*
 * Frank 9/14/04  v8.0131 QA70-6903 PAD_CHAR_TO_STRING							*
 * Frank 9/23/04  v8.0137 QA70-6027 CONVERT_NUM_TO_STRING_VECTOR				*
 * SY 10/13/2004 v8.0147 IMPORT_WIZARD_CLEANUP									*
 * Frank 10/27/04 v8.0156  MATRIX_OR_VECTOR_TREENODE_OUTPUT_STRING				*
 * Frank 1/22/05 v8.0185c  FUNCTION_FINDFOLDER_TO_TREENODE_OR_VECTOR			*
 * DSC 2/7/05 v8.0190 CONVERT_STRING_TO_TAG_NAME								*
 * DSC 2/17/05 GET_ORIGIN_PATH													*
 * DSC 2/25/04 v8.0198 ALLOW_WILDCARD_IN_FIND_FILES								*
 * DSC 3/7/05 v8.0201 MOVE_TO_OKUTIL											*
 * DG 3/31/05 v8.0213 REMOVE_REPEAT_ITEM_IN_VECTOR								*
 * DG 4/2/05 v8.0214 FOLDER_WITH_DISPLAY_ICON									*
 * DG 4/6/05 v8.0217 FILE_TIME_COMPARE											*
 * DSC 6/16/05 ADD_SORT_XF_LIST_OPTIONS											*
 * DSC 6/27/05 CONSTRUCT_THEME_FILE_FROM_COMPOSITE_NAME							*
 * DG 7/18/05 QA70-6599 v8.0270 IS_REPEATE_STR									*
 * DSC 8/4/05 NEED_FILE_SIZE_IN_BYTES											*
 * Frank 9/14/05 MOVE_FROM_LT_PE_STATIC											*
 * Kevin 09/30/05 ADD_FILE_COMPARE_TIME_OPTION									*
 * EJP 2005-10-06 v8.0314 ADD_GETOPENBOX_WITH_GROUP_NAME						*
 * Frank 10/17/06 ADD_DOUBLE_OUTPUR_FORMAT_IN_TREE_OUT							*
 * Kevin 11/15/05 FIX_ATOF_FAIL_TO_CONVERT_WHEN_STRING_HAVE_BLANK				*
 * CPY 11/17/05 DLGSAVE_XF, some clean up, group to allow *.txt					*
 * EJP 2006-01-27 v8.0362 QA70-7921 MULTI_FILE_IMPORT_WITH_XF					*
 * DSC 1/31/06 QA70-7635 v8.0366 CENTRALIZE_FIND_FILES_CODES					*
 * EJP 2006-02-17 v8.0366 MOVE_IMPORT_FILE_INFO_FROM_OC_TO_VC					*
 * Iris 4/13/06 CHECK_SIGN_DIGITES_LARGE_THAN_0									*
 * Joe  6/26/06 ADD_STR_SEPARATE                                                *
 * SY 2006-10-02 v8.0493 QA70-9015 XF_THEME_BOOK_AND_SHEET						*
 * Jasmine 10/13/06 GET_FILE_EXT_DESC											*
 * Cheney 2006-11-10 MOVE_IS_EMPTY_OR_UNASSIGN_FROM_EXPASC						*
 * Jasmine 12/12/06 FIND_CONTIGUOUS_RANGE										*
 * Iris 12/13/2006 KEEP_OLD_POSTFIX_FORMAT_FOR_NEXT_FILENAME					*
 * Jake 05/23/07 GET_SAVE_PATH_FROM_ORIGIN_INI									*
 * EJP 2007-05-24 v8.0627 QA70-9796 OC_ACCESS_TO_FDLOG							*
 * Jake 05/31/07 STATIC_GET_PATH_FROM_INI										*
 *	Folger 06/13/07 SET_FILE_GROUP_DEFAULT_PATH									*
 * Sim 06-15-2007 FILE_NAME_CAN_NOT_BE_EMPTY_OR_ONLY_WITH_SPACE_CHARS			*
 * Jake 06/18/07 v8.0643 GET_PATH_TRACK_LIST_FROM_REGISTRY						*
 * Jake 06/18/07 v8.0643 UPDATE_PATH_TRACK_LIST_TO_REGISTRY						*
 * Sim 06-18-2007 ADD_SHOW_DLG_CHECK_BOX_TO_SAVE_AS_DLG							*
 * Folger 06/18/07 CORRECT_ERROR_COMMENT										*
 * Jake 06/19/07 v8.0644 CONVERT_PREDEFINED_PATH_TO_REAL_PATH					*
 * Nicole 07/05/2007 v8.0655 REMOVE_SPACE_FOR_LOCATION_STRING					*
 * Sim 07-17-2007 IMPROVE_FILTER_SETTING_FUNC									*
 *	Hong 08/14/07 QA80-9015 ADD_GROUP_FOLDER_INTO_SEARCH_LIST_FOR_DRAG_AND_DROP	*
 * Folger 08/21/07 ADD_FILE_PATH_PARAM_TO_SPECIFY_GROUP_PATH					*
 * Folger 08/21/07 REMOVE_ONE_LINE_FROM_FILTER_INI_SETTING						*
 * Folger 08/23/07 COMPARE_TWO_FILES_MODIFIED_TIME								*
 * Folger 09/03/07 MODIFY_GET_ORIGIN75_USER_PATH_SUGGESTED_BY_DAVID				*
 * Folger 09/04/07 USE_FILE_LAST_MODIFIED_COMPARE_OF_VC_LEVEL					*
 *	Hong 09/04/07 QA80-10340 v8.0695 FIX_DEFAULT_PATH_FAIL_KEPT_FOR_EVERY_IMPORT_XF_OPEN_FILE
 *	Hong 09/26/07 8.0709 FIX_FILE_DIALOG_SHOW_ASCII_FOR_ALL_IMPORT				*
 *	Hong 12/06/07 v8.0762 IMPORT_SUPPORT_RELATIVE_PATH_FOR_REIMPORT_SAMPLE_REQUIREMENT
 * EJP 2007-12-18 v8.0773 GET_NUM_FILE_EXT_GRPS_FROM_LT_SYSTEM_OBJ				*
 *	CPY 12/26/07 QA70-10870 NUMERIC_INPUT_BOX_NEEDED							*
 *	Hong 01/08/08 QA80-10541 USE_GROUP_TYPE_REMEMBER_LAST_OPEN_PATH				*
 *	Folger 01/14/08 GET_ORIGIN75_SYSTEM_FILE_PATH								*
 *	Folger 01/15/08 OKUTIL_GET_ORIGIN75_PATH									*
 *	Folger 01/18/08 SHOULD_SORT_INPUT_VECTOR_BEFORE_FIND_CONTIGUOUS_RANGE		*
 * EJP 2008-01-23 v8.0792 QA70-10839 OC_CHECK_FOR_UPDATES						*
 * EJP 2008-02-05 v8.0801 QA70-11058 IW_NEED_SHOW_ALL_TEMPLATES_IN_UFF			*
 *	CPY 4/3/08 PA_FIT_CNTRL_OPEN_EMPTY_NO_ERR_MSG								*
 *	Folger 04/17/08 QA80-11440 SYSTEM_UTILITY_FUNCTION_TO_REFRESH_ORIGIN_MAIN_MENU
 *	Jasmine 04/29/08 ADD_FUNC_REMOVE_EMPTY_ITEM_FROM_STRING_VECTOR				*
 *	Jasmine 05/05/08 GET_ELEMENT_FROM_VECTOR_BY_ANOTHER_FILTER_VECTOT			*
 *	Folger 06/05/08 OPX_FILE_PUBLISH_SHOULD_IDENTIFY_BY_VERSION_FIRST			*
 *	Hong 07/18/08 QA80-11861 FIX_FILE_GROUP_FAIL_USING_DEFAULT_PATH				*
 *	Folger 08/22/08 QA80-12074 ADD_UTILITY_FUNCTION_FOR_INITIAL_TEMPLATE_LIST	*
 *	Kyle 09/12/08 READ_ALL_LINES_IF_INUMLINES_IS_0_IN_FUNC_READFILELINES		*
 *	Jasmine 10/23/08 QA80-12442 SHOW_WARNING_WHEN_SAVE_READ_ONLY_FILE			*
 *	Jasmine 10/29/08 MISS_CASE_THAT_vsToCheck_ELEMENT_ALL_IN_vsList				*
 *	Sophy 12/18/2008 MOVE_CONVERT_STRINGVECTORY_TO_DOUBLEVECTOR_FROM_OC_TO_VC	*
 *	Sim 12-23-2008 QA80-12836 SUPPORT_FILE_BROWSER_BUTTON						*
 *	Kyle 01/04/2009 QA70-12890-P4 CENTRALIZE_CODE_TO_GET_AND_UPDATE_CUSTOM_DATE_FORMAT
 *  Iris 01/21/2009 QA80-12997 GETOPENBOX_GOT_RUNTIME_ERR_WHEN_WORKED_WITH_FILEDLGFOURPTYPE
 *	Hong 03/13/09 FIX_UNSORTED_VECTOR_FAIL_GET_CORRECT_INDEX					*
 *	Folger 03/26/09 ANALYSIS_OUTPUT_REPORT_SHEET_NAME_SHOULD_BE_EXCLAMATION_CHAR_ENDING
 *	DSC 4/6/09 QA70-13396 STANDARDIZE_ORIGIN_INI_CASE							*
 *	Hong 04/07/09 QA80-13419 GET_DEBUG_VECTOR_TREENODE_DISPLAY_STRING			*
 *	Hong 04/08/09 QA80-13419 NO_BRACKET_WHEN_ONLY_ONE_ELEMENT					*
 *	EJP 2009-04-23 DLGFILE_XF_NEED_DEFAULT_TO_CALLERS_FILE_TYPE					*
 *	Sim 05-07-2009 QA80-13571 FIX_CRASH_WHEN_FILE_PATH_LENGTH_IS_TOO_LONG		*
 *	Folger 05/11/09 QA80-13571 CHECK_ADD_FILE_EXT_SHOULD_RETURN_PROPER_ERROR	*
 *	Hong 05/18/09 QA80-13629 LT_FILE_DLG_ADD_DEFAILT_PATH_OPTION				*
 *	Kyle 06/22/2009 QA80-13818 CUSTOM_DATE_FORMAT_SHOULD_BE_CASE_SENSITIVE		*
 *	Sim 07-02-2009 QA80-13869 SUPPORT_DRAG_AND_DROP_OMC_FILE					*
 *	Hong 07/03/09 QA80-12534-P1 FIX_IMPWIZ_FAIL_PREVIEW_UNICODE_HEADLINES		*
 *	Sim 07-09-2009 QA80-13891 EXPORT_FILE_SUPPRESS_FILE_EXIST_PROMPT			*
 *	Folger 08/10/09 QA80-13998 ACTIVE_SUMMARY_BOOK_ONLY_IF_IN_ACTIVE_FOLDER		*
 *	Folger 08/27/09 QA80-14215 CHANGE_USER_FILES_FOLDER_IN_ORIGIN				*
 *	Sim 08-31-2009 QA81-14106 IMPROVE_ED_DIALOG									*
 *	Folger 10/21/09 QA81-14506 FAILS_TO_IMPORT_CSV_FILE_IN_SAMPLES_FOLDER_UNDER_GOS_BY_DEFAULT
 *	EJP 2010-01-13 QA81-14672 DRAG_DROP_OIF_FILE								*
 *	ML 2/12/2010 QA70-15113 FORMAT_MENU_UPDATE_ON_INSTALLING_OMC				*
 *	Folger 04/23/10 QA81-15347 LT_ACCESS_TO_WKS_SELECTION_BY_XF					*
 *	Folger 07/12/10 ORG-532 TRANSFER_USER_FILES_FAILED_TO_SHOW_81_FILES			*
 *------------------------------------------------------------------------------*/

#include <origin.h> // main Origin C header that is precompiled and already include most headers
#include <..\OriginLab\INIFileEx.h>
#pragma labtalk(0) //--- CPY 7/26/05 hide all functions in this file from LT access, as XF should be used instead
 
// TD 10-22-03 REMOVED_DEPENDENCY
//#include "Filter_Utils.h"
///DSC 1/11/07 REMOVE_LOCAL_H #include "$local.h"
#include <OC_Res.h>		///DG FOLDER_WITH_DISPLAY_ICON
#include <..\OriginLab\PathTrack.h>///Jake 06/18/07 v8.0643 GET_PATH_TRACK_LIST_FROM_REGISTRY
/// EJP 2007-05-24 v8.0627 QA70-9796 OC_ACCESS_TO_FDLOG
#define USE_OC_ACCESS_TO_FDLOG 1
#ifdef USE_OC_ACCESS_TO_FDLOG 
#include <okocUtils.h>
#endif // !USE_OC_ACCESS_TO_FDLOG
/// end OC_ACCESS_TO_FDLOG

#include <ocu.h>	///Jasmine 10/23/08 QA80-12442 SHOW_WARNING_WHEN_SAVE_READ_ONLY_FILE

/// EJP 11-24-2003 v7.5769 QA70-5604 LOCALIZE_FILE_TYPE_ALL_FILES
#define FILETYPE_ALL_FILES _L("[All Files (*.*)] *.*")
/// end LOCALIZE_FILE_TYPE_ALL_FILES
///Frank 5/26/04  v8.0878 QA70-6418 GET_ALLUSER_FOLDEL_PATH						
//#define ALLUSERFOLDER	"All Users\\"///Frank 1/22/05 CENTRALIZE_MARCO_OF_FOLDER_INFO remove this 
///End GET_ALLUSER_FOLDEL_PATH

///---Sim 07-17-2007 IMPROVE_FILTER_SETTING_FUNC
/*
///Jake 07/12/07 GET_AND_SET_FILTER_SETTING
#define STR_FILTER_SECTION			"Filter" 
#define STR_INI_FILENAME			"origin.ini"
///end GET_AND_SET_FILTER_SETTING
*/
///---END IMPROVE_FILTER_SETTING_FUNC

/**
	It appends to the string str the ' ' characters until its size
	reaches nSize. 
*/
void	append_blanks_to_size(string &str, int nSize)
{
	int		nLength = str.GetLength();
	for (int ii = nLength + 1; ii <= nSize; ii++)
		str += ' ';
	
	return;
}

// Function prototypes of static functions


static int GetFileDialogBox( StringArray &saFilePaths, StringArray &saFiletypes, FDLogDialogType fdtDialogType = FDLOG_TYPE_OPEN_SINGLE,
	 LPCSTR lpcszPath = NULL, LPCSTR lpcszFilename = NULL, LPCSTR lpcszDialogName = NULL );

static int GetFileDialogBox( StringArray &saFilePaths, FDLogUseGroup nFDLogUseGroup, FDLogDialogType fdtDialogType = FDLOG_TYPE_OPEN_SINGLE,
	 LPCSTR lpcszPath = NULL, LPCSTR lpcszFilename = NULL, LPCSTR lpcszDialogName = NULL );

static int GetFileDialogBox( StringArray& saFilePaths, LPCSTR lpcszFileType = NULL, FDLogDialogType fdtDialogType = FDLOG_TYPE_OPEN_SINGLE,
	 LPCSTR lpcszPath = NULL, LPCSTR lpcszFilename = NULL, LPCSTR lpcszDialogName = NULL );

//////////////////////////////////////////////////////////////////////////////////
/**
		Resets or initializes the LabTalk FDLog object. Should be called prior to
		opening an FDLog dialog box.
	Example:
		FDLogInit();
	Parameters:
		None
	Return:
		Returns 0 on successful exit.
*/
int FDLogInit()
{
	_LT_Obj
	{
		FDLog.Reset();                // Reset FDLog object
		FDlog.NumTypes = 0;           // Remove all file types
		FDLOG.OptionDLG$ = "";        // Reset button to off
		FDLOG.Checkname$ = "";        // Reset check box to null
		FDLOG.ShowComment = 0;        // Reset the comments box to closed
		FDLOG.CheckStatus = 0;        // Reset checkbox to off
		FDLOG.DlgName$ = "";		  // Reset dialog name to nothing
		FDLOG.Path$ = "";			  // Reset default path to nothing	
		FDLOG.Default$ = "";		  // Reset contents of "File Name" edit box to nothing
		FDLOG.AsReadOnly = 0;         // Reset read only checkbox to disabled
		//------------------- CPY v6.0252 t6746 1/26/00 MULTI_OPEN_SUPPORT_BY_ROW_AND_BY_COL_APPEND
		FDLOG.MultiOpen.ComboName$ = "";
		if( FDLOG.MultiOpen.ComboSel < 1 || FDLOG.MultiOpen.ComboSel > 3 )
			FDLOG.MultiOpen.ComboSel = 2; // Import into new columns
		//------------------- end t6746

		//------------------- GJL v7.0358 QA70-4078 3/17/03 ORIGINC_MULTI_OPEN_SUPPORT
		FDLOG.Open.MultiSel = 0;      // Reset multiple selection switch (turn off by default)
		//------------------- QA70-4078
	}
	
	return 0;
}

//------------------- GJL v7.0357 QA70-4078 3/17/03 ORIGINC_MULTI_OPEN_SUPPORT
//////////////////////////////////////////////////////////////////////////////////
/**
		Open an FDLog dialog box having the enumerated type FDLogDialogType with
		possible values FDLOG_TYPE_SAVE_AS, FDLOG_TYPE_OPEN_SINGLE, FDLOG_TYPE_OPEN_MULTISEL,
		and FDLOG_TYPE_MULTI_OPEN. Return the path and filename of all selected files. 
	Example:
		See overloaded GetFileDialogBox functions in this source file. 
	Parameters:
		saFilePaths=Output vector of strings containing path and filename of all selected files
		fdtDialogType=Input type of dialog: FDLOG_TYPE_SAVE_AS, FDLOG_TYPE_OPEN_SINGLE, FDLOG_TYPE_OPEN_MULTISEL,
			and FDLOG_TYPE_MULTI_OPEN
	Return:
		Returns the number of selected files.
*/
/// SY 2006-10-02 v8.0493 XF_THEME_BOOK_AND_SHEET
///	int GetFDLogBox( StringArray &saFilePaths, FDLogDialogType fdtDialogType )	
/// Hong 05/18/09 QA80-13629 LT_FILE_DLG_ADD_DEFAILT_PATH_OPTION
//int GetFDLogBox(StringArray &saFilePaths, FDLogDialogType fdtDialogType, BOOL bUseTemplate) // = FALSE
int GetFDLogBox(StringArray &saFilePaths, FDLogDialogType fdtDialogType, BOOL bUseTemplate, LPCSTR lpcszPath/* = NULL*/) // = FALSE
/// end LT_FILE_DLG_ADD_DEFAILT_PATH_OPTION
/// end XF_THEME_BOOK_AND_SHEET
{
	char szTemp[ MAXFULLPATH ];
	
	saFilePaths.SetSize(1);                      // Assume 1 file
	saFilePaths[0] = "";                         // Initialize path and filename to ""
	
	using FDLog = LabTalk.FDLog;                 // Use LabTalk FDLog object
	/// Hong 05/18/09 QA80-13629 LT_FILE_DLG_ADD_DEFAILT_PATH_OPTION
	if( lpcszPath && '\0' != *lpcszPath )
		FDLog.Path$ = lpcszPath;
	/// end LT_FILE_DLG_ADD_DEFAILT_PATH_OPTION
	
	switch( fdtDialogType )                      // Open requested dialog type
	{
		case FDLOG_TYPE_SAVE_AS:
			if( FDLog.SaveAs( "A" ) )                    // Open SaveAs dialog box
				return 0;                                // Error, 0 files selected
			else
			{
				LT_get_str( "%A", szTemp, MAXFULLPATH ); // Get filename of selected file from LabTalk variable
				saFilePaths[0] = FDLog.Path$ + szTemp;   // Return path and filename
			}
			return 1;                                    // Return number of selected files
		case FDLOG_TYPE_OPEN_SINGLE:
			FDLog.Open.MultiSel = 0;
			if( FDLog.Open( "A" ) )                      // Open Single Open dialog box without muliple selection
				return 0;                                // Error, 0 files selected
			else
			{
				LT_get_str( "%A", szTemp, MAXFULLPATH ); // Get filename of selected file from LabTalk variable
				saFilePaths[0] = FDLog.Path$ + szTemp;   // Return path and filename
			}
			return 1;                                    // Return number of selected files
		case FDLOG_TYPE_OPEN_MULTISEL:
			FDLog.Open.MultiSel = 1;    
			if( FDLog.Open( "A" ) )                              // Open Single Open dialog box with multiple selection
				return 0;                                        // Error, 0 files selected
			saFilePaths.SetSize(FDLog.MultiOpen.Count);
			for( int ii = 0; ii < FDLog.MultiOpen.Count; ii++ )  // For each file selected
			{
				FDLog.Get("A", ii+1);                            // Get filename into LabTalk variable
				LT_get_str( "%A", szTemp, MAXFULLPATH );         // Get filename of selected file from LabTalk variable
				saFilePaths[ii] = FDLog.Path$ + szTemp;          // Return path and filename
			}
			return ii;                                           // Return number of selected files
		case FDLOG_TYPE_MULTI_OPEN:
			/// SY 2006-10-02 v8.0493 XF_THEME_BOOK_AND_SHEET                          
			///	FDLog.MultiOpen.ColView = FDLOG_MULTI_OPEN_SHOW_FILE_SIZE |
			///                          FDLOG_MULTI_OPEN_SHOW_MODIFY; // Display Filename, Size, and Modified
			DWORD dwFlags = FDLOG_MULTI_OPEN_SHOW_FILE_SIZE |
			                          FDLOG_MULTI_OPEN_SHOW_MODIFY; // Display Filename, Size, and Modified
			
			if( bUseTemplate )
				dwFlags |= FDLOG_MULTI_OPEN_SHOW_TEMPLATE;
			
			FDLog.MultiOpen.ColView = dwFlags;
			/// end XF_THEME_BOOK_AND_SHEET
			
			FDLog.Checkname$="";                                 // Clear Checkbox name 
			if( FDLog.MultiOpen() == NANUM )                     // Open Multi-Open dialog box
				return 0;                                        // Error, 0 files selected
			saFilePaths.SetSize(FDLog.MultiOpen.Count);
			for( int ii = 0; ii < FDLog.MultiOpen.Count; ii++ )  // For each file selected
			{
				FDLog.Get("A", ii+1);                            // Get path and filename into LabTalk variable
				LT_get_str( "%A", szTemp, MAXFULLPATH );         // Get path and filename of selected file from LabTalk variable
				saFilePaths[ii] = szTemp;                        // Return path and filename
			}
			return ii;                                           // Return number of selected files
		default:
			return 0;                                    // Return with 0 files saved or opened
	}
	return 0;                                    // Return with 0 files saved or opened
}
//------------------- QA70-4078

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

/**
		Open an FDLog SaveAs, Open (with or without multiple selection enabled), or
		MultiOpen dialog box passing the file types to list in an array of strings. 
	Example:
		See overloaded GetSaveAsBox, GetOpenBox, and GetMultiOpenBox functions in
		this source file.
	Parameters:
		saFilePaths=Output vector of strings containing path and filename of all selected files
		saFiletypes=Vector containing file types to list in the dialog box, each element
			of vector must follow syntax of LabTalk FDLog.TypeN$ object property
		fdtDialogType=Input type of dialog: FDLOG_TYPE_SAVE_AS, FDLOG_TYPE_OPEN_SINGLE, FDLOG_TYPE_OPEN_MULTISEL,
			and FDLOG_TYPE_MULTI_OPEN
		lpcszPath=Initial path when dialog opens, default NULL uses FDLog tracking
		lpcszFileName=Initial filename when dialog opens, default NULL uses an empty string 
		lpcszDialogName=Title of the dialog box, default NULL uses "Open" or "Save As" 
	Return:
		Returns the number of selected files.
*/
static int GetFileDialogBox( StringArray &saFilePaths, StringArray &saFiletypes, FDLogDialogType fdtDialogType,
	 LPCSTR lpcszPath, LPCSTR lpcszFilename, LPCSTR lpcszDialogName ) // fdtDialogType = FDLOG_TYPE_OPEN_SINGLE, lpcszPath = NULL, lpcszFilename = NULL, lpcszDialogName = NULL
{
	int ii, iSize;
	string strDefaultPath = lpcszPath;
	string strDefaultFilename = lpcszFilename;
	string strDialogName = lpcszDialogName;
	string strLTCommand;
	
	_LT_Obj
	{
		if( strDefaultPath.IsEmpty() )               // If path is not passed as argument...
			strDefaultPath = FDLog.Path$;            //   get last used path from FDLog object for tracking

		FDLogInit();                                 // Initialize LabTalk FDLog object
		
		if( !strDefaultPath.IsEmpty() )              // If path is passed as argument or is being tracked...
			FDLog.Path$ = strDefaultPath;            //   initialize path

		FDLog.Default$ = strDefaultFilename;         // Initialize filename

		iSize = saFiletypes.GetSize();                // Get number of file types
		if( iSize <= 1 && saFiletypes[ii].IsEmpty() ) // If no file types are specified...
		{
			iSize = 0;                               //   set size as 0
			FDLog.NumTypes = iSize;                  //   initialize number of passed filetypes to 0
		}
		else                                         // Else filetypes are specified...
		{
			FDLog.NumTypes = iSize;                  //   initialize number of passed filetypes
			FDLog.Deftype=1;                         //   initialize default filetype to first in filetype list
			for( ii = 0; ii < iSize; ii++ )          //   loop on all filetypes
			{
				strLTCommand.Format( "FDLog.Type%d$=%s;", ii+1, saFiletypes[ii] ); // create enumerated LabTalk command
				LT_execute( strLTCommand );          //     execute enumerated LabTalk command to initialize filetypes
			}
		}
		FDLog.DlgName$ = strDialogName;              // Initialize dialog box name

		return GetFDLogBox(saFilePaths, fdtDialogType); // Open FDLog dialog box and get path and filename(s)
	}
}

/// SY 2006-10-02 v8.0493 QA70-9015 XF_THEME_BOOK_AND_SHEET
// Move from GETNBox.c
typedef bool (*PFN_IMG_DLG) (HWND hwndParent, string& szFileName, LPCSTR lpcszTitle, bool bOpen);
typedef bool (*PFN_IMGS_DLG) (HWND hwndParent, StringArray& saFileName, LPCSTR lpcszTitle, bool bOpen, bool bMultiSel);

/// EJP 2007-05-24 v8.0627 QA70-9796 OC_ACCESS_TO_FDLOG
static int get_image_open_box(string& strFile, LPCSTR lpcszTitle, bool bMultiFiles)
{
	//---- CPY 4/20/07 IMPORT_INTO_MATRIX_SHOWS_NO_DIALOG
	// as a result of CPY 4/19/07 QA70-9653 FIND_FUNC_NEED_DEFAULT_TO_ORIGINC
	string strImgUitls = "originlab\\image_utils";
	//----
	
	/// Iris 8/28/06 SUPPORT_GRAPHS_FILES_CONTRL
	if(bMultiFiles)
	{
		Function fn = Project.FindFunction("image_files_dlg", strImgUitls);//"image_utils");
		PFN_IMGS_DLG pfn = fn;
		if( pfn )
		{
			StringArray saFiles;
			bool bRet = pfn(GetWindow(), saFiles, lpcszTitle, true, true);
			if(bRet)
			{
				//--- Iris 8/31/06
				//file_name_array_to_str(strFile, saFiles);
				strFile = str_combine(saFiles, "\r\n");
				//--- 
				return 1;
			}
		}
		else
			out_str("error:image_files_dlg not found");
	}
	///end SUPPORT_GRAPHS_FILES_CONTRL
	else
	{
		Function fn = Project.FindFunction("image_file_dlg", strImgUitls);//"image_utils");
		PFN_IMG_DLG pfn = fn;
		if( pfn )
		{
			bool bRet = pfn(GetWindow(), strFile, lpcszTitle, true);
			if(bRet)
				return 1;
		}
		else
			out_str("error:image_file_dlg not found");
	}
	return 0;
}
/// end OC_ACCESS_TO_FDLOG

//--- Iris 11/01/06 v8.0502d NEED_SHOW_DEFAULT_PATH_FOR_XF_IMGPLATTE
///	int get_open_box_by_file_group(string& strFile, LPCSTR lpcszGroup, LPCSTR lpcszTitle, BOOL bMultiFiles)
int get_open_box_by_file_group(string& strFile, LPCSTR lpcszGroup, LPCSTR lpcszTitle, bool bMultiFiles, bool bUseTemplate, LPCSTR lpcszDefaultPath, LPCSTR lpcszDefaultFilename) // = FALSE
//--- 
{
	/// EJP 2007-05-30 v8.0631 QA70-9796 OC_ACCESS_TO_FDLOG
	DWORD dwFlags = 0;
	if( bMultiFiles )
		dwFlags |= OPENBOX_FLAG_MULTIFILES;
	if( bUseTemplate )
		dwFlags |= OPENBOX_FLAG_USETEMPLATE;

	return get_open_box_by_file_group(strFile, lpcszGroup, lpcszTitle, dwFlags, lpcszDefaultPath, lpcszDefaultFilename);
	/// end OC_ACCESS_TO_FDLOG
}

/// EJP 2007-05-30 v8.0631 QA70-9796 OC_ACCESS_TO_FDLOG
int get_open_box_by_file_group(
	string& strFile,
	LPCSTR lpcszGroup, // name of file extension group
	LPCSTR lpcszTitle, // dialog title, = NULL
	DWORD dwFlags, // see OPENBOX_FLAG_* constants, = 0
	LPCSTR lpcszDefaultPath, // default path, = NULL
	LPCSTR lpcszDefaultFilename, // default file name, = NULL
	LPCSTR lpcszCheckBoxName, // optional check box label, = NULL
	int* lpnCheckBoxState, // state of optional check box, = NULL
	LPCSTR lpcszFuncName // registry name to load/save check box state, = NULL
	)
{
	if( NULL == lpcszGroup || 0 == *lpcszGroup )
		return 0; // group name is required
/// end OC_ACCESS_TO_FDLOG

	//---- CPY 10/2/06 FILE_DIALOG_SHOW_ASCII_FOR_ALL_IMPORT
	string strTitle = lpcszTitle; 
	if(strTitle.IsEmpty()) 
		strTitle = lpcszGroup;	// we may have a better file group label somewhere, but this is at least better then "Multiple ASCII"
	//----
	///Sophy 6/4/2010 ORG-150 IMAGE_GROUP_FOR_IMPORT_IMAGE_FILE_DLG
	//if(lstrcmpi(lpcszGroup, "image") == 0)
		////return get_image_open_box(strFile, lpcszTitle, (dwFlags & OPENBOX_FLAG_MULTIFILES));
		//return get_image_open_box(strFile, strTitle, (dwFlags & OPENBOX_FLAG_MULTIFILES)); /// Hong 09/26/07 8.0709 FIX_FILE_DIALOG_SHOW_ASCII_FOR_ALL_IMPORT
	///end IMAGE_GROUP_FOR_IMPORT_IMAGE_FILE_DLG
	
/// EJP 2007-05-24 v8.0627 QA70-9796 OC_ACCESS_TO_FDLOG
#ifdef USE_OC_ACCESS_TO_FDLOG 

	FDLOGINFO fdi;
	memset(&fdi, 0, sizeof(FDLOGINFO));
	fdi.hWndParent = GetWindow();

	if( dwFlags & OPENBOX_FLAG_MULTIFILES )
	{
		fdi.nDialogType = FDLOGTYPE_MULTIOPEN;
		fdi.nColView = FDLOG_MULTI_OPEN_SHOW_FILE_SIZE | FDLOG_MULTI_OPEN_SHOW_MODIFY;
		if( dwFlags & OPENBOX_FLAG_USETEMPLATE )
			fdi.nColView |= FDLOG_MULTI_OPEN_SHOW_TEMPLATE;
	}
	else
	{
		fdi.nDialogType = FDLOGTYPE_OPEN;
		if( dwFlags & OPENBOX_FLAG_MULTISEL )
			fdi.bMultiSel = TRUE;
	}
	fdi.lpcszGroupName = lpcszGroup;
	//fdi.lpcszCaption = lpcszTitle;
	fdi.lpcszCaption = strTitle; /// Hong 09/26/07 8.0709 FIX_FILE_DIALOG_SHOW_ASCII_FOR_ALL_IMPORT
///---Sim 07-09-2009 QA80-13891 EXPORT_FILE_SUPPRESS_FILE_EXIST_PROMPT	
#ifdef __EXPORT_FILE_SUPPRESS_FILE_EXIST_PROMPT__
	fdi.bSuppressPrompt = ( dwFlags & OPENBOX_FLAG_SUPPRESSPROMPT ) ? TRUE : FALSE;
#endif // __EXPORT_FILE_SUPPRESS_FILE_EXIST_PROMPT__
///---END QA80-13891 EXPORT_FILE_SUPPRESS_FILE_EXIST_PROMPT	

	// Setup optional check box label and state.
	string strRegSec, strRegKey;
	if( lpcszCheckBoxName )
	{
		fdi.lpcszCheckName = lpcszCheckBoxName;

		DWORD dwVal = 0; // 0 for our internal default

		// if caller passed in a value then use it
		if( lpnCheckBoxState )
			dwVal = *lpnCheckBoxState;

		// if caller does not force their passed in value then use value in registry
		if( 0 == (dwFlags & OPENBOX_FLAG_FORCECHECKSTATE) )
		{
			// Make registry section name
			strRegSec.Format("FileDialog %s", lpcszCheckBoxName);
			
			// Make registry key name
			if( lpcszFuncName )
				strRegKey = lpcszFuncName;
			else
			{
				char szLastXFName[MAXFULLPATH];
				LT_get_str(LTVAR_LAST_XF, szLastXFName, MAXFULLPATH); 
				strRegKey = szLastXFName;
			}
	
			// Load registry value.
			// It is okay if this call fails since we have already init the value
			// with an internal default or the callers passed in value.
			dlg_load_registry(strRegSec, strRegKey, dwVal, dwVal);
		}

		fdi.nCheckStatus = dwVal;
	}

	// Need write access to default path so use local string.
	char szDefaultPath[MAX_PATH];
	/// Hong 09/04/07 QA80-10340 v8.0695 FIX_DEFAULT_PATH_FAIL_KEPT_FOR_EVERY_IMPORT_XF_OPEN_FILE
	/*
	if( lpcszDefaultPath )
		lstrcpy(szDefaultPath, lpcszDefaultPath);
	else
		szDefaultPath[0] = 0;
	fdi.lpszPath = szDefaultPath;
	*/
	if( lpcszDefaultPath )
	{
		/// Hong 07/18/08 QA80-11861 FIX_FILE_GROUP_FAIL_USING_DEFAULT_PATH
		//lstrcpy(szDefaultPath, lpcszDefaultPath);
		lstrcpyn(szDefaultPath, lpcszDefaultPath, MAX_PATH);
		/// end FIX_FILE_GROUP_FAIL_USING_DEFAULT_PATH
		fdi.lpszPath = szDefaultPath;
	}
	/// end FIX_DEFAULT_PATH_FAIL_KEPT_FOR_EVERY_IMPORT_XF_OPEN_FILE

	// Need write access to default file name so use local string.
	char szDefaultFileName[MAX_PATH];
	///---Sim 06-18-2007 FIX_DEFAULT_FILE_NAME
	//if( szDefaultFileName )
	if( lpcszDefaultFilename )		
	///---END FIX_DEFAULT_FILE_NAME
		lstrcpy(szDefaultFileName, lpcszDefaultFilename);
	else
		szDefaultFileName[0] = 0;
	fdi.lpszDefaultFileName = szDefaultFileName;

	StringArray saFileNames;
	if( okoc_file_dialog(&fdi, &saFileNames) )
		return 0;

	// Return optional check box state.
	if( lpcszCheckBoxName )
	{
		if( lpnCheckBoxState )	///---Sim 06-18-2007 FIX_AVOID_RUNTIME_ERROR
			*lpnCheckBoxState = fdi.nCheckStatus;
		dlg_save_to_registry(strRegSec, strRegKey, fdi.nCheckStatus);
	}

	strFile = str_combine(saFileNames, "\r\n");
	return saFileNames.GetSize();

#else !USE_OC_ACCESS_TO_FDLOG
/// end OC_ACCESS_TO_FDLOG

	//--- Iris 11/01/06 v8.0502d NEED_SHOW_DEFAULT_PATH_FOR_XF_IMGPLATTE
	//init_fdlog_with_group_name(lpcszGroup, NULL, NULL, strTitle);
	init_fdlog_with_group_name(lpcszGroup, lpcszDefaultPath, lpcszDefaultFilename, strTitle);
	//--- 
	
	int nType = (bMultiFiles ? FDLOG_TYPE_MULTI_OPEN : FDLOG_TYPE_OPEN_SINGLE);
	StringArray saFileNames;
	/// SY 2006-10-02 v8.0493 XF_THEME_BOOK_AND_SHEET
	///	if( GetFDLogBox(saFileNames, nType) )	
	if( GetFDLogBox(saFileNames, nType, bUseTemplate) )
	/// end XF_THEME_BOOK_AND_SHEET
	{
		int nFiles = saFileNames.GetSize();
		if( nFiles > 1 )
			//--- Iris 8/31/06
			//file_name_array_to_str(strFile, saFileNames);
			strFile = str_combine(saFileNames, "\r\n");
			//--- 
		else
			strFile = saFileNames[0];
		return nFiles;
	}
	return 0;

#endif // !USE_OC_ACCESS_TO_FDLOG /// EJP 2007-05-24 v8.0627 QA70-9796 OC_ACCESS_TO_FDLOG
}
/// end XF_THEME_BOOK_AND_SHEET

///---Sim 06-18-2007 ADD_SHOW_DLG_CHECK_BOX_TO_SAVE_AS_DLG
int get_saveas_box_by_file_group(
	string& strFile,
	LPCSTR lpcszGroup, // name of file extension group
	LPCSTR lpcszTitle, // dialog title, = NULL
	DWORD dwFlags, // see OPENBOX_FLAG_* constants, = 0
	LPCSTR lpcszDefaultPath, // default path, = NULL
	LPCSTR lpcszDefaultFilename, // default file name, = NULL
	LPCSTR lpcszCheckBoxName, // optional check box label, = NULL
	int* lpnCheckBoxState, // state of optional check box, = NULL
	LPCSTR lpcszFuncName // registry name to load/save check box state, = NULL
	)
{
	if( NULL == lpcszGroup || 0 == *lpcszGroup )
		return 0; // group name is required

	//---- CPY 10/2/06 FILE_DIALOG_SHOW_ASCII_FOR_ALL_IMPORT
	string strTitle = lpcszTitle; 
	if(strTitle.IsEmpty()) 
		strTitle = lpcszGroup;	// we may have a better file group label somewhere, but this is at least better then "Multiple ASCII"
	//----
	
	//if(lstrcmpi(lpcszGroup, "image") == 0)
		//return get_image_open_box(strFile, lpcszTitle, (dwFlags & OPENBOX_FLAG_MULTIFILES));
	
#ifdef USE_OC_ACCESS_TO_FDLOG 

	FDLOGINFO fdi;
	memset(&fdi, 0, sizeof(FDLOGINFO));
	fdi.hWndParent = GetWindow();

	/*
	if( dwFlags & OPENBOX_FLAG_MULTIFILES )
	{
		fdi.nDialogType = FDLOGTYPE_MULTIOPEN;
		fdi.nColView = FDLOG_MULTI_OPEN_SHOW_FILE_SIZE | FDLOG_MULTI_OPEN_SHOW_MODIFY;
		if( dwFlags & OPENBOX_FLAG_USETEMPLATE )
			fdi.nColView |= FDLOG_MULTI_OPEN_SHOW_TEMPLATE;
	}
	else
	{
	fdi.nDialogType = FDLOGTYPE_OPEN;
	if( dwFlags & OPENBOX_FLAG_MULTISEL )
		fdi.bMultiSel = TRUE;
	}
	*/
	fdi.nDialogType = FDLOGTYPE_SAVEAS;
	fdi.lpcszGroupName = lpcszGroup;
	//fdi.lpcszCaption = lpcszTitle;
	fdi.lpcszCaption = strTitle; /// Hong 09/26/07 8.0709 FIX_FILE_DIALOG_SHOW_ASCII_FOR_ALL_IMPORT
///---Sim 07-09-2009 QA80-13891 EXPORT_FILE_SUPPRESS_FILE_EXIST_PROMPT	
#ifdef __EXPORT_FILE_SUPPRESS_FILE_EXIST_PROMPT__
	fdi.bSuppressPrompt = ( dwFlags & OPENBOX_FLAG_SUPPRESSPROMPT ) ? TRUE : FALSE;
#endif // __EXPORT_FILE_SUPPRESS_FILE_EXIST_PROMPT__
///---END QA80-13891 EXPORT_FILE_SUPPRESS_FILE_EXIST_PROMPT	

	// Setup optional check box label and state.
	string strRegSec, strRegKey;
	if( lpcszCheckBoxName )
	{
		fdi.lpcszCheckName = lpcszCheckBoxName;

		DWORD dwVal = 0; // 0 for our internal default

		// if caller passed in a value then use it
		if( lpnCheckBoxState )
			dwVal = *lpnCheckBoxState;

		// if caller does not force their passed in value then use value in registry
		if( 0 == (dwFlags & OPENBOX_FLAG_FORCECHECKSTATE) )
		{
			// Make registry section name
			strRegSec.Format("FileDialog %s", lpcszCheckBoxName);
			
			// Make registry key name
			if( lpcszFuncName )
				strRegKey = lpcszFuncName;
			else
			{
				char szLastXFName[MAXFULLPATH];
				LT_get_str(LTVAR_LAST_XF, szLastXFName, MAXFULLPATH); 
				strRegKey = szLastXFName;
			}
	
			// Load registry value.
			// It is okay if this call fails since we have already init the value
			// with an internal default or the callers passed in value.
			dlg_load_registry(strRegSec, strRegKey, dwVal, dwVal);
		}

		fdi.nCheckStatus = dwVal;
	}

	// Need write access to default path so use local string.
	/// Hong 07/18/08 QA80-11861 FIX_FILE_GROUP_FAIL_USING_DEFAULT_PATH
	/*
	char szDefaultPath[MAX_PATH];	
	if( lpcszDefaultPath )
		lstrcpy(szDefaultPath, lpcszDefaultPath);
	else
		szDefaultPath[0] = 0;
	fdi.lpszPath = szDefaultPath;
	*/	
	char szDefaultPath[MAX_PATH];
	if ( lpcszDefaultPath )
	{		
		lstrcpyn(szDefaultPath, lpcszDefaultPath, MAX_PATH);
		fdi.lpszPath = szDefaultPath;
	}
	/// end FIX_FILE_GROUP_FAIL_USING_DEFAULT_PATH

	// Need write access to default file name so use local string.
	char szDefaultFileName[MAX_PATH];
	if( lpcszDefaultFilename )
		lstrcpy(szDefaultFileName, lpcszDefaultFilename);
	else
		szDefaultFileName[0] = 0;
	fdi.lpszDefaultFileName = szDefaultFileName;

	StringArray saFileNames;
	if( okoc_file_dialog(&fdi, &saFileNames) )
		return 0;

	// Return optional check box state.
	if( lpcszCheckBoxName )
	{
		if( lpnCheckBoxState )
			*lpnCheckBoxState = fdi.nCheckStatus;
		dlg_save_to_registry(strRegSec, strRegKey, fdi.nCheckStatus);
	}

	strFile = str_combine(saFileNames, "\r\n");
	return saFileNames.GetSize();

#else !USE_OC_ACCESS_TO_FDLOG
	/*
	//--- Iris 11/01/06 v8.0502d NEED_SHOW_DEFAULT_PATH_FOR_XF_IMGPLATTE
	//init_fdlog_with_group_name(lpcszGroup, NULL, NULL, strTitle);
	init_fdlog_with_group_name(lpcszGroup, lpcszDefaultPath, lpcszDefaultFilename, strTitle);
	//--- 
	
	int nType = (bMultiFiles ? FDLOG_TYPE_MULTI_OPEN : FDLOG_TYPE_OPEN_SINGLE);
	StringArray saFileNames;
	/// SY 2006-10-02 v8.0493 XF_THEME_BOOK_AND_SHEET
	///	if( GetFDLogBox(saFileNames, nType) )	
	if( GetFDLogBox(saFileNames, nType, bUseTemplate) )
	/// end XF_THEME_BOOK_AND_SHEET
	{
		int nFiles = saFileNames.GetSize();
		if( nFiles > 1 )
			//--- Iris 8/31/06
			//file_name_array_to_str(strFile, saFileNames);
			strFile = str_combine(saFileNames, "\r\n");
			//--- 
		else
			strFile = saFileNames[0];
		return nFiles;
	}
	return 0;
	*/
#endif // !USE_OC_ACCESS_TO_FDLOG /// EJP 2007-05-24 v8.0627 QA70-9796 OC_ACCESS_TO_FDLOG
}
///---END ADD_SHOW_DLG_CHECK_BOX_TO_SAVE_AS_DLG

/// EJP 2005-10-06 v8.0314 ADD_GETOPENBOX_WITH_GROUP_NAME
bool init_fdlog_with_group_name(LPCSTR lpcszFileType, LPCSTR lpcszPath,LPCSTR lpcszFileName,LPCSTR lpcszDialogName)//= NULL, NULL, NULL
{
	using FDlog = LabTalk.FDlog;
	
	///FDlog.Reset();
	FDLogInit();
	
	string strFileType = lpcszFileType;
	if( strFileType.FindOneOf("*?") == -1 )
	{
		string strGroup;
		if( strFileType.IsEmpty() )
			strGroup = "Origin";
		else
			strGroup = strFileType;
		try
		{
			FDlog.UseGroup(strGroup);
		}
		catch(int nError)
		{
			return false;
		}
	}
	else
	{
		string str;
		str.Format("[%s] %s", strFileType, strFileType);
		FDlog.AddType(str);
		if( strFileType.Compare("*.*") )
			FDlog.AddType(_L("[All Files (*.*)] *.*"));
		FDlog.DefType = 1; /// EJP 2009-04-23 DLGFILE_XF_NEED_DEFAULT_TO_CALLERS_FILE_TYPE
	}
	if( lpcszPath && *lpcszPath )
		FDlog.Path$ = lpcszPath;
	if( lpcszFileName && *lpcszFileName )
		FDlog.Default$ = lpcszFileName;
	if( lpcszDialogName && *lpcszDialogName )
		FDlog.DlgName$ = lpcszDialogName;
	return true;
}
/// end ADD_GETOPENBOX_WITH_GROUP_NAME

/**
		Open an FDLog SaveAs, Open (with or without multiple selection enabled), or
		MultiOpen dialog box using an enumerated FDLog.UseGroup code to indicate the
		set of file types to list. See sys_utils.h or the Origin.ini file for a list
		of the enumerated FDLOG.UseGroup codes.
	Example:
		See overloaded GetSaveAsBox, GetOpenBox, and GetMultiOpenBox functions in
		this source file.
	Parameters:
		saFilePaths=Output vector of strings containing path and filename of all selected files
		nFDLogUseGroup=A LabTalk FDLog.UseGroup code as enumerated in sys_utils.h and in the Origin.ini file
		fdtDialogType=Input type of dialog: FDLOG_TYPE_SAVE_AS, FDLOG_TYPE_OPEN_SINGLE, FDLOG_TYPE_OPEN_MULTISEL,
			and FDLOG_TYPE_MULTI_OPEN
		lpcszPath=Initial path when dialog opens, default NULL uses FDLog tracking
		lpcszFileName=Initial filename when dialog opens, default NULL uses an empty string 
		lpcszDialogName=Title of the dialog box, default NULL uses "Open" or "Save As" 
	Return:
		Returns the number of selected files.
*/
static int GetFileDialogBox( StringArray &saFilePaths, FDLogUseGroup nFDLogUseGroup, FDLogDialogType fdtDialogType,
	 LPCSTR lpcszPath, LPCSTR lpcszFilename, LPCSTR lpcszDialogName ) // fdtDialogType = FDLOG_TYPE_OPEN_SINGLE, lpcszPath = NULL, lpcszFilename = NULL, lpcszDialogName = NULL
{
	string strFDLogUseGroup;
	string strDefaultPath = lpcszPath;
	string strDefaultFilename = lpcszFilename;
	string strDialogName = lpcszDialogName;
	string strIniKeyName;
	double dNumGroups;
	char szTemp[ MAXFULLPATH ];

	_LT_Obj
	{
		FDLogInit();                                            // Initialize LabTalk FDLog object

		if( nFDLogUseGroup < FDLOG_FILTER_ASCII )
		{
			/// EJP 2007-12-18 v8.0773 GET_NUM_FILE_EXT_GRPS_FROM_LT_SYSTEM_OBJ, sys obj always has correct number
			///ini.file$ = "Origin.ini";                               // Look in Origin.ini file for UseGroup NumGroups and Name
			///
			///// Check that UseGroup is between 1 and ini.FileExt.NumGroups
			///LT_get_var( "ini.FileExt.NumGroups", &dNumGroups );     // Get number of currently defined UseGroups
			LT_get_var("system.fileext.numgroups", &dNumGroups);
			/// end GET_NUM_FILE_EXT_GRPS_FROM_LT_SYSTEM_OBJ
			if( nFDLogUseGroup > dNumGroups || nFDLogUseGroup < 1 ) // If UseGroup is out of bounds use blank for All Files 
				strFDLogUseGroup = "";
			else                                                    // Else get UseGroup name from Origin.ini
			{
				/// Iris 01/21/2009 QA80-12997 GETOPENBOX_GOT_RUNTIME_ERR_WHEN_WORKED_WITH_FILEDLGFOURPTYPE
				/*
				strIniKeyName.Format( "%%A=ini.FileExt.%d_Name$", nFDLogUseGroup ); // Format LabTalk command to get UseGroup name
				LT_execute( strIniKeyName );                        // Get specfied UseGroup name
				LT_get_str( "%A", szTemp, MAXFULLPATH );
				strFDLogUseGroup = szTemp;
				*/
				string strKey;
				strKey.Format("%d_Name", nFDLogUseGroup);
				
				///DSC 4/6/09 QA70-13396 STANDARDIZE_ORIGIN_INI_CASE
				//INIFile ini("origin.ini");
				INIFile ini(STR_ORIGIN_INI_FILE_NAME);
				///end STANDARDIZE_ORIGIN_INI_CASE


				strFDLogUseGroup = ini.ReadString("FileExt", strKey, "");
				///END GETOPENBOX_GOT_RUNTIME_ERR_WHEN_WORKED_WITH_FILEDLGFOURPTYPE
			}
	
			FDLog.UseGroup( strFDLogUseGroup );          // Execute FDLog.UseGroup method to set file types and path
		}
		else
		{
			switch( nFDLogUseGroup )
			{
			case FDLOG_FILTER_ASCII:
				FDLog.UseGroup("ASCII");
				FDLog.AddUserTypes(FILTER_TYPE_ASCII);
				break;
			case FDLOG_FILTER_BINARY:
				/// Hong 01/08/08 QA80-10541 USE_GROUP_TYPE_REMEMBER_LAST_OPEN_PATH
				//FDLog.NumTypes = 0;								
				//FDLog.AddUserTypes(FILTER_TYPE_BINARY);
				//FDlog.AddType(FILETYPE_ALL_FILES);
				FDLog.UseGroup("Binary");
				FDLog.AddUserTypes(FILTER_TYPE_BINARY);
				if ( strDialogName.IsEmpty() )
					strDialogName = _L("Import Multiple Binary");
				/// end USE_GROUP_TYPE_REMEMBER_LAST_OPEN_PATH
				break;
			case FDLOG_FILTER_USERDEFINED:
				/// Hong 01/08/08 QA80-10541 USE_GROUP_TYPE_REMEMBER_LAST_OPEN_PATH
				//FDLog.NumTypes = 0;
				//FDLog.AddUserTypes(FILTER_TYPE_USERDEFINED);
				//FDlog.AddType(FILETYPE_ALL_FILES);
				FDLog.UseGroup("UserDefined");
				FDLog.AddUserTypes(FILTER_TYPE_USERDEFINED);
				if ( strDialogName.IsEmpty() )
					strDialogName = _L("Import Multiple User defined");
				/// end USE_GROUP_TYPE_REMEMBER_LAST_OPEN_PATH
				break;
			}
		}

		if( !strDefaultPath.IsEmpty() )              // If path is passed as argument...
			FDLog.Path$ = strDefaultPath;            //   initialize path overwriting FDLog.UseGroup setting

		FDLog.Default$ = strDefaultFilename;         // Initialize filename

		FDLog.DlgName$ = strDialogName;              // Initialize dialog box name
		
		return GetFDLogBox(saFilePaths, fdtDialogType); // Open FDLog dialog box and get path and filename(s)
	}
}

//////////////////////////////////////////////////////////////////////////////////
/**
		An easier to use version of GetFileDialogBox that works for a single file type.
	Example:
		See overloaded GetSaveAsBox, GetOpenBox, and GetMultiOpenBox functions in
		this source file.
	Parameters:
		saFilePaths=Output vector of strings containing path and filename of all selected files
		lpcszFileType="*.ext description", or "[decription (*.ext)] *.ext", or just "*.ext"
		fdtDialogType=Input type of dialog: FDLOG_TYPE_SAVE_AS, FDLOG_TYPE_OPEN_SINGLE, FDLOG_TYPE_OPEN_MULTISEL,
			and FDLOG_TYPE_MULTI_OPEN
		lpcszPath=Initial path when dialog opens, default NULL uses FDLog tracking
		lpcszFileName=Initial filename when dialog opens, default NULL uses an empty string 
		lpcszDialogName=Title of the dialog box, default NULL uses "Open" or "Save As" 
	Return:
		Returns the number of selected files.
*/
static int GetFileDialogBox( StringArray& saFilePaths, LPCSTR lpcszFileType, FDLogDialogType fdtDialogType,
	 LPCSTR lpcszPath, LPCSTR lpcszFilename, LPCSTR lpcszDialogName) // lpcszFileType = NULL, fdtDialogType = FDLOG_TYPE_OPEN_SINGLE, lpcszPath = NULL, lpcszFileName = NULL, lpcszDialogName = NULL
{
	string strFileType;
	if( lpcszFileType )
		strFileType = lpcszFileType;
	else
		strFileType = "*.* All Files";

	string strFileTypeText;
	
	strFileType.TrimLeft();			  // In case there are blanks to ensure proper testing of 1st char
	if(strFileType[0] == '[')
		strFileTypeText = strFileType;// User specified in correct LabTalk syntax, we will use as is
	else
	{
		// We will construct the proper syntax here
		if(strFileType[0] != '*' || strFileType[1] != '.')
			return "";	              // Bad format, return empty string
		
		int nFileTypeTextSeparator = strFileType.Find(' ');
		if(nFileTypeTextSeparator > 0) // There is explanation text after ext
		{
			string strText = strFileType;
			strFileType = strText.Left(nFileTypeTextSeparator);
			strText = strText.Mid(nFileTypeTextSeparator+1);
			strFileTypeText = "[" + strText + " (" + strFileType + ")] " + strFileType;
		}
		else
			strFileTypeText = "[" + strFileType + " (" + strFileType + ")] " + strFileType;
	}
		
	StringArray saFiletypes;
	saFiletypes.SetSize( 1 );
	saFiletypes[0]=strFileTypeText; // "[Project (*.OPJ)] *.OPJ";
	
	return GetFileDialogBox( saFilePaths, saFiletypes, fdtDialogType, lpcszPath, lpcszFilename, lpcszDialogName );
}

//////////////////////////////////////////////////////////////////////////////////
/**
		Open an FDLog Browse (OpenPath) dialog box.
	Example:
		string strPath;
		strPath = BrowseGetPath();                                      // or
		strPath = BrowseGetPath( "C:\\Program Files\\" );               // or
		strPath = BrowseGetPath( GetAppPath() + "OriginC\\", "Browse" );
	Parameters:
		lpcszPath=Initial path when dialog opens, default NULL uses FDLog tracking  
		lpcszDialogName=Title of the dialog box, default NULL uses "Open" 
	Return:
		Returns the path browsed to or an empty string if Cancel button in dialog
		box is clicked.
*/
string BrowseGetPath( LPCSTR lpcszPath, LPCSTR lpcszDialogName ) // lpcszPath = NULL, lpcszDialogName = NULL
{
	double dErr;
	char szTemp[ MAXFULLPATH ];
	string strDefaultPath = lpcszPath;
	string strDialogName = lpcszDialogName;
	string strReturnPath;

	_LT_Obj
	{
		if( strDefaultPath.IsEmpty() )               // If path is not passed as argument...
			strDefaultPath = FDLog.Path$;            //   get last used path from FDLog object for tracking

		FDLogInit();                                 // Initialize LabTalk FDLog object

		if( !strDefaultPath.IsEmpty() )              // If path is passed as argument...
		{
			FDLog.Path$ = strDefaultPath;            //   initialize path
			FDLog.Default$ = strDefaultPath;         //   initialize filename which is same as path for this DB
		}
		FDLog.DlgName$ = strDialogName;              // Initialize dialog box name

		dErr = FDLog.OpenPath( "A" );   // Open browse dialog box and put result into %A Labtalk string
		
		if( dErr )                      // If Cancel button is clicked...
			strReturnPath.Empty();      //   return empty string
		else                            // Else OK is clicked...
		{
			LT_get_str( "%A", szTemp, MAXFULLPATH );//   get path browsed to from %A LabTalk variable
			strReturnPath = szTemp;                 //   return path browsed to
		}
	}

	return strReturnPath;
}

//////////////////////////////////////////////////////////////////////////////////
/**
		Open an FDLog Open dialog box passing the file types to list in an array
		of strings.
	Example:
		string strPath;
		StringArray saFiletypes;
		saFiletypes.SetSize( 3 );
		saFiletypes[0]="[Project (*.OPJ)] *.OPJ";
		saFiletypes[1]="[Old version (*.ORG)] *.ORG";
		saFiletypes[2]="[Worksheets (*.OGW)] *.OGW";
		strPath = GetOpenBox( saFiletypes ); // or
		//strPath = GetOpenBox( saFiletypes, "C:\\Program Files\\" ); // or
		//strPath = GetOpenBox( saFiletypes, "C:\\Program Files\\", "Origin" ); // or
		//strPath = GetOpenBox( saFiletypes, "C:\\Program Files\\", "Origin", "OpenOPJ" );
		if( strPath.IsEmpty() )
			out_str( "User has cancelled the Open dialog box." );
		else
			printf( "The file chosen is %s\n.", strPath );
	Parameters:
		saFiletypes=Vector containing file types to list in the dialog box, each element
			of vector must follow syntax of LabTalk FDLog.TypeN$ object property
		lpcszPath=Initial path when dialog opens, default NULL uses FDLog tracking
		lpcszFileName=Initial filename when dialog opens, default NULL uses an empty string 
		lpcszDialogName=Title of the dialog box, default NULL uses "Open" 
	Return:
		Returns the path and filename of a selecetd file or an empty string if Cancel button
		in dialog box is clicked.
*/
string GetOpenBox( StringArray &saFiletypes, LPCSTR lpcszPath, LPCSTR lpcszFilename,
	 LPCSTR lpcszDialogName ) // lpcszPath = NULL, lpcszFilename = NULL, lpcszDialogName = NULL
{
	//------------------- GJL v7.0357 QA70-4078 3/17/03 ORIGINC_MULTI_OPEN_SUPPORT
	StringArray saFilePaths;
	GetFileDialogBox( saFilePaths, saFiletypes, FDLOG_TYPE_OPEN_SINGLE, lpcszPath, lpcszFilename, lpcszDialogName );
	return saFilePaths[0];
	//return GetFileDialogBox( saFiletypes, FALSE, lpcszPath, lpcszFilename, lpcszDialogName );
	//------------------- QA70-4078
}

/**
		An FDLog.UseGroup version of GetOpenBox that uses an enumerated FDLog.UseGroup
		code to indicate the set of file types to list. See sys_utils.h or the Origin.ini
		file for a list of the enumerated FDLOG.UseGroup codes.
	Example:
		string strPath;
		strPath = GetOpenBox( FDLOG_ORIGIN ); // or
		//strPath = GetOpenBox( FDLOG_EXCEL, "C:\\Program Files\\" ); // or
		//strPath = GetOpenBox( FDLOG_ASCII, "C:\\Program Files\\", "Origin" ); // or
		//strPath = GetOpenBox( FDLOG_SCRIPT, "C:\\Program Files\\", "Origin", "OpenOGS" );
		if( strPath.IsEmpty() )
			out_str( "User has cancelled the Open dialog box." );
		else
			printf( "The file chosen is %s\n.", strPath );
	Parameters:
		nFDLogUseGroup=A LabTalk FDLog.UseGroup code as enumerated in sys_utils.h and in
			the Origin.ini file
		lpcszPath=Initial path when dialog opens, default NULL uses FDLog tracking
		lpcszFileName=Initial filename when dialog opens, default NULL uses an empty string
		lpcszDialogName=Title of the dialog box, default NULL uses "Open"
	Return:
		Returns the path and filename of a selected file or an empty string if Cancel button
		in dialog box is clicked.
*/
string GetOpenBox( FDLogUseGroup nFDLogUseGroup, LPCSTR lpcszPath, LPCSTR lpcszFilename,
	 LPCSTR lpcszDialogName ) // lpcszPath = NULL, lpcszFilename = NULL, lpcszDialogName = NULL
{
	//------------------- GJL v7.0357 QA70-4078 3/17/03 ORIGINC_MULTI_OPEN_SUPPORT
	StringArray saFilePaths;
	GetFileDialogBox( saFilePaths, nFDLogUseGroup, FDLOG_TYPE_OPEN_SINGLE, lpcszPath, lpcszFilename, lpcszDialogName );
	return saFilePaths[0];
	//return GetFileDialogBox( nFDLogUseGroup, FALSE, lpcszPath, lpcszFilename, lpcszDialogName );
	//------------------- QA70-4078

}
//CPY 11/17/05 DLGSAVE_XF, I remove below and expose the tow lower level function so we have more control from XF, dlgFile and dlgSave
/*
/// EJP 2005-10-06 v8.0314 ADD_GETOPENBOX_WITH_GROUP_NAME
 >User Interface
		Display a file open dialog after initializing it with settings from a specified
		File Extension Group.
	Parameters:
		strFileName = [output]The string to receive the selected file name.
		lpcszFileExtGroupName = [input]Pointer to the File Extension Group name.
		lpcszPath = [input]Initial path when dialog opens, default NULL uses FDLog tracking
		lpcszFileName = [input]Initial filename when dialog opens, default NULL uses an empty string
		lpcszDialogName = [input]Title of the dialog box, default NULL uses "Open"
	Return:
		Returns TRUE if the user selected a file, FALSE if user canceled.

BOOL GetOpenBox(
	string& strFileName,
	LPCSTR lpcszFileExtGroupName,
	LPCSTR lpcszPath = NULL,
	LPCSTR lpcszFileName = NULL,
	LPCSTR lpcszDialogName = NULL);

BOOL GetOpenBox(
	string& strFileName,
	LPCSTR lpcszFileExtGroupName,
	LPCSTR lpcszPath,
	LPCSTR lpcszFileName,
	LPCSTR lpcszDialogName)
{
	_init_fdlog_with_group_name(lpcszFileExtGroupName, lpcszPath, lpcszFileName, lpcszDialogName);

	StringArray saFileNames;
	if( GetFDLogBox(saFileNames, FDLOG_TYPE_OPEN_SINGLE) )
	{
		strFileName = saFileNames[0];
		return TRUE;
	}
	return FALSE;
}
/// end ADD_GETOPENBOX_WITH_GROUP_NAME
*/
//////////////////////////////////////////////////////////////////////////////////
/**
		An easier to use version of GetOpenBox that works for a single file type.
	Example:
		string strPath;
		strPath = GetOpenBox(); // or
		//strPath = GetOpenBox( "[Old version (*.ORG)] *.ORG" ); // or
		//strPath = GetOpenBox( "*.OPJ"); // or
		//strPath = GetOpenBox( "*.ocw Workspace", GetAppPath() + "OriginC\\" ); // or
		//strPath = GetOpenBox( "*.ocw Workspace", GetAppPath() + "OriginC\\", "Origin" ); // or
		//strPath = GetOpenBox( "*.ocw Workspace", "C:\\Program Files\\", "Origin", "Open Workspace" );
		if( strPath.IsEmpty() )
			out_str( "User has cancelled the Open dialog box." );
		else
			printf( "The file chosen is %s\n.", strPath );
	Parameters:
		lpcszFileType="*.ext description", or "[decription (*.ext)] *.ext", or just "*.ext"
		lpcszPath=Initial path when dialog opens, default NULL uses FDLog tracking
		lpcszFileName=Initial filename when dialog opens, default NULL uses an empty string
		lpcszDialogName=Title of the dialog box, default NULL uses "Open"
	Return:
		Returns the path and filename of a selecetd file or an empty string if Cancel button
		in dialog box is clicked.
*/
string GetOpenBox( LPCSTR lpcszFileType, LPCSTR lpcszPath, LPCSTR lpcszFilename,
	 LPCSTR lpcszDialogName ) // lpcszFileType = "*.* All Files", lpcszPath = NULL, lpcszFileName = NULL, lpcszDialogName = NULL
{
	//------------------- GJL v7.0357 QA70-4078 3/17/03 ORIGINC_MULTI_OPEN_SUPPORT
	StringArray saFilePaths;
	GetFileDialogBox( saFilePaths, lpcszFileType, FDLOG_TYPE_OPEN_SINGLE, lpcszPath, lpcszFilename, lpcszDialogName );
	return saFilePaths[0];
	//return GetFileDialogBox( lpcszFileType, FALSE, lpcszPath, lpcszFilename, lpcszDialogName );
	//------------------- QA70-4078
}

//////////////////////////////////////////////////////////////////////////////////
/**
		Open an FDLog SaveAs dialog box passing the file types to list in an array
		of strings.
	Example:
		string strPath;
		StringArray saFiletypes;
		saFiletypes.SetSize( 3 );
		saFiletypes[0]="[Project (*.OPJ)] *.OPJ";
		saFiletypes[1]="[Old version (*.ORG)] *.ORG";
		saFiletypes[2]="[Worksheets (*.OGW)] *.OGW";
		strPath = GetSaveAsBox( saFiletypes ); // or
		//strPath = GetSaveAsBox( saFiletypes, "C:\\Program Files\\" ); // or
		//strPath = GetSaveAsBox( saFiletypes, "C:\\Program Files\\", "Origin" ); // or
		//strPath = GetSaveAsBox( saFiletypes, "C:\\Program Files\\", "Origin", "SaveAsOPJ" );
		if( strPath.IsEmpty() )
			out_str( "User has cancelled the SaveAs dialog box." );
		else
			printf( "The file chosen is %s\n.", strPath );
	Parameters:
		saFiletypes=Vector containing file types to list in the dialog box, each element
			of vector must follow syntax of LabTalk FDLog.TypeN$ object property
		lpcszPath=Initial path when dialog opens, default NULL uses FDLog tracking
		lpcszFileName=Initial filename when dialog opens, default NULL uses an empty string 
		lpcszDialogName=Title of the dialog box, default NULL uses "SaveAs" 
	Return:
		Returns the path and filename of a selecetd file or an empty string if Cancel button
		in dialog box is clicked.
*/
string GetSaveAsBox( StringArray &saFiletypes, LPCSTR lpcszPath, LPCSTR lpcszFilename,
	 LPCSTR lpcszDialogName ) // lpcszPath = NULL, lpcszFilename = NULL, lpcszDialogName = NULL
{
	//------------------- GJL v7.0357 QA70-4078 3/17/03 ORIGINC_MULTI_OPEN_SUPPORT
	StringArray saFilePaths;
	GetFileDialogBox( saFilePaths, saFiletypes, FDLOG_TYPE_SAVE_AS, lpcszPath, lpcszFilename, lpcszDialogName );
	return saFilePaths[0];
	//return GetFileDialogBox( saFiletypes, TRUE, lpcszPath, lpcszFilename, lpcszDialogName );
	//------------------- QA70-4078
}

/**
		An FDLog.UseGroup version of GetSaveAsBox that uses an enumerated FDLog.UseGroup
		code to indicate the set of file types to list. See sys_utils.h or the Origin.ini
		file for a list of the enumerated FDLOG.UseGroup codes.
	Example:
		string strPath;
		strPath = GetSaveAsBox( FDLOG_ORIGIN ); // or
		//strPath = GetSaveAsBox( FDLOG_EXCEL, "C:\\Program Files\\" ); // or
		//strPath = GetSaveAsBox( FDLOG_ASCII, "C:\\Program Files\\", "Origin" ); // or
		//strPath = GetSaveAsBox( FDLOG_SCRIPT, "C:\\Program Files\\", "Origin", "SaveAsOGS" );
		if( strPath.IsEmpty() )
			out_str( "User has cancelled the SaveAs dialog box." );
		else
			printf( "The file chosen is %s\n.", strPath );
	Parameters:
		nFDLogUseGroup=A LabTalk FDLog.UseGroup code as enumerated in sys_utils.h and in
			the Origin.ini file
		lpcszPath=Initial path when dialog opens, default NULL uses FDLog tracking
		lpcszFileName=Initial filename when dialog opens, default NULL uses an empty string
		lpcszDialogName=Title of the dialog box, default NULL uses "SaveAs"
	Return:
		Returns the path and filename of a selected file or an empty string if Cancel button
		in dialog box is clicked.
*/
string GetSaveAsBox( FDLogUseGroup nFDLogUseGroup, LPCSTR lpcszPath, LPCSTR lpcszFilename,
	 LPCSTR lpcszDialogName ) // lpcszPath = NULL, lpcszFilename = NULL, lpcszDialogName = NULL
{
	//------------------- GJL v7.0357 QA70-4078 3/17/03 ORIGINC_MULTI_OPEN_SUPPORT
	StringArray saFilePaths;	
	GetFileDialogBox( saFilePaths, nFDLogUseGroup, FDLOG_TYPE_SAVE_AS, lpcszPath, lpcszFilename, lpcszDialogName );
	return saFilePaths[0];
	//return GetFileDialogBox( nFDLogUseGroup, TRUE, lpcszPath, lpcszFilename, lpcszDialogName );
	//------------------- QA70-4078
}

//////////////////////////////////////////////////////////////////////////////////
/**
		An easier to use version of GetSaveAsBox that works for a single file type.
	Example:
		string strPath;
		strPath = GetSaveAsBox(); // or
		//strPath = GetSaveAsBox( "[Old version (*.ORG)] *.ORG" ); // or
		//strPath = GetSaveAsBox( "*.OPJ"); // or
		//strPath = GetSaveAsBox( "*.ocw Workspace", GetAppPath() + "OriginC\\" ); // or
		//strPath = GetSaveAsBox( "*.ocw Workspace", GetAppPath() + "OriginC\\", "Origin" ); // or
		//strPath = GetSaveAsBox( "*.ocw Workspace", "C:\\Program Files\\", "Origin", "SaveAs Workspace" );
		if( strPath.IsEmpty() )
			out_str( "User has cancelled the SaveAs dialog box." );
		else
			printf( "The file chosen is %s\n.", strPath );
	Parameters:
		lpcszFileType="*.ext description", or "[decription (*.ext)] *.ext", or just "*.ext"
		lpcszPath=Initial path when dialog opens, default NULL uses FDLog tracking
		lpcszFileName=Initial filename when dialog opens, default NULL uses an empty string
		lpcszDialogName=Title of the dialog box, default NULL uses "SaveAs"
	Return:
		Returns the path and filename of a selecetd file or an empty string if Cancel button
		in dialog box is clicked.
*/
string GetSaveAsBox( LPCSTR lpcszFileType, LPCSTR lpcszPath, LPCSTR lpcszFilename,
	 LPCSTR lpcszDialogName ) // lpcszFileType = "*.* All Files", lpcszPath = NULL, lpcszFileName = NULL, lpcszDialogName = NULL
{
	//------------------- GJL v7.0357 QA70-4078 3/17/03 ORIGINC_MULTI_OPEN_SUPPORT
	StringArray saFilePaths;	
	GetFileDialogBox( saFilePaths, lpcszFileType, FDLOG_TYPE_SAVE_AS, lpcszPath, lpcszFilename, lpcszDialogName );
	return saFilePaths[0];
	//return GetFileDialogBox( lpcszFileType, TRUE, lpcszPath, lpcszFilename, lpcszDialogName );
	//------------------- QA70-4078
}

/////////////////////////////////////////////////////////////////
// These functions make it easy to put complex expression together
/////////////////////////////////////////////////////////////////
//---- CPY 2/3/03 we have decided to change to use Macros so that Re(aa)=1 can be used
//
//double Re(complex cc)
//{
//	return cc.m_re;
//}
//double Im(complex cc)
//{
//	return cc.m_im;
//}
//----
complex Conj(complex cc)
{
	return cc.Conjugate();
}

/** >Character/String Manipulation
		Converts string to a complex. If the input cannot be converted to a value of complex. The return value is undefined.
		The function stops reading the input string at the first character that it cannot recognize as part of a number. 
		This character may be the null character ('\0') terminating the string.
	Parameter:
		lpcsz = the string to convert.
	Return:
		a complex
	Example:
		void	run_atof()
		{
			char	szString[] = " -4.05 - 3.007i";
			complex	c = atof(szString);
			out_complex("value = ", c);
		}
*/
#define IS_INTRODUCTORY_LETTER(_cc) ( (_cc) == 'e' || (_cc) == 'E' || (_cc) == 'd' || (_cc) == 'D' )
#define IS_PLUS_OR_MINUS(_cc) ( (_cc) == '-' || (_cc) == '+' )

complex atoc(LPCSTR lpcsz)
{
	complex c;

	string str(lpcsz);
	str.TrimRight();
	str.TrimLeft();
	
	int nLength = str.GetLength();
	if( nLength <= 0 )
		return c;
	
	LPSTR lpstr = str.GetBuffer(nLength + 1);
	LPSTR lpc = lpstr + nLength - 1;
	
	if( 'i' == *lpc )
	{
		*lpc = '\0';
		
		// Find operator '+' or '-'
		while( lpc > lpstr )
		{
			// if not an exponent sign
			if( IS_PLUS_OR_MINUS(*lpc) && !IS_INTRODUCTORY_LETTER(*(lpc - 1)) )
				break; // we found the operator
			lpc--;
		}
		
		// Get the imaginary part
		LPSTR lpIm;
		if( lpc == lpstr )
			lpIm = lpc;
		else
			lpIm = (lpc + 1);
		
		string strIm(lpIm);
		strIm.TrimRight();
		strIm.TrimLeft();
		
		if( IS_PLUS_OR_MINUS(*lpc) )
			strIm.Insert(0, *lpc);

		if( (c.m_im = atof(strIm)) == 0.0 )
			c.m_im = 1; // If only 'i' in the imaginary part

		*lpc = '\0';
	}
	
	// Get the real part
	str.TrimRight();	///Kevin 11/15/05 FIX_ATOF_FAIL_TO_CONVERT_WHEN_STRING_HAVE_BLANK
	///Sophy 10/28/2009 FAIL_TO_CONVERT_STRING_WITH_IMAGINARY_PART_ONLY_TO_COMPLEX
	//c.m_re = atof(lpstr)
	if ( lpc == lpstr )
		c.m_re = 0;
	else
		c.m_re = atof(lpstr);
	///end FAIL_TO_CONVERT_STRING_WITH_IMAGINARY_PART_ONLY_TO_COMPLEX;
	str.ReleaseBuffer(nLength);
	
	return c;
}

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

// this function is added because LabTalk has both rnd and ran, so we allow
// the same in Origin C
double ran(int nSeed)
{
	return rnd(nSeed);
}

//////////////////////////////////////////////////////////////////////////////////
/** >System
		Get the text data copied onto the clipboard.
	Example:
		string strClipboardText;
		BOOL bSuccess;
		bSuccess = GetClipboardText( strClipboardText );
		if( bSuccess )
			out_str( strClipboardText );
		else
			out_str( "Error reading Clipboard or Clipboard is empty." );
	Parameters:
		strData = Output text copied from clipboard
	Return:
		Returns TRUE and a string containing text copied onto the clipboard
		on success or returns FALSE and an empty string on failure or if
		the Clipboard is empty.
*/
BOOL GetClipboardText( string& strData )
{
	BOOL bRet = FALSE;                                        // Declare and intitialize variables                                             
	strData = "";
	
	if( OpenClipboard(NULL) )                                 // If the clipboard opens successflly...
	{
		if( IsClipboardFormatAvailable( CF_TEXT ) )           // If the clipboard contains text data...
		{
			HANDLE hData = GetClipboardData( CF_TEXT );       // Get text data from clipboard
			if( hData )                                       // If handle to clipboard good...
			{
				LPCSTR lpData = (LPCSTR) GlobalLock( hData ); // Lock clipboard
				if( lpData )                                  // If lock successful...
				{
					strData = lpData;                         // Put clipboard data in string
					bRet = TRUE;                              // Tell user about success!
					GlobalUnlock( hData );                    // Unlock clipboard
				}
			}
		}
		CloseClipboard();                                     // Close the clipboard
	}

	return bRet;                                              // Return, strData contains clipboard text
}


//construct a temporary file name in the Windows Temp path
BOOL GetTempFileName(string &strFile, LPCSTR lpcszPrefix)// = NULL)
{
	char sz[MAXFULLPATH];
	/// SY 09-12-2003 QA70-5158 v7.0694 OC_NEED_ROBUST_GET_TEMP_PATH_FUNCTION
	///	DWORD dw = GetTempPath(MAXFULLPATH, sz);
	///	if( dw )
	DWORD dw = get_temp_path(sz, MAXFULLPATH);
	if( 2 != dw )
	/// end OC_NEED_ROBUST_GET_TEMP_PATH_FUNCTION
	{
		strFile = sz;
		string strSignature = lpcszPrefix==NULL? "OTF" : lpcszPrefix;
		
		dw = GetTempFileName(strFile, strSignature, 0, sz);
		if( dw )
		{
			strFile = sz;
			return TRUE;
		}
	}
	return FALSE;
}

/// EJP 2008-01-23 v8.0792 QA70-10839 OC_CHECK_FOR_UPDATES
/**
		Get the file modification date of a file from an input string containing
		a path and filename.
	Parameters:
		lpcstrPathAndFilename=Input string containing a path and filename with filetype extension
		sysTime=Output reference to a SYSTEMTIME structure
	Return:
		Returns TRUE for success else FALSE for error
*/
BOOL GetFileModificationDate(LPCSTR lpcstrPathAndFilename, SYSTEMTIME& sysTime)
{
	WIN32_FILE_ATTRIBUTE_DATA fileInfo;
	if( GetFileAttributesEx(lpcstrPathAndFilename, 0, &fileInfo) )
	{
		FILETIME localFileTime;
		if( FileTimeToLocalFileTime(&fileInfo.ftLastWriteTime, &localFileTime) )
		{
			return FileTimeToSystemTime(&localFileTime, &sysTime);
		}
	}
	return FALSE;
}
/// end OC_CHECK_FOR_UPDATES

/**
		Get the file modification date of a file from an input string containing
		a path and filename.
	Example:
		string strFileDate, strDataFile = "C:\\Origin80\\Origin.ini";
		strFileDate = auGetFileSize(strDataFile);
	Parameters:
		lpcstrPathAndFilename=Input string containing a path and filename with filetype extension
	Return:
		Returns a Windows like file modification date formatted for display. 
*/
string GetFileModificationDate(LPCSTR lpcstrPathAndFilename, WORD wFormat)
{
	string strFileModDate;

	/// EJP 2008-01-23 v8.0792 QA70-10839 OC_CHECK_FOR_UPDATES, move to function to allow sharing
	/*
	WIN32_FILE_ATTRIBUTE_DATA fileInfo;
	if( GetFileAttributesEx(lpcstrPathAndFilename, 0, &fileInfo) )
	{
		FILETIME localFileTime;
		if( FileTimeToLocalFileTime(&fileInfo.ftLastWriteTime, &localFileTime) )
		{
			SYSTEMTIME sysTime;
			if( FileTimeToSystemTime(&localFileTime, &sysTime) )
			{
	*/
	SYSTEMTIME sysTime;
	if( GetFileModificationDate(lpcstrPathAndFilename, sysTime) )
	{
	/// end OC_CHECK_FOR_UPDATES
				LPSTR lpstr = strFileModDate.GetBuffer(MAXFULLPATH);
				if( lpstr )
				{
					systemtime_to_date_str(&sysTime, lpstr, wFormat);
					strFileModDate.ReleaseBuffer();
				}
	/// EJP 2008-01-23 v8.0792 QA70-10839 OC_CHECK_FOR_UPDATES
	///		}
	///	}
	/// end OC_CHECK_FOR_UPDATES
	}

	return strFileModDate;
}


/*
	List all files of a specified file type or form found in a folder

Example1: just path supplied and (optional) extension
	string strExePath = GetAppPath();
	StringArray saResult;
	FindFiles(saResult, strExePath, "otw");
	
Example2: 
	string strPath = "c:\Origin\Subfolder\"
	string lpcszFileOrExt = "a*c*e.ext"; 
	StringArray saResult;
	FindFiles(saResult, strPath, lpcszFileOrExt);
	
Parameters:
	saResult = [out] the referrence of string array will receive the finding results
	lpcszPath = [in] the path to search for files with specified extension.
	lpcszFileOrExt = [in] the extension, or file name with wild characters and extension, or NULL to search all files in a folder lpcszPath without wildcards.
	bCheckExist = [in] true will check the given saReult to see if the file is already in that array
Return:
	Returns TRUE for success, otherwise failure.
*/	
BOOL FindFiles(StringArray& saResult, LPCSTR lpcszPath, LPCSTR lpcszFileOrExt, bool bCheckExist)// = false);
{	
	///DSC 6/30/05 MOVE_GET_CLASS_SETTINGS_TO_VC
	/*
	WIN32_FIND_DATAA FileData;
	string strFilePath = lpcszPath;
	string strFileExt = lpcszExt;
	
	///DSC 2/25/04 ALLOW_WILDCARD_IN_FIND_FILES	
	// if no "*" found, add strFileExt, else ignor lpcszExt
	if(strFilePath.Find("*")<0) //no * found, 
	{
	///end  ALLOW_WILDCARD_IN_FIND_FILES
	
		if(strFileExt.IsEmpty())
				strFileExt = "*.*";
		else
		{
			if(strFileExt[0] != '*')
			{
				if(strFileExt[0] == '.')
					strFileExt = "*" + strFileExt;
				else	
					strFileExt = "*." + strFileExt;
			}
		}
		
		strFilePath += strFileExt;
	}
			
	///DSC 2/25/04 ALLOW_WILDCARD_IN_FIND_FILES	
	// HANDLE hFind = FindFirstFile( strFilePath + strFileExt, &FileData);
	HANDLE hFind = FindFirstFile( strFilePath, &FileData);
	///end ALLOW_WILDCARD_IN_FIND_FILES

	if(INVALID_HANDLE_VALUE != hFind)
	{
		saResult.Add(FileData.cFileName); // the first file name found
		
		int ii; 
		// start the loop
		while(FindNextFile(hFind, &FileData)) 
		{ 
			bool bExist = false; // may need to determin the string existed in the array or not
			if(bCheckExist)
			{
				for(ii = 0; ii < saResult.GetSize(); ii++)
				{				
					if( 0 == saResult[ii].CompareNoCase(FileData.cFileName))
						bExist = true;
				}
			}
	
			if(!bExist)
				saResult.Add(FileData.cFileName);
		}

		FindClose(hFind);	
		return TRUE;
	}
	return FALSE;
	*/
	return okutil_find_files_from_name_or_ext(&saResult, lpcszPath, lpcszFileOrExt, bCheckExist);
	///end MOVE_GET_CLASS_SETTINGS_TO_VC
}

BOOL SetFileToCurrentTime(LPCSTR lpcszFilename)
{
	BOOL bRet = FALSE;
	HANDLE hFile = CreateFile(lpcszFilename, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hFile != INVALID_HANDLE_VALUE)
	{
		FILETIME ft;
		SYSTEMTIME st;
		GetSystemTime(&st);              // gets current time
		SystemTimeToFileTime(&st, &ft);  // converts to file time format
		bRet = SetFileTime(hFile,NULL, NULL, &ft);
		CloseHandle(hFile);
	}
	return bRet;
}

void get_current_time(SYSTEMTIME& systime, bool bConvertToLocalTime)
{
	GetSystemTime(&systime);  		// gets current time, 
	if(bConvertToLocalTime)
	{
		// need to convert to local time
		FILETIME ft, ftLocal;
		SystemTimeToFileTime(&systime, &ft);
		FileTimeToLocalFileTime(&ft, &ftLocal);
		FileTimeToSystemTime(&ftLocal, &systime);
	}
}


/** >File Management
	Copy file and also set destination file's attribute
Example:
Parameters:
	lpcszSrc = [in] Pointer to a null-terminated string that specifies the name of an existing file. 
	lpcszDest =	[in] Pointer to a null-terminated string that specifies the name of the new file. 
	dwAttribute = the file attribute to set on the new file lpcszDest
	bSetCurrentTime = set the destination file to the current time or not
Return:
	Returns TRUE for success, otherwise failure.
Remark:
	This function will call CopyFile with default bFailIfExists = FALSE
*/
BOOL FileCopy(LPCSTR lpcszSrc, LPCSTR lpcszDest, DWORD dwAttribute, bool bSetCurrentTime)// = FILE_ATTRIBUTE_NORMAL, true);
{
	if(CopyFile(lpcszSrc, lpcszDest))
	{
		SetFileAttributes(lpcszDest, dwAttribute);
		if(bSetCurrentTime)
		{
			SetFileToCurrentTime(lpcszDest);
		}
		return TRUE;
	}
	return FALSE;
}

// export a page to an image using settings from a tree node
bool export_page(Page &pg, LPCSTR lpcszFileName, const TreeNode &trExport)
{
	// get image format
	string str = trExport.tagName;
	
	// backup ini settings
	Tree trIniSettings;
	tree_read_image_export_settings(trIniSettings, str);

	// write tree settings to ini
	tree_write_image_export_settings(trExport, str);
	
	// export page to image
	bool bRet = export_page_to_image(pg, lpcszFileName, str, false);
	
	// restore ini settings
	tree_write_image_export_settings(trIniSettings, str, true);

	return bRet;
}

// export a page to an image using the page's export settings
bool export_page(Page &pg, LPCSTR lpcszFileName, LPCSTR lpcszFormat)
{
	Tree trIniSettings;
	bool bPageSettings = false;

	// get page settings
	Tree trPageSettings;
	if( tree_get_page_image_export_settings(trPageSettings, pg, lpcszFormat) )
	{
		bPageSettings = true;

		// backup ini settings
		tree_read_image_export_settings(trIniSettings, lpcszFormat);

		// write page settings to ini
		tree_write_image_export_settings(trPageSettings, lpcszFormat);
	}
	
	// export page to image
	bool bRet = export_page_to_image(pg, lpcszFileName, lpcszFormat, false);

	if( bPageSettings )
	{
		// restore ini settings
		tree_write_image_export_settings(trIniSettings, lpcszFormat, true);
	}
	
	return bRet;
}

/// EJP 04-14-2004 v7.5857 QA70-5587 FAIL_TO_EXPORT_1200DPI_BITMAP
#define EPTI_LT_VAR "imgexp"
static int get_export_page_to_image_error(int* pnErr)
{
	double dErr;
	if( pnErr )
	{
		if( LT_get_var(EPTI_LT_VAR, &dErr) )
			*pnErr = (int)dErr;
		else
			return 1; // failed to get export error number
	}
	return 0; // success
}
/// end FAIL_TO_EXPORT_1200DPI_BITMAP

// export a page to an image using current ini settings or prompt user with export options
bool export_page_to_image(Page &pg, LPCSTR lpcszFileName, LPCSTR lpcszFormat, BOOL bShowOptions)
{
	if( EXIST_PLOT != pg.GetType() && EXIST_LAYOUT != pg.GetType() )
		return false; // invalid page type
	string str;
	str.Format("Image.ShowOptions=%d;Image.FileName$=%s;", bShowOptions, lpcszFileName);
	pg.LT_execute(str);

	// LabTalk's Image.Export.PageDPI arguments:
	// 1  File format extension (str)
	// 2  dots per inch (int)
	// 3  bits per pixel (int)
	// 4  compression (int)
	/// EJP 04-14-2004 v7.5857 QA70-5587 FAIL_TO_EXPORT_1200DPI_BITMAP
	///	/// EJP 11-20-2003 v7.5764 QA70-5587 FAIL_TO_EXPORT_1200DPI_BITMAP
	///	///str.Format("Image.Export.PageDPI(%s);", lpcszFormat);
	///	str.Format("imgexp = Image.Export.PageDPI(%s);", lpcszFormat);
	///	/// end FAIL_TO_EXPORT_1200DPI_BITMAP
	str.Format(EPTI_LT_VAR"=Image.Export.PageDPI(%s);", lpcszFormat);
	/// end FAIL_TO_EXPORT_1200DPI_BITMAP
	if( !pg.LT_execute(str) )
		return false;

	return true;
}

// export a page to an image using the specified settings
//---- Iris 12/04/06 FIX_GRAY_SCALE_FAIL_TO_WORK
//bool export_page_to_image(LPCSTR lpcszFileName, LPCSTR lpcszFormat, Page &pg, int nWidth, int nHeight, int nBitsPerPixel, int nCompression)
bool export_page_to_image(LPCSTR lpcszFileName, LPCSTR lpcszFormat, Page &pg, int nWidth, int nHeight, int nBitsPerPixel, int nCompression, bool bGrayScale)
//----
{
	if( EXIST_PLOT != pg.GetType() && EXIST_LAYOUT != pg.GetType() )
		return false; // invalid page type
	
	string str;
	str.Format("Image.ShowOptions=0;Image.FileName$=%s;", lpcszFileName);
	if( !pg.LT_execute(str) )
		return false;
	
	/// EJP 04-14-2004 v7.5857 QA70-5587 FAIL_TO_EXPORT_1200DPI_BITMAP
	///	if( 0 == nHeight ) // height not specified, use width as DPI
	///		str.Format("Image.Export.PageDPI(%s, %d, %d, %d);", lpcszFormat, nWidth, nBitsPerPixel, nCompression);	
	///	else
	///		str.Format("Image.Export.PagePixel(%s, %d, %d, %d, %d);", lpcszFormat, nWidth, nHeight, nBitsPerPixel, nCompression);	
	if( 0 == nHeight ) // height not specified, use width as DPI
		str.Format(EPTI_LT_VAR"=Image.Export.PageDPI(%s, %d, %d, %d);", lpcszFormat, nWidth, nBitsPerPixel, nCompression);	
	else
		/// Iris 12/04/06 FIX_GRAY_SCALE_FAIL_TO_WORK
		//str.Format(EPTI_LT_VAR"=Image.Export.PagePixel(%s, %d, %d, %d, %d);", lpcszFormat, nWidth, nHeight, nBitsPerPixel, nCompression);	
		str.Format(EPTI_LT_VAR"=Image.Export.PagePixel(%s, %d, %d, %d, %d, %d);", lpcszFormat, nWidth, nHeight, nBitsPerPixel, nCompression, bGrayScale);	
		///end FIX_GRAY_SCALE_FAIL_TO_WORK
		
	/// end FAIL_TO_EXPORT_1200DPI_BITMAP
	return pg.LT_execute(str) ? true : false;
}

//------------------- GJL v7.0357 QA70-4078 3/17/03 ORIGINC_MULTI_OPEN_SUPPORT
//////////////////////////////////////////////////////////////////////////////////
/**
		Open an FDLog Open dialog box passing the file types to list in an array
		of strings. Optionally uses a simple Open dialog with multiple selection
		enabled or a Multi-Open dialog box.
	Example:
		int iNumSelFiles;
		string strPath;
		StringArray saFiletypes, saFilePaths;
		saFiletypes.SetSize( 3 );
		saFiletypes[0]="[Project (*.OPJ)] *.OPJ";
		saFiletypes[1]="[Old version (*.ORG)] *.ORG";
		saFiletypes[2]="[Worksheets (*.OGW)] *.OGW";
		iNumSelFiles = GetMultiOpenBox( saFilePaths, saFiletypes ); // or
		iNumSelFiles = GetMultiOpenBox( saFilePaths, saFiletypes, "C:\\Program Files\\" ); // or
		iNumSelFiles = GetMultiOpenBox( saFilePaths, saFiletypes, "C:\\Program Files\\", "Origin" ); // or
		iNumSelFiles = GetMultiOpenBox( saFilePaths, saFiletypes, "C:\\Program Files\\", "Origin", "OpenOPJ" ); // or
		iNumSelFiles = GetMultiOpenBox( saFilePaths, saFiletypes, "C:\\Program Files\\", "Origin", "OpenOPJ", true );
	Parameters:
		saFilePaths=Output vector of strings containing path and filename of all selected files
		saFiletypes=Input vector containing file types to list in the dialog box, each element
			of vector must follow syntax of LabTalk FDLog.TypeN$ object property
		lpcszPath=Input initial path when dialog opens, default NULL uses FDLog tracking
		lpcszFileName=Input initial filename when dialog opens, default NULL uses an empty string 
		lpcszDialogName=Input title of the dialog box, default NULL uses "Open"
		bMultiSelection=Input flag specifiying to use multi-selection Open (default true) or Multi-Open (false) dialog box
	Return:
		Returns the path and filename of all selected files or an empty string if Cancel button
		in dialog box is clicked. Also returns the number of files selected.
*/
int GetMultiOpenBox( StringArray& saFilePaths, StringArray &saFiletypes, LPCSTR lpcszPath, LPCSTR lpcszFilename,
	 LPCSTR lpcszDialogName, bool bMultiSelection ) // lpcszPath = NULL, lpcszFilename = NULL, lpcszDialogName = NULL, bMultiSelection = true
{
	if( bMultiSelection )
		return GetFileDialogBox( saFilePaths, saFiletypes, FDLOG_TYPE_OPEN_MULTISEL, lpcszPath, lpcszFilename, lpcszDialogName );
	else
		return GetFileDialogBox( saFilePaths, saFiletypes, FDLOG_TYPE_MULTI_OPEN, lpcszPath, lpcszFilename, lpcszDialogName );
}

/**
		An FDLog.UseGroup version of GetMultiOpenBox that uses an enumerated FDLog.UseGroup
		code to indicate the set of file types to list. See sys_utils.h or the Origin.ini
		file for a list of the enumerated FDLOG.UseGroup codes. Optionally uses a simple
		Open dialog with multiple selection enabled or a Multi-Open dialog box.
	Example:
		int iNumFiles;
		StringArray saFilePaths;
		iNumFiles = GetMultiOpenBox( saFilePaths, FDLOG_ORIGIN ); // or
		iNumFiles = GetMultiOpenBox( saFilePaths, FDLOG_EXCEL, "C:\\Program Files\\" ); // or
		iNumFiles = GetMultiOpenBox( saFilePaths, FDLOG_ASCII, "C:\\Program Files\\", "Origin" ); // or
		iNumFiles = GetMultiOpenBox( saFilePaths, FDLOG_SCRIPT, "C:\\Program Files\\", "Origin", "OpenOGS" );
		iNumFiles = GetMultiOpenBox( saFilePaths, FDLOG_SCRIPT, "C:\\Program Files\\", "Origin", "OpenOGS", false );
	Parameters:
		saFilePaths=Output vector of strings containing path and filename of all selected files
		nFDLogUseGroup=Input LabTalk FDLog.UseGroup code as enumerated in sys_utils.h and in
			the Origin.ini file
		lpcszPath=Input initial path when dialog opens, default NULL uses FDLog tracking
		lpcszFileName=Input initial filename when dialog opens, default NULL uses an empty string 
		lpcszDialogName=Input title of the dialog box, default NULL uses "Open"
		bMultiSelection=Input flag specifiying to use multi-selection Open (default true) or Multi-Open (false) dialog box
	Return:
		Returns the path and filename of all selected files or an empty string if Cancel button
		in dialog box is clicked. Also returns the number of files selected.
*/
int GetMultiOpenBox( StringArray& saFilePaths, FDLogUseGroup nFDLogUseGroup, LPCSTR lpcszPath, LPCSTR lpcszFilename,
	 LPCSTR lpcszDialogName, bool bMultiSelection ) // lpcszPath = NULL, lpcszFilename = NULL, lpcszDialogName = NULL, bMultiSelection = true
{
	if( bMultiSelection )
		return GetFileDialogBox( saFilePaths, nFDLogUseGroup, FDLOG_TYPE_OPEN_MULTISEL, lpcszPath, lpcszFilename, lpcszDialogName );
	else
		return GetFileDialogBox( saFilePaths, nFDLogUseGroup, FDLOG_TYPE_MULTI_OPEN, lpcszPath, lpcszFilename, lpcszDialogName );
}

//////////////////////////////////////////////////////////////////////////////////
/**
		An easier to use version of GetMultiOpenBox that works for a single file type.
		Optionally uses a simple Open dialog with multiple selection enabled or a
		Multi-Open dialog box.
	Example:
		int iNumFiles;
		StringArray saFilePaths;
		iNumFiles = GetMultiOpenBox(saFilePaths); // or
		iNumFiles = GetMultiOpenBox( saFilePaths, "[Old version (*.ORG)] *.ORG" ); // or
		iNumFiles = GetMultiOpenBox( saFilePaths, "*.OPJ"); // or
		iNumFiles = GetMultiOpenBox( saFilePaths, "*.ocw Workspace", GetAppPath() + "OriginC\\" ); // or
		iNumFiles = GetMultiOpenBox( saFilePaths, "*.ocw Workspace", GetAppPath() + "OriginC\\", "Origin" ); // or
		iNumFiles = GetMultiOpenBox( saFilePaths, "*.ocw Workspace", "C:\\Program Files\\", "Origin", "Open Workspace", false );
	Parameters:
		saFilePaths=Output vector of strings containing path and filename of all selected files
		lpcszFileType=Input file type string like "*.ext description", "[decription (*.ext)] *.ext", or just "*.ext"
		lpcszPath=Input initial path when dialog opens, default NULL uses FDLog tracking
		lpcszFileName=Input initial filename when dialog opens, default NULL uses an empty string 
		lpcszDialogName=Input title of the dialog box, default NULL uses "Open"
		bMultiSelection=Input flag specifiying to use multi-selection Open (default true) or Multi-Open (false) dialog box
	Return:
		Returns the path and filename of all selected files or an empty string if Cancel button
		in dialog box is clicked. Also returns the number of files selected.
*/
int GetMultiOpenBox( StringArray& saFilePaths, LPCSTR lpcszFileType, LPCSTR lpcszPath, LPCSTR lpcszFilename,
	 LPCSTR lpcszDialogName, bool bMultiSelection ) // lpcszFileType = "*.* All Files", lpcszPath = NULL, lpcszFileName = NULL, lpcszDialogName = NULL, bMultiSelection = true
{
	if( bMultiSelection )
		return GetFileDialogBox( saFilePaths, lpcszFileType, FDLOG_TYPE_OPEN_MULTISEL, lpcszPath, lpcszFilename, lpcszDialogName );
	else
		return GetFileDialogBox( saFilePaths, lpcszFileType, FDLOG_TYPE_MULTI_OPEN, lpcszPath, lpcszFilename, lpcszDialogName );
}
//------------------- QA70-4078

/**
		Compute a LabTalk (1 based) index from a C (0 based) index and add an offset.
	Parameters:
		iCindex=Input 0 based C index
		nOffset=Input offset, default is 0
	Return:
		Returns a LabTalk 1 based index with added offset.
*/
int c_index_to_labtalk_index(int iCindex, int nOffset) // nOffset = 0
{
	return iCindex + 1 + nOffset;	
}

/**
		Compute a C (0 based) index from a LabTalk (1 based) index and add an offset.
	Parameters:
		iLTindex=Input 1 based LabTalk index
		nOffset=Input offset, default is 0
	Return:
		Returns a C 0 based index with added offset.
*/
int labtalk_index_to_c_index(int iLTindex, int nOffset) // nOffset = 0
{
	return iLTindex - 1 + nOffset;
}

/// EJP 11-20-2003 v7.5764 QA70-5587 FAIL_TO_EXPORT_1200DPI_BITMAP
int ImageExportErrorMessageBox(int nErr)
{
	bool bLibErr = false;
	
	string strDescrip;
	switch( nErr )
	{
	case 301: // OERR_ORIGIN_INTERNAL_BMP
		strDescrip = _L("Internal bitmap error");
		break;
	case 302: // OERR_ORIGIN_CREATE_BMP_FILE
		strDescrip = _L("Error creating bitmap file");
		break;
	case 309: // OERR_ORIGIN_INTERNAL_BMP_COLOR_DEPTH
		strDescrip = _L("Internal bitmap color depth error");
		break;
	/// EJP 04-14-2004 v7.5857 QA70-5587 FAIL_TO_EXPORT_1200DPI_BITMAP
	case 500: // Inso error
		strDescrip = _L("Inso Error");
		bLibErr = true;
		break;
	case 400: // LeadTools error
		strDescrip = _L("LeadTools Error");
		bLibErr = true;
		break;
	/// end FAIL_TO_EXPORT_1200DPI_BITMAP
	}

	string strLibErr;
	if( bLibErr )
	{
		double dErr;
		if( LT_get_var("Image.LibError", &dErr) )
			strLibErr.Format(" %d", (int)dErr);
	}

	string strMsg;
	string strMsgFormat = _L("Error %d\n%s%s");
	strMsg.Format(strMsgFormat, nErr, strDescrip, strLibErr);
	
	MessageBox(GetWindow(), strMsg, _L("Origin Image Export"));
	return nErr;
}
/// end FAIL_TO_EXPORT_1200DPI_BITMAP

#define IS_CHAR_LETTER(_ch)		(('A' <= (_ch) && (_ch) <= 'Z') || ('a' <= (_ch) && (_ch) <= 'z'))
#define IS_CHAR_NUMBER(_ch)		('0' <= (_ch) && (_ch) <= '9')
bool validate_identifier_name(string &strName)
{
	/// JCG 06/17/03 QA70-4575 IMP_WIZD_BUG_45_AND_28
	/// if( !IS_CHAR_LETTER(strName[0]) && strName[0] != '_' )
	///	strName.Delete(0);
	//
	// when scan header lines, the identifier name can be only a number such "1"
	// so shouldn't remove it, otherwise, this line can not be scanned.
	if( !IS_CHAR_LETTER(strName[0]) && strName[0] != '_' )
	{
		if( strName.GetLength() > 1 ) // keep it if only a number
			strName.Delete(0);
	}
	/// end IMP_WIZD_BUG_45_AND_28
	int n = 0;
	while( n < strName.GetLength() )
	{
		if( IS_CHAR_LETTER(strName[n]) || IS_CHAR_NUMBER(strName[n]) || '_' == strName[n] )
			n++;
		else
			strName.Delete(n);
	}
	return true;
}


/**
		Makes sure that a Note window with the name strNoteWnd exists. If not, it will be created
		and given that name. If strNoteWnd is empty, it will just create a new Note window.  
	Example:
	Parameters:
		lpcszName=the Note window name
	Return:
		Returns TRUE if OK, otherwise FALSE.
*/
bool	get_create_Note(string &strNoteWnd)
{
	BOOL		bDone = FALSE;
	if (!strNoteWnd.IsEmpty())	// specified?
	{
		Note		nt(strNoteWnd);
		if (nt)
		{
			return true;
		}
	}
	
	// does not exist, must be created:
	Note		ntNew;
	if (ntNew.Create())
	{
		if (!strNoteWnd.IsEmpty())
			ntNew.Rename(strNoteWnd);
		
		strNoteWnd = ntNew.GetName();
	}
	else
		return false;

	return true;
}

//CPY 7/20/04 add bCheckSheetName
BOOL	worksheets_are_same(Worksheet &wks1, Worksheet &wks2, bool bCheckSheetName) //=true
{
	if (!wks1 || !wks2)
		return FALSE;	// one not attached consider the different
	
	WorksheetPage	wp1;
	wks1.GetParent(wp1);
	
	WorksheetPage	wp2;
	wks2.GetParent(wp2);
	
	if (!wp1 || !wp2)
		return FALSE;
	
	string		strName1 = wp1.GetName();
	string		strName2 = wp2.GetName();
	
	BOOL		bSame = strName1.CompareNoCase(strName2) == 0;
	if(bSame && bCheckSheetName)
	{
		strName1 = wks1.GetName();
		strName2 = wks2.GetName();
		return strName1.CompareNoCase(strName2) == 0? true:false;
	}
	return bSame;
}

/// EJP 2006-02-17 v8.0366 MOVE_IMPORT_FILE_INFO_FROM_OC_TO_VC
///	/// EJP 07-10-2003 v7.0622 QA70-4745 SET_PAGE_IMPORT_INFO_ON_123_ASC_IMPORT
///	BOOL set_page_import_info(Page &pgTarget, LPCSTR lpcszFile, int iDataType)
///	{
///		if( !pgTarget )
///			return FALSE;
///		
///		// file date
///		double dJulianDate = 0.0;
///		WIN32_FILE_ATTRIBUTE_DATA fad;
///		if( GetFileAttributesEx(lpcszFile, 0, &fad) )
///		{
///			SYSTEMTIME st;
///			if( FileTimeToSystemTime(&fad.ftLastWriteTime, &st) )
///				SystemTimeToJulianDate(&dJulianDate, &st);
///		}
///		pgTarget.Info.System.Import.FileDate = dJulianDate;
///	
///		pgTarget.Info.System.Import.FileName$ = GetFileName(lpcszFile);
///		pgTarget.Info.System.Import.FilePath$ = lpcszFile;
///		pgTarget.Info.System.Import.Filter$ = ""; // filter file unknown
///		pgTarget.Info.System.Import.FileType = iDataType;
///		return TRUE;
///	}
///	/// end SET_PAGE_IMPORT_INFO_ON_123_ASC_IMPORT
/// end MOVE_IMPORT_FILE_INFO_FROM_OC_TO_VC

//--------------------------------------------------------- CPY 8/12/03 QA70-4999
bool add_file_extension(string& strFilename, LPCSTR lpcszExt)
{
	LPSTR lpstr = strFilename.GetBuffer(MAXFULLPATH);
	char	szTemp[20];// file ext only 3 chars
	bool	bRet = false;
	///------ Folger 05/11/09 QA80-13571 CHECK_ADD_FILE_EXT_SHOULD_RETURN_PROPER_ERROR
	//if(check_add_file_ext(lpstr, NULL, szTemp) || lstrcmpi(szTemp, lpcszExt) != 0) // NO file extension, or is diff
	if( CHECKADDFILEEXT_HAS_NOT_EXTENSION == check_add_file_ext(lpstr, NULL, szTemp) || lstrcmpi(szTemp, lpcszExt) != 0 ) // NO file extension, or is diff
	///------ End CHECK_ADD_FILE_EXT_SHOULD_RETURN_PROPER_ERROR
	{
		lstrcat(lpstr, ".");
		lstrcat(lpstr, lpcszExt);
		bRet = true;
	}
	strFilename.ReleaseBuffer();
	return bRet;
}
//---------------------------------------------------------

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 is_win2k(bool bAndLater) // true
{
	DWORD	dwVersion = GetVersion();
	// Get major and minor version numbers of Windows
	WORD loword = LOWORD(dwVersion);
	int lowbyte = LOBYTE(loword);
	int hibyte =  HIBYTE(loword);
	if(!(dwVersion & 0x80000000))                // Windows NT, 2000, XP
	{
		if(bAndLater)
			return lowbyte >= 5? true:false;
		
		return (5 == lowbyte && 0 == hibyte)? true:false;
	}
	// Windows 95, 98, ME
	return false;
}

//---- CPY 10/25/06 BETTER_SEPARATE_FILE_NAME_AND_EXT
//void separate_file_name_ext(string& strFileName, string& strExt)
//return FALSE if no ext
bool separate_file_name_ext(LPCSTR lpcszFilename, string* pstrFileName, string* pstrExt)
{
	char	szExt[20];// file ext only 3 chars
	char	szTemp[MAXFULLPATH];
	lstrcpyn(szTemp, lpcszFilename, MAXFULLPATH);
	///---Sim 05-07-2009 QA80-13571 FIX_CRASH_WHEN_FILE_PATH_LENGTH_IS_TOO_LONG
#ifdef CHECK_EXCEED_FILE_PATH_LENGTH_LIMITATION
	int 	nLength = lstrlen(szTemp);
#endif
	///------ Folger 05/11/09 QA80-13571 CHECK_ADD_FILE_EXT_SHOULD_RETURN_PROPER_ERROR
	//if(check_add_file_ext(szTemp, NULL, szExt))
	if ( CHECKADDFILEEXT_HAS_NOT_EXTENSION == check_add_file_ext(szTemp, NULL, szExt) )
	///------ End CHECK_ADD_FILE_EXT_SHOULD_RETURN_PROPER_ERROR
	{
		if(pstrExt)
			pstrExt->Empty();
		if(pstrFileName)
			///---Sim 05-07-2009 QA80-13571 FIX_CRASH_WHEN_FILE_PATH_LENGTH_IS_TOO_LONG
#ifndef CHECK_EXCEED_FILE_PATH_LENGTH_LIMITATION
			*pstrFileName = lpcszFilename;
#else
			*pstrFileName = szTemp;
#endif
			///---END QA80-13571 FIX_CRASH_WHEN_FILE_PATH_LENGTH_IS_TOO_LONG
		
		return false;
	}
	else
	{
		if(pstrExt)
			*pstrExt = szExt;
		int nExtLen = lstrlen(szExt);
		string strFileName = lpcszFilename;
		///---Sim 05-07-2009 QA80-13571 FIX_CRASH_WHEN_FILE_PATH_LENGTH_IS_TOO_LONG
#ifndef CHECK_EXCEED_FILE_PATH_LENGTH_LIMITATION
		strFileName.Delete(strFileName.GetLength() - nExtLen-1, nExtLen+1);
#else
		int nDelPos = nLength - (nExtLen + 1);
		strFileName.Delete(nDelPos, strFileName.GetLength() - nDelPos);
#endif
		///---END QA80-13571 FIX_CRASH_WHEN_FILE_PATH_LENGTH_IS_TOO_LONG
		if(pstrFileName)
			*pstrFileName = strFileName;
	}
	return true;
}
//----

static string _format_postfix(int nPostfix, int nBitsOfPostfix)
{
	string	strPostfix = nPostfix;
	if(nBitsOfPostfix <= 0)
		return strPostfix;	
	
	int		nSpace = nBitsOfPostfix - lstrlen(strPostfix);
	for(int ii=0; ii<nSpace; ii++)
	{
		strPostfix.Insert(0, "0");
	}
	return strPostfix;
}

//Check to find the strPathFilename that does not already exist 
bool get_next_file_name(string& strPathFilename, bool bCheckCreatePath, bool bKeepPostfixFormat) /// = true = true
{
	string strPath = GetFilePath(strPathFilename);
	if(bCheckCreatePath && !CheckMakePath(strPath))
		return false;

	if(!bCheckCreatePath && !strPath.IsPath())
		return false;
	
	string strFilename = GetFileName(strPathFilename);
	string strExt;
	/// Iris 12/13/2006 KEEP_OLD_POSTFIX_FORMAT_FOR_NEXT_FILENAME
	//for now, if exist Graph1, the next filename will be Graph11; but the correct next name should be Graph2!	
	/*
	separate_file_name_ext(strPathFilename, NULL, &strExt);	
	int nn = 1;
	*/
	separate_file_name_ext(strFilename, &strFilename, &strExt);	
	string		strPrefix; 
	int			nn = string_to_prefix_end_number(strPrefix.GetBuffer(MAXLINE), strFilename);	strPrefix.ReleaseBuffer();	
	////end KEEP_OLD_POSTFIX_FORMAT_FOR_NEXT_FILENAME
	
	while(strPathFilename.IsFile())
	{
		/// Iris 12/13/2006 KEEP_OLD_POSTFIX_FORMAT_FOR_NEXT_FILENAME
		//string strTemp = strPath + strFilename + (nn++);
		string 	strPostfix = (++nn);
		if(bKeepPostfixFormat)
		{
			int		nBitsOfPostfix = lstrlen(strFilename) - lstrlen(strPrefix);
			strPostfix = _format_postfix(nn, nBitsOfPostfix);
		}
		string strTemp = strPath + strPrefix + strPostfix;
		///end KEEP_OLD_POSTFIX_FORMAT_FOR_NEXT_FILENAME
		if(!strExt.IsEmpty())
			strTemp += "." + strExt;
		strPathFilename = strTemp;
		///---Sim 05-07-2009 QA80-13571 FIX_CRASH_WHEN_FILE_PATH_LENGTH_IS_TOO_LONG
		if ( check_trim_file_path_if_too_long(strPathFilename) )
		{
			//strPathFilename.Empty();
			okoc_out_msg(_L("Auto Rename Failed. File Name Path is too long!"), 'W');
			return false;
		}
		///---END QA80-13571 FIX_CRASH_WHEN_FILE_PATH_LENGTH_IS_TOO_LONG
	}
	return true;
}

int remove_if_in_list(vector<string>& vsToCheck, const vector<string>& vsList, bool bCaseSensitive) // = false
{
	int nCount = 0;
	vector<string> vsTemp;
	for(int ii = 0; ii < vsToCheck.GetSize(); ii++)
	{
		if(!is_in_list(vsToCheck[ii], vsList, bCaseSensitive))
		{
			vsTemp.Add(vsToCheck[ii]);
			nCount++;
		}		
	}
	
	if( nCount > 0)
		vsToCheck = vsTemp;
	else	///Jasmine 10/29/08 MISS_CASE_THAT_vsToCheck_ELEMENT_ALL_IN_vsList
		vsToCheck.RemoveAll();
	
	return nCount;
}

int remove_if_not_in_list(vector<string>& vsToCheck, const vector<string>& vsList, bool bCaseSensitive) // = false
{
	vector<string> vsTemp;
	LPCSTR lpcsz;
	for(int ii = 0; ii < vsToCheck.GetSize(); ii++)
	{
		lpcsz = vsToCheck[ii];
		if(is_in_list(lpcsz, vsList, bCaseSensitive))
			vsTemp.Add(lpcsz);
	}
	int nRemoved = vsToCheck.GetSize() - vsTemp.GetSize();
	vsToCheck = vsTemp;
	return nRemoved;
}
///Hong 8/01/06 ADD_POSTFIX_SUPPORT
//int get_list_enum_number(vector<string> vsVals, string strPrefix)
int get_list_enum_number(vector<string> vsVals, string strPrefix, string strPostfix)
///end ADD_POSTFIX_SUPPORT
{
	//if(-1 == vsVals.Find(strPrefix))
	if(-1 == vsVals.Find(strPrefix + strPostfix))//Hong 8/01/06 ADD_POSTFIX_SUPPORT
		return 0;
	for(int ii=1; ;ii++)
	{
		//if(-1 == vsVals.Find(strPrefix+(string)ii))
		if(-1 == vsVals.Find(strPrefix+(string)ii + strPostfix))//Hong 8/01/06 ADD_POSTFIX_SUPPORT
			return ii;
	} 
}

int count_list(const vector<string>& vsList, vector<string>& vsUnique, vector<uint>& vnCounts, bool bCaseSensitive) // = false
{
	vsUnique.SetSize(0);
	vnCounts.SetSize(0);
	int nCount = 0;
	int nn;
	for(int ii = 0; ii < vsList.GetSize(); ii++)
	{
		if(is_in_list(vsList[ii], vsUnique, bCaseSensitive, &nn))
		{
			nCount++;
			vnCounts[nn] += 1;
		}
		else
		{
			vsUnique.Add(vsList[ii]);
			vnCounts.Add(1);
		}
	}
	return nCount;
}
//--- CPY 12/6/04 SHOW_RANGE_TO_LABEL_FOR_MULTIPLE_RANGE_ON_SAME_DATA
// this version of count will set set vnCounts to be same size as input str
// and put 0 in all str that dose not have duplicates but for all with duplicates
// it will put 1,2,3 as sequence into vnCounts correpsonding entries
bool count_list(const vector<string>& vs, vector<int>& vnIndices, bool bCaseSensitive)//= = false
{
	uint nSize = vs.GetSize();
	vnIndices.SetSize(nSize);
	vnIndices = 0;
	vector<string> vsUnique;
	vector<uint> vnUniqueCts;
	if(count_list(vs, vsUnique, vnUniqueCts))
	{
		vector<uint> vnCC;
		vnCC.SetSize(vnUniqueCts.GetSize());
		vnCC = 0;
		int nn;
		for(int ii = 0; ii < nSize; ii++)
		{
			if(is_in_list(vs[ii], vsUnique, bCaseSensitive, &nn))
			{
				if(vnUniqueCts[nn]> 1) // duplicate entries
				{
					vnCC[nn] += 1;
					vnIndices[ii] = vnCC[nn];
				}
			}
			else
				out_str("count_list error, should never come here");
		}
		return true;
	}
	return false;
}

int find_in_list(int nVal, const vector<int>& vn, bool bWasSortedAccending)
{
	if(vn.GetSize() < 1) // CPY 6/26/06
		return -1;
	/// Hong 03/13/09 FIX_UNSORTED_VECTOR_FAIL_GET_CORRECT_INDEX
	/* Hong, code below is really amazing~~
	if(!bWasSortedAccending)
	{
		vector<int> vnTemp;
		vnTemp = vn;
		vnTemp.Sort();
		return find_in_list(nVal, vnTemp, true);
	}
	*/
	/// end FIX_UNSORTED_VECTOR_FAIL_GET_CORRECT_INDEX
	for(int ii = 0; ii < vn.GetSize(); ii++)
	{
		if(vn[ii] == nVal)
			return ii;
		/// Hong 03/13/09 FIX_UNSORTED_VECTOR_FAIL_GET_CORRECT_INDEX
		//else if(vn[ii] > nVal)
		else if( bWasSortedAccending && vn[ii] > nVal )
		/// end FIX_UNSORTED_VECTOR_FAIL_GET_CORRECT_INDEX
			return -1;
	}
	return -1;
}
		
// return -1 if not
// use numeric comparison
string find_in_list(double dVal, const string& strList, char cSeparator)
{
	vector<string> vsList;
	strList.GetTokens(vsList, cSeparator);
	string str;
	for(int ii = 0; ii < vsList.GetSize(); ii++)
	{
		str = vsList[ii];
		double dTemp = atof(str);
		if(is_equal(dVal, dTemp))
			return str;
	}
	return "";
}

bool is_in_list(LPCSTR lpcszName, const vector<string>& vsList, bool bCaseSensitive, int* pn) // = false = NULL
{
	/*
	if(NULL == lpcszName)
		return false;
	
	int ii;
	if(bCaseSensitive)
	{
		for(ii = 0; ii < vsList.GetSize(); ii++)
		{
			if(vsList[ii].Compare(lpcszName) == 0)
			{
				if(pn)
					*pn = ii;
				return true;
			}
		}
		return false;
	}
	
	for(ii = 0; ii < vsList.GetSize(); ii++)
	{
		if(vsList[ii].CompareNoCase(lpcszName) == 0)
		{
				if(pn)
					*pn = ii;
			return true;
		}
	}
	return false;
	*/
	return okutil_is_in_list(lpcszName, &vsList, bCaseSensitive, false, pn ); //false, false, NULL, 0
}
///Sophy 04/09/2008 SET_INSERT_STRING_CASE_SENSITIVE
//bool insert_str_to_str_list(LPCSTR lpcszInsert, string& strList, LPCSTR lpcszBefore, bool bFullMatch, string strDelimiter) // =  NULL, "|"
bool insert_str_to_str_list(LPCSTR lpcszInsert, string& strList, LPCSTR lpcszBefore, bool bFullMatch, string strDelimiter) // =  NULL, true, "|"
///end SET_INSERT_STRING_CASE_SENSITIVE
{
	if(NULL == lpcszInsert)
		return false;
	
	vector<string> 	vsList;	
	char 			chDelimiter = strDelimiter.GetAt(0);	
	int nCount = strList.GetTokens(vsList, chDelimiter);
	
	int 	nIndex;
	if(NULL != lpcszBefore)
	{
		///Sophy 04/09/2008 SET_INSERT_STRING_CASE_SENSITIVE
		//nIndex = vsList.Find(lpcszBefore);
		nIndex = vsList.Find(lpcszBefore,0,false,bFullMatch,-1);
		///end SET_INSERT_STRING_CASE_SENSITIVE

		if(nIndex<0)
			nIndex = 0;
	}
	else
		nIndex = nCount;
	
	if( vsList.Find(lpcszInsert) < 0 )
	{
		vsList.InsertAt(nIndex, lpcszInsert);
		strList.SetTokens(vsList, chDelimiter);	
	}
	
	return true;
}
string get_str_from_str_list(string& strList, string strDelimiter, uint nIndex )
{
	vector<string> 	vsList;	
	char 			chDelimiter = strDelimiter.GetAt(0);	
	int nCount = strList.GetTokens(vsList, chDelimiter);
	
	if(nIndex > nCount)
		nIndex = nCount-1;
	return vsList[nIndex];
}
///Sophy 04/09/2008 SET_REMOVE_STRING_CASE_SENSITIVE
//bool remove_str_from_str_list(LPCSTR lpcszRemoved, string& strList, string strDelimiter)// = "|"
bool remove_str_from_str_list(LPCSTR lpcszRemoved, string& strList, bool bFullMatch, string strDelimiter)// = "|"
///end SET_REMOVE_STRING_CASE_SENSITIVE
{
	if(NULL == lpcszRemoved)
		return false;
	
	char chDelimiter = strDelimiter.GetAt(0); 
	vector<string> 	vsList;
	if(0 == strList.GetTokens(vsList, chDelimiter))
		return false;	
	///Sophy 04/09/2008 SET_REMOVE_STRING_CASE_SENSITIVE
	//int nIndex = vsList.Find(lpcszRemoved);
	int nIndex = vsList.Find(lpcszRemoved,0,false,bFullMatch);
	///end SET_REMOVE_STRING_CASE_SENSITIVE
	if(nIndex < 0)
		return false;
	
	vsList.RemoveAt(nIndex);
	strList.SetTokens(vsList, chDelimiter);
	
	return true;
	
}

///Jasmine 05/05/08 GET_ELEMENT_FROM_VECTOR_BY_ANOTHER_FILTER_VECTOT
int trim_vector(vectorbase& vec, const vectorbase& vbFiltor)
{
	int nSize = vec.GetSize();
	int nFilterSize = vbFiltor.GetSize();
	if(0 == nFilterSize)
	{
		vec.RemoveAll();
		return 0;
	}
	
	int nSum = 0;
	vbFiltor.Sum(nSum);
	if(nSum == 0)
	{
		vec.RemoveAll();
		return 0;
	}
	if(nSum == nFilterSize)
	{
		if(nSize > nFilterSize)
		{
			vec.SetSize(nFilterSize);
			nSize = nFilterSize;
		}
		return nSize;
	}
	
	vector<uint> vnIndeces;
	int nEnd = -1;;
	if(nSize < nFilterSize)
		nEnd = nSize;		
	int nn = vbFiltor.Find(vnIndeces, true, _ONAN, 8, 0, nEnd);	
	for(int ii = 0; ii < nn; ii++)
	{
		int nValueIndex = vnIndeces[ii];
		vec[ii] = vec[nValueIndex];
	}
	vec.SetSize(nn);
	return nn;
}
///End GET_ELEMENT_FROM_VECTOR_BY_ANOTHER_FILTER_VECTOT

///DG REMOVE_REPEAT_ITEM_IN_VECTOR : rewrite this as auto correct is needed
/*
bool is_str_valid_for_filename(LPCSTR lpcszFilename)
{
	string strPath = GetFilePath(lpcszFilename);
	if(!strPath.IsEmpty())
		return false;
	//IsFile seems not able to handle filename with * and ?, so better check first
	string strTest = lpcszFilename;
	if(strTest.IsEmpty() || strTest.Find('*') >=0 || strTest.Find('?') >= 0)
		return false;
	
	char szTempPath[MAXFULLPATH];
	DWORD dw = GetTempPath(MAXFULLPATH, szTempPath);
	if( dw )
	{
		strTest = szTempPath;
		strTest += lpcszFilename;
		if(strTest.IsFile())
			return true; // already existed in temp folder, must be good filename
		
		// not a file in temp folder, safe to create and delete
		HANDLE hFile = CreateFile(strTest,GENERIC_READ, FILE_SHARE_READ,// share for reading
						NULL,                      // no security
						CREATE_NEW,             // new file only
						FILE_ATTRIBUTE_NORMAL,     // normal file
						NULL);                     // no attr. template
		if (hFile == INVALID_HANDLE_VALUE)
			return false;
		CloseHandle(hFile);// must close file after reading	
		DeleteFile(strTest);
		return true;
	}
	return false;
}
*/
bool is_str_valid_for_filename(string &strName, bool bAutoCorrect) // = false
{
	///---Sim 11-30-2006 FIX_BUG_OF_FILE_NAME_WITH_EXT
	//string strAutoName = strName;
	//strAutoName.MakeValidCName();
	/*
	string strFileName, strFileExt, strDot;
	
	// get extension
	int nPosExt = strName.ReverseFind('.');
	if ( 0 <= nPosExt )
	{
		strFileExt = strName.Right(strName.GetLength() - (nPosExt+1));
		strFileExt.MakeValidCName();
		strDot = '.';
	}
	else
	{	// no extension
		strFileExt = "";
		strDot = "";
		nPosExt = strName.GetLength(); // for get file name
	}
	
	// get file name
	strFileName = strName.Left(nPosExt);
	strFileName.Insert(0, 'a');
	strFileName.MakeValidCName();
	strFileName.Delete(0);
	if ( strFileName.IsEmpty() ) // file name can't be empty
		return false;
	
	string strAutoName = strFileName + strDot + strFileExt;	
	
	if(0 != strAutoName.Compare(strName))
	{
		if(bAutoCorrect && !strAutoName.IsEmpty())
			strName = strAutoName;
		else
			return false;
	}
	*/
	///---Sim 06-15-2007 FILE_NAME_CAN_NOT_BE_EMPTY_OR_ONLY_WITH_SPACE_CHARS
	strName.TrimLeft();
	strName.TrimRight();
	if ( strName.IsEmpty() )
		return false;
	///---END FILE_NAME_CAN_NOT_BE_EMPTY_OR_ONLY_WITH_SPACE_CHARS
	
	if ( !bAutoCorrect )
	{
		return strName.FindOneOf(FILENAME_RESTRICTION) == -1 ? true : false;
	}
	else
	{
		string strAutoName = strName;
		int nPos;
		while ( (nPos = strAutoName.FindOneOf(FILENAME_RESTRICTION)) >= 0 )
		{
			strAutoName.Delete(nPos, 1);
		}
		
		///---Sim 06-15-2007 FILE_NAME_CAN_NOT_BE_EMPTY_OR_ONLY_WITH_SPACE_CHARS
		strAutoName.TrimLeft();
		strAutoName.TrimRight();
		///---END FILE_NAME_CAN_NOT_BE_EMPTY_OR_ONLY_WITH_SPACE_CHARS
		
		if ( strAutoName.IsEmpty() )
			return false;
		
		strName = strAutoName;
	}
	///---END FIX_BUG_OF_FILE_NAME_WITH_EXT
	return true;
}
void remove_repeat_item(vector<string> &vsList, bool bRemoveEmpty, bool bCaseSensitive) //=true, false
{
	int ii, nFind;
	string str;
	for(ii=0; ii<vsList.GetSize(); ii++)
	{
		str=vsList[ii];
		nFind=ii;
		if((bRemoveEmpty && str.IsEmpty()) || -1 != (nFind=vsList.Find(str, ii+1, bCaseSensitive)))
		{
			vsList.RemoveAt(nFind);
			ii--;	//search itself again
		}
	}
}
///end REMOVE_REPEAT_ITEM_IN_VECTOR

///DG IS_REPEATE_STR
#define MAX_LENGTH	50
int is_repeat_str(string str)
{
	int nLength = str.GetLength(), nRet;
	if(MAX_LENGTH < nLength/2)
	{
		error_report("String too long");
		ASSERT(0);
	}
	for(int ii=nLength/2; ii>0; ii--)
	{
		string strTemp(str);
		char chSubStr[MAX_LENGTH];
		strncpy(chSubStr, str, ii);
		nRet = strTemp.Replace(chSubStr, "");
		if(strTemp.IsEmpty())
			return nRet-1;
	}
	return 0;
}
///end IS_REPEATE_STR

///Jasmine 04/29/08 ADD_FUNC_REMOVE_EMPTY_ITEM_FROM_STRING_VECTOR
int	remove_empty_item(vector<string>& vs)
{
	for(int ii = vs.GetSize() - 1; ii >= 0; ii--)
	{
		string str = vs[ii];
		
		if( !str.IsEmpty() )
		{
			str.TrimLeft();
			str.TrimRight();
		}
		
		if( str.IsEmpty() )
			vs.RemoveAt(ii);
	}
	
	return vs.GetSize();
}
///End ADD_FUNC_REMOVE_EMPTY_ITEM_FROM_STRING_VECTOR

///DG 9/2/05 : Count tab('\t') number and enter('\n') number in word programming
int find_prefix_char_number(const string& str, char ch)
{
	vector<string> vs;
	str.GetTokens(vs, ch);
	for(int ii=0; ii<vs.GetSize(); ii++)
	{
		if(!vs[ii].IsEmpty())
			return ii;
	}
	return 0;
}
int find_end_char_number(const string& str, char ch)
{
	vector<string> vs;
	str.GetTokens(vs, ch);
	int nSize=vs.GetSize()-1;
	for(int ii=0; ii<=nSize; ii++)
	{
		if(!vs[nSize-ii].IsEmpty())
			return ii;
	}
	return 0;
}
///end

// for used in LatTalk to access to this path
// example:
// get_project_attached_files_path %A;
// %Z=%Atest.dat; 
bool get_project_attached_files_path(string& strPath)
{
	strPath = GetProjectAttachedFilesPath();
	return strPath.IsEmpty()? false:true;
}


/// AW 10/27/03 v7.0733 QA70-5398 ADD_OC_BASIC_IO 
static TM s_tm;
TM *gmtime( time_t *ptimer )
{
   convert_time_to_tm(ptimer, &s_tm);
   return &s_tm;
}

TM *localtime( time_t *ptimer )
{
   convert_time_to_local(ptimer, &s_tm);
   return &s_tm;
}

static int _daylight;
static long _timezone;
static char *_tzname[2];


void gettimeSetting()
{
	get_time_setting(&_daylight, &_timezone, _tzname); 	
}
/// END ADD_OC_BASIC_IO 


/// EJP 04-29-2004 v7.5837 QA70-6342 ACCESS_STR_TO_TIME_FUNC_FROM_LABTALK
/** >Date Time
		Convert a time formatted string to a Julian date value.
	Parameters:
		strTime = string containing the time.
	Returns:
		A double containing a Julian date value
	Example:
		// When specifying days you must use 3 digits, so prefix with leading zero(s) when necessary.
		string strTime = "001:12:00:00.0"; // 1 day, 12 hrs, 0 mins, 0 secs
		double dTime;
		dTime = Time(strTime);
		printf("%s == %f\n", strTime, dTime);
*/
double Time(string strTime)
{
	return str_to_time(strTime);
}
/// end ACCESS_STR_TO_TIME_FUNC_FROM_LABTALK

///DSC 2/17/05 GET_ORIGIN_PATH
/*
///Frank 5/26/04  v8.0878 QA70-6418 GET_ALLUSER_FOLDEL_PATH						
string get_alluserfolder_path(bool bCreateIfNoExist ) // = false
{
	string strAllUserFolderPath;
	strAllUserFolderPath =  GetAppPath(true) + get_origin_folder_type_info( ALL_USER_FOLDER ,"\\");//ALLUSERFOLDER;///Frank 1/22/05 CENTRALIZE_MARCO_OF_FOLDER_INFO
	if(bCreateIfNoExist)
	{
		if(!CheckMakePath(strAllUserFolderPath))
			strAllUserFolderPath =  "" ;
	}
	else
	{
		if(!strAllUserFolderPath.IsPath())
			strAllUserFolderPath =  "" ;
	}
	return strAllUserFolderPath;
}
///End GET_ALLUSER_FOLDEL_PATH 
*/
///end GET_ORIGIN_PATH

//--- CPY 5/6/04 QA70-6367 HISTOGRAM_GRAPHS
bool error_report(LPCSTR lpcszErrMsg, bool bCritical)
{
	//------ CPY 4/3/08 PA_FIT_CNTRL_OPEN_EMPTY_NO_ERR_MSG
	if(bCritical)
	{
		MessageBox(GetWindow(), lpcszErrMsg, _L("Origin C Report Critical Error"));
		return false;
	}
	//----- end PA_FIT_CNTRL_OPEN_EMPTY_NO_ERR_MSG
		
	//out_str(lpcszErrMsg);
	string str = lpcszErrMsg;
	str.WriteLine(WRITE_COMPILER_OUTPUT);
	return false;
}
//---

#if _OC_VER >= 0x0800

bool is_pro_version()
{
	DWORD dwProd = GetLicenseInfo();
	if( ORGPRODUCTTYPE_PRO == (dwProd & 0x000000FF) )
		return true;
	
	return false;
}


//--- CPY ML 8/11/05
bool	assign_HWND_to_PHWND(LPVOID lpDest, HWND hwndSource)
{
	if(NULL == lpDest)
		return false;
	DWORD		*pdwDest = (DWORD*)lpDest;
	DWORD		dwHandle = (DWORD)hwndSource;
	*pdwDest = dwHandle;
	return true;
}

///Frank 9/14/04  v8.0131 QA70-6903 PAD_CHAR_TO_STRING	
string	str_pad_char(LPCSTR lpcstr, int nTotalLength, int nPaddingFormat, char	chPading )
{
	int nSourceLength ; 
	int		nFillCharCountAtLeft;
	string	strRet;
	char	*pstrPadedString;
	
	nSourceLength = lstrlen(lpcstr);
	pstrPadedString = strRet.GetBuffer(nTotalLength + 1);
	if(nSourceLength >= nTotalLength)
	{
		lstrcpyn(pstrPadedString,lpcstr,  nTotalLength+1);
		strRet.ReleaseBuffer();
		return strRet;
	}
	
	for(int	i=0; i<nTotalLength; i++)
	{
		pstrPadedString[i] = chPading;
	};
	switch(nPaddingFormat)
	{
	case DISPLAY_LEFT:
		nFillCharCountAtLeft = 0;
		break;
	case DISPLAY_CENTER:
		nFillCharCountAtLeft = (nTotalLength - nSourceLength)/2 ;
		break;
	case DISPLAY_RIGHT:
		nFillCharCountAtLeft = nTotalLength - nSourceLength ;
		break;
	}
	
	pstrPadedString[nFillCharCountAtLeft] = 0;//Set zero in first left element of the char array, 
	
	strcat(pstrPadedString,lpcstr);
	
	pstrPadedString[nFillCharCountAtLeft + nSourceLength] = chPading;
	
	pstrPadedString[nTotalLength] = 0;
	
	strRet.ReleaseBuffer();

	return strRet;
}
///End PAD_CHAR_TO_STRING

///DG FILE_TIME_COMPARE
#define TOTAL_FILES			2
int file_time_compare(LPCSTR lpczFile1, LPCSTR lpczFile2, DWORD dwOption)
{
	WIN32_FILE_ATTRIBUTE_DATA cFileInfo;
	FILETIME cFileTime[TOTAL_FILES];
	LPCSTR lpcszFile[TOTAL_FILES];
	lpcszFile[0]=lpczFile1;
	lpcszFile[1]=lpczFile2;
	for(int ii=0; ii<TOTAL_FILES; ii++)
	{
		if(!GetFileAttributesEx(lpcszFile[ii], 0, &cFileInfo))
			return -1;
	//----- Kevin 09/30/05 ADD_FILE_COMPARE_TIME_OPTION
		//cFileTime[ii]=cFileInfo.ftCreationTime;
		switch(dwOption) 
		{
		case CREATION_TIME:
			cFileTime[ii]=cFileInfo.ftCreationTime;
			break;

		case LAST_ACCESS_TIME:
			cFileTime[ii]=cFileInfo.ftLastAccessTime;
			break;

		case LAST_WRITE_TIME:
			cFileTime[ii]=cFileInfo.ftLastWriteTime;
			break;

		default:
			break;
		}

	//------	ADD_FILE_COMPARE_TIME_OPTION
	}
	
	if(1 == CompareFileTime(&cFileTime[0], &cFileTime[1]))
		return 1;
	else
		return 0;
}
///end FILE_TIME_COMPARE

///Frank 9/23/04  v8.0137 QA70-6027 CONVERT_NUM_TO_STRING_VECTOR
//CPY 10/4/04 change to use treenode instead of vector
/**
		Convert double vector treenode to string vector. 
	Example:
		void test_convert_tree_double_vector_to_str_vector()
		{
			Tree tr;
			vector	vd = {1,2,3,4.0989};
			tr.tr1.dVals = vd;
			vector<string> vs;
			int nRet = convert_tree_double_vector_to_str_vector(tr.tr1, vs, vd.GetSize(),"*3");    
			for(int nIndex =0 ; nIndex < vs.GetSize(); nIndex++)
				out_str(vs[nIndex]);
		}
	Parameters:
		trVec	= soruce vector treenode.
		vs		= destination string vector 
		nSize	= vs's size, if nSize > trVec.dVals.GetSize(), vs will size of trvec size.
		strFmt	= format of convert double value.
	Return:
		Returns the -1 when trVec not double vector. else return the size of vs.
*/
int convert_tree_double_vector_to_str_vector(const TreeNode& trVec, vector<string>& vs, uint nSize, string strFmt)
{
	vector<double> vTemp;
	///Frank 11/24/04  v8.0166 CHECK_TYPEID_DVALS_NOT_ASSIGN
	if(!trVec || trVec.TypeID != TNVAL_TYPE_DOUBLE_VECTOR)
		return -1;
	//if(trVec)
	//	vTemp = trVec.dVals;
	vTemp = trVec.dVals;
	//END CHECK_TYPEID_DVALS_NOT_ASSIGN
	///Frank 10/27/04 v8.0156  MATRIX_OR_VECTOR_TREENODE_OUTPUT_STRING
	/*
	uint nMinSize = min(vTemp.GetSize(), nSize);
	vs.SetSize( nSize );
	for(int nIndex =0; nIndex < nMinSize; nIndex++)
	{
		vs[nIndex] = ftoa(vTemp[nIndex], strFmt);
	}
	for(nIndex = nMinSize ; nIndex < nSize ; nIndex++)
		vs[nIndex] = "--";
	
	return nMinSize;
	*/
	///Frank 10/17/06 ADD_DOUBLE_OUTPUR_FORMAT_IN_TREE_OUT
	//return convert_double_vector_to_string_vector(vTemp, vs, nSize, strFmt );
	vector<string> vsFormat;
	if(nSize)
		vsFormat.InsertAt(0,strFmt, nSize);
	return convert_double_vector_to_string_vector(vTemp, vs, nSize, vsFormat );
	///End ADD_DOUBLE_OUTPUR_FORMAT_IN_TREE_OUT
	///End  MATRIX_OR_VECTOR_TREENODE_OUTPUT_STRING
}

int convert_tree_double_vector_to_str_vector(const TreeNode& trVec, vector<string>& vs, const vector<int>& vnSignDigites) // = NULL)
{
	vector<double> vTemp;
	if(!trVec || trVec.TypeID != TNVAL_TYPE_DOUBLE_VECTOR)
		return -1;
	vTemp = trVec.dVals;
	
	///Frank 10/17/06 ADD_DOUBLE_OUTPUR_FORMAT_IN_TREE_OUT
	//return convert_double_vector_to_string_vector(vTemp, vs, vnSignDigites);	
	vector<string>  vsDoubleFormat ;
	if(vnSignDigites != NULL)
	{
		vsDoubleFormat.SetSize(vnSignDigites.GetSize());
		
		for(int n =0; n <vsDoubleFormat.GetSize() ; n++ )
		/// Iris 4/13/06 CHECK_SIGN_DIGITES_LARGE_THAN_0
			//vsDoubleFormat[n] = "*" + vnSignDigites[n];
		{
			vsDoubleFormat[n] = "*";
			if(vnSignDigites[n] > 0)
				vsDoubleFormat[n] += vnSignDigites[n];
		}
		/// End CHECK_SIGN_DIGITES_LARGE_THAN_0
		
		return convert_double_vector_to_string_vector(vTemp, vs, vTemp.GetSize(), vsDoubleFormat);	
	}
	else
		return convert_double_vector_to_string_vector(vTemp, vs, vTemp.GetSize());	
	///End ADD_DOUBLE_OUTPUR_FORMAT_IN_TREE_OUT
	
}


int convert_str_vector_to_num_vector(const vector<string>& vs, vector<double>& vd)
{
	///Sophy 12/18/2008 MOVE_CONVERT_STRINGVECTORY_TO_DOUBLEVECTOR_FROM_OC_TO_VC
	//int nSize =  vs.GetSize();
	//vd.SetSize(nSize);
	//for(int n=0 ; n< nSize; n++)
	//{
		//string str = vs[n]; str.TrimLeft(); str.TrimRight();
		//if(str.IsEmpty() || str == "--")
			//vd[n] = NANUM;
		//else
			//vd[n] = atof(vs[n]);
	//}
	//return nSize;
	return okutil_covert_str_vec_to_num_vec(&vs, &vd);
	///end MOVE_CONVERT_STRINGVECTORY_TO_DOUBLEVECTOR_FROM_OC_TO_VC
}
///Frank 10/17/06 ADD_DOUBLE_OUTPUR_FORMAT_IN_TREE_OUT
/*
///Frank 10/27/04 v8.0156  MATRIX_OR_VECTOR_TREENODE_OUTPUT_STRING
int convert_double_vector_to_string_vector(const vector<double>& vd, vector<string>& vs, uint nSize, LPCSTR lpcstrFormat )
{
	uint nMinSize = min(vd.GetSize(), nSize);
	vs.SetSize( nSize );
	
	for(int nIndex =0; nIndex < nMinSize; nIndex++)
	{
		vs[nIndex] = ftoa(vd[nIndex], lpcstrFormat);
	}
	for(nIndex = nMinSize ; nIndex < nSize ; nIndex++)
		vs[nIndex] = "--";

	return nMinSize;
}
///End  MATRIX_OR_VECTOR_TREENODE_OUTPUT_STRING
/// Iris 10/12/05 ADD_SIGNIFICANT_DIGITE
int convert_double_vector_to_string_vector(const vector<double>& vd, vector<string>& vs, const vector<int>& vnSignDigites) // = NULL)
{
	vs.SetSize(0);
	
	for(int ii=0; ii<vd.GetSize(); ii++)
	{
		int 	nSignDigite = 5;  //default significant digite is 5 here
		if(vnSignDigites && ii<vnSignDigites.GetSize() && vnSignDigites[ii]>=1 && vnSignDigites[ii]<=16 ) //the number of significant digite from 1 to 16
		{
			nSignDigite = vnSignDigites[ii];
		}
		
		string 	strFormat;
		strFormat = "%." + nSignDigite + "f";
		
		string 	strVal;
		strVal.Format(strFormat, vd[ii]);
		vs.Add(strVal);
	}
	return vs.GetSize();
}
///End ADD_SIGNIFICANT_DIGITE
*/
int convert_double_vector_to_string_vector(const vector<double>& vd, vector<string>& vs, uint nSize, vector<string> &vsFormat )
{
	/// YuI 07/05/07 can't compile
	//	uint nMinSize = min(vd.GetSize(), nSize);
	uint nVectorSize = vd.GetSize();
	uint nMinSize = min(nVectorSize, nSize);
	/// end YuI
	vs.SetSize( nSize );
	
	vector<string> vsDoubleFormat;
	if(nSize)
		vsDoubleFormat.InsertAt(0,"*",nSize);
	if(vsFormat != NULL)
		vsDoubleFormat =vsFormat;
	if(vsDoubleFormat.GetSize() < nSize)
		vsDoubleFormat.InsertAt(vsDoubleFormat.GetSize(),"*",nSize -vsDoubleFormat.GetSize());
	
	for(int nIndex =0; nIndex < nMinSize; nIndex++)
	{
		vs[nIndex] = ftoa(vd[nIndex], vsDoubleFormat[nIndex]);
	}
	for(nIndex = nMinSize ; nIndex < nSize ; nIndex++)
		vs[nIndex] = "--";

	return nMinSize;
}
///End ADD_DOUBLE_OUTPUR_FORMAT_IN_TREE_OUT

/// Iris 5/07/2008 ADD_CLASS_FOR_COL_LIST
int convert_int_vector_to_string_vector(const vector<int>& vn, vector<string>& vs)
{
	vs.SetSize(vn.GetSize());
	for(int ii = 0; ii < vn.GetSize(); ii++)
	{
		vs[ii] = vn[ii];
	}
	return vn.GetSize();
}

int convert_string_vector_to_int_vector(const vector<string>& vs, vector<int>& vn, int nNoNumericReplace)
{
	vn.SetSize(vs.GetSize());
	for(int ii = 0; ii < vs.GetSize(); ii++)
	{
		if( !is_numeric(vs[ii]) )
			vn[ii] = nNoNumericReplace;
		else
			vn[ii] = atoi(vs[ii]);
	}
	return vs.GetSize();
}

int convert_uint_vector_to_string_vector(const vector<uint>& vn, vector<string>& vs)
{
	vector<int> vInt;
	vInt = vn;
	return convert_int_vector_to_string_vector(vInt, vs);
}

int convert_string_vector_to_uint_vector(const vector<string>& vs, vector<uint>& vn, int nNoNumericReplace)
{
	vector<int> vInt;
	int 		nSize = convert_string_vector_to_int_vector(vs, vInt, nNoNumericReplace);
	vn = vInt;
	return nSize;
}

int convert_byte_vector_to_string_vector(const vector<byte>& vn, vector<string>& vs)
{
	vector<int> vInt;
	vInt = vn;
	return convert_int_vector_to_string_vector(vInt, vs);
}

int convert_string_vector_to_byte_vector(const vector<string>& vs, vector<byte>& vn, int nNoNumericReplace)
{
	vector<int> vInt;
	int 		nSize = convert_string_vector_to_int_vector(vs, vInt, nNoNumericReplace);
	vn = vInt;
	return nSize;
}
///end ADD_CLASS_FOR_COL_LIST

void str_vector_to_double_vector_treenode(TreeNode& tr, const vector<string>& vs)
{
	vector<double> vd;
	convert_str_vector_to_num_vector(vs, vd);
	tr.dVals = vd;
}
void init_vector_string(vector<string> &vsEmptyVec, int nSize, string strDefault)
{
	vsEmptyVec.SetSize(nSize);

	for(int nParaIndex =0; nParaIndex< nSize;  nParaIndex++)
	{
		vsEmptyVec[nParaIndex] = strDefault;
	}
	/*
	vsEmptyVec = strDefault;
	*/
}	

///End CONVERT_NUM_TO_STRING_VECTOR

/// SY 10/13/2004 v8.0147 IMPORT_WIZARD_CLEANUP
// Move from App_Utils.c
/// EJP 03-30-2004 v7.5826 QA70-6188 CHECK_FILE_FOR_READING
bool OpenExistingFile(file& filSrc, LPCSTR lpcszFile, UINT nOpenFlags)
{
	string strFile = lpcszFile;
	if( strFile.IsFile() )
	{
		if( filSrc.Open(lpcszFile, nOpenFlags) )
			return true;

		string strMsg;
		strMsg.Format(_L("%s\n\nThe file exists but failed to open.\nCheck if it is being used by another application."), strFile);
		MessageBox(GetWindow(), strMsg, _L("Import Wizard"), MB_OK);
	}
	return false;
}
/// end CHECK_FILE_FOR_READING

/**
	Read specified lines from a text file into an array of strings.
Example:
	StringArray saLines;
	int iError = ReadFileLines(saLines, "C:\\Origin80\\Origin.ini");
Parameters:
	saLines=Reference to a string array that will hold the lines
	lpcszFile=Name of file to read
	iNumLines=Number of lines to read into the string array. If 0 then all lines are read.
	iFirstLine=Zero based index of the first line to read into the string array.
	iSkipLines=Number of lines to skip after every one line read.
Return:
	Returns zero for success or non-zero to indicate error.  
*/
int ReadFileLines(StringArray &saLines, LPCSTR lpcszFile, uint iNumLines, uint iFirstLine, uint iSkipLines)
{
	if( NULL == lpcszFile )
		return 1; // file name required
	///Kyle 09/12/08 READ_ALL_LINES_IF_INUMLINES_IS_0_IN_FUNC_READFILELINES
	//if( 0 == iNumLines )
		//return 0; // no lines to read
	///End READ_ALL_LINES_IF_INUMLINES_IS_0_IN_FUNC_READFILELINES

	stdioFile sf;
	if( sf.Open(lpcszFile, file::modeRead | file::shareDenyRead | file::typeText) )
	{
		/// Hong 07/03/09 QA80-12534-P1 FIX_IMPWIZ_FAIL_PREVIEW_UNICODE_HEADLINES
	#ifdef			ASCIMP_SUPPORT_UNICODE
		sf.SetUniCodeType(sf.CheckUniCodeBOM());
	#endif			//ASCIMP_SUPPORT_UNICODE
		/// end FIX_IMPWIZ_FAIL_PREVIEW_UNICODE_HEADLINES
		string strLine;
               
		BOOL bCont = TRUE;
		while( iFirstLine-- && bCont )
			bCont = sf.ReadString(strLine);

		if( bCont ) // If can continue reading
		{
			int iLine = 0, iSkip;
			
			while( sf.ReadString(strLine) )
			{
				saLines.Add(strLine);
				if( iNumLines && ++iLine == iNumLines )
					break;
				
				iSkip = iSkipLines;
				while( iSkip-- && bCont )
					bCont = sf.ReadString(strLine);
			}
		}

		sf.Close();
		return 0; // success
	}
	return 1; // failed to open file
}

/**
	List all files of a specified file type found in the Origin
	App Data folder and/or in the Origin software folder. 
	
Example:
	int iRetCode;
	StringArray saResult;
	iRetCode = GetSystemFiles(saResult, "otw");
Parameters:
	saResult = the referrence of string array will receive the finding results
	lpcszExt = the file extension name to matach file finding.
Return:
	Returns TRUE for success, otherwise failure.
*/
BOOL GetSystemFiles(StringArray& saResult, LPCSTR lpcszExt)
{	
	///DSC 1/31/06 QA70-7635  v8.0366 CENTRALIZE_FIND_FILES_CODES
	/*
	// first, the application data path  
	string strAppDataPath = GetAppPath();
	BOOL bRetApp = FindFiles(saResult, strAppDataPath, lpcszExt);

	// Second, the Origin Exe path
	string strOrgExePath = GetAppPath(TRUE);
	
	// if either of tow seach succeed will return true.
	BOOL bRetExe = FindFiles(saResult, strOrgExePath, lpcszExt, true);// 2nd time will need to check already in list or not
	
	return (bRetApp || bRetExe);
	*/
	int nNumFound = okutil_find_files(&saResult, lpcszExt, NULL, true, false, ORIGIN_PATH_UNDEF, true); // remove duplicates
	return saResult.GetSize()>0? TRUE : FALSE;	
	///end CENTRALIZE_FIND_FILES_CODES
	
}

/**
		Get the path and/or just filename without extension from a string containing a path and/or
		just filename. 
	Example:
		string strFilenameWithoutExt, strFilenameWithExt;
		strFilenameWithExt = "Default.oaf";
		strFilenameWithoutExt = GetFilenameWithoutExt( strFilenameWithExt );
		ASSERT( strFilenameWithoutExt.Compare( "Default" ) == 0 );
	Parameters:
		strFilenameWithExt=Input string containing an optional path and a filename with filetype extension
	Return:
		Returns a filename without filetype extension (but with path if in original string) from an optional
		path and filename with extension.
*/
string GetFilenameWithoutExt( string strPathAndFilename )
{
	return strPathAndFilename.Left( strPathAndFilename.ReverseFind( '.' ) );
}

/**
	Get the contents of a text file.
Example:
	string strText;
	int iError = LoadTextFile(strText, "C:\\Origin80\\Origin.ini");
Parameters:
	lpcszFile=Input full path and file name to read
	iNumLines=Input number of lines to read not counting skipped lines, default 0 reads all lines (after iFirstLine) 
	iFirstLine=Input first line to read, default 0 reads first line
	iSkipLines=Input number of lines to skip for every one line read, default 0 skips no lines
Return:
	Returns the contents of a text file on success and "" on failure.  
*/
int LoadTextFile(string &strText, LPCSTR lpcszFile, uint iNumLines, uint iFirstLine, uint iSkipLines) // iNumLines = 0, iFirstLine = 0, iSkipLines = 0
{
	StringArray saLines;
	int iError = ReadFileLines(saLines, lpcszFile, iNumLines, iFirstLine, iSkipLines);
	if( 0 == iError )
	{
		strText.SetTokens(saLines, '\n');
		strText += "\n"; // EOL for last line
	}

	return iError;
}

/**
		Get the file size of a file from an input string containing a path
		and filename. 
	Example:
		string strFileSize, strDataFile = "C:\\Origin80\\Origin.ini";
		strFileSize = GetFileSize(strDataFile);
	Parameters:
		strPathAndFilename=[in] string containing a path and filename with filetype extension
		pnBytes=[out] the size in bytes of the file. NULL by default.
	Return:
		Returns a Windows like file size formatted for display. 
*/
///DSC 8/4/05 NEED_FILE_SIZE_IN_BYTES
// string GetFileSize(string strPathAndFilename)
string GetFileSize(string strPathAndFilename, uint* pnBytes) //=NULL
///end NEED_FILE_SIZE_IN_BYTES
{
	string strFileSize;
	
	WIN32_FILE_ATTRIBUTE_DATA fileInfo;
	if( GetFileAttributesEx(strPathAndFilename, 0, &fileInfo) )
	{
		///DSC 8/4/05 NEED_FILE_SIZE_IN_BYTES
		if(pnBytes)
			*pnBytes=fileInfo.nFileSizeLow;
		///end NEED_FILE_SIZE_IN_BYTES
		
		if( fileInfo.nFileSizeLow < 1024 )
			strFileSize.Format("%d bytes", fileInfo.nFileSizeLow);
		else
		{
			int nSize = fileInfo.nFileSizeLow/1024.0 + 0.5;
			if( nSize < 1024 )
				strFileSize.Format("%d KB", nSize);
			else
			{
				nSize = nSize/1024.0 + 0.5;
				strFileSize.Format("%d MB", nSize);
			}
		}
	}
	
	return strFileSize;
}

/// EJP 2008-02-05 v8.0801 QA70-11058 IW_NEED_SHOW_ALL_TEMPLATES_IN_UFF
// This general function is being added to share a majority of the code in
// GetFilenamesInFolder which is not useful for all purposes.
static int get_file_names(
	StringArray& saFileNames,
	LPCSTR lpcszPath,
	LPCSTR lpcszFileSpec,
	DWORD dwCtrl)
{
	string strPath = lpcszPath;
	if( strPath.IsEmpty() )
		strPath = GetAppPath(FALSE); // user files folder

	///Sophy 10/21/2009 FAIL_TO_GET_FILENAME_WHEN_PATH_NOT_ENDED_WITH_BACKSLASH
	if ( str_end_char(strPath) != '\\' ) //as to keep consistency with string::IsPath(), e.g. str = "F:\\New", str.IsPath, is true, need to updated to "F:\\New\\" as to make this function work
		strPath += "\\";
	///end FAIL_TO_GET_FILENAME_WHEN_PATH_NOT_ENDED_WITH_BACKSLASH
	string strFileSpec = lpcszFileSpec;
	if( strFileSpec.IsEmpty() )
		strFileSpec = "*.*"; // all files

	string strFind;
	strFind.Format("%s*.*", strPath); // tell Windows to always find *.*

	string str;
	WIN32_FIND_DATAA fd;

	HANDLE hFind = FindFirstFile(strFind, &fd);
	if( hFind != INVALID_HANDLE_VALUE )
	{
		do
		{
			if( fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
			{
				if( (dwCtrl & GFIF_FILE_RECURSIVE) && lstrcmp(fd.cFileName, ".") && lstrcmp(fd.cFileName, "..") )
				{
					str.Format("%s%s\\", strPath, fd.cFileName);
					get_file_names(saFileNames, str, lpcszFileSpec, dwCtrl);
				}
			}
			else
			{
				str = fd.cFileName;
				if( str.Match(strFileSpec) )
				{
					if( dwCtrl & GFIF_FILE_NO_PATH )
						str = fd.cFileName;
					else
						str.Format("%s%s", strPath, fd.cFileName);
	
					if( dwCtrl & GFIF_FILE_NO_EXT )
						str = GetFilenameWithoutExt(str);
	
					saFileNames.Add(str);
				}
			}
		} while( FindNextFile(hFind, &fd) );

		FindClose(hFind);
		return GFIF_NO_ERROR;
	}
	return GFIF_NO_FILES_FOUND_ERROR;
}

int GetFileNames(StringArray& saFileNames, LPCSTR lpcszPath, LPCSTR lpcszFileSpec, DWORD dwCtrl)
{
	if( GFIF_STRIP_START_PATH == (dwCtrl & (GFIF_STRIP_START_PATH|GFIF_FILE_NO_PATH)) )
	{
		StringArray saTmpFileNames;
		int nRet = get_file_names(saTmpFileNames, lpcszPath, lpcszFileSpec, dwCtrl);
		if( GFIF_NO_ERROR == nRet )
		{
			string strStartPath = lpcszPath;
			if( strStartPath.IsEmpty() )
				strStartPath = GetAppPath(FALSE);
			int nStartPathLen = strStartPath.GetLength();

			for( int i = 0; i < saTmpFileNames.GetSize(); i++ )
				saFileNames.Add(saTmpFileNames[i].Mid(nStartPathLen));
		}
		return nRet;
	}

	return get_file_names(saFileNames, lpcszPath, lpcszFileSpec, dwCtrl);
}

/// end IW_NEED_SHOW_ALL_TEMPLATES_IN_UFF

/**
		Search a windows folder adding any filenames that match a specified file filter to an output string.
		Options specify whether or not subfolders are to be recursively searched and whether or not path
		and file extension are to be included with filename.
	Example:
		string strTemplateFileList;
		GetFilenamesInFolder(strTemplateFileList, "", "*.otw", FALSE, 3);
	Parameters:
		strListOfFilenames=Output list of formatted filenames found in folder 
		lpcstrPath=Input path to start searching, default "" is path to Origin software folder  
		lpcstrFileFilter=Input file filter which may include DOS wild card characters, default is "*.*"
		bRecursive=Input option to recursively search subfolders, default is FALSE
		wDisplayOptions=Input bitwise flag specifying display options, default value GFIF_FILE_WITH_PATH
			displays path, filename and filetype, GFIF_FILE_NO_PATH displays filename and filetype without
			path, GFIF_FILE_NO_EXT displays path and filename with out filetype extension, and
			GFIF_FILE_NO_PATH | GFIF_FILE_NO_EXT displays file name without path or filetype extension
	Return:
		Returns GFIF_NO_ERROR on success or an GFIF warning or error code on failure.
*/
int GetFilenamesInFolder(
	string& strListOfFilenames,
	LPCSTR lpcstrPath,
	LPCSTR lpcstrFileFilter,
	BOOL bRecursive,
	UINT wDisplayOptions) // lpcstrPath = "", lpcstrFileFilter = "", bRecursive = FALSE, wDisplayOptions = GFIF_FILE_WITH_PATH
{
	/// EJP 2008-02-05 v8.0801 QA70-11058 IW_NEED_SHOW_ALL_TEMPLATES_IN_UFF
	/* Move this general code to a separate function for use by other utility functions.
	string strPath = lpcstrPath;
	if( strPath.IsEmpty() )
		strPath = GetAppPath(TRUE);
	string strFileFilter = lpcstrFileFilter;
	if( strFileFilter.IsEmpty() )
		strFileFilter = "*.*";
	string strSearchPathFilter;
	strSearchPathFilter.Format( "%s*.*", strPath );             // Build search start path\file name
		
	WIN32_FIND_DATAA find;

	HANDLE hFile = FindFirstFile(strSearchPathFilter, &find);   // Find first file/folder that matches
	if( hFile != INVALID_HANDLE_VALUE )                         // If valid handle...
	{
		string strFileFound;
		do                                                      // Do while next file/folder is found...
		{
			if( find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )                     // If folder is next...                     
			{
				if( bRecursive )                                                       // If user wants to recurse...
				{
					strFileFound = find.cFileName;
					if( strFileFound.Compare(".") && strFileFound.Compare("..") )      // If folder is not "." or ".." 
					{
						strFileFound.Format("%s%s\\", strPath, find.cFileName);
						GetFilenamesInFolder(strListOfFilenames, strFileFound,
							strFileFilter, TRUE, wDisplayOptions);                     // Recurse into subfolder
					}
				}
			}
			else                                                                       // Else file is next...
			{
				strFileFound = find.cFileName; 
				if( strFileFound.Match(strFileFilter) )                                // If file name matches file filter...
				{
					if( !(wDisplayOptions & GFIF_FILE_NO_PATH) )                  // If user wants path...
						strFileFound.Format("%s%s", strPath, strFileFound);            // Else use path and filename 
					if( wDisplayOptions & GFIF_FILE_NO_EXT )                      // If user does not want file extension...
						strFileFound = GetFilenameWithoutExt(strFileFound);          // Strip off file extension from filename
					if( !strListOfFilenames.IsEmpty() )                                           // If list already has item...
						strListOfFilenames += "|";                                     // Append token separator
					strListOfFilenames += strFileFound;                                // Append newly found filename to list
				}
			}
		} while( FindNextFile( hFile, &find ) );                // While next file is found... 

		FindClose( hFile );                                     // Close find
		
		return GFIF_NO_ERROR;
	}

	return GFIF_NO_FILES_FOUND_ERROR;
	*/
	DWORD dwCtrl = wDisplayOptions;
	if( bRecursive )
		dwCtrl |= GFIF_FILE_RECURSIVE;

	StringArray saFileNames;
	int nRet = GetFileNames(saFileNames, lpcstrPath, lpcstrFileFilter, dwCtrl);
	if( GFIF_NO_ERROR == nRet )
	{
		strListOfFilenames = saFileNames[0];
		for( int i = 1; i < saFileNames.GetSize(); i++ )
		{
			strListOfFilenames += "|";
			strListOfFilenames += saFileNames[i];
		}
	}
	return nRet;
	/// end IW_NEED_SHOW_ALL_TEMPLATES_IN_UFF
}
/// end IMPORT_WIZARD_CLEANUP
BOOL XOR(bool b1, bool b2)
{
	return ((b1 && !b2) || (!b1 && b2));
}

/// EJP 12-20-2004 v8.0177 UTIL_FUNC_CONV_CR_TO_CRLF
bool check_convert_CR_str_to_CRLF(string& str)
{
	int n = str.Find('\n');
	if( n < 0 || (0 < n && '\r' == str[n - 1]) )
		return false; // '\n' not found OR char before it is not '\r'
	str.Replace("\n", "\r\n");
	return true;
}
/// end UTIL_FUNC_CONV_CR_TO_CRLF


///DSC 2/7/05 v8.0190 CONVERT_STRING_TO_TAG_NAME
// remove characters not allowed in tag name
string cvt_str_to_tag_name(LPCTSTR lpcszStr)
{	
	string strTemp = lpcszStr;
	
	//remove space
	strTemp.Replace(" ", "");
	
	// example (*.fdf) -> fdf
	strTemp.Replace("(", "");
	strTemp.Replace(")", "");
	strTemp.Replace(".", "");
	strTemp.Replace("*", "");
	
	strTemp.Replace("?", "");
	
	
	return strTemp;	
}
///end CONVERT_STRING_TO_TAG_NAME



///Joseph 05/09/07 NOT_USE_THIS_FUNCTION_ANY_MORE
//this function now not used and can't work
/*
/// Frank 1/22/05 v8.0185c  FUNCTION_FINDFOLDER_TO_TREENODE_OR_VECTOR
int FindFolders(TreeNode &tr, LPCSTR lpcszPath, bool bRecursive, string strTagnamePrefix, int nSubFolderLevel)
{
	string strPath = lpcszPath;
	if(!tr)
		return -1;
	
	int	nCount = 0;
	vector<string> vsFolder;
	nCount += FindFolders(vsFolder, strPath);
	if(nSubFolderLevel >0)
		strTagnamePrefix += nSubFolderLevel;
	for(int n =0; n<vsFolder.GetSize(); n++)
	{
		string strTagname = strTagnamePrefix + "Folder" + n;
		TreeNode trFolder = tr.AddNode(strTagname);
		trFolder.SetAttribute(STR_LABEL_ATTRIB, vsFolder[n]);  
		trFolder.SetAttribute(STR_DISPLAY_ATTRIB, IDI_FOLDER_CLOSED);	///DG FOLDER_WITH_DISPLAY_ICON
		
		if(bRecursive)
			nCount += FindFolders(trFolder,strPath + vsFolder[n] + "\\", true, "sub", nSubFolderLevel+1 );
	}
	return nCount;
}

int FindFolders(vector<string> &vsFolderName, LPCSTR lpcszPath)
{
	string strPath = lpcszPath;
	vsFolderName.RemoveAll();
	if(!strPath.IsPath())
		return -1;
	
	vector<string> vsStorageName;
	/// DSC 6/27/05	CONSTRUCT_THEME_FILE_FROM_COMPOSITE_NAME
	//FindFiles(vsStorageName, strPath,NULL);
	FindFiles(vsStorageName, strPath, "*.*");
	///end CONSTRUCT_THEME_FILE_FROM_COMPOSITE_NAME
	string strTemp;
	for(int nIndex =0 ; nIndex < vsStorageName.GetSize(); nIndex++)
	{
		string strFileName = vsStorageName[nIndex];
		strTemp = strPath + strFileName;
		if(strTemp.IsPath() && strFileName.Find('.') != 0)
			vsFolderName.Add(strFileName);
	}
	return vsFolderName.GetSize();
}
/// End  FUNCTION_FINDFOLDER_TO_TREENODE_OR_VECTOR
*/
///End NOT_USE_THIS_FUNCTION_ANY_MORE

///DSC 1/17/05 GET_ORIGIN_PATH
/*
string get_origin_path(int nIniPath, string strSubPath)
{
	string strIniFilePath;
	switch(nIniPath)
	{
	case USER_FOLDER:
		//default is user inifile
		strIniFilePath=GET_USER_FOLDER;
		break;
	case ALL_USER_FOLDER:
		strIniFilePath=get_alluserfolder_path(true);
		break;
	default:
		//---- CPY 1/6/04 v8.0183 NLFIT_NOT_WORKING_NEED_CLEAN_UP
		strIniFilePath = GET_SYSTEM_FOLDER;
		//----
		break;
	}
	if(!strSubPath.IsEmpty())
		strIniFilePath += strSubPath + "\\";
	
	return strIniFilePath;
}
*/
// uses external function GetOriginPath(int nPathType);
// string get_origin_path(int nPathType, string strSubPath)//=""
///DSC 3/7/05 v8.0201 MOVE_TO_OKUTIL
/* 
string get_origin_path(int nPathType, LPCSTR lpcszSubPath)//=NULL 
{
	string strOrgPath;
	strOrgPath = GetOriginPath(nPathType);

	//if(!strSubPath.IsEmpty())
	if(lpcszSubPath && *lpcszSubPath!='\0')
	{
		string strSubPath=lpcszSubPath;
		///DG 2/22/05 trim junk "\\"
		strSubPath.TrimLeft("\\");
		strSubPath.TrimRight("\\");
		///end
		
		if(!strOrgPath.IsEmpty())
			strOrgPath += strSubPath + "\\";
	}
	
	return strOrgPath;
	
}
*/
///end MOVE_TO_OKUTIL
///end GET_ORIGIN_PATH



///Forest 3/3/05 ADD_FUNCTION_TO_GET_ORIGINC_TYPE_LIST
int get_origin_c_data_types(vector<string>& vsDataTypes)
{
	//best arranged types in ascending order for the convinence of user selection
	vector<string> vsTypes = {
		"bool", "BOOL", "byte", "BYTE",
		"char","double", "DWORD","float",
		"int", "long", "LONG", "LPCSTR", "LPSTR", "matrix",
		"short", "short int","signed short int","size_t", "string", "Tree", "TreeNode",
		"uint", "UINT", "unsigned int", "unsigned short", "unsigned short int",
		"ushort", "vector", "void",	"WORD"};
	vsDataTypes = vsTypes;
	return	vsTypes.GetSize();
}
///End ADD_FUNCTION_TO_GET_ORIGINC_TYPE_LIST


//-------- CPY 3/30/05
void set_reg_value(LPCSTR lpcszRegPath, LPCSTR lpcszDataName, LPCSTR lpcszDataValue, int nHEKY)// = HKEY_CURRENT_USER)
{
	Registry reg(nHEKY);
	string strKey = GetRegKey() + "\\" + lpcszRegPath + "\\";
	reg.SetValue(strKey, lpcszDataName, lpcszDataValue);
}
string get_reg_value(LPCSTR lpcszRegPath, LPCSTR lpcszKeyName, int nHEKY)// = HKEY_CURRENT_USER)
{
	Registry reg(nHEKY);
	string strKey = GetRegKey() + "\\" + lpcszRegPath + "\\";
	string str;
	if(reg.GetValue(strKey, lpcszKeyName, str))
		return str;
	
	return "";
}
//--------- end

///DSC 6/16/05 ADD_SORT_XF_LIST_OPTIONS
// it may be better to add an option to sort in okutil_find_files, or sort when creating/updating the cashed list
void sort_composite_name_vs(vector<string>& vsNames, DWORD dwListOptions, DWORD dwStandardOptions)//=LIST_XF_SORT_DISPLAY, =SORT_ASCENDING | SORT_NUMERIC_SUFFIX
{	
	if(LIST_XF_SORT_DISPLAY & dwListOptions)
	{
		/// sort by composite name, but put User first, then Group, then System
		vector<string> vsProject, vsCustom, vsUser, vsGroup, vsSystem;
		
		// need array of array of strings
		for(int ii=0; ii<vsNames.GetSize(); ii++)
		{
			int nPathType;
			string strChar;
			okutil_separate_composite_name(vsNames[ii], &nPathType, NULL);
			
			// separate
			if(ORIGIN_PATH_PROJECT == nPathType)
				vsProject.Add(vsNames[ii]);
			if(ORIGIN_PATH_CUSTOM == nPathType)
				vsCustom.Add(vsNames[ii]);
			if(ORIGIN_PATH_USER == nPathType)
				vsUser.Add(vsNames[ii]);	
			else if(ORIGIN_PATH_GROUP == nPathType)
				vsGroup.Add(vsNames[ii]);				
			else if(ORIGIN_PATH_SYSTEM == nPathType)
				vsSystem.Add(vsNames[ii]);
			
		}
		
		// sort
		vsProject.Sort(dwStandardOptions);
		vsCustom.Sort(dwStandardOptions);
		vsUser.Sort(dwStandardOptions);
		vsGroup.Sort(dwStandardOptions);
		vsSystem.Sort(dwStandardOptions);
		
		// put back together
		int nSizeSoFar = 0;
		for(ii=0; ii<vsProject.GetSize(); ii++)
			vsNames[ii]=vsProject[ii];
		nSizeSoFar = vsProject.GetSize();
		
		for(ii=0; ii<vsCustom.GetSize(); ii++)
			vsNames[nSizeSoFar + ii] = vsCustom[ii];
		nSizeSoFar += vsCustom.GetSize();
		
		for(ii=0; ii<vsUser.GetSize(); ii++)
			vsNames[nSizeSoFar + ii] = vsUser[ii];
		nSizeSoFar += vsUser.GetSize();
		
		for(ii=0; ii<vsGroup.GetSize(); ii++)
			vsNames[nSizeSoFar + ii] = vsGroup[ii];
		nSizeSoFar += vsGroup.GetSize();
		
		for(ii=0; ii<vsSystem.GetSize(); ii++)
			vsNames[nSizeSoFar + ii] = vsSystem[ii];
	
	}

	if(LIST_XF_SORT_NAME & dwListOptions)	
	{	
		//this is a trick  to sort by name and tag along the full composite name.
		//to do properly, need to create 2 arrays and nest sort
		
		/// add prefix
		for(int ii=0; ii<vsNames.GetSize(); ii++)
		{
			string strNameOnly = okutil_separate_composite_name(vsNames[ii], NULL, NULL);
			vsNames[ii]=strNameOnly + "|" + vsNames[ii];	
		}
		
		// sort
		vsNames.Sort(dwStandardOptions);
		
		/// remove prefix
		for(ii=0; ii<vsNames.GetSize(); ii++)
		{
			int nPos = vsNames[ii].Find('|');
			vsNames[ii]=vsNames[ii].Mid(nPos+1);
		}
	}
	
}
///end ADD_SORT_XF_LIST_OPTIONS	

////////////////////////////  MOVE_TO_OKUTIL_DLL  /////////////////////////////////////		
////////////////////////////  MOVE_TO_OKUTIL_DLL  /////////////////////////////////////		
////////////////////////////  MOVE_TO_OKUTIL_DLL  /////////////////////////////////////		
////////////////////////////  MOVE_TO_OKUTIL_DLL  /////////////////////////////////////		
////////////////////////////  MOVE_TO_OKUTIL_DLL  /////////////////////////////////////		
////////////////////////////  MOVE_TO_OKUTIL_DLL  /////////////////////////////////////		
////////////////////////////  MOVE_TO_OKUTIL_DLL  /////////////////////////////////////		
///DSC 3/9/05 QA70-7479 MOVE_TO_OKUTIL_DLL
//-- these functions were renamed, and will eventually be moved to okutil dll.




/*
//-- Creates a filepath given FileType (enum ORIGIN_PATH_TYPE), subfolder, name and extension.
//-- The resulting file at filepath may not exist
//-- If the path does not exist, or if the path is the same as the USER path (and nPathType!= User path),
//-- then return FALSE, and empty string strFilePath.
//bool okutil_make_file_path(string& strFilePath, int nPathType, LPCSTR lpcszSubFolder, LPCSTR lpcszFunctionName, LPCSTR lpcszExt, bool bCheckExist) //=NULL, true
bool okutil_make_file_path(string* pstrFilePath, int nPathType, LPCSTR lpcszSubFolder, LPCSTR lpcszFunctionName, LPCSTR lpcszExt, bool bCheckExist) //=NULL, true
{	
	if(!lpcszFunctionName)		
	{
		*pstrFilePath="";
		return false;
	}
	
	//-- check if nPathType folder exists, and if nPathType!=USER_FOLDER, also check path is not User path.
	string strPath = GetOriginPath(nPathType, TRUE);
	if(strPath.IsEmpty())
	{
		*pstrFilePath = "";
		return false;//either path not exist, or path is same as user path
	}
	
	//-- get filepath
	//strPath = get_origin_path(nPathType, lpcszSubFolder);
	string strSubFolder = lpcszSubFolder;
	strSubFolder.TrimRight("\\");
	if(!strSubFolder.IsEmpty())
		strPath += strSubFolder + "\\";
	
	//-- form file path
	if(lpcszExt)
	{
		// strFilePath->Format("%s%s%s", strPath, lpcszFunctionName, lpcszExt);
		string strTemp;
		strTemp.Format("%s%s%s", strPath, lpcszFunctionName, lpcszExt);
		*pstrFilePath = strTemp;
	}
	else
	{
		//strFilePath = strPath + lpcszFunctionName;
		strPath+=lpcszFunctionName;
		*pstrFilePath = strPath;
	}
	
	if(bCheckExist)
	{
		//return strFilePath.IsFile();
		string strTemp = *pstrFilePath;
		return strTemp.IsFile();
	}
	
	return true;
}
*/

#endif //_OC_VER >= 0x0800
///Frank 9/14/05 MOVE_FROM_LT_PE_STATIC
int page_type_2_int(string strType)
{
	if( strType.IsEmpty() )
		return 0; // any page
	
	strType.MakeUpper();
	switch( strType[0] )
	{
	case 'W':
		return EXIST_WKS;
	case 'P': case 'G':
		return EXIST_GRAPH;
	case 'M':
		return EXIST_MATRIX;
	case 'N':
		return EXIST_NOTES;
	case 'L':
		return EXIST_LAYOUT;
	}
	return 0;
}
///Ebd MOVE_FROM_LT_PE_STATIC

//--- CPY 9/13/06 grpah export should be using new XF, should not use this anymore
/*
//////////////////////////////////////////////////////
// OC functions to be used from LabTalk directly
#pragma labtalk(1) //--- CPY 7/26/05 hide/show (0/1) all functions in this file from LT access, as XF should be used instead

int ExportActiveGraphPageToImage()
{
	PageBase pbActive;
	pbActive = Project.Pages();
	if( EXIST_PLOT != pbActive.GetType() && EXIST_LAYOUT != pbActive.GetType() )
		return 1; // invalid page type
	string strPgName = pbActive.GetName();
	
	using FDlog = LabTalk.FDLog;
	using Image = LabTalk.Image;

	FDLogInit(); // call sys_utils func		

	FDlog.CheckName$ = SHOW_EXPORT_OPTIONS;
	FDlog.CheckStatus = Image.ShowOptions;
	FDlog.Default$ = strPgName;
	FDlog.UseGroup("Image");
	Image.GetExtList("z","e");

	char szUseType[MAX_PATH];
	if( !LT_get_str( "%z", szUseType, sizeof(szUseType) ) )
		return 1;
	FDlog.UseType(szUseType);

	if( FDlog.SaveAs("a") )
		return 1; // user canceled or error

	string strFileName;
	strFileName.Format("%s%s", FDlog.Path$, FDlog.Default$);

	bool bShowOptions = (FDlog.CheckStatus ? true : false);
	
	Page pg(strPgName);
	/// EJP 04-14-2004 v7.5857 QA70-5587 FAIL_TO_EXPORT_1200DPI_BITMAP
	///	if( !export_page_to_image(pg, strFileName, FDlog.DefTypeExt$, bShowOptions) )
	///	{
	///		/// EJP 11-20-2003 v7.5764 QA70-5587 FAIL_TO_EXPORT_1200DPI_BITMAP
	///		double dErr;
	///		if( LT_get_var("imgexp", &dErr) )
	///			ImageExportErrorMessageBox((int)dErr);
	///		/// end FAIL_TO_EXPORT_1200DPI_BITMAP
	///		return 1;
	///	}
	if( export_page_to_image(pg, strFileName, FDlog.DefTypeExt$, bShowOptions) )
	{
		int nErr;
		if( 0 == get_export_page_to_image_error(&nErr) && nErr > 1 )
			ImageExportErrorMessageBox(nErr);
	}
	else
	{
		MessageBox(GetWindow(), _L("The Origin C function \"export_page_to_image\" failed."), _L("Origin Image Export"));
	}
	/// end FAIL_TO_EXPORT_1200DPI_BITMAP

	// Copy export settings into page.info
	Tree trSettings;
	if( !tree_read_image_export_settings(trSettings, FDlog.DefTypeExt$) )
		return 1;
	if( !tree_set_page_image_export_settings(trSettings, pg, FDlog.DefTypeExt$) )
		return 1;
	return 0;
}
*/

/// EJP 2006-01-27 v8.0362 QA70-7921 MULTI_FILE_IMPORT_WITH_XF
void file_name_array_to_str(string& strDst, const StringArray& saSrc)
{
	strDst.Empty();
	
	if( 0 == saSrc.GetSize() )
		return; // nothing to do

	string strTmp;
	for( int nIndex = 0; nIndex < saSrc.GetSize(); nIndex++ )
	{
		//strTmp.Format("\"%s\"\r\n", saSrc[nIndex]);
		strTmp.Format("%s\r\n", saSrc[nIndex]);// Hong 9/13/06 NO_NEED_ADD_DOUBLE_QUOTATION
		strDst += strTmp;
	}
	strDst.TrimRight("\r\n"); // last delim is not needed
}
/// end MULTI_FILE_IMPORT_WITH_XF

/// Iris 6/05/06 SET_WORK_DIR_AS_HISTORY_SAVE_PATH
string get_current_working_directory()
{
	INIFile ini(STR_ORIGIN_INI_FILE_NAME);
	string str = ini.ReadString("Config","CurrentWorkingDirectory");
	return str;	
}
///End SET_WORK_DIR_AS_HISTORY_SAVE_PATH

///Joe 6/26/06  ADD_STR_SEPARATE

int str_separate(LPCSTR lpcszStr, LPCSTR lpcszSep, vector<string>& vsSections)
{
	///------ Folger 04/23/10 QA81-15347 LT_ACCESS_TO_WKS_SELECTION_BY_XF
	/*
	string strSource(lpcszStr);  
	string strSep(lcpszSep);      
	int nIndex;                  
	int nSepLength = strSep.GetLength();
	int nSourceLength = strSource.GetLength();
	int nCurrent;
	
	for(;nIndex >= 0;)
	{
		nIndex = strSource.Find(strSep,nCurrent);
		if(nIndex >= 0)
		{
			string strCurrentSec;
			strCurrentSec = strSource.Mid(nCurrent,nIndex - nCurrent);
			vsSections.Add(strCurrentSec);
			nCurrent = nIndex + nSepLength;
		}
	}
	string strSourceEnd = strSource.Mid(nCurrent,nSourceLength);
	vsSections.Add(strSourceEnd);
	
	return vsSections.GetSize();
	*/
	return ocu_separate_by_str(lpcszStr, &vsSections, lpcszSep);
	///------ End LT_ACCESS_TO_WKS_SELECTION_BY_XF
}
///End ADD_STR_SEPARATE
///Joe 8/24/06 ADD_STR_COMBINE_BY_TOKENS

///Joseph 05/25/07 SHOULD_USE_REFERENCE_ON_TRANSFOR_BIG_OBJECT
//string str_combine(vector<string> vsSource, LPCSTR lcpszSep)
string str_combine(const vector<string>& vsSource, LPCSTR lpcszSep)
///End SHOULD_USE_REFERENCE_ON_TRANSFOR_BIG_OBJECT

{
	///------ Folger 04/23/10 QA81-15347 LT_ACCESS_TO_WKS_SELECTION_BY_XF
	/*
	string strDest;
	string strSep(lcpszSep);
	int nSize = vsSource.GetSize();
	for(int ii=0; ii<(nSize-1);ii++)
	{
		strDest = strDest + vsSource[ii] + strSep;
	}
	if(nSize > 0)
		strDest += vsSource[nSize -1];
	return strDest;
	*/
	string		str;
	ocu_set_tokens_by_str(str, &vsSource, lpcszSep);
	return str;
	///------ End LT_ACCESS_TO_WKS_SELECTION_BY_XF
}
///End ADD_STR_COMBINE_BY_TOKENS
/// Iris 7/20/06 GET_IMAGE_FILE_TYPE_LIST
bool get_export_image_types(StringArray& saImgTypes)
{
	using FDlog = LabTalk.FDLog;
	using Image = LabTalk.Image;
	
	// Put supported Raster Export file extension list into %Z
	Image.GetExtList("z","e"); // e = export, re = reaster export, ve = vector export, i = import
	char sz[MAX_PATH];
	if( !LT_get_str("%z", sz, MAX_PATH) )
		return false;
	
	// Setup FDlog with all the file types in the Image group
	if( FDlog.UseGroup("Image") )
		return false;
	
	// Remove all file types not in the supported extension list
	if( FDlog.UseType(sz) )
		return false;
	
	// Put all remaining file types into the string array
	string str;
	for( int nType = 1; nType <= FDlog.NumTypes; nType++ )
	{
		str.Format("FDlog.Type%d$", nType);
		if( LT_get_str(str, sz, MAX_PATH) )
		{
			str = sz;
			str.Delete(0); // delete '['
			int n = str.Find(']');
			str = str.Left(n);
			
			saImgTypes.Add(str);
		}
	}
	return true;

}
///end GET_IMAGE_FILE_TYPE_LIST
/// Hong 9/12/06 GET_FILE_LIST
/// Hong 10/30/06 ADD_SOPPURT_FIRST_INVALID_FILE_INDEX
//int separate_multiline_files(LPCSTR lpcszStr, vector<string>& vsFiles)
int separate_multiline_files(LPCSTR lpcszStr, vector<string>& vsFiles, int* pnInvalidFile)//= NULL
/// end ADD_SOPPURT_FIRST_INVALID_FILE_INDEX
{
	string strSource(lpcszStr);
	strSource.GetTokens(vsFiles, '\n');
	bool bOnce = true;// Hong 10/30/06 ADD_SOPPURT_FIRST_INVALID_FILE_INDEX
	for(int ii=0; ii < vsFiles.GetSize(); ii++)
	{
		vsFiles[ii].TrimLeft();
		vsFiles[ii].TrimRight();
		/// Hong 12/06/07 v8.0762 IMPORT_SUPPORT_RELATIVE_PATH_FOR_REIMPORT_SAMPLE_REQUIREMENT
		//if(!vsFiles[ii].IsFile())
		string strRealFileName = cvt_predefined_path_to_real_path(vsFiles[ii]);
		if (!strRealFileName.IsFile())
		/// end IMPORT_SUPPORT_RELATIVE_PATH_FOR_REIMPORT_SAMPLE_REQUIREMENT		
		{
			/// Hong 10/30/06 ADD_SOPPURT_FIRST_INVALID_FILE_INDEX
			/// Hong 11/1/06 IGNORE_EMPTH_STRING
			//if( bOnce && &nInvalidFile != NULL )
			if( bOnce && pnInvalidFile != NULL && !vsFiles[ii].IsEmpty())
			/// end IGNORE_EMPTH_STRING
			{
				*pnInvalidFile = ii + 1;
				bOnce = false;
			}
			/// end ADD_SOPPURT_FIRST_INVALID_FILE_INDEX
			vsFiles.RemoveAt(ii, 1);
			--ii;
		}
	}
	return vsFiles.GetSize();
}
/// end GET_FILE_LIST
///Jasmine 10/13/06 GET_FILE_EXT_DESC
bool get_file_ext_desc(LPCSTR lpcszFiletype, string& strExt, string* pstrDesc, bool bUpper)//= NULL, = false 
{
	string strFiletype(lpcszFiletype);
	int nPos = strFiletype.Find("*."), nMinLen = 3;//suppose the shortest extension is *.*
	if(nPos == -1)
		return error_report("Invalid Format!");
	if(pstrDesc)
	{
		string strDesc = strFiletype.Left(nPos);
		int nLen = strDesc.GetLength();	
		strDesc.TrimRight("(");
		strDesc.TrimLeft(); 
		strDesc.TrimRight();
		strDesc.TrimLeft("[");
		strDesc.TrimRight("]");
		*pstrDesc = strDesc;
	}	
	strExt = strFiletype;
	strExt.Delete(0,nPos);
	int n1 = strExt.Find(")");
	nPos = n1 >= nMinLen? n1 : -1;
	int n2 = strExt.Find("]");
	nPos = n2 >= nMinLen && (nPos<nMinLen || n2<nPos)? n2 : nPos;
	if(nPos >= nMinLen)
		strExt = strExt.Left(nPos);	
	if(bUpper)
		strExt.MakeUpper();
	else
		strExt.MakeLower();
	return true;
}
///End

///Cheney 2006-11-10 MOVE_IS_EMPTY_OR_UNASSIGN_FROM_EXPASC
bool is_empty_or_unassigned(LPCSTR lpcsz)
{
	string str = lpcsz;
	str.TrimLeft();
	str.TrimRight();
	if(str.IsEmpty())
		return true;
	return okutil_cvt_str_to_predefined_type(str) == PDS_UNASSIGNED? true:false;
}
///end MOVE_IS_EMPTY_OR_UNASSIGN_FROM_EXPASC

///Jasmine 12/12/06 FIND_CONTIGUOUS_RANGE
int find_contiguous_range(const vector<int>& vn, int nValue, vector<uint>& uBegins, vector<uint>& uEnds)
{
	vector<uint> vnIndeces;
	vn.Find(vnIndeces, nValue);
	return find_contiguous_range(vnIndeces, uBegins, uEnds);	
}
//------ Folger 01/18/08 SHOULD_SORT_INPUT_VECTOR_BEFORE_FIND_CONTIGUOUS_RANGE
//int find_contiguous_range(const vector<uint>& vnIndeces, vector<uint>& uBegins, vector<uint>& uEnds)
int find_contiguous_range(vector<uint> vnIndeces, vector<uint>& uBegins, vector<uint>& uEnds)
//------
{
	vnIndeces.Sort();		//------ Folger 01/18/08 SHOULD_SORT_INPUT_VECTOR_BEFORE_FIND_CONTIGUOUS_RANGE
	int nSize = vnIndeces.GetSize();
	if(1 > nSize)
		return -1;
	uBegins.RemoveAll();
	uEnds.RemoveAll();
	uBegins.Add(vnIndeces[0]);
	for(int ii = 1; ii < nSize; ii++)
	{
		if(vnIndeces[ii] - vnIndeces[ii-1] > 1)//not contiguous, a new range
		{
			uEnds.Add(vnIndeces[ii-1]);
			uBegins.Add(vnIndeces[ii]);
		}
	}
	uEnds.Add(vnIndeces[ii-1]);
	return uBegins.GetSize();
}
///End FIND_CONTIGUOUS_RANGE

//---- CPY 4/23/07 GRAPH_EXPORT_SPEED_TESTING
void show_time(LPCSTR lpcsz)
{
	static DWORD l_dwLast;
	if(NULL == lpcsz)
	{
		l_dwLast = GetTickCount();
		SYSTEMTIME st;
		get_current_time(st, true);
		double dDate;
		SystemTimeToJulianDate(&dDate, &st);
		string strDate = get_date_str(dDate, LDF_SHORT_AND_HHMM_SEPARCOLON);
		printf("Time counting started at %s\n", strDate);
	}
	else
	{
		double tt = GetTickCount();
		tt -= l_dwLast;
		printf("%s: %7.3f sec.\n", lpcsz, tt/1000.);
	}
}
//----


//----Jake 05/31/07 STATIC_GET_PATH_FROM_INI
//string _get_path_from_ini_file(const INIFile& ini,LPCSTR lpcszFileGroup,bool bSavePath)
//static bool _access_path_from_ini_file(const INIFile& ini,LPCSTR lpcszFileGroup, string &strFilePath, bool bSavePath, bool bRead = true)
static bool _access_path_from_ini_file(const INIFileEx& ini,LPCSTR lpcszFileGroup, string &strFilePath, bool bSavePath, bool bRead = true)///Jake 10/07/07 USE_INIFILEEX_CLASS
{
//	string 		strPath;	///Folger 06/13/07 SET_FILE_GROUP_DEFAULT_PATH
	LPCSTR 		lpcszSection = "FileExt";
	int nKeyNum = ini.ReadInt(lpcszSection,"NumGroups",0);
	for(int ii = 1; ii <= nKeyNum; ii++)
	{
		string strKeyName;
		strKeyName.Format("%d_Name",ii);
		string strKeyVal = ini.ReadString(lpcszSection,strKeyName);
		if(strKeyVal.CompareNoCase(lpcszFileGroup) == 0)
		{
			if(bSavePath)
				strKeyName.Format("%d_SavePath",ii);
			else
				strKeyName.Format("%d_DefPath",ii);
			///Folger 06/13/07 SET_FILE_GROUP_DEFAULT_PATH
			///Folger 06/18/07 CORRECT_ERROR_COMMENT
			//strFilePath = ini.ReadString(lpcszSection,strKeyName);
			//return strPath;
			///End CORRECT_ERROR_COMMENT
			if (bRead)
			{
				strFilePath = ini.ReadString(lpcszSection,strKeyName);
			}
			else
			{
				ini.WriteString(lpcszSection, strKeyName, strFilePath);
			}
			//return strPath;
			return true;
			///Folger 06/13/07 SET_FILE_GROUP_DEFAULT_PATH
		}
	}
	///Folger 06/18/07 CORRECT_ERROR_COMMENT
	//return strPath;
	return false;	///Folger 06/13/07 SET_FILE_GROUP_DEFAULT_PATH
	///End CORRECT_ERROR_COMMENT
}



//----Jake 05/23/07 GET_SAVE_PATH_FROM_ORIGIN_INI

string get_file_group_default_path(LPCSTR lpcszFileGroup,bool bSavePath)///Jake 05/28/07 MODIFY_VARIABLE_NAME
{
	string 		strSavePath;
	///Jake 10/07/07 V8.0656 CORRECT_CODES_USING_INIFILEEX_CLASS
	/*
	string		strINIPath;
	file 		fTestPath;
	
	strINIPath = GetAppPath(FALSE) + "origin.ini";//get path from user folder ini file
	//if(fTestPath.Open(strINIPath, file::modeRead))
	//{
		//fTestPath.Close();
	if(strINIPath.IsFile())
	{
		INIFile     ini(strINIPath);
		///Folger 06/18/07 CORRECT_ERROR_COMMENT
		//strSavePath = _get_path_from_ini_file(ini,lpcszFileGroup,bSavePath);//----Jake 05/31/07 GET_PATH_FROM_INI
		_access_path_from_ini_file(ini, lpcszFileGroup, strSavePath, bSavePath);	///Folger 06/13/07 SET_FILE_GROUP_DEFAULT_PATH
		///End CORRECT_ERROR_COMMENT
		if(strSavePath == "")//if can't get path from user folder, try system folder file
		{
			strINIPath = GetAppPath(TRUE) + "origin.ini";
			//if(fTestPath.Open(strINIPath, file::modeRead))
			//{
				//fTestPath.Close();
			if(strINIPath.IsFile())
			{
				INIFile     ini(strINIPath);
				///Folger 06/18/07 CORRECT_ERROR_COMMENT
				//strSavePath = _get_path_from_ini_file(ini,lpcszFileGroup,bSavePath);//----Jake 05/31/07 GET_PATH_FROM_INI
				_access_path_from_ini_file(ini, lpcszFileGroup, strSavePath, bSavePath);	///Folger 06/13/07 SET_FILE_GROUP_DEFAULT_PATH
				///End CORRECT_ERROR_COMMENT
				if(strSavePath == "")
					/// Nicole 07/05/2007 v8.0655 REMOVE_SPACE_FOR_LOCATION_STRING
					//error_report(_L("Failed to get save path from File Group "));
					error_report(_L("Failed to get save path from File Group"));
					/// END REMOVE_SPACE_FOR_LOCATION_STRING
			}
			else
				error_report(_L("Failed to open origin ini file."));
		}
	}
	else
	{
		strINIPath = GetAppPath(TRUE) + "origin.ini";
		//if(fTestPath.Open(strINIPath, file::modeRead))
		//{
			//fTestPath.Close();
		if(strINIPath.IsFile())
		{
			INIFile     ini(strINIPath);
			///Folger 06/18/07 CORRECT_ERROR_COMMENT
			//strSavePath = _get_path_from_ini_file(ini,lpcszFileGroup,bSavePath);//----Jake 05/31/07 GET_PATH_FROM_INI
			_access_path_from_ini_file(ini, lpcszFileGroup, strSavePath, bSavePath);	///Folger 06/13/07 SET_FILE_GROUP_DEFAULT_PATH
			///End CORRECT_ERROR_COMMENT
			if(strSavePath == "")
				error_report(_L("Failed to get save path from File Group."));
		}
		else
			error_report(_L("Failed to open origin ini file."));
	}
	*/
	INIFileEx ini(STR_ORIGIN_INI_FILE_NAME);
	_access_path_from_ini_file(ini, lpcszFileGroup, strSavePath, bSavePath);
	///end CORRECT_CODES_USING_INIFILEEX_CLASS
	return strSavePath;
}

//----end GET_SAVE_PATH_FROM_ORIGIN_INI

//----end STATIC_GET_PATH_FROM_INI

///Folger 06/13/07 SET_FILE_GROUP_DEFAULT_PATH

//bool set_file_group_default_path(LPCSTR lpcszFileGroup, LPCSTR lpcszFilePath, bool bSavePath)
//{
	//string strSavePath;
	//string strINIPath;
	//
	//strINIPath = GetAppPath() + "origin.ini";
	//if(strINIPath.IsFile())
	//{
		//INIFile ini(strINIPath);
		//if(!_access_path_from_ini_file(ini, lpcszFileGroup, lpcszFilePath, bSavePath, false))//if can't set path from user folder, try system folder file
		//{
			//strINIPath = GetAppPath(TRUE) + "origin.ini";
			//if(strINIPath.IsFile())
			//{
				//INIFile ini(strINIPath);
				//if(!_access_path_from_ini_file(ini, lpcszFileGroup, lpcszFilePath, bSavePath, false))
				//{
					//error_report(_L("Failed to set save path from File Group "));
					//return false;
				//}
			//}
			//else
			//{
				//error_report(_L("Failed to open origin ini file."));
				//return false;
			//}
		//}
	//}
	//else
	//{
		//strINIPath = GetAppPath(TRUE) + "origin.ini";
		//if(strINIPath.IsFile())
		//{
			//INIFile ini(strINIPath);
			//if(!_access_path_from_ini_file(ini, lpcszFileGroup, lpcszFilePath, bSavePath, false))
			//{
				//error_report(_L("Failed to set save path from File Group."));
				//return false;
			//}
		//}
		//else
		//{
			//error_report(_L("Failed to open origin ini file."));
			//return false;
		//}
	//}
	//return true;
//}

///End SET_FILE_GROUP_DEFAULT_PATH

//----Jake 06/18/07 v8.0643 GET_PATH_TRACK_LIST_FROM_REGISTRY
/// Iris 07/03/2007 v8.0654 USAGE_OF_BROWSER_COMBO_NOT_CONSISTENT_IN_FILE_AND_PATH_CONTROL
//int get_path_list(LPCSTR lpcszXFDlgName, vector<string>& vsPathList,bool bOnlyRecent)
int get_path_list(LPCSTR lpcszXFDlgName, vector<string>& vsPathList, bool bIncSpecialFolder, LPCSTR lpcszFilename)
{
	PathTrack pathtrack(lpcszXFDlgName);
	string strPaths = pathtrack.Load();

	if(!strPaths.IsEmpty())
		strPaths.GetTokens(vsPathList, '|');
	
	string	strFilename(lpcszFilename);				
	if(bIncSpecialFolder)
	{
		/// Iris 07/03/2007 v8.0654 USAGE_OF_BROWSER_COMBO_NOT_CONSISTENT_IN_FILE_AND_PATH_CONTROL
		// should show full filename for file browser control list.
		/*
		vsPathList.Add(STR_USER_FOLDER);		
		
		//----Jake 06/19/07 v8.0644 CHECK_REAL_PATH
		//vsPathList.Add(STR_PROJECT_FOLDER);
		string strRealPath = cvt_predefined_path_to_real_path(STR_PROJECT_FOLDER);
		if(!strRealPath.IsEmpty())
			vsPathList.Add(STR_PROJECT_FOLDER);
		//----end CHECK_REAL_PATH
		*/
		string 	strPath = STR_USER_FOLDER;
		if( !strFilename.IsEmpty() )
			strPath += STR_RELATIVE_PATH_SEP + strFilename;
		if( vsPathList.Find(strPath) < 0)
			vsPathList.Add(strPath);
		
		if( !Project.GetPath().IsEmpty() ) //if the project has not been saved, then <Project Folder> should not show in list
		{
			strPath = STR_PROJECT_FOLDER;
			if( !strFilename.IsEmpty() )
				strPath += STR_RELATIVE_PATH_SEP + strFilename;
			if( vsPathList.Find(strPath) < 0)
				vsPathList.Add(strPath);		
		}
		///end USAGE_OF_BROWSER_COMBO_NOT_CONSISTENT_IN_FILE_AND_PATH_CONTROL
	}

	return vsPathList.GetSize();
}
//----end GET_PATH_TRACK_LIST_FROM_REGISTRY

//----Jake 06/18/07 v8.0643 UPDATE_PATH_TRACK_LIST_TO_REGISTRY
void update_recent_path_list(LPCSTR lpcszNewPath, LPCSTR lpcszClassName, int nMaxPathNum)
{
	///Jake 06/28/07 SET_DEFAULT_KEY_NAME
	string strClassName = lpcszClassName;
	if(strClassName.IsEmpty())
	{
		char szLastXFName[MAXFULLPATH];
		LT_get_str(LTVAR_LAST_XF, szLastXFName, MAXFULLPATH);
		strClassName = szLastXFName;
	}
	///end SET_DEFAULT_KEY_NAME
	
	PathTrack pathtrack(strClassName,nMaxPathNum);
	/// Iris 07/04/2007 v8.0654 USAGE_OF_BROWSER_COMBO_NOT_CONSISTENT_IN_FILE_AND_PATH_CONTROL
	// Discussed with Max to decide to alwasy save absolute path to Reg
	//pathtrack.Add(lpcszNewPath);
	string 	strNewPath = cvt_predefined_path_to_real_path(lpcszNewPath);
	pathtrack.Add(strNewPath);
	///end USAGE_OF_BROWSER_COMBO_NOT_CONSISTENT_IN_FILE_AND_PATH_CONTROL
	pathtrack.Save();
}
//----end UPDATE_PATH_TRACK_LIST_TO_REGISTRY

/// Iris 07/13/2007 v8.0659 SHARE_CHECK_PATH_CODES_FOR_ALL_EXPORT_XFS
//bool	str_is_predefined_path(LPCSTR lpcszPath, int* pnTypeID, string* pstrSubFolder)
bool	str_is_predefined_path(LPCSTR lpcszPath, int* pnTypeID, string* pstrSubFolder, int* pErrInfo)
///end SHARE_CHECK_PATH_CODES_FOR_ALL_EXPORT_XFS
{
	string strPath(lpcszPath);
	///---Sim 05-07-2009 QA80-13571 FIX_CRASH_WHEN_FILE_PATH_LENGTH_IS_TOO_LONG
#ifndef CHECK_EXCEED_FILE_PATH_LENGTH_LIMITATION
	if(strPath.IsPath() || strPath.GetLength() == 0 || strPath.IsFile())
		return false;
#else
	// predefined path contain '<' or '>', must isn't real file name
	if ( strPath.GetLength() == 0 )
		return false;
#endif
	///---END QA80-13571 FIX_CRASH_WHEN_FILE_PATH_LENGTH_IS_TOO_LONG
	
	int		nErrInfo = 0; /// Iris 07/13/2007 v8.0659 SHARE_CHECK_PATH_CODES_FOR_ALL_EXPORT_XFS
	bool	bRet = false;
	strPath.TrimLeft();
	strPath.TrimRight();
	if( strPath[0] == '<' && strPath.Find('>') >= 0) //may be special folder
	{
		string	strSep = STR_RELATIVE_PATH_SEP; //only one character
		char 	chSep = strSep[0];
		string	strPrefix = strPath;
		string	strSubfolderTemp;		
		
		if( strPath.GetNumTokens(chSep) > 1 ) //if include sub folder, to separate prefix and sub folder
		{
			strPrefix = strPath.GetToken(0, chSep);
			strSubfolderTemp = strPath;
			strSubfolderTemp.TrimLeft(strPrefix);
			strSubfolderTemp.Replace(chSep, '\\');
			strSubfolderTemp.TrimLeft('\\');
		}
		
		int nID = okutil_cvt_str_to_predefined_type(strPrefix);		
		switch(nID)
		{
		case PDS_PROJECT_FOLDER:
		case PDS_USER_FOLDER:
		/// Hong 12/06/07 v8.0762 IMPORT_SUPPORT_RELATIVE_PATH_FOR_REIMPORT_SAMPLE_REQUIREMENT
		case PDS_EXE_FOLDER:
		/// end IMPORT_SUPPORT_RELATIVE_PATH_FOR_REIMPORT_SAMPLE_REQUIREMENT
			bRet = true;
			break;
		default:
			bRet = false;
			break;
		}
		
		/// Iris 07/13/2007 v8.0659 SHARE_CHECK_PATH_CODES_FOR_ALL_EXPORT_XFS
		if( !bRet && NULL != pErrInfo) //is relative folder string, but contains some errors
		{
			if( strPrefix.Find('\\') >= 0 ) //the sperator should be "//", but user may write as "\\"
				nErrInfo = CVT_RELATIVE_PATH_ERR_SEP;
		}		
		if(pErrInfo)
			*pErrInfo = nErrInfo;
		///end SHARE_CHECK_PATH_CODES_FOR_ALL_EXPORT_XFS
		
		if(pnTypeID)
			*pnTypeID = nID;
		if(pstrSubFolder && !strSubfolderTemp.IsEmpty())
			*pstrSubFolder = strSubfolderTemp;
	}
	
	return bRet;
}
	
//----Jake 06/19/07 v8.0644 CONVERT_PREDEFINED_PATH_TO_REAL_PATH
/// Iris 07/13/2007 v8.0659 SHARE_CHECK_PATH_CODES_FOR_ALL_EXPORT_XFS
//string cvt_predefined_path_to_real_path(LPCSTR lpcszPredefinedPath)
string cvt_predefined_path_to_real_path(LPCSTR lpcszPredefinedPath, int* pErrInfo)
///end CONVERT_PREDEFINED_PATH_TO_REAL_PATH
{
	/// Iris 07/03/2007 v8.0654 USAGE_OF_BROWSER_COMBO_NOT_CONSISTENT_IN_FILE_AND_PATH_CONTROL
	/*
	string strRealPath(lpcszPredefinedPath);
	if(strRealPath.IsPath())
		return strRealPath;
	
	int nID = okutil_cvt_str_to_predefined_type(lpcszPredefinedPath);
	switch(nID)
	{
	case PDS_PROJECT_FOLDER:
		strRealPath = Project.GetPath();
		break;
	case PDS_USER_FOLDER:
		strRealPath = GetAppPath(FALSE);
		break;
	default:
		strRealPath.Empty();
	}
	*/
	string 	strPath(lpcszPredefinedPath);
	int		nID;
	string	strSubFolder;
	if( str_is_predefined_path(strPath, &nID, strSubFolder, pErrInfo) ) //is absolute path or empty string
	{
		switch(nID)
		{
		case PDS_PROJECT_FOLDER:
			strPath = Project.GetPath() + strSubFolder;
			break;
		case PDS_USER_FOLDER:
			strPath = GetAppPath(FALSE) + strSubFolder;
			break;
		/// Hong 12/06/07 v8.0762 IMPORT_SUPPORT_RELATIVE_PATH_FOR_REIMPORT_SAMPLE_REQUIREMENT
		case PDS_EXE_FOLDER:
			strPath = GetAppPath(TRUE) + strSubFolder;
			break;
		/// end IMPORT_SUPPORT_RELATIVE_PATH_FOR_REIMPORT_SAMPLE_REQUIREMENT
		default:
			strPath.Empty();
		}			
	}
	///end USAGE_OF_BROWSER_COMBO_NOT_CONSISTENT_IN_FILE_AND_PATH_CONTROL
	///---Sim 05-07-2009 QA80-13571 FIX_CRASH_WHEN_FILE_PATH_LENGTH_IS_TOO_LONG
	check_trim_file_path_if_too_long(strPath);
	///---END QA80-13571 FIX_CRASH_WHEN_FILE_PATH_LENGTH_IS_TOO_LONG
	
	return strPath;

}
//----end CONVERT_PREDEFINED_PATH_TO_REAL_PATH

/// Iris 07/13/2007 v8.0659 SHARE_CHECK_PATH_CODES_FOR_ALL_EXPORT_XFS
void	check_relative_path(LPCSTR lpcszPath, bool bPathWithoutFilename, string* pstrErr, bool* pbOKEnable)
{
	string	strErr;
	bool	bOKEnable = true;
	
	int		nErrRelativePathInfo;
	string  strPath = cvt_predefined_path_to_real_path(lpcszPath, &nErrRelativePathInfo);
	if(nErrRelativePathInfo > 0)
	{
		if(CVT_RELATIVE_PATH_ERR_SEP == nErrRelativePathInfo)
		{
			strErr = XFERR_PLS_USE_CORRECT_SEP_FOR_RELATIVE_PATH;
			bOKEnable = false;
		}
	}
	else
	{
		if( !bPathWithoutFilename )
		{
			if( !is_str_valid_for_filename(GetFileName(strPath)) )
			{
				strErr = CER_INVALID_FILENAME;
				bOKEnable = false;
			}
			else
				strPath = GetFilePath(strPath); //trim filename and file extension
		}
		
		if( !strPath.IsPath() )
		{
			bool	bCreateNew = false;
			if ( OM_RETURN_OK == OptionalMessage( "CreateNotExistingPath", MB_YESNO ) ) 
				bCreateNew = true;
			
			if(bCreateNew)
			{
				if( !CreateDirectory(strPath, NULL) )
				{
					strErr = CER_FAIL_TO_CREATE_PATH;
					bOKEnable = false;
				}
			}
			else
			{
				strErr = CER_INVALID_FILEPATH;
				bOKEnable = false;
			}
		}
	}	
	
	if ( NULL != pstrErr )
		*pstrErr = strErr;
	if ( NULL != pbOKEnable && !bOKEnable)
		*pbOKEnable = bOKEnable;

}
///end SHARE_CHECK_PATH_CODES_FOR_ALL_EXPORT_XFS

///---Sim 07-17-2007 IMPROVE_FILTER_SETTING_FUNC
/*
///Jake 07/12/07 GET_AND_SET_FILTER_SETTING

bool get_filter_setting(LPCSTR lpcszFilterName, bool& bValue, bool bSystemFolder, int nType )
{
	
	//bValue = true;
	INIFileEx ini(STR_INI_FILENAME);
	string strKeyName;
	strKeyName.Format("%s_%d",lpcszFilterName,bSystemFolder?1:0);
	
	int nRet = ini.ReadInt(STR_FILTER_SECTION,strKeyName,-1);
	if(nRet < 0)
		return false;
	
	bValue = nRet;//nRet here will be 0 or 1 
	
	return true;
}
bool set_filter_setting(LPCSTR lpcszFilterName, bool bValue, bool bSystemFolder, int nType )
{
	INIFileEx ini(STR_INI_FILENAME);
	string strKeyName;
	strKeyName.Format("%s_%d",lpcszFilterName,bSystemFolder?1:0);
	
	ini.WriteInt(STR_FILTER_SECTION,strKeyName,bValue);
	return true;
}
///end GET_AND_SET_FILTER_SETTING
*/

#define STR_FILTER_DRAG_AND_DROP_SECTION		"Filter Drag and Drop" 
//#define STR_FILTER_INI_FILENAME					"origin.ini" /// Hong 08/15/07 v8.0682 PUBLISH_FILTER_WITH_DRAG_AND_GROP_SETTING
#define STR_FILTER_SETTING_KEY_FORMAT			"%s_%d"
/// Hong 08/14/07 QA80-9015 ADD_GROUP_FOLDER_INTO_SEARCH_LIST_FOR_DRAG_AND_DROP
//bool get_filter_setting(LPCSTR lpcszFilterName, bool& bValue, bool bSystemFolder, int nType ) // = FILTER_SETTING_DRAG_AND_DROG
//------ Folger 08/21/07 ADD_FILE_PATH_PARAM_TO_SPECIFY_GROUP_PATH
//bool get_filter_setting(LPCSTR lpcszFilterName, bool& bValue, int nLocation, int nType ) // = FILTER_LOCATION_USER, = FILTER_SETTING_DRAG_AND_DROG
bool get_filter_setting(LPCSTR lpcszFilterName, bool& bValue, int nLocation, int nType, LPCSTR lpcszFilePath)
//------ End ADD_FILE_PATH_PARAM_TO_SPECIFY_GROUP_PATH
/// end ADD_GROUP_FOLDER_INTO_SEARCH_LIST_FOR_DRAG_AND_DROP
{
	string strSection;
	
	switch (nType)
	{
	case FILTER_SETTING_DRAG_AND_DROG:
		strSection = STR_FILTER_DRAG_AND_DROP_SECTION;
		break;
	default: // not supported
		return false;
	}
	
	//bValue = true;
	//INIFileEx ini(STR_FILTER_INI_FILENAME);	//------ Folger 08/21/07 ADD_FILE_PATH_PARAM_TO_SPECIFY_GROUP_PATH
	string strKeyName;
	//strKeyName.Format(STR_FILTER_SETTING_KEY_FORMAT, lpcszFilterName, bSystemFolder?1:0);
	strKeyName.Format(STR_FILTER_SETTING_KEY_FORMAT, lpcszFilterName, nLocation);/// Hong 08/14/07 QA80-9015 ADD_GROUP_FOLDER_INTO_SEARCH_LIST_FOR_DRAG_AND_DROP
	strKeyName.MakeUpper();
	
	//------ Folger 08/21/07 ADD_FILE_PATH_PARAM_TO_SPECIFY_GROUP_PATH
	//int nRet = ini.ReadInt(strSection, strKeyName, -1);
	int nRet;
	string strPath = lpcszFilePath;
	if (!strPath.IsEmpty())
	{		
		INIFile ini(strPath + STR_FILTER_INI_FILENAME);
		nRet = ini.ReadInt(strSection, strKeyName, -1);
	}
	
	else
	{
		INIFileEx ini(STR_FILTER_INI_FILENAME);
		nRet = ini.ReadInt(strSection, strKeyName, -1);
	}
	//------ End ADD_FILE_PATH_PARAM_TO_SPECIFY_GROUP_PATH
	if(nRet < 0)
		return false;
	
	bValue = nRet;//nRet here will be 0 or 1 
	
	return true;
}
/// Hong 08/14/07 QA80-9015 ADD_GROUP_FOLDER_INTO_SEARCH_LIST_FOR_DRAG_AND_DROP
//bool set_filter_setting(LPCSTR lpcszFilterName, bool bValue, bool bSystemFolder, int nType ) // = FILTER_SETTING_DRAG_AND_DROG
//------ Folger 08/21/07 ADD_FILE_PATH_PARAM_TO_SPECIFY_GROUP_PATH
//bool set_filter_setting(LPCSTR lpcszFilterName, bool bValue, int nLocation, int nType ) // = FILTER_LOCATION_USER, = FILTER_SETTING_DRAG_AND_DROG
bool set_filter_setting(LPCSTR lpcszFilterName, bool bValue, int nLocation, int nType, LPCSTR lpcszFilePath) // = FILTER_LOCATION_USER, = FILTER_SETTING_DRAG_AND_DROG
//------ End ADD_FILE_PATH_PARAM_TO_SPECIFY_GROUP_PATH
/// end ADD_GROUP_FOLDER_INTO_SEARCH_LIST_FOR_DRAG_AND_DROP
{
	string strSection;
	
	switch (nType)
	{
	case FILTER_SETTING_DRAG_AND_DROG:
		strSection = STR_FILTER_DRAG_AND_DROP_SECTION;
		break;
	default: // not supported
		return false;
	}
	
	//INIFileEx ini(STR_FILTER_INI_FILENAME);	//------ Folger 08/21/07 ADD_FILE_PATH_PARAM_TO_SPECIFY_GROUP_PATH
	string strKeyName;
	//strKeyName.Format(STR_FILTER_SETTING_KEY_FORMAT, lpcszFilterName, bSystemFolder?1:0);
	strKeyName.Format(STR_FILTER_SETTING_KEY_FORMAT, lpcszFilterName, nLocation);/// Hong 08/14/07 QA80-9015 ADD_GROUP_FOLDER_INTO_SEARCH_LIST_FOR_DRAG_AND_DROP
	strKeyName.MakeUpper();
	
	//------ Folger 08/21/07 ADD_FILE_PATH_PARAM_TO_SPECIFY_GROUP_PATH
	//ini.WriteInt(strSection, strKeyName, bValue);
	string strPath = lpcszFilePath;
	if (!strPath.IsEmpty())
	{
		INIFile ini(strPath + STR_FILTER_INI_FILENAME);
		ini.WriteInt(strSection, strKeyName, bValue);
	}
	
	else
	{
		INIFileEx ini(STR_FILTER_INI_FILENAME);
		ini.WriteInt(strSection, strKeyName, bValue);
	}
	//------ End ADD_FILE_PATH_PARAM_TO_SPECIFY_GROUP_PATH
	
	return true;
}
///---END IMPROVE_FILTER_SETTING_FUNC

//------ Folger 08/21/07 REMOVE_ONE_LINE_FROM_FILTER_INI_SETTING
bool remove_line_from_filter_setting(LPCSTR lpcszFilterName, int nLocation, int nType, LPCSTR lpcszFilePath)
{
	string strSection;
	
	switch (nType)
	{
	case FILTER_SETTING_DRAG_AND_DROG:
		strSection = STR_FILTER_DRAG_AND_DROP_SECTION;
		break;
	default: // not supported
		return false;
	}
	
	string strKeyName;
	strKeyName.Format(STR_FILTER_SETTING_KEY_FORMAT, lpcszFilterName, nLocation);
	strKeyName.MakeUpper();
	
	string strPath = lpcszFilePath;
	if (!strPath.IsEmpty())
	{
		INIFile ini(strPath + STR_FILTER_INI_FILENAME);
		ini.WriteString(strSection, strKeyName, NULL);
	}
	
	else
	{
		INIFileEx ini(STR_FILTER_INI_FILENAME);
		ini.WriteString(strSection, strKeyName, NULL);
	}
	
	return true;
}
//------ End REMOVE_ONE_LINE_FROM_FILTER_INI_SETTING


//------ CPY 9/1/2007 CLEAN_UP_CODE_RELATED_TO_GETTING_75_FDF_FILES
//------ Folger 01/14/08 GET_ORIGIN75_SYSTEM_FILE_PATH
//bool get_origin75_user_path(string& strUserFilePath)
bool get_origin75_user_path(string& strUserFilePath, bool bUser)
//------
{
	//------ Folger 01/15/08 OKUTIL_GET_ORIGIN75_PATH
	////------ Folger 09/03/07 MODIFY_GET_ORIGIN75_USER_PATH_SUGGESTED_BY_DAVID
	////return okutil_find_path_from_origin_registry_key(&strUserFilePath, "Path", "Origin 7.5");
	//string strLanguage;
	//bool bRet = false;
	//string strKey = bUser ? "Path" : "Executable Path";		//------ Folger 01/14/08 GET_ORIGIN75_SYSTEM_FILE_PATH
	//if (okutil_get_serial_number_language(&strLanguage))
	//{
		////------ Folger 01/14/08 GET_ORIGIN75_SYSTEM_FILE_PATH
		////bRet = okutil_find_path_from_origin_registry_key(&strUserFilePath, "Path", "Origin 7.5", NULL, NULL, strLanguage);
		//bRet = okutil_find_path_from_origin_registry_key(&strUserFilePath, strKey, "Origin 7.5", NULL, NULL, strLanguage);
		////------
		//if (!bRet && strLanguage.CompareNoCase("English"))
			////------ Folger 01/14/08 GET_ORIGIN75_SYSTEM_FILE_PATH
			////bRet = okutil_find_path_from_origin_registry_key(&strUserFilePath, "Path", "Origin 7.5", NULL, NULL, "English");
			//bRet = okutil_find_path_from_origin_registry_key(&strUserFilePath, strKey, "Origin 7.5", NULL, NULL, "English");
			////------
	//}
	//return bRet;
	////------ End MODIFY_GET_ORIGIN75_USER_PATH_SUGGESTED_BY_DAVID
	
	//move to VC
	return okutil_get_origin75_path(&strUserFilePath, bUser);
	//------
}
//------

//----- CPY 12/26/07 QA70-10870 NUMERIC_INPUT_BOX_NEEDED
// return NANUM if cancel
double InputBox(double dDefault, LPCSTR lpcszMsg)
{
	string strMsg = lpcszMsg;
	if(strMsg.IsEmpty())
		strMsg = "Please enter a number";
	
	string str = ftoa(dDefault, "*14*");
	try
	{
		str = InputBox(strMsg, str, 0);
	}
	catch(int nErr)
	{
		return NANUM;
	}
	return atof(str);
}
//-----

//------ Folger 04/17/08 QA80-11440 SYSTEM_UTILITY_FUNCTION_TO_REFRESH_ORIGIN_MAIN_MENU
bool	refresh_origin_main_menu()
{
	const	int	nMenuLevelBase = 32768;
	
	double	rMenuLevel = 1.0;
	LT_get_var("system.level", &rMenuLevel);
	
	return	LT_execute("menu -e " + (int)(nMenuLevelBase + rMenuLevel - 1));
}
//------

//------ Folger 06/05/08 OPX_FILE_PUBLISH_SHOULD_IDENTIFY_BY_VERSION_FIRST
int opx_file_version_compare(LPCSTR lpcszFile1, LPCSTR lpcszFile2)
{
	Tree	trOpx1, trOpx2;
	if ( !trOpx1.Load(lpcszFile1) || !trOpx2.Load(lpcszFile2) )
		return -3;
	
	const char* szVersion = "Version";
	TreeNode	trVersion1 = tree_get_node_by_tagname(trOpx1, szVersion, true);
	TreeNode	trVersion2 = tree_get_node_by_tagname(trOpx2, szVersion, true);
	if ( !trVersion1 || !trVersion2 )
		return -2;
	
	if ( trVersion1.dVal < trVersion2.dVal )
		return -1;
	
	if ( trVersion1.dVal > trVersion2.dVal )
		return 1;
	
	return 0;
}
//------ End OPX_FILE_PUBLISH_SHOULD_IDENTIFY_BY_VERSION_FIRST

//------ Folger 08/22/08 QA80-12074 ADD_UTILITY_FUNCTION_FOR_INITIAL_TEMPLATE_LIST
bool init_template_list(TreeNode& trTemplate, DWORD dwType/* = TEMPLATE_WORKSHEET*/)
{
	StringArray saTemplates;
	if ( dwType & TEMPLATE_WORKSHEET )
	{
		GetFileNames(saTemplates, NULL, "*.otw", GFIF_FILE_RECURSIVE | GFIF_STRIP_START_PATH);
		GetFileNames(saTemplates, NULL, "*.ogw", GFIF_FILE_RECURSIVE | GFIF_STRIP_START_PATH);
	}
	if ( dwType & TEMPLATE_MATRIX )
	{
		GetFileNames(saTemplates, NULL, "*.otm", GFIF_FILE_RECURSIVE | GFIF_STRIP_START_PATH);
		GetFileNames(saTemplates, NULL, "*.ogm", GFIF_FILE_RECURSIVE | GFIF_STRIP_START_PATH);
	}
	if ( dwType & TEMPLATE_PLOT )
	{
		GetFileNames(saTemplates, NULL, "*.otp", GFIF_FILE_RECURSIVE | GFIF_STRIP_START_PATH);
		GetFileNames(saTemplates, NULL, "*.ogg", GFIF_FILE_RECURSIVE | GFIF_STRIP_START_PATH);
	}

	///---Sim 12-23-2008 QA80-12836 SUPPORT_FILE_BROWSER_BUTTON
	// centralize code
	/*
	string	strAttr;
	if ( !trTemplate.GetAttribute(STR_COMBO_ATTRIB, strAttr) )
		return false;
	
	int nPos;
	nPos = strAttr.Find(STR_ATTR_BROWSE_COMBO_LIST_DELIMITER);
	if ( nPos >= 0 )
	{
		strAttr = strAttr.Left(nPos); // remove last recent list
	}
	
	strAttr += STR_ATTR_BROWSE_COMBO_LIST_DELIMITER;
	
	string strListString;
	strListString.SetTokens(saTemplates,'|');
	strListString.Insert(0,strAttr);
	
	trTemplate.ID = ONODETYPE_BROWSECOMBO;
	trTemplate.SetAttribute(STR_COMBO_ATTRIB, strListString);
	return true;
	*/
	return tree_set_file_browse_combo_attrib(trTemplate, saTemplates);
	///---END QA80-12836 SUPPORT_FILE_BROWSER_BUTTON
}
//------ End ADD_UTILITY_FUNCTION_FOR_INITIAL_TEMPLATE_LIST

///Jasmine 10/23/08 QA80-12442 SHOW_WARNING_WHEN_SAVE_READ_ONLY_FILE
void popup_errmsg_save_readonly_file(LPCSTR lpcszFile, HWND hwnd)
{
	string strErr;
	ocu_load_msg_str(CER_SAVE_READ_ONLY_FILE_FAIL, &strErr, lpcszFile);
	MessageBox(hwnd, strErr, NULL, MB_OK | MB_ICONEXCLAMATION);
}
///End SHOW_WARNING_WHEN_SAVE_READ_ONLY_FILE

///---Sim 12-23-2008 QA80-12836 SUPPORT_FILE_BROWSER_BUTTON
string get_open_dlg_file_filter(LPCSTR lpcszDescription, LPCSTR lpcszExtension)
{
	string str;
	str.Format("[%s] *.%s", lpcszDescription, lpcszExtension);
	return str;
}
///---END QA80-12836 SUPPORT_FILE_BROWSER_BUTTON


//---CPY 5/21/09 QA70-13649 CUSTOM_DATE_FORMAT_INIT_FROM_EXE_INI
/*
///Kyle 01/04/2009 QA70-12890-P4 CENTRALIZE_CODE_TO_GET_AND_UPDATE_CUSTOM_DATE_FORMAT
int get_custom_date_format_list(vector<string>& vsList)
{
	vsList.SetSize(0);

	vector<string> vsKeyNames;
	INIFile	iniFile(STR_CUSTOM_DATE_FORMAT_LIST_FILE);

	iniFile.GetKeyNames(vsKeyNames, STR_CUSTOM_DATE_FORMAT_LIST_SECTION);
	for ( int ii = 0; ii < vsKeyNames.GetSize(); ii++ )
		vsList.Add(iniFile.ReadString(STR_CUSTOM_DATE_FORMAT_LIST_SECTION, vsKeyNames[ii]));
	// get default list
	if(vsList.GetSize() <= 0)
	{
		string strDefFormat = STR_CUSTOM_DATE_FORMAT_LIST_DEFAULT;
		strDefFormat.GetTokens(vsList, '|');
	}

	if(vsList.GetSize() > CUSTOM_DATE_FORMAT_LIST_MAX_NUM)
		vsList.SetSize(CUSTOM_DATE_FORMAT_LIST_MAX_NUM);

	return vsList.GetSize();
}
*/
///Sophy 9/26/2010 ORG-1142 ADO_IMPORT_SHOULD_ALLOW_SET_COL_FORMAT_FOR_DATE_FIELD
#ifndef	_ADO_SET_COLUMN_DATE_FORMAT_
///end ADO_IMPORT_SHOULD_ALLOW_SET_COL_FORMAT_FOR_DATE_FIELD
#define CUSTOM_DATE_FORMAT_LIST_MAX_NUM			20 //Kyle had this 10, which is too few
//#define STR_CUSTOM_DATE_FORMAT_LIST_FILE		okutil_get_origin_path(ORIGIN_PATH_USER) + STR_ORIGIN_INI_FILE_NAME
#define STR_CUSTOM_DATE_FORMAT_LIST_SECTION		"Column Custom Format List"	// really should be "Custom Date Format List"
#define STR_CUSTOM_DATE_FORMAT_LIST_PREFIX		"CustomFmt"
static void _load_custom_date_format_list(INIFile& iniFile, const vector<string>& vsKeyNames, vector<string>& vsList)
{
	for ( int ii = 0; ii < vsKeyNames.GetSize(); ii++ )
	{
		string strVal = iniFile.ReadString(STR_CUSTOM_DATE_FORMAT_LIST_SECTION, vsKeyNames[ii]);
		if(strVal.GetLength() > 0) // user might have empty str if they don't want to add certain value
			vsList.Add(strVal);
	}
}
///Sophy 9/26/2010 ORG-1142 ADO_IMPORT_SHOULD_ALLOW_SET_COL_FORMAT_FOR_DATE_FIELD
#endif	_ADO_SET_COLUMN_DATE_FORMAT_
///end ADO_IMPORT_SHOULD_ALLOW_SET_COL_FORMAT_FOR_DATE_FIELD
int get_custom_date_format_list(vector<string>& vsList)
{
	///Sophy 9/26/2010 ORG-1142 ADO_IMPORT_SHOULD_ALLOW_SET_COL_FORMAT_FOR_DATE_FIELD
#ifdef	_ADO_SET_COLUMN_DATE_FORMAT_
	return okutil_get_custom_date_format_list(&vsList);
#else	//not defined, run old OC code
	///end ADO_IMPORT_SHOULD_ALLOW_SET_COL_FORMAT_FOR_DATE_FIELD
	vsList.SetSize(0);
	vector<string> vsKeyNames;
	INIFile	iniUFF(STR_ORIGIN_INI_FILE_NAME);
	INIFile	iniEXE(STR_ORIGIN_INI_FILE_NAME, false);
	iniUFF.GetKeyNames(vsKeyNames, STR_CUSTOM_DATE_FORMAT_LIST_SECTION);
	if(vsKeyNames.GetSize() > 0)
		_load_custom_date_format_list(iniUFF, vsKeyNames, vsList);
	else
	{
		iniEXE.GetKeyNames(vsKeyNames, STR_CUSTOM_DATE_FORMAT_LIST_SECTION);
		if(vsKeyNames.GetSize() > 0)
			_load_custom_date_format_list(iniEXE, vsKeyNames, vsList);
		else
		{
			string strDefFormat = "dd'/'MM'/'yyyy|dd'.'MM'.'yy|dd'-'MM'-'yy|yyyy'-'MM'-'dd|yyyy'-'MM'-'dd' 'hh':'mm':'ss'.'###";
			strDefFormat.GetTokens(vsList, '|');
		}
	}
	if(vsList.GetSize() > CUSTOM_DATE_FORMAT_LIST_MAX_NUM)
	{
		okoc_out_msg(STR_CUSTOM_DATE_FORMAT_LIST_SECTION + ": too many entries", 'W');

		vsList.SetSize(CUSTOM_DATE_FORMAT_LIST_MAX_NUM);
	}

	return vsList.GetSize();
#endif	//_ADO_SET_COLUMN_DATE_FORMAT_	///Sophy 9/26/2010 ORG-1142 ADO_IMPORT_SHOULD_ALLOW_SET_COL_FORMAT_FOR_DATE_FIELD
}		

//---CPY 5/21/09 QA70-13649 CUSTOM_DATE_FORMAT_INIT_FROM_EXE_INI
//I replace update_ini_line with iniFile.WriteString as that function does not make much sense, should really be cleaned up(remove)
//---
int update_custom_date_format_last_used(LPCSTR lpcszFormat)
{
	///Sophy 9/26/2010 ORG-1142 ADO_IMPORT_SHOULD_ALLOW_SET_COL_FORMAT_FOR_DATE_FIELD
#ifdef	_ADO_SET_COLUMN_DATE_FORMAT_
	return okutil_update_custom_date_last_used(lpcszFormat);
#else	//old OC code
	///end ADO_IMPORT_SHOULD_ALLOW_SET_COL_FORMAT_FOR_DATE_FIELD
	string strFormat(lpcszFormat);
	if(strFormat.IsEmpty())
		return -1;
	// prepare list
	vector<string> vsList;
	get_custom_date_format_list(vsList);
	///Kyle 06/22/2009 QA80-13818 CUSTOM_DATE_FORMAT_SHOULD_BE_CASE_SENSITIVE
	//int nRemove = vsList.Find( strFormat );
	int nRemove = vsList.Find( strFormat, 0, TRUE );
	///End CUSTOM_DATE_FORMAT_SHOULD_BE_CASE_SENSITIVE
	if(nRemove == 0)
		return 1;		// no need to update list
	if(nRemove < 0 && vsList.GetSize() >= CUSTOM_DATE_FORMAT_LIST_MAX_NUM)
		nRemove = vsList.GetSize() -1;
	if(nRemove >= 0)
		vsList.RemoveAt(nRemove);
	vsList.InsertAt(0, strFormat);

	//INIFile	iniFile(STR_CUSTOM_DATE_FORMAT_LIST_FILE);
	//update_ini_line(iniFile, STR_CUSTOM_DATE_FORMAT_LIST_SECTION, NULL, NULL );//clean list
	INIFile	iniFile(STR_ORIGIN_INI_FILE_NAME);
	iniFile.WriteString(STR_CUSTOM_DATE_FORMAT_LIST_SECTION, NULL, NULL);


	for(int ii=0; ii<vsList.GetSize(); ii++)
		//update_ini_line(iniFile, STR_CUSTOM_DATE_FORMAT_LIST_SECTION, STR_CUSTOM_DATE_FORMAT_LIST_PREFIX + (string)ii, vsList[ii]);
		iniFile.WriteString(STR_CUSTOM_DATE_FORMAT_LIST_SECTION, STR_CUSTOM_DATE_FORMAT_LIST_PREFIX + (string)ii, vsList[ii]);
		
	return 0;
#endif	//_ADO_SET_COLUMN_DATE_FORMAT_	///Sophy 9/26/2010 ORG-1142 ADO_IMPORT_SHOULD_ALLOW_SET_COL_FORMAT_FOR_DATE_FIELD
}
///End CENTRALIZE_CODE_TO_GET_AND_UPDATE_CUSTOM_DATE_FORMAT

///------ Folger 03/26/09 ANALYSIS_OUTPUT_REPORT_SHEET_NAME_SHOULD_BE_EXCLAMATION_CHAR_ENDING
void		check_add_ending_char(string& str, char nChar)
{
	if ( nChar != str_end_char(str) )
		str += nChar;
}

string		convert_str_with_exclamation_char_endding(LPCSTR lpcsz)
{
	string		str = lpcsz;
	check_add_ending_char(str, '!');
	return str;
}

///------ End ANALYSIS_OUTPUT_REPORT_SHEET_NAME_SHOULD_BE_EXCLAMATION_CHAR_ENDING

/// Hong 04/07/09 QA80-13419 GET_DEBUG_VECTOR_TREENODE_DISPLAY_STRING
string get_display_string(const vector<string>& vstr, int nDisplayNum/* = 3*/, LPCSTR lpcszSep/* = ","*/)
{
	/// Hong 04/08/09 QA80-13419 NO_BRACKET_WHEN_ONLY_ONE_ELEMENT
	//string		strRet("{");
	string		strRet;
	bool		bAddBracket = (vstr.GetSize() > 1 ? true : false);
	if ( bAddBracket )
		strRet += "{";
	/// end NO_BRACKET_WHEN_ONLY_ONE_ELEMENT
	bool		bDotted = vstr.GetSize() > nDisplayNum ? true : false;
	for ( int ii = 0; ii < vstr.GetSize(); ii++ )
	{
		if ( bDotted && (ii == nDisplayNum - 1) )
		{
			strRet += STR_THREE_DOTS;
			strRet += lpcszSep;
			ii = vstr.GetSize() - 1;
		}
		
		strRet += vstr[ii];
		if ( ii != vstr.GetSize() - 1 )
			strRet += lpcszSep;
	}
	/// Hong 04/08/09 QA80-13419 NO_BRACKET_WHEN_ONLY_ONE_ELEMENT
	//strRet += "}";
	if ( bAddBracket )
		strRet += "}";
	/// end NO_BRACKET_WHEN_ONLY_ONE_ELEMENT
	return strRet;
}
/// end GET_DEBUG_VECTOR_TREENODE_DISPLAY_STRING

///---Sim 05-07-2009 QA80-13571 FIX_CRASH_WHEN_FILE_PATH_LENGTH_IS_TOO_LONG
bool check_trim_file_path_if_too_long(string& strFullFilePath, int nMaxPath/* = MAX_PATH*/)
{
	#ifdef CHECK_EXCEED_FILE_PATH_LENGTH_LIMITATION
	if ( strFullFilePath.GetLength() > nMaxPath - 1 )
	{
		string strFullFilePathCorrected = strFullFilePath.Left(nMaxPath-1);
		
		string strErrMsg;
		strErrMsg.Format(_L("File path is too long, system auto trim it.\nfrom:\n\t%s\nTo:\n\t%s\n"), strFullFilePath, strFullFilePathCorrected);
		okoc_out_msg(strErrMsg, 'W');
		
		strFullFilePath = strFullFilePathCorrected;		
		return true;
	}
	#endif /// CHECK_EXCEED_FILE_PATH_LENGTH_LIMITATION
	return false;
}
///---END QA80-13571 FIX_CRASH_WHEN_FILE_PATH_LENGTH_IS_TOO_LONG

///---Sim 07-02-2009 QA80-13869 SUPPORT_DRAG_AND_DROP_OMC_FILE
//////////////////////////////////////////////////////
// begin OC functions to be used from LabTalk via run -oc
//////////////////////////////////////////////////////
//---- CPY 12/6/06 QA70-12736 LT_NEED_MORE_CNTRL_ON_ALLOWING_OC_FUNCS
//#pragma labtalk(1)
#pragma labtalk(2)	// the following can be used from LT only inside the "run -oc cmd" syntax, or "run -oc {val=func(arg)}" syntax.
//----

/**$
return:
	0,	success
	1,	user cancel
	-1, invalid full filename
	-2, invalid file extension
	-3, fail to repace readonly file
	-4, fail create path
*/
int install_customization_menu(string strFileName)
{
	if ( !strFileName.IsFile() )
		return -1; // Invalid full filename
	
	string		strExt;
	if ( !separate_file_name_ext(strFileName, NULL, &strExt) || 0 != strExt.CompareNoCase(MENU_CUSTOMIZATION_FILE_EXT) )
		return -2; // Invalid file extension
	
	string strDestPath = GetAppPath(FALSE);
	if ( CheckMakePath(strDestPath) )
	{
		string strDestFileName = strDestPath + GetFileName(strFileName);
		if ( strDestFileName.IsFile() )
		{
			if ( IDCANCEL == MessageBox(NULL, _L("The named customization menu file already existed, do you want to replace it?"), _L("Install Customization Menu"), MB_OKCANCEL) )
				return 1; // user cancel
		}
		
		if( !CopyFile(strFileName, strDestFileName) )
		{
			popup_errmsg_save_readonly_file( strDestFileName, NULL );
			return -3; // fail to repace readonly file
		}
		/// ML 2/12/2010 QA70-15113 FORMAT_MENU_UPDATE_ON_INSTALLING_OMC
		on_install_omc(strDestFileName);
		/// end FORMAT_MENU_UPDATE_ON_INSTALLING_OMC
		
		return 0; // success	
	}
	return -4; // fail create path	
}
//////////////////////////////////////////////////////
// end OC functions to be used from LabTalk via run -oc
//////////////////////////////////////////////////////
#pragma labtalk(0)
///---END QA80-13869 SUPPORT_DRAG_AND_DROP_OMC_FILE

///------ Folger 08/10/09 QA80-13998 ACTIVE_SUMMARY_BOOK_ONLY_IF_IN_ACTIVE_FOLDER
bool	is_same_folder(Folder fld1, Folder fld2)
{
	return	0 == fld1.GetPath().Compare(fld2.GetPath());
}
///------ End ACTIVE_SUMMARY_BOOK_ONLY_IF_IN_ACTIVE_FOLDER

///------ Folger 08/27/09 QA80-14215 CHANGE_USER_FILES_FOLDER_IN_ORIGIN
#define ADD_BACKSLASH_IF_NOT(strPath) {string strLast = strPath.Right(1); if(strLast != "\\") strPath += "\\";}
BOOL	is_path_writable(LPCSTR lpcszFilePath)
{
	string	strTmpDir = lpcszFilePath;
	ADD_BACKSLASH_IF_NOT(strTmpDir);
	strTmpDir += "Tmp";
	
	if ( !CreateDirectory(strTmpDir, NULL) )
		return FALSE;
	
	RemoveDirectory(strTmpDir);
	return TRUE;
}
///------ End CHANGE_USER_FILES_FOLDER_IN_ORIGIN

///---Sim 08-31-2009 QA81-14106 IMPROVE_ED_DIALOG
int string_array_find_one_of(const StringArray& saDests, const StringArray& saRefs, int nStart, int *pIndexOnArr)// = 0, NULL
{
	int nIndex = -1;
	for (int ii = 0; ii < saRefs.GetSize(); ii++ )
	{
		int nPos = saDests.Find(saRefs[ii], nStart);
		if ( nPos >= 0 )
		{
			nIndex = nPos;
			if ( pIndexOnArr )
				*pIndexOnArr = ii;
			break;
		}
	}
	
	return nIndex;
}
///---END QA81-14106 IMPROVE_ED_DIALOG

///------ Folger 10/21/09 QA81-14506 FAILS_TO_IMPORT_CSV_FILE_IN_SAMPLES_FOLDER_UNDER_GOS_BY_DEFAULT
BOOL	is_builtin_sample_file(LPCSTR lpcszFile)
{
	string		strSamples = okutil_get_origin_path(ORIGIN_PATH_SYSTEM, "Samples\\");
	string		strFile = lpcszFile;
	strSamples.MakeUpper();
	strFile.MakeUpper();
	return strFile.Find(strSamples) == 0;
}
///------ End FAILS_TO_IMPORT_CSV_FILE_IN_SAMPLES_FOLDER_UNDER_GOS_BY_DEFAULT

///------ Folger 10/28/09 QA81-14541 SYSTEM_DEFAULT_FILE_EXTENSION_TEMP_CHANGE_SUPPORT
SystemDefaultFileExtTempChange::SystemDefaultFileExtTempChange(LPCSTR lpcszGroup, int nDefaultType/* = INVALID_FILE_EXT_DEFAULT_TYPE*/)
{
	m_strActiveGroupKey = "FILEEXT.ACTIVEGROUP";
	m_strDefaultTypeKey = "FILEEXT.DEFTYPE";
	changeStr(m_strActiveGroupKey, lpcszGroup, m_strActiveGroup);
	changeInt(m_strDefaultTypeKey, nDefaultType, m_nDefaultType);
}

SystemDefaultFileExtTempChange::~SystemDefaultFileExtTempChange()
{
	changeStr(m_strActiveGroupKey, m_strActiveGroup);
	changeInt(m_strDefaultTypeKey, m_nDefaultType);
}
	
void	SystemDefaultFileExtTempChange::changeStr(LPCSTR lpcszKey, LPCSTR lpcszSet, string& strSaved/* = NULL*/)
{
	if ( NULL != strSaved )
	{
		m_os.GetValue(lpcszKey, strSaved);
	}
	if ( lpcszSet )
	{
		m_os.SetValue(lpcszKey, lpcszSet);
	}
}
	
void	SystemDefaultFileExtTempChange::changeInt(LPCSTR lpcszKey, int nSet, int& nSaved/* = NULL*/)
{
	if ( NULL != nSaved )
	{
		m_os.GetValue(lpcszKey, nSaved);
	}
	if ( INVALID_FILE_EXT_DEFAULT_TYPE != nSet )
	{	
		m_os.SetValue(lpcszKey, nSet);
	}
}
///------ End SYSTEM_DEFAULT_FILE_EXTENSION_TEMP_CHANGE_SUPPORT

/// EJP 2010-01-13 QA81-14672 DRAG_DROP_OIF_FILE
#pragma labtalk(2) // allow following func to be called from LabTalk.
int install_filter(string lpcszFileName, int bPromptIfTargetExist)
{
	string str = lpcszFileName;
	if (!str.IsFile())
		return -1; // source file does not exist

	str = GetAppPath() + "Filters\\";
	if (!CheckMakePath(str))
		return -2; // target path does not exist and could not be made

	string strFilterName = GetFileName(lpcszFileName);
	str += strFilterName;
	if (str.IsFile() && bPromptIfTargetExist)
	{
		string strMsg;
		strMsg.Format(_L("Your Filters folder already contains a file named\n%s\nDo you want to replace it?"), strFilterName);
		if (IDYES != MessageBox(GetWindow(), strMsg, _L("Warning"), MB_YESNO|MB_ICONQUESTION))
			return 1; // user canceled install
	}

	if (FALSE == CopyFile(lpcszFileName, str))
		return -3; // failed to copy file to user's filters folder

	return 0; // success
}
/// end DRAG_DROP_OIF_FILE

///------ Folger 07/12/10 ORG-532 TRANSFER_USER_FILES_FAILED_TO_SHOW_81_FILES
double	__Current_Version(UINT nDecimalPlaces)
{
	double	rr = 0.0;
	LT_get_var("@V", &rr);
	return round(rr, nDecimalPlaces);
}
///------ End TRANSFER_USER_FILES_FAILED_TO_SHOW_81_FILES