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