TGWin32.cxx

Go to the documentation of this file.
00001 // @(#)root/win32gdk:$Id: TGWin32.cxx 32927 2010-04-09 15:05:56Z couet $
00002 // Author: Rene Brun, Olivier Couet, Fons Rademakers, Valeri Onuchin, Bertrand Bellenot 27/11/01
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2001, 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 // TGWin32                                                              //
00015 //                                                                      //
00016 // This class is the basic interface to the Win32 graphics system.      //
00017 // It is  an implementation of the abstract TVirtualX class.            //
00018 //                                                                      //
00019 // This code was initially developed in the context of HIGZ and PAW     //
00020 // by Olivier Couet (package X11INT).                                   //
00021 //                                                                      //
00022 //////////////////////////////////////////////////////////////////////////
00023 
00024 #include "TGWin32.h"
00025 #include <stdio.h>
00026 #include <string.h>
00027 #include <stdlib.h>
00028 #include <ctype.h>
00029 #include <process.h>
00030 #include <wchar.h>
00031 #include "gdk/gdkkeysyms.h"
00032 #include "xatom.h"
00033 #include <winuser.h>
00034 
00035 #include "TROOT.h"
00036 #include "TApplication.h"
00037 #include "TColor.h"
00038 #include "TPoint.h"
00039 #include "TMath.h"
00040 #include "TStorage.h"
00041 #include "TStyle.h"
00042 #include "TSystem.h"
00043 #include "TGFrame.h"
00044 #include "TError.h"
00045 #include "TException.h"
00046 #include "TClassTable.h"
00047 #include "KeySymbols.h"
00048 #include "TWinNTSystem.h"
00049 #include "TGWin32VirtualXProxy.h"
00050 #include "TGWin32InterpreterProxy.h"
00051 #include "TWin32SplashThread.h"
00052 #include "TString.h"
00053 #include "TObjString.h"
00054 #include "TObjArray.h"
00055 #include "TExMap.h"
00056 #include "TEnv.h"
00057 #include "RStipples.h"
00058 #include "TEnv.h"
00059 
00060 // DND protocol version
00061 #define XDND_PROTOCOL_VERSION   5
00062 #ifndef IDC_HAND
00063 #define IDC_HAND  MAKEINTRESOURCE(32649)
00064 #endif
00065 
00066 extern "C" {
00067 void gdk_win32_draw_rectangle (GdkDrawable    *drawable,
00068                                       GdkGC          *gc,
00069                                       gint            filled,
00070                                       gint            x,
00071                                       gint            y,
00072                                       gint            width,
00073                                       gint            height);
00074 void gdk_win32_draw_arc       (GdkDrawable    *drawable,
00075                                       GdkGC          *gc,
00076                                       gint            filled,
00077                                       gint            x,
00078                                       gint            y,
00079                                       gint            width,
00080                                       gint            height,
00081                                       gint            angle1,
00082                                       gint            angle2);
00083 void gdk_win32_draw_polygon   (GdkDrawable    *drawable,
00084                                       GdkGC          *gc,
00085                                       gint            filled,
00086                                       GdkPoint       *points,
00087                                       gint            npoints);
00088 void gdk_win32_draw_text      (GdkDrawable    *drawable,
00089                                       GdkFont        *font,
00090                                       GdkGC          *gc,
00091                                       gint            x,
00092                                       gint            y,
00093                                       const gchar    *text,
00094                                       gint            text_length);
00095 void gdk_win32_draw_points    (GdkDrawable    *drawable,
00096                                       GdkGC          *gc,
00097                                       GdkPoint       *points,
00098                                       gint            npoints);
00099 void gdk_win32_draw_segments  (GdkDrawable    *drawable,
00100                                       GdkGC          *gc,
00101                                       GdkSegment     *segs,
00102                                       gint            nsegs);
00103 void gdk_win32_draw_lines     (GdkDrawable    *drawable,
00104                                       GdkGC          *gc,
00105                                       GdkPoint       *points,
00106                                       gint            npoints);
00107 
00108 };
00109 
00110 //////////// internal classes & structures (very private) ////////////////
00111 
00112 struct XWindow_t {
00113    Int_t    open;                 // 1 if the window is open, 0 if not
00114    Int_t    double_buffer;        // 1 if the double buffer is on, 0 if not
00115    Int_t    ispixmap;             // 1 if pixmap, 0 if not
00116    GdkDrawable *drawing;          // drawing area, equal to window or buffer
00117    GdkDrawable *window;           // win32 window
00118    GdkDrawable *buffer;           // pixmap used for double buffer
00119    UInt_t   width;                // width of the window
00120    UInt_t   height;               // height of the window
00121    Int_t    clip;                 // 1 if the clipping is on
00122    Int_t    xclip;                // x coordinate of the clipping rectangle
00123    Int_t    yclip;                // y coordinate of the clipping rectangle
00124    UInt_t   wclip;                // width of the clipping rectangle
00125    UInt_t   hclip;                // height of the clipping rectangle
00126    ULong_t *new_colors;           // new image colors (after processing)
00127    Int_t    ncolors;              // number of different colors
00128 };
00129 
00130 
00131 /////////////////////////////////// globals //////////////////////////////////
00132 int gdk_debug_level;
00133 
00134 namespace {
00135 /////////////////////////////////// globals //////////////////////////////////
00136 
00137 GdkAtom gClipboardAtom = GDK_NONE;
00138 static XWindow_t *gCws;         // gCws: pointer to the current window
00139 static XWindow_t *gTws;         // gTws: temporary pointer
00140 
00141 //
00142 // gColors[0]           : background also used for b/w screen
00143 // gColors[1]           : foreground also used for b/w screen
00144 // gColors[2..kMAXCOL-1]: colors which can be set by SetColor
00145 //
00146 const Int_t kBIGGEST_RGB_VALUE = 65535;
00147 //const Int_t kMAXCOL = 1000;
00148 //static struct {
00149 //   Int_t defined;
00150 //   GdkColor color;
00151 //} gColors[kMAXCOL];
00152 
00153 //
00154 // Primitives Graphic Contexts global for all windows
00155 //
00156 const int kMAXGC = 7;
00157 static GdkGC *gGClist[kMAXGC];
00158 static GdkGC *gGCline;          // = gGClist[0];  // PolyLines
00159 static GdkGC *gGCmark;          // = gGClist[1];  // PolyMarker
00160 static GdkGC *gGCfill;          // = gGClist[2];  // Fill areas
00161 static GdkGC *gGCtext;          // = gGClist[3];  // Text
00162 static GdkGC *gGCinvt;          // = gGClist[4];  // Inverse text
00163 static GdkGC *gGCdash;          // = gGClist[5];  // Dashed lines
00164 static GdkGC *gGCpxmp;          // = gGClist[6];  // Pixmap management
00165 
00166 static GdkGC *gGCecho;          // Input echo
00167 
00168 static Int_t gFillHollow;       // Flag if fill style is hollow
00169 static GdkPixmap *gFillPattern; // Fill pattern
00170 
00171 //
00172 // Text management
00173 //
00174 static char *gTextFont = "arial.ttf";      // Current font
00175 
00176 //
00177 // Markers
00178 //
00179 const Int_t kMAXMK = 100;
00180 static struct {
00181    int type;
00182    int n;
00183    GdkPoint xy[kMAXMK];
00184 } gMarker;                      // Point list to draw marker
00185 
00186 //
00187 // Keep style values for line GdkGC
00188 //
00189 static int  gLineStyle = GDK_LINE_SOLID;
00190 static int  gCapStyle  = GDK_CAP_BUTT;
00191 static int  gJoinStyle = GDK_JOIN_MITER;
00192 static char gDashList[10];
00193 static int  gDashLength = 0;
00194 static int  gDashOffset = 0;
00195 static int  gDashSize   = 0;
00196 
00197 //
00198 // Event masks
00199 //
00200 static ULong_t gMouseMask =
00201     GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK
00202     | GDK_LEAVE_NOTIFY_MASK | GDK_POINTER_MOTION_MASK | GDK_KEY_PRESS_MASK
00203     | GDK_KEY_RELEASE_MASK;
00204 static ULong_t gKeybdMask =
00205     GDK_BUTTON_PRESS_MASK | GDK_KEY_PRESS_MASK | GDK_ENTER_NOTIFY_MASK |
00206     GDK_LEAVE_NOTIFY_MASK;
00207 
00208 //
00209 // Data to create an invisible cursor
00210 //
00211 const char null_cursor_bits[] = {
00212    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00213    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00214    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
00215 };
00216 static GdkCursor *gNullCursor;
00217 
00218 static bool gdk_initialized = false;
00219 
00220 //---- MWM Hints stuff
00221 
00222 struct MWMHintsProperty_t {
00223    Handle_t fFlags;
00224    Handle_t fFunctions;
00225    Handle_t fDecorations;
00226    Int_t fInputMode;
00227 };
00228 
00229 //---- hints
00230 
00231 const ULong_t kMWMHintsFunctions = BIT(0);
00232 const ULong_t kMWMHintsDecorations = BIT(1);
00233 const ULong_t kMWMHintsInputMode = BIT(2);
00234 
00235 const Int_t kPropMotifWMHintsElements = 4;
00236 const Int_t kPropMWMHintElements = kPropMotifWMHintsElements;
00237 
00238 
00239 //---- Key symbol mapping
00240 
00241 struct KeySymbolMap_t {
00242    KeySym fXKeySym;
00243    EKeySym fKeySym;
00244 };
00245 
00246 static char *keyCodeToString[] = {
00247    "",                          /* 0x000 */
00248    "",                          /* 0x001, VK_LBUTTON */
00249    "",                          /* 0x002, VK_RBUTTON */
00250    "",                          /* 0x003, VK_CANCEL */
00251    "",                          /* 0x004, VK_MBUTTON */
00252    "",                          /* 0x005 */
00253    "",                          /* 0x006 */
00254    "",                          /* 0x007 */
00255    "\015",                      /* 0x008, VK_BACK */
00256    "\t",                        /* 0x009, VK_TAB */
00257    "",                          /* 0x00A */
00258    "",                          /* 0x00B */
00259    "",                          /* 0x00C, VK_CLEAR */
00260    "\r",                        /* 0x00D, VK_RETURN */
00261    "",                          /* 0x00E */
00262    "",                          /* 0x00F */
00263    "",                          /* 0x010, VK_SHIFT */
00264    "",                          /* 0x011, VK_CONTROL */
00265    "",                          /* 0x012, VK_MENU */
00266    "",                          /* 0x013, VK_PAUSE */
00267    "",                          /* 0x014, VK_CAPITAL */
00268    "",                          /* 0x015, VK_KANA */
00269    "",                          /* 0x016 */
00270    "",                          /* 0x017 */
00271    "",                          /* 0x018 */
00272    "",                          /* 0x019, VK_KANJI */
00273    "",                          /* 0x01A */
00274    "",                          /* 0x01B, VK_ESCAPE */
00275    "",                          /* 0x01C, VK_CONVERT */
00276    "",                          /* 0x01D, VK_NONCONVERT */
00277    "",                          /* 0x01E */
00278    "",                          /* 0x01F */
00279    " ",                         /* 0x020, VK_SPACE */
00280    "",                          /* 0x021, VK_PRIOR */
00281    "",                          /* 0x022, VK_NEXT */
00282    "",                          /* 0x023, VK_END */
00283    "",                          /* 0x024, VK_HOME */
00284    "",                          /* 0x025, VK_LEFT */
00285    "",                          /* 0x026, VK_UP */
00286    "",                          /* 0x027, VK_RIGHT */
00287    "",                          /* 0x028, VK_DOWN */
00288    "",                          /* 0x029, VK_SELECT */
00289    "",                          /* 0x02A, VK_PRINT */
00290    "",                          /* 0x02B, VK_EXECUTE */
00291    "",                          /* 0x02C, VK_SNAPSHOT */
00292    "",                          /* 0x02D, VK_INSERT */
00293    "\037",                      /* 0x02E, VK_DELETE */
00294    "",                          /* 0x02F, VK_HELP */
00295 };
00296 
00297 //---- Mapping table of all non-trivial mappings (the ASCII keys map
00298 //---- one to one so are not included)
00299 
00300 static KeySymbolMap_t gKeyMap[] = {
00301    {GDK_Escape, kKey_Escape},
00302    {GDK_Tab, kKey_Tab},
00303 #ifndef GDK_ISO_Left_Tab
00304    {0xFE20, kKey_Backtab},
00305 #else
00306    {GDK_ISO_Left_Tab, kKey_Backtab},
00307 #endif
00308    {GDK_BackSpace, kKey_Backspace},
00309    {GDK_Return, kKey_Return},
00310    {GDK_Insert, kKey_Insert},
00311    {GDK_Delete, kKey_Delete},
00312    {GDK_Clear, kKey_Delete},
00313    {GDK_Pause, kKey_Pause},
00314    {GDK_Print, kKey_Print},
00315    {0x1005FF60, kKey_SysReq},   // hardcoded Sun SysReq
00316    {0x1007ff00, kKey_SysReq},   // hardcoded X386 SysReq
00317    {GDK_Home, kKey_Home},       // cursor movement
00318    {GDK_End, kKey_End},
00319    {GDK_Left, kKey_Left},
00320    {GDK_Up, kKey_Up},
00321    {GDK_Right, kKey_Right},
00322    {GDK_Down, kKey_Down},
00323    {GDK_Prior, kKey_Prior},
00324    {GDK_Next, kKey_Next},
00325    {GDK_Shift_L, kKey_Shift},   // modifiers
00326    {GDK_Shift_R, kKey_Shift},
00327    {GDK_Shift_Lock, kKey_Shift},
00328    {GDK_Control_L, kKey_Control},
00329    {GDK_Control_R, kKey_Control},
00330    {GDK_Meta_L, kKey_Meta},
00331    {GDK_Meta_R, kKey_Meta},
00332    {GDK_Alt_L, kKey_Alt},
00333    {GDK_Alt_R, kKey_Alt},
00334    {GDK_Caps_Lock, kKey_CapsLock},
00335    {GDK_Num_Lock, kKey_NumLock},
00336    {GDK_Scroll_Lock, kKey_ScrollLock},
00337    {GDK_KP_Space, kKey_Space},  // numeric keypad
00338    {GDK_KP_Tab, kKey_Tab},
00339    {GDK_KP_Enter, kKey_Enter},
00340    {GDK_KP_Equal, kKey_Equal},
00341    {GDK_KP_Multiply, kKey_Asterisk},
00342    {GDK_KP_Add, kKey_Plus},
00343    {GDK_KP_Separator, kKey_Comma},
00344    {GDK_KP_Subtract, kKey_Minus},
00345    {GDK_KP_Decimal, kKey_Period},
00346    {GDK_KP_Divide, kKey_Slash},
00347    {0, (EKeySym) 0}
00348 };
00349 
00350 
00351 /////////////////////static auxilary functions /////////////////////////////////
00352 //______________________________________________________________________________
00353 static Int_t _lookup_string(Event_t * event, char *buf, Int_t buflen)
00354 {
00355    int i;
00356    int n = event->fUser[1];
00357    if (n > 0) {
00358       for (i = 0; i < n; i++) {
00359          buf[i] = event->fUser[2 + i];
00360       }
00361       buf[n] = 0;
00362    } else {
00363       buf[0] = 0;
00364    }
00365    if (event->fCode <= 0x20) {
00366       strncpy(buf, keyCodeToString[event->fCode], buflen - 1);
00367    }
00368    return n;
00369 }
00370 
00371 //______________________________________________________________________________
00372 inline void SplitLong(Long_t ll, Long_t & i1, Long_t & i2)
00373 {
00374    union {
00375       Long_t l;
00376       Int_t i[2];
00377    } conv;
00378 
00379    conv.l    = 0L;
00380    conv.i[0] = 0;
00381    conv.i[1] = 0;
00382 
00383    conv.l = ll;
00384    i1 = conv.i[0];
00385    i2 = conv.i[1];
00386 }
00387 
00388 //______________________________________________________________________________
00389 inline void AsmLong(Long_t i1, Long_t i2, Long_t & ll)
00390 {
00391    union {
00392       Long_t l;
00393       Int_t i[2];
00394    } conv;
00395 
00396    conv.i[0] = (Int_t) i1;
00397    conv.i[1] = (Int_t) i2;
00398    ll = conv.l;
00399 }
00400 
00401 //______________________________________________________________________________
00402 static BOOL CALLBACK EnumChildProc(HWND hwndChild, LPARAM lParam)
00403 {
00404    // Make sure the child window is visible.
00405 
00406    ::ShowWindow(hwndChild, SW_SHOWNORMAL);
00407    GdkWindow *child = gdk_window_lookup(hwndChild);
00408    if (child)
00409       ((GdkWindowPrivate *) child)->mapped = TRUE;
00410    return TRUE;
00411 }
00412 
00413 //______________________________________________________________________________
00414 static void _ChangeProperty(HWND w, char *np, char *dp, int n, Atom_t type)
00415 {
00416    HGLOBAL hMem;
00417    char *p;
00418 
00419    hMem = ::GetProp(w, np);
00420    if (hMem != NULL) {
00421       ::GlobalFree(hMem);
00422    }
00423    hMem = ::GlobalAlloc(GHND, n + sizeof(Atom_t));
00424    p = (char *) ::GlobalLock(hMem);
00425    memcpy(p, &type, sizeof(Atom_t));
00426    memcpy(p + sizeof(Atom_t), dp, n);
00427    ::GlobalUnlock(hMem);
00428    ::SetProp(w, np, hMem);
00429    ::GlobalFree(hMem);
00430 }
00431 
00432 //______________________________________________________________________________
00433 static void W32ChangeProperty(HWND w, Atom_t property, Atom_t type,
00434                        int format, int mode, const unsigned char *data,
00435                        int nelements)
00436 {
00437    //
00438 
00439    char *atomName;
00440    char buffer[256];
00441    char *p, *s;
00442    int len;
00443    char propName[32];
00444 
00445    if (mode == GDK_PROP_MODE_REPLACE || mode == GDK_PROP_MODE_PREPEND) {
00446       len = (int) ::GlobalGetAtomName(property, buffer, sizeof(buffer));
00447       if ((atomName = (char *) malloc(len + 1)) == NULL) {
00448          return;
00449       } else {
00450          strcpy(atomName, buffer);
00451       }
00452       sprintf(propName, "#0x%0.4x", atomName);
00453       _ChangeProperty(w, propName, (char *) data, nelements, type);
00454       free(atomName);
00455    }
00456 }
00457 
00458 //______________________________________________________________________________
00459 static int _GetWindowProperty(GdkWindow * id, Atom_t property, Long_t long_offset,
00460                        Long_t long_length, Bool_t delete_it, Atom_t req_type,
00461                        Atom_t * actual_type_return,
00462                        Int_t * actual_format_return, ULong_t * nitems_return,
00463                        ULong_t * bytes_after_return, UChar_t ** prop_return)
00464 {
00465    //
00466 
00467    if (!id) return 0;
00468 
00469    char *atomName;
00470    char *data, *destPtr;
00471    char propName[32];
00472    HGLOBAL handle;
00473    HGLOBAL hMem;
00474    HWND w;
00475 
00476    w = (HWND) GDK_DRAWABLE_XID(id);
00477 
00478    if (::IsClipboardFormatAvailable(CF_TEXT) && ::OpenClipboard(NULL)) {
00479       handle = ::GetClipboardData(CF_TEXT);
00480       if (handle != NULL) {
00481          data = (char *) ::GlobalLock(handle);
00482          *nitems_return = strlen(data);
00483          *prop_return = (UChar_t *) malloc(*nitems_return + 1);
00484          destPtr = (char *) *prop_return;
00485          while (*data != '\0') {
00486             if (*data != '\r') {
00487                *destPtr = *data;
00488                destPtr++;
00489             }
00490             data++;
00491          }
00492          *destPtr = '\0';
00493          ::GlobalUnlock(handle);
00494          *actual_type_return = XA_STRING;
00495          *bytes_after_return = 0;
00496       }
00497       ::CloseClipboard();
00498       return 1;
00499    }
00500    if (delete_it) {
00501       ::RemoveProp(w, propName);
00502    }
00503    return 1;
00504 }
00505 
00506 //______________________________________________________________________________
00507 static ULong_t GetPixelImage(Drawable_t id, Int_t x, Int_t y)
00508 {
00509    //
00510 
00511    if (!id) return 0;
00512 
00513    GdkImage *image = (GdkImage *)id;
00514    ULong_t pixel;
00515 
00516    if (image->depth == 1) {
00517       pixel = (((char *) image->mem)[y * image->bpl + (x >> 3)] & (1 << (7 - (x & 0x7)))) != 0;
00518    } else {
00519       UChar_t *pixelp = (UChar_t *) image->mem + y * image->bpl + x * image->bpp;
00520       switch (image->bpp) {
00521          case 1:
00522             pixel = *pixelp;
00523             break;
00524          // Windows is always LSB, no need to check image->byte_order.
00525          case 2:
00526             pixel = pixelp[0] | (pixelp[1] << 8);
00527             break;
00528          case 3:
00529             pixel = pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16);
00530             break;
00531          case 4:
00532             pixel = pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16);
00533             break;
00534       }
00535    }
00536    return pixel;
00537 }
00538 
00539 //______________________________________________________________________________
00540 static void CollectImageColors(ULong_t pixel, ULong_t * &orgcolors,
00541                                  Int_t & ncolors, Int_t & maxcolors)
00542 {
00543    // Collect in orgcolors all different original image colors.
00544 
00545    if (maxcolors == 0) {
00546       ncolors = 0;
00547       maxcolors = 100;
00548       orgcolors = (ULong_t*) ::operator new(maxcolors*sizeof(ULong_t));
00549    }
00550 
00551    for (int i = 0; i < ncolors; i++) {
00552       if (pixel == orgcolors[i]) return;
00553    }
00554    if (ncolors >= maxcolors) {
00555       orgcolors = (ULong_t *) TStorage::ReAlloc(orgcolors,
00556                                                 maxcolors * 2 *
00557                                                 sizeof(ULong_t),
00558                                                 maxcolors *
00559                                                 sizeof(ULong_t));
00560       maxcolors *= 2;
00561    }
00562    orgcolors[ncolors++] = pixel;
00563 }
00564 
00565 //______________________________________________________________________________
00566 static char *EventMask2String(UInt_t evmask)
00567 {
00568    // debug function for printing event mask
00569 
00570    static char bfr[500];
00571    char *p = bfr;
00572 
00573    *p = '\0';
00574 #define BITmask(x) \
00575   if (evmask & k##x##Mask) \
00576     p += sprintf (p, "%s" #x, (p > bfr ? " " : ""))
00577    BITmask(Exposure);
00578    BITmask(PointerMotion);
00579    BITmask(ButtonMotion);
00580    BITmask(ButtonPress);
00581    BITmask(ButtonRelease);
00582    BITmask(KeyPress);
00583    BITmask(KeyRelease);
00584    BITmask(EnterWindow);
00585    BITmask(LeaveWindow);
00586    BITmask(FocusChange);
00587    BITmask(StructureNotify);
00588 #undef BITmask
00589 
00590    return bfr;
00591 }
00592 
00593 ///////////////////////////////////////////////////////////////////////////////
00594 class TGWin32MainThread {
00595 
00596 public:
00597    void     *fHandle;                     // handle of server (aka command) thread
00598    DWORD    fId;                          // id of server (aka command) thread
00599    static LPCRITICAL_SECTION  fCritSec;      // general mutex
00600    static LPCRITICAL_SECTION  fMessageMutex; // message queue mutex
00601 
00602    TGWin32MainThread();
00603    ~TGWin32MainThread();
00604    static void LockMSG();
00605    static void UnlockMSG();
00606 };
00607 
00608 TGWin32MainThread *gMainThread = 0;
00609 LPCRITICAL_SECTION TGWin32MainThread::fCritSec = 0;
00610 LPCRITICAL_SECTION TGWin32MainThread::fMessageMutex = 0;
00611 
00612 
00613 //______________________________________________________________________________
00614 TGWin32MainThread::~TGWin32MainThread()
00615 {
00616    // dtor
00617 
00618    if (fCritSec) {
00619       ::LeaveCriticalSection(fCritSec);
00620       ::DeleteCriticalSection(fCritSec);
00621       delete fCritSec;
00622    }
00623    fCritSec = 0;
00624 
00625    if (fMessageMutex) {
00626       ::LeaveCriticalSection(fMessageMutex);
00627       ::DeleteCriticalSection(fMessageMutex);
00628       delete fMessageMutex;
00629    }
00630    fMessageMutex = 0;
00631 
00632    if(fHandle) {
00633       ::PostThreadMessage(fId, WM_QUIT, 0, 0);
00634       ::CloseHandle(fHandle);
00635    }
00636    fHandle = 0;
00637 }
00638 
00639 //______________________________________________________________________________
00640 void TGWin32MainThread::LockMSG()
00641 {
00642    // lock message queue
00643 
00644    if (fMessageMutex) ::EnterCriticalSection(fMessageMutex);
00645 }
00646 
00647 //______________________________________________________________________________
00648 void TGWin32MainThread::UnlockMSG()
00649 {
00650    // unlock message queue
00651 
00652    if (fMessageMutex) ::LeaveCriticalSection(fMessageMutex);
00653 }
00654 
00655 ///////////////////////////////////////////////////////////////////////////////
00656 class TGWin32RefreshTimer : public TTimer {
00657 
00658 public:
00659    TGWin32RefreshTimer() : TTimer(10, kTRUE) { if (gSystem) gSystem->AddTimer(this); }
00660    ~TGWin32RefreshTimer() { if (gSystem) gSystem->RemoveTimer(this); }
00661    Bool_t Notify()
00662    {
00663       Reset();
00664       MSG msg;
00665 
00666       while (::PeekMessage(&msg, NULL, NULL, NULL, PM_NOREMOVE)) {
00667          ::PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE);
00668          if (!gVirtualX)
00669             Sleep(200); // avoid start-up race
00670          if (gVirtualX)
00671             ((TGWin32*)gVirtualX)->GUIThreadMessageFunc(&msg);
00672       }
00673       return kFALSE;
00674    }
00675 };
00676 /*
00677 //______________________________________________________________________________
00678 static DWORD WINAPI MessageProcessingLoop(void *p)
00679 {
00680    // thread for processing windows messages (aka Main/Server thread)
00681 
00682    MSG msg;
00683    Int_t erret;
00684    Bool_t endLoop = kFALSE;
00685    TGWin32RefreshTimer *refersh = 0;
00686 
00687    // force to create message queue
00688    ::PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
00689 
00690    // periodically we refresh windows
00691    // Don't create refresh timer if the application has been created inside PVSS
00692    if (gApplication) {
00693       TString arg = gSystem->BaseName(gApplication->Argv(0));
00694       if (!arg.Contains("PVSS"))
00695          refersh = new TGWin32RefreshTimer();
00696    }
00697 
00698    while (!endLoop) {
00699       erret = ::GetMessage(&msg, NULL, NULL, NULL);
00700       if (erret <= 0) endLoop = kTRUE;
00701       endLoop = MessageProcessingFunc(&msg);
00702    }
00703 
00704    TGWin32::Instance()->CloseDisplay();
00705    if (refersh)
00706       delete refersh;
00707 
00708    // exit thread
00709    if (erret == -1) {
00710       erret = ::GetLastError();
00711       Error("MsgLoop", "Error in GetMessage");
00712       ::ExitThread(-1);
00713    } else {
00714       ::ExitThread(0);
00715    }
00716    return 0;
00717 }
00718 */
00719 
00720 Bool_t GUIThreadMessageWrapper(MSG* msg)
00721 {
00722    // Static wrapper for handling GUI messages.
00723    // Forwards from TWinNTSystem's GUIThreadMessageProcessingLoop()
00724    // to TGWin32::GUIThreadMessageFunc()
00725 
00726    return ((TGWin32*)gVirtualX)->GUIThreadMessageFunc(msg);
00727 }
00728 
00729 //______________________________________________________________________________
00730 TGWin32MainThread::TGWin32MainThread()
00731 {
00732    // constructor
00733 
00734    fCritSec = new CRITICAL_SECTION;
00735    ::InitializeCriticalSection(fCritSec);
00736    fMessageMutex = new CRITICAL_SECTION;
00737    ::InitializeCriticalSection(fMessageMutex);
00738    fHandle = ((TWinNTSystem*)gSystem)->GetGUIThreadHandle();
00739    fId = ((TWinNTSystem*)gSystem)->GetGUIThreadId();
00740    ((TWinNTSystem*)gSystem)->SetGUIThreadMsgHandler(GUIThreadMessageWrapper);
00741 }
00742 
00743 } // unnamed namespace
00744 
00745 ///////////////////////// TGWin32 implementation ///////////////////////////////
00746 ClassImp(TGWin32)
00747 
00748 //______________________________________________________________________________
00749 TGWin32::TGWin32(): fRefreshTimer(0)
00750 {
00751    // Default constructor.
00752 
00753    fScreenNumber = 0;
00754    fWindows      = 0;
00755    fColors       = 0;
00756 }
00757 
00758 //______________________________________________________________________________
00759 TGWin32::TGWin32(const char *name, const char *title) : TVirtualX(name,title), fRefreshTimer(0)
00760 {
00761    // Normal Constructor.
00762 
00763    fScreenNumber = 0;
00764    fHasTTFonts = kFALSE;
00765    fUseSysPointers = kFALSE;
00766    fTextAlignH = 1;
00767    fTextAlignV = 1;
00768    fTextAlign = 7;
00769    fTextMagnitude = 1;
00770    fCharacterUpX = 1;
00771    fCharacterUpY = 1;
00772    fDrawMode = kCopy;
00773    fWindows = 0;
00774    fMaxNumberOfWindows = 10;
00775    fXEvent = 0;
00776    fFillColorModified = kFALSE;
00777    fFillStyleModified = kFALSE;
00778    fLineColorModified = kFALSE;
00779    fPenModified = kFALSE;
00780    fMarkerStyleModified = kFALSE;
00781    fMarkerColorModified = kFALSE;
00782 
00783    fWindows = (XWindow_t*) TStorage::Alloc(fMaxNumberOfWindows*sizeof(XWindow_t));
00784    for (int i = 0; i < fMaxNumberOfWindows; i++) fWindows[i].open = 0;
00785 
00786    fColors = new TExMap;
00787 
00788    if (gApplication) {
00789       TString arg = gSystem->BaseName(gApplication->Argv(0));
00790       if (!arg.Contains("PVSS"))
00791          fRefreshTimer = new TGWin32RefreshTimer();
00792    } else {
00793       fRefreshTimer = new TGWin32RefreshTimer();
00794    }
00795 
00796    // initialize GUI thread and proxy objects
00797    if (!gROOT->IsBatch() && !gMainThread) {
00798       gMainThread = new TGWin32MainThread();
00799       TGWin32ProxyBase::fgMainThreadId = ::GetCurrentThreadId(); // gMainThread->fId;
00800       TGWin32VirtualXProxy::fgRealObject = this;
00801       gPtr2VirtualX = &TGWin32VirtualXProxy::ProxyObject;
00802       gPtr2Interpreter = &TGWin32InterpreterProxy::ProxyObject;
00803    }
00804 }
00805 
00806 //______________________________________________________________________________
00807 TGWin32::~TGWin32()
00808 {
00809    // destructor.
00810 
00811    CloseDisplay();
00812    if (fRefreshTimer)
00813       delete fRefreshTimer;
00814    if (!fColors) return;
00815    Long64_t key, value;
00816    TExMapIter it(fColors);
00817    while (it.Next(key, value)) {
00818       XColor_t *col = (XColor_t *) value;
00819       delete col;
00820    }
00821    delete fColors;
00822 }
00823 
00824 //______________________________________________________________________________
00825 VOID CALLBACK MyTimerProc(HWND hwnd, UINT message, UINT idTimer, DWORD dwTime)
00826 {
00827    // Windows timer handling events while moving/resizing windows
00828 
00829    gSystem->ProcessEvents();
00830    //gVirtualX->UpdateWindow(1); // cause problems with OpenGL in pad...
00831 } 
00832 
00833 //______________________________________________________________________________
00834 Bool_t TGWin32::GUIThreadMessageFunc(MSG* msg)
00835 {
00836    // Message processing function for the GUI thread.
00837    // Kicks in once TGWin32 becomes active, and "replaces" the dummy one
00838    // in TWinNTSystem; see TWinNTSystem.cxx's GUIThreadMessageProcessingLoop().
00839 
00840    Bool_t ret = kFALSE;
00841    static Int_t m_timer = 0;
00842 
00843    if ( (msg->message == WM_NCLBUTTONDOWN) ) {
00844       if (m_timer == 0)
00845          m_timer = SetTimer(NULL, 1, 20, (TIMERPROC) MyTimerProc);
00846    }
00847    else if (msg->message == WM_NCMOUSELEAVE ) {
00848       if (m_timer) {
00849          KillTimer(NULL, m_timer);
00850       }
00851       m_timer = 0;
00852    }
00853 
00854    if (msg->message == TGWin32ProxyBase::fgPostMessageId) {
00855       if (msg->wParam) {
00856          TGWin32ProxyBase *proxy = (TGWin32ProxyBase*)msg->wParam;
00857          proxy->ExecuteCallBack(kTRUE);
00858       } else {
00859          ret = kTRUE;
00860       }
00861    } else if (msg->message == TGWin32ProxyBase::fgPingMessageId) {
00862       TGWin32ProxyBase::GlobalUnlock();
00863    } else {
00864       //if ( (msg->message >= WM_NCMOUSEMOVE) &&
00865       //     (msg->message <= WM_NCMBUTTONDBLCLK) ) {
00866       //   TGWin32ProxyBase::GlobalLock();
00867       //}
00868       TGWin32MainThread::LockMSG();
00869       TranslateMessage(msg);
00870       DispatchMessage(msg);
00871       TGWin32MainThread::UnlockMSG();
00872    }
00873    return ret;
00874 }
00875 
00876 //______________________________________________________________________________
00877 Bool_t TGWin32::IsCmdThread() const
00878 {
00879    // returns kTRUE if we are inside cmd/server thread
00880 
00881    return ((::GetCurrentThreadId() == TGWin32ProxyBase::fgMainThreadId) ||
00882            (::GetCurrentThreadId() == TGWin32ProxyBase::fgUserThreadId));
00883 }
00884 
00885 //______________________________________________________________________________
00886 void TGWin32::CloseDisplay()
00887 {
00888    // close display (terminate server/gMainThread thread)
00889 
00890    // disable any processing while exiting
00891    TGWin32ProxyBase::GlobalLock();
00892 
00893    // terminate server thread
00894    gPtr2VirtualX = 0;
00895    gPtr2Interpreter = 0;
00896    gVirtualX = TGWin32VirtualXProxy::RealObject();
00897    gInterpreter = TGWin32InterpreterProxy::RealObject();
00898 
00899    // The lock above does not work, so at least
00900    // minimize the risk
00901    TGWin32MainThread *delThread = gMainThread;
00902    if (gMainThread) {
00903       gMainThread = 0;
00904       delete delThread;
00905    }
00906 
00907    TGWin32ProxyBase::fgMainThreadId = 0;
00908 
00909    // terminate ROOT logo splash thread
00910    TWin32SplashThread *delSplash = gSplash;
00911    if (gSplash) {
00912       gSplash = 0;
00913       delete delSplash;
00914    }
00915 
00916    if (fWindows) TStorage::Dealloc(fWindows);
00917    fWindows = 0;
00918 
00919    if (fXEvent) gdk_event_free((GdkEvent*)fXEvent);
00920 
00921    TGWin32ProxyBase::GlobalUnlock();
00922 
00923    gROOT->SetBatch(kTRUE); // no GUI is possible
00924 }
00925 
00926 //______________________________________________________________________________
00927 void  TGWin32::Lock()
00928 {
00929    //
00930 
00931    if (gMainThread && gMainThread->fCritSec) ::EnterCriticalSection(gMainThread->fCritSec);
00932 }
00933 
00934 //______________________________________________________________________________
00935 void TGWin32::Unlock()
00936 {
00937    //
00938 
00939    if (gMainThread && gMainThread->fCritSec) ::LeaveCriticalSection(gMainThread->fCritSec);
00940 }
00941 
00942 //______________________________________________________________________________
00943 Bool_t TGWin32::Init(void *display)
00944 {
00945    // Initialize Win32 system. Returns kFALSE in case of failure.
00946 
00947    if (!gdk_initialized) {
00948       if (!gdk_init_check(NULL, NULL)) return kFALSE;
00949       gdk_initialized = true;
00950    }
00951 
00952    if (!gClipboardAtom) {
00953       gClipboardAtom = gdk_atom_intern("CLIPBOARD", kFALSE);
00954    }
00955 
00956    return kTRUE;
00957 }
00958 
00959 //______________________________________________________________________________
00960 Int_t TGWin32::OpenDisplay(const char *dpyName)
00961 {
00962    // Open the display. Return -1 if the opening fails, 0 when ok.
00963 
00964    GdkPixmap *pixmp1, *pixmp2;
00965    GdkColor fore, back;
00966    GdkColor color;
00967    GdkGCValues gcvals;
00968    int i;
00969 
00970    if (!Init((void*)dpyName)) {
00971       return -1;
00972    }
00973 
00974    if (gDebug <= 4) {
00975       gdk_debug_level = gDebug;
00976    } else {
00977       gdk_debug_level = 0;
00978    }
00979 
00980    fore.red = fore.green = fore.blue = 0;
00981    back.red = back.green = back.blue = 0;
00982    color.red = color.green = color.blue = 0;
00983       
00984    fScreenNumber = 0;           //DefaultScreen(fDisplay);
00985    fVisual = gdk_visual_get_best();
00986    fColormap = gdk_colormap_get_system();
00987    fDepth = gdk_visual_get_best_depth();
00988 
00989    GetColor(1).fDefined = kTRUE; // default foreground
00990    gdk_color_black((GdkColormap *)fColormap, &GetColor(1).color);
00991 
00992    GetColor(0).fDefined = kTRUE; // default background
00993    gdk_color_white((GdkColormap *)fColormap, &GetColor(0).color);
00994 
00995    // Create primitives graphic contexts
00996    for (i = 0; i < kMAXGC; i++) {
00997       gGClist[i]  = gdk_gc_new(GDK_ROOT_PARENT());
00998       gdk_gc_set_foreground(gGClist[i], &GetColor(1).color);
00999       gdk_gc_set_background(gGClist[i], &GetColor(0).color);
01000    }
01001 
01002    gGCline = gGClist[0];        // PolyLines
01003    gGCmark = gGClist[1];        // PolyMarker
01004    gGCfill = gGClist[2];        // Fill areas
01005    gGCtext = gGClist[3];        // Text
01006    gGCinvt = gGClist[4];        // Inverse text
01007    gGCdash = gGClist[5];        // Dashed lines
01008    gGCpxmp = gGClist[6];        // Pixmap management
01009 
01010    gdk_gc_get_values(gGCtext, &gcvals);
01011    gdk_gc_set_foreground(gGCinvt, &gcvals.background);
01012    gdk_gc_set_background(gGCinvt, &gcvals.foreground);
01013 
01014    // Create input echo graphic context
01015    GdkGCValues echov;
01016    gdk_color_black(fColormap, &echov.foreground);       // = BlackPixel(fDisplay, fScreenNumber);
01017    gdk_color_white(fColormap, &echov.background);       // = WhitePixel(fDisplay, fScreenNumber);
01018    echov.function = GDK_INVERT;
01019    echov.subwindow_mode = GDK_CLIP_BY_CHILDREN;
01020    gGCecho =
01021        gdk_gc_new_with_values((GdkWindow *) GDK_ROOT_PARENT(), &echov,
01022                               (GdkGCValuesMask) (GDK_GC_FOREGROUND |
01023                                                  GDK_GC_BACKGROUND |
01024                                                  GDK_GC_FUNCTION |
01025                                                  GDK_GC_SUBWINDOW));
01026    // Create a null cursor
01027    pixmp1 = gdk_bitmap_create_from_data(GDK_ROOT_PARENT(),
01028                                        (const char *)null_cursor_bits, 16,16);
01029 
01030    pixmp2 = gdk_bitmap_create_from_data(GDK_ROOT_PARENT(),
01031                                        (const char *)null_cursor_bits, 16, 16);
01032 
01033    gNullCursor = gdk_cursor_new_from_pixmap((GdkDrawable *)pixmp1, (GdkDrawable *)pixmp2,
01034                                              &fore, &back, 0, 0);
01035    // Create cursors
01036    if (gEnv->GetValue("Win32.UseSysPointers", 0)) {
01037       fUseSysPointers = kTRUE;
01038       fCursors[kBottomLeft] = gdk_syscursor_new((ULong_t)IDC_SIZENESW);
01039       fCursors[kBottomRight] = gdk_syscursor_new((ULong_t)IDC_SIZENWSE);
01040       fCursors[kTopLeft] = gdk_syscursor_new((ULong_t)IDC_SIZENWSE);
01041       fCursors[kTopRight] = gdk_syscursor_new((ULong_t)IDC_SIZENESW);
01042       fCursors[kBottomSide] =  gdk_syscursor_new((ULong_t)IDC_SIZENS);
01043       fCursors[kLeftSide] = gdk_syscursor_new((ULong_t)IDC_SIZEWE);
01044       fCursors[kTopSide] = gdk_syscursor_new((ULong_t)IDC_SIZENS);
01045       fCursors[kRightSide] = gdk_syscursor_new((ULong_t)IDC_SIZEWE);
01046       fCursors[kMove] = gdk_syscursor_new((ULong_t)IDC_SIZEALL);
01047       fCursors[kCross] =gdk_syscursor_new((ULong_t)IDC_CROSS);
01048       fCursors[kArrowHor] = gdk_syscursor_new((ULong_t)IDC_SIZEWE);
01049       fCursors[kArrowVer] = gdk_syscursor_new((ULong_t)IDC_SIZENS);
01050       fCursors[kHand] = gdk_syscursor_new((ULong_t)IDC_HAND);
01051       fCursors[kPointer] = gdk_syscursor_new((ULong_t)IDC_ARROW);
01052       fCursors[kCaret] =  gdk_syscursor_new((ULong_t)IDC_IBEAM);
01053       fCursors[kWatch] = gdk_syscursor_new((ULong_t)IDC_WAIT);
01054       fCursors[kNoDrop] = gdk_syscursor_new((ULong_t)IDC_NO);
01055    }
01056    else {
01057       fUseSysPointers = kFALSE;
01058       fCursors[kBottomLeft] = gdk_cursor_new(GDK_BOTTOM_LEFT_CORNER);
01059       fCursors[kBottomRight] = gdk_cursor_new(GDK_BOTTOM_RIGHT_CORNER);
01060       fCursors[kTopLeft] = gdk_cursor_new(GDK_TOP_LEFT_CORNER);
01061       fCursors[kTopRight] = gdk_cursor_new(GDK_TOP_RIGHT_CORNER);
01062       fCursors[kBottomSide] =  gdk_cursor_new(GDK_BOTTOM_SIDE);
01063       fCursors[kLeftSide] = gdk_cursor_new(GDK_LEFT_SIDE);
01064       fCursors[kTopSide] = gdk_cursor_new(GDK_TOP_SIDE);
01065       fCursors[kRightSide] = gdk_cursor_new(GDK_RIGHT_SIDE);
01066       fCursors[kMove] = gdk_cursor_new(GDK_FLEUR);
01067       fCursors[kCross] =gdk_cursor_new(GDK_CROSSHAIR);
01068       fCursors[kArrowHor] = gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW);
01069       fCursors[kArrowVer] = gdk_cursor_new(GDK_SB_V_DOUBLE_ARROW);
01070       fCursors[kHand] = gdk_cursor_new(GDK_HAND2);
01071       fCursors[kPointer] = gdk_cursor_new(GDK_LEFT_PTR);
01072       fCursors[kCaret] =  gdk_cursor_new(GDK_XTERM);
01073       //fCursors[kWatch] = gdk_cursor_new(GDK_WATCH);
01074       fCursors[kWatch] = gdk_cursor_new(GDK_BUSY);
01075       fCursors[kNoDrop] = gdk_cursor_new(GDK_PIRATE);
01076    }
01077    fCursors[kRotate] = gdk_cursor_new(GDK_EXCHANGE);
01078    fCursors[kArrowRight] = gdk_cursor_new(GDK_ARROW);
01079 
01080    // Setup color information
01081    fRedDiv = fGreenDiv = fBlueDiv = fRedShift = fGreenShift = fBlueShift = -1;
01082 
01083    if ( gdk_visual_get_best_type() == GDK_VISUAL_TRUE_COLOR) {
01084       int i;
01085       for (i = 0; i < int(sizeof(fVisual->blue_mask)*kBitsPerByte); i++) {
01086          if (fBlueShift == -1 && ((fVisual->blue_mask >> i) & 1)) {
01087             fBlueShift = i;
01088          }
01089          if ((fVisual->blue_mask >> i) == 1) {
01090             fBlueDiv = sizeof(UShort_t)*kBitsPerByte - i - 1 + fBlueShift;
01091             break;
01092          }
01093       }
01094       for (i = 0; i < int(sizeof(fVisual->green_mask)*kBitsPerByte); i++) {
01095          if (fGreenShift == -1 && ((fVisual->green_mask >> i) & 1)) {
01096             fGreenShift = i;
01097          }
01098          if ((fVisual->green_mask >> i) == 1) {
01099             fGreenDiv = sizeof(UShort_t)*kBitsPerByte - i - 1 + fGreenShift;
01100             break;
01101          }
01102       }
01103       for (i = 0; i < int(sizeof(fVisual->red_mask)*kBitsPerByte); i++) {
01104          if (fRedShift == -1 && ((fVisual->red_mask >> i) & 1)) {
01105             fRedShift = i;
01106          }
01107          if ((fVisual->red_mask >> i) == 1) {
01108             fRedDiv = sizeof(UShort_t)*kBitsPerByte - i - 1 + fRedShift;
01109             break;
01110          }
01111       }
01112    }
01113 
01114    SetName("Win32TTF");
01115    SetTitle("ROOT interface to Win32 with TrueType fonts");
01116 
01117    if (!TTF::IsInitialized()) TTF::Init();
01118 
01119    if (fDepth > 8) {
01120       TTF::SetSmoothing(kTRUE);
01121    } else {
01122       TTF::SetSmoothing(kFALSE);
01123    }
01124 
01125    TGWin32VirtualXProxy::fMaxResponseTime = 1000;
01126    fHasTTFonts = kTRUE;
01127    return 0;
01128 }
01129 
01130 //______________________________________________________________________________
01131 Bool_t TGWin32::AllocColor(GdkColormap *cmap, GdkColor *color)
01132 {
01133    // Allocate color in colormap. If we are on an <= 8 plane machine
01134    // we will use XAllocColor. If we are on a >= 15 (15, 16 or 24) plane
01135    // true color machine we will calculate the pixel value using:
01136    // for 15 and 16 bit true colors have 6 bits precision per color however
01137    // only the 5 most significant bits are used in the color index.
01138    // Except for 16 bits where green uses all 6 bits. I.e.:
01139    //   15 bits = rrrrrgggggbbbbb
01140    //   16 bits = rrrrrggggggbbbbb
01141    // for 24 bits each r, g and b are represented by 8 bits.
01142    //
01143    // Since all colors are set with a max of 65535 (16 bits) per r, g, b
01144    // we just right shift them by 10, 11 and 10 bits for 16 planes, and
01145    // (10, 10, 10 for 15 planes) and by 8 bits for 24 planes.
01146    // Returns kFALSE in case color allocation failed.
01147 
01148    if (fRedDiv == -1) {
01149       if ( gdk_color_alloc((GdkColormap *)cmap, (GdkColor *)color) ) return kTRUE;
01150    } else {
01151       color->pixel = (color->red   >> fRedDiv)   << fRedShift |
01152                      (color->green >> fGreenDiv) << fGreenShift |
01153                      (color->blue  >> fBlueDiv)  << fBlueShift;
01154       return kTRUE;
01155    }
01156 
01157    return kFALSE;
01158 }
01159 
01160 //______________________________________________________________________________
01161 void TGWin32::QueryColors(GdkColormap *cmap, GdkColor *color, Int_t ncolors)
01162 {
01163    // Returns the current RGB value for the pixel in the XColor structure.
01164 
01165    ULong_t r, g, b;
01166 
01167    if (fRedDiv == -1) {
01168       GdkColorContext *cc = gdk_color_context_new(gdk_visual_get_system(), cmap);
01169       gdk_color_context_query_colors(cc, color, ncolors);
01170       gdk_color_context_free(cc);
01171    } else {
01172       for (Int_t i = 0; i < ncolors; i++) {
01173          r = (color[i].pixel & fVisual->red_mask) >> fRedShift;
01174          color[i].red = UShort_t(r*kBIGGEST_RGB_VALUE/(fVisual->red_mask >> fRedShift));
01175 
01176          g = (color[i].pixel & fVisual->green_mask) >> fGreenShift;
01177          color[i].green = UShort_t(g*kBIGGEST_RGB_VALUE/(fVisual->green_mask >> fGreenShift));
01178 
01179          b = (color[i].pixel & fVisual->blue_mask) >> fBlueShift;
01180          color[i].blue = UShort_t(b*kBIGGEST_RGB_VALUE/(fVisual->blue_mask >> fBlueShift));
01181       }
01182    }
01183 }
01184 
01185 //______________________________________________________________________________
01186 void TGWin32::Align(void)
01187 {
01188    // Compute alignment variables. The alignment is done on the horizontal string
01189    // then the rotation is applied on the alignment variables.
01190    // SetRotation and LayoutGlyphs should have been called before.
01191 
01192    EAlign align = (EAlign) fTextAlign;
01193 
01194    // vertical alignment
01195    if (align == kTLeft || align == kTCenter || align == kTRight) {
01196       fAlign.y = TTF::GetAscent();
01197    } else if (align == kMLeft || align == kMCenter || align == kMRight) {
01198       fAlign.y = TTF::GetAscent()/2;
01199    } else {
01200       fAlign.y = 0;
01201    }
01202    // horizontal alignment
01203    if (align == kTRight || align == kMRight || align == kBRight) {
01204       fAlign.x = TTF::GetWidth();
01205    } else if (align == kTCenter || align == kMCenter || align == kBCenter) {
01206       fAlign.x = TTF::GetWidth()/2;
01207    } else {
01208       fAlign.x = 0;
01209    }
01210 
01211    FT_Vector_Transform(&fAlign, TTF::GetRotMatrix());
01212    fAlign.x = fAlign.x >> 6;
01213    fAlign.y = fAlign.y >> 6;
01214 }
01215 
01216 //______________________________________________________________________________
01217 void TGWin32::DrawImage(FT_Bitmap *source, ULong_t fore, ULong_t back,
01218                          GdkImage *xim, Int_t bx, Int_t by)
01219 {
01220    // Draw FT_Bitmap bitmap to xim image at position bx,by using specified
01221    // foreground color.
01222 
01223    UChar_t d = 0, *s = source->buffer;
01224 
01225    if (TTF::GetSmoothing()) {
01226 
01227       static GdkColor col[5];
01228       GdkColor *bcol = 0, *bc;
01229       Int_t    x, y;
01230 
01231       // background kClear, i.e. transparent, we take as background color
01232       // the average of the rgb values of all pixels covered by this character
01233       if (back == (ULong_t) -1 && (UInt_t)source->width) {
01234          ULong_t r, g, b;
01235          Int_t   dots, dotcnt;
01236          const Int_t maxdots = 50000;
01237 
01238          dots = Int_t(source->width * source->rows);
01239          dots = dots > maxdots ? maxdots : dots;
01240          bcol = new GdkColor[dots];
01241          if (!bcol) return;
01242 
01243          bc = bcol;
01244          dotcnt = 0;
01245          for (y = 0; y < (int) source->rows; y++) {
01246             for (x = 0; x < (int) source->width; x++, bc++) {
01247                bc->pixel = GetPixelImage((Drawable_t)xim, bx + x, by + y);
01248                if (++dotcnt >= maxdots) break;
01249             }
01250          }
01251          QueryColors(fColormap, bcol, dots);
01252          r = g = b = 0;
01253          bc = bcol;
01254          dotcnt = 0;
01255          for (y = 0; y < (int) source->rows; y++) {
01256             for (x = 0; x < (int) source->width; x++, bc++) {
01257                r += bc->red;
01258                g += bc->green;
01259                b += bc->blue;
01260                if (++dotcnt >= maxdots) break;
01261             }
01262          }
01263          if (dots != 0) {
01264             r /= dots;
01265             g /= dots;
01266             b /= dots;
01267          }
01268          bc = &col[0];
01269          if (bc->red == r && bc->green == g && bc->blue == b) {
01270             bc->pixel = back;
01271          } else {
01272             bc->pixel = ~back;
01273             bc->red   = (UShort_t) r;
01274             bc->green = (UShort_t) g;
01275             bc->blue  = (UShort_t) b;
01276          }
01277       }
01278       delete [] bcol;
01279 
01280       // if fore or background have changed from previous character
01281       // recalculate the 3 smooting colors (interpolation between fore-
01282       // and background colors)
01283       if (fore != col[4].pixel || back != col[0].pixel) {
01284          col[4].pixel = fore;
01285          if (back != (ULong_t) -1) {
01286             col[3].pixel = back;
01287             QueryColors(fColormap, &col[3], 2);
01288             col[0] = col[3];
01289          } else {
01290             QueryColors(fColormap, &col[4], 1);
01291          }
01292 
01293          // interpolate between fore and backgound colors
01294          for (x = 3; x > 0; x--) {
01295             col[x].red   = (col[4].red  *x + col[0].red  *(4-x)) /4;
01296             col[x].green = (col[4].green*x + col[0].green*(4-x)) /4;
01297             col[x].blue  = (col[4].blue *x + col[0].blue *(4-x)) /4;
01298             if (!AllocColor(fColormap, &col[x])) {
01299                Warning("DrawImage", "cannot allocate smoothing color");
01300                col[x].pixel = col[x+1].pixel;
01301             }
01302          }
01303       }
01304 
01305       // put smoothed character, character pixmap values are an index
01306       // into the 5 colors used for aliasing (4 = foreground, 0 = background)
01307       for (y = 0; y < (int) source->rows; y++) {
01308          for (x = 0; x < (int) source->width; x++) {
01309             d = *s++ & 0xff;
01310             d = ((d + 10) * 5) / 256;
01311             if (d > 4) d = 4;
01312             if (d && x < (int) source->width) {
01313                ULong_t p = col[d].pixel;
01314                PutPixel((Drawable_t)xim, bx + x, by + y, p);
01315             }
01316          }
01317       }
01318    } else {
01319       // no smoothing, just put character using foreground color
01320       UChar_t* row=s;
01321       for (int y = 0; y < (int) source->rows; y++) {
01322          int n = 0;
01323          s = row;
01324          for (int x = 0; x < (int) source->width; x++) {
01325             if (n == 0) d = *s++;
01326             if (TESTBIT(d,7-n)) {
01327                PutPixel((Drawable_t)xim, bx + x, by + y, fore);
01328             }
01329             if (++n == (int) kBitsPerByte) n = 0;
01330          }
01331          row += source->pitch;
01332       }
01333    }
01334 }
01335 
01336 //______________________________________________________________________________
01337 void TGWin32::DrawText(Int_t x, Int_t y, Float_t angle, Float_t mgn,
01338                        const char *text, ETextMode mode)
01339 {
01340    // Draw text using TrueType fonts. If TrueType fonts are not available the
01341    // text is drawn with TGWin32::DrawText.
01342 
01343    if (!TTF::IsInitialized()) TTF::Init();
01344    TTF::SetRotationMatrix(angle);
01345    TTF::PrepareString(text);
01346    TTF::LayoutGlyphs();
01347    Align();
01348    RenderString(x, y, mode);
01349 }
01350 
01351 //______________________________________________________________________________
01352 GdkImage *TGWin32::GetBackground(Int_t x, Int_t y, UInt_t w, UInt_t h)
01353 {
01354    // Get the background of the current window in an XImage.
01355 
01356    Window_t cws = GetCurrentWindow();
01357    UInt_t width;
01358    UInt_t height;
01359    Int_t xy;
01360    gVirtualX->GetWindowSize(cws, xy, xy, width, height);
01361 
01362    if (x < 0) {
01363       w += x;
01364       x  = 0;
01365    }
01366    if (y < 0) {
01367       h += y;
01368       y  = 0;
01369    }
01370 
01371    if (x+w > width)  w = width - x;
01372    if (y+h > height) h = height - y;
01373 
01374    return gdk_image_get((GdkDrawable*)cws, x, y, w, h);
01375 }
01376 
01377 //______________________________________________________________________________
01378 Bool_t TGWin32::IsVisible(Int_t x, Int_t y, UInt_t w, UInt_t h)
01379 {
01380    // Test if there is really something to render
01381 
01382    Window_t cws = GetCurrentWindow();
01383    UInt_t width;
01384    UInt_t height;
01385    Int_t xy;
01386    gVirtualX->GetWindowSize(cws, xy, xy, width, height);
01387 
01388    // If w or h is 0, very likely the string is only blank characters
01389    if ((int)w == 0 || (int)h == 0)  return kFALSE;
01390 
01391    // If string falls outside window, there is probably no need to draw it.
01392    if (x + (int)w <= 0 || x >= (int)width)  return kFALSE;
01393    if (y + (int)h <= 0 || y >= (int)height) return kFALSE;
01394 
01395    return kTRUE;
01396 }
01397 
01398 //______________________________________________________________________________
01399 void TGWin32::RenderString(Int_t x, Int_t y, ETextMode mode)
01400 {
01401    // Perform the string rendering in the pad.
01402    // LayoutGlyphs should have been called before.
01403 
01404    TTGlyph* glyph = TTF::GetGlyphs();
01405    GdkGCValues gcvals;
01406 
01407    // compute the size and position of the XImage that will contain the text
01408    Int_t Xoff = 0; if (TTF::GetBox().xMin < 0) Xoff = -TTF::GetBox().xMin;
01409    Int_t Yoff = 0; if (TTF::GetBox().yMin < 0) Yoff = -TTF::GetBox().yMin;
01410    Int_t w    = TTF::GetBox().xMax + Xoff;
01411    Int_t h    = TTF::GetBox().yMax + Yoff;
01412    Int_t x1   = x-Xoff-fAlign.x;
01413    Int_t y1   = y+Yoff+fAlign.y-h;
01414 
01415    if (!IsVisible(x1, y1, w, h)) {
01416        return;
01417    }
01418 
01419    // create the XImage that will contain the text
01420    UInt_t depth = fDepth;
01421    GdkImage *xim  = gdk_image_new(GDK_IMAGE_SHARED, gdk_visual_get_best(), w, h);
01422 
01423    // use malloc since Xlib will use free() in XDestroyImage
01424 //   xim->data = (char *) malloc(xim->bytes_per_line * h);
01425 //   memset(xim->data, 0, xim->bytes_per_line * h);
01426 
01427    ULong_t   pixel;
01428    ULong_t   bg;
01429 
01430    gdk_gc_get_values((GdkGC*)GetGC(3), &gcvals);
01431 
01432    // get the background
01433    if (mode == kClear) {
01434       // if mode == kClear we need to get an image of the background
01435       GdkImage *bim = GetBackground(x1, y1, w, h);
01436       if (!bim) {
01437          Error("DrawText", "error getting background image");
01438          return;
01439       }
01440 
01441       // and copy it into the text image
01442       Int_t xo = 0, yo = 0;
01443       if (x1 < 0) xo = -x1;
01444       if (y1 < 0) yo = -y1;
01445 
01446       for (int yp = 0; yp < (int) bim->height; yp++) {
01447          for (int xp = 0; xp < (int) bim->width; xp++) {
01448             pixel = GetPixelImage((Drawable_t)bim, xp, yp);
01449             PutPixel((Drawable_t)xim, xo+xp, yo+yp, pixel);
01450          }
01451       }
01452 
01453       gdk_image_unref((GdkImage *)bim);
01454 
01455       bg = (ULong_t) -1;
01456    } else {
01457       // if mode == kOpaque its simple, we just draw the background
01458 
01459       GdkImage *bim = GetBackground(x1, y1, w, h);
01460       if (!bim) {
01461          pixel = gcvals.background.pixel;
01462       } else {
01463          pixel = GetPixelImage((Drawable_t)bim, 0, 0);
01464       }
01465       Int_t xo = 0, yo = 0;
01466       if (x1 < 0) xo = -x1;
01467       if (y1 < 0) yo = -y1;
01468 
01469       for (int yp = 0; yp < h; yp++) {
01470          for (int xp = 0; xp < (int) w; xp++) {
01471             PutPixel((Drawable_t)xim, xo+xp, yo+yp, pixel);
01472          }
01473       }
01474       if (bim) {
01475          gdk_image_unref((GdkImage *)bim);
01476          bg = (ULong_t) -1;
01477       } else {
01478          bg = pixel;
01479       }
01480    }
01481 
01482    // paint the glyphs in the XImage
01483    glyph = TTF::GetGlyphs();
01484    for (int n = 0; n < TTF::GetNumGlyphs(); n++, glyph++) {
01485       if (FT_Glyph_To_Bitmap(&glyph->fImage,
01486                              TTF::GetSmoothing() ? ft_render_mode_normal
01487                                               : ft_render_mode_mono,
01488                              0, 1 )) continue;
01489       FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyph->fImage;
01490       FT_Bitmap*     source = &bitmap->bitmap;
01491       Int_t          bx, by;
01492 
01493       bx = bitmap->left+Xoff;
01494       by = h - bitmap->top-Yoff;
01495       DrawImage(source, gcvals.foreground.pixel, bg, xim, bx, by);
01496    }
01497 
01498    // put the Ximage on the screen
01499    Window_t cws = GetCurrentWindow();
01500    gdk_draw_image((GdkDrawable *)cws, GetGC(6), xim, 0, 0, x1, y1, w, h);
01501 
01502    gdk_image_unref(xim);
01503 }
01504 
01505 //______________________________________________________________________________
01506 void TGWin32::SetTextFont(Font_t fontnumber)
01507 {
01508    // Set specified font.
01509 
01510    fTextFont = fontnumber;
01511    TTF::SetTextFont(fontnumber);
01512 }
01513 
01514 //______________________________________________________________________________
01515 Int_t TGWin32::SetTextFont(char *fontname, ETextSetMode mode)
01516 {
01517    // Set text font to specified name.
01518    // mode       : loading flag
01519    // mode=0     : search if the font exist (kCheck)
01520    // mode=1     : search the font and load it if it exists (kLoad)
01521    // font       : font name
01522    //
01523    // Set text font to specified name. This function returns 0 if
01524    // the specified font is found, 1 if not.
01525 
01526    return TTF::SetTextFont(fontname);
01527 }
01528 
01529 //______________________________________________________________________________
01530 void TGWin32::SetTextSize(Float_t textsize)
01531 {
01532    // Set current text size.
01533 
01534    fTextSize = textsize;
01535    TTF::SetTextSize(textsize);
01536 }
01537 
01538 //______________________________________________________________________________
01539 void TGWin32::ClearWindow()
01540 {
01541    // Clear current window.
01542 
01543    if (!fWindows) return;
01544 
01545    if (!gCws->ispixmap && !gCws->double_buffer) {
01546       gdk_window_set_background(gCws->drawing, (GdkColor *) & GetColor(0).color);
01547       gdk_window_clear(gCws->drawing);
01548       GdiFlush();
01549    } else {
01550       SetColor(gGCpxmp, 0);
01551       gdk_win32_draw_rectangle(gCws->drawing, gGCpxmp, 1,
01552                          0, 0, gCws->width, gCws->height);
01553       SetColor(gGCpxmp, 1);
01554    }
01555 }
01556 
01557 //______________________________________________________________________________
01558 void TGWin32::ClosePixmap()
01559 {
01560    // Delete current pixmap.
01561 
01562    CloseWindow1();
01563 }
01564 
01565 //______________________________________________________________________________
01566 void TGWin32::CloseWindow()
01567 {
01568    // Delete current window.
01569 
01570    CloseWindow1();
01571 }
01572 
01573 //______________________________________________________________________________
01574 void TGWin32::CloseWindow1()
01575 {
01576    // Delete current window.
01577 
01578    int wid;
01579 
01580    if (gCws->ispixmap) {
01581       gdk_pixmap_unref(gCws->window);
01582    } else {
01583       gdk_window_destroy(gCws->window, kTRUE);
01584    }
01585 
01586    if (gCws->buffer) {
01587       gdk_pixmap_unref(gCws->buffer);
01588    }
01589    if (gCws->new_colors) {
01590       gdk_colormap_free_colors((GdkColormap *) fColormap,
01591                                (GdkColor *)gCws->new_colors, gCws->ncolors);
01592 
01593       delete [] gCws->new_colors;
01594       gCws->new_colors = 0;
01595    }
01596 
01597    GdiFlush();
01598    gCws->open = 0;
01599 
01600    if (!fWindows) return;
01601 
01602    // make first window in list the current window
01603    for (wid = 0; wid < fMaxNumberOfWindows; wid++) {
01604       if (fWindows[wid].open) {
01605          gCws = &fWindows[wid];
01606          return;
01607       }
01608    }
01609    gCws = 0;
01610 }
01611 
01612 //______________________________________________________________________________
01613 void TGWin32::CopyPixmap(int wid, int xpos, int ypos)
01614 {
01615    // Copy the pixmap wid at the position xpos, ypos in the current window.
01616 
01617    if (!fWindows) return;
01618 
01619    gTws = &fWindows[wid];
01620    gdk_window_copy_area(gCws->drawing, gGCpxmp, xpos, ypos, gTws->drawing,
01621                         0, 0, gTws->width, gTws->height);
01622    GdiFlush();
01623 }
01624 
01625 //______________________________________________________________________________
01626 void TGWin32::DrawBox(int x1, int y1, int x2, int y2, EBoxMode mode)
01627 {
01628    // Draw a box.
01629    // mode=0 hollow  (kHollow)
01630    // mode=1 solid   (kSolid)
01631 
01632    if (!fWindows) return;
01633 
01634    Int_t x = TMath::Min(x1, x2);
01635    Int_t y = TMath::Min(y1, y2);
01636    Int_t w = TMath::Abs(x2 - x1);
01637    Int_t h = TMath::Abs(y2 - y1);
01638 
01639    switch (mode) {
01640 
01641    case kHollow:
01642       if (fLineColorModified) UpdateLineColor();
01643       if (fPenModified) UpdateLineStyle();
01644       gdk_win32_draw_rectangle(gCws->drawing, gGCline, 0, x, y, w, h);
01645       break;
01646 
01647    case kFilled:
01648       if (fFillStyleModified) UpdateFillStyle();
01649       if (fFillColorModified) UpdateFillColor();
01650       gdk_win32_draw_rectangle(gCws->drawing, gGCfill, 1, x, y, w, h);
01651       break;
01652 
01653    default:
01654       break;
01655    }
01656 }
01657 
01658 //______________________________________________________________________________
01659 void TGWin32::DrawCellArray(Int_t x1, Int_t y1, Int_t x2, Int_t y2,
01660                             Int_t nx, Int_t ny, Int_t *ic)
01661 {
01662    // Draw a cell array.
01663    // x1,y1        : left down corner
01664    // x2,y2        : right up corner
01665    // nx,ny        : array size
01666    // ic           : array
01667    //
01668    // Draw a cell array. The drawing is done with the pixel presicion
01669    // if (X2-X1)/NX (or Y) is not a exact pixel number the position of
01670    // the top rigth corner may be wrong.
01671 
01672    int i, j, icol, ix, iy, w, h, current_icol;
01673 
01674    if (!fWindows) return;
01675 
01676    current_icol = -1;
01677    w = TMath::Max((x2 - x1) / (nx), 1);
01678    h = TMath::Max((y1 - y2) / (ny), 1);
01679    ix = x1;
01680 
01681    if (fFillStyleModified) UpdateFillStyle();
01682    if (fFillColorModified) UpdateFillColor();
01683 
01684    for (i = 0; i < nx; i++) {
01685       iy = y1 - h;
01686       for (j = 0; j < ny; j++) {
01687          icol = ic[i + (nx * j)];
01688          if (icol != current_icol) {
01689             gdk_gc_set_foreground(gGCfill, (GdkColor *) & GetColor(icol).color);
01690             current_icol = icol;
01691          }
01692 
01693          gdk_win32_draw_rectangle(gCws->drawing, gGCfill, kTRUE, ix,  iy, w, h);
01694          iy = iy - h;
01695       }
01696       ix = ix + w;
01697    }
01698 }
01699 
01700 //______________________________________________________________________________
01701 void TGWin32::DrawFillArea(int n, TPoint *xyt)
01702 {
01703    // Fill area described by polygon.
01704    // n         : number of points
01705    // xy(2,n)   : list of points
01706 
01707    int i;
01708    static int lastn = 0;
01709    static GdkPoint *xy = 0;
01710 
01711    if (!fWindows) return;
01712 
01713    if (fFillStyleModified) UpdateFillStyle();
01714    if (fFillColorModified) UpdateFillColor();
01715 
01716    if (lastn!=n) {
01717       delete [] (GdkPoint *)xy;
01718       xy = new GdkPoint[n];
01719       lastn = n;
01720    }
01721    for (i = 0; i < n; i++) {
01722       xy[i].x = xyt[i].fX;
01723       xy[i].y = xyt[i].fY;
01724    }
01725 
01726    if (gFillHollow) {
01727       gdk_win32_draw_lines(gCws->drawing, gGCfill, xy, n);
01728    } else {
01729       gdk_win32_draw_polygon(gCws->drawing, gGCfill, 1, xy, n);
01730    }
01731 }
01732 
01733 //______________________________________________________________________________
01734 void TGWin32::DrawLine(int x1, int y1, int x2, int y2)
01735 {
01736    // Draw a line.
01737    // x1,y1        : begin of line
01738    // x2,y2        : end of line
01739 
01740    if (!fWindows) return;
01741 
01742    if (fLineColorModified) UpdateLineColor();
01743    if (fPenModified) UpdateLineStyle();
01744 
01745    if (gLineStyle == GDK_LINE_SOLID) {
01746       gdk_draw_line(gCws->drawing, gGCline, x1, y1, x2, y2);
01747    } else {
01748       int i;
01749       gint8 dashes[32];
01750       for (i = 0; i < gDashSize; i++) {
01751          dashes[i] = (gint8) gDashList[i];
01752       }
01753       for (i = gDashSize; i < 32; i++) {
01754          dashes[i] = (gint8) 0;
01755       }
01756       gdk_gc_set_dashes(gGCdash, gDashOffset, dashes, gDashSize);
01757       gdk_draw_line(gCws->drawing, gGCdash, x1, y1, x2, y2);
01758    }
01759 }
01760 
01761 //______________________________________________________________________________
01762 void TGWin32::DrawPolyLine(int n, TPoint * xyt)
01763 {
01764    // Draw a line through all points.
01765    // n         : number of points
01766    // xy        : list of points
01767 
01768    int i;
01769 
01770    if (!fWindows) return;
01771 
01772    Point_t *xy = new Point_t[n];
01773 
01774    for (i = 0; i < n; i++) {
01775       xy[i].fX = xyt[i].fX;
01776       xy[i].fY = xyt[i].fY;
01777    }
01778 
01779    if (fLineColorModified) UpdateLineColor();
01780    if (fPenModified) UpdateLineStyle();
01781 
01782    if (n > 1) {
01783       if (gLineStyle == GDK_LINE_SOLID) {
01784          gdk_win32_draw_lines(gCws->drawing, gGCline, (GdkPoint *)xy, n);
01785       } else {
01786          int i;
01787          gint8 dashes[32];
01788 
01789          for (i = 0; i < gDashSize; i++) {
01790             dashes[i] = (gint8) gDashList[i];
01791          }
01792          for (i = gDashSize; i < 32; i++) {
01793             dashes[i] = (gint8) 0;
01794          }
01795 
01796          gdk_gc_set_dashes(gGCdash, gDashOffset, dashes, gDashSize);
01797          gdk_win32_draw_lines(gCws->drawing, (GdkGC*)gGCdash, (GdkPoint *)xy, n);
01798 
01799          // calculate length of line to update dash offset
01800          for (i = 1; i < n; i++) {
01801             int dx = xy[i].fX - xy[i - 1].fX;
01802             int dy = xy[i].fY - xy[i - 1].fY;
01803 
01804             if (dx < 0) dx = -dx;
01805             if (dy < 0) dy = -dy;
01806             gDashOffset += dx > dy ? dx : dy;
01807          }
01808          gDashOffset %= gDashLength;
01809       }
01810    } else {
01811       gdk_win32_draw_points( gCws->drawing, gLineStyle == GDK_LINE_SOLID ?
01812                               gGCline : gGCdash, (GdkPoint *)xy,1);
01813    }
01814    delete [] xy;
01815 }
01816 
01817 //______________________________________________________________________________
01818 void TGWin32::DrawPolyMarker(int n, TPoint *xyt)
01819 {
01820    // Draw n markers with the current attributes at position x, y.
01821    // n    : number of markers to draw
01822    // xy   : x,y coordinates of markers
01823 
01824    int i;
01825    static int lastn = 0;
01826    static GdkPoint *xy = 0;
01827 
01828    if (!fWindows) return;
01829 
01830    if (fMarkerStyleModified) UpdateMarkerStyle();
01831    if (fMarkerColorModified) UpdateMarkerColor();
01832 
01833    if (lastn!=n) {
01834       delete [] (GdkPoint *)xy;
01835       xy = new GdkPoint[n];
01836       lastn = n;
01837    }
01838 
01839    for (i = 0; i < n; i++) {
01840       xy[i].x = xyt[i].fX;
01841       xy[i].y = xyt[i].fY;
01842    }
01843 
01844    if (gMarker.n <= 0) {
01845        gdk_win32_draw_points(gCws->drawing, gGCmark, xy, n);
01846    } else {
01847       int r = gMarker.n / 2;
01848       int m;
01849 
01850       for (m = 0; m < n; m++) {
01851          int hollow = 0;
01852          switch (gMarker.type) {
01853             int i;
01854 
01855          case 0:               // hollow circle
01856             gdk_win32_draw_arc(gCws->drawing, gGCmark, kFALSE, xy[m].x-r, xy[m].y-r,
01857                               gMarker.n, gMarker.n, 0, 23040);
01858             break;
01859 
01860          case 1:               // filled circle
01861             gdk_win32_draw_arc(gCws->drawing, gGCmark, kTRUE, xy[m].x-r, xy[m].y-r,
01862                               gMarker.n, gMarker.n, 0, 23040);
01863             break;
01864 
01865          case 2:               // hollow polygon
01866             hollow = 1;
01867          case 3:               // filled polygon
01868             for (i = 0; i < gMarker.n; i++) {
01869                gMarker.xy[i].x += xy[m].x;
01870                gMarker.xy[i].y += xy[m].y;
01871             }
01872             if (hollow) {
01873                gdk_win32_draw_lines(gCws->drawing, gGCmark, (GdkPoint *)gMarker.xy, gMarker.n);
01874             } else {
01875                gdk_win32_draw_polygon(gCws->drawing, gGCmark, 1, (GdkPoint *)gMarker.xy, gMarker.n);
01876             }
01877             for (i = 0; i < gMarker.n; i++) {
01878                gMarker.xy[i].x -= xy[m].x;
01879                gMarker.xy[i].y -= xy[m].y;
01880             }
01881             break;
01882 
01883          case 4:               // segmented line
01884             for (i = 0; i < gMarker.n; i += 2) {
01885                gdk_draw_line(gCws->drawing, gGCmark,
01886                              xy[m].x + gMarker.xy[i].x,
01887                              xy[m].y + gMarker.xy[i].y,
01888                              xy[m].x + gMarker.xy[i + 1].x,
01889                              xy[m].y + gMarker.xy[i + 1].y);
01890             }
01891             break;
01892          }
01893       }
01894    }
01895 }
01896 
01897 //______________________________________________________________________________
01898 void TGWin32::GetCharacterUp(Float_t & chupx, Float_t & chupy)
01899 {
01900    // Return character up vector.
01901 
01902    chupx = fCharacterUpX;
01903    chupy = fCharacterUpY;
01904 }
01905 
01906 //______________________________________________________________________________
01907 XColor_t &TGWin32::GetColor(Int_t cid)
01908 {
01909    // Return reference to internal color structure associated
01910    // to color index cid.
01911 
01912    XColor_t *col = (XColor_t*) fColors->GetValue(cid);
01913    if (!col) {
01914       col = new XColor_t;
01915       fColors->Add(cid, (Long_t) col);
01916    }
01917    return *col;
01918 }
01919 
01920 //______________________________________________________________________________
01921 Window_t TGWin32::GetCurrentWindow() const
01922 {
01923    // Return current window pointer. Protected method used by TGWin32TTF.
01924 
01925    return (Window_t)(gCws ? gCws->drawing : 0);
01926 }
01927 
01928 //______________________________________________________________________________
01929 GdkGC *TGWin32::GetGC(Int_t which) const
01930 {
01931    // Return desired Graphics Context ("which" maps directly on gGCList[]).
01932    // Protected method used by TGWin32TTF.
01933 
01934    if (which >= kMAXGC || which < 0) {
01935       Error("GetGC", "trying to get illegal GdkGC (which = %d)", which);
01936       return 0;
01937    }
01938 
01939    return gGClist[which];
01940 }
01941 
01942 //______________________________________________________________________________
01943 Int_t TGWin32::GetDoubleBuffer(int wid)
01944 {
01945    // Query the double buffer value for the window wid.
01946 
01947    if (!fWindows) return 0;
01948 
01949    gTws = &fWindows[wid];
01950 
01951    if (!gTws->open) {
01952       return -1;
01953    } else {
01954       return gTws->double_buffer;
01955    }
01956 }
01957 
01958 //______________________________________________________________________________
01959 void TGWin32::GetGeometry(int wid, int &x, int &y, unsigned int &w,
01960                           unsigned int &h)
01961 {
01962    // Return position and size of window wid.
01963    // wid        : window identifier
01964    // x,y        : window position (output)
01965    // w,h        : window size (output)
01966    // if wid < 0 the size of the display is returned
01967 
01968    if (!fWindows) return;
01969 
01970    if (wid < 0) {
01971       x = 0;
01972       y = 0;
01973 
01974       w = gdk_screen_width();
01975       h = gdk_screen_height();
01976    } else {
01977       int depth;
01978       int width, height;
01979 
01980       gTws = &fWindows[wid];
01981       gdk_window_get_geometry((GdkDrawable *) gTws->window, &x, &y,
01982                               &width, &height, &depth);
01983 
01984       gdk_window_get_deskrelative_origin((GdkDrawable *) gTws->window, &x, &y);
01985 
01986       if (width > 0 && height > 0) {
01987          gTws->width = width;
01988          gTws->height = height;
01989       }
01990       w = gTws->width;
01991       h = gTws->height;
01992    }
01993 }
01994 
01995 //______________________________________________________________________________
01996 const char *TGWin32::DisplayName(const char *dpyName)
01997 {
01998    // Return hostname on which the display is opened.
01999 
02000    return "localhost";          //return gdk_get_display();
02001 }
02002 
02003 //______________________________________________________________________________
02004 void TGWin32::GetPlanes(int &nplanes)
02005 {
02006    // Get maximum number of planes.
02007 
02008    nplanes = gdk_visual_get_best_depth();
02009 }
02010 
02011 //______________________________________________________________________________
02012 void TGWin32::GetRGB(int index, float &r, float &g, float &b)
02013 {
02014    // Get rgb values for color "index".
02015 
02016    if (index == 0) {
02017       r = g = b = 1.0;
02018    } else if (index == 1) {
02019       r = g = b = 0.0;
02020    } else {
02021       XColor_t &col = GetColor(index);
02022       r = ((float) col.color.red) / ((float) kBIGGEST_RGB_VALUE);
02023       g = ((float) col.color.green) / ((float) kBIGGEST_RGB_VALUE);
02024       b = ((float) col.color.blue) / ((float) kBIGGEST_RGB_VALUE);
02025    }
02026 }
02027 
02028 //______________________________________________________________________________
02029 void TGWin32::GetTextExtent(unsigned int &w, unsigned int &h, char *mess)
02030 {
02031    // Return the size of a character string.
02032    // iw          : text width
02033    // ih          : text height
02034    // mess        : message
02035 
02036    TTF::SetTextFont(gTextFont);
02037    TTF::SetTextSize(fTextSize);
02038    TTF::GetTextExtent(w, h, mess);
02039 }
02040 
02041 //______________________________________________________________________________
02042 Window_t TGWin32::GetWindowID(int wid)
02043 {
02044    // Return the X11 window identifier.
02045    // wid      : Workstation identifier (input)
02046 
02047    if (!fWindows) return 0;
02048    return (Window_t) fWindows[wid].window;
02049 }
02050 
02051 //______________________________________________________________________________
02052 void TGWin32::MoveWindow(int wid, int x, int y)
02053 {
02054    // Move the window wid.
02055    // wid  : GdkWindow identifier.
02056    // x    : x new window position
02057    // y    : y new window position
02058 
02059    if (!fWindows) return;
02060 
02061    gTws = &fWindows[wid];
02062    if (!gTws->open) return;
02063 
02064    gdk_window_move((GdkDrawable *) gTws->window, x, y);
02065 }
02066 
02067 //______________________________________________________________________________
02068 Int_t TGWin32::OpenPixmap(unsigned int w, unsigned int h)
02069 {
02070    // Open a new pixmap.
02071    // w,h : Width and height of the pixmap.
02072 
02073    GdkWindow root;
02074    int wval, hval;
02075    int xx, yy, i, wid;
02076    int ww, hh, border, depth;
02077    wval = w;
02078    hval = h;
02079 
02080    // Select next free window number
02081  again:
02082    for (wid = 0; wid < fMaxNumberOfWindows; wid++) {
02083       if (!fWindows[wid].open) {
02084          fWindows[wid].open = 1;
02085          gCws = &fWindows[wid];
02086          break;
02087       }
02088    }
02089    if (wid == fMaxNumberOfWindows) {
02090       int newsize = fMaxNumberOfWindows + 10;
02091       fWindows = (XWindow_t *) TStorage::ReAlloc(fWindows,
02092                                                  newsize * sizeof(XWindow_t),
02093                                                  fMaxNumberOfWindows *
02094                                                  sizeof(XWindow_t));
02095 
02096       for (i = fMaxNumberOfWindows; i < newsize; i++) fWindows[i].open = 0;
02097       fMaxNumberOfWindows = newsize;
02098       goto again;
02099    }
02100 
02101    depth =gdk_visual_get_best_depth();
02102    gCws->window = (GdkPixmap *) gdk_pixmap_new(GDK_ROOT_PARENT(),wval,hval,depth);
02103    gdk_drawable_get_size((GdkDrawable *) gCws->window, &ww, &hh);
02104 
02105    for (i = 0; i < kMAXGC; i++) {
02106       gdk_gc_set_clip_mask((GdkGC *) gGClist[i], (GdkDrawable *)None);
02107    }
02108 
02109    SetColor(gGCpxmp, 0);
02110    gdk_win32_draw_rectangle(gCws->window,(GdkGC *)gGCpxmp, kTRUE,
02111                            0, 0, ww, hh);
02112    SetColor(gGCpxmp, 1);
02113 
02114    // Initialise the window structure
02115    gCws->drawing = gCws->window;
02116    gCws->buffer = 0;
02117    gCws->double_buffer = 0;
02118    gCws->ispixmap = 1;
02119    gCws->clip = 0;
02120    gCws->width = wval;
02121    gCws->height = hval;
02122    gCws->new_colors = 0;
02123 
02124    return wid;
02125 }
02126 
02127 //______________________________________________________________________________
02128 Int_t TGWin32::InitWindow(ULong_t win)
02129 {
02130    // Open window and return window number.
02131    // Return -1 if window initialization fails.
02132 
02133    GdkWindowAttr attributes;
02134    unsigned long attr_mask = 0;
02135    int wid;
02136    int xval, yval;
02137    int wval, hval, border, depth;
02138    GdkWindow root;
02139 
02140    GdkWindow *wind = (GdkWindow *) win;
02141 
02142    gdk_window_get_geometry(wind, &xval, &yval, &wval, &hval, &depth);
02143 
02144    // Select next free window number
02145 
02146  again:
02147    for (wid = 0; wid < fMaxNumberOfWindows; wid++) {
02148       if (!fWindows[wid].open) {
02149          fWindows[wid].open = 1;
02150          fWindows[wid].double_buffer = 0;
02151          gCws = &fWindows[wid];
02152          break;
02153       }
02154    }
02155 
02156    if (wid == fMaxNumberOfWindows) {
02157       int newsize = fMaxNumberOfWindows + 10;
02158       fWindows =
02159           (XWindow_t *) TStorage::ReAlloc(fWindows,
02160                                           newsize * sizeof(XWindow_t),
02161                                           fMaxNumberOfWindows *
02162                                           sizeof(XWindow_t));
02163 
02164       for (int i = fMaxNumberOfWindows; i < newsize; i++) {
02165          fWindows[i].open = 0;
02166       }
02167 
02168       fMaxNumberOfWindows = newsize;
02169       goto again;
02170    }
02171    // Create window
02172    attributes.wclass = GDK_INPUT_OUTPUT;
02173    attributes.event_mask = 0L;  //GDK_ALL_EVENTS_MASK;
02174    attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK |
02175        GDK_PROPERTY_CHANGE_MASK;
02176 //                            GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK;
02177    if (xval >= 0) {
02178       attributes.x = xval;
02179    } else {
02180       attributes.x = -1.0 * xval;
02181    }
02182 
02183    if (yval >= 0) {
02184       attributes.y = yval;
02185    } else {
02186       attributes.y = -1.0 * yval;
02187    }
02188    attributes.width = wval;
02189    attributes.height = hval;
02190    attributes.colormap = gdk_colormap_get_system();
02191    attributes.visual = gdk_window_get_visual(wind);
02192    attributes.override_redirect = TRUE;
02193 
02194    if ((attributes.y > 0) && (attributes.x > 0)) {
02195       attr_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_COLORMAP |
02196           GDK_WA_WMCLASS | GDK_WA_NOREDIR;
02197    } else {
02198       attr_mask = GDK_WA_COLORMAP | GDK_WA_WMCLASS | GDK_WA_NOREDIR;
02199    }
02200 
02201    if (attributes.visual != NULL) {
02202       attr_mask |= GDK_WA_VISUAL;
02203    }
02204    attributes.window_type = GDK_WINDOW_CHILD;
02205    gCws->window = gdk_window_new(wind, &attributes, attr_mask);
02206    HWND window = (HWND)GDK_DRAWABLE_XID((GdkWindow *)gCws->window);
02207    ::ShowWindow(window, SW_SHOWNORMAL);
02208    ::ShowWindow(window, SW_RESTORE);
02209    ::BringWindowToTop(window);
02210 
02211    if (!fUseSysPointers) {
02212       ::SetClassLong(window, GCL_HCURSOR,
02213                     (LONG)GDK_CURSOR_XID(fCursors[kPointer]));
02214    }
02215    
02216    // Initialise the window structure
02217 
02218    gCws->drawing = gCws->window;
02219    gCws->buffer = 0;
02220    gCws->double_buffer = 0;
02221    gCws->ispixmap = 0;
02222    gCws->clip = 0;
02223    gCws->width = wval;
02224    gCws->height = hval;
02225    gCws->new_colors = 0;
02226 
02227    return wid;
02228 }
02229 
02230 //______________________________________________________________________________
02231 void TGWin32::QueryPointer(int &ix, int &iy)
02232 {
02233    // Query pointer position.
02234    // ix       : X coordinate of pointer
02235    // iy       : Y coordinate of pointer
02236    // (both coordinates are relative to the origin of the root window)
02237 
02238    GdkModifierType mask;
02239    GdkWindow *retw = gdk_window_get_pointer((GdkWindow *) gCws->window,
02240                                              &ix, &iy, &mask);
02241 }
02242 
02243 //______________________________________________________________________________
02244 void TGWin32::RemovePixmap(GdkDrawable *pix)
02245 {
02246    // Remove the pixmap pix.
02247 
02248    gdk_pixmap_unref((GdkPixmap *)pix);
02249 }
02250 
02251 //______________________________________________________________________________
02252 Int_t TGWin32::RequestLocator(Int_t mode, Int_t ctyp, Int_t & x, Int_t & y)
02253 {
02254    // Request Locator position.
02255    // x,y       : cursor position at moment of button press (output)
02256    // ctyp      : cursor type (input)
02257    //   ctyp=1 tracking cross
02258    //   ctyp=2 cross-hair
02259    //   ctyp=3 rubber circle
02260    //   ctyp=4 rubber band
02261    //   ctyp=5 rubber rectangle
02262    //
02263    // mode      : input mode
02264    //   mode=0 request
02265    //   mode=1 sample
02266    //
02267    // Request locator:
02268    // return button number  1 = left is pressed
02269    //                       2 = middle is pressed
02270    //                       3 = right is pressed
02271    //        in sample mode:
02272    //                      11 = left is released
02273    //                      12 = middle is released
02274    //                      13 = right is released
02275    //                      -1 = nothing is pressed or released
02276    //                      -2 = leave the window
02277    //                    else = keycode (keyboard is pressed)
02278 
02279    static int xloc = 0;
02280    static int yloc = 0;
02281    static int xlocp = 0;
02282    static int ylocp = 0;
02283    static GdkCursor *cursor = NULL;
02284    Int_t  xtmp, ytmp;
02285 
02286    GdkEvent *event;
02287    GdkEvent *next_event;
02288    int button_press;
02289    int radius;
02290 
02291    // Change the cursor shape
02292    if (cursor == NULL) {
02293       if (ctyp > 1) {
02294          gdk_window_set_cursor((GdkWindow *)gCws->window, (GdkCursor *)gNullCursor);
02295          gdk_gc_set_foreground((GdkGC *) gGCecho, &GetColor(0).color);
02296       } else {
02297          if (fUseSysPointers)
02298             cursor = gdk_syscursor_new((ULong_t)IDC_CROSS);
02299          else
02300             cursor = gdk_cursor_new((GdkCursorType)GDK_CROSSHAIR);
02301          gdk_window_set_cursor((GdkWindow *)gCws->window, (GdkCursor *)cursor);
02302       }
02303    }
02304 
02305    // Event loop
02306    button_press = 0;
02307 
02308    // Set max response time to 2 minutes to avoid timeout
02309    // in TGWin32ProxyBase::ForwardCallBack during RequestLocator
02310    TGWin32VirtualXProxy::fMaxResponseTime = 120000;
02311    while (button_press == 0) {
02312       event = gdk_event_get();
02313 
02314       switch (ctyp) {
02315 
02316       case 1:
02317          break;
02318 
02319       case 2:
02320          gdk_draw_line(gCws->window, gGCecho, xloc, 0, xloc, gCws->height);
02321          gdk_draw_line(gCws->window, gGCecho, 0, yloc, gCws->width, yloc);
02322          break;
02323 
02324       case 3:
02325          radius = (int) TMath::Sqrt((double)((xloc - xlocp) * (xloc - xlocp) +
02326                                              (yloc - ylocp) * (yloc - ylocp)));
02327 
02328          gdk_win32_draw_arc(gCws->window, gGCecho, kFALSE,
02329                             xlocp - radius, ylocp - radius,
02330                             2 * radius, 2 * radius, 0, 23040);
02331          break;
02332 
02333       case 4:
02334          gdk_draw_line(gCws->window, gGCecho, xlocp, ylocp, xloc, yloc);
02335          break;
02336 
02337       case 5:
02338          gdk_win32_draw_rectangle( gCws->window, gGCecho, kFALSE,
02339                                  TMath::Min(xlocp, xloc), TMath::Min(ylocp, yloc),
02340                                  TMath::Abs(xloc - xlocp), TMath::Abs(yloc - ylocp));
02341          break;
02342 
02343       default:
02344          break;
02345       }
02346 
02347       xloc = event->button.x;
02348       yloc = event->button.y;
02349 
02350       switch (event->type) {
02351 
02352       case GDK_LEAVE_NOTIFY:
02353          if (mode == 0) {
02354             while (1) {
02355                event = gdk_event_get();
02356 
02357                if (event->type == GDK_ENTER_NOTIFY) {
02358                   gdk_event_free(event);
02359                   break;
02360                }
02361                gdk_event_free(event);
02362             }
02363          } else {
02364             button_press = -2;
02365          }
02366          break;
02367 
02368       case GDK_BUTTON_PRESS:
02369          button_press = event->button.button;
02370          xlocp = event->button.x;
02371          ylocp = event->button.y;
02372          gdk_cursor_unref(cursor);
02373          cursor = 0;
02374          break;
02375 
02376       case GDK_BUTTON_RELEASE:
02377          if (mode == 1) {
02378             button_press = 10 + event->button.button;
02379             xlocp = event->button.x;
02380             ylocp = event->button.y;
02381          }
02382          break;
02383 
02384       case GDK_KEY_PRESS:
02385          if (mode == 1) {
02386             button_press = event->key.keyval;
02387             xlocp = event->button.x;
02388             ylocp = event->button.y;
02389          }
02390          break;
02391 
02392       case GDK_KEY_RELEASE:
02393          if (mode == 1) {
02394             button_press = -1 * (int)(event->key.keyval);
02395             xlocp = event->button.x;
02396             ylocp = event->button.y;
02397          }
02398          break;
02399 
02400       default:
02401          break;
02402       }
02403 
02404       xtmp = event->button.x;
02405       ytmp = event->button.y;
02406 
02407       gdk_event_free(event);
02408 
02409       if (mode == 1) {
02410          if (button_press == 0) {
02411             button_press = -1;
02412          }
02413          break;
02414       }
02415    }
02416    TGWin32VirtualXProxy::fMaxResponseTime = 1000;
02417 
02418    x = xtmp;
02419    y = ytmp;
02420 
02421    return button_press;
02422 }
02423 
02424 //______________________________________________________________________________
02425 Int_t TGWin32::RequestString(int x, int y, char *text)
02426 {
02427    // Request a string.
02428    // x,y         : position where text is displayed
02429    // text        : text displayed (input), edited text (output)
02430    //
02431    // Request string:
02432    // text is displayed and can be edited with Emacs-like keybinding
02433    // return termination code (0 for ESC, 1 for RETURN)
02434 
02435    static GdkCursor *cursor = NULL;
02436    static int percent = 0;      // bell volume
02437    static GdkWindow *CurWnd;
02438    HWND focuswindow;
02439    int focusrevert;
02440    GdkEvent *event;
02441    KeySym keysym;
02442    int key = -1;
02443    int len_text = strlen(text);
02444    int nt;                      // defined length of text
02445    int pt;                      // cursor position in text
02446    MSG msg;
02447 
02448    CurWnd = (GdkWindow *)gCws->window;
02449    // change the cursor shape
02450    if (cursor == NULL) {
02451       if (fUseSysPointers)
02452          cursor = gdk_syscursor_new((ULong_t)IDC_HELP);
02453       else
02454          cursor = gdk_cursor_new((GdkCursorType)GDK_QUESTION_ARROW);
02455    }
02456    if (cursor != 0) {
02457       gdk_window_set_cursor(CurWnd, cursor);
02458    }
02459    for (nt = len_text; nt > 0 && text[nt - 1] == ' '; nt--);
02460 
02461    pt = nt;
02462    focuswindow = ::SetFocus((HWND)GDK_DRAWABLE_XID(CurWnd));
02463 
02464    // Set max response time to 2 minutes to avoid timeout
02465    // in TGWin32ProxyBase::ForwardCallBack during RequestString
02466    TGWin32VirtualXProxy::fMaxResponseTime = 120000;
02467    TTF::SetTextFont(gTextFont);
02468    TTF::SetTextSize(fTextSize);
02469    do {
02470       char tmp[2];
02471       char keybuf[8];
02472       char nbytes;
02473       UInt_t dx, ddx, h;
02474       int i;
02475 
02476       if (EventsPending()) {
02477          event = gdk_event_get();
02478       } else {
02479          gSystem->ProcessEvents();
02480          ::SleepEx(10, kTRUE);
02481          continue;
02482       }
02483 
02484       DrawText(x, y, 0.0, 1.0, text, kOpaque);
02485       TTF::GetTextExtent(dx, h, text);
02486       DrawText(x+dx, y, 0.0, 1.0, " ", kOpaque);
02487 
02488       if (pt == 0) {
02489          dx = 0;
02490       } else {
02491          char *stmp = new char[pt+1];
02492          strncpy(stmp, text, pt);
02493          stmp[pt] = '\0';
02494          TTF::GetTextExtent(ddx, h, stmp);
02495          dx = ddx;
02496          delete stmp;
02497       }
02498 
02499       if (pt < len_text) {
02500          tmp[0] = text[pt];
02501          tmp[1] = '\0';
02502          DrawText(x+dx, y, 0.0, 1.0, tmp, kOpaque);
02503       } else {
02504          DrawText(x+dx, y, 0.0, 1.0, " ", kOpaque);
02505       }
02506 
02507       if (event != NULL) {
02508          switch (event->type) {
02509          case GDK_BUTTON_PRESS:
02510          case GDK_ENTER_NOTIFY:
02511             focuswindow = ::SetFocus((HWND)GDK_DRAWABLE_XID(CurWnd));
02512             break;
02513 
02514          case GDK_LEAVE_NOTIFY:
02515             ::SetFocus(focuswindow);
02516             break;
02517          case GDK_KEY_PRESS:
02518             nbytes = event->key.length;
02519             for (i = 0; i < nbytes; i++) {
02520                keybuf[i] = event->key.string[i];
02521             }
02522             keysym = event->key.keyval;
02523             switch (keysym) {   // map cursor keys
02524             case GDK_BackSpace:
02525                keybuf[0] = 0x08;        // backspace
02526                nbytes = 1;
02527                break;
02528             case GDK_Return:
02529                keybuf[0] = 0x0d;        // return
02530                nbytes = 1;
02531                break;
02532             case GDK_Delete:
02533                keybuf[0] = 0x7f;        // del
02534                nbytes = 1;
02535                break;
02536             case GDK_Escape:
02537                keybuf[0] = 0x1b;        // esc
02538                nbytes = 1;
02539                break;
02540             case GDK_Home:
02541                keybuf[0] = 0x01;        // home
02542                nbytes = 1;
02543                break;
02544             case GDK_Left:
02545                keybuf[0] = 0x02;        // backward
02546                nbytes = 1;
02547                break;
02548             case GDK_Right:
02549                keybuf[0] = 0x06;        // forward
02550                nbytes = 1;
02551                break;
02552             case GDK_End:
02553                keybuf[0] = 0x05;        // end
02554                nbytes = 1;
02555                break;
02556             }
02557             if (nbytes == 1) {
02558                if (isascii(keybuf[0]) && isprint(keybuf[0])) {
02559                   // insert character
02560                   if (nt < len_text) {
02561                      nt++;
02562                   }
02563                   for (i = nt - 1; i > pt; i--) {
02564                      text[i] = text[i - 1];
02565                   }
02566                   if (pt < len_text) {
02567                      text[pt] = keybuf[0];
02568                      pt++;
02569                   }
02570                } else {
02571                   switch (keybuf[0]) {
02572                      // Emacs-like editing keys
02573 
02574                   case 0x08:   //'\010':    // backspace
02575                   case 0x7f:   //'\177':    // delete
02576                      // delete backward
02577                      if (pt > 0) {
02578                         for (i = pt; i < nt; i++) {
02579                            text[i - 1] = text[i];
02580                         }
02581                         text[nt - 1] = ' ';
02582                         nt--;
02583                         pt--;
02584                      }
02585                      break;
02586                   case 0x01:   //'\001':    // ^A
02587                      // beginning of line
02588                      pt = 0;
02589                      break;
02590                   case 0x02:   //'\002':    // ^B
02591                      // move backward
02592                      if (pt > 0) {
02593                         pt--;
02594                      }
02595                      break;
02596                   case 0x04:   //'\004':    // ^D
02597                      // delete forward
02598                      if (pt > 0) {
02599                         for (i = pt; i < nt; i++) {
02600                            text[i - 1] = text[i];
02601                         }
02602                         text[nt - 1] = ' ';
02603                         pt--;
02604                      }
02605                      break;
02606                   case 0x05:   //'\005':    // ^E
02607                      // end of line
02608                      pt = nt;
02609                      break;
02610 
02611                   case 0x06:   //'\006':    // ^F
02612                      // move forward
02613                      if (pt < nt) {
02614                         pt++;
02615                      }
02616                      break;
02617                   case 0x0b:   //'\013':    // ^K
02618                      // delete to end of line
02619                      for (i = pt; i < nt; i++)
02620                         text[i] = ' ';
02621                      nt = pt;
02622                      break;
02623                   case 0x14:   //'\024':    // ^T
02624                      // transpose
02625                      if (pt > 0) {
02626                         char c = text[pt];
02627                         text[pt] = text[pt - 1];
02628                         text[pt - 1] = c;
02629                      }
02630                      break;
02631                   case 0x0A:   //'\012':    // newline
02632                   case 0x0D:   //'\015':    // return
02633                      key = 1;
02634                      break;
02635                   case 0x1B:   //'\033':    // escape
02636                      key = 0;
02637                      break;
02638 
02639                   default:
02640                      gSystem->Beep();
02641                      break;
02642                   }
02643                }
02644             }
02645          default:
02646             SetInputFocus((Window_t)gCws->window);
02647             break;
02648          }
02649          gdk_event_free(event);
02650       }
02651    } while (key < 0);
02652    TGWin32VirtualXProxy::fMaxResponseTime = 1000;
02653    ::SetFocus(focuswindow);
02654    SetInputFocus((Window_t)CurWnd);
02655 
02656    gdk_window_set_cursor(CurWnd, (GdkCursor *)fCursors[kPointer]);
02657    if (cursor != 0) {
02658       gdk_cursor_unref(cursor);
02659       cursor = 0;
02660    }
02661 
02662    return key;
02663 }
02664 
02665 //______________________________________________________________________________
02666 void TGWin32::RescaleWindow(int wid, unsigned int w, unsigned int h)
02667 {
02668    // Rescale the window wid.
02669    // wid  : GdkWindow identifier
02670    // w    : Width
02671    // h    : Heigth
02672 
02673     int i;
02674 
02675    if (!fWindows) return;
02676 
02677    gTws = &fWindows[wid];
02678    if (!gTws->open)
02679       return;
02680 
02681    // don't do anything when size did not change
02682    if (gTws->width == w && gTws->height == h)
02683       return;
02684 
02685    gdk_window_resize((GdkWindow *) gTws->window, w, h);
02686 
02687    if (gTws->buffer) {
02688       // don't free and recreate pixmap when new pixmap is smaller
02689       if (gTws->width < w || gTws->height < h) {
02690          gdk_pixmap_unref(gTws->buffer);
02691          gTws->buffer = gdk_pixmap_new(GDK_ROOT_PARENT(),       // NULL,
02692                                        w, h, gdk_visual_get_best_depth());
02693       }
02694       for (i = 0; i < kMAXGC; i++) {
02695          gdk_gc_set_clip_mask(gGClist[i], None);
02696       }
02697       SetColor(gGCpxmp, 0);
02698       gdk_win32_draw_rectangle(gTws->buffer, gGCpxmp, 1, 0, 0, w, h);
02699       SetColor(gGCpxmp, 1);
02700 
02701       if (gTws->double_buffer) gTws->drawing = gTws->buffer;
02702    }
02703    gTws->width = w;
02704    gTws->height = h;
02705 }
02706 
02707 //______________________________________________________________________________
02708 int TGWin32::ResizePixmap(int wid, unsigned int w, unsigned int h)
02709 {
02710    // Resize a pixmap.
02711    // wid : pixmap to be resized
02712    // w,h : Width and height of the pixmap
02713 
02714    GdkWindow root;
02715    int wval, hval;
02716    int xx, yy, i;
02717    int ww, hh, border, depth;
02718    wval = w;
02719    hval = h;
02720 
02721    if (!fWindows) return 0;
02722 
02723    gTws = &fWindows[wid];
02724 
02725    // don't do anything when size did not change
02726    //  if (gTws->width == wval && gTws->height == hval) return 0;
02727 
02728    // due to round-off errors in TPad::Resize() we might get +/- 1 pixel
02729    // change, in those cases don't resize pixmap
02730    if (gTws->width >= wval - 1 && gTws->width <= wval + 1 &&
02731        gTws->height >= hval - 1 && gTws->height <= hval + 1)
02732       return 0;
02733 
02734    // don't free and recreate pixmap when new pixmap is smaller
02735    if (gTws->width < wval || gTws->height < hval) {
02736       gdk_pixmap_unref((GdkPixmap *)gTws->window);
02737       depth = gdk_visual_get_best_depth();
02738       gTws->window = gdk_pixmap_new(GDK_ROOT_PARENT(), wval, hval, depth);
02739    }
02740 
02741    gdk_drawable_get_size(gTws->window, &ww, &hh);
02742 
02743    for (i = 0; i < kMAXGC; i++) {
02744       gdk_gc_set_clip_mask((GdkGC *) gGClist[i], (GdkDrawable *)None);
02745    }
02746 
02747    SetColor(gGCpxmp, 0);
02748    gdk_win32_draw_rectangle(gTws->window,(GdkGC *)gGCpxmp, kTRUE, 0, 0, ww, hh);
02749    SetColor(gGCpxmp, 1);
02750 
02751    // Initialise the window structure
02752    gTws->drawing = gTws->window;
02753    gTws->width = wval;
02754    gTws->height = hval;
02755    return 1;
02756 }
02757 
02758 //______________________________________________________________________________
02759 void TGWin32::ResizeWindow(int wid)
02760 {
02761    // Resize the current window if necessary.
02762 
02763    int i;
02764    int xval = 0, yval = 0;
02765    GdkWindow *win, *root = NULL;
02766    int wval = 0, hval = 0, depth = 0;
02767 
02768    if (!fWindows) return;
02769 
02770    gTws = &fWindows[wid];
02771 
02772    win = (GdkWindow *) gTws->window;
02773    gdk_window_get_geometry(win, &xval, &yval,
02774                            &wval, &hval, &depth);
02775 
02776    // don't do anything when size did not change
02777    if (gTws->width == wval && gTws->height == hval) {
02778       return;
02779    }
02780 
02781    gdk_window_resize((GdkWindow *) gTws->window, wval, hval);
02782 
02783    if (gTws->buffer) {
02784       if (gTws->width < wval || gTws->height < hval) {
02785          gdk_pixmap_unref((GdkPixmap *)gTws->buffer);
02786          depth = gdk_visual_get_best_depth();
02787          gTws->buffer = (GdkPixmap *) gdk_pixmap_new(GDK_ROOT_PARENT(),
02788                                                      wval, hval, depth);
02789       }
02790 
02791       for (i = 0; i < kMAXGC; i++) {
02792          gdk_gc_set_clip_mask((GdkGC *) gGClist[i], (GdkDrawable *)None);
02793       }
02794 
02795       SetColor(gGCpxmp, 0);
02796       gdk_win32_draw_rectangle(gTws->buffer,(GdkGC *)gGCpxmp, kTRUE, 0, 0, wval, hval);
02797 
02798       SetColor(gGCpxmp, 1);
02799 
02800       if (gTws->double_buffer) gTws->drawing = gTws->buffer;
02801    }
02802 
02803    gTws->width = wval;
02804    gTws->height = hval;
02805 }
02806 
02807 //______________________________________________________________________________
02808 void TGWin32::SelectWindow(int wid)
02809 {
02810    // Select window to which subsequent output is directed.
02811 
02812    int i;
02813    GdkRectangle rect;
02814 
02815    if (!fWindows || wid < 0 || wid >= fMaxNumberOfWindows || !fWindows[wid].open) {
02816       return;
02817    }
02818 
02819    gCws = &fWindows[wid];
02820 
02821    if (gCws->clip && !gCws->ispixmap && !gCws->double_buffer) {
02822       rect.x = gCws->xclip;
02823       rect.y = gCws->yclip;
02824       rect.width = gCws->wclip;
02825       rect.height = gCws->hclip;
02826 
02827       for (i = 0; i < kMAXGC; i++) {
02828          gdk_gc_set_clip_rectangle((GdkGC *) gGClist[i], &rect);
02829       }
02830    } else {
02831       for (i = 0; i < kMAXGC; i++) {
02832          gdk_gc_set_clip_mask((GdkGC *) gGClist[i], (GdkDrawable *)None);
02833       }
02834    }
02835 }
02836 
02837 //______________________________________________________________________________
02838 void TGWin32::SetCharacterUp(Float_t chupx, Float_t chupy)
02839 {
02840    // Set character up vector.
02841 
02842    if (chupx == fCharacterUpX && chupy == fCharacterUpY) return;
02843 
02844    if (chupx == 0 && chupy == 0) {
02845       fTextAngle = 0;
02846    } else if (chupx == 0 && chupy == 1) {
02847       fTextAngle = 0;
02848    } else if (chupx == -1 && chupy == 0) {
02849       fTextAngle = 90;
02850    } else if (chupx == 0 && chupy == -1) {
02851       fTextAngle = 180;
02852    } else if (chupx == 1 && chupy == 0) {
02853       fTextAngle = 270;
02854    } else {
02855       fTextAngle =
02856           ((TMath::
02857             ACos(chupx / TMath::Sqrt(chupx * chupx + chupy * chupy)) *
02858             180.) / 3.14159) - 90;
02859       if (chupy < 0) fTextAngle = 180 - fTextAngle;
02860       if (TMath::Abs(fTextAngle) <= 0.01) fTextAngle = 0;
02861    }
02862    fCharacterUpX = chupx;
02863    fCharacterUpY = chupy;
02864 }
02865 
02866 //______________________________________________________________________________
02867 void TGWin32::SetClipOFF(int wid)
02868 {
02869    // Turn off the clipping for the window wid.
02870 
02871    if (!fWindows) return;
02872 
02873    gTws = &fWindows[wid];
02874    gTws->clip = 0;
02875 
02876    for (int i = 0; i < kMAXGC; i++) {
02877       gdk_gc_set_clip_mask((GdkGC *) gGClist[i], (GdkDrawable *)None);
02878    }
02879 }
02880 
02881 //______________________________________________________________________________
02882 void TGWin32::SetClipRegion(int wid, int x, int y, unsigned int w,
02883                             unsigned int h)
02884 {
02885    // Set clipping region for the window wid.
02886    // wid        : GdkWindow indentifier
02887    // x,y        : origin of clipping rectangle
02888    // w,h        : size of clipping rectangle;
02889 
02890    if (!fWindows) return;
02891 
02892    gTws = &fWindows[wid];
02893    gTws->xclip = x;
02894    gTws->yclip = y;
02895    gTws->wclip = w;
02896    gTws->hclip = h;
02897    gTws->clip = 1;
02898    GdkRectangle rect;
02899 
02900    if (gTws->clip && !gTws->ispixmap && !gTws->double_buffer) {
02901       rect.x = gTws->xclip;
02902       rect.y = gTws->yclip;
02903       rect.width = gTws->wclip;
02904       rect.height = gTws->hclip;
02905 
02906       for (int i = 0; i < kMAXGC; i++) {
02907          gdk_gc_set_clip_rectangle((GdkGC *)gGClist[i], &rect);
02908       }
02909    }
02910 }
02911 
02912 //______________________________________________________________________________
02913 ULong_t TGWin32::GetPixel(Color_t ci)
02914 {
02915    // Return pixel value associated to specified ROOT color number.
02916 
02917    TColor *color = gROOT->GetColor(ci);
02918    if (color)
02919       SetRGB(ci, color->GetRed(), color->GetGreen(), color->GetBlue());
02920    XColor_t &col = GetColor(ci);
02921    return col.color.pixel;
02922 }
02923 
02924 //______________________________________________________________________________
02925 void TGWin32::SetColor(GdkGC *gc, int ci)
02926 {
02927    // Set the foreground color in GdkGC.
02928 
02929    GdkGCValues gcvals;
02930    GdkColor color;
02931 
02932    if (ci<=0) ci = 10; //white
02933 
02934    TColor *clr = gROOT->GetColor(ci);
02935    if (clr)
02936       SetRGB(ci, clr->GetRed(), clr->GetGreen(), clr->GetBlue());
02937 
02938    XColor_t &col = GetColor(ci);
02939    if (fColormap && !col.fDefined) {
02940       col = GetColor(0);
02941    } else if (!fColormap && (ci < 0 || ci > 1)) {
02942       col = GetColor(0);
02943    }
02944 
02945    if (fDrawMode == kXor) {
02946       gdk_gc_get_values(gc, &gcvals);
02947 
02948       color.pixel = col.color.pixel ^ gcvals.background.pixel;
02949       color.red = GetRValue(color.pixel);
02950       color.green = GetGValue(color.pixel);
02951       color.blue = GetBValue(color.pixel);
02952       gdk_gc_set_foreground(gc, &color);
02953 
02954    } else {
02955       gdk_gc_set_foreground(gc, &col.color);
02956 
02957       // make sure that foreground and background are different
02958       gdk_gc_get_values(gc, &gcvals);
02959 
02960       if (gcvals.foreground.pixel != gcvals.background.pixel) {
02961          gdk_gc_set_background(gc, &GetColor(!ci).color);
02962       }
02963    }
02964 }
02965 
02966 //______________________________________________________________________________
02967 void TGWin32::SetCursor(int wid, ECursor cursor)
02968 {
02969    // Set the cursor.
02970 
02971    if (!fWindows) return;
02972 
02973    gTws = &fWindows[wid];
02974    gdk_window_set_cursor((GdkWindow *)gTws->window, (GdkCursor *)fCursors[cursor]);
02975 }
02976 
02977 //______________________________________________________________________________
02978 void TGWin32::SetCursor(Window_t id, Cursor_t curid)
02979 {
02980    // Set the specified cursor.
02981 
02982    if (!id) return;
02983 
02984    static GdkWindow *lid = 0;
02985    static GdkCursor *lcur = 0;
02986 
02987    if ((lid == (GdkWindow *)id) && (lcur==(GdkCursor *)curid)) return;
02988    lid = (GdkWindow *)id;
02989    lcur = (GdkCursor *)curid;
02990 
02991    gdk_window_set_cursor((GdkWindow *) id, (GdkCursor *)curid);
02992 }
02993 
02994 //______________________________________________________________________________
02995 void TGWin32::SetDoubleBuffer(int wid, int mode)
02996 {
02997    // Set the double buffer on/off on window wid.
02998    // wid  : GdkWindow identifier.
02999    //        999 means all the opened windows.
03000    // mode : 1 double buffer is on
03001    //        0 double buffer is off
03002 
03003    if (!fWindows) return;
03004 
03005    if (wid == 999) {
03006       for (int i = 0; i < fMaxNumberOfWindows; i++) {
03007          gTws = &fWindows[i];
03008          if (gTws->open) {
03009             switch (mode) {
03010             case 1:
03011                SetDoubleBufferON();
03012                break;
03013             default:
03014                SetDoubleBufferOFF();
03015                break;
03016             }
03017          }
03018       }
03019    } else {
03020       gTws = &fWindows[wid];
03021       if (!gTws->open) return;
03022 
03023       switch (mode) {
03024       case 1:
03025          SetDoubleBufferON();
03026          return;
03027       default:
03028          SetDoubleBufferOFF();
03029          return;
03030       }
03031    }
03032 }
03033 
03034 //______________________________________________________________________________
03035 void TGWin32::SetDoubleBufferOFF()
03036 {
03037    // Turn double buffer mode off.
03038 
03039    if (!gTws->double_buffer) return;
03040    gTws->double_buffer = 0;
03041    gTws->drawing = gTws->window;
03042 }
03043 
03044 //______________________________________________________________________________
03045 void TGWin32::SetDoubleBufferON()
03046 {
03047    // Turn double buffer mode on.
03048 
03049    Int_t depth;
03050 
03051    if (!fWindows || gTws->double_buffer || gTws->ispixmap) return;
03052 
03053    if (!gTws->buffer) {
03054       gTws->buffer = gdk_pixmap_new(GDK_ROOT_PARENT(),  //NULL,
03055                                     gTws->width, gTws->height,
03056                                     gdk_visual_get_best_depth());
03057       SetColor(gGCpxmp, 0);
03058       gdk_win32_draw_rectangle(gTws->buffer, gGCpxmp, 1, 0, 0, gTws->width,
03059                          gTws->height);
03060       SetColor(gGCpxmp, 1);
03061    }
03062    for (int i = 0; i < kMAXGC; i++) {
03063       gdk_gc_set_clip_mask(gGClist[i], None);
03064    }
03065    gTws->double_buffer = 1;
03066    gTws->drawing = gTws->buffer;
03067 }
03068 
03069 //______________________________________________________________________________
03070 void TGWin32::SetDrawMode(EDrawMode mode)
03071 {
03072    // Set the drawing mode.
03073    // mode : drawing mode
03074    //   mode=1 copy
03075    //   mode=2 xor
03076    //   mode=3 invert
03077    //   mode=4 set the suitable mode for cursor echo according to
03078    //          the vendor
03079 
03080    int i;
03081 
03082    switch (mode) {
03083    case kCopy:
03084       for (i = 0; i < kMAXGC; i++) {
03085          gdk_gc_set_function(gGClist[i], GDK_COPY);
03086       }
03087       break;
03088 
03089    case kXor:
03090       for (i = 0; i < kMAXGC; i++) {
03091          gdk_gc_set_function(gGClist[i], GDK_XOR);
03092       }
03093       break;
03094 
03095    case kInvert:
03096       for (i = 0; i < kMAXGC; i++) {
03097          gdk_gc_set_function(gGClist[i], GDK_INVERT);
03098       }
03099       break;
03100    }
03101    fDrawMode = mode;
03102 }
03103 
03104 //______________________________________________________________________________
03105 void TGWin32::SetFillColor(Color_t cindex)
03106 {
03107    // Set color index for fill areas.
03108 
03109    Int_t indx = Int_t(cindex);
03110 
03111    if (!gStyle->GetFillColor() && cindex > 1) {
03112       indx = 0;
03113    }
03114 
03115    fFillColor = indx;
03116    fFillColorModified = kTRUE;
03117 }
03118 
03119 //______________________________________________________________________________
03120 void TGWin32::UpdateFillColor()
03121 {
03122    //
03123 
03124    if (fFillColor >= 0) {
03125       SetColor(gGCfill, fFillColor);
03126    }
03127 
03128    // invalidate fill pattern
03129    if (gFillPattern != NULL) {
03130       gdk_pixmap_unref(gFillPattern);
03131       gFillPattern = NULL;
03132    }
03133    fFillColorModified = kFALSE;
03134 }
03135 
03136 //______________________________________________________________________________
03137 void TGWin32::SetFillStyle(Style_t fstyle)
03138 {
03139    // Set fill area style.
03140    // fstyle   : compound fill area interior style
03141    //    fstyle = 1000*interiorstyle + styleindex
03142 
03143    if (fFillStyle==fstyle) return;
03144 
03145    fFillStyle = fstyle;
03146    fFillStyleModified = kTRUE;
03147 }
03148 
03149 //______________________________________________________________________________
03150 void TGWin32::UpdateFillStyle()
03151 {
03152    // Set fill area style index.
03153 
03154    char* pchar;
03155    static int current_fasi = 0;
03156 
03157    Int_t style = fFillStyle / 1000;
03158    Int_t fasi = fFillStyle % 1000;
03159 
03160    switch (style) {
03161 
03162    case 1:                     // solid
03163       gFillHollow = 0;
03164       gdk_gc_set_fill(gGCfill, GDK_SOLID);
03165       break;
03166 
03167    case 2:                     // pattern
03168       gFillHollow = 1;
03169       break;
03170 
03171    case 3:                     // hatch
03172       gFillHollow = 0;
03173       gdk_gc_set_fill(gGCfill, GDK_STIPPLED);
03174 
03175       if (fasi != current_fasi) {
03176          if (gFillPattern != NULL) {
03177             gdk_pixmap_unref(gFillPattern);
03178             gFillPattern = NULL;
03179          }
03180          int stn = (fasi >= 1 && fasi <=25) ? fasi : 2;
03181          gFillPattern = gdk_bitmap_create_from_data(GDK_ROOT_PARENT(),
03182                                                     (const char *)gStipples[stn], 16, 16);
03183          gdk_gc_set_stipple(gGCfill, gFillPattern);
03184          current_fasi = fasi;
03185       }
03186       break;
03187 
03188    default:
03189       gFillHollow = 1;
03190    }
03191 
03192    fFillStyleModified = kFALSE;
03193 }
03194 
03195 //______________________________________________________________________________
03196 void TGWin32::SetInput(int inp)
03197 {
03198    // Set input on or off.
03199 
03200    EnableWindow((HWND) GDK_DRAWABLE_XID(gCws->window), inp);
03201 }
03202 
03203 //______________________________________________________________________________
03204 void TGWin32::SetLineColor(Color_t cindex)
03205 {
03206    // Set color index for lines.
03207 
03208    if ((cindex < 0) || (cindex==fLineColor)) return;
03209 
03210    fLineColor =  cindex;
03211    fLineColorModified = kTRUE;
03212 }
03213 
03214 //______________________________________________________________________________
03215 void TGWin32::UpdateLineColor()
03216 {
03217    //
03218 
03219    SetColor(gGCline, Int_t(fLineColor));
03220    SetColor(gGCdash, Int_t(fLineColor));
03221    fLineColorModified = kFALSE;
03222 }
03223 
03224 //______________________________________________________________________________
03225 void TGWin32::SetLineType(int n, int *dash)
03226 {
03227    // Set line type.
03228    // n         : length of dash list
03229    // dash(n)   : dash segment lengths
03230    //
03231    // if n <= 0 use solid lines
03232    // if n >  0 use dashed lines described by DASH(N)
03233    //    e.g. N=4,DASH=(6,3,1,3) gives a dashed-dotted line with dash length 6
03234    //    and a gap of 7 between dashes
03235 
03236    if (n <= 0) {
03237       gLineStyle = GDK_LINE_SOLID;
03238       gdk_gc_set_line_attributes(gGCline, fLineWidth,
03239                                  (GdkLineStyle)gLineStyle,
03240                                  (GdkCapStyle) gCapStyle,
03241                                  (GdkJoinStyle) gJoinStyle);
03242    } else {
03243       int i, j;
03244       gDashSize = TMath::Min((int)sizeof(gDashList),n);
03245       gDashLength = 0;
03246       for (i = 0; i < gDashSize; i++) {
03247          gDashList[i] = dash[i];
03248          gDashLength += gDashList[i];
03249       }
03250       gDashOffset = 0;
03251       gLineStyle = GDK_LINE_ON_OFF_DASH;
03252       gdk_gc_set_line_attributes(gGCdash, fLineWidth,
03253                                  (GdkLineStyle) gLineStyle,
03254                                  (GdkCapStyle) gCapStyle,
03255                                  (GdkJoinStyle) gJoinStyle);
03256    }
03257    fPenModified = kFALSE;
03258 }
03259 
03260 //______________________________________________________________________________
03261 void TGWin32::SetLineStyle(Style_t lstyle)
03262 {
03263    // Set line style.
03264 
03265    if (fLineStyle == lstyle) return;
03266 
03267    fLineStyle = lstyle;
03268    fPenModified = kTRUE;
03269 }
03270 
03271 //______________________________________________________________________________
03272 void TGWin32::UpdateLineStyle()
03273 {
03274    // Update line style
03275 
03276    static Int_t dashed[2] = { 3, 3 };
03277    static Int_t dotted[2] = { 1, 2 };
03278    static Int_t dasheddotted[4] = { 3, 4, 1, 4 };
03279 
03280    if (fLineStyle <= 1) {
03281       SetLineType(0, 0);
03282    } else if (fLineStyle == 2) {
03283       SetLineType(2, dashed);
03284    } else if (fLineStyle == 3) {
03285       SetLineType(2, dotted);
03286    } else if (fLineStyle == 4) {
03287       SetLineType(4, dasheddotted);
03288    } else {
03289       TString st = (TString)gStyle->GetLineStyleString(fLineStyle);
03290       TObjArray *tokens = st.Tokenize(" ");
03291       Int_t nt;
03292       nt = tokens->GetEntries();
03293       Int_t *linestyle = new Int_t[nt];
03294       for (Int_t j = 0; j<nt; j++) {
03295          Int_t it;
03296          sscanf(((TObjString*)tokens->At(j))->GetName(), "%d", &it);
03297          linestyle[j] = (Int_t)(it/4);
03298       }
03299       SetLineType(nt,linestyle);
03300       delete [] linestyle;
03301       delete tokens;
03302    }
03303    fPenModified = kFALSE;
03304 }
03305 
03306 //______________________________________________________________________________
03307 void TGWin32::SetLineWidth(Width_t width)
03308 {
03309    // Set line width.
03310    // width   : line width in pixels
03311 
03312    if ((fLineWidth==width) || (width<0)) return;
03313 
03314    if (width == 1) {
03315       fLineWidth = 0;
03316    } else {
03317       fLineWidth = width;
03318    }
03319 
03320    fPenModified = kTRUE;
03321 }
03322 
03323 //______________________________________________________________________________
03324 void TGWin32::SetMarkerColor(Color_t cindex)
03325 {
03326    // Set color index for markers.
03327 
03328    if ((cindex<0) || (cindex==fMarkerColor)) return;
03329    fMarkerColor = cindex;
03330    fMarkerColorModified = kTRUE;
03331 }
03332 
03333 //______________________________________________________________________________
03334 void TGWin32::UpdateMarkerColor()
03335 {
03336    //
03337 
03338    SetColor(gGCmark, Int_t(fMarkerColor));
03339    fMarkerColorModified = kFALSE;
03340 }
03341 
03342 //______________________________________________________________________________
03343 void TGWin32::SetMarkerSize(Float_t msize)
03344 {
03345    // Set marker size index.
03346    // msize  : marker scale factor
03347 
03348    if ((msize==fMarkerSize) || (msize<0)) return;
03349 
03350    fMarkerSize = msize;
03351    SetMarkerStyle(-fMarkerStyle);
03352 }
03353 
03354 //______________________________________________________________________________
03355 void TGWin32::SetMarkerType(int type, int n, GdkPoint * xy)
03356 {
03357    // Set marker type.
03358    // type      : marker type
03359    // n         : length of marker description
03360    // xy        : list of points describing marker shape
03361    //
03362    // if n == 0 marker is a single point
03363    // if TYPE == 0 marker is hollow circle of diameter N
03364    // if TYPE == 1 marker is filled circle of diameter N
03365    // if TYPE == 2 marker is a hollow polygon describe by line XY
03366    // if TYPE == 3 marker is a filled polygon describe by line XY
03367    // if TYPE == 4 marker is described by segmented line XY
03368    //   e.g. TYPE=4,N=4,XY=(-3,0,3,0,0,-3,0,3) sets a plus shape of 7x7 pixels
03369 
03370    gMarker.type = type;
03371    gMarker.n = n < kMAXMK ? n : kMAXMK;
03372    if (gMarker.type >= 2) {
03373       for (int i = 0; i < gMarker.n; i++) {
03374          gMarker.xy[i] = xy[i];
03375       }
03376    }
03377 }
03378 
03379 //______________________________________________________________________________
03380 void TGWin32::SetMarkerStyle(Style_t markerstyle)
03381 {
03382    // Set marker style.
03383 
03384    if ((fMarkerStyle==markerstyle) || (markerstyle >= 35)) return;
03385    fMarkerStyle = TMath::Abs(markerstyle);
03386    fMarkerStyleModified = kTRUE;
03387 }
03388 
03389 //______________________________________________________________________________
03390 void TGWin32::UpdateMarkerStyle()
03391 {
03392    //
03393 
03394    static GdkPoint shape[15];
03395 
03396    Int_t im = Int_t(4 * fMarkerSize + 0.5);
03397 
03398    if (fMarkerStyle == 2) {
03399       // + shaped marker
03400       shape[0].x = -im;
03401       shape[0].y = 0;
03402       shape[1].x = im;
03403       shape[1].y = 0;
03404       shape[2].x = 0;
03405       shape[2].y = -im;
03406       shape[3].x = 0;
03407       shape[3].y = im;
03408       SetMarkerType(4, 4, shape);
03409    } else if (fMarkerStyle == 3 || fMarkerStyle == 31) {
03410       // * shaped marker
03411       shape[0].x = -im;
03412       shape[0].y = 0;
03413       shape[1].x = im;
03414       shape[1].y = 0;
03415       shape[2].x = 0;
03416       shape[2].y = -im;
03417       shape[3].x = 0;
03418       shape[3].y = im;
03419       im = Int_t(0.707 * Float_t(im) + 0.5);
03420       shape[4].x = -im;
03421       shape[4].y = -im;
03422       shape[5].x = im;
03423       shape[5].y = im;
03424       shape[6].x = -im;
03425       shape[6].y = im;
03426       shape[7].x = im;
03427       shape[7].y = -im;
03428       SetMarkerType(4, 8, shape);
03429    } else if (fMarkerStyle == 4 || fMarkerStyle == 24) {
03430       // O shaped marker
03431       SetMarkerType(0, im * 2, shape);
03432    } else if (fMarkerStyle == 5) {
03433       // X shaped marker
03434       im = Int_t(0.707 * Float_t(im) + 0.5);
03435       shape[0].x = -im;
03436       shape[0].y = -im;
03437       shape[1].x = im;
03438       shape[1].y = im;
03439       shape[2].x = -im;
03440       shape[2].y = im;
03441       shape[3].x = im;
03442       shape[3].y = -im;
03443       SetMarkerType(4, 4, shape);
03444    } else if (fMarkerStyle == 6) {
03445       // + shaped marker (with 1 pixel)
03446       shape[0].x = -1;
03447       shape[0].y = 0;
03448       shape[1].x = 1;
03449       shape[1].y = 0;
03450       shape[2].x = 0;
03451       shape[2].y = -1;
03452       shape[3].x = 0;
03453       shape[3].y = 1;
03454       SetMarkerType(4, 4, shape);
03455    } else if (fMarkerStyle == 7) {
03456       // . shaped marker (with 9 pixel)
03457       shape[0].x = -1;
03458       shape[0].y = 1;
03459       shape[1].x = 1;
03460       shape[1].y = 1;
03461       shape[2].x = -1;
03462       shape[2].y = 0;
03463       shape[3].x = 1;
03464       shape[3].y = 0;
03465       shape[4].x = -1;
03466       shape[4].y = -1;
03467       shape[5].x = 1;
03468       shape[5].y = -1;
03469       SetMarkerType(4, 6, shape);
03470    } else if (fMarkerStyle == 8 || fMarkerStyle == 20) {
03471       // O shaped marker (filled)
03472       SetMarkerType(1, im * 2, shape);
03473    } else if (fMarkerStyle == 21) {
03474       // full square
03475       shape[0].x = -im;
03476       shape[0].y = -im;
03477       shape[1].x = im;
03478       shape[1].y = -im;
03479       shape[2].x = im;
03480       shape[2].y = im;
03481       shape[3].x = -im;
03482       shape[3].y = im;
03483       shape[4].x = -im;
03484       shape[4].y = -im;
03485       SetMarkerType(3, 5, shape);
03486    } else if (fMarkerStyle == 22) {
03487       // full triangle up
03488       shape[0].x = -im;
03489       shape[0].y = im;
03490       shape[1].x = im;
03491       shape[1].y = im;
03492       shape[2].x = 0;
03493       shape[2].y = -im;
03494       shape[3].x = -im;
03495       shape[3].y = im;
03496       SetMarkerType(3, 4, shape);
03497    } else if (fMarkerStyle == 23) {
03498       // full triangle down
03499       shape[0].x = 0;
03500       shape[0].y = im;
03501       shape[1].x = im;
03502       shape[1].y = -im;
03503       shape[2].x = -im;
03504       shape[2].y = -im;
03505       shape[3].x = 0;
03506       shape[3].y = im;
03507       SetMarkerType(3, 4, shape);
03508    } else if (fMarkerStyle == 25) {
03509       // open square
03510       shape[0].x = -im;
03511       shape[0].y = -im;
03512       shape[1].x = im;
03513       shape[1].y = -im;
03514       shape[2].x = im;
03515       shape[2].y = im;
03516       shape[3].x = -im;
03517       shape[3].y = im;
03518       shape[4].x = -im;
03519       shape[4].y = -im;
03520       SetMarkerType(2, 5, shape);
03521    } else if (fMarkerStyle == 26) {
03522       // open triangle up
03523       shape[0].x = -im;
03524       shape[0].y = im;
03525       shape[1].x = im;
03526       shape[1].y = im;
03527       shape[2].x = 0;
03528       shape[2].y = -im;
03529       shape[3].x = -im;
03530       shape[3].y = im;
03531       SetMarkerType(2, 4, shape);
03532    } else if (fMarkerStyle == 27) {
03533       // open losange
03534       Int_t imx = Int_t(2.66 * fMarkerSize + 0.5);
03535       shape[0].x = -imx;
03536       shape[0].y = 0;
03537       shape[1].x = 0;
03538       shape[1].y = -im;
03539       shape[2].x = imx;
03540       shape[2].y = 0;
03541       shape[3].x = 0;
03542       shape[3].y = im;
03543       shape[4].x = -imx;
03544       shape[4].y = 0;
03545       SetMarkerType(2, 5, shape);
03546    } else if (fMarkerStyle == 28) {
03547       // open cross
03548       Int_t imx = Int_t(1.33 * fMarkerSize + 0.5);
03549       shape[0].x = -im;
03550       shape[0].y = -imx;
03551       shape[1].x = -imx;
03552       shape[1].y = -imx;
03553       shape[2].x = -imx;
03554       shape[2].y = -im;
03555       shape[3].x = imx;
03556       shape[3].y = -im;
03557       shape[4].x = imx;
03558       shape[4].y = -imx;
03559       shape[5].x = im;
03560       shape[5].y = -imx;
03561       shape[6].x = im;
03562       shape[6].y = imx;
03563       shape[7].x = imx;
03564       shape[7].y = imx;
03565       shape[8].x = imx;
03566       shape[8].y = im;
03567       shape[9].x = -imx;
03568       shape[9].y = im;
03569       shape[10].x = -imx;
03570       shape[10].y = imx;
03571       shape[11].x = -im;
03572       shape[11].y = imx;
03573       shape[12].x = -im;
03574       shape[12].y = -imx;
03575       SetMarkerType(2, 13, shape);
03576    } else if (fMarkerStyle == 29) {
03577       // full star pentagone
03578       Int_t im1 = Int_t(0.66 * fMarkerSize + 0.5);
03579       Int_t im2 = Int_t(2.00 * fMarkerSize + 0.5);
03580       Int_t im3 = Int_t(2.66 * fMarkerSize + 0.5);
03581       Int_t im4 = Int_t(1.33 * fMarkerSize + 0.5);
03582       shape[0].x = -im;
03583       shape[0].y = im4;
03584       shape[1].x = -im2;
03585       shape[1].y = -im1;
03586       shape[2].x = -im3;
03587       shape[2].y = -im;
03588       shape[3].x = 0;
03589       shape[3].y = -im2;
03590       shape[4].x = im3;
03591       shape[4].y = -im;
03592       shape[5].x = im2;
03593       shape[5].y = -im1;
03594       shape[6].x = im;
03595       shape[6].y = im4;
03596       shape[7].x = im4;
03597       shape[7].y = im4;
03598       shape[8].x = 0;
03599       shape[8].y = im;
03600       shape[9].x = -im4;
03601       shape[9].y = im4;
03602       shape[10].x = -im;
03603       shape[10].y = im4;
03604       SetMarkerType(3, 11, shape);
03605    } else if (fMarkerStyle == 30) {
03606       // open star pentagone
03607       Int_t im1 = Int_t(0.66 * fMarkerSize + 0.5);
03608       Int_t im2 = Int_t(2.00 * fMarkerSize + 0.5);
03609       Int_t im3 = Int_t(2.66 * fMarkerSize + 0.5);
03610       Int_t im4 = Int_t(1.33 * fMarkerSize + 0.5);
03611       shape[0].x = -im;
03612       shape[0].y = im4;
03613       shape[1].x = -im2;
03614       shape[1].y = -im1;
03615       shape[2].x = -im3;
03616       shape[2].y = -im;
03617       shape[3].x = 0;
03618       shape[3].y = -im2;
03619       shape[4].x = im3;
03620       shape[4].y = -im;
03621       shape[5].x = im2;
03622       shape[5].y = -im1;
03623       shape[6].x = im;
03624       shape[6].y = im4;
03625       shape[7].x = im4;
03626       shape[7].y = im4;
03627       shape[8].x = 0;
03628       shape[8].y = im;
03629       shape[9].x = -im4;
03630       shape[9].y = im4;
03631       shape[10].x = -im;
03632       shape[10].y = im4;
03633       SetMarkerType(2, 11, shape);
03634    } else if (fMarkerStyle == 32) {
03635       // open triangle down
03636       shape[0].x =   0;  shape[0].y = im;
03637       shape[1].x =  im;  shape[1].y = -im;
03638       shape[2].x = -im;  shape[2].y = -im;
03639       shape[3].x =   0;  shape[3].y = im;
03640       SetMarkerType(2,4,shape);   
03641    } else if (fMarkerStyle == 33) {
03642       // full losange
03643       Int_t imx = Int_t(2.66*fMarkerSize + 0.5);
03644       shape[0].x =-imx;  shape[0].y = 0;  
03645       shape[1].x =   0;  shape[1].y = -im;
03646       shape[2].x = imx;  shape[2].y = 0;  
03647       shape[3].x =   0;  shape[3].y = im; 
03648       shape[4].x =-imx;  shape[4].y = 0;  
03649       SetMarkerType(3,5,shape);
03650    } else if (fMarkerStyle == 34) {
03651       // full cross
03652       Int_t imx = Int_t(1.33*fMarkerSize + 0.5);
03653       shape[0].x = -im;  shape[0].y =-imx;
03654       shape[1].x =-imx;  shape[1].y =-imx;
03655       shape[2].x =-imx;  shape[2].y = -im;
03656       shape[3].x = imx;  shape[3].y = -im;
03657       shape[4].x = imx;  shape[4].y =-imx;
03658       shape[5].x =  im;  shape[5].y =-imx;
03659       shape[6].x =  im;  shape[6].y = imx;
03660       shape[7].x = imx;  shape[7].y = imx;
03661       shape[8].x = imx;  shape[8].y = im;
03662       shape[9].x =-imx;  shape[9].y = im;
03663       shape[10].x=-imx;  shape[10].y= imx;
03664       shape[11].x= -im;  shape[11].y= imx;
03665       shape[12].x= -im;  shape[12].y=-imx;
03666       SetMarkerType(3,13,shape);
03667    } else {
03668       // single dot
03669       SetMarkerType(0, 0, shape);
03670    }
03671    fMarkerStyleModified = kFALSE;
03672 }
03673 
03674 //______________________________________________________________________________
03675 void TGWin32::SetOpacity(Int_t percent)
03676 {
03677    // Set opacity of a window. This image manipulation routine works
03678    // by adding to a percent amount of neutral to each pixels RGB.
03679    // Since it requires quite some additional color map entries is it
03680    // only supported on displays with more than > 8 color planes (> 256
03681    // colors)
03682 
03683    Int_t depth = gdk_visual_get_best_depth();
03684 
03685    if (depth <= 8) return;
03686    if (percent == 0) return;
03687 
03688    // if 100 percent then just make white
03689    ULong_t *orgcolors = 0, *tmpc = 0;
03690    Int_t maxcolors = 0, ncolors, ntmpc = 0;
03691 
03692    // save previous allocated colors, delete at end when not used anymore
03693    if (gCws->new_colors) {
03694       tmpc = gCws->new_colors;
03695       ntmpc = gCws->ncolors;
03696    }
03697    // get pixmap from server as image
03698    GdkImage *image = gdk_image_get((GdkDrawable*)gCws->drawing, 0, 0,
03699                                    gCws->width, gCws->height);
03700 
03701    // collect different image colors
03702    int x, y;
03703    for (y = 0; y < (int) gCws->height; y++) {
03704       for (x = 0; x < (int) gCws->width; x++) {
03705          ULong_t pixel = GetPixelImage((Drawable_t)image, x, y);
03706          CollectImageColors(pixel, orgcolors, ncolors, maxcolors);
03707       }
03708    }
03709    if (ncolors == 0) {
03710       gdk_image_unref(image);
03711       ::operator delete(orgcolors);
03712       return;
03713    }
03714    // create opaque counter parts
03715    MakeOpaqueColors(percent, orgcolors, ncolors);
03716 
03717    // put opaque colors in image
03718    for (y = 0; y < (int) gCws->height; y++) {
03719       for (x = 0; x < (int) gCws->width; x++) {
03720          ULong_t pixel = GetPixelImage((Drawable_t)image, x, y);
03721          Int_t idx = FindColor(pixel, orgcolors, ncolors);
03722          PutPixel((Drawable_t)image, x, y, gCws->new_colors[idx]);
03723       }
03724    }
03725 
03726    // put image back in pixmap on server
03727    gdk_draw_image(gCws->drawing, gGCpxmp, (GdkImage *)image,
03728                   0, 0, 0, 0, gCws->width, gCws->height);
03729    GdiFlush();
03730 
03731    // clean up
03732    if (tmpc) {
03733       gdk_colors_free((GdkColormap *)fColormap, tmpc, ntmpc, 0);
03734       delete[]tmpc;
03735    }
03736    gdk_image_unref(image);
03737    ::operator delete(orgcolors);
03738 }
03739 
03740 //______________________________________________________________________________
03741 void TGWin32::MakeOpaqueColors(Int_t percent, ULong_t *orgcolors, Int_t ncolors)
03742 {
03743    // Get RGB values for orgcolors, add percent neutral to the RGB and
03744    // allocate new_colors.
03745 
03746    Int_t ret;
03747    if (ncolors <= 0) return;
03748    GdkColor *xcol = new GdkColor[ncolors];
03749 
03750    int i;
03751    for (i = 0; i < ncolors; i++) {
03752       xcol[i].pixel = orgcolors[i];
03753       xcol[i].red = xcol[i].green = xcol[i].blue = 0;
03754    }
03755 
03756    GdkColorContext *cc;
03757    cc = gdk_color_context_new(gdk_visual_get_system(), (GdkColormap *)fColormap);
03758    gdk_color_context_query_colors(cc, xcol, ncolors);
03759    gdk_color_context_free(cc);
03760 
03761    UShort_t add = percent * kBIGGEST_RGB_VALUE / 100;
03762 
03763    Int_t val;
03764    for (i = 0; i < ncolors; i++) {
03765       val = xcol[i].red + add;
03766       if (val > kBIGGEST_RGB_VALUE) {
03767          val = kBIGGEST_RGB_VALUE;
03768       }
03769       xcol[i].red = (UShort_t) val;
03770       val = xcol[i].green + add;
03771       if (val > kBIGGEST_RGB_VALUE) {
03772          val = kBIGGEST_RGB_VALUE;
03773       }
03774       xcol[i].green = (UShort_t) val;
03775       val = xcol[i].blue + add;
03776       if (val > kBIGGEST_RGB_VALUE) {
03777          val = kBIGGEST_RGB_VALUE;
03778       }
03779       xcol[i].blue = (UShort_t) val;
03780 
03781       ret = gdk_color_alloc((GdkColormap *)fColormap, &xcol[i]);
03782 
03783       if (!ret) {
03784          Warning("MakeOpaqueColors",
03785                  "failed to allocate color %hd, %hd, %hd", xcol[i].red,
03786                  xcol[i].green, xcol[i].blue);
03787       // assumes that in case of failure xcol[i].pixel is not changed
03788       }
03789    }
03790 
03791    gCws->new_colors = new ULong_t[ncolors];
03792    gCws->ncolors = ncolors;
03793 
03794    for (i = 0; i < ncolors; i++) {
03795       gCws->new_colors[i] = xcol[i].pixel;
03796    }
03797 
03798    delete []xcol;
03799 }
03800 
03801 //______________________________________________________________________________
03802 Int_t TGWin32::FindColor(ULong_t pixel, ULong_t * orgcolors, Int_t ncolors)
03803 {
03804    // Returns index in orgcolors (and new_colors) for pixel.
03805 
03806    for (int i = 0; i < ncolors; i++) {
03807       if (pixel == orgcolors[i]) return i;
03808    }
03809    Error("FindColor", "did not find color, should never happen!");
03810 
03811    return 0;
03812 }
03813 
03814 //______________________________________________________________________________
03815 void TGWin32::SetRGB(int cindex, float r, float g, float b)
03816 {
03817    // Set color intensities for given color index.
03818    // cindex     : color index
03819    // r,g,b      : red, green, blue intensities between 0.0 and 1.0
03820 
03821    GdkColor xcol;
03822 
03823    if (fColormap && cindex >= 0) {
03824       xcol.red = (unsigned short) (r * kBIGGEST_RGB_VALUE);
03825       xcol.green = (unsigned short) (g * kBIGGEST_RGB_VALUE);
03826       xcol.blue = (unsigned short) (b * kBIGGEST_RGB_VALUE);
03827       xcol.pixel = RGB(xcol.red, xcol.green, xcol.blue);
03828 
03829       XColor_t &col = GetColor(cindex);
03830       if (col.fDefined) {
03831          // if color is already defined with same rgb just return
03832          if (col.color.red  == xcol.red && col.color.green == xcol.green &&
03833              col.color.blue == xcol.blue)
03834             return;
03835          col.fDefined = kFALSE;
03836          gdk_colormap_free_colors((GdkColormap *) fColormap,
03837                                   (GdkColor *)&col, 1);
03838       }
03839 
03840       Int_t ret = gdk_colormap_alloc_color(fColormap, &xcol, 1, 1);
03841       if (ret != 0) {
03842          col.fDefined = kTRUE;
03843          col.color.pixel   = xcol.pixel;
03844          col.color.red     = xcol.red;
03845          col.color.green   = xcol.green;
03846          col.color.blue    = xcol.blue;
03847       }
03848    }
03849 }
03850 
03851 //______________________________________________________________________________
03852 void TGWin32::SetTextAlign(Short_t talign)
03853 {
03854    // Set text alignment.
03855    // txalh   : horizontal text alignment
03856    // txalv   : vertical text alignment
03857 
03858    static Short_t current = 0;
03859    if (talign==current) return;
03860    current = talign;
03861 
03862    Int_t txalh = talign / 10;
03863    Int_t txalv = talign % 10;
03864    fTextAlignH = txalh;
03865    fTextAlignV = txalv;
03866 
03867    switch (txalh) {
03868 
03869    case 0:
03870    case 1:
03871       switch (txalv) {          //left
03872       case 1:
03873          fTextAlign = 7;        //bottom
03874          break;
03875       case 2:
03876          fTextAlign = 4;        //center
03877          break;
03878       case 3:
03879          fTextAlign = 1;        //top
03880          break;
03881       }
03882       break;
03883    case 2:
03884       switch (txalv) {          //center
03885       case 1:
03886          fTextAlign = 8;        //bottom
03887          break;
03888       case 2:
03889          fTextAlign = 5;        //center
03890          break;
03891       case 3:
03892          fTextAlign = 2;        //top
03893          break;
03894       }
03895       break;
03896    case 3:
03897       switch (txalv) {          //right
03898       case 1:
03899          fTextAlign = 9;        //bottom
03900          break;
03901       case 2:
03902          fTextAlign = 6;        //center
03903          break;
03904       case 3:
03905          fTextAlign = 3;        //top
03906          break;
03907       }
03908       break;
03909    }
03910    TAttText::SetTextAlign(fTextAlign);
03911 }
03912 
03913 //______________________________________________________________________________
03914 void TGWin32::SetTextColor(Color_t cindex)
03915 {
03916    // Set color index for text.
03917 
03918    static Int_t current = 0;
03919    GdkGCValues values;
03920    if ((cindex < 0) || (Int_t(cindex)==current)) return;
03921 
03922    SetColor(gGCtext, Int_t(cindex));
03923    gdk_gc_get_values(gGCtext, &values);
03924    gdk_gc_set_foreground(gGCinvt, &values.background);
03925    gdk_gc_set_background(gGCinvt, &values.foreground);
03926    gdk_gc_set_background(gGCtext, (GdkColor *) & GetColor(0).color);
03927    current = Int_t(cindex);
03928 }
03929 
03930 //______________________________________________________________________________
03931 void TGWin32::Sync(int mode)
03932 {
03933 }
03934 
03935 //______________________________________________________________________________
03936 void TGWin32::UpdateWindow(int mode)
03937 {
03938    // Update display.
03939    // mode : (1) update
03940    //        (0) sync
03941    //
03942    // Synchronise client and server once (not permanent).
03943    // Copy the pixmap gCws->drawing on the window gCws->window
03944    // if the double buffer is on.
03945 
03946    if (gCws && gCws->double_buffer) {
03947       gdk_window_copy_area(gCws->window, gGCpxmp, 0, 0,
03948                            gCws->drawing, 0, 0, gCws->width, gCws->height);
03949    }
03950    Update(mode);
03951 }
03952 
03953 //______________________________________________________________________________
03954 void TGWin32::Warp(int ix, int iy, Window_t id)
03955 {
03956    // Set pointer position.
03957    // ix       : New X coordinate of pointer
03958    // iy       : New Y coordinate of pointer
03959    // Coordinates are relative to the origin of the window id
03960    // or to the origin of the current window if id == 0.
03961 
03962    if (!id) return;
03963 
03964    POINT cpt, tmp;
03965    HWND dw;
03966    if (!id)
03967       dw = (HWND) GDK_DRAWABLE_XID((GdkWindow *)gCws->window);
03968    else
03969       dw = (HWND) GDK_DRAWABLE_XID((GdkWindow *)id);
03970    GetCursorPos(&cpt);
03971    tmp.x = ix > 0 ? ix : cpt.x;
03972    tmp.y = iy > 0 ? iy : cpt.y;
03973    ClientToScreen(dw, &tmp);
03974    SetCursorPos(tmp.x, tmp.y);
03975 }
03976 
03977 //______________________________________________________________________________
03978 void TGWin32::WritePixmap(int wid, unsigned int w, unsigned int h,
03979                           char *pxname)
03980 {
03981    // Write the pixmap wid in the bitmap file pxname.
03982    // wid         : Pixmap address
03983    // w,h         : Width and height of the pixmap.
03984    // lenname     : pixmap name length
03985    // pxname      : pixmap name
03986 
03987    int wval, hval;
03988    wval = w;
03989    hval = h;
03990 
03991    if (!fWindows) return;
03992    gTws = &fWindows[wid];
03993 //   XWriteBitmapFile(fDisplay,pxname,(Pixmap)gTws->drawing,wval,hval,-1,-1);
03994 }
03995 
03996 
03997 //
03998 // Functions for GIFencode()
03999 //
04000 
04001 static FILE *gGifFile;           // output unit used WriteGIF and PutByte
04002 static GdkImage *gGifImage = 0;  // image used in WriteGIF and GetPixel
04003 
04004 extern "C" {
04005    int GIFquantize(UInt_t width, UInt_t height, Int_t * ncol, Byte_t * red,
04006                    Byte_t * green, Byte_t * blue, Byte_t * outputBuf,
04007                    Byte_t * outputCmap);
04008    long GIFencode(int Width, int Height, Int_t Ncol, Byte_t R[],
04009                   Byte_t G[], Byte_t B[], Byte_t ScLine[],
04010                   void (*get_scline) (int, int, Byte_t *),
04011                   void (*pb) (Byte_t));
04012    int GIFdecode(Byte_t * GIFarr, Byte_t * PIXarr, int *Width, int *Height,
04013                  int *Ncols, Byte_t * R, Byte_t * G, Byte_t * B);
04014    int GIFinfo(Byte_t * GIFarr, int *Width, int *Height, int *Ncols);
04015 }
04016 
04017 
04018 //______________________________________________________________________________
04019 static void GetPixel(int y, int width, Byte_t * scline)
04020 {
04021    // Get pixels in line y and put in array scline.
04022 
04023    for (int i = 0; i < width; i++) {
04024        scline[i] = Byte_t(GetPixelImage((Drawable_t)gGifImage, i, y));
04025    }
04026 }
04027 
04028 //______________________________________________________________________________
04029 static void PutByte(Byte_t b)
04030 {
04031    // Put byte b in output stream.
04032 
04033    if (ferror(gGifFile) == 0) fputc(b, gGifFile);
04034 }
04035 
04036 //______________________________________________________________________________
04037 void TGWin32::ImgPickPalette(GdkImage * image, Int_t & ncol, Int_t * &R,
04038                              Int_t * &G, Int_t * &B)
04039 {
04040    // Returns in R G B the ncol colors of the palette used by the image.
04041    // The image pixels are changed to index values in these R G B arrays.
04042    // This produces a colormap with only the used colors (so even on displays
04043    // with more than 8 planes we will be able to create GIF's when the image
04044    // contains no more than 256 different colors). If it does contain more
04045    // colors we will have to use GIFquantize to reduce the number of colors.
04046    // The R G B arrays must be deleted by the caller.
04047 
04048    ULong_t *orgcolors = 0;
04049    Int_t maxcolors = 0, ncolors;
04050 
04051    // collect different image colors
04052    int x, y;
04053    for (x = 0; x < (int) gCws->width; x++) {
04054       for (y = 0; y < (int) gCws->height; y++) {
04055          ULong_t pixel = GetPixelImage((Drawable_t)image, x, y);
04056          CollectImageColors(pixel, orgcolors, ncolors, maxcolors);
04057       }
04058    }
04059 
04060    // get RGB values belonging to pixels
04061    GdkColor *xcol = new GdkColor[ncolors];
04062 
04063    int i;
04064    for (i = 0; i < ncolors; i++) {
04065       xcol[i].pixel = orgcolors[i];
04066 //      xcol[i].red   = xcol[i].green = xcol[i].blue = 0;
04067       xcol[i].red = GetRValue(xcol[i].pixel);
04068       xcol[i].green = GetGValue(xcol[i].pixel);
04069       xcol[i].blue = GetBValue(xcol[i].pixel);
04070    }
04071 
04072    GdkColorContext *cc;
04073    cc =  gdk_color_context_new(gdk_visual_get_system(), (GdkColormap *)fColormap);
04074    gdk_color_context_query_colors(cc, xcol, ncolors);
04075    gdk_color_context_free(cc);
04076 
04077    // create RGB arrays and store RGB's for each color and set number of colors
04078    // (space must be delete by caller)
04079    R = new Int_t[ncolors];
04080    G = new Int_t[ncolors];
04081    B = new Int_t[ncolors];
04082 
04083    for (i = 0; i < ncolors; i++) {
04084       R[i] = xcol[i].red;
04085       G[i] = xcol[i].green;
04086       B[i] = xcol[i].blue;
04087    }
04088    ncol = ncolors;
04089 
04090    // update image with indices (pixels) into the new RGB colormap
04091    for (x = 0; x < (int) gCws->width; x++) {
04092       for (y = 0; y < (int) gCws->height; y++) {
04093          ULong_t pixel = GetPixelImage((Drawable_t)image, x, y);
04094          Int_t idx = FindColor(pixel, orgcolors, ncolors);
04095          PutPixel((Drawable_t)image, x, y, idx);
04096       }
04097    }
04098 
04099    // cleanup
04100    delete[]xcol;
04101    ::operator delete(orgcolors);
04102 }
04103 
04104 //______________________________________________________________________________
04105 Int_t TGWin32::WriteGIF(char *name)
04106 {
04107    // Writes the current window into GIF file.
04108 
04109    Byte_t scline[2000], r[256], b[256], g[256];
04110    Int_t *R, *G, *B;
04111    Int_t ncol, maxcol, i;
04112 
04113    if (gGifImage) {
04114       gdk_image_unref((GdkImage *)gGifImage);
04115    }
04116 
04117    gGifImage = gdk_image_get((GdkDrawable*)gCws->drawing, 0, 0,
04118                              gCws->width, gCws->height);
04119 
04120    ImgPickPalette(gGifImage, ncol, R, G, B);
04121 
04122    if (ncol > 256) {
04123       //GIFquantize(...);
04124       Error("WriteGIF",
04125             "can not create GIF of image containing more than 256 colors");
04126       delete[]R;
04127       delete[]G;
04128       delete[]B;
04129       return 0;
04130    }
04131 
04132    maxcol = 0;
04133    for (i = 0; i < ncol; i++) {
04134       if (maxcol < R[i]) maxcol = R[i];
04135       if (maxcol < G[i]) maxcol = G[i];
04136       if (maxcol < B[i]) maxcol = B[i];
04137       r[i] = 0;
04138       g[i] = 0;
04139       b[i] = 0;
04140    }
04141    if (maxcol != 0) {
04142       for (i = 0; i < ncol; i++) {
04143          r[i] = R[i] * 255 / maxcol;
04144          g[i] = G[i] * 255 / maxcol;
04145          b[i] = B[i] * 255 / maxcol;
04146       }
04147    }
04148 
04149    gGifFile = fopen(name, "wb");
04150 
04151    if (gGifFile) {
04152       GIFencode(gCws->width, gCws->height,
04153           ncol, r, g, b, scline, ::GetPixel, PutByte);
04154       fclose(gGifFile);
04155       i = 1;
04156     } else {
04157       Error("WriteGIF","cannot write file: %s",name);
04158       i = 0;
04159    }
04160    delete[]R;
04161    delete[]G;
04162    delete[]B;
04163 
04164    return i;
04165 }
04166 
04167 //______________________________________________________________________________
04168 void TGWin32::PutImage(int offset, int itran, int x0, int y0, int nx,
04169                        int ny, int xmin, int ymin, int xmax, int ymax,
04170                        unsigned char *image, Drawable_t wid)
04171 {
04172    // Draw image.
04173 
04174    const int MAX_SEGMENT = 20;
04175    int i, n, x, y, xcur, x1, x2, y1, y2;
04176    unsigned char *jimg, *jbase, icol;
04177    int nlines[256];
04178    GdkSegment lines[256][MAX_SEGMENT];
04179    GdkDrawable *id;
04180 
04181    if (wid) {
04182       id = (GdkDrawable*)wid;
04183    } else {
04184       id = gCws->drawing;
04185    }
04186 
04187    for (i = 0; i < 256; i++) nlines[i] = 0;
04188 
04189    x1 = x0 + xmin;
04190    y1 = y0 + ny - ymax - 1;
04191    x2 = x0 + xmax;
04192    y2 = y0 + ny - ymin - 1;
04193    jbase = image + (ymin - 1) * nx + xmin;
04194 
04195    for (y = y2; y >= y1; y--) {
04196       xcur = x1;
04197       jbase += nx;
04198       for (jimg = jbase, icol = *jimg++, x = x1 + 1; x <= x2; jimg++, x++) {
04199          if (icol != *jimg) {
04200             if (icol != itran) {
04201                n = nlines[icol]++;
04202                lines[icol][n].x1 = xcur;
04203                lines[icol][n].y1 = y;
04204                lines[icol][n].x2 = x - 1;
04205                lines[icol][n].y2 = y;
04206                if (nlines[icol] == MAX_SEGMENT) {
04207                   SetColor(gGCline, (int) icol + offset);
04208                   gdk_win32_draw_segments(id, (GdkGC *) gGCline,
04209                                        (GdkSegment *) &lines[icol][0], MAX_SEGMENT);
04210                   nlines[icol] = 0;
04211                }
04212             }
04213             icol = *jimg;
04214             xcur = x;
04215          }
04216       }
04217       if (icol != itran) {
04218          n = nlines[icol]++;
04219          lines[icol][n].x1 = xcur;
04220          lines[icol][n].y1 = y;
04221          lines[icol][n].x2 = x - 1;
04222          lines[icol][n].y2 = y;
04223          if (nlines[icol] == MAX_SEGMENT) {
04224             SetColor(gGCline, (int) icol + offset);
04225             gdk_win32_draw_segments(id, (GdkGC *) gGCline,
04226                               (GdkSegment *)&lines[icol][0], MAX_SEGMENT);
04227             nlines[icol] = 0;
04228          }
04229       }
04230    }
04231 
04232    for (i = 0; i < 256; i++) {
04233       if (nlines[i] != 0) {
04234          SetColor(gGCline, i + offset);
04235          gdk_win32_draw_segments(id, (GdkGC *) gGCline,
04236                            (GdkSegment *)&lines[icol][0], nlines[i]);
04237       }
04238    }
04239 }
04240 
04241 //______________________________________________________________________________
04242 Pixmap_t TGWin32::ReadGIF(int x0, int y0, const char *file, Window_t id)
04243 {
04244    // If id is NULL - loads the specified gif file at position [x0,y0] in the
04245    // current window. Otherwise creates pixmap from gif file
04246 
04247    FILE *fd;
04248    Seek_t filesize;
04249    unsigned char *GIFarr, *PIXarr, R[256], G[256], B[256], *j1, *j2, icol;
04250    int i, j, k, width, height, ncolor, irep, offset;
04251    float rr, gg, bb;
04252    Pixmap_t pic = 0;
04253 
04254    fd = fopen(file, "r+b");
04255    if (!fd) {
04256       Error("ReadGIF", "unable to open GIF file");
04257       return pic;
04258    }
04259 
04260    fseek(fd, 0L, 2);
04261    filesize = Seek_t(ftell(fd));
04262    fseek(fd, 0L, 0);
04263 
04264    if (!(GIFarr = (unsigned char *) calloc(filesize + 256, 1))) {
04265       Error("ReadGIF", "unable to allocate array for gif");
04266       return pic;
04267    }
04268 
04269    if (fread(GIFarr, filesize, 1, fd) != 1) {
04270       Error("ReadGIF", "GIF file read failed");
04271       return pic;
04272    }
04273 
04274    irep = GIFinfo(GIFarr, &width, &height, &ncolor);
04275    if (irep != 0) {
04276       return pic;
04277    }
04278 
04279    if (!(PIXarr = (unsigned char *) calloc((width * height), 1))) {
04280       Error("ReadGIF", "unable to allocate array for image");
04281       return pic;
04282    }
04283 
04284    irep = GIFdecode(GIFarr, PIXarr, &width, &height, &ncolor, R, G, B);
04285    if (irep != 0) {
04286       return pic;
04287    }
04288    // S E T   P A L E T T E
04289 
04290    offset = 8;
04291 
04292    for (i = 0; i < ncolor; i++) {
04293       rr = R[i] / 255.;
04294       gg = G[i] / 255.;
04295       bb = B[i] / 255.;
04296       j = i + offset;
04297       SetRGB(j, rr, gg, bb);
04298    }
04299 
04300    // O U T P U T   I M A G E
04301 
04302    for (i = 1; i <= height / 2; i++) {
04303       j1 = PIXarr + (i - 1) * width;
04304       j2 = PIXarr + (height - i) * width;
04305       for (k = 0; k < width; k++) {
04306          icol = *j1;
04307          *j1++ = *j2;
04308          *j2++ = icol;
04309       }
04310    }
04311 
04312    if (id) pic = CreatePixmap(id, width, height);
04313    PutImage(offset, -1, x0, y0, width, height, 0, 0, width-1, height-1, PIXarr, pic);
04314 
04315    if (pic) return pic;
04316    else if (gCws->drawing) return  (Pixmap_t)gCws->drawing;
04317    else return 0;
04318 }
04319 
04320 //////////////////////////// GWin32Gui //////////////////////////////////////////
04321 //______________________________________________________________________________
04322 void TGWin32::MapWindow(Window_t id)
04323 {
04324    // Map window on screen.
04325 
04326    if (!id) return;
04327 
04328    gdk_window_show((GdkWindow *)id);
04329    if ((GDK_DRAWABLE_TYPE((GdkWindow *)id) != GDK_WINDOW_TEMP) &&
04330        (GetParent(id) == GetDefaultRootWindow())) {
04331       HWND window = (HWND)GDK_DRAWABLE_XID((GdkWindow *)id);
04332       ::SetForegroundWindow(window);
04333    }
04334 }
04335 
04336 //______________________________________________________________________________
04337 void TGWin32::MapSubwindows(Window_t id)
04338 {
04339    //
04340 
04341    if (!id) return;
04342 
04343    HWND wp;
04344    EnumChildWindows((HWND)GDK_DRAWABLE_XID((GdkWindow *)id),
04345                     EnumChildProc, (LPARAM) NULL);
04346 }
04347 
04348 //______________________________________________________________________________
04349 void TGWin32::MapRaised(Window_t id)
04350 {
04351    // Map window on screen and put on top of all windows.
04352 
04353    if (!id) return;
04354 
04355    HWND hwnd = ::GetForegroundWindow();
04356    HWND window = (HWND)GDK_DRAWABLE_XID((GdkWindow *)id);
04357    gdk_window_show((GdkWindow *)id);
04358    if (GDK_DRAWABLE_TYPE((GdkWindow *)id) != GDK_WINDOW_TEMP) {
04359       ::BringWindowToTop(window);
04360       if (GDK_DRAWABLE_TYPE((GdkWindow *)id) != GDK_WINDOW_CHILD)
04361          ::SetForegroundWindow(window);
04362    }
04363 
04364    if (gConsoleWindow && (hwnd == (HWND)gConsoleWindow)) {
04365       RECT r1, r2, r3;
04366       ::GetWindowRect((HWND)gConsoleWindow, &r1);
04367       HWND fore = ::GetForegroundWindow();
04368       ::GetWindowRect(fore, &r2);
04369       if (!::IntersectRect(&r3, &r2, &r1)) {
04370          ::SetForegroundWindow((HWND)gConsoleWindow);
04371       }
04372    }
04373 }
04374 
04375 //______________________________________________________________________________
04376 void TGWin32::UnmapWindow(Window_t id)
04377 {
04378    // Unmap window from screen.
04379 
04380    if (!id) return;
04381 
04382    gdk_window_hide((GdkWindow *) id);
04383 }
04384 
04385 //______________________________________________________________________________
04386 void TGWin32::DestroyWindow(Window_t id)
04387 {
04388    // Destroy window.
04389 
04390    if (!id) return;
04391 
04392    gdk_window_destroy((GdkDrawable *) id, kTRUE);
04393 }
04394 
04395 //______________________________________________________________________________
04396 void TGWin32::DestroySubwindows(Window_t id)
04397 {
04398    // Destroy all internal subwindows
04399 
04400    if (!id) return;
04401 
04402    gdk_window_destroy((GdkDrawable *) id, kFALSE);
04403 }
04404 
04405 //______________________________________________________________________________
04406 void TGWin32::RaiseWindow(Window_t id)
04407 {
04408    // Put window on top of window stack.
04409 
04410    if (!id) return;
04411 
04412    HWND window = (HWND)GDK_DRAWABLE_XID((GdkWindow *)id);
04413    if (GDK_DRAWABLE_TYPE((GdkWindow *)id) == GDK_WINDOW_TEMP) {
04414        ::SetWindowPos(window, HWND_TOPMOST,  0, 0, 0, 0,
04415                       SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
04416    }
04417    else {
04418       ::BringWindowToTop(window);
04419       if (GDK_DRAWABLE_TYPE((GdkWindow *)id) != GDK_WINDOW_CHILD)
04420          ::SetForegroundWindow(window);
04421    }
04422 }
04423 
04424 //______________________________________________________________________________
04425 void TGWin32::LowerWindow(Window_t id)
04426 {
04427    // Lower window so it lays below all its siblings.
04428 
04429    if (!id) return;
04430 
04431    HWND window = (HWND)GDK_DRAWABLE_XID((GdkWindow *)id);
04432    ::SetWindowPos(window, HWND_BOTTOM, 0, 0, 0, 0,
04433                   SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
04434 }
04435 
04436 //______________________________________________________________________________
04437 void TGWin32::MoveWindow(Window_t id, Int_t x, Int_t y)
04438 {
04439    // Move a window.
04440 
04441    if (!id) return;
04442 
04443    gdk_window_move((GdkDrawable *) id, x, y);
04444 }
04445 
04446 //______________________________________________________________________________
04447 void TGWin32::MoveResizeWindow(Window_t id, Int_t x, Int_t y, UInt_t w,
04448                                UInt_t h)
04449 {
04450    // Move and resize a window.
04451 
04452    if (!id) return;
04453 
04454    gdk_window_move_resize((GdkWindow *) id, x, y, w, h);
04455 }
04456 
04457 //______________________________________________________________________________
04458 void TGWin32::ResizeWindow(Window_t id, UInt_t w, UInt_t h)
04459 {
04460    // Resize the window.
04461 
04462    if (!id) return;
04463 
04464    gdk_window_resize((GdkWindow *) id, w, h);
04465 }
04466 
04467 //______________________________________________________________________________
04468 void TGWin32::IconifyWindow(Window_t id)
04469 {
04470    // Iconify the window.
04471 
04472    if (!id) return;
04473 
04474    gdk_window_lower((GdkWindow *) id);
04475    ::CloseWindow((HWND)GDK_DRAWABLE_XID((GdkWindow *)id));
04476 }
04477 
04478 //______________________________________________________________________________
04479 void TGWin32::ReparentWindow(Window_t id, Window_t pid, Int_t x, Int_t y)
04480 {
04481    // Reparent window, make pid the new parent and position the window at
04482    // position (x,y) in new parent.
04483 
04484    if (!id) return;
04485 
04486    gdk_window_reparent((GdkWindow *)id, (GdkWindow *)pid, x, y);
04487 }
04488 
04489 //______________________________________________________________________________
04490 void TGWin32::SetWindowBackground(Window_t id, ULong_t color)
04491 {
04492    // Set the window background color.
04493 
04494    if (!id) return;
04495 
04496    GdkColor back;
04497    back.pixel = color;
04498    back.red = GetRValue(color);
04499    back.green = GetGValue(color);
04500    back.blue = GetBValue(color);
04501 
04502    gdk_window_set_background((GdkWindow *) id, &back);
04503 }
04504 
04505 //______________________________________________________________________________
04506 void TGWin32::SetWindowBackgroundPixmap(Window_t id, Pixmap_t pxm)
04507 {
04508    // Set pixmap as window background.
04509 
04510    if (!id) return;
04511 
04512    gdk_window_set_back_pixmap((GdkWindow *) id, (GdkPixmap *) pxm, 0);
04513 }
04514 
04515 //______________________________________________________________________________
04516 Window_t TGWin32::CreateWindow(Window_t parent, Int_t x, Int_t y,
04517                                UInt_t w, UInt_t h, UInt_t border,
04518                                Int_t depth, UInt_t clss,
04519                                void *visual, SetWindowAttributes_t * attr,
04520                                UInt_t wtype)
04521 {
04522    // Return handle to newly created gdk window.
04523 
04524    GdkWMDecoration deco;
04525    GdkWindowAttr xattr;
04526    GdkWindow *newWin;
04527    GdkColor background_color;
04528    ULong_t xmask = 0;
04529    UInt_t xevmask;
04530 
04531    if (attr) {
04532       MapSetWindowAttributes(attr, xmask, xattr);
04533       xattr.window_type = GDK_WINDOW_CHILD;
04534       if (wtype & kMainFrame) {
04535          xattr.window_type = GDK_WINDOW_TOPLEVEL;
04536       }
04537       if (wtype & kTransientFrame) {
04538          xattr.window_type = GDK_WINDOW_DIALOG;
04539       }
04540       if (wtype & kTempFrame) {
04541          xattr.window_type = GDK_WINDOW_TEMP;
04542       }
04543       newWin = gdk_window_new((GdkWindow *) parent, &xattr, xmask);
04544    } else {
04545       xattr.width = w;
04546       xattr.height = h;
04547       xattr.wclass = GDK_INPUT_OUTPUT;
04548       xattr.event_mask = 0L;    //GDK_ALL_EVENTS_MASK;
04549       xattr.event_mask |= GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK |
04550           GDK_PROPERTY_CHANGE_MASK;
04551 //                          GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK;
04552       if (x >= 0) {
04553          xattr.x = x;
04554       } else {
04555          xattr.x = -1.0 * x;
04556       }
04557       if (y >= 0) {
04558          xattr.y = y;
04559       } else {
04560          xattr.y = -1.0 * y;
04561       }
04562       xattr.colormap = gdk_colormap_get_system();
04563       xattr.cursor = NULL;
04564       xattr.override_redirect = TRUE;
04565       if ((xattr.y > 0) && (xattr.x > 0)) {
04566          xmask = GDK_WA_X | GDK_WA_Y | GDK_WA_COLORMAP |
04567              GDK_WA_WMCLASS | GDK_WA_NOREDIR;
04568       } else {
04569          xmask = GDK_WA_COLORMAP | GDK_WA_WMCLASS | GDK_WA_NOREDIR;
04570       }
04571       if (visual != NULL) {
04572          xattr.visual = (GdkVisual *) visual;
04573          xmask |= GDK_WA_VISUAL;
04574       } else {
04575          xattr.visual = gdk_visual_get_system();
04576          xmask |= GDK_WA_VISUAL;
04577       }
04578       xattr.window_type = GDK_WINDOW_CHILD;
04579       if (wtype & kMainFrame) {
04580          xattr.window_type = GDK_WINDOW_TOPLEVEL;
04581       }
04582       if (wtype & kTransientFrame) {
04583          xattr.window_type = GDK_WINDOW_DIALOG;
04584       }
04585       if (wtype & kTempFrame) {
04586          xattr.window_type = GDK_WINDOW_TEMP;
04587       }
04588       newWin = gdk_window_new((GdkWindow *) parent, &xattr, xmask);
04589       gdk_window_set_events(newWin, (GdkEventMask) 0L);
04590    }
04591    if (border > 0) {
04592       gdk_window_set_decorations(newWin,
04593                                  (GdkWMDecoration) GDK_DECOR_BORDER);
04594    }
04595    if (attr) {
04596       if ((attr->fMask & kWABackPixmap)) {
04597          if (attr->fBackgroundPixmap == kNone) {
04598             gdk_window_set_back_pixmap(newWin, (GdkPixmap *) GDK_NONE, 0);
04599          } else if (attr->fBackgroundPixmap == kParentRelative) {
04600             gdk_window_set_back_pixmap(newWin, (GdkPixmap *) GDK_NONE, 1);
04601          } else {
04602             gdk_window_set_back_pixmap(newWin,
04603                                        (GdkPixmap *) attr->
04604                                        fBackgroundPixmap, 0);
04605          }
04606       }
04607       if ((attr->fMask & kWABackPixel)) {
04608          background_color.pixel = attr->fBackgroundPixel;
04609          background_color.red = GetRValue(attr->fBackgroundPixel);
04610          background_color.green = GetGValue(attr->fBackgroundPixel);
04611          background_color.blue = GetBValue(attr->fBackgroundPixel);
04612          gdk_window_set_background(newWin, &background_color);
04613       }
04614    }
04615    if (!fUseSysPointers) {
04616       ::SetClassLong((HWND)GDK_DRAWABLE_XID(newWin), GCL_HCURSOR, 
04617                      (LONG)GDK_CURSOR_XID(fCursors[kPointer]));
04618    }
04619    return (Window_t) newWin;
04620 }
04621 
04622 //______________________________________________________________________________
04623 void TGWin32::MapEventMask(UInt_t & emask, UInt_t & xemask, Bool_t tox)
04624 {
04625    // Map event mask to or from gdk.
04626 
04627    if (tox) {
04628       Long_t lxemask = 0L;
04629       if ((emask & kKeyPressMask)) {
04630          lxemask |= GDK_KEY_PRESS_MASK;
04631       }
04632       if ((emask & kKeyReleaseMask)) {
04633          lxemask |= GDK_KEY_RELEASE_MASK;
04634       }
04635       if ((emask & kButtonPressMask)) {
04636          lxemask |= GDK_BUTTON_PRESS_MASK;
04637       }
04638       if ((emask & kButtonReleaseMask)) {
04639          lxemask |= GDK_BUTTON_RELEASE_MASK;
04640       }
04641       if ((emask & kPointerMotionMask)) {
04642          lxemask |= GDK_POINTER_MOTION_MASK;
04643       }
04644       if ((emask & kButtonMotionMask)) {
04645          lxemask |= GDK_BUTTON_MOTION_MASK;
04646       }
04647       if ((emask & kExposureMask)) {
04648          lxemask |= GDK_EXPOSURE_MASK;
04649       }
04650       if ((emask & kStructureNotifyMask)) {
04651          lxemask |= GDK_STRUCTURE_MASK;
04652       }
04653       if ((emask & kEnterWindowMask)) {
04654          lxemask |= GDK_ENTER_NOTIFY_MASK;
04655       }
04656       if ((emask & kLeaveWindowMask)) {
04657          lxemask |= GDK_LEAVE_NOTIFY_MASK;
04658       }
04659       if ((emask & kFocusChangeMask)) {
04660          lxemask |= GDK_FOCUS_CHANGE_MASK;
04661       }
04662       xemask = (UInt_t) lxemask;
04663    } else {
04664       emask = 0;
04665       if ((xemask & GDK_KEY_PRESS_MASK)) {
04666          emask |= kKeyPressMask;
04667       }
04668       if ((xemask & GDK_KEY_RELEASE_MASK)) {
04669          emask |= kKeyReleaseMask;
04670       }
04671       if ((xemask & GDK_BUTTON_PRESS_MASK)) {
04672          emask |= kButtonPressMask;
04673       }
04674       if ((xemask & GDK_BUTTON_RELEASE_MASK)) {
04675          emask |= kButtonReleaseMask;
04676       }
04677       if ((xemask & GDK_POINTER_MOTION_MASK)) {
04678          emask |= kPointerMotionMask;
04679       }
04680       if ((xemask & GDK_BUTTON_MOTION_MASK)) {
04681          emask |= kButtonMotionMask;
04682       }
04683       if ((xemask & GDK_EXPOSURE_MASK)) {
04684          emask |= kExposureMask;
04685       }
04686       if ((xemask & GDK_STRUCTURE_MASK)) {
04687          emask |= kStructureNotifyMask;
04688       }
04689       if ((xemask & GDK_ENTER_NOTIFY_MASK)) {
04690          emask |= kEnterWindowMask;
04691       }
04692       if ((xemask & GDK_LEAVE_NOTIFY_MASK)) {
04693          emask |= kLeaveWindowMask;
04694       }
04695       if ((xemask & GDK_FOCUS_CHANGE_MASK)) {
04696          emask |= kFocusChangeMask;
04697       }
04698    }
04699 }
04700 
04701 //______________________________________________________________________________
04702 void TGWin32::MapSetWindowAttributes(SetWindowAttributes_t * attr,
04703                                      ULong_t & xmask,
04704                                      GdkWindowAttr & xattr)
04705 {
04706    // Map a SetWindowAttributes_t to a GdkWindowAttr structure.
04707 
04708    Mask_t mask = attr->fMask;
04709    xmask = 0;
04710 
04711    if ((mask & kWAOverrideRedirect)) {
04712       xmask |= GDK_WA_NOREDIR;
04713       xattr.override_redirect = attr->fOverrideRedirect;
04714    }
04715    if ((mask & kWAEventMask)) {
04716       UInt_t xmsk, msk = (UInt_t) attr->fEventMask;
04717       MapEventMask(msk, xmsk, kTRUE);
04718       xattr.event_mask = xmsk;
04719    }
04720    if ((mask & kWAColormap)) {
04721       xmask |= GDK_WA_COLORMAP;
04722       xattr.colormap = (GdkColormap *) attr->fColormap;
04723    }
04724    if ((mask & kWACursor)) {
04725       xmask |= GDK_WA_CURSOR;
04726       if (attr->fCursor != kNone) {
04727          xattr.cursor = (GdkCursor *) attr->fCursor;
04728       }
04729    }
04730    xattr.wclass = GDK_INPUT_OUTPUT;
04731 }
04732 
04733 //______________________________________________________________________________
04734 void TGWin32::MapGCValues(GCValues_t & gval,
04735                           ULong_t & xmask, GdkGCValues & xgval, Bool_t tox)
04736 {
04737    // Map a GCValues_t to a XCGValues structure if tox is true. Map
04738    // the other way in case tox is false.
04739 
04740    if (tox) {
04741       // map GCValues_t to XGCValues
04742       Mask_t mask = gval.fMask;
04743       xmask = 0;
04744 
04745       if ((mask & kGCFunction)) {
04746          xmask |= GDK_GC_FUNCTION;
04747          switch (gval.fFunction) {
04748          case kGXclear:
04749             xgval.function = GDK_CLEAR;
04750             break;
04751          case kGXand:
04752             xgval.function = GDK_AND;
04753             break;
04754          case kGXandReverse:
04755             xgval.function = GDK_AND_REVERSE;
04756             break;
04757          case kGXcopy:
04758             xgval.function = GDK_COPY;
04759             break;
04760          case kGXandInverted:
04761             xgval.function = GDK_AND_INVERT;
04762             break;
04763          case kGXnoop:
04764             xgval.function = GDK_NOOP;
04765             break;
04766          case kGXxor:
04767             xgval.function = GDK_XOR;
04768             break;
04769          case kGXor:
04770             xgval.function = GDK_OR;
04771             break;
04772          case kGXequiv:
04773             xgval.function = GDK_EQUIV;
04774             break;
04775          case kGXinvert:
04776             xgval.function = GDK_INVERT;
04777             break;
04778          case kGXorReverse:
04779             xgval.function = GDK_OR_REVERSE;
04780             break;
04781          case kGXcopyInverted:
04782             xgval.function = GDK_COPY_INVERT;
04783             break;
04784          case kGXorInverted:
04785             xgval.function = GDK_OR_INVERT;
04786             break;
04787          case kGXnand:
04788             xgval.function = GDK_NAND;
04789             break;
04790          case kGXset:
04791             xgval.function = GDK_SET;
04792             break;
04793          }
04794       }
04795       if (mask & kGCSubwindowMode) {
04796          xmask |= GDK_GC_SUBWINDOW;
04797          if (gval.fSubwindowMode == kIncludeInferiors) {
04798             xgval.subwindow_mode = GDK_INCLUDE_INFERIORS;
04799          } else {
04800             xgval.subwindow_mode = GDK_CLIP_BY_CHILDREN;
04801          }
04802       }
04803       if (mask & kGCForeground) {
04804          xmask |= GDK_GC_FOREGROUND;
04805          xgval.foreground.pixel = gval.fForeground;
04806          xgval.foreground.red = GetRValue(gval.fForeground);
04807          xgval.foreground.green = GetGValue(gval.fForeground);
04808          xgval.foreground.blue = GetBValue(gval.fForeground);
04809       }
04810       if (mask & kGCBackground) {
04811          xmask |= GDK_GC_BACKGROUND;
04812          xgval.background.pixel = gval.fBackground;
04813          xgval.background.red = GetRValue(gval.fBackground);
04814          xgval.background.green = GetGValue(gval.fBackground);
04815          xgval.background.blue = GetBValue(gval.fBackground);
04816       }
04817       if (mask & kGCLineWidth) {
04818          xmask |= GDK_GC_LINE_WIDTH;
04819          xgval.line_width = gval.fLineWidth;
04820       }
04821       if (mask & kGCLineStyle) {
04822          xmask |= GDK_GC_LINE_STYLE;
04823          xgval.line_style = (GdkLineStyle) gval.fLineStyle; // ident mapping
04824       }
04825       if (mask & kGCCapStyle) {
04826          xmask |= GDK_GC_CAP_STYLE;
04827          xgval.cap_style = (GdkCapStyle) gval.fCapStyle; // ident mapping
04828       }
04829       if (mask & kGCJoinStyle) {
04830          xmask |= GDK_GC_JOIN_STYLE;
04831          xgval.join_style = (GdkJoinStyle) gval.fJoinStyle; // ident mapping
04832       }
04833       if ((mask & kGCFillStyle)) {
04834          xmask |= GDK_GC_FILL;
04835          xgval.fill = (GdkFill) gval.fFillStyle;   // ident mapping
04836       }
04837       if ((mask & kGCTile)) {
04838          xmask |= GDK_GC_TILE;
04839          xgval.tile = (GdkPixmap *) gval.fTile;
04840       }
04841       if ((mask & kGCStipple)) {
04842          xmask |= GDK_GC_STIPPLE;
04843          xgval.stipple = (GdkPixmap *) gval.fStipple;
04844       }
04845       if ((mask & kGCTileStipXOrigin)) {
04846          xmask |= GDK_GC_TS_X_ORIGIN;
04847          xgval.ts_x_origin = gval.fTsXOrigin;
04848       }
04849       if ((mask & kGCTileStipYOrigin)) {
04850          xmask |= GDK_GC_TS_Y_ORIGIN;
04851          xgval.ts_y_origin = gval.fTsYOrigin;
04852       }
04853       if ((mask & kGCFont)) {
04854          xmask |= GDK_GC_FONT;
04855          xgval.font = (GdkFont *) gval.fFont;
04856       }
04857       if ((mask & kGCGraphicsExposures)) {
04858          xmask |= GDK_GC_EXPOSURES;
04859          xgval.graphics_exposures = gval.fGraphicsExposures;
04860       }
04861       if ((mask & kGCClipXOrigin)) {
04862          xmask |= GDK_GC_CLIP_X_ORIGIN;
04863          xgval.clip_x_origin = gval.fClipXOrigin;
04864       }
04865       if ((mask & kGCClipYOrigin)) {
04866          xmask |= GDK_GC_CLIP_Y_ORIGIN;
04867          xgval.clip_y_origin = gval.fClipYOrigin;
04868       }
04869       if ((mask & kGCClipMask)) {
04870          xmask |= GDK_GC_CLIP_MASK;
04871          xgval.clip_mask = (GdkPixmap *) gval.fClipMask;
04872       }
04873    } else {
04874       // map XValues to GCValues_t
04875       Mask_t mask = 0;
04876 
04877       if ((xmask & GDK_GC_FUNCTION)) {
04878          mask |= kGCFunction;
04879          gval.fFunction = (EGraphicsFunction) xgval.function;   // ident mapping
04880          switch (xgval.function) {
04881          case GDK_CLEAR:
04882             gval.fFunction = kGXclear;
04883             break;
04884          case GDK_AND:
04885             gval.fFunction = kGXand;
04886             break;
04887          case GDK_AND_REVERSE:
04888             gval.fFunction = kGXandReverse;
04889             break;
04890          case GDK_COPY:
04891             gval.fFunction = kGXcopy;
04892             break;
04893          case GDK_AND_INVERT:
04894             gval.fFunction = kGXandInverted;
04895             break;
04896          case GDK_NOOP:
04897             gval.fFunction = kGXnoop;
04898             break;
04899          case GDK_XOR:
04900             gval.fFunction = kGXxor;
04901             break;
04902          case GDK_OR:
04903             gval.fFunction = kGXor;
04904             break;
04905          case GDK_EQUIV:
04906             gval.fFunction = kGXequiv;
04907             break;
04908          case GDK_INVERT:
04909             gval.fFunction = kGXinvert;
04910             break;
04911          case GDK_OR_REVERSE:
04912             gval.fFunction = kGXorReverse;
04913             break;
04914          case GDK_COPY_INVERT:
04915             gval.fFunction = kGXcopyInverted;
04916             break;
04917          case GDK_OR_INVERT:
04918             gval.fFunction = kGXorInverted;
04919             break;
04920          case GDK_NAND:
04921             gval.fFunction = kGXnand;
04922             break;
04923          case GDK_SET:
04924             gval.fFunction = kGXset;
04925             break;
04926          }
04927       }
04928       if (xmask & GDK_GC_SUBWINDOW) {
04929          mask |= kGCSubwindowMode;
04930          if (xgval.subwindow_mode == GDK_INCLUDE_INFERIORS)
04931             gval.fSubwindowMode = kIncludeInferiors;
04932          else
04933             gval.fSubwindowMode = kClipByChildren;
04934       }
04935       if ((xmask & GDK_GC_FOREGROUND)) {
04936          mask |= kGCForeground;
04937          gval.fForeground = xgval.foreground.pixel;
04938       }
04939       if ((xmask & GDK_GC_BACKGROUND)) {
04940          mask |= kGCBackground;
04941          gval.fBackground = xgval.background.pixel;
04942       }
04943       if ((xmask & GDK_GC_LINE_WIDTH)) {
04944          mask |= kGCLineWidth;
04945          gval.fLineWidth = xgval.line_width;
04946       }
04947       if ((xmask & GDK_GC_LINE_STYLE)) {
04948          mask |= kGCLineStyle;
04949          gval.fLineStyle = xgval.line_style;    // ident mapping
04950       }
04951       if ((xmask & GDK_GC_CAP_STYLE)) {
04952          mask |= kGCCapStyle;
04953          gval.fCapStyle = xgval.cap_style;      // ident mapping
04954       }
04955       if ((xmask & GDK_GC_JOIN_STYLE)) {
04956          mask |= kGCJoinStyle;
04957          gval.fJoinStyle = xgval.join_style;    // ident mapping
04958       }
04959       if ((xmask & GDK_GC_FILL)) {
04960          mask |= kGCFillStyle;
04961          gval.fFillStyle = xgval.fill;  // ident mapping
04962       }
04963       if ((xmask & GDK_GC_TILE)) {
04964          mask |= kGCTile;
04965          gval.fTile = (Pixmap_t) xgval.tile;
04966       }
04967       if ((xmask & GDK_GC_STIPPLE)) {
04968          mask |= kGCStipple;
04969          gval.fStipple = (Pixmap_t) xgval.stipple;
04970       }
04971       if ((xmask & GDK_GC_TS_X_ORIGIN)) {
04972          mask |= kGCTileStipXOrigin;
04973          gval.fTsXOrigin = xgval.ts_x_origin;
04974       }
04975       if ((xmask & GDK_GC_TS_Y_ORIGIN)) {
04976          mask |= kGCTileStipYOrigin;
04977          gval.fTsYOrigin = xgval.ts_y_origin;
04978       }
04979       if ((xmask & GDK_GC_FONT)) {
04980          mask |= kGCFont;
04981          gval.fFont = (FontH_t) xgval.font;
04982       }
04983       if ((xmask & GDK_GC_EXPOSURES)) {
04984          mask |= kGCGraphicsExposures;
04985          gval.fGraphicsExposures = (Bool_t) xgval.graphics_exposures;
04986       }
04987       if ((xmask & GDK_GC_CLIP_X_ORIGIN)) {
04988          mask |= kGCClipXOrigin;
04989          gval.fClipXOrigin = xgval.clip_x_origin;
04990       }
04991       if ((xmask & GDK_GC_CLIP_Y_ORIGIN)) {
04992          mask |= kGCClipYOrigin;
04993          gval.fClipYOrigin = xgval.clip_y_origin;
04994       }
04995       if ((xmask & GDK_GC_CLIP_MASK)) {
04996          mask |= kGCClipMask;
04997          gval.fClipMask = (Pixmap_t) xgval.clip_mask;
04998       }
04999       gval.fMask = mask;
05000    }
05001 }
05002 
05003 //______________________________________________________________________________
05004 void TGWin32::GetWindowAttributes(Window_t id, WindowAttributes_t & attr)
05005 {
05006    // Get window attributes and return filled in attributes structure.
05007 
05008    if (!id) return;
05009 
05010    GdkWindowAttr xattr;
05011    RECT rcClient, rcWind;
05012    ::GetClientRect((HWND)GDK_DRAWABLE_XID((GdkWindow *) id), &rcClient);
05013    ::GetWindowRect((HWND)GDK_DRAWABLE_XID((GdkWindow *) id), &rcWind);
05014 
05015    gdk_window_get_geometry((GdkWindow *) id, &attr.fX, &attr.fY,
05016                            &attr.fWidth, &attr.fHeight, &attr.fDepth);
05017    attr.fX = ((rcWind.right - rcWind.left) - rcClient.right) / 2;
05018    attr.fY = ((rcWind.bottom - rcWind.top) - rcClient.bottom) - attr.fX;
05019 
05020    attr.fRoot = (Window_t) GDK_ROOT_PARENT();
05021    attr.fColormap = (Colormap_t) gdk_window_get_colormap((GdkWindow *) id);
05022    attr.fBorderWidth = 0;
05023    attr.fVisual = gdk_window_get_visual((GdkWindow *) id);
05024    attr.fClass = kInputOutput;
05025    attr.fBackingStore = kNotUseful;
05026    attr.fSaveUnder = kFALSE;
05027    attr.fMapInstalled = kTRUE;
05028    attr.fOverrideRedirect = kFALSE;   // boolean value for override-redirect
05029 
05030    if (!gdk_window_is_visible((GdkWindow *) id)) {
05031       attr.fMapState = kIsUnmapped;
05032    } else if (!gdk_window_is_viewable((GdkWindow *) id)) {
05033       attr.fMapState = kIsUnviewable;
05034    } else {
05035       attr.fMapState = kIsViewable;
05036    }
05037 
05038    UInt_t tmp_mask = (UInt_t)gdk_window_get_events((GdkWindow *) id);
05039    UInt_t evmask;
05040    MapEventMask(evmask, tmp_mask, kFALSE);
05041 
05042    attr.fYourEventMask = evmask;
05043 }
05044 
05045 //______________________________________________________________________________
05046 Display_t TGWin32::GetDisplay() const
05047 {
05048    //
05049 
05050    return 0;
05051 }
05052 
05053 //______________________________________________________________________________
05054 Int_t TGWin32::GetDepth() const
05055 {
05056    // Get maximum number of planes.
05057 
05058    return gdk_visual_get_best_depth();
05059 }
05060 
05061 //______________________________________________________________________________
05062 Atom_t TGWin32::InternAtom(const char *atom_name, Bool_t only_if_exist)
05063 {
05064    // Return atom handle for atom_name. If it does not exist
05065    // create it if only_if_exist is false. Atoms are used to communicate
05066    // between different programs (i.e. window manager) via the X server.
05067 
05068    GdkAtom a = gdk_atom_intern((const gchar *) atom_name, only_if_exist);
05069 
05070    if (a == None) return kNone;
05071    return (Atom_t) a;
05072 }
05073 
05074 //______________________________________________________________________________
05075 Window_t TGWin32::GetDefaultRootWindow() const
05076 {
05077    // Return handle to the default root window created when calling
05078    // XOpenDisplay().
05079 
05080    return (Window_t) GDK_ROOT_PARENT();
05081 }
05082 
05083 //______________________________________________________________________________
05084 Window_t TGWin32::GetParent(Window_t id) const
05085 {
05086    // Return the parent of the window.
05087 
05088    if (!id) return (Window_t)0;
05089 
05090    return (Window_t)gdk_window_get_parent((GdkWindow *) id);
05091 }
05092 
05093 //______________________________________________________________________________
05094 FontStruct_t TGWin32::LoadQueryFont(const char *font_name)
05095 {
05096    // Load font and query font. If font is not found 0 is returned,
05097    // otherwise an opaque pointer to the FontStruct_t.
05098    // Free the loaded font using DeleteFont().
05099 
05100    char  family[100], weight[32], slant[32], fontname[256];
05101    Int_t n1, pixel, numfields;
05102 
05103    numfields = sscanf(font_name, "%s -%d%n", family, &pixel, &n1);
05104    if (numfields == 2) {
05105       sprintf(weight,"medium");
05106       if (strstr(font_name, "bold"))
05107          sprintf(weight,"bold");
05108       sprintf(slant,"r");
05109       if (strstr(font_name, "italic"))
05110          sprintf(slant,"i");
05111       sprintf(fontname, "-*-%s-%s-%s-*-*-%d-*-*-*-*-*-iso8859-1", 
05112               family, weight, slant, pixel);
05113    }
05114    else
05115       sprintf(fontname, "%s", font_name);
05116    return (FontStruct_t) gdk_font_load(fontname);
05117 }
05118 
05119 //______________________________________________________________________________
05120 FontH_t TGWin32::GetFontHandle(FontStruct_t fs)
05121 {
05122    // Return handle to font described by font structure.
05123 
05124    if (fs) {
05125       return (FontH_t)gdk_font_ref((GdkFont *) fs);
05126    }
05127    return 0;
05128 }
05129 
05130 //______________________________________________________________________________
05131 void TGWin32::DeleteFont(FontStruct_t fs)
05132 {
05133    // Explicitely delete font structure obtained with LoadQueryFont().
05134 
05135    gdk_font_unref((GdkFont *) fs);
05136 }
05137 
05138 //______________________________________________________________________________
05139 GContext_t TGWin32::CreateGC(Drawable_t id, GCValues_t *gval)
05140 {
05141    // Create a graphics context using the values set in gval (but only for
05142    // those entries that are in the mask).
05143 
05144    if (!id) return (GContext_t)0;
05145 
05146    GdkGCValues xgval;
05147    ULong_t xmask = 0;
05148 
05149    if (gval) MapGCValues(*gval, xmask, xgval, kTRUE);
05150 
05151    xgval.subwindow_mode = GDK_CLIP_BY_CHILDREN; // GDK_INCLUDE_INFERIORS;
05152 
05153    GdkGC *gc = gdk_gc_new_with_values((GdkDrawable *) id,
05154                                       &xgval, (GdkGCValuesMask)xmask);
05155    return (GContext_t) gc;
05156 }
05157 
05158 //______________________________________________________________________________
05159 void TGWin32::ChangeGC(GContext_t gc, GCValues_t * gval)
05160 {
05161    // Change entries in an existing graphics context, gc, by values from gval.
05162 
05163    GdkGCValues xgval;
05164    ULong_t xmask = 0;
05165    Mask_t mask = 0;
05166 
05167    if (gval) {
05168       mask = gval->fMask;
05169       MapGCValues(*gval, xmask, xgval, kTRUE);
05170    }
05171    if (mask & kGCForeground) {
05172       gdk_gc_set_foreground((GdkGC *) gc, &xgval.foreground);
05173    }
05174    if (mask & kGCBackground) {
05175       gdk_gc_set_background((GdkGC *) gc, &xgval.background);
05176    }
05177    if (mask & kGCFont) {
05178       gdk_gc_set_font((GdkGC *) gc, xgval.font);
05179    }
05180    if (mask & kGCFunction) {
05181       gdk_gc_set_function((GdkGC *) gc, xgval.function);
05182    }
05183    if (mask & kGCFillStyle) {
05184       gdk_gc_set_fill((GdkGC *) gc, xgval.fill);
05185    }
05186    if (mask & kGCTile) {
05187       gdk_gc_set_tile((GdkGC *) gc, xgval.tile);
05188    }
05189    if (mask & kGCStipple) {
05190       gdk_gc_set_stipple((GdkGC *) gc, xgval.stipple);
05191    }
05192    if ((mask & kGCTileStipXOrigin) || (mask & kGCTileStipYOrigin)) {
05193       gdk_gc_set_ts_origin((GdkGC *) gc, xgval.ts_x_origin,
05194                            xgval.ts_y_origin);
05195    }
05196    if ((mask & kGCClipXOrigin) || (mask & kGCClipYOrigin)) {
05197       gdk_gc_set_clip_origin((GdkGC *) gc, xgval.clip_x_origin,
05198                              xgval.clip_y_origin);
05199    }
05200    if (mask & kGCClipMask) {
05201       gdk_gc_set_clip_mask((GdkGC *) gc, xgval.clip_mask);
05202    }
05203    if (mask & kGCGraphicsExposures) {
05204       gdk_gc_set_exposures((GdkGC *) gc, xgval.graphics_exposures);
05205    }
05206    if (mask & kGCLineWidth) {
05207       gdk_gc_set_values((GdkGC *) gc, &xgval, GDK_GC_LINE_WIDTH);
05208    }
05209    if (mask & kGCLineStyle) {
05210       gdk_gc_set_values((GdkGC *) gc, &xgval, GDK_GC_LINE_STYLE);
05211    }
05212    if (mask & kGCCapStyle) {
05213       gdk_gc_set_values((GdkGC *) gc, &xgval, GDK_GC_CAP_STYLE);
05214    }
05215    if (mask & kGCJoinStyle) {
05216       gdk_gc_set_values((GdkGC *) gc, &xgval, GDK_GC_JOIN_STYLE);
05217    }
05218    if (mask & kGCSubwindowMode) {
05219       gdk_gc_set_subwindow((GdkGC *) gc, xgval.subwindow_mode);
05220    }
05221 }
05222 
05223 //______________________________________________________________________________
05224 void TGWin32::CopyGC(GContext_t org, GContext_t dest, Mask_t mask)
05225 {
05226    // Copies graphics context from org to dest. Only the values specified
05227    // in mask are copied. Both org and dest must exist.
05228 
05229    GCValues_t gval;
05230    GdkGCValues xgval;
05231    ULong_t xmask;
05232 
05233    if (!mask) {
05234       // in this case copy all fields
05235       mask = (Mask_t) - 1;
05236    }
05237 
05238    gval.fMask = mask;           // only set fMask used to convert to xmask
05239    MapGCValues(gval, xmask, xgval, kTRUE);
05240 
05241    gdk_gc_copy((GdkGC *) dest, (GdkGC *) org);
05242 }
05243 
05244 //______________________________________________________________________________
05245 void TGWin32::DeleteGC(GContext_t gc)
05246 {
05247    // Explicitely delete a graphics context.
05248 
05249    gdk_gc_unref((GdkGC *) gc);
05250 }
05251 
05252 //______________________________________________________________________________
05253 Cursor_t TGWin32::CreateCursor(ECursor cursor)
05254 {
05255    // Create cursor handle (just return cursor from cursor pool fCursors).
05256 
05257    return (Cursor_t) fCursors[cursor];
05258 }
05259 
05260 //______________________________________________________________________________
05261 Pixmap_t TGWin32::CreatePixmap(Drawable_t id, UInt_t w, UInt_t h)
05262 {
05263    // Creates a pixmap of the width and height you specified
05264    // and returns a pixmap ID that identifies it.
05265 
05266    GdkWindow *wid = (GdkWindow *)id;
05267    if (!id) wid =  GDK_ROOT_PARENT();
05268 
05269    return (Pixmap_t) gdk_pixmap_new(wid, w, h, gdk_visual_get_best_depth());
05270 }
05271 
05272 //______________________________________________________________________________
05273 Pixmap_t TGWin32::CreatePixmap(Drawable_t id, const char *bitmap,
05274                                UInt_t width, UInt_t height,
05275                                ULong_t forecolor, ULong_t backcolor,
05276                                Int_t depth)
05277 {
05278    // Create a pixmap from bitmap data. Ones will get foreground color and
05279    // zeroes background color.
05280 
05281    GdkColor fore, back;
05282    fore.pixel = forecolor;
05283    fore.red = GetRValue(forecolor);
05284    fore.green = GetGValue(forecolor);
05285    fore.blue = GetBValue(forecolor);
05286 
05287    back.pixel = backcolor;
05288    back.red = GetRValue(backcolor);
05289    back.green = GetGValue(backcolor);
05290    back.blue = GetBValue(backcolor);
05291 
05292    GdkWindow *wid = (GdkWindow *)id;
05293    if (!id) wid =  GDK_ROOT_PARENT();
05294 
05295    return (Pixmap_t) gdk_pixmap_create_from_data(wid, (char *) bitmap, width,
05296                                                  height, depth, &fore, &back);
05297 }
05298 
05299 //______________________________________________________________________________
05300 Pixmap_t TGWin32::CreateBitmap(Drawable_t id, const char *bitmap,
05301                                UInt_t width, UInt_t height)
05302 {
05303    // Create a bitmap (i.e. pixmap with depth 1) from the bitmap data.
05304 
05305    GdkWindow *wid = (GdkWindow *)id;
05306    if (!id) wid =  GDK_ROOT_PARENT();
05307 
05308    Pixmap_t ret = (Pixmap_t) gdk_bitmap_create_from_data(wid,
05309                                                  (char *)bitmap, width, height);
05310    return ret;
05311 }
05312 
05313 //______________________________________________________________________________
05314 void TGWin32::DeletePixmap(Pixmap_t pmap)
05315 {
05316    // Explicitely delete pixmap resource.
05317 
05318    gdk_pixmap_unref((GdkPixmap *) pmap);
05319 }
05320 
05321 //______________________________________________________________________________
05322 Bool_t TGWin32::CreatePictureFromFile(Drawable_t id, const char *filename,
05323                                       Pixmap_t & pict,
05324                                       Pixmap_t & pict_mask,
05325                                       PictureAttributes_t & attr)
05326 {
05327    // Create a picture pixmap from data on file. The picture attributes
05328    // are used for input and output. Returns kTRUE in case of success,
05329    // kFALSE otherwise. If mask does not exist it is set to kNone.
05330 
05331    GdkBitmap *gdk_pixmap_mask;
05332    if (strstr(filename, ".xpm") || strstr(filename, ".XPM")) {
05333       GdkWindow *wid = (GdkWindow *)id;
05334       if (!id) wid =  GDK_ROOT_PARENT();
05335 
05336       pict = (Pixmap_t) gdk_pixmap_create_from_xpm(wid, &gdk_pixmap_mask, 0,
05337                                                 filename);
05338       pict_mask = (Pixmap_t) gdk_pixmap_mask;
05339    } else if (strstr(filename, ".gif") || strstr(filename, ".GIF")) {
05340       pict = ReadGIF(0, 0, filename, id);
05341       pict_mask = kNone;
05342    }
05343 
05344    gdk_drawable_get_size((GdkPixmap *) pict, (int *) &attr.fWidth,
05345                          (int *) &attr.fHeight);
05346    if (pict) {
05347       return kTRUE;
05348    }
05349    if (pict_mask) {
05350       pict_mask = kNone;
05351    }
05352    return kFALSE;
05353 }
05354 
05355 //______________________________________________________________________________
05356 Bool_t TGWin32::CreatePictureFromData(Drawable_t id, char **data,
05357                                       Pixmap_t & pict,
05358                                       Pixmap_t & pict_mask,
05359                                       PictureAttributes_t & attr)
05360 {
05361    // Create a pixture pixmap from data. The picture attributes
05362    // are used for input and output. Returns kTRUE in case of success,
05363    // kFALSE otherwise. If mask does not exist it is set to kNone.
05364 
05365    GdkBitmap *gdk_pixmap_mask;
05366    GdkWindow *wid = (GdkWindow *)id;
05367    if (!id) wid =  GDK_ROOT_PARENT();
05368 
05369    pict = (Pixmap_t) gdk_pixmap_create_from_xpm_d(wid, &gdk_pixmap_mask, 0,
05370                                                   data);
05371    pict_mask = (Pixmap_t) gdk_pixmap_mask;
05372 
05373    if (pict) {
05374       return kTRUE;
05375    }
05376    if (pict_mask) {
05377       pict_mask = kNone;
05378    }
05379    return kFALSE;
05380 }
05381 
05382 //______________________________________________________________________________
05383 Bool_t TGWin32::ReadPictureDataFromFile(const char *filename, char ***ret_data)
05384 {
05385    // Read picture data from file and store in ret_data. Returns kTRUE in
05386    // case of success, kFALSE otherwise.
05387 
05388    Bool_t ret = kFALSE;
05389    GdkPixmap *pxm = gdk_pixmap_create_from_xpm(NULL, NULL, NULL, filename);
05390    ret_data = 0;
05391 
05392    if (pxm==NULL) return kFALSE;
05393 
05394    HBITMAP hbm = (HBITMAP)GDK_DRAWABLE_XID(pxm);
05395    BITMAP bitmap;
05396 
05397    ret = ::GetObject(hbm, sizeof(HBITMAP), (LPVOID)&bitmap);
05398    ret_data = (char ***)&bitmap.bmBits;
05399    gdk_pixmap_unref(pxm);
05400    return ret;
05401 }
05402 
05403 //______________________________________________________________________________
05404 void TGWin32::DeletePictureData(void *data)
05405 {
05406    // Delete picture data created by the function ReadPictureDataFromFile.
05407 
05408    free(data);
05409 }
05410 
05411 //______________________________________________________________________________
05412 void TGWin32::SetDashes(GContext_t gc, Int_t offset, const char *dash_list,
05413                         Int_t n)
05414 {
05415    // Specify a dash pattertn. Offset defines the phase of the pattern.
05416    // Each element in the dash_list array specifies the length (in pixels)
05417    // of a segment of the pattern. N defines the length of the list.
05418 
05419    int i;
05420    gint8 dashes[32];
05421    for (i = 0; i < n; i++) {
05422       dashes[i] = (gint8) dash_list[i];
05423    }
05424    for (i = n; i < 32; i++) {
05425       dashes[i] = (gint8) 0;
05426    }
05427 
05428    gdk_gc_set_dashes((GdkGC *) gc, offset, dashes, n);
05429 }
05430 
05431 //______________________________________________________________________________
05432 void TGWin32::MapColorStruct(ColorStruct_t * color, GdkColor & xcolor)
05433 {
05434    // Map a ColorStruct_t to a XColor structure.
05435 
05436    xcolor.pixel = color->fPixel;
05437    xcolor.red = color->fRed;
05438    xcolor.green = color->fGreen;
05439    xcolor.blue = color->fBlue;
05440 }
05441 
05442 //______________________________________________________________________________
05443 Bool_t TGWin32::ParseColor(Colormap_t cmap, const char *cname,
05444                            ColorStruct_t & color)
05445 {
05446    // Parse string cname containing color name, like "green" or "#00FF00".
05447    // It returns a filled in ColorStruct_t. Returns kFALSE in case parsing
05448    // failed, kTRUE in case of success. On success, the ColorStruct_t
05449    // fRed, fGreen and fBlue fields are all filled in and the mask is set
05450    // for all three colors, but fPixel is not set.
05451 
05452    GdkColor xc;
05453 
05454    if (gdk_color_parse((char *)cname, &xc)) {
05455       color.fPixel = xc.pixel = RGB(xc.red, xc.green, xc.blue);
05456       color.fRed = xc.red;
05457       color.fGreen = xc.green;
05458       color.fBlue = xc.blue;
05459       return kTRUE;
05460    }
05461    return kFALSE;
05462 }
05463 
05464 //______________________________________________________________________________
05465 Bool_t TGWin32::AllocColor(Colormap_t cmap, ColorStruct_t & color)
05466 {
05467    // Find and allocate a color cell according to the color values specified
05468    // in the ColorStruct_t. If no cell could be allocated it returns kFALSE,
05469    // otherwise kTRUE.
05470 
05471    int status;
05472    GdkColor xc;
05473 
05474    xc.red = color.fRed;
05475    xc.green = color.fGreen;
05476    xc.blue = color.fBlue;
05477 
05478    status = gdk_colormap_alloc_color((GdkColormap *) cmap, &xc, FALSE, TRUE);
05479    color.fPixel = xc.pixel;
05480 
05481    return kTRUE;                // status != 0 ? kTRUE : kFALSE;
05482 }
05483 
05484 //______________________________________________________________________________
05485 void TGWin32::QueryColor(Colormap_t cmap, ColorStruct_t & color)
05486 {
05487    // Fill in the primary color components for a specific pixel value.
05488    // On input fPixel should be set on return the fRed, fGreen and
05489    // fBlue components will be set.
05490 
05491    GdkColor xc;
05492    xc.pixel = color.fPixel;
05493 
05494    GdkColorContext *cc = gdk_color_context_new(gdk_visual_get_system(), fColormap);
05495    gdk_color_context_query_color(cc, &xc);
05496    gdk_color_context_free(cc);
05497 
05498    color.fPixel = xc.pixel;
05499    color.fRed = xc.red;
05500    color.fGreen = xc.green;
05501    color.fBlue = xc.blue;
05502 }
05503 
05504 //______________________________________________________________________________
05505 void TGWin32::FreeColor(Colormap_t cmap, ULong_t pixel)
05506 {
05507    // Free color cell with specified pixel value.
05508 
05509    // FIXME: to be implemented.
05510 }
05511 
05512 //______________________________________________________________________________
05513 Bool_t TGWin32::CheckEvent(Window_t id, EGEventType type, Event_t & ev)
05514 {
05515    // Check if there is for window "id" an event of type "type". If there
05516    // is fill in the event structure and return true. If no such event
05517    // return false.
05518 
05519    if (!id) return kFALSE;
05520 
05521    Event_t tev;
05522    GdkEvent xev;
05523 
05524    tev.fType = type;
05525    tev.fWindow = (Window_t) id;
05526    tev.fTime = 0;
05527    tev.fX = tev.fY = 0;
05528    tev.fXRoot = tev.fYRoot = 0;
05529    tev.fCode = 0;
05530    tev.fState = 0;
05531    tev.fWidth = tev.fHeight = 0;
05532    tev.fCount = 0;
05533    tev.fSendEvent = kFALSE;
05534    tev.fHandle = 0;
05535    tev.fFormat = 0;
05536    tev.fUser[0] = tev.fUser[1] = tev.fUser[2] = tev.fUser[3] = tev.fUser[4] = 0L;
05537 
05538    TGWin32MainThread::LockMSG();
05539    MapEvent(tev, xev, kTRUE);
05540    Bool_t r = gdk_check_typed_window_event((GdkWindow *) id, xev.type, &xev);
05541 
05542    if (r) MapEvent(ev, xev, kFALSE);
05543    TGWin32MainThread::UnlockMSG();
05544 
05545    return r ? kTRUE : kFALSE;
05546 }
05547 
05548 //______________________________________________________________________________
05549 void TGWin32::SendEvent(Window_t id, Event_t * ev)
05550 {
05551    // Send event ev to window id.
05552 
05553    if (!ev || !id) return;
05554 
05555    TGWin32MainThread::LockMSG();
05556    GdkEvent xev;
05557    MapEvent(*ev, xev, kTRUE);
05558    gdk_event_put(&xev);
05559    TGWin32MainThread::UnlockMSG();
05560 }
05561 
05562 //______________________________________________________________________________
05563 Int_t TGWin32::EventsPending()
05564 {
05565     // Returns number of pending events.
05566 
05567    Int_t ret;
05568 
05569    TGWin32MainThread::LockMSG();
05570    ret = (Int_t)gdk_event_queue_find_first();
05571    TGWin32MainThread::UnlockMSG();
05572 
05573    return ret;
05574 }
05575 
05576 //______________________________________________________________________________
05577 void TGWin32::NextEvent(Event_t & event)
05578 {
05579    // Copies first pending event from event queue to Event_t structure
05580    // and removes event from queue. Not all of the event fields are valid
05581    // for each event type, except fType and fWindow.
05582 
05583    TGWin32MainThread::LockMSG();
05584    GdkEvent *xev = gdk_event_unqueue();
05585 
05586    // fill in Event_t
05587    event.fType = kOtherEvent;   // bb add
05588    if (xev == NULL) {
05589       TGWin32MainThread::UnlockMSG();
05590       return;
05591    }
05592    MapEvent(event, *xev, kFALSE);
05593    gdk_event_free (xev);
05594    TGWin32MainThread::UnlockMSG();
05595 }
05596 
05597 //______________________________________________________________________________
05598 void TGWin32::MapModifierState(UInt_t & state, UInt_t & xstate, Bool_t tox)
05599 {
05600    // Map modifier key state to or from X.
05601 
05602    if (tox) {
05603       xstate = state;
05604       if (state & kAnyModifier) {
05605          xstate = GDK_MODIFIER_MASK;
05606       }
05607    } else {
05608       state = xstate;
05609    }
05610 }
05611 
05612 static void _set_event_time(GdkEvent &event, UInt_t time)
05613 {
05614    // set gdk event time
05615 
05616    switch (event.type) {
05617       case GDK_MOTION_NOTIFY:
05618          event.motion.time = time;
05619       case GDK_BUTTON_PRESS:
05620       case GDK_2BUTTON_PRESS:
05621       case GDK_3BUTTON_PRESS:
05622       case GDK_BUTTON_RELEASE:
05623       case GDK_SCROLL:
05624          event.button.time = time;
05625       case GDK_KEY_PRESS:
05626       case GDK_KEY_RELEASE:
05627          event.key.time = time;
05628       case GDK_ENTER_NOTIFY:
05629       case GDK_LEAVE_NOTIFY:
05630          event.crossing.time = time;
05631       case GDK_PROPERTY_NOTIFY:
05632          event.property.time = time;
05633       case GDK_SELECTION_CLEAR:
05634       case GDK_SELECTION_REQUEST:
05635       case GDK_SELECTION_NOTIFY:
05636          event.selection.time = time;
05637       case GDK_PROXIMITY_IN:
05638       case GDK_PROXIMITY_OUT:
05639          event.proximity.time = time;
05640       case GDK_DRAG_ENTER:
05641       case GDK_DRAG_LEAVE:
05642       case GDK_DRAG_MOTION:
05643       case GDK_DRAG_STATUS:
05644       case GDK_DROP_START:
05645       case GDK_DROP_FINISHED:
05646          event.dnd.time = time;
05647       default:                 /* use current time */
05648          break;
05649    }
05650 }
05651 
05652 //______________________________________________________________________________
05653 void TGWin32::MapEvent(Event_t & ev, GdkEvent & xev, Bool_t tox)
05654 {
05655    // Map Event_t structure to gdk_event structure. If tox is false
05656    // map the other way.
05657 
05658    if (tox) {
05659       // map from Event_t to gdk_event
05660       xev.type = GDK_NOTHING;
05661       if (ev.fType == kGKeyPress)
05662          xev.type = GDK_KEY_PRESS;
05663       if (ev.fType == kKeyRelease)
05664          xev.type = GDK_KEY_RELEASE;
05665       if (ev.fType == kButtonPress)
05666          xev.type = GDK_BUTTON_PRESS;
05667       if (ev.fType == kButtonRelease)
05668          xev.type = GDK_BUTTON_RELEASE;
05669       if (ev.fType == kMotionNotify)
05670          xev.type = GDK_MOTION_NOTIFY;
05671       if (ev.fType == kEnterNotify)
05672          xev.type = GDK_ENTER_NOTIFY;
05673       if (ev.fType == kLeaveNotify)
05674          xev.type = GDK_LEAVE_NOTIFY;
05675       if (ev.fType == kExpose)
05676          xev.type = GDK_EXPOSE;
05677       if (ev.fType == kConfigureNotify)
05678          xev.type = GDK_CONFIGURE;
05679       if (ev.fType == kMapNotify)
05680          xev.type = GDK_MAP;
05681       if (ev.fType == kUnmapNotify)
05682          xev.type = GDK_UNMAP;
05683       if (ev.fType == kDestroyNotify)
05684          xev.type = GDK_DESTROY;
05685       if (ev.fType == kClientMessage)
05686          xev.type = GDK_CLIENT_EVENT;
05687       if (ev.fType == kSelectionClear)
05688          xev.type = GDK_SELECTION_CLEAR;
05689       if (ev.fType == kSelectionRequest)
05690          xev.type = GDK_SELECTION_REQUEST;
05691       if (ev.fType == kSelectionNotify)
05692          xev.type = GDK_SELECTION_NOTIFY;
05693 
05694       xev.any.type = xev.type;
05695       xev.any.send_event = ev.fSendEvent;
05696       if (ev.fType == kDestroyNotify) {
05697          xev.any.window = (GdkWindow *) ev.fWindow;
05698       }
05699       if (ev.fType == kFocusIn) {
05700          xev.type = GDK_FOCUS_CHANGE;
05701          xev.focus_change.type = xev.type;
05702          xev.focus_change.window = (GdkWindow *) ev.fWindow;
05703          xev.focus_change.in = TRUE;
05704       }
05705       if (ev.fType == kFocusOut) {
05706          xev.type = GDK_FOCUS_CHANGE;
05707          xev.focus_change.type = xev.type;
05708          xev.focus_change.window = (GdkWindow *) ev.fWindow;
05709          xev.focus_change.in = FALSE;
05710       }
05711       if (ev.fType == kGKeyPress || ev.fType == kKeyRelease) {
05712          xev.key.window = (GdkWindow *) ev.fWindow;
05713          xev.key.type = xev.type;
05714          MapModifierState(ev.fState, xev.key.state, kTRUE); // key mask
05715          xev.key.keyval = ev.fCode; // key code
05716       }
05717       if (ev.fType == kButtonPress || ev.fType == kButtonRelease) {
05718          xev.button.window = (GdkWindow *) ev.fWindow;
05719          xev.button.type = xev.type;
05720          xev.button.x = ev.fX;
05721          xev.button.y = ev.fY;
05722          xev.button.x_root = ev.fXRoot;
05723          xev.button.y_root = ev.fYRoot;
05724          MapModifierState(ev.fState, xev.button.state, kTRUE); // button mask
05725          xev.button.button = ev.fCode; // button code
05726       }
05727       if (ev.fType == kSelectionNotify) {
05728          xev.selection.window = (GdkWindow *) ev.fUser[0];
05729          xev.selection.requestor = (guint32) ev.fUser[0];
05730          xev.selection.selection = (GdkAtom) ev.fUser[1];
05731          xev.selection.target = (GdkAtom) ev.fUser[2];
05732          xev.selection.property = (GdkAtom) ev.fUser[3];
05733          xev.selection.type = xev.type;
05734       }
05735       if (ev.fType == kClientMessage) {
05736          if ((ev.fFormat == 32) && (ev.fHandle == gWM_DELETE_WINDOW)) {
05737             xev.type = GDK_DELETE;
05738             xev.any.type = xev.type;
05739             xev.any.window = (GdkWindow *) ev.fWindow;
05740          } else {
05741             xev.client.window = (GdkWindow *) ev.fWindow;
05742             xev.client.type = xev.type;
05743             xev.client.message_type = (GdkAtom) ev.fHandle;
05744             xev.client.data_format = ev.fFormat;
05745             xev.client.data.l[0] = ev.fUser[0];
05746             if (sizeof(ev.fUser[0]) > 4) {
05747                SplitLong(ev.fUser[1], xev.client.data.l[1],
05748                          xev.client.data.l[3]);
05749                SplitLong(ev.fUser[2], xev.client.data.l[2],
05750                          xev.client.data.l[4]);
05751             } else {
05752                xev.client.data.l[1] = ev.fUser[1];
05753                xev.client.data.l[2] = ev.fUser[2];
05754                xev.client.data.l[3] = ev.fUser[3];
05755                xev.client.data.l[4] = ev.fUser[4];
05756             }
05757          }
05758       }
05759       if (ev.fType == kMotionNotify) {
05760          xev.motion.window = (GdkWindow *) ev.fWindow;
05761          xev.motion.type = xev.type;
05762          xev.motion.x = ev.fX;
05763          xev.motion.y = ev.fY;
05764          xev.motion.x_root = ev.fXRoot;
05765          xev.motion.y_root = ev.fYRoot;
05766       }
05767       if ((ev.fType == kEnterNotify) || (ev.fType == kLeaveNotify)) {
05768          xev.crossing.window = (GdkWindow *) ev.fWindow;
05769          xev.crossing.type = xev.type;
05770          xev.crossing.x = ev.fX;
05771          xev.crossing.y = ev.fY;
05772          xev.crossing.x_root = ev.fXRoot;
05773          xev.crossing.y_root = ev.fYRoot;
05774          xev.crossing.mode = (GdkCrossingMode) ev.fCode; // NotifyNormal, NotifyGrab, NotifyUngrab
05775          MapModifierState(ev.fState, xev.crossing.state, kTRUE);  // key or button mask
05776       }
05777       if (ev.fType == kExpose) {
05778          xev.expose.window = (GdkWindow *) ev.fWindow;
05779          xev.expose.type = xev.type;
05780          xev.expose.area.x = ev.fX;
05781          xev.expose.area.y = ev.fY;
05782          xev.expose.area.width = ev.fWidth;  // width and
05783          xev.expose.area.height = ev.fHeight;   // height of exposed area
05784          xev.expose.count = ev.fCount; // number of expose events still to come
05785       }
05786       if (ev.fType == kConfigureNotify) {
05787          xev.configure.window = (GdkWindow *) ev.fWindow;
05788          xev.configure.type = xev.type;
05789          xev.configure.x = ev.fX;
05790          xev.configure.y = ev.fY;
05791          xev.configure.width = ev.fWidth;
05792          xev.configure.height = ev.fHeight;
05793       }
05794       if (ev.fType == kSelectionClear) {
05795          xev.selection.window = (GdkWindow *) ev.fWindow;
05796          xev.selection.type = xev.type;
05797          xev.selection.selection = ev.fUser[0];
05798       }
05799       if (ev.fType == kSelectionRequest) {
05800          xev.selection.window = (GdkWindow *) ev.fUser[0];
05801          xev.selection.type = xev.type;
05802          xev.selection.selection = ev.fUser[1];
05803          xev.selection.target = ev.fUser[2];
05804          xev.selection.property = ev.fUser[3];
05805       }
05806       if ((ev.fType == kMapNotify) || (ev.fType == kUnmapNotify)) {
05807          xev.any.window = (GdkWindow *) ev.fWindow;
05808       }
05809       if (xev.type != GDK_CLIENT_EVENT)
05810          _set_event_time(xev, ev.fTime);
05811    } else {
05812       // map from gdk_event to Event_t
05813       ev.fType = kOtherEvent;
05814       if (xev.type == GDK_KEY_PRESS)
05815          ev.fType = kGKeyPress;
05816       if (xev.type == GDK_KEY_RELEASE)
05817          ev.fType = kKeyRelease;
05818       if (xev.type == GDK_BUTTON_PRESS)
05819          ev.fType = kButtonPress;
05820       if (xev.type == GDK_BUTTON_RELEASE)
05821          ev.fType = kButtonRelease;
05822       if (xev.type == GDK_MOTION_NOTIFY)
05823          ev.fType = kMotionNotify;
05824       if (xev.type == GDK_ENTER_NOTIFY)
05825          ev.fType = kEnterNotify;
05826       if (xev.type == GDK_LEAVE_NOTIFY)
05827          ev.fType = kLeaveNotify;
05828       if (xev.type == GDK_EXPOSE)
05829          ev.fType = kExpose;
05830       if (xev.type == GDK_CONFIGURE)
05831          ev.fType = kConfigureNotify;
05832       if (xev.type == GDK_MAP)
05833          ev.fType = kMapNotify;
05834       if (xev.type == GDK_UNMAP)
05835          ev.fType = kUnmapNotify;
05836       if (xev.type == GDK_DESTROY)
05837          ev.fType = kDestroyNotify;
05838       if (xev.type == GDK_SELECTION_CLEAR)
05839          ev.fType = kSelectionClear;
05840       if (xev.type == GDK_SELECTION_REQUEST)
05841          ev.fType = kSelectionRequest;
05842       if (xev.type == GDK_SELECTION_NOTIFY)
05843          ev.fType = kSelectionNotify;
05844 
05845       ev.fSendEvent = kFALSE; //xev.any.send_event ? kTRUE : kFALSE;
05846       ev.fTime = gdk_event_get_time((GdkEvent *)&xev);
05847       ev.fWindow = (Window_t) xev.any.window;
05848 
05849       if ((xev.type == GDK_MAP) || (xev.type == GDK_UNMAP)) {
05850          ev.fWindow = (Window_t) xev.any.window;
05851       }
05852       if (xev.type == GDK_DELETE) {
05853          ev.fWindow = (Window_t) xev.any.window;
05854          ev.fType = kClientMessage;
05855          ev.fFormat = 32;
05856          ev.fHandle = gWM_DELETE_WINDOW;
05857          ev.fUser[0] = (Long_t) gWM_DELETE_WINDOW;
05858          if (sizeof(ev.fUser[0]) > 4) {
05859             AsmLong(xev.client.data.l[1], xev.client.data.l[3],
05860                     ev.fUser[1]);
05861             AsmLong(xev.client.data.l[2], xev.client.data.l[4],
05862                     ev.fUser[2]);
05863          } else {
05864             ev.fUser[1] = 0; //xev.client.data.l[1];
05865             ev.fUser[2] = 0; //xev.client.data.l[2];
05866             ev.fUser[3] = 0; //xev.client.data.l[3];
05867             ev.fUser[4] = 0; //xev.client.data.l[4];
05868          }
05869       }
05870       if (xev.type == GDK_DESTROY) {
05871          ev.fType = kDestroyNotify;
05872          ev.fHandle = (Window_t) xev.any.window;   // window to be destroyed
05873          ev.fWindow = (Window_t) xev.any.window;
05874       }
05875       if (xev.type == GDK_FOCUS_CHANGE) {
05876          ev.fWindow = (Window_t) xev.focus_change.window;
05877          ev.fCode = kNotifyNormal;
05878          ev.fState = 0;
05879          if (xev.focus_change.in == TRUE) {
05880             ev.fType = kFocusIn;
05881          } else {
05882             ev.fType = kFocusOut;
05883          }
05884       }
05885       if (ev.fType == kGKeyPress || ev.fType == kKeyRelease) {
05886          ev.fWindow = (Window_t) xev.key.window;
05887          MapModifierState(ev.fState, xev.key.state, kFALSE);   // key mask
05888          ev.fCode = xev.key.keyval;  // key code
05889          ev.fUser[1] = xev.key.length;
05890          if (xev.key.length > 0) ev.fUser[2] = xev.key.string[0];
05891          if (xev.key.length > 1) ev.fUser[3] = xev.key.string[1];
05892          if (xev.key.length > 2) ev.fUser[4] = xev.key.string[2];
05893          HWND tmpwin = (HWND) GetWindow((HWND) GDK_DRAWABLE_XID((GdkWindow *)xev.key.window), GW_CHILD);
05894          if (tmpwin) {
05895             ev.fUser[0] = (ULong_t) gdk_xid_table_lookup((HANDLE)tmpwin);
05896          } else {
05897             ev.fUser[0] = (ULong_t) xev.key.window;
05898          }
05899       }
05900       if (ev.fType == kButtonPress || ev.fType == kButtonRelease) {
05901          ev.fWindow = (Window_t) xev.button.window;
05902          ev.fX = xev.button.x;
05903          ev.fY = xev.button.y;
05904          ev.fXRoot = xev.button.x_root;
05905          ev.fYRoot = xev.button.y_root;
05906          MapModifierState(ev.fState, xev.button.state, kFALSE);   // button mask
05907          ev.fCode = xev.button.button; // button code
05908          POINT tpoint;
05909          tpoint.x = xev.button.x;
05910          tpoint.y = xev.button.y;
05911          HWND tmpwin = ChildWindowFromPoint((HWND) GDK_DRAWABLE_XID((GdkWindow *)xev.button.window), tpoint);
05912          if (tmpwin) {
05913              ev.fUser[0] = (ULong_t) gdk_xid_table_lookup((HANDLE)tmpwin);
05914          } else {
05915             ev.fUser[0] = (ULong_t) 0;
05916          }
05917       }
05918       if (ev.fType == kMotionNotify) {
05919          ev.fWindow = (Window_t) xev.motion.window;
05920          ev.fX = xev.motion.x;
05921          ev.fY = xev.motion.y;
05922          ev.fXRoot = xev.motion.x_root;
05923          ev.fYRoot = xev.motion.y_root;
05924          MapModifierState(ev.fState, xev.motion.state, kFALSE);   // key or button mask
05925 
05926          POINT tpoint;
05927          tpoint.x = xev.button.x;
05928          tpoint.y = xev.button.y;
05929          HWND tmpwin = ChildWindowFromPoint((HWND) GDK_DRAWABLE_XID((GdkWindow *)xev.motion.window), tpoint);
05930          if (tmpwin) {
05931              ev.fUser[0] = (ULong_t)gdk_xid_table_lookup((HANDLE)tmpwin);
05932          } else {
05933             ev.fUser[0] = (ULong_t) xev.motion.window;
05934          }
05935       }
05936       if (ev.fType == kEnterNotify || ev.fType == kLeaveNotify) {
05937          ev.fWindow = (Window_t) xev.crossing.window;
05938          ev.fX = xev.crossing.x;
05939          ev.fY = xev.crossing.y;
05940          ev.fXRoot = xev.crossing.x_root;
05941          ev.fYRoot = xev.crossing.y_root;
05942          ev.fCode = xev.crossing.mode; // NotifyNormal, NotifyGrab, NotifyUngrab
05943          MapModifierState(ev.fState, xev.crossing.state, kFALSE); // key or button mask
05944       }
05945       if (ev.fType == kExpose) {
05946          ev.fWindow = (Window_t) xev.expose.window;
05947          ev.fX = xev.expose.area.x;
05948          ev.fY = xev.expose.area.y;
05949          ev.fWidth = xev.expose.area.width;  // width and
05950          ev.fHeight = xev.expose.area.height;   // height of exposed area
05951          ev.fCount = xev.expose.count; // number of expose events still to come
05952       }
05953       if (ev.fType == kConfigureNotify) {
05954          ev.fWindow = (Window_t) xev.configure.window;
05955          ev.fX = xev.configure.x;
05956          ev.fY = xev.configure.y;
05957          ev.fWidth = xev.configure.width;
05958          ev.fHeight = xev.configure.height;
05959       }
05960       if (xev.type == GDK_CLIENT_EVENT) {
05961          ev.fWindow = (Window_t) xev.client.window;
05962          ev.fType = kClientMessage;
05963          ev.fHandle = xev.client.message_type;
05964          ev.fFormat = xev.client.data_format;
05965          ev.fUser[0] = xev.client.data.l[0];
05966          if (sizeof(ev.fUser[0]) > 4) {
05967             AsmLong(xev.client.data.l[1], xev.client.data.l[3],
05968                     ev.fUser[1]);
05969             AsmLong(xev.client.data.l[2], xev.client.data.l[4],
05970                     ev.fUser[2]);
05971          } else {
05972             ev.fUser[1] = xev.client.data.l[1];
05973             ev.fUser[2] = xev.client.data.l[2];
05974             ev.fUser[3] = xev.client.data.l[3];
05975             ev.fUser[4] = xev.client.data.l[4];
05976          }
05977       }
05978       if (ev.fType == kSelectionClear) {
05979          ev.fWindow = (Window_t) xev.selection.window;
05980          ev.fUser[0] = xev.selection.selection;
05981       }
05982       if (ev.fType == kSelectionRequest) {
05983          ev.fWindow = (Window_t) xev.selection.window;
05984          ev.fUser[0] = (ULong_t) xev.selection.window;
05985          ev.fUser[1] = xev.selection.selection;
05986          ev.fUser[2] = xev.selection.target;
05987          ev.fUser[3] = xev.selection.property;
05988       }
05989       if (ev.fType == kSelectionNotify) {
05990          ev.fWindow = (Window_t) xev.selection.window;
05991          ev.fUser[0] = (ULong_t) xev.selection.window;
05992          ev.fUser[1] = xev.selection.selection;
05993          ev.fUser[2] = xev.selection.target;
05994          ev.fUser[3] = xev.selection.property;
05995       }
05996       if (xev.type == GDK_SCROLL) {
05997          ev.fType = kButtonRelease;
05998          if (xev.scroll.direction == GDK_SCROLL_UP) {
05999             ev.fCode = kButton4;
06000          } else if (xev.scroll.direction == GDK_SCROLL_DOWN) {
06001             ev.fCode = kButton5;
06002          }
06003          ev.fWindow = (Window_t) xev.scroll.window;
06004          ev.fX = xev.scroll.x;
06005          ev.fY = xev.scroll.y;
06006          ev.fXRoot = xev.scroll.x_root;
06007          ev.fYRoot = xev.scroll.y_root;
06008          POINT tpoint;
06009          tpoint.x = xev.scroll.x;
06010          tpoint.y = xev.scroll.y;
06011          HWND tmpwin = ChildWindowFromPoint((HWND) GDK_DRAWABLE_XID((GdkWindow *)xev.scroll.window), tpoint);
06012          if (tmpwin) {
06013              ev.fUser[0] = (ULong_t)gdk_xid_table_lookup((HANDLE)tmpwin);
06014          } else {
06015             ev.fUser[0] = (ULong_t) 0;
06016          }
06017       }
06018    }
06019 }
06020 
06021 //______________________________________________________________________________
06022 void TGWin32::Bell(Int_t percent)
06023 {
06024    //
06025 
06026    gSystem->Beep();
06027 }
06028 
06029 //______________________________________________________________________________
06030 void TGWin32::CopyArea(Drawable_t src, Drawable_t dest, GContext_t gc,
06031                        Int_t src_x, Int_t src_y, UInt_t width,
06032                        UInt_t height, Int_t dest_x, Int_t dest_y)
06033 {
06034    // Copy a drawable (i.e. pixmap) to another drawable (pixmap, window).
06035    // The graphics context gc will be used and the source will be copied
06036    // from src_x,src_y,src_x+width,src_y+height to dest_x,dest_y.
06037 
06038    if (!src || !dest) return;
06039 
06040    gdk_window_copy_area((GdkDrawable *) dest, (GdkGC *) gc, dest_x, dest_y,
06041                         (GdkDrawable *) src, src_x, src_y, width, height);
06042 }
06043 
06044 //______________________________________________________________________________
06045 void TGWin32::ChangeWindowAttributes(Window_t id, SetWindowAttributes_t * attr)
06046 {
06047    // Change window attributes.
06048 
06049    if (!id) return;
06050 
06051    GdkWMDecoration deco;
06052    GdkColor color;
06053    GdkEventMask xevent_mask;
06054    UInt_t xevmask;
06055    Mask_t evmask;
06056    HWND w, flag;
06057 
06058    if (attr && (attr->fMask & kWAEventMask)) {
06059       evmask = (Mask_t) attr->fEventMask;
06060       MapEventMask(evmask, xevmask);
06061       gdk_window_set_events((GdkWindow *) id, (GdkEventMask) xevmask);
06062    }
06063    if (attr && (attr->fMask & kWABackPixel)) {
06064       color.pixel = attr->fBackgroundPixel;
06065       color.red = GetRValue(attr->fBackgroundPixel);
06066       color.green = GetGValue(attr->fBackgroundPixel);
06067       color.blue = GetBValue(attr->fBackgroundPixel);
06068       gdk_window_set_background((GdkWindow *) id, &color);
06069    }
06070 //   if (attr && (attr->fMask & kWAOverrideRedirect))
06071 //      gdk_window_set_override_redirect ((GdkWindow *) id, attr->fOverrideRedirect);
06072    if (attr && (attr->fMask & kWABackPixmap)) {
06073       gdk_window_set_back_pixmap((GdkWindow *) id,
06074                                  (GdkPixmap *) attr->fBackgroundPixmap, 0);
06075    }
06076    if (attr && (attr->fMask & kWACursor)) {
06077       gdk_window_set_cursor((GdkWindow *) id, (GdkCursor *) attr->fCursor);
06078    }
06079    if (attr && (attr->fMask & kWAColormap)) {
06080       gdk_window_set_colormap((GdkWindow *) id,(GdkColormap *) attr->fColormap);
06081    }
06082    if (attr && (attr->fMask & kWABorderWidth)) {
06083       if (attr->fBorderWidth > 0) {
06084          gdk_window_set_decorations((GdkWindow *) id,
06085                                     (GdkWMDecoration) GDK_DECOR_BORDER);
06086       }
06087    }
06088 }
06089 
06090 //______________________________________________________________________________
06091 void TGWin32::ChangeProperty(Window_t id, Atom_t property, Atom_t type,
06092                              UChar_t * data, Int_t len)
06093 {
06094    // This function alters the property for the specified window and
06095    // causes the X server to generate a PropertyNotify event on that
06096    // window.
06097 
06098    if (!id) return;
06099 
06100    gdk_property_change((GdkWindow *) id, (GdkAtom) property,
06101                        (GdkAtom) type, 8, GDK_PROP_MODE_REPLACE, data,len);
06102 }
06103 
06104 //______________________________________________________________________________
06105 void TGWin32::DrawLine(Drawable_t id, GContext_t gc, Int_t x1, Int_t y1,
06106                        Int_t x2, Int_t y2)
06107 {
06108    // Draw a line.
06109 
06110    if (!id) return;
06111 
06112    gdk_draw_line((GdkDrawable *) id, (GdkGC *) gc, x1, y1, x2, y2);
06113 }
06114 
06115 //______________________________________________________________________________
06116 void TGWin32::ClearArea(Window_t id, Int_t x, Int_t y, UInt_t w, UInt_t h)
06117 {
06118    // Clear a window area to the bakcground color.
06119 
06120    if (!id) return;
06121 
06122    gdk_window_clear_area((GdkWindow *) id, x, y, w, h);
06123 }
06124 
06125 //______________________________________________________________________________
06126 void TGWin32::WMDeleteNotify(Window_t id)
06127 {
06128    // Tell WM to send message when window is closed via WM.
06129 
06130    if (!id) return;
06131 
06132    Atom prop;
06133    prop = (Atom_t) gdk_atom_intern("WM_DELETE_WINDOW", FALSE);
06134 
06135    W32ChangeProperty((HWND) GDK_DRAWABLE_XID((GdkWindow *) id),
06136                      prop, XA_ATOM, 32, GDK_PROP_MODE_REPLACE,
06137                      (unsigned char *) &gWM_DELETE_WINDOW, 1);
06138 }
06139 
06140 //______________________________________________________________________________
06141 void TGWin32::SetKeyAutoRepeat(Bool_t on)
06142 {
06143    // Turn key auto repeat on or off.
06144 
06145    if (on) {
06146       gdk_key_repeat_restore();
06147     } else {
06148       gdk_key_repeat_disable();
06149    }
06150 }
06151 
06152 //______________________________________________________________________________
06153 void TGWin32::GrabKey(Window_t id, Int_t keycode, UInt_t modifier, Bool_t grab)
06154 {
06155    // Establish passive grab on a certain key. That is, when a certain key
06156    // keycode is hit while certain modifier's (Shift, Control, Meta, Alt)
06157    // are active then the keyboard will be grabed for window id.
06158    // When grab is false, ungrab the keyboard for this key and modifier.
06159 
06160    UInt_t xmod;
06161 
06162    MapModifierState(modifier, xmod);
06163 
06164    if (grab) {
06165       gdk_key_grab(keycode, (GdkEventMask)xmod, (GdkWindow *)id);
06166    } else {
06167       gdk_key_ungrab(keycode, (GdkEventMask)xmod, (GdkWindow *)id);
06168    }
06169 }
06170 
06171 //______________________________________________________________________________
06172 void TGWin32::GrabButton(Window_t id, EMouseButton button, UInt_t modifier,
06173                          UInt_t evmask, Window_t confine, Cursor_t cursor,
06174                          Bool_t grab)
06175 {
06176    // Establish passive grab on a certain mouse button. That is, when a
06177    // certain mouse button is hit while certain modifier's (Shift, Control,
06178    // Meta, Alt) are active then the mouse will be grabed for window id.
06179    // When grab is false, ungrab the mouse button for this button and modifier.
06180 
06181    UInt_t xevmask;
06182    UInt_t xmod;
06183 
06184    if (!id) return;
06185 
06186    MapModifierState(modifier, xmod);
06187 
06188    if (grab) {
06189       MapEventMask(evmask, xevmask);
06190       gdk_button_grab(button, xmod, ( GdkWindow *)id, 1,  (GdkEventMask)xevmask,
06191                       (GdkWindow*)confine,  (GdkCursor*)cursor);
06192    } else {
06193       gdk_button_ungrab(button, xmod, ( GdkWindow *)id);
06194    }
06195 }
06196 
06197 //______________________________________________________________________________
06198 void TGWin32::GrabPointer(Window_t id, UInt_t evmask, Window_t confine,
06199                           Cursor_t cursor, Bool_t grab, Bool_t owner_events)
06200 {
06201    // Establish an active pointer grab. While an active pointer grab is in
06202    // effect, further pointer events are only reported to the grabbing
06203    // client window.
06204 
06205    UInt_t xevmask;
06206    MapEventMask(evmask, xevmask);
06207 
06208    if (grab) {
06209       if(!::IsWindowVisible((HWND)GDK_DRAWABLE_XID(id))) return;
06210       gdk_pointer_grab((GdkWindow *) id, owner_events, (GdkEventMask) xevmask,
06211                        (GdkWindow *) confine, (GdkCursor *) cursor,
06212                        GDK_CURRENT_TIME);
06213    } else {
06214       gdk_pointer_ungrab(GDK_CURRENT_TIME);
06215       ::SetCursor((HCURSOR)GDK_CURSOR_XID(fCursors[kPointer]));
06216    }
06217 }
06218 
06219 //______________________________________________________________________________
06220 void TGWin32::SetWindowName(Window_t id, char *name)
06221 {
06222    // Set window name.
06223 
06224    if (!id) return;
06225 
06226    gdk_window_set_title((GdkWindow *) id, name);
06227 }
06228 
06229 //______________________________________________________________________________
06230 void TGWin32::SetIconName(Window_t id, char *name)
06231 {
06232    // Set window icon name.
06233 
06234    if (!id) return;
06235 
06236    gdk_window_set_icon_name((GdkWindow *) id, name);
06237 }
06238 
06239 //______________________________________________________________________________
06240 void TGWin32::SetIconPixmap(Window_t id, Pixmap_t pic)
06241 {
06242    // Set pixmap the WM can use when the window is iconized.
06243 
06244    if (!id) return;
06245 
06246    gdk_window_set_icon((GdkWindow *)id, NULL, (GdkPixmap *)pic, (GdkPixmap *)pic);
06247 }
06248 
06249 #define safestrlen(s) ((s) ? strlen(s) : 0)
06250 
06251 //______________________________________________________________________________
06252 void TGWin32::SetClassHints(Window_t id, char *className, char *resourceName)
06253 {
06254    // Set the windows class and resource name.
06255 
06256    if (!id) return;
06257 
06258    char *class_string;
06259    char *s;
06260    int len_nm, len_cl;
06261    GdkAtom type, prop;
06262 
06263    prop = gdk_atom_intern("WM_CLASS", kFALSE);
06264 
06265    len_nm = safestrlen(resourceName);
06266    len_cl = safestrlen(className);
06267 
06268    if ((class_string = s =
06269         (char *) malloc((unsigned) (len_nm + len_cl + 2)))) {
06270       if (len_nm) {
06271          strcpy(s, resourceName);
06272          s += len_nm + 1;
06273       } else
06274          *s++ = '\0';
06275       if (len_cl) {
06276          strcpy(s, className);
06277       } else {
06278          *s = '\0';
06279       }
06280 
06281       W32ChangeProperty((HWND) GDK_DRAWABLE_XID((GdkWindow *) id),
06282                             (Atom) XA_WM_CLASS, (Atom) XA_WM_CLASS, 8,
06283                             GDK_PROP_MODE_REPLACE,
06284                             (unsigned char *) class_string,
06285                             len_nm + len_cl + 2);
06286       free(class_string);
06287    }
06288 }
06289 
06290 //______________________________________________________________________________
06291 void TGWin32::SetMWMHints(Window_t id, UInt_t value, UInt_t funcs,
06292                           UInt_t input)
06293 {
06294    // Set decoration style for MWM-compatible wm (mwm, ncdwm, fvwm?).
06295 
06296    if (!id) return;
06297 
06298    gdk_window_set_decorations((GdkDrawable *) id, (GdkWMDecoration) value);
06299    gdk_window_set_functions((GdkDrawable *) id, (GdkWMFunction) funcs);
06300 }
06301 
06302 //______________________________________________________________________________
06303 void TGWin32::SetWMPosition(Window_t id, Int_t x, Int_t y)
06304 {
06305    //
06306 
06307    if (!id) return;
06308 
06309    gdk_window_move((GdkDrawable *) id, x, y);
06310 }
06311 
06312 //______________________________________________________________________________
06313 void TGWin32::SetWMSize(Window_t id, UInt_t w, UInt_t h)
06314 {
06315    //
06316 
06317    if (!id) return;
06318 
06319    gdk_window_resize((GdkWindow *) id, w, h);
06320 }
06321 
06322 //______________________________________________________________________________
06323 void TGWin32::SetWMSizeHints(Window_t id, UInt_t wmin, UInt_t hmin,
06324                              UInt_t wmax, UInt_t hmax,
06325                              UInt_t winc, UInt_t hinc)
06326 {
06327    // Give the window manager minimum and maximum size hints. Also
06328    // specify via winc and hinc the resize increments.
06329 
06330    if (!id) return;
06331 
06332    GdkGeometry hints;
06333    GdkWindowHints flags;
06334 
06335    flags = (GdkWindowHints) (GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE |
06336                              GDK_HINT_RESIZE_INC);
06337    hints.min_width = (Int_t) wmin;
06338    hints.max_width = (Int_t) wmax;
06339    hints.min_height = (Int_t) hmin;
06340    hints.max_height = (Int_t) hmax;
06341    hints.width_inc = (Int_t) winc;
06342    hints.height_inc = (Int_t) hinc;
06343 
06344    gdk_window_set_geometry_hints((GdkWindow *) id, (GdkGeometry *) &hints,
06345                                  (GdkWindowHints) flags);
06346 }
06347 
06348 //______________________________________________________________________________
06349 void TGWin32::SetWMState(Window_t id, EInitialState state)
06350 {
06351    // Set the initial state of the window. Either kNormalState or kIconicState.
06352 
06353    if (!id) return;
06354 
06355 #if 0
06356    XWMHints hints;
06357    Int_t xstate = NormalState;
06358 
06359    if (state == kNormalState)
06360       xstate = NormalState;
06361    if (state == kIconicState)
06362       xstate = IconicState;
06363 
06364    hints.flags = StateHint;
06365    hints.initial_state = xstate;
06366 
06367    XSetWMHints((GdkWindow *) id, &hints);
06368 #endif
06369 }
06370 
06371 //______________________________________________________________________________
06372 void TGWin32::SetWMTransientHint(Window_t id, Window_t main_id)
06373 {
06374    // Tell window manager that window is a transient window of gdk_parent_root.
06375 
06376    if (!id) return;
06377 
06378    gdk_window_set_transient_for((GdkWindow *) id, (GdkWindow *) main_id);
06379 }
06380 
06381 //______________________________________________________________________________
06382 void TGWin32::DrawString(Drawable_t id, GContext_t gc, Int_t x, Int_t y,
06383                          const char *s, Int_t len)
06384 {
06385    // Draw a string using a specific graphics context in position (x,y).
06386 
06387    if (!id) return;
06388 
06389    GdkGCValues values;
06390    gdk_gc_get_values((GdkGC *) gc, &values);
06391    gdk_win32_draw_text((GdkDrawable *) id, (GdkFont *) values.font,
06392                  (GdkGC *) gc, x, y, (const gchar *)s, len);
06393 }
06394 
06395 //______________________________________________________________________________
06396 Int_t TGWin32::TextWidth(FontStruct_t font, const char *s, Int_t len)
06397 {
06398    // Return lenght of string in pixels. Size depends on font.
06399 
06400    return gdk_text_width((GdkFont *)font, s, len);
06401 }
06402 
06403 //______________________________________________________________________________
06404 void TGWin32::GetFontProperties(FontStruct_t font, Int_t & max_ascent,
06405                                 Int_t & max_descent)
06406 {
06407    // Return some font properties.
06408 
06409    GdkFont *f = (GdkFont *) font;
06410    max_ascent = f->ascent;
06411    max_descent = f->descent;
06412 }
06413 
06414 //______________________________________________________________________________
06415 void TGWin32::GetGCValues(GContext_t gc, GCValues_t & gval)
06416 {
06417    // Get current values from graphics context gc. Which values of the
06418    // context to get is encoded in the GCValues::fMask member.
06419 
06420    GdkGCValues xgval;
06421    ULong_t xmask;
06422 
06423    MapGCValues(gval, xmask, xgval, kTRUE);
06424    gdk_gc_get_values((GdkGC *) gc, &xgval);
06425    MapGCValues(gval, xmask, xgval, kFALSE);
06426 }
06427 
06428 //______________________________________________________________________________
06429 FontStruct_t TGWin32::GetFontStruct(FontH_t fh)
06430 {
06431    // Retrieve associated font structure once we have the font handle.
06432    // Free returned FontStruct_t using FreeFontStruct().
06433 
06434    return (FontStruct_t) gdk_font_ref((GdkFont *) fh);
06435 }
06436 
06437 //______________________________________________________________________________
06438 void TGWin32::FreeFontStruct(FontStruct_t fs)
06439 {
06440    // Free font structure returned by GetFontStruct().
06441 
06442    gdk_font_unref((GdkFont *) fs);
06443 }
06444 
06445 //______________________________________________________________________________
06446 void TGWin32::ClearWindow(Window_t id)
06447 {
06448    // Clear window.
06449 
06450    if (!id) return;
06451 
06452    gdk_window_clear((GdkDrawable *) id);
06453 }
06454 
06455 //______________________________________________________________________________
06456 Int_t TGWin32::KeysymToKeycode(UInt_t keysym)
06457 {
06458    // Convert a keysym to the appropriate keycode. For example keysym is
06459    // a letter and keycode is the matching keyboard key (which is dependend
06460    // on the current keyboard mapping).
06461 
06462    UInt_t xkeysym;
06463    MapKeySym(keysym, xkeysym);
06464    return xkeysym;
06465 }
06466 
06467 //______________________________________________________________________________
06468 void TGWin32::FillRectangle(Drawable_t id, GContext_t gc, Int_t x, Int_t y,
06469                             UInt_t w, UInt_t h)
06470 {
06471    // Draw a filled rectangle. Filling is done according to the gc.
06472 
06473    if (!id) return;
06474 
06475    gdk_win32_draw_rectangle((GdkDrawable *) id, (GdkGC *) gc, kTRUE, x, y, w, h);
06476 }
06477 
06478 //______________________________________________________________________________
06479 void TGWin32::DrawRectangle(Drawable_t id, GContext_t gc, Int_t x, Int_t y,
06480                             UInt_t w, UInt_t h)
06481 {
06482    // Draw a rectangle outline.
06483 
06484    if (!id) return;
06485 
06486    gdk_win32_draw_rectangle((GdkDrawable *) id, (GdkGC *) gc, kFALSE, x, y, w, h);
06487 }
06488 
06489 //______________________________________________________________________________
06490 void TGWin32::DrawSegments(Drawable_t id, GContext_t gc, Segment_t * seg,
06491                            Int_t nseg)
06492 {
06493    // Draws multiple line segments. Each line is specified by a pair of points.
06494 
06495    if (!id) return;
06496 
06497    gdk_win32_draw_segments((GdkDrawable *) id, (GdkGC *) gc, (GdkSegment *)seg, nseg);
06498 }
06499 
06500 //______________________________________________________________________________
06501 void TGWin32::SelectInput(Window_t id, UInt_t evmask)
06502 {
06503    // Defines which input events the window is interested in. By default
06504    // events are propageted up the window stack. This mask can also be
06505    // set at window creation time via the SetWindowAttributes_t::fEventMask
06506    // attribute.
06507 
06508    if (!id) return;
06509 
06510    UInt_t xevmask;
06511    MapEventMask(evmask, xevmask, kTRUE);
06512    gdk_window_set_events((GdkWindow *) id, (GdkEventMask)xevmask);
06513 }
06514 
06515 //______________________________________________________________________________
06516 Window_t TGWin32::GetInputFocus()
06517 {
06518    // Returns the window id of the window having the input focus.
06519 
06520    HWND hwnd = ::GetFocus();
06521    return (Window_t) gdk_xid_table_lookup(hwnd);
06522 }
06523 
06524 //______________________________________________________________________________
06525 void TGWin32::SetInputFocus(Window_t id)
06526 {
06527    // Set keyboard input focus to window id.
06528 
06529    if (!id) return;
06530 
06531    HWND hwnd = (HWND)GDK_DRAWABLE_XID((GdkWindow *)id);
06532    ::SetFocus(hwnd);
06533 }
06534 
06535 //______________________________________________________________________________
06536 Window_t TGWin32::GetPrimarySelectionOwner()
06537 {
06538    // Returns the window id of the current owner of the primary selection.
06539    // That is the window in which, for example some text is selected.
06540 
06541    return (Window_t)gdk_selection_owner_get(gClipboardAtom);
06542 }
06543 
06544 //______________________________________________________________________________
06545 void TGWin32::SetPrimarySelectionOwner(Window_t id)
06546 {
06547    // Makes the window id the current owner of the primary selection.
06548    // That is the window in which, for example some text is selected.
06549 
06550    if (!id) return;
06551 
06552    gdk_selection_owner_set((GdkWindow *) id, gClipboardAtom, GDK_CURRENT_TIME, 0);
06553 }
06554 
06555 //______________________________________________________________________________
06556 void TGWin32::ConvertPrimarySelection(Window_t id, Atom_t clipboard, Time_t when)
06557 {
06558    // XConvertSelection() causes a SelectionRequest event to be sent to the
06559    // current primary selection owner. This event specifies the selection
06560    // property (primary selection), the format into which to convert that
06561    // data before storing it (target = XA_STRING), the property in which
06562    // the owner will place the information (sel_property), the window that
06563    // wants the information (id), and the time of the conversion request
06564    // (when).
06565    // The selection owner responds by sending a SelectionNotify event, which
06566    // confirms the selected atom and type.
06567 
06568    if (!id) return;
06569 
06570    gdk_selection_convert((GdkWindow *) id, clipboard,
06571                          gdk_atom_intern("GDK_TARGET_STRING", 0), when);
06572 }
06573 
06574 //______________________________________________________________________________
06575 void TGWin32::LookupString(Event_t * event, char *buf, Int_t buflen,
06576                            UInt_t & keysym)
06577 {
06578    // Convert the keycode from the event structure to a key symbol (according
06579    // to the modifiers specified in the event structure and the current
06580    // keyboard mapping). In buf a null terminated ASCII string is returned
06581    // representing the string that is currently mapped to the key code.
06582 
06583    KeySym xkeysym;
06584    _lookup_string(event, buf, buflen);
06585    UInt_t ks, xks = (UInt_t) event->fCode;
06586    MapKeySym(ks, xks, kFALSE);
06587    keysym = (Int_t) ks;
06588 }
06589 
06590 //______________________________________________________________________________
06591 void TGWin32::MapKeySym(UInt_t & keysym, UInt_t & xkeysym, Bool_t tox)
06592 {
06593    // Map to and from X key symbols. Keysym are the values returned by
06594    // XLookUpString.
06595 
06596    if (tox) {
06597       xkeysym = GDK_VoidSymbol;
06598       if (keysym < 127) {
06599          xkeysym = keysym;
06600       } else if (keysym >= kKey_F1 && keysym <= kKey_F35) {
06601          xkeysym = GDK_F1 + (keysym - (UInt_t) kKey_F1);        // function keys
06602       } else {
06603          for (int i = 0; gKeyMap[i].fKeySym; i++) {     // any other keys
06604             if (keysym == (UInt_t) gKeyMap[i].fKeySym) {
06605                xkeysym = (UInt_t) gKeyMap[i].fXKeySym;
06606                break;
06607             }
06608          }
06609       }
06610    } else {
06611       keysym = kKey_Unknown;
06612       // commentary in X11/keysymdef says that X codes match ASCII
06613       if (xkeysym < 127) {
06614          keysym = xkeysym;
06615       } else if (xkeysym >= GDK_F1 && xkeysym <= GDK_F35) {
06616          keysym = kKey_F1 + (xkeysym - GDK_F1); // function keys
06617       } else if (xkeysym >= GDK_KP_0 && xkeysym <= GDK_KP_9) {
06618          keysym = kKey_0 + (xkeysym - GDK_KP_0);        // numeric keypad keys
06619       } else {
06620          for (int i = 0; gKeyMap[i].fXKeySym; i++) {    // any other keys
06621             if (xkeysym == gKeyMap[i].fXKeySym) {
06622                keysym = (UInt_t) gKeyMap[i].fKeySym;
06623                break;
06624             }
06625          }
06626       }
06627    }
06628 }
06629 
06630 //______________________________________________________________________________
06631 void TGWin32::GetPasteBuffer(Window_t id, Atom_t atom, TString & text,
06632                              Int_t & nchar, Bool_t del)
06633 {
06634    // Get contents of paste buffer atom into string. If del is true delete
06635    // the paste buffer afterwards.
06636 
06637    if (!id) return;
06638 
06639    char *data;
06640    int nread, actual_format;
06641 
06642    nread = gdk_selection_property_get((GdkWindow *) id,
06643                                       (unsigned char **) &data,
06644                                       (GdkAtom *) & atom, &actual_format);
06645 
06646    if ((nread == 0) || (data == NULL)) {
06647       nchar = 0;
06648       return;
06649    }
06650 
06651    text.Insert(0, (const char *) data);
06652    nchar = 1;                   //strlen(data);
06653    g_free(data);
06654 
06655    // if (del)
06656    gdk_property_delete((GdkWindow *) id,
06657                        gdk_atom_intern("GDK_SELECTION", FALSE));
06658 }
06659 
06660 //______________________________________________________________________________
06661 void TGWin32::TranslateCoordinates(Window_t src, Window_t dest,
06662                                    Int_t src_x, Int_t src_y,
06663                                    Int_t &dest_x, Int_t &dest_y,
06664                                    Window_t &child)
06665 {
06666    // TranslateCoordinates translates coordinates from the frame of
06667    // reference of one window to another. If the point is contained
06668    // in a mapped child of the destination, the id of that child is
06669    // returned as well.
06670 
06671    if (!src || !dest) return;
06672 
06673    HWND sw, dw, ch = NULL;
06674    POINT point;
06675    sw = (HWND)GDK_DRAWABLE_XID((GdkWindow *)src);
06676    dw = (HWND)GDK_DRAWABLE_XID((GdkWindow *)dest);
06677    point.x = src_x;
06678    point.y = src_y;
06679    ::MapWindowPoints(sw,        // handle of window to be mapped from
06680                    dw,          // handle to window to be mapped to
06681                    &point,      // pointer to array with points to map
06682                    1);          // number of structures in array
06683    ch = ::ChildWindowFromPointEx(dw, point, CWP_SKIPDISABLED | CWP_SKIPINVISIBLE);
06684    child = (Window_t)gdk_xid_table_lookup(ch);
06685 
06686    if (child == src) {
06687       child = (Window_t) 0;
06688    }
06689    dest_x = point.x;
06690    dest_y = point.y;
06691 }
06692 
06693 //______________________________________________________________________________
06694 void TGWin32::GetWindowSize(Drawable_t id, Int_t & x, Int_t & y,
06695                             UInt_t & w, UInt_t & h)
06696 {
06697    // Return geometry of window (should be called GetGeometry but signature
06698    // already used).
06699 
06700    if (!id) return;
06701 
06702    Int_t ddum;
06703    if (GDK_DRAWABLE_TYPE(id) == GDK_DRAWABLE_PIXMAP) {
06704       x = y = 0;
06705       gdk_drawable_get_size((GdkDrawable *)id, (int*)&w, (int*)&h);
06706    }
06707    else {
06708       gdk_window_get_geometry((GdkDrawable *) id, &x, &y, (int*)&w,
06709                               (int*)&h, &ddum);
06710    }
06711 }
06712 
06713 //______________________________________________________________________________
06714 void TGWin32::FillPolygon(Window_t id, GContext_t gc, Point_t * points,
06715                           Int_t npnt)
06716 {
06717    // FillPolygon fills the region closed by the specified path.
06718    // The path is closed automatically if the last point in the list does
06719    // not coincide with the first point. All point coordinates are
06720    // treated as relative to the origin. For every pair of points
06721    // inside the polygon, the line segment connecting them does not
06722    // intersect the path.
06723 
06724    if (!id) return;
06725 
06726    gdk_win32_draw_polygon((GdkWindow *) id, (GdkGC *) gc, 1, (GdkPoint *) points, npnt);
06727 }
06728 
06729 //______________________________________________________________________________
06730 void TGWin32::QueryPointer(Window_t id, Window_t &rootw,
06731                            Window_t &childw, Int_t &root_x,
06732                            Int_t &root_y, Int_t &win_x, Int_t &win_y,
06733                            UInt_t &mask)
06734 {
06735    // Returns the root window the pointer is logically on and the pointer
06736    // coordinates relative to the root window's origin.
06737    // The pointer coordinates returned to win_x and win_y are relative to
06738    // the origin of the specified window. In this case, QueryPointer returns
06739    // the child that contains the pointer, if any, or else kNone to
06740    // childw. QueryPointer returns the current logical state of the
06741    // keyboard buttons and the modifier keys in mask.
06742 
06743    if (!id) return;
06744 
06745    POINT mousePt, sPt, currPt;
06746    HWND chw, window;
06747    UInt_t umask = 0;
06748    BYTE kbd[256];
06749 
06750    window = (HWND)GDK_DRAWABLE_XID((GdkWindow *)id);
06751    rootw = (Window_t)GDK_ROOT_PARENT();
06752    ::GetCursorPos(&currPt);
06753    chw = ::WindowFromPoint(currPt);
06754    childw = (Window_t)gdk_xid_table_lookup(chw);
06755    root_x = currPt.x;
06756    root_y = currPt.y;
06757 
06758    ::ScreenToClient(window, &currPt);
06759    win_x = currPt.x;
06760    win_y = currPt.y;
06761 
06762    ::GetKeyboardState (kbd);
06763 
06764    if (kbd[VK_SHIFT] & 0x80) {
06765       umask |= GDK_SHIFT_MASK;
06766    }
06767    if (kbd[VK_CAPITAL] & 0x80) {
06768       umask |= GDK_LOCK_MASK;
06769    }
06770    if (kbd[VK_CONTROL] & 0x80) {
06771       umask |= GDK_CONTROL_MASK;
06772    }
06773    if (kbd[VK_MENU] & 0x80) {
06774       umask |= GDK_MOD1_MASK;
06775    }
06776    if (kbd[VK_LBUTTON] & 0x80) {
06777       umask |= GDK_BUTTON1_MASK;
06778    }
06779    if (kbd[VK_MBUTTON] & 0x80) {
06780       umask |= GDK_BUTTON2_MASK;
06781    }
06782    if (kbd[VK_RBUTTON] & 0x80) {
06783       umask |= GDK_BUTTON3_MASK;
06784    }
06785 
06786    MapModifierState(mask, umask, kFALSE);
06787 }
06788 
06789 //______________________________________________________________________________
06790 void TGWin32::SetForeground(GContext_t gc, ULong_t foreground)
06791 {
06792    // Set foreground color in graphics context (shortcut for ChangeGC with
06793    // only foreground mask set).
06794 
06795    GdkColor fore;
06796    fore.pixel = foreground;
06797    fore.red = GetRValue(foreground);
06798    fore.green = GetGValue(foreground);
06799    fore.blue = GetBValue(foreground);
06800    gdk_gc_set_foreground((GdkGC *) gc, &fore);
06801 }
06802 
06803 //______________________________________________________________________________
06804 void TGWin32::SetClipRectangles(GContext_t gc, Int_t x, Int_t y,
06805                                 Rectangle_t * recs, Int_t n)
06806 {
06807    // Set clipping rectangles in graphics context. X, Y specify the origin
06808    // of the rectangles. Recs specifies an array of rectangles that define
06809    // the clipping mask and n is the number of rectangles.
06810 
06811    Int_t i;
06812    GdkRectangle *grects = new GdkRectangle[n];
06813 
06814    for (i = 0; i < n; i++) {
06815       grects[i].x = x+recs[i].fX;
06816       grects[i].y = y+recs[i].fY;
06817       grects[i].width = recs[i].fWidth;
06818       grects[i].height = recs[i].fHeight;
06819    }
06820 
06821    for (i = 0; i < n; i++) {
06822       gdk_gc_set_clip_rectangle((GdkGC *)gc, (GdkRectangle*)recs);
06823    }
06824    delete [] grects;
06825 }
06826 
06827 //______________________________________________________________________________
06828 void TGWin32::Update(Int_t mode)
06829 {
06830    // Flush (mode = 0, default) or synchronize (mode = 1) X output buffer.
06831    // Flush flushes output buffer. Sync flushes buffer and waits till all
06832    // requests have been processed by X server.
06833 
06834    GdiFlush();
06835 }
06836 
06837 //______________________________________________________________________________
06838 Region_t TGWin32::CreateRegion()
06839 {
06840    // Create a new empty region.
06841 
06842    return (Region_t) gdk_region_new();
06843 }
06844 
06845 //______________________________________________________________________________
06846 void TGWin32::DestroyRegion(Region_t reg)
06847 {
06848    // Destroy region.
06849 
06850    gdk_region_destroy((GdkRegion *) reg);
06851 }
06852 
06853 //______________________________________________________________________________
06854 void TGWin32::UnionRectWithRegion(Rectangle_t * rect, Region_t src, Region_t dest)
06855 {
06856    // Union of rectangle with a region.
06857 
06858    GdkRectangle r;
06859    r.x = rect->fX;
06860    r.y = rect->fY;
06861    r.width = rect->fWidth;
06862    r.height = rect->fHeight;
06863    dest = (Region_t) gdk_region_union_with_rect((GdkRegion *) src, &r);
06864 }
06865 
06866 //______________________________________________________________________________
06867 Region_t TGWin32::PolygonRegion(Point_t * points, Int_t np, Bool_t winding)
06868 {
06869    // Create region for the polygon defined by the points array.
06870    // If winding is true use WindingRule else EvenOddRule as fill rule.
06871 
06872    return (Region_t) gdk_region_polygon((GdkPoint*)points, np,
06873                                  winding ? GDK_WINDING_RULE : GDK_EVEN_ODD_RULE);
06874 }
06875 
06876 //______________________________________________________________________________
06877 void TGWin32::UnionRegion(Region_t rega, Region_t regb, Region_t result)
06878 {
06879    // Compute the union of rega and regb and return result region.
06880    // The output region may be the same result region.
06881 
06882    result = (Region_t) gdk_regions_union((GdkRegion *) rega, (GdkRegion *) regb);
06883 }
06884 
06885 //______________________________________________________________________________
06886 void TGWin32::IntersectRegion(Region_t rega, Region_t regb,
06887                               Region_t result)
06888 {
06889    // Compute the intersection of rega and regb and return result region.
06890    // The output region may be the same as the result region.
06891 
06892    result = (Region_t) gdk_regions_intersect((GdkRegion *) rega,(GdkRegion *) regb);
06893 }
06894 
06895 //______________________________________________________________________________
06896 void TGWin32::SubtractRegion(Region_t rega, Region_t regb, Region_t result)
06897 {
06898    // Subtract rega from regb.
06899 
06900    result = (Region_t)gdk_regions_subtract((GdkRegion *) rega,(GdkRegion *) regb);
06901 }
06902 
06903 //______________________________________________________________________________
06904 void TGWin32::XorRegion(Region_t rega, Region_t regb, Region_t result)
06905 {
06906    // Calculate the difference between the union and intersection of
06907    // two regions.
06908 
06909    result = (Region_t) gdk_regions_xor((GdkRegion *) rega, (GdkRegion *) regb);
06910 }
06911 
06912 //______________________________________________________________________________
06913 Bool_t TGWin32::EmptyRegion(Region_t reg)
06914 {
06915    // Return true if the region is empty.
06916 
06917    return (Bool_t) gdk_region_empty((GdkRegion *) reg);
06918 }
06919 
06920 //______________________________________________________________________________
06921 Bool_t TGWin32::PointInRegion(Int_t x, Int_t y, Region_t reg)
06922 {
06923    // Returns true if the point x,y is in the region.
06924 
06925    return (Bool_t) gdk_region_point_in((GdkRegion *) reg, x, y);
06926 }
06927 
06928 //______________________________________________________________________________
06929 Bool_t TGWin32::EqualRegion(Region_t rega, Region_t regb)
06930 {
06931    // Returns true if two regions are equal.
06932 
06933    return (Bool_t) gdk_region_equal((GdkRegion *) rega, (GdkRegion *) regb);
06934 }
06935 
06936 //______________________________________________________________________________
06937 void TGWin32::GetRegionBox(Region_t reg, Rectangle_t * rect)
06938 {
06939    // Return smallest enclosing rectangle.
06940 
06941    GdkRectangle r;
06942    gdk_region_get_clipbox((GdkRegion *) reg, &r);
06943    rect->fX = r.x;
06944    rect->fY = r.y;
06945    rect->fWidth = r.width;
06946    rect->fHeight = r.height;
06947 }
06948 
06949 //______________________________________________________________________________
06950 char **TGWin32::ListFonts(const char *fontname, Int_t /*max*/, Int_t &count)
06951 {
06952    // Return list of font names matching "fontname".
06953 
06954    char  foundry[32], family[100], weight[32], slant[32], font_name[256];
06955    char  **fontlist;
06956    Int_t n1, fontcount = 0;
06957 
06958    sscanf(fontname, "-%30[^-]-%100[^-]-%30[^-]-%30[^-]-%n",
06959           foundry, family, weight, slant, &n1);
06960    // replace "medium" by "normal"
06961    if(!stricmp(weight,"medium")) {
06962       sprintf(weight,"normal");
06963    }
06964    // since all sizes are allowed with TTF, just forget it...
06965    sprintf(font_name, "-%s-%s-%s-%s-*", foundry, family, weight, slant);
06966    fontlist = gdk_font_list_new(font_name, &fontcount);
06967    count = fontcount;
06968 
06969    if (fontcount > 0) return fontlist;
06970    return 0;
06971 }
06972 
06973 //______________________________________________________________________________
06974 void TGWin32::FreeFontNames(char **fontlist)
06975 {
06976    //
06977 
06978    gdk_font_list_free(fontlist);
06979 }
06980 
06981 //______________________________________________________________________________
06982 Drawable_t TGWin32::CreateImage(UInt_t width, UInt_t height)
06983 {
06984    //
06985 
06986    return (Drawable_t) gdk_image_new(GDK_IMAGE_SHARED, gdk_visual_get_best(),
06987                                      width, height);
06988 }
06989 
06990 //______________________________________________________________________________
06991 void TGWin32::GetImageSize(Drawable_t id, UInt_t &width, UInt_t &height)
06992 {
06993    //
06994 
06995    width  = ((GdkImage*)id)->width;
06996    height = ((GdkImage*)id)->height;
06997 }
06998 
06999 //______________________________________________________________________________
07000 void TGWin32::PutPixel(Drawable_t id, Int_t x, Int_t y, ULong_t pixel)
07001 {
07002    //
07003 
07004    if (!id) return;
07005 
07006    GdkImage *image = (GdkImage *)id;
07007    if (image->depth == 1) {
07008       if (pixel & 1) {
07009          ((UChar_t *) image->mem)[y * image->bpl + (x >> 3)] |= (1 << (7 - (x & 0x7)));
07010       } else {
07011          ((UChar_t *) image->mem)[y * image->bpl + (x >> 3)] &= ~(1 << (7 - (x & 0x7)));
07012       }
07013    } else {
07014       UChar_t *pixelp = (UChar_t *) image->mem + y * image->bpl + x * image->bpp;
07015       // Windows is always LSB, no need to check image->byte_order.
07016       switch (image->bpp) {
07017          case 4:
07018             pixelp[3] = 0;
07019          case 3:
07020             pixelp[2] = ((pixel >> 16) & 0xFF);
07021          case 2:
07022             pixelp[1] = ((pixel >> 8) & 0xFF);
07023          case 1:
07024             pixelp[0] = (pixel & 0xFF);
07025       }
07026    }
07027 }
07028 
07029 //______________________________________________________________________________
07030 void TGWin32::PutImage(Drawable_t id, GContext_t gc, Drawable_t img, Int_t dx,
07031                        Int_t dy, Int_t x, Int_t y, UInt_t w, UInt_t h)
07032 {
07033    //
07034 
07035    if (!id) return;
07036 
07037    gdk_draw_image((GdkDrawable *) id, (GdkGC *)gc, (GdkImage *)img,
07038                   x, y, dx, dy, w, h);
07039    ::GdiFlush();
07040 }
07041 
07042 //______________________________________________________________________________
07043 void TGWin32::DeleteImage(Drawable_t img)
07044 {
07045    //
07046 
07047    gdk_image_unref((GdkImage *)img);
07048 }
07049 
07050 //______________________________________________________________________________
07051 unsigned char *TGWin32::GetColorBits(Drawable_t wid,  Int_t x, Int_t y,
07052                                      UInt_t width, UInt_t height)
07053 {
07054    // Gets DIB bits
07055    // x, y, width, height - position of bitmap
07056    // returns a pointer on bitmap bits array
07057    // in format:
07058    // b1, g1, r1, 0,  b2, g2, r2, 0 ... bn, gn, rn, 0 ..
07059    //
07060    // Pixels are numbered from left to right and from top to bottom.
07061    // By default all pixels from the whole drawable are returned.
07062 
07063    HDC hdc, memdc;
07064    BITMAPINFO bmi;
07065    HGDIOBJ oldbitmap1, oldbitmap2;
07066    BITMAP bm;
07067    HBITMAP ximage = 0;
07068    VOID  *bmbits = 0;
07069    unsigned char *ret = 0;
07070 
07071    if (GDK_DRAWABLE_TYPE(wid) == GDK_DRAWABLE_PIXMAP) {
07072       hdc = ::CreateCompatibleDC(NULL);
07073       oldbitmap1 = ::SelectObject(hdc, GDK_DRAWABLE_XID(wid));
07074       ::GetObject(GDK_DRAWABLE_XID(wid), sizeof(BITMAP), &bm);
07075    } else {
07076       hdc = ::GetDC((HWND)GDK_DRAWABLE_XID(wid));
07077    }
07078    memdc = ::CreateCompatibleDC(hdc);
07079 
07080    bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
07081    bmi.bmiHeader.biWidth = width;
07082    bmi.bmiHeader.biHeight = -1 * (int)(height);
07083    bmi.bmiHeader.biPlanes = 1;
07084    bmi.bmiHeader.biBitCount = 32;
07085    bmi.bmiHeader.biCompression = BI_RGB;
07086    bmi.bmiHeader.biSizeImage = 0;
07087    bmi.bmiHeader.biXPelsPerMeter = bmi.bmiHeader.biYPelsPerMeter = 0;
07088    bmi.bmiHeader.biClrUsed = 0;
07089    bmi.bmiHeader.biClrImportant = 0;
07090 
07091    ximage = ::CreateDIBSection(hdc, (BITMAPINFO *) &bmi, DIB_RGB_COLORS, &bmbits, NULL, 0);
07092 
07093    if (ximage && bmbits) {
07094       oldbitmap2 = ::SelectObject(memdc, ximage);
07095       ::BitBlt(memdc, x, y, width, height, hdc, 0, 0, SRCCOPY);
07096       ::SelectObject(memdc, oldbitmap2);
07097    }
07098    ::DeleteDC(memdc);
07099    if (GDK_DRAWABLE_TYPE(wid) == GDK_DRAWABLE_PIXMAP) {
07100       ::SelectObject(hdc, oldbitmap1);
07101       ::DeleteDC(hdc);
07102    } else {
07103       ::ReleaseDC((HWND)GDK_DRAWABLE_XID(wid), hdc);
07104    }
07105    if (ximage && bmbits) {
07106       ULong_t sz = width*height*4;
07107       ret = new unsigned char[sz];
07108       memcpy(ret, bmbits, sz);
07109       ::DeleteObject(ximage);
07110    }
07111    return ret;
07112 }
07113 
07114 //______________________________________________________________________________
07115 Pixmap_t TGWin32::CreatePixmapFromData(unsigned char *bits, UInt_t width, UInt_t height)
07116 {
07117    // create an image from RGB data. RGB data is in format :
07118    // b1, g1, r1, 0,  b2, g2, r2, 0 ... bn, gn, rn, 0 ..
07119    //
07120    // Pixels are numbered from left to right and from top to bottom.
07121    // Note that data must be 32-bit aligned
07122 
07123    BITMAPINFO bmp_info;
07124    bmp_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
07125    bmp_info.bmiHeader.biWidth = width;
07126    bmp_info.bmiHeader.biHeight = -1 * (int)(height);
07127    bmp_info.bmiHeader.biPlanes = 1;
07128    bmp_info.bmiHeader.biBitCount = 32;
07129    bmp_info.bmiHeader.biCompression = BI_RGB;
07130    bmp_info.bmiHeader.biSizeImage = 0;
07131    bmp_info.bmiHeader.biClrUsed = 0;
07132    bmp_info.bmiHeader.biXPelsPerMeter = 0L;
07133    bmp_info.bmiHeader.biYPelsPerMeter = 0L;
07134    bmp_info.bmiHeader.biClrImportant = 0;
07135    bmp_info.bmiColors[0].rgbRed = 0;
07136    bmp_info.bmiColors[0].rgbGreen = 0;
07137    bmp_info.bmiColors[0].rgbBlue = 0;
07138    bmp_info.bmiColors[0].rgbReserved = 0;
07139 
07140    HDC hdc = ::GetDC(NULL);
07141    HBITMAP hbitmap = ::CreateDIBitmap(hdc, &bmp_info.bmiHeader, CBM_INIT,
07142                                       (void *)bits, &bmp_info, DIB_RGB_COLORS);
07143    ::ReleaseDC(NULL, hdc);
07144 
07145    SIZE size;
07146    // For an obscure reason, we have to set the size of the
07147    // bitmap this way before to call gdk_pixmap_foreign_new
07148    // otherwise, it fails...
07149    ::SetBitmapDimensionEx(hbitmap,width, height, &size);
07150 
07151    return (Pixmap_t)gdk_pixmap_foreign_new((guint32)hbitmap);
07152 }
07153 
07154 //______________________________________________________________________________
07155 Int_t TGWin32::AddPixmap(ULong_t pix, UInt_t w, UInt_t h)
07156 {
07157    //register pixmap created by TGWin32GLManager
07158    HBITMAP hBmp = reinterpret_cast<HBITMAP>(pix);
07159    SIZE sz = SIZE();
07160 
07161    SetBitmapDimensionEx(hBmp, w, h, &sz);
07162    GdkPixmap *newPix = gdk_pixmap_foreign_new(reinterpret_cast<guint32>(hBmp));
07163 
07164    Int_t wid = 0;
07165    for(; wid < fMaxNumberOfWindows; ++wid)
07166       if (!fWindows[wid].open)
07167          break;
07168 
07169    if (wid == fMaxNumberOfWindows) {
07170       Int_t newSize = fMaxNumberOfWindows + 10;
07171 
07172       fWindows = (XWindow_t *)TStorage::ReAlloc(fWindows, newSize * sizeof(XWindow_t),
07173                                                 fMaxNumberOfWindows * sizeof(XWindow_t));
07174 
07175       for (Int_t i = fMaxNumberOfWindows; i < newSize; ++i)
07176          fWindows[i].open = 0;
07177 
07178       fMaxNumberOfWindows = newSize;
07179    }
07180 
07181    fWindows[wid].open = 1;
07182    gCws = fWindows + wid;
07183    gCws->window = newPix;
07184    gCws->drawing = gCws->window;
07185    gCws->buffer = 0;
07186    gCws->double_buffer = 0;
07187    gCws->ispixmap = 1;
07188    gCws->clip = 0;
07189    gCws->width = w;
07190    gCws->height = h;
07191    gCws->new_colors = 0;
07192 
07193    return wid;
07194 }
07195 
07196 //______________________________________________________________________________
07197 Int_t TGWin32::AddWindow(ULong_t qwid, UInt_t w, UInt_t h)
07198 {
07199    // Register a window created by Qt as a ROOT window (like InitWindow()).
07200 
07201    Int_t wid;
07202    // Select next free window number
07203 
07204  again:
07205    for (wid = 0; wid < fMaxNumberOfWindows; wid++) {
07206       if (!fWindows[wid].open) {
07207          fWindows[wid].open = 1;
07208          fWindows[wid].double_buffer = 0;
07209          gCws = &fWindows[wid];
07210          break;
07211       }
07212    }
07213 
07214    if (wid == fMaxNumberOfWindows) {
07215       int newsize = fMaxNumberOfWindows + 10;
07216       fWindows =
07217           (XWindow_t *) TStorage::ReAlloc(fWindows,
07218                                           newsize * sizeof(XWindow_t),
07219                                           fMaxNumberOfWindows *
07220                                           sizeof(XWindow_t));
07221 
07222       for (int i = fMaxNumberOfWindows; i < newsize; i++) {
07223          fWindows[i].open = 0;
07224       }
07225 
07226       fMaxNumberOfWindows = newsize;
07227       goto again;
07228    }
07229 
07230    gCws->window = gdk_window_foreign_new((guint32)qwid);
07231 
07232    gCws->drawing       = gCws->window;
07233    gCws->buffer        = 0;
07234    gCws->double_buffer = 0;
07235    gCws->ispixmap      = 0;
07236    gCws->clip          = 0;
07237    gCws->width         = w;
07238    gCws->height        = h;
07239    gCws->new_colors    = 0;
07240 
07241    return wid;
07242 }
07243 
07244 //______________________________________________________________________________
07245 void TGWin32::RemoveWindow(ULong_t qwid)
07246 {
07247    // Remove a window created by Qt (like CloseWindow1()).
07248 
07249    int wid;
07250 
07251    SelectWindow((int)qwid);
07252 
07253    if (gCws->buffer) {
07254       gdk_pixmap_unref(gCws->buffer);
07255    }
07256    if (gCws->new_colors) {
07257       gdk_colormap_free_colors((GdkColormap *) fColormap,
07258                                (GdkColor *)gCws->new_colors, gCws->ncolors);
07259 
07260       delete [] gCws->new_colors;
07261       gCws->new_colors = 0;
07262    }
07263 
07264    GdiFlush();
07265    gCws->open = 0;
07266 
07267    if (!fWindows) return;
07268 
07269    // make first window in list the current window
07270    for (wid = 0; wid < fMaxNumberOfWindows; wid++) {
07271       if (fWindows[wid].open) {
07272          gCws = &fWindows[wid];
07273          return;
07274       }
07275    }
07276    gCws = 0;
07277 }
07278 
07279 //______________________________________________________________________________
07280 void TGWin32::ShapeCombineMask(Window_t id, Int_t x, Int_t y, Pixmap_t mask)
07281 {
07282    // The Nonrectangular Window Shape Extension adds nonrectangular
07283    // windows to the System.
07284    // This allows for making shaped (partially transparent) windows
07285 
07286    gdk_window_shape_combine_mask((GdkWindow *)id, (GdkBitmap *) mask, x, y);
07287 }
07288 
07289 //______________________________________________________________________________
07290 UInt_t TGWin32::ScreenWidthMM() const
07291 {
07292    // Returns the width of the screen in millimeters.
07293 
07294    return (UInt_t)gdk_screen_width_mm();
07295 }
07296 
07297 //------------------------------ Drag and Drop ---------------------------------
07298 
07299 //______________________________________________________________________________
07300 void TGWin32::DeleteProperty(Window_t win, Atom_t& prop)
07301 {
07302    // Deletes the specified property on the specified window.
07303 
07304    HWND hWnd = (HWND)GDK_DRAWABLE_XID((GdkWindow *)win);
07305    Atom_t atom = (Atom_t)GetProp(hWnd,(LPCTSTR)MAKELONG(prop,0));
07306    if (atom != 0) {
07307            GlobalDeleteAtom(atom);
07308    }
07309    RemoveProp(hWnd,(LPCTSTR)MAKELONG(prop,0));
07310 }
07311 
07312 //______________________________________________________________________________
07313 Int_t TGWin32::GetProperty(Window_t win, Atom_t prop, Long_t offset, Long_t len,
07314                          Bool_t del, Atom_t req_type, Atom_t *act_type,
07315                          Int_t *act_format, ULong_t *nitems, ULong_t *bytes,
07316                          unsigned char **prop_list)
07317 {
07318    // Returns the actual type of the property, the actual format of the property,
07319    // and a pointer to the data actually returned.
07320    
07321    HGLOBAL hdata;
07322    UChar_t *ptr, *data;
07323    UInt_t i, n, length;
07324 
07325    HWND hWnd = (HWND)GDK_DRAWABLE_XID((GdkWindow *)win);
07326    if (hWnd == NULL)
07327       return 0;
07328 
07329    Atom_t dndproxy = InternAtom("XdndProxy", kFALSE);
07330    Atom_t dndtypelist = InternAtom("XdndTypeList", kFALSE);
07331 
07332    if (prop == dndproxy)
07333       return 0;
07334    if (prop == dndtypelist) {
07335       *act_type = XA_ATOM;
07336       *prop_list = (unsigned char *)GetProp(hWnd, (LPCTSTR)MAKELONG(prop,0));
07337       for (n = 0; prop_list[n]; n++);
07338       *nitems = n;
07339       return n;
07340    }
07341    else {
07342       if (!OpenClipboard((HWND)GDK_DRAWABLE_XID((GdkWindow *)win))) {
07343          return 0;
07344       }
07345       hdata = GetClipboardData(CF_PRIVATEFIRST);
07346       ptr = (UChar_t *)GlobalLock(hdata);
07347       length = GlobalSize(hdata);
07348       data = (UChar_t *)malloc(length + 1);
07349       for (i = 0; i < length; i++) {
07350          data[i] = ptr[i];
07351       }
07352       GlobalUnlock(hdata);
07353       CloseClipboard();
07354       *prop_list = data;
07355       *bytes = *nitems = length;
07356       return length;
07357    }
07358    return 0;
07359 }
07360 
07361 //______________________________________________________________________________
07362 void TGWin32::ChangeActivePointerGrab(Window_t win, UInt_t mask, Cursor_t cur)
07363 {
07364    // Changes the active cursor of the specified window.
07365 
07366    UInt_t xevmask;
07367    MapEventMask(mask, xevmask);
07368    if (cur == kNone)
07369       gdk_window_set_cursor((GdkWindow *) win, fCursors[kHand]);
07370    else
07371       gdk_window_set_cursor((GdkWindow *) win, (GdkCursor *)cur);
07372 }
07373 
07374 //______________________________________________________________________________
07375 void TGWin32::ConvertSelection(Window_t win, Atom_t &sel, Atom_t &target,
07376                              Atom_t &prop, Time_t &stamp)
07377 {
07378    // Get Clipboard data.
07379 
07380    HGLOBAL hdata;
07381 
07382    static UINT gdk_selection_notify_msg = 
07383       RegisterWindowMessage("gdk-selection-notify");
07384    HWND hWnd = (HWND)GDK_DRAWABLE_XID((GdkWindow *)win);
07385    if (!OpenClipboard((HWND)GDK_DRAWABLE_XID((GdkWindow *)win))) {
07386       return;
07387    }
07388    hdata = GetClipboardData(CF_PRIVATEFIRST);
07389    CloseClipboard();
07390    if (hdata == 0)
07391       return;
07392    /* Send ourselves an ersatz selection notify message so that we actually
07393     * fetch the data.
07394     */
07395    PostMessage(hWnd, gdk_selection_notify_msg, sel, target);
07396 }
07397 
07398 //______________________________________________________________________________
07399 Bool_t TGWin32::SetSelectionOwner(Window_t owner, Atom_t &sel)
07400 {
07401    // Assigns owner of Clipboard.
07402 
07403    static UINT gdk_selection_request_msg = 
07404       RegisterWindowMessage("gdk-selection-request");
07405    HWND hWnd = (HWND)GDK_DRAWABLE_XID((GdkWindow *)owner);
07406    OpenClipboard(hWnd);
07407    EmptyClipboard();
07408    CloseClipboard();
07409    if (owner) {
07410       ::PostMessage(hWnd, gdk_selection_request_msg, sel, 0);
07411    }
07412    return kTRUE;
07413 }
07414 
07415 //______________________________________________________________________________
07416 void TGWin32::ChangeProperties(Window_t id, Atom_t property, Atom_t type,
07417                                Int_t format, UChar_t *data, Int_t len)
07418 {
07419    // Put data into Clipboard.
07420 
07421    HGLOBAL hdata;
07422    Int_t i, length;
07423    UChar_t *ptr;
07424 
07425    if (data == 0 || len == 0)
07426       return;
07427    if (!OpenClipboard((HWND)GDK_DRAWABLE_XID((GdkWindow *)id))) {
07428       return;
07429    }
07430    hdata = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, len + 1);
07431    ptr = (UChar_t *)GlobalLock(hdata);
07432    for (i = 0; i < len; i++) {
07433       *ptr++ = *data++;
07434    }
07435    GlobalUnlock(hdata);
07436    SetClipboardData(CF_PRIVATEFIRST, hdata);
07437    CloseClipboard();
07438 }
07439 
07440 //______________________________________________________________________________
07441 void TGWin32::SetTypeList(Window_t win, Atom_t prop, Atom_t *typelist)
07442 {
07443    // Add the list of drag and drop types to the Window win.
07444 
07445    SetProp((HWND)GDK_DRAWABLE_XID((GdkWindow *)win),
07446            (LPCTSTR)MAKELONG(prop,0),
07447            (HANDLE)typelist);
07448 }
07449 
07450 //______________________________________________________________________________
07451 Window_t TGWin32::FindRWindow(Window_t root, Window_t dragwin, Window_t input, 
07452                               int x, int y, int maxd)
07453 {
07454    // Recursively search in the children of Window for a Window which is at 
07455    // location x, y and is DND aware, with a maximum depth of maxd.
07456    // Possibility to exclude dragwin and input.
07457 
07458    POINT screen_point, point;
07459    POINT cpt;
07460    RECT  rect;
07461    HWND hwnd, hwndc;
07462    HWND hwndt;
07463    Window_t win, retwin = kNone;
07464    Atom_t version = 0;
07465    Atom_t dndaware = InternAtom("XdndAware", kFALSE);
07466 
07467    cpt.x = x;
07468    cpt.y = y;
07469    hwnd = ::ChildWindowFromPointEx((HWND)GDK_DRAWABLE_XID((GdkWindow *)root),
07470                                     cpt, CWP_ALL);
07471    while (hwnd) {
07472       GetWindowRect(hwnd, &rect);
07473       if (PtInRect(&rect, cpt)) {
07474          if (GetProp(hwnd,(LPCTSTR)MAKELONG(dndaware,0))) {
07475             win = (Window_t) gdk_xid_table_lookup(hwnd);
07476             if (win && win != dragwin && win != input)
07477                return win;
07478          }
07479          Bool_t done = kFALSE;
07480          hwndt = hwnd;
07481          while (!done) {
07482             point = cpt;
07483             ::MapWindowPoints(NULL, hwndt, &point, 1);
07484             hwndc = ChildWindowFromPoint (hwndt, point);
07485             if (GetProp(hwnd,(LPCTSTR)MAKELONG(dndaware,0))) {
07486                win = (Window_t) gdk_xid_table_lookup(hwndc);
07487                if (win && win != dragwin && win != input)
07488                   return win;
07489             }
07490             if (hwndc == NULL)
07491                done = TRUE;
07492             else if (hwndc == hwndt)
07493                done = TRUE;
07494             else
07495                hwndt = hwndc;
07496             if (GetProp(hwndt,(LPCTSTR)MAKELONG(dndaware,0))) {
07497                win = (Window_t) gdk_xid_table_lookup(hwndt);
07498                if (win && win != dragwin && win != input)
07499                   return win;
07500             }
07501          }
07502       }
07503       hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
07504    }
07505    return kNone;
07506 }
07507 
07508 //______________________________________________________________________________
07509 Bool_t TGWin32::IsDNDAware(Window_t win, Atom_t *typelist)
07510 {
07511    // Checks if Window win is DND aware, and knows any of the DND formats
07512    // passed in argument.
07513 
07514    if (!win) return kFALSE;
07515 
07516    Atom_t version = 0;
07517    Atom_t dndaware = InternAtom("XdndAware", kFALSE);
07518    HWND window = (HWND)GDK_DRAWABLE_XID((GdkWindow *)win);
07519    while (window) {
07520       version = (Atom_t)GetProp(window,(LPCTSTR)MAKELONG(dndaware,0));
07521       if (version) return kTRUE;
07522       window = ::GetParent(window);
07523    }
07524    return kFALSE;
07525 }
07526 
07527 //______________________________________________________________________________
07528 void TGWin32::SetDNDAware(Window_t id, Atom_t *typelist)
07529 {
07530    // Add XdndAware property and the list of drag and drop types to the 
07531    // Window win.
07532 
07533    int n;
07534    if (!id) return;
07535 
07536    DWORD dwStyle = GetWindowLong((HWND)GDK_DRAWABLE_XID((GdkWindow *)id), 
07537                                  GWL_EXSTYLE);
07538    SetWindowLong((HWND)GDK_DRAWABLE_XID((GdkWindow *)id), GWL_EXSTYLE, 
07539                  dwStyle | WS_EX_ACCEPTFILES);
07540    Atom_t dndaware = InternAtom("XdndAware", kFALSE);
07541    SetProp((HWND)GDK_DRAWABLE_XID((GdkWindow *)id),
07542            (LPCTSTR)MAKELONG(dndaware,0),
07543            (HANDLE)XDND_PROTOCOL_VERSION);
07544 
07545    if (typelist == 0)
07546       return;
07547    for (n = 0; typelist[n]; n++);
07548    Atom_t dndtypelist = InternAtom("XdndTypeList", kFALSE);
07549    SetProp((HWND)GDK_DRAWABLE_XID((GdkWindow *)id),
07550            (LPCTSTR)MAKELONG(dndtypelist,0),
07551            (HANDLE)typelist);
07552 
07553 }
07554 
07555 //______________________________________________________________________________
07556 void TGWin32::SetUserThreadId(ULong_t id)
07557 {
07558    // Set user thread id. This is used when an extra thread is created
07559    // to process events.
07560 
07561    if (id == 0) {
07562       TGWin32ProxyBase::fgMainThreadId = ((TWinNTSystem*)gSystem)->GetGUIThreadId();
07563    }
07564    else {
07565       TGWin32ProxyBase::fgUserThreadId = id;
07566    }
07567 }
07568 

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