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