

#include "Clipboard.h"

#include <stdio.h>

FILE* logfile = 0;

FILE* Log(void);
void CloseLog(void);

#ifdef ALLEGRO_WINDOWS
#include <winalleg.h>

/** Vanneto's implementation
#include <windows.h>
#include <string>
#include <stdio.h>

void clipboard_paste (const std::string &text)
{
    if (OpenClipboard(NULL)) {
        HGLOBAL clipBuffer;
        char *buffer;

        EmptyClipboard();
        clipBuffer = GlobalAlloc (GMEM_DDESHARE, text.size() + 1);
        buffer = (char*)GlobalLock(clipBuffer);

        strcpy(buffer, text.c_str());
        GlobalUnlock (clipBuffer);
        SetClipboardData(CF_TEXT, clipBuffer);
        CloseClipboard();
    }
}

std::string clipboard_copy ()
{
    std::string fromClipboard;
    if (OpenClipboard(NULL)) {
        HANDLE hData = GetClipboardData(CF_TEXT);
        char *buffer = (char*)GlobalLock(hData);
        fromClipboard = buffer;
        GlobalUnlock (hData);
        CloseClipboard ();
    }

    return fromClipboard;
}

int main (int argc, char *argv[])
{
    clipboard_paste ("foobar");
    printf("%s\n", clipboard_copy().c_str());
    return 0;
}

*/

int SetClipboardString(const char* cstr) {
   HGLOBAL clipBuffer = 0;
   char* buffer = 0;
   HWND allegro_window = win_get_window();
   
   if (!cstr) {return 1;}
   if (OpenClipboard(allegro_window) == 0) {return 1;}
   
   EmptyClipboard();
   
   clipBuffer = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT , strlen(cstr) + 1);
   buffer = (char*)GlobalLock(clipBuffer);
   strcpy(buffer , cstr);
   GlobalUnlock(clipBuffer);
   
   if (SetClipboardData(CF_TEXT , clipBuffer) == (void*)0) {return 1;}
   CloseClipboard();
   return 0;
}



int SetClipboardBitmap(BITMAP* bmp) {
   HWND allegro_window = win_get_window();
   HBITMAP hbitmap = 0;
   
   if (!bmp) {return 1;}
   hbitmap = convert_bitmap_to_hbitmap(bmp);
   if (!bmp) {return 1;}
   
   if (OpenClipboard(allegro_window) == 0) {return 1;}
   
   if (SetClipboardData(CF_BITMAP , hbitmap) == (void*)0) {return 1;}
   CloseClipboard();
   return 0;
}



char* GetNewClipboardString() {
   char* clipstr = 0;
   char* newstr = 0;
   HWND allegro_window = win_get_window();
   HANDLE cliphandle = 0;
   
   if (IsClipboardFormatAvailable(CF_TEXT) == 0) {return (char*)0;}

   if (OpenClipboard(allegro_window) == 0) {return (char*)0;}
   cliphandle = GetClipboardData(CF_TEXT);
   if (cliphandle == (void*)0) {
      CloseClipboard();
      return (char*)0;
   }
   clipstr = (char*)GlobalLock(cliphandle);
//   clipstr = (char*)cliphandle;
   newstr = strdup(clipstr);
   GlobalUnlock(cliphandle);
   CloseClipboard();
   return newstr;
}



BITMAP* GetNewClipboardBitmap() {
   HBITMAP clipbmp = 0;
   BITMAP* bmp = 0;
   HWND allegro_window = win_get_window();
   HANDLE cliphandle = 0;
   
   if (IsClipboardFormatAvailable(CF_BITMAP) == 0) {return (BITMAP*)0;}
   
   if (OpenClipboard(allegro_window) == 0) {return (BITMAP*)0;}
   cliphandle = GetClipboardData(CF_BITMAP);
   if (cliphandle == (void*)0) {
      CloseClipboard();
      return (BITMAP*)0;
   }
   clipbmp = (HBITMAP)cliphandle;
   bmp = convert_hbitmap_to_bitmap(clipbmp);
   CloseClipboard();
   return bmp;
}



