fmx::errcode UpdateProgressDialog ( const unsigned long value, const WStringAutoPtr description )
{
    fmx::errcode error = kNoError;

    BOOL user_cancelled = progress_dialog->HasUserCancelled();

    if ( (user_cancelled != 0) || (value > progress_dialog_maximum) ) {

        progress_dialog->StopProgressDialog();
        progress_dialog->Release();
        progress_dialog = NULL;

        error = user_cancelled ? kUserCancelledError : error;

    } else {

        HRESULT result;

        if ( !description->empty () ) {
            result = progress_dialog->SetLine ( 2, description->c_str (), false, NULL );
        }

        if ( result == S_OK ) {
            result = progress_dialog->SetProgress ( value, progress_dialog_maximum );
            error = result == S_FALSE ? kNoError : (fmx::errcode)result;
        }
    }

    return error;
}
bool SetPreference ( WStringAutoPtr key, WStringAutoPtr value, WStringAutoPtr domain )
{
    HKEY registry_key;

    LSTATUS status;

    status = RegCreateKeyEx ( HKEY_CURRENT_USER,
                              domain->c_str(),
                              0,
                              NULL,
                              REG_OPTION_NON_VOLATILE,
                              KEY_WRITE,
                              NULL,
                              &registry_key,
                              NULL
                            );

    if ( status == ERROR_SUCCESS ) {

        status = RegSetValueEx ( registry_key,
                                 key->c_str(),
                                 0,
                                 REG_SZ,
                                 (PBYTE)value->c_str(),
                                 (DWORD)(value->size() * sizeof(wchar_t)) + 1
                               );
        RegCloseKey ( registry_key );
    }

    g_last_error = (fmx::errcode)status;

    return ( status == ERROR_SUCCESS );

}
WStringAutoPtr SelectFile ( WStringAutoPtr prompt, WStringAutoPtr in_folder )
{
	OPENFILENAME open_file_dialog;   // common dialog box structure

	ZeroMemory ( &open_file_dialog, sizeof(open_file_dialog) );

	open_file_dialog.lStructSize = sizeof(open_file_dialog);
	open_file_dialog.hwndOwner = GetActiveWindow();

	wchar_t szFile[MAX_PATH];        // buffer for file name
	open_file_dialog.lpstrFile = szFile;
	open_file_dialog.lpstrFilter = L"All Files (*.*)\0*.*\0";
	open_file_dialog.lpstrFile[0] = '\0';
	open_file_dialog.nMaxFile = sizeof(szFile);
	open_file_dialog.lpstrTitle = prompt->c_str();
	open_file_dialog.lpstrInitialDir = in_folder->c_str();
	open_file_dialog.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;

	 // Display the Open dialog box

	wchar_t path[MAX_PATH] = L"";

	if ( GetOpenFileName ( &open_file_dialog ) == TRUE ) {
		wcscpy_s ( path, open_file_dialog.lpstrFile );
	 }

	 return WStringAutoPtr ( new wstring ( path ) );

}	//	SelectFile
fmx::errcode UpdateProgressDialog ( const long value, const WStringAutoPtr description )
{
	fmx::errcode error = kNoError;

	bool user_cancelled = progress_dialog->HasUserCancelled();

	if ( user_cancelled || value > progress_dialog_maximum ) {

		progress_dialog->StopProgressDialog();
		progress_dialog->Release();
        progress_dialog = NULL;

		error = user_cancelled ? kUserCancelledError : error;

	} else {

		if ( !description->empty () ) {
			error = progress_dialog->SetLine ( 2, description->c_str (), false, NULL );
		}

		if ( error == S_OK ) {
			error = progress_dialog->SetProgress ( value, progress_dialog_maximum );
			error = error == S_FALSE ? kNoError : error;
		}
	}

	return error;
}
WStringAutoPtr GetPreference ( WStringAutoPtr key, WStringAutoPtr domain )
{

    HKEY registry_key;
    DWORD buffer_size = 1024;
    wchar_t * preference_data = new wchar_t[buffer_size]();

    LSTATUS status;

    status = RegOpenKeyEx ( HKEY_CURRENT_USER,
                            domain->c_str(),
                            NULL,
                            KEY_READ,
                            &registry_key
                          );

    if ( status == ERROR_SUCCESS ) {

        status = RegQueryValueEx ( registry_key,
                                   key->c_str(),
                                   NULL,
                                   NULL,
                                   (LPBYTE)preference_data,
                                   &buffer_size
                                 );

        // if preference_data isn't big enough resize it and try again
        if ( status == ERROR_MORE_DATA ) {

            delete [] preference_data;
            preference_data = new wchar_t[buffer_size + 1]();

            status = RegQueryValueEx ( registry_key,
                                       key->c_str(),
                                       NULL,
                                       NULL,
                                       (LPBYTE)preference_data,
                                       &buffer_size
                                     );
        }
        RegCloseKey ( registry_key );
    }

    WStringAutoPtr value = WStringAutoPtr ( new wstring ( preference_data ) );

    delete [] preference_data;

    g_last_error = (fmx::errcode)status;

    return value;

}
int DisplayDialog ( WStringAutoPtr title, WStringAutoPtr message, WStringAutoPtr button1, WStringAutoPtr button2, WStringAutoPtr button3 )
{
    // set the names to be used for each button
    g_button1_name.swap ( *button1 );
    g_button2_name.swap ( *button2 );
    g_button3_name.swap ( *button3 );

    // the type of dialog displayed varies depends on the nunmber of buttons required
    UINT type = MB_OK;

    if ( g_button2_name != L"" ) {
        type = MB_OKCANCEL;
        if ( g_button3_name != L"" ) {
            type = MB_YESNOCANCEL;
        }
    }

    // set the callback so that the custom button names are installed
    g_window_hook = SetWindowsHookEx ( WH_CBT, &DialogCallback, 0, GetCurrentThreadId() );

    /*
     get the user's choice and translate that into a response that matches the equivalent
     choice on OS X
     */

    int button_clicked = MessageBox ( GetForegroundWindow(), message->c_str(), title->c_str(), type );

    unsigned long response = 0;

    switch ( button_clicked ) {

    case IDOK:
    case IDYES:
        response = kBE_OKButton;
        break;
    case IDCANCEL:
        response = kBE_CancelButton;
        break;
    case IDNO:
        response = kBE_AlternateButton;
        break;
    }

    return response;

} // DisplayDialog
bool OpenURL ( WStringAutoPtr url )
{

    HINSTANCE result = ShellExecute ( NULL, (LPCWSTR)L"open", url->c_str(), NULL, NULL, SW_SHOWNORMAL );

    // see http://msdn.microsoft.com/en-us/library/bb762153(VS.85).aspx

    return ( result > (HINSTANCE)32 );
}
WStringAutoPtr ParameterAsWideString ( const DataVect& parameters, FMX_UInt32 which )
{	
	
	WStringAutoPtr result ( new wstring );
	
	try {
		
		TextAutoPtr raw_data;
		raw_data->SetText ( parameters.AtAsText(which) );
		
		FMX_Int32 text_size = raw_data->GetSize();
		FMX_UInt16 * text = new FMX_UInt16 [ text_size + 1 ];
		raw_data->GetUnicode ( text, 0, text_size );
        text[text_size] = 0x0000;

		// wchar_t is 4 bytes on OS X and 2 on Windows
		
		#if defined(FMX_MAC_TARGET)
		
			wchar_t * parameter = new wchar_t [ text_size + 1 ];
			for ( long i = 0 ; i <= text_size ; i++ ) {
				parameter[i] = (wchar_t)text[i];
			}
			delete [] text;
		
		#endif 
		
		#if defined(FMX_WIN_TARGET)
		
			wchar_t * parameter = (wchar_t*)text;
		
		#endif
		
		result->append ( parameter );
		delete [] parameter; // parameter == text on Windows
				
	} catch ( exception& e ) {
		;	// return an empty string
	}
	
	return result;
	
} // ParameterAsUnicodeString
fmx::errcode DisplayProgressDialog ( const WStringAutoPtr title, const WStringAutoPtr description, const long maximum, const bool can_cancel )
{
	HRESULT result = S_OK;

	if ( progress_dialog ) {
		result = kFileOrObjectIsInUse;
	} else {

		progress_dialog_maximum = maximum;

		HWND parent_window = GetForegroundWindow();
		result = CoCreateInstance ( CLSID_ProgressDialog, NULL, CLSCTX_INPROC_SERVER, IID_IProgressDialog, (void**)&progress_dialog );

		if ( result == S_OK ) {
			result = progress_dialog->SetTitle ( title->c_str () );
		}

		if ( result == S_OK ) {
			result = progress_dialog->SetLine ( 2, description->c_str (), false, NULL );
		}

		DWORD flags = PROGDLG_NORMAL;
		if ( !can_cancel ) {
			flags |= PROGDLG_NOCANCEL;
		}

		if ( 0 == maximum ) {
			flags |= PROGDLG_MARQUEEPROGRESS;
		}

		if ( result == S_OK ) {
			result = progress_dialog->StartProgressDialog ( parent_window, NULL, flags, NULL );
		}

	}

	return (fmx::errcode)result;

} // DisplayProgressDialog
fmx::errcode DisplayProgressDialog ( const WStringAutoPtr title, const WStringAutoPtr description, const long maximum, const bool can_cancel )
{
	fmx::errcode error = kNoError;

	if ( progress_dialog ) {
		return error;
	}

	progress_dialog_maximum = maximum;

	HWND parent_window = GetActiveWindow ( );
	error = CoCreateInstance ( CLSID_ProgressDialog, NULL, CLSCTX_INPROC_SERVER, IID_IProgressDialog, (void**)&progress_dialog );

	if ( error == S_OK ) {
		error = progress_dialog->SetTitle ( title->c_str () );
	}

	if ( error == S_OK ) {
		progress_dialog->SetLine ( 2, description->c_str (), false, NULL );
	}

	DWORD flags = PROGDLG_NORMAL;
	if ( !can_cancel ) {
		flags |= PROGDLG_NOCANCEL;
	}

	if ( 0 == maximum ) {
		flags |= PROGDLG_MARQUEEPROGRESS;
	}

	if ( error == S_OK ) {
		error = progress_dialog->StartProgressDialog ( parent_window, NULL, flags, NULL );
	}

	return error;

} // DisplayProgressDialog
WStringAutoPtr SelectFolder ( WStringAutoPtr prompt, WStringAutoPtr in_folder )
{
    BROWSEINFO browse_info = { 0 };
    browse_info.hwndOwner = GetActiveWindow();
    browse_info.ulFlags = BIF_RETURNONLYFSDIRS | BIF_USENEWUI;
    browse_info.lpszTitle = prompt->c_str();
    if ( !in_folder->empty() ) {
        browse_info.lpfn = SelectFolderCallback;
        browse_info.lParam = (LPARAM)in_folder->c_str();
    }

    LPITEMIDLIST item_list = SHBrowseForFolder ( &browse_info );

    // if the user hasn't cancelled the dialog get the path to the folder

    wchar_t path[MAX_PATH] = L"";

    if ( item_list != 0 ) {
        SHGetPathFromIDList ( item_list, path );
    }

    return WStringAutoPtr ( new wstring ( path ) );

}	//	SelectFolder
WStringAutoPtr SelectFile ( WStringAutoPtr prompt )
{
	CWnd * parent_window = CWnd::FromHandle ( GetActiveWindow() );
	CString filter =  "All Files (*.*)|*.*||";
	CFileDialog file_dialog ( TRUE, NULL, NULL, OFN_HIDEREADONLY, filter, parent_window, 0 );
	file_dialog.m_ofn.lpstrTitle = prompt->c_str();

	// if the user hasn't cancelled the dialog get the path to the file

	wchar_t path[MAX_PATH] = L"";
	
	if ( file_dialog.DoModal() == IDOK ) {
		CString file_path = file_dialog.GetPathName();
		wcscpy_s ( path, (LPCTSTR)file_path );
	}

	return WStringAutoPtr ( new wstring ( path ) );

}	//	SelectFile
WStringAutoPtr SelectFolder ( WStringAutoPtr prompt )
{
	BROWSEINFO browse_info = { 0 };
	browse_info.hwndOwner = GetActiveWindow();
	browse_info.ulFlags = BIF_RETURNONLYFSDIRS | BIF_USENEWUI | BIF_NONEWFOLDERBUTTON;
    browse_info.lpszTitle = prompt->c_str();

    LPITEMIDLIST item_list = SHBrowseForFolder ( &browse_info );
	
	// if the user hasn't cancelled the dialog get the path to the folder

    wchar_t path[MAX_PATH] = L"";

	if ( item_list != 0 ) {
		SHGetPathFromIDList ( item_list, path );
	}

	return WStringAutoPtr ( new wstring ( path ) );

}	//	SelectFolder
StringAutoPtr ClipboardData ( WStringAutoPtr atype )
{
	char * clipboard_data = NULL;

	if ( OpenClipboard ( NULL ) ) {
		
		UINT format_wanted = RegisterClipboardFormat ( atype->c_str() );

		if ( IsClipboardFormatAvailable ( format_wanted ) ) {
			
			HGLOBAL memory_handle = GetClipboardData ( format_wanted );
			unsigned char * clipboard_contents = (unsigned char *)GlobalLock ( memory_handle );
			UINT clipboard_size = GlobalSize ( memory_handle );

			clipboard_data = new char [ clipboard_size + 1 ]();
			memcpy ( clipboard_data, clipboard_contents, clipboard_size );

			GlobalUnlock ( memory_handle );

		}
		
		CloseClipboard();
	
	} 
	
	if ( !clipboard_data ) {
		clipboard_data = new char [ 1 ]();
	}

	/* 
	 prefix the data to place on the clipboard with the size of the data
	 */
	UINT32 offset = ClipboardOffset ( *atype );
	StringAutoPtr reply ( new string ( clipboard_data + offset ) );

	delete[] clipboard_data;

	return reply;

} // ClipboardData
errcode TextConstantFunction ( WStringAutoPtr text, Data& results )
{
	
	errcode error_result = kNoError;
	
	try {
		
		TextAutoPtr result_text;
		result_text->AssignWide ( text->c_str() );
		
		LocaleAutoPtr default_locale;
		results.SetAsText ( *result_text, *default_locale );
		
	} catch ( bad_alloc& e ) {
		error_result = kLowMemoryError;
	} catch ( exception& e ) {
		error_result = kErrorUnknown;
	}
	
	return error_result;
	
} // TextConstantFunction
bool SetClipboardData ( StringAutoPtr data, WStringAutoPtr atype )
{
	bool ok = FALSE;
	
	if ( OpenClipboard ( NULL ) ) {
		
		EmptyClipboard();

		SIZE_T data_size = data->size();

		/* 
		 prefix the data to place on the clipboard with the size of the data
		 */
		SIZE_T offset = ClipboardOffset ( *atype );
		SIZE_T clipboard_size = data_size + offset;
		HGLOBAL memory_handle = GlobalAlloc ( GMEM_SHARE | GMEM_MOVEABLE, clipboard_size );

		unsigned char * clipboard_contents = (unsigned char *)GlobalLock ( memory_handle );
		if ( IsFileMakerClipboardType ( *atype ) == TRUE ) {
			memcpy ( clipboard_contents, &data_size, offset );
		}
		memcpy ( clipboard_contents + offset, data->c_str(), clipboard_size );

		GlobalUnlock ( memory_handle );

		UINT format = RegisterClipboardFormat ( atype->c_str() );
		
		if ( SetClipboardData ( format, clipboard_contents ) ) {
			ok = TRUE;
		}

		CloseClipboard();

	}

	return ok;

}	//	Set_ClipboardData
void SetResult ( const WStringAutoPtr text, Data& results )
{
	TextAutoPtr result_text;
	result_text->AssignWide ( text->c_str() );			
	SetResult ( *result_text, results );
}
FMX_PROC(errcode) BE_ExtractScriptVariables ( short /* funcId */, const ExprEnv& /* environment */, const DataVect& data_vect, Data& results)
{
	errcode error_result = kNoError;
	
	try {
		
		BEWStringVector variables;
		WStringAutoPtr calculation = ParameterAsWideString ( data_vect, 0 );

		wstring search_for = L"$/\""; // variables, comments and strings (including escaped strings)
		size_t found = calculation->find_first_of ( search_for );

		while ( found != wstring::npos )
		{
			size_t end = 0;
			size_t search_from = found + 1;
									
			switch ( calculation->at ( found ) ) {
				case L'$': // variables
				{
					/*
					 find the end of the variable
						+ - * / ^ & = ≠ < > ≤ ≥ ( , ; ) [ ] " :: $ }
					 unicode escapes are required on Windows
					 */
					
					end = calculation->find_first_of ( L" ;+-=*/&^<>\t\r[]()\u2260\u2264\u2265,", search_from );
					if ( end == wstring::npos ) {
						end = calculation->size();
					}

					// add the variable to the list
					wstring wanted = calculation->substr ( found, end - found );
					variables.PushBack ( wanted );
					search_from = end + 1;
				}
				break;
					
				case L'/': // comments
					switch ( calculation->at ( search_from ) ) {
						case L'/':
							end = calculation->find ( L"\r", search_from );
							search_from = end + 1;
							break;
							
						case L'*':
							end = calculation->find ( L"*/", search_from );
							search_from = end + 2;
							break;
							
						default:
							break;
					}
					break;
					
				case L'\"': // escaped strings
					end = calculation->find ( L"\"", search_from );
					while ( (end != string::npos) && (calculation->at ( end - 1 ) == L'\\') ) {
						end = calculation->find ( L"\"", end + 1 );
					}
					search_from = end + 1;
					break;
					
//				default:
			}
			
			// this is not on an eternal quest
			if ( (end != string::npos) && (search_from < calculation->size()) ) { 
				found = calculation->find_first_of ( search_for, search_from );
			} else {
				found = string::npos;
			}
		}
		
		results.SetAsText( *(variables.AsValueList()), data_vect.At(0).GetLocale() );
		
	} catch ( bad_alloc e ) {
		error_result = kLowMemoryError;
	} catch ( exception e ) {
		error_result = kErrorUnknown;
	}
	
	return error_result;
	
} // BE_ExtractScriptVariables