// ----
// ----    file: Clipboard_scrap.cpp
// ----  author: (C) 2002, 2005 Sam Lantinga, Bastian Spiegel <bs@tkscript.de>, Carsten Busse <car.busse@gmx.de>
// ----  
// ----    date: 27-Jun-2005, 29-Jun-2005
// ---- license: Distributed under terms of the Lesser General Public License (LGPL). 
// ----          See <http://www.gnu.org/licenses/licenses.html#LGPL> for further information.
// ----
// ----    note: See <http://www.libsdl.org/projects/scrap/> for the original "scrap" package.
// ----          This file is based on Sam Lantingas "scrap" code, it has been slightly modified
// ----          for the "tksdl" plugin.
// ----          Parts of clipboard_filter were copied from the "Battle of Wesnoth" project <http://wesnoth.org>
// ----          The scrap win32 code was copied from my Clipboard_win32.cpp code (the original scrap code did 
// ----          not work on my win2k machine).
// ----


#include <math.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>

#define YAC_BIGSTRING defined
#include <yac.h>


#ifdef YAC_WIN32
#include <windows.h>
#include <ddraw.h>
#endif

#include "HAL.h"
extern YAC_Host *yac_host;

#include "Clipboard.h"



#ifdef TKSDL_SCRAP_CLIPBOARD 





/* Determine what type of clipboard we are using */
#ifdef YAC_WIN32
#define WIN_SCRAP
#else
#ifdef YAC_QNX
#define QNX_SCRAP
#else
#define X11_SCRAP 
#endif
#endif


#define MAX_CLIPBOARD_SIZE 1024*256

#define T(A, B, C, D)	(int)((A<<24)|(B<<16)|(C<<8)|(D<<0)) 
#define Ph_CL_TEXT T('T', 'E', 'X', 'T')

void put_scrap(int type, int srclen, char *src);
void get_scrap(int type, int *dstlen, char **dst); 
int init_scrap(void);

#ifdef X11_SCRAP
void SetCutBuffer(YAC_String *);
#endif

void SDL_SetClipboard(YAC_Object *_o) {
   ////yac_host->printf("SDL_SetClipboard()\n");
   if(YAC_BCHK(_o, YAC_CLID_STRING))
   {
      YAC_String *s=(YAC_String*)_o;
      if((s->length>1)&&(s->length<MAX_CLIPBOARD_SIZE))
      {
         tks_HAL->scrap_string.copy((sChar*)s->chars);
         put_scrap(Ph_CL_TEXT, s->length, (char*)s->chars);
#ifdef X11_SCRAP
         SetCutBuffer(s);
#endif
      }
      ////yac_host->printf("[...] tksdl::SDL_SetClipboard(): copied string \"%s\" to clipboard.\n", (char*)s->chars);
   }
}

void SDL_GetClipboard(YAC_Value *_r) {
  ////yac_host->printf("SDL_GetClipboard\n");
   YAC_String *s=YAC_New_String();
   if(s)
   {
      _r->initString(s, 1);
      
      int dstlen=0;
      char *dst=NULL;
      get_scrap(Ph_CL_TEXT, &dstlen, &dst);
      if( (dst != NULL) && (dstlen > 0) )
      {
         YAC_String t; t.visit(dst);
         s->yacCopy(&t);
         tks_HAL->scrap_string.copy(dst);
         ////yac_host->printf("Got String %s from clipboard\n",dst);
         ::free((void*)dst);
      }
   }
   else
   {
      _r->initObject(NULL, 0);
   }
}



/* Handle clipboard text and data in arbitrary formats */

#include <stdio.h>
#include <limits.h>

#include "sdl_includes.h"

////#include "scrap.h"

/* Miscellaneous defines */
#define PUBLIC
#define PRIVATE	static




/* System dependent data types */
#if defined(X11_SCRAP)
/* * */
typedef Atom scrap_type;
Atom clipboardAtom;
Atom utf8Atom;

void SetCutBuffer(YAC_String *s) {
   if (s->length>1) 
   {
      SDL_SysWMinfo wmInf_;
      SDL_VERSION(&wmInf_.version);
      if (SDL_GetWMInfo(&wmInf_)) 
      {
         Display *disp=wmInf_.info.x11.display;
         ////yac_host->printf("SetCutBuffer Copying string (%s) of %d bytes length into a global buffer, also got Display Ptr %p\n", s->chars,s->length, disp);
         XStoreBytes(disp,(const char*)s->chars,s->length);
      } 
      else 
      {
         yac_host->printf("[---] tksdl::SetCutBuffer_x11: SDL_GetWMInfo() failed.\n");
         return;
      }
   }
}

