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