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