/* GDK - The GIMP Drawing Kit
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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 library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <string.h>
#include "gdk.h"
#include "gdkprivate.h"


gint
gdk_selection_owner_set (GdkWindow *owner,
			 GdkAtom    selection,
			 guint32    time,
			 gint       send_event)
{
  GdkWindowPrivate *private;
  Display *xdisplay;
  Window xwindow;
  int type;

  if (owner)
    {
      private = (GdkWindowPrivate*) owner;
      xdisplay = private->xdisplay;
      xwindow = private->xwindow;
    }
  else
    {
      xdisplay = gdk_display;
      xwindow = None;
    }

  XSetSelectionOwner (xdisplay, selection, xwindow, time);
  if (XGetSelectionOwner (xdisplay, selection) == xwindow)
    {
      switch (selection)
	{
	case GDK_SELECTION_PRIMARY:
	  type = 0;
	  break;
	case GDK_SELECTION_SECONDARY:
	  type = 1;
	  break;
	default:
	  type = -1;
	}

      if (send_event && selection_owner[type] && (selection_owner[type] != owner))
	{
	  GdkEventSelection event;

	  event.type = GDK_SELECTION_CLEAR;
	  event.window = selection_owner[type];
	  event.selection = selection;
	  event.time = time;

	  gdk_event_put ((GdkEvent*) &event);
	}

      selection_owner[type] = owner;
      return TRUE;
    }
  return FALSE;
}

GdkWindow*
gdk_selection_owner_get (GdkAtom selection)
{
  Window xwindow;

  xwindow = XGetSelectionOwner (gdk_display, selection);
  if (xwindow == None)
    return NULL;

  return gdk_window_lookup (xwindow);
}

void
gdk_selection_convert (GdkWindow *requestor,
		       GdkAtom    selection,
		       guint32    time)
{
  GdkWindowPrivate *private;

  g_return_if_fail (requestor != NULL);

  private = (GdkWindowPrivate*) requestor;

  XConvertSelection (private->xdisplay, selection, XA_STRING,
		     gdk_selection_property, private->xwindow, time);
}

void
gdk_selection_get (GdkWindow  *requestor,
		   guchar    **data)
{
  GdkWindowPrivate *private;
  Atom prop_type;
  gint prop_format;
  gulong nitems;
  gulong nbytes;
  gulong length;
  guchar *t;

  g_return_if_fail (requestor != NULL);

  private = (GdkWindowPrivate*) requestor;

  XGetWindowProperty (private->xdisplay, private->xwindow,
		      gdk_selection_property, 0, 0, False,
		      AnyPropertyType, &prop_type, &prop_format,
		      &nitems, &nbytes, &t);
  XFree (t);

  if (prop_type != XA_STRING)
    {
      XDeleteProperty (private->xdisplay, private->xwindow, gdk_selection_property);
    }
  else
    {
      length = nbytes + 1;

      XGetWindowProperty (private->xdisplay, private->xwindow,
			  gdk_selection_property, 0, (nbytes + 3) / 4, True,
			  XA_STRING, &prop_type, &prop_format,
			  &nitems, &nbytes, &t);

      *data = g_new (guchar, length);
      memcpy (*data, t, length);
      XFree (t);
    }
}

void
gdk_selection_set (guint32  requestor,
		   GdkAtom  selection,
		   GdkAtom  property,
		   guint32  time,
		   guchar  *data,
		   gint     length)
{
  XSelectionEvent xevent;

  if (property != None)
    XChangeProperty (gdk_display, requestor,
		     property, XA_STRING, 8,
		     PropModeReplace, data,
		     length);

  xevent.type = SelectionNotify;
  xevent.serial = 0;
  xevent.send_event = True;
  xevent.display = gdk_display;
  xevent.requestor = requestor;
  xevent.selection = selection;
  xevent.target = XA_STRING;
  xevent.property = property;
  xevent.time = time;

  XSendEvent (gdk_display, requestor, False, 0, (XEvent*) &xevent);
}
