#include <stdlib.h>
#include <string.h>

#include "ecore_xcb_private.h"
#include "Ecore_X_Atoms.h"

/*
 * Set CARD32 (array) property
 */
EAPI void
ecore_x_window_prop_card32_set(Ecore_X_Window win,
                               Ecore_X_Atom   atom,
                               unsigned int  *val,
                               unsigned int   num)
{
   xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, win,
                       atom, ECORE_X_ATOM_CARDINAL, 32, num, (const void *)val);
} /* ecore_x_window_prop_card32_set */

/**
 * Sends the GetProperty request.
 * @param window Window whose properties are requested.
 * @param atom   The atom.
 */
EAPI void
ecore_x_window_prop_card32_get_prefetch(Ecore_X_Window window,
                                        Ecore_X_Atom   atom)
{
   xcb_get_property_cookie_t cookie;

   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0,
                                       window,
                                       atom,
                                       ECORE_X_ATOM_CARDINAL,
                                       0, 0x7fffffff);
   _ecore_xcb_cookie_cache(cookie.sequence);
} /* ecore_x_window_prop_card32_get_prefetch */

/**
 * Gets the reply of the GetProperty request sent by ecore_x_window_prop_card32_get_prefetch().
 */
EAPI void
ecore_x_window_prop_card32_get_fetch(void)
{
   xcb_get_property_cookie_t cookie;
   xcb_get_property_reply_t *reply;

   cookie.sequence = _ecore_xcb_cookie_get();
   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
   _ecore_xcb_reply_cache(reply);
} /* ecore_x_window_prop_card32_get_fetch */

/*
 * Get CARD32 (array) property
 *
 * At most len items are returned in val.
 * If the property was successfully fetched the number of items stored in
 * val is returned, otherwise -1 is returned.
 * Note: Return value 0 means that the property exists but has no elements.
 */
EAPI int
ecore_x_window_prop_card32_get(Ecore_X_Window win __UNUSED__,
                               Ecore_X_Atom atom  __UNUSED__,
                               unsigned int      *val,
                               unsigned int       len)
{
   xcb_get_property_reply_t *reply;

   reply = _ecore_xcb_reply_get();
   if (!reply ||
       (reply->type != ECORE_X_ATOM_CARDINAL) ||
       (reply->format != 32))
      return -1;

   if (reply->value_len < len)
      len = xcb_get_property_value_length(reply);

   if (val)
      memcpy(val, xcb_get_property_value(reply), len);

   return (int)len;
} /* ecore_x_window_prop_card32_get */

/*
 * Get CARD32 (array) property of any length
 *
 * If the property was successfully fetched the number of items stored in
 * val is returned, otherwise -1 is returned.
 * Note: Return value 0 means that the property exists but has no elements.
 */
EAPI int
ecore_x_window_prop_card32_list_get(Ecore_X_Window win __UNUSED__,
                                    Ecore_X_Atom atom  __UNUSED__,
                                    unsigned int     **plist)
{
   xcb_get_property_reply_t *reply;
   int num = -1;

   if (plist)
      *plist = NULL;

   reply = _ecore_xcb_reply_get();
   if (!reply)
      return -1;

   if ((reply->type == XCB_NONE) ||
       (reply->value_len == 0))
      num = 0;
   else if ((reply->type == ECORE_X_ATOM_CARDINAL) &&
            (reply->format == 32))
     {
        uint32_t *val;

        num = xcb_get_property_value_length(reply);
        if (plist)
          {
             val = (uint32_t *)malloc (num);
             if (!val)
                goto error;

             memcpy(val, xcb_get_property_value(reply), num);
             *plist = val;
          }
     }

error:

   return num;
} /* ecore_x_window_prop_card32_list_get */

/*
 * Set X ID (array) property
 */
EAPI void
ecore_x_window_prop_xid_set(Ecore_X_Window win,
                            Ecore_X_Atom   atom,
                            Ecore_X_Atom   type,
                            Ecore_X_ID    *xids,
                            unsigned int   num)
{
   xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, win,
                       atom, type, 32, num, xids);
} /* ecore_x_window_prop_xid_set */

/**
 * Sends the GetProperty request.
 * @param window Window whose properties are requested.
 * @param atom   The atom.
 * @param type   The atom type.
 */