#elif defined(WIN_SCRAP)
/* * */
typedef UINT scrap_type;

#elif defined(QNX_SCRAP)
/* * */
typedef uint32_t scrap_type;

#endif /* scrap type */

/* System dependent variables */
#if defined(X11_SCRAP)
/* * */
static Display *SDL_Display;
static Window SDL_Window;
static void (*Lock_Display)(void);
static void (*Unlock_Display)(void);

#elif defined(WIN_SCRAP)
/* * */
static HWND SDL_Window;

#elif defined(QNX_SCRAP)
/* * */
static unsigned short InputGroup;

#endif /* scrap type */

#define FORMAT_PREFIX	"SDL_scrap_0x"

PRIVATE scrap_type
convert_format(int type)
{
   switch (type)
   {
      
   case T('T', 'E', 'X', 'T'):
#if defined(X11_SCRAP)
      /* * */
      return XA_STRING;
      
#elif defined(WIN_SCRAP)
      /* * */
      return CF_TEXT;
      
#elif defined(QNX_SCRAP)
      /* * */
      return Ph_CL_TEXT;
      
#endif /* scrap type */
      
   default:
      {
         char format[sizeof(FORMAT_PREFIX)+8+1];
         
         sprintf(format, "%s%08lx", FORMAT_PREFIX, (unsigned long)type);
         
#if defined(X11_SCRAP)
         /* * */
         return XInternAtom(SDL_Display, format, False);
         
#elif defined(WIN_SCRAP)
         /* * */
         return CF_TEXT;////RegisterClipboardFormat(format);
         
#endif /* scrap type */
      }
   }
}

/* Convert internal data to scrap format */
PRIVATE int
convert_data(int type, char *dst, char *src, int srclen)
{
   int dstlen;
   
   dstlen = 0;
   switch (type)
   {
   case T('T', 'E', 'X', 'T'):
      if ( dst )
      {
         while ( --srclen >= 0 )
         {
#if defined(__unix__)
            if ( *src == '\r' )
            {
               *dst++ = '\n';
               ++dstlen;
            }
            else
#elif defined(__WIN32__)
               if ( *src == '\r' )
               {
                  *dst++ = '\r';
                  ++dstlen;
                  *dst++ = '\n';
                  ++dstlen;
               }
               else
#endif
               {
                  *dst++ = *src;
                  ++dstlen;
               }
               ++src;
         }
         *dst = '\0';
         ++dstlen;
      }
      else
      {
         while ( --srclen >= 0 )
         {
#if defined(__unix__)
            if ( *src == '\r' )
            {
               ++dstlen;
            }
            else
#elif defined(__WIN32__)
               if ( *src == '\r' )
               {
                  ++dstlen;
                  ++dstlen;
               }
               else
#endif
               {
                  ++dstlen;
               }
               ++src;
         }
         ++dstlen;
      }
      break;
      
   default:
      if ( dst )
      {
         *(int *)dst = srclen;
         dst += sizeof(int);
         memcpy(dst, src, srclen);
      }
      dstlen = sizeof(int)+srclen;
      break;
   }
   return(dstlen);
}

/* Convert scrap data to internal format */
PRIVATE int
convert_scrap(int type, char *dst, char *src, int srclen)
{
   int dstlen;
   
   dstlen = 0;
   switch (type)
   {
   case T('T', 'E', 'X', 'T'):
      {
         if ( srclen == 0 )
            srclen = strlen(src);
         if ( dst )
         {
            while ( --srclen >= 0 )
            {
#if defined(__WIN32__)
               if ( *src == '\r' )
                  /* drop extraneous '\r' */;
                  else
#endif

#if 0
                  if ( *src == '\n' )
                  {
                     *dst++ = '\r';
                     ++dstlen;
                  }
                  else
#endif // 0
                  {
                     *dst++ = *src;
                     ++dstlen;
                  }
                  ++src;
            }
            *dst = '\0';
            ++dstlen;
         }
         else
         {
            while ( --srclen >= 0 )
            {
#if defined(__WIN32__)
               if ( *src == '\r' )
                  /* drop extraneous '\r' */;
                  else
#endif
                  ++dstlen;
               ++src;
            }
            ++dstlen;
         }
      }
      break;
      
   default:
      dstlen = *(int *)src;
      if ( dst )
      {
         if ( srclen == 0 )
            memcpy(dst, src+sizeof(int), dstlen);
         else
            memcpy(dst, src+sizeof(int), srclen-sizeof(int));
      }
      break;
   }
   return dstlen;
}

