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