EAPI void
ecore_x_window_prop_xid_get_prefetch(Ecore_X_Window window,
                                     Ecore_X_Atom   atom,
                                     Ecore_X_Atom   type)
{
   xcb_get_property_cookie_t cookie;

   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0,
                                       window,
                                       atom,
                                       type,
                                       0, 0x7fffffff);
   _ecore_xcb_cookie_cache(cookie.sequence);
} /* ecore_x_window_prop_xid_get_prefetch */

/**
 * Gets the reply of the GetProperty request sent by ecore_x_window_prop_xid_get_prefetch().
 */
EAPI void
ecore_x_window_prop_xid_get_fetch(void)
{
   xcb_get_property_cookie_t cookie;
   xcb_get_property_reply_t *reply;

   cookie.sequence = _ecore_xcb_cookie_get();
   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
   _ecore_xcb_reply_cache(reply);
} /* ecore_x_window_prop_xid_get_fetch */

/*
 * Get X ID (array) property
 *
 * At most len items are returned in val.
 * If the property was successfully fetched the number of items stored in
 * val is returned, otherwise -1 is returned.
 * Note: Return value 0 means that the property exists but has no elements.
 */
EAPI int
ecore_x_window_prop_xid_get(Ecore_X_Window win __UNUSED__,
                            Ecore_X_Atom atom  __UNUSED__,
                            Ecore_X_Atom type  __UNUSED__,
                            Ecore_X_ID        *xids,
                            unsigned int       len)
{
   xcb_get_property_reply_t *reply;
   int num = len;

   reply = _ecore_xcb_reply_get();
   if (!reply)
      return -1;

   if (reply->type == XCB_NONE)
      num = 0;
   else if (reply->format == 32)
     {
        if (reply->value_len < len)
           num = xcb_get_property_value_length(reply);

        if (xids)
           memcpy(xids, xcb_get_property_value(reply), num);
     }

   return num;
} /* ecore_x_window_prop_xid_get */

/*
 * Get X ID (array) property
 *
 * If the property was successfully fetched the number of items stored in
 * val is returned, otherwise -1 is returned.
 * The returned array must be freed with free().
 * Note: Return value 0 means that the property exists but has no elements.
 */
EAPI int
ecore_x_window_prop_xid_list_get(Ecore_X_Window win __UNUSED__,
                                 Ecore_X_Atom atom  __UNUSED__,
                                 Ecore_X_Atom type  __UNUSED__,
                                 Ecore_X_ID       **pxids)
{
   xcb_get_property_reply_t *reply;
   int num = -1;

   if (pxids)
      *pxids = NULL;

   reply = _ecore_xcb_reply_get();
   if (!reply)
      return -1;

   if ((reply->type == XCB_NONE) ||
       (reply->value_len == 0))
      num = 0;
   else if ((reply->type == ECORE_X_ATOM_CARDINAL) &&
            (reply->format == 32))
     {
        uint32_t *val;

        num = xcb_get_property_value_length(reply);
        if (pxids)
          {
             val = (uint32_t *)malloc (num);
             if (!val)
                return -1;

             memcpy(val, xcb_get_property_value(reply), num);
             *pxids = val;
          }
     }

   return num;
} /* ecore_x_window_prop_xid_list_get */

/*
 * Remove/add/toggle X ID list item.
 */
EAPI void
ecore_x_window_prop_xid_list_change(Ecore_X_Window win,
                                    Ecore_X_Atom   atom,
                                    Ecore_X_Atom   type,
                                    Ecore_X_ID     item,
                                    int            op)
{
   Ecore_X_ID *lst;
   int i;
   int num;

   num = ecore_x_window_prop_xid_list_get(win, atom, type, &lst);
   if (num < 0)
      return;  /* Error - assuming invalid window */

   /* Is it there? */
   for (i = 0; i < num; i++)
     {
        if (lst[i] == item)
           break;
     }

   if (i < num)
     {
        /* Was in list */
        if (op == ECORE_X_PROP_LIST_ADD)
           goto done;

        /* Remove it */
        num--;
        for (; i < num; i++)
           lst[i] = lst[i + 1];
     }
   else
     {
        /* Was not in list */
        if (op == ECORE_X_PROP_LIST_REMOVE)
           goto done;

        /* Add it */
        num++;
        lst = realloc(lst, num * sizeof(Ecore_X_ID));
        lst[i] = item;
     }

   ecore_x_window_prop_xid_set(win, atom, type, lst, num);

done:
   if (lst)
      free(lst);
} /* ecore_x_window_prop_xid_list_change */

/*
 * Set Atom (array) property
 */
