blob: 83c897e8a17bffdc3def4d5857e4a3962fe6a2d0 [file] [log] [blame]
/* Copyright (C) 2000 Free Software Foundation
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
// Needed to avoid linking in libstdc++
#ifndef __STL_USE_EXCEPTIONS
# include <java/lang/OutOfMemoryError.h>
# define __THROW_BAD_ALLOC throw new java::lang::OutOfMemoryError()
#endif
#include <vector>
#include <X11/Xlib.h>
#include <gcj/cni.h>
#include <java/lang/RuntimeException.h>
#include <gnu/gcj/xlib/Display.h>
#include <gnu/gcj/xlib/Screen.h>
#include <gnu/gcj/xlib/Colormap.h>
#include <gnu/gcj/xlib/XColor.h>
#include <gnu/gcj/RawData.h>
jlong gnu::gcj::xlib::Colormap::allocateColorPixel(XColor* color)
{
::Display* dpy = (::Display*) (screen->getDisplay()->display);
::XColor* col = (::XColor*) (color->structure);
Status result = XAllocColor(dpy, xid, col);
if (result == 0)
throw new java::lang::RuntimeException(
JvNewStringLatin1("Unable to allocate color pixel."));
return col->pixel;
}
typedef JArray<gnu::gcj::xlib::XColor*>* xcolorarray;
xcolorarray gnu::gcj::xlib::Colormap::getSharedColors()
{
::Display* dpy = (::Display*) (screen->getDisplay()->display);
unsigned int nCells = CellsOfScreen(ScreenOfDisplay(dpy, screen->screenNumber));
typedef ::XColor xcolor;
std::vector<xcolor> colors(nCells);
for (unsigned int i=0; i<nCells; i++)
colors[i].pixel = i;
::XColor* cols = colors.get_allocator().address(colors.front());
XQueryColors(dpy, xid, cols,
nCells);
int nShared = 0;
for (unsigned int i=0; i<nCells; i++)
{
::XColor color = colors[i];
if (!XAllocColor(dpy, xid, &color))
continue;
/* FIXME: In some cases this algorithm may identify a free
color cell as a shared one. */
if (color.pixel != i)
{
// Oops, the color wasn't shared. Free it.
XFreeColors(dpy, xid, &(color.pixel), 1, 0);
colors[i].flags = FLAG_NOT_SHARED;
continue;
}
// FIXME: Shared or free?
nShared++;
colors[i].flags = FLAG_SHARED;
}
JArray<XColor*>* shared = newXColorArray(nShared);
int si=0;
for (unsigned int i=0; i<nCells; i++)
{
if (colors[i].flags != FLAG_SHARED)
continue;
XColor* col = elements(shared)[si++];
gnu::gcj::RawData* colorData = col->structure;
::XColor* colStruct = reinterpret_cast<xcolor*>(colorData);
*colStruct = colors[i];
}
return shared;
}
xcolorarray gnu::gcj::xlib::Colormap::getXColors()
{
::Display* dpy = (::Display*) (screen->getDisplay()->display);
unsigned int nCells =
CellsOfScreen(ScreenOfDisplay(dpy, screen->screenNumber));
typedef ::XColor xcolor;
std::vector<xcolor> colors(nCells);
JArray<XColor*>* colArray = newXColorArray(nCells);
for (unsigned int i=0; i<nCells; i++)
colors[i].pixel = i;
XQueryColors(dpy, xid, &(colors.front()), nCells);
/* TODO: The current problem with this code is that it relies on
(color.pixel == i) as an indicator that the color is
shared. However, (color.pixel == i), may also occur simply
because color cell i simply was the next free in the list of
unallocated color cells. IDEA: run through the list both
backwards and forwards, and only pick out the colorcells that
have been identified as shared during both passes. Reversing the
traversal direction might prevent i from corresponding to the
next free colorcell, atleast in one of the passes. */
for (unsigned int i=0; i<nCells; i++)
{
::XColor color = colors[i];
char flag = FLAG_NOT_SHARED;
if (XAllocColor(dpy, xid, &color))
{
if (color.pixel == i)
{
flag = FLAG_SHARED;
}
else
{
// Oops, the color wasn't shared. Free it.
XFreeColors(dpy, xid, &(color.pixel), 1, 0);
}
}
// Copy color data into object in array
XColor* col = elements(colArray)[i];
gnu::gcj::RawData* colorData = col->structure;
::XColor* colStruct = reinterpret_cast<xcolor*>(colorData);
*colStruct = colors[i];
colStruct->flags = flag;
}
return colArray;
}