TGX11.cxx

Go to the documentation of this file.
00001 // @(#)root/x11:$Id: TGX11.cxx 36156 2010-10-07 14:08:57Z rdm $
00002 // Author: Rene Brun, Olivier Couet, Fons Rademakers   28/11/94
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 //////////////////////////////////////////////////////////////////////////
00013 //                                                                      //
00014 // TGX11                                                                //
00015 //                                                                      //
00016 // This class is the basic interface to the X11 graphics system. It is  //
00017 // an implementation of the abstract TVirtualX class. The companion     //
00018 // class for Win32 is TGWin32.                                          //
00019 //                                                                      //
00020 // This code was initially developed in the context of HIGZ and PAW     //
00021 // by Olivier Couet (package X11INT).                                   //
00022 //                                                                      //
00023 //////////////////////////////////////////////////////////////////////////
00024 #include "TROOT.h"
00025 #include "TColor.h"
00026 #include "TGX11.h"
00027 #include "TPoint.h"
00028 #include "TMath.h"
00029 #include "TStorage.h"
00030 #include "TStyle.h"
00031 #include "TExMap.h"
00032 #include "TEnv.h"
00033 #include "TString.h"
00034 #include "TObjString.h"
00035 #include "TObjArray.h"
00036 #include "RStipples.h"
00037 
00038 #include <stdio.h>
00039 #include <string.h>
00040 #include <stdlib.h>
00041 #include <ctype.h>
00042 #include <unistd.h>
00043 #ifdef R__AIX
00044 #   include <sys/socket.h>
00045 #endif
00046 
00047 extern float   XRotVersion(char*, int);
00048 extern void    XRotSetMagnification(float);
00049 extern void    XRotSetBoundingBoxPad(int);
00050 extern int     XRotDrawString(Display*, XFontStruct*, float,
00051                               Drawable, GC, int, int, char*);
00052 extern int     XRotDrawImageString(Display*, XFontStruct*, float,
00053                                    Drawable, GC, int, int, char*);
00054 extern int     XRotDrawAlignedString(Display*, XFontStruct*, float,
00055                                      Drawable, GC, int, int, char*, int);
00056 extern int     XRotDrawAlignedImageString(Display*, XFontStruct*, float,
00057                                           Drawable, GC, int, int, char*, int);
00058 extern XPoint *XRotTextExtents(Display*, XFontStruct*, float,
00059                                int, int, char*, int);
00060 
00061 //---- globals
00062 
00063 static XWindow_t *gCws;      // gCws: pointer to the current window
00064 static XWindow_t *gTws;      // gTws: temporary pointer
00065 
00066 const Int_t kBIGGEST_RGB_VALUE = 65535;
00067 
00068 //
00069 // Primitives Graphic Contexts global for all windows
00070 //
00071 const int kMAXGC = 7;
00072 static GC gGClist[kMAXGC];
00073 static GC *gGCline = &gGClist[0];  // PolyLines
00074 static GC *gGCmark = &gGClist[1];  // PolyMarker
00075 static GC *gGCfill = &gGClist[2];  // Fill areas
00076 static GC *gGCtext = &gGClist[3];  // Text
00077 static GC *gGCinvt = &gGClist[4];  // Inverse text
00078 static GC *gGCdash = &gGClist[5];  // Dashed lines
00079 static GC *gGCpxmp = &gGClist[6];  // Pixmap management
00080 
00081 static GC gGCecho;                 // Input echo
00082 
00083 static Int_t  gFillHollow;         // Flag if fill style is hollow
00084 static Pixmap gFillPattern = 0;    // Fill pattern
00085 
00086 //
00087 // Text management
00088 //
00089 const Int_t kMAXFONT = 4;
00090 static struct {
00091    XFontStruct *id;
00092    char         name[80];                    // Font name
00093 } gFont[kMAXFONT];                          // List of fonts loaded
00094 
00095 static XFontStruct *gTextFont;              // Current font
00096 static Int_t        gCurrentFontNumber = 0; // Current font number in gFont[]
00097 
00098 //
00099 // Markers
00100 //
00101 const Int_t kMAXMK = 100;
00102 static struct {
00103    int    type;
00104    int    n;
00105    XPoint xy[kMAXMK];
00106 } gMarker;                        // Point list to draw marker
00107 
00108 //
00109 // Keep style values for line GC
00110 //
00111 static int  gLineWidth = 0;
00112 static int  gLineStyle = LineSolid;
00113 static int  gCapStyle  = CapButt;
00114 static int  gJoinStyle = JoinMiter;
00115 static char gDashList[10];
00116 static int  gDashLength = 0;
00117 static int  gDashOffset = 0;
00118 static int  gDashSize   = 0;
00119 
00120 //
00121 // Event masks
00122 //
00123 static ULong_t gMouseMask =   ButtonPressMask   | ButtonReleaseMask |
00124                               EnterWindowMask   | LeaveWindowMask   |
00125                               PointerMotionMask | KeyPressMask      |
00126                               KeyReleaseMask;
00127 static ULong_t gKeybdMask =   ButtonPressMask | KeyPressMask |
00128                               EnterWindowMask | LeaveWindowMask;
00129 
00130 //
00131 // Data to create an invisible cursor
00132 //
00133 const char null_cursor_bits[] = {
00134 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00135 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00136 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
00137 static Cursor gNullCursor = 0;
00138 
00139 
00140 ClassImp(TGX11)
00141 
00142 //______________________________________________________________________________
00143 TGX11::TGX11()
00144 {
00145    // Default constructor.
00146 
00147    int i;
00148    fDisplay            = 0;
00149    fScreenNumber       = 0;
00150    fVisual             = 0;
00151    fRootWin            = 0;
00152    fVisRootWin         = 0;
00153    fColormap           = 0;
00154    fBlackPixel         = 0;
00155    fWhitePixel         = 0;
00156    fWindows            = 0;
00157    fColors             = 0;
00158    fXEvent             = new XEvent;
00159    fRedDiv             = -1;
00160    fGreenDiv           = -1;
00161    fBlueDiv            = -1;
00162    fRedShift           = -1;
00163    fGreenShift         = -1;
00164    fBlueShift          = -1;
00165    fCharacterUpX       = 1;
00166    fCharacterUpY       = 1;
00167    fDepth              = 0;
00168    fHasTTFonts         = kFALSE;
00169    fMaxNumberOfWindows = 10;
00170    fTextAlignH         = 1;
00171    fTextAlignV         = 1;
00172    fTextAlign          = 7;
00173    fTextMagnitude      = 1;
00174    for (i = 0; i < kNumCursors; i++) fCursors[i] = 0;
00175 }
00176 
00177 //______________________________________________________________________________
00178 TGX11::TGX11(const char *name, const char *title) : TVirtualX(name, title)
00179 {
00180    // Normal Constructor.
00181 
00182    int i;
00183    fDisplay            = 0;
00184    fScreenNumber       = 0;
00185    fVisual             = 0;
00186    fRootWin            = 0;
00187    fVisRootWin         = 0;
00188    fColormap           = 0;
00189    fBlackPixel         = 0;
00190    fWhitePixel         = 0;
00191    fDrawMode           = kCopy;
00192    fXEvent             = new XEvent;
00193    fRedDiv             = -1;
00194    fGreenDiv           = -1;
00195    fBlueDiv            = -1;
00196    fRedShift           = -1;
00197    fGreenShift         = -1;
00198    fBlueShift          = -1;
00199    fCharacterUpX       = 1;
00200    fCharacterUpY       = 1;
00201    fDepth              = 0;
00202    fHasTTFonts         = kFALSE;
00203    fMaxNumberOfWindows = 10;
00204    fTextAlignH         = 1;
00205    fTextAlignV         = 1;
00206    fTextAlign          = 7;
00207    fTextMagnitude      = 1;
00208    for (i = 0; i < kNumCursors; i++) fCursors[i] = 0;
00209 
00210    //fWindows = new XWindow_t[fMaxNumberOfWindows];
00211    fWindows = (XWindow_t*) TStorage::Alloc(fMaxNumberOfWindows*sizeof(XWindow_t));
00212    for (i = 0; i < fMaxNumberOfWindows; i++)
00213       fWindows[i].fOpen = 0;
00214 
00215    fColors = new TExMap;
00216 }
00217 
00218 //______________________________________________________________________________
00219 TGX11::TGX11(const TGX11 &org) : TVirtualX(org)
00220 {
00221    // Copy constructor. Currently only used by TGX11TTF.
00222 
00223    int i;
00224 
00225    fDisplay         = org.fDisplay;
00226    fScreenNumber    = org.fScreenNumber;
00227    fVisual          = org.fVisual;
00228    fRootWin         = org.fRootWin;
00229    fVisRootWin      = org.fVisRootWin;
00230    fColormap        = org.fColormap;
00231    fBlackPixel      = org.fBlackPixel;
00232    fWhitePixel      = org.fWhitePixel;
00233    fHasTTFonts      = org.fHasTTFonts;
00234    fTextAlignH      = org.fTextAlignH;
00235    fTextAlignV      = org.fTextAlignV;
00236    fTextAlign       = org.fTextAlign;
00237    fTextMagnitude   = org.fTextMagnitude;
00238    fCharacterUpX    = org.fCharacterUpX;
00239    fCharacterUpY    = org.fCharacterUpY;
00240    fDepth           = org.fDepth;
00241    fRedDiv          = org.fRedDiv;
00242    fGreenDiv        = org.fGreenDiv;
00243    fBlueDiv         = org.fBlueDiv;
00244    fRedShift        = org.fRedShift;
00245    fGreenShift      = org.fGreenShift;
00246    fBlueShift       = org.fBlueShift;
00247    fDrawMode        = org.fDrawMode;
00248    fXEvent          = new XEvent;
00249 
00250    fMaxNumberOfWindows = org.fMaxNumberOfWindows;
00251    //fWindows = new XWindow_t[fMaxNumberOfWindows];
00252    fWindows = (XWindow_t*) TStorage::Alloc(fMaxNumberOfWindows*sizeof(XWindow_t));
00253    for (i = 0; i < fMaxNumberOfWindows; i++) {
00254       fWindows[i].fOpen         = org.fWindows[i].fOpen;
00255       fWindows[i].fDoubleBuffer = org.fWindows[i].fDoubleBuffer;
00256       fWindows[i].fIsPixmap     = org.fWindows[i].fIsPixmap;
00257       fWindows[i].fDrawing      = org.fWindows[i].fDrawing;
00258       fWindows[i].fWindow       = org.fWindows[i].fWindow;
00259       fWindows[i].fBuffer       = org.fWindows[i].fBuffer;
00260       fWindows[i].fWidth        = org.fWindows[i].fWidth;
00261       fWindows[i].fHeight       = org.fWindows[i].fHeight;
00262       fWindows[i].fClip         = org.fWindows[i].fClip;
00263       fWindows[i].fXclip        = org.fWindows[i].fXclip;
00264       fWindows[i].fYclip        = org.fWindows[i].fYclip;
00265       fWindows[i].fWclip        = org.fWindows[i].fWclip;
00266       fWindows[i].fHclip        = org.fWindows[i].fHclip;
00267       fWindows[i].fNewColors    = org.fWindows[i].fNewColors;
00268       fWindows[i].fNcolors      = org.fWindows[i].fNcolors;
00269       fWindows[i].fShared       = org.fWindows[i].fShared;
00270    }
00271 
00272    for (i = 0; i < kNumCursors; i++)
00273       fCursors[i] = org.fCursors[i];
00274 
00275    fColors = new TExMap;
00276    Long64_t key, value;
00277    TExMapIter it(org.fColors);
00278    while (it.Next(key, value)) {
00279       XColor_t *colo = (XColor_t *) (Long_t)value;
00280       XColor_t *col  = new XColor_t;
00281       col->fPixel   = colo->fPixel;
00282       col->fRed     = colo->fRed;
00283       col->fGreen   = colo->fGreen;
00284       col->fBlue    = colo->fBlue;
00285       col->fDefined = colo->fDefined;
00286       fColors->Add(key, (Long_t) col);
00287    }
00288 }
00289 
00290 //______________________________________________________________________________
00291 TGX11::~TGX11()
00292 {
00293    // Destructor.
00294 
00295    delete fXEvent;
00296    if (fWindows) TStorage::Dealloc(fWindows);
00297 
00298    if (!fColors) return;
00299    Long64_t key, value;
00300    TExMapIter it(fColors);
00301    while (it.Next(key, value)) {
00302       XColor_t *col = (XColor_t *) (Long_t)value;
00303       delete col;
00304    }
00305    delete fColors;
00306 }
00307 
00308 //______________________________________________________________________________
00309 Bool_t TGX11::Init(void *display)
00310 {
00311    // Initialize X11 system. Returns kFALSE in case of failure.
00312 
00313    if (OpenDisplay((Display *) display) == -1) return kFALSE;
00314    return kTRUE;
00315 }
00316 
00317 //______________________________________________________________________________
00318 Bool_t TGX11::AllocColor(Colormap cmap, XColor *color)
00319 {
00320    // Allocate color in colormap. If we are on an <= 8 plane machine
00321    // we will use XAllocColor. If we are on a >= 15 (15, 16 or 24) plane
00322    // true color machine we will calculate the pixel value using:
00323    // for 15 and 16 bit true colors have 6 bits precision per color however
00324    // only the 5 most significant bits are used in the color index.
00325    // Except for 16 bits where green uses all 6 bits. I.e.:
00326    //   15 bits = rrrrrgggggbbbbb
00327    //   16 bits = rrrrrggggggbbbbb
00328    // for 24 bits each r, g and b are represented by 8 bits.
00329    //
00330    // Since all colors are set with a max of 65535 (16 bits) per r, g, b
00331    // we just right shift them by 10, 11 and 10 bits for 16 planes, and
00332    // (10, 10, 10 for 15 planes) and by 8 bits for 24 planes.
00333    // Returns kFALSE in case color allocation failed.
00334 
00335    if (fRedDiv == -1) {
00336       if (XAllocColor(fDisplay, cmap, color))
00337          return kTRUE;
00338    } else {
00339       color->pixel = (color->red   >> fRedDiv)   << fRedShift |
00340                      (color->green >> fGreenDiv) << fGreenShift |
00341                      (color->blue  >> fBlueDiv)  << fBlueShift;
00342       return kTRUE;
00343    }
00344    return kFALSE;
00345 }
00346 
00347 //______________________________________________________________________________
00348 void TGX11::QueryColors(Colormap cmap, XColor *color, Int_t ncolors)
00349 {
00350    // Returns the current RGB value for the pixel in the XColor structure.
00351 
00352    if (fRedDiv == -1) {
00353       XQueryColors(fDisplay, cmap, color, ncolors);
00354    } else {
00355       ULong_t r, g, b;
00356       for (Int_t i = 0; i < ncolors; i++) {
00357          r = (color[i].pixel & fVisual->red_mask) >> fRedShift;
00358          color[i].red = UShort_t(r*kBIGGEST_RGB_VALUE/(fVisual->red_mask >> fRedShift));
00359 
00360          g = (color[i].pixel & fVisual->green_mask) >> fGreenShift;
00361          color[i].green = UShort_t(g*kBIGGEST_RGB_VALUE/(fVisual->green_mask >> fGreenShift));
00362 
00363          b = (color[i].pixel & fVisual->blue_mask) >> fBlueShift;
00364          color[i].blue = UShort_t(b*kBIGGEST_RGB_VALUE/(fVisual->blue_mask >> fBlueShift));
00365 
00366          color[i].flags = DoRed | DoGreen | DoBlue;
00367       }
00368    }
00369 }
00370 
00371 //______________________________________________________________________________
00372 void TGX11::ClearPixmap(Drawable *pix)
00373 {
00374    // Clear the pixmap pix.
00375 
00376    Window root;
00377    int xx, yy;
00378    unsigned int ww, hh, border, depth;
00379    XGetGeometry(fDisplay, *pix, &root, &xx, &yy, &ww, &hh, &border, &depth);
00380    SetColor(*gGCpxmp, 0);
00381    XFillRectangle(fDisplay, *pix, *gGCpxmp, 0 ,0 ,ww ,hh);
00382    SetColor(*gGCpxmp, 1);
00383    XFlush(fDisplay);
00384 }
00385 
00386 //______________________________________________________________________________
00387 void TGX11::ClearWindow()
00388 {
00389    // Clear current window.
00390 
00391    if (!gCws->fIsPixmap && !gCws->fDoubleBuffer) {
00392       XSetWindowBackground(fDisplay, gCws->fDrawing, GetColor(0).fPixel);
00393       XClearWindow(fDisplay, gCws->fDrawing);
00394       XFlush(fDisplay);
00395    } else {
00396       SetColor(*gGCpxmp, 0);
00397       XFillRectangle(fDisplay, gCws->fDrawing, *gGCpxmp,
00398                      0, 0, gCws->fWidth, gCws->fHeight);
00399       SetColor(*gGCpxmp, 1);
00400    }
00401 }
00402 
00403 //______________________________________________________________________________
00404 void TGX11::ClosePixmap()
00405 {
00406    // Delete current pixmap.
00407 
00408    CloseWindow1();
00409 }
00410 
00411 //______________________________________________________________________________
00412 void TGX11::CloseWindow()
00413 {
00414    // Delete current window.
00415 
00416    if (gCws->fShared)
00417       gCws->fOpen = 0;
00418    else
00419       CloseWindow1();
00420 
00421    // Never close connection. TApplication takes care of that
00422    //   if (!gCws) Close();    // close X when no open window left
00423 }
00424 
00425 //______________________________________________________________________________
00426 void TGX11::CloseWindow1()
00427 {
00428    // Delete current window.
00429 
00430    int wid;
00431 
00432    if (gCws->fIsPixmap)
00433       XFreePixmap(fDisplay, gCws->fWindow);
00434    else
00435       XDestroyWindow(fDisplay, gCws->fWindow);
00436 
00437    if (gCws->fBuffer) XFreePixmap(fDisplay, gCws->fBuffer);
00438 
00439    if (gCws->fNewColors) {
00440       if (fRedDiv == -1)
00441          XFreeColors(fDisplay, fColormap, gCws->fNewColors, gCws->fNcolors, 0);
00442       delete [] gCws->fNewColors;
00443       gCws->fNewColors = 0;
00444    }
00445 
00446    XFlush(fDisplay);
00447 
00448    gCws->fOpen = 0;
00449 
00450    // make first window in list the current window
00451    for (wid = 0; wid < fMaxNumberOfWindows; wid++)
00452       if (fWindows[wid].fOpen) {
00453          gCws = &fWindows[wid];
00454          return;
00455       }
00456 
00457    gCws = 0;
00458 }
00459 
00460 //______________________________________________________________________________
00461 void TGX11::CopyPixmap(int wid, int xpos, int ypos)
00462 {
00463    // Copy the pixmap wid at the position xpos, ypos in the current window.
00464 
00465    gTws = &fWindows[wid];
00466 
00467    XCopyArea(fDisplay, gTws->fDrawing, gCws->fDrawing, *gGCpxmp, 0, 0, gTws->fWidth,
00468              gTws->fHeight, xpos, ypos);
00469    XFlush(fDisplay);
00470 }
00471 
00472 //______________________________________________________________________________
00473 void TGX11::CopyWindowtoPixmap(Drawable *pix, int xpos, int ypos )
00474 {
00475    // Copy area of current window in the pixmap pix.
00476 
00477    Window root;
00478    int xx, yy;
00479    unsigned int ww, hh, border, depth;
00480 
00481    XGetGeometry(fDisplay, *pix, &root, &xx, &yy, &ww, &hh, &border, &depth);
00482    XCopyArea(fDisplay, gCws->fDrawing, *pix, *gGCpxmp, xpos, ypos, ww, hh, 0, 0);
00483    XFlush(fDisplay);
00484 }
00485 
00486 //______________________________________________________________________________
00487 void TGX11::DrawBox(int x1, int y1, int x2, int y2, EBoxMode mode)
00488 {
00489    // Draw a box.
00490    // mode=0 hollow  (kHollow)
00491    // mode=1 solid   (kSolid)
00492 
00493    Int_t x = TMath::Min(x1, x2);
00494    Int_t y = TMath::Min(y1, y2);
00495    Int_t w = TMath::Abs(x2 - x1);
00496    Int_t h = TMath::Abs(y2 - y1);
00497 
00498    switch (mode) {
00499 
00500       case kHollow:
00501          XDrawRectangle(fDisplay, gCws->fDrawing, *gGCline, x, y, w, h);
00502          break;
00503 
00504       case kFilled:
00505          XFillRectangle(fDisplay, gCws->fDrawing, *gGCfill, x, y, w, h);
00506          break;
00507 
00508       default:
00509          break;
00510    }
00511 }
00512 
00513 //______________________________________________________________________________
00514 void TGX11::DrawCellArray(int x1, int y1, int x2, int y2, int nx, int ny, int *ic)
00515 {
00516    // Draw a cell array.
00517    // x1,y1        : left down corner
00518    // x2,y2        : right up corner
00519    // nx,ny        : array size
00520    // ic           : array
00521    //
00522    // Draw a cell array. The drawing is done with the pixel presicion
00523    // if (X2-X1)/NX (or Y) is not a exact pixel number the position of
00524    // the top rigth corner may be wrong.
00525 
00526    int i, j, icol, ix, iy, w, h, current_icol;
00527 
00528    current_icol = -1;
00529    w            = TMath::Max((x2-x1)/(nx),1);
00530    h            = TMath::Max((y1-y2)/(ny),1);
00531    ix           = x1;
00532 
00533    for (i = 0; i < nx; i++) {
00534       iy = y1-h;
00535       for (j = 0; j < ny; j++) {
00536          icol = ic[i+(nx*j)];
00537          if (icol != current_icol) {
00538             XSetForeground(fDisplay, *gGCfill, GetColor(icol).fPixel);
00539             current_icol = icol;
00540          }
00541          XFillRectangle(fDisplay, gCws->fDrawing, *gGCfill, ix, iy, w, h);
00542          iy = iy-h;
00543       }
00544       ix = ix+w;
00545    }
00546 }
00547 
00548 //______________________________________________________________________________
00549 void TGX11::DrawFillArea(int n, TPoint *xyt)
00550 {
00551    // Fill area described by polygon.
00552    // n         : number of points
00553    // xy(2,n)   : list of points
00554 
00555    XPoint *xy = (XPoint*)xyt;
00556 
00557    if (gFillHollow)
00558       XDrawLines(fDisplay, gCws->fDrawing, *gGCfill, xy, n, CoordModeOrigin);
00559 
00560    else {
00561       XFillPolygon(fDisplay, gCws->fDrawing, *gGCfill,
00562                    xy, n, Nonconvex, CoordModeOrigin);
00563    }
00564 }
00565 
00566 //______________________________________________________________________________
00567 void TGX11::DrawLine(int x1, int y1, int x2, int y2)
00568 {
00569    // Draw a line.
00570    // x1,y1        : begin of line
00571    // x2,y2        : end of line
00572 
00573    if (gLineStyle == LineSolid)
00574       XDrawLine(fDisplay, gCws->fDrawing, *gGCline, x1, y1, x2, y2);
00575    else {
00576       XSetDashes(fDisplay, *gGCdash, gDashOffset, gDashList, gDashSize);
00577       XDrawLine(fDisplay, gCws->fDrawing, *gGCdash, x1, y1, x2, y2);
00578    }
00579 }
00580 
00581 //______________________________________________________________________________
00582 void TGX11::DrawPolyLine(int n, TPoint *xyt)
00583 {
00584    // Draw a line through all points.
00585    // n         : number of points
00586    // xy        : list of points
00587 
00588    XPoint *xy = (XPoint*)xyt;
00589 
00590    const Int_t kMaxPoints = 1000001;
00591 
00592    if (n > kMaxPoints) {
00593       int ibeg = 0;
00594       int iend = kMaxPoints - 1;
00595       while (iend < n) {
00596          DrawPolyLine( kMaxPoints, &xyt[ibeg] );
00597          ibeg = iend;
00598          iend += kMaxPoints - 1;
00599       }
00600       if (ibeg < n) {
00601          int npt = n - ibeg;
00602          DrawPolyLine( npt, &xyt[ibeg] );
00603       }
00604    } else if (n > 1) {
00605       if (gLineStyle == LineSolid)
00606          XDrawLines(fDisplay, gCws->fDrawing, *gGCline, xy, n, CoordModeOrigin);
00607       else {
00608          int i;
00609          XSetDashes(fDisplay, *gGCdash,
00610                     gDashOffset, gDashList, gDashSize);
00611          XDrawLines(fDisplay, gCws->fDrawing, *gGCdash, xy, n, CoordModeOrigin);
00612 
00613          // calculate length of line to update dash offset
00614          for (i = 1; i < n; i++) {
00615             int dx = xy[i].x - xy[i-1].x;
00616             int dy = xy[i].y - xy[i-1].y;
00617             if (dx < 0) dx = - dx;
00618             if (dy < 0) dy = - dy;
00619             gDashOffset += dx > dy ? dx : dy;
00620          }
00621          gDashOffset %= gDashLength;
00622       }
00623    } else {
00624       int px,py;
00625       px=xy[0].x;
00626       py=xy[0].y;
00627       XDrawPoint(fDisplay, gCws->fDrawing,
00628                  gLineStyle == LineSolid ? *gGCline : *gGCdash, px, py);
00629    }
00630 }
00631 
00632 //______________________________________________________________________________
00633 void TGX11::DrawPolyMarker(int n, TPoint *xyt)
00634 {
00635    // Draw n markers with the current attributes at position x, y.
00636    // n    : number of markers to draw
00637    // xy   : x,y coordinates of markers
00638 
00639    XPoint *xy = (XPoint*)xyt;
00640 
00641    if (gMarker.n <= 0) {
00642       const int kNMAX = 1000000;
00643       int nt = n/kNMAX;
00644       for (int it=0;it<=nt;it++) {
00645          if (it < nt) {
00646             XDrawPoints(fDisplay, gCws->fDrawing, *gGCmark, &xy[it*kNMAX], kNMAX, CoordModeOrigin);
00647          } else {
00648             XDrawPoints(fDisplay, gCws->fDrawing, *gGCmark, &xy[it*kNMAX], n-it*kNMAX, CoordModeOrigin);
00649          }
00650       }
00651    } else {
00652       int r = gMarker.n / 2;
00653       int m;
00654 
00655       for (m = 0; m < n; m++) {
00656          int hollow = 0;
00657 
00658          switch (gMarker.type) {
00659             int i;
00660 
00661             case 0:        // hollow circle
00662                XDrawArc(fDisplay, gCws->fDrawing, *gGCmark,
00663                         xy[m].x - r, xy[m].y - r, gMarker.n, gMarker.n, 0, 360*64);
00664                break;
00665 
00666             case 1:        // filled circle
00667                XFillArc(fDisplay, gCws->fDrawing, *gGCmark,
00668                         xy[m].x - r, xy[m].y - r, gMarker.n, gMarker.n, 0, 360*64);
00669                break;
00670 
00671             case 2:        // hollow polygon
00672                hollow = 1;
00673             case 3:        // filled polygon
00674                for (i = 0; i < gMarker.n; i++) {
00675                   gMarker.xy[i].x += xy[m].x;
00676                   gMarker.xy[i].y += xy[m].y;
00677                }
00678                if (hollow)
00679                   XDrawLines(fDisplay, gCws->fDrawing, *gGCmark,
00680                              gMarker.xy, gMarker.n, CoordModeOrigin);
00681                else
00682                   XFillPolygon(fDisplay, gCws->fDrawing, *gGCmark,
00683                                gMarker.xy, gMarker.n, Nonconvex, CoordModeOrigin);
00684                for (i = 0; i < gMarker.n; i++) {
00685                   gMarker.xy[i].x -= xy[m].x;
00686                   gMarker.xy[i].y -= xy[m].y;
00687                }
00688                break;
00689 
00690             case 4:        // segmented line
00691                for (i = 0; i < gMarker.n; i += 2)
00692                   XDrawLine(fDisplay, gCws->fDrawing, *gGCmark,
00693                             xy[m].x + gMarker.xy[i].x, xy[m].y + gMarker.xy[i].y,
00694                             xy[m].x + gMarker.xy[i+1].x, xy[m].y + gMarker.xy[i+1].y);
00695                break;
00696          }
00697       }
00698    }
00699 }
00700 
00701 //______________________________________________________________________________
00702 void TGX11::DrawText(int x, int y, float angle, float mgn,
00703                      const char *text, ETextMode mode)
00704 {
00705    // Draw a text string using current font.
00706    // mode       : drawing mode
00707    // mode=0     : the background is not drawn (kClear)
00708    // mode=1     : the background is drawn (kOpaque)
00709    // x,y        : text position
00710    // angle      : text angle
00711    // mgn        : magnification factor
00712    // text       : text string
00713 
00714    XRotSetMagnification(mgn);
00715 
00716    if (!text) return;
00717 
00718    switch (mode) {
00719 
00720       case kClear:
00721          XRotDrawAlignedString(fDisplay, gTextFont, angle,
00722                       gCws->fDrawing, *gGCtext, x, y, (char*)text, fTextAlign);
00723          break;
00724 
00725       case kOpaque:
00726          XRotDrawAlignedImageString(fDisplay, gTextFont, angle,
00727                       gCws->fDrawing, *gGCtext, x, y, (char*)text, fTextAlign);
00728          break;
00729 
00730       default:
00731          break;
00732    }
00733 }
00734 
00735 //______________________________________________________________________________
00736 void TGX11::FindBestVisual()
00737 {
00738    // Find best visual, i.e. the one with the most planes and TrueColor or
00739    // DirectColor. Sets fVisual, fDepth, fRootWin, fColormap, fBlackPixel
00740    // and fWhitePixel.
00741 
00742    Int_t findvis = gEnv->GetValue("X11.FindBestVisual", 1);
00743 
00744    Visual *vis = DefaultVisual(fDisplay, fScreenNumber);
00745    if (((vis->c_class != TrueColor && vis->c_class != DirectColor) ||
00746        DefaultDepth(fDisplay, fScreenNumber) < 15) && findvis) {
00747 
00748       // try to find better visual
00749       static XVisualInfo templates[] = {
00750          // Visual, visualid, screen, depth, class      , red_mask, green_mask, blue_mask, colormap_size, bits_per_rgb
00751          { 0     , 0       , 0     , 24   , TrueColor  , 0       , 0         , 0        , 0            , 0 },
00752          { 0     , 0       , 0     , 32   , TrueColor  , 0       , 0         , 0        , 0            , 0 },
00753          { 0     , 0       , 0     , 16   , TrueColor  , 0       , 0         , 0        , 0            , 0 },
00754          { 0     , 0       , 0     , 15   , TrueColor  , 0       , 0         , 0        , 0            , 0 },
00755          // no suitable TrueColorMode found - now do the same thing to DirectColor
00756          { 0     , 0       , 0     , 24   , DirectColor, 0       , 0         , 0        , 0            , 0 },
00757          { 0     , 0       , 0     , 32   , DirectColor, 0       , 0         , 0        , 0            , 0 },
00758          { 0     , 0       , 0     , 16   , DirectColor, 0       , 0         , 0        , 0            , 0 },
00759          { 0     , 0       , 0     , 15   , DirectColor, 0       , 0         , 0        , 0            , 0 },
00760          { 0     , 0       , 0     , 0    , 0          , 0       , 0         , 0        , 0            , 0 },
00761       };
00762 
00763       Int_t nitems = 0;
00764       XVisualInfo *vlist = 0;
00765       for (Int_t i = 0; templates[i].depth != 0; i++) {
00766          Int_t mask = VisualScreenMask|VisualDepthMask|VisualClassMask;
00767          templates[i].screen = fScreenNumber;
00768          if ((vlist = XGetVisualInfo(fDisplay, mask, &(templates[i]), &nitems))) {
00769             FindUsableVisual(vlist, nitems);
00770             XFree(vlist);
00771             vlist = 0;
00772             if (fVisual)
00773                break;
00774          }
00775       }
00776    }
00777 
00778    fRootWin = RootWindow(fDisplay, fScreenNumber);
00779 
00780    if (!fVisual) {
00781       fDepth      = DefaultDepth(fDisplay, fScreenNumber);
00782       fVisual     = DefaultVisual(fDisplay, fScreenNumber);
00783       fVisRootWin = fRootWin;
00784       if (fDepth > 1)
00785          fColormap = DefaultColormap(fDisplay, fScreenNumber);
00786       fBlackPixel = BlackPixel(fDisplay, fScreenNumber);
00787       fWhitePixel = WhitePixel(fDisplay, fScreenNumber);
00788    }
00789    if (gDebug > 1)
00790       Printf("Selected visual 0x%lx: depth %d, class %d, colormap: %s",
00791              fVisual->visualid, fDepth, fVisual->c_class,
00792              fColormap == DefaultColormap(fDisplay, fScreenNumber) ? "default" :
00793              "custom");
00794 }
00795 
00796 //______________________________________________________________________________
00797 static Int_t DummyX11ErrorHandler(Display *, XErrorEvent *)
00798 {
00799    // Dummy error handler for X11. Used by FindUsableVisual().
00800 
00801    return 0;
00802 }
00803 
00804 //______________________________________________________________________________
00805 void TGX11::FindUsableVisual(XVisualInfo *vlist, Int_t nitems)
00806 {
00807    // Check if visual is usable, if so set fVisual, fDepth, fColormap,
00808    // fBlackPixel and fWhitePixel.
00809 
00810    Int_t (*oldErrorHandler)(Display *, XErrorEvent *) =
00811        XSetErrorHandler(DummyX11ErrorHandler);
00812 
00813    XSetWindowAttributes attr;
00814    memset(&attr, 0, sizeof(attr));
00815 
00816    Window root = RootWindow(fDisplay, fScreenNumber);
00817 
00818    for (Int_t i = 0; i < nitems; i++) {
00819       Window w = None, wjunk;
00820       UInt_t width, height, ujunk;
00821       Int_t  junk;
00822 
00823       // try and use default colormap when possible
00824       if (vlist[i].visual == DefaultVisual(fDisplay, fScreenNumber)) {
00825          attr.colormap = DefaultColormap(fDisplay, fScreenNumber);
00826       } else {
00827          attr.colormap = XCreateColormap(fDisplay, root, vlist[i].visual, AllocNone);
00828       }
00829 
00830       static XColor black_xcol = { 0, 0x0000, 0x0000, 0x0000, DoRed|DoGreen|DoBlue, 0 };
00831       static XColor white_xcol = { 0, 0xFFFF, 0xFFFF, 0xFFFF, DoRed|DoGreen|DoBlue, 0 };
00832       XAllocColor(fDisplay, attr.colormap, &black_xcol);
00833       XAllocColor(fDisplay, attr.colormap, &white_xcol);
00834       attr.border_pixel = black_xcol.pixel;
00835       attr.override_redirect = True;
00836 
00837       w = XCreateWindow(fDisplay, root, -20, -20, 10, 10, 0, vlist[i].depth,
00838                         CopyFromParent, vlist[i].visual,
00839                         CWColormap|CWBorderPixel|CWOverrideRedirect, &attr);
00840       if (w != None && XGetGeometry(fDisplay, w, &wjunk, &junk, &junk,
00841                                     &width, &height, &ujunk, &ujunk)) {
00842          fVisual     = vlist[i].visual;
00843          fDepth      = vlist[i].depth;
00844          fColormap   = attr.colormap;
00845          fBlackPixel = black_xcol.pixel;
00846          fWhitePixel = white_xcol.pixel;
00847          fVisRootWin = w;
00848          break;
00849       }
00850       if (attr.colormap != DefaultColormap(fDisplay, fScreenNumber))
00851          XFreeColormap(fDisplay, attr.colormap);
00852    }
00853    XSetErrorHandler(oldErrorHandler);
00854 }
00855 
00856 //______________________________________________________________________________
00857 void TGX11::GetCharacterUp(Float_t &chupx, Float_t &chupy)
00858 {
00859    // Return character up vector.
00860 
00861    chupx = fCharacterUpX;
00862    chupy = fCharacterUpY;
00863 }
00864 
00865 //______________________________________________________________________________
00866 XColor_t &TGX11::GetColor(Int_t cid)
00867 {
00868    // Return reference to internal color structure associated
00869    // to color index cid.
00870 
00871    XColor_t *col = (XColor_t*) (Long_t)fColors->GetValue(cid);
00872    if (!col) {
00873       col = new XColor_t;
00874       fColors->Add(cid, (Long_t) col);
00875    }
00876    return *col;
00877 }
00878 
00879 //______________________________________________________________________________
00880 Window_t TGX11::GetCurrentWindow() const
00881 {
00882    // Return current window pointer. Protected method used by TGX11TTF.
00883 
00884    return (Window_t)(gCws ? gCws->fDrawing : 0);
00885 }
00886 
00887 //______________________________________________________________________________
00888 GC *TGX11::GetGC(Int_t which) const
00889 {
00890    // Return desired Graphics Context ("which" maps directly on gGCList[]).
00891    // Protected method used by TGX11TTF.
00892 
00893    if (which >= kMAXGC || which < 0) {
00894       Error("GetGC", "trying to get illegal GC (which = %d)", which);
00895       return 0;
00896    }
00897    return &gGClist[which];
00898 }
00899 
00900 //______________________________________________________________________________
00901 Int_t TGX11::GetDoubleBuffer(int wid)
00902 {
00903    // Query the double buffer value for the window wid.
00904 
00905    gTws = &fWindows[wid];
00906    if (!gTws->fOpen)
00907       return -1;
00908    else
00909       return gTws->fDoubleBuffer;
00910 }
00911 
00912 //______________________________________________________________________________
00913 void TGX11::GetGeometry(int wid, int &x, int &y, unsigned int &w, unsigned int &h)
00914 {
00915    // Return position and size of window wid.
00916    // wid        : window identifier
00917    // x,y        : window position (output)
00918    // w,h        : window size (output)
00919    // if wid < 0 the size of the display is returned
00920 
00921    Window junkwin=0;
00922 
00923    if (wid < 0) {
00924       x = 0;
00925       y = 0;
00926       w = DisplayWidth(fDisplay,fScreenNumber);
00927       h = DisplayHeight(fDisplay,fScreenNumber);
00928    } else {
00929       Window root;
00930       unsigned int border, depth;
00931       unsigned int width, height;
00932 
00933       gTws = &fWindows[wid];
00934       XGetGeometry(fDisplay, gTws->fWindow, &root, &x, &y,
00935                    &width, &height, &border, &depth);
00936       XTranslateCoordinates(fDisplay, gTws->fWindow, fRootWin,
00937                             0, 0, &x, &y, &junkwin);
00938       if (width >= 65535)
00939          width = 1;
00940       if (height >= 65535)
00941          height = 1;
00942       if (width > 0 && height > 0) {
00943          gTws->fWidth  = width;
00944          gTws->fHeight = height;
00945       }
00946       w = gTws->fWidth;
00947       h = gTws->fHeight;
00948    }
00949 }
00950 
00951 //______________________________________________________________________________
00952 const char *TGX11::DisplayName(const char *dpyName)
00953 {
00954    // Return hostname on which the display is opened.
00955 
00956    return XDisplayName(dpyName);
00957 }
00958 
00959 //______________________________________________________________________________
00960 ULong_t TGX11::GetPixel(Color_t ci)
00961 {
00962    // Return pixel value associated to specified ROOT color number.
00963 
00964    TColor *color = gROOT->GetColor(ci);
00965    if (color)
00966       SetRGB(ci, color->GetRed(), color->GetGreen(), color->GetBlue());
00967 //   else
00968 //      Warning("GetPixel", "color with index %d not defined", ci);
00969 
00970    XColor_t &col = GetColor(ci);
00971    return col.fPixel;
00972 }
00973 
00974 //______________________________________________________________________________
00975 void TGX11::GetPlanes(int &nplanes)
00976 {
00977    // Get maximum number of planes.
00978 
00979    nplanes = fDepth;
00980 }
00981 
00982 //______________________________________________________________________________
00983 void TGX11::GetRGB(int index, float &r, float &g, float &b)
00984 {
00985    // Get rgb values for color "index".
00986 
00987    if (index == 0) {
00988       r = g = b = 1.0;
00989    } else if (index == 1) {
00990       r = g = b = 0.0;
00991    } else {
00992       XColor_t &col = GetColor(index);
00993       r = ((float) col.fRed) / ((float) kBIGGEST_RGB_VALUE);
00994       g = ((float) col.fGreen) / ((float) kBIGGEST_RGB_VALUE);
00995       b = ((float) col.fBlue) / ((float) kBIGGEST_RGB_VALUE);
00996    }
00997 }
00998 
00999 //______________________________________________________________________________
01000 void TGX11::GetTextExtent(unsigned int &w, unsigned int &h, char *mess)
01001 {
01002    // Return the size of a character string.
01003    // iw          : text width
01004    // ih          : text height
01005    // mess        : message
01006 
01007    w=0; h=0;
01008    if (strlen(mess)==0) return;
01009 
01010    XPoint *cBox;
01011    XRotSetMagnification(fTextMagnitude);
01012    cBox = XRotTextExtents(fDisplay, gTextFont, 0., 0, 0, mess, 0);
01013    w    = cBox[2].x;
01014    h    = -cBox[2].y;
01015    free((char *)cBox);
01016 }
01017 
01018 //______________________________________________________________________________
01019 Window_t TGX11::GetWindowID(int wid)
01020 {
01021    // Return the X11 window identifier.
01022    // wid      : Workstation identifier (input)
01023 
01024    return (Window_t) fWindows[wid].fWindow;
01025 }
01026 
01027 //______________________________________________________________________________
01028 void TGX11::MoveWindow(int wid, int x, int y)
01029 {
01030    // Move the window wid.
01031    // wid  : Window identifier.
01032    // x    : x new window position
01033    // y    : y new window position
01034 
01035    gTws = &fWindows[wid];
01036    if (!gTws->fOpen) return;
01037 
01038    XMoveWindow(fDisplay, gTws->fWindow, x, y);
01039 }
01040 
01041 //______________________________________________________________________________
01042 Int_t TGX11::OpenDisplay(Display *disp)
01043 {
01044    // Open the display. Return -1 if the opening fails, 0 when ok.
01045 
01046    Pixmap  pixmp1, pixmp2;
01047    XColor  fore, back;
01048    char  **fontlist;
01049    int     fontcount = 0;
01050    int     i;
01051 
01052    if (fDisplay) return 0;
01053 
01054    fDisplay      = disp;
01055    fScreenNumber = DefaultScreen(fDisplay);
01056 
01057    FindBestVisual();
01058 
01059    GetColor(1).fDefined = kTRUE; // default foreground
01060    GetColor(1).fPixel = fBlackPixel;
01061    GetColor(0).fDefined = kTRUE; // default background
01062    GetColor(0).fPixel = fWhitePixel;
01063 
01064    // Inquire the the XServer Vendor
01065    char vendor[132];
01066    strlcpy(vendor, XServerVendor(fDisplay),132);
01067 
01068    // Create primitives graphic contexts
01069    for (i = 0; i < kMAXGC; i++)
01070       gGClist[i] = XCreateGC(fDisplay, fVisRootWin, 0, 0);
01071 
01072    XGCValues values;
01073    if (XGetGCValues(fDisplay, *gGCtext, GCForeground|GCBackground, &values)) {
01074       XSetForeground(fDisplay, *gGCinvt, values.background);
01075       XSetBackground(fDisplay, *gGCinvt, values.foreground);
01076    } else {
01077       Error("OpenDisplay", "cannot get GC values");
01078    }
01079 
01080    // Turn-off GraphicsExpose and NoExpose event reporting for the pixmap
01081    // manipulation GC, this to prevent these events from being stacked up
01082    // without ever being processed and thereby wasting a lot of memory.
01083    XSetGraphicsExposures(fDisplay, *gGCpxmp, False);
01084 
01085    // Create input echo graphic context
01086    XGCValues echov;
01087    echov.foreground = fBlackPixel;
01088    echov.background = fWhitePixel;
01089    if (strstr(vendor,"Hewlett"))
01090       echov.function   = GXxor;
01091    else
01092       echov.function   = GXinvert;
01093 
01094    gGCecho = XCreateGC(fDisplay, fVisRootWin,
01095                        GCForeground | GCBackground | GCFunction,
01096                        &echov);
01097 
01098    // Load a default Font
01099    static int isdisp = 0;
01100    if (!isdisp) {
01101       for (i = 0; i < kMAXFONT; i++) {
01102          gFont[i].id = 0;
01103          strcpy(gFont[i].name, " ");
01104       }
01105       fontlist = XListFonts(fDisplay, "*courier*", 1, &fontcount);
01106       if (fontcount != 0) {
01107          gFont[gCurrentFontNumber].id = XLoadQueryFont(fDisplay, fontlist[0]);
01108          gTextFont = gFont[gCurrentFontNumber].id;
01109          strcpy(gFont[gCurrentFontNumber].name, "*courier*");
01110          gCurrentFontNumber++;
01111          XFreeFontNames(fontlist);
01112       } else {
01113          // emergency: try fixed font
01114          fontlist = XListFonts(fDisplay, "fixed", 1, &fontcount);
01115          if (fontcount != 0) {
01116             gFont[gCurrentFontNumber].id = XLoadQueryFont(fDisplay, fontlist[0]);
01117             gTextFont = gFont[gCurrentFontNumber].id;
01118             strcpy(gFont[gCurrentFontNumber].name, "fixed");
01119             gCurrentFontNumber++;
01120             XFreeFontNames(fontlist);
01121          } else {
01122             Warning("OpenDisplay", "no default font loaded");
01123          }
01124       }
01125       isdisp = 1;
01126    }
01127 
01128    // Create a null cursor
01129    pixmp1 = XCreateBitmapFromData(fDisplay, fRootWin,
01130                                   null_cursor_bits, 16, 16);
01131    pixmp2 = XCreateBitmapFromData(fDisplay, fRootWin,
01132                                   null_cursor_bits, 16, 16);
01133    gNullCursor = XCreatePixmapCursor(fDisplay,pixmp1,pixmp2,&fore,&back,0,0);
01134 
01135    // Create cursors
01136    fCursors[kBottomLeft]  = XCreateFontCursor(fDisplay, XC_bottom_left_corner);
01137    fCursors[kBottomRight] = XCreateFontCursor(fDisplay, XC_bottom_right_corner);
01138    fCursors[kTopLeft]     = XCreateFontCursor(fDisplay, XC_top_left_corner);
01139    fCursors[kTopRight]    = XCreateFontCursor(fDisplay, XC_top_right_corner);
01140    fCursors[kBottomSide]  = XCreateFontCursor(fDisplay, XC_bottom_side);
01141    fCursors[kLeftSide]    = XCreateFontCursor(fDisplay, XC_left_side);
01142    fCursors[kTopSide]     = XCreateFontCursor(fDisplay, XC_top_side);
01143    fCursors[kRightSide]   = XCreateFontCursor(fDisplay, XC_right_side);
01144    fCursors[kMove]        = XCreateFontCursor(fDisplay, XC_fleur);
01145    fCursors[kCross]       = XCreateFontCursor(fDisplay, XC_tcross);
01146    fCursors[kArrowHor]    = XCreateFontCursor(fDisplay, XC_sb_h_double_arrow);
01147    fCursors[kArrowVer]    = XCreateFontCursor(fDisplay, XC_sb_v_double_arrow);
01148    fCursors[kHand]        = XCreateFontCursor(fDisplay, XC_hand2);
01149    fCursors[kRotate]      = XCreateFontCursor(fDisplay, XC_exchange);
01150    fCursors[kPointer]     = XCreateFontCursor(fDisplay, XC_left_ptr);
01151    fCursors[kArrowRight]  = XCreateFontCursor(fDisplay, XC_arrow);
01152    fCursors[kCaret]       = XCreateFontCursor(fDisplay, XC_xterm);
01153    fCursors[kWatch]       = XCreateFontCursor(fDisplay, XC_watch);
01154    fCursors[kNoDrop]      = XCreateFontCursor(fDisplay, XC_pirate);
01155 
01156    // Setup color information
01157    fRedDiv = fGreenDiv = fBlueDiv = fRedShift = fGreenShift = fBlueShift = -1;
01158 
01159    if (fVisual->c_class == TrueColor) {
01160       for (i = 0; i < int(sizeof(fVisual->blue_mask)*kBitsPerByte); i++) {
01161          if (fBlueShift == -1 && ((fVisual->blue_mask >> i) & 1))
01162             fBlueShift = i;
01163          if ((fVisual->blue_mask >> i) == 1) {
01164             fBlueDiv = sizeof(UShort_t)*kBitsPerByte - i - 1 + fBlueShift;
01165             break;
01166          }
01167       }
01168       for (i = 0; i < int(sizeof(fVisual->green_mask)*kBitsPerByte); i++) {
01169          if (fGreenShift == -1 && ((fVisual->green_mask >> i) & 1))
01170             fGreenShift = i;
01171          if ((fVisual->green_mask >> i) == 1) {
01172             fGreenDiv = sizeof(UShort_t)*kBitsPerByte - i - 1 + fGreenShift;
01173             break;
01174          }
01175       }
01176       for (i = 0; i < int(sizeof(fVisual->red_mask)*kBitsPerByte); i++) {
01177          if (fRedShift == -1 && ((fVisual->red_mask >> i) & 1))
01178             fRedShift = i;
01179          if ((fVisual->red_mask >> i) == 1) {
01180             fRedDiv = sizeof(UShort_t)*kBitsPerByte - i - 1 + fRedShift;
01181             break;
01182          }
01183       }
01184       //printf("fRedDiv = %d, fGreenDiv = %d, fBlueDiv = %d, fRedShift = %d, fGreenShift = %d, fBlueShift = %d\n",
01185       //       fRedDiv, fGreenDiv, fBlueDiv, fRedShift, fGreenShift, fBlueShift);
01186    }
01187 
01188    return 0;
01189 }
01190 
01191 //______________________________________________________________________________
01192 Int_t TGX11::OpenPixmap(unsigned int w, unsigned int h)
01193 {
01194    // Open a new pixmap.
01195    // w,h : Width and height of the pixmap.
01196 
01197    Window root;
01198    unsigned int wval, hval;
01199    int xx, yy, i, wid;
01200    unsigned int ww, hh, border, depth;
01201    wval = w;
01202    hval = h;
01203 
01204    // Select next free window number
01205 
01206 again:
01207    for (wid = 0; wid < fMaxNumberOfWindows; wid++)
01208       if (!fWindows[wid].fOpen) {
01209          fWindows[wid].fOpen = 1;
01210          gCws = &fWindows[wid];
01211          break;
01212       }
01213 
01214    if (wid == fMaxNumberOfWindows) {
01215       int newsize = fMaxNumberOfWindows + 10;
01216       fWindows = (XWindow_t*) TStorage::ReAlloc(fWindows, newsize*sizeof(XWindow_t),
01217                                                 fMaxNumberOfWindows*sizeof(XWindow_t));
01218       for (i = fMaxNumberOfWindows; i < newsize; i++)
01219          fWindows[i].fOpen = 0;
01220       fMaxNumberOfWindows = newsize;
01221       goto again;
01222    }
01223 
01224    gCws->fWindow = XCreatePixmap(fDisplay, fRootWin, wval, hval, fDepth);
01225    XGetGeometry(fDisplay, gCws->fWindow, &root, &xx, &yy, &ww, &hh, &border, &depth);
01226 
01227    for (i = 0; i < kMAXGC; i++)
01228       XSetClipMask(fDisplay, gGClist[i], None);
01229 
01230    SetColor(*gGCpxmp, 0);
01231    XFillRectangle(fDisplay, gCws->fWindow, *gGCpxmp, 0, 0, ww, hh);
01232    SetColor(*gGCpxmp, 1);
01233 
01234    // Initialise the window structure
01235    gCws->fDrawing       = gCws->fWindow;
01236    gCws->fBuffer        = 0;
01237    gCws->fDoubleBuffer  = 0;
01238    gCws->fIsPixmap      = 1;
01239    gCws->fClip          = 0;
01240    gCws->fWidth         = wval;
01241    gCws->fHeight        = hval;
01242    gCws->fNewColors     = 0;
01243    gCws->fShared        = kFALSE;
01244 
01245    return wid;
01246 }
01247 
01248 //______________________________________________________________________________
01249 Int_t TGX11::InitWindow(ULong_t win)
01250 {
01251    // Open window and return window number.
01252    // Return -1 if window initialization fails.
01253 
01254    XSetWindowAttributes attributes;
01255    ULong_t attr_mask = 0;
01256    int wid;
01257    int xval, yval;
01258    unsigned int wval, hval, border, depth;
01259    Window root;
01260 
01261    Window wind = (Window) win;
01262 
01263    XGetGeometry(fDisplay, wind, &root, &xval, &yval, &wval, &hval, &border, &depth);
01264 
01265    // Select next free window number
01266 
01267 again:
01268    for (wid = 0; wid < fMaxNumberOfWindows; wid++)
01269       if (!fWindows[wid].fOpen) {
01270          fWindows[wid].fOpen = 1;
01271          fWindows[wid].fDoubleBuffer = 0;
01272          gCws = &fWindows[wid];
01273          break;
01274       }
01275 
01276    if (wid == fMaxNumberOfWindows) {
01277       int newsize = fMaxNumberOfWindows + 10;
01278       fWindows = (XWindow_t*) TStorage::ReAlloc(fWindows, newsize*sizeof(XWindow_t),
01279                                                 fMaxNumberOfWindows*sizeof(XWindow_t));
01280       for (int i = fMaxNumberOfWindows; i < newsize; i++)
01281          fWindows[i].fOpen = 0;
01282       fMaxNumberOfWindows = newsize;
01283       goto again;
01284    }
01285 
01286    // Create window
01287 
01288    attributes.background_pixel = GetColor(0).fPixel;
01289    attr_mask |= CWBackPixel;
01290    attributes.border_pixel = GetColor(1).fPixel;
01291    attr_mask |= CWBorderPixel;
01292    attributes.event_mask = NoEventMask;
01293    attr_mask |= CWEventMask;
01294    attributes.backing_store = Always;
01295    attr_mask |= CWBackingStore;
01296    attributes.bit_gravity = NorthWestGravity;
01297    attr_mask |= CWBitGravity;
01298    if (fColormap) {
01299       attributes.colormap = fColormap;
01300       attr_mask |= CWColormap;
01301    }
01302 
01303    gCws->fWindow = XCreateWindow(fDisplay, wind,
01304                                  xval, yval, wval, hval, 0, fDepth,
01305                                  InputOutput, fVisual,
01306                                  attr_mask, &attributes);
01307 
01308    XMapWindow(fDisplay, gCws->fWindow);
01309    XFlush(fDisplay);
01310 
01311    // Initialise the window structure
01312 
01313    gCws->fDrawing      = gCws->fWindow;
01314    gCws->fBuffer       = 0;
01315    gCws->fDoubleBuffer = 0;
01316    gCws->fIsPixmap     = 0;
01317    gCws->fClip         = 0;
01318    gCws->fWidth        = wval;
01319    gCws->fHeight       = hval;
01320    gCws->fNewColors    = 0;
01321    gCws->fShared       = kFALSE;
01322 
01323    return wid;
01324 }
01325 
01326 //______________________________________________________________________________
01327 Int_t TGX11::AddWindow(ULong_t qwid, UInt_t w, UInt_t h)
01328 {
01329    // Register a window created by Qt as a ROOT window (like InitWindow()).
01330 
01331    Int_t wid;
01332 
01333    // Select next free window number
01334 
01335 again:
01336    for (wid = 0; wid < fMaxNumberOfWindows; wid++)
01337       if (!fWindows[wid].fOpen) {
01338          fWindows[wid].fOpen = 1;
01339          fWindows[wid].fDoubleBuffer = 0;
01340          gCws = &fWindows[wid];
01341          break;
01342       }
01343 
01344    if (wid == fMaxNumberOfWindows) {
01345       int newsize = fMaxNumberOfWindows + 10;
01346       fWindows = (XWindow_t*) TStorage::ReAlloc(fWindows, newsize*sizeof(XWindow_t),
01347                                                 fMaxNumberOfWindows*sizeof(XWindow_t));
01348       for (int i = fMaxNumberOfWindows; i < newsize; i++)
01349          fWindows[i].fOpen = 0;
01350       fMaxNumberOfWindows = newsize;
01351       goto again;
01352    }
01353 
01354    gCws->fWindow = qwid;
01355 
01356    //init Xwindow_t struct
01357    gCws->fDrawing       = gCws->fWindow;
01358    gCws->fBuffer        = 0;
01359    gCws->fDoubleBuffer  = 0;
01360    gCws->fIsPixmap      = 0;
01361    gCws->fClip          = 0;
01362    gCws->fWidth         = w;
01363    gCws->fHeight        = h;
01364    gCws->fNewColors     = 0;
01365    gCws->fShared        = kTRUE;
01366 
01367    return wid;
01368 }
01369 
01370 //______________________________________________________________________________
01371 void TGX11::RemoveWindow(ULong_t qwid)
01372 {
01373    // Remove a window created by Qt (like CloseWindow1()).
01374 
01375    SelectWindow((int)qwid);
01376 
01377    if (gCws->fBuffer) XFreePixmap(fDisplay, gCws->fBuffer);
01378 
01379    if (gCws->fNewColors) {
01380       if (fRedDiv == -1)
01381          XFreeColors(fDisplay, fColormap, gCws->fNewColors, gCws->fNcolors, 0);
01382       delete [] gCws->fNewColors;
01383       gCws->fNewColors = 0;
01384    }
01385 
01386    gCws->fOpen = 0;
01387 
01388    // make first window in list the current window
01389    for (Int_t wid = 0; wid < fMaxNumberOfWindows; wid++)
01390       if (fWindows[wid].fOpen) {
01391          gCws = &fWindows[wid];
01392          return;
01393       }
01394 
01395    gCws = 0;
01396 }
01397 
01398 //______________________________________________________________________________
01399 void TGX11::QueryPointer(int &ix, int &iy)
01400 {
01401    // Query pointer position.
01402    // ix       : X coordinate of pointer
01403    // iy       : Y coordinate of pointer
01404    // (both coordinates are relative to the origin of the root window)
01405 
01406    Window    root_return, child_return;
01407    int       win_x_return, win_y_return;
01408    int       root_x_return, root_y_return;
01409    unsigned int mask_return;
01410 
01411    XQueryPointer(fDisplay,gCws->fWindow, &root_return,
01412                  &child_return, &root_x_return, &root_y_return, &win_x_return,
01413                  &win_y_return, &mask_return);
01414 
01415    ix = root_x_return;
01416    iy = root_y_return;
01417 }
01418 
01419 //______________________________________________________________________________
01420 void  TGX11::RemovePixmap(Drawable *pix)
01421 {
01422    // Remove the pixmap pix.
01423 
01424    XFreePixmap(fDisplay,*pix);
01425 }
01426 
01427 //______________________________________________________________________________
01428 Int_t TGX11::RequestLocator(int mode, int ctyp, int &x, int &y)
01429 {
01430    // Request Locator position.
01431    // x,y       : cursor position at moment of button press (output)
01432    // ctyp      : cursor type (input)
01433    //   ctyp=1 tracking cross
01434    //   ctyp=2 cross-hair
01435    //   ctyp=3 rubber circle
01436    //   ctyp=4 rubber band
01437    //   ctyp=5 rubber rectangle
01438    //
01439    // mode      : input mode
01440    //   mode=0 request
01441    //   mode=1 sample
01442    //
01443    // Request locator:
01444    // return button number  1 = left is pressed
01445    //                       2 = middle is pressed
01446    //                       3 = right is pressed
01447    //        in sample mode:
01448    //                      11 = left is released
01449    //                      12 = middle is released
01450    //                      13 = right is released
01451    //                      -1 = nothing is pressed or released
01452    //                      -2 = leave the window
01453    //                    else = keycode (keyboard is pressed)
01454 
01455    static int xloc  = 0;
01456    static int yloc  = 0;
01457    static int xlocp = 0;
01458    static int ylocp = 0;
01459    static Cursor cursor = 0;
01460 
01461    XEvent event;
01462    int button_press;
01463    int radius;
01464 
01465    // Change the cursor shape
01466    if (cursor == 0) {
01467       if (ctyp > 1) {
01468          XDefineCursor(fDisplay, gCws->fWindow, gNullCursor);
01469          XSetForeground(fDisplay, gGCecho, GetColor(0).fPixel);
01470       } else {
01471          cursor = XCreateFontCursor(fDisplay, XC_crosshair);
01472          XDefineCursor(fDisplay, gCws->fWindow, cursor);
01473       }
01474    }
01475 
01476    // Event loop
01477 
01478    button_press = 0;
01479 
01480    while (button_press == 0) {
01481 
01482       switch (ctyp) {
01483 
01484          case 1 :
01485             break;
01486 
01487          case 2 :
01488             XDrawLine(fDisplay, gCws->fWindow, gGCecho,
01489                       xloc, 0, xloc, gCws->fHeight);
01490             XDrawLine(fDisplay, gCws->fWindow, gGCecho,
01491                       0, yloc, gCws->fWidth, yloc);
01492             break;
01493 
01494          case 3 :
01495             radius = (int) TMath::Sqrt((double)((xloc-xlocp)*(xloc-xlocp) +
01496                                        (yloc-ylocp)*(yloc-ylocp)));
01497             XDrawArc(fDisplay, gCws->fWindow, gGCecho,
01498                      xlocp-radius, ylocp-radius,
01499                      2*radius, 2*radius, 0, 23040);
01500             break;
01501 
01502          case 4 :
01503             XDrawLine(fDisplay, gCws->fWindow, gGCecho,
01504                       xlocp, ylocp, xloc, yloc);
01505             break;
01506 
01507          case 5 :
01508             XDrawRectangle(fDisplay, gCws->fWindow, gGCecho,
01509                            TMath::Min(xlocp,xloc), TMath::Min(ylocp,yloc),
01510                            TMath::Abs(xloc-xlocp), TMath::Abs(yloc-ylocp));
01511             break;
01512 
01513          default:
01514             break;
01515       }
01516 
01517       while (XEventsQueued( fDisplay, QueuedAlready) > 1) {
01518          XNextEvent(fDisplay, &event);
01519       }
01520       XWindowEvent(fDisplay, gCws->fWindow, gMouseMask, &event);
01521 
01522       switch (ctyp) {
01523 
01524          case 1 :
01525             break;
01526 
01527          case 2 :
01528             XDrawLine(fDisplay, gCws->fWindow, gGCecho,
01529                       xloc, 0, xloc, gCws->fHeight);
01530             XDrawLine(fDisplay, gCws->fWindow, gGCecho,
01531                       0, yloc, gCws->fWidth, yloc);
01532             break;
01533 
01534          case 3 :
01535             radius = (int) TMath::Sqrt((double)((xloc-xlocp)*(xloc-xlocp) +
01536                                            (yloc-ylocp)*(yloc-ylocp)));
01537             XDrawArc(fDisplay, gCws->fWindow, gGCecho,
01538                      xlocp-radius, ylocp-radius,
01539                      2*radius, 2*radius, 0, 23040);
01540             break;
01541 
01542          case 4 :
01543             XDrawLine(fDisplay, gCws->fWindow, gGCecho,
01544                       xlocp, ylocp, xloc, yloc);
01545             break;
01546 
01547          case 5 :
01548             XDrawRectangle(fDisplay, gCws->fWindow, gGCecho,
01549                            TMath::Min(xlocp,xloc), TMath::Min(ylocp,yloc),
01550                            TMath::Abs(xloc-xlocp), TMath::Abs(yloc-ylocp));
01551             break;
01552 
01553          default:
01554             break;
01555       }
01556 
01557       xloc = event.xbutton.x;
01558       yloc = event.xbutton.y;
01559 
01560       switch (event.type) {
01561 
01562          case LeaveNotify :
01563             if (mode == 0) {
01564                while (1) {
01565                   XNextEvent(fDisplay, &event);
01566                   if (event.type == EnterNotify) break;
01567                }
01568             } else {
01569                button_press = -2;
01570             }
01571             break;
01572 
01573          case ButtonPress :
01574             button_press = event.xbutton.button ;
01575             xlocp = event.xbutton.x;
01576             ylocp = event.xbutton.y;
01577             XUndefineCursor( fDisplay, gCws->fWindow );
01578             cursor = 0;
01579             break;
01580 
01581          case ButtonRelease :
01582             if (mode == 1) {
01583                button_press = 10+event.xbutton.button ;
01584                xlocp = event.xbutton.x;
01585                ylocp = event.xbutton.y;
01586             }
01587             break;
01588 
01589          case KeyPress :
01590             if (mode == 1) {
01591                button_press = event.xkey.keycode;
01592                xlocp = event.xbutton.x;
01593                ylocp = event.xbutton.y;
01594             }
01595             break;
01596 
01597          case KeyRelease :
01598             if (mode == 1) {
01599                button_press = -event.xkey.keycode;
01600                xlocp = event.xbutton.x;
01601                ylocp = event.xbutton.y;
01602             }
01603             break;
01604 
01605          default :
01606             break;
01607       }
01608 
01609       if (mode == 1) {
01610          if (button_press == 0)
01611             button_press = -1;
01612          break;
01613       }
01614    }
01615    x = event.xbutton.x;
01616    y = event.xbutton.y;
01617 
01618    return button_press;
01619 }
01620 
01621 //______________________________________________________________________________
01622 Int_t TGX11::RequestString(int x, int y, char *text)
01623 {
01624    // Request a string.
01625    // x,y         : position where text is displayed
01626    // text        : text displayed (input), edited text (output)
01627    //
01628    // Request string:
01629    // text is displayed and can be edited with Emacs-like keybinding
01630    // return termination code (0 for ESC, 1 for RETURN)
01631 
01632    static Cursor cursor = 0;
01633    static int percent = 0;  // bell volume
01634    Window focuswindow;
01635    int focusrevert;
01636    XEvent event;
01637    KeySym keysym;
01638    int key = -1;
01639    int len_text = strlen(text);
01640    int nt;         // defined length of text
01641    int pt;         // cursor position in text
01642 
01643    // change the cursor shape
01644    if (cursor == 0) {
01645       XKeyboardState kbstate;
01646       cursor = XCreateFontCursor(fDisplay, XC_question_arrow);
01647       XGetKeyboardControl(fDisplay, &kbstate);
01648       percent = kbstate.bell_percent;
01649    }
01650    if (cursor != 0)
01651       XDefineCursor(fDisplay, gCws->fWindow, cursor);
01652    for (nt = len_text; nt > 0 && text[nt-1] == ' '; nt--) { }
01653       pt = nt;
01654    XGetInputFocus(fDisplay, &focuswindow, &focusrevert);
01655    XSetInputFocus(fDisplay, gCws->fWindow, focusrevert, CurrentTime);
01656    while (key < 0) {
01657       char keybuf[8];
01658       char nbytes;
01659       int dx;
01660       int i;
01661       XDrawImageString(fDisplay, gCws->fWindow, *gGCtext, x, y, text, nt);
01662       dx = XTextWidth(gTextFont, text, nt);
01663       XDrawImageString(fDisplay, gCws->fWindow, *gGCtext, x + dx, y, " ", 1);
01664       dx = pt == 0 ? 0 : XTextWidth(gTextFont, text, pt);
01665       XDrawImageString(fDisplay, gCws->fWindow, *gGCinvt,
01666                        x + dx, y, pt < len_text ? &text[pt] : " ", 1);
01667       XWindowEvent(fDisplay, gCws->fWindow, gKeybdMask, &event);
01668       switch (event.type) {
01669          case ButtonPress:
01670          case EnterNotify:
01671             XSetInputFocus(fDisplay, gCws->fWindow, focusrevert, CurrentTime);
01672             break;
01673          case LeaveNotify:
01674             XSetInputFocus(fDisplay, focuswindow, focusrevert, CurrentTime);
01675             break;
01676          case KeyPress:
01677             nbytes = XLookupString(&event.xkey, keybuf, sizeof(keybuf),
01678                                    &keysym, 0);
01679             switch (keysym) {      // map cursor keys
01680                case XK_Left:
01681                   keybuf[0] = '\002';  // Control-B
01682                   nbytes = 1;
01683                   break;
01684                case XK_Right:
01685                   keybuf[0] = '\006';  // Control-F
01686                   nbytes = 1;
01687                   break;
01688             }
01689             if (nbytes == 1) {
01690             if (isascii(keybuf[0]) && isprint(keybuf[0])) {
01691                // insert character
01692                if (nt < len_text)
01693                   nt++;
01694                for (i = nt - 1; i > pt; i--)
01695                   text[i] = text[i-1];
01696                if (pt < len_text) {
01697                   text[pt] = keybuf[0];
01698                   pt++;
01699                }
01700             } else
01701                switch (keybuf[0]) {
01702                   // Emacs-like editing keys
01703 
01704                   case '\010':    // backspace
01705                   case '\177':    // delete
01706                      // delete backward
01707                      if (pt > 0) {
01708                         for (i = pt; i < nt; i++)
01709                            text[i-1] = text[i];
01710                         text[nt-1] = ' ';
01711                         nt--;
01712                         pt--;
01713                      }
01714                      break;
01715                   case '\001':    // ^A
01716                      // beginning of line
01717                      pt = 0;
01718                      break;
01719                   case '\002':    // ^B
01720                      // move backward
01721                      if (pt > 0)
01722                         pt--;
01723                      break;
01724                   case '\004':    // ^D
01725                      // delete forward
01726                      if (pt > 0) {
01727                         for (i = pt; i < nt; i++)
01728                            text[i-1] = text[i];
01729                         text[nt-1] = ' ';
01730                         pt--;
01731                      }
01732                      break;
01733                   case '\005':    // ^E
01734                      // end of line
01735                      pt = nt;
01736                      break;
01737 
01738                   case '\006':    // ^F
01739                      // move forward
01740                      if (pt < nt)
01741                         pt++;
01742                      break;
01743                   case '\013':    // ^K
01744                      // delete to end of line
01745                      for (i = pt; i < nt; i++)
01746                         text[i] = ' ';
01747                      nt = pt;
01748                      break;
01749                   case '\024':    // ^T
01750                      // transpose
01751                      if (pt > 0) {
01752                         char c = text[pt];
01753                         text[pt] = text[pt-1];
01754                         text[pt-1] = c;
01755                      }
01756                      break;
01757                   case '\012':    // newline
01758                   case '\015':    // return
01759                      key = 1;
01760                      break;
01761                   case '\033':    // escape
01762                      key = 0;
01763                      break;
01764 
01765                   default:
01766                      XBell(fDisplay, percent);
01767                }
01768             }
01769       }
01770    }
01771    XSetInputFocus(fDisplay, focuswindow, focusrevert, CurrentTime);
01772 
01773    if (cursor != 0) {
01774       XUndefineCursor(fDisplay, gCws->fWindow);
01775       cursor = 0;
01776    }
01777 
01778    return key;
01779 }
01780 
01781 //______________________________________________________________________________
01782 void TGX11::RescaleWindow(int wid, unsigned int w, unsigned int h)
01783 {
01784    // Rescale the window wid.
01785    // wid  : Window identifier
01786    // w    : Width
01787    // h    : Heigth
01788 
01789    int i;
01790 
01791    gTws = &fWindows[wid];
01792    if (!gTws->fOpen) return;
01793 
01794    // don't do anything when size did not change
01795    if (gTws->fWidth == w && gTws->fHeight == h) return;
01796 
01797    XResizeWindow(fDisplay, gTws->fWindow, w, h);
01798 
01799    if (gTws->fBuffer) {
01800       // don't free and recreate pixmap when new pixmap is smaller
01801       if (gTws->fWidth < w || gTws->fHeight < h) {
01802          XFreePixmap(fDisplay,gTws->fBuffer);
01803          gTws->fBuffer = XCreatePixmap(fDisplay, fRootWin, w, h, fDepth);
01804       }
01805       for (i = 0; i < kMAXGC; i++) XSetClipMask(fDisplay, gGClist[i], None);
01806       SetColor(*gGCpxmp, 0);
01807       XFillRectangle( fDisplay, gTws->fBuffer, *gGCpxmp, 0, 0, w, h);
01808       SetColor(*gGCpxmp, 1);
01809       if (gTws->fDoubleBuffer) gTws->fDrawing = gTws->fBuffer;
01810    }
01811    gTws->fWidth  = w;
01812    gTws->fHeight = h;
01813 }
01814 
01815 //______________________________________________________________________________
01816 int TGX11::ResizePixmap(int wid, unsigned int w, unsigned int h)
01817 {
01818    // Resize a pixmap.
01819    // wid : pixmap to be resized
01820    // w,h : Width and height of the pixmap
01821 
01822    Window root;
01823    unsigned int wval, hval;
01824    int xx, yy, i;
01825    unsigned int ww, hh, border, depth;
01826    wval = w;
01827    hval = h;
01828 
01829    gTws = &fWindows[wid];
01830 
01831    // don't do anything when size did not change
01832    //  if (gTws->fWidth == wval && gTws->fHeight == hval) return 0;
01833 
01834    // due to round-off errors in TPad::Resize() we might get +/- 1 pixel
01835    // change, in those cases don't resize pixmap
01836    if (gTws->fWidth  >= wval-1 && gTws->fWidth  <= wval+1 &&
01837        gTws->fHeight >= hval-1 && gTws->fHeight <= hval+1) return 0;
01838 
01839    // don't free and recreate pixmap when new pixmap is smaller
01840    if (gTws->fWidth < wval || gTws->fHeight < hval) {
01841       XFreePixmap(fDisplay, gTws->fWindow);
01842       gTws->fWindow = XCreatePixmap(fDisplay, fRootWin, wval, hval, fDepth);
01843    }
01844    XGetGeometry(fDisplay, gTws->fWindow, &root, &xx, &yy, &ww, &hh, &border, &depth);
01845 
01846    for (i = 0; i < kMAXGC; i++)
01847       XSetClipMask(fDisplay, gGClist[i], None);
01848 
01849    SetColor(*gGCpxmp, 0);
01850    XFillRectangle(fDisplay, gTws->fWindow, *gGCpxmp, 0, 0, ww, hh);
01851    SetColor(*gGCpxmp, 1);
01852 
01853    // Initialise the window structure
01854    gTws->fDrawing = gTws->fWindow;
01855    gTws->fWidth   = wval;
01856    gTws->fHeight  = hval;
01857 
01858    return 1;
01859 }
01860 
01861 //______________________________________________________________________________
01862 void TGX11::ResizeWindow(int wid)
01863 {
01864    // Resize the current window if necessary.
01865 
01866    int i;
01867    int xval=0, yval=0;
01868    Window win, root=0;
01869    unsigned int wval=0, hval=0, border=0, depth=0;
01870 
01871    gTws = &fWindows[wid];
01872 
01873    win = gTws->fWindow;
01874 
01875    XGetGeometry(fDisplay, win, &root,
01876                 &xval, &yval, &wval, &hval, &border, &depth);
01877    if (wval >= 65500) wval = 1;
01878    if (hval >= 65500) hval = 1;
01879 
01880    // don't do anything when size did not change
01881    if (gTws->fWidth == wval && gTws->fHeight == hval) return;
01882 
01883    XResizeWindow(fDisplay, gTws->fWindow, wval, hval);
01884 
01885    if (gTws->fBuffer) {
01886       if (gTws->fWidth < wval || gTws->fHeight < hval) {
01887          XFreePixmap(fDisplay,gTws->fBuffer);
01888          gTws->fBuffer = XCreatePixmap(fDisplay, fRootWin, wval, hval, fDepth);
01889       }
01890       for (i = 0; i < kMAXGC; i++) XSetClipMask(fDisplay, gGClist[i], None);
01891       SetColor(*gGCpxmp, 0);
01892       XFillRectangle(fDisplay, gTws->fBuffer, *gGCpxmp, 0, 0, wval, hval);
01893       SetColor(*gGCpxmp, 1);
01894       if (gTws->fDoubleBuffer) gTws->fDrawing = gTws->fBuffer;
01895    }
01896    gTws->fWidth  = wval;
01897    gTws->fHeight = hval;
01898 }
01899 
01900 //______________________________________________________________________________
01901 void TGX11::SelectWindow(int wid)
01902 {
01903    // Select window to which subsequent output is directed.
01904 
01905    XRectangle region;
01906    int i;
01907 
01908    if (wid < 0 || wid >= fMaxNumberOfWindows || !fWindows[wid].fOpen) return;
01909 
01910    gCws = &fWindows[wid];
01911 
01912    if (gCws->fClip && !gCws->fIsPixmap && !gCws->fDoubleBuffer) {
01913       region.x      = gCws->fXclip;
01914       region.y      = gCws->fYclip;
01915       region.width  = gCws->fWclip;
01916       region.height = gCws->fHclip;
01917       for (i = 0; i < kMAXGC; i++)
01918          XSetClipRectangles(fDisplay, gGClist[i], 0, 0, &region, 1, YXBanded);
01919    } else {
01920       for (i = 0; i < kMAXGC; i++)
01921          XSetClipMask(fDisplay, gGClist[i], None);
01922    }
01923 }
01924 
01925 //______________________________________________________________________________
01926 void TGX11::SetCharacterUp(Float_t chupx, Float_t chupy)
01927 {
01928    // Set character up vector.
01929 
01930    if (chupx == fCharacterUpX  && chupy == fCharacterUpY) return;
01931 
01932    if      (chupx == 0  && chupy == 0)  fTextAngle = 0;
01933    else if (chupx == 0  && chupy == 1)  fTextAngle = 0;
01934    else if (chupx == -1 && chupy == 0)  fTextAngle = 90;
01935    else if (chupx == 0  && chupy == -1) fTextAngle = 180;
01936    else if (chupx == 1  && chupy ==  0) fTextAngle = 270;
01937    else {
01938       fTextAngle = ((TMath::ACos(chupx/TMath::Sqrt(chupx*chupx +chupy*chupy))*180.)/TMath::Pi())-90;
01939       if (chupy < 0) fTextAngle = 180 - fTextAngle;
01940       if (TMath::Abs(fTextAngle) <= 0.01) fTextAngle = 0;
01941    }
01942    fCharacterUpX = chupx;
01943    fCharacterUpY = chupy;
01944 }
01945 
01946 //______________________________________________________________________________
01947 void TGX11::SetClipOFF(int wid)
01948 {
01949    // Turn off the clipping for the window wid.
01950 
01951    gTws       = &fWindows[wid];
01952    gTws->fClip = 0;
01953 
01954    for (int i = 0; i < kMAXGC; i++)
01955       XSetClipMask( fDisplay, gGClist[i], None );
01956 }
01957 
01958 //______________________________________________________________________________
01959 void TGX11::SetClipRegion(int wid, int x, int y, unsigned int w, unsigned int h)
01960 {
01961    // Set clipping region for the window wid.
01962    // wid        : Window indentifier
01963    // x,y        : origin of clipping rectangle
01964    // w,h        : size of clipping rectangle;
01965 
01966 
01967    gTws = &fWindows[wid];
01968    gTws->fXclip = x;
01969    gTws->fYclip = y;
01970    gTws->fWclip = w;
01971    gTws->fHclip = h;
01972    gTws->fClip  = 1;
01973    if (gTws->fClip && !gTws->fIsPixmap && !gTws->fDoubleBuffer) {
01974       XRectangle region;
01975       region.x      = gTws->fXclip;
01976       region.y      = gTws->fYclip;
01977       region.width  = gTws->fWclip;
01978       region.height = gTws->fHclip;
01979       for (int i = 0; i < kMAXGC; i++)
01980          XSetClipRectangles(fDisplay, gGClist[i], 0, 0, &region, 1, YXBanded);
01981    }
01982 }
01983 
01984 //______________________________________________________________________________
01985 void  TGX11::SetColor(GC gc, int ci)
01986 {
01987    // Set the foreground color in GC.
01988 
01989    TColor *color = gROOT->GetColor(ci);
01990    if (color)
01991       SetRGB(ci, color->GetRed(), color->GetGreen(), color->GetBlue());
01992 //   else
01993 //      Warning("SetColor", "color with index %d not defined", ci);
01994 
01995    XColor_t &col = GetColor(ci);
01996    if (fColormap && !col.fDefined) {
01997       col = GetColor(0);
01998    } else if (!fColormap && (ci < 0 || ci > 1)) {
01999       col = GetColor(0);
02000    }
02001 
02002    if (fDrawMode == kXor) {
02003       XGCValues values;
02004       XGetGCValues(fDisplay, gc, GCBackground, &values);
02005       XSetForeground(fDisplay, gc, col.fPixel ^ values.background);
02006    } else {
02007       XSetForeground(fDisplay, gc, col.fPixel);
02008 
02009       // make sure that foreground and background are different
02010       XGCValues values;
02011       XGetGCValues(fDisplay, gc, GCForeground | GCBackground, &values);
02012       if (values.foreground == values.background)
02013          XSetBackground(fDisplay, gc, GetColor(!ci).fPixel);
02014    }
02015 }
02016 
02017 //______________________________________________________________________________
02018 void  TGX11::SetCursor(int wid, ECursor cursor)
02019 {
02020    // Set the cursor.
02021 
02022    gTws = &fWindows[wid];
02023    XDefineCursor(fDisplay, gTws->fWindow, fCursors[cursor]);
02024 }
02025 
02026 //______________________________________________________________________________
02027 void TGX11::SetDoubleBuffer(int wid, int mode)
02028 {
02029    // Set the double buffer on/off on window wid.
02030    // wid  : Window identifier.
02031    //        999 means all the opened windows.
02032    // mode : 1 double buffer is on
02033    //        0 double buffer is off
02034 
02035    if (wid == 999) {
02036       for (int i = 0; i < fMaxNumberOfWindows; i++) {
02037          gTws = &fWindows[i];
02038          if (gTws->fOpen) {
02039             switch (mode) {
02040                case 1 :
02041                   SetDoubleBufferON();
02042                   break;
02043                default:
02044                   SetDoubleBufferOFF();
02045                   break;
02046             }
02047          }
02048       }
02049    } else {
02050       gTws = &fWindows[wid];
02051       if (!gTws->fOpen) return;
02052       switch (mode) {
02053          case 1 :
02054             SetDoubleBufferON();
02055             return;
02056          default:
02057             SetDoubleBufferOFF();
02058             return;
02059       }
02060    }
02061 }
02062 
02063 //______________________________________________________________________________
02064 void TGX11::SetDoubleBufferOFF()
02065 {
02066    // Turn double buffer mode off.
02067 
02068    if (!gTws->fDoubleBuffer) return;
02069    gTws->fDoubleBuffer = 0;
02070    gTws->fDrawing      = gTws->fWindow;
02071 }
02072 
02073 //______________________________________________________________________________
02074 void TGX11::SetDoubleBufferON()
02075 {
02076    // Turn double buffer mode on.
02077 
02078    if (gTws->fDoubleBuffer || gTws->fIsPixmap) return;
02079    if (!gTws->fBuffer) {
02080       gTws->fBuffer = XCreatePixmap(fDisplay, fRootWin,
02081                                    gTws->fWidth, gTws->fHeight, fDepth);
02082       SetColor(*gGCpxmp, 0);
02083       XFillRectangle(fDisplay, gTws->fBuffer, *gGCpxmp, 0, 0, gTws->fWidth, gTws->fHeight);
02084       SetColor(*gGCpxmp, 1);
02085    }
02086    for (int i = 0; i < kMAXGC; i++) XSetClipMask(fDisplay, gGClist[i], None);
02087    gTws->fDoubleBuffer  = 1;
02088    gTws->fDrawing       = gTws->fBuffer;
02089 }
02090 
02091 //______________________________________________________________________________
02092 void TGX11::SetDrawMode(EDrawMode mode)
02093 {
02094    // Set the drawing mode.
02095    // mode : drawing mode
02096    //   mode=1 copy
02097    //   mode=2 xor
02098    //   mode=3 invert
02099    //   mode=4 set the suitable mode for cursor echo according to
02100    //          the vendor
02101 
02102    int i;
02103    switch (mode) {
02104       case kCopy:
02105          for (i = 0; i < kMAXGC; i++) XSetFunction(fDisplay, gGClist[i], GXcopy);
02106          break;
02107 
02108       case kXor:
02109          for (i = 0; i < kMAXGC; i++) XSetFunction(fDisplay, gGClist[i], GXxor);
02110          break;
02111 
02112       case kInvert:
02113          for (i = 0; i < kMAXGC; i++) XSetFunction(fDisplay, gGClist[i], GXinvert);
02114          break;
02115    }
02116    fDrawMode = mode;
02117 }
02118 
02119 //______________________________________________________________________________
02120 void TGX11::SetFillColor(Color_t cindex)
02121 {
02122    // Set color index for fill areas.
02123 
02124    if (!gStyle->GetFillColor() && cindex > 1) cindex = 0;
02125    if (cindex >= 0) SetColor(*gGCfill, Int_t(cindex));
02126    fFillColor = cindex;
02127 
02128    // invalidate fill pattern
02129    if (gFillPattern != 0) {
02130       XFreePixmap(fDisplay, gFillPattern);
02131       gFillPattern = 0;
02132    }
02133 }
02134 
02135 //______________________________________________________________________________
02136 void TGX11::SetFillStyle(Style_t fstyle)
02137 {
02138    // Set fill area style.
02139    // fstyle   : compound fill area interior style
02140    //    fstyle = 1000*interiorstyle + styleindex
02141 
02142    if (fFillStyle == fstyle) return;
02143    fFillStyle = fstyle;
02144    Int_t style = fstyle/1000;
02145    Int_t fasi  = fstyle%1000;
02146    SetFillStyleIndex(style,fasi);
02147 }
02148 
02149 //______________________________________________________________________________
02150 void TGX11::SetFillStyleIndex(Int_t style, Int_t fasi)
02151 {
02152    // Set fill area style index.
02153 
02154    static int current_fasi = 0;
02155 
02156    fFillStyle = 1000*style + fasi;
02157 
02158    switch (style) {
02159 
02160       case 1:         // solid
02161          gFillHollow = 0;
02162          XSetFillStyle(fDisplay, *gGCfill, FillSolid);
02163          break;
02164 
02165       case 2:         // pattern
02166          gFillHollow = 1;
02167          break;
02168 
02169       case 3:         // hatch
02170          gFillHollow = 0;
02171          XSetFillStyle(fDisplay, *gGCfill, FillStippled);
02172          if (fasi != current_fasi) {
02173             if (gFillPattern != 0) {
02174                XFreePixmap(fDisplay, gFillPattern);
02175                gFillPattern = 0;
02176             }
02177             int stn = (fasi >= 1 && fasi <=25) ? fasi : 2;
02178 
02179             gFillPattern = XCreateBitmapFromData(fDisplay, fRootWin,
02180                                                  (const char*)gStipples[stn], 16, 16);
02181 
02182             XSetStipple( fDisplay, *gGCfill, gFillPattern );
02183             current_fasi = fasi;
02184          }
02185          break;
02186 
02187       default:
02188          gFillHollow = 1;
02189    }
02190 }
02191 
02192 //______________________________________________________________________________
02193 void TGX11::SetInput(int inp)
02194 {
02195    // Set input on or off.
02196 
02197    XSetWindowAttributes attributes;
02198    ULong_t attr_mask;
02199 
02200    if (inp == 1) {
02201       attributes.event_mask = gMouseMask | gKeybdMask;
02202       attr_mask = CWEventMask;
02203       XChangeWindowAttributes(fDisplay, gCws->fWindow, attr_mask, &attributes);
02204    } else {
02205       attributes.event_mask = NoEventMask;
02206       attr_mask = CWEventMask;
02207       XChangeWindowAttributes(fDisplay, gCws->fWindow, attr_mask, &attributes);
02208    }
02209 }
02210 
02211 //______________________________________________________________________________
02212 void TGX11::SetLineColor(Color_t cindex)
02213 {
02214    // Set color index for lines.
02215 
02216    if (cindex < 0) return;
02217 
02218    TAttLine::SetLineColor(cindex);
02219 
02220    SetColor(*gGCline, Int_t(cindex));
02221    SetColor(*gGCdash, Int_t(cindex));
02222 }
02223 
02224 //______________________________________________________________________________
02225 void TGX11::SetLineType(int n, int *dash)
02226 {
02227    // Set line type.
02228    // n         : length of dash list
02229    // dash(n)   : dash segment lengths
02230    //
02231    // if n <= 0 use solid lines
02232    // if n >  0 use dashed lines described by DASH(N)
02233    //    e.g. N=4,DASH=(6,3,1,3) gives a dashed-dotted line with dash length 6
02234    //    and a gap of 7 between dashes
02235 
02236    if (n <= 0) {
02237       gLineStyle = LineSolid;
02238       XSetLineAttributes(fDisplay, *gGCline, gLineWidth,
02239                          gLineStyle, gCapStyle, gJoinStyle);
02240    } else {
02241       gDashSize = TMath::Min((int)sizeof(gDashList),n);
02242       gDashLength = 0;
02243       for (int i = 0; i < gDashSize; i++ ) {
02244          gDashList[i] = dash[i];
02245          gDashLength += gDashList[i];
02246       }
02247       gDashOffset = 0;
02248       gLineStyle = LineOnOffDash;
02249       XSetLineAttributes(fDisplay, *gGCline, gLineWidth,
02250                          gLineStyle, gCapStyle, gJoinStyle);
02251       XSetLineAttributes(fDisplay, *gGCdash, gLineWidth,
02252                          gLineStyle, gCapStyle, gJoinStyle);
02253    }
02254 }
02255 
02256 //______________________________________________________________________________
02257 void TGX11::SetLineStyle(Style_t lstyle)
02258 {
02259    // Set line style.
02260 
02261    static Int_t dashed[2] = {3,3};
02262    static Int_t dotted[2] = {1,2};
02263    static Int_t dasheddotted[4] = {3,4,1,4};
02264 
02265    if (fLineStyle != lstyle) { //set style index only if different
02266       fLineStyle = lstyle;
02267       if (lstyle <= 1 ) {
02268          SetLineType(0,0);
02269       } else if (lstyle == 2 ) {
02270          SetLineType(2,dashed);
02271       } else if (lstyle == 3 ) {
02272          SetLineType(2,dotted);
02273       } else if (lstyle == 4 ) {
02274          SetLineType(4,dasheddotted);
02275       } else {
02276          TString st = (TString)gStyle->GetLineStyleString(lstyle);
02277          TObjArray *tokens = st.Tokenize(" ");
02278          Int_t nt;
02279          nt = tokens->GetEntries();
02280          Int_t *linestyle = new Int_t[nt];
02281          for (Int_t j = 0; j<nt; j++) {
02282             Int_t it;
02283             sscanf(((TObjString*)tokens->At(j))->GetName(), "%d", &it);
02284             linestyle[j] = (Int_t)(it/4);
02285          }
02286          SetLineType(nt,linestyle);
02287          delete [] linestyle;
02288          delete tokens;
02289       }
02290    }
02291 }
02292 
02293 //______________________________________________________________________________
02294 void TGX11::SetLineWidth(Width_t width )
02295 {
02296    // Set line width.
02297    // width   : line width in pixels
02298 
02299    if (fLineWidth == width) return;
02300    if (width == 1) gLineWidth = 0;
02301    else            gLineWidth = width;
02302 
02303    fLineWidth = gLineWidth;
02304    if (gLineWidth < 0) return;
02305 
02306    XSetLineAttributes(fDisplay, *gGCline, gLineWidth,
02307                       gLineStyle, gCapStyle, gJoinStyle);
02308    XSetLineAttributes(fDisplay, *gGCdash, gLineWidth,
02309               gLineStyle, gCapStyle, gJoinStyle);
02310 }
02311 
02312 //______________________________________________________________________________
02313 void TGX11::SetMarkerColor(Color_t cindex)
02314 {
02315    // Set color index for markers.
02316 
02317    if (cindex < 0) return;
02318 
02319    TAttMarker::SetMarkerColor(cindex);
02320 
02321    SetColor(*gGCmark, Int_t(cindex));
02322 }
02323 
02324 //______________________________________________________________________________
02325 void TGX11::SetMarkerSize(Float_t msize)
02326 {
02327    // Set marker size index.
02328    // msize  : marker scale factor
02329 
02330    if (msize == fMarkerSize) return;
02331 
02332    fMarkerSize = msize;
02333    if (msize < 0) return;
02334 
02335    SetMarkerStyle(-fMarkerStyle);
02336 }
02337 
02338 //______________________________________________________________________________
02339 void TGX11::SetMarkerType(int type, int n, XPoint *xy)
02340 {
02341    // Set marker type.
02342    // type      : marker type
02343    // n         : length of marker description
02344    // xy        : list of points describing marker shape
02345    //
02346    // if n == 0 marker is a single point
02347    // if TYPE == 0 marker is hollow circle of diameter N
02348    // if TYPE == 1 marker is filled circle of diameter N
02349    // if TYPE == 2 marker is a hollow polygon describe by line XY
02350    // if TYPE == 3 marker is a filled polygon describe by line XY
02351    // if TYPE == 4 marker is described by segmented line XY
02352    //   e.g. TYPE=4,N=4,XY=(-3,0,3,0,0,-3,0,3) sets a plus shape of 7x7 pixels
02353 
02354    gMarker.type = type;
02355    gMarker.n = n < kMAXMK ? n : kMAXMK;
02356    if (gMarker.type >= 2) {
02357       for (int i = 0; i < gMarker.n; i++) {
02358          gMarker.xy[i].x = xy[i].x;
02359          gMarker.xy[i].y = xy[i].y;
02360       }
02361    }
02362 }
02363 
02364 //______________________________________________________________________________
02365 void TGX11::SetMarkerStyle(Style_t markerstyle)
02366 {
02367    // Set marker style.
02368 
02369    if (fMarkerStyle == markerstyle) return;
02370    static XPoint shape[15];
02371    if (markerstyle >= 35) return;
02372    markerstyle  = TMath::Abs(markerstyle);
02373    fMarkerStyle = markerstyle;
02374    Int_t im = Int_t(4*fMarkerSize + 0.5);
02375    if (markerstyle == 2) {
02376       // + shaped marker
02377       shape[0].x = -im;  shape[0].y = 0;
02378       shape[1].x =  im;  shape[1].y = 0;
02379       shape[2].x = 0  ;  shape[2].y = -im;
02380       shape[3].x = 0  ;  shape[3].y = im;
02381       SetMarkerType(4,4,shape);
02382    } else if (markerstyle == 3 || markerstyle == 31) {
02383       // * shaped marker
02384       shape[0].x = -im;  shape[0].y = 0;
02385       shape[1].x =  im;  shape[1].y = 0;
02386       shape[2].x = 0  ;  shape[2].y = -im;
02387       shape[3].x = 0  ;  shape[3].y = im;
02388       im = Int_t(0.707*Float_t(im) + 0.5);
02389       shape[4].x = -im;  shape[4].y = -im;
02390       shape[5].x =  im;  shape[5].y = im;
02391       shape[6].x = -im;  shape[6].y = im;
02392       shape[7].x =  im;  shape[7].y = -im;
02393       SetMarkerType(4,8,shape);
02394    } else if (markerstyle == 4 || markerstyle == 24) {
02395       // O shaped marker
02396       SetMarkerType(0,im*2,shape);
02397    } else if (markerstyle == 5) {
02398       // X shaped marker
02399       im = Int_t(0.707*Float_t(im) + 0.5);
02400       shape[0].x = -im;  shape[0].y = -im;
02401       shape[1].x =  im;  shape[1].y = im;
02402       shape[2].x = -im;  shape[2].y = im;
02403       shape[3].x =  im;  shape[3].y = -im;
02404       SetMarkerType(4,4,shape);
02405    } else if (markerstyle == 6) {
02406       // + shaped marker (with 1 pixel)
02407       shape[0].x = -1 ;  shape[0].y = 0;
02408       shape[1].x =  1 ;  shape[1].y = 0;
02409       shape[2].x =  0 ;  shape[2].y = -1;
02410       shape[3].x =  0 ;  shape[3].y = 1;
02411       SetMarkerType(4,4,shape);
02412    } else if (markerstyle == 7) {
02413       // . shaped marker (with 9 pixel)
02414       shape[0].x = -1 ;  shape[0].y = 1;
02415       shape[1].x =  1 ;  shape[1].y = 1;
02416       shape[2].x = -1 ;  shape[2].y = 0;
02417       shape[3].x =  1 ;  shape[3].y = 0;
02418       shape[4].x = -1 ;  shape[4].y = -1;
02419       shape[5].x =  1 ;  shape[5].y = -1;
02420       SetMarkerType(4,6,shape);
02421    } else if (markerstyle == 8 || markerstyle == 20) {
02422       // O shaped marker (filled)
02423       SetMarkerType(1,im*2,shape);
02424    } else if (markerstyle == 21) {
02425       // full square
02426       shape[0].x = -im;  shape[0].y = -im;
02427       shape[1].x =  im;  shape[1].y = -im;
02428       shape[2].x =  im;  shape[2].y = im;
02429       shape[3].x = -im;  shape[3].y = im;
02430       shape[4].x = -im;  shape[4].y = -im;
02431       SetMarkerType(3,5,shape);
02432    } else if (markerstyle == 22) {
02433       // full triangle up
02434       shape[0].x = -im;  shape[0].y = im;
02435       shape[1].x =  im;  shape[1].y = im;
02436       shape[2].x =   0;  shape[2].y = -im;
02437       shape[3].x = -im;  shape[3].y = im;
02438       SetMarkerType(3,4,shape);
02439    } else if (markerstyle == 23) {
02440       // full triangle down
02441       shape[0].x =   0;  shape[0].y = im;
02442       shape[1].x =  im;  shape[1].y = -im;
02443       shape[2].x = -im;  shape[2].y = -im;
02444       shape[3].x =   0;  shape[3].y = im;
02445       SetMarkerType(3,4,shape);
02446    } else if (markerstyle == 25) {
02447       // open square
02448       shape[0].x = -im;  shape[0].y = -im;
02449       shape[1].x =  im;  shape[1].y = -im;
02450       shape[2].x =  im;  shape[2].y = im;
02451       shape[3].x = -im;  shape[3].y = im;
02452       shape[4].x = -im;  shape[4].y = -im;
02453       SetMarkerType(2,5,shape);
02454    } else if (markerstyle == 26) {
02455       // open triangle up
02456       shape[0].x = -im;  shape[0].y = im;
02457       shape[1].x =  im;  shape[1].y = im;
02458       shape[2].x =   0;  shape[2].y = -im;
02459       shape[3].x = -im;  shape[3].y = im;
02460       SetMarkerType(2,4,shape);
02461    } else if (markerstyle == 27) {
02462       // open losange
02463       Int_t imx = Int_t(2.66*fMarkerSize + 0.5);
02464       shape[0].x =-imx;  shape[0].y = 0;
02465       shape[1].x =   0;  shape[1].y = -im;
02466       shape[2].x = imx;  shape[2].y = 0;
02467       shape[3].x =   0;  shape[3].y = im;
02468       shape[4].x =-imx;  shape[4].y = 0;
02469       SetMarkerType(2,5,shape);
02470    } else if (markerstyle == 28) {
02471       // open cross
02472       Int_t imx = Int_t(1.33*fMarkerSize + 0.5);
02473       shape[0].x = -im;  shape[0].y =-imx;
02474       shape[1].x =-imx;  shape[1].y =-imx;
02475       shape[2].x =-imx;  shape[2].y = -im;
02476       shape[3].x = imx;  shape[3].y = -im;
02477       shape[4].x = imx;  shape[4].y =-imx;
02478       shape[5].x =  im;  shape[5].y =-imx;
02479       shape[6].x =  im;  shape[6].y = imx;
02480       shape[7].x = imx;  shape[7].y = imx;
02481       shape[8].x = imx;  shape[8].y = im;
02482       shape[9].x =-imx;  shape[9].y = im;
02483       shape[10].x=-imx;  shape[10].y= imx;
02484       shape[11].x= -im;  shape[11].y= imx;
02485       shape[12].x= -im;  shape[12].y=-imx;
02486       SetMarkerType(2,13,shape);
02487    } else if (markerstyle == 29) {
02488       // full star pentagone
02489       Int_t im1 = Int_t(0.66*fMarkerSize + 0.5);
02490       Int_t im2 = Int_t(2.00*fMarkerSize + 0.5);
02491       Int_t im3 = Int_t(2.66*fMarkerSize + 0.5);
02492       Int_t im4 = Int_t(1.33*fMarkerSize + 0.5);
02493       shape[0].x = -im;  shape[0].y = im4;
02494       shape[1].x =-im2;  shape[1].y =-im1;
02495       shape[2].x =-im3;  shape[2].y = -im;
02496       shape[3].x =   0;  shape[3].y =-im2;
02497       shape[4].x = im3;  shape[4].y = -im;
02498       shape[5].x = im2;  shape[5].y =-im1;
02499       shape[6].x =  im;  shape[6].y = im4;
02500       shape[7].x = im4;  shape[7].y = im4;
02501       shape[8].x =   0;  shape[8].y = im;
02502       shape[9].x =-im4;  shape[9].y = im4;
02503       shape[10].x= -im;  shape[10].y= im4;
02504       SetMarkerType(3,11,shape);
02505    } else if (markerstyle == 30) {
02506       // open star pentagone
02507       Int_t im1 = Int_t(0.66*fMarkerSize + 0.5);
02508       Int_t im2 = Int_t(2.00*fMarkerSize + 0.5);
02509       Int_t im3 = Int_t(2.66*fMarkerSize + 0.5);
02510       Int_t im4 = Int_t(1.33*fMarkerSize + 0.5);
02511       shape[0].x = -im;  shape[0].y = im4;
02512       shape[1].x =-im2;  shape[1].y =-im1;
02513       shape[2].x =-im3;  shape[2].y = -im;
02514       shape[3].x =   0;  shape[3].y =-im2;
02515       shape[4].x = im3;  shape[4].y = -im;
02516       shape[5].x = im2;  shape[5].y =-im1;
02517       shape[6].x =  im;  shape[6].y = im4;
02518       shape[7].x = im4;  shape[7].y = im4;
02519       shape[8].x =   0;  shape[8].y = im;
02520       shape[9].x =-im4;  shape[9].y = im4;
02521       shape[10].x= -im;  shape[10].y= im4;
02522       SetMarkerType(2,11,shape);
02523    } else if (markerstyle == 32) {
02524       // open triangle down
02525       shape[0].x =   0;  shape[0].y = im;
02526       shape[1].x =  im;  shape[1].y = -im;
02527       shape[2].x = -im;  shape[2].y = -im;
02528       shape[3].x =   0;  shape[3].y = im;
02529       SetMarkerType(2,4,shape);
02530    } else if (markerstyle == 33) {
02531       // full losange
02532       Int_t imx = Int_t(2.66*fMarkerSize + 0.5);
02533       shape[0].x =-imx;  shape[0].y = 0;
02534       shape[1].x =   0;  shape[1].y = -im;
02535       shape[2].x = imx;  shape[2].y = 0;
02536       shape[3].x =   0;  shape[3].y = im;
02537       shape[4].x =-imx;  shape[4].y = 0;
02538       SetMarkerType(3,5,shape);
02539    } else if (markerstyle == 34) {
02540       // full cross
02541       Int_t imx = Int_t(1.33*fMarkerSize + 0.5);
02542       shape[0].x = -im;  shape[0].y =-imx;
02543       shape[1].x =-imx;  shape[1].y =-imx;
02544       shape[2].x =-imx;  shape[2].y = -im;
02545       shape[3].x = imx;  shape[3].y = -im;
02546       shape[4].x = imx;  shape[4].y =-imx;
02547       shape[5].x =  im;  shape[5].y =-imx;
02548       shape[6].x =  im;  shape[6].y = imx;
02549       shape[7].x = imx;  shape[7].y = imx;
02550       shape[8].x = imx;  shape[8].y = im;
02551       shape[9].x =-imx;  shape[9].y = im;
02552       shape[10].x=-imx;  shape[10].y= imx;
02553       shape[11].x= -im;  shape[11].y= imx;
02554       shape[12].x= -im;  shape[12].y=-imx;
02555       SetMarkerType(3,13,shape);
02556    } else {
02557       // single dot
02558       SetMarkerType(0,0,shape);
02559    }
02560 }
02561 
02562 //______________________________________________________________________________
02563 void TGX11::SetOpacity(Int_t percent)
02564 {
02565    // Set opacity of a window. This image manipulation routine works
02566    // by adding to a percent amount of neutral to each pixels RGB.
02567    // Since it requires quite some additional color map entries is it
02568    // only supported on displays with more than > 8 color planes (> 256
02569    // colors).
02570 
02571    if (fDepth <= 8) return;
02572    if (percent == 0) return;
02573    // if 100 percent then just make white
02574 
02575    ULong_t *orgcolors = 0, *tmpc = 0;
02576    Int_t    maxcolors = 0, ncolors, ntmpc = 0;
02577 
02578    // save previous allocated colors, delete at end when not used anymore
02579    if (gCws->fNewColors) {
02580       tmpc = gCws->fNewColors;
02581       ntmpc = gCws->fNcolors;
02582    }
02583 
02584    // get pixmap from server as image
02585    XImage *image = XGetImage(fDisplay, gCws->fDrawing, 0, 0, gCws->fWidth,
02586                              gCws->fHeight, AllPlanes, ZPixmap);
02587 
02588    // collect different image colors
02589    int x, y;
02590    for (y = 0; y < (int) gCws->fHeight; y++) {
02591       for (x = 0; x < (int) gCws->fWidth; x++) {
02592          ULong_t pixel = XGetPixel(image, x, y);
02593          CollectImageColors(pixel, orgcolors, ncolors, maxcolors);
02594       }
02595    }
02596    if (ncolors == 0) {
02597       XDestroyImage(image);
02598       ::operator delete(orgcolors);
02599       return;
02600    }
02601 
02602    // create opaque counter parts
02603    MakeOpaqueColors(percent, orgcolors, ncolors);
02604 
02605    // put opaque colors in image
02606    for (y = 0; y < (int) gCws->fHeight; y++) {
02607       for (x = 0; x < (int) gCws->fWidth; x++) {
02608          ULong_t pixel = XGetPixel(image, x, y);
02609          Int_t idx = FindColor(pixel, orgcolors, ncolors);
02610          XPutPixel(image, x, y, gCws->fNewColors[idx]);
02611       }
02612    }
02613 
02614    // put image back in pixmap on server
02615    XPutImage(fDisplay, gCws->fDrawing, *gGCpxmp, image, 0, 0, 0, 0,
02616              gCws->fWidth, gCws->fHeight);
02617    XFlush(fDisplay);
02618 
02619    // clean up
02620    if (tmpc) {
02621       if (fRedDiv == -1)
02622          XFreeColors(fDisplay, fColormap, tmpc, ntmpc, 0);
02623       delete [] tmpc;
02624    }
02625    XDestroyImage(image);
02626    ::operator delete(orgcolors);
02627 }
02628 
02629 //______________________________________________________________________________
02630 void TGX11::CollectImageColors(ULong_t pixel, ULong_t *&orgcolors, Int_t &ncolors,
02631                                Int_t &maxcolors)
02632 {
02633    // Collect in orgcolors all different original image colors.
02634 
02635    if (maxcolors == 0) {
02636       ncolors   = 0;
02637       maxcolors = 100;
02638       orgcolors = (ULong_t*) ::operator new(maxcolors*sizeof(ULong_t));
02639    }
02640 
02641    for (int i = 0; i < ncolors; i++)
02642       if (pixel == orgcolors[i]) return;
02643 
02644    if (ncolors >= maxcolors) {
02645       orgcolors = (ULong_t*) TStorage::ReAlloc(orgcolors,
02646           maxcolors*2*sizeof(ULong_t), maxcolors*sizeof(ULong_t));
02647       maxcolors *= 2;
02648    }
02649 
02650    orgcolors[ncolors++] = pixel;
02651 }
02652 
02653 //______________________________________________________________________________
02654 void TGX11::MakeOpaqueColors(Int_t percent, ULong_t *orgcolors, Int_t ncolors)
02655 {
02656    // Get RGB values for orgcolors, add percent neutral to the RGB and
02657    // allocate fNewColors.
02658 
02659    if (ncolors == 0) return;
02660 
02661    XColor *xcol = new XColor[ncolors];
02662 
02663    int i;
02664    for (i = 0; i < ncolors; i++) {
02665       xcol[i].pixel = orgcolors[i];
02666       xcol[i].red   = xcol[i].green = xcol[i].blue = 0;
02667       xcol[i].flags = DoRed | DoGreen | DoBlue;
02668    }
02669    QueryColors(fColormap, xcol, ncolors);
02670 
02671    UShort_t add = percent * kBIGGEST_RGB_VALUE / 100;
02672 
02673    Int_t val;
02674    for (i = 0; i < ncolors; i++) {
02675       val = xcol[i].red + add;
02676       if (val > kBIGGEST_RGB_VALUE) val = kBIGGEST_RGB_VALUE;
02677       xcol[i].red = (UShort_t) val;
02678       val = xcol[i].green + add;
02679       if (val > kBIGGEST_RGB_VALUE) val = kBIGGEST_RGB_VALUE;
02680       xcol[i].green = (UShort_t) val;
02681       val = xcol[i].blue + add;
02682       if (val > kBIGGEST_RGB_VALUE) val = kBIGGEST_RGB_VALUE;
02683       xcol[i].blue = (UShort_t) val;
02684       if (!AllocColor(fColormap, &xcol[i]))
02685          Warning("MakeOpaqueColors", "failed to allocate color %hd, %hd, %hd",
02686                  xcol[i].red, xcol[i].green, xcol[i].blue);
02687       // assumes that in case of failure xcol[i].pixel is not changed
02688    }
02689 
02690    gCws->fNewColors = new ULong_t[ncolors];
02691    gCws->fNcolors   = ncolors;
02692 
02693    for (i = 0; i < ncolors; i++)
02694       gCws->fNewColors[i] = xcol[i].pixel;
02695 
02696    delete [] xcol;
02697 }
02698 
02699 //______________________________________________________________________________
02700 Int_t TGX11::FindColor(ULong_t pixel, ULong_t *orgcolors, Int_t ncolors)
02701 {
02702    // Returns index in orgcolors (and fNewColors) for pixel.
02703 
02704    for (int i = 0; i < ncolors; i++)
02705       if (pixel == orgcolors[i]) return i;
02706 
02707    Error("FindColor", "did not find color, should never happen!");
02708 
02709    return 0;
02710 }
02711 
02712 //______________________________________________________________________________
02713 void TGX11::SetRGB(int cindex, float r, float g, float b)
02714 {
02715    // Set color intensities for given color index.
02716    // cindex     : color index
02717    // r,g,b      : red, green, blue intensities between 0.0 and 1.0
02718 
02719    if (fColormap) {
02720       XColor xcol;
02721       xcol.red   = (UShort_t)(r * kBIGGEST_RGB_VALUE);
02722       xcol.green = (UShort_t)(g * kBIGGEST_RGB_VALUE);
02723       xcol.blue  = (UShort_t)(b * kBIGGEST_RGB_VALUE);
02724       xcol.flags = DoRed | DoGreen | DoBlue;
02725       XColor_t &col = GetColor(cindex);
02726       if (col.fDefined) {
02727          // if color is already defined with same rgb just return
02728          if (col.fRed  == xcol.red && col.fGreen == xcol.green &&
02729              col.fBlue == xcol.blue)
02730             return;
02731          col.fDefined = kFALSE;
02732          if (fRedDiv == -1)
02733             XFreeColors(fDisplay, fColormap, &col.fPixel, 1, 0);
02734       }
02735       if (AllocColor(fColormap, &xcol)) {
02736          col.fDefined = kTRUE;
02737          col.fPixel   = xcol.pixel;
02738          col.fRed     = xcol.red;
02739          col.fGreen   = xcol.green;
02740          col.fBlue    = xcol.blue;
02741       }
02742    }
02743 }
02744 
02745 //______________________________________________________________________________
02746 void TGX11::SetTextAlign(Short_t talign)
02747 {
02748    // Set text alignment.
02749    // txalh   : horizontal text alignment
02750    // txalv   : vertical text alignment
02751 
02752    Int_t txalh = talign/10;
02753    Int_t txalv = talign%10;
02754    fTextAlignH = txalh;
02755    fTextAlignV = txalv;
02756 
02757    switch (txalh) {
02758 
02759       case 0 :
02760       case 1 :
02761          switch (txalv) {  //left
02762             case 1 :
02763                fTextAlign = 7;   //bottom
02764                break;
02765             case 2 :
02766                fTextAlign = 4;   //center
02767                break;
02768             case 3 :
02769                fTextAlign = 1;   //top
02770                break;
02771          }
02772          break;
02773       case 2 :
02774          switch (txalv) { //center
02775             case 1 :
02776                fTextAlign = 8;   //bottom
02777                break;
02778             case 2 :
02779                fTextAlign = 5;   //center
02780                break;
02781             case 3 :
02782                fTextAlign = 2;   //top
02783                break;
02784          }
02785          break;
02786       case 3 :
02787          switch (txalv) {  //right
02788             case 1 :
02789                fTextAlign = 9;   //bottom
02790                break;
02791             case 2 :
02792                fTextAlign = 6;   //center
02793                break;
02794             case 3 :
02795                fTextAlign = 3;   //top
02796                break;
02797          }
02798          break;
02799    }
02800 
02801    TAttText::SetTextAlign(fTextAlign);
02802 }
02803 
02804 //______________________________________________________________________________
02805 void TGX11::SetTextColor(Color_t cindex)
02806 {
02807    // Set color index for text.
02808 
02809    if (cindex < 0) return;
02810 
02811    TAttText::SetTextColor(cindex);
02812 
02813    SetColor(*gGCtext, Int_t(cindex));
02814 
02815    XGCValues values;
02816    if (XGetGCValues(fDisplay, *gGCtext, GCForeground | GCBackground, &values)) {
02817       XSetForeground( fDisplay, *gGCinvt, values.background );
02818       XSetBackground( fDisplay, *gGCinvt, values.foreground );
02819    } else {
02820       Error("SetTextColor", "cannot get GC values");
02821    }
02822    XSetBackground(fDisplay, *gGCtext, GetColor(0).fPixel);
02823 }
02824 
02825 //______________________________________________________________________________
02826 Int_t TGX11::SetTextFont(char *fontname, ETextSetMode mode)
02827 {
02828    // Set text font to specified name.
02829    // mode       : loading flag
02830    // mode=0     : search if the font exist (kCheck)
02831    // mode=1     : search the font and load it if it exists (kLoad)
02832    // font       : font name
02833    //
02834    // Set text font to specified name. This function returns 0 if
02835    // the specified font is found, 1 if not.
02836 
02837    char **fontlist;
02838    int fontcount;
02839    int i;
02840 
02841    if (mode == kLoad) {
02842       for (i = 0; i < kMAXFONT; i++) {
02843          if (strcmp(fontname, gFont[i].name) == 0) {
02844             gTextFont = gFont[i].id;
02845             XSetFont(fDisplay, *gGCtext, gTextFont->fid);
02846             XSetFont(fDisplay, *gGCinvt, gTextFont->fid);
02847             return 0;
02848          }
02849       }
02850    }
02851 
02852    fontlist = XListFonts(fDisplay, fontname, 1, &fontcount);
02853 
02854    if (fontcount != 0) {
02855       if (mode == kLoad) {
02856          if (gFont[gCurrentFontNumber].id)
02857             XFreeFont(fDisplay, gFont[gCurrentFontNumber].id);
02858          gTextFont = XLoadQueryFont(fDisplay, fontlist[0]);
02859          XSetFont(fDisplay, *gGCtext, gTextFont->fid);
02860          XSetFont(fDisplay, *gGCinvt, gTextFont->fid);
02861          gFont[gCurrentFontNumber].id = gTextFont;
02862          strlcpy(gFont[gCurrentFontNumber].name,fontname,80);
02863          gCurrentFontNumber++;
02864          if (gCurrentFontNumber == kMAXFONT) gCurrentFontNumber = 0;
02865       }
02866       XFreeFontNames(fontlist);
02867       return 0;
02868    } else {
02869       return 1;
02870    }
02871 }
02872 
02873 //______________________________________________________________________________
02874 void TGX11::SetTextFont(Font_t fontnumber)
02875 {
02876    // Set current text font number.
02877 
02878    fTextFont = fontnumber;
02879 }
02880 
02881 //______________________________________________________________________________
02882 void TGX11::SetTextSize(Float_t textsize)
02883 {
02884    // Set current text size.
02885 
02886    fTextSize = textsize;
02887 }
02888 
02889 //______________________________________________________________________________
02890 void TGX11::Sync(int mode)
02891 {
02892    // Set synchronisation on or off.
02893    // mode : synchronisation on/off
02894    //    mode=1  on
02895    //    mode<>0 off
02896 
02897    switch (mode) {
02898 
02899       case 1 :
02900          XSynchronize(fDisplay,1);
02901          break;
02902 
02903       default:
02904          XSynchronize(fDisplay,0);
02905          break;
02906    }
02907 }
02908 
02909 //______________________________________________________________________________
02910 void TGX11::UpdateWindow(int mode)
02911 {
02912    // Update display.
02913    // mode : (1) update
02914    //        (0) sync
02915    //
02916    // Synchronise client and server once (not permanent).
02917    // Copy the pixmap gCws->fDrawing on the window gCws->fWindow
02918    // if the double buffer is on.
02919 
02920    if (gCws->fDoubleBuffer) {
02921       XCopyArea(fDisplay, gCws->fDrawing, gCws->fWindow,
02922                 *gGCpxmp, 0, 0, gCws->fWidth, gCws->fHeight, 0, 0);
02923    }
02924    if (mode == 1) {
02925       XFlush(fDisplay);
02926    } else {
02927       XSync(fDisplay, False);
02928    }
02929 }
02930 
02931 //______________________________________________________________________________
02932 void TGX11::Warp(Int_t ix, Int_t iy, Window_t id)
02933 {
02934    // Set pointer position.
02935    // ix       : New X coordinate of pointer
02936    // iy       : New Y coordinate of pointer
02937    // Coordinates are relative to the origin of the window id
02938    // or to the origin of the current window if id == 0.
02939 
02940    if (!id) {
02941       // Causes problems when calling ProcessEvents()... BadWindow
02942       //XWarpPointer(fDisplay, None, gCws->fWindow, 0, 0, 0, 0, ix, iy);
02943    } else {
02944       XWarpPointer(fDisplay, None, (Window) id, 0, 0, 0, 0, ix, iy);
02945    }
02946 }
02947 
02948 //______________________________________________________________________________
02949 void TGX11::WritePixmap(int wid, unsigned int w, unsigned int h, char *pxname)
02950 {
02951    // Write the pixmap wid in the bitmap file pxname.
02952    // wid         : Pixmap address
02953    // w,h         : Width and height of the pixmap.
02954    // lenname     : pixmap name length
02955    // pxname      : pixmap name
02956 
02957    unsigned int wval, hval;
02958    wval = w;
02959    hval = h;
02960 
02961    gTws = &fWindows[wid];
02962    XWriteBitmapFile(fDisplay, pxname, gTws->fDrawing, wval, hval, -1, -1);
02963 }
02964 
02965 
02966 //
02967 // Functions for GIFencode()
02968 //
02969 
02970 static FILE *gOut;                      // output unit used WriteGIF and PutByte
02971 static XImage *gXimage = 0;             // image used in WriteGIF and GetPixel
02972 
02973 extern "C" {
02974    int GIFquantize(UInt_t width, UInt_t height, Int_t *ncol, Byte_t *red, Byte_t *green,
02975                    Byte_t *blue, Byte_t *outputBuf, Byte_t *outputCmap);
02976    long GIFencode(int Width, int Height, Int_t Ncol, Byte_t R[], Byte_t G[], Byte_t B[], Byte_t ScLine[],
02977                   void (*get_scline) (int, int, Byte_t *), void (*pb)(Byte_t));
02978    int GIFdecode(Byte_t *gifArr, Byte_t *pixArr, int *Width, int *Height, int *Ncols, Byte_t *R, Byte_t *G, Byte_t *B);
02979    int GIFinfo(Byte_t *gifArr, int *Width, int *Height, int *Ncols);
02980 }
02981 
02982 //______________________________________________________________________________
02983 static void GetPixel(int y, int width, Byte_t *scline)
02984 {
02985    // Get pixels in line y and put in array scline.
02986 
02987    for (int i = 0; i < width; i++)
02988       scline[i] = Byte_t(XGetPixel(gXimage, i, y));
02989 }
02990 
02991 //______________________________________________________________________________
02992 static void PutByte(Byte_t b)
02993 {
02994    // Put byte b in output stream.
02995 
02996    if (ferror(gOut) == 0) fputc(b, gOut);
02997 }
02998 
02999 //______________________________________________________________________________
03000 void TGX11::ImgPickPalette(XImage *image, Int_t &ncol, Int_t *&R, Int_t *&G, Int_t *&B)
03001 {
03002    // Returns in R G B the ncol colors of the palette used by the image.
03003    // The image pixels are changed to index values in these R G B arrays.
03004    // This produces a colormap with only the used colors (so even on displays
03005    // with more than 8 planes we will be able to create GIF's when the image
03006    // contains no more than 256 different colors). If it does contain more
03007    // colors we will have to use GIFquantize to reduce the number of colors.
03008    // The R G B arrays must be deleted by the caller.
03009 
03010    ULong_t *orgcolors = 0;
03011    Int_t    maxcolors = 0, ncolors;
03012 
03013    // collect different image colors
03014    int x, y;
03015    for (x = 0; x < (int) gCws->fWidth; x++) {
03016       for (y = 0; y < (int) gCws->fHeight; y++) {
03017          ULong_t pixel = XGetPixel(image, x, y);
03018          CollectImageColors(pixel, orgcolors, ncolors, maxcolors);
03019       }
03020    }
03021 
03022    // get RGB values belonging to pixels
03023    XColor *xcol = new XColor[ncolors];
03024 
03025    int i;
03026    for (i = 0; i < ncolors; i++) {
03027       xcol[i].pixel = orgcolors[i];
03028       xcol[i].red   = xcol[i].green = xcol[i].blue = 0;
03029       xcol[i].flags = DoRed | DoGreen | DoBlue;
03030    }
03031    QueryColors(fColormap, xcol, ncolors);
03032 
03033    // create RGB arrays and store RGB's for each color and set number of colors
03034    // (space must be delete by caller)
03035    R = new Int_t[ncolors];
03036    G = new Int_t[ncolors];
03037    B = new Int_t[ncolors];
03038 
03039    for (i = 0; i < ncolors; i++) {
03040       R[i] = xcol[i].red;
03041       G[i] = xcol[i].green;
03042       B[i] = xcol[i].blue;
03043    }
03044    ncol = ncolors;
03045 
03046    // update image with indices (pixels) into the new RGB colormap
03047    for (x = 0; x < (int) gCws->fWidth; x++) {
03048       for (y = 0; y < (int) gCws->fHeight; y++) {
03049          ULong_t pixel = XGetPixel(image, x, y);
03050          Int_t idx = FindColor(pixel, orgcolors, ncolors);
03051          XPutPixel(image, x, y, idx);
03052       }
03053    }
03054 
03055    // cleanup
03056    delete [] xcol;
03057    ::operator delete(orgcolors);
03058 }
03059 
03060 //______________________________________________________________________________
03061 Int_t TGX11::WriteGIF(char *name)
03062 {
03063    // Writes the current window into GIF file. Returns 1 in case of success,
03064    // 0 otherwise.
03065 
03066    Byte_t    scline[2000], r[256], b[256], g[256];
03067    Int_t    *red, *green, *blue;
03068    Int_t     ncol, maxcol, i;
03069 
03070    if (gXimage) {
03071       XDestroyImage(gXimage);
03072       gXimage = 0;
03073    }
03074 
03075    gXimage = XGetImage(fDisplay, gCws->fDrawing, 0, 0,
03076                        gCws->fWidth, gCws->fHeight,
03077                        AllPlanes, ZPixmap);
03078 
03079    ImgPickPalette(gXimage, ncol, red, green, blue);
03080 
03081    if (ncol > 256) {
03082       //GIFquantize(...);
03083       Error("WriteGIF", "can not create GIF of image containing more than 256 colors");
03084       delete [] red;
03085       delete [] green;
03086       delete [] blue;
03087       return 0;
03088    }
03089 
03090    maxcol = 0;
03091    for (i = 0; i < ncol; i++) {
03092       if (maxcol < red[i] )   maxcol = red[i];
03093       if (maxcol < green[i] ) maxcol = green[i];
03094       if (maxcol < blue[i] )  maxcol = blue[i];
03095       r[i] = 0;
03096       g[i] = 0;
03097       b[i] = 0;
03098    }
03099    if (maxcol != 0) {
03100       for (i = 0; i < ncol; i++) {
03101          r[i] = red[i] * 255/maxcol;
03102          g[i] = green[i] * 255/maxcol;
03103          b[i] = blue[i] * 255/maxcol;
03104       }
03105    }
03106 
03107    gOut = fopen(name, "w+");
03108 
03109    if (gOut) {
03110       GIFencode(gCws->fWidth, gCws->fHeight,
03111              ncol, r, g, b, scline, ::GetPixel, PutByte);
03112       fclose(gOut);
03113       i = 1;
03114    } else {
03115       Error("WriteGIF","cannot write file: %s",name);
03116       i = 0;
03117    }
03118    delete [] red;
03119    delete [] green;
03120    delete [] blue;
03121    return i;
03122 }
03123 
03124 //______________________________________________________________________________
03125 void TGX11::PutImage(int offset,int itran,int x0,int y0,int nx,int ny,int xmin,
03126                      int ymin,int xmax,int ymax, unsigned char *image,Drawable_t wid)
03127 {
03128    // Draw image.
03129 
03130    const int maxSegment = 20;
03131    int           i, n, x, y, xcur, x1, x2, y1, y2;
03132    unsigned char *jimg, *jbase, icol;
03133    int           nlines[256];
03134    XSegment      lines[256][maxSegment];
03135    Drawable_t    id;
03136 
03137    if (wid) {
03138       id = wid;
03139    } else {
03140       id = gCws->fDrawing;
03141    }
03142 
03143    for (i = 0; i < 256; i++) nlines[i] = 0;
03144 
03145    x1 = x0 + xmin; y1 = y0 + ny - ymax - 1;
03146    x2 = x0 + xmax; y2 = y0 + ny - ymin - 1;
03147    jbase = image + (ymin-1)*nx + xmin;
03148 
03149    for (y = y2; y >= y1; y--) {
03150       xcur = x1; jbase += nx;
03151       for (jimg = jbase, icol = *jimg++, x = x1+1; x <= x2; jimg++, x++) {
03152          if (icol != *jimg) {
03153             if (icol != itran) {
03154                n = nlines[icol]++;
03155                lines[icol][n].x1 = xcur; lines[icol][n].y1 = y;
03156                lines[icol][n].x2 = x-1;  lines[icol][n].y2 = y;
03157                if (nlines[icol] == maxSegment) {
03158                   SetColor(*gGCline,(int)icol+offset);
03159                   XDrawSegments(fDisplay,id,*gGCline,&lines[icol][0],
03160                                 maxSegment);
03161                   nlines[icol] = 0;
03162                }
03163             }
03164             icol = *jimg; xcur = x;
03165          }
03166       }
03167       if (icol != itran) {
03168          n = nlines[icol]++;
03169          lines[icol][n].x1 = xcur; lines[icol][n].y1 = y;
03170          lines[icol][n].x2 = x-1;  lines[icol][n].y2 = y;
03171          if (nlines[icol] == maxSegment) {
03172             SetColor(*gGCline,(int)icol+offset);
03173             XDrawSegments(fDisplay,id,*gGCline,&lines[icol][0],
03174                           maxSegment);
03175             nlines[icol] = 0;
03176          }
03177       }
03178    }
03179 
03180    for (i = 0; i < 256; i++) {
03181       if (nlines[i] != 0) {
03182          SetColor(*gGCline,i+offset);
03183          XDrawSegments(fDisplay,id,*gGCline,&lines[i][0],nlines[i]);
03184       }
03185    }
03186 }
03187 
03188 //______________________________________________________________________________
03189 Pixmap_t TGX11::ReadGIF(int x0, int y0, const char *file, Window_t id)
03190 {
03191    // If id is NULL - loads the specified gif file at position [x0,y0] in the
03192    // current window. Otherwise creates pixmap from gif file
03193 
03194    FILE  *fd;
03195    Seek_t filesize = 0;
03196    unsigned char *gifArr, *pixArr, red[256], green[256], blue[256], *j1, *j2, icol;
03197    int   i, j, k, width, height, ncolor, irep, offset;
03198    float rr, gg, bb;
03199    Pixmap_t pic = 0;
03200 
03201    fd = fopen(file, "r");
03202    if (!fd) {
03203       Error("ReadGIF", "unable to open GIF file");
03204       return pic;
03205    }
03206 
03207    fseek(fd, 0L, 2);
03208    long ft = ftell(fd);
03209    if (ft <=0) {
03210       Error("ReadGIF", "unable to open GIF file");
03211       fclose(fd);
03212       return pic;
03213    } else {
03214       filesize = Seek_t(ft);
03215    }
03216    fseek(fd, 0L, 0);
03217 
03218    if (!(gifArr = (unsigned char *) calloc(filesize+256,1))) {
03219       Error("ReadGIF", "unable to allocate array for gif");
03220       fclose(fd);
03221       return pic;
03222    }
03223 
03224    if (fread(gifArr, filesize, 1, fd) != 1) {
03225       Error("ReadGIF", "GIF file read failed");
03226       free(gifArr);
03227       fclose(fd);
03228       return pic;
03229    }
03230    fclose(fd);
03231 
03232    irep = GIFinfo(gifArr, &width, &height, &ncolor);
03233    if (irep != 0) {
03234       free(gifArr);
03235       return pic;
03236    }
03237 
03238    if (!(pixArr = (unsigned char *) calloc((width*height),1))) {
03239       Error("ReadGIF", "unable to allocate array for image");
03240       free(gifArr);
03241       return pic;
03242    }
03243 
03244    irep = GIFdecode(gifArr, pixArr, &width, &height, &ncolor, red, green, blue);
03245    if (irep != 0) {
03246       free(gifArr);
03247       free(pixArr);
03248       return pic;
03249    }
03250 
03251    // S E T   P A L E T T E
03252 
03253    offset = 8;
03254 
03255    for (i = 0; i < ncolor; i++) {
03256       rr = red[i]/255.;
03257       gg = green[i]/255.;
03258       bb = blue[i]/255.;
03259       j = i+offset;
03260       SetRGB(j,rr,gg,bb);
03261    }
03262 
03263    // O U T P U T   I M A G E
03264 
03265    for (i = 1; i <= height/2; i++) {
03266       j1 = pixArr + (i-1)*width;
03267       j2 = pixArr + (height-i)*width;
03268       for (k = 0; k < width; k++) {
03269          icol = *j1; *j1++ = *j2; *j2++ = icol;
03270       }
03271    }
03272    if (id) pic = CreatePixmap(id, width, height);
03273    PutImage(offset,-1,x0,y0,width,height,0,0,width-1,height-1,pixArr,pic);
03274 
03275    free(gifArr);
03276    free(pixArr);
03277 
03278    if (pic)
03279       return pic;
03280    else if (gCws->fDrawing)
03281       return (Pixmap_t)gCws->fDrawing;
03282    return 0;
03283 }
03284 
03285 //______________________________________________________________________________
03286 unsigned char *TGX11::GetColorBits(Drawable_t /*wid*/, Int_t /*x*/, Int_t /*y*/,
03287                                        UInt_t /*w*/, UInt_t /*h*/)
03288 {
03289    // Returns an array of pixels created from a part of drawable (defined by x, y, w, h)
03290    // in format:
03291    // b1, g1, r1, 0,  b2, g2, r2, 0 ... bn, gn, rn, 0 ..
03292    //
03293    // Pixels are numbered from left to right and from top to bottom.
03294    // By default all pixels from the whole drawable are returned.
03295    //
03296    // Note that return array is 32-bit aligned
03297 
03298    return 0;
03299 }
03300 
03301 //______________________________________________________________________________
03302 Pixmap_t TGX11::CreatePixmapFromData(unsigned char * /*bits*/, UInt_t /*width*/,
03303                                        UInt_t /*height*/)
03304 {
03305    // create pixmap from RGB data. RGB data is in format :
03306    // b1, g1, r1, 0,  b2, g2, r2, 0 ... bn, gn, rn, 0 ..
03307    //
03308    // Pixels are numbered from left to right and from top to bottom.
03309    // Note that data must be 32-bit aligned
03310 
03311    return (Pixmap_t)0;
03312 }
03313 
03314 //______________________________________________________________________________
03315 Int_t TGX11::AddPixmap(ULong_t pixid, UInt_t w, UInt_t h)
03316 {
03317    // Register pixmap created by gVirtualGL
03318    // w,h : Width and height of the pixmap.
03319    //register new pixmap
03320    Int_t wid = 0;
03321 
03322    // Select next free window number
03323    for (; wid < fMaxNumberOfWindows; ++wid)
03324       if (!fWindows[wid].fOpen)
03325          break;
03326 
03327    if (wid == fMaxNumberOfWindows) {
03328       Int_t newsize = fMaxNumberOfWindows + 10;
03329       fWindows = (XWindow_t*) TStorage::ReAlloc(
03330                                                 fWindows, newsize * sizeof(XWindow_t),
03331                                                 fMaxNumberOfWindows*sizeof(XWindow_t)
03332                                                );
03333 
03334       for (Int_t i = fMaxNumberOfWindows; i < newsize; ++i)
03335          fWindows[i].fOpen = 0;
03336 
03337       fMaxNumberOfWindows = newsize;
03338    }
03339 
03340    fWindows[wid].fOpen = 1;
03341    gCws = fWindows + wid;
03342    gCws->fWindow = pixid;
03343    gCws->fDrawing = gCws->fWindow;
03344    gCws->fBuffer = 0;
03345    gCws->fDoubleBuffer = 0;
03346    gCws->fIsPixmap = 1;
03347    gCws->fClip = 0;
03348    gCws->fWidth = w;
03349    gCws->fHeight = h;
03350    gCws->fNewColors = 0;
03351    gCws->fShared = kFALSE;
03352 
03353    return wid;
03354 }
03355 
03356 //______________________________________________________________________________
03357 Int_t TGX11::SupportsExtension(const char *ext) const
03358 {
03359    // Returns 1 if window system server supports extension given by the
03360    // argument, returns 0 in case extension is not supported and returns -1
03361    // in case of error (like server not initialized).
03362    // Examples:
03363    //   "Apple-WM" - does server run on MacOS X;
03364    //   "XINERAMA" - does server support Xinerama.
03365    // See also the output of xdpyinfo.
03366 
03367    Int_t major_opcode, first_event, first_error;
03368    if (!fDisplay)
03369       return -1;
03370    return XQueryExtension(fDisplay, ext, &major_opcode, &first_event, &first_error);
03371 }

Generated on Tue Jul 5 14:14:46 2011 for ROOT_528-00b_version by  doxygen 1.5.1