EAPI void
ecore_x_window_prop_atom_set(Ecore_X_Window win,
                             Ecore_X_Atom   atom,
                             Ecore_X_Atom  *list,
                             unsigned int   num)
{
   ecore_x_window_prop_xid_set(win, atom, ECORE_X_ATOM_ATOM, list, num);
} /* ecore_x_window_prop_atom_set */

/**
 * Sends the GetProperty request.
 * @param window Window whose properties are requested.
 * @param atom   Property atom.
 */
EAPI void
ecore_x_window_prop_atom_get_prefetch(Ecore_X_Window window,
                                      Ecore_X_Atom   atom)
{
   xcb_get_property_cookie_t cookie;

   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0,
                                       window,
                                       atom,
                                       ECORE_X_ATOM_ATOM,
                                       0, 0x7fffffff);
   _ecore_xcb_cookie_cache(cookie.sequence);
} /* ecore_x_window_prop_atom_get_prefetch */

/**
 * Gets the reply of the GetProperty request sent by ecore_x_window_prop_atom_get_prefetch().
 */
EAPI void
ecore_x_window_prop_atom_get_fetch(void)
{
   xcb_get_property_cookie_t cookie;
   xcb_get_property_reply_t *reply;

   cookie.sequence = _ecore_xcb_cookie_get();
   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
   _ecore_xcb_reply_cache(reply);
} /* ecore_x_window_prop_atom_get_fetch */

/*
 * Get Atom (array) property
 *
 * At most len items are returned in val.
 * If the property was successfully fetched the number of items stored in
 * val is returned, otherwise -1 is returned.
 * Note: Return value 0 means that the property exists but has no elements.
 */
EAPI int
ecore_x_window_prop_atom_get(Ecore_X_Window win,
                             Ecore_X_Atom   atom,
                             Ecore_X_Atom  *list,
                             unsigned int   len)
{
   return ecore_x_window_prop_xid_get(win, atom, ECORE_X_ATOM_ATOM, list, len);
} /* ecore_x_window_prop_atom_get */

/*
 * Get Atom (array) property
 *
 * If the property was successfully fetched the number of items stored in
 * val is returned, otherwise -1 is returned.
 * The returned array must be freed with free().
 * Note: Return value 0 means that the property exists but has no elements.
 */
EAPI int
ecore_x_window_prop_atom_list_get(Ecore_X_Window win,
                                  Ecore_X_Atom   atom,
                                  Ecore_X_Atom **plist)
{
   return ecore_x_window_prop_xid_list_get(win, atom, ECORE_X_ATOM_ATOM, plist);
} /* ecore_x_window_prop_atom_list_get */

/*
 * Remove/add/toggle atom list item.
 */
EAPI void
ecore_x_window_prop_atom_list_change(Ecore_X_Window win,
                                     Ecore_X_Atom   atom,
                                     Ecore_X_Atom   item,
                                     int            op)
{
   ecore_x_window_prop_xid_list_change(win, atom, ECORE_X_ATOM_ATOM, item, op);
} /* ecore_x_window_prop_atom_list_change */

/*
 * Set Window (array) property
 */
EAPI void
ecore_x_window_prop_window_set(Ecore_X_Window  win,
                               Ecore_X_Atom    atom,
                               Ecore_X_Window *list,
                               unsigned int    num)
{
   ecore_x_window_prop_xid_set(win, atom, ECORE_X_ATOM_WINDOW, list, num);
} /* ecore_x_window_prop_window_set */

/**
 * Sends the GetProperty request.
 * @param window Window whose properties are requested.
 * @param atom   The atom.
 */
EAPI void
ecore_x_window_prop_window_get_prefetch(Ecore_X_Window window,
                                        Ecore_X_Atom   atom)
{
   xcb_get_property_cookie_t cookie;

   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0,
                                       window,
                                       atom,
                                       ECORE_X_ATOM_WINDOW,
                                       0, 0x7fffffff);
   _ecore_xcb_cookie_cache(cookie.sequence);
} /* ecore_x_window_prop_window_get_prefetch */

/**
 * Gets the reply of the GetProperty request sent by ecore_x_window_prop_window_get_prefetch().
 */
EAPI void
ecore_x_window_prop_window_get_fetch(void)
{
   xcb_get_property_cookie_t cookie;
   xcb_get_property_reply_t *reply;

   cookie.sequence = _ecore_xcb_cookie_get();
   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
   _ecore_xcb_reply_cache(reply);
} /* ecore_x_window_prop_window_get_fetch */

