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
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 // include windows.h first to have all definitions available
22 #include <Standard_ErrorHandler.hxx>
25 #include <Draw_Interpretor.hxx>
26 #include <Draw_Window.hxx>
27 #include <Draw_Appli.hxx>
28 #include <TCollection_AsciiString.hxx>
29 #include <TCollection_ExtendedString.hxx>
30 #include <Image_AlienPixMap.hxx>
31 #include <NCollection_List.hxx>
33 extern Standard_Boolean Draw_Batch;
34 extern Standard_Boolean Draw_VirtualWindows;
35 static Tcl_Interp *interp; /* Interpreter for this application. */
36 static NCollection_List<Draw_Window::FCallbackBeforeTerminate> MyCallbacks;
38 void Draw_Window::AddCallbackBeforeTerminate(FCallbackBeforeTerminate theCB)
40 MyCallbacks.Append(theCB);
43 void Draw_Window::RemoveCallbackBeforeTerminate(FCallbackBeforeTerminate theCB)
45 NCollection_List<Draw_Window::FCallbackBeforeTerminate>::Iterator Iter(MyCallbacks);
46 for(; Iter.More(); Iter.Next())
48 if (Iter.Value() == theCB)
50 MyCallbacks.Remove(Iter);
57 *----------------------------------------------------------------------
61 * Issue a prompt on standard output, or invoke a script
62 * to issue the prompt.
68 * A prompt gets output, and a Tcl script may be evaluated
71 *----------------------------------------------------------------------
74 static void Prompt(Tcl_Interp *Interp, int partial)
78 #if ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4))) && !defined(USE_NON_CONST)
79 const char *promptCmd;
84 Tcl_Channel outChannel, errChannel;
85 outChannel = Tcl_GetStdChannel(TCL_STDOUT);
86 promptCmd = Tcl_GetVar(Interp,(char*)
87 (partial ? "tcl_prompt2" : "tcl_prompt1"), TCL_GLOBAL_ONLY);
89 if (promptCmd == NULL) {
91 if (!partial && outChannel) {
92 Tcl_Write(outChannel, "% ", 2);
95 code = Tcl_Eval(Interp, promptCmd);
96 outChannel = Tcl_GetStdChannel(TCL_STDOUT);
97 errChannel = Tcl_GetStdChannel(TCL_STDERR);
100 #if ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 5)))
101 Tcl_Write(errChannel, Tcl_GetStringResult(Interp), -1);
103 Tcl_Write(errChannel, Interp->result, -1);
105 Tcl_Write(errChannel, "\n", 1);
107 Tcl_AddErrorInfo(Interp,
108 "\n (script that generates prompt)");
113 Tcl_Flush(outChannel);
117 #if !defined(_WIN32) && !defined(__WIN32__)
119 #include <OSD_Timer.hxx>
120 #include <Draw_Window.hxx>
123 #if defined(__APPLE__) && !defined(MACOSX_USE_GLX)
124 // use forward declaration for small subset of used Tk functions
125 // to workaround broken standard Tk framework installation within OS X SDKs
126 // which *HAS* X11 headers in Tk.framework but doesn't install them appropriately
128 typedef struct Tk_Window_* Tk_Window;
129 typedef const char* Tk_Uid;
131 extern "C" int Tk_Init (Tcl_Interp* interp);
132 extern "C" void Tk_MainLoop();
133 extern "C" Tk_Window Tk_MainWindow (Tcl_Interp* interp) ;
134 extern "C" Tk_Uid Tk_GetUid (const char* str);
135 extern "C" const char* Tk_SetAppName (Tk_Window tkwin, const char* name) ;
136 extern "C" void Tk_GeometryRequest (Tk_Window tkwin, int reqWidth, int reqHeight);
143 * Global variables used by the main program:
146 char *tcl_RcFileName = NULL; /* Name of a user-specific startup script
147 * to source if the application is being run
148 * interactively (e.g. "~/.wishrc"). Set
149 * by Tcl_AppInit. NULL means don't source
152 static Tcl_DString command; /* Used to assemble lines of terminal input
153 * into Tcl commands. */
154 static Tcl_DString line; /* Used to read the next line from the
156 //static char errorExitCmd[] = "exit 1";
159 * Forward declarations for procedures defined later in this file:
162 static void StdinProc (ClientData clientData, int mask);
164 static void Prompt (Tcl_Interp *Interp, int partial);
166 static Standard_Boolean tty; /* Non-zero means standard input is a
167 * terminal-like device. Zero means it's
170 Standard_Integer Draw_WindowScreen = 0;
171 Standard_Boolean Draw_BlackBackGround = Standard_True;
174 // Initialization of static variables of Draw_Window
175 //======================================================
176 Draw_Window* Draw_Window::firstWindow = NULL;
179 #if !defined(__APPLE__) || defined(MACOSX_USE_GLX)
180 #include <X11/Xutil.h>
181 #include <Aspect_DisplayConnection.hxx>
183 static unsigned long thePixels[MAXCOLOR];
185 Display* Draw_WindowDisplay = NULL;
186 Colormap Draw_WindowColorMap;
187 static Handle(Aspect_DisplayConnection) Draw_DisplayConnection;
189 // Base_Window struct definition
190 //===================================
194 XSetWindowAttributes xswa;
197 //=======================================================================
198 //function : Draw_Window
200 //=======================================================================
201 Draw_Window::Draw_Window() :
202 base(*new Base_Window()),
207 myUseBuffer(Standard_False),
208 withWindowManager(Standard_True)
210 myMother = RootWindow(Draw_WindowDisplay,
213 if (firstWindow) firstWindow->previous = this;
217 //=======================================================================
218 //function : Draw_Window
220 //=======================================================================
221 Draw_Window::Draw_Window(Window mother) :
222 base(*new Base_Window()),
227 myUseBuffer(Standard_False),
228 withWindowManager(Standard_True)
232 if (firstWindow) firstWindow->previous = this;
236 //=======================================================================
237 //function : Draw_Window
239 //=======================================================================
240 Draw_Window::Draw_Window (const char* title,
241 Standard_Integer X, Standard_Integer Y,
242 Standard_Integer DX, Standard_Integer DY) :
243 base(*new Base_Window()),
248 myUseBuffer(Standard_False),
249 withWindowManager(Standard_True)
251 myMother = RootWindow(Draw_WindowDisplay,
254 if (firstWindow) firstWindow->previous = this;
260 //=======================================================================
261 //function : Draw_Window
263 //=======================================================================
264 Draw_Window::Draw_Window (const char* window ) :
265 base(*new Base_Window()),
270 myUseBuffer(Standard_False),
271 withWindowManager(Standard_True)
273 sscanf(window,"%lx",&win);
274 Standard_Integer X,Y,DX,DY;
276 if (firstWindow) firstWindow->previous = this;
285 //=======================================================================
286 //function : Draw_Window
288 //=======================================================================
289 Draw_Window::Draw_Window (Window mother,
291 Standard_Integer X, Standard_Integer Y,
292 Standard_Integer DX, Standard_Integer DY) :
293 base(*new Base_Window()),
298 myUseBuffer(Standard_False),
299 withWindowManager(Standard_True)
303 if (firstWindow) firstWindow->previous = this;
309 //=======================================================================
310 //function : ~Draw_Window
312 //=======================================================================
313 Draw_Window::~Draw_Window()
316 previous->next = next;
320 next->previous = previous;
324 XFreePixmap(Draw_WindowDisplay, myBuffer);
327 // Liberation pointer on Base_Window
331 //=======================================================================
334 //=======================================================================
335 void Draw_Window::Init(Standard_Integer X, Standard_Integer Y,
336 Standard_Integer DX, Standard_Integer DY)
338 unsigned long setmask;
340 if (Draw_BlackBackGround)
342 base.xswa.background_pixel = BlackPixel(Draw_WindowDisplay,Draw_WindowScreen);
343 base.xswa.border_pixel = WhitePixel(Draw_WindowDisplay,Draw_WindowScreen);
347 base.xswa.background_pixel = WhitePixel(Draw_WindowDisplay,Draw_WindowScreen);
348 base.xswa.border_pixel = BlackPixel(Draw_WindowDisplay,Draw_WindowScreen);
350 base.xswa.colormap = Draw_WindowColorMap;
351 setmask = CWBackPixel | CWBorderPixel ;
354 myHints.flags = USPosition;
360 win = XCreateWindow(Draw_WindowDisplay,
363 (unsigned int) DX,(unsigned int) DY,
365 DefaultDepth(Draw_WindowDisplay,Draw_WindowScreen),
367 DefaultVisual(Draw_WindowDisplay,Draw_WindowScreen),
369 XSelectInput(Draw_WindowDisplay, win, ButtonPressMask|ExposureMask|
370 StructureNotifyMask);
372 // advise to the window manager to place it where I need
373 XSetWMNormalHints(Draw_WindowDisplay,win,&myHints);
375 Atom aDeleteWindowAtom = Draw_DisplayConnection->GetAtom (Aspect_XA_DELETE_WINDOW);
376 XSetWMProtocols (Draw_WindowDisplay, win, &aDeleteWindowAtom, 1);
378 if (Draw_VirtualWindows)
380 myUseBuffer = Standard_True;
385 base.gc = XCreateGC(Draw_WindowDisplay, win, 0, NULL);
387 XSetPlaneMask(Draw_WindowDisplay,base.gc,AllPlanes);
388 XSetForeground(Draw_WindowDisplay,
389 base.gc, WhitePixel(Draw_WindowDisplay,Draw_WindowScreen));
390 XSetBackground(Draw_WindowDisplay,
391 base.gc, BlackPixel(Draw_WindowDisplay,Draw_WindowScreen));
392 // save in case of window recovery
394 base.xswa.backing_store = Always;
395 XChangeWindowAttributes(Draw_WindowDisplay, win,
396 CWBackingStore, &base.xswa);
398 XSetLineAttributes (Draw_WindowDisplay, base.gc,
399 0, LineSolid, CapButt, JoinMiter);
402 //=======================================================================
403 //function : InitBuffer
405 //=======================================================================
406 void Draw_Window::InitBuffer()
410 XFreePixmap (Draw_WindowDisplay, myBuffer);
412 XWindowAttributes winAttr;
413 XGetWindowAttributes (Draw_WindowDisplay, win, &winAttr);
414 myBuffer = XCreatePixmap (Draw_WindowDisplay, win, winAttr.width, winAttr.height, winAttr.depth);
416 else if (myBuffer != 0)
418 XFreePixmap (Draw_WindowDisplay, myBuffer);
423 //=======================================================================
424 //function : StopWinManager
426 //=======================================================================
427 void Draw_Window::StopWinManager()
430 XWindowAttributes winAttr;
431 XGetWindowAttributes (Draw_WindowDisplay, win, &winAttr);
435 myHints.flags = USPosition;
436 myHints.x = (int) 30;
437 myHints.y = (int) 100;
439 base.xswa.override_redirect = 1;
440 base.xswa.border_pixel = BlackPixel(Draw_WindowDisplay,
442 base.xswa.background_pixel = WhitePixel(Draw_WindowDisplay,
445 withWindowManager = Standard_False;
447 win = XCreateWindow(Draw_WindowDisplay, myMother,
448 winAttr.x, winAttr.y,
449 winAttr.width, winAttr.height,
451 CopyFromParent, InputOutput, CopyFromParent,
452 CWBorderPixel|CWOverrideRedirect|CWBackPixel, &base.xswa);
455 // adwise to the window manager to place it where I wish
456 XSetWMNormalHints(Draw_WindowDisplay,win,&myHints);
458 // all masks of the old window are reassigned to the new one.
459 XSelectInput(Draw_WindowDisplay,win,winAttr.your_event_mask);
462 //=======================================================================
463 //function : SetPosition
465 //=======================================================================
466 void Draw_Window::SetPosition(Standard_Integer NewXpos,
467 Standard_Integer NewYpos)
469 Standard_Integer x,y;
472 if ( (x != NewXpos) || (y != NewYpos) )
473 XMoveWindow(Draw_WindowDisplay, win, NewXpos, NewYpos);
476 //=======================================================================
477 //function : SetDimension
479 //=======================================================================
480 void Draw_Window::SetDimension(Standard_Integer NewDx,
481 Standard_Integer NewDy)
483 if ( (NewDx != WidthWin() ) || (NewDy != HeightWin() ) )
484 XResizeWindow(Draw_WindowDisplay, win, NewDx, NewDy);
487 //=======================================================================
488 //function : GetPosition
490 //=======================================================================
491 void Draw_Window::GetPosition(Standard_Integer &PosX,
492 Standard_Integer &PosY)
494 XWindowAttributes winAttr;
495 XGetWindowAttributes(Draw_WindowDisplay, win, &winAttr);
501 //=======================================================================
502 //function : HeightWin
504 //=======================================================================
505 Standard_Integer Draw_Window::HeightWin() const
508 XWindowAttributes winAttr;
509 XGetWindowAttributes(Draw_WindowDisplay, win, &winAttr);
515 //=======================================================================
516 //function : WidthWin
518 //=======================================================================
519 Standard_Integer Draw_Window::WidthWin() const
522 XWindowAttributes winAttr;
523 XGetWindowAttributes(Draw_WindowDisplay, win, &winAttr);
529 //=======================================================================
530 //function : SetTitle
532 //=======================================================================
533 void Draw_Window::SetTitle(const TCollection_AsciiString& theTitle)
535 XStoreName (Draw_WindowDisplay, win, theTitle.ToCString());
538 //=======================================================================
539 //function : GetTitle
541 //=======================================================================
542 TCollection_AsciiString Draw_Window::GetTitle() const
545 XFetchName (Draw_WindowDisplay, win, &aTitle);
546 return TCollection_AsciiString (aTitle);
549 //=======================================================================
550 //function : GetDrawable
552 //=======================================================================
553 Drawable Draw_Window::GetDrawable() const
555 return myUseBuffer ? myBuffer : win;
558 //=======================================================================
559 //function :DefineColor
561 //=======================================================================
562 Standard_Boolean Draw_Window::DefineColor(const Standard_Integer i, const char* colorName)
566 if (!XParseColor(Draw_WindowDisplay,Draw_WindowColorMap,colorName,&color))
567 return Standard_False;
568 if (!XAllocColor(Draw_WindowDisplay,Draw_WindowColorMap,&color))
569 return Standard_False;
570 thePixels[i % MAXCOLOR] = color.pixel;
571 return Standard_True;
574 //=======================================================================
575 //function : IsMapped
577 //=======================================================================
578 bool Draw_Window::IsMapped() const
580 if (Draw_VirtualWindows
586 XFlush (Draw_WindowDisplay);
587 XWindowAttributes aWinAttr;
588 XGetWindowAttributes (Draw_WindowDisplay, win, &aWinAttr);
589 return aWinAttr.map_state == IsUnviewable
590 || aWinAttr.map_state == IsViewable;
593 //=======================================================================
594 //function : DisplayWindow
596 //=======================================================================
597 void Draw_Window::DisplayWindow()
599 if (Draw_VirtualWindows)
605 XMapRaised(Draw_WindowDisplay, win);
607 XFlush(Draw_WindowDisplay);
610 //=======================================================================
613 //=======================================================================
614 void Draw_Window::Hide()
616 XUnmapWindow(Draw_WindowDisplay, win);
619 //=======================================================================
622 //=======================================================================
623 void Draw_Window::Destroy()
625 XFreeGC (Draw_WindowDisplay, base.gc);
626 XDestroyWindow(Draw_WindowDisplay, win);
630 XFreePixmap(Draw_WindowDisplay, myBuffer);
635 //=======================================================================
638 //=======================================================================
639 void Draw_Window::Clear()
643 // XClearArea only applicable for windows
644 XGCValues currValues;
645 XGetGCValues(Draw_WindowDisplay, base.gc, GCBackground | GCForeground, &currValues);
646 XSetForeground(Draw_WindowDisplay, base.gc, currValues.background);
647 XFillRectangle(Draw_WindowDisplay, myBuffer, base.gc, 0, 0, WidthWin(), HeightWin());
648 XSetForeground(Draw_WindowDisplay, base.gc, currValues.foreground);
652 XClearArea(Draw_WindowDisplay, win, 0, 0, 0, 0, False);
656 //=======================================================================
659 //=======================================================================
660 void Draw_Window::Flush()
662 XFlush(Draw_WindowDisplay);
665 //=======================================================================
666 //function : DrawString
668 //=======================================================================
669 void Draw_Window::DrawString(int X, int Y, char *text)
671 XDrawString(Draw_WindowDisplay, GetDrawable(), base.gc, X, Y, text, strlen(text));
674 //=======================================================================
675 //function : DrawSegments
677 //=======================================================================
678 void Draw_Window::DrawSegments(Segment *tab, int nbElem)
680 XDrawSegments(Draw_WindowDisplay, GetDrawable(), base.gc, (XSegment*) tab, nbElem);
683 //=======================================================================
686 //=======================================================================
687 void Draw_Window::Redraw()
690 XCopyArea (Draw_WindowDisplay,
691 myBuffer, win, // source, destination Drawables
694 WidthWin(), HeightWin(),
695 0, 0); // destination x, y
699 //=======================================================================
700 //function : SetColor
702 //=======================================================================
703 void Draw_Window::SetColor(Standard_Integer color)
705 XSetForeground(Draw_WindowDisplay, base.gc, thePixels[color]);
708 //=======================================================================
711 //=======================================================================
712 void Draw_Window::SetMode( int mode)
714 XSetFunction(Draw_WindowDisplay, base.gc, mode);
717 //=======================================================================
720 //=======================================================================
721 Standard_Boolean Draw_Window::Save (const char* theFileName) const
723 // make sure all draw operations done
724 XSync (Draw_WindowDisplay, True);
727 XWindowAttributes winAttr;
728 XGetWindowAttributes (Draw_WindowDisplay, win, &winAttr);
732 // make sure that the whole window fit on display to prevent BadMatch error
733 XWindowAttributes winAttrRoot;
734 XGetWindowAttributes (Draw_WindowDisplay, XRootWindowOfScreen (winAttr.screen), &winAttrRoot);
736 Window winChildDummy;
739 XTranslateCoordinates (Draw_WindowDisplay, win, XRootWindowOfScreen (winAttr.screen),
740 0, 0, &winLeft, &winTop, &winChildDummy);
742 if (((winLeft + winAttr.width) > winAttrRoot.width) || winLeft < winAttrRoot.x ||
743 ((winTop + winAttr.height) > winAttrRoot.height) || winTop < winAttrRoot.y)
745 std::cerr << "The window not fully visible! Can't create the snapshot.\n";
746 return Standard_False;
751 if (XMatchVisualInfo (Draw_WindowDisplay, Draw_WindowScreen, 32, TrueColor, &aVInfo) == 0
752 && XMatchVisualInfo (Draw_WindowDisplay, Draw_WindowScreen, 24, TrueColor, &aVInfo) == 0)
754 std::cerr << "24-bit TrueColor visual is not supported by server!\n";
755 return Standard_False;
758 Image_AlienPixMap anImage;
759 bool isBigEndian = Image_PixMap::IsBigEndianHost();
760 const Standard_Size aSizeRowBytes = Standard_Size(winAttr.width) * 4;
761 if (!anImage.InitTrash (isBigEndian ? Image_Format_RGB32 : Image_Format_BGR32,
762 Standard_Size(winAttr.width), Standard_Size(winAttr.height), aSizeRowBytes))
764 return Standard_False;
766 anImage.SetTopDown (true);
768 XImage* anXImage = XCreateImage (Draw_WindowDisplay, aVInfo.visual,
769 32, ZPixmap, 0, (char* )anImage.ChangeData(), winAttr.width, winAttr.height, 32, int(aSizeRowBytes));
770 anXImage->bitmap_bit_order = anXImage->byte_order = (isBigEndian ? MSBFirst : LSBFirst);
771 if (XGetSubImage (Draw_WindowDisplay, GetDrawable(),
772 0, 0, winAttr.width, winAttr.height,
773 AllPlanes, ZPixmap, anXImage, 0, 0) == NULL)
775 anXImage->data = NULL;
776 XDestroyImage (anXImage);
777 return Standard_False;
781 anXImage->data = NULL;
782 XDestroyImage (anXImage);
785 return anImage.Save (theFileName);
788 //=======================================================================
791 //=======================================================================
793 void Draw_Window::Wait (Standard_Boolean wait)
797 XSelectInput(Draw_WindowDisplay,win,
798 ButtonPressMask|ExposureMask | StructureNotifyMask |
802 XSelectInput(Draw_WindowDisplay,win,
803 ButtonPressMask|ExposureMask | StructureNotifyMask);
807 //=======================================================================
808 //function : ProcessEvent
810 //=======================================================================
812 void ProcessEvent(Draw_Window& win, XEvent& xev)
814 Standard_Integer X,Y,button;
823 if (xev.xclient.data.l[0] == (int )Draw_DisplayConnection->GetAtom (Aspect_XA_DELETE_WINDOW))
825 // just hide the window
837 button = xev.xbutton.button;
838 win.WButtonPress(X,Y,button);
844 button = xev.xbutton.button;
845 win.WButtonRelease(X,Y,button);
849 XLookupString(&(xev.xkey),
859 win.WMotionNotify(X,Y);
862 case ConfigureNotify :
863 if (win.withWindowManager)
864 win.WConfigureNotify(xev.xconfigure.x, xev.xconfigure.y,
865 xev.xconfigure.width,
866 xev.xconfigure.height);
876 //=======================================================================
879 //=======================================================================
880 void Draw_Window::WExpose()
884 //=======================================================================
885 //function : WButtonPress
887 //=======================================================================
888 void Draw_Window::WButtonPress(const Standard_Integer,
889 const Standard_Integer,
890 const Standard_Integer&)
894 //=======================================================================
895 //function : WButtonRelease
897 //=======================================================================
898 void Draw_Window::WButtonRelease(const Standard_Integer,
899 const Standard_Integer,
900 const Standard_Integer&)
904 /**************************
905 //=======================================================================
906 //function : WKeyPress
908 //=======================================================================
910 void Draw_Window::WKeyPress(char, KeySym&)
913 ***************************/
915 //=======================================================================
916 //function : WMotionNotify
918 //=======================================================================
919 void Draw_Window::WMotionNotify(const Standard_Integer ,
920 const Standard_Integer )
924 //=======================================================================
925 //function : WConfigureNotify
927 //=======================================================================
929 void Draw_Window::WConfigureNotify(const Standard_Integer,
930 const Standard_Integer,
931 const Standard_Integer,
932 const Standard_Integer)
936 //=======================================================================
937 //function : WUnmapNotify
939 //=======================================================================
941 void Draw_Window::WUnmapNotify()
946 //======================================================
947 // funtion : ProcessEvents
948 // purpose : process pending X events
949 //======================================================
951 static void ProcessEvents(ClientData,int)
955 while (XPending(Draw_WindowDisplay)) {
960 XNextEvent(Draw_WindowDisplay,&xev);
962 /* search the window in the window list */
963 Draw_Window* w = Draw_Window::firstWindow;
964 Standard_Integer found=0;
966 if (xev.xany.window == w->win) {
967 ProcessEvent(*w, xev);
974 Tk_HandleEvent(&xev);
979 //======================================================
980 // funtion : GetNextEvent()
982 //======================================================
983 void GetNextEvent(Event& ev)
986 XNextEvent(Draw_WindowDisplay, &xev);
991 ev.window = xev.xbutton.window;
992 ev.button = xev.xbutton.button;
993 ev.x = xev.xbutton.x;
994 ev.y = xev.xbutton.y;
999 ev.window = xev.xmotion.window;
1001 ev.x = xev.xmotion.x;
1002 ev.y = xev.xmotion.y;
1008 //======================================================
1009 // funtion :Run_Appli
1011 //======================================================
1014 static Standard_Boolean(*Interprete) (const char*);
1016 void Run_Appli(Standard_Boolean (*interprete) (const char*))
1018 Tcl_Channel outChannel, inChannel ;
1019 Interprete = interprete;
1024 * Commands will come from standard input, so set up an event
1025 * handler for standard input. If the input device is aEvaluate the
1026 * .rc file, if one has been specified, set up an event handler
1027 * for standard input, and print a prompt if the input
1028 * device is a terminal.
1030 inChannel = Tcl_GetStdChannel(TCL_STDIN);
1032 Tcl_CreateChannelHandler(inChannel, TCL_READABLE, StdinProc,
1033 (ClientData) inChannel);
1036 // Create a handler for the draw display
1038 // Adding of the casting into void* to be able to compile on AO1
1039 // ConnectionNumber(Draw_WindowDisplay) is an int 32 bits
1040 // (void*) is a pointer 64 bits ???????
1042 #if !defined(__APPLE__) || defined(MACOSX_USE_GLX)
1043 #if TCL_MAJOR_VERSION < 8
1044 Tk_CreateFileHandler((void*) ConnectionNumber(Draw_WindowDisplay),
1045 TK_READABLE, ProcessEvents,(ClientData) 0 );
1047 Tk_CreateFileHandler(ConnectionNumber(Draw_WindowDisplay),
1048 TK_READABLE, ProcessEvents,(ClientData) 0 );
1054 Draw_Interpretor& aCommands = Draw::GetInterpretor();
1056 if (tty) Prompt(aCommands.Interp(), 0);
1057 Prompt(aCommands.Interp(), 0);
1059 outChannel = Tcl_GetStdChannel(TCL_STDOUT);
1061 Tcl_Flush(outChannel);
1063 Tcl_DStringInit(&command);
1066 * Loop infinitely, waiting for commands to execute. When there
1067 * are no windows left, Tk_MainLoop returns and we exit.
1072 if (Draw_VirtualWindows) {
1073 // main window will never shown
1074 // but main loop will parse all Xlib messages
1075 Tcl_Eval(aCommands.Interp(), "wm withdraw .");
1082 Standard_Integer count = ConnectionNumber(Draw_WindowDisplay);
1083 Standard_Integer numfd;
1087 FD_SET(count,&readset);
1089 numfd = select(count+1,(Integer*)&readset,NULL,NULL,NULL);
1091 numfd = select(count+1,&readset,NULL,NULL,NULL);
1093 if (FD_ISSET(0,&readset)) StdinProc((ClientData)0,0);
1094 if (FD_ISSET(count,&readset)) ProcessEvents((ClientData)0,0);
1098 NCollection_List<Draw_Window::FCallbackBeforeTerminate>::Iterator Iter(MyCallbacks);
1099 for(; Iter.More(); Iter.Next())
1105 //======================================================
1106 // funtion : Init_Appli()
1108 //======================================================
1109 Standard_Boolean Init_Appli()
1111 Draw_Interpretor& aCommands = Draw::GetInterpretor();
1113 interp = aCommands.Interp();
1119 } catch (Standard_Failure) {
1120 cout <<" Pb au lancement de TK_Init "<<endl;
1123 Tcl_StaticPackage(interp, "Tk", Tk_Init, (Tcl_PackageInitProc *) NULL);
1125 Tk_Window aMainWindow = Tk_MainWindow(interp) ;
1126 if (aMainWindow == NULL) {
1127 #if ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 5)))
1128 fprintf(stderr, "%s\n", Tcl_GetStringResult(interp));
1130 fprintf(stderr, "%s\n", interp->result);
1134 #if defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1135 Tk_SetAppName(aMainWindow, "Draw");
1137 Tk_Name(aMainWindow) = Tk_GetUid(Tk_SetAppName(aMainWindow, "Draw"));
1140 Tk_GeometryRequest (aMainWindow, 200, 200);
1142 #if !defined(__APPLE__) || defined(MACOSX_USE_GLX)
1143 if (Draw_DisplayConnection.IsNull())
1147 Draw_DisplayConnection = new Aspect_DisplayConnection();
1149 catch (Standard_Failure)
1151 std::cout << "Cannot open display. Interpret commands in batch mode." << std::endl;
1152 return Standard_False;
1155 if (Draw_WindowDisplay == NULL)
1157 Draw_WindowDisplay = Draw_DisplayConnection->GetDisplay();
1160 // synchronize the display server : could be done within Tk_Init
1162 XSynchronize(Draw_WindowDisplay, True);
1163 XSetInputFocus(Draw_WindowDisplay,
1165 RevertToPointerRoot,
1168 Draw_WindowScreen = DefaultScreen(Draw_WindowDisplay);
1169 Draw_WindowColorMap = DefaultColormap(Draw_WindowDisplay,
1174 Tcl_SetVar(interp,"tcl_interactive",(char*)(tty ? "1" : "0"), TCL_GLOBAL_ONLY);
1175 // Tcl_SetVar(interp,"tcl_interactive",tty ? "1" : "0", TCL_GLOBAL_ONLY);
1176 return Standard_True;
1179 //======================================================
1180 // funtion : Destroy_Appli()
1182 //======================================================
1183 void Destroy_Appli()
1185 //XCloseDisplay(Draw_WindowDisplay);
1189 *----------------------------------------------------------------------
1193 * This procedure is invoked by the event dispatcher whenever
1194 * standard input becomes readable. It grabs the next line of
1195 * input characters, adds them to a command being assembled, and
1196 * executes the command if it's complete.
1202 * Could be almost arbitrary, depending on the command that's
1205 *----------------------------------------------------------------------
1209 //static void StdinProc(ClientData clientData, int mask)
1210 static void StdinProc(ClientData clientData, int )
1212 static int gotPartial = 0;
1216 Tcl_Channel chan = (Tcl_Channel) clientData;
1218 // MSV Nov 2, 2001: patch for TCL 8.3: initialize line to avoid exception
1219 // when first user input is an empty string
1220 Tcl_DStringFree(&line);
1221 count = Tcl_Gets(chan, &line);
1224 #if ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4)))
1225 Tcl_DString linetmp;
1226 Tcl_DStringInit(&linetmp);
1227 Tcl_UniChar * UniCharString;
1228 UniCharString = Tcl_UtfToUniCharDString(Tcl_DStringValue(&line),-1,&linetmp);
1229 Standard_Integer l = Tcl_UniCharLen(UniCharString);
1230 TCollection_AsciiString AsciiString("");
1231 Standard_Character Character;
1233 for (i=0; i<l; i++) {
1234 Character = UniCharString[i];
1235 AsciiString.AssignCat(Character);
1237 Tcl_DStringInit(&line);
1238 Tcl_DStringAppend(&line, AsciiString.ToCString(), -1);
1245 Tcl_DeleteChannelHandler(chan, StdinProc, (ClientData) chan);
1253 (void) Tcl_DStringAppend(&command, Tcl_DStringValue(&line), -1);
1254 cmd = Tcl_DStringAppend(&command, "\n", -1);
1255 Tcl_DStringFree(&line);
1258 if (!Tcl_CommandComplete(cmd)) {
1265 * Disable the stdin channel handler while evaluating the command;
1266 * otherwise if the command re-enters the event loop we might
1267 * process commands from stdin before the current command is
1268 * finished. Among other things, this will trash the text of the
1269 * command being evaluated.
1272 Tcl_CreateChannelHandler(chan, 0, StdinProc, (ClientData) chan);
1276 * Disable the stdin file handler while evaluating the command;
1277 * otherwise if the command re-enters the event loop we might
1278 * process commands from stdin before the current command is
1279 * finished. Among other things, this will trash the text of the
1280 * command being evaluated.
1284 // Tk_CreateFileHandler(0, 0, StdinProc, (ClientData) 0);
1287 // xab average to avoid an output SIGBUS of DRAW
1288 // to ultimately prescise or remove once
1289 // the problem of free on the global variable at the average
1296 Tcl_CreateChannelHandler(chan, TCL_READABLE, StdinProc,
1298 Tcl_DStringFree(&command);
1305 if (tty) Prompt(interp, gotPartial);
1307 } catch (Standard_Failure) {}
1313 // Source Specifique WNT
1315 /****************************************************\
1318 \****************************************************/
1320 #include "Draw_Window.hxx"
1321 #include "DrawRessource.h"
1324 #include <Draw_Appli.hxx>
1331 // Position of information in the extra memory
1333 // indicates SUBSYSTEM:CONSOLE linker option, to be set to True in main()
1335 Standard_Boolean Draw_IsConsoleSubsystem = Standard_False;
1338 Standard_Boolean Draw_BlackBackGround = Standard_True;
1340 // Creation of color stylos
1341 HPEN colorPenTab[MAXCOLOR] = {CreatePen(PS_SOLID, PENWIDTH, RGB(255,255,255)),
1342 CreatePen(PS_SOLID, PENWIDTH, RGB(255,0,0)),
1343 CreatePen(PS_SOLID, PENWIDTH, RGB(0,255,0)),
1344 CreatePen(PS_SOLID, PENWIDTH, RGB(0,0,255)),
1345 CreatePen(PS_SOLID, PENWIDTH, RGB(0,255,255)),
1346 CreatePen(PS_SOLID, PENWIDTH, RGB(255,215,0)),
1347 CreatePen(PS_SOLID, PENWIDTH, RGB(255,0,255)),
1348 CreatePen(PS_SOLID, PENWIDTH, RGB(255,52,179)),
1349 CreatePen(PS_SOLID, PENWIDTH, RGB(255,165,0)),
1350 CreatePen(PS_SOLID, PENWIDTH, RGB(255,228,225)),
1351 CreatePen(PS_SOLID, PENWIDTH, RGB(255,160,122)),
1352 CreatePen(PS_SOLID, PENWIDTH, RGB(199,21,133)),
1353 CreatePen(PS_SOLID, PENWIDTH, RGB(255,255,0)),
1354 CreatePen(PS_SOLID, PENWIDTH, RGB(240,230,140)),
1355 CreatePen(PS_SOLID, PENWIDTH, RGB(255,127,80))};
1357 // Correspondance mode X11 and WINDOWS NT
1358 int modeTab[16] = {R2_BLACK, R2_MASKPEN, R2_MASKPENNOT, R2_COPYPEN,
1359 R2_MASKNOTPEN, R2_NOP, R2_XORPEN, R2_MERGEPEN,
1360 R2_NOTMASKPEN, R2_NOTXORPEN, R2_NOT, R2_MERGEPENNOT,
1361 R2_NOTCOPYPEN, R2_MERGENOTPEN, R2_NOTMERGEPEN, R2_WHITE};
1363 /*--------------------------------------------------------*\
1364 | CREATE DRAW WINDOW PROCEDURE
1365 \*--------------------------------------------------------*/
1366 HWND DrawWindow::CreateDrawWindow(HWND hWndClient, int nitem)
1368 if (Draw_IsConsoleSubsystem) {
1369 HWND aWin = CreateWindowW (DRAWCLASS, DRAWTITLE,
1370 WS_OVERLAPPEDWINDOW,
1372 NULL, NULL,::GetModuleHandle(NULL), NULL);
1373 if (!Draw_VirtualWindows)
1375 SetWindowPos(aWin, HWND_TOPMOST, 1,1,1,1, SWP_NOMOVE);
1376 SetWindowPos(aWin, HWND_NOTOPMOST, 1,1,1,1, SWP_NOMOVE);
1381 HANDLE hInstance = (HANDLE )GetWindowLongPtrW (hWndClient, GWLP_HINSTANCE);
1383 return CreateMDIWindowW(DRAWCLASS, DRAWTITLE,
1384 WS_CAPTION | WS_CHILD | WS_THICKFRAME,
1386 hWndClient, (HINSTANCE)hInstance, nitem);
1391 /*--------------------------------------------------------*\
1392 | DRAW WINDOW PROCEDURE
1393 \*--------------------------------------------------------*/
1394 LRESULT APIENTRY DrawWindow::DrawProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam )
1396 DrawWindow* localObjet = (DrawWindow* )GetWindowLongPtrW (hWnd, CLIENTWND);
1399 return Draw_IsConsoleSubsystem
1400 ? DefWindowProcW (hWnd, wMsg, wParam, lParam)
1401 : DefMDIChildProcW (hWnd, wMsg, wParam, lParam);
1409 return 0; // do nothing - window destruction should be performed by application
1414 BeginPaint (hWnd, &ps);
1415 if (localObjet->GetUseBuffer())
1417 localObjet->Redraw();
1421 localObjet->WExpose();
1423 EndPaint (hWnd, &ps);
1428 if (localObjet->GetUseBuffer())
1430 localObjet->InitBuffer();
1431 localObjet->WExpose();
1432 localObjet->Redraw();
1438 return Draw_IsConsoleSubsystem
1439 ? DefWindowProcW (hWnd, wMsg, wParam, lParam)
1440 : DefMDIChildProcW (hWnd, wMsg, wParam, lParam);
1446 ** IMPLEMENTATION of the CLASS DRAWWINDOW
1449 /*--------------------------------------------------------*\
1450 | Initialization of static variables of DrawWindow
1451 \*--------------------------------------------------------*/
1453 DrawWindow* DrawWindow::firstWindow = NULL;
1454 HWND DrawWindow::hWndClientMDI = 0;
1456 /*--------------------------------------------------------*\
1457 | Constructors of Draw_Window
1458 \*--------------------------------------------------------*/
1460 // Default Constructor
1461 //________________________
1462 DrawWindow::DrawWindow() :
1467 myUseBuffer(Standard_False)
1469 if (firstWindow) firstWindow->previous = this;
1473 //________________________
1474 DrawWindow::DrawWindow(const char* title,
1475 Standard_Integer X, Standard_Integer Y,
1476 Standard_Integer dX,Standard_Integer dY) :
1477 win(0), next(firstWindow), previous(NULL), myMemHbm(NULL), myUseBuffer(Standard_False)
1479 if (firstWindow) firstWindow->previous = this;
1484 DrawWindow::DrawWindow(const char* title,
1485 Standard_Integer X, Standard_Integer Y,
1486 Standard_Integer dX,Standard_Integer dY,
1488 win(theWin),next(firstWindow), previous(NULL), myMemHbm(NULL), myUseBuffer(Standard_False)
1490 if (firstWindow) firstWindow->previous = this;
1498 /*--------------------------------------------------------*\
1499 | Destructor of DrawWindow
1500 \*--------------------------------------------------------*/
1501 DrawWindow::~DrawWindow()
1504 previous->next = next;
1508 next->previous = previous;
1510 // Delete 'off-screen drawing'-related objects
1512 DeleteObject(myMemHbm);
1519 /*--------------------------------------------------------*\
1521 \*--------------------------------------------------------*/
1522 void DrawWindow::Init(Standard_Integer theXLeft, Standard_Integer theYTop,
1523 Standard_Integer theWidth, Standard_Integer theHeight)
1527 win = CreateDrawWindow(hWndClientMDI, 0);
1530 // include decorations in the window dimensions
1531 // to reproduce same behaviour of Xlib window.
1532 DWORD aWinStyle = GetWindowLongW (win, GWL_STYLE);
1533 DWORD aWinStyleEx = GetWindowLongW (win, GWL_EXSTYLE);
1534 HMENU aMenu = GetMenu (win);
1537 aRect.top = theYTop;
1538 aRect.bottom = theYTop + theHeight;
1539 aRect.left = theXLeft;
1540 aRect.right = theXLeft + theWidth;
1541 AdjustWindowRectEx (&aRect, aWinStyle, aMenu != NULL ? TRUE : FALSE, aWinStyleEx);
1543 SetPosition (aRect.left, aRect.top);
1544 SetDimension (aRect.right - aRect.left, aRect.bottom - aRect.top);
1545 // Save the pointer at the instance associated to the window
1546 SetWindowLongPtrW (win, CLIENTWND, (LONG_PTR)this);
1547 HDC hDC = GetDC(win);
1548 SetBkColor(hDC, RGB(0, 0, 0));
1551 SelectObject(hDC, colorPenTab[myCurrPen]); // Default pencil
1552 SelectObject(hDC, GetStockObject(BLACK_BRUSH));
1553 SetTextColor(hDC, RGB(0,0,255));
1554 ReleaseDC(win, hDC);
1556 if (Draw_VirtualWindows)
1558 // create a virtual window
1559 SetUseBuffer (Standard_True);
1563 /*--------------------------------------------------------*\
1565 \*--------------------------------------------------------*/
1566 void DrawWindow::SetUseBuffer(Standard_Boolean use)
1572 /*--------------------------------------------------------*\
1574 \*--------------------------------------------------------*/
1575 void DrawWindow::InitBuffer()
1579 HDC hDC = GetDC(win);
1580 GetClientRect(win, &rc);
1583 GetObjectW (myMemHbm, sizeof(BITMAP), &aBmp);
1584 if (rc.right-rc.left == aBmp.bmWidth && rc.bottom-rc.top == aBmp.bmHeight) return;
1585 DeleteObject(myMemHbm);
1587 myMemHbm = (HBITMAP)CreateCompatibleBitmap(hDC,
1590 HDC aMemDC = GetMemDC(hDC);
1591 FillRect(aMemDC, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH));
1592 ReleaseMemDC(aMemDC);
1593 ReleaseDC(win, hDC);
1597 DeleteObject(myMemHbm);
1603 /*--------------------------------------------------------*\
1605 \*--------------------------------------------------------*/
1606 HDC DrawWindow::GetMemDC(HDC theWinDC)
1608 if (!myUseBuffer) return NULL;
1610 HDC aWorkDC = CreateCompatibleDC(theWinDC);
1611 myOldHbm = (HBITMAP)SelectObject(aWorkDC, myMemHbm);
1612 SetROP2(aWorkDC, modeTab[myCurrMode]);
1613 SelectObject(aWorkDC, colorPenTab[myCurrPen]);
1614 SetBkColor(aWorkDC, RGB(0, 0, 0));
1615 SelectObject(aWorkDC, GetStockObject(BLACK_BRUSH));
1616 SetTextColor(aWorkDC, RGB(0,0,255));
1621 /*--------------------------------------------------------*\
1623 \*--------------------------------------------------------*/
1624 void DrawWindow::ReleaseMemDC(HDC theMemDC)
1626 if (!myUseBuffer || !theMemDC) return;
1628 if (myOldHbm) SelectObject(theMemDC, myOldHbm);
1633 /*--------------------------------------------------------*\
1635 \*--------------------------------------------------------*/
1636 void DrawWindow::SetPosition(Standard_Integer posX, Standard_Integer posY)
1638 UINT aFlags = SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER;
1639 if (Draw_VirtualWindows)
1641 aFlags |= SWP_NOSENDCHANGING;
1643 SetWindowPos (win, 0, posX, posY, 0, 0, aFlags);
1647 /*--------------------------------------------------------*\
1649 \*--------------------------------------------------------*/
1650 void DrawWindow::SetDimension(Standard_Integer dimX, Standard_Integer dimY)
1652 UINT aFlags = SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER;
1653 if (Draw_VirtualWindows)
1655 aFlags |= SWP_NOSENDCHANGING;
1657 SetWindowPos (win, 0, 0, 0, dimX, dimY, aFlags);
1661 /*--------------------------------------------------------*\
1663 \*--------------------------------------------------------*/
1664 void DrawWindow::GetPosition(Standard_Integer &dimX,
1665 Standard_Integer &dimY)
1668 GetWindowRect(win, &rect);
1671 point.x = rect.left;
1674 ScreenToClient(hWndClientMDI, &point);
1680 /*--------------------------------------------------------*\
1682 \*--------------------------------------------------------*/
1683 Standard_Integer DrawWindow::HeightWin() const
1686 GetClientRect(win, &rect);
1687 return(rect.bottom-rect.top);
1691 /*--------------------------------------------------------*\
1693 \*--------------------------------------------------------*/
1694 Standard_Integer DrawWindow::WidthWin() const
1697 GetClientRect(win, &rect);
1698 return(rect.right-rect.left);
1702 /*--------------------------------------------------------*\
1704 \*--------------------------------------------------------*/
1705 void DrawWindow::SetTitle (const TCollection_AsciiString& theTitle)
1707 const TCollection_ExtendedString aTitleW (theTitle);
1708 SetWindowTextW (win, aTitleW.ToWideString());
1712 /*--------------------------------------------------------*\
1714 \*--------------------------------------------------------*/
1715 TCollection_AsciiString DrawWindow::GetTitle() const
1717 wchar_t aTitleW[32];
1718 GetWindowTextW (win, aTitleW, 30);
1719 return TCollection_AsciiString (aTitleW);
1722 //=======================================================================
1723 //function : IsMapped
1725 //=======================================================================
1726 bool Draw_Window::IsMapped() const
1728 if (Draw_VirtualWindows
1734 LONG aWinStyle = GetWindowLongW (win, GWL_STYLE);
1735 return (aWinStyle & WS_VISIBLE) != 0
1736 && (aWinStyle & WS_MINIMIZE) == 0;
1739 /*--------------------------------------------------------*\
1741 \*--------------------------------------------------------*/
1742 void DrawWindow::DisplayWindow()
1744 if (Draw_VirtualWindows)
1748 ShowWindow (win, SW_SHOW);
1753 /*--------------------------------------------------------*\
1755 \*--------------------------------------------------------*/
1756 void DrawWindow::Hide()
1758 ShowWindow(win, SW_HIDE);
1762 /*--------------------------------------------------------*\
1764 \*--------------------------------------------------------*/
1765 void DrawWindow::Destroy()
1772 /*--------------------------------------------------------*\
1774 \*--------------------------------------------------------*/
1775 void DrawWindow::Clear()
1777 HDC hDC = GetDC(win);
1778 HDC aWorkDC = myUseBuffer ? GetMemDC(hDC) : hDC;
1781 SelectObject(aWorkDC,GetStockObject(BLACK_PEN));
1782 Rectangle(aWorkDC, 0, 0, WidthWin(), HeightWin());
1783 RestoreDC(aWorkDC,-1);
1785 if (myUseBuffer) ReleaseMemDC(aWorkDC);
1789 /*--------------------------------------------------------*\
1791 \*--------------------------------------------------------*/
1792 static Standard_Boolean SaveBitmap (HBITMAP theHBitmap,
1793 const char* theFileName)
1795 // Get informations about the bitmap
1797 if (GetObjectW (theHBitmap, sizeof(BITMAP), &aBitmap) == 0)
1799 return Standard_False;
1802 Image_AlienPixMap anImage;
1803 const Standard_Size aSizeRowBytes = ((Standard_Size(aBitmap.bmWidth) * 24 + 31) / 32) * 4; // 4 bytes alignment for GetDIBits()
1804 if (!anImage.InitTrash (Image_Format_BGR, Standard_Size(aBitmap.bmWidth), Standard_Size(aBitmap.bmHeight), aSizeRowBytes))
1806 return Standard_False;
1808 anImage.SetTopDown (false);
1811 BITMAPINFOHEADER aBitmapInfo;
1812 memset (&aBitmapInfo, 0, sizeof(BITMAPINFOHEADER));
1813 aBitmapInfo.biSize = sizeof(BITMAPINFOHEADER);
1814 aBitmapInfo.biWidth = aBitmap.bmWidth;
1815 aBitmapInfo.biHeight = aBitmap.bmHeight; // positive means bottom-up!
1816 aBitmapInfo.biPlanes = 1;
1817 aBitmapInfo.biBitCount = 24;
1818 aBitmapInfo.biCompression = BI_RGB;
1821 HDC aDC = GetDC (NULL);
1822 Standard_Boolean isSuccess = GetDIBits (aDC, theHBitmap,
1823 0, // first scan line to set
1824 aBitmap.bmHeight, // number of scan lines to copy
1825 anImage.ChangeData(), // array for bitmap bits
1826 (LPBITMAPINFO )&aBitmapInfo, // bitmap data info
1827 DIB_RGB_COLORS) != 0;
1828 ReleaseDC (NULL, aDC);
1829 return isSuccess && anImage.Save (theFileName);
1832 /*--------------------------------------------------------*\
1834 \*--------------------------------------------------------*/
1835 Standard_Boolean DrawWindow::Save (const char* theFileName) const
1839 return SaveBitmap (myMemHbm, theFileName);
1843 GetClientRect (win, &aRect);
1844 int aWidth = aRect.right - aRect.left;
1845 int aHeight = aRect.bottom - aRect.top;
1848 HDC aDstDC = GetDC (NULL);
1849 HDC aSrcDC = GetDC (win); // we copy only client area
1850 HDC aMemDC = CreateCompatibleDC (aDstDC);
1852 // Copy the screen to the bitmap
1853 HBITMAP anHBitmapDump = CreateCompatibleBitmap (aDstDC, aWidth, aHeight);
1854 HBITMAP anHBitmapOld = (HBITMAP )SelectObject (aMemDC, anHBitmapDump);
1855 BitBlt (aMemDC, 0, 0, aWidth, aHeight, aSrcDC, 0, 0, SRCCOPY);
1857 Standard_Boolean isSuccess = SaveBitmap (anHBitmapDump, theFileName);
1860 DeleteObject (SelectObject (aMemDC, anHBitmapOld));
1866 /*--------------------------------------------------------*\
1868 \*--------------------------------------------------------*/
1869 void DrawWindow::DrawString(int x,int y, char* text)
1871 HDC hDC = GetDC(win);
1872 HDC aWorkDC = myUseBuffer ? GetMemDC(hDC) : hDC;
1874 TCollection_ExtendedString textW (text);
1875 TextOutW(aWorkDC, x, y, (const wchar_t*)textW.ToExtString(), (int )strlen(text));
1877 if (myUseBuffer) ReleaseMemDC(aWorkDC);
1881 /*--------------------------------------------------------*\
1883 \*--------------------------------------------------------*/
1884 void DrawWindow::DrawSegments(Segment *tab, int nbElem)
1886 HDC hDC = GetDC(win);
1887 HDC aWorkDC = myUseBuffer ? GetMemDC(hDC) : hDC;
1889 for(int i = 0 ; i < nbElem ; i++)
1891 MoveToEx(aWorkDC, tab[i].x1, tab[i].y1, NULL);
1892 LineTo(aWorkDC, tab[i].x2, tab[i].y2);
1895 if (myUseBuffer) ReleaseMemDC(aWorkDC);
1899 /*--------------------------------------------------------*\
1901 \*--------------------------------------------------------*/
1902 void DrawWindow::Redraw()
1905 HDC hDC = GetDC(win);
1907 GetClientRect(win, &rc);
1908 HDC aMemDC = GetMemDC(hDC);
1911 rc.right-rc.left, rc.bottom-rc.top,
1914 ReleaseMemDC(aMemDC);
1919 /*--------------------------------------------------------*\
1921 \*--------------------------------------------------------*/
1922 void DrawWindow::SetMode(int mode)
1924 HDC hDC = GetDC(win);
1926 SetROP2(hDC, modeTab[mode]);
1931 /*--------------------------------------------------------*\
1933 \*--------------------------------------------------------*/
1934 void DrawWindow::SetColor(Standard_Integer color)
1936 HDC hDC = GetDC(win);
1938 SelectObject(hDC,colorPenTab[color]);
1943 /*--------------------------------------------------------*\
1945 \*--------------------------------------------------------*/
1946 void DrawWindow::WExpose()
1951 /*--------------------------------------------------------*\
1953 \*--------------------------------------------------------*/
1954 void DrawWindow::WButtonPress(const Standard_Integer,
1955 const Standard_Integer,
1956 const Standard_Integer&)
1961 /*--------------------------------------------------------*\
1963 \*--------------------------------------------------------*/
1964 void DrawWindow::WButtonRelease(const Standard_Integer,
1965 const Standard_Integer,
1966 const Standard_Integer&)
1971 /*--------------------------------------------------------*\
1973 \*--------------------------------------------------------*/
1974 void Draw_Window::WMotionNotify(const Standard_Integer ,
1975 const Standard_Integer )
1980 /*--------------------------------------------------------*\
1982 \*--------------------------------------------------------*/
1983 void DrawWindow::WConfigureNotify(const Standard_Integer,
1984 const Standard_Integer,
1985 const Standard_Integer,
1986 const Standard_Integer)
1991 /*--------------------------------------------------------*\
1993 \*--------------------------------------------------------*/
1994 void DrawWindow::WUnmapNotify()
2001 ** IMPLEMENTATION of the CLASS SEGMENT
2004 /*--------------------------------------------------------*\
2006 \*--------------------------------------------------------*/
2008 void Segment::Init(Standard_Integer a1, Standard_Integer a2,
2009 Standard_Integer a3, Standard_Integer a4)
2017 static DWORD WINAPI tkLoop(VOID);
2019 static Tk_Window mainWindow;
2022 //* threads sinchronization *//
2023 DWORD dwMainThreadId;
2024 console_semaphore_value volatile console_semaphore = WAIT_CONSOLE_COMMAND;
2025 wchar_t console_command[DRAW_COMMAND_SIZE + 1];
2026 bool volatile isTkLoopStarted = false;
2028 /*--------------------------------------------------------*\
2030 \*--------------------------------------------------------*/
2031 Standard_Boolean Init_Appli(HINSTANCE hInst,
2032 HINSTANCE hPrevInst, int nShow, HWND& hWndFrame )
2034 Draw_Interpretor& aCommands = Draw::GetInterpretor();
2038 console_semaphore = STOP_CONSOLE;
2040 interp = aCommands.Interp();
2043 dwMainThreadId = GetCurrentThreadId();
2045 //necessary for normal Tk operation
2046 hThread = CreateThread(NULL, // no security attributes
2047 0, // use default stack size
2048 (LPTHREAD_START_ROUTINE) tkLoop, // thread function
2049 NULL, // no thread function argument
2050 0, // use default creation flags
2053 cout << "Tcl/Tk main loop thread not created. Switching to batch mode..." << endl;
2054 Draw_Batch = Standard_True;
2059 } catch (Standard_Failure) {
2060 cout <<" Pb au lancement de TK_Init "<<endl;
2063 Tcl_StaticPackage(interp, "Tk", Tk_Init, (Tcl_PackageInitProc *) NULL);
2065 //since the main Tcl/Tk loop wasn't created --> switch to batch mode
2066 return Standard_False;
2069 // san - 06/08/2002 - Time for tkLoop to start; Tk fails to initialize otherwise
2070 while (!isTkLoopStarted)
2073 // Saving of window classes
2075 if(!RegisterAppClass(hInst))
2076 return(Standard_False);
2079 ** Enter the application message-polling loop. This is the anchor for
2082 hWndFrame = !Draw_IsConsoleSubsystem ? CreateAppWindow (hInst) : NULL;
2083 if (hWndFrame != NULL)
2085 ShowWindow(hWndFrame,nShow);
2086 UpdateWindow(hWndFrame);
2089 return Standard_True;
2092 Standard_Boolean Draw_Interprete (const char*);
2094 /*--------------------------------------------------------*\
2095 | readStdinThreadFunc
2096 \*--------------------------------------------------------*/
2097 static DWORD WINAPI readStdinThreadFunc()
2099 if (!Draw_IsConsoleSubsystem)
2104 // Console locale could be set to the system codepage .OCP (UTF-8 is not properly supported on Windows).
2105 // However, to use it, we have to care using std::wcerr/fwprintf/WriteConsoleW for non-ascii strings everywhere (including Tcl itself),
2106 // or otherwise we can have incomplete output issues
2107 // (e.g. UNICODE string will be NOT just corrupted as in case when we don't set setlocale()
2108 // but will break further normal output to console due to special characters being accidentally handled by console in the wrong way).
2109 //setlocale (LC_ALL, ".OCP");
2111 // _O_U16TEXT can be used with fgetws() to get similar result as ReadConsoleW() without affecting setlocale(),
2112 // however it would break pipe input
2113 //_setmode (_fileno(stdin), _O_U16TEXT);
2115 bool isConsoleInput = true;
2118 while (console_semaphore != WAIT_CONSOLE_COMMAND)
2123 const HANDLE anStdIn = ::GetStdHandle (STD_INPUT_HANDLE);
2125 && anStdIn != INVALID_HANDLE_VALUE
2129 if (ReadConsoleW (anStdIn, console_command, DRAW_COMMAND_SIZE, &aNbRead, NULL))
2131 console_command[aNbRead] = L'\0';
2132 console_semaphore = HAS_CONSOLE_COMMAND;
2137 const DWORD anErr = GetLastError();
2138 if (anErr != ERROR_SUCCESS)
2140 // fallback using fgetws() which would work with pipes
2141 // but supports Unicode only through multi-byte encoding (which is not UTF-8)
2142 isConsoleInput = false;
2148 // fgetws() works only for characters within active locale (see setlocale())
2149 if (fgetws (console_command, DRAW_COMMAND_SIZE, stdin))
2151 console_semaphore = HAS_CONSOLE_COMMAND;
2156 /*--------------------------------------------------------*\
2157 | exitProc: finalization handler for Tcl/Tk thread. Forces parent process to die
2158 \*--------------------------------------------------------*/
2159 void exitProc(ClientData /*dc*/)
2161 NCollection_List<Draw_Window::FCallbackBeforeTerminate>::Iterator Iter(MyCallbacks);
2162 for(; Iter.More(); Iter.Next())
2166 HANDLE proc = GetCurrentProcess();
2167 TerminateProcess(proc, 0);
2170 // This is fixed version of TclpGetDefaultStdChannel() defined in tclWinChan.c
2171 // See https://core.tcl.tk/tcl/tktview/91c9bc1c457fda269ae18595944fc3c2b54d961d
2173 TclpGetDefaultStdChannel(
2174 int type) /* One of TCL_STDIN, TCL_STDOUT, or
2177 Tcl_Channel channel;
2180 const char *bufMode = NULL;
2181 DWORD handleId = (DWORD) -1;
2182 /* Standard handle to retrieve. */
2186 handleId = STD_INPUT_HANDLE;
2187 mode = TCL_READABLE;
2191 handleId = STD_OUTPUT_HANDLE;
2192 mode = TCL_WRITABLE;
2196 handleId = STD_ERROR_HANDLE;
2197 mode = TCL_WRITABLE;
2201 Tcl_Panic("TclGetDefaultStdChannel: Unexpected channel type");
2205 handle = GetStdHandle(handleId);
2208 * Note that we need to check for 0 because Windows may return 0 if this
2209 * is not a console mode application, even though this is not a valid
2213 if ((handle == INVALID_HANDLE_VALUE) || (handle == 0)) {
2214 return (Tcl_Channel) NULL;
2218 * Make duplicate of the standard handle as it may be altered
2219 * (closed, reopened with another type of the object etc.) by
2220 * the system or a user code at any time, e.g. by call to _dup2()
2222 if (! DuplicateHandle (GetCurrentProcess(), handle,
2223 GetCurrentProcess(), &handle,
2224 0, FALSE, DUPLICATE_SAME_ACCESS)) {
2225 return (Tcl_Channel) NULL;
2228 channel = Tcl_MakeFileChannel(handle, mode);
2230 if (channel == NULL) {
2231 return (Tcl_Channel) NULL;
2235 * Set up the normal channel options for stdio handles.
2238 if (Tcl_SetChannelOption(NULL,channel,"-translation","auto")!=TCL_OK ||
2239 Tcl_SetChannelOption(NULL,channel,"-eofchar","\032 {}")!=TCL_OK ||
2240 Tcl_SetChannelOption(NULL,channel,"-buffering",bufMode)!=TCL_OK) {
2241 Tcl_Close(NULL, channel);
2242 return (Tcl_Channel) NULL;
2248 static void ResetStdChannel (int type)
2250 Tcl_Channel aChannel = TclpGetDefaultStdChannel (type);
2251 Tcl_SetStdChannel (aChannel, type);
2254 Tcl_RegisterChannel (NULL, aChannel);
2258 /*--------------------------------------------------------*\
2259 | tkLoop: implements Tk_Main()-like behaviour in a separate thread
2260 \*--------------------------------------------------------*/
2261 static DWORD WINAPI tkLoop(VOID)
2263 Tcl_CreateExitHandler(exitProc, 0);
2265 // Work-around against issue with Tcl standard channels on Windows.
2266 // These channels by default use OS handles owned by the system which
2267 // may get invalidated e.g. by dup2() (see dlog command).
2268 // If this happens, output to stdout from Tcl (e.g. puts) gets broken
2269 // (sympthom is error message: "error writing "stdout": bad file number").
2270 // To prevent this, we set standard channels using duplicate of system handles.
2271 // The effect is that Tcl channel becomes independent on C file descriptor
2272 // and even if stdout/stderr are redirected using dup2(), Tcl keeps using
2274 ResetStdChannel (TCL_STDOUT);
2275 ResetStdChannel (TCL_STDERR);
2277 #if (TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 5))
2278 // Plain Tcl (8.6.4+) initializes interpretor channels automatically, but
2279 // ActiveState Tcl (at least 8.6.4) does not seem to do that, so channels
2280 // need to be set into interpretor explicitly
2282 Draw_Interpretor& aCommands = Draw::GetInterpretor();
2284 Tcl_Channel aChannelIn = Tcl_GetStdChannel (TCL_STDIN);
2285 Tcl_Channel aChannelOut = Tcl_GetStdChannel (TCL_STDOUT);
2286 Tcl_Channel aChannelErr = Tcl_GetStdChannel (TCL_STDERR);
2287 if (aChannelIn != NULL)
2289 Tcl_RegisterChannel (aCommands.Interp(), aChannelIn);
2291 if (aChannelOut != NULL)
2293 Tcl_RegisterChannel (aCommands.Interp(), aChannelOut);
2295 if (aChannelErr != NULL)
2297 Tcl_RegisterChannel (aCommands.Interp(), aChannelErr);
2303 // initialize the Tk library if not in 'virtual windows' mode
2304 // (virtual windows are created by OCCT with native APIs,
2305 // thus Tk will be useless)
2306 if (!Draw_VirtualWindows)
2311 Standard_Integer res = Tk_Init (interp);
2314 #if ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 5)))
2315 cout << "tkLoop: error in Tk initialization. Tcl reported: " << Tcl_GetStringResult(interp) << endl;
2317 cout << "tkLoop: error in Tk initialization. Tcl reported: " << interp->result << endl;
2321 catch (Standard_Failure)
2323 cout << "tkLoop: exception in TK_Init\n";
2325 Tcl_StaticPackage (interp, "Tk", Tk_Init, (Tcl_PackageInitProc* ) NULL);
2326 mainWindow = Tk_MainWindow (interp);
2327 if (mainWindow == NULL)
2329 #if ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 5)))
2330 fprintf (stderr, "%s\n", Tcl_GetStringResult(interp));
2332 fprintf (stderr, "%s\n", interp->result);
2334 cout << "tkLoop: Tk_MainWindow() returned NULL. Exiting...\n";
2337 Tk_Name(mainWindow) = Tk_GetUid (Tk_SetAppName (mainWindow, "Draw"));
2341 // set signal handler in the new thread
2342 OSD::SetSignal(Standard_False);
2344 // inform the others that we have started
2345 isTkLoopStarted = true;
2347 while (console_semaphore == STOP_CONSOLE)
2348 Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT);
2350 if (Draw_IsConsoleSubsystem && console_semaphore == WAIT_CONSOLE_COMMAND)
2354 Standard_Boolean toLoop = Standard_True;
2357 while(Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT));
2358 if (console_semaphore == HAS_CONSOLE_COMMAND)
2360 TCollection_AsciiString aCmdUtf8 (console_command);
2361 if (Draw_Interprete (aCmdUtf8.ToCString()))
2363 if (Draw_IsConsoleSubsystem) Prompt (interp, 0);
2367 if (Draw_IsConsoleSubsystem) Prompt (interp, 1);
2369 console_semaphore = WAIT_CONSOLE_COMMAND;
2376 // We should not exit until the Main Tk window is closed
2377 toLoop = (Draw_VirtualWindows || Tk_GetNumMainWindows() > 0);
2385 /*--------------------------------------------------------*\
2387 \*--------------------------------------------------------*/
2388 void Run_Appli(HWND hWnd)
2391 HACCEL hAccel = NULL;
2395 // if (!(hAccel = LoadAccelerators (hInstance, MAKEINTRESOURCE(ACCEL_ID))))
2396 // MessageBox(hWnd, "MDI: Load Accel failure!", "Error", MB_OK);
2399 if (Draw_IsConsoleSubsystem) {
2400 hThread = CreateThread(NULL, // no security attributes
2401 0, // use default stack size
2402 (LPTHREAD_START_ROUTINE) readStdinThreadFunc, // thread function
2403 NULL, // no thread function argument
2404 0, // use default creation flags
2405 &IDThread); // returns thread identifier
2407 cout << "pb in creation of the thread reading stdin" << endl;
2408 Draw_IsConsoleSubsystem = Standard_False;
2409 Init_Appli (GetModuleHandleW (NULL),
2410 GetModuleHandleW (NULL),
2411 1, hWnd); // reinit => create MDI client wnd
2415 //turn on the command interpretation mechanism (regardless of the mode)
2416 if (console_semaphore == STOP_CONSOLE)
2417 console_semaphore = WAIT_CONSOLE_COMMAND;
2419 //simple Win32 message loop
2420 while (GetMessageW (&msg, NULL, 0, 0) > 0)
2422 if (!TranslateAcceleratorW (hWnd, hAccel, &msg))
2424 TranslateMessage (&msg);
2425 DispatchMessageW (&msg);
2432 /*--------------------------------------------------------*\
2434 \*--------------------------------------------------------*/
2435 void Destroy_Appli(HINSTANCE hInst)
2437 UnregisterAppClass(hInst);
2438 for (int i = 0 ; i < MAXCOLOR ; i++)
2439 DeleteObject(colorPenTab[i]);
2442 /*--------------------------------------------------------*\
2444 \*--------------------------------------------------------*/
2445 void DrawWindow::SelectWait(HANDLE& hWnd, int& x, int& y, int& button)
2451 GetMessageW (&msg, NULL, 0, 0);
2452 while((msg.message != WM_RBUTTONDOWN && msg.message != WM_LBUTTONDOWN) ||
2453 ! ( Draw_IsConsoleSubsystem || IsChild(DrawWindow::hWndClientMDI,msg.hwnd)) )
2455 GetMessageW (&msg, NULL, 0, 0);
2459 x = LOWORD(msg.lParam);
2460 y = HIWORD(msg.lParam);
2461 if (msg.message == WM_LBUTTONDOWN)
2467 /*--------------------------------------------------------*\
2469 \*--------------------------------------------------------*/
2470 void DrawWindow::SelectNoWait(HANDLE& hWnd, int& x, int& y, int& button)
2476 GetMessageW (&msg,NULL,0,0);
2477 while((msg.message != WM_RBUTTONDOWN && msg.message != WM_LBUTTONDOWN &&
2478 msg.message != WM_MOUSEMOVE) ||
2479 ! ( Draw_IsConsoleSubsystem || IsChild(DrawWindow::hWndClientMDI,msg.hwnd) ) )
2481 GetMessageW(&msg,NULL,0,0);
2484 x = LOWORD(msg.lParam);
2485 y = HIWORD(msg.lParam);
2486 switch (msg.message)
2488 case WM_LBUTTONDOWN :
2492 case WM_RBUTTONDOWN :
2502 Standard_Boolean DrawWindow::DefineColor (const Standard_Integer, const char*)
2504 return Standard_True;