#if defined(X11_SCRAP)
/* The system message filter function -- handle clipboard messages */
PRIVATE int clipboard_filter(const SDL_Event *event);
#endif

PUBLIC int
init_scrap(void)
{
   SDL_SysWMinfo info;
   int retval;
   
   /* Grab the window manager specific information */
   retval = -1;
   SDL_SetError("[---] tksdl::init_scrap: SDL is not running on known window manager");
   
   SDL_VERSION(&info.version);
   if ( SDL_GetWMInfo(&info) )
   {
      /* Save the information for later use */
#if defined(X11_SCRAP)
      /* * */
      if ( info.subsystem == SDL_SYSWM_X11 )
      {
         SDL_Display = info.info.x11.display;
         SDL_Window = info.info.x11.window;
         Lock_Display = info.info.x11.lock_func;
         Unlock_Display = info.info.x11.unlock_func;
         
         clipboardAtom=XInternAtom(SDL_Display, "CLIPBOARD", 1);
         utf8Atom=XInternAtom(SDL_Display,"UTF8_STRING",1);
         
         /* Enable the special window hook events */
         SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
         SDL_SetEventFilter(clipboard_filter);
         
         retval = 0;
      }
      else
      {
         SDL_SetError("SDL is not running on X11");
      }
      
#elif defined(WIN_SCRAP)
      /* * */
      SDL_Window = info.window;
      retval = 0;
      
#elif defined(QNX_SCRAP)
      /* * */
      InputGroup=PhInputGroup(NULL);
      retval = 0;
      
#endif /* scrap type */
   }
   return(retval);
}

PUBLIC int
lost_scrap(void)
{
   int retval;
   
#if defined(X11_SCRAP)
   /* * */
   Lock_Display();
   retval = ( XGetSelectionOwner(SDL_Display, XA_PRIMARY) != SDL_Window );
   Unlock_Display();
   
#elif defined(WIN_SCRAP)
   /* * */
   retval = ( GetClipboardOwner() != SDL_Window );
   
#elif defined(QNX_SCRAP)
   /* * */
   retval = ( PhInputGroup(NULL) != InputGroup );
   
#endif /* scrap type */
   
   return(retval);
}