/*
 * Get Window (array) property
 *
 * At most len items are returned in val.
 * If the property was successfully fetched the number of items stored in
 * val is returned, otherwise -1 is returned.
 * Note: Return value 0 means that the property exists but has no elements.
 */
EAPI int
ecore_x_window_prop_window_get(Ecore_X_Window  win,
                               Ecore_X_Atom    atom,
                               Ecore_X_Window *list,
                               unsigned int    len)
{
   return ecore_x_window_prop_xid_get(win, atom, ECORE_X_ATOM_WINDOW, list, len);
} /* ecore_x_window_prop_window_get */

/*
 * Get Window (array) property
 *
 * If the property was successfully fetched the number of items stored in
 * val is returned, otherwise -1 is returned.
 * The returned array must be freed with free().
 * Note: Return value 0 means that the property exists but has no elements.
 */
EAPI int
ecore_x_window_prop_window_list_get(Ecore_X_Window   win,
                                    Ecore_X_Atom     atom,
                                    Ecore_X_Window **plist)
{
   return ecore_x_window_prop_xid_list_get(win, atom, ECORE_X_ATOM_WINDOW, plist);
} /* ecore_x_window_prop_window_list_get */

/**
 * To be documented.
 *
 * FIXME: To be fixed.
 */
EAPI Ecore_X_Atom
ecore_x_window_prop_any_type(void)
{
   return XCB_GET_PROPERTY_TYPE_ANY;
} /* ecore_x_window_prop_any_type */

/**
 * To be documented.
 * @param window   The window.
 * @param property The property atom.
 * @param type     The type atom.
 * @param size     The size.
 * @param data     The data.
 * @param number   The size of the data.
 *
 * FIXME: To be fixed.
 */
EAPI void
ecore_x_window_prop_property_set(Ecore_X_Window window,
                                 Ecore_X_Atom   property,
                                 Ecore_X_Atom   type,
                                 int            size,
                                 void          *data,
                                 int            number)
{
   if (window == 0)
      window = ((xcb_screen_t *)_ecore_xcb_screen)->root;

   xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, window,
                       property, type,
                       size, number, data);
} /* ecore_x_window_prop_property_set */

/**
 * Sends the GetProperty request.
 * @param window   Window whose properties are requested.
 * @param property Property atom.
 * @param type     Type atom.
 */
EAPI void
ecore_x_window_prop_property_get_prefetch(Ecore_X_Window window,
                                          Ecore_X_Atom   property,
                                          Ecore_X_Atom   type)
{
   xcb_get_property_cookie_t cookie;

   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0,
                                       window ? window : ((xcb_screen_t *)_ecore_xcb_screen)->root,
                                       property, type, 0, LONG_MAX);
   _ecore_xcb_cookie_cache(cookie.sequence);
} /* ecore_x_window_prop_property_get_prefetch */

/**
 * Gets the reply of the GetProperty request sent by ecore_x_window_prop_property_get_prefetch().
 */
EAPI void
ecore_x_window_prop_property_get_fetch(void)
{
   xcb_get_property_cookie_t cookie;
   xcb_get_property_reply_t *reply;

   cookie.sequence = _ecore_xcb_cookie_get();
   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
   _ecore_xcb_reply_cache(reply);
} /* ecore_x_window_prop_property_get_fetch */

/**
 * To be documented.
 * @param window   The window (Unused).
 * @param property The property atom (Unused).
 * @param type     The type atom (Unused).
 * @param size     The size (Unused).
 * @param data     The returned data.
 * @param num      The size of the data.
 * @return         1 on success, 0 otherwise.
 *
 * FIXME: To be fixed.
 */
EAPI int
ecore_x_window_prop_property_get(Ecore_X_Window window __UNUSED__,
                                 Ecore_X_Atom property __UNUSED__,
                                 Ecore_X_Atom type     __UNUSED__,
                                 int size              __UNUSED__,
                                 unsigned char       **data,
                                 int                  *num)
{
   xcb_get_property_reply_t *reply;

   /* make sure these are initialized */
   if (num)
      *num = 0L;

   if (data)
      *data = NULL;
   else /* we can't store the retrieved data, so just return */
      return 0;

   reply = _ecore_xcb_reply_get();
   if (!reply)
      return 0;

   if ((reply->format != size) ||
       (reply->value_len == 0))
      return 0;

   *data = malloc(reply->value_len);
   if (!*data)
      return 0;

   memcpy(*data, xcb_get_property_value(reply),
          xcb_get_property_value_length(reply));

   if (num)
      *num = reply->value_len;

   return reply->format;
} /* ecore_x_window_prop_property_get */

