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 Draw_Interpretor theCommands;
34 extern Standard_Boolean Draw_VirtualWindows;
35 static Tcl_Interp *interp; /* Interpreter for this application. */
36 static NCollection_List<Draw_Window::FCallbackBeforeTerminate> MyCallbacks;
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 if (Draw_VirtualWindows)
377 myUseBuffer = Standard_True;
382 base.gc = XCreateGC(Draw_WindowDisplay, win, 0, NULL);
384 XSetPlaneMask(Draw_WindowDisplay,base.gc,AllPlanes);
385 XSetForeground(Draw_WindowDisplay,
386 base.gc, WhitePixel(Draw_WindowDisplay,Draw_WindowScreen));
387 XSetBackground(Draw_WindowDisplay,
388 base.gc, BlackPixel(Draw_WindowDisplay,Draw_WindowScreen));
389 // save in case of window recovery
391 base.xswa.backing_store = Always;
392 XChangeWindowAttributes(Draw_WindowDisplay, win,
393 CWBackingStore, &base.xswa);
395 XSetLineAttributes (Draw_WindowDisplay, base.gc,
396 0, LineSolid, CapButt, JoinMiter);
399 //=======================================================================
400 //function : InitBuffer
402 //=======================================================================
403 void Draw_Window::InitBuffer()
407 XFreePixmap (Draw_WindowDisplay, myBuffer);
409 XWindowAttributes winAttr;
410 XGetWindowAttributes (Draw_WindowDisplay, win, &winAttr);
411 myBuffer = XCreatePixmap (Draw_WindowDisplay, win, winAttr.width, winAttr.height, winAttr.depth);
413 else if (myBuffer != 0)
415 XFreePixmap (Draw_WindowDisplay, myBuffer);
420 //=======================================================================
421 //function : StopWinManager
423 //=======================================================================
424 void Draw_Window::StopWinManager()
427 XWindowAttributes winAttr;
428 XGetWindowAttributes (Draw_WindowDisplay, win, &winAttr);
432 myHints.flags = USPosition;
433 myHints.x = (int) 30;
434 myHints.y = (int) 100;
436 base.xswa.override_redirect = 1;
437 base.xswa.border_pixel = BlackPixel(Draw_WindowDisplay,
439 base.xswa.background_pixel = WhitePixel(Draw_WindowDisplay,
442 withWindowManager = Standard_False;
444 win = XCreateWindow(Draw_WindowDisplay, myMother,
445 winAttr.x, winAttr.y,
446 winAttr.width, winAttr.height,
448 CopyFromParent, InputOutput, CopyFromParent,
449 CWBorderPixel|CWOverrideRedirect|CWBackPixel, &base.xswa);
452 // adwise to the window manager to place it where I wish
453 XSetWMNormalHints(Draw_WindowDisplay,win,&myHints);
455 // all masks of the old window are reassigned to the new one.
456 XSelectInput(Draw_WindowDisplay,win,winAttr.your_event_mask);
459 //=======================================================================
460 //function : SetPosition
462 //=======================================================================
463 void Draw_Window::SetPosition(Standard_Integer NewXpos,
464 Standard_Integer NewYpos)
466 Standard_Integer x,y;
469 if ( (x != NewXpos) || (y != NewYpos) )
470 XMoveWindow(Draw_WindowDisplay, win, NewXpos, NewYpos);
473 //=======================================================================
474 //function : SetDimension
476 //=======================================================================
477 void Draw_Window::SetDimension(Standard_Integer NewDx,
478 Standard_Integer NewDy)
480 if ( (NewDx != WidthWin() ) || (NewDy != HeightWin() ) )
481 XResizeWindow(Draw_WindowDisplay, win, NewDx, NewDy);
484 //=======================================================================
485 //function : GetPosition
487 //=======================================================================
488 void Draw_Window::GetPosition(Standard_Integer &PosX,
489 Standard_Integer &PosY)
491 XWindowAttributes winAttr;
492 XGetWindowAttributes(Draw_WindowDisplay, win, &winAttr);
498 //=======================================================================
499 //function : HeightWin
501 //=======================================================================
502 Standard_Integer Draw_Window::HeightWin() const
505 XWindowAttributes winAttr;
506 XGetWindowAttributes(Draw_WindowDisplay, win, &winAttr);
512 //=======================================================================
513 //function : WidthWin
515 //=======================================================================
516 Standard_Integer Draw_Window::WidthWin() const
519 XWindowAttributes winAttr;
520 XGetWindowAttributes(Draw_WindowDisplay, win, &winAttr);
526 //=======================================================================
527 //function : SetTitle
529 //=======================================================================
530 void Draw_Window::SetTitle(const TCollection_AsciiString& theTitle)
532 XStoreName (Draw_WindowDisplay, win, theTitle.ToCString());
535 //=======================================================================
536 //function : GetTitle
538 //=======================================================================
539 TCollection_AsciiString Draw_Window::GetTitle() const
542 XFetchName (Draw_WindowDisplay, win, &aTitle);
543 return TCollection_AsciiString (aTitle);
546 //=======================================================================
547 //function : GetDrawable
549 //=======================================================================
550 Drawable Draw_Window::GetDrawable() const
552 return myUseBuffer ? myBuffer : win;
555 //=======================================================================
556 //function :DefineColor
558 //=======================================================================
559 Standard_Boolean Draw_Window::DefineColor(const Standard_Integer i, const char* colorName)
563 if (!XParseColor(Draw_WindowDisplay,Draw_WindowColorMap,colorName,&color))
564 return Standard_False;
565 if (!XAllocColor(Draw_WindowDisplay,Draw_WindowColorMap,&color))
566 return Standard_False;
567 thePixels[i % MAXCOLOR] = color.pixel;
568 return Standard_True;
571 //=======================================================================
572 //function : DisplayWindow
574 //=======================================================================
575 void Draw_Window::DisplayWindow()
577 if (Draw_VirtualWindows)
583 XMapRaised(Draw_WindowDisplay, win);
585 XFlush(Draw_WindowDisplay);
588 //=======================================================================
591 //=======================================================================
592 void Draw_Window::Hide()
594 XUnmapWindow(Draw_WindowDisplay, win);
597 //=======================================================================
600 //=======================================================================
601 void Draw_Window::Destroy()
603 XFreeGC (Draw_WindowDisplay, base.gc);
604 XDestroyWindow(Draw_WindowDisplay, win);
608 XFreePixmap(Draw_WindowDisplay, myBuffer);
613 //=======================================================================
616 //=======================================================================
617 void Draw_Window::Clear()
621 // XClearArea only applicable for windows
622 XGCValues currValues;
623 XGetGCValues(Draw_WindowDisplay, base.gc, GCBackground | GCForeground, &currValues);
624 XSetForeground(Draw_WindowDisplay, base.gc, currValues.background);
625 XFillRectangle(Draw_WindowDisplay, myBuffer, base.gc, 0, 0, WidthWin(), HeightWin());
626 XSetForeground(Draw_WindowDisplay, base.gc, currValues.foreground);
630 XClearArea(Draw_WindowDisplay, win, 0, 0, 0, 0, False);
634 //=======================================================================
637 //=======================================================================
638 void Draw_Window::Flush()
640 XFlush(Draw_WindowDisplay);
643 //=======================================================================
644 //function : DrawString
646 //=======================================================================
647 void Draw_Window::DrawString(int X, int Y, char *text)
649 XDrawString(Draw_WindowDisplay, GetDrawable(), base.gc, X, Y, text, strlen(text));
652 //=======================================================================
653 //function : DrawSegments
655 //=======================================================================
656 void Draw_Window::DrawSegments(Segment *tab, int nbElem)
658 XDrawSegments(Draw_WindowDisplay, GetDrawable(), base.gc, (XSegment*) tab, nbElem);
661 //=======================================================================
664 //=======================================================================
665 void Draw_Window::Redraw()
668 XCopyArea (Draw_WindowDisplay,
669 myBuffer, win, // source, destination Drawables
672 WidthWin(), HeightWin(),
673 0, 0); // destination x, y
677 //=======================================================================
678 //function : SetColor
680 //=======================================================================
681 void Draw_Window::SetColor(Standard_Integer color)
683 XSetForeground(Draw_WindowDisplay, base.gc, thePixels[color]);
686 //=======================================================================
689 //=======================================================================
690 void Draw_Window::SetMode( int mode)
692 XSetFunction(Draw_WindowDisplay, base.gc, mode);
695 //=======================================================================
698 //=======================================================================
699 Standard_Boolean Draw_Window::Save (const char* theFileName) const
701 // make sure all draw operations done
702 XSync (Draw_WindowDisplay, True);
705 XWindowAttributes winAttr;
706 XGetWindowAttributes (Draw_WindowDisplay, win, &winAttr);
710 // make sure that the whole window fit on display to prevent BadMatch error
711 XWindowAttributes winAttrRoot;
712 XGetWindowAttributes (Draw_WindowDisplay, XRootWindowOfScreen (winAttr.screen), &winAttrRoot);
714 Window winChildDummy;
717 XTranslateCoordinates (Draw_WindowDisplay, win, XRootWindowOfScreen (winAttr.screen),
718 0, 0, &winLeft, &winTop, &winChildDummy);
720 if (((winLeft + winAttr.width) > winAttrRoot.width) || winLeft < winAttrRoot.x ||
721 ((winTop + winAttr.height) > winAttrRoot.height) || winTop < winAttrRoot.y)
723 std::cerr << "The window not fully visible! Can't create the snapshot.\n";
724 return Standard_False;
729 if (XMatchVisualInfo (Draw_WindowDisplay, Draw_WindowScreen, 32, TrueColor, &aVInfo) == 0
730 && XMatchVisualInfo (Draw_WindowDisplay, Draw_WindowScreen, 24, TrueColor, &aVInfo) == 0)
732 std::cerr << "24-bit TrueColor visual is not supported by server!\n";
733 return Standard_False;
736 Image_AlienPixMap anImage;
737 bool isBigEndian = Image_PixMap::IsBigEndianHost();
738 const Standard_Size aSizeRowBytes = Standard_Size(winAttr.width) * 4;
739 if (!anImage.InitTrash (isBigEndian ? Image_PixMap::ImgRGB32 : Image_PixMap::ImgBGR32,
740 Standard_Size(winAttr.width), Standard_Size(winAttr.height), aSizeRowBytes))
742 return Standard_False;
744 anImage.SetTopDown (true);
746 XImage* anXImage = XCreateImage (Draw_WindowDisplay, aVInfo.visual,
747 32, ZPixmap, 0, (char* )anImage.ChangeData(), winAttr.width, winAttr.height, 32, int(aSizeRowBytes));
748 anXImage->bitmap_bit_order = anXImage->byte_order = (isBigEndian ? MSBFirst : LSBFirst);
749 if (XGetSubImage (Draw_WindowDisplay, GetDrawable(),
750 0, 0, winAttr.width, winAttr.height,
751 AllPlanes, ZPixmap, anXImage, 0, 0) == NULL)
753 anXImage->data = NULL;
754 XDestroyImage (anXImage);
755 return Standard_False;
759 anXImage->data = NULL;
760 XDestroyImage (anXImage);
763 return anImage.Save (theFileName);
766 //=======================================================================
769 //=======================================================================
771 void Draw_Window::Wait (Standard_Boolean wait)
775 XSelectInput(Draw_WindowDisplay,win,
776 ButtonPressMask|ExposureMask | StructureNotifyMask |
780 XSelectInput(Draw_WindowDisplay,win,
781 ButtonPressMask|ExposureMask | StructureNotifyMask);
785 //=======================================================================
786 //function : ProcessEvent
788 //=======================================================================
790 void ProcessEvent(Draw_Window& win, XEvent& xev)
792 Standard_Integer X,Y,button;
807 button = xev.xbutton.button;
808 win.WButtonPress(X,Y,button);
814 button = xev.xbutton.button;
815 win.WButtonRelease(X,Y,button);
819 XLookupString(&(xev.xkey),
829 win.WMotionNotify(X,Y);
832 case ConfigureNotify :
833 if (win.withWindowManager)
834 win.WConfigureNotify(xev.xconfigure.x, xev.xconfigure.y,
835 xev.xconfigure.width,
836 xev.xconfigure.height);
846 //=======================================================================
849 //=======================================================================
850 void Draw_Window::WExpose()
854 //=======================================================================
855 //function : WButtonPress
857 //=======================================================================
858 void Draw_Window::WButtonPress(const Standard_Integer,
859 const Standard_Integer,
860 const Standard_Integer&)
864 //=======================================================================
865 //function : WButtonRelease
867 //=======================================================================
868 void Draw_Window::WButtonRelease(const Standard_Integer,
869 const Standard_Integer,
870 const Standard_Integer&)
874 /**************************
875 //=======================================================================
876 //function : WKeyPress
878 //=======================================================================
880 void Draw_Window::WKeyPress(char, KeySym&)
883 ***************************/
885 //=======================================================================
886 //function : WMotionNotify
888 //=======================================================================
889 void Draw_Window::WMotionNotify(const Standard_Integer ,
890 const Standard_Integer )
894 //=======================================================================
895 //function : WConfigureNotify
897 //=======================================================================
899 void Draw_Window::WConfigureNotify(const Standard_Integer,
900 const Standard_Integer,
901 const Standard_Integer,
902 const Standard_Integer)
906 //=======================================================================
907 //function : WUnmapNotify
909 //=======================================================================
911 void Draw_Window::WUnmapNotify()
916 //======================================================
917 // funtion : ProcessEvents
918 // purpose : process pending X events
919 //======================================================
921 static void ProcessEvents(ClientData,int)
925 while (XPending(Draw_WindowDisplay)) {
930 XNextEvent(Draw_WindowDisplay,&xev);
932 /* search the window in the window list */
933 Draw_Window* w = Draw_Window::firstWindow;
934 Standard_Integer found=0;
936 if (xev.xany.window == w->win) {
937 ProcessEvent(*w, xev);
944 Tk_HandleEvent(&xev);
949 //======================================================
950 // funtion : GetNextEvent()
952 //======================================================
953 void GetNextEvent(Event& ev)
956 XNextEvent(Draw_WindowDisplay, &xev);
961 ev.window = xev.xbutton.window;
962 ev.button = xev.xbutton.button;
963 ev.x = xev.xbutton.x;
964 ev.y = xev.xbutton.y;
969 ev.window = xev.xmotion.window;
971 ev.x = xev.xmotion.x;
972 ev.y = xev.xmotion.y;
978 //======================================================
979 // funtion :Run_Appli
981 //======================================================
984 static Standard_Boolean(*Interprete) (const char*);
986 void Run_Appli(Standard_Boolean (*interprete) (const char*))
988 Tcl_Channel outChannel, inChannel ;
989 Interprete = interprete;
994 * Commands will come from standard input, so set up an event
995 * handler for standard input. If the input device is aEvaluate the
996 * .rc file, if one has been specified, set up an event handler
997 * for standard input, and print a prompt if the input
998 * device is a terminal.
1000 inChannel = Tcl_GetStdChannel(TCL_STDIN);
1002 Tcl_CreateChannelHandler(inChannel, TCL_READABLE, StdinProc,
1003 (ClientData) inChannel);
1006 // Create a handler for the draw display
1008 // Adding of the casting into void* to be able to compile on AO1
1009 // ConnectionNumber(Draw_WindowDisplay) is an int 32 bits
1010 // (void*) is a pointer 64 bits ???????
1012 #if !defined(__APPLE__) || defined(MACOSX_USE_GLX)
1013 #if TCL_MAJOR_VERSION < 8
1014 Tk_CreateFileHandler((void*) ConnectionNumber(Draw_WindowDisplay),
1015 TK_READABLE, ProcessEvents,(ClientData) 0 );
1017 Tk_CreateFileHandler(ConnectionNumber(Draw_WindowDisplay),
1018 TK_READABLE, ProcessEvents,(ClientData) 0 );
1024 if (tty) Prompt(theCommands.Interp(), 0);
1025 Prompt(theCommands.Interp(), 0);
1027 outChannel = Tcl_GetStdChannel(TCL_STDOUT);
1029 Tcl_Flush(outChannel);
1031 Tcl_DStringInit(&command);
1034 * Loop infinitely, waiting for commands to execute. When there
1035 * are no windows left, Tk_MainLoop returns and we exit.
1040 if (Draw_VirtualWindows) {
1041 // main window will never shown
1042 // but main loop will parse all Xlib messages
1043 Tcl_Eval(theCommands.Interp(), "wm withdraw .");
1050 Standard_Integer count = ConnectionNumber(Draw_WindowDisplay);
1051 Standard_Integer numfd;
1055 FD_SET(count,&readset);
1057 numfd = select(count+1,(Integer*)&readset,NULL,NULL,NULL);
1059 numfd = select(count+1,&readset,NULL,NULL,NULL);
1061 if (FD_ISSET(0,&readset)) StdinProc((ClientData)0,0);
1062 if (FD_ISSET(count,&readset)) ProcessEvents((ClientData)0,0);
1066 NCollection_List<Draw_Window::FCallbackBeforeTerminate>::Iterator Iter(MyCallbacks);
1067 for(; Iter.More(); Iter.Next())
1073 //======================================================
1074 // funtion : Init_Appli()
1076 //======================================================
1077 Standard_Boolean Init_Appli()
1080 interp = theCommands.Interp();
1086 } catch (Standard_Failure) {
1087 cout <<" Pb au lancement de TK_Init "<<endl;
1090 Tcl_StaticPackage(interp, "Tk", Tk_Init, (Tcl_PackageInitProc *) NULL);
1092 Tk_Window aMainWindow = Tk_MainWindow(interp) ;
1093 if (aMainWindow == NULL) {
1094 #if ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 5)))
1095 fprintf(stderr, "%s\n", Tcl_GetStringResult(interp));
1097 fprintf(stderr, "%s\n", interp->result);
1101 #if defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1102 Tk_SetAppName(aMainWindow, "Draw");
1104 Tk_Name(aMainWindow) = Tk_GetUid(Tk_SetAppName(aMainWindow, "Draw"));
1107 Tk_GeometryRequest (aMainWindow, 200, 200);
1109 #if !defined(__APPLE__) || defined(MACOSX_USE_GLX)
1110 if (Draw_DisplayConnection.IsNull())
1114 Draw_DisplayConnection = new Aspect_DisplayConnection();
1116 catch (Standard_Failure)
1118 std::cout << "Cannot open display. Interpret commands in batch mode." << std::endl;
1119 return Standard_False;
1122 if (Draw_WindowDisplay == NULL)
1124 Draw_WindowDisplay = Draw_DisplayConnection->GetDisplay();
1127 // synchronize the display server : could be done within Tk_Init
1129 XSynchronize(Draw_WindowDisplay, True);
1130 XSetInputFocus(Draw_WindowDisplay,
1132 RevertToPointerRoot,
1135 Draw_WindowScreen = DefaultScreen(Draw_WindowDisplay);
1136 Draw_WindowColorMap = DefaultColormap(Draw_WindowDisplay,
1141 Tcl_SetVar(interp,"tcl_interactive",(char*)(tty ? "1" : "0"), TCL_GLOBAL_ONLY);
1142 // Tcl_SetVar(interp,"tcl_interactive",tty ? "1" : "0", TCL_GLOBAL_ONLY);
1143 return Standard_True;
1146 //======================================================
1147 // funtion : Destroy_Appli()
1149 //======================================================
1150 void Destroy_Appli()
1152 //XCloseDisplay(Draw_WindowDisplay);
1156 *----------------------------------------------------------------------
1160 * This procedure is invoked by the event dispatcher whenever
1161 * standard input becomes readable. It grabs the next line of
1162 * input characters, adds them to a command being assembled, and
1163 * executes the command if it's complete.
1169 * Could be almost arbitrary, depending on the command that's
1172 *----------------------------------------------------------------------
1176 //static void StdinProc(ClientData clientData, int mask)
1177 static void StdinProc(ClientData clientData, int )
1179 static int gotPartial = 0;
1183 Tcl_Channel chan = (Tcl_Channel) clientData;
1185 // MSV Nov 2, 2001: patch for TCL 8.3: initialize line to avoid exception
1186 // when first user input is an empty string
1187 Tcl_DStringFree(&line);
1188 count = Tcl_Gets(chan, &line);
1191 #if ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4)))
1192 Tcl_DString linetmp;
1193 Tcl_DStringInit(&linetmp);
1194 Tcl_UniChar * UniCharString;
1195 UniCharString = Tcl_UtfToUniCharDString(Tcl_DStringValue(&line),-1,&linetmp);
1196 Standard_Integer l = Tcl_UniCharLen(UniCharString);
1197 TCollection_AsciiString AsciiString("");
1198 Standard_Character Character;
1200 for (i=0; i<l; i++) {
1201 Character = UniCharString[i];
1202 AsciiString.AssignCat(Character);
1204 Tcl_DStringInit(&line);
1205 Tcl_DStringAppend(&line, AsciiString.ToCString(), -1);
1212 Tcl_DeleteChannelHandler(chan, StdinProc, (ClientData) chan);
1220 (void) Tcl_DStringAppend(&command, Tcl_DStringValue(&line), -1);
1221 cmd = Tcl_DStringAppend(&command, "\n", -1);
1222 Tcl_DStringFree(&line);
1225 if (!Tcl_CommandComplete(cmd)) {
1232 * Disable the stdin channel handler while evaluating the command;
1233 * otherwise if the command re-enters the event loop we might
1234 * process commands from stdin before the current command is
1235 * finished. Among other things, this will trash the text of the
1236 * command being evaluated.
1239 Tcl_CreateChannelHandler(chan, 0, StdinProc, (ClientData) chan);
1243 * Disable the stdin file handler while evaluating the command;
1244 * otherwise if the command re-enters the event loop we might
1245 * process commands from stdin before the current command is
1246 * finished. Among other things, this will trash the text of the
1247 * command being evaluated.
1251 // Tk_CreateFileHandler(0, 0, StdinProc, (ClientData) 0);
1254 // xab average to avoid an output SIGBUS of DRAW
1255 // to ultimately prescise or remove once
1256 // the problem of free on the global variable at the average
1263 Tcl_CreateChannelHandler(chan, TCL_READABLE, StdinProc,
1265 Tcl_DStringFree(&command);
1272 if (tty) Prompt(interp, gotPartial);
1274 } catch (Standard_Failure) {}
1280 // Source Specifique WNT
1282 /****************************************************\
1285 \****************************************************/
1287 #include "Draw_Window.hxx"
1288 #include "DrawRessource.h"
1291 #include <Draw_Appli.hxx>
1298 // Position of information in the extra memory
1300 // indicates SUBSYSTEM:CONSOLE linker option, to be set to True in main()
1302 Standard_Boolean Draw_IsConsoleSubsystem = Standard_False;
1305 Standard_Boolean Draw_BlackBackGround = Standard_True;
1307 // Creation of color stylos
1308 HPEN colorPenTab[MAXCOLOR] = {CreatePen(PS_SOLID, PENWIDTH, RGB(255,255,255)),
1309 CreatePen(PS_SOLID, PENWIDTH, RGB(255,0,0)),
1310 CreatePen(PS_SOLID, PENWIDTH, RGB(0,255,0)),
1311 CreatePen(PS_SOLID, PENWIDTH, RGB(0,0,255)),
1312 CreatePen(PS_SOLID, PENWIDTH, RGB(0,255,255)),
1313 CreatePen(PS_SOLID, PENWIDTH, RGB(255,215,0)),
1314 CreatePen(PS_SOLID, PENWIDTH, RGB(255,0,255)),
1315 CreatePen(PS_SOLID, PENWIDTH, RGB(255,52,179)),
1316 CreatePen(PS_SOLID, PENWIDTH, RGB(255,165,0)),
1317 CreatePen(PS_SOLID, PENWIDTH, RGB(255,228,225)),
1318 CreatePen(PS_SOLID, PENWIDTH, RGB(255,160,122)),
1319 CreatePen(PS_SOLID, PENWIDTH, RGB(199,21,133)),
1320 CreatePen(PS_SOLID, PENWIDTH, RGB(255,255,0)),
1321 CreatePen(PS_SOLID, PENWIDTH, RGB(240,230,140)),
1322 CreatePen(PS_SOLID, PENWIDTH, RGB(255,127,80))};
1324 // Correspondance mode X11 and WINDOWS NT
1325 int modeTab[16] = {R2_BLACK, R2_MASKPEN, R2_MASKPENNOT, R2_COPYPEN,
1326 R2_MASKNOTPEN, R2_NOP, R2_XORPEN, R2_MERGEPEN,
1327 R2_NOTMASKPEN, R2_NOTXORPEN, R2_NOT, R2_MERGEPENNOT,
1328 R2_NOTCOPYPEN, R2_MERGENOTPEN, R2_NOTMERGEPEN, R2_WHITE};
1330 /*--------------------------------------------------------*\
1331 | CREATE DRAW WINDOW PROCEDURE
1332 \*--------------------------------------------------------*/
1333 HWND DrawWindow::CreateDrawWindow(HWND hWndClient, int nitem)
1335 if (Draw_IsConsoleSubsystem) {
1336 HWND aWin = CreateWindowW (DRAWCLASS, DRAWTITLE,
1337 WS_OVERLAPPEDWINDOW,
1339 NULL, NULL,::GetModuleHandle(NULL), NULL);
1340 if (!Draw_VirtualWindows)
1342 SetWindowPos(aWin, HWND_TOPMOST, 1,1,1,1, SWP_NOMOVE);
1343 SetWindowPos(aWin, HWND_NOTOPMOST, 1,1,1,1, SWP_NOMOVE);
1348 HANDLE hInstance = (HANDLE )GetWindowLongPtrW (hWndClient, GWLP_HINSTANCE);
1350 return CreateMDIWindowW(DRAWCLASS, DRAWTITLE,
1351 WS_CAPTION | WS_CHILD | WS_THICKFRAME,
1353 hWndClient, (HINSTANCE)hInstance, nitem);
1358 /*--------------------------------------------------------*\
1359 | DRAW WINDOW PROCEDURE
1360 \*--------------------------------------------------------*/
1361 LRESULT APIENTRY DrawWindow::DrawProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam )
1363 DrawWindow* localObjet = (DrawWindow* )GetWindowLongPtrW (hWnd, CLIENTWND);
1366 return Draw_IsConsoleSubsystem
1367 ? DefWindowProcW (hWnd, wMsg, wParam, lParam)
1368 : DefMDIChildProcW (hWnd, wMsg, wParam, lParam);
1376 BeginPaint (hWnd, &ps);
1377 if (localObjet->GetUseBuffer())
1379 localObjet->Redraw();
1383 localObjet->WExpose();
1385 EndPaint (hWnd, &ps);
1390 if (localObjet->GetUseBuffer())
1392 localObjet->InitBuffer();
1393 localObjet->WExpose();
1394 localObjet->Redraw();
1400 return Draw_IsConsoleSubsystem
1401 ? DefWindowProcW (hWnd, wMsg, wParam, lParam)
1402 : DefMDIChildProcW (hWnd, wMsg, wParam, lParam);
1408 ** IMPLEMENTATION of the CLASS DRAWWINDOW
1411 /*--------------------------------------------------------*\
1412 | Initialization of static variables of DrawWindow
1413 \*--------------------------------------------------------*/
1415 DrawWindow* DrawWindow::firstWindow = NULL;
1416 HWND DrawWindow::hWndClientMDI = 0;
1418 /*--------------------------------------------------------*\
1419 | Constructors of Draw_Window
1420 \*--------------------------------------------------------*/
1422 // Default Constructor
1423 //________________________
1424 DrawWindow::DrawWindow() :
1429 myUseBuffer(Standard_False)
1431 if (firstWindow) firstWindow->previous = this;
1435 //________________________
1436 DrawWindow::DrawWindow(const char* title,
1437 Standard_Integer X, Standard_Integer Y,
1438 Standard_Integer dX,Standard_Integer dY) :
1439 win(0), next(firstWindow), previous(NULL), myMemHbm(NULL), myUseBuffer(Standard_False)
1441 if (firstWindow) firstWindow->previous = this;
1446 DrawWindow::DrawWindow(const char* title,
1447 Standard_Integer X, Standard_Integer Y,
1448 Standard_Integer dX,Standard_Integer dY,
1450 win(theWin),next(firstWindow), previous(NULL), myMemHbm(NULL), myUseBuffer(Standard_False)
1452 if (firstWindow) firstWindow->previous = this;
1460 /*--------------------------------------------------------*\
1461 | Destructor of DrawWindow
1462 \*--------------------------------------------------------*/
1463 DrawWindow::~DrawWindow()
1466 previous->next = next;
1470 next->previous = previous;
1472 // Delete 'off-screen drawing'-related objects
1474 DeleteObject(myMemHbm);
1481 /*--------------------------------------------------------*\
1483 \*--------------------------------------------------------*/
1484 void DrawWindow::Init(Standard_Integer theXLeft, Standard_Integer theYTop,
1485 Standard_Integer theWidth, Standard_Integer theHeight)
1489 win = CreateDrawWindow(hWndClientMDI, 0);
1492 // include decorations in the window dimensions
1493 // to reproduce same behaviour of Xlib window.
1494 DWORD aWinStyle = GetWindowLongW (win, GWL_STYLE);
1495 DWORD aWinStyleEx = GetWindowLongW (win, GWL_EXSTYLE);
1496 HMENU aMenu = GetMenu (win);
1499 aRect.top = theYTop;
1500 aRect.bottom = theYTop + theHeight;
1501 aRect.left = theXLeft;
1502 aRect.right = theXLeft + theWidth;
1503 AdjustWindowRectEx (&aRect, aWinStyle, aMenu != NULL ? TRUE : FALSE, aWinStyleEx);
1505 SetPosition (aRect.left, aRect.top);
1506 SetDimension (aRect.right - aRect.left, aRect.bottom - aRect.top);
1507 // Save the pointer at the instance associated to the window
1508 SetWindowLongPtrW (win, CLIENTWND, (LONG_PTR)this);
1509 HDC hDC = GetDC(win);
1510 SetBkColor(hDC, RGB(0, 0, 0));
1513 SelectObject(hDC, colorPenTab[myCurrPen]); // Default pencil
1514 SelectObject(hDC, GetStockObject(BLACK_BRUSH));
1515 SetTextColor(hDC, RGB(0,0,255));
1516 ReleaseDC(win, hDC);
1518 if (Draw_VirtualWindows)
1520 // create a virtual window
1521 SetUseBuffer (Standard_True);
1525 /*--------------------------------------------------------*\
1527 \*--------------------------------------------------------*/
1528 void DrawWindow::SetUseBuffer(Standard_Boolean use)
1534 /*--------------------------------------------------------*\
1536 \*--------------------------------------------------------*/
1537 void DrawWindow::InitBuffer()
1541 HDC hDC = GetDC(win);
1542 GetClientRect(win, &rc);
1545 GetObject(myMemHbm, sizeof(BITMAP), &aBmp);
1546 if (rc.right-rc.left == aBmp.bmWidth && rc.bottom-rc.top == aBmp.bmHeight) return;
1547 DeleteObject(myMemHbm);
1549 myMemHbm = (HBITMAP)CreateCompatibleBitmap(hDC,
1552 HDC aMemDC = GetMemDC(hDC);
1553 FillRect(aMemDC, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH));
1554 ReleaseMemDC(aMemDC);
1555 ReleaseDC(win, hDC);
1559 DeleteObject(myMemHbm);
1565 /*--------------------------------------------------------*\
1567 \*--------------------------------------------------------*/
1568 HDC DrawWindow::GetMemDC(HDC theWinDC)
1570 if (!myUseBuffer) return NULL;
1572 HDC aWorkDC = CreateCompatibleDC(theWinDC);
1573 myOldHbm = (HBITMAP)SelectObject(aWorkDC, myMemHbm);
1574 SetROP2(aWorkDC, modeTab[myCurrMode]);
1575 SelectObject(aWorkDC, colorPenTab[myCurrPen]);
1576 SetBkColor(aWorkDC, RGB(0, 0, 0));
1577 SelectObject(aWorkDC, GetStockObject(BLACK_BRUSH));
1578 SetTextColor(aWorkDC, RGB(0,0,255));
1583 /*--------------------------------------------------------*\
1585 \*--------------------------------------------------------*/
1586 void DrawWindow::ReleaseMemDC(HDC theMemDC)
1588 if (!myUseBuffer || !theMemDC) return;
1590 if (myOldHbm) SelectObject(theMemDC, myOldHbm);
1595 /*--------------------------------------------------------*\
1597 \*--------------------------------------------------------*/
1598 void DrawWindow::SetPosition(Standard_Integer posX, Standard_Integer posY)
1600 SetWindowPos(win, 0,
1603 SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
1607 /*--------------------------------------------------------*\
1609 \*--------------------------------------------------------*/
1610 void DrawWindow::SetDimension(Standard_Integer dimX, Standard_Integer dimY)
1612 SetWindowPos(win, 0,
1615 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER);
1619 /*--------------------------------------------------------*\
1621 \*--------------------------------------------------------*/
1622 void DrawWindow::GetPosition(Standard_Integer &dimX,
1623 Standard_Integer &dimY)
1626 GetWindowRect(win, &rect);
1629 point.x = rect.left;
1632 ScreenToClient(hWndClientMDI, &point);
1638 /*--------------------------------------------------------*\
1640 \*--------------------------------------------------------*/
1641 Standard_Integer DrawWindow::HeightWin() const
1644 GetClientRect(win, &rect);
1645 return(rect.bottom-rect.top);
1649 /*--------------------------------------------------------*\
1651 \*--------------------------------------------------------*/
1652 Standard_Integer DrawWindow::WidthWin() const
1655 GetClientRect(win, &rect);
1656 return(rect.right-rect.left);
1660 /*--------------------------------------------------------*\
1662 \*--------------------------------------------------------*/
1663 void DrawWindow::SetTitle (const TCollection_AsciiString& theTitle)
1665 const TCollection_ExtendedString aTitleW (theTitle);
1666 SetWindowTextW (win, aTitleW.ToWideString());
1670 /*--------------------------------------------------------*\
1672 \*--------------------------------------------------------*/
1673 TCollection_AsciiString DrawWindow::GetTitle() const
1675 wchar_t aTitleW[32];
1676 GetWindowTextW (win, aTitleW, 30);
1677 return TCollection_AsciiString (aTitleW);
1681 /*--------------------------------------------------------*\
1683 \*--------------------------------------------------------*/
1684 void DrawWindow::DisplayWindow()
1686 if (Draw_VirtualWindows)
1690 ShowWindow (win, SW_SHOW);
1695 /*--------------------------------------------------------*\
1697 \*--------------------------------------------------------*/
1698 void DrawWindow::Hide()
1700 ShowWindow(win, SW_HIDE);
1704 /*--------------------------------------------------------*\
1706 \*--------------------------------------------------------*/
1707 void DrawWindow::Destroy()
1714 /*--------------------------------------------------------*\
1716 \*--------------------------------------------------------*/
1717 void DrawWindow::Clear()
1719 HDC hDC = GetDC(win);
1720 HDC aWorkDC = myUseBuffer ? GetMemDC(hDC) : hDC;
1723 SelectObject(aWorkDC,GetStockObject(BLACK_PEN));
1724 Rectangle(aWorkDC, 0, 0, WidthWin(), HeightWin());
1725 RestoreDC(aWorkDC,-1);
1727 if (myUseBuffer) ReleaseMemDC(aWorkDC);
1731 /*--------------------------------------------------------*\
1733 \*--------------------------------------------------------*/
1734 static Standard_Boolean SaveBitmap (HBITMAP theHBitmap,
1735 const char* theFileName)
1737 // Get informations about the bitmap
1739 if (GetObject (theHBitmap, sizeof(BITMAP), (LPSTR )&aBitmap) == 0)
1741 return Standard_False;
1744 Image_AlienPixMap anImage;
1745 const Standard_Size aSizeRowBytes = Standard_Size(aBitmap.bmWidth) * 4;
1746 if (!anImage.InitTrash (Image_PixMap::ImgBGR32, Standard_Size(aBitmap.bmWidth), Standard_Size(aBitmap.bmHeight), aSizeRowBytes))
1748 return Standard_False;
1750 anImage.SetTopDown (false);
1753 BITMAPINFOHEADER aBitmapInfo;
1754 memset (&aBitmapInfo, 0, sizeof(BITMAPINFOHEADER));
1755 aBitmapInfo.biSize = sizeof(BITMAPINFOHEADER);
1756 aBitmapInfo.biWidth = aBitmap.bmWidth;
1757 aBitmapInfo.biHeight = aBitmap.bmHeight; // positive means bottom-up!
1758 aBitmapInfo.biPlanes = 1;
1759 aBitmapInfo.biBitCount = 32; // use 32bit for automatic word-alignment per row
1760 aBitmapInfo.biCompression = BI_RGB;
1763 HDC aDC = GetDC (NULL);
1764 Standard_Boolean isSuccess = GetDIBits (aDC, theHBitmap,
1765 0, // first scan line to set
1766 aBitmap.bmHeight, // number of scan lines to copy
1767 anImage.ChangeData(), // array for bitmap bits
1768 (LPBITMAPINFO )&aBitmapInfo, // bitmap data info
1769 DIB_RGB_COLORS) != 0;
1770 ReleaseDC (NULL, aDC);
1771 return isSuccess && anImage.Save (theFileName);
1774 /*--------------------------------------------------------*\
1776 \*--------------------------------------------------------*/
1777 Standard_Boolean DrawWindow::Save (const char* theFileName) const
1781 return SaveBitmap (myMemHbm, theFileName);
1785 GetClientRect (win, &aRect);
1786 int aWidth = aRect.right - aRect.left;
1787 int aHeight = aRect.bottom - aRect.top;
1790 HDC aDstDC = GetDC (NULL);
1791 HDC aSrcDC = GetDC (win); // we copy only client area
1792 HDC aMemDC = CreateCompatibleDC (aDstDC);
1794 // Copy the screen to the bitmap
1795 HBITMAP anHBitmapDump = CreateCompatibleBitmap (aDstDC, aWidth, aHeight);
1796 HBITMAP anHBitmapOld = (HBITMAP )SelectObject (aMemDC, anHBitmapDump);
1797 BitBlt (aMemDC, 0, 0, aWidth, aHeight, aSrcDC, 0, 0, SRCCOPY);
1799 Standard_Boolean isSuccess = SaveBitmap (anHBitmapDump, theFileName);
1802 DeleteObject (SelectObject (aMemDC, anHBitmapOld));
1808 /*--------------------------------------------------------*\
1810 \*--------------------------------------------------------*/
1811 void DrawWindow::DrawString(int x,int y, char* text)
1813 HDC hDC = GetDC(win);
1814 HDC aWorkDC = myUseBuffer ? GetMemDC(hDC) : hDC;
1816 TCollection_ExtendedString textW (text);
1817 TextOutW(aWorkDC, x, y, (const wchar_t*)textW.ToExtString(), (int )strlen(text));
1819 if (myUseBuffer) ReleaseMemDC(aWorkDC);
1823 /*--------------------------------------------------------*\
1825 \*--------------------------------------------------------*/
1826 void DrawWindow::DrawSegments(Segment *tab, int nbElem)
1828 HDC hDC = GetDC(win);
1829 HDC aWorkDC = myUseBuffer ? GetMemDC(hDC) : hDC;
1831 for(int i = 0 ; i < nbElem ; i++)
1833 MoveToEx(aWorkDC, tab[i].x1, tab[i].y1, NULL);
1834 LineTo(aWorkDC, tab[i].x2, tab[i].y2);
1837 if (myUseBuffer) ReleaseMemDC(aWorkDC);
1841 /*--------------------------------------------------------*\
1843 \*--------------------------------------------------------*/
1844 void DrawWindow::Redraw()
1847 HDC hDC = GetDC(win);
1849 GetClientRect(win, &rc);
1850 HDC aMemDC = GetMemDC(hDC);
1853 rc.right-rc.left, rc.bottom-rc.top,
1856 ReleaseMemDC(aMemDC);
1861 /*--------------------------------------------------------*\
1863 \*--------------------------------------------------------*/
1864 void DrawWindow::SetMode(int mode)
1866 HDC hDC = GetDC(win);
1868 SetROP2(hDC, modeTab[mode]);
1873 /*--------------------------------------------------------*\
1875 \*--------------------------------------------------------*/
1876 void DrawWindow::SetColor(Standard_Integer color)
1878 HDC hDC = GetDC(win);
1880 SelectObject(hDC,colorPenTab[color]);
1885 /*--------------------------------------------------------*\
1887 \*--------------------------------------------------------*/
1888 void DrawWindow::WExpose()
1893 /*--------------------------------------------------------*\
1895 \*--------------------------------------------------------*/
1896 void DrawWindow::WButtonPress(const Standard_Integer,
1897 const Standard_Integer,
1898 const Standard_Integer&)
1903 /*--------------------------------------------------------*\
1905 \*--------------------------------------------------------*/
1906 void DrawWindow::WButtonRelease(const Standard_Integer,
1907 const Standard_Integer,
1908 const Standard_Integer&)
1913 /*--------------------------------------------------------*\
1915 \*--------------------------------------------------------*/
1916 void Draw_Window::WMotionNotify(const Standard_Integer ,
1917 const Standard_Integer )
1922 /*--------------------------------------------------------*\
1924 \*--------------------------------------------------------*/
1925 void DrawWindow::WConfigureNotify(const Standard_Integer,
1926 const Standard_Integer,
1927 const Standard_Integer,
1928 const Standard_Integer)
1933 /*--------------------------------------------------------*\
1935 \*--------------------------------------------------------*/
1936 void DrawWindow::WUnmapNotify()
1943 ** IMPLEMENTATION of the CLASS SEGMENT
1946 /*--------------------------------------------------------*\
1948 \*--------------------------------------------------------*/
1950 void Segment::Init(Standard_Integer a1, Standard_Integer a2,
1951 Standard_Integer a3, Standard_Integer a4)
1959 static DWORD WINAPI tkLoop(VOID);
1961 static Tk_Window mainWindow;
1964 //* threads sinchronization *//
1965 DWORD dwMainThreadId;
1966 console_semaphore_value volatile console_semaphore = WAIT_CONSOLE_COMMAND;
1967 #define THE_COMMAND_SIZE 1000 /* Console Command size */
1968 wchar_t console_command[THE_COMMAND_SIZE];
1969 bool volatile isTkLoopStarted = false;
1971 /*--------------------------------------------------------*\
1973 \*--------------------------------------------------------*/
1974 Standard_Boolean Init_Appli(HINSTANCE hInst,
1975 HINSTANCE hPrevInst, int nShow, HWND& hWndFrame )
1979 console_semaphore = STOP_CONSOLE;
1981 interp = theCommands.Interp();
1984 dwMainThreadId = GetCurrentThreadId();
1986 //necessary for normal Tk operation
1987 hThread = CreateThread(NULL, // no security attributes
1988 0, // use default stack size
1989 (LPTHREAD_START_ROUTINE) tkLoop, // thread function
1990 NULL, // no thread function argument
1991 0, // use default creation flags
1994 cout << "Tcl/Tk main loop thread not created. Switching to batch mode..." << endl;
1999 } catch (Standard_Failure) {
2000 cout <<" Pb au lancement de TK_Init "<<endl;
2003 Tcl_StaticPackage(interp, "Tk", Tk_Init, (Tcl_PackageInitProc *) NULL);
2005 //since the main Tcl/Tk loop wasn't created --> switch to batch mode
2006 return Standard_False;
2009 // san - 06/08/2002 - Time for tkLoop to start; Tk fails to initialize otherwise
2010 while (!isTkLoopStarted)
2013 // Saving of window classes
2015 if(!RegisterAppClass(hInst))
2016 return(Standard_False);
2019 ** Enter the application message-polling loop. This is the anchor for
2022 hWndFrame = !Draw_IsConsoleSubsystem ? CreateAppWindow (hInst) : NULL;
2023 if (hWndFrame != NULL)
2025 ShowWindow(hWndFrame,nShow);
2026 UpdateWindow(hWndFrame);
2029 return Standard_True;
2032 Standard_Boolean Draw_Interprete (const char*);
2034 /*--------------------------------------------------------*\
2035 | readStdinThreadFunc
2036 \*--------------------------------------------------------*/
2037 static DWORD WINAPI readStdinThreadFunc()
2039 if (!Draw_IsConsoleSubsystem)
2044 // Console locale could be set to the system codepage .OCP (UTF-8 is not properly supported on Windows).
2045 // However, to use it, we have to care using std::wcerr/fwprintf/WriteConsoleW for non-ascii strings everywhere (including Tcl itself),
2046 // or otherwise we can have incomplete output issues
2047 // (e.g. UNICODE string will be NOT just corrupted as in case when we don't set setlocale()
2048 // but will break further normal output to console due to special characters being accidentally handled by console in the wrong way).
2049 //setlocale (LC_ALL, ".OCP");
2051 // _O_U16TEXT can be used with fgetws() to get similar result as ReadConsoleW() without affecting setlocale(),
2052 // however it would break pipe input
2053 //_setmode (_fileno(stdin), _O_U16TEXT);
2055 bool isConsoleInput = true;
2058 while (console_semaphore != WAIT_CONSOLE_COMMAND)
2063 const HANDLE anStdIn = ::GetStdHandle (STD_INPUT_HANDLE);
2065 && anStdIn != INVALID_HANDLE_VALUE
2069 if (ReadConsoleW (anStdIn, console_command, THE_COMMAND_SIZE, &aNbRead, NULL))
2071 console_command[aNbRead] = L'\0';
2072 console_semaphore = HAS_CONSOLE_COMMAND;
2077 const DWORD anErr = GetLastError();
2078 if (anErr != ERROR_SUCCESS)
2080 // fallback using fgetws() which would work with pipes
2081 // but supports Unicode only through multi-byte encoding (which is not UTF-8)
2082 isConsoleInput = false;
2088 // fgetws() works only for characters within active locale (see setlocale())
2089 if (fgetws (console_command, THE_COMMAND_SIZE, stdin))
2091 console_semaphore = HAS_CONSOLE_COMMAND;
2096 /*--------------------------------------------------------*\
2097 | exitProc: finalization handler for Tcl/Tk thread. Forces parent process to die
2098 \*--------------------------------------------------------*/
2099 void exitProc(ClientData /*dc*/)
2101 NCollection_List<Draw_Window::FCallbackBeforeTerminate>::Iterator Iter(MyCallbacks);
2102 for(; Iter.More(); Iter.Next())
2106 HANDLE proc = GetCurrentProcess();
2107 TerminateProcess(proc, 0);
2110 /*--------------------------------------------------------*\
2111 | tkLoop: implements Tk_Main()-like behaviour in a separate thread
2112 \*--------------------------------------------------------*/
2113 static DWORD WINAPI tkLoop(VOID)
2115 Tcl_CreateExitHandler(exitProc, 0);
2116 #if (TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 5))
2118 Tcl_Channel aChannelIn = Tcl_GetStdChannel (TCL_STDIN);
2119 Tcl_Channel aChannelOut = Tcl_GetStdChannel (TCL_STDOUT);
2120 Tcl_Channel aChannelErr = Tcl_GetStdChannel (TCL_STDERR);
2121 if (aChannelIn != NULL)
2123 Tcl_RegisterChannel (theCommands.Interp(), aChannelIn);
2125 if (aChannelOut != NULL)
2127 Tcl_RegisterChannel (theCommands.Interp(), aChannelOut);
2129 if (aChannelErr != NULL)
2131 Tcl_RegisterChannel (theCommands.Interp(), aChannelErr);
2137 // initialize the Tk library if not in 'virtual windows' mode
2138 // (virtual windows are created by OCCT with native APIs,
2139 // thus Tk will be useless)
2140 if (!Draw_VirtualWindows)
2145 Standard_Integer res = Tk_Init (interp);
2148 #if ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 5)))
2149 cout << "tkLoop: error in Tk initialization. Tcl reported: " << Tcl_GetStringResult(interp) << endl;
2151 cout << "tkLoop: error in Tk initialization. Tcl reported: " << interp->result << endl;
2155 catch (Standard_Failure)
2157 cout << "tkLoop: exception in TK_Init\n";
2159 Tcl_StaticPackage (interp, "Tk", Tk_Init, (Tcl_PackageInitProc* ) NULL);
2160 mainWindow = Tk_MainWindow (interp);
2161 if (mainWindow == NULL)
2163 #if ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 5)))
2164 fprintf (stderr, "%s\n", Tcl_GetStringResult(interp));
2166 fprintf (stderr, "%s\n", interp->result);
2168 cout << "tkLoop: Tk_MainWindow() returned NULL. Exiting...\n";
2171 Tk_Name(mainWindow) = Tk_GetUid (Tk_SetAppName (mainWindow, "Draw"));
2175 // set signal handler in the new thread
2176 OSD::SetSignal(Standard_False);
2178 // inform the others that we have started
2179 isTkLoopStarted = true;
2181 while (console_semaphore == STOP_CONSOLE)
2182 Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT);
2184 if (Draw_IsConsoleSubsystem && console_semaphore == WAIT_CONSOLE_COMMAND)
2188 Standard_Boolean toLoop = Standard_True;
2191 while(Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT));
2192 if (console_semaphore == HAS_CONSOLE_COMMAND)
2194 TCollection_AsciiString aCmdUtf8 (console_command);
2195 if (Draw_Interprete (aCmdUtf8.ToCString()))
2197 if (Draw_IsConsoleSubsystem) Prompt (interp, 0);
2201 if (Draw_IsConsoleSubsystem) Prompt (interp, 1);
2203 console_semaphore = WAIT_CONSOLE_COMMAND;
2210 // We should not exit until the Main Tk window is closed
2211 toLoop = (Tk_GetNumMainWindows() > 0) || Draw_VirtualWindows;
2219 /*--------------------------------------------------------*\
2221 \*--------------------------------------------------------*/
2222 void Run_Appli(HWND hWnd)
2225 HACCEL hAccel = NULL;
2229 // if (!(hAccel = LoadAccelerators (hInstance, MAKEINTRESOURCE(ACCEL_ID))))
2230 // MessageBox(hWnd, "MDI: Load Accel failure!", "Error", MB_OK);
2233 if (Draw_IsConsoleSubsystem) {
2234 hThread = CreateThread(NULL, // no security attributes
2235 0, // use default stack size
2236 (LPTHREAD_START_ROUTINE) readStdinThreadFunc, // thread function
2237 NULL, // no thread function argument
2238 0, // use default creation flags
2239 &IDThread); // returns thread identifier
2241 cout << "pb in creation of the thread reading stdin" << endl;
2242 Draw_IsConsoleSubsystem = Standard_False;
2243 Init_Appli (GetModuleHandleW (NULL),
2244 GetModuleHandleW (NULL),
2245 1, hWnd); // reinit => create MDI client wnd
2249 //turn on the command interpretation mechanism (regardless of the mode)
2250 if (console_semaphore == STOP_CONSOLE)
2251 console_semaphore = WAIT_CONSOLE_COMMAND;
2253 //simple Win32 message loop
2254 while (GetMessageW (&msg, NULL, 0, 0) > 0)
2256 if (!TranslateAcceleratorW (hWnd, hAccel, &msg))
2258 TranslateMessage (&msg);
2259 DispatchMessageW (&msg);
2266 /*--------------------------------------------------------*\
2268 \*--------------------------------------------------------*/
2269 void Destroy_Appli(HINSTANCE hInst)
2271 UnregisterAppClass(hInst);
2272 for (int i = 0 ; i < MAXCOLOR ; i++)
2273 DeleteObject(colorPenTab[i]);
2276 /*--------------------------------------------------------*\
2278 \*--------------------------------------------------------*/
2279 void DrawWindow::SelectWait(HANDLE& hWnd, int& x, int& y, int& button)
2285 GetMessageW (&msg, NULL, 0, 0);
2286 while((msg.message != WM_RBUTTONDOWN && msg.message != WM_LBUTTONDOWN) ||
2287 ! ( Draw_IsConsoleSubsystem || IsChild(DrawWindow::hWndClientMDI,msg.hwnd)) )
2289 GetMessageW (&msg, NULL, 0, 0);
2293 x = LOWORD(msg.lParam);
2294 y = HIWORD(msg.lParam);
2295 if (msg.message == WM_LBUTTONDOWN)
2301 /*--------------------------------------------------------*\
2303 \*--------------------------------------------------------*/
2304 void DrawWindow::SelectNoWait(HANDLE& hWnd, int& x, int& y, int& button)
2310 GetMessageW (&msg,NULL,0,0);
2311 while((msg.message != WM_RBUTTONDOWN && msg.message != WM_LBUTTONDOWN &&
2312 msg.message != WM_MOUSEMOVE) ||
2313 ! ( Draw_IsConsoleSubsystem || IsChild(DrawWindow::hWndClientMDI,msg.hwnd) ) )
2315 GetMessageW(&msg,NULL,0,0);
2318 x = LOWORD(msg.lParam);
2319 y = HIWORD(msg.lParam);
2320 switch (msg.message)
2322 case WM_LBUTTONDOWN :
2326 case WM_RBUTTONDOWN :
2336 Standard_Boolean DrawWindow::DefineColor (const Standard_Integer, const char*)
2338 return Standard_True;