PUBLIC void
put_scrap(int type, int srclen, char *src)
{
   scrap_type format;
   int dstlen;
   char *dst;

   format = convert_format(type);
   dstlen = convert_data(type, NULL, src, srclen);
   
#if defined(X11_SCRAP)
   /* * */
   dst = (char *)malloc(dstlen);
   if ( dst != NULL )
   {
      Lock_Display();
      convert_data(type, dst, src, srclen);
      //////yac_host->printf("convert data dst=\"%s\"END format %d %s\n", dst,format,XGetAtomName(SDL_Display,format));
      XChangeProperty(
                     SDL_Display,                     // "the connection to the X server."
                     DefaultRootWindow(SDL_Display),  // "the window whose property you want to change."
                     XA_CUT_BUFFER0,                  // "the property name."
                     format,                          // "the type of the property. The X server does not interpret the type but simply passes it back to an application that later calls XGetWindowProperty()."
                     8,                               // "whether the data should be viewed as a list of 8-bit, 16-bit, or 32-bit quantities. Possible values are 8, 16, and 32. This information allows the X server to correctly perform byte-swap operations as necessary. If the format is 16-bit or 32-bit, you must explicitly cast your data pointer to an (unsigned char *) in the call to XChangeProperty()."
                     PropModeReplace,                 // "the mode of the operation. You can pass PropModeReplace, PropModePrepend, or PropModeAppend."
                     (const unsigned char*)dst,       // "the property data."
                     dstlen                           // "the number of elements of the specified data format."
                     );
         
         if ( lost_scrap() )
         {
            XSetSelectionOwner(SDL_Display, XA_PRIMARY, SDL_Window, CurrentTime);
            XSetSelectionOwner(SDL_Display, clipboardAtom, SDL_Window, CurrentTime);
         }
         //      XFlush(SDL_Display);
         free(dst);
         Unlock_Display();
   }
   
#elif defined(WIN_SCRAP)
   {
      HANDLE hMem;
      
      hMem = GlobalAlloc((GMEM_MOVEABLE|GMEM_DDESHARE|GMEM_ZEROINIT), dstlen);
      if ( hMem != NULL )
      {
         dst = (char *)GlobalLock(hMem);
         convert_data(type, dst, src, srclen);
         GlobalUnlock(hMem);
         if ( OpenClipboard(SDL_Window) )
         {
            EmptyClipboard();
            SetClipboardData(CF_TEXT, hMem);
            CloseClipboard();
         }
         /*if(::GlobalDiscard(hMem)==NULL)
         {
            yac_host->printf("[---] SDL_SetClipboard_win32(): ::GlobalDiscard() failed with error code %08x.\n",
                ::GetLastError());
         }*/
      }
   }
   
#elif defined(QNX_SCRAP)
   /* * */
#if (_NTO_VERSION < 620) /* before 6.2.0 releases */
   {
      PhClipHeader clheader={Ph_CLIPBOARD_TYPE_TEXT, 0, NULL};
      int* cldata;
      int status;
      
      dst = (char *)malloc(dstlen+4);
      if (dst != NULL)
      {
         cldata=(int*)dst;
         *cldata=type;
         convert_data(type, dst+4, src, srclen);
         clheader.data=dst;
         if (dstlen>65535)
         {
            clheader.length=65535; /* maximum photon clipboard size :( */
         }
         else
         {
            clheader.length=dstlen+4;
         }
         status=PhClipboardCopy(InputGroup, 1, &clheader);
         if (status==-1)
         {
            fprintf(stderr, "Photon: copy to clipboard was failed !\n");
         }
         free(dst);
      }
   }
#else /* 6.2.0 and 6.2.1 and future releases */
   {
      PhClipboardHdr clheader={Ph_CLIPBOARD_TYPE_TEXT, 0, NULL};
      int* cldata;
      int status;
      
      dst = (char *)malloc(dstlen+4);
      if (dst != NULL)
      {
         cldata=(int*)dst;
         *cldata=type;
         convert_data(type, dst+4, src, srclen);
         clheader.data=dst;
         clheader.length=dstlen+4;
         status=PhClipboardWrite(InputGroup, 1, &clheader);
         if (status==-1)
         {
            fprintf(stderr, "Photon: copy to clipboard was failed !\n");
         }
         free(dst);
      }
   }
#endif
#endif /* scrap type */
}

