/******************************************************************************
 JXSelectionManager.h

	Interface for JXSelectionManager class.

	Copyright © 1996-98 by John Lindal. All rights reserved.

 ******************************************************************************/

#ifndef _H_JXSelectionManager
#define _H_JXSelectionManager

#include <JArray.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>

class JXDisplay;
class JXWindow;
class JXWidget;

const Atom kJXClipboardName = XA_PRIMARY;

class JXSelectionManager : virtual public JBroadcaster
{
	friend class JXWidget;

public:

	enum DeleteMethod
	{
		kArrayDelete,
		kXFree,
		kCFree
	};

public:

	JXSelectionManager(JXDisplay* display);

	virtual ~JXSelectionManager();

	JBoolean	GetSelectionOwner(const Atom selectionName, const Time time,
								  JXWidget** owner);

	JBoolean	GetAvailableTypes(const Atom selectionName, const Time time,
								  const JXWindow* window, JArray<Atom>* typeList);
	JBoolean	GetSelectionData(const Atom selectionName, const Time time,
								 const JXWindow* window, const Atom requestType,
								 Atom* returnType,
								 unsigned char** data, JSize* dataLength,
								 DeleteMethod* delMethod);
	void		DeleteSelectionData(unsigned char** data, const DeleteMethod delMethod);

	void	SendDeleteSelectionRequest(const Atom selectionName, const Time time,
									   const JXWindow* window);

	Atom	GetTargetsXAtom() const;
	Atom	GetTimeStampXAtom() const;
	Atom	GetTextXAtom() const;
	Atom	GetCompoundTextXAtom() const;
	Atom	GetMultipleXAtom() const;
	Atom	GetMimePlainTextXAtom() const;
	Atom	GetURLXAtom() const;

	Atom	GetDeleteSelectionXAtom() const;
	Atom	GetNULLXAtom() const;

	// called by JXDisplay

	void	HandleSelectionRequest(const XSelectionRequestEvent& selReqEvent);
	void	ClearSelectionOwner(const Atom selectionName);

protected:

	virtual void	ReceiveWithFeedback(JBroadcaster* sender, Message* message);

private:

	struct OwnerInfo
	{
		Atom		name;
		JXWidget*	owner;		// not owned
		Window		xWindow;	// not owned
		Time		startTime;

		OwnerInfo()
			:
			name(None), owner(NULL), xWindow(None)
		{ };

		OwnerInfo(Atom n, JXWidget* o, Window xw, Time t)
			:
			name(n), owner(o), xWindow(xw), startTime(t)
		{ };
	};

private:

	JXDisplay*			itsDisplay;		// we don't own this
	JArray<OwnerInfo>*	itsOwnerList;	// sorted by selection name

	JSize		itsMaxDataChunkSize;	// max # of 4-byte blocks that we can send
	JBoolean	itsReceivedAllocErrorFlag;
	Window		itsTargetWindow;
	JBoolean	itsTargetWindowDeletedFlag;

	Atom itsSelectionWindPropXAtom;		// for receiving selection data
	Atom itsIncrementalSendXAtom;		// for sending data incrementally

	Atom itsTargetsXAtom;				// returns type XA_ATOM
	Atom itsTimeStampXAtom;				// returns type XA_INTEGER
	Atom itsTextXAtom;					//  8-bit characters
	Atom itsCompoundTextXAtom;			// 16-bit characters
	Atom itsMultipleXAtom;				// several formats at once
	Atom itsMimePlainTextXAtom;			// text/plain
	Atom itsURLXAtom;					// text/uri-list
	Atom itsDeleteSelectionXAtom;		// returns type "NULL"
	Atom itsNULLXAtom;					// "NULL"

private:

	JBoolean	RequestSelectionData(const Atom selectionName, const Time time,
									 const Window xWindow, const Atom type,
									 XSelectionEvent* selEvent);

	void		SendSelectionData(const Window requestor, const Atom property,
								  const Atom type, unsigned char* data,
								  const JSize dataLength, const JSize bitsPerBlock,
								  XEvent* returnEvent);
	JBoolean	SendSelectionData1(const Window requestor, const Atom property,
								   const Atom type, unsigned char* data,
								   const JSize dataLength, const JSize bitsPerBlock);
	JBoolean	WaitForPropertyDeleted(const Window xWindow, const Atom property);
	static Bool	GetNextPropDeletedEvent(Display* display, XEvent* event, char* arg);

	JBoolean	ReceiveSelectionDataIncr(const Atom selectionName, const Window xWindow,
										 Atom* returnType, unsigned char** data,
										 JSize* dataLength, DeleteMethod* delMethod);
	JBoolean	WaitForPropertyCreated(const Window xWindow, const Atom property,
									   const Window sender);
	static Bool	GetNextNewPropertyEvent(Display* display, XEvent* event, char* arg);

	static JOrderedSetT::CompareResult
		CompareSelectionNames(const OwnerInfo& info1, const OwnerInfo& info2);

	// for use by JXWidget

	JBoolean	BecomeOwner(JXWidget* widget, const Atom selectionName);
	void		RelinquishOwnership(JXWidget* widget, const Atom selectionName);

	// not allowed

	JXSelectionManager(const JXSelectionManager& source);
	const JXSelectionManager& operator=(const JXSelectionManager& source);
};


/******************************************************************************
 Get atom

 ******************************************************************************/

inline Atom
JXSelectionManager::GetTargetsXAtom()
	const
{
	return itsTargetsXAtom;
}

inline Atom
JXSelectionManager::GetTimeStampXAtom()
	const
{
	return itsTimeStampXAtom;
}

inline Atom
JXSelectionManager::GetTextXAtom()
	const
{
	return itsTextXAtom;
}

inline Atom
JXSelectionManager::GetCompoundTextXAtom()
	const
{
	return itsCompoundTextXAtom;
}

inline Atom
JXSelectionManager::GetMultipleXAtom()
	const
{
	return itsMultipleXAtom;
}

inline Atom
JXSelectionManager::GetMimePlainTextXAtom()
	const
{
	return itsMimePlainTextXAtom;
}

inline Atom
JXSelectionManager::GetURLXAtom()
	const
{
	return itsURLXAtom;
}

inline Atom
JXSelectionManager::GetDeleteSelectionXAtom()
	const
{
	return itsDeleteSelectionXAtom;
}

inline Atom
JXSelectionManager::GetNULLXAtom()
	const
{
	return itsNULLXAtom;
}

#endif
