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