EAPI void
ecore_x_window_prop_property_del(Ecore_X_Window window,
                                 Ecore_X_Atom   property)
{
   xcb_delete_property(_ecore_xcb_conn, window, property);
} /* ecore_x_window_prop_property_del */

/**
 * Sends the ListProperties request.
 * @param window Window whose properties are requested.
 */
EAPI void
ecore_x_window_prop_list_prefetch(Ecore_X_Window window)
{
   xcb_list_properties_cookie_t cookie;

   cookie = xcb_list_properties_unchecked(_ecore_xcb_conn, window);
   _ecore_xcb_cookie_cache(cookie.sequence);
} /* ecore_x_window_prop_list_prefetch */

/**
 * Gets the reply of the ListProperties request sent by ecore_x_window_prop_list_prefetch().
 */
EAPI void
ecore_x_window_prop_list_fetch(void)
{
   xcb_list_properties_cookie_t cookie;
   xcb_list_properties_reply_t *reply;

   cookie.sequence = _ecore_xcb_cookie_get();
   reply = xcb_list_properties_reply(_ecore_xcb_conn, cookie, NULL);
   _ecore_xcb_reply_cache(reply);
} /* ecore_x_window_prop_list_fetch */

/**
 * To be documented.
 * @param window  The window (Unused).
 * @param num_ret The number of atoms.
 * @return        The returned atoms.
 *
 * FIXME: To be fixed.
 */
EAPI Ecore_X_Atom *
ecore_x_window_prop_list(Ecore_X_Window window __UNUSED__,
                         int                  *num_ret)
{
   xcb_list_properties_reply_t *reply;
   Ecore_X_Atom *atoms;

   if (num_ret)
      *num_ret = 0;

   reply = _ecore_xcb_reply_get();
   if (!reply)
      return NULL;

   atoms = (Ecore_X_Atom *)malloc(reply->atoms_len * sizeof(Ecore_X_Atom));
   if (!atoms)
      return NULL;

   memcpy(atoms,
          xcb_list_properties_atoms(reply),
          reply->atoms_len * sizeof(Ecore_X_Atom));
   if(num_ret)
      *num_ret = reply->atoms_len;

   return atoms;
} /* ecore_x_window_prop_list */

/**
 * Set a window string property.
 * @param win The window
 * @param type The property
 * @param str The string
 *
 * Set a window string property
 */
EAPI void
ecore_x_window_prop_string_set(Ecore_X_Window win,
                               Ecore_X_Atom   type,
                               const char    *str)
{
   if (win == 0)
      win = ((xcb_screen_t *)_ecore_xcb_screen)->root;

   xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, win,
                       type, ECORE_X_ATOM_UTF8_STRING,
                       8, strlen(str), str);
} /* ecore_x_window_prop_string_set */

/**
 * Sends the GetProperty request.
 * @param window Window whose properties are requested.
 * @param type   The atom.
 */
EAPI void
ecore_x_window_prop_string_get_prefetch(Ecore_X_Window window,
                                        Ecore_X_Atom   type)
{
   xcb_get_property_cookie_t cookie;

   cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0,
                                       window ? window : ((xcb_screen_t *)_ecore_xcb_screen)->root,
                                       type, XCB_GET_PROPERTY_TYPE_ANY, 0L, 1000000L);
   _ecore_xcb_cookie_cache(cookie.sequence);
} /* ecore_x_window_prop_string_get_prefetch */

/**
 * Gets the reply of the GetProperty request sent by ecore_x_window_prop_string_get_prefetch().
 */
EAPI void
ecore_x_window_prop_string_get_fetch(void)
{
   xcb_get_property_cookie_t cookie;
   xcb_get_property_reply_t *reply;

   cookie.sequence = _ecore_xcb_cookie_get();
   reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL);
   _ecore_xcb_reply_cache(reply);
} /* ecore_x_window_prop_string_get_fetch */

/**
 * Get a window string property.
 * @param window The window
 * @param type The property
 *
 * Return window string property of a window. String must be free'd when done.
 *
 * To use this function, you must call before, and in order,
 * ecore_x_window_prop_string_get_prefetch(), which sends the GetProperty request,
 * then ecore_x_window_prop_string_get_fetch(), which gets the reply.
 */
