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
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:
1663 break;
1664
1665 case kFilled:
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
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) {
1746 } else {
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) {
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
1875 gMarker.n, gMarker.n, 0, 23040);
1876 break;
1877
1878 case 1: // filled circle
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) {
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;
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);
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 =
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:
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);
2716 SetColor(gGCpxmp, 1);
2717
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
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);
3073 gTws->height);
3074 SetColor(gGCpxmp, 1);
3075 }
3076 for (int i = 0; i < kMAXGC; i++) {
3077 gdk_gc_set_clip_mask(gGClist[i], None);
3078 }
3079 gTws->double_buffer = 1;
3080 gTws->drawing = gTws->buffer;
3081}
3082
3083////////////////////////////////////////////////////////////////////////////////
3084/// Set the drawing mode.
3085/// mode : drawing mode
3086/// mode=1 copy
3087/// mode=2 xor
3088/// mode=3 invert
3089/// mode=4 set the suitable mode for cursor echo according to
3090/// the vendor
3091
3093{
3094 int i;
3095
3096 switch (mode) {
3097 case kCopy:
3098 for (i = 0; i < kMAXGC; i++) {
3099 gdk_gc_set_function(gGClist[i], GDK_COPY);
3100 }
3101 break;
3102
3103 case kXor:
3104 for (i = 0; i < kMAXGC; i++) {
3105 gdk_gc_set_function(gGClist[i], GDK_XOR);
3106 }
3107 break;
3108
3109 case kInvert:
3110 for (i = 0; i < kMAXGC; i++) {
3111 gdk_gc_set_function(gGClist[i], GDK_INVERT);
3112 }
3113 break;
3114 }
3115 fDrawMode = mode;
3116}
3117
3118////////////////////////////////////////////////////////////////////////////////
3119/// Set color index for fill areas.
3120
3122{
3123 Int_t indx = Int_t(cindex);
3124
3125 if (!gStyle->GetFillColor() && cindex > 1) {
3126 indx = 0;
3127 }
3128
3129 fFillColor = indx;
3131}
3132
3133////////////////////////////////////////////////////////////////////////////////
3134///
3135
3137{
3138 if (fFillColor >= 0) {
3140 }
3141
3142 // invalidate fill pattern
3143 if (gFillPattern != NULL) {
3144 gdk_pixmap_unref(gFillPattern);
3145 gFillPattern = NULL;
3146 }
3148}
3149
3150////////////////////////////////////////////////////////////////////////////////
3151/// Set fill area style.
3152/// fstyle : compound fill area interior style
3153/// fstyle = 1000*interiorstyle + styleindex
3154
3156{
3157 if (fFillStyle==fstyle) return;
3158
3159 fFillStyle = fstyle;
3161}
3162
3163////////////////////////////////////////////////////////////////////////////////
3164/// Set fill area style index.
3165
3167{
3168 static int current_fasi = 0;
3169
3170 Int_t style = fFillStyle / 1000;
3171 Int_t fasi = fFillStyle % 1000;
3172
3173 switch (style) {
3174
3175 case 1: // solid
3176 gFillHollow = 0;
3177 gdk_gc_set_fill(gGCfill, GDK_SOLID);
3178 break;
3179
3180 case 2: // pattern
3181 gFillHollow = 1;
3182 break;
3183
3184 case 3: // hatch
3185 gFillHollow = 0;
3186 gdk_gc_set_fill(gGCfill, GDK_STIPPLED);
3187
3188 if (fasi != current_fasi) {
3189 if (gFillPattern != NULL) {
3190 gdk_pixmap_unref(gFillPattern);
3191 gFillPattern = NULL;
3192 }
3193 int stn = (fasi >= 1 && fasi <=25) ? fasi : 2;
3194 char pattern[32];
3195 for (int i=0;i<32;++i)
3196 pattern[i] = ~gStipples[stn][i];
3197 gFillPattern = gdk_bitmap_create_from_data(GDK_ROOT_PARENT(),
3198 (const char *)&pattern, 16, 16);
3199 gdk_gc_set_stipple(gGCfill, gFillPattern);
3200 current_fasi = fasi;
3201 }
3202 break;
3203
3204 default:
3205 gFillHollow = 1;
3206 }
3207
3209}
3210
3211////////////////////////////////////////////////////////////////////////////////
3212/// Set input on or off.
3213
3215{
3216 EnableWindow((HWND) GDK_DRAWABLE_XID(gCws->window), inp);
3217}
3218
3219////////////////////////////////////////////////////////////////////////////////
3220/// Set color index for lines.
3221
3223{
3224 if ((cindex < 0) || (cindex==fLineColor)) return;
3225
3226 fLineColor = cindex;
3228}
3229
3230////////////////////////////////////////////////////////////////////////////////
3231///
3232
3234{
3238}
3239
3240////////////////////////////////////////////////////////////////////////////////
3241/// Set line type.
3242/// n : length of dash list
3243/// dash(n) : dash segment lengths
3244///
3245/// if n <= 0 use solid lines
3246/// if n > 0 use dashed lines described by DASH(N)
3247/// e.g. N=4,DASH=(6,3,1,3) gives a dashed-dotted line with dash length 6
3248/// and a gap of 7 between dashes
3249
3250void TGWin32::SetLineType(int n, int *dash)
3251{
3252 if (n <= 0) {
3253 gLineStyle = GDK_LINE_SOLID;
3254 gdk_gc_set_line_attributes(gGCline, gLineWidth,
3255 (GdkLineStyle)gLineStyle,
3256 (GdkCapStyle) gCapStyle,
3257 (GdkJoinStyle) gJoinStyle);
3258 } else {
3259 int i;
3260 gDashSize = TMath::Min((int)sizeof(gDashList),n);
3261 gDashLength = 0;
3262 for (i = 0; i < gDashSize; i++) {
3263 gDashList[i] = dash[i];
3264 gDashLength += gDashList[i];
3265 }
3266 gDashOffset = 0;
3267 gLineStyle = GDK_LINE_ON_OFF_DASH;
3268 if (gLineWidth == 0) gLineWidth =1;
3269 gdk_gc_set_line_attributes(gGCdash, gLineWidth,
3270 (GdkLineStyle) gLineStyle,
3271 (GdkCapStyle) gCapStyle,
3272 (GdkJoinStyle) gJoinStyle);
3273 }
3275}
3276
3277////////////////////////////////////////////////////////////////////////////////
3278/// Set line style.
3279
3281{
3282 if (fLineStyle == lstyle) return;
3283
3284 fLineStyle = lstyle;
3286}
3287
3288////////////////////////////////////////////////////////////////////////////////
3289/// Update line style
3290
3292{
3293 static Int_t dashed[2] = { 3, 3 };
3294 static Int_t dotted[2] = { 1, 2 };
3295 static Int_t dasheddotted[4] = { 3, 4, 1, 4 };
3296
3297 if (fLineStyle <= 1) {
3298 SetLineType(0, 0);
3299 } else if (fLineStyle == 2) {
3300 SetLineType(2, dashed);
3301 } else if (fLineStyle == 3) {
3302 SetLineType(2, dotted);
3303 } else if (fLineStyle == 4) {
3304 SetLineType(4, dasheddotted);
3305 } else {
3307 TObjArray *tokens = st.Tokenize(" ");
3308 Int_t nt;
3309 nt = tokens->GetEntries();
3310 Int_t *linestyle = new Int_t[nt];
3311 for (Int_t j = 0; j<nt; j++) {
3312 Int_t it;
3313 sscanf(((TObjString*)tokens->At(j))->GetName(), "%d", &it);
3314 linestyle[j] = (Int_t)(it/4);
3315 }
3316 SetLineType(nt,linestyle);
3317 delete [] linestyle;
3318 delete tokens;
3319 }
3321}
3322
3323////////////////////////////////////////////////////////////////////////////////
3324/// Set line width.
3325/// width : line width in pixels
3326
3328{
3329 if (fLineWidth == width) return;
3330 fLineWidth = width;
3331
3332 if (width == 1 && gLineStyle == GDK_LINE_SOLID) gLineWidth = 0;
3333 else gLineWidth = width;
3334
3336}
3337
3338////////////////////////////////////////////////////////////////////////////////
3339/// Set color index for markers.
3340
3342{
3343 if ((cindex<0) || (cindex==fMarkerColor)) return;
3344 fMarkerColor = cindex;
3346}
3347
3348////////////////////////////////////////////////////////////////////////////////
3349///
3350
3352{
3355}
3356
3357////////////////////////////////////////////////////////////////////////////////
3358/// Set marker size index.
3359/// msize : marker scale factor
3360
3362{
3363 if ((msize==fMarkerSize) || (msize<0)) return;
3364
3365 fMarkerSize = msize;
3367}
3368
3369////////////////////////////////////////////////////////////////////////////////
3370/// Set marker type.
3371/// type : marker type
3372/// n : length of marker description
3373/// xy : list of points describing marker shape
3374///
3375/// if n == 0 marker is a single point
3376/// if TYPE == 0 marker is hollow circle of diameter N
3377/// if TYPE == 1 marker is filled circle of diameter N
3378/// if TYPE == 2 marker is a hollow polygon describe by line XY
3379/// if TYPE == 3 marker is a filled polygon describe by line XY
3380/// if TYPE == 4 marker is described by segmented line XY
3381/// e.g. TYPE=4,N=4,XY=(-3,0,3,0,0,-3,0,3) sets a plus shape of 7x7 pixels
3382
3383void TGWin32::SetMarkerType(int type, int n, GdkPoint * xy)
3384{
3385 gMarker.type = type;
3386 gMarker.n = n < kMAXMK ? n : kMAXMK;
3387 if (gMarker.type >= 2) {
3388 for (int i = 0; i < gMarker.n; i++) {
3389 gMarker.xy[i] = xy[i];
3390 }
3391 }
3392}
3393
3394////////////////////////////////////////////////////////////////////////////////
3395/// Set marker style.
3396
3398{
3399 if (fMarkerStyle == markerstyle) return;
3400 fMarkerStyle = TMath::Abs(markerstyle);
3402}
3403
3404////////////////////////////////////////////////////////////////////////////////
3405///
3406
3408{
3411
3412 // The fast pixel markers need to be treated separately
3413 if (markerstyle == 1 || markerstyle == 6 || markerstyle == 7) {
3414 gdk_gc_set_line_attributes(gGCmark, 0, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
3415 } else {
3416 gdk_gc_set_line_attributes(gGCmark, gMarkerLineWidth,
3417 (GdkLineStyle) gMarkerLineStyle,
3418 (GdkCapStyle) gMarkerCapStyle,
3419 (GdkJoinStyle) gMarkerJoinStyle);
3420 }
3421
3422 static GdkPoint shape[30];
3423
3424 Float_t MarkerSizeReduced = fMarkerSize - TMath::Floor(gMarkerLineWidth/2.)/4.;
3425 Int_t im = Int_t(4 * MarkerSizeReduced + 0.5);
3426
3427 if (markerstyle == 2) {
3428 // + shaped marker
3429 shape[0].x = -im;
3430 shape[0].y = 0;
3431 shape[1].x = im;
3432 shape[1].y = 0;
3433 shape[2].x = 0;
3434 shape[2].y = -im;
3435 shape[3].x = 0;
3436 shape[3].y = im;
3437 SetMarkerType(4, 4, shape);
3438 } else if (markerstyle == 3 || markerstyle == 31) {
3439 // * shaped marker
3440 shape[0].x = -im;
3441 shape[0].y = 0;
3442 shape[1].x = im;
3443 shape[1].y = 0;
3444 shape[2].x = 0;
3445 shape[2].y = -im;
3446 shape[3].x = 0;
3447 shape[3].y = im;
3448 im = Int_t(0.707 * Float_t(im) + 0.5);
3449 shape[4].x = -im;
3450 shape[4].y = -im;
3451 shape[5].x = im;
3452 shape[5].y = im;
3453 shape[6].x = -im;
3454 shape[6].y = im;
3455 shape[7].x = im;
3456 shape[7].y = -im;
3457 SetMarkerType(4, 8, shape);
3458 } else if (markerstyle == 4 || markerstyle == 24) {
3459 // O shaped marker
3460 SetMarkerType(0, im * 2, shape);
3461 } else if (markerstyle == 5) {
3462 // X shaped marker
3463 im = Int_t(0.707 * Float_t(im) + 0.5);
3464 shape[0].x = -im;
3465 shape[0].y = -im;
3466 shape[1].x = im;
3467 shape[1].y = im;
3468 shape[2].x = -im;
3469 shape[2].y = im;
3470 shape[3].x = im;
3471 shape[3].y = -im;
3472 SetMarkerType(4, 4, shape);
3473 } else if (markerstyle == 6) {
3474 // + shaped marker (with 1 pixel)
3475 shape[0].x = -1;
3476 shape[0].y = 0;
3477 shape[1].x = 1;
3478 shape[1].y = 0;
3479 shape[2].x = 0;
3480 shape[2].y = -1;
3481 shape[3].x = 0;
3482 shape[3].y = 1;
3483 SetMarkerType(4, 4, shape);
3484 } else if (markerstyle == 7) {
3485 // . shaped marker (with 9 pixel)
3486 shape[0].x = -1;
3487 shape[0].y = 1;
3488 shape[1].x = 1;
3489 shape[1].y = 1;
3490 shape[2].x = -1;
3491 shape[2].y = 0;
3492 shape[3].x = 1;
3493 shape[3].y = 0;
3494 shape[4].x = -1;
3495 shape[4].y = -1;
3496 shape[5].x = 1;
3497 shape[5].y = -1;
3498 SetMarkerType(4, 6, shape);
3499 } else if (markerstyle == 8 || markerstyle == 20) {
3500 // O shaped marker (filled)
3501 SetMarkerType(1, im * 2, shape);
3502 } else if (markerstyle == 21) {
3503 // full square
3504 shape[0].x = -im;
3505 shape[0].y = -im;
3506 shape[1].x = im;
3507 shape[1].y = -im;
3508 shape[2].x = im;
3509 shape[2].y = im;
3510 shape[3].x = -im;
3511 shape[3].y = im;
3512 shape[4].x = -im;
3513 shape[4].y = -im;
3514 SetMarkerType(3, 5, shape);
3515 } else if (markerstyle == 22) {
3516 // full triangle up
3517 shape[0].x = -im;
3518 shape[0].y = im;
3519 shape[1].x = im;
3520 shape[1].y = im;
3521 shape[2].x = 0;
3522 shape[2].y = -im;
3523 shape[3].x = -im;
3524 shape[3].y = im;
3525 SetMarkerType(3, 4, shape);
3526 } else if (markerstyle == 23) {
3527 // full triangle down
3528 shape[0].x = 0;
3529 shape[0].y = im;
3530 shape[1].x = im;
3531 shape[1].y = -im;
3532 shape[2].x = -im;
3533 shape[2].y = -im;
3534 shape[3].x = 0;
3535 shape[3].y = im;
3536 SetMarkerType(3, 4, shape);
3537 } else if (markerstyle == 25) {
3538 // open square
3539 shape[0].x = -im;
3540 shape[0].y = -im;
3541 shape[1].x = im;
3542 shape[1].y = -im;
3543 shape[2].x = im;
3544 shape[2].y = im;
3545 shape[3].x = -im;
3546 shape[3].y = im;
3547 shape[4].x = -im;
3548 shape[4].y = -im;
3549 SetMarkerType(2, 5, shape);
3550 } else if (markerstyle == 26) {
3551 // open triangle up
3552 shape[0].x = -im;
3553 shape[0].y = im;
3554 shape[1].x = im;
3555 shape[1].y = im;
3556 shape[2].x = 0;
3557 shape[2].y = -im;
3558 shape[3].x = -im;
3559 shape[3].y = im;
3560 SetMarkerType(2, 4, shape);
3561 } else if (markerstyle == 27) {
3562 // open losange
3563 Int_t imx = Int_t(2.66 * MarkerSizeReduced + 0.5);
3564 shape[0].x = -imx;
3565 shape[0].y = 0;
3566 shape[1].x = 0;
3567 shape[1].y = -im;
3568 shape[2].x = imx;
3569 shape[2].y = 0;
3570 shape[3].x = 0;
3571 shape[3].y = im;
3572 shape[4].x = -imx;
3573 shape[4].y = 0;
3574 SetMarkerType(2, 5, shape);
3575 } else if (markerstyle == 28) {
3576 // open cross
3577 Int_t imx = Int_t(1.33 * MarkerSizeReduced + 0.5);
3578 shape[0].x = -im;
3579 shape[0].y = -imx;
3580 shape[1].x = -imx;
3581 shape[1].y = -imx;
3582 shape[2].x = -imx;
3583 shape[2].y = -im;
3584 shape[3].x = imx;
3585 shape[3].y = -im;
3586 shape[4].x = imx;
3587 shape[4].y = -imx;
3588 shape[5].x = im;
3589 shape[5].y = -imx;
3590 shape[6].x = im;
3591 shape[6].y = imx;
3592 shape[7].x = imx;
3593 shape[7].y = imx;
3594 shape[8].x = imx;
3595 shape[8].y = im;
3596 shape[9].x = -imx;
3597 shape[9].y = im;
3598 shape[10].x = -imx;
3599 shape[10].y = imx;
3600 shape[11].x = -im;
3601 shape[11].y = imx;
3602 shape[12].x = -im;
3603 shape[12].y = -imx;
3604 SetMarkerType(2, 13, shape);
3605 } else if (markerstyle == 29) {
3606 // full star pentagone
3607 Int_t im1 = Int_t(0.66 * MarkerSizeReduced + 0.5);
3608 Int_t im2 = Int_t(2.00 * MarkerSizeReduced + 0.5);
3609 Int_t im3 = Int_t(2.66 * MarkerSizeReduced + 0.5);
3610 Int_t im4 = Int_t(1.33 * MarkerSizeReduced + 0.5);
3611 shape[0].x = -im;
3612 shape[0].y = im4;
3613 shape[1].x = -im2;
3614 shape[1].y = -im1;
3615 shape[2].x = -im3;
3616 shape[2].y = -im;
3617 shape[3].x = 0;
3618 shape[3].y = -im2;
3619 shape[4].x = im3;
3620 shape[4].y = -im;
3621 shape[5].x = im2;
3622 shape[5].y = -im1;
3623 shape[6].x = im;
3624 shape[6].y = im4;
3625 shape[7].x = im4;
3626 shape[7].y = im4;
3627 shape[8].x = 0;
3628 shape[8].y = im;
3629 shape[9].x = -im4;
3630 shape[9].y = im4;
3631 shape[10].x = -im;
3632 shape[10].y = im4;
3633 SetMarkerType(3, 11, shape);
3634 } else if (markerstyle == 30) {
3635 // open star pentagone
3636 Int_t im1 = Int_t(0.66 * MarkerSizeReduced + 0.5);
3637 Int_t im2 = Int_t(2.00 * MarkerSizeReduced + 0.5);
3638 Int_t im3 = Int_t(2.66 * MarkerSizeReduced + 0.5);
3639 Int_t im4 = Int_t(1.33 * MarkerSizeReduced + 0.5);
3640 shape[0].x = -im;
3641 shape[0].y = im4;
3642 shape[1].x = -im2;
3643 shape[1].y = -im1;
3644 shape[2].x = -im3;
3645 shape[2].y = -im;
3646 shape[3].x = 0;
3647 shape[3].y = -im2;
3648 shape[4].x = im3;
3649 shape[4].y = -im;
3650 shape[5].x = im2;
3651 shape[5].y = -im1;
3652 shape[6].x = im;
3653 shape[6].y = im4;
3654 shape[7].x = im4;
3655 shape[7].y = im4;
3656 shape[8].x = 0;
3657 shape[8].y = im;
3658 shape[9].x = -im4;
3659 shape[9].y = im4;
3660 shape[10].x = -im;
3661 shape[10].y = im4;
3662 SetMarkerType(2, 11, shape);
3663 } else if (markerstyle == 32) {
3664 // open triangle down
3665 shape[0].x = 0; shape[0].y = im;
3666 shape[1].x = im; shape[1].y = -im;
3667 shape[2].x = -im; shape[2].y = -im;
3668 shape[3].x = 0; shape[3].y = im;
3669 SetMarkerType(2,4,shape);
3670 } else if (markerstyle == 33) {
3671 // full losange
3672 Int_t imx = Int_t(2.66*MarkerSizeReduced + 0.5);
3673 shape[0].x =-imx; shape[0].y = 0;
3674 shape[1].x = 0; shape[1].y = -im;
3675 shape[2].x = imx; shape[2].y = 0;
3676 shape[3].x = 0; shape[3].y = im;
3677 shape[4].x =-imx; shape[4].y = 0;
3678 SetMarkerType(3,5,shape);
3679 } else if (markerstyle == 34) {
3680 // full cross
3681 Int_t imx = Int_t(1.33*MarkerSizeReduced + 0.5);
3682 shape[0].x = -im; shape[0].y =-imx;
3683 shape[1].x =-imx; shape[1].y =-imx;
3684 shape[2].x =-imx; shape[2].y = -im;
3685 shape[3].x = imx; shape[3].y = -im;
3686 shape[4].x = imx; shape[4].y =-imx;
3687 shape[5].x = im; shape[5].y =-imx;
3688 shape[6].x = im; shape[6].y = imx;
3689 shape[7].x = imx; shape[7].y = imx;
3690 shape[8].x = imx; shape[8].y = im;
3691 shape[9].x =-imx; shape[9].y = im;
3692 shape[10].x=-imx; shape[10].y= imx;
3693 shape[11].x= -im; shape[11].y= imx;
3694 shape[12].x= -im; shape[12].y=-imx;
3695 SetMarkerType(3,13,shape);
3696 } else if (markerstyle == 35) {
3697 // square with diagonal cross
3698 shape[0].x = -im; shape[0].y = -im;
3699 shape[1].x = im; shape[1].y = -im;
3700 shape[2].x = im; shape[2].y = im;
3701 shape[3].x = -im; shape[3].y = im;
3702 shape[4].x = -im; shape[4].y = -im;
3703 shape[5].x = im; shape[5].y = im;
3704 shape[6].x = -im; shape[6].y = im;
3705 shape[7].x = im; shape[7].y = -im;
3706 SetMarkerType(2,8,shape);
3707 } else if (markerstyle == 36) {
3708 // diamond with cross
3709 shape[0].x =-im; shape[0].y = 0;
3710 shape[1].x = 0; shape[1].y = -im;
3711 shape[2].x = im; shape[2].y = 0;
3712 shape[3].x = 0; shape[3].y = im;
3713 shape[4].x =-im; shape[4].y = 0;
3714 shape[5].x = im; shape[5].y = 0;
3715 shape[6].x = 0; shape[6].y = im;
3716 shape[7].x = 0; shape[7].y =-im;
3717 SetMarkerType(2,8,shape);
3718 } else if (markerstyle == 37) {
3719 // open three triangles
3720 Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5);
3721 shape[0].x = 0; shape[0].y = 0;
3722 shape[1].x =-im2; shape[1].y = im;
3723 shape[2].x = -im; shape[2].y = 0;
3724 shape[3].x = 0; shape[3].y = 0;
3725 shape[4].x =-im2; shape[4].y = -im;
3726 shape[5].x = im2; shape[5].y = -im;
3727 shape[6].x = 0; shape[6].y = 0;
3728 shape[7].x = im; shape[7].y = 0;
3729 shape[8].x = im2; shape[8].y = im;
3730 shape[9].x = 0; shape[9].y = 0;
3731 SetMarkerType(2,10,shape);
3732 } else if (markerstyle == 38) {
3733 // + shaped marker with octagon
3734 Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5);
3735 shape[0].x = -im; shape[0].y = 0;
3736 shape[1].x = -im; shape[1].y =-im2;
3737 shape[2].x =-im2; shape[2].y =-im;
3738 shape[3].x = im2; shape[3].y = -im;
3739 shape[4].x = im; shape[4].y =-im2;
3740 shape[5].x = im; shape[5].y = im2;
3741 shape[6].x = im2; shape[6].y = im;
3742 shape[7].x =-im2; shape[7].y = im;
3743 shape[8].x = -im; shape[8].y = im2;
3744 shape[9].x = -im; shape[9].y = 0;
3745 shape[10].x = im; shape[10].y = 0;
3746 shape[11].x = 0; shape[11].y = 0;
3747 shape[12].x = 0; shape[12].y = -im;
3748 shape[13].x = 0; shape[13].y = im;
3749 shape[14].x = 0; shape[14].y = 0;
3750 SetMarkerType(2,15,shape);
3751 } else if (markerstyle == 39) {
3752 // filled three triangles
3753 Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5);
3754 shape[0].x = 0; shape[0].y = 0;
3755 shape[1].x =-im2; shape[1].y = im;
3756 shape[2].x = -im; shape[2].y = 0;
3757 shape[3].x = 0; shape[3].y = 0;
3758 shape[4].x =-im2; shape[4].y = -im;
3759 shape[5].x = im2; shape[5].y = -im;
3760 shape[6].x = 0; shape[6].y = 0;
3761 shape[7].x = im; shape[7].y = 0;
3762 shape[8].x = im2; shape[8].y = im;
3763 SetMarkerType(3,9,shape);
3764 } else if (markerstyle == 40) {
3765 // four open triangles X
3766 Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5);
3767 shape[0].x = 0; shape[0].y = 0;
3768 shape[1].x = im2; shape[1].y = im;
3769 shape[2].x = im; shape[2].y = im2;
3770 shape[3].x = 0; shape[3].y = 0;
3771 shape[4].x = im; shape[4].y = -im2;
3772 shape[5].x = im2; shape[5].y = -im;
3773 shape[6].x = 0; shape[6].y = 0;
3774 shape[7].x = -im2; shape[7].y = -im;
3775 shape[8].x = -im; shape[8].y = -im2;
3776 shape[9].x = 0; shape[9].y = 0;
3777 shape[10].x = -im; shape[10].y = im2;
3778 shape[11].x = -im2; shape[11].y = im;
3779 shape[12].x = 0; shape[12].y = 0;
3780 SetMarkerType(2,13,shape);
3781 } else if (markerstyle == 41) {
3782 // four filled triangles X
3783 Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5);
3784 shape[0].x = 0; shape[0].y = 0;
3785 shape[1].x = im2; shape[1].y = im;
3786 shape[2].x = im; shape[2].y = im2;
3787 shape[3].x = 0; shape[3].y = 0;
3788 shape[4].x = im; shape[4].y = -im2;
3789 shape[5].x = im2; shape[5].y = -im;
3790 shape[6].x = 0; shape[6].y = 0;
3791 shape[7].x = -im2; shape[7].y = -im;
3792 shape[8].x = -im; shape[8].y = -im2;
3793 shape[9].x = 0; shape[9].y = 0;
3794 shape[10].x = -im; shape[10].y = im2;
3795 shape[11].x = -im2; shape[11].y = im;
3796 shape[12].x = 0; shape[12].y = 0;
3797 SetMarkerType(3,13,shape);
3798 } else if (markerstyle == 42) {
3799 // open double diamonds
3800 Int_t imx = Int_t(MarkerSizeReduced + 0.5);
3801 shape[0].x= 0; shape[0].y= im;
3802 shape[1].x= -imx; shape[1].y= imx;
3803 shape[2].x = -im; shape[2].y = 0;
3804 shape[3].x = -imx; shape[3].y = -imx;
3805 shape[4].x = 0; shape[4].y = -im;
3806 shape[5].x = imx; shape[5].y = -imx;
3807 shape[6].x = im; shape[6].y = 0;
3808 shape[7].x= imx; shape[7].y= imx;
3809 shape[8].x= 0; shape[8].y= im;
3810 SetMarkerType(2,9,shape);
3811 } else if (markerstyle == 43) {
3812 // filled double diamonds
3813 Int_t imx = Int_t(MarkerSizeReduced + 0.5);
3814 shape[0].x = 0; shape[0].y = im;
3815 shape[1].x = -imx; shape[1].y = imx;
3816 shape[2].x = -im; shape[2].y = 0;
3817 shape[3].x = -imx; shape[3].y = -imx;
3818 shape[4].x = 0; shape[4].y = -im;
3819 shape[5].x = imx; shape[5].y = -imx;
3820 shape[6].x = im; shape[6].y = 0;
3821 shape[7].x = imx; shape[7].y = imx;
3822 shape[8].x = 0; shape[8].y = im;
3823 SetMarkerType(3,9,shape);
3824 } else if (markerstyle == 44) {
3825 // open four triangles plus
3826 Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5);
3827 shape[0].x = 0; shape[0].y = 0;
3828 shape[1].x = im2; shape[1].y = im;
3829 shape[2].x = -im2; shape[2].y = im;
3830 shape[3].x = im2; shape[3].y = -im;
3831 shape[4].x = -im2; shape[4].y = -im;
3832 shape[5].x = 0; shape[5].y = 0;
3833 shape[6].x = im; shape[6].y = im2;
3834 shape[7].x = im; shape[7].y = -im2;
3835 shape[8].x = -im; shape[8].y = im2;
3836 shape[9].x = -im; shape[9].y = -im2;
3837 shape[10].x = 0; shape[10].y = 0;
3838 SetMarkerType(2,11,shape);
3839 } else if (markerstyle == 45) {
3840 // filled four triangles plus
3841 Int_t im0 = Int_t(0.4*MarkerSizeReduced + 0.5);
3842 Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5);
3843 shape[0].x = im0; shape[0].y = im0;
3844 shape[1].x = im2; shape[1].y = im;
3845 shape[2].x = -im2; shape[2].y = im;
3846 shape[3].x = -im0; shape[3].y = im0;
3847 shape[4].x = -im; shape[4].y = im2;
3848 shape[5].x = -im; shape[5].y = -im2;
3849 shape[6].x = -im0; shape[6].y = -im0;
3850 shape[7].x = -im2; shape[7].y = -im;
3851 shape[8].x = im2; shape[8].y = -im;
3852 shape[9].x = im0; shape[9].y = -im0;
3853 shape[10].x = im; shape[10].y = -im2;
3854 shape[11].x = im; shape[11].y = im2;
3855 shape[12].x = im0; shape[12].y = im0;
3856 SetMarkerType(3,13,shape);
3857 } else if (markerstyle == 46) {
3858 // open four triangles X
3859 Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5);
3860 shape[0].x = 0; shape[0].y = im2;
3861 shape[1].x = -im2; shape[1].y = im;
3862 shape[2].x = -im; shape[2].y = im2;
3863 shape[3].x = -im2; shape[3].y = 0;
3864 shape[4].x = -im; shape[4].y = -im2;
3865 shape[5].x = -im2; shape[5].y = -im;
3866 shape[6].x = 0; shape[6].y = -im2;
3867 shape[7].x = im2; shape[7].y = -im;
3868 shape[8].x = im; shape[8].y = -im2;
3869 shape[9].x = im2; shape[9].y = 0;
3870 shape[10].x = im; shape[10].y = im2;
3871 shape[11].x = im2; shape[11].y = im;
3872 shape[12].x = 0; shape[12].y = im2;
3873 SetMarkerType(2,13,shape);
3874 } else if (markerstyle == 47) {
3875 // filled four triangles X
3876 Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5);
3877 shape[0].x = 0; shape[0].y = im2;
3878 shape[1].x = -im2; shape[1].y = im;
3879 shape[2].x = -im; shape[2].y = im2;
3880 shape[3].x = -im2; shape[3].y = 0;
3881 shape[4].x = -im; shape[4].y = -im2;
3882 shape[5].x = -im2; shape[5].y = -im;
3883 shape[6].x = 0; shape[6].y = -im2;
3884 shape[7].x = im2; shape[7].y = -im;
3885 shape[8].x = im; shape[8].y = -im2;
3886 shape[9].x = im2; shape[9].y = 0;
3887 shape[10].x = im; shape[10].y = im2;
3888 shape[11].x = im2; shape[11].y = im;
3889 shape[12].x = 0; shape[12].y = im2;
3890 SetMarkerType(3,13,shape);
3891 } else if (markerstyle == 48) {
3892 // four filled squares X
3893 Int_t im2 = Int_t(2.0*MarkerSizeReduced + 0.5);
3894 shape[0].x = 0; shape[0].y = im2*1.005;
3895 shape[1].x = -im2; shape[1].y = im;
3896 shape[2].x = -im; shape[2].y = im2;
3897 shape[3].x = -im2; shape[3].y = 0;
3898 shape[4].x = -im; shape[4].y = -im2;
3899 shape[5].x = -im2; shape[5].y = -im;
3900 shape[6].x = 0; shape[6].y = -im2;
3901 shape[7].x = im2; shape[7].y = -im;
3902 shape[8].x = im; shape[8].y = -im2;
3903 shape[9].x = im2; shape[9].y = 0;
3904 shape[10].x = im; shape[10].y = im2;
3905 shape[11].x = im2; shape[11].y = im;
3906 shape[12].x = 0; shape[12].y = im2*0.995;
3907 shape[13].x = im2*0.995; shape[13].y = 0;
3908 shape[14].x = 0; shape[14].y = -im2*0.995;
3909 shape[15].x = -im2*0.995; shape[15].y = 0;
3910 shape[16].x = 0; shape[16].y = im2*0.995;
3911 SetMarkerType(3,16,shape);
3912 } else if (markerstyle == 49) {
3913 // four filled squares plus
3914 Int_t imx = Int_t(1.33*MarkerSizeReduced + 0.5);
3915 shape[0].x =-imx; shape[0].y =-imx*1.005;
3916 shape[1].x =-imx; shape[1].y = -im;
3917 shape[2].x = imx; shape[2].y = -im;
3918 shape[3].x = imx; shape[3].y =-imx;
3919 shape[4].x = im; shape[4].y =-imx;
3920 shape[5].x = im; shape[5].y = imx;
3921 shape[6].x = imx; shape[6].y = imx;
3922 shape[7].x = imx; shape[7].y = im;
3923 shape[8].x =-imx; shape[8].y = im;
3924 shape[9].x =-imx; shape[9].y = imx;
3925 shape[10].x = -im; shape[10].y = imx;
3926 shape[11].x = -im; shape[11].y =-imx;
3927 shape[12].x =-imx; shape[12].y =-imx*0.995;
3928 shape[13].x =-imx; shape[13].y = imx;
3929 shape[14].x = imx; shape[14].y = imx;
3930 shape[15].x = imx; shape[15].y =-imx;
3931 shape[16].x =-imx; shape[16].y =-imx*1.005;
3932 SetMarkerType(3,17,shape);
3933 } else {
3934 // single dot
3935 SetMarkerType(0, 0, shape);
3936 }
3938}
3939
3940////////////////////////////////////////////////////////////////////////////////
3941/// Set opacity of a window. This image manipulation routine works
3942/// by adding to a percent amount of neutral to each pixels RGB.
3943/// Since it requires quite some additional color map entries is it
3944/// only supported on displays with more than > 8 color planes (> 256
3945/// colors)
3946
3948{
3949 Int_t depth = gdk_visual_get_best_depth();
3950
3951 if (depth <= 8) return;
3952 if (percent == 0) return;
3953
3954 // if 100 percent then just make white
3955 ULong_t *orgcolors = 0, *tmpc = 0;
3956 Int_t maxcolors = 0, ncolors, ntmpc = 0;
3957
3958 // save previous allocated colors, delete at end when not used anymore
3959 if (gCws->new_colors) {
3960 tmpc = gCws->new_colors;
3961 ntmpc = gCws->ncolors;
3962 }
3963 // get pixmap from server as image
3964 GdkImage *image = gdk_image_get((GdkDrawable*)gCws->drawing, 0, 0,
3965 gCws->width, gCws->height);
3966
3967 // collect different image colors
3968 int x, y;
3969 for (y = 0; y < (int) gCws->height; y++) {
3970 for (x = 0; x < (int) gCws->width; x++) {
3971 ULong_t pixel = GetPixelImage((Drawable_t)image, x, y);
3972 CollectImageColors(pixel, orgcolors, ncolors, maxcolors);
3973 }
3974 }
3975 if (ncolors == 0) {
3976 gdk_image_unref(image);
3977 ::operator delete(orgcolors);
3978 return;
3979 }
3980 // create opaque counter parts
3981 MakeOpaqueColors(percent, orgcolors, ncolors);
3982
3983 // put opaque colors in image
3984 for (y = 0; y < (int) gCws->height; y++) {
3985 for (x = 0; x < (int) gCws->width; x++) {
3986 ULong_t pixel = GetPixelImage((Drawable_t)image, x, y);
3987 Int_t idx = FindColor(pixel, orgcolors, ncolors);
3988 PutPixel((Drawable_t)image, x, y, gCws->new_colors[idx]);
3989 }
3990 }
3991
3992 // put image back in pixmap on server
3993 gdk_draw_image(gCws->drawing, gGCpxmp, (GdkImage *)image,
3994 0, 0, 0, 0, gCws->width, gCws->height);
3995 GdiFlush();
3996
3997 // clean up
3998 if (tmpc) {
3999 gdk_colors_free((GdkColormap *)fColormap, tmpc, ntmpc, 0);
4000 delete[]tmpc;
4001 }
4002 gdk_image_unref(image);
4003 ::operator delete(orgcolors);
4004}
4005
4006////////////////////////////////////////////////////////////////////////////////
4007/// Get RGB values for orgcolors, add percent neutral to the RGB and
4008/// allocate new_colors.
4009
4010void TGWin32::MakeOpaqueColors(Int_t percent, ULong_t *orgcolors, Int_t ncolors)
4011{
4012 Int_t ret;
4013 if (ncolors <= 0) return;
4014 GdkColor *xcol = new GdkColor[ncolors];
4015
4016 int i;
4017 for (i = 0; i < ncolors; i++) {
4018 xcol[i].pixel = orgcolors[i];
4019 xcol[i].red = xcol[i].green = xcol[i].blue = 0;
4020 }
4021
4022 GdkColorContext *cc;
4023 cc = gdk_color_context_new(gdk_visual_get_system(), (GdkColormap *)fColormap);
4024 gdk_color_context_query_colors(cc, xcol, ncolors);
4025 gdk_color_context_free(cc);
4026
4027 UShort_t add = percent * kBIGGEST_RGB_VALUE / 100;
4028
4029 Int_t val;
4030 for (i = 0; i < ncolors; i++) {
4031 val = xcol[i].red + add;
4032 if (val > kBIGGEST_RGB_VALUE) {
4033 val = kBIGGEST_RGB_VALUE;
4034 }
4035 xcol[i].red = (UShort_t) val;
4036 val = xcol[i].green + add;
4037 if (val > kBIGGEST_RGB_VALUE) {
4038 val = kBIGGEST_RGB_VALUE;
4039 }
4040 xcol[i].green = (UShort_t) val;
4041 val = xcol[i].blue + add;
4042 if (val > kBIGGEST_RGB_VALUE) {
4043 val = kBIGGEST_RGB_VALUE;
4044 }
4045 xcol[i].blue = (UShort_t) val;
4046
4047 ret = gdk_color_alloc((GdkColormap *)fColormap, &xcol[i]);
4048
4049 if (!ret) {
4050 Warning("MakeOpaqueColors",
4051 "failed to allocate color %hd, %hd, %hd", xcol[i].red,
4052 xcol[i].green, xcol[i].blue);
4053 // assumes that in case of failure xcol[i].pixel is not changed
4054 }
4055 }
4056
4057 gCws->new_colors = new ULong_t[ncolors];
4058 gCws->ncolors = ncolors;
4059
4060 for (i = 0; i < ncolors; i++) {
4061 gCws->new_colors[i] = xcol[i].pixel;
4062 }
4063
4064 delete []xcol;
4065}
4066
4067////////////////////////////////////////////////////////////////////////////////
4068/// Returns index in orgcolors (and new_colors) for pixel.
4069
4070Int_t TGWin32::FindColor(ULong_t pixel, ULong_t * orgcolors, Int_t ncolors)
4071{
4072 for (int i = 0; i < ncolors; i++) {
4073 if (pixel == orgcolors[i]) return i;
4074 }
4075 Error("FindColor", "did not find color, should never happen!");
4076
4077 return 0;
4078}
4079
4080////////////////////////////////////////////////////////////////////////////////
4081/// Set color intensities for given color index.
4082/// cindex : color index
4083/// r,g,b : red, green, blue intensities between 0.0 and 1.0
4084
4085void TGWin32::SetRGB(int cindex, float r, float g, float b)
4086{
4087 GdkColor xcol;
4088
4089 if (fColormap && cindex >= 0) {
4090 xcol.red = (unsigned short) (r * kBIGGEST_RGB_VALUE);
4091 xcol.green = (unsigned short) (g * kBIGGEST_RGB_VALUE);
4092 xcol.blue = (unsigned short) (b * kBIGGEST_RGB_VALUE);
4093 xcol.pixel = RGB(xcol.red, xcol.green, xcol.blue);
4094
4095 XColor_t &col = GetColor(cindex);
4096 if (col.fDefined) {
4097 // if color is already defined with same rgb just return
4098 if (col.color.red == xcol.red && col.color.green == xcol.green &&
4099 col.color.blue == xcol.blue)
4100 return;
4101 col.fDefined = kFALSE;
4102 gdk_colormap_free_colors((GdkColormap *) fColormap,
4103 (GdkColor *)&col, 1);
4104 }
4105
4106 Int_t ret = gdk_colormap_alloc_color(fColormap, &xcol, 1, 1);
4107 if (ret != 0) {
4108 col.fDefined = kTRUE;
4109 col.color.pixel = xcol.pixel;
4110 col.color.red = xcol.red;
4111 col.color.green = xcol.green;
4112 col.color.blue = xcol.blue;
4113 }
4114 }
4115}
4116
4117////////////////////////////////////////////////////////////////////////////////
4118/// Set text alignment.
4119/// txalh : horizontal text alignment
4120/// txalv : vertical text alignment
4121
4123{
4124 static Short_t current = 0;
4125 if (talign==current) return;
4126 current = talign;
4127
4128 Int_t txalh = talign / 10;
4129 Int_t txalv = talign % 10;
4130 fTextAlignH = txalh;
4131 fTextAlignV = txalv;
4132
4133 switch (txalh) {
4134
4135 case 0:
4136 case 1:
4137 switch (txalv) { //left
4138 case 1:
4139 fTextAlign = 7; //bottom
4140 break;
4141 case 2:
4142 fTextAlign = 4; //center
4143 break;
4144 case 3:
4145 fTextAlign = 1; //top
4146 break;
4147 }
4148 break;
4149 case 2:
4150 switch (txalv) { //center
4151 case 1:
4152 fTextAlign = 8; //bottom
4153 break;
4154 case 2:
4155 fTextAlign = 5; //center
4156 break;
4157 case 3:
4158 fTextAlign = 2; //top
4159 break;
4160 }
4161 break;
4162 case 3:
4163 switch (txalv) { //right
4164 case 1:
4165 fTextAlign = 9; //bottom
4166 break;
4167 case 2:
4168 fTextAlign = 6; //center
4169 break;
4170 case 3:
4171 fTextAlign = 3; //top
4172 break;
4173 }
4174 break;
4175 }
4177}
4178
4179////////////////////////////////////////////////////////////////////////////////
4180/// Set color index for text.
4181
4183{
4184 static Int_t current = 0;
4185 GdkGCValues values;
4186 if ((cindex < 0) || (Int_t(cindex)==current)) return;
4187
4188 TAttText::SetTextColor(cindex);
4189
4190 SetColor(gGCtext, Int_t(cindex));
4191 gdk_gc_get_values(gGCtext, &values);
4192 gdk_gc_set_foreground(gGCinvt, &values.background);
4193 gdk_gc_set_background(gGCinvt, &values.foreground);
4194 gdk_gc_set_background(gGCtext, (GdkColor *) & GetColor(0).color);
4195 current = Int_t(cindex);
4196}
4197
4198////////////////////////////////////////////////////////////////////////////////
4199
4200void TGWin32::Sync(int mode)
4201{
4202}
4203
4204////////////////////////////////////////////////////////////////////////////////
4205/// Update display.
4206/// mode : (1) update
4207/// (0) sync
4208///
4209/// Synchronise client and server once (not permanent).
4210/// Copy the pixmap gCws->drawing on the window gCws->window
4211/// if the double buffer is on.
4212
4214{
4215 if (gCws && gCws->double_buffer) {
4216 gdk_window_copy_area(gCws->window, gGCpxmp, 0, 0,
4217 gCws->drawing, 0, 0, gCws->width, gCws->height);
4218 }
4219 Update(mode);
4220}
4221
4222////////////////////////////////////////////////////////////////////////////////
4223/// Set pointer position.
4224/// ix : New X coordinate of pointer
4225/// iy : New Y coordinate of pointer
4226/// Coordinates are relative to the origin of the window id
4227/// or to the origin of the current window if id == 0.
4228
4229void TGWin32::Warp(int ix, int iy, Window_t id)
4230{
4231 if (!id) return;
4232
4233 POINT cpt, tmp;
4234 HWND dw;
4235 if (!id)
4236 dw = (HWND) GDK_DRAWABLE_XID((GdkWindow *)gCws->window);
4237 else
4238 dw = (HWND) GDK_DRAWABLE_XID((GdkWindow *)id);
4239 GetCursorPos(&cpt);
4240 tmp.x = ix > 0 ? ix : cpt.x;
4241 tmp.y = iy > 0 ? iy : cpt.y;
4242 ClientToScreen(dw, &tmp);
4243 SetCursorPos(tmp.x, tmp.y);
4244}
4245
4246////////////////////////////////////////////////////////////////////////////////
4247/// Write the pixmap wid in the bitmap file pxname.
4248/// wid : Pixmap address
4249/// w,h : Width and height of the pixmap.
4250/// lenname : pixmap name length
4251/// pxname : pixmap name
4252
4253void TGWin32::WritePixmap(int wid, unsigned int w, unsigned int h,
4254 char *pxname)
4255{
4256 int wval, hval;
4257 wval = w;
4258 hval = h;
4259
4260 if (!fWindows) return;
4261 gTws = &fWindows[wid];
4262// XWriteBitmapFile(fDisplay,pxname,(Pixmap)gTws->drawing,wval,hval,-1,-1);
4263}
4264
4265
4266//
4267// Functions for GIFencode()
4268//
4269
4270static FILE *gGifFile; // output unit used WriteGIF and PutByte
4271static GdkImage *gGifImage = 0; // image used in WriteGIF and GetPixel
4272
4273extern "C" {
4274 int GIFquantize(UInt_t width, UInt_t height, Int_t * ncol, Byte_t * red,
4275 Byte_t * green, Byte_t * blue, Byte_t * outputBuf,
4276 Byte_t * outputCmap);
4277 long GIFencode(int Width, int Height, Int_t Ncol, Byte_t R[],
4278 Byte_t G[], Byte_t B[], Byte_t ScLine[],
4279 void (*get_scline) (int, int, Byte_t *),
4280 void (*pb) (Byte_t));
4281 int GIFdecode(Byte_t * GIFarr, Byte_t * PIXarr, int *Width, int *Height,
4282 int *Ncols, Byte_t * R, Byte_t * G, Byte_t * B);
4283 int GIFinfo(Byte_t * GIFarr, int *Width, int *Height, int *Ncols);
4284}
4285
4286
4287////////////////////////////////////////////////////////////////////////////////
4288/// Get pixels in line y and put in array scline.
4289
4290static void GetPixel(int y, int width, Byte_t * scline)
4291{
4292 for (int i = 0; i < width; i++) {
4293 scline[i] = Byte_t(GetPixelImage((Drawable_t)gGifImage, i, y));
4294 }
4295}
4296
4297////////////////////////////////////////////////////////////////////////////////
4298/// Put byte b in output stream.
4299
4300static void PutByte(Byte_t b)
4301{
4302 if (ferror(gGifFile) == 0) fputc(b, gGifFile);
4303}
4304
4305////////////////////////////////////////////////////////////////////////////////
4306/// Returns in R G B the ncol colors of the palette used by the image.
4307/// The image pixels are changed to index values in these R G B arrays.
4308/// This produces a colormap with only the used colors (so even on displays
4309/// with more than 8 planes we will be able to create GIF's when the image
4310/// contains no more than 256 different colors). If it does contain more
4311/// colors we will have to use GIFquantize to reduce the number of colors.
4312/// The R G B arrays must be deleted by the caller.
4313
4314void TGWin32::ImgPickPalette(GdkImage * image, Int_t & ncol, Int_t * &R,
4315 Int_t * &G, Int_t * &B)
4316{
4317 ULong_t *orgcolors = 0;
4318 Int_t maxcolors = 0, ncolors;
4319
4320 // collect different image colors
4321 int x, y;
4322 for (x = 0; x < (int) gCws->width; x++) {
4323 for (y = 0; y < (int) gCws->height; y++) {
4324 ULong_t pixel = GetPixelImage((Drawable_t)image, x, y);
4325 CollectImageColors(pixel, orgcolors, ncolors, maxcolors);
4326 }
4327 }
4328
4329 // get RGB values belonging to pixels
4330 GdkColor *xcol = new GdkColor[ncolors];
4331
4332 int i;
4333 for (i = 0; i < ncolors; i++) {
4334 xcol[i].pixel = orgcolors[i];
4335// xcol[i].red = xcol[i].green = xcol[i].blue = 0;
4336 xcol[i].red = GetRValue(xcol[i].pixel);
4337 xcol[i].green = GetGValue(xcol[i].pixel);
4338 xcol[i].blue = GetBValue(xcol[i].pixel);
4339 }
4340
4341 GdkColorContext *cc;
4342 cc = gdk_color_context_new(gdk_visual_get_system(), (GdkColormap *)fColormap);
4343 gdk_color_context_query_colors(cc, xcol, ncolors);
4344 gdk_color_context_free(cc);
4345
4346 // create RGB arrays and store RGB's for each color and set number of colors
4347 // (space must be delete by caller)
4348 R = new Int_t[ncolors];
4349 G = new Int_t[ncolors];
4350 B = new Int_t[ncolors];
4351
4352 for (i = 0; i < ncolors; i++) {
4353 R[i] = xcol[i].red;
4354 G[i] = xcol[i].green;
4355 B[i] = xcol[i].blue;
4356 }
4357 ncol = ncolors;
4358
4359 // update image with indices (pixels) into the new RGB colormap
4360 for (x = 0; x < (int) gCws->width; x++) {
4361 for (y = 0; y < (int) gCws->height; y++) {
4362 ULong_t pixel = GetPixelImage((Drawable_t)image, x, y);
4363 Int_t idx = FindColor(pixel, orgcolors, ncolors);
4364 PutPixel((Drawable_t)image, x, y, idx);
4365 }
4366 }
4367
4368 // cleanup
4369 delete[]xcol;
4370 ::operator delete(orgcolors);
4371}
4372
4373////////////////////////////////////////////////////////////////////////////////
4374/// Writes the current window into GIF file.
4375
4377{
4378 Byte_t scline[2000], r[256], b[256], g[256];
4379 Int_t *R, *G, *B;
4380 Int_t ncol, maxcol, i;
4381
4382 if (gGifImage) {
4383 gdk_image_unref((GdkImage *)gGifImage);
4384 }
4385
4386 gGifImage = gdk_image_get((GdkDrawable*)gCws->drawing, 0, 0,
4387 gCws->width, gCws->height);
4388
4389 ImgPickPalette(gGifImage, ncol, R, G, B);
4390
4391 if (ncol > 256) {
4392 //GIFquantize(...);
4393 Error("WriteGIF",
4394 "can not create GIF of image containing more than 256 colors");
4395 delete[]R;
4396 delete[]G;
4397 delete[]B;
4398 return 0;
4399 }
4400
4401 maxcol = 0;
4402 for (i = 0; i < ncol; i++) {
4403 if (maxcol < R[i]) maxcol = R[i];
4404 if (maxcol < G[i]) maxcol = G[i];
4405 if (maxcol < B[i]) maxcol = B[i];
4406 r[i] = 0;
4407 g[i] = 0;
4408 b[i] = 0;
4409 }
4410 if (maxcol != 0) {
4411 for (i = 0; i < ncol; i++) {
4412 r[i] = R[i] * 255 / maxcol;
4413 g[i] = G[i] * 255 / maxcol;
4414 b[i] = B[i] * 255 / maxcol;
4415 }
4416 }
4417
4418 gGifFile = fopen(name, "wb");
4419
4420 if (gGifFile) {
4422 ncol, r, g, b, scline, ::GetPixel, PutByte);
4423 fclose(gGifFile);
4424 i = 1;
4425 } else {
4426 Error("WriteGIF","cannot write file: %s",name);
4427 i = 0;
4428 }
4429 delete[]R;
4430 delete[]G;
4431 delete[]B;
4432
4433 return i;
4434}
4435
4436////////////////////////////////////////////////////////////////////////////////
4437/// Draw image.
4438
4439void TGWin32::PutImage(int offset, int itran, int x0, int y0, int nx,
4440 int ny, int xmin, int ymin, int xmax, int ymax,
4441 unsigned char *image, Drawable_t wid)
4442{
4443 const int MAX_SEGMENT = 20;
4444 int i, n, x, y, xcur, x1, x2, y1, y2;
4445 unsigned char *jimg, *jbase, icol;
4446 int nlines[256];
4447 GdkSegment lines[256][MAX_SEGMENT];
4448 GdkDrawable *id;
4449
4450 if (wid) {
4451 id = (GdkDrawable*)wid;
4452 } else {
4453 id = gCws->drawing;
4454 }
4455
4456 for (i = 0; i < 256; i++) nlines[i] = 0;
4457
4458 x1 = x0 + xmin;
4459 y1 = y0 + ny - ymax - 1;
4460 x2 = x0 + xmax;
4461 y2 = y0 + ny - ymin - 1;
4462 jbase = image + (ymin - 1) * nx + xmin;
4463
4464 for (y = y2; y >= y1; y--) {
4465 xcur = x1;
4466 jbase += nx;
4467 for (jimg = jbase, icol = *jimg++, x = x1 + 1; x <= x2; jimg++, x++) {
4468 if (icol != *jimg) {
4469 if (icol != itran) {
4470 n = nlines[icol]++;
4471 lines[icol][n].x1 = xcur;
4472 lines[icol][n].y1 = y;
4473 lines[icol][n].x2 = x - 1;
4474 lines[icol][n].y2 = y;
4475 if (nlines[icol] == MAX_SEGMENT) {
4476 SetColor(gGCline, (int) icol + offset);
4477 gdk_win32_draw_segments(id, (GdkGC *) gGCline,
4478 (GdkSegment *) &lines[icol][0], MAX_SEGMENT);
4479 nlines[icol] = 0;
4480 }
4481 }
4482 icol = *jimg;
4483 xcur = x;
4484 }
4485 }
4486 if (icol != itran) {
4487 n = nlines[icol]++;
4488 lines[icol][n].x1 = xcur;
4489 lines[icol][n].y1 = y;
4490 lines[icol][n].x2 = x - 1;
4491 lines[icol][n].y2 = y;
4492 if (nlines[icol] == MAX_SEGMENT) {
4493 SetColor(gGCline, (int) icol + offset);
4494 gdk_win32_draw_segments(id, (GdkGC *) gGCline,
4495 (GdkSegment *)&lines[icol][0], MAX_SEGMENT);
4496 nlines[icol] = 0;
4497 }
4498 }
4499 }
4500
4501 for (i = 0; i < 256; i++) {
4502 if (nlines[i] != 0) {
4503 SetColor(gGCline, i + offset);
4504 gdk_win32_draw_segments(id, (GdkGC *) gGCline,
4505 (GdkSegment *)&lines[icol][0], nlines[i]);
4506 }
4507 }
4508}
4509
4510////////////////////////////////////////////////////////////////////////////////
4511/// If id is NULL - loads the specified gif file at position [x0,y0] in the
4512/// current window. Otherwise creates pixmap from gif file
4513
4514Pixmap_t TGWin32::ReadGIF(int x0, int y0, const char *file, Window_t id)
4515{
4516 FILE *fd;
4517 Seek_t filesize;
4518 unsigned char *GIFarr, *PIXarr, R[256], G[256], B[256], *j1, *j2, icol;
4519 int i, j, k, width, height, ncolor, irep, offset;
4520 float rr, gg, bb;
4521 Pixmap_t pic = 0;
4522
4523 fd = fopen(file, "r+b");
4524 if (!fd) {
4525 Error("ReadGIF", "unable to open GIF file");
4526 return pic;
4527 }
4528
4529 fseek(fd, 0L, 2);
4530 filesize = Seek_t(ftell(fd));
4531 fseek(fd, 0L, 0);
4532
4533 if (!(GIFarr = (unsigned char *) calloc(filesize + 256, 1))) {
4534 fclose(fd);
4535 Error("ReadGIF", "unable to allocate array for gif");
4536 return pic;
4537 }
4538
4539 if (fread(GIFarr, filesize, 1, fd) != 1) {
4540 fclose(fd);
4541 Error("ReadGIF", "GIF file read failed");
4542 free(GIFarr);
4543 return pic;
4544 }
4545 fclose(fd);
4546
4547 irep = GIFinfo(GIFarr, &width, &height, &ncolor);
4548 if (irep != 0) {
4549 return pic;
4550 }
4551
4552 if (!(PIXarr = (unsigned char *) calloc((width * height), 1))) {
4553 Error("ReadGIF", "unable to allocate array for image");
4554 return pic;
4555 }
4556
4557 irep = GIFdecode(GIFarr, PIXarr, &width, &height, &ncolor, R, G, B);
4558 if (irep != 0) {
4559 return pic;
4560 }
4561 // S E T P A L E T T E
4562
4563 offset = 8;
4564
4565 for (i = 0; i < ncolor; i++) {
4566 rr = R[i] / 255.;
4567 gg = G[i] / 255.;
4568 bb = B[i] / 255.;
4569 j = i + offset;
4570 SetRGB(j, rr, gg, bb);
4571 }
4572
4573 // O U T P U T I M A G E
4574
4575 for (i = 1; i <= height / 2; i++) {
4576 j1 = PIXarr + (i - 1) * width;
4577 j2 = PIXarr + (height - i) * width;
4578 for (k = 0; k < width; k++) {
4579 icol = *j1;
4580 *j1++ = *j2;
4581 *j2++ = icol;
4582 }
4583 }
4584
4585 if (id) pic = CreatePixmap(id, width, height);
4586 PutImage(offset, -1, x0, y0, width, height, 0, 0, width-1, height-1, PIXarr, pic);
4587
4588 if (pic) return pic;
4589 else if (gCws->drawing) return (Pixmap_t)gCws->drawing;
4590 else return 0;
4591}
4592
4593//////////////////////////// GWin32Gui //////////////////////////////////////////
4594////////////////////////////////////////////////////////////////////////////////
4595/// Map window on screen.
4596
4598{
4599 if (!id) return;
4600
4601 gdk_window_show((GdkWindow *)id);
4602 if ((GDK_DRAWABLE_TYPE((GdkWindow *)id) != GDK_WINDOW_TEMP) &&
4603 (GetParent(id) == GetDefaultRootWindow())) {
4604 HWND window = (HWND)GDK_DRAWABLE_XID((GdkWindow *)id);
4605 ::SetForegroundWindow(window);
4606 }
4607}
4608
4609////////////////////////////////////////////////////////////////////////////////
4610///
4611
4613{
4614 if (!id) return;
4615
4616 EnumChildWindows((HWND)GDK_DRAWABLE_XID((GdkWindow *)id),
4617 EnumChildProc, (LPARAM) NULL);
4618}
4619
4620////////////////////////////////////////////////////////////////////////////////
4621/// Map window on screen and put on top of all windows.
4622
4624{
4625 if (!id) return;
4626
4627 HWND hwnd = ::GetForegroundWindow();
4628 HWND window = (HWND)GDK_DRAWABLE_XID((GdkWindow *)id);
4629 gdk_window_show((GdkWindow *)id);
4630 if (GDK_DRAWABLE_TYPE((GdkWindow *)id) != GDK_WINDOW_TEMP) {
4631 ::BringWindowToTop(window);
4632 if (GDK_DRAWABLE_TYPE((GdkWindow *)id) != GDK_WINDOW_CHILD)
4633 ::SetForegroundWindow(window);
4634 }
4635
4636 if (gConsoleWindow && (hwnd == (HWND)gConsoleWindow)) {
4637 RECT r1, r2, r3;
4638 ::GetWindowRect((HWND)gConsoleWindow, &r1);
4639 HWND fore = ::GetForegroundWindow();
4640 ::GetWindowRect(fore, &r2);
4641 if (!::IntersectRect(&r3, &r2, &r1)) {
4642 ::SetForegroundWindow((HWND)gConsoleWindow);
4643 }
4644 }
4645}
4646
4647////////////////////////////////////////////////////////////////////////////////
4648/// Unmap window from screen.
4649
4651{
4652 if (!id) return;
4653
4654 gdk_window_hide((GdkWindow *) id);
4655}
4656
4657////////////////////////////////////////////////////////////////////////////////
4658/// Destroy window.
4659
4661{
4662 if (!id) return;
4663
4664 // we need to unmap the window before to destroy it, in order to properly
4665 // receive kUnmapNotify needed by gClient->WaitForUnmap()...
4666 gdk_window_hide((GdkWindow *) id);
4667 gdk_window_destroy((GdkDrawable *) id, kTRUE);
4668}
4669
4670////////////////////////////////////////////////////////////////////////////////
4671/// Destroy all internal subwindows
4672
4674{
4675 if (!id) return;
4676
4677 gdk_window_destroy((GdkDrawable *) id, kFALSE);
4678}
4679
4680////////////////////////////////////////////////////////////////////////////////
4681/// Put window on top of window stack.
4682
4684{
4685 if (!id) return;
4686
4687 HWND window = (HWND)GDK_DRAWABLE_XID((GdkWindow *)id);
4688 if (GDK_DRAWABLE_TYPE((GdkWindow *)id) == GDK_WINDOW_TEMP) {
4689 ::SetWindowPos(window, HWND_TOPMOST, 0, 0, 0, 0,
4690 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
4691 }
4692 else {
4693 ::BringWindowToTop(window);
4694 if (GDK_DRAWABLE_TYPE((GdkWindow *)id) != GDK_WINDOW_CHILD)
4695 ::SetForegroundWindow(window);
4696 }
4697}
4698
4699////////////////////////////////////////////////////////////////////////////////
4700/// Lower window so it lays below all its siblings.
4701
4703{
4704 if (!id) return;
4705
4706 HWND window = (HWND)GDK_DRAWABLE_XID((GdkWindow *)id);
4707 ::SetWindowPos(window, HWND_BOTTOM, 0, 0, 0, 0,
4708 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
4709}
4710
4711////////////////////////////////////////////////////////////////////////////////
4712/// Move a window.
4713
4715{
4716 if (!id) return;
4717
4718 gdk_window_move((GdkDrawable *) id, x, y);
4719}
4720
4721////////////////////////////////////////////////////////////////////////////////
4722/// Move and resize a window.
4723
4725 UInt_t h)
4726{
4727 if (!id) return;
4728
4729 gdk_window_move_resize((GdkWindow *) id, x, y, w, h);
4730}
4731
4732////////////////////////////////////////////////////////////////////////////////
4733/// Resize the window.
4734
4736{
4737 if (!id) return;
4738
4739 // protect against potential negative values
4740 if (w >= (UInt_t)INT_MAX || h >= (UInt_t)INT_MAX)
4741 return;
4742 gdk_window_resize((GdkWindow *) id, w, h);
4743}
4744
4745////////////////////////////////////////////////////////////////////////////////
4746/// Iconify the window.
4747
4749{
4750 if (!id) return;
4751
4752 gdk_window_lower((GdkWindow *) id);
4753 ::CloseWindow((HWND)GDK_DRAWABLE_XID((GdkWindow *)id));
4754}
4755
4756////////////////////////////////////////////////////////////////////////////////
4757/// Reparent window, make pid the new parent and position the window at
4758/// position (x,y) in new parent.
4759
4761{
4762 if (!id) return;
4763
4764 gdk_window_reparent((GdkWindow *)id, (GdkWindow *)pid, x, y);
4765}
4766
4767////////////////////////////////////////////////////////////////////////////////
4768/// Set the window background color.
4769
4771{
4772 if (!id) return;
4773
4774 GdkColor back;
4775 back.pixel = color;
4776 back.red = GetRValue(color);
4777 back.green = GetGValue(color);
4778 back.blue = GetBValue(color);
4779
4780 gdk_window_set_background((GdkWindow *) id, &back);
4781}
4782
4783////////////////////////////////////////////////////////////////////////////////
4784/// Set pixmap as window background.
4785
4787{
4788 if (!id) return;
4789
4790 gdk_window_set_back_pixmap((GdkWindow *) id, (GdkPixmap *) pxm, 0);
4791}
4792
4793////////////////////////////////////////////////////////////////////////////////
4794/// Return handle to newly created gdk window.
4795
4797 UInt_t w, UInt_t h, UInt_t border,
4798 Int_t depth, UInt_t clss,
4799 void *visual, SetWindowAttributes_t * attr,
4800 UInt_t wtype)
4801{
4802 GdkWindowAttr xattr;
4803 GdkWindow *newWin;
4804 GdkColor background_color;
4805 ULong_t xmask = 0;
4806
4807 if (attr) {
4808 MapSetWindowAttributes(attr, xmask, xattr);
4809 xattr.window_type = GDK_WINDOW_CHILD;
4810 if (wtype & kMainFrame) {
4811 xattr.window_type = GDK_WINDOW_TOPLEVEL;
4812 }
4813 if (wtype & kTransientFrame) {
4814 xattr.window_type = GDK_WINDOW_DIALOG;
4815 }
4816 if (wtype & kTempFrame) {
4817 xattr.window_type = GDK_WINDOW_TEMP;
4818 }
4819 newWin = gdk_window_new((GdkWindow *) parent, &xattr, xmask);
4820 } else {
4821 xattr.width = w;
4822 xattr.height = h;
4823 xattr.wclass = GDK_INPUT_OUTPUT;
4824 xattr.event_mask = 0L; //GDK_ALL_EVENTS_MASK;
4825 xattr.event_mask |= GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK |
4826 GDK_PROPERTY_CHANGE_MASK;
4827// GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK;
4828 if (x >= 0) {
4829 xattr.x = x;
4830 } else {
4831 xattr.x = -1.0 * x;
4832 }
4833 if (y >= 0) {
4834 xattr.y = y;
4835 } else {
4836 xattr.y = -1.0 * y;
4837 }
4838 xattr.colormap = gdk_colormap_get_system();
4839 xattr.cursor = NULL;
4840 xattr.override_redirect = TRUE;
4841 if ((xattr.y > 0) && (xattr.x > 0)) {
4842 xmask = GDK_WA_X | GDK_WA_Y | GDK_WA_COLORMAP |
4843 GDK_WA_WMCLASS | GDK_WA_NOREDIR;
4844 } else {
4845 xmask = GDK_WA_COLORMAP | GDK_WA_WMCLASS | GDK_WA_NOREDIR;
4846 }
4847 if (visual != NULL) {
4848 xattr.visual = (GdkVisual *) visual;
4849 xmask |= GDK_WA_VISUAL;
4850 } else {
4851 xattr.visual = gdk_visual_get_system();
4852 xmask |= GDK_WA_VISUAL;
4853 }
4854 xattr.window_type = GDK_WINDOW_CHILD;
4855 if (wtype & kMainFrame) {
4856 xattr.window_type = GDK_WINDOW_TOPLEVEL;
4857 }
4858 if (wtype & kTransientFrame) {
4859 xattr.window_type = GDK_WINDOW_DIALOG;
4860 }
4861 if (wtype & kTempFrame) {
4862 xattr.window_type = GDK_WINDOW_TEMP;
4863 }
4864 newWin = gdk_window_new((GdkWindow *) parent, &xattr, xmask);
4865 gdk_window_set_events(newWin, (GdkEventMask) 0L);
4866 }
4867 if (border > 0) {
4868 gdk_window_set_decorations(newWin,
4869 (GdkWMDecoration) GDK_DECOR_BORDER);
4870 }
4871 if (attr) {
4872 if ((attr->fMask & kWABackPixmap)) {
4873 if (attr->fBackgroundPixmap == kNone) {
4874 gdk_window_set_back_pixmap(newWin, (GdkPixmap *) GDK_NONE, 0);
4875 } else if (attr->fBackgroundPixmap == kParentRelative) {
4876 gdk_window_set_back_pixmap(newWin, (GdkPixmap *) GDK_NONE, 1);
4877 } else {
4878 gdk_window_set_back_pixmap(newWin,
4879 (GdkPixmap *) attr->
4880 fBackgroundPixmap, 0);
4881 }
4882 }
4883 if ((attr->fMask & kWABackPixel)) {
4884 background_color.pixel = attr->fBackgroundPixel;
4885 background_color.red = GetRValue(attr->fBackgroundPixel);
4886 background_color.green = GetGValue(attr->fBackgroundPixel);
4887 background_color.blue = GetBValue(attr->fBackgroundPixel);
4888 gdk_window_set_background(newWin, &background_color);
4889 }
4890 }
4891 if (!fUseSysPointers) {
4892 ::SetClassLong((HWND)GDK_DRAWABLE_XID(newWin), GCL_HCURSOR,
4893 (LONG)GDK_CURSOR_XID(fCursors[kPointer]));
4894 }
4895 return (Window_t) newWin;
4896}
4897
4898////////////////////////////////////////////////////////////////////////////////
4899/// Map event mask to or from gdk.
4900
4901void TGWin32::MapEventMask(UInt_t & emask, UInt_t & xemask, Bool_t tox)
4902{
4903 if (tox) {
4904 Long_t lxemask = 0L;
4905 if ((emask & kKeyPressMask)) {
4906 lxemask |= GDK_KEY_PRESS_MASK;
4907 }
4908 if ((emask & kKeyReleaseMask)) {
4909 lxemask |= GDK_KEY_RELEASE_MASK;
4910 }
4911 if ((emask & kButtonPressMask)) {
4912 lxemask |= GDK_BUTTON_PRESS_MASK;
4913 }
4914 if ((emask & kButtonReleaseMask)) {
4915 lxemask |= GDK_BUTTON_RELEASE_MASK;
4916 }
4917 if ((emask & kPointerMotionMask)) {
4918 lxemask |= GDK_POINTER_MOTION_MASK;
4919 }
4920 if ((emask & kButtonMotionMask)) {
4921 lxemask |= GDK_BUTTON_MOTION_MASK;
4922 }
4923 if ((emask & kExposureMask)) {
4924 lxemask |= GDK_EXPOSURE_MASK;
4925 }
4926 if ((emask & kStructureNotifyMask)) {
4927 lxemask |= GDK_STRUCTURE_MASK;
4928 }
4929 if ((emask & kEnterWindowMask)) {
4930 lxemask |= GDK_ENTER_NOTIFY_MASK;
4931 }
4932 if ((emask & kLeaveWindowMask)) {
4933 lxemask |= GDK_LEAVE_NOTIFY_MASK;
4934 }
4935 if ((emask & kFocusChangeMask)) {
4936 lxemask |= GDK_FOCUS_CHANGE_MASK;
4937 }
4938 xemask = (UInt_t) lxemask;
4939 } else {
4940 emask = 0;
4941 if ((xemask & GDK_KEY_PRESS_MASK)) {
4942 emask |= kKeyPressMask;
4943 }
4944 if ((xemask & GDK_KEY_RELEASE_MASK)) {
4945 emask |= kKeyReleaseMask;
4946 }
4947 if ((xemask & GDK_BUTTON_PRESS_MASK)) {
4948 emask |= kButtonPressMask;
4949 }
4950 if ((xemask & GDK_BUTTON_RELEASE_MASK)) {
4951 emask |= kButtonReleaseMask;
4952 }
4953 if ((xemask & GDK_POINTER_MOTION_MASK)) {
4954 emask |= kPointerMotionMask;
4955 }
4956 if ((xemask & GDK_BUTTON_MOTION_MASK)) {
4957 emask |= kButtonMotionMask;
4958 }
4959 if ((xemask & GDK_EXPOSURE_MASK)) {
4960 emask |= kExposureMask;
4961 }
4962 if ((xemask & GDK_STRUCTURE_MASK)) {
4963 emask |= kStructureNotifyMask;
4964 }
4965 if ((xemask & GDK_ENTER_NOTIFY_MASK)) {
4966 emask |= kEnterWindowMask;
4967 }
4968 if ((xemask & GDK_LEAVE_NOTIFY_MASK)) {
4969 emask |= kLeaveWindowMask;
4970 }
4971 if ((xemask & GDK_FOCUS_CHANGE_MASK)) {
4972 emask |= kFocusChangeMask;
4973 }
4974 }
4975}
4976
4977////////////////////////////////////////////////////////////////////////////////
4978/// Map a SetWindowAttributes_t to a GdkWindowAttr structure.
4979
4981 ULong_t & xmask,
4982 GdkWindowAttr & xattr)
4983{
4984 Mask_t mask = attr->fMask;
4985 xmask = 0;
4986
4987 if ((mask & kWAOverrideRedirect)) {
4988 xmask |= GDK_WA_NOREDIR;
4989 xattr.override_redirect = attr->fOverrideRedirect;
4990 }
4991 if ((mask & kWAEventMask)) {
4992 UInt_t xmsk, msk = (UInt_t) attr->fEventMask;
4993 MapEventMask(msk, xmsk, kTRUE);
4994 xattr.event_mask = xmsk;
4995 }
4996 if ((mask & kWAColormap)) {
4997 xmask |= GDK_WA_COLORMAP;
4998 xattr.colormap = (GdkColormap *) attr->fColormap;
4999 }
5000 if ((mask & kWACursor)) {
5001 xmask |= GDK_WA_CURSOR;
5002 if (attr->fCursor != kNone) {
5003 xattr.cursor = (GdkCursor *) attr->fCursor;
5004 }
5005 }
5006 xattr.wclass = GDK_INPUT_OUTPUT;
5007}
5008
5009////////////////////////////////////////////////////////////////////////////////
5010/// Map a GCValues_t to a XCGValues structure if tox is true. Map
5011/// the other way in case tox is false.
5012
5014 ULong_t & xmask, GdkGCValues & xgval, Bool_t tox)
5015{
5016 if (tox) {
5017 // map GCValues_t to XGCValues
5018 Mask_t mask = gval.fMask;
5019 xmask = 0;
5020
5021 if ((mask & kGCFunction)) {
5022 xmask |= GDK_GC_FUNCTION;
5023 switch (gval.fFunction) {
5024 case kGXclear:
5025 xgval.function = GDK_CLEAR;
5026 break;
5027 case kGXand:
5028 xgval.function = GDK_AND;
5029 break;
5030 case kGXandReverse:
5031 xgval.function = GDK_AND_REVERSE;
5032 break;
5033 case kGXcopy:
5034 xgval.function = GDK_COPY;
5035 break;
5036 case kGXandInverted:
5037 xgval.function = GDK_AND_INVERT;
5038 break;
5039 case kGXnoop:
5040 xgval.function = GDK_NOOP;
5041 break;
5042 case kGXxor:
5043 xgval.function = GDK_XOR;
5044 break;
5045 case kGXor:
5046 xgval.function = GDK_OR;
5047 break;
5048 case kGXequiv:
5049 xgval.function = GDK_EQUIV;
5050 break;
5051 case kGXinvert:
5052 xgval.function = GDK_INVERT;
5053 break;
5054 case kGXorReverse:
5055 xgval.function = GDK_OR_REVERSE;
5056 break;
5057 case kGXcopyInverted:
5058 xgval.function = GDK_COPY_INVERT;
5059 break;
5060 case kGXorInverted:
5061 xgval.function = GDK_OR_INVERT;
5062 break;
5063 case kGXnand:
5064 xgval.function = GDK_NAND;
5065 break;
5066 case kGXset:
5067 xgval.function = GDK_SET;
5068 break;
5069 }
5070 }
5071 if (mask & kGCSubwindowMode) {
5072 xmask |= GDK_GC_SUBWINDOW;
5073 if (gval.fSubwindowMode == kIncludeInferiors) {
5074 xgval.subwindow_mode = GDK_INCLUDE_INFERIORS;
5075 } else {
5076 xgval.subwindow_mode = GDK_CLIP_BY_CHILDREN;
5077 }
5078 }
5079 if (mask & kGCForeground) {
5080 xmask |= GDK_GC_FOREGROUND;
5081 xgval.foreground.pixel = gval.fForeground;
5082 xgval.foreground.red = GetRValue(gval.fForeground);
5083 xgval.foreground.green = GetGValue(gval.fForeground);
5084 xgval.foreground.blue = GetBValue(gval.fForeground);
5085 }
5086 if (mask & kGCBackground) {
5087 xmask |= GDK_GC_BACKGROUND;
5088 xgval.background.pixel = gval.fBackground;
5089 xgval.background.red = GetRValue(gval.fBackground);
5090 xgval.background.green = GetGValue(gval.fBackground);
5091 xgval.background.blue = GetBValue(gval.fBackground);
5092 }
5093 if (mask & kGCLineWidth) {
5094 xmask |= GDK_GC_LINE_WIDTH;
5095 xgval.line_width = gval.fLineWidth;
5096 }
5097 if (mask & kGCLineStyle) {
5098 xmask |= GDK_GC_LINE_STYLE;
5099 xgval.line_style = (GdkLineStyle) gval.fLineStyle; // ident mapping
5100 }
5101 if (mask & kGCCapStyle) {
5102 xmask |= GDK_GC_CAP_STYLE;
5103 xgval.cap_style = (GdkCapStyle) gval.fCapStyle; // ident mapping
5104 }
5105 if (mask & kGCJoinStyle) {
5106 xmask |= GDK_GC_JOIN_STYLE;
5107 xgval.join_style = (GdkJoinStyle) gval.fJoinStyle; // ident mapping
5108 }
5109 if ((mask & kGCFillStyle)) {
5110 xmask |= GDK_GC_FILL;
5111 xgval.fill = (GdkFill) gval.fFillStyle; // ident mapping
5112 }
5113 if ((mask & kGCTile)) {
5114 xmask |= GDK_GC_TILE;
5115 xgval.tile = (GdkPixmap *) gval.fTile;
5116 }
5117 if ((mask & kGCStipple)) {
5118 xmask |= GDK_GC_STIPPLE;
5119 xgval.stipple = (GdkPixmap *) gval.fStipple;
5120 }
5121 if ((mask & kGCTileStipXOrigin)) {
5122 xmask |= GDK_GC_TS_X_ORIGIN;
5123 xgval.ts_x_origin = gval.fTsXOrigin;
5124 }
5125 if ((mask & kGCTileStipYOrigin)) {
5126 xmask |= GDK_GC_TS_Y_ORIGIN;
5127 xgval.ts_y_origin = gval.fTsYOrigin;
5128 }
5129 if ((mask & kGCFont)) {
5130 xmask |= GDK_GC_FONT;
5131 xgval.font = (GdkFont *) gval.fFont;
5132 }
5133 if ((mask & kGCGraphicsExposures)) {
5134 xmask |= GDK_GC_EXPOSURES;
5135 xgval.graphics_exposures = gval.fGraphicsExposures;
5136 }
5137 if ((mask & kGCClipXOrigin)) {
5138 xmask |= GDK_GC_CLIP_X_ORIGIN;
5139 xgval.clip_x_origin = gval.fClipXOrigin;
5140 }
5141 if ((mask & kGCClipYOrigin)) {
5142 xmask |= GDK_GC_CLIP_Y_ORIGIN;
5143 xgval.clip_y_origin = gval.fClipYOrigin;
5144 }
5145 if ((mask & kGCClipMask)) {
5146 xmask |= GDK_GC_CLIP_MASK;
5147 xgval.clip_mask = (GdkPixmap *) gval.fClipMask;
5148 }
5149 } else {
5150 // map XValues to GCValues_t
5151 Mask_t mask = 0;
5152
5153 if ((xmask & GDK_GC_FUNCTION)) {
5154 mask |= kGCFunction;
5155 gval.fFunction = (EGraphicsFunction) xgval.function; // ident mapping
5156 switch (xgval.function) {
5157 case GDK_CLEAR:
5158 gval.fFunction = kGXclear;
5159 break;
5160 case GDK_AND:
5161 gval.fFunction = kGXand;
5162 break;
5163 case GDK_AND_REVERSE:
5164 gval.fFunction = kGXandReverse;
5165 break;
5166 case GDK_COPY:
5167 gval.fFunction = kGXcopy;
5168 break;
5169 case GDK_AND_INVERT:
5171 break;
5172 case GDK_NOOP:
5173 gval.fFunction = kGXnoop;
5174 break;
5175 case GDK_XOR:
5176 gval.fFunction = kGXxor;
5177 break;
5178 case GDK_OR:
5179 gval.fFunction = kGXor;
5180 break;
5181 case GDK_EQUIV:
5182 gval.fFunction = kGXequiv;
5183 break;
5184 case GDK_INVERT:
5185 gval.fFunction = kGXinvert;
5186 break;
5187 case GDK_OR_REVERSE:
5188 gval.fFunction = kGXorReverse;
5189 break;
5190 case GDK_COPY_INVERT:
5192 break;
5193 case GDK_OR_INVERT:
5194 gval.fFunction = kGXorInverted;
5195 break;
5196 case GDK_NAND:
5197 gval.fFunction = kGXnand;
5198 break;
5199 case GDK_SET:
5200 gval.fFunction = kGXset;
5201 break;
5202 }
5203 }
5204 if (xmask & GDK_GC_SUBWINDOW) {
5205 mask |= kGCSubwindowMode;
5206 if (xgval.subwindow_mode == GDK_INCLUDE_INFERIORS)
5208 else
5210 }
5211 if ((xmask & GDK_GC_FOREGROUND)) {
5212 mask |= kGCForeground;
5213 gval.fForeground = xgval.foreground.pixel;
5214 }
5215 if ((xmask & GDK_GC_BACKGROUND)) {
5216 mask |= kGCBackground;
5217 gval.fBackground = xgval.background.pixel;
5218 }
5219 if ((xmask & GDK_GC_LINE_WIDTH)) {
5220 mask |= kGCLineWidth;
5221 gval.fLineWidth = xgval.line_width;
5222 }
5223 if ((xmask & GDK_GC_LINE_STYLE)) {
5224 mask |= kGCLineStyle;
5225 gval.fLineStyle = xgval.line_style; // ident mapping
5226 }
5227 if ((xmask & GDK_GC_CAP_STYLE)) {
5228 mask |= kGCCapStyle;
5229 gval.fCapStyle = xgval.cap_style; // ident mapping
5230 }
5231 if ((xmask & GDK_GC_JOIN_STYLE)) {
5232 mask |= kGCJoinStyle;
5233 gval.fJoinStyle = xgval.join_style; // ident mapping
5234 }
5235 if ((xmask & GDK_GC_FILL)) {
5236 mask |= kGCFillStyle;
5237 gval.fFillStyle = xgval.fill; // ident mapping
5238 }
5239 if ((xmask & GDK_GC_TILE)) {
5240 mask |= kGCTile;
5241 gval.fTile = (Pixmap_t) xgval.tile;
5242 }
5243 if ((xmask & GDK_GC_STIPPLE)) {
5244 mask |= kGCStipple;
5245 gval.fStipple = (Pixmap_t) xgval.stipple;
5246 }
5247 if ((xmask & GDK_GC_TS_X_ORIGIN)) {
5248 mask |= kGCTileStipXOrigin;
5249 gval.fTsXOrigin = xgval.ts_x_origin;
5250 }
5251 if ((xmask & GDK_GC_TS_Y_ORIGIN)) {
5252 mask |= kGCTileStipYOrigin;
5253 gval.fTsYOrigin = xgval.ts_y_origin;
5254 }
5255 if ((xmask & GDK_GC_FONT)) {
5256 mask |= kGCFont;
5257 gval.fFont = (FontH_t) xgval.font;
5258 }
5259 if ((xmask & GDK_GC_EXPOSURES)) {
5260 mask |= kGCGraphicsExposures;
5261 gval.fGraphicsExposures = (Bool_t) xgval.graphics_exposures;
5262 }
5263 if ((xmask & GDK_GC_CLIP_X_ORIGIN)) {
5264 mask |= kGCClipXOrigin;
5265 gval.fClipXOrigin = xgval.clip_x_origin;
5266 }
5267 if ((xmask & GDK_GC_CLIP_Y_ORIGIN)) {
5268 mask |= kGCClipYOrigin;
5269 gval.fClipYOrigin = xgval.clip_y_origin;
5270 }
5271 if ((xmask & GDK_GC_CLIP_MASK)) {
5272 mask |= kGCClipMask;
5273 gval.fClipMask = (Pixmap_t) xgval.clip_mask;
5274 }
5275 gval.fMask = mask;
5276 }
5277}
5278
5279////////////////////////////////////////////////////////////////////////////////
5280/// Get window attributes and return filled in attributes structure.
5281
5283{
5284 if (!id) return;
5285
5286 RECT rcClient, rcWind;
5287 ::GetClientRect((HWND)GDK_DRAWABLE_XID((GdkWindow *) id), &rcClient);
5288 ::GetWindowRect((HWND)GDK_DRAWABLE_XID((GdkWindow *) id), &rcWind);
5289
5290 gdk_window_get_geometry((GdkWindow *) id, &attr.fX, &attr.fY,
5291 &attr.fWidth, &attr.fHeight, &attr.fDepth);
5292 attr.fX = ((rcWind.right - rcWind.left) - rcClient.right) / 2;
5293 attr.fY = ((rcWind.bottom - rcWind.top) - rcClient.bottom) - attr.fX;
5294
5295 attr.fRoot = (Window_t) GDK_ROOT_PARENT();
5296 attr.fColormap = (Colormap_t) gdk_window_get_colormap((GdkWindow *) id);
5297 attr.fBorderWidth = 0;
5298 attr.fVisual = gdk_window_get_visual((GdkWindow *) id);
5299 attr.fClass = kInputOutput;
5301 attr.fSaveUnder = kFALSE;
5302 attr.fMapInstalled = kTRUE;
5303 attr.fOverrideRedirect = kFALSE; // boolean value for override-redirect
5304
5305 if (!gdk_window_is_visible((GdkWindow *) id)) {
5306 attr.fMapState = kIsUnmapped;
5307 } else if (!gdk_window_is_viewable((GdkWindow *) id)) {
5308 attr.