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