#endif // #ifdef ALLEGRO_WINDOWS



#ifdef ALLEGRO_UNIX

#include <stdio.h>
#include <stdlib.h>


/** Get/Set..ClipboardString using xclip

int SetClipboardString(const char* cstr) {
   const char* tempfilename = "temp_clipboard.txt";
   const char* command = "cat %s | xclip -selection c"
   char* command_buffer = 0;
   FILE* tempfile = 0;
   
   if (!cstr) {return 1;}
   tempfile = fopen(tempfilename , "w");
   if (!tempfile) {return 1;}
   fwrite(cstr , sizeof(char) , strlen(cstr) , tempfile);
   fflush(tempfile);
   if (fclose(tempfile) != 0) {return 1;}
   
   command_buffer = (char*)malloc(strlen(tempfilename) + strlen(command) - 2 + 1);
   if (!command_buffer) {return 1;}
   sprintf(command_buffer , command , tempfilename);
   system(command_buffer)
   free(command_buffer);
   return 0;
}



int SetClipboardBitmap(BITMAP* bmp) {
   return 1;
}



char* GetNewClipboardString() {
   FILE* tempfile = 0;
   char* newstr = 0;
   int size = 0;
   int i = 0;
   
   system("xclip -o -selection c > temp_clipboard.txt");
   tempfile = fopen(tempfile , "r");
   if (!tempfile) {return (char*)0;}
   while(fgetc(tempfile) != EOF) {++size;}
   if (fseek(tempfile , 0 , SEEK_SET) != 0) {return (char*)0;}
   newstr = (char*)malloc(size + 1);
   if (!newstr) {return (char*)0;
   while (i < size) {
      newstr[i] = fgetc(tempfile);
      ++i;
   }
   newstr[size] = '\0';
   fclose(tempfile);
   return newstr;
}



BITMAP* GetNewClipboardBitmap() {
   return (BITMAP*)0;
}
//*/

#include <xalleg.h>
#include <X11/Xatom.h>
#include <X11/Xmu/Atoms.h>

int SetClipboardString(const char* cstr) {
   Display* d = _xwin.display;
   Window w = _xwin.window;
   char* str = 0;
   Atom ClipboardAtom = XInternAtom(d , "CLIPBOARD" , True);
   Atom StringAtom = XInternAtom(d , "STRING" , True);
   
   if ((ClipboardAtom == None) || (StringAtom == None)) {
      if (ClipboardAtom == None) {
         fprintf(Log() , "The CLIPBOARD atom is not defined.\n");
      }
      if (StringAtom == None) {
         fprintf(Log() , "The STRING atom is not defined.\n");
      }
      return 1;
   }
   
   if (!cstr) {return 1;}
   str = strdup(cstr);
///   XChangeProperty(d , w , XA_CLIPBOARD , XA_STRING , 8 , PropModeReplace , (unsigned char*)str , strlen(str) + 1);
   XChangeProperty(d , w , ClipboardAtom , StringAtom , 8 , PropModeReplace , (unsigned char*)str , strlen(str) + 1);
   XFlush(d);
   free(str);
///   XSetSelectionOwner(d , XA_CLIPBOARD , w , CurrentTime);
   XSetSelectionOwner(d , XA_CLIPBOARD(d) , w , CurrentTime);
   return 0;
}// returns 0 if successful, non-zero otherwise



int SetClipboardBitmap(BITMAP* bmp) {
   return 1;// not implemented yet
}// returns 0 if successful, non-zero otherwise



