#include "TROOT.h"
#include "TColor.h"
#include "TGX11.h"
#include "TPoint.h"
#include "TMath.h"
#include "TStorage.h"
#include "TStyle.h"
#include "TExMap.h"
#include "TEnv.h"
#include "TString.h"
#include "TObjString.h"
#include "TObjArray.h"
#include "RStipples.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#ifdef R__AIX
# include <sys/socket.h>
#endif
extern float XRotVersion(char*, int);
extern void XRotSetMagnification(float);
extern void XRotSetBoundingBoxPad(int);
extern int XRotDrawString(Display*, XFontStruct*, float,
Drawable, GC, int, int, char*);
extern int XRotDrawImageString(Display*, XFontStruct*, float,
Drawable, GC, int, int, char*);
extern int XRotDrawAlignedString(Display*, XFontStruct*, float,
Drawable, GC, int, int, char*, int);
extern int XRotDrawAlignedImageString(Display*, XFontStruct*, float,
Drawable, GC, int, int, char*, int);
extern XPoint *XRotTextExtents(Display*, XFontStruct*, float,
int, int, char*, int);
static XWindow_t *gCws;
static XWindow_t *gTws;
const Int_t kBIGGEST_RGB_VALUE = 65535;
const int kMAXGC = 7;
static GC gGClist[kMAXGC];
static GC *gGCline = &gGClist[0];
static GC *gGCmark = &gGClist[1];
static GC *gGCfill = &gGClist[2];
static GC *gGCtext = &gGClist[3];
static GC *gGCinvt = &gGClist[4];
static GC *gGCdash = &gGClist[5];
static GC *gGCpxmp = &gGClist[6];
static GC gGCecho;
static Int_t gFillHollow;
static Pixmap gFillPattern = 0;
const Int_t kMAXFONT = 4;
static struct {
XFontStruct *id;
char name[80];
} gFont[kMAXFONT];
static XFontStruct *gTextFont;
static Int_t gCurrentFontNumber = 0;
const Int_t kMAXMK = 100;
static struct {
int type;
int n;
XPoint xy[kMAXMK];
} gMarker;
static int gLineWidth = 0;
static int gLineStyle = LineSolid;
static int gCapStyle = CapButt;
static int gJoinStyle = JoinMiter;
static char gDashList[10];
static int gDashLength = 0;
static int gDashOffset = 0;
static int gDashSize = 0;
static ULong_t gMouseMask = ButtonPressMask | ButtonReleaseMask |
EnterWindowMask | LeaveWindowMask |
PointerMotionMask | KeyPressMask |
KeyReleaseMask;
static ULong_t gKeybdMask = ButtonPressMask | KeyPressMask |
EnterWindowMask | LeaveWindowMask;
const char null_cursor_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static Cursor gNullCursor = 0;
ClassImp(TGX11)
TGX11::TGX11()
{
int i;
fDisplay = 0;
fScreenNumber = 0;
fVisual = 0;
fRootWin = 0;
fVisRootWin = 0;
fColormap = 0;
fBlackPixel = 0;
fWhitePixel = 0;
fWindows = 0;
fColors = 0;
fXEvent = new XEvent;
fRedDiv = -1;
fGreenDiv = -1;
fBlueDiv = -1;
fRedShift = -1;
fGreenShift = -1;
fBlueShift = -1;
fCharacterUpX = 1;
fCharacterUpY = 1;
fDepth = 0;
fHasTTFonts = kFALSE;
fHasXft = kFALSE;
fMaxNumberOfWindows = 10;
fTextAlignH = 1;
fTextAlignV = 1;
fTextAlign = 7;
fTextMagnitude = 1;
for (i = 0; i < kNumCursors; i++) fCursors[i] = 0;
}
TGX11::TGX11(const char *name, const char *title) : TVirtualX(name, title)
{
int i;
fDisplay = 0;
fScreenNumber = 0;
fVisual = 0;
fRootWin = 0;
fVisRootWin = 0;
fColormap = 0;
fBlackPixel = 0;
fWhitePixel = 0;
fDrawMode = kCopy;
fXEvent = new XEvent;
fRedDiv = -1;
fGreenDiv = -1;
fBlueDiv = -1;
fRedShift = -1;
fGreenShift = -1;
fBlueShift = -1;
fCharacterUpX = 1;
fCharacterUpY = 1;
fDepth = 0;
fHasTTFonts = kFALSE;
fHasXft = kFALSE;
fMaxNumberOfWindows = 10;
fTextAlignH = 1;
fTextAlignV = 1;
fTextAlign = 7;
fTextMagnitude = 1;
for (i = 0; i < kNumCursors; i++) fCursors[i] = 0;
fWindows = (XWindow_t*) TStorage::Alloc(fMaxNumberOfWindows*sizeof(XWindow_t));
for (i = 0; i < fMaxNumberOfWindows; i++)
fWindows[i].fOpen = 0;
fColors = new TExMap;
}
TGX11::TGX11(const TGX11 &org) : TVirtualX(org)
{
int i;
fDisplay = org.fDisplay;
fScreenNumber = org.fScreenNumber;
fVisual = org.fVisual;
fRootWin = org.fRootWin;
fVisRootWin = org.fVisRootWin;
fColormap = org.fColormap;
fBlackPixel = org.fBlackPixel;
fWhitePixel = org.fWhitePixel;
fHasTTFonts = org.fHasTTFonts;
fHasXft = org.fHasXft;
fTextAlignH = org.fTextAlignH;
fTextAlignV = org.fTextAlignV;
fTextAlign = org.fTextAlign;
fTextMagnitude = org.fTextMagnitude;
fCharacterUpX = org.fCharacterUpX;
fCharacterUpY = org.fCharacterUpY;
fDepth = org.fDepth;
fRedDiv = org.fRedDiv;
fGreenDiv = org.fGreenDiv;
fBlueDiv = org.fBlueDiv;
fRedShift = org.fRedShift;
fGreenShift = org.fGreenShift;
fBlueShift = org.fBlueShift;
fDrawMode = org.fDrawMode;
fXEvent = new XEvent;
fMaxNumberOfWindows = org.fMaxNumberOfWindows;
fWindows = (XWindow_t*) TStorage::Alloc(fMaxNumberOfWindows*sizeof(XWindow_t));
for (i = 0; i < fMaxNumberOfWindows; i++) {
fWindows[i].fOpen = org.fWindows[i].fOpen;
fWindows[i].fDoubleBuffer = org.fWindows[i].fDoubleBuffer;
fWindows[i].fIsPixmap = org.fWindows[i].fIsPixmap;
fWindows[i].fDrawing = org.fWindows[i].fDrawing;
fWindows[i].fWindow = org.fWindows[i].fWindow;
fWindows[i].fBuffer = org.fWindows[i].fBuffer;
fWindows[i].fWidth = org.fWindows[i].fWidth;
fWindows[i].fHeight = org.fWindows[i].fHeight;
fWindows[i].fClip = org.fWindows[i].fClip;
fWindows[i].fXclip = org.fWindows[i].fXclip;
fWindows[i].fYclip = org.fWindows[i].fYclip;
fWindows[i].fWclip = org.fWindows[i].fWclip;
fWindows[i].fHclip = org.fWindows[i].fHclip;
fWindows[i].fNewColors = org.fWindows[i].fNewColors;
fWindows[i].fNcolors = org.fWindows[i].fNcolors;
fWindows[i].fShared = org.fWindows[i].fShared;
}
for (i = 0; i < kNumCursors; i++)
fCursors[i] = org.fCursors[i];
fColors = new TExMap;
Long64_t key, value;
TExMapIter it(org.fColors);
while (it.Next(key, value)) {
XColor_t *colo = (XColor_t *) (Long_t)value;
XColor_t *col = new XColor_t;
col->fPixel = colo->fPixel;
col->fRed = colo->fRed;
col->fGreen = colo->fGreen;
col->fBlue = colo->fBlue;
col->fDefined = colo->fDefined;
fColors->Add(key, (Long_t) col);
}
}
TGX11::~TGX11()
{
delete fXEvent;
if (fWindows) TStorage::Dealloc(fWindows);
if (!fColors) return;
Long64_t key, value;
TExMapIter it(fColors);
while (it.Next(key, value)) {
XColor_t *col = (XColor_t *) (Long_t)value;
delete col;
}
delete fColors;
}
Bool_t TGX11::Init(void *display)
{
if (OpenDisplay((Display *) display) == -1) return kFALSE;
return kTRUE;
}
Bool_t TGX11::AllocColor(Colormap cmap, XColor *color)
{
if (fRedDiv == -1) {
if (XAllocColor(fDisplay, cmap, color))
return kTRUE;
} else {
color->pixel = (color->red >> fRedDiv) << fRedShift |
(color->green >> fGreenDiv) << fGreenShift |
(color->blue >> fBlueDiv) << fBlueShift;
return kTRUE;
}
return kFALSE;
}
void TGX11::QueryColors(Colormap cmap, XColor *color, Int_t ncolors)
{
if (fRedDiv == -1) {
XQueryColors(fDisplay, cmap, color, ncolors);
} else {
ULong_t r, g, b;
for (Int_t i = 0; i < ncolors; i++) {
r = (color[i].pixel & fVisual->red_mask) >> fRedShift;
color[i].red = UShort_t(r*kBIGGEST_RGB_VALUE/(fVisual->red_mask >> fRedShift));
g = (color[i].pixel & fVisual->green_mask) >> fGreenShift;
color[i].green = UShort_t(g*kBIGGEST_RGB_VALUE/(fVisual->green_mask >> fGreenShift));
b = (color[i].pixel & fVisual->blue_mask) >> fBlueShift;
color[i].blue = UShort_t(b*kBIGGEST_RGB_VALUE/(fVisual->blue_mask >> fBlueShift));
color[i].flags = DoRed | DoGreen | DoBlue;
}
}
}
void TGX11::ClearPixmap(Drawable *pix)
{
Window root;
int xx, yy;
unsigned int ww, hh, border, depth;
XGetGeometry(fDisplay, *pix, &root, &xx, &yy, &ww, &hh, &border, &depth);
SetColor(*gGCpxmp, 0);
XFillRectangle(fDisplay, *pix, *gGCpxmp, 0 ,0 ,ww ,hh);
SetColor(*gGCpxmp, 1);
XFlush(fDisplay);
}
void TGX11::ClearWindow()
{
if (!gCws->fIsPixmap && !gCws->fDoubleBuffer) {
XSetWindowBackground(fDisplay, gCws->fDrawing, GetColor(0).fPixel);
XClearWindow(fDisplay, gCws->fDrawing);
XFlush(fDisplay);
} else {
SetColor(*gGCpxmp, 0);
XFillRectangle(fDisplay, gCws->fDrawing, *gGCpxmp,
0, 0, gCws->fWidth, gCws->fHeight);
SetColor(*gGCpxmp, 1);
}
}
void TGX11::ClosePixmap()
{
CloseWindow1();
}
void TGX11::CloseWindow()
{
if (gCws->fShared)
gCws->fOpen = 0;
else
CloseWindow1();
}
void TGX11::CloseWindow1()
{
int wid;
if (gCws->fIsPixmap)
XFreePixmap(fDisplay, gCws->fWindow);
else
XDestroyWindow(fDisplay, gCws->fWindow);
if (gCws->fBuffer) XFreePixmap(fDisplay, gCws->fBuffer);
if (gCws->fNewColors) {
if (fRedDiv == -1)
XFreeColors(fDisplay, fColormap, gCws->fNewColors, gCws->fNcolors, 0);
delete [] gCws->fNewColors;
gCws->fNewColors = 0;
}
XFlush(fDisplay);
gCws->fOpen = 0;
for (wid = 0; wid < fMaxNumberOfWindows; wid++)
if (fWindows[wid].fOpen) {
gCws = &fWindows[wid];
return;
}
gCws = 0;
}
void TGX11::CopyPixmap(int wid, int xpos, int ypos)
{
gTws = &fWindows[wid];
XCopyArea(fDisplay, gTws->fDrawing, gCws->fDrawing, *gGCpxmp, 0, 0, gTws->fWidth,
gTws->fHeight, xpos, ypos);
XFlush(fDisplay);
}
void TGX11::CopyWindowtoPixmap(Drawable *pix, int xpos, int ypos )
{
Window root;
int xx, yy;
unsigned int ww, hh, border, depth;
XGetGeometry(fDisplay, *pix, &root, &xx, &yy, &ww, &hh, &border, &depth);
XCopyArea(fDisplay, gCws->fDrawing, *pix, *gGCpxmp, xpos, ypos, ww, hh, 0, 0);
XFlush(fDisplay);
}
void TGX11::DrawBox(int x1, int y1, int x2, int y2, EBoxMode mode)
{
Int_t x = TMath::Min(x1, x2);
Int_t y = TMath::Min(y1, y2);
Int_t w = TMath::Abs(x2 - x1);
Int_t h = TMath::Abs(y2 - y1);
switch (mode) {
case kHollow:
XDrawRectangle(fDisplay, gCws->fDrawing, *gGCline, x, y, w, h);
break;
case kFilled:
XFillRectangle(fDisplay, gCws->fDrawing, *gGCfill, x, y, w, h);
break;
default:
break;
}
}
void TGX11::DrawCellArray(int x1, int y1, int x2, int y2, int nx, int ny, int *ic)
{
int i, j, icol, ix, iy, w, h, current_icol;
current_icol = -1;
w = TMath::Max((x2-x1)/(nx),1);
h = TMath::Max((y1-y2)/(ny),1);
ix = x1;
for (i = 0; i < nx; i++) {
iy = y1-h;
for (j = 0; j < ny; j++) {
icol = ic[i+(nx*j)];
if (icol != current_icol) {
XSetForeground(fDisplay, *gGCfill, GetColor(icol).fPixel);
current_icol = icol;
}
XFillRectangle(fDisplay, gCws->fDrawing, *gGCfill, ix, iy, w, h);
iy = iy-h;
}
ix = ix+w;
}
}
void TGX11::DrawFillArea(int n, TPoint *xyt)
{
XPoint *xy = (XPoint*)xyt;
if (gFillHollow)
XDrawLines(fDisplay, gCws->fDrawing, *gGCfill, xy, n, CoordModeOrigin);
else {
XFillPolygon(fDisplay, gCws->fDrawing, *gGCfill,
xy, n, Nonconvex, CoordModeOrigin);
}
}
void TGX11::DrawLine(int x1, int y1, int x2, int y2)
{
if (gLineStyle == LineSolid)
XDrawLine(fDisplay, gCws->fDrawing, *gGCline, x1, y1, x2, y2);
else {
XSetDashes(fDisplay, *gGCdash, gDashOffset, gDashList, gDashSize);
XDrawLine(fDisplay, gCws->fDrawing, *gGCdash, x1, y1, x2, y2);
}
}
void TGX11::DrawPolyLine(int n, TPoint *xyt)
{
XPoint *xy = (XPoint*)xyt;
const Int_t kMaxPoints = 1000001;
if (n > kMaxPoints) {
int ibeg = 0;
int iend = kMaxPoints - 1;
while (iend < n) {
DrawPolyLine( kMaxPoints, &xyt[ibeg] );
ibeg = iend;
iend += kMaxPoints - 1;
}
if (ibeg < n) {
int npt = n - ibeg;
DrawPolyLine( npt, &xyt[ibeg] );
}
} else if (n > 1) {
if (gLineStyle == LineSolid)
XDrawLines(fDisplay, gCws->fDrawing, *gGCline, xy, n, CoordModeOrigin);
else {
int i;
XSetDashes(fDisplay, *gGCdash,
gDashOffset, gDashList, gDashSize);
XDrawLines(fDisplay, gCws->fDrawing, *gGCdash, xy, n, CoordModeOrigin);
for (i = 1; i < n; i++) {
int dx = xy[i].x - xy[i-1].x;
int dy = xy[i].y - xy[i-1].y;
if (dx < 0) dx = - dx;
if (dy < 0) dy = - dy;
gDashOffset += dx > dy ? dx : dy;
}
gDashOffset %= gDashLength;
}
} else {
int px,py;
px=xy[0].x;
py=xy[0].y;
XDrawPoint(fDisplay, gCws->fDrawing,
gLineStyle == LineSolid ? *gGCline : *gGCdash, px, py);
}
}
void TGX11::DrawPolyMarker(int n, TPoint *xyt)
{
XPoint *xy = (XPoint*)xyt;
if (gMarker.n <= 0) {
const int kNMAX = 1000000;
int nt = n/kNMAX;
for (int it=0;it<=nt;it++) {
if (it < nt) {
XDrawPoints(fDisplay, gCws->fDrawing, *gGCmark, &xy[it*kNMAX], kNMAX, CoordModeOrigin);
} else {
XDrawPoints(fDisplay, gCws->fDrawing, *gGCmark, &xy[it*kNMAX], n-it*kNMAX, CoordModeOrigin);
}
}
} else {
int r = gMarker.n / 2;
int m;
for (m = 0; m < n; m++) {
int hollow = 0;
switch (gMarker.type) {
int i;
case 0:
XDrawArc(fDisplay, gCws->fDrawing, *gGCmark,
xy[m].x - r, xy[m].y - r, gMarker.n, gMarker.n, 0, 360*64);
break;
case 1:
XFillArc(fDisplay, gCws->fDrawing, *gGCmark,
xy[m].x - r, xy[m].y - r, gMarker.n, gMarker.n, 0, 360*64);
break;
case 2:
hollow = 1;
case 3:
for (i = 0; i < gMarker.n; i++) {
gMarker.xy[i].x += xy[m].x;
gMarker.xy[i].y += xy[m].y;
}
if (hollow)
XDrawLines(fDisplay, gCws->fDrawing, *gGCmark,
gMarker.xy, gMarker.n, CoordModeOrigin);
else
XFillPolygon(fDisplay, gCws->fDrawing, *gGCmark,
gMarker.xy, gMarker.n, Nonconvex, CoordModeOrigin);
for (i = 0; i < gMarker.n; i++) {
gMarker.xy[i].x -= xy[m].x;
gMarker.xy[i].y -= xy[m].y;
}
break;
case 4:
for (i = 0; i < gMarker.n; i += 2)
XDrawLine(fDisplay, gCws->fDrawing, *gGCmark,
xy[m].x + gMarker.xy[i].x, xy[m].y + gMarker.xy[i].y,
xy[m].x + gMarker.xy[i+1].x, xy[m].y + gMarker.xy[i+1].y);
break;
}
}
}
}
void TGX11::DrawText(int x, int y, float angle, float mgn,
const char *text, ETextMode mode)
{
XRotSetMagnification(mgn);
if (!text) return;
switch (mode) {
case kClear:
XRotDrawAlignedString(fDisplay, gTextFont, angle,
gCws->fDrawing, *gGCtext, x, y, (char*)text, fTextAlign);
break;
case kOpaque:
XRotDrawAlignedImageString(fDisplay, gTextFont, angle,
gCws->fDrawing, *gGCtext, x, y, (char*)text, fTextAlign);
break;
default:
break;
}
}
void TGX11::FindBestVisual()
{
Int_t findvis = gEnv->GetValue("X11.FindBestVisual", 1);
Visual *vis = DefaultVisual(fDisplay, fScreenNumber);
if (((vis->c_class != TrueColor && vis->c_class != DirectColor) ||
DefaultDepth(fDisplay, fScreenNumber) < 15) && findvis) {
static XVisualInfo templates[] = {
{ 0 , 0 , 0 , 24 , TrueColor , 0 , 0 , 0 , 0 , 0 },
{ 0 , 0 , 0 , 32 , TrueColor , 0 , 0 , 0 , 0 , 0 },
{ 0 , 0 , 0 , 16 , TrueColor , 0 , 0 , 0 , 0 , 0 },
{ 0 , 0 , 0 , 15 , TrueColor , 0 , 0 , 0 , 0 , 0 },
{ 0 , 0 , 0 , 24 , DirectColor, 0 , 0 , 0 , 0 , 0 },
{ 0 , 0 , 0 , 32 , DirectColor, 0 , 0 , 0 , 0 , 0 },
{ 0 , 0 , 0 , 16 , DirectColor, 0 , 0 , 0 , 0 , 0 },
{ 0 , 0 , 0 , 15 , DirectColor, 0 , 0 , 0 , 0 , 0 },
{ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
};
Int_t nitems = 0;
XVisualInfo *vlist = 0;
for (Int_t i = 0; templates[i].depth != 0; i++) {
Int_t mask = VisualScreenMask|VisualDepthMask|VisualClassMask;
templates[i].screen = fScreenNumber;
if ((vlist = XGetVisualInfo(fDisplay, mask, &(templates[i]), &nitems))) {
FindUsableVisual(vlist, nitems);
XFree(vlist);
vlist = 0;
if (fVisual)
break;
}
}
}
fRootWin = RootWindow(fDisplay, fScreenNumber);
if (!fVisual) {
fDepth = DefaultDepth(fDisplay, fScreenNumber);
fVisual = DefaultVisual(fDisplay, fScreenNumber);
fVisRootWin = fRootWin;
if (fDepth > 1)
fColormap = DefaultColormap(fDisplay, fScreenNumber);
fBlackPixel = BlackPixel(fDisplay, fScreenNumber);
fWhitePixel = WhitePixel(fDisplay, fScreenNumber);
}
if (gDebug > 1)
Printf("Selected visual 0x%lx: depth %d, class %d, colormap: %s",
fVisual->visualid, fDepth, fVisual->c_class,
fColormap == DefaultColormap(fDisplay, fScreenNumber) ? "default" :
"custom");
}
static Int_t DummyX11ErrorHandler(Display *, XErrorEvent *)
{
return 0;
}
void TGX11::FindUsableVisual(XVisualInfo *vlist, Int_t nitems)
{
Int_t (*oldErrorHandler)(Display *, XErrorEvent *) =
XSetErrorHandler(DummyX11ErrorHandler);
XSetWindowAttributes attr;
memset(&attr, 0, sizeof(attr));
Window root = RootWindow(fDisplay, fScreenNumber);
for (Int_t i = 0; i < nitems; i++) {
Window w = None, wjunk;
UInt_t width, height, ujunk;
Int_t junk;
if (vlist[i].visual == DefaultVisual(fDisplay, fScreenNumber)) {
attr.colormap = DefaultColormap(fDisplay, fScreenNumber);
} else {
attr.colormap = XCreateColormap(fDisplay, root, vlist[i].visual, AllocNone);
}
static XColor black_xcol = { 0, 0x0000, 0x0000, 0x0000, DoRed|DoGreen|DoBlue, 0 };
static XColor white_xcol = { 0, 0xFFFF, 0xFFFF, 0xFFFF, DoRed|DoGreen|DoBlue, 0 };
XAllocColor(fDisplay, attr.colormap, &black_xcol);
XAllocColor(fDisplay, attr.colormap, &white_xcol);
attr.border_pixel = black_xcol.pixel;
attr.override_redirect = True;
w = XCreateWindow(fDisplay, root, -20, -20, 10, 10, 0, vlist[i].depth,
CopyFromParent, vlist[i].visual,
CWColormap|CWBorderPixel|CWOverrideRedirect, &attr);
if (w != None && XGetGeometry(fDisplay, w, &wjunk, &junk, &junk,
&width, &height, &ujunk, &ujunk)) {
fVisual = vlist[i].visual;
fDepth = vlist[i].depth;
fColormap = attr.colormap;
fBlackPixel = black_xcol.pixel;
fWhitePixel = white_xcol.pixel;
fVisRootWin = w;
break;
}
if (attr.colormap != DefaultColormap(fDisplay, fScreenNumber))
XFreeColormap(fDisplay, attr.colormap);
}
XSetErrorHandler(oldErrorHandler);
}
void TGX11::GetCharacterUp(Float_t &chupx, Float_t &chupy)
{
chupx = fCharacterUpX;
chupy = fCharacterUpY;
}
XColor_t &TGX11::GetColor(Int_t cid)
{
XColor_t *col = (XColor_t*) (Long_t)fColors->GetValue(cid);
if (!col) {
col = new XColor_t;
fColors->Add(cid, (Long_t) col);
}
return *col;
}
Window_t TGX11::GetCurrentWindow() const
{
return (Window_t)(gCws ? gCws->fDrawing : 0);
}
GC *TGX11::GetGC(Int_t which) const
{
if (which >= kMAXGC || which < 0) {
Error("GetGC", "trying to get illegal GC (which = %d)", which);
return 0;
}
return &gGClist[which];
}
Int_t TGX11::GetDoubleBuffer(int wid)
{
gTws = &fWindows[wid];
if (!gTws->fOpen)
return -1;
else
return gTws->fDoubleBuffer;
}
void TGX11::GetGeometry(int wid, int &x, int &y, unsigned int &w, unsigned int &h)
{
Window junkwin=0;
if (wid < 0) {
x = 0;
y = 0;
w = DisplayWidth(fDisplay,fScreenNumber);
h = DisplayHeight(fDisplay,fScreenNumber);
} else {
Window root;
unsigned int border, depth;
unsigned int width, height;
gTws = &fWindows[wid];
XGetGeometry(fDisplay, gTws->fWindow, &root, &x, &y,
&width, &height, &border, &depth);
XTranslateCoordinates(fDisplay, gTws->fWindow, fRootWin,
0, 0, &x, &y, &junkwin);
if (width >= 65535)
width = 1;
if (height >= 65535)
height = 1;
if (width > 0 && height > 0) {
gTws->fWidth = width;
gTws->fHeight = height;
}
w = gTws->fWidth;
h = gTws->fHeight;
}
}
const char *TGX11::DisplayName(const char *dpyName)
{
return XDisplayName(dpyName);
}
ULong_t TGX11::GetPixel(Color_t ci)
{
TColor *color = gROOT->GetColor(ci);
if (color)
SetRGB(ci, color->GetRed(), color->GetGreen(), color->GetBlue());
XColor_t &col = GetColor(ci);
return col.fPixel;
}
void TGX11::GetPlanes(int &nplanes)
{
nplanes = fDepth;
}
void TGX11::GetRGB(int index, float &r, float &g, float &b)
{
if (index == 0) {
r = g = b = 1.0;
} else if (index == 1) {
r = g = b = 0.0;
} else {
XColor_t &col = GetColor(index);
r = ((float) col.fRed) / ((float) kBIGGEST_RGB_VALUE);
g = ((float) col.fGreen) / ((float) kBIGGEST_RGB_VALUE);
b = ((float) col.fBlue) / ((float) kBIGGEST_RGB_VALUE);
}
}
void TGX11::GetTextExtent(unsigned int &w, unsigned int &h, char *mess)
{
w=0; h=0;
if (strlen(mess)==0) return;
XPoint *cBox;
XRotSetMagnification(fTextMagnitude);
cBox = XRotTextExtents(fDisplay, gTextFont, 0., 0, 0, mess, 0);
if (cBox) {
w = cBox[2].x;
h = -cBox[2].y;
free((char *)cBox);
}
}
Window_t TGX11::GetWindowID(int wid)
{
return (Window_t) fWindows[wid].fWindow;
}
void TGX11::MoveWindow(int wid, int x, int y)
{
gTws = &fWindows[wid];
if (!gTws->fOpen) return;
XMoveWindow(fDisplay, gTws->fWindow, x, y);
}
Int_t TGX11::OpenDisplay(Display *disp)
{
Pixmap pixmp1, pixmp2;
XColor fore, back;
char **fontlist;
int fontcount = 0;
int i;
if (fDisplay) return 0;
fDisplay = disp;
fScreenNumber = DefaultScreen(fDisplay);
FindBestVisual();
GetColor(1).fDefined = kTRUE;
GetColor(1).fPixel = fBlackPixel;
GetColor(0).fDefined = kTRUE;
GetColor(0).fPixel = fWhitePixel;
char vendor[132];
strlcpy(vendor, XServerVendor(fDisplay),132);
for (i = 0; i < kMAXGC; i++)
gGClist[i] = XCreateGC(fDisplay, fVisRootWin, 0, 0);
XGCValues values;
if (XGetGCValues(fDisplay, *gGCtext, GCForeground|GCBackground, &values)) {
XSetForeground(fDisplay, *gGCinvt, values.background);
XSetBackground(fDisplay, *gGCinvt, values.foreground);
} else {
Error("OpenDisplay", "cannot get GC values");
}
XSetGraphicsExposures(fDisplay, *gGCpxmp, False);
XGCValues echov;
echov.foreground = fBlackPixel;
echov.background = fWhitePixel;
if (strstr(vendor,"Hewlett"))
echov.function = GXxor;
else
echov.function = GXinvert;
gGCecho = XCreateGC(fDisplay, fVisRootWin,
GCForeground | GCBackground | GCFunction,
&echov);
static int isdisp = 0;
if (!isdisp) {
for (i = 0; i < kMAXFONT; i++) {
gFont[i].id = 0;
strcpy(gFont[i].name, " ");
}
fontlist = XListFonts(fDisplay, "*courier*", 1, &fontcount);
if (fontlist && fontcount != 0) {
gFont[gCurrentFontNumber].id = XLoadQueryFont(fDisplay, fontlist[0]);
gTextFont = gFont[gCurrentFontNumber].id;
strcpy(gFont[gCurrentFontNumber].name, "*courier*");
gCurrentFontNumber++;
XFreeFontNames(fontlist);
} else {
fontlist = XListFonts(fDisplay, "fixed", 1, &fontcount);
if (fontlist && fontcount != 0) {
gFont[gCurrentFontNumber].id = XLoadQueryFont(fDisplay, fontlist[0]);
gTextFont = gFont[gCurrentFontNumber].id;
strcpy(gFont[gCurrentFontNumber].name, "fixed");
gCurrentFontNumber++;
XFreeFontNames(fontlist);
} else {
Warning("OpenDisplay", "no default font loaded");
}
}
isdisp = 1;
}
pixmp1 = XCreateBitmapFromData(fDisplay, fRootWin,
null_cursor_bits, 16, 16);
pixmp2 = XCreateBitmapFromData(fDisplay, fRootWin,
null_cursor_bits, 16, 16);
gNullCursor = XCreatePixmapCursor(fDisplay,pixmp1,pixmp2,&fore,&back,0,0);
fCursors[kBottomLeft] = XCreateFontCursor(fDisplay, XC_bottom_left_corner);
fCursors[kBottomRight] = XCreateFontCursor(fDisplay, XC_bottom_right_corner);
fCursors[kTopLeft] = XCreateFontCursor(fDisplay, XC_top_left_corner);
fCursors[kTopRight] = XCreateFontCursor(fDisplay, XC_top_right_corner);
fCursors[kBottomSide] = XCreateFontCursor(fDisplay, XC_bottom_side);
fCursors[kLeftSide] = XCreateFontCursor(fDisplay, XC_left_side);
fCursors[kTopSide] = XCreateFontCursor(fDisplay, XC_top_side);
fCursors[kRightSide] = XCreateFontCursor(fDisplay, XC_right_side);
fCursors[kMove] = XCreateFontCursor(fDisplay, XC_fleur);
fCursors[kCross] = XCreateFontCursor(fDisplay, XC_tcross);
fCursors[kArrowHor] = XCreateFontCursor(fDisplay, XC_sb_h_double_arrow);
fCursors[kArrowVer] = XCreateFontCursor(fDisplay, XC_sb_v_double_arrow);
fCursors[kHand] = XCreateFontCursor(fDisplay, XC_hand2);
fCursors[kRotate] = XCreateFontCursor(fDisplay, XC_exchange);
fCursors[kPointer] = XCreateFontCursor(fDisplay, XC_left_ptr);
fCursors[kArrowRight] = XCreateFontCursor(fDisplay, XC_arrow);
fCursors[kCaret] = XCreateFontCursor(fDisplay, XC_xterm);
fCursors[kWatch] = XCreateFontCursor(fDisplay, XC_watch);
fCursors[kNoDrop] = XCreateFontCursor(fDisplay, XC_pirate);
fRedDiv = fGreenDiv = fBlueDiv = fRedShift = fGreenShift = fBlueShift = -1;
if (fVisual->c_class == TrueColor) {
for (i = 0; i < int(sizeof(fVisual->blue_mask)*kBitsPerByte); i++) {
if (fBlueShift == -1 && ((fVisual->blue_mask >> i) & 1))
fBlueShift = i;
if ((fVisual->blue_mask >> i) == 1) {
fBlueDiv = sizeof(UShort_t)*kBitsPerByte - i - 1 + fBlueShift;
break;
}
}
for (i = 0; i < int(sizeof(fVisual->green_mask)*kBitsPerByte); i++) {
if (fGreenShift == -1 && ((fVisual->green_mask >> i) & 1))
fGreenShift = i;
if ((fVisual->green_mask >> i) == 1) {
fGreenDiv = sizeof(UShort_t)*kBitsPerByte - i - 1 + fGreenShift;
break;
}
}
for (i = 0; i < int(sizeof(fVisual->red_mask)*kBitsPerByte); i++) {
if (fRedShift == -1 && ((fVisual->red_mask >> i) & 1))
fRedShift = i;
if ((fVisual->red_mask >> i) == 1) {
fRedDiv = sizeof(UShort_t)*kBitsPerByte - i - 1 + fRedShift;
break;
}
}
}
return 0;
}
Int_t TGX11::OpenPixmap(unsigned int w, unsigned int h)
{
Window root;
unsigned int wval, hval;
int xx, yy, i, wid;
unsigned int ww, hh, border, depth;
wval = w;
hval = h;
again:
for (wid = 0; wid < fMaxNumberOfWindows; wid++)
if (!fWindows[wid].fOpen) {
fWindows[wid].fOpen = 1;
gCws = &fWindows[wid];
break;
}
if (wid == fMaxNumberOfWindows) {
int newsize = fMaxNumberOfWindows + 10;
fWindows = (XWindow_t*) TStorage::ReAlloc(fWindows, newsize*sizeof(XWindow_t),
fMaxNumberOfWindows*sizeof(XWindow_t));
for (i = fMaxNumberOfWindows; i < newsize; i++)
fWindows[i].fOpen = 0;
fMaxNumberOfWindows = newsize;
goto again;
}
gCws->fWindow = XCreatePixmap(fDisplay, fRootWin, wval, hval, fDepth);
XGetGeometry(fDisplay, gCws->fWindow, &root, &xx, &yy, &ww, &hh, &border, &depth);
for (i = 0; i < kMAXGC; i++)
XSetClipMask(fDisplay, gGClist[i], None);
SetColor(*gGCpxmp, 0);
XFillRectangle(fDisplay, gCws->fWindow, *gGCpxmp, 0, 0, ww, hh);
SetColor(*gGCpxmp, 1);
gCws->fDrawing = gCws->fWindow;
gCws->fBuffer = 0;
gCws->fDoubleBuffer = 0;
gCws->fIsPixmap = 1;
gCws->fClip = 0;
gCws->fWidth = wval;
gCws->fHeight = hval;
gCws->fNewColors = 0;
gCws->fShared = kFALSE;
return wid;
}
Int_t TGX11::InitWindow(ULong_t win)
{
XSetWindowAttributes attributes;
ULong_t attr_mask = 0;
int wid;
int xval, yval;
unsigned int wval, hval, border, depth;
Window root;
Window wind = (Window) win;
XGetGeometry(fDisplay, wind, &root, &xval, &yval, &wval, &hval, &border, &depth);
again:
for (wid = 0; wid < fMaxNumberOfWindows; wid++)
if (!fWindows[wid].fOpen) {
fWindows[wid].fOpen = 1;
fWindows[wid].fDoubleBuffer = 0;
gCws = &fWindows[wid];
break;
}
if (wid == fMaxNumberOfWindows) {
int newsize = fMaxNumberOfWindows + 10;
fWindows = (XWindow_t*) TStorage::ReAlloc(fWindows, newsize*sizeof(XWindow_t),
fMaxNumberOfWindows*sizeof(XWindow_t));
for (int i = fMaxNumberOfWindows; i < newsize; i++)
fWindows[i].fOpen = 0;
fMaxNumberOfWindows = newsize;
goto again;
}
attributes.background_pixel = GetColor(0).fPixel;
attr_mask |= CWBackPixel;
attributes.border_pixel = GetColor(1).fPixel;
attr_mask |= CWBorderPixel;
attributes.event_mask = NoEventMask;
attr_mask |= CWEventMask;
attributes.backing_store = Always;
attr_mask |= CWBackingStore;
attributes.bit_gravity = NorthWestGravity;
attr_mask |= CWBitGravity;
if (fColormap) {
attributes.colormap = fColormap;
attr_mask |= CWColormap;
}
gCws->fWindow = XCreateWindow(fDisplay, wind,
xval, yval, wval, hval, 0, fDepth,
InputOutput, fVisual,
attr_mask, &attributes);
XMapWindow(fDisplay, gCws->fWindow);
XFlush(fDisplay);
gCws->fDrawing = gCws->fWindow;
gCws->fBuffer = 0;
gCws->fDoubleBuffer = 0;
gCws->fIsPixmap = 0;
gCws->fClip = 0;
gCws->fWidth = wval;
gCws->fHeight = hval;
gCws->fNewColors = 0;
gCws->fShared = kFALSE;
return wid;
}
Int_t TGX11::AddWindow(ULong_t qwid, UInt_t w, UInt_t h)
{
Int_t wid;
again:
for (wid = 0; wid < fMaxNumberOfWindows; wid++)
if (!fWindows[wid].fOpen) {
fWindows[wid].fOpen = 1;
fWindows[wid].fDoubleBuffer = 0;
gCws = &fWindows[wid];
break;
}
if (wid == fMaxNumberOfWindows) {
int newsize = fMaxNumberOfWindows + 10;
fWindows = (XWindow_t*) TStorage::ReAlloc(fWindows, newsize*sizeof(XWindow_t),
fMaxNumberOfWindows*sizeof(XWindow_t));
for (int i = fMaxNumberOfWindows; i < newsize; i++)
fWindows[i].fOpen = 0;
fMaxNumberOfWindows = newsize;
goto again;
}
gCws->fWindow = qwid;
gCws->fDrawing = gCws->fWindow;
gCws->fBuffer = 0;
gCws->fDoubleBuffer = 0;
gCws->fIsPixmap = 0;
gCws->fClip = 0;
gCws->fWidth = w;
gCws->fHeight = h;
gCws->fNewColors = 0;
gCws->fShared = kTRUE;
return wid;
}
void TGX11::RemoveWindow(ULong_t qwid)
{
SelectWindow((int)qwid);
if (gCws->fBuffer) XFreePixmap(fDisplay, gCws->fBuffer);
if (gCws->fNewColors) {
if (fRedDiv == -1)
XFreeColors(fDisplay, fColormap, gCws->fNewColors, gCws->fNcolors, 0);
delete [] gCws->fNewColors;
gCws->fNewColors = 0;
}
gCws->fOpen = 0;
for (Int_t wid = 0; wid < fMaxNumberOfWindows; wid++)
if (fWindows[wid].fOpen) {
gCws = &fWindows[wid];
return;
}
gCws = 0;
}
void TGX11::QueryPointer(int &ix, int &iy)
{
Window root_return, child_return;
int win_x_return, win_y_return;
int root_x_return, root_y_return;
unsigned int mask_return;
XQueryPointer(fDisplay,gCws->fWindow, &root_return,
&child_return, &root_x_return, &root_y_return, &win_x_return,
&win_y_return, &mask_return);
ix = root_x_return;
iy = root_y_return;
}
void TGX11::RemovePixmap(Drawable *pix)
{
XFreePixmap(fDisplay,*pix);
}
Int_t TGX11::RequestLocator(int mode, int ctyp, int &x, int &y)
{
static int xloc = 0;
static int yloc = 0;
static int xlocp = 0;
static int ylocp = 0;
static Cursor cursor = 0;
XEvent event;
int button_press;
int radius;
if (cursor == 0) {
if (ctyp > 1) {
XDefineCursor(fDisplay, gCws->fWindow, gNullCursor);
XSetForeground(fDisplay, gGCecho, GetColor(0).fPixel);
} else {
cursor = XCreateFontCursor(fDisplay, XC_crosshair);
XDefineCursor(fDisplay, gCws->fWindow, cursor);
}
}
button_press = 0;
while (button_press == 0) {
switch (ctyp) {
case 1 :
break;
case 2 :
XDrawLine(fDisplay, gCws->fWindow, gGCecho,
xloc, 0, xloc, gCws->fHeight);
XDrawLine(fDisplay, gCws->fWindow, gGCecho,
0, yloc, gCws->fWidth, yloc);
break;
case 3 :
radius = (int) TMath::Sqrt((double)((xloc-xlocp)*(xloc-xlocp) +
(yloc-ylocp)*(yloc-ylocp)));
XDrawArc(fDisplay, gCws->fWindow, gGCecho,
xlocp-radius, ylocp-radius,
2*radius, 2*radius, 0, 23040);
break;
case 4 :
XDrawLine(fDisplay, gCws->fWindow, gGCecho,
xlocp, ylocp, xloc, yloc);
break;
case 5 :
XDrawRectangle(fDisplay, gCws->fWindow, gGCecho,
TMath::Min(xlocp,xloc), TMath::Min(ylocp,yloc),
TMath::Abs(xloc-xlocp), TMath::Abs(yloc-ylocp));
break;
default:
break;
}
while (XEventsQueued( fDisplay, QueuedAlready) > 1) {
XNextEvent(fDisplay, &event);
}
XWindowEvent(fDisplay, gCws->fWindow, gMouseMask, &event);
switch (ctyp) {
case 1 :
break;
case 2 :
XDrawLine(fDisplay, gCws->fWindow, gGCecho,
xloc, 0, xloc, gCws->fHeight);
XDrawLine(fDisplay, gCws->fWindow, gGCecho,
0, yloc, gCws->fWidth, yloc);
break;
case 3 :
radius = (int) TMath::Sqrt((double)((xloc-xlocp)*(xloc-xlocp) +
(yloc-ylocp)*(yloc-ylocp)));
XDrawArc(fDisplay, gCws->fWindow, gGCecho,
xlocp-radius, ylocp-radius,
2*radius, 2*radius, 0, 23040);
break;
case 4 :
XDrawLine(fDisplay, gCws->fWindow, gGCecho,
xlocp, ylocp, xloc, yloc);
break;
case 5 :
XDrawRectangle(fDisplay, gCws->fWindow, gGCecho,
TMath::Min(xlocp,xloc), TMath::Min(ylocp,yloc),
TMath::Abs(xloc-xlocp), TMath::Abs(yloc-ylocp));
break;
default:
break;
}
xloc = event.xbutton.x;
yloc = event.xbutton.y;
switch (event.type) {
case LeaveNotify :
if (mode == 0) {
while (1) {
XNextEvent(fDisplay, &event);
if (event.type == EnterNotify) break;
}
} else {
button_press = -2;
}
break;
case ButtonPress :
button_press = event.xbutton.button ;
xlocp = event.xbutton.x;
ylocp = event.xbutton.y;
XUndefineCursor( fDisplay, gCws->fWindow );
cursor = 0;
break;
case ButtonRelease :
if (mode == 1) {
button_press = 10+event.xbutton.button ;
xlocp = event.xbutton.x;
ylocp = event.xbutton.y;
}
break;
case KeyPress :
if (mode == 1) {
button_press = event.xkey.keycode;
xlocp = event.xbutton.x;
ylocp = event.xbutton.y;
}
break;
case KeyRelease :
if (mode == 1) {
button_press = -event.xkey.keycode;
xlocp = event.xbutton.x;
ylocp = event.xbutton.y;
}
break;
default :
break;
}
if (mode == 1) {
if (button_press == 0)
button_press = -1;
break;
}
}
x = event.xbutton.x;
y = event.xbutton.y;
return button_press;
}
Int_t TGX11::RequestString(int x, int y, char *text)
{
static Cursor cursor = 0;
static int percent = 0;
Window focuswindow;
int focusrevert;
XEvent event;
KeySym keysym;
int key = -1;
int len_text = strlen(text);
int nt;
int pt;
if (cursor == 0) {
XKeyboardState kbstate;
cursor = XCreateFontCursor(fDisplay, XC_question_arrow);
XGetKeyboardControl(fDisplay, &kbstate);
percent = kbstate.bell_percent;
}
if (cursor != 0)
XDefineCursor(fDisplay, gCws->fWindow, cursor);
for (nt = len_text; nt > 0 && text[nt-1] == ' '; nt--) { }
pt = nt;
XGetInputFocus(fDisplay, &focuswindow, &focusrevert);
XSetInputFocus(fDisplay, gCws->fWindow, focusrevert, CurrentTime);
while (key < 0) {
char keybuf[8];
char nbytes;
int dx;
int i;
XDrawImageString(fDisplay, gCws->fWindow, *gGCtext, x, y, text, nt);
dx = XTextWidth(gTextFont, text, nt);
XDrawImageString(fDisplay, gCws->fWindow, *gGCtext, x + dx, y, " ", 1);
dx = pt == 0 ? 0 : XTextWidth(gTextFont, text, pt);
XDrawImageString(fDisplay, gCws->fWindow, *gGCinvt,
x + dx, y, pt < len_text ? &text[pt] : " ", 1);
XWindowEvent(fDisplay, gCws->fWindow, gKeybdMask, &event);
switch (event.type) {
case ButtonPress:
case EnterNotify:
XSetInputFocus(fDisplay, gCws->fWindow, focusrevert, CurrentTime);
break;
case LeaveNotify:
XSetInputFocus(fDisplay, focuswindow, focusrevert, CurrentTime);
break;
case KeyPress:
nbytes = XLookupString(&event.xkey, keybuf, sizeof(keybuf),
&keysym, 0);
switch (keysym) {
case XK_Left:
keybuf[0] = '\002';
nbytes = 1;
break;
case XK_Right:
keybuf[0] = '\006';
nbytes = 1;
break;
}
if (nbytes == 1) {
if (isascii(keybuf[0]) && isprint(keybuf[0])) {
if (nt < len_text)
nt++;
for (i = nt - 1; i > pt; i--)
text[i] = text[i-1];
if (pt < len_text) {
text[pt] = keybuf[0];
pt++;
}
} else
switch (keybuf[0]) {
case '\010':
case '\177':
if (pt > 0) {
for (i = pt; i < nt; i++)
text[i-1] = text[i];
text[nt-1] = ' ';
nt--;
pt--;
}
break;
case '\001':
pt = 0;
break;
case '\002':
if (pt > 0)
pt--;
break;
case '\004':
if (pt > 0) {
for (i = pt; i < nt; i++)
text[i-1] = text[i];
text[nt-1] = ' ';
pt--;
}
break;
case '\005':
pt = nt;
break;
case '\006':
if (pt < nt)
pt++;
break;
case '\013':
for (i = pt; i < nt; i++)
text[i] = ' ';
nt = pt;
break;
case '\024':
if (pt > 0) {
char c = text[pt];
text[pt] = text[pt-1];
text[pt-1] = c;
}
break;
case '\012':
case '\015':
key = 1;
break;
case '\033':
key = 0;
break;
default:
XBell(fDisplay, percent);
}
}
}
}
XSetInputFocus(fDisplay, focuswindow, focusrevert, CurrentTime);
if (cursor != 0) {
XUndefineCursor(fDisplay, gCws->fWindow);
cursor = 0;
}
return key;
}
void TGX11::RescaleWindow(int wid, unsigned int w, unsigned int h)
{
int i;
gTws = &fWindows[wid];
if (!gTws->fOpen) return;
if (gTws->fWidth == w && gTws->fHeight == h) return;
XResizeWindow(fDisplay, gTws->fWindow, w, h);
if (gTws->fBuffer) {
if (gTws->fWidth < w || gTws->fHeight < h) {
XFreePixmap(fDisplay,gTws->fBuffer);
gTws->fBuffer = XCreatePixmap(fDisplay, fRootWin, w, h, fDepth);
}
for (i = 0; i < kMAXGC; i++) XSetClipMask(fDisplay, gGClist[i], None);
SetColor(*gGCpxmp, 0);
XFillRectangle( fDisplay, gTws->fBuffer, *gGCpxmp, 0, 0, w, h);
SetColor(*gGCpxmp, 1);
if (gTws->fDoubleBuffer) gTws->fDrawing = gTws->fBuffer;
}
gTws->fWidth = w;
gTws->fHeight = h;
}
int TGX11::ResizePixmap(int wid, unsigned int w, unsigned int h)
{
Window root;
unsigned int wval, hval;
int xx, yy, i;
unsigned int ww, hh, border, depth;
wval = w;
hval = h;
gTws = &fWindows[wid];
if (gTws->fWidth >= wval-1 && gTws->fWidth <= wval+1 &&
gTws->fHeight >= hval-1 && gTws->fHeight <= hval+1) return 0;
if (gTws->fWidth < wval || gTws->fHeight < hval) {
XFreePixmap(fDisplay, gTws->fWindow);
gTws->fWindow = XCreatePixmap(fDisplay, fRootWin, wval, hval, fDepth);
}
XGetGeometry(fDisplay, gTws->fWindow, &root, &xx, &yy, &ww, &hh, &border, &depth);
for (i = 0; i < kMAXGC; i++)
XSetClipMask(fDisplay, gGClist[i], None);
SetColor(*gGCpxmp, 0);
XFillRectangle(fDisplay, gTws->fWindow, *gGCpxmp, 0, 0, ww, hh);
SetColor(*gGCpxmp, 1);
gTws->fDrawing = gTws->fWindow;
gTws->fWidth = wval;
gTws->fHeight = hval;
return 1;
}
void TGX11::ResizeWindow(int wid)
{
int i;
int xval=0, yval=0;
Window win, root=0;
unsigned int wval=0, hval=0, border=0, depth=0;
gTws = &fWindows[wid];
win = gTws->fWindow;
XGetGeometry(fDisplay, win, &root,
&xval, &yval, &wval, &hval, &border, &depth);
if (wval >= 65500) wval = 1;
if (hval >= 65500) hval = 1;
if (gTws->fWidth == wval && gTws->fHeight == hval) return;
XResizeWindow(fDisplay, gTws->fWindow, wval, hval);
if (gTws->fBuffer) {
if (gTws->fWidth < wval || gTws->fHeight < hval) {
XFreePixmap(fDisplay,gTws->fBuffer);
gTws->fBuffer = XCreatePixmap(fDisplay, fRootWin, wval, hval, fDepth);
}
for (i = 0; i < kMAXGC; i++) XSetClipMask(fDisplay, gGClist[i], None);
SetColor(*gGCpxmp, 0);
XFillRectangle(fDisplay, gTws->fBuffer, *gGCpxmp, 0, 0, wval, hval);
SetColor(*gGCpxmp, 1);
if (gTws->fDoubleBuffer) gTws->fDrawing = gTws->fBuffer;
}
gTws->fWidth = wval;
gTws->fHeight = hval;
}
void TGX11::SelectWindow(int wid)
{
XRectangle region;
int i;
if (wid < 0 || wid >= fMaxNumberOfWindows || !fWindows[wid].fOpen) return;
gCws = &fWindows[wid];
if (gCws->fClip && !gCws->fIsPixmap && !gCws->fDoubleBuffer) {
region.x = gCws->fXclip;
region.y = gCws->fYclip;
region.width = gCws->fWclip;
region.height = gCws->fHclip;
for (i = 0; i < kMAXGC; i++)
XSetClipRectangles(fDisplay, gGClist[i], 0, 0, ®ion, 1, YXBanded);
} else {
for (i = 0; i < kMAXGC; i++)
XSetClipMask(fDisplay, gGClist[i], None);
}
}
void TGX11::SetCharacterUp(Float_t chupx, Float_t chupy)
{
if (chupx == fCharacterUpX && chupy == fCharacterUpY) return;
if (chupx == 0 && chupy == 0) fTextAngle = 0;
else if (chupx == 0 && chupy == 1) fTextAngle = 0;
else if (chupx == -1 && chupy == 0) fTextAngle = 90;
else if (chupx == 0 && chupy == -1) fTextAngle = 180;
else if (chupx == 1 && chupy == 0) fTextAngle = 270;
else {
fTextAngle = ((TMath::ACos(chupx/TMath::Sqrt(chupx*chupx +chupy*chupy))*180.)/TMath::Pi())-90;
if (chupy < 0) fTextAngle = 180 - fTextAngle;
if (TMath::Abs(fTextAngle) <= 0.01) fTextAngle = 0;
}
fCharacterUpX = chupx;
fCharacterUpY = chupy;
}
void TGX11::SetClipOFF(int wid)
{
gTws = &fWindows[wid];
gTws->fClip = 0;
for (int i = 0; i < kMAXGC; i++)
XSetClipMask( fDisplay, gGClist[i], None );
}
void TGX11::SetClipRegion(int wid, int x, int y, unsigned int w, unsigned int h)
{
gTws = &fWindows[wid];
gTws->fXclip = x;
gTws->fYclip = y;
gTws->fWclip = w;
gTws->fHclip = h;
gTws->fClip = 1;
if (gTws->fClip && !gTws->fIsPixmap && !gTws->fDoubleBuffer) {
XRectangle region;
region.x = gTws->fXclip;
region.y = gTws->fYclip;
region.width = gTws->fWclip;
region.height = gTws->fHclip;
for (int i = 0; i < kMAXGC; i++)
XSetClipRectangles(fDisplay, gGClist[i], 0, 0, ®ion, 1, YXBanded);
}
}
void TGX11::SetColor(GC gc, int ci)
{
TColor *color = gROOT->GetColor(ci);
if (color)
SetRGB(ci, color->GetRed(), color->GetGreen(), color->GetBlue());
XColor_t &col = GetColor(ci);
if (fColormap && !col.fDefined) {
col = GetColor(0);
} else if (!fColormap && (ci < 0 || ci > 1)) {
col = GetColor(0);
}
if (fDrawMode == kXor) {
XGCValues values;
XGetGCValues(fDisplay, gc, GCBackground, &values);
XSetForeground(fDisplay, gc, col.fPixel ^ values.background);
} else {
XSetForeground(fDisplay, gc, col.fPixel);
XGCValues values;
XGetGCValues(fDisplay, gc, GCForeground | GCBackground, &values);
if (values.foreground == values.background)
XSetBackground(fDisplay, gc, GetColor(!ci).fPixel);
}
}
void TGX11::SetCursor(int wid, ECursor cursor)
{
gTws = &fWindows[wid];
XDefineCursor(fDisplay, gTws->fWindow, fCursors[cursor]);
}
void TGX11::SetDoubleBuffer(int wid, int mode)
{
if (wid == 999) {
for (int i = 0; i < fMaxNumberOfWindows; i++) {
gTws = &fWindows[i];
if (gTws->fOpen) {
switch (mode) {
case 1 :
SetDoubleBufferON();
break;
default:
SetDoubleBufferOFF();
break;
}
}
}
} else {
gTws = &fWindows[wid];
if (!gTws->fOpen) return;
switch (mode) {
case 1 :
SetDoubleBufferON();
return;
default:
SetDoubleBufferOFF();
return;
}
}
}
void TGX11::SetDoubleBufferOFF()
{
if (!gTws->fDoubleBuffer) return;
gTws->fDoubleBuffer = 0;
gTws->fDrawing = gTws->fWindow;
}
void TGX11::SetDoubleBufferON()
{
if (gTws->fDoubleBuffer || gTws->fIsPixmap) return;
if (!gTws->fBuffer) {
gTws->fBuffer = XCreatePixmap(fDisplay, fRootWin,
gTws->fWidth, gTws->fHeight, fDepth);
SetColor(*gGCpxmp, 0);
XFillRectangle(fDisplay, gTws->fBuffer, *gGCpxmp, 0, 0, gTws->fWidth, gTws->fHeight);
SetColor(*gGCpxmp, 1);
}
for (int i = 0; i < kMAXGC; i++) XSetClipMask(fDisplay, gGClist[i], None);
gTws->fDoubleBuffer = 1;
gTws->fDrawing = gTws->fBuffer;
}
void TGX11::SetDrawMode(EDrawMode mode)
{
int i;
switch (mode) {
case kCopy:
for (i = 0; i < kMAXGC; i++) XSetFunction(fDisplay, gGClist[i], GXcopy);
break;
case kXor:
for (i = 0; i < kMAXGC; i++) XSetFunction(fDisplay, gGClist[i], GXxor);
break;
case kInvert:
for (i = 0; i < kMAXGC; i++) XSetFunction(fDisplay, gGClist[i], GXinvert);
break;
}
fDrawMode = mode;
}
void TGX11::SetFillColor(Color_t cindex)
{
if (!gStyle->GetFillColor() && cindex > 1) cindex = 0;
if (cindex >= 0) SetColor(*gGCfill, Int_t(cindex));
fFillColor = cindex;
if (gFillPattern != 0) {
XFreePixmap(fDisplay, gFillPattern);
gFillPattern = 0;
}
}
void TGX11::SetFillStyle(Style_t fstyle)
{
if (fFillStyle == fstyle) return;
fFillStyle = fstyle;
Int_t style = fstyle/1000;
Int_t fasi = fstyle%1000;
SetFillStyleIndex(style,fasi);
}
void TGX11::SetFillStyleIndex(Int_t style, Int_t fasi)
{
static int current_fasi = 0;
fFillStyle = 1000*style + fasi;
switch (style) {
case 1:
gFillHollow = 0;
XSetFillStyle(fDisplay, *gGCfill, FillSolid);
break;
case 2:
gFillHollow = 1;
break;
case 3:
gFillHollow = 0;
XSetFillStyle(fDisplay, *gGCfill, FillStippled);
if (fasi != current_fasi) {
if (gFillPattern != 0) {
XFreePixmap(fDisplay, gFillPattern);
gFillPattern = 0;
}
int stn = (fasi >= 1 && fasi <=25) ? fasi : 2;
gFillPattern = XCreateBitmapFromData(fDisplay, fRootWin,
(const char*)gStipples[stn], 16, 16);
XSetStipple( fDisplay, *gGCfill, gFillPattern );
current_fasi = fasi;
}
break;
default:
gFillHollow = 1;
}
}
void TGX11::SetInput(int inp)
{
XSetWindowAttributes attributes;
ULong_t attr_mask;
if (inp == 1) {
attributes.event_mask = gMouseMask | gKeybdMask;
attr_mask = CWEventMask;
XChangeWindowAttributes(fDisplay, gCws->fWindow, attr_mask, &attributes);
} else {
attributes.event_mask = NoEventMask;
attr_mask = CWEventMask;
XChangeWindowAttributes(fDisplay, gCws->fWindow, attr_mask, &attributes);
}
}
void TGX11::SetLineColor(Color_t cindex)
{
if (cindex < 0) return;
TAttLine::SetLineColor(cindex);
SetColor(*gGCline, Int_t(cindex));
SetColor(*gGCdash, Int_t(cindex));
}
void TGX11::SetLineType(int n, int *dash)
{
if (n <= 0) {
gLineStyle = LineSolid;
XSetLineAttributes(fDisplay, *gGCline, gLineWidth,
gLineStyle, gCapStyle, gJoinStyle);
} else {
gDashSize = TMath::Min((int)sizeof(gDashList),n);
gDashLength = 0;
for (int i = 0; i < gDashSize; i++ ) {
gDashList[i] = dash[i];
gDashLength += gDashList[i];
}
gDashOffset = 0;
gLineStyle = LineOnOffDash;
XSetLineAttributes(fDisplay, *gGCline, gLineWidth,
gLineStyle, gCapStyle, gJoinStyle);
XSetLineAttributes(fDisplay, *gGCdash, gLineWidth,
gLineStyle, gCapStyle, gJoinStyle);
}
}
void TGX11::SetLineStyle(Style_t lstyle)
{
static Int_t dashed[2] = {3,3};
static Int_t dotted[2] = {1,2};
static Int_t dasheddotted[4] = {3,4,1,4};
if (fLineStyle != lstyle) {
fLineStyle = lstyle;
if (lstyle <= 1 ) {
SetLineType(0,0);
} else if (lstyle == 2 ) {
SetLineType(2,dashed);
} else if (lstyle == 3 ) {
SetLineType(2,dotted);
} else if (lstyle == 4 ) {
SetLineType(4,dasheddotted);
} else {
TString st = (TString)gStyle->GetLineStyleString(lstyle);
TObjArray *tokens = st.Tokenize(" ");
Int_t nt;
nt = tokens->GetEntries();
Int_t *linestyle = new Int_t[nt];
for (Int_t j = 0; j<nt; j++) {
Int_t it;
sscanf(((TObjString*)tokens->At(j))->GetName(), "%d", &it);
linestyle[j] = (Int_t)(it/4);
}
SetLineType(nt,linestyle);
delete [] linestyle;
delete tokens;
}
}
}
void TGX11::SetLineWidth(Width_t width )
{
if (fLineWidth == width) return;
if (width == 1) gLineWidth = 0;
else gLineWidth = width;
fLineWidth = gLineWidth;
if (gLineWidth < 0) return;
XSetLineAttributes(fDisplay, *gGCline, gLineWidth,
gLineStyle, gCapStyle, gJoinStyle);
XSetLineAttributes(fDisplay, *gGCdash, gLineWidth,
gLineStyle, gCapStyle, gJoinStyle);
}
void TGX11::SetMarkerColor(Color_t cindex)
{
if (cindex < 0) return;
TAttMarker::SetMarkerColor(cindex);
SetColor(*gGCmark, Int_t(cindex));
}
void TGX11::SetMarkerSize(Float_t msize)
{
if (msize == fMarkerSize) return;
fMarkerSize = msize;
if (msize < 0) return;
SetMarkerStyle(-fMarkerStyle);
}
void TGX11::SetMarkerType(int type, int n, XPoint *xy)
{
gMarker.type = type;
gMarker.n = n < kMAXMK ? n : kMAXMK;
if (gMarker.type >= 2) {
for (int i = 0; i < gMarker.n; i++) {
gMarker.xy[i].x = xy[i].x;
gMarker.xy[i].y = xy[i].y;
}
}
}
void TGX11::SetMarkerStyle(Style_t markerstyle)
{
if (fMarkerStyle == markerstyle) return;
static XPoint shape[15];
if (markerstyle >= 35) return;
markerstyle = TMath::Abs(markerstyle);
fMarkerStyle = markerstyle;
Int_t im = Int_t(4*fMarkerSize + 0.5);
if (markerstyle == 2) {
shape[0].x = -im; shape[0].y = 0;
shape[1].x = im; shape[1].y = 0;
shape[2].x = 0 ; shape[2].y = -im;
shape[3].x = 0 ; shape[3].y = im;
SetMarkerType(4,4,shape);
} else if (markerstyle == 3 || markerstyle == 31) {
shape[0].x = -im; shape[0].y = 0;
shape[1].x = im; shape[1].y = 0;
shape[2].x = 0 ; shape[2].y = -im;
shape[3].x = 0 ; shape[3].y = im;
im = Int_t(0.707*Float_t(im) + 0.5);
shape[4].x = -im; shape[4].y = -im;
shape[5].x = im; shape[5].y = im;
shape[6].x = -im; shape[6].y = im;
shape[7].x = im; shape[7].y = -im;
SetMarkerType(4,8,shape);
} else if (markerstyle == 4 || markerstyle == 24) {
SetMarkerType(0,im*2,shape);
} else if (markerstyle == 5) {
im = Int_t(0.707*Float_t(im) + 0.5);
shape[0].x = -im; shape[0].y = -im;
shape[1].x = im; shape[1].y = im;
shape[2].x = -im; shape[2].y = im;
shape[3].x = im; shape[3].y = -im;
SetMarkerType(4,4,shape);
} else if (markerstyle == 6) {
shape[0].x = -1 ; shape[0].y = 0;
shape[1].x = 1 ; shape[1].y = 0;
shape[2].x = 0 ; shape[2].y = -1;
shape[3].x = 0 ; shape[3].y = 1;
SetMarkerType(4,4,shape);
} else if (markerstyle == 7) {
shape[0].x = -1 ; shape[0].y = 1;
shape[1].x = 1 ; shape[1].y = 1;
shape[2].x = -1 ; shape[2].y = 0;
shape[3].x = 1 ; shape[3].y = 0;
shape[4].x = -1 ; shape[4].y = -1;
shape[5].x = 1 ; shape[5].y = -1;
SetMarkerType(4,6,shape);
} else if (markerstyle == 8 || markerstyle == 20) {
SetMarkerType(1,im*2,shape);
} else if (markerstyle == 21) {
shape[0].x = -im; shape[0].y = -im;
shape[1].x = im; shape[1].y = -im;
shape[2].x = im; shape[2].y = im;
shape[3].x = -im; shape[3].y = im;
shape[4].x = -im; shape[4].y = -im;
SetMarkerType(3,5,shape);
} else if (markerstyle == 22) {
shape[0].x = -im; shape[0].y = im;
shape[1].x = im; shape[1].y = im;
shape[2].x = 0; shape[2].y = -im;
shape[3].x = -im; shape[3].y = im;
SetMarkerType(3,4,shape);
} else if (markerstyle == 23) {
shape[0].x = 0; shape[0].y = im;
shape[1].x = im; shape[1].y = -im;
shape[2].x = -im; shape[2].y = -im;
shape[3].x = 0; shape[3].y = im;
SetMarkerType(3,4,shape);
} else if (markerstyle == 25) {
shape[0].x = -im; shape[0].y = -im;
shape[1].x = im; shape[1].y = -im;
shape[2].x = im; shape[2].y = im;
shape[3].x = -im; shape[3].y = im;
shape[4].x = -im; shape[4].y = -im;
SetMarkerType(2,5,shape);
} else if (markerstyle == 26) {
shape[0].x = -im; shape[0].y = im;
shape[1].x = im; shape[1].y = im;
shape[2].x = 0; shape[2].y = -im;
shape[3].x = -im; shape[3].y = im;
SetMarkerType(2,4,shape);
} else if (markerstyle == 27) {
Int_t imx = Int_t(2.66*fMarkerSize + 0.5);
shape[0].x =-imx; shape[0].y = 0;
shape[1].x = 0; shape[1].y = -im;
shape[2].x = imx; shape[2].y = 0;
shape[3].x = 0; shape[3].y = im;
shape[4].x =-imx; shape[4].y = 0;
SetMarkerType(2,5,shape);
} else if (markerstyle == 28) {
Int_t imx = Int_t(1.33*fMarkerSize + 0.5);
shape[0].x = -im; shape[0].y =-imx;
shape[1].x =-imx; shape[1].y =-imx;
shape[2].x =-imx; shape[2].y = -im;
shape[3].x = imx; shape[3].y = -im;
shape[4].x = imx; shape[4].y =-imx;
shape[5].x = im; shape[5].y =-imx;
shape[6].x = im; shape[6].y = imx;
shape[7].x = imx; shape[7].y = imx;
shape[8].x = imx; shape[8].y = im;
shape[9].x =-imx; shape[9].y = im;
shape[10].x=-imx; shape[10].y= imx;
shape[11].x= -im; shape[11].y= imx;
shape[12].x= -im; shape[12].y=-imx;
SetMarkerType(2,13,shape);
} else if (markerstyle == 29) {
Int_t im1 = Int_t(0.66*fMarkerSize + 0.5);
Int_t im2 = Int_t(2.00*fMarkerSize + 0.5);
Int_t im3 = Int_t(2.66*fMarkerSize + 0.5);
Int_t im4 = Int_t(1.33*fMarkerSize + 0.5);
shape[0].x = -im; shape[0].y = im4;
shape[1].x =-im2; shape[1].y =-im1;
shape[2].x =-im3; shape[2].y = -im;
shape[3].x = 0; shape[3].y =-im2;
shape[4].x = im3; shape[4].y = -im;
shape[5].x = im2; shape[5].y =-im1;
shape[6].x = im; shape[6].y = im4;
shape[7].x = im4; shape[7].y = im4;
shape[8].x = 0; shape[8].y = im;
shape[9].x =-im4; shape[9].y = im4;
shape[10].x= -im; shape[10].y= im4;
SetMarkerType(3,11,shape);
} else if (markerstyle == 30) {
Int_t im1 = Int_t(0.66*fMarkerSize + 0.5);
Int_t im2 = Int_t(2.00*fMarkerSize + 0.5);
Int_t im3 = Int_t(2.66*fMarkerSize + 0.5);
Int_t im4 = Int_t(1.33*fMarkerSize + 0.5);
shape[0].x = -im; shape[0].y = im4;
shape[1].x =-im2; shape[1].y =-im1;
shape[2].x =-im3; shape[2].y = -im;
shape[3].x = 0; shape[3].y =-im2;
shape[4].x = im3; shape[4].y = -im;
shape[5].x = im2; shape[5].y =-im1;
shape[6].x = im; shape[6].y = im4;
shape[7].x = im4; shape[7].y = im4;
shape[8].x = 0; shape[8].y = im;
shape[9].x =-im4; shape[9].y = im4;
shape[10].x= -im; shape[10].y= im4;
SetMarkerType(2,11,shape);
} else if (markerstyle == 32) {
shape[0].x = 0; shape[0].y = im;
shape[1].x = im; shape[1].y = -im;
shape[2].x = -im; shape[2].y = -im;
shape[3].x = 0; shape[3].y = im;
SetMarkerType(2,4,shape);
} else if (markerstyle == 33) {
Int_t imx = Int_t(2.66*fMarkerSize + 0.5);
shape[0].x =-imx; shape[0].y = 0;
shape[1].x = 0; shape[1].y = -im;
shape[2].x = imx; shape[2].y = 0;
shape[3].x = 0; shape[3].y = im;
shape[4].x =-imx; shape[4].y = 0;
SetMarkerType(3,5,shape);
} else if (markerstyle == 34) {
Int_t imx = Int_t(1.33*fMarkerSize + 0.5);
shape[0].x = -im; shape[0].y =-imx;
shape[1].x =-imx; shape[1].y =-imx;
shape[2].x =-imx; shape[2].y = -im;
shape[3].x = imx; shape[3].y = -im;
shape[4].x = imx; shape[4].y =-imx;
shape[5].x = im; shape[5].y =-imx;
shape[6].x = im; shape[6].y = imx;
shape[7].x = imx; shape[7].y = imx;
shape[8].x = imx; shape[8].y = im;
shape[9].x =-imx; shape[9].y = im;
shape[10].x=-imx; shape[10].y= imx;
shape[11].x= -im; shape[11].y= imx;
shape[12].x= -im; shape[12].y=-imx;
SetMarkerType(3,13,shape);
} else {
SetMarkerType(0,0,shape);
}
}
void TGX11::SetOpacity(Int_t percent)
{
if (fDepth <= 8) return;
if (percent == 0) return;
ULong_t *orgcolors = 0, *tmpc = 0;
Int_t maxcolors = 0, ncolors = 0, ntmpc = 0;
if (gCws->fNewColors) {
tmpc = gCws->fNewColors;
ntmpc = gCws->fNcolors;
}
XImage *image = XGetImage(fDisplay, gCws->fDrawing, 0, 0, gCws->fWidth,
gCws->fHeight, AllPlanes, ZPixmap);
if (!image) return;
int x, y;
for (y = 0; y < (int) gCws->fHeight; y++) {
for (x = 0; x < (int) gCws->fWidth; x++) {
ULong_t pixel = XGetPixel(image, x, y);
CollectImageColors(pixel, orgcolors, ncolors, maxcolors);
}
}
if (ncolors == 0) {
XDestroyImage(image);
::operator delete(orgcolors);
return;
}
MakeOpaqueColors(percent, orgcolors, ncolors);
if (gCws->fNewColors) {
for (y = 0; y < (int) gCws->fHeight; y++) {
for (x = 0; x < (int) gCws->fWidth; x++) {
ULong_t pixel = XGetPixel(image, x, y);
Int_t idx = FindColor(pixel, orgcolors, ncolors);
XPutPixel(image, x, y, gCws->fNewColors[idx]);
}
}
}
XPutImage(fDisplay, gCws->fDrawing, *gGCpxmp, image, 0, 0, 0, 0,
gCws->fWidth, gCws->fHeight);
XFlush(fDisplay);
if (tmpc) {
if (fRedDiv == -1)
XFreeColors(fDisplay, fColormap, tmpc, ntmpc, 0);
delete [] tmpc;
}
XDestroyImage(image);
::operator delete(orgcolors);
}
void TGX11::CollectImageColors(ULong_t pixel, ULong_t *&orgcolors, Int_t &ncolors,
Int_t &maxcolors)
{
if (maxcolors == 0) {
ncolors = 0;
maxcolors = 100;
orgcolors = (ULong_t*) ::operator new(maxcolors*sizeof(ULong_t));
}
for (int i = 0; i < ncolors; i++)
if (pixel == orgcolors[i]) return;
if (ncolors >= maxcolors) {
orgcolors = (ULong_t*) TStorage::ReAlloc(orgcolors,
maxcolors*2*sizeof(ULong_t), maxcolors*sizeof(ULong_t));
maxcolors *= 2;
}
orgcolors[ncolors++] = pixel;
}
void TGX11::MakeOpaqueColors(Int_t percent, ULong_t *orgcolors, Int_t ncolors)
{
if (ncolors == 0) return;
XColor *xcol = new XColor[ncolors];
int i;
for (i = 0; i < ncolors; i++) {
xcol[i].pixel = orgcolors[i];
xcol[i].red = xcol[i].green = xcol[i].blue = 0;
xcol[i].flags = DoRed | DoGreen | DoBlue;
}
QueryColors(fColormap, xcol, ncolors);
UShort_t add = percent * kBIGGEST_RGB_VALUE / 100;
Int_t val;
for (i = 0; i < ncolors; i++) {
val = xcol[i].red + add;
if (val > kBIGGEST_RGB_VALUE) val = kBIGGEST_RGB_VALUE;
xcol[i].red = (UShort_t) val;
val = xcol[i].green + add;
if (val > kBIGGEST_RGB_VALUE) val = kBIGGEST_RGB_VALUE;
xcol[i].green = (UShort_t) val;
val = xcol[i].blue + add;
if (val > kBIGGEST_RGB_VALUE) val = kBIGGEST_RGB_VALUE;
xcol[i].blue = (UShort_t) val;
if (!AllocColor(fColormap, &xcol[i]))
Warning("MakeOpaqueColors", "failed to allocate color %hd, %hd, %hd",
xcol[i].red, xcol[i].green, xcol[i].blue);
}
gCws->fNewColors = new ULong_t[ncolors];
gCws->fNcolors = ncolors;
for (i = 0; i < ncolors; i++)
gCws->fNewColors[i] = xcol[i].pixel;
delete [] xcol;
}
Int_t TGX11::FindColor(ULong_t pixel, ULong_t *orgcolors, Int_t ncolors)
{
for (int i = 0; i < ncolors; i++)
if (pixel == orgcolors[i]) return i;
Error("FindColor", "did not find color, should never happen!");
return 0;
}
void TGX11::SetRGB(int cindex, float r, float g, float b)
{
if (fColormap) {
XColor xcol;
xcol.red = (UShort_t)(r * kBIGGEST_RGB_VALUE);
xcol.green = (UShort_t)(g * kBIGGEST_RGB_VALUE);
xcol.blue = (UShort_t)(b * kBIGGEST_RGB_VALUE);
xcol.flags = DoRed | DoGreen | DoBlue;
XColor_t &col = GetColor(cindex);
if (col.fDefined) {
if (col.fRed == xcol.red && col.fGreen == xcol.green &&
col.fBlue == xcol.blue)
return;
col.fDefined = kFALSE;
if (fRedDiv == -1)
XFreeColors(fDisplay, fColormap, &col.fPixel, 1, 0);
}
if (AllocColor(fColormap, &xcol)) {
col.fDefined = kTRUE;
col.fPixel = xcol.pixel;
col.fRed = xcol.red;
col.fGreen = xcol.green;
col.fBlue = xcol.blue;
}
}
}
void TGX11::SetTextAlign(Short_t talign)
{
Int_t txalh = talign/10;
Int_t txalv = talign%10;
fTextAlignH = txalh;
fTextAlignV = txalv;
switch (txalh) {
case 0 :
case 1 :
switch (txalv) {
case 1 :
fTextAlign = 7;
break;
case 2 :
fTextAlign = 4;
break;
case 3 :
fTextAlign = 1;
break;
}
break;
case 2 :
switch (txalv) {
case 1 :
fTextAlign = 8;
break;
case 2 :
fTextAlign = 5;
break;
case 3 :
fTextAlign = 2;
break;
}
break;
case 3 :
switch (txalv) {
case 1 :
fTextAlign = 9;
break;
case 2 :
fTextAlign = 6;
break;
case 3 :
fTextAlign = 3;
break;
}
break;
}
TAttText::SetTextAlign(fTextAlign);
}
void TGX11::SetTextColor(Color_t cindex)
{
if (cindex < 0) return;
TAttText::SetTextColor(cindex);
SetColor(*gGCtext, Int_t(cindex));
XGCValues values;
if (XGetGCValues(fDisplay, *gGCtext, GCForeground | GCBackground, &values)) {
XSetForeground( fDisplay, *gGCinvt, values.background );
XSetBackground( fDisplay, *gGCinvt, values.foreground );
} else {
Error("SetTextColor", "cannot get GC values");
}
XSetBackground(fDisplay, *gGCtext, GetColor(0).fPixel);
}
Int_t TGX11::SetTextFont(char *fontname, ETextSetMode mode)
{
char **fontlist;
int fontcount;
int i;
if (mode == kLoad) {
for (i = 0; i < kMAXFONT; i++) {
if (strcmp(fontname, gFont[i].name) == 0) {
gTextFont = gFont[i].id;
XSetFont(fDisplay, *gGCtext, gTextFont->fid);
XSetFont(fDisplay, *gGCinvt, gTextFont->fid);
return 0;
}
}
}
fontlist = XListFonts(fDisplay, fontname, 1, &fontcount);
if (fontlist && fontcount != 0) {
if (mode == kLoad) {
if (gFont[gCurrentFontNumber].id)
XFreeFont(fDisplay, gFont[gCurrentFontNumber].id);
gTextFont = XLoadQueryFont(fDisplay, fontlist[0]);
XSetFont(fDisplay, *gGCtext, gTextFont->fid);
XSetFont(fDisplay, *gGCinvt, gTextFont->fid);
gFont[gCurrentFontNumber].id = gTextFont;
strlcpy(gFont[gCurrentFontNumber].name,fontname,80);
gCurrentFontNumber++;
if (gCurrentFontNumber == kMAXFONT) gCurrentFontNumber = 0;
}
XFreeFontNames(fontlist);
return 0;
} else {
return 1;
}
}
void TGX11::SetTextFont(Font_t fontnumber)
{
fTextFont = fontnumber;
}
void TGX11::SetTextSize(Float_t textsize)
{
fTextSize = textsize;
}
void TGX11::Sync(int mode)
{
switch (mode) {
case 1 :
XSynchronize(fDisplay,1);
break;
default:
XSynchronize(fDisplay,0);
break;
}
}
void TGX11::UpdateWindow(int mode)
{
if (gCws->fDoubleBuffer) {
XCopyArea(fDisplay, gCws->fDrawing, gCws->fWindow,
*gGCpxmp, 0, 0, gCws->fWidth, gCws->fHeight, 0, 0);
}
if (mode == 1) {
XFlush(fDisplay);
} else {
XSync(fDisplay, False);
}
}
void TGX11::Warp(Int_t ix, Int_t iy, Window_t id)
{
if (!id) {
} else {
XWarpPointer(fDisplay, None, (Window) id, 0, 0, 0, 0, ix, iy);
}
}
void TGX11::WritePixmap(int wid, unsigned int w, unsigned int h, char *pxname)
{
unsigned int wval, hval;
wval = w;
hval = h;
gTws = &fWindows[wid];
XWriteBitmapFile(fDisplay, pxname, gTws->fDrawing, wval, hval, -1, -1);
}
static FILE *gOut;
static XImage *gXimage = 0;
extern "C" {
int GIFquantize(UInt_t width, UInt_t height, Int_t *ncol, Byte_t *red, Byte_t *green,
Byte_t *blue, Byte_t *outputBuf, Byte_t *outputCmap);
long GIFencode(int Width, int Height, Int_t Ncol, Byte_t R[], Byte_t G[], Byte_t B[], Byte_t ScLine[],
void (*get_scline) (int, int, Byte_t *), void (*pb)(Byte_t));
int GIFdecode(Byte_t *gifArr, Byte_t *pixArr, int *Width, int *Height, int *Ncols, Byte_t *R, Byte_t *G, Byte_t *B);
int GIFinfo(Byte_t *gifArr, int *Width, int *Height, int *Ncols);
}
static void GetPixel(int y, int width, Byte_t *scline)
{
for (int i = 0; i < width; i++)
scline[i] = Byte_t(XGetPixel(gXimage, i, y));
}
static void PutByte(Byte_t b)
{
if (ferror(gOut) == 0) fputc(b, gOut);
}
void TGX11::ImgPickPalette(XImage *image, Int_t &ncol, Int_t *&R, Int_t *&G, Int_t *&B)
{
ULong_t *orgcolors = 0;
Int_t maxcolors = 0, ncolors = 0;
int x, y;
for (x = 0; x < (int) gCws->fWidth; x++) {
for (y = 0; y < (int) gCws->fHeight; y++) {
ULong_t pixel = XGetPixel(image, x, y);
CollectImageColors(pixel, orgcolors, ncolors, maxcolors);
}
}
XColor *xcol = new XColor[ncolors];
int i;
for (i = 0; i < ncolors; i++) {
xcol[i].pixel = orgcolors[i];
xcol[i].red = xcol[i].green = xcol[i].blue = 0;
xcol[i].flags = DoRed | DoGreen | DoBlue;
}
QueryColors(fColormap, xcol, ncolors);
R = new Int_t[ncolors];
G = new Int_t[ncolors];
B = new Int_t[ncolors];
for (i = 0; i < ncolors; i++) {
R[i] = xcol[i].red;
G[i] = xcol[i].green;
B[i] = xcol[i].blue;
}
ncol = ncolors;
for (x = 0; x < (int) gCws->fWidth; x++) {
for (y = 0; y < (int) gCws->fHeight; y++) {
ULong_t pixel = XGetPixel(image, x, y);
Int_t idx = FindColor(pixel, orgcolors, ncolors);
XPutPixel(image, x, y, idx);
}
}
delete [] xcol;
::operator delete(orgcolors);
}
Int_t TGX11::WriteGIF(char *name)
{
Byte_t scline[2000], r[256], b[256], g[256];
Int_t *red, *green, *blue;
Int_t ncol, maxcol, i;
if (gXimage) {
XDestroyImage(gXimage);
gXimage = 0;
}
gXimage = XGetImage(fDisplay, gCws->fDrawing, 0, 0,
gCws->fWidth, gCws->fHeight,
AllPlanes, ZPixmap);
ImgPickPalette(gXimage, ncol, red, green, blue);
if (ncol > 256) {
Error("WriteGIF", "can not create GIF of image containing more than 256 colors");
delete [] red;
delete [] green;
delete [] blue;
return 0;
}
maxcol = 0;
for (i = 0; i < ncol; i++) {
if (maxcol < red[i] ) maxcol = red[i];
if (maxcol < green[i] ) maxcol = green[i];
if (maxcol < blue[i] ) maxcol = blue[i];
r[i] = 0;
g[i] = 0;
b[i] = 0;
}
if (maxcol != 0) {
for (i = 0; i < ncol; i++) {
r[i] = red[i] * 255/maxcol;
g[i] = green[i] * 255/maxcol;
b[i] = blue[i] * 255/maxcol;
}
}
gOut = fopen(name, "w+");
if (gOut) {
GIFencode(gCws->fWidth, gCws->fHeight,
ncol, r, g, b, scline, ::GetPixel, PutByte);
fclose(gOut);
i = 1;
} else {
Error("WriteGIF","cannot write file: %s",name);
i = 0;
}
delete [] red;
delete [] green;
delete [] blue;
return i;
}
void TGX11::PutImage(int offset,int itran,int x0,int y0,int nx,int ny,int xmin,
int ymin,int xmax,int ymax, unsigned char *image,Drawable_t wid)
{
const int maxSegment = 20;
int i, n, x, y, xcur, x1, x2, y1, y2;
unsigned char *jimg, *jbase, icol;
int nlines[256];
XSegment lines[256][maxSegment];
Drawable_t id;
if (wid) {
id = wid;
} else {
id = gCws->fDrawing;
}
for (i = 0; i < 256; i++) nlines[i] = 0;
x1 = x0 + xmin; y1 = y0 + ny - ymax - 1;
x2 = x0 + xmax; y2 = y0 + ny - ymin - 1;
jbase = image + (ymin-1)*nx + xmin;
for (y = y2; y >= y1; y--) {
xcur = x1; jbase += nx;
for (jimg = jbase, icol = *jimg++, x = x1+1; x <= x2; jimg++, x++) {
if (icol != *jimg) {
if (icol != itran) {
n = nlines[icol]++;
lines[icol][n].x1 = xcur; lines[icol][n].y1 = y;
lines[icol][n].x2 = x-1; lines[icol][n].y2 = y;
if (nlines[icol] == maxSegment) {
SetColor(*gGCline,(int)icol+offset);
XDrawSegments(fDisplay,id,*gGCline,&lines[icol][0],
maxSegment);
nlines[icol] = 0;
}
}
icol = *jimg; xcur = x;
}
}
if (icol != itran) {
n = nlines[icol]++;
lines[icol][n].x1 = xcur; lines[icol][n].y1 = y;
lines[icol][n].x2 = x-1; lines[icol][n].y2 = y;
if (nlines[icol] == maxSegment) {
SetColor(*gGCline,(int)icol+offset);
XDrawSegments(fDisplay,id,*gGCline,&lines[icol][0],
maxSegment);
nlines[icol] = 0;
}
}
}
for (i = 0; i < 256; i++) {
if (nlines[i] != 0) {
SetColor(*gGCline,i+offset);
XDrawSegments(fDisplay,id,*gGCline,&lines[i][0],nlines[i]);
}
}
}
Pixmap_t TGX11::ReadGIF(int x0, int y0, const char *file, Window_t id)
{
FILE *fd;
Seek_t filesize = 0;
unsigned char *gifArr, *pixArr, red[256], green[256], blue[256], *j1, *j2, icol;
int i, j, k, width, height, ncolor, irep, offset;
float rr, gg, bb;
Pixmap_t pic = 0;
fd = fopen(file, "r");
if (!fd) {
Error("ReadGIF", "unable to open GIF file");
return pic;
}
fseek(fd, 0L, 2);
long ft = ftell(fd);
if (ft <=0) {
Error("ReadGIF", "unable to open GIF file");
fclose(fd);
return pic;
} else {
filesize = Seek_t(ft);
}
fseek(fd, 0L, 0);
if (!(gifArr = (unsigned char *) calloc(filesize+256,1))) {
Error("ReadGIF", "unable to allocate array for gif");
fclose(fd);
return pic;
}
if (fread(gifArr, filesize, 1, fd) != 1) {
Error("ReadGIF", "GIF file read failed");
free(gifArr);
fclose(fd);
return pic;
}
fclose(fd);
irep = GIFinfo(gifArr, &width, &height, &ncolor);
if (irep != 0) {
free(gifArr);
return pic;
}
if (!(pixArr = (unsigned char *) calloc((width*height),1))) {
Error("ReadGIF", "unable to allocate array for image");
free(gifArr);
return pic;
}
irep = GIFdecode(gifArr, pixArr, &width, &height, &ncolor, red, green, blue);
if (irep != 0) {
free(gifArr);
free(pixArr);
return pic;
}
offset = 8;
for (i = 0; i < ncolor; i++) {
rr = red[i]/255.;
gg = green[i]/255.;
bb = blue[i]/255.;
j = i+offset;
SetRGB(j,rr,gg,bb);
}
for (i = 1; i <= height/2; i++) {
j1 = pixArr + (i-1)*width;
j2 = pixArr + (height-i)*width;
for (k = 0; k < width; k++) {
icol = *j1; *j1++ = *j2; *j2++ = icol;
}
}
if (id) pic = CreatePixmap(id, width, height);
PutImage(offset,-1,x0,y0,width,height,0,0,width-1,height-1,pixArr,pic);
free(gifArr);
free(pixArr);
if (pic)
return pic;
else if (gCws->fDrawing)
return (Pixmap_t)gCws->fDrawing;
return 0;
}
unsigned char *TGX11::GetColorBits(Drawable_t , Int_t , Int_t ,
UInt_t , UInt_t )
{
return 0;
}
Pixmap_t TGX11::CreatePixmapFromData(unsigned char * , UInt_t ,
UInt_t )
{
return (Pixmap_t)0;
}
Int_t TGX11::AddPixmap(ULong_t pixid, UInt_t w, UInt_t h)
{
Int_t wid = 0;
for (; wid < fMaxNumberOfWindows; ++wid)
if (!fWindows[wid].fOpen)
break;
if (wid == fMaxNumberOfWindows) {
Int_t newsize = fMaxNumberOfWindows + 10;
fWindows = (XWindow_t*) TStorage::ReAlloc(
fWindows, newsize * sizeof(XWindow_t),
fMaxNumberOfWindows*sizeof(XWindow_t)
);
for (Int_t i = fMaxNumberOfWindows; i < newsize; ++i)
fWindows[i].fOpen = 0;
fMaxNumberOfWindows = newsize;
}
fWindows[wid].fOpen = 1;
gCws = fWindows + wid;
gCws->fWindow = pixid;
gCws->fDrawing = gCws->fWindow;
gCws->fBuffer = 0;
gCws->fDoubleBuffer = 0;
gCws->fIsPixmap = 1;
gCws->fClip = 0;
gCws->fWidth = w;
gCws->fHeight = h;
gCws->fNewColors = 0;
gCws->fShared = kFALSE;
return wid;
}
Int_t TGX11::SupportsExtension(const char *ext) const
{
Int_t major_opcode, first_event, first_error;
if (!fDisplay)
return -1;
return XQueryExtension(fDisplay, ext, &major_opcode, &first_event, &first_error);
}