mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-04 18:06:22 +03:00
2504 lines
73 KiB
C++
2504 lines
73 KiB
C++
// Created on: 1994-07-27
|
|
// Created by: Remi LEQUETTE
|
|
// Copyright (c) 1994-1999 Matra Datavision
|
|
// Copyright (c) 1999-2014 OPEN CASCADE SAS
|
|
//
|
|
// This file is part of Open CASCADE Technology software library.
|
|
//
|
|
// This library is free software; you can redistribute it and/or modify it under
|
|
// the terms of the GNU Lesser General Public License version 2.1 as published
|
|
// by the Free Software Foundation, with special exception defined in the file
|
|
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
|
// distribution for complete text of the license and disclaimer of any warranty.
|
|
//
|
|
// Alternatively, this file may be used under the terms of Open CASCADE
|
|
// commercial license or contractual agreement.
|
|
|
|
// include windows.h first to have all definitions available
|
|
#ifdef _WIN32
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
#include <Standard_ErrorHandler.hxx>
|
|
|
|
#include <tcl.h>
|
|
#include <Draw_Interpretor.hxx>
|
|
#include <Draw_Window.hxx>
|
|
#include <Draw_Appli.hxx>
|
|
#include <TCollection_AsciiString.hxx>
|
|
#include <TCollection_ExtendedString.hxx>
|
|
#include <Image_AlienPixMap.hxx>
|
|
#include <NCollection_List.hxx>
|
|
|
|
extern Standard_Boolean Draw_Batch;
|
|
extern Standard_Boolean Draw_VirtualWindows;
|
|
static NCollection_List<Draw_Window::FCallbackBeforeTerminate> MyCallbacks;
|
|
|
|
void Draw_Window::AddCallbackBeforeTerminate(FCallbackBeforeTerminate theCB)
|
|
{
|
|
MyCallbacks.Append(theCB);
|
|
}
|
|
|
|
void Draw_Window::RemoveCallbackBeforeTerminate(FCallbackBeforeTerminate theCB)
|
|
{
|
|
NCollection_List<Draw_Window::FCallbackBeforeTerminate>::Iterator Iter(MyCallbacks);
|
|
for(; Iter.More(); Iter.Next())
|
|
{
|
|
if (Iter.Value() == theCB)
|
|
{
|
|
MyCallbacks.Remove(Iter);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
*----------------------------------------------------------------------
|
|
*
|
|
* Prompt --
|
|
*
|
|
* Issue a prompt on standard output, or invoke a script
|
|
* to issue the prompt.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* A prompt gets output, and a Tcl script may be evaluated
|
|
* in interp.
|
|
*
|
|
*----------------------------------------------------------------------
|
|
*/
|
|
|
|
static void Prompt(Tcl_Interp *Interp, int partial)
|
|
{
|
|
Tcl_Channel errChannel;
|
|
Tcl_Channel outChannel = Tcl_GetStdChannel(TCL_STDOUT);
|
|
const char* promptCmd = Tcl_GetVar (Interp, partial ? "tcl_prompt2" : "tcl_prompt1", TCL_GLOBAL_ONLY);
|
|
if (promptCmd == NULL) {
|
|
defaultPrompt:
|
|
if (!partial && outChannel) {
|
|
Tcl_Write(outChannel, "% ", 2);
|
|
}
|
|
} else {
|
|
int code = Tcl_Eval(Interp, promptCmd);
|
|
outChannel = Tcl_GetStdChannel(TCL_STDOUT);
|
|
errChannel = Tcl_GetStdChannel(TCL_STDERR);
|
|
if (code != TCL_OK) {
|
|
if (errChannel) {
|
|
#if ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 5)))
|
|
Tcl_Write(errChannel, Tcl_GetStringResult(Interp), -1);
|
|
#else
|
|
Tcl_Write(errChannel, Interp->result, -1);
|
|
#endif
|
|
Tcl_Write(errChannel, "\n", 1);
|
|
}
|
|
Tcl_AddErrorInfo(Interp,
|
|
"\n (script that generates prompt)");
|
|
goto defaultPrompt;
|
|
}
|
|
}
|
|
if (outChannel) {
|
|
Tcl_Flush(outChannel);
|
|
}
|
|
}
|
|
|
|
#if !defined(_WIN32) && !defined(__WIN32__)
|
|
|
|
#include <OSD_Timer.hxx>
|
|
#include <Draw_Window.hxx>
|
|
#include <unistd.h>
|
|
|
|
#if defined(__APPLE__) && !defined(MACOSX_USE_GLX)
|
|
// use forward declaration for small subset of used Tk functions
|
|
// to workaround broken standard Tk framework installation within OS X SDKs
|
|
// which *HAS* X11 headers in Tk.framework but doesn't install them appropriately
|
|
#define _TK
|
|
typedef struct Tk_Window_* Tk_Window;
|
|
typedef const char* Tk_Uid;
|
|
|
|
extern "C" int Tk_Init (Tcl_Interp* interp);
|
|
extern "C" void Tk_MainLoop();
|
|
extern "C" Tk_Window Tk_MainWindow (Tcl_Interp* interp) ;
|
|
extern "C" Tk_Uid Tk_GetUid (const char* str);
|
|
extern "C" const char* Tk_SetAppName (Tk_Window tkwin, const char* name) ;
|
|
extern "C" void Tk_GeometryRequest (Tk_Window tkwin, int reqWidth, int reqHeight);
|
|
|
|
#else
|
|
#include <tk.h>
|
|
#endif
|
|
|
|
/*
|
|
* Global variables used by the main program:
|
|
*/
|
|
|
|
char *tcl_RcFileName = NULL; /* Name of a user-specific startup script
|
|
* to source if the application is being run
|
|
* interactively (e.g. "~/.wishrc"). Set
|
|
* by Tcl_AppInit. NULL means don't source
|
|
* anything ever. */
|
|
|
|
static Tcl_DString command; /* Used to assemble lines of terminal input
|
|
* into Tcl commands. */
|
|
static Tcl_DString line; /* Used to read the next line from the
|
|
* terminal input. */
|
|
//static char errorExitCmd[] = "exit 1";
|
|
|
|
/*
|
|
* Forward declarations for procedures defined later in this file:
|
|
*/
|
|
|
|
static void StdinProc (ClientData clientData, int mask);
|
|
|
|
static void Prompt (Tcl_Interp *Interp, int partial);
|
|
|
|
static Standard_Boolean tty; /* Non-zero means standard input is a
|
|
* terminal-like device. Zero means it's
|
|
* a file. */
|
|
|
|
Standard_Integer Draw_WindowScreen = 0;
|
|
Standard_Boolean Draw_BlackBackGround = Standard_True;
|
|
|
|
|
|
// Initialization of static variables of Draw_Window
|
|
//======================================================
|
|
Draw_Window* Draw_Window::firstWindow = NULL;
|
|
|
|
// X11 specific part
|
|
#if !defined(__APPLE__) || defined(MACOSX_USE_GLX)
|
|
#include <X11/Xutil.h>
|
|
#include <Aspect_DisplayConnection.hxx>
|
|
|
|
static unsigned long thePixels[MAXCOLOR];
|
|
|
|
Display* Draw_WindowDisplay = NULL;
|
|
Colormap Draw_WindowColorMap;
|
|
static Handle(Aspect_DisplayConnection) Draw_DisplayConnection;
|
|
|
|
// Base_Window struct definition
|
|
//===================================
|
|
struct Base_Window
|
|
{
|
|
GC gc;
|
|
XSetWindowAttributes xswa;
|
|
};
|
|
|
|
//=======================================================================
|
|
//function : Draw_Window
|
|
//purpose :
|
|
//=======================================================================
|
|
Draw_Window::Draw_Window() :
|
|
base(*new Base_Window()),
|
|
win(0),
|
|
myBuffer(0),
|
|
next(firstWindow),
|
|
previous(NULL),
|
|
myUseBuffer(Standard_False),
|
|
withWindowManager(Standard_True)
|
|
{
|
|
myMother = RootWindow(Draw_WindowDisplay,
|
|
Draw_WindowScreen);
|
|
|
|
if (firstWindow) firstWindow->previous = this;
|
|
firstWindow = this;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Draw_Window
|
|
//purpose :
|
|
//=======================================================================
|
|
Draw_Window::Draw_Window(Window mother) :
|
|
base(*new Base_Window()),
|
|
win(0),
|
|
myBuffer(0),
|
|
next(firstWindow),
|
|
previous(NULL),
|
|
myUseBuffer(Standard_False),
|
|
withWindowManager(Standard_True)
|
|
{
|
|
myMother = mother;
|
|
|
|
if (firstWindow) firstWindow->previous = this;
|
|
firstWindow = this;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Draw_Window
|
|
//purpose :
|
|
//=======================================================================
|
|
Draw_Window::Draw_Window (const char* title,
|
|
Standard_Integer X, Standard_Integer Y,
|
|
Standard_Integer DX, Standard_Integer DY) :
|
|
base(*new Base_Window()),
|
|
win(0),
|
|
myBuffer(0),
|
|
next(firstWindow),
|
|
previous(NULL),
|
|
myUseBuffer(Standard_False),
|
|
withWindowManager(Standard_True)
|
|
{
|
|
myMother = RootWindow(Draw_WindowDisplay,
|
|
Draw_WindowScreen);
|
|
|
|
if (firstWindow) firstWindow->previous = this;
|
|
firstWindow = this;
|
|
Init(X,Y,DX,DY);
|
|
SetTitle(title);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Draw_Window
|
|
//purpose :
|
|
//=======================================================================
|
|
Draw_Window::Draw_Window (const char* window ) :
|
|
base(*new Base_Window()),
|
|
win(0),
|
|
myBuffer(0),
|
|
next(firstWindow),
|
|
previous(NULL),
|
|
myUseBuffer(Standard_False),
|
|
withWindowManager(Standard_True)
|
|
{
|
|
sscanf(window,"%lx",&win);
|
|
Standard_Integer X,Y,DX,DY;
|
|
|
|
if (firstWindow) firstWindow->previous = this;
|
|
firstWindow = this;
|
|
GetPosition(X,Y);
|
|
DX=HeightWin();
|
|
DY=WidthWin();
|
|
|
|
Init(X,Y,DX,DY);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Draw_Window
|
|
//purpose :
|
|
//=======================================================================
|
|
Draw_Window::Draw_Window (Window mother,
|
|
char* title,
|
|
Standard_Integer X, Standard_Integer Y,
|
|
Standard_Integer DX, Standard_Integer DY) :
|
|
base(*new Base_Window()),
|
|
win(0),
|
|
myBuffer(0),
|
|
next(firstWindow),
|
|
previous(NULL),
|
|
myUseBuffer(Standard_False),
|
|
withWindowManager(Standard_True)
|
|
{
|
|
myMother = mother;
|
|
|
|
if (firstWindow) firstWindow->previous = this;
|
|
firstWindow = this;
|
|
Init(X,Y,DX,DY);
|
|
SetTitle(title);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : ~Draw_Window
|
|
//purpose :
|
|
//=======================================================================
|
|
Draw_Window::~Draw_Window()
|
|
{
|
|
if (previous)
|
|
previous->next = next;
|
|
else
|
|
firstWindow = next;
|
|
if (next)
|
|
next->previous = previous;
|
|
|
|
if (myBuffer != 0)
|
|
{
|
|
XFreePixmap(Draw_WindowDisplay, myBuffer);
|
|
myBuffer = 0;
|
|
}
|
|
// Liberation pointer on Base_Window
|
|
delete &base;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Init
|
|
//purpose :
|
|
//=======================================================================
|
|
void Draw_Window::Init(Standard_Integer X, Standard_Integer Y,
|
|
Standard_Integer DX, Standard_Integer DY)
|
|
{
|
|
unsigned long setmask;
|
|
|
|
if (Draw_BlackBackGround)
|
|
{
|
|
base.xswa.background_pixel = BlackPixel(Draw_WindowDisplay,Draw_WindowScreen);
|
|
base.xswa.border_pixel = WhitePixel(Draw_WindowDisplay,Draw_WindowScreen);
|
|
}
|
|
else
|
|
{
|
|
base.xswa.background_pixel = WhitePixel(Draw_WindowDisplay,Draw_WindowScreen);
|
|
base.xswa.border_pixel = BlackPixel(Draw_WindowDisplay,Draw_WindowScreen);
|
|
}
|
|
base.xswa.colormap = Draw_WindowColorMap;
|
|
setmask = CWBackPixel | CWBorderPixel ;
|
|
|
|
XSizeHints myHints;
|
|
myHints.flags = USPosition;
|
|
myHints.x = (int) X;
|
|
myHints.y = (int) Y;
|
|
|
|
if (win == 0)
|
|
{
|
|
win = XCreateWindow(Draw_WindowDisplay,
|
|
myMother,
|
|
(int) X,(int) Y,
|
|
(unsigned int) DX,(unsigned int) DY,
|
|
5,
|
|
DefaultDepth(Draw_WindowDisplay,Draw_WindowScreen),
|
|
InputOutput,
|
|
DefaultVisual(Draw_WindowDisplay,Draw_WindowScreen),
|
|
setmask,&base.xswa);
|
|
XSelectInput(Draw_WindowDisplay, win, ButtonPressMask|ExposureMask|
|
|
StructureNotifyMask);
|
|
|
|
// advise to the window manager to place it where I need
|
|
XSetWMNormalHints(Draw_WindowDisplay,win,&myHints);
|
|
|
|
Atom aDeleteWindowAtom = Draw_DisplayConnection->GetAtom (Aspect_XA_DELETE_WINDOW);
|
|
XSetWMProtocols (Draw_WindowDisplay, win, &aDeleteWindowAtom, 1);
|
|
|
|
if (Draw_VirtualWindows)
|
|
{
|
|
myUseBuffer = Standard_True;
|
|
InitBuffer();
|
|
}
|
|
}
|
|
|
|
base.gc = XCreateGC(Draw_WindowDisplay, win, 0, NULL);
|
|
|
|
XSetPlaneMask(Draw_WindowDisplay,base.gc,AllPlanes);
|
|
XSetForeground(Draw_WindowDisplay,
|
|
base.gc, WhitePixel(Draw_WindowDisplay,Draw_WindowScreen));
|
|
XSetBackground(Draw_WindowDisplay,
|
|
base.gc, BlackPixel(Draw_WindowDisplay,Draw_WindowScreen));
|
|
// save in case of window recovery
|
|
|
|
base.xswa.backing_store = Always;
|
|
XChangeWindowAttributes(Draw_WindowDisplay, win,
|
|
CWBackingStore, &base.xswa);
|
|
|
|
XSetLineAttributes (Draw_WindowDisplay, base.gc,
|
|
0, LineSolid, CapButt, JoinMiter);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : InitBuffer
|
|
//purpose :
|
|
//=======================================================================
|
|
void Draw_Window::InitBuffer()
|
|
{
|
|
if (myUseBuffer) {
|
|
if (myBuffer != 0) {
|
|
XFreePixmap (Draw_WindowDisplay, myBuffer);
|
|
}
|
|
XWindowAttributes winAttr;
|
|
XGetWindowAttributes (Draw_WindowDisplay, win, &winAttr);
|
|
myBuffer = XCreatePixmap (Draw_WindowDisplay, win, winAttr.width, winAttr.height, winAttr.depth);
|
|
}
|
|
else if (myBuffer != 0)
|
|
{
|
|
XFreePixmap (Draw_WindowDisplay, myBuffer);
|
|
myBuffer = 0;
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : StopWinManager
|
|
//purpose :
|
|
//=======================================================================
|
|
void Draw_Window::StopWinManager()
|
|
{
|
|
// XGCValues winGc;
|
|
XWindowAttributes winAttr;
|
|
XGetWindowAttributes (Draw_WindowDisplay, win, &winAttr);
|
|
Destroy();
|
|
|
|
XSizeHints myHints;
|
|
myHints.flags = USPosition;
|
|
myHints.x = (int) 30;
|
|
myHints.y = (int) 100;
|
|
|
|
base.xswa.override_redirect = 1;
|
|
base.xswa.border_pixel = BlackPixel(Draw_WindowDisplay,
|
|
Draw_WindowScreen);
|
|
base.xswa.background_pixel = WhitePixel(Draw_WindowDisplay,
|
|
Draw_WindowScreen);
|
|
|
|
withWindowManager = Standard_False;
|
|
|
|
win = XCreateWindow(Draw_WindowDisplay, myMother,
|
|
winAttr.x, winAttr.y,
|
|
winAttr.width, winAttr.height,
|
|
2,
|
|
CopyFromParent, InputOutput, CopyFromParent,
|
|
CWBorderPixel|CWOverrideRedirect|CWBackPixel, &base.xswa);
|
|
|
|
|
|
// adwise to the window manager to place it where I wish
|
|
XSetWMNormalHints(Draw_WindowDisplay,win,&myHints);
|
|
|
|
// all masks of the old window are reassigned to the new one.
|
|
XSelectInput(Draw_WindowDisplay,win,winAttr.your_event_mask);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : SetPosition
|
|
//purpose :
|
|
//=======================================================================
|
|
void Draw_Window::SetPosition(Standard_Integer NewXpos,
|
|
Standard_Integer NewYpos)
|
|
{
|
|
Standard_Integer x,y;
|
|
GetPosition(x, y);
|
|
|
|
if ( (x != NewXpos) || (y != NewYpos) )
|
|
XMoveWindow(Draw_WindowDisplay, win, NewXpos, NewYpos);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : SetDimension
|
|
//purpose :
|
|
//=======================================================================
|
|
void Draw_Window::SetDimension(Standard_Integer NewDx,
|
|
Standard_Integer NewDy)
|
|
{
|
|
if ( (NewDx != WidthWin() ) || (NewDy != HeightWin() ) )
|
|
XResizeWindow(Draw_WindowDisplay, win, NewDx, NewDy);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : GetPosition
|
|
//purpose :
|
|
//=======================================================================
|
|
void Draw_Window::GetPosition(Standard_Integer &PosX,
|
|
Standard_Integer &PosY)
|
|
{
|
|
XWindowAttributes winAttr;
|
|
XGetWindowAttributes(Draw_WindowDisplay, win, &winAttr);
|
|
|
|
PosX = winAttr.x;
|
|
PosY = winAttr.y;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : HeightWin
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Integer Draw_Window::HeightWin() const
|
|
{
|
|
Standard_Integer DY;
|
|
XWindowAttributes winAttr;
|
|
XGetWindowAttributes(Draw_WindowDisplay, win, &winAttr);
|
|
|
|
DY = winAttr.height;
|
|
return DY;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : WidthWin
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Integer Draw_Window::WidthWin() const
|
|
{
|
|
Standard_Integer DX;
|
|
XWindowAttributes winAttr;
|
|
XGetWindowAttributes(Draw_WindowDisplay, win, &winAttr);
|
|
|
|
DX = winAttr.width;
|
|
return DX;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : SetTitle
|
|
//purpose :
|
|
//=======================================================================
|
|
void Draw_Window::SetTitle(const TCollection_AsciiString& theTitle)
|
|
{
|
|
XStoreName (Draw_WindowDisplay, win, theTitle.ToCString());
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : GetTitle
|
|
//purpose :
|
|
//=======================================================================
|
|
TCollection_AsciiString Draw_Window::GetTitle() const
|
|
{
|
|
char* aTitle = NULL;
|
|
XFetchName (Draw_WindowDisplay, win, &aTitle);
|
|
return TCollection_AsciiString (aTitle);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : GetDrawable
|
|
//purpose :
|
|
//=======================================================================
|
|
Drawable Draw_Window::GetDrawable() const
|
|
{
|
|
return myUseBuffer ? myBuffer : win;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function :DefineColor
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Boolean Draw_Window::DefineColor(const Standard_Integer i, const char* colorName)
|
|
{
|
|
XColor color;
|
|
|
|
if (!XParseColor(Draw_WindowDisplay,Draw_WindowColorMap,colorName,&color))
|
|
return Standard_False;
|
|
if (!XAllocColor(Draw_WindowDisplay,Draw_WindowColorMap,&color))
|
|
return Standard_False;
|
|
thePixels[i % MAXCOLOR] = color.pixel;
|
|
return Standard_True;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : IsMapped
|
|
//purpose :
|
|
//=======================================================================
|
|
bool Draw_Window::IsMapped() const
|
|
{
|
|
if (Draw_VirtualWindows
|
|
|| win == 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
XFlush (Draw_WindowDisplay);
|
|
XWindowAttributes aWinAttr;
|
|
XGetWindowAttributes (Draw_WindowDisplay, win, &aWinAttr);
|
|
return aWinAttr.map_state == IsUnviewable
|
|
|| aWinAttr.map_state == IsViewable;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : DisplayWindow
|
|
//purpose :
|
|
//=======================================================================
|
|
void Draw_Window::DisplayWindow()
|
|
{
|
|
if (Draw_VirtualWindows)
|
|
{
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
XMapRaised(Draw_WindowDisplay, win);
|
|
}
|
|
XFlush(Draw_WindowDisplay);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Hide
|
|
//purpose :
|
|
//=======================================================================
|
|
void Draw_Window::Hide()
|
|
{
|
|
XUnmapWindow(Draw_WindowDisplay, win);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Destroy
|
|
//purpose :
|
|
//=======================================================================
|
|
void Draw_Window::Destroy()
|
|
{
|
|
XFreeGC (Draw_WindowDisplay, base.gc);
|
|
XDestroyWindow(Draw_WindowDisplay, win);
|
|
win = 0;
|
|
if (myBuffer != 0)
|
|
{
|
|
XFreePixmap(Draw_WindowDisplay, myBuffer);
|
|
myBuffer = 0;
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Clear
|
|
//purpose :
|
|
//=======================================================================
|
|
void Draw_Window::Clear()
|
|
{
|
|
if (myUseBuffer)
|
|
{
|
|
// XClearArea only applicable for windows
|
|
XGCValues currValues;
|
|
XGetGCValues(Draw_WindowDisplay, base.gc, GCBackground | GCForeground, &currValues);
|
|
XSetForeground(Draw_WindowDisplay, base.gc, currValues.background);
|
|
XFillRectangle(Draw_WindowDisplay, myBuffer, base.gc, 0, 0, WidthWin(), HeightWin());
|
|
XSetForeground(Draw_WindowDisplay, base.gc, currValues.foreground);
|
|
}
|
|
else
|
|
{
|
|
XClearArea(Draw_WindowDisplay, win, 0, 0, 0, 0, False);
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Flush
|
|
//purpose :
|
|
//=======================================================================
|
|
void Draw_Window::Flush()
|
|
{
|
|
XFlush(Draw_WindowDisplay);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : DrawString
|
|
//purpose :
|
|
//=======================================================================
|
|
void Draw_Window::DrawString(int X, int Y, char *text)
|
|
{
|
|
XDrawString(Draw_WindowDisplay, GetDrawable(), base.gc, X, Y, text, strlen(text));
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : DrawSegments
|
|
//purpose :
|
|
//=======================================================================
|
|
void Draw_Window::DrawSegments(Segment *tab, int nbElem)
|
|
{
|
|
XDrawSegments(Draw_WindowDisplay, GetDrawable(), base.gc, (XSegment*) tab, nbElem);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Redraw
|
|
//purpose :
|
|
//=======================================================================
|
|
void Draw_Window::Redraw()
|
|
{
|
|
if (myUseBuffer) {
|
|
XCopyArea (Draw_WindowDisplay,
|
|
myBuffer, win, // source, destination Drawables
|
|
base.gc,
|
|
0, 0, // source x, y
|
|
WidthWin(), HeightWin(),
|
|
0, 0); // destination x, y
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : SetColor
|
|
//purpose :
|
|
//=======================================================================
|
|
void Draw_Window::SetColor(Standard_Integer color)
|
|
{
|
|
XSetForeground(Draw_WindowDisplay, base.gc, thePixels[color]);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : SetMode
|
|
//purpose :
|
|
//=======================================================================
|
|
void Draw_Window::SetMode( int mode)
|
|
{
|
|
XSetFunction(Draw_WindowDisplay, base.gc, mode);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Save
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Boolean Draw_Window::Save (const char* theFileName) const
|
|
{
|
|
// make sure all draw operations done
|
|
XSync (Draw_WindowDisplay, True);
|
|
|
|
// the attributes
|
|
XWindowAttributes winAttr;
|
|
XGetWindowAttributes (Draw_WindowDisplay, win, &winAttr);
|
|
|
|
if (!myUseBuffer)
|
|
{
|
|
// make sure that the whole window fit on display to prevent BadMatch error
|
|
XWindowAttributes winAttrRoot;
|
|
XGetWindowAttributes (Draw_WindowDisplay, XRootWindowOfScreen (winAttr.screen), &winAttrRoot);
|
|
|
|
Window winChildDummy;
|
|
int winLeft = 0;
|
|
int winTop = 0;
|
|
XTranslateCoordinates (Draw_WindowDisplay, win, XRootWindowOfScreen (winAttr.screen),
|
|
0, 0, &winLeft, &winTop, &winChildDummy);
|
|
|
|
if (((winLeft + winAttr.width) > winAttrRoot.width) || winLeft < winAttrRoot.x ||
|
|
((winTop + winAttr.height) > winAttrRoot.height) || winTop < winAttrRoot.y)
|
|
{
|
|
std::cerr << "The window not fully visible! Can't create the snapshot.\n";
|
|
return Standard_False;
|
|
}
|
|
}
|
|
|
|
XVisualInfo aVInfo;
|
|
if (XMatchVisualInfo (Draw_WindowDisplay, Draw_WindowScreen, 32, TrueColor, &aVInfo) == 0
|
|
&& XMatchVisualInfo (Draw_WindowDisplay, Draw_WindowScreen, 24, TrueColor, &aVInfo) == 0)
|
|
{
|
|
std::cerr << "24-bit TrueColor visual is not supported by server!\n";
|
|
return Standard_False;
|
|
}
|
|
|
|
Image_AlienPixMap anImage;
|
|
bool isBigEndian = Image_PixMap::IsBigEndianHost();
|
|
const Standard_Size aSizeRowBytes = Standard_Size(winAttr.width) * 4;
|
|
if (!anImage.InitTrash (isBigEndian ? Image_Format_RGB32 : Image_Format_BGR32,
|
|
Standard_Size(winAttr.width), Standard_Size(winAttr.height), aSizeRowBytes))
|
|
{
|
|
return Standard_False;
|
|
}
|
|
anImage.SetTopDown (true);
|
|
|
|
XImage* anXImage = XCreateImage (Draw_WindowDisplay, aVInfo.visual,
|
|
32, ZPixmap, 0, (char* )anImage.ChangeData(), winAttr.width, winAttr.height, 32, int(aSizeRowBytes));
|
|
anXImage->bitmap_bit_order = anXImage->byte_order = (isBigEndian ? MSBFirst : LSBFirst);
|
|
if (XGetSubImage (Draw_WindowDisplay, GetDrawable(),
|
|
0, 0, winAttr.width, winAttr.height,
|
|
AllPlanes, ZPixmap, anXImage, 0, 0) == NULL)
|
|
{
|
|
anXImage->data = NULL;
|
|
XDestroyImage (anXImage);
|
|
return Standard_False;
|
|
}
|
|
|
|
// destroy the image
|
|
anXImage->data = NULL;
|
|
XDestroyImage (anXImage);
|
|
|
|
// save the image
|
|
return anImage.Save (theFileName);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Wait
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void Draw_Window::Wait (Standard_Boolean wait)
|
|
{
|
|
Flush();
|
|
if (!wait) {
|
|
XSelectInput(Draw_WindowDisplay,win,
|
|
ButtonPressMask|ExposureMask | StructureNotifyMask |
|
|
PointerMotionMask);
|
|
}
|
|
else {
|
|
XSelectInput(Draw_WindowDisplay,win,
|
|
ButtonPressMask|ExposureMask | StructureNotifyMask);
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : ProcessEvent
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void ProcessEvent(Draw_Window& win, XEvent& xev)
|
|
{
|
|
Standard_Integer X,Y,button;
|
|
KeySym keysym;
|
|
XComposeStatus stat;
|
|
char chainekey[10];
|
|
|
|
switch (xev.type)
|
|
{
|
|
case ClientMessage:
|
|
{
|
|
if (xev.xclient.data.l[0] == (int )Draw_DisplayConnection->GetAtom (Aspect_XA_DELETE_WINDOW))
|
|
{
|
|
// just hide the window
|
|
win.Hide();
|
|
}
|
|
return;
|
|
}
|
|
case Expose :
|
|
win.WExpose();
|
|
break;
|
|
|
|
case ButtonPress :
|
|
X = xev.xbutton.x;
|
|
Y = xev.xbutton.y;
|
|
button = xev.xbutton.button;
|
|
win.WButtonPress(X,Y,button);
|
|
break;
|
|
|
|
case ButtonRelease :
|
|
X = xev.xbutton.x;
|
|
Y = xev.xbutton.y;
|
|
button = xev.xbutton.button;
|
|
win.WButtonRelease(X,Y,button);
|
|
break;
|
|
|
|
case KeyPress :
|
|
XLookupString(&(xev.xkey),
|
|
chainekey,
|
|
10,
|
|
&keysym,
|
|
&stat);
|
|
break;
|
|
|
|
case MotionNotify :
|
|
X = xev.xmotion.x;
|
|
Y = xev.xmotion.y;
|
|
win.WMotionNotify(X,Y);
|
|
break;
|
|
|
|
case ConfigureNotify :
|
|
if (win.withWindowManager)
|
|
win.WConfigureNotify(xev.xconfigure.x, xev.xconfigure.y,
|
|
xev.xconfigure.width,
|
|
xev.xconfigure.height);
|
|
break;
|
|
|
|
case UnmapNotify :
|
|
|
|
win.WUnmapNotify();
|
|
break;
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : WExpose
|
|
//purpose :
|
|
//=======================================================================
|
|
void Draw_Window::WExpose()
|
|
{
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : WButtonPress
|
|
//purpose :
|
|
//=======================================================================
|
|
void Draw_Window::WButtonPress(const Standard_Integer,
|
|
const Standard_Integer,
|
|
const Standard_Integer&)
|
|
{
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : WButtonRelease
|
|
//purpose :
|
|
//=======================================================================
|
|
void Draw_Window::WButtonRelease(const Standard_Integer,
|
|
const Standard_Integer,
|
|
const Standard_Integer&)
|
|
{
|
|
}
|
|
|
|
/**************************
|
|
//=======================================================================
|
|
//function : WKeyPress
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void Draw_Window::WKeyPress(char, KeySym&)
|
|
{
|
|
}
|
|
***************************/
|
|
|
|
//=======================================================================
|
|
//function : WMotionNotify
|
|
//purpose :
|
|
//=======================================================================
|
|
void Draw_Window::WMotionNotify(const Standard_Integer ,
|
|
const Standard_Integer )
|
|
{
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : WConfigureNotify
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void Draw_Window::WConfigureNotify(const Standard_Integer,
|
|
const Standard_Integer,
|
|
const Standard_Integer,
|
|
const Standard_Integer)
|
|
{
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : WUnmapNotify
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void Draw_Window::WUnmapNotify()
|
|
{
|
|
}
|
|
|
|
|
|
//======================================================
|
|
// function : ProcessEvents
|
|
// purpose : process pending X events
|
|
//======================================================
|
|
|
|
static void ProcessEvents(ClientData,int)
|
|
{
|
|
// test for X Event
|
|
|
|
while (XPending(Draw_WindowDisplay)) {
|
|
|
|
XEvent xev;
|
|
xev.type = 0;
|
|
|
|
XNextEvent(Draw_WindowDisplay,&xev);
|
|
|
|
/* search the window in the window list */
|
|
Draw_Window* w = Draw_Window::firstWindow;
|
|
Standard_Integer found=0;
|
|
while (w) {
|
|
if (xev.xany.window == w->win) {
|
|
ProcessEvent(*w, xev);
|
|
found=1;
|
|
break;
|
|
}
|
|
w = w->next;
|
|
}
|
|
if (found==0) {
|
|
Tk_HandleEvent(&xev);
|
|
}
|
|
}
|
|
}
|
|
|
|
//======================================================
|
|
// function : GetNextEvent()
|
|
// purpose :
|
|
//======================================================
|
|
void GetNextEvent(Event& ev)
|
|
{
|
|
XEvent xev;
|
|
XNextEvent(Draw_WindowDisplay, &xev);
|
|
switch(xev.type)
|
|
{
|
|
case ButtonPress :
|
|
ev.type = 4;
|
|
ev.window = xev.xbutton.window;
|
|
ev.button = xev.xbutton.button;
|
|
ev.x = xev.xbutton.x;
|
|
ev.y = xev.xbutton.y;
|
|
break;
|
|
|
|
case MotionNotify :
|
|
ev.type = 6;
|
|
ev.window = xev.xmotion.window;
|
|
ev.button = 0;
|
|
ev.x = xev.xmotion.x;
|
|
ev.y = xev.xmotion.y;
|
|
break;
|
|
}
|
|
}
|
|
#endif //__APPLE__
|
|
|
|
//======================================================
|
|
// function :Run_Appli
|
|
// purpose :
|
|
//======================================================
|
|
|
|
|
|
static Standard_Boolean(*Interprete) (const char*);
|
|
|
|
void Run_Appli(Standard_Boolean (*interprete) (const char*))
|
|
{
|
|
Tcl_Channel outChannel, inChannel ;
|
|
Interprete = interprete;
|
|
|
|
#ifdef _TK
|
|
|
|
/*
|
|
* Commands will come from standard input, so set up an event
|
|
* handler for standard input. If the input device is aEvaluate the
|
|
* .rc file, if one has been specified, set up an event handler
|
|
* for standard input, and print a prompt if the input
|
|
* device is a terminal.
|
|
*/
|
|
inChannel = Tcl_GetStdChannel(TCL_STDIN);
|
|
if (inChannel) {
|
|
Tcl_CreateChannelHandler(inChannel, TCL_READABLE, StdinProc,
|
|
(ClientData) inChannel);
|
|
}
|
|
|
|
// Create a handler for the draw display
|
|
|
|
// Adding of the casting into void* to be able to compile on AO1
|
|
// ConnectionNumber(Draw_WindowDisplay) is an int 32 bits
|
|
// (void*) is a pointer 64 bits ???????
|
|
|
|
#if !defined(__APPLE__) || defined(MACOSX_USE_GLX)
|
|
#if TCL_MAJOR_VERSION < 8
|
|
Tk_CreateFileHandler((void*) ConnectionNumber(Draw_WindowDisplay),
|
|
TK_READABLE, ProcessEvents,(ClientData) 0 );
|
|
#else
|
|
Tk_CreateFileHandler(ConnectionNumber(Draw_WindowDisplay),
|
|
TK_READABLE, ProcessEvents,(ClientData) 0 );
|
|
#endif
|
|
#endif // __APPLE__
|
|
|
|
#endif
|
|
|
|
Draw_Interpretor& aCommands = Draw::GetInterpretor();
|
|
|
|
if (tty) Prompt(aCommands.Interp(), 0);
|
|
Prompt(aCommands.Interp(), 0);
|
|
|
|
outChannel = Tcl_GetStdChannel(TCL_STDOUT);
|
|
if (outChannel) {
|
|
Tcl_Flush(outChannel);
|
|
}
|
|
Tcl_DStringInit(&command);
|
|
|
|
/*
|
|
* Loop infinitely, waiting for commands to execute. When there
|
|
* are no windows left, Tk_MainLoop returns and we exit.
|
|
*/
|
|
|
|
#ifdef _TK
|
|
|
|
if (Draw_VirtualWindows) {
|
|
// main window will never shown
|
|
// but main loop will parse all Xlib messages
|
|
Tcl_Eval(aCommands.Interp(), "wm withdraw .");
|
|
}
|
|
Tk_MainLoop();
|
|
|
|
#else
|
|
|
|
fd_set readset;
|
|
Standard_Integer count = ConnectionNumber(Draw_WindowDisplay);
|
|
Standard_Integer numfd;
|
|
while (1) {
|
|
FD_ZERO(&readset);
|
|
FD_SET(0,&readset);
|
|
FD_SET(count,&readset);
|
|
#ifdef HPUX
|
|
numfd = select(count+1,(Integer*)&readset,NULL,NULL,NULL);
|
|
#else
|
|
numfd = select(count+1,&readset,NULL,NULL,NULL);
|
|
#endif
|
|
if (FD_ISSET(0,&readset)) StdinProc((ClientData)0,0);
|
|
if (FD_ISSET(count,&readset)) ProcessEvents((ClientData)0,0);
|
|
}
|
|
|
|
#endif
|
|
NCollection_List<Draw_Window::FCallbackBeforeTerminate>::Iterator Iter(MyCallbacks);
|
|
for(; Iter.More(); Iter.Next())
|
|
{
|
|
(*Iter.Value())();
|
|
}
|
|
}
|
|
|
|
//======================================================
|
|
// function : Init_Appli()
|
|
// purpose :
|
|
//======================================================
|
|
Standard_Boolean Init_Appli()
|
|
{
|
|
Draw_Interpretor& aCommands = Draw::GetInterpretor();
|
|
aCommands.Init();
|
|
Tcl_Interp *interp = aCommands.Interp();
|
|
Tcl_Init (interp);
|
|
|
|
try {
|
|
OCC_CATCH_SIGNALS
|
|
Tk_Init(interp) ;
|
|
} catch (Standard_Failure const&) {
|
|
std::cout <<" Pb au lancement de TK_Init "<<std::endl;
|
|
}
|
|
|
|
Tcl_StaticPackage(interp, "Tk", Tk_Init, (Tcl_PackageInitProc *) NULL);
|
|
|
|
Tk_Window aMainWindow = Tk_MainWindow(interp) ;
|
|
if (aMainWindow == NULL) {
|
|
#if ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 5)))
|
|
fprintf(stderr, "%s\n", Tcl_GetStringResult(interp));
|
|
#else
|
|
fprintf(stderr, "%s\n", interp->result);
|
|
#endif
|
|
exit(1);
|
|
}
|
|
#if defined(__APPLE__) && !defined(MACOSX_USE_GLX)
|
|
Tk_SetAppName(aMainWindow, "Draw");
|
|
#else
|
|
Tk_Name(aMainWindow) = Tk_GetUid(Tk_SetAppName(aMainWindow, "Draw"));
|
|
#endif
|
|
|
|
Tk_GeometryRequest (aMainWindow, 200, 200);
|
|
|
|
#if !defined(__APPLE__) || defined(MACOSX_USE_GLX)
|
|
if (Draw_DisplayConnection.IsNull())
|
|
{
|
|
try
|
|
{
|
|
Draw_DisplayConnection = new Aspect_DisplayConnection();
|
|
}
|
|
catch (Standard_Failure const&)
|
|
{
|
|
std::cout << "Cannot open display. Interpret commands in batch mode." << std::endl;
|
|
return Standard_False;
|
|
}
|
|
}
|
|
if (Draw_WindowDisplay == NULL)
|
|
{
|
|
Draw_WindowDisplay = Draw_DisplayConnection->GetDisplay();
|
|
}
|
|
//
|
|
// synchronize the display server : could be done within Tk_Init
|
|
//
|
|
XSynchronize(Draw_WindowDisplay, True);
|
|
XSetInputFocus(Draw_WindowDisplay,
|
|
PointerRoot,
|
|
RevertToPointerRoot,
|
|
CurrentTime);
|
|
|
|
Draw_WindowScreen = DefaultScreen(Draw_WindowDisplay);
|
|
Draw_WindowColorMap = DefaultColormap(Draw_WindowDisplay,
|
|
Draw_WindowScreen);
|
|
#endif // __APPLE__
|
|
|
|
tty = isatty(0);
|
|
Tcl_SetVar(interp,"tcl_interactive",(char*)(tty ? "1" : "0"), TCL_GLOBAL_ONLY);
|
|
// Tcl_SetVar(interp,"tcl_interactive",tty ? "1" : "0", TCL_GLOBAL_ONLY);
|
|
return Standard_True;
|
|
}
|
|
|
|
//======================================================
|
|
// function : Destroy_Appli()
|
|
// purpose :
|
|
//======================================================
|
|
void Destroy_Appli()
|
|
{
|
|
//XCloseDisplay(Draw_WindowDisplay);
|
|
}
|
|
|
|
/*
|
|
*----------------------------------------------------------------------
|
|
*
|
|
* StdinProc --
|
|
*
|
|
* This procedure is invoked by the event dispatcher whenever
|
|
* standard input becomes readable. It grabs the next line of
|
|
* input characters, adds them to a command being assembled, and
|
|
* executes the command if it's complete.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* Could be almost arbitrary, depending on the command that's
|
|
* typed.
|
|
*
|
|
*----------------------------------------------------------------------
|
|
*/
|
|
|
|
/* ARGSUSED */
|
|
//static void StdinProc(ClientData clientData, int mask)
|
|
static void StdinProc(ClientData clientData, int )
|
|
{
|
|
static int gotPartial = 0;
|
|
char *cmd;
|
|
// int code, count;
|
|
int count;
|
|
Tcl_Channel chan = (Tcl_Channel) clientData;
|
|
|
|
// MSV Nov 2, 2001: patch for TCL 8.3: initialize line to avoid exception
|
|
// when first user input is an empty string
|
|
Tcl_DStringFree(&line);
|
|
count = Tcl_Gets(chan, &line);
|
|
|
|
// MKV 26.05.05
|
|
#if ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4)))
|
|
Tcl_DString linetmp;
|
|
Tcl_DStringInit(&linetmp);
|
|
Tcl_UniChar * UniCharString;
|
|
UniCharString = Tcl_UtfToUniCharDString(Tcl_DStringValue(&line),-1,&linetmp);
|
|
Standard_Integer l = Tcl_UniCharLen(UniCharString);
|
|
TCollection_AsciiString AsciiString("");
|
|
Standard_Character Character;
|
|
Standard_Integer i;
|
|
for (i=0; i<l; i++) {
|
|
Character = UniCharString[i];
|
|
AsciiString.AssignCat(Character);
|
|
}
|
|
Tcl_DStringInit(&line);
|
|
Tcl_DStringAppend(&line, AsciiString.ToCString(), -1);
|
|
#endif
|
|
if (count < 0) {
|
|
if (!gotPartial) {
|
|
if (tty) {
|
|
Tcl_Exit(0);
|
|
} else {
|
|
Tcl_DeleteChannelHandler(chan, StdinProc, (ClientData) chan);
|
|
}
|
|
return;
|
|
} else {
|
|
count = 0;
|
|
}
|
|
}
|
|
|
|
(void) Tcl_DStringAppend(&command, Tcl_DStringValue(&line), -1);
|
|
cmd = Tcl_DStringAppend(&command, "\n", -1);
|
|
Tcl_DStringFree(&line);
|
|
try {
|
|
OCC_CATCH_SIGNALS
|
|
if (!Tcl_CommandComplete(cmd)) {
|
|
gotPartial = 1;
|
|
goto prompt;
|
|
}
|
|
gotPartial = 0;
|
|
|
|
/*
|
|
* Disable the stdin channel handler while evaluating the command;
|
|
* otherwise if the command re-enters the event loop we might
|
|
* process commands from stdin before the current command is
|
|
* finished. Among other things, this will trash the text of the
|
|
* command being evaluated.
|
|
*/
|
|
|
|
Tcl_CreateChannelHandler(chan, 0, StdinProc, (ClientData) chan);
|
|
|
|
|
|
/*
|
|
* Disable the stdin file handler while evaluating the command;
|
|
* otherwise if the command re-enters the event loop we might
|
|
* process commands from stdin before the current command is
|
|
* finished. Among other things, this will trash the text of the
|
|
* command being evaluated.
|
|
*/
|
|
|
|
#ifdef _TK
|
|
// Tk_CreateFileHandler(0, 0, StdinProc, (ClientData) 0);
|
|
#endif
|
|
//
|
|
// xab average to avoid an output SIGBUS of DRAW
|
|
// to ultimately prescise or remove once
|
|
// the problem of free on the global variable at the average
|
|
//
|
|
//
|
|
|
|
Interprete(cmd);
|
|
|
|
|
|
Tcl_CreateChannelHandler(chan, TCL_READABLE, StdinProc,
|
|
(ClientData) chan);
|
|
Tcl_DStringFree(&command);
|
|
|
|
/*
|
|
* Output a prompt.
|
|
*/
|
|
|
|
prompt:
|
|
if (tty) Prompt(Draw::GetInterpretor().Interp(), gotPartial);
|
|
|
|
} catch (Standard_Failure const&) {}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
// Source Specifique WNT
|
|
|
|
/****************************************************\
|
|
* Draw_Window.cxx :
|
|
*
|
|
\****************************************************/
|
|
|
|
#include "Draw_Window.hxx"
|
|
#include "DrawRessource.h"
|
|
#include "init.h"
|
|
|
|
#include <Draw_Appli.hxx>
|
|
#include <OSD.hxx>
|
|
|
|
#include <tk.h>
|
|
|
|
#define PENWIDTH 1
|
|
#define CLIENTWND 0
|
|
// Position of information in the extra memory
|
|
|
|
// indicates SUBSYSTEM:CONSOLE linker option, to be set to True in main()
|
|
Standard_EXPORT
|
|
Standard_Boolean Draw_IsConsoleSubsystem = Standard_False;
|
|
|
|
|
|
Standard_Boolean Draw_BlackBackGround = Standard_True;
|
|
|
|
// Creation of color stylos
|
|
HPEN colorPenTab[MAXCOLOR] = {CreatePen(PS_SOLID, PENWIDTH, RGB(255,255,255)),
|
|
CreatePen(PS_SOLID, PENWIDTH, RGB(255,0,0)),
|
|
CreatePen(PS_SOLID, PENWIDTH, RGB(0,255,0)),
|
|
CreatePen(PS_SOLID, PENWIDTH, RGB(0,0,255)),
|
|
CreatePen(PS_SOLID, PENWIDTH, RGB(0,255,255)),
|
|
CreatePen(PS_SOLID, PENWIDTH, RGB(255,215,0)),
|
|
CreatePen(PS_SOLID, PENWIDTH, RGB(255,0,255)),
|
|
CreatePen(PS_SOLID, PENWIDTH, RGB(255,52,179)),
|
|
CreatePen(PS_SOLID, PENWIDTH, RGB(255,165,0)),
|
|
CreatePen(PS_SOLID, PENWIDTH, RGB(255,228,225)),
|
|
CreatePen(PS_SOLID, PENWIDTH, RGB(255,160,122)),
|
|
CreatePen(PS_SOLID, PENWIDTH, RGB(199,21,133)),
|
|
CreatePen(PS_SOLID, PENWIDTH, RGB(255,255,0)),
|
|
CreatePen(PS_SOLID, PENWIDTH, RGB(240,230,140)),
|
|
CreatePen(PS_SOLID, PENWIDTH, RGB(255,127,80))};
|
|
|
|
// Correspondence mode X11 and WINDOWS NT
|
|
int modeTab[16] = {R2_BLACK, R2_MASKPEN, R2_MASKPENNOT, R2_COPYPEN,
|
|
R2_MASKNOTPEN, R2_NOP, R2_XORPEN, R2_MERGEPEN,
|
|
R2_NOTMASKPEN, R2_NOTXORPEN, R2_NOT, R2_MERGEPENNOT,
|
|
R2_NOTCOPYPEN, R2_MERGENOTPEN, R2_NOTMERGEPEN, R2_WHITE};
|
|
|
|
/*--------------------------------------------------------*\
|
|
| CREATE DRAW WINDOW PROCEDURE
|
|
\*--------------------------------------------------------*/
|
|
HWND DrawWindow::CreateDrawWindow(HWND hWndClient, int nitem)
|
|
{
|
|
if (Draw_IsConsoleSubsystem) {
|
|
HWND aWin = CreateWindowW (DRAWCLASS, DRAWTITLE,
|
|
WS_OVERLAPPEDWINDOW,
|
|
1,1,1,1,
|
|
NULL, NULL,::GetModuleHandle(NULL), NULL);
|
|
if (!Draw_VirtualWindows)
|
|
{
|
|
SetWindowPos(aWin, HWND_TOPMOST, 1,1,1,1, SWP_NOMOVE);
|
|
SetWindowPos(aWin, HWND_NOTOPMOST, 1,1,1,1, SWP_NOMOVE);
|
|
}
|
|
return aWin;
|
|
}
|
|
else {
|
|
HANDLE hInstance = (HANDLE )GetWindowLongPtrW (hWndClient, GWLP_HINSTANCE);
|
|
|
|
return CreateMDIWindowW(DRAWCLASS, DRAWTITLE,
|
|
WS_CAPTION | WS_CHILD | WS_THICKFRAME,
|
|
1,1,0,0,
|
|
hWndClient, (HINSTANCE)hInstance, nitem);
|
|
}
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------*\
|
|
| DRAW WINDOW PROCEDURE
|
|
\*--------------------------------------------------------*/
|
|
LRESULT APIENTRY DrawWindow::DrawProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
DrawWindow* localObjet = (DrawWindow* )GetWindowLongPtrW (hWnd, CLIENTWND);
|
|
if (!localObjet)
|
|
{
|
|
return Draw_IsConsoleSubsystem
|
|
? DefWindowProcW (hWnd, wMsg, wParam, lParam)
|
|
: DefMDIChildProcW (hWnd, wMsg, wParam, lParam);
|
|
}
|
|
|
|
switch (wMsg)
|
|
{
|
|
case WM_CLOSE:
|
|
{
|
|
localObjet->Hide();
|
|
return 0; // do nothing - window destruction should be performed by application
|
|
}
|
|
case WM_PAINT:
|
|
{
|
|
PAINTSTRUCT ps;
|
|
BeginPaint (hWnd, &ps);
|
|
if (localObjet->GetUseBuffer())
|
|
{
|
|
localObjet->Redraw();
|
|
}
|
|
else
|
|
{
|
|
localObjet->WExpose();
|
|
}
|
|
EndPaint (hWnd, &ps);
|
|
return 0;
|
|
}
|
|
case WM_SIZE:
|
|
{
|
|
if (localObjet->GetUseBuffer())
|
|
{
|
|
localObjet->InitBuffer();
|
|
localObjet->WExpose();
|
|
localObjet->Redraw();
|
|
return 0;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return Draw_IsConsoleSubsystem
|
|
? DefWindowProcW (hWnd, wMsg, wParam, lParam)
|
|
: DefMDIChildProcW (hWnd, wMsg, wParam, lParam);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
** IMPLEMENTATION of the CLASS DRAWWINDOW
|
|
*/
|
|
|
|
/*--------------------------------------------------------*\
|
|
| Initialization of static variables of DrawWindow
|
|
\*--------------------------------------------------------*/
|
|
|
|
DrawWindow* DrawWindow::firstWindow = NULL;
|
|
HWND DrawWindow::hWndClientMDI = 0;
|
|
|
|
/*--------------------------------------------------------*\
|
|
| Constructors of Draw_Window
|
|
\*--------------------------------------------------------*/
|
|
|
|
// Default Constructor
|
|
//________________________
|
|
DrawWindow::DrawWindow() :
|
|
win(0),
|
|
next(firstWindow),
|
|
previous(NULL),
|
|
myMemHbm(NULL),
|
|
myUseBuffer(Standard_False),
|
|
myCurrPen(0),
|
|
myCurrMode(0)
|
|
{
|
|
if (firstWindow) firstWindow->previous = this;
|
|
firstWindow = this;
|
|
}
|
|
|
|
//________________________
|
|
DrawWindow::DrawWindow(const char* title,
|
|
Standard_Integer X, Standard_Integer Y,
|
|
Standard_Integer dX,Standard_Integer dY) :
|
|
win(0), next(firstWindow), previous(NULL), myMemHbm(NULL), myUseBuffer(Standard_False)
|
|
{
|
|
if (firstWindow) firstWindow->previous = this;
|
|
firstWindow = this;
|
|
Init(X, Y, dX, dY);
|
|
SetTitle(title);
|
|
}
|
|
DrawWindow::DrawWindow(const char* title,
|
|
Standard_Integer X, Standard_Integer Y,
|
|
Standard_Integer dX,Standard_Integer dY,
|
|
HWND theWin) :
|
|
win(theWin),next(firstWindow), previous(NULL), myMemHbm(NULL), myUseBuffer(Standard_False)
|
|
{
|
|
if (firstWindow) firstWindow->previous = this;
|
|
firstWindow = this;
|
|
Init(X, Y, dX, dY);
|
|
SetTitle(title);
|
|
}
|
|
|
|
|
|
|
|
/*--------------------------------------------------------*\
|
|
| Destructor of DrawWindow
|
|
\*--------------------------------------------------------*/
|
|
DrawWindow::~DrawWindow()
|
|
{
|
|
if (previous)
|
|
previous->next = next;
|
|
else
|
|
firstWindow = next;
|
|
if (next)
|
|
next->previous = previous;
|
|
|
|
// Delete 'off-screen drawing'-related objects
|
|
if (myMemHbm) {
|
|
DeleteObject(myMemHbm);
|
|
myMemHbm = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*--------------------------------------------------------*\
|
|
| Init
|
|
\*--------------------------------------------------------*/
|
|
void DrawWindow::Init(Standard_Integer theXLeft, Standard_Integer theYTop,
|
|
Standard_Integer theWidth, Standard_Integer theHeight)
|
|
{
|
|
if (win == NULL)
|
|
{
|
|
win = CreateDrawWindow(hWndClientMDI, 0);
|
|
}
|
|
|
|
// include decorations in the window dimensions
|
|
// to reproduce same behaviour of Xlib window.
|
|
DWORD aWinStyle = GetWindowLongW (win, GWL_STYLE);
|
|
DWORD aWinStyleEx = GetWindowLongW (win, GWL_EXSTYLE);
|
|
HMENU aMenu = GetMenu (win);
|
|
|
|
RECT aRect;
|
|
aRect.top = theYTop;
|
|
aRect.bottom = theYTop + theHeight;
|
|
aRect.left = theXLeft;
|
|
aRect.right = theXLeft + theWidth;
|
|
AdjustWindowRectEx (&aRect, aWinStyle, aMenu != NULL ? TRUE : FALSE, aWinStyleEx);
|
|
|
|
SetPosition (aRect.left, aRect.top);
|
|
SetDimension (aRect.right - aRect.left, aRect.bottom - aRect.top);
|
|
// Save the pointer at the instance associated to the window
|
|
SetWindowLongPtrW (win, CLIENTWND, (LONG_PTR)this);
|
|
HDC hDC = GetDC(win);
|
|
SetBkColor(hDC, RGB(0, 0, 0));
|
|
myCurrPen = 3;
|
|
myCurrMode = 3;
|
|
SelectObject(hDC, colorPenTab[myCurrPen]); // Default pencil
|
|
SelectObject(hDC, GetStockObject(BLACK_BRUSH));
|
|
SetTextColor(hDC, RGB(0,0,255));
|
|
ReleaseDC(win, hDC);
|
|
|
|
if (Draw_VirtualWindows)
|
|
{
|
|
// create a virtual window
|
|
SetUseBuffer (Standard_True);
|
|
}
|
|
}
|
|
|
|
/*--------------------------------------------------------*\
|
|
| SetUseBuffer
|
|
\*--------------------------------------------------------*/
|
|
void DrawWindow::SetUseBuffer(Standard_Boolean use)
|
|
{
|
|
myUseBuffer = use;
|
|
InitBuffer();
|
|
}
|
|
|
|
/*--------------------------------------------------------*\
|
|
| InitBuffer
|
|
\*--------------------------------------------------------*/
|
|
void DrawWindow::InitBuffer()
|
|
{
|
|
if (myUseBuffer) {
|
|
RECT rc;
|
|
HDC hDC = GetDC(win);
|
|
GetClientRect(win, &rc);
|
|
if (myMemHbm) {
|
|
BITMAP aBmp;
|
|
GetObjectW (myMemHbm, sizeof(BITMAP), &aBmp);
|
|
if (rc.right-rc.left == aBmp.bmWidth && rc.bottom-rc.top == aBmp.bmHeight) return;
|
|
DeleteObject(myMemHbm);
|
|
}
|
|
myMemHbm = (HBITMAP)CreateCompatibleBitmap(hDC,
|
|
rc.right-rc.left,
|
|
rc.bottom-rc.top);
|
|
HDC aMemDC = GetMemDC(hDC);
|
|
FillRect(aMemDC, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH));
|
|
ReleaseMemDC(aMemDC);
|
|
ReleaseDC(win, hDC);
|
|
}
|
|
else {
|
|
if (myMemHbm) {
|
|
DeleteObject(myMemHbm);
|
|
myMemHbm = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*--------------------------------------------------------*\
|
|
| GetMemDC
|
|
\*--------------------------------------------------------*/
|
|
HDC DrawWindow::GetMemDC(HDC theWinDC)
|
|
{
|
|
if (!myUseBuffer) return NULL;
|
|
|
|
HDC aWorkDC = CreateCompatibleDC(theWinDC);
|
|
myOldHbm = (HBITMAP)SelectObject(aWorkDC, myMemHbm);
|
|
SetROP2(aWorkDC, modeTab[myCurrMode]);
|
|
SelectObject(aWorkDC, colorPenTab[myCurrPen]);
|
|
SetBkColor(aWorkDC, RGB(0, 0, 0));
|
|
SelectObject(aWorkDC, GetStockObject(BLACK_BRUSH));
|
|
SetTextColor(aWorkDC, RGB(0,0,255));
|
|
return aWorkDC;
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------*\
|
|
| ReleaseMemDC
|
|
\*--------------------------------------------------------*/
|
|
void DrawWindow::ReleaseMemDC(HDC theMemDC)
|
|
{
|
|
if (!myUseBuffer || !theMemDC) return;
|
|
|
|
if (myOldHbm) SelectObject(theMemDC, myOldHbm);
|
|
DeleteDC(theMemDC);
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------*\
|
|
| SetPosition
|
|
\*--------------------------------------------------------*/
|
|
void DrawWindow::SetPosition(Standard_Integer posX, Standard_Integer posY)
|
|
{
|
|
UINT aFlags = SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER;
|
|
if (Draw_VirtualWindows)
|
|
{
|
|
aFlags |= SWP_NOSENDCHANGING;
|
|
}
|
|
SetWindowPos (win, 0, posX, posY, 0, 0, aFlags);
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------*\
|
|
| SetDimension
|
|
\*--------------------------------------------------------*/
|
|
void DrawWindow::SetDimension(Standard_Integer dimX, Standard_Integer dimY)
|
|
{
|
|
UINT aFlags = SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER;
|
|
if (Draw_VirtualWindows)
|
|
{
|
|
aFlags |= SWP_NOSENDCHANGING;
|
|
}
|
|
SetWindowPos (win, 0, 0, 0, dimX, dimY, aFlags);
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------*\
|
|
| GetPosition
|
|
\*--------------------------------------------------------*/
|
|
void DrawWindow::GetPosition(Standard_Integer &dimX,
|
|
Standard_Integer &dimY)
|
|
{
|
|
RECT rect;
|
|
GetWindowRect(win, &rect);
|
|
|
|
POINT point;
|
|
point.x = rect.left;
|
|
point.y = rect.top;
|
|
|
|
ScreenToClient(hWndClientMDI, &point);
|
|
dimX = point.x;
|
|
dimY = point.y;
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------*\
|
|
| HeightWin
|
|
\*--------------------------------------------------------*/
|
|
Standard_Integer DrawWindow::HeightWin() const
|
|
{
|
|
RECT rect;
|
|
GetClientRect(win, &rect);
|
|
return(rect.bottom-rect.top);
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------*\
|
|
| WidthWin
|
|
\*--------------------------------------------------------*/
|
|
Standard_Integer DrawWindow::WidthWin() const
|
|
{
|
|
RECT rect;
|
|
GetClientRect(win, &rect);
|
|
return(rect.right-rect.left);
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------*\
|
|
| SetTitle
|
|
\*--------------------------------------------------------*/
|
|
void DrawWindow::SetTitle (const TCollection_AsciiString& theTitle)
|
|
{
|
|
const TCollection_ExtendedString aTitleW (theTitle);
|
|
SetWindowTextW (win, aTitleW.ToWideString());
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------*\
|
|
| GetTitle
|
|
\*--------------------------------------------------------*/
|
|
TCollection_AsciiString DrawWindow::GetTitle() const
|
|
{
|
|
wchar_t aTitleW[32];
|
|
GetWindowTextW (win, aTitleW, 30);
|
|
return TCollection_AsciiString (aTitleW);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : IsMapped
|
|
//purpose :
|
|
//=======================================================================
|
|
bool Draw_Window::IsMapped() const
|
|
{
|
|
if (Draw_VirtualWindows
|
|
|| win == NULL)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
LONG aWinStyle = GetWindowLongW (win, GWL_STYLE);
|
|
return (aWinStyle & WS_VISIBLE) != 0
|
|
&& (aWinStyle & WS_MINIMIZE) == 0;
|
|
}
|
|
|
|
/*--------------------------------------------------------*\
|
|
| DisplayWindow
|
|
\*--------------------------------------------------------*/
|
|
void DrawWindow::DisplayWindow()
|
|
{
|
|
if (Draw_VirtualWindows)
|
|
{
|
|
return;
|
|
}
|
|
ShowWindow (win, SW_SHOW);
|
|
UpdateWindow (win);
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------*\
|
|
| Hide
|
|
\*--------------------------------------------------------*/
|
|
void DrawWindow::Hide()
|
|
{
|
|
ShowWindow(win, SW_HIDE);
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------*\
|
|
| Destroy
|
|
\*--------------------------------------------------------*/
|
|
void DrawWindow::Destroy()
|
|
{
|
|
DestroyWindow(win);
|
|
}
|
|
|
|
|
|
|
|
/*--------------------------------------------------------*\
|
|
| Clear
|
|
\*--------------------------------------------------------*/
|
|
void DrawWindow::Clear()
|
|
{
|
|
HDC hDC = GetDC(win);
|
|
HDC aWorkDC = myUseBuffer ? GetMemDC(hDC) : hDC;
|
|
|
|
SaveDC(aWorkDC);
|
|
SelectObject(aWorkDC,GetStockObject(BLACK_PEN));
|
|
Rectangle(aWorkDC, 0, 0, WidthWin(), HeightWin());
|
|
RestoreDC(aWorkDC,-1);
|
|
|
|
if (myUseBuffer) ReleaseMemDC(aWorkDC);
|
|
ReleaseDC(win,hDC);
|
|
}
|
|
|
|
/*--------------------------------------------------------*\
|
|
| SaveBitmap
|
|
\*--------------------------------------------------------*/
|
|
static Standard_Boolean SaveBitmap (HBITMAP theHBitmap,
|
|
const char* theFileName)
|
|
{
|
|
// Get information about the bitmap
|
|
BITMAP aBitmap;
|
|
if (GetObjectW (theHBitmap, sizeof(BITMAP), &aBitmap) == 0)
|
|
{
|
|
return Standard_False;
|
|
}
|
|
|
|
Image_AlienPixMap anImage;
|
|
const Standard_Size aSizeRowBytes = ((Standard_Size(aBitmap.bmWidth) * 24 + 31) / 32) * 4; // 4 bytes alignment for GetDIBits()
|
|
if (!anImage.InitTrash (Image_Format_BGR, Standard_Size(aBitmap.bmWidth), Standard_Size(aBitmap.bmHeight), aSizeRowBytes))
|
|
{
|
|
return Standard_False;
|
|
}
|
|
anImage.SetTopDown (false);
|
|
|
|
// Setup image data
|
|
BITMAPINFOHEADER aBitmapInfo;
|
|
memset (&aBitmapInfo, 0, sizeof(BITMAPINFOHEADER));
|
|
aBitmapInfo.biSize = sizeof(BITMAPINFOHEADER);
|
|
aBitmapInfo.biWidth = aBitmap.bmWidth;
|
|
aBitmapInfo.biHeight = aBitmap.bmHeight; // positive means bottom-up!
|
|
aBitmapInfo.biPlanes = 1;
|
|
aBitmapInfo.biBitCount = 24;
|
|
aBitmapInfo.biCompression = BI_RGB;
|
|
|
|
// Copy the pixels
|
|
HDC aDC = GetDC (NULL);
|
|
Standard_Boolean isSuccess = GetDIBits (aDC, theHBitmap,
|
|
0, // first scan line to set
|
|
aBitmap.bmHeight, // number of scan lines to copy
|
|
anImage.ChangeData(), // array for bitmap bits
|
|
(LPBITMAPINFO )&aBitmapInfo, // bitmap data info
|
|
DIB_RGB_COLORS) != 0;
|
|
ReleaseDC (NULL, aDC);
|
|
return isSuccess && anImage.Save (theFileName);
|
|
}
|
|
|
|
/*--------------------------------------------------------*\
|
|
| Save
|
|
\*--------------------------------------------------------*/
|
|
Standard_Boolean DrawWindow::Save (const char* theFileName) const
|
|
{
|
|
if (myUseBuffer)
|
|
{
|
|
return SaveBitmap (myMemHbm, theFileName);
|
|
}
|
|
|
|
RECT aRect;
|
|
GetClientRect (win, &aRect);
|
|
int aWidth = aRect.right - aRect.left;
|
|
int aHeight = aRect.bottom - aRect.top;
|
|
|
|
// Prepare the DCs
|
|
HDC aDstDC = GetDC (NULL);
|
|
HDC aSrcDC = GetDC (win); // we copy only client area
|
|
HDC aMemDC = CreateCompatibleDC (aDstDC);
|
|
|
|
// Copy the screen to the bitmap
|
|
HBITMAP anHBitmapDump = CreateCompatibleBitmap (aDstDC, aWidth, aHeight);
|
|
HBITMAP anHBitmapOld = (HBITMAP )SelectObject (aMemDC, anHBitmapDump);
|
|
BitBlt (aMemDC, 0, 0, aWidth, aHeight, aSrcDC, 0, 0, SRCCOPY);
|
|
|
|
Standard_Boolean isSuccess = SaveBitmap (anHBitmapDump, theFileName);
|
|
|
|
// Free objects
|
|
DeleteObject (SelectObject (aMemDC, anHBitmapOld));
|
|
DeleteDC (aMemDC);
|
|
|
|
return isSuccess;
|
|
}
|
|
|
|
/*--------------------------------------------------------*\
|
|
| DrawString
|
|
\*--------------------------------------------------------*/
|
|
void DrawWindow::DrawString(int x,int y, char* text)
|
|
{
|
|
HDC hDC = GetDC(win);
|
|
HDC aWorkDC = myUseBuffer ? GetMemDC(hDC) : hDC;
|
|
|
|
TCollection_ExtendedString textW (text);
|
|
TextOutW(aWorkDC, x, y, (const wchar_t*)textW.ToExtString(), (int )strlen(text));
|
|
|
|
if (myUseBuffer) ReleaseMemDC(aWorkDC);
|
|
ReleaseDC(win,hDC);
|
|
}
|
|
|
|
/*--------------------------------------------------------*\
|
|
| DrawSegments
|
|
\*--------------------------------------------------------*/
|
|
void DrawWindow::DrawSegments(Segment *tab, int nbElem)
|
|
{
|
|
HDC hDC = GetDC(win);
|
|
HDC aWorkDC = myUseBuffer ? GetMemDC(hDC) : hDC;
|
|
|
|
for(int i = 0 ; i < nbElem ; i++)
|
|
{
|
|
MoveToEx(aWorkDC, tab[i].x1, tab[i].y1, NULL);
|
|
LineTo(aWorkDC, tab[i].x2, tab[i].y2);
|
|
}
|
|
|
|
if (myUseBuffer) ReleaseMemDC(aWorkDC);
|
|
ReleaseDC(win,hDC);
|
|
}
|
|
|
|
/*--------------------------------------------------------*\
|
|
| Redraw
|
|
\*--------------------------------------------------------*/
|
|
void DrawWindow::Redraw()
|
|
{
|
|
if (myUseBuffer) {
|
|
HDC hDC = GetDC(win);
|
|
RECT rc;
|
|
GetClientRect(win, &rc);
|
|
HDC aMemDC = GetMemDC(hDC);
|
|
BitBlt(hDC,
|
|
rc.left, rc.top,
|
|
rc.right-rc.left, rc.bottom-rc.top,
|
|
aMemDC,
|
|
0, 0, SRCCOPY);
|
|
ReleaseMemDC(aMemDC);
|
|
ReleaseDC(win,hDC);
|
|
}
|
|
}
|
|
|
|
/*--------------------------------------------------------*\
|
|
| SetMode
|
|
\*--------------------------------------------------------*/
|
|
void DrawWindow::SetMode(int mode)
|
|
{
|
|
HDC hDC = GetDC(win);
|
|
myCurrMode = mode;
|
|
SetROP2(hDC, modeTab[mode]);
|
|
ReleaseDC(win,hDC);
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------*\
|
|
| SetColor
|
|
\*--------------------------------------------------------*/
|
|
void DrawWindow::SetColor(Standard_Integer color)
|
|
{
|
|
HDC hDC = GetDC(win);
|
|
myCurrPen = color;
|
|
SelectObject(hDC,colorPenTab[color]);
|
|
ReleaseDC(win,hDC);
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------*\
|
|
| WExpose
|
|
\*--------------------------------------------------------*/
|
|
void DrawWindow::WExpose()
|
|
{
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------*\
|
|
| WButtonPress
|
|
\*--------------------------------------------------------*/
|
|
void DrawWindow::WButtonPress(const Standard_Integer,
|
|
const Standard_Integer,
|
|
const Standard_Integer&)
|
|
{
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------*\
|
|
| WButtonRelease
|
|
\*--------------------------------------------------------*/
|
|
void DrawWindow::WButtonRelease(const Standard_Integer,
|
|
const Standard_Integer,
|
|
const Standard_Integer&)
|
|
{
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------*\
|
|
| WMotionNotify
|
|
\*--------------------------------------------------------*/
|
|
void Draw_Window::WMotionNotify(const Standard_Integer ,
|
|
const Standard_Integer )
|
|
{
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------*\
|
|
| WConfigureNotify
|
|
\*--------------------------------------------------------*/
|
|
void DrawWindow::WConfigureNotify(const Standard_Integer,
|
|
const Standard_Integer,
|
|
const Standard_Integer,
|
|
const Standard_Integer)
|
|
{
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------*\
|
|
| WUnmapNotify
|
|
\*--------------------------------------------------------*/
|
|
void DrawWindow::WUnmapNotify()
|
|
{
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
** IMPLEMENTATION of the CLASS SEGMENT
|
|
*/
|
|
|
|
/*--------------------------------------------------------*\
|
|
| Init
|
|
\*--------------------------------------------------------*/
|
|
|
|
void Segment::Init(Standard_Integer a1, Standard_Integer a2,
|
|
Standard_Integer a3, Standard_Integer a4)
|
|
{
|
|
x1=a1;
|
|
y1=a2;
|
|
x2=a3;
|
|
y2=a4;
|
|
}
|
|
|
|
static DWORD WINAPI tkLoop (LPVOID theThreadParameter);
|
|
#ifdef _TK
|
|
static Tk_Window mainWindow;
|
|
#endif
|
|
|
|
//* threads sinchronization *//
|
|
DWORD dwMainThreadId;
|
|
console_semaphore_value volatile console_semaphore = WAIT_CONSOLE_COMMAND;
|
|
wchar_t console_command[DRAW_COMMAND_SIZE + 1];
|
|
bool volatile isTkLoopStarted = false;
|
|
|
|
/*--------------------------------------------------------*\
|
|
| Init_Appli
|
|
\*--------------------------------------------------------*/
|
|
Standard_Boolean Init_Appli(HINSTANCE hInst,
|
|
HINSTANCE hPrevInst, int nShow, HWND& hWndFrame )
|
|
{
|
|
DWORD IDThread;
|
|
HANDLE hThread;
|
|
console_semaphore = STOP_CONSOLE;
|
|
|
|
dwMainThreadId = GetCurrentThreadId();
|
|
|
|
//necessary for normal Tk operation
|
|
hThread = CreateThread (NULL, // no security attributes
|
|
0, // use default stack size
|
|
tkLoop, // thread function
|
|
NULL, // no thread function argument
|
|
0, // use default creation flags
|
|
&IDThread);
|
|
if (!hThread) {
|
|
std::cout << "Failed to create Tcl/Tk main loop thread. Switching to batch mode..." << std::endl;
|
|
Draw_Batch = Standard_True;
|
|
Draw_Interpretor& aCommands = Draw::GetInterpretor();
|
|
aCommands.Init();
|
|
Tcl_Interp *interp = aCommands.Interp();
|
|
Tcl_Init(interp);
|
|
#ifdef _TK
|
|
try {
|
|
OCC_CATCH_SIGNALS
|
|
Tk_Init(interp);
|
|
} catch (Standard_Failure& anExcept) {
|
|
std::cout << "Failed to initialize Tk: " << anExcept.GetMessageString() << std::endl;
|
|
}
|
|
|
|
Tcl_StaticPackage(interp, "Tk", Tk_Init, (Tcl_PackageInitProc *) NULL);
|
|
#endif
|
|
//since the main Tcl/Tk loop wasn't created --> switch to batch mode
|
|
return Standard_False;
|
|
}
|
|
|
|
// san - 06/08/2002 - Time for tkLoop to start; Tk fails to initialize otherwise
|
|
while (!isTkLoopStarted)
|
|
Sleep(10);
|
|
|
|
// Saving of window classes
|
|
if(!hPrevInst)
|
|
if(!RegisterAppClass(hInst))
|
|
return(Standard_False);
|
|
|
|
/*
|
|
** Enter the application message-polling loop. This is the anchor for
|
|
** the application.
|
|
*/
|
|
hWndFrame = !Draw_IsConsoleSubsystem ? CreateAppWindow (hInst) : NULL;
|
|
if (hWndFrame != NULL)
|
|
{
|
|
ShowWindow(hWndFrame,nShow);
|
|
UpdateWindow(hWndFrame);
|
|
}
|
|
|
|
return Standard_True;
|
|
}
|
|
|
|
Standard_Boolean Draw_Interprete (const char*);
|
|
|
|
/*--------------------------------------------------------*\
|
|
| readStdinThreadFunc
|
|
\*--------------------------------------------------------*/
|
|
static DWORD WINAPI readStdinThreadFunc (const LPVOID theThreadParameter)
|
|
{
|
|
(void)theThreadParameter;
|
|
if (!Draw_IsConsoleSubsystem)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
// Console locale could be set to the system codepage .OCP (UTF-8 is not properly supported on Windows).
|
|
// However, to use it, we have to care using std::wcerr/fwprintf/WriteConsoleW for non-ascii strings everywhere (including Tcl itself),
|
|
// or otherwise we can have incomplete output issues
|
|
// (e.g. UNICODE string will be NOT just corrupted as in case when we don't set setlocale()
|
|
// but will break further normal output to console due to special characters being accidentally handled by console in the wrong way).
|
|
//setlocale (LC_ALL, ".OCP");
|
|
|
|
// _O_U16TEXT can be used with fgetws() to get similar result as ReadConsoleW() without affecting setlocale(),
|
|
// however it would break pipe input
|
|
//_setmode (_fileno(stdin), _O_U16TEXT);
|
|
|
|
bool isConsoleInput = true;
|
|
for (;;)
|
|
{
|
|
while (console_semaphore != WAIT_CONSOLE_COMMAND)
|
|
{
|
|
Sleep (100);
|
|
}
|
|
|
|
const HANDLE anStdIn = ::GetStdHandle (STD_INPUT_HANDLE);
|
|
if (anStdIn != NULL
|
|
&& anStdIn != INVALID_HANDLE_VALUE
|
|
&& isConsoleInput)
|
|
{
|
|
DWORD aNbRead = 0;
|
|
if (ReadConsoleW (anStdIn, console_command, DRAW_COMMAND_SIZE, &aNbRead, NULL))
|
|
{
|
|
console_command[aNbRead] = L'\0';
|
|
console_semaphore = HAS_CONSOLE_COMMAND;
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
const DWORD anErr = GetLastError();
|
|
if (anErr != ERROR_SUCCESS)
|
|
{
|
|
// fallback using fgetws() which would work with pipes
|
|
// but supports Unicode only through multi-byte encoding (which is not UTF-8)
|
|
isConsoleInput = false;
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
// fgetws() works only for characters within active locale (see setlocale())
|
|
if (fgetws (console_command, DRAW_COMMAND_SIZE, stdin))
|
|
{
|
|
console_semaphore = HAS_CONSOLE_COMMAND;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*--------------------------------------------------------*\
|
|
| exitProc: finalization handler for Tcl/Tk thread. Forces parent process to die
|
|
\*--------------------------------------------------------*/
|
|
void exitProc(ClientData /*dc*/)
|
|
{
|
|
NCollection_List<Draw_Window::FCallbackBeforeTerminate>::Iterator Iter(MyCallbacks);
|
|
for(; Iter.More(); Iter.Next())
|
|
{
|
|
(*Iter.Value())();
|
|
}
|
|
HANDLE proc = GetCurrentProcess();
|
|
TerminateProcess(proc, 0);
|
|
}
|
|
|
|
// This is fixed version of TclpGetDefaultStdChannel() defined in tclWinChan.c
|
|
// See https://core.tcl.tk/tcl/tktview/91c9bc1c457fda269ae18595944fc3c2b54d961d
|
|
static Tcl_Channel
|
|
TclpGetDefaultStdChannel(
|
|
int type) /* One of TCL_STDIN, TCL_STDOUT, or
|
|
* TCL_STDERR. */
|
|
{
|
|
Tcl_Channel channel;
|
|
HANDLE handle;
|
|
int mode = -1;
|
|
const char *bufMode = NULL;
|
|
DWORD handleId = (DWORD) -1;
|
|
/* Standard handle to retrieve. */
|
|
|
|
switch (type) {
|
|
case TCL_STDIN:
|
|
handleId = STD_INPUT_HANDLE;
|
|
mode = TCL_READABLE;
|
|
bufMode = "line";
|
|
break;
|
|
case TCL_STDOUT:
|
|
handleId = STD_OUTPUT_HANDLE;
|
|
mode = TCL_WRITABLE;
|
|
bufMode = "line";
|
|
break;
|
|
case TCL_STDERR:
|
|
handleId = STD_ERROR_HANDLE;
|
|
mode = TCL_WRITABLE;
|
|
bufMode = "none";
|
|
break;
|
|
default:
|
|
Tcl_Panic("TclGetDefaultStdChannel: Unexpected channel type");
|
|
break;
|
|
}
|
|
|
|
handle = GetStdHandle(handleId);
|
|
|
|
/*
|
|
* Note that we need to check for 0 because Windows may return 0 if this
|
|
* is not a console mode application, even though this is not a valid
|
|
* handle.
|
|
*/
|
|
|
|
if ((handle == INVALID_HANDLE_VALUE) || (handle == 0)) {
|
|
return (Tcl_Channel) NULL;
|
|
}
|
|
|
|
/*
|
|
* Make duplicate of the standard handle as it may be altered
|
|
* (closed, reopened with another type of the object etc.) by
|
|
* the system or a user code at any time, e.g. by call to _dup2()
|
|
*/
|
|
if (! DuplicateHandle (GetCurrentProcess(), handle,
|
|
GetCurrentProcess(), &handle,
|
|
0, FALSE, DUPLICATE_SAME_ACCESS)) {
|
|
return (Tcl_Channel) NULL;
|
|
}
|
|
|
|
channel = Tcl_MakeFileChannel(handle, mode);
|
|
|
|
if (channel == NULL) {
|
|
return (Tcl_Channel) NULL;
|
|
}
|
|
|
|
/*
|
|
* Set up the normal channel options for stdio handles.
|
|
*/
|
|
|
|
if (Tcl_SetChannelOption(NULL,channel,"-translation","auto")!=TCL_OK ||
|
|
Tcl_SetChannelOption(NULL,channel,"-eofchar","\032 {}")!=TCL_OK ||
|
|
Tcl_SetChannelOption(NULL,channel,"-buffering",bufMode)!=TCL_OK) {
|
|
Tcl_Close(NULL, channel);
|
|
return (Tcl_Channel) NULL;
|
|
}
|
|
return channel;
|
|
}
|
|
|
|
// helper functuion
|
|
static void ResetStdChannel (int type)
|
|
{
|
|
Tcl_Channel aChannel = TclpGetDefaultStdChannel (type);
|
|
Tcl_SetStdChannel (aChannel, type);
|
|
if (aChannel)
|
|
{
|
|
Tcl_RegisterChannel (NULL, aChannel);
|
|
}
|
|
}
|
|
|
|
/*--------------------------------------------------------*\
|
|
| tkLoop: implements Tk_Main()-like behaviour in a separate thread
|
|
\*--------------------------------------------------------*/
|
|
static DWORD WINAPI tkLoop (const LPVOID theThreadParameter)
|
|
{
|
|
(void)theThreadParameter;
|
|
Tcl_CreateExitHandler(exitProc, 0);
|
|
|
|
Draw_Interpretor& aCommands = Draw::GetInterpretor();
|
|
aCommands.Init();
|
|
Tcl_Interp *interp = aCommands.Interp();
|
|
Tcl_Init(interp);
|
|
|
|
// Work-around against issue with Tcl standard channels on Windows.
|
|
// These channels by default use OS handles owned by the system which
|
|
// may get invalidated e.g. by dup2() (see dlog command).
|
|
// If this happens, output to stdout from Tcl (e.g. puts) gets broken
|
|
// (sympthom is error message: "error writing "stdout": bad file number").
|
|
// To prevent this, we set standard channels using duplicate of system handles.
|
|
// The effect is that Tcl channel becomes independent on C file descriptor
|
|
// and even if stdout/stderr are redirected using dup2(), Tcl keeps using
|
|
// original device.
|
|
ResetStdChannel (TCL_STDOUT);
|
|
ResetStdChannel (TCL_STDERR);
|
|
|
|
#if (TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 5))
|
|
// Plain Tcl (8.6.4+) initializes interpretor channels automatically, but
|
|
// ActiveState Tcl (at least 8.6.4) does not seem to do that, so channels
|
|
// need to be set into interpretor explicitly
|
|
{
|
|
Tcl_Channel aChannelIn = Tcl_GetStdChannel (TCL_STDIN);
|
|
Tcl_Channel aChannelOut = Tcl_GetStdChannel (TCL_STDOUT);
|
|
Tcl_Channel aChannelErr = Tcl_GetStdChannel (TCL_STDERR);
|
|
if (aChannelIn != NULL)
|
|
{
|
|
Tcl_RegisterChannel (aCommands.Interp(), aChannelIn);
|
|
}
|
|
if (aChannelOut != NULL)
|
|
{
|
|
Tcl_RegisterChannel (aCommands.Interp(), aChannelOut);
|
|
}
|
|
if (aChannelErr != NULL)
|
|
{
|
|
Tcl_RegisterChannel (aCommands.Interp(), aChannelErr);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef _TK
|
|
// initialize the Tk library if not in 'virtual windows' mode
|
|
// (virtual windows are created by OCCT with native APIs,
|
|
// thus Tk will be useless)
|
|
if (!Draw_VirtualWindows)
|
|
{
|
|
try
|
|
{
|
|
OCC_CATCH_SIGNALS
|
|
Standard_Integer res = Tk_Init (interp);
|
|
if (res != TCL_OK)
|
|
{
|
|
#if ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 5)))
|
|
std::cout << "tkLoop: error in Tk initialization. Tcl reported: " << Tcl_GetStringResult(interp) << std::endl;
|
|
#else
|
|
std::cout << "tkLoop: error in Tk initialization. Tcl reported: " << interp->result << std::endl;
|
|
#endif
|
|
}
|
|
}
|
|
catch (const Standard_Failure&)
|
|
{
|
|
std::cout << "tkLoop: exception in TK_Init\n";
|
|
}
|
|
Tcl_StaticPackage (interp, "Tk", Tk_Init, (Tcl_PackageInitProc* ) NULL);
|
|
mainWindow = Tk_MainWindow (interp);
|
|
if (mainWindow == NULL)
|
|
{
|
|
#if ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 5)))
|
|
fprintf (stderr, "%s\n", Tcl_GetStringResult(interp));
|
|
#else
|
|
fprintf (stderr, "%s\n", interp->result);
|
|
#endif
|
|
std::cout << "tkLoop: Tk_MainWindow() returned NULL. Exiting...\n";
|
|
Tcl_Exit (0);
|
|
}
|
|
Tk_Name(mainWindow) = Tk_GetUid (Tk_SetAppName (mainWindow, "Draw"));
|
|
}
|
|
#endif //#ifdef _TK
|
|
|
|
// set signal handler in the new thread
|
|
OSD::SetSignal(Standard_False);
|
|
|
|
// inform the others that we have started
|
|
isTkLoopStarted = true;
|
|
|
|
while (console_semaphore == STOP_CONSOLE)
|
|
Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT);
|
|
|
|
if (Draw_IsConsoleSubsystem && console_semaphore == WAIT_CONSOLE_COMMAND)
|
|
Prompt(interp, 0);
|
|
|
|
//process a command
|
|
Standard_Boolean toLoop = Standard_True;
|
|
while (toLoop)
|
|
{
|
|
// The natural way is first flushing events, already put into queue, and then processing custom code in-between.
|
|
// Unfortunately, Tcl has no API returning the number of queued events like XPending(), and only empty state can be checked.
|
|
// Since events can be continuously fed from parallel threads, Tcl_DoOneEvent might never return empty state at all.
|
|
const bool isTclEventQueueEmpty = Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT) == 0;
|
|
if (console_semaphore == HAS_CONSOLE_COMMAND)
|
|
{
|
|
const TCollection_AsciiString aCmdUtf8 (console_command);
|
|
const bool wasInterpreted = Draw_Interprete (aCmdUtf8.ToCString());
|
|
if (Draw_IsConsoleSubsystem)
|
|
{
|
|
Prompt (interp, wasInterpreted ? 0 : 1);
|
|
}
|
|
console_semaphore = WAIT_CONSOLE_COMMAND;
|
|
}
|
|
else if (isTclEventQueueEmpty)
|
|
{
|
|
// release CPU while polling
|
|
Sleep (1);
|
|
}
|
|
#ifdef _TK
|
|
// We should not exit until the Main Tk window is closed
|
|
toLoop = (Draw_VirtualWindows || Tk_GetNumMainWindows() > 0);
|
|
#endif
|
|
}
|
|
Tcl_Exit(0);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------*\
|
|
| Run_Appli
|
|
\*--------------------------------------------------------*/
|
|
void Run_Appli(HWND hWnd)
|
|
{
|
|
MSG msg;
|
|
HACCEL hAccel = NULL;
|
|
|
|
msg.wParam = 1;
|
|
|
|
// if (!(hAccel = LoadAccelerators (hInstance, MAKEINTRESOURCE(ACCEL_ID))))
|
|
// MessageBox(hWnd, "MDI: Load Accel failure!", "Error", MB_OK);
|
|
DWORD IDThread;
|
|
HANDLE hThread;
|
|
if (Draw_IsConsoleSubsystem) {
|
|
hThread = CreateThread (NULL, // no security attributes
|
|
0, // use default stack size
|
|
readStdinThreadFunc, // thread function
|
|
NULL, // no thread function argument
|
|
0, // use default creation flags
|
|
&IDThread); // returns thread identifier
|
|
if (!hThread) {
|
|
std::cout << "pb in creation of the thread reading stdin" << std::endl;
|
|
Draw_IsConsoleSubsystem = Standard_False;
|
|
Init_Appli (GetModuleHandleW (NULL),
|
|
GetModuleHandleW (NULL),
|
|
1, hWnd); // reinit => create MDI client wnd
|
|
}
|
|
}
|
|
|
|
//turn on the command interpretation mechanism (regardless of the mode)
|
|
if (console_semaphore == STOP_CONSOLE)
|
|
console_semaphore = WAIT_CONSOLE_COMMAND;
|
|
|
|
//simple Win32 message loop
|
|
while (GetMessageW (&msg, NULL, 0, 0) > 0)
|
|
{
|
|
if (!TranslateAcceleratorW (hWnd, hAccel, &msg))
|
|
{
|
|
TranslateMessage (&msg);
|
|
DispatchMessageW (&msg);
|
|
}
|
|
}
|
|
ExitProcess(0);
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------*\
|
|
| Destroy_Appli
|
|
\*--------------------------------------------------------*/
|
|
void Destroy_Appli(HINSTANCE hInst)
|
|
{
|
|
UnregisterAppClass(hInst);
|
|
for (int i = 0 ; i < MAXCOLOR ; i++)
|
|
DeleteObject(colorPenTab[i]);
|
|
}
|
|
|
|
/*--------------------------------------------------------*\
|
|
| SelectWait
|
|
\*--------------------------------------------------------*/
|
|
void DrawWindow::SelectWait(HANDLE& hWnd, int& x, int& y, int& button)
|
|
{
|
|
MSG msg;
|
|
|
|
msg.wParam = 1;
|
|
|
|
GetMessageW (&msg, NULL, 0, 0);
|
|
while((msg.message != WM_RBUTTONDOWN && msg.message != WM_LBUTTONDOWN) ||
|
|
! ( Draw_IsConsoleSubsystem || IsChild(DrawWindow::hWndClientMDI,msg.hwnd)) )
|
|
{
|
|
GetMessageW (&msg, NULL, 0, 0);
|
|
}
|
|
|
|
hWnd = msg.hwnd;
|
|
x = LOWORD(msg.lParam);
|
|
y = HIWORD(msg.lParam);
|
|
if (msg.message == WM_LBUTTONDOWN)
|
|
button = 1;
|
|
else
|
|
button = 3;
|
|
}
|
|
|
|
/*--------------------------------------------------------*\
|
|
| SelectNoWait
|
|
\*--------------------------------------------------------*/
|
|
void DrawWindow::SelectNoWait(HANDLE& hWnd, int& x, int& y, int& button)
|
|
{
|
|
MSG msg;
|
|
|
|
msg.wParam = 1;
|
|
|
|
GetMessageW (&msg,NULL,0,0);
|
|
while((msg.message != WM_RBUTTONDOWN && msg.message != WM_LBUTTONDOWN &&
|
|
msg.message != WM_MOUSEMOVE) ||
|
|
! ( Draw_IsConsoleSubsystem || IsChild(DrawWindow::hWndClientMDI,msg.hwnd) ) )
|
|
{
|
|
GetMessageW(&msg,NULL,0,0);
|
|
}
|
|
hWnd = msg.hwnd;
|
|
x = LOWORD(msg.lParam);
|
|
y = HIWORD(msg.lParam);
|
|
switch (msg.message)
|
|
{
|
|
case WM_LBUTTONDOWN :
|
|
button = 1;
|
|
break;
|
|
|
|
case WM_RBUTTONDOWN :
|
|
button = 3;
|
|
break;
|
|
|
|
case WM_MOUSEMOVE :
|
|
button = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
Standard_Boolean DrawWindow::DefineColor (const Standard_Integer, const char*)
|
|
{
|
|
return Standard_True;
|
|
}
|
|
|
|
#endif
|