char* GetNewClipboardString() {
   Display* d = _xwin.display;
//   Window w = _xwin.window;
   Atom returned_type;
   int returned_format;
   unsigned long num_items_returned;
   unsigned long bytes_left;
   unsigned char* returned_property;
   char* return_string = 0;
   int ret = 0;
   char* AtomName = 0;
   Atom ClipboardAtom = XInternAtom(d , "CLIPBOARD" , True);
   Atom StringAtom = XInternAtom(d , "STRING" , True);
   
   Window selowner = XGetSelectionOwner(d , XA_CLIPBOARD(d));
   if (selowner == None) {return (char*)0;}
   if ((ClipboardAtom == None) || (StringAtom == None)) {
      if (ClipboardAtom == None) {
         fprintf(Log() , "The CLIPBOARD atom is not defined.\n");
      }
      if (StringAtom == None) {
         fprintf(Log() , "The STRING atom is not defined.\n");
      }
      return (char*)0;
   }
   
///   XConvertSelection(d , XA_CLIPBOARD , XA_STRING , None , selowner , CurrentTime);
   XConvertSelection(d , ClipboardAtom , StringAtom , None , selowner , CurrentTime);
   XFlush(d);
   
   // check for data
///   ret = XGetWindowProperty(d , selowner , XA_STRING , 0 , 0 , 0 , AnyPropertyType , &returned_type ,
///                            &returned_format , &num_items_returned , &bytes_left , &returned_property);
   ret = XGetWindowProperty(d , selowner , StringAtom , 0 , 0 , 0 , AnyPropertyType , &returned_type ,
                            &returned_format , &num_items_returned , &bytes_left , &returned_property);
   if (ret != Success) {
      fprintf(Log() , "Failed to Get Window Property XA_STRING attempt 1\n");
      return (char*)0;
   }
   if (bytes_left < 1) {
      fprintf(Log() , "There are no bytes to read in the requested property.\n");
      return (char*)0;
   }
///   ret = XGetWindowProperty(d , selowner , XA_STRING , 0 , bytes_left*4 , 0 , AnyPropertyType , &returned_type ,
///                                     &returned_format , &num_items_returned , &bytes_left , &returned_property);
   ret = XGetWindowProperty(d , selowner , StringAtom , 0 , bytes_left*4 , 0 , AnyPropertyType , &returned_type ,
                                     &returned_format , &num_items_returned , &bytes_left , &returned_property);
   if (ret != Success) {
      fprintf(Log() , "Failed to Get Window Property XA_STRING attempt 2\n");
      return (char*)0;
   }
   // Success, temporary logging of returned data
//*
   AtomName = XGetAtomName(d , returned_type);
   if (!AtomName) {AtomName = "Unidentified Atom";}
   fprintf(Log() , "Success retrieving property. Return type \"%s\" , Format=%d , NumItemsReturned=%lu\n"
                   "   Bytes Left=%lu , String Returned=\"%s\"" ,
                   AtomName , returned_format , num_items_returned , bytes_left , returned_property);
   if (strcmp(AtomName , "Unidentified Atom") != 0) {XFree(AtomName);}
//*/
   if (returned_format == 8) {
      return_string = strdup((const char*)returned_property);
   } else {
      fprintf(Log() , "The string returned was not in char format. Data size was %d." , returned_format);
   }
   XFree(returned_property);
   
   return return_string;
}// returns a new string if successful, else returns 0



BITMAP* GetNewClipboardBitmap() {
   return 0;// not implemented yet
}// returns a new bitmap if successful, else returns 0


#endif // #ifdef ALLEGRO_UNIX

#ifdef ALLEGRO_MACOSX
//   #include <MACOSX_HEADER> // TODO : Find out what mac header to include



int SetClipboardString(const char* cstr) {
   return 1;
}



int SetClipboardBitmap(BITMAP* bmp) {
   return 1;
}



char* GetNewClipboardString() {
   return (const char*)0;
}



BITMAP* GetNewClipboardBitmap() {
   return (BITMAP*)0;
}



#endif // #ifdef ALLEGRO_MACOSX

FILE* Log(void) {
   if (logfile) {return logfile;}
   logfile = fopen("ClipboardLog.txt" , "w");
   if (logfile) {
      atexit(CloseLog);
   }
   return logfile;
}

void CloseLog(void) {
   if (logfile) {
      fclose(logfile);
      logfile = 0;
   }
}


