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