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