Logo ROOT  
Reference Guide
TGWin32.cxx
Go to the documentation of this file.
1 // @(#)root/win32gdk:$Id$
2 // Author: Rene Brun, Olivier Couet, Fons Rademakers, Valeri Onuchin, Bertrand Bellenot 27/11/01
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2001, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 /// \defgroup win32 Win32 backend
13 /// \brief Interface to Windows graphics.
14 /// \ingroup GraphicsBackends
15 
16 /** \class TGWin32
17 \ingroup win32
18 This class is the basic interface to the Win32 graphics system.
19 It is an implementation of the abstract TVirtualX class.
20 
21 This code was initially developed in the context of HIGZ and PAW
22 by Olivier Couet (package X11INT).
23 */
24 
25 #include <ft2build.h>
26 #include FT_FREETYPE_H
27 #include FT_GLYPH_H
28 #include "TGWin32.h"
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdlib.h>
32 #include <ctype.h>
33 #include <limits.h>
34 #include <process.h>
35 #include <wchar.h>
36 #include "gdk/gdkkeysyms.h"
37 #include "xatom.h"
38 #include <winuser.h>
39 
40 #include "TROOT.h"
41 #include "TApplication.h"
42 #include "TColor.h"
43 #include "TPoint.h"
44 #include "TMath.h"
45 #include "TStorage.h"
46 #include "TStyle.h"
47 #include "TSystem.h"
48 #include "TError.h"
49 #include "TException.h"
50 #include "TClassTable.h"
51 #include "KeySymbols.h"
52 #include "TWinNTSystem.h"
53 #include "TGWin32VirtualXProxy.h"
54 #include "TWin32SplashThread.h"
55 #include "TString.h"
56 #include "TObjString.h"
57 #include "TObjArray.h"
58 #include "TExMap.h"
59 #include "TEnv.h"
60 #include "RStipples.h"
61 #include "GuiTypes.h"
62 
63 // DND protocol version
64 #define XDND_PROTOCOL_VERSION 5
65 #ifndef IDC_HAND
66 #define IDC_HAND MAKEINTRESOURCE(32649)
67 #endif
68 
69 extern "C" {
70 void gdk_win32_draw_rectangle (GdkDrawable *drawable,
71  GdkGC *gc,
72  gint filled,
73  gint x,
74  gint y,
75  gint width,
76  gint height);
77 void gdk_win32_draw_arc (GdkDrawable *drawable,
78  GdkGC *gc,
79  gint filled,
80  gint x,
81  gint y,
82  gint width,
83  gint height,
84  gint angle1,
85  gint angle2);
86 void gdk_win32_draw_polygon (GdkDrawable *drawable,
87  GdkGC *gc,
88  gint filled,
89  GdkPoint *points,
90  gint npoints);
91 void gdk_win32_draw_text (GdkDrawable *drawable,
92  GdkFont *font,
93  GdkGC *gc,
94  gint x,
95  gint y,
96  const gchar *text,
97  gint text_length);
98 void gdk_win32_draw_points (GdkDrawable *drawable,
99  GdkGC *gc,
100  GdkPoint *points,
101  gint npoints);
102 void gdk_win32_draw_segments (GdkDrawable *drawable,
103  GdkGC *gc,
104  GdkSegment *segs,
105  gint nsegs);
106 void gdk_win32_draw_lines (GdkDrawable *drawable,
107  GdkGC *gc,
108  GdkPoint *points,
109  gint npoints);
110 
111 };
112 
113 //////////// internal classes & structures (very private) ////////////////
114 
115 struct XWindow_t {
116  Int_t open; // 1 if the window is open, 0 if not
117  Int_t double_buffer; // 1 if the double buffer is on, 0 if not
118  Int_t ispixmap; // 1 if pixmap, 0 if not
119  GdkDrawable *drawing; // drawing area, equal to window or buffer
120  GdkDrawable *window; // win32 window
121  GdkDrawable *buffer; // pixmap used for double buffer
122  UInt_t width; // width of the window
123  UInt_t height; // height of the window
124  Int_t clip; // 1 if the clipping is on
125  Int_t xclip; // x coordinate of the clipping rectangle
126  Int_t yclip; // y coordinate of the clipping rectangle
127  UInt_t wclip; // width of the clipping rectangle
128  UInt_t hclip; // height of the clipping rectangle
129  ULong_t *new_colors; // new image colors (after processing)
130  Int_t ncolors; // number of different colors
131 };
132 
133 
134 /////////////////////////////////// globals //////////////////////////////////
136 
137 namespace {
138 /////////////////////////////////// globals //////////////////////////////////
139 
140 GdkAtom gClipboardAtom = GDK_NONE;
141 static XWindow_t *gCws; // gCws: pointer to the current window
142 static XWindow_t *gTws; // gTws: temporary pointer
143 
144 //
145 // gColors[0] : background also used for b/w screen
146 // gColors[1] : foreground also used for b/w screen
147 // gColors[2..kMAXCOL-1]: colors which can be set by SetColor
148 //
149 const Int_t kBIGGEST_RGB_VALUE = 65535;
150 //const Int_t kMAXCOL = 1000;
151 //static struct {
152 // Int_t defined;
153 // GdkColor color;
154 //} gColors[kMAXCOL];
155 
156 //
157 // Primitives Graphic Contexts global for all windows
158 //
159 const int kMAXGC = 7;
160 static GdkGC *gGClist[kMAXGC];
161 static GdkGC *gGCline; // = gGClist[0]; // PolyLines
162 static GdkGC *gGCmark; // = gGClist[1]; // PolyMarker
163 static GdkGC *gGCfill; // = gGClist[2]; // Fill areas
164 static GdkGC *gGCtext; // = gGClist[3]; // Text
165 static GdkGC *gGCinvt; // = gGClist[4]; // Inverse text
166 static GdkGC *gGCdash; // = gGClist[5]; // Dashed lines
167 static GdkGC *gGCpxmp; // = gGClist[6]; // Pixmap management
168 
169 static GdkGC *gGCecho; // Input echo
170 
171 static Int_t gFillHollow; // Flag if fill style is hollow
172 static GdkPixmap *gFillPattern; // Fill pattern
173 
174 //
175 // Text management
176 //
177 static const char *gTextFont = "arial.ttf"; // Current font
178 
179 //
180 // Markers
181 //
182 const Int_t kMAXMK = 100;
183 static struct {
184  int type;
185  int n;
186  GdkPoint xy[kMAXMK];
187 } gMarker; // Point list to draw marker
188 static int gMarkerLineWidth = 0;
189 static int gMarkerLineStyle = GDK_LINE_SOLID;
190 static int gMarkerCapStyle = GDK_CAP_ROUND;
191 static int gMarkerJoinStyle = GDK_JOIN_ROUND;
192 
193 //
194 // Keep style values for line GdkGC
195 //
196 static int gLineWidth = 0;
197 static int gLineStyle = GDK_LINE_SOLID;
198 static int gCapStyle = GDK_CAP_BUTT;
199 static int gJoinStyle = GDK_JOIN_MITER;
200 static char gDashList[10];
201 static int gDashLength = 0;
202 static int gDashOffset = 0;
203 static int gDashSize = 0;
204 
205 //
206 // Event masks
207 //
208 static ULong_t gMouseMask =
209  GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK
210  | GDK_LEAVE_NOTIFY_MASK | GDK_POINTER_MOTION_MASK | GDK_KEY_PRESS_MASK
211  | GDK_KEY_RELEASE_MASK;
212 static ULong_t gKeybdMask =
213  GDK_BUTTON_PRESS_MASK | GDK_KEY_PRESS_MASK | GDK_ENTER_NOTIFY_MASK |
214  GDK_LEAVE_NOTIFY_MASK;
215 
216 //
217 // Data to create an invisible cursor
218 //
219 const char null_cursor_bits[] = {
220  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
221  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
222  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
223 };
224 static GdkCursor *gNullCursor;
225 
226 static bool gdk_initialized = false;
227 
228 //---- MWM Hints stuff
229 
230 struct MWMHintsProperty_t {
232  Handle_t fFunctions;
233  Handle_t fDecorations;
234  Int_t fInputMode;
235 };
236 
237 //---- hints
238 
239 const ULong_t kMWMHintsFunctions = BIT(0);
240 const ULong_t kMWMHintsDecorations = BIT(1);
241 const ULong_t kMWMHintsInputMode = BIT(2);
242 
245 
246 
247 //---- Key symbol mapping
248 
249 struct KeySymbolMap_t {
250  KeySym fXKeySym;
251  EKeySym fKeySym;
252 };
253 
254 static const char *keyCodeToString[] = {
255  "", /* 0x000 */
256  "", /* 0x001, VK_LBUTTON */
257  "", /* 0x002, VK_RBUTTON */
258  "", /* 0x003, VK_CANCEL */
259  "", /* 0x004, VK_MBUTTON */
260  "", /* 0x005 */
261  "", /* 0x006 */
262  "", /* 0x007 */
263  "\015", /* 0x008, VK_BACK */
264  "\t", /* 0x009, VK_TAB */
265  "", /* 0x00A */
266  "", /* 0x00B */
267  "", /* 0x00C, VK_CLEAR */
268  "\r", /* 0x00D, VK_RETURN */
269  "", /* 0x00E */
270  "", /* 0x00F */
271  "", /* 0x010, VK_SHIFT */
272  "", /* 0x011, VK_CONTROL */
273  "", /* 0x012, VK_MENU */
274  "", /* 0x013, VK_PAUSE */
275  "", /* 0x014, VK_CAPITAL */
276  "", /* 0x015, VK_KANA */
277  "", /* 0x016 */
278  "", /* 0x017 */
279  "", /* 0x018 */
280  "", /* 0x019, VK_KANJI */
281  "", /* 0x01A */
282  "", /* 0x01B, VK_ESCAPE */
283  "", /* 0x01C, VK_CONVERT */
284  "", /* 0x01D, VK_NONCONVERT */
285  "", /* 0x01E */
286  "", /* 0x01F */
287  " ", /* 0x020, VK_SPACE */
288  "", /* 0x021, VK_PRIOR */
289  "", /* 0x022, VK_NEXT */
290  "", /* 0x023, VK_END */
291  "", /* 0x024, VK_HOME */
292  "", /* 0x025, VK_LEFT */
293  "", /* 0x026, VK_UP */
294  "", /* 0x027, VK_RIGHT */
295  "", /* 0x028, VK_DOWN */
296  "", /* 0x029, VK_SELECT */
297  "", /* 0x02A, VK_PRINT */
298  "", /* 0x02B, VK_EXECUTE */
299  "", /* 0x02C, VK_SNAPSHOT */
300  "", /* 0x02D, VK_INSERT */
301  "\037", /* 0x02E, VK_DELETE */
302  "", /* 0x02F, VK_HELP */
303 };
304 
305 //---- Mapping table of all non-trivial mappings (the ASCII keys map
306 //---- one to one so are not included)
307 
308 static KeySymbolMap_t gKeyMap[] = {
309  {GDK_Escape, kKey_Escape},
310  {GDK_Tab, kKey_Tab},
311 #ifndef GDK_ISO_Left_Tab
312  {0xFE20, kKey_Backtab},
313 #else
314  {GDK_ISO_Left_Tab, kKey_Backtab},
315 #endif
316  {GDK_BackSpace, kKey_Backspace},
317  {GDK_Return, kKey_Return},
318  {GDK_Insert, kKey_Insert},
319  {GDK_Delete, kKey_Delete},
320  {GDK_Clear, kKey_Delete},
321  {GDK_Pause, kKey_Pause},
322  {GDK_Print, kKey_Print},
323  {0x1005FF60, kKey_SysReq}, // hardcoded Sun SysReq
324  {0x1007ff00, kKey_SysReq}, // hardcoded X386 SysReq
325  {GDK_Home, kKey_Home}, // cursor movement
326  {GDK_End, kKey_End},
327  {GDK_Left, kKey_Left},
328  {GDK_Up, kKey_Up},
329  {GDK_Right, kKey_Right},
330  {GDK_Down, kKey_Down},
331  {GDK_Prior, kKey_Prior},
332  {GDK_Next, kKey_Next},
333  {GDK_Shift_L, kKey_Shift}, // modifiers
334  {GDK_Shift_R, kKey_Shift},
335  {GDK_Shift_Lock, kKey_Shift},
336  {GDK_Control_L, kKey_Control},
337  {GDK_Control_R, kKey_Control},
338  {GDK_Meta_L, kKey_Meta},
339  {GDK_Meta_R, kKey_Meta},
340  {GDK_Alt_L, kKey_Alt},
341  {GDK_Alt_R, kKey_Alt},
342  {GDK_Caps_Lock, kKey_CapsLock},
343  {GDK_Num_Lock, kKey_NumLock},
344  {GDK_Scroll_Lock, kKey_ScrollLock},
345  {GDK_KP_Space, kKey_Space}, // numeric keypad
346  {GDK_KP_Tab, kKey_Tab},
347  {GDK_KP_Enter, kKey_Enter},
348  {GDK_KP_Equal, kKey_Equal},
349  {GDK_KP_Multiply, kKey_Asterisk},
350  {GDK_KP_Add, kKey_Plus},
351  {GDK_KP_Separator, kKey_Comma},
352  {GDK_KP_Subtract, kKey_Minus},
353  {GDK_KP_Decimal, kKey_Period},
354  {GDK_KP_Divide, kKey_Slash},
355  {0, (EKeySym) 0}
356 };
357 
358 
359 /////////////////////static auxilary functions /////////////////////////////////
360 ////////////////////////////////////////////////////////////////////////////////
361 
362 static Int_t _lookup_string(Event_t * event, char *buf, Int_t buflen)
363 {
364  int i;
365  int n = event->fUser[1];
366  if (n > 0) {
367  for (i = 0; i < n; i++) {
368  buf[i] = event->fUser[2 + i];
369  }
370  buf[n] = 0;
371  } else {
372  buf[0] = 0;
373  }
374  if (event->fCode <= 0x20) {
375  strncpy(buf, keyCodeToString[event->fCode], buflen - 1);
376  }
377  return n;
378 }
379 
380 ////////////////////////////////////////////////////////////////////////////////
381 
382 inline void SplitLong(Long_t ll, Long_t & i1, Long_t & i2)
383 {
384  union {
385  Long_t l;
386  Int_t i[2];
387  } conv;
388 
389  conv.l = 0L;
390  conv.i[0] = 0;
391  conv.i[1] = 0;
392 
393  conv.l = ll;
394  i1 = conv.i[0];
395  i2 = conv.i[1];
396 }
397 
398 ////////////////////////////////////////////////////////////////////////////////
399 
400 inline void AsmLong(Long_t i1, Long_t i2, Long_t & ll)
401 {
402  union {
403  Long_t l;
404  Int_t i[2];
405  } conv;
406 
407  conv.i[0] = (Int_t) i1;
408  conv.i[1] = (Int_t) i2;
409  ll = conv.l;
410 }
411 
412 ////////////////////////////////////////////////////////////////////////////////
413 /// Make sure the child window is visible.
414 
415 static BOOL CALLBACK EnumChildProc(HWND hwndChild, LPARAM lParam)
416 {
417  ::ShowWindow(hwndChild, SW_SHOWNORMAL);
418  GdkWindow *child = gdk_window_lookup(hwndChild);
419  if (child)
420  ((GdkWindowPrivate *) child)->mapped = TRUE;
421  return TRUE;
422 }
423 
424 ////////////////////////////////////////////////////////////////////////////////
425 
426 static void _ChangeProperty(HWND w, char *np, char *dp, int n, Atom_t type)
427 {
428  HGLOBAL hMem;
429  char *p;
430 
431  hMem = ::GetProp(w, np);
432  if (hMem != NULL) {
433  ::GlobalFree(hMem);
434  }
435  hMem = ::GlobalAlloc(GHND, n + sizeof(Atom_t));
436  p = (char *) ::GlobalLock(hMem);
437  memcpy(p, &type, sizeof(Atom_t));
438  memcpy(p + sizeof(Atom_t), dp, n);
439  ::GlobalUnlock(hMem);
440  ::SetProp(w, np, hMem);
441  ::GlobalFree(hMem);
442 }
443 
444 ////////////////////////////////////////////////////////////////////////////////
445 ///
446 
447 static void W32ChangeProperty(HWND w, Atom_t property, Atom_t type,
448  int format, int mode, const unsigned char *data,
449  int nelements)
450 {
451  char *atomName;
452  char buffer[256];
453  int len;
454  char propName[32];
455 
456  if (mode == GDK_PROP_MODE_REPLACE || mode == GDK_PROP_MODE_PREPEND) {
457  len = (int) ::GlobalGetAtomName(property, buffer, sizeof(buffer));
458  if ((atomName = (char *) malloc(len + 1)) == NULL) {
459  return;
460  } else {
461  strcpy(atomName, buffer);
462  }
463  sprintf(propName, "#0x%0.4x", (unsigned) atomName);
464  _ChangeProperty(w, propName, (char *) data, nelements, type);
465  free(atomName);
466  }
467 }
468 
469 ////////////////////////////////////////////////////////////////////////////////
470 ///
471 
472 static int _GetWindowProperty(GdkWindow * id, Atom_t property, Long_t long_offset,
473  Long_t long_length, Bool_t delete_it, Atom_t req_type,
474  Atom_t * actual_type_return,
475  Int_t * actual_format_return, ULong_t * nitems_return,
476  ULong_t * bytes_after_return, UChar_t ** prop_return)
477 {
478  if (!id) return 0;
479 
480  char *data, *destPtr;
481  char propName[32];
482  HGLOBAL handle;
483  HWND w;
484 
485  w = (HWND) GDK_DRAWABLE_XID(id);
486 
487  if (::IsClipboardFormatAvailable(CF_TEXT) && ::OpenClipboard(NULL)) {
488  handle = ::GetClipboardData(CF_TEXT);
489  if (handle != NULL) {
490  data = (char *) ::GlobalLock(handle);
491  *nitems_return = strlen(data);
492  *prop_return = (UChar_t *) malloc(*nitems_return + 1);
493  destPtr = (char *) *prop_return;
494  while (*data != '\0') {
495  if (*data != '\r') {
496  *destPtr = *data;
497  destPtr++;
498  }
499  data++;
500  }
501  *destPtr = '\0';
502  ::GlobalUnlock(handle);
503  *actual_type_return = XA_STRING;
504  *bytes_after_return = 0;
505  }
506  ::CloseClipboard();
507  return 1;
508  }
509  if (delete_it) {
510  ::RemoveProp(w, propName);
511  }
512  return 1;
513 }
514 
515 ////////////////////////////////////////////////////////////////////////////////
516 ///
517 
518 static ULong_t GetPixelImage(Drawable_t id, Int_t x, Int_t y)
519 {
520  if (!id) return 0;
521 
522  GdkImage *image = (GdkImage *)id;
523  ULong_t pixel;
524 
525  if (image->depth == 1) {
526  pixel = (((char *) image->mem)[y * image->bpl + (x >> 3)] & (1 << (7 - (x & 0x7)))) != 0;
527  } else {
528  UChar_t *pixelp = (UChar_t *) image->mem + y * image->bpl + x * image->bpp;
529  switch (image->bpp) {
530  case 1:
531  pixel = *pixelp;
532  break;
533  // Windows is always LSB, no need to check image->byte_order.
534  case 2:
535  pixel = pixelp[0] | (pixelp[1] << 8);
536  break;
537  case 3:
538  pixel = pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16);
539  break;
540  case 4:
541  pixel = pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16);
542  break;
543  }
544  }
545  return pixel;
546 }
547 
548 ////////////////////////////////////////////////////////////////////////////////
549 /// Collect in orgcolors all different original image colors.
550 
551 static void CollectImageColors(ULong_t pixel, ULong_t * &orgcolors,
552  Int_t & ncolors, Int_t & maxcolors)
553 {
554  if (maxcolors == 0) {
555  ncolors = 0;
556  maxcolors = 100;
557  orgcolors = (ULong_t*) ::operator new(maxcolors*sizeof(ULong_t));
558  }
559 
560  for (int i = 0; i < ncolors; i++) {
561  if (pixel == orgcolors[i]) return;
562  }
563  if (ncolors >= maxcolors) {
564  orgcolors = (ULong_t *) TStorage::ReAlloc(orgcolors,
565  maxcolors * 2 *
566  sizeof(ULong_t),
567  maxcolors *
568  sizeof(ULong_t));
569  maxcolors *= 2;
570  }
571  orgcolors[ncolors++] = pixel;
572 }
573 
574 ////////////////////////////////////////////////////////////////////////////////
575 /// debug function for printing event mask
576 
577 static char *EventMask2String(UInt_t evmask)
578 {
579  static char bfr[500];
580  char *p = bfr;
581 
582  *p = '\0';
583 #define BITmask(x) \
584  if (evmask & k##x##Mask) \
585  p += sprintf (p, "%s" #x, (p > bfr ? " " : ""))
586  BITmask(Exposure);
587  BITmask(PointerMotion);
588  BITmask(ButtonMotion);
589  BITmask(ButtonPress);
590  BITmask(ButtonRelease);
591  BITmask(KeyPress);
592  BITmask(KeyRelease);
593  BITmask(EnterWindow);
594  BITmask(LeaveWindow);
595  BITmask(FocusChange);
596  BITmask(StructureNotify);
597 #undef BITmask
598 
599  return bfr;
600 }
601 
602 ///////////////////////////////////////////////////////////////////////////////
603 class TGWin32MainThread {
604 
605 public:
606  void *fHandle; // handle of server (aka command) thread
607  DWORD fId; // id of server (aka command) thread
608  static LPCRITICAL_SECTION fCritSec; // general mutex
609  static LPCRITICAL_SECTION fMessageMutex; // message queue mutex
610 
611  TGWin32MainThread();
612  ~TGWin32MainThread();
613  static void LockMSG();
614  static void UnlockMSG();
615 };
616 
617 TGWin32MainThread *gMainThread = 0;
618 LPCRITICAL_SECTION TGWin32MainThread::fCritSec = 0;
619 LPCRITICAL_SECTION TGWin32MainThread::fMessageMutex = 0;
620 
621 
622 ////////////////////////////////////////////////////////////////////////////////
623 /// dtor
624 
625 TGWin32MainThread::~TGWin32MainThread()
626 {
627  if (fCritSec) {
628  ::LeaveCriticalSection(fCritSec);
629  ::DeleteCriticalSection(fCritSec);
630  delete fCritSec;
631  }
632  fCritSec = 0;
633 
634  if (fMessageMutex) {
635  ::LeaveCriticalSection(fMessageMutex);
636  ::DeleteCriticalSection(fMessageMutex);
637  delete fMessageMutex;
638  }
639  fMessageMutex = 0;
640 
641  if(fHandle) {
642  ::PostThreadMessage(fId, WM_QUIT, 0, 0);
643  ::CloseHandle(fHandle);
644  }
645  fHandle = 0;
646 }
647 
648 ////////////////////////////////////////////////////////////////////////////////
649 /// lock message queue
650 
651 void TGWin32MainThread::LockMSG()
652 {
653  if (fMessageMutex) ::EnterCriticalSection(fMessageMutex);
654 }
655 
656 ////////////////////////////////////////////////////////////////////////////////
657 /// unlock message queue
658 
659 void TGWin32MainThread::UnlockMSG()
660 {
661  if (fMessageMutex) ::LeaveCriticalSection(fMessageMutex);
662 }
663 
664 
665 ////////////////////////////////////////////////////////////////////////////////
666 /// Windows timer handling events while moving/resizing windows
667 
668 VOID CALLBACK MyTimerProc(HWND hwnd, UINT message, UINT idTimer, DWORD dwTime)
669 {
671  //gVirtualX->UpdateWindow(1); // cause problems with OpenGL in pad...
672 }
673 
674 ////////////////////////////////////////////////////////////////////////////////
675 /// Message processing function for the GUI thread.
676 /// Kicks in once TGWin32 becomes active, and "replaces" the dummy one
677 /// in TWinNTSystem; see TWinNTSystem.cxx's GUIThreadMessageProcessingLoop().
678 
679 Bool_t GUIThreadMessageFunc(MSG *msg)
680 {
681  Bool_t ret = kFALSE;
682  static Int_t m_timer = 0;
683 
684  if ( (msg->message == WM_NCLBUTTONDOWN) ) {
685  if (m_timer == 0)
686  m_timer = SetTimer(NULL, 1, 20, (TIMERPROC) MyTimerProc);
687  }
688  else if (msg->message == WM_NCMOUSELEAVE ) {
689  if (m_timer) {
690  KillTimer(NULL, m_timer);
691  }
692  m_timer = 0;
693  }
694 
695  if (msg->message == TGWin32ProxyBase::fgPostMessageId) {
696  if (msg->wParam) {
697  TGWin32ProxyBase *proxy = (TGWin32ProxyBase*)msg->wParam;
698  proxy->ExecuteCallBack(kTRUE);
699  } else {
700  ret = kTRUE;
701  }
702  } else if (msg->message == TGWin32ProxyBase::fgPingMessageId) {
704  } else {
705  //if ( (msg->message >= WM_NCMOUSEMOVE) &&
706  // (msg->message <= WM_NCMBUTTONDBLCLK) ) {
707  // TGWin32ProxyBase::GlobalLock();
708  //}
709  TGWin32MainThread::LockMSG();
710  TranslateMessage(msg);
711  DispatchMessage(msg);
712  TGWin32MainThread::UnlockMSG();
713  }
714  return ret;
715 }
716 
717 
718 ///////////////////////////////////////////////////////////////////////////////
719 class TGWin32RefreshTimer : public TTimer {
720 
721 public:
722  TGWin32RefreshTimer() : TTimer(10, kTRUE) { if (gSystem) gSystem->AddTimer(this); }
723  ~TGWin32RefreshTimer() { if (gSystem) gSystem->RemoveTimer(this); }
724  Bool_t Notify()
725  {
726  Reset();
727  MSG msg;
728 
729  while (::PeekMessage(&msg, NULL, NULL, NULL, PM_NOREMOVE)) {
730  ::PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE);
731  if (!gVirtualX)
732  Sleep(200); // avoid start-up race
733  if (gVirtualX)
734  GUIThreadMessageFunc(&msg);
735  }
736  return kFALSE;
737  }
738 };
739 /*
740 ////////////////////////////////////////////////////////////////////////////////
741 /// thread for processing windows messages (aka Main/Server thread)
742 
743 static DWORD WINAPI MessageProcessingLoop(void *p)
744 {
745  MSG msg;
746  Int_t erret;
747  Bool_t endLoop = kFALSE;
748  TGWin32RefreshTimer *refersh = 0;
749 
750  // force to create message queue
751  ::PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
752 
753  // periodically we refresh windows
754  // Don't create refresh timer if the application has been created inside PVSS
755  if (gApplication) {
756  TString arg = gSystem->BaseName(gApplication->Argv(0));
757  if (!arg.Contains("PVSS"))
758  refersh = new TGWin32RefreshTimer();
759  }
760 
761  while (!endLoop) {
762  erret = ::GetMessage(&msg, NULL, NULL, NULL);
763  if (erret <= 0) endLoop = kTRUE;
764  endLoop = MessageProcessingFunc(&msg);
765  }
766 
767  TGWin32::Instance()->CloseDisplay();
768  if (refersh)
769  delete refersh;
770 
771  // exit thread
772  if (erret == -1) {
773  erret = ::GetLastError();
774  Error("MsgLoop", "Error in GetMessage");
775  ::ExitThread(-1);
776  } else {
777  ::ExitThread(0);
778  }
779  return 0;
780 }
781 */
782 
783 ////////////////////////////////////////////////////////////////////////////////
784 /// constructor
785 
786 TGWin32MainThread::TGWin32MainThread()
787 {
788  fCritSec = new CRITICAL_SECTION;
789  ::InitializeCriticalSection(fCritSec);
790  fMessageMutex = new CRITICAL_SECTION;
791  ::InitializeCriticalSection(fMessageMutex);
792  fHandle = ((TWinNTSystem*)gSystem)->GetGUIThreadHandle();
793  fId = ((TWinNTSystem*)gSystem)->GetGUIThreadId();
794  ((TWinNTSystem*)gSystem)->SetGUIThreadMsgHandler(GUIThreadMessageFunc);
795 }
796 
797 } // unnamed namespace
798 
799 ///////////////////////// TGWin32 implementation ///////////////////////////////
801 
802 ////////////////////////////////////////////////////////////////////////////////
803 /// Default constructor.
804 
805 TGWin32::TGWin32(): fRefreshTimer(0)
806 {
807  fScreenNumber = 0;
808  fWindows = 0;
809  fColors = 0;
810 }
811 
812 ////////////////////////////////////////////////////////////////////////////////
813 /// Normal Constructor.
814 
815 TGWin32::TGWin32(const char *name, const char *title) : TVirtualX(name,title), fRefreshTimer(0)
816 {
817  fScreenNumber = 0;
820  fTextAlignH = 1;
821  fTextAlignV = 1;
822  fTextAlign = 7;
823  fTextMagnitude = 1;
824  fCharacterUpX = 1;
825  fCharacterUpY = 1;
826  fDrawMode = kCopy;
827  fWindows = 0;
828  fMaxNumberOfWindows = 10;
829  fXEvent = 0;
836 
837  fWindows = (XWindow_t*) TStorage::Alloc(fMaxNumberOfWindows*sizeof(XWindow_t));
838  for (int i = 0; i < fMaxNumberOfWindows; i++) fWindows[i].open = 0;
839 
840  fColors = new TExMap;
841 
842  if (gApplication) {
844  if (!arg.Contains("PVSS"))
845  fRefreshTimer = new TGWin32RefreshTimer();
846  } else {
847  fRefreshTimer = new TGWin32RefreshTimer();
848  }
849 
850  // initialize GUI thread and proxy objects
851  if (!gROOT->IsBatch() && !gMainThread) {
852  gMainThread = new TGWin32MainThread();
853  TGWin32ProxyBase::fgMainThreadId = ::GetCurrentThreadId(); // gMainThread->fId;
856  }
857 }
858 
859 ////////////////////////////////////////////////////////////////////////////////
860 /// destructor.
861 
863 {
864  CloseDisplay();
865  if (fRefreshTimer)
866  delete fRefreshTimer;
867  if (!fColors) return;
868  Long64_t key, value;
869  TExMapIter it(fColors);
870  while (it.Next(key, value)) {
871  XColor_t *col = (XColor_t *) value;
872  delete col;
873  }
874  delete fColors;
875 }
876 
877 ////////////////////////////////////////////////////////////////////////////////
878 /// returns kTRUE if we are inside cmd/server thread
879 
881 {
882 #ifdef OLD_THREAD_IMPLEMENTATION
883  return ((::GetCurrentThreadId() == TGWin32ProxyBase::fgMainThreadId) ||
884  (::GetCurrentThreadId() == TGWin32ProxyBase::fgUserThreadId));
885 #else
886  return kTRUE;
887 #endif
888 }
889 
890 ////////////////////////////////////////////////////////////////////////////////
891 /// close display (terminate server/gMainThread thread)
892 
894 {
895  // disable any processing while exiting
897 
898  // terminate server thread
899  gPtr2VirtualX = 0;
901 
902  // The lock above does not work, so at least
903  // minimize the risk
904  TGWin32MainThread *delThread = gMainThread;
905  if (gMainThread) {
906  gMainThread = 0;
907  delete delThread;
908  }
909 
911 
912  // terminate ROOT logo splash thread
913  TWin32SplashThread *delSplash = gSplash;
914  if (gSplash) {
915  gSplash = 0;
916  delete delSplash;
917  }
918 
920  fWindows = 0;
921 
922  if (fXEvent) gdk_event_free((GdkEvent*)fXEvent);
923 
925 
926  gROOT->SetBatch(kTRUE); // no GUI is possible
927 }
928 
929 ////////////////////////////////////////////////////////////////////////////////
930 ///
931 
933 {
934  if (gMainThread && gMainThread->fCritSec) ::EnterCriticalSection(gMainThread->fCritSec);
935 }
936 
937 ////////////////////////////////////////////////////////////////////////////////
938 ///
939 
941 {
942  if (gMainThread && gMainThread->fCritSec) ::LeaveCriticalSection(gMainThread->fCritSec);
943 }
944 
945 ////////////////////////////////////////////////////////////////////////////////
946 /// Initialize Win32 system. Returns kFALSE in case of failure.
947 
948 Bool_t TGWin32::Init(void *display)
949 {
950  if (!gdk_initialized) {
951  if (!gdk_init_check(NULL, NULL)) return kFALSE;
952  gdk_initialized = true;
953  }
954 
955  if (!gClipboardAtom) {
956  gClipboardAtom = gdk_atom_intern("CLIPBOARD", kFALSE);
957  }
958 
959  return kTRUE;
960 }
961 
962 ////////////////////////////////////////////////////////////////////////////////
963 /// Open the display. Return -1 if the opening fails, 0 when ok.
964 
965 Int_t TGWin32::OpenDisplay(const char *dpyName)
966 {
967  GdkPixmap *pixmp1, *pixmp2;
968  GdkColor fore, back;
969  GdkColor color;
970  GdkGCValues gcvals;
971  int i;
972 
973  if (!Init((void*)dpyName)) {
974  return -1;
975  }
976 
977  if (gDebug <= 4) {
979  } else {
980  gdk_debug_level = 0;
981  }
982 
983  fore.red = fore.green = fore.blue = 0;
984  back.red = back.green = back.blue = 0;
985  color.red = color.green = color.blue = 0;
986 
987  fScreenNumber = 0; //DefaultScreen(fDisplay);
988  fVisual = gdk_visual_get_best();
989  fColormap = gdk_colormap_get_system();
990  fDepth = gdk_visual_get_best_depth();
991 
992  GetColor(1).fDefined = kTRUE; // default foreground
993  gdk_color_black((GdkColormap *)fColormap, &GetColor(1).color);
994 
995  GetColor(0).fDefined = kTRUE; // default background
996  gdk_color_white((GdkColormap *)fColormap, &GetColor(0).color);
997 
998  // Create primitives graphic contexts
999  for (i = 0; i < kMAXGC; i++) {
1000  gGClist[i] = gdk_gc_new(GDK_ROOT_PARENT());
1001  gdk_gc_set_foreground(gGClist[i], &GetColor(1).color);
1002  gdk_gc_set_background(gGClist[i], &GetColor(0).color);
1003  }
1004 
1005  gGCline = gGClist[0]; // PolyLines
1006  gGCmark = gGClist[1]; // PolyMarker
1007  gGCfill = gGClist[2]; // Fill areas
1008  gGCtext = gGClist[3]; // Text
1009  gGCinvt = gGClist[4]; // Inverse text
1010  gGCdash = gGClist[5]; // Dashed lines
1011  gGCpxmp = gGClist[6]; // Pixmap management
1012 
1013  gdk_gc_get_values(gGCtext, &gcvals);
1014  gdk_gc_set_foreground(gGCinvt, &gcvals.background);
1015  gdk_gc_set_background(gGCinvt, &gcvals.foreground);
1016 
1017  // Create input echo graphic context
1018  GdkGCValues echov;
1019  gdk_color_black(fColormap, &echov.foreground); // = BlackPixel(fDisplay, fScreenNumber);
1020  gdk_color_white(fColormap, &echov.background); // = WhitePixel(fDisplay, fScreenNumber);
1021  echov.function = GDK_INVERT;
1022  echov.subwindow_mode = GDK_CLIP_BY_CHILDREN;
1023  gGCecho =
1024  gdk_gc_new_with_values((GdkWindow *) GDK_ROOT_PARENT(), &echov,
1025  (GdkGCValuesMask) (GDK_GC_FOREGROUND |
1026  GDK_GC_BACKGROUND |
1027  GDK_GC_FUNCTION |
1028  GDK_GC_SUBWINDOW));
1029  // Create a null cursor
1030  pixmp1 = gdk_bitmap_create_from_data(GDK_ROOT_PARENT(),
1031  (const char *)null_cursor_bits, 16,16);
1032 
1033  pixmp2 = gdk_bitmap_create_from_data(GDK_ROOT_PARENT(),
1034  (const char *)null_cursor_bits, 16, 16);
1035 
1036  gNullCursor = gdk_cursor_new_from_pixmap((GdkDrawable *)pixmp1, (GdkDrawable *)pixmp2,
1037  &fore, &back, 0, 0);
1038  // Create cursors
1039  if (gEnv->GetValue("Win32.UseSysPointers", 0)) {
1041  fCursors[kBottomLeft] = gdk_syscursor_new((ULong_t)IDC_SIZENESW);
1042  fCursors[kBottomRight] = gdk_syscursor_new((ULong_t)IDC_SIZENWSE);
1043  fCursors[kTopLeft] = gdk_syscursor_new((ULong_t)IDC_SIZENWSE);
1044  fCursors[kTopRight] = gdk_syscursor_new((ULong_t)IDC_SIZENESW);
1045  fCursors[kBottomSide] = gdk_syscursor_new((ULong_t)IDC_SIZENS);
1046  fCursors[kLeftSide] = gdk_syscursor_new((ULong_t)IDC_SIZEWE);
1047  fCursors[kTopSide] = gdk_syscursor_new((ULong_t)IDC_SIZENS);
1048  fCursors[kRightSide] = gdk_syscursor_new((ULong_t)IDC_SIZEWE);
1049  fCursors[kMove] = gdk_syscursor_new((ULong_t)IDC_SIZEALL);
1050  fCursors[kCross] =gdk_syscursor_new((ULong_t)IDC_CROSS);
1051  fCursors[kArrowHor] = gdk_syscursor_new((ULong_t)IDC_SIZEWE);
1052  fCursors[kArrowVer] = gdk_syscursor_new((ULong_t)IDC_SIZENS);
1053  fCursors[kHand] = gdk_syscursor_new((ULong_t)IDC_HAND);
1054  fCursors[kPointer] = gdk_syscursor_new((ULong_t)IDC_ARROW);
1055  fCursors[kCaret] = gdk_syscursor_new((ULong_t)IDC_IBEAM);
1056  fCursors[kWatch] = gdk_syscursor_new((ULong_t)IDC_WAIT);
1057  fCursors[kNoDrop] = gdk_syscursor_new((ULong_t)IDC_NO);
1058  }
1059  else {
1061  fCursors[kBottomLeft] = gdk_cursor_new(GDK_BOTTOM_LEFT_CORNER);
1062  fCursors[kBottomRight] = gdk_cursor_new(GDK_BOTTOM_RIGHT_CORNER);
1063  fCursors[kTopLeft] = gdk_cursor_new(GDK_TOP_LEFT_CORNER);
1064  fCursors[kTopRight] = gdk_cursor_new(GDK_TOP_RIGHT_CORNER);
1065  fCursors[kBottomSide] = gdk_cursor_new(GDK_BOTTOM_SIDE);
1066  fCursors[kLeftSide] = gdk_cursor_new(GDK_LEFT_SIDE);
1067  fCursors[kTopSide] = gdk_cursor_new(GDK_TOP_SIDE);
1068  fCursors[kRightSide] = gdk_cursor_new(GDK_RIGHT_SIDE);
1069  fCursors[kMove] = gdk_cursor_new(GDK_FLEUR);
1070  fCursors[kCross] =gdk_cursor_new(GDK_CROSSHAIR);
1071  fCursors[kArrowHor] = gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW);
1072  fCursors[kArrowVer] = gdk_cursor_new(GDK_SB_V_DOUBLE_ARROW);
1073  fCursors[kHand] = gdk_cursor_new(GDK_HAND2);
1074  fCursors[kPointer] = gdk_cursor_new(GDK_LEFT_PTR);
1075  fCursors[kCaret] = gdk_cursor_new(GDK_XTERM);
1076  //fCursors[kWatch] = gdk_cursor_new(GDK_WATCH);
1077  fCursors[kWatch] = gdk_cursor_new(GDK_BUSY);
1078  fCursors[kNoDrop] = gdk_cursor_new(GDK_PIRATE);
1079  }
1080  fCursors[kRotate] = gdk_cursor_new(GDK_EXCHANGE);
1081  fCursors[kArrowRight] = gdk_cursor_new(GDK_ARROW);
1082 
1083  // Setup color information
1085 
1086  if ( gdk_visual_get_best_type() == GDK_VISUAL_TRUE_COLOR) {
1087  int i;
1088  for (i = 0; i < int(sizeof(fVisual->blue_mask)*kBitsPerByte); i++) {
1089  if (fBlueShift == -1 && ((fVisual->blue_mask >> i) & 1)) {
1090  fBlueShift = i;
1091  }
1092  if ((fVisual->blue_mask >> i) == 1) {
1093  fBlueDiv = sizeof(UShort_t)*kBitsPerByte - i - 1 + fBlueShift;
1094  break;
1095  }
1096  }
1097  for (i = 0; i < int(sizeof(fVisual->green_mask)*kBitsPerByte); i++) {
1098  if (fGreenShift == -1 && ((fVisual->green_mask >> i) & 1)) {
1099  fGreenShift = i;
1100  }
1101  if ((fVisual->green_mask >> i) == 1) {
1102  fGreenDiv = sizeof(UShort_t)*kBitsPerByte - i - 1 + fGreenShift;
1103  break;
1104  }
1105  }
1106  for (i = 0; i < int(sizeof(fVisual->red_mask)*kBitsPerByte); i++) {
1107  if (fRedShift == -1 && ((fVisual->red_mask >> i) & 1)) {
1108  fRedShift = i;
1109  }
1110  if ((fVisual->red_mask >> i) == 1) {
1111  fRedDiv = sizeof(UShort_t)*kBitsPerByte - i - 1 + fRedShift;
1112  break;
1113  }
1114  }
1115  }
1116 
1117  SetName("Win32TTF");
1118  SetTitle("ROOT interface to Win32 with TrueType fonts");
1119 
1120  if (!TTF::IsInitialized()) TTF::Init();
1121 
1122  if (fDepth > 8) {
1124  } else {
1126  }
1127 
1129  fHasTTFonts = kTRUE;
1130  return 0;
1131 }
1132 
1133 ////////////////////////////////////////////////////////////////////////////////
1134 /// Allocate color in colormap. If we are on an <= 8 plane machine
1135 /// we will use XAllocColor. If we are on a >= 15 (15, 16 or 24) plane
1136 /// true color machine we will calculate the pixel value using:
1137 /// for 15 and 16 bit true colors have 6 bits precision per color however
1138 /// only the 5 most significant bits are used in the color index.
1139 /// Except for 16 bits where green uses all 6 bits. I.e.:
1140 /// 15 bits = rrrrrgggggbbbbb
1141 /// 16 bits = rrrrrggggggbbbbb
1142 /// for 24 bits each r, g and b are represented by 8 bits.
1143 ///
1144 /// Since all colors are set with a max of 65535 (16 bits) per r, g, b
1145 /// we just right shift them by 10, 11 and 10 bits for 16 planes, and
1146 /// (10, 10, 10 for 15 planes) and by 8 bits for 24 planes.
1147 /// Returns kFALSE in case color allocation failed.
1148 
1149 Bool_t TGWin32::AllocColor(GdkColormap *cmap, GdkColor *color)
1150 {
1151  if (fRedDiv == -1) {
1152  if ( gdk_color_alloc((GdkColormap *)cmap, (GdkColor *)color) ) return kTRUE;
1153  } else {
1154  color->pixel = (color->red >> fRedDiv) << fRedShift |
1155  (color->green >> fGreenDiv) << fGreenShift |
1156  (color->blue >> fBlueDiv) << fBlueShift;
1157  return kTRUE;
1158  }
1159 
1160  return kFALSE;
1161 }
1162 
1163 ////////////////////////////////////////////////////////////////////////////////
1164 /// Returns the current RGB value for the pixel in the XColor structure.
1165 
1166 void TGWin32::QueryColors(GdkColormap *cmap, GdkColor *color, Int_t ncolors)
1167 {
1168  ULong_t r, g, b;
1169 
1170  if (fRedDiv == -1) {
1171  GdkColorContext *cc = gdk_color_context_new(gdk_visual_get_system(), cmap);
1172  gdk_color_context_query_colors(cc, color, ncolors);
1173  gdk_color_context_free(cc);
1174  } else {
1175  for (Int_t i = 0; i < ncolors; i++) {
1176  r = (color[i].pixel & fVisual->red_mask) >> fRedShift;
1177  color[i].red = UShort_t(r*kBIGGEST_RGB_VALUE/(fVisual->red_mask >> fRedShift));
1178 
1179  g = (color[i].pixel & fVisual->green_mask) >> fGreenShift;
1180  color[i].green = UShort_t(g*kBIGGEST_RGB_VALUE/(fVisual->green_mask >> fGreenShift));
1181 
1182  b = (color[i].pixel & fVisual->blue_mask) >> fBlueShift;
1183  color[i].blue = UShort_t(b*kBIGGEST_RGB_VALUE/(fVisual->blue_mask >> fBlueShift));
1184  }
1185  }
1186 }
1187 
1188 ////////////////////////////////////////////////////////////////////////////////
1189 /// Compute alignment variables. The alignment is done on the horizontal string
1190 /// then the rotation is applied on the alignment variables.
1191 /// SetRotation and LayoutGlyphs should have been called before.
1192 
1193 void TGWin32::Align(void)
1194 {
1195  EAlign align = (EAlign) fTextAlign;
1196 
1197  // vertical alignment
1198  if (align == kTLeft || align == kTCenter || align == kTRight) {
1199  fAlign.y = TTF::GetAscent();
1200  } else if (align == kMLeft || align == kMCenter || align == kMRight) {
1201  fAlign.y = TTF::GetAscent()/2;
1202  } else {
1203  fAlign.y = 0;
1204  }
1205  // horizontal alignment
1206  if (align == kTRight || align == kMRight || align == kBRight) {
1207  fAlign.x = TTF::GetWidth();
1208  } else if (align == kTCenter || align == kMCenter || align == kBCenter) {
1209  fAlign.x = TTF::GetWidth()/2;
1210  } else {
1211  fAlign.x = 0;
1212  }
1213 
1214  FT_Vector_Transform(&fAlign, TTF::GetRotMatrix());
1215  fAlign.x = fAlign.x >> 6;
1216  fAlign.y = fAlign.y >> 6;
1217 }
1218 
1219 ////////////////////////////////////////////////////////////////////////////////
1220 /// Draw FT_Bitmap bitmap to xim image at position bx,by using specified
1221 /// foreground color.
1222 
1223 void TGWin32::DrawImage(FT_Bitmap *source, ULong_t fore, ULong_t back,
1224  GdkImage *xim, Int_t bx, Int_t by)
1225 {
1226  UChar_t d = 0, *s = source->buffer;
1227 
1228  if (TTF::GetSmoothing()) {
1229 
1230  static GdkColor col[5];
1231  GdkColor *bcol = 0, *bc;
1232  Int_t x, y;
1233 
1234  // background kClear, i.e. transparent, we take as background color
1235  // the average of the rgb values of all pixels covered by this character
1236  if (back == (ULong_t) -1 && (UInt_t)source->width) {
1237  ULong_t r, g, b;
1238  Int_t dots, dotcnt;
1239  const Int_t maxdots = 50000;
1240 
1241  dots = Int_t(source->width * source->rows);
1242  dots = dots > maxdots ? maxdots : dots;
1243  bcol = new GdkColor[dots];
1244  if (!bcol) return;
1245 
1246  bc = bcol;
1247  dotcnt = 0;
1248  for (y = 0; y < (int) source->rows; y++) {
1249  for (x = 0; x < (int) source->width; x++, bc++) {
1250  bc->pixel = GetPixelImage((Drawable_t)xim, bx + x, by + y);
1251  if (++dotcnt >= maxdots) break;
1252  }
1253  }
1254  QueryColors(fColormap, bcol, dots);
1255  r = g = b = 0;
1256  bc = bcol;
1257  dotcnt = 0;
1258  for (y = 0; y < (int) source->rows; y++) {
1259  for (x = 0; x < (int) source->width; x++, bc++) {
1260  r += bc->red;
1261  g += bc->green;
1262  b += bc->blue;
1263  if (++dotcnt >= maxdots) break;
1264  }
1265  }
1266  if (dots != 0) {
1267  r /= dots;
1268  g /= dots;
1269  b /= dots;
1270  }
1271  bc = &col[0];
1272  if (bc->red == r && bc->green == g && bc->blue == b) {
1273  bc->pixel = back;
1274  } else {
1275  bc->pixel = ~back;
1276  bc->red = (UShort_t) r;
1277  bc->green = (UShort_t) g;
1278  bc->blue = (UShort_t) b;
1279  }
1280  }
1281  delete [] bcol;
1282 
1283  // if fore or background have changed from previous character
1284  // recalculate the 3 smooting colors (interpolation between fore-
1285  // and background colors)
1286  if (fore != col[4].pixel || back != col[0].pixel) {
1287  col[4].pixel = fore;
1288  if (back != (ULong_t) -1) {
1289  col[3].pixel = back;
1290  QueryColors(fColormap, &col[3], 2);
1291  col[0] = col[3];
1292  } else {
1293  QueryColors(fColormap, &col[4], 1);
1294  }
1295 
1296  // interpolate between fore and backgound colors
1297  for (x = 3; x > 0; x--) {
1298  col[x].red = (col[4].red *x + col[0].red *(4-x)) /4;
1299  col[x].green = (col[4].green*x + col[0].green*(4-x)) /4;
1300  col[x].blue = (col[4].blue *x + col[0].blue *(4-x)) /4;
1301  if (!AllocColor(fColormap, &col[x])) {
1302  Warning("DrawImage", "cannot allocate smoothing color");
1303  col[x].pixel = col[x+1].pixel;
1304  }
1305  }
1306  }
1307 
1308  // put smoothed character, character pixmap values are an index
1309  // into the 5 colors used for aliasing (4 = foreground, 0 = background)
1310  for (y = 0; y < (int) source->rows; y++) {
1311  for (x = 0; x < (int) source->width; x++) {
1312  d = *s++ & 0xff;
1313  d = ((d + 10) * 5) / 256;
1314  if (d > 4) d = 4;
1315  if (d && x < (int) source->width) {
1316  ULong_t p = col[d].pixel;
1317  PutPixel((Drawable_t)xim, bx + x, by + y, p);
1318  }
1319  }
1320  }
1321  } else {
1322  // no smoothing, just put character using foreground color
1323  UChar_t* row=s;
1324  for (int y = 0; y < (int) source->rows; y++) {
1325  int n = 0;
1326  s = row;
1327  for (int x = 0; x < (int) source->width; x++) {
1328  if (n == 0) d = *s++;
1329  if (TESTBIT(d,7-n)) {
1330  PutPixel((Drawable_t)xim, bx + x, by + y, fore);
1331  }
1332  if (++n == (int) kBitsPerByte) n = 0;
1333  }
1334  row += source->pitch;
1335  }
1336  }
1337 }
1338 
1339 ////////////////////////////////////////////////////////////////////////////////
1340 /// Draw text using TrueType fonts. If TrueType fonts are not available the
1341 /// text is drawn with TGWin32::DrawText.
1342 
1344  const char *text, ETextMode mode)
1345 {
1346  if (!TTF::IsInitialized()) TTF::Init();
1347  TTF::SetRotationMatrix(angle);
1350  Align();
1351  RenderString(x, y, mode);
1352 }
1353 
1354 ////////////////////////////////////////////////////////////////////////////////
1355 /// Draw text using TrueType fonts. If TrueType fonts are not available the
1356 /// text is drawn with TGWin32::DrawText.
1357 
1359  const wchar_t *text, ETextMode mode)
1360 {
1361  if (!TTF::IsInitialized()) TTF::Init();
1362  TTF::SetRotationMatrix(angle);
1365  Align();
1366  RenderString(x, y, mode);
1367 }
1368 
1369 ////////////////////////////////////////////////////////////////////////////////
1370 /// Get the background of the current window in an XImage.
1371 
1373 {
1374  Window_t cws = GetCurrentWindow();
1375  UInt_t width;
1376  UInt_t height;
1377  Int_t xy;
1378  gVirtualX->GetWindowSize(cws, xy, xy, width, height);
1379 
1380  if (x < 0) {
1381  w += x;
1382  x = 0;
1383  }
1384  if (y < 0) {
1385  h += y;
1386  y = 0;
1387  }
1388 
1389  if (x+w > width) w = width - x;
1390  if (y+h > height) h = height - y;
1391 
1392  return gdk_image_get((GdkDrawable*)cws, x, y, w, h);
1393 }
1394 
1395 ////////////////////////////////////////////////////////////////////////////////
1396 /// Test if there is really something to render
1397 
1399 {
1400  Window_t cws = GetCurrentWindow();
1401  UInt_t width;
1402  UInt_t height;
1403  Int_t xy;
1404  gVirtualX->GetWindowSize(cws, xy, xy, width, height);
1405 
1406  // If w or h is 0, very likely the string is only blank characters
1407  if ((int)w == 0 || (int)h == 0) return kFALSE;
1408 
1409  // If string falls outside window, there is probably no need to draw it.
1410  if (x + (int)w <= 0 || x >= (int)width) return kFALSE;
1411  if (y + (int)h <= 0 || y >= (int)height) return kFALSE;
1412 
1413  return kTRUE;
1414 }
1415 
1416 ////////////////////////////////////////////////////////////////////////////////
1417 /// Perform the string rendering in the pad.
1418 /// LayoutGlyphs should have been called before.
1419 
1421 {
1422  TTF::TTGlyph* glyph = TTF::GetGlyphs();
1423  GdkGCValues gcvals;
1424 
1425  // compute the size and position of the XImage that will contain the text
1426  Int_t Xoff = 0; if (TTF::GetBox().xMin < 0) Xoff = -TTF::GetBox().xMin;
1427  Int_t Yoff = 0; if (TTF::GetBox().yMin < 0) Yoff = -TTF::GetBox().yMin;
1428  Int_t w = TTF::GetBox().xMax + Xoff;
1429  Int_t h = TTF::GetBox().yMax + Yoff;
1430  Int_t x1 = x-Xoff-fAlign.x;
1431  Int_t y1 = y+Yoff+fAlign.y-h;
1432 
1433  if (!IsVisible(x1, y1, w, h)) {
1434  return;
1435  }
1436 
1437  // create the XImage that will contain the text
1438  UInt_t depth = fDepth;
1439  GdkImage *xim = gdk_image_new(GDK_IMAGE_SHARED, gdk_visual_get_best(), w, h);
1440 
1441  // use malloc since Xlib will use free() in XDestroyImage
1442 // xim->data = (char *) malloc(xim->bytes_per_line * h);
1443 // memset(xim->data, 0, xim->bytes_per_line * h);
1444 
1445  ULong_t pixel;
1446  ULong_t bg;
1447 
1448  gdk_gc_get_values((GdkGC*)GetGC(3), &gcvals);
1449 
1450  // get the background
1451  if (mode == kClear) {
1452  // if mode == kClear we need to get an image of the background
1453  GdkImage *bim = GetBackground(x1, y1, w, h);
1454  if (!bim) {
1455  Error("DrawText", "error getting background image");
1456  return;
1457  }
1458 
1459  // and copy it into the text image
1460  Int_t xo = 0, yo = 0;
1461  if (x1 < 0) xo = -x1;
1462  if (y1 < 0) yo = -y1;
1463 
1464  for (int yp = 0; yp < (int) bim->height; yp++) {
1465  for (int xp = 0; xp < (int) bim->width; xp++) {
1466  pixel = GetPixelImage((Drawable_t)bim, xp, yp);
1467  PutPixel((Drawable_t)xim, xo+xp, yo+yp, pixel);
1468  }
1469  }
1470 
1471  gdk_image_unref((GdkImage *)bim);
1472 
1473  bg = (ULong_t) -1;
1474  } else {
1475  // if mode == kOpaque its simple, we just draw the background
1476 
1477  GdkImage *bim = GetBackground(x1, y1, w, h);
1478  if (!bim) {
1479  pixel = gcvals.background.pixel;
1480  } else {
1481  pixel = GetPixelImage((Drawable_t)bim, 0, 0);
1482  }
1483  Int_t xo = 0, yo = 0;
1484  if (x1 < 0) xo = -x1;
1485  if (y1 < 0) yo = -y1;
1486 
1487  for (int yp = 0; yp < h; yp++) {
1488  for (int xp = 0; xp < (int) w; xp++) {
1489  PutPixel((Drawable_t)xim, xo+xp, yo+yp, pixel);
1490  }
1491  }
1492  if (bim) {
1493  gdk_image_unref((GdkImage *)bim);
1494  bg = (ULong_t) -1;
1495  } else {
1496  bg = pixel;
1497  }
1498  }
1499 
1500  // paint the glyphs in the XImage
1501  glyph = TTF::GetGlyphs();
1502  for (int n = 0; n < TTF::GetNumGlyphs(); n++, glyph++) {
1503  if (FT_Glyph_To_Bitmap(&glyph->fImage,
1504  TTF::GetSmoothing() ? ft_render_mode_normal
1505  : ft_render_mode_mono,
1506  0, 1 )) continue;
1507  FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyph->fImage;
1508  FT_Bitmap* source = &bitmap->bitmap;
1509  Int_t bx, by;
1510 
1511  bx = bitmap->left+Xoff;
1512  by = h - bitmap->top-Yoff;
1513  DrawImage(source, gcvals.foreground.pixel, bg, xim, bx, by);
1514  }
1515 
1516  // put the Ximage on the screen
1517  Window_t cws = GetCurrentWindow();
1518  gdk_draw_image((GdkDrawable *)cws, GetGC(6), xim, 0, 0, x1, y1, w, h);
1519 
1520  gdk_image_unref(xim);
1521 }
1522 
1523 ////////////////////////////////////////////////////////////////////////////////
1524 /// Set specified font.
1525 
1527 {
1528  fTextFont = fontnumber;
1529  TTF::SetTextFont(fontnumber);
1530 }
1531 
1532 ////////////////////////////////////////////////////////////////////////////////
1533 /// Set text font to specified name.
1534 /// mode : loading flag
1535 /// mode=0 : search if the font exist (kCheck)
1536 /// mode=1 : search the font and load it if it exists (kLoad)
1537 /// font : font name
1538 ///
1539 /// Set text font to specified name. This function returns 0 if
1540 /// the specified font is found, 1 if not.
1541 
1543 {
1544  return TTF::SetTextFont(fontname);
1545 }
1546 
1547 ////////////////////////////////////////////////////////////////////////////////
1548 /// Set current text size.
1549 
1551 {
1552  fTextSize = textsize;
1553  TTF::SetTextSize(textsize);
1554 }
1555 
1556 ////////////////////////////////////////////////////////////////////////////////
1557 /// Clear current window.
1558 
1560 {
1561  if (!fWindows) return;
1562 
1563  if (!gCws->ispixmap && !gCws->double_buffer) {
1564  gdk_window_set_background(gCws->drawing, (GdkColor *) & GetColor(0).color);
1565  gdk_window_clear(gCws->drawing);
1566  GdiFlush();
1567  } else {
1568  SetColor(gGCpxmp, 0);
1569  gdk_win32_draw_rectangle(gCws->drawing, gGCpxmp, 1,
1570  0, 0, gCws->width, gCws->height);
1571  SetColor(gGCpxmp, 1);
1572  }
1573 }
1574 
1575 ////////////////////////////////////////////////////////////////////////////////
1576 /// Delete current pixmap.
1577 
1579 {
1580  CloseWindow1();
1581 }
1582 
1583 ////////////////////////////////////////////////////////////////////////////////
1584 /// Delete current window.
1585 
1587 {
1588  CloseWindow1();
1589 }
1590 
1591 ////////////////////////////////////////////////////////////////////////////////
1592 /// Delete current window.
1593 
1595 {
1596  int wid;
1597 
1598  if (gCws->ispixmap) {
1599  gdk_pixmap_unref(gCws->window);
1600  } else {
1601  gdk_window_destroy(gCws->window, kTRUE);
1602  }
1603 
1604  if (gCws->buffer) {
1605  gdk_pixmap_unref(gCws->buffer);
1606  }
1607  if (gCws->new_colors) {
1608  gdk_colormap_free_colors((GdkColormap *) fColormap,
1609  (GdkColor *)gCws->new_colors, gCws->ncolors);
1610 
1611  delete [] gCws->new_colors;
1612  gCws->new_colors = 0;
1613  }
1614 
1615  GdiFlush();
1616  gCws->open = 0;
1617 
1618  if (!fWindows) return;
1619 
1620  // make first window in list the current window
1621  for (wid = 0; wid < fMaxNumberOfWindows; wid++) {
1622  if (fWindows[wid].open) {
1623  gCws = &fWindows[wid];
1624  return;
1625  }
1626  }
1627  gCws = 0;
1628 }
1629 
1630 ////////////////////////////////////////////////////////////////////////////////
1631 /// Copy the pixmap wid at the position xpos, ypos in the current window.
1632 
1633 void TGWin32::CopyPixmap(int wid, int xpos, int ypos)
1634 {
1635  if (!fWindows) return;
1636 
1637  gTws = &fWindows[wid];
1638  gdk_window_copy_area(gCws->drawing, gGCpxmp, xpos, ypos, gTws->drawing,
1639  0, 0, gTws->width, gTws->height);
1640  GdiFlush();
1641 }
1642 
1643 ////////////////////////////////////////////////////////////////////////////////
1644 /// Draw a box.
1645 /// mode=0 hollow (kHollow)
1646 /// mode=1 solid (kSolid)
1647 
1648 void TGWin32::DrawBox(int x1, int y1, int x2, int y2, EBoxMode mode)
1649 {
1650  if (!fWindows) return;
1651 
1652  Int_t x = TMath::Min(x1, x2);
1653  Int_t y = TMath::Min(y1, y2);
1654  Int_t w = TMath::Abs(x2 - x1);
1655  Int_t h = TMath::Abs(y2 - y1);
1656 
1657  switch (mode) {
1658 
1659  case kHollow:
1662  gdk_win32_draw_rectangle(gCws->drawing, gGCline, 0, x, y, w, h);
1663  break;
1664 
1665  case kFilled:
1668  gdk_win32_draw_rectangle(gCws->drawing, gGCfill, 1, x, y, w, h);
1669  break;
1670 
1671  default:
1672  break;
1673  }
1674 }
1675 
1676 ////////////////////////////////////////////////////////////////////////////////
1677 /// Draw a cell array.
1678 /// x1,y1 : left down corner
1679 /// x2,y2 : right up corner
1680 /// nx,ny : array size
1681 /// ic : array
1682 ///
1683 /// Draw a cell array. The drawing is done with the pixel presicion
1684 /// if (X2-X1)/NX (or Y) is not a exact pixel number the position of
1685 /// the top rigth corner may be wrong.
1686 
1688  Int_t nx, Int_t ny, Int_t *ic)
1689 {
1690  int i, j, icol, ix, iy, w, h, current_icol;
1691 
1692  if (!fWindows) return;
1693 
1694  current_icol = -1;
1695  w = TMath::Max((x2 - x1) / (nx), 1);
1696  h = TMath::Max((y1 - y2) / (ny), 1);
1697  ix = x1;
1698 
1701 
1702  for (i = 0; i < nx; i++) {
1703  iy = y1 - h;
1704  for (j = 0; j < ny; j++) {
1705  icol = ic[i + (nx * j)];
1706  if (icol != current_icol) {
1707  gdk_gc_set_foreground(gGCfill, (GdkColor *) & GetColor(icol).color);
1708  current_icol = icol;
1709  }
1710 
1711  gdk_win32_draw_rectangle(gCws->drawing, gGCfill, kTRUE, ix, iy, w, h);
1712  iy = iy - h;
1713  }
1714  ix = ix + w;
1715  }
1716 }
1717 
1718 ////////////////////////////////////////////////////////////////////////////////
1719 /// Fill area described by polygon.
1720 /// n : number of points
1721 /// xy(2,n) : list of points
1722 
1724 {
1725  int i;
1726  static int lastn = 0;
1727  static GdkPoint *xy = 0;
1728 
1729  if (!fWindows) return;
1730 
1733 
1734  if (lastn!=n) {
1735  delete [] (GdkPoint *)xy;
1736  xy = new GdkPoint[n];
1737  lastn = n;
1738  }
1739  for (i = 0; i < n; i++) {
1740  xy[i].x = xyt[i].fX;
1741  xy[i].y = xyt[i].fY;
1742  }
1743 
1744  if (gFillHollow) {
1745  gdk_win32_draw_lines(gCws->drawing, gGCfill, xy, n);
1746  } else {
1747  gdk_win32_draw_polygon(gCws->drawing, gGCfill, 1, xy, n);
1748  }
1749 }
1750 
1751 ////////////////////////////////////////////////////////////////////////////////
1752 /// Draw a line.
1753 /// x1,y1 : begin of line
1754 /// x2,y2 : end of line
1755 
1756 void TGWin32::DrawLine(int x1, int y1, int x2, int y2)
1757 {
1758  if (!fWindows) return;
1759 
1762 
1763  if (gLineStyle == GDK_LINE_SOLID) {
1764  gdk_draw_line(gCws->drawing, gGCline, x1, y1, x2, y2);
1765  } else {
1766  int i;
1767  gint8 dashes[32];
1768  for (i = 0; i < gDashSize; i++) {
1769  dashes[i] = (gint8) gDashList[i];
1770  }
1771  for (i = gDashSize; i < 32; i++) {
1772  dashes[i] = (gint8) 0;
1773  }
1774  gdk_gc_set_dashes(gGCdash, gDashOffset, dashes, gDashSize);
1775  gdk_draw_line(gCws->drawing, gGCdash, x1, y1, x2, y2);
1776  }
1777 }
1778 
1779 ////////////////////////////////////////////////////////////////////////////////
1780 /// Draw a line through all points.
1781 /// n : number of points
1782 /// xy : list of points
1783 
1785 {
1786  int i;
1787 
1788  if (!fWindows) return;
1789 
1790  Point_t *xy = new Point_t[n];
1791 
1792  for (i = 0; i < n; i++) {
1793  xy[i].fX = xyt[i].fX;
1794  xy[i].fY = xyt[i].fY;
1795  }
1796 
1799 
1800  if (n > 1) {
1801  if (gLineStyle == GDK_LINE_SOLID) {
1802  gdk_win32_draw_lines(gCws->drawing, gGCline, (GdkPoint *)xy, n);
1803  } else {
1804  int i;
1805  gint8 dashes[32];
1806 
1807  for (i = 0; i < gDashSize; i++) {
1808  dashes[i] = (gint8) gDashList[i];
1809  }
1810  for (i = gDashSize; i < 32; i++) {
1811  dashes[i] = (gint8) 0;
1812  }
1813 
1814  gdk_gc_set_dashes(gGCdash, gDashOffset, dashes, gDashSize);
1815  gdk_win32_draw_lines(gCws->drawing, (GdkGC*)gGCdash, (GdkPoint *)xy, n);
1816 
1817  // calculate length of line to update dash offset
1818  for (i = 1; i < n; i++) {
1819  int dx = xy[i].fX - xy[i - 1].fX;
1820  int dy = xy[i].fY - xy[i - 1].fY;
1821 
1822  if (dx < 0) dx = -dx;
1823  if (dy < 0) dy = -dy;
1824  gDashOffset += dx > dy ? dx : dy;
1825  }
1827  }
1828  } else {
1829  gdk_win32_draw_points( gCws->drawing, gLineStyle == GDK_LINE_SOLID ?
1830  gGCline : gGCdash, (GdkPoint *)xy,1);
1831  }
1832  delete [] xy;
1833 }
1834 
1835 ////////////////////////////////////////////////////////////////////////////////
1836 /// Draw n markers with the current attributes at position x, y.
1837 /// n : number of markers to draw
1838 /// xy : x,y coordinates of markers
1839 
1841 {
1842  int i;
1843  static int lastn = 0;
1844  static GdkPoint *xy = 0;
1845 
1846  if (!fWindows) return;
1847 
1850 
1851  if (lastn!=n) {
1852  delete [] (GdkPoint *)xy;
1853  xy = new GdkPoint[n];
1854  lastn = n;
1855  }
1856 
1857  for (i = 0; i < n; i++) {
1858  xy[i].x = xyt[i].fX;
1859  xy[i].y = xyt[i].fY;
1860  }
1861 
1862  if (gMarker.n <= 0) {
1863  gdk_win32_draw_points(gCws->drawing, gGCmark, xy, n);
1864  } else {
1865  int r = gMarker.n / 2;
1866  int m;
1867 
1868  for (m = 0; m < n; m++) {
1869  int hollow = 0;
1870  switch (gMarker.type) {
1871  int i;
1872 
1873  case 0: // hollow circle
1874  gdk_win32_draw_arc(gCws->drawing, gGCmark, kFALSE, xy[m].x-r, xy[m].y-r,
1875  gMarker.n, gMarker.n, 0, 23040);
1876  break;
1877 
1878  case 1: // filled circle
1879  gdk_win32_draw_arc(gCws->drawing, gGCmark, kTRUE, xy[m].x-r, xy[m].y-r,
1880  gMarker.n, gMarker.n, 0, 23040);
1881  break;
1882 
1883  case 2: // hollow polygon
1884  hollow = 1;
1885  case 3: // filled polygon
1886  for (i = 0; i < gMarker.n; i++) {
1887  gMarker.xy[i].x += xy[m].x;
1888  gMarker.xy[i].y += xy[m].y;
1889  }
1890  if (hollow) {
1891  gdk_win32_draw_lines(gCws->drawing, gGCmark, (GdkPoint *)gMarker.xy, gMarker.n);
1892  } else {
1893  gdk_win32_draw_polygon(gCws->drawing, gGCmark, 1, (GdkPoint *)gMarker.xy, gMarker.n);
1894  }
1895  for (i = 0; i < gMarker.n; i++) {
1896  gMarker.xy[i].x -= xy[m].x;
1897  gMarker.xy[i].y -= xy[m].y;
1898  }
1899  break;
1900 
1901  case 4: // segmented line
1902  for (i = 0; i < gMarker.n; i += 2) {
1903  gdk_draw_line(gCws->drawing, gGCmark,
1904  xy[m].x + gMarker.xy[i].x,
1905  xy[m].y + gMarker.xy[i].y,
1906  xy[m].x + gMarker.xy[i + 1].x,
1907  xy[m].y + gMarker.xy[i + 1].y);
1908  }
1909  break;
1910  }
1911  }
1912  }
1913 }
1914 
1915 ////////////////////////////////////////////////////////////////////////////////
1916 /// Return character up vector.
1917 
1919 {
1920  chupx = fCharacterUpX;
1921  chupy = fCharacterUpY;
1922 }
1923 
1924 ////////////////////////////////////////////////////////////////////////////////
1925 /// Return reference to internal color structure associated
1926 /// to color index cid.
1927 
1929 {
1930  XColor_t *col = (XColor_t*) fColors->GetValue(cid);
1931  if (!col) {
1932  col = new XColor_t;
1933  fColors->Add(cid, (Long_t) col);
1934  }
1935  return *col;
1936 }
1937 
1938 ////////////////////////////////////////////////////////////////////////////////
1939 /// Return current window pointer. Protected method used by TGWin32TTF.
1940 
1942 {
1943  return (Window_t)(gCws ? gCws->drawing : 0);
1944 }
1945 
1946 ////////////////////////////////////////////////////////////////////////////////
1947 /// Return desired Graphics Context ("which" maps directly on gGCList[]).
1948 /// Protected method used by TGWin32TTF.
1949 
1950 GdkGC *TGWin32::GetGC(Int_t which) const
1951 {
1952  if (which >= kMAXGC || which < 0) {
1953  Error("GetGC", "trying to get illegal GdkGC (which = %d)", which);
1954  return 0;
1955  }
1956 
1957  return gGClist[which];
1958 }
1959 
1960 ////////////////////////////////////////////////////////////////////////////////
1961 /// Query the double buffer value for the window wid.
1962 
1964 {
1965  if (!fWindows) return 0;
1966 
1967  gTws = &fWindows[wid];
1968 
1969  if (!gTws->open) {
1970  return -1;
1971  } else {
1972  return gTws->double_buffer;
1973  }
1974 }
1975 
1976 ////////////////////////////////////////////////////////////////////////////////
1977 /// Return position and size of window wid.
1978 /// wid : window identifier
1979 /// x,y : window position (output)
1980 /// w,h : window size (output)
1981 /// if wid < 0 the size of the display is returned
1982 
1983 void TGWin32::GetGeometry(int wid, int &x, int &y, unsigned int &w,
1984  unsigned int &h)
1985 {
1986  if (!fWindows) return;
1987 
1988  if (wid < 0) {
1989  x = 0;
1990  y = 0;
1991 
1992  w = gdk_screen_width();
1993  h = gdk_screen_height();
1994  } else {
1995  int depth;
1996  int width, height;
1997 
1998  gTws = &fWindows[wid];
1999  gdk_window_get_geometry((GdkDrawable *) gTws->window, &x, &y,
2000  &width, &height, &depth);
2001 
2002  gdk_window_get_deskrelative_origin((GdkDrawable *) gTws->window, &x, &y);
2003 
2004  if (width > 0 && height > 0) {
2005  gTws->width = width;
2006  gTws->height = height;
2007  }
2008  w = gTws->width;
2009  h = gTws->height;
2010  }
2011 }
2012 
2013 ////////////////////////////////////////////////////////////////////////////////
2014 /// Return hostname on which the display is opened.
2015 
2016 const char *TGWin32::DisplayName(const char *dpyName)
2017 {
2018  return "localhost"; //return gdk_get_display();
2019 }
2020 
2021 ////////////////////////////////////////////////////////////////////////////////
2022 /// Get maximum number of planes.
2023 
2024 void TGWin32::GetPlanes(int &nplanes)
2025 {
2026  nplanes = gdk_visual_get_best_depth();
2027 }
2028 
2029 ////////////////////////////////////////////////////////////////////////////////
2030 /// Get rgb values for color "index".
2031 
2032 void TGWin32::GetRGB(int index, float &r, float &g, float &b)
2033 {
2034  if (index == 0) {
2035  r = g = b = 1.0;
2036  } else if (index == 1) {
2037  r = g = b = 0.0;
2038  } else {
2039  XColor_t &col = GetColor(index);
2040  r = ((float) col.color.red) / ((float) kBIGGEST_RGB_VALUE);
2041  g = ((float) col.color.green) / ((float) kBIGGEST_RGB_VALUE);
2042  b = ((float) col.color.blue) / ((float) kBIGGEST_RGB_VALUE);
2043  }
2044 }
2045 
2046 ////////////////////////////////////////////////////////////////////////////////
2047 /// Return the size of a character string.
2048 /// iw : text width
2049 /// ih : text height
2050 /// mess : message
2051 
2052 void TGWin32::GetTextExtent(unsigned int &w, unsigned int &h, char *mess)
2053 {
2056  TTF::GetTextExtent(w, h, mess);
2057 }
2058 
2059 ////////////////////////////////////////////////////////////////////////////////
2060 /// Return the X11 window identifier.
2061 /// wid : Workstation identifier (input)
2062 
2064 {
2065  if (!fWindows) return 0;
2066  return (Window_t) fWindows[wid].window;
2067 }
2068 
2069 ////////////////////////////////////////////////////////////////////////////////
2070 /// Move the window wid.
2071 /// wid : GdkWindow identifier.
2072 /// x : x new window position
2073 /// y : y new window position
2074 
2075 void TGWin32::MoveWindow(int wid, int x, int y)
2076 {
2077  if (!fWindows) return;
2078 
2079  gTws = &fWindows[wid];
2080  if (!gTws->open) return;
2081 
2082  gdk_window_move((GdkDrawable *) gTws->window, x, y);
2083 }
2084 
2085 ////////////////////////////////////////////////////////////////////////////////
2086 /// Open a new pixmap.
2087 /// w,h : Width and height of the pixmap.
2088 
2089 Int_t TGWin32::OpenPixmap(unsigned int w, unsigned int h)
2090 {
2091  int wval, hval;
2092  int i, wid;
2093  int ww, hh, depth;
2094  wval = w;
2095  hval = h;
2096 
2097  // Select next free window number
2098  again:
2099  for (wid = 0; wid < fMaxNumberOfWindows; wid++) {
2100  if (!fWindows[wid].open) {
2101  fWindows[wid].open = 1;
2102  gCws = &fWindows[wid];
2103  break;
2104  }
2105  }
2106  if (wid == fMaxNumberOfWindows) {
2107  int newsize = fMaxNumberOfWindows + 10;
2108  fWindows = (XWindow_t *) TStorage::ReAlloc(fWindows,
2109  newsize * sizeof(XWindow_t),
2111  sizeof(XWindow_t));
2112 
2113  for (i = fMaxNumberOfWindows; i < newsize; i++) fWindows[i].open = 0;
2114  fMaxNumberOfWindows = newsize;
2115  goto again;
2116  }
2117 
2118  depth =gdk_visual_get_best_depth();
2119  gCws->window = (GdkPixmap *) gdk_pixmap_new(GDK_ROOT_PARENT(),wval,hval,depth);
2120  gdk_drawable_get_size((GdkDrawable *) gCws->window, &ww, &hh);
2121 
2122  for (i = 0; i < kMAXGC; i++) {
2123  gdk_gc_set_clip_mask((GdkGC *) gGClist[i], (GdkDrawable *)None);
2124  }
2125 
2126  SetColor(gGCpxmp, 0);
2127  gdk_win32_draw_rectangle(gCws->window,(GdkGC *)gGCpxmp, kTRUE,
2128  0, 0, ww, hh);
2129  SetColor(gGCpxmp, 1);
2130 
2131  // Initialise the window structure
2132  gCws->drawing = gCws->window;
2133  gCws->buffer = 0;
2134  gCws->double_buffer = 0;
2135  gCws->ispixmap = 1;
2136  gCws->clip = 0;
2137  gCws->width = wval;
2138  gCws->height = hval;
2139  gCws->new_colors = 0;
2140 
2141  return wid;
2142 }
2143 
2144 ////////////////////////////////////////////////////////////////////////////////
2145 /// Open window and return window number.
2146 /// Return -1 if window initialization fails.
2147 
2149 {
2150  GdkWindowAttr attributes;
2151  unsigned long attr_mask = 0;
2152  int wid;
2153  int xval, yval;
2154  int wval, hval, depth;
2155 
2156  GdkWindow *wind = (GdkWindow *) win;
2157 
2158  gdk_window_get_geometry(wind, &xval, &yval, &wval, &hval, &depth);
2159 
2160  // Select next free window number
2161 
2162  again:
2163  for (wid = 0; wid < fMaxNumberOfWindows; wid++) {
2164  if (!fWindows[wid].open) {
2165  fWindows[wid].open = 1;
2166  fWindows[wid].double_buffer = 0;
2167  gCws = &fWindows[wid];
2168  break;
2169  }
2170  }
2171 
2172  if (wid == fMaxNumberOfWindows) {
2173  int newsize = fMaxNumberOfWindows + 10;
2174  fWindows =
2175  (XWindow_t *) TStorage::ReAlloc(fWindows,
2176  newsize * sizeof(XWindow_t),
2178  sizeof(XWindow_t));
2179 
2180  for (int i = fMaxNumberOfWindows; i < newsize; i++) {
2181  fWindows[i].open = 0;
2182  }
2183 
2184  fMaxNumberOfWindows = newsize;
2185  goto again;
2186  }
2187  // Create window
2188  attributes.wclass = GDK_INPUT_OUTPUT;
2189  attributes.event_mask = 0L; //GDK_ALL_EVENTS_MASK;
2190  attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK |
2191  GDK_PROPERTY_CHANGE_MASK;
2192 // GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK;
2193  if (xval >= 0) {
2194  attributes.x = xval;
2195  } else {
2196  attributes.x = -1.0 * xval;
2197  }
2198 
2199  if (yval >= 0) {
2200  attributes.y = yval;
2201  } else {
2202  attributes.y = -1.0 * yval;
2203  }
2204  attributes.width = wval;
2205  attributes.height = hval;
2206  attributes.colormap = gdk_colormap_get_system();
2207  attributes.visual = gdk_window_get_visual(wind);
2208  attributes.override_redirect = TRUE;
2209 
2210  if ((attributes.y > 0) && (attributes.x > 0)) {
2211  attr_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_COLORMAP |
2212  GDK_WA_WMCLASS | GDK_WA_NOREDIR;
2213  } else {
2214  attr_mask = GDK_WA_COLORMAP | GDK_WA_WMCLASS | GDK_WA_NOREDIR;
2215  }
2216 
2217  if (attributes.visual != NULL) {
2218  attr_mask |= GDK_WA_VISUAL;
2219  }
2220  attributes.window_type = GDK_WINDOW_CHILD;
2221  gCws->window = gdk_window_new(wind, &attributes, attr_mask);
2222  HWND window = (HWND)GDK_DRAWABLE_XID((GdkWindow *)gCws->window);
2223  ::ShowWindow(window, SW_SHOWNORMAL);
2224  ::ShowWindow(window, SW_RESTORE);
2225  ::BringWindowToTop(window);
2226 
2227  if (!fUseSysPointers) {
2228  ::SetClassLong(window, GCL_HCURSOR,
2229  (LONG)GDK_CURSOR_XID(fCursors[kPointer]));
2230  }
2231 
2232  // Initialise the window structure
2233 
2234  gCws->drawing = gCws->window;
2235  gCws->buffer = 0;
2236  gCws->double_buffer = 0;
2237  gCws->ispixmap = 0;
2238  gCws->clip = 0;
2239  gCws->width = wval;
2240  gCws->height = hval;
2241  gCws->new_colors = 0;
2242 
2243  return wid;
2244 }
2245 
2246 ////////////////////////////////////////////////////////////////////////////////
2247 /// Query pointer position.
2248 /// ix : X coordinate of pointer
2249 /// iy : Y coordinate of pointer
2250 /// (both coordinates are relative to the origin of the root window)
2251 
2252 void TGWin32::QueryPointer(int &ix, int &iy)
2253 {
2254  //GdkModifierType mask;
2255  //GdkWindow *retw = gdk_window_get_pointer((GdkWindow *) gCws->window,
2256  // &ix, &iy, &mask);
2257  POINT cpt;
2258  GetCursorPos(&cpt);
2259  ix = cpt.x;
2260  iy = cpt.y;
2261 }
2262 
2263 ////////////////////////////////////////////////////////////////////////////////
2264 /// Remove the pixmap pix.
2265 
2266 void TGWin32::RemovePixmap(GdkDrawable *pix)
2267 {
2268  gdk_pixmap_unref((GdkPixmap *)pix);
2269 }
2270 
2271 ////////////////////////////////////////////////////////////////////////////////
2272 /// Request Locator position.
2273 /// x,y : cursor position at moment of button press (output)
2274 /// ctyp : cursor type (input)
2275 /// ctyp=1 tracking cross
2276 /// ctyp=2 cross-hair
2277 /// ctyp=3 rubber circle
2278 /// ctyp=4 rubber band
2279 /// ctyp=5 rubber rectangle
2280 ///
2281 /// mode : input mode
2282 /// mode=0 request
2283 /// mode=1 sample
2284 ///
2285 /// Request locator:
2286 /// return button number 1 = left is pressed
2287 /// 2 = middle is pressed
2288 /// 3 = right is pressed
2289 /// in sample mode:
2290 /// 11 = left is released
2291 /// 12 = middle is released
2292 /// 13 = right is released
2293 /// -1 = nothing is pressed or released
2294 /// -2 = leave the window
2295 /// else = keycode (keyboard is pressed)
2296 
2298 {
2299  static int xloc = 0;
2300  static int yloc = 0;
2301  static int xlocp = 0;
2302  static int ylocp = 0;
2303  static GdkCursor *cursor = NULL;
2304  Int_t xtmp, ytmp;
2305 
2306  GdkEvent *event;
2307  int button_press;
2308  int radius;
2309 
2310  // Change the cursor shape
2311  if (cursor == NULL) {
2312  if (ctyp > 1) {
2313  gdk_window_set_cursor((GdkWindow *)gCws->window, (GdkCursor *)gNullCursor);
2314  gdk_gc_set_foreground((GdkGC *) gGCecho, &GetColor(0).color);
2315  } else {
2316  if (fUseSysPointers)
2317  cursor = gdk_syscursor_new((ULong_t)IDC_CROSS);
2318  else
2319  cursor = gdk_cursor_new((GdkCursorType)GDK_CROSSHAIR);
2320  gdk_window_set_cursor((GdkWindow *)gCws->window, (GdkCursor *)cursor);
2321  }
2322  }
2323 
2324  // Event loop
2325  button_press = 0;
2326 
2327  // Set max response time to 2 minutes to avoid timeout
2328  // in TGWin32ProxyBase::ForwardCallBack during RequestLocator
2330  while (button_press == 0) {
2331  event = gdk_event_get();
2332 
2333  switch (ctyp) {
2334 
2335  case 1:
2336  break;
2337 
2338  case 2:
2339  gdk_draw_line(gCws->window, gGCecho, xloc, 0, xloc, gCws->height);
2340  gdk_draw_line(gCws->window, gGCecho, 0, yloc, gCws->width, yloc);
2341  break;
2342 
2343  case 3:
2344  radius = (int) TMath::Sqrt((double)((xloc - xlocp) * (xloc - xlocp) +
2345  (yloc - ylocp) * (yloc - ylocp)));
2346 
2348  xlocp - radius, ylocp - radius,
2349  2 * radius, 2 * radius, 0, 23040);
2350  break;
2351 
2352  case 4:
2353  gdk_draw_line(gCws->window, gGCecho, xlocp, ylocp, xloc, yloc);
2354  break;
2355 
2356  case 5:
2358  TMath::Min(xlocp, xloc), TMath::Min(ylocp, yloc),
2359  TMath::Abs(xloc - xlocp), TMath::Abs(yloc - ylocp));
2360  break;
2361 
2362  default:
2363  break;
2364  }
2365 
2366  xloc = event->button.x;
2367  yloc = event->button.y;
2368 
2369  switch (event->type) {
2370 
2371  case GDK_LEAVE_NOTIFY:
2372  if (mode == 0) {
2373  while (1) {
2374  event = gdk_event_get();
2375 
2376  if (event->type == GDK_ENTER_NOTIFY) {
2377  gdk_event_free(event);
2378  break;
2379  }
2380  gdk_event_free(event);
2381  }
2382  } else {
2383  button_press = -2;
2384  }
2385  break;
2386 
2387  case GDK_BUTTON_PRESS:
2388  button_press = event->button.button;
2389  xlocp = event->button.x;
2390  ylocp = event->button.y;
2391  gdk_cursor_unref(cursor);
2392  cursor = 0;
2393  break;
2394 
2395  case GDK_BUTTON_RELEASE:
2396  if (mode == 1) {
2397  button_press = 10 + event->button.button;
2398  xlocp = event->button.x;
2399  ylocp = event->button.y;
2400  }
2401  break;
2402 
2403  case GDK_KEY_PRESS:
2404  if (mode == 1) {
2405  button_press = event->key.keyval;
2406  xlocp = event->button.x;
2407  ylocp = event->button.y;
2408  }
2409  break;
2410 
2411  case GDK_KEY_RELEASE:
2412  if (mode == 1) {
2413  button_press = -1 * (int)(event->key.keyval);
2414  xlocp = event->button.x;
2415  ylocp = event->button.y;
2416  }
2417  break;
2418 
2419  default:
2420  break;
2421  }
2422 
2423  xtmp = event->button.x;
2424  ytmp = event->button.y;
2425 
2426  gdk_event_free(event);
2427 
2428  if (mode == 1) {
2429  if (button_press == 0) {
2430  button_press = -1;
2431  }
2432  break;
2433  }
2434  }
2436 
2437  x = xtmp;
2438  y = ytmp;
2439 
2440  return button_press;
2441 }
2442 
2443 ////////////////////////////////////////////////////////////////////////////////
2444 /// Request a string.
2445 /// x,y : position where text is displayed
2446 /// text : text displayed (input), edited text (output)
2447 ///
2448 /// Request string:
2449 /// text is displayed and can be edited with Emacs-like keybinding
2450 /// return termination code (0 for ESC, 1 for RETURN)
2451 
2453 {
2454  static GdkCursor *cursor = NULL;
2455  static int percent = 0; // bell volume
2456  static GdkWindow *CurWnd;
2457  HWND focuswindow;
2458  GdkEvent *event;
2459  KeySym keysym;
2460  int key = -1;
2461  int len_text = strlen(text);
2462  int nt; // defined length of text
2463  int pt; // cursor position in text
2464 
2465  CurWnd = (GdkWindow *)gCws->window;
2466  // change the cursor shape
2467  if (cursor == NULL) {
2468  if (fUseSysPointers)
2469  cursor = gdk_syscursor_new((ULong_t)IDC_HELP);
2470  else
2471  cursor = gdk_cursor_new((GdkCursorType)GDK_QUESTION_ARROW);
2472  }
2473  if (cursor != 0) {
2474  gdk_window_set_cursor(CurWnd, cursor);
2475  }
2476  for (nt = len_text; nt > 0 && text[nt - 1] == ' '; nt--);
2477 
2478  pt = nt;
2479  focuswindow = ::SetFocus((HWND)GDK_DRAWABLE_XID(CurWnd));
2480 
2481  // Set max response time to 2 minutes to avoid timeout
2482  // in TGWin32ProxyBase::ForwardCallBack during RequestString
2486  do {
2487  char tmp[2];
2488  char keybuf[8];
2489  char nbytes;
2490  UInt_t dx, ddx, h;
2491  int i;
2492 
2493  if (EventsPending()) {
2494  event = gdk_event_get();
2495  } else {
2497  ::SleepEx(10, kTRUE);
2498  continue;
2499  }
2500 
2501  DrawText(x, y, 0.0, 1.0, text, kOpaque);
2502  TTF::GetTextExtent(dx, h, text);
2503  DrawText(x+dx, y, 0.0, 1.0, " ", kOpaque);
2504 
2505  if (pt == 0) {
2506  dx = 0;
2507  } else {
2508  char *stmp = new char[pt+1];
2509  strncpy(stmp, text, pt);
2510  stmp[pt] = '\0';
2511  TTF::GetTextExtent(ddx, h, stmp);
2512  dx = ddx;
2513  delete[] stmp;
2514  }
2515 
2516  if (pt < len_text) {
2517  tmp[0] = text[pt];
2518  tmp[1] = '\0';
2519  DrawText(x+dx, y, 0.0, 1.0, tmp, kOpaque);
2520  } else {
2521  DrawText(x+dx, y, 0.0, 1.0, " ", kOpaque);
2522  }
2523 
2524  if (event != NULL) {
2525  switch (event->type) {
2526  case GDK_BUTTON_PRESS:
2527  case GDK_ENTER_NOTIFY:
2528  focuswindow = ::SetFocus((HWND)GDK_DRAWABLE_XID(CurWnd));
2529  break;
2530 
2531  case GDK_LEAVE_NOTIFY:
2532  ::SetFocus(focuswindow);
2533  break;
2534  case GDK_KEY_PRESS:
2535  nbytes = event->key.length;
2536  for (i = 0; i < nbytes; i++) {
2537  keybuf[i] = event->key.string[i];
2538  }
2539  keysym = event->key.keyval;
2540  switch (keysym) { // map cursor keys
2541  case GDK_BackSpace:
2542  keybuf[0] = 0x08; // backspace
2543  nbytes = 1;
2544  break;
2545  case GDK_Return:
2546  keybuf[0] = 0x0d; // return
2547  nbytes = 1;
2548  break;
2549  case GDK_Delete:
2550  keybuf[0] = 0x7f; // del
2551  nbytes = 1;
2552  break;
2553  case GDK_Escape:
2554  keybuf[0] = 0x1b; // esc
2555  nbytes = 1;
2556  break;
2557  case GDK_Home:
2558  keybuf[0] = 0x01; // home
2559  nbytes = 1;
2560  break;
2561  case GDK_Left:
2562  keybuf[0] = 0x02; // backward
2563  nbytes = 1;
2564  break;
2565  case GDK_Right:
2566  keybuf[0] = 0x06; // forward
2567  nbytes = 1;
2568  break;
2569  case GDK_End:
2570  keybuf[0] = 0x05; // end
2571  nbytes = 1;
2572  break;
2573  }
2574  if (nbytes == 1) {
2575  if (isascii(keybuf[0]) && isprint(keybuf[0])) {
2576  // insert character
2577  if (nt < len_text) {
2578  nt++;
2579  }
2580  for (i = nt - 1; i > pt; i--) {
2581  text[i] = text[i - 1];
2582  }
2583  if (pt < len_text) {
2584  text[pt] = keybuf[0];
2585  pt++;
2586  }
2587  } else {
2588  switch (keybuf[0]) {
2589  // Emacs-like editing keys
2590 
2591  case 0x08: //'\010': // backspace
2592  case 0x7f: //'\177': // delete
2593  // delete backward
2594  if (pt > 0) {
2595  for (i = pt; i < nt; i++) {
2596  text[i - 1] = text[i];
2597  }
2598  text[nt - 1] = ' ';
2599  nt--;
2600  pt--;
2601  }
2602  break;
2603  case 0x01: //'\001': // ^A
2604  // beginning of line
2605  pt = 0;
2606  break;
2607  case 0x02: //'\002': // ^B
2608  // move backward
2609  if (pt > 0) {
2610  pt--;
2611  }
2612  break;
2613  case 0x04: //'\004': // ^D
2614  // delete forward
2615  if (pt > 0) {
2616  for (i = pt; i < nt; i++) {
2617  text[i - 1] = text[i];
2618  }
2619  text[nt - 1] = ' ';
2620  pt--;
2621  }
2622  break;
2623  case 0x05: //'\005': // ^E
2624  // end of line
2625  pt = nt;
2626  break;
2627 
2628  case 0x06: //'\006': // ^F
2629  // move forward
2630  if (pt < nt) {
2631  pt++;
2632  }
2633  break;
2634  case 0x0b: //'\013': // ^K
2635  // delete to end of line
2636  for (i = pt; i < nt; i++)
2637  text[i] = ' ';
2638  nt = pt;
2639  break;
2640  case 0x14: //'\024': // ^T
2641  // transpose
2642  if (pt > 0) {
2643  char c = text[pt];
2644  text[pt] = text[pt - 1];
2645  text[pt - 1] = c;
2646  }
2647  break;
2648  case 0x0A: //'\012': // newline
2649  case 0x0D: //'\015': // return
2650  key = 1;
2651  break;
2652  case 0x1B: //'\033': // escape
2653  key = 0;
2654  break;
2655 
2656  default:
2657  gSystem->Beep();
2658  break;
2659  }
2660  }
2661  }
2662  default:
2663  SetInputFocus((Window_t)gCws->window);
2664  break;
2665  }
2666  gdk_event_free(event);
2667  }
2668  } while (key < 0);
2670  ::SetFocus(focuswindow);
2671  SetInputFocus((Window_t)CurWnd);
2672 
2673  gdk_window_set_cursor(CurWnd, (GdkCursor *)fCursors[kPointer]);
2674  if (cursor != 0) {
2675  gdk_cursor_unref(cursor);
2676  cursor = 0;
2677  }
2678 
2679  return key;
2680 }
2681 
2682 ////////////////////////////////////////////////////////////////////////////////
2683 /// Rescale the window wid.
2684 /// wid : GdkWindow identifier
2685 /// w : Width
2686 /// h : Heigth
2687 
2688 void TGWin32::RescaleWindow(int wid, unsigned int w, unsigned int h)
2689 {
2690  int i;
2691 
2692  if (!fWindows) return;
2693 
2694  gTws = &fWindows[wid];
2695  if (!gTws->open)
2696  return;
2697 
2698  // don't do anything when size did not change
2699  if (gTws->width == w && gTws->height == h)
2700  return;
2701 
2702  gdk_window_resize((GdkWindow *) gTws->window, w, h);
2703 
2704  if (gTws->buffer) {
2705  // don't free and recreate pixmap when new pixmap is smaller
2706  if (gTws->width < w || gTws->height < h) {
2707  gdk_pixmap_unref(gTws->buffer);
2708  gTws->buffer = gdk_pixmap_new(GDK_ROOT_PARENT(), // NULL,
2709  w, h, gdk_visual_get_best_depth());
2710  }
2711  for (i = 0; i < kMAXGC; i++) {
2712  gdk_gc_set_clip_mask(gGClist[i], None);
2713  }
2714  SetColor(gGCpxmp, 0);
2715  gdk_win32_draw_rectangle(gTws->buffer, gGCpxmp, 1, 0, 0, w, h);
2716  SetColor(gGCpxmp, 1);
2717 
2718  if (gTws->double_buffer) gTws->drawing = gTws->buffer;
2719  }
2720  gTws->width = w;
2721  gTws->height = h;
2722 }
2723 
2724 ////////////////////////////////////////////////////////////////////////////////
2725 /// Resize a pixmap.
2726 /// wid : pixmap to be resized
2727 /// w,h : Width and height of the pixmap
2728 
2729 int TGWin32::ResizePixmap(int wid, unsigned int w, unsigned int h)
2730 {
2731  int wval, hval;
2732  int i;
2733  int ww, hh, depth;
2734  wval = w;
2735  hval = h;
2736 
2737  if (!fWindows) return 0;
2738 
2739  gTws = &fWindows[wid];
2740 
2741  // don't do anything when size did not change
2742  // if (gTws->width == wval && gTws->height == hval) return 0;
2743 
2744  // due to round-off errors in TPad::Resize() we might get +/- 1 pixel
2745  // change, in those cases don't resize pixmap
2746  if (gTws->width >= wval - 1 && gTws->width <= wval + 1 &&
2747  gTws->height >= hval - 1 && gTws->height <= hval + 1)
2748  return 0;
2749 
2750  // don't free and recreate pixmap when new pixmap is smaller
2751  if (gTws->width < wval || gTws->height < hval) {
2752  gdk_pixmap_unref((GdkPixmap *)gTws->window);
2753  depth = gdk_visual_get_best_depth();
2754  gTws->window = gdk_pixmap_new(GDK_ROOT_PARENT(), wval, hval, depth);
2755  }
2756 
2757  gdk_drawable_get_size(gTws->window, &ww, &hh);
2758 
2759  for (i = 0; i < kMAXGC; i++) {
2760  gdk_gc_set_clip_mask((GdkGC *) gGClist[i], (GdkDrawable *)None);
2761  }
2762 
2763  SetColor(gGCpxmp, 0);
2764  gdk_win32_draw_rectangle(gTws->window,(GdkGC *)gGCpxmp, kTRUE, 0, 0, ww, hh);
2765  SetColor(gGCpxmp, 1);
2766 
2767  // Initialise the window structure
2768  gTws->drawing = gTws->window;
2769  gTws->width = wval;
2770  gTws->height = hval;
2771  return 1;
2772 }
2773 
2774 ////////////////////////////////////////////////////////////////////////////////
2775 /// Resize the current window if necessary.
2776 
2778 {
2779  int i;
2780  int xval = 0, yval = 0;
2781  GdkWindow *win, *root = NULL;
2782  int wval = 0, hval = 0, depth = 0;
2783 
2784  if (!fWindows) return;
2785 
2786  gTws = &fWindows[wid];
2787 
2788  win = (GdkWindow *) gTws->window;
2789  gdk_window_get_geometry(win, &xval, &yval,
2790  &wval, &hval, &depth);
2791 
2792  // don't do anything when size did not change
2793  if (gTws->width == wval && gTws->height == hval) {
2794  return;
2795  }
2796 
2797  gdk_window_resize((GdkWindow *) gTws->window, wval, hval);
2798 
2799  if (gTws->buffer) {
2800  if (gTws->width < wval || gTws->height < hval) {
2801  gdk_pixmap_unref((GdkPixmap *)gTws->buffer);
2802  depth = gdk_visual_get_best_depth();
2803  gTws->buffer = (GdkPixmap *) gdk_pixmap_new(GDK_ROOT_PARENT(),
2804  wval, hval, depth);
2805  }
2806 
2807  for (i = 0; i < kMAXGC; i++) {
2808  gdk_gc_set_clip_mask((GdkGC *) gGClist[i], (GdkDrawable *)None);
2809  }
2810 
2811  SetColor(gGCpxmp, 0);
2812  gdk_win32_draw_rectangle(gTws->buffer,(GdkGC *)gGCpxmp, kTRUE, 0, 0, wval, hval);
2813 
2814  SetColor(gGCpxmp, 1);
2815 
2816  if (gTws->double_buffer) gTws->drawing = gTws->buffer;
2817  }
2818 
2819  gTws->width = wval;
2820  gTws->height = hval;
2821 }
2822 
2823 ////////////////////////////////////////////////////////////////////////////////
2824 /// Select window to which subsequent output is directed.
2825 
2827 {
2828  int i;
2829  GdkRectangle rect;
2830 
2831  if (!fWindows || wid < 0 || wid >= fMaxNumberOfWindows || !fWindows[wid].open) {
2832  return;
2833  }
2834 
2835  gCws = &fWindows[wid];
2836 
2837  if (gCws->clip && !gCws->ispixmap && !gCws->double_buffer) {
2838  rect.x = gCws->xclip;
2839  rect.y = gCws->yclip;
2840  rect.width = gCws->wclip;
2841  rect.height = gCws->hclip;
2842 
2843  for (i = 0; i < kMAXGC; i++) {
2844  gdk_gc_set_clip_rectangle((GdkGC *) gGClist[i], &rect);
2845  }
2846  } else {
2847  for (i = 0; i < kMAXGC; i++) {
2848  gdk_gc_set_clip_mask((GdkGC *) gGClist[i], (GdkDrawable *)None);
2849  }
2850  }
2851 }
2852 
2853 ////////////////////////////////////////////////////////////////////////////////
2854 /// Set character up vector.
2855 
2857 {
2858  if (chupx == fCharacterUpX && chupy == fCharacterUpY) return;
2859 
2860  if (chupx == 0 && chupy == 0) {
2861  fTextAngle = 0;
2862  } else if (chupx == 0 && chupy == 1) {
2863  fTextAngle = 0;
2864  } else if (chupx == -1 && chupy == 0) {
2865  fTextAngle = 90;
2866  } else if (chupx == 0 && chupy == -1) {
2867  fTextAngle = 180;
2868  } else if (chupx == 1 && chupy == 0) {
2869  fTextAngle = 270;
2870  } else {
2871  fTextAngle =
2872  ((TMath::
2873  ACos(chupx / TMath::Sqrt(chupx * chupx + chupy * chupy)) *
2874  180.) / 3.14159) - 90;
2875  if (chupy < 0) fTextAngle = 180 - fTextAngle;
2876  if (TMath::Abs(fTextAngle) <= 0.01) fTextAngle = 0;
2877  }
2878  fCharacterUpX = chupx;
2879  fCharacterUpY = chupy;
2880 }
2881 
2882 ////////////////////////////////////////////////////////////////////////////////
2883 /// Turn off the clipping for the window wid.
2884 
2885 void TGWin32::SetClipOFF(int wid)
2886 {
2887  if (!fWindows) return;
2888 
2889  gTws = &fWindows[wid];
2890  gTws->clip = 0;
2891 
2892  for (int i = 0; i < kMAXGC; i++) {
2893  gdk_gc_set_clip_mask((GdkGC *) gGClist[i], (GdkDrawable *)None);
2894  }
2895 }
2896 
2897 ////////////////////////////////////////////////////////////////////////////////
2898 /// Set clipping region for the window wid.
2899 /// wid : GdkWindow indentifier
2900 /// x,y : origin of clipping rectangle
2901 /// w,h : size of clipping rectangle;
2902 
2903 void TGWin32::SetClipRegion(int wid, int x, int y, unsigned int w,
2904  unsigned int h)
2905 {
2906  if (!fWindows) return;
2907 
2908  gTws = &fWindows[wid];
2909  gTws->xclip = x;
2910  gTws->yclip = y;
2911  gTws->wclip = w;
2912  gTws->hclip = h;
2913  gTws->clip = 1;
2914  GdkRectangle rect;
2915 
2916  if (gTws->clip && !gTws->ispixmap && !gTws->double_buffer) {
2917  rect.x = gTws->xclip;
2918  rect.y = gTws->yclip;
2919  rect.width = gTws->wclip;
2920  rect.height = gTws->hclip;
2921 
2922  for (int i = 0; i < kMAXGC; i++) {
2923  gdk_gc_set_clip_rectangle((GdkGC *)gGClist[i], &rect);
2924  }
2925  }
2926 }
2927 
2928 ////////////////////////////////////////////////////////////////////////////////
2929 /// Return pixel value associated to specified ROOT color number.
2930 
2932 {
2933  TColor *color = gROOT->GetColor(ci);
2934  if (color)
2935  SetRGB(ci, color->GetRed(), color->GetGreen(), color->GetBlue());
2936  XColor_t &col = GetColor(ci);
2937  return col.color.pixel;
2938 }
2939 
2940 ////////////////////////////////////////////////////////////////////////////////
2941 /// Set the foreground color in GdkGC.
2942 
2943 void TGWin32::SetColor(GdkGC *gc, int ci)
2944 {
2945  GdkGCValues gcvals;
2946  GdkColor color;
2947 
2948  if (ci<=0) ci = 10; //white
2949 
2950  TColor *clr = gROOT->GetColor(ci);
2951  if (clr)
2952  SetRGB(ci, clr->GetRed(), clr->GetGreen(), clr->GetBlue());
2953 
2954  XColor_t &col = GetColor(ci);
2955  if (fColormap && !col.fDefined) {
2956  col = GetColor(0);
2957  } else if (!fColormap && (ci < 0 || ci > 1)) {
2958  col = GetColor(0);
2959  }
2960 
2961  if (fDrawMode == kXor) {
2962  gdk_gc_get_values(gc, &gcvals);
2963 
2964  color.pixel = col.color.pixel ^ gcvals.background.pixel;
2965  color.red = GetRValue(color.pixel);
2966  color.green = GetGValue(color.pixel);
2967  color.blue = GetBValue(color.pixel);
2968  gdk_gc_set_foreground(gc, &color);
2969 
2970  } else {
2971  gdk_gc_set_foreground(gc, &col.color);
2972 
2973  // make sure that foreground and background are different
2974  gdk_gc_get_values(gc, &gcvals);
2975 
2976  if (gcvals.foreground.pixel != gcvals.background.pixel) {
2977  gdk_gc_set_background(gc, &GetColor(!ci).color);
2978  }
2979  }
2980 }
2981 
2982 ////////////////////////////////////////////////////////////////////////////////
2983 /// Set the cursor.
2984 
2985 void TGWin32::SetCursor(int wid, ECursor cursor)
2986 {
2987  if (!fWindows) return;
2988 
2989  gTws = &fWindows[wid];
2990  gdk_window_set_cursor((GdkWindow *)gTws->window, (GdkCursor *)fCursors[cursor]);
2991 }
2992 
2993 ////////////////////////////////////////////////////////////////////////////////
2994 /// Set the specified cursor.
2995 
2997 {
2998  if (!id) return;
2999 
3000  static GdkWindow *lid = 0;
3001  static GdkCursor *lcur = 0;
3002 
3003  if ((lid == (GdkWindow *)id) && (lcur==(GdkCursor *)curid)) return;
3004  lid = (GdkWindow *)id;
3005  lcur = (GdkCursor *)curid;
3006 
3007  gdk_window_set_cursor((GdkWindow *) id, (GdkCursor *)curid);
3008 }
3009 
3010 ////////////////////////////////////////////////////////////////////////////////
3011 /// Set the double buffer on/off on window wid.
3012 /// wid : GdkWindow identifier.
3013 /// 999 means all the opened windows.
3014 /// mode : 1 double buffer is on
3015 /// 0 double buffer is off
3016 
3017 void TGWin32::SetDoubleBuffer(int wid, int mode)
3018 {
3019  if (!fWindows) return;
3020 
3021  if (wid == 999) {
3022  for (int i = 0; i < fMaxNumberOfWindows; i++) {
3023  gTws = &fWindows[i];
3024  if (gTws->open) {
3025  switch (mode) {
3026  case 1:
3028  break;
3029  default:
3031  break;
3032  }
3033  }
3034  }
3035  } else {
3036  gTws = &fWindows[wid];
3037  if (!gTws->open) return;
3038 
3039  switch (mode) {
3040  case 1:
3042  return;
3043  default:
3045  return;
3046  }
3047  }
3048 }
3049 
3050 ////////////////////////////////////////////////////////////////////////////////
3051 /// Turn double buffer mode off.
3052 
3054 {
3055  if (!gTws->double_buffer) return;
3056  gTws->double_buffer = 0;
3057  gTws->drawing = gTws->window;
3058 }
3059 
3060 ////////////////////////////////////////////////////////////////////////////////
3061 /// Turn double buffer mode on.
3062 
3064 {
3065  if (!fWindows || gTws->double_buffer || gTws->ispixmap) return;
3066 
3067  if (!gTws->buffer) {
3068  gTws->buffer = gdk_pixmap_new(GDK_ROOT_PARENT(), //NULL,
3069  gTws->width, gTws->height,
3070  gdk_visual_get_best_depth());
3071  SetColor(gGCpxmp, 0);
3072  gdk_win32_draw_rectangle(gTws->buffer, gGCpxmp, 1, 0, 0, gTws->width,
3073  gTws->height);
3074  SetColor(gGCpxmp, 1);
3075  }
3076  for (int i = 0; i < kMAXGC; i++) {
3077  gdk_gc_set_clip_mask(gGClist[i], None);
3078  }
3079  gTws->double_buffer = 1;
3080  gTws->drawing = gTws->buffer;
3081 }
3082 
3083 ////////////////////////////////////////////////////////////////////////////////
3084 /// Set the drawing mode.
3085 /// mode : drawing mode
3086 /// mode=1 copy
3087 /// mode=2 xor
3088 /// mode=3 invert
3089 /// mode=4 set the suitable mode for cursor echo according to
3090 /// the vendor
3091 
3093 {
3094  int i;
3095 
3096  switch (mode) {
3097  case kCopy:
3098  for (i = 0; i < kMAXGC; i++) {
3099  gdk_gc_set_function(gGClist[i], GDK_COPY);
3100  }
3101  break;
3102 
3103  case kXor:
3104  for (i = 0; i < kMAXGC; i++) {
3105  gdk_gc_set_function(gGClist[i], GDK_XOR);
3106  }
3107  break;
3108 
3109  case kInvert:
3110  for (i = 0; i < kMAXGC; i++) {
3111  gdk_gc_set_function(gGClist[i], GDK_INVERT);
3112  }
3113  break;
3114  }
3115  fDrawMode = mode;
3116 }
3117 
3118 ////////////////////////////////////////////////////////////////////////////////
3119 /// Set color index for fill areas.
3120 
3122 {
3123  Int_t indx = Int_t(cindex);
3124 
3125  if (!gStyle->GetFillColor() && cindex > 1) {
3126  indx = 0;
3127  }
3128 
3129  fFillColor = indx;
3131 }
3132 
3133 ////////////////////////////////////////////////////////////////////////////////
3134 ///
3135 
3137 {
3138  if (fFillColor >= 0) {
3140  }
3141 
3142  // invalidate fill pattern
3143  if (gFillPattern != NULL) {
3144  gdk_pixmap_unref(gFillPattern);
3145  gFillPattern = NULL;
3146  }
3148 }
3149 
3150 ////////////////////////////////////////////////////////////////////////////////
3151 /// Set fill area style.
3152 /// fstyle : compound fill area interior style
3153 /// fstyle = 1000*interiorstyle + styleindex
3154 
3156 {
3157  if (fFillStyle==fstyle) return;
3158 
3159  fFillStyle = fstyle;
3161 }
3162 
3163 ////////////////////////////////////////////////////////////////////////////////
3164 /// Set fill area style index.
3165 
3167 {
3168  static int current_fasi = 0;
3169 
3170  Int_t style = fFillStyle / 1000;
3171  Int_t fasi = fFillStyle % 1000;
3172 
3173  switch (style) {
3174 
3175  case 1: // solid
3176  gFillHollow = 0;
3177  gdk_gc_set_fill(gGCfill, GDK_SOLID);
3178  break;
3179 
3180  case 2: // pattern
3181  gFillHollow = 1;
3182  break;
3183 
3184  case 3: // hatch
3185  gFillHollow = 0;
3186  gdk_gc_set_fill(gGCfill, GDK_STIPPLED);
3187 
3188  if (fasi != current_fasi) {
3189  if (gFillPattern != NULL) {
3190  gdk_pixmap_unref(gFillPattern);
3191  gFillPattern = NULL;
3192  }
3193  int stn = (fasi >= 1 && fasi <=25) ? fasi : 2;
3194  gFillPattern = gdk_bitmap_create_from_data(GDK_ROOT_PARENT(),
3195  (const char *)gStipples[stn], 16, 16);
3196  gdk_gc_set_stipple(gGCfill, gFillPattern);
3197  current_fasi = fasi;
3198  }
3199  break;
3200 
3201  default:
3202  gFillHollow = 1;
3203  }
3204 
3206 }
3207 
3208 ////////////////////////////////////////////////////////////////////////////////
3209 /// Set input on or off.
3210 
3211 void TGWin32::SetInput(int inp)
3212 {
3213  EnableWindow((HWND) GDK_DRAWABLE_XID(gCws->window), inp);
3214 }
3215 
3216 ////////////////////////////////////////////////////////////////////////////////
3217 /// Set color index for lines.
3218 
3220 {
3221  if ((cindex < 0) || (cindex==fLineColor)) return;
3222 
3223  fLineColor = cindex;
3225 }
3226 
3227 ////////////////////////////////////////////////////////////////////////////////
3228 ///
3229 
3231 {
3235 }
3236 
3237 ////////////////////////////////////////////////////////////////////////////////
3238 /// Set line type.
3239 /// n : length of dash list
3240 /// dash(n) : dash segment lengths
3241 ///
3242 /// if n <= 0 use solid lines
3243 /// if n > 0 use dashed lines described by DASH(N)
3244 /// e.g. N=4,DASH=(6,3,1,3) gives a dashed-dotted line with dash length 6
3245 /// and a gap of 7 between dashes
3246 
3247 void TGWin32::SetLineType(int n, int *dash)
3248 {
3249  if (n <= 0) {
3250  gLineStyle = GDK_LINE_SOLID;
3251  gdk_gc_set_line_attributes(gGCline, gLineWidth,
3252  (GdkLineStyle)gLineStyle,
3253  (GdkCapStyle) gCapStyle,
3254  (GdkJoinStyle) gJoinStyle);
3255  } else {
3256  int i;
3257  gDashSize = TMath::Min((int)sizeof(gDashList),n);
3258  gDashLength = 0;
3259  for (i = 0; i < gDashSize; i++) {
3260  gDashList[i] = dash[i];
3261  gDashLength += gDashList[i];
3262  }
3263  gDashOffset = 0;
3264  gLineStyle = GDK_LINE_ON_OFF_DASH;
3265  if (gLineWidth == 0) gLineWidth =1;
3266  gdk_gc_set_line_attributes(gGCdash, gLineWidth,
3267  (GdkLineStyle) gLineStyle,
3268  (GdkCapStyle) gCapStyle,
3269  (GdkJoinStyle) gJoinStyle);
3270  }
3271  fPenModified = kFALSE;
3272 }
3273 
3274 ////////////////////////////////////////////////////////////////////////////////
3275 /// Set line style.
3276 
3278 {
3279  if (fLineStyle == lstyle) return;
3280 
3281  fLineStyle = lstyle;
3282  fPenModified = kTRUE;
3283 }
3284 
3285 ////////////////////////////////////////////////////////////////////////////////
3286 /// Update line style
3287 
3289 {
3290  static Int_t dashed[2] = { 3, 3 };
3291  static Int_t dotted[2] = { 1, 2 };
3292  static Int_t dasheddotted[4] = { 3, 4, 1, 4 };
3293 
3294  if (fLineStyle <= 1) {
3295  SetLineType(0, 0);
3296  } else if (fLineStyle == 2) {
3297  SetLineType(2, dashed);
3298  } else if (fLineStyle == 3) {
3299  SetLineType(2, dotted);
3300  } else if (fLineStyle == 4) {
3301  SetLineType(4, dasheddotted);
3302  } else {
3304  TObjArray *tokens = st.Tokenize(" ");
3305  Int_t nt;
3306  nt = tokens->GetEntries();
3307  Int_t *linestyle = new Int_t[nt];
3308  for (Int_t j = 0; j<nt; j++) {
3309  Int_t it;
3310  sscanf(((TObjString*)tokens->At(j))->GetName(), "%d", &it);
3311  linestyle[j] = (Int_t)(it/4);
3312  }
3313  SetLineType(nt,linestyle);
3314  delete [] linestyle;
3315  delete tokens;
3316  }
3317  fPenModified = kFALSE;
3318 }
3319 
3320 ////////////////////////////////////////////////////////////////////////////////
3321 /// Set line width.
3322 /// width : line width in pixels
3323 
3325 {
3326  if (fLineWidth == width) return;
3327  fLineWidth = width;
3328 
3329  if (width == 1 && gLineStyle == GDK_LINE_SOLID) gLineWidth = 0;
3330  else gLineWidth = width;
3331 
3332  fPenModified = kTRUE;
3333 }
3334 
3335 ////////////////////////////////////////////////////////////////////////////////
3336 /// Set color index for markers.
3337 
3339 {
3340  if ((cindex<0) || (cindex==fMarkerColor)) return;
3341  fMarkerColor = cindex;
3343 }
3344 
3345 ////////////////////////////////////////////////////////////////////////////////
3346 ///
3347 
3349 {
3352 }
3353 
3354 ////////////////////////////////////////////////////////////////////////////////
3355 /// Set marker size index.
3356 /// msize : marker scale factor
3357 
3359 {
3360  if ((msize==fMarkerSize) || (msize<0)) return;
3361 
3362  fMarkerSize = msize;
3364 }
3365 
3366 ////////////////////////////////////////////////////////////////////////////////
3367 /// Set marker type.
3368 /// type : marker type
3369 /// n : length of marker description
3370 /// xy : list of points describing marker shape
3371 ///
3372 /// if n == 0 marker is a single point
3373 /// if TYPE == 0 marker is hollow circle of diameter N
3374 /// if TYPE == 1 marker is filled circle of diameter N
3375 /// if TYPE == 2 marker is a hollow polygon describe by line XY
3376 /// if TYPE == 3 marker is a filled polygon describe by line XY
3377 /// if TYPE == 4 marker is described by segmented line XY
3378 /// e.g. TYPE=4,N=4,XY=(-3,0,3,0,0,-3,0,3) sets a plus shape of 7x7 pixels
3379 
3380 void TGWin32::SetMarkerType(int type, int n, GdkPoint * xy)
3381 {
3382  gMarker.type = type;
3383  gMarker.n = n < kMAXMK ? n : kMAXMK;
3384  if (gMarker.type >= 2) {
3385  for (int i = 0; i < gMarker.n; i++) {
3386  gMarker.xy[i] = xy[i];
3387  }
3388  }
3389 }
3390 
3391 ////////////////////////////////////////////////////////////////////////////////
3392 /// Set marker style.
3393 
3395 {
3396  if (fMarkerStyle == markerstyle) return;
3397  fMarkerStyle = TMath::Abs(markerstyle);
3399 }
3400 
3401 ////////////////////////////////////////////////////////////////////////////////
3402 ///
3403 
3405 {
3408 
3409  // The fast pixel markers need to be treated separately
3410  if (markerstyle == 1 || markerstyle == 6 || markerstyle == 7) {
3411  gdk_gc_set_line_attributes(gGCmark, 0, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
3412  } else {
3413  gdk_gc_set_line_attributes(gGCmark, gMarkerLineWidth,
3414  (GdkLineStyle) gMarkerLineStyle,
3415  (GdkCapStyle) gMarkerCapStyle,
3416  (GdkJoinStyle) gMarkerJoinStyle);
3417  }
3418 
3419  static GdkPoint shape[30];
3420 
3421  Float_t MarkerSizeReduced = fMarkerSize - TMath::Floor(gMarkerLineWidth/2.)/4.;
3422  Int_t im = Int_t(4 * MarkerSizeReduced + 0.5);
3423 
3424  if (markerstyle == 2) {
3425  // + shaped marker
3426  shape[0].x = -im;
3427  shape[0].y = 0;
3428  shape[1].x = im;
3429  shape[1].y = 0;
3430  shape[2].x = 0;
3431  shape[2].y = -im;
3432  shape[3].x = 0;
3433  shape[3].y = im;
3434  SetMarkerType(4, 4, shape);
3435  } else if (markerstyle == 3 || markerstyle == 31) {
3436  // * shaped marker
3437  shape[0].x = -im;
3438  shape[0].y = 0;
3439  shape[1].x = im;
3440  shape[1].y = 0;
3441  shape[2].x = 0;
3442  shape[2].y = -im;
3443  shape[3].x = 0;
3444  shape[3].y = im;
3445  im = Int_t(0.707 * Float_t(im) + 0.5);
3446  shape[4].x = -im;
3447  shape[4].y = -im;
3448  shape[5].x = im;
3449  shape[5].y = im;
3450  shape[6].x = -im;
3451  shape[6].y = im;
3452  shape[7].x = im;
3453  shape[7].y = -im;
3454  SetMarkerType(4, 8, shape);
3455  } else if (markerstyle == 4 || markerstyle == 24) {
3456  // O shaped marker
3457  SetMarkerType(0, im * 2, shape);
3458  } else if (markerstyle == 5) {
3459  // X shaped marker
3460  im = Int_t(0.707 * Float_t(im) + 0.5);
3461  shape[0].x = -im;
3462  shape[0].y = -im;
3463  shape[1].x = im;
3464  shape[1].y = im;
3465  shape[2].x = -im;
3466  shape[2].y = im;
3467  shape[3].x = im;
3468  shape[3].y = -im;
3469  SetMarkerType(4, 4, shape);
3470  } else if (markerstyle == 6) {
3471  // + shaped marker (with 1 pixel)
3472  shape[0].x = -1;
3473  shape[0].y = 0;
3474  shape[1].x = 1;
3475  shape[1].y = 0;
3476  shape[2].x = 0;
3477  shape[2].y = -1;
3478  shape[3].x = 0;
3479  shape[3].y = 1;
3480  SetMarkerType(4, 4, shape);
3481  } else if (markerstyle == 7) {
3482  // . shaped marker (with 9 pixel)
3483  shape[0].x = -1;
3484  shape[0].y = 1;
3485  shape[1].x = 1;
3486  shape[1].y = 1;
3487  shape[2].x = -1;
3488  shape[2].y = 0;
3489  shape[3].x = 1;
3490  shape[3].y = 0;
3491  shape[4].x = -1;
3492  shape[4].y = -1;
3493  shape[5].x = 1;
3494  shape[5].y = -1;
3495  SetMarkerType(4, 6, shape);
3496  } else if (markerstyle == 8 || markerstyle == 20) {
3497  // O shaped marker (filled)
3498  SetMarkerType(1, im * 2, shape);
3499  } else if (markerstyle == 21) {
3500  // full square
3501  shape[0].x = -im;
3502  shape[0].y = -im;
3503  shape[1].x = im;
3504  shape[1].y = -im;
3505  shape[2].x = im;
3506  shape[2].y = im;
3507  shape[3].x = -im;
3508  shape[3].y = im;
3509  shape[4].x = -im;
3510  shape[4].y = -im;
3511  SetMarkerType(3, 5, shape);
3512  } else if (markerstyle == 22) {
3513  // full triangle up
3514  shape[0].x = -im;
3515  shape[0].y = im;
3516  shape[1].x = im;
3517  shape[1].y = im;
3518  shape[2].x = 0;
3519  shape[2].y = -im;
3520  shape[3].x = -im;
3521  shape[3].y = im;
3522  SetMarkerType(3, 4, shape);
3523  } else if (markerstyle == 23) {
3524  // full triangle down
3525  shape[0].x = 0;
3526  shape[0].y = im;
3527  shape[1].x = im;
3528  shape[1].y = -im;
3529  shape[2].x = -im;
3530  shape[2].y = -im;
3531  shape[3].x = 0;
3532  shape[3].y = im;
3533  SetMarkerType(3, 4, shape);
3534  } else if (markerstyle == 25) {
3535  // open square
3536  shape[0].x = -im;
3537  shape[0].y = -im;
3538  shape[1].x = im;
3539  shape[1].y = -im;
3540  shape[2].x = im;
3541  shape[2].y = im;
3542  shape[3].x = -im;
3543  shape[3].y = im;
3544  shape[4].x = -im;
3545  shape[4].y = -im;
3546  SetMarkerType(2, 5, shape);
3547  } else if (markerstyle == 26) {
3548  // open triangle up
3549  shape[0].x = -im;
3550  shape[0].y = im;
3551  shape[1].x = im;
3552  shape[1].y = im;
3553  shape[2].x = 0;
3554  shape[2].y = -im;
3555  shape[3].x = -im;
3556  shape[3].y = im;
3557  SetMarkerType(2, 4, shape);
3558  } else if (markerstyle == 27) {
3559  // open losange
3560  Int_t imx = Int_t(2.66 * MarkerSizeReduced + 0.5);
3561  shape[0].x = -imx;
3562  shape[0].y = 0;
3563  shape[1].x = 0;
3564  shape[1].y = -im;
3565  shape[2].x = imx;
3566  shape[2].y = 0;
3567  shape[3].x = 0;
3568  shape[3].y = im;
3569  shape[4].x = -imx;
3570  shape[4].y = 0;
3571  SetMarkerType(2, 5, shape);
3572  } else if (markerstyle == 28) {
3573  // open cross
3574  Int_t imx = Int_t(1.33 * MarkerSizeReduced + 0.5);
3575  shape[0].x = -im;
3576  shape[0].y = -imx;
3577  shape[1].x = -imx;
3578  shape[1].y = -imx;
3579  shape[2].x = -imx;
3580  shape[2].y = -im;
3581  shape[3].x = imx;
3582  shape[3].y = -im;
3583  shape[4].x = imx;
3584  shape[4].y = -imx;
3585  shape[5].x = im;
3586  shape[5].y = -imx;
3587  shape[6].x = im;
3588  shape[6].y = imx;
3589  shape[7].x = imx;
3590  shape[7].y = imx;
3591  shape[8].x = imx;
3592  shape[8].y = im;
3593  shape[9].x = -imx;
3594  shape[9].y = im;
3595  shape[10].x = -imx;
3596  shape[10].y = imx;
3597  shape[11].x = -im;
3598  shape[11].y = imx;
3599  shape[12].x = -im;
3600  shape[12].y = -imx;
3601  SetMarkerType(2, 13, shape);
3602  } else if (markerstyle == 29) {
3603  // full star pentagone
3604  Int_t im1 = Int_t(0.66 * MarkerSizeReduced + 0.5);
3605  Int_t im2 = Int_t(2.00 * MarkerSizeReduced + 0.5);
3606  Int_t im3 = Int_t(2.66 * MarkerSizeReduced + 0.5);
3607  Int_t im4 = Int_t(1.33 * MarkerSizeReduced + 0.5);
3608  shape[0].x = -im;
3609  shape[0].y = im4;
3610  shape[1].x = -im2;
3611  shape[1].y = -im1;
3612  shape[2].x = -im3;
3613  shape[2].y = -im;
3614  shape[3].x = 0;
3615  shape[3].y = -im2;
3616  shape[4].x = im3;
3617  shape[4].y = -im;
3618  shape[5].x = im2;
3619  shape[5].y = -im1;
3620  shape[6].x = im;
3621  shape[6].y = im4;
3622  shape[7].x = im4;
3623  shape[7].y = im4;
3624  shape[8].x = 0;
3625  shape[8].y = im;
3626  shape[9].x = -im4;
3627  shape[9].y = im4;
3628  shape[10].x = -im;
3629  shape[10].y = im4;
3630  SetMarkerType(3, 11, shape);
3631  } else if (markerstyle == 30) {
3632  // open star pentagone
3633  Int_t im1 = Int_t(0.66 * MarkerSizeReduced + 0.5);
3634  Int_t im2 = Int_t(2.00 * MarkerSizeReduced + 0.5);
3635  Int_t im3 = Int_t(2.66 * MarkerSizeReduced + 0.5);
3636  Int_t im4 = Int_t(1.33 * MarkerSizeReduced + 0.5);
3637  shape[0].x = -im;
3638  shape[0].y = im4;
3639  shape[1].x = -im2;
3640  shape[1].y = -im1;
3641  shape[2].x = -im3;
3642  shape[2].y = -im;
3643  shape[3].x = 0;
3644  shape[3].y = -im2;
3645  shape[4].x = im3;
3646  shape[4].y = -im;
3647  shape[5].x = im2;
3648  shape[5].y = -im1;
3649  shape[6].x = im;
3650  shape[6].y = im4;
3651  shape[7].x = im4;
3652  shape[7].y = im4;
3653  shape[8].x = 0;
3654  shape[8].y = im;
3655  shape[9].x = -im4;
3656  shape[9].y = im4;
3657  shape[10].x = -im;
3658  shape[10].y = im4;
3659  SetMarkerType(2, 11, shape);
3660  } else if (markerstyle == 32) {
3661  // open triangle down
3662  shape[0].x = 0; shape[0].y = im;
3663  shape[1].x = im; shape[1].y = -im;
3664  shape[2].x = -im; shape[2].y = -im;
3665  shape[3].x = 0; shape[3].y = im;
3666  SetMarkerType(2,4,shape);
3667  } else if (markerstyle == 33) {
3668  // full losange
3669  Int_t imx = Int_t(2.66*MarkerSizeReduced + 0.5);
3670  shape[0].x =-imx; shape[0].y = 0;
3671  shape[1].x = 0; shape[1].y = -im;
3672  shape[2].x = imx; shape[2].y = 0;
3673  shape[3].x = 0; shape[3].y = im;
3674  shape[4].x =-imx; shape[4].y = 0;
3675  SetMarkerType(3,5,shape);
3676  } else if (markerstyle == 34) {
3677  // full cross
3678  Int_t imx = Int_t(1.33*MarkerSizeReduced + 0.5);
3679  shape[0].x = -im; shape[0].y =-imx;
3680  shape[1].x =-imx; shape[1].y =-imx;
3681  shape[2].x =-imx; shape[2].y = -im;
3682  shape[3].x = imx; shape[3].y = -im;
3683  shape[4].x = imx; shape[4].y =-imx;
3684  shape[5].x = im; shape[5].y =-imx;
3685  shape[6].x = im; shape[6].y = imx;
3686  shape[7].x = imx; shape[7].y = imx;
3687  shape[8].x = imx; shape[8].y = im;
3688  shape[9].x =-imx; shape[9].y = im;
3689  shape[10].x=-imx; shape[10].y= imx;
3690  shape[11].x= -im; shape[11].y= imx;
3691  shape[12].x= -im; shape[12].y=-imx;
3692  SetMarkerType(3,13,shape);
3693  } else if (markerstyle == 35) {
3694  // square with diagonal cross
3695  shape[0].x = -im; shape[0].y = -im;
3696  shape[1].x = im; shape[1].y = -im;
3697  shape[2].x = im; shape[2].y = im;
3698  shape[3].x = -im; shape[3].y = im;
3699  shape[4].x = -im; shape[4].y = -im;
3700  shape[5].x = im; shape[5].y = im;
3701  shape[6].x = -im; shape[6].y = im;
3702  shape[7].x = im; shape[7].y = -im;
3703  SetMarkerType(2,8,shape);
3704  } else if (markerstyle == 36) {
3705  // diamond with cross
3706  shape[0].x =-im; shape[0].y = 0;
3707  shape[1].x = 0; shape[1].y = -im;
3708  shape[2].x = im; shape[2].y = 0;
3709  shape[3].x = 0; shape[3].y = im;
3710  shape[4].x =-im; shape[4].y = 0;
3711  shape[5].x = im; shape[5].y = 0;
3712  shape[6].x = 0; shape[6].y = im;
3713  shape[7].x = 0; shape[7].y =-im;
3714  SetMarkerType(2,8,shape);
3715  } else if (markerstyle == 37) {
3716  // open three triangles
3717  Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5);
3718  shape[0].x = 0; shape[0].y = 0;
3719  shape[1].x =-im2; shape[1].y = im;
3720  shape[2].x = -im; shape[2].y = 0;
3721  shape[3].x = 0; shape[3].y = 0;
3722  shape[4].x =-im2; shape[4].y = -im;
3723  shape[5].x = im2; shape[5].y = -im;
3724  shape[6].x = 0; shape[6].y = 0;
3725  shape[7].x = im; shape[7].y = 0;
3726  shape[8].x = im2; shape[8].y = im;
3727  shape[9].x = 0; shape[9].y = 0;
3728  SetMarkerType(2,10,shape);
3729  } else if (markerstyle == 38) {
3730  // + shaped marker with octagon
3731  Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5);
3732  shape[0].x = -im; shape[0].y = 0;
3733  shape[1].x = -im; shape[1].y =-im2;
3734  shape[2].x =-im2; shape[2].y =-im;
3735  shape[3].x = im2; shape[3].y = -im;
3736  shape[4].x = im; shape[4].y =-im2;
3737  shape[5].x = im; shape[5].y = im2;
3738  shape[6].x = im2; shape[6].y = im;
3739  shape[7].x =-im2; shape[7].y = im;
3740  shape[8].x = -im; shape[8].y = im2;
3741  shape[9].x = -im; shape[9].y = 0;
3742  shape[10].x = im; shape[10].y = 0;
3743  shape[11].x = 0; shape[11].y = 0;
3744  shape[12].x = 0; shape[12].y = -im;
3745  shape[13].x = 0; shape[13].y = im;
3746  shape[14].x = 0; shape[14].y = 0;
3747  SetMarkerType(2,15,shape);
3748  } else if (markerstyle == 39) {
3749  // filled three triangles
3750  Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5);
3751  shape[0].x = 0; shape[0].y = 0;
3752  shape[1].x =-im2; shape[1].y = im;
3753  shape[2].x = -im; shape[2].y = 0;
3754  shape[3].x = 0; shape[3].y = 0;
3755  shape[4].x =-im2; shape[4].y = -im;
3756  shape[5].x = im2; shape[5].y = -im;
3757  shape[6].x = 0; shape[6].y = 0;
3758  shape[7].x = im; shape[7].y = 0;
3759  shape[8].x = im2; shape[8].y = im;
3760  SetMarkerType(3,9,shape);
3761  } else if (markerstyle == 40) {
3762  // four open triangles X
3763  Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5);
3764  shape[0].x = 0; shape[0].y = 0;
3765  shape[1].x = im2; shape[1].y = im;
3766  shape[2].x = im; shape[2].y = im2;
3767  shape[3].x = 0; shape[3].y = 0;
3768  shape[4].x = im; shape[4].y = -im2;
3769  shape[5].x = im2; shape[5].y = -im;
3770  shape[6].x = 0; shape[6].y = 0;
3771  shape[7].x = -im2; shape[7].y = -im;
3772  shape[8].x = -im; shape[8].y = -im2;
3773  shape[9].x = 0; shape[9].y = 0;
3774  shape[10].x = -im; shape[10].y = im2;
3775  shape[11].x = -im2; shape[11].y = im;
3776  shape[12].x = 0; shape[12].y = 0;
3777  SetMarkerType(2,13,shape);
3778  } else if (markerstyle == 41) {
3779  // four filled triangles X
3780  Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5);
3781  shape[0].x = 0; shape[0].y = 0;
3782  shape[1].x = im2; shape[1].y = im;
3783  shape[2].x = im; shape[2].y = im2;
3784  shape[3].x = 0; shape[3].y = 0;
3785  shape[4].x = im; shape[4].y = -im2;
3786  shape[5].x = im2; shape[5].y = -im;
3787  shape[6].x = 0; shape[6].y = 0;
3788  shape[7].x = -im2; shape[7].y = -im;
3789  shape[8].x = -im; shape[8].y = -im2;
3790  shape[9].x = 0; shape[9].y = 0;
3791  shape[10].x = -im; shape[10].y = im2;
3792  shape[11].x = -im2; shape[11].y = im;
3793  shape[12].x = 0; shape[12].y = 0;
3794  SetMarkerType(3,13,shape);
3795  } else if (markerstyle == 42) {
3796  // open double diamonds
3797  Int_t imx = Int_t(MarkerSizeReduced + 0.5);
3798  shape[0].x= 0; shape[0].y= im;
3799  shape[1].x= -imx; shape[1].y= imx;
3800  shape[2].x = -im; shape[2].y = 0;
3801  shape[3].x = -imx; shape[3].y = -imx;
3802  shape[4].x = 0; shape[4].y = -im;
3803  shape[5].x = imx; shape[5].y = -imx;
3804  shape[6].x = im; shape[6].y = 0;
3805  shape[7].x= imx; shape[7].y= imx;
3806  shape[8].x= 0; shape[8].y= im;
3807  SetMarkerType(2,9,shape);
3808  } else if (markerstyle == 43) {
3809  // filled double diamonds
3810  Int_t imx = Int_t(MarkerSizeReduced + 0.5);
3811  shape[0].x = 0; shape[0].y = im;
3812  shape[1].x = -imx; shape[1].y = imx;
3813  shape[2].x = -im; shape[2].y = 0;
3814  shape[3].x = -imx; shape[3].y = -imx;
3815  shape[4].x = 0; shape[4].y = -im;
3816  shape[5].x = imx; shape[5].y = -imx;
3817  shape[6].x = im; shape[6].y = 0;
3818  shape[7].x = imx; shape[7].y = imx;
3819  shape[8].x = 0; shape[8].y = im;
3820  SetMarkerType(3,9,shape);
3821  } else if (markerstyle == 44) {
3822  // open four triangles plus
3823  Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5);
3824  shape[0].x = 0; shape[0].y = 0;
3825  shape[1].x = im2; shape[1].y = im;
3826  shape[2].x = -im2; shape[2].y = im;
3827  shape[3].x = im2; shape[3].y = -im;
3828  shape[4].x = -im2; shape[4].y = -im;
3829  shape[5].x = 0; shape[5].y = 0;
3830  shape[6].x = im; shape[6].y = im2;
3831  shape[7].x = im; shape[7].y = -im2;
3832  shape[8].x = -im; shape[8].y = im2;
3833  shape[9].x = -im; shape[9].y = -im2;
3834  shape[10].x = 0; shape[10].y = 0;
3835  SetMarkerType(2,11,shape);
3836  } else if (markerstyle == 45) {
3837  // filled four triangles plus
3838  Int_t im0 = Int_t(0.4*MarkerSizeReduced + 0.5);
3839  Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5);
3840  shape[0].x = im0; shape[0].y = im0;
3841  shape[1].x = im2; shape[1].y = im;
3842  shape[2].x = -im2; shape[2].y = im;
3843  shape[3].x = -im0; shape[3].y = im0;
3844  shape[4].x = -im; shape[4].y = im2;
3845  shape[5].x = -im; shape[5].y = -im2;
3846  shape[6].x = -im0; shape[6].y = -im0;
3847  shape[7].x = -im2; shape[7].y = -im;
3848  shape[8].x = im2; shape[8].y = -im;
3849  shape[9].x = im0; shape[9].y = -im0;
3850  shape[10].x = im; shape[10].y = -im2;
3851  shape[11].x = im; shape[11].y = im2;
3852  shape[12].x = im0; shape[12].y = im0;
3853  SetMarkerType(3,13,shape);
3854  } else if (markerstyle == 46) {
3855  // open four triangles X
3856  Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5);
3857  shape[0].x = 0; shape[0].y = im2;
3858  shape[1].x = -im2; shape[1].y = im;
3859  shape[2].x = -im; shape[2].y = im2;
3860  shape[3].x = -im2; shape[3].y = 0;
3861  shape[4].x = -im; shape[4].y = -im2;
3862  shape[5].x = -im2; shape[5].y = -im;
3863  shape[6].x = 0; shape[6].y = -im2;
3864  shape[7].x = im2; shape[7].y = -im;
3865  shape[8].x = im; shape[8].y = -im2;
3866  shape[9].x = im2; shape[9].y = 0;
3867  shape[10].x = im; shape[10].y = im2;
3868  shape[11].x = im2; shape[11].y = im;
3869  shape[12].x = 0; shape[12].y = im2;
3870  SetMarkerType(2,13,shape);
3871  } else if (markerstyle == 47) {
3872  // filled four triangles X
3873  Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5);
3874  shape[0].x = 0; shape[0].y = im2;
3875  shape[1].x = -im2; shape[1].y = im;
3876  shape[2].x = -im; shape[2].y = im2;
3877  shape[3].x = -im2; shape[3].y = 0;
3878  shape[4].x = -im; shape[4].y = -im2;
3879  shape[5].x = -im2; shape[5].y = -im;
3880  shape[6].x = 0; shape[6].y = -im2;
3881  shape[7].x = im2; shape[7].y = -im;
3882  shape[8].x = im; shape[8].y = -im2;
3883  shape[9].x = im2; shape[9].y = 0;
3884  shape[10].x = im; shape[10].y = im2;
3885  shape[11].x = im2; shape[11].y = im;
3886  shape[12].x = 0; shape[12].y = im2;
3887  SetMarkerType(3,13,shape);
3888  } else if (markerstyle == 48) {
3889  // four filled squares X
3890  Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5);
3891  shape[0].x = 0; shape[0].y = im2*1.005;
3892  shape[1].x = -im2; shape[1].y = im;
3893  shape[2].x = -im; shape[2].y = im2;
3894  shape[3].x = -im2; shape[3].y = 0;
3895  shape[4].x = -im; shape[4].y = -im2;
3896  shape[5].x = -im2; shape[5].y = -im;
3897  shape[6].x = 0; shape[6].y = -im2;
3898  shape[7].x = im2; shape[7].y = -im;
3899  shape[8].x = im; shape[8].y = -im2;
3900  shape[9].x = im2; shape[9].y = 0;
3901  shape[10].x = im; shape[10].y = im2;
3902  shape[11].x = im2; shape[11].y = im;
3903  shape[12].x = 0; shape[12].y = im2*0.995;
3904  shape[13].x = im2*0.995; shape[13].y = 0;
3905  shape[14].x = 0; shape[14].y = -im2*0.995;
3906  shape[15].x = -im2*0.995; shape[15].y = 0;
3907  shape[16].x = 0; shape[16].y = im2*0.995;
3908  SetMarkerType(3,16,shape);
3909  } else if (markerstyle == 49) {
3910  // four filled squares plus
3911  Int_t imx = Int_t(1.33*MarkerSizeReduced + 0.5);
3912  shape[0].x =-imx; shape[0].y =-imx*1.005;
3913  shape[1].x =-imx; shape[1].y = -im;
3914  shape[2].x = imx; shape[2].y = -im;
3915  shape[3].x = imx; shape[3].y =-imx;
3916  shape[4].x = im; shape[4].y =-imx;
3917  shape[5].x = im; shape[5].y = imx;
3918  shape[6].x = imx; shape[6].y = imx;
3919  shape[7].x = imx; shape[7].y = im;
3920  shape[8].x =-imx; shape[8].y = im;
3921  shape[9].x =-imx; shape[9].y = imx;
3922  shape[10].x = -im; shape[10].y = imx;
3923  shape[11].x = -im; shape[11].y =-imx;
3924  shape[12].x =-imx; shape[12].y =-imx*0.995;
3925  shape[13].x =-imx; shape[13].y = imx;
3926  shape[14].x = imx; shape[14].y = imx;
3927  shape[15].x = imx; shape[15].y =-imx;
3928  shape[16].x =-imx; shape[16].y =-imx*1.005;
3929  SetMarkerType(3,17,shape);
3930  } else {
3931  // single dot
3932  SetMarkerType(0, 0, shape);
3933  }
3935 }
3936 
3937 ////////////////////////////////////////////////////////////////////////////////
3938 /// Set opacity of a window. This image manipulation routine works
3939 /// by adding to a percent amount of neutral to each pixels RGB.
3940 /// Since it requires quite some additional color map entries is it
3941 /// only supported on displays with more than > 8 color planes (> 256
3942 /// colors)
3943 
3945 {
3946  Int_t depth = gdk_visual_get_best_depth();
3947 
3948  if (depth <= 8) return;
3949  if (percent == 0) return;
3950 
3951  // if 100 percent then just make white
3952  ULong_t *orgcolors = 0, *tmpc = 0;
3953  Int_t maxcolors = 0, ncolors, ntmpc = 0;
3954 
3955  // save previous allocated colors, delete at end when not used anymore
3956  if (gCws->new_colors) {
3957  tmpc = gCws->new_colors;
3958  ntmpc = gCws->ncolors;
3959  }
3960  // get pixmap from server as image
3961  GdkImage *image = gdk_image_get((GdkDrawable*)gCws->drawing, 0, 0,
3962  gCws->width, gCws->height);
3963 
3964  // collect different image colors
3965  int x, y;
3966  for (y = 0; y < (int) gCws->height; y++) {
3967  for (x = 0; x < (int) gCws->width; x++) {
3968  ULong_t pixel = GetPixelImage((Drawable_t)image, x, y);
3969  CollectImageColors(pixel, orgcolors, ncolors, maxcolors);
3970  }
3971  }
3972  if (ncolors == 0) {
3973  gdk_image_unref(image);
3974  ::operator delete(orgcolors);
3975  return;
3976  }
3977  // create opaque counter parts
3978  MakeOpaqueColors(percent, orgcolors, ncolors);
3979 
3980  // put opaque colors in image
3981  for (y = 0; y < (int) gCws->height; y++) {
3982  for (x = 0; x < (int) gCws->width; x++) {
3983  ULong_t pixel = GetPixelImage((Drawable_t)image, x, y);
3984  Int_t idx = FindColor(pixel, orgcolors, ncolors);
3985  PutPixel((Drawable_t)image, x, y, gCws->new_colors[idx]);
3986  }
3987  }
3988 
3989  // put image back in pixmap on server
3990  gdk_draw_image(gCws->drawing, gGCpxmp, (GdkImage *)image,
3991  0, 0, 0, 0, gCws->width, gCws->height);
3992  GdiFlush();
3993 
3994  // clean up
3995  if (tmpc) {
3996  gdk_colors_free((GdkColormap *)fColormap, tmpc, ntmpc, 0);
3997  delete[]tmpc;
3998  }
3999  gdk_image_unref(image);
4000  ::operator delete(orgcolors);
4001 }
4002 
4003 ////////////////////////////////////////////////////////////////////////////////
4004 /// Get RGB values for orgcolors, add percent neutral to the RGB and
4005 /// allocate new_colors.
4006 
4007 void TGWin32::MakeOpaqueColors(Int_t percent, ULong_t *orgcolors, Int_t ncolors)
4008 {
4009  Int_t ret;
4010  if (ncolors <= 0) return;
4011  GdkColor *xcol = new GdkColor[ncolors];
4012 
4013  int i;
4014  for (i = 0; i < ncolors; i++) {
4015  xcol[i].pixel = orgcolors[i];
4016  xcol[i].red = xcol[i].green = xcol[i].blue = 0;
4017  }
4018 
4019  GdkColorContext *cc;
4020  cc = gdk_color_context_new(gdk_visual_get_system(), (GdkColormap *)fColormap);
4021  gdk_color_context_query_colors(cc, xcol, ncolors);
4022  gdk_color_context_free(cc);
4023 
4024  UShort_t add = percent * kBIGGEST_RGB_VALUE / 100;
4025 
4026  Int_t val;
4027  for (i = 0; i < ncolors; i++) {
4028  val = xcol[i].red + add;
4029  if (val > kBIGGEST_RGB_VALUE) {
4030  val = kBIGGEST_RGB_VALUE;
4031  }
4032  xcol[i].red = (UShort_t) val;
4033  val = xcol[i].green + add;
4034  if (val > kBIGGEST_RGB_VALUE) {
4035  val = kBIGGEST_RGB_VALUE;
4036  }
4037  xcol[i].green = (UShort_t) val;
4038  val = xcol[i].blue + add;
4039  if (val > kBIGGEST_RGB_VALUE) {
4040  val = kBIGGEST_RGB_VALUE;
4041  }
4042  xcol[i].blue = (UShort_t) val;
4043 
4044  ret = gdk_color_alloc((GdkColormap *)fColormap, &xcol[i]);
4045 
4046  if (!ret) {
4047  Warning("MakeOpaqueColors",
4048  "failed to allocate color %hd, %hd, %hd", xcol[i].red,
4049  xcol[i].green, xcol[i].blue);
4050  // assumes that in case of failure xcol[i].pixel is not changed
4051  }
4052  }
4053 
4054  gCws->new_colors = new ULong_t[ncolors];
4055  gCws->ncolors = ncolors;
4056 
4057  for (i = 0; i < ncolors; i++) {
4058  gCws->new_colors[i] = xcol[i].pixel;
4059  }
4060 
4061  delete []xcol;
4062 }
4063 
4064 ////////////////////////////////////////////////////////////////////////////////
4065 /// Returns index in orgcolors (and new_colors) for pixel.
4066 
4067 Int_t TGWin32::FindColor(ULong_t pixel, ULong_t * orgcolors, Int_t ncolors)
4068 {
4069  for (int i = 0; i < ncolors; i++) {
4070  if (pixel == orgcolors[i]) return i;
4071  }
4072  Error("FindColor", "did not find color, should never happen!");
4073 
4074  return 0;
4075 }
4076 
4077 ////////////////////////////////////////////////////////////////////////////////
4078 /// Set color intensities for given color index.
4079 /// cindex : color index
4080 /// r,g,b : red, green, blue intensities between 0.0 and 1.0
4081 
4082 void TGWin32::SetRGB(int cindex, float r, float g, float b)
4083 {
4084  GdkColor xcol;
4085 
4086  if (fColormap && cindex >= 0) {
4087  xcol.red = (unsigned short) (r * kBIGGEST_RGB_VALUE);
4088  xcol.green = (unsigned short) (g * kBIGGEST_RGB_VALUE);
4089  xcol.blue = (unsigned short) (b * kBIGGEST_RGB_VALUE);
4090  xcol.pixel = RGB(xcol.red, xcol.green, xcol.blue);
4091 
4092  XColor_t &col = GetColor(cindex);
4093  if (col.fDefined) {
4094  // if color is already defined with same rgb just return
4095  if (col.color.red == xcol.red && col.color.green == xcol.green &&
4096  col.color.blue == xcol.blue)
4097  return;
4098  col.fDefined = kFALSE;
4099  gdk_colormap_free_colors((GdkColormap *) fColormap,
4100  (GdkColor *)&col, 1);
4101  }
4102 
4103  Int_t ret = gdk_colormap_alloc_color(fColormap, &xcol, 1, 1);
4104  if (ret != 0) {
4105  col.fDefined = kTRUE;
4106  col.color.pixel = xcol.pixel;
4107  col.color.red = xcol.red;
4108  col.color.green = xcol.green;
4109  col.color.blue = xcol.blue;
4110  }
4111  }
4112 }
4113 
4114 ////////////////////////////////////////////////////////////////////////////////
4115 /// Set text alignment.
4116 /// txalh : horizontal text alignment
4117 /// txalv : vertical text alignment
4118 
4120 {
4121  static Short_t current = 0;
4122  if (talign==current) return;
4123  current = talign;
4124 
4125  Int_t txalh = talign / 10;
4126  Int_t txalv = talign % 10;
4127  fTextAlignH = txalh;
4128  fTextAlignV = txalv;
4129 
4130  switch (txalh) {
4131 
4132  case 0:
4133  case 1:
4134  switch (txalv) { //left
4135  case 1:
4136  fTextAlign = 7; //bottom
4137  break;
4138  case 2:
4139  fTextAlign = 4; //center
4140  break;
4141  case 3:
4142  fTextAlign = 1; //top
4143  break;
4144  }
4145  break;
4146  case 2:
4147  switch (txalv) { //center
4148  case 1:
4149  fTextAlign = 8; //bottom
4150  break;
4151  case 2:
4152  fTextAlign = 5; //center
4153  break;
4154  case 3:
4155  fTextAlign = 2; //top
4156  break;
4157  }
4158  break;
4159  case 3:
4160  switch (txalv) { //right
4161  case 1:
4162  fTextAlign = 9; //bottom
4163  break;
4164  case 2:
4165  fTextAlign = 6; //center
4166  break;
4167  case 3:
4168  fTextAlign = 3; //top
4169  break;
4170  }
4171  break;
4172  }
4174 }
4175 
4176 ////////////////////////////////////////////////////////////////////////////////
4177 /// Set color index for text.
4178 
4180 {
4181  static Int_t current = 0;
4182  GdkGCValues values;
4183  if ((cindex < 0) || (Int_t(cindex)==current)) return;
4184 
4185  TAttText::SetTextColor(cindex);
4186 
4187  SetColor(gGCtext, Int_t(cindex));
4188  gdk_gc_get_values(gGCtext, &values);
4189  gdk_gc_set_foreground(gGCinvt, &values.background);
4190  gdk_gc_set_background(gGCinvt, &values.foreground);
4191  gdk_gc_set_background(gGCtext, (GdkColor *) & GetColor(0).color);
4192  current = Int_t(cindex);
4193 }
4194 
4195 ////////////////////////////////////////////////////////////////////////////////
4196 
4197 void TGWin32::Sync(int mode)
4198 {
4199 }
4200 
4201 ////////////////////////////////////////////////////////////////////////////////
4202 /// Update display.
4203 /// mode : (1) update
4204 /// (0) sync
4205 ///
4206 /// Synchronise client and server once (not permanent).
4207 /// Copy the pixmap gCws->drawing on the window gCws->window
4208 /// if the double buffer is on.
4209 
4211 {
4212  if (gCws && gCws->double_buffer) {
4213  gdk_window_copy_area(gCws->window, gGCpxmp, 0, 0,
4214  gCws->drawing, 0, 0, gCws->width, gCws->height);
4215  }
4216  Update(mode);
4217 }
4218 
4219 ////////////////////////////////////////////////////////////////////////////////
4220 /// Set pointer position.
4221 /// ix : New X coordinate of pointer
4222 /// iy : New Y coordinate of pointer
4223 /// Coordinates are relative to the origin of the window id
4224 /// or to the origin of the current window if id == 0.
4225 
4226 void TGWin32::Warp(int ix, int iy, Window_t id)
4227 {
4228  if (!id) return;
4229 
4230  POINT cpt, tmp;
4231  HWND dw;
4232  if (!id)
4233  dw = (HWND) GDK_DRAWABLE_XID((GdkWindow *)gCws->window);
4234  else
4235  dw = (HWND) GDK_DRAWABLE_XID((GdkWindow *)id);
4236  GetCursorPos(&cpt);
4237  tmp.x = ix > 0 ? ix : cpt.x;
4238  tmp.y = iy > 0 ? iy : cpt.y;
4239  ClientToScreen(dw, &tmp);
4240  SetCursorPos(tmp.x, tmp.y);
4241 }
4242 
4243 ////////////////////////////////////////////////////////////////////////////////
4244 /// Write the pixmap wid in the bitmap file pxname.
4245 /// wid : Pixmap address
4246 /// w,h : Width and height of the pixmap.
4247 /// lenname : pixmap name length
4248 /// pxname : pixmap name
4249 
4250 void TGWin32::WritePixmap(int wid, unsigned int w, unsigned int h,
4251  char *pxname)
4252 {
4253  int wval, hval;
4254  wval = w;
4255  hval = h;
4256 
4257  if (!fWindows) return;
4258  gTws = &fWindows[wid];
4259 // XWriteBitmapFile(fDisplay,pxname,(Pixmap)gTws->drawing,wval,hval,-1,-1);
4260 }
4261 
4262 
4263 //
4264 // Functions for GIFencode()
4265 //
4266 
4267 static FILE *gGifFile; // output unit used WriteGIF and PutByte
4268 static GdkImage *gGifImage = 0; // image used in WriteGIF and GetPixel
4269 
4270 extern "C" {
4271  int GIFquantize(UInt_t width, UInt_t height, Int_t * ncol, Byte_t * red,
4272  Byte_t * green, Byte_t * blue, Byte_t * outputBuf,
4273  Byte_t * outputCmap);
4274  long GIFencode(int Width, int Height, Int_t Ncol, Byte_t R[],
4275  Byte_t G[], Byte_t B[], Byte_t ScLine[],
4276  void (*get_scline) (int, int, Byte_t *),
4277  void (*pb) (Byte_t));
4278  int GIFdecode(Byte_t * GIFarr, Byte_t * PIXarr, int *Width, int *Height,
4279  int *Ncols, Byte_t * R, Byte_t * G, Byte_t * B);
4280  int GIFinfo(Byte_t * GIFarr, int *Width, int *Height, int *Ncols);
4281 }
4282 
4283 
4284 ////////////////////////////////////////////////////////////////////////////////
4285 /// Get pixels in line y and put in array scline.
4286 
4287 static void GetPixel(int y, int width, Byte_t * scline)
4288 {
4289  for (int i = 0; i < width; i++) {
4290  scline[i] = Byte_t(GetPixelImage((Drawable_t)gGifImage, i, y));
4291  }
4292 }
4293 
4294 ////////////////////////////////////////////////////////////////////////////////
4295 /// Put byte b in output stream.
4296 
4297 static void PutByte(Byte_t b)
4298 {
4299  if (ferror(gGifFile) == 0) fputc(b, gGifFile);
4300 }
4301 
4302 ////////////////////////////////////////////////////////////////////////////////
4303 /// Returns in R G B the ncol colors of the palette used by the image.
4304 /// The image pixels are changed to index values in these R G B arrays.
4305 /// This produces a colormap with only the used colors (so even on displays
4306 /// with more than 8 planes we will be able to create GIF's when the image
4307 /// contains no more than 256 different colors). If it does contain more
4308 /// colors we will have to use GIFquantize to reduce the number of colors.
4309 /// The R G B arrays must be deleted by the caller.
4310 
4311 void TGWin32::ImgPickPalette(GdkImage * image, Int_t & ncol, Int_t * &R,
4312  Int_t * &G, Int_t * &B)
4313 {
4314  ULong_t *orgcolors = 0;
4315  Int_t maxcolors = 0, ncolors;
4316 
4317  // collect different image colors
4318  int x, y;
4319  for (x = 0; x < (int) gCws->width; x++) {
4320  for (y = 0; y < (int) gCws->height; y++) {
4321  ULong_t pixel = GetPixelImage((Drawable_t)image, x, y);
4322  CollectImageColors(pixel, orgcolors, ncolors, maxcolors);
4323  }
4324  }
4325 
4326  // get RGB values belonging to pixels
4327  GdkColor *xcol = new GdkColor[ncolors];
4328 
4329  int i;
4330  for (i = 0; i < ncolors; i++) {
4331  xcol[i].pixel = orgcolors[i];
4332 // xcol[i].red = xcol[i].green = xcol[i].blue = 0;
4333  xcol[i].red = GetRValue(xcol[i].pixel);
4334  xcol[i].green = GetGValue(xcol[i].pixel);
4335  xcol[i].blue = GetBValue(xcol[i].pixel);
4336  }
4337 
4338  GdkColorContext *cc;
4339  cc = gdk_color_context_new(gdk_visual_get_system(), (GdkColormap *)fColormap);
4340  gdk_color_context_query_colors(cc, xcol, ncolors);
4341  gdk_color_context_free(cc);
4342 
4343  // create RGB arrays and store RGB's for each color and set number of colors
4344  // (space must be delete by caller)
4345  R = new Int_t[ncolors];
4346  G = new Int_t[ncolors];
4347  B = new Int_t[ncolors];
4348 
4349  for (i = 0; i < ncolors; i++) {
4350  R[i] = xcol[i].red;
4351  G[i] = xcol[i].green;
4352  B[i] = xcol[i].blue;
4353  }
4354  ncol = ncolors;
4355 
4356  // update image with indices (pixels) into the new RGB colormap
4357  for (x = 0; x < (int) gCws->width; x++) {
4358  for (y = 0; y < (int) gCws->height; y++) {
4359  ULong_t pixel = GetPixelImage((Drawable_t)image, x, y);
4360  Int_t idx = FindColor(pixel, orgcolors, ncolors);
4361  PutPixel((Drawable_t)image, x, y, idx);
4362  }
4363  }
4364 
4365  // cleanup
4366  delete[]xcol;
4367  ::operator delete(orgcolors);
4368 }
4369 
4370 ////////////////////////////////////////////////////////////////////////////////
4371 /// Writes the current window into GIF file.
4372 
4374 {
4375  Byte_t scline[2000], r[256], b[256], g[256];
4376  Int_t *R, *G, *B;
4377  Int_t ncol, maxcol, i;
4378 
4379  if (gGifImage) {
4380  gdk_image_unref((GdkImage *)gGifImage);
4381  }
4382 
4383  gGifImage = gdk_image_get((GdkDrawable*)gCws->drawing, 0, 0,
4384  gCws->width, gCws->height);
4385 
4386  ImgPickPalette(gGifImage, ncol, R, G, B);
4387 
4388  if (ncol > 256) {
4389  //GIFquantize(...);
4390  Error("WriteGIF",
4391  "can not create GIF of image containing more than 256 colors");
4392  delete[]R;
4393  delete[]G;
4394  delete[]B;
4395  return 0;
4396  }
4397 
4398  maxcol = 0;
4399  for (i = 0; i < ncol; i++) {
4400  if (maxcol < R[i]) maxcol = R[i];
4401  if (maxcol < G[i]) maxcol = G[i];
4402  if (maxcol < B[i]) maxcol = B[i];
4403  r[i] = 0;
4404  g[i] = 0;
4405  b[i] = 0;
4406  }
4407  if (maxcol != 0) {
4408  for (i = 0; i < ncol; i++) {
4409  r[i] = R[i] * 255 / maxcol;
4410  g[i] = G[i] * 255 / maxcol;
4411  b[i] = B[i] * 255 / maxcol;
4412  }
4413  }
4414 
4415  gGifFile = fopen(name, "wb");
4416 
4417  if (gGifFile) {
4418  GIFencode(gCws->width, gCws->height,
4419  ncol, r, g, b, scline, ::GetPixel, PutByte);
4420  fclose(gGifFile);
4421  i = 1;
4422  } else {
4423  Error("WriteGIF","cannot write file: %s",name);
4424  i = 0;
4425  }
4426  delete[]R;
4427  delete[]G;
4428  delete[]B;
4429 
4430  return i;
4431 }
4432 
4433 ////////////////////////////////////////////////////////////////////////////////
4434 /// Draw image.
4435 
4436 void TGWin32::PutImage(int offset, int itran, int x0, int y0, int nx,
4437  int ny, int xmin, int ymin, int xmax, int ymax,
4438  unsigned char *image, Drawable_t wid)
4439 {
4440  const int MAX_SEGMENT = 20;
4441  int i, n, x, y, xcur, x1, x2, y1, y2;
4442  unsigned char *jimg, *jbase, icol;
4443  int nlines[256];
4444  GdkSegment lines[256][MAX_SEGMENT];
4445  GdkDrawable *id;
4446 
4447  if (wid) {
4448  id = (GdkDrawable*)wid;
4449  } else {
4450  id = gCws->drawing;
4451  }
4452 
4453  for (i = 0; i < 256; i++) nlines[i] = 0;
4454 
4455  x1 = x0 + xmin;
4456  y1 = y0 + ny - ymax - 1;
4457  x2 = x0 + xmax;
4458  y2 = y0 + ny - ymin - 1;
4459  jbase = image + (ymin - 1) * nx + xmin;
4460 
4461  for (y = y2; y >= y1; y--) {
4462  xcur = x1;
4463  jbase += nx;
4464  for (jimg = jbase, icol = *jimg++, x = x1 + 1; x <= x2; jimg++, x++) {
4465  if (icol != *jimg) {
4466  if (icol != itran) {
4467  n = nlines[icol]++;
4468  lines[icol][n].x1 = xcur;
4469  lines[icol][n].y1 = y;
4470  lines[icol][n].x2 = x - 1;
4471  lines[icol][n].y2 = y;
4472  if (nlines[icol] == MAX_SEGMENT) {
4473  SetColor(gGCline, (int) icol + offset);
4474  gdk_win32_draw_segments(id, (GdkGC *) gGCline,
4475  (GdkSegment *) &lines[icol][0], MAX_SEGMENT);
4476  nlines[icol] = 0;
4477  }
4478  }
4479  icol = *jimg;
4480  xcur = x;
4481  }
4482  }
4483  if (icol != itran) {
4484  n = nlines[icol]++;
4485  lines[icol][n].x1 = xcur;
4486  lines[icol][n].y1 = y;
4487  lines[icol][n].x2 = x - 1;
4488  lines[icol][n].y2 = y;
4489  if (nlines[icol] == MAX_SEGMENT) {
4490  SetColor(gGCline, (int) icol + offset);
4491  gdk_win32_draw_segments(id, (GdkGC *) gGCline,
4492  (GdkSegment *)&lines[icol][0], MAX_SEGMENT);
4493  nlines[icol] = 0;
4494  }
4495  }
4496  }
4497 
4498  for (i = 0; i < 256; i++) {
4499  if (nlines[i] != 0) {
4500  SetColor(gGCline, i + offset);
4501  gdk_win32_draw_segments(id, (GdkGC *) gGCline,
4502  (GdkSegment *)&lines[icol][0], nlines[i]);
4503  }
4504  }
4505 }
4506 
4507 ////////////////////////////////////////////////////////////////////////////////
4508 /// If id is NULL - loads the specified gif file at position [x0,y0] in the
4509 /// current window. Otherwise creates pixmap from gif file
4510 
4511 Pixmap_t TGWin32::ReadGIF(int x0, int y0, const char *file, Window_t id)
4512 {
4513  FILE *fd;
4514  Seek_t filesize;
4515  unsigned char *GIFarr, *PIXarr, R[256], G[256], B[256], *j1, *j2, icol;
4516  int i, j, k, width, height, ncolor, irep, offset;
4517  float rr, gg, bb;
4518  Pixmap_t pic = 0;
4519 
4520  fd = fopen(file, "r+b");
4521  if (!fd) {
4522  Error("ReadGIF", "unable to open GIF file");
4523  return pic;
4524  }
4525 
4526  fseek(fd, 0L, 2);
4527  filesize = Seek_t(ftell(fd));
4528  fseek(fd, 0L, 0);
4529 
4530  if (!(GIFarr = (unsigned char *) calloc(filesize + 256, 1))) {
4531  fclose(fd);
4532  Error("ReadGIF", "unable to allocate array for gif");
4533  return pic;
4534  }
4535 
4536  if (fread(GIFarr, filesize, 1, fd) != 1) {
4537  fclose(fd);
4538  Error("ReadGIF", "GIF file read failed");
4539  free(GIFarr);
4540  return pic;
4541  }
4542  fclose(fd);
4543 
4544  irep = GIFinfo(GIFarr, &width, &height, &ncolor);
4545  if (irep != 0) {
4546  return pic;
4547  }
4548 
4549  if (!(PIXarr = (unsigned char *) calloc((width * height), 1))) {
4550  Error("ReadGIF", "unable to allocate array for image");
4551  return pic;
4552  }
4553 
4554  irep = GIFdecode(GIFarr, PIXarr, &width, &height, &ncolor, R, G, B);
4555  if (irep != 0) {
4556  return pic;
4557  }
4558  // S E T P A L E T T E
4559 
4560  offset = 8;
4561 
4562  for (i = 0; i < ncolor; i++) {
4563  rr = R[i] / 255.;
4564  gg = G[i] / 255.;
4565  bb = B[i] / 255.;
4566  j = i + offset;
4567  SetRGB(j, rr, gg, bb);
4568  }
4569 
4570  // O U T P U T I M A G E
4571 
4572  for (i = 1; i <= height / 2; i++) {
4573  j1 = PIXarr + (i - 1) * width;
4574  j2 = PIXarr + (height - i) * width;
4575  for (k = 0; k < width; k++) {
4576  icol = *j1;
4577  *j1++ = *j2;
4578  *j2++ = icol;
4579  }
4580  }
4581 
4582  if (id) pic = CreatePixmap(id, width, height);
4583  PutImage(offset, -1, x0, y0, width, height, 0, 0, width-1, height-1, PIXarr, pic);
4584 
4585  if (pic) return pic;
4586  else if (gCws->drawing) return (Pixmap_t)gCws->drawing;
4587  else return 0;
4588 }
4589 
4590 //////////////////////////// GWin32Gui //////////////////////////////////////////
4591 ////////////////////////////////////////////////////////////////////////////////
4592 /// Map window on screen.
4593 
4595 {
4596  if (!id) return;
4597 
4598  gdk_window_show((GdkWindow *)id);
4599  if ((GDK_DRAWABLE_TYPE((GdkWindow *)id) != GDK_WINDOW_TEMP) &&
4600  (GetParent(id) == GetDefaultRootWindow())) {
4601  HWND window = (HWND)GDK_DRAWABLE_XID((GdkWindow *)id);
4602  ::SetForegroundWindow(window);
4603  }
4604 }
4605 
4606 ////////////////////////////////////////////////////////////////////////////////
4607 ///
4608 
4610 {
4611  if (!id) return;
4612 
4613  EnumChildWindows((HWND)GDK_DRAWABLE_XID((GdkWindow *)id),
4614  EnumChildProc, (LPARAM) NULL);
4615 }
4616 
4617 ////////////////////////////////////////////////////////////////////////////////
4618 /// Map window on screen and put on top of all windows.
4619 
4621 {
4622  if (!id) return;
4623 
4624  HWND hwnd = ::GetForegroundWindow();
4625  HWND window = (HWND)GDK_DRAWABLE_XID((GdkWindow *)id);
4626  gdk_window_show((GdkWindow *)id);
4627  if (GDK_DRAWABLE_TYPE((GdkWindow *)id) != GDK_WINDOW_TEMP) {
4628  ::BringWindowToTop(window);
4629  if (GDK_DRAWABLE_TYPE((GdkWindow *)id) != GDK_WINDOW_CHILD)
4630  ::SetForegroundWindow(window);
4631  }
4632 
4633  if (gConsoleWindow && (hwnd == (HWND)gConsoleWindow)) {
4634  RECT r1, r2, r3;
4635  ::GetWindowRect((HWND)gConsoleWindow, &r1);
4636  HWND fore = ::GetForegroundWindow();
4637  ::GetWindowRect(fore, &r2);
4638  if (!::IntersectRect(&r3, &r2, &r1)) {
4639  ::SetForegroundWindow((HWND)gConsoleWindow);
4640  }
4641  }
4642 }
4643 
4644 ////////////////////////////////////////////////////////////////////////////////
4645 /// Unmap window from screen.
4646 
4648 {
4649  if (!id) return;
4650 
4651  gdk_window_hide((GdkWindow *) id);
4652 }
4653 
4654 ////////////////////////////////////////////////////////////////////////////////
4655 /// Destroy window.
4656 
4658 {
4659  if (!id) return;
4660 
4661  // we need to unmap the window before to destroy it, in order to properly
4662  // receive kUnmapNotify needed by gClient->WaitForUnmap()...
4663  gdk_window_hide((GdkWindow *) id);
4664  gdk_window_destroy((GdkDrawable *) id, kTRUE);
4665 }
4666 
4667 ////////////////////////////////////////////////////////////////////////////////
4668 /// Destroy all internal subwindows
4669 
4671 {
4672  if (!id) return;
4673 
4674  gdk_window_destroy((GdkDrawable *) id, kFALSE);
4675 }
4676 
4677 ////////////////////////////////////////////////////////////////////////////////
4678 /// Put window on top of window stack.
4679 
4681 {
4682  if (!id) return;
4683 
4684  HWND window = (HWND)GDK_DRAWABLE_XID((GdkWindow *)id);
4685  if (GDK_DRAWABLE_TYPE((GdkWindow *)id) == GDK_WINDOW_TEMP) {
4686  ::SetWindowPos(window, HWND_TOPMOST, 0, 0, 0, 0,
4687  SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
4688  }
4689  else {
4690  ::BringWindowToTop(window);
4691  if (GDK_DRAWABLE_TYPE((GdkWindow *)id) != GDK_WINDOW_CHILD)
4692  ::SetForegroundWindow(window);
4693  }
4694 }
4695 
4696 ////////////////////////////////////////////////////////////////////////////////
4697 /// Lower window so it lays below all its siblings.
4698 
4700 {
4701  if (!id) return;
4702 
4703  HWND window = (HWND)GDK_DRAWABLE_XID((GdkWindow *)id);
4704  ::SetWindowPos(window, HWND_BOTTOM, 0, 0, 0, 0,
4705  SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
4706 }
4707 
4708 ////////////////////////////////////////////////////////////////////////////////
4709 /// Move a window.
4710 
4712 {
4713  if (!id) return;
4714 
4715  gdk_window_move((GdkDrawable *) id, x, y);
4716 }
4717 
4718 ////////////////////////////////////////////////////////////////////////////////
4719 /// Move and resize a window.
4720 
4722  UInt_t h)
4723 {
4724  if (!id) return;
4725 
4726  gdk_window_move_resize((GdkWindow *) id, x, y, w, h);
4727 }
4728 
4729 ////////////////////////////////////////////////////////////////////////////////
4730 /// Resize the window.
4731 
4733 {
4734  if (!id) return;
4735 
4736  // protect against potential negative values
4737  if (w >= (UInt_t)INT_MAX || h >= (UInt_t)INT_MAX)
4738  return;
4739  gdk_window_resize((GdkWindow *) id, w, h);
4740 }
4741 
4742 ////////////////////////////////////////////////////////////////////////////////
4743 /// Iconify the window.
4744 
4746 {
4747  if (!id) return;
4748 
4749  gdk_window_lower((GdkWindow *) id);
4750  ::CloseWindow((HWND)GDK_DRAWABLE_XID((GdkWindow *)id));
4751 }
4752 
4753 ////////////////////////////////////////////////////////////////////////////////
4754 /// Reparent window, make pid the new parent and position the window at
4755 /// position (x,y) in new parent.
4756 
4758 {
4759  if (!id) return;
4760 
4761  gdk_window_reparent((GdkWindow *)id, (GdkWindow *)pid, x, y);
4762 }
4763 
4764 ////////////////////////////////////////////////////////////////////////////////
4765 /// Set the window background color.
4766 
4768 {
4769  if (!id) return;
4770 
4771  GdkColor back;
4772  back.pixel = color;
4773  back.red = GetRValue(color);
4774  back.green = GetGValue(color);
4775  back.blue = GetBValue(color);
4776 
4777  gdk_window_set_background((GdkWindow *) id, &back);
4778 }
4779 
4780 ////////////////////////////////////////////////////////////////////////////////
4781 /// Set pixmap as window background.
4782 
4784 {
4785  if (!id) return;
4786 
4787  gdk_window_set_back_pixmap((GdkWindow *) id, (GdkPixmap *) pxm, 0);
4788 }
4789 
4790 ////////////////////////////////////////////////////////////////////////////////
4791 /// Return handle to newly created gdk window.
4792 
4794  UInt_t w, UInt_t h, UInt_t border,
4795  Int_t depth, UInt_t clss,
4796  void *visual, SetWindowAttributes_t * attr,
4797  UInt_t wtype)
4798 {
4799  GdkWindowAttr xattr;
4800  GdkWindow *newWin;
4801  GdkColor background_color;
4802  ULong_t xmask = 0;
4803 
4804  if (attr) {
4805  MapSetWindowAttributes(attr, xmask, xattr);
4806  xattr.window_type = GDK_WINDOW_CHILD;
4807  if (wtype & kMainFrame) {
4808  xattr.window_type = GDK_WINDOW_TOPLEVEL;
4809  }
4810  if (wtype & kTransientFrame) {
4811  xattr.window_type = GDK_WINDOW_DIALOG;
4812  }
4813  if (wtype & kTempFrame) {
4814  xattr.window_type = GDK_WINDOW_TEMP;
4815  }
4816  newWin = gdk_window_new((GdkWindow *) parent, &xattr, xmask);
4817  } else {
4818  xattr.width = w;
4819  xattr.height = h;
4820  xattr.wclass = GDK_INPUT_OUTPUT;
4821  xattr.event_mask = 0L; //GDK_ALL_EVENTS_MASK;
4822  xattr.event_mask |= GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK |
4823  GDK_PROPERTY_CHANGE_MASK;
4824 // GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK;
4825  if (x >= 0) {
4826  xattr.x = x;
4827  } else {
4828  xattr.x = -1.0 * x;
4829  }
4830  if (y >= 0) {
4831  xattr.y = y;
4832  } else {
4833  xattr.y = -1.0 * y;
4834  }
4835  xattr.colormap = gdk_colormap_get_system();
4836  xattr.cursor = NULL;
4837  xattr.override_redirect = TRUE;
4838  if ((xattr.y > 0) && (xattr.x > 0)) {
4839  xmask = GDK_WA_X | GDK_WA_Y | GDK_WA_COLORMAP |
4840  GDK_WA_WMCLASS | GDK_WA_NOREDIR;
4841  } else {
4842  xmask = GDK_WA_COLORMAP | GDK_WA_WMCLASS | GDK_WA_NOREDIR;
4843  }
4844  if (visual != NULL) {
4845  xattr.visual = (GdkVisual *) visual;
4846  xmask |= GDK_WA_VISUAL;
4847  } else {
4848  xattr.visual = gdk_visual_get_system();
4849  xmask |= GDK_WA_VISUAL;
4850  }
4851  xattr.window_type = GDK_WINDOW_CHILD;
4852  if (wtype & kMainFrame) {
4853  xattr.window_type = GDK_WINDOW_TOPLEVEL;
4854  }
4855  if (wtype & kTransientFrame) {
4856  xattr.window_type = GDK_WINDOW_DIALOG;
4857  }
4858  if (wtype & kTempFrame) {
4859  xattr.window_type = GDK_WINDOW_TEMP;
4860  }
4861  newWin = gdk_window_new((GdkWindow *) parent, &xattr, xmask);
4862  gdk_window_set_events(newWin, (GdkEventMask) 0L);
4863  }
4864  if (border > 0) {
4865  gdk_window_set_decorations(newWin,
4866  (GdkWMDecoration) GDK_DECOR_BORDER);
4867  }
4868  if (attr) {
4869  if ((attr->fMask & kWABackPixmap)) {
4870  if (attr->fBackgroundPixmap == kNone) {
4871  gdk_window_set_back_pixmap(newWin, (GdkPixmap *) GDK_NONE, 0);
4872  } else if (attr->fBackgroundPixmap == kParentRelative) {
4873  gdk_window_set_back_pixmap(newWin, (GdkPixmap *) GDK_NONE, 1);
4874  } else {
4875  gdk_window_set_back_pixmap(newWin,
4876  (GdkPixmap *) attr->
4877  fBackgroundPixmap, 0);
4878  }
4879  }
4880  if ((attr->fMask & kWABackPixel)) {
4881  background_color.pixel = attr->fBackgroundPixel;
4882  background_color.red = GetRValue(attr->fBackgroundPixel);
4883  background_color.green = GetGValue(attr->fBackgroundPixel);
4884  background_color.blue = GetBValue(attr->fBackgroundPixel);
4885  gdk_window_set_background(newWin, &background_color);
4886  }
4887  }
4888  if (!fUseSysPointers) {
4889  ::SetClassLong((HWND)GDK_DRAWABLE_XID(newWin), GCL_HCURSOR,
4890  (LONG)GDK_CURSOR_XID(fCursors[kPointer]));
4891  }
4892  return (Window_t) newWin;
4893 }
4894 
4895 ////////////////////////////////////////////////////////////////////////////////
4896 /// Map event mask to or from gdk.
4897 
4898 void TGWin32::MapEventMask(UInt_t & emask, UInt_t & xemask, Bool_t tox)
4899 {
4900  if (tox) {
4901  Long_t lxemask = 0L;
4902  if ((emask & kKeyPressMask)) {
4903  lxemask |= GDK_KEY_PRESS_MASK;
4904  }
4905  if ((emask & kKeyReleaseMask)) {
4906  lxemask |= GDK_KEY_RELEASE_MASK;
4907  }
4908  if ((emask & kButtonPressMask)) {
4909  lxemask |= GDK_BUTTON_PRESS_MASK;
4910  }
4911  if ((emask & kButtonReleaseMask)) {
4912  lxemask |= GDK_BUTTON_RELEASE_MASK;
4913  }
4914  if ((emask & kPointerMotionMask)) {
4915  lxemask |= GDK_POINTER_MOTION_MASK;
4916  }
4917  if ((emask & kButtonMotionMask)) {
4918  lxemask |= GDK_BUTTON_MOTION_MASK;
4919  }
4920  if ((emask & kExposureMask)) {
4921  lxemask |= GDK_EXPOSURE_MASK;
4922  }
4923  if ((emask & kStructureNotifyMask)) {
4924  lxemask |= GDK_STRUCTURE_MASK;
4925  }
4926  if ((emask & kEnterWindowMask)) {
4927  lxemask |= GDK_ENTER_NOTIFY_MASK;
4928  }
4929  if ((emask & kLeaveWindowMask)) {
4930  lxemask |= GDK_LEAVE_NOTIFY_MASK;
4931  }
4932  if ((emask & kFocusChangeMask)) {
4933  lxemask |= GDK_FOCUS_CHANGE_MASK;
4934  }
4935  xemask = (UInt_t) lxemask;
4936  } else {
4937  emask = 0;
4938  if ((xemask & GDK_KEY_PRESS_MASK)) {
4939  emask |= kKeyPressMask;
4940  }
4941  if ((xemask & GDK_KEY_RELEASE_MASK)) {
4942  emask |= kKeyReleaseMask;
4943  }
4944  if ((xemask & GDK_BUTTON_PRESS_MASK)) {
4945  emask |= kButtonPressMask;
4946  }
4947  if ((xemask & GDK_BUTTON_RELEASE_MASK)) {
4948  emask |= kButtonReleaseMask;
4949  }
4950  if ((xemask & GDK_POINTER_MOTION_MASK)) {
4951  emask |= kPointerMotionMask;
4952  }
4953  if ((xemask & GDK_BUTTON_MOTION_MASK)) {
4954  emask |= kButtonMotionMask;
4955  }
4956  if ((xemask & GDK_EXPOSURE_MASK)) {
4957  emask |= kExposureMask;
4958  }
4959  if ((xemask & GDK_STRUCTURE_MASK)) {
4960  emask |= kStructureNotifyMask;
4961  }
4962  if ((xemask & GDK_ENTER_NOTIFY_MASK)) {
4963  emask |= kEnterWindowMask;
4964  }
4965  if ((xemask & GDK_LEAVE_NOTIFY_MASK)) {
4966  emask |= kLeaveWindowMask;
4967  }
4968  if ((xemask & GDK_FOCUS_CHANGE_MASK)) {
4969  emask |= kFocusChangeMask;
4970  }
4971  }
4972 }
4973 
4974 ////////////////////////////////////////////////////////////////////////////////
4975 /// Map a SetWindowAttributes_t to a GdkWindowAttr structure.
4976 
4978  ULong_t & xmask,
4979  GdkWindowAttr & xattr)
4980 {
4981  Mask_t mask = attr->fMask;
4982  xmask = 0;
4983 
4984  if ((mask & kWAOverrideRedirect)) {
4985  xmask |= GDK_WA_NOREDIR;
4986  xattr.override_redirect = attr->fOverrideRedirect;
4987  }
4988  if ((mask & kWAEventMask)) {
4989  UInt_t xmsk, msk = (UInt_t) attr->fEventMask;
4990  MapEventMask(msk, xmsk, kTRUE);
4991  xattr.event_mask = xmsk;
4992  }
4993  if ((mask & kWAColormap)) {
4994  xmask |= GDK_WA_COLORMAP;
4995  xattr.colormap = (GdkColormap *) attr->fColormap;
4996  }
4997  if ((mask & kWACursor)) {
4998  xmask |= GDK_WA_CURSOR;
4999  if (attr->fCursor != kNone) {
5000  xattr.cursor = (GdkCursor *) attr->fCursor;
5001  }
5002  }
5003  xattr.wclass = GDK_INPUT_OUTPUT;
5004 }
5005 
5006 ////////////////////////////////////////////////////////////////////////////////
5007 /// Map a GCValues_t to a XCGValues structure if tox is true. Map
5008 /// the other way in case tox is false.
5009 
5011  ULong_t & xmask, GdkGCValues & xgval, Bool_t tox)
5012 {
5013  if (tox) {
5014  // map GCValues_t to XGCValues
5015  Mask_t mask = gval.fMask;
5016  xmask = 0;
5017 
5018  if ((mask & kGCFunction)) {
5019  xmask |= GDK_GC_FUNCTION;
5020  switch (gval.fFunction) {
5021  case kGXclear:
5022  xgval.function = GDK_CLEAR;
5023  break;
5024  case kGXand:
5025  xgval.function = GDK_AND;
5026  break;
5027  case kGXandReverse:
5028  xgval.function = GDK_AND_REVERSE;
5029  break;
5030  case kGXcopy:
5031  xgval.function = GDK_COPY;
5032  break;
5033  case kGXandInverted:
5034  xgval.function = GDK_AND_INVERT;
5035  break;
5036  case kGXnoop:
5037  xgval.function = GDK_NOOP;
5038  break;
5039  case kGXxor:
5040  xgval.function = GDK_XOR;
5041  break;
5042  case kGXor:
5043  xgval.function = GDK_OR;
5044  break;
5045  case kGXequiv:
5046  xgval.function = GDK_EQUIV;
5047  break;
5048  case kGXinvert:
5049  xgval.function = GDK_INVERT;
5050  break;
5051  case kGXorReverse:
5052  xgval.function = GDK_OR_REVERSE;
5053  break;
5054  case kGXcopyInverted:
5055  xgval.function = GDK_COPY_INVERT;
5056  break;
5057  case kGXorInverted:
5058  xgval.function = GDK_OR_INVERT;
5059  break;
5060  case kGXnand:
5061  xgval.function = GDK_NAND;
5062  break;
5063  case kGXset:
5064  xgval.function = GDK_SET;
5065  break;
5066  }
5067  }
5068  if (mask & kGCSubwindowMode) {
5069  xmask |= GDK_GC_SUBWINDOW;
5070  if (gval.fSubwindowMode == kIncludeInferiors) {
5071  xgval.subwindow_mode = GDK_INCLUDE_INFERIORS;
5072  } else {
5073  xgval.subwindow_mode = GDK_CLIP_BY_CHILDREN;
5074  }
5075  }
5076  if (mask & kGCForeground) {
5077  xmask |= GDK_GC_FOREGROUND;
5078  xgval.foreground.pixel = gval.fForeground;
5079  xgval.foreground.red = GetRValue(gval.fForeground);
5080  xgval.foreground.green = GetGValue(gval.fForeground);
5081  xgval.foreground.blue = GetBValue(gval.fForeground);
5082  }
5083  if (mask & kGCBackground) {
5084  xmask |= GDK_GC_BACKGROUND;
5085  xgval.background.pixel = gval.fBackground;
5086  xgval.background.red = GetRValue(gval.fBackground);
5087  xgval.background.green = GetGValue(gval.fBackground);
5088  xgval.background.blue = GetBValue(gval.fBackground);
5089  }
5090  if (mask & kGCLineWidth) {
5091  xmask |= GDK_GC_LINE_WIDTH;
5092  xgval.line_width = gval.fLineWidth;
5093  }
5094  if (mask & kGCLineStyle) {
5095  xmask |= GDK_GC_LINE_STYLE;
5096  xgval.line_style = (GdkLineStyle) gval.fLineStyle; // ident mapping
5097  }
5098  if (mask & kGCCapStyle) {
5099  xmask |= GDK_GC_CAP_STYLE;
5100  xgval.cap_style = (GdkCapStyle) gval.fCapStyle; // ident mapping
5101  }
5102  if (mask & kGCJoinStyle) {
5103  xmask |= GDK_GC_JOIN_STYLE;
5104  xgval.join_style = (GdkJoinStyle) gval.fJoinStyle; // ident mapping
5105  }
5106  if ((mask & kGCFillStyle)) {
5107  xmask |= GDK_GC_FILL;
5108  xgval.fill = (GdkFill) gval.fFillStyle; // ident mapping
5109  }
5110  if ((mask & kGCTile)) {
5111  xmask |= GDK_GC_TILE;
5112  xgval.tile = (GdkPixmap *) gval.fTile;
5113  }
5114  if ((mask & kGCStipple)) {
5115  xmask |= GDK_GC_STIPPLE;
5116  xgval.stipple = (GdkPixmap *) gval.fStipple;
5117  }
5118  if ((mask & kGCTileStipXOrigin)) {
5119  xmask |= GDK_GC_TS_X_ORIGIN;
5120  xgval.ts_x_origin = gval.fTsXOrigin;
5121  }
5122  if ((mask & kGCTileStipYOrigin)) {
5123  xmask |= GDK_GC_TS_Y_ORIGIN;
5124  xgval.ts_y_origin = gval.fTsYOrigin;
5125  }
5126  if ((mask & kGCFont)) {
5127  xmask |= GDK_GC_FONT;
5128  xgval.font = (GdkFont *) gval.fFont;
5129  }
5130  if ((mask & kGCGraphicsExposures)) {
5131  xmask |= GDK_GC_EXPOSURES;
5132  xgval.graphics_exposures = gval.fGraphicsExposures;
5133  }
5134  if ((mask & kGCClipXOrigin)) {
5135  xmask |= GDK_GC_CLIP_X_ORIGIN;
5136  xgval.clip_x_origin = gval.fClipXOrigin;
5137  }
5138  if ((mask & kGCClipYOrigin)) {
5139  xmask |= GDK_GC_CLIP_Y_ORIGIN;
5140  xgval.clip_y_origin = gval.fClipYOrigin;
5141  }
5142  if ((mask & kGCClipMask)) {
5143  xmask |= GDK_GC_CLIP_MASK;
5144  xgval.clip_mask = (GdkPixmap *) gval.fClipMask;
5145  }
5146  } else {
5147  // map XValues to GCValues_t
5148  Mask_t mask = 0;
5149 
5150  if ((xmask & GDK_GC_FUNCTION)) {
5151  mask |= kGCFunction;
5152  gval.fFunction = (EGraphicsFunction) xgval.function; // ident mapping
5153  switch (xgval.function) {
5154  case GDK_CLEAR:
5155  gval.fFunction = kGXclear;
5156  break;
5157  case GDK_AND:
5158  gval.fFunction = kGXand;
5159  break;
5160  case GDK_AND_REVERSE:
5161  gval.fFunction = kGXandReverse;
5162  break;
5163  case GDK_COPY:
5164  gval.fFunction = kGXcopy;
5165  break;
5166  case GDK_AND_INVERT:
5167  gval.fFunction = kGXandInverted;
5168  break;
5169  case GDK_NOOP:
5170  gval.fFunction = kGXnoop;
5171  break;
5172  case GDK_XOR:
5173  gval.fFunction = kGXxor;
5174  break;
5175  case GDK_OR:
5176  gval.fFunction = kGXor;
5177  break;
5178  case GDK_EQUIV:
5179  gval.fFunction = kGXequiv;
5180  break;
5181  case GDK_INVERT:
5182  gval.fFunction = kGXinvert;
5183  break;
5184  case GDK_OR_REVERSE:
5185  gval.fFunction = kGXorReverse;
5186  break;
5187  case GDK_COPY_INVERT:
5188  gval.fFunction = kGXcopyInverted;
5189  break;
5190  case GDK_OR_INVERT:
5191  gval.fFunction = kGXorInverted;
5192  break;
5193  case GDK_NAND:
5194  gval.fFunction = kGXnand;
5195  break;
5196  case GDK_SET:
5197  gval.fFunction = kGXset;
5198  break;
5199  }
5200  }
5201  if (xmask & GDK_GC_SUBWINDOW) {
5202  mask |= kGCSubwindowMode;
5203  if (xgval.subwindow_mode == GDK_INCLUDE_INFERIORS)
5205  else
5207  }
5208  if ((xmask & GDK_GC_FOREGROUND)) {
5209  mask |= kGCForeground;
5210  gval.fForeground = xgval.foreground.pixel;
5211  }
5212  if ((xmask & GDK_GC_BACKGROUND)) {
5213  mask |= kGCBackground;
5214  gval.fBackground = xgval.background.pixel;
5215  }
5216  if ((xmask & GDK_GC_LINE_WIDTH)) {
5217  mask |= kGCLineWidth;
5218  gval.fLineWidth = xgval.line_width;
5219  }
5220  if ((xmask & GDK_GC_LINE_STYLE)) {
5221  mask |= kGCLineStyle;
5222  gval.fLineStyle = xgval.line_style; // ident mapping
5223  }
5224  if ((xmask & GDK_GC_CAP_STYLE)) {
5225  mask |= kGCCapStyle;
5226  gval.fCapStyle = xgval.cap_style; // ident mapping
5227  }
5228  if ((xmask & GDK_GC_JOIN_STYLE)) {
5229  mask |= kGCJoinStyle;
5230  gval.fJoinStyle = xgval.join_style; // ident mapping
5231  }
5232  if ((xmask & GDK_GC_FILL)) {
5233  mask |= kGCFillStyle;
5234  gval.fFillStyle = xgval.fill; // ident mapping
5235  }
5236  if ((xmask & GDK_GC_TILE)) {
5237  mask |= kGCTile;
5238  gval.fTile = (Pixmap_t) xgval.tile;
5239  }
5240  if ((xmask & GDK_GC_STIPPLE)) {
5241  mask |= kGCStipple;
5242  gval.fStipple = (Pixmap_t) xgval.stipple;
5243  }
5244  if ((xmask & GDK_GC_TS_X_ORIGIN)) {
5245  mask |= kGCTileStipXOrigin;
5246  gval.fTsXOrigin = xgval.ts_x_origin;
5247  }
5248  if ((xmask & GDK_GC_TS_Y_ORIGIN)) {
5249  mask |= kGCTileStipYOrigin;
5250  gval.fTsYOrigin = xgval.ts_y_origin;
5251  }
5252  if ((xmask & GDK_GC_FONT)) {
5253  mask |= kGCFont;
5254  gval.fFont = (FontH_t) xgval.font;
5255  }
5256  if ((xmask & GDK_GC_EXPOSURES)) {
5257  mask |= kGCGraphicsExposures;
5258  gval.fGraphicsExposures = (Bool_t) xgval.graphics_exposures;
5259  }
5260  if ((xmask & GDK_GC_CLIP_X_ORIGIN)) {
5261  mask |= kGCClipXOrigin;
5262  gval.fClipXOrigin = xgval.clip_x_origin;
5263  }
5264  if ((xmask & GDK_GC_CLIP_Y_ORIGIN)) {
5265  mask |= kGCClipYOrigin;
5266  gval.fClipYOrigin = xgval.clip_y_origin;
5267  }
5268  if ((xmask & GDK_GC_CLIP_MASK)) {
5269  mask |= kGCClipMask;
5270  gval.fClipMask = (Pixmap_t) xgval.clip_mask;
5271  }
5272  gval.fMask = mask;
5273  }
5274 }
5275 
5276 ////////////////////////////////////////////////////////////////////////////////
5277 /// Get window attributes and return filled in attributes structure.
5278 
5280 {
5281  if (!id) return;
5282 
5283  RECT rcClient, rcWind;
5284  ::GetClientRect((HWND)GDK_DRAWABLE_XID((GdkWindow *) id), &rcClient);
5285  ::GetWindowRect((HWND)GDK_DRAWABLE_XID((GdkWindow *) id), &rcWind);
5286 
5287  gdk_window_get_geometry((GdkWindow *) id, &attr.fX, &attr.fY,
5288  &attr.fWidth, &attr.fHeight, &attr.fDepth);
5289  attr.fX = ((rcWind.right - rcWind.left) - rcClient.right) / 2;
5290  attr.fY = ((rcWind.bottom - rcWind.top) - rcClient.bottom) - attr.fX;
5291 
5292  attr.fRoot = (Window_t) GDK_ROOT_PARENT();
5293  attr.fColormap = (Colormap_t) gdk_window_get_colormap((GdkWindow *) id);
5294  attr.fBorderWidth = 0;
5295  attr.fVisual = gdk_window_get_visual((GdkWindow *) id);
5296  attr.fClass = kInputOutput;
5297  attr.fBackingStore = kNotUseful;
5298  attr.fSaveUnder = kFALSE;
5299  attr.fMapInstalled = kTRUE;
5300  attr.fOverrideRedirect = kFALSE; // boolean value for override-redirect
5301 
5302  if (!gdk_window_is_visible((GdkWindow *) id)) {
5303  attr.fMapState = kIsUnmapped;
5304  } else if (!gdk_window_is_viewable((GdkWindow *) id)) {
5305  attr.fMapState = kIsUnviewable;
5306  } else {
5307  attr.fMapState = kIsViewable;
5308  }
5309 
5310  UInt_t tmp_mask = (UInt_t)gdk_window_get_events((GdkWindow *) id);
5311  UInt_t evmask;
5312  MapEventMask(evmask, tmp_mask, kFALSE);
5313 
5314  attr.fYourEventMask = evmask;
5315 }
5316 
5317 ////////////////////////////////////////////////////////////////////////////////
5318 ///
5319 
5321 {
5322  return 0;
5323 }
5324 
5325 ////////////////////////////////////////////////////////////////////////////////
5326 /// Get maximum number of planes.
5327 
5329 {
5330  return gdk_visual_get_best_depth();
5331 }
5332 
5333 ////////////////////////////////////////////////////////////////////////////////
5334 /// Return atom handle for atom_name. If it does not exist
5335 /// create it if only_if_exist is false. Atoms are used to communicate
5336 /// between different programs (i.e. window manager) via the X server.
5337 
5338 Atom_t TGWin32::InternAtom(const char *atom_name, Bool_t only_if_exist)
5339 {
5340  GdkAtom a = gdk_atom_intern((const gchar *) atom_name, only_if_exist);
5341 
5342  if (a == None) return kNone;
5343  return (Atom_t) a;
5344 }
5345 
5346 ////////////////////////////////////////////////////////////////////////////////
5347 /// Return handle to the default root window created when calling
5348 /// XOpenDisplay().
5349 
5351 {
5352  return (Window_t) GDK_ROOT_PARENT();
5353 }
5354 
5355 ////////////////////////////////////////////////////////////////////////////////
5356 /// Return the parent of the window.
5357 
5359 {
5360  if (!id) return (Window_t)0;
5361 
5362  return (Window_t)gdk_window_get_parent((GdkWindow *) id);
5363 }
5364 
5365 ////////////////////////////////////////////////////////////////////////////////
5366 /// Load font and query font. If font is not found 0 is returned,
5367 /// otherwise an opaque pointer to the FontStruct_t.
5368 /// Free the loaded font using DeleteFont().
5369 
5370 FontStruct_t TGWin32::LoadQueryFont(const char *font_name)
5371 {
5372  char family[100], weight[32], slant[32], fontname[256];
5373  Int_t n1, pixel, numfields;
5374 
5375  numfields = sscanf(font_name, "%s -%d%n", family, &pixel, &n1);
5376  if (numfields == 2) {
5377  sprintf(weight,"medium");
5378  if (strstr(font_name, "bold"))
5379  sprintf(weight,"bold");
5380  sprintf(slant,"r");
5381  if (strstr(font_name, "italic"))
5382  sprintf(slant,"i");
5383  sprintf(fontname, "-*-%s-%s-%s-*-*-%d-*-*-*-*-*-iso8859-1",
5384  family, weight, slant, pixel);
5385  }
5386  else
5387  sprintf(fontname, "%s", font_name);
5388  return (FontStruct_t) gdk_font_load(fontname);
5389 }
5390 
5391 ////////////////////////////////////////////////////////////////////////////////
5392 /// Return handle to font described by font structure.
5393 
5395 {
5396  if (fs) {
5397  return (FontH_t)gdk_font_ref((GdkFont *) fs);
5398  }
5399  return 0;
5400 }
5401 
5402 ////////////////////////////////////////////////////////////////////////////////
5403 /// Explicitely delete font structure obtained with LoadQueryFont().
5404 
5406 {
5407  gdk_font_unref((GdkFont *) fs);
5408 }
5409 
5410 ////////////////////////////////////////////////////////////////////////////////
5411 /// Create a graphics context using the values set in gval (but only for
5412 /// those entries that are in the mask).
5413 
5415 {
5416  if (!id) return (GContext_t)0;
5417 
5418  GdkGCValues xgval;
5419  ULong_t xmask = 0;
5420 
5421  if (gval) MapGCValues(*gval, xmask, xgval, kTRUE);
5422 
5423  xgval.subwindow_mode = GDK_CLIP_BY_CHILDREN; // GDK_INCLUDE_INFERIORS;
5424 
5425  GdkGC *gc = gdk_gc_new_with_values((GdkDrawable *) id,
5426  &xgval, (GdkGCValuesMask)xmask);
5427  return (GContext_t) gc;
5428 }
5429 
5430 ////////////////////////////////////////////////////////////////////////////////
5431 /// Change entries in an existing graphics context, gc, by values from gval.
5432 
5434 {
5435  GdkGCValues xgval;
5436  ULong_t xmask = 0;
5437  Mask_t mask = 0;
5438 
5439  if (gval) {
5440  mask = gval->fMask;
5441  MapGCValues(*gval, xmask, xgval, kTRUE);
5442  }
5443  if (mask & kGCForeground) {
5444  gdk_gc_set_foreground((GdkGC *) gc, &xgval.foreground);
5445  }
5446  if (mask & kGCBackground) {
5447  gdk_gc_set_background((GdkGC *) gc, &xgval.background);
5448  }
5449  if (mask & kGCFont) {
5450  gdk_gc_set_font((GdkGC *) gc, xgval.font);
5451  }
5452  if (mask & kGCFunction) {
5453  gdk_gc_set_function((GdkGC *) gc, xgval.function);
5454  }
5455  if (mask & kGCFillStyle) {
5456  gdk_gc_set_fill((GdkGC *) gc, xgval.fill);
5457  }
5458  if (mask & kGCTile) {
5459  gdk_gc_set_tile((GdkGC *) gc, xgval.tile);
5460  }
5461  if (mask & kGCStipple) {
5462  gdk_gc_set_stipple((GdkGC *) gc, xgval.stipple);
5463  }
5464  if ((mask & kGCTileStipXOrigin) || (mask & kGCTileStipYOrigin)) {
5465  gdk_gc_set_ts_origin((GdkGC *) gc, xgval.ts_x_origin,
5466  xgval.ts_y_origin);
5467  }
5468  if ((mask & kGCClipXOrigin) || (mask & kGCClipYOrigin)) {
5469  gdk_gc_set_clip_origin((GdkGC *) gc, xgval.clip_x_origin,
5470  xgval.clip_y_origin);
5471  }
5472  if (mask & kGCClipMask) {
5473  gdk_gc_set_clip_mask((GdkGC *) gc, xgval.clip_mask);
5474  }
5475  if (mask & kGCGraphicsExposures) {
5476  gdk_gc_set_exposures((GdkGC *) gc, xgval.graphics_exposures);
5477  }
5478  if (mask & kGCLineWidth) {
5479  gdk_gc_set_values((GdkGC *) gc, &xgval, GDK_GC_LINE_WIDTH);
5480  }
5481  if (mask & kGCLineStyle) {
5482  gdk_gc_set_values((GdkGC *) gc, &xgval, GDK_GC_LINE_STYLE);
5483  }
5484  if (mask & kGCCapStyle) {
5485  gdk_gc_set_values((GdkGC *) gc, &xgval, GDK_GC_CAP_STYLE);
5486  }
5487  if (mask & kGCJoinStyle) {
5488  gdk_gc_set_values((GdkGC *) gc, &xgval, GDK_GC_JOIN_STYLE);
5489  }
5490  if (mask & kGCSubwindowMode) {
5491  gdk_gc_set_subwindow((GdkGC *) gc, xgval.subwindow_mode);
5492  }
5493 }
5494 
5495 ////////////////////////////////////////////////////////////////////////////////
5496 /// Copies graphics context from org to dest. Only the values specified
5497 /// in mask are copied. Both org and dest must exist.
5498 
5500 {
5501  GCValues_t gval;
5502  GdkGCValues xgval;
5503  ULong_t xmask;
5504 
5505  if (!mask) {
5506  // in this case copy all fields
5507  mask = (Mask_t) - 1;
5508  }
5509 
5510  gval.fMask = mask; // only set fMask used to convert to xmask
5511  MapGCValues(gval, xmask, xgval, kTRUE);
5512 
5513  gdk_gc_copy((GdkGC *) dest, (GdkGC *) org);
5514 }
5515 
5516 ////////////////////////////////////////////////////////////////////////////////
5517 /// Explicitely delete a graphics context.
5518 
5520 {
5521  gdk_gc_unref((GdkGC *) gc);
5522 }
5523 
5524 ////////////////////////////////////////////////////////////////////////////////
5525 /// Create cursor handle (just return cursor from cursor pool fCursors).
5526 
5528 {
5529  return (Cursor_t) fCursors[cursor];
5530 }
5531 
5532 ////////////////////////////////////////////////////////////////////////////////
5533 /// Creates a pixmap of the width and height you specified
5534 /// and returns a pixmap ID that identifies it.
5535 
5537 {
5538  GdkWindow *wid = (GdkWindow *)id;
5539  if (!id) wid = GDK_ROOT_PARENT();
5540 
5541  return (Pixmap_t) gdk_pixmap_new(wid, w, h, gdk_visual_get_best_depth());
5542 }
5543 
5544 ////////////////////////////////////////////////////////////////////////////////
5545 /// Create a pixmap from bitmap data. Ones will get foreground color and
5546 /// zeroes background color.
5547 
5549  UInt_t width, UInt_t height,
5550  ULong_t forecolor, ULong_t backcolor,
5551  Int_t depth)
5552 {
5553  GdkColor fore, back;
5554  fore.pixel = forecolor;
5555  fore.red = GetRValue(forecolor);
5556  fore.green = GetGValue(forecolor);
5557  fore.blue = GetBValue(forecolor);
5558 
5559  back.pixel = backcolor;
5560  back.red = GetRValue(backcolor);
5561  back.green = GetGValue(backcolor);
5562  back.blue = GetBValue(backcolor);
5563 
5564  GdkWindow *wid = (GdkWindow *)id;
5565  if (!id) wid = GDK_ROOT_PARENT();
5566 
5567  return (Pixmap_t) gdk_pixmap_create_from_data(wid, (char *) bitmap, width,
5568  height, depth, &fore, &back);
5569 }
5570 
5571 ////////////////////////////////////////////////////////////////////////////////
5572 /// Create a bitmap (i.e. pixmap with depth 1) from the bitmap data.
5573 
5575  UInt_t width, UInt_t height)
5576 {
5577  GdkWindow *wid = (GdkWindow *)id;
5578  if (!id) wid = GDK_ROOT_PARENT();
5579 
5580  Pixmap_t ret = (Pixmap_t) gdk_bitmap_create_from_data(wid,
5581  (char *)bitmap, width, height);
5582  return ret;
5583 }
5584 
5585 ////////////////////////////////////////////////////////////////////////////////
5586 /// Explicitely delete pixmap resource.
5587 
5589 {
5590  gdk_pixmap_unref((GdkPixmap *) pmap);
5591 }
5592 
5593 ////////////////////////////////////////////////////////////////////////////////
5594 /// Create a picture pixmap from data on file. The picture attributes
5595 /// are used for input and output. Returns kTRUE in case of success,
5596 /// kFALSE otherwise. If mask does not exist it is set to kNone.
5597 
5599  Pixmap_t & pict,
5600  Pixmap_t & pict_mask,
5601  PictureAttributes_t & attr)
5602 {
5603  GdkBitmap *gdk_pixmap_mask;
5604  if (strstr(filename, ".xpm") || strstr(filename, ".XPM")) {
5605  GdkWindow *wid = (GdkWindow *)id;
5606  if (!id) wid = GDK_ROOT_PARENT();
5607 
5608  pict = (Pixmap_t) gdk_pixmap_create_from_xpm(wid, &gdk_pixmap_mask, 0,
5609  filename);
5610  pict_mask = (Pixmap_t) gdk_pixmap_mask;
5611  } else if (strstr(filename, ".gif") || strstr(filename, ".GIF")) {
5612  pict = ReadGIF(0, 0, filename, id);
5613  pict_mask = kNone;
5614  }
5615 
5616  gdk_drawable_get_size((GdkPixmap *) pict, (int *) &attr.fWidth,
5617  (int *) &attr.fHeight);
5618  if (pict) {
5619  return kTRUE;
5620  }
5621  if (pict_mask) {
5622  pict_mask = kNone;
5623  }
5624  return kFALSE;
5625 }
5626 
5627 ////////////////////////////////////////////////////////////////////////////////
5628 /// Create a pixture pixmap from data. The picture attributes
5629 /// are used for input and output. Returns kTRUE in case of success,
5630 /// kFALSE otherwise. If mask does not exist it is set to kNone.
5631 
5633  Pixmap_t & pict,
5634  Pixmap_t & pict_mask,
5635  PictureAttributes_t & attr)
5636 {
5637  GdkBitmap *gdk_pixmap_mask;
5638  GdkWindow *wid = (GdkWindow *)id;
5639  if (!id) wid = GDK_ROOT_PARENT();
5640 
5641  pict = (Pixmap_t) gdk_pixmap_create_from_xpm_d(wid, &gdk_pixmap_mask, 0,
5642  data);
5643  pict_mask = (Pixmap_t) gdk_pixmap_mask;
5644 
5645  if (pict) {
5646  return kTRUE;
5647  }
5648  if (pict_mask) {
5649  pict_mask = kNone;
5650  }
5651  return kFALSE;
5652 }
5653 
5654 ////////////////////////////////////////////////////////////////////////////////
5655 /// Read picture data from file and store in ret_data. Returns kTRUE in
5656 /// case of success, kFALSE otherwise.
5657 
5658 Bool_t TGWin32::ReadPictureDataFromFile(const char *filename, char ***ret_data)
5659 {
5660  Bool_t ret = kFALSE;
5661  GdkPixmap *pxm = gdk_pixmap_create_from_xpm(NULL, NULL, NULL, filename);
5662  ret_data = 0;
5663 
5664  if (pxm==NULL) return kFALSE;
5665 
5666  HBITMAP hbm = (HBITMAP)GDK_DRAWABLE_XID(pxm);
5667  BITMAP bitmap;
5668 
5669  ret = ::GetObject(hbm, sizeof(HBITMAP), (LPVOID)&bitmap);
5670  ret_data = (char ***)&bitmap.bmBits;
5671  gdk_pixmap_unref(pxm);
5672  return ret;
5673 }
5674 
5675 ////////////////////////////////////////////////////////////////////////////////
5676 /// Delete picture data created by the function ReadPictureDataFromFile.
5677 
5679 {
5680  free(data);
5681 }
5682 
5683 ////////////////////////////////////////////////////////////////////////////////
5684 /// Specify a dash pattertn. Offset defines the phase of the pattern.
5685 /// Each element in the dash_list array specifies the length (in pixels)
5686 /// of a segment of the pattern. N defines the length of the list.
5687 
5688 void TGWin32::SetDashes(GContext_t gc, Int_t offset, const char *dash_list,
5689  Int_t n)
5690 {
5691  int i;
5692  gint8 dashes[32];
5693  for (i = 0; i < n; i++) {
5694  dashes[i] = (gint8) dash_list[i];
5695  }
5696  for (i = n; i < 32; i++) {
5697  dashes[i] = (gint8) 0;
5698  }
5699 
5700  gdk_gc_set_dashes((GdkGC *) gc, offset, dashes, n);
5701 }
5702 
5703 ////////////////////////////////////////////////////////////////////////////////
5704 /// Map a ColorStruct_t to a XColor structure.
5705 
5706 void TGWin32::MapColorStruct(ColorStruct_t * color, GdkColor & xcolor)
5707 {
5708  xcolor.pixel = color->fPixel;
5709  xcolor.red = color->fRed;
5710  xcolor.green = color->fGreen;
5711  xcolor.blue = color->fBlue;
5712 }
5713 
5714 ////////////////////////////////////////////////////////////////////////////////
5715 /// Parse string cname containing color name, like "green" or "#00FF00".
5716 /// It returns a filled in ColorStruct_t. Returns kFALSE in case parsing
5717 /// failed, kTRUE in case of success. On success, the ColorStruct_t
5718 /// fRed, fGreen and fBlue fields are all filled in and the mask is set
5719 /// for all three colors, but fPixel is not set.
5720 
5721 Bool_t TGWin32::ParseColor(Colormap_t cmap, const char *cname,
5722  ColorStruct_t & color)
5723 {
5724  GdkColor xc;
5725 
5726  if (gdk_color_parse((char *)cname, &xc)) {
5727  color.fPixel = xc.pixel = RGB(xc.red, xc.green, xc.blue);
5728  color.fRed = xc.red;
5729  color.fGreen = xc.green;
5730  color.fBlue = xc.blue;
5731  return kTRUE;
5732  }
5733  return kFALSE;
5734 }
5735 
5736 ////////////////////////////////////////////////////////////////////////////////
5737 /// Find and allocate a color cell according to the color values specified
5738 /// in the ColorStruct_t. If no cell could be allocated it returns kFALSE,
5739 /// otherwise kTRUE.
5740 
5742 {
5743  int status;
5744  GdkColor xc;
5745 
5746  xc.red = color.fRed;
5747  xc.green = color.fGreen;
5748  xc.blue = color.fBlue;
5749 
5750  status = gdk_colormap_alloc_color((GdkColormap *) cmap, &xc, FALSE, TRUE);
5751  color.fPixel = xc.pixel;
5752 
5753  return kTRUE; // status != 0 ? kTRUE : kFALSE;
5754 }
5755 
5756 ////////////////////////////////////////////////////////////////////////////////
5757 /// Fill in the primary color components for a specific pixel value.
5758 /// On input fPixel should be set on return the fRed, fGreen and
5759 /// fBlue components will be set.
5760 
5762 {
5763  GdkColor xc;
5764  xc.pixel = color.fPixel;
5765 
5766  GdkColorContext *cc = gdk_color_context_new(gdk_visual_get_system(), fColormap);
5767  gdk_color_context_query_color(cc, &xc);
5768  gdk_color_context_free(cc);
5769 
5770  color.fPixel = xc.pixel;
5771  color.fRed = xc.red;
5772  color.fGreen = xc.green;
5773  color.fBlue = xc.blue;
5774 }
5775 
5776 ////////////////////////////////////////////////////////////////////////////////
5777 /// Free color cell with specified pixel value.
5778 
5780 {
5781  // FIXME: to be implemented.
5782 }
5783 
5784 ////////////////////////////////////////////////////////////////////////////////
5785 /// Check if there is for window "id" an event of type "type". If there
5786 /// is fill in the event structure and return true. If no such event
5787 /// return false.
5788 
5790 {
5791  if (!id) return kFALSE;
5792 
5793  Event_t tev;
5794  GdkEvent xev;
5795 
5796  tev.fType = type;
5797  tev.fWindow = (Window_t) id;
5798  tev.fTime = 0;
5799  tev.fX = tev.fY = 0;
5800  tev.fXRoot = tev.fYRoot = 0;
5801  tev.fCode = 0;
5802  tev.fState = 0;
5803  tev.fWidth = tev.fHeight = 0;
5804  tev.fCount = 0;
5805  tev.fSendEvent = kFALSE;
5806  tev.fHandle = 0;
5807  tev.fFormat = 0;
5808  tev.fUser[0] = tev.fUser[1] = tev.fUser[2] = tev.fUser[3] = tev.fUser[4] = 0L;
5809 
5810  TGWin32MainThread::LockMSG();
5811  MapEvent(tev, xev, kTRUE);
5812  Bool_t r = gdk_check_typed_window_event((GdkWindow *) id, xev.type, &xev);
5813 
5814  if (r) MapEvent(ev, xev, kFALSE);
5815  TGWin32MainThread::UnlockMSG();
5816 
5817  return r ? kTRUE : kFALSE;
5818 }
5819 
5820 ////////////////////////////////////////////////////////////////////////////////
5821 /// Send event ev to window id.
5822 
5824 {
5825  if (!ev || !id) return;
5826 
5827  TGWin32MainThread::LockMSG();
5828  GdkEvent xev;
5829  MapEvent(*ev, xev, kTRUE);
5830  gdk_event_put(&xev);
5831  TGWin32MainThread::UnlockMSG();
5832 }
5833 
5834 ////////////////////////////////////////////////////////////////////////////////
5835 /// Returns number of pending events.
5836 
5838 {
5839  Int_t ret;
5840 
5841  TGWin32MainThread::LockMSG();
5842  ret = (Int_t)gdk_event_queue_find_first();
5843  TGWin32MainThread::UnlockMSG();
5844 
5845  return ret;
5846 }
5847 
5848 ////////////////////////////////////////////////////////////////////////////////
5849 /// Copies first pending event from event queue to Event_t structure
5850 /// and removes event from queue. Not all of the event fields are valid
5851 /// for each event type, except fType and fWindow.
5852 
5854 {
5855  TGWin32MainThread::LockMSG();
5856  GdkEvent *xev = gdk_event_unqueue();
5857 
5858