/** 
 *  Yudit Unicode Editor Source File
 *
 *  GNU Copyright (C) 1997-2023  Gaspar Sinai <gaspar@yudit.org>  
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License, version 2,
 *  dated June 1991. See file COPYYING for details.
 *
 *  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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
#ifndef SX11Impl_h
#define SX11Impl_h

#include "stoolkit/SEncoder.h"
#include "stoolkit/SExcept.h"
#include "stoolkit/SString.h"
#include "stoolkit/SEvent.h"
#include "stoolkit/SBinHashtable.h"
#include "stoolkit/SHashtable.h"
#include "stoolkit/SProperties.h"
#include "swindow/SAwt.h"
#include "swindow/SRedrawEvent.h"
#include "swindow/sx11/SXEventHandler.h"

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

/**
 * @author: Gaspar Sinai <gaspar@yudit.org>
 * @version: 2000-04-23
 * This is the abstract widget toolkit
 */

typedef unsigned long SPixel;
typedef SBinHashtable<SWindow*> SWindowHashtable;
typedef SBinHashtable<SWindowListener*> SListenerHashtable;
typedef SHashtable<SRedrawEvent> SRedrawEventTable;


/**
 * This class should be implemented for a window toolkit implementation
 */
class SX11Impl : public SAwtImpl, public SEventTarget
{
public:
  SX11Impl(void);

  virtual ~SX11Impl();
  virtual SWindow* getWindow (SWindowListener* l, const SString& name);
  bool    getKeyboardFocus (SWindow *w);
  virtual SFontNative* getFont (const SString& encoding);

  virtual bool isOK();
  /* My implementation */
  void          addWindow(long id, SWindow* w);
  void          deleteWindow(long id, SWindow* w);
  void          show (long id);
  void          hide (long id);

  void          addRedrawEvent (long id, const SRedrawEvent& evt);
  void          addRedrawChildrenEvent (long id, const SRedrawEvent& evt);
  void          moveRedrawEvent (long id, int xoffset, int yoffset);

  void          setXEventHandler (long id, long type, SXEventHandler* h);
  void          removeXEventHandler (long id, long type);
  void          sendString (long id, const SString& string);

  bool          sendAcceleratorPressed (int key, 
                       bool ctrl, bool shift, bool meta);
  bool          sendAcceleratorReleased ();

  virtual SString  getClipUTF8(long id, bool isPrimary);
  virtual void putClipUTF8 (long id, const SString& utf8, bool isPrimary);

  virtual void setEncoding(const SString& str);

  virtual void addAccelerator (long id, const SAccelerator& a); 
  virtual void removeAccelerator (long id, const SAccelerator& a); 
  long getAnyWindow ();

  void processSelection (const XSelectionRequestEvent& event);
  void processSelection (const XSelectionEvent& event);
  void processSelection (const XSelectionClearEvent& event);

  bool dndEvent (const XEvent& event);
  /*--------------- xdnd stuff --------------------------*/
  void xdndEnter (const XEvent& event);
  void xdndPosition (const XEvent& event);
  void xdndDrop (const XEvent& event);
  void xdndLeave (const XEvent& event);
  void dndProtocol (const XEvent& event);
 
  /*------ good to have's ---------------*/
  Atom toAtom (const SString& str);
  SString getPropertyData (Window window, Atom property, int format);
  SString getSelectionData (Atom dataName, Atom dataType, long id, Time time);

  SBinHashtable<SXEventHandler*> eventHandlerTable;
  SBinHashtable<long>   acceleratorTable;

  bool          accelPressed;
  SAccelerator  currentAccelerator;

  Display*      display;
  Visual*       visual;
  Colormap      colormap;
  int           screen;
  int           cellCount;
  Window        root;
  unsigned int  rootWidth;
  unsigned int  rootHeight;

  XRectangle    rectangle;
  SPixel        background;
  SPixel        foreground;
  unsigned short border;
  Atom          wmProtocols;
  Atom          wmDeleteWindow;
  Atom          xa_clipboard;
  Atom          xa_property_yudit;
  Window        focusWindow;

  Window        clipOwnerPrimary;
  Window        clipOwnerSecondary;
  SEncoder      encoder; // used for clip.
  SString       clipBufferPrimary;
  SString       clipBufferSecondary;

  SInputStream  in;

  SWindowHashtable   windowHashtable;
  SListenerHashtable listenerHashtable;
  SRedrawEventTable  redrawEventTable;
  /* SEventTarget */
  int           readable(const SEventSource* s);
  bool          doX();
  bool          doXLoop();
  long          shown;
  SJob*         job;
  bool          done (const SEventSource* s); 
  long          needFocusWhenMapped;
  Window        getTopLevelWindow (Window w);

private:
  bool               isOKToDeliver (long id);
  
  Window             xdndSource;
  SString            acceptedDataType;
  Atom               acceptedDataTypeAtom;
  SBinVector<Atom>   dndTypes;
  SBinVector<long>   modalStack;
  SBinVector<long>   modalFocusStack;
};

#endif /* SX11Impl_h */
