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