PUBLIC void
get_scrap(int type, int *dstlen, char **dst)
{
   scrap_type format;
   
   *dstlen = 0;

   format = convert_format(type);
   
#if defined(X11_SCRAP)
   /* * */
   {
      Window owner;
      Atom selection;
      Atom seln_type;
      int seln_format;
      unsigned long nbytes;
      unsigned long overflow;
      char *src;
      
      Lock_Display();
      owner = XGetSelectionOwner(SDL_Display, XA_PRIMARY);
      Unlock_Display();
      if ( (owner == None) || (owner == SDL_Window) )
      {
         owner = DefaultRootWindow(SDL_Display);
         selection = XA_CUT_BUFFER0;
      }
      else
      {
  	int selection_response = 0;
	SDL_Event event;
         
         owner = SDL_Window;
         Lock_Display();
         selection = XInternAtom(SDL_Display, "SDL_SELECTION", False);
         XConvertSelection(SDL_Display, XA_PRIMARY, format,
			   selection, owner, CurrentTime);
         Unlock_Display();
	 XFlush(SDL_Display);
         while ( ! selection_response )
         {
            SDL_WaitEvent(&event);
            if ( event.type == SDL_SYSWMEVENT )
            {
               XEvent xevent = event.syswm.msg->event.xevent;
               
               if ( (xevent.type == SelectionNotify) &&
                  (xevent.xselection.requestor == owner) )
                  selection_response = 1;
            }
         }
      }
      Lock_Display();
      if ( XGetWindowProperty(SDL_Display, owner, selection, 0, INT_MAX/4,
         False, format, &seln_type, &seln_format,
         &nbytes, &overflow, (unsigned char **)&src) == Success )
      {
         if ( seln_type == format )
         {
            *dstlen = convert_scrap(type, NULL, src, nbytes);
            *dst = (char *)realloc(*dst, *dstlen);
            if ( *dst == NULL )
               *dstlen = 0;
            else
               convert_scrap(type, *dst, src, nbytes);
         }
         XFree(src);
      }
   }
   Unlock_Display();
   
#elif defined(WIN_SCRAP)
   /* * */
   if(::OpenClipboard(NULL))
   {
      HGLOBAL hMem = ::GetClipboardData(CF_TEXT);
      if(hMem!=NULL)
      {
         LPTSTR src = (LPTSTR)::GlobalLock(hMem);
         if(src!=NULL)
         {
            *dstlen=strlen(src)+1;
            *dst=(char*)realloc(*dst, *dstlen);
            if(*dst == NULL)
               *dstlen=0;
            else
               ::strcpy(*dst, src);
            ::GlobalUnlock(hMem);
         }
      }
      ::CloseClipboard();
   }
   else
   {
      yac_host->printf("[---] SDL_SetClipboard_win32(): ::OpenClipboard() failed.\n");
   }
   /*if ( IsClipboardFormatAvailable(format) && OpenClipboard(SDL_Window) )
   {
      HANDLE hMem;
      char *src;
      
      hMem = GetClipboardData(format);
      if ( hMem != NULL )
      {
         src = (char *)GlobalLock(hMem);
         if(src!=NULL)
         {
            *dstlen = convert_scrap(type, NULL, src, 0);
            *dst = (char *)realloc(*dst, *dstlen);
            if ( *dst == NULL )
               *dstlen = 0;
            else
               convert_scrap(type, *dst, src, 0);
            GlobalUnlock(hMem);
         }
      }
      CloseClipboard();
   }*/
#elif defined(QNX_SCRAP)
   /* * */
#if (_NTO_VERSION < 620) /* before 6.2.0 releases */
   {
      void* clhandle;
      PhClipHeader* clheader;
      int* cldata;
      
      clhandle=PhClipboardPasteStart(InputGroup);
      if (clhandle!=NULL)
      {
         clheader=PhClipboardPasteType(clhandle, Ph_CLIPBOARD_TYPE_TEXT);
         if (clheader!=NULL)
         {
            cldata=clheader->data;
            if ((clheader->length>4) && (*cldata==type))
            {
               *dstlen = convert_scrap(type, NULL, (char*)clheader->data+4, clheader->length-4);
               *dst = (char *)realloc(*dst, *dstlen);
               if (*dst == NULL)
               {
                  *dstlen = 0;
               }
               else
               {
                  convert_scrap(type, *dst, (char*)clheader->data+4, clheader->length-4);
               }
            }
         }
         PhClipboardPasteFinish(clhandle);
      }
   }
#else /* 6.2.0 and 6.2.1 and future releases */
   {
      void* clhandle;
      PhClipboardHdr* clheader;
      int* cldata;
      
      clheader=PhClipboardRead(InputGroup, Ph_CLIPBOARD_TYPE_TEXT);
      if (clheader!=NULL)
      {
         cldata=clheader->data;
         if ((clheader->length>4) && (*cldata==type))
         {
            *dstlen = convert_scrap(type, NULL, (char*)clheader->data+4, clheader->length-4);
            *dst = (char *)realloc(*dst, *dstlen);
            if (*dst == NULL)
            {
               *dstlen = 0;
            }
            else
            {
               convert_scrap(type, *dst, (char*)clheader->data+4, clheader->length-4);
            }
         }
      }
   }
#endif
#endif /* scrap type */
}