EAPI char *
ecore_x_window_prop_string_get(Ecore_X_Window window __UNUSED__,
                               Ecore_X_Atom type     __UNUSED__)
{
   xcb_get_property_reply_t *reply;
   char *str = NULL;

   reply = _ecore_xcb_reply_get();
   if (!reply)
      return NULL;

   if (reply->type == ECORE_X_ATOM_UTF8_STRING)
     {
        int length;

        length = reply->value_len;
        str = (char *)malloc(length + 1);
        memcpy(str,
               xcb_get_property_value(reply),
               length);
        str[length] = '\0';
     }
   else
     {
        /* FIXME: to be done... */

/* #ifdef X_HAVE_UTF8_STRING */
/*         s = Xutf8TextPropertyToTextList(_ecore_xcb_conn, &xtp, */
/*                                         &list, &items); */
/* #else */
/*         s = XmbTextPropertyToTextList(_ecore_xcb_conn, &xtp, */
/*                                       &list, &items); */
/* #endif */
/*         if ((s == XLocaleNotSupported) || */
/*             (s == XNoMemory) || (s == XConverterNotFound)) */
/*           { */
/*              str = strdup((char *)xtp.value); */
/*           } */
/*         else if ((s >= Success) && (items > 0)) */
/*           { */
/*              str = strdup(list[0]); */
/*           } */
/*         if (list) */
/*            XFreeStringList(list); */
     }

   return str;
} /* ecore_x_window_prop_string_get */

/* FIXME : round trips because of GetWMProtocols */
/*         should we rewrite its code ? */
EAPI Eina_Bool
ecore_x_window_prop_protocol_isset(Ecore_X_Window      window,
                                   Ecore_X_WM_Protocol protocol)
{
   xcb_get_property_cookie_t cookie;
   xcb_get_wm_protocols_reply_t protocols;
   Ecore_X_Atom proto;
   uint32_t i;
   uint8_t ret = 0;

   /* check for invalid values */
   if (protocol >= ECORE_X_WM_PROTOCOL_NUM)
      return ret;

   proto = _ecore_xcb_atoms_wm_protocols[protocol];

   cookie = xcb_get_wm_protocols(_ecore_xcb_conn, window, ECORE_X_ATOM_WM_PROTOCOLS);

   if (!xcb_get_wm_protocols_reply(_ecore_xcb_conn, cookie, &protocols, NULL))
      return ret;

   for (i = 0; i < protocols.atoms_len; i++)
      if (protocols.atoms[i] == proto)
        {
           ret = 1;
           break;
        }

   xcb_get_wm_protocols_reply_wipe(&protocols);

   return ret;
} /* ecore_x_window_prop_protocol_isset */

/**
 * To be documented.
 * @param window  The window.
 * @param num_ret The number of WM protocols.
 * @return        The returned WM protocols.
 *
 * FIXME: To be fixed.
 */

/* FIXME : round trips because of get_wm_protocols */
/*         should we rewrite its code ? */

EAPI Ecore_X_WM_Protocol *
ecore_x_window_prop_protocol_list_get(Ecore_X_Window window,
                                      int           *num_ret)
{
   xcb_get_property_cookie_t cookie;
   xcb_get_wm_protocols_reply_t protocols;
   Ecore_X_WM_Protocol *prot_ret = NULL;
   uint32_t protos_count;
   uint32_t i;

   cookie = xcb_get_wm_protocols(_ecore_xcb_conn, window, ECORE_X_ATOM_WM_PROTOCOLS);

   if (!xcb_get_wm_protocols_reply(_ecore_xcb_conn, cookie, &protocols, NULL))
      return NULL;

   if ((protocols.atoms_len <= 0))
      return NULL;

   prot_ret = calloc(1, protocols.atoms_len * sizeof(Ecore_X_WM_Protocol));
   if (!prot_ret)
     {
        xcb_get_wm_protocols_reply_wipe(&protocols);
        return NULL;
     }

   for (i = 0; i < protocols.atoms_len; i++)
     {
        Ecore_X_WM_Protocol j;

        prot_ret[i] = -1;
        for (j = 0; j < ECORE_X_WM_PROTOCOL_NUM; j++)
          {
             if (_ecore_xcb_atoms_wm_protocols[j] == protocols.atoms[i])
                prot_ret[i] = j;
          }
     }
   xcb_get_wm_protocols_reply_wipe(&protocols);
   *num_ret = protos_count;

   return prot_ret;
} /* ecore_x_window_prop_protocol_list_get */

