From 56754e907dcc40f5caa9bcae242a1d0ae5eb1932 Mon Sep 17 00:00:00 2001
From: Anatoly Baksheev <no@email>
Date: Sat, 15 Feb 2014 20:08:04 +0400
Subject: [PATCH] fixed crash for windows if console widow is closed or
 CTRL_C/CTRL_BRAK keys in console are pressed.

---
 modules/viz/include/opencv2/viz/viz3d.hpp |  2 +
 modules/viz/src/precomp.hpp               | 14 +++++-
 modules/viz/src/viz3d.cpp                 |  2 +
 modules/viz/src/vizcore.cpp               | 52 +++++++++++++++++++----
 modules/viz/src/vizimpl.cpp               |  2 +
 modules/viz/src/vizimpl.hpp               |  2 +-
 6 files changed, 62 insertions(+), 12 deletions(-)

diff --git a/modules/viz/include/opencv2/viz/viz3d.hpp b/modules/viz/include/opencv2/viz/viz3d.hpp
index 1a137bcfb3..1be748c8cd 100644
--- a/modules/viz/include/opencv2/viz/viz3d.hpp
+++ b/modules/viz/include/opencv2/viz/viz3d.hpp
@@ -114,6 +114,8 @@ namespace cv
             double getRenderingProperty(const String &id, int property);
 
             void setRepresentation(int representation);
+
+            void setGlobalWarnings(bool enabled = false);
         private:
 
             struct VizImpl;
diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp
index c594962059..795ac16b07 100644
--- a/modules/viz/src/precomp.hpp
+++ b/modules/viz/src/precomp.hpp
@@ -155,7 +155,16 @@ namespace cv
     namespace viz
     {
         typedef std::map<String, vtkSmartPointer<vtkProp> > WidgetActorMap;
-        typedef std::map<String, Viz3d> VizMap;
+
+        struct VizMap
+        {
+            typedef std::map<String, Viz3d> type;
+            typedef type::iterator iterator;
+
+            type m;
+            ~VizMap();
+            void replace_clear();
+        };
 
         class VizStorage
         {
@@ -167,7 +176,6 @@ namespace cv
 
         private:
             VizStorage(); // Static
-            ~VizStorage();
 
             static void add(const Viz3d& window);
             static Viz3d& get(const String &window_name);
@@ -177,6 +185,8 @@ namespace cv
 
             static VizMap storage;
             friend class Viz3d;
+
+            static VizStorage init;
         };
 
         template<typename _Tp> inline _Tp normalized(const _Tp& v) { return v * 1/norm(v); }
diff --git a/modules/viz/src/viz3d.cpp b/modules/viz/src/viz3d.cpp
index 56f978c0ea..6e7dfcae78 100644
--- a/modules/viz/src/viz3d.cpp
+++ b/modules/viz/src/viz3d.cpp
@@ -146,3 +146,5 @@ void cv::viz::Viz3d::setRenderingProperty(const String &id, int property, double
 double cv::viz::Viz3d::getRenderingProperty(const String &id, int property) { return getWidget(id).getRenderingProperty(property); }
 
 void cv::viz::Viz3d::setRepresentation(int representation) { impl_->setRepresentation(representation); }
+
+void cv::viz::Viz3d::setGlobalWarnings(bool enabled) { vtkObject::SetGlobalWarningDisplay(enabled ? 1 : 0); }
diff --git a/modules/viz/src/vizcore.cpp b/modules/viz/src/vizcore.cpp
index b4332a860a..1166c08741 100644
--- a/modules/viz/src/vizcore.cpp
+++ b/modules/viz/src/vizcore.cpp
@@ -67,36 +67,70 @@ cv::Affine3d cv::viz::makeCameraPose(const Vec3d& position, const Vec3d& focal_p
 ///////////////////////////////////////////////////////////////////////////////////////////////
 /// VizStorage implementation
 
+#if defined(_WIN32) && !defined(__CYGWIN__)
+
+    #include <windows.h>
+
+    static BOOL WINAPI ConsoleHandlerRoutine(DWORD /*dwCtrlType*/)
+    {
+        vtkObject::GlobalWarningDisplayOff();
+        return FALSE;
+    }
+
+    static void register_console_handler()
+    {
+        HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
+        CONSOLE_SCREEN_BUFFER_INFO hOutInfo;
+        if (GetConsoleScreenBufferInfo(hOut, &hOutInfo))
+            SetConsoleCtrlHandler(ConsoleHandlerRoutine, TRUE);
+    }
+
+#else
+
+    void register_console_handler() {}
+
+#endif
+
+
+cv::viz::VizStorage cv::viz::VizStorage::init;
 cv::viz::VizMap cv::viz::VizStorage::storage;
-void cv::viz::VizStorage::unregisterAll() { storage.clear(); }
+
+void cv::viz::VizMap::replace_clear() { type().swap(m); }
+cv::viz::VizMap::~VizMap() { replace_clear(); }
+
+cv::viz::VizStorage::VizStorage()
+{
+    register_console_handler();
+}
+void cv::viz::VizStorage::unregisterAll() { storage.replace_clear(); }
 
 cv::viz::Viz3d& cv::viz::VizStorage::get(const String &window_name)
 {
     String name = generateWindowName(window_name);
-    VizMap::iterator vm_itr = storage.find(name);
-    CV_Assert(vm_itr != storage.end());
+    VizMap::iterator vm_itr = storage.m.find(name);
+    CV_Assert(vm_itr != storage.m.end());
     return vm_itr->second;
 }
 
 void cv::viz::VizStorage::add(const Viz3d& window)
 {
     String window_name = window.getWindowName();
-    VizMap::iterator vm_itr = storage.find(window_name);
-    CV_Assert(vm_itr == storage.end());
-    storage.insert(std::make_pair(window_name, window));
+    VizMap::iterator vm_itr = storage.m.find(window_name);
+    CV_Assert(vm_itr == storage.m.end());
+    storage.m.insert(std::make_pair(window_name, window));
 }
 
 bool cv::viz::VizStorage::windowExists(const String &window_name)
 {
     String name = generateWindowName(window_name);
-    return storage.find(name) != storage.end();
+    return storage.m.find(name) != storage.m.end();
 }
 
 void cv::viz::VizStorage::removeUnreferenced()
 {
-    for(VizMap::iterator pos = storage.begin(); pos != storage.end();)
+    for(VizMap::iterator pos = storage.m.begin(); pos != storage.m.end();)
         if(pos->second.impl_->ref_counter == 1)
-            storage.erase(pos++);
+            storage.m.erase(pos++);
         else
             ++pos;
 }
diff --git a/modules/viz/src/vizimpl.cpp b/modules/viz/src/vizimpl.cpp
index 3e852dd718..37d008bc82 100644
--- a/modules/viz/src/vizimpl.cpp
+++ b/modules/viz/src/vizimpl.cpp
@@ -72,6 +72,8 @@ cv::viz::Viz3d::VizImpl::VizImpl(const String &name) : spin_once_state_(false),
     setBackgroundMeshLab();
 }
 
+cv::viz::Viz3d::VizImpl::~VizImpl() { close(); }
+
 /////////////////////////////////////////////////////////////////////////////////////////////
 void cv::viz::Viz3d::VizImpl::TimerCallback::Execute(vtkObject* caller, unsigned long event_id, void* cookie)
 {
diff --git a/modules/viz/src/vizimpl.hpp b/modules/viz/src/vizimpl.hpp
index 02675e0a5c..67cab3674b 100644
--- a/modules/viz/src/vizimpl.hpp
+++ b/modules/viz/src/vizimpl.hpp
@@ -55,7 +55,7 @@ public:
     int ref_counter;
 
     VizImpl(const String &name);
-    virtual ~VizImpl() {}
+    virtual ~VizImpl();
 
     bool wasStopped() const;
     void close();