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