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