/*  Inti: Integrated Foundation Classes
 *  Copyright (C) 2002 The Inti Development Team.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

//! @file inti/glib/error.h
//! @brief A C++ GLib error reporting class.
//!
//! GLib provides a standard method of reporting errors from a called function to the calling code.
//! It's important to understand that this method is both a data type (the G::Error object) and a
//! set of rules. If you use G::Error incorrectly, then your code will not properly interoperate
//! with other code that uses G::Error, and users of your API will probably get confused.

#ifndef INTI_G_ERROR_H
#define INTI_G_ERROR_H

#ifndef INTI_STACK_OBJECT_H
#include <inti/stackobject.h>
#endif

#ifndef INTI_UTF_STRING_H
#include <inti/utf-string.h>
#endif

#ifndef __G_ERROR_H__
#include <glib/gerror.h>
#endif

namespace Inti {

namespace G {

class Quark;

//! @class Error error.h inti/glib/error.h
//! @brief A C++ GLib error reporting class.
//!
//! Error provides a C++ wrapper for GLib's standard method of reporting errors from a called
//! function to the calling code. It's important to understand that this method is both a data type
//! (the Error object) and a set of rules. If you use Error incorrectly, then your code will
//! not properly interoperate with other code that uses Error, and users of your API will probably
//! get confused.
//!
//! First and foremost: Error should only be used to report recoverable runtime errors, never to
//! report programming errors. If the programmer has screwed up, then you should use g_warning(),
//! g_return_if_fail(), g_assert(), g_error(), or some similar facility. (Incidentally, remember that
//! the g_error() function should only be used for programming errors, it should not be used to print
//! any error reportable via G::Error.)
//!
//! Examples of recoverable runtime errors are "file not found" or "failed to parse input". Runtime 
//! errors should be handled or reported to the user, programming errors should be eliminated by
//! fixing the bug in the program. This is why most functions in Inti do not use the Error facility.
//! You will find examples of Error usage in the inti-demo program. The following example is from
//! "demowindow.cc".
//! @code
//! Pointer<Gdk::Pixbuf> pixbuf;
//! G::Error error;
//!
//! String filename = find_file("gtk-logo-rgb.gif", &error);
//! if (!filename.null())
//! 	pixbuf = new Gdk::Pixbuf(filename, &error);
//!
//! if (error.get())
//! {
//! 	Gtk::MessageDialog dialog(Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, this);
//! 	dialog.set_message("Failed to read icon file: %s", error.message());
//! 	dialog.set_position(Gtk::WIN_POS_CENTER);
//! 	dialog.run();
//! 	dialog.dispose();
//! }
//! @endcode
//! <BR>Note that passing NULL for the error location ignores errors.

class Error : public StackObject
{
	GError *error_;

public:
//! @name Constructors
//! @{

	Error();
	//!< Create a properly initialized error object.

	Error(GQuark domain, int code, const char *format, ...);
	//!< Create a new error object with the given domain and code, and a message formatted with format.
	//!< @param domain The error domain.
	//!< @param code The error code.
	//!< @param format Parameters for message format.
	//!< @param ... Arguments to format.

	Error(GQuark domain, int code, const String& message);
	//!< Create a new error object with the given domain, code, and message.
	//!< @param domain The error domain.
	//!< @param code The error code.
	//!< @param message The error message.
	//!<
	//!< <BR>Unlike the other constructor, message is not a printf()-style format string. Use
	//!< this constructor if message contains text you don't have control over, that could include
	//!< printf() escape sequences.

	Error(GError *error);
	//!< Create an Error from an existing GError*. Used by Inti for error reporting.

	Error(const Error& src);
	//!< Copy constructor.

	~Error();
	//!< Destructor.

	Error& operator=(const Error& src);
	//!< Assignment operator.

//! @}
//! @name Accessors
//! @{

	operator GError* () const;
	//!< Returns the internal GError pointer.

	operator GError** ();
	//!< The return location for an allocated error

	bool get() const;
	//!< Returns true if the error-reporting function failed and reported an error.

	bool matches(GQuark domain, int code) const;
	//!< Returns <EM>true</EM> if error matches domain and code, <EM>false</EM> otherwise.
	//!< @param domain An error domain.
	//!< @param code An error code.
	//!< @return Whether error has domain and code.

	Quark domain() const;
	//!< Returns the error domain.

	int code() const;
	//!< Returns the error code.

	const char* message() const;
	//!< Returns the human-readable informative error message.

//! @}
//! @name Methods
//! @{

	void set(GQuark domain, int code, const char *format, ...);
	//!< A new error object is created and assigned to the internal error pointer.
	//!< @param domain The error domain.
	//!< @param code The error code.
	//!< @param format printf()-style message format.
	//!< @param ... Arguments to format.
	
	void set(GQuark domain, int code, const String& message);
	//!< A new error object is created and assigned to the internal error pointer.
	//!< @param domain The error domain.
	//!< @param code The error code.
	//!< @param message The error message.
	//!<
	//!< <BR>Unlike the other set method, message is not a printf()-style format string. Use
	//!< this method if message contains text you don't have control over, that could include
	//!< printf() escape sequences.

	void propagate(const Error& src);
	//!< Moves src into the calling error object.

	void clear();
	//!< Frees the associated GError object and sets the internal error pointer to null.

//! @}
};

} // namespace G

} // namespace Inti

#endif // INTI_G_ERROR_H
