0027620: Test perf bop boxholes crashes DRAW
[occt.git] / src / Draw / Draw_Window.cxx
CommitLineData
b311480e 1// Created on: 1994-07-27
2// Created by: Remi LEQUETTE
3// Copyright (c) 1994-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
7fd59977 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 8// This library is free software; you can redistribute it and/or modify it under
9// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 10// by the Free Software Foundation, with special exception defined in the file
11// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12// distribution for complete text of the license and disclaimer of any warranty.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
b311480e 16
7fd59977 17// include windows.h first to have all definitions available
57c28b61 18#ifdef _WIN32
7fd59977 19#include <windows.h>
20#endif
21
22#include <Standard_ErrorHandler.hxx>
23
24#include <tcl.h>
25#include <Draw_Interpretor.hxx>
a0fc422a 26#include <Draw_Window.hxx>
7fd59977 27#include <Draw_Appli.hxx>
28#include <TCollection_AsciiString.hxx>
ad03c234 29#include <TCollection_ExtendedString.hxx>
692613e5 30#include <Image_AlienPixMap.hxx>
a0fc422a 31#include <NCollection_List.hxx>
7fd59977 32
bf03eb83 33extern Standard_Boolean Draw_VirtualWindows;
7fd59977 34static Tcl_Interp *interp; /* Interpreter for this application. */
a0fc422a 35static NCollection_List<Draw_Window::FCallbackBeforeTerminate> MyCallbacks;
36
37void Draw_Window::AddCallbackBeforeTerminate(FCallbackBeforeTerminate theCB)
38{
39 MyCallbacks.Append(theCB);
40}
41
42void Draw_Window::RemoveCallbackBeforeTerminate(FCallbackBeforeTerminate theCB)
43{
44 NCollection_List<Draw_Window::FCallbackBeforeTerminate>::Iterator Iter(MyCallbacks);
45 for(; Iter.More(); Iter.Next())
46 {
47 if (Iter.Value() == theCB)
48 {
49 MyCallbacks.Remove(Iter);
50 break;
51 }
52 }
53}
7fd59977 54
55/*
56 *----------------------------------------------------------------------
57 *
58 * Prompt --
59 *
60 * Issue a prompt on standard output, or invoke a script
61 * to issue the prompt.
62 *
63 * Results:
64 * None.
65 *
66 * Side effects:
67 * A prompt gets output, and a Tcl script may be evaluated
68 * in interp.
69 *
70 *----------------------------------------------------------------------
71 */
72
73static void Prompt(Tcl_Interp *Interp, int partial)
74{
75
76 // MKV 29.03.05
77#if ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4))) && !defined(USE_NON_CONST)
78 const char *promptCmd;
79#else
80 char *promptCmd;
81#endif
82 int code;
83 Tcl_Channel outChannel, errChannel;
84 outChannel = Tcl_GetStdChannel(TCL_STDOUT);
85 promptCmd = Tcl_GetVar(Interp,(char*)
86 (partial ? "tcl_prompt2" : "tcl_prompt1"), TCL_GLOBAL_ONLY);
87
88 if (promptCmd == NULL) {
89defaultPrompt:
90 if (!partial && outChannel) {
91 Tcl_Write(outChannel, "% ", 2);
92 }
93 } else {
94 code = Tcl_Eval(Interp, promptCmd);
95 outChannel = Tcl_GetStdChannel(TCL_STDOUT);
96 errChannel = Tcl_GetStdChannel(TCL_STDERR);
97 if (code != TCL_OK) {
98 if (errChannel) {
7fb60cfd 99#if ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 5)))
100 Tcl_Write(errChannel, Tcl_GetStringResult(Interp), -1);
101#else
7fd59977 102 Tcl_Write(errChannel, Interp->result, -1);
7fb60cfd 103#endif
7fd59977 104 Tcl_Write(errChannel, "\n", 1);
105 }
106 Tcl_AddErrorInfo(Interp,
107 "\n (script that generates prompt)");
108 goto defaultPrompt;
109 }
110 }
111 if (outChannel) {
112 Tcl_Flush(outChannel);
113 }
114}
115
67d97f0e 116#if !defined(_WIN32) && !defined(__WIN32__)
7fd59977 117
7fd59977 118#include <OSD_Timer.hxx>
7fd59977 119#include <Draw_Window.hxx>
03155c18 120#include <unistd.h>
262bf46d 121
122#if defined(__APPLE__) && !defined(MACOSX_USE_GLX)
123 // use forward declaration for small subset of used Tk functions
124 // to workaround broken standard Tk framework installation within OS X SDKs
125 // which *HAS* X11 headers in Tk.framework but doesn't install them appropriately
126 #define _TK
127 typedef struct Tk_Window_* Tk_Window;
128 typedef const char* Tk_Uid;
129
130 extern "C" int Tk_Init (Tcl_Interp* interp);
131 extern "C" void Tk_MainLoop();
132 extern "C" Tk_Window Tk_MainWindow (Tcl_Interp* interp) ;
133 extern "C" Tk_Uid Tk_GetUid (const char* str);
134 extern "C" const char* Tk_SetAppName (Tk_Window tkwin, const char* name) ;
135 extern "C" void Tk_GeometryRequest (Tk_Window tkwin, int reqWidth, int reqHeight);
136
137#else
138 #include <tk.h>
139#endif
7fd59977 140
141/*
142 * Global variables used by the main program:
143 */
144
7fd59977 145char *tcl_RcFileName = NULL; /* Name of a user-specific startup script
146 * to source if the application is being run
147 * interactively (e.g. "~/.wishrc"). Set
148 * by Tcl_AppInit. NULL means don't source
149 * anything ever. */
150
151static Tcl_DString command; /* Used to assemble lines of terminal input
152 * into Tcl commands. */
153static Tcl_DString line; /* Used to read the next line from the
154 * terminal input. */
155//static char errorExitCmd[] = "exit 1";
156
157/*
158 * Forward declarations for procedures defined later in this file:
159 */
160
161static void StdinProc (ClientData clientData, int mask);
162
163static void Prompt (Tcl_Interp *Interp, int partial);
164
165static Standard_Boolean tty; /* Non-zero means standard input is a
166 * terminal-like device. Zero means it's
167 * a file. */
168
7fd59977 169Standard_Integer Draw_WindowScreen = 0;
7fd59977 170Standard_Boolean Draw_BlackBackGround = Standard_True;
7fd59977 171
172
173// Initialization of static variables of Draw_Window
174//======================================================
175Draw_Window* Draw_Window::firstWindow = NULL;
176
a6a96586 177// X11 specific part
67d97f0e 178#if !defined(__APPLE__) || defined(MACOSX_USE_GLX)
87225ffd 179#include <X11/Xutil.h>
a6a96586 180#include <Aspect_DisplayConnection.hxx>
181
276130e7 182static unsigned long thePixels[MAXCOLOR];
183
87225ffd 184Display* Draw_WindowDisplay = NULL;
185Colormap Draw_WindowColorMap;
a6a96586 186static Handle(Aspect_DisplayConnection) Draw_DisplayConnection;
187
87225ffd 188// Base_Window struct definition
189//===================================
190struct Base_Window
191{
192 GC gc;
193 XSetWindowAttributes xswa;
194};
195
7fd59977 196//=======================================================================
197//function : Draw_Window
198//purpose :
199//=======================================================================
200Draw_Window::Draw_Window() :
201 base(*new Base_Window()),
202 win(0),
203 myBuffer(0),
204 next(firstWindow),
205 previous(NULL),
206 myUseBuffer(Standard_False),
207 withWindowManager(Standard_True)
208{
209 myMother = RootWindow(Draw_WindowDisplay,
210 Draw_WindowScreen);
211
212 if (firstWindow) firstWindow->previous = this;
213 firstWindow = this;
214}
215
216//=======================================================================
217//function : Draw_Window
218//purpose :
219//=======================================================================
220Draw_Window::Draw_Window(Window mother) :
221 base(*new Base_Window()),
222 win(0),
223 myBuffer(0),
224 next(firstWindow),
225 previous(NULL),
226 myUseBuffer(Standard_False),
227 withWindowManager(Standard_True)
228{
229 myMother = mother;
230
231 if (firstWindow) firstWindow->previous = this;
232 firstWindow = this;
233}
234
235//=======================================================================
236//function : Draw_Window
237//purpose :
238//=======================================================================
239Draw_Window::Draw_Window (const char* title,
240 Standard_Integer X, Standard_Integer Y,
241 Standard_Integer DX, Standard_Integer DY) :
242 base(*new Base_Window()),
243 win(0),
244 myBuffer(0),
245 next(firstWindow),
246 previous(NULL),
247 myUseBuffer(Standard_False),
248 withWindowManager(Standard_True)
249{
250 myMother = RootWindow(Draw_WindowDisplay,
251 Draw_WindowScreen);
252
253 if (firstWindow) firstWindow->previous = this;
254 firstWindow = this;
255 Init(X,Y,DX,DY);
256 SetTitle(title);
257}
258
259//=======================================================================
260//function : Draw_Window
261//purpose :
262//=======================================================================
263Draw_Window::Draw_Window (const char* window ) :
264 base(*new Base_Window()),
265 win(0),
266 myBuffer(0),
267 next(firstWindow),
268 previous(NULL),
269 myUseBuffer(Standard_False),
270 withWindowManager(Standard_True)
271{
272 sscanf(window,"%lx",&win);
273 Standard_Integer X,Y,DX,DY;
274
275 if (firstWindow) firstWindow->previous = this;
276 firstWindow = this;
277 GetPosition(X,Y);
278 DX=HeightWin();
279 DY=WidthWin();
280
281 Init(X,Y,DX,DY);
282}
283
284//=======================================================================
285//function : Draw_Window
286//purpose :
287//=======================================================================
288Draw_Window::Draw_Window (Window mother,
289 char* title,
290 Standard_Integer X, Standard_Integer Y,
291 Standard_Integer DX, Standard_Integer DY) :
292 base(*new Base_Window()),
293 win(0),
294 myBuffer(0),
295 next(firstWindow),
296 previous(NULL),
297 myUseBuffer(Standard_False),
298 withWindowManager(Standard_True)
299{
300 myMother = mother;
301
302 if (firstWindow) firstWindow->previous = this;
303 firstWindow = this;
304 Init(X,Y,DX,DY);
305 SetTitle(title);
306}
307
308//=======================================================================
309//function : ~Draw_Window
310//purpose :
311//=======================================================================
312Draw_Window::~Draw_Window()
313{
314 if (previous)
315 previous->next = next;
316 else
317 firstWindow = next;
318 if (next)
319 next->previous = previous;
320
321 if (myBuffer != 0)
322 {
323 XFreePixmap(Draw_WindowDisplay, myBuffer);
324 myBuffer = 0;
325 }
326 // Liberation pointer on Base_Window
327 delete &base;
328}
329
330//=======================================================================
331//function : Init
332//purpose :
333//=======================================================================
334void Draw_Window::Init(Standard_Integer X, Standard_Integer Y,
335 Standard_Integer DX, Standard_Integer DY)
336{
337 unsigned long setmask;
338
339 if (Draw_BlackBackGround)
340 {
341 base.xswa.background_pixel = BlackPixel(Draw_WindowDisplay,Draw_WindowScreen);
342 base.xswa.border_pixel = WhitePixel(Draw_WindowDisplay,Draw_WindowScreen);
343 }
344 else
345 {
346 base.xswa.background_pixel = WhitePixel(Draw_WindowDisplay,Draw_WindowScreen);
347 base.xswa.border_pixel = BlackPixel(Draw_WindowDisplay,Draw_WindowScreen);
348 }
349 base.xswa.colormap = Draw_WindowColorMap;
350 setmask = CWBackPixel | CWBorderPixel ;
351
352 XSizeHints myHints;
353 myHints.flags = USPosition;
354 myHints.x = (int) X;
355 myHints.y = (int) Y;
356
357 if (win == 0)
358 {
359 win = XCreateWindow(Draw_WindowDisplay,
360 myMother,
361 (int) X,(int) Y,
362 (unsigned int) DX,(unsigned int) DY,
363 5,
364 DefaultDepth(Draw_WindowDisplay,Draw_WindowScreen),
365 InputOutput,
366 DefaultVisual(Draw_WindowDisplay,Draw_WindowScreen),
367 setmask,&base.xswa);
368 XSelectInput(Draw_WindowDisplay, win, ButtonPressMask|ExposureMask|
369 StructureNotifyMask);
370
371 // advise to the window manager to place it where I need
372 XSetWMNormalHints(Draw_WindowDisplay,win,&myHints);
373
7c441da0 374 Atom aDeleteWindowAtom = Draw_DisplayConnection->GetAtom (Aspect_XA_DELETE_WINDOW);
375 XSetWMProtocols (Draw_WindowDisplay, win, &aDeleteWindowAtom, 1);
376
7fd59977 377 if (Draw_VirtualWindows)
378 {
379 myUseBuffer = Standard_True;
380 InitBuffer();
381 }
382 }
383
384 base.gc = XCreateGC(Draw_WindowDisplay, win, 0, NULL);
385
386 XSetPlaneMask(Draw_WindowDisplay,base.gc,AllPlanes);
387 XSetForeground(Draw_WindowDisplay,
388 base.gc, WhitePixel(Draw_WindowDisplay,Draw_WindowScreen));
389 XSetBackground(Draw_WindowDisplay,
390 base.gc, BlackPixel(Draw_WindowDisplay,Draw_WindowScreen));
391 // save in case of window recovery
392
393 base.xswa.backing_store = Always;
394 XChangeWindowAttributes(Draw_WindowDisplay, win,
395 CWBackingStore, &base.xswa);
396
397 XSetLineAttributes (Draw_WindowDisplay, base.gc,
398 0, LineSolid, CapButt, JoinMiter);
399}
400
401//=======================================================================
402//function : InitBuffer
403//purpose :
404//=======================================================================
405void Draw_Window::InitBuffer()
406{
407 if (myUseBuffer) {
408 if (myBuffer != 0) {
409 XFreePixmap (Draw_WindowDisplay, myBuffer);
410 }
411 XWindowAttributes winAttr;
412 XGetWindowAttributes (Draw_WindowDisplay, win, &winAttr);
413 myBuffer = XCreatePixmap (Draw_WindowDisplay, win, winAttr.width, winAttr.height, winAttr.depth);
414 }
415 else if (myBuffer != 0)
416 {
417 XFreePixmap (Draw_WindowDisplay, myBuffer);
418 myBuffer = 0;
419 }
420}
421
422//=======================================================================
423//function : StopWinManager
424//purpose :
425//=======================================================================
426void Draw_Window::StopWinManager()
427{
428// XGCValues winGc;
429 XWindowAttributes winAttr;
430 XGetWindowAttributes (Draw_WindowDisplay, win, &winAttr);
431 Destroy();
432
433 XSizeHints myHints;
434 myHints.flags = USPosition;
435 myHints.x = (int) 30;
436 myHints.y = (int) 100;
437
438 base.xswa.override_redirect = 1;
439 base.xswa.border_pixel = BlackPixel(Draw_WindowDisplay,
440 Draw_WindowScreen);
441 base.xswa.background_pixel = WhitePixel(Draw_WindowDisplay,
442 Draw_WindowScreen);
443
444 withWindowManager = Standard_False;
445
446 win = XCreateWindow(Draw_WindowDisplay, myMother,
447 winAttr.x, winAttr.y,
448 winAttr.width, winAttr.height,
449 2,
450 CopyFromParent, InputOutput, CopyFromParent,
451 CWBorderPixel|CWOverrideRedirect|CWBackPixel, &base.xswa);
452
453
454 // adwise to the window manager to place it where I wish
455 XSetWMNormalHints(Draw_WindowDisplay,win,&myHints);
456
457 // all masks of the old window are reassigned to the new one.
458 XSelectInput(Draw_WindowDisplay,win,winAttr.your_event_mask);
459}
460
461//=======================================================================
462//function : SetPosition
463//purpose :
464//=======================================================================
465void Draw_Window::SetPosition(Standard_Integer NewXpos,
466 Standard_Integer NewYpos)
467{
468 Standard_Integer x,y;
469 GetPosition(x, y);
470
471 if ( (x != NewXpos) || (y != NewYpos) )
472 XMoveWindow(Draw_WindowDisplay, win, NewXpos, NewYpos);
473}
474
475//=======================================================================
476//function : SetDimension
477//purpose :
478//=======================================================================
479void Draw_Window::SetDimension(Standard_Integer NewDx,
480 Standard_Integer NewDy)
481{
482 if ( (NewDx != WidthWin() ) || (NewDy != HeightWin() ) )
483 XResizeWindow(Draw_WindowDisplay, win, NewDx, NewDy);
484}
485
486//=======================================================================
487//function : GetPosition
488//purpose :
489//=======================================================================
490void Draw_Window::GetPosition(Standard_Integer &PosX,
491 Standard_Integer &PosY)
492{
493 XWindowAttributes winAttr;
494 XGetWindowAttributes(Draw_WindowDisplay, win, &winAttr);
495
496 PosX = winAttr.x;
497 PosY = winAttr.y;
498}
499
500//=======================================================================
501//function : HeightWin
502//purpose :
503//=======================================================================
504Standard_Integer Draw_Window::HeightWin() const
505{
506 Standard_Integer DY;
507 XWindowAttributes winAttr;
508 XGetWindowAttributes(Draw_WindowDisplay, win, &winAttr);
509
510 DY = winAttr.height;
511 return DY;
512}
513
514//=======================================================================
515//function : WidthWin
516//purpose :
517//=======================================================================
518Standard_Integer Draw_Window::WidthWin() const
519{
520 Standard_Integer DX;
521 XWindowAttributes winAttr;
522 XGetWindowAttributes(Draw_WindowDisplay, win, &winAttr);
523
524 DX = winAttr.width;
525 return DX;
526}
527
528//=======================================================================
529//function : SetTitle
530//purpose :
531//=======================================================================
ad03c234 532void Draw_Window::SetTitle(const TCollection_AsciiString& theTitle)
7fd59977 533{
ad03c234 534 XStoreName (Draw_WindowDisplay, win, theTitle.ToCString());
7fd59977 535}
536
537//=======================================================================
538//function : GetTitle
539//purpose :
540//=======================================================================
ad03c234 541TCollection_AsciiString Draw_Window::GetTitle() const
7fd59977 542{
ad03c234 543 char* aTitle = NULL;
544 XFetchName (Draw_WindowDisplay, win, &aTitle);
545 return TCollection_AsciiString (aTitle);
7fd59977 546}
547
548//=======================================================================
549//function : GetDrawable
550//purpose :
551//=======================================================================
552Drawable Draw_Window::GetDrawable() const
553{
554 return myUseBuffer ? myBuffer : win;
555}
556
557//=======================================================================
558//function :DefineColor
559//purpose :
560//=======================================================================
561Standard_Boolean Draw_Window::DefineColor(const Standard_Integer i, const char* colorName)
562{
563 XColor color;
564
565 if (!XParseColor(Draw_WindowDisplay,Draw_WindowColorMap,colorName,&color))
566 return Standard_False;
567 if (!XAllocColor(Draw_WindowDisplay,Draw_WindowColorMap,&color))
568 return Standard_False;
569 thePixels[i % MAXCOLOR] = color.pixel;
570 return Standard_True;
571}
572
7c441da0 573//=======================================================================
574//function : IsMapped
575//purpose :
576//=======================================================================
577bool Draw_Window::IsMapped() const
578{
579 if (Draw_VirtualWindows
580 || win == 0)
581 {
582 return false;
583 }
584
585 XFlush (Draw_WindowDisplay);
586 XWindowAttributes aWinAttr;
587 XGetWindowAttributes (Draw_WindowDisplay, win, &aWinAttr);
588 return aWinAttr.map_state == IsUnviewable
589 || aWinAttr.map_state == IsViewable;
590}
591
7fd59977 592//=======================================================================
593//function : DisplayWindow
594//purpose :
595//=======================================================================
596void Draw_Window::DisplayWindow()
597{
598 if (Draw_VirtualWindows)
599 {
600 return;
601 }
7fd59977 602 else
603 {
604 XMapRaised(Draw_WindowDisplay, win);
605 }
606 XFlush(Draw_WindowDisplay);
607}
608
609//=======================================================================
610//function : Hide
611//purpose :
612//=======================================================================
613void Draw_Window::Hide()
614{
615 XUnmapWindow(Draw_WindowDisplay, win);
616}
617
618//=======================================================================
619//function : Destroy
620//purpose :
621//=======================================================================
622void Draw_Window::Destroy()
623{
87225ffd 624 XFreeGC (Draw_WindowDisplay, base.gc);
7fd59977 625 XDestroyWindow(Draw_WindowDisplay, win);
626 win = 0;
627 if (myBuffer != 0)
628 {
629 XFreePixmap(Draw_WindowDisplay, myBuffer);
630 myBuffer = 0;
631 }
632}
633
634//=======================================================================
635//function : Clear
636//purpose :
637//=======================================================================
638void Draw_Window::Clear()
639{
640 if (myUseBuffer)
641 {
642 // XClearArea only applicable for windows
643 XGCValues currValues;
644 XGetGCValues(Draw_WindowDisplay, base.gc, GCBackground | GCForeground, &currValues);
645 XSetForeground(Draw_WindowDisplay, base.gc, currValues.background);
646 XFillRectangle(Draw_WindowDisplay, myBuffer, base.gc, 0, 0, WidthWin(), HeightWin());
647 XSetForeground(Draw_WindowDisplay, base.gc, currValues.foreground);
648 }
649 else
650 {
651 XClearArea(Draw_WindowDisplay, win, 0, 0, 0, 0, False);
652 }
653}
654
655//=======================================================================
656//function : Flush
657//purpose :
658//=======================================================================
659void Draw_Window::Flush()
660{
661 XFlush(Draw_WindowDisplay);
662}
663
664//=======================================================================
665//function : DrawString
666//purpose :
667//=======================================================================
668void Draw_Window::DrawString(int X, int Y, char *text)
669{
670 XDrawString(Draw_WindowDisplay, GetDrawable(), base.gc, X, Y, text, strlen(text));
671}
672
673//=======================================================================
674//function : DrawSegments
675//purpose :
676//=======================================================================
677void Draw_Window::DrawSegments(Segment *tab, int nbElem)
678{
679 XDrawSegments(Draw_WindowDisplay, GetDrawable(), base.gc, (XSegment*) tab, nbElem);
680}
681
682//=======================================================================
683//function : Redraw
684//purpose :
685//=======================================================================
686void Draw_Window::Redraw()
687{
688 if (myUseBuffer) {
689 XCopyArea (Draw_WindowDisplay,
690 myBuffer, win, // source, destination Drawables
691 base.gc,
692 0, 0, // source x, y
693 WidthWin(), HeightWin(),
694 0, 0); // destination x, y
695 }
696}
697
698//=======================================================================
699//function : SetColor
700//purpose :
701//=======================================================================
702void Draw_Window::SetColor(Standard_Integer color)
703{
704 XSetForeground(Draw_WindowDisplay, base.gc, thePixels[color]);
705}
706
707//=======================================================================
708//function : SetMode
709//purpose :
710//=======================================================================
711void Draw_Window::SetMode( int mode)
712{
713 XSetFunction(Draw_WindowDisplay, base.gc, mode);
714}
715
716//=======================================================================
717//function : Save
718//purpose :
719//=======================================================================
720Standard_Boolean Draw_Window::Save (const char* theFileName) const
721{
722 // make sure all draw operations done
723 XSync (Draw_WindowDisplay, True);
724
725 // the attributes
726 XWindowAttributes winAttr;
727 XGetWindowAttributes (Draw_WindowDisplay, win, &winAttr);
728
729 if (!myUseBuffer)
730 {
731 // make sure that the whole window fit on display to prevent BadMatch error
732 XWindowAttributes winAttrRoot;
733 XGetWindowAttributes (Draw_WindowDisplay, XRootWindowOfScreen (winAttr.screen), &winAttrRoot);
734
735 Window winChildDummy;
736 int winLeft = 0;
737 int winTop = 0;
738 XTranslateCoordinates (Draw_WindowDisplay, win, XRootWindowOfScreen (winAttr.screen),
739 0, 0, &winLeft, &winTop, &winChildDummy);
740
741 if (((winLeft + winAttr.width) > winAttrRoot.width) || winLeft < winAttrRoot.x ||
742 ((winTop + winAttr.height) > winAttrRoot.height) || winTop < winAttrRoot.y)
743 {
744 std::cerr << "The window not fully visible! Can't create the snapshot.\n";
745 return Standard_False;
746 }
747 }
748
692613e5 749 XVisualInfo aVInfo;
750 if (XMatchVisualInfo (Draw_WindowDisplay, Draw_WindowScreen, 32, TrueColor, &aVInfo) == 0
751 && XMatchVisualInfo (Draw_WindowDisplay, Draw_WindowScreen, 24, TrueColor, &aVInfo) == 0)
7fd59977 752 {
692613e5 753 std::cerr << "24-bit TrueColor visual is not supported by server!\n";
7fd59977 754 return Standard_False;
755 }
756
692613e5 757 Image_AlienPixMap anImage;
758 bool isBigEndian = Image_PixMap::IsBigEndianHost();
759 const Standard_Size aSizeRowBytes = Standard_Size(winAttr.width) * 4;
dc858f4c 760 if (!anImage.InitTrash (isBigEndian ? Image_Format_RGB32 : Image_Format_BGR32,
692613e5 761 Standard_Size(winAttr.width), Standard_Size(winAttr.height), aSizeRowBytes))
7fd59977 762 {
692613e5 763 return Standard_False;
7fd59977 764 }
692613e5 765 anImage.SetTopDown (true);
766
767 XImage* anXImage = XCreateImage (Draw_WindowDisplay, aVInfo.visual,
768 32, ZPixmap, 0, (char* )anImage.ChangeData(), winAttr.width, winAttr.height, 32, int(aSizeRowBytes));
769 anXImage->bitmap_bit_order = anXImage->byte_order = (isBigEndian ? MSBFirst : LSBFirst);
770 if (XGetSubImage (Draw_WindowDisplay, GetDrawable(),
771 0, 0, winAttr.width, winAttr.height,
772 AllPlanes, ZPixmap, anXImage, 0, 0) == NULL)
7fd59977 773 {
692613e5 774 anXImage->data = NULL;
775 XDestroyImage (anXImage);
7fd59977 776 return Standard_False;
777 }
7fd59977 778
692613e5 779 // destroy the image
780 anXImage->data = NULL;
781 XDestroyImage (anXImage);
782
783 // save the image
784 return anImage.Save (theFileName);
785}
7fd59977 786
67d97f0e 787//=======================================================================
788//function : Wait
789//purpose :
790//=======================================================================
791
792void Draw_Window::Wait (Standard_Boolean wait)
793{
794 Flush();
795 if (!wait) {
796 XSelectInput(Draw_WindowDisplay,win,
797 ButtonPressMask|ExposureMask | StructureNotifyMask |
798 PointerMotionMask);
799 }
800 else {
801 XSelectInput(Draw_WindowDisplay,win,
802 ButtonPressMask|ExposureMask | StructureNotifyMask);
803 }
804}
805
7fd59977 806//=======================================================================
807//function : ProcessEvent
808//purpose :
809//=======================================================================
810
811void ProcessEvent(Draw_Window& win, XEvent& xev)
812{
96a95605 813 Standard_Integer X,Y,button;
7fd59977 814 KeySym keysym;
815 XComposeStatus stat;
816 char chainekey[10];
817
7c441da0 818 switch (xev.type)
819 {
820 case ClientMessage:
821 {
822 if (xev.xclient.data.l[0] == (int )Draw_DisplayConnection->GetAtom (Aspect_XA_DELETE_WINDOW))
823 {
824 // just hide the window
825 win.Hide();
826 }
827 return;
828 }
7fd59977 829 case Expose :
830 win.WExpose();
831 break;
832
833 case ButtonPress :
834 X = xev.xbutton.x;
835 Y = xev.xbutton.y;
836 button = xev.xbutton.button;
837 win.WButtonPress(X,Y,button);
838 break;
839
840 case ButtonRelease :
841 X = xev.xbutton.x;
842 Y = xev.xbutton.y;
843 button = xev.xbutton.button;
844 win.WButtonRelease(X,Y,button);
845 break;
846
847 case KeyPress :
96a95605 848 XLookupString(&(xev.xkey),
7fd59977 849 chainekey,
850 10,
851 &keysym,
852 &stat);
7fd59977 853 break;
854
855 case MotionNotify :
856 X = xev.xmotion.x;
857 Y = xev.xmotion.y;
858 win.WMotionNotify(X,Y);
859 break;
860
861 case ConfigureNotify :
862 if (win.withWindowManager)
863 win.WConfigureNotify(xev.xconfigure.x, xev.xconfigure.y,
864 xev.xconfigure.width,
865 xev.xconfigure.height);
866 break;
867
868 case UnmapNotify :
869
870 win.WUnmapNotify();
871 break;
872 }
873}
874
875//=======================================================================
876//function : WExpose
877//purpose :
878//=======================================================================
879void Draw_Window::WExpose()
880{
881}
882
883//=======================================================================
884//function : WButtonPress
885//purpose :
886//=======================================================================
887void Draw_Window::WButtonPress(const Standard_Integer,
888 const Standard_Integer,
889 const Standard_Integer&)
890{
891}
892
893//=======================================================================
894//function : WButtonRelease
895//purpose :
896//=======================================================================
897void Draw_Window::WButtonRelease(const Standard_Integer,
898 const Standard_Integer,
899 const Standard_Integer&)
900{
901}
902
903/**************************
904//=======================================================================
905//function : WKeyPress
906//purpose :
907//=======================================================================
908
909void Draw_Window::WKeyPress(char, KeySym&)
910{
911}
912***************************/
913
914//=======================================================================
915//function : WMotionNotify
916//purpose :
917//=======================================================================
918void Draw_Window::WMotionNotify(const Standard_Integer ,
919 const Standard_Integer )
920{
921}
922
923//=======================================================================
924//function : WConfigureNotify
925//purpose :
926//=======================================================================
927
928void Draw_Window::WConfigureNotify(const Standard_Integer,
929 const Standard_Integer,
930 const Standard_Integer,
931 const Standard_Integer)
932{
933}
934
7fd59977 935//=======================================================================
936//function : WUnmapNotify
937//purpose :
938//=======================================================================
939
940void Draw_Window::WUnmapNotify()
941{
942}
943
944
945//======================================================
946// funtion : ProcessEvents
947// purpose : process pending X events
948//======================================================
949
950static void ProcessEvents(ClientData,int)
951{
952 // test for X Event
953
954 while (XPending(Draw_WindowDisplay)) {
955
956 XEvent xev;
957 xev.type = 0;
958
959 XNextEvent(Draw_WindowDisplay,&xev);
960
961 /* search the window in the window list */
962 Draw_Window* w = Draw_Window::firstWindow;
963 Standard_Integer found=0;
964 while (w) {
965 if (xev.xany.window == w->win) {
966 ProcessEvent(*w, xev);
967 found=1;
968 break;
969 }
970 w = w->next;
971 }
972 if (found==0) {
973 Tk_HandleEvent(&xev);
974 }
975 }
976}
977
67d97f0e 978//======================================================
979// funtion : GetNextEvent()
980// purpose :
981//======================================================
982void GetNextEvent(Event& ev)
983{
984 XEvent xev;
985 XNextEvent(Draw_WindowDisplay, &xev);
986 switch(xev.type)
987 {
988 case ButtonPress :
989 ev.type = 4;
990 ev.window = xev.xbutton.window;
991 ev.button = xev.xbutton.button;
992 ev.x = xev.xbutton.x;
993 ev.y = xev.xbutton.y;
994 break;
995
996 case MotionNotify :
997 ev.type = 6;
998 ev.window = xev.xmotion.window;
999 ev.button = 0;
1000 ev.x = xev.xmotion.x;
1001 ev.y = xev.xmotion.y;
1002 break;
1003 }
1004}
1005#endif //__APPLE__
1006
7fd59977 1007//======================================================
1008// funtion :Run_Appli
1009// purpose :
1010//======================================================
1011
1012
bf03eb83 1013static Standard_Boolean(*Interprete) (const char*);
7fd59977 1014
bf03eb83 1015void Run_Appli(Standard_Boolean (*interprete) (const char*))
7fd59977 1016{
1017 Tcl_Channel outChannel, inChannel ;
1018 Interprete = interprete;
1019
1020#ifdef _TK
1021
1022 /*
1023 * Commands will come from standard input, so set up an event
1024 * handler for standard input. If the input device is aEvaluate the
1025 * .rc file, if one has been specified, set up an event handler
1026 * for standard input, and print a prompt if the input
1027 * device is a terminal.
1028 */
1029 inChannel = Tcl_GetStdChannel(TCL_STDIN);
1030 if (inChannel) {
1031 Tcl_CreateChannelHandler(inChannel, TCL_READABLE, StdinProc,
1032 (ClientData) inChannel);
1033 }
1034
1035 // Create a handler for the draw display
1036
1037 // Adding of the casting into void* to be able to compile on AO1
1038 // ConnectionNumber(Draw_WindowDisplay) is an int 32 bits
1039 // (void*) is a pointer 64 bits ???????
1040
67d97f0e 1041#if !defined(__APPLE__) || defined(MACOSX_USE_GLX)
7fd59977 1042#if TCL_MAJOR_VERSION < 8
1043 Tk_CreateFileHandler((void*) ConnectionNumber(Draw_WindowDisplay),
1044 TK_READABLE, ProcessEvents,(ClientData) 0 );
1045#else
1046 Tk_CreateFileHandler(ConnectionNumber(Draw_WindowDisplay),
1047 TK_READABLE, ProcessEvents,(ClientData) 0 );
1048#endif
67d97f0e 1049#endif // __APPLE__
7fd59977 1050
1051#endif
1052
e59839c8 1053 Draw_Interpretor& aCommands = Draw::GetInterpretor();
1054
1055 if (tty) Prompt(aCommands.Interp(), 0);
1056 Prompt(aCommands.Interp(), 0);
7fd59977 1057
1058 outChannel = Tcl_GetStdChannel(TCL_STDOUT);
1059 if (outChannel) {
1060 Tcl_Flush(outChannel);
1061 }
1062 Tcl_DStringInit(&command);
1063
1064 /*
1065 * Loop infinitely, waiting for commands to execute. When there
1066 * are no windows left, Tk_MainLoop returns and we exit.
1067 */
1068
1069#ifdef _TK
1070
1071 if (Draw_VirtualWindows) {
1072 // main window will never shown
1073 // but main loop will parse all Xlib messages
e59839c8 1074 Tcl_Eval(aCommands.Interp(), "wm withdraw .");
7fd59977 1075 }
1076 Tk_MainLoop();
1077
1078#else
1079
1080 fd_set readset;
1081 Standard_Integer count = ConnectionNumber(Draw_WindowDisplay);
1082 Standard_Integer numfd;
1083 while (1) {
1084 FD_ZERO(&readset);
1085 FD_SET(0,&readset);
1086 FD_SET(count,&readset);
1087#ifdef HPUX
1088 numfd = select(count+1,(Integer*)&readset,NULL,NULL,NULL);
1089#else
1090 numfd = select(count+1,&readset,NULL,NULL,NULL);
1091#endif
1092 if (FD_ISSET(0,&readset)) StdinProc((ClientData)0,0);
1093 if (FD_ISSET(count,&readset)) ProcessEvents((ClientData)0,0);
1094 }
1095
1096#endif
a0fc422a 1097 NCollection_List<Draw_Window::FCallbackBeforeTerminate>::Iterator Iter(MyCallbacks);
1098 for(; Iter.More(); Iter.Next())
1099 {
1100 (*Iter.Value())();
1101 }
7fd59977 1102}
1103
1104//======================================================
1105// funtion : Init_Appli()
1106// purpose :
1107//======================================================
1108Standard_Boolean Init_Appli()
1109{
e59839c8 1110 Draw_Interpretor& aCommands = Draw::GetInterpretor();
1111 aCommands.Init();
1112 interp = aCommands.Interp();
7fd59977 1113
1114 Tcl_Init(interp) ;
1115 try {
1116 OCC_CATCH_SIGNALS
1117 Tk_Init(interp) ;
1118 } catch (Standard_Failure) {
1119 cout <<" Pb au lancement de TK_Init "<<endl;
1120 }
1121
1122 Tcl_StaticPackage(interp, "Tk", Tk_Init, (Tcl_PackageInitProc *) NULL);
1123
262bf46d 1124 Tk_Window aMainWindow = Tk_MainWindow(interp) ;
1125 if (aMainWindow == NULL) {
7fb60cfd 1126#if ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 5)))
1127 fprintf(stderr, "%s\n", Tcl_GetStringResult(interp));
1128#else
7fd59977 1129 fprintf(stderr, "%s\n", interp->result);
7fb60cfd 1130#endif
7fd59977 1131 exit(1);
1132 }
262bf46d 1133#if defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1134 Tk_SetAppName(aMainWindow, "Draw");
1135#else
1136 Tk_Name(aMainWindow) = Tk_GetUid(Tk_SetAppName(aMainWindow, "Draw"));
1137#endif
7fd59977 1138
262bf46d 1139 Tk_GeometryRequest (aMainWindow, 200, 200);
7fd59977 1140
67d97f0e 1141#if !defined(__APPLE__) || defined(MACOSX_USE_GLX)
a6a96586 1142 if (Draw_DisplayConnection.IsNull())
1143 {
1144 try
1145 {
1146 Draw_DisplayConnection = new Aspect_DisplayConnection();
1147 }
1148 catch (Standard_Failure)
1149 {
1150 std::cout << "Cannot open display. Interpret commands in batch mode." << std::endl;
262bf46d 1151 return Standard_False;
a6a96586 1152 }
7fd59977 1153 }
a6a96586 1154 if (Draw_WindowDisplay == NULL)
1155 {
1156 Draw_WindowDisplay = Draw_DisplayConnection->GetDisplay();
7fd59977 1157 }
1158 //
1159 // synchronize the display server : could be done within Tk_Init
1160 //
1161 XSynchronize(Draw_WindowDisplay, True);
1162 XSetInputFocus(Draw_WindowDisplay,
1163 PointerRoot,
1164 RevertToPointerRoot,
1165 CurrentTime);
1166
1167 Draw_WindowScreen = DefaultScreen(Draw_WindowDisplay);
1168 Draw_WindowColorMap = DefaultColormap(Draw_WindowDisplay,
1169 Draw_WindowScreen);
67d97f0e 1170#endif // __APPLE__
1171
7fd59977 1172 tty = isatty(0);
1173 Tcl_SetVar(interp,"tcl_interactive",(char*)(tty ? "1" : "0"), TCL_GLOBAL_ONLY);
1174// Tcl_SetVar(interp,"tcl_interactive",tty ? "1" : "0", TCL_GLOBAL_ONLY);
1175 return Standard_True;
1176}
1177
1178//======================================================
1179// funtion : Destroy_Appli()
1180// purpose :
1181//======================================================
1182void Destroy_Appli()
1183{
1184 //XCloseDisplay(Draw_WindowDisplay);
1185}
1186
7fd59977 1187/*
1188 *----------------------------------------------------------------------
1189 *
1190 * StdinProc --
1191 *
1192 * This procedure is invoked by the event dispatcher whenever
1193 * standard input becomes readable. It grabs the next line of
1194 * input characters, adds them to a command being assembled, and
1195 * executes the command if it's complete.
1196 *
1197 * Results:
1198 * None.
1199 *
1200 * Side effects:
1201 * Could be almost arbitrary, depending on the command that's
1202 * typed.
1203 *
1204 *----------------------------------------------------------------------
1205 */
1206
1207 /* ARGSUSED */
1208//static void StdinProc(ClientData clientData, int mask)
1209static void StdinProc(ClientData clientData, int )
1210{
1211 static int gotPartial = 0;
1212 char *cmd;
1213// int code, count;
1214 int count;
1215 Tcl_Channel chan = (Tcl_Channel) clientData;
1216
1217 // MSV Nov 2, 2001: patch for TCL 8.3: initialize line to avoid exception
1218 // when first user input is an empty string
1219 Tcl_DStringFree(&line);
1220 count = Tcl_Gets(chan, &line);
1221
1222 // MKV 26.05.05
1223#if ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4)))
1224 Tcl_DString linetmp;
1225 Tcl_DStringInit(&linetmp);
1226 Tcl_UniChar * UniCharString;
1227 UniCharString = Tcl_UtfToUniCharDString(Tcl_DStringValue(&line),-1,&linetmp);
1228 Standard_Integer l = Tcl_UniCharLen(UniCharString);
1229 TCollection_AsciiString AsciiString("");
1230 Standard_Character Character;
1231 Standard_Integer i;
1232 for (i=0; i<l; i++) {
1233 Character = UniCharString[i];
1234 AsciiString.AssignCat(Character);
1235 }
1236 Tcl_DStringInit(&line);
1237 Tcl_DStringAppend(&line, AsciiString.ToCString(), -1);
1238#endif
1239 if (count < 0) {
1240 if (!gotPartial) {
1241 if (tty) {
1242 Tcl_Exit(0);
1243 } else {
1244 Tcl_DeleteChannelHandler(chan, StdinProc, (ClientData) chan);
1245 }
1246 return;
1247 } else {
1248 count = 0;
1249 }
1250 }
1251
1252 (void) Tcl_DStringAppend(&command, Tcl_DStringValue(&line), -1);
1253 cmd = Tcl_DStringAppend(&command, "\n", -1);
1254 Tcl_DStringFree(&line);
1255 try {
1256 OCC_CATCH_SIGNALS
1257 if (!Tcl_CommandComplete(cmd)) {
1258 gotPartial = 1;
1259 goto prompt;
1260 }
1261 gotPartial = 0;
1262
1263 /*
1264 * Disable the stdin channel handler while evaluating the command;
1265 * otherwise if the command re-enters the event loop we might
1266 * process commands from stdin before the current command is
1267 * finished. Among other things, this will trash the text of the
1268 * command being evaluated.
1269 */
1270
1271 Tcl_CreateChannelHandler(chan, 0, StdinProc, (ClientData) chan);
1272
1273
1274 /*
1275 * Disable the stdin file handler while evaluating the command;
1276 * otherwise if the command re-enters the event loop we might
1277 * process commands from stdin before the current command is
1278 * finished. Among other things, this will trash the text of the
1279 * command being evaluated.
1280 */
1281
1282#ifdef _TK
1283 // Tk_CreateFileHandler(0, 0, StdinProc, (ClientData) 0);
1284#endif
1285 //
1286 // xab average to avoid an output SIGBUS of DRAW
1287 // to ultimately prescise or remove once
1288 // the problem of free on the global variable at the average
1289 //
1290 //
1291
1292 Interprete(cmd);
1293
1294
1295 Tcl_CreateChannelHandler(chan, TCL_READABLE, StdinProc,
1296 (ClientData) chan);
1297 Tcl_DStringFree(&command);
1298
1299 /*
1300 * Output a prompt.
1301 */
1302
1303prompt:
1304 if (tty) Prompt(interp, gotPartial);
1305
1306 } catch (Standard_Failure) {}
1307
1308}
1309
1310#else
1311
1312// Source Specifique WNT
1313
1314/****************************************************\
1315* Draw_Window.cxx :
1316*
1317\****************************************************/
1318
1319#include "Draw_Window.hxx"
1320#include "DrawRessource.h"
1321#include "init.h"
1322
1323#include <Draw_Appli.hxx>
1324#include <OSD.hxx>
1325
1326#include <tk.h>
1327
1328#define PENWIDTH 1
1329#define CLIENTWND 0
1330// Position of information in the extra memory
1331
1332// indicates SUBSYSTEM:CONSOLE linker option, to be set to True in main()
1333Standard_EXPORT
1334Standard_Boolean Draw_IsConsoleSubsystem = Standard_False;
1335
1336
1337Standard_Boolean Draw_BlackBackGround = Standard_True;
1338
1339// Creation of color stylos
1340HPEN colorPenTab[MAXCOLOR] = {CreatePen(PS_SOLID, PENWIDTH, RGB(255,255,255)),
1341 CreatePen(PS_SOLID, PENWIDTH, RGB(255,0,0)),
1342 CreatePen(PS_SOLID, PENWIDTH, RGB(0,255,0)),
1343 CreatePen(PS_SOLID, PENWIDTH, RGB(0,0,255)),
1344 CreatePen(PS_SOLID, PENWIDTH, RGB(0,255,255)),
1345 CreatePen(PS_SOLID, PENWIDTH, RGB(255,215,0)),
1346 CreatePen(PS_SOLID, PENWIDTH, RGB(255,0,255)),
1347 CreatePen(PS_SOLID, PENWIDTH, RGB(255,52,179)),
1348 CreatePen(PS_SOLID, PENWIDTH, RGB(255,165,0)),
1349 CreatePen(PS_SOLID, PENWIDTH, RGB(255,228,225)),
1350 CreatePen(PS_SOLID, PENWIDTH, RGB(255,160,122)),
1351 CreatePen(PS_SOLID, PENWIDTH, RGB(199,21,133)),
1352 CreatePen(PS_SOLID, PENWIDTH, RGB(255,255,0)),
1353 CreatePen(PS_SOLID, PENWIDTH, RGB(240,230,140)),
1354 CreatePen(PS_SOLID, PENWIDTH, RGB(255,127,80))};
1355
1356// Correspondance mode X11 and WINDOWS NT
1357int modeTab[16] = {R2_BLACK, R2_MASKPEN, R2_MASKPENNOT, R2_COPYPEN,
1358 R2_MASKNOTPEN, R2_NOP, R2_XORPEN, R2_MERGEPEN,
1359 R2_NOTMASKPEN, R2_NOTXORPEN, R2_NOT, R2_MERGEPENNOT,
1360 R2_NOTCOPYPEN, R2_MERGENOTPEN, R2_NOTMERGEPEN, R2_WHITE};
1361
1362/*--------------------------------------------------------*\
1363| CREATE DRAW WINDOW PROCEDURE
1364\*--------------------------------------------------------*/
1365HWND DrawWindow::CreateDrawWindow(HWND hWndClient, int nitem)
1366{
1367 if (Draw_IsConsoleSubsystem) {
ad03c234 1368 HWND aWin = CreateWindowW (DRAWCLASS, DRAWTITLE,
7fd59977 1369 WS_OVERLAPPEDWINDOW,
1370 1,1,1,1,
1371 NULL, NULL,::GetModuleHandle(NULL), NULL);
87c58d4f
K
1372 if (!Draw_VirtualWindows)
1373 {
1374 SetWindowPos(aWin, HWND_TOPMOST, 1,1,1,1, SWP_NOMOVE);
1375 SetWindowPos(aWin, HWND_NOTOPMOST, 1,1,1,1, SWP_NOMOVE);
1376 }
7fd59977 1377 return aWin;
1378 }
1379 else {
ad03c234 1380 HANDLE hInstance = (HANDLE )GetWindowLongPtrW (hWndClient, GWLP_HINSTANCE);
7fd59977 1381
ad03c234 1382 return CreateMDIWindowW(DRAWCLASS, DRAWTITLE,
7fd59977 1383 WS_CAPTION | WS_CHILD | WS_THICKFRAME,
1384 1,1,0,0,
1385 hWndClient, (HINSTANCE)hInstance, nitem);
1386 }
1387}
1388
1389
1390/*--------------------------------------------------------*\
1391| DRAW WINDOW PROCEDURE
1392\*--------------------------------------------------------*/
6a7d83c4 1393LRESULT APIENTRY DrawWindow::DrawProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam )
7fd59977 1394{
ad03c234 1395 DrawWindow* localObjet = (DrawWindow* )GetWindowLongPtrW (hWnd, CLIENTWND);
7fd59977 1396 if (!localObjet)
ad03c234 1397 {
1398 return Draw_IsConsoleSubsystem
1399 ? DefWindowProcW (hWnd, wMsg, wParam, lParam)
1400 : DefMDIChildProcW (hWnd, wMsg, wParam, lParam);
1401 }
1402
1403 switch (wMsg)
1404 {
7c441da0 1405 case WM_CLOSE:
1406 {
1407 localObjet->Hide();
1408 return 0; // do nothing - window destruction should be performed by application
1409 }
ad03c234 1410 case WM_PAINT:
7fd59977 1411 {
ad03c234 1412 PAINTSTRUCT ps;
1413 BeginPaint (hWnd, &ps);
1414 if (localObjet->GetUseBuffer())
1415 {
1416 localObjet->Redraw();
1417 }
7fd59977 1418 else
ad03c234 1419 {
1420 localObjet->WExpose();
1421 }
1422 EndPaint (hWnd, &ps);
1423 return 0;
7fd59977 1424 }
ad03c234 1425 case WM_SIZE:
1426 {
1427 if (localObjet->GetUseBuffer())
1428 {
1429 localObjet->InitBuffer();
1430 localObjet->WExpose();
1431 localObjet->Redraw();
1432 return 0;
1433 }
1434 break;
7fd59977 1435 }
7fd59977 1436 }
ad03c234 1437 return Draw_IsConsoleSubsystem
1438 ? DefWindowProcW (hWnd, wMsg, wParam, lParam)
1439 : DefMDIChildProcW (hWnd, wMsg, wParam, lParam);
7fd59977 1440}
1441
1442
1443
1444/*
1445** IMPLEMENTATION of the CLASS DRAWWINDOW
1446 */
1447
1448/*--------------------------------------------------------*\
1449| Initialization of static variables of DrawWindow
1450\*--------------------------------------------------------*/
1451
1452DrawWindow* DrawWindow::firstWindow = NULL;
1453HWND DrawWindow::hWndClientMDI = 0;
1454
1455/*--------------------------------------------------------*\
1456| Constructors of Draw_Window
1457\*--------------------------------------------------------*/
1458
1459// Default Constructor
1460//________________________
1461DrawWindow::DrawWindow() :
1462 win(0),
1463 next(firstWindow),
1464 previous(NULL),
1465 myMemHbm(NULL),
1466 myUseBuffer(Standard_False)
1467{
1468 if (firstWindow) firstWindow->previous = this;
1469 firstWindow = this;
1470}
1471
1472//________________________
7c65581d 1473DrawWindow::DrawWindow(const char* title,
7fd59977 1474 Standard_Integer X, Standard_Integer Y,
1475 Standard_Integer dX,Standard_Integer dY) :
1476 win(0), next(firstWindow), previous(NULL), myMemHbm(NULL), myUseBuffer(Standard_False)
1477{
1478 if (firstWindow) firstWindow->previous = this;
1479 firstWindow = this;
1480 Init(X, Y, dX, dY);
1481 SetTitle(title);
1482}
7c65581d 1483DrawWindow::DrawWindow(const char* title,
7fd59977 1484 Standard_Integer X, Standard_Integer Y,
1485 Standard_Integer dX,Standard_Integer dY,
1486 HWND theWin) :
1487 win(theWin),next(firstWindow), previous(NULL), myMemHbm(NULL), myUseBuffer(Standard_False)
1488{
1489 if (firstWindow) firstWindow->previous = this;
1490 firstWindow = this;
1491 Init(X, Y, dX, dY);
1492 SetTitle(title);
1493}
1494
1495
1496
1497/*--------------------------------------------------------*\
1498| Destructor of DrawWindow
1499\*--------------------------------------------------------*/
1500DrawWindow::~DrawWindow()
1501{
1502 if (previous)
1503 previous->next = next;
1504 else
1505 firstWindow = next;
1506 if (next)
1507 next->previous = previous;
1508
1509 // Delete 'off-screen drawing'-related objects
1510 if (myMemHbm) {
1511 DeleteObject(myMemHbm);
1512 myMemHbm = NULL;
1513 }
1514}
1515
1516
1517
1518/*--------------------------------------------------------*\
1519| Init
1520\*--------------------------------------------------------*/
1521void DrawWindow::Init(Standard_Integer theXLeft, Standard_Integer theYTop,
1522 Standard_Integer theWidth, Standard_Integer theHeight)
1523{
6a7d83c4 1524 if (win == NULL)
7fd59977 1525 {
1526 win = CreateDrawWindow(hWndClientMDI, 0);
1527 }
1528
1529 // include decorations in the window dimensions
1530 // to reproduce same behaviour of Xlib window.
ad03c234 1531 DWORD aWinStyle = GetWindowLongW (win, GWL_STYLE);
1532 DWORD aWinStyleEx = GetWindowLongW (win, GWL_EXSTYLE);
7fe83417 1533 HMENU aMenu = GetMenu (win);
1534
1535 RECT aRect;
1536 aRect.top = theYTop;
1537 aRect.bottom = theYTop + theHeight;
1538 aRect.left = theXLeft;
1539 aRect.right = theXLeft + theWidth;
1540 AdjustWindowRectEx (&aRect, aWinStyle, aMenu != NULL ? TRUE : FALSE, aWinStyleEx);
1541
1542 SetPosition (aRect.left, aRect.top);
1543 SetDimension (aRect.right - aRect.left, aRect.bottom - aRect.top);
7fd59977 1544 // Save the pointer at the instance associated to the window
ad03c234 1545 SetWindowLongPtrW (win, CLIENTWND, (LONG_PTR)this);
7fd59977 1546 HDC hDC = GetDC(win);
1547 SetBkColor(hDC, RGB(0, 0, 0));
1548 myCurrPen = 3;
1549 myCurrMode = 3;
1550 SelectObject(hDC, colorPenTab[myCurrPen]); // Default pencil
1551 SelectObject(hDC, GetStockObject(BLACK_BRUSH));
1552 SetTextColor(hDC, RGB(0,0,255));
1553 ReleaseDC(win, hDC);
1554
1555 if (Draw_VirtualWindows)
1556 {
1557 // create a virtual window
1558 SetUseBuffer (Standard_True);
1559 }
1560}
1561
1562/*--------------------------------------------------------*\
1563| SetUseBuffer
1564\*--------------------------------------------------------*/
1565void DrawWindow::SetUseBuffer(Standard_Boolean use)
1566{
1567 myUseBuffer = use;
1568 InitBuffer();
1569}
1570
1571/*--------------------------------------------------------*\
1572| InitBuffer
1573\*--------------------------------------------------------*/
1574void DrawWindow::InitBuffer()
1575{
1576 if (myUseBuffer) {
1577 RECT rc;
1578 HDC hDC = GetDC(win);
1579 GetClientRect(win, &rc);
1580 if (myMemHbm) {
1581 BITMAP aBmp;
b07ce12b 1582 GetObjectW (myMemHbm, sizeof(BITMAP), &aBmp);
7fd59977 1583 if (rc.right-rc.left == aBmp.bmWidth && rc.bottom-rc.top == aBmp.bmHeight) return;
1584 DeleteObject(myMemHbm);
1585 }
1586 myMemHbm = (HBITMAP)CreateCompatibleBitmap(hDC,
1587 rc.right-rc.left,
1588 rc.bottom-rc.top);
1589 HDC aMemDC = GetMemDC(hDC);
1590 FillRect(aMemDC, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH));
1591 ReleaseMemDC(aMemDC);
1592 ReleaseDC(win, hDC);
1593 }
1594 else {
1595 if (myMemHbm) {
1596 DeleteObject(myMemHbm);
1597 myMemHbm = NULL;
1598 }
1599 }
1600}
1601
1602/*--------------------------------------------------------*\
1603| GetMemDC
1604\*--------------------------------------------------------*/
1605HDC DrawWindow::GetMemDC(HDC theWinDC)
1606{
1607 if (!myUseBuffer) return NULL;
1608
1609 HDC aWorkDC = CreateCompatibleDC(theWinDC);
1610 myOldHbm = (HBITMAP)SelectObject(aWorkDC, myMemHbm);
1611 SetROP2(aWorkDC, modeTab[myCurrMode]);
1612 SelectObject(aWorkDC, colorPenTab[myCurrPen]);
1613 SetBkColor(aWorkDC, RGB(0, 0, 0));
1614 SelectObject(aWorkDC, GetStockObject(BLACK_BRUSH));
1615 SetTextColor(aWorkDC, RGB(0,0,255));
1616 return aWorkDC;
1617}
1618
1619
1620/*--------------------------------------------------------*\
1621| ReleaseMemDC
1622\*--------------------------------------------------------*/
1623void DrawWindow::ReleaseMemDC(HDC theMemDC)
1624{
1625 if (!myUseBuffer || !theMemDC) return;
1626
1627 if (myOldHbm) SelectObject(theMemDC, myOldHbm);
1628 DeleteDC(theMemDC);
1629}
1630
1631
1632/*--------------------------------------------------------*\
1633| SetPosition
1634\*--------------------------------------------------------*/
1635void DrawWindow::SetPosition(Standard_Integer posX, Standard_Integer posY)
1636{
72a2da56 1637 UINT aFlags = SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER;
1638 if (Draw_VirtualWindows)
1639 {
1640 aFlags |= SWP_NOSENDCHANGING;
1641 }
1642 SetWindowPos (win, 0, posX, posY, 0, 0, aFlags);
7fd59977 1643}
1644
1645
1646/*--------------------------------------------------------*\
1647| SetDimension
1648\*--------------------------------------------------------*/
1649void DrawWindow::SetDimension(Standard_Integer dimX, Standard_Integer dimY)
1650{
72a2da56 1651 UINT aFlags = SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER;
1652 if (Draw_VirtualWindows)
1653 {
1654 aFlags |= SWP_NOSENDCHANGING;
1655 }
1656 SetWindowPos (win, 0, 0, 0, dimX, dimY, aFlags);
7fd59977 1657}
1658
1659
1660/*--------------------------------------------------------*\
1661| GetPosition
1662\*--------------------------------------------------------*/
1663void DrawWindow::GetPosition(Standard_Integer &dimX,
1664 Standard_Integer &dimY)
1665{
1666 RECT rect;
1667 GetWindowRect(win, &rect);
1668
1669 POINT point;
1670 point.x = rect.left;
1671 point.y = rect.top;
1672
1673 ScreenToClient(hWndClientMDI, &point);
1674 dimX = point.x;
1675 dimY = point.y;
1676}
1677
1678
1679/*--------------------------------------------------------*\
1680| HeightWin
1681\*--------------------------------------------------------*/
1682Standard_Integer DrawWindow::HeightWin() const
1683{
1684 RECT rect;
1685 GetClientRect(win, &rect);
1686 return(rect.bottom-rect.top);
1687}
1688
1689
1690/*--------------------------------------------------------*\
1691| WidthWin
1692\*--------------------------------------------------------*/
1693Standard_Integer DrawWindow::WidthWin() const
1694{
1695 RECT rect;
1696 GetClientRect(win, &rect);
1697 return(rect.right-rect.left);
1698}
1699
1700
1701/*--------------------------------------------------------*\
1702| SetTitle
1703\*--------------------------------------------------------*/
ad03c234 1704void DrawWindow::SetTitle (const TCollection_AsciiString& theTitle)
7fd59977 1705{
ad03c234 1706 const TCollection_ExtendedString aTitleW (theTitle);
1707 SetWindowTextW (win, aTitleW.ToWideString());
7fd59977 1708}
1709
1710
1711/*--------------------------------------------------------*\
1712| GetTitle
7fd59977 1713\*--------------------------------------------------------*/
ad03c234 1714TCollection_AsciiString DrawWindow::GetTitle() const
7fd59977 1715{
ad03c234 1716 wchar_t aTitleW[32];
1717 GetWindowTextW (win, aTitleW, 30);
1718 return TCollection_AsciiString (aTitleW);
7fd59977 1719}
1720
7c441da0 1721//=======================================================================
1722//function : IsMapped
1723//purpose :
1724//=======================================================================
1725bool Draw_Window::IsMapped() const
1726{
1727 if (Draw_VirtualWindows
1728 || win == NULL)
1729 {
1730 return false;
1731 }
1732
1733 LONG aWinStyle = GetWindowLongW (win, GWL_STYLE);
1734 return (aWinStyle & WS_VISIBLE) != 0
1735 && (aWinStyle & WS_MINIMIZE) == 0;
1736}
7fd59977 1737
1738/*--------------------------------------------------------*\
1739| DisplayWindow
1740\*--------------------------------------------------------*/
1741void DrawWindow::DisplayWindow()
1742{
1743 if (Draw_VirtualWindows)
1744 {
1745 return;
1746 }
1747 ShowWindow (win, SW_SHOW);
1748 UpdateWindow (win);
1749}
1750
1751
1752/*--------------------------------------------------------*\
1753| Hide
1754\*--------------------------------------------------------*/
1755void DrawWindow::Hide()
1756{
1757 ShowWindow(win, SW_HIDE);
1758}
1759
1760
1761/*--------------------------------------------------------*\
1762| Destroy
1763\*--------------------------------------------------------*/
1764void DrawWindow::Destroy()
1765{
1766 DestroyWindow(win);
1767}
1768
1769
1770
1771/*--------------------------------------------------------*\
1772| Clear
1773\*--------------------------------------------------------*/
1774void DrawWindow::Clear()
1775{
1776 HDC hDC = GetDC(win);
1777 HDC aWorkDC = myUseBuffer ? GetMemDC(hDC) : hDC;
1778
7fd59977 1779 SaveDC(aWorkDC);
1780 SelectObject(aWorkDC,GetStockObject(BLACK_PEN));
1781 Rectangle(aWorkDC, 0, 0, WidthWin(), HeightWin());
1782 RestoreDC(aWorkDC,-1);
1783
1784 if (myUseBuffer) ReleaseMemDC(aWorkDC);
1785 ReleaseDC(win,hDC);
1786}
1787
1788/*--------------------------------------------------------*\
1789| SaveBitmap
1790\*--------------------------------------------------------*/
692613e5 1791static Standard_Boolean SaveBitmap (HBITMAP theHBitmap,
7fd59977 1792 const char* theFileName)
1793{
692613e5 1794 // Get informations about the bitmap
7fd59977 1795 BITMAP aBitmap;
b07ce12b 1796 if (GetObjectW (theHBitmap, sizeof(BITMAP), &aBitmap) == 0)
692613e5 1797 {
1798 return Standard_False;
1799 }
7fd59977 1800
692613e5 1801 Image_AlienPixMap anImage;
7c4ce93b 1802 const Standard_Size aSizeRowBytes = ((Standard_Size(aBitmap.bmWidth) * 24 + 31) / 32) * 4; // 4 bytes alignment for GetDIBits()
1803 if (!anImage.InitTrash (Image_Format_BGR, Standard_Size(aBitmap.bmWidth), Standard_Size(aBitmap.bmHeight), aSizeRowBytes))
692613e5 1804 {
1805 return Standard_False;
1806 }
1807 anImage.SetTopDown (false);
7fd59977 1808
1809 // Setup image data
1810 BITMAPINFOHEADER aBitmapInfo;
1811 memset (&aBitmapInfo, 0, sizeof(BITMAPINFOHEADER));
692613e5 1812 aBitmapInfo.biSize = sizeof(BITMAPINFOHEADER);
1813 aBitmapInfo.biWidth = aBitmap.bmWidth;
1814 aBitmapInfo.biHeight = aBitmap.bmHeight; // positive means bottom-up!
1815 aBitmapInfo.biPlanes = 1;
7c4ce93b 1816 aBitmapInfo.biBitCount = 24;
7fd59977 1817 aBitmapInfo.biCompression = BI_RGB;
1818
7fd59977 1819 // Copy the pixels
1820 HDC aDC = GetDC (NULL);
692613e5 1821 Standard_Boolean isSuccess = GetDIBits (aDC, theHBitmap,
1822 0, // first scan line to set
1823 aBitmap.bmHeight, // number of scan lines to copy
1824 anImage.ChangeData(), // array for bitmap bits
1825 (LPBITMAPINFO )&aBitmapInfo, // bitmap data info
1826 DIB_RGB_COLORS) != 0;
7fd59977 1827 ReleaseDC (NULL, aDC);
692613e5 1828 return isSuccess && anImage.Save (theFileName);
7fd59977 1829}
1830
1831/*--------------------------------------------------------*\
1832| Save
1833\*--------------------------------------------------------*/
1834Standard_Boolean DrawWindow::Save (const char* theFileName) const
1835{
1836 if (myUseBuffer)
1837 {
1838 return SaveBitmap (myMemHbm, theFileName);
1839 }
1840
1841 RECT aRect;
1842 GetClientRect (win, &aRect);
1843 int aWidth = aRect.right - aRect.left;
1844 int aHeight = aRect.bottom - aRect.top;
1845
1846 // Prepare the DCs
1847 HDC aDstDC = GetDC (NULL);
1848 HDC aSrcDC = GetDC (win); // we copy only client area
1849 HDC aMemDC = CreateCompatibleDC (aDstDC);
1850
1851 // Copy the screen to the bitmap
1852 HBITMAP anHBitmapDump = CreateCompatibleBitmap (aDstDC, aWidth, aHeight);
1853 HBITMAP anHBitmapOld = (HBITMAP )SelectObject (aMemDC, anHBitmapDump);
1854 BitBlt (aMemDC, 0, 0, aWidth, aHeight, aSrcDC, 0, 0, SRCCOPY);
1855
1856 Standard_Boolean isSuccess = SaveBitmap (anHBitmapDump, theFileName);
1857
1858 // Free objects
1859 DeleteObject (SelectObject (aMemDC, anHBitmapOld));
1860 DeleteDC (aMemDC);
1861
1862 return isSuccess;
1863}
1864
1865/*--------------------------------------------------------*\
1866| DrawString
1867\*--------------------------------------------------------*/
1868void DrawWindow::DrawString(int x,int y, char* text)
1869{
1870 HDC hDC = GetDC(win);
1871 HDC aWorkDC = myUseBuffer ? GetMemDC(hDC) : hDC;
1872
ad03c234 1873 TCollection_ExtendedString textW (text);
1874 TextOutW(aWorkDC, x, y, (const wchar_t*)textW.ToExtString(), (int )strlen(text));
7fd59977 1875
1876 if (myUseBuffer) ReleaseMemDC(aWorkDC);
1877 ReleaseDC(win,hDC);
1878}
1879
1880/*--------------------------------------------------------*\
1881| DrawSegments
1882\*--------------------------------------------------------*/
1883void DrawWindow::DrawSegments(Segment *tab, int nbElem)
1884{
1885 HDC hDC = GetDC(win);
1886 HDC aWorkDC = myUseBuffer ? GetMemDC(hDC) : hDC;
1887
1888 for(int i = 0 ; i < nbElem ; i++)
1889 {
1890 MoveToEx(aWorkDC, tab[i].x1, tab[i].y1, NULL);
1891 LineTo(aWorkDC, tab[i].x2, tab[i].y2);
1892 }
1893
1894 if (myUseBuffer) ReleaseMemDC(aWorkDC);
1895 ReleaseDC(win,hDC);
1896}
1897
1898/*--------------------------------------------------------*\
1899| Redraw
1900\*--------------------------------------------------------*/
1901void DrawWindow::Redraw()
1902{
1903 if (myUseBuffer) {
1904 HDC hDC = GetDC(win);
1905 RECT rc;
1906 GetClientRect(win, &rc);
1907 HDC aMemDC = GetMemDC(hDC);
1908 BitBlt(hDC,
1909 rc.left, rc.top,
1910 rc.right-rc.left, rc.bottom-rc.top,
1911 aMemDC,
1912 0, 0, SRCCOPY);
1913 ReleaseMemDC(aMemDC);
1914 ReleaseDC(win,hDC);
1915 }
1916}
1917
1918/*--------------------------------------------------------*\
1919| SetMode
1920\*--------------------------------------------------------*/
1921void DrawWindow::SetMode(int mode)
1922{
1923 HDC hDC = GetDC(win);
1924 myCurrMode = mode;
1925 SetROP2(hDC, modeTab[mode]);
1926 ReleaseDC(win,hDC);
1927}
1928
1929
1930/*--------------------------------------------------------*\
1931| SetColor
1932\*--------------------------------------------------------*/
1933void DrawWindow::SetColor(Standard_Integer color)
1934{
1935 HDC hDC = GetDC(win);
1936 myCurrPen = color;
1937 SelectObject(hDC,colorPenTab[color]);
1938 ReleaseDC(win,hDC);
1939}
1940
1941
1942/*--------------------------------------------------------*\
1943| WExpose
1944\*--------------------------------------------------------*/
1945void DrawWindow::WExpose()
1946{
1947}
1948
1949
1950/*--------------------------------------------------------*\
1951| WButtonPress
1952\*--------------------------------------------------------*/
1953void DrawWindow::WButtonPress(const Standard_Integer,
1954 const Standard_Integer,
1955 const Standard_Integer&)
1956{
1957}
1958
1959
1960/*--------------------------------------------------------*\
1961| WButtonRelease
1962\*--------------------------------------------------------*/
1963void DrawWindow::WButtonRelease(const Standard_Integer,
1964 const Standard_Integer,
1965 const Standard_Integer&)
1966{
1967}
1968
1969
1970/*--------------------------------------------------------*\
1971| WMotionNotify
1972\*--------------------------------------------------------*/
1973void Draw_Window::WMotionNotify(const Standard_Integer ,
1974 const Standard_Integer )
1975{
1976}
1977
1978
1979/*--------------------------------------------------------*\
1980| WConfigureNotify
1981\*--------------------------------------------------------*/
1982void DrawWindow::WConfigureNotify(const Standard_Integer,
1983 const Standard_Integer,
1984 const Standard_Integer,
1985 const Standard_Integer)
1986{
1987}
1988
1989
1990/*--------------------------------------------------------*\
1991| WUnmapNotify
1992\*--------------------------------------------------------*/
1993void DrawWindow::WUnmapNotify()
1994{
1995}
1996
1997
1998
1999/*
2000** IMPLEMENTATION of the CLASS SEGMENT
2001 */
2002
2003/*--------------------------------------------------------*\
2004| Init
2005\*--------------------------------------------------------*/
2006
2007void Segment::Init(Standard_Integer a1, Standard_Integer a2,
2008 Standard_Integer a3, Standard_Integer a4)
2009{
2010 x1=a1;
2011 y1=a2;
2012 x2=a3;
2013 y2=a4;
2014}
2015
2016static DWORD WINAPI tkLoop(VOID);
2017#ifdef _TK
2018static Tk_Window mainWindow;
2019#endif
2020
2021//* threads sinchronization *//
2022DWORD dwMainThreadId;
2023console_semaphore_value volatile console_semaphore = WAIT_CONSOLE_COMMAND;
ad03c234 2024#define THE_COMMAND_SIZE 1000 /* Console Command size */
2025wchar_t console_command[THE_COMMAND_SIZE];
7fd59977 2026bool volatile isTkLoopStarted = false;
2027
2028/*--------------------------------------------------------*\
2029| Init_Appli
2030\*--------------------------------------------------------*/
2031Standard_Boolean Init_Appli(HINSTANCE hInst,
2032 HINSTANCE hPrevInst, int nShow, HWND& hWndFrame )
2033{
e59839c8 2034 Draw_Interpretor& aCommands = Draw::GetInterpretor();
2035
7fd59977 2036 DWORD IDThread;
2037 HANDLE hThread;
2038 console_semaphore = STOP_CONSOLE;
e59839c8 2039 aCommands.Init();
2040 interp = aCommands.Interp();
7fd59977 2041 Tcl_Init(interp) ;
2042
2043 dwMainThreadId = GetCurrentThreadId();
2044
2045 //necessary for normal Tk operation
2046 hThread = CreateThread(NULL, // no security attributes
2047 0, // use default stack size
2048 (LPTHREAD_START_ROUTINE) tkLoop, // thread function
2049 NULL, // no thread function argument
2050 0, // use default creation flags
2051 &IDThread);
2052 if (!hThread) {
2053 cout << "Tcl/Tk main loop thread not created. Switching to batch mode..." << endl;
2054#ifdef _TK
2055 try {
2056 OCC_CATCH_SIGNALS
2057 Tk_Init(interp) ;
2058 } catch (Standard_Failure) {
2059 cout <<" Pb au lancement de TK_Init "<<endl;
2060 }
2061
2062 Tcl_StaticPackage(interp, "Tk", Tk_Init, (Tcl_PackageInitProc *) NULL);
2063#endif
2064 //since the main Tcl/Tk loop wasn't created --> switch to batch mode
2065 return Standard_False;
2066 }
2067
2068 // san - 06/08/2002 - Time for tkLoop to start; Tk fails to initialize otherwise
2069 while (!isTkLoopStarted)
2070 Sleep(10);
2071
2072 // Saving of window classes
2073 if(!hPrevInst)
2074 if(!RegisterAppClass(hInst))
2075 return(Standard_False);
2076
7fd59977 2077 /*
2078 ** Enter the application message-polling loop. This is the anchor for
2079 ** the application.
2080 */
773f53f1 2081 hWndFrame = !Draw_IsConsoleSubsystem ? CreateAppWindow (hInst) : NULL;
2082 if (hWndFrame != NULL)
7fd59977 2083 {
2084 ShowWindow(hWndFrame,nShow);
2085 UpdateWindow(hWndFrame);
2086 }
2087
2088 return Standard_True;
2089}
2090
bf03eb83 2091Standard_Boolean Draw_Interprete (const char*);
7fd59977 2092
2093/*--------------------------------------------------------*\
2094| readStdinThreadFunc
2095\*--------------------------------------------------------*/
ad03c234 2096static DWORD WINAPI readStdinThreadFunc()
7fd59977 2097{
ad03c234 2098 if (!Draw_IsConsoleSubsystem)
2099 {
2100 return 1;
2101 }
2102
7755fe82 2103 // Console locale could be set to the system codepage .OCP (UTF-8 is not properly supported on Windows).
2104 // However, to use it, we have to care using std::wcerr/fwprintf/WriteConsoleW for non-ascii strings everywhere (including Tcl itself),
2105 // or otherwise we can have incomplete output issues
2106 // (e.g. UNICODE string will be NOT just corrupted as in case when we don't set setlocale()
2107 // but will break further normal output to console due to special characters being accidentally handled by console in the wrong way).
ad03c234 2108 //setlocale (LC_ALL, ".OCP");
7755fe82 2109
2110 // _O_U16TEXT can be used with fgetws() to get similar result as ReadConsoleW() without affecting setlocale(),
2111 // however it would break pipe input
2112 //_setmode (_fileno(stdin), _O_U16TEXT);
2113
2114 bool isConsoleInput = true;
ad03c234 2115 for (;;)
2116 {
7fd59977 2117 while (console_semaphore != WAIT_CONSOLE_COMMAND)
ad03c234 2118 {
2119 Sleep (100);
2120 }
2121
7755fe82 2122 const HANDLE anStdIn = ::GetStdHandle (STD_INPUT_HANDLE);
2123 if (anStdIn != NULL
2124 && anStdIn != INVALID_HANDLE_VALUE
2125 && isConsoleInput)
ad03c234 2126 {
7755fe82 2127 DWORD aNbRead = 0;
2128 if (ReadConsoleW (anStdIn, console_command, THE_COMMAND_SIZE, &aNbRead, NULL))
2129 {
2130 console_command[aNbRead] = L'\0';
2131 console_semaphore = HAS_CONSOLE_COMMAND;
2132 continue;
2133 }
2134 else
7fd59977 2135 {
7755fe82 2136 const DWORD anErr = GetLastError();
0f358da3 2137 if (anErr != ERROR_SUCCESS)
7755fe82 2138 {
2139 // fallback using fgetws() which would work with pipes
2140 // but supports Unicode only through multi-byte encoding (which is not UTF-8)
2141 isConsoleInput = false;
ad03c234 2142 continue;
2143 }
7755fe82 2144 }
2145 }
2146
2147 // fgetws() works only for characters within active locale (see setlocale())
2148 if (fgetws (console_command, THE_COMMAND_SIZE, stdin))
2149 {
ad03c234 2150 console_semaphore = HAS_CONSOLE_COMMAND;
2151 }
7fd59977 2152 }
7fd59977 2153}
2154
2155/*--------------------------------------------------------*\
2156| exitProc: finalization handler for Tcl/Tk thread. Forces parent process to die
2157\*--------------------------------------------------------*/
2158void exitProc(ClientData /*dc*/)
2159{
a0fc422a 2160 NCollection_List<Draw_Window::FCallbackBeforeTerminate>::Iterator Iter(MyCallbacks);
2161 for(; Iter.More(); Iter.Next())
2162 {
2163 (*Iter.Value())();
2164 }
7fd59977 2165 HANDLE proc = GetCurrentProcess();
2166 TerminateProcess(proc, 0);
2167}
2168
e05c25c1 2169// This is fixed version of TclpGetDefaultStdChannel() defined in tclWinChan.c
2170// See https://core.tcl.tk/tcl/tktview/91c9bc1c457fda269ae18595944fc3c2b54d961d
2171static Tcl_Channel
2172TclpGetDefaultStdChannel(
2173 int type) /* One of TCL_STDIN, TCL_STDOUT, or
2174 * TCL_STDERR. */
2175{
2176 Tcl_Channel channel;
2177 HANDLE handle;
2178 int mode = -1;
2179 const char *bufMode = NULL;
2180 DWORD handleId = (DWORD) -1;
2181 /* Standard handle to retrieve. */
2182
2183 switch (type) {
2184 case TCL_STDIN:
2185 handleId = STD_INPUT_HANDLE;
2186 mode = TCL_READABLE;
2187 bufMode = "line";
2188 break;
2189 case TCL_STDOUT:
2190 handleId = STD_OUTPUT_HANDLE;
2191 mode = TCL_WRITABLE;
2192 bufMode = "line";
2193 break;
2194 case TCL_STDERR:
2195 handleId = STD_ERROR_HANDLE;
2196 mode = TCL_WRITABLE;
2197 bufMode = "none";
2198 break;
2199 default:
2200 Tcl_Panic("TclGetDefaultStdChannel: Unexpected channel type");
2201 break;
2202 }
2203
2204 handle = GetStdHandle(handleId);
2205
2206 /*
2207 * Note that we need to check for 0 because Windows may return 0 if this
2208 * is not a console mode application, even though this is not a valid
2209 * handle.
2210 */
2211
2212 if ((handle == INVALID_HANDLE_VALUE) || (handle == 0)) {
2213 return (Tcl_Channel) NULL;
2214 }
2215
2216 /*
2217 * Make duplicate of the standard handle as it may be altered
2218 * (closed, reopened with another type of the object etc.) by
2219 * the system or a user code at any time, e.g. by call to _dup2()
2220 */
2221 if (! DuplicateHandle (GetCurrentProcess(), handle,
2222 GetCurrentProcess(), &handle,
2223 0, FALSE, DUPLICATE_SAME_ACCESS)) {
2224 return (Tcl_Channel) NULL;
2225 }
2226
2227 channel = Tcl_MakeFileChannel(handle, mode);
2228
2229 if (channel == NULL) {
2230 return (Tcl_Channel) NULL;
2231 }
2232
2233 /*
2234 * Set up the normal channel options for stdio handles.
2235 */
2236
2237 if (Tcl_SetChannelOption(NULL,channel,"-translation","auto")!=TCL_OK ||
2238 Tcl_SetChannelOption(NULL,channel,"-eofchar","\032 {}")!=TCL_OK ||
2239 Tcl_SetChannelOption(NULL,channel,"-buffering",bufMode)!=TCL_OK) {
2240 Tcl_Close(NULL, channel);
2241 return (Tcl_Channel) NULL;
2242 }
2243 return channel;
2244}
2245
2246// helper functuion
2247static void ResetStdChannel (int type)
2248{
2249 Tcl_Channel aChannel = TclpGetDefaultStdChannel (type);
2250 Tcl_SetStdChannel (aChannel, type);
2251 if (aChannel)
2252 {
2253 Tcl_RegisterChannel (NULL, aChannel);
2254 }
2255}
2256
7fd59977 2257/*--------------------------------------------------------*\
2258| tkLoop: implements Tk_Main()-like behaviour in a separate thread
2259\*--------------------------------------------------------*/
2260static DWORD WINAPI tkLoop(VOID)
2261{
2262 Tcl_CreateExitHandler(exitProc, 0);
e05c25c1 2263
2264 // Work-around against issue with Tcl standard channels on Windows.
2265 // These channels by default use OS handles owned by the system which
2266 // may get invalidated e.g. by dup2() (see dlog command).
2267 // If this happens, output to stdout from Tcl (e.g. puts) gets broken
2268 // (sympthom is error message: "error writing "stdout": bad file number").
2269 // To prevent this, we set standard channels using duplicate of system handles.
2270 // The effect is that Tcl channel becomes independent on C file descriptor
2271 // and even if stdout/stderr are redirected using dup2(), Tcl keeps using
2272 // original device.
2273 ResetStdChannel (TCL_STDOUT);
2274 ResetStdChannel (TCL_STDERR);
2275
7fd59977 2276#if (TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 5))
e05c25c1 2277 // Plain Tcl (8.6.4+) initializes interpretor channels automatically, but
2278 // ActiveState Tcl (at least 8.6.4) does not seem to do that, so channels
2279 // need to be set into interpretor explicitly
ad03c234 2280 {
e05c25c1 2281 Draw_Interpretor& aCommands = Draw::GetInterpretor();
2282
ad03c234 2283 Tcl_Channel aChannelIn = Tcl_GetStdChannel (TCL_STDIN);
2284 Tcl_Channel aChannelOut = Tcl_GetStdChannel (TCL_STDOUT);
2285 Tcl_Channel aChannelErr = Tcl_GetStdChannel (TCL_STDERR);
2286 if (aChannelIn != NULL)
2287 {
e59839c8 2288 Tcl_RegisterChannel (aCommands.Interp(), aChannelIn);
ad03c234 2289 }
2290 if (aChannelOut != NULL)
2291 {
e59839c8 2292 Tcl_RegisterChannel (aCommands.Interp(), aChannelOut);
ad03c234 2293 }
2294 if (aChannelErr != NULL)
2295 {
e59839c8 2296 Tcl_RegisterChannel (aCommands.Interp(), aChannelErr);
ad03c234 2297 }
2298 }
7fd59977 2299#endif
2300
2301#ifdef _TK
87c58d4f
K
2302 // initialize the Tk library if not in 'virtual windows' mode
2303 // (virtual windows are created by OCCT with native APIs,
2304 // thus Tk will be useless)
2305 if (!Draw_VirtualWindows)
2306 {
2307 try
2308 {
2309 OCC_CATCH_SIGNALS
2310 Standard_Integer res = Tk_Init (interp);
2311 if (res != TCL_OK)
2312 {
7fb60cfd 2313#if ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 5)))
2314 cout << "tkLoop: error in Tk initialization. Tcl reported: " << Tcl_GetStringResult(interp) << endl;
2315#else
87c58d4f 2316 cout << "tkLoop: error in Tk initialization. Tcl reported: " << interp->result << endl;
7fb60cfd 2317#endif
87c58d4f
K
2318 }
2319 }
2320 catch (Standard_Failure)
2321 {
2322 cout << "tkLoop: exception in TK_Init\n";
2323 }
2324 Tcl_StaticPackage (interp, "Tk", Tk_Init, (Tcl_PackageInitProc* ) NULL);
2325 mainWindow = Tk_MainWindow (interp);
2326 if (mainWindow == NULL)
2327 {
7fb60cfd 2328#if ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 5)))
2329 fprintf (stderr, "%s\n", Tcl_GetStringResult(interp));
2330#else
87c58d4f 2331 fprintf (stderr, "%s\n", interp->result);
7fb60cfd 2332#endif
87c58d4f
K
2333 cout << "tkLoop: Tk_MainWindow() returned NULL. Exiting...\n";
2334 Tcl_Exit (0);
2335 }
2336 Tk_Name(mainWindow) = Tk_GetUid (Tk_SetAppName (mainWindow, "Draw"));
7fd59977 2337 }
87c58d4f 2338#endif //#ifdef _TK
7fd59977 2339
87c58d4f 2340 // set signal handler in the new thread
d538d7a2 2341 OSD::SetSignal(Standard_False);
7fd59977 2342
87c58d4f 2343 // inform the others that we have started
7fd59977 2344 isTkLoopStarted = true;
2345
2346 while (console_semaphore == STOP_CONSOLE)
2347 Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT);
2348
2349 if (Draw_IsConsoleSubsystem && console_semaphore == WAIT_CONSOLE_COMMAND)
2350 Prompt(interp, 0);
2351
2352 //process a command
87c58d4f
K
2353 Standard_Boolean toLoop = Standard_True;
2354 while (toLoop)
2355 {
7fd59977 2356 while(Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT));
87c58d4f
K
2357 if (console_semaphore == HAS_CONSOLE_COMMAND)
2358 {
ad03c234 2359 TCollection_AsciiString aCmdUtf8 (console_command);
2360 if (Draw_Interprete (aCmdUtf8.ToCString()))
87c58d4f
K
2361 {
2362 if (Draw_IsConsoleSubsystem) Prompt (interp, 0);
2363 }
7fd59977 2364 else
87c58d4f
K
2365 {
2366 if (Draw_IsConsoleSubsystem) Prompt (interp, 1);
2367 }
7fd59977 2368 console_semaphore = WAIT_CONSOLE_COMMAND;
2369 }
2370 else
87c58d4f 2371 {
7fd59977 2372 Sleep(100);
87c58d4f
K
2373 }
2374 #ifdef _TK
2375 // We should not exit until the Main Tk window is closed
2376 toLoop = (Tk_GetNumMainWindows() > 0) || Draw_VirtualWindows;
2377 #endif
7fd59977 2378 }
7fd59977 2379 Tcl_Exit(0);
7fd59977 2380 return 0;
2381}
2382
2383
2384/*--------------------------------------------------------*\
2385| Run_Appli
2386\*--------------------------------------------------------*/
2387void Run_Appli(HWND hWnd)
2388{
2389 MSG msg;
2390 HACCEL hAccel = NULL;
2391
2392 msg.wParam = 1;
2393
2394// if (!(hAccel = LoadAccelerators (hInstance, MAKEINTRESOURCE(ACCEL_ID))))
2395// MessageBox(hWnd, "MDI: Load Accel failure!", "Error", MB_OK);
2396 DWORD IDThread;
2397 HANDLE hThread;
2398 if (Draw_IsConsoleSubsystem) {
2399 hThread = CreateThread(NULL, // no security attributes
2400 0, // use default stack size
2401 (LPTHREAD_START_ROUTINE) readStdinThreadFunc, // thread function
2402 NULL, // no thread function argument
2403 0, // use default creation flags
2404 &IDThread); // returns thread identifier
2405 if (!hThread) {
2406 cout << "pb in creation of the thread reading stdin" << endl;
2407 Draw_IsConsoleSubsystem = Standard_False;
ad03c234 2408 Init_Appli (GetModuleHandleW (NULL),
2409 GetModuleHandleW (NULL),
2410 1, hWnd); // reinit => create MDI client wnd
7fd59977 2411 }
2412 }
2413
2414 //turn on the command interpretation mechanism (regardless of the mode)
2415 if (console_semaphore == STOP_CONSOLE)
2416 console_semaphore = WAIT_CONSOLE_COMMAND;
2417
2418 //simple Win32 message loop
ad03c234 2419 while (GetMessageW (&msg, NULL, 0, 0) > 0)
7fd59977 2420 {
ad03c234 2421 if (!TranslateAcceleratorW (hWnd, hAccel, &msg))
7fd59977 2422 {
ad03c234 2423 TranslateMessage (&msg);
2424 DispatchMessageW (&msg);
7fd59977 2425 }
2426 }
2427 ExitProcess(0);
2428}
2429
2430
2431/*--------------------------------------------------------*\
2432| Destroy_Appli
2433\*--------------------------------------------------------*/
2434void Destroy_Appli(HINSTANCE hInst)
2435{
2436 UnregisterAppClass(hInst);
2437 for (int i = 0 ; i < MAXCOLOR ; i++)
2438 DeleteObject(colorPenTab[i]);
2439}
2440
2441/*--------------------------------------------------------*\
2442| SelectWait
2443\*--------------------------------------------------------*/
2444void DrawWindow::SelectWait(HANDLE& hWnd, int& x, int& y, int& button)
2445{
2446 MSG msg;
2447
2448 msg.wParam = 1;
2449
ad03c234 2450 GetMessageW (&msg, NULL, 0, 0);
7fd59977 2451 while((msg.message != WM_RBUTTONDOWN && msg.message != WM_LBUTTONDOWN) ||
2452 ! ( Draw_IsConsoleSubsystem || IsChild(DrawWindow::hWndClientMDI,msg.hwnd)) )
ad03c234 2453 {
2454 GetMessageW (&msg, NULL, 0, 0);
2455 }
7fd59977 2456
2457 hWnd = msg.hwnd;
2458 x = LOWORD(msg.lParam);
2459 y = HIWORD(msg.lParam);
2460 if (msg.message == WM_LBUTTONDOWN)
2461 button = 1;
2462 else
2463 button = 3;
2464}
2465
2466/*--------------------------------------------------------*\
2467| SelectNoWait
2468\*--------------------------------------------------------*/
2469void DrawWindow::SelectNoWait(HANDLE& hWnd, int& x, int& y, int& button)
2470{
2471 MSG msg;
2472
2473 msg.wParam = 1;
2474
ad03c234 2475 GetMessageW (&msg,NULL,0,0);
7fd59977 2476 while((msg.message != WM_RBUTTONDOWN && msg.message != WM_LBUTTONDOWN &&
2477 msg.message != WM_MOUSEMOVE) ||
2478 ! ( Draw_IsConsoleSubsystem || IsChild(DrawWindow::hWndClientMDI,msg.hwnd) ) )
ad03c234 2479 {
2480 GetMessageW(&msg,NULL,0,0);
2481 }
7fd59977 2482 hWnd = msg.hwnd;
2483 x = LOWORD(msg.lParam);
2484 y = HIWORD(msg.lParam);
2485 switch (msg.message)
2486 {
2487 case WM_LBUTTONDOWN :
2488 button = 1;
2489 break;
2490
2491 case WM_RBUTTONDOWN :
2492 button = 3;
2493 break;
2494
2495 case WM_MOUSEMOVE :
2496 button = 0;
2497 break;
2498 }
2499}
2500
2501Standard_Boolean DrawWindow::DefineColor (const Standard_Integer, const char*)
2502{
2503 return Standard_True;
2504};
2505
2506#endif