#if defined(X11_SCRAP)
PRIVATE int clipboard_filter(const SDL_Event *event)
{
   /* Post all non-window manager specific events */
   if ( event->type != SDL_SYSWMEVENT ) {
      return(1);
   }
   
   /* Handle window-manager specific clipboard events */
   switch (event->syswm.msg->event.xevent.type) {
      /* Copy the selection from XA_CUT_BUFFER0 to the requested property */
   case SelectionRequest: {
      XSelectionRequestEvent *req;
#if 0
      XEvent sevent;
#endif
//        int seln_format;
//        unsigned long nbytes;
//        unsigned long overflow;
//        unsigned char *seln_data;
      
      req = &event->syswm.msg->event.xevent.xselectionrequest;

#if 0
      sevent.xselection.type = SelectionNotify;
      sevent.xselection.display = req->display;
      sevent.xselection.selection = req->selection;
      sevent.xselection.target = req->target/*None*/;
      sevent.xselection.property = None;
      sevent.xselection.requestor = req->requestor;
      sevent.xselection.time = req->time;
#endif

      ////yac_host->printf("[...] tksdl::clipboard_filter: xselectionrequest received. target=%i\n", req->target);

      XEvent& xev=event->syswm.msg->event.xevent;
	     if (xev.type == SelectionRequest) {
           if ((xev.xselectionrequest.owner     == SDL_Window) &&
              ((xev.xselectionrequest.selection == XA_PRIMARY) ||
              (xev.xselectionrequest.selection == XInternAtom(SDL_Display,"CLIPBOARD",false)))) {
              XEvent responseEvent;
              
              responseEvent.xselection.type      = SelectionNotify;
              responseEvent.xselection.display   = SDL_Display;
              responseEvent.xselection.requestor = xev.xselectionrequest.requestor;
              responseEvent.xselection.selection = xev.xselectionrequest.selection;
              responseEvent.xselection.target    = xev.xselectionrequest.target;
              responseEvent.xselection.property  = None; //nothing available, by default
              responseEvent.xselection.time      = xev.xselectionrequest.time;
              
              
              if (xev.xselectionrequest.target == XInternAtom(SDL_Display, "TARGETS", false)) {
                 responseEvent.xselection.property = xev.xselectionrequest.property;
                 
                 Atom supported[] = {
                    XInternAtom(SDL_Display,"TEXT",false),
                       XInternAtom(SDL_Display,"COMPOUND_TEXT",false),
                       XInternAtom(SDL_Display,"UTF8_STRING",false),
                       XInternAtom(SDL_Display,"TARGETS",false),
                       XInternAtom(SDL_Display,"STRING",false)
                 };
                 
                 XChangeProperty(SDL_Display, responseEvent.xselection.requestor,
                    xev.xselectionrequest.property, XA_ATOM, 32, PropModeReplace,
                    (unsigned char*)supported, 5);
              }
              
              //The encoding of XA_TEXT and XA_COMPOUND_TEXT is not specified
              //by the ICCCM... So we assume wesnoth native/utf-8 for simplicity.
              //modern apps are going to use UTF8_STRING anyway
              if (xev.xselectionrequest.target == XInternAtom(SDL_Display,"TEXT",false) ||
                 xev.xselectionrequest.target == XInternAtom(SDL_Display,"COMPOUND_TEXT",false) ||
                 xev.xselectionrequest.target == XInternAtom(SDL_Display,"UTF8_STRING",false) ||
                 xev.xselectionrequest.target == XInternAtom(SDL_Display,"STRING",false)) {
                 responseEvent.xselection.property = xev.xselectionrequest.property;
                 
                 XChangeProperty(SDL_Display, responseEvent.xselection.requestor,
                    xev.xselectionrequest.property,
                    xev.xselectionrequest.target, 8, PropModeReplace,
                    (const unsigned char*) tks_HAL->scrap_string.chars, tks_HAL->scrap_string.length);
              }
              else
              {
                 XEvent response; // can only do XA_STRING 
                 response.xselection.property=None;
                 response.xselection.type= SelectionNotify;
                 response.xselection.display= req->display;
                 response.xselection.requestor= req->requestor;
                 response.xselection.selection=req->selection;
                 response.xselection.target= req->target;
                 response.xselection.time = req->time;
                 XSendEvent (SDL_Display, req->requestor,0,0,&response);
                 XFlush (SDL_Display);
                 return 1;
              }
              
              XSendEvent(SDL_Display, xev.xselectionrequest.requestor, False, NoEventMask,
                 &responseEvent);
              
           }
        }
        return(1);
   }
   }
   return 1;
}
#endif /* X11_SCRAP */ 






#endif // TKSDL_SCRAP_